aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 15:36:37 +0100
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 15:36:37 +0100
commit2fc2991175bf77395e6b15fe6b2304d3bf72da40 (patch)
treeb0ff38c09240e7c00e1577d447ebe89143d752dc /drivers
parent[MTD] mtdchar: Return EINVAL for bad seeks instead of fixing up to valid byte (diff)
parent[PATCH] nvidiafb: Geforce 7800 series support added (diff)
downloadlinux-dev-2fc2991175bf77395e6b15fe6b2304d3bf72da40.tar.xz
linux-dev-2fc2991175bf77395e6b15fe6b2304d3bf72da40.zip
Merge branch 'master' of /home/tglx/work/mtd/git/linux-2.6.git/
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile8
-rw-r--r--drivers/acorn/block/fd1772.c15
-rw-r--r--drivers/acorn/char/pcf8583.c83
-rw-r--r--drivers/acpi/Kconfig84
-rw-r--r--drivers/acpi/Makefile14
-rw-r--r--drivers/acpi/ac.c138
-rw-r--r--drivers/acpi/acpi_memhotplug.c177
-rw-r--r--drivers/acpi/asus_acpi.c690
-rw-r--r--drivers/acpi/battery.c400
-rw-r--r--drivers/acpi/blacklist.c122
-rw-r--r--drivers/acpi/bus.c310
-rw-r--r--drivers/acpi/button.c274
-rw-r--r--drivers/acpi/container.c128
-rw-r--r--drivers/acpi/debug.c115
-rw-r--r--drivers/acpi/dispatcher/dsfield.c346
-rw-r--r--drivers/acpi/dispatcher/dsinit.c141
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c404
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c424
-rw-r--r--drivers/acpi/dispatcher/dsobject.c330
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c723
-rw-r--r--drivers/acpi/dispatcher/dsutils.c421
-rw-r--r--drivers/acpi/dispatcher/dswexec.c519
-rw-r--r--drivers/acpi/dispatcher/dswload.c524
-rw-r--r--drivers/acpi/dispatcher/dswscope.c139
-rw-r--r--drivers/acpi/dispatcher/dswstate.c668
-rw-r--r--drivers/acpi/ec.c1028
-rw-r--r--drivers/acpi/event.c83
-rw-r--r--drivers/acpi/events/evevent.c168
-rw-r--r--drivers/acpi/events/evgpe.c427
-rw-r--r--drivers/acpi/events/evgpeblk.c767
-rw-r--r--drivers/acpi/events/evmisc.c293
-rw-r--r--drivers/acpi/events/evregion.c582
-rw-r--r--drivers/acpi/events/evrgnini.c315
-rw-r--r--drivers/acpi/events/evsci.c77
-rw-r--r--drivers/acpi/events/evxface.c444
-rw-r--r--drivers/acpi/events/evxfevnt.c465
-rw-r--r--drivers/acpi/events/evxfregn.c114
-rw-r--r--drivers/acpi/executer/exconfig.c351
-rw-r--r--drivers/acpi/executer/exconvrt.c311
-rw-r--r--drivers/acpi/executer/excreate.c342
-rw-r--r--drivers/acpi/executer/exdump.c793
-rw-r--r--drivers/acpi/executer/exfield.c253
-rw-r--r--drivers/acpi/executer/exfldio.c644
-rw-r--r--drivers/acpi/executer/exmisc.c358
-rw-r--r--drivers/acpi/executer/exmutex.c160
-rw-r--r--drivers/acpi/executer/exnames.c236
-rw-r--r--drivers/acpi/executer/exoparg1.c574
-rw-r--r--drivers/acpi/executer/exoparg2.c317
-rw-r--r--drivers/acpi/executer/exoparg3.c167
-rw-r--r--drivers/acpi/executer/exoparg6.c127
-rw-r--r--drivers/acpi/executer/exprep.c381
-rw-r--r--drivers/acpi/executer/exregion.c280
-rw-r--r--drivers/acpi/executer/exresnte.c172
-rw-r--r--drivers/acpi/executer/exresolv.c284
-rw-r--r--drivers/acpi/executer/exresop.c398
-rw-r--r--drivers/acpi/executer/exstore.c417
-rw-r--r--drivers/acpi/executer/exstoren.c125
-rw-r--r--drivers/acpi/executer/exstorob.c86
-rw-r--r--drivers/acpi/executer/exsystem.c183
-rw-r--r--drivers/acpi/executer/exutils.c173
-rw-r--r--drivers/acpi/fan.c142
-rw-r--r--drivers/acpi/glue.c17
-rw-r--r--drivers/acpi/hardware/hwacpi.c116
-rw-r--r--drivers/acpi/hardware/hwgpe.c203
-rw-r--r--drivers/acpi/hardware/hwregs.c600
-rw-r--r--drivers/acpi/hardware/hwsleep.c415
-rw-r--r--drivers/acpi/hardware/hwtimer.c77
-rw-r--r--drivers/acpi/hotkey.c233
-rw-r--r--drivers/acpi/ibm_acpi.c1598
-rw-r--r--drivers/acpi/motherboard.c110
-rw-r--r--drivers/acpi/namespace/nsaccess.c355
-rw-r--r--drivers/acpi/namespace/nsalloc.c350
-rw-r--r--drivers/acpi/namespace/nsdump.c461
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c74
-rw-r--r--drivers/acpi/namespace/nseval.c274
-rw-r--r--drivers/acpi/namespace/nsinit.c257
-rw-r--r--drivers/acpi/namespace/nsload.c264
-rw-r--r--drivers/acpi/namespace/nsnames.c118
-rw-r--r--drivers/acpi/namespace/nsobject.c209
-rw-r--r--drivers/acpi/namespace/nsparse.c84
-rw-r--r--drivers/acpi/namespace/nssearch.c205
-rw-r--r--drivers/acpi/namespace/nsutils.c502
-rw-r--r--drivers/acpi/namespace/nswalk.c105
-rw-r--r--drivers/acpi/namespace/nsxfeval.c430
-rw-r--r--drivers/acpi/namespace/nsxfname.c173
-rw-r--r--drivers/acpi/namespace/nsxfobj.c91
-rw-r--r--drivers/acpi/numa.c125
-rw-r--r--drivers/acpi/osl.c707
-rw-r--r--drivers/acpi/parser/Makefile2
-rw-r--r--drivers/acpi/parser/psargs.c376
-rw-r--r--drivers/acpi/parser/psloop.c874
-rw-r--r--drivers/acpi/parser/psopcode.c739
-rw-r--r--drivers/acpi/parser/psparse.c1080
-rw-r--r--drivers/acpi/parser/psscope.c130
-rw-r--r--drivers/acpi/parser/pstree.c92
-rw-r--r--drivers/acpi/parser/psutils.c134
-rw-r--r--drivers/acpi/parser/pswalk.c26
-rw-r--r--drivers/acpi/parser/psxface.c251
-rw-r--r--drivers/acpi/pci_bind.c220
-rw-r--r--drivers/acpi/pci_irq.c275
-rw-r--r--drivers/acpi/pci_link.c489
-rw-r--r--drivers/acpi/pci_root.c130
-rw-r--r--drivers/acpi/power.c271
-rw-r--r--drivers/acpi/processor_core.c437
-rw-r--r--drivers/acpi/processor_idle.c316
-rw-r--r--drivers/acpi/processor_perflib.c297
-rw-r--r--drivers/acpi/processor_thermal.c153
-rw-r--r--drivers/acpi/processor_throttling.c133
-rw-r--r--drivers/acpi/resources/rsaddr.c873
-rw-r--r--drivers/acpi/resources/rscalc.c314
-rw-r--r--drivers/acpi/resources/rscreate.c297
-rw-r--r--drivers/acpi/resources/rsdump.c847
-rw-r--r--drivers/acpi/resources/rsio.c172
-rw-r--r--drivers/acpi/resources/rsirq.c251
-rw-r--r--drivers/acpi/resources/rslist.c279
-rw-r--r--drivers/acpi/resources/rsmemory.c218
-rw-r--r--drivers/acpi/resources/rsmisc.c230
-rw-r--r--drivers/acpi/resources/rsutils.c159
-rw-r--r--drivers/acpi/resources/rsxface.c182
-rw-r--r--drivers/acpi/scan.c437
-rw-r--r--drivers/acpi/sleep/main.c16
-rw-r--r--drivers/acpi/sleep/poweroff.c12
-rw-r--r--drivers/acpi/sleep/proc.c271
-rw-r--r--drivers/acpi/sleep/wakeup.c115
-rw-r--r--drivers/acpi/system.c76
-rw-r--r--drivers/acpi/tables.c434
-rw-r--r--drivers/acpi/tables/tbconvrt.c408
-rw-r--r--drivers/acpi/tables/tbget.c275
-rw-r--r--drivers/acpi/tables/tbgetall.c189
-rw-r--r--drivers/acpi/tables/tbinstal.c264
-rw-r--r--drivers/acpi/tables/tbrsdt.c231
-rw-r--r--drivers/acpi/tables/tbutils.c178
-rw-r--r--drivers/acpi/tables/tbxface.c253
-rw-r--r--drivers/acpi/tables/tbxfroot.c513
-rw-r--r--drivers/acpi/thermal.c801
-rw-r--r--drivers/acpi/toshiba_acpi.c174
-rw-r--r--drivers/acpi/utilities/Makefile2
-rw-r--r--drivers/acpi/utilities/utalloc.c713
-rw-r--r--drivers/acpi/utilities/utcache.c305
-rw-r--r--drivers/acpi/utilities/utcopy.c592
-rw-r--r--drivers/acpi/utilities/utdebug.c400
-rw-r--r--drivers/acpi/utilities/utdelete.c431
-rw-r--r--drivers/acpi/utilities/uteval.c396
-rw-r--r--drivers/acpi/utilities/utglobal.c653
-rw-r--r--drivers/acpi/utilities/utinit.c135
-rw-r--r--drivers/acpi/utilities/utmath.c144
-rw-r--r--drivers/acpi/utilities/utmisc.c1175
-rw-r--r--drivers/acpi/utilities/utmutex.c354
-rw-r--r--drivers/acpi/utilities/utobject.c354
-rw-r--r--drivers/acpi/utilities/utstate.c333
-rw-r--r--drivers/acpi/utilities/utxface.c278
-rw-r--r--drivers/acpi/utils.c195
-rw-r--r--drivers/acpi/video.c1076
-rw-r--r--drivers/atm/ambassador.c4
-rw-r--r--drivers/atm/atmtcp.c2
-rw-r--r--drivers/atm/eni.c2
-rw-r--r--drivers/atm/firestream.c7
-rw-r--r--drivers/atm/fore200e.c12
-rw-r--r--drivers/atm/he.c2
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/atm/idt77105.c6
-rw-r--r--drivers/atm/idt77252.c8
-rw-r--r--drivers/atm/iphase.c2
-rw-r--r--drivers/atm/lanai.c2
-rw-r--r--drivers/atm/nicstar.c167
-rw-r--r--drivers/atm/nicstar.h16
-rw-r--r--drivers/atm/zatm.c10
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/attribute_container.c93
-rw-r--r--drivers/base/base.h12
-rw-r--r--drivers/base/bus.c46
-rw-r--r--drivers/base/class.c213
-rw-r--r--drivers/base/core.c40
-rw-r--r--drivers/base/cpu.c17
-rw-r--r--drivers/base/dd.c5
-rw-r--r--drivers/base/dmapool.c4
-rw-r--r--drivers/base/driver.c18
-rw-r--r--drivers/base/firmware.c3
-rw-r--r--drivers/base/firmware_class.c145
-rw-r--r--drivers/base/init.c12
-rw-r--r--drivers/base/map.c3
-rw-r--r--drivers/base/memory.c452
-rw-r--r--drivers/base/node.c24
-rw-r--r--drivers/base/platform.c28
-rw-r--r--drivers/base/power/main.c26
-rw-r--r--drivers/base/power/power.h13
-rw-r--r--drivers/base/power/resume.c8
-rw-r--r--drivers/base/power/runtime.c9
-rw-r--r--drivers/base/power/suspend.c12
-rw-r--r--drivers/base/power/sysfs.c81
-rw-r--r--drivers/base/sys.c111
-rw-r--r--drivers/base/transport_class.c19
-rw-r--r--drivers/block/Kconfig46
-rw-r--r--drivers/block/Kconfig.iosched28
-rw-r--r--drivers/block/acsi.c2
-rw-r--r--drivers/block/acsi_slm.c2
-rw-r--r--drivers/block/aoe/aoe.h12
-rw-r--r--drivers/block/aoe/aoechr.c2
-rw-r--r--drivers/block/aoe/aoecmd.c28
-rw-r--r--drivers/block/aoe/aoedev.c2
-rw-r--r--drivers/block/aoe/aoenet.c2
-rw-r--r--drivers/block/as-iosched.c330
-rw-r--r--drivers/block/ataflop.c14
-rw-r--r--drivers/block/cciss.c643
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c79
-rw-r--r--drivers/block/cfq-iosched.c419
-rw-r--r--drivers/block/cryptoloop.c6
-rw-r--r--drivers/block/deadline-iosched.c136
-rw-r--r--drivers/block/elevator.c396
-rw-r--r--drivers/block/floppy.c47
-rw-r--r--drivers/block/genhd.c56
-rw-r--r--drivers/block/ll_rw_blk.c414
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/noop-iosched.c49
-rw-r--r--drivers/block/paride/paride.c1
-rw-r--r--drivers/block/paride/pcd.c3
-rw-r--r--drivers/block/paride/pf.c21
-rw-r--r--drivers/block/paride/pg.c7
-rw-r--r--drivers/block/paride/pt.c8
-rw-r--r--drivers/block/pktcdvd.c89
-rw-r--r--drivers/block/ps2esdi.c3
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/scsi_ioctl.c70
-rw-r--r--drivers/block/swim3.c9
-rw-r--r--drivers/block/swim_iop.c3
-rw-r--r--drivers/block/sx8.c51
-rw-r--r--drivers/block/ub.c306
-rw-r--r--drivers/block/umem.c11
-rw-r--r--drivers/block/viodasd.c19
-rw-r--r--drivers/block/xd.c21
-rw-r--r--drivers/block/z2ram.c2
-rw-r--r--drivers/bluetooth/Kconfig8
-rw-r--r--drivers/bluetooth/bfusb.c16
-rw-r--r--drivers/bluetooth/bluecard_cs.c24
-rw-r--r--drivers/bluetooth/bpa10x.c27
-rw-r--r--drivers/bluetooth/bt3c_cs.c12
-rw-r--r--drivers/bluetooth/btuart_cs.c10
-rw-r--r--drivers/bluetooth/dtl1_cs.c10
-rw-r--r--drivers/bluetooth/hci_bcsp.c180
-rw-r--r--drivers/bluetooth/hci_bcsp.h70
-rw-r--r--drivers/bluetooth/hci_h4.c110
-rw-r--r--drivers/bluetooth/hci_h4.h44
-rw-r--r--drivers/bluetooth/hci_ldisc.c140
-rw-r--r--drivers/bluetooth/hci_uart.h84
-rw-r--r--drivers/bluetooth/hci_usb.c53
-rw-r--r--drivers/bluetooth/hci_usb.h5
-rw-r--r--drivers/bluetooth/hci_vhci.c386
-rw-r--r--drivers/bluetooth/hci_vhci.h50
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/cdrom/cdrom.c15
-rw-r--r--drivers/cdrom/gscd.c2
-rw-r--r--drivers/cdrom/optcd.c2
-rw-r--r--drivers/cdrom/sbpcd.c18
-rw-r--r--drivers/cdrom/sjcd.c2
-rw-r--r--drivers/cdrom/sonycd535.c3
-rw-r--r--drivers/cdrom/viocd.c17
-rw-r--r--drivers/char/.gitignore3
-rw-r--r--drivers/char/Kconfig23
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/Kconfig16
-rw-r--r--drivers/char/agp/ali-agp.c1
-rw-r--r--drivers/char/agp/amd64-agp.c3
-rw-r--r--drivers/char/agp/ati-agp.c2
-rw-r--r--drivers/char/agp/backend.c7
-rw-r--r--drivers/char/agp/generic.c33
-rw-r--r--drivers/char/agp/hp-agp.c2
-rw-r--r--drivers/char/agp/i460-agp.c2
-rw-r--r--drivers/char/agp/isoch.c1
-rw-r--r--drivers/char/agp/sgi-agp.c1
-rw-r--r--drivers/char/agp/sworks-agp.c2
-rw-r--r--drivers/char/amiserial.c4
-rw-r--r--drivers/char/applicom.c24
-rw-r--r--drivers/char/cyclades.c4
-rw-r--r--drivers/char/digi1.h38
-rw-r--r--drivers/char/digiFep1.h154
-rw-r--r--drivers/char/drm/Kconfig16
-rw-r--r--drivers/char/drm/Makefile7
-rw-r--r--drivers/char/drm/ati_pcigart.c152
-rw-r--r--drivers/char/drm/drm.h295
-rw-r--r--drivers/char/drm/drmP.h971
-rw-r--r--drivers/char/drm/drm_agpsupport.c257
-rw-r--r--drivers/char/drm/drm_auth.c68
-rw-r--r--drivers/char/drm/drm_bufs.c1450
-rw-r--r--drivers/char/drm/drm_context.c311
-rw-r--r--drivers/char/drm/drm_dma.c87
-rw-r--r--drivers/char/drm/drm_drawable.c8
-rw-r--r--drivers/char/drm/drm_drv.c428
-rw-r--r--drivers/char/drm/drm_fops.c302
-rw-r--r--drivers/char/drm/drm_init.c7
-rw-r--r--drivers/char/drm/drm_ioc32.c225
-rw-r--r--drivers/char/drm/drm_ioctl.c168
-rw-r--r--drivers/char/drm/drm_irq.c169
-rw-r--r--drivers/char/drm/drm_lock.c177
-rw-r--r--drivers/char/drm/drm_memory.c60
-rw-r--r--drivers/char/drm/drm_memory.h73
-rw-r--r--drivers/char/drm/drm_memory_debug.h224
-rw-r--r--drivers/char/drm/drm_os_linux.h17
-rw-r--r--drivers/char/drm/drm_pci.c57
-rw-r--r--drivers/char/drm/drm_pciids.h80
-rw-r--r--drivers/char/drm/drm_proc.c281
-rw-r--r--drivers/char/drm/drm_sarea.h30
-rw-r--r--drivers/char/drm/drm_scatter.c190
-rw-r--r--drivers/char/drm/drm_stub.c122
-rw-r--r--drivers/char/drm/drm_sysfs.c3
-rw-r--r--drivers/char/drm/drm_vm.c456
-rw-r--r--drivers/char/drm/ffb_context.c230
-rw-r--r--drivers/char/drm/ffb_drv.c144
-rw-r--r--drivers/char/drm/ffb_drv.h433
-rw-r--r--drivers/char/drm/gamma_context.h492
-rw-r--r--drivers/char/drm/gamma_dma.c946
-rw-r--r--drivers/char/drm/gamma_drm.h90
-rw-r--r--drivers/char/drm/gamma_drv.c59
-rw-r--r--drivers/char/drm/gamma_drv.h147
-rw-r--r--drivers/char/drm/gamma_lists.h215
-rw-r--r--drivers/char/drm/gamma_lock.h140
-rw-r--r--drivers/char/drm/gamma_old_dma.h313
-rw-r--r--drivers/char/drm/i810_dma.c1109
-rw-r--r--drivers/char/drm/i810_drm.h75
-rw-r--r--drivers/char/drm/i810_drv.c64
-rw-r--r--drivers/char/drm/i810_drv.h42
-rw-r--r--drivers/char/drm/i830_dma.c1337
-rw-r--r--drivers/char/drm/i830_drm.h90
-rw-r--r--drivers/char/drm/i830_drv.c63
-rw-r--r--drivers/char/drm/i830_drv.h86
-rw-r--r--drivers/char/drm/i830_irq.c137
-rw-r--r--drivers/char/drm/i915_dma.c63
-rw-r--r--drivers/char/drm/i915_drv.c65
-rw-r--r--drivers/char/drm/i915_drv.h18
-rw-r--r--drivers/char/drm/i915_ioc32.c64
-rw-r--r--drivers/char/drm/i915_mem.c8
-rw-r--r--drivers/char/drm/mga_dma.c985
-rw-r--r--drivers/char/drm/mga_drm.h206
-rw-r--r--drivers/char/drm/mga_drv.c107
-rw-r--r--drivers/char/drm/mga_drv.h125
-rw-r--r--drivers/char/drm/mga_ioc32.c117
-rw-r--r--drivers/char/drm/mga_irq.c102
-rw-r--r--drivers/char/drm/mga_state.c996
-rw-r--r--drivers/char/drm/mga_ucode.h16070
-rw-r--r--drivers/char/drm/mga_warp.c209
-rw-r--r--drivers/char/drm/r128_cce.c598
-rw-r--r--drivers/char/drm/r128_drm.h34
-rw-r--r--drivers/char/drm/r128_drv.c63
-rw-r--r--drivers/char/drm/r128_drv.h73
-rw-r--r--drivers/char/drm/r128_ioc32.c35
-rw-r--r--drivers/char/drm/r128_irq.c53
-rw-r--r--drivers/char/drm/r128_state.c1386
-rw-r--r--drivers/char/drm/r300_cmdbuf.c823
-rw-r--r--drivers/char/drm/r300_reg.h1406
-rw-r--r--drivers/char/drm/radeon_cp.c2529
-rw-r--r--drivers/char/drm/radeon_drm.h320
-rw-r--r--drivers/char/drm/radeon_drv.c70
-rw-r--r--drivers/char/drm/radeon_drv.h218
-rw-r--r--drivers/char/drm/radeon_ioc32.c51
-rw-r--r--drivers/char/drm/radeon_irq.c127
-rw-r--r--drivers/char/drm/radeon_mem.c148
-rw-r--r--drivers/char/drm/radeon_state.c2536
-rw-r--r--drivers/char/drm/savage_bci.c1099
-rw-r--r--drivers/char/drm/savage_drm.h210
-rw-r--r--drivers/char/drm/savage_drv.c107
-rw-r--r--drivers/char/drm/savage_drv.h582
-rw-r--r--drivers/char/drm/savage_state.c1161
-rw-r--r--drivers/char/drm/sis_drm.h2
-rw-r--r--drivers/char/drm/sis_drv.c61
-rw-r--r--drivers/char/drm/sis_drv.h13
-rw-r--r--drivers/char/drm/sis_ds.c82
-rw-r--r--drivers/char/drm/sis_ds.h40
-rw-r--r--drivers/char/drm/sis_mm.c127
-rw-r--r--drivers/char/drm/tdfx_drv.c52
-rw-r--r--drivers/char/drm/via_3d_reg.h1
-rw-r--r--drivers/char/drm/via_dma.c259
-rw-r--r--drivers/char/drm/via_drm.h4
-rw-r--r--drivers/char/drm/via_drv.c22
-rw-r--r--drivers/char/drm/via_drv.h22
-rw-r--r--drivers/char/drm/via_irq.c106
-rw-r--r--drivers/char/drm/via_map.c4
-rw-r--r--drivers/char/drm/via_mm.c17
-rw-r--r--drivers/char/drm/via_verifier.c483
-rw-r--r--drivers/char/drm/via_verifier.h22
-rw-r--r--drivers/char/drm/via_video.c30
-rw-r--r--drivers/char/dsp56k.c2
-rw-r--r--drivers/char/epca.c1635
-rw-r--r--drivers/char/epca.h108
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c6
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c12
-rw-r--r--drivers/char/hangcheck-timer.c5
-rw-r--r--drivers/char/hpet.c185
-rw-r--r--drivers/char/hvc_console.c6
-rw-r--r--drivers/char/hvc_vio.c4
-rw-r--r--drivers/char/hvcs.c7
-rw-r--r--drivers/char/hw_random.c5
-rw-r--r--drivers/char/ip2/i2lib.c6
-rw-r--r--drivers/char/ip2main.c13
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c69
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c108
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c3
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c342
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c168
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c418
-rw-r--r--drivers/char/ipmi/ipmi_smic_sm.c3
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c52
-rw-r--r--drivers/char/istallion.c5
-rw-r--r--drivers/char/keyboard.c114
-rw-r--r--drivers/char/lcd.c11
-rw-r--r--drivers/char/lcd.h2
-rw-r--r--drivers/char/lp.c5
-rw-r--r--drivers/char/mbcs.c5
-rw-r--r--drivers/char/mem.c23
-rw-r--r--drivers/char/misc.c11
-rw-r--r--drivers/char/mmtimer.c4
-rw-r--r--drivers/char/moxa.c2
-rw-r--r--drivers/char/mwave/3780i.c2
-rw-r--r--drivers/char/mwave/mwavedd.c21
-rw-r--r--drivers/char/mxser.c13
-rw-r--r--drivers/char/n_r3964.c92
-rw-r--r--drivers/char/n_tty.c2
-rw-r--r--drivers/char/pcmcia/synclink_cs.c16
-rw-r--r--drivers/char/ppdev.c2
-rw-r--r--drivers/char/pty.c5
-rw-r--r--drivers/char/qtronix.c5
-rw-r--r--drivers/char/random.c34
-rw-r--r--drivers/char/raw.c4
-rw-r--r--drivers/char/rocket.c10
-rw-r--r--drivers/char/rtc.c12
-rw-r--r--drivers/char/s3c2410-rtc.c23
-rw-r--r--drivers/char/ser_a2232.c2
-rw-r--r--drivers/char/snsc.c6
-rw-r--r--drivers/char/snsc_event.c11
-rw-r--r--drivers/char/sonypi.c225
-rw-r--r--drivers/char/specialix.c342
-rw-r--r--drivers/char/stallion.c4
-rw-r--r--drivers/char/synclink.c30
-rw-r--r--drivers/char/synclinkmp.c42
-rw-r--r--drivers/char/tb0219.c2
-rw-r--r--drivers/char/tipar.c2
-rw-r--r--drivers/char/tlclk.c897
-rw-r--r--drivers/char/tpm/Kconfig11
-rw-r--r--drivers/char/tpm/tpm.c104
-rw-r--r--drivers/char/tpm/tpm.h12
-rw-r--r--drivers/char/tpm/tpm_atmel.c144
-rw-r--r--drivers/char/tpm/tpm_infineon.c237
-rw-r--r--drivers/char/tpm/tpm_nsc.c165
-rw-r--r--drivers/char/tty_io.c105
-rw-r--r--drivers/char/vc_screen.c10
-rw-r--r--drivers/char/viocons.c10
-rw-r--r--drivers/char/viotape.c25
-rw-r--r--drivers/char/vr41xx_giu.c2
-rw-r--r--drivers/char/vr41xx_rtc.c2
-rw-r--r--drivers/char/vt.c61
-rw-r--r--drivers/char/vt_ioctl.c3
-rw-r--r--drivers/char/watchdog/Kconfig109
-rw-r--r--drivers/char/watchdog/Makefile78
-rw-r--r--drivers/char/watchdog/booke_wdt.c192
-rw-r--r--drivers/char/watchdog/cpu5wdt.c1
-rw-r--r--drivers/char/watchdog/i6300esb.c527
-rw-r--r--drivers/char/watchdog/i8xx_tco.c41
-rw-r--r--drivers/char/watchdog/ibmasr.c405
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c2
-rw-r--r--drivers/char/watchdog/mixcomwd.c4
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c437
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c255
-rw-r--r--drivers/char/watchdog/pcwd.c2
-rw-r--r--drivers/char/watchdog/pcwd_pci.c288
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c86
-rw-r--r--drivers/char/watchdog/sbc8360.c414
-rw-r--r--drivers/char/watchdog/sc520_wdt.c1
-rw-r--r--drivers/char/watchdog/scx200_wdt.c2
-rw-r--r--drivers/char/watchdog/softdog.c15
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c8
-rw-r--r--drivers/char/watchdog/w83977f_wdt.c543
-rw-r--r--drivers/char/watchdog/wdt_pci.c1
-rw-r--r--drivers/connector/Kconfig13
-rw-r--r--drivers/connector/Makefile3
-rw-r--r--drivers/connector/cn_queue.c179
-rw-r--r--drivers/connector/connector.c488
-rw-r--r--drivers/cpufreq/cpufreq.c91
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c6
-rw-r--r--drivers/cpufreq/cpufreq_stats.c42
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/eisa/virtual_root.c2
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/firmware/Kconfig26
-rw-r--r--drivers/firmware/Makefile2
-rw-r--r--drivers/firmware/dcdbas.c596
-rw-r--r--drivers/firmware/dcdbas.h107
-rw-r--r--drivers/firmware/dell_rbu.c695
-rw-r--r--drivers/hwmon/Kconfig88
-rw-r--r--drivers/hwmon/Makefile5
-rw-r--r--drivers/hwmon/adm1021.c40
-rw-r--r--drivers/hwmon/adm1025.c34
-rw-r--r--drivers/hwmon/adm1026.c49
-rw-r--r--drivers/hwmon/adm1031.c29
-rw-r--r--drivers/hwmon/adm9240.c464
-rw-r--r--drivers/hwmon/asb100.c67
-rw-r--r--drivers/hwmon/atxp1.c31
-rw-r--r--drivers/hwmon/ds1621.c38
-rw-r--r--drivers/hwmon/fscher.c30
-rw-r--r--drivers/hwmon/fscpos.c34
-rw-r--r--drivers/hwmon/gl518sm.c31
-rw-r--r--drivers/hwmon/gl520sm.c34
-rw-r--r--drivers/hwmon/hdaps.c614
-rw-r--r--drivers/hwmon/hwmon-vid.c189
-rw-r--r--drivers/hwmon/hwmon.c98
-rw-r--r--drivers/hwmon/it87.c112
-rw-r--r--drivers/hwmon/lm63.c30
-rw-r--r--drivers/hwmon/lm75.c44
-rw-r--r--drivers/hwmon/lm75.h2
-rw-r--r--drivers/hwmon/lm77.c27
-rw-r--r--drivers/hwmon/lm78.c90
-rw-r--r--drivers/hwmon/lm80.c32
-rw-r--r--drivers/hwmon/lm83.c30
-rw-r--r--drivers/hwmon/lm85.c54
-rw-r--r--drivers/hwmon/lm87.c34
-rw-r--r--drivers/hwmon/lm90.c208
-rw-r--r--drivers/hwmon/lm92.c31
-rw-r--r--drivers/hwmon/max1619.c31
-rw-r--r--drivers/hwmon/pc87360.c855
-rw-r--r--drivers/hwmon/sis5595.c76
-rw-r--r--drivers/hwmon/smsc47b397.c86
-rw-r--r--drivers/hwmon/smsc47m1.c84
-rw-r--r--drivers/hwmon/via686a.c107
-rw-r--r--drivers/hwmon/w83627ehf.c78
-rw-r--r--drivers/hwmon/w83627hf.c124
-rw-r--r--drivers/hwmon/w83781d.c101
-rw-r--r--drivers/hwmon/w83792d.c1646
-rw-r--r--drivers/hwmon/w83l785ts.c69
-rw-r--r--drivers/i2c/Makefile4
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c18
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-sgi.c5
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c6
-rw-r--r--drivers/i2c/busses/Kconfig39
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c9
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c9
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c12
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c10
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c18
-rw-r--r--drivers/i2c/busses/i2c-au1550.c2
-rw-r--r--drivers/i2c/busses/i2c-elektor.c138
-rw-r--r--drivers/i2c/busses/i2c-hydra.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c63
-rw-r--r--drivers/i2c/busses/i2c-i810.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c7
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c22
-rw-r--r--drivers/i2c/busses/i2c-isa.c163
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c10
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c10
-rw-r--r--drivers/i2c/busses/i2c-keywest.c21
-rw-r--r--drivers/i2c/busses/i2c-mpc.c10
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c20
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c54
-rw-r--r--drivers/i2c/busses/i2c-parport.c11
-rw-r--r--drivers/i2c/busses/i2c-piix4.c15
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c315
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c10
-rw-r--r--drivers/i2c/busses/i2c-pxa.c1027
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c20
-rw-r--r--drivers/i2c/busses/i2c-savage4.c1
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c4
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c12
-rw-r--r--drivers/i2c/busses/i2c-sis630.c11
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c10
-rw-r--r--drivers/i2c/busses/i2c-stub.c2
-rw-r--r--drivers/i2c/busses/i2c-via.c7
-rw-r--r--drivers/i2c/busses/i2c-viapro.c273
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/i2c/busses/scx200_acb.c7
-rw-r--r--drivers/i2c/chips/Kconfig19
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/ds1337.c14
-rw-r--r--drivers/i2c/chips/ds1374.c10
-rw-r--r--drivers/i2c/chips/eeprom.c26
-rw-r--r--drivers/i2c/chips/isp1301_omap.c5
-rw-r--r--drivers/i2c/chips/m41t00.c7
-rw-r--r--drivers/i2c/chips/max6875.c460
-rw-r--r--drivers/i2c/chips/pca9539.c15
-rw-r--r--drivers/i2c/chips/pcf8574.c18
-rw-r--r--drivers/i2c/chips/pcf8591.c18
-rw-r--r--drivers/i2c/chips/rtc8564.c6
-rw-r--r--drivers/i2c/chips/tps65010.c3
-rw-r--r--drivers/i2c/chips/x1205.c698
-rw-r--r--drivers/i2c/i2c-core.c453
-rw-r--r--drivers/i2c/i2c-dev.c23
-rw-r--r--drivers/i2c/i2c-sensor-detect.c145
-rw-r--r--drivers/i2c/i2c-sensor-vid.c98
-rw-r--r--drivers/ide/Kconfig32
-rw-r--r--drivers/ide/ide-cd.c56
-rw-r--r--drivers/ide/ide-disk.c4
-rw-r--r--drivers/ide/ide-floppy.c2
-rw-r--r--drivers/ide/ide-io.c16
-rw-r--r--drivers/ide/ide-iops.c41
-rw-r--r--drivers/ide/ide-probe.c7
-rw-r--r--drivers/ide/ide-proc.c1
-rw-r--r--drivers/ide/ide-tape.c41
-rw-r--r--drivers/ide/ide-taskfile.c1
-rw-r--r--drivers/ide/ide-timing.h25
-rw-r--r--drivers/ide/ide.c4
-rw-r--r--drivers/ide/legacy/ide-cs.c12
-rw-r--r--drivers/ide/mips/au1xxx-ide.c1250
-rw-r--r--drivers/ide/pci/cmd64x.c2
-rw-r--r--drivers/ide/pci/generic.c7
-rw-r--r--drivers/ide/pci/hpt34x.c2
-rw-r--r--drivers/ide/pci/hpt366.c8
-rw-r--r--drivers/ide/pci/sc1200.c12
-rw-r--r--drivers/ide/pci/serverworks.c23
-rw-r--r--drivers/ide/ppc/pmac.c98
-rw-r--r--drivers/ide/setup-pci.c1
-rw-r--r--drivers/ieee1394/amdtp.c1
-rw-r--r--drivers/ieee1394/csr1212.h1
-rw-r--r--drivers/ieee1394/dv1394.c3
-rw-r--r--drivers/ieee1394/eth1394.c14
-rw-r--r--drivers/ieee1394/eth1394.h6
-rw-r--r--drivers/ieee1394/hosts.c3
-rw-r--r--drivers/ieee1394/hosts.h8
-rw-r--r--drivers/ieee1394/ieee1394_core.c36
-rw-r--r--drivers/ieee1394/nodemgr.c35
-rw-r--r--drivers/ieee1394/ohci1394.c18
-rw-r--r--drivers/ieee1394/pcilynx.c20
-rw-r--r--drivers/ieee1394/raw1394.c105
-rw-r--r--drivers/ieee1394/sbp2.c115
-rw-r--r--drivers/ieee1394/video1394.c5
-rw-r--r--drivers/infiniband/Kconfig28
-rw-r--r--drivers/infiniband/Makefile1
-rw-r--r--drivers/infiniband/core/Makefile7
-rw-r--r--drivers/infiniband/core/agent.c307
-rw-r--r--drivers/infiniband/core/agent.h14
-rw-r--r--drivers/infiniband/core/agent_priv.h62
-rw-r--r--drivers/infiniband/core/cache.c7
-rw-r--r--drivers/infiniband/core/cm.c351
-rw-r--r--drivers/infiniband/core/cm_msgs.h195
-rw-r--r--drivers/infiniband/core/core_priv.h2
-rw-r--r--drivers/infiniband/core/device.c23
-rw-r--r--drivers/infiniband/core/fmr_pool.c8
-rw-r--r--drivers/infiniband/core/mad.c377
-rw-r--r--drivers/infiniband/core/mad_priv.h16
-rw-r--r--drivers/infiniband/core/mad_rmpp.c354
-rw-r--r--drivers/infiniband/core/mad_rmpp.h2
-rw-r--r--drivers/infiniband/core/packer.c3
-rw-r--r--drivers/infiniband/core/sa_query.c313
-rw-r--r--drivers/infiniband/core/smi.c13
-rw-r--r--drivers/infiniband/core/smi.h2
-rw-r--r--drivers/infiniband/core/sysfs.c64
-rw-r--r--drivers/infiniband/core/ucm.c901
-rw-r--r--drivers/infiniband/core/ucm.h89
-rw-r--r--drivers/infiniband/core/ud_header.c11
-rw-r--r--drivers/infiniband/core/user_mad.c490
-rw-r--r--drivers/infiniband/core/uverbs.h101
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c1148
-rw-r--r--drivers/infiniband/core/uverbs_main.c580
-rw-r--r--drivers/infiniband/core/uverbs_mem.c1
-rw-r--r--drivers/infiniband/core/verbs.c83
-rw-r--r--drivers/infiniband/hw/mthca/Makefile5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c116
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c30
-rw-r--r--drivers/infiniband/hw/mthca/mthca_catas.c153
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c123
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h22
-rw-r--r--drivers/infiniband/hw/mthca/mthca_config_reg.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c287
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h78
-rw-r--r--drivers/infiniband/hw/mthca/mthca_doorbell.h13
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c127
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c85
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c217
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c49
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c34
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h8
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c39
-rw-r--r--drivers/infiniband/hw/mthca/mthca_pd.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.c8
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c166
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h54
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c481
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c9
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c628
-rw-r--r--drivers/infiniband/hw/mthca/mthca_uar.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_user.h17
-rw-r--r--drivers/infiniband/hw/mthca/mthca_wqe.h114
-rw-r--r--drivers/infiniband/include/ib_cache.h103
-rw-r--r--drivers/infiniband/include/ib_cm.h568
-rw-r--r--drivers/infiniband/include/ib_fmr_pool.h93
-rw-r--r--drivers/infiniband/include/ib_mad.h577
-rw-r--r--drivers/infiniband/include/ib_pack.h245
-rw-r--r--drivers/infiniband/include/ib_sa.h373
-rw-r--r--drivers/infiniband/include/ib_smi.h96
-rw-r--r--drivers/infiniband/include/ib_user_cm.h328
-rw-r--r--drivers/infiniband/include/ib_user_mad.h139
-rw-r--r--drivers/infiniband/include/ib_user_verbs.h389
-rw-r--r--drivers/infiniband/include/ib_verbs.h1365
-rw-r--r--drivers/infiniband/ulp/ipoib/Makefile2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h40
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c142
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c77
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c29
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c16
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c1
-rw-r--r--drivers/infiniband/ulp/srp/Kbuild1
-rw-r--r--drivers/infiniband/ulp/srp/Kconfig11
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c1700
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h150
-rw-r--r--drivers/input/evdev.c34
-rw-r--r--drivers/input/gameport/emu10k1-gp.c2
-rw-r--r--drivers/input/gameport/fm801-gp.c2
-rw-r--r--drivers/input/gameport/gameport.c1
-rw-r--r--drivers/input/gameport/ns558.c8
-rw-r--r--drivers/input/input.c453
-rw-r--r--drivers/input/joydev.c16
-rw-r--r--drivers/input/joystick/a3d.c3
-rw-r--r--drivers/input/joystick/adi.c94
-rw-r--r--drivers/input/joystick/amijoy.c85
-rw-r--r--drivers/input/joystick/analog.c99
-rw-r--r--drivers/input/joystick/cobra.c67
-rw-r--r--drivers/input/joystick/db9.c292
-rw-r--r--drivers/input/joystick/gamecon.c396
-rw-r--r--drivers/input/joystick/gf2k.c70
-rw-r--r--drivers/input/joystick/grip.c80
-rw-r--r--drivers/input/joystick/grip_mp.c152
-rw-r--r--drivers/input/joystick/guillemot.c52
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c106
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c37
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c10
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c23
-rw-r--r--drivers/input/joystick/iforce/iforce.h2
-rw-r--r--drivers/input/joystick/interact.c54
-rw-r--r--drivers/input/joystick/joydump.c1
-rw-r--r--drivers/input/joystick/magellan.c71
-rw-r--r--drivers/input/joystick/sidewinder.c73
-rw-r--r--drivers/input/joystick/spaceball.c82
-rw-r--r--drivers/input/joystick/spaceorb.c78
-rw-r--r--drivers/input/joystick/stinger.c75
-rw-r--r--drivers/input/joystick/tmdc.c327
-rw-r--r--drivers/input/joystick/turbografx.c215
-rw-r--r--drivers/input/joystick/twidjoy.c120
-rw-r--r--drivers/input/joystick/warrior.c83
-rw-r--r--drivers/input/keyboard/Kconfig17
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/amikbd.c59
-rw-r--r--drivers/input/keyboard/atkbd.c198
-rw-r--r--drivers/input/keyboard/corgikbd.c162
-rw-r--r--drivers/input/keyboard/hil_kbd.c28
-rw-r--r--drivers/input/keyboard/hilkbd.c8
-rw-r--r--drivers/input/keyboard/lkkbd.c126
-rw-r--r--drivers/input/keyboard/maple_keyb.c72
-rw-r--r--drivers/input/keyboard/newtonkbd.c83
-rw-r--r--drivers/input/keyboard/spitzkbd.c487
-rw-r--r--drivers/input/keyboard/sunkbd.c119
-rw-r--r--drivers/input/keyboard/xtkbd.c80
-rw-r--r--drivers/input/misc/Kconfig2
-rw-r--r--drivers/input/misc/m68kspkr.c36
-rw-r--r--drivers/input/misc/pcspkr.c30
-rw-r--r--drivers/input/misc/sparcspkr.c49
-rw-r--r--drivers/input/misc/uinput.c4
-rw-r--r--drivers/input/mouse/Kconfig2
-rw-r--r--drivers/input/mouse/Makefile2
-rw-r--r--drivers/input/mouse/alps.c65
-rw-r--r--drivers/input/mouse/alps.h2
-rw-r--r--drivers/input/mouse/amimouse.c49
-rw-r--r--drivers/input/mouse/hil_ptr.c33
-rw-r--r--drivers/input/mouse/inport.c96
-rw-r--r--drivers/input/mouse/lifebook.c16
-rw-r--r--drivers/input/mouse/logibm.c88
-rw-r--r--drivers/input/mouse/logips2pp.c33
-rw-r--r--drivers/input/mouse/maplemouse.c10
-rw-r--r--drivers/input/mouse/pc110pad.c64
-rw-r--r--drivers/input/mouse/psmouse-base.c231
-rw-r--r--drivers/input/mouse/psmouse.h54
-rw-r--r--drivers/input/mouse/rpcmouse.c43
-rw-r--r--drivers/input/mouse/sermouse.c82
-rw-r--r--drivers/input/mouse/synaptics.c6
-rw-r--r--drivers/input/mouse/trackpoint.c304
-rw-r--r--drivers/input/mouse/trackpoint.h147
-rw-r--r--drivers/input/mouse/vsxxxaa.c84
-rw-r--r--drivers/input/mousedev.c25
-rw-r--r--drivers/input/serio/ct82c710.c1
-rw-r--r--drivers/input/serio/gscps2.c17
-rw-r--r--drivers/input/serio/hil_mlc.c14
-rw-r--r--drivers/input/serio/hp_sdc.c8
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c1
-rw-r--r--drivers/input/serio/i8042-io.h6
-rw-r--r--drivers/input/serio/i8042-ip22io.h2
-rw-r--r--drivers/input/serio/i8042-jazzio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h12
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h72
-rw-r--r--drivers/input/serio/i8042.c213
-rw-r--r--drivers/input/serio/maceps2.c2
-rw-r--r--drivers/input/serio/q40kbd.c1
-rw-r--r--drivers/input/serio/rpckbd.c1
-rw-r--r--drivers/input/serio/serport.c4
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/corgi_ts.c234
-rw-r--r--drivers/input/touchscreen/elo.c89
-rw-r--r--drivers/input/touchscreen/gunze.c66
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c149
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c50
-rw-r--r--drivers/input/touchscreen/mk712.c80
-rw-r--r--drivers/input/touchscreen/mtouch.c64
-rw-r--r--drivers/input/tsdev.c19
-rw-r--r--drivers/isdn/act2000/capi.c2
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/isdn/capi/capifs.c5
-rw-r--r--drivers/isdn/divert/divert_procfs.c6
-rw-r--r--drivers/isdn/hardware/eicon/diva_didd.c6
-rw-r--r--drivers/isdn/hardware/eicon/divasproc.c2
-rw-r--r--drivers/isdn/hisax/Kconfig1
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c10
-rw-r--r--drivers/isdn/hisax/hfc_pci.c1
-rw-r--r--drivers/isdn/hisax/hisax.h3
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c2
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_b.c20
-rw-r--r--drivers/isdn/hisax/st5481_d.c26
-rw-r--r--drivers/isdn/hisax/st5481_init.c4
-rw-r--r--drivers/isdn/hisax/st5481_usb.c68
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c2
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c14
-rw-r--r--drivers/isdn/i4l/isdn_common.c3
-rw-r--r--drivers/isdn/i4l/isdn_net.c1
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c1
-rw-r--r--drivers/isdn/i4l/isdn_v110.c4
-rw-r--r--drivers/isdn/icn/icn.c5
-rw-r--r--drivers/isdn/sc/init.c4
-rw-r--r--drivers/macintosh/Kconfig2
-rw-r--r--drivers/macintosh/adb.c2
-rw-r--r--drivers/macintosh/adbhid.c223
-rw-r--r--drivers/macintosh/ans-lcd.c10
-rw-r--r--drivers/macintosh/apm_emu.c8
-rw-r--r--drivers/macintosh/mac_hid.c40
-rw-r--r--drivers/macintosh/macio_asic.c2
-rw-r--r--drivers/macintosh/macio_sysfs.c26
-rw-r--r--drivers/macintosh/mediabay.c62
-rw-r--r--drivers/macintosh/smu.c1032
-rw-r--r--drivers/macintosh/therm_adt746x.c2
-rw-r--r--drivers/macintosh/therm_pm72.c2
-rw-r--r--drivers/macintosh/therm_windtunnel.c2
-rw-r--r--drivers/macintosh/via-cuda.c1
-rw-r--r--drivers/macintosh/via-pmu.c173
-rw-r--r--drivers/macintosh/via-pmu68k.c15
-rw-r--r--drivers/mca/mca-device.c1
-rw-r--r--drivers/md/bitmap.c248
-rw-r--r--drivers/md/dm-crypt.c23
-rw-r--r--drivers/md/dm-exception-store.c9
-rw-r--r--drivers/md/dm-io.c8
-rw-r--r--drivers/md/dm-ioctl.c9
-rw-r--r--drivers/md/dm-mpath.c16
-rw-r--r--drivers/md/dm-raid1.c16
-rw-r--r--drivers/md/dm.c6
-rw-r--r--drivers/md/linear.c108
-rw-r--r--drivers/md/md.c259
-rw-r--r--drivers/md/multipath.c17
-rw-r--r--drivers/md/raid0.c13
-rw-r--r--drivers/md/raid1.c279
-rw-r--r--drivers/md/raid10.c62
-rw-r--r--drivers/md/raid5.c148
-rw-r--r--drivers/md/raid6.h4
-rw-r--r--drivers/md/raid6algos.c1
-rw-r--r--drivers/md/raid6altivec.uc18
-rw-r--r--drivers/md/raid6main.c150
-rw-r--r--drivers/md/raid6test/Makefile27
-rw-r--r--drivers/media/Makefile5
-rw-r--r--drivers/media/common/ir-common.c70
-rw-r--r--drivers/media/common/saa7146_core.c6
-rw-r--r--drivers/media/common/saa7146_fops.c1
-rw-r--r--drivers/media/common/saa7146_i2c.c10
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c102
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c3
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig6
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h2
-rw-r--r--drivers/media/dvb/bt8xx/dst.c763
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c554
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h8
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c282
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h2
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c178
-rw-r--r--drivers/media/dvb/dvb-core/demux.h36
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c20
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c532
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.h116
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c9
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig23
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c2
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c68
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h27
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c21
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c20
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c2
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c42
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c25
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c5
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h10
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c20
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c50
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h7
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c2
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c339
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c290
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h109
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c9
-rw-r--r--drivers/media/dvb/frontends/Kconfig2
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c3
-rw-r--r--drivers/media/dvb/frontends/cx24110.c22
-rw-r--r--drivers/media/dvb/frontends/cx24110.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c3
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c3
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c16
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h1
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c2
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c530
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.h16
-rw-r--r--drivers/media/dvb/frontends/lgdt330x_priv.h8
-rw-r--r--drivers/media/dvb/frontends/mt312.c2
-rw-r--r--drivers/media/dvb/frontends/mt352.c8
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c2
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c9
-rw-r--r--drivers/media/dvb/frontends/or51132.c29
-rw-r--r--drivers/media/dvb/frontends/or51211.c2
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c164
-rw-r--r--drivers/media/dvb/frontends/s5h1420.h3
-rw-r--r--drivers/media/dvb/frontends/sp8870.c2
-rw-r--r--drivers/media/dvb/frontends/sp887x.c2
-rw-r--r--drivers/media/dvb/frontends/stv0297.c131
-rw-r--r--drivers/media/dvb/frontends/stv0297.h8
-rw-r--r--drivers/media/dvb/frontends/stv0299.c20
-rw-r--r--drivers/media/dvb/frontends/stv0299.h4
-rw-r--r--drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c7
-rw-r--r--drivers/media/dvb/frontends/tda8083.c1
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c1
-rw-r--r--drivers/media/dvb/frontends/ves1820.c15
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c1
-rw-r--r--drivers/media/dvb/ttpci/Kconfig3
-rw-r--r--drivers/media/dvb/ttpci/av7110.c201
-rw-r--r--drivers/media/dvb/ttpci/av7110.h11
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c8
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c165
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c74
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c9
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c221
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c5
-rw-r--r--drivers/media/dvb/ttpci/budget.c6
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c13
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c52
-rw-r--r--drivers/media/radio/miropcm20-rds.c1
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-aztech.c2
-rw-r--r--drivers/media/radio/radio-cadet.c4
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c2
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-typhoon.c2
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
-rw-r--r--drivers/media/video/Kconfig19
-rw-r--r--drivers/media/video/Makefile4
-rw-r--r--drivers/media/video/adv7170.c2
-rw-r--r--drivers/media/video/adv7175.c2
-rw-r--r--drivers/media/video/bt819.c2
-rw-r--r--drivers/media/video/bt832.c4
-rw-r--r--drivers/media/video/bt856.c2
-rw-r--r--drivers/media/video/btcx-risc.c1
-rw-r--r--drivers/media/video/btcx-risc.h1
-rw-r--r--drivers/media/video/bttv-cards.c1188
-rw-r--r--drivers/media/video/bttv-driver.c108
-rw-r--r--drivers/media/video/bttv-gpio.c1
-rw-r--r--drivers/media/video/bttv-i2c.c14
-rw-r--r--drivers/media/video/bttv-if.c1
-rw-r--r--drivers/media/video/bttv-risc.c1
-rw-r--r--drivers/media/video/bttv-vbi.c1
-rw-r--r--drivers/media/video/bttv.h3
-rw-r--r--drivers/media/video/bttvp.h5
-rw-r--r--drivers/media/video/cpia.c2
-rw-r--r--drivers/media/video/cpia_usb.c30
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c73
-rw-r--r--drivers/media/video/cx88/cx88-cards.c26
-rw-r--r--drivers/media/video/cx88/cx88-core.c21
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c72
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c9
-rw-r--r--drivers/media/video/cx88/cx88-input.c149
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c37
-rw-r--r--drivers/media/video/cx88/cx88-reg.h24
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c742
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c1
-rw-r--r--drivers/media/video/cx88/cx88-video.c408
-rw-r--r--drivers/media/video/cx88/cx88.h41
-rw-r--r--drivers/media/video/indycam.c410
-rw-r--r--drivers/media/video/indycam.h112
-rw-r--r--drivers/media/video/ir-kbd-gpio.c52
-rw-r--r--drivers/media/video/ir-kbd-i2c.c40
-rw-r--r--drivers/media/video/meye.c3
-rw-r--r--drivers/media/video/msp3400.c22
-rw-r--r--drivers/media/video/msp3400.h1
-rw-r--r--drivers/media/video/mt20xx.c2
-rw-r--r--drivers/media/video/ovcamchip/ov6x20.c6
-rw-r--r--drivers/media/video/ovcamchip/ov6x30.c4
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c14
-rw-r--r--drivers/media/video/rds.h48
-rw-r--r--drivers/media/video/saa6588.c534
-rw-r--r--drivers/media/video/saa7110.c1
-rw-r--r--drivers/media/video/saa7111.c2
-rw-r--r--drivers/media/video/saa7114.c2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c132
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c39
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-reg.h1
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c25
-rw-r--r--drivers/media/video/saa7134/saa7134.h6
-rw-r--r--drivers/media/video/saa7185.c2
-rw-r--r--drivers/media/video/saa7191.c510
-rw-r--r--drivers/media/video/saa7191.h139
-rw-r--r--drivers/media/video/stradis.c32
-rw-r--r--drivers/media/video/tda7432.c4
-rw-r--r--drivers/media/video/tda8290.c19
-rw-r--r--drivers/media/video/tda9840.c4
-rw-r--r--drivers/media/video/tda9875.c4
-rw-r--r--drivers/media/video/tda9887.c64
-rw-r--r--drivers/media/video/tea5767.c37
-rw-r--r--drivers/media/video/tea6415c.c4
-rw-r--r--drivers/media/video/tea6420.c4
-rw-r--r--drivers/media/video/tuner-3036.c3
-rw-r--r--drivers/media/video/tuner-core.c97
-rw-r--r--drivers/media/video/tuner-simple.c54
-rw-r--r--drivers/media/video/tvaudio.c225
-rw-r--r--drivers/media/video/tveeprom.c364
-rw-r--r--drivers/media/video/tvmixer.c15
-rw-r--r--drivers/media/video/v4l1-compat.c16
-rw-r--r--drivers/media/video/v4l2-common.c18
-rw-r--r--drivers/media/video/video-buf-dvb.c1
-rw-r--r--drivers/media/video/video-buf.c9
-rw-r--r--drivers/media/video/vino.c4274
-rw-r--r--drivers/media/video/vino.h61
-rw-r--r--drivers/media/video/vpx3220.c33
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/media/video/zoran_driver.c2
-rw-r--r--drivers/media/video/zr36120.c6
-rw-r--r--drivers/message/fusion/Kconfig17
-rw-r--r--drivers/message/fusion/Makefile1
-rw-r--r--drivers/message/fusion/lsi/mpi.h19
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h85
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt67
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h203
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h11
-rw-r--r--drivers/message/fusion/lsi/mpi_targ.h74
-rw-r--r--drivers/message/fusion/mptbase.c1276
-rw-r--r--drivers/message/fusion/mptbase.h61
-rw-r--r--drivers/message/fusion/mptctl.c18
-rw-r--r--drivers/message/fusion/mptfc.c2
-rw-r--r--drivers/message/fusion/mptlan.c7
-rw-r--r--drivers/message/fusion/mptsas.c1239
-rw-r--r--drivers/message/fusion/mptscsih.c593
-rw-r--r--drivers/message/fusion/mptscsih.h7
-rw-r--r--drivers/message/fusion/mptspi.c8
-rw-r--r--drivers/message/i2o/Kconfig3
-rw-r--r--drivers/message/i2o/config-osm.c499
-rw-r--r--drivers/message/i2o/core.h3
-rw-r--r--drivers/message/i2o/debug.c2
-rw-r--r--drivers/message/i2o/device.c274
-rw-r--r--drivers/message/i2o/driver.c6
-rw-r--r--drivers/message/i2o/exec-osm.c4
-rw-r--r--drivers/message/i2o/iop.c33
-rw-r--r--drivers/message/i2o/pci.c10
-rw-r--r--drivers/mfd/Kconfig25
-rw-r--r--drivers/mfd/Makefile12
-rw-r--r--drivers/mfd/mcp-core.c255
-rw-r--r--drivers/mfd/mcp-sa11x0.c273
-rw-r--r--drivers/mfd/mcp.h66
-rw-r--r--drivers/mfd/ucb1x00-assabet.c73
-rw-r--r--drivers/mfd/ucb1x00-core.c663
-rw-r--r--drivers/mfd/ucb1x00-ts.c436
-rw-r--r--drivers/mfd/ucb1x00.h254
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c25
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c2
-rw-r--r--drivers/misc/ibmasm/uart.c20
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/au1xmmc.c1026
-rw-r--r--drivers/mmc/au1xmmc.h96
-rw-r--r--drivers/mmc/mmc.c565
-rw-r--r--drivers/mmc/mmc.h5
-rw-r--r--drivers/mmc/mmc_block.c15
-rw-r--r--drivers/mmc/mmc_sysfs.c113
-rw-r--r--drivers/mmc/mmci.c7
-rw-r--r--drivers/mmc/pxamci.c26
-rw-r--r--drivers/mmc/wbsd.c665
-rw-r--r--drivers/mmc/wbsd.h27
-rw-r--r--drivers/mtd/chips/jedec.c1
-rw-r--r--drivers/mtd/devices/docecc.c8
-rw-r--r--drivers/mtd/devices/lart.c1
-rw-r--r--drivers/mtd/devices/mtdram.c3
-rw-r--r--drivers/mtd/devices/phram.c1
-rw-r--r--drivers/mtd/ftl.c11
-rw-r--r--drivers/mtd/maps/bast-flash.c4
-rw-r--r--drivers/mtd/maps/ceiva.c1
-rw-r--r--drivers/mtd/maps/dc21285.c1
-rw-r--r--drivers/mtd/maps/dilnetpc.c5
-rw-r--r--drivers/mtd/maps/epxa10db-flash.c5
-rw-r--r--drivers/mtd/maps/fortunet.c5
-rw-r--r--drivers/mtd/maps/integrator-flash.c2
-rw-r--r--drivers/mtd/maps/ixp2000.c8
-rw-r--r--drivers/mtd/maps/ixp4xx.c11
-rw-r--r--drivers/mtd/maps/lubbock-flash.c3
-rw-r--r--drivers/mtd/maps/mainstone-flash.c3
-rw-r--r--drivers/mtd/maps/omap-toto-flash.c2
-rw-r--r--drivers/mtd/maps/omap_nor.c5
-rw-r--r--drivers/mtd/maps/pci.c1
-rw-r--r--drivers/mtd/maps/plat-ram.c2
-rw-r--r--drivers/mtd/maps/sa1100-flash.c78
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c2
-rw-r--r--drivers/mtd/maps/tqm8xxl.c4
-rw-r--r--drivers/mtd/maps/uclinux.c13
-rw-r--r--drivers/mtd/mtdblock.c1
-rw-r--r--drivers/mtd/mtdchar.c5
-rw-r--r--drivers/mtd/mtdconcat.c2
-rw-r--r--drivers/mtd/nand/nand_base.c1
-rw-r--r--drivers/mtd/nand/s3c2410.c4
-rw-r--r--drivers/mtd/nand/sharpsl.c10
-rw-r--r--drivers/net/3c59x.c19
-rw-r--r--drivers/net/8139cp.c58
-rw-r--r--drivers/net/8139too.c5
-rw-r--r--drivers/net/8390.c2
-rw-r--r--drivers/net/Kconfig177
-rw-r--r--drivers/net/Makefile13
-rw-r--r--drivers/net/Space.c12
-rw-r--r--drivers/net/ac3200.c2
-rw-r--r--drivers/net/acenic.c6
-rw-r--r--[-rwxr-xr-x]drivers/net/amd8111e.c0
-rw-r--r--[-rwxr-xr-x]drivers/net/amd8111e.h0
-rw-r--r--drivers/net/arcnet/arcnet.c25
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/arm/am79c961a.c64
-rw-r--r--drivers/net/arm/am79c961a.h2
-rw-r--r--drivers/net/atari_bionet.c2
-rw-r--r--drivers/net/atari_pamsnet.c2
-rw-r--r--drivers/net/atarilance.c2
-rw-r--r--drivers/net/au1000_eth.c19
-rw-r--r--drivers/net/b44.c164
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bmac.c9
-rw-r--r--drivers/net/bnx2.c264
-rw-r--r--drivers/net/bnx2.h11
-rw-r--r--drivers/net/bonding/bond_3ad.c11
-rw-r--r--drivers/net/bonding/bond_3ad.h2
-rw-r--r--drivers/net/bonding/bond_alb.c22
-rw-r--r--drivers/net/bonding/bond_main.c416
-rw-r--r--drivers/net/bonding/bonding.h7
-rw-r--r--drivers/net/bsd_comp.c28
-rw-r--r--drivers/net/cassini.c5237
-rw-r--r--drivers/net/cassini.h4425
-rw-r--r--drivers/net/chelsio/Makefile11
-rw-r--r--drivers/net/chelsio/common.h314
-rw-r--r--drivers/net/chelsio/cphy.h148
-rw-r--r--drivers/net/chelsio/cpl5_cmd.h145
-rw-r--r--drivers/net/chelsio/cxgb2.c1256
-rw-r--r--drivers/net/chelsio/elmer0.h151
-rw-r--r--drivers/net/chelsio/espi.c346
-rw-r--r--drivers/net/chelsio/espi.h68
-rw-r--r--drivers/net/chelsio/gmac.h134
-rw-r--r--drivers/net/chelsio/mv88x201x.c252
-rw-r--r--drivers/net/chelsio/pm3393.c826
-rw-r--r--drivers/net/chelsio/regs.h468
-rw-r--r--drivers/net/chelsio/sge.c1684
-rw-r--r--drivers/net/chelsio/sge.h105
-rw-r--r--drivers/net/chelsio/subr.c812
-rw-r--r--drivers/net/chelsio/suni1x10gexp_regs.h213
-rw-r--r--drivers/net/cris/eth_v10.c6
-rw-r--r--drivers/net/cs89x0.c20
-rw-r--r--drivers/net/declance.c37
-rw-r--r--drivers/net/depca.c2
-rw-r--r--drivers/net/dm9000.c61
-rw-r--r--drivers/net/e100.c25
-rw-r--r--drivers/net/e1000/e1000.h74
-rw-r--r--drivers/net/e1000/e1000_ethtool.c102
-rw-r--r--drivers/net/e1000/e1000_hw.c220
-rw-r--r--drivers/net/e1000/e1000_hw.h98
-rw-r--r--drivers/net/e1000/e1000_main.c1103
-rw-r--r--drivers/net/e1000/e1000_param.c10
-rw-r--r--drivers/net/eepro.c57
-rw-r--r--drivers/net/eepro100.c8
-rw-r--r--drivers/net/epic100.c4
-rw-r--r--drivers/net/fec.c478
-rw-r--r--drivers/net/fec.h7
-rw-r--r--drivers/net/forcedeth.c840
-rw-r--r--drivers/net/fs_enet/Kconfig20
-rw-r--r--drivers/net/fs_enet/Makefile10
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c1226
-rw-r--r--drivers/net/fs_enet/fs_enet-mii.c507
-rw-r--r--drivers/net/fs_enet/fs_enet.h245
-rw-r--r--drivers/net/fs_enet/mac-fcc.c578
-rw-r--r--drivers/net/fs_enet/mac-fec.c653
-rw-r--r--drivers/net/fs_enet/mac-scc.c524
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c405
-rw-r--r--drivers/net/fs_enet/mii-fixed.c92
-rw-r--r--drivers/net/gianfar.c414
-rw-r--r--drivers/net/gianfar.h30
-rw-r--r--drivers/net/gianfar_ethtool.c100
-rw-r--r--drivers/net/gianfar_mii.c220
-rw-r--r--drivers/net/gianfar_mii.h45
-rw-r--r--drivers/net/gianfar_phy.c661
-rw-r--r--drivers/net/gianfar_phy.h213
-rw-r--r--drivers/net/hamachi.c4
-rw-r--r--drivers/net/hamradio/6pack.c31
-rw-r--r--drivers/net/hamradio/Kconfig3
-rw-r--r--drivers/net/hamradio/baycom_epp.c20
-rw-r--r--drivers/net/hamradio/baycom_par.c3
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c3
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c3
-rw-r--r--drivers/net/hamradio/bpqether.c15
-rw-r--r--drivers/net/hamradio/dmascc.c10
-rw-r--r--drivers/net/hamradio/hdlcdrv.c16
-rw-r--r--drivers/net/hamradio/mkiss.c1244
-rw-r--r--drivers/net/hamradio/mkiss.h62
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/hamradio/yam.c30
-rw-r--r--drivers/net/hp100.c48
-rw-r--r--drivers/net/ibm_emac/Makefile13
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h408
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c3372
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.h313
-rw-r--r--drivers/net/ibm_emac/ibm_emac_debug.c363
-rw-r--r--drivers/net/ibm_emac/ibm_emac_debug.h63
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.c674
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.h332
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.c335
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.h105
-rw-r--r--drivers/net/ibm_emac/ibm_emac_rgmii.c201
-rw-r--r--drivers/net/ibm_emac/ibm_emac_rgmii.h60
-rw-r--r--drivers/net/ibm_emac/ibm_emac_tah.c111
-rw-r--r--drivers/net/ibm_emac/ibm_emac_tah.h96
-rw-r--r--drivers/net/ibm_emac/ibm_emac_zmii.c255
-rw-r--r--drivers/net/ibm_emac/ibm_emac_zmii.h104
-rw-r--r--drivers/net/ibmveth.c208
-rw-r--r--drivers/net/ibmveth.h23
-rw-r--r--drivers/net/ioc3-eth.c8
-rw-r--r--drivers/net/irda/Kconfig10
-rw-r--r--drivers/net/irda/Makefile1
-rw-r--r--drivers/net/irda/donauboe.c6
-rw-r--r--drivers/net/irda/irda-usb.c19
-rw-r--r--drivers/net/irda/irport.c3
-rw-r--r--drivers/net/irda/pxaficp_ir.c866
-rw-r--r--drivers/net/irda/sa1100_ir.c10
-rw-r--r--drivers/net/irda/sir_dev.c3
-rw-r--r--drivers/net/irda/smsc-ircc2.c1273
-rw-r--r--drivers/net/irda/smsc-ircc2.h50
-rw-r--r--drivers/net/irda/stir4200.c7
-rw-r--r--drivers/net/irda/vlsi_ir.c28
-rw-r--r--drivers/net/irda/vlsi_ir.h6
-rw-r--r--drivers/net/iseries_veth.c896
-rw-r--r--drivers/net/iseries_veth.h46
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_ee.c170
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c67
-rw-r--r--drivers/net/ixgb/ixgb_hw.h9
-rw-r--r--drivers/net/ixgb/ixgb_main.c58
-rw-r--r--drivers/net/jazzsonic.c188
-rw-r--r--drivers/net/lance.c4
-rw-r--r--drivers/net/lasi_82596.c30
-rw-r--r--drivers/net/lne390.c2
-rw-r--r--drivers/net/loopback.c24
-rw-r--r--drivers/net/mace.c7
-rw-r--r--drivers/net/macsonic.c538
-rw-r--r--drivers/net/mii.c15
-rw-r--r--drivers/net/mipsnet.c372
-rw-r--r--drivers/net/mipsnet.h127
-rw-r--r--drivers/net/mv643xx_eth.c175
-rw-r--r--drivers/net/mv643xx_eth.h8
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/myri_sbus.h2
-rw-r--r--drivers/net/ne.c15
-rw-r--r--drivers/net/ne2k-pci.c3
-rw-r--r--drivers/net/ne3210.c9
-rw-r--r--drivers/net/ni65.c9
-rw-r--r--drivers/net/ns83820.c5
-rw-r--r--drivers/net/pci-skeleton.c6
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c25
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c6
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c2
-rw-r--r--drivers/net/pcnet32.c278
-rw-r--r--drivers/net/phy/Kconfig49
-rw-r--r--drivers/net/phy/Makefile10
-rw-r--r--drivers/net/phy/cicada.c134
-rw-r--r--drivers/net/phy/davicom.c195
-rw-r--r--drivers/net/phy/lxt.c179
-rw-r--r--drivers/net/phy/marvell.c140
-rw-r--r--drivers/net/phy/mdio_bus.c168
-rw-r--r--drivers/net/phy/phy.c863
-rw-r--r--drivers/net/phy/phy_device.c693
-rw-r--r--drivers/net/phy/qsemi.c143
-rw-r--r--drivers/net/ppp_generic.c26
-rw-r--r--drivers/net/pppoe.c10
-rw-r--r--drivers/net/r8169.c10
-rw-r--r--drivers/net/rionet.c574
-rw-r--r--drivers/net/rrunner.c9
-rw-r--r--drivers/net/s2io-regs.h103
-rw-r--r--drivers/net/s2io.c3888
-rw-r--r--drivers/net/s2io.h415
-rw-r--r--drivers/net/saa9730.c8
-rw-r--r--drivers/net/sb1250-mac.c1384
-rw-r--r--drivers/net/sgiseeq.c37
-rw-r--r--drivers/net/shaper.c50
-rw-r--r--drivers/net/sis190.c1884
-rw-r--r--drivers/net/sis900.c16
-rw-r--r--drivers/net/sk98lin/skge.c20
-rw-r--r--drivers/net/skfp/smt.c2
-rw-r--r--drivers/net/skge.c399
-rw-r--r--drivers/net/skge.h23
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smc91x.c14
-rw-r--r--drivers/net/smc91x.h14
-rw-r--r--drivers/net/sonic.c676
-rw-r--r--drivers/net/sonic.h460
-rw-r--r--drivers/net/spider_net.c2338
-rw-r--r--drivers/net/spider_net.h469
-rw-r--r--drivers/net/spider_net_ethtool.c126
-rw-r--r--drivers/net/starfire.c50
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/sunbmac.c3
-rw-r--r--drivers/net/sunbmac.h2
-rw-r--r--drivers/net/sundance.c111
-rw-r--r--drivers/net/sungem.c37
-rw-r--r--drivers/net/sungem.h5
-rw-r--r--drivers/net/sunhme.c43
-rw-r--r--drivers/net/tg3.c827
-rw-r--r--drivers/net/tg3.h21
-rw-r--r--drivers/net/tokenring/Kconfig4
-rw-r--r--drivers/net/tokenring/abyss.c2
-rw-r--r--drivers/net/tokenring/ibmtr.c14
-rw-r--r--drivers/net/tokenring/madgemc.c521
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/proteon.c105
-rw-r--r--drivers/net/tokenring/skisa.c105
-rw-r--r--drivers/net/tokenring/tms380tr.c49
-rw-r--r--drivers/net/tokenring/tms380tr.h9
-rw-r--r--drivers/net/tokenring/tmspci.c4
-rw-r--r--drivers/net/tulip/21142.c2
-rw-r--r--drivers/net/tulip/Kconfig12
-rw-r--r--drivers/net/tulip/Makefile1
-rw-r--r--drivers/net/tulip/de2104x.c13
-rw-r--r--drivers/net/tulip/de4x5.c4
-rw-r--r--drivers/net/tulip/media.c36
-rw-r--r--drivers/net/tulip/timer.c1
-rw-r--r--drivers/net/tulip/tulip.h8
-rw-r--r--drivers/net/tulip/tulip_core.c41
-rw-r--r--drivers/net/tulip/uli526x.c1749
-rw-r--r--drivers/net/tulip/xircom_cb.c2
-rw-r--r--drivers/net/tun.c15
-rw-r--r--drivers/net/typhoon.c7
-rw-r--r--drivers/net/via-rhine.c38
-rw-r--r--drivers/net/via-velocity.c6
-rw-r--r--drivers/net/wan/cosa.c8
-rw-r--r--drivers/net/wan/cycx_drv.c31
-rw-r--r--drivers/net/wan/cycx_main.c2
-rw-r--r--drivers/net/wan/cycx_x25.c5
-rw-r--r--drivers/net/wan/dscc4.c23
-rw-r--r--drivers/net/wan/farsync.c27
-rw-r--r--drivers/net/wan/hdlc_cisco.c2
-rw-r--r--drivers/net/wan/hdlc_fr.c2
-rw-r--r--drivers/net/wan/hdlc_generic.c2
-rw-r--r--drivers/net/wan/lapbether.c2
-rw-r--r--drivers/net/wan/lmc/lmc_debug.c10
-rw-r--r--drivers/net/wan/lmc/lmc_media.c8
-rw-r--r--drivers/net/wan/pc300.h16
-rw-r--r--drivers/net/wan/pc300_drv.c87
-rw-r--r--drivers/net/wan/pc300_tty.c18
-rw-r--r--drivers/net/wan/sdla.c20
-rw-r--r--drivers/net/wan/sdla_fr.c26
-rw-r--r--drivers/net/wan/sdla_x25.c8
-rw-r--r--drivers/net/wan/sdladrv.c16
-rw-r--r--drivers/net/wan/sdlamain.c23
-rw-r--r--drivers/net/wan/syncppp.c15
-rw-r--r--drivers/net/wireless/Kconfig148
-rw-r--r--drivers/net/wireless/Makefile8
-rw-r--r--drivers/net/wireless/airo.c218
-rw-r--r--drivers/net/wireless/airo_cs.c4
-rw-r--r--drivers/net/wireless/airport.c19
-rw-r--r--drivers/net/wireless/atmel.c85
-rw-r--r--drivers/net/wireless/atmel_cs.c3
-rw-r--r--drivers/net/wireless/hermes.c49
-rw-r--r--drivers/net/wireless/hermes.h113
-rw-r--r--drivers/net/wireless/hostap/Kconfig73
-rw-r--r--drivers/net/wireless/hostap/Makefile5
-rw-r--r--drivers/net/wireless/hostap/hostap.c1192
-rw-r--r--drivers/net/wireless/hostap/hostap.h57
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h96
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c1092
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c524
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c3288
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h261
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h435
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h55
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c1006
-rw-r--r--drivers/net/wireless/hostap/hostap_download.c766
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c3447
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c499
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c4090
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c474
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c640
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c448
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h1031
-rw-r--r--drivers/net/wireless/ieee802_11.h78
-rw-r--r--drivers/net/wireless/ipw2100.c8676
-rw-r--r--drivers/net/wireless/ipw2100.h1167
-rw-r--r--drivers/net/wireless/ipw2200.c7386
-rw-r--r--drivers/net/wireless/ipw2200.h1680
-rw-r--r--drivers/net/wireless/netwave_cs.c184
-rw-r--r--drivers/net/wireless/orinoco.c423
-rw-r--r--drivers/net/wireless/orinoco.h16
-rw-r--r--drivers/net/wireless/orinoco_cs.c112
-rw-r--r--drivers/net/wireless/orinoco_nortel.c308
-rw-r--r--drivers/net/wireless/orinoco_pci.c20
-rw-r--r--drivers/net/wireless/orinoco_plx.c18
-rw-r--r--drivers/net/wireless/orinoco_tmd.c18
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c9
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c12
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c13
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.c7
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c9
-rw-r--r--drivers/net/wireless/ray_cs.c866
-rw-r--r--drivers/net/wireless/ray_cs.h7
-rw-r--r--drivers/net/wireless/spectrum_cs.c1073
-rw-r--r--drivers/net/wireless/strip.c44
-rw-r--r--drivers/net/wireless/wavelan.c8
-rw-r--r--drivers/net/wireless/wavelan.p.h4
-rw-r--r--drivers/net/wireless/wavelan_cs.c34
-rw-r--r--drivers/net/wireless/wavelan_cs.h6
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h21
-rw-r--r--drivers/net/wireless/wl3501.h5
-rw-r--r--drivers/net/wireless/wl3501_cs.c18
-rw-r--r--drivers/parisc/asp.c6
-rw-r--r--drivers/parisc/ccio-dma.c144
-rw-r--r--drivers/parisc/ccio-rm-dma.c2
-rw-r--r--drivers/parisc/dino.c42
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/gsc.c11
-rw-r--r--drivers/parisc/hppb.c10
-rw-r--r--drivers/parisc/iosapic.c4
-rw-r--r--drivers/parisc/lasi.c5
-rw-r--r--drivers/parisc/lba_pci.c14
-rw-r--r--drivers/parisc/led.c230
-rw-r--r--drivers/parisc/pdc_stable.c2
-rw-r--r--drivers/parisc/sba_iommu.c166
-rw-r--r--drivers/parisc/superio.c3
-rw-r--r--drivers/parisc/wax.c2
-rw-r--r--drivers/parport/Kconfig2
-rw-r--r--drivers/parport/ieee1284.c7
-rw-r--r--drivers/parport/ieee1284_ops.c10
-rw-r--r--drivers/parport/parport_gsc.c5
-rw-r--r--drivers/parport/parport_pc.c8
-rw-r--r--drivers/parport/parport_serial.c339
-rw-r--r--drivers/pci/.gitignore4
-rw-r--r--drivers/pci/Kconfig17
-rw-r--r--drivers/pci/Makefile22
-rw-r--r--drivers/pci/access.c89
-rw-r--r--drivers/pci/bus.c51
-rw-r--r--drivers/pci/gen-devlist.c132
-rw-r--r--drivers/pci/hotplug.c55
-rw-r--r--drivers/pci/hotplug/Kconfig4
-rw-r--r--drivers/pci/hotplug/Makefile7
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c8
-rw-r--r--drivers/pci/hotplug/cpcihp_generic.c1
-rw-r--r--drivers/pci/hotplug/cpcihp_zt5550.c26
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c24
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h4
-rw-r--r--drivers/pci/hotplug/pciehp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c6
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c4
-rw-r--r--drivers/pci/hotplug/pciehprm.h2
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c10
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.c5
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.h2
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c302
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c4
-rw-r--r--drivers/pci/hotplug/rpaphp.h38
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c149
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c312
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c69
-rw-r--r--drivers/pci/hotplug/rpaphp_vio.c129
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c195
-rw-r--r--drivers/pci/hotplug/shpchp.h128
-rw-r--r--drivers/pci/hotplug/shpchp_core.c113
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c2037
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c177
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c863
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c119
-rw-r--r--drivers/pci/hotplug/shpchprm.h55
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c1651
-rw-r--r--drivers/pci/hotplug/shpchprm_legacy.c397
-rw-r--r--drivers/pci/hotplug/shpchprm_legacy.h113
-rw-r--r--drivers/pci/hotplug/shpchprm_nonacpi.c393
-rw-r--r--drivers/pci/hotplug/shpchprm_nonacpi.h56
-rw-r--r--drivers/pci/msi.c34
-rw-r--r--drivers/pci/msi.h5
-rw-r--r--drivers/pci/names.c137
-rw-r--r--drivers/pci/pci-driver.c56
-rw-r--r--drivers/pci/pci-sysfs.c32
-rw-r--r--drivers/pci/pci.c134
-rw-r--r--drivers/pci/pci.h14
-rw-r--r--drivers/pci/pci.ids10180
-rw-r--r--drivers/pci/pcie/portdrv_core.c6
-rw-r--r--drivers/pci/pcie/portdrv_pci.c9
-rw-r--r--drivers/pci/probe.c83
-rw-r--r--drivers/pci/proc.c40
-rw-r--r--drivers/pci/quirks.c465
-rw-r--r--drivers/pci/rom.c25
-rw-r--r--drivers/pci/setup-bus.c6
-rw-r--r--drivers/pci/setup-res.c18
-rw-r--r--drivers/pci/syscall.c14
-rw-r--r--drivers/pcmcia/Kconfig19
-rw-r--r--drivers/pcmcia/Makefile5
-rw-r--r--drivers/pcmcia/au1000_db1x00.c21
-rw-r--r--drivers/pcmcia/au1000_generic.c31
-rw-r--r--drivers/pcmcia/au1000_generic.h4
-rw-r--r--drivers/pcmcia/cardbus.c5
-rw-r--r--drivers/pcmcia/cs.c12
-rw-r--r--drivers/pcmcia/cs_internal.h4
-rw-r--r--drivers/pcmcia/ds.c40
-rw-r--r--drivers/pcmcia/hd64465_ss.c22
-rw-r--r--drivers/pcmcia/i82365.c22
-rw-r--r--drivers/pcmcia/m32r_cfc.c23
-rw-r--r--drivers/pcmcia/m32r_pcc.c23
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c1290
-rw-r--r--drivers/pcmcia/omap_cf.c358
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c12
-rw-r--r--drivers/pcmcia/pcmcia_resource.c12
-rw-r--r--drivers/pcmcia/pxa2xx_base.c29
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c4
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c149
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c18
-rw-r--r--drivers/pcmcia/sa1100_generic.c30
-rw-r--r--drivers/pcmcia/sa1111_generic.c4
-rw-r--r--drivers/pcmcia/sa11xx_base.c2
-rw-r--r--drivers/pcmcia/soc_common.c14
-rw-r--r--drivers/pcmcia/socket_sysfs.c6
-rw-r--r--drivers/pcmcia/tcic.c22
-rw-r--r--drivers/pcmcia/ti113x.h118
-rw-r--r--drivers/pcmcia/topic.h17
-rw-r--r--drivers/pcmcia/vrc4171_card.c25
-rw-r--r--drivers/pcmcia/yenta_socket.c304
-rw-r--r--drivers/pcmcia/yenta_socket.h8
-rw-r--r--drivers/pnp/Kconfig2
-rw-r--r--drivers/pnp/card.c9
-rw-r--r--drivers/pnp/driver.c7
-rw-r--r--drivers/pnp/isapnp/core.c33
-rw-r--r--drivers/pnp/manager.c9
-rw-r--r--drivers/pnp/pnpacpi/Kconfig2
-rw-r--r--drivers/pnp/pnpacpi/core.c16
-rw-r--r--drivers/pnp/pnpacpi/pnpacpi.h1
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c93
-rw-r--r--drivers/pnp/pnpbios/core.c26
-rw-r--r--drivers/pnp/pnpbios/pnpbios.h1
-rw-r--r--drivers/pnp/pnpbios/proc.c8
-rw-r--r--drivers/pnp/pnpbios/rsparser.c18
-rw-r--r--drivers/pnp/quirks.c7
-rw-r--r--drivers/pnp/support.c7
-rw-r--r--drivers/s390/block/Kconfig2
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_devmap.c8
-rw-r--r--drivers/s390/block/dasd_diag.c334
-rw-r--r--drivers/s390/block/dasd_diag.h105
-rw-r--r--drivers/s390/block/dasd_genhd.c10
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c17
-rw-r--r--drivers/s390/block/dasd_proc.c8
-rw-r--r--drivers/s390/char/con3270.c7
-rw-r--r--drivers/s390/char/fs3270.c234
-rw-r--r--drivers/s390/char/raw3270.c116
-rw-r--r--drivers/s390/char/raw3270.h7
-rw-r--r--drivers/s390/char/tape_class.c1
-rw-r--r--drivers/s390/char/tty3270.c27
-rw-r--r--drivers/s390/char/vmlogrdr.c1
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/cio/ccwgroup.c2
-rw-r--r--drivers/s390/cio/cio.c7
-rw-r--r--drivers/s390/cio/cmf.c3
-rw-r--r--drivers/s390/cio/device.c22
-rw-r--r--drivers/s390/cio/device_fsm.c5
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/ioasm.h26
-rw-r--r--drivers/s390/cio/qdio.c4
-rw-r--r--drivers/s390/crypto/z90common.h3
-rw-r--r--drivers/s390/crypto/z90crypt.h9
-rw-r--r--drivers/s390/crypto/z90hardware.c127
-rw-r--r--drivers/s390/crypto/z90main.c243
-rw-r--r--drivers/s390/net/claw.c20
-rw-r--r--drivers/s390/net/ctcmain.c41
-rw-r--r--drivers/s390/net/fsm.c2
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/qeth.h51
-rw-r--r--drivers/s390/net/qeth_fs.h12
-rw-r--r--drivers/s390/net/qeth_main.c615
-rw-r--r--drivers/s390/net/qeth_mpc.c6
-rw-r--r--drivers/s390/net/qeth_mpc.h15
-rw-r--r--drivers/s390/net/qeth_proc.c126
-rw-r--r--drivers/s390/net/qeth_sys.c41
-rw-r--r--drivers/s390/s390mach.c2
-rw-r--r--drivers/s390/scsi/Makefile2
-rw-r--r--drivers/s390/scsi/zfcp_aux.c214
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c995
-rw-r--r--drivers/s390/scsi/zfcp_def.h309
-rw-r--r--drivers/s390/scsi/zfcp_erp.c160
-rw-r--r--drivers/s390/scsi/zfcp_ext.h32
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c768
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h54
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c30
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c298
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c14
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c2
-rw-r--r--drivers/sbus/char/Kconfig39
-rw-r--r--drivers/sbus/char/aurora.c3
-rw-r--r--drivers/sbus/char/bbc_envctrl.c42
-rw-r--r--drivers/sbus/char/bpp.c3
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/sbus/char/envctrl.c49
-rw-r--r--drivers/sbus/char/vfc.h2
-rw-r--r--drivers/sbus/char/vfc_dev.c1
-rw-r--r--drivers/sbus/char/vfc_i2c.c18
-rw-r--r--drivers/scsi/3w-9xxx.c83
-rw-r--r--drivers/scsi/3w-9xxx.h17
-rw-r--r--drivers/scsi/3w-xxxx.c57
-rw-r--r--drivers/scsi/53c7xx.c4
-rw-r--r--drivers/scsi/Kconfig57
-rw-r--r--drivers/scsi/Makefile7
-rw-r--r--drivers/scsi/NCR5380.c9
-rw-r--r--drivers/scsi/NCR53c406a.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c590
-rw-r--r--drivers/scsi/aacraid/aacraid.h74
-rw-r--r--drivers/scsi/aacraid/commctrl.c20
-rw-r--r--drivers/scsi/aacraid/comminit.c21
-rw-r--r--drivers/scsi/aacraid/commsup.c589
-rw-r--r--drivers/scsi/aacraid/linit.c120
-rw-r--r--drivers/scsi/aacraid/rkt.c20
-rw-r--r--drivers/scsi/aacraid/rx.c20
-rw-r--r--drivers/scsi/aacraid/sa.c22
-rw-r--r--drivers/scsi/advansys.c4
-rw-r--r--drivers/scsi/ahci.c199
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx1
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c1
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c104
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4578
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h288
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c85
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c88
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.seq5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_93cx6.c36
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c60
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c138
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c40
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c45
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped6
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped933
-rw-r--r--drivers/scsi/aic7xxx/aiclib.c1377
-rw-r--r--drivers/scsi/aic7xxx/aiclib.h890
-rw-r--r--drivers/scsi/arm/Kconfig2
-rw-r--r--drivers/scsi/arm/scsi.h6
-rw-r--r--drivers/scsi/ata_piix.c129
-rw-r--r--drivers/scsi/atp870u.c6
-rw-r--r--drivers/scsi/atp870u.h5
-rw-r--r--drivers/scsi/ch.c73
-rw-r--r--drivers/scsi/constants.c49
-rw-r--r--drivers/scsi/cpqfcTSinit.c3
-rw-r--r--drivers/scsi/dc395x.c48
-rw-r--r--drivers/scsi/dec_esp.c2
-rw-r--r--drivers/scsi/dpt_i2o.c9
-rw-r--r--drivers/scsi/eata.c2
-rw-r--r--drivers/scsi/fd_mcs.c2
-rw-r--r--drivers/scsi/hosts.c150
-rw-r--r--drivers/scsi/ibmmca.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c200
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c8
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c1
-rw-r--r--drivers/scsi/ibmvscsi/srp.h2
-rw-r--r--drivers/scsi/ide-scsi.c18
-rw-r--r--drivers/scsi/ipr.c2
-rw-r--r--drivers/scsi/ips.c8
-rw-r--r--drivers/scsi/ips.h39
-rw-r--r--drivers/scsi/lasi700.c6
-rw-r--r--drivers/scsi/libata-core.c1448
-rw-r--r--drivers/scsi/libata-scsi.c1607
-rw-r--r--drivers/scsi/libata.h71
-rw-r--r--drivers/scsi/lpfc/lpfc.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c28
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h17
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c24
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h13
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid.c70
-rw-r--r--drivers/scsi/megaraid/Kconfig.megaraid9
-rw-r--r--drivers/scsi/megaraid/Makefile1
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c10
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c2806
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h1142
-rw-r--r--drivers/scsi/mesh.c37
-rw-r--r--drivers/scsi/osst.c21
-rw-r--r--drivers/scsi/pdc_adma.c741
-rw-r--r--drivers/scsi/pluto.c3
-rw-r--r--drivers/scsi/qla1280.c359
-rw-r--r--drivers/scsi/qla1280.h336
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c154
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h157
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h16
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c564
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c51
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c97
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c120
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c34
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/qlogicpti.c39
-rw-r--r--drivers/scsi/raid_class.c250
-rw-r--r--drivers/scsi/sata_mv.c1575
-rw-r--r--drivers/scsi/sata_nv.c82
-rw-r--r--drivers/scsi/sata_promise.c160
-rw-r--r--drivers/scsi/sata_promise.h31
-rw-r--r--drivers/scsi/sata_qstor.c88
-rw-r--r--drivers/scsi/sata_sil.c94
-rw-r--r--drivers/scsi/sata_sil24.c871
-rw-r--r--drivers/scsi/sata_sis.c142
-rw-r--r--drivers/scsi/sata_svw.c79
-rw-r--r--drivers/scsi/sata_sx4.c275
-rw-r--r--drivers/scsi/sata_uli.c62
-rw-r--r--drivers/scsi/sata_via.c106
-rw-r--r--drivers/scsi/sata_vsc.c73
-rw-r--r--drivers/scsi/scsi.c30
-rw-r--r--drivers/scsi/scsi_devinfo.c6
-rw-r--r--drivers/scsi/scsi_error.c116
-rw-r--r--drivers/scsi/scsi_ioctl.c67
-rw-r--r--drivers/scsi/scsi_lib.c429
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_scan.c346
-rw-r--r--drivers/scsi/scsi_sysfs.c101
-rw-r--r--drivers/scsi/scsi_transport_fc.c39
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c3
-rw-r--r--drivers/scsi/scsi_transport_sas.c819
-rw-r--r--drivers/scsi/scsi_transport_spi.c168
-rw-r--r--drivers/scsi/sd.c186
-rw-r--r--drivers/scsi/sg.c58
-rw-r--r--drivers/scsi/sr.c76
-rw-r--r--drivers/scsi/sr.h1
-rw-r--r--drivers/scsi/sr_ioctl.c62
-rw-r--r--drivers/scsi/st.c183
-rw-r--r--drivers/scsi/st.h3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h2
-rw-r--r--drivers/scsi/zalon.c4
-rw-r--r--drivers/serial/21285.c12
-rw-r--r--drivers/serial/68328serial.c1
-rw-r--r--drivers/serial/68360serial.c8
-rw-r--r--drivers/serial/8250.c105
-rw-r--r--drivers/serial/8250.h6
-rw-r--r--drivers/serial/8250_accent.c2
-rw-r--r--drivers/serial/8250_acpi.c20
-rw-r--r--drivers/serial/8250_boca.c2
-rw-r--r--drivers/serial/8250_early.c2
-rw-r--r--drivers/serial/8250_fourport.c2
-rw-r--r--drivers/serial/8250_gsc.c6
-rw-r--r--drivers/serial/8250_hub6.c2
-rw-r--r--drivers/serial/8250_mca.c2
-rw-r--r--drivers/serial/8250_pci.c500
-rw-r--r--drivers/serial/8250_pnp.c4
-rw-r--r--drivers/serial/Kconfig10
-rw-r--r--drivers/serial/amba-pl010.c11
-rw-r--r--drivers/serial/amba-pl011.c11
-rw-r--r--drivers/serial/au1x00_uart.c8
-rw-r--r--drivers/serial/clps711x.c14
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h10
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c141
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c53
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c11
-rw-r--r--drivers/serial/crisv10.c15
-rw-r--r--drivers/serial/dz.c10
-rw-r--r--drivers/serial/icom.c13
-rw-r--r--drivers/serial/imx.c89
-rw-r--r--drivers/serial/ioc4_serial.c98
-rw-r--r--drivers/serial/ip22zilog.c4
-rw-r--r--drivers/serial/jsm/jsm_tty.c4
-rw-r--r--drivers/serial/m32r_sio.c10
-rw-r--r--drivers/serial/mcfserial.c14
-rw-r--r--drivers/serial/mpc52xx_uart.c18
-rw-r--r--drivers/serial/mpsc.c12
-rw-r--r--drivers/serial/mux.c21
-rw-r--r--drivers/serial/pmac_zilog.c13
-rw-r--r--drivers/serial/pxa.c45
-rw-r--r--drivers/serial/s3c2410.c39
-rw-r--r--drivers/serial/sa1100.c20
-rw-r--r--drivers/serial/serial_core.c169
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/serial_lh7a40x.c11
-rw-r--r--drivers/serial/serial_txx9.c126
-rw-r--r--drivers/serial/sh-sci.c14
-rw-r--r--drivers/serial/sn_console.c9
-rw-r--r--drivers/serial/sunsab.c9
-rw-r--r--drivers/serial/sunsu.c42
-rw-r--r--drivers/serial/sunzilog.c9
-rw-r--r--drivers/serial/uart00.c8
-rw-r--r--drivers/serial/v850e_uart.c6
-rw-r--r--drivers/serial/vr41xx_siu.c20
-rw-r--r--drivers/sh/superhyway/superhyway.c2
-rw-r--r--drivers/tc/tc.c89
-rw-r--r--drivers/tc/zs.c34
-rw-r--r--drivers/telephony/ixj.c116
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/atm/cxacru.c2
-rw-r--r--drivers/usb/atm/usbatm.c2
-rw-r--r--drivers/usb/class/Kconfig44
-rw-r--r--drivers/usb/class/Makefile1
-rw-r--r--drivers/usb/class/audio.c12
-rw-r--r--drivers/usb/class/bluetty.c1279
-rw-r--r--drivers/usb/class/cdc-acm.c5
-rw-r--r--drivers/usb/class/usblp.c12
-rw-r--r--drivers/usb/core/Kconfig11
-rw-r--r--drivers/usb/core/Makefile4
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/config.c22
-rw-r--r--drivers/usb/core/devio.c260
-rw-r--r--drivers/usb/core/file.c23
-rw-r--r--drivers/usb/core/hcd-pci.c105
-rw-r--r--drivers/usb/core/hcd.c161
-rw-r--r--drivers/usb/core/hcd.h85
-rw-r--r--drivers/usb/core/hub.c548
-rw-r--r--drivers/usb/core/hub.h9
-rw-r--r--drivers/usb/core/inode.c53
-rw-r--r--drivers/usb/core/message.c100
-rw-r--r--drivers/usb/core/notify.c120
-rw-r--r--drivers/usb/core/sysfs.c319
-rw-r--r--drivers/usb/core/urb.c33
-rw-r--r--drivers/usb/core/usb.c208
-rw-r--r--drivers/usb/core/usb.h35
-rw-r--r--drivers/usb/gadget/dummy_hcd.c56
-rw-r--r--drivers/usb/gadget/ether.c56
-rw-r--r--drivers/usb/gadget/file_storage.c85
-rw-r--r--drivers/usb/gadget/gadget_chips.h55
-rw-r--r--drivers/usb/gadget/goku_udc.c7
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c15
-rw-r--r--drivers/usb/gadget/net2280.c7
-rw-r--r--drivers/usb/gadget/omap_udc.c30
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c26
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h2
-rw-r--r--drivers/usb/gadget/serial.c67
-rw-r--r--drivers/usb/gadget/zero.c57
-rw-r--r--drivers/usb/host/Makefile5
-rw-r--r--drivers/usb/host/ehci-dbg.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c525
-rw-r--r--drivers/usb/host/ehci-hub.c35
-rw-r--r--drivers/usb/host/ehci-mem.c6
-rw-r--r--drivers/usb/host/ehci-pci.c415
-rw-r--r--drivers/usb/host/ehci-q.c18
-rw-r--r--drivers/usb/host/ehci-sched.c33
-rw-r--r--drivers/usb/host/ehci.h9
-rw-r--r--drivers/usb/host/hc_crisv10.c4
-rw-r--r--drivers/usb/host/isp116x-hcd.c155
-rw-r--r--drivers/usb/host/isp116x.h1
-rw-r--r--drivers/usb/host/ohci-au1xxx.c8
-rw-r--r--drivers/usb/host/ohci-dbg.c15
-rw-r--r--drivers/usb/host/ohci-hcd.c20
-rw-r--r--drivers/usb/host/ohci-hub.c74
-rw-r--r--drivers/usb/host/ohci-lh7a404.c10
-rw-r--r--drivers/usb/host/ohci-mem.c5
-rw-r--r--drivers/usb/host/ohci-omap.c60
-rw-r--r--drivers/usb/host/ohci-pci.c49
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c33
-rw-r--r--drivers/usb/host/ohci-pxa27x.c62
-rw-r--r--drivers/usb/host/ohci-s3c2410.c16
-rw-r--r--drivers/usb/host/ohci-sa1111.c7
-rw-r--r--drivers/usb/host/ohci.h2
-rw-r--r--drivers/usb/host/pci-quirks.c319
-rw-r--r--drivers/usb/host/sl811-hcd.c54
-rw-r--r--drivers/usb/host/sl811_cs.c1
-rw-r--r--drivers/usb/host/uhci-debug.c5
-rw-r--r--drivers/usb/host/uhci-hcd.c238
-rw-r--r--drivers/usb/host/uhci-hcd.h109
-rw-r--r--drivers/usb/host/uhci-hub.c11
-rw-r--r--drivers/usb/host/uhci-q.c66
-rw-r--r--drivers/usb/image/mdc800.c33
-rw-r--r--drivers/usb/image/microtek.c3
-rw-r--r--drivers/usb/input/Kconfig34
-rw-r--r--drivers/usb/input/Makefile2
-rw-r--r--drivers/usb/input/acecad.c78
-rw-r--r--drivers/usb/input/aiptek.c209
-rw-r--r--drivers/usb/input/appletouch.c475
-rw-r--r--drivers/usb/input/ati_remote.c173
-rw-r--r--drivers/usb/input/hid-core.c138
-rw-r--r--drivers/usb/input/hid-debug.h34
-rw-r--r--drivers/usb/input/hid-input.c122
-rw-r--r--drivers/usb/input/hid-lgff.c17
-rw-r--r--drivers/usb/input/hid-tmff.c11
-rw-r--r--drivers/usb/input/hid.h11
-rw-r--r--drivers/usb/input/hiddev.c4
-rw-r--r--drivers/usb/input/itmtouch.c70
-rw-r--r--drivers/usb/input/kbtab.c82
-rw-r--r--drivers/usb/input/keyspan_remote.c211
-rw-r--r--drivers/usb/input/map_to_7segment.h189
-rw-r--r--drivers/usb/input/mtouchusb.c111
-rw-r--r--drivers/usb/input/pid.c16
-rw-r--r--drivers/usb/input/powermate.c136
-rw-r--r--drivers/usb/input/touchkitusb.c118
-rw-r--r--drivers/usb/input/usbkbd.c105
-rw-r--r--drivers/usb/input/usbmouse.c93
-rw-r--r--drivers/usb/input/wacom.c163
-rw-r--r--drivers/usb/input/xpad.c95
-rw-r--r--drivers/usb/input/yealink.c1017
-rw-r--r--drivers/usb/input/yealink.h220
-rw-r--r--drivers/usb/media/dabusb.c3
-rw-r--r--drivers/usb/media/konicawc.c89
-rw-r--r--drivers/usb/media/stv680.c26
-rw-r--r--drivers/usb/media/vicam.c4
-rw-r--r--drivers/usb/media/w9968cf.c12
-rw-r--r--drivers/usb/misc/auerswald.c6
-rw-r--r--drivers/usb/misc/idmouse.c21
-rw-r--r--drivers/usb/misc/ldusb.c6
-rw-r--r--drivers/usb/misc/legousbtower.c5
-rw-r--r--drivers/usb/misc/rio500.c3
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig42
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile4
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c464
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h73
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c1658
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c1047
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h830
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_struct.h169
-rw-r--r--drivers/usb/misc/usblcd.c9
-rw-r--r--drivers/usb/misc/usbtest.c22
-rw-r--r--drivers/usb/misc/uss720.c393
-rw-r--r--drivers/usb/mon/Kconfig9
-rw-r--r--drivers/usb/mon/Makefile3
-rw-r--r--drivers/usb/mon/mon_dma.c55
-rw-r--r--drivers/usb/mon/mon_main.c27
-rw-r--r--drivers/usb/mon/mon_text.c37
-rw-r--r--drivers/usb/mon/usb_mon.h6
-rw-r--r--drivers/usb/net/Kconfig210
-rw-r--r--drivers/usb/net/Makefile10
-rw-r--r--drivers/usb/net/asix.c948
-rw-r--r--drivers/usb/net/catc.c2
-rw-r--r--drivers/usb/net/cdc_ether.c509
-rw-r--r--drivers/usb/net/cdc_subset.c335
-rw-r--r--drivers/usb/net/gl620a.c407
-rw-r--r--drivers/usb/net/kaweth.c9
-rw-r--r--drivers/usb/net/net1080.c622
-rw-r--r--drivers/usb/net/pegasus.c32
-rw-r--r--drivers/usb/net/pegasus.h2
-rw-r--r--drivers/usb/net/plusb.c156
-rw-r--r--drivers/usb/net/rndis_host.c615
-rw-r--r--drivers/usb/net/rtl8150.c2
-rw-r--r--drivers/usb/net/usbnet.c3249
-rw-r--r--drivers/usb/net/usbnet.h193
-rw-r--r--drivers/usb/net/zaurus.c386
-rw-r--r--drivers/usb/net/zd1201.c22
-rw-r--r--drivers/usb/serial/ChangeLog.old730
-rw-r--r--drivers/usb/serial/Kconfig9
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/airprime.c11
-rw-r--r--drivers/usb/serial/belkin_sa.c10
-rw-r--r--drivers/usb/serial/bus.c37
-rw-r--r--drivers/usb/serial/cp2101.c15
-rw-r--r--drivers/usb/serial/cyberjack.c10
-rw-r--r--drivers/usb/serial/cypress_m8.c274
-rw-r--r--drivers/usb/serial/digi_acceleport.c20
-rw-r--r--drivers/usb/serial/empeg.c8
-rw-r--r--drivers/usb/serial/ftdi_sio.c80
-rw-r--r--drivers/usb/serial/ftdi_sio.h70
-rw-r--r--drivers/usb/serial/garmin_gps.c15
-rw-r--r--drivers/usb/serial/generic.c11
-rw-r--r--drivers/usb/serial/hp4x.c10
-rw-r--r--drivers/usb/serial/io_edgeport.c219
-rw-r--r--drivers/usb/serial/io_tables.h30
-rw-r--r--drivers/usb/serial/io_ti.c20
-rw-r--r--drivers/usb/serial/ipaq.c247
-rw-r--r--drivers/usb/serial/ipw.c10
-rw-r--r--drivers/usb/serial/ir-usb.c9
-rw-r--r--drivers/usb/serial/keyspan.c8
-rw-r--r--drivers/usb/serial/keyspan.h40
-rw-r--r--drivers/usb/serial/keyspan_pda.c30
-rw-r--r--drivers/usb/serial/kl5kusb105.c10
-rw-r--r--drivers/usb/serial/kobil_sct.c9
-rw-r--r--drivers/usb/serial/mct_u232.c10
-rw-r--r--drivers/usb/serial/nokia_dku2.c142
-rw-r--r--drivers/usb/serial/omninet.c10
-rw-r--r--drivers/usb/serial/option.c224
-rw-r--r--drivers/usb/serial/pl2303.c45
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/serial/safe_serial.c10
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c18
-rw-r--r--drivers/usb/serial/usb-serial.c402
-rw-r--r--drivers/usb/serial/usb-serial.h81
-rw-r--r--drivers/usb/serial/visor.c170
-rw-r--r--drivers/usb/serial/whiteheat.c42
-rw-r--r--drivers/usb/storage/Kconfig15
-rw-r--r--drivers/usb/storage/Makefile1
-rw-r--r--drivers/usb/storage/onetouch.c211
-rw-r--r--drivers/usb/storage/onetouch.h9
-rw-r--r--drivers/usb/storage/scsiglue.c28
-rw-r--r--drivers/usb/storage/shuttle_usbat.c391
-rw-r--r--drivers/usb/storage/shuttle_usbat.h66
-rw-r--r--drivers/usb/storage/transport.c23
-rw-r--r--drivers/usb/storage/transport.h2
-rw-r--r--drivers/usb/storage/unusual_devs.h98
-rw-r--r--drivers/usb/storage/usb.c253
-rw-r--r--drivers/usb/storage/usb.h6
-rw-r--r--drivers/usb/usb-skeleton.c3
-rw-r--r--drivers/video/Kconfig95
-rw-r--r--drivers/video/Makefile9
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amba-clcd.c5
-rw-r--r--drivers/video/arcfb.c1
-rw-r--r--drivers/video/aty/aty128fb.c18
-rw-r--r--drivers/video/aty/atyfb_base.c25
-rw-r--r--drivers/video/aty/radeon_base.c36
-rw-r--r--drivers/video/aty/radeon_i2c.c2
-rw-r--r--drivers/video/aty/radeon_pm.c26
-rw-r--r--drivers/video/aty/radeonfb.h2
-rw-r--r--drivers/video/aty/xlinit.c11
-rw-r--r--drivers/video/au1100fb.c971
-rw-r--r--drivers/video/au1100fb.h614
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/corgi_bl.c45
-rw-r--r--drivers/video/backlight/locomolcd.c157
-rw-r--r--drivers/video/chipsfb.c4
-rw-r--r--drivers/video/cirrusfb.c24
-rw-r--r--drivers/video/console/Kconfig12
-rw-r--r--drivers/video/console/Makefile4
-rw-r--r--drivers/video/console/bitblit.c148
-rw-r--r--drivers/video/console/fbcon.c203
-rw-r--r--drivers/video/console/fbcon.h5
-rw-r--r--drivers/video/console/font_10x18.c4
-rw-r--r--drivers/video/console/font_6x11.c4
-rw-r--r--drivers/video/console/font_7x14.c4
-rw-r--r--drivers/video/console/font_8x16.c4
-rw-r--r--drivers/video/console/font_8x8.c4
-rw-r--r--drivers/video/console/font_acorn_8x8.c4
-rw-r--r--drivers/video/console/font_mini_4x6.c4
-rw-r--r--drivers/video/console/font_pearl_8x8.c4
-rw-r--r--drivers/video/console/font_sun12x22.c4
-rw-r--r--drivers/video/console/font_sun8x16.c4
-rw-r--r--drivers/video/console/fonts.c9
-rw-r--r--drivers/video/console/newport_con.c1
-rw-r--r--drivers/video/console/sticore.c126
-rw-r--r--drivers/video/console/vgacon.c80
-rw-r--r--drivers/video/cyblafb.c1457
-rw-r--r--drivers/video/dnfb.c2
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fbcvt.c380
-rw-r--r--drivers/video/fbmem.c77
-rw-r--r--drivers/video/fbmon.c39
-rw-r--r--drivers/video/fbsysfs.c8
-rw-r--r--drivers/video/gbefb.c22
-rw-r--r--drivers/video/geode/Kconfig10
-rw-r--r--drivers/video/geode/display_gx1.c2
-rw-r--r--drivers/video/geode/geodefb.h1
-rw-r--r--drivers/video/geode/gx1fb_core.c182
-rw-r--r--drivers/video/geode/video_cs5530.c4
-rw-r--r--drivers/video/i810/Makefile5
-rw-r--r--drivers/video/i810/i810-i2c.c257
-rw-r--r--drivers/video/i810/i810.h14
-rw-r--r--drivers/video/i810/i810_main.c229
-rw-r--r--drivers/video/i810/i810_main.h16
-rw-r--r--drivers/video/imxfb.c13
-rw-r--r--drivers/video/intelfb/intelfb.h1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c58
-rw-r--r--drivers/video/intelfb/intelfbhw.c4
-rw-r--r--drivers/video/logo/.gitignore7
-rw-r--r--drivers/video/matrox/matroxfb_base.c13
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/matrox/matroxfb_misc.c30
-rw-r--r--drivers/video/modedb.c67
-rw-r--r--drivers/video/nvidia/nv_i2c.c22
-rw-r--r--drivers/video/nvidia/nv_local.h4
-rw-r--r--drivers/video/nvidia/nv_of.c3
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c6
-rw-r--r--drivers/video/nvidia/nvidia.c30
-rw-r--r--drivers/video/offb.c2
-rw-r--r--drivers/video/p9100.c4
-rw-r--r--drivers/video/pm3fb.c3
-rw-r--r--drivers/video/pmag-aa-fb.c2
-rw-r--r--drivers/video/pmag-ba-fb.c285
-rw-r--r--drivers/video/pmagb-b-fb.c417
-rw-r--r--drivers/video/pxafb.c160
-rw-r--r--drivers/video/pxafb.h11
-rw-r--r--drivers/video/q40fb.c2
-rw-r--r--drivers/video/radeonfb.c2
-rw-r--r--drivers/video/riva/fbdev.c4
-rw-r--r--drivers/video/riva/rivafb-i2c.c3
-rw-r--r--drivers/video/s1d13xxxfb.c9
-rw-r--r--drivers/video/s3c2410fb.c911
-rw-r--r--drivers/video/s3c2410fb.h56
-rw-r--r--drivers/video/sa1100fb.c16
-rw-r--r--drivers/video/savage/savagefb-i2c.c22
-rw-r--r--drivers/video/savage/savagefb.h11
-rw-r--r--drivers/video/savage/savagefb_driver.c148
-rw-r--r--drivers/video/sgivwfb.c2
-rw-r--r--drivers/video/sis/300vtbl.h1363
-rw-r--r--drivers/video/sis/310vtbl.h2125
-rw-r--r--drivers/video/sis/Makefile2
-rw-r--r--drivers/video/sis/init.c5603
-rw-r--r--drivers/video/sis/init.h1732
-rw-r--r--drivers/video/sis/init301.c9630
-rw-r--r--drivers/video/sis/init301.h351
-rw-r--r--drivers/video/sis/initdef.h145
-rw-r--r--drivers/video/sis/initextlfb.c238
-rw-r--r--drivers/video/sis/oem300.h335
-rw-r--r--drivers/video/sis/oem310.h421
-rw-r--r--drivers/video/sis/osdef.h27
-rw-r--r--drivers/video/sis/sis.h746
-rw-r--r--drivers/video/sis/sis_accel.c479
-rw-r--r--drivers/video/sis/sis_accel.h9
-rw-r--r--drivers/video/sis/sis_main.c7525
-rw-r--r--drivers/video/sis/sis_main.h602
-rw-r--r--drivers/video/sis/vgatypes.h155
-rw-r--r--drivers/video/sis/vstruct.h1097
-rw-r--r--drivers/video/tridentfb.c5
-rw-r--r--drivers/video/vesafb.c40
-rw-r--r--drivers/video/vfb.c2
-rw-r--r--drivers/video/vgastate.c15
-rw-r--r--drivers/video/w100fb.c1930
-rw-r--r--drivers/video/w100fb.h777
-rw-r--r--drivers/w1/Kconfig16
-rw-r--r--drivers/w1/Makefile7
-rw-r--r--drivers/w1/ds_w1_bridge.c24
-rw-r--r--drivers/w1/dscore.c161
-rw-r--r--drivers/w1/dscore.h10
-rw-r--r--drivers/w1/w1.c303
-rw-r--r--drivers/w1/w1.h22
-rw-r--r--drivers/w1/w1_ds2433.c331
-rw-r--r--drivers/w1/w1_family.c12
-rw-r--r--drivers/w1/w1_family.h7
-rw-r--r--drivers/w1/w1_int.c30
-rw-r--r--drivers/w1/w1_io.c24
-rw-r--r--drivers/w1/w1_io.h1
-rw-r--r--drivers/w1/w1_netlink.c28
-rw-r--r--drivers/w1/w1_netlink.h2
-rw-r--r--drivers/w1/w1_smem.c49
-rw-r--r--drivers/w1/w1_therm.c47
-rw-r--r--drivers/zorro/zorro-sysfs.c1
-rw-r--r--drivers/zorro/zorro.c2
2183 files changed, 260632 insertions, 150450 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index cecab0acc3fe..48f446d3c671 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -4,6 +4,8 @@ menu "Device Drivers"
source "drivers/base/Kconfig"
+source "drivers/connector/Kconfig"
+
source "drivers/mtd/Kconfig"
source "drivers/parport/Kconfig"
@@ -48,6 +50,8 @@ source "drivers/hwmon/Kconfig"
source "drivers/misc/Kconfig"
+source "drivers/mfd/Kconfig"
+
source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 126a851d5653..65670be6ff1a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,10 +5,10 @@
# Rewritten to use lists instead of if-statements.
#
-obj-$(CONFIG_PCI) += pci/
+obj-$(CONFIG_PCI) += pci/ usb/
obj-$(CONFIG_PARISC) += parisc/
obj-y += video/
-obj-$(CONFIG_ACPI_BOOT) += acpi/
+obj-$(CONFIG_ACPI) += acpi/
# PnP must come after ACPI since it will eventually need to check if acpi
# was used and do nothing if so
obj-$(CONFIG_PNP) += pnp/
@@ -17,6 +17,8 @@ obj-$(CONFIG_PNP) += pnp/
# default.
obj-y += char/
+obj-$(CONFIG_CONNECTOR) += connector/
+
# i810fb and intelfb depend on char/agp/
obj-$(CONFIG_FB_I810) += video/i810/
obj-$(CONFIG_FB_INTEL) += video/intelfb/
@@ -26,7 +28,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/
obj-$(CONFIG_SERIO) += input/serio/
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
-obj-y += base/ block/ misc/ net/ media/
+obj-y += base/ block/ misc/ mfd/ net/ media/
obj-$(CONFIG_NUBUS) += nubus/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_PPC_PMAC) += macintosh/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 3cd2e968e96c..048542341204 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -376,19 +376,15 @@ static void do_fd_request(request_queue_t *);
/************************* End of Prototypes **************************/
-static struct timer_list motor_off_timer =
- TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
#ifdef TRACKBUFFER
-static struct timer_list readtrack_timer =
- TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
#endif
-static struct timer_list timeout_timer =
- TIMER_INITIALIZER(fd_times_out, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
-static struct timer_list fd_timer =
- TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
/* DAG: Haven't got a clue what this is? */
int stdma_islocked(void)
@@ -1283,8 +1279,7 @@ static void do_fd_request(request_queue_t* q)
if (fdc_busy) return;
save_flags(flags);
cli();
- while (fdc_busy)
- sleep_on(&fdc_wait);
+ wait_event(fdc_wait, !fdc_busy);
fdc_busy = 1;
ENABLE_IRQ();
restore_flags(flags);
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index 141b4c237a50..e26f007a1417 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -9,6 +9,7 @@
*
* Driver for PCF8583 RTC & RAM chip
*/
+#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -23,15 +24,17 @@ static struct i2c_driver pcf8583_driver;
static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
+static unsigned short *forces[] = { NULL };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
+ .forces = forces,
};
-#define DAT(x) ((unsigned int)(x->dev.driver_data))
+#define set_ctrl(x, v) i2c_set_clientdata(x, (void *)(unsigned int)(v))
+#define get_ctrl(x) ((unsigned int)i2c_get_clientdata(x))
static int
pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
@@ -39,8 +42,17 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *c;
unsigned char buf[1], ad[1] = { 0 };
struct i2c_msg msgs[2] = {
- { addr, 0, 1, ad },
- { addr, I2C_M_RD, 1, buf }
+ {
+ .addr = addr,
+ .flags = 0,
+ .len = 1,
+ .buf = ad,
+ }, {
+ .addr = addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = buf,
+ }
};
c = kmalloc(sizeof(*c), GFP_KERNEL);
@@ -53,7 +65,7 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
c->driver = &pcf8583_driver;
if (i2c_transfer(c->adapter, msgs, 2) == 2)
- DAT(c) = buf[0];
+ set_ctrl(c, buf[0]);
return i2c_attach_client(c);
}
@@ -77,8 +89,17 @@ pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
{
unsigned char buf[8], addr[1] = { 1 };
struct i2c_msg msgs[2] = {
- { client->addr, 0, 1, addr },
- { client->addr, I2C_M_RD, 6, buf }
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 6,
+ .buf = buf,
+ }
};
int ret = -EIO;
@@ -112,7 +133,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
int ret, len = 6;
buf[0] = 0;
- buf[1] = DAT(client) | 0x80;
+ buf[1] = get_ctrl(client) | 0x80;
buf[2] = BIN_TO_BCD(dt->cs);
buf[3] = BIN_TO_BCD(dt->secs);
buf[4] = BIN_TO_BCD(dt->mins);
@@ -128,7 +149,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
if (ret == len)
ret = 0;
- buf[1] = DAT(client);
+ buf[1] = get_ctrl(client);
i2c_master_send(client, (char *)buf, 2);
return ret;
@@ -137,7 +158,7 @@ pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
static int
pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
{
- *ctrl = DAT(client);
+ *ctrl = get_ctrl(client);
return 0;
}
@@ -148,7 +169,7 @@ pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
buf[0] = 0;
buf[1] = *ctrl;
- DAT(client) = *ctrl;
+ set_ctrl(client, *ctrl);
return i2c_master_send(client, (char *)buf, 2);
}
@@ -158,15 +179,23 @@ pcf8583_read_mem(struct i2c_client *client, struct mem *mem)
{
unsigned char addr[1];
struct i2c_msg msgs[2] = {
- { client->addr, 0, 1, addr },
- { client->addr, I2C_M_RD, 0, mem->data }
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = mem->nr,
+ .buf = mem->data,
+ }
};
if (mem->loc < 8)
return -EINVAL;
addr[0] = mem->loc;
- msgs[1].len = mem->nr;
return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
}
@@ -176,15 +205,23 @@ pcf8583_write_mem(struct i2c_client *client, struct mem *mem)
{
unsigned char addr[1];
struct i2c_msg msgs[2] = {
- { client->addr, 0, 1, addr },
- { client->addr, 0, 0, mem->data }
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_NOSTART,
+ .len = mem->nr,
+ .buf = mem->data,
+ }
};
if (mem->loc < 8)
return -EINVAL;
addr[0] = mem->loc;
- msgs[1].len = mem->nr;
return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
}
@@ -233,4 +270,14 @@ static __init int pcf8583_init(void)
return i2c_add_driver(&pcf8583_driver);
}
-__initcall(pcf8583_init);
+static __exit void pcf8583_exit(void)
+{
+ i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ba13896cae40..fe1e8126fbae 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -3,7 +3,6 @@
#
menu "ACPI (Advanced Configuration and Power Interface) Support"
- depends on PM
depends on !X86_VISWS
depends on !IA64_HP_SIM
depends on IA64 || X86
@@ -11,6 +10,8 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
config ACPI
bool "ACPI Support"
depends on IA64 || X86
+ select PM
+ select PCI
default y
---help---
@@ -43,20 +44,10 @@ config ACPI
if ACPI
-config ACPI_BOOT
- bool
- default y
-
-config ACPI_INTERPRETER
- bool
- default y
-
-if ACPI_INTERPRETER
-
config ACPI_SLEEP
- bool "Sleep States (EXPERIMENTAL)"
+ bool "Sleep States"
depends on X86 && (!SMP || SUSPEND_SMP)
- depends on EXPERIMENTAL && PM
+ depends on PM
default y
---help---
This option adds support for ACPI suspend states.
@@ -90,16 +81,16 @@ config ACPI_SLEEP_PROC_SLEEP
config ACPI_AC
tristate "AC Adapter"
depends on X86
- default m
+ default y
help
This driver adds support for the AC Adapter object, which indicates
- whether a system is on AC, or not. Typically, only mobile systems
- have this object, since desktops are always on AC.
+ whether a system is on AC, or not. If you have a system that can
+ switch between A/C and battery, say Y.
config ACPI_BATTERY
tristate "Battery"
depends on X86
- default m
+ default y
help
This driver adds support for battery information through
/proc/acpi/battery. If you have a mobile system with a battery,
@@ -107,18 +98,17 @@ config ACPI_BATTERY
config ACPI_BUTTON
tristate "Button"
- default m
+ default y
help
- This driver registers for events based on buttons, such as the
- power, sleep, and lid switch. In the future, a daemon will read
- /proc/acpi/event and perform user-defined actions such as shutting
- down the system. Until then, you can cat it, and see output when
- a button is pressed.
+ This driver handles events on the power, sleep and lid buttons.
+ A daemon reads /proc/acpi/event and perform user-defined actions
+ such as shutting down the system. This is necessary for
+ software controlled poweroff.
config ACPI_VIDEO
tristate "Video"
- depends on EXPERIMENTAL
- default m
+ depends on X86
+ default y
help
This driver implement the ACPI Extensions For Display Adapters
for integrated graphics devices on motherboard, as specified in
@@ -129,10 +119,9 @@ config ACPI_VIDEO
for your integrated video device.
config ACPI_HOTKEY
- tristate "Generic Hotkey"
- depends on ACPI_INTERPRETER
+ tristate "Generic Hotkey (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on !IA64_SGI_SN
+ depends on X86
default n
help
Experimental consolidated hotkey driver.
@@ -140,31 +129,30 @@ config ACPI_HOTKEY
config ACPI_FAN
tristate "Fan"
- default m
+ default y
help
This driver adds support for ACPI fan devices, allowing user-mode
applications to perform basic fan control (on, off, status).
config ACPI_PROCESSOR
tristate "Processor"
- default m
+ default y
help
This driver installs ACPI as the idle handler for Linux, and uses
ACPI C2 and C3 processor states to save power, on systems that
- support it.
+ support it. It is required by several flavors of cpufreq
+ Performance-state drivers.
config ACPI_HOTPLUG_CPU
- bool "Processor Hotplug (EXPERIMENTAL)"
- depends on ACPI_PROCESSOR && HOTPLUG_CPU && EXPERIMENTAL
+ bool
+ depends on ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_CONTAINER
- default n
- ---help---
- Select this option if your platform support physical CPU hotplug.
+ default y
config ACPI_THERMAL
tristate "Thermal Zone"
depends on ACPI_PROCESSOR
- default m
+ default y
help
This driver adds support for ACPI thermal zones. Most mobile and
some desktop systems support ACPI thermal zones. It is HIGHLY
@@ -180,7 +168,7 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
- default m
+ default y
---help---
This driver provides support for extra features of ACPI-compatible
ASUS laptops. As some of Medion laptops are made by ASUS, it may also
@@ -209,7 +197,7 @@ config ACPI_ASUS
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
- default m
+ default y
---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
@@ -222,7 +210,7 @@ config ACPI_IBM
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
- default m
+ default y
---help---
This driver adds support for access to certain system settings
on "legacy free" Toshiba laptops. These laptops can be recognized by
@@ -262,8 +250,7 @@ config ACPI_CUSTOM_DSDT_FILE
Enter the full path name to the file wich includes the AmlCode declaration.
config ACPI_BLACKLIST_YEAR
- int "Disable ACPI for systems before Jan 1st this year"
- depends on ACPI_INTERPRETER
+ int "Disable ACPI for systems before Jan 1st this year" if X86
default 0
help
enter a 4-digit year, eg. 2001 to disable ACPI by default
@@ -281,10 +268,6 @@ config ACPI_DEBUG
of verbosity. Saying Y enables these statements. This will increase
your kernel size by around 50K.
-config ACPI_BUS
- bool
- default y
-
config ACPI_EC
bool
depends on X86
@@ -298,10 +281,6 @@ config ACPI_POWER
bool
default y
-config ACPI_PCI
- bool
- default PCI
-
config ACPI_SYSTEM
bool
default y
@@ -309,14 +288,11 @@ config ACPI_SYSTEM
This driver will enable your system to shut down using ACPI, and
dump your ACPI DSDT table using /proc/acpi/dsdt.
-endif # ACPI_INTERPRETER
-
config X86_PM_TIMER
bool "Power Management Timer Support"
depends on X86
- depends on ACPI_BOOT && EXPERIMENTAL
depends on !X86_64
- default n
+ default y
help
The Power Management Timer is available on all ACPI-capable,
in most cases even if ACPI is unusable or blacklisted.
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index ad67e8f61e6c..a18243488c66 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -15,13 +15,13 @@ EXTRA_CFLAGS += $(ACPI_CFLAGS)
#
# ACPI Boot-Time Table Parsing
#
-obj-$(CONFIG_ACPI_BOOT) += tables.o
-obj-$(CONFIG_ACPI_INTERPRETER) += blacklist.o
+obj-y += tables.o
+obj-y += blacklist.o
#
# ACPI Core Subsystem (Interpreter)
#
-obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \
+obj-y += osl.o utils.o \
dispatcher/ events/ executer/ hardware/ \
namespace/ parser/ resources/ tables/ \
utilities/
@@ -35,8 +35,8 @@ ifdef CONFIG_CPU_FREQ
processor-objs += processor_perflib.o
endif
-obj-$(CONFIG_ACPI_BUS) += sleep/
-obj-$(CONFIG_ACPI_BUS) += bus.o glue.o
+obj-y += sleep/
+obj-y += bus.o glue.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
@@ -44,7 +44,7 @@ obj-$(CONFIG_ACPI_EC) += ec.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o
-obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o
+obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
@@ -55,5 +55,5 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
-obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o
+obj-y += scan.o motherboard.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 23ab761dd721..7839b831df94 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -32,7 +32,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_AC_COMPONENT 0x00020000
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_HID "ACPI0003"
@@ -45,47 +44,45 @@
#define ACPI_AC_STATUS_UNKNOWN 0xFF
#define _COMPONENT ACPI_AC_COMPONENT
-ACPI_MODULE_NAME ("acpi_ac")
+ACPI_MODULE_NAME("acpi_ac")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_ac_add (struct acpi_device *device);
-static int acpi_ac_remove (struct acpi_device *device, int type);
+static int acpi_ac_add(struct acpi_device *device);
+static int acpi_ac_remove(struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_ac_driver = {
- .name = ACPI_AC_DRIVER_NAME,
- .class = ACPI_AC_CLASS,
- .ids = ACPI_AC_HID,
- .ops = {
- .add = acpi_ac_add,
- .remove = acpi_ac_remove,
- },
+ .name = ACPI_AC_DRIVER_NAME,
+ .class = ACPI_AC_CLASS,
+ .ids = ACPI_AC_HID,
+ .ops = {
+ .add = acpi_ac_add,
+ .remove = acpi_ac_remove,
+ },
};
struct acpi_ac {
- acpi_handle handle;
- unsigned long state;
+ acpi_handle handle;
+ unsigned long state;
};
static struct file_operations acpi_ac_fops = {
- .open = acpi_ac_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_ac_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
AC Adapter Management
-------------------------------------------------------------------------- */
-static int
-acpi_ac_get_state (
- struct acpi_ac *ac)
+static int acpi_ac_get_state(struct acpi_ac *ac)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_ac_get_state");
@@ -95,24 +92,23 @@ acpi_ac_get_state (
status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading AC Adapter state\n"));
+ "Error reading AC Adapter state\n"));
ac->state = ACPI_AC_STATUS_UNKNOWN;
return_VALUE(-ENODEV);
}
-
+
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_ac_dir;
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_ac *ac = (struct acpi_ac *) seq->private;
+ struct acpi_ac *ac = (struct acpi_ac *)seq->private;
ACPI_FUNCTION_TRACE("acpi_ac_seq_show");
@@ -139,23 +135,21 @@ static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
return_VALUE(0);
}
-
+
static int acpi_ac_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
}
-static int
-acpi_ac_add_fs (
- struct acpi_device *device)
+static int acpi_ac_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_ac_dir);
+ acpi_ac_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -163,11 +157,11 @@ acpi_ac_add_fs (
/* 'state' [R] */
entry = create_proc_entry(ACPI_AC_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_AC_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_AC_FILE_STATE));
else {
entry->proc_fops = &acpi_ac_fops;
entry->data = acpi_driver_data(device);
@@ -177,16 +171,12 @@ acpi_ac_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_ac_remove_fs (
- struct acpi_device *device)
+static int acpi_ac_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_AC_FILE_STATE,
- acpi_device_dir(device));
+ remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
acpi_device_dir(device) = NULL;
@@ -195,19 +185,14 @@ acpi_ac_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Model
-------------------------------------------------------------------------- */
-static void
-acpi_ac_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_ac *ac = (struct acpi_ac *) data;
- struct acpi_device *device = NULL;
+ struct acpi_ac *ac = (struct acpi_ac *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_notify");
@@ -224,21 +209,18 @@ acpi_ac_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_ac_add (
- struct acpi_device *device)
+static int acpi_ac_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_ac *ac = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add");
@@ -264,19 +246,20 @@ acpi_ac_add (
goto end;
status = acpi_install_notify_handler(ac->handle,
- ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac);
+ ACPI_DEVICE_NOTIFY, acpi_ac_notify,
+ ac);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
- printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
- acpi_device_name(device), acpi_device_bid(device),
- ac->state?"on-line":"off-line");
+ printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ ac->state ? "on-line" : "off-line");
-end:
+ end:
if (result) {
acpi_ac_remove_fs(device);
kfree(ac);
@@ -285,27 +268,23 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_ac_remove (
- struct acpi_device *device,
- int type)
+static int acpi_ac_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_ac *ac = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- ac = (struct acpi_ac *) acpi_driver_data(device);
+ ac = (struct acpi_ac *)acpi_driver_data(device);
status = acpi_remove_notify_handler(ac->handle,
- ACPI_DEVICE_NOTIFY, acpi_ac_notify);
+ ACPI_DEVICE_NOTIFY, acpi_ac_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_ac_remove_fs(device);
@@ -314,11 +293,9 @@ acpi_ac_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_ac_init (void)
+static int __init acpi_ac_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ac_init");
@@ -336,9 +313,7 @@ acpi_ac_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_ac_exit (void)
+static void __exit acpi_ac_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_ac_exit");
@@ -349,6 +324,5 @@ acpi_ac_exit (void)
return_VOID;
}
-
module_init(acpi_ac_init);
module_exit(acpi_ac_exit);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 77285ffe41c5..2143609d2936 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -32,7 +32,6 @@
#include <linux/memory_hotplug.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
#define ACPI_MEMORY_DEVICE_CLASS "memory"
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
@@ -41,8 +40,8 @@
#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
-ACPI_MODULE_NAME ("acpi_memory")
-MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+ACPI_MODULE_NAME("acpi_memory")
+ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -56,34 +55,33 @@ MODULE_LICENSE("GPL");
#define MEMORY_POWER_ON_STATE 1
#define MEMORY_POWER_OFF_STATE 2
-static int acpi_memory_device_add (struct acpi_device *device);
-static int acpi_memory_device_remove (struct acpi_device *device, int type);
+static int acpi_memory_device_add(struct acpi_device *device);
+static int acpi_memory_device_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_memory_device_driver = {
- .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
- .class = ACPI_MEMORY_DEVICE_CLASS,
- .ids = ACPI_MEMORY_DEVICE_HID,
- .ops = {
- .add = acpi_memory_device_add,
- .remove = acpi_memory_device_remove,
- },
+ .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+ .class = ACPI_MEMORY_DEVICE_CLASS,
+ .ids = ACPI_MEMORY_DEVICE_HID,
+ .ops = {
+ .add = acpi_memory_device_add,
+ .remove = acpi_memory_device_remove,
+ },
};
struct acpi_memory_device {
acpi_handle handle;
- unsigned int state; /* State of the memory device */
+ unsigned int state; /* State of the memory device */
unsigned short cache_attribute; /* memory cache attribute */
- unsigned short read_write_attribute;/* memory read/write attribute */
- u64 start_addr; /* Memory Range start physical addr */
- u64 end_addr; /* Memory Range end physical addr */
+ unsigned short read_write_attribute; /* memory read/write attribute */
+ u64 start_addr; /* Memory Range start physical addr */
+ u64 end_addr; /* Memory Range end physical addr */
};
-
static int
acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
{
acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_resource *resource = NULL;
struct acpi_resource_address64 address64;
@@ -94,15 +92,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
if (ACPI_FAILURE(status))
return_VALUE(-EINVAL);
- resource = (struct acpi_resource *) buffer.pointer;
+ resource = (struct acpi_resource *)buffer.pointer;
status = acpi_resource_to_address64(resource, &address64);
if (ACPI_SUCCESS(status)) {
if (address64.resource_type == ACPI_MEMORY_RANGE) {
/* Populate the structure */
mem_device->cache_attribute =
- address64.attribute.memory.cache_attribute;
+ address64.attribute.memory.cache_attribute;
mem_device->read_write_attribute =
- address64.attribute.memory.read_write_attribute;
+ address64.attribute.memory.read_write_attribute;
mem_device->start_addr = address64.min_address_range;
mem_device->end_addr = address64.max_address_range;
}
@@ -114,7 +112,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
static int
acpi_memory_get_device(acpi_handle handle,
- struct acpi_memory_device **mem_device)
+ struct acpi_memory_device **mem_device)
{
acpi_status status;
acpi_handle phandle;
@@ -128,8 +126,7 @@ acpi_memory_get_device(acpi_handle handle,
status = acpi_get_parent(handle, &phandle);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_get_parent\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_get_parent\n"));
return_VALUE(-EINVAL);
}
@@ -137,7 +134,7 @@ acpi_memory_get_device(acpi_handle handle,
status = acpi_bus_get_device(phandle, &pdevice);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_bus_get_device\n"));
+ "Error in acpi_bus_get_device\n"));
return_VALUE(-EINVAL);
}
@@ -147,23 +144,21 @@ acpi_memory_get_device(acpi_handle handle,
*/
status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_bus_add\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_bus_add\n"));
return_VALUE(-EINVAL);
}
-end:
+ end:
*mem_device = acpi_driver_data(device);
if (!(*mem_device)) {
- printk(KERN_ERR "\n driver data not found" );
+ printk(KERN_ERR "\n driver data not found");
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
-static int
-acpi_memory_check_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
unsigned long current_status;
@@ -171,22 +166,21 @@ acpi_memory_check_device(struct acpi_memory_device *mem_device)
/* Get device present/absent information from the _STA */
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
- NULL, &current_status)))
+ NULL, &current_status)))
return_VALUE(-ENODEV);
/*
* Check for device status. Device should be
* present/enabled/functioning.
*/
if (!((current_status & ACPI_MEMORY_STA_PRESENT)
- && (current_status & ACPI_MEMORY_STA_ENABLED)
- && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
+ && (current_status & ACPI_MEMORY_STA_ENABLED)
+ && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
return_VALUE(-ENODEV);
return_VALUE(0);
}
-static int
-acpi_memory_enable_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
{
int result;
@@ -196,7 +190,7 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
result = acpi_memory_get_device_resources(mem_device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "\nget_device_resources failed\n"));
+ "\nget_device_resources failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
return result;
}
@@ -206,11 +200,9 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
* Note: Assume that this function returns zero on success
*/
result = add_memory(mem_device->start_addr,
- (mem_device->end_addr - mem_device->start_addr) + 1,
- mem_device->read_write_attribute);
+ (mem_device->end_addr - mem_device->start_addr) + 1);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "\nadd_memory failed\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
return result;
}
@@ -218,11 +210,10 @@ acpi_memory_enable_device(struct acpi_memory_device *mem_device)
return result;
}
-static int
-acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
{
acpi_status status;
- struct acpi_object_list arg_list;
+ struct acpi_object_list arg_list;
union acpi_object arg;
unsigned long current_status;
@@ -234,16 +225,16 @@ acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = 1;
status = acpi_evaluate_object(mem_device->handle,
- "_EJ0", &arg_list, NULL);
+ "_EJ0", &arg_list, NULL);
/* Return on _EJ0 failure */
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "_EJ0 failed.\n"));
return_VALUE(-ENODEV);
}
/* Evalute _STA to check if the device is disabled */
status = acpi_evaluate_integer(mem_device->handle, "_STA",
- NULL, &current_status);
+ NULL, &current_status);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -254,8 +245,7 @@ acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
return_VALUE(0);
}
-static int
-acpi_memory_disable_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
{
int result;
u64 start = mem_device->start_addr;
@@ -268,7 +258,7 @@ acpi_memory_disable_device(struct acpi_memory_device *mem_device)
* Ask the VM to offline this memory range.
* Note: Assume that this function returns zero on success
*/
- result = remove_memory(start, len, attr);
+ result = remove_memory(start, len);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
return_VALUE(result);
@@ -278,7 +268,7 @@ acpi_memory_disable_device(struct acpi_memory_device *mem_device)
result = acpi_memory_powerdown_device(mem_device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device Power Down failed.\n"));
+ "Device Power Down failed.\n"));
/* Set the status of the device to invalid */
mem_device->state = MEMORY_INVALID_STATE;
return result;
@@ -288,8 +278,7 @@ acpi_memory_disable_device(struct acpi_memory_device *mem_device)
return result;
}
-static void
-acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_memory_device *mem_device;
struct acpi_device *device;
@@ -299,37 +288,37 @@ acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived BUS CHECK notification for device\n"));
+ "\nReceived BUS CHECK notification for device\n"));
/* Fall Through */
case ACPI_NOTIFY_DEVICE_CHECK:
if (event == ACPI_NOTIFY_DEVICE_CHECK)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived DEVICE CHECK notification for device\n"));
+ "\nReceived DEVICE CHECK notification for device\n"));
if (acpi_memory_get_device(handle, &mem_device)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in finding driver data\n"));
+ "Error in finding driver data\n"));
return_VOID;
}
if (!acpi_memory_check_device(mem_device)) {
if (acpi_memory_enable_device(mem_device))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_enable_device\n"));
+ "Error in acpi_memory_enable_device\n"));
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "\nReceived EJECT REQUEST notification for device\n"));
+ "\nReceived EJECT REQUEST notification for device\n"));
if (acpi_bus_get_device(handle, &device)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device doesn't exist\n"));
+ "Device doesn't exist\n"));
break;
}
mem_device = acpi_driver_data(device);
if (!mem_device) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Driver Data is NULL\n"));
+ "Driver Data is NULL\n"));
break;
}
@@ -337,26 +326,25 @@ acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
* Currently disabling memory device from kernel mode
* TBD: Can also be disabled from user mode scripts
* TBD: Can also be disabled by Callback registration
- * with generic sysfs driver
+ * with generic sysfs driver
*/
if (acpi_memory_disable_device(mem_device))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error in acpi_memory_disable_device\n"));
+ "Error in acpi_memory_disable_device\n"));
/*
* TBD: Invoke acpi_bus_remove to cleanup data structures
*/
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static int
-acpi_memory_device_add(struct acpi_device *device)
+static int acpi_memory_device_add(struct acpi_device *device)
{
int result;
struct acpi_memory_device *mem_device = NULL;
@@ -391,8 +379,7 @@ acpi_memory_device_add(struct acpi_device *device)
return_VALUE(result);
}
-static int
-acpi_memory_device_remove (struct acpi_device *device, int type)
+static int acpi_memory_device_remove(struct acpi_device *device, int type)
{
struct acpi_memory_device *mem_device = NULL;
@@ -401,7 +388,7 @@ acpi_memory_device_remove (struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- mem_device = (struct acpi_memory_device *) acpi_driver_data(device);
+ mem_device = (struct acpi_memory_device *)acpi_driver_data(device);
kfree(mem_device);
return_VALUE(0);
@@ -410,12 +397,11 @@ acpi_memory_device_remove (struct acpi_device *device, int type)
/*
* Helper function to check for memory device
*/
-static acpi_status
-is_memory_device(acpi_handle handle)
+static acpi_status is_memory_device(acpi_handle handle)
{
char *hardware_id;
acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info;
ACPI_FUNCTION_TRACE("is_memory_device");
@@ -432,7 +418,7 @@ is_memory_device(acpi_handle handle)
hardware_id = info->hardware_id.value;
if ((hardware_id == NULL) ||
- (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
+ (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
status = AE_ERROR;
acpi_os_free(buffer.pointer);
@@ -440,8 +426,8 @@ is_memory_device(acpi_handle handle)
}
static acpi_status
-acpi_memory_register_notify_handler (acpi_handle handle,
- u32 level, void *ctxt, void **retv)
+acpi_memory_register_notify_handler(acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
{
acpi_status status;
@@ -452,10 +438,10 @@ acpi_memory_register_notify_handler (acpi_handle handle,
return_ACPI_STATUS(AE_OK); /* continue */
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- acpi_memory_device_notify, NULL);
+ acpi_memory_device_notify, NULL);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
return_ACPI_STATUS(AE_OK); /* continue */
}
@@ -463,8 +449,8 @@ acpi_memory_register_notify_handler (acpi_handle handle,
}
static acpi_status
-acpi_memory_deregister_notify_handler (acpi_handle handle,
- u32 level, void *ctxt, void **retv)
+acpi_memory_deregister_notify_handler(acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
{
acpi_status status;
@@ -475,18 +461,18 @@ acpi_memory_deregister_notify_handler (acpi_handle handle,
return_ACPI_STATUS(AE_OK); /* continue */
status = acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_memory_device_notify);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
return_ACPI_STATUS(AE_OK); /* continue */
}
return_ACPI_STATUS(status);
}
-static int __init
-acpi_memory_device_init (void)
+static int __init acpi_memory_device_init(void)
{
int result;
acpi_status status;
@@ -499,21 +485,20 @@ acpi_memory_device_init (void)
return_VALUE(-ENODEV);
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_register_notify_handler,
- NULL, NULL);
+ ACPI_UINT32_MAX,
+ acpi_memory_register_notify_handler,
+ NULL, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed\n"));
acpi_bus_unregister_driver(&acpi_memory_device_driver);
return_VALUE(-ENODEV);
- }
+ }
return_VALUE(0);
}
-static void __exit
-acpi_memory_device_exit (void)
+static void __exit acpi_memory_device_exit(void)
{
acpi_status status;
@@ -524,12 +509,12 @@ acpi_memory_device_exit (void)
* handles.
*/
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_deregister_notify_handler,
- NULL, NULL);
+ ACPI_UINT32_MAX,
+ acpi_memory_deregister_notify_handler,
+ NULL, NULL);
- if (ACPI_FAILURE (status))
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed\n"));
acpi_bus_unregister_driver(&acpi_memory_device_driver);
@@ -538,5 +523,3 @@ acpi_memory_device_exit (void)
module_init(acpi_memory_device_init);
module_exit(acpi_memory_device_exit);
-
-
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index a560b1e2da77..fec895af6ae6 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -61,7 +61,7 @@
/*
* Some events we use, same for all Asus
*/
-#define BR_UP 0x10
+#define BR_UP 0x10
#define BR_DOWN 0x20
/*
@@ -75,7 +75,6 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
MODULE_LICENSE("GPL");
-
static uid_t asus_uid;
static gid_t asus_gid;
module_param(asus_uid, uint, 0);
@@ -83,26 +82,25 @@ MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
module_param(asus_gid, uint, 0);
MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n");
-
/* For each model, all features implemented,
* those marked with R are relative to HOTK, A for absolute */
struct model_data {
- char *name; //name of the laptop________________A
- char *mt_mled; //method to handle mled_____________R
- char *mled_status; //node to handle mled reading_______A
- char *mt_wled; //method to handle wled_____________R
- char *wled_status; //node to handle wled reading_______A
- char *mt_tled; //method to handle tled_____________R
- char *tled_status; //node to handle tled reading_______A
- char *mt_lcd_switch; //method to turn LCD ON/OFF_________A
- char *lcd_status; //node to read LCD panel state______A
- char *brightness_up; //method to set brightness up_______A
- char *brightness_down; //guess what ?______________________A
- char *brightness_set; //method to set absolute brightness_R
- char *brightness_get; //method to get absolute brightness_R
- char *brightness_status; //node to get brightness____________A
- char *display_set; //method to set video output________R
- char *display_get; //method to get video output________R
+ char *name; //name of the laptop________________A
+ char *mt_mled; //method to handle mled_____________R
+ char *mled_status; //node to handle mled reading_______A
+ char *mt_wled; //method to handle wled_____________R
+ char *wled_status; //node to handle wled reading_______A
+ char *mt_tled; //method to handle tled_____________R
+ char *tled_status; //node to handle tled reading_______A
+ char *mt_lcd_switch; //method to turn LCD ON/OFF_________A
+ char *lcd_status; //node to read LCD panel state______A
+ char *brightness_up; //method to set brightness up_______A
+ char *brightness_down; //guess what ?______________________A
+ char *brightness_set; //method to set absolute brightness_R
+ char *brightness_get; //method to get absolute brightness_R
+ char *brightness_status; //node to get brightness____________A
+ char *display_set; //method to set video output________R
+ char *display_get; //method to get video output________R
};
/*
@@ -110,34 +108,34 @@ struct model_data {
* about the hotk device
*/
struct asus_hotk {
- struct acpi_device *device; //the device we are in
- acpi_handle handle; //the handle of the hotk device
- char status; //status of the hotk, for LEDs, ...
- struct model_data *methods; //methods available on the laptop
- u8 brightness; //brightness level
+ struct acpi_device *device; //the device we are in
+ acpi_handle handle; //the handle of the hotk device
+ char status; //status of the hotk, for LEDs, ...
+ struct model_data *methods; //methods available on the laptop
+ u8 brightness; //brightness level
enum {
- A1x = 0, //A1340D, A1300F
- A2x, //A2500H
- D1x, //D1
- L2D, //L2000D
- L3C, //L3800C
- L3D, //L3400D
- L3H, //L3H, but also L2000E
- L4R, //L4500R
- L5x, //L5800C
- L8L, //L8400L
- M1A, //M1300A
- M2E, //M2400E, L4400L
- M6N, //M6800N
- M6R, //M6700R
- P30, //Samsung P30
- S1x, //S1300A, but also L1400B and M2400A (L84F)
- S2x, //S200 (J1 reported), Victor MP-XP7210
- xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
- //(Centrino)
+ A1x = 0, //A1340D, A1300F
+ A2x, //A2500H
+ D1x, //D1
+ L2D, //L2000D
+ L3C, //L3800C
+ L3D, //L3400D
+ L3H, //L3H, but also L2000E
+ L4R, //L4500R
+ L5x, //L5800C
+ L8L, //L8400L
+ M1A, //M1300A
+ M2E, //M2400E, L4400L
+ M6N, //M6800N
+ M6R, //M6700R
+ P30, //Samsung P30
+ S1x, //S1300A, but also L1400B and M2400A (L84F)
+ S2x, //S200 (J1 reported), Victor MP-XP7210
+ xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
+ //(Centrino)
END_MODEL
- } model; //Models currently supported
- u16 event_count[128]; //count for each event TODO make this better
+ } model; //Models currently supported
+ u16 event_count[128]; //count for each event TODO make this better
};
/* Here we go */
@@ -150,7 +148,7 @@ struct asus_hotk {
#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
static struct model_data model_conf[END_MODEL] = {
- /*
+ /*
* Those pathnames are relative to the HOTK / ATKD device :
* - mt_mled
* - mt_wled
@@ -165,215 +163,197 @@ static struct model_data model_conf[END_MODEL] = {
*/
{
- .name = "A1x",
- .mt_mled = "MLED",
- .mled_status = "\\MAIL",
- .mt_lcd_switch = A1x_PREFIX "_Q10",
- .lcd_status = "\\BKLI",
- .brightness_up = A1x_PREFIX "_Q0E",
- .brightness_down = A1x_PREFIX "_Q0F"
- },
+ .name = "A1x",
+ .mt_mled = "MLED",
+ .mled_status = "\\MAIL",
+ .mt_lcd_switch = A1x_PREFIX "_Q10",
+ .lcd_status = "\\BKLI",
+ .brightness_up = A1x_PREFIX "_Q0E",
+ .brightness_down = A1x_PREFIX "_Q0F"},
{
- .name = "A2x",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\SG66",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\BAOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "A2x",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\SG66",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\BAOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "D1x",
- .mt_mled = "MLED",
- .mt_lcd_switch = "\\Q0D",
- .lcd_status = "\\GP11",
- .brightness_up = "\\Q0C",
- .brightness_down = "\\Q0B",
- .brightness_status = "\\BLVL",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "D1x",
+ .mt_mled = "MLED",
+ .mt_lcd_switch = "\\Q0D",
+ .lcd_status = "\\GP11",
+ .brightness_up = "\\Q0C",
+ .brightness_down = "\\Q0B",
+ .brightness_status = "\\BLVL",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L2D",
- .mt_mled = "MLED",
- .mled_status = "\\SGP6",
- .mt_wled = "WLED",
- .wled_status = "\\RCP3",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\SGP0",
- .brightness_up = "\\Q0E",
- .brightness_down = "\\Q0F",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L2D",
+ .mt_mled = "MLED",
+ .mled_status = "\\SGP6",
+ .mt_wled = "WLED",
+ .wled_status = "\\RCP3",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\SGP0",
+ .brightness_up = "\\Q0E",
+ .brightness_down = "\\Q0F",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L3C",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = L3C_PREFIX "_Q10",
- .lcd_status = "\\GL32",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"
- },
+ .name = "L3C",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = L3C_PREFIX "_Q10",
+ .lcd_status = "\\GL32",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"},
{
- .name = "L3D",
- .mt_mled = "MLED",
- .mled_status = "\\MALD",
- .mt_wled = "WLED",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\BKLG",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L3D",
+ .mt_mled = "MLED",
+ .mled_status = "\\MALD",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\BKLG",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L3H",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = "EHK",
- .lcd_status = "\\_SB.PCI0.PM.PBC",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "L3H",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "EHK",
+ .lcd_status = "\\_SB.PCI0.PM.PBC",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L4R",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\_SB.PCI0.SBRG.SG13",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"
- },
+ .name = "L4R",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\_SB.PCI0.SBRG.SG13",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
{
- .name = "L5x",
- .mt_mled = "MLED",
+ .name = "L5x",
+ .mt_mled = "MLED",
/* WLED present, but not controlled by ACPI */
- .mt_tled = "TLED",
- .mt_lcd_switch = "\\Q0D",
- .lcd_status = "\\BAOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .mt_tled = "TLED",
+ .mt_lcd_switch = "\\Q0D",
+ .lcd_status = "\\BAOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "L8L"
+ .name = "L8L"
/* No features, but at least support the hotkeys */
- },
+ },
{
- .name = "M1A",
- .mt_mled = "MLED",
- .mt_lcd_switch = M1A_PREFIX "Q10",
- .lcd_status = "\\PNOF",
- .brightness_up = M1A_PREFIX "Q0E",
- .brightness_down = M1A_PREFIX "Q0F",
- .brightness_status = "\\BRIT",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "M1A",
+ .mt_mled = "MLED",
+ .mt_lcd_switch = M1A_PREFIX "Q10",
+ .lcd_status = "\\PNOF",
+ .brightness_up = M1A_PREFIX "Q0E",
+ .brightness_down = M1A_PREFIX "Q0F",
+ .brightness_status = "\\BRIT",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "M2E",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = "\\Q10",
- .lcd_status = "\\GP06",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\INFB"
- },
+ .name = "M2E",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = "\\Q10",
+ .lcd_status = "\\GP06",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\INFB"},
{
- .name = "M6N",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .wled_status = "\\_SB.PCI0.SBRG.SG13",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.BKLT",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\SSTE"
- },
+ .name = "M6N",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .wled_status = "\\_SB.PCI0.SBRG.SG13",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.BKLT",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\SSTE"},
{
- .name = "M6R",
- .mt_mled = "MLED",
- .mt_wled = "WLED",
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\SSTE"
- },
-
+ .name = "M6R",
+ .mt_mled = "MLED",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\SSTE"},
{
- .name = "P30",
- .mt_wled = "WLED",
- .mt_lcd_switch = P30_PREFIX "_Q0E",
- .lcd_status = "\\BKLT",
- .brightness_up = P30_PREFIX "_Q68",
- .brightness_down = P30_PREFIX "_Q69",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\DNXT"
- },
+ .name = "P30",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = P30_PREFIX "_Q0E",
+ .lcd_status = "\\BKLT",
+ .brightness_up = P30_PREFIX "_Q68",
+ .brightness_down = P30_PREFIX "_Q69",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\DNXT"},
{
- .name = "S1x",
- .mt_mled = "MLED",
- .mled_status = "\\EMLE",
- .mt_wled = "WLED",
- .mt_lcd_switch = S1x_PREFIX "Q10" ,
- .lcd_status = "\\PNOF",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV"
- },
+ .name = "S1x",
+ .mt_mled = "MLED",
+ .mled_status = "\\EMLE",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = S1x_PREFIX "Q10",
+ .lcd_status = "\\PNOF",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV"},
{
- .name = "S2x",
- .mt_mled = "MLED",
- .mled_status = "\\MAIL",
- .mt_lcd_switch = S2x_PREFIX "_Q10",
- .lcd_status = "\\BKLI",
- .brightness_up = S2x_PREFIX "_Q0B",
- .brightness_down = S2x_PREFIX "_Q0A"
- },
+ .name = "S2x",
+ .mt_mled = "MLED",
+ .mled_status = "\\MAIL",
+ .mt_lcd_switch = S2x_PREFIX "_Q10",
+ .lcd_status = "\\BKLI",
+ .brightness_up = S2x_PREFIX "_Q0B",
+ .brightness_down = S2x_PREFIX "_Q0A"},
{
- .name = "xxN",
- .mt_mled = "MLED",
+ .name = "xxN",
+ .mt_mled = "MLED",
/* WLED present, but not controlled by ACPI */
- .mt_lcd_switch = xxN_PREFIX "_Q10",
- .lcd_status = "\\BKLT",
- .brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .display_set = "SDSP",
- .display_get = "\\ADVG"
- }
+ .mt_lcd_switch = xxN_PREFIX "_Q10",
+ .lcd_status = "\\BKLT",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\ADVG"}
};
/* procdir we use */
@@ -395,13 +375,13 @@ static struct asus_hotk *hotk;
static int asus_hotk_add(struct acpi_device *device);
static int asus_hotk_remove(struct acpi_device *device, int type);
static struct acpi_driver asus_hotk_driver = {
- .name = ACPI_HOTK_NAME,
- .class = ACPI_HOTK_CLASS,
- .ids = ACPI_HOTK_HID,
- .ops = {
- .add = asus_hotk_add,
- .remove = asus_hotk_remove,
- },
+ .name = ACPI_HOTK_NAME,
+ .class = ACPI_HOTK_CLASS,
+ .ids = ACPI_HOTK_HID,
+ .ops = {
+ .add = asus_hotk_add,
+ .remove = asus_hotk_remove,
+ },
};
/*
@@ -423,11 +403,10 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = val;
- status = acpi_evaluate_object(handle, (char *) method, &params, output);
+ status = acpi_evaluate_object(handle, (char *)method, &params, output);
return (status == AE_OK);
}
-
static int read_acpi_int(acpi_handle handle, const char *method, int *val)
{
struct acpi_buffer output;
@@ -437,7 +416,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
output.length = sizeof(out_obj);
output.pointer = &out_obj;
- status = acpi_evaluate_object(handle, (char *) method, NULL, &output);
+ status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
*val = out_obj.integer.value;
return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
}
@@ -449,7 +428,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
*/
static int
proc_read_info(char *page, char **start, off_t off, int count, int *eof,
- void *data)
+ void *data)
{
int len = 0;
int temp;
@@ -460,7 +439,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
*/
len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
- len += sprintf(page + len, "Model reference : %s\n",
+ len += sprintf(page + len, "Model reference : %s\n",
hotk->methods->name);
/*
* The SFUN method probably allows the original driver to get the list
@@ -469,7 +448,8 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
* The significance of others is yet to be found.
*/
if (read_acpi_int(hotk->handle, "SFUN", &temp))
- len += sprintf(page + len, "SFUN value : 0x%04x\n", temp);
+ len +=
+ sprintf(page + len, "SFUN value : 0x%04x\n", temp);
/*
* Another value for userspace: the ASYM method returns 0x02 for
* battery low and 0x04 for battery critical, its readings tend to be
@@ -478,7 +458,8 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
* silently ignored.
*/
if (read_acpi_int(hotk->handle, "ASYM", &temp))
- len += sprintf(page + len, "ASYM value : 0x%04x\n", temp);
+ len +=
+ sprintf(page + len, "ASYM value : 0x%04x\n", temp);
if (asus_info) {
snprintf(buf, 16, "%d", asus_info->length);
len += sprintf(page + len, "DSDT length : %s\n", buf);
@@ -501,7 +482,6 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
return len;
}
-
/*
* /proc handlers
* We write our info in page, we begin at offset off and cannot write more
@@ -510,8 +490,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
*/
/* Generic LED functions */
-static int
-read_led(const char *ledname, int ledmask)
+static int read_led(const char *ledname, int ledmask)
{
if (ledname) {
int led_status;
@@ -525,7 +504,7 @@ read_led(const char *ledname, int ledmask)
return (hotk->status & ledmask) ? 1 : 0;
}
-static int parse_arg(const char __user *buf, unsigned long count, int *val)
+static int parse_arg(const char __user * buf, unsigned long count, int *val)
{
char s[32];
if (!count)
@@ -542,8 +521,8 @@ static int parse_arg(const char __user *buf, unsigned long count, int *val)
/* FIXME: kill extraneous args so it can be called independently */
static int
-write_led(const char __user *buffer, unsigned long count,
- char *ledname, int ledmask, int invert)
+write_led(const char __user * buffer, unsigned long count,
+ char *ledname, int ledmask, int invert)
{
int value;
int led_out = 0;
@@ -555,16 +534,16 @@ write_led(const char __user *buffer, unsigned long count,
hotk->status =
(led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
- if (invert) /* invert target value */
+ if (invert) /* invert target value */
led_out = !led_out & 0x1;
if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
- printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname);
+ printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+ ledname);
return count;
}
-
/*
* Proc handlers for MLED
*/
@@ -572,12 +551,12 @@ static int
proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->mled_status, MLED_ON));
}
-
static int
-proc_write_mled(struct file *file, const char __user *buffer,
+proc_write_mled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
@@ -590,11 +569,12 @@ static int
proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->wled_status, WLED_ON));
}
static int
-proc_write_wled(struct file *file, const char __user *buffer,
+proc_write_wled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
@@ -607,35 +587,36 @@ static int
proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
+ return sprintf(page, "%d\n",
+ read_led(hotk->methods->tled_status, TLED_ON));
}
static int
-proc_write_tled(struct file *file, const char __user *buffer,
+proc_write_tled(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
}
-
static int get_lcd_state(void)
{
int lcd = 0;
if (hotk->model != L3H) {
- /* We don't have to check anything if we are here */
+ /* We don't have to check anything if we are here */
if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
- printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n");
-
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading LCD status\n");
+
if (hotk->model == L2D)
lcd = ~lcd;
- } else { /* L3H and the like have to be handled differently */
+ } else { /* L3H and the like have to be handled differently */
acpi_status status = 0;
struct acpi_object_list input;
union acpi_object mt_params[2];
struct acpi_buffer output;
union acpi_object out_obj;
-
+
input.count = 2;
input.pointer = mt_params;
/* Note: the following values are partly guessed up, but
@@ -647,15 +628,17 @@ static int get_lcd_state(void)
output.length = sizeof(out_obj);
output.pointer = &out_obj;
-
- status = acpi_evaluate_object(NULL, hotk->methods->lcd_status, &input, &output);
+
+ status =
+ acpi_evaluate_object(NULL, hotk->methods->lcd_status,
+ &input, &output);
if (status != AE_OK)
return -1;
if (out_obj.type == ACPI_TYPE_INTEGER)
/* That's what the AML code does */
lcd = out_obj.integer.value >> 8;
}
-
+
return (lcd & 1);
}
@@ -669,10 +652,13 @@ static int set_lcd_state(int value)
/* switch */
if (hotk->model != L3H) {
status =
- acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch,
+ acpi_evaluate_object(NULL,
+ hotk->methods->mt_lcd_switch,
NULL, NULL);
- } else { /* L3H and the like have to be handled differently */
- if (!write_acpi_int(hotk->handle, hotk->methods->mt_lcd_switch, 0x07, NULL))
+ } else { /* L3H and the like have to be handled differently */
+ if (!write_acpi_int
+ (hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
+ NULL))
status = AE_ERROR;
/* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
the exact behaviour is simulated here */
@@ -691,33 +677,33 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
return sprintf(page, "%d\n", get_lcd_state());
}
-
static int
-proc_write_lcd(struct file *file, const char __user *buffer,
+proc_write_lcd(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int value;
-
+
count = parse_arg(buffer, count, &value);
if (count > 0)
set_lcd_state(value);
return count;
}
-
static int read_brightness(void)
{
int value;
-
- if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
- if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
+
+ if (hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
+ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
&value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else if (hotk->methods->brightness_status) { /* For D1 for example */
- if (!read_acpi_int(NULL, hotk->methods->brightness_status,
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading brightness\n");
+ } else if (hotk->methods->brightness_status) { /* For D1 for example */
+ if (!read_acpi_int(NULL, hotk->methods->brightness_status,
&value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else /* No GPLV method */
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading brightness\n");
+ } else /* No GPLV method */
value = hotk->brightness;
return value;
}
@@ -730,23 +716,25 @@ static void set_brightness(int value)
acpi_status status = 0;
/* SPLV laptop */
- if(hotk->methods->brightness_set) {
- if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
+ if (hotk->methods->brightness_set) {
+ if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
value, NULL))
- printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ printk(KERN_WARNING
+ "Asus ACPI: Error changing brightness\n");
return;
}
/* No SPLV method if we are here, act as appropriate */
value -= read_brightness();
while (value != 0) {
- status = acpi_evaluate_object(NULL, (value > 0) ?
- hotk->methods->brightness_up :
+ status = acpi_evaluate_object(NULL, (value > 0) ?
+ hotk->methods->brightness_up :
hotk->methods->brightness_down,
NULL, NULL);
(value > 0) ? value-- : value++;
if (ACPI_FAILURE(status))
- printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ printk(KERN_WARNING
+ "Asus ACPI: Error changing brightness\n");
}
return;
}
@@ -759,7 +747,7 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
}
static int
-proc_write_brn(struct file *file, const char __user *buffer,
+proc_write_brn(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int value;
@@ -767,7 +755,7 @@ proc_write_brn(struct file *file, const char __user *buffer,
count = parse_arg(buffer, count, &value);
if (count > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
- /* 0 <= value <= 15 */
+ /* 0 <= value <= 15 */
set_brightness(value);
} else if (count < 0) {
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
@@ -779,7 +767,7 @@ proc_write_brn(struct file *file, const char __user *buffer,
static void set_display(int value)
{
/* no sanity check needed for now */
- if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
+ if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
value, NULL))
printk(KERN_WARNING "Asus ACPI: Error setting display\n");
return;
@@ -791,13 +779,14 @@ static void set_display(int value)
*/
static int
proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
- void *data)
+ void *data)
{
int value = 0;
-
+
if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
- printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
- value &= 0x07; /* needed for some models, shouldn't hurt others */
+ printk(KERN_WARNING
+ "Asus ACPI: Error reading display status\n");
+ value &= 0x07; /* needed for some models, shouldn't hurt others */
return sprintf(page, "%d\n", value);
}
@@ -808,8 +797,8 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
* simultaneously, so be warned. See the acpi4asus README for more info.
*/
static int
-proc_write_disp(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+proc_write_disp(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
{
int value;
@@ -822,19 +811,19 @@ proc_write_disp(struct file *file, const char __user *buffer,
return count;
}
-
-typedef int (proc_readfunc)(char *page, char **start, off_t off, int count,
- int *eof, void *data);
-typedef int (proc_writefunc)(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
+typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
+ int *eof, void *data);
+typedef int (proc_writefunc) (struct file * file, const char __user * buffer,
+ unsigned long count, void *data);
static int
-__init asus_proc_add(char *name, proc_writefunc *writefunc,
- proc_readfunc *readfunc, mode_t mode,
- struct acpi_device *device)
+__init asus_proc_add(char *name, proc_writefunc * writefunc,
+ proc_readfunc * readfunc, mode_t mode,
+ struct acpi_device *device)
{
- struct proc_dir_entry *proc = create_proc_entry(name, mode, acpi_device_dir(device));
- if(!proc) {
+ struct proc_dir_entry *proc =
+ create_proc_entry(name, mode, acpi_device_dir(device));
+ if (!proc) {
printk(KERN_WARNING " Unable to create %s fs entry\n", name);
return -1;
}
@@ -851,14 +840,14 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *proc;
mode_t mode;
-
+
/*
* If parameter uid or gid is not changed, keep the default setting for
* our proc entries (-rw-rw-rw-) else, it means we care about security,
* and then set to -rw-rw----
*/
- if ((asus_uid == 0) && (asus_gid == 0)){
+ if ((asus_uid == 0) && (asus_gid == 0)) {
mode = S_IFREG | S_IRUGO | S_IWUGO;
} else {
mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
@@ -881,15 +870,18 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
}
if (hotk->methods->mt_wled) {
- asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, mode, device);
+ asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled,
+ mode, device);
}
if (hotk->methods->mt_mled) {
- asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, mode, device);
+ asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled,
+ mode, device);
}
if (hotk->methods->mt_tled) {
- asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, mode, device);
+ asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled,
+ mode, device);
}
/*
@@ -897,35 +889,40 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
* from keyboard
*/
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
- asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, device);
+ asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode,
+ device);
}
-
+
if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
(hotk->methods->brightness_get && hotk->methods->brightness_set)) {
- asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device);
+ asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode,
+ device);
}
if (hotk->methods->display_set) {
- asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device);
+ asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp,
+ mode, device);
}
return 0;
}
-static int asus_hotk_remove_fs(struct acpi_device* device)
+static int asus_hotk_remove_fs(struct acpi_device *device)
{
- if(acpi_device_dir(device)) {
- remove_proc_entry(PROC_INFO,acpi_device_dir(device));
+ if (acpi_device_dir(device)) {
+ remove_proc_entry(PROC_INFO, acpi_device_dir(device));
if (hotk->methods->mt_wled)
- remove_proc_entry(PROC_WLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_WLED, acpi_device_dir(device));
if (hotk->methods->mt_mled)
- remove_proc_entry(PROC_MLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_MLED, acpi_device_dir(device));
if (hotk->methods->mt_tled)
- remove_proc_entry(PROC_TLED,acpi_device_dir(device));
+ remove_proc_entry(PROC_TLED, acpi_device_dir(device));
if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
remove_proc_entry(PROC_LCD, acpi_device_dir(device));
- if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
- (hotk->methods->brightness_get && hotk->methods->brightness_set))
+ if ((hotk->methods->brightness_up
+ && hotk->methods->brightness_down)
+ || (hotk->methods->brightness_get
+ && hotk->methods->brightness_set))
remove_proc_entry(PROC_BRN, acpi_device_dir(device));
if (hotk->methods->display_set)
remove_proc_entry(PROC_DISP, acpi_device_dir(device));
@@ -933,16 +930,15 @@ static int asus_hotk_remove_fs(struct acpi_device* device)
return 0;
}
-
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
{
- /* TODO Find a better way to handle events count.*/
+ /* TODO Find a better way to handle events count. */
if (!hotk)
return;
if ((event & ~((u32) BR_UP)) < 16) {
hotk->brightness = (event & ~((u32) BR_UP));
- } else if ((event & ~((u32) BR_DOWN)) < 16 ) {
+ } else if ((event & ~((u32) BR_DOWN)) < 16) {
hotk->brightness = (event & ~((u32) BR_DOWN));
}
@@ -976,7 +972,7 @@ static int __init asus_hotk_get_info(void)
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Couldn't get the DSDT table header\n");
else
- asus_info = (struct acpi_table_header *) dsdt.pointer;
+ asus_info = (struct acpi_table_header *)dsdt.pointer;
/* We have to write 0 on init this far for all ASUS models */
if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
@@ -988,15 +984,17 @@ static int __init asus_hotk_get_info(void)
if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
printk(KERN_WARNING " Error calling BSTS\n");
else if (bsts_result)
- printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result);
+ printk(KERN_NOTICE " BSTS called, 0x%02x returned\n",
+ bsts_result);
/* Samsung P30 has a device with a valid _HID whose INIT does not
* return anything. Catch this one and any similar here */
if (buffer.pointer == NULL) {
- if (asus_info && /* Samsung P30 */
+ if (asus_info && /* Samsung P30 */
strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
hotk->model = P30;
- printk(KERN_NOTICE " Samsung P30 detected, supported\n");
+ printk(KERN_NOTICE
+ " Samsung P30 detected, supported\n");
} else {
hotk->model = M2E;
printk(KERN_WARNING " no string returned by INIT\n");
@@ -1006,10 +1004,11 @@ static int __init asus_hotk_get_info(void)
hotk->methods = &model_conf[hotk->model];
return AE_OK;
}
-
- model = (union acpi_object *) buffer.pointer;
+
+ model = (union acpi_object *)buffer.pointer;
if (model->type == ACPI_TYPE_STRING) {
- printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
+ printk(KERN_NOTICE " %s model detected, ",
+ model->string.pointer);
}
hotk->model = END_MODEL;
@@ -1035,7 +1034,7 @@ static int __init asus_hotk_get_info(void)
strncmp(model->string.pointer, "M6N", 3) == 0 ||
strncmp(model->string.pointer, "S1N", 3) == 0 ||
strncmp(model->string.pointer, "S5N", 3) == 0 ||
- strncmp(model->string.pointer, "W1N", 3) == 0)
+ strncmp(model->string.pointer, "W1N", 3) == 0)
hotk->model = xxN;
else if (strncmp(model->string.pointer, "M1", 2) == 0)
hotk->model = M1A;
@@ -1069,21 +1068,21 @@ static int __init asus_hotk_get_info(void)
/* Sort of per-model blacklist */
if (strncmp(model->string.pointer, "L2B", 3) == 0)
- hotk->methods->lcd_status = NULL;
+ hotk->methods->lcd_status = NULL;
/* L2B is similar enough to L3C to use its settings, with this only
exception */
else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
strncmp(model->string.pointer, "M5N", 3) == 0)
- hotk->methods->mt_mled = NULL;
+ hotk->methods->mt_mled = NULL;
/* S5N and M5N have no MLED */
else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
strncmp(model->string.pointer, "W1N", 3) == 0)
- hotk->methods->mt_wled = "WLED";
+ hotk->methods->mt_wled = "WLED";
/* M2N and W1N have a usable WLED */
else if (asus_info) {
if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
hotk->methods->mled_status = NULL;
- /* S1300A reports L84F, but L1400B too, account for that */
+ /* S1300A reports L84F, but L1400B too, account for that */
}
acpi_os_free(model);
@@ -1091,7 +1090,6 @@ static int __init asus_hotk_get_info(void)
return AE_OK;
}
-
static int __init asus_hotk_check(void)
{
int result = 0;
@@ -1110,7 +1108,6 @@ static int __init asus_hotk_check(void)
return result;
}
-
static int __init asus_hotk_add(struct acpi_device *device)
{
acpi_status status = AE_OK;
@@ -1123,7 +1120,7 @@ static int __init asus_hotk_add(struct acpi_device *device)
ASUS_ACPI_VERSION);
hotk =
- (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+ (struct asus_hotk *)kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
if (!hotk)
return -ENOMEM;
memset(hotk, 0, sizeof(struct asus_hotk));
@@ -1134,7 +1131,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
acpi_driver_data(device) = hotk;
hotk->device = device;
-
result = asus_hotk_check();
if (result)
goto end;
@@ -1153,17 +1149,22 @@ static int __init asus_hotk_add(struct acpi_device *device)
printk(KERN_ERR " Error installing notify handler\n");
/* For laptops without GPLV: init the hotk->brightness value */
- if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) &&
- (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
- status = acpi_evaluate_object(NULL, hotk->methods->brightness_down,
- NULL, NULL);
+ if ((!hotk->methods->brightness_get)
+ && (!hotk->methods->brightness_status)
+ && (hotk->methods->brightness_up
+ && hotk->methods->brightness_down)) {
+ status =
+ acpi_evaluate_object(NULL, hotk->methods->brightness_down,
+ NULL, NULL);
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Error changing brightness\n");
else {
- status = acpi_evaluate_object(NULL, hotk->methods->brightness_up,
- NULL, NULL);
+ status =
+ acpi_evaluate_object(NULL,
+ hotk->methods->brightness_up,
+ NULL, NULL);
if (ACPI_FAILURE(status))
- printk(KERN_WARNING " Strange, error changing"
+ printk(KERN_WARNING " Strange, error changing"
" brightness\n");
}
}
@@ -1176,7 +1177,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
return result;
}
-
static int asus_hotk_remove(struct acpi_device *device, int type)
{
acpi_status status = 0;
@@ -1196,7 +1196,6 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
return 0;
}
-
static int __init asus_acpi_init(void)
{
int result;
@@ -1204,9 +1203,9 @@ static int __init asus_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
+ if (!acpi_specific_hotkey_enabled) {
printk(KERN_ERR "Using generic hotkey driver\n");
- return -ENODEV;
+ return -ENODEV;
}
asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
if (!asus_proc_dir) {
@@ -1225,7 +1224,6 @@ static int __init asus_acpi_init(void)
return 0;
}
-
static void __exit asus_acpi_exit(void)
{
acpi_bus_unregister_driver(&asus_hotk_driver);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index c55feca9b7d5..702e857e98c5 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -34,7 +34,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
@@ -53,87 +52,85 @@
#define ACPI_BATTERY_UNITS_WATTS "mW"
#define ACPI_BATTERY_UNITS_AMPS "mA"
-
#define _COMPONENT ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME ("acpi_battery")
+ACPI_MODULE_NAME("acpi_battery")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_battery_add (struct acpi_device *device);
-static int acpi_battery_remove (struct acpi_device *device, int type);
+static int acpi_battery_add(struct acpi_device *device);
+static int acpi_battery_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_battery_driver = {
- .name = ACPI_BATTERY_DRIVER_NAME,
- .class = ACPI_BATTERY_CLASS,
- .ids = ACPI_BATTERY_HID,
- .ops = {
- .add = acpi_battery_add,
- .remove = acpi_battery_remove,
- },
+ .name = ACPI_BATTERY_DRIVER_NAME,
+ .class = ACPI_BATTERY_CLASS,
+ .ids = ACPI_BATTERY_HID,
+ .ops = {
+ .add = acpi_battery_add,
+ .remove = acpi_battery_remove,
+ },
};
struct acpi_battery_status {
- acpi_integer state;
- acpi_integer present_rate;
- acpi_integer remaining_capacity;
- acpi_integer present_voltage;
+ acpi_integer state;
+ acpi_integer present_rate;
+ acpi_integer remaining_capacity;
+ acpi_integer present_voltage;
};
struct acpi_battery_info {
- acpi_integer power_unit;
- acpi_integer design_capacity;
- acpi_integer last_full_capacity;
- acpi_integer battery_technology;
- acpi_integer design_voltage;
- acpi_integer design_capacity_warning;
- acpi_integer design_capacity_low;
- acpi_integer battery_capacity_granularity_1;
- acpi_integer battery_capacity_granularity_2;
- acpi_string model_number;
- acpi_string serial_number;
- acpi_string battery_type;
- acpi_string oem_info;
+ acpi_integer power_unit;
+ acpi_integer design_capacity;
+ acpi_integer last_full_capacity;
+ acpi_integer battery_technology;
+ acpi_integer design_voltage;
+ acpi_integer design_capacity_warning;
+ acpi_integer design_capacity_low;
+ acpi_integer battery_capacity_granularity_1;
+ acpi_integer battery_capacity_granularity_2;
+ acpi_string model_number;
+ acpi_string serial_number;
+ acpi_string battery_type;
+ acpi_string oem_info;
};
struct acpi_battery_flags {
- u8 present:1; /* Bay occupied? */
- u8 power_unit:1; /* 0=watts, 1=apms */
- u8 alarm:1; /* _BTP present? */
- u8 reserved:5;
+ u8 present:1; /* Bay occupied? */
+ u8 power_unit:1; /* 0=watts, 1=apms */
+ u8 alarm:1; /* _BTP present? */
+ u8 reserved:5;
};
struct acpi_battery_trips {
- unsigned long warning;
- unsigned long low;
+ unsigned long warning;
+ unsigned long low;
};
struct acpi_battery {
- acpi_handle handle;
+ acpi_handle handle;
struct acpi_battery_flags flags;
struct acpi_battery_trips trips;
- unsigned long alarm;
+ unsigned long alarm;
struct acpi_battery_info *info;
};
-
/* --------------------------------------------------------------------------
Battery Management
-------------------------------------------------------------------------- */
static int
-acpi_battery_get_info (
- struct acpi_battery *battery,
- struct acpi_battery_info **bif)
+acpi_battery_get_info(struct acpi_battery *battery,
+ struct acpi_battery_info **bif)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
- ACPI_BATTERY_FORMAT_BIF};
- struct acpi_buffer data = {0, NULL};
- union acpi_object *package = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
+ ACPI_BATTERY_FORMAT_BIF
+ };
+ struct acpi_buffer data = { 0, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_get_info");
@@ -148,7 +145,7 @@ acpi_battery_get_info (
return_VALUE(-ENODEV);
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
/* Extract Package Data */
@@ -174,27 +171,27 @@ acpi_battery_get_info (
goto end;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
if (!result)
- (*bif) = (struct acpi_battery_info *) data.pointer;
+ (*bif) = (struct acpi_battery_info *)data.pointer;
return_VALUE(result);
}
static int
-acpi_battery_get_status (
- struct acpi_battery *battery,
- struct acpi_battery_status **bst)
+acpi_battery_get_status(struct acpi_battery *battery,
+ struct acpi_battery_status **bst)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST),
- ACPI_BATTERY_FORMAT_BST};
- struct acpi_buffer data = {0, NULL};
- union acpi_object *package = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
+ ACPI_BATTERY_FORMAT_BST
+ };
+ struct acpi_buffer data = { 0, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_get_status");
@@ -209,7 +206,7 @@ acpi_battery_get_status (
return_VALUE(-ENODEV);
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
/* Extract Package Data */
@@ -235,24 +232,21 @@ acpi_battery_get_status (
goto end;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
if (!result)
- (*bst) = (struct acpi_battery_status *) data.pointer;
+ (*bst) = (struct acpi_battery_status *)data.pointer;
return_VALUE(result);
}
-
static int
-acpi_battery_set_alarm (
- struct acpi_battery *battery,
- unsigned long alarm)
+acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
{
- acpi_status status = 0;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg0};
+ acpi_status status = 0;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
@@ -275,19 +269,16 @@ acpi_battery_set_alarm (
return_VALUE(0);
}
-
-static int
-acpi_battery_check (
- struct acpi_battery *battery)
+static int acpi_battery_check(struct acpi_battery *battery)
{
- int result = 0;
- acpi_status status = AE_OK;
- acpi_handle handle = NULL;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ acpi_handle handle = NULL;
+ struct acpi_device *device = NULL;
struct acpi_battery_info *bif = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_check");
-
+
if (!battery)
return_VALUE(-EINVAL);
@@ -336,18 +327,17 @@ acpi_battery_check (
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_battery_dir;
+static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
+ int result = 0;
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
struct acpi_battery_info *bif = NULL;
- char *units = "?";
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_info");
@@ -369,19 +359,21 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
goto end;
}
- units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
-
+ units =
+ bif->
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+
if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "design capacity: unknown\n");
else
seq_printf(seq, "design capacity: %d %sh\n",
- (u32) bif->design_capacity, units);
+ (u32) bif->design_capacity, units);
if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "last full capacity: unknown\n");
else
seq_printf(seq, "last full capacity: %d %sh\n",
- (u32) bif->last_full_capacity, units);
+ (u32) bif->last_full_capacity, units);
switch ((u32) bif->battery_technology) {
case 0:
@@ -399,26 +391,22 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
seq_printf(seq, "design voltage: unknown\n");
else
seq_printf(seq, "design voltage: %d mV\n",
- (u32) bif->design_voltage);
-
+ (u32) bif->design_voltage);
+
seq_printf(seq, "design capacity warning: %d %sh\n",
- (u32) bif->design_capacity_warning, units);
+ (u32) bif->design_capacity_warning, units);
seq_printf(seq, "design capacity low: %d %sh\n",
- (u32) bif->design_capacity_low, units);
+ (u32) bif->design_capacity_low, units);
seq_printf(seq, "capacity granularity 1: %d %sh\n",
- (u32) bif->battery_capacity_granularity_1, units);
+ (u32) bif->battery_capacity_granularity_1, units);
seq_printf(seq, "capacity granularity 2: %d %sh\n",
- (u32) bif->battery_capacity_granularity_2, units);
- seq_printf(seq, "model number: %s\n",
- bif->model_number);
- seq_printf(seq, "serial number: %s\n",
- bif->serial_number);
- seq_printf(seq, "battery type: %s\n",
- bif->battery_type);
- seq_printf(seq, "OEM info: %s\n",
- bif->oem_info);
-
-end:
+ (u32) bif->battery_capacity_granularity_2, units);
+ seq_printf(seq, "model number: %s\n", bif->model_number);
+ seq_printf(seq, "serial number: %s\n", bif->serial_number);
+ seq_printf(seq, "battery type: %s\n", bif->battery_type);
+ seq_printf(seq, "OEM info: %s\n", bif->oem_info);
+
+ end:
kfree(bif);
return_VALUE(0);
@@ -429,14 +417,12 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_battery_read_info, PDE(inode)->data);
}
-
-static int
-acpi_battery_read_state (struct seq_file *seq, void *offset)
+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
+ int result = 0;
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
struct acpi_battery_status *bst = NULL;
- char *units = "?";
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_state");
@@ -452,7 +438,9 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
/* Battery Units */
- units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+ units =
+ battery->flags.
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
/* Battery Status (_BST) */
@@ -467,12 +455,12 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
else
seq_printf(seq, "capacity state: critical\n");
- if ((bst->state & 0x01) && (bst->state & 0x02)){
- seq_printf(seq, "charging state: charging/discharging\n");
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Battery Charging and Discharging?\n"));
- }
- else if (bst->state & 0x01)
+ if ((bst->state & 0x01) && (bst->state & 0x02)) {
+ seq_printf(seq,
+ "charging state: charging/discharging\n");
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Battery Charging and Discharging?\n"));
+ } else if (bst->state & 0x01)
seq_printf(seq, "charging state: discharging\n");
else if (bst->state & 0x02)
seq_printf(seq, "charging state: charging\n");
@@ -484,21 +472,21 @@ acpi_battery_read_state (struct seq_file *seq, void *offset)
seq_printf(seq, "present rate: unknown\n");
else
seq_printf(seq, "present rate: %d %s\n",
- (u32) bst->present_rate, units);
+ (u32) bst->present_rate, units);
if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "remaining capacity: unknown\n");
else
seq_printf(seq, "remaining capacity: %d %sh\n",
- (u32) bst->remaining_capacity, units);
+ (u32) bst->remaining_capacity, units);
if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
seq_printf(seq, "present voltage: unknown\n");
else
seq_printf(seq, "present voltage: %d mV\n",
- (u32) bst->present_voltage);
+ (u32) bst->present_voltage);
-end:
+ end:
kfree(bst);
return_VALUE(0);
@@ -509,12 +497,10 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_battery_read_state, PDE(inode)->data);
}
-
-static int
-acpi_battery_read_alarm (struct seq_file *seq, void *offset)
+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
{
- struct acpi_battery *battery = (struct acpi_battery *) seq->private;
- char *units = "?";
+ struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ char *units = "?";
ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
@@ -527,8 +513,10 @@ acpi_battery_read_alarm (struct seq_file *seq, void *offset)
}
/* Battery Units */
-
- units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
+
+ units =
+ battery->flags.
+ power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
/* Battery Alarm */
@@ -538,22 +526,19 @@ acpi_battery_read_alarm (struct seq_file *seq, void *offset)
else
seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
-end:
+ end:
return_VALUE(0);
}
-
static ssize_t
-acpi_battery_write_alarm (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_battery_write_alarm(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- int result = 0;
- char alarm_string[12] = {'\0'};
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_battery *battery = (struct acpi_battery *)m->private;
+ int result = 0;
+ char alarm_string[12] = { '\0' };
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_battery *battery = (struct acpi_battery *)m->private;
ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
@@ -565,11 +550,11 @@ acpi_battery_write_alarm (
if (copy_from_user(alarm_string, buffer, count))
return_VALUE(-EFAULT);
-
+
alarm_string[count] = '\0';
- result = acpi_battery_set_alarm(battery,
- simple_strtoul(alarm_string, NULL, 0));
+ result = acpi_battery_set_alarm(battery,
+ simple_strtoul(alarm_string, NULL, 0));
if (result)
return_VALUE(result);
@@ -582,41 +567,39 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_battery_info_ops = {
- .open = acpi_battery_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
static struct file_operations acpi_battery_state_ops = {
- .open = acpi_battery_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
static struct file_operations acpi_battery_alarm_ops = {
- .open = acpi_battery_alarm_open_fs,
- .read = seq_read,
- .write = acpi_battery_write_alarm,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_battery_alarm_open_fs,
+ .read = seq_read,
+ .write = acpi_battery_write_alarm,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_battery_add_fs (
- struct acpi_device *device)
+static int acpi_battery_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_battery_dir);
+ acpi_battery_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -624,24 +607,24 @@ acpi_battery_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_INFO));
else {
- entry->proc_fops = &acpi_battery_info_ops;
+ entry->proc_fops = &acpi_battery_info_ops;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
/* 'status' [R] */
entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_STATUS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_STATUS));
else {
entry->proc_fops = &acpi_battery_state_ops;
entry->data = acpi_driver_data(device);
@@ -650,11 +633,12 @@ acpi_battery_add_fs (
/* 'alarm' [R/W] */
entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BATTERY_FILE_ALARM));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BATTERY_FILE_ALARM));
else {
entry->proc_fops = &acpi_battery_alarm_ops;
entry->data = acpi_driver_data(device);
@@ -664,10 +648,7 @@ acpi_battery_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_battery_remove_fs (
- struct acpi_device *device)
+static int acpi_battery_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
@@ -686,19 +667,14 @@ acpi_battery_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_battery_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_battery *battery = (struct acpi_battery *) data;
- struct acpi_device *device = NULL;
+ struct acpi_battery *battery = (struct acpi_battery *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_notify");
@@ -716,24 +692,21 @@ acpi_battery_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_battery_add (
- struct acpi_device *device)
+static int acpi_battery_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_battery *battery = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_battery *battery = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_add");
-
+
if (!device)
return_VALUE(-EINVAL);
@@ -756,19 +729,20 @@ acpi_battery_add (
goto end;
status = acpi_install_notify_handler(battery->handle,
- ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery);
+ ACPI_DEVICE_NOTIFY,
+ acpi_battery_notify, battery);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
- ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
- device->status.battery_present?"present":"absent");
-
-end:
+ ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+ device->status.battery_present ? "present" : "absent");
+
+ end:
if (result) {
acpi_battery_remove_fs(device);
kfree(battery);
@@ -777,27 +751,24 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_battery_remove (
- struct acpi_device *device,
- int type)
+static int acpi_battery_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_battery *battery = NULL;
+ acpi_status status = 0;
+ struct acpi_battery *battery = NULL;
ACPI_FUNCTION_TRACE("acpi_battery_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- battery = (struct acpi_battery *) acpi_driver_data(device);
+ battery = (struct acpi_battery *)acpi_driver_data(device);
status = acpi_remove_notify_handler(battery->handle,
- ACPI_DEVICE_NOTIFY, acpi_battery_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_battery_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_battery_remove_fs(device);
@@ -806,11 +777,9 @@ acpi_battery_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_battery_init (void)
+static int __init acpi_battery_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_battery_init");
@@ -828,9 +797,7 @@ acpi_battery_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_battery_exit (void)
+static void __exit acpi_battery_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_battery_exit");
@@ -841,6 +808,5 @@ acpi_battery_exit (void)
return_VOID;
}
-
module_init(acpi_battery_init);
module_exit(acpi_battery_exit);
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 4c010e7f11b8..9824f679a910 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -26,7 +26,6 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -34,49 +33,49 @@
#include <acpi/acpi_bus.h>
#include <linux/dmi.h>
-enum acpi_blacklist_predicates
-{
- all_versions,
- less_than_or_equal,
- equal,
- greater_than_or_equal,
+enum acpi_blacklist_predicates {
+ all_versions,
+ less_than_or_equal,
+ equal,
+ greater_than_or_equal,
};
-struct acpi_blacklist_item
-{
- char oem_id[7];
- char oem_table_id[9];
- u32 oem_revision;
- acpi_table_type table;
- enum acpi_blacklist_predicates oem_revision_predicate;
- char *reason;
- u32 is_critical_error;
+struct acpi_blacklist_item {
+ char oem_id[7];
+ char oem_table_id[9];
+ u32 oem_revision;
+ acpi_table_type table;
+ enum acpi_blacklist_predicates oem_revision_predicate;
+ char *reason;
+ u32 is_critical_error;
};
/*
* POLICY: If *anything* doesn't work, put it on the blacklist.
* If they are critical errors, mark it critical, and abort driver load.
*/
-static struct acpi_blacklist_item acpi_blacklist[] __initdata =
-{
+static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
/* Compaq Presario 1700 */
- {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
+ {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal,
+ "Multiple problems", 1},
/* Sony FX120, FX140, FX150? */
- {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1},
+ {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal,
+ "ACPI driver problem", 1},
/* Compaq Presario 800, Insyde BIOS */
- {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
+ {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal,
+ "Does not use _REG to protect EC OpRegions", 1},
/* IBM 600E - _ADR should return 7, but it returns 1 */
- {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
- {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1},
+ {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal,
+ "Incorrect _ADR", 1},
+ {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions,
+ "Bogus PCI routing", 1},
{""}
};
-
#if CONFIG_ACPI_BLACKLIST_YEAR
-static int __init
-blacklist_by_year(void)
+static int __init blacklist_by_year(void)
{
int year;
char *s = dmi_get_system_info(DMI_BIOS_DATE);
@@ -92,36 +91,38 @@ blacklist_by_year(void)
s += 1;
- year = simple_strtoul(s,NULL,0);
+ year = simple_strtoul(s, NULL, 0);
- if (year < 100) { /* 2-digit year */
+ if (year < 100) { /* 2-digit year */
year += 1900;
if (year < 1996) /* no dates < spec 1.0 */
year += 100;
}
if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
- printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
- "acpi=force is required to enable ACPI\n",
- year, CONFIG_ACPI_BLACKLIST_YEAR);
+ printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
+ "acpi=force is required to enable ACPI\n",
+ year, CONFIG_ACPI_BLACKLIST_YEAR);
return 1;
}
return 0;
}
#else
-static inline int blacklist_by_year(void) { return 0; }
+static inline int blacklist_by_year(void)
+{
+ return 0;
+}
#endif
-int __init
-acpi_blacklisted(void)
+int __init acpi_blacklisted(void)
{
int i = 0;
int blacklisted = 0;
struct acpi_table_header *table_header;
- while (acpi_blacklist[i].oem_id[0] != '\0')
- {
- if (acpi_get_table_header_early(acpi_blacklist[i].table, &table_header)) {
+ while (acpi_blacklist[i].oem_id[0] != '\0') {
+ if (acpi_get_table_header_early
+ (acpi_blacklist[i].table, &table_header)) {
i++;
continue;
}
@@ -131,33 +132,43 @@ acpi_blacklisted(void)
continue;
}
- if (strncmp(acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) {
+ if (strncmp
+ (acpi_blacklist[i].oem_table_id, table_header->oem_table_id,
+ 8)) {
i++;
continue;
}
if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
- || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal
- && table_header->oem_revision <= acpi_blacklist[i].oem_revision)
- || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal
- && table_header->oem_revision >= acpi_blacklist[i].oem_revision)
+ || (acpi_blacklist[i].oem_revision_predicate ==
+ less_than_or_equal
+ && table_header->oem_revision <=
+ acpi_blacklist[i].oem_revision)
+ || (acpi_blacklist[i].oem_revision_predicate ==
+ greater_than_or_equal
+ && table_header->oem_revision >=
+ acpi_blacklist[i].oem_revision)
|| (acpi_blacklist[i].oem_revision_predicate == equal
- && table_header->oem_revision == acpi_blacklist[i].oem_revision)) {
-
- printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" "
- "Revision 0x%x has a known ACPI BIOS problem.\n",
- acpi_blacklist[i].oem_id,
- acpi_blacklist[i].oem_table_id,
- acpi_blacklist[i].oem_revision);
-
- printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n",
- acpi_blacklist[i].reason,
- (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable"));
+ && table_header->oem_revision ==
+ acpi_blacklist[i].oem_revision)) {
+
+ printk(KERN_ERR PREFIX
+ "Vendor \"%6.6s\" System \"%8.8s\" "
+ "Revision 0x%x has a known ACPI BIOS problem.\n",
+ acpi_blacklist[i].oem_id,
+ acpi_blacklist[i].oem_table_id,
+ acpi_blacklist[i].oem_revision);
+
+ printk(KERN_ERR PREFIX
+ "Reason: %s. This is a %s error\n",
+ acpi_blacklist[i].reason,
+ (acpi_blacklist[i].
+ is_critical_error ? "non-recoverable" :
+ "recoverable"));
blacklisted = acpi_blacklist[i].is_critical_error;
break;
- }
- else {
+ } else {
i++;
}
}
@@ -166,4 +177,3 @@ acpi_blacklisted(void)
return blacklisted;
}
-
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d77c2307883c..6a4da417c16b 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -36,19 +36,17 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("acpi_bus")
-
+ACPI_MODULE_NAME("acpi_bus")
#ifdef CONFIG_X86
extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
#endif
-FADT_DESCRIPTOR acpi_fadt;
+FADT_DESCRIPTOR acpi_fadt;
EXPORT_SYMBOL(acpi_fadt);
-struct acpi_device *acpi_root;
-struct proc_dir_entry *acpi_root_dir;
+struct acpi_device *acpi_root;
+struct proc_dir_entry *acpi_root_dir;
EXPORT_SYMBOL(acpi_root_dir);
#define STRUCT_TO_INT(s) (*((int*)&s))
@@ -57,12 +55,9 @@ EXPORT_SYMBOL(acpi_root_dir);
Device Management
-------------------------------------------------------------------------- */
-int
-acpi_bus_get_device (
- acpi_handle handle,
- struct acpi_device **device)
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_bus_get_device");
@@ -71,24 +66,23 @@ acpi_bus_get_device (
/* TBD: Support fixed-feature devices */
- status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device);
+ status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No context for object [%p]\n",
- handle));
+ handle));
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
+
EXPORT_SYMBOL(acpi_bus_get_device);
-int
-acpi_bus_get_status (
- struct acpi_device *device)
+int acpi_bus_get_status(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- unsigned long sta = 0;
-
+ acpi_status status = AE_OK;
+ unsigned long sta = 0;
+
ACPI_FUNCTION_TRACE("acpi_bus_get_status");
if (!device)
@@ -98,10 +92,11 @@ acpi_bus_get_status (
* Evaluate _STA if present.
*/
if (device->flags.dynamic_status) {
- status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
+ status =
+ acpi_evaluate_integer(device->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- STRUCT_TO_INT(device->status) = (int) sta;
+ STRUCT_TO_INT(device->status) = (int)sta;
}
/*
@@ -115,33 +110,30 @@ acpi_bus_get_status (
if (device->status.functional && !device->status.present) {
printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
- "functional but not present; setting present\n",
- device->pnp.bus_id,
- (u32) STRUCT_TO_INT(device->status));
+ "functional but not present; setting present\n",
+ device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status));
device->status.present = 1;
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
- device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
+ device->pnp.bus_id,
+ (u32) STRUCT_TO_INT(device->status)));
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_get_status);
+EXPORT_SYMBOL(acpi_bus_get_status);
/* --------------------------------------------------------------------------
Power Management
-------------------------------------------------------------------------- */
-int
-acpi_bus_get_power (
- acpi_handle handle,
- int *state)
+int acpi_bus_get_power(acpi_handle handle, int *state)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_device *device = NULL;
- unsigned long psc = 0;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_device *device = NULL;
+ unsigned long psc = 0;
ACPI_FUNCTION_TRACE("acpi_bus_get_power");
@@ -157,20 +149,18 @@ acpi_bus_get_power (
*state = device->parent->power.state;
else
*state = ACPI_STATE_D0;
- }
- else {
+ } else {
/*
* Get the device's power state either directly (via _PSC) or
* indirectly (via power resources).
*/
if (device->power.flags.explicit_get) {
- status = acpi_evaluate_integer(device->handle, "_PSC",
- NULL, &psc);
+ status = acpi_evaluate_integer(device->handle, "_PSC",
+ NULL, &psc);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- device->power.state = (int) psc;
- }
- else if (device->power.flags.power_resources) {
+ device->power.state = (int)psc;
+ } else if (device->power.flags.power_resources) {
result = acpi_power_get_inferred_state(device);
if (result)
return_VALUE(result);
@@ -180,22 +170,19 @@ acpi_bus_get_power (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
- device->pnp.bus_id, device->power.state));
+ device->pnp.bus_id, device->power.state));
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_get_power);
+EXPORT_SYMBOL(acpi_bus_get_power);
-int
-acpi_bus_set_power (
- acpi_handle handle,
- int state)
+int acpi_bus_set_power(acpi_handle handle, int state)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
- char object_name[5] = {'_','P','S','0'+state,'\0'};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
+ char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
ACPI_FUNCTION_TRACE("acpi_bus_set_power");
@@ -209,7 +196,8 @@ acpi_bus_set_power (
/* Make sure this is a valid target state */
if (!device->flags.power_manageable) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Device is not power manageable\n"));
return_VALUE(-ENODEV);
}
/*
@@ -219,15 +207,18 @@ acpi_bus_set_power (
if (device->power.state == ACPI_STATE_UNKNOWN)
acpi_bus_get_power(device->handle, &device->power.state);
if (state == device->power.state) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+ state));
return_VALUE(0);
}
if (!device->power.states[state].flags.valid) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n",
+ state));
return_VALUE(-ENODEV);
}
if (device->parent && (state < device->parent->power.state)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Cannot set device to a higher-powered state than parent\n"));
return_VALUE(-ENODEV);
}
@@ -245,18 +236,17 @@ acpi_bus_set_power (
goto end;
}
if (device->power.states[state].flags.explicit_set) {
- status = acpi_evaluate_object(device->handle,
- object_name, NULL, NULL);
+ status = acpi_evaluate_object(device->handle,
+ object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto end;
}
}
- }
- else {
+ } else {
if (device->power.states[state].flags.explicit_set) {
- status = acpi_evaluate_object(device->handle,
- object_name, NULL, NULL);
+ status = acpi_evaluate_object(device->handle,
+ object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto end;
@@ -269,19 +259,20 @@ acpi_bus_set_power (
}
}
-end:
+ end:
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Error transitioning device [%s] to D%d\n",
+ device->pnp.bus_id, state));
else
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device [%s] transitioned to D%d\n",
+ device->pnp.bus_id, state));
return_VALUE(result);
}
-EXPORT_SYMBOL(acpi_bus_set_power);
-
+EXPORT_SYMBOL(acpi_bus_set_power);
/* --------------------------------------------------------------------------
Event Management
@@ -292,16 +283,12 @@ static DEFINE_SPINLOCK(acpi_bus_event_lock);
LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
-extern int event_is_open;
+extern int event_is_open;
-int
-acpi_bus_generate_event (
- struct acpi_device *device,
- u8 type,
- int data)
+int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data)
{
- struct acpi_bus_event *event = NULL;
- unsigned long flags = 0;
+ struct acpi_bus_event *event = NULL;
+ unsigned long flags = 0;
ACPI_FUNCTION_TRACE("acpi_bus_generate_event");
@@ -329,14 +316,13 @@ acpi_bus_generate_event (
return_VALUE(0);
}
+
EXPORT_SYMBOL(acpi_bus_generate_event);
-int
-acpi_bus_receive_event (
- struct acpi_bus_event *event)
+int acpi_bus_receive_event(struct acpi_bus_event *event)
{
- unsigned long flags = 0;
- struct acpi_bus_event *entry = NULL;
+ unsigned long flags = 0;
+ struct acpi_bus_event *entry = NULL;
DECLARE_WAITQUEUE(wait, current);
@@ -361,7 +347,8 @@ acpi_bus_receive_event (
}
spin_lock_irqsave(&acpi_bus_event_lock, flags);
- entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
+ entry =
+ list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node);
if (entry)
list_del(&entry->node);
spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
@@ -375,19 +362,17 @@ acpi_bus_receive_event (
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_receive_event);
+EXPORT_SYMBOL(acpi_bus_receive_event);
/* --------------------------------------------------------------------------
Notification Handling
-------------------------------------------------------------------------- */
static int
-acpi_bus_check_device (
- struct acpi_device *device,
- int *status_changed)
+acpi_bus_check_device(struct acpi_device *device, int *status_changed)
{
- acpi_status status = 0;
+ acpi_status status = 0;
struct acpi_device_status old_status;
ACPI_FUNCTION_TRACE("acpi_bus_check_device");
@@ -422,15 +407,14 @@ acpi_bus_check_device (
if (status_changed)
*status_changed = 1;
-
+
/*
* Device Insertion/Removal
*/
if ((device->status.present) && !(old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
/* TBD: Handle device insertion */
- }
- else if (!(device->status.present) && (old_status.present)) {
+ } else if (!(device->status.present) && (old_status.present)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
/* TBD: Handle device removal */
}
@@ -438,13 +422,10 @@ acpi_bus_check_device (
return_VALUE(0);
}
-
-static int
-acpi_bus_check_scope (
- struct acpi_device *device)
+static int acpi_bus_check_scope(struct acpi_device *device)
{
- int result = 0;
- int status_changed = 0;
+ int result = 0;
+ int status_changed = 0;
ACPI_FUNCTION_TRACE("acpi_bus_check_scope");
@@ -467,20 +448,15 @@ acpi_bus_check_scope (
return_VALUE(0);
}
-
/**
* acpi_bus_notify
* ---------------
* Callback for all 'system-level' device notifications (values 0x00-0x7F).
*/
-static void
-acpi_bus_notify (
- acpi_handle handle,
- u32 type,
- void *data)
+static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_notify");
@@ -490,64 +466,73 @@ acpi_bus_notify (
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received BUS CHECK notification for device [%s]\n",
+ device->pnp.bus_id));
result = acpi_bus_check_scope(device);
/*
* TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
+ * drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_CHECK:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE CHECK notification for device [%s]\n",
+ device->pnp.bus_id));
result = acpi_bus_check_device(device, NULL);
/*
* TBD: We'll need to outsource certain events to non-ACPI
- * drivers via the device manager (device.c).
+ * drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_WAKE:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE WAKE notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_EJECT_REQUEST:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received EJECT REQUEST notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received DEVICE CHECK LIGHT notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD: Exactly what does 'light' mean? */
break;
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received FREQUENCY MISMATCH notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received BUS MODE MISMATCH notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
case ACPI_NOTIFY_POWER_FAULT:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received POWER FAULT notification for device [%s]\n",
+ device->pnp.bus_id));
/* TBD */
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n",
- type));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Received unknown/unsupported notification [%08x]\n",
+ type));
break;
}
@@ -558,13 +543,12 @@ acpi_bus_notify (
Initialization/Cleanup
-------------------------------------------------------------------------- */
-static int __init
-acpi_bus_init_irq (void)
+static int __init acpi_bus_init_irq(void)
{
- acpi_status status = AE_OK;
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- char *message = NULL;
+ acpi_status status = AE_OK;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ char *message = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_init_irq");
@@ -601,12 +585,10 @@ acpi_bus_init_irq (void)
return_VALUE(0);
}
-
-void __init
-acpi_early_init (void)
+void __init acpi_early_init(void)
{
- acpi_status status = AE_OK;
- struct acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt};
+ acpi_status status = AE_OK;
+ struct acpi_buffer buffer = { sizeof(acpi_fadt), &acpi_fadt };
ACPI_FUNCTION_TRACE("acpi_early_init");
@@ -619,13 +601,15 @@ acpi_early_init (void)
status = acpi_initialize_subsystem();
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n");
+ printk(KERN_ERR PREFIX
+ "Unable to initialize the ACPI Interpreter\n");
goto error0;
}
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n");
+ printk(KERN_ERR PREFIX
+ "Unable to load the System Description Tables\n");
goto error0;
}
@@ -637,7 +621,6 @@ acpi_early_init (void)
printk(KERN_ERR PREFIX "Unable to get the FADT\n");
goto error0;
}
-
#ifdef CONFIG_X86
if (!acpi_ioapic) {
extern acpi_interrupt_flags acpi_sci_flags;
@@ -647,7 +630,8 @@ acpi_early_init (void)
acpi_sci_flags.trigger = 3;
/* Set PIC-mode SCI trigger type */
- acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
+ acpi_pic_sci_set_trigger(acpi_fadt.sci_int,
+ acpi_sci_flags.trigger);
} else {
extern int acpi_sci_override_gsi;
/*
@@ -658,7 +642,10 @@ acpi_early_init (void)
}
#endif
- status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE));
+ status =
+ acpi_enable_subsystem(~
+ (ACPI_NO_HARDWARE_INIT |
+ ACPI_NO_ACPI_ENABLE));
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
goto error0;
@@ -666,30 +653,32 @@ acpi_early_init (void)
return_VOID;
-error0:
+ error0:
disable_acpi();
return_VOID;
}
-static int __init
-acpi_bus_init (void)
+static int __init acpi_bus_init(void)
{
- int result = 0;
- acpi_status status = AE_OK;
- extern acpi_status acpi_os_initialize1(void);
+ int result = 0;
+ acpi_status status = AE_OK;
+ extern acpi_status acpi_os_initialize1(void);
ACPI_FUNCTION_TRACE("acpi_bus_init");
status = acpi_os_initialize1();
- status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
+ status =
+ acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n");
+ printk(KERN_ERR PREFIX
+ "Unable to start the ACPI Interpreter\n");
goto error1;
}
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n");
+ printk(KERN_ERR PREFIX
+ "Unable to initialize ACPI OS objects\n");
goto error1;
}
#ifdef CONFIG_ACPI_EC
@@ -723,9 +712,12 @@ acpi_bus_init (void)
/*
* Register the for all standard device notifications.
*/
- status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
+ status =
+ acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
+ &acpi_bus_notify, NULL);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Unable to register for device notifications\n");
+ printk(KERN_ERR PREFIX
+ "Unable to register for device notifications\n");
goto error1;
}
@@ -737,21 +729,20 @@ acpi_bus_init (void)
return_VALUE(0);
/* Mimic structured exception handling */
-error1:
+ error1:
acpi_terminate();
return_VALUE(-ENODEV);
}
-decl_subsys(acpi,NULL,NULL);
+decl_subsys(acpi, NULL, NULL);
-static int __init acpi_init (void)
+static int __init acpi_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_init");
- printk(KERN_INFO PREFIX "Subsystem revision %08x\n",
- ACPI_CA_VERSION);
+ printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION);
if (acpi_disabled) {
printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -767,7 +758,8 @@ static int __init acpi_init (void)
if (!PM_IS_ACTIVE())
pm_active = 1;
else {
- printk(KERN_INFO PREFIX "APM is already active, exiting\n");
+ printk(KERN_INFO PREFIX
+ "APM is already active, exiting\n");
disable_acpi();
result = -ENODEV;
}
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 8162fd0c21a7..4b6d9f0096a1 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -32,7 +32,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_BUTTON_COMPONENT 0x00080000
#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
#define ACPI_BUTTON_CLASS "button"
@@ -42,7 +41,7 @@
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
#define ACPI_BUTTON_SUBCLASS_POWER "power"
-#define ACPI_BUTTON_HID_POWER "PNP0C0C"
+#define ACPI_BUTTON_HID_POWER "PNP0C0C"
#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
#define ACPI_BUTTON_TYPE_POWER 0x01
@@ -61,65 +60,65 @@
#define ACPI_BUTTON_TYPE_LID 0x05
#define _COMPONENT ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME ("acpi_button")
+ACPI_MODULE_NAME("acpi_button")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
MODULE_LICENSE("GPL");
-
-static int acpi_button_add (struct acpi_device *device);
-static int acpi_button_remove (struct acpi_device *device, int type);
+static int acpi_button_add(struct acpi_device *device);
+static int acpi_button_remove(struct acpi_device *device, int type);
static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
- .name = ACPI_BUTTON_DRIVER_NAME,
- .class = ACPI_BUTTON_CLASS,
- .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
- .ops = {
- .add = acpi_button_add,
- .remove = acpi_button_remove,
- },
+ .name = ACPI_BUTTON_DRIVER_NAME,
+ .class = ACPI_BUTTON_CLASS,
+ .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
+ .ops = {
+ .add = acpi_button_add,
+ .remove = acpi_button_remove,
+ },
};
struct acpi_button {
- acpi_handle handle;
- struct acpi_device *device; /* Fixed button kludge */
- u8 type;
- unsigned long pushed;
+ acpi_handle handle;
+ struct acpi_device *device; /* Fixed button kludge */
+ u8 type;
+ unsigned long pushed;
};
static struct file_operations acpi_button_info_fops = {
- .open = acpi_button_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_button_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_button_state_fops = {
- .open = acpi_button_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_button_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
+
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_button_dir;
+static struct proc_dir_entry *acpi_button_dir;
static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *) seq->private;
+ struct acpi_button *button = (struct acpi_button *)seq->private;
ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
if (!button || !button->device)
return_VALUE(0);
- seq_printf(seq, "type: %s\n",
- acpi_device_name(button->device));
+ seq_printf(seq, "type: %s\n",
+ acpi_device_name(button->device));
return_VALUE(0);
}
@@ -128,24 +127,24 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
}
-
+
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *) seq->private;
- acpi_status status;
- unsigned long state;
+ struct acpi_button *button = (struct acpi_button *)seq->private;
+ acpi_status status;
+ unsigned long state;
ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
if (!button || !button->device)
return_VALUE(0);
- status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state);
+ status = acpi_evaluate_integer(button->handle, "_LID", NULL, &state);
if (ACPI_FAILURE(status)) {
seq_printf(seq, "state: unsupported\n");
- }
- else{
- seq_printf(seq, "state: %s\n", (state ? "open" : "closed"));
+ } else {
+ seq_printf(seq, "state: %s\n",
+ (state ? "open" : "closed"));
}
return_VALUE(0);
@@ -160,12 +159,10 @@ static struct proc_dir_entry *acpi_power_dir;
static struct proc_dir_entry *acpi_sleep_dir;
static struct proc_dir_entry *acpi_lid_dir;
-static int
-acpi_button_add_fs (
- struct acpi_device *device)
+static int acpi_button_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_button *button = NULL;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add_fs");
@@ -178,21 +175,21 @@ acpi_button_add_fs (
case ACPI_BUTTON_TYPE_POWER:
case ACPI_BUTTON_TYPE_POWERF:
if (!acpi_power_dir)
- acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
- acpi_button_dir);
+ acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
+ acpi_button_dir);
entry = acpi_power_dir;
break;
case ACPI_BUTTON_TYPE_SLEEP:
case ACPI_BUTTON_TYPE_SLEEPF:
if (!acpi_sleep_dir)
- acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
- acpi_button_dir);
+ acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
+ acpi_button_dir);
entry = acpi_sleep_dir;
break;
case ACPI_BUTTON_TYPE_LID:
if (!acpi_lid_dir)
- acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
- acpi_button_dir);
+ acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
+ acpi_button_dir);
entry = acpi_lid_dir;
break;
}
@@ -208,11 +205,11 @@ acpi_button_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BUTTON_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
else {
entry->proc_fops = &acpi_button_info_fops;
entry->data = acpi_driver_data(device);
@@ -222,11 +219,11 @@ acpi_button_add_fs (
/* show lid state [R] */
if (button->type == ACPI_BUTTON_TYPE_LID) {
entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_BUTTON_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
else {
entry->proc_fops = &acpi_button_state_fops;
entry->data = acpi_driver_data(device);
@@ -237,12 +234,9 @@ acpi_button_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_button_remove_fs (
- struct acpi_device *device)
+static int acpi_button_remove_fs(struct acpi_device *device)
{
- struct acpi_button *button = NULL;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
@@ -250,30 +244,25 @@ acpi_button_remove_fs (
if (acpi_device_dir(device)) {
if (button->type == ACPI_BUTTON_TYPE_LID)
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
- acpi_device_dir(device));
+ acpi_device_dir(device));
remove_proc_entry(ACPI_BUTTON_FILE_INFO,
- acpi_device_dir(device));
+ acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device),
- acpi_device_dir(device)->parent);
+ acpi_device_dir(device)->parent);
acpi_device_dir(device) = NULL;
}
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_button_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_button *button = (struct acpi_button *) data;
+ struct acpi_button *button = (struct acpi_button *)data;
ACPI_FUNCTION_TRACE("acpi_button_notify");
@@ -282,24 +271,22 @@ acpi_button_notify (
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
- acpi_bus_generate_event(button->device, event, ++button->pushed);
+ acpi_bus_generate_event(button->device, event,
+ ++button->pushed);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static acpi_status
-acpi_button_notify_fixed (
- void *data)
+static acpi_status acpi_button_notify_fixed(void *data)
{
- struct acpi_button *button = (struct acpi_button *) data;
-
+ struct acpi_button *button = (struct acpi_button *)data;
+
ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
if (!button)
@@ -310,14 +297,11 @@ acpi_button_notify_fixed (
return_ACPI_STATUS(AE_OK);
}
-
-static int
-acpi_button_add (
- struct acpi_device *device)
+static int acpi_button_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_button *button = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add");
@@ -339,42 +323,34 @@ acpi_button_add (
*/
if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
button->type = ACPI_BUTTON_TYPE_POWER;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_POWER);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_POWER);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWERF;
strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_POWERF);
- sprintf(acpi_device_class(device), "%s/%s",
+ ACPI_BUTTON_DEVICE_NAME_POWERF);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_SLEEP);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_SLEEP);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEPF;
strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_SLEEPF);
- sprintf(acpi_device_class(device), "%s/%s",
+ ACPI_BUTTON_DEVICE_NAME_SLEEPF);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
- }
- else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
+ } else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
- strcpy(acpi_device_name(device),
- ACPI_BUTTON_DEVICE_NAME_LID);
- sprintf(acpi_device_class(device), "%s/%s",
+ strcpy(acpi_device_name(device), ACPI_BUTTON_DEVICE_NAME_LID);
+ sprintf(acpi_device_class(device), "%s/%s",
ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
- }
- else {
+ } else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
- acpi_device_hid(device)));
+ acpi_device_hid(device)));
result = -ENODEV;
goto end;
}
@@ -385,46 +361,46 @@ acpi_button_add (
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
- status = acpi_install_fixed_event_handler (
- ACPI_EVENT_POWER_BUTTON,
- acpi_button_notify_fixed,
- button);
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed,
+ button);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
- status = acpi_install_fixed_event_handler (
- ACPI_EVENT_SLEEP_BUTTON,
- acpi_button_notify_fixed,
- button);
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed,
+ button);
break;
default:
- status = acpi_install_notify_handler (
- button->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_button_notify,
- button);
+ status = acpi_install_notify_handler(button->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify,
+ button);
break;
}
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
- acpi_set_gpe_type(device->wakeup.gpe_device,
- device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
- acpi_enable_gpe(device->wakeup.gpe_device,
- device->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_set_gpe_type(device->wakeup.gpe_device,
+ device->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_enable_gpe(device->wakeup.gpe_device,
+ device->wakeup.gpe_number, ACPI_NOT_ISR);
device->wakeup.state.enabled = 1;
}
- printk(KERN_INFO PREFIX "%s [%s]\n",
- acpi_device_name(device), acpi_device_bid(device));
+ printk(KERN_INFO PREFIX "%s [%s]\n",
+ acpi_device_name(device), acpi_device_bid(device));
-end:
+ end:
if (result) {
acpi_button_remove_fs(device);
kfree(button);
@@ -433,12 +409,10 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_button_remove (struct acpi_device *device, int type)
+static int acpi_button_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_button *button = NULL;
+ acpi_status status = 0;
+ struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_remove");
@@ -450,35 +424,36 @@ acpi_button_remove (struct acpi_device *device, int type)
/* Unregister for device notifications. */
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
- status = acpi_remove_fixed_event_handler(
- ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed);
+ status =
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
- status = acpi_remove_fixed_event_handler(
- ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed);
+ status =
+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed);
break;
default:
status = acpi_remove_notify_handler(button->handle,
- ACPI_DEVICE_NOTIFY, acpi_button_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify);
break;
}
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
- acpi_button_remove_fs(device);
+ acpi_button_remove_fs(device);
kfree(button);
return_VALUE(0);
}
-
-static int __init
-acpi_button_init (void)
+static int __init acpi_button_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_button_init");
@@ -495,15 +470,13 @@ acpi_button_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_button_exit (void)
+static void __exit acpi_button_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_button_exit");
acpi_bus_unregister_driver(&acpi_button_driver);
- if (acpi_power_dir)
+ if (acpi_power_dir)
remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
if (acpi_sleep_dir)
remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
@@ -514,6 +487,5 @@ acpi_button_exit (void)
return_VOID;
}
-
module_init(acpi_button_init);
module_exit(acpi_button_exit);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 97013ddfa202..10dd695a1dd9 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -44,9 +44,9 @@
#define ACPI_CONTAINER_COMPONENT 0x01000000
#define _COMPONENT ACPI_CONTAINER_COMPONENT
-ACPI_MODULE_NAME ("acpi_container")
+ACPI_MODULE_NAME("acpi_container")
-MODULE_AUTHOR("Anil S Keshavamurthy");
+ MODULE_AUTHOR("Anil S Keshavamurthy");
MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -56,41 +56,38 @@ static int acpi_container_add(struct acpi_device *device);
static int acpi_container_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_container_driver = {
- .name = ACPI_CONTAINER_DRIVER_NAME,
- .class = ACPI_CONTAINER_CLASS,
- .ids = "ACPI0004,PNP0A05,PNP0A06",
- .ops = {
- .add = acpi_container_add,
- .remove = acpi_container_remove,
- },
+ .name = ACPI_CONTAINER_DRIVER_NAME,
+ .class = ACPI_CONTAINER_CLASS,
+ .ids = "ACPI0004,PNP0A05,PNP0A06",
+ .ops = {
+ .add = acpi_container_add,
+ .remove = acpi_container_remove,
+ },
};
-
/*******************************************************************/
-static int
-is_device_present(acpi_handle handle)
+static int is_device_present(acpi_handle handle)
{
- acpi_handle temp;
- acpi_status status;
- unsigned long sta;
+ acpi_handle temp;
+ acpi_status status;
+ unsigned long sta;
ACPI_FUNCTION_TRACE("is_device_present");
status = acpi_get_handle(handle, "_STA", &temp);
if (ACPI_FAILURE(status))
- return_VALUE(1); /* _STA not found, assmue device present */
+ return_VALUE(1); /* _STA not found, assmue device present */
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
- return_VALUE(0); /* Firmware error */
+ return_VALUE(0); /* Firmware error */
return_VALUE((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT);
}
/*******************************************************************/
-static int
-acpi_container_add(struct acpi_device *device)
+static int acpi_container_add(struct acpi_device *device)
{
struct acpi_container *container;
@@ -102,28 +99,26 @@ acpi_container_add(struct acpi_device *device)
}
container = kmalloc(sizeof(struct acpi_container), GFP_KERNEL);
- if(!container)
+ if (!container)
return_VALUE(-ENOMEM);
-
+
memset(container, 0, sizeof(struct acpi_container));
container->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
acpi_driver_data(device) = container;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", \
- acpi_device_name(device), acpi_device_bid(device)));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
+ acpi_device_name(device), acpi_device_bid(device)));
return_VALUE(0);
}
-static int
-acpi_container_remove(struct acpi_device *device, int type)
+static int acpi_container_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_container *pc = NULL;
- pc = (struct acpi_container*) acpi_driver_data(device);
+ acpi_status status = AE_OK;
+ struct acpi_container *pc = NULL;
+ pc = (struct acpi_container *)acpi_driver_data(device);
if (pc)
kfree(pc);
@@ -131,9 +126,7 @@ acpi_container_remove(struct acpi_device *device, int type)
return status;
}
-
-static int
-container_device_add(struct acpi_device **device, acpi_handle handle)
+static int container_device_add(struct acpi_device **device, acpi_handle handle)
{
acpi_handle phandle;
struct acpi_device *pdev;
@@ -158,10 +151,9 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
return_VALUE(result);
}
-static void
-container_notify_cb(acpi_handle handle, u32 type, void *context)
+static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = NULL;
int result;
int present;
acpi_status status;
@@ -169,14 +161,14 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
ACPI_FUNCTION_TRACE("container_notify_cb");
present = is_device_present(handle);
-
+
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* Fall through */
case ACPI_NOTIFY_DEVICE_CHECK:
printk("Container driver received %s event\n",
- (type == ACPI_NOTIFY_BUS_CHECK)?
- "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ (type == ACPI_NOTIFY_BUS_CHECK) ?
+ "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
status = acpi_bus_get_device(handle, &device);
if (present) {
if (ACPI_FAILURE(status) || !device) {
@@ -207,15 +199,13 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
static acpi_status
container_walk_namespace_cb(acpi_handle handle,
- u32 lvl,
- void *context,
- void **rv)
+ u32 lvl, void *context, void **rv)
{
- char *hid = NULL;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_device_info *info;
- acpi_status status;
- int *action = context;
+ char *hid = NULL;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_device_info *info;
+ acpi_status status;
+ int *action = context;
ACPI_FUNCTION_TRACE("container_walk_namespace_cb");
@@ -233,66 +223,60 @@ container_walk_namespace_cb(acpi_handle handle,
}
if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
- strcmp(hid, "PNP0A06")) {
+ strcmp(hid, "PNP0A06")) {
goto end;
}
- switch(*action) {
+ switch (*action) {
case INSTALL_NOTIFY_HANDLER:
acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb,
- NULL);
+ ACPI_SYSTEM_NOTIFY,
+ container_notify_cb, NULL);
break;
case UNINSTALL_NOTIFY_HANDLER:
acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb);
+ ACPI_SYSTEM_NOTIFY,
+ container_notify_cb);
break;
default:
break;
}
-end:
+ end:
acpi_os_free(buffer.pointer);
return_ACPI_STATUS(AE_OK);
}
-
-static int __init
-acpi_container_init(void)
+static int __init acpi_container_init(void)
{
- int result = 0;
- int action = INSTALL_NOTIFY_HANDLER;
+ int result = 0;
+ int action = INSTALL_NOTIFY_HANDLER;
result = acpi_bus_register_driver(&acpi_container_driver);
if (result < 0) {
- return(result);
+ return (result);
}
/* register notify handler to every container device */
acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ container_walk_namespace_cb, &action, NULL);
- return(0);
+ return (0);
}
-static void __exit
-acpi_container_exit(void)
+static void __exit acpi_container_exit(void)
{
- int action = UNINSTALL_NOTIFY_HANDLER;
+ int action = UNINSTALL_NOTIFY_HANDLER;
ACPI_FUNCTION_TRACE("acpi_container_exit");
acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ container_walk_namespace_cb, &action, NULL);
acpi_bus_unregister_driver(&acpi_container_driver);
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 2c0dac559f16..263322b7d113 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -12,17 +12,14 @@
#include <acpi/acglobal.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("debug")
-
+ACPI_MODULE_NAME("debug")
#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
-
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
-
#define MODULE_PARAM_PREFIX
-module_param(acpi_dbg_layer, uint, 0400);
+ module_param(acpi_dbg_layer, uint, 0400);
module_param(acpi_dbg_level, uint, 0400);
struct acpi_dlayer {
@@ -35,8 +32,7 @@ struct acpi_dlevel {
};
#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
-static const struct acpi_dlayer acpi_debug_layers[] =
-{
+static const struct acpi_dlayer acpi_debug_layers[] = {
ACPI_DEBUG_INIT(ACPI_UTILITIES),
ACPI_DEBUG_INIT(ACPI_HARDWARE),
ACPI_DEBUG_INIT(ACPI_EVENTS),
@@ -53,8 +49,7 @@ static const struct acpi_dlayer acpi_debug_layers[] =
ACPI_DEBUG_INIT(ACPI_TOOLS),
};
-static const struct acpi_dlevel acpi_debug_levels[] =
-{
+static const struct acpi_dlevel acpi_debug_levels[] = {
ACPI_DEBUG_INIT(ACPI_LV_ERROR),
ACPI_DEBUG_INIT(ACPI_LV_WARN),
ACPI_DEBUG_INIT(ACPI_LV_INIT),
@@ -88,81 +83,77 @@ static const struct acpi_dlevel acpi_debug_levels[] =
ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
- ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
+ ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
};
static int
-acpi_system_read_debug (
- char *page,
- char **start,
- off_t off,
- int count,
- int *eof,
- void *data)
+acpi_system_read_debug(char *page,
+ char **start, off_t off, int count, int *eof, void *data)
{
- char *p = page;
- int size = 0;
- unsigned int i;
+ char *p = page;
+ int size = 0;
+ unsigned int i;
if (off != 0)
goto end;
p += sprintf(p, "%-25s\tHex SET\n", "Description");
- switch ((unsigned long) data) {
+ switch ((unsigned long)data) {
case 0:
for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
- acpi_debug_layers[i].name,
- acpi_debug_layers[i].value,
- (acpi_dbg_layer & acpi_debug_layers[i].value) ?
- '*' : ' ');
+ acpi_debug_layers[i].name,
+ acpi_debug_layers[i].value,
+ (acpi_dbg_layer & acpi_debug_layers[i].
+ value) ? '*' : ' ');
}
p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
- ACPI_ALL_DRIVERS,
- (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
- '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
- ' ' : '-');
+ ACPI_ALL_DRIVERS,
+ (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
+ ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
+ ACPI_ALL_DRIVERS) ==
+ 0 ? ' ' : '-');
p += sprintf(p,
- "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
- acpi_dbg_layer);
+ "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
+ acpi_dbg_layer);
break;
case 1:
for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
- acpi_debug_levels[i].name,
- acpi_debug_levels[i].value,
- (acpi_dbg_level & acpi_debug_levels[i].value) ?
- '*' : ' ');
+ acpi_debug_levels[i].name,
+ acpi_debug_levels[i].value,
+ (acpi_dbg_level & acpi_debug_levels[i].
+ value) ? '*' : ' ');
}
p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
- acpi_dbg_level);
+ acpi_dbg_level);
break;
default:
p += sprintf(p, "Invalid debug option\n");
break;
}
-
-end:
+
+ end:
size = (p - page);
- if (size <= off+count) *eof = 1;
+ if (size <= off + count)
+ *eof = 1;
*start = page + off;
size -= off;
- if (size>count) size = count;
- if (size<0) size = 0;
+ if (size > count)
+ size = count;
+ if (size < 0)
+ size = 0;
return size;
}
-
static int
-acpi_system_write_debug (
- struct file *file,
- const char __user *buffer,
- unsigned long count,
- void *data)
+acpi_system_write_debug(struct file *file,
+ const char __user * buffer,
+ unsigned long count, void *data)
{
- char debug_string[12] = {'\0'};
+ char debug_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_system_write_debug");
@@ -174,7 +165,7 @@ acpi_system_write_debug (
debug_string[count] = '\0';
- switch ((unsigned long) data) {
+ switch ((unsigned long)data) {
case 0:
acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
break;
@@ -190,9 +181,9 @@ acpi_system_write_debug (
static int __init acpi_debug_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
- char * name;
+ char *name;
ACPI_FUNCTION_TRACE("acpi_debug_init");
@@ -201,8 +192,10 @@ static int __init acpi_debug_init(void)
/* 'debug_layer' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
- entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
- acpi_system_read_debug,(void *)0);
+ entry =
+ create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir, acpi_system_read_debug,
+ (void *)0);
if (entry)
entry->write_proc = acpi_system_write_debug;
else
@@ -210,19 +203,21 @@ static int __init acpi_debug_init(void)
/* 'debug_level' [R/W] */
name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
- entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
- acpi_system_read_debug, (void *)1);
- if (entry)
+ entry =
+ create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir, acpi_system_read_debug,
+ (void *)1);
+ if (entry)
entry->write_proc = acpi_system_write_debug;
else
goto Error;
- Done:
+ Done:
return_VALUE(error);
- Error:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n", name));
+ Error:
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n", name));
remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 84193983d6ba..2022aeaecfbb 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
@@ -49,18 +48,14 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsfield")
+ACPI_MODULE_NAME("dsfield")
/* Local prototypes */
-
static acpi_status
-acpi_ds_get_field_names (
- struct acpi_create_field_info *info,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg);
-
+acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg);
/*******************************************************************************
*
@@ -82,41 +77,36 @@ acpi_ds_get_field_names (
******************************************************************************/
acpi_status
-acpi_ds_create_buffer_field (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_buffer_field(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *arg;
- struct acpi_namespace_node *node;
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *second_desc = NULL;
- u32 flags;
-
-
- ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *second_desc = NULL;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ds_create_buffer_field");
/* Get the name_string argument */
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
- arg = acpi_ps_get_arg (op, 3);
- }
- else {
+ arg = acpi_ps_get_arg(op, 3);
+ } else {
/* Create Bit/Byte/Word/Dword field */
- arg = acpi_ps_get_arg (op, 2);
+ arg = acpi_ps_get_arg(op, 2);
}
if (!arg) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
if (walk_state->deferred_node) {
node = walk_state->deferred_node;
status = AE_OK;
- }
- else {
+ } else {
/*
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the size
@@ -124,21 +114,22 @@ acpi_ds_create_buffer_field (
*/
if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
- }
- else {
+ } else {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
- ACPI_NS_ERROR_IF_FOUND;
+ ACPI_NS_ERROR_IF_FOUND;
}
/*
* Enter the name_string into the namespace
*/
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
- flags, walk_state, &(node));
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state,
+ &(node));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
}
@@ -153,9 +144,9 @@ acpi_ds_create_buffer_field (
* and we need to create the field object. Otherwise, this was a lookup
* of an existing node and we don't want to create the field object again.
*/
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -165,7 +156,7 @@ acpi_ds_create_buffer_field (
/* Create the buffer field object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -176,28 +167,26 @@ acpi_ds_create_buffer_field (
* opcode and operands -- since the buffer and index
* operands must be evaluated.
*/
- second_desc = obj_desc->common.next_object;
+ second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data;
second_desc->extra.aml_length = op->named.length;
obj_desc->buffer_field.node = node;
/* Attach constructed field descriptors to parent node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_field_names
@@ -214,17 +203,14 @@ cleanup:
******************************************************************************/
static acpi_status
-acpi_ds_get_field_names (
- struct acpi_create_field_info *info,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg)
+acpi_ds_get_field_names(struct acpi_create_field_info *info,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg)
{
- acpi_status status;
- acpi_integer position;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
+ acpi_status status;
+ acpi_integer position;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info);
/* First field starts at bit zero */
@@ -243,18 +229,16 @@ acpi_ds_get_field_names (
case AML_INT_RESERVEDFIELD_OP:
position = (acpi_integer) info->field_bit_position
- + (acpi_integer) arg->common.value.size;
+ + (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR ((
- "Bit offset within field too large (> 0xFFFFFFFF)\n"));
- return_ACPI_STATUS (AE_SUPPORT);
+ ACPI_REPORT_ERROR(("Bit offset within field too large (> 0xFFFFFFFF)\n"));
+ return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position = (u32) position;
break;
-
case AML_INT_ACCESSFIELD_OP:
/*
@@ -266,73 +250,70 @@ acpi_ds_get_field_names (
* ACCESS_TYPE bits
*/
info->field_flags = (u8)
- ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
- ((u8) ((u32) arg->common.value.integer >> 8)));
+ ((info->
+ field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
+ ((u8) ((u32) arg->common.value.integer >> 8)));
info->attribute = (u8) (arg->common.value.integer);
break;
-
case AML_INT_NAMEDFIELD_OP:
/* Lookup the name */
- status = acpi_ns_lookup (walk_state->scope_info,
- (char *) &arg->named.name,
- info->field_type, ACPI_IMODE_EXECUTE,
- ACPI_NS_DONT_OPEN_SCOPE,
- walk_state, &info->field_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ (char *)&arg->named.name,
+ info->field_type,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state, &info->field_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Already exists, ignore error */
- }
- else {
+ } else {
arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size;
/* Create and initialize an object for the new Field Node */
- status = acpi_ex_prep_field_value (info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_prep_field_value(info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Keep track of bit position for the next field */
position = (acpi_integer) info->field_bit_position
- + (acpi_integer) arg->common.value.size;
+ + (acpi_integer) arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
- ACPI_REPORT_ERROR ((
- "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
- (char *) &info->field_node->name));
- return_ACPI_STATUS (AE_SUPPORT);
+ ACPI_REPORT_ERROR(("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", (char *)&info->field_node->name));
+ return_ACPI_STATUS(AE_SUPPORT);
}
info->field_bit_position += info->field_bit_length;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid opcode in field list: %X\n",
- arg->common.aml_opcode));
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid opcode in field list: %X\n",
+ arg->common.aml_opcode));
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg = arg->common.next;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_field
@@ -348,29 +329,28 @@ acpi_ds_get_field_names (
******************************************************************************/
acpi_status
-acpi_ds_create_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_field", op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
- ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.name, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.name, ACPI_TYPE_REGION,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &region_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ return_ACPI_STATUS(status);
}
}
@@ -385,12 +365,11 @@ acpi_ds_create_field (
info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_field_objects
@@ -407,37 +386,34 @@ acpi_ds_create_field (
******************************************************************************/
acpi_status
-acpi_ds_init_field_objects (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_init_field_objects(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg = NULL;
- struct acpi_namespace_node *node;
- u8 type = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
+ acpi_status status;
+ union acpi_parse_object *arg = NULL;
+ struct acpi_namespace_node *node;
+ u8 type = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op);
switch (walk_state->opcode) {
case AML_FIELD_OP:
- arg = acpi_ps_get_arg (op, 2);
+ arg = acpi_ps_get_arg(op, 2);
type = ACPI_TYPE_LOCAL_REGION_FIELD;
break;
case AML_BANK_FIELD_OP:
- arg = acpi_ps_get_arg (op, 4);
+ arg = acpi_ps_get_arg(op, 4);
type = ACPI_TYPE_LOCAL_BANK_FIELD;
break;
case AML_INDEX_FIELD_OP:
- arg = acpi_ps_get_arg (op, 3);
+ arg = acpi_ps_get_arg(op, 3);
type = ACPI_TYPE_LOCAL_INDEX_FIELD;
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -447,16 +423,18 @@ acpi_ds_init_field_objects (
/* Ignore OFFSET and ACCESSAS terms here */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
- status = acpi_ns_lookup (walk_state->scope_info,
- (char *) &arg->named.name,
- type, ACPI_IMODE_LOAD_PASS1,
- ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
- ACPI_NS_ERROR_IF_FOUND,
- walk_state, &node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ (char *)&arg->named.name,
+ type, ACPI_IMODE_LOAD_PASS1,
+ ACPI_NS_NO_UPSEARCH |
+ ACPI_NS_DONT_OPEN_SCOPE |
+ ACPI_NS_ERROR_IF_FOUND,
+ walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR((char *)&arg->named.name,
+ status);
if (status != AE_ALREADY_EXISTS) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Name already exists, just ignore this error */
@@ -472,10 +450,9 @@ acpi_ds_init_field_objects (
arg = arg->common.next;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_bank_field
@@ -491,41 +468,42 @@ acpi_ds_init_field_objects (
******************************************************************************/
acpi_status
-acpi_ds_create_bank_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_bank_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op);
/* First arg is the name of the parent op_region (must already exist) */
arg = op->common.value.arg;
if (!region_node) {
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
- ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.name, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.name, ACPI_TYPE_REGION,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &region_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.name, status);
+ return_ACPI_STATUS(status);
}
}
/* Second arg is the Bank Register (Field) (must already exist) */
arg = arg->common.next;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Third arg is the bank_value */
@@ -543,12 +521,11 @@ acpi_ds_create_bank_field (
info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_index_field
@@ -564,39 +541,40 @@ acpi_ds_create_bank_field (
******************************************************************************/
acpi_status
-acpi_ds_create_index_field (
- union acpi_parse_object *op,
- struct acpi_namespace_node *region_node,
- struct acpi_walk_state *walk_state)
+acpi_ds_create_index_field(union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_parse_object *arg;
- struct acpi_create_field_info info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op);
/* First arg is the name of the Index register (must already exist) */
arg = op->common.value.arg;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Second arg is the data register (must already exist) */
arg = arg->common.next;
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &info.data_register_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
+ return_ACPI_STATUS(status);
}
/* Next arg is the field flags */
@@ -609,9 +587,7 @@ acpi_ds_create_index_field (
info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
info.region_node = region_node;
- status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+ status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index d7790db50178..8693c704aea6 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -41,23 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsinit")
+ACPI_MODULE_NAME("dsinit")
/* Local prototypes */
-
static acpi_status
-acpi_ds_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
-
+acpi_ds_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
/*******************************************************************************
*
@@ -80,26 +74,23 @@ acpi_ds_init_one_object (
******************************************************************************/
static acpi_status
-acpi_ds_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ds_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- acpi_object_type type;
- acpi_status status;
- struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
-
-
- ACPI_FUNCTION_NAME ("ds_init_one_object");
+ struct acpi_init_walk_info *info =
+ (struct acpi_init_walk_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ acpi_object_type type;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ds_init_one_object");
/*
- * We are only interested in objects owned by the table that
+ * We are only interested in NS nodes owned by the table that
* was just loaded
*/
- if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
- info->table_desc->table_id) {
+ if (node->owner_id != info->table_desc->owner_id) {
return (AE_OK);
}
@@ -107,33 +98,31 @@ acpi_ds_init_one_object (
/* And even then, we are only interested in a few object types */
- type = acpi_ns_get_type (obj_handle);
+ type = acpi_ns_get_type(obj_handle);
switch (type) {
case ACPI_TYPE_REGION:
- status = acpi_ds_initialize_region (obj_handle);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Region %p [%4.4s] - Init failure, %s\n",
- obj_handle, acpi_ut_get_node_name (obj_handle),
- acpi_format_exception (status)));
+ status = acpi_ds_initialize_region(obj_handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region %p [%4.4s] - Init failure, %s\n",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle),
+ acpi_format_exception(status)));
}
info->op_region_count++;
break;
-
case ACPI_TYPE_METHOD:
- info->method_count++;
-
/*
* Print a dot for each method unless we are going to print
* the entire pathname
*/
if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
/*
@@ -143,41 +132,32 @@ acpi_ds_init_one_object (
* on a per-table basis. Currently, we just use a global for the width.
*/
if (info->table_desc->pointer->revision == 1) {
- ((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
+ node->flags |= ANOBJ_DATA_WIDTH_32;
}
/*
* Always parse methods to detect errors, we will delete
* the parse tree below
*/
- status = acpi_ds_parse_method (obj_handle);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Method %p [%4.4s] - parse failure, %s\n",
- obj_handle, acpi_ut_get_node_name (obj_handle),
- acpi_format_exception (status)));
+ status = acpi_ds_parse_method(obj_handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\n+Method %p [%4.4s] - parse failure, %s\n",
+ obj_handle,
+ acpi_ut_get_node_name(obj_handle),
+ acpi_format_exception(status)));
/* This parse failed, but we will continue parsing more methods */
-
- break;
}
- /*
- * Delete the parse tree. We simply re-parse the method
- * for every execution since there isn't much overhead
- */
- acpi_ns_delete_namespace_subtree (obj_handle);
- acpi_ns_delete_namespace_by_owner (
- ((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
+ info->method_count++;
break;
-
case ACPI_TYPE_DEVICE:
info->device_count++;
break;
-
default:
break;
}
@@ -189,7 +169,6 @@ acpi_ds_init_one_object (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_objects
@@ -205,45 +184,43 @@ acpi_ds_init_one_object (
******************************************************************************/
acpi_status
-acpi_ds_initialize_objects (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *start_node)
+acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
+ struct acpi_namespace_node * start_node)
{
- acpi_status status;
- struct acpi_init_walk_info info;
+ acpi_status status;
+ struct acpi_init_walk_info info;
+ ACPI_FUNCTION_TRACE("ds_initialize_objects");
- ACPI_FUNCTION_TRACE ("ds_initialize_objects");
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "**** Starting initialization of namespace objects ****\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:"));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "**** Starting initialization of namespace objects ****\n"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));
-
- info.method_count = 0;
+ info.method_count = 0;
info.op_region_count = 0;
- info.object_count = 0;
- info.device_count = 0;
- info.table_desc = table_desc;
+ info.object_count = 0;
+ info.device_count = 0;
+ info.table_desc = table_desc;
/* Walk entire namespace from the supplied root */
- status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
- acpi_ds_init_one_object, &info, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
+ acpi_ds_init_one_object, &info, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
- table_desc->pointer->signature, table_desc->table_id, info.object_count,
- info.device_count, info.method_count, info.op_region_count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
+ table_desc->pointer->signature,
+ table_desc->owner_id, info.object_count,
+ info.device_count, info.method_count,
+ info.op_region_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Methods, %hd Regions\n", info.method_count,
+ info.op_region_count));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 9fc3f4c033eb..36c1ca0b9adb 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -49,67 +48,57 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsmethod")
-
+ACPI_MODULE_NAME("dsmethod")
/*******************************************************************************
*
* FUNCTION: acpi_ds_parse_method
*
- * PARAMETERS: obj_handle - Method node
+ * PARAMETERS: Node - Method node
*
* RETURN: Status
*
- * DESCRIPTION: Call the parser and parse the AML that is associated with the
- * method.
+ * DESCRIPTION: Parse the AML that is associated with the method.
*
* MUTEX: Assumes parser is locked
*
******************************************************************************/
-
-acpi_status
-acpi_ds_parse_method (
- acpi_handle obj_handle)
+acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_owner_id owner_id;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
/* Parameter Validation */
- if (!obj_handle) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ if (!node) {
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
- acpi_ut_get_node_name (obj_handle), obj_handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Parsing [%4.4s] **** named_obj=%p\n",
+ acpi_ut_get_node_name(node), node));
/* Extract the method object from the method Node */
- node = (struct acpi_namespace_node *) obj_handle;
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Create a mutex for the method if there is a concurrency limit */
if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
- (!obj_desc->method.semaphore)) {
- status = acpi_os_create_semaphore (obj_desc->method.concurrency,
- obj_desc->method.concurrency,
- &obj_desc->method.semaphore);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ (!obj_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore(obj_desc->method.concurrency,
+ obj_desc->method.concurrency,
+ &obj_desc->method.semaphore);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -117,14 +106,14 @@ acpi_ds_parse_method (
* Allocate a new parser op to be the root of the parsed
* method tree
*/
- op = acpi_ps_alloc_op (AML_METHOD_OP);
+ op = acpi_ps_alloc_op(AML_METHOD_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init new op with the method name and pointer back to the Node */
- acpi_ps_set_name (op, node->name.integer);
+ acpi_ps_set_name(op, node->name.integer);
op->common.node = node;
/*
@@ -132,22 +121,27 @@ acpi_ds_parse_method (
* objects (such as Operation Regions) can be created during the
* first pass parse.
*/
- owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
- obj_desc->method.owning_id = owner_id;
+ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
/* Create and initialize a new walk state */
- walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
+ walk_state =
+ acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
+ NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup2;
}
- status = acpi_ds_init_aml_walk (walk_state, op, node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup2;
}
/*
@@ -159,19 +153,30 @@ acpi_ds_parse_method (
* method so that operands to the named objects can take on dynamic
* run-time values.
*/
- status = acpi_ps_parse_aml (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ps_parse_aml(walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup2;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
- acpi_ut_get_node_name (obj_handle), obj_handle, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+ acpi_ut_get_node_name(node), node, op));
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
-}
+ /*
+ * Delete the parse tree. We simply re-parse the method for every
+ * execution since there isn't much overhead (compared to keeping lots
+ * of parse trees around)
+ */
+ acpi_ns_delete_namespace_subtree(node);
+ acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
+
+ cleanup2:
+ acpi_ut_release_owner_id(&obj_desc->method.owner_id);
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -190,19 +195,23 @@ acpi_ds_parse_method (
******************************************************************************/
acpi_status
-acpi_ds_begin_method_execution (
- struct acpi_namespace_node *method_node,
- union acpi_operand_object *obj_desc,
- struct acpi_namespace_node *calling_method_node)
+acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
+ union acpi_operand_object *obj_desc,
+ struct acpi_namespace_node *calling_method_node)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node);
- ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node);
+ if (!method_node) {
+ return_ACPI_STATUS(AE_NULL_ENTRY);
+ }
+ /* Prevent wraparound of thread count */
- if (!method_node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {
+ ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n"));
+ return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
/*
@@ -219,8 +228,9 @@ acpi_ds_begin_method_execution (
* thread that is making recursive method calls.
*/
if (method_node == calling_method_node) {
- if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
- return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
+ if (obj_desc->method.thread_count >=
+ obj_desc->method.concurrency) {
+ return_ACPI_STATUS(AE_AML_METHOD_LIMIT);
}
}
@@ -228,8 +238,21 @@ acpi_ds_begin_method_execution (
* Get a unit from the method semaphore. This releases the
* interpreter if we block
*/
- status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
- ACPI_WAIT_FOREVER);
+ status =
+ acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
+ ACPI_WAIT_FOREVER);
+ }
+
+ /*
+ * Allocate an Owner ID for this method, only if this is the first thread
+ * to begin concurrent execution. We only need one owner_id, even if the
+ * method is invoked recursively.
+ */
+ if (!obj_desc->method.owner_id) {
+ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
}
/*
@@ -237,10 +260,9 @@ acpi_ds_begin_method_execution (
* reentered one more time (even if it is the same thread)
*/
obj_desc->method.thread_count++;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_call_control_method
@@ -256,101 +278,99 @@ acpi_ds_begin_method_execution (
******************************************************************************/
acpi_status
-acpi_ds_call_control_method (
- struct acpi_thread_state *thread,
- struct acpi_walk_state *this_walk_state,
- union acpi_parse_object *op)
+acpi_ds_call_control_method(struct acpi_thread_state *thread,
+ struct acpi_walk_state *this_walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- struct acpi_namespace_node *method_node;
- struct acpi_walk_state *next_walk_state;
- union acpi_operand_object *obj_desc;
- struct acpi_parameter_info info;
- u32 i;
-
+ acpi_status status;
+ struct acpi_namespace_node *method_node;
+ struct acpi_walk_state *next_walk_state = NULL;
+ union acpi_operand_object *obj_desc;
+ struct acpi_parameter_info info;
+ u32 i;
- ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state);
+ ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state);
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
- this_walk_state->prev_op, this_walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Execute method %p, currentstate=%p\n",
+ this_walk_state->prev_op, this_walk_state));
/*
* Get the namespace entry for the control method we are about to call
*/
method_node = this_walk_state->method_call_node;
if (!method_node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
- obj_desc = acpi_ns_get_attached_object (method_node);
+ obj_desc = acpi_ns_get_attached_object(method_node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
- obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
-
/* Init for new method, wait on concurrency semaphore */
- status = acpi_ds_begin_method_execution (method_node, obj_desc,
- this_walk_state->method_node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_begin_method_execution(method_node, obj_desc,
+ this_walk_state->method_node);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
/* 1) Parse: Create a new walk state for the preempting walk */
- next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- op, obj_desc, NULL);
+ next_walk_state =
+ acpi_ds_create_walk_state(obj_desc->method.owner_id, op,
+ obj_desc, NULL);
if (!next_walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Create and init a Root Node */
- op = acpi_ps_create_scope_op ();
+ op = acpi_ps_create_scope_op();
if (!op) {
status = AE_NO_MEMORY;
goto cleanup;
}
- status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
- obj_desc->method.aml_start, obj_desc->method.aml_length,
- NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (next_walk_state);
+ status = acpi_ds_init_aml_walk(next_walk_state, op, method_node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length,
+ NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(next_walk_state);
goto cleanup;
}
/* Begin AML parse */
- status = acpi_ps_parse_aml (next_walk_state);
- acpi_ps_delete_parse_tree (op);
+ status = acpi_ps_parse_aml(next_walk_state);
+ acpi_ps_delete_parse_tree(op);
}
/* 2) Execute: Create a new state for the preempting walk */
- next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- NULL, obj_desc, thread);
+ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
+ NULL, obj_desc, thread);
if (!next_walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
}
/*
* The resolved arguments were put on the previous walk state's operand
- * stack. Operands on the previous walk state stack always
- * start at index 0.
- * Null terminate the list of arguments
+ * stack. Operands on the previous walk state stack always
+ * start at index 0. Also, null terminate the list of arguments
*/
- this_walk_state->operands [this_walk_state->num_operands] = NULL;
+ this_walk_state->operands[this_walk_state->num_operands] = NULL;
info.parameters = &this_walk_state->operands[0];
info.parameter_type = ACPI_PARAM_ARGS;
- status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
- obj_desc->method.aml_start, obj_desc->method.aml_length,
- &info, 3);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, &info, 3);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -359,38 +379,37 @@ acpi_ds_call_control_method (
* (they were copied to new objects)
*/
for (i = 0; i < obj_desc->method.param_count; i++) {
- acpi_ut_remove_reference (this_walk_state->operands [i]);
- this_walk_state->operands [i] = NULL;
+ acpi_ut_remove_reference(this_walk_state->operands[i]);
+ this_walk_state->operands[i] = NULL;
}
/* Clear the operand stack */
this_walk_state->num_operands = 0;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Starting nested execution, newstate=%p\n", next_walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Starting nested execution, newstate=%p\n",
+ next_walk_state));
if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
- status = obj_desc->method.implementation (next_walk_state);
- return_ACPI_STATUS (status);
+ status = obj_desc->method.implementation(next_walk_state);
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(status);
- /* On error, we must delete the new walk state */
+ cleanup:
+ /* Decrement the thread count on the method parse tree */
-cleanup:
if (next_walk_state && (next_walk_state->method_desc)) {
- /* Decrement the thread count on the method parse tree */
-
- next_walk_state->method_desc->method.thread_count--;
+ next_walk_state->method_desc->method.thread_count--;
}
- (void) acpi_ds_terminate_control_method (next_walk_state);
- acpi_ds_delete_walk_state (next_walk_state);
- return_ACPI_STATUS (status);
-}
+ /* On error, we must delete the new walk state */
+
+ acpi_ds_terminate_control_method(next_walk_state);
+ acpi_ds_delete_walk_state(next_walk_state);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -407,25 +426,22 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ds_restart_control_method (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *return_desc)
+acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *return_desc)
{
- acpi_status status;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state);
- ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+ (char *)&walk_state->method_node->name,
+ walk_state->method_call_op, return_desc));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
- (char *) &walk_state->method_node->name, walk_state->method_call_op,
- return_desc));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- " return_from_this_method_used?=%X res_stack %p Walk %p\n",
- walk_state->return_used,
- walk_state->results, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ " return_from_this_method_used?=%X res_stack %p Walk %p\n",
+ walk_state->return_used,
+ walk_state->results, walk_state));
/* Did the called method return a value? */
@@ -435,10 +451,10 @@ acpi_ds_restart_control_method (
if (walk_state->return_used) {
/* Save the return value from the previous method */
- status = acpi_ds_result_push (return_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
- return_ACPI_STATUS (status);
+ status = acpi_ds_result_push(return_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
+ return_ACPI_STATUS(status);
}
/*
@@ -456,26 +472,26 @@ acpi_ds_restart_control_method (
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
- else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) {
+ else if (!acpi_ds_do_implicit_return
+ (return_desc, walk_state, FALSE)) {
/*
* Delete the return value if it will not be used by the
* calling method
*/
- acpi_ut_remove_reference (return_desc);
+ acpi_ut_remove_reference(return_desc);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_terminate_control_method
*
* PARAMETERS: walk_state - State of the method
*
- * RETURN: Status
+ * RETURN: None
*
* DESCRIPTION: Terminate a control method. Delete everything that the method
* created, delete all locals and arguments, and delete the parse
@@ -483,63 +499,59 @@ acpi_ds_restart_control_method (
*
******************************************************************************/
-acpi_status
-acpi_ds_terminate_control_method (
- struct acpi_walk_state *walk_state)
+void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *method_node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state);
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *method_node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state);
if (!walk_state) {
- return (AE_BAD_PARAMETER);
+ return_VOID;
}
/* The current method object was saved in the walk state */
obj_desc = walk_state->method_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_OK);
+ return_VOID;
}
/* Delete all arguments and locals */
- acpi_ds_method_data_delete_all (walk_state);
+ acpi_ds_method_data_delete_all(walk_state);
/*
* Lock the parser while we terminate this method.
* If this is the last thread executing the method,
* we have additional cleanup to perform
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER);
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
}
/* Signal completion of the execution of this method if necessary */
if (walk_state->method_desc->method.semaphore) {
- status = acpi_os_signal_semaphore (
- walk_state->method_desc->method.semaphore, 1);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
- status = AE_OK;
+ status =
+ acpi_os_signal_semaphore(walk_state->method_desc->method.
+ semaphore, 1);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not signal method semaphore\n"));
/* Ignore error and continue cleanup */
}
}
if (walk_state->method_desc->method.thread_count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "*** Not deleting method namespace, there are still %d threads\n",
- walk_state->method_desc->method.thread_count));
- }
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "*** Not deleting method namespace, there are still %d threads\n",
+ walk_state->method_desc->method.
+ thread_count));
+ } else { /* This is the last executing thread */
- if (!walk_state->method_desc->method.thread_count) {
/*
* Support to dynamically change a method from not_serialized to
* Serialized if it appears that the method is written foolishly and
@@ -551,10 +563,11 @@ acpi_ds_terminate_control_method (
* before creating the synchronization semaphore.
*/
if ((walk_state->method_desc->method.concurrency == 1) &&
- (!walk_state->method_desc->method.semaphore)) {
- status = acpi_os_create_semaphore (1,
- 1,
- &walk_state->method_desc->method.semaphore);
+ (!walk_state->method_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore(1, 1,
+ &walk_state->
+ method_desc->method.
+ semaphore);
}
/*
@@ -569,28 +582,27 @@ acpi_ds_terminate_control_method (
* Delete any namespace entries created immediately underneath
* the method
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
}
if (method_node->child) {
- acpi_ns_delete_namespace_subtree (method_node);
+ acpi_ns_delete_namespace_subtree(method_node);
}
/*
* Delete any namespace entries created anywhere else within
* the namespace
*/
- acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
+ method.owner_id);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ acpi_ut_release_owner_id(&walk_state->method_desc->method.
+ owner_id);
}
- status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
- return_ACPI_STATUS (status);
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
+ return_VOID;
}
-
-
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index f7998306f756..4095ce70982b 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -41,41 +41,32 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsmthdat")
+ACPI_MODULE_NAME("dsmthdat")
/* Local prototypes */
-
static void
-acpi_ds_method_data_delete_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_delete_value(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state);
static acpi_status
-acpi_ds_method_data_set_value (
- u16 opcode,
- u32 index,
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_set_value(u16 opcode,
+ u32 index,
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state);
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_object_type
-acpi_ds_method_data_get_type (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_method_data_get_type(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init
@@ -97,45 +88,41 @@ acpi_ds_method_data_get_type (
*
******************************************************************************/
-void
-acpi_ds_method_data_init (
- struct acpi_walk_state *walk_state)
+void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_init");
+ u32 i;
+ ACPI_FUNCTION_TRACE("ds_method_data_init");
/* Init the method arguments */
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
- ACPI_MOVE_32_TO_32 (&walk_state->arguments[i].name,
+ ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
NAMEOF_ARG_NTE);
walk_state->arguments[i].name.integer |= (i << 24);
- walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
- walk_state->arguments[i].type = ACPI_TYPE_ANY;
- walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST |
- ANOBJ_METHOD_ARG;
+ walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
+ walk_state->arguments[i].type = ACPI_TYPE_ANY;
+ walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST |
+ ANOBJ_METHOD_ARG;
}
/* Init the method locals */
for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
- ACPI_MOVE_32_TO_32 (&walk_state->local_variables[i].name,
+ ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
NAMEOF_LOCAL_NTE);
walk_state->local_variables[i].name.integer |= (i << 24);
- walk_state->local_variables[i].descriptor = ACPI_DESC_TYPE_NAMED;
- walk_state->local_variables[i].type = ACPI_TYPE_ANY;
- walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST |
- ANOBJ_METHOD_LOCAL;
+ walk_state->local_variables[i].descriptor =
+ ACPI_DESC_TYPE_NAMED;
+ walk_state->local_variables[i].type = ACPI_TYPE_ANY;
+ walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST |
+ ANOBJ_METHOD_LOCAL;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_all
@@ -149,26 +136,25 @@ acpi_ds_method_data_init (
*
******************************************************************************/
-void
-acpi_ds_method_data_delete_all (
- struct acpi_walk_state *walk_state)
+void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
{
- u32 index;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_delete_all");
+ u32 index;
+ ACPI_FUNCTION_TRACE("ds_method_data_delete_all");
/* Detach the locals */
for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
if (walk_state->local_variables[index].object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
- index, walk_state->local_variables[index].object));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
+ index,
+ walk_state->local_variables[index].
+ object));
/* Detach object (if present) and remove a reference */
- acpi_ns_detach_object (&walk_state->local_variables[index]);
+ acpi_ns_detach_object(&walk_state->
+ local_variables[index]);
}
}
@@ -176,19 +162,19 @@ acpi_ds_method_data_delete_all (
for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
if (walk_state->arguments[index].object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
- index, walk_state->arguments[index].object));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
+ index,
+ walk_state->arguments[index].object));
/* Detach object (if present) and remove a reference */
- acpi_ns_detach_object (&walk_state->arguments[index]);
+ acpi_ns_detach_object(&walk_state->arguments[index]);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_init_args
@@ -206,47 +192,44 @@ acpi_ds_method_data_delete_all (
******************************************************************************/
acpi_status
-acpi_ds_method_data_init_args (
- union acpi_operand_object **params,
- u32 max_param_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_init_args(union acpi_operand_object **params,
+ u32 max_param_count,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- u32 index = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_method_data_init_args", params);
+ acpi_status status;
+ u32 index = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params);
if (!params) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n"));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "No param list passed to method\n"));
+ return_ACPI_STATUS(AE_OK);
}
/* Copy passed parameters into the new method stack frame */
while ((index < ACPI_METHOD_NUM_ARGS) &&
- (index < max_param_count) &&
- params[index]) {
+ (index < max_param_count) && params[index]) {
/*
* A valid parameter.
* Store the argument in the method/walk descriptor.
* Do not copy the arg in order to implement call by reference
*/
- status = acpi_ds_method_data_set_value (AML_ARG_OP, index,
- params[index], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_set_value(AML_ARG_OP, index,
+ params[index],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
index++;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", index));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%d args passed to method\n", index));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_node
@@ -263,14 +246,12 @@ acpi_ds_method_data_init_args (
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_node (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **node)
+acpi_ds_method_data_get_node(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **node)
{
- ACPI_FUNCTION_TRACE ("ds_method_data_get_node");
-
+ ACPI_FUNCTION_TRACE("ds_method_data_get_node");
/*
* Method Locals and Arguments are supported
@@ -279,10 +260,10 @@ acpi_ds_method_data_get_node (
case AML_LOCAL_OP:
if (index > ACPI_METHOD_MAX_LOCAL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Local index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_LOCAL));
- return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Local index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_LOCAL));
+ return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
@@ -293,10 +274,10 @@ acpi_ds_method_data_get_node (
case AML_ARG_OP:
if (index > ACPI_METHOD_MAX_ARG) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Arg index %d is invalid (max %d)\n",
- index, ACPI_METHOD_MAX_ARG));
- return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Arg index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_ARG));
+ return_ACPI_STATUS(AE_AML_INVALID_INDEX);
}
/* Return a pointer to the pseudo-node */
@@ -305,14 +286,14 @@ acpi_ds_method_data_get_node (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode));
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Opcode %d is invalid\n",
+ opcode));
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_set_value
@@ -330,29 +311,26 @@ acpi_ds_method_data_get_node (
******************************************************************************/
static acpi_status
-acpi_ds_method_data_set_value (
- u16 opcode,
- u32 index,
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_set_value(u16 opcode,
+ u32 index,
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE ("ds_method_data_set_value");
+ ACPI_FUNCTION_TRACE("ds_method_data_set_value");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
- opcode, object->common.reference_count,
- acpi_ut_get_type_name (object->common.type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
+ opcode, object->common.reference_count,
+ acpi_ut_get_type_name(object->common.type)));
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -361,15 +339,14 @@ acpi_ds_method_data_set_value (
* reference semantics of ACPI Control Method invocation.
* (See ACPI specification 2.0_c)
*/
- acpi_ut_add_reference (object);
+ acpi_ut_add_reference(object);
/* Install the object */
node->object = object;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_get_value
@@ -387,32 +364,30 @@ acpi_ds_method_data_set_value (
******************************************************************************/
acpi_status
-acpi_ds_method_data_get_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **dest_desc)
+acpi_ds_method_data_get_value(u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object **dest_desc)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_get_value");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_get_value");
/* Validate the object descriptor */
if (!dest_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null object descriptor pointer\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the object from the node */
@@ -433,9 +408,10 @@ acpi_ds_method_data_get_value (
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
if (acpi_gbl_enable_interpreter_slack) {
- object = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ object =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!object) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
object->integer.value = 0;
@@ -444,27 +420,29 @@ acpi_ds_method_data_get_value (
/* Otherwise, return the error */
- else switch (opcode) {
- case AML_ARG_OP:
+ else
+ switch (opcode) {
+ case AML_ARG_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Uninitialized Arg[%d] at node %p\n",
- index, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Uninitialized Arg[%d] at node %p\n",
+ index, node));
- return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
+ return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
- case AML_LOCAL_OP:
+ case AML_LOCAL_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Uninitialized Local[%d] at node %p\n",
- index, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Uninitialized Local[%d] at node %p\n",
+ index, node));
- return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
+ return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
- default:
- ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
- }
+ default:
+ ACPI_REPORT_ERROR(("Not Arg/Local opcode: %X\n",
+ opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
+ }
}
/*
@@ -472,12 +450,11 @@ acpi_ds_method_data_get_value (
* Return an additional reference to the object
*/
*dest_desc = object;
- acpi_ut_add_reference (object);
+ acpi_ut_add_reference(object);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_method_data_delete_value
@@ -494,29 +471,25 @@ acpi_ds_method_data_get_value (
******************************************************************************/
static void
-acpi_ds_method_data_delete_value (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_delete_value(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_delete_value");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_delete_value");
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Get the associated object */
- object = acpi_ns_get_attached_object (node);
+ object = acpi_ns_get_attached_object(node);
/*
* Undefine the Arg or Local by setting its descriptor
@@ -526,19 +499,18 @@ acpi_ds_method_data_delete_value (
node->object = NULL;
if ((object) &&
- (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) {
+ (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
/*
* There is a valid object.
* Decrement the reference count by one to balance the
* increment when the object was stored.
*/
- acpi_ut_remove_reference (object);
+ acpi_ut_remove_reference(object);
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_store_object_to_local
@@ -557,40 +529,38 @@ acpi_ds_method_data_delete_value (
******************************************************************************/
acpi_status
-acpi_ds_store_object_to_local (
- u16 opcode,
- u32 index,
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ds_store_object_to_local(u16 opcode,
+ u32 index,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *current_obj_desc;
- union acpi_operand_object *new_obj_desc;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *current_obj_desc;
+ union acpi_operand_object *new_obj_desc;
- ACPI_FUNCTION_TRACE ("ds_store_object_to_local");
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
- opcode, index, obj_desc));
+ ACPI_FUNCTION_TRACE("ds_store_object_to_local");
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
+ opcode, index, obj_desc));
/* Parameter validation */
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- current_obj_desc = acpi_ns_get_attached_object (node);
+ current_obj_desc = acpi_ns_get_attached_object(node);
if (current_obj_desc == obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
- obj_desc));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
+ obj_desc));
+ return_ACPI_STATUS(status);
}
/*
@@ -602,9 +572,11 @@ acpi_ds_store_object_to_local (
*/
new_obj_desc = obj_desc;
if (obj_desc->common.reference_count > 1) {
- status = acpi_ut_copy_iobject_to_iobject (obj_desc, &new_obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -633,42 +605,39 @@ acpi_ds_store_object_to_local (
*/
if (opcode == AML_ARG_OP) {
/*
- * Make sure that the object is the correct type. This may be
- * overkill, butit is here because references were NS nodes in
- * the past. Now they are operand objects of type Reference.
- */
- if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_REPORT_ERROR ((
- "Invalid descriptor type while storing to method arg: [%s]\n",
- acpi_ut_get_descriptor_name (current_obj_desc)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
- }
-
- /*
* If we have a valid reference object that came from ref_of(),
* do the indirect store
*/
- if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (current_obj_desc->reference.opcode == AML_REF_OF_OP)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Arg (%p) is an obj_ref(Node), storing in node %p\n",
- new_obj_desc, current_obj_desc));
+ if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (current_obj_desc->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (current_obj_desc->reference.opcode ==
+ AML_REF_OF_OP)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Arg (%p) is an obj_ref(Node), storing in node %p\n",
+ new_obj_desc,
+ current_obj_desc));
/*
* Store this object to the Node (perform the indirect store)
* NOTE: No implicit conversion is performed, as per the ACPI
* specification rules on storing to Locals/Args.
*/
- status = acpi_ex_store_object_to_node (new_obj_desc,
- current_obj_desc->reference.object, walk_state,
- ACPI_NO_IMPLICIT_CONVERSION);
+ status =
+ acpi_ex_store_object_to_node(new_obj_desc,
+ current_obj_desc->
+ reference.
+ object,
+ walk_state,
+ ACPI_NO_IMPLICIT_CONVERSION);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
- acpi_ut_remove_reference (new_obj_desc);
+ acpi_ut_remove_reference(new_obj_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
}
@@ -676,7 +645,7 @@ acpi_ds_store_object_to_local (
* Delete the existing object
* before storing the new one
*/
- acpi_ds_method_data_delete_value (opcode, index, walk_state);
+ acpi_ds_method_data_delete_value(opcode, index, walk_state);
}
/*
@@ -684,18 +653,19 @@ acpi_ds_store_object_to_local (
* the descriptor for the Arg or Local.
* (increments the object reference count by one)
*/
- status = acpi_ds_method_data_set_value (opcode, index, new_obj_desc, walk_state);
+ status =
+ acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
+ walk_state);
/* Remove local reference if we copied the object above */
if (new_obj_desc != obj_desc) {
- acpi_ut_remove_reference (new_obj_desc);
+ acpi_ut_remove_reference(new_obj_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -712,39 +682,33 @@ acpi_ds_store_object_to_local (
******************************************************************************/
acpi_object_type
-acpi_ds_method_data_get_type (
- u16 opcode,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_method_data_get_type(u16 opcode,
+ u32 index, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- union acpi_operand_object *object;
-
-
- ACPI_FUNCTION_TRACE ("ds_method_data_get_type");
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ds_method_data_get_type");
/* Get the namespace node for the arg/local */
- status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_VALUE ((ACPI_TYPE_NOT_FOUND));
+ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
+ if (ACPI_FAILURE(status)) {
+ return_VALUE((ACPI_TYPE_NOT_FOUND));
}
/* Get the object */
- object = acpi_ns_get_attached_object (node);
+ object = acpi_ns_get_attached_object(node);
if (!object) {
/* Uninitialized local/arg, return TYPE_ANY */
- return_VALUE (ACPI_TYPE_ANY);
+ return_VALUE(ACPI_TYPE_ANY);
}
/* Get the object type */
- return_VALUE (ACPI_GET_OBJECT_TYPE (object));
+ return_VALUE(ACPI_GET_OBJECT_TYPE(object));
}
#endif
-
-
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index bfbae4e4c667..8ac0cd93adb5 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -50,14 +49,12 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsobject")
+ACPI_MODULE_NAME("dsobject")
static acpi_status
-acpi_ds_build_internal_object (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object **obj_desc_ptr);
-
+acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object **obj_desc_ptr);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -76,17 +73,14 @@ acpi_ds_build_internal_object (
******************************************************************************/
static acpi_status
-acpi_ds_build_internal_object (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_object");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ds_build_internal_object");
*obj_desc_ptr = NULL;
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -96,40 +90,44 @@ acpi_ds_build_internal_object (
* Otherwise, go ahead and look it up now
*/
if (!op->common.node) {
- status = acpi_ns_lookup (walk_state->scope_info,
- op->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- NULL,
- (struct acpi_namespace_node **) &(op->common.node));
-
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (op->common.value.string, status);
- return_ACPI_STATUS (status);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ op->common.value.string,
+ ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, NULL,
+ (struct acpi_namespace_node **)
+ &(op->common.node));
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(op->common.value.string,
+ status);
+ return_ACPI_STATUS(status);
}
}
}
/* Create and init the internal ACPI object */
- obj_desc = acpi_ut_create_internal_object (
- (acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
+ obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
+ (op->common.aml_opcode))->
+ object_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
*obj_desc_ptr = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_buffer_obj
@@ -147,20 +145,17 @@ acpi_ds_build_internal_object (
******************************************************************************/
acpi_status
-acpi_ds_build_internal_buffer_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 buffer_length,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 buffer_length,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_parse_object *arg;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *byte_list;
- u32 byte_list_length = 0;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
+ union acpi_parse_object *arg;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *byte_list;
+ u32 byte_list_length = 0;
+ ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
obj_desc = *obj_desc_ptr;
if (obj_desc) {
@@ -168,14 +163,13 @@ acpi_ds_build_internal_buffer_obj (
* We are evaluating a Named buffer object "Name (xxxx, Buffer)".
* The buffer object already exists (from the NS node)
*/
- }
- else {
+ } else {
/* Create a new buffer object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
}
@@ -184,16 +178,17 @@ acpi_ds_build_internal_buffer_obj (
* individual bytes or a string initializer. In either case, a
* byte_list appears in the AML.
*/
- arg = op->common.value.arg; /* skip first arg */
+ arg = op->common.value.arg; /* skip first arg */
byte_list = arg->named.next;
if (byte_list) {
if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Expecting bytelist, got AML opcode %X in op %p\n",
- byte_list->common.aml_opcode, byte_list));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting bytelist, got AML opcode %X in op %p\n",
+ byte_list->common.aml_opcode,
+ byte_list));
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return (AE_TYPE);
}
@@ -214,31 +209,29 @@ acpi_ds_build_internal_buffer_obj (
if (obj_desc->buffer.length == 0) {
obj_desc->buffer.pointer = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Buffer defined with zero length in AML, creating\n"));
- }
- else {
- obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
- obj_desc->buffer.length);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Buffer defined with zero length in AML, creating\n"));
+ } else {
+ obj_desc->buffer.pointer =
+ ACPI_MEM_CALLOCATE(obj_desc->buffer.length);
if (!obj_desc->buffer.pointer) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize buffer from the byte_list (if present) */
if (byte_list) {
- ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
- byte_list_length);
+ ACPI_MEMCPY(obj_desc->buffer.pointer,
+ byte_list->named.data, byte_list_length);
}
}
obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
- op->common.node = (struct acpi_namespace_node *) obj_desc;
- return_ACPI_STATUS (AE_OK);
+ op->common.node = (struct acpi_namespace_node *)obj_desc;
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_build_internal_package_obj
@@ -256,28 +249,25 @@ acpi_ds_build_internal_buffer_obj (
******************************************************************************/
acpi_status
-acpi_ds_build_internal_package_obj (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u32 package_length,
- union acpi_operand_object **obj_desc_ptr)
+acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 package_length,
+ union acpi_operand_object **obj_desc_ptr)
{
- union acpi_parse_object *arg;
- union acpi_parse_object *parent;
- union acpi_operand_object *obj_desc = NULL;
- u32 package_list_length;
- acpi_status status = AE_OK;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
+ union acpi_parse_object *arg;
+ union acpi_parse_object *parent;
+ union acpi_operand_object *obj_desc = NULL;
+ u32 package_list_length;
+ acpi_status status = AE_OK;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
/* Find the parent of a possibly nested package */
parent = op->common.parent;
- while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
+ while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
+ (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
parent = parent->common.parent;
}
@@ -287,12 +277,11 @@ acpi_ds_build_internal_package_obj (
* We are evaluating a Named package object "Name (xxxx, Package)".
* Get the existing package object from the NS node
*/
- }
- else {
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+ } else {
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
*obj_desc_ptr = obj_desc;
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
obj_desc->package.node = parent->common.node;
@@ -323,12 +312,13 @@ acpi_ds_build_internal_package_obj (
* individual objects). Add an extra pointer slot so
* that the list is always null terminated.
*/
- obj_desc->package.elements = ACPI_MEM_CALLOCATE (
- ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
+ obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc->
+ package.count +
+ 1) * sizeof(void *));
if (!obj_desc->package.elements) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -342,11 +332,13 @@ acpi_ds_build_internal_package_obj (
/* Object (package or buffer) is already built */
obj_desc->package.elements[i] =
- ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
- }
- else {
- status = acpi_ds_build_internal_object (walk_state, arg,
- &obj_desc->package.elements[i]);
+ ACPI_CAST_PTR(union acpi_operand_object,
+ arg->common.node);
+ } else {
+ status = acpi_ds_build_internal_object(walk_state, arg,
+ &obj_desc->
+ package.
+ elements[i]);
}
i++;
@@ -354,11 +346,10 @@ acpi_ds_build_internal_package_obj (
}
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
- op->common.node = (struct acpi_namespace_node *) obj_desc;
- return_ACPI_STATUS (status);
+ op->common.node = (struct acpi_namespace_node *)obj_desc;
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_node
@@ -374,57 +365,53 @@ acpi_ds_build_internal_package_obj (
******************************************************************************/
acpi_status
-acpi_ds_create_node (
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- union acpi_parse_object *op)
+acpi_ds_create_node(struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_node", op);
/*
* Because of the execution pass through the non-control-method
* parts of the table, we can arrive here twice. Only init
* the named object node the first time through
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
if (!op->common.value.arg) {
/* No arguments, there is nothing to do */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Build an internal object for the argument(s) */
- status = acpi_ds_build_internal_object (walk_state, op->common.value.arg,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Re-type the object according to its argument */
- node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ node->type = ACPI_GET_OBJECT_TYPE(obj_desc);
/* Attach obj to node */
- status = acpi_ns_attach_object (node, obj_desc, node->type);
+ status = acpi_ns_attach_object(node, obj_desc, node->type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_NO_METHOD_EXECUTION */
-
+#endif /* ACPI_NO_METHOD_EXECUTION */
/*******************************************************************************
*
@@ -444,55 +431,50 @@ acpi_ds_create_node (
******************************************************************************/
acpi_status
-acpi_ds_init_object_from_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- u16 opcode,
- union acpi_operand_object **ret_obj_desc)
+acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u16 opcode,
+ union acpi_operand_object **ret_obj_desc)
{
- const struct acpi_opcode_info *op_info;
- union acpi_operand_object *obj_desc;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
+ const struct acpi_opcode_info *op_info;
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ds_init_object_from_op");
obj_desc = *ret_obj_desc;
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Unknown opcode */
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Perform per-object initialization */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER:
/*
* Defer evaluation of Buffer term_arg operand
*/
- obj_desc->buffer.node = (struct acpi_namespace_node *)
- walk_state->operands[0];
+ obj_desc->buffer.node = (struct acpi_namespace_node *)
+ walk_state->operands[0];
obj_desc->buffer.aml_start = op->named.data;
obj_desc->buffer.aml_length = op->named.length;
break;
-
case ACPI_TYPE_PACKAGE:
/*
* Defer evaluation of Package term_arg operand
*/
- obj_desc->package.node = (struct acpi_namespace_node *)
- walk_state->operands[0];
+ obj_desc->package.node = (struct acpi_namespace_node *)
+ walk_state->operands[0];
obj_desc->package.aml_start = op->named.data;
obj_desc->package.aml_length = op->named.length;
break;
-
case ACPI_TYPE_INTEGER:
switch (op_info->type) {
@@ -525,7 +507,7 @@ acpi_ds_init_object_from_op (
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
- acpi_ex_truncate_for32bit_table (obj_desc);
+ acpi_ex_truncate_for32bit_table(obj_desc);
#endif
break;
@@ -536,33 +518,36 @@ acpi_ds_init_object_from_op (
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown constant opcode %X\n", opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown constant opcode %X\n",
+ opcode));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
-
case AML_TYPE_LITERAL:
obj_desc->integer.value = op->common.value.integer;
+#ifndef ACPI_NO_METHOD_EXECUTION
+ acpi_ex_truncate_for32bit_table(obj_desc);
+#endif
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n",
- op_info->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Integer type %X\n",
+ op_info->type));
status = AE_AML_OPERAND_TYPE;
break;
}
break;
-
case ACPI_TYPE_STRING:
obj_desc->string.pointer = op->common.value.string;
- obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
+ obj_desc->string.length =
+ (u32) ACPI_STRLEN(op->common.value.string);
/*
* The string is contained in the ACPI table, don't ever try
@@ -571,11 +556,9 @@ acpi_ds_init_object_from_op (
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
-
case ACPI_TYPE_METHOD:
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
switch (op_info->type) {
@@ -587,14 +570,17 @@ acpi_ds_init_object_from_op (
obj_desc->reference.offset = opcode - AML_LOCAL_OP;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node (AML_LOCAL_OP,
- obj_desc->reference.offset,
- walk_state,
- (struct acpi_namespace_node **) &obj_desc->reference.object);
+ status = acpi_ds_method_data_get_node(AML_LOCAL_OP,
+ obj_desc->
+ reference.offset,
+ walk_state,
+ (struct
+ acpi_namespace_node
+ **)&obj_desc->
+ reference.object);
#endif
break;
-
case AML_TYPE_METHOD_ARGUMENT:
/* Split the opcode into a base opcode + offset */
@@ -603,14 +589,18 @@ acpi_ds_init_object_from_op (
obj_desc->reference.offset = opcode - AML_ARG_OP;
#ifndef ACPI_NO_METHOD_EXECUTION
- status = acpi_ds_method_data_get_node (AML_ARG_OP,
- obj_desc->reference.offset,
- walk_state,
- (struct acpi_namespace_node **) &obj_desc->reference.object);
+ status = acpi_ds_method_data_get_node(AML_ARG_OP,
+ obj_desc->
+ reference.offset,
+ walk_state,
+ (struct
+ acpi_namespace_node
+ **)&obj_desc->
+ reference.object);
#endif
break;
- default: /* Other literals, etc.. */
+ default: /* Other literals, etc.. */
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
/* Node was saved in Op */
@@ -623,17 +613,15 @@ acpi_ds_init_object_from_op (
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
- ACPI_GET_OBJECT_TYPE (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unimplemented data type: %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index ba13bca28bee..939d167bf87b 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -52,26 +51,21 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsopcode")
+ACPI_MODULE_NAME("dsopcode")
/* Local prototypes */
-
static acpi_status
-acpi_ds_execute_arguments (
- struct acpi_namespace_node *node,
- struct acpi_namespace_node *scope_node,
- u32 aml_length,
- u8 *aml_start);
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+ struct acpi_namespace_node *scope_node,
+ u32 aml_length, u8 * aml_start);
static acpi_status
-acpi_ds_init_buffer_field (
- u16 aml_opcode,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *buffer_desc,
- union acpi_operand_object *offset_desc,
- union acpi_operand_object *length_desc,
- union acpi_operand_object *result_desc);
-
+acpi_ds_init_buffer_field(u16 aml_opcode,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object *buffer_desc,
+ union acpi_operand_object *offset_desc,
+ union acpi_operand_object *length_desc,
+ union acpi_operand_object *result_desc);
/*******************************************************************************
*
@@ -89,26 +83,22 @@ acpi_ds_init_buffer_field (
******************************************************************************/
static acpi_status
-acpi_ds_execute_arguments (
- struct acpi_namespace_node *node,
- struct acpi_namespace_node *scope_node,
- u32 aml_length,
- u8 *aml_start)
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+ struct acpi_namespace_node *scope_node,
+ u32 aml_length, u8 * aml_start)
{
- acpi_status status;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("ds_execute_arguments");
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ds_execute_arguments");
/*
* Allocate a new parser op to be the root of the parsed tree
*/
- op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the Node for use in acpi_ps_parse_aml */
@@ -117,16 +107,17 @@ acpi_ds_execute_arguments (
/* Create and initialize a new parser state */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
- aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+ aml_length, NULL, 1);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
/* Mark this parse as a deferred opcode */
@@ -136,50 +127,51 @@ acpi_ds_execute_arguments (
/* Pass1: Parse the entire declaration */
- status = acpi_ps_parse_aml (walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
+ status = acpi_ps_parse_aml(walk_state);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
/* Get and init the Op created above */
op->common.node = node;
- acpi_ps_delete_parse_tree (op);
+ acpi_ps_delete_parse_tree(op);
/* Evaluate the deferred arguments */
- op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
op->common.node = scope_node;
/* Create and initialize a new parser state */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
if (!walk_state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
/* Execute the opcode and arguments */
- status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
- aml_length, NULL, 3);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+ aml_length, NULL, 3);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
/* Mark this execution as a deferred opcode */
walk_state->deferred_node = node;
- status = acpi_ps_parse_aml (walk_state);
- acpi_ps_delete_parse_tree (op);
- return_ACPI_STATUS (status);
-}
+ status = acpi_ps_parse_aml(walk_state);
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
@@ -195,38 +187,36 @@ acpi_ds_execute_arguments (
******************************************************************************/
acpi_status
-acpi_ds_get_buffer_field_arguments (
- union acpi_operand_object *obj_desc)
+acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
{
- union acpi_operand_object *extra_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_field_arguments", obj_desc);
+ union acpi_operand_object *extra_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the AML pointer (method object) and buffer_field node */
- extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->buffer_field.node;
- ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL));
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
- acpi_ut_get_node_name (node)));
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_BUFFER_FIELD, node, NULL));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
+ acpi_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
- extra_desc->extra.aml_length, extra_desc->extra.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
+ extra_desc->extra.aml_length,
+ extra_desc->extra.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_arguments
@@ -240,40 +230,35 @@ acpi_ds_get_buffer_field_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_get_buffer_arguments (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_arguments", obj_desc);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the Buffer node */
node = obj_desc->buffer.node;
if (!node) {
- ACPI_REPORT_ERROR ((
- "No pointer back to NS node in buffer obj %p\n", obj_desc));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("No pointer back to NS node in buffer obj %p\n", obj_desc));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, node,
- obj_desc->buffer.aml_length, obj_desc->buffer.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, node,
+ obj_desc->buffer.aml_length,
+ obj_desc->buffer.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_package_arguments
@@ -287,40 +272,36 @@ acpi_ds_get_buffer_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_get_package_arguments (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_package_arguments", obj_desc);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the Package node */
node = obj_desc->package.node;
if (!node) {
- ACPI_REPORT_ERROR ((
- "No pointer back to NS node in package %p\n", obj_desc));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("No pointer back to NS node in package %p\n",
+ obj_desc));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
/* Execute the AML code for the term_arg arguments */
- status = acpi_ds_execute_arguments (node, node,
- obj_desc->package.aml_length, obj_desc->package.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, node,
+ obj_desc->package.aml_length,
+ obj_desc->package.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_get_region_arguments
@@ -334,44 +315,43 @@ acpi_ds_get_package_arguments (
*
****************************************************************************/
-acpi_status
-acpi_ds_get_region_arguments (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
{
- struct acpi_namespace_node *node;
- acpi_status status;
- union acpi_operand_object *extra_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_region_arguments", obj_desc);
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *extra_desc;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc);
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ extra_desc = acpi_ns_get_secondary_object(obj_desc);
if (!extra_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the Region node */
node = obj_desc->region.node;
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_REGION, node, NULL));
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Arg Init at AML %p\n",
- acpi_ut_get_node_name (node), extra_desc->extra.aml_start));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%4.4s] op_region Arg Init at AML %p\n",
+ acpi_ut_get_node_name(node),
+ extra_desc->extra.aml_start));
/* Execute the argument AML */
- status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
- extra_desc->extra.aml_length, extra_desc->extra.aml_start);
- return_ACPI_STATUS (status);
+ status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
+ extra_desc->extra.aml_length,
+ extra_desc->extra.aml_start);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_initialize_region
@@ -384,23 +364,19 @@ acpi_ds_get_region_arguments (
*
******************************************************************************/
-acpi_status
-acpi_ds_initialize_region (
- acpi_handle obj_handle)
+acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
-
- obj_desc = acpi_ns_get_attached_object (obj_handle);
+ obj_desc = acpi_ns_get_attached_object(obj_handle);
/* Namespace is NOT locked */
- status = acpi_ev_initialize_region (obj_desc, FALSE);
+ status = acpi_ev_initialize_region(obj_desc, FALSE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_buffer_field
@@ -419,30 +395,27 @@ acpi_ds_initialize_region (
******************************************************************************/
static acpi_status
-acpi_ds_init_buffer_field (
- u16 aml_opcode,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *buffer_desc,
- union acpi_operand_object *offset_desc,
- union acpi_operand_object *length_desc,
- union acpi_operand_object *result_desc)
+acpi_ds_init_buffer_field(u16 aml_opcode,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object *buffer_desc,
+ union acpi_operand_object *offset_desc,
+ union acpi_operand_object *length_desc,
+ union acpi_operand_object *result_desc)
{
- u32 offset;
- u32 bit_offset;
- u32 bit_count;
- u8 field_flags;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_init_buffer_field", obj_desc);
+ u32 offset;
+ u32 bit_offset;
+ u32 bit_count;
+ u8 field_flags;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc);
/* Host object must be a Buffer */
- if (ACPI_GET_OBJECT_TYPE (buffer_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target of Create Field is not a Buffer object - %s\n",
- acpi_ut_get_object_type_name (buffer_desc)));
+ if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target of Create Field is not a Buffer object - %s\n",
+ acpi_ut_get_object_type_name(buffer_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -453,11 +426,11 @@ acpi_ds_init_buffer_field (
* out as a name_string, and should therefore now be a NS node
* after resolution in acpi_ex_resolve_operands().
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(%s) destination not a NS Node [%s]\n",
- acpi_ps_get_opcode_name (aml_opcode),
- acpi_ut_get_descriptor_name (result_desc)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(%s) destination not a NS Node [%s]\n",
+ acpi_ps_get_opcode_name(aml_opcode),
+ acpi_ut_get_descriptor_name(result_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -475,13 +448,13 @@ acpi_ds_init_buffer_field (
field_flags = AML_FIELD_ACCESS_BYTE;
bit_offset = offset;
- bit_count = (u32) length_desc->integer.value;
+ bit_count = (u32) length_desc->integer.value;
/* Must have a valid (>0) bit count */
if (bit_count == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Attempt to create_field of length 0\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Attempt to create_field of length 0\n"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -492,7 +465,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bits, Field is one bit */
bit_offset = offset;
- bit_count = 1;
+ bit_count = 1;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
@@ -501,7 +474,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one byte */
bit_offset = 8 * offset;
- bit_count = 8;
+ bit_count = 8;
field_flags = AML_FIELD_ACCESS_BYTE;
break;
@@ -510,7 +483,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one word */
bit_offset = 8 * offset;
- bit_count = 16;
+ bit_count = 16;
field_flags = AML_FIELD_ACCESS_WORD;
break;
@@ -519,7 +492,7 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one dword */
bit_offset = 8 * offset;
- bit_count = 32;
+ bit_count = 32;
field_flags = AML_FIELD_ACCESS_DWORD;
break;
@@ -528,29 +501,29 @@ acpi_ds_init_buffer_field (
/* Offset is in bytes, field is one qword */
bit_offset = 8 * offset;
- bit_count = 64;
+ bit_count = 64;
field_flags = AML_FIELD_ACCESS_QWORD;
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown field creation opcode %02x\n",
- aml_opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown field creation opcode %02x\n",
+ aml_opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Entire field must fit within the current length of the buffer */
- if ((bit_offset + bit_count) >
- (8 * (u32) buffer_desc->buffer.length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
- acpi_ut_get_node_name (result_desc),
- bit_offset + bit_count,
- acpi_ut_get_node_name (buffer_desc->buffer.node),
- 8 * (u32) buffer_desc->buffer.length));
+ if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
+ acpi_ut_get_node_name(result_desc),
+ bit_offset + bit_count,
+ acpi_ut_get_node_name(buffer_desc->buffer.
+ node),
+ 8 * (u32) buffer_desc->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
@@ -560,9 +533,9 @@ acpi_ds_init_buffer_field (
* For field_flags, use LOCK_RULE = 0 (NO_LOCK),
* UPDATE_RULE = 0 (UPDATE_PRESERVE)
*/
- status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0,
- bit_offset, bit_count);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
+ bit_offset, bit_count);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -571,35 +544,33 @@ acpi_ds_init_buffer_field (
/* Reference count for buffer_desc inherits obj_desc count */
buffer_desc->common.reference_count = (u16)
- (buffer_desc->common.reference_count + obj_desc->common.reference_count);
+ (buffer_desc->common.reference_count +
+ obj_desc->common.reference_count);
-
-cleanup:
+ cleanup:
/* Always delete the operands */
- acpi_ut_remove_reference (offset_desc);
- acpi_ut_remove_reference (buffer_desc);
+ acpi_ut_remove_reference(offset_desc);
+ acpi_ut_remove_reference(buffer_desc);
if (aml_opcode == AML_CREATE_FIELD_OP) {
- acpi_ut_remove_reference (length_desc);
+ acpi_ut_remove_reference(length_desc);
}
/* On failure, delete the result descriptor */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (result_desc); /* Result descriptor */
- }
- else {
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(result_desc); /* Result descriptor */
+ } else {
/* Now the address and length are valid for this buffer_field */
obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_buffer_field_operands
@@ -615,24 +586,21 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ds_eval_buffer_field_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- union acpi_parse_object *next_op;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_eval_buffer_field_operands", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+ ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op);
/*
* This is where we evaluate the address and length fields of the
* create_xxx_field declaration
*/
- node = op->common.node;
+ node = op->common.node;
/* next_op points to the op that holds the Buffer */
@@ -640,30 +608,32 @@ acpi_ds_eval_buffer_field_operands (
/* Evaluate/create the address and length operands */
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Resolve the operands */
- status = acpi_ex_resolve_operands (op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
+ status = acpi_ex_resolve_operands(op->common.aml_opcode,
+ ACPI_WALK_OPERANDS, walk_state);
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- walk_state->num_operands, "after acpi_ex_resolve_operands");
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ walk_state->num_operands,
+ "after acpi_ex_resolve_operands");
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode), status));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
+ acpi_ps_get_opcode_name(op->common.
+ aml_opcode), status));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Initialize the Buffer Field */
@@ -671,22 +641,25 @@ acpi_ds_eval_buffer_field_operands (
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* NOTE: Slightly different operands for this opcode */
- status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
- walk_state->operands[0], walk_state->operands[1],
- walk_state->operands[2], walk_state->operands[3]);
- }
- else {
+ status =
+ acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
+ walk_state->operands[0],
+ walk_state->operands[1],
+ walk_state->operands[2],
+ walk_state->operands[3]);
+ } else {
/* All other, create_xxx_field opcodes */
- status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
- walk_state->operands[0], walk_state->operands[1],
- NULL, walk_state->operands[2]);
+ status =
+ acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
+ walk_state->operands[0],
+ walk_state->operands[1], NULL,
+ walk_state->operands[2]);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_region_operands
@@ -702,25 +675,22 @@ acpi_ds_eval_buffer_field_operands (
******************************************************************************/
acpi_status
-acpi_ds_eval_region_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *operand_desc;
- struct acpi_namespace_node *node;
- union acpi_parse_object *next_op;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_eval_region_operands", op);
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *operand_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+ ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op);
/*
* This is where we evaluate the address and length fields of the
* op_region declaration
*/
- node = op->common.node;
+ node = op->common.node;
/* next_op points to the op that holds the space_iD */
@@ -732,26 +702,26 @@ acpi_ds_eval_region_operands (
/* Evaluate/create the address and length operands */
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Resolve the length and address operands to numbers */
- status = acpi_ex_resolve_operands (op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_operands(op->common.aml_opcode,
+ ACPI_WALK_OPERANDS, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- 1, "after acpi_ex_resolve_operands");
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ 1, "after acpi_ex_resolve_operands");
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -761,7 +731,7 @@ acpi_ds_eval_region_operands (
operand_desc = walk_state->operands[walk_state->num_operands - 1];
obj_desc->region.length = (u32) operand_desc->integer.value;
- acpi_ut_remove_reference (operand_desc);
+ acpi_ut_remove_reference(operand_desc);
/*
* Get the address and save it
@@ -770,22 +740,21 @@ acpi_ds_eval_region_operands (
operand_desc = walk_state->operands[walk_state->num_operands - 2];
obj_desc->region.address = (acpi_physical_address)
- operand_desc->integer.value;
- acpi_ut_remove_reference (operand_desc);
+ operand_desc->integer.value;
+ acpi_ut_remove_reference(operand_desc);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
- obj_desc,
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
+ obj_desc,
+ ACPI_FORMAT_UINT64(obj_desc->region.address),
+ obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_data_object_operands
@@ -802,46 +771,44 @@ acpi_ds_eval_region_operands (
******************************************************************************/
acpi_status
-acpi_ds_eval_data_object_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- union acpi_operand_object *obj_desc)
+acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object *obj_desc)
{
- acpi_status status;
- union acpi_operand_object *arg_desc;
- u32 length;
-
-
- ACPI_FUNCTION_TRACE ("ds_eval_data_object_operands");
+ acpi_status status;
+ union acpi_operand_object *arg_desc;
+ u32 length;
+ ACPI_FUNCTION_TRACE("ds_eval_data_object_operands");
/* The first operand (for all of these data objects) is the length */
- status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_resolve_operands (walk_state->opcode,
- &(walk_state->operands [walk_state->num_operands -1]),
- walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_operands(walk_state->opcode,
+ &(walk_state->
+ operands[walk_state->num_operands -
+ 1]), walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Extract length operand */
- arg_desc = walk_state->operands [walk_state->num_operands - 1];
+ arg_desc = walk_state->operands[walk_state->num_operands - 1];
length = (u32) arg_desc->integer.value;
/* Cleanup for length operand */
- status = acpi_ds_obj_stack_pop (1, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_pop(1, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- acpi_ut_remove_reference (arg_desc);
+ acpi_ut_remove_reference(arg_desc);
/*
* Create the actual data object
@@ -849,37 +816,42 @@ acpi_ds_eval_data_object_operands (
switch (op->common.aml_opcode) {
case AML_BUFFER_OP:
- status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc);
+ status =
+ acpi_ds_build_internal_buffer_obj(walk_state, op, length,
+ &obj_desc);
break;
case AML_PACKAGE_OP:
case AML_VAR_PACKAGE_OP:
- status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc);
+ status =
+ acpi_ds_build_internal_package_obj(walk_state, op, length,
+ &obj_desc);
break;
default:
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Return the object in the walk_state, unless the parent is a package -
* in this case, the return object will be stored in the parse tree
* for the package.
*/
if ((!op->common.parent) ||
- ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
- (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) &&
- (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+ ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
+ (op->common.parent->common.aml_opcode !=
+ AML_VAR_PACKAGE_OP)
+ && (op->common.parent->common.aml_opcode !=
+ AML_NAME_OP))) {
walk_state->result_obj = obj_desc;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_control_op
@@ -895,19 +867,16 @@ acpi_ds_eval_data_object_operands (
******************************************************************************/
acpi_status
-acpi_ds_exec_begin_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *control_state;
-
+ acpi_status status = AE_OK;
+ union acpi_generic_state *control_state;
- ACPI_FUNCTION_NAME ("ds_exec_begin_control_op");
+ ACPI_FUNCTION_NAME("ds_exec_begin_control_op");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
- op->common.aml_opcode, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
+ op->common.aml_opcode, walk_state));
switch (op->common.aml_opcode) {
case AML_IF_OP:
@@ -918,7 +887,7 @@ acpi_ds_exec_begin_control_op (
* constructs. We need to manage these as a stack, in order
* to handle nesting.
*/
- control_state = acpi_ut_create_control_state ();
+ control_state = acpi_ut_create_control_state();
if (!control_state) {
status = AE_NO_MEMORY;
break;
@@ -927,14 +896,16 @@ acpi_ds_exec_begin_control_op (
* Save a pointer to the predicate for multiple executions
* of a loop
*/
- control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1;
- control_state->control.package_end = walk_state->parser_state.pkg_end;
+ control_state->control.aml_predicate_start =
+ walk_state->parser_state.aml - 1;
+ control_state->control.package_end =
+ walk_state->parser_state.pkg_end;
control_state->control.opcode = op->common.aml_opcode;
-
/* Push the control state on this walk's control stack */
- acpi_ut_push_generic_state (&walk_state->control_state, control_state);
+ acpi_ut_push_generic_state(&walk_state->control_state,
+ control_state);
break;
case AML_ELSE_OP:
@@ -959,7 +930,6 @@ acpi_ds_exec_begin_control_op (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_end_control_op
@@ -975,46 +945,42 @@ acpi_ds_exec_begin_control_op (
******************************************************************************/
acpi_status
-acpi_ds_exec_end_control_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *control_state;
-
-
- ACPI_FUNCTION_NAME ("ds_exec_end_control_op");
+ acpi_status status = AE_OK;
+ union acpi_generic_state *control_state;
+ ACPI_FUNCTION_NAME("ds_exec_end_control_op");
switch (op->common.aml_opcode) {
case AML_IF_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
/*
* Save the result of the predicate in case there is an
* ELSE to come
*/
walk_state->last_predicate =
- (u8) walk_state->control_state->common.value;
+ (u8) walk_state->control_state->common.value;
/*
* Pop the control state that was created at the start
* of the IF and free it
*/
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
- acpi_ut_delete_generic_state (control_state);
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->control_state);
+ acpi_ut_delete_generic_state(control_state);
break;
-
case AML_ELSE_OP:
break;
-
case AML_WHILE_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
if (walk_state->control_state->common.value) {
/* Predicate was true, go back and evaluate it again! */
@@ -1022,22 +988,24 @@ acpi_ds_exec_end_control_op (
status = AE_CTRL_PENDING;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[WHILE_OP] termination! Op=%p\n",op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[WHILE_OP] termination! Op=%p\n", op));
/* Pop this control state and free it */
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->control_state);
- walk_state->aml_last_while = control_state->control.aml_predicate_start;
- acpi_ut_delete_generic_state (control_state);
+ walk_state->aml_last_while =
+ control_state->control.aml_predicate_start;
+ acpi_ut_delete_generic_state(control_state);
break;
-
case AML_RETURN_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[RETURN_OP] Op=%p Arg=%p\n", op,
+ op->common.value.arg));
/*
* One optional operand -- the return value
@@ -1047,12 +1015,14 @@ acpi_ds_exec_end_control_op (
if (op->common.value.arg) {
/* Since we have a real Return(), delete any implicit return */
- acpi_ds_clear_implicit_return (walk_state);
+ acpi_ds_clear_implicit_return(walk_state);
/* Return statement has an immediate operand */
- status = acpi_ds_create_operands (walk_state, op->common.value.arg);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.arg);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -1061,8 +1031,10 @@ acpi_ds_exec_end_control_op (
* an arg or local), resolve it now because it may
* cease to exist at the end of the method.
*/
- status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -1072,12 +1044,11 @@ acpi_ds_exec_end_control_op (
* is set to anything other than zero!
*/
walk_state->return_desc = walk_state->operands[0];
- }
- else if ((walk_state->results) &&
- (walk_state->results->results.num_results > 0)) {
+ } else if ((walk_state->results) &&
+ (walk_state->results->results.num_results > 0)) {
/* Since we have a real Return(), delete any implicit return */
- acpi_ds_clear_implicit_return (walk_state);
+ acpi_ds_clear_implicit_return(walk_state);
/*
* The return value has come from a previous calculation.
@@ -1088,67 +1059,78 @@ acpi_ds_exec_end_control_op (
*
* Allow references created by the Index operator to return unchanged.
*/
- if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc [0]) == ACPI_TYPE_LOCAL_REFERENCE) &&
- ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
- status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
- if (ACPI_FAILURE (status)) {
+ if ((ACPI_GET_DESCRIPTOR_TYPE
+ (walk_state->results->results.obj_desc[0]) ==
+ ACPI_DESC_TYPE_OPERAND)
+ &&
+ (ACPI_GET_OBJECT_TYPE
+ (walk_state->results->results.obj_desc[0]) ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && ((walk_state->results->results.obj_desc[0])->
+ reference.opcode != AML_INDEX_OP)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->
+ results->results.
+ obj_desc[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
- walk_state->return_desc = walk_state->results->results.obj_desc [0];
- }
- else {
+ walk_state->return_desc =
+ walk_state->results->results.obj_desc[0];
+ } else {
/* No return operand */
if (walk_state->num_operands) {
- acpi_ut_remove_reference (walk_state->operands [0]);
+ acpi_ut_remove_reference(walk_state->
+ operands[0]);
}
- walk_state->operands [0] = NULL;
- walk_state->num_operands = 0;
- walk_state->return_desc = NULL;
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
+ walk_state->return_desc = NULL;
}
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Completed RETURN_OP State=%p, ret_val=%p\n",
- walk_state, walk_state->return_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Completed RETURN_OP State=%p, ret_val=%p\n",
+ walk_state, walk_state->return_desc));
/* End the control method execution right now */
status = AE_CTRL_TERMINATE;
break;
-
case AML_NOOP_OP:
/* Just do nothing! */
break;
-
case AML_BREAK_POINT_OP:
/* Call up to the OS service layer to handle this */
- status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
+ status =
+ acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
+ "Executed AML Breakpoint opcode");
/* If and when it returns, all done. */
break;
-
case AML_BREAK_OP:
- case AML_CONTINUE_OP: /* ACPI 2.0 */
-
+ case AML_CONTINUE_OP: /* ACPI 2.0 */
/* Pop and delete control states until we find a while */
while (walk_state->control_state &&
- (walk_state->control_state->control.opcode != AML_WHILE_OP)) {
- control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
- acpi_ut_delete_generic_state (control_state);
+ (walk_state->control_state->control.opcode !=
+ AML_WHILE_OP)) {
+ control_state =
+ acpi_ut_pop_generic_state(&walk_state->
+ control_state);
+ acpi_ut_delete_generic_state(control_state);
}
/* No while found? */
@@ -1159,23 +1141,23 @@ acpi_ds_exec_end_control_op (
/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
- walk_state->aml_last_while = walk_state->control_state->control.package_end;
+ walk_state->aml_last_while =
+ walk_state->control_state->control.package_end;
/* Return status depending on opcode */
if (op->common.aml_opcode == AML_BREAK_OP) {
status = AE_CTRL_BREAK;
- }
- else {
+ } else {
status = AE_CTRL_CONTINUE;
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n",
- op->common.aml_opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown control opcode=%X Op=%p\n",
+ op->common.aml_opcode, op));
status = AE_AML_BAD_OPCODE;
break;
@@ -1183,4 +1165,3 @@ acpi_ds_exec_end_control_op (
return (status);
}
-
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 9613349ac31d..83ae1c1aa286 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -51,8 +50,7 @@
#include <acpi/acdebug.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dsutils")
-
+ACPI_MODULE_NAME("dsutils")
/*******************************************************************************
*
@@ -68,13 +66,9 @@
* parent method exits.)
*
******************************************************************************/
-
-void
-acpi_ds_clear_implicit_return (
- struct acpi_walk_state *walk_state)
+void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
-
+ ACPI_FUNCTION_NAME("ds_clear_implicit_return");
/*
* Slack must be enabled for this feature
@@ -89,16 +83,15 @@ acpi_ds_clear_implicit_return (
* complex statements, the implicit return value can be
* bubbled up several levels.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Removing reference on stale implicit return obj %p\n",
- walk_state->implicit_return_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
- acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ acpi_ut_remove_reference(walk_state->implicit_return_obj);
walk_state->implicit_return_obj = NULL;
}
}
-
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -119,27 +112,22 @@ acpi_ds_clear_implicit_return (
******************************************************************************/
u8
-acpi_ds_do_implicit_return (
- union acpi_operand_object *return_desc,
- struct acpi_walk_state *walk_state,
- u8 add_reference)
+acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state, u8 add_reference)
{
- ACPI_FUNCTION_NAME ("ds_do_implicit_return");
-
+ ACPI_FUNCTION_NAME("ds_do_implicit_return");
/*
* Slack must be enabled for this feature, and we must
* have a valid return object
*/
- if ((!acpi_gbl_enable_interpreter_slack) ||
- (!return_desc)) {
+ if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
return (FALSE);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result %p will be implicitly returned; Prev=%p\n",
- return_desc,
- walk_state->implicit_return_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc, walk_state->implicit_return_obj));
/*
* Delete any "stale" implicit return value first. However, in
@@ -151,20 +139,19 @@ acpi_ds_do_implicit_return (
if (walk_state->implicit_return_obj == return_desc) {
return (TRUE);
}
- acpi_ds_clear_implicit_return (walk_state);
+ acpi_ds_clear_implicit_return(walk_state);
}
/* Save the implicit return value, add a reference if requested */
walk_state->implicit_return_obj = return_desc;
if (add_reference) {
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
return (TRUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_is_result_used
@@ -179,20 +166,18 @@ acpi_ds_do_implicit_return (
******************************************************************************/
u8
-acpi_ds_is_result_used (
- union acpi_parse_object *op,
- struct acpi_walk_state *walk_state)
+acpi_ds_is_result_used(union acpi_parse_object * op,
+ struct acpi_walk_state * walk_state)
{
- const struct acpi_opcode_info *parent_info;
-
- ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
+ const struct acpi_opcode_info *parent_info;
+ ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op);
/* Must have both an Op and a Result Object */
if (!op) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
- return_VALUE (TRUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
+ return_VALUE(TRUE);
}
/*
@@ -204,7 +189,8 @@ acpi_ds_is_result_used (
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
- (void) acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+ (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
+ TRUE);
/*
* Now determine if the parent will use the result
@@ -215,22 +201,24 @@ acpi_ds_is_result_used (
* via execute_control_method has a scope_op as the parent.
*/
if ((!op->common.parent) ||
- (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
+ (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
/* No parent, the return value cannot possibly be used */
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "At Method level, result of [%s] not used\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode)));
- return_VALUE (FALSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "At Method level, result of [%s] not used\n",
+ acpi_ps_get_opcode_name(op->common.
+ aml_opcode)));
+ return_VALUE(FALSE);
}
/* Get info on the parent. The root_op is AML_SCOPE */
- parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
+ parent_info =
+ acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
if (parent_info->class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown parent opcode. Op=%p\n", op));
- return_VALUE (FALSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown parent opcode. Op=%p\n", op));
+ return_VALUE(FALSE);
}
/*
@@ -256,8 +244,10 @@ acpi_ds_is_result_used (
* If we are executing the predicate AND this is the predicate op,
* we will use the return value
*/
- if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
- (walk_state->control_state->control.predicate_op == op)) {
+ if ((walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING)
+ && (walk_state->control_state->control.
+ predicate_op == op)) {
goto result_used;
}
break;
@@ -271,7 +261,6 @@ acpi_ds_is_result_used (
goto result_not_used;
-
case AML_CLASS_CREATE:
/*
@@ -280,15 +269,16 @@ acpi_ds_is_result_used (
*/
goto result_used;
-
case AML_CLASS_NAMED_OBJECT:
- if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
+ if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
+ (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
+ || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_INT_EVAL_SUBTREE_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
@@ -298,7 +288,6 @@ acpi_ds_is_result_used (
goto result_not_used;
-
default:
/*
@@ -308,26 +297,25 @@ acpi_ds_is_result_used (
goto result_used;
}
+ result_used:
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result of [%s] used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ acpi_ps_get_opcode_name(op->common.parent->common.
+ aml_opcode), op));
-result_used:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] used by Parent [%s] Op=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
-
- return_VALUE (TRUE);
-
+ return_VALUE(TRUE);
-result_not_used:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] not used by Parent [%s] Op=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode),
- acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
+ result_not_used:
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Result of [%s] not used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ acpi_ps_get_opcode_name(op->common.parent->common.
+ aml_opcode), op));
- return_VALUE (FALSE);
+ return_VALUE(FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_result_if_not_used
@@ -346,20 +334,17 @@ result_not_used:
******************************************************************************/
void
-acpi_ds_delete_result_if_not_used (
- union acpi_parse_object *op,
- union acpi_operand_object *result_obj,
- struct acpi_walk_state *walk_state)
+acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
+ union acpi_operand_object *result_obj,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
if (!op) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n"));
return_VOID;
}
@@ -367,19 +352,18 @@ acpi_ds_delete_result_if_not_used (
return_VOID;
}
- if (!acpi_ds_is_result_used (op, walk_state)) {
+ if (!acpi_ds_is_result_used(op, walk_state)) {
/* Must pop the result stack (obj_desc should be equal to result_obj) */
- status = acpi_ds_result_pop (&obj_desc, walk_state);
- if (ACPI_SUCCESS (status)) {
- acpi_ut_remove_reference (result_obj);
+ status = acpi_ds_result_pop(&obj_desc, walk_state);
+ if (ACPI_SUCCESS(status)) {
+ acpi_ut_remove_reference(result_obj);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_resolve_operands
@@ -394,16 +378,12 @@ acpi_ds_delete_result_if_not_used (
*
******************************************************************************/
-acpi_status
-acpi_ds_resolve_operands (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
{
- u32 i;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_resolve_operands", walk_state);
+ u32 i;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state);
/*
* Attempt to resolve each of the valid operands
@@ -411,16 +391,17 @@ acpi_ds_resolve_operands (
* that the actual objects are passed, not copies of the objects.
*/
for (i = 0; i < walk_state->num_operands; i++) {
- status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[i],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_clear_operands
@@ -433,15 +414,11 @@ acpi_ds_resolve_operands (
*
******************************************************************************/
-void
-acpi_ds_clear_operands (
- struct acpi_walk_state *walk_state)
+void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
+ u32 i;
+ ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state);
/* Remove a reference on each operand on the stack */
@@ -450,7 +427,7 @@ acpi_ds_clear_operands (
* Remove a reference to all operands, including both
* "Arguments" and "Targets".
*/
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
@@ -459,7 +436,6 @@ acpi_ds_clear_operands (
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operand
@@ -478,37 +454,36 @@ acpi_ds_clear_operands (
******************************************************************************/
acpi_status
-acpi_ds_create_operand (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *arg,
- u32 arg_index)
+acpi_ds_create_operand(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg, u32 arg_index)
{
- acpi_status status = AE_OK;
- char *name_string;
- u32 name_length;
- union acpi_operand_object *obj_desc;
- union acpi_parse_object *parent_op;
- u16 opcode;
- acpi_interpreter_mode interpreter_mode;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
+ acpi_status status = AE_OK;
+ char *name_string;
+ u32 name_length;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *parent_op;
+ u16 opcode;
+ acpi_interpreter_mode interpreter_mode;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg);
/* A valid name must be looked up in the namespace */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
- (arg->common.value.string)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
+ (arg->common.value.string)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
+ arg));
/* Get the entire name string from the AML stream */
- status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
- &name_string, &name_length);
+ status =
+ acpi_ex_get_name_string(ACPI_TYPE_ANY,
+ arg->common.value.buffer,
+ &name_string, &name_length);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* All prefixes have been handled, and the name is in name_string */
@@ -523,13 +498,14 @@ acpi_ds_create_operand (
* actual opcode exists.
*/
if ((walk_state->deferred_node) &&
- (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
- (arg_index != 0)) {
- obj_desc = ACPI_CAST_PTR (
- union acpi_operand_object, walk_state->deferred_node);
+ (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
+ && (arg_index != 0)) {
+ obj_desc =
+ ACPI_CAST_PTR(union acpi_operand_object,
+ walk_state->deferred_node);
status = AE_OK;
- }
- else /* All other opcodes */ {
+ } else { /* All other opcodes */
+
/*
* Differentiate between a namespace "create" operation
* versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
@@ -537,43 +513,51 @@ acpi_ds_create_operand (
* namespace objects during the execution of control methods.
*/
parent_op = arg->common.parent;
- op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
- if ((op_info->flags & AML_NSNODE) &&
- (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
- (parent_op->common.aml_opcode != AML_REGION_OP) &&
- (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
+ op_info =
+ acpi_ps_get_opcode_info(parent_op->common.
+ aml_opcode);
+ if ((op_info->flags & AML_NSNODE)
+ && (parent_op->common.aml_opcode !=
+ AML_INT_METHODCALL_OP)
+ && (parent_op->common.aml_opcode != AML_REGION_OP)
+ && (parent_op->common.aml_opcode !=
+ AML_INT_NAMEPATH_OP)) {
/* Enter name into namespace if not found */
interpreter_mode = ACPI_IMODE_LOAD_PASS2;
- }
- else {
+ } else {
/* Return a failure if name not found */
interpreter_mode = ACPI_IMODE_EXECUTE;
}
- status = acpi_ns_lookup (walk_state->scope_info, name_string,
- ACPI_TYPE_ANY, interpreter_mode,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- walk_state,
- ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
+ status =
+ acpi_ns_lookup(walk_state->scope_info, name_string,
+ ACPI_TYPE_ANY, interpreter_mode,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, walk_state,
+ ACPI_CAST_INDIRECT_PTR(struct
+ acpi_namespace_node,
+ &obj_desc));
/*
* The only case where we pass through (ignore) a NOT_FOUND
* error is for the cond_ref_of opcode.
*/
if (status == AE_NOT_FOUND) {
- if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
+ if (parent_op->common.aml_opcode ==
+ AML_COND_REF_OF_OP) {
/*
* For the Conditional Reference op, it's OK if
* the name is not found; We just need a way to
* indicate this to the interpreter, set the
* object to the root
*/
- obj_desc = ACPI_CAST_PTR (
- union acpi_operand_object, acpi_gbl_root_node);
+ obj_desc =
+ ACPI_CAST_PTR(union
+ acpi_operand_object,
+ acpi_gbl_root_node);
status = AE_OK;
- }
- else {
+ } else {
/*
* We just plain didn't find it -- which is a
* very serious error at this point
@@ -582,30 +566,30 @@ acpi_ds_create_operand (
}
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (name_string, status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(name_string, status);
}
}
/* Free the namestring created above */
- ACPI_MEM_FREE (name_string);
+ ACPI_MEM_FREE(name_string);
/* Check status from the lookup */
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Put the resulting object onto the current object stack */
- status = acpi_ds_obj_stack_push (obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_push(obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
- }
- else {
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (obj_desc, walk_state));
+ } else {
/* Check for null name case */
if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -615,77 +599,83 @@ acpi_ds_create_operand (
* in the original ASL. Create a Zero Constant for a
* placeholder. (Store to a constant is a Noop.)
*/
- opcode = AML_ZERO_OP; /* Has no arguments! */
+ opcode = AML_ZERO_OP; /* Has no arguments! */
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Null namepath: Arg=%p\n", arg));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Null namepath: Arg=%p\n", arg));
+ } else {
opcode = arg->common.aml_opcode;
}
/* Get the object type of the argument */
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->object_type == ACPI_TYPE_INVALID) {
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
if (op_info->flags & AML_HAS_RETVAL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Argument previously created, already stacked \n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Argument previously created, already stacked \n"));
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
- walk_state->operands [walk_state->num_operands - 1], walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (walk_state->
+ operands[walk_state->num_operands -
+ 1], walk_state));
/*
* Use value that was already previously returned
* by the evaluation of this argument
*/
- status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_result_pop_from_bottom(&obj_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
/*
* Only error is underflow, and this indicates
* a missing or null operand!
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Missing or null operand, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Missing or null operand, %s\n",
+ acpi_format_exception
+ (status)));
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/* Create an ACPI_INTERNAL_OBJECT for the argument */
- obj_desc = acpi_ut_create_internal_object (op_info->object_type);
+ obj_desc =
+ acpi_ut_create_internal_object(op_info->
+ object_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new object */
- status = acpi_ds_init_object_from_op (
- walk_state, arg, opcode, &obj_desc);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_init_object_from_op(walk_state, arg, opcode,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
}
}
/* Put the operand object on the object stack */
- status = acpi_ds_obj_stack_push (obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_obj_stack_push(obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
+ (obj_desc, walk_state));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_operands
@@ -702,29 +692,27 @@ acpi_ds_create_operand (
******************************************************************************/
acpi_status
-acpi_ds_create_operands (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *first_arg)
+acpi_ds_create_operands(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *first_arg)
{
- acpi_status status = AE_OK;
- union acpi_parse_object *arg;
- u32 arg_count = 0;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
+ acpi_status status = AE_OK;
+ union acpi_parse_object *arg;
+ u32 arg_count = 0;
+ ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg);
/* For all arguments in the list... */
arg = first_arg;
while (arg) {
- status = acpi_ds_create_operand (walk_state, arg, arg_count);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operand(walk_state, arg, arg_count);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
- arg_count, arg, first_arg));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Arg #%d (%p) done, Arg1=%p\n", arg_count,
+ arg, first_arg));
/* Move on to next argument, if any */
@@ -732,20 +720,17 @@ acpi_ds_create_operands (
arg_count++;
}
- return_ACPI_STATUS (status);
-
+ return_ACPI_STATUS(status);
-cleanup:
+ cleanup:
/*
* We must undo everything done above; meaning that we must
* pop everything off of the operand stack and delete those
* objects
*/
- (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
+ (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
- (arg_count + 1), acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
+ (arg_count + 1), acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index 10f71318e23b..e522763bb692 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -52,27 +51,26 @@
#include <acpi/acdebug.h>
#include <acpi/acdisasm.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswexec")
+ACPI_MODULE_NAME("dswexec")
/*
* Dispatch table for opcode classes
*/
-static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
- acpi_ex_opcode_0A_0T_1R,
- acpi_ex_opcode_1A_0T_0R,
- acpi_ex_opcode_1A_0T_1R,
- acpi_ex_opcode_1A_1T_0R,
- acpi_ex_opcode_1A_1T_1R,
- acpi_ex_opcode_2A_0T_0R,
- acpi_ex_opcode_2A_0T_1R,
- acpi_ex_opcode_2A_1T_1R,
- acpi_ex_opcode_2A_2T_1R,
- acpi_ex_opcode_3A_0T_0R,
- acpi_ex_opcode_3A_1T_1R,
- acpi_ex_opcode_6A_0T_1R};
-
+static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = {
+ acpi_ex_opcode_0A_0T_1R,
+ acpi_ex_opcode_1A_0T_0R,
+ acpi_ex_opcode_1A_0T_1R,
+ acpi_ex_opcode_1A_1T_0R,
+ acpi_ex_opcode_1A_1T_1R,
+ acpi_ex_opcode_2A_0T_0R,
+ acpi_ex_opcode_2A_0T_1R,
+ acpi_ex_opcode_2A_1T_1R,
+ acpi_ex_opcode_2A_2T_1R,
+ acpi_ex_opcode_3A_0T_0R,
+ acpi_ex_opcode_3A_1T_1R,
+ acpi_ex_opcode_6A_0T_1R
+};
/*****************************************************************************
*
@@ -88,64 +86,64 @@ static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
****************************************************************************/
acpi_status
-acpi_ds_get_predicate_value (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *result_obj) {
- acpi_status status = AE_OK;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *local_obj_desc = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
+acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *result_obj)
+{
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state);
walk_state->control_state->common.state = 0;
if (result_obj) {
- status = acpi_ds_result_pop (&obj_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not get result from predicate evaluation, %s\n",
- acpi_format_exception (status)));
+ status = acpi_ds_result_pop(&obj_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not get result from predicate evaluation, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- }
- else {
- status = acpi_ds_create_operand (walk_state, walk_state->op, 0);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ } else {
+ status = acpi_ds_create_operand(walk_state, walk_state->op, 0);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_resolve_to_value(&walk_state->operands[0],
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = walk_state->operands [0];
+ obj_desc = walk_state->operands[0];
}
if (!obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No predicate obj_desc=%p State=%p\n",
- obj_desc, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No predicate obj_desc=%p State=%p\n",
+ obj_desc, walk_state));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
* Result of predicate evaluation must be an Integer
* object. Implicitly convert the argument if necessary.
*/
- status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
- obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
+ if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
+ obj_desc, walk_state,
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
@@ -153,7 +151,7 @@ acpi_ds_get_predicate_value (
/* Truncate the predicate to 32-bits if necessary */
- acpi_ex_truncate_for32bit_table (local_obj_desc);
+ acpi_ex_truncate_for32bit_table(local_obj_desc);
/*
* Save the result of the predicate evaluation on
@@ -161,8 +159,7 @@ acpi_ds_get_predicate_value (
*/
if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
- }
- else {
+ } else {
/*
* Predicate is FALSE, we will just toss the
* rest of the package
@@ -171,30 +168,30 @@ acpi_ds_get_predicate_value (
status = AE_CTRL_FALSE;
}
+ cleanup:
-cleanup:
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
+ walk_state->control_state->common.value,
+ walk_state->op));
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
- walk_state->control_state->common.value, walk_state->op));
+ /* Break to debugger to display result */
- /* Break to debugger to display result */
-
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
+ (local_obj_desc, walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
if (local_obj_desc != obj_desc) {
- acpi_ut_remove_reference (local_obj_desc);
+ acpi_ut_remove_reference(local_obj_desc);
}
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_op
@@ -211,38 +208,39 @@ cleanup:
****************************************************************************/
acpi_status
-acpi_ds_exec_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- u32 opcode_class;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_exec_begin_op", walk_state);
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 opcode_class;
+ ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state);
op = walk_state->op;
if (!op) {
- status = acpi_ds_load2_begin_op (walk_state, out_op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_load2_begin_op(walk_state, out_op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
op = *out_op;
walk_state->op = op;
walk_state->opcode = op->common.aml_opcode;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
-
- if (acpi_ns_opens_scope (walk_state->op_info->object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "(%s) Popping scope for Op %p\n",
- acpi_ut_get_type_name (walk_state->op_info->object_type), op));
-
- status = acpi_ds_scope_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+
+ if (acpi_ns_opens_scope(walk_state->op_info->object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name(walk_state->
+ op_info->
+ object_type),
+ op));
+
+ status = acpi_ds_scope_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
@@ -252,7 +250,7 @@ acpi_ds_exec_begin_op (
*out_op = op;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -261,19 +259,20 @@ acpi_ds_exec_begin_op (
* Save this knowledge in the current scope descriptor
*/
if ((walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n",
- op, walk_state));
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Exec predicate Op=%p State=%p\n", op,
+ walk_state));
- walk_state->control_state->common.state = ACPI_CONTROL_PREDICATE_EXECUTING;
+ walk_state->control_state->common.state =
+ ACPI_CONTROL_PREDICATE_EXECUTING;
/* Save start of predicate */
walk_state->control_state->control.predicate_op = op;
}
-
opcode_class = walk_state->op_info->class;
/* We want to send namepaths to the load code */
@@ -288,15 +287,14 @@ acpi_ds_exec_begin_op (
switch (opcode_class) {
case AML_CLASS_CONTROL:
- status = acpi_ds_result_stack_push (walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_result_stack_push(walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ds_exec_begin_control_op (walk_state, op);
+ status = acpi_ds_exec_begin_control_op(walk_state, op);
break;
-
case AML_CLASS_NAMED_OBJECT:
if (walk_state->walk_type == ACPI_WALK_METHOD) {
@@ -306,15 +304,14 @@ acpi_ds_exec_begin_op (
* object is temporary and will be deleted upon completion of
* the execution of this method.
*/
- status = acpi_ds_load2_begin_op (walk_state, NULL);
+ status = acpi_ds_load2_begin_op(walk_state, NULL);
}
if (op->common.aml_opcode == AML_REGION_OP) {
- status = acpi_ds_result_stack_push (walk_state);
+ status = acpi_ds_result_stack_push(walk_state);
}
break;
-
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
@@ -322,20 +319,18 @@ acpi_ds_exec_begin_op (
* Most operators with arguments.
* Start a new result/operand state
*/
- status = acpi_ds_result_stack_push (walk_state);
+ status = acpi_ds_result_stack_push(walk_state);
break;
-
default:
break;
}
/* Nothing to do here during method execution */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*****************************************************************************
*
* FUNCTION: acpi_ds_exec_end_op
@@ -350,28 +345,25 @@ acpi_ds_exec_begin_op (
*
****************************************************************************/
-acpi_status
-acpi_ds_exec_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- u32 op_type;
- u32 op_class;
- union acpi_parse_object *next_op;
- union acpi_parse_object *first_arg;
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 op_type;
+ u32 op_class;
+ union acpi_parse_object *next_op;
+ union acpi_parse_object *first_arg;
+ ACPI_FUNCTION_TRACE_PTR("ds_exec_end_op", walk_state);
- ACPI_FUNCTION_TRACE_PTR ("ds_exec_end_op", walk_state);
-
-
- op = walk_state->op;
+ op = walk_state->op;
op_type = walk_state->op_info->type;
op_class = walk_state->op_info->class;
if (op_class == AML_CLASS_UNKNOWN) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown opcode %X\n",
+ op->common.aml_opcode));
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
first_arg = op->common.value.arg;
@@ -384,29 +376,31 @@ acpi_ds_exec_end_op (
/* Call debugger for single step support (DEBUG build only) */
- ACPI_DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class));
- ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);});
+ ACPI_DEBUGGER_EXEC(status =
+ acpi_db_single_step(walk_state, op, op_class));
+ ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);}
+ ) ;
/* Decode the Opcode Class */
switch (op_class) {
- case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
+ case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */
break;
-
- case AML_CLASS_EXECUTE: /* most operators with arguments */
+ case AML_CLASS_EXECUTE: /* most operators with arguments */
/* Build resolved operand stack */
- status = acpi_ds_create_operands (walk_state, first_arg);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, first_arg);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Done with this result state (Now that operand stack is built) */
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -417,86 +411,93 @@ acpi_ds_exec_end_op (
if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
/* Resolve all operands */
- status = acpi_ex_resolve_operands (walk_state->opcode,
- &(walk_state->operands [walk_state->num_operands -1]),
- walk_state);
- if (ACPI_SUCCESS (status)) {
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (walk_state->opcode),
- walk_state->num_operands, "after ex_resolve_operands");
+ status = acpi_ex_resolve_operands(walk_state->opcode,
+ &(walk_state->
+ operands
+ [walk_state->
+ num_operands - 1]),
+ walk_state);
+ if (ACPI_SUCCESS(status)) {
+ ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
+ ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name
+ (walk_state->opcode),
+ walk_state->num_operands,
+ "after ex_resolve_operands");
}
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Dispatch the request to the appropriate interpreter handler
* routine. There is one routine per opcode "type" based upon the
* number of opcode arguments and return type.
*/
- status = acpi_gbl_op_type_dispatch[op_type] (walk_state);
- }
- else {
+ status =
+ acpi_gbl_op_type_dispatch[op_type] (walk_state);
+ } else {
/*
* Treat constructs of the form "Store(local_x,local_x)" as noops when the
* Local is uninitialized.
*/
- if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
- (walk_state->opcode == AML_STORE_OP) &&
- (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
- (walk_state->operands[0]->reference.opcode ==
- walk_state->operands[1]->reference.opcode) &&
- (walk_state->operands[0]->reference.offset ==
- walk_state->operands[1]->reference.offset)) {
+ if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
+ (walk_state->opcode == AML_STORE_OP) &&
+ (walk_state->operands[0]->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (walk_state->operands[1]->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (walk_state->operands[0]->reference.opcode ==
+ walk_state->operands[1]->reference.opcode)
+ && (walk_state->operands[0]->reference.offset ==
+ walk_state->operands[1]->reference.offset)) {
status = AE_OK;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "[%s]: Could not resolve operands, %s\n",
- acpi_ps_get_opcode_name (walk_state->opcode),
- acpi_format_exception (status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "[%s]: Could not resolve operands, %s\n",
+ acpi_ps_get_opcode_name
+ (walk_state->opcode),
+ acpi_format_exception
+ (status)));
}
}
/* Always delete the argument objects and clear the operand stack */
- acpi_ds_clear_operands (walk_state);
+ acpi_ds_clear_operands(walk_state);
/*
* If a result object was returned from above, push it on the
* current result stack
*/
- if (ACPI_SUCCESS (status) &&
- walk_state->result_obj) {
- status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ if (ACPI_SUCCESS(status) && walk_state->result_obj) {
+ status =
+ acpi_ds_result_push(walk_state->result_obj,
+ walk_state);
}
break;
-
default:
switch (op_type) {
- case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
+ case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
/* 1 Operand, 0 external_result, 0 internal_result */
- status = acpi_ds_exec_end_control_op (walk_state, op);
+ status = acpi_ds_exec_end_control_op(walk_state, op);
/* Make sure to properly pop the result stack */
- if (ACPI_SUCCESS (status)) {
- status = acpi_ds_result_stack_pop (walk_state);
- }
- else if (status == AE_CTRL_PENDING) {
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ } else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_SUCCESS(status)) {
status = AE_CTRL_PENDING;
}
}
break;
-
case AML_TYPE_METHOD_CALL:
/*
@@ -505,16 +506,22 @@ acpi_ds_exec_end_op (
* a reference to it.
*/
if ((op->asl.parent) &&
- ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
- (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Method Reference in a Package, Op=%p\n", op));
- op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
- acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
- return_ACPI_STATUS (AE_OK);
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
+ || (op->asl.parent->asl.aml_opcode ==
+ AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Method Reference in a Package, Op=%p\n",
+ op));
+ op->common.node =
+ (struct acpi_namespace_node *)op->asl.value.
+ arg->asl.node->object;
+ acpi_ut_add_reference(op->asl.value.arg->asl.
+ node->object);
+ return_ACPI_STATUS(AE_OK);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Method invocation, Op=%p\n", op));
/*
* (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
@@ -531,8 +538,8 @@ acpi_ds_exec_end_op (
/*
* Get the method's arguments and put them on the operand stack
*/
- status = acpi_ds_create_operands (walk_state, next_op);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, next_op);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -541,11 +548,11 @@ acpi_ds_exec_end_op (
* we must resolve all local references here (Local variables,
* arguments to *this* method, etc.)
*/
- status = acpi_ds_resolve_operands (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_resolve_operands(walk_state);
+ if (ACPI_FAILURE(status)) {
/* On error, clear all resolved operands */
- acpi_ds_clear_operands (walk_state);
+ acpi_ds_clear_operands(walk_state);
break;
}
@@ -559,27 +566,28 @@ acpi_ds_exec_end_op (
* Return now; we don't want to disturb anything,
* especially the operand count!
*/
- return_ACPI_STATUS (status);
-
+ return_ACPI_STATUS(status);
case AML_TYPE_CREATE_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing create_field Buffer/Index Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing create_field Buffer/Index Op=%p\n",
+ op));
- status = acpi_ds_load2_end_op (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_load2_end_op(walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
- status = acpi_ds_eval_buffer_field_operands (walk_state, op);
+ status =
+ acpi_ds_eval_buffer_field_operands(walk_state, op);
break;
-
case AML_TYPE_CREATE_OBJECT:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing create_object (Buffer/Package) Op=%p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing create_object (Buffer/Package) Op=%p\n",
+ op));
switch (op->common.parent->common.aml_opcode) {
case AML_NAME_OP:
@@ -588,13 +596,15 @@ acpi_ds_exec_end_op (
* Put the Node on the object stack (Contains the ACPI Name
* of this object)
*/
- walk_state->operands[0] = (void *) op->common.parent->common.node;
+ walk_state->operands[0] =
+ (void *)op->common.parent->common.node;
walk_state->num_operands = 1;
- status = acpi_ds_create_node (walk_state,
- op->common.parent->common.node,
- op->common.parent);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_node(walk_state,
+ op->common.parent->
+ common.node,
+ op->common.parent);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -603,20 +613,26 @@ acpi_ds_exec_end_op (
case AML_INT_EVAL_SUBTREE_OP:
- status = acpi_ds_eval_data_object_operands (walk_state, op,
- acpi_ns_get_attached_object (op->common.parent->common.node));
+ status =
+ acpi_ds_eval_data_object_operands
+ (walk_state, op,
+ acpi_ns_get_attached_object(op->common.
+ parent->common.
+ node));
break;
default:
- status = acpi_ds_eval_data_object_operands (walk_state, op, NULL);
+ status =
+ acpi_ds_eval_data_object_operands
+ (walk_state, op, NULL);
break;
}
/* Done with result state (Now that operand stack is built) */
- status = acpi_ds_result_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_result_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -625,56 +641,58 @@ acpi_ds_exec_end_op (
* current result stack
*/
if (walk_state->result_obj) {
- status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ status =
+ acpi_ds_result_push(walk_state->result_obj,
+ walk_state);
}
break;
-
case AML_TYPE_NAMED_FIELD:
case AML_TYPE_NAMED_COMPLEX:
case AML_TYPE_NAMED_SIMPLE:
case AML_TYPE_NAMED_NO_OBJ:
- status = acpi_ds_load2_end_op (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_load2_end_op(walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
if (op->common.aml_opcode == AML_REGION_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Executing op_region Address/Length Op=%p\n", op));
-
- status = acpi_ds_eval_region_operands (walk_state, op);
- if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Executing op_region Address/Length Op=%p\n",
+ op));
+
+ status =
+ acpi_ds_eval_region_operands(walk_state,
+ op);
+ if (ACPI_FAILURE(status)) {
break;
}
- status = acpi_ds_result_stack_pop (walk_state);
+ status = acpi_ds_result_stack_pop(walk_state);
}
break;
-
case AML_TYPE_UNDEFINED:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Undefined opcode type Op=%p\n", op));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
-
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Undefined opcode type Op=%p\n", op));
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
case AML_TYPE_BOGUS:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Internal opcode=%X type Op=%p\n",
- walk_state->opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Internal opcode=%X type Op=%p\n",
+ walk_state->opcode, op));
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
- op_class, op_type, op->common.aml_opcode, op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
+ op_class, op_type,
+ op->common.aml_opcode, op));
status = AE_NOT_IMPLEMENTED;
break;
@@ -685,55 +703,58 @@ acpi_ds_exec_end_op (
* ACPI 2.0 support for 64-bit integers: Truncate numeric
* result value if we are executing from a 32-bit ACPI table
*/
- acpi_ex_truncate_for32bit_table (walk_state->result_obj);
+ acpi_ex_truncate_for32bit_table(walk_state->result_obj);
/*
* Check if we just completed the evaluation of a
* conditional predicate
*/
- if ((ACPI_SUCCESS (status)) &&
- (walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_PREDICATE_EXECUTING) &&
- (walk_state->control_state->control.predicate_op == op)) {
- status = acpi_ds_get_predicate_value (walk_state, walk_state->result_obj);
+ if ((ACPI_SUCCESS(status)) &&
+ (walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING) &&
+ (walk_state->control_state->control.predicate_op == op)) {
+ status =
+ acpi_ds_get_predicate_value(walk_state,
+ walk_state->result_obj);
walk_state->result_obj = NULL;
}
-
-cleanup:
+ cleanup:
/* Invoke exception handler on error */
- if (ACPI_FAILURE (status) &&
- acpi_gbl_exception_handler &&
- !(status & AE_CODE_CONTROL)) {
- acpi_ex_exit_interpreter ();
- status = acpi_gbl_exception_handler (status,
- walk_state->method_node->name.integer, walk_state->opcode,
- walk_state->aml_offset, NULL);
- (void) acpi_ex_enter_interpreter ();
+ if (ACPI_FAILURE(status) &&
+ acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
+ acpi_ex_exit_interpreter();
+ status = acpi_gbl_exception_handler(status,
+ walk_state->method_node->
+ name.integer,
+ walk_state->opcode,
+ walk_state->aml_offset,
+ NULL);
+ (void)acpi_ex_enter_interpreter();
}
if (walk_state->result_obj) {
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj,
- walk_state));
+ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
+ (walk_state->result_obj, walk_state));
/*
* Delete the result op if and only if:
* Parent will not use the result -- such as any
* non-nested type2 op in a method (parent will be method)
*/
- acpi_ds_delete_result_if_not_used (op, walk_state->result_obj, walk_state);
+ acpi_ds_delete_result_if_not_used(op, walk_state->result_obj,
+ walk_state);
}
-
#ifdef _UNDER_DEVELOPMENT
if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
- acpi_db_method_end (walk_state);
+ acpi_db_method_end(walk_state);
}
#endif
@@ -745,12 +766,10 @@ cleanup:
/* On error, display method locals/args */
- if (ACPI_FAILURE (status)) {
- acpi_dm_dump_method_info (status, walk_state, op);
+ if (ACPI_FAILURE(status)) {
+ acpi_dm_dump_method_info(status, walk_state, op);
}
#endif
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 1ac197ccfc80..411731261c29 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
@@ -50,13 +49,12 @@
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
-#ifdef _ACPI_ASL_COMPILER
+#ifdef ACPI_ASL_COMPILER
#include <acpi/acdisasm.h>
#endif
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswload")
-
+ACPI_MODULE_NAME("dswload")
/*******************************************************************************
*
@@ -70,32 +68,29 @@
* DESCRIPTION: Init walk state callbacks
*
******************************************************************************/
-
acpi_status
-acpi_ds_init_callbacks (
- struct acpi_walk_state *walk_state,
- u32 pass_number)
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
{
switch (pass_number) {
case 1:
- walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load1_begin_op;
walk_state->ascending_callback = acpi_ds_load1_end_op;
break;
case 2:
- walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_load2_begin_op;
walk_state->ascending_callback = acpi_ds_load2_end_op;
break;
case 3:
#ifndef ACPI_NO_METHOD_EXECUTION
- walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
- ACPI_PARSE_DELETE_TREE;
+ walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
+ ACPI_PARSE_DELETE_TREE;
walk_state->descending_callback = acpi_ds_exec_begin_op;
walk_state->ascending_callback = acpi_ds_exec_end_op;
#endif
@@ -108,7 +103,6 @@ acpi_ds_init_callbacks (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_begin_op
@@ -123,37 +117,26 @@ acpi_ds_init_callbacks (
******************************************************************************/
acpi_status
-acpi_ds_load1_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object ** out_op)
{
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_status status;
- acpi_object_type object_type;
- char *path;
- u32 flags;
-
-
- ACPI_FUNCTION_NAME ("ds_load1_begin_op");
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *path;
+ u32 flags;
+ ACPI_FUNCTION_NAME("ds_load1_begin_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
/* We are only interested in opcodes that have an associated name */
if (op) {
if (!(walk_state->op_info->flags & AML_NAMED)) {
-#if 0
- if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
- (walk_state->op_info->class == AML_CLASS_CONTROL)) {
- acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n",
- walk_state->op_info->name);
- *out_op = op;
- return (AE_CTRL_SKIP);
- }
-#endif
*out_op = op;
return (AE_OK);
}
@@ -166,14 +149,15 @@ acpi_ds_load1_begin_op (
}
}
- path = acpi_ps_get_next_namestring (&walk_state->parser_state);
+ path = acpi_ps_get_next_namestring(&walk_state->parser_state);
/* Map the raw opcode into an internal object type */
object_type = walk_state->op_info->object_type;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name (object_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "State=%p Op=%p [%s]\n", walk_state, op,
+ acpi_ut_get_type_name(object_type)));
switch (walk_state->opcode) {
case AML_SCOPE_OP:
@@ -183,23 +167,27 @@ acpi_ds_load1_begin_op (
* that we can actually open the scope to enter new names underneath it.
* Allow search-to-root for single namesegs.
*/
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
-#ifdef _ACPI_ASL_COMPILER
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
+ walk_state, &(node));
+#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
/*
* Table disassembly:
* Target of Scope() not found. Generate an External for it, and
* insert the name into the namespace.
*/
- acpi_dm_add_to_external_list (path);
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
+ acpi_dm_add_to_external_list(path);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path,
+ object_type, ACPI_IMODE_LOAD_PASS1,
+ ACPI_NS_SEARCH_PARENT, walk_state,
+ &(node));
}
#endif
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (path, status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(path, status);
return (status);
}
@@ -208,7 +196,7 @@ acpi_ds_load1_begin_op (
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
- case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
@@ -232,9 +220,10 @@ acpi_ds_load1_begin_op (
* a warning
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
- path, acpi_ut_get_type_name (node->type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
+ path,
+ acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -244,15 +233,12 @@ acpi_ds_load1_begin_op (
/* All other types are an error */
- ACPI_REPORT_ERROR ((
- "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n",
- acpi_ut_get_type_name (node->type), path));
+ ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path));
return (AE_AML_OPERAND_TYPE);
}
break;
-
default:
/*
@@ -281,15 +267,15 @@ acpi_ds_load1_begin_op (
flags = ACPI_NS_NO_UPSEARCH;
if ((walk_state->opcode != AML_SCOPE_OP) &&
- (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
+ (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
flags |= ACPI_NS_ERROR_IF_FOUND;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
- acpi_ut_get_type_name (object_type)));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "[%s] Both Find or Create allowed\n",
- acpi_ut_get_type_name (object_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[%s] Cannot already exist\n",
+ acpi_ut_get_type_name(object_type)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "[%s] Both Find or Create allowed\n",
+ acpi_ut_get_type_name(object_type)));
}
/*
@@ -298,22 +284,23 @@ acpi_ds_load1_begin_op (
* involve arguments to the opcode must be created as we go back up the
* parse tree later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
- ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node));
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (path, status);
+ status =
+ acpi_ns_lookup(walk_state->scope_info, path, object_type,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state,
+ &(node));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(path, status);
return (status);
}
break;
}
-
/* Common exit */
if (!op) {
/* Create a new op */
- op = acpi_ps_alloc_op (walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
if (!op) {
return (AE_NO_MEMORY);
}
@@ -327,19 +314,18 @@ acpi_ds_load1_begin_op (
op->named.path = (u8 *) path;
#endif
-
/*
* Put the Node in the "op" object that the parser uses, so we
* can get it again quickly when this scope is closed
*/
op->common.node = node;
- acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
+ acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
+ op);
*out_op = op;
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load1_end_op
@@ -353,20 +339,17 @@ acpi_ds_load1_begin_op (
*
******************************************************************************/
-acpi_status
-acpi_ds_load1_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state)
{
- union acpi_parse_object *op;
- acpi_object_type object_type;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_NAME ("ds_load1_end_op");
+ union acpi_parse_object *op;
+ acpi_object_type object_type;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_NAME("ds_load1_end_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
/* We are only interested in opcodes that have an associated name */
@@ -380,21 +363,20 @@ acpi_ds_load1_end_op (
#ifndef ACPI_NO_METHOD_EXECUTION
if (walk_state->op_info->flags & AML_FIELD) {
- if (walk_state->opcode == AML_FIELD_OP ||
- walk_state->opcode == AML_BANK_FIELD_OP ||
- walk_state->opcode == AML_INDEX_FIELD_OP) {
- status = acpi_ds_init_field_objects (op, walk_state);
+ if (walk_state->opcode == AML_FIELD_OP ||
+ walk_state->opcode == AML_BANK_FIELD_OP ||
+ walk_state->opcode == AML_INDEX_FIELD_OP) {
+ status = acpi_ds_init_field_objects(op, walk_state);
}
return (status);
}
-
if (op->common.aml_opcode == AML_REGION_OP) {
- status = acpi_ex_create_region (op->named.data, op->named.length,
- (acpi_adr_space_type)
- ((op->common.value.arg)->common.value.integer),
- walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_create_region(op->named.data, op->named.length,
+ (acpi_adr_space_type)
+ ((op->common.value.arg)->common.
+ value.integer), walk_state);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -404,8 +386,11 @@ acpi_ds_load1_end_op (
/* For Name opcode, get the object type from the argument */
if (op->common.value.arg) {
- object_type = (acpi_ps_get_opcode_info (
- (op->common.value.arg)->common.aml_opcode))->object_type;
+ object_type = (acpi_ps_get_opcode_info((op->common.
+ value.arg)->
+ common.
+ aml_opcode))->
+ object_type;
op->common.node->type = (u8) object_type;
}
}
@@ -419,23 +404,26 @@ acpi_ds_load1_end_op (
* of invocations of the method (need to know the number of
* arguments.)
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "LOADING-Method: State=%p Op=%p named_obj=%p\n",
- walk_state, op, op->named.node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, op->named.node));
- if (!acpi_ns_get_attached_object (op->named.node)) {
- walk_state->operands[0] = (void *) op->named.node;
+ if (!acpi_ns_get_attached_object(op->named.node)) {
+ walk_state->operands[0] = (void *)op->named.node;
walk_state->num_operands = 1;
- status = acpi_ds_create_operands (walk_state, op->common.value.arg);
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_create_method (op->named.data,
- op->named.length, walk_state);
+ status =
+ acpi_ds_create_operands(walk_state,
+ op->common.value.arg);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ex_create_method(op->named.data,
+ op->named.length,
+ walk_state);
}
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -443,17 +431,17 @@ acpi_ds_load1_end_op (
/* Pop the scope stack */
- if (acpi_ns_opens_scope (object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
- acpi_ut_get_type_name (object_type), op));
+ if (acpi_ns_opens_scope(object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s): Popping scope for Op %p\n",
+ acpi_ut_get_type_name(object_type), op));
- status = acpi_ds_scope_stack_pop (walk_state);
+ status = acpi_ds_scope_stack_pop(walk_state);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_begin_op
@@ -468,36 +456,53 @@ acpi_ds_load1_end_op (
******************************************************************************/
acpi_status
-acpi_ds_load2_begin_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object **out_op)
+acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object ** out_op)
{
- union acpi_parse_object *op;
- struct acpi_namespace_node *node;
- acpi_status status;
- acpi_object_type object_type;
- char *buffer_ptr;
-
-
- ACPI_FUNCTION_TRACE ("ds_load2_begin_op");
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *buffer_ptr;
+ ACPI_FUNCTION_TRACE("ds_load2_begin_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+ walk_state));
if (op) {
+ if ((walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+ /* We are executing a while loop outside of a method */
+
+ status = acpi_ds_exec_begin_op(walk_state, out_op);
+ return_ACPI_STATUS(status);
+ }
+
/* We only care about Namespace opcodes here */
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
- (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
- (!(walk_state->op_info->flags & AML_NAMED))) {
+ (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
+ (!(walk_state->op_info->flags & AML_NAMED))) {
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
- (walk_state->op_info->class == AML_CLASS_CONTROL)) {
- ACPI_REPORT_WARNING ((
- "Encountered executable code at module level, [%s]\n",
- acpi_ps_get_opcode_name (walk_state->opcode)));
+ (walk_state->op_info->class == AML_CLASS_CONTROL)) {
+
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Begin/EXEC: %s (fl %8.8X)\n",
+ walk_state->op_info->name,
+ walk_state->op_info->flags));
+
+ /* Executing a type1 or type2 opcode outside of a method */
+
+ status =
+ acpi_ds_exec_begin_op(walk_state, out_op);
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (AE_OK);
+#endif
+ return_ACPI_STATUS(AE_OK);
}
/* Get the name we are going to enter or lookup in the namespace */
@@ -509,28 +514,27 @@ acpi_ds_load2_begin_op (
if (!buffer_ptr) {
/* No name, just exit */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- }
- else {
+ } else {
/* Get name from the op */
- buffer_ptr = (char *) &op->named.name;
+ buffer_ptr = (char *)&op->named.name;
}
- }
- else {
+ } else {
/* Get the namestring from the raw AML */
- buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
+ buffer_ptr =
+ acpi_ps_get_next_namestring(&walk_state->parser_state);
}
/* Map the opcode into an internal object type */
object_type = walk_state->op_info->object_type;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "State=%p Op=%p Type=%X\n", walk_state, op, object_type));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "State=%p Op=%p Type=%X\n", walk_state, op,
+ object_type));
switch (walk_state->opcode) {
case AML_FIELD_OP:
@@ -548,9 +552,10 @@ acpi_ds_load2_begin_op (
* Don't enter the name into the namespace, but look it up
* for use later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &(node));
break;
case AML_SCOPE_OP:
@@ -560,28 +565,28 @@ acpi_ds_load2_begin_op (
* Don't enter the name into the namespace, but look it up
* for use later.
*/
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
- walk_state, &(node));
- if (ACPI_FAILURE (status)) {
-#ifdef _ACPI_ASL_COMPILER
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+ if (ACPI_FAILURE(status)) {
+#ifdef ACPI_ASL_COMPILER
if (status == AE_NOT_FOUND) {
status = AE_OK;
- }
- else {
- ACPI_REPORT_NSERROR (buffer_ptr, status);
+ } else {
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
}
#else
- ACPI_REPORT_NSERROR (buffer_ptr, status);
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
#endif
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
* We must check to make sure that the target is
* one of the opcodes that actually opens a scope
*/
switch (node->type) {
- case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
@@ -602,9 +607,7 @@ acpi_ds_load2_begin_op (
* Scope (DEB) { ... }
*/
- ACPI_REPORT_WARNING ((
- "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
- buffer_ptr, acpi_ut_get_type_name (node->type)));
+ ACPI_REPORT_WARNING(("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", buffer_ptr, acpi_ut_get_type_name(node->type)));
node->type = ACPI_TYPE_ANY;
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
@@ -614,9 +617,7 @@ acpi_ds_load2_begin_op (
/* All other types are an error */
- ACPI_REPORT_ERROR ((
- "Invalid type (%s) for target of Scope operator [%4.4s]\n",
- acpi_ut_get_type_name (node->type), buffer_ptr));
+ ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s]\n", acpi_ut_get_type_name(node->type), buffer_ptr));
return (AE_AML_OPERAND_TYPE);
}
@@ -631,14 +632,16 @@ acpi_ds_load2_begin_op (
node = op->common.node;
- if (acpi_ns_opens_scope (object_type)) {
- status = acpi_ds_scope_stack_push (node, object_type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (acpi_ns_opens_scope(object_type)) {
+ status =
+ acpi_ds_scope_stack_push(node, object_type,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -657,24 +660,26 @@ acpi_ds_load2_begin_op (
break;
}
- status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH,
- walk_state, &(node));
+ /* Add new entry into namespace */
+
+ status =
+ acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+ object_type, ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_NO_UPSEARCH, walk_state, &(node));
break;
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_NSERROR (buffer_ptr, status);
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_NSERROR(buffer_ptr, status);
+ return_ACPI_STATUS(status);
}
-
if (!op) {
/* Create a new op */
- op = acpi_ps_alloc_op (walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
if (!op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new op */
@@ -682,9 +687,7 @@ acpi_ds_load2_begin_op (
if (node) {
op->named.name = node->name.integer;
}
- if (out_op) {
- *out_op = op;
- }
+ *out_op = op;
}
/*
@@ -693,10 +696,9 @@ acpi_ds_load2_begin_op (
*/
op->common.node = node;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_load2_end_op
@@ -710,39 +712,54 @@ acpi_ds_load2_begin_op (
*
******************************************************************************/
-acpi_status
-acpi_ds_load2_end_op (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
{
- union acpi_parse_object *op;
- acpi_status status = AE_OK;
- acpi_object_type object_type;
- struct acpi_namespace_node *node;
- union acpi_parse_object *arg;
- struct acpi_namespace_node *new_node;
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ acpi_object_type object_type;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *new_node;
#ifndef ACPI_NO_METHOD_EXECUTION
- u32 i;
+ u32 i;
#endif
-
- ACPI_FUNCTION_TRACE ("ds_load2_end_op");
+ ACPI_FUNCTION_TRACE("ds_load2_end_op");
op = walk_state->op;
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
- walk_state->op_info->name, op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
+ walk_state->op_info->name, op, walk_state));
- /* Only interested in opcodes that have namespace objects */
+ /* Check if opcode had an associated namespace object */
if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
- return_ACPI_STATUS (AE_OK);
+#ifndef ACPI_NO_METHOD_EXECUTION
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
+ /* No namespace object. Executable opcode? */
+
+ if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
+ (walk_state->op_info->class == AML_CLASS_CONTROL)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "End/EXEC: %s (fl %8.8X)\n",
+ walk_state->op_info->name,
+ walk_state->op_info->flags));
+
+ /* Executing a type1 or type2 opcode outside of a method */
+
+ status = acpi_ds_exec_end_op(walk_state);
+ return_ACPI_STATUS(status);
+ }
+#endif
+#endif
+ return_ACPI_STATUS(AE_OK);
}
if (op->common.aml_opcode == AML_SCOPE_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Ending scope Op=%p State=%p\n", op, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Ending scope Op=%p State=%p\n", op,
+ walk_state));
}
-
object_type = walk_state->op_info->object_type;
/*
@@ -755,18 +772,19 @@ acpi_ds_load2_end_op (
* Put the Node on the object stack (Contains the ACPI Name of
* this object)
*/
- walk_state->operands[0] = (void *) node;
+ walk_state->operands[0] = (void *)node;
walk_state->num_operands = 1;
/* Pop the scope stack */
- if (acpi_ns_opens_scope (object_type) &&
- (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
- acpi_ut_get_type_name (object_type), op));
+ if (acpi_ns_opens_scope(object_type) &&
+ (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name(object_type), op));
- status = acpi_ds_scope_stack_pop (walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_scope_stack_pop(walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
@@ -799,9 +817,10 @@ acpi_ds_load2_end_op (
* AML_THERMALZONE
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
+ acpi_ps_get_opcode_name(op->common.aml_opcode),
+ walk_state, op, node));
/* Decode the opcode */
@@ -816,27 +835,32 @@ acpi_ds_load2_end_op (
* Create the field object, but the field buffer and index must
* be evaluated later during the execution phase
*/
- status = acpi_ds_create_buffer_field (op, walk_state);
+ status = acpi_ds_create_buffer_field(op, walk_state);
break;
-
- case AML_TYPE_NAMED_FIELD:
+ case AML_TYPE_NAMED_FIELD:
switch (op->common.aml_opcode) {
case AML_INDEX_FIELD_OP:
- status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node,
- walk_state);
+ status =
+ acpi_ds_create_index_field(op,
+ (acpi_handle) arg->
+ common.node, walk_state);
break;
case AML_BANK_FIELD_OP:
- status = acpi_ds_create_bank_field (op, arg->common.node, walk_state);
+ status =
+ acpi_ds_create_bank_field(op, arg->common.node,
+ walk_state);
break;
case AML_FIELD_OP:
- status = acpi_ds_create_field (op, arg->common.node, walk_state);
+ status =
+ acpi_ds_create_field(op, arg->common.node,
+ walk_state);
break;
default:
@@ -845,43 +869,42 @@ acpi_ds_load2_end_op (
}
break;
+ case AML_TYPE_NAMED_SIMPLE:
- case AML_TYPE_NAMED_SIMPLE:
-
- status = acpi_ds_create_operands (walk_state, arg);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ds_create_operands(walk_state, arg);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
switch (op->common.aml_opcode) {
case AML_PROCESSOR_OP:
- status = acpi_ex_create_processor (walk_state);
+ status = acpi_ex_create_processor(walk_state);
break;
case AML_POWER_RES_OP:
- status = acpi_ex_create_power_resource (walk_state);
+ status = acpi_ex_create_power_resource(walk_state);
break;
case AML_MUTEX_OP:
- status = acpi_ex_create_mutex (walk_state);
+ status = acpi_ex_create_mutex(walk_state);
break;
case AML_EVENT_OP:
- status = acpi_ex_create_event (walk_state);
+ status = acpi_ex_create_event(walk_state);
break;
case AML_DATA_REGION_OP:
- status = acpi_ex_create_table_region (walk_state);
+ status = acpi_ex_create_table_region(walk_state);
break;
case AML_ALIAS_OP:
- status = acpi_ex_create_alias (walk_state);
+ status = acpi_ex_create_alias(walk_state);
break;
default:
@@ -894,12 +917,12 @@ acpi_ds_load2_end_op (
/* Delete operands */
for (i = 1; i < walk_state->num_operands; i++) {
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
break;
-#endif /* ACPI_NO_METHOD_EXECUTION */
+#endif /* ACPI_NO_METHOD_EXECUTION */
case AML_TYPE_NAMED_COMPLEX:
@@ -915,9 +938,10 @@ acpi_ds_load2_end_op (
* If we have a valid region, initialize it
* Namespace is NOT locked at this point.
*/
- status = acpi_ev_initialize_region (acpi_ns_get_attached_object (node),
- FALSE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_initialize_region
+ (acpi_ns_get_attached_object(node), FALSE);
+ if (ACPI_FAILURE(status)) {
/*
* If AE_NOT_EXIST is returned, it is not fatal
* because many regions get created before a handler
@@ -929,13 +953,11 @@ acpi_ds_load2_end_op (
}
break;
-
case AML_NAME_OP:
- status = acpi_ds_create_node (walk_state, node, op);
+ status = acpi_ds_create_node(walk_state, node, op);
break;
-#endif /* ACPI_NO_METHOD_EXECUTION */
-
+#endif /* ACPI_NO_METHOD_EXECUTION */
default:
/* All NAMED_COMPLEX opcodes must be handled above */
@@ -944,27 +966,29 @@ acpi_ds_load2_end_op (
}
break;
-
case AML_CLASS_INTERNAL:
/* case AML_INT_NAMEPATH_OP: */
break;
-
case AML_CLASS_METHOD_CALL:
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
- walk_state, op, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, node));
/*
* Lookup the method name and save the Node
*/
- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
- ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- walk_state, &(new_node));
- if (ACPI_SUCCESS (status)) {
+ status =
+ acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, walk_state,
+ &(new_node));
+ if (ACPI_SUCCESS(status)) {
+
/*
* Make sure that what we found is indeed a method
* We didn't search for a method on purpose, to see if the name
@@ -979,24 +1003,20 @@ acpi_ds_load2_end_op (
* parser uses, so we can get it again at the end of this scope
*/
op->common.node = new_node;
- }
- else {
- ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ } else {
+ ACPI_REPORT_NSERROR(arg->common.value.string, status);
}
break;
-
default:
break;
}
-cleanup:
+ cleanup:
/* Remove the Node pushed at the very beginning */
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index 21f4548ff323..defe956ef751 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswscope")
-
+ACPI_MODULE_NAME("dswscope")
/****************************************************************************
*
@@ -62,15 +59,11 @@
* root scope object (which remains at the stack top.)
*
***************************************************************************/
-
-void
-acpi_ds_scope_stack_clear (
- struct acpi_walk_state *walk_state)
+void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *scope_info;
-
- ACPI_FUNCTION_NAME ("ds_scope_stack_clear");
+ union acpi_generic_state *scope_info;
+ ACPI_FUNCTION_NAME("ds_scope_stack_clear");
while (walk_state->scope_info) {
/* Pop a scope off the stack */
@@ -78,14 +71,14 @@ acpi_ds_scope_stack_clear (
scope_info = walk_state->scope_info;
walk_state->scope_info = scope_info->scope.next;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Popped object type (%s)\n",
- acpi_ut_get_type_name (scope_info->common.value)));
- acpi_ut_delete_generic_state (scope_info);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Popped object type (%s)\n",
+ acpi_ut_get_type_name(scope_info->common.
+ value)));
+ acpi_ut_delete_generic_state(scope_info);
}
}
-
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_push
@@ -102,74 +95,70 @@ acpi_ds_scope_stack_clear (
***************************************************************************/
acpi_status
-acpi_ds_scope_stack_push (
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_walk_state *walk_state)
+acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *scope_info;
- union acpi_generic_state *old_scope_info;
-
-
- ACPI_FUNCTION_TRACE ("ds_scope_stack_push");
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *old_scope_info;
+ ACPI_FUNCTION_TRACE("ds_scope_stack_push");
if (!node) {
/* Invalid scope */
- ACPI_REPORT_ERROR (("ds_scope_stack_push: null scope passed\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ds_scope_stack_push: null scope passed\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Make sure object type is valid */
- if (!acpi_ut_valid_object_type (type)) {
- ACPI_REPORT_WARNING ((
- "ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+ if (!acpi_ut_valid_object_type(type)) {
+ ACPI_REPORT_WARNING(("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
}
/* Allocate a new scope object */
- scope_info = acpi_ut_create_generic_state ();
+ scope_info = acpi_ut_create_generic_state();
if (!scope_info) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init new scope object */
scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
- scope_info->scope.node = node;
- scope_info->common.value = (u16) type;
+ scope_info->scope.node = node;
+ scope_info->common.value = (u16) type;
walk_state->scope_depth++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[%.2d] Pushed scope ", (u32) walk_state->scope_depth));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%.2d] Pushed scope ",
+ (u32) walk_state->scope_depth));
old_scope_info = walk_state->scope_info;
if (old_scope_info) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[%4.4s] (%s)",
- acpi_ut_get_node_name (old_scope_info->scope.node),
- acpi_ut_get_type_name (old_scope_info->common.value)));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[\\___] (%s)", "ROOT"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ "[%4.4s] (%s)",
+ acpi_ut_get_node_name(old_scope_info->
+ scope.node),
+ acpi_ut_get_type_name(old_scope_info->
+ common.value)));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT"));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- ", New scope -> [%4.4s] (%s)\n",
- acpi_ut_get_node_name (scope_info->scope.node),
- acpi_ut_get_type_name (scope_info->common.value)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ ", New scope -> [%4.4s] (%s)\n",
+ acpi_ut_get_node_name(scope_info->scope.node),
+ acpi_ut_get_type_name(scope_info->common.value)));
/* Push new scope object onto stack */
- acpi_ut_push_generic_state (&walk_state->scope_info, scope_info);
- return_ACPI_STATUS (AE_OK);
+ acpi_ut_push_generic_state(&walk_state->scope_info, scope_info);
+ return_ACPI_STATUS(AE_OK);
}
-
/****************************************************************************
*
* FUNCTION: acpi_ds_scope_stack_pop
@@ -182,47 +171,41 @@ acpi_ds_scope_stack_push (
*
***************************************************************************/
-acpi_status
-acpi_ds_scope_stack_pop (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *scope_info;
- union acpi_generic_state *new_scope_info;
-
-
- ACPI_FUNCTION_TRACE ("ds_scope_stack_pop");
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *new_scope_info;
+ ACPI_FUNCTION_TRACE("ds_scope_stack_pop");
/*
* Pop scope info object off the stack.
*/
- scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info);
+ scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info);
if (!scope_info) {
- return_ACPI_STATUS (AE_STACK_UNDERFLOW);
+ return_ACPI_STATUS(AE_STACK_UNDERFLOW);
}
walk_state->scope_depth--;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
- (u32) walk_state->scope_depth,
- acpi_ut_get_node_name (scope_info->scope.node),
- acpi_ut_get_type_name (scope_info->common.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
+ (u32) walk_state->scope_depth,
+ acpi_ut_get_node_name(scope_info->scope.node),
+ acpi_ut_get_type_name(scope_info->common.value)));
new_scope_info = walk_state->scope_info;
if (new_scope_info) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[%4.4s] (%s)\n",
- acpi_ut_get_node_name (new_scope_info->scope.node),
- acpi_ut_get_type_name (new_scope_info->common.value)));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
- "[\\___] (ROOT)\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
+ "[%4.4s] (%s)\n",
+ acpi_ut_get_node_name(new_scope_info->
+ scope.node),
+ acpi_ut_get_type_name(new_scope_info->
+ common.value)));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n"));
}
- acpi_ut_delete_generic_state (scope_info);
- return_ACPI_STATUS (AE_OK);
+ acpi_ut_delete_generic_state(scope_info);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 9cd3db652b31..7d68a5aaf3c4 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -41,37 +41,28 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_DISPATCHER
- ACPI_MODULE_NAME ("dswstate")
+ACPI_MODULE_NAME("dswstate")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_status
-acpi_ds_result_insert (
- void *object,
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_result_insert(void *object,
+ u32 index, struct acpi_walk_state *walk_state);
-acpi_status
-acpi_ds_obj_stack_delete_all (
- struct acpi_walk_state *walk_state);
+acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state);
acpi_status
-acpi_ds_obj_stack_pop_object (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state);
-
-void *
-acpi_ds_obj_stack_get_value (
- u32 index,
- struct acpi_walk_state *walk_state);
+acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state);
+
+void *acpi_ds_obj_stack_get_value(u32 index,
+ struct acpi_walk_state *walk_state);
#endif
#ifdef ACPI_FUTURE_USAGE
@@ -92,36 +83,35 @@ acpi_ds_obj_stack_get_value (
******************************************************************************/
acpi_status
-acpi_ds_result_remove (
- union acpi_operand_object **object,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_remove(union acpi_operand_object **object,
+ u32 index, struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_remove");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_remove");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_MAX_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index out of range: %X State=%p Num=%X\n",
- index, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index out of range: %X State=%p Num=%X\n",
+ index, walk_state,
+ state->results.num_results));
}
/* Check for a valid result object */
- if (!state->results.obj_desc [index]) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X, Index=%X\n",
- walk_state, state->results.num_results, index));
+ if (!state->results.obj_desc[index]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X, Index=%X\n",
+ walk_state, state->results.num_results,
+ index));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -129,18 +119,20 @@ acpi_ds_result_remove (
state->results.num_results--;
- *object = state->results.obj_desc [index];
- state->results.obj_desc [index] = NULL;
+ *object = state->results.obj_desc[index];
+ state->results.obj_desc[index] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
- *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- index, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object,
+ (*object) ? acpi_ut_get_object_type_name(*object) :
+ "NULL", index, walk_state,
+ state->results.num_results));
return (AE_OK);
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -157,16 +149,13 @@ acpi_ds_result_remove (
******************************************************************************/
acpi_status
-acpi_ds_result_pop (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_pop(union acpi_operand_object ** object,
+ struct acpi_walk_state * walk_state)
{
- acpi_native_uint index;
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_pop");
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_pop");
state = walk_state->results;
if (!state) {
@@ -174,8 +163,9 @@ acpi_ds_result_pop (
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Result stack is empty! State=%p\n",
+ walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
@@ -186,26 +176,27 @@ acpi_ds_result_pop (
for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
/* Check for a valid result object */
- if (state->results.obj_desc [index -1]) {
- *object = state->results.obj_desc [index -1];
- state->results.obj_desc [index -1] = NULL;
+ if (state->results.obj_desc[index - 1]) {
+ *object = state->results.obj_desc[index - 1];
+ state->results.obj_desc[index - 1] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] Index=%X State=%p Num=%X\n",
- *object,
- (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- (u32) index -1, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object,
+ (*object) ?
+ acpi_ut_get_object_type_name(*object)
+ : "NULL", (u32) index - 1, walk_state,
+ state->results.num_results));
return (AE_OK);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No result objects! State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result objects! State=%p\n", walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_pop_from_bottom
@@ -221,38 +212,37 @@ acpi_ds_result_pop (
******************************************************************************/
acpi_status
-acpi_ds_result_pop_from_bottom (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
+ struct acpi_walk_state * walk_state)
{
- acpi_native_uint index;
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_pop_from_bottom");
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_pop_from_bottom");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Warning: No result object pushed! State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Warning: No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (!state->results.num_results) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result objects! State=%p\n", walk_state));
return (AE_AML_NO_RETURN_VALUE);
}
/* Remove Bottom element */
- *object = state->results.obj_desc [0];
+ *object = state->results.obj_desc[0];
/* Push entire stack down one element */
for (index = 0; index < state->results.num_results; index++) {
- state->results.obj_desc [index] = state->results.obj_desc [index + 1];
+ state->results.obj_desc[index] =
+ state->results.obj_desc[index + 1];
}
state->results.num_results--;
@@ -260,20 +250,21 @@ acpi_ds_result_pop_from_bottom (
/* Check for a valid result object */
if (!*object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X, Index=%X\n",
- walk_state, state->results.num_results, (u32) index));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X Index=%X\n",
+ walk_state, state->results.num_results,
+ (u32) index));
return (AE_AML_NO_RETURN_VALUE);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n",
- *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
- state, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n",
+ *object,
+ (*object) ? acpi_ut_get_object_type_name(*object) :
+ "NULL", state, walk_state));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_push
@@ -288,47 +279,50 @@ acpi_ds_result_pop_from_bottom (
******************************************************************************/
acpi_status
-acpi_ds_result_push (
- union acpi_operand_object *object,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_push(union acpi_operand_object * object,
+ struct acpi_walk_state * walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_push");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_push");
state = walk_state->results;
if (!state) {
- ACPI_REPORT_ERROR (("No result stack frame during push\n"));
+ ACPI_REPORT_ERROR(("No result stack frame during push\n"));
return (AE_AML_INTERNAL);
}
if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Result stack overflow: Obj=%p State=%p Num=%X\n",
- object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Result stack overflow: Obj=%p State=%p Num=%X\n",
+ object, walk_state,
+ state->results.num_results));
return (AE_STACK_OVERFLOW);
}
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null Object! Obj=%p State=%p Num=%X\n",
- object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null Object! Obj=%p State=%p Num=%X\n",
+ object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
- state->results.obj_desc [state->results.num_results] = object;
+ state->results.obj_desc[state->results.num_results] = object;
state->results.num_results++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
- object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
- walk_state, state->results.num_results, walk_state->current_result));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object,
+ object ?
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object) : "NULL",
+ walk_state, state->results.num_results,
+ walk_state->current_result));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_push
@@ -341,30 +335,26 @@ acpi_ds_result_push (
*
******************************************************************************/
-acpi_status
-acpi_ds_result_stack_push (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state)
{
- union acpi_generic_state *state;
-
- ACPI_FUNCTION_NAME ("ds_result_stack_push");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_stack_push");
- state = acpi_ut_create_generic_state ();
+ state = acpi_ut_create_generic_state();
if (!state) {
return (AE_NO_MEMORY);
}
state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
- acpi_ut_push_generic_state (&walk_state->results, state);
+ acpi_ut_push_generic_state(&walk_state->results, state);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
- state, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
+ state, walk_state));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_stack_pop
@@ -377,35 +367,31 @@ acpi_ds_result_stack_push (
*
******************************************************************************/
-acpi_status
-acpi_ds_result_stack_pop (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
{
- union acpi_generic_state *state;
-
- ACPI_FUNCTION_NAME ("ds_result_stack_pop");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_stack_pop");
/* Check for stack underflow */
if (walk_state->results == NULL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n",
+ walk_state));
return (AE_AML_NO_OPERAND);
}
- state = acpi_ut_pop_generic_state (&walk_state->results);
+ state = acpi_ut_pop_generic_state(&walk_state->results);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Result=%p remaining_results=%X State=%p\n",
- state, state->results.num_results, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Result=%p remaining_results=%X State=%p\n",
+ state, state->results.num_results, walk_state));
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_push
@@ -420,35 +406,35 @@ acpi_ds_result_stack_pop (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_push (
- void *object,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
{
- ACPI_FUNCTION_NAME ("ds_obj_stack_push");
-
+ ACPI_FUNCTION_NAME("ds_obj_stack_push");
/* Check for stack overflow */
if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "overflow! Obj=%p State=%p #Ops=%X\n",
- object, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "overflow! Obj=%p State=%p #Ops=%X\n",
+ object, walk_state,
+ walk_state->num_operands));
return (AE_STACK_OVERFLOW);
}
/* Put the object onto the stack */
- walk_state->operands [walk_state->num_operands] = object;
+ walk_state->operands[walk_state->num_operands] = object;
walk_state->num_operands++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
- object, acpi_ut_get_object_type_name ((union acpi_operand_object *) object),
- walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ object,
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object), walk_state,
+ walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop
@@ -464,38 +450,35 @@ acpi_ds_obj_stack_push (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop (
- u32 pop_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
{
- u32 i;
-
- ACPI_FUNCTION_NAME ("ds_obj_stack_pop");
+ u32 i;
+ ACPI_FUNCTION_NAME("ds_obj_stack_pop");
for (i = 0; i < pop_count; i++) {
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
/* Just set the stack entry to null */
walk_state->num_operands--;
- walk_state->operands [walk_state->num_operands] = NULL;
+ walk_state->operands[walk_state->num_operands] = NULL;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
pop_count, walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop_and_delete
@@ -511,44 +494,43 @@ acpi_ds_obj_stack_pop (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop_and_delete (
- u32 pop_count,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
+ struct acpi_walk_state * walk_state)
{
- u32 i;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete");
+ u32 i;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete");
for (i = 0; i < pop_count; i++) {
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Underflow! Count=%X State=%p #Ops=%X\n",
- pop_count, walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state,
+ walk_state->num_operands));
return (AE_STACK_UNDERFLOW);
}
/* Pop the stack and delete an object if present in this stack entry */
walk_state->num_operands--;
- obj_desc = walk_state->operands [walk_state->num_operands];
+ obj_desc = walk_state->operands[walk_state->num_operands];
if (obj_desc) {
- acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]);
- walk_state->operands [walk_state->num_operands] = NULL;
+ acpi_ut_remove_reference(walk_state->
+ operands[walk_state->
+ num_operands]);
+ walk_state->operands[walk_state->num_operands] = NULL;
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
pop_count, walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_get_current_walk_state
@@ -562,25 +544,21 @@ acpi_ds_obj_stack_pop_and_delete (
*
******************************************************************************/
-struct acpi_walk_state *
-acpi_ds_get_current_walk_state (
- struct acpi_thread_state *thread)
-
+struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
+ *thread)
{
- ACPI_FUNCTION_NAME ("ds_get_current_walk_state");
-
+ ACPI_FUNCTION_NAME("ds_get_current_walk_state");
if (!thread) {
return (NULL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current walk_state %p\n",
- thread->walk_state_list));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n",
+ thread->walk_state_list));
return (thread->walk_state_list);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_push_walk_state
@@ -595,20 +573,17 @@ acpi_ds_get_current_walk_state (
******************************************************************************/
void
-acpi_ds_push_walk_state (
- struct acpi_walk_state *walk_state,
- struct acpi_thread_state *thread)
+acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
+ struct acpi_thread_state *thread)
{
- ACPI_FUNCTION_TRACE ("ds_push_walk_state");
-
+ ACPI_FUNCTION_TRACE("ds_push_walk_state");
- walk_state->next = thread->walk_state_list;
+ walk_state->next = thread->walk_state_list;
thread->walk_state_list = walk_state;
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_pop_walk_state
@@ -623,15 +598,11 @@ acpi_ds_push_walk_state (
*
******************************************************************************/
-struct acpi_walk_state *
-acpi_ds_pop_walk_state (
- struct acpi_thread_state *thread)
+struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
{
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("ds_pop_walk_state");
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ds_pop_walk_state");
walk_state = thread->walk_state_list;
@@ -647,10 +618,9 @@ acpi_ds_pop_walk_state (
*/
}
- return_PTR (walk_state);
+ return_PTR(walk_state);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_create_walk_state
@@ -667,57 +637,55 @@ acpi_ds_pop_walk_state (
*
******************************************************************************/
-struct acpi_walk_state *
-acpi_ds_create_walk_state (
- acpi_owner_id owner_id,
- union acpi_parse_object *origin,
- union acpi_operand_object *mth_desc,
- struct acpi_thread_state *thread)
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
+ union acpi_parse_object
+ *origin,
+ union acpi_operand_object
+ *mth_desc,
+ struct acpi_thread_state
+ *thread)
{
- struct acpi_walk_state *walk_state;
- acpi_status status;
-
+ struct acpi_walk_state *walk_state;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ds_create_walk_state");
+ ACPI_FUNCTION_TRACE("ds_create_walk_state");
-
- walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK);
+ walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state));
if (!walk_state) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- walk_state->data_type = ACPI_DESC_TYPE_WALK;
- walk_state->owner_id = owner_id;
- walk_state->origin = origin;
- walk_state->method_desc = mth_desc;
- walk_state->thread = thread;
+ walk_state->data_type = ACPI_DESC_TYPE_WALK;
+ walk_state->owner_id = owner_id;
+ walk_state->origin = origin;
+ walk_state->method_desc = mth_desc;
+ walk_state->thread = thread;
walk_state->parser_state.start_op = origin;
/* Init the method args/local */
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
- acpi_ds_method_data_init (walk_state);
+ acpi_ds_method_data_init(walk_state);
#endif
/* Create an initial result stack entry */
- status = acpi_ds_result_stack_push (walk_state);
- if (ACPI_FAILURE (status)) {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
- return_PTR (NULL);
+ status = acpi_ds_result_stack_push(walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(walk_state);
+ return_PTR(NULL);
}
/* Put the new state at the head of the walk list */
if (thread) {
- acpi_ds_push_walk_state (walk_state, thread);
+ acpi_ds_push_walk_state(walk_state, thread);
}
- return_PTR (walk_state);
+ return_PTR(walk_state);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_init_aml_walk
@@ -737,70 +705,70 @@ acpi_ds_create_walk_state (
******************************************************************************/
acpi_status
-acpi_ds_init_aml_walk (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- struct acpi_namespace_node *method_node,
- u8 *aml_start,
- u32 aml_length,
- struct acpi_parameter_info *info,
- u32 pass_number)
+acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *method_node,
+ u8 * aml_start,
+ u32 aml_length,
+ struct acpi_parameter_info *info, u8 pass_number)
{
- acpi_status status;
- struct acpi_parse_state *parser_state = &walk_state->parser_state;
- union acpi_parse_object *extra_op;
+ acpi_status status;
+ struct acpi_parse_state *parser_state = &walk_state->parser_state;
+ union acpi_parse_object *extra_op;
+ ACPI_FUNCTION_TRACE("ds_init_aml_walk");
- ACPI_FUNCTION_TRACE ("ds_init_aml_walk");
-
-
- walk_state->parser_state.aml =
- walk_state->parser_state.aml_start = aml_start;
+ walk_state->parser_state.aml =
+ walk_state->parser_state.aml_start = aml_start;
walk_state->parser_state.aml_end =
- walk_state->parser_state.pkg_end = aml_start + aml_length;
+ walk_state->parser_state.pkg_end = aml_start + aml_length;
/* The next_op of the next_walk will be the beginning of the method */
walk_state->next_op = NULL;
+ walk_state->pass_number = pass_number;
if (info) {
if (info->parameter_type == ACPI_PARAM_GPE) {
- walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
- info->parameters);
- }
- else {
- walk_state->params = info->parameters;
+ walk_state->gpe_event_info =
+ ACPI_CAST_PTR(struct acpi_gpe_event_info,
+ info->parameters);
+ } else {
+ walk_state->params = info->parameters;
walk_state->caller_return_desc = &info->return_object;
}
}
- status = acpi_ps_init_scope (&walk_state->parser_state, op);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ps_init_scope(&walk_state->parser_state, op);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (method_node) {
walk_state->parser_state.start_node = method_node;
- walk_state->walk_type = ACPI_WALK_METHOD;
- walk_state->method_node = method_node;
- walk_state->method_desc = acpi_ns_get_attached_object (method_node);
+ walk_state->walk_type = ACPI_WALK_METHOD;
+ walk_state->method_node = method_node;
+ walk_state->method_desc =
+ acpi_ns_get_attached_object(method_node);
/* Push start scope on scope stack and make it current */
- status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Init the method arguments */
- status = acpi_ds_method_data_init_args (walk_state->params,
- ACPI_METHOD_NUM_ARGS, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_init_args(walk_state->params,
+ ACPI_METHOD_NUM_ARGS,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/*
* Setup the current scope.
* Find a Named Op that has a namespace node associated with it.
@@ -814,27 +782,27 @@ acpi_ds_init_aml_walk (
if (!extra_op) {
parser_state->start_node = NULL;
- }
- else {
+ } else {
parser_state->start_node = extra_op->common.node;
}
if (parser_state->start_node) {
/* Push start scope on scope stack and make it current */
- status = acpi_ds_scope_stack_push (parser_state->start_node,
- parser_state->start_node->type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_scope_stack_push(parser_state->start_node,
+ parser_state->start_node->
+ type, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
- status = acpi_ds_init_callbacks (walk_state, pass_number);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_callbacks(walk_state, pass_number);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_delete_walk_state
@@ -847,29 +815,27 @@ acpi_ds_init_aml_walk (
*
******************************************************************************/
-void
-acpi_ds_delete_walk_state (
- struct acpi_walk_state *walk_state)
+void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_delete_walk_state", walk_state);
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state);
if (!walk_state) {
return;
}
if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p is not a valid walk state\n",
+ walk_state));
return;
}
if (walk_state->parser_state.scope) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p walk still has a scope list\n",
+ walk_state));
}
/* Always must free any linked control states */
@@ -878,7 +844,7 @@ acpi_ds_delete_walk_state (
state = walk_state->control_state;
walk_state->control_state = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
/* Always must free any linked parse states */
@@ -887,7 +853,7 @@ acpi_ds_delete_walk_state (
state = walk_state->scope_info;
walk_state->scope_info = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
/* Always must free any stacked result states */
@@ -896,40 +862,12 @@ acpi_ds_delete_walk_state (
state = walk_state->results;
walk_state->results = state->common.next;
- acpi_ut_delete_generic_state (state);
+ acpi_ut_delete_generic_state(state);
}
- acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/******************************************************************************
- *
- * FUNCTION: acpi_ds_delete_walk_state_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ds_delete_walk_state_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK);
+ ACPI_MEM_FREE(walk_state);
return_VOID;
}
-#endif
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
@@ -947,50 +885,53 @@ acpi_ds_delete_walk_state_cache (
******************************************************************************/
acpi_status
-acpi_ds_result_insert (
- void *object,
- u32 index,
- struct acpi_walk_state *walk_state)
+acpi_ds_result_insert(void *object,
+ u32 index, struct acpi_walk_state *walk_state)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_NAME ("ds_result_insert");
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_NAME("ds_result_insert");
state = walk_state->results;
if (!state) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
- walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No result object pushed! State=%p\n",
+ walk_state));
return (AE_NOT_EXIST);
}
if (index >= ACPI_OBJ_NUM_OPERANDS) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index out of range: %X Obj=%p State=%p Num=%X\n",
- index, object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index out of range: %X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
- index, object, walk_state, state->results.num_results));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state,
+ state->results.num_results));
return (AE_BAD_PARAMETER);
}
- state->results.obj_desc [index] = object;
+ state->results.obj_desc[index] = object;
state->results.num_results++;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
- object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
- walk_state, state->results.num_results, walk_state->current_result));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object,
+ object ?
+ acpi_ut_get_object_type_name((union
+ acpi_operand_object *)
+ object) : "NULL",
+ walk_state, state->results.num_results,
+ walk_state->current_result));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_delete_all
@@ -1004,29 +945,24 @@ acpi_ds_result_insert (
*
******************************************************************************/
-acpi_status
-acpi_ds_obj_stack_delete_all (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_delete_all", walk_state);
+ u32 i;
+ ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state);
/* The stack size is configurable, but fixed */
for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) {
if (walk_state->operands[i]) {
- acpi_ut_remove_reference (walk_state->operands[i]);
+ acpi_ut_remove_reference(walk_state->operands[i]);
walk_state->operands[i] = NULL;
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_pop_object
@@ -1042,19 +978,17 @@ acpi_ds_obj_stack_delete_all (
******************************************************************************/
acpi_status
-acpi_ds_obj_stack_pop_object (
- union acpi_operand_object **object,
- struct acpi_walk_state *walk_state)
+acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_NAME ("ds_obj_stack_pop_object");
-
+ ACPI_FUNCTION_NAME("ds_obj_stack_pop_object");
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Missing operand/stack empty! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Missing operand/stack empty! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
@@ -1065,27 +999,26 @@ acpi_ds_obj_stack_pop_object (
/* Check for a valid operand */
- if (!walk_state->operands [walk_state->num_operands]) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null operand! State=%p #Ops=%X\n",
- walk_state, walk_state->num_operands));
+ if (!walk_state->operands[walk_state->num_operands]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
*object = NULL;
return (AE_AML_NO_OPERAND);
}
/* Get operand and set stack entry to null */
- *object = walk_state->operands [walk_state->num_operands];
- walk_state->operands [walk_state->num_operands] = NULL;
+ *object = walk_state->operands[walk_state->num_operands];
+ walk_state->operands[walk_state->num_operands] = NULL;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
- *object, acpi_ut_get_object_type_name (*object),
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ *object, acpi_ut_get_object_type_name(*object),
walk_state, walk_state->num_operands));
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_obj_stack_get_value
@@ -1101,30 +1034,25 @@ acpi_ds_obj_stack_pop_object (
*
******************************************************************************/
-void *
-acpi_ds_obj_stack_get_value (
- u32 index,
- struct acpi_walk_state *walk_state)
+void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_get_value", walk_state);
-
+ ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_get_value", walk_state);
/* Can't do it if the stack is empty */
if (walk_state->num_operands == 0) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* or if the index is past the top of the stack */
if (index > (walk_state->num_operands - (u32) 1)) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) -
- index]);
+ return_PTR(walk_state->
+ operands[(acpi_native_uint) (walk_state->num_operands - 1) -
+ index]);
}
#endif
-
-
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 1ac5731d45e5..7e1a445955bc 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -38,130 +38,112 @@
#include <acpi/actypes.h>
#define _COMPONENT ACPI_EC_COMPONENT
-ACPI_MODULE_NAME ("acpi_ec")
-
+ACPI_MODULE_NAME("acpi_ec")
#define ACPI_EC_COMPONENT 0x00100000
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_HID "PNP0C09"
#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
-
-
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
-
#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */
#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */
-
#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
-
-#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
-
+#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
+#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
#define ACPI_EC_COMMAND_READ 0x80
#define ACPI_EC_COMMAND_WRITE 0x81
#define ACPI_EC_BURST_ENABLE 0x82
#define ACPI_EC_BURST_DISABLE 0x83
#define ACPI_EC_COMMAND_QUERY 0x84
-
#define EC_POLLING 0xFF
#define EC_BURST 0x00
-
-
-static int acpi_ec_remove (struct acpi_device *device, int type);
-static int acpi_ec_start (struct acpi_device *device);
-static int acpi_ec_stop (struct acpi_device *device, int type);
-static int acpi_ec_burst_add ( struct acpi_device *device);
-static int acpi_ec_polling_add ( struct acpi_device *device);
+static int acpi_ec_remove(struct acpi_device *device, int type);
+static int acpi_ec_start(struct acpi_device *device);
+static int acpi_ec_stop(struct acpi_device *device, int type);
+static int acpi_ec_burst_add(struct acpi_device *device);
+static int acpi_ec_polling_add(struct acpi_device *device);
static struct acpi_driver acpi_ec_driver = {
- .name = ACPI_EC_DRIVER_NAME,
- .class = ACPI_EC_CLASS,
- .ids = ACPI_EC_HID,
- .ops = {
- .add = acpi_ec_polling_add,
- .remove = acpi_ec_remove,
- .start = acpi_ec_start,
- .stop = acpi_ec_stop,
- },
+ .name = ACPI_EC_DRIVER_NAME,
+ .class = ACPI_EC_CLASS,
+ .ids = ACPI_EC_HID,
+ .ops = {
+ .add = acpi_ec_polling_add,
+ .remove = acpi_ec_remove,
+ .start = acpi_ec_start,
+ .stop = acpi_ec_stop,
+ },
};
union acpi_ec {
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
} common;
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
- unsigned int expect_event;
- atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
- atomic_t pending_gpe;
- struct semaphore sem;
- wait_queue_head_t wait;
- }burst;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ unsigned int expect_event;
+ atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
+ atomic_t pending_gpe;
+ struct semaphore sem;
+ wait_queue_head_t wait;
+ } burst;
struct {
- u32 mode;
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
- spinlock_t lock;
- }polling;
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ spinlock_t lock;
+ } polling;
};
-static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event);
+static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event);
static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data);
-static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data);
-static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data);
-static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data);
-static void acpi_ec_gpe_polling_query ( void *ec_cxt);
-static void acpi_ec_gpe_burst_query ( void *ec_cxt);
-static u32 acpi_ec_gpe_polling_handler ( void *data);
-static u32 acpi_ec_gpe_burst_handler ( void *data);
+static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data);
+static void acpi_ec_gpe_polling_query(void *ec_cxt);
+static void acpi_ec_gpe_burst_query(void *ec_cxt);
+static u32 acpi_ec_gpe_polling_handler(void *data);
+static u32 acpi_ec_gpe_burst_handler(void *data);
static acpi_status __init
-acpi_fake_ecdt_polling_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval);
+acpi_fake_ecdt_polling_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval);
static acpi_status __init
-acpi_fake_ecdt_burst_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval);
-
-static int __init
-acpi_ec_polling_get_real_ecdt(void);
-static int __init
-acpi_ec_burst_get_real_ecdt(void);
+acpi_fake_ecdt_burst_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval);
+
+static int __init acpi_ec_polling_get_real_ecdt(void);
+static int __init acpi_ec_burst_get_real_ecdt(void);
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
-static union acpi_ec *ec_ecdt;
+static union acpi_ec *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
@@ -173,30 +155,24 @@ static int acpi_ec_polling_mode = EC_POLLING;
static inline u32 acpi_ec_read_status(union acpi_ec *ec)
{
- u32 status = 0;
+ u32 status = 0;
acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
return status;
}
-static int
-acpi_ec_wait (
- union acpi_ec *ec,
- u8 event)
+static int acpi_ec_wait(union acpi_ec *ec, u8 event)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_wait (ec, event);
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_wait(ec, event);
else
- return acpi_ec_burst_wait (ec, event);
+ return acpi_ec_burst_wait(ec, event);
}
-static int
-acpi_ec_polling_wait (
- union acpi_ec *ec,
- u8 event)
+static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
{
- u32 acpi_ec_status = 0;
- u32 i = ACPI_EC_UDELAY_COUNT;
+ u32 acpi_ec_status = 0;
+ u32 i = ACPI_EC_UDELAY_COUNT;
if (!ec)
return -EINVAL;
@@ -205,19 +181,21 @@ acpi_ec_polling_wait (
switch (event) {
case ACPI_EC_EVENT_OBF:
do {
- acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ acpi_hw_low_level_read(8, &acpi_ec_status,
+ &ec->common.status_addr);
if (acpi_ec_status & ACPI_EC_FLAG_OBF)
return 0;
udelay(ACPI_EC_UDELAY);
- } while (--i>0);
+ } while (--i > 0);
break;
case ACPI_EC_EVENT_IBE:
do {
- acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ acpi_hw_low_level_read(8, &acpi_ec_status,
+ &ec->common.status_addr);
if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
return 0;
udelay(ACPI_EC_UDELAY);
- } while (--i>0);
+ } while (--i > 0);
break;
default:
return -EINVAL;
@@ -227,25 +205,36 @@ acpi_ec_polling_wait (
}
static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_wait");
ec->burst.expect_event = event;
smp_mb();
- result = wait_event_interruptible_timeout(ec->burst.wait,
- !ec->burst.expect_event,
- msecs_to_jiffies(ACPI_EC_DELAY));
-
- ec->burst.expect_event = 0;
- smp_mb();
+ switch (event) {
+ case ACPI_EC_EVENT_OBF:
+ if (acpi_ec_read_status(ec) & event) {
+ ec->burst.expect_event = 0;
+ return_VALUE(0);
+ }
+ break;
- if (result < 0){
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result));
- return_VALUE(result);
+ case ACPI_EC_EVENT_IBE:
+ if (~acpi_ec_read_status(ec) & event) {
+ ec->burst.expect_event = 0;
+ return_VALUE(0);
+ }
+ break;
}
+ result = wait_event_timeout(ec->burst.wait,
+ !ec->burst.expect_event,
+ msecs_to_jiffies(ACPI_EC_DELAY));
+
+ ec->burst.expect_event = 0;
+ smp_mb();
+
/*
* Verify that the event in question has actually happened by
* querying EC status. Do the check even if operation timed-out
@@ -266,95 +255,65 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
return_VALUE(-ETIME);
}
-
-
-static int
-acpi_ec_enter_burst_mode (
- union acpi_ec *ec)
+static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
{
- u32 tmp = 0;
- int status = 0;
+ u32 tmp = 0;
+ int status = 0;
ACPI_FUNCTION_TRACE("acpi_ec_enter_burst_mode");
status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- !(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
+ if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status)
+ goto end;
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ if (status)
return_VALUE(-EINVAL);
- }
acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if(tmp != 0x90 ) {/* Burst ACK byte*/
+ if (tmp != 0x90) { /* Burst ACK byte */
return_VALUE(-EINVAL);
}
}
- atomic_set(&ec->burst.leaving_burst , 0);
+ atomic_set(&ec->burst.leaving_burst, 0);
return_VALUE(0);
+ end:
+ printk("Error in acpi_ec_wait\n");
+ return_VALUE(-1);
}
-static int
-acpi_ec_leave_burst_mode (
- union acpi_ec *ec)
+static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
{
- int status =0;
ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
- atomic_set(&ec->burst.leaving_burst , 1);
- status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- (status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n"));
- return_VALUE(-EINVAL);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = acpi_ec_read_status(ec);
- }
-
+ atomic_set(&ec->burst.leaving_burst, 1);
return_VALUE(0);
}
-static int
-acpi_ec_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_read(ec, address, data);
else
return acpi_ec_burst_read(ec, address, data);
}
-static int
-acpi_ec_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_write(ec, address, data);
else
return acpi_ec_burst_write(ec, address, data);
}
-static int
-acpi_ec_polling_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
{
- acpi_status status = AE_OK;
- int result = 0;
- unsigned long flags = 0;
- u32 glk = 0;
+ acpi_status status = AE_OK;
+ int result = 0;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_read");
@@ -371,7 +330,8 @@ acpi_ec_polling_read (
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (result)
goto end;
@@ -384,9 +344,9 @@ acpi_ec_polling_read (
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
-
-end:
+ *data, address));
+
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -395,17 +355,12 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_ec_polling_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
{
- int result = 0;
- acpi_status status = AE_OK;
- unsigned long flags = 0;
- u32 glk = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_write");
@@ -420,7 +375,8 @@ acpi_ec_polling_write (
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (result)
goto end;
@@ -436,9 +392,9 @@ acpi_ec_polling_write (
goto end;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
+ data, address));
-end:
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -447,21 +403,16 @@ end:
return_VALUE(result);
}
-static int
-acpi_ec_burst_read (
- union acpi_ec *ec,
- u8 address,
- u32 *data)
+static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
{
- int status = 0;
- u32 glk;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_read");
if (!ec || !data)
return_VALUE(-EINVAL);
-retry:
*data = 0;
if (ec->common.global_lock) {
@@ -473,64 +424,49 @@ retry:
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
- goto end;
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+ acpi_ec_enter_burst_mode(ec);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (status) {
+ printk("read EC, IB not empty\n");
goto end;
}
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
+ &ec->common.command_addr);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("read EC, IB not empty\n");
+ }
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+ if (status) {
+ printk("read EC, OB not full\n");
goto end;
}
-
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
-
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
-
-end:
+ *data, address));
+
+ end:
acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->burst.pending_gpe)){
- msleep(1);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto retry;
- }
-
return_VALUE(status);
}
-
-static int
-acpi_ec_burst_write (
- union acpi_ec *ec,
- u8 address,
- u8 data)
+static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
{
- int status = 0;
- u32 glk;
- u32 tmp;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_write");
if (!ec)
return_VALUE(-EINVAL);
-retry:
+
if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
@@ -540,69 +476,43 @@ retry:
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
- goto end;
+ acpi_ec_enter_burst_mode(ec);
- status = acpi_ec_read_status(ec);
- if (status != -EINVAL &&
- !(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status)
- goto end;
- acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
- if(tmp != 0x90 ) /* Burst ACK byte*/
- goto end;
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("write EC, IB not empty\n");
}
- /*Now we are in burst mode*/
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if (status){
- goto end;
+ if (status) {
+ printk("write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto end;
+ if (status) {
+ printk("write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, data, &ec->common.data_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- if (status)
- goto end;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
+ data, address));
-end:
acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->burst.pending_gpe)){
- msleep(1);
- }
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- goto retry;
- }
-
return_VALUE(status);
}
/*
* Externally callable EC access functions. For now, assume 1 EC only
*/
-int
-ec_read(u8 addr, u8 *val)
+int ec_read(u8 addr, u8 * val)
{
union acpi_ec *ec;
int err;
@@ -618,14 +528,13 @@ ec_read(u8 addr, u8 *val)
if (!err) {
*val = temp_data;
return 0;
- }
- else
+ } else
return err;
}
+
EXPORT_SYMBOL(ec_read);
-int
-ec_write(u8 addr, u8 val)
+int ec_write(u8 addr, u8 val)
{
union acpi_ec *ec;
int err;
@@ -639,27 +548,22 @@ ec_write(u8 addr, u8 val)
return err;
}
+
EXPORT_SYMBOL(ec_write);
-static int
-acpi_ec_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_query(union acpi_ec *ec, u32 * data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_polling_query(ec, data);
else
return acpi_ec_burst_query(ec, data);
}
-static int
-acpi_ec_polling_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
{
- int result = 0;
- acpi_status status = AE_OK;
- unsigned long flags = 0;
- u32 glk = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
ACPI_FUNCTION_TRACE("acpi_ec_query");
@@ -681,7 +585,8 @@ acpi_ec_polling_query (
*/
spin_lock_irqsave(&ec->polling.lock, flags);
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
+ &ec->common.command_addr);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (result)
goto end;
@@ -690,7 +595,7 @@ acpi_ec_polling_query (
if (!*data)
result = -ENODATA;
-end:
+ end:
spin_unlock_irqrestore(&ec->polling.lock, flags);
if (ec->common.global_lock)
@@ -698,13 +603,10 @@ end:
return_VALUE(result);
}
-static int
-acpi_ec_burst_query (
- union acpi_ec *ec,
- u32 *data)
+static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
{
- int status = 0;
- u32 glk;
+ int status = 0;
+ u32 glk;
ACPI_FUNCTION_TRACE("acpi_ec_query");
@@ -719,70 +621,64 @@ acpi_ec_burst_query (
}
down(&ec->burst.sem);
- if(acpi_ec_enter_burst_mode(ec))
+
+ status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (status) {
+ printk("query EC, IB not empty\n");
goto end;
+ }
/*
* Query the EC to find out which _Qxx method we need to evaluate.
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
+ &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status){
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ if (status) {
+ printk("query EC, OB not full\n");
goto end;
}
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (!*data)
status = -ENODATA;
-end:
- acpi_ec_leave_burst_mode(ec);
+ end:
up(&ec->burst.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->burst.leaving_burst) == 2){
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = -ENODATA;
- }
return_VALUE(status);
}
-
/* --------------------------------------------------------------------------
Event Management
-------------------------------------------------------------------------- */
union acpi_ec_query_data {
- acpi_handle handle;
- u8 data;
+ acpi_handle handle;
+ u8 data;
};
-static void
-acpi_ec_gpe_query (
- void *ec_cxt)
+static void acpi_ec_gpe_query(void *ec_cxt)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
acpi_ec_gpe_polling_query(ec_cxt);
else
acpi_ec_gpe_burst_query(ec_cxt);
}
-static void
-acpi_ec_gpe_polling_query (
- void *ec_cxt)
+static void acpi_ec_gpe_polling_query(void *ec_cxt)
{
- union acpi_ec *ec = (union acpi_ec *) ec_cxt;
- u32 value = 0;
- unsigned long flags = 0;
- static char object_name[5] = {'_','Q','0','0','\0'};
- const char hex[] = {'0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'};
+ union acpi_ec *ec = (union acpi_ec *)ec_cxt;
+ u32 value = 0;
+ unsigned long flags = 0;
+ static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
+ const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
@@ -812,19 +708,18 @@ acpi_ec_gpe_polling_query (
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
-end:
+ end:
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
}
-static void
-acpi_ec_gpe_burst_query (
- void *ec_cxt)
+static void acpi_ec_gpe_burst_query(void *ec_cxt)
{
- union acpi_ec *ec = (union acpi_ec *) ec_cxt;
- u32 value;
- int result = -ENODATA;
- static char object_name[5] = {'_','Q','0','0','\0'};
- const char hex[] = {'0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'};
+ union acpi_ec *ec = (union acpi_ec *)ec_cxt;
+ u32 value;
+ int result = -ENODATA;
+ static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
+ const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
@@ -840,26 +735,22 @@ acpi_ec_gpe_burst_query (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
-end:
+ end:
atomic_dec(&ec->burst.pending_gpe);
return;
}
-static u32
-acpi_ec_gpe_handler (
- void *data)
+static u32 acpi_ec_gpe_handler(void *data)
{
- if (acpi_ec_polling_mode)
+ if (acpi_ec_polling_mode)
return acpi_ec_gpe_polling_handler(data);
else
- return acpi_ec_gpe_burst_handler(data);
+ return acpi_ec_gpe_burst_handler(data);
}
-static u32
-acpi_ec_gpe_polling_handler (
- void *data)
+static u32 acpi_ec_gpe_polling_handler(void *data)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = (union acpi_ec *) data;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = (union acpi_ec *)data;
if (!ec)
return ACPI_INTERRUPT_NOT_HANDLED;
@@ -867,61 +758,49 @@ acpi_ec_gpe_polling_handler (
acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, ec);
+ acpi_ec_gpe_query, ec);
if (status == AE_OK)
return ACPI_INTERRUPT_HANDLED;
else
return ACPI_INTERRUPT_NOT_HANDLED;
}
-static u32
-acpi_ec_gpe_burst_handler (
- void *data)
+static u32 acpi_ec_gpe_burst_handler(void *data)
{
- acpi_status status = AE_OK;
- u32 value;
- union acpi_ec *ec = (union acpi_ec *) data;
+ acpi_status status = AE_OK;
+ u32 value;
+ union acpi_ec *ec = (union acpi_ec *)data;
if (!ec)
return ACPI_INTERRUPT_NOT_HANDLED;
- acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
-
+ acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
value = acpi_ec_read_status(ec);
- if((value & ACPI_EC_FLAG_IBF) &&
- !(value & ACPI_EC_FLAG_BURST) &&
- (atomic_read(&ec->burst.leaving_burst) == 0)) {
- /*
- * the embedded controller disables
- * burst mode for any reason other
- * than the burst disable command
- * to process critical event.
- */
- atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction
- and retry */
+ switch (ec->burst.expect_event) {
+ case ACPI_EC_EVENT_OBF:
+ if (!(value & ACPI_EC_FLAG_OBF))
+ break;
+ case ACPI_EC_EVENT_IBE:
+ if ((value & ACPI_EC_FLAG_IBF))
+ break;
+ ec->burst.expect_event = 0;
wake_up(&ec->burst.wait);
- }else {
- if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF &&
- (value & ACPI_EC_FLAG_OBF)) ||
- (ec->burst.expect_event == ACPI_EC_EVENT_IBE &&
- !(value & ACPI_EC_FLAG_IBF))) {
- ec->burst.expect_event = 0;
- wake_up(&ec->burst.wait);
- return ACPI_INTERRUPT_HANDLED;
- }
+ return ACPI_INTERRUPT_HANDLED;
+ default:
+ break;
}
- if (value & ACPI_EC_FLAG_SCI){
- atomic_add(1, &ec->burst.pending_gpe) ;
+ if (value & ACPI_EC_FLAG_SCI) {
+ atomic_add(1, &ec->burst.pending_gpe);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, ec);
+ acpi_ec_gpe_query, ec);
return status == AE_OK ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
- }
+ ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ }
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
return status == AE_OK ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
/* --------------------------------------------------------------------------
@@ -929,37 +808,31 @@ acpi_ec_gpe_burst_handler (
-------------------------------------------------------------------------- */
static acpi_status
-acpi_ec_space_setup (
- acpi_handle region_handle,
- u32 function,
- void *handler_context,
- void **return_context)
+acpi_ec_space_setup(acpi_handle region_handle,
+ u32 function, void *handler_context, void **return_context)
{
/*
* The EC object is in the handler context and is needed
* when calling the acpi_ec_space_handler.
*/
- *return_context = (function != ACPI_REGION_DEACTIVATE) ?
- handler_context : NULL;
+ *return_context = (function != ACPI_REGION_DEACTIVATE) ?
+ handler_context : NULL;
return AE_OK;
}
-
static acpi_status
-acpi_ec_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ec_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- int result = 0;
- union acpi_ec *ec = NULL;
- u64 temp = *value;
- acpi_integer f_v = 0;
- int i = 0;
+ int result = 0;
+ union acpi_ec *ec = NULL;
+ u64 temp = *value;
+ acpi_integer f_v = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_ec_space_handler");
@@ -967,17 +840,18 @@ acpi_ec_space_handler (
return_VALUE(AE_BAD_PARAMETER);
if (bit_width != 8 && acpi_strict) {
- printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n");
+ printk(KERN_WARNING PREFIX
+ "acpi_ec_space_handler: bit_width should be 8\n");
return_VALUE(AE_BAD_PARAMETER);
}
- ec = (union acpi_ec *) handler_context;
+ ec = (union acpi_ec *)handler_context;
-next_byte:
+ next_byte:
switch (function) {
case ACPI_READ:
temp = 0;
- result = acpi_ec_read(ec, (u8) address, (u32 *)&temp);
+ result = acpi_ec_read(ec, (u8) address, (u32 *) & temp);
break;
case ACPI_WRITE:
result = acpi_ec_write(ec, (u8) address, (u8) temp);
@@ -1004,8 +878,7 @@ next_byte:
*value = f_v;
}
-
-out:
+ out:
switch (result) {
case -EINVAL:
return_VALUE(AE_BAD_PARAMETER);
@@ -1021,18 +894,15 @@ out:
}
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_ec_dir;
-
+static struct proc_dir_entry *acpi_ec_dir;
-static int
-acpi_ec_read_info (struct seq_file *seq, void *offset)
+static int acpi_ec_read_info(struct seq_file *seq, void *offset)
{
- union acpi_ec *ec = (union acpi_ec *) seq->private;
+ union acpi_ec *ec = (union acpi_ec *)seq->private;
ACPI_FUNCTION_TRACE("acpi_ec_read_info");
@@ -1040,14 +910,15 @@ acpi_ec_read_info (struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "gpe bit: 0x%02x\n",
- (u32) ec->common.gpe_bit);
+ (u32) ec->common.gpe_bit);
seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
- (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address);
+ (u32) ec->common.status_addr.address,
+ (u32) ec->common.data_addr.address);
seq_printf(seq, "use global lock: %s\n",
- ec->common.global_lock?"yes":"no");
+ ec->common.global_lock ? "yes" : "no");
acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
-end:
+ end:
return_VALUE(0);
}
@@ -1057,34 +928,32 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_ec_info_ops = {
- .open = acpi_ec_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_ec_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_ec_add_fs (
- struct acpi_device *device)
+static int acpi_ec_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_ec_dir);
+ acpi_ec_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
- acpi_device_dir(device));
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Unable to create '%s' fs entry\n",
- ACPI_EC_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_EC_FILE_INFO));
else {
entry->proc_fops = &acpi_ec_info_ops;
entry->data = acpi_driver_data(device);
@@ -1094,10 +963,7 @@ acpi_ec_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_ec_remove_fs (
- struct acpi_device *device)
+static int acpi_ec_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
@@ -1110,20 +976,16 @@ acpi_ec_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-
-static int
-acpi_ec_polling_add (
- struct acpi_device *device)
+static int acpi_ec_polling_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
- unsigned long uid;
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
+ unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1143,26 +1005,31 @@ acpi_ec_polling_add (
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
+ &ec->common.global_lock);
/* If our UID matches the UID for the ECDT-enumerated EC,
- we now have the *real* EC info, so kill the makeshift one.*/
+ we now have the *real* EC info, so kill the makeshift one. */
acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
if (ec_ecdt && ec_ecdt->common.uid == uid) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
-
- acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
+
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+ &acpi_ec_gpe_handler);
kfree(ec_ecdt);
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
+ &ec->common.gpe_bit);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error obtaining GPE bit assignment\n"));
+ "Error obtaining GPE bit assignment\n"));
result = -ENODEV;
goto end;
}
@@ -1172,26 +1039,24 @@ acpi_ec_polling_add (
goto end;
printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
- acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->common.gpe_bit);
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->common.gpe_bit);
if (!first_ec)
first_ec = device;
-end:
+ end:
if (result)
kfree(ec);
return_VALUE(result);
}
-static int
-acpi_ec_burst_add (
- struct acpi_device *device)
+static int acpi_ec_burst_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
- unsigned long uid;
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
+ unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1205,35 +1070,40 @@ acpi_ec_burst_add (
ec->common.handle = device->handle;
ec->common.uid = -1;
- atomic_set(&ec->burst.pending_gpe, 0);
- atomic_set(&ec->burst.leaving_burst , 1);
- init_MUTEX(&ec->burst.sem);
- init_waitqueue_head(&ec->burst.wait);
+ atomic_set(&ec->burst.pending_gpe, 0);
+ atomic_set(&ec->burst.leaving_burst, 1);
+ init_MUTEX(&ec->burst.sem);
+ init_waitqueue_head(&ec->burst.wait);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
+ &ec->common.global_lock);
/* If our UID matches the UID for the ECDT-enumerated EC,
- we now have the *real* EC info, so kill the makeshift one.*/
+ we now have the *real* EC info, so kill the makeshift one. */
acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
if (ec_ecdt && ec_ecdt->common.uid == uid) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
- acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
+ &acpi_ec_gpe_handler);
kfree(ec_ecdt);
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
+ &ec->common.gpe_bit);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error obtaining GPE bit assignment\n"));
+ "Error obtaining GPE bit assignment\n"));
result = -ENODEV;
goto end;
}
@@ -1242,27 +1112,24 @@ acpi_ec_burst_add (
if (result)
goto end;
+ printk("burst-mode-ec-10-Aug\n");
printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
- acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->common.gpe_bit);
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->common.gpe_bit);
if (!first_ec)
first_ec = device;
-end:
+ end:
if (result)
kfree(ec);
return_VALUE(result);
}
-
-static int
-acpi_ec_remove (
- struct acpi_device *device,
- int type)
+static int acpi_ec_remove(struct acpi_device *device, int type)
{
- union acpi_ec *ec = NULL;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_remove");
@@ -1278,13 +1145,10 @@ acpi_ec_remove (
return_VALUE(0);
}
-
static acpi_status
-acpi_ec_io_ports (
- struct acpi_resource *resource,
- void *context)
+acpi_ec_io_ports(struct acpi_resource *resource, void *context)
{
- union acpi_ec *ec = (union acpi_ec *) context;
+ union acpi_ec *ec = (union acpi_ec *)context;
struct acpi_generic_address *addr;
if (resource->id != ACPI_RSTYPE_IO) {
@@ -1312,13 +1176,10 @@ acpi_ec_io_ports (
return AE_OK;
}
-
-static int
-acpi_ec_start (
- struct acpi_device *device)
+static int acpi_ec_start(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_start");
@@ -1334,49 +1195,50 @@ acpi_ec_start (
* Get I/O port addresses. Convert to GAS format.
*/
status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec);
- if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses"));
+ acpi_ec_io_ports, ec);
+ if (ACPI_FAILURE(status)
+ || ec->common.command_addr.register_bit_width == 0) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error getting I/O port addresses"));
return_VALUE(-ENODEV);
}
ec->common.status_addr = ec->common.command_addr;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
- (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address,
- (u32) ec->common.data_addr.address));
-
+ (u32) ec->common.gpe_bit,
+ (u32) ec->common.command_addr.address,
+ (u32) ec->common.data_addr.address));
/*
* Install GPE handler
*/
status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
- ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
return_VALUE(-ENODEV);
}
- acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = acpi_install_address_space_handler (ec->common.handle,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
- &acpi_ec_space_setup, ec);
+ status = acpi_install_address_space_handler(ec->common.handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ &acpi_ec_space_setup, ec);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+ &acpi_ec_gpe_handler);
return_VALUE(-ENODEV);
}
return_VALUE(AE_OK);
}
-
-static int
-acpi_ec_stop (
- struct acpi_device *device,
- int type)
+static int acpi_ec_stop(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- union acpi_ec *ec = NULL;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_stop");
@@ -1386,11 +1248,14 @@ acpi_ec_stop (
ec = acpi_driver_data(device);
status = acpi_remove_address_space_handler(ec->common.handle,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
+ status =
+ acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
+ &acpi_ec_gpe_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -1398,32 +1263,26 @@ acpi_ec_stop (
}
static acpi_status __init
-acpi_fake_ecdt_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
if (acpi_ec_polling_mode)
return acpi_fake_ecdt_polling_callback(handle,
- Level, context, retval);
+ Level, context, retval);
else
return acpi_fake_ecdt_burst_callback(handle,
- Level, context, retval);
+ Level, context, retval);
}
static acpi_status __init
-acpi_fake_ecdt_polling_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_polling_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
- acpi_status status;
+ acpi_status status;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec_ecdt);
+ acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
@@ -1431,33 +1290,33 @@ acpi_fake_ecdt_polling_callback (
ec_ecdt->common.uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(handle, "_GPE", NULL,
+ &ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
spin_lock_init(&ec_ecdt->polling.lock);
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
- printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
- (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
- (u32) ec_ecdt->common.data_addr.address);
+ printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+ (u32) ec_ecdt->common.gpe_bit,
+ (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
return AE_CTRL_TERMINATE;
}
static acpi_status __init
-acpi_fake_ecdt_burst_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval)
+acpi_fake_ecdt_burst_callback(acpi_handle handle,
+ u32 Level, void *context, void **retval)
{
- acpi_status status;
+ acpi_status status;
init_MUTEX(&ec_ecdt->burst.sem);
init_waitqueue_head(&ec_ecdt->burst.wait);
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
- acpi_ec_io_ports, ec_ecdt);
+ acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
@@ -1465,15 +1324,18 @@ acpi_fake_ecdt_burst_callback (
ec_ecdt->common.uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+ status =
+ acpi_evaluate_integer(handle, "_GPE", NULL,
+ &ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
- printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
- (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
- (u32) ec_ecdt->common.data_addr.address);
+ printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+ (u32) ec_ecdt->common.gpe_bit,
+ (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
return AE_CTRL_TERMINATE;
}
@@ -1488,11 +1350,10 @@ acpi_fake_ecdt_burst_callback (
* op region (since _REG isn't invoked yet). The assumption is true for
* all systems found.
*/
-static int __init
-acpi_ec_fake_ecdt(void)
+static int __init acpi_ec_fake_ecdt(void)
{
- acpi_status status;
- int ret = 0;
+ acpi_status status;
+ int ret = 0;
printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
@@ -1503,10 +1364,8 @@ acpi_ec_fake_ecdt(void)
}
memset(ec_ecdt, 0, sizeof(union acpi_ec));
- status = acpi_get_devices (ACPI_EC_HID,
- acpi_fake_ecdt_callback,
- NULL,
- NULL);
+ status = acpi_get_devices(ACPI_EC_HID,
+ acpi_fake_ecdt_callback, NULL, NULL);
if (ACPI_FAILURE(status)) {
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1514,13 +1373,12 @@ acpi_ec_fake_ecdt(void)
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Can't make an fake ECDT\n");
return ret;
}
-static int __init
-acpi_ec_get_real_ecdt(void)
+static int __init acpi_ec_get_real_ecdt(void)
{
if (acpi_ec_polling_mode)
return acpi_ec_polling_get_real_ecdt();
@@ -1528,14 +1386,14 @@ acpi_ec_get_real_ecdt(void)
return acpi_ec_burst_get_real_ecdt();
}
-static int __init
-acpi_ec_polling_get_real_ecdt(void)
+static int __init acpi_ec_polling_get_real_ecdt(void)
{
- acpi_status status;
- struct acpi_table_ecdt *ecdt_ptr;
+ acpi_status status;
+ struct acpi_table_ecdt *ecdt_ptr;
- status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
- (struct acpi_table_header **) &ecdt_ptr);
+ status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **)
+ &ecdt_ptr);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -1558,13 +1416,14 @@ acpi_ec_polling_get_real_ecdt(void)
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+ status =
+ acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
if (ACPI_FAILURE(status)) {
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1572,15 +1431,14 @@ error:
return -ENODEV;
}
-
-static int __init
-acpi_ec_burst_get_real_ecdt(void)
+static int __init acpi_ec_burst_get_real_ecdt(void)
{
- acpi_status status;
- struct acpi_table_ecdt *ecdt_ptr;
+ acpi_status status;
+ struct acpi_table_ecdt *ecdt_ptr;
status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
- (struct acpi_table_header **) &ecdt_ptr);
+ (struct acpi_table_header **)
+ &ecdt_ptr);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -1594,8 +1452,8 @@ acpi_ec_burst_get_real_ecdt(void)
return -ENOMEM;
memset(ec_ecdt, 0, sizeof(union acpi_ec));
- init_MUTEX(&ec_ecdt->burst.sem);
- init_waitqueue_head(&ec_ecdt->burst.wait);
+ init_MUTEX(&ec_ecdt->burst.sem);
+ init_waitqueue_head(&ec_ecdt->burst.wait);
ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
@@ -1604,13 +1462,14 @@ acpi_ec_burst_get_real_ecdt(void)
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+ status =
+ acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
if (ACPI_FAILURE(status)) {
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1619,11 +1478,10 @@ error:
}
static int __initdata acpi_fake_ecdt_enabled;
-int __init
-acpi_ec_ecdt_probe (void)
+int __init acpi_ec_ecdt_probe(void)
{
- acpi_status status;
- int ret;
+ acpi_status status;
+ int ret;
ret = acpi_ec_get_real_ecdt();
/* Try to make a fake ECDT */
@@ -1638,26 +1496,28 @@ acpi_ec_ecdt_probe (void)
* Install GPE handler
*/
status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
- ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
- ec_ecdt);
+ ACPI_GPE_EDGE_TRIGGERED,
+ &acpi_ec_gpe_handler, ec_ecdt);
if (ACPI_FAILURE(status)) {
goto error;
}
- acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
-
- status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
- &acpi_ec_space_setup, ec_ecdt);
+ acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
+
+ status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler,
+ &acpi_ec_space_setup,
+ ec_ecdt);
if (ACPI_FAILURE(status)) {
acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
- &acpi_ec_gpe_handler);
+ &acpi_ec_gpe_handler);
goto error;
}
return 0;
-error:
+ error:
printk(KERN_ERR PREFIX "Could not use ECDT\n");
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -1665,10 +1525,9 @@ error:
return -ENODEV;
}
-
-static int __init acpi_ec_init (void)
+static int __init acpi_ec_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_init");
@@ -1693,8 +1552,7 @@ subsys_initcall(acpi_ec_init);
/* EC driver currently not unloadable */
#if 0
-static void __exit
-acpi_ec_exit (void)
+static void __exit acpi_ec_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_ec_exit");
@@ -1704,7 +1562,7 @@ acpi_ec_exit (void)
return_VOID;
}
-#endif /* 0 */
+#endif /* 0 */
static int __init acpi_fake_ecdt_setup(char *str)
{
@@ -1727,8 +1585,8 @@ static int __init acpi_ec_set_polling_mode(char *str)
acpi_ec_polling_mode = EC_POLLING;
acpi_ec_driver.ops.add = acpi_ec_polling_add;
}
- printk(KERN_INFO PREFIX "EC %s mode.\n",
- burst ? "burst": "polling");
+ printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling");
return 0;
}
+
__setup("ec_burst=", acpi_ec_set_polling_mode);
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 43c49f66a328..2dbb1b0f11d5 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -13,45 +13,40 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("event")
+ACPI_MODULE_NAME("event")
/* Global vars for handling event proc entry */
static DEFINE_SPINLOCK(acpi_system_event_lock);
-int event_is_open = 0;
-extern struct list_head acpi_bus_event_list;
-extern wait_queue_head_t acpi_bus_event_queue;
+int event_is_open = 0;
+extern struct list_head acpi_bus_event_list;
+extern wait_queue_head_t acpi_bus_event_queue;
-static int
-acpi_system_open_event(struct inode *inode, struct file *file)
+static int acpi_system_open_event(struct inode *inode, struct file *file)
{
- spin_lock_irq (&acpi_system_event_lock);
+ spin_lock_irq(&acpi_system_event_lock);
- if(event_is_open)
+ if (event_is_open)
goto out_busy;
event_is_open = 1;
- spin_unlock_irq (&acpi_system_event_lock);
+ spin_unlock_irq(&acpi_system_event_lock);
return 0;
-out_busy:
- spin_unlock_irq (&acpi_system_event_lock);
+ out_busy:
+ spin_unlock_irq(&acpi_system_event_lock);
return -EBUSY;
}
static ssize_t
-acpi_system_read_event (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
+ loff_t * ppos)
{
- int result = 0;
- struct acpi_bus_event event;
- static char str[ACPI_MAX_STRING];
- static int chars_remaining = 0;
- static char *ptr;
-
+ int result = 0;
+ struct acpi_bus_event event;
+ static char str[ACPI_MAX_STRING];
+ static int chars_remaining = 0;
+ static char *ptr;
ACPI_FUNCTION_TRACE("acpi_system_read_event");
@@ -63,14 +58,15 @@ acpi_system_read_event (
return_VALUE(-EAGAIN);
result = acpi_bus_receive_event(&event);
- if (result) {
- return_VALUE(-EIO);
- }
-
- chars_remaining = sprintf(str, "%s %s %08x %08x\n",
- event.device_class?event.device_class:"<unknown>",
- event.bus_id?event.bus_id:"<unknown>",
- event.type, event.data);
+ if (result)
+ return_VALUE(result);
+
+ chars_remaining = sprintf(str, "%s %s %08x %08x\n",
+ event.device_class ? event.
+ device_class : "<unknown>",
+ event.bus_id ? event.
+ bus_id : "<unknown>", event.type,
+ event.data);
ptr = str;
}
@@ -88,19 +84,15 @@ acpi_system_read_event (
return_VALUE(count);
}
-static int
-acpi_system_close_event(struct inode *inode, struct file *file)
+static int acpi_system_close_event(struct inode *inode, struct file *file)
{
- spin_lock_irq (&acpi_system_event_lock);
+ spin_lock_irq(&acpi_system_event_lock);
event_is_open = 0;
- spin_unlock_irq (&acpi_system_event_lock);
+ spin_unlock_irq(&acpi_system_event_lock);
return 0;
}
-static unsigned int
-acpi_system_poll_event(
- struct file *file,
- poll_table *wait)
+static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
{
poll_wait(file, &acpi_bus_event_queue, wait);
if (!list_empty(&acpi_bus_event_list))
@@ -109,15 +101,15 @@ acpi_system_poll_event(
}
static struct file_operations acpi_system_event_ops = {
- .open = acpi_system_open_event,
- .read = acpi_system_read_event,
- .release = acpi_system_close_event,
- .poll = acpi_system_poll_event,
+ .open = acpi_system_open_event,
+ .read = acpi_system_read_event,
+ .release = acpi_system_close_event,
+ .poll = acpi_system_poll_event,
};
static int __init acpi_event_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
ACPI_FUNCTION_TRACE("acpi_event_init");
@@ -130,8 +122,9 @@ static int __init acpi_event_init(void)
if (entry)
entry->proc_fops = &acpi_system_event_ops;
else {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n","event" ));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n",
+ "event"));
error = -EFAULT;
}
return_VALUE(error);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index dd3a72a869f4..842d1e3fb37b 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -45,18 +45,12 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evevent")
+ACPI_MODULE_NAME("evevent")
/* Local prototypes */
+static acpi_status acpi_ev_fixed_event_initialize(void);
-static acpi_status
-acpi_ev_fixed_event_initialize (
- void);
-
-static u32
-acpi_ev_fixed_event_dispatch (
- u32 event);
-
+static u32 acpi_ev_fixed_event_dispatch(u32 event);
/*******************************************************************************
*
@@ -70,21 +64,17 @@ acpi_ev_fixed_event_dispatch (
*
******************************************************************************/
-acpi_status
-acpi_ev_initialize_events (
- void)
+acpi_status acpi_ev_initialize_events(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_initialize_events");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_initialize_events");
/* Make sure we have ACPI tables */
if (!acpi_gbl_DSDT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No ACPI tables present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
@@ -92,26 +82,22 @@ acpi_ev_initialize_events (
* enabling SCIs to prevent interrupts from occurring before the handlers are
* installed.
*/
- status = acpi_ev_fixed_event_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize fixed events, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_fixed_event_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize fixed events, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- status = acpi_ev_gpe_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize general purpose events, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_gpe_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize general purpose events, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_xrupt_handlers
@@ -124,41 +110,32 @@ acpi_ev_initialize_events (
*
******************************************************************************/
-acpi_status
-acpi_ev_install_xrupt_handlers (
- void)
+acpi_status acpi_ev_install_xrupt_handlers(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers");
/* Install the SCI handler */
- status = acpi_ev_install_sci_handler ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to install System Control Interrupt Handler, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_sci_handler();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* Install the handler for the Global Lock */
- status = acpi_ev_init_global_lock_handler ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Unable to initialize Global Lock handler, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ev_init_global_lock_handler();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Unable to initialize Global Lock handler, %s\n", acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
acpi_gbl_events_initialized = TRUE;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_initialize
@@ -171,13 +148,10 @@ acpi_ev_install_xrupt_handlers (
*
******************************************************************************/
-static acpi_status
-acpi_ev_fixed_event_initialize (
- void)
+static acpi_status acpi_ev_fixed_event_initialize(void)
{
- acpi_native_uint i;
- acpi_status status;
-
+ acpi_native_uint i;
+ acpi_status status;
/*
* Initialize the structure that keeps track of fixed event handlers
@@ -190,10 +164,11 @@ acpi_ev_fixed_event_initialize (
/* Enable the fixed event */
if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
- status = acpi_set_register (
- acpi_gbl_fixed_event_info[i].enable_register_id,
- 0, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[i].
+ enable_register_id, 0,
+ ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -202,7 +177,6 @@ acpi_ev_fixed_event_initialize (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_detect
@@ -215,31 +189,27 @@ acpi_ev_fixed_event_initialize (
*
******************************************************************************/
-u32
-acpi_ev_fixed_event_detect (
- void)
+u32 acpi_ev_fixed_event_detect(void)
{
- u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
- u32 fixed_status;
- u32 fixed_enable;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_NAME ("ev_fixed_event_detect");
+ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+ u32 fixed_status;
+ u32 fixed_enable;
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ev_fixed_event_detect");
/*
* Read the fixed feature status and enable registers, as all the cases
* depend on their values. Ignore errors here.
*/
- (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
- &fixed_status);
- (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE,
- &fixed_enable);
+ (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS, &fixed_status);
+ (void)acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
- ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
- "Fixed Event Block: Enable %08X Status %08X\n",
- fixed_enable, fixed_status));
+ ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+ "Fixed Event Block: Enable %08X Status %08X\n",
+ fixed_enable, fixed_status));
/*
* Check for all possible Fixed Events and dispatch those that are active
@@ -247,18 +217,19 @@ acpi_ev_fixed_event_detect (
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
/* Both the status and enable bits must be on for this event */
- if ((fixed_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
- (fixed_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
+ if ((fixed_status & acpi_gbl_fixed_event_info[i].
+ status_bit_mask)
+ && (fixed_enable & acpi_gbl_fixed_event_info[i].
+ enable_bit_mask)) {
/* Found an active (signalled) event */
- int_status |= acpi_ev_fixed_event_dispatch ((u32) i);
+ int_status |= acpi_ev_fixed_event_dispatch((u32) i);
}
}
return (int_status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_fixed_event_dispatch
@@ -272,39 +243,32 @@ acpi_ev_fixed_event_detect (
*
******************************************************************************/
-static u32
-acpi_ev_fixed_event_dispatch (
- u32 event)
+static u32 acpi_ev_fixed_event_dispatch(u32 event)
{
-
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/* Clear the status bit */
- (void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)acpi_set_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, 1, ACPI_MTX_DO_NOT_LOCK);
/*
* Make sure we've got a handler. If not, report an error.
* The event is disabled to prevent further interrupts.
*/
if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
- (void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 0, ACPI_MTX_DO_NOT_LOCK);
+ (void)acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 0,
+ ACPI_MTX_DO_NOT_LOCK);
- ACPI_REPORT_ERROR (
- ("No installed handler for fixed event [%08X]\n",
- event));
+ ACPI_REPORT_ERROR(("No installed handler for fixed event [%08X]\n", event));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
/* Invoke the Fixed Event handler */
- return ((acpi_gbl_fixed_event_handlers[event].handler)(
- acpi_gbl_fixed_event_handlers[event].context));
+ return ((acpi_gbl_fixed_event_handlers[event].
+ handler) (acpi_gbl_fixed_event_handlers[event].context));
}
-
-
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 081120b109ba..b2f232df13d8 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -46,14 +46,10 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evgpe")
+ACPI_MODULE_NAME("evgpe")
/* Local prototypes */
-
-static void ACPI_SYSTEM_XFACE
-acpi_ev_asynch_execute_gpe_method (
- void *context);
-
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
/*******************************************************************************
*
@@ -69,15 +65,11 @@ acpi_ev_asynch_execute_gpe_method (
******************************************************************************/
acpi_status
-acpi_ev_set_gpe_type (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type)
+acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_set_gpe_type");
/* Validate type and update register enable masks */
@@ -88,21 +80,20 @@ acpi_ev_set_gpe_type (
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Disable the GPE if currently enabled */
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
/* Type was validated above */
- gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
- gpe_event_info->flags |= type; /* Insert type */
- return_ACPI_STATUS (status);
+ gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
+ gpe_event_info->flags |= type; /* Insert type */
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_update_gpe_enable_masks
@@ -118,57 +109,55 @@ acpi_ev_set_gpe_type (
******************************************************************************/
acpi_status
-acpi_ev_update_gpe_enable_masks (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 type)
+acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
+ u8 type)
{
- struct acpi_gpe_register_info *gpe_register_info;
- u8 register_bit;
-
-
- ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
+ struct acpi_gpe_register_info *gpe_register_info;
+ u8 register_bit;
+ ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks");
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
register_bit = gpe_event_info->register_bit;
/* 1) Disable case. Simply clear all enable bits */
if (type == ACPI_GPE_DISABLE) {
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
- return_ACPI_STATUS (AE_OK);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+ register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
+ return_ACPI_STATUS(AE_OK);
}
/* 2) Enable case. Set/Clear the appropriate enable bits */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
break;
case ACPI_GPE_TYPE_RUNTIME:
- ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+ register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit);
- ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_enable_gpe
@@ -184,21 +173,19 @@ acpi_ev_update_gpe_enable_masks (
******************************************************************************/
acpi_status
-acpi_ev_enable_gpe (
- struct acpi_gpe_event_info *gpe_event_info,
- u8 write_to_hardware)
+acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
+ u8 write_to_hardware)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_enable_gpe");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_enable_gpe");
/* Make sure HW enable masks are updated */
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Mark wake-enabled or HW enable, or both */
@@ -206,41 +193,40 @@ acpi_ev_enable_gpe (
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
/*lint -fallthrough */
case ACPI_GPE_TYPE_RUNTIME:
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
if (write_to_hardware) {
/* Clear the GPE (of stale events), then enable it */
- status = acpi_hw_clear_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Enable the requested runtime GPE */
- status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+ status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
}
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_disable_gpe
@@ -253,36 +239,33 @@ acpi_ev_enable_gpe (
*
******************************************************************************/
-acpi_status
-acpi_ev_disable_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_disable_gpe");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_disable_gpe");
if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Make sure HW enable masks are updated */
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Mark wake-disabled or HW disable, or both */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
break;
case ACPI_GPE_TYPE_WAKE_RUN:
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
/*lint -fallthrough */
@@ -290,18 +273,17 @@ acpi_ev_disable_gpe (
/* Disable the requested runtime GPE */
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
- status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+ status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_event_info
@@ -319,18 +301,14 @@ acpi_ev_disable_gpe (
*
******************************************************************************/
-struct acpi_gpe_event_info *
-acpi_ev_get_gpe_event_info (
- acpi_handle gpe_device,
- u32 gpe_number)
+struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
+ u32 gpe_number)
{
- union acpi_operand_object *obj_desc;
- struct acpi_gpe_block_info *gpe_block;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_operand_object *obj_desc;
+ struct acpi_gpe_block_info *gpe_block;
+ acpi_native_uint i;
+ ACPI_FUNCTION_ENTRY();
/* A NULL gpe_block means use the FADT-defined GPE block(s) */
@@ -340,11 +318,14 @@ acpi_ev_get_gpe_event_info (
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
gpe_block = acpi_gbl_gpe_fadt_blocks[i];
if (gpe_block) {
- if ((gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number +
- (gpe_block->register_count * 8))) {
- return (&gpe_block->event_info[gpe_number -
- gpe_block->block_base_number]);
+ if ((gpe_number >= gpe_block->block_base_number)
+ && (gpe_number <
+ gpe_block->block_base_number +
+ (gpe_block->register_count * 8))) {
+ return (&gpe_block->
+ event_info[gpe_number -
+ gpe_block->
+ block_base_number]);
}
}
}
@@ -356,23 +337,25 @@ acpi_ev_get_gpe_event_info (
/* A Non-NULL gpe_device means this is a GPE Block Device */
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
- if (!obj_desc ||
- !obj_desc->device.gpe_block) {
+ obj_desc =
+ acpi_ns_get_attached_object((struct acpi_namespace_node *)
+ gpe_device);
+ if (!obj_desc || !obj_desc->device.gpe_block) {
return (NULL);
}
gpe_block = obj_desc->device.gpe_block;
if ((gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
- return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
+ (gpe_number <
+ gpe_block->block_base_number + (gpe_block->register_count * 8))) {
+ return (&gpe_block->
+ event_info[gpe_number - gpe_block->block_base_number]);
}
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_detect
@@ -387,22 +370,20 @@ acpi_ev_get_gpe_event_info (
*
******************************************************************************/
-u32
-acpi_ev_gpe_detect (
- struct acpi_gpe_xrupt_info *gpe_xrupt_list)
+u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
{
- u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
- u8 enabled_status_byte;
- struct acpi_gpe_register_info *gpe_register_info;
- u32 status_reg;
- u32 enable_reg;
- acpi_status status;
- struct acpi_gpe_block_info *gpe_block;
- acpi_native_uint i;
- acpi_native_uint j;
-
-
- ACPI_FUNCTION_NAME ("ev_gpe_detect");
+ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+ u8 enabled_status_byte;
+ struct acpi_gpe_register_info *gpe_register_info;
+ u32 status_reg;
+ u32 enable_reg;
+ u32 flags;
+ acpi_status status;
+ struct acpi_gpe_block_info *gpe_block;
+ acpi_native_uint i;
+ acpi_native_uint j;
+
+ ACPI_FUNCTION_NAME("ev_gpe_detect");
/* Check for the case where there are no GPEs */
@@ -412,7 +393,7 @@ acpi_ev_gpe_detect (
/* Examine all GPE blocks attached to this interrupt level */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) {
/*
@@ -427,23 +408,30 @@ acpi_ev_gpe_detect (
/* Read the Status Register */
- status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
- &gpe_register_info->status_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
+ &status_reg,
+ &gpe_register_info->
+ status_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Read the Enable Register */
- status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
- &gpe_register_info->enable_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
+ &enable_reg,
+ &gpe_register_info->
+ enable_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
- "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
- gpe_register_info->base_gpe_number, status_reg, enable_reg));
+ ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+ "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
+ gpe_register_info->base_gpe_number,
+ status_reg, enable_reg));
/* Check if there is anything active at all in this register */
@@ -459,14 +447,21 @@ acpi_ev_gpe_detect (
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
/* Examine one GPE bit */
- if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) {
+ if (enabled_status_byte &
+ acpi_gbl_decode_to8bit[j]) {
/*
* Found an active GPE. Dispatch the event to a handler
* or method.
*/
- int_status |= acpi_ev_gpe_dispatch (
- &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
- (u32) j + gpe_register_info->base_gpe_number);
+ int_status |=
+ acpi_ev_gpe_dispatch(&gpe_block->
+ event_info[(i *
+ ACPI_GPE_REGISTER_WIDTH)
+ +
+ j],
+ (u32) j +
+ gpe_register_info->
+ base_gpe_number);
}
}
}
@@ -474,13 +469,12 @@ acpi_ev_gpe_detect (
gpe_block = gpe_block->next;
}
-unlock_and_exit:
+ unlock_and_exit:
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return (int_status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_asynch_execute_gpe_method
@@ -497,45 +491,41 @@ unlock_and_exit:
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_asynch_execute_gpe_method (
- void *context)
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
{
- struct acpi_gpe_event_info *gpe_event_info = (void *) context;
- u32 gpe_number = 0;
- acpi_status status;
- struct acpi_gpe_event_info local_gpe_event_info;
- struct acpi_parameter_info info;
-
+ struct acpi_gpe_event_info *gpe_event_info = (void *)context;
+ u32 gpe_number = 0;
+ acpi_status status;
+ struct acpi_gpe_event_info local_gpe_event_info;
+ struct acpi_parameter_info info;
- ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
+ ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method");
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Must revalidate the gpe_number/gpe_block */
- if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (!acpi_ev_valid_gpe_event(gpe_event_info)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_VOID;
}
/* Set the GPE flags for return to enabled state */
- (void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
+ (void)acpi_ev_enable_gpe(gpe_event_info, FALSE);
/*
* Take a snapshot of the GPE info for this level - we copy the
* info to prevent a race condition with remove_handler/remove_block.
*/
- ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info,
- sizeof (struct acpi_gpe_event_info));
+ ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
+ sizeof(struct acpi_gpe_event_info));
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
@@ -544,44 +534,40 @@ acpi_ev_asynch_execute_gpe_method (
* time to avoid race with ev_gpe_install_handler
*/
if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_METHOD) {
+ ACPI_GPE_DISPATCH_METHOD) {
/*
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
* control method that corresponds to this GPE
*/
info.node = local_gpe_event_info.dispatch.method_node;
- info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
+ info.parameters =
+ ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info);
info.parameter_type = ACPI_PARAM_GPE;
- status = acpi_ns_evaluate_by_handle (&info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "%s while evaluating method [%4.4s] for GPE[%2X]\n",
- acpi_format_exception (status),
- acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
- gpe_number));
+ status = acpi_ns_evaluate_by_handle(&info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number));
}
}
if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_LEVEL_TRIGGERED) {
+ ACPI_GPE_LEVEL_TRIGGERED) {
/*
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
- status = acpi_hw_clear_gpe (&local_gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_clear_gpe(&local_gpe_event_info);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Enable this GPE */
- (void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
+ (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_dispatch
@@ -599,38 +585,31 @@ acpi_ev_asynch_execute_gpe_method (
******************************************************************************/
u32
-acpi_ev_gpe_dispatch (
- struct acpi_gpe_event_info *gpe_event_info,
- u32 gpe_number)
+acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_gpe_dispatch");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_gpe_dispatch");
/*
* If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_EDGE_TRIGGERED) {
- status = acpi_hw_clear_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_GPE_EDGE_TRIGGERED) {
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
}
/* Save current system state */
if (acpi_gbl_system_awake_and_running) {
- ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
- }
- else {
- ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+ ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+ } else {
+ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
}
/*
@@ -647,19 +626,19 @@ acpi_ev_gpe_dispatch (
* Invoke the installed handler (at interrupt level)
* Ignore return status for now. TBD: leave GPE disabled on error?
*/
- (void) gpe_event_info->dispatch.handler->address (
- gpe_event_info->dispatch.handler->context);
+ (void)gpe_event_info->dispatch.handler->address(gpe_event_info->
+ dispatch.
+ handler->
+ context);
/* It is now safe to clear level-triggered events. */
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_LEVEL_TRIGGERED) {
- status = acpi_hw_clear_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ ACPI_GPE_LEVEL_TRIGGERED) {
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
}
break;
@@ -670,24 +649,21 @@ acpi_ev_gpe_dispatch (
* Disable GPE, so it doesn't keep firing before the method has a
* chance to run.
*/
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
/*
* Execute the method associated with the GPE
* NOTE: Level-triggered GPEs are cleared after the method completes.
*/
- status = acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
- acpi_ev_asynch_execute_gpe_method, gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n",
- acpi_format_exception (status), gpe_number));
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+ acpi_ev_asynch_execute_gpe_method,
+ gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number));
}
break;
@@ -695,28 +671,23 @@ acpi_ev_gpe_dispatch (
/* No handler or method to run! */
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n",
- gpe_number));
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number));
/*
* Disable the GPE. The GPE will remain disabled until the ACPI
* Core Subsystem is restarted, or a handler is installed.
*/
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
- acpi_format_exception (status), gpe_number));
- return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number));
+ return_VALUE(ACPI_INTERRUPT_NOT_HANDLED);
}
break;
}
- return_VALUE (ACPI_INTERRUPT_HANDLED);
+ return_VALUE(ACPI_INTERRUPT_HANDLED);
}
-
#ifdef ACPI_GPE_NOTIFY_CHECK
/*******************************************************************************
* TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
@@ -735,35 +706,29 @@ acpi_ev_gpe_dispatch (
******************************************************************************/
acpi_status
-acpi_ev_check_for_wake_only_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
- acpi_status status;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe");
- ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
-
-
- if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
- ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
+ if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
+ ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) { /* System state at GPE time */
/* This must be a wake-only GPE, disable it */
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
/* Set GPE to wake-only. Do not change wake disabled/enabled status */
- acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+ acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
- ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
- gpe_event_info));
+ ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info));
/* This was a wake-only GPE */
- return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+ return_ACPI_STATUS(AE_WAKE_ONLY_GPE);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
-
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index 84186a7d17b2..b312eb33c43e 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -46,41 +46,29 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evgpeblk")
+ACPI_MODULE_NAME("evgpeblk")
/* Local prototypes */
-
static acpi_status
-acpi_ev_save_method_info (
- acpi_handle obj_handle,
- u32 level,
- void *obj_desc,
- void **return_value);
+acpi_ev_save_method_info(acpi_handle obj_handle,
+ u32 level, void *obj_desc, void **return_value);
static acpi_status
-acpi_ev_match_prw_and_gpe (
- acpi_handle obj_handle,
- u32 level,
- void *info,
- void **return_value);
+acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
+ u32 level, void *info, void **return_value);
-static struct acpi_gpe_xrupt_info *
-acpi_ev_get_gpe_xrupt_block (
- u32 interrupt_level);
+static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
+ interrupt_number);
static acpi_status
-acpi_ev_delete_gpe_xrupt (
- struct acpi_gpe_xrupt_info *gpe_xrupt);
+acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
static acpi_status
-acpi_ev_install_gpe_block (
- struct acpi_gpe_block_info *gpe_block,
- u32 interrupt_level);
+acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
+ u32 interrupt_number);
static acpi_status
-acpi_ev_create_gpe_info_blocks (
- struct acpi_gpe_block_info *gpe_block);
-
+acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
/*******************************************************************************
*
@@ -96,16 +84,12 @@ acpi_ev_create_gpe_info_blocks (
*
******************************************************************************/
-u8
-acpi_ev_valid_gpe_event (
- struct acpi_gpe_event_info *gpe_event_info)
+u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
{
- struct acpi_gpe_xrupt_info *gpe_xrupt_block;
- struct acpi_gpe_block_info *gpe_block;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_gpe_xrupt_info *gpe_xrupt_block;
+ struct acpi_gpe_block_info *gpe_block;
+ ACPI_FUNCTION_ENTRY();
/* No need for spin lock since we are not changing any list elements */
@@ -119,7 +103,10 @@ acpi_ev_valid_gpe_event (
while (gpe_block) {
if ((&gpe_block->event_info[0] <= gpe_event_info) &&
- (&gpe_block->event_info[((acpi_size) gpe_block->register_count) * 8] > gpe_event_info)) {
+ (&gpe_block->
+ event_info[((acpi_size) gpe_block->
+ register_count) * 8] >
+ gpe_event_info)) {
return (TRUE);
}
@@ -132,13 +119,11 @@ acpi_ev_valid_gpe_event (
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_walk_gpe_list
*
* PARAMETERS: gpe_walk_callback - Routine called for each GPE block
- * Flags - ACPI_NOT_ISR or ACPI_ISR
*
* RETURN: Status
*
@@ -146,20 +131,16 @@ acpi_ev_valid_gpe_event (
*
******************************************************************************/
-acpi_status
-acpi_ev_walk_gpe_list (
- ACPI_GPE_CALLBACK gpe_walk_callback,
- u32 flags)
+acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- acpi_status status = AE_OK;
-
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ acpi_status status = AE_OK;
+ u32 flags;
- ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
+ ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
-
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Walk the interrupt level descriptor list */
@@ -171,8 +152,8 @@ acpi_ev_walk_gpe_list (
while (gpe_block) {
/* One callback per GPE block */
- status = gpe_walk_callback (gpe_xrupt_info, gpe_block);
- if (ACPI_FAILURE (status)) {
+ status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -182,12 +163,11 @@ acpi_ev_walk_gpe_list (
gpe_xrupt_info = gpe_xrupt_info->next;
}
-unlock_and_exit:
- acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_handlers
@@ -203,17 +183,14 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ev_delete_gpe_handlers (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block)
{
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
-
-
- ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers");
/* Examine each GPE Register within the block */
@@ -221,21 +198,23 @@ acpi_ev_delete_gpe_handlers (
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
- gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ gpe_event_info =
+ &gpe_block->
+ event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_HANDLER) {
- ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
+ ACPI_GPE_DISPATCH_HANDLER) {
+ ACPI_MEM_FREE(gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
- gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
+ gpe_event_info->flags &=
+ ~ACPI_GPE_DISPATCH_MASK;
}
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_save_method_info
@@ -259,30 +238,26 @@ acpi_ev_delete_gpe_handlers (
******************************************************************************/
static acpi_status
-acpi_ev_save_method_info (
- acpi_handle obj_handle,
- u32 level,
- void *obj_desc,
- void **return_value)
+acpi_ev_save_method_info(acpi_handle obj_handle,
+ u32 level, void *obj_desc, void **return_value)
{
- struct acpi_gpe_block_info *gpe_block = (void *) obj_desc;
- struct acpi_gpe_event_info *gpe_event_info;
- u32 gpe_number;
- char name[ACPI_NAME_SIZE + 1];
- u8 type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_save_method_info");
+ struct acpi_gpe_block_info *gpe_block = (void *)obj_desc;
+ struct acpi_gpe_event_info *gpe_event_info;
+ u32 gpe_number;
+ char name[ACPI_NAME_SIZE + 1];
+ u8 type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_save_method_info");
/*
* _Lxx and _Exx GPE method support
*
* 1) Extract the name from the object and convert to a string
*/
- ACPI_MOVE_32_TO_32 (name,
- &((struct acpi_namespace_node *) obj_handle)->name.integer);
+ ACPI_MOVE_32_TO_32(name,
+ &((struct acpi_namespace_node *)obj_handle)->name.
+ integer);
name[ACPI_NAME_SIZE] = 0;
/*
@@ -304,34 +279,36 @@ acpi_ev_save_method_info (
default:
/* Unknown method type, just ignore it! */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
- name));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
+ name));
+ return_ACPI_STATUS(AE_OK);
}
/* Convert the last two characters of the name to the GPE Number */
- gpe_number = ACPI_STRTOUL (&name[2], NULL, 16);
+ gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
if (gpe_number == ACPI_UINT32_MAX) {
/* Conversion failed; invalid method, just ignore it */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
- name));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
+ name));
+ return_ACPI_STATUS(AE_OK);
}
/* Ensure that we have a valid GPE number for this GPE block */
if ((gpe_number < gpe_block->block_base_number) ||
- (gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) {
+ (gpe_number >=
+ (gpe_block->block_base_number +
+ (gpe_block->register_count * 8)))) {
/*
* Not valid for this GPE block, just ignore it
* However, it may be valid for a different GPE block, since GPE0 and GPE1
* methods both appear under \_GPE.
*/
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -339,24 +316,25 @@ acpi_ev_save_method_info (
* for use during dispatch of this GPE. Default type is RUNTIME, although
* this may change when the _PRW methods are executed later.
*/
- gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
+ gpe_event_info =
+ &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
- ACPI_GPE_TYPE_RUNTIME);
+ ACPI_GPE_TYPE_RUNTIME);
- gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
+ gpe_event_info->dispatch.method_node =
+ (struct acpi_namespace_node *)obj_handle;
/* Update enable mask, but don't enable the HW GPE as of yet */
- status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
+ status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
- "Registered GPE method %s as GPE number 0x%.2X\n",
- name, gpe_number));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "Registered GPE method %s as GPE number 0x%.2X\n",
+ name, gpe_number));
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_match_prw_and_gpe
@@ -373,34 +351,29 @@ acpi_ev_save_method_info (
******************************************************************************/
static acpi_status
-acpi_ev_match_prw_and_gpe (
- acpi_handle obj_handle,
- u32 level,
- void *info,
- void **return_value)
+acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
+ u32 level, void *info, void **return_value)
{
- struct acpi_gpe_walk_info *gpe_info = (void *) info;
- struct acpi_namespace_node *gpe_device;
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_namespace_node *target_gpe_device;
- struct acpi_gpe_event_info *gpe_event_info;
- union acpi_operand_object *pkg_desc;
- union acpi_operand_object *obj_desc;
- u32 gpe_number;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
-
+ struct acpi_gpe_walk_info *gpe_info = (void *)info;
+ struct acpi_namespace_node *gpe_device;
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_namespace_node *target_gpe_device;
+ struct acpi_gpe_event_info *gpe_event_info;
+ union acpi_operand_object *pkg_desc;
+ union acpi_operand_object *obj_desc;
+ u32 gpe_number;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe");
/* Check for a _PRW method under this device */
- status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
- ACPI_BTYPE_PACKAGE, &pkg_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW,
+ ACPI_BTYPE_PACKAGE, &pkg_desc);
+ if (ACPI_FAILURE(status)) {
/* Ignore all errors from _PRW, we don't want to abort the subsystem */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* The returned _PRW package must have at least two elements */
@@ -420,7 +393,7 @@ acpi_ev_match_prw_and_gpe (
*/
obj_desc = pkg_desc->package.elements[0];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Use FADT-defined GPE device (from definition of _PRW) */
target_gpe_device = acpi_gbl_fadt_gpe_device;
@@ -428,22 +401,23 @@ acpi_ev_match_prw_and_gpe (
/* Integer is the GPE number in the FADT described GPE blocks */
gpe_number = (u32) obj_desc->integer.value;
- }
- else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+ } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
/* Package contains a GPE reference and GPE number within a GPE block */
if ((obj_desc->package.count < 2) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) !=
+ ACPI_TYPE_LOCAL_REFERENCE)
+ || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) !=
+ ACPI_TYPE_INTEGER)) {
goto cleanup;
}
/* Get GPE block reference and decode */
- target_gpe_device = obj_desc->package.elements[0]->reference.node;
+ target_gpe_device =
+ obj_desc->package.elements[0]->reference.node;
gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
- }
- else {
+ } else {
/* Unknown type, just ignore it */
goto cleanup;
@@ -458,31 +432,37 @@ acpi_ev_match_prw_and_gpe (
* associated with the GPE device.
*/
if ((gpe_device == target_gpe_device) &&
- (gpe_number >= gpe_block->block_base_number) &&
- (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
- gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
+ (gpe_number >= gpe_block->block_base_number) &&
+ (gpe_number <
+ gpe_block->block_base_number + (gpe_block->register_count * 8))) {
+ gpe_event_info =
+ &gpe_block->event_info[gpe_number -
+ gpe_block->block_base_number];
/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
- gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
- status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
- if (ACPI_FAILURE (status)) {
+ gpe_event_info->flags &=
+ ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+ status =
+ acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
+ status =
+ acpi_ev_update_gpe_enable_masks(gpe_event_info,
+ ACPI_GPE_DISABLE);
}
-cleanup:
- acpi_ut_remove_reference (pkg_desc);
- return_ACPI_STATUS (AE_OK);
+ cleanup:
+ acpi_ut_remove_reference(pkg_desc);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
- * PARAMETERS: interrupt_level - Interrupt for a GPE block
+ * PARAMETERS: interrupt_number - Interrupt for a GPE block
*
* RETURN: A GPE interrupt block
*
@@ -493,24 +473,22 @@ cleanup:
*
******************************************************************************/
-static struct acpi_gpe_xrupt_info *
-acpi_ev_get_gpe_xrupt_block (
- u32 interrupt_level)
+static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
+ interrupt_number)
{
- struct acpi_gpe_xrupt_info *next_gpe_xrupt;
- struct acpi_gpe_xrupt_info *gpe_xrupt;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_get_gpe_xrupt_block");
+ struct acpi_gpe_xrupt_info *next_gpe_xrupt;
+ struct acpi_gpe_xrupt_info *gpe_xrupt;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
/* No need for lock since we are not changing any list elements here */
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt) {
- if (next_gpe_xrupt->interrupt_level == interrupt_level) {
- return_PTR (next_gpe_xrupt);
+ if (next_gpe_xrupt->interrupt_number == interrupt_number) {
+ return_PTR(next_gpe_xrupt);
}
next_gpe_xrupt = next_gpe_xrupt->next;
@@ -518,16 +496,16 @@ acpi_ev_get_gpe_xrupt_block (
/* Not found, must allocate a new xrupt descriptor */
- gpe_xrupt = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_xrupt_info));
+ gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- gpe_xrupt->interrupt_level = interrupt_level;
+ gpe_xrupt->interrupt_number = interrupt_number;
/* Install new interrupt descriptor with spin lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (acpi_gbl_gpe_xrupt_list_head) {
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt->next) {
@@ -536,29 +514,28 @@ acpi_ev_get_gpe_xrupt_block (
next_gpe_xrupt->next = gpe_xrupt;
gpe_xrupt->previous = next_gpe_xrupt;
- }
- else {
+ } else {
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Install new interrupt handler if not SCI_INT */
- if (interrupt_level != acpi_gbl_FADT->sci_int) {
- status = acpi_os_install_interrupt_handler (interrupt_level,
- acpi_ev_gpe_xrupt_handler, gpe_xrupt);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not install GPE interrupt handler at level 0x%X\n",
- interrupt_level));
- return_PTR (NULL);
+ if (interrupt_number != acpi_gbl_FADT->sci_int) {
+ status = acpi_os_install_interrupt_handler(interrupt_number,
+ acpi_ev_gpe_xrupt_handler,
+ gpe_xrupt);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not install GPE interrupt handler at level 0x%X\n",
+ interrupt_number));
+ return_PTR(NULL);
}
}
- return_PTR (gpe_xrupt);
+ return_PTR(gpe_xrupt);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_xrupt
@@ -573,33 +550,31 @@ acpi_ev_get_gpe_xrupt_block (
******************************************************************************/
static acpi_status
-acpi_ev_delete_gpe_xrupt (
- struct acpi_gpe_xrupt_info *gpe_xrupt)
+acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt");
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
/* We never want to remove the SCI interrupt handler */
- if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) {
+ if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) {
gpe_xrupt->gpe_block_list_head = NULL;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Disable this interrupt */
- status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level,
- acpi_ev_gpe_xrupt_handler);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
+ acpi_ev_gpe_xrupt_handler);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Unlink the interrupt block with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt->previous) {
gpe_xrupt->previous->next = gpe_xrupt->next;
}
@@ -607,21 +582,20 @@ acpi_ev_delete_gpe_xrupt (
if (gpe_xrupt->next) {
gpe_xrupt->next->previous = gpe_xrupt->previous;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Free the block */
- ACPI_MEM_FREE (gpe_xrupt);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MEM_FREE(gpe_xrupt);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_gpe_block
*
* PARAMETERS: gpe_block - New GPE block
- * interrupt_level - Level to be associated with this GPE block
+ * interrupt_number - Xrupt to be associated with this GPE block
*
* RETURN: Status
*
@@ -630,24 +604,22 @@ acpi_ev_delete_gpe_xrupt (
******************************************************************************/
static acpi_status
-acpi_ev_install_gpe_block (
- struct acpi_gpe_block_info *gpe_block,
- u32 interrupt_level)
+acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
+ u32 interrupt_number)
{
- struct acpi_gpe_block_info *next_gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_block;
- acpi_status status;
+ struct acpi_gpe_block_info *next_gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_block;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_install_gpe_block");
- ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
-
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
+ gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number);
if (!gpe_xrupt_block) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -655,7 +627,7 @@ acpi_ev_install_gpe_block (
/* Install the new block at the end of the list with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_xrupt_block->gpe_block_list_head) {
next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (next_gpe_block->next) {
@@ -664,20 +636,18 @@ acpi_ev_install_gpe_block (
next_gpe_block->next = gpe_block;
gpe_block->previous = next_gpe_block;
- }
- else {
+ } else {
gpe_xrupt_block->gpe_block_list_head = gpe_block;
}
gpe_block->xrupt_block = gpe_xrupt_block;
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_block
@@ -690,62 +660,57 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ev_delete_gpe_block (
- struct acpi_gpe_block_info *gpe_block)
+acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("ev_install_gpe_block");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Disable all GPEs in this block */
- status = acpi_hw_disable_gpe_block (gpe_block->xrupt_block, gpe_block);
+ status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block);
if (!gpe_block->previous && !gpe_block->next) {
/* This is the last gpe_block on this interrupt */
- status = acpi_ev_delete_gpe_xrupt (gpe_block->xrupt_block);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Remove the block on this interrupt with lock */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (gpe_block->previous) {
gpe_block->previous->next = gpe_block->next;
- }
- else {
- gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next;
+ } else {
+ gpe_block->xrupt_block->gpe_block_list_head =
+ gpe_block->next;
}
if (gpe_block->next) {
gpe_block->next->previous = gpe_block->previous;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
/* Free the gpe_block */
- ACPI_MEM_FREE (gpe_block->register_info);
- ACPI_MEM_FREE (gpe_block->event_info);
- ACPI_MEM_FREE (gpe_block);
+ ACPI_MEM_FREE(gpe_block->register_info);
+ ACPI_MEM_FREE(gpe_block->event_info);
+ ACPI_MEM_FREE(gpe_block);
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_info_blocks
@@ -759,43 +724,41 @@ unlock_and_exit:
******************************************************************************/
static acpi_status
-acpi_ev_create_gpe_info_blocks (
- struct acpi_gpe_block_info *gpe_block)
+acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
{
- struct acpi_gpe_register_info *gpe_register_info = NULL;
- struct acpi_gpe_event_info *gpe_event_info = NULL;
- struct acpi_gpe_event_info *this_event;
- struct acpi_gpe_register_info *this_register;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_create_gpe_info_blocks");
+ struct acpi_gpe_register_info *gpe_register_info = NULL;
+ struct acpi_gpe_event_info *gpe_event_info = NULL;
+ struct acpi_gpe_event_info *this_event;
+ struct acpi_gpe_register_info *this_register;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks");
/* Allocate the GPE register information block */
- gpe_register_info = ACPI_MEM_CALLOCATE (
- (acpi_size) gpe_block->register_count *
- sizeof (struct acpi_gpe_register_info));
+ gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block->
+ register_count *
+ sizeof(struct
+ acpi_gpe_register_info));
if (!gpe_register_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not allocate the gpe_register_info table\n"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not allocate the gpe_register_info table\n"));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Allocate the GPE event_info block. There are eight distinct GPEs
* per register. Initialization to zeros is sufficient.
*/
- gpe_event_info = ACPI_MEM_CALLOCATE (
- ((acpi_size) gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH) *
- sizeof (struct acpi_gpe_event_info));
+ gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
+ register_count *
+ ACPI_GPE_REGISTER_WIDTH) *
+ sizeof(struct acpi_gpe_event_info));
if (!gpe_event_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not allocate the gpe_event_info table\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not allocate the gpe_event_info table\n"));
status = AE_NO_MEMORY;
goto error_exit;
}
@@ -803,7 +766,7 @@ acpi_ev_create_gpe_info_blocks (
/* Save the new Info arrays in the GPE block */
gpe_block->register_info = gpe_register_info;
- gpe_block->event_info = gpe_event_info;
+ gpe_block->event_info = gpe_event_info;
/*
* Initialize the GPE Register and Event structures. A goal of these
@@ -812,29 +775,34 @@ acpi_ev_create_gpe_info_blocks (
* and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
- this_event = gpe_event_info;
+ this_event = gpe_event_info;
for (i = 0; i < gpe_block->register_count; i++) {
/* Init the register_info for this GPE register (8 GPEs) */
- this_register->base_gpe_number = (u8) (gpe_block->block_base_number +
- (i * ACPI_GPE_REGISTER_WIDTH));
-
- ACPI_STORE_ADDRESS (this_register->status_address.address,
- (gpe_block->block_address.address
- + i));
-
- ACPI_STORE_ADDRESS (this_register->enable_address.address,
- (gpe_block->block_address.address
- + i
- + gpe_block->register_count));
-
- this_register->status_address.address_space_id = gpe_block->block_address.address_space_id;
- this_register->enable_address.address_space_id = gpe_block->block_address.address_space_id;
- this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
- this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH;
- this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
- this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH;
+ this_register->base_gpe_number =
+ (u8) (gpe_block->block_base_number +
+ (i * ACPI_GPE_REGISTER_WIDTH));
+
+ ACPI_STORE_ADDRESS(this_register->status_address.address,
+ (gpe_block->block_address.address + i));
+
+ ACPI_STORE_ADDRESS(this_register->enable_address.address,
+ (gpe_block->block_address.address
+ + i + gpe_block->register_count));
+
+ this_register->status_address.address_space_id =
+ gpe_block->block_address.address_space_id;
+ this_register->enable_address.address_space_id =
+ gpe_block->block_address.address_space_id;
+ this_register->status_address.register_bit_width =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->enable_address.register_bit_width =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->status_address.register_bit_offset =
+ ACPI_GPE_REGISTER_WIDTH;
+ this_register->enable_address.register_bit_offset =
+ ACPI_GPE_REGISTER_WIDTH;
/* Init the event_info for each GPE within this register */
@@ -849,36 +817,36 @@ acpi_ev_create_gpe_info_blocks (
* are cleared by writing a '1', while enable registers are cleared
* by writing a '0'.
*/
- status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00,
- &this_register->enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
+ &this_register->
+ enable_address);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
- status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF,
- &this_register->status_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
+ &this_register->
+ status_address);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
this_register++;
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
if (gpe_register_info) {
- ACPI_MEM_FREE (gpe_register_info);
+ ACPI_MEM_FREE(gpe_register_info);
}
if (gpe_event_info) {
- ACPI_MEM_FREE (gpe_event_info);
+ ACPI_MEM_FREE(gpe_event_info);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_create_gpe_block
@@ -887,7 +855,7 @@ error_exit:
* gpe_block_address - Address and space_iD
* register_count - Number of GPE register pairs in the block
* gpe_block_base_number - Starting GPE number for the block
- * interrupt_level - H/W interrupt for the block
+ * interrupt_number - H/W interrupt for the block
* return_gpe_block - Where the new block descriptor is returned
*
* RETURN: Status
@@ -897,68 +865,66 @@ error_exit:
******************************************************************************/
acpi_status
-acpi_ev_create_gpe_block (
- struct acpi_namespace_node *gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u8 gpe_block_base_number,
- u32 interrupt_level,
- struct acpi_gpe_block_info **return_gpe_block)
+acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u8 gpe_block_base_number,
+ u32 interrupt_number,
+ struct acpi_gpe_block_info **return_gpe_block)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
- u32 wake_gpe_count;
- u32 gpe_enabled_count;
- acpi_status status;
- struct acpi_gpe_walk_info gpe_info;
-
-
- ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ u32 wake_gpe_count;
+ u32 gpe_enabled_count;
+ acpi_status status;
+ struct acpi_gpe_walk_info gpe_info;
+ ACPI_FUNCTION_TRACE("ev_create_gpe_block");
if (!register_count) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Allocate a new GPE block */
- gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
+ gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info));
if (!gpe_block) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the new GPE block */
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
- gpe_block->node = gpe_device;
+ gpe_block->node = gpe_device;
- ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address,
- sizeof (struct acpi_generic_address));
+ ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
+ sizeof(struct acpi_generic_address));
/* Create the register_info and event_info sub-structures */
- status = acpi_ev_create_gpe_info_blocks (gpe_block);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (gpe_block);
- return_ACPI_STATUS (status);
+ status = acpi_ev_create_gpe_info_blocks(gpe_block);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(gpe_block);
+ return_ACPI_STATUS(status);
}
/* Install the new block in the global list(s) */
- status = acpi_ev_install_gpe_block (gpe_block, interrupt_level);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (gpe_block);
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(gpe_block);
+ return_ACPI_STATUS(status);
}
/* Find all GPE methods (_Lxx, _Exx) for this block */
- status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
- gpe_block, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ev_save_method_info, gpe_block,
+ NULL);
/*
* Runtime option: Should Wake GPEs be enabled at runtime? The default
@@ -974,9 +940,11 @@ acpi_ev_create_gpe_block (
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
- &gpe_info, NULL);
+ status =
+ acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
+ acpi_ev_match_prw_and_gpe, &gpe_info,
+ NULL);
}
/*
@@ -991,10 +959,14 @@ acpi_ev_create_gpe_block (
for (j = 0; j < 8; j++) {
/* Get the info block for this particular GPE */
- gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+ gpe_event_info =
+ &gpe_block->
+ event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
- if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
- (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
+ if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_METHOD)
+ && (gpe_event_info->
+ flags & ACPI_GPE_TYPE_RUNTIME)) {
gpe_enabled_count++;
}
@@ -1006,22 +978,22 @@ acpi_ev_create_gpe_block (
/* Dump info about this GPE block */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
- (u32) gpe_block->block_base_number,
- (u32) (gpe_block->block_base_number +
- ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
- gpe_device->name.ascii,
- gpe_block->register_count,
- interrupt_level));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ (u32) gpe_block->block_base_number,
+ (u32) (gpe_block->block_base_number +
+ ((gpe_block->register_count *
+ ACPI_GPE_REGISTER_WIDTH) - 1)),
+ gpe_device->name.ascii, gpe_block->register_count,
+ interrupt_number));
/* Enable all valid GPEs found above */
- status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
+ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
- wake_gpe_count, gpe_enabled_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
+ wake_gpe_count, gpe_enabled_count));
/* Return the new block */
@@ -1029,10 +1001,9 @@ acpi_ev_create_gpe_block (
(*return_gpe_block) = gpe_block;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_initialize
@@ -1045,22 +1016,18 @@ acpi_ev_create_gpe_block (
*
******************************************************************************/
-acpi_status
-acpi_ev_gpe_initialize (
- void)
+acpi_status acpi_ev_gpe_initialize(void)
{
- u32 register_count0 = 0;
- u32 register_count1 = 0;
- u32 gpe_number_max = 0;
- acpi_status status;
+ u32 register_count0 = 0;
+ u32 register_count1 = 0;
+ u32 gpe_number_max = 0;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_gpe_initialize");
- ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
-
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -1088,29 +1055,29 @@ acpi_ev_gpe_initialize (
* If EITHER the register length OR the block address are zero, then that
* particular block is not supported.
*/
- if (acpi_gbl_FADT->gpe0_blk_len &&
- acpi_gbl_FADT->xgpe0_blk.address) {
+ if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) {
/* GPE block 0 exists (has both length and address > 0) */
register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2);
- gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
+ gpe_number_max =
+ (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
/* Install GPE Block 0 */
- status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device,
- &acpi_gbl_FADT->xgpe0_blk, register_count0, 0,
- acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
+ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
+ &acpi_gbl_FADT->xgpe0_blk,
+ register_count0, 0,
+ acpi_gbl_FADT->sci_int,
+ &acpi_gbl_gpe_fadt_blocks[0]);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not create GPE Block 0, %s\n",
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n",
+ acpi_format_exception(status)));
}
}
- if (acpi_gbl_FADT->gpe1_blk_len &&
- acpi_gbl_FADT->xgpe1_blk.address) {
+ if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) {
/* GPE block 1 exists (has both length and address > 0) */
register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2);
@@ -1118,29 +1085,26 @@ acpi_ev_gpe_initialize (
/* Check for GPE0/GPE1 overlap (if both banks exist) */
if ((register_count0) &&
- (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
- ACPI_REPORT_ERROR ((
- "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n",
- gpe_number_max, acpi_gbl_FADT->gpe1_base,
- acpi_gbl_FADT->gpe1_base +
- ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
+ (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
+ ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
/* Ignore GPE1 block by setting the register count to zero */
register_count1 = 0;
- }
- else {
+ } else {
/* Install GPE Block 1 */
- status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device,
- &acpi_gbl_FADT->xgpe1_blk, register_count1,
- acpi_gbl_FADT->gpe1_base,
- acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
-
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not create GPE Block 1, %s\n",
- acpi_format_exception (status)));
+ status =
+ acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
+ &acpi_gbl_FADT->xgpe1_blk,
+ register_count1,
+ acpi_gbl_FADT->gpe1_base,
+ acpi_gbl_FADT->sci_int,
+ &acpi_gbl_gpe_fadt_blocks
+ [1]);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status)));
}
/*
@@ -1148,7 +1112,7 @@ acpi_ev_gpe_initialize (
* space. However, GPE0 always starts at GPE number zero.
*/
gpe_number_max = acpi_gbl_FADT->gpe1_base +
- ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
+ ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
}
}
@@ -1157,8 +1121,8 @@ acpi_ev_gpe_initialize (
if ((register_count0 + register_count1) == 0) {
/* GPEs are not required by ACPI, this is OK */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "There are no GPE blocks defined in the FADT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "There are no GPE blocks defined in the FADT\n"));
status = AE_OK;
goto cleanup;
}
@@ -1166,15 +1130,12 @@ acpi_ev_gpe_initialize (
/* Check for Max GPE number out-of-range */
if (gpe_number_max > ACPI_GPE_MAX) {
- ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
- gpe_number_max));
+ ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max));
status = AE_BAD_VALUE;
goto cleanup;
}
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (AE_OK);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 659e90956112..7e57b8470f55 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -47,12 +47,10 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evmisc")
-
+ACPI_MODULE_NAME("evmisc")
#ifdef ACPI_DEBUG_OUTPUT
-static const char *acpi_notify_value_names[] =
-{
+static const char *acpi_notify_value_names[] = {
"Bus Check",
"Device Check",
"Device Wake",
@@ -66,18 +64,11 @@ static const char *acpi_notify_value_names[] =
/* Local prototypes */
-static void ACPI_SYSTEM_XFACE
-acpi_ev_notify_dispatch (
- void *context);
-
-static void ACPI_SYSTEM_XFACE
-acpi_ev_global_lock_thread (
- void *context);
+static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
-static u32
-acpi_ev_global_lock_handler (
- void *context);
+static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context);
+static u32 acpi_ev_global_lock_handler(void *context);
/*******************************************************************************
*
@@ -93,9 +84,7 @@ acpi_ev_global_lock_handler (
*
******************************************************************************/
-u8
-acpi_ev_is_notify_object (
- struct acpi_namespace_node *node)
+u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
{
switch (node->type) {
case ACPI_TYPE_DEVICE:
@@ -112,7 +101,6 @@ acpi_ev_is_notify_object (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_queue_notify_request
@@ -128,18 +116,15 @@ acpi_ev_is_notify_object (
******************************************************************************/
acpi_status
-acpi_ev_queue_notify_request (
- struct acpi_namespace_node *node,
- u32 notify_value)
+acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
+ u32 notify_value)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj = NULL;
- union acpi_generic_state *notify_info;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_NAME ("ev_queue_notify_request");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj = NULL;
+ union acpi_generic_state *notify_info;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_NAME("ev_queue_notify_request");
/*
* For value 3 (Ejection Request), some device method may need to be run.
@@ -148,22 +133,22 @@ acpi_ev_queue_notify_request (
* For value 0x80 (Status Change) on the power button or sleep button,
* initiate soft-off or sleep operation?
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Dispatching Notify(%X) on node %p\n", notify_value, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Dispatching Notify(%X) on node %p\n", notify_value,
+ node));
if (notify_value <= 7) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
- acpi_notify_value_names[notify_value]));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Notify value: 0x%2.2X **Device Specific**\n",
- notify_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
+ acpi_notify_value_names[notify_value]));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Notify value: 0x%2.2X **Device Specific**\n",
+ notify_value));
}
/* Get the notify object attached to the NS Node */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* We have the notify object, Get the right handler */
@@ -174,10 +159,11 @@ acpi_ev_queue_notify_request (
case ACPI_TYPE_POWER:
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
- handler_obj = obj_desc->common_notify.system_notify;
- }
- else {
- handler_obj = obj_desc->common_notify.device_notify;
+ handler_obj =
+ obj_desc->common_notify.system_notify;
+ } else {
+ handler_obj =
+ obj_desc->common_notify.device_notify;
}
break;
@@ -189,23 +175,25 @@ acpi_ev_queue_notify_request (
/* If there is any handler to run, schedule the dispatcher */
- if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
- (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) ||
- handler_obj) {
- notify_info = acpi_ut_create_generic_state ();
+ if ((acpi_gbl_system_notify.handler
+ && (notify_value <= ACPI_MAX_SYS_NOTIFY))
+ || (acpi_gbl_device_notify.handler
+ && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) {
+ notify_info = acpi_ut_create_generic_state();
if (!notify_info) {
return (AE_NO_MEMORY);
}
notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
- notify_info->notify.node = node;
- notify_info->notify.value = (u16) notify_value;
+ notify_info->notify.node = node;
+ notify_info->notify.value = (u16) notify_value;
notify_info->notify.handler_obj = handler_obj;
- status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
- acpi_ev_notify_dispatch, notify_info);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_generic_state (notify_info);
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
+ acpi_ev_notify_dispatch,
+ notify_info);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_generic_state(notify_info);
}
}
@@ -214,15 +202,15 @@ acpi_ev_queue_notify_request (
* There is no per-device notify handler for this device.
* This may or may not be a problem.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "No notify handler for Notify(%4.4s, %X) node %p\n",
- acpi_ut_get_node_name (node), notify_value, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No notify handler for Notify(%4.4s, %X) node %p\n",
+ acpi_ut_get_node_name(node), notify_value,
+ node));
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_notify_dispatch
@@ -236,18 +224,15 @@ acpi_ev_queue_notify_request (
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_notify_dispatch (
- void *context)
+static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
{
- union acpi_generic_state *notify_info = (union acpi_generic_state *) context;
- acpi_notify_handler global_handler = NULL;
- void *global_context = NULL;
- union acpi_operand_object *handler_obj;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_generic_state *notify_info =
+ (union acpi_generic_state *)context;
+ acpi_notify_handler global_handler = NULL;
+ void *global_context = NULL;
+ union acpi_operand_object *handler_obj;
+ ACPI_FUNCTION_ENTRY();
/*
* We will invoke a global notify handler if installed.
@@ -261,8 +246,7 @@ acpi_ev_notify_dispatch (
global_handler = acpi_gbl_system_notify.handler;
global_context = acpi_gbl_system_notify.context;
}
- }
- else {
+ } else {
/* Global driver notification handler */
if (acpi_gbl_device_notify.handler) {
@@ -274,25 +258,24 @@ acpi_ev_notify_dispatch (
/* Invoke the system handler first, if present */
if (global_handler) {
- global_handler (notify_info->notify.node, notify_info->notify.value,
- global_context);
+ global_handler(notify_info->notify.node,
+ notify_info->notify.value, global_context);
}
/* Now invoke the per-device handler, if present */
handler_obj = notify_info->notify.handler_obj;
if (handler_obj) {
- handler_obj->notify.handler (notify_info->notify.node,
- notify_info->notify.value,
- handler_obj->notify.context);
+ handler_obj->notify.handler(notify_info->notify.node,
+ notify_info->notify.value,
+ handler_obj->notify.context);
}
/* All done with the info object */
- acpi_ut_delete_generic_state (notify_info);
+ acpi_ut_delete_generic_state(notify_info);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_global_lock_thread
@@ -307,27 +290,24 @@ acpi_ev_notify_dispatch (
*
******************************************************************************/
-static void ACPI_SYSTEM_XFACE
-acpi_ev_global_lock_thread (
- void *context)
+static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
{
- acpi_status status;
-
+ acpi_status status;
/* Signal threads that are waiting for the lock */
if (acpi_gbl_global_lock_thread_count) {
/* Send sufficient units to the semaphore */
- status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore,
- acpi_gbl_global_lock_thread_count);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n"));
+ status =
+ acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
+ acpi_gbl_global_lock_thread_count);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not signal Global Lock semaphore\n"));
}
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_global_lock_handler
@@ -342,20 +322,17 @@ acpi_ev_global_lock_thread (
*
******************************************************************************/
-static u32
-acpi_ev_global_lock_handler (
- void *context)
+static u32 acpi_ev_global_lock_handler(void *context)
{
- u8 acquired = FALSE;
- acpi_status status;
-
+ u8 acquired = FALSE;
+ acpi_status status;
/*
* Attempt to get the lock
* If we don't get it now, it will be marked pending and we will
* take another interrupt when it becomes free.
*/
- ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
/* Got the lock, now wake all threads waiting for it */
@@ -363,11 +340,11 @@ acpi_ev_global_lock_handler (
/* Run the Global Lock thread which will signal all waiting threads */
- status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
- acpi_ev_global_lock_thread, context);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n",
- acpi_format_exception (status)));
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
+ acpi_ev_global_lock_thread,
+ context);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not queue Global Lock thread, %s\n", acpi_format_exception(status)));
return (ACPI_INTERRUPT_NOT_HANDLED);
}
@@ -376,7 +353,6 @@ acpi_ev_global_lock_handler (
return (ACPI_INTERRUPT_HANDLED);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_init_global_lock_handler
@@ -389,19 +365,16 @@ acpi_ev_global_lock_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_init_global_lock_handler (
- void)
+acpi_status acpi_ev_init_global_lock_handler(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_init_global_lock_handler");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_init_global_lock_handler");
acpi_gbl_global_lock_present = TRUE;
- status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL,
- acpi_ev_global_lock_handler, NULL);
+ status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
+ acpi_ev_global_lock_handler,
+ NULL);
/*
* If the global lock does not exist on this platform, the attempt
@@ -411,14 +384,15 @@ acpi_ev_init_global_lock_handler (
* with an error.
*/
if (status == AE_NO_HARDWARE_RESPONSE) {
+ ACPI_REPORT_ERROR(("No response from Global Lock hardware, disabling lock\n"));
+
acpi_gbl_global_lock_present = FALSE;
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_acquire_global_lock
@@ -431,22 +405,18 @@ acpi_ev_init_global_lock_handler (
*
*****************************************************************************/
-acpi_status
-acpi_ev_acquire_global_lock (
- u16 timeout)
+acpi_status acpi_ev_acquire_global_lock(u16 timeout)
{
- acpi_status status = AE_OK;
- u8 acquired = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("ev_acquire_global_lock");
+ acpi_status status = AE_OK;
+ u8 acquired = FALSE;
+ ACPI_FUNCTION_TRACE("ev_acquire_global_lock");
#ifndef ACPI_APPLICATION
/* Make sure that we actually have a global lock */
if (!acpi_gbl_global_lock_present) {
- return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
+ return_ACPI_STATUS(AE_NO_GLOBAL_LOCK);
}
#endif
@@ -459,37 +429,37 @@ acpi_ev_acquire_global_lock (
* we are done
*/
if (acpi_gbl_global_lock_acquired) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* We must acquire the actual hardware lock */
- ACPI_ACQUIRE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
- /* We got the lock */
+ /* We got the lock */
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Acquired the HW Global Lock\n"));
acpi_gbl_global_lock_acquired = TRUE;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
* Did not get the lock. The pending bit was set above, and we must now
* wait until we get the global lock released interrupt.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
/*
* Acquire the global lock semaphore first.
* Since this wait will block, we must release the interpreter
*/
- status = acpi_ex_system_wait_semaphore (acpi_gbl_global_lock_semaphore,
- timeout);
- return_ACPI_STATUS (status);
+ status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
+ timeout);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_release_global_lock
@@ -502,21 +472,16 @@ acpi_ev_acquire_global_lock (
*
******************************************************************************/
-acpi_status
-acpi_ev_release_global_lock (
- void)
+acpi_status acpi_ev_release_global_lock(void)
{
- u8 pending = FALSE;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ev_release_global_lock");
+ u8 pending = FALSE;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ev_release_global_lock");
if (!acpi_gbl_global_lock_thread_count) {
- ACPI_REPORT_WARNING((
- "Cannot release HW Global Lock, it has not been acquired\n"));
- return_ACPI_STATUS (AE_NOT_ACQUIRED);
+ ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
+ return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
/* One fewer thread has the global lock */
@@ -525,14 +490,14 @@ acpi_ev_release_global_lock (
if (acpi_gbl_global_lock_thread_count) {
/* There are still some threads holding the lock, cannot release */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
* No more threads holding lock, we can do the actual hardware
* release
*/
- ACPI_RELEASE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, pending);
+ ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
acpi_gbl_global_lock_acquired = FALSE;
/*
@@ -540,14 +505,13 @@ acpi_ev_release_global_lock (
* register
*/
if (pending) {
- status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE,
- 1, ACPI_MTX_LOCK);
+ status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
+ 1, ACPI_MTX_LOCK);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_terminate
@@ -560,16 +524,12 @@ acpi_ev_release_global_lock (
*
******************************************************************************/
-void
-acpi_ev_terminate (
- void)
+void acpi_ev_terminate(void)
{
- acpi_native_uint i;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_terminate");
+ acpi_native_uint i;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_terminate");
if (acpi_gbl_events_initialized) {
/*
@@ -580,38 +540,39 @@ acpi_ev_terminate (
/* Disable all fixed events */
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
- status = acpi_disable_event ((u32) i, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not disable fixed event %d\n", (u32) i));
+ status = acpi_disable_event((u32) i, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not disable fixed event %d\n",
+ (u32) i));
}
}
/* Disable all GPEs in all GPE blocks */
- status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
/* Remove SCI handler */
- status = acpi_ev_remove_sci_handler ();
+ status = acpi_ev_remove_sci_handler();
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not remove SCI handler\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not remove SCI handler\n"));
}
}
/* Deallocate all handler objects installed within GPE info structs */
- status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers);
/* Return to original mode if necessary */
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
- status = acpi_disable ();
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_disable failed\n"));
+ status = acpi_disable();
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "acpi_disable failed\n"));
}
}
return_VOID;
}
-
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index a1d7276c5742..84fad082d80d 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -41,39 +41,30 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evregion")
-
+ACPI_MODULE_NAME("evregion")
#define ACPI_NUM_DEFAULT_SPACES 4
-
-static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE};
+static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
/* Local prototypes */
static acpi_status
-acpi_ev_reg_run (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
static acpi_status
-acpi_ev_install_handler (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
-
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
/*******************************************************************************
*
@@ -87,19 +78,16 @@ acpi_ev_install_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_install_region_handlers (
- void) {
- acpi_status status;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
+acpi_status acpi_ev_install_region_handlers(void)
+{
+ acpi_status status;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ev_install_region_handlers");
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -121,9 +109,11 @@ acpi_ev_install_region_handlers (
* Similar for AE_SAME_HANDLER.
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
- status = acpi_ev_install_space_handler (acpi_gbl_root_node,
- acpi_gbl_default_address_spaces[i],
- ACPI_DEFAULT_HANDLER, NULL, NULL);
+ status = acpi_ev_install_space_handler(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i],
+ ACPI_DEFAULT_HANDLER,
+ NULL, NULL);
switch (status) {
case AE_OK:
case AE_SAME_HANDLER:
@@ -140,12 +130,11 @@ acpi_ev_install_region_handlers (
}
}
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_op_regions
@@ -159,20 +148,16 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ev_initialize_op_regions (
- void)
+acpi_status acpi_ev_initialize_op_regions(void)
{
- acpi_status status;
- acpi_native_uint i;
-
+ acpi_status status;
+ acpi_native_uint i;
- ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
+ ACPI_FUNCTION_TRACE("ev_initialize_op_regions");
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -182,15 +167,15 @@ acpi_ev_initialize_op_regions (
/* TBD: Make sure handler is the DEFAULT handler, otherwise
* _REG will have already been run.
*/
- status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
- acpi_gbl_default_address_spaces[i]);
+ status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i]);
}
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_method
@@ -205,26 +190,22 @@ acpi_ev_initialize_op_regions (
******************************************************************************/
acpi_status
-acpi_ev_execute_reg_method (
- union acpi_operand_object *region_obj,
- u32 function)
+acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[3];
- union acpi_operand_object *region_obj2;
- acpi_status status;
-
+ struct acpi_parameter_info info;
+ union acpi_operand_object *params[3];
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ev_execute_reg_method");
+ ACPI_FUNCTION_TRACE("ev_execute_reg_method");
-
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
if (region_obj2->extra.method_REG == NULL) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -237,12 +218,12 @@ acpi_ev_execute_reg_method (
* 0 for disconnecting the handler
* Passed as a parameter
*/
- params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[0]) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[1]) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -260,19 +241,18 @@ acpi_ev_execute_reg_method (
/* Execute the method, no return value */
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
- ACPI_TYPE_METHOD, info.node, NULL));
- status = acpi_ns_evaluate_by_handle (&info);
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_METHOD, info.node, NULL));
+ status = acpi_ns_evaluate_by_handle(&info);
- acpi_ut_remove_reference (params[1]);
+ acpi_ut_remove_reference(params[1]);
-cleanup:
- acpi_ut_remove_reference (params[0]);
+ cleanup:
+ acpi_ut_remove_reference(params[0]);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_address_space_dispatch
@@ -291,40 +271,38 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ev_address_space_dispatch (
- union acpi_operand_object *region_obj,
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- void *value)
+acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ u32 function,
+ acpi_physical_address address,
+ u32 bit_width, void *value)
{
- acpi_status status;
- acpi_status status2;
- acpi_adr_space_handler handler;
- acpi_adr_space_setup region_setup;
- union acpi_operand_object *handler_desc;
- union acpi_operand_object *region_obj2;
- void *region_context = NULL;
+ acpi_status status;
+ acpi_status status2;
+ acpi_adr_space_handler handler;
+ acpi_adr_space_setup region_setup;
+ union acpi_operand_object *handler_desc;
+ union acpi_operand_object *region_obj2;
+ void *region_context = NULL;
+ ACPI_FUNCTION_TRACE("ev_address_space_dispatch");
- ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");
-
-
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Ensure that there is a handler associated with this region */
handler_desc = region_obj->region.handler;
if (!handler_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No handler for Region [%4.4s] (%p) [%s]\n",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
-
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No handler for Region [%4.4s] (%p) [%s]\n",
+ acpi_ut_get_node_name(region_obj->region.
+ node), region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
+
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -339,10 +317,13 @@ acpi_ev_address_space_dispatch (
if (!region_setup) {
/* No initialization routine, exit with error */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No init routine for region(%p) [%s]\n",
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No init routine for region(%p) [%s]\n",
+ region_obj,
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
@@ -350,25 +331,29 @@ acpi_ev_address_space_dispatch (
* setup will potentially execute control methods
* (e.g., _REG method for this region)
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
- handler_desc->address_space.context, &region_context);
+ status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
+ handler_desc->address_space.context,
+ &region_context);
/* Re-enter the interpreter */
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
/* Check for failure of the Region Setup */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region Init: %s [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
+ return_ACPI_STATUS(status);
}
/*
@@ -380,14 +365,14 @@ acpi_ev_address_space_dispatch (
if (region_obj2->extra.region_context) {
/* The handler for this region was already installed */
- ACPI_MEM_FREE (region_context);
- }
- else {
+ ACPI_MEM_FREE(region_context);
+ } else {
/*
* Save the returned context for use in all accesses to
* this particular region
*/
- region_obj2->extra.region_context = region_context;
+ region_obj2->extra.region_context =
+ region_context;
}
}
}
@@ -396,13 +381,16 @@ acpi_ev_address_space_dispatch (
handler = handler_desc->address_space.handler;
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
- &region_obj->region.handler->address_space, handler,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ &region_obj->region.handler->address_space, handler,
+ ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
- if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+ if (!
+ (handler_desc->address_space.
+ hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
@@ -413,31 +401,33 @@ acpi_ev_address_space_dispatch (
/* Call the handler */
- status = handler (function, address, bit_width, value,
+ status = handler(function, address, bit_width, value,
handler_desc->address_space.context,
region_obj2->extra.region_context);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
- acpi_ut_get_region_name (region_obj->region.space_id),
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Handler for [%s] returned %s\n",
+ acpi_ut_get_region_name(region_obj->region.
+ space_id),
+ acpi_format_exception(status)));
}
- if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+ if (!
+ (handler_desc->address_space.
+ hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_detach_region
@@ -453,23 +443,20 @@ acpi_ev_address_space_dispatch (
******************************************************************************/
void
-acpi_ev_detach_region(
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_detach_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object **last_obj_ptr;
- acpi_adr_space_setup region_setup;
- void **region_context;
- union acpi_operand_object *region_obj2;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_detach_region");
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object **last_obj_ptr;
+ acpi_adr_space_setup region_setup;
+ void **region_context;
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_detach_region");
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_VOID;
}
@@ -493,34 +480,39 @@ acpi_ev_detach_region(
/* Is this the correct Region? */
if (obj_desc == region_obj) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Removing Region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Removing Region %p from address handler %p\n",
+ region_obj, handler_obj));
/* This is it, remove it from the handler's list */
*last_obj_ptr = obj_desc->region.next;
- obj_desc->region.next = NULL; /* Must clear field */
+ obj_desc->region.next = NULL; /* Must clear field */
if (acpi_ns_is_locked) {
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Now stop region accesses by executing the _REG method */
- status = acpi_ev_execute_reg_method (region_obj, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ status = acpi_ev_execute_reg_method(region_obj, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s from region _REG, [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name
+ (region_obj->region.
+ space_id)));
}
if (acpi_ns_is_locked) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
@@ -528,15 +520,20 @@ acpi_ev_detach_region(
/* Call the setup handler with the deactivate notification */
region_setup = handler_obj->address_space.setup;
- status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
- handler_obj->address_space.context, region_context);
+ status =
+ region_setup(region_obj, ACPI_REGION_DEACTIVATE,
+ handler_obj->address_space.context,
+ region_context);
/* Init routine may fail, Just ignore errors */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s from region init, [%s]\n",
+ acpi_format_exception(status),
+ acpi_ut_get_region_name
+ (region_obj->region.
+ space_id)));
}
region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
@@ -552,7 +549,7 @@ acpi_ev_detach_region(
* this better be the region's handler
*/
region_obj->region.handler = NULL;
- acpi_ut_remove_reference (handler_obj);
+ acpi_ut_remove_reference(handler_obj);
return_VOID;
}
@@ -565,14 +562,13 @@ acpi_ev_detach_region(
/* If we get here, the region was not in the handler's region list */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Cannot remove region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Cannot remove region %p from address handler %p\n",
+ region_obj, handler_obj));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_attach_region
@@ -589,20 +585,19 @@ acpi_ev_detach_region(
******************************************************************************/
acpi_status
-acpi_ev_attach_region (
- union acpi_operand_object *handler_obj,
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_attach_region(union acpi_operand_object *handler_obj,
+ union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked)
{
- ACPI_FUNCTION_TRACE ("ev_attach_region");
-
+ ACPI_FUNCTION_TRACE("ev_attach_region");
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Adding Region [%4.4s] %p to address handler %p [%s]\n",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, handler_obj,
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Adding Region [%4.4s] %p to address handler %p [%s]\n",
+ acpi_ut_get_node_name(region_obj->region.node),
+ region_obj, handler_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
/* Link this region to the front of the handler's list */
@@ -612,16 +607,15 @@ acpi_ev_attach_region (
/* Install the region's handler */
if (region_obj->region.handler) {
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
region_obj->region.handler = handler_obj;
- acpi_ut_add_reference (handler_obj);
+ acpi_ut_add_reference(handler_obj);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_handler
@@ -640,23 +634,18 @@ acpi_ev_attach_region (
******************************************************************************/
static acpi_status
-acpi_ev_install_handler (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *next_handler_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *next_handler_obj;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ev_install_handler");
- ACPI_FUNCTION_NAME ("ev_install_handler");
-
-
- handler_obj = (union acpi_operand_object *) context;
+ handler_obj = (union acpi_operand_object *)context;
/* Parameter validation */
@@ -666,7 +655,7 @@ acpi_ev_install_handler (
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
@@ -676,14 +665,13 @@ acpi_ev_install_handler (
* that are allowed to have address space handlers
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
- (node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
@@ -692,18 +680,22 @@ acpi_ev_install_handler (
/* Devices are handled different than regions */
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) {
/* Check if this Device already has a handler for this address space */
next_handler_obj = obj_desc->device.handler;
while (next_handler_obj) {
/* Found a handler, is it for the same address space? */
- if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) handler %p\n",
- acpi_ut_get_region_name (handler_obj->address_space.space_id),
- obj_desc, next_handler_obj, handler_obj));
+ if (next_handler_obj->address_space.space_id ==
+ handler_obj->address_space.space_id) {
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) handler %p\n",
+ acpi_ut_get_region_name
+ (handler_obj->address_space.
+ space_id), obj_desc,
+ next_handler_obj,
+ handler_obj));
/*
* Since the object we found it on was a device, then it
@@ -744,15 +736,14 @@ acpi_ev_install_handler (
*
* First disconnect region for any previous handler (if any)
*/
- acpi_ev_detach_region (obj_desc, FALSE);
+ acpi_ev_detach_region(obj_desc, FALSE);
/* Connect the region to the new handler */
- status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
+ status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_space_handler
@@ -771,32 +762,27 @@ acpi_ev_install_handler (
******************************************************************************/
acpi_status
-acpi_ev_install_space_handler (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context)
+acpi_ev_install_space_handler(struct acpi_namespace_node * node,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj;
- acpi_status status;
- acpi_object_type type;
- u16 flags = 0;
-
-
- ACPI_FUNCTION_TRACE ("ev_install_space_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ acpi_status status;
+ acpi_object_type type;
+ u16 flags = 0;
+ ACPI_FUNCTION_TRACE("ev_install_space_handler");
/*
* This registration is valid for only the types below
* and the root. This is where the default handlers
* get placed.
*/
- if ((node->type != ACPI_TYPE_DEVICE) &&
- (node->type != ACPI_TYPE_PROCESSOR) &&
- (node->type != ACPI_TYPE_THERMAL) &&
- (node != acpi_gbl_root_node)) {
+ if ((node->type != ACPI_TYPE_DEVICE) &&
+ (node->type != ACPI_TYPE_PROCESSOR) &&
+ (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
@@ -807,32 +793,32 @@ acpi_ev_install_space_handler (
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
handler = acpi_ex_system_memory_space_handler;
- setup = acpi_ev_system_memory_region_setup;
+ setup = acpi_ev_system_memory_region_setup;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
handler = acpi_ex_system_io_space_handler;
- setup = acpi_ev_io_space_region_setup;
+ setup = acpi_ev_io_space_region_setup;
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
handler = acpi_ex_pci_config_space_handler;
- setup = acpi_ev_pci_config_region_setup;
+ setup = acpi_ev_pci_config_region_setup;
break;
case ACPI_ADR_SPACE_CMOS:
handler = acpi_ex_cmos_space_handler;
- setup = acpi_ev_cmos_region_setup;
+ setup = acpi_ev_cmos_region_setup;
break;
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
handler = acpi_ex_pci_bar_space_handler;
- setup = acpi_ev_pci_bar_region_setup;
+ setup = acpi_ev_pci_bar_region_setup;
break;
case ACPI_ADR_SPACE_DATA_TABLE:
handler = acpi_ex_data_table_space_handler;
- setup = NULL;
+ setup = NULL;
break;
default:
@@ -849,7 +835,7 @@ acpi_ev_install_space_handler (
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/*
* The attached device object already exists.
@@ -863,7 +849,8 @@ acpi_ev_install_space_handler (
/* Same space_id indicates a handler already installed */
if (handler_obj->address_space.space_id == space_id) {
- if (handler_obj->address_space.handler == handler) {
+ if (handler_obj->address_space.handler ==
+ handler) {
/*
* It is (relatively) OK to attempt to install the SAME
* handler twice. This can easily happen
@@ -871,8 +858,7 @@ acpi_ev_install_space_handler (
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
- }
- else {
+ } else {
/* A handler is already installed */
status = AE_ALREADY_EXISTS;
@@ -884,21 +870,20 @@ acpi_ev_install_space_handler (
handler_obj = handler_obj->address_space.next;
}
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Creating object on Device %p while installing handler\n", node));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Creating object on Device %p while installing handler\n",
+ node));
/* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
- }
- else {
+ } else {
type = node->type;
}
- obj_desc = acpi_ut_create_internal_object (type);
+ obj_desc = acpi_ut_create_internal_object(type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -910,21 +895,21 @@ acpi_ev_install_space_handler (
/* Attach the new object to the Node */
- status = acpi_ns_attach_object (node, obj_desc, type);
+ status = acpi_ns_attach_object(node, obj_desc, type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
- acpi_ut_get_region_name (space_id), space_id,
- acpi_ut_get_node_name (node), node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ acpi_ut_get_region_name(space_id), space_id,
+ acpi_ut_get_node_name(node), node, obj_desc));
/*
* Install the handler
@@ -933,7 +918,8 @@ acpi_ev_install_space_handler (
* Just allocate the object for the handler and link it
* into the list.
*/
- handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+ handler_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -941,17 +927,17 @@ acpi_ev_install_space_handler (
/* Init handler obj */
- handler_obj->address_space.space_id = (u8) space_id;
- handler_obj->address_space.hflags = flags;
+ handler_obj->address_space.space_id = (u8) space_id;
+ handler_obj->address_space.hflags = flags;
handler_obj->address_space.region_list = NULL;
- handler_obj->address_space.node = node;
- handler_obj->address_space.handler = handler;
- handler_obj->address_space.context = context;
- handler_obj->address_space.setup = setup;
+ handler_obj->address_space.node = node;
+ handler_obj->address_space.handler = handler;
+ handler_obj->address_space.context = context;
+ handler_obj->address_space.setup = setup;
/* Install at head of Device.address_space list */
- handler_obj->address_space.next = obj_desc->device.handler;
+ handler_obj->address_space.next = obj_desc->device.handler;
/*
* The Device object is the first reference on the handler_obj.
@@ -971,15 +957,15 @@ acpi_ev_install_space_handler (
* In either case, back up and search down the remainder
* of the branch
*/
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
- handler_obj, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK,
+ acpi_ev_install_handler, handler_obj,
+ NULL);
-unlock_and_exit:
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_methods
@@ -995,15 +981,12 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ev_execute_reg_methods (
- struct acpi_namespace_node *node,
- acpi_adr_space_type space_id)
+acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
+ acpi_adr_space_type space_id)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_execute_reg_methods");
/*
* Run all _REG methods for all Operation Regions for this
@@ -1012,14 +995,13 @@ acpi_ev_execute_reg_methods (
* must be installed for all regions of this Space ID before we
* can run any _REG methods)
*/
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
- &space_id, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
+ &space_id, NULL);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_reg_run
@@ -1031,23 +1013,19 @@ acpi_ev_execute_reg_methods (
******************************************************************************/
static acpi_status
-acpi_ev_reg_run (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_adr_space_type space_id;
- acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_adr_space_type space_id;
+ acpi_status status;
-
- space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
+ space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context);
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
@@ -1056,14 +1034,13 @@ acpi_ev_reg_run (
* We only care about regions.and objects
* that are allowed to have address space handlers
*/
- if ((node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
@@ -1080,7 +1057,6 @@ acpi_ev_reg_run (
return (AE_OK);
}
- status = acpi_ev_execute_reg_method (obj_desc, 1);
+ status = acpi_ev_execute_reg_method(obj_desc, 1);
return (status);
}
-
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 95bc09c73a6a..a1bd2da27c45 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -41,14 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evrgnini")
-
+ACPI_MODULE_NAME("evrgnini")
/*******************************************************************************
*
@@ -64,34 +62,31 @@
* DESCRIPTION: Setup a system_memory operation region
*
******************************************************************************/
-
acpi_status
-acpi_ev_system_memory_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_system_memory_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- union acpi_operand_object *region_desc = (union acpi_operand_object *) handle;
- struct acpi_mem_space_context *local_region_context;
-
-
- ACPI_FUNCTION_TRACE ("ev_system_memory_region_setup");
+ union acpi_operand_object *region_desc =
+ (union acpi_operand_object *)handle;
+ struct acpi_mem_space_context *local_region_context;
+ ACPI_FUNCTION_TRACE("ev_system_memory_region_setup");
if (function == ACPI_REGION_DEACTIVATE) {
if (*region_context) {
- ACPI_MEM_FREE (*region_context);
+ ACPI_MEM_FREE(*region_context);
*region_context = NULL;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Create a new context */
- local_region_context = ACPI_MEM_CALLOCATE (sizeof (struct acpi_mem_space_context));
+ local_region_context =
+ ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context));
if (!(local_region_context)) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the region length and address for use in the handler */
@@ -100,10 +95,9 @@ acpi_ev_system_memory_region_setup (
local_region_context->address = region_desc->region.address;
*region_context = local_region_context;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_io_space_region_setup
@@ -120,26 +114,21 @@ acpi_ev_system_memory_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_io_space_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_io_space_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE ("ev_io_space_region_setup");
-
+ ACPI_FUNCTION_TRACE("ev_io_space_region_setup");
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
- }
- else {
+ } else {
*region_context = handler_context;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_config_region_setup
@@ -158,24 +147,21 @@ acpi_ev_io_space_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_pci_config_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_pci_config_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- acpi_status status = AE_OK;
- acpi_integer pci_value;
- struct acpi_pci_id *pci_id = *region_context;
- union acpi_operand_object *handler_obj;
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *pci_root_node;
- union acpi_operand_object *region_obj = (union acpi_operand_object *) handle;
- struct acpi_device_id object_hID;
-
-
- ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup");
-
+ acpi_status status = AE_OK;
+ acpi_integer pci_value;
+ struct acpi_pci_id *pci_id = *region_context;
+ union acpi_operand_object *handler_obj;
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *pci_root_node;
+ union acpi_operand_object *region_obj =
+ (union acpi_operand_object *)handle;
+ struct acpi_device_id object_hID;
+
+ ACPI_FUNCTION_TRACE("ev_pci_config_region_setup");
handler_obj = region_obj->region.handler;
if (!handler_obj) {
@@ -183,20 +169,21 @@ acpi_ev_pci_config_region_setup (
* No installed handler. This shouldn't happen because the dispatch
* routine checks before we get here, but we check again just in case.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Attempting to init a region %p, with no handler\n", region_obj));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Attempting to init a region %p, with no handler\n",
+ region_obj));
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
*region_context = NULL;
if (function == ACPI_REGION_DEACTIVATE) {
if (pci_id) {
- ACPI_MEM_FREE (pci_id);
+ ACPI_MEM_FREE(pci_id);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- parent_node = acpi_ns_get_parent_node (region_obj->region.node);
+ parent_node = acpi_ns_get_parent_node(region_obj->region.node);
/*
* Get the _SEG and _BBN values from the device upon which the handler
@@ -216,18 +203,28 @@ acpi_ev_pci_config_region_setup (
pci_root_node = parent_node;
while (pci_root_node != acpi_gbl_root_node) {
- status = acpi_ut_execute_HID (pci_root_node, &object_hID);
- if (ACPI_SUCCESS (status)) {
- /* Got a valid _HID, check if this is a PCI root */
-
- if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING,
- sizeof (PCI_ROOT_HID_STRING)))) {
+ status =
+ acpi_ut_execute_HID(pci_root_node, &object_hID);
+ if (ACPI_SUCCESS(status)) {
+ /*
+ * Got a valid _HID string, check if this is a PCI root.
+ * New for ACPI 3.0: check for a PCI Express root also.
+ */
+ if (!
+ (ACPI_STRNCMP
+ (object_hID.value, PCI_ROOT_HID_STRING,
+ sizeof(PCI_ROOT_HID_STRING))
+ ||
+ !(ACPI_STRNCMP
+ (object_hID.value,
+ PCI_EXPRESS_ROOT_HID_STRING,
+ sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
+ {
/* Install a handler for this PCI root bridge */
- status = acpi_install_address_space_handler ((acpi_handle) pci_root_node,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
if (status == AE_SAME_HANDLER) {
/*
* It is OK if the handler is already installed on the root
@@ -235,23 +232,19 @@ acpi_ev_pci_config_region_setup (
* new PCI_Config operation region, however.
*/
status = AE_OK;
- }
- else {
- ACPI_REPORT_ERROR ((
- "Could not install pci_config handler for Root Bridge %4.4s, %s\n",
- acpi_ut_get_node_name (pci_root_node), acpi_format_exception (status)));
+ } else {
+ ACPI_REPORT_ERROR(("Could not install pci_config handler for Root Bridge %4.4s, %s\n", acpi_ut_get_node_name(pci_root_node), acpi_format_exception(status)));
}
}
break;
}
}
- pci_root_node = acpi_ns_get_parent_node (pci_root_node);
+ pci_root_node = acpi_ns_get_parent_node(pci_root_node);
}
/* PCI root bridge not found, use namespace root node */
- }
- else {
+ } else {
pci_root_node = handler_obj->address_space.node;
}
@@ -260,14 +253,14 @@ acpi_ev_pci_config_region_setup (
* (install_address_space_handler could have initialized it)
*/
if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Region is still not initialized. Create a new context */
- pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id));
+ pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id));
if (!pci_id) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -279,40 +272,45 @@ acpi_ev_pci_config_region_setup (
* Get the PCI device and function numbers from the _ADR object
* contained in the parent's scope.
*/
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node,
+ &pci_value);
/*
* The default is zero, and since the allocation above zeroed
* the data, just do nothing on failure.
*/
- if (ACPI_SUCCESS (status)) {
- pci_id->device = ACPI_HIWORD (ACPI_LODWORD (pci_value));
- pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value));
+ if (ACPI_SUCCESS(status)) {
+ pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
+ pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
}
/* The PCI segment number comes from the _SEG method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value);
- if (ACPI_SUCCESS (status)) {
- pci_id->segment = ACPI_LOWORD (pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node,
+ &pci_value);
+ if (ACPI_SUCCESS(status)) {
+ pci_id->segment = ACPI_LOWORD(pci_value);
}
/* The PCI bus number comes from the _BBN method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value);
- if (ACPI_SUCCESS (status)) {
- pci_id->bus = ACPI_LOWORD (pci_value);
+ status =
+ acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node,
+ &pci_value);
+ if (ACPI_SUCCESS(status)) {
+ pci_id->bus = ACPI_LOWORD(pci_value);
}
/* Complete this device's pci_id */
- acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id);
+ acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);
*region_context = pci_id;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_pci_bar_region_setup
@@ -331,19 +329,15 @@ acpi_ev_pci_config_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_pci_bar_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_pci_bar_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE ("ev_pci_bar_region_setup");
-
+ ACPI_FUNCTION_TRACE("ev_pci_bar_region_setup");
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_cmos_region_setup
@@ -362,19 +356,15 @@ acpi_ev_pci_bar_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_cmos_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_cmos_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE ("ev_cmos_region_setup");
-
+ ACPI_FUNCTION_TRACE("ev_cmos_region_setup");
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_default_region_setup
@@ -391,26 +381,21 @@ acpi_ev_cmos_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_default_region_setup (
- acpi_handle handle,
- u32 function,
- void *handler_context,
- void **region_context)
+acpi_ev_default_region_setup(acpi_handle handle,
+ u32 function,
+ void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE ("ev_default_region_setup");
-
+ ACPI_FUNCTION_TRACE("ev_default_region_setup");
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
- }
- else {
+ } else {
*region_context = handler_context;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_region
@@ -434,37 +419,34 @@ acpi_ev_default_region_setup (
******************************************************************************/
acpi_status
-acpi_ev_initialize_region (
- union acpi_operand_object *region_obj,
- u8 acpi_ns_locked)
+acpi_ev_initialize_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_locked)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *obj_desc;
- acpi_adr_space_type space_id;
- struct acpi_namespace_node *node;
- acpi_status status;
- struct acpi_namespace_node *method_node;
- acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
- union acpi_operand_object *region_obj2;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ev_initialize_region", acpi_ns_locked);
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *obj_desc;
+ acpi_adr_space_type space_id;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ struct acpi_namespace_node *method_node;
+ acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
+ union acpi_operand_object *region_obj2;
+ ACPI_FUNCTION_TRACE_U32("ev_initialize_region", acpi_ns_locked);
if (!region_obj) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- node = acpi_ns_get_parent_node (region_obj->region.node);
+ node = acpi_ns_get_parent_node(region_obj->region.node);
space_id = region_obj->region.space_id;
/* Setup defaults */
@@ -476,9 +458,9 @@ acpi_ev_initialize_region (
/* Find any "_REG" method associated with this region definition */
- status = acpi_ns_search_node (*reg_name_ptr, node,
- ACPI_TYPE_METHOD, &method_node);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_search_node(*reg_name_ptr, node,
+ ACPI_TYPE_METHOD, &method_node);
+ if (ACPI_SUCCESS(status)) {
/*
* The _REG method is optional and there can be only one per region
* definition. This will be executed when the handler is attached
@@ -495,7 +477,7 @@ acpi_ev_initialize_region (
/* Check to see if a handler exists */
handler_obj = NULL;
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* Can only be a handler if the object exists */
@@ -523,37 +505,50 @@ acpi_ev_initialize_region (
while (handler_obj) {
/* Is this handler of the correct type? */
- if (handler_obj->address_space.space_id == space_id) {
+ if (handler_obj->address_space.space_id ==
+ space_id) {
/* Found correct handler */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler %p for region %p in obj %p\n",
- handler_obj, region_obj, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler %p for region %p in obj %p\n",
+ handler_obj,
+ region_obj,
+ obj_desc));
- status = acpi_ev_attach_region (handler_obj, region_obj,
- acpi_ns_locked);
+ status =
+ acpi_ev_attach_region(handler_obj,
+ region_obj,
+ acpi_ns_locked);
/*
* Tell all users that this region is usable by running the _REG
* method
*/
if (acpi_ns_locked) {
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_release_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS
+ (status);
}
}
- status = acpi_ev_execute_reg_method (region_obj, 1);
+ status =
+ acpi_ev_execute_reg_method
+ (region_obj, 1);
if (acpi_ns_locked) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_acquire_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS
+ (status);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Try next handler in the list */
@@ -566,15 +561,15 @@ acpi_ev_initialize_region (
* This node does not have the handler we need;
* Pop up one level
*/
- node = acpi_ns_get_parent_node (node);
+ node = acpi_ns_get_parent_node(node);
}
/* If we get here, there is no handler for this region */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "No handler for region_type %s(%X) (region_obj %p)\n",
- acpi_ut_get_region_name (space_id), space_id, region_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "No handler for region_type %s(%X) (region_obj %p)\n",
+ acpi_ut_get_region_name(space_id), space_id,
+ region_obj));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
-
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index f3123c26ae98..141835977002 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -45,16 +45,11 @@
#include <acpi/acpi.h>
#include <acpi/acevents.h>
-
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evsci")
+ACPI_MODULE_NAME("evsci")
/* Local prototypes */
-
-static u32 ACPI_SYSTEM_XFACE
-acpi_ev_sci_xrupt_handler (
- void *context);
-
+static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
/*******************************************************************************
*
@@ -69,17 +64,13 @@ acpi_ev_sci_xrupt_handler (
*
******************************************************************************/
-static u32 ACPI_SYSTEM_XFACE
-acpi_ev_sci_xrupt_handler (
- void *context)
+static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
{
- struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
- u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
-
+ struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
+ u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
-
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
@@ -89,18 +80,17 @@ acpi_ev_sci_xrupt_handler (
* Fixed Events:
* Check for and dispatch any Fixed Events that have occurred
*/
- interrupt_handled |= acpi_ev_fixed_event_detect ();
+ interrupt_handled |= acpi_ev_fixed_event_detect();
/*
* General Purpose Events:
* Check for and dispatch any GPEs that have occurred
*/
- interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
+ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE (interrupt_handled);
+ return_VALUE(interrupt_handled);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_xrupt_handler
@@ -113,17 +103,13 @@ acpi_ev_sci_xrupt_handler (
*
******************************************************************************/
-u32 ACPI_SYSTEM_XFACE
-acpi_ev_gpe_xrupt_handler (
- void *context)
+u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
{
- struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
- u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
-
+ struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
+ u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
-
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
@@ -133,12 +119,11 @@ acpi_ev_gpe_xrupt_handler (
* GPEs:
* Check for and dispatch any GPEs that have occurred
*/
- interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
+ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
- return_VALUE (interrupt_handled);
+ return_VALUE(interrupt_handled);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_install_sci_handler
@@ -151,22 +136,18 @@ acpi_ev_gpe_xrupt_handler (
*
******************************************************************************/
-u32
-acpi_ev_install_sci_handler (
- void)
+u32 acpi_ev_install_sci_handler(void)
{
- u32 status = AE_OK;
-
+ u32 status = AE_OK;
- ACPI_FUNCTION_TRACE ("ev_install_sci_handler");
+ ACPI_FUNCTION_TRACE("ev_install_sci_handler");
-
- status = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
- acpi_ev_sci_xrupt_handler, acpi_gbl_gpe_xrupt_list_head);
- return_ACPI_STATUS (status);
+ status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
+ acpi_ev_sci_xrupt_handler,
+ acpi_gbl_gpe_xrupt_list_head);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_remove_sci_handler
@@ -186,22 +167,16 @@ acpi_ev_install_sci_handler (
*
******************************************************************************/
-acpi_status
-acpi_ev_remove_sci_handler (
- void)
+acpi_status acpi_ev_remove_sci_handler(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ev_remove_sci_handler");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_remove_sci_handler");
/* Just let the OS remove the handler and disable the level */
- status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
- acpi_ev_sci_xrupt_handler);
+ status = acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
+ acpi_ev_sci_xrupt_handler);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index 4092d47f6758..43b33d19cdf9 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -49,8 +49,7 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxface")
-
+ACPI_MODULE_NAME("evxface")
/*******************************************************************************
*
@@ -64,21 +63,16 @@
* DESCRIPTION: Saves the pointer to the handler function
*
******************************************************************************/
-
#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_install_exception_handler (
- acpi_exception_handler handler)
+acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
{
- acpi_status status;
-
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("acpi_install_exception_handler");
+ ACPI_FUNCTION_TRACE("acpi_install_exception_handler");
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
@@ -92,12 +86,11 @@ acpi_install_exception_handler (
acpi_gbl_exception_handler = handler;
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -116,26 +109,22 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_install_fixed_event_handler (
- u32 event,
- acpi_event_handler handler,
- void *context)
+acpi_install_fixed_event_handler(u32 event,
+ acpi_event_handler handler, void *context)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_fixed_event_handler");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler");
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
@@ -150,29 +139,29 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
- status = acpi_clear_event (event);
+ status = acpi_clear_event(event);
if (ACPI_SUCCESS(status))
- status = acpi_enable_event (event, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
+ status = acpi_enable_event(event, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Could not enable fixed event.\n"));
/* Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Enabled fixed event %X, Handler=%p\n", event, handler));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Enabled fixed event %X, Handler=%p\n", event,
+ handler));
}
-
-cleanup:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ cleanup:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_fixed_event_handler);
+EXPORT_SYMBOL(acpi_install_fixed_event_handler);
/*******************************************************************************
*
@@ -188,49 +177,45 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler);
******************************************************************************/
acpi_status
-acpi_remove_fixed_event_handler (
- u32 event,
- acpi_event_handler handler)
+acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_fixed_event_handler");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler");
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Disable the event before removing the handler */
- status = acpi_disable_event (event, 0);
+ status = acpi_disable_event(event, 0);
/* Always Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
- "Could not write to fixed event enable register.\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Could not write to fixed event enable register.\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X.\n",
+ event));
}
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
+EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
/*******************************************************************************
*
@@ -251,37 +236,32 @@ EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
******************************************************************************/
acpi_status
-acpi_install_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler,
- void *context)
+acpi_install_notify_handler(acpi_handle device,
+ u32 handler_type,
+ acpi_notify_handler handler, void *context)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *notify_obj;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_notify_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *notify_obj;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_notify_handler");
/* Parameter validation */
- if ((!device) ||
- (!handler) ||
- (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device) ||
+ (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -297,21 +277,21 @@ acpi_install_notify_handler (
/* Make sure the handler is not already installed */
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
- acpi_gbl_system_notify.handler) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- acpi_gbl_device_notify.handler)) {
+ acpi_gbl_system_notify.handler) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ acpi_gbl_device_notify.handler)) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
if (handler_type & ACPI_SYSTEM_NOTIFY) {
- acpi_gbl_system_notify.node = node;
+ acpi_gbl_system_notify.node = node;
acpi_gbl_system_notify.handler = handler;
acpi_gbl_system_notify.context = context;
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
- acpi_gbl_device_notify.node = node;
+ acpi_gbl_device_notify.node = node;
acpi_gbl_device_notify.handler = handler;
acpi_gbl_device_notify.context = context;
}
@@ -327,29 +307,28 @@ acpi_install_notify_handler (
else {
/* Notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
+ if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE;
goto unlock_and_exit;
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* Object exists - make sure there's no handler */
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
- obj_desc->common_notify.system_notify) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- obj_desc->common_notify.device_notify)) {
+ obj_desc->common_notify.system_notify) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ obj_desc->common_notify.device_notify)) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Create a new object */
- obj_desc = acpi_ut_create_internal_object (node->type);
+ obj_desc = acpi_ut_create_internal_object(node->type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -357,25 +336,27 @@ acpi_install_notify_handler (
/* Attach new object to the Node */
- status = acpi_ns_attach_object (device, obj_desc, node->type);
+ status =
+ acpi_ns_attach_object(device, obj_desc, node->type);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- if (ACPI_FAILURE (status)) {
+ acpi_ut_remove_reference(obj_desc);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
/* Install the handler */
- notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY);
+ notify_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
if (!notify_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- notify_obj->notify.node = node;
+ notify_obj->notify.node = node;
notify_obj->notify.handler = handler;
notify_obj->notify.context = context;
@@ -390,17 +371,16 @@ acpi_install_notify_handler (
if (handler_type == ACPI_ALL_NOTIFY) {
/* Extra ref if installed in both */
- acpi_ut_add_reference (notify_obj);
+ acpi_ut_add_reference(notify_obj);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_notify_handler);
+EXPORT_SYMBOL(acpi_install_notify_handler);
/*******************************************************************************
*
@@ -420,36 +400,31 @@ EXPORT_SYMBOL(acpi_install_notify_handler);
******************************************************************************/
acpi_status
-acpi_remove_notify_handler (
- acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler)
+acpi_remove_notify_handler(acpi_handle device,
+ u32 handler_type, acpi_notify_handler handler)
{
- union acpi_operand_object *notify_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler");
+ union acpi_operand_object *notify_obj;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
/* Parameter validation */
- if ((!device) ||
- (!handler) ||
- (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device) ||
+ (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -458,34 +433,34 @@ acpi_remove_notify_handler (
/* Root Object */
if (device == ACPI_ROOT_OBJECT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Removing notify handler for ROOT object.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Removing notify handler for ROOT object.\n"));
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
- !acpi_gbl_system_notify.handler) ||
- ((handler_type & ACPI_DEVICE_NOTIFY) &&
- !acpi_gbl_device_notify.handler)) {
+ !acpi_gbl_system_notify.handler) ||
+ ((handler_type & ACPI_DEVICE_NOTIFY) &&
+ !acpi_gbl_device_notify.handler)) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
if (handler_type & ACPI_SYSTEM_NOTIFY) {
- acpi_gbl_system_notify.node = NULL;
+ acpi_gbl_system_notify.node = NULL;
acpi_gbl_system_notify.handler = NULL;
acpi_gbl_system_notify.context = NULL;
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
- acpi_gbl_device_notify.node = NULL;
+ acpi_gbl_device_notify.node = NULL;
acpi_gbl_device_notify.handler = NULL;
acpi_gbl_device_notify.context = NULL;
}
@@ -496,14 +471,14 @@ acpi_remove_notify_handler (
else {
/* Notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
+ if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE;
goto unlock_and_exit;
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
@@ -514,53 +489,52 @@ acpi_remove_notify_handler (
if (handler_type & ACPI_SYSTEM_NOTIFY) {
notify_obj = obj_desc->common_notify.system_notify;
if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ (notify_obj->notify.handler != handler)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
obj_desc->common_notify.system_notify = NULL;
- acpi_ut_remove_reference (notify_obj);
+ acpi_ut_remove_reference(notify_obj);
}
if (handler_type & ACPI_DEVICE_NOTIFY) {
notify_obj = obj_desc->common_notify.device_notify;
if ((!notify_obj) ||
- (notify_obj->notify.handler != handler)) {
+ (notify_obj->notify.handler != handler)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
obj_desc->common_notify.device_notify = NULL;
- acpi_ut_remove_reference (notify_obj);
+ acpi_ut_remove_reference(notify_obj);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_notify_handler);
+EXPORT_SYMBOL(acpi_remove_notify_handler);
/*******************************************************************************
*
@@ -581,35 +555,31 @@ EXPORT_SYMBOL(acpi_remove_notify_handler);
******************************************************************************/
acpi_status
-acpi_install_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 type,
- acpi_event_handler address,
- void *context)
+acpi_install_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number,
+ u32 type, acpi_event_handler address, void *context)
{
- struct acpi_gpe_event_info *gpe_event_info;
- struct acpi_handler_info *handler;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
/* Parameter validation */
if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -617,49 +587,49 @@ acpi_install_gpe_handler (
/* Make sure that there isn't a handler there already */
- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
+ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_HANDLER) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
/* Allocate and init handler object */
- handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
+ handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
if (!handler) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- handler->address = address;
- handler->context = context;
+ handler->address = address;
+ handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
/* Disable the GPE before installing the handler */
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Install the handler */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
gpe_event_info->dispatch.handler = handler;
/* Setup up dispatch flags to indicate handler (vs. method) */
- gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
+ gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_handler);
+EXPORT_SYMBOL(acpi_install_gpe_handler);
/*******************************************************************************
*
@@ -677,33 +647,30 @@ EXPORT_SYMBOL(acpi_install_gpe_handler);
******************************************************************************/
acpi_status
-acpi_remove_gpe_handler (
- acpi_handle gpe_device,
- u32 gpe_number,
- acpi_event_handler address)
+acpi_remove_gpe_handler(acpi_handle gpe_device,
+ u32 gpe_number, acpi_event_handler address)
{
- struct acpi_gpe_event_info *gpe_event_info;
- struct acpi_handler_info *handler;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_handler_info *handler;
+ acpi_status status;
+ u32 flags;
+ ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
/* Parameter validation */
if (!address) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -711,7 +678,8 @@ acpi_remove_gpe_handler (
/* Make sure that a handler is indeed installed */
- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
+ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
+ ACPI_GPE_DISPATCH_HANDLER) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
@@ -725,45 +693,44 @@ acpi_remove_gpe_handler (
/* Disable the GPE before removing the handler */
- status = acpi_ev_disable_gpe (gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_disable_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
acpi_os_wait_events_complete(NULL);
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Remove the handler */
- acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
handler = gpe_event_info->dispatch.handler;
/* Restore Method node (if any), set dispatch flags */
gpe_event_info->dispatch.method_node = handler->method_node;
- gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
+ gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
if (handler->method_node) {
gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
}
- acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
/* Now we can free the handler object */
- ACPI_MEM_FREE (handler);
+ ACPI_MEM_FREE(handler);
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_gpe_handler);
+EXPORT_SYMBOL(acpi_remove_gpe_handler);
/*******************************************************************************
*
@@ -779,35 +746,31 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler);
*
******************************************************************************/
-acpi_status
-acpi_acquire_global_lock (
- u16 timeout,
- u32 *handle)
+acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
{
- acpi_status status;
-
+ acpi_status status;
if (!handle) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
return (status);
}
- status = acpi_ev_acquire_global_lock (timeout);
- acpi_ex_exit_interpreter ();
+ status = acpi_ev_acquire_global_lock(timeout);
+ acpi_ex_exit_interpreter();
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
acpi_gbl_global_lock_handle++;
*handle = acpi_gbl_global_lock_handle;
}
return (status);
}
-EXPORT_SYMBOL(acpi_acquire_global_lock);
+EXPORT_SYMBOL(acpi_acquire_global_lock);
/*******************************************************************************
*
@@ -821,19 +784,16 @@ EXPORT_SYMBOL(acpi_acquire_global_lock);
*
******************************************************************************/
-acpi_status
-acpi_release_global_lock (
- u32 handle)
+acpi_status acpi_release_global_lock(u32 handle)
{
- acpi_status status;
-
+ acpi_status status;
if (handle != acpi_gbl_global_lock_handle) {
return (AE_NOT_ACQUIRED);
}
- status = acpi_ev_release_global_lock ();
+ status = acpi_ev_release_global_lock();
return (status);
}
-EXPORT_SYMBOL(acpi_release_global_lock);
+EXPORT_SYMBOL(acpi_release_global_lock);
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index f337dc2cc569..887ff9f28a0d 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -48,8 +48,7 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxfevnt")
-
+ACPI_MODULE_NAME("evxfevnt")
/*******************************************************************************
*
@@ -62,44 +61,39 @@
* DESCRIPTION: Transfers the system into ACPI mode.
*
******************************************************************************/
-
-acpi_status
-acpi_enable (
- void)
+acpi_status acpi_enable(void)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("acpi_enable");
+ ACPI_FUNCTION_TRACE("acpi_enable");
-
- /* Make sure we have the FADT*/
+ /* Make sure we have the FADT */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "No FADT information present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n"));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "System is already in ACPI mode\n"));
+ } else {
/* Transition to ACPI mode */
- status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not transition to ACPI mode.\n"));
- return_ACPI_STATUS (status);
+ status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not transition to ACPI mode.\n"));
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Transition to ACPI mode successful\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Transition to ACPI mode successful\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_disable
@@ -112,43 +106,38 @@ acpi_enable (
*
******************************************************************************/
-acpi_status
-acpi_disable (
- void)
+acpi_status acpi_disable(void)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_disable");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_disable");
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "No FADT information present!\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "System is already in legacy (non-ACPI) mode\n"));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "System is already in legacy (non-ACPI) mode\n"));
+ } else {
/* Transition to LEGACY mode */
- status = acpi_hw_set_mode (ACPI_SYS_MODE_LEGACY);
+ status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not exit ACPI mode to legacy mode"));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not exit ACPI mode to legacy mode"));
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enable_event
@@ -162,52 +151,50 @@ acpi_disable (
*
******************************************************************************/
-acpi_status
-acpi_enable_event (
- u32 event,
- u32 flags)
+acpi_status acpi_enable_event(u32 event, u32 flags)
{
- acpi_status status = AE_OK;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enable_event");
+ acpi_status status = AE_OK;
+ u32 value;
+ ACPI_FUNCTION_TRACE("acpi_enable_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Enable the requested fixed event (by writing a one to the
* enable register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 1, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 1, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Make sure that the hardware responded */
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (value != 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not enable %s event\n", acpi_ut_get_event_name (event)));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not enable %s event\n",
+ acpi_ut_get_event_name(event)));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_event);
+EXPORT_SYMBOL(acpi_enable_event);
/*******************************************************************************
*
@@ -223,40 +210,34 @@ EXPORT_SYMBOL(acpi_enable_event);
*
******************************************************************************/
-acpi_status
-acpi_set_gpe_type (
- acpi_handle gpe_device,
- u32 gpe_number,
- u8 type)
+acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_set_gpe_type");
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Set the new type (will disable GPE if currently enabled) */
- status = acpi_ev_set_gpe_type (gpe_event_info, type);
+ status = acpi_ev_set_gpe_type(gpe_event_info, type);
-unlock_and_exit:
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_gpe_type);
+EXPORT_SYMBOL(acpi_set_gpe_type);
/*******************************************************************************
*
@@ -273,31 +254,25 @@ EXPORT_SYMBOL(acpi_set_gpe_type);
*
******************************************************************************/
-acpi_status
-acpi_enable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_enable_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -305,16 +280,16 @@ acpi_enable_gpe (
/* Perform the enable */
- status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
+ status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_gpe);
+EXPORT_SYMBOL(acpi_enable_gpe);
/*******************************************************************************
*
@@ -331,46 +306,39 @@ EXPORT_SYMBOL(acpi_enable_gpe);
*
******************************************************************************/
-acpi_status
-acpi_disable_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_disable_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ev_disable_gpe (gpe_event_info);
+ status = acpi_ev_disable_gpe(gpe_event_info);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
@@ -384,50 +352,48 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_disable_event (
- u32 event,
- u32 flags)
+acpi_status acpi_disable_event(u32 event, u32 flags)
{
- acpi_status status = AE_OK;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("acpi_disable_event");
+ acpi_status status = AE_OK;
+ u32 value;
+ ACPI_FUNCTION_TRACE("acpi_disable_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Disable the requested fixed event (by writing a zero to the
* enable register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- 0, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, 0, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
- &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ enable_register_id, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (value != 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not disable %s events\n", acpi_ut_get_event_name (event)));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not disable %s events\n",
+ acpi_ut_get_event_name(event)));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_disable_event);
+EXPORT_SYMBOL(acpi_disable_event);
/*******************************************************************************
*
@@ -441,33 +407,30 @@ EXPORT_SYMBOL(acpi_disable_event);
*
******************************************************************************/
-acpi_status
-acpi_clear_event (
- u32 event)
+acpi_status acpi_clear_event(u32 event)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_clear_event");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_clear_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Clear the requested fixed event (By writing a one to the
* status register bit)
*/
- status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
- 1, ACPI_MTX_LOCK);
+ status =
+ acpi_set_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, 1, ACPI_MTX_LOCK);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_clear_event);
+EXPORT_SYMBOL(acpi_clear_event);
/*******************************************************************************
*
@@ -483,46 +446,39 @@ EXPORT_SYMBOL(acpi_clear_event);
*
******************************************************************************/
-acpi_status
-acpi_clear_gpe (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags)
+acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_clear_gpe");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_hw_clear_gpe (gpe_event_info);
+ status = acpi_hw_clear_gpe(gpe_event_info);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -538,36 +494,31 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_get_event_status (
- u32 event,
- acpi_event_status *event_status)
+acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_event_status");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_get_event_status");
if (!event_status) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the status of the requested fixed event */
- status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
- event_status, ACPI_MTX_LOCK);
+ status =
+ acpi_get_register(acpi_gbl_fixed_event_info[event].
+ status_register_id, event_status, ACPI_MTX_LOCK);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_status
@@ -585,31 +536,26 @@ acpi_get_event_status (
******************************************************************************/
acpi_status
-acpi_get_gpe_status (
- acpi_handle gpe_device,
- u32 gpe_number,
- u32 flags,
- acpi_event_status *event_status)
+acpi_get_gpe_status(acpi_handle gpe_device,
+ u32 gpe_number, u32 flags, acpi_event_status * event_status)
{
- acpi_status status = AE_OK;
- struct acpi_gpe_event_info *gpe_event_info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ ACPI_FUNCTION_TRACE("acpi_get_gpe_status");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */
- gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -617,16 +563,15 @@ acpi_get_gpe_status (
/* Obtain status on the requested GPE number */
- status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
+ status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -635,7 +580,7 @@ unlock_and_exit:
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
* gpe_block_address - Address and space_iD
* register_count - Number of GPE register pairs in the block
- * interrupt_level - H/W interrupt for the block
+ * interrupt_number - H/W interrupt for the block
*
* RETURN: Status
*
@@ -644,33 +589,27 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_install_gpe_block (
- acpi_handle gpe_device,
- struct acpi_generic_address *gpe_block_address,
- u32 register_count,
- u32 interrupt_level)
+acpi_install_gpe_block(acpi_handle gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count, u32 interrupt_number)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- struct acpi_gpe_block_info *gpe_block;
-
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ struct acpi_gpe_block_info *gpe_block;
- ACPI_FUNCTION_TRACE ("acpi_install_gpe_block");
+ ACPI_FUNCTION_TRACE("acpi_install_gpe_block");
-
- if ((!gpe_device) ||
- (!gpe_block_address) ||
- (!register_count)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (gpe_device);
+ node = acpi_ns_map_handle_to_node(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -680,31 +619,33 @@ acpi_install_gpe_block (
* For user-installed GPE Block Devices, the gpe_block_base_number
* is always zero
*/
- status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count,
- 0, interrupt_level, &gpe_block);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
+ interrupt_number, &gpe_block);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Get the device_object attached to the node */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, create a new one */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_DEVICE);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE);
+ status =
+ acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
@@ -713,13 +654,12 @@ acpi_install_gpe_block (
obj_desc->device.gpe_block = gpe_block;
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_block);
+EXPORT_SYMBOL(acpi_install_gpe_block);
/*******************************************************************************
*
@@ -733,28 +673,24 @@ EXPORT_SYMBOL(acpi_install_gpe_block);
*
******************************************************************************/
-acpi_status
-acpi_remove_gpe_block (
- acpi_handle gpe_device)
+acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
- struct acpi_namespace_node *node;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_gpe_block");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ ACPI_FUNCTION_TRACE("acpi_remove_gpe_block");
if (!gpe_device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (gpe_device);
+ node = acpi_ns_map_handle_to_node(gpe_device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -762,22 +698,21 @@ acpi_remove_gpe_block (
/* Get the device_object attached to the node */
- obj_desc = acpi_ns_get_attached_object (node);
- if (!obj_desc ||
- !obj_desc->device.gpe_block) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ obj_desc = acpi_ns_get_attached_object(node);
+ if (!obj_desc || !obj_desc->device.gpe_block) {
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Delete the GPE block (but not the device_object) */
- status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
+ if (ACPI_SUCCESS(status)) {
obj_desc->device.gpe_block = NULL;
}
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_remove_gpe_block);
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index d058587b3427..6f28ea2db5ba 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -49,8 +49,7 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evxfregn")
-
+ACPI_MODULE_NAME("evxfregn")
/*******************************************************************************
*
@@ -67,36 +66,31 @@
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
*
******************************************************************************/
-
acpi_status
-acpi_install_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context)
+acpi_install_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup, void *context)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_install_address_space_handler");
/* Parameter validation */
if (!device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -104,21 +98,23 @@ acpi_install_address_space_handler (
/* Install the handler for all Regions for this Space ID */
- status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_install_space_handler(node, space_id, handler, setup,
+ context);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Run all _REG methods for this address space */
- status = acpi_ev_execute_reg_methods (node, space_id);
+ status = acpi_ev_execute_reg_methods(node, space_id);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_address_space_handler);
+EXPORT_SYMBOL(acpi_install_address_space_handler);
/*******************************************************************************
*
@@ -135,36 +131,33 @@ EXPORT_SYMBOL(acpi_install_address_space_handler);
******************************************************************************/
acpi_status
-acpi_remove_address_space_handler (
- acpi_handle device,
- acpi_adr_space_type space_id,
- acpi_adr_space_handler handler)
+acpi_remove_address_space_handler(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *region_obj;
- union acpi_operand_object **last_obj_ptr;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_remove_address_space_handler");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *region_obj;
+ union acpi_operand_object **last_obj_ptr;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler");
/* Parameter validation */
if (!device) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (device);
+ node = acpi_ns_map_handle_to_node(device);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -172,7 +165,7 @@ acpi_remove_address_space_handler (
/* Make sure the internal object exists */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
@@ -188,10 +181,11 @@ acpi_remove_address_space_handler (
if (handler_obj->address_space.space_id == space_id) {
/* Matched space_id, first dereference this in the Regions */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
- handler_obj, handler, acpi_ut_get_region_name (space_id),
- node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Removing address handler %p(%p) for region %s on Device %p(%p)\n",
+ handler_obj, handler,
+ acpi_ut_get_region_name(space_id),
+ node, obj_desc));
region_obj = handler_obj->address_space.region_list;
@@ -205,13 +199,14 @@ acpi_remove_address_space_handler (
* The region is just inaccessible as indicated to
* the _REG method
*/
- acpi_ev_detach_region (region_obj, TRUE);
+ acpi_ev_detach_region(region_obj, TRUE);
/*
* Walk the list: Just grab the head because the
* detach_region removed the previous head.
*/
- region_obj = handler_obj->address_space.region_list;
+ region_obj =
+ handler_obj->address_space.region_list;
}
@@ -221,7 +216,7 @@ acpi_remove_address_space_handler (
/* Now we can delete the handler object */
- acpi_ut_remove_reference (handler_obj);
+ acpi_ut_remove_reference(handler_obj);
goto unlock_and_exit;
}
@@ -233,15 +228,16 @@ acpi_remove_address_space_handler (
/* The handler does not exist */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
- handler, acpi_ut_get_region_name (space_id), space_id, node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
+ handler, acpi_ut_get_region_name(space_id), space_id,
+ node, obj_desc));
status = AE_NOT_EXIST;
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_address_space_handler);
+EXPORT_SYMBOL(acpi_remove_address_space_handler);
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 734b2f24af48..1ce365d651d8 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -50,18 +49,14 @@
#include <acpi/actables.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exconfig")
+ACPI_MODULE_NAME("exconfig")
/* Local prototypes */
-
static acpi_status
-acpi_ex_add_table (
- struct acpi_table_header *table,
- struct acpi_namespace_node *parent_node,
- union acpi_operand_object **ddb_handle);
-
+acpi_ex_add_table(struct acpi_table_header *table,
+ struct acpi_namespace_node *parent_node,
+ union acpi_operand_object **ddb_handle);
/*******************************************************************************
*
@@ -79,64 +74,67 @@ acpi_ex_add_table (
******************************************************************************/
static acpi_status
-acpi_ex_add_table (
- struct acpi_table_header *table,
- struct acpi_namespace_node *parent_node,
- union acpi_operand_object **ddb_handle)
+acpi_ex_add_table(struct acpi_table_header *table,
+ struct acpi_namespace_node *parent_node,
+ union acpi_operand_object **ddb_handle)
{
- acpi_status status;
- struct acpi_table_desc table_info;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ex_add_table");
+ acpi_status status;
+ struct acpi_table_desc table_info;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ex_add_table");
/* Create an object to be the table handle */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
+ /* Init the table handle */
+
+ obj_desc->reference.opcode = AML_LOAD_OP;
+ *ddb_handle = obj_desc;
+
/* Install the new table into the local data structures */
- ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc));
+ ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc));
- table_info.type = ACPI_TABLE_SSDT;
- table_info.pointer = table;
- table_info.length = (acpi_size) table->length;
+ table_info.type = ACPI_TABLE_SSDT;
+ table_info.pointer = table;
+ table_info.length = (acpi_size) table->length;
table_info.allocation = ACPI_MEM_ALLOCATED;
- status = acpi_tb_install_table (&table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_install_table(&table_info);
+ obj_desc->reference.object = table_info.installed_desc;
+
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ /* Table already exists, just return the handle */
+
+ return_ACPI_STATUS(AE_OK);
+ }
goto cleanup;
}
/* Add the table to the namespace */
- status = acpi_ns_load_table (table_info.installed_desc, parent_node);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_load_table(table_info.installed_desc, parent_node);
+ if (ACPI_FAILURE(status)) {
/* Uninstall table on error */
- (void) acpi_tb_uninstall_table (table_info.installed_desc);
+ (void)acpi_tb_uninstall_table(table_info.installed_desc);
goto cleanup;
}
- /* Init the table handle */
+ return_ACPI_STATUS(AE_OK);
- obj_desc->reference.opcode = AML_LOAD_OP;
- obj_desc->reference.object = table_info.installed_desc;
- *ddb_handle = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
-
-cleanup:
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ cleanup:
+ acpi_ut_remove_reference(obj_desc);
+ *ddb_handle = NULL;
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_table_op
@@ -151,56 +149,53 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ex_load_table_op (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object **return_desc)
+acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
+ union acpi_operand_object **return_desc)
{
- acpi_status status;
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_table_header *table;
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *start_node;
- struct acpi_namespace_node *parameter_node = NULL;
- union acpi_operand_object *ddb_handle;
-
-
- ACPI_FUNCTION_TRACE ("ex_load_table_op");
+ acpi_status status;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_table_header *table;
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *start_node;
+ struct acpi_namespace_node *parameter_node = NULL;
+ union acpi_operand_object *ddb_handle;
+ ACPI_FUNCTION_TRACE("ex_load_table_op");
#if 0
/*
* Make sure that the signature does not match one of the tables that
* is already loaded.
*/
- status = acpi_tb_match_signature (operand[0]->string.pointer, NULL);
+ status = acpi_tb_match_signature(operand[0]->string.pointer, NULL);
if (status == AE_OK) {
/* Signature matched -- don't allow override */
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
#endif
/* Find the ACPI table */
- status = acpi_tb_find_table (operand[0]->string.pointer,
- operand[1]->string.pointer,
- operand[2]->string.pointer, &table);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_find_table(operand[0]->string.pointer,
+ operand[1]->string.pointer,
+ operand[2]->string.pointer, &table);
+ if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Table not found, return an Integer=0 and AE_OK */
- ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!ddb_handle) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
ddb_handle->integer.value = 0;
*return_desc = ddb_handle;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Default nodes */
@@ -215,10 +210,12 @@ acpi_ex_load_table_op (
* Find the node referenced by the root_path_string. This is the
* location within the namespace where the table will be loaded.
*/
- status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node,
- ACPI_NS_SEARCH_PARENT, &parent_node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_get_node_by_path(operand[3]->string.pointer,
+ start_node, ACPI_NS_SEARCH_PARENT,
+ &parent_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -226,7 +223,7 @@ acpi_ex_load_table_op (
if (operand[4]->string.length > 0) {
if ((operand[4]->string.pointer[0] != '\\') &&
- (operand[4]->string.pointer[0] != '^')) {
+ (operand[4]->string.pointer[0] != '^')) {
/*
* Path is not absolute, so it will be relative to the node
* referenced by the root_path_string (or the NS root if omitted)
@@ -236,18 +233,20 @@ acpi_ex_load_table_op (
/* Find the node referenced by the parameter_path_string */
- status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node,
- ACPI_NS_SEARCH_PARENT, &parameter_node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_get_node_by_path(operand[4]->string.pointer,
+ start_node, ACPI_NS_SEARCH_PARENT,
+ &parameter_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Load the table into the namespace */
- status = acpi_ex_add_table (table, parent_node, &ddb_handle);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_add_table(table, parent_node, &ddb_handle);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Parameter Data (optional) */
@@ -255,20 +254,20 @@ acpi_ex_load_table_op (
if (parameter_node) {
/* Store the parameter data into the optional parameter object */
- status = acpi_ex_store (operand[5],
- ACPI_CAST_PTR (union acpi_operand_object, parameter_node),
- walk_state);
- if (ACPI_FAILURE (status)) {
- (void) acpi_ex_unload_table (ddb_handle);
- return_ACPI_STATUS (status);
+ status = acpi_ex_store(operand[5],
+ ACPI_CAST_PTR(union acpi_operand_object,
+ parameter_node),
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ (void)acpi_ex_unload_table(ddb_handle);
+ return_ACPI_STATUS(status);
}
}
*return_desc = ddb_handle;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_load_op
@@ -285,38 +284,37 @@ acpi_ex_load_table_op (
******************************************************************************/
acpi_status
-acpi_ex_load_op (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object *target,
- struct acpi_walk_state *walk_state)
+acpi_ex_load_op(union acpi_operand_object *obj_desc,
+ union acpi_operand_object *target,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *ddb_handle;
- union acpi_operand_object *buffer_desc = NULL;
- struct acpi_table_header *table_ptr = NULL;
- acpi_physical_address address;
- struct acpi_table_header table_header;
- u32 i;
-
- ACPI_FUNCTION_TRACE ("ex_load_op");
+ acpi_status status;
+ union acpi_operand_object *ddb_handle;
+ union acpi_operand_object *buffer_desc = NULL;
+ struct acpi_table_header *table_ptr = NULL;
+ acpi_physical_address address;
+ struct acpi_table_header table_header;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ex_load_op");
/* Object can be either an op_region or a Field */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
+ obj_desc,
+ acpi_ut_get_object_type_name(obj_desc)));
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_region_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_region_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -328,116 +326,127 @@ acpi_ex_load_op (
table_header.length = 0;
for (i = 0; i < 8; i++) {
- status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
- (acpi_physical_address) (i + address), 8,
- ((u8 *) &table_header) + i);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
+ (acpi_physical_address)
+ (i + address), 8,
+ ((u8 *) &
+ table_header) + i);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Sanity check the table length */
- if (table_header.length < sizeof (struct acpi_table_header)) {
- return_ACPI_STATUS (AE_BAD_HEADER);
+ if (table_header.length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_BAD_HEADER);
}
/* Allocate a buffer for the entire table */
- table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
+ table_ptr = ACPI_MEM_ALLOCATE(table_header.length);
if (!table_ptr) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Get the entire table from the op region */
for (i = 0; i < table_header.length; i++) {
- status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
- (acpi_physical_address) (i + address), 8,
- ((u8 *) table_ptr + i));
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
+ (acpi_physical_address)
+ (i + address), 8,
+ ((u8 *) table_ptr +
+ i));
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n",
+ obj_desc,
+ acpi_ut_get_object_type_name(obj_desc)));
/*
* The length of the field must be at least as large as the table.
* Read the entire field and thus the entire table. Buffer is
* allocated during the read.
*/
- status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
+ status =
+ acpi_ex_read_data_from_field(walk_state, obj_desc,
+ &buffer_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- table_ptr = ACPI_CAST_PTR (struct acpi_table_header,
- buffer_desc->buffer.pointer);
+ table_ptr = ACPI_CAST_PTR(struct acpi_table_header,
+ buffer_desc->buffer.pointer);
- /* Sanity check the table length */
+ /* All done with the buffer_desc, delete it */
- if (table_ptr->length < sizeof (struct acpi_table_header)) {
- return_ACPI_STATUS (AE_BAD_HEADER);
+ buffer_desc->buffer.pointer = NULL;
+ acpi_ut_remove_reference(buffer_desc);
+
+ /* Sanity check the table length */
+
+ if (table_ptr->length < sizeof(struct acpi_table_header)) {
+ status = AE_BAD_HEADER;
+ goto cleanup;
}
break;
-
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* The table must be either an SSDT or a PSDT */
- if ((!ACPI_STRNCMP (table_ptr->signature,
- acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
- acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
- (!ACPI_STRNCMP (table_ptr->signature,
- acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
- acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
- table_ptr->signature));
+ if ((!ACPI_STRNCMP(table_ptr->signature,
+ acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
+ acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
+ (!ACPI_STRNCMP(table_ptr->signature,
+ acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
+ acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
+ table_ptr->signature));
status = AE_BAD_SIGNATURE;
goto cleanup;
}
/* Install the new table into the local data structures */
- status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
- }
-
- /* Store the ddb_handle into the Target operand */
+ status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle);
+ if (ACPI_FAILURE(status)) {
+ /* On error, table_ptr was deallocated above */
- status = acpi_ex_store (ddb_handle, target, walk_state);
- if (ACPI_FAILURE (status)) {
- (void) acpi_ex_unload_table (ddb_handle);
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ /* Store the ddb_handle into the Target operand */
+ status = acpi_ex_store(ddb_handle, target, walk_state);
+ if (ACPI_FAILURE(status)) {
+ (void)acpi_ex_unload_table(ddb_handle);
-cleanup:
+ /* table_ptr was deallocated above */
- if (buffer_desc) {
- acpi_ut_remove_reference (buffer_desc);
+ return_ACPI_STATUS(status);
}
- else {
- ACPI_MEM_FREE (table_ptr);
+
+ cleanup:
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(table_ptr);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_unload_table
@@ -450,17 +459,13 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_unload_table (
- union acpi_operand_object *ddb_handle)
+acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *table_desc = ddb_handle;
- struct acpi_table_desc *table_info;
-
-
- ACPI_FUNCTION_TRACE ("ex_unload_table");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *table_desc = ddb_handle;
+ struct acpi_table_desc *table_info;
+ ACPI_FUNCTION_TRACE("ex_unload_table");
/*
* Validate the handle
@@ -469,28 +474,28 @@ acpi_ex_unload_table (
* validated here.
*/
if ((!ddb_handle) ||
- (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
- (ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
+ (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the actual table descriptor from the ddb_handle */
- table_info = (struct acpi_table_desc *) table_desc->reference.object;
+ table_info = (struct acpi_table_desc *)table_desc->reference.object;
/*
* Delete the entire namespace under this table Node
* (Offset contains the table_id)
*/
- acpi_ns_delete_namespace_by_owner (table_info->table_id);
+ acpi_ns_delete_namespace_by_owner(table_info->owner_id);
+ acpi_ut_release_owner_id(&table_info->owner_id);
/* Delete the table itself */
- (void) acpi_tb_uninstall_table (table_info->installed_desc);
+ (void)acpi_tb_uninstall_table(table_info->installed_desc);
/* Delete the table descriptor (ddb_handle) */
- acpi_ut_remove_reference (table_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(table_desc);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index 97856c48bd74..04e5194989a6 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -41,24 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exconvrt")
+ACPI_MODULE_NAME("exconvrt")
/* Local prototypes */
-
static u32
-acpi_ex_convert_to_ascii (
- acpi_integer integer,
- u16 base,
- u8 *string,
- u8 max_length);
-
+acpi_ex_convert_to_ascii(acpi_integer integer,
+ u16 base, u8 * string, u8 max_length);
/*******************************************************************************
*
@@ -76,29 +69,25 @@ acpi_ex_convert_to_ascii (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_integer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 flags)
+acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc, u32 flags)
{
- union acpi_operand_object *return_desc;
- u8 *pointer;
- acpi_integer result;
- u32 i;
- u32 count;
- acpi_status status;
-
+ union acpi_operand_object *return_desc;
+ u8 *pointer;
+ acpi_integer result;
+ u32 i;
+ u32 count;
+ acpi_status status;
- ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_integer", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR("ex_convert_to_integer", obj_desc);
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
@@ -106,11 +95,11 @@ acpi_ex_convert_to_integer (
/* Note: Takes advantage of common buffer/string fields */
pointer = obj_desc->buffer.pointer;
- count = obj_desc->buffer.length;
+ count = obj_desc->buffer.length;
break;
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/*
@@ -126,7 +115,7 @@ acpi_ex_convert_to_integer (
/* String conversion is different than Buffer conversion */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
/*
@@ -135,19 +124,18 @@ acpi_ex_convert_to_integer (
* of ACPI 3.0) is that the to_integer() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
- status = acpi_ut_strtoul64 ((char *) pointer, flags, &result);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_strtoul64((char *)pointer, flags, &result);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
break;
-
case ACPI_TYPE_BUFFER:
/* Check for zero-length buffer */
if (!count) {
- return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
/* Transfer no more than an integer's worth of data */
@@ -170,7 +158,6 @@ acpi_ex_convert_to_integer (
}
break;
-
default:
/* No other types can get here */
break;
@@ -178,20 +165,19 @@ acpi_ex_convert_to_integer (
/* Create a new integer */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the Result */
return_desc->integer.value = result;
- acpi_ex_truncate_for32bit_table (return_desc);
+ acpi_ex_truncate_for32bit_table(return_desc);
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_buffer
@@ -207,25 +193,21 @@ acpi_ex_convert_to_integer (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_buffer (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc)
+acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
+ union acpi_operand_object *return_desc;
+ u8 *new_buf;
+ ACPI_FUNCTION_TRACE_PTR("ex_convert_to_buffer", obj_desc);
- ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_buffer", obj_desc);
-
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
@@ -233,20 +215,20 @@ acpi_ex_convert_to_buffer (
* Create a new Buffer object.
* Need enough space for one integer
*/
- return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
+ return_desc =
+ acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the integer to the buffer, LSB first */
new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY (new_buf,
- &obj_desc->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf,
+ &obj_desc->integer.value,
+ acpi_gbl_integer_byte_width);
break;
-
case ACPI_TYPE_STRING:
/*
@@ -258,32 +240,31 @@ acpi_ex_convert_to_buffer (
* ASL/AML code that depends on the null being transferred to the new
* buffer.
*/
- return_desc = acpi_ut_create_buffer_object (
- (acpi_size) obj_desc->string.length + 1);
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ obj_desc->string.
+ length + 1);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the string to the buffer */
new_buf = return_desc->buffer.pointer;
- ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer,
- obj_desc->string.length);
+ ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer,
+ obj_desc->string.length);
break;
-
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Mark buffer initialized */
return_desc->common.flags |= AOPOBJ_DATA_VALID;
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_ascii
@@ -300,24 +281,19 @@ acpi_ex_convert_to_buffer (
******************************************************************************/
static u32
-acpi_ex_convert_to_ascii (
- acpi_integer integer,
- u16 base,
- u8 *string,
- u8 data_width)
+acpi_ex_convert_to_ascii(acpi_integer integer,
+ u16 base, u8 * string, u8 data_width)
{
- acpi_integer digit;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_native_uint k = 0;
- acpi_native_uint hex_length;
- acpi_native_uint decimal_length;
- u32 remainder;
- u8 supress_zeros;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_integer digit;
+ acpi_native_uint i;
+ acpi_native_uint j;
+ acpi_native_uint k = 0;
+ acpi_native_uint hex_length;
+ acpi_native_uint decimal_length;
+ u32 remainder;
+ u8 supress_zeros;
+ ACPI_FUNCTION_ENTRY();
switch (base) {
case 10:
@@ -339,7 +315,7 @@ acpi_ex_convert_to_ascii (
break;
}
- supress_zeros = TRUE; /* No leading zeros */
+ supress_zeros = TRUE; /* No leading zeros */
remainder = 0;
for (i = decimal_length; i > 0; i--) {
@@ -347,7 +323,8 @@ acpi_ex_convert_to_ascii (
digit = integer;
for (j = 0; j < i; j++) {
- (void) acpi_ut_short_divide (digit, 10, &digit, &remainder);
+ (void)acpi_ut_short_divide(digit, 10, &digit,
+ &remainder);
}
/* Handle leading zeros */
@@ -367,11 +344,13 @@ acpi_ex_convert_to_ascii (
/* hex_length: 2 ascii hex chars per data byte */
- hex_length = ACPI_MUL_2 (data_width);
- for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) {
+ hex_length = (acpi_native_uint) ACPI_MUL_2(data_width);
+ for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
/* Get one hex digit, most significant digits first */
- string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j));
+ string[k] =
+ (u8) acpi_ut_hex_to_ascii_char(integer,
+ ACPI_MUL_4(j));
k++;
}
break;
@@ -387,15 +366,14 @@ acpi_ex_convert_to_ascii (
* Finally, null terminate the string and return the length
*/
if (!k) {
- string [0] = ACPI_ASCII_ZERO;
+ string[0] = ACPI_ASCII_ZERO;
k = 1;
}
- string [k] = 0;
+ string[k] = 0;
return ((u32) k);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_string
@@ -412,30 +390,25 @@ acpi_ex_convert_to_ascii (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_string (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc,
- u32 type)
+acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
+ union acpi_operand_object ** result_desc, u32 type)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
- u32 i;
- u32 string_length = 0;
- u16 base = 16;
- u8 separator = ',';
+ union acpi_operand_object *return_desc;
+ u8 *new_buf;
+ u32 i;
+ u32 string_length = 0;
+ u16 base = 16;
+ u8 separator = ',';
+ ACPI_FUNCTION_TRACE_PTR("ex_convert_to_string", obj_desc);
- ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
-
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
/* No conversion necessary */
*result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_INTEGER:
@@ -452,7 +425,7 @@ acpi_ex_convert_to_string (
/* Two hex string characters for each integer byte */
- string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width);
+ string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
break;
}
@@ -460,31 +433,33 @@ acpi_ex_convert_to_string (
* Create a new String
* Need enough space for one ASCII integer (plus null terminator)
*/
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
+ return_desc =
+ acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
/* Convert integer to string */
- string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base,
- new_buf, acpi_gbl_integer_byte_width);
+ string_length =
+ acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
+ new_buf,
+ acpi_gbl_integer_byte_width);
/* Null terminate at the correct place */
return_desc->string.length = string_length;
- new_buf [string_length] = 0;
+ new_buf[string_length] = 0;
break;
-
case ACPI_TYPE_BUFFER:
/* Setup string length, base, and separator */
switch (type) {
- case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
+ case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* decimal values separated by commas."
@@ -498,11 +473,9 @@ acpi_ex_convert_to_string (
for (i = 0; i < obj_desc->buffer.length; i++) {
if (obj_desc->buffer.pointer[i] >= 100) {
string_length += 4;
- }
- else if (obj_desc->buffer.pointer[i] >= 10) {
+ } else if (obj_desc->buffer.pointer[i] >= 10) {
string_length += 3;
- }
- else {
+ } else {
string_length += 2;
}
}
@@ -518,7 +491,7 @@ acpi_ex_convert_to_string (
string_length = (obj_desc->buffer.length * 3);
break;
- case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */
+ case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */
/*
* From ACPI: "If Data is a buffer, it is converted to a string of
* hexadecimal values separated by commas."
@@ -527,7 +500,7 @@ acpi_ex_convert_to_string (
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -535,15 +508,16 @@ acpi_ex_convert_to_string (
* (-1 because of extra separator included in string_length from above)
*/
string_length--;
- if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ {
- return_ACPI_STATUS (AE_AML_STRING_LIMIT);
+ if (string_length > ACPI_MAX_STRING_CONVERSION) { /* ACPI limit */
+ return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
/* Create a new string object and string buffer */
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
+ return_desc =
+ acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
new_buf = return_desc->buffer.pointer;
@@ -553,10 +527,11 @@ acpi_ex_convert_to_string (
* (separated by commas or spaces)
*/
for (i = 0; i < obj_desc->buffer.length; i++) {
- new_buf += acpi_ex_convert_to_ascii (
- (acpi_integer) obj_desc->buffer.pointer[i], base,
- new_buf, 1);
- *new_buf++ = separator; /* each separated by a comma or space */
+ new_buf += acpi_ex_convert_to_ascii((acpi_integer)
+ obj_desc->buffer.
+ pointer[i], base,
+ new_buf, 1);
+ *new_buf++ = separator; /* each separated by a comma or space */
}
/*
@@ -568,14 +543,13 @@ acpi_ex_convert_to_string (
break;
default:
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
*result_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_convert_to_target_type
@@ -592,17 +566,14 @@ acpi_ex_convert_to_string (
******************************************************************************/
acpi_status
-acpi_ex_convert_to_target_type (
- acpi_object_type destination_type,
- union acpi_operand_object *source_desc,
- union acpi_operand_object **result_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_convert_to_target_type(acpi_object_type destination_type,
+ union acpi_operand_object *source_desc,
+ union acpi_operand_object **result_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_convert_to_target_type");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_convert_to_target_type");
/* Default behavior */
@@ -612,10 +583,10 @@ acpi_ex_convert_to_target_type (
* If required by the target,
* perform implicit conversion on the source before we store it.
*/
- switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
+ switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
case ARGI_SIMPLE_TARGET:
case ARGI_FIXED_TARGET:
- case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
+ case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
switch (destination_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
@@ -627,17 +598,19 @@ acpi_ex_convert_to_target_type (
default:
/* No conversion allowed for these types */
- if (destination_type != ACPI_GET_OBJECT_TYPE (source_desc)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Explicit operator, will store (%s) over existing type (%s)\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_type_name (destination_type)));
+ if (destination_type !=
+ ACPI_GET_OBJECT_TYPE(source_desc)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Explicit operator, will store (%s) over existing type (%s)\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_type_name
+ (destination_type)));
status = AE_TYPE;
}
}
break;
-
case ARGI_TARGETREF:
switch (destination_type) {
@@ -649,55 +622,55 @@ acpi_ex_convert_to_target_type (
* These types require an Integer operand. We can convert
* a Buffer or a String to an Integer if necessary.
*/
- status = acpi_ex_convert_to_integer (source_desc, result_desc,
- 16);
+ status =
+ acpi_ex_convert_to_integer(source_desc, result_desc,
+ 16);
break;
-
case ACPI_TYPE_STRING:
/*
* The operand must be a String. We can convert an
* Integer or Buffer if necessary
*/
- status = acpi_ex_convert_to_string (source_desc, result_desc,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status =
+ acpi_ex_convert_to_string(source_desc, result_desc,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
-
case ACPI_TYPE_BUFFER:
/*
* The operand must be a Buffer. We can convert an
* Integer or String if necessary
*/
- status = acpi_ex_convert_to_buffer (source_desc, result_desc);
+ status =
+ acpi_ex_convert_to_buffer(source_desc, result_desc);
break;
-
default:
- ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
- destination_type));
+ ACPI_REPORT_ERROR(("Bad destination type during conversion: %X\n", destination_type));
status = AE_AML_INTERNAL;
break;
}
break;
-
case ARGI_REFERENCE:
/*
* create_xxxx_field cases - we are storing the field object into the name
*/
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown Target type ID 0x%X Op %s dest_type %s\n",
- GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
- walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
-
- ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
- GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
- status = AE_AML_INTERNAL;
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Target type ID 0x%X Op %s dest_type %s\n",
+ GET_CURRENT_ARG_TYPE(walk_state->op_info->
+ runtime_args),
+ walk_state->op_info->name,
+ acpi_ut_get_type_name(destination_type)));
+
+ ACPI_REPORT_ERROR(("Bad Target Type (ARGI): %X\n",
+ GET_CURRENT_ARG_TYPE(walk_state->op_info->
+ runtime_args)))
+ status = AE_AML_INTERNAL;
}
/*
@@ -710,7 +683,5 @@ acpi_ex_convert_to_target_type (
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 812cdcb2e370..91c49188fb07 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -49,10 +48,8 @@
#include <acpi/acevents.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("excreate")
-
+ACPI_MODULE_NAME("excreate")
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -66,33 +63,30 @@
* DESCRIPTION: Create a new named alias
*
******************************************************************************/
-
-acpi_status
-acpi_ex_create_alias (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
{
- struct acpi_namespace_node *target_node;
- struct acpi_namespace_node *alias_node;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_alias");
+ struct acpi_namespace_node *target_node;
+ struct acpi_namespace_node *alias_node;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_create_alias");
/* Get the source/alias operands (both namespace nodes) */
- alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
- target_node = (struct acpi_namespace_node *) walk_state->operands[1];
+ alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
+ target_node = (struct acpi_namespace_node *)walk_state->operands[1];
if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
- (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+ (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/*
* Dereference an existing alias so that we don't create a chain
* of aliases. With this code, we guarantee that an alias is
* always exactly one level of indirection away from the
* actual aliased name.
*/
- target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
+ target_node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ target_node->object);
}
/*
@@ -115,7 +109,8 @@ acpi_ex_create_alias (
* types, the object can change dynamically via a Store.
*/
alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
- alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
+ alias_node->object =
+ ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
case ACPI_TYPE_METHOD:
@@ -126,7 +121,8 @@ acpi_ex_create_alias (
* types, the object can change dynamically via a Store.
*/
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
- alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
+ alias_node->object =
+ ACPI_CAST_PTR(union acpi_operand_object, target_node);
break;
default:
@@ -139,17 +135,18 @@ acpi_ex_create_alias (
* additional reference to prevent deletion out from under either the
* target node or the alias Node
*/
- status = acpi_ns_attach_object (alias_node,
- acpi_ns_get_attached_object (target_node), target_node->type);
+ status = acpi_ns_attach_object(alias_node,
+ acpi_ns_get_attached_object
+ (target_node),
+ target_node->type);
break;
}
/* Since both operands are Nodes, we don't need to delete them */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_event
@@ -162,18 +159,14 @@ acpi_ex_create_alias (
*
******************************************************************************/
-acpi_status
-acpi_ex_create_event (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_event");
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ex_create_event");
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -183,27 +176,27 @@ acpi_ex_create_event (
* Create the actual OS semaphore, with zero initial units -- meaning
* that the event is created in an unsignalled state
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0,
- &obj_desc->event.semaphore);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
+ &obj_desc->event.semaphore);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Attach object to the Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0],
- obj_desc, ACPI_TYPE_EVENT);
+ status =
+ acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
+ operands[0], obj_desc, ACPI_TYPE_EVENT);
-cleanup:
+ cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_mutex
@@ -218,20 +211,16 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_mutex (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS);
/* Create the new mutex object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -242,30 +231,30 @@ acpi_ex_create_mutex (
* One unit max to make it a mutex, with one initial unit to allow
* the mutex to be acquired.
*/
- status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_create_semaphore(1, 1, &obj_desc->mutex.semaphore);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Init object and attach to NS node */
- obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value;
- obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0];
-
- status = acpi_ns_attach_object (obj_desc->mutex.node,
- obj_desc, ACPI_TYPE_MUTEX);
+ obj_desc->mutex.sync_level =
+ (u8) walk_state->operands[1]->integer.value;
+ obj_desc->mutex.node =
+ (struct acpi_namespace_node *)walk_state->operands[0];
+ status = acpi_ns_attach_object(obj_desc->mutex.node,
+ obj_desc, ACPI_TYPE_MUTEX);
-cleanup:
+ cleanup:
/*
* Remove local reference to the object (on error, will cause deletion
* of both object and semaphore if present.)
*/
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_region
@@ -282,20 +271,16 @@ cleanup:
******************************************************************************/
acpi_status
-acpi_ex_create_region (
- u8 *aml_start,
- u32 aml_length,
- u8 region_space,
- struct acpi_walk_state *walk_state)
+acpi_ex_create_region(u8 * aml_start,
+ u32 aml_length,
+ u8 region_space, struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- union acpi_operand_object *region_obj2;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_region");
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *region_obj2;
+ ACPI_FUNCTION_TRACE("ex_create_region");
/* Get the Namespace Node */
@@ -305,8 +290,8 @@ acpi_ex_create_region (
* If the region object is already attached to this node,
* just return
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -314,17 +299,18 @@ acpi_ex_create_region (
* range
*/
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
- (region_space < ACPI_USER_REGION_BEGIN)) {
- ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space));
- return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
+ (region_space < ACPI_USER_REGION_BEGIN)) {
+ ACPI_REPORT_ERROR(("Invalid address_space type %X\n",
+ region_space));
+ return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
- acpi_ut_get_region_name (region_space), region_space));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
+ acpi_ut_get_region_name(region_space), region_space));
/* Create the region descriptor */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -334,7 +320,7 @@ acpi_ex_create_region (
* Remember location in AML stream of address & length
* operands since they need to be evaluated at run time.
*/
- region_obj2 = obj_desc->common.next_object;
+ region_obj2 = obj_desc->common.next_object;
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
@@ -343,22 +329,20 @@ acpi_ex_create_region (
obj_desc->region.space_id = region_space;
obj_desc->region.address = 0;
obj_desc->region.length = 0;
- obj_desc->region.node = node;
+ obj_desc->region.node = node;
/* Install the new region object in the parent Node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_table_region
@@ -371,20 +355,16 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_table_region (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
{
- acpi_status status;
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- struct acpi_table_header *table;
- union acpi_operand_object *region_obj2;
-
-
- ACPI_FUNCTION_TRACE ("ex_create_table_region");
+ acpi_status status;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ struct acpi_table_header *table;
+ union acpi_operand_object *region_obj2;
+ ACPI_FUNCTION_TRACE("ex_create_table_region");
/* Get the Node from the object stack */
@@ -394,66 +374,64 @@ acpi_ex_create_table_region (
* If the region object is already attached to this node,
* just return
*/
- if (acpi_ns_get_attached_object (node)) {
- return_ACPI_STATUS (AE_OK);
+ if (acpi_ns_get_attached_object(node)) {
+ return_ACPI_STATUS(AE_OK);
}
/* Find the ACPI table */
- status = acpi_tb_find_table (operand[1]->string.pointer,
- operand[2]->string.pointer,
- operand[3]->string.pointer, &table);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_find_table(operand[1]->string.pointer,
+ operand[2]->string.pointer,
+ operand[3]->string.pointer, &table);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Create the region descriptor */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- region_obj2 = obj_desc->common.next_object;
+ region_obj2 = obj_desc->common.next_object;
region_obj2->extra.region_context = NULL;
/* Init the region from the operands */
obj_desc->region.space_id = REGION_DATA_TABLE;
- obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table);
+ obj_desc->region.address =
+ (acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;
- obj_desc->region.node = node;
- obj_desc->region.flags = AOPOBJ_DATA_VALID;
+ obj_desc->region.node = node;
+ obj_desc->region.flags = AOPOBJ_DATA_VALID;
/* Install the new region object in the parent Node */
- status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ev_initialize_region (obj_desc, FALSE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_initialize_region(obj_desc, FALSE);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_EXIST) {
status = AE_OK;
- }
- else {
+ } else {
goto cleanup;
}
}
obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
-
-cleanup:
+ cleanup:
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_processor
@@ -468,43 +446,39 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_create_processor (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state);
/* Create the processor object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the processor object from the operands */
- obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
- obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value;
- obj_desc->processor.length = (u8) operand[3]->integer.value;
+ obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
+ obj_desc->processor.address =
+ (acpi_io_address) operand[2]->integer.value;
+ obj_desc->processor.length = (u8) operand[3]->integer.value;
/* Install the processor object in the parent Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_PROCESSOR);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_PROCESSOR);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_power_resource
@@ -519,43 +493,39 @@ acpi_ex_create_processor (
*
******************************************************************************/
-acpi_status
-acpi_ex_create_power_resource (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state);
/* Create the power resource object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize the power object from the operands */
obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
- obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value;
+ obj_desc->power_resource.resource_order =
+ (u16) operand[2]->integer.value;
/* Install the power resource object in the parent Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_POWER);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_POWER);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_create_method
@@ -571,25 +541,21 @@ acpi_ex_create_power_resource (
******************************************************************************/
acpi_status
-acpi_ex_create_method (
- u8 *aml_start,
- u32 aml_length,
- struct acpi_walk_state *walk_state)
+acpi_ex_create_method(u8 * aml_start,
+ u32 aml_length, struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u8 method_flags;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state);
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u8 method_flags;
+ ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state);
/* Create a new method object */
- obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD);
+ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Save the method's AML pointer and length */
@@ -603,8 +569,10 @@ acpi_ex_create_method (
*/
method_flags = (u8) operand[1]->integer.value;
- obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
- obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
+ obj_desc->method.method_flags =
+ (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
+ obj_desc->method.param_count =
+ (u8) (method_flags & AML_METHOD_ARG_COUNT);
/*
* Get the concurrency count. If required, a semaphore will be
@@ -613,32 +581,28 @@ acpi_ex_create_method (
if (acpi_gbl_all_methods_serialized) {
obj_desc->method.concurrency = 1;
obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
- }
- else if (method_flags & AML_METHOD_SERIALIZED) {
+ } else if (method_flags & AML_METHOD_SERIALIZED) {
/*
* ACPI 1.0: Concurrency = 1
* ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
*/
obj_desc->method.concurrency = (u8)
- (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
- }
- else {
+ (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
+ } else {
obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
}
/* Attach the new object to the method Node */
- status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
- obj_desc, ACPI_TYPE_METHOD);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
+ obj_desc, ACPI_TYPE_METHOD);
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
/* Remove a reference to the operand */
- acpi_ut_remove_reference (operand[1]);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(operand[1]);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 408500648114..bc2fa996047e 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
@@ -49,37 +48,27 @@
#include <acpi/acparser.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exdump")
+ACPI_MODULE_NAME("exdump")
+/*
+ * The following routines are used for debug output only
+ */
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
-
#ifdef ACPI_FUTURE_USAGE
-static void
-acpi_ex_out_string (
- char *title,
- char *value);
+static void acpi_ex_out_string(char *title, char *value);
-static void
-acpi_ex_out_pointer (
- char *title,
- void *value);
+static void acpi_ex_out_pointer(char *title, void *value);
-static void
-acpi_ex_out_integer (
- char *title,
- u32 value);
+static void acpi_ex_out_integer(char *title, u32 value);
-static void
-acpi_ex_out_address (
- char *title,
- acpi_physical_address value);
-#endif /* ACPI_FUTURE_USAGE */
+static void acpi_ex_out_address(char *title, acpi_physical_address value);
+static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc);
-/*
- * The following routines are used for debug output only
- */
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+static void
+acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index);
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -94,143 +83,140 @@ acpi_ex_out_address (
*
******************************************************************************/
-void
-acpi_ex_dump_operand (
- union acpi_operand_object *obj_desc,
- u32 depth)
+void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
{
- u32 length;
- u32 index;
-
+ u32 length;
+ u32 index;
- ACPI_FUNCTION_NAME ("ex_dump_operand")
+ ACPI_FUNCTION_NAME("ex_dump_operand")
-
- if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_EXEC & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return;
}
if (!obj_desc) {
/* This could be a null element of a package */
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
return;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc));
- ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC);
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ",
+ obj_desc));
+ ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC);
return;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%p is not a node or operand object: [%s]\n",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
- ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object));
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%p is not a node or operand object: [%s]\n",
+ obj_desc,
+ acpi_ut_get_descriptor_name(obj_desc)));
+ ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object));
return;
}
/* obj_desc is a valid object */
if (depth > 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ",
- depth, " ", depth, obj_desc));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ",
+ depth, " ", depth, obj_desc));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc));
}
/* Decode object type */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
switch (obj_desc->reference.opcode) {
case AML_DEBUG_OP:
- acpi_os_printf ("Reference: Debug\n");
+ acpi_os_printf("Reference: Debug\n");
break;
-
case AML_NAME_OP:
- ACPI_DUMP_PATHNAME (obj_desc->reference.object,
- "Reference: Name: ", ACPI_LV_INFO, _COMPONENT);
- ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO);
+ ACPI_DUMP_PATHNAME(obj_desc->reference.object,
+ "Reference: Name: ", ACPI_LV_INFO,
+ _COMPONENT);
+ ACPI_DUMP_ENTRY(obj_desc->reference.object,
+ ACPI_LV_INFO);
break;
-
case AML_INDEX_OP:
- acpi_os_printf ("Reference: Index %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("Reference: Index %p\n",
+ obj_desc->reference.object);
break;
-
case AML_REF_OF_OP:
- acpi_os_printf ("Reference: (ref_of) %p\n",
- obj_desc->reference.object);
+ acpi_os_printf("Reference: (ref_of) %p\n",
+ obj_desc->reference.object);
break;
-
case AML_ARG_OP:
- acpi_os_printf ("Reference: Arg%d",
- obj_desc->reference.offset);
+ acpi_os_printf("Reference: Arg%d",
+ obj_desc->reference.offset);
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Value is an Integer */
- acpi_os_printf (" value is [%8.8X%8.8x]",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" value is [%8.8X%8.8x]",
+ ACPI_FORMAT_UINT64(obj_desc->
+ integer.
+ value));
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
-
case AML_LOCAL_OP:
- acpi_os_printf ("Reference: Local%d",
- obj_desc->reference.offset);
+ acpi_os_printf("Reference: Local%d",
+ obj_desc->reference.offset);
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Value is an Integer */
- acpi_os_printf (" value is [%8.8X%8.8x]",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" value is [%8.8X%8.8x]",
+ ACPI_FORMAT_UINT64(obj_desc->
+ integer.
+ value));
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
-
case AML_INT_NAMEPATH_OP:
- acpi_os_printf ("Reference.Node->Name %X\n",
- obj_desc->reference.node->name.integer);
+ acpi_os_printf("Reference.Node->Name %X\n",
+ obj_desc->reference.node->name.integer);
break;
-
default:
/* Unknown opcode */
- acpi_os_printf ("Unknown Reference opcode=%X\n",
- obj_desc->reference.opcode);
+ acpi_os_printf("Unknown Reference opcode=%X\n",
+ obj_desc->reference.opcode);
break;
}
break;
-
case ACPI_TYPE_BUFFER:
- acpi_os_printf ("Buffer len %X @ %p \n",
- obj_desc->buffer.length, obj_desc->buffer.pointer);
+ acpi_os_printf("Buffer len %X @ %p \n",
+ obj_desc->buffer.length,
+ obj_desc->buffer.pointer);
length = obj_desc->buffer.length;
if (length > 64) {
@@ -240,178 +226,166 @@ acpi_ex_dump_operand (
/* Debug only -- dump the buffer contents */
if (obj_desc->buffer.pointer) {
- acpi_os_printf ("Buffer Contents: ");
+ acpi_os_printf("Buffer Contents: ");
for (index = 0; index < length; index++) {
- acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]);
+ acpi_os_printf(" %02x",
+ obj_desc->buffer.pointer[index]);
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
}
break;
-
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("Integer %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("Integer %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
-
case ACPI_TYPE_PACKAGE:
- acpi_os_printf ("Package [Len %X] element_array %p\n",
- obj_desc->package.count, obj_desc->package.elements);
+ acpi_os_printf("Package [Len %X] element_array %p\n",
+ obj_desc->package.count,
+ obj_desc->package.elements);
/*
* If elements exist, package element pointer is valid,
* and debug_level exceeds 1, dump package's elements.
*/
if (obj_desc->package.count &&
- obj_desc->package.elements &&
- acpi_dbg_level > 1) {
- for (index = 0; index < obj_desc->package.count; index++) {
- acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1);
+ obj_desc->package.elements && acpi_dbg_level > 1) {
+ for (index = 0; index < obj_desc->package.count;
+ index++) {
+ acpi_ex_dump_operand(obj_desc->package.
+ elements[index],
+ depth + 1);
}
}
break;
-
case ACPI_TYPE_REGION:
- acpi_os_printf ("Region %s (%X)",
- acpi_ut_get_region_name (obj_desc->region.space_id),
- obj_desc->region.space_id);
+ acpi_os_printf("Region %s (%X)",
+ acpi_ut_get_region_name(obj_desc->region.
+ space_id),
+ obj_desc->region.space_id);
/*
* If the address and length have not been evaluated,
* don't print them.
*/
if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) {
- acpi_os_printf ("\n");
- }
- else {
- acpi_os_printf (" base %8.8X%8.8X Length %X\n",
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length);
+ acpi_os_printf("\n");
+ } else {
+ acpi_os_printf(" base %8.8X%8.8X Length %X\n",
+ ACPI_FORMAT_UINT64(obj_desc->region.
+ address),
+ obj_desc->region.length);
}
break;
-
case ACPI_TYPE_STRING:
- acpi_os_printf ("String length %X @ %p ",
- obj_desc->string.length,
- obj_desc->string.pointer);
+ acpi_os_printf("String length %X @ %p ",
+ obj_desc->string.length,
+ obj_desc->string.pointer);
- acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
- acpi_os_printf ("\n");
+ acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_os_printf ("bank_field\n");
+ acpi_os_printf("bank_field\n");
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_os_printf (
- "region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
- obj_desc->field.bit_length,
- obj_desc->field.access_byte_width,
- obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
- obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
- obj_desc->field.base_byte_offset,
- obj_desc->field.start_field_bit_offset);
+ acpi_os_printf
+ ("region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
+ obj_desc->field.bit_length,
+ obj_desc->field.access_byte_width,
+ obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
+ obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
+ obj_desc->field.base_byte_offset,
+ obj_desc->field.start_field_bit_offset);
- acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1);
+ acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1);
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf ("index_field\n");
+ acpi_os_printf("index_field\n");
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- acpi_os_printf (
- "buffer_field: %X bits at byte %X bit %X of \n",
- obj_desc->buffer_field.bit_length,
- obj_desc->buffer_field.base_byte_offset,
- obj_desc->buffer_field.start_field_bit_offset);
+ acpi_os_printf("buffer_field: %X bits at byte %X bit %X of \n",
+ obj_desc->buffer_field.bit_length,
+ obj_desc->buffer_field.base_byte_offset,
+ obj_desc->buffer_field.start_field_bit_offset);
if (!obj_desc->buffer_field.buffer_obj) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n"));
- }
- else if (ACPI_GET_OBJECT_TYPE (obj_desc->buffer_field.buffer_obj) !=
- ACPI_TYPE_BUFFER) {
- acpi_os_printf ("*not a Buffer* \n");
- }
- else {
- acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL* \n"));
+ } else
+ if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj)
+ != ACPI_TYPE_BUFFER) {
+ acpi_os_printf("*not a Buffer* \n");
+ } else {
+ acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj,
+ depth + 1);
}
break;
-
case ACPI_TYPE_EVENT:
- acpi_os_printf ("Event\n");
+ acpi_os_printf("Event\n");
break;
-
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Method(%X) @ %p:%X\n",
- obj_desc->method.param_count,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length);
+ acpi_os_printf("Method(%X) @ %p:%X\n",
+ obj_desc->method.param_count,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length);
break;
-
case ACPI_TYPE_MUTEX:
- acpi_os_printf ("Mutex\n");
+ acpi_os_printf("Mutex\n");
break;
-
case ACPI_TYPE_DEVICE:
- acpi_os_printf ("Device\n");
+ acpi_os_printf("Device\n");
break;
-
case ACPI_TYPE_POWER:
- acpi_os_printf ("Power\n");
+ acpi_os_printf("Power\n");
break;
-
case ACPI_TYPE_PROCESSOR:
- acpi_os_printf ("Processor\n");
+ acpi_os_printf("Processor\n");
break;
-
case ACPI_TYPE_THERMAL:
- acpi_os_printf ("Thermal\n");
+ acpi_os_printf("Thermal\n");
break;
-
default:
/* Unknown Type */
- acpi_os_printf ("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE (obj_desc));
+ acpi_os_printf("Unknown Type %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc));
break;
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_operands
@@ -429,20 +403,15 @@ acpi_ex_dump_operand (
******************************************************************************/
void
-acpi_ex_dump_operands (
- union acpi_operand_object **operands,
- acpi_interpreter_mode interpreter_mode,
- char *ident,
- u32 num_levels,
- char *note,
- char *module_name,
- u32 line_number)
+acpi_ex_dump_operands(union acpi_operand_object **operands,
+ acpi_interpreter_mode interpreter_mode,
+ char *ident,
+ u32 num_levels,
+ char *note, char *module_name, u32 line_number)
{
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_NAME ("ex_dump_operands");
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ex_dump_operands");
if (!ident) {
ident = "?";
@@ -452,9 +421,9 @@ acpi_ex_dump_operands (
note = "?";
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
- ident, num_levels));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
+ ident, num_levels));
if (num_levels == 0) {
num_levels = 1;
@@ -463,16 +432,15 @@ acpi_ex_dump_operands (
/* Dump the operand stack starting at the top */
for (i = 0; num_levels > 0; i--, num_levels--) {
- acpi_ex_dump_operand (operands[i], 0);
+ acpi_ex_dump_operand(operands[i], 0);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "************* Stack dump from %s(%d), %s\n",
- module_name, line_number, note));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "************* Operand Stack dump from %s(%d), %s\n",
+ module_name, line_number, note));
return;
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -487,44 +455,31 @@ acpi_ex_dump_operands (
*
******************************************************************************/
-static void
-acpi_ex_out_string (
- char *title,
- char *value)
+static void acpi_ex_out_string(char *title, char *value)
{
- acpi_os_printf ("%20s : %s\n", title, value);
+ acpi_os_printf("%20s : %s\n", title, value);
}
-static void
-acpi_ex_out_pointer (
- char *title,
- void *value)
+static void acpi_ex_out_pointer(char *title, void *value)
{
- acpi_os_printf ("%20s : %p\n", title, value);
+ acpi_os_printf("%20s : %p\n", title, value);
}
-static void
-acpi_ex_out_integer (
- char *title,
- u32 value)
+static void acpi_ex_out_integer(char *title, u32 value)
{
- acpi_os_printf ("%20s : %X\n", title, value);
+ acpi_os_printf("%20s : %.2X\n", title, value);
}
-static void
-acpi_ex_out_address (
- char *title,
- acpi_physical_address value)
+static void acpi_ex_out_address(char *title, acpi_physical_address value)
{
#if ACPI_MACHINE_WIDTH == 16
- acpi_os_printf ("%20s : %p\n", title, value);
+ acpi_os_printf("%20s : %p\n", title, value);
#else
- acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value));
+ acpi_os_printf("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
#endif
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_node
@@ -536,38 +491,161 @@ acpi_ex_out_address (
*
******************************************************************************/
-void
-acpi_ex_dump_node (
- struct acpi_namespace_node *node,
- u32 flags)
+void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return;
}
}
- acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node));
- acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type));
- acpi_ex_out_integer ("Flags", node->flags);
- acpi_ex_out_integer ("Owner Id", node->owner_id);
- acpi_ex_out_integer ("Reference Count", node->reference_count);
- acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node));
- acpi_ex_out_pointer ("child_list", node->child);
- acpi_ex_out_pointer ("next_peer", node->peer);
- acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node));
+ acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node));
+ acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
+ acpi_ex_out_integer("Flags", node->flags);
+ acpi_ex_out_integer("Owner Id", node->owner_id);
+ acpi_ex_out_integer("Reference Count", node->reference_count);
+ acpi_ex_out_pointer("Attached Object",
+ acpi_ns_get_attached_object(node));
+ acpi_ex_out_pointer("child_list", node->child);
+ acpi_ex_out_pointer("next_peer", node->peer);
+ acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_dump_reference
+ *
+ * PARAMETERS: Object - Descriptor to dump
+ *
+ * DESCRIPTION: Dumps a reference object
+ *
+ ******************************************************************************/
+
+static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc)
+{
+ struct acpi_buffer ret_buf;
+ acpi_status status;
+
+ if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) {
+ acpi_os_printf("Named Object %p ", obj_desc->reference.node);
+ ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status =
+ acpi_ns_handle_to_pathname(obj_desc->reference.node,
+ &ret_buf);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not convert name to pathname\n");
+ } else {
+ acpi_os_printf("%s\n", (char *)ret_buf.pointer);
+ ACPI_MEM_FREE(ret_buf.pointer);
+ }
+ } else if (obj_desc->reference.object) {
+ acpi_os_printf("\nReferenced Object: %p\n",
+ obj_desc->reference.object);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_dump_package
+ *
+ * PARAMETERS: Object - Descriptor to dump
+ * Level - Indentation Level
+ * Index - Package index for this object
+ *
+ * DESCRIPTION: Dumps the elements of the package
+ *
+ ******************************************************************************/
+
+static void
+acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index)
+{
+ u32 i;
+
+ /* Indentation and index output */
+
+ if (level > 0) {
+ for (i = 0; i < level; i++) {
+ acpi_os_printf(" ");
+ }
+
+ acpi_os_printf("[%.2d] ", index);
+ }
+
+ acpi_os_printf("%p ", obj_desc);
+
+ /* Null package elements are allowed */
+
+ if (!obj_desc) {
+ acpi_os_printf("[Null Object]\n");
+ return;
+ }
+
+ /* Packages may only contain a few object types */
+
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
+ case ACPI_TYPE_INTEGER:
+
+ acpi_os_printf("[Integer] = %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
+ break;
+
+ case ACPI_TYPE_STRING:
+
+ acpi_os_printf("[String] Value: ");
+ for (i = 0; i < obj_desc->string.length; i++) {
+ acpi_os_printf("%c", obj_desc->string.pointer[i]);
+ }
+ acpi_os_printf("\n");
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ acpi_os_printf("[Buffer] Length %.2X = ",
+ obj_desc->buffer.length);
+ if (obj_desc->buffer.length) {
+ acpi_ut_dump_buffer((u8 *) obj_desc->buffer.pointer,
+ obj_desc->buffer.length,
+ DB_DWORD_DISPLAY, _COMPONENT);
+ } else {
+ acpi_os_printf("\n");
+ }
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ acpi_os_printf("[Package] Contains %d Elements: \n",
+ obj_desc->package.count);
+
+ for (i = 0; i < obj_desc->package.count; i++) {
+ acpi_ex_dump_package(obj_desc->package.elements[i],
+ level + 1, i);
+ }
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ acpi_os_printf("[Object Reference] ");
+ acpi_ex_dump_reference(obj_desc);
+ break;
+
+ default:
+
+ acpi_os_printf("[Unknown Type] %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc));
+ break;
+ }
+}
/*******************************************************************************
*
* FUNCTION: acpi_ex_dump_object_descriptor
*
- * PARAMETERS: *Object - Descriptor to dump
+ * PARAMETERS: Object - Descriptor to dump
* Flags - Force display if TRUE
*
* DESCRIPTION: Dumps the members of the object descriptor given.
@@ -575,202 +653,213 @@ acpi_ex_dump_node (
******************************************************************************/
void
-acpi_ex_dump_object_descriptor (
- union acpi_operand_object *obj_desc,
- u32 flags)
+acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor");
-
+ ACPI_FUNCTION_TRACE("ex_dump_object_descriptor");
if (!obj_desc) {
return_VOID;
}
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
+ && (_COMPONENT & acpi_dbg_layer))) {
return_VOID;
}
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
- acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags);
- acpi_os_printf ("\nAttached Object (%p):\n",
- ((struct acpi_namespace_node *) obj_desc)->object);
- acpi_ex_dump_object_descriptor (
- ((struct acpi_namespace_node *) obj_desc)->object, flags);
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ acpi_ex_dump_node((struct acpi_namespace_node *)obj_desc,
+ flags);
+ acpi_os_printf("\nAttached Object (%p):\n",
+ ((struct acpi_namespace_node *)obj_desc)->
+ object);
+ acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *)
+ obj_desc)->object, flags);
return_VOID;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
- acpi_os_printf (
- "ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc));
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ acpi_os_printf
+ ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
+ obj_desc, acpi_ut_get_descriptor_name(obj_desc));
return_VOID;
}
/* Common Fields */
- acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc));
- acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count);
- acpi_ex_out_integer ("Flags", obj_desc->common.flags);
+ acpi_ex_out_string("Type", acpi_ut_get_object_type_name(obj_desc));
+ acpi_ex_out_integer("Reference Count",
+ obj_desc->common.reference_count);
+ acpi_ex_out_integer("Flags", obj_desc->common.flags);
/* Object-specific Fields */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("%20s : %8.8X%8.8X\n", "Value",
+ ACPI_FORMAT_UINT64(obj_desc->integer.value));
break;
-
case ACPI_TYPE_STRING:
- acpi_ex_out_integer ("Length", obj_desc->string.length);
+ acpi_ex_out_integer("Length", obj_desc->string.length);
- acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer);
- acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
- acpi_os_printf ("\n");
+ acpi_os_printf("%20s : %p ", "Pointer",
+ obj_desc->string.pointer);
+ acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_BUFFER:
- acpi_ex_out_integer ("Length", obj_desc->buffer.length);
- acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer);
- ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length);
+ acpi_ex_out_integer("Length", obj_desc->buffer.length);
+ acpi_ex_out_pointer("Pointer", obj_desc->buffer.pointer);
+ ACPI_DUMP_BUFFER(obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
break;
-
case ACPI_TYPE_PACKAGE:
- acpi_ex_out_integer ("Flags", obj_desc->package.flags);
- acpi_ex_out_integer ("Count", obj_desc->package.count);
- acpi_ex_out_pointer ("Elements", obj_desc->package.elements);
+ acpi_ex_out_integer("Flags", obj_desc->package.flags);
+ acpi_ex_out_integer("Elements", obj_desc->package.count);
+ acpi_ex_out_pointer("Element List", obj_desc->package.elements);
/* Dump the package contents */
- if (obj_desc->package.count > 0) {
- acpi_os_printf ("\nPackage Contents:\n");
- for (i = 0; i < obj_desc->package.count; i++) {
- acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]);
- if (obj_desc->package.elements[i]) {
- acpi_os_printf (" %s",
- acpi_ut_get_object_type_name (obj_desc->package.elements[i]));
- }
- acpi_os_printf ("\n");
- }
- }
+ acpi_os_printf("\nPackage Contents:\n");
+ acpi_ex_dump_package(obj_desc, 0, 0);
break;
-
case ACPI_TYPE_DEVICE:
- acpi_ex_out_pointer ("Handler", obj_desc->device.handler);
- acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->device.handler);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->device.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->device.device_notify);
break;
-
case ACPI_TYPE_EVENT:
- acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore);
+ acpi_ex_out_pointer("Semaphore", obj_desc->event.semaphore);
break;
-
case ACPI_TYPE_METHOD:
- acpi_ex_out_integer ("param_count", obj_desc->method.param_count);
- acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency);
- acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore);
- acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id);
- acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length);
- acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start);
+ acpi_ex_out_integer("param_count",
+ obj_desc->method.param_count);
+ acpi_ex_out_integer("Concurrency",
+ obj_desc->method.concurrency);
+ acpi_ex_out_pointer("Semaphore", obj_desc->method.semaphore);
+ acpi_ex_out_integer("owner_id", obj_desc->method.owner_id);
+ acpi_ex_out_integer("aml_length", obj_desc->method.aml_length);
+ acpi_ex_out_pointer("aml_start", obj_desc->method.aml_start);
break;
-
case ACPI_TYPE_MUTEX:
- acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level);
- acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread);
- acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth);
- acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore);
+ acpi_ex_out_integer("sync_level", obj_desc->mutex.sync_level);
+ acpi_ex_out_pointer("owner_thread",
+ obj_desc->mutex.owner_thread);
+ acpi_ex_out_integer("acquire_depth",
+ obj_desc->mutex.acquisition_depth);
+ acpi_ex_out_pointer("Semaphore", obj_desc->mutex.semaphore);
break;
-
case ACPI_TYPE_REGION:
- acpi_ex_out_integer ("space_id", obj_desc->region.space_id);
- acpi_ex_out_integer ("Flags", obj_desc->region.flags);
- acpi_ex_out_address ("Address", obj_desc->region.address);
- acpi_ex_out_integer ("Length", obj_desc->region.length);
- acpi_ex_out_pointer ("Handler", obj_desc->region.handler);
- acpi_ex_out_pointer ("Next", obj_desc->region.next);
+ acpi_ex_out_integer("space_id", obj_desc->region.space_id);
+ acpi_ex_out_integer("Flags", obj_desc->region.flags);
+ acpi_ex_out_address("Address", obj_desc->region.address);
+ acpi_ex_out_integer("Length", obj_desc->region.length);
+ acpi_ex_out_pointer("Handler", obj_desc->region.handler);
+ acpi_ex_out_pointer("Next", obj_desc->region.next);
break;
-
case ACPI_TYPE_POWER:
- acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level);
- acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order);
- acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify);
+ acpi_ex_out_integer("system_level",
+ obj_desc->power_resource.system_level);
+ acpi_ex_out_integer("resource_order",
+ obj_desc->power_resource.resource_order);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->power_resource.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->power_resource.device_notify);
break;
-
case ACPI_TYPE_PROCESSOR:
- acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id);
- acpi_ex_out_integer ("Length", obj_desc->processor.length);
- acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address);
- acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify);
- acpi_ex_out_pointer ("Handler", obj_desc->processor.handler);
+ acpi_ex_out_integer("Processor ID",
+ obj_desc->processor.proc_id);
+ acpi_ex_out_integer("Length", obj_desc->processor.length);
+ acpi_ex_out_address("Address",
+ (acpi_physical_address) obj_desc->processor.
+ address);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->processor.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->processor.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->processor.handler);
break;
-
case ACPI_TYPE_THERMAL:
- acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify);
- acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify);
- acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler);
+ acpi_ex_out_pointer("system_notify",
+ obj_desc->thermal_zone.system_notify);
+ acpi_ex_out_pointer("device_notify",
+ obj_desc->thermal_zone.device_notify);
+ acpi_ex_out_pointer("Handler", obj_desc->thermal_zone.handler);
break;
-
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags);
- acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width);
- acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
- acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
- acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
- acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ acpi_ex_out_integer("field_flags",
+ obj_desc->common_field.field_flags);
+ acpi_ex_out_integer("access_byte_width",
+ obj_desc->common_field.access_byte_width);
+ acpi_ex_out_integer("bit_length",
+ obj_desc->common_field.bit_length);
+ acpi_ex_out_integer("fld_bit_offset",
+ obj_desc->common_field.
+ start_field_bit_offset);
+ acpi_ex_out_integer("base_byte_offset",
+ obj_desc->common_field.base_byte_offset);
+ acpi_ex_out_pointer("parent_node", obj_desc->common_field.node);
+
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER_FIELD:
- acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj);
+ acpi_ex_out_pointer("buffer_obj",
+ obj_desc->buffer_field.buffer_obj);
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj);
+ acpi_ex_out_pointer("region_obj",
+ obj_desc->field.region_obj);
break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_ex_out_integer ("Value", obj_desc->bank_field.value);
- acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj);
- acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj);
+ acpi_ex_out_integer("Value",
+ obj_desc->bank_field.value);
+ acpi_ex_out_pointer("region_obj",
+ obj_desc->bank_field.region_obj);
+ acpi_ex_out_pointer("bank_obj",
+ obj_desc->bank_field.bank_obj);
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_ex_out_integer ("Value", obj_desc->index_field.value);
- acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj);
- acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj);
+ acpi_ex_out_integer("Value",
+ obj_desc->index_field.value);
+ acpi_ex_out_pointer("Index",
+ obj_desc->index_field.index_obj);
+ acpi_ex_out_pointer("Data",
+ obj_desc->index_field.data_obj);
break;
default:
@@ -779,56 +868,52 @@ acpi_ex_dump_object_descriptor (
}
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
- acpi_ex_out_integer ("target_type", obj_desc->reference.target_type);
- acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (
- obj_desc->reference.opcode))->name);
- acpi_ex_out_integer ("Offset", obj_desc->reference.offset);
- acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object);
- acpi_ex_out_pointer ("Node", obj_desc->reference.node);
- acpi_ex_out_pointer ("Where", obj_desc->reference.where);
-
- if (obj_desc->reference.object) {
- acpi_os_printf ("\nReferenced Object:\n");
- acpi_ex_dump_object_descriptor (obj_desc->reference.object, flags);
- }
- break;
+ acpi_ex_out_integer("target_type",
+ obj_desc->reference.target_type);
+ acpi_ex_out_string("Opcode",
+ (acpi_ps_get_opcode_info
+ (obj_desc->reference.opcode))->name);
+ acpi_ex_out_integer("Offset", obj_desc->reference.offset);
+ acpi_ex_out_pointer("obj_desc", obj_desc->reference.object);
+ acpi_ex_out_pointer("Node", obj_desc->reference.node);
+ acpi_ex_out_pointer("Where", obj_desc->reference.where);
+ acpi_ex_dump_reference(obj_desc);
+ break;
case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
- acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id);
- acpi_ex_out_pointer ("Next", obj_desc->address_space.next);
- acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list);
- acpi_ex_out_pointer ("Node", obj_desc->address_space.node);
- acpi_ex_out_pointer ("Context", obj_desc->address_space.context);
+ acpi_ex_out_integer("space_id",
+ obj_desc->address_space.space_id);
+ acpi_ex_out_pointer("Next", obj_desc->address_space.next);
+ acpi_ex_out_pointer("region_list",
+ obj_desc->address_space.region_list);
+ acpi_ex_out_pointer("Node", obj_desc->address_space.node);
+ acpi_ex_out_pointer("Context", obj_desc->address_space.context);
break;
-
case ACPI_TYPE_LOCAL_NOTIFY:
- acpi_ex_out_pointer ("Node", obj_desc->notify.node);
- acpi_ex_out_pointer ("Context", obj_desc->notify.context);
+ acpi_ex_out_pointer("Node", obj_desc->notify.node);
+ acpi_ex_out_pointer("Context", obj_desc->notify.context);
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
case ACPI_TYPE_LOCAL_EXTRA:
case ACPI_TYPE_LOCAL_DATA:
default:
- acpi_os_printf (
- "ex_dump_object_descriptor: Display not implemented for object type %s\n",
- acpi_ut_get_object_type_name (obj_desc));
+ acpi_os_printf
+ ("ex_dump_object_descriptor: Display not implemented for object type %s\n",
+ acpi_ut_get_object_type_name(obj_desc));
break;
}
return_VOID;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
#endif
-
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index 22c8fa480f60..ab1ba399aa28 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -41,15 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exfield")
-
+ACPI_MODULE_NAME("exfield")
/*******************************************************************************
*
@@ -65,64 +62,70 @@
* Buffer, depending on the size of the field.
*
******************************************************************************/
-
acpi_status
-acpi_ex_read_data_from_field (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **ret_buffer_desc)
+acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **ret_buffer_desc)
{
- acpi_status status;
- union acpi_operand_object *buffer_desc;
- acpi_size length;
- void *buffer;
- u8 locked;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_read_data_from_field", obj_desc);
+ acpi_status status;
+ union acpi_operand_object *buffer_desc;
+ acpi_size length;
+ void *buffer;
+ u8 locked;
+ ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc);
/* Parameter validation */
if (!obj_desc) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
+ }
+ if (!ret_buffer_desc) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- }
- else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
- (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+ } else
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
+ && (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_SMBUS)) {
/*
* This is an SMBus read. We must create a buffer to hold the data
* and directly access the region handler.
*/
- buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
+ buffer_desc =
+ acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.
+ field_flags);
/*
* Perform the read.
* Note: Smbus protocol value is passed in upper 16-bits of Function
*/
- status = acpi_ex_access_region (obj_desc, 0,
- ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer),
- ACPI_READ | (obj_desc->field.attribute << 16));
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_access_region(obj_desc, 0,
+ ACPI_CAST_PTR(acpi_integer,
+ buffer_desc->
+ buffer.pointer),
+ ACPI_READ | (obj_desc->field.
+ attribute << 16));
+ acpi_ex_release_global_lock(locked);
goto exit;
}
@@ -136,22 +139,22 @@ acpi_ex_read_data_from_field (
*
* Note: Field.length is in bits.
*/
- length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length);
+ length =
+ (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
if (length > acpi_gbl_integer_byte_width) {
/* Field is too large for an Integer, create a Buffer instead */
- buffer_desc = acpi_ut_create_buffer_object (length);
+ buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
- }
- else {
+ } else {
/* Field will fit within an Integer (normal case) */
- buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
length = acpi_gbl_integer_byte_width;
@@ -159,37 +162,36 @@ acpi_ex_read_data_from_field (
buffer = &buffer_desc->integer.value;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n",
- obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, (u32) length));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
- obj_desc->common_field.bit_length,
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.base_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n",
+ obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer,
+ (u32) length));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Read from the field */
- status = acpi_ex_extract_from_field (obj_desc, buffer, (u32) length);
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
+ acpi_ex_release_global_lock(locked);
-
-exit:
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (buffer_desc);
- }
- else if (ret_buffer_desc) {
+ exit:
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(buffer_desc);
+ } else {
*ret_buffer_desc = buffer_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_write_data_to_field
@@ -205,97 +207,96 @@ exit:
******************************************************************************/
acpi_status
-acpi_ex_write_data_to_field (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc)
+acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object **result_desc)
{
- acpi_status status;
- u32 length;
- u32 required_length;
- void *buffer;
- void *new_buffer;
- u8 locked;
- union acpi_operand_object *buffer_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_write_data_to_field", obj_desc);
+ acpi_status status;
+ u32 length;
+ u32 required_length;
+ void *buffer;
+ void *new_buffer;
+ u8 locked;
+ union acpi_operand_object *buffer_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc);
/* Parameter validation */
if (!source_desc || !obj_desc) {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- }
- else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
- (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
+ } else
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
+ && (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_SMBUS)) {
/*
* This is an SMBus write. We will bypass the entire field mechanism
* and handoff the buffer directly to the handler.
*
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
*/
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_REPORT_ERROR(("SMBus write requires Buffer, found type %s\n", acpi_ut_get_object_type_name(source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
- ACPI_REPORT_ERROR ((
- "SMBus write requires Buffer of length %X, found length %X\n",
- ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
+ ACPI_REPORT_ERROR(("SMBus write requires Buffer of length %X, found length %X\n", ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
- return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
+ return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
- buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
+ buffer_desc =
+ acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (!buffer_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
buffer = buffer_desc->buffer.pointer;
- ACPI_MEMCPY (buffer, source_desc->buffer.pointer,
- ACPI_SMBUS_BUFFER_SIZE);
+ ACPI_MEMCPY(buffer, source_desc->buffer.pointer,
+ ACPI_SMBUS_BUFFER_SIZE);
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.
+ field_flags);
/*
* Perform the write (returns status and perhaps data in the
* same buffer)
* Note: SMBus protocol type is passed in upper 16-bits of Function.
*/
- status = acpi_ex_access_region (obj_desc, 0,
- (acpi_integer *) buffer,
- ACPI_WRITE | (obj_desc->field.attribute << 16));
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_access_region(obj_desc, 0,
+ (acpi_integer *) buffer,
+ ACPI_WRITE | (obj_desc->field.
+ attribute << 16));
+ acpi_ex_release_global_lock(locked);
*result_desc = buffer_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Get a pointer to the data to be written */
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
buffer = &source_desc->integer.value;
- length = sizeof (source_desc->integer.value);
+ length = sizeof(source_desc->integer.value);
break;
case ACPI_TYPE_BUFFER:
@@ -309,7 +310,7 @@ acpi_ex_write_data_to_field (
break;
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -319,15 +320,15 @@ acpi_ex_write_data_to_field (
* the ACPI specification.
*/
new_buffer = NULL;
- required_length = ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length);
+ required_length =
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
if (length < required_length) {
/* We need to create a new buffer */
- new_buffer = ACPI_MEM_CALLOCATE (required_length);
+ new_buffer = ACPI_MEM_CALLOCATE(required_length);
if (!new_buffer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -335,40 +336,42 @@ acpi_ex_write_data_to_field (
* at Byte zero. All unused (upper) bytes of the
* buffer will be 0.
*/
- ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length);
+ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length);
buffer = new_buffer;
length = required_length;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
- source_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (source_desc)),
- ACPI_GET_OBJECT_TYPE (source_desc), buffer, length));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
- obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)),
- ACPI_GET_OBJECT_TYPE (obj_desc),
- obj_desc->common_field.bit_length,
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.base_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
+ source_desc,
+ acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE
+ (source_desc)),
+ ACPI_GET_OBJECT_TYPE(source_desc), buffer, length));
+
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
+ obj_desc,
+ acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)),
+ ACPI_GET_OBJECT_TYPE(obj_desc),
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.base_byte_offset));
/* Lock entire transaction if requested */
- locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
+ locked =
+ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
/* Write to the field */
- status = acpi_ex_insert_into_field (obj_desc, buffer, length);
- acpi_ex_release_global_lock (locked);
+ status = acpi_ex_insert_into_field(obj_desc, buffer, length);
+ acpi_ex_release_global_lock(locked);
/* Free temporary buffer if we used one */
if (new_buffer) {
- ACPI_MEM_FREE (new_buffer);
+ ACPI_MEM_FREE(new_buffer);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index 3c2f89e00f78..ba6e08843c29 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -41,36 +41,28 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acevents.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exfldio")
+ACPI_MODULE_NAME("exfldio")
/* Local prototypes */
-
static acpi_status
-acpi_ex_field_datum_io (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 read_write);
+acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 read_write);
static u8
-acpi_ex_register_overflow (
- union acpi_operand_object *obj_desc,
- acpi_integer value);
+acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
+ acpi_integer value);
static acpi_status
-acpi_ex_setup_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset);
-
+acpi_ex_setup_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset);
/*******************************************************************************
*
@@ -89,27 +81,25 @@ acpi_ex_setup_region (
******************************************************************************/
static acpi_status
-acpi_ex_setup_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset)
+acpi_ex_setup_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *rgn_desc;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *rgn_desc;
+ ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset);
rgn_desc = obj_desc->common_field.region_obj;
/* We must have a valid region */
- if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
- ACPI_GET_OBJECT_TYPE (rgn_desc),
- acpi_ut_get_object_type_name (rgn_desc)));
+ if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Region, found type %X (%s)\n",
+ ACPI_GET_OBJECT_TYPE(rgn_desc),
+ acpi_ut_get_object_type_name(rgn_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -117,26 +107,25 @@ acpi_ex_setup_region (
* evaluate them now and save the results.
*/
if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_region_arguments (rgn_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_region_arguments(rgn_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
/* SMBus has a non-linear address space */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
#ifdef ACPI_UNDER_DEVELOPMENT
/*
* If the Field access is any_acc, we can now compute the optimal
* access (because we know know the length of the parent region)
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
#endif
@@ -147,56 +136,64 @@ acpi_ex_setup_region (
* (Region length is specified in bytes)
*/
if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset +
- field_datum_byte_offset +
- obj_desc->common_field.access_byte_width)) {
+ field_datum_byte_offset +
+ obj_desc->common_field.
+ access_byte_width)) {
if (acpi_gbl_enable_interpreter_slack) {
/*
* Slack mode only: We will go ahead and allow access to this
* field if it is within the region length rounded up to the next
* access width boundary.
*/
- if (ACPI_ROUND_UP (rgn_desc->region.length,
- obj_desc->common_field.access_byte_width) >=
- (obj_desc->common_field.base_byte_offset +
- (acpi_native_uint) obj_desc->common_field.access_byte_width +
- field_datum_byte_offset)) {
- return_ACPI_STATUS (AE_OK);
+ if (ACPI_ROUND_UP(rgn_desc->region.length,
+ obj_desc->common_field.
+ access_byte_width) >=
+ (obj_desc->common_field.base_byte_offset +
+ (acpi_native_uint) obj_desc->common_field.
+ access_byte_width + field_datum_byte_offset)) {
+ return_ACPI_STATUS(AE_OK);
}
}
- if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
+ if (rgn_desc->region.length <
+ obj_desc->common_field.access_byte_width) {
/*
* This is the case where the access_type (acc_word, etc.) is wider
* than the region itself. For example, a region of length one
* byte, and a field with Dword access specified.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name (obj_desc->common_field.node),
- obj_desc->common_field.access_byte_width,
- acpi_ut_get_node_name (rgn_desc->region.node),
- rgn_desc->region.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ node),
+ obj_desc->common_field.
+ access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->
+ region.node),
+ rgn_desc->region.length));
}
/*
* Offset rounded up to next multiple of field width
* exceeds region length, indicate an error
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
- acpi_ut_get_node_name (obj_desc->common_field.node),
- obj_desc->common_field.base_byte_offset,
- field_datum_byte_offset, obj_desc->common_field.access_byte_width,
- acpi_ut_get_node_name (rgn_desc->region.node),
- rgn_desc->region.length));
-
- return_ACPI_STATUS (AE_AML_REGION_LIMIT);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
+ acpi_ut_get_node_name(obj_desc->common_field.
+ node),
+ obj_desc->common_field.base_byte_offset,
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width,
+ acpi_ut_get_node_name(rgn_desc->region.node),
+ rgn_desc->region.length));
+
+ return_ACPI_STATUS(AE_AML_REGION_LIMIT);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_access_region
@@ -216,27 +213,23 @@ acpi_ex_setup_region (
******************************************************************************/
acpi_status
-acpi_ex_access_region (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 function)
+acpi_ex_access_region(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 function)
{
- acpi_status status;
- union acpi_operand_object *rgn_desc;
- acpi_physical_address address;
-
-
- ACPI_FUNCTION_TRACE ("ex_access_region");
+ acpi_status status;
+ union acpi_operand_object *rgn_desc;
+ acpi_physical_address address;
+ ACPI_FUNCTION_TRACE("ex_access_region");
/*
* Ensure that the region operands are fully evaluated and verify
* the validity of the request
*/
- status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -248,50 +241,53 @@ acpi_ex_access_region (
*/
rgn_desc = obj_desc->common_field.region_obj;
address = rgn_desc->region.address +
- obj_desc->common_field.base_byte_offset +
- field_datum_byte_offset;
+ obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
if ((function & ACPI_IO_MASK) == ACPI_READ) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
- " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id,
- obj_desc->common_field.access_byte_width,
- obj_desc->common_field.base_byte_offset,
- field_datum_byte_offset,
- ACPI_FORMAT_UINT64 (address)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
+ " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
+ acpi_ut_get_region_name(rgn_desc->region.
+ space_id),
+ rgn_desc->region.space_id,
+ obj_desc->common_field.access_byte_width,
+ obj_desc->common_field.base_byte_offset,
+ field_datum_byte_offset,
+ ACPI_FORMAT_UINT64(address)));
/* Invoke the appropriate address_space/op_region handler */
- status = acpi_ev_address_space_dispatch (rgn_desc, function,
- address,
- ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
+ status = acpi_ev_address_space_dispatch(rgn_desc, function,
+ address,
+ ACPI_MUL_8(obj_desc->
+ common_field.
+ access_byte_width),
+ value);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_IMPLEMENTED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Region %s(%X) not implemented\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id));
- }
- else if (status == AE_NOT_EXIST) {
- ACPI_REPORT_ERROR ((
- "Region %s(%X) has no handler\n",
- acpi_ut_get_region_name (rgn_desc->region.space_id),
- rgn_desc->region.space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Region %s(%X) not implemented\n",
+ acpi_ut_get_region_name(rgn_desc->
+ region.
+ space_id),
+ rgn_desc->region.space_id));
+ } else if (status == AE_NOT_EXIST) {
+ ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n",
+ acpi_ut_get_region_name(rgn_desc->
+ region.
+ space_id),
+ rgn_desc->region.space_id));
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_register_overflow
@@ -310,9 +306,8 @@ acpi_ex_access_region (
******************************************************************************/
static u8
-acpi_ex_register_overflow (
- union acpi_operand_object *obj_desc,
- acpi_integer value)
+acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
+ acpi_integer value)
{
if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
@@ -336,7 +331,6 @@ acpi_ex_register_overflow (
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_field_datum_io
@@ -356,18 +350,14 @@ acpi_ex_register_overflow (
******************************************************************************/
static acpi_status
-acpi_ex_field_datum_io (
- union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- acpi_integer *value,
- u32 read_write)
+acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
+ u32 field_datum_byte_offset,
+ acpi_integer * value, u32 read_write)
{
- acpi_status status;
- acpi_integer local_value;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);
+ acpi_status status;
+ acpi_integer local_value;
+ ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset);
if (read_write == ACPI_READ) {
if (!value) {
@@ -392,16 +382,16 @@ acpi_ex_field_datum_io (
* index_field - Write to an Index Register, then read/write from/to a
* Data Register
*/
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER_FIELD:
/*
* If the buffer_field arguments have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -410,47 +400,50 @@ acpi_ex_field_datum_io (
* Copy the data from the source buffer.
* Length is the field width in bytes.
*/
- ACPI_MEMCPY (value,
- (obj_desc->buffer_field.buffer_obj)->buffer.pointer +
- obj_desc->buffer_field.base_byte_offset +
- field_datum_byte_offset,
- obj_desc->common_field.access_byte_width);
- }
- else {
+ ACPI_MEMCPY(value,
+ (obj_desc->buffer_field.buffer_obj)->buffer.
+ pointer +
+ obj_desc->buffer_field.base_byte_offset +
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width);
+ } else {
/*
* Copy the data to the target buffer.
* Length is the field width in bytes.
*/
- ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer +
- obj_desc->buffer_field.base_byte_offset +
- field_datum_byte_offset,
- value, obj_desc->common_field.access_byte_width);
+ ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
+ pointer +
+ obj_desc->buffer_field.base_byte_offset +
+ field_datum_byte_offset, value,
+ obj_desc->common_field.access_byte_width);
}
status = AE_OK;
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
/*
* Ensure that the bank_value is not beyond the capacity of
* the register
*/
- if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
- (acpi_integer) obj_desc->bank_field.value)) {
- return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
+ if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
+ (acpi_integer) obj_desc->
+ bank_field.value)) {
+ return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
}
/*
* For bank_fields, we must write the bank_value to the bank_register
* (itself a region_field) before we can access the data.
*/
- status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
- &obj_desc->bank_field.value,
- sizeof (obj_desc->bank_field.value));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
+ &obj_desc->bank_field.value,
+ sizeof(obj_desc->bank_field.
+ value));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -460,90 +453,92 @@ acpi_ex_field_datum_io (
/*lint -fallthrough */
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
/*
* For simple region_fields, we just directly access the owning
* Operation Region.
*/
- status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
- read_write);
+ status =
+ acpi_ex_access_region(obj_desc, field_datum_byte_offset,
+ value, read_write);
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
-
/*
* Ensure that the index_value is not beyond the capacity of
* the register
*/
- if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
- (acpi_integer) obj_desc->index_field.value)) {
- return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
+ if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
+ (acpi_integer) obj_desc->
+ index_field.value)) {
+ return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
}
/* Write the index value to the index_register (itself a region_field) */
field_datum_byte_offset += obj_desc->index_field.value;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Write to Index Register: Value %8.8X\n",
- field_datum_byte_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Write to Index Register: Value %8.8X\n",
+ field_datum_byte_offset));
- status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
- &field_datum_byte_offset,
- sizeof (field_datum_byte_offset));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
+ &field_datum_byte_offset,
+ sizeof(field_datum_byte_offset));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "I/O to Data Register: value_ptr %p\n",
- value));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "I/O to Data Register: value_ptr %p\n",
+ value));
if (read_write == ACPI_READ) {
/* Read the datum from the data_register */
- status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
- value, sizeof (acpi_integer));
- }
- else {
+ status =
+ acpi_ex_extract_from_field(obj_desc->index_field.
+ data_obj, value,
+ sizeof(acpi_integer));
+ } else {
/* Write the datum to the data_register */
- status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
- value, sizeof (acpi_integer));
+ status =
+ acpi_ex_insert_into_field(obj_desc->index_field.
+ data_obj, value,
+ sizeof(acpi_integer));
}
break;
-
default:
- ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
- ACPI_GET_OBJECT_TYPE (obj_desc)));
+ ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n",
+ ACPI_GET_OBJECT_TYPE(obj_desc)));
status = AE_AML_INTERNAL;
break;
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
if (read_write == ACPI_READ) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Value Read %8.8X%8.8X, Width %d\n",
- ACPI_FORMAT_UINT64 (*value),
- obj_desc->common_field.access_byte_width));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Value Written %8.8X%8.8X, Width %d\n",
- ACPI_FORMAT_UINT64 (*value),
- obj_desc->common_field.access_byte_width));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Value Read %8.8X%8.8X, Width %d\n",
+ ACPI_FORMAT_UINT64(*value),
+ obj_desc->common_field.
+ access_byte_width));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Value Written %8.8X%8.8X, Width %d\n",
+ ACPI_FORMAT_UINT64(*value),
+ obj_desc->common_field.
+ access_byte_width));
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_write_with_update_rule
@@ -560,19 +555,16 @@ acpi_ex_field_datum_io (
******************************************************************************/
acpi_status
-acpi_ex_write_with_update_rule (
- union acpi_operand_object *obj_desc,
- acpi_integer mask,
- acpi_integer field_value,
- u32 field_datum_byte_offset)
+acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
+ acpi_integer mask,
+ acpi_integer field_value,
+ u32 field_datum_byte_offset)
{
- acpi_status status = AE_OK;
- acpi_integer merged_value;
- acpi_integer current_value;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);
+ acpi_status status = AE_OK;
+ acpi_integer merged_value;
+ acpi_integer current_value;
+ ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask);
/* Start with the new bits */
@@ -583,22 +575,27 @@ acpi_ex_write_with_update_rule (
if (mask != ACPI_INTEGER_MAX) {
/* Decode the update rule */
- switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
+ switch (obj_desc->common_field.
+ field_flags & AML_FIELD_UPDATE_RULE_MASK) {
case AML_FIELD_UPDATE_PRESERVE:
/*
* Check if update rule needs to be applied (not if mask is all
* ones) The left shift drops the bits we want to ignore.
*/
- if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
- ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
+ if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
+ ACPI_MUL_8(obj_desc->common_field.
+ access_byte_width))) != 0) {
/*
* Read the current contents of the byte/word/dword containing
* the field, and merge with the new field value.
*/
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &current_value, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_field_datum_io(obj_desc,
+ field_datum_byte_offset,
+ &current_value,
+ ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
merged_value |= (current_value & ~mask);
@@ -621,30 +618,31 @@ acpi_ex_write_with_update_rule (
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "write_with_update_rule: Unknown update_rule setting: %X\n",
- (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "write_with_update_rule: Unknown update_rule setting: %X\n",
+ (obj_desc->common_field.
+ field_flags &
+ AML_FIELD_UPDATE_RULE_MASK)));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (mask),
- field_datum_byte_offset,
- obj_desc->common_field.access_byte_width,
- ACPI_FORMAT_UINT64 (field_value),
- ACPI_FORMAT_UINT64 (merged_value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(mask),
+ field_datum_byte_offset,
+ obj_desc->common_field.access_byte_width,
+ ACPI_FORMAT_UINT64(field_value),
+ ACPI_FORMAT_UINT64(merged_value)));
/* Write the merged value */
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &merged_value, ACPI_WRITE);
+ status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
+ &merged_value, ACPI_WRITE);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_extract_from_field
@@ -660,54 +658,54 @@ acpi_ex_write_with_update_rule (
******************************************************************************/
acpi_status
-acpi_ex_extract_from_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length)
+acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length)
{
- acpi_status status;
- acpi_integer raw_datum;
- acpi_integer merged_datum;
- u32 field_offset = 0;
- u32 buffer_offset = 0;
- u32 buffer_tail_bits;
- u32 datum_count;
- u32 field_datum_count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_extract_from_field");
-
+ acpi_status status;
+ acpi_integer raw_datum;
+ acpi_integer merged_datum;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
+ u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ex_extract_from_field");
/* Validate target buffer and clear it */
- if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length, buffer_length));
+ if (buffer_length <
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length,
+ buffer_length));
- return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+ return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
- ACPI_MEMSET (buffer, 0, buffer_length);
+ ACPI_MEMSET(buffer, 0, buffer_length);
/* Compute the number of datums (access width data items) */
- datum_count = ACPI_ROUND_UP_TO (
- obj_desc->common_field.bit_length,
- obj_desc->common_field.access_bit_width);
- field_datum_count = ACPI_ROUND_UP_TO (
- obj_desc->common_field.bit_length +
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.access_bit_width);
+ datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+ obj_desc->common_field.access_bit_width);
+ field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
+ obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.
+ access_bit_width);
/* Priming read from the field */
- status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
+ ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum >> obj_desc->common_field.start_field_bit_offset;
/* Read the rest of the field */
@@ -715,17 +713,17 @@ acpi_ex_extract_from_field (
/* Get next input datum from the field */
field_offset += obj_desc->common_field.access_byte_width;
- status = acpi_ex_field_datum_io (obj_desc, field_offset,
- &raw_datum, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_field_datum_io(obj_desc, field_offset,
+ &raw_datum, ACPI_READ);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Merge with previous datum if necessary */
merged_datum |= raw_datum <<
- (obj_desc->common_field.access_bit_width -
- obj_desc->common_field.start_field_bit_offset);
+ (obj_desc->common_field.access_bit_width -
+ obj_desc->common_field.start_field_bit_offset);
if (i == datum_count) {
break;
@@ -733,32 +731,32 @@ acpi_ex_extract_from_field (
/* Write merged datum to target buffer */
- ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
buffer_offset += obj_desc->common_field.access_byte_width;
- merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum >> obj_desc->common_field.start_field_bit_offset;
}
/* Mask off any extra bits in the last datum */
buffer_tail_bits = obj_desc->common_field.bit_length %
- obj_desc->common_field.access_bit_width;
+ obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
- merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
+ merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
/* Write the last datum to the buffer */
- ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_insert_into_field
@@ -774,53 +772,54 @@ acpi_ex_extract_from_field (
******************************************************************************/
acpi_status
-acpi_ex_insert_into_field (
- union acpi_operand_object *obj_desc,
- void *buffer,
- u32 buffer_length)
+acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
+ void *buffer, u32 buffer_length)
{
- acpi_status status;
- acpi_integer mask;
- acpi_integer merged_datum;
- acpi_integer raw_datum = 0;
- u32 field_offset = 0;
- u32 buffer_offset = 0;
- u32 buffer_tail_bits;
- u32 datum_count;
- u32 field_datum_count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_insert_into_field");
-
+ acpi_status status;
+ acpi_integer mask;
+ acpi_integer merged_datum;
+ acpi_integer raw_datum = 0;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
+ u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ex_insert_into_field");
/* Validate input buffer */
- if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
- obj_desc->common_field.bit_length, buffer_length));
+ if (buffer_length <
+ ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length,
+ buffer_length));
- return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+ return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
/* Compute the number of datums (access width data items) */
- mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
- datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
- obj_desc->common_field.access_bit_width);
- field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.access_bit_width);
+ mask =
+ ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
+ datum_count =
+ ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+ obj_desc->common_field.access_bit_width);
+ field_datum_count =
+ ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.access_bit_width);
/* Get initial Datum from the input buffer */
- ACPI_MEMCPY (&raw_datum, buffer,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
+ ACPI_MEMCPY(&raw_datum, buffer,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
+ merged_datum =
+ raw_datum << obj_desc->common_field.start_field_bit_offset;
/* Write the entire field */
@@ -828,18 +827,19 @@ acpi_ex_insert_into_field (
/* Write merged datum to the target field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule (obj_desc, mask,
- merged_datum, field_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_write_with_update_rule(obj_desc, mask,
+ merged_datum,
+ field_offset);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Start new output datum by merging with previous input datum */
field_offset += obj_desc->common_field.access_byte_width;
merged_datum = raw_datum >>
- (obj_desc->common_field.access_bit_width -
- obj_desc->common_field.start_field_bit_offset);
+ (obj_desc->common_field.access_bit_width -
+ obj_desc->common_field.start_field_bit_offset);
mask = ACPI_INTEGER_MAX;
if (i == datum_count) {
@@ -849,28 +849,28 @@ acpi_ex_insert_into_field (
/* Get the next input datum from the buffer */
buffer_offset += obj_desc->common_field.access_byte_width;
- ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
- ACPI_MIN(obj_desc->common_field.access_byte_width,
- buffer_length - buffer_offset));
- merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
+ ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
+ merged_datum |=
+ raw_datum << obj_desc->common_field.start_field_bit_offset;
}
/* Mask off any extra bits in the last datum */
buffer_tail_bits = (obj_desc->common_field.bit_length +
- obj_desc->common_field.start_field_bit_offset) %
- obj_desc->common_field.access_bit_width;
+ obj_desc->common_field.start_field_bit_offset) %
+ obj_desc->common_field.access_bit_width;
if (buffer_tail_bits) {
- mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
+ mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
/* Write the last datum to the field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule (obj_desc,
- mask, merged_datum, field_offset);
+ status = acpi_ex_write_with_update_rule(obj_desc,
+ mask, merged_datum,
+ field_offset);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 022f281345b8..a3f4d72bedc9 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -42,15 +42,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exmisc")
-
+ACPI_MODULE_NAME("exmisc")
/*******************************************************************************
*
@@ -66,27 +63,23 @@
* Common code for the ref_of_op and the cond_ref_of_op.
*
******************************************************************************/
-
acpi_status
-acpi_ex_get_object_reference (
- union acpi_operand_object *obj_desc,
- union acpi_operand_object **return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
+ union acpi_operand_object **return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *reference_obj;
- union acpi_operand_object *referenced_obj;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc);
+ union acpi_operand_object *reference_obj;
+ union acpi_operand_object *referenced_obj;
+ ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc);
*return_desc = NULL;
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
- if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -104,13 +97,11 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
- obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
break;
-
case ACPI_DESC_TYPE_NAMED:
/*
@@ -119,34 +110,32 @@ acpi_ex_get_object_reference (
referenced_obj = obj_desc;
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
- ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
- return_ACPI_STATUS (AE_TYPE);
+ ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
+ return_ACPI_STATUS(AE_TYPE);
}
-
/* Create a new reference object */
- reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ reference_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!reference_obj) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
reference_obj->reference.opcode = AML_REF_OF_OP;
reference_obj->reference.object = referenced_obj;
*return_desc = reference_obj;
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Object %p Type [%s], returning Reference %p\n",
- obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Object %p Type [%s], returning Reference %p\n",
+ obj_desc, acpi_ut_get_object_type_name(obj_desc),
+ *return_desc));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_concat_template
@@ -163,63 +152,58 @@ acpi_ex_get_object_reference (
******************************************************************************/
acpi_status
-acpi_ex_concat_template (
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_concat_template(union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *return_desc;
- u8 *new_buf;
- u8 *end_tag1;
- u8 *end_tag2;
- acpi_size length1;
- acpi_size length2;
-
-
- ACPI_FUNCTION_TRACE ("ex_concat_template");
+ union acpi_operand_object *return_desc;
+ u8 *new_buf;
+ u8 *end_tag1;
+ u8 *end_tag2;
+ acpi_size length1;
+ acpi_size length2;
+ ACPI_FUNCTION_TRACE("ex_concat_template");
/* Find the end_tags in each resource template */
- end_tag1 = acpi_ut_get_resource_end_tag (operand0);
- end_tag2 = acpi_ut_get_resource_end_tag (operand1);
+ end_tag1 = acpi_ut_get_resource_end_tag(operand0);
+ end_tag2 = acpi_ut_get_resource_end_tag(operand1);
if (!end_tag1 || !end_tag2) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Compute the length of each part */
- length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer);
- length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) +
- 2; /* Size of END_TAG */
+ length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer);
+ length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2; /* Size of END_TAG */
/* Create a new buffer object for the result */
- return_desc = acpi_ut_create_buffer_object (length1 + length2);
+ return_desc = acpi_ut_create_buffer_object(length1 + length2);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the templates to the new descriptor */
new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1);
- ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2);
+ ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1);
+ ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2);
/* Compute the new checksum */
new_buf[return_desc->buffer.length - 1] =
- acpi_ut_generate_checksum (return_desc->buffer.pointer,
- (return_desc->buffer.length - 1));
+ acpi_ut_generate_checksum(return_desc->buffer.pointer,
+ (return_desc->buffer.length - 1));
/* Return the completed template descriptor */
*actual_return_desc = return_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_concatenate
@@ -236,21 +220,18 @@ acpi_ex_concat_template (
******************************************************************************/
acpi_status
-acpi_ex_do_concatenate (
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- union acpi_operand_object **actual_return_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_do_concatenate(union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1,
+ union acpi_operand_object **actual_return_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *local_operand1 = operand1;
- union acpi_operand_object *return_desc;
- char *new_buf;
- acpi_status status;
- acpi_size new_length;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_concatenate");
+ union acpi_operand_object *local_operand1 = operand1;
+ union acpi_operand_object *return_desc;
+ char *new_buf;
+ acpi_status status;
+ acpi_size new_length;
+ ACPI_FUNCTION_TRACE("ex_do_concatenate");
/*
* Convert the second operand if necessary. The first operand
@@ -259,27 +240,28 @@ acpi_ex_do_concatenate (
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
- status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
+ status =
+ acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_convert_to_string (operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
- status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
+ status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
- ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
- ACPI_GET_OBJECT_TYPE (operand0)));
+ ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n",
+ ACPI_GET_OBJECT_TYPE(operand0)));
status = AE_AML_INTERNAL;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -296,32 +278,33 @@ acpi_ex_do_concatenate (
* 2) Two Strings concatenated to produce a new String
* 3) Two Buffers concatenated to produce a new Buffer
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
/* Result of two Integers is a Buffer */
/* Need enough buffer space for two integers */
- return_desc = acpi_ut_create_buffer_object (
- ACPI_MUL_2 (acpi_gbl_integer_byte_width));
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ ACPI_MUL_2
+ (acpi_gbl_integer_byte_width));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- new_buf = (char *) return_desc->buffer.pointer;
+ new_buf = (char *)return_desc->buffer.pointer;
/* Copy the first integer, LSB first */
- ACPI_MEMCPY (new_buf,
- &operand0->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf,
+ &operand0->integer.value,
+ acpi_gbl_integer_byte_width);
/* Copy the second integer (LSB first) after the first */
- ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width,
- &local_operand1->integer.value,
- acpi_gbl_integer_byte_width);
+ ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width,
+ &local_operand1->integer.value,
+ acpi_gbl_integer_byte_width);
break;
case ACPI_TYPE_STRING:
@@ -329,13 +312,13 @@ acpi_ex_do_concatenate (
/* Result of two Strings is a String */
new_length = (acpi_size) operand0->string.length +
- (acpi_size) local_operand1->string.length;
+ (acpi_size) local_operand1->string.length;
if (new_length > ACPI_MAX_STRING_CONVERSION) {
status = AE_AML_STRING_LIMIT;
goto cleanup;
}
- return_desc = acpi_ut_create_string_object (new_length);
+ return_desc = acpi_ut_create_string_object(new_length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -345,56 +328,56 @@ acpi_ex_do_concatenate (
/* Concatenate the strings */
- ACPI_STRCPY (new_buf,
- operand0->string.pointer);
- ACPI_STRCPY (new_buf + operand0->string.length,
- local_operand1->string.pointer);
+ ACPI_STRCPY(new_buf, operand0->string.pointer);
+ ACPI_STRCPY(new_buf + operand0->string.length,
+ local_operand1->string.pointer);
break;
case ACPI_TYPE_BUFFER:
/* Result of two Buffers is a Buffer */
- return_desc = acpi_ut_create_buffer_object (
- (acpi_size) operand0->buffer.length +
- (acpi_size) local_operand1->buffer.length);
+ return_desc = acpi_ut_create_buffer_object((acpi_size)
+ operand0->buffer.
+ length +
+ (acpi_size)
+ local_operand1->
+ buffer.length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- new_buf = (char *) return_desc->buffer.pointer;
+ new_buf = (char *)return_desc->buffer.pointer;
/* Concatenate the buffers */
- ACPI_MEMCPY (new_buf,
- operand0->buffer.pointer,
- operand0->buffer.length);
- ACPI_MEMCPY (new_buf + operand0->buffer.length,
- local_operand1->buffer.pointer,
- local_operand1->buffer.length);
+ ACPI_MEMCPY(new_buf,
+ operand0->buffer.pointer, operand0->buffer.length);
+ ACPI_MEMCPY(new_buf + operand0->buffer.length,
+ local_operand1->buffer.pointer,
+ local_operand1->buffer.length);
break;
default:
/* Invalid object type, should not happen here */
- ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
- ACPI_GET_OBJECT_TYPE (operand0)));
- status =AE_AML_INTERNAL;
+ ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n",
+ ACPI_GET_OBJECT_TYPE(operand0)));
+ status = AE_AML_INTERNAL;
goto cleanup;
}
*actual_return_desc = return_desc;
-cleanup:
+ cleanup:
if (local_operand1 != operand1) {
- acpi_ut_remove_reference (local_operand1);
+ acpi_ut_remove_reference(local_operand1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_math_op
@@ -412,62 +395,49 @@ cleanup:
******************************************************************************/
acpi_integer
-acpi_ex_do_math_op (
- u16 opcode,
- acpi_integer integer0,
- acpi_integer integer1)
+acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
switch (opcode) {
- case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
+ case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
return (integer0 + integer1);
-
- case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
+ case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
return (integer0 & integer1);
-
- case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
+ case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
return (~(integer0 & integer1));
-
- case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
+ case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
return (integer0 | integer1);
-
- case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
+ case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
return (~(integer0 | integer1));
-
- case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
+ case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
return (integer0 ^ integer1);
-
- case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
+ case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
return (integer0 * integer1);
-
- case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result)*/
+ case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
return (integer0 << integer1);
-
- case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
+ case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
return (integer0 >> integer1);
-
- case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
+ case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
return (integer0 - integer1);
@@ -477,7 +447,6 @@ acpi_ex_do_math_op (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_numeric_op
@@ -499,28 +468,24 @@ acpi_ex_do_math_op (
******************************************************************************/
acpi_status
-acpi_ex_do_logical_numeric_op (
- u16 opcode,
- acpi_integer integer0,
- acpi_integer integer1,
- u8 *logical_result)
+acpi_ex_do_logical_numeric_op(u16 opcode,
+ acpi_integer integer0,
+ acpi_integer integer1, u8 * logical_result)
{
- acpi_status status = AE_OK;
- u8 local_result = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op");
+ acpi_status status = AE_OK;
+ u8 local_result = FALSE;
+ ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op");
switch (opcode) {
- case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
+ case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
if (integer0 && integer1) {
local_result = TRUE;
}
break;
- case AML_LOR_OP: /* LOr (Integer0, Integer1) */
+ case AML_LOR_OP: /* LOr (Integer0, Integer1) */
if (integer0 || integer1) {
local_result = TRUE;
@@ -535,10 +500,9 @@ acpi_ex_do_logical_numeric_op (
/* Return the logical result and status */
*logical_result = local_result;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_do_logical_op
@@ -566,24 +530,20 @@ acpi_ex_do_logical_numeric_op (
******************************************************************************/
acpi_status
-acpi_ex_do_logical_op (
- u16 opcode,
- union acpi_operand_object *operand0,
- union acpi_operand_object *operand1,
- u8 *logical_result)
+acpi_ex_do_logical_op(u16 opcode,
+ union acpi_operand_object *operand0,
+ union acpi_operand_object *operand1, u8 * logical_result)
{
- union acpi_operand_object *local_operand1 = operand1;
- acpi_integer integer0;
- acpi_integer integer1;
- u32 length0;
- u32 length1;
- acpi_status status = AE_OK;
- u8 local_result = FALSE;
- int compare;
-
-
- ACPI_FUNCTION_TRACE ("ex_do_logical_op");
+ union acpi_operand_object *local_operand1 = operand1;
+ acpi_integer integer0;
+ acpi_integer integer1;
+ u32 length0;
+ u32 length1;
+ acpi_status status = AE_OK;
+ u8 local_result = FALSE;
+ int compare;
+ ACPI_FUNCTION_TRACE("ex_do_logical_op");
/*
* Convert the second operand if necessary. The first operand
@@ -592,18 +552,19 @@ acpi_ex_do_logical_op (
* guaranteed to be either Integer/String/Buffer by the operand
* resolution mechanism.
*/
- switch (ACPI_GET_OBJECT_TYPE (operand0)) {
+ switch (ACPI_GET_OBJECT_TYPE(operand0)) {
case ACPI_TYPE_INTEGER:
- status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
+ status =
+ acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_convert_to_string (operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
- status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
+ status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
break;
default:
@@ -611,14 +572,14 @@ acpi_ex_do_logical_op (
break;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/*
* Two cases: 1) Both Integers, 2) Both Strings or Buffers
*/
- if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) {
/*
* 1) Both operands are of type integer
* Note: local_operand1 may have changed above
@@ -627,21 +588,21 @@ acpi_ex_do_logical_op (
integer1 = local_operand1->integer.value;
switch (opcode) {
- case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
+ case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
if (integer0 == integer1) {
local_result = TRUE;
}
break;
- case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
+ case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (integer0 > integer1) {
local_result = TRUE;
}
break;
- case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
+ case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (integer0 < integer1) {
local_result = TRUE;
@@ -652,8 +613,7 @@ acpi_ex_do_logical_op (
status = AE_AML_INTERNAL;
break;
}
- }
- else {
+ } else {
/*
* 2) Both operands are Strings or both are Buffers
* Note: Code below takes advantage of common Buffer/String
@@ -665,31 +625,31 @@ acpi_ex_do_logical_op (
/* Lexicographic compare: compare the data bytes */
- compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer,
- (const char * ) local_operand1->buffer.pointer,
- (length0 > length1) ? length1 : length0);
+ compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer,
+ (const char *)local_operand1->buffer.
+ pointer,
+ (length0 > length1) ? length1 : length0);
switch (opcode) {
- case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
+ case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
/* Length and all bytes must be equal */
- if ((length0 == length1) &&
- (compare == 0)) {
+ if ((length0 == length1) && (compare == 0)) {
/* Length and all bytes match ==> TRUE */
local_result = TRUE;
}
break;
- case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
+ case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
if (compare > 0) {
local_result = TRUE;
- goto cleanup; /* TRUE */
+ goto cleanup; /* TRUE */
}
if (compare < 0) {
- goto cleanup; /* FALSE */
+ goto cleanup; /* FALSE */
}
/* Bytes match (to shortest length), compare lengths */
@@ -699,14 +659,14 @@ acpi_ex_do_logical_op (
}
break;
- case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
+ case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
if (compare > 0) {
- goto cleanup; /* FALSE */
+ goto cleanup; /* FALSE */
}
if (compare < 0) {
local_result = TRUE;
- goto cleanup; /* TRUE */
+ goto cleanup; /* TRUE */
}
/* Bytes match (to shortest length), compare lengths */
@@ -722,18 +682,16 @@ acpi_ex_do_logical_op (
}
}
-cleanup:
+ cleanup:
/* New object was created if implicit conversion performed - delete */
if (local_operand1 != operand1) {
- acpi_ut_remove_reference (local_operand1);
+ acpi_ut_remove_reference(local_operand1);
}
/* Return the logical result and status */
*logical_result = local_result;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index c3cb714d2cba..ab47f6d8b5c0 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -42,20 +42,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exmutex")
+ACPI_MODULE_NAME("exmutex")
/* Local prototypes */
-
static void
-acpi_ex_link_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_thread_state *thread);
-
+acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread);
/*******************************************************************************
*
@@ -69,12 +65,9 @@ acpi_ex_link_mutex (
*
******************************************************************************/
-void
-acpi_ex_unlink_mutex (
- union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
{
- struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
+ struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
if (!thread) {
return;
@@ -88,13 +81,11 @@ acpi_ex_unlink_mutex (
if (obj_desc->mutex.prev) {
(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
- }
- else {
+ } else {
thread->acquired_mutex_list = obj_desc->mutex.next;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_link_mutex
@@ -109,12 +100,10 @@ acpi_ex_unlink_mutex (
******************************************************************************/
static void
-acpi_ex_link_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_thread_state *thread)
+acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread)
{
- union acpi_operand_object *list_head;
-
+ union acpi_operand_object *list_head;
list_head = thread->acquired_mutex_list;
@@ -134,7 +123,6 @@ acpi_ex_link_mutex (
thread->acquired_mutex_list = obj_desc;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_mutex
@@ -150,27 +138,23 @@ acpi_ex_link_mutex (
******************************************************************************/
acpi_status
-acpi_ex_acquire_mutex (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc);
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc);
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
@@ -178,10 +162,8 @@ acpi_ex_acquire_mutex (
* mutex. This mechanism provides some deadlock prevention
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
- ACPI_REPORT_ERROR ((
- "Cannot acquire Mutex [%4.4s], incorrect sync_level\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
+ ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/* Support for multiple acquires by the owning thread */
@@ -190,43 +172,43 @@ acpi_ex_acquire_mutex (
/* Special case for Global Lock, allow all threads */
if ((obj_desc->mutex.owner_thread->thread_id ==
- walk_state->thread->thread_id) ||
- (obj_desc->mutex.semaphore ==
- acpi_gbl_global_lock_semaphore)) {
+ walk_state->thread->thread_id) ||
+ (obj_desc->mutex.semaphore ==
+ acpi_gbl_global_lock_semaphore)) {
/*
* The mutex is already owned by this thread,
* just increment the acquisition depth
*/
obj_desc->mutex.acquisition_depth++;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
/* Acquire the mutex, wait if necessary */
- status = acpi_ex_system_acquire_mutex (time_desc, obj_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_system_acquire_mutex(time_desc, obj_desc);
+ if (ACPI_FAILURE(status)) {
/* Includes failure from a timeout on time_desc */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Have the mutex: update mutex and walk info and save the sync_level */
- obj_desc->mutex.owner_thread = walk_state->thread;
+ obj_desc->mutex.owner_thread = walk_state->thread;
obj_desc->mutex.acquisition_depth = 1;
- obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
+ obj_desc->mutex.original_sync_level =
+ walk_state->thread->current_sync_level;
walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
/* Link the mutex to the current thread for force-unlock at method exit */
- acpi_ex_link_mutex (obj_desc, walk_state->thread);
+ acpi_ex_link_mutex(obj_desc, walk_state->thread);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_mutex
@@ -241,48 +223,40 @@ acpi_ex_acquire_mutex (
******************************************************************************/
acpi_status
-acpi_ex_release_mutex (
- union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_release_mutex");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_release_mutex");
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* The mutex must have been previously acquired in order to release it */
if (!obj_desc->mutex.owner_thread) {
- ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], not acquired\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
}
/* Sanity check -- we must have a valid thread ID */
if (!walk_state->thread) {
- ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
* The Mutex is owned, but this thread must be the owner.
* Special case for Global Lock, any thread can release
*/
- if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
- (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
- ACPI_REPORT_ERROR ((
- "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
- walk_state->thread->thread_id,
- acpi_ut_get_node_name (obj_desc->mutex.node),
- obj_desc->mutex.owner_thread->thread_id));
- return_ACPI_STATUS (AE_AML_NOT_OWNER);
+ if ((obj_desc->mutex.owner_thread->thread_id !=
+ walk_state->thread->thread_id)
+ && (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
+ ACPI_REPORT_ERROR(("Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id));
+ return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
/*
@@ -290,10 +264,8 @@ acpi_ex_release_mutex (
* equal to the current sync level
*/
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
- ACPI_REPORT_ERROR ((
- "Cannot release Mutex [%4.4s], incorrect sync_level\n",
- acpi_ut_get_node_name (obj_desc->mutex.node)));
- return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
+ ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node)));
+ return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
/* Match multiple Acquires with multiple Releases */
@@ -302,26 +274,26 @@ acpi_ex_release_mutex (
if (obj_desc->mutex.acquisition_depth != 0) {
/* Just decrement the depth and return */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Unlink the mutex from the owner's list */
- acpi_ex_unlink_mutex (obj_desc);
+ acpi_ex_unlink_mutex(obj_desc);
/* Release the mutex */
- status = acpi_ex_system_release_mutex (obj_desc);
+ status = acpi_ex_system_release_mutex(obj_desc);
/* Update the mutex and walk state, restore sync_level before acquire */
obj_desc->mutex.owner_thread = NULL;
- walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
+ walk_state->thread->current_sync_level =
+ obj_desc->mutex.original_sync_level;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_all_mutexes
@@ -334,17 +306,13 @@ acpi_ex_release_mutex (
*
******************************************************************************/
-void
-acpi_ex_release_all_mutexes (
- struct acpi_thread_state *thread)
+void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
{
- union acpi_operand_object *next = thread->acquired_mutex_list;
- union acpi_operand_object *this;
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_operand_object *next = thread->acquired_mutex_list;
+ union acpi_operand_object *this;
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Traverse the list of owned mutexes, releasing each one */
@@ -353,13 +321,13 @@ acpi_ex_release_all_mutexes (
next = this->mutex.next;
this->mutex.acquisition_depth = 1;
- this->mutex.prev = NULL;
- this->mutex.next = NULL;
+ this->mutex.prev = NULL;
+ this->mutex.next = NULL;
- /* Release the mutex */
+ /* Release the mutex */
- status = acpi_ex_system_release_mutex (this);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_system_release_mutex(this);
+ if (ACPI_FAILURE(status)) {
continue;
}
@@ -372,5 +340,3 @@ acpi_ex_release_all_mutexes (
thread->current_sync_level = this->mutex.original_sync_level;
}
}
-
-
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 639f0bd3f6d8..239d8473e9a5 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -42,26 +42,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exnames")
+ACPI_MODULE_NAME("exnames")
/* Local prototypes */
-
-static char *
-acpi_ex_allocate_name_string (
- u32 prefix_count,
- u32 num_name_segs);
+static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
static acpi_status
-acpi_ex_name_segment (
- u8 **in_aml_address,
- char *name_string);
-
+acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
/*******************************************************************************
*
@@ -79,17 +71,13 @@ acpi_ex_name_segment (
*
******************************************************************************/
-static char *
-acpi_ex_allocate_name_string (
- u32 prefix_count,
- u32 num_name_segs)
+static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
{
- char *temp_ptr;
- char *name_string;
- u32 size_needed;
-
- ACPI_FUNCTION_TRACE ("ex_allocate_name_string");
+ char *temp_ptr;
+ char *name_string;
+ u32 size_needed;
+ ACPI_FUNCTION_TRACE("ex_allocate_name_string");
/*
* Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
@@ -100,20 +88,19 @@ acpi_ex_allocate_name_string (
/* Special case for root */
size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
- }
- else {
- size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
+ } else {
+ size_needed =
+ prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
}
/*
* Allocate a buffer for the name.
* This buffer must be deleted by the caller!
*/
- name_string = ACPI_MEM_ALLOCATE (size_needed);
+ name_string = ACPI_MEM_ALLOCATE(size_needed);
if (!name_string) {
- ACPI_REPORT_ERROR ((
- "ex_allocate_name_string: Could not allocate size %d\n", size_needed));
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
+ return_PTR(NULL);
}
temp_ptr = name_string;
@@ -122,23 +109,20 @@ acpi_ex_allocate_name_string (
if (prefix_count == ACPI_UINT32_MAX) {
*temp_ptr++ = AML_ROOT_PREFIX;
- }
- else {
+ } else {
while (prefix_count--) {
*temp_ptr++ = AML_PARENT_PREFIX;
}
}
-
/* Set up Dual or Multi prefixes if needed */
if (num_name_segs > 2) {
/* Set up multi prefixes */
*temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
- *temp_ptr++ = (char) num_name_segs;
- }
- else if (2 == num_name_segs) {
+ *temp_ptr++ = (char)num_name_segs;
+ } else if (2 == num_name_segs) {
/* Set up dual prefixes */
*temp_ptr++ = AML_DUAL_NAME_PREFIX;
@@ -150,7 +134,7 @@ acpi_ex_allocate_name_string (
*/
*temp_ptr = 0;
- return_PTR (name_string);
+ return_PTR(name_string);
}
/*******************************************************************************
@@ -167,19 +151,14 @@ acpi_ex_allocate_name_string (
*
******************************************************************************/
-static acpi_status
-acpi_ex_name_segment (
- u8 **in_aml_address,
- char *name_string)
+static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
{
- char *aml_address = (void *) *in_aml_address;
- acpi_status status = AE_OK;
- u32 index;
- char char_buf[5];
-
-
- ACPI_FUNCTION_TRACE ("ex_name_segment");
+ char *aml_address = (void *)*in_aml_address;
+ acpi_status status = AE_OK;
+ u32 index;
+ char char_buf[5];
+ ACPI_FUNCTION_TRACE("ex_name_segment");
/*
* If first character is a digit, then we know that we aren't looking at a
@@ -188,20 +167,20 @@ acpi_ex_name_segment (
char_buf[0] = *aml_address;
if ('0' <= char_buf[0] && char_buf[0] <= '9') {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
- return_ACPI_STATUS (AE_CTRL_PENDING);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "leading digit: %c\n",
+ char_buf[0]));
+ return_ACPI_STATUS(AE_CTRL_PENDING);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
for (index = 0;
- (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address));
- index++) {
+ (index < ACPI_NAME_SIZE)
+ && (acpi_ut_valid_acpi_character(*aml_address)); index++) {
char_buf[index] = *aml_address++;
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index]));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
}
-
/* Valid name segment */
if (index == 4) {
@@ -210,41 +189,37 @@ acpi_ex_name_segment (
char_buf[4] = '\0';
if (name_string) {
- ACPI_STRCAT (name_string, char_buf);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Appended to - %s \n", name_string));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "No Name string - %s \n", char_buf));
+ ACPI_STRCAT(name_string, char_buf);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Appended to - %s \n", name_string));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "No Name string - %s \n", char_buf));
}
- }
- else if (index == 0) {
+ } else if (index == 0) {
/*
* First character was not a valid name character,
* so we are looking at something other than a name.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Leading character is not alpha: %02Xh (not a name)\n",
- char_buf[0]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Leading character is not alpha: %02Xh (not a name)\n",
+ char_buf[0]));
status = AE_CTRL_PENDING;
- }
- else {
+ } else {
/*
* Segment started with one or more valid characters, but fewer than
* the required 4
*/
status = AE_AML_BAD_NAME;
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad character %02x in name, at %p\n",
- *aml_address, aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad character %02x in name, at %p\n",
+ *aml_address, aml_address));
}
*in_aml_address = (u8 *) aml_address;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_get_name_string
@@ -263,37 +238,32 @@ acpi_ex_name_segment (
******************************************************************************/
acpi_status
-acpi_ex_get_name_string (
- acpi_object_type data_type,
- u8 *in_aml_address,
- char **out_name_string,
- u32 *out_name_length)
+acpi_ex_get_name_string(acpi_object_type data_type,
+ u8 * in_aml_address,
+ char **out_name_string, u32 * out_name_length)
{
- acpi_status status = AE_OK;
- u8 *aml_address = in_aml_address;
- char *name_string = NULL;
- u32 num_segments;
- u32 prefix_count = 0;
- u8 has_prefix = FALSE;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address);
-
-
- if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
- ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
- ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
+ acpi_status status = AE_OK;
+ u8 *aml_address = in_aml_address;
+ char *name_string = NULL;
+ u32 num_segments;
+ u32 prefix_count = 0;
+ u8 has_prefix = FALSE;
+
+ ACPI_FUNCTION_TRACE_PTR("ex_get_name_string", aml_address);
+
+ if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
+ ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
+ ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
/* Disallow prefixes for types associated with field_unit names */
- name_string = acpi_ex_allocate_name_string (0, 1);
+ name_string = acpi_ex_allocate_name_string(0, 1);
if (!name_string) {
status = AE_NO_MEMORY;
+ } else {
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
}
- else {
- status = acpi_ex_name_segment (&aml_address, name_string);
- }
- }
- else {
+ } else {
/*
* data_type is not a field name.
* Examine first character of name for root or parent prefix operators
@@ -301,8 +271,9 @@ acpi_ex_get_name_string (
switch (*aml_address) {
case AML_ROOT_PREFIX:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "root_prefix(\\) at %p\n",
+ aml_address));
/*
* Remember that we have a root_prefix --
@@ -313,14 +284,14 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
break;
-
case AML_PARENT_PREFIX:
/* Increment past possibly multiple parent prefixes */
do {
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "parent_prefix (^) at %p\n",
+ aml_address));
aml_address++;
prefix_count++;
@@ -330,7 +301,6 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
break;
-
default:
/* Not a prefix character */
@@ -343,11 +313,13 @@ acpi_ex_get_name_string (
switch (*aml_address) {
case AML_DUAL_NAME_PREFIX:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "dual_name_prefix at %p\n",
+ aml_address));
aml_address++;
- name_string = acpi_ex_allocate_name_string (prefix_count, 2);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 2);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -357,24 +329,29 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
- status = acpi_ex_name_segment (&aml_address, name_string);
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_name_segment (&aml_address, name_string);
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ex_name_segment(&aml_address,
+ name_string);
}
break;
-
case AML_MULTI_NAME_PREFIX_OP:
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n",
- aml_address));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "multi_name_prefix at %p\n",
+ aml_address));
/* Fetch count of segments remaining in name path */
aml_address++;
num_segments = *aml_address;
- name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count,
+ num_segments);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -386,27 +363,28 @@ acpi_ex_get_name_string (
has_prefix = TRUE;
while (num_segments &&
- (status = acpi_ex_name_segment (&aml_address, name_string)) ==
- AE_OK) {
+ (status =
+ acpi_ex_name_segment(&aml_address,
+ name_string)) == AE_OK) {
num_segments--;
}
break;
-
case 0:
/* null_name valid as of 8-12-98 ASL/AML Grammar Update */
if (prefix_count == ACPI_UINT32_MAX) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "name_seg is \"\\\" followed by NULL\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "name_seg is \"\\\" followed by NULL\n"));
}
/* Consume the NULL byte */
aml_address++;
- name_string = acpi_ex_allocate_name_string (prefix_count, 0);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 0);
if (!name_string) {
status = AE_NO_MEMORY;
break;
@@ -414,18 +392,19 @@ acpi_ex_get_name_string (
break;
-
default:
/* Name segment string */
- name_string = acpi_ex_allocate_name_string (prefix_count, 1);
+ name_string =
+ acpi_ex_allocate_name_string(prefix_count, 1);
if (!name_string) {
status = AE_NO_MEMORY;
break;
}
- status = acpi_ex_name_segment (&aml_address, name_string);
+ status =
+ acpi_ex_name_segment(&aml_address, name_string);
break;
}
}
@@ -433,15 +412,20 @@ acpi_ex_get_name_string (
if (AE_CTRL_PENDING == status && has_prefix) {
/* Ran out of segments after processing a prefix */
- ACPI_REPORT_ERROR (
- ("ex_do_name: Malformed Name at %p\n", name_string));
+ ACPI_REPORT_ERROR(("ex_do_name: Malformed Name at %p\n",
+ name_string));
status = AE_AML_BAD_NAME;
}
+ if (ACPI_FAILURE(status)) {
+ if (name_string) {
+ ACPI_MEM_FREE(name_string);
+ }
+ return_ACPI_STATUS(status);
+ }
+
*out_name_string = name_string;
*out_name_length = (u32) (aml_address - in_aml_address);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index dbdf8262ba00..97e34542f5e4 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
@@ -50,10 +49,8 @@
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg1")
-
+ACPI_MODULE_NAME("exoparg1")
/*!
* Naming convention for AML interpreter execution routines.
@@ -76,7 +73,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_0A_0T_1R
@@ -88,59 +84,53 @@
* DESCRIPTION: Execute operator with no operands, one return value
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_0A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *return_desc = NULL;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_0A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ acpi_status status = AE_OK;
+ union acpi_operand_object *return_desc = NULL;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_TIMER_OP: /* Timer () */
+ case AML_TIMER_OP: /* Timer () */
/* Create a return object of type Integer */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
-
- return_desc->integer.value = acpi_os_get_timer ();
+#if ACPI_MACHINE_WIDTH != 16
+ return_desc->integer.value = acpi_os_get_timer();
+#endif
break;
- default: /* Unknown opcode */
+ default: /* Unknown opcode */
- ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
-cleanup:
-
- if (!walk_state->result_obj) {
- walk_state->result_obj = return_desc;
- }
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
+ } else {
+ /* Save the return value */
+
+ walk_state->result_obj = return_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_0T_0R
@@ -154,69 +144,58 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_0T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_RELEASE_OP: /* Release (mutex_object) */
+ case AML_RELEASE_OP: /* Release (mutex_object) */
- status = acpi_ex_release_mutex (operand[0], walk_state);
+ status = acpi_ex_release_mutex(operand[0], walk_state);
break;
+ case AML_RESET_OP: /* Reset (event_object) */
- case AML_RESET_OP: /* Reset (event_object) */
-
- status = acpi_ex_system_reset_event (operand[0]);
+ status = acpi_ex_system_reset_event(operand[0]);
break;
+ case AML_SIGNAL_OP: /* Signal (event_object) */
- case AML_SIGNAL_OP: /* Signal (event_object) */
-
- status = acpi_ex_system_signal_event (operand[0]);
+ status = acpi_ex_system_signal_event(operand[0]);
break;
+ case AML_SLEEP_OP: /* Sleep (msec_time) */
- case AML_SLEEP_OP: /* Sleep (msec_time) */
-
- status = acpi_ex_system_do_suspend (operand[0]->integer.value);
+ status = acpi_ex_system_do_suspend(operand[0]->integer.value);
break;
+ case AML_STALL_OP: /* Stall (usec_time) */
- case AML_STALL_OP: /* Stall (usec_time) */
-
- status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value);
+ status =
+ acpi_ex_system_do_stall((u32) operand[0]->integer.value);
break;
+ case AML_UNLOAD_OP: /* Unload (Handle) */
- case AML_UNLOAD_OP: /* Unload (Handle) */
-
- status = acpi_ex_unload_table (operand[0]);
+ status = acpi_ex_unload_table(operand[0]);
break;
+ default: /* Unknown opcode */
- default: /* Unknown opcode */
-
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_1T_0R
@@ -230,41 +209,34 @@ acpi_ex_opcode_1A_0T_0R (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_1T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object **operand = &walk_state->operands[0];
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ acpi_status status = AE_OK;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
case AML_LOAD_OP:
- status = acpi_ex_load_op (operand[0], operand[1], walk_state);
+ status = acpi_ex_load_op(operand[0], operand[1], walk_state);
break;
- default: /* Unknown opcode */
+ default: /* Unknown opcode */
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
+ cleanup:
-cleanup:
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_1T_1R
@@ -278,23 +250,19 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- union acpi_operand_object *return_desc2 = NULL;
- u32 temp32;
- u32 i;
- acpi_integer power_of_ten;
- acpi_integer digit;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
-
+ acpi_status status = AE_OK;
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ union acpi_operand_object *return_desc2 = NULL;
+ u32 temp32;
+ u32 i;
+ acpi_integer power_of_ten;
+ acpi_integer digit;
+
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -308,20 +276,19 @@ acpi_ex_opcode_1A_1T_1R (
/* Create a return object of type Integer for these opcodes */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
switch (walk_state->opcode) {
- case AML_BIT_NOT_OP: /* Not (Operand, Result) */
+ case AML_BIT_NOT_OP: /* Not (Operand, Result) */
return_desc->integer.value = ~operand[0]->integer.value;
break;
-
- case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
+ case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
return_desc->integer.value = operand[0]->integer.value;
@@ -330,15 +297,14 @@ acpi_ex_opcode_1A_1T_1R (
* endian unsigned value, so this boundary condition is valid.
*/
for (temp32 = 0; return_desc->integer.value &&
- temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
+ temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
return_desc->integer.value >>= 1;
}
return_desc->integer.value = temp32;
break;
-
- case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
+ case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
return_desc->integer.value = operand[0]->integer.value;
@@ -347,18 +313,17 @@ acpi_ex_opcode_1A_1T_1R (
* endian unsigned value, so this boundary condition is valid.
*/
for (temp32 = 0; return_desc->integer.value &&
- temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
+ temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
return_desc->integer.value <<= 1;
}
/* Since the bit position is one-based, subtract from 33 (65) */
return_desc->integer.value = temp32 == 0 ? 0 :
- (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
+ (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
break;
-
- case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
+ case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
/*
* The 64-bit ACPI integer can hold 16 4-bit BCD characters
@@ -371,7 +336,9 @@ acpi_ex_opcode_1A_1T_1R (
/* Convert each BCD digit (each is one nybble wide) */
- for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
+ for (i = 0;
+ (i < acpi_gbl_integer_nybble_width) && (digit > 0);
+ i++) {
/* Get the least significant 4-bit BCD digit */
temp32 = ((u32) digit) & 0xF;
@@ -379,9 +346,9 @@ acpi_ex_opcode_1A_1T_1R (
/* Check the range of the digit */
if (temp32 > 9) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "BCD digit too large (not decimal): 0x%X\n",
- temp32));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "BCD digit too large (not decimal): 0x%X\n",
+ temp32));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
@@ -389,8 +356,8 @@ acpi_ex_opcode_1A_1T_1R (
/* Sum the digit into the result with the current power of 10 */
- return_desc->integer.value += (((acpi_integer) temp32) *
- power_of_ten);
+ return_desc->integer.value +=
+ (((acpi_integer) temp32) * power_of_ten);
/* Shift to next BCD digit */
@@ -402,45 +369,50 @@ acpi_ex_opcode_1A_1T_1R (
}
break;
-
- case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
+ case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
return_desc->integer.value = 0;
digit = operand[0]->integer.value;
/* Each BCD digit is one nybble wide */
- for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) {
- (void) acpi_ut_short_divide (digit, 10, &digit, &temp32);
+ for (i = 0;
+ (i < acpi_gbl_integer_nybble_width) && (digit > 0);
+ i++) {
+ (void)acpi_ut_short_divide(digit, 10, &digit,
+ &temp32);
/*
* Insert the BCD digit that resides in the
* remainder from above
*/
- return_desc->integer.value |= (((acpi_integer) temp32) <<
- ACPI_MUL_4 (i));
+ return_desc->integer.value |=
+ (((acpi_integer) temp32) << ACPI_MUL_4(i));
}
/* Overflow if there is any data left in Digit */
if (digit > 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Integer too large to convert to BCD: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (operand[0]->integer.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Integer too large to convert to BCD: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(operand
+ [0]->
+ integer.
+ value)));
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
}
break;
-
- case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */
+ case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */
/*
* This op is a little strange because the internal return value is
* different than the return value stored in the result descriptor
* (There are really two return values)
*/
- if ((struct acpi_namespace_node *) operand[0] == acpi_gbl_root_node) {
+ if ((struct acpi_namespace_node *)operand[0] ==
+ acpi_gbl_root_node) {
/*
* This means that the object does not exist in the namespace,
* return FALSE
@@ -451,38 +423,38 @@ acpi_ex_opcode_1A_1T_1R (
/* Get the object reference, store it, and remove our reference */
- status = acpi_ex_get_object_reference (operand[0],
- &return_desc2, walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_get_object_reference(operand[0],
+ &return_desc2,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_store (return_desc2, operand[1], walk_state);
- acpi_ut_remove_reference (return_desc2);
+ status =
+ acpi_ex_store(return_desc2, operand[1], walk_state);
+ acpi_ut_remove_reference(return_desc2);
/* The object exists in the namespace, return TRUE */
return_desc->integer.value = ACPI_INTEGER_MAX;
goto cleanup;
-
default:
/* No other opcodes get here */
break;
}
break;
-
- case AML_STORE_OP: /* Store (Source, Target) */
+ case AML_STORE_OP: /* Store (Source, Target) */
/*
* A store operand is typically a number, string, buffer or lvalue
* Be careful about deleting the source object,
* since the object itself may have been stored.
*/
- status = acpi_ex_store (operand[0], operand[1], walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_store(operand[0], operand[1], walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* It is possible that the Store already produced a return object */
@@ -495,92 +467,84 @@ acpi_ex_opcode_1A_1T_1R (
* cancel out, and we simply don't do anything.
*/
walk_state->result_obj = operand[0];
- walk_state->operands[0] = NULL; /* Prevent deletion */
+ walk_state->operands[0] = NULL; /* Prevent deletion */
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
+ /*
+ * ACPI 2.0 Opcodes
+ */
+ case AML_COPY_OP: /* Copy (Source, Target) */
- /*
- * ACPI 2.0 Opcodes
- */
- case AML_COPY_OP: /* Copy (Source, Target) */
-
- status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc,
- walk_state);
+ status =
+ acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
+ walk_state);
break;
+ case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
- case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
-
- status = acpi_ex_convert_to_string (operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_DECIMAL);
+ status = acpi_ex_convert_to_string(operand[0], &return_desc,
+ ACPI_EXPLICIT_CONVERT_DECIMAL);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
- case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
-
- status = acpi_ex_convert_to_string (operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(operand[0], &return_desc,
+ ACPI_EXPLICIT_CONVERT_HEX);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
- case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
-
- status = acpi_ex_convert_to_buffer (operand[0], &return_desc);
+ status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
break;
+ case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
- case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
-
- status = acpi_ex_convert_to_integer (operand[0], &return_desc,
- ACPI_ANY_BASE);
+ status = acpi_ex_convert_to_integer(operand[0], &return_desc,
+ ACPI_ANY_BASE);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
}
break;
-
- case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
- case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
+ case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
+ case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
/* These are two obsolete opcodes */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%s is obsolete and not implemented\n",
- acpi_ps_get_opcode_name (walk_state->opcode)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s is obsolete and not implemented\n",
+ acpi_ps_get_opcode_name(walk_state->opcode)));
status = AE_SUPPORT;
goto cleanup;
+ default: /* Unknown opcode */
- default: /* Unknown opcode */
-
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Store the return value computed above into the target object */
- status = acpi_ex_store (return_desc, operand[1], walk_state);
+ status = acpi_ex_store(return_desc, operand[1], walk_state);
}
-
-cleanup:
+ cleanup:
if (!walk_state->result_obj) {
walk_state->result_obj = return_desc;
@@ -588,14 +552,13 @@ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_1A_0T_1R
@@ -608,28 +571,24 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_1A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *temp_desc;
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- u32 type;
- acpi_integer value;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *temp_desc;
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ u32 type;
+ acpi_integer value;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
switch (walk_state->opcode) {
- case AML_LNOT_OP: /* LNot (Operand) */
+ case AML_LNOT_OP: /* LNot (Operand) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -644,15 +603,14 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
- case AML_DECREMENT_OP: /* Decrement (Operand) */
- case AML_INCREMENT_OP: /* Increment (Operand) */
+ case AML_DECREMENT_OP: /* Decrement (Operand) */
+ case AML_INCREMENT_OP: /* Increment (Operand) */
/*
* Create a new integer. Can't just get the base integer and
* increment it because it may be an Arg or Field.
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -663,10 +621,11 @@ acpi_ex_opcode_1A_0T_1R (
* NS Node or an internal object.
*/
temp_desc = operand[0];
- if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
+ ACPI_DESC_TYPE_OPERAND) {
/* Internal reference object - prevent deletion */
- acpi_ut_add_reference (temp_desc);
+ acpi_ut_add_reference(temp_desc);
}
/*
@@ -676,11 +635,15 @@ acpi_ex_opcode_1A_0T_1R (
* NOTE: We use LNOT_OP here in order to force resolution of the
* reference operand to an actual integer.
*/
- status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n",
- acpi_ps_get_opcode_name (walk_state->opcode),
- acpi_format_exception(status)));
+ status =
+ acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s: bad operand(s) %s\n",
+ acpi_ps_get_opcode_name(walk_state->
+ opcode),
+ acpi_format_exception(status)));
goto cleanup;
}
@@ -690,25 +653,25 @@ acpi_ex_opcode_1A_0T_1R (
* Perform the actual increment or decrement
*/
if (walk_state->opcode == AML_INCREMENT_OP) {
- return_desc->integer.value = temp_desc->integer.value +1;
- }
- else {
- return_desc->integer.value = temp_desc->integer.value -1;
+ return_desc->integer.value =
+ temp_desc->integer.value + 1;
+ } else {
+ return_desc->integer.value =
+ temp_desc->integer.value - 1;
}
/* Finished with this Integer object */
- acpi_ut_remove_reference (temp_desc);
+ acpi_ut_remove_reference(temp_desc);
/*
* Store the result back (indirectly) through the original
* Reference object
*/
- status = acpi_ex_store (return_desc, operand[0], walk_state);
+ status = acpi_ex_store(return_desc, operand[0], walk_state);
break;
-
- case AML_TYPE_OP: /* object_type (source_object) */
+ case AML_TYPE_OP: /* object_type (source_object) */
/*
* Note: The operand is not resolved at this point because we want to
@@ -719,13 +682,15 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the type of the base object */
- status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_multiple(walk_state, operand[0], &type,
+ NULL);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Allocate a descriptor to hold the type. */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -734,8 +699,7 @@ acpi_ex_opcode_1A_0T_1R (
return_desc->integer.value = type;
break;
-
- case AML_SIZE_OF_OP: /* size_of (source_object) */
+ case AML_SIZE_OF_OP: /* size_of (source_object) */
/*
* Note: The operand is not resolved at this point because we want to
@@ -744,9 +708,10 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the base object */
- status = acpi_ex_resolve_multiple (walk_state,
- operand[0], &type, &temp_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_resolve_multiple(walk_state,
+ operand[0], &type,
+ &temp_desc);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -777,9 +742,9 @@ acpi_ex_opcode_1A_0T_1R (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
- acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n",
+ acpi_ut_get_type_name(type)));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
@@ -788,7 +753,7 @@ acpi_ex_opcode_1A_0T_1R (
* Now that we have the size of the object, create a result
* object to hold the value
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -797,22 +762,23 @@ acpi_ex_opcode_1A_0T_1R (
return_desc->integer.value = value;
break;
+ case AML_REF_OF_OP: /* ref_of (source_object) */
- case AML_REF_OF_OP: /* ref_of (source_object) */
-
- status = acpi_ex_get_object_reference (operand[0], &return_desc, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_get_object_reference(operand[0], &return_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
break;
-
- case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
+ case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
/* Check for a method local or argument, or standalone String */
- if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) {
- switch (ACPI_GET_OBJECT_TYPE (operand[0])) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+ ACPI_DESC_TYPE_NAMED) {
+ switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
case ACPI_TYPE_LOCAL_REFERENCE:
/*
* This is a deref_of (local_x | arg_x)
@@ -825,11 +791,12 @@ acpi_ex_opcode_1A_0T_1R (
/* Set Operand[0] to the value of the local/arg */
- status = acpi_ds_method_data_get_value (
- operand[0]->reference.opcode,
- operand[0]->reference.offset,
- walk_state, &temp_desc);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ds_method_data_get_value
+ (operand[0]->reference.opcode,
+ operand[0]->reference.offset,
+ walk_state, &temp_desc);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -837,7 +804,7 @@ acpi_ex_opcode_1A_0T_1R (
* Delete our reference to the input object and
* point to the object just retrieved
*/
- acpi_ut_remove_reference (operand[0]);
+ acpi_ut_remove_reference(operand[0]);
operand[0] = temp_desc;
break;
@@ -845,8 +812,9 @@ acpi_ex_opcode_1A_0T_1R (
/* Get the object to which the reference refers */
- temp_desc = operand[0]->reference.object;
- acpi_ut_remove_reference (operand[0]);
+ temp_desc =
+ operand[0]->reference.object;
+ acpi_ut_remove_reference(operand[0]);
operand[0] = temp_desc;
break;
@@ -857,7 +825,6 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
case ACPI_TYPE_STRING:
/*
@@ -868,22 +835,28 @@ acpi_ex_opcode_1A_0T_1R (
* 2) Dereference the node to an actual object. Could be a
* Field, so we need to resolve the node to a value.
*/
- status = acpi_ns_get_node_by_path (operand[0]->string.pointer,
- walk_state->scope_info->scope.node,
- ACPI_NS_SEARCH_PARENT,
- ACPI_CAST_INDIRECT_PTR (
- struct acpi_namespace_node, &return_desc));
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ns_get_node_by_path(operand[0]->string.
+ pointer,
+ walk_state->
+ scope_info->scope.
+ node,
+ ACPI_NS_SEARCH_PARENT,
+ ACPI_CAST_INDIRECT_PTR
+ (struct
+ acpi_namespace_node,
+ &return_desc));
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_resolve_node_to_value (
- ACPI_CAST_INDIRECT_PTR (
- struct acpi_namespace_node, &return_desc),
- walk_state);
+ status =
+ acpi_ex_resolve_node_to_value
+ (ACPI_CAST_INDIRECT_PTR
+ (struct acpi_namespace_node, &return_desc),
+ walk_state);
goto cleanup;
-
default:
status = AE_AML_OPERAND_TYPE;
@@ -893,17 +866,20 @@ acpi_ex_opcode_1A_0T_1R (
/* Operand[0] may have changed from the code above */
- if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
+ ACPI_DESC_TYPE_NAMED) {
/*
* This is a deref_of (object_reference)
* Get the actual object from the Node (This is the dereference).
* This case may only happen when a local_x or arg_x is
* dereferenced above.
*/
- return_desc = acpi_ns_get_attached_object (
- (struct acpi_namespace_node *) operand[0]);
- }
- else {
+ return_desc = acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)
+ operand[0]);
+ acpi_ut_add_reference(return_desc);
+ } else {
/*
* This must be a reference object produced by either the
* Index() or ref_of() operator
@@ -918,7 +894,8 @@ acpi_ex_opcode_1A_0T_1R (
switch (operand[0]->reference.target_type) {
case ACPI_TYPE_BUFFER_FIELD:
- temp_desc = operand[0]->reference.object;
+ temp_desc =
+ operand[0]->reference.object;
/*
* Create a new object that contains one element of the
@@ -928,7 +905,9 @@ acpi_ex_opcode_1A_0T_1R (
* sub-buffer of the main buffer, it is only a pointer to a
* single element (byte) of the buffer!
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc =
+ acpi_ut_create_internal_object
+ (ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -940,66 +919,63 @@ acpi_ex_opcode_1A_0T_1R (
* reference to the buffer itself.
*/
return_desc->integer.value =
- temp_desc->buffer.pointer[operand[0]->reference.offset];
+ temp_desc->buffer.
+ pointer[operand[0]->reference.
+ offset];
break;
-
case ACPI_TYPE_PACKAGE:
/*
* Return the referenced element of the package. We must
* add another reference to the referenced object, however.
*/
- return_desc = *(operand[0]->reference.where);
- if (!return_desc) {
- /*
- * We can't return a NULL dereferenced value. This is
- * an uninitialized package element and is thus a
- * severe error.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "NULL package element obj %p\n",
- operand[0]));
- status = AE_AML_UNINITIALIZED_ELEMENT;
- goto cleanup;
+ return_desc =
+ *(operand[0]->reference.where);
+ if (return_desc) {
+ acpi_ut_add_reference
+ (return_desc);
}
- acpi_ut_add_reference (return_desc);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown Index target_type %X in obj %p\n",
- operand[0]->reference.target_type, operand[0]));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown Index target_type %X in obj %p\n",
+ operand[0]->reference.
+ target_type,
+ operand[0]));
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
break;
-
case AML_REF_OF_OP:
return_desc = operand[0]->reference.object;
- if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) ==
- ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
- return_desc = acpi_ns_get_attached_object (
- (struct acpi_namespace_node *) return_desc);
+ return_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)
+ return_desc);
}
/* Add another reference to the object! */
- acpi_ut_add_reference (return_desc);
+ acpi_ut_add_reference(return_desc);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown opcode in ref(%p) - %X\n",
- operand[0], operand[0]->reference.opcode));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown opcode in ref(%p) - %X\n",
+ operand[0],
+ operand[0]->reference.
+ opcode));
status = AE_TYPE;
goto cleanup;
@@ -1007,25 +983,21 @@ acpi_ex_opcode_1A_0T_1R (
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
walk_state->result_obj = return_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 7429032c2b6c..8d70c6beef00 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -41,17 +41,14 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg2")
-
+ACPI_MODULE_NAME("exoparg2")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,8 +71,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_0R
@@ -90,29 +85,24 @@
* ALLOCATION: Deletes both operands
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_2A_0T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_namespace_node *node;
- u32 value;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_namespace_node *node;
+ u32 value;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the opcode */
switch (walk_state->opcode) {
- case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
+ case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
/* The first operand is a namespace node */
- node = (struct acpi_namespace_node *) operand[0];
+ node = (struct acpi_namespace_node *)operand[0];
/* Second value is the notify value */
@@ -120,15 +110,14 @@ acpi_ex_opcode_2A_0T_0R (
/* Are notifies allowed on this object? */
- if (!acpi_ev_is_notify_object (node)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unexpected notify object type [%s]\n",
- acpi_ut_get_type_name (node->type)));
+ if (!acpi_ev_is_notify_object(node)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unexpected notify object type [%s]\n",
+ acpi_ut_get_type_name(node->type)));
status = AE_AML_OPERAND_TYPE;
break;
}
-
#ifdef ACPI_GPE_NOTIFY_CHECK
/*
* GPE method wake/notify check. Here, we want to ensure that we
@@ -144,12 +133,14 @@ acpi_ex_opcode_2A_0T_0R (
* If all three cases are true, this is a wake-only GPE that should
* be disabled at runtime.
*/
- if (value == 2) /* device_wake */ {
- status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
- if (ACPI_FAILURE (status)) {
+ if (value == 2) { /* device_wake */
+ status =
+ acpi_ev_check_for_wake_only_gpe(walk_state->
+ gpe_event_info);
+ if (ACPI_FAILURE(status)) {
/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
- return_ACPI_STATUS (AE_OK)
+ return_ACPI_STATUS(AE_OK)
}
}
#endif
@@ -161,21 +152,18 @@ acpi_ex_opcode_2A_0T_0R (
* from this thread -- because handlers may in turn run other
* control methods.
*/
- status = acpi_ev_queue_notify_request (node, value);
+ status = acpi_ev_queue_notify_request(node, value);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_2T_1R
@@ -189,19 +177,15 @@ acpi_ex_opcode_2A_0T_0R (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_2T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc1 = NULL;
- union acpi_operand_object *return_desc2 = NULL;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc1 = NULL;
+ union acpi_operand_object *return_desc2 = NULL;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
@@ -210,13 +194,15 @@ acpi_ex_opcode_2A_2T_1R (
/* Divide (Dividend, Divisor, remainder_result quotient_result) */
- return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc1 =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc1) {
status = AE_NO_MEMORY;
goto cleanup;
}
- return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc2 =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc2) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -224,33 +210,31 @@ acpi_ex_opcode_2A_2T_1R (
/* Quotient to return_desc1, remainder to return_desc2 */
- status = acpi_ut_divide (operand[0]->integer.value,
- operand[1]->integer.value,
- &return_desc1->integer.value,
- &return_desc2->integer.value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_divide(operand[0]->integer.value,
+ operand[1]->integer.value,
+ &return_desc1->integer.value,
+ &return_desc2->integer.value);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the results to the target reference operands */
- status = acpi_ex_store (return_desc2, operand[2], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc2, operand[2], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_ex_store (return_desc1, operand[3], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc1, operand[3], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -258,24 +242,22 @@ acpi_ex_opcode_2A_2T_1R (
walk_state->result_obj = return_desc1;
-
-cleanup:
+ cleanup:
/*
* Since the remainder is not returned indirectly, remove a reference to
* it. Only the quotient is returned indirectly.
*/
- acpi_ut_remove_reference (return_desc2);
+ acpi_ut_remove_reference(return_desc2);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Delete the return object */
- acpi_ut_remove_reference (return_desc1);
+ acpi_ut_remove_reference(return_desc1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_1T_1R
@@ -289,42 +271,39 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_integer index;
- acpi_status status = AE_OK;
- acpi_size length;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_integer index;
+ acpi_status status = AE_OK;
+ acpi_size length;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_1T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
if (walk_state->op_info->flags & AML_MATH) {
/* All simple math opcodes (add, etc.) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
- operand[0]->integer.value,
- operand[1]->integer.value);
+ return_desc->integer.value =
+ acpi_ex_do_math_op(walk_state->opcode,
+ operand[0]->integer.value,
+ operand[1]->integer.value);
goto store_result_to_target;
}
switch (walk_state->opcode) {
- case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
+ case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -332,21 +311,18 @@ acpi_ex_opcode_2A_1T_1R (
/* return_desc will contain the remainder */
- status = acpi_ut_divide (operand[0]->integer.value,
- operand[1]->integer.value,
- NULL,
- &return_desc->integer.value);
+ status = acpi_ut_divide(operand[0]->integer.value,
+ operand[1]->integer.value,
+ NULL, &return_desc->integer.value);
break;
+ case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
- case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
-
- status = acpi_ex_do_concatenate (operand[0], operand[1],
- &return_desc, walk_state);
+ status = acpi_ex_do_concatenate(operand[0], operand[1],
+ &return_desc, walk_state);
break;
-
- case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
+ case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
/*
* Input object is guaranteed to be a buffer at this point (it may have
@@ -365,8 +341,8 @@ acpi_ex_opcode_2A_1T_1R (
*/
length = 0;
while ((length < operand[0]->buffer.length) &&
- (length < operand[1]->integer.value) &&
- (operand[0]->buffer.pointer[length])) {
+ (length < operand[1]->integer.value) &&
+ (operand[0]->buffer.pointer[length])) {
length++;
if (length > ACPI_MAX_STRING_CONVERSION) {
status = AE_AML_STRING_LIMIT;
@@ -376,33 +352,32 @@ acpi_ex_opcode_2A_1T_1R (
/* Allocate a new string object */
- return_desc = acpi_ut_create_string_object (length);
+ return_desc = acpi_ut_create_string_object(length);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Copy the raw buffer data with no transform. NULL terminated already*/
+ /* Copy the raw buffer data with no transform. NULL terminated already */
- ACPI_MEMCPY (return_desc->string.pointer,
- operand[0]->buffer.pointer, length);
+ ACPI_MEMCPY(return_desc->string.pointer,
+ operand[0]->buffer.pointer, length);
break;
-
case AML_CONCAT_RES_OP:
/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
- status = acpi_ex_concat_template (operand[0], operand[1],
- &return_desc, walk_state);
+ status = acpi_ex_concat_template(operand[0], operand[1],
+ &return_desc, walk_state);
break;
-
- case AML_INDEX_OP: /* Index (Source Index Result) */
+ case AML_INDEX_OP: /* Index (Source Index Result) */
/* Create the internal return object */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
+ return_desc =
+ acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -412,76 +387,75 @@ acpi_ex_opcode_2A_1T_1R (
/* At this point, the Source operand is a Package, Buffer, or String */
- if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) {
/* Object to be indexed is a Package */
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index value (%X%8.8X) beyond package end (%X)\n",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
- return_desc->reference.object = operand[0];
- return_desc->reference.where = &operand[0]->package.elements [
- index];
- }
- else {
+ return_desc->reference.object = operand[0];
+ return_desc->reference.where =
+ &operand[0]->package.elements[index];
+ } else {
/* Object to be indexed is a Buffer/String */
if (index >= operand[0]->buffer.length) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index value (%X%8.8X) beyond end of buffer (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->buffer.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index value (%X%8.8X) beyond end of buffer (%X)\n",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->buffer.length));
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
- return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
- return_desc->reference.object = operand[0];
+ return_desc->reference.target_type =
+ ACPI_TYPE_BUFFER_FIELD;
+ return_desc->reference.object = operand[0];
}
/*
* Add a reference to the target package/buffer/string for the life
* of the index.
*/
- acpi_ut_add_reference (operand[0]);
+ acpi_ut_add_reference(operand[0]);
/* Complete the Index reference object */
- return_desc->reference.opcode = AML_INDEX_OP;
- return_desc->reference.offset = (u32) index;
+ return_desc->reference.opcode = AML_INDEX_OP;
+ return_desc->reference.offset = (u32) index;
/* Store the reference to the Target */
- status = acpi_ex_store (return_desc, operand[2], walk_state);
+ status = acpi_ex_store(return_desc, operand[2], walk_state);
/* Return the reference */
walk_state->result_obj = return_desc;
goto cleanup;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
break;
}
+ store_result_to_target:
-store_result_to_target:
-
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Store the result of the operation (which is now in return_desc) into
* the Target descriptor.
*/
- status = acpi_ex_store (return_desc, operand[2], walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_store(return_desc, operand[2], walk_state);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -490,19 +464,17 @@ store_result_to_target:
}
}
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_2A_0T_1R
@@ -515,23 +487,19 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_2A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- u8 logical_result = FALSE;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ u8 logical_result = FALSE;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
/* Create the internal return object */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -542,50 +510,48 @@ acpi_ex_opcode_2A_0T_1R (
if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
/* logical_op (Operand0, Operand1) */
- status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
- operand[0]->integer.value, operand[1]->integer.value,
- &logical_result);
+ status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
+ operand[0]->integer.
+ value,
+ operand[1]->integer.
+ value, &logical_result);
goto store_logical_result;
- }
- else if (walk_state->op_info->flags & AML_LOGICAL) {
+ } else if (walk_state->op_info->flags & AML_LOGICAL) {
/* logical_op (Operand0, Operand1) */
- status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
- operand[1], &logical_result);
+ status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
+ operand[1], &logical_result);
goto store_logical_result;
}
switch (walk_state->opcode) {
- case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
+ case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
- status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
+ status =
+ acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
if (status == AE_TIME) {
- logical_result = TRUE; /* TRUE = Acquire timed out */
+ logical_result = TRUE; /* TRUE = Acquire timed out */
status = AE_OK;
}
break;
+ case AML_WAIT_OP: /* Wait (event_object, Timeout) */
- case AML_WAIT_OP: /* Wait (event_object, Timeout) */
-
- status = acpi_ex_system_wait_event (operand[1], operand[0]);
+ status = acpi_ex_system_wait_event(operand[1], operand[0]);
if (status == AE_TIME) {
- logical_result = TRUE; /* TRUE, Wait timed out */
+ logical_result = TRUE; /* TRUE, Wait timed out */
status = AE_OK;
}
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
-
-store_logical_result:
+ store_logical_result:
/*
* Set return value to according to logical_result. logical TRUE (all ones)
* Default is FALSE (zero)
@@ -596,16 +562,13 @@ store_logical_result:
walk_state->result_obj = return_desc;
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 23b068adbf58..483365777670 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -42,16 +42,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg3")
-
+ACPI_MODULE_NAME("exoparg3")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,8 +71,6 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_0T_0R
@@ -87,61 +82,53 @@
* DESCRIPTION: Execute Triadic operator (3 operands)
*
******************************************************************************/
-
-acpi_status
-acpi_ex_opcode_3A_0T_0R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- struct acpi_signal_fatal_info *fatal;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_0T_0R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ struct acpi_signal_fatal_info *fatal;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
- case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
+ case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
- (u32) operand[0]->integer.value,
- (u32) operand[1]->integer.value,
- (u32) operand[2]->integer.value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
+ (u32) operand[0]->integer.value,
+ (u32) operand[1]->integer.value,
+ (u32) operand[2]->integer.value));
- fatal = ACPI_MEM_ALLOCATE (sizeof (struct acpi_signal_fatal_info));
+ fatal =
+ ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
if (fatal) {
- fatal->type = (u32) operand[0]->integer.value;
- fatal->code = (u32) operand[1]->integer.value;
+ fatal->type = (u32) operand[0]->integer.value;
+ fatal->code = (u32) operand[1]->integer.value;
fatal->argument = (u32) operand[2]->integer.value;
}
/* Always signal the OS! */
- status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
+ status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
/* Might return while OS is shutting down, just continue */
- ACPI_MEM_FREE (fatal);
+ ACPI_MEM_FREE(fatal);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
+ cleanup:
-cleanup:
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_3A_1T_1R
@@ -154,31 +141,28 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_3A_1T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- char *buffer;
- acpi_status status = AE_OK;
- acpi_integer index;
- acpi_size length;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_1T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ char *buffer = NULL;
+ acpi_status status = AE_OK;
+ acpi_integer index;
+ acpi_size length;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
- case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
+ case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
/*
* Create the return object. The Source operand is guaranteed to be
* either a String or a Buffer, so just use its type.
*/
- return_desc = acpi_ut_create_internal_object (
- ACPI_GET_OBJECT_TYPE (operand[0]));
+ return_desc =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE
+ (operand[0]));
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -193,67 +177,92 @@ acpi_ex_opcode_3A_1T_1R (
* If the index is beyond the length of the String/Buffer, or if the
* requested length is zero, return a zero-length String/Buffer
*/
- if ((index < operand[0]->string.length) &&
- (length > 0)) {
- /* Truncate request if larger than the actual String/Buffer */
-
- if ((index + length) >
- operand[0]->string.length) {
- length = (acpi_size) operand[0]->string.length -
- (acpi_size) index;
- }
+ if (index >= operand[0]->string.length) {
+ length = 0;
+ }
+
+ /* Truncate request if larger than the actual String/Buffer */
+
+ else if ((index + length) > operand[0]->string.length) {
+ length = (acpi_size) operand[0]->string.length -
+ (acpi_size) index;
+ }
+
+ /* Strings always have a sub-pointer, not so for buffers */
+
+ switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
+ case ACPI_TYPE_STRING:
- /* Allocate a new buffer for the String/Buffer */
+ /* Always allocate a new buffer for the String */
- buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
+ buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
}
+ break;
- /* Copy the portion requested */
+ case ACPI_TYPE_BUFFER:
- ACPI_MEMCPY (buffer, operand[0]->string.pointer + index,
- length);
+ /* If the requested length is zero, don't allocate a buffer */
- /* Set the length of the new String/Buffer */
+ if (length > 0) {
+ /* Allocate a new buffer for the Buffer */
- return_desc->string.pointer = buffer;
- return_desc->string.length = (u32) length;
+ buffer = ACPI_MEM_CALLOCATE(length);
+ if (!buffer) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+ }
+ break;
+
+ default: /* Should not happen */
+
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
}
+ if (length > 0) {
+ /* Copy the portion requested */
+
+ ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
+ length);
+ }
+
+ /* Set the length of the new String/Buffer */
+
+ return_desc->string.pointer = buffer;
+ return_desc->string.length = (u32) length;
+
/* Mark buffer initialized */
return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Store the result in the target */
- status = acpi_ex_store (return_desc, operand[3], walk_state);
+ status = acpi_ex_store(return_desc, operand[3], walk_state);
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status) || walk_state->result_obj) {
+ acpi_ut_remove_reference(return_desc);
}
/* Set the return object and exit */
- if (!walk_state->result_obj) {
+ else {
walk_state->result_obj = return_desc;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index 17f81d42ee41..5dee77139576 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -42,16 +42,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exoparg6")
-
+ACPI_MODULE_NAME("exoparg6")
/*!
* Naming convention for AML interpreter execution routines.
@@ -74,15 +71,11 @@
* The AcpiExOpcode* functions are called via the Dispatcher component with
* fully resolved operands.
!*/
-
/* Local prototypes */
-
static u8
-acpi_ex_do_match (
- u32 match_op,
- union acpi_operand_object *package_obj,
- union acpi_operand_object *match_obj);
-
+acpi_ex_do_match(u32 match_op,
+ union acpi_operand_object *package_obj,
+ union acpi_operand_object *match_obj);
/*******************************************************************************
*
@@ -101,14 +94,12 @@ acpi_ex_do_match (
******************************************************************************/
static u8
-acpi_ex_do_match (
- u32 match_op,
- union acpi_operand_object *package_obj,
- union acpi_operand_object *match_obj)
+acpi_ex_do_match(u32 match_op,
+ union acpi_operand_object *package_obj,
+ union acpi_operand_object *match_obj)
{
- u8 logical_result = TRUE;
- acpi_status status;
-
+ u8 logical_result = TRUE;
+ acpi_status status;
/*
* Note: Since the package_obj/match_obj ordering is opposite to that of
@@ -133,9 +124,10 @@ acpi_ex_do_match (
* True if equal: (P[i] == M)
* Change to: (M == P[i])
*/
- status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -146,12 +138,13 @@ acpi_ex_do_match (
* True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
* Change to: (M >= P[i]) (M not_less than P[i])
*/
- status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
- logical_result = (u8) !logical_result;
+ logical_result = (u8) ! logical_result;
break;
case MATCH_MLT:
@@ -160,9 +153,10 @@ acpi_ex_do_match (
* True if less than: (P[i] < M)
* Change to: (M > P[i])
*/
- status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+ package_obj, &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -173,12 +167,13 @@ acpi_ex_do_match (
* True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
* Change to: (M <= P[i]) (M not_greater than P[i])
*/
- status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+ package_obj, &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
- logical_result = (u8)!logical_result;
+ logical_result = (u8) ! logical_result;
break;
case MATCH_MGT:
@@ -187,9 +182,10 @@ acpi_ex_do_match (
* True if greater than: (P[i] > M)
* Change to: (M < P[i])
*/
- status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
- &logical_result);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
+ &logical_result);
+ if (ACPI_FAILURE(status)) {
return (FALSE);
}
break;
@@ -204,7 +200,6 @@ acpi_ex_do_match (
return logical_result;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_opcode_6A_0T_1R
@@ -217,20 +212,16 @@ acpi_ex_do_match (
*
******************************************************************************/
-acpi_status
-acpi_ex_opcode_6A_0T_1R (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
{
- union acpi_operand_object **operand = &walk_state->operands[0];
- union acpi_operand_object *return_desc = NULL;
- acpi_status status = AE_OK;
- acpi_integer index;
- union acpi_operand_object *this_element;
-
-
- ACPI_FUNCTION_TRACE_STR ("ex_opcode_6A_0T_1R",
- acpi_ps_get_opcode_name (walk_state->opcode));
+ union acpi_operand_object **operand = &walk_state->operands[0];
+ union acpi_operand_object *return_desc = NULL;
+ acpi_status status = AE_OK;
+ acpi_integer index;
+ union acpi_operand_object *this_element;
+ ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R",
+ acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_MATCH_OP:
@@ -242,8 +233,9 @@ acpi_ex_opcode_6A_0T_1R (
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
- (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n"));
+ (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Match operator out of range\n"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -252,16 +244,17 @@ acpi_ex_opcode_6A_0T_1R (
index = operand[5]->integer.value;
if (index >= operand[0]->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Index (%X%8.8X) beyond package end (%X)\n",
- ACPI_FORMAT_UINT64 (index), operand[0]->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Index (%X%8.8X) beyond package end (%X)\n",
+ ACPI_FORMAT_UINT64(index),
+ operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
/* Create an integer for the return value */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -283,7 +276,7 @@ acpi_ex_opcode_6A_0T_1R (
* ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
- for ( ; index < operand[0]->package.count; index++) {
+ for (; index < operand[0]->package.count; index++) {
/* Get the current package element */
this_element = operand[0]->package.elements[index];
@@ -299,13 +292,13 @@ acpi_ex_opcode_6A_0T_1R (
* (proceed to next iteration of enclosing for loop) signifies a
* non-match.
*/
- if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
- this_element, operand[2])) {
+ if (!acpi_ex_do_match((u32) operand[1]->integer.value,
+ this_element, operand[2])) {
continue;
}
- if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
- this_element, operand[4])) {
+ if (!acpi_ex_do_match((u32) operand[3]->integer.value,
+ this_element, operand[4])) {
continue;
}
@@ -316,31 +309,27 @@ acpi_ex_opcode_6A_0T_1R (
}
break;
-
case AML_LOAD_TABLE_OP:
- status = acpi_ex_load_table_op (walk_state, &return_desc);
+ status = acpi_ex_load_table_op(walk_state, &return_desc);
break;
-
default:
- ACPI_REPORT_ERROR (("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n",
- walk_state->opcode));
+ ACPI_REPORT_ERROR(("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
walk_state->result_obj = return_desc;
-
-cleanup:
+ cleanup:
/* Delete return object on error */
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (return_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(return_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index c9e3c68b5549..7476c363e407 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -42,32 +42,24 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exprep")
+ACPI_MODULE_NAME("exprep")
/* Local prototypes */
-
static u32
-acpi_ex_decode_field_access (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u32 *return_byte_alignment);
-
+acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
+ u8 field_flags, u32 * return_byte_alignment);
#ifdef ACPI_UNDER_DEVELOPMENT
static u32
-acpi_ex_generate_access (
- u32 field_bit_offset,
- u32 field_bit_length,
- u32 region_length);
+acpi_ex_generate_access(u32 field_bit_offset,
+ u32 field_bit_length, u32 region_length);
/*******************************************************************************
*
@@ -92,39 +84,36 @@ acpi_ex_generate_access (
******************************************************************************/
static u32
-acpi_ex_generate_access (
- u32 field_bit_offset,
- u32 field_bit_length,
- u32 region_length)
+acpi_ex_generate_access(u32 field_bit_offset,
+ u32 field_bit_length, u32 region_length)
{
- u32 field_byte_length;
- u32 field_byte_offset;
- u32 field_byte_end_offset;
- u32 access_byte_width;
- u32 field_start_offset;
- u32 field_end_offset;
- u32 minimum_access_width = 0xFFFFFFFF;
- u32 minimum_accesses = 0xFFFFFFFF;
- u32 accesses;
-
-
- ACPI_FUNCTION_TRACE ("ex_generate_access");
-
+ u32 field_byte_length;
+ u32 field_byte_offset;
+ u32 field_byte_end_offset;
+ u32 access_byte_width;
+ u32 field_start_offset;
+ u32 field_end_offset;
+ u32 minimum_access_width = 0xFFFFFFFF;
+ u32 minimum_accesses = 0xFFFFFFFF;
+ u32 accesses;
+
+ ACPI_FUNCTION_TRACE("ex_generate_access");
/* Round Field start offset and length to "minimal" byte boundaries */
- field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
- field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length +
- field_bit_offset, 8));
- field_byte_length = field_byte_end_offset - field_byte_offset;
+ field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
+ field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
+ field_bit_offset, 8));
+ field_byte_length = field_byte_end_offset - field_byte_offset;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Bit length %d, Bit offset %d\n",
- field_bit_length, field_bit_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Bit length %d, Bit offset %d\n",
+ field_bit_length, field_bit_offset));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Byte Length %d, Byte Offset %d, End Offset %d\n",
- field_byte_length, field_byte_offset, field_byte_end_offset));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Byte Length %d, Byte Offset %d, End Offset %d\n",
+ field_byte_length, field_byte_offset,
+ field_byte_end_offset));
/*
* Iterative search for the maximum access width that is both aligned
@@ -132,7 +121,8 @@ acpi_ex_generate_access (
*
* Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
*/
- for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
+ for (access_byte_width = 1; access_byte_width <= 8;
+ access_byte_width <<= 1) {
/*
* 1) Round end offset up to next access boundary and make sure that
* this does not go beyond the end of the parent region.
@@ -140,31 +130,37 @@ acpi_ex_generate_access (
* are done. (This does not optimize for the perfectly aligned
* case yet).
*/
- if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
+ if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <=
+ region_length) {
field_start_offset =
- ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
- access_byte_width;
+ ACPI_ROUND_DOWN(field_byte_offset,
+ access_byte_width) /
+ access_byte_width;
field_end_offset =
- ACPI_ROUND_UP ((field_byte_length + field_byte_offset),
- access_byte_width) / access_byte_width;
+ ACPI_ROUND_UP((field_byte_length +
+ field_byte_offset),
+ access_byte_width) /
+ access_byte_width;
accesses = field_end_offset - field_start_offset;
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "access_width %d end is within region\n", access_byte_width));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "access_width %d end is within region\n",
+ access_byte_width));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Field Start %d, Field End %d -- requires %d accesses\n",
- field_start_offset, field_end_offset, accesses));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Field Start %d, Field End %d -- requires %d accesses\n",
+ field_start_offset, field_end_offset,
+ accesses));
/* Single access is optimal */
if (accesses <= 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Entire field can be accessed with one operation of size %d\n",
- access_byte_width));
- return_VALUE (access_byte_width);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Entire field can be accessed with one operation of size %d\n",
+ access_byte_width));
+ return_VALUE(access_byte_width);
}
/*
@@ -172,30 +168,30 @@ acpi_ex_generate_access (
* try the next wider access on next iteration
*/
if (accesses < minimum_accesses) {
- minimum_accesses = accesses;
+ minimum_accesses = accesses;
minimum_access_width = access_byte_width;
}
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "access_width %d end is NOT within region\n", access_byte_width));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "access_width %d end is NOT within region\n",
+ access_byte_width));
if (access_byte_width == 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Field goes beyond end-of-region!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Field goes beyond end-of-region!\n"));
/* Field does not fit in the region at all */
- return_VALUE (0);
+ return_VALUE(0);
}
/*
* This width goes beyond the end-of-region, back off to
* previous access
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Backing off to previous optimal access width of %d\n",
- minimum_access_width));
- return_VALUE (minimum_access_width);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Backing off to previous optimal access width of %d\n",
+ minimum_access_width));
+ return_VALUE(minimum_access_width);
}
}
@@ -203,12 +199,11 @@ acpi_ex_generate_access (
* Could not read/write field with one operation,
* just use max access width
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Cannot access field in one operation, using width 8\n"));
- return_VALUE (8);
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Cannot access field in one operation, using width 8\n"));
+ return_VALUE(8);
}
-#endif /* ACPI_UNDER_DEVELOPMENT */
-
+#endif /* ACPI_UNDER_DEVELOPMENT */
/*******************************************************************************
*
@@ -226,18 +221,14 @@ acpi_ex_generate_access (
******************************************************************************/
static u32
-acpi_ex_decode_field_access (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u32 *return_byte_alignment)
+acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
+ u8 field_flags, u32 * return_byte_alignment)
{
- u32 access;
- u32 byte_alignment;
- u32 bit_length;
-
-
- ACPI_FUNCTION_TRACE ("ex_decode_field_access");
+ u32 access;
+ u32 byte_alignment;
+ u32 bit_length;
+ ACPI_FUNCTION_TRACE("ex_decode_field_access");
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -246,9 +237,12 @@ acpi_ex_decode_field_access (
#ifdef ACPI_UNDER_DEVELOPMENT
byte_alignment =
- acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.bit_length,
- 0xFFFFFFFF /* Temp until we pass region_length as parameter */);
+ acpi_ex_generate_access(obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+ 0xFFFFFFFF
+ /* Temp until we pass region_length as parameter */
+ );
bit_length = byte_alignment * 8;
#endif
@@ -257,36 +251,35 @@ acpi_ex_decode_field_access (
break;
case AML_FIELD_ACCESS_BYTE:
- case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
+ case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
byte_alignment = 1;
- bit_length = 8;
+ bit_length = 8;
break;
case AML_FIELD_ACCESS_WORD:
byte_alignment = 2;
- bit_length = 16;
+ bit_length = 16;
break;
case AML_FIELD_ACCESS_DWORD:
byte_alignment = 4;
- bit_length = 32;
+ bit_length = 32;
break;
- case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
+ case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
byte_alignment = 8;
- bit_length = 64;
+ bit_length = 64;
break;
default:
/* Invalid field access type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown field access type %X\n",
- access));
- return_VALUE (0);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown field access type %X\n", access));
+ return_VALUE(0);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
* buffer_field access can be on any byte boundary, so the
* byte_alignment is always 1 byte -- regardless of any byte_alignment
@@ -296,10 +289,9 @@ acpi_ex_decode_field_access (
}
*return_byte_alignment = byte_alignment;
- return_VALUE (bit_length);
+ return_VALUE(bit_length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_common_field_object
@@ -322,20 +314,16 @@ acpi_ex_decode_field_access (
******************************************************************************/
acpi_status
-acpi_ex_prep_common_field_object (
- union acpi_operand_object *obj_desc,
- u8 field_flags,
- u8 field_attribute,
- u32 field_bit_position,
- u32 field_bit_length)
+acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
+ u8 field_flags,
+ u8 field_attribute,
+ u32 field_bit_position, u32 field_bit_length)
{
- u32 access_bit_width;
- u32 byte_alignment;
- u32 nearest_byte_address;
-
-
- ACPI_FUNCTION_TRACE ("ex_prep_common_field_object");
+ u32 access_bit_width;
+ u32 byte_alignment;
+ u32 nearest_byte_address;
+ ACPI_FUNCTION_TRACE("ex_prep_common_field_object");
/*
* Note: the structure being initialized is the
@@ -361,16 +349,16 @@ acpi_ex_prep_common_field_object (
* For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
* the same (equivalent) as the byte_alignment.
*/
- access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
- &byte_alignment);
+ access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags,
+ &byte_alignment);
if (!access_bit_width) {
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
/* Setup width (access granularity) fields */
obj_desc->common_field.access_byte_width = (u8)
- ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
+ ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
@@ -385,30 +373,30 @@ acpi_ex_prep_common_field_object (
* region or buffer.
*/
nearest_byte_address =
- ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
+ ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position);
obj_desc->common_field.base_byte_offset = (u32)
- ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
+ ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment);
/*
* start_field_bit_offset is the offset of the first bit of the field within
* a field datum.
*/
obj_desc->common_field.start_field_bit_offset = (u8)
- (field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
+ (field_bit_position -
+ ACPI_MUL_8(obj_desc->common_field.base_byte_offset));
/*
* Does the entire field fit within a single field access element? (datum)
* (i.e., without crossing a datum boundary)
*/
- if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
- (u16) access_bit_width) {
+ if ((obj_desc->common_field.start_field_bit_offset +
+ field_bit_length) <= (u16) access_bit_width) {
obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_prep_field_value
@@ -422,51 +410,49 @@ acpi_ex_prep_common_field_object (
*
******************************************************************************/
-acpi_status
-acpi_ex_prep_field_value (
- struct acpi_create_field_info *info)
+acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
- union acpi_operand_object *obj_desc;
- u32 type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_prep_field_value");
+ union acpi_operand_object *obj_desc;
+ u32 type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_prep_field_value");
/* Parameter validation */
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
if (!info->region_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null region_node\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
- type = acpi_ns_get_type (info->region_node);
+ type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed Region, found type %X (%s)\n",
- type, acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Region, found type %X (%s)\n",
+ type, acpi_ut_get_type_name(type)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
/* Allocate a new field object */
- obj_desc = acpi_ut_create_internal_object (info->field_type);
+ obj_desc = acpi_ut_create_internal_object(info->field_type);
if (!obj_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node;
- status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
- info->attribute, info->field_bit_position, info->field_bit_length);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (status);
+ status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
+ info->attribute,
+ info->field_bit_position,
+ info->field_bit_length);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
}
/* Initialize areas of the object that are specific to the field type */
@@ -474,71 +460,73 @@ acpi_ex_prep_field_value (
switch (info->field_type) {
case ACPI_TYPE_LOCAL_REGION_FIELD:
- obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node);
+ obj_desc->field.region_obj =
+ acpi_ns_get_attached_object(info->region_node);
/* An additional reference for the container */
- acpi_ut_add_reference (obj_desc->field.region_obj);
+ acpi_ut_add_reference(obj_desc->field.region_obj);
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
- obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
- obj_desc->field.access_byte_width, obj_desc->field.region_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
+ obj_desc->field.start_field_bit_offset,
+ obj_desc->field.base_byte_offset,
+ obj_desc->field.access_byte_width,
+ obj_desc->field.region_obj));
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- obj_desc->bank_field.value = info->bank_value;
- obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (
- info->region_node);
- obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (
- info->register_node);
+ obj_desc->bank_field.value = info->bank_value;
+ obj_desc->bank_field.region_obj =
+ acpi_ns_get_attached_object(info->region_node);
+ obj_desc->bank_field.bank_obj =
+ acpi_ns_get_attached_object(info->register_node);
/* An additional reference for the attached objects */
- acpi_ut_add_reference (obj_desc->bank_field.region_obj);
- acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
+ acpi_ut_add_reference(obj_desc->bank_field.region_obj);
+ acpi_ut_add_reference(obj_desc->bank_field.bank_obj);
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
- obj_desc->bank_field.start_field_bit_offset,
- obj_desc->bank_field.base_byte_offset,
- obj_desc->field.access_byte_width,
- obj_desc->bank_field.region_obj,
- obj_desc->bank_field.bank_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
+ obj_desc->bank_field.start_field_bit_offset,
+ obj_desc->bank_field.base_byte_offset,
+ obj_desc->field.access_byte_width,
+ obj_desc->bank_field.region_obj,
+ obj_desc->bank_field.bank_obj));
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- obj_desc->index_field.index_obj = acpi_ns_get_attached_object (
- info->register_node);
- obj_desc->index_field.data_obj = acpi_ns_get_attached_object (
- info->data_register_node);
- obj_desc->index_field.value = (u32)
- (info->field_bit_position / ACPI_MUL_8 (
- obj_desc->field.access_byte_width));
-
- if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
- ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
- acpi_ut_delete_object_desc (obj_desc);
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ obj_desc->index_field.index_obj =
+ acpi_ns_get_attached_object(info->register_node);
+ obj_desc->index_field.data_obj =
+ acpi_ns_get_attached_object(info->data_register_node);
+ obj_desc->index_field.value = (u32)
+ (info->field_bit_position /
+ ACPI_MUL_8(obj_desc->field.access_byte_width));
+
+ if (!obj_desc->index_field.data_obj
+ || !obj_desc->index_field.index_obj) {
+ ACPI_REPORT_ERROR(("Null Index Object during field prep\n"));
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* An additional reference for the attached objects */
- acpi_ut_add_reference (obj_desc->index_field.data_obj);
- acpi_ut_add_reference (obj_desc->index_field.index_obj);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
- obj_desc->index_field.start_field_bit_offset,
- obj_desc->index_field.base_byte_offset,
- obj_desc->index_field.value,
- obj_desc->field.access_byte_width,
- obj_desc->index_field.index_obj,
- obj_desc->index_field.data_obj));
+ acpi_ut_add_reference(obj_desc->index_field.data_obj);
+ acpi_ut_add_reference(obj_desc->index_field.index_obj);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
+ obj_desc->index_field.start_field_bit_offset,
+ obj_desc->index_field.base_byte_offset,
+ obj_desc->index_field.value,
+ obj_desc->field.access_byte_width,
+ obj_desc->index_field.index_obj,
+ obj_desc->index_field.data_obj));
break;
default:
@@ -550,15 +538,16 @@ acpi_ex_prep_field_value (
* Store the constructed descriptor (obj_desc) into the parent Node,
* preserving the current type of that named_obj.
*/
- status = acpi_ns_attach_object (info->field_node, obj_desc,
- acpi_ns_get_type (info->field_node));
+ status = acpi_ns_attach_object(info->field_node, obj_desc,
+ acpi_ns_get_type(info->field_node));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
- info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Set named_obj %p [%4.4s], obj_desc %p\n",
+ info->field_node,
+ acpi_ut_get_node_name(info->field_node), obj_desc));
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 723aaef4bb4a..9a2f5bea3afe 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exregion")
-
+ACPI_MODULE_NAME("exregion")
/*******************************************************************************
*
@@ -68,27 +65,23 @@
* DESCRIPTION: Handler for the System Memory address space (Op Region)
*
******************************************************************************/
-
acpi_status
-acpi_ex_system_memory_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_system_memory_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- void *logical_addr_ptr = NULL;
- struct acpi_mem_space_context *mem_info = region_context;
- u32 length;
- acpi_size window_size;
+ acpi_status status = AE_OK;
+ void *logical_addr_ptr = NULL;
+ struct acpi_mem_space_context *mem_info = region_context;
+ u32 length;
+ acpi_size window_size;
#ifndef ACPI_MISALIGNED_TRANSFERS
- u32 remainder;
+ u32 remainder;
#endif
- ACPI_FUNCTION_TRACE ("ex_system_memory_space_handler");
-
+ ACPI_FUNCTION_TRACE("ex_system_memory_space_handler");
/* Validate and translate the bit width */
@@ -110,9 +103,10 @@ acpi_ex_system_memory_space_handler (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n",
- bit_width));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid system_memory width %d\n",
+ bit_width));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
#ifndef ACPI_MISALIGNED_TRANSFERS
@@ -120,9 +114,10 @@ acpi_ex_system_memory_space_handler (
* Hardware does not support non-aligned data transfers, we must verify
* the request.
*/
- (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder);
+ (void)acpi_ut_short_divide((acpi_integer) address, length, NULL,
+ &remainder);
if (remainder != 0) {
- return_ACPI_STATUS (AE_AML_ALIGNMENT);
+ return_ACPI_STATUS(AE_AML_ALIGNMENT);
}
#endif
@@ -132,9 +127,10 @@ acpi_ex_system_memory_space_handler (
* 2) Address beyond the current mapping?
*/
if ((address < mem_info->mapped_physical_address) ||
- (((acpi_integer) address + length) >
- ((acpi_integer)
- mem_info->mapped_physical_address + mem_info->mapped_length))) {
+ (((acpi_integer) address + length) > ((acpi_integer)
+ mem_info->
+ mapped_physical_address +
+ mem_info->mapped_length))) {
/*
* The request cannot be resolved by the current memory mapping;
* Delete the existing mapping and create a new one.
@@ -142,8 +138,8 @@ acpi_ex_system_memory_space_handler (
if (mem_info->mapped_length) {
/* Valid mapping, delete it */
- acpi_os_unmap_memory (mem_info->mapped_logical_address,
- mem_info->mapped_length);
+ acpi_os_unmap_memory(mem_info->mapped_logical_address,
+ mem_info->mapped_length);
}
/*
@@ -151,7 +147,7 @@ acpi_ex_system_memory_space_handler (
* constrain the maximum mapping size to something reasonable.
*/
window_size = (acpi_size)
- ((mem_info->address + mem_info->length) - address);
+ ((mem_info->address + mem_info->length) - address);
if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
@@ -159,14 +155,16 @@ acpi_ex_system_memory_space_handler (
/* Create a new mapping starting at the address given */
- status = acpi_os_map_memory (address, window_size,
- (void **) &mem_info->mapped_logical_address);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X%8.8X, size %X\n",
- ACPI_FORMAT_UINT64 (address), (u32) window_size));
+ status = acpi_os_map_memory(address, window_size,
+ (void **)&mem_info->
+ mapped_logical_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X%8.8X, size %X\n",
+ ACPI_FORMAT_UINT64(address),
+ (u32) window_size));
mem_info->mapped_length = 0;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Save the physical address and mapping size */
@@ -180,42 +178,41 @@ acpi_ex_system_memory_space_handler (
* access
*/
logical_addr_ptr = mem_info->mapped_logical_address +
- ((acpi_integer) address -
- (acpi_integer) mem_info->mapped_physical_address);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "system_memory %d (%d width) Address=%8.8X%8.8X\n",
- function, bit_width,
- ACPI_FORMAT_UINT64 (address)));
-
- /*
- * Perform the memory read or write
- *
- * Note: For machines that do not support non-aligned transfers, the target
- * address was checked for alignment above. We do not attempt to break the
- * transfer up into smaller (byte-size) chunks because the AML specifically
- * asked for a transfer width that the hardware may require.
- */
+ ((acpi_integer) address -
+ (acpi_integer) mem_info->mapped_physical_address);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "system_memory %d (%d width) Address=%8.8X%8.8X\n",
+ function, bit_width, ACPI_FORMAT_UINT64(address)));
+
+ /*
+ * Perform the memory read or write
+ *
+ * Note: For machines that do not support non-aligned transfers, the target
+ * address was checked for alignment above. We do not attempt to break the
+ * transfer up into smaller (byte-size) chunks because the AML specifically
+ * asked for a transfer width that the hardware may require.
+ */
switch (function) {
case ACPI_READ:
*value = 0;
switch (bit_width) {
case 8:
- *value = (acpi_integer) *((u8 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u8 *) logical_addr_ptr);
break;
case 16:
- *value = (acpi_integer) *((u16 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u16 *) logical_addr_ptr);
break;
case 32:
- *value = (acpi_integer) *((u32 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u32 *) logical_addr_ptr);
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *value = (acpi_integer) *((u64 *) logical_addr_ptr);
+ *value = (acpi_integer) * ((u64 *) logical_addr_ptr);
break;
#endif
default:
@@ -228,20 +225,20 @@ acpi_ex_system_memory_space_handler (
switch (bit_width) {
case 8:
- *(u8 *) logical_addr_ptr = (u8) *value;
+ *(u8 *) logical_addr_ptr = (u8) * value;
break;
case 16:
- *(u16 *) logical_addr_ptr = (u16) *value;
+ *(u16 *) logical_addr_ptr = (u16) * value;
break;
case 32:
- *(u32 *) logical_addr_ptr = (u32) *value;
+ *(u32 *) logical_addr_ptr = (u32) * value;
break;
#if ACPI_MACHINE_WIDTH != 16
case 64:
- *(u64 *) logical_addr_ptr = (u64) *value;
+ *(u64 *) logical_addr_ptr = (u64) * value;
break;
#endif
@@ -256,10 +253,9 @@ acpi_ex_system_memory_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_io_space_handler
@@ -279,39 +275,35 @@ acpi_ex_system_memory_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_system_io_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_system_io_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- u32 value32;
+ acpi_status status = AE_OK;
+ u32 value32;
+ ACPI_FUNCTION_TRACE("ex_system_io_space_handler");
- ACPI_FUNCTION_TRACE ("ex_system_io_space_handler");
-
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
- ACPI_FORMAT_UINT64 (address)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "system_iO %d (%d width) Address=%8.8X%8.8X\n",
+ function, bit_width, ACPI_FORMAT_UINT64(address)));
/* Decode the function parameter */
switch (function) {
case ACPI_READ:
- status = acpi_os_read_port ((acpi_io_address) address,
- &value32, bit_width);
+ status = acpi_os_read_port((acpi_io_address) address,
+ &value32, bit_width);
*value = value32;
break;
case ACPI_WRITE:
- status = acpi_os_write_port ((acpi_io_address) address,
- (u32) *value, bit_width);
+ status = acpi_os_write_port((acpi_io_address) address,
+ (u32) * value, bit_width);
break;
default:
@@ -319,10 +311,9 @@ acpi_ex_system_io_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_config_space_handler
@@ -342,21 +333,17 @@ acpi_ex_system_io_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_pci_config_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_pci_config_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- struct acpi_pci_id *pci_id;
- u16 pci_register;
-
-
- ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler");
+ acpi_status status = AE_OK;
+ struct acpi_pci_id *pci_id;
+ u16 pci_register;
+ ACPI_FUNCTION_TRACE("ex_pci_config_space_handler");
/*
* The arguments to acpi_os(Read|Write)pci_configuration are:
@@ -370,26 +357,26 @@ acpi_ex_pci_config_space_handler (
* Value - input value for write, output address for read
*
*/
- pci_id = (struct acpi_pci_id *) region_context;
+ pci_id = (struct acpi_pci_id *)region_context;
pci_register = (u16) (u32) address;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
- function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
- pci_id->function, pci_register));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
+ function, bit_width, pci_id->segment, pci_id->bus,
+ pci_id->device, pci_id->function, pci_register));
switch (function) {
case ACPI_READ:
*value = 0;
- status = acpi_os_read_pci_configuration (pci_id, pci_register,
- value, bit_width);
+ status = acpi_os_read_pci_configuration(pci_id, pci_register,
+ value, bit_width);
break;
case ACPI_WRITE:
- status = acpi_os_write_pci_configuration (pci_id, pci_register,
- *value, bit_width);
+ status = acpi_os_write_pci_configuration(pci_id, pci_register,
+ *value, bit_width);
break;
default:
@@ -398,10 +385,9 @@ acpi_ex_pci_config_space_handler (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_cmos_space_handler
@@ -421,24 +407,19 @@ acpi_ex_pci_config_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_cmos_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_cmos_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("ex_cmos_space_handler");
+ ACPI_FUNCTION_TRACE("ex_cmos_space_handler");
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_bar_space_handler
@@ -458,24 +439,19 @@ acpi_ex_cmos_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_pci_bar_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_pci_bar_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler");
+ ACPI_FUNCTION_TRACE("ex_pci_bar_space_handler");
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_data_table_space_handler
@@ -495,24 +471,20 @@ acpi_ex_pci_bar_space_handler (
******************************************************************************/
acpi_status
-acpi_ex_data_table_space_handler (
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- acpi_integer *value,
- void *handler_context,
- void *region_context)
+acpi_ex_data_table_space_handler(u32 function,
+ acpi_physical_address address,
+ u32 bit_width,
+ acpi_integer * value,
+ void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- u32 byte_width = ACPI_DIV_8 (bit_width);
- u32 i;
- char *logical_addr_ptr;
-
+ acpi_status status = AE_OK;
+ u32 byte_width = ACPI_DIV_8(bit_width);
+ u32 i;
+ char *logical_addr_ptr;
- ACPI_FUNCTION_TRACE ("ex_data_table_space_handler");
+ ACPI_FUNCTION_TRACE("ex_data_table_space_handler");
-
- logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address);
+ logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address);
/* Perform the memory read or write */
@@ -520,17 +492,15 @@ acpi_ex_data_table_space_handler (
case ACPI_READ:
for (i = 0; i < byte_width; i++) {
- ((char *) value) [i] = logical_addr_ptr[i];
+ ((char *)value)[i] = logical_addr_ptr[i];
}
break;
case ACPI_WRITE:
default:
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 21d5c74fa309..ff5d8f97e8eb 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
@@ -50,10 +49,8 @@
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresnte")
-
+ACPI_MODULE_NAME("exresnte")
/*******************************************************************************
*
@@ -80,41 +77,37 @@
* ACPI_TYPE_PACKAGE
*
******************************************************************************/
-
acpi_status
-acpi_ex_resolve_node_to_value (
- struct acpi_namespace_node **object_ptr,
- struct acpi_walk_state *walk_state)
-
+acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *source_desc;
- union acpi_operand_object *obj_desc = NULL;
- struct acpi_namespace_node *node;
- acpi_object_type entry_type;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *source_desc;
+ union acpi_operand_object *obj_desc = NULL;
+ struct acpi_namespace_node *node;
+ acpi_object_type entry_type;
+ ACPI_FUNCTION_TRACE("ex_resolve_node_to_value");
/*
* The stack pointer points to a struct acpi_namespace_node (Node). Get the
* object that is attached to the Node.
*/
- node = *object_ptr;
- source_desc = acpi_ns_get_attached_object (node);
- entry_type = acpi_ns_get_type ((acpi_handle) node);
+ node = *object_ptr;
+ source_desc = acpi_ns_get_attached_object(node);
+ entry_type = acpi_ns_get_type((acpi_handle) node);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
- node, source_desc, acpi_ut_get_type_name (entry_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
+ node, source_desc,
+ acpi_ut_get_type_name(entry_type)));
if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
- (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+ (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/* There is always exactly one level of indirection */
- node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
- source_desc = acpi_ns_get_attached_object (node);
- entry_type = acpi_ns_get_type ((acpi_handle) node);
+ node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
+ source_desc = acpi_ns_get_attached_object(node);
+ entry_type = acpi_ns_get_type((acpi_handle) node);
*object_ptr = node;
}
@@ -124,14 +117,14 @@ acpi_ex_resolve_node_to_value (
* 2) Method locals and arguments have a pseudo-Node
*/
if (entry_type == ACPI_TYPE_DEVICE ||
- (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
- return_ACPI_STATUS (AE_OK);
+ (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
+ return_ACPI_STATUS(AE_OK);
}
if (!source_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n",
- node));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No object attached to node %p\n", node));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
@@ -141,83 +134,89 @@ acpi_ex_resolve_node_to_value (
switch (entry_type) {
case ACPI_TYPE_PACKAGE:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Package, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- status = acpi_ds_get_package_arguments (source_desc);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_get_package_arguments(source_desc);
+ if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
}
break;
-
case ACPI_TYPE_BUFFER:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Buffer, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- status = acpi_ds_get_buffer_arguments (source_desc);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_get_buffer_arguments(source_desc);
+ if (ACPI_SUCCESS(status)) {
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
}
break;
-
case ACPI_TYPE_STRING:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a String, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
-
case ACPI_TYPE_INTEGER:
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Object not a Integer, type %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
-
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "field_read Node=%p source_desc=%p Type=%X\n",
- node, source_desc, entry_type));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "field_read Node=%p source_desc=%p Type=%X\n",
+ node, source_desc, entry_type));
- status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
+ status =
+ acpi_ex_read_data_from_field(walk_state, source_desc,
+ &obj_desc);
break;
- /* For these objects, just return the object attached to the Node */
+ /* For these objects, just return the object attached to the Node */
case ACPI_TYPE_MUTEX:
case ACPI_TYPE_METHOD:
@@ -230,19 +229,18 @@ acpi_ex_resolve_node_to_value (
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
- /* TYPE_ANY is untyped, and thus there is no object associated with it */
+ /* TYPE_ANY is untyped, and thus there is no object associated with it */
case ACPI_TYPE_ANY:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Untyped entry %p, no attached object!\n",
- node));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Untyped entry %p, no attached object!\n",
+ node));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -253,39 +251,37 @@ acpi_ex_resolve_node_to_value (
/* Return an additional reference to the object */
obj_desc = source_desc;
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
break;
default:
/* No named references are allowed here */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported Reference opcode %X (%s)\n",
- source_desc->reference.opcode,
- acpi_ps_get_opcode_name (source_desc->reference.opcode)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported Reference opcode %X (%s)\n",
+ source_desc->reference.opcode,
+ acpi_ps_get_opcode_name(source_desc->
+ reference.
+ opcode)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
-
default:
/* Default case is for unknown types */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Node %p - Unknown object type %X\n",
- node, entry_type));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Node %p - Unknown object type %X\n",
+ node, entry_type));
- } /* switch (entry_type) */
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+ } /* switch (entry_type) */
/* Return the object descriptor */
- *object_ptr = (void *) obj_desc;
- return_ACPI_STATUS (status);
+ *object_ptr = (void *)obj_desc;
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 3de45672379a..97eecbd3242d 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
@@ -50,17 +49,13 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresolv")
+ACPI_MODULE_NAME("exresolv")
/* Local prototypes */
-
static acpi_status
-acpi_ex_resolve_object_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -78,19 +73,16 @@ acpi_ex_resolve_object_to_value (
******************************************************************************/
acpi_status
-acpi_ex_resolve_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_resolve_to_value", stack_ptr);
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
if (!stack_ptr || !*stack_ptr) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Internal - null pointer\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/*
@@ -98,15 +90,16 @@ acpi_ex_resolve_to_value (
* 1) A valid union acpi_operand_object, or
* 2) A struct acpi_namespace_node (named_obj)
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
- status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
+ status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (!*stack_ptr) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Internal - null pointer\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
}
@@ -114,20 +107,20 @@ acpi_ex_resolve_to_value (
* Object on the stack may have changed if acpi_ex_resolve_object_to_value()
* was called (i.e., we can't use an _else_ here.)
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
- status = acpi_ex_resolve_node_to_value (
- ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, stack_ptr),
- walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
+ status =
+ acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
+ (struct acpi_namespace_node,
+ stack_ptr), walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_object_to_value
@@ -143,25 +136,22 @@ acpi_ex_resolve_to_value (
******************************************************************************/
static acpi_status
-acpi_ex_resolve_object_to_value (
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *stack_desc;
- void *temp_node;
- union acpi_operand_object *obj_desc;
- u16 opcode;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_object_to_value");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *stack_desc;
+ void *temp_node;
+ union acpi_operand_object *obj_desc;
+ u16 opcode;
+ ACPI_FUNCTION_TRACE("ex_resolve_object_to_value");
stack_desc = *stack_ptr;
/* This is an union acpi_operand_object */
- switch (ACPI_GET_OBJECT_TYPE (stack_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
opcode = stack_desc->reference.opcode;
@@ -177,14 +167,13 @@ acpi_ex_resolve_object_to_value (
/* Delete the Reference Object */
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_remove_reference(stack_desc);
/* Return the namespace node */
(*stack_ptr) = temp_node;
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
@@ -192,24 +181,28 @@ acpi_ex_resolve_object_to_value (
* Get the local from the method's state info
* Note: this increments the local's object reference count
*/
- status = acpi_ds_method_data_get_value (opcode,
- stack_desc->reference.offset, walk_state, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_method_data_get_value(opcode,
+ stack_desc->
+ reference.offset,
+ walk_state,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
- stack_desc->reference.offset, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Arg/Local %X] value_obj is %p\n",
+ stack_desc->reference.offset,
+ obj_desc));
/*
* Now we can delete the original Reference Object and
* replace it with the resolved value
*/
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_remove_reference(stack_desc);
*stack_ptr = obj_desc;
break;
-
case AML_INDEX_OP:
switch (stack_desc->reference.target_type) {
@@ -218,7 +211,6 @@ acpi_ex_resolve_object_to_value (
/* Just return - leave the Reference on the stack */
break;
-
case ACPI_TYPE_PACKAGE:
obj_desc = *stack_desc->reference.where;
@@ -228,36 +220,31 @@ acpi_ex_resolve_object_to_value (
* (i.e., dereference the package index)
* Delete the ref object, increment the returned object
*/
- acpi_ut_remove_reference (stack_desc);
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_remove_reference(stack_desc);
+ acpi_ut_add_reference(obj_desc);
*stack_ptr = obj_desc;
- }
- else {
+ } else {
/*
* A NULL object descriptor means an unitialized element of
* the package, can't dereference it
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Attempt to deref an Index to NULL pkg element Idx=%p\n",
- stack_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Attempt to deref an Index to NULL pkg element Idx=%p\n",
+ stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
break;
-
default:
/* Invalid reference object */
- ACPI_REPORT_ERROR ((
- "During resolve, Unknown target_type %X in Index/Reference obj %p\n",
- stack_desc->reference.target_type, stack_desc));
+ ACPI_REPORT_ERROR(("During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
-
case AML_REF_OF_OP:
case AML_DEBUG_OP:
case AML_LOAD_OP:
@@ -266,60 +253,58 @@ acpi_ex_resolve_object_to_value (
break;
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
+ case AML_INT_NAMEPATH_OP: /* Reference to a named object */
/* Get the object pointed to by the namespace node */
*stack_ptr = (stack_desc->reference.node)->object;
- acpi_ut_add_reference (*stack_ptr);
- acpi_ut_remove_reference (stack_desc);
+ acpi_ut_add_reference(*stack_ptr);
+ acpi_ut_remove_reference(stack_desc);
break;
default:
- ACPI_REPORT_ERROR ((
- "During resolve, Unknown Reference opcode %X (%s) in %p\n",
- opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
+ ACPI_REPORT_ERROR(("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name(opcode), stack_desc));
status = AE_AML_INTERNAL;
break;
}
break;
-
case ACPI_TYPE_BUFFER:
- status = acpi_ds_get_buffer_arguments (stack_desc);
+ status = acpi_ds_get_buffer_arguments(stack_desc);
break;
-
case ACPI_TYPE_PACKAGE:
- status = acpi_ds_get_package_arguments (stack_desc);
+ status = acpi_ds_get_package_arguments(stack_desc);
break;
-
- /* These cases may never happen here, but just in case.. */
+ /* These cases may never happen here, but just in case.. */
case ACPI_TYPE_BUFFER_FIELD:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read source_desc=%p Type=%X\n",
- stack_desc, ACPI_GET_OBJECT_TYPE (stack_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "field_read source_desc=%p Type=%X\n",
+ stack_desc,
+ ACPI_GET_OBJECT_TYPE(stack_desc)));
- status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc);
- *stack_ptr = (void *) obj_desc;
+ status =
+ acpi_ex_read_data_from_field(walk_state, stack_desc,
+ &obj_desc);
+ *stack_ptr = (void *)obj_desc;
break;
default:
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_multiple
@@ -337,42 +322,44 @@ acpi_ex_resolve_object_to_value (
******************************************************************************/
acpi_status
-acpi_ex_resolve_multiple (
- struct acpi_walk_state *walk_state,
- union acpi_operand_object *operand,
- acpi_object_type *return_type,
- union acpi_operand_object **return_desc)
+acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
+ union acpi_operand_object *operand,
+ acpi_object_type * return_type,
+ union acpi_operand_object **return_desc)
{
- union acpi_operand_object *obj_desc = (void *) operand;
- struct acpi_namespace_node *node;
- acpi_object_type type;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple");
+ union acpi_operand_object *obj_desc = (void *)operand;
+ struct acpi_namespace_node *node;
+ acpi_object_type type;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple");
/* Operand can be either a namespace node or an operand descriptor */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_OPERAND:
type = obj_desc->common.type;
break;
case ACPI_DESC_TYPE_NAMED:
- type = ((struct acpi_namespace_node *) obj_desc)->type;
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
+ type = ((struct acpi_namespace_node *)obj_desc)->type;
+ obj_desc =
+ acpi_ns_get_attached_object((struct acpi_namespace_node *)
+ obj_desc);
/* If we had an Alias node, use the attached object for type info */
if (type == ACPI_TYPE_LOCAL_ALIAS) {
- type = ((struct acpi_namespace_node *) obj_desc)->type;
- obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
+ type = ((struct acpi_namespace_node *)obj_desc)->type;
+ obj_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node *)
+ obj_desc);
}
break;
default:
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* If type is anything other than a reference, we are done */
@@ -387,7 +374,7 @@ acpi_ex_resolve_multiple (
* of the object_type and size_of operators). This means traversing
* the list of possibly many nested references.
*/
- while (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
+ while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.opcode) {
case AML_REF_OF_OP:
@@ -397,31 +384,29 @@ acpi_ex_resolve_multiple (
/* All "References" point to a NS node */
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Get the attached object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, use the NS node type */
- type = acpi_ns_get_type (node);
+ type = acpi_ns_get_type(node);
goto exit;
}
/* Check for circular references */
if (obj_desc == operand) {
- return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
+ return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
}
break;
-
case AML_INDEX_OP:
/* Get the type of this reference (index into another object) */
@@ -442,12 +427,11 @@ acpi_ex_resolve_multiple (
if (!obj_desc) {
/* NULL package elements are allowed */
- type = 0; /* Uninitialized */
+ type = 0; /* Uninitialized */
goto exit;
}
break;
-
case AML_INT_NAMEPATH_OP:
/* Dereference the reference pointer */
@@ -456,50 +440,61 @@ acpi_ex_resolve_multiple (
/* All "References" point to a NS node */
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Get the attached object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, use the NS node type */
- type = acpi_ns_get_type (node);
+ type = acpi_ns_get_type(node);
goto exit;
}
/* Check for circular references */
if (obj_desc == operand) {
- return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
+ return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
}
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
if (return_desc) {
- status = acpi_ds_method_data_get_value (obj_desc->reference.opcode,
- obj_desc->reference.offset, walk_state, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_method_data_get_value(obj_desc->
+ reference.
+ opcode,
+ obj_desc->
+ reference.
+ offset,
+ walk_state,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- acpi_ut_remove_reference (obj_desc);
- }
- else {
- status = acpi_ds_method_data_get_node (obj_desc->reference.opcode,
- obj_desc->reference.offset, walk_state, &node);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ } else {
+ status =
+ acpi_ds_method_data_get_node(obj_desc->
+ reference.
+ opcode,
+ obj_desc->
+ reference.
+ offset,
+ walk_state,
+ &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
type = ACPI_TYPE_ANY;
goto exit;
@@ -507,7 +502,6 @@ acpi_ex_resolve_multiple (
}
break;
-
case AML_DEBUG_OP:
/* The Debug Object is of type "debug_object" */
@@ -515,13 +509,10 @@ acpi_ex_resolve_multiple (
type = ACPI_TYPE_DEBUG_OBJECT;
goto exit;
-
default:
- ACPI_REPORT_ERROR ((
- "acpi_ex_resolve_multiple: Unknown Reference subtype %X\n",
- obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
}
@@ -529,10 +520,9 @@ acpi_ex_resolve_multiple (
* Now we are guaranteed to have an object that has not been created
* via the ref_of or Index operators.
*/
- type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ type = ACPI_GET_OBJECT_TYPE(obj_desc);
-
-exit:
+ exit:
/* Convert internal types to external types */
switch (type) {
@@ -559,7 +549,5 @@ exit:
if (return_desc) {
*return_desc = obj_desc;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index d8b470eefe7a..ff064e79ab90 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -42,24 +42,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exresop")
+ACPI_MODULE_NAME("exresop")
/* Local prototypes */
-
static acpi_status
-acpi_ex_check_object_type (
- acpi_object_type type_needed,
- acpi_object_type this_type,
- void *object);
-
+acpi_ex_check_object_type(acpi_object_type type_needed,
+ acpi_object_type this_type, void *object);
/*******************************************************************************
*
@@ -76,13 +70,10 @@ acpi_ex_check_object_type (
******************************************************************************/
static acpi_status
-acpi_ex_check_object_type (
- acpi_object_type type_needed,
- acpi_object_type this_type,
- void *object)
+acpi_ex_check_object_type(acpi_object_type type_needed,
+ acpi_object_type this_type, void *object)
{
- ACPI_FUNCTION_NAME ("ex_check_object_type");
-
+ ACPI_FUNCTION_NAME("ex_check_object_type");
if (type_needed == ACPI_TYPE_ANY) {
/* All types OK, so we don't perform any typechecks */
@@ -97,16 +88,17 @@ acpi_ex_check_object_type (
* specification, a store to a constant is a noop.)
*/
if ((this_type == ACPI_TYPE_INTEGER) &&
- (((union acpi_operand_object *) object)->common.flags & AOPOBJ_AML_CONSTANT)) {
+ (((union acpi_operand_object *)object)->common.
+ flags & AOPOBJ_AML_CONSTANT)) {
return (AE_OK);
}
}
if (type_needed != this_type) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [%s], found [%s] %p\n",
- acpi_ut_get_type_name (type_needed),
- acpi_ut_get_type_name (this_type), object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [%s], found [%s] %p\n",
+ acpi_ut_get_type_name(type_needed),
+ acpi_ut_get_type_name(this_type), object));
return (AE_AML_OPERAND_TYPE);
}
@@ -114,7 +106,6 @@ acpi_ex_check_object_type (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_resolve_operands
@@ -137,41 +128,37 @@ acpi_ex_check_object_type (
******************************************************************************/
acpi_status
-acpi_ex_resolve_operands (
- u16 opcode,
- union acpi_operand_object **stack_ptr,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_operands(u16 opcode,
+ union acpi_operand_object ** stack_ptr,
+ struct acpi_walk_state * walk_state)
{
- union acpi_operand_object *obj_desc;
- acpi_status status = AE_OK;
- u8 object_type;
- void *temp_node;
- u32 arg_types;
- const struct acpi_opcode_info *op_info;
- u32 this_arg_type;
- acpi_object_type type_needed;
- u16 target_op = 0;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_resolve_operands", opcode);
-
-
- op_info = acpi_ps_get_opcode_info (opcode);
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ u8 object_type;
+ void *temp_node;
+ u32 arg_types;
+ const struct acpi_opcode_info *op_info;
+ u32 this_arg_type;
+ acpi_object_type type_needed;
+ u16 target_op = 0;
+
+ ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode);
+
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
arg_types = op_info->runtime_args;
if (arg_types == ARGI_INVALID_OPCODE) {
- ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
- opcode));
+ ACPI_REPORT_ERROR(("resolve_operands: %X is not a valid AML opcode\n", opcode));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Opcode %X [%s] required_operand_types=%8.8X \n",
- opcode, op_info->name, arg_types));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Opcode %X [%s] required_operand_types=%8.8X \n",
+ opcode, op_info->name, arg_types));
/*
* Normal exit is with (arg_types == 0) at end of argument list.
@@ -180,12 +167,11 @@ acpi_ex_resolve_operands (
* to) the required type; if stack underflows; or upon
* finding a NULL stack entry (which should not happen).
*/
- while (GET_CURRENT_ARG_TYPE (arg_types)) {
+ while (GET_CURRENT_ARG_TYPE(arg_types)) {
if (!stack_ptr || !*stack_ptr) {
- ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
- stack_ptr));
+ ACPI_REPORT_ERROR(("resolve_operands: Null stack entry at %p\n", stack_ptr));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/* Extract useful items */
@@ -194,37 +180,37 @@ acpi_ex_resolve_operands (
/* Decode the descriptor type */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_NAMED:
/* Namespace Node */
- object_type = ((struct acpi_namespace_node *) obj_desc)->type;
+ object_type =
+ ((struct acpi_namespace_node *)obj_desc)->type;
break;
-
case ACPI_DESC_TYPE_OPERAND:
/* ACPI internal object */
- object_type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ object_type = ACPI_GET_OBJECT_TYPE(obj_desc);
/* Check for bad acpi_object_type */
- if (!acpi_ut_valid_object_type (object_type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad operand object type [%X]\n",
- object_type));
+ if (!acpi_ut_valid_object_type(object_type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bad operand object type [%X]\n",
+ object_type));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
/* Decode the Reference */
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
- return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ return_ACPI_STATUS(AE_AML_BAD_OPCODE);
}
switch (obj_desc->reference.opcode) {
@@ -238,51 +224,62 @@ acpi_ex_resolve_operands (
case AML_REF_OF_OP:
case AML_ARG_OP:
case AML_LOCAL_OP:
- case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
- case AML_INT_NAMEPATH_OP: /* Reference to a named object */
-
- ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Operand is a Reference, ref_opcode [%s]\n",
- (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)));
+ case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
+ case AML_INT_NAMEPATH_OP: /* Reference to a named object */
+
+ ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
+ ((ACPI_DB_EXEC,
+ "Operand is a Reference, ref_opcode [%s]\n",
+ (acpi_ps_get_opcode_info
+ (obj_desc->
+ reference.
+ opcode))->
+ name)));
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
- obj_desc->reference.opcode,
- (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name));
-
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
+ obj_desc->reference.
+ opcode,
+ (acpi_ps_get_opcode_info
+ (obj_desc->reference.
+ opcode))->name));
+
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
}
break;
-
default:
/* Invalid descriptor */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid descriptor %p [%s]\n",
- obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid descriptor %p [%s]\n",
+ obj_desc,
+ acpi_ut_get_descriptor_name
+ (obj_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Get one argument type, point to the next */
- this_arg_type = GET_CURRENT_ARG_TYPE (arg_types);
- INCREMENT_ARG_LIST (arg_types);
+ this_arg_type = GET_CURRENT_ARG_TYPE(arg_types);
+ INCREMENT_ARG_LIST(arg_types);
/*
* Handle cases where the object does not need to be
* resolved to a value
*/
switch (this_arg_type) {
- case ARGI_REF_OR_STRING: /* Can be a String or Reference */
+ case ARGI_REF_OR_STRING: /* Can be a String or Reference */
- if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) {
+ if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_OBJECT_TYPE(obj_desc) ==
+ ACPI_TYPE_STRING)) {
/*
* String found - the string references a named object and
* must be resolved to a node
@@ -296,39 +293,40 @@ acpi_ex_resolve_operands (
*/
/*lint -fallthrough */
- case ARGI_REFERENCE: /* References: */
+ case ARGI_REFERENCE: /* References: */
case ARGI_INTEGER_REF:
case ARGI_OBJECT_REF:
case ARGI_DEVICE_REF:
- case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
- case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
- case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
+ case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
+ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
+ case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
/*
* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE
* A Namespace Node is OK as-is
*/
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
goto next_operand;
}
- status = acpi_ex_check_object_type (ACPI_TYPE_LOCAL_REFERENCE,
- object_type, obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_check_object_type(ACPI_TYPE_LOCAL_REFERENCE,
+ object_type, obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (obj_desc->reference.opcode == AML_NAME_OP) {
/* Convert a named reference to the actual named object */
temp_node = obj_desc->reference.object;
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
(*stack_ptr) = temp_node;
}
goto next_operand;
-
- case ARGI_DATAREFOBJ: /* Store operator only */
+ case ARGI_DATAREFOBJ: /* Store operator only */
/*
* We don't want to resolve index_op reference objects during
@@ -337,8 +335,10 @@ acpi_ex_resolve_operands (
* -- All others must be resolved below.
*/
if ((opcode == AML_STORE_OP) &&
- (ACPI_GET_OBJECT_TYPE (*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) &&
- ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
+ (ACPI_GET_OBJECT_TYPE(*stack_ptr) ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && ((*stack_ptr)->reference.opcode ==
+ AML_INDEX_OP)) {
goto next_operand;
}
break;
@@ -351,9 +351,9 @@ acpi_ex_resolve_operands (
/*
* Resolve this object to a value
*/
- status = acpi_ex_resolve_to_value (stack_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_to_value(stack_ptr, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the resolved object */
@@ -364,10 +364,10 @@ acpi_ex_resolve_operands (
* Check the resulting object (value) type
*/
switch (this_arg_type) {
- /*
- * For the simple cases, only one type of resolved object
- * is allowed
- */
+ /*
+ * For the simple cases, only one type of resolved object
+ * is allowed
+ */
case ARGI_MUTEX:
/* Need an operand of type ACPI_TYPE_MUTEX */
@@ -382,7 +382,7 @@ acpi_ex_resolve_operands (
type_needed = ACPI_TYPE_EVENT;
break;
- case ARGI_PACKAGE: /* Package */
+ case ARGI_PACKAGE: /* Package */
/* Need an operand of type ACPI_TYPE_PACKAGE */
@@ -403,10 +403,9 @@ acpi_ex_resolve_operands (
type_needed = ACPI_TYPE_LOCAL_REFERENCE;
break;
-
- /*
- * The more complex cases allow multiple resolved object types
- */
+ /*
+ * The more complex cases allow multiple resolved object types
+ */
case ARGI_INTEGER:
/*
@@ -414,20 +413,26 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a STRING or BUFFER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_BUFFER:
@@ -436,20 +441,25 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a STRING or INTEGER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_STRING:
@@ -458,75 +468,86 @@ acpi_ex_resolve_operands (
* But we can implicitly convert from a BUFFER or INTEGER
* Aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_string (obj_desc, stack_ptr,
- ACPI_IMPLICIT_CONVERT_HEX);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_convert_to_string(obj_desc, stack_ptr,
+ ACPI_IMPLICIT_CONVERT_HEX);
+ if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc),
+ obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- goto next_operand;
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
+ }
+ goto next_operand;
case ARGI_COMPUTEDATA:
/* Need an operand of type INTEGER, STRING or BUFFER */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
- break;
+ break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_BUFFER_OR_STRING:
/* Need an operand of type STRING or BUFFER */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
/* Valid operand */
- break;
+ break;
case ACPI_TYPE_INTEGER:
/* Highest priority conversion is to type Buffer */
- status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_convert_to_buffer(obj_desc,
+ stack_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ if (obj_desc != *stack_ptr) {
+ acpi_ut_remove_reference(obj_desc);
}
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Integer/String/Buffer], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Integer/String/Buffer], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_DATAOBJECT:
/*
* ARGI_DATAOBJECT is only used by the size_of operator.
@@ -535,7 +556,7 @@ acpi_ex_resolve_operands (
* The only reference allowed here is a direct reference to
* a namespace node.
*/
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -545,20 +566,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Buffer/String/Package/Reference], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_COMPLEXOBJ:
/* Need a buffer or package or (ACPI 2.0) String */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -567,20 +588,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Buffer/String/Package], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Buffer/String/Package], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_REGION_OR_FIELD:
/* Need an operand of type REGION or a FIELD in a region */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_REGION:
case ACPI_TYPE_LOCAL_REGION_FIELD:
case ACPI_TYPE_LOCAL_BANK_FIELD:
@@ -590,20 +611,20 @@ acpi_ex_resolve_operands (
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed [Region/region_field], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed [Region/region_field], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
case ARGI_DATAREFOBJ:
/* Used by the Store() operator only */
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_STRING:
@@ -635,47 +656,46 @@ acpi_ex_resolve_operands (
break;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
- acpi_ut_get_object_type_name (obj_desc), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
+ acpi_ut_get_object_type_name
+ (obj_desc), obj_desc));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
goto next_operand;
-
default:
/* Unknown type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Internal - Unknown ARGI (required operand) type %X\n",
- this_arg_type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Internal - Unknown ARGI (required operand) type %X\n",
+ this_arg_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Make sure that the original object was resolved to the
* required object type (Simple cases only).
*/
- status = acpi_ex_check_object_type (type_needed,
- ACPI_GET_OBJECT_TYPE (*stack_ptr), *stack_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_check_object_type(type_needed,
+ ACPI_GET_OBJECT_TYPE
+ (*stack_ptr), *stack_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
-next_operand:
+ next_operand:
/*
* If more operands needed, decrement stack_ptr to point
* to next operand on stack
*/
- if (GET_CURRENT_ARG_TYPE (arg_types)) {
+ if (GET_CURRENT_ARG_TYPE(arg_types)) {
stack_ptr--;
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 2725db0901b8..a7d8eea305c2 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
@@ -50,24 +49,18 @@
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstore")
+ACPI_MODULE_NAME("exstore")
/* Local prototypes */
-
static void
-acpi_ex_do_debug_object (
- union acpi_operand_object *source_desc,
- u32 level,
- u32 index);
+acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ u32 level, u32 index);
static acpi_status
-acpi_ex_store_object_to_index (
- union acpi_operand_object *val_desc,
- union acpi_operand_object *dest_desc,
- struct acpi_walk_state *walk_state);
-
+acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
+ union acpi_operand_object *dest_desc,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -84,136 +77,146 @@ acpi_ex_store_object_to_index (
******************************************************************************/
static void
-acpi_ex_do_debug_object (
- union acpi_operand_object *source_desc,
- u32 level,
- u32 index)
+acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
+ u32 level, u32 index)
{
- u32 i;
-
+ u32 i;
- ACPI_FUNCTION_TRACE_PTR ("ex_do_debug_object", source_desc);
+ ACPI_FUNCTION_TRACE_PTR("ex_do_debug_object", source_desc);
-
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
- level, " "));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
+ level, " "));
/* Display index for package output only */
if (index > 0) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
- "(%.2u) ", index -1));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "(%.2u) ", index - 1));
}
if (!source_desc) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
return_VOID;
}
- if (ACPI_GET_DESCRIPTOR_TYPE (source_desc) == ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s: ",
- acpi_ut_get_object_type_name (source_desc)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ",
+ acpi_ut_get_object_type_name
+ (source_desc)));
- if (!acpi_ut_valid_internal_object (source_desc)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
- "%p, Invalid Internal Object!\n", source_desc));
- return_VOID;
+ if (!acpi_ut_valid_internal_object(source_desc)) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "%p, Invalid Internal Object!\n",
+ source_desc));
+ return_VOID;
}
- }
- else if (ACPI_GET_DESCRIPTOR_TYPE (source_desc) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
- acpi_ut_get_type_name (((struct acpi_namespace_node *) source_desc)->type),
- source_desc));
+ } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
+ acpi_ut_get_type_name(((struct
+ acpi_namespace_node
+ *)source_desc)->
+ type),
+ source_desc));
return_VOID;
- }
- else {
+ } else {
return_VOID;
}
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
/* Output correct integer width */
if (acpi_gbl_integer_byte_width == 4) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
- (u32) source_desc->integer.value));
- }
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (source_desc->integer.value)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
+ (u32) source_desc->integer.
+ value));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "0x%8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(source_desc->
+ integer.
+ value)));
}
break;
case ACPI_TYPE_BUFFER:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]",
- (u32) source_desc->buffer.length));
- ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
- (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n",
+ (u32) source_desc->buffer.length));
+ ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
+ (source_desc->buffer.length <
+ 32) ? source_desc->buffer.length : 32);
break;
case ACPI_TYPE_STRING:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
- source_desc->string.length, source_desc->string.pointer));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
+ source_desc->string.length,
+ source_desc->string.pointer));
break;
case ACPI_TYPE_PACKAGE:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X Elements]\n",
- source_desc->package.count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "[0x%.2X Elements]\n",
+ source_desc->package.count));
/* Output the entire contents of the package */
for (i = 0; i < source_desc->package.count; i++) {
- acpi_ex_do_debug_object (source_desc->package.elements[i],
- level+4, i+1);
+ acpi_ex_do_debug_object(source_desc->package.
+ elements[i], level + 4, i + 1);
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
if (source_desc->reference.opcode == AML_INDEX_OP) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[%s, 0x%X]\n",
- acpi_ps_get_opcode_name (source_desc->reference.opcode),
- source_desc->reference.offset));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
+ "[%s, 0x%X]\n",
+ acpi_ps_get_opcode_name
+ (source_desc->reference.opcode),
+ source_desc->reference.offset));
+ } else {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
+ acpi_ps_get_opcode_name
+ (source_desc->reference.opcode)));
}
- else {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
- acpi_ps_get_opcode_name (source_desc->reference.opcode)));
- }
-
if (source_desc->reference.object) {
- if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) ==
- ACPI_DESC_TYPE_NAMED) {
- acpi_ex_do_debug_object (((struct acpi_namespace_node *)
- source_desc->reference.object)->object,
- level+4, 0);
+ if (ACPI_GET_DESCRIPTOR_TYPE
+ (source_desc->reference.object) ==
+ ACPI_DESC_TYPE_NAMED) {
+ acpi_ex_do_debug_object(((struct
+ acpi_namespace_node *)
+ source_desc->reference.
+ object)->object,
+ level + 4, 0);
+ } else {
+ acpi_ex_do_debug_object(source_desc->reference.
+ object, level + 4, 0);
}
- else {
- acpi_ex_do_debug_object (source_desc->reference.object, level+4, 0);
- }
- }
- else if (source_desc->reference.node) {
- acpi_ex_do_debug_object ((source_desc->reference.node)->object,
- level+4, 0);
+ } else if (source_desc->reference.node) {
+ acpi_ex_do_debug_object((source_desc->reference.node)->
+ object, level + 4, 0);
}
break;
default:
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
- source_desc, acpi_ut_get_object_type_name (source_desc)));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
+ source_desc,
+ acpi_ut_get_object_type_name
+ (source_desc)));
break;
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n"));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store
@@ -235,42 +238,41 @@ acpi_ex_do_debug_object (
******************************************************************************/
acpi_status
-acpi_ex_store (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *ref_desc = dest_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *ref_desc = dest_desc;
+ ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc);
/* Validate parameters */
if (!source_desc || !dest_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n"));
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null parameter\n"));
+ return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/* dest_desc can be either a namespace node or an ACPI object */
- if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
/*
* Dest is a namespace node,
* Storing an object into a Named node.
*/
- status = acpi_ex_store_object_to_node (source_desc,
- (struct acpi_namespace_node *) dest_desc, walk_state,
- ACPI_IMPLICIT_CONVERSION);
+ status = acpi_ex_store_object_to_node(source_desc,
+ (struct
+ acpi_namespace_node *)
+ dest_desc, walk_state,
+ ACPI_IMPLICIT_CONVERSION);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Destination object must be a Reference or a Constant object */
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
break;
@@ -279,7 +281,7 @@ acpi_ex_store (
/* Allow stores to Constants -- a Noop as per ACPI spec */
if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*lint -fallthrough */
@@ -288,16 +290,18 @@ acpi_ex_store (
/* Destination is not a Reference object */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target is not a Reference or Constant object - %s [%p]\n",
- acpi_ut_get_object_type_name (dest_desc), dest_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target is not a Reference or Constant object - %s [%p]\n",
+ acpi_ut_get_object_type_name(dest_desc),
+ dest_desc));
- ACPI_DUMP_STACK_ENTRY (source_desc);
- ACPI_DUMP_STACK_ENTRY (dest_desc);
- ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
- 2, "Target is not a Reference or Constant object");
+ ACPI_DUMP_STACK_ENTRY(source_desc);
+ ACPI_DUMP_STACK_ENTRY(dest_desc);
+ ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
+ 2,
+ "Target is not a Reference or Constant object");
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
@@ -314,58 +318,59 @@ acpi_ex_store (
/* Storing an object into a Name "container" */
- status = acpi_ex_store_object_to_node (source_desc,
- ref_desc->reference.object,
- walk_state, ACPI_IMPLICIT_CONVERSION);
+ status = acpi_ex_store_object_to_node(source_desc,
+ ref_desc->reference.
+ object, walk_state,
+ ACPI_IMPLICIT_CONVERSION);
break;
-
case AML_INDEX_OP:
/* Storing to an Index (pointer into a packager or buffer) */
- status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state);
+ status =
+ acpi_ex_store_object_to_index(source_desc, ref_desc,
+ walk_state);
break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
/* Store to a method local/arg */
- status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
- ref_desc->reference.offset, source_desc, walk_state);
+ status =
+ acpi_ds_store_object_to_local(ref_desc->reference.opcode,
+ ref_desc->reference.offset,
+ source_desc, walk_state);
break;
-
case AML_DEBUG_OP:
/*
* Storing to the Debug object causes the value stored to be
* displayed and otherwise has no effect -- see ACPI Specification
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "**** Write to Debug Object: Object %p %s ****:\n\n",
- source_desc, acpi_ut_get_object_type_name (source_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "**** Write to Debug Object: Object %p %s ****:\n\n",
+ source_desc,
+ acpi_ut_get_object_type_name(source_desc)));
- acpi_ex_do_debug_object (source_desc, 0, 0);
+ acpi_ex_do_debug_object(source_desc, 0, 0);
break;
-
default:
- ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
- ref_desc->reference.opcode));
- ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
+ ACPI_REPORT_ERROR(("ex_store: Unknown Reference opcode %X\n",
+ ref_desc->reference.opcode));
+ ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR);
status = AE_AML_INTERNAL;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_index
@@ -381,20 +386,17 @@ acpi_ex_store (
******************************************************************************/
static acpi_status
-acpi_ex_store_object_to_index (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *index_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
+ union acpi_operand_object *index_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *new_desc;
- u8 value = 0;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *new_desc;
+ u8 value = 0;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ex_store_object_to_index");
/*
* Destination must be a reference pointer, and
@@ -413,19 +415,20 @@ acpi_ex_store_object_to_index (
*/
obj_desc = *(index_desc->reference.where);
- status = acpi_ut_copy_iobject_to_iobject (source_desc, &new_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (obj_desc) {
/* Decrement reference count by the ref count of the parent package */
- for (i = 0;
- i < ((union acpi_operand_object *)
- index_desc->reference.object)->common.reference_count;
- i++) {
- acpi_ut_remove_reference (obj_desc);
+ for (i = 0; i < ((union acpi_operand_object *)
+ index_desc->reference.object)->common.
+ reference_count; i++) {
+ acpi_ut_remove_reference(obj_desc);
}
}
@@ -433,16 +436,14 @@ acpi_ex_store_object_to_index (
/* Increment ref count by the ref count of the parent package-1 */
- for (i = 1;
- i < ((union acpi_operand_object *)
- index_desc->reference.object)->common.reference_count;
- i++) {
- acpi_ut_add_reference (new_desc);
+ for (i = 1; i < ((union acpi_operand_object *)
+ index_desc->reference.object)->common.
+ reference_count; i++) {
+ acpi_ut_add_reference(new_desc);
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
/*
@@ -460,16 +461,16 @@ acpi_ex_store_object_to_index (
* by the INDEX_OP code.
*/
obj_desc = index_desc->reference.object;
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) &&
- (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_STRING)) {
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) &&
+ (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) {
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/*
* The assignment of the individual elements will be slightly
* different for each source type.
*/
- switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
case ACPI_TYPE_INTEGER:
/* Use the least-significant byte of the integer */
@@ -489,10 +490,11 @@ acpi_ex_store_object_to_index (
/* All other types are invalid */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Source must be Integer/Buffer/String type, not %s\n",
- acpi_ut_get_object_type_name (source_desc)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Source must be Integer/Buffer/String type, not %s\n",
+ acpi_ut_get_object_type_name
+ (source_desc)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Store the source value into the target buffer byte */
@@ -500,18 +502,16 @@ acpi_ex_store_object_to_index (
obj_desc->buffer.pointer[index_desc->reference.offset] = value;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Target is not a Package or buffer_field\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Target is not a Package or buffer_field\n"));
status = AE_AML_OPERAND_TYPE;
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_node
@@ -539,42 +539,40 @@ acpi_ex_store_object_to_index (
******************************************************************************/
acpi_status
-acpi_ex_store_object_to_node (
- union acpi_operand_object *source_desc,
- struct acpi_namespace_node *node,
- struct acpi_walk_state *walk_state,
- u8 implicit_conversion)
+acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
+ struct acpi_namespace_node *node,
+ struct acpi_walk_state *walk_state,
+ u8 implicit_conversion)
{
- acpi_status status = AE_OK;
- union acpi_operand_object *target_desc;
- union acpi_operand_object *new_desc;
- acpi_object_type target_type;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc);
+ acpi_status status = AE_OK;
+ union acpi_operand_object *target_desc;
+ union acpi_operand_object *new_desc;
+ acpi_object_type target_type;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc);
/* Get current type of the node, and object attached to Node */
- target_type = acpi_ns_get_type (node);
- target_desc = acpi_ns_get_attached_object (node);
+ target_type = acpi_ns_get_type(node);
+ target_desc = acpi_ns_get_attached_object(node);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
- source_desc, acpi_ut_get_object_type_name (source_desc),
- node, acpi_ut_get_type_name (target_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
+ source_desc,
+ acpi_ut_get_object_type_name(source_desc), node,
+ acpi_ut_get_type_name(target_type)));
/*
* Resolve the source object to an actual value
* (If it is a reference object)
*/
- status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* If no implicit conversion, drop into the default case below */
- if (!implicit_conversion) {
+ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
/* Force execution of default (no implicit conversion) */
target_type = ACPI_TYPE_ANY;
@@ -590,11 +588,10 @@ acpi_ex_store_object_to_node (
/* For fields, copy the source data to the target field. */
- status = acpi_ex_write_data_to_field (source_desc, target_desc,
- &walk_state->result_obj);
+ status = acpi_ex_write_data_to_field(source_desc, target_desc,
+ &walk_state->result_obj);
break;
-
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
@@ -605,10 +602,11 @@ acpi_ex_store_object_to_node (
*
* Copy and/or convert the source object to a new target object
*/
- status = acpi_ex_store_object_to_object (source_desc, target_desc,
- &new_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_store_object_to_object(source_desc, target_desc,
+ &new_desc, walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (new_desc != target_desc) {
@@ -621,30 +619,33 @@ acpi_ex_store_object_to_node (
* has been performed such that the node/object type has been
* changed.
*/
- status = acpi_ns_attach_object (node, new_desc, new_desc->common.type);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Store %s into %s via Convert/Attach\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_object_type_name (new_desc)));
+ status =
+ acpi_ns_attach_object(node, new_desc,
+ new_desc->common.type);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Store %s into %s via Convert/Attach\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_object_type_name
+ (new_desc)));
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Storing %s (%p) directly into node (%p), no implicit conversion\n",
- acpi_ut_get_object_type_name (source_desc), source_desc, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
+ acpi_ut_get_object_type_name(source_desc),
+ source_desc, node));
/* No conversions for all other types. Just attach the source object */
- status = acpi_ns_attach_object (node, source_desc,
- ACPI_GET_OBJECT_TYPE (source_desc));
+ status = acpi_ns_attach_object(node, source_desc,
+ ACPI_GET_OBJECT_TYPE
+ (source_desc));
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 120f30ed0bd4..382f63c14ea1 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -43,15 +43,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstoren")
-
+ACPI_MODULE_NAME("exstoren")
/*******************************************************************************
*
@@ -67,19 +64,15 @@
* it and return the actual object in the source_desc_ptr.
*
******************************************************************************/
-
acpi_status
-acpi_ex_resolve_object (
- union acpi_operand_object **source_desc_ptr,
- acpi_object_type target_type,
- struct acpi_walk_state *walk_state)
+acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
+ acpi_object_type target_type,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *source_desc = *source_desc_ptr;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_resolve_object");
+ union acpi_operand_object *source_desc = *source_desc_ptr;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_resolve_object");
/* Ensure we have a Target that can be stored to */
@@ -102,11 +95,14 @@ acpi_ex_resolve_object (
* are all essentially the same. This case handles the
* "interchangeable" types Integer, String, and Buffer.
*/
- if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
+ if (ACPI_GET_OBJECT_TYPE(source_desc) ==
+ ACPI_TYPE_LOCAL_REFERENCE) {
/* Resolve a reference object first */
- status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ex_resolve_to_value(source_desc_ptr,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
break;
}
}
@@ -119,31 +115,32 @@ acpi_ex_resolve_object (
/* Must have a Integer, Buffer, or String */
- if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) &&
- (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) &&
- (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) &&
- !((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) {
+ if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) &&
+ (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) &&
+ (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) &&
+ !((ACPI_GET_OBJECT_TYPE(source_desc) ==
+ ACPI_TYPE_LOCAL_REFERENCE)
+ && (source_desc->reference.opcode == AML_LOAD_OP))) {
/* Conversion successful but still not a valid type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
- acpi_ut_get_object_type_name (source_desc),
- acpi_ut_get_type_name (target_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
+ acpi_ut_get_object_type_name
+ (source_desc),
+ acpi_ut_get_type_name(target_type)));
status = AE_AML_OPERAND_TYPE;
}
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
/* Aliases are resolved by acpi_ex_prep_operands */
- ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
+ ACPI_REPORT_ERROR(("Store into Alias - should never happen\n"));
status = AE_AML_INTERNAL;
break;
-
case ACPI_TYPE_PACKAGE:
default:
@@ -154,10 +151,9 @@ acpi_ex_resolve_object (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_object_to_object
@@ -194,18 +190,15 @@ acpi_ex_resolve_object (
******************************************************************************/
acpi_status
-acpi_ex_store_object_to_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc,
- union acpi_operand_object **new_desc,
- struct acpi_walk_state *walk_state)
+acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc,
+ union acpi_operand_object **new_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *actual_src_desc;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
+ union acpi_operand_object *actual_src_desc;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_object", source_desc);
actual_src_desc = source_desc;
if (!dest_desc) {
@@ -214,11 +207,14 @@ acpi_ex_store_object_to_object (
* package element), so we can simply copy the source object
* creating a new destination object
*/
- status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_iobject_to_iobject(actual_src_desc, new_desc,
+ walk_state);
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ if (ACPI_GET_OBJECT_TYPE(source_desc) !=
+ ACPI_GET_OBJECT_TYPE(dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
@@ -228,10 +224,13 @@ acpi_ex_store_object_to_object (
* Otherwise, actual_src_desc is a temporary object to hold the
* converted object.
*/
- status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc),
- source_desc, &actual_src_desc, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE
+ (dest_desc), source_desc,
+ &actual_src_desc,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (source_desc == actual_src_desc) {
@@ -240,7 +239,7 @@ acpi_ex_store_object_to_object (
* new object.
*/
*new_desc = source_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -248,42 +247,42 @@ acpi_ex_store_object_to_object (
* We now have two objects of identical types, and we can perform a
* copy of the *value* of the source object.
*/
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
case ACPI_TYPE_INTEGER:
dest_desc->integer.value = actual_src_desc->integer.value;
/* Truncate value if we are executing from a 32-bit ACPI table */
- acpi_ex_truncate_for32bit_table (dest_desc);
+ acpi_ex_truncate_for32bit_table(dest_desc);
break;
case ACPI_TYPE_STRING:
- status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc);
+ status =
+ acpi_ex_store_string_to_string(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_BUFFER:
- /*
- * Note: There is different store behavior depending on the original
- * source type
- */
- status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
+ status =
+ acpi_ex_store_buffer_to_buffer(actual_src_desc, dest_desc);
break;
case ACPI_TYPE_PACKAGE:
- status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc,
- walk_state);
+ status =
+ acpi_ut_copy_iobject_to_iobject(actual_src_desc, &dest_desc,
+ walk_state);
break;
default:
/*
* All other types come here.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n",
- acpi_ut_get_object_type_name (dest_desc)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Store into type %s not implemented\n",
+ acpi_ut_get_object_type_name(dest_desc)));
status = AE_NOT_IMPLEMENTED;
break;
@@ -292,11 +291,9 @@ acpi_ex_store_object_to_object (
if (actual_src_desc != source_desc) {
/* Delete the intermediate (temporary) source object */
- acpi_ut_remove_reference (actual_src_desc);
+ acpi_ut_remove_reference(actual_src_desc);
}
*new_desc = dest_desc;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 12d1527669c8..c4ff654a6697 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exstorob")
-
+ACPI_MODULE_NAME("exstorob")
/*******************************************************************************
*
@@ -63,18 +60,14 @@
* DESCRIPTION: Copy a buffer object to another buffer object.
*
******************************************************************************/
-
acpi_status
-acpi_ex_store_buffer_to_buffer (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc)
+acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc)
{
- u32 length;
- u8 *buffer;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
+ u32 length;
+ u8 *buffer;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc);
/* We know that source_desc is a buffer by now */
@@ -86,10 +79,10 @@ acpi_ex_store_buffer_to_buffer (
* allocate a new buffer of the proper length
*/
if ((target_desc->buffer.length == 0) ||
- (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
- target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length);
+ (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
+ target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length);
if (!target_desc->buffer.pointer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->buffer.length = length;
@@ -100,8 +93,9 @@ acpi_ex_store_buffer_to_buffer (
if (length <= target_desc->buffer.length) {
/* Clear existing buffer and copy in the new one */
- ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
- ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
+ ACPI_MEMSET(target_desc->buffer.pointer, 0,
+ target_desc->buffer.length);
+ ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length);
#ifdef ACPI_OBSOLETE_BEHAVIOR
/*
@@ -124,26 +118,24 @@ acpi_ex_store_buffer_to_buffer (
target_desc->buffer.length = length;
}
#endif
- }
- else {
+ } else {
/* Truncate the source, copy only what will fit */
- ACPI_MEMCPY (target_desc->buffer.pointer, buffer,
- target_desc->buffer.length);
+ ACPI_MEMCPY(target_desc->buffer.pointer, buffer,
+ target_desc->buffer.length);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Truncating source buffer from %X to %X\n",
- length, target_desc->buffer.length));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Truncating source buffer from %X to %X\n",
+ length, target_desc->buffer.length));
}
/* Copy flags */
target_desc->buffer.flags = source_desc->buffer.flags;
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_store_string_to_string
@@ -158,16 +150,13 @@ acpi_ex_store_buffer_to_buffer (
******************************************************************************/
acpi_status
-acpi_ex_store_string_to_string (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *target_desc)
+acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
+ union acpi_operand_object *target_desc)
{
- u32 length;
- u8 *buffer;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
+ u32 length;
+ u8 *buffer;
+ ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc);
/* We know that source_desc is a string by now */
@@ -179,41 +168,38 @@ acpi_ex_store_string_to_string (
* pointer is not a static pointer (part of an ACPI table)
*/
if ((length < target_desc->string.length) &&
- (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+ (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
/*
* String will fit in existing non-static buffer.
* Clear old string and copy in the new one
*/
- ACPI_MEMSET (target_desc->string.pointer, 0,
- (acpi_size) target_desc->string.length + 1);
- ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
- }
- else {
+ ACPI_MEMSET(target_desc->string.pointer, 0,
+ (acpi_size) target_desc->string.length + 1);
+ ACPI_MEMCPY(target_desc->string.pointer, buffer, length);
+ } else {
/*
* Free the current buffer, then allocate a new buffer
* large enough to hold the value
*/
if (target_desc->string.pointer &&
- (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+ (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
/* Only free if not a pointer into the DSDT */
- ACPI_MEM_FREE (target_desc->string.pointer);
+ ACPI_MEM_FREE(target_desc->string.pointer);
}
- target_desc->string.pointer = ACPI_MEM_CALLOCATE (
- (acpi_size) length + 1);
+ target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size)
+ length + 1);
if (!target_desc->string.pointer) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
+ ACPI_MEMCPY(target_desc->string.pointer, buffer, length);
}
/* Set the new target length */
target_desc->string.length = length;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index cafa702108dc..8a88b841237d 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -42,14 +42,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exsystem")
-
+ACPI_MODULE_NAME("exsystem")
/*******************************************************************************
*
@@ -65,49 +63,42 @@
* interpreter is released.
*
******************************************************************************/
-
-acpi_status
-acpi_ex_system_wait_semaphore (
- acpi_handle semaphore,
- u16 timeout)
+acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
{
- acpi_status status;
- acpi_status status2;
-
+ acpi_status status;
+ acpi_status status2;
- ACPI_FUNCTION_TRACE ("ex_system_wait_semaphore");
+ ACPI_FUNCTION_TRACE("ex_system_wait_semaphore");
-
- status = acpi_os_wait_semaphore (semaphore, 1, 0);
- if (ACPI_SUCCESS (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_wait_semaphore(semaphore, 1, 0);
+ if (ACPI_SUCCESS(status)) {
+ return_ACPI_STATUS(status);
}
if (status == AE_TIME) {
/* We must wait, so unlock the interpreter */
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- status = acpi_os_wait_semaphore (semaphore, 1, timeout);
+ status = acpi_os_wait_semaphore(semaphore, 1, timeout);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "*** Thread awake after blocking, %s\n",
- acpi_format_exception (status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "*** Thread awake after blocking, %s\n",
+ acpi_format_exception(status)));
/* Reacquire the interpreter */
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
/* Report fatal error, could not acquire interpreter */
- return_ACPI_STATUS (status2);
+ return_ACPI_STATUS(status2);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_stall
@@ -125,35 +116,29 @@ acpi_ex_system_wait_semaphore (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_do_stall (
- u32 how_long)
+acpi_status acpi_ex_system_do_stall(u32 how_long)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- if (how_long > 255) /* 255 microseconds */ {
+ if (how_long > 255) { /* 255 microseconds */
/*
* Longer than 255 usec, this is an error
*
* (ACPI specifies 100 usec as max, but this gives some slack in
* order to support existing BIOSs)
*/
- ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n",
- how_long));
+ ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n",
+ how_long));
status = AE_AML_OPERAND_VALUE;
- }
- else {
- acpi_os_stall (how_long);
+ } else {
+ acpi_os_stall(how_long);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_do_suspend
@@ -167,29 +152,24 @@ acpi_ex_system_do_stall (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_do_suspend (
- acpi_integer how_long)
+acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Since this thread will sleep, we must release the interpreter */
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- acpi_os_sleep (how_long);
+ acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
- status = acpi_ex_enter_interpreter ();
+ status = acpi_ex_enter_interpreter();
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_acquire_mutex
@@ -206,33 +186,30 @@ acpi_ex_system_do_suspend (
******************************************************************************/
acpi_status
-acpi_ex_system_acquire_mutex (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc)
+acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc,
+ union acpi_operand_object * obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ex_system_acquire_mutex", obj_desc);
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc);
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Support for the _GL_ Mutex object -- go get the global lock */
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
- status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ev_acquire_global_lock((u16) time_desc->integer.value);
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore,
- (u16) time_desc->integer.value);
- return_ACPI_STATUS (status);
+ status = acpi_ex_system_wait_semaphore(obj_desc->mutex.semaphore,
+ (u16) time_desc->integer.value);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_release_mutex
@@ -248,32 +225,27 @@ acpi_ex_system_acquire_mutex (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_release_mutex (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_system_release_mutex");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_release_mutex");
if (!obj_desc) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Support for the _GL_ Mutex object -- release the global lock */
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
- status = acpi_ev_release_global_lock ();
- return_ACPI_STATUS (status);
+ status = acpi_ev_release_global_lock();
+ return_ACPI_STATUS(status);
}
- status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1);
- return_ACPI_STATUS (status);
+ status = acpi_os_signal_semaphore(obj_desc->mutex.semaphore, 1);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_signal_event
@@ -287,24 +259,19 @@ acpi_ex_system_release_mutex (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_signal_event (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_system_signal_event");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_signal_event");
if (obj_desc) {
- status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1);
+ status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_wait_event
@@ -321,25 +288,23 @@ acpi_ex_system_signal_event (
******************************************************************************/
acpi_status
-acpi_ex_system_wait_event (
- union acpi_operand_object *time_desc,
- union acpi_operand_object *obj_desc)
+acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
+ union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ex_system_wait_event");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ex_system_wait_event");
if (obj_desc) {
- status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore,
- (u16) time_desc->integer.value);
+ status =
+ acpi_ex_system_wait_semaphore(obj_desc->event.semaphore,
+ (u16) time_desc->integer.
+ value);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_system_reset_event
@@ -352,27 +317,23 @@ acpi_ex_system_wait_event (
*
******************************************************************************/
-acpi_status
-acpi_ex_system_reset_event (
- union acpi_operand_object *obj_desc)
+acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
{
- acpi_status status = AE_OK;
- void *temp_semaphore;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status = AE_OK;
+ void *temp_semaphore;
+ ACPI_FUNCTION_ENTRY();
/*
* We are going to simply delete the existing semaphore and
* create a new one!
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
- if (ACPI_SUCCESS (status)) {
- (void) acpi_os_delete_semaphore (obj_desc->event.semaphore);
+ status =
+ acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
+ if (ACPI_SUCCESS(status)) {
+ (void)acpi_os_delete_semaphore(obj_desc->event.semaphore);
obj_desc->event.semaphore = temp_semaphore;
}
return (status);
}
-
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index 5c7ec0c04177..1ee79d8c8f88 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
/*
* DEFINE_AML_GLOBALS is tested in amlcode.h
* to determine whether certain global names should be "defined" or only
@@ -65,15 +64,10 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_EXECUTER
- ACPI_MODULE_NAME ("exutils")
+ACPI_MODULE_NAME("exutils")
/* Local prototypes */
-
-static u32
-acpi_ex_digits_needed (
- acpi_integer value,
- u32 base);
-
+static u32 acpi_ex_digits_needed(acpi_integer value, u32 base);
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
@@ -89,24 +83,20 @@ acpi_ex_digits_needed (
*
******************************************************************************/
-acpi_status
-acpi_ex_enter_interpreter (
- void)
+acpi_status acpi_ex_enter_interpreter(void)
{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE ("ex_enter_interpreter");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_enter_interpreter");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n"));
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n"));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_exit_interpreter
@@ -129,25 +119,20 @@ acpi_ex_enter_interpreter (
*
******************************************************************************/
-void
-acpi_ex_exit_interpreter (
- void)
+void acpi_ex_exit_interpreter(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_exit_interpreter");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_exit_interpreter");
- status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not release interpreter mutex\n"));
+ status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not release interpreter mutex\n"));
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_truncate_for32bit_table
@@ -161,20 +146,17 @@ acpi_ex_exit_interpreter (
*
******************************************************************************/
-void
-acpi_ex_truncate_for32bit_table (
- union acpi_operand_object *obj_desc)
+void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/*
* Object must be a valid number and we must be executing
* a control method
*/
if ((!obj_desc) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
return;
}
@@ -187,7 +169,6 @@ acpi_ex_truncate_for32bit_table (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_acquire_global_lock
@@ -203,37 +184,31 @@ acpi_ex_truncate_for32bit_table (
*
******************************************************************************/
-u8
-acpi_ex_acquire_global_lock (
- u32 field_flags)
+u8 acpi_ex_acquire_global_lock(u32 field_flags)
{
- u8 locked = FALSE;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_acquire_global_lock");
+ u8 locked = FALSE;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_acquire_global_lock");
/* Only attempt lock if the always_lock bit is set */
if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
/* We should attempt to get the lock, wait forever */
- status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
+ if (ACPI_SUCCESS(status)) {
locked = TRUE;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not acquire Global Lock, %s\n",
- acpi_format_exception (status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not acquire Global Lock, %s\n",
+ acpi_format_exception(status)));
}
}
- return_VALUE (locked);
+ return_VALUE(locked);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_release_global_lock
@@ -247,34 +222,28 @@ acpi_ex_acquire_global_lock (
*
******************************************************************************/
-void
-acpi_ex_release_global_lock (
- u8 locked_by_me)
+void acpi_ex_release_global_lock(u8 locked_by_me)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ex_release_global_lock");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ex_release_global_lock");
/* Only attempt unlock if the caller locked it */
if (locked_by_me) {
/* OK, now release the lock */
- status = acpi_ev_release_global_lock ();
- if (ACPI_FAILURE (status)) {
+ status = acpi_ev_release_global_lock();
+ if (ACPI_FAILURE(status)) {
/* Report the error, but there isn't much else we can do */
- ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n",
- acpi_format_exception (status)));
+ ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status)));
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_digits_needed
@@ -289,22 +258,17 @@ acpi_ex_release_global_lock (
*
******************************************************************************/
-static u32
-acpi_ex_digits_needed (
- acpi_integer value,
- u32 base)
+static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
{
- u32 num_digits;
- acpi_integer current_value;
-
-
- ACPI_FUNCTION_TRACE ("ex_digits_needed");
+ u32 num_digits;
+ acpi_integer current_value;
+ ACPI_FUNCTION_TRACE("ex_digits_needed");
/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
if (value == 0) {
- return_VALUE (1);
+ return_VALUE(1);
}
current_value = value;
@@ -313,14 +277,14 @@ acpi_ex_digits_needed (
/* Count the digits in the requested base */
while (current_value) {
- (void) acpi_ut_short_divide (current_value, base, &current_value, NULL);
+ (void)acpi_ut_short_divide(current_value, base, &current_value,
+ NULL);
num_digits++;
}
- return_VALUE (num_digits);
+ return_VALUE(num_digits);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_eisa_id_to_string
@@ -334,32 +298,26 @@ acpi_ex_digits_needed (
*
******************************************************************************/
-void
-acpi_ex_eisa_id_to_string (
- u32 numeric_id,
- char *out_string)
+void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string)
{
- u32 eisa_id;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 eisa_id;
+ ACPI_FUNCTION_ENTRY();
/* Swap ID to big-endian to get contiguous bits */
- eisa_id = acpi_ut_dword_byte_swap (numeric_id);
+ eisa_id = acpi_ut_dword_byte_swap(numeric_id);
- out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f));
- out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f));
- out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f));
- out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12);
- out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8);
- out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4);
- out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0);
+ out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f));
+ out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f));
+ out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f));
+ out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12);
+ out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8);
+ out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4);
+ out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0);
out_string[7] = 0;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ex_unsigned_integer_to_string
@@ -369,30 +327,25 @@ acpi_ex_eisa_id_to_string (
*
* RETURN: None, string
*
- * DESCRIPTOIN: Convert a number to string representation. Assumes string
+ * DESCRIPTION: Convert a number to string representation. Assumes string
* buffer is large enough to hold the string.
*
******************************************************************************/
-void
-acpi_ex_unsigned_integer_to_string (
- acpi_integer value,
- char *out_string)
+void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string)
{
- u32 count;
- u32 digits_needed;
- u32 remainder;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 count;
+ u32 digits_needed;
+ u32 remainder;
+ ACPI_FUNCTION_ENTRY();
- digits_needed = acpi_ex_digits_needed (value, 10);
+ digits_needed = acpi_ex_digits_needed(value, 10);
out_string[digits_needed] = 0;
for (count = digits_needed; count > 0; count--) {
- (void) acpi_ut_short_divide (value, 10, &value, &remainder);
- out_string[count-1] = (char) ('0' + remainder);\
+ (void)acpi_ut_short_divide(value, 10, &value, &remainder);
+ out_string[count - 1] = (char)('0' + remainder);
}
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 14192ee55f8f..e8165c4f162a 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -34,52 +34,45 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define ACPI_FAN_COMPONENT 0x00200000
#define ACPI_FAN_CLASS "fan"
-#define ACPI_FAN_HID "PNP0C0B"
#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver"
-#define ACPI_FAN_DEVICE_NAME "Fan"
#define ACPI_FAN_FILE_STATE "state"
-#define ACPI_FAN_NOTIFY_STATUS 0x80
#define _COMPONENT ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME ("acpi_fan")
+ACPI_MODULE_NAME("acpi_fan")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_fan_add (struct acpi_device *device);
-static int acpi_fan_remove (struct acpi_device *device, int type);
+static int acpi_fan_add(struct acpi_device *device);
+static int acpi_fan_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
- .name = ACPI_FAN_DRIVER_NAME,
- .class = ACPI_FAN_CLASS,
- .ids = ACPI_FAN_HID,
- .ops = {
- .add = acpi_fan_add,
- .remove = acpi_fan_remove,
- },
+ .name = ACPI_FAN_DRIVER_NAME,
+ .class = ACPI_FAN_CLASS,
+ .ids = "PNP0C0B",
+ .ops = {
+ .add = acpi_fan_add,
+ .remove = acpi_fan_remove,
+ },
};
struct acpi_fan {
- acpi_handle handle;
+ acpi_handle handle;
};
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_fan_dir;
+static struct proc_dir_entry *acpi_fan_dir;
-
-static int
-acpi_fan_read_state (struct seq_file *seq, void *offset)
+static int acpi_fan_read_state(struct seq_file *seq, void *offset)
{
- struct acpi_fan *fan = seq->private;
- int state = 0;
+ struct acpi_fan *fan = seq->private;
+ int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_read_state");
@@ -88,7 +81,7 @@ acpi_fan_read_state (struct seq_file *seq, void *offset)
seq_printf(seq, "status: ERROR\n");
else
seq_printf(seq, "status: %s\n",
- !state?"on":"off");
+ !state ? "on" : "off");
}
return_VALUE(0);
}
@@ -99,29 +92,26 @@ static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_fan_write_state (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_fan_write_state(struct file *file, const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_fan *fan = (struct acpi_fan *) m->private;
- char state_string[12] = {'\0'};
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_fan *fan = (struct acpi_fan *)m->private;
+ char state_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_fan_write_state");
if (!fan || (count > sizeof(state_string) - 1))
return_VALUE(-EINVAL);
-
+
if (copy_from_user(state_string, buffer, count))
return_VALUE(-EFAULT);
-
+
state_string[count] = '\0';
-
- result = acpi_bus_set_power(fan->handle,
- simple_strtoul(state_string, NULL, 0));
+
+ result = acpi_bus_set_power(fan->handle,
+ simple_strtoul(state_string, NULL, 0));
if (result)
return_VALUE(result);
@@ -129,19 +119,17 @@ acpi_fan_write_state (
}
static struct file_operations acpi_fan_state_ops = {
- .open = acpi_fan_state_open_fs,
- .read = seq_read,
- .write = acpi_fan_write_state,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_fan_state_open_fs,
+ .read = seq_read,
+ .write = acpi_fan_write_state,
+ .llseek = seq_lseek,
+ .release = single_release,
.owner = THIS_MODULE,
};
-static int
-acpi_fan_add_fs (
- struct acpi_device *device)
+static int acpi_fan_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_add_fs");
@@ -150,7 +138,7 @@ acpi_fan_add_fs (
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_fan_dir);
+ acpi_fan_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -158,11 +146,12 @@ acpi_fan_add_fs (
/* 'status' [R/W] */
entry = create_proc_entry(ACPI_FAN_FILE_STATE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_FAN_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_FAN_FILE_STATE));
else {
entry->proc_fops = &acpi_fan_state_ops;
entry->data = acpi_driver_data(device);
@@ -172,16 +161,12 @@ acpi_fan_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_fan_remove_fs (
- struct acpi_device *device)
+static int acpi_fan_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_FAN_FILE_STATE,
- acpi_device_dir(device));
+ remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
acpi_device_dir(device) = NULL;
}
@@ -189,18 +174,15 @@ acpi_fan_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_fan_add (
- struct acpi_device *device)
+static int acpi_fan_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_fan *fan = NULL;
- int state = 0;
+ int result = 0;
+ struct acpi_fan *fan = NULL;
+ int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_add");
@@ -213,14 +195,14 @@ acpi_fan_add (
memset(fan, 0, sizeof(struct acpi_fan));
fan->handle = device->handle;
- strcpy(acpi_device_name(device), ACPI_FAN_DEVICE_NAME);
+ strcpy(acpi_device_name(device), "Fan");
strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
acpi_driver_data(device) = fan;
result = acpi_bus_get_power(fan->handle, &state);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error reading power state\n"));
+ "Error reading power state\n"));
goto end;
}
@@ -229,30 +211,26 @@ acpi_fan_add (
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
- acpi_device_name(device), acpi_device_bid(device),
- !device->power.state?"on":"off");
+ acpi_device_name(device), acpi_device_bid(device),
+ !device->power.state ? "on" : "off");
-end:
+ end:
if (result)
kfree(fan);
return_VALUE(result);
}
-
-static int
-acpi_fan_remove (
- struct acpi_device *device,
- int type)
+static int acpi_fan_remove(struct acpi_device *device, int type)
{
- struct acpi_fan *fan = NULL;
+ struct acpi_fan *fan = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- fan = (struct acpi_fan *) acpi_driver_data(device);
+ fan = (struct acpi_fan *)acpi_driver_data(device);
acpi_fan_remove_fs(device);
@@ -261,11 +239,9 @@ acpi_fan_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_fan_init (void)
+static int __init acpi_fan_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_fan_init");
@@ -283,9 +259,7 @@ acpi_fan_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_fan_exit (void)
+static void __exit acpi_fan_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_fan_exit");
@@ -296,7 +270,5 @@ acpi_fan_exit (void)
return_VOID;
}
-
module_init(acpi_fan_init);
module_exit(acpi_fan_exit);
-
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 770cfc8b17e0..3937adf4e5e5 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -29,7 +29,8 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "bus type %s registered\n", type->bus->name);
+ printk(KERN_INFO PREFIX "bus type %s registered\n",
+ type->bus->name);
return 0;
}
return -ENODEV;
@@ -45,7 +46,8 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_del_init(&type->list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", type->bus->name);
+ printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
+ type->bus->name);
return 0;
}
return -ENODEV;
@@ -94,7 +96,7 @@ struct acpi_find_pci_root {
static acpi_status
do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
- int *busnr = (int *)data;
+ unsigned long *busnr = (unsigned long *)data;
struct acpi_resource_address64 address;
if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
@@ -113,13 +115,13 @@ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
static int get_root_bridge_busnr(acpi_handle handle)
{
acpi_status status;
- int bus, bbn;
+ unsigned long bus, bbn;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL,
- (unsigned long *)&bbn);
+ &bbn);
if (status == AE_NOT_FOUND) {
/* Assume bus = 0 */
printk(KERN_INFO PREFIX
@@ -151,7 +153,7 @@ static int get_root_bridge_busnr(acpi_handle handle)
}
exit:
acpi_os_free(buffer.pointer);
- return bbn;
+ return (int)bbn;
}
static acpi_status
@@ -168,9 +170,6 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &seg);
if (status == AE_NOT_FOUND) {
/* Assume seg = 0 */
- printk(KERN_INFO PREFIX
- "Assume root bridge [%s] segment is 0\n",
- (char *)buffer.pointer);
status = AE_OK;
seg = 0;
}
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index b51001e74eea..1bb3463d7040 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -42,13 +42,10 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwacpi")
-
+ACPI_MODULE_NAME("hwacpi")
/******************************************************************************
*
@@ -62,36 +59,30 @@
* the FADT.
*
******************************************************************************/
-
-acpi_status
-acpi_hw_initialize (
- void)
+acpi_status acpi_hw_initialize(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_initialize");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("hw_initialize");
/* We must have the ACPI tables by the time we get here */
if (!acpi_gbl_FADT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT is present\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No FADT is present\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Sanity check the FADT for valid values */
- status = acpi_ut_validate_fadt ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_fadt();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_set_mode
@@ -104,24 +95,21 @@ acpi_hw_initialize (
*
******************************************************************************/
-acpi_status
-acpi_hw_set_mode (
- u32 mode)
+acpi_status acpi_hw_set_mode(u32 mode)
{
- acpi_status status;
- u32 retry;
-
+ acpi_status status;
+ u32 retry;
- ACPI_FUNCTION_TRACE ("hw_set_mode");
+ ACPI_FUNCTION_TRACE("hw_set_mode");
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- ACPI_REPORT_ERROR (("No SMI_CMD in FADT, mode transition failed.\n"));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_REPORT_ERROR(("No SMI_CMD in FADT, mode transition failed.\n"));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
/*
@@ -132,9 +120,8 @@ acpi_hw_set_mode (
* transitions are not supported.
*/
if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) {
- ACPI_REPORT_ERROR ((
- "No ACPI mode transition supported in this system (enable/disable both zero)\n"));
- return_ACPI_STATUS (AE_OK);
+ ACPI_REPORT_ERROR(("No ACPI mode transition supported in this system (enable/disable both zero)\n"));
+ return_ACPI_STATUS(AE_OK);
}
switch (mode) {
@@ -142,9 +129,11 @@ acpi_hw_set_mode (
/* BIOS should have disabled ALL fixed and GP events */
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->acpi_enable, 8);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->acpi_enable,
+ 8);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Attempting to enable ACPI mode\n"));
break;
case ACPI_SYS_MODE_LEGACY:
@@ -153,20 +142,21 @@ acpi_hw_set_mode (
* BIOS should clear all fixed status bits and restore fixed event
* enable bits to default
*/
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->acpi_disable, 8);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Attempting to enable Legacy (non-ACPI) mode\n"));
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->acpi_disable,
+ 8);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Attempting to enable Legacy (non-ACPI) mode\n"));
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not write mode change, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not write mode change, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
@@ -176,19 +166,19 @@ acpi_hw_set_mode (
retry = 3000;
while (retry) {
if (acpi_hw_get_mode() == mode) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
- mode));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Mode %X successfully enabled\n",
+ mode));
+ return_ACPI_STATUS(AE_OK);
}
acpi_os_stall(1000);
retry--;
}
- ACPI_REPORT_ERROR (("Hardware never changed modes\n"));
- return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ ACPI_REPORT_ERROR(("Hardware never changed modes\n"));
+ return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_mode
@@ -202,34 +192,30 @@ acpi_hw_set_mode (
*
******************************************************************************/
-u32
-acpi_hw_get_mode (
- void)
+u32 acpi_hw_get_mode(void)
{
- acpi_status status;
- u32 value;
-
-
- ACPI_FUNCTION_TRACE ("hw_get_mode");
+ acpi_status status;
+ u32 value;
+ ACPI_FUNCTION_TRACE("hw_get_mode");
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition.
*/
if (!acpi_gbl_FADT->smi_cmd) {
- return_VALUE (ACPI_SYS_MODE_ACPI);
+ return_VALUE(ACPI_SYS_MODE_ACPI);
}
- status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
- if (ACPI_FAILURE (status)) {
- return_VALUE (ACPI_SYS_MODE_LEGACY);
+ status =
+ acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_VALUE(ACPI_SYS_MODE_LEGACY);
}
if (value) {
- return_VALUE (ACPI_SYS_MODE_ACPI);
- }
- else {
- return_VALUE (ACPI_SYS_MODE_LEGACY);
+ return_VALUE(ACPI_SYS_MODE_ACPI);
+ } else {
+ return_VALUE(ACPI_SYS_MODE_LEGACY);
}
}
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 8daeabb2fc7a..5c8e5dfd024e 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -46,15 +46,12 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwgpe")
+ACPI_MODULE_NAME("hwgpe")
/* Local prototypes */
-
static acpi_status
-acpi_hw_enable_wakeup_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
-
+acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
/******************************************************************************
*
@@ -71,15 +68,12 @@ acpi_hw_enable_wakeup_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_write_gpe_enable_reg (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info)
{
- struct acpi_gpe_register_info *gpe_register_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_gpe_register_info *gpe_register_info;
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
@@ -90,13 +84,12 @@ acpi_hw_write_gpe_enable_reg (
/* Write the entire GPE (runtime) enable register */
- status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
+ status = acpi_hw_low_level_write(8, gpe_register_info->enable_for_run,
+ &gpe_register_info->enable_address);
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe
@@ -109,27 +102,23 @@ acpi_hw_write_gpe_enable_reg (
*
******************************************************************************/
-acpi_status
-acpi_hw_clear_gpe (
- struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ ACPI_FUNCTION_ENTRY();
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
- status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
- &gpe_event_info->register_info->status_address);
+ status = acpi_hw_low_level_write(8, gpe_event_info->register_bit,
+ &gpe_event_info->register_info->
+ status_address);
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_get_gpe_status
@@ -145,19 +134,16 @@ acpi_hw_clear_gpe (
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_hw_get_gpe_status (
- struct acpi_gpe_event_info *gpe_event_info,
- acpi_event_status *event_status)
+acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
+ acpi_event_status * event_status)
{
- u32 in_byte;
- u8 register_bit;
- struct acpi_gpe_register_info *gpe_register_info;
- acpi_status status;
- acpi_event_status local_event_status = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u32 in_byte;
+ u8 register_bit;
+ struct acpi_gpe_register_info *gpe_register_info;
+ acpi_status status;
+ acpi_event_status local_event_status = 0;
+ ACPI_FUNCTION_ENTRY();
if (!event_status) {
return (AE_BAD_PARAMETER);
@@ -185,8 +171,10 @@ acpi_hw_get_gpe_status (
/* GPE currently active (status bit == 1)? */
- status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(8, &in_byte,
+ &gpe_register_info->status_address);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -198,12 +186,10 @@ acpi_hw_get_gpe_status (
(*event_status) = local_event_status;
-
-unlock_and_exit:
+ unlock_and_exit:
return (status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/******************************************************************************
*
@@ -219,22 +205,21 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_hw_disable_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Disable all GPEs in this register */
- status = acpi_hw_low_level_write (8, 0x00,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8, 0x00,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -242,7 +227,6 @@ acpi_hw_disable_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe_block
@@ -257,22 +241,21 @@ acpi_hw_disable_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_clear_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Clear status on all GPEs in this register */
- status = acpi_hw_low_level_write (8, 0xFF,
- &gpe_block->register_info[i].status_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8, 0xFF,
+ &gpe_block->register_info[i].
+ status_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -280,7 +263,6 @@ acpi_hw_clear_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_runtime_gpe_block
@@ -296,13 +278,11 @@ acpi_hw_clear_gpe_block (
******************************************************************************/
acpi_status
-acpi_hw_enable_runtime_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
+ struct acpi_gpe_block_info * gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* NOTE: assumes that all GPEs are currently disabled */
@@ -315,9 +295,13 @@ acpi_hw_enable_runtime_gpe_block (
/* Enable all "runtime" GPEs in this register */
- status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(8,
+ gpe_block->register_info[i].
+ enable_for_run,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -325,7 +309,6 @@ acpi_hw_enable_runtime_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_wakeup_gpe_block
@@ -341,13 +324,11 @@ acpi_hw_enable_runtime_gpe_block (
******************************************************************************/
static acpi_status
-acpi_hw_enable_wakeup_gpe_block (
- struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block)
{
- u32 i;
- acpi_status status;
-
+ u32 i;
+ acpi_status status;
/* Examine each GPE Register within the block */
@@ -358,10 +339,12 @@ acpi_hw_enable_wakeup_gpe_block (
/* Enable all "wake" GPEs in this register */
- status = acpi_hw_low_level_write (8,
- gpe_block->register_info[i].enable_for_wake,
- &gpe_block->register_info[i].enable_address);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_low_level_write(8,
+ gpe_block->register_info[i].
+ enable_for_wake,
+ &gpe_block->register_info[i].
+ enable_address);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
@@ -369,12 +352,11 @@ acpi_hw_enable_wakeup_gpe_block (
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_all_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -382,27 +364,22 @@ acpi_hw_enable_wakeup_gpe_block (
*
******************************************************************************/
-acpi_status
-acpi_hw_disable_all_gpes (
- u32 flags)
+acpi_status acpi_hw_disable_all_gpes(void)
{
- acpi_status status;
-
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
+ ACPI_FUNCTION_TRACE("hw_disable_all_gpes");
-
- status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
- status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
- return_ACPI_STATUS (status);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_runtime_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -410,26 +387,21 @@ acpi_hw_disable_all_gpes (
*
******************************************************************************/
-acpi_status
-acpi_hw_enable_all_runtime_gpes (
- u32 flags)
+acpi_status acpi_hw_enable_all_runtime_gpes(void)
{
- acpi_status status;
-
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
+ ACPI_FUNCTION_TRACE("hw_enable_all_runtime_gpes");
-
- status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
- return_ACPI_STATUS (status);
+ status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_wakeup_gpes
*
- * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR
+ * PARAMETERS: None
*
* RETURN: Status
*
@@ -437,17 +409,12 @@ acpi_hw_enable_all_runtime_gpes (
*
******************************************************************************/
-acpi_status
-acpi_hw_enable_all_wakeup_gpes (
- u32 flags)
+acpi_status acpi_hw_enable_all_wakeup_gpes(void)
{
- acpi_status status;
-
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
+ ACPI_FUNCTION_TRACE("hw_enable_all_wakeup_gpes");
-
- status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
- return_ACPI_STATUS (status);
+ status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 6d9e4eb84836..536a7aea80c9 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -50,8 +50,7 @@
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwregs")
-
+ACPI_MODULE_NAME("hwregs")
/*******************************************************************************
*
@@ -65,57 +64,52 @@
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
-
-acpi_status
-acpi_hw_clear_acpi_status (
- u32 flags)
+acpi_status acpi_hw_clear_acpi_status(u32 flags)
{
- acpi_status status;
-
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("hw_clear_acpi_status");
+ ACPI_FUNCTION_TRACE("hw_clear_acpi_status");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
- ACPI_BITMASK_ALL_FIXED_STATUS,
- (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
+ ACPI_BITMASK_ALL_FIXED_STATUS,
+ (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS,
- ACPI_BITMASK_ALL_FIXED_STATUS);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITMASK_ALL_FIXED_STATUS);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Clear the fixed events */
if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
- status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS,
- &acpi_gbl_FADT->xpm1b_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
}
/* Clear the GPE Bits in all GPE registers in all GPE blocks */
- status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_sleep_type_data
@@ -132,53 +126,48 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_get_sleep_type_data (
- u8 sleep_state,
- u8 *sleep_type_a,
- u8 *sleep_type_b)
+acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
{
- acpi_status status = AE_OK;
- struct acpi_parameter_info info;
- char *sleep_state_name;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
+ acpi_status status = AE_OK;
+ struct acpi_parameter_info info;
+ char *sleep_state_name;
+ ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data");
/* Validate parameters */
- if ((sleep_state > ACPI_S_STATES_MAX) ||
- !sleep_type_a || !sleep_type_b) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Evaluate the namespace object containing the values for this state */
info.parameters = NULL;
info.return_object = NULL;
- sleep_state_name = (char *) acpi_gbl_sleep_state_names[sleep_state];
+ sleep_state_name = (char *)acpi_gbl_sleep_state_names[sleep_state];
- status = acpi_ns_evaluate_by_name (sleep_state_name, &info);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s while evaluating sleep_state [%s]\n",
- acpi_format_exception (status), sleep_state_name));
+ status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%s while evaluating sleep_state [%s]\n",
+ acpi_format_exception(status),
+ sleep_state_name));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Must have a return object */
if (!info.return_object) {
- ACPI_REPORT_ERROR (("No Sleep State object returned from [%s]\n",
- sleep_state_name));
+ ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n",
+ sleep_state_name));
status = AE_NOT_EXIST;
}
/* It must be of type Package */
- else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
- ACPI_REPORT_ERROR (("Sleep State return object is not a Package\n"));
+ else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
+ ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n"));
status = AE_AML_OPERAND_TYPE;
}
@@ -190,45 +179,41 @@ acpi_get_sleep_type_data (
* one per sleep type (A/B).
*/
else if (info.return_object->package.count < 2) {
- ACPI_REPORT_ERROR ((
- "Sleep State return package does not have at least two elements\n"));
+ ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n"));
status = AE_AML_NO_OPERAND;
}
/* The first two elements must both be of type Integer */
- else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0])
- != ACPI_TYPE_INTEGER) ||
- (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1])
- != ACPI_TYPE_INTEGER)) {
- ACPI_REPORT_ERROR ((
- "Sleep State return package elements are not both Integers (%s, %s)\n",
- acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
- acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
+ else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0])
+ != ACPI_TYPE_INTEGER) ||
+ (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
+ != ACPI_TYPE_INTEGER)) {
+ ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1])));
status = AE_AML_OPERAND_TYPE;
- }
- else {
+ } else {
/* Valid _Sx_ package size, type, and value */
*sleep_type_a = (u8)
- (info.return_object->package.elements[0])->integer.value;
+ (info.return_object->package.elements[0])->integer.value;
*sleep_type_b = (u8)
- (info.return_object->package.elements[1])->integer.value;
+ (info.return_object->package.elements[1])->integer.value;
}
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
- acpi_format_exception (status),
- sleep_state_name, info.return_object,
- acpi_ut_get_object_type_name (info.return_object)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+ acpi_format_exception(status),
+ sleep_state_name, info.return_object,
+ acpi_ut_get_object_type_name(info.
+ return_object)));
}
- acpi_ut_remove_reference (info.return_object);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(info.return_object);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_sleep_type_data);
+EXPORT_SYMBOL(acpi_get_sleep_type_data);
/*******************************************************************************
*
@@ -242,22 +227,20 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data);
*
******************************************************************************/
-struct acpi_bit_register_info *
-acpi_hw_get_bit_register_info (
- u32 register_id)
+struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
{
- ACPI_FUNCTION_NAME ("hw_get_bit_register_info");
-
+ ACPI_FUNCTION_NAME("hw_get_bit_register_info");
if (register_id > ACPI_BITREG_MAX) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid bit_register ID: %X\n", register_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid bit_register ID: %X\n",
+ register_id));
return (NULL);
}
return (&acpi_gbl_bit_register_info[register_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_register
@@ -273,59 +256,56 @@ acpi_hw_get_bit_register_info (
*
******************************************************************************/
-acpi_status
-acpi_get_register (
- u32 register_id,
- u32 *return_value,
- u32 flags)
+acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
{
- u32 register_value = 0;
- struct acpi_bit_register_info *bit_reg_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_register");
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_register");
/* Get the info structure corresponding to the requested ACPI Register */
- bit_reg_info = acpi_hw_get_bit_register_info (register_id);
+ bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Read from the register */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- bit_reg_info->parent_register, &register_value);
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register,
+ &register_value);
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Normalize the value that was read */
- register_value = ((register_value & bit_reg_info->access_bit_mask)
- >> bit_reg_info->bit_position);
+ register_value =
+ ((register_value & bit_reg_info->access_bit_mask)
+ >> bit_reg_info->bit_position);
*return_value = register_value;
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
- register_value, bit_reg_info->parent_register));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n",
+ register_value,
+ bit_reg_info->parent_register));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_register);
+EXPORT_SYMBOL(acpi_get_register);
/*******************************************************************************
*
@@ -342,40 +322,36 @@ EXPORT_SYMBOL(acpi_get_register);
*
******************************************************************************/
-acpi_status
-acpi_set_register (
- u32 register_id,
- u32 value,
- u32 flags)
+acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
{
- u32 register_value = 0;
- struct acpi_bit_register_info *bit_reg_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_U32 ("acpi_set_register", register_id);
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id);
/* Get the info structure corresponding to the requested ACPI Register */
- bit_reg_info = acpi_hw_get_bit_register_info (register_id);
+ bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- ACPI_REPORT_ERROR (("Bad ACPI HW register_id: %X\n", register_id));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n",
+ register_id));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Always do a register read first so we can insert the new bits */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- bit_reg_info->parent_register, &register_value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register,
+ &register_value);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -395,26 +371,30 @@ acpi_set_register (
* information is the single bit we're interested in, all others should
* be written as 0 so they will be left unchanged.
*/
- value = ACPI_REGISTER_PREPARE_BITS (value,
- bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
+ value = ACPI_REGISTER_PREPARE_BITS(value,
+ bit_reg_info->bit_position,
+ bit_reg_info->
+ access_bit_mask);
if (value) {
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_STATUS, (u16) value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS,
+ (u16) value);
register_value = 0;
}
break;
-
case ACPI_REGISTER_PM1_ENABLE:
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_ENABLE, (u16) register_value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_ENABLE,
+ (u16) register_value);
break;
-
case ACPI_REGISTER_PM1_CONTROL:
/*
@@ -422,65 +402,73 @@ acpi_set_register (
* Note that at this level, the fact that there are actually TWO
* registers (A and B - and B may not exist) is abstracted.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n",
+ register_value));
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, (u16) register_value);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ (u16) register_value);
break;
-
case ACPI_REGISTER_PM2_CONTROL:
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL, &register_value);
- if (ACPI_FAILURE (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL,
+ &register_value);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
- register_value,
- ACPI_FORMAT_UINT64 (
- acpi_gbl_FADT->xpm2_cnt_blk.address)));
-
- ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
- bit_reg_info->access_bit_mask, value);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
- register_value,
- ACPI_FORMAT_UINT64 (
- acpi_gbl_FADT->xpm2_cnt_blk.address)));
-
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM2_CONTROL, (u8) (register_value));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "PM2 control: Read %X from %8.8X%8.8X\n",
+ register_value,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT->
+ xpm2_cnt_blk.address)));
+
+ ACPI_REGISTER_INSERT_VALUE(register_value,
+ bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask,
+ value);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "About to write %4.4X to %8.8X%8.8X\n",
+ register_value,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT->
+ xpm2_cnt_blk.address)));
+
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL,
+ (u8) (register_value));
break;
-
default:
break;
}
-
-unlock_and_exit:
+ unlock_and_exit:
if (flags & ACPI_MTX_LOCK) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
/* Normalize the value that was read */
- ACPI_DEBUG_EXEC (register_value =
- ((register_value & bit_reg_info->access_bit_mask) >>
- bit_reg_info->bit_position));
+ ACPI_DEBUG_EXEC(register_value =
+ ((register_value & bit_reg_info->access_bit_mask) >>
+ bit_reg_info->bit_position));
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
- value, register_value, bit_reg_info->parent_register));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Set bits: %8.8X actual %8.8X register %X\n", value,
+ register_value, bit_reg_info->parent_register));
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_register);
+EXPORT_SYMBOL(acpi_set_register);
/******************************************************************************
*
@@ -498,103 +486,107 @@ EXPORT_SYMBOL(acpi_set_register);
******************************************************************************/
acpi_status
-acpi_hw_register_read (
- u8 use_lock,
- u32 register_id,
- u32 *return_value)
+acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
{
- u32 value1 = 0;
- u32 value2 = 0;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_register_read");
+ u32 value1 = 0;
+ u32 value2 = 0;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("hw_register_read");
if (ACPI_MTX_LOCK == use_lock) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1,
+ &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk);
+ status =
+ acpi_hw_low_level_read(16, &value2,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
-
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable);
+ status =
+ acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_read(16, &value1,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_read(16, &value2,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
value1 |= value2;
break;
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk);
+ status =
+ acpi_hw_low_level_read(8, &value1,
+ &acpi_gbl_FADT->xpm2_cnt_blk);
break;
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk);
+ status =
+ acpi_hw_low_level_read(32, &value1,
+ &acpi_gbl_FADT->xpm_tmr_blk);
break;
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
- status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8);
+ status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8);
break;
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
- register_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
+ register_id));
status = AE_BAD_PARAMETER;
break;
}
-unlock_and_exit:
+ unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
*return_value = value1;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_register_write
@@ -610,109 +602,112 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_hw_register_write (
- u8 use_lock,
- u32 register_id,
- u32 value)
+acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("hw_register_write");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("hw_register_write");
if (ACPI_MTX_LOCK == use_lock) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* PM1B is optional */
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable);
+ status =
+ acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
break;
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
+ case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1a_cnt_blk);
break;
+ case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
- case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
-
- status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ status =
+ acpi_hw_low_level_write(16, value,
+ &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk);
+ status =
+ acpi_hw_low_level_write(8, value,
+ &acpi_gbl_FADT->xpm2_cnt_blk);
break;
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk);
+ status =
+ acpi_hw_low_level_write(32, value,
+ &acpi_gbl_FADT->xpm_tmr_blk);
break;
-
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
/* SMI_CMD is currently always in IO space */
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8);
break;
-
default:
status = AE_BAD_PARAMETER;
break;
}
-unlock_and_exit:
+ unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_low_level_read
@@ -728,17 +723,12 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_hw_low_level_read (
- u32 width,
- u32 *value,
- struct acpi_generic_address *reg)
+acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
{
- u64 address;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("hw_low_level_read");
+ u64 address;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("hw_low_level_read");
/*
* Must have a valid pointer to a GAS structure, and
@@ -751,7 +741,7 @@ acpi_hw_low_level_read (
/* Get a local copy of the address. Handles possible alignment issues */
- ACPI_MOVE_64_TO_64 (&address, &reg->address);
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_OK);
}
@@ -764,35 +754,32 @@ acpi_hw_low_level_read (
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_read_memory (
- (acpi_physical_address) address,
- value, width);
+ status = acpi_os_read_memory((acpi_physical_address) address,
+ value, width);
break;
-
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_read_port ((acpi_io_address) address,
- value, width);
+ status = acpi_os_read_port((acpi_io_address) address,
+ value, width);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported address space: %X\n", reg->address_space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO,
- "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
- *value, width,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (reg->address_space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
+ *value, width,
+ ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->address_space_id)));
return (status);
}
-
/******************************************************************************
*
* FUNCTION: acpi_hw_low_level_write
@@ -808,17 +795,12 @@ acpi_hw_low_level_read (
******************************************************************************/
acpi_status
-acpi_hw_low_level_write (
- u32 width,
- u32 value,
- struct acpi_generic_address *reg)
+acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
{
- u64 address;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("hw_low_level_write");
+ u64 address;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("hw_low_level_write");
/*
* Must have a valid pointer to a GAS structure, and
@@ -831,7 +813,7 @@ acpi_hw_low_level_write (
/* Get a local copy of the address. Handles possible alignment issues */
- ACPI_MOVE_64_TO_64 (&address, &reg->address);
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_OK);
}
@@ -843,30 +825,28 @@ acpi_hw_low_level_write (
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- status = acpi_os_write_memory (
- (acpi_physical_address) address,
- value, width);
+ status = acpi_os_write_memory((acpi_physical_address) address,
+ value, width);
break;
-
case ACPI_ADR_SPACE_SYSTEM_IO:
- status = acpi_os_write_port ((acpi_io_address) address,
- value, width);
+ status = acpi_os_write_port((acpi_io_address) address,
+ value, width);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported address space: %X\n", reg->address_space_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n",
+ reg->address_space_id));
return (AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_IO,
- "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
- value, width,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (reg->address_space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
+ value, width,
+ ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->address_space_id)));
return (status);
}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 415d342aeab5..34519069050c 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -46,8 +46,7 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwsleep")
-
+ACPI_MODULE_NAME("hwsleep")
/*******************************************************************************
*
@@ -61,30 +60,25 @@
* DESCRIPTION: Access function for the firmware_waking_vector field in FACS
*
******************************************************************************/
-
acpi_status
-acpi_set_firmware_waking_vector (
- acpi_physical_address physical_address)
+acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
{
- ACPI_FUNCTION_TRACE ("acpi_set_firmware_waking_vector");
-
+ ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector");
/* Set the vector */
if (acpi_gbl_common_fACS.vector_width == 32) {
- *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector))
- = (u32) physical_address;
- }
- else {
- *acpi_gbl_common_fACS.firmware_waking_vector
- = physical_address;
+ *(ACPI_CAST_PTR
+ (u32, acpi_gbl_common_fACS.firmware_waking_vector))
+ = (u32) physical_address;
+ } else {
+ *acpi_gbl_common_fACS.firmware_waking_vector = physical_address;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_waking_vector
@@ -101,33 +95,31 @@ acpi_set_firmware_waking_vector (
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_firmware_waking_vector (
- acpi_physical_address *physical_address)
+acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
{
- ACPI_FUNCTION_TRACE ("acpi_get_firmware_waking_vector");
-
+ ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector");
if (!physical_address) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the vector */
if (acpi_gbl_common_fACS.vector_width == 32) {
*physical_address = (acpi_physical_address)
- *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector));
- }
- else {
+ *
+ (ACPI_CAST_PTR
+ (u32, acpi_gbl_common_fACS.firmware_waking_vector));
+ } else {
*physical_address =
- *acpi_gbl_common_fACS.firmware_waking_vector;
+ *acpi_gbl_common_fACS.firmware_waking_vector;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_prep
@@ -143,25 +135,22 @@ acpi_get_firmware_waking_vector (
*
******************************************************************************/
-acpi_status
-acpi_enter_sleep_state_prep (
- u8 sleep_state)
+acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
{
- acpi_status status;
- struct acpi_object_list arg_list;
- union acpi_object arg;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_prep");
+ acpi_status status;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep");
/*
* _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
*/
- status = acpi_get_sleep_type_data (sleep_state,
- &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_sleep_type_data(sleep_state,
+ &acpi_gbl_sleep_type_a,
+ &acpi_gbl_sleep_type_b);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Setup parameter object */
@@ -174,14 +163,14 @@ acpi_enter_sleep_state_prep (
/* Run the _PTS and _GTS methods */
- status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
}
- status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS (status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
}
/* Setup the argument to _SST */
@@ -202,22 +191,21 @@ acpi_enter_sleep_state_prep (
break;
default:
- arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */
+ arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */
break;
}
/* Set the system indicators to show the desired sleep state. */
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state
@@ -231,80 +219,82 @@ acpi_enter_sleep_state_prep (
*
******************************************************************************/
-acpi_status asmlinkage
-acpi_enter_sleep_state (
- u8 sleep_state)
+acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
- u32 PM1Acontrol;
- u32 PM1Bcontrol;
- struct acpi_bit_register_info *sleep_type_reg_info;
- struct acpi_bit_register_info *sleep_enable_reg_info;
- u32 in_value;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state");
+ u32 PM1Acontrol;
+ u32 PM1Bcontrol;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
+ u32 in_value;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_enter_sleep_state");
if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
- (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
- ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
- acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
- return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
+ ACPI_REPORT_ERROR(("Sleep values out of range: A=%X B=%X\n",
+ acpi_gbl_sleep_type_a,
+ acpi_gbl_sleep_type_b));
+ return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
- sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
- sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
+ sleep_type_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
+ sleep_enable_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Clear wake status */
- status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Clear all fixed and general purpose status bits */
- status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
- status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_wakeup_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get current value of PM1A control */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Entering sleep state [S%d]\n", sleep_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "Entering sleep state [S%d]\n", sleep_state));
/* Clear SLP_EN and SLP_TYP fields */
PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
- sleep_enable_reg_info->access_bit_mask);
+ sleep_enable_reg_info->access_bit_mask);
PM1Bcontrol = PM1Acontrol;
/* Insert SLP_TYP bits */
- PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
- PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+ PM1Acontrol |=
+ (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
+ PM1Bcontrol |=
+ (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
/*
* We split the writes of SLP_TYP and SLP_EN to workaround
@@ -313,16 +303,18 @@ acpi_enter_sleep_state (
/* Write #1: fill in SLP_TYP data */
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Insert SLP_ENABLE bit */
@@ -332,18 +324,20 @@ acpi_enter_sleep_state (
/* Write #2: SLP_TYP + SLP_EN */
- ACPI_FLUSH_CPU_CACHE ();
+ ACPI_FLUSH_CPU_CACHE();
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
if (sleep_state > ACPI_STATE_S3) {
@@ -358,33 +352,34 @@ acpi_enter_sleep_state (
* still read the right value. Ideally, this block would go
* away entirely.
*/
- acpi_os_stall (10000000);
-
- status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL,
- sleep_enable_reg_info->access_bit_mask);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ acpi_os_stall(10000000);
+
+ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ sleep_enable_reg_info->
+ access_bit_mask);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Wait until we enter sleep state */
do {
- status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value,
- ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
+ ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Spin until we wake */
} while (!in_value);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state);
+EXPORT_SYMBOL(acpi_enter_sleep_state);
/*******************************************************************************
*
@@ -399,60 +394,57 @@ EXPORT_SYMBOL(acpi_enter_sleep_state);
*
******************************************************************************/
-acpi_status asmlinkage
-acpi_enter_sleep_state_s4bios (
- void)
+acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
{
- u32 in_value;
- acpi_status status;
-
+ u32 in_value;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios");
+ ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios");
-
- status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
- status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_wakeup_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_FLUSH_CPU_CACHE ();
+ ACPI_FLUSH_CPU_CACHE();
- status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd,
- (u32) acpi_gbl_FADT->S4bios_req, 8);
+ status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd,
+ (u32) acpi_gbl_FADT->S4bios_req, 8);
do {
acpi_os_stall(1000);
- status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value,
- ACPI_MTX_DO_NOT_LOCK);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
+ ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
} while (!in_value);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
+EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
/*******************************************************************************
*
@@ -467,55 +459,62 @@ EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
*
******************************************************************************/
-acpi_status
-acpi_leave_sleep_state (
- u8 sleep_state)
+acpi_status acpi_leave_sleep_state(u8 sleep_state)
{
- struct acpi_object_list arg_list;
- union acpi_object arg;
- acpi_status status;
- struct acpi_bit_register_info *sleep_type_reg_info;
- struct acpi_bit_register_info *sleep_enable_reg_info;
- u32 PM1Acontrol;
- u32 PM1Bcontrol;
-
-
- ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state");
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ acpi_status status;
+ struct acpi_bit_register_info *sleep_type_reg_info;
+ struct acpi_bit_register_info *sleep_enable_reg_info;
+ u32 PM1Acontrol;
+ u32 PM1Bcontrol;
+ ACPI_FUNCTION_TRACE("acpi_leave_sleep_state");
/*
* Set SLP_TYPE and SLP_EN to state S0.
* This is unclear from the ACPI Spec, but it is required
* by some machines.
*/
- status = acpi_get_sleep_type_data (ACPI_STATE_S0,
- &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
- if (ACPI_SUCCESS (status)) {
- sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
- sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
+ status = acpi_get_sleep_type_data(ACPI_STATE_S0,
+ &acpi_gbl_sleep_type_a,
+ &acpi_gbl_sleep_type_b);
+ if (ACPI_SUCCESS(status)) {
+ sleep_type_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
+ sleep_enable_reg_info =
+ acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
/* Get current value of PM1A control */
- status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL,
+ &PM1Acontrol);
+ if (ACPI_SUCCESS(status)) {
/* Clear SLP_EN and SLP_TYP fields */
PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
- sleep_enable_reg_info->access_bit_mask);
+ sleep_enable_reg_info->
+ access_bit_mask);
PM1Bcontrol = PM1Acontrol;
/* Insert SLP_TYP bits */
- PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
- PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
+ PM1Acontrol |=
+ (acpi_gbl_sleep_type_a << sleep_type_reg_info->
+ bit_position);
+ PM1Bcontrol |=
+ (acpi_gbl_sleep_type_b << sleep_type_reg_info->
+ bit_position);
/* Just ignore any errors */
- (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
- (void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
+ (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL,
+ PM1Acontrol);
+ (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL,
+ PM1Bcontrol);
}
}
@@ -532,23 +531,23 @@ acpi_leave_sleep_state (
/* Ignore any errors from these methods */
arg.integer.value = ACPI_SST_WAKING;
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
arg.integer.value = sleep_state;
- status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _BFS failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _BFS failed, %s\n",
+ acpi_format_exception(status)));
}
- status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _WAK failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _WAK failed, %s\n",
+ acpi_format_exception(status)));
}
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
@@ -557,33 +556,35 @@ acpi_leave_sleep_state (
* 1) Disable/Clear all GPEs
* 2) Enable all runtime GPEs
*/
- status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = TRUE;
- status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_enable_all_runtime_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Enable power button */
- (void) acpi_set_register(
- acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)
+ acpi_set_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1,
+ ACPI_MTX_DO_NOT_LOCK);
- (void) acpi_set_register(
- acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ (void)
+ acpi_set_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_POWER_BUTTON].status_register_id, 1,
+ ACPI_MTX_DO_NOT_LOCK);
arg.integer.value = ACPI_SST_WORKING;
- status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
- if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
- ACPI_REPORT_ERROR (("Method _SST failed, %s\n",
- acpi_format_exception (status)));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_REPORT_ERROR(("Method _SST failed, %s\n",
+ acpi_format_exception(status)));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index 49d7b395322e..aff6dc141784 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -46,8 +46,7 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
- ACPI_MODULE_NAME ("hwtimer")
-
+ACPI_MODULE_NAME("hwtimer")
/******************************************************************************
*
@@ -60,29 +59,23 @@
* DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
*
******************************************************************************/
-
-acpi_status
-acpi_get_timer_resolution (
- u32 *resolution)
+acpi_status acpi_get_timer_resolution(u32 * resolution)
{
- ACPI_FUNCTION_TRACE ("acpi_get_timer_resolution");
-
+ ACPI_FUNCTION_TRACE("acpi_get_timer_resolution");
if (!resolution) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (0 == acpi_gbl_FADT->tmr_val_ext) {
*resolution = 24;
- }
- else {
+ } else {
*resolution = 32;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_get_timer
@@ -95,26 +88,22 @@ acpi_get_timer_resolution (
*
******************************************************************************/
-acpi_status
-acpi_get_timer (
- u32 *ticks)
+acpi_status acpi_get_timer(u32 * ticks)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_timer");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_timer");
if (!ticks) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk);
+ status = acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT->xpm_tmr_blk);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_timer);
+EXPORT_SYMBOL(acpi_get_timer);
/******************************************************************************
*
@@ -146,21 +135,16 @@ EXPORT_SYMBOL(acpi_get_timer);
******************************************************************************/
acpi_status
-acpi_get_timer_duration (
- u32 start_ticks,
- u32 end_ticks,
- u32 *time_elapsed)
+acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
{
- acpi_status status;
- u32 delta_ticks;
- acpi_integer quotient;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_timer_duration");
+ acpi_status status;
+ u32 delta_ticks;
+ acpi_integer quotient;
+ ACPI_FUNCTION_TRACE("acpi_get_timer_duration");
if (!time_elapsed) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -169,22 +153,22 @@ acpi_get_timer_duration (
*/
if (start_ticks < end_ticks) {
delta_ticks = end_ticks - start_ticks;
- }
- else if (start_ticks > end_ticks) {
+ } else if (start_ticks > end_ticks) {
if (0 == acpi_gbl_FADT->tmr_val_ext) {
/* 24-bit Timer */
- delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF);
- }
- else {
+ delta_ticks =
+ (((0x00FFFFFF - start_ticks) +
+ end_ticks) & 0x00FFFFFF);
+ } else {
/* 32-bit Timer */
delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
}
- }
- else /* start_ticks == end_ticks */ {
+ } else { /* start_ticks == end_ticks */
+
*time_elapsed = 0;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -192,12 +176,11 @@ acpi_get_timer_duration (
*
* time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
*/
- status = acpi_ut_short_divide (((u64) delta_ticks) * 1000000,
- PM_TIMER_FREQUENCY, &quotient, NULL);
+ status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000,
+ PM_TIMER_FREQUENCY, &quotient, NULL);
*time_elapsed = (u32) quotient;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
EXPORT_SYMBOL(acpi_get_timer_duration);
-
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 1f76a40badec..2e2e4051dfa7 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -62,7 +62,7 @@
#define _COMPONENT ACPI_HOTKEY_COMPONENT
ACPI_MODULE_NAME("acpi_hotkey")
-MODULE_AUTHOR("luming.yu@intel.com");
+ MODULE_AUTHOR("luming.yu@intel.com");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
MODULE_LICENSE("GPL");
@@ -180,8 +180,8 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event);
+ acpi_hotkey_list
+ *hotkey_list, int event);
/* event based config */
static struct file_operations hotkey_config_fops = {
@@ -246,7 +246,7 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
static char *format_result(union acpi_object *object)
{
char *buf = NULL;
-
+
buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
if (buf)
memset(buf, 0, RESULT_STR_LEN);
@@ -256,7 +256,7 @@ static char *format_result(union acpi_object *object)
/* Now, just support integer type */
if (object->type == ACPI_TYPE_INTEGER)
sprintf(buf, "%d\n", (u32) object->integer.value);
-do_fail:
+ do_fail:
return (buf);
}
@@ -268,9 +268,9 @@ static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
ACPI_FUNCTION_TRACE("hotkey_polling_seq_show");
- if (poll_hotkey->poll_result){
+ if (poll_hotkey->poll_result) {
buf = format_result(poll_hotkey->poll_result);
- if(buf)
+ if (buf)
seq_printf(seq, "%s", buf);
kfree(buf);
}
@@ -299,7 +299,7 @@ static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
- && key->event_hotkey.external_hotkey_num == event){
+ && key->event_hotkey.external_hotkey_num == event) {
val = key->link.hotkey_standard_num;
break;
}
@@ -343,7 +343,7 @@ static int auto_hotkey_remove(struct acpi_device *device, int type)
static int create_polling_proc(union acpi_hotkey *device)
{
struct proc_dir_entry *proc;
- char proc_name[80];
+ char proc_name[80];
mode_t mode;
ACPI_FUNCTION_TRACE("create_polling_proc");
@@ -351,8 +351,8 @@ static int create_polling_proc(union acpi_hotkey *device)
sprintf(proc_name, "%d", device->link.hotkey_standard_num);
/*
- strcat(proc_name, device->poll_hotkey.poll_method);
- */
+ strcat(proc_name, device->poll_hotkey.poll_method);
+ */
proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
if (!proc) {
@@ -415,50 +415,50 @@ static int hotkey_remove(union acpi_hotkey *device)
return_VALUE(0);
}
-static int hotkey_update(union acpi_hotkey *key)
+static int hotkey_update(union acpi_hotkey *key)
{
struct list_head *entries;
ACPI_FUNCTION_TRACE("hotkey_update");
list_for_each(entries, global_hotkey_list.entries) {
- union acpi_hotkey *tmp=
+ union acpi_hotkey *tmp =
container_of(entries, union acpi_hotkey, entries);
if (tmp->link.hotkey_standard_num ==
key->link.hotkey_standard_num) {
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
free_hotkey_buffer(tmp);
tmp->event_hotkey.bus_handle =
- key->event_hotkey.bus_handle;
+ key->event_hotkey.bus_handle;
tmp->event_hotkey.external_hotkey_num =
- key->event_hotkey.external_hotkey_num;
+ key->event_hotkey.external_hotkey_num;
tmp->event_hotkey.action_handle =
- key->event_hotkey.action_handle;
+ key->event_hotkey.action_handle;
tmp->event_hotkey.action_method =
- key->event_hotkey.action_method;
+ key->event_hotkey.action_method;
kfree(key);
} else {
/*
- char proc_name[80];
+ char proc_name[80];
- sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
- strcat(proc_name, tmp->poll_hotkey.poll_method);
- remove_proc_entry(proc_name,hotkey_proc_dir);
- */
+ sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
+ strcat(proc_name, tmp->poll_hotkey.poll_method);
+ remove_proc_entry(proc_name,hotkey_proc_dir);
+ */
free_poll_hotkey_buffer(tmp);
tmp->poll_hotkey.poll_handle =
- key->poll_hotkey.poll_handle;
+ key->poll_hotkey.poll_handle;
tmp->poll_hotkey.poll_method =
- key->poll_hotkey.poll_method;
+ key->poll_hotkey.poll_method;
tmp->poll_hotkey.action_handle =
- key->poll_hotkey.action_handle;
+ key->poll_hotkey.action_handle;
tmp->poll_hotkey.action_method =
- key->poll_hotkey.action_method;
+ key->poll_hotkey.action_method;
tmp->poll_hotkey.poll_result =
- key->poll_hotkey.poll_result;
+ key->poll_hotkey.poll_result;
/*
- create_polling_proc(tmp);
- */
+ create_polling_proc(tmp);
+ */
kfree(key);
}
return_VALUE(0);
@@ -483,27 +483,25 @@ static void free_hotkey_device(union acpi_hotkey *key)
acpi_hotkey_notify_handler);
free_hotkey_buffer(key);
} else {
- char proc_name[80];
+ char proc_name[80];
sprintf(proc_name, "%d", key->link.hotkey_standard_num);
/*
- strcat(proc_name, key->poll_hotkey.poll_method);
- */
- remove_proc_entry(proc_name,hotkey_proc_dir);
+ strcat(proc_name, key->poll_hotkey.poll_method);
+ */
+ remove_proc_entry(proc_name, hotkey_proc_dir);
free_poll_hotkey_buffer(key);
}
kfree(key);
return_VOID;
}
-static void
-free_hotkey_buffer(union acpi_hotkey *key)
+static void free_hotkey_buffer(union acpi_hotkey *key)
{
kfree(key->event_hotkey.action_method);
}
-static void
-free_poll_hotkey_buffer(union acpi_hotkey *key)
+static void free_poll_hotkey_buffer(union acpi_hotkey *key)
{
kfree(key->poll_hotkey.action_method);
kfree(key->poll_hotkey.poll_method);
@@ -513,15 +511,15 @@ static int
init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
char *method, int std_num, int external_num)
{
- acpi_handle tmp_handle;
+ acpi_handle tmp_handle;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("init_hotkey_device");
- if(std_num < 0 || IS_POLL(std_num) || !key )
+ if (std_num < 0 || IS_POLL(std_num) || !key)
goto do_fail;
- if(!bus_str || !action_str || !method)
+ if (!bus_str || !action_str || !method)
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_EVENT;
@@ -529,19 +527,22 @@ init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
key->event_hotkey.flag = 0;
key->event_hotkey.action_method = method;
- status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
key->event_hotkey.external_hotkey_num = external_num;
- status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, action_str,
+ &(key->event_hotkey.action_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->event_hotkey.action_handle,
- method, &tmp_handle);
+ method, &tmp_handle);
if (ACPI_FAILURE(status))
goto do_fail;
return_VALUE(AE_OK);
-do_fail:
+ do_fail:
return_VALUE(-ENODEV);
}
@@ -552,14 +553,14 @@ init_poll_hotkey_device(union acpi_hotkey *key,
char *action_str, char *action_method, int std_num)
{
acpi_status status = AE_OK;
- acpi_handle tmp_handle;
+ acpi_handle tmp_handle;
ACPI_FUNCTION_TRACE("init_poll_hotkey_device");
- if(std_num < 0 || IS_EVENT(std_num) || !key)
+ if (std_num < 0 || IS_EVENT(std_num) || !key)
goto do_fail;
- if(!poll_str || !poll_method || !action_str || !action_method)
+ if (!poll_str || !poll_method || !action_str || !action_method)
goto do_fail;
key->link.hotkey_type = ACPI_HOTKEY_POLLING;
@@ -568,30 +569,32 @@ init_poll_hotkey_device(union acpi_hotkey *key,
key->poll_hotkey.poll_method = poll_method;
key->poll_hotkey.action_method = action_method;
- status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle));
- if(ACPI_FAILURE(status))
+ status =
+ acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle));
+ if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->poll_hotkey.poll_handle,
- poll_method, &tmp_handle);
- if (ACPI_FAILURE(status))
- goto do_fail;
- status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle));
+ poll_method, &tmp_handle);
+ if (ACPI_FAILURE(status))
+ goto do_fail;
+ status =
+ acpi_get_handle(NULL, action_str,
+ &(key->poll_hotkey.action_handle));
if (ACPI_FAILURE(status))
goto do_fail;
status = acpi_get_handle(key->poll_hotkey.action_handle,
- action_method, &tmp_handle);
+ action_method, &tmp_handle);
if (ACPI_FAILURE(status))
goto do_fail;
key->poll_hotkey.poll_result =
(union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if(!key->poll_hotkey.poll_result)
+ if (!key->poll_hotkey.poll_result)
goto do_fail;
return_VALUE(AE_OK);
-do_fail:
+ do_fail:
return_VALUE(-ENODEV);
}
-
static int hotkey_open_config(struct inode *inode, struct file *file)
{
ACPI_FUNCTION_TRACE("hotkey_open_config");
@@ -679,8 +682,9 @@ get_parms(char *config_record,
sscanf(config_record, "%d", cmd);
- if(*cmd == 1){
- if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2)
+ if (*cmd == 1) {
+ if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
+ 2)
goto do_fail;
else
return (6);
@@ -694,8 +698,8 @@ get_parms(char *config_record,
goto do_fail;
count = tmp1 - tmp;
- *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*bus_handle)
+ *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*bus_handle)
goto do_fail;
strncpy(*bus_handle, tmp, count);
*(*bus_handle + count) = 0;
@@ -706,8 +710,8 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *bus_method = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*bus_method)
+ *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*bus_method)
goto do_fail;
strncpy(*bus_method, tmp, count);
*(*bus_method + count) = 0;
@@ -718,7 +722,7 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *action_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+ *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
strncpy(*action_handle, tmp, count);
*(*action_handle + count) = 0;
@@ -728,17 +732,18 @@ get_parms(char *config_record,
if (!tmp1)
goto do_fail;
count = tmp1 - tmp;
- *method = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!*method)
+ *method = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!*method)
goto do_fail;
strncpy(*method, tmp, count);
*(*method + count) = 0;
- if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0)
+ if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <=
+ 0)
goto do_fail;
return_VALUE(6);
-do_fail:
+ do_fail:
return_VALUE(-1);
}
@@ -758,8 +763,8 @@ static ssize_t hotkey_write_config(struct file *file,
ACPI_FUNCTION_TRACE(("hotkey_write_config"));
- config_record = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!config_record)
+ config_record = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!config_record)
return_VALUE(-ENOMEM);
if (copy_from_user(config_record, buffer, count)) {
@@ -777,10 +782,10 @@ static ssize_t hotkey_write_config(struct file *file,
&method, &internal_event_num, &external_event_num);
kfree(config_record);
- if(IS_OTHERS(internal_event_num))
+ if (IS_OTHERS(internal_event_num))
goto do_fail;
if (ret != 6) {
-do_fail:
+ do_fail:
kfree(bus_handle);
kfree(bus_method);
kfree(action_handle);
@@ -791,14 +796,14 @@ do_fail:
}
key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
- if(!key)
+ if (!key)
goto do_fail;
memset(key, 0, sizeof(union acpi_hotkey));
- if(cmd == 1) {
+ if (cmd == 1) {
union acpi_hotkey *tmp = NULL;
tmp = get_hotkey_by_event(&global_hotkey_list,
- internal_event_num);
- if(!tmp)
+ internal_event_num);
+ if (!tmp)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key"));
else
memcpy(key, tmp, sizeof(union acpi_hotkey));
@@ -807,15 +812,16 @@ do_fail:
if (IS_EVENT(internal_event_num)) {
kfree(bus_method);
ret = init_hotkey_device(key, bus_handle, action_handle, method,
- internal_event_num, external_event_num);
+ internal_event_num,
+ external_event_num);
} else
ret = init_poll_hotkey_device(key, bus_handle, bus_method,
- action_handle, method,
- internal_event_num);
+ action_handle, method,
+ internal_event_num);
if (ret) {
kfree(bus_handle);
kfree(action_handle);
- if(IS_EVENT(internal_event_num))
+ if (IS_EVENT(internal_event_num))
free_hotkey_buffer(key);
else
free_poll_hotkey_buffer(key);
@@ -824,13 +830,14 @@ do_fail:
return_VALUE(-EINVAL);
}
-cont_cmd:
+ cont_cmd:
kfree(bus_handle);
kfree(action_handle);
switch (cmd) {
case 0:
- if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num))
+ if (get_hotkey_by_event
+ (&global_hotkey_list, key->link.hotkey_standard_num))
goto fail_out;
else
hotkey_add(key);
@@ -839,7 +846,7 @@ cont_cmd:
hotkey_remove(key);
break;
case 2:
- if(hotkey_update(key))
+ if (hotkey_update(key))
goto fail_out;
break;
default:
@@ -847,8 +854,8 @@ cont_cmd:
break;
}
return_VALUE(count);
-fail_out:
- if(IS_EVENT(internal_event_num))
+ fail_out:
+ if (IS_EVENT(internal_event_num))
free_hotkey_buffer(key);
else
free_poll_hotkey_buffer(key);
@@ -882,7 +889,8 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
return_VALUE(status == AE_OK);
}
-static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val)
+static int read_acpi_int(acpi_handle handle, const char *method,
+ union acpi_object *val)
{
struct acpi_buffer output;
union acpi_object out_obj;
@@ -893,7 +901,7 @@ static int read_acpi_int(acpi_handle handle, const char *method, union acpi_obje
output.pointer = &out_obj;
status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
- if(val){
+ if (val) {
val->integer.value = out_obj.integer.value;
val->type = out_obj.type;
} else
@@ -903,8 +911,8 @@ static int read_acpi_int(acpi_handle handle, const char *method, union acpi_obje
}
static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event)
+ acpi_hotkey_list
+ *hotkey_list, int event)
{
struct list_head *entries;
@@ -912,10 +920,10 @@ static union acpi_hotkey *get_hotkey_by_event(struct
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_standard_num == event) {
- return(key);
+ return (key);
}
}
- return(NULL);
+ return (NULL);
}
/*
@@ -932,15 +940,15 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
{
struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
char *arg;
- int event,method_type,type, value;
+ int event, method_type, type, value;
union acpi_hotkey *key;
ACPI_FUNCTION_TRACE("hotkey_execte_aml_method");
- arg = (char *) kmalloc(count+1, GFP_KERNEL);
- if(!arg)
+ arg = (char *)kmalloc(count + 1, GFP_KERNEL);
+ if (!arg)
return_VALUE(-ENOMEM);
- arg[count]=0;
+ arg[count] = 0;
if (copy_from_user(arg, buffer, count)) {
kfree(arg);
@@ -948,7 +956,8 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
return_VALUE(-EINVAL);
}
- if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) {
+ if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) !=
+ 4) {
kfree(arg);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3"));
return_VALUE(-EINVAL);
@@ -956,19 +965,21 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
kfree(arg);
if (type == ACPI_TYPE_INTEGER) {
key = get_hotkey_by_event(hotkey_list, event);
- if(!key)
+ if (!key)
goto do_fail;
if (IS_EVENT(event))
write_acpi_int(key->event_hotkey.action_handle,
- key->event_hotkey.action_method, value, NULL);
+ key->event_hotkey.action_method, value,
+ NULL);
else if (IS_POLL(event)) {
- if ( method_type == POLL_METHOD )
+ if (method_type == POLL_METHOD)
read_acpi_int(key->poll_hotkey.poll_handle,
- key->poll_hotkey.poll_method,
- key->poll_hotkey.poll_result);
- else if ( method_type == ACTION_METHOD )
+ key->poll_hotkey.poll_method,
+ key->poll_hotkey.poll_result);
+ else if (method_type == ACTION_METHOD)
write_acpi_int(key->poll_hotkey.action_handle,
- key->poll_hotkey.action_method, value, NULL);
+ key->poll_hotkey.action_method,
+ value, NULL);
else
goto do_fail;
@@ -978,7 +989,7 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
return_VALUE(-EINVAL);
}
return_VALUE(count);
-do_fail:
+ do_fail:
return_VALUE(-EINVAL);
}
@@ -1074,15 +1085,15 @@ static int __init hotkey_init(void)
return (0);
-do_fail5:
+ do_fail5:
remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
-do_fail4:
+ do_fail4:
remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
-do_fail3:
+ do_fail3:
remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
-do_fail2:
+ do_fail2:
remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
-do_fail1:
+ do_fail1:
remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
return (-ENODEV);
}
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index ad85e10001f4..5cc090326ddc 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -2,7 +2,7 @@
* ibm_acpi.c - IBM ThinkPad ACPI Extras
*
*
- * Copyright (C) 2004 Borislav Deianov
+ * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.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
@@ -17,38 +17,62 @@
* 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 IBM_VERSION "0.12a"
+
+/*
* Changelog:
- *
- * 2004-08-09 0.1 initial release, support for X series
- * 2004-08-14 0.2 support for T series, X20
- * bluetooth enable/disable
- * hotkey events disabled by default
- * removed fan control, currently useless
- * 2004-08-17 0.3 support for R40
- * lcd off, brightness control
- * thinklight on/off
- * 2004-09-16 0.4 support for module parameters
- * hotkey mask can be prefixed by 0x
- * video output switching
- * video expansion control
- * ultrabay eject support
- * removed lcd brightness/on/off control, didn't work
+ *
+ * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
+ * 2005-03-17 0.11 support for 600e, 770x
+ * thanks to Jamie Lentin <lentinj@dial.pipex.com>
+ * support for 770e, G41
+ * G40 and G41 don't have a thinklight
+ * temperatures no longer experimental
+ * experimental brightness control
+ * experimental volume control
+ * experimental fan enable/disable
+ * 2005-01-16 0.10 fix module loading on R30, R31
+ * 2005-01-16 0.9 support for 570, R30, R31
+ * ultrabay support on A22p, A3x
+ * limit arg for cmos, led, beep, drop experimental status
+ * more capable led control on A21e, A22p, T20-22, X20
+ * experimental temperatures and fan speed
+ * experimental embedded controller register dump
+ * mark more functions as __init, drop incorrect __exit
+ * use MODULE_VERSION
+ * thanks to Henrik Brix Andersen <brix@gentoo.org>
+ * fix parameter passing on module loading
+ * thanks to Rusty Russell <rusty@rustcorp.com.au>
+ * thanks to Jim Radford <radford@blackbean.org>
+ * 2004-11-08 0.8 fix init error case, don't return from a macro
+ * thanks to Chris Wright <chrisw@osdl.org>
+ * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
+ * fix led control on A21e
+ * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
* 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20
* proc file format changed
* video_switch command
* experimental cmos control
* experimental led control
* experimental acpi sounds
- * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device
- * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20
- * fix LED control on A21e
- * 2004-11-08 0.8 fix init error case, don't return from a macro
- * thanks to Chris Wright <chrisw@osdl.org>
+ * 2004-09-16 0.4 support for module parameters
+ * hotkey mask can be prefixed by 0x
+ * video output switching
+ * video expansion control
+ * ultrabay eject support
+ * removed lcd brightness/on/off control, didn't work
+ * 2004-08-17 0.3 support for R40
+ * lcd off, brightness control
+ * thinklight on/off
+ * 2004-08-14 0.2 support for T series, X20
+ * bluetooth enable/disable
+ * hotkey events disabled by default
+ * removed fan control, currently useless
+ * 2004-08-09 0.1 initial release, support for X series
*/
-#define IBM_VERSION "0.8"
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -64,6 +88,11 @@
#define IBM_FILE "ibm_acpi"
#define IBM_URL "http://ibm-acpi.sf.net/"
+MODULE_AUTHOR("Borislav Deianov");
+MODULE_DESCRIPTION(IBM_DESC);
+MODULE_VERSION(IBM_VERSION);
+MODULE_LICENSE("GPL");
+
#define IBM_DIR IBM_NAME
#define IBM_LOG IBM_FILE ": "
@@ -84,54 +113,122 @@ static acpi_handle root_handle = NULL;
#define IBM_HANDLE(object, parent, paths...) \
static acpi_handle object##_handle; \
static acpi_handle *object##_parent = &parent##_handle; \
+ static char *object##_path; \
static char *object##_paths[] = { paths }
-IBM_HANDLE(ec, root,
- "\\_SB.PCI0.ISA.EC", /* A21e, A22p, T20, T21, X20 */
- "\\_SB.PCI0.LPC.EC", /* all others */
-);
-
-IBM_HANDLE(vid, root,
- "\\_SB.PCI0.VID", /* A21e, G40, X30, X40 */
- "\\_SB.PCI0.AGP.VID", /* all others */
-);
-
-IBM_HANDLE(cmos, root,
- "\\UCMS", /* R50, R50p, R51, T4x, X31, X40 */
- "\\CMOS", /* A3x, G40, R32, T23, T30, X22, X24, X30 */
- "\\CMS", /* R40, R40e */
-); /* A21e, A22p, T20, T21, X20 */
-
-IBM_HANDLE(dock, root,
- "\\_SB.GDCK", /* X30, X31, X40 */
- "\\_SB.PCI0.DOCK", /* A22p, T20, T21, X20 */
- "\\_SB.PCI0.PCI1.DOCK", /* all others */
-); /* A21e, G40, R32, R40, R40e */
-
-IBM_HANDLE(bay, root,
- "\\_SB.PCI0.IDE0.SCND.MSTR"); /* all except A21e */
-IBM_HANDLE(bayej, root,
- "\\_SB.PCI0.IDE0.SCND.MSTR._EJ0"); /* all except A2x, A3x */
-
-IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(hkey, ec, "HKEY"); /* all */
-IBM_HANDLE(led, ec, "LED"); /* all except A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(sysl, ec, "SYSL"); /* A21e, A22p, T20, T21, X20 */
-IBM_HANDLE(bled, ec, "BLED"); /* A22p, T20, T21, X20 */
-IBM_HANDLE(beep, ec, "BEEP"); /* all models */
+/*
+ * The following models are supported to various degrees:
+ *
+ * 570, 600e, 600x, 770e, 770x
+ * A20m, A21e, A21m, A21p, A22p, A30, A30p, A31, A31p
+ * G40, G41
+ * R30, R31, R32, R40, R40e, R50, R50e, R50p, R51
+ * T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p, T43
+ * X20, X21, X22, X23, X24, X30, X31, X40
+ *
+ * The following models have no supported features:
+ *
+ * 240, 240x, i1400
+ *
+ * Still missing DSDTs for the following models:
+ *
+ * A20p, A22e, A22m
+ * R52
+ * S31
+ * T43p
+ */
+
+IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
+ "\\_SB.PCI.ISA.EC", /* 570 */
+ "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
+ "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */
+ "\\_SB.PCI0.AD4S.EC0", /* i1400, R30 */
+ "\\_SB.PCI0.ICH3.EC0", /* R31 */
+ "\\_SB.PCI0.LPC.EC", /* all others */
+ );
+
+IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */
+ "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */
+ "\\_SB.PCI0.VID0", /* 770e */
+ "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */
+ "\\_SB.PCI0.AGP.VID", /* all others */
+ ); /* R30, R31 */
+
+IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */
+
+IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */
+ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */
+ "\\CMS", /* R40, R40e */
+ ); /* all others */
+
+IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
+ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
+ "\\_SB.PCI0.PCI1.DOCK", /* all others */
+ "\\_SB.PCI.ISA.SLCE", /* 570 */
+ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
+
+IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
+ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
+ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
+ ); /* A21e, R30, R31 */
+
+IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */
+ "_EJ0", /* all others */
+ ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
+
+IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
+ "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
+ ); /* all others */
+
+IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */
+ "_EJ0", /* 770x */
+ ); /* all others */
+
+/* don't list other alternatives as we install a notify handler on the 570 */
+IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
+
+IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */
+ "^HKEY", /* R30, R31 */
+ "HKEY", /* all others */
+ ); /* 570 */
+
+IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */
+IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */
+
+IBM_HANDLE(led, ec, "SLED", /* 570 */
+ "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+ "LED", /* all others */
+ ); /* R30, R31 */
+
+IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
+IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
+IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
+IBM_HANDLE(fans, ec, "FANS"); /* X31, X40 */
+
+IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
+ "\\FSPD", /* 600e/x, 770e, 770x */
+ ); /* all others */
+
+IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
+ "JFNS", /* 770x-JL */
+ ); /* all others */
+
+#define IBM_HKEY_HID "IBM0068"
+#define IBM_PCI_HID "PNP0A03"
struct ibm_struct {
char *name;
+ char param[32];
char *hid;
struct acpi_driver *driver;
-
- int (*init) (struct ibm_struct *);
- int (*read) (struct ibm_struct *, char *);
- int (*write) (struct ibm_struct *, char *);
- void (*exit) (struct ibm_struct *);
- void (*notify) (struct ibm_struct *, u32);
+ int (*init) (void);
+ int (*read) (char *);
+ int (*write) (char *);
+ void (*exit) (void);
+
+ void (*notify) (struct ibm_struct *, u32);
acpi_handle *handle;
int type;
struct acpi_device *device;
@@ -141,17 +238,6 @@ struct ibm_struct {
int init_called;
int notify_installed;
- int supported;
- union {
- struct {
- int status;
- int mask;
- } hotkey;
- struct {
- int autoswitch;
- } video;
- } state;
-
int experimental;
};
@@ -165,15 +251,15 @@ static int acpi_evalf(acpi_handle handle,
void *res, char *method, char *fmt, ...)
{
char *fmt0 = fmt;
- struct acpi_object_list params;
- union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
- struct acpi_buffer result;
- union acpi_object out_obj;
- acpi_status status;
- va_list ap;
- char res_type;
- int success;
- int quiet;
+ struct acpi_object_list params;
+ union acpi_object in_objs[IBM_MAX_ACPI_ARGS];
+ struct acpi_buffer result, *resultp;
+ union acpi_object out_obj;
+ acpi_status status;
+ va_list ap;
+ char res_type;
+ int success;
+ int quiet;
if (!*fmt) {
printk(IBM_ERR "acpi_evalf() called with empty format\n");
@@ -199,7 +285,7 @@ static int acpi_evalf(acpi_handle handle,
in_objs[params.count].integer.value = va_arg(ap, int);
in_objs[params.count++].type = ACPI_TYPE_INTEGER;
break;
- /* add more types as needed */
+ /* add more types as needed */
default:
printk(IBM_ERR "acpi_evalf() called "
"with invalid format character '%c'\n", c);
@@ -208,21 +294,25 @@ static int acpi_evalf(acpi_handle handle,
}
va_end(ap);
- result.length = sizeof(out_obj);
- result.pointer = &out_obj;
+ if (res_type != 'v') {
+ result.length = sizeof(out_obj);
+ result.pointer = &out_obj;
+ resultp = &result;
+ } else
+ resultp = NULL;
- status = acpi_evaluate_object(handle, method, &params, &result);
+ status = acpi_evaluate_object(handle, method, &params, resultp);
switch (res_type) {
- case 'd': /* int */
+ case 'd': /* int */
if (res)
*(int *)res = out_obj.integer.value;
success = status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER;
break;
- case 'v': /* void */
+ case 'v': /* void */
success = status == AE_OK;
break;
- /* add more types as needed */
+ /* add more types as needed */
default:
printk(IBM_ERR "acpi_evalf() called "
"with invalid format character '%c'\n", res_type);
@@ -262,7 +352,7 @@ static char *next_cmd(char **cmds)
return start;
}
-static int driver_init(struct ibm_struct *ibm)
+static int driver_init(void)
{
printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
printk(IBM_INFO "%s\n", IBM_URL);
@@ -270,7 +360,7 @@ static int driver_init(struct ibm_struct *ibm)
return 0;
}
-static int driver_read(struct ibm_struct *ibm, char *p)
+static int driver_read(char *p)
{
int len = 0;
@@ -280,67 +370,74 @@ static int driver_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int hotkey_get(struct ibm_struct *ibm, int *status, int *mask)
+static int hotkey_supported;
+static int hotkey_mask_supported;
+static int hotkey_orig_status;
+static int hotkey_orig_mask;
+
+static int hotkey_get(int *status, int *mask)
{
if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
- return -EIO;
- if (ibm->supported) {
- if (!acpi_evalf(hkey_handle, mask, "DHKN", "qd"))
- return -EIO;
- } else {
- *mask = ibm->state.hotkey.mask;
- }
- return 0;
+ return 0;
+
+ if (hotkey_mask_supported)
+ if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
+ return 0;
+
+ return 1;
}
-static int hotkey_set(struct ibm_struct *ibm, int status, int mask)
+static int hotkey_set(int status, int mask)
{
int i;
if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
- return -EIO;
-
- if (!ibm->supported)
return 0;
- for (i=0; i<32; i++) {
- int bit = ((1 << i) & mask) != 0;
- if (!acpi_evalf(hkey_handle, NULL, "MHKM", "vdd", i+1, bit))
- return -EIO;
- }
+ if (hotkey_mask_supported)
+ for (i = 0; i < 32; i++) {
+ int bit = ((1 << i) & mask) != 0;
+ if (!acpi_evalf(hkey_handle,
+ NULL, "MHKM", "vdd", i + 1, bit))
+ return 0;
+ }
- return 0;
+ return 1;
}
-static int hotkey_init(struct ibm_struct *ibm)
+static int hotkey_init(void)
{
- int ret;
+ /* hotkey not supported on 570 */
+ hotkey_supported = hkey_handle != NULL;
- ibm->supported = 1;
- ret = hotkey_get(ibm,
- &ibm->state.hotkey.status,
- &ibm->state.hotkey.mask);
- if (ret < 0) {
- /* mask not supported on A21e, A22p, T20, T21, X20, X22, X24 */
- ibm->supported = 0;
- ret = hotkey_get(ibm,
- &ibm->state.hotkey.status,
- &ibm->state.hotkey.mask);
+ if (hotkey_supported) {
+ /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ A30, R30, R31, T20-22, X20-21, X22-24 */
+ hotkey_mask_supported =
+ acpi_evalf(hkey_handle, NULL, "DHKN", "qv");
+
+ if (!hotkey_get(&hotkey_orig_status, &hotkey_orig_mask))
+ return -ENODEV;
}
- return ret;
-}
+ return 0;
+}
-static int hotkey_read(struct ibm_struct *ibm, char *p)
+static int hotkey_read(char *p)
{
int status, mask;
int len = 0;
- if (hotkey_get(ibm, &status, &mask) < 0)
+ if (!hotkey_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+
+ if (!hotkey_get(&status, &mask))
return -EIO;
len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
- if (ibm->supported) {
+ if (hotkey_mask_supported) {
len += sprintf(p + len, "mask:\t\t0x%04x\n", mask);
len += sprintf(p + len,
"commands:\tenable, disable, reset, <mask>\n");
@@ -352,23 +449,26 @@ static int hotkey_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int hotkey_write(struct ibm_struct *ibm, char *buf)
+static int hotkey_write(char *buf)
{
int status, mask;
char *cmd;
int do_cmd = 0;
- if (hotkey_get(ibm, &status, &mask) < 0)
+ if (!hotkey_supported)
return -ENODEV;
+ if (!hotkey_get(&status, &mask))
+ return -EIO;
+
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
status = 1;
} else if (strlencmp(cmd, "disable") == 0) {
status = 0;
} else if (strlencmp(cmd, "reset") == 0) {
- status = ibm->state.hotkey.status;
- mask = ibm->state.hotkey.mask;
+ status = hotkey_orig_status;
+ mask = hotkey_orig_mask;
} else if (sscanf(cmd, "0x%x", &mask) == 1) {
/* mask set */
} else if (sscanf(cmd, "%x", &mask) == 1) {
@@ -378,15 +478,16 @@ static int hotkey_write(struct ibm_struct *ibm, char *buf)
do_cmd = 1;
}
- if (do_cmd && hotkey_set(ibm, status, mask) < 0)
+ if (do_cmd && !hotkey_set(status, mask))
return -EIO;
return 0;
-}
+}
-static void hotkey_exit(struct ibm_struct *ibm)
+static void hotkey_exit(void)
{
- hotkey_set(ibm, ibm->state.hotkey.status, ibm->state.hotkey.mask);
+ if (hotkey_supported)
+ hotkey_set(hotkey_orig_status, hotkey_orig_mask);
}
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -398,33 +499,38 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
else {
printk(IBM_ERR "unknown hotkey event %d\n", event);
acpi_bus_generate_event(ibm->device, event, 0);
- }
+ }
}
-static int bluetooth_init(struct ibm_struct *ibm)
+static int bluetooth_supported;
+
+static int bluetooth_init(void)
{
- /* bluetooth not supported on A21e, G40, T20, T21, X20 */
- ibm->supported = acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
+ /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ G4x, R30, R31, R40e, R50e, T20-22, X20-21 */
+ bluetooth_supported = hkey_handle &&
+ acpi_evalf(hkey_handle, NULL, "GBDC", "qv");
return 0;
}
-static int bluetooth_status(struct ibm_struct *ibm)
+static int bluetooth_status(void)
{
int status;
- if (!ibm->supported || !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+ if (!bluetooth_supported ||
+ !acpi_evalf(hkey_handle, &status, "GBDC", "d"))
status = 0;
return status;
}
-static int bluetooth_read(struct ibm_struct *ibm, char *p)
+static int bluetooth_read(char *p)
{
int len = 0;
- int status = bluetooth_status(ibm);
+ int status = bluetooth_status();
- if (!ibm->supported)
+ if (!bluetooth_supported)
len += sprintf(p + len, "status:\t\tnot supported\n");
else if (!(status & 1))
len += sprintf(p + len, "status:\t\tnot installed\n");
@@ -436,14 +542,14 @@ static int bluetooth_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int bluetooth_write(struct ibm_struct *ibm, char *buf)
+static int bluetooth_write(char *buf)
{
- int status = bluetooth_status(ibm);
+ int status = bluetooth_status();
char *cmd;
int do_cmd = 0;
- if (!ibm->supported)
- return -EINVAL;
+ if (!bluetooth_supported)
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
@@ -456,64 +562,166 @@ static int bluetooth_write(struct ibm_struct *ibm, char *buf)
}
if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
- return -EIO;
+ return -EIO;
return 0;
}
-static int video_init(struct ibm_struct *ibm)
+static int video_supported;
+static int video_orig_autosw;
+
+#define VIDEO_570 1
+#define VIDEO_770 2
+#define VIDEO_NEW 3
+
+static int video_init(void)
{
- if (!acpi_evalf(vid_handle,
- &ibm->state.video.autoswitch, "^VDEE", "d"))
- return -ENODEV;
+ int ivga;
+
+ if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga)
+ /* G41, assume IVGA doesn't change */
+ vid_handle = vid2_handle;
+
+ if (!vid_handle)
+ /* video switching not supported on R30, R31 */
+ video_supported = 0;
+ else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
+ /* 570 */
+ video_supported = VIDEO_570;
+ else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
+ /* 600e/x, 770e, 770x */
+ video_supported = VIDEO_770;
+ else
+ /* all others */
+ video_supported = VIDEO_NEW;
return 0;
}
-static int video_status(struct ibm_struct *ibm)
+static int video_status(void)
{
int status = 0;
int i;
- acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
- if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
- status |= 0x02 * i;
+ if (video_supported == VIDEO_570) {
+ if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
+ status = i & 3;
+ } else if (video_supported == VIDEO_770) {
+ if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
+ status |= 0x01 * i;
+ if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
+ status |= 0x02 * i;
+ } else if (video_supported == VIDEO_NEW) {
+ acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
+ if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
+ status |= 0x02 * i;
+
+ acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
+ if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
+ status |= 0x01 * i;
+ if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
+ status |= 0x08 * i;
+ }
+
+ return status;
+}
- acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0);
- if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
- status |= 0x01 * i;
- if (acpi_evalf(NULL, &i, "\\VCDD", "d"))
- status |= 0x08 * i;
+static int video_autosw(void)
+{
+ int autosw = 0;
- if (acpi_evalf(vid_handle, &i, "^VDEE", "d"))
- status |= 0x10 * (i & 1);
+ if (video_supported == VIDEO_570)
+ acpi_evalf(vid_handle, &autosw, "SWIT", "d");
+ else if (video_supported == VIDEO_770 || video_supported == VIDEO_NEW)
+ acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
- return status;
+ return autosw & 1;
}
-static int video_read(struct ibm_struct *ibm, char *p)
+static int video_read(char *p)
{
- int status = video_status(ibm);
+ int status = video_status();
+ int autosw = video_autosw();
int len = 0;
+ if (!video_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+
+ len += sprintf(p + len, "status:\t\tsupported\n");
len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
- len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
- len += sprintf(p + len, "auto:\t\t%s\n", enabled(status, 4));
- len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable, "
- "crt_enable, crt_disable\n");
- len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable, "
- "auto_enable, auto_disable\n");
+ if (video_supported == VIDEO_NEW)
+ len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
+ len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
+ len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
+ len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
+ if (video_supported == VIDEO_NEW)
+ len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
+ len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
return len;
}
-static int video_write(struct ibm_struct *ibm, char *buf)
+static int video_switch(void)
+{
+ int autosw = video_autosw();
+ int ret;
+
+ if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
+ return -EIO;
+ ret = video_supported == VIDEO_570 ?
+ acpi_evalf(ec_handle, NULL, "_Q16", "v") :
+ acpi_evalf(vid_handle, NULL, "VSWT", "v");
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
+
+ return ret;
+}
+
+static int video_expand(void)
+{
+ if (video_supported == VIDEO_570)
+ return acpi_evalf(ec_handle, NULL, "_Q17", "v");
+ else if (video_supported == VIDEO_770)
+ return acpi_evalf(vid_handle, NULL, "VEXP", "v");
+ else
+ return acpi_evalf(NULL, NULL, "\\VEXP", "v");
+}
+
+static int video_switch2(int status)
+{
+ int ret;
+
+ if (video_supported == VIDEO_570) {
+ ret = acpi_evalf(NULL, NULL,
+ "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
+ } else if (video_supported == VIDEO_770) {
+ int autosw = video_autosw();
+ if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
+ return -EIO;
+
+ ret = acpi_evalf(vid_handle, NULL,
+ "ASWT", "vdd", status * 0x100, 0);
+
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
+ } else {
+ ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
+ acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
+ }
+
+ return ret;
+}
+
+static int video_write(char *buf)
{
char *cmd;
int enable, disable, status;
+ if (!video_supported)
+ return -ENODEV;
+
enable = disable = 0;
while ((cmd = next_cmd(&buf))) {
@@ -525,9 +733,11 @@ static int video_write(struct ibm_struct *ibm, char *buf)
enable |= 0x02;
} else if (strlencmp(cmd, "crt_disable") == 0) {
disable |= 0x02;
- } else if (strlencmp(cmd, "dvi_enable") == 0) {
+ } else if (video_supported == VIDEO_NEW &&
+ strlencmp(cmd, "dvi_enable") == 0) {
enable |= 0x08;
- } else if (strlencmp(cmd, "dvi_disable") == 0) {
+ } else if (video_supported == VIDEO_NEW &&
+ strlencmp(cmd, "dvi_disable") == 0) {
disable |= 0x08;
} else if (strlencmp(cmd, "auto_enable") == 0) {
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
@@ -536,71 +746,75 @@ static int video_write(struct ibm_struct *ibm, char *buf)
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0))
return -EIO;
} else if (strlencmp(cmd, "video_switch") == 0) {
- int autoswitch;
- if (!acpi_evalf(vid_handle, &autoswitch, "^VDEE", "d"))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "VSWT", "v"))
- return -EIO;
- if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd",
- autoswitch))
+ if (!video_switch())
return -EIO;
} else if (strlencmp(cmd, "expand_toggle") == 0) {
- if (!acpi_evalf(NULL, NULL, "\\VEXP", "v"))
+ if (!video_expand())
return -EIO;
} else
return -EINVAL;
}
if (enable || disable) {
- status = (video_status(ibm) & 0x0f & ~disable) | enable;
- if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80))
- return -EIO;
- if (!acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1))
+ status = (video_status() & 0x0f & ~disable) | enable;
+ if (!video_switch2(status))
return -EIO;
}
return 0;
}
-static void video_exit(struct ibm_struct *ibm)
+static void video_exit(void)
{
- acpi_evalf(vid_handle, NULL, "_DOS", "vd",
- ibm->state.video.autoswitch);
+ acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw);
}
-static int light_init(struct ibm_struct *ibm)
+static int light_supported;
+static int light_status_supported;
+
+static int light_init(void)
{
- /* kblt not supported on G40, R32, X20 */
- ibm->supported = acpi_evalf(ec_handle, NULL, "KBLT", "qv");
+ /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
+ light_supported = (cmos_handle || lght_handle) && !ledb_handle;
+
+ if (light_supported)
+ /* light status not supported on
+ 570, 600e/x, 770e, 770x, G4x, R30, R31, R32, X20 */
+ light_status_supported = acpi_evalf(ec_handle, NULL,
+ "KBLT", "qv");
return 0;
}
-static int light_read(struct ibm_struct *ibm, char *p)
+static int light_read(char *p)
{
int len = 0;
int status = 0;
- if (ibm->supported) {
+ if (!light_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ } else if (!light_status_supported) {
+ len += sprintf(p + len, "status:\t\tunknown\n");
+ len += sprintf(p + len, "commands:\ton, off\n");
+ } else {
if (!acpi_evalf(ec_handle, &status, "KBLT", "d"))
return -EIO;
len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
- } else
- len += sprintf(p + len, "status:\t\tunknown\n");
-
- len += sprintf(p + len, "commands:\ton, off\n");
+ len += sprintf(p + len, "commands:\ton, off\n");
+ }
return len;
}
-static int light_write(struct ibm_struct *ibm, char *buf)
+static int light_write(char *buf)
{
int cmos_cmd, lght_cmd;
char *cmd;
int success;
-
+
+ if (!light_supported)
+ return -ENODEV;
+
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "on") == 0) {
cmos_cmd = 0x0c;
@@ -610,10 +824,10 @@ static int light_write(struct ibm_struct *ibm, char *buf)
lght_cmd = 0;
} else
return -EINVAL;
-
+
success = cmos_handle ?
- acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
- acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
+ acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) :
+ acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd);
if (!success)
return -EIO;
}
@@ -633,7 +847,7 @@ static int _sta(acpi_handle handle)
#define dock_docked() (_sta(dock_handle) & 1)
-static int dock_read(struct ibm_struct *ibm, char *p)
+static int dock_read(char *p)
{
int len = 0;
int docked = dock_docked();
@@ -650,18 +864,17 @@ static int dock_read(struct ibm_struct *ibm, char *p)
return len;
}
-static int dock_write(struct ibm_struct *ibm, char *buf)
+static int dock_write(char *buf)
{
char *cmd;
if (!dock_docked())
- return -EINVAL;
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "undock") == 0) {
- if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0))
- return -EIO;
- if (!acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
+ if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
+ !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
return -EIO;
} else if (strlencmp(cmd, "dock") == 0) {
if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
@@ -671,90 +884,131 @@ static int dock_write(struct ibm_struct *ibm, char *buf)
}
return 0;
-}
+}
static void dock_notify(struct ibm_struct *ibm, u32 event)
{
int docked = dock_docked();
-
- if (event == 3 && docked)
- acpi_bus_generate_event(ibm->device, event, 1); /* button */
+ int pci = ibm->hid && strstr(ibm->hid, IBM_PCI_HID);
+
+ if (event == 1 && !pci) /* 570 */
+ acpi_bus_generate_event(ibm->device, event, 1); /* button */
+ else if (event == 1 && pci) /* 570 */
+ acpi_bus_generate_event(ibm->device, event, 3); /* dock */
+ else if (event == 3 && docked)
+ acpi_bus_generate_event(ibm->device, event, 1); /* button */
else if (event == 3 && !docked)
- acpi_bus_generate_event(ibm->device, event, 2); /* undock */
+ acpi_bus_generate_event(ibm->device, event, 2); /* undock */
else if (event == 0 && docked)
- acpi_bus_generate_event(ibm->device, event, 3); /* dock */
+ acpi_bus_generate_event(ibm->device, event, 3); /* dock */
else {
printk(IBM_ERR "unknown dock event %d, status %d\n",
event, _sta(dock_handle));
- acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
+ acpi_bus_generate_event(ibm->device, event, 0); /* unknown */
}
}
-#define bay_occupied() (_sta(bay_handle) & 1)
+static int bay_status_supported;
+static int bay_status2_supported;
+static int bay_eject_supported;
+static int bay_eject2_supported;
-static int bay_init(struct ibm_struct *ibm)
+static int bay_init(void)
{
- /* bay not supported on A21e, A22p, A31, A31p, G40, R32, R40e */
- ibm->supported = bay_handle && bayej_handle &&
- acpi_evalf(bay_handle, NULL, "_STA", "qv");
+ bay_status_supported = bay_handle &&
+ acpi_evalf(bay_handle, NULL, "_STA", "qv");
+ bay_status2_supported = bay2_handle &&
+ acpi_evalf(bay2_handle, NULL, "_STA", "qv");
+
+ bay_eject_supported = bay_handle && bay_ej_handle &&
+ (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
+ bay_eject2_supported = bay2_handle && bay2_ej_handle &&
+ (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
return 0;
}
-static int bay_read(struct ibm_struct *ibm, char *p)
+#define bay_occupied(b) (_sta(b##_handle) & 1)
+
+static int bay_read(char *p)
{
int len = 0;
- int occupied = bay_occupied();
-
- if (!ibm->supported)
- len += sprintf(p + len, "status:\t\tnot supported\n");
- else if (!occupied)
- len += sprintf(p + len, "status:\t\tunoccupied\n");
- else {
- len += sprintf(p + len, "status:\t\toccupied\n");
+ int occupied = bay_occupied(bay);
+ int occupied2 = bay_occupied(bay2);
+ int eject, eject2;
+
+ len += sprintf(p + len, "status:\t\t%s\n", bay_status_supported ?
+ (occupied ? "occupied" : "unoccupied") :
+ "not supported");
+ if (bay_status2_supported)
+ len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
+ "occupied" : "unoccupied");
+
+ eject = bay_eject_supported && occupied;
+ eject2 = bay_eject2_supported && occupied2;
+
+ if (eject && eject2)
+ len += sprintf(p + len, "commands:\teject, eject2\n");
+ else if (eject)
len += sprintf(p + len, "commands:\teject\n");
- }
+ else if (eject2)
+ len += sprintf(p + len, "commands:\teject2\n");
return len;
}
-static int bay_write(struct ibm_struct *ibm, char *buf)
+static int bay_write(char *buf)
{
char *cmd;
+ if (!bay_eject_supported && !bay_eject2_supported)
+ return -ENODEV;
+
while ((cmd = next_cmd(&buf))) {
- if (strlencmp(cmd, "eject") == 0) {
- if (!ibm->supported ||
- !acpi_evalf(bay_handle, NULL, "_EJ0", "vd", 1))
+ if (bay_eject_supported && strlencmp(cmd, "eject") == 0) {
+ if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
+ return -EIO;
+ } else if (bay_eject2_supported &&
+ strlencmp(cmd, "eject2") == 0) {
+ if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
return -EIO;
} else
return -EINVAL;
}
return 0;
-}
+}
static void bay_notify(struct ibm_struct *ibm, u32 event)
{
acpi_bus_generate_event(ibm->device, event, 0);
}
-static int cmos_read(struct ibm_struct *ibm, char *p)
+static int cmos_read(char *p)
{
int len = 0;
- /* cmos not supported on A21e, A22p, T20, T21, X20 */
+ /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+ R30, R31, T20-22, X20-21 */
if (!cmos_handle)
len += sprintf(p + len, "status:\t\tnot supported\n");
else {
len += sprintf(p + len, "status:\t\tsupported\n");
- len += sprintf(p + len, "commands:\t<int>\n");
+ len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
}
return len;
}
-static int cmos_write(struct ibm_struct *ibm, char *buf)
+static int cmos_eval(int cmos_cmd)
+{
+ if (cmos_handle)
+ return acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd);
+ else
+ return 1;
+}
+
+static int cmos_write(char *buf)
{
char *cmd;
int cmos_cmd;
@@ -763,183 +1017,644 @@ static int cmos_write(struct ibm_struct *ibm, char *buf)
return -EINVAL;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &cmos_cmd) == 1) {
+ if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
+ cmos_cmd >= 0 && cmos_cmd <= 21) {
/* cmos_cmd set */
} else
return -EINVAL;
- if (!acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd))
+ if (!cmos_eval(cmos_cmd))
return -EIO;
}
return 0;
-}
-
-static int led_read(struct ibm_struct *ibm, char *p)
+}
+
+static int led_supported;
+
+#define LED_570 1
+#define LED_OLD 2
+#define LED_NEW 3
+
+static int led_init(void)
+{
+ if (!led_handle)
+ /* led not supported on R30, R31 */
+ led_supported = 0;
+ else if (strlencmp(led_path, "SLED") == 0)
+ /* 570 */
+ led_supported = LED_570;
+ else if (strlencmp(led_path, "SYSL") == 0)
+ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+ led_supported = LED_OLD;
+ else
+ /* all others */
+ led_supported = LED_NEW;
+
+ return 0;
+}
+
+#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))
+
+static int led_read(char *p)
{
int len = 0;
+ if (!led_supported) {
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ return len;
+ }
+ len += sprintf(p + len, "status:\t\tsupported\n");
+
+ if (led_supported == LED_570) {
+ /* 570 */
+ int i, status;
+ for (i = 0; i < 8; i++) {
+ if (!acpi_evalf(ec_handle,
+ &status, "GLED", "dd", 1 << i))
+ return -EIO;
+ len += sprintf(p + len, "%d:\t\t%s\n",
+ i, led_status(status));
+ }
+ }
+
len += sprintf(p + len, "commands:\t"
- "<int> on, <int> off, <int> blink\n");
+ "<led> on, <led> off, <led> blink (<led> is 0-7)\n");
return len;
}
-static int led_write(struct ibm_struct *ibm, char *buf)
+/* off, on, blink */
+static const int led_sled_arg1[] = { 0, 1, 3 };
+static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */
+static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */
+static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
+
+#define EC_HLCL 0x0c
+#define EC_HLBL 0x0d
+#define EC_HLMS 0x0e
+
+static int led_write(char *buf)
{
char *cmd;
- unsigned int led;
- int led_cmd, sysl_cmd, bled_a, bled_b;
+ int led, ind, ret;
+
+ if (!led_supported)
+ return -ENODEV;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &led) != 1)
+ if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7)
return -EINVAL;
- if (strstr(cmd, "blink")) {
- led_cmd = 0xc0;
- sysl_cmd = 2;
- bled_a = 2;
- bled_b = 1;
+ if (strstr(cmd, "off")) {
+ ind = 0;
} else if (strstr(cmd, "on")) {
- led_cmd = 0x80;
- sysl_cmd = 1;
- bled_a = 2;
- bled_b = 0;
- } else if (strstr(cmd, "off")) {
- led_cmd = sysl_cmd = bled_a = bled_b = 0;
+ ind = 1;
+ } else if (strstr(cmd, "blink")) {
+ ind = 2;
} else
return -EINVAL;
-
- if (led_handle) {
+
+ if (led_supported == LED_570) {
+ /* 570 */
+ led = 1 << led;
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
- led, led_cmd))
+ led, led_sled_arg1[ind]))
return -EIO;
- } else if (led < 2) {
- if (acpi_evalf(sysl_handle, NULL, NULL, "vdd",
- led, sysl_cmd))
+ } else if (led_supported == LED_OLD) {
+ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+ led = 1 << led;
+ ret = ec_write(EC_HLMS, led);
+ if (ret >= 0)
+ ret =
+ ec_write(EC_HLBL, led * led_exp_hlbl[ind]);
+ if (ret >= 0)
+ ret =
+ ec_write(EC_HLCL, led * led_exp_hlcl[ind]);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* all others */
+ if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+ led, led_led_arg1[ind]))
return -EIO;
- } else if (led == 2 && bled_handle) {
- if (acpi_evalf(bled_handle, NULL, NULL, "vdd",
- bled_a, bled_b))
+ }
+ }
+
+ return 0;
+}
+
+static int beep_read(char *p)
+{
+ int len = 0;
+
+ if (!beep_handle)
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ else {
+ len += sprintf(p + len, "status:\t\tsupported\n");
+ len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
+ }
+
+ return len;
+}
+
+static int beep_write(char *buf)
+{
+ char *cmd;
+ int beep_cmd;
+
+ if (!beep_handle)
+ return -ENODEV;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
+ beep_cmd >= 0 && beep_cmd <= 17) {
+ /* beep_cmd set */
+ } else
+ return -EINVAL;
+ if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int acpi_ec_read(int i, u8 * p)
+{
+ int v;
+
+ if (ecrd_handle) {
+ if (!acpi_evalf(ecrd_handle, &v, NULL, "dd", i))
+ return 0;
+ *p = v;
+ } else {
+ if (ec_read(i, p) < 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int acpi_ec_write(int i, u8 v)
+{
+ if (ecwr_handle) {
+ if (!acpi_evalf(ecwr_handle, NULL, NULL, "vdd", i, v))
+ return 0;
+ } else {
+ if (ec_write(i, v) < 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int thermal_tmp_supported;
+static int thermal_updt_supported;
+
+static int thermal_init(void)
+{
+ /* temperatures not supported on 570, G4x, R30, R31, R32 */
+ thermal_tmp_supported = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+
+ /* 600e/x, 770e, 770x */
+ thermal_updt_supported = acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+
+ return 0;
+}
+
+static int thermal_read(char *p)
+{
+ int len = 0;
+
+ if (!thermal_tmp_supported)
+ len += sprintf(p + len, "temperatures:\tnot supported\n");
+ else {
+ int i, t;
+ char tmpi[] = "TMPi";
+ s8 tmp[8];
+
+ if (thermal_updt_supported)
+ if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+ return -EIO;
+
+ for (i = 0; i < 8; i++) {
+ tmpi[3] = '0' + i;
+ if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+ return -EIO;
+ if (thermal_updt_supported)
+ tmp[i] = (t - 2732 + 5) / 10;
+ else
+ tmp[i] = t;
+ }
+
+ len += sprintf(p + len,
+ "temperatures:\t%d %d %d %d %d %d %d %d\n",
+ tmp[0], tmp[1], tmp[2], tmp[3],
+ tmp[4], tmp[5], tmp[6], tmp[7]);
+ }
+
+ return len;
+}
+
+static u8 ecdump_regs[256];
+
+static int ecdump_read(char *p)
+{
+ int len = 0;
+ int i, j;
+ u8 v;
+
+ len += sprintf(p + len, "EC "
+ " +00 +01 +02 +03 +04 +05 +06 +07"
+ " +08 +09 +0a +0b +0c +0d +0e +0f\n");
+ for (i = 0; i < 256; i += 16) {
+ len += sprintf(p + len, "EC 0x%02x:", i);
+ for (j = 0; j < 16; j++) {
+ if (!acpi_ec_read(i + j, &v))
+ break;
+ if (v != ecdump_regs[i + j])
+ len += sprintf(p + len, " *%02x", v);
+ else
+ len += sprintf(p + len, " %02x", v);
+ ecdump_regs[i + j] = v;
+ }
+ len += sprintf(p + len, "\n");
+ if (j != 16)
+ break;
+ }
+
+ /* These are way too dangerous to advertise openly... */
+#if 0
+ len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
+ " (<offset> is 00-ff, <value> is 00-ff)\n");
+ len += sprintf(p + len, "commands:\t0x<offset> <value> "
+ " (<offset> is 00-ff, <value> is 0-255)\n");
+#endif
+ return len;
+}
+
+static int ecdump_write(char *buf)
+{
+ char *cmd;
+ int i, v;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) {
+ /* i and v set */
+ } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) {
+ /* i and v set */
+ } else
+ return -EINVAL;
+ if (i >= 0 && i < 256 && v >= 0 && v < 256) {
+ if (!acpi_ec_write(i, v))
return -EIO;
} else
return -EINVAL;
}
return 0;
-}
-
-static int beep_read(struct ibm_struct *ibm, char *p)
+}
+
+static int brightness_offset = 0x31;
+
+static int brightness_read(char *p)
{
int len = 0;
+ u8 level;
- len += sprintf(p + len, "commands:\t<int>\n");
+ if (!acpi_ec_read(brightness_offset, &level)) {
+ len += sprintf(p + len, "level:\t\tunreadable\n");
+ } else {
+ len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
+ len += sprintf(p + len, "commands:\tup, down\n");
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-7)\n");
+ }
return len;
}
-static int beep_write(struct ibm_struct *ibm, char *buf)
+#define BRIGHTNESS_UP 4
+#define BRIGHTNESS_DOWN 5
+
+static int brightness_write(char *buf)
{
+ int cmos_cmd, inc, i;
+ u8 level;
+ int new_level;
char *cmd;
- int beep_cmd;
while ((cmd = next_cmd(&buf))) {
- if (sscanf(cmd, "%u", &beep_cmd) == 1) {
- /* beep_cmd set */
+ if (!acpi_ec_read(brightness_offset, &level))
+ return -EIO;
+ level &= 7;
+
+ if (strlencmp(cmd, "up") == 0) {
+ new_level = level == 7 ? 7 : level + 1;
+ } else if (strlencmp(cmd, "down") == 0) {
+ new_level = level == 0 ? 0 : level - 1;
+ } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
+ new_level >= 0 && new_level <= 7) {
+ /* new_level set */
+ } else
+ return -EINVAL;
+
+ cmos_cmd = new_level > level ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
+ inc = new_level > level ? 1 : -1;
+ for (i = level; i != new_level; i += inc) {
+ if (!cmos_eval(cmos_cmd))
+ return -EIO;
+ if (!acpi_ec_write(brightness_offset, i + inc))
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int volume_offset = 0x30;
+
+static int volume_read(char *p)
+{
+ int len = 0;
+ u8 level;
+
+ if (!acpi_ec_read(volume_offset, &level)) {
+ len += sprintf(p + len, "level:\t\tunreadable\n");
+ } else {
+ len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
+ len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
+ len += sprintf(p + len, "commands:\tup, down, mute\n");
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-15)\n");
+ }
+
+ return len;
+}
+
+#define VOLUME_DOWN 0
+#define VOLUME_UP 1
+#define VOLUME_MUTE 2
+
+static int volume_write(char *buf)
+{
+ int cmos_cmd, inc, i;
+ u8 level, mute;
+ int new_level, new_mute;
+ char *cmd;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (!acpi_ec_read(volume_offset, &level))
+ return -EIO;
+ new_mute = mute = level & 0x40;
+ new_level = level = level & 0xf;
+
+ if (strlencmp(cmd, "up") == 0) {
+ if (mute)
+ new_mute = 0;
+ else
+ new_level = level == 15 ? 15 : level + 1;
+ } else if (strlencmp(cmd, "down") == 0) {
+ if (mute)
+ new_mute = 0;
+ else
+ new_level = level == 0 ? 0 : level - 1;
+ } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
+ new_level >= 0 && new_level <= 15) {
+ /* new_level set */
+ } else if (strlencmp(cmd, "mute") == 0) {
+ new_mute = 0x40;
} else
return -EINVAL;
- if (!acpi_evalf(beep_handle, NULL, NULL, "vd", beep_cmd))
+ if (new_level != level) { /* mute doesn't change */
+ cmos_cmd = new_level > level ? VOLUME_UP : VOLUME_DOWN;
+ inc = new_level > level ? 1 : -1;
+
+ if (mute && (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, level)))
+ return -EIO;
+
+ for (i = level; i != new_level; i += inc)
+ if (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, i + inc))
+ return -EIO;
+
+ if (mute && (!cmos_eval(VOLUME_MUTE) ||
+ !acpi_ec_write(volume_offset,
+ new_level + mute)))
+ return -EIO;
+ }
+
+ if (new_mute != mute) { /* level doesn't change */
+ cmos_cmd = new_mute ? VOLUME_MUTE : VOLUME_UP;
+
+ if (!cmos_eval(cmos_cmd) ||
+ !acpi_ec_write(volume_offset, level + new_mute))
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int fan_status_offset = 0x2f;
+static int fan_rpm_offset = 0x84;
+
+static int fan_read(char *p)
+{
+ int len = 0;
+ int s;
+ u8 lo, hi, status;
+
+ if (gfan_handle) {
+ /* 570, 600e/x, 770e, 770x */
+ if (!acpi_evalf(gfan_handle, &s, NULL, "d"))
return -EIO;
+
+ len += sprintf(p + len, "level:\t\t%d\n", s);
+ } else {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_read(fan_status_offset, &status))
+ len += sprintf(p + len, "status:\t\tunreadable\n");
+ else
+ len += sprintf(p + len, "status:\t\t%s\n",
+ enabled(status, 7));
+
+ if (!acpi_ec_read(fan_rpm_offset, &lo) ||
+ !acpi_ec_read(fan_rpm_offset + 1, &hi))
+ len += sprintf(p + len, "speed:\t\tunreadable\n");
+ else
+ len += sprintf(p + len, "speed:\t\t%d\n",
+ (hi << 8) + lo);
+ }
+
+ if (sfan_handle)
+ /* 570, 770x-JL */
+ len += sprintf(p + len, "commands:\tlevel <level>"
+ " (<level> is 0-7)\n");
+ if (!gfan_handle)
+ /* all except 570, 600e/x, 770e, 770x */
+ len += sprintf(p + len, "commands:\tenable, disable\n");
+ if (fans_handle)
+ /* X31, X40 */
+ len += sprintf(p + len, "commands:\tspeed <speed>"
+ " (<speed> is 0-65535)\n");
+
+ return len;
+}
+
+static int fan_write(char *buf)
+{
+ char *cmd;
+ int level, speed;
+
+ while ((cmd = next_cmd(&buf))) {
+ if (sfan_handle &&
+ sscanf(cmd, "level %d", &level) == 1 &&
+ level >= 0 && level <= 7) {
+ /* 570, 770x-JL */
+ if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+ return -EIO;
+ } else if (!gfan_handle && strlencmp(cmd, "enable") == 0) {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_write(fan_status_offset, 0x80))
+ return -EIO;
+ } else if (!gfan_handle && strlencmp(cmd, "disable") == 0) {
+ /* all except 570, 600e/x, 770e, 770x */
+ if (!acpi_ec_write(fan_status_offset, 0x00))
+ return -EIO;
+ } else if (fans_handle &&
+ sscanf(cmd, "speed %d", &speed) == 1 &&
+ speed >= 0 && speed <= 65535) {
+ /* X31, X40 */
+ if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
+ speed, speed, speed))
+ return -EIO;
+ } else
+ return -EINVAL;
}
return 0;
-}
-
+}
+
static struct ibm_struct ibms[] = {
{
- .name = "driver",
- .init = driver_init,
- .read = driver_read,
- },
+ .name = "driver",
+ .init = driver_init,
+ .read = driver_read,
+ },
+ {
+ .name = "hotkey",
+ .hid = IBM_HKEY_HID,
+ .init = hotkey_init,
+ .read = hotkey_read,
+ .write = hotkey_write,
+ .exit = hotkey_exit,
+ .notify = hotkey_notify,
+ .handle = &hkey_handle,
+ .type = ACPI_DEVICE_NOTIFY,
+ },
+ {
+ .name = "bluetooth",
+ .init = bluetooth_init,
+ .read = bluetooth_read,
+ .write = bluetooth_write,
+ },
+ {
+ .name = "video",
+ .init = video_init,
+ .read = video_read,
+ .write = video_write,
+ .exit = video_exit,
+ },
{
- .name = "hotkey",
- .hid = "IBM0068",
- .init = hotkey_init,
- .read = hotkey_read,
- .write = hotkey_write,
- .exit = hotkey_exit,
- .notify = hotkey_notify,
- .handle = &hkey_handle,
- .type = ACPI_DEVICE_NOTIFY,
- },
+ .name = "light",
+ .init = light_init,
+ .read = light_read,
+ .write = light_write,
+ },
{
- .name = "bluetooth",
- .init = bluetooth_init,
- .read = bluetooth_read,
- .write = bluetooth_write,
- },
+ .name = "dock",
+ .read = dock_read,
+ .write = dock_write,
+ .notify = dock_notify,
+ .handle = &dock_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "video",
- .init = video_init,
- .read = video_read,
- .write = video_write,
- .exit = video_exit,
- },
+ .name = "dock",
+ .hid = IBM_PCI_HID,
+ .notify = dock_notify,
+ .handle = &pci_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "light",
- .init = light_init,
- .read = light_read,
- .write = light_write,
- },
+ .name = "bay",
+ .init = bay_init,
+ .read = bay_read,
+ .write = bay_write,
+ .notify = bay_notify,
+ .handle = &bay_handle,
+ .type = ACPI_SYSTEM_NOTIFY,
+ },
{
- .name = "dock",
- .read = dock_read,
- .write = dock_write,
- .notify = dock_notify,
- .handle = &dock_handle,
- .type = ACPI_SYSTEM_NOTIFY,
- },
+ .name = "cmos",
+ .read = cmos_read,
+ .write = cmos_write,
+ },
{
- .name = "bay",
- .init = bay_init,
- .read = bay_read,
- .write = bay_write,
- .notify = bay_notify,
- .handle = &bay_handle,
- .type = ACPI_SYSTEM_NOTIFY,
- },
+ .name = "led",
+ .init = led_init,
+ .read = led_read,
+ .write = led_write,
+ },
{
- .name = "cmos",
- .read = cmos_read,
- .write = cmos_write,
- .experimental = 1,
- },
+ .name = "beep",
+ .read = beep_read,
+ .write = beep_write,
+ },
{
- .name = "led",
- .read = led_read,
- .write = led_write,
- .experimental = 1,
- },
+ .name = "thermal",
+ .init = thermal_init,
+ .read = thermal_read,
+ },
{
- .name = "beep",
- .read = beep_read,
- .write = beep_write,
- .experimental = 1,
- },
+ .name = "ecdump",
+ .read = ecdump_read,
+ .write = ecdump_write,
+ .experimental = 1,
+ },
+ {
+ .name = "brightness",
+ .read = brightness_read,
+ .write = brightness_write,
+ .experimental = 1,
+ },
+ {
+ .name = "volume",
+ .read = volume_read,
+ .write = volume_write,
+ .experimental = 1,
+ },
+ {
+ .name = "fan",
+ .read = fan_read,
+ .write = fan_write,
+ .experimental = 1,
+ },
};
-#define NUM_IBMS (sizeof(ibms)/sizeof(ibms[0]))
static int dispatch_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct ibm_struct *ibm = (struct ibm_struct *)data;
int len;
-
+
if (!ibm || !ibm->read)
return -EINVAL;
- len = ibm->read(ibm, page);
+ len = ibm->read(page);
if (len < 0)
return len;
@@ -955,7 +1670,7 @@ static int dispatch_read(char *page, char **start, off_t off, int count,
return len;
}
-static int dispatch_write(struct file *file, const char __user *userbuf,
+static int dispatch_write(struct file *file, const char __user * userbuf,
unsigned long count, void *data)
{
struct ibm_struct *ibm = (struct ibm_struct *)data;
@@ -969,20 +1684,20 @@ static int dispatch_write(struct file *file, const char __user *userbuf,
if (!kernbuf)
return -ENOMEM;
- if (copy_from_user(kernbuf, userbuf, count)) {
+ if (copy_from_user(kernbuf, userbuf, count)) {
kfree(kernbuf);
- return -EFAULT;
+ return -EFAULT;
}
kernbuf[count] = 0;
strcat(kernbuf, ",");
- ret = ibm->write(ibm, kernbuf);
+ ret = ibm->write(kernbuf);
if (ret == 0)
ret = count;
kfree(kernbuf);
- return ret;
+ return ret;
}
static void dispatch_notify(acpi_handle handle, u32 event, void *data)
@@ -995,7 +1710,7 @@ static void dispatch_notify(acpi_handle handle, u32 event, void *data)
ibm->notify(ibm, event);
}
-static int setup_notify(struct ibm_struct *ibm)
+static int __init setup_notify(struct ibm_struct *ibm)
{
acpi_status status;
int ret;
@@ -1020,17 +1735,15 @@ static int setup_notify(struct ibm_struct *ibm)
return -ENODEV;
}
- ibm->notify_installed = 1;
-
return 0;
}
-static int ibmacpi_device_add(struct acpi_device *device)
+static int __init ibm_device_add(struct acpi_device *device)
{
return 0;
}
-static int register_driver(struct ibm_struct *ibm)
+static int __init register_driver(struct ibm_struct *ibm)
{
int ret;
@@ -1043,7 +1756,7 @@ static int register_driver(struct ibm_struct *ibm)
memset(ibm->driver, 0, sizeof(struct acpi_driver));
sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name);
ibm->driver->ids = ibm->hid;
- ibm->driver->ops.add = &ibmacpi_device_add;
+ ibm->driver->ops.add = &ibm_device_add;
ret = acpi_bus_register_driver(ibm->driver);
if (ret < 0) {
@@ -1055,7 +1768,7 @@ static int register_driver(struct ibm_struct *ibm)
return ret;
}
-static int ibm_init(struct ibm_struct *ibm)
+static int __init ibm_init(struct ibm_struct *ibm)
{
int ret;
struct proc_dir_entry *entry;
@@ -1071,31 +1784,34 @@ static int ibm_init(struct ibm_struct *ibm)
}
if (ibm->init) {
- ret = ibm->init(ibm);
+ ret = ibm->init();
if (ret != 0)
return ret;
ibm->init_called = 1;
}
- entry = create_proc_entry(ibm->name, S_IFREG | S_IRUGO | S_IWUSR,
- proc_dir);
- if (!entry) {
- printk(IBM_ERR "unable to create proc entry %s\n", ibm->name);
- return -ENODEV;
- }
- entry->owner = THIS_MODULE;
- ibm->proc_created = 1;
-
- entry->data = ibm;
- if (ibm->read)
+ if (ibm->read) {
+ entry = create_proc_entry(ibm->name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ proc_dir);
+ if (!entry) {
+ printk(IBM_ERR "unable to create proc entry %s\n",
+ ibm->name);
+ return -ENODEV;
+ }
+ entry->owner = THIS_MODULE;
+ entry->data = ibm;
entry->read_proc = &dispatch_read;
- if (ibm->write)
- entry->write_proc = &dispatch_write;
+ if (ibm->write)
+ entry->write_proc = &dispatch_write;
+ ibm->proc_created = 1;
+ }
if (ibm->notify) {
ret = setup_notify(ibm);
if (ret < 0)
return ret;
+ ibm->notify_installed = 1;
}
return 0;
@@ -1111,7 +1827,7 @@ static void ibm_exit(struct ibm_struct *ibm)
remove_proc_entry(ibm->name, proc_dir);
if (ibm->init_called && ibm->exit)
- ibm->exit(ibm);
+ ibm->exit();
if (ibm->driver_registered) {
acpi_bus_unregister_driver(ibm->driver);
@@ -1119,60 +1835,66 @@ static void ibm_exit(struct ibm_struct *ibm)
}
}
-static int ibm_handle_init(char *name,
- acpi_handle *handle, acpi_handle parent,
- char **paths, int num_paths, int required)
+static void __init ibm_handle_init(char *name,
+ acpi_handle * handle, acpi_handle parent,
+ char **paths, int num_paths, char **path)
{
int i;
acpi_status status;
- for (i=0; i<num_paths; i++) {
+ for (i = 0; i < num_paths; i++) {
status = acpi_get_handle(parent, paths[i], handle);
- if (ACPI_SUCCESS(status))
- return 0;
- }
-
- *handle = NULL;
-
- if (required) {
- printk(IBM_ERR "%s object not found\n", name);
- return -1;
+ if (ACPI_SUCCESS(status)) {
+ *path = paths[i];
+ return;
+ }
}
- return 0;
+ *handle = NULL;
}
-#define IBM_HANDLE_INIT(object, required) \
+#define IBM_HANDLE_INIT(object) \
ibm_handle_init(#object, &object##_handle, *object##_parent, \
- object##_paths, sizeof(object##_paths)/sizeof(char*), required)
-
+ object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
static int set_ibm_param(const char *val, struct kernel_param *kp)
{
unsigned int i;
- char arg_with_comma[32];
-
- if (strlen(val) > 30)
- return -ENOSPC;
- strcpy(arg_with_comma, val);
- strcat(arg_with_comma, ",");
+ for (i = 0; i < ARRAY_SIZE(ibms); i++)
+ if (strcmp(ibms[i].name, kp->name) == 0 && ibms[i].write) {
+ if (strlen(val) > sizeof(ibms[i].param) - 2)
+ return -ENOSPC;
+ strcpy(ibms[i].param, val);
+ strcat(ibms[i].param, ",");
+ return 0;
+ }
- for (i=0; i<NUM_IBMS; i++)
- if (strcmp(ibms[i].name, kp->name) == 0)
- return ibms[i].write(&ibms[i], arg_with_comma);
- BUG();
return -EINVAL;
}
#define IBM_PARAM(feature) \
module_param_call(feature, set_ibm_param, NULL, NULL, 0)
+IBM_PARAM(hotkey);
+IBM_PARAM(bluetooth);
+IBM_PARAM(video);
+IBM_PARAM(light);
+IBM_PARAM(dock);
+IBM_PARAM(bay);
+IBM_PARAM(cmos);
+IBM_PARAM(led);
+IBM_PARAM(beep);
+IBM_PARAM(ecdump);
+IBM_PARAM(brightness);
+IBM_PARAM(volume);
+IBM_PARAM(fan);
+
static void acpi_ibm_exit(void)
{
int i;
- for (i=NUM_IBMS-1; i>=0; i--)
+ for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
ibm_exit(&ibms[i]);
remove_proc_entry(IBM_DIR, acpi_root_dir);
@@ -1185,30 +1907,40 @@ static int __init acpi_ibm_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
- printk(IBM_ERR "Using generic hotkey driver\n");
- return -ENODEV;
- }
- /* these handles are required */
- if (IBM_HANDLE_INIT(ec, 1) < 0 ||
- IBM_HANDLE_INIT(hkey, 1) < 0 ||
- IBM_HANDLE_INIT(vid, 1) < 0 ||
- IBM_HANDLE_INIT(beep, 1) < 0)
+ if (!acpi_specific_hotkey_enabled) {
+ printk(IBM_ERR "using generic hotkey driver\n");
return -ENODEV;
+ }
- /* these handles have alternatives */
- IBM_HANDLE_INIT(lght, 0);
- if (IBM_HANDLE_INIT(cmos, !lght_handle) < 0)
- return -ENODEV;
- IBM_HANDLE_INIT(sysl, 0);
- if (IBM_HANDLE_INIT(led, !sysl_handle) < 0)
+ /* ec is required because many other handles are relative to it */
+ IBM_HANDLE_INIT(ec);
+ if (!ec_handle) {
+ printk(IBM_ERR "ec object not found\n");
return -ENODEV;
+ }
/* these handles are not required */
- IBM_HANDLE_INIT(dock, 0);
- IBM_HANDLE_INIT(bay, 0);
- IBM_HANDLE_INIT(bayej, 0);
- IBM_HANDLE_INIT(bled, 0);
+ IBM_HANDLE_INIT(vid);
+ IBM_HANDLE_INIT(vid2);
+ IBM_HANDLE_INIT(ledb);
+ IBM_HANDLE_INIT(led);
+ IBM_HANDLE_INIT(hkey);
+ IBM_HANDLE_INIT(lght);
+ IBM_HANDLE_INIT(cmos);
+ IBM_HANDLE_INIT(dock);
+ IBM_HANDLE_INIT(pci);
+ IBM_HANDLE_INIT(bay);
+ if (bay_handle)
+ IBM_HANDLE_INIT(bay_ej);
+ IBM_HANDLE_INIT(bay2);
+ if (bay2_handle)
+ IBM_HANDLE_INIT(bay2_ej);
+ IBM_HANDLE_INIT(beep);
+ IBM_HANDLE_INIT(ecrd);
+ IBM_HANDLE_INIT(ecwr);
+ IBM_HANDLE_INIT(fans);
+ IBM_HANDLE_INIT(gfan);
+ IBM_HANDLE_INIT(sfan);
proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
if (!proc_dir) {
@@ -1216,9 +1948,11 @@ static int __init acpi_ibm_init(void)
return -ENODEV;
}
proc_dir->owner = THIS_MODULE;
-
- for (i=0; i<NUM_IBMS; i++) {
+
+ for (i = 0; i < ARRAY_SIZE(ibms); i++) {
ret = ibm_init(&ibms[i]);
+ if (ret >= 0 && *ibms[i].param)
+ ret = ibms[i].write(ibms[i].param);
if (ret < 0) {
acpi_ibm_exit();
return ret;
@@ -1230,17 +1964,3 @@ static int __init acpi_ibm_init(void)
module_init(acpi_ibm_init);
module_exit(acpi_ibm_exit);
-
-MODULE_AUTHOR("Borislav Deianov");
-MODULE_DESCRIPTION(IBM_DESC);
-MODULE_LICENSE("GPL");
-
-IBM_PARAM(hotkey);
-IBM_PARAM(bluetooth);
-IBM_PARAM(video);
-IBM_PARAM(light);
-IBM_PARAM(dock);
-IBM_PARAM(bay);
-IBM_PARAM(cmos);
-IBM_PARAM(led);
-IBM_PARAM(beep);
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index 2934475d67d6..e928e8c2c6ec 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -30,12 +30,11 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("acpi_motherboard")
+ACPI_MODULE_NAME("acpi_motherboard")
/* Dell use PNP0C01 instead of PNP0C02 */
#define ACPI_MB_HID1 "PNP0C01"
#define ACPI_MB_HID2 "PNP0C02"
-
/**
* Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
* Doesn't care about the failure of 'request_region', since other may reserve
@@ -43,16 +42,13 @@ ACPI_MODULE_NAME ("acpi_motherboard")
*/
#define IS_RESERVED_ADDR(base, len) \
(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
- && ((base) + (len) > 0x1000))
-
+ && ((base) + (len) > PCIBIOS_MIN_IO))
/*
* Clearing the flag (IORESOURCE_BUSY) allows drivers to use
* the io ports if they really know they can use it, while
* still preventing hotplug PCI devices from using it.
*/
-
-static acpi_status
-acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
+static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
{
struct resource *requested_res = NULL;
@@ -63,22 +59,32 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
if (io_res->min_base_address != io_res->max_base_address)
return_VALUE(AE_OK);
- if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
- io_res->min_base_address,
- io_res->min_base_address + io_res->range_length));
- requested_res = request_region(io_res->min_base_address,
- io_res->range_length, "motherboard");
+ if (IS_RESERVED_ADDR
+ (io_res->min_base_address, io_res->range_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Motherboard resources 0x%08x - 0x%08x\n",
+ io_res->min_base_address,
+ io_res->min_base_address +
+ io_res->range_length));
+ requested_res =
+ request_region(io_res->min_base_address,
+ io_res->range_length, "motherboard");
}
} else if (res->id == ACPI_RSTYPE_FIXED_IO) {
- struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
-
- if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
- fixed_io_res->base_address,
- fixed_io_res->base_address + fixed_io_res->range_length));
- requested_res = request_region(fixed_io_res->base_address,
- fixed_io_res->range_length, "motherboard");
+ struct acpi_resource_fixed_io *fixed_io_res =
+ &res->data.fixed_io;
+
+ if (IS_RESERVED_ADDR
+ (fixed_io_res->base_address, fixed_io_res->range_length)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Motherboard resources 0x%08x - 0x%08x\n",
+ fixed_io_res->base_address,
+ fixed_io_res->base_address +
+ fixed_io_res->range_length));
+ requested_res =
+ request_region(fixed_io_res->base_address,
+ fixed_io_res->range_length,
+ "motherboard");
}
} else {
/* Memory mapped IO? */
@@ -89,72 +95,70 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
return_VALUE(AE_OK);
}
-static int acpi_motherboard_add (struct acpi_device *device)
+static int acpi_motherboard_add(struct acpi_device *device)
{
if (!device)
return -EINVAL;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- acpi_reserve_io_ranges, NULL);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ acpi_reserve_io_ranges, NULL);
return 0;
}
static struct acpi_driver acpi_motherboard_driver1 = {
- .name = "motherboard",
- .class = "",
- .ids = ACPI_MB_HID1,
- .ops = {
- .add = acpi_motherboard_add,
- },
+ .name = "motherboard",
+ .class = "",
+ .ids = ACPI_MB_HID1,
+ .ops = {
+ .add = acpi_motherboard_add,
+ },
};
static struct acpi_driver acpi_motherboard_driver2 = {
- .name = "motherboard",
- .class = "",
- .ids = ACPI_MB_HID2,
- .ops = {
- .add = acpi_motherboard_add,
- },
+ .name = "motherboard",
+ .class = "",
+ .ids = ACPI_MB_HID2,
+ .ops = {
+ .add = acpi_motherboard_add,
+ },
};
-static void __init
-acpi_reserve_resources (void)
+static void __init acpi_reserve_resources(void)
{
if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
- request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
- acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
+ request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
+ acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
- acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
+ acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
- request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
- acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
+ request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
+ acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
- request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
- acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
+ request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
+ acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
- request_region(acpi_gbl_FADT->xpm_tmr_blk.address,
- 4, "PM_TMR");
+ request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "PM_TMR");
if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
- acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
+ acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
/* Length of GPE blocks must be a non-negative multiple of 2 */
if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
- !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
+ !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
request_region(acpi_gbl_FADT->xgpe0_blk.address,
- acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+ acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
- !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+ !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
request_region(acpi_gbl_FADT->xgpe1_blk.address,
- acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+ acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
}
static int __init acpi_motherboard_init(void)
@@ -166,7 +170,7 @@ static int __init acpi_motherboard_init(void)
* This module must run after scan.c
*/
if (!acpi_disabled)
- acpi_reserve_resources ();
+ acpi_reserve_resources();
return 0;
}
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index ece7a9dedd5c..edfbe34600f5 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsaccess")
-
+ACPI_MODULE_NAME("nsaccess")
/*******************************************************************************
*
@@ -65,24 +62,19 @@
* MUTEX: Locks namespace for entire execution
*
******************************************************************************/
-
-acpi_status
-acpi_ns_root_initialize (
- void)
+acpi_status acpi_ns_root_initialize(void)
{
- acpi_status status;
+ acpi_status status;
const struct acpi_predefined_names *init_val = NULL;
- struct acpi_namespace_node *new_node;
- union acpi_operand_object *obj_desc;
- acpi_string val = NULL;
-
-
- ACPI_FUNCTION_TRACE ("ns_root_initialize");
+ struct acpi_namespace_node *new_node;
+ union acpi_operand_object *obj_desc;
+ acpi_string val = NULL;
+ ACPI_FUNCTION_TRACE("ns_root_initialize");
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -102,24 +94,26 @@ acpi_ns_root_initialize (
/* Enter the pre-defined names in the name table */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Entering predefined entries into namespace\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Entering predefined entries into namespace\n"));
for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
/* _OSI is optional for now, will be permanent later */
- if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) {
+ if (!ACPI_STRCMP(init_val->name, "_OSI")
+ && !acpi_gbl_create_osi_method) {
continue;
}
- status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
- ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
- NULL, &new_node);
+ status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
+ ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_NO_UPSEARCH, NULL, &new_node);
- if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not create predefined name %s, %s\n",
- init_val->name, acpi_format_exception (status)));
+ if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not create predefined name %s, %s\n",
+ init_val->name,
+ acpi_format_exception(status)));
}
/*
@@ -128,11 +122,11 @@ acpi_ns_root_initialize (
* initial value, create the initial value.
*/
if (init_val->val) {
- status = acpi_os_predefined_override (init_val, &val);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not override predefined %s\n",
- init_val->name));
+ status = acpi_os_predefined_override(init_val, &val);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not override predefined %s\n",
+ init_val->name));
}
if (!val) {
@@ -143,7 +137,8 @@ acpi_ns_root_initialize (
* Entry requests an initial value, allocate a
* descriptor for it.
*/
- obj_desc = acpi_ut_create_internal_object (init_val->type);
+ obj_desc =
+ acpi_ut_create_internal_object(init_val->type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -156,55 +151,62 @@ acpi_ns_root_initialize (
*/
switch (init_val->type) {
case ACPI_TYPE_METHOD:
- obj_desc->method.param_count = (u8) ACPI_TO_INTEGER (val);
+ obj_desc->method.param_count =
+ (u8) ACPI_TO_INTEGER(val);
obj_desc->common.flags |= AOPOBJ_DATA_VALID;
-#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
+#if defined (ACPI_ASL_COMPILER)
- /*
- * i_aSL Compiler cheats by putting parameter count
- * in the owner_iD
- */
- new_node->owner_id = obj_desc->method.param_count;
+ /* save the parameter count for the i_aSL compiler */
+
+ new_node->value = obj_desc->method.param_count;
#else
/* Mark this as a very SPECIAL method */
- obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
- obj_desc->method.implementation = acpi_ut_osi_implementation;
+ obj_desc->method.method_flags =
+ AML_METHOD_INTERNAL_ONLY;
+
+#ifndef ACPI_DUMP_APP
+ obj_desc->method.implementation =
+ acpi_ut_osi_implementation;
+#endif
#endif
break;
case ACPI_TYPE_INTEGER:
- obj_desc->integer.value = ACPI_TO_INTEGER (val);
+ obj_desc->integer.value = ACPI_TO_INTEGER(val);
break;
-
case ACPI_TYPE_STRING:
/*
* Build an object around the static string
*/
- obj_desc->string.length = (u32) ACPI_STRLEN (val);
+ obj_desc->string.length =
+ (u32) ACPI_STRLEN(val);
obj_desc->string.pointer = val;
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
-
case ACPI_TYPE_MUTEX:
obj_desc->mutex.node = new_node;
- obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER (val) - 1);
+ obj_desc->mutex.sync_level =
+ (u8) (ACPI_TO_INTEGER(val) - 1);
- if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
+ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) {
/*
* Create a counting semaphore for the
* global lock
*/
- status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
- 1, &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
+ status =
+ acpi_os_create_semaphore
+ (ACPI_NO_UNIT_LIMIT, 1,
+ &obj_desc->mutex.semaphore);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference
+ (obj_desc);
goto unlock_and_exit;
}
@@ -212,56 +214,58 @@ acpi_ns_root_initialize (
* We just created the mutex for the
* global lock, save it
*/
- acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
- }
- else {
+ acpi_gbl_global_lock_semaphore =
+ obj_desc->mutex.semaphore;
+ } else {
/* Create a mutex */
- status = acpi_os_create_semaphore (1, 1,
- &obj_desc->mutex.semaphore);
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (obj_desc);
+ status = acpi_os_create_semaphore(1, 1,
+ &obj_desc->
+ mutex.
+ semaphore);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference
+ (obj_desc);
goto unlock_and_exit;
}
}
break;
-
default:
- ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
- init_val->type));
- acpi_ut_remove_reference (obj_desc);
+ ACPI_REPORT_ERROR(("Unsupported initial type value %X\n", init_val->type));
+ acpi_ut_remove_reference(obj_desc);
obj_desc = NULL;
continue;
}
/* Store pointer to value descriptor in the Node */
- status = acpi_ns_attach_object (new_node, obj_desc,
- ACPI_GET_OBJECT_TYPE (obj_desc));
+ status = acpi_ns_attach_object(new_node, obj_desc,
+ ACPI_GET_OBJECT_TYPE
+ (obj_desc));
/* Remove local reference to the object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
}
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* Save a handle to "_GPE", it is always present */
- if (ACPI_SUCCESS (status)) {
- status = acpi_ns_get_node_by_path ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
- &acpi_gbl_fadt_gpe_device);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_ns_get_node_by_path("\\_GPE", NULL,
+ ACPI_NS_NO_UPSEARCH,
+ &acpi_gbl_fadt_gpe_device);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_lookup
@@ -286,62 +290,57 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_ns_lookup (
- union acpi_generic_state *scope_info,
- char *pathname,
- acpi_object_type type,
- acpi_interpreter_mode interpreter_mode,
- u32 flags,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node **return_node)
+acpi_ns_lookup(union acpi_generic_state *scope_info,
+ char *pathname,
+ acpi_object_type type,
+ acpi_interpreter_mode interpreter_mode,
+ u32 flags,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **return_node)
{
- acpi_status status;
- char *path = pathname;
- struct acpi_namespace_node *prefix_node;
- struct acpi_namespace_node *current_node = NULL;
- struct acpi_namespace_node *this_node = NULL;
- u32 num_segments;
- u32 num_carats;
- acpi_name simple_name;
- acpi_object_type type_to_check_for;
- acpi_object_type this_search_type;
- u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
- u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
- ACPI_NS_SEARCH_PARENT);
-
-
- ACPI_FUNCTION_TRACE ("ns_lookup");
-
+ acpi_status status;
+ char *path = pathname;
+ struct acpi_namespace_node *prefix_node;
+ struct acpi_namespace_node *current_node = NULL;
+ struct acpi_namespace_node *this_node = NULL;
+ u32 num_segments;
+ u32 num_carats;
+ acpi_name simple_name;
+ acpi_object_type type_to_check_for;
+ acpi_object_type this_search_type;
+ u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
+ u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
+ ACPI_NS_SEARCH_PARENT);
+
+ ACPI_FUNCTION_TRACE("ns_lookup");
if (!return_node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
acpi_gbl_ns_lookup_count++;
*return_node = ACPI_ENTRY_NOT_FOUND;
if (!acpi_gbl_root_node) {
- return_ACPI_STATUS (AE_NO_NAMESPACE);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
/*
* Get the prefix scope.
* A null scope means use the root scope
*/
- if ((!scope_info) ||
- (!scope_info->scope.node)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Null scope prefix, using root node (%p)\n",
- acpi_gbl_root_node));
+ if ((!scope_info) || (!scope_info->scope.node)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Null scope prefix, using root node (%p)\n",
+ acpi_gbl_root_node));
prefix_node = acpi_gbl_root_node;
- }
- else {
+ } else {
prefix_node = scope_info->scope.node;
- if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
- ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
- prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
+ ACPI_DESC_TYPE_NAMED) {
+ ACPI_REPORT_ERROR(("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name(prefix_node)));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*
@@ -349,9 +348,9 @@ acpi_ns_lookup (
* Device/Method, etc.) It could be a Package or other object node.
* Backup up the tree to find the containing scope node.
*/
- while (!acpi_ns_opens_scope (prefix_node->type) &&
- prefix_node->type != ACPI_TYPE_ANY) {
- prefix_node = acpi_ns_get_parent_node (prefix_node);
+ while (!acpi_ns_opens_scope(prefix_node->type) &&
+ prefix_node->type != ACPI_TYPE_ANY) {
+ prefix_node = acpi_ns_get_parent_node(prefix_node);
}
}
@@ -366,13 +365,13 @@ acpi_ns_lookup (
/* A Null name_path is allowed and refers to the root */
num_segments = 0;
- this_node = acpi_gbl_root_node;
- path = "";
+ this_node = acpi_gbl_root_node;
+ path = "";
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Null Pathname (Zero segments), Flags=%X\n", flags));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Null Pathname (Zero segments), Flags=%X\n",
+ flags));
+ } else {
/*
* Name pointer is valid (and must be in internal name format)
*
@@ -396,15 +395,16 @@ acpi_ns_lookup (
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Path is absolute from root [%p]\n", this_node));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Path is absolute from root [%p]\n",
+ this_node));
+ } else {
/* Pathname is relative to current scope, start there */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching relative to prefix scope [%4.4s] (%p)\n",
- acpi_ut_get_node_name (prefix_node), prefix_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching relative to prefix scope [%4.4s] (%p)\n",
+ acpi_ut_get_node_name(prefix_node),
+ prefix_node));
/*
* Handle multiple Parent Prefixes (carat) by just getting
@@ -425,20 +425,20 @@ acpi_ns_lookup (
/* Backup to the parent node */
num_carats++;
- this_node = acpi_ns_get_parent_node (this_node);
+ this_node = acpi_ns_get_parent_node(this_node);
if (!this_node) {
/* Current scope has no parent scope */
- ACPI_REPORT_ERROR (
- ("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_REPORT_ERROR(("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
}
if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Search scope is [%4.4s], path has %d carat(s)\n",
- acpi_ut_get_node_name (this_node), num_carats));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Search scope is [%4.4s], path has %d carat(s)\n",
+ acpi_ut_get_node_name
+ (this_node), num_carats));
}
}
@@ -464,9 +464,9 @@ acpi_ns_lookup (
num_segments = 0;
type = this_node->type;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Prefix-only Pathname (Zero name segments), Flags=%X\n",
- flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Prefix-only Pathname (Zero name segments), Flags=%X\n",
+ flags));
break;
case AML_DUAL_NAME_PREFIX:
@@ -480,8 +480,9 @@ acpi_ns_lookup (
num_segments = 2;
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Dual Pathname (2 segments, Flags=%X)\n", flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Dual Pathname (2 segments, Flags=%X)\n",
+ flags));
break;
case AML_MULTI_NAME_PREFIX_OP:
@@ -493,12 +494,12 @@ acpi_ns_lookup (
/* Extract segment count, point to first name segment */
path++;
- num_segments = (u32) (u8) *path;
+ num_segments = (u32) (u8) * path;
path++;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Multi Pathname (%d Segments, Flags=%X) \n",
- num_segments, flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Multi Pathname (%d Segments, Flags=%X) \n",
+ num_segments, flags));
break;
default:
@@ -508,15 +509,15 @@ acpi_ns_lookup (
*/
num_segments = 1;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Simple Pathname (1 segment, Flags=%X)\n", flags));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Simple Pathname (1 segment, Flags=%X)\n",
+ flags));
break;
}
- ACPI_DEBUG_EXEC (acpi_ns_print_pathname (num_segments, path));
+ ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path));
}
-
/*
* Search namespace for each segment of the name. Loop through and
* verify (or add to the namespace) each name segment.
@@ -540,7 +541,7 @@ acpi_ns_lookup (
* requested it AND we have a single, non-fully-qualified name_seg
*/
if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
- (flags & ACPI_NS_SEARCH_PARENT)) {
+ (flags & ACPI_NS_SEARCH_PARENT)) {
local_flags |= ACPI_NS_SEARCH_PARENT;
}
@@ -553,24 +554,28 @@ acpi_ns_lookup (
/* Extract one ACPI name from the front of the pathname */
- ACPI_MOVE_32_TO_32 (&simple_name, path);
+ ACPI_MOVE_32_TO_32(&simple_name, path);
/* Try to find the single (4 character) ACPI name */
- status = acpi_ns_search_and_enter (simple_name, walk_state, current_node,
- interpreter_mode, this_search_type, local_flags, &this_node);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ns_search_and_enter(simple_name, walk_state,
+ current_node, interpreter_mode,
+ this_search_type, local_flags,
+ &this_node);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
/* Name not found in ACPI namespace */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] not found in scope [%4.4s] %p\n",
- (char *) &simple_name, (char *) &current_node->name,
- current_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] not found in scope [%4.4s] %p\n",
+ (char *)&simple_name,
+ (char *)&current_node->name,
+ current_node));
}
*return_node = this_node;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
@@ -586,19 +591,16 @@ acpi_ns_lookup (
*
* Then we have a type mismatch. Just warn and ignore it.
*/
- if ((num_segments == 0) &&
- (type_to_check_for != ACPI_TYPE_ANY) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
- (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
- (this_node->type != ACPI_TYPE_ANY) &&
- (this_node->type != type_to_check_for)) {
+ if ((num_segments == 0) &&
+ (type_to_check_for != ACPI_TYPE_ANY) &&
+ (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
+ (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
+ (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
+ (this_node->type != ACPI_TYPE_ANY) &&
+ (this_node->type != type_to_check_for)) {
/* Complain about a type mismatch */
- ACPI_REPORT_WARNING (
- ("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n",
- (char *) &simple_name, acpi_ut_get_type_name (this_node->type),
- acpi_ut_get_type_name (type_to_check_for)));
+ ACPI_REPORT_WARNING(("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n", (char *)&simple_name, acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(type_to_check_for)));
}
/*
@@ -624,15 +626,16 @@ acpi_ns_lookup (
* If entry is a type which opens a scope, push the new scope on the
* scope stack.
*/
- if (acpi_ns_opens_scope (type)) {
- status = acpi_ds_scope_stack_push (this_node, type, walk_state);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (acpi_ns_opens_scope(type)) {
+ status =
+ acpi_ds_scope_stack_push(this_node, type,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
*return_node = this_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 5653a19d7172..cc7a85f8cfe6 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -41,20 +41,14 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsalloc")
+ACPI_MODULE_NAME("nsalloc")
/* Local prototypes */
-
-static void
-acpi_ns_remove_reference (
- struct acpi_namespace_node *node);
-
+static void acpi_ns_remove_reference(struct acpi_namespace_node *node);
/*******************************************************************************
*
@@ -68,31 +62,26 @@ acpi_ns_remove_reference (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_create_node (
- u32 name)
+struct acpi_namespace_node *acpi_ns_create_node(u32 name)
{
- struct acpi_namespace_node *node;
-
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE ("ns_create_node");
+ ACPI_FUNCTION_TRACE("ns_create_node");
-
- node = ACPI_MEM_CALLOCATE (sizeof (struct acpi_namespace_node));
+ node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node));
if (!node) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
- node->name.integer = name;
+ node->name.integer = name;
node->reference_count = 1;
- ACPI_SET_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED);
+ ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
- return_PTR (node);
+ return_PTR(node);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_node
@@ -105,19 +94,15 @@ acpi_ns_create_node (
*
******************************************************************************/
-void
-acpi_ns_delete_node (
- struct acpi_namespace_node *node)
+void acpi_ns_delete_node(struct acpi_namespace_node *node)
{
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *prev_node;
- struct acpi_namespace_node *next_node;
-
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *prev_node;
+ struct acpi_namespace_node *next_node;
- ACPI_FUNCTION_TRACE_PTR ("ns_delete_node", node);
+ ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node);
-
- parent_node = acpi_ns_get_parent_node (node);
+ parent_node = acpi_ns_get_parent_node(node);
prev_node = NULL;
next_node = parent_node->child;
@@ -136,32 +121,29 @@ acpi_ns_delete_node (
if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
}
- }
- else {
+ } else {
/* Node is first child (has no previous peer) */
if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
/* No peers at all */
parent_node->child = NULL;
- }
- else { /* Link peer list to parent */
+ } else { /* Link peer list to parent */
parent_node->child = next_node->peer;
}
}
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
/*
* Detach an object if there is one then delete the node
*/
- acpi_ns_detach_object (node);
- ACPI_MEM_FREE (node);
+ acpi_ns_detach_object(node);
+ ACPI_MEM_FREE(node);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_install_node
@@ -176,30 +158,20 @@ acpi_ns_delete_node (
* DESCRIPTION: Initialize a new namespace node and install it amongst
* its peers.
*
- * Note: Current namespace lookup is linear search. However, the
- * nodes are linked in alphabetical order to 1) put all reserved
- * names (start with underscore) first, and to 2) make a readable
- * namespace dump.
+ * Note: Current namespace lookup is linear search. This appears
+ * to be sufficient as namespace searches consume only a small
+ * fraction of the execution time of the ACPI subsystem.
*
******************************************************************************/
-void
-acpi_ns_install_node (
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *parent_node, /* Parent */
- struct acpi_namespace_node *node, /* New Child*/
- acpi_object_type type)
+void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */
+ struct acpi_namespace_node *node, /* New Child */
+ acpi_object_type type)
{
- u16 owner_id = 0;
- struct acpi_namespace_node *child_node;
-#ifdef ACPI_ALPHABETIC_NAMESPACE
-
- struct acpi_namespace_node *previous_child_node;
-#endif
-
-
- ACPI_FUNCTION_TRACE ("ns_install_node");
+ acpi_owner_id owner_id = 0;
+ struct acpi_namespace_node *child_node;
+ ACPI_FUNCTION_TRACE("ns_install_node");
/*
* Get the owner ID from the Walk state
@@ -217,59 +189,7 @@ acpi_ns_install_node (
parent_node->child = node;
node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
- }
- else {
-#ifdef ACPI_ALPHABETIC_NAMESPACE
- /*
- * Walk the list whilst searching for the correct
- * alphabetic placement.
- */
- previous_child_node = NULL;
- while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node),
- acpi_ut_get_node_name (node)) < 0) {
- if (child_node->flags & ANOBJ_END_OF_PEER_LIST) {
- /* Last peer; Clear end-of-list flag */
-
- child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
-
- /* This node is the new peer to the child node */
-
- child_node->peer = node;
-
- /* This node is the new end-of-list */
-
- node->flags |= ANOBJ_END_OF_PEER_LIST;
- node->peer = parent_node;
- break;
- }
-
- /* Get next peer */
-
- previous_child_node = child_node;
- child_node = child_node->peer;
- }
-
- /* Did the node get inserted at the end-of-list? */
-
- if (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
- /*
- * Loop above terminated without reaching the end-of-list.
- * Insert the new node at the current location
- */
- if (previous_child_node) {
- /* Insert node alphabetically */
-
- node->peer = child_node;
- previous_child_node->peer = node;
- }
- else {
- /* Insert node alphabetically at start of list */
-
- node->peer = child_node;
- parent_node->child = node;
- }
- }
-#else
+ } else {
while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
child_node = child_node->peer;
}
@@ -279,9 +199,8 @@ acpi_ns_install_node (
/* Clear end-of-list flag */
child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
- node->flags |= ANOBJ_END_OF_PEER_LIST;
+ node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
-#endif
}
/* Init the new entry */
@@ -289,24 +208,25 @@ acpi_ns_install_node (
node->owner_id = owner_id;
node->type = (u8) type;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
- acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
- acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
- parent_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(node->type), node, owner_id,
+ acpi_ut_get_node_name(parent_node),
+ acpi_ut_get_type_name(parent_node->type),
+ parent_node));
/*
* Increment the reference count(s) of all parents up to
* the root!
*/
- while ((node = acpi_ns_get_parent_node (node)) != NULL) {
+ while ((node = acpi_ns_get_parent_node(node)) != NULL) {
node->reference_count++;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_children
@@ -320,18 +240,14 @@ acpi_ns_install_node (
*
******************************************************************************/
-void
-acpi_ns_delete_children (
- struct acpi_namespace_node *parent_node)
+void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
{
- struct acpi_namespace_node *child_node;
- struct acpi_namespace_node *next_node;
- struct acpi_namespace_node *node;
- u8 flags;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ns_delete_children", parent_node);
+ struct acpi_namespace_node *child_node;
+ struct acpi_namespace_node *next_node;
+ struct acpi_namespace_node *node;
+ u8 flags;
+ ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node);
if (!parent_node) {
return_VOID;
@@ -350,48 +266,48 @@ acpi_ns_delete_children (
do {
/* Get the things we need */
- next_node = child_node->peer;
- flags = child_node->flags;
+ next_node = child_node->peer;
+ flags = child_node->flags;
/* Grandchildren should have all been deleted already */
if (child_node->child) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
- parent_node, child_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Found a grandchild! P=%p C=%p\n",
+ parent_node, child_node));
}
/* Now we can free this child object */
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
+ ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
- child_node, acpi_gbl_current_node_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Object %p, Remaining %X\n", child_node,
+ acpi_gbl_current_node_count));
/*
* Detach an object if there is one, then free the child node
*/
- acpi_ns_detach_object (child_node);
+ acpi_ns_detach_object(child_node);
/*
* Decrement the reference count(s) of all parents up to
* the root! (counts were incremented when the node was created)
*/
node = child_node;
- while ((node = acpi_ns_get_parent_node (node)) != NULL) {
+ while ((node = acpi_ns_get_parent_node(node)) != NULL) {
node->reference_count--;
}
/* There should be only one reference remaining on this node */
if (child_node->reference_count != 1) {
- ACPI_REPORT_WARNING ((
- "Existing references (%d) on node being deleted (%p)\n",
- child_node->reference_count, child_node));
+ ACPI_REPORT_WARNING(("Existing references (%d) on node being deleted (%p)\n", child_node->reference_count, child_node));
}
/* Now we can delete the node */
- ACPI_MEM_FREE (child_node);
+ ACPI_MEM_FREE(child_node);
/* And move on to the next child in the list */
@@ -399,7 +315,6 @@ acpi_ns_delete_children (
} while (!(flags & ANOBJ_END_OF_PEER_LIST));
-
/* Clear the parent's child pointer */
parent_node->child = NULL;
@@ -407,7 +322,6 @@ acpi_ns_delete_children (
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_namespace_subtree
@@ -421,16 +335,12 @@ acpi_ns_delete_children (
*
******************************************************************************/
-void
-acpi_ns_delete_namespace_subtree (
- struct acpi_namespace_node *parent_node)
+void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
{
- struct acpi_namespace_node *child_node = NULL;
- u32 level = 1;
-
-
- ACPI_FUNCTION_TRACE ("ns_delete_namespace_subtree");
+ struct acpi_namespace_node *child_node = NULL;
+ u32 level = 1;
+ ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree");
if (!parent_node) {
return_VOID;
@@ -443,16 +353,17 @@ acpi_ns_delete_namespace_subtree (
while (level > 0) {
/* Get the next node in this scope (NULL if none) */
- child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node,
- child_node);
+ child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
+ child_node);
if (child_node) {
/* Found a child node - detach any attached object */
- acpi_ns_detach_object (child_node);
+ acpi_ns_detach_object(child_node);
/* Check if this node has any children */
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this node,
* visit the node
@@ -461,8 +372,7 @@ acpi_ns_delete_namespace_subtree (
parent_node = child_node;
child_node = NULL;
}
- }
- else {
+ } else {
/*
* No more children of this parent node.
* Move up to the grandparent.
@@ -473,7 +383,7 @@ acpi_ns_delete_namespace_subtree (
* Now delete all of the children of this parent
* all at the same time.
*/
- acpi_ns_delete_children (parent_node);
+ acpi_ns_delete_children(parent_node);
/* New "last child" is this parent node */
@@ -481,14 +391,13 @@ acpi_ns_delete_namespace_subtree (
/* Move up the tree to the grandparent */
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_remove_reference
@@ -504,16 +413,12 @@ acpi_ns_delete_namespace_subtree (
*
******************************************************************************/
-static void
-acpi_ns_remove_reference (
- struct acpi_namespace_node *node)
+static void acpi_ns_remove_reference(struct acpi_namespace_node *node)
{
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *this_node;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_namespace_node *parent_node;
+ struct acpi_namespace_node *this_node;
+ ACPI_FUNCTION_ENTRY();
/*
* Decrement the reference count(s) of this node and all
@@ -523,7 +428,7 @@ acpi_ns_remove_reference (
while (this_node) {
/* Prepare to move up to parent */
- parent_node = acpi_ns_get_parent_node (this_node);
+ parent_node = acpi_ns_get_parent_node(this_node);
/* Decrement the reference count on this node */
@@ -534,15 +439,14 @@ acpi_ns_remove_reference (
if (!this_node->reference_count) {
/* Delete all children and delete the node */
- acpi_ns_delete_children (this_node);
- acpi_ns_delete_node (this_node);
+ acpi_ns_delete_children(this_node);
+ acpi_ns_delete_node(this_node);
}
this_node = parent_node;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_delete_namespace_by_owner
@@ -557,23 +461,23 @@ acpi_ns_remove_reference (
*
******************************************************************************/
-void
-acpi_ns_delete_namespace_by_owner (
- u16 owner_id)
+void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
{
- struct acpi_namespace_node *child_node;
- struct acpi_namespace_node *deletion_node;
- u32 level;
- struct acpi_namespace_node *parent_node;
-
+ struct acpi_namespace_node *child_node;
+ struct acpi_namespace_node *deletion_node;
+ u32 level;
+ struct acpi_namespace_node *parent_node;
- ACPI_FUNCTION_TRACE_U32 ("ns_delete_namespace_by_owner", owner_id);
+ ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id);
+ if (owner_id == 0) {
+ return_VOID;
+ }
- parent_node = acpi_gbl_root_node;
- child_node = NULL;
+ parent_node = acpi_gbl_root_node;
+ child_node = NULL;
deletion_node = NULL;
- level = 1;
+ level = 1;
/*
* Traverse the tree of nodes until we bubble back up
@@ -584,10 +488,12 @@ acpi_ns_delete_namespace_by_owner (
* Get the next child of this parent node. When child_node is NULL,
* the first child of the parent is returned
*/
- child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
+ child_node =
+ acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
+ child_node);
if (deletion_node) {
- acpi_ns_remove_reference (deletion_node);
+ acpi_ns_remove_reference(deletion_node);
deletion_node = NULL;
}
@@ -595,12 +501,13 @@ acpi_ns_delete_namespace_by_owner (
if (child_node->owner_id == owner_id) {
/* Found a matching child node - detach any attached object */
- acpi_ns_detach_object (child_node);
+ acpi_ns_detach_object(child_node);
}
/* Check if this node has any children */
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this node,
* visit the node
@@ -608,12 +515,10 @@ acpi_ns_delete_namespace_by_owner (
level++;
parent_node = child_node;
child_node = NULL;
- }
- else if (child_node->owner_id == owner_id) {
+ } else if (child_node->owner_id == owner_id) {
deletion_node = child_node;
}
- }
- else {
+ } else {
/*
* No more children of this parent node.
* Move up to the grandparent.
@@ -631,62 +536,9 @@ acpi_ns_delete_namespace_by_owner (
/* Move up the tree to the grandparent */
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
return_VOID;
}
-
-
-#ifdef ACPI_ALPHABETIC_NAMESPACE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_compare_names
- *
- * PARAMETERS: Name1 - First name to compare
- * Name2 - Second name to compare
- *
- * RETURN: value from strncmp
- *
- * DESCRIPTION: Compare two ACPI names. Names that are prefixed with an
- * underscore are forced to be alphabetically first.
- *
- ******************************************************************************/
-
-int
-acpi_ns_compare_names (
- char *name1,
- char *name2)
-{
- char reversed_name1[ACPI_NAME_SIZE];
- char reversed_name2[ACPI_NAME_SIZE];
- u32 i;
- u32 j;
-
-
- /*
- * Replace all instances of "underscore" with a value that is smaller so
- * that all names that are prefixed with underscore(s) are alphabetically
- * first.
- *
- * Reverse the name bytewise so we can just do a 32-bit compare instead
- * of a strncmp.
- */
- for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--) {
- reversed_name1[j] = name1[i];
- if (name1[i] == '_') {
- reversed_name1[j] = '*';
- }
-
- reversed_name2[j] = name2[i];
- if (name2[i] == '_') {
- reversed_name2[j] = '*';
- }
- }
-
- return (*(int *) reversed_name1 - *(int *) reversed_name2);
-}
-#endif
-
-
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index 6c2aef0e0dd4..9faf1d5c86ed 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -41,31 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsdump")
+ACPI_MODULE_NAME("nsdump")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
-void
-acpi_ns_dump_root_devices (
- void);
+void acpi_ns_dump_root_devices(void);
static acpi_status
-acpi_ns_dump_one_device (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ns_dump_one_device(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
#endif
-
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*******************************************************************************
*
@@ -80,36 +71,38 @@ acpi_ns_dump_one_device (
*
******************************************************************************/
-void
-acpi_ns_print_pathname (
- u32 num_segments,
- char *pathname)
+void acpi_ns_print_pathname(u32 num_segments, char *pathname)
{
- ACPI_FUNCTION_NAME ("ns_print_pathname");
+ acpi_native_uint i;
+ ACPI_FUNCTION_NAME("ns_print_pathname");
- if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
+ if (!(acpi_dbg_level & ACPI_LV_NAMES)
+ || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
return;
}
/* Print the entire name */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "["));
while (num_segments) {
- acpi_os_printf ("%4.4s", pathname);
- pathname += ACPI_NAME_SIZE;
+ for (i = 0; i < 4; i++) {
+ ACPI_IS_PRINT(pathname[i]) ?
+ acpi_os_printf("%c", pathname[i]) :
+ acpi_os_printf("?");
+ }
+ pathname += ACPI_NAME_SIZE;
num_segments--;
if (num_segments) {
- acpi_os_printf (".");
+ acpi_os_printf(".");
}
}
- acpi_os_printf ("]\n");
+ acpi_os_printf("]\n");
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_pathname
@@ -127,15 +120,10 @@ acpi_ns_print_pathname (
******************************************************************************/
void
-acpi_ns_dump_pathname (
- acpi_handle handle,
- char *msg,
- u32 level,
- u32 component)
+acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
{
- ACPI_FUNCTION_TRACE ("ns_dump_pathname");
-
+ ACPI_FUNCTION_TRACE("ns_dump_pathname");
/* Do this only if the requested debug level and component are enabled */
@@ -145,12 +133,11 @@ acpi_ns_dump_pathname (
/* Convert handle to a full pathname and print it (with supplied message) */
- acpi_ns_print_node_pathname (handle, msg);
- acpi_os_printf ("\n");
+ acpi_ns_print_node_pathname(handle, msg);
+ acpi_os_printf("\n");
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_object
@@ -168,24 +155,19 @@ acpi_ns_dump_pathname (
******************************************************************************/
acpi_status
-acpi_ns_dump_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_dump_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- struct acpi_walk_info *info = (struct acpi_walk_info *) context;
- struct acpi_namespace_node *this_node;
- union acpi_operand_object *obj_desc = NULL;
- acpi_object_type obj_type;
- acpi_object_type type;
- u32 bytes_to_dump;
- u32 dbg_level;
- u32 i;
-
-
- ACPI_FUNCTION_NAME ("ns_dump_one_object");
+ struct acpi_walk_info *info = (struct acpi_walk_info *)context;
+ struct acpi_namespace_node *this_node;
+ union acpi_operand_object *obj_desc = NULL;
+ acpi_object_type obj_type;
+ acpi_object_type type;
+ u32 bytes_to_dump;
+ u32 dbg_level;
+ u32 i;
+ ACPI_FUNCTION_NAME("ns_dump_one_object");
/* Is output enabled? */
@@ -194,193 +176,215 @@ acpi_ns_dump_one_object (
}
if (!obj_handle) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
return (AE_OK);
}
- this_node = acpi_ns_map_handle_to_node (obj_handle);
+ this_node = acpi_ns_map_handle_to_node(obj_handle);
type = this_node->type;
/* Check if the owner matches */
- if ((info->owner_id != ACPI_UINT32_MAX) &&
- (info->owner_id != this_node->owner_id)) {
+ if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
+ (info->owner_id != this_node->owner_id)) {
return (AE_OK);
}
- /* Indent the object according to the level */
+ if (!(info->display_type & ACPI_DISPLAY_SHORT)) {
+ /* Indent the object according to the level */
- acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " ");
+ acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");
- /* Check the node type and name */
+ /* Check the node type and name */
- if (type > ACPI_TYPE_LOCAL_MAX) {
- ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type));
- }
+ if (type > ACPI_TYPE_LOCAL_MAX) {
+ ACPI_REPORT_WARNING(("Invalid ACPI Type %08X\n", type));
+ }
+
+ if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
+ ACPI_REPORT_WARNING(("Invalid ACPI Name %08X\n",
+ this_node->name.integer));
+ }
- if (!acpi_ut_valid_acpi_name (this_node->name.integer)) {
- ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n",
- this_node->name.integer));
+ acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
}
/*
* Now we can print out the pertinent information
*/
- acpi_os_printf ("%4.4s %-12s %p ",
- acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node);
+ acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node);
dbg_level = acpi_dbg_level;
acpi_dbg_level = 0;
- obj_desc = acpi_ns_get_attached_object (this_node);
+ obj_desc = acpi_ns_get_attached_object(this_node);
acpi_dbg_level = dbg_level;
- switch (info->display_type) {
+ switch (info->display_type & ACPI_DISPLAY_MASK) {
case ACPI_DISPLAY_SUMMARY:
if (!obj_desc) {
/* No attached object, we are done */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return (AE_OK);
}
switch (type) {
case ACPI_TYPE_PROCESSOR:
- acpi_os_printf ("ID %X Len %.4X Addr %p\n",
- obj_desc->processor.proc_id, obj_desc->processor.length,
- (char *) obj_desc->processor.address);
+ acpi_os_printf("ID %X Len %.4X Addr %p\n",
+ obj_desc->processor.proc_id,
+ obj_desc->processor.length,
+ (char *)obj_desc->processor.address);
break;
-
case ACPI_TYPE_DEVICE:
- acpi_os_printf ("Notify Object: %p\n", obj_desc);
+ acpi_os_printf("Notify Object: %p\n", obj_desc);
break;
-
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Args %X Len %.4X Aml %p\n",
- (u32) obj_desc->method.param_count,
- obj_desc->method.aml_length, obj_desc->method.aml_start);
+ acpi_os_printf("Args %X Len %.4X Aml %p\n",
+ (u32) obj_desc->method.param_count,
+ obj_desc->method.aml_length,
+ obj_desc->method.aml_start);
break;
-
case ACPI_TYPE_INTEGER:
- acpi_os_printf ("= %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf("= %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.
+ value));
break;
-
case ACPI_TYPE_PACKAGE:
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf ("Elements %.2X\n",
- obj_desc->package.count);
- }
- else {
- acpi_os_printf ("[Length not yet evaluated]\n");
+ acpi_os_printf("Elements %.2X\n",
+ obj_desc->package.count);
+ } else {
+ acpi_os_printf("[Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_BUFFER:
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf ("Len %.2X",
- obj_desc->buffer.length);
+ acpi_os_printf("Len %.2X",
+ obj_desc->buffer.length);
/* Dump some of the buffer */
if (obj_desc->buffer.length > 0) {
- acpi_os_printf (" =");
- for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
- acpi_os_printf (" %.2hX", obj_desc->buffer.pointer[i]);
+ acpi_os_printf(" =");
+ for (i = 0;
+ (i < obj_desc->buffer.length
+ && i < 12); i++) {
+ acpi_os_printf(" %.2hX",
+ obj_desc->buffer.
+ pointer[i]);
}
}
- acpi_os_printf ("\n");
- }
- else {
- acpi_os_printf ("[Length not yet evaluated]\n");
+ acpi_os_printf("\n");
+ } else {
+ acpi_os_printf("[Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_STRING:
- acpi_os_printf ("Len %.2X ", obj_desc->string.length);
- acpi_ut_print_string (obj_desc->string.pointer, 32);
- acpi_os_printf ("\n");
+ acpi_os_printf("Len %.2X ", obj_desc->string.length);
+ acpi_ut_print_string(obj_desc->string.pointer, 32);
+ acpi_os_printf("\n");
break;
-
case ACPI_TYPE_REGION:
- acpi_os_printf ("[%s]",
- acpi_ut_get_region_name (obj_desc->region.space_id));
+ acpi_os_printf("[%s]",
+ acpi_ut_get_region_name(obj_desc->region.
+ space_id));
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
- acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n",
- ACPI_FORMAT_UINT64 (obj_desc->region.address),
- obj_desc->region.length);
- }
- else {
- acpi_os_printf (" [Address/Length not yet evaluated]\n");
+ acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
+ ACPI_FORMAT_UINT64(obj_desc->
+ region.
+ address),
+ obj_desc->region.length);
+ } else {
+ acpi_os_printf
+ (" [Address/Length not yet evaluated]\n");
}
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
- acpi_os_printf ("[%s]\n",
- acpi_ps_get_opcode_name (obj_desc->reference.opcode));
+ acpi_os_printf("[%s]\n",
+ acpi_ps_get_opcode_name(obj_desc->
+ reference.
+ opcode));
break;
-
case ACPI_TYPE_BUFFER_FIELD:
if (obj_desc->buffer_field.buffer_obj &&
- obj_desc->buffer_field.buffer_obj->buffer.node) {
- acpi_os_printf ("Buf [%4.4s]",
- acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node));
+ obj_desc->buffer_field.buffer_obj->buffer.node) {
+ acpi_os_printf("Buf [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ buffer_field.
+ buffer_obj->
+ buffer.
+ node));
}
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
- acpi_os_printf ("Rgn [%4.4s]",
- acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node));
+ acpi_os_printf("Rgn [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ region_obj->region.
+ node));
break;
-
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]",
- acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node),
- acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node));
+ acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ common_field.
+ region_obj->region.
+ node),
+ acpi_ut_get_node_name(obj_desc->
+ bank_field.
+ bank_obj->
+ common_field.
+ node));
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]",
- acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node),
- acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node));
+ acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
+ acpi_ut_get_node_name(obj_desc->
+ index_field.
+ index_obj->
+ common_field.node),
+ acpi_ut_get_node_name(obj_desc->
+ index_field.
+ data_obj->
+ common_field.
+ node));
break;
-
case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
- acpi_os_printf ("Target %4.4s (%p)\n",
- acpi_ut_get_node_name (obj_desc), obj_desc);
+ acpi_os_printf("Target %4.4s (%p)\n",
+ acpi_ut_get_node_name(obj_desc),
+ obj_desc);
break;
default:
- acpi_os_printf ("Object %p\n", obj_desc);
+ acpi_os_printf("Object %p\n", obj_desc);
break;
}
@@ -392,11 +396,15 @@ acpi_ns_dump_one_object (
case ACPI_TYPE_LOCAL_BANK_FIELD:
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n",
- (obj_desc->common_field.base_byte_offset * 8)
- + obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.bit_length,
- obj_desc->common_field.access_byte_width);
+ acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
+ (obj_desc->common_field.
+ base_byte_offset * 8)
+ +
+ obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.
+ access_byte_width);
break;
default:
@@ -404,56 +412,55 @@ acpi_ns_dump_one_object (
}
break;
-
case ACPI_DISPLAY_OBJECTS:
- acpi_os_printf ("O:%p", obj_desc);
+ acpi_os_printf("O:%p", obj_desc);
if (!obj_desc) {
/* No attached object, we are done */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return (AE_OK);
}
- acpi_os_printf ("(R%d)", obj_desc->common.reference_count);
+ acpi_os_printf("(R%d)", obj_desc->common.reference_count);
switch (type) {
case ACPI_TYPE_METHOD:
/* Name is a Method and its AML offset/length are set */
- acpi_os_printf (" M:%p-%X\n", obj_desc->method.aml_start,
- obj_desc->method.aml_length);
+ acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
+ obj_desc->method.aml_length);
break;
case ACPI_TYPE_INTEGER:
- acpi_os_printf (" I:%8.8X8.8%X\n",
- ACPI_FORMAT_UINT64 (obj_desc->integer.value));
+ acpi_os_printf(" I:%8.8X8.8%X\n",
+ ACPI_FORMAT_UINT64(obj_desc->integer.
+ value));
break;
case ACPI_TYPE_STRING:
- acpi_os_printf (" S:%p-%X\n", obj_desc->string.pointer,
- obj_desc->string.length);
+ acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
+ obj_desc->string.length);
break;
case ACPI_TYPE_BUFFER:
- acpi_os_printf (" B:%p-%X\n", obj_desc->buffer.pointer,
- obj_desc->buffer.length);
+ acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
break;
default:
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
}
break;
-
default:
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
break;
}
@@ -463,61 +470,58 @@ acpi_ns_dump_one_object (
return (AE_OK);
}
-
/* If there is an attached object, display it */
- dbg_level = acpi_dbg_level;
+ dbg_level = acpi_dbg_level;
acpi_dbg_level = 0;
- obj_desc = acpi_ns_get_attached_object (this_node);
+ obj_desc = acpi_ns_get_attached_object(this_node);
acpi_dbg_level = dbg_level;
/* Dump attached objects */
while (obj_desc) {
obj_type = ACPI_TYPE_INVALID;
- acpi_os_printf (" Attached Object %p: ", obj_desc);
+ acpi_os_printf("Attached Object %p: ", obj_desc);
/* Decode the type of attached object and dump the contents */
- switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
case ACPI_DESC_TYPE_NAMED:
- acpi_os_printf ("(Ptr to Node)\n");
- bytes_to_dump = sizeof (struct acpi_namespace_node);
+ acpi_os_printf("(Ptr to Node)\n");
+ bytes_to_dump = sizeof(struct acpi_namespace_node);
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
break;
-
case ACPI_DESC_TYPE_OPERAND:
- obj_type = ACPI_GET_OBJECT_TYPE (obj_desc);
+ obj_type = ACPI_GET_OBJECT_TYPE(obj_desc);
if (obj_type > ACPI_TYPE_LOCAL_MAX) {
- acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
- obj_type);
+ acpi_os_printf
+ ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
+ obj_type);
bytes_to_dump = 32;
+ } else {
+ acpi_os_printf
+ ("(Ptr to ACPI Object type %X [%s])\n",
+ obj_type, acpi_ut_get_type_name(obj_type));
+ bytes_to_dump =
+ sizeof(union acpi_operand_object);
}
- else {
- acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n",
- acpi_ut_get_type_name (obj_type), obj_type);
- bytes_to_dump = sizeof (union acpi_operand_object);
- }
- break;
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
+ break;
default:
- acpi_os_printf (
- "(String or Buffer ptr - not an object descriptor) [%s]\n",
- acpi_ut_get_descriptor_name (obj_desc));
- bytes_to_dump = 16;
break;
}
- ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump);
-
/* If value is NOT an internal object, we are done */
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
+ ACPI_DESC_TYPE_OPERAND) {
goto cleanup;
}
@@ -525,51 +529,56 @@ acpi_ns_dump_one_object (
* Valid object, get the pointer to next level, if any
*/
switch (obj_type) {
- case ACPI_TYPE_STRING:
- obj_desc = (void *) obj_desc->string.pointer;
- break;
-
case ACPI_TYPE_BUFFER:
- obj_desc = (void *) obj_desc->buffer.pointer;
- break;
+ case ACPI_TYPE_STRING:
+ /*
+ * NOTE: takes advantage of common fields between string/buffer
+ */
+ bytes_to_dump = obj_desc->string.length;
+ obj_desc = (void *)obj_desc->string.pointer;
+ acpi_os_printf("(Buffer/String pointer %p length %X)\n",
+ obj_desc, bytes_to_dump);
+ ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
+ goto cleanup;
case ACPI_TYPE_BUFFER_FIELD:
- obj_desc = (union acpi_operand_object *) obj_desc->buffer_field.buffer_obj;
+ obj_desc =
+ (union acpi_operand_object *)obj_desc->buffer_field.
+ buffer_obj;
break;
case ACPI_TYPE_PACKAGE:
- obj_desc = (void *) obj_desc->package.elements;
+ obj_desc = (void *)obj_desc->package.elements;
break;
case ACPI_TYPE_METHOD:
- obj_desc = (void *) obj_desc->method.aml_start;
+ obj_desc = (void *)obj_desc->method.aml_start;
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
- obj_desc = (void *) obj_desc->field.region_obj;
+ obj_desc = (void *)obj_desc->field.region_obj;
break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- obj_desc = (void *) obj_desc->bank_field.region_obj;
+ obj_desc = (void *)obj_desc->bank_field.region_obj;
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- obj_desc = (void *) obj_desc->index_field.index_obj;
+ obj_desc = (void *)obj_desc->index_field.index_obj;
break;
default:
goto cleanup;
}
- obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
+ obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
}
-cleanup:
- acpi_os_printf ("\n");
+ cleanup:
+ acpi_os_printf("\n");
return (AE_OK);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -591,29 +600,25 @@ cleanup:
******************************************************************************/
void
-acpi_ns_dump_objects (
- acpi_object_type type,
- u8 display_type,
- u32 max_depth,
- u32 owner_id,
- acpi_handle start_handle)
+acpi_ns_dump_objects(acpi_object_type type,
+ u8 display_type,
+ u32 max_depth,
+ acpi_owner_id owner_id, acpi_handle start_handle)
{
- struct acpi_walk_info info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_walk_info info;
+ ACPI_FUNCTION_ENTRY();
info.debug_level = ACPI_LV_TABLES;
info.owner_id = owner_id;
info.display_type = display_type;
- (void) acpi_ns_walk_namespace (type, start_handle, max_depth,
- ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object,
- (void *) &info, NULL);
+ (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+ ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ns_dump_one_object, (void *)&info,
+ NULL);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -628,26 +633,20 @@ acpi_ns_dump_objects (
*
******************************************************************************/
-void
-acpi_ns_dump_entry (
- acpi_handle handle,
- u32 debug_level)
+void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
{
- struct acpi_walk_info info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_walk_info info;
+ ACPI_FUNCTION_ENTRY();
info.debug_level = debug_level;
- info.owner_id = ACPI_UINT32_MAX;
+ info.owner_id = ACPI_OWNER_ID_MAX;
info.display_type = ACPI_DISPLAY_SUMMARY;
- (void) acpi_ns_dump_one_object (handle, 1, &info, NULL);
+ (void)acpi_ns_dump_one_object(handle, 1, &info, NULL);
}
-
-#ifdef _ACPI_ASL_COMPILER
+#ifdef ACPI_ASL_COMPILER
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_tables
@@ -663,23 +662,19 @@ acpi_ns_dump_entry (
*
******************************************************************************/
-void
-acpi_ns_dump_tables (
- acpi_handle search_base,
- u32 max_depth)
+void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth)
{
- acpi_handle search_handle = search_base;
-
-
- ACPI_FUNCTION_TRACE ("ns_dump_tables");
+ acpi_handle search_handle = search_base;
+ ACPI_FUNCTION_TRACE("ns_dump_tables");
if (!acpi_gbl_root_node) {
/*
* If the name space has not been initialized,
* there is nothing to dump.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "namespace not initialized!\n"));
return_VOID;
}
@@ -687,12 +682,12 @@ acpi_ns_dump_tables (
/* Entire namespace */
search_handle = acpi_gbl_root_node;
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "\\\n"));
}
- acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
- ACPI_UINT32_MAX, search_handle);
+ acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
+ ACPI_OWNER_ID_MAX, search_handle);
return_VOID;
}
-#endif /* _ACPI_ASL_COMPILER */
-#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */
+#endif /* _ACPI_ASL_COMPILER */
+#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index 27c4f7cd2a43..55de883943d6 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -41,20 +41,15 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
/* TBD: This entire module is apparently obsolete and should be removed */
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsdumpdv")
-
+ACPI_MODULE_NAME("nsdumpdv")
#ifdef ACPI_OBSOLETE_FUNCTIONS
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-
#include <acpi/acnamesp.h>
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_device
@@ -70,44 +65,39 @@
* This procedure is a user_function called by acpi_ns_walk_namespace.
*
******************************************************************************/
-
static acpi_status
-acpi_ns_dump_one_device (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_dump_one_device(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- struct acpi_buffer buffer;
- struct acpi_device_info *info;
- acpi_status status;
- u32 i;
-
+ struct acpi_buffer buffer;
+ struct acpi_device_info *info;
+ acpi_status status;
+ u32 i;
- ACPI_FUNCTION_NAME ("ns_dump_one_device");
+ ACPI_FUNCTION_NAME("ns_dump_one_device");
-
- status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
+ status =
+ acpi_ns_dump_one_object(obj_handle, level, context, return_value);
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_get_object_info (obj_handle, &buffer);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_get_object_info(obj_handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
info = buffer.pointer;
for (i = 0; i < level; i++) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " "));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES,
- " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
- info->hardware_id.value, ACPI_FORMAT_UINT64 (info->address),
- info->current_status));
- ACPI_MEM_FREE (info);
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
+ " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
+ info->hardware_id.value,
+ ACPI_FORMAT_UINT64(info->address),
+ info->current_status));
+ ACPI_MEM_FREE(info);
}
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_root_devices
@@ -120,16 +110,12 @@ acpi_ns_dump_one_device (
*
******************************************************************************/
-void
-acpi_ns_dump_root_devices (
- void)
+void acpi_ns_dump_root_devices(void)
{
- acpi_handle sys_bus_handle;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("ns_dump_root_devices");
+ acpi_handle sys_bus_handle;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ns_dump_root_devices");
/* Only dump the table if tracing is enabled */
@@ -138,19 +124,17 @@ acpi_ns_dump_root_devices (
}
status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
return;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Display of all devices in the namespace:\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Display of all devices in the namespace:\n"));
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
- ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ns_dump_one_device, NULL, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ acpi_ns_dump_one_device, NULL, NULL);
}
#endif
#endif
-
-
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 1ae89a1c8826..0191c7d92824 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -42,26 +42,19 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nseval")
+ACPI_MODULE_NAME("nseval")
/* Local prototypes */
-
static acpi_status
-acpi_ns_execute_control_method (
- struct acpi_parameter_info *info);
-
-static acpi_status
-acpi_ns_get_object_value (
- struct acpi_parameter_info *info);
+acpi_ns_execute_control_method(struct acpi_parameter_info *info);
+static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info);
/*******************************************************************************
*
@@ -85,48 +78,44 @@ acpi_ns_get_object_value (
******************************************************************************/
acpi_status
-acpi_ns_evaluate_relative (
- char *pathname,
- struct acpi_parameter_info *info)
+acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info)
{
- acpi_status status;
- struct acpi_namespace_node *node = NULL;
- union acpi_generic_state *scope_info;
- char *internal_path = NULL;
-
-
- ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
+ acpi_status status;
+ struct acpi_namespace_node *node = NULL;
+ union acpi_generic_state *scope_info;
+ char *internal_path = NULL;
+ ACPI_FUNCTION_TRACE("ns_evaluate_relative");
/*
* Must have a valid object handle
*/
if (!info || !info->node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Build an internal name string for the method */
- status = acpi_ns_internalize_name (pathname, &internal_path);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- scope_info = acpi_ut_create_generic_state ();
+ scope_info = acpi_ut_create_generic_state();
if (!scope_info) {
goto cleanup1;
}
/* Get the prefix handle and Node */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- info->node = acpi_ns_map_handle_to_node (info->node);
+ info->node = acpi_ns_map_handle_to_node(info->node);
if (!info->node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
status = AE_BAD_PARAMETER;
goto cleanup;
}
@@ -134,39 +123,38 @@ acpi_ns_evaluate_relative (
/* Lookup the name in the namespace */
scope_info->scope.node = info->node;
- status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
- &node);
+ status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
+ &node);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
- pathname, acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
+ pathname, acpi_format_exception(status)));
goto cleanup;
}
/*
* Now that we have a handle to the object, we can attempt to evaluate it.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
- pathname, node, acpi_ns_get_attached_object (node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
+ pathname, node, acpi_ns_get_attached_object(node)));
info->node = node;
- status = acpi_ns_evaluate_by_handle (info);
+ status = acpi_ns_evaluate_by_handle(info);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
- pathname));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "*** Completed eval of object %s ***\n", pathname));
-cleanup:
- acpi_ut_delete_generic_state (scope_info);
+ cleanup:
+ acpi_ut_delete_generic_state(scope_info);
-cleanup1:
- ACPI_MEM_FREE (internal_path);
- return_ACPI_STATUS (status);
+ cleanup1:
+ ACPI_MEM_FREE(internal_path);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate_by_name
@@ -189,68 +177,63 @@ cleanup1:
******************************************************************************/
acpi_status
-acpi_ns_evaluate_by_name (
- char *pathname,
- struct acpi_parameter_info *info)
+acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
{
- acpi_status status;
- char *internal_path = NULL;
-
-
- ACPI_FUNCTION_TRACE ("ns_evaluate_by_name");
+ acpi_status status;
+ char *internal_path = NULL;
+ ACPI_FUNCTION_TRACE("ns_evaluate_by_name");
/* Build an internal name string for the method */
- status = acpi_ns_internalize_name (pathname, &internal_path);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Lookup the name in the namespace */
- status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
- &info->node);
+ status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
+ &info->node);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Object at [%s] was not found, status=%.4X\n",
- pathname, status));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Object at [%s] was not found, status=%.4X\n",
+ pathname, status));
goto cleanup;
}
/*
* Now that we have a handle to the object, we can attempt to evaluate it.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
- pathname, info->node, acpi_ns_get_attached_object (info->node)));
-
- status = acpi_ns_evaluate_by_handle (info);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
+ pathname, info->node,
+ acpi_ns_get_attached_object(info->node)));
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
- pathname));
+ status = acpi_ns_evaluate_by_handle(info);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "*** Completed eval of object %s ***\n", pathname));
-cleanup:
+ cleanup:
/* Cleanup */
if (internal_path) {
- ACPI_MEM_FREE (internal_path);
+ ACPI_MEM_FREE(internal_path);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate_by_handle
@@ -275,26 +258,22 @@ cleanup:
*
******************************************************************************/
-acpi_status
-acpi_ns_evaluate_by_handle (
- struct acpi_parameter_info *info)
+acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_evaluate_by_handle");
/* Check if namespace has been initialized */
if (!acpi_gbl_root_node) {
- return_ACPI_STATUS (AE_NO_NAMESPACE);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
/* Parameter Validation */
if (!info) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Initialize the return value to an invalid object */
@@ -303,23 +282,25 @@ acpi_ns_evaluate_by_handle (
/* Get the prefix handle and Node */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- info->node = acpi_ns_map_handle_to_node (info->node);
+ info->node = acpi_ns_map_handle_to_node(info->node);
if (!info->node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* For a method alias, we must grab the actual method node so that proper
* scoping context will be established before execution.
*/
- if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
+ if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ info->node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ info->node->object);
}
/*
@@ -329,17 +310,16 @@ acpi_ns_evaluate_by_handle (
*
* In both cases, the namespace is unlocked by the acpi_ns* procedure
*/
- if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
+ if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) {
/*
* Case 1) We have an actual control method to execute
*/
- status = acpi_ns_execute_control_method (info);
- }
- else {
+ status = acpi_ns_execute_control_method(info);
+ } else {
/*
* Case 2) Object is NOT a method, just return its current value
*/
- status = acpi_ns_get_object_value (info);
+ status = acpi_ns_get_object_value(info);
}
/*
@@ -355,16 +335,16 @@ acpi_ns_evaluate_by_handle (
* Namespace was unlocked by the handling acpi_ns* function, so we
* just return
*/
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_execute_control_method
*
* PARAMETERS: Info - Method info block, contains:
* Node - Method Node to execute
+ * obj_desc - Method object
* Parameters - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
* NULL if no parameters are being passed.
@@ -383,31 +363,29 @@ acpi_ns_evaluate_by_handle (
******************************************************************************/
static acpi_status
-acpi_ns_execute_control_method (
- struct acpi_parameter_info *info)
+acpi_ns_execute_control_method(struct acpi_parameter_info *info)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_execute_control_method");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_execute_control_method");
/* Verify that there is a method associated with this object */
- obj_desc = acpi_ns_get_attached_object (info->node);
- if (!obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
+ info->obj_desc = acpi_ns_get_attached_object(info->node);
+ if (!info->obj_desc) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No attached method object\n"));
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
- ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
- ACPI_LV_INFO, _COMPONENT);
+ ACPI_DUMP_PATHNAME(info->node, "Execute Method:",
+ ACPI_LV_INFO, _COMPONENT);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
- obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
+ info->obj_desc->method.aml_start + 1,
+ info->obj_desc->method.aml_length - 1));
/*
* Unlock the namespace before execution. This allows namespace access
@@ -416,27 +394,26 @@ acpi_ns_execute_control_method (
* interpreter locks to ensure that no thread is using the portion of the
* namespace that is being deleted.
*/
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Execute the method via the interpreter. The interpreter is locked
* here before calling into the AML parser
*/
- status = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_psx_execute (info);
- acpi_ex_exit_interpreter ();
+ status = acpi_ps_execute_method(info);
+ acpi_ex_exit_interpreter();
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_object_value
@@ -454,16 +431,12 @@ acpi_ns_execute_control_method (
*
******************************************************************************/
-static acpi_status
-acpi_ns_get_object_value (
- struct acpi_parameter_info *info)
+static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info)
{
- acpi_status status = AE_OK;
- struct acpi_namespace_node *resolved_node = info->node;
-
-
- ACPI_FUNCTION_TRACE ("ns_get_object_value");
+ acpi_status status = AE_OK;
+ struct acpi_namespace_node *resolved_node = info->node;
+ ACPI_FUNCTION_TRACE("ns_get_object_value");
/*
* Objects require additional resolution steps (e.g., the Node may be a
@@ -486,32 +459,33 @@ acpi_ns_get_object_value (
*
* We must release the namespace lock before entering the intepreter.
*/
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ex_enter_interpreter ();
- if (ACPI_SUCCESS (status)) {
- status = acpi_ex_resolve_node_to_value (&resolved_node, NULL);
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
/*
* If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
* in resolved_node.
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
status = AE_CTRL_RETURN_VALUE;
info->return_object = ACPI_CAST_PTR
- (union acpi_operand_object, resolved_node);
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
- info->return_object,
- acpi_ut_get_object_type_name (info->return_object)));
+ (union acpi_operand_object, resolved_node);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Returning object %p [%s]\n",
+ info->return_object,
+ acpi_ut_get_object_type_name(info->
+ return_object)));
}
}
/* Namespace is unlocked */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 362802ae29a2..0a08d2f04a06 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -41,31 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsinit")
+ACPI_MODULE_NAME("nsinit")
/* Local prototypes */
-
static acpi_status
-acpi_ns_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value);
+acpi_ns_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
static acpi_status
-acpi_ns_init_one_device (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value);
-
+acpi_ns_init_one_device(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
/*******************************************************************************
*
@@ -80,52 +71,48 @@ acpi_ns_init_one_device (
*
******************************************************************************/
-acpi_status
-acpi_ns_initialize_objects (
- void)
+acpi_status acpi_ns_initialize_objects(void)
{
- acpi_status status;
- struct acpi_init_walk_info info;
-
+ acpi_status status;
+ struct acpi_init_walk_info info;
- ACPI_FUNCTION_TRACE ("ns_initialize_objects");
+ ACPI_FUNCTION_TRACE("ns_initialize_objects");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "**** Starting initialization of namespace objects ****\n"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Completing Region/Field/Buffer/Package initialization:"));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "**** Starting initialization of namespace objects ****\n"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "Completing Region/Field/Buffer/Package initialization:"));
/* Set all init info to zero */
- ACPI_MEMSET (&info, 0, sizeof (struct acpi_init_walk_info));
+ ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info));
/* Walk entire namespace from the supplied root */
- status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, acpi_ns_init_one_object,
- &info, NULL);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception (status)));
+ status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_ns_init_one_object,
+ &info, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
- info.op_region_init, info.op_region_count,
- info.field_init, info.field_count,
- info.buffer_init, info.buffer_count,
- info.package_init, info.package_count, info.object_count));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
+ info.op_region_init, info.op_region_count,
+ info.field_init, info.field_count,
+ info.buffer_init, info.buffer_count,
+ info.package_init, info.package_count,
+ info.object_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Control Methods found\n", info.method_count));
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%hd Op Regions found\n", info.op_region_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Control Methods found\n", info.method_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+ "%hd Op Regions found\n", info.op_region_count));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_initialize_devices
@@ -142,16 +129,12 @@ acpi_ns_initialize_objects (
*
******************************************************************************/
-acpi_status
-acpi_ns_initialize_devices (
- void)
+acpi_status acpi_ns_initialize_devices(void)
{
- acpi_status status;
- struct acpi_device_walk_info info;
-
-
- ACPI_FUNCTION_TRACE ("ns_initialize_devices");
+ acpi_status status;
+ struct acpi_device_walk_info info;
+ ACPI_FUNCTION_TRACE("ns_initialize_devices");
/* Init counters */
@@ -159,34 +142,34 @@ acpi_ns_initialize_devices (
info.num_STA = 0;
info.num_INI = 0;
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Executing all Device _STA and_INI methods:"));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "Executing all Device _STA and_INI methods:"));
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Walk namespace for all objects */
- status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, TRUE,
+ acpi_ns_init_one_device, &info, NULL);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
- info.device_count, info.num_STA, info.num_INI));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
+ info.device_count, info.num_STA, info.num_INI));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_init_one_object
@@ -208,28 +191,25 @@ acpi_ns_initialize_devices (
******************************************************************************/
static acpi_status
-acpi_ns_init_one_object (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+acpi_ns_init_one_object(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- acpi_object_type type;
- acpi_status status;
- struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
- struct acpi_namespace_node *node = (struct acpi_namespace_node *) obj_handle;
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_NAME ("ns_init_one_object");
+ acpi_object_type type;
+ acpi_status status;
+ struct acpi_init_walk_info *info =
+ (struct acpi_init_walk_info *)context;
+ struct acpi_namespace_node *node =
+ (struct acpi_namespace_node *)obj_handle;
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_NAME("ns_init_one_object");
info->object_count++;
/* And even then, we are only interested in a few object types */
- type = acpi_ns_get_type (obj_handle);
- obj_desc = acpi_ns_get_attached_object (node);
+ type = acpi_ns_get_type(obj_handle);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return (AE_OK);
}
@@ -269,8 +249,8 @@ acpi_ns_init_one_object (
/*
* Must lock the interpreter before executing AML code
*/
- status = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status)) {
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -282,25 +262,25 @@ acpi_ns_init_one_object (
case ACPI_TYPE_REGION:
info->op_region_init++;
- status = acpi_ds_get_region_arguments (obj_desc);
+ status = acpi_ds_get_region_arguments(obj_desc);
break;
case ACPI_TYPE_BUFFER_FIELD:
info->field_init++;
- status = acpi_ds_get_buffer_field_arguments (obj_desc);
+ status = acpi_ds_get_buffer_field_arguments(obj_desc);
break;
case ACPI_TYPE_BUFFER:
info->buffer_init++;
- status = acpi_ds_get_buffer_arguments (obj_desc);
+ status = acpi_ds_get_buffer_arguments(obj_desc);
break;
case ACPI_TYPE_PACKAGE:
info->package_init++;
- status = acpi_ds_get_package_arguments (obj_desc);
+ status = acpi_ds_get_package_arguments(obj_desc);
break;
default:
@@ -308,12 +288,13 @@ acpi_ns_init_one_object (
break;
}
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not execute arguments for [%4.4s] (%s), %s\n",
- acpi_ut_get_node_name (node), acpi_ut_get_type_name (type),
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not execute arguments for [%4.4s] (%s), %s\n",
+ acpi_ut_get_node_name(node),
+ acpi_ut_get_type_name(type),
+ acpi_format_exception(status)));
}
/*
@@ -321,18 +302,17 @@ acpi_ns_init_one_object (
* pathname
*/
if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
/*
* We ignore errors from above, and always return OK, since we don't want
* to abort the walk on any single error.
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_init_one_device
@@ -348,41 +328,37 @@ acpi_ns_init_one_object (
******************************************************************************/
static acpi_status
-acpi_ns_init_one_device (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value)
+acpi_ns_init_one_device(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
{
- struct acpi_device_walk_info *info = (struct acpi_device_walk_info *) context;
- struct acpi_parameter_info pinfo;
- u32 flags;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_init_one_device");
+ struct acpi_device_walk_info *info =
+ (struct acpi_device_walk_info *)context;
+ struct acpi_parameter_info pinfo;
+ u32 flags;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_init_one_device");
pinfo.parameters = NULL;
pinfo.parameter_type = ACPI_PARAM_ARGS;
- pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
+ pinfo.node = acpi_ns_map_handle_to_node(obj_handle);
if (!pinfo.node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We will run _STA/_INI on Devices, Processors and thermal_zones only
*/
- if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
- (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
- (pinfo.node->type != ACPI_TYPE_THERMAL)) {
- return_ACPI_STATUS (AE_OK);
+ if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
+ (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
+ (pinfo.node->type != ACPI_TYPE_THERMAL)) {
+ return_ACPI_STATUS(AE_OK);
}
if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
- (!(acpi_dbg_level & ACPI_LV_INFO))) {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ (!(acpi_dbg_level & ACPI_LV_INFO))) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
}
info->device_count++;
@@ -390,20 +366,20 @@ acpi_ns_init_one_device (
/*
* Run _STA to determine if we can run _INI on the device.
*/
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD,
- pinfo.node, METHOD_NAME__STA));
- status = acpi_ut_execute_STA (pinfo.node, &flags);
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
+ pinfo.node,
+ METHOD_NAME__STA));
+ status = acpi_ut_execute_STA(pinfo.node, &flags);
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
if (pinfo.node->type == ACPI_TYPE_DEVICE) {
/* Ignore error and move on to next device */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* _STA is not required for Processor or thermal_zone objects */
- }
- else {
+ } else {
info->num_STA++;
if (!(flags & 0x01)) {
@@ -416,32 +392,34 @@ acpi_ns_init_one_device (
/*
* The device is present. Run _INI.
*/
- ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD,
- pinfo.node, METHOD_NAME__INI));
- status = acpi_ns_evaluate_relative (METHOD_NAME__INI, &pinfo);
- if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
+ pinfo.node,
+ METHOD_NAME__INI));
+ status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
+ if (ACPI_FAILURE(status)) {
/* No _INI (AE_NOT_FOUND) means device requires no initialization */
if (status != AE_NOT_FOUND) {
/* Ignore error and move on to next device */
#ifdef ACPI_DEBUG_OUTPUT
- char *scope_name = acpi_ns_get_external_pathname (pinfo.node);
+ char *scope_name =
+ acpi_ns_get_external_pathname(pinfo.node);
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
- scope_name, acpi_format_exception (status)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n",
+ scope_name,
+ acpi_format_exception(status)));
- ACPI_MEM_FREE (scope_name);
+ ACPI_MEM_FREE(scope_name);
#endif
}
status = AE_OK;
- }
- else {
+ } else {
/* Delete any return object (especially if implicit_return is enabled) */
if (pinfo.return_object) {
- acpi_ut_remove_reference (pinfo.return_object);
+ acpi_ut_remove_reference(pinfo.return_object);
}
/* Count of successful INIs */
@@ -452,8 +430,9 @@ acpi_ns_init_one_device (
if (acpi_gbl_init_handler) {
/* External initialization handler is present, call it */
- status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
+ status =
+ acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 34e497016601..c28849de465a 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -41,32 +41,22 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsload")
+ACPI_MODULE_NAME("nsload")
/* Local prototypes */
-
-static acpi_status
-acpi_ns_load_table_by_type (
- acpi_table_type table_type);
+static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type);
#ifdef ACPI_FUTURE_IMPLEMENTATION
-acpi_status
-acpi_ns_unload_namespace (
- acpi_handle handle);
+acpi_status acpi_ns_unload_namespace(acpi_handle handle);
-static acpi_status
-acpi_ns_delete_subtree (
- acpi_handle start_handle);
+static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
#endif
-
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
@@ -82,40 +72,39 @@ acpi_ns_delete_subtree (
******************************************************************************/
acpi_status
-acpi_ns_load_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *node)
+acpi_ns_load_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *node)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_load_table");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_load_table");
/* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
- if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) {
+ if (!
+ (acpi_gbl_table_data[table_desc->type].
+ flags & ACPI_TABLE_EXECUTABLE)) {
/* Just ignore this table */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Check validity of the AML start and length */
if (!table_desc->aml_start) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null AML pointer\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
- table_desc->aml_start));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AML block at %p\n",
+ table_desc->aml_start));
/* Ignore table if there is no AML contained within */
if (!table_desc->aml_length) {
- ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
- table_desc->pointer->signature));
- return_ACPI_STATUS (AE_OK);
+ ACPI_REPORT_WARNING(("Zero-length AML block in table [%4.4s]\n",
+ table_desc->pointer->signature));
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -127,19 +116,19 @@ acpi_ns_load_table (
* to another control method, we can't continue parsing
* because we don't know how many arguments to parse next!
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Loading table into namespace ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Loading table into namespace ****\n"));
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ns_parse_table (table_desc, node->child);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ns_parse_table(table_desc, node->child);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -148,18 +137,17 @@ acpi_ns_load_table (
* just-in-time parsing, we delete the control method
* parse trees.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Begin Table Method Parsing and Object Initialization ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Begin Table Method Parsing and Object Initialization ****\n"));
- status = acpi_ds_initialize_objects (table_desc, node);
+ status = acpi_ds_initialize_objects(table_desc, node);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "**** Completed Table Method Parsing and Object Initialization ****\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "**** Completed Table Method Parsing and Object Initialization ****\n"));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_load_table_by_type
@@ -174,21 +162,17 @@ acpi_ns_load_table (
*
******************************************************************************/
-static acpi_status
-acpi_ns_load_table_by_type (
- acpi_table_type table_type)
+static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
{
- u32 i;
- acpi_status status;
- struct acpi_table_desc *table_desc;
-
+ u32 i;
+ acpi_status status;
+ struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_TRACE ("ns_load_table_by_type");
+ ACPI_FUNCTION_TRACE("ns_load_table_by_type");
-
- status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -198,7 +182,7 @@ acpi_ns_load_table_by_type (
switch (table_type) {
case ACPI_TABLE_DSDT:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n"));
table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
@@ -210,57 +194,33 @@ acpi_ns_load_table_by_type (
/* Now load the single DSDT */
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_load_table(table_desc, acpi_gbl_root_node);
+ if (ACPI_SUCCESS(status)) {
table_desc->loaded_into_namespace = TRUE;
}
break;
-
case ACPI_TABLE_SSDT:
+ case ACPI_TABLE_PSDT:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
- acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Namespace load: %d SSDT or PSDTs\n",
+ acpi_gbl_table_lists[table_type].count));
/*
- * Traverse list of SSDT tables
+ * Traverse list of SSDT or PSDT tables
*/
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
- for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
+ table_desc = acpi_gbl_table_lists[table_type].next;
+ for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) {
/*
- * Only attempt to load table if it is not
+ * Only attempt to load table into namespace if it is not
* already loaded!
*/
if (!table_desc->loaded_into_namespace) {
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_FAILURE (status)) {
- break;
- }
-
- table_desc->loaded_into_namespace = TRUE;
- }
-
- table_desc = table_desc->next;
- }
- break;
-
-
- case ACPI_TABLE_PSDT:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
- acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
-
- /*
- * Traverse list of PSDT tables
- */
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
-
- for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
- /* Only attempt to load table if it is not already loaded! */
-
- if (!table_desc->loaded_into_namespace) {
- status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ns_load_table(table_desc,
+ acpi_gbl_root_node);
+ if (ACPI_FAILURE(status)) {
break;
}
@@ -271,19 +231,16 @@ acpi_ns_load_table_by_type (
}
break;
-
default:
status = AE_SUPPORT;
break;
}
-
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_load_namespace
@@ -297,45 +254,40 @@ unlock_and_exit:
*
******************************************************************************/
-acpi_status
-acpi_ns_load_namespace (
- void)
+acpi_status acpi_ns_load_namespace(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_load_name_space");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_load_name_space");
/* There must be at least a DSDT installed */
if (acpi_gbl_DSDT == NULL) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "DSDT is not in memory\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* Load the namespace. The DSDT is required,
* but the SSDT and PSDT tables are optional.
*/
- status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Ignore exceptions from these */
- (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
- (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
+ (void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT);
+ (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT);
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "ACPI Namespace successfully loaded at root %p\n",
- acpi_gbl_root_node));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+ "ACPI Namespace successfully loaded at root %p\n",
+ acpi_gbl_root_node));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_IMPLEMENTATION
/*******************************************************************************
*
@@ -353,24 +305,20 @@ acpi_ns_load_namespace (
*
******************************************************************************/
-static acpi_status
-acpi_ns_delete_subtree (
- acpi_handle start_handle)
+static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
{
- acpi_status status;
- acpi_handle child_handle;
- acpi_handle parent_handle;
- acpi_handle next_child_handle;
- acpi_handle dummy;
- u32 level;
-
-
- ACPI_FUNCTION_TRACE ("ns_delete_subtree");
+ acpi_status status;
+ acpi_handle child_handle;
+ acpi_handle parent_handle;
+ acpi_handle next_child_handle;
+ acpi_handle dummy;
+ u32 level;
+ ACPI_FUNCTION_TRACE("ns_delete_subtree");
parent_handle = start_handle;
child_handle = NULL;
- level = 1;
+ level = 1;
/*
* Traverse the tree of objects until we bubble back up
@@ -379,18 +327,19 @@ acpi_ns_delete_subtree (
while (level > 0) {
/* Attempt to get the next object in this scope */
- status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
- child_handle, &next_child_handle);
+ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
+ child_handle, &next_child_handle);
child_handle = next_child_handle;
/* Did we get a new object? */
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/* Check if this object has any children */
- if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
- NULL, &dummy))) {
+ if (ACPI_SUCCESS
+ (acpi_get_next_object
+ (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
/*
* There is at least one child of this object,
* visit the object
@@ -399,8 +348,7 @@ acpi_ns_delete_subtree (
parent_handle = child_handle;
child_handle = NULL;
}
- }
- else {
+ } else {
/*
* No more children in this object, go back up to
* the object's parent
@@ -409,24 +357,23 @@ acpi_ns_delete_subtree (
/* Delete all children now */
- acpi_ns_delete_children (child_handle);
+ acpi_ns_delete_children(child_handle);
child_handle = parent_handle;
- status = acpi_get_parent (parent_handle, &parent_handle);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_parent(parent_handle, &parent_handle);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
}
/* Now delete the starting object, and we are done */
- acpi_ns_delete_node (child_handle);
+ acpi_ns_delete_node(child_handle);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_unload_name_space
@@ -441,32 +388,27 @@ acpi_ns_delete_subtree (
*
******************************************************************************/
-acpi_status
-acpi_ns_unload_namespace (
- acpi_handle handle)
+acpi_status acpi_ns_unload_namespace(acpi_handle handle)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_unload_name_space");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_unload_name_space");
/* Parameter validation */
if (!acpi_gbl_root_node) {
- return_ACPI_STATUS (AE_NO_NAMESPACE);
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
if (!handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* This function does the real work */
- status = acpi_ns_delete_subtree (handle);
+ status = acpi_ns_delete_subtree(handle);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
#endif
#endif
-
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index d8ce7e39795f..d5e8dea61c27 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -41,23 +41,17 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsnames")
+ACPI_MODULE_NAME("nsnames")
/* Local prototypes */
-
static void
-acpi_ns_build_external_path (
- struct acpi_namespace_node *node,
- acpi_size size,
- char *name_buffer);
-
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+ acpi_size size, char *name_buffer);
/*******************************************************************************
*
@@ -75,17 +69,13 @@ acpi_ns_build_external_path (
******************************************************************************/
static void
-acpi_ns_build_external_path (
- struct acpi_namespace_node *node,
- acpi_size size,
- char *name_buffer)
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+ acpi_size size, char *name_buffer)
{
- acpi_size index;
- struct acpi_namespace_node *parent_node;
-
-
- ACPI_FUNCTION_NAME ("ns_build_external_path");
+ acpi_size index;
+ struct acpi_namespace_node *parent_node;
+ ACPI_FUNCTION_NAME("ns_build_external_path");
/* Special case for root */
@@ -106,8 +96,8 @@ acpi_ns_build_external_path (
/* Put the name into the buffer */
- ACPI_MOVE_32_TO_32 ((name_buffer + index), &parent_node->name);
- parent_node = acpi_ns_get_parent_node (parent_node);
+ ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name);
+ parent_node = acpi_ns_get_parent_node(parent_node);
/* Prefix name with the path separator */
@@ -120,15 +110,14 @@ acpi_ns_build_external_path (
name_buffer[index] = AML_ROOT_PREFIX;
if (index != 0) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not construct pathname; index=%X, size=%X, Path=%s\n",
- (u32) index, (u32) size, &name_buffer[size]));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not construct pathname; index=%X, size=%X, Path=%s\n",
+ (u32) index, (u32) size, &name_buffer[size]));
}
return;
}
-
#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
*
@@ -144,37 +133,32 @@ acpi_ns_build_external_path (
*
******************************************************************************/
-char *
-acpi_ns_get_external_pathname (
- struct acpi_namespace_node *node)
+char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
{
- char *name_buffer;
- acpi_size size;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ns_get_external_pathname", node);
+ char *name_buffer;
+ acpi_size size;
+ ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node);
/* Calculate required buffer size based on depth below root */
- size = acpi_ns_get_pathname_length (node);
+ size = acpi_ns_get_pathname_length(node);
/* Allocate a buffer to be returned to caller */
- name_buffer = ACPI_MEM_CALLOCATE (size);
+ name_buffer = ACPI_MEM_CALLOCATE(size);
if (!name_buffer) {
- ACPI_REPORT_ERROR (("ns_get_table_pathname: allocation failure\n"));
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("ns_get_table_pathname: allocation failure\n"));
+ return_PTR(NULL);
}
/* Build the path in the allocated buffer */
- acpi_ns_build_external_path (node, size, name_buffer);
- return_PTR (name_buffer);
+ acpi_ns_build_external_path(node, size, name_buffer);
+ return_PTR(name_buffer);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_pathname_length
@@ -187,16 +171,12 @@ acpi_ns_get_external_pathname (
*
******************************************************************************/
-acpi_size
-acpi_ns_get_pathname_length (
- struct acpi_namespace_node *node)
+acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
{
- acpi_size size;
- struct acpi_namespace_node *next_node;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_size size;
+ struct acpi_namespace_node *next_node;
+ ACPI_FUNCTION_ENTRY();
/*
* Compute length of pathname as 5 * number of name segments.
@@ -207,17 +187,16 @@ acpi_ns_get_pathname_length (
while (next_node && (next_node != acpi_gbl_root_node)) {
size += ACPI_PATH_SEGMENT_LENGTH;
- next_node = acpi_ns_get_parent_node (next_node);
+ next_node = acpi_ns_get_parent_node(next_node);
}
if (!size) {
- size = 1; /* Root node case */
+ size = 1; /* Root node case */
}
- return (size + 1); /* +1 for null string terminator */
+ return (size + 1); /* +1 for null string terminator */
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_handle_to_pathname
@@ -233,41 +212,36 @@ acpi_ns_get_pathname_length (
******************************************************************************/
acpi_status
-acpi_ns_handle_to_pathname (
- acpi_handle target_handle,
- struct acpi_buffer *buffer)
+acpi_ns_handle_to_pathname(acpi_handle target_handle,
+ struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- acpi_size required_size;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ acpi_size required_size;
+ ACPI_FUNCTION_TRACE_PTR("ns_handle_to_pathname", target_handle);
- ACPI_FUNCTION_TRACE_PTR ("ns_handle_to_pathname", target_handle);
-
-
- node = acpi_ns_map_handle_to_node (target_handle);
+ node = acpi_ns_map_handle_to_node(target_handle);
if (!node) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Determine size required for the caller buffer */
- required_size = acpi_ns_get_pathname_length (node);
+ required_size = acpi_ns_get_pathname_length(node);
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, required_size);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(buffer, required_size);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Build the path in the caller buffer */
- acpi_ns_build_external_path (node, required_size, buffer->pointer);
+ acpi_ns_build_external_path(node, required_size, buffer->pointer);
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n",
- (char *) buffer->pointer, (u32) required_size));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X] \n",
+ (char *)buffer->pointer, (u32) required_size));
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index 27258c1ca4f1..fc9be946ebed 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -42,14 +42,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsobject")
-
+ACPI_MODULE_NAME("nsobject")
/*******************************************************************************
*
@@ -71,20 +68,15 @@
* MUTEX: Assumes namespace is locked
*
******************************************************************************/
-
acpi_status
-acpi_ns_attach_object (
- struct acpi_namespace_node *node,
- union acpi_operand_object *object,
- acpi_object_type type)
+acpi_ns_attach_object(struct acpi_namespace_node *node,
+ union acpi_operand_object *object, acpi_object_type type)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *last_obj_desc;
- acpi_object_type object_type = ACPI_TYPE_ANY;
-
-
- ACPI_FUNCTION_TRACE ("ns_attach_object");
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *last_obj_desc;
+ acpi_object_type object_type = ACPI_TYPE_ANY;
+ ACPI_FUNCTION_TRACE("ns_attach_object");
/*
* Parameter validation
@@ -92,40 +84,39 @@ acpi_ns_attach_object (
if (!node) {
/* Invalid handle */
- ACPI_REPORT_ERROR (("ns_attach_object: Null named_obj handle\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Null named_obj handle\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (!object && (ACPI_TYPE_ANY != type)) {
/* Null object */
- ACPI_REPORT_ERROR ((
- "ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
/* Not a name handle */
- ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle %p [%s]\n",
- node, acpi_ut_get_descriptor_name (node)));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_attach_object: Invalid handle %p [%s]\n",
+ node, acpi_ut_get_descriptor_name(node)));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check if this object is already attached */
if (node->object == object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Obj %p already installed in name_obj %p\n",
- object, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Obj %p already installed in name_obj %p\n",
+ object, node));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* If null object, we will just install it */
if (!object) {
- obj_desc = NULL;
+ obj_desc = NULL;
object_type = ACPI_TYPE_ANY;
}
@@ -133,14 +124,14 @@ acpi_ns_attach_object (
* If the source object is a namespace Node with an attached object,
* we will use that (attached) object
*/
- else if ((ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) &&
- ((struct acpi_namespace_node *) object)->object) {
+ else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
+ ((struct acpi_namespace_node *)object)->object) {
/*
* Value passed is a name handle and that name has a
* non-null value. Use that name's value and type.
*/
- obj_desc = ((struct acpi_namespace_node *) object)->object;
- object_type = ((struct acpi_namespace_node *) object)->type;
+ obj_desc = ((struct acpi_namespace_node *)object)->object;
+ object_type = ((struct acpi_namespace_node *)object)->type;
}
/*
@@ -148,20 +139,20 @@ acpi_ns_attach_object (
* it first
*/
else {
- obj_desc = (union acpi_operand_object *) object;
+ obj_desc = (union acpi_operand_object *)object;
/* Use the given type */
object_type = type;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
- obj_desc, node, acpi_ut_get_node_name (node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
+ obj_desc, node, acpi_ut_get_node_name(node)));
/* Detach an existing attached object if present */
if (node->object) {
- acpi_ns_detach_object (node);
+ acpi_ns_detach_object(node);
}
if (obj_desc) {
@@ -169,7 +160,7 @@ acpi_ns_attach_object (
* Must increment the new value's reference count
* (if it is an internal object)
*/
- acpi_ut_add_reference (obj_desc);
+ acpi_ut_add_reference(obj_desc);
/*
* Handle objects with multiple descriptors - walk
@@ -185,13 +176,12 @@ acpi_ns_attach_object (
last_obj_desc->common.next_object = node->object;
}
- node->type = (u8) object_type;
- node->object = obj_desc;
+ node->type = (u8) object_type;
+ node->object = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_detach_object
@@ -206,30 +196,27 @@ acpi_ns_attach_object (
*
******************************************************************************/
-void
-acpi_ns_detach_object (
- struct acpi_namespace_node *node)
+void acpi_ns_detach_object(struct acpi_namespace_node *node)
{
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_detach_object");
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ns_detach_object");
obj_desc = node->object;
if (!obj_desc ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
+ (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
return_VOID;
}
/* Clear the entry in all cases */
node->object = NULL;
- if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
node->object = obj_desc->common.next_object;
if (node->object &&
- (ACPI_GET_OBJECT_TYPE (node->object) != ACPI_TYPE_LOCAL_DATA)) {
+ (ACPI_GET_OBJECT_TYPE(node->object) !=
+ ACPI_TYPE_LOCAL_DATA)) {
node->object = node->object->common.next_object;
}
}
@@ -238,16 +225,15 @@ acpi_ns_detach_object (
node->type = ACPI_TYPE_ANY;
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
- node, acpi_ut_get_node_name (node), obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
+ node, acpi_ut_get_node_name(node), obj_desc));
/* Remove one reference on the object (and all subobjects) */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_attached_object
@@ -261,29 +247,28 @@ acpi_ns_detach_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ns_get_attached_object (
- struct acpi_namespace_node *node)
+union acpi_operand_object *acpi_ns_get_attached_object(struct
+ acpi_namespace_node
+ *node)
{
- ACPI_FUNCTION_TRACE_PTR ("ns_get_attached_object", node);
-
+ ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
if (!node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Null Node ptr\n"));
- return_PTR (NULL);
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Null Node ptr\n"));
+ return_PTR(NULL);
}
if (!node->object ||
- ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) ||
- (ACPI_GET_OBJECT_TYPE (node->object) == ACPI_TYPE_LOCAL_DATA)) {
- return_PTR (NULL);
+ ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
+ ACPI_DESC_TYPE_NAMED))
+ || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) {
+ return_PTR(NULL);
}
- return_PTR (node->object);
+ return_PTR(node->object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_secondary_object
@@ -297,24 +282,23 @@ acpi_ns_get_attached_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ns_get_secondary_object (
- union acpi_operand_object *obj_desc)
+union acpi_operand_object *acpi_ns_get_secondary_object(union
+ acpi_operand_object
+ *obj_desc)
{
- ACPI_FUNCTION_TRACE_PTR ("ns_get_secondary_object", obj_desc);
-
-
- if ((!obj_desc) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
- (!obj_desc->common.next_object) ||
- (ACPI_GET_OBJECT_TYPE (obj_desc->common.next_object) == ACPI_TYPE_LOCAL_DATA)) {
- return_PTR (NULL);
+ ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc);
+
+ if ((!obj_desc) ||
+ (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
+ (!obj_desc->common.next_object) ||
+ (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) ==
+ ACPI_TYPE_LOCAL_DATA)) {
+ return_PTR(NULL);
}
- return_PTR (obj_desc->common.next_object);
+ return_PTR(obj_desc->common.next_object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_attach_data
@@ -330,23 +314,20 @@ acpi_ns_get_secondary_object (
******************************************************************************/
acpi_status
-acpi_ns_attach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void *data)
+acpi_ns_attach_data(struct acpi_namespace_node *node,
+ acpi_object_handler handler, void *data)
{
- union acpi_operand_object *prev_obj_desc;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *data_desc;
-
+ union acpi_operand_object *prev_obj_desc;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *data_desc;
/* We only allow one attachment per handler */
prev_obj_desc = NULL;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
return (AE_ALREADY_EXISTS);
}
@@ -356,7 +337,7 @@ acpi_ns_attach_data (
/* Create an internal object for the data */
- data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA);
+ data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
if (!data_desc) {
return (AE_NO_MEMORY);
}
@@ -368,15 +349,13 @@ acpi_ns_attach_data (
if (prev_obj_desc) {
prev_obj_desc->common.next_object = data_desc;
- }
- else {
+ } else {
node->object = data_desc;
}
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_detach_data
@@ -392,27 +371,25 @@ acpi_ns_attach_data (
******************************************************************************/
acpi_status
-acpi_ns_detach_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler)
+acpi_ns_detach_data(struct acpi_namespace_node * node,
+ acpi_object_handler handler)
{
- union acpi_operand_object *obj_desc;
- union acpi_operand_object *prev_obj_desc;
-
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *prev_obj_desc;
prev_obj_desc = NULL;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
if (prev_obj_desc) {
- prev_obj_desc->common.next_object = obj_desc->common.next_object;
- }
- else {
+ prev_obj_desc->common.next_object =
+ obj_desc->common.next_object;
+ } else {
node->object = obj_desc->common.next_object;
}
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
return (AE_OK);
}
@@ -423,7 +400,6 @@ acpi_ns_detach_data (
return (AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_attached_data
@@ -440,18 +416,15 @@ acpi_ns_detach_data (
******************************************************************************/
acpi_status
-acpi_ns_get_attached_data (
- struct acpi_namespace_node *node,
- acpi_object_handler handler,
- void **data)
+acpi_ns_get_attached_data(struct acpi_namespace_node * node,
+ acpi_object_handler handler, void **data)
{
- union acpi_operand_object *obj_desc;
-
+ union acpi_operand_object *obj_desc;
obj_desc = node->object;
while (obj_desc) {
- if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
- (obj_desc->data.handler == handler)) {
+ if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
+ (obj_desc->data.handler == handler)) {
*data = obj_desc->data.pointer;
return (AE_OK);
}
@@ -461,5 +434,3 @@ acpi_ns_get_attached_data (
return (AE_NOT_FOUND);
}
-
-
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index a0e13e8d3764..433442a9ec74 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsparse")
-
+ACPI_MODULE_NAME("nsparse")
/*******************************************************************************
*
@@ -64,54 +61,50 @@
* DESCRIPTION: Perform one complete parse of an ACPI/AML table.
*
******************************************************************************/
-
acpi_status
-acpi_ns_one_complete_parse (
- u32 pass_number,
- struct acpi_table_desc *table_desc)
+acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc * table_desc)
{
- union acpi_parse_object *parse_root;
- acpi_status status;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("ns_one_complete_parse");
+ union acpi_parse_object *parse_root;
+ acpi_status status;
+ struct acpi_walk_state *walk_state;
+ ACPI_FUNCTION_TRACE("ns_one_complete_parse");
/* Create and init a Root Node */
- parse_root = acpi_ps_create_scope_op ();
+ parse_root = acpi_ps_create_scope_op();
if (!parse_root) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Create and initialize a new walk state */
- walk_state = acpi_ds_create_walk_state (table_desc->table_id,
- NULL, NULL, NULL);
+ walk_state = acpi_ds_create_walk_state(table_desc->owner_id,
+ NULL, NULL, NULL);
if (!walk_state) {
- acpi_ps_free_op (parse_root);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_ps_free_op(parse_root);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
- table_desc->aml_start, table_desc->aml_length,
- NULL, pass_number);
- if (ACPI_FAILURE (status)) {
- acpi_ds_delete_walk_state (walk_state);
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
+ table_desc->aml_start,
+ table_desc->aml_length, NULL,
+ pass_number);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ return_ACPI_STATUS(status);
}
/* Parse the AML */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", pass_number));
- status = acpi_ps_parse_aml (walk_state);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n",
+ pass_number));
+ status = acpi_ps_parse_aml(walk_state);
- acpi_ps_delete_parse_tree (parse_root);
- return_ACPI_STATUS (status);
+ acpi_ps_delete_parse_tree(parse_root);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_parse_table
@@ -126,15 +119,12 @@ acpi_ns_one_complete_parse (
******************************************************************************/
acpi_status
-acpi_ns_parse_table (
- struct acpi_table_desc *table_desc,
- struct acpi_namespace_node *start_node)
+acpi_ns_parse_table(struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *start_node)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_parse_table");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_parse_table");
/*
* AML Parse, pass 1
@@ -146,9 +136,10 @@ acpi_ns_parse_table (
* to service the entire parse. The second pass of the parse then
* performs another complete parse of the AML..
*/
- status = acpi_ns_one_complete_parse (1, table_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+ status = acpi_ns_one_complete_parse(1, table_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -160,12 +151,11 @@ acpi_ns_parse_table (
* overhead of this is compensated for by the fact that the
* parse objects are all cached.
*/
- status = acpi_ns_one_complete_parse (2, table_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
+ status = acpi_ns_one_complete_parse(2, table_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index af8aaa9cc4f3..50a3ca5470ed 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -41,23 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nssearch")
+ACPI_MODULE_NAME("nssearch")
/* Local prototypes */
-
static acpi_status
-acpi_ns_search_parent_tree (
- u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node);
-
+acpi_ns_search_parent_tree(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node);
/*******************************************************************************
*
@@ -87,30 +82,28 @@ acpi_ns_search_parent_tree (
******************************************************************************/
acpi_status
-acpi_ns_search_node (
- u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_node(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node)
{
- struct acpi_namespace_node *next_node;
-
-
- ACPI_FUNCTION_TRACE ("ns_search_node");
+ struct acpi_namespace_node *next_node;
+ ACPI_FUNCTION_TRACE("ns_search_node");
#ifdef ACPI_DEBUG_OUTPUT
if (ACPI_LV_NAMES & acpi_dbg_level) {
- char *scope_name;
+ char *scope_name;
- scope_name = acpi_ns_get_external_pathname (node);
+ scope_name = acpi_ns_get_external_pathname(node);
if (scope_name) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching %s (%p) For [%4.4s] (%s)\n",
- scope_name, node, (char *) &target_name,
- acpi_ut_get_type_name (type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching %s (%p) For [%4.4s] (%s)\n",
+ scope_name, node,
+ (char *)&target_name,
+ acpi_ut_get_type_name(type)));
- ACPI_MEM_FREE (scope_name);
+ ACPI_MEM_FREE(scope_name);
}
}
#endif
@@ -126,20 +119,26 @@ acpi_ns_search_node (
if (next_node->name.integer == target_name) {
/* Resolve a control method alias if any */
- if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
+ if (acpi_ns_get_type(next_node) ==
+ ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ next_node =
+ ACPI_CAST_PTR(struct acpi_namespace_node,
+ next_node->object);
}
/*
* Found matching entry.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
- (char *) &target_name, acpi_ut_get_type_name (next_node->type),
- next_node, acpi_ut_get_node_name (node), node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
+ (char *)&target_name,
+ acpi_ut_get_type_name(next_node->
+ type),
+ next_node,
+ acpi_ut_get_node_name(node), node));
*return_node = next_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -159,15 +158,14 @@ acpi_ns_search_node (
/* Searched entire namespace level, not found */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
- (char *) &target_name, acpi_ut_get_type_name (type),
- acpi_ut_get_node_name (node), node, node->child));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
+ (char *)&target_name, acpi_ut_get_type_name(type),
+ acpi_ut_get_node_name(node), node, node->child));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_search_parent_tree
@@ -194,43 +192,42 @@ acpi_ns_search_node (
******************************************************************************/
static acpi_status
-acpi_ns_search_parent_tree (
- u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_parent_tree(u32 target_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node)
{
- acpi_status status;
- struct acpi_namespace_node *parent_node;
+ acpi_status status;
+ struct acpi_namespace_node *parent_node;
+ ACPI_FUNCTION_TRACE("ns_search_parent_tree");
- ACPI_FUNCTION_TRACE ("ns_search_parent_tree");
-
-
- parent_node = acpi_ns_get_parent_node (node);
+ parent_node = acpi_ns_get_parent_node(node);
/*
* If there is no parent (i.e., we are at the root) or type is "local",
* we won't be searching the parent tree.
*/
if (!parent_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
- (char *) &target_name));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
+ (char *)&target_name));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
- if (acpi_ns_local (type)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
- (char *) &target_name, acpi_ut_get_type_name (type)));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ if (acpi_ns_local(type)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
+ (char *)&target_name,
+ acpi_ut_get_type_name(type)));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
/* Search the parent tree */
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "Searching parent [%4.4s] for [%4.4s]\n",
- acpi_ut_get_node_name (parent_node), (char *) &target_name));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "Searching parent [%4.4s] for [%4.4s]\n",
+ acpi_ut_get_node_name(parent_node),
+ (char *)&target_name));
/*
* Search parents until target is found or we have backed up to the root
@@ -241,25 +238,24 @@ acpi_ns_search_parent_tree (
* object type at this point, we only care about the existence of
* the actual name we are searching for. Typechecking comes later.
*/
- status = acpi_ns_search_node (target_name, parent_node,
- ACPI_TYPE_ANY, return_node);
- if (ACPI_SUCCESS (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_search_node(target_name, parent_node,
+ ACPI_TYPE_ANY, return_node);
+ if (ACPI_SUCCESS(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Not found here, go up another level
* (until we reach the root)
*/
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
/* Not found in parent tree */
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_search_and_enter
@@ -286,52 +282,46 @@ acpi_ns_search_parent_tree (
******************************************************************************/
acpi_status
-acpi_ns_search_and_enter (
- u32 target_name,
- struct acpi_walk_state *walk_state,
- struct acpi_namespace_node *node,
- acpi_interpreter_mode interpreter_mode,
- acpi_object_type type,
- u32 flags,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_and_enter(u32 target_name,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ acpi_interpreter_mode interpreter_mode,
+ acpi_object_type type,
+ u32 flags, struct acpi_namespace_node **return_node)
{
- acpi_status status;
- struct acpi_namespace_node *new_node;
-
-
- ACPI_FUNCTION_TRACE ("ns_search_and_enter");
+ acpi_status status;
+ struct acpi_namespace_node *new_node;
+ ACPI_FUNCTION_TRACE("ns_search_and_enter");
/* Parameter validation */
if (!node || !target_name || !return_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Null param: Node %p Name %X return_node %p\n",
- node, target_name, return_node));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Null param: Node %p Name %X return_node %p\n",
+ node, target_name, return_node));
- ACPI_REPORT_ERROR (("ns_search_and_enter: Null parameter\n"));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("ns_search_and_enter: Null parameter\n"));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Name must consist of printable characters */
- if (!acpi_ut_valid_acpi_name (target_name)) {
- ACPI_REPORT_ERROR (("ns_search_and_enter: Bad character in ACPI Name: %X\n",
- target_name));
- return_ACPI_STATUS (AE_BAD_CHARACTER);
+ if (!acpi_ut_valid_acpi_name(target_name)) {
+ ACPI_REPORT_ERROR(("ns_search_and_enter: Bad character in ACPI Name: %X\n", target_name));
+ return_ACPI_STATUS(AE_BAD_CHARACTER);
}
/* Try to find the name in the namespace level specified by the caller */
*return_node = ACPI_ENTRY_NOT_FOUND;
- status = acpi_ns_search_node (target_name, node, type, return_node);
+ status = acpi_ns_search_node(target_name, node, type, return_node);
if (status != AE_NOT_FOUND) {
/*
* If we found it AND the request specifies that a find is an error,
* return the error
*/
- if ((status == AE_OK) &&
- (flags & ACPI_NS_ERROR_IF_FOUND)) {
+ if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) {
status = AE_ALREADY_EXISTS;
}
@@ -339,7 +329,7 @@ acpi_ns_search_and_enter (
* Either found it or there was an error
* -- finished either way
*/
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*
@@ -351,14 +341,16 @@ acpi_ns_search_and_enter (
* and during the execution phase.
*/
if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) &&
- (flags & ACPI_NS_SEARCH_PARENT)) {
+ (flags & ACPI_NS_SEARCH_PARENT)) {
/*
* Not found at this level - search parent tree according to the
* ACPI specification
*/
- status = acpi_ns_search_parent_tree (target_name, node, type, return_node);
- if (ACPI_SUCCESS (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ns_search_parent_tree(target_name, node, type,
+ return_node);
+ if (ACPI_SUCCESS(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -366,25 +358,24 @@ acpi_ns_search_and_enter (
* In execute mode, just search, never add names. Exit now.
*/
if (interpreter_mode == ACPI_IMODE_EXECUTE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "%4.4s Not found in %p [Not adding]\n",
- (char *) &target_name, node));
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "%4.4s Not found in %p [Not adding]\n",
+ (char *)&target_name, node));
- return_ACPI_STATUS (AE_NOT_FOUND);
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
/* Create the new named object */
- new_node = acpi_ns_create_node (target_name);
+ new_node = acpi_ns_create_node(target_name);
if (!new_node) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Install the new object into the parent's list of children */
- acpi_ns_install_node (walk_state, node, new_node, type);
+ acpi_ns_install_node(walk_state, node, new_node, type);
*return_node = new_node;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index c53b82e94ce3..ebec036423c9 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -42,28 +42,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/amlcode.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsutils")
+ACPI_MODULE_NAME("nsutils")
/* Local prototypes */
-
-static u8
-acpi_ns_valid_path_separator (
- char sep);
+static u8 acpi_ns_valid_path_separator(char sep);
#ifdef ACPI_OBSOLETE_FUNCTIONS
-acpi_name
-acpi_ns_find_parent_name (
- struct acpi_namespace_node *node_to_search);
+acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_error
@@ -81,51 +74,45 @@ acpi_ns_find_parent_name (
******************************************************************************/
void
-acpi_ns_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *internal_name,
- acpi_status lookup_status)
+acpi_ns_report_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *internal_name, acpi_status lookup_status)
{
- acpi_status status;
- char *name = NULL;
-
+ acpi_status status;
+ char *name = NULL;
- acpi_os_printf ("%8s-%04d: *** Error: Looking up ",
- module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Error: Looking up ",
+ module_name, line_number);
if (lookup_status == AE_BAD_CHARACTER) {
/* There is a non-ascii character in the name */
- acpi_os_printf ("[0x%4.4X] (NON-ASCII)\n",
- *(ACPI_CAST_PTR (u32, internal_name)));
- }
- else {
+ acpi_os_printf("[0x%4.4X] (NON-ASCII)\n",
+ *(ACPI_CAST_PTR(u32, internal_name)));
+ } else {
/* Convert path to external format */
- status = acpi_ns_externalize_name (ACPI_UINT32_MAX,
- internal_name, NULL, &name);
+ status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
+ internal_name, NULL, &name);
/* Print target name */
- if (ACPI_SUCCESS (status)) {
- acpi_os_printf ("[%s]", name);
- }
- else {
- acpi_os_printf ("[COULD NOT EXTERNALIZE NAME]");
+ if (ACPI_SUCCESS(status)) {
+ acpi_os_printf("[%s]", name);
+ } else {
+ acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
}
if (name) {
- ACPI_MEM_FREE (name);
+ ACPI_MEM_FREE(name);
}
}
- acpi_os_printf (" in namespace, %s\n",
- acpi_format_exception (lookup_status));
+ acpi_os_printf(" in namespace, %s\n",
+ acpi_format_exception(lookup_status));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_method_error
@@ -145,34 +132,31 @@ acpi_ns_report_error (
******************************************************************************/
void
-acpi_ns_report_method_error (
- char *module_name,
- u32 line_number,
- u32 component_id,
- char *message,
- struct acpi_namespace_node *prefix_node,
- char *path,
- acpi_status method_status)
+acpi_ns_report_method_error(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ char *message,
+ struct acpi_namespace_node *prefix_node,
+ char *path, acpi_status method_status)
{
- acpi_status status;
- struct acpi_namespace_node *node = prefix_node;
-
+ acpi_status status;
+ struct acpi_namespace_node *node = prefix_node;
if (path) {
- status = acpi_ns_get_node_by_path (path, prefix_node,
- ACPI_NS_NO_UPSEARCH, &node);
- if (ACPI_FAILURE (status)) {
- acpi_os_printf ("report_method_error: Could not get node\n");
+ status = acpi_ns_get_node_by_path(path, prefix_node,
+ ACPI_NS_NO_UPSEARCH, &node);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf
+ ("report_method_error: Could not get node\n");
return;
}
}
- acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
- acpi_ns_print_node_pathname (node, message);
- acpi_os_printf (", %s\n", acpi_format_exception (method_status));
+ acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
+ acpi_ns_print_node_pathname(node, message);
+ acpi_os_printf(", %s\n", acpi_format_exception(method_status));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_print_node_pathname
@@ -186,16 +170,13 @@ acpi_ns_report_method_error (
******************************************************************************/
void
-acpi_ns_print_node_pathname (
- struct acpi_namespace_node *node,
- char *message)
+acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
{
- struct acpi_buffer buffer;
- acpi_status status;
-
+ struct acpi_buffer buffer;
+ acpi_status status;
if (!node) {
- acpi_os_printf ("[NULL NAME]");
+ acpi_os_printf("[NULL NAME]");
return;
}
@@ -203,18 +184,17 @@ acpi_ns_print_node_pathname (
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_ns_handle_to_pathname (node, &buffer);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_handle_to_pathname(node, &buffer);
+ if (ACPI_SUCCESS(status)) {
if (message) {
- acpi_os_printf ("%s ", message);
+ acpi_os_printf("%s ", message);
}
- acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node);
- ACPI_MEM_FREE (buffer.pointer);
+ acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
+ ACPI_MEM_FREE(buffer.pointer);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_valid_root_prefix
@@ -227,15 +207,12 @@ acpi_ns_print_node_pathname (
*
******************************************************************************/
-u8
-acpi_ns_valid_root_prefix (
- char prefix)
+u8 acpi_ns_valid_root_prefix(char prefix)
{
return ((u8) (prefix == '\\'));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_valid_path_separator
@@ -248,15 +225,12 @@ acpi_ns_valid_root_prefix (
*
******************************************************************************/
-static u8
-acpi_ns_valid_path_separator (
- char sep)
+static u8 acpi_ns_valid_path_separator(char sep)
{
return ((u8) (sep == '.'));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_type
@@ -269,22 +243,18 @@ acpi_ns_valid_path_separator (
*
******************************************************************************/
-acpi_object_type
-acpi_ns_get_type (
- struct acpi_namespace_node *node)
+acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
{
- ACPI_FUNCTION_TRACE ("ns_get_type");
-
+ ACPI_FUNCTION_TRACE("ns_get_type");
if (!node) {
- ACPI_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
- return_VALUE (ACPI_TYPE_ANY);
+ ACPI_REPORT_WARNING(("ns_get_type: Null Node input pointer\n"));
+ return_VALUE(ACPI_TYPE_ANY);
}
- return_VALUE ((acpi_object_type) node->type);
+ return_VALUE((acpi_object_type) node->type);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_local
@@ -298,24 +268,20 @@ acpi_ns_get_type (
*
******************************************************************************/
-u32
-acpi_ns_local (
- acpi_object_type type)
+u32 acpi_ns_local(acpi_object_type type)
{
- ACPI_FUNCTION_TRACE ("ns_local");
-
+ ACPI_FUNCTION_TRACE("ns_local");
- if (!acpi_ut_valid_object_type (type)) {
+ if (!acpi_ut_valid_object_type(type)) {
/* Type code out of range */
- ACPI_REPORT_WARNING (("ns_local: Invalid Object Type\n"));
- return_VALUE (ACPI_NS_NORMAL);
+ ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n"));
+ return_VALUE(ACPI_NS_NORMAL);
}
- return_VALUE ((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
+ return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_internal_name_length
@@ -330,16 +296,12 @@ acpi_ns_local (
*
******************************************************************************/
-void
-acpi_ns_get_internal_name_length (
- struct acpi_namestring_info *info)
+void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
{
- char *next_external_char;
- u32 i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ char *next_external_char;
+ u32 i;
+ ACPI_FUNCTION_ENTRY();
next_external_char = info->external_name;
info->num_carats = 0;
@@ -353,11 +315,10 @@ acpi_ns_get_internal_name_length (
*
* strlen() + 1 covers the first name_seg, which has no path separator
*/
- if (acpi_ns_valid_root_prefix (next_external_char[0])) {
+ if (acpi_ns_valid_root_prefix(next_external_char[0])) {
info->fully_qualified = TRUE;
next_external_char++;
- }
- else {
+ } else {
/*
* Handle Carat prefixes
*/
@@ -375,19 +336,18 @@ acpi_ns_get_internal_name_length (
if (*next_external_char) {
info->num_segments = 1;
for (i = 0; next_external_char[i]; i++) {
- if (acpi_ns_valid_path_separator (next_external_char[i])) {
+ if (acpi_ns_valid_path_separator(next_external_char[i])) {
info->num_segments++;
}
}
}
info->length = (ACPI_NAME_SIZE * info->num_segments) +
- 4 + info->num_carats;
+ 4 + info->num_carats;
info->next_external_char = next_external_char;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_build_internal_name
@@ -401,19 +361,15 @@ acpi_ns_get_internal_name_length (
*
******************************************************************************/
-acpi_status
-acpi_ns_build_internal_name (
- struct acpi_namestring_info *info)
+acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
{
- u32 num_segments = info->num_segments;
- char *internal_name = info->internal_name;
- char *external_name = info->next_external_char;
- char *result = NULL;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ns_build_internal_name");
+ u32 num_segments = info->num_segments;
+ char *internal_name = info->internal_name;
+ char *external_name = info->next_external_char;
+ char *result = NULL;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ns_build_internal_name");
/* Setup the correct prefixes, counts, and pointers */
@@ -422,18 +378,15 @@ acpi_ns_build_internal_name (
if (num_segments <= 1) {
result = &internal_name[1];
- }
- else if (num_segments == 2) {
+ } else if (num_segments == 2) {
internal_name[1] = AML_DUAL_NAME_PREFIX;
result = &internal_name[2];
- }
- else {
+ } else {
internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[2] = (char) num_segments;
+ internal_name[2] = (char)num_segments;
result = &internal_name[3];
}
- }
- else {
+ } else {
/*
* Not fully qualified.
* Handle Carats first, then append the name segments
@@ -447,15 +400,14 @@ acpi_ns_build_internal_name (
if (num_segments <= 1) {
result = &internal_name[i];
- }
- else if (num_segments == 2) {
+ } else if (num_segments == 2) {
internal_name[i] = AML_DUAL_NAME_PREFIX;
- result = &internal_name[(acpi_native_uint) (i+1)];
- }
- else {
+ result = &internal_name[(acpi_native_uint) (i + 1)];
+ } else {
internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[(acpi_native_uint) (i+1)] = (char) num_segments;
- result = &internal_name[(acpi_native_uint) (i+2)];
+ internal_name[(acpi_native_uint) (i + 1)] =
+ (char)num_segments;
+ result = &internal_name[(acpi_native_uint) (i + 2)];
}
}
@@ -463,25 +415,25 @@ acpi_ns_build_internal_name (
for (; num_segments; num_segments--) {
for (i = 0; i < ACPI_NAME_SIZE; i++) {
- if (acpi_ns_valid_path_separator (*external_name) ||
- (*external_name == 0)) {
+ if (acpi_ns_valid_path_separator(*external_name) ||
+ (*external_name == 0)) {
/* Pad the segment with underscore(s) if segment is short */
result[i] = '_';
- }
- else {
+ } else {
/* Convert the character to uppercase and save it */
- result[i] = (char) ACPI_TOUPPER ((int) *external_name);
+ result[i] =
+ (char)ACPI_TOUPPER((int)*external_name);
external_name++;
}
}
/* Now we must have a path separator, or the pathname is bad */
- if (!acpi_ns_valid_path_separator (*external_name) &&
- (*external_name != 0)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if (!acpi_ns_valid_path_separator(*external_name) &&
+ (*external_name != 0)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Move on the next segment */
@@ -495,18 +447,17 @@ acpi_ns_build_internal_name (
*result = 0;
if (info->fully_qualified) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
- internal_name, internal_name));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
- internal_name, internal_name));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Returning [%p] (abs) \"\\%s\"\n",
+ internal_name, internal_name));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
+ internal_name, internal_name));
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_internalize_name
@@ -522,51 +473,43 @@ acpi_ns_build_internal_name (
*
*******************************************************************************/
-acpi_status
-acpi_ns_internalize_name (
- char *external_name,
- char **converted_name)
+acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
{
- char *internal_name;
- struct acpi_namestring_info info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ns_internalize_name");
+ char *internal_name;
+ struct acpi_namestring_info info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ns_internalize_name");
- if ((!external_name) ||
- (*external_name == 0) ||
- (!converted_name)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!external_name) || (*external_name == 0) || (!converted_name)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get the length of the new internal name */
info.external_name = external_name;
- acpi_ns_get_internal_name_length (&info);
+ acpi_ns_get_internal_name_length(&info);
/* We need a segment to store the internal name */
- internal_name = ACPI_MEM_CALLOCATE (info.length);
+ internal_name = ACPI_MEM_CALLOCATE(info.length);
if (!internal_name) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Build the name */
info.internal_name = internal_name;
- status = acpi_ns_build_internal_name (&info);
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (internal_name);
- return_ACPI_STATUS (status);
+ status = acpi_ns_build_internal_name(&info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(internal_name);
+ return_ACPI_STATUS(status);
}
*converted_name = internal_name;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_externalize_name
@@ -585,27 +528,21 @@ acpi_ns_internalize_name (
******************************************************************************/
acpi_status
-acpi_ns_externalize_name (
- u32 internal_name_length,
- char *internal_name,
- u32 *converted_name_length,
- char **converted_name)
+acpi_ns_externalize_name(u32 internal_name_length,
+ char *internal_name,
+ u32 * converted_name_length, char **converted_name)
{
- acpi_native_uint names_index = 0;
- acpi_native_uint num_segments = 0;
- acpi_native_uint required_length;
- acpi_native_uint prefix_length = 0;
- acpi_native_uint i = 0;
- acpi_native_uint j = 0;
-
+ acpi_native_uint names_index = 0;
+ acpi_native_uint num_segments = 0;
+ acpi_native_uint required_length;
+ acpi_native_uint prefix_length = 0;
+ acpi_native_uint i = 0;
+ acpi_native_uint j = 0;
- ACPI_FUNCTION_TRACE ("ns_externalize_name");
+ ACPI_FUNCTION_TRACE("ns_externalize_name");
-
- if (!internal_name_length ||
- !internal_name ||
- !converted_name) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if (!internal_name_length || !internal_name || !converted_name) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -620,8 +557,7 @@ acpi_ns_externalize_name (
for (i = 0; i < internal_name_length; i++) {
if (internal_name[i] == '^') {
prefix_length = i + 1;
- }
- else {
+ } else {
break;
}
}
@@ -648,7 +584,8 @@ acpi_ns_externalize_name (
names_index = prefix_length + 2;
num_segments = (acpi_native_uint) (u8)
- internal_name[(acpi_native_uint) (prefix_length + 1)];
+ internal_name[(acpi_native_uint)
+ (prefix_length + 1)];
break;
case AML_DUAL_NAME_PREFIX:
@@ -683,23 +620,23 @@ acpi_ns_externalize_name (
* punctuation ('.') between object names, plus the NULL terminator.
*/
required_length = prefix_length + (4 * num_segments) +
- ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
+ ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
/*
* Check to see if we're still in bounds. If not, there's a problem
* with internal_name (invalid format).
*/
if (required_length > internal_name_length) {
- ACPI_REPORT_ERROR (("ns_externalize_name: Invalid internal name\n"));
- return_ACPI_STATUS (AE_BAD_PATHNAME);
+ ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n"));
+ return_ACPI_STATUS(AE_BAD_PATHNAME);
}
/*
* Build converted_name
*/
- *converted_name = ACPI_MEM_CALLOCATE (required_length);
+ *converted_name = ACPI_MEM_CALLOCATE(required_length);
if (!(*converted_name)) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
j = 0;
@@ -725,10 +662,9 @@ acpi_ns_externalize_name (
*converted_name_length = (u32) required_length;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_map_handle_to_node
@@ -745,13 +681,10 @@ acpi_ns_externalize_name (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_map_handle_to_node (
- acpi_handle handle)
+struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/*
* Simple implementation.
@@ -766,14 +699,13 @@ acpi_ns_map_handle_to_node (
/* We can at least attempt to verify the handle */
- if (ACPI_GET_DESCRIPTOR_TYPE (handle) != ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
return (NULL);
}
- return ((struct acpi_namespace_node *) handle);
+ return ((struct acpi_namespace_node *)handle);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_convert_entry_to_handle
@@ -786,18 +718,14 @@ acpi_ns_map_handle_to_node (
*
******************************************************************************/
-acpi_handle
-acpi_ns_convert_entry_to_handle (
- struct acpi_namespace_node *node)
+acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node)
{
-
/*
* Simple implementation for now;
*/
return ((acpi_handle) node);
-
/* Example future implementation ---------------------
if (!Node)
@@ -810,12 +738,10 @@ acpi_ns_convert_entry_to_handle (
return (ACPI_ROOT_OBJECT);
}
-
return ((acpi_handle) Node);
------------------------------------------------------*/
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_terminate
@@ -828,42 +754,37 @@ acpi_ns_convert_entry_to_handle (
*
******************************************************************************/
-void
-acpi_ns_terminate (
- void)
+void acpi_ns_terminate(void)
{
- union acpi_operand_object *obj_desc;
-
-
- ACPI_FUNCTION_TRACE ("ns_terminate");
+ union acpi_operand_object *obj_desc;
+ ACPI_FUNCTION_TRACE("ns_terminate");
/*
* 1) Free the entire namespace -- all nodes and objects
*
* Delete all object descriptors attached to namepsace nodes
*/
- acpi_ns_delete_namespace_subtree (acpi_gbl_root_node);
+ acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
/* Detach any objects attached to the root */
- obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node);
+ obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
if (obj_desc) {
- acpi_ns_detach_object (acpi_gbl_root_node);
+ acpi_ns_detach_object(acpi_gbl_root_node);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
/*
* 2) Now we can delete the ACPI tables
*/
- acpi_tb_delete_all_tables ();
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
+ acpi_tb_delete_all_tables();
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_opens_scope
@@ -875,24 +796,21 @@ acpi_ns_terminate (
*
******************************************************************************/
-u32
-acpi_ns_opens_scope (
- acpi_object_type type)
+u32 acpi_ns_opens_scope(acpi_object_type type)
{
- ACPI_FUNCTION_TRACE_STR ("ns_opens_scope", acpi_ut_get_type_name (type));
-
+ ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type));
- if (!acpi_ut_valid_object_type (type)) {
+ if (!acpi_ut_valid_object_type(type)) {
/* type code out of range */
- ACPI_REPORT_WARNING (("ns_opens_scope: Invalid Object Type %X\n", type));
- return_VALUE (ACPI_NS_NORMAL);
+ ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n",
+ type));
+ return_VALUE(ACPI_NS_NORMAL);
}
- return_VALUE (((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
+ return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_node_by_path
@@ -916,33 +834,29 @@ acpi_ns_opens_scope (
******************************************************************************/
acpi_status
-acpi_ns_get_node_by_path (
- char *pathname,
- struct acpi_namespace_node *start_node,
- u32 flags,
- struct acpi_namespace_node **return_node)
+acpi_ns_get_node_by_path(char *pathname,
+ struct acpi_namespace_node *start_node,
+ u32 flags, struct acpi_namespace_node **return_node)
{
- union acpi_generic_state scope_info;
- acpi_status status;
- char *internal_path = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ns_get_node_by_path", pathname);
+ union acpi_generic_state scope_info;
+ acpi_status status;
+ char *internal_path = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname);
if (pathname) {
/* Convert path to internal representation */
- status = acpi_ns_internalize_name (pathname, &internal_path);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Must lock namespace during lookup */
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -952,25 +866,25 @@ acpi_ns_get_node_by_path (
/* Lookup the name in the namespace */
- status = acpi_ns_lookup (&scope_info, internal_path,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- (flags | ACPI_NS_DONT_OPEN_SCOPE),
- NULL, return_node);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s, %s\n",
- internal_path, acpi_format_exception (status)));
+ status = acpi_ns_lookup(&scope_info, internal_path,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ (flags | ACPI_NS_DONT_OPEN_SCOPE),
+ NULL, return_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n",
+ internal_path,
+ acpi_format_exception(status)));
}
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-cleanup:
+ cleanup:
if (internal_path) {
- ACPI_MEM_FREE (internal_path);
+ ACPI_MEM_FREE(internal_path);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_parent_node
@@ -983,12 +897,10 @@ cleanup:
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_get_parent_node (
- struct acpi_namespace_node *node)
+struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node
+ *node)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
if (!node) {
return (NULL);
@@ -1006,7 +918,6 @@ acpi_ns_get_parent_node (
return (node->peer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_get_next_valid_node
@@ -1021,9 +932,9 @@ acpi_ns_get_parent_node (
*
******************************************************************************/
-struct acpi_namespace_node *
-acpi_ns_get_next_valid_node (
- struct acpi_namespace_node *node)
+struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct
+ acpi_namespace_node
+ *node)
{
/* If we are at the end of this peer list, return NULL */
@@ -1037,7 +948,6 @@ acpi_ns_get_next_valid_node (
return (node->peer);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -1053,38 +963,36 @@ acpi_ns_get_next_valid_node (
*
******************************************************************************/
-acpi_name
-acpi_ns_find_parent_name (
- struct acpi_namespace_node *child_node)
+acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node)
{
- struct acpi_namespace_node *parent_node;
-
-
- ACPI_FUNCTION_TRACE ("ns_find_parent_name");
+ struct acpi_namespace_node *parent_node;
+ ACPI_FUNCTION_TRACE("ns_find_parent_name");
if (child_node) {
/* Valid entry. Get the parent Node */
- parent_node = acpi_ns_get_parent_node (child_node);
+ parent_node = acpi_ns_get_parent_node(child_node);
if (parent_node) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Parent of %p [%4.4s] is %p [%4.4s]\n",
- child_node, acpi_ut_get_node_name (child_node),
- parent_node, acpi_ut_get_node_name (parent_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Parent of %p [%4.4s] is %p [%4.4s]\n",
+ child_node,
+ acpi_ut_get_node_name(child_node),
+ parent_node,
+ acpi_ut_get_node_name(parent_node)));
if (parent_node->name.integer) {
- return_VALUE ((acpi_name) parent_node->name.integer);
+ return_VALUE((acpi_name) parent_node->name.
+ integer);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Unable to find parent of %p (%4.4s)\n",
- child_node, acpi_ut_get_node_name (child_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Unable to find parent of %p (%4.4s)\n",
+ child_node,
+ acpi_ut_get_node_name(child_node)));
}
- return_VALUE (ACPI_UNKNOWN_NAME);
+ return_VALUE(ACPI_UNKNOWN_NAME);
}
#endif
-
-
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index f9a7277dca6e..5f164c0df33b 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nswalk")
-
+ACPI_MODULE_NAME("nswalk")
/*******************************************************************************
*
@@ -68,18 +65,15 @@
* within Scope is returned.
*
******************************************************************************/
-
-struct acpi_namespace_node *
-acpi_ns_get_next_node (
- acpi_object_type type,
- struct acpi_namespace_node *parent_node,
- struct acpi_namespace_node *child_node)
+struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
+ struct acpi_namespace_node
+ *parent_node,
+ struct acpi_namespace_node
+ *child_node)
{
- struct acpi_namespace_node *next_node = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_namespace_node *next_node = NULL;
+ ACPI_FUNCTION_ENTRY();
if (!child_node) {
/* It's really the parent's _scope_ that we want */
@@ -92,7 +86,7 @@ acpi_ns_get_next_node (
else {
/* Start search at the NEXT node */
- next_node = acpi_ns_get_next_valid_node (child_node);
+ next_node = acpi_ns_get_next_valid_node(child_node);
}
/* If any type is OK, we are done */
@@ -114,7 +108,7 @@ acpi_ns_get_next_node (
/* Otherwise, move on to the next node */
- next_node = acpi_ns_get_next_valid_node (next_node);
+ next_node = acpi_ns_get_next_valid_node(next_node);
}
/* Not found */
@@ -122,7 +116,6 @@ acpi_ns_get_next_node (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_walk_namespace
@@ -154,25 +147,21 @@ acpi_ns_get_next_node (
******************************************************************************/
acpi_status
-acpi_ns_walk_namespace (
- acpi_object_type type,
- acpi_handle start_node,
- u32 max_depth,
- u8 unlock_before_callback,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_ns_walk_namespace(acpi_object_type type,
+ acpi_handle start_node,
+ u32 max_depth,
+ u8 unlock_before_callback,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
- acpi_status mutex_status;
- struct acpi_namespace_node *child_node;
- struct acpi_namespace_node *parent_node;
- acpi_object_type child_type;
- u32 level;
-
-
- ACPI_FUNCTION_TRACE ("ns_walk_namespace");
+ acpi_status status;
+ acpi_status mutex_status;
+ struct acpi_namespace_node *child_node;
+ struct acpi_namespace_node *parent_node;
+ acpi_object_type child_type;
+ u32 level;
+ ACPI_FUNCTION_TRACE("ns_walk_namespace");
/* Special case for the namespace Root Node */
@@ -183,9 +172,9 @@ acpi_ns_walk_namespace (
/* Null child means "get first node" */
parent_node = start_node;
- child_node = NULL;
- child_type = ACPI_TYPE_ANY;
- level = 1;
+ child_node = NULL;
+ child_type = ACPI_TYPE_ANY;
+ level = 1;
/*
* Traverse the tree of nodes until we bubble back up to where we
@@ -196,7 +185,9 @@ acpi_ns_walk_namespace (
/* Get the next node in this scope. Null if not found */
status = AE_OK;
- child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
+ child_node =
+ acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
+ child_node);
if (child_node) {
/*
* Found node, Get the type if we are not
@@ -212,19 +203,25 @@ acpi_ns_walk_namespace (
* callback function
*/
if (unlock_before_callback) {
- mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (mutex_status)) {
- return_ACPI_STATUS (mutex_status);
+ mutex_status =
+ acpi_ut_release_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS
+ (mutex_status);
}
}
- status = user_function (child_node, level,
- context, return_value);
+ status = user_function(child_node, level,
+ context, return_value);
if (unlock_before_callback) {
- mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (mutex_status)) {
- return_ACPI_STATUS (mutex_status);
+ mutex_status =
+ acpi_ut_acquire_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(mutex_status)) {
+ return_ACPI_STATUS
+ (mutex_status);
}
}
@@ -239,13 +236,13 @@ acpi_ns_walk_namespace (
/* Exit now, with OK status */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
default:
/* All others are valid exceptions */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
}
@@ -258,7 +255,8 @@ acpi_ns_walk_namespace (
* maximum depth has been reached.
*/
if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
- if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
+ if (acpi_ns_get_next_node
+ (ACPI_TYPE_ANY, child_node, NULL)) {
/*
* There is at least one child of this
* node, visit the onde
@@ -268,8 +266,7 @@ acpi_ns_walk_namespace (
child_node = NULL;
}
}
- }
- else {
+ } else {
/*
* No more children of this node (acpi_ns_get_next_node
* failed), go back upwards in the namespace tree to
@@ -277,13 +274,11 @@ acpi_ns_walk_namespace (
*/
level--;
child_node = parent_node;
- parent_node = acpi_ns_get_parent_node (parent_node);
+ parent_node = acpi_ns_get_parent_node(parent_node);
}
}
/* Complete walk, not terminated by user function */
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 12ea202257fa..c07b046659ff 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -48,10 +48,8 @@
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfeval")
-
+ACPI_MODULE_NAME("nsxfeval")
/*******************************************************************************
*
@@ -73,27 +71,23 @@
* be valid (non-null)
*
******************************************************************************/
-
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_evaluate_object_typed (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *external_params,
- struct acpi_buffer *return_buffer,
- acpi_object_type return_type)
+acpi_evaluate_object_typed(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *external_params,
+ struct acpi_buffer *return_buffer,
+ acpi_object_type return_type)
{
- acpi_status status;
- u8 must_free = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("acpi_evaluate_object_typed");
+ acpi_status status;
+ u8 must_free = FALSE;
+ ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed");
/* Return buffer must be valid */
if (!return_buffer) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
@@ -102,51 +96,52 @@ acpi_evaluate_object_typed (
/* Evaluate the object */
- status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_evaluate_object(handle, pathname, external_params,
+ return_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Type ANY means "don't care" */
if (return_type == ACPI_TYPE_ANY) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
if (return_buffer->length == 0) {
/* Error because caller specifically asked for a return value */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No return value\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return value\n"));
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_OBJECT);
}
/* Examine the object type returned from evaluate_object */
- if (((union acpi_object *) return_buffer->pointer)->type == return_type) {
- return_ACPI_STATUS (AE_OK);
+ if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
+ return_ACPI_STATUS(AE_OK);
}
/* Return object type does not match requested type */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Incorrect return type [%s] requested [%s]\n",
- acpi_ut_get_type_name (((union acpi_object *) return_buffer->pointer)->type),
- acpi_ut_get_type_name (return_type)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Incorrect return type [%s] requested [%s]\n",
+ acpi_ut_get_type_name(((union acpi_object *)
+ return_buffer->pointer)->type),
+ acpi_ut_get_type_name(return_type)));
if (must_free) {
/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
- acpi_os_free (return_buffer->pointer);
+ acpi_os_free(return_buffer->pointer);
return_buffer->pointer = NULL;
}
return_buffer->length = 0;
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -169,21 +164,18 @@ acpi_evaluate_object_typed (
******************************************************************************/
acpi_status
-acpi_evaluate_object (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *external_params,
- struct acpi_buffer *return_buffer)
+acpi_evaluate_object(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *external_params,
+ struct acpi_buffer *return_buffer)
{
- acpi_status status;
- acpi_status status2;
- struct acpi_parameter_info info;
- acpi_size buffer_space_needed;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
+ acpi_status status;
+ acpi_status status2;
+ struct acpi_parameter_info info;
+ acpi_size buffer_space_needed;
+ u32 i;
+ ACPI_FUNCTION_TRACE("acpi_evaluate_object");
info.node = handle;
info.parameters = NULL;
@@ -200,11 +192,11 @@ acpi_evaluate_object (
* Allocate a new parameter block for the internal objects
* Add 1 to count to allow for null terminated internal list
*/
- info.parameters = ACPI_MEM_CALLOCATE (
- ((acpi_size) external_params->count + 1) *
- sizeof (void *));
+ info.parameters = ACPI_MEM_CALLOCATE(((acpi_size)
+ external_params->count +
+ 1) * sizeof(void *));
if (!info.parameters) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -212,48 +204,47 @@ acpi_evaluate_object (
* internal object
*/
for (i = 0; i < external_params->count; i++) {
- status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
- &info.parameters[i]);
- if (ACPI_FAILURE (status)) {
- acpi_ut_delete_internal_object_list (info.parameters);
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_copy_eobject_to_iobject(&external_params->
+ pointer[i],
+ &info.
+ parameters[i]);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_internal_object_list(info.
+ parameters);
+ return_ACPI_STATUS(status);
}
}
info.parameters[external_params->count] = NULL;
}
-
/*
* Three major cases:
* 1) Fully qualified pathname
* 2) No handle, not fully qualified pathname (error)
* 3) Valid handle
*/
- if ((pathname) &&
- (acpi_ns_valid_root_prefix (pathname[0]))) {
+ if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
/*
* The path is fully qualified, just evaluate by name
*/
- status = acpi_ns_evaluate_by_name (pathname, &info);
- }
- else if (!handle) {
+ status = acpi_ns_evaluate_by_name(pathname, &info);
+ } else if (!handle) {
/*
* A handle is optional iff a fully qualified pathname
* is specified. Since we've already handled fully
* qualified names above, this is an error
*/
if (!pathname) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Both Handle and Pathname are NULL\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Handle is NULL and Pathname is relative\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Both Handle and Pathname are NULL\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Handle is NULL and Pathname is relative\n"));
}
status = AE_BAD_PARAMETER;
- }
- else {
+ } else {
/*
* We get here if we have a handle -- and if we have a
* pathname it is relative. The handle will be validated
@@ -264,17 +255,15 @@ acpi_evaluate_object (
* The null pathname case means the handle is for
* the actual object to be evaluated
*/
- status = acpi_ns_evaluate_by_handle (&info);
- }
- else {
- /*
- * Both a Handle and a relative Pathname
- */
- status = acpi_ns_evaluate_relative (pathname, &info);
+ status = acpi_ns_evaluate_by_handle(&info);
+ } else {
+ /*
+ * Both a Handle and a relative Pathname
+ */
+ status = acpi_ns_evaluate_relative(pathname, &info);
}
}
-
/*
* If we are expecting a return value, and all went well above,
* copy the return value to an external object.
@@ -282,9 +271,9 @@ acpi_evaluate_object (
if (return_buffer) {
if (!info.return_object) {
return_buffer->length = 0;
- }
- else {
- if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
+ } else {
+ if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) ==
+ ACPI_DESC_TYPE_NAMED) {
/*
* If we received a NS Node as a return object, this means that
* the object we are evaluating has nothing interesting to
@@ -294,37 +283,43 @@ acpi_evaluate_object (
* support for various types at a later date if necessary.
*/
status = AE_TYPE;
- info.return_object = NULL; /* No need to delete a NS Node */
+ info.return_object = NULL; /* No need to delete a NS Node */
return_buffer->length = 0;
}
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* Find out how large a buffer is needed
* to contain the returned object
*/
- status = acpi_ut_get_object_size (info.return_object,
- &buffer_space_needed);
- if (ACPI_SUCCESS (status)) {
+ status =
+ acpi_ut_get_object_size(info.return_object,
+ &buffer_space_needed);
+ if (ACPI_SUCCESS(status)) {
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (return_buffer,
- buffer_space_needed);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_initialize_buffer
+ (return_buffer,
+ buffer_space_needed);
+ if (ACPI_FAILURE(status)) {
/*
* Caller's buffer is too small or a new one can't be allocated
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Needed buffer size %X, %s\n",
- (u32) buffer_space_needed,
- acpi_format_exception (status)));
- }
- else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Needed buffer size %X, %s\n",
+ (u32)
+ buffer_space_needed,
+ acpi_format_exception
+ (status)));
+ } else {
/*
* We have enough space for the object, build it
*/
- status = acpi_ut_copy_iobject_to_eobject (info.return_object,
- return_buffer);
+ status =
+ acpi_ut_copy_iobject_to_eobject
+ (info.return_object,
+ return_buffer);
}
}
}
@@ -336,14 +331,14 @@ acpi_evaluate_object (
* Delete the internal return object. NOTE: Interpreter
* must be locked to avoid race condition.
*/
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_SUCCESS (status2)) {
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_SUCCESS(status2)) {
/*
* Delete the internal return object. (Or at least
* decrement the reference count by one)
*/
- acpi_ut_remove_reference (info.return_object);
- acpi_ex_exit_interpreter ();
+ acpi_ut_remove_reference(info.return_object);
+ acpi_ex_exit_interpreter();
}
}
@@ -353,13 +348,13 @@ acpi_evaluate_object (
if (info.parameters) {
/* Free the allocated parameter block */
- acpi_ut_delete_internal_object_list (info.parameters);
+ acpi_ut_delete_internal_object_list(info.parameters);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_evaluate_object);
+EXPORT_SYMBOL(acpi_evaluate_object);
/*******************************************************************************
*
@@ -392,26 +387,20 @@ EXPORT_SYMBOL(acpi_evaluate_object);
******************************************************************************/
acpi_status
-acpi_walk_namespace (
- acpi_object_type type,
- acpi_handle start_object,
- u32 max_depth,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_walk_namespace(acpi_object_type type,
+ acpi_handle start_object,
+ u32 max_depth,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_walk_namespace");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_walk_namespace");
/* Parameter validation */
- if ((type > ACPI_TYPE_EXTERNAL_MAX) ||
- (!max_depth) ||
- (!user_function)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((type > ACPI_TYPE_EXTERNAL_MAX) || (!max_depth) || (!user_function)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -420,20 +409,20 @@ acpi_walk_namespace (
* to the user function - since this function
* must be allowed to make Acpi calls itself.
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ns_walk_namespace (type, start_object, max_depth,
- ACPI_NS_WALK_UNLOCK,
- user_function, context, return_value);
+ status = acpi_ns_walk_namespace(type, start_object, max_depth,
+ ACPI_NS_WALK_UNLOCK,
+ user_function, context, return_value);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_namespace);
+EXPORT_SYMBOL(acpi_walk_namespace);
/*******************************************************************************
*
@@ -450,29 +439,26 @@ EXPORT_SYMBOL(acpi_walk_namespace);
******************************************************************************/
static acpi_status
-acpi_ns_get_device_callback (
- acpi_handle obj_handle,
- u32 nesting_level,
- void *context,
- void **return_value)
+acpi_ns_get_device_callback(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
{
- struct acpi_get_devices_info *info = context;
- acpi_status status;
- struct acpi_namespace_node *node;
- u32 flags;
- struct acpi_device_id hid;
+ struct acpi_get_devices_info *info = context;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ u32 flags;
+ struct acpi_device_id hid;
struct acpi_compatible_id_list *cid;
- acpi_native_uint i;
-
+ acpi_native_uint i;
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (obj_handle);
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ node = acpi_ns_map_handle_to_node(obj_handle);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -482,8 +468,8 @@ acpi_ns_get_device_callback (
/* Run _STA to determine if device is present */
- status = acpi_ut_execute_STA (node, &flags);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_execute_STA(node, &flags);
+ if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
@@ -496,44 +482,43 @@ acpi_ns_get_device_callback (
/* Filter based on device HID & CID */
if (info->hid != NULL) {
- status = acpi_ut_execute_HID (node, &hid);
+ status = acpi_ut_execute_HID(node, &hid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
+ } else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
- if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) {
+ if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
/* Get the list of Compatible IDs */
- status = acpi_ut_execute_CID (node, &cid);
+ status = acpi_ut_execute_CID(node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
- }
- else if (ACPI_FAILURE (status)) {
+ } else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
/* Walk the CID list */
for (i = 0; i < cid->count; i++) {
- if (ACPI_STRNCMP (cid->id[i].value, info->hid,
- sizeof (struct acpi_compatible_id)) != 0) {
- ACPI_MEM_FREE (cid);
+ if (ACPI_STRNCMP(cid->id[i].value, info->hid,
+ sizeof(struct
+ acpi_compatible_id)) !=
+ 0) {
+ ACPI_MEM_FREE(cid);
return (AE_OK);
}
}
- ACPI_MEM_FREE (cid);
+ ACPI_MEM_FREE(cid);
}
}
- status = info->user_function (obj_handle, nesting_level, info->context,
- return_value);
+ status = info->user_function(obj_handle, nesting_level, info->context,
+ return_value);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_devices
@@ -560,32 +545,28 @@ acpi_ns_get_device_callback (
******************************************************************************/
acpi_status
-acpi_get_devices (
- char *HID,
- acpi_walk_callback user_function,
- void *context,
- void **return_value)
+acpi_get_devices(char *HID,
+ acpi_walk_callback user_function,
+ void *context, void **return_value)
{
- acpi_status status;
- struct acpi_get_devices_info info;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_devices");
+ acpi_status status;
+ struct acpi_get_devices_info info;
+ ACPI_FUNCTION_TRACE("acpi_get_devices");
/* Parameter validation */
if (!user_function) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
- info.context = context;
+ info.context = context;
info.user_function = user_function;
- info.hid = HID;
+ info.hid = HID;
/*
* Lock the namespace around the walk.
@@ -593,22 +574,22 @@ acpi_get_devices (
* to the user function - since this function
* must be allowed to make Acpi calls itself.
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK,
- acpi_ns_get_device_callback, &info,
- return_value);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE,
+ ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK,
+ acpi_ns_get_device_callback, &info,
+ return_value);
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (status);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_devices);
+EXPORT_SYMBOL(acpi_get_devices);
/*******************************************************************************
*
@@ -625,44 +606,38 @@ EXPORT_SYMBOL(acpi_get_devices);
******************************************************************************/
acpi_status
-acpi_attach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void *data)
+acpi_attach_data(acpi_handle obj_handle,
+ acpi_object_handler handler, void *data)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler ||
- !data) {
+ if (!obj_handle || !handler || !data) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_attach_data (node, handler, data);
+ status = acpi_ns_attach_data(node, handler, data);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_detach_data
@@ -677,42 +652,37 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_detach_data (
- acpi_handle obj_handle,
- acpi_object_handler handler)
+acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler) {
+ if (!obj_handle || !handler) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_detach_data (node, handler);
+ status = acpi_ns_detach_data(node, handler);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_data
@@ -728,41 +698,33 @@ unlock_and_exit:
******************************************************************************/
acpi_status
-acpi_get_data (
- acpi_handle obj_handle,
- acpi_object_handler handler,
- void **data)
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter validation */
- if (!obj_handle ||
- !handler ||
- !data) {
+ if (!obj_handle || !handler || !data) {
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- status = acpi_ns_get_attached_data (node, handler, data);
+ status = acpi_ns_get_attached_data(node, handler, data);
-unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-
-
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 8d097914c49a..6b5f8d4481d1 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -47,10 +47,8 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfname")
-
+ACPI_MODULE_NAME("nsxfname")
/******************************************************************************
*
@@ -69,20 +67,15 @@
* namespace handle.
*
******************************************************************************/
-
acpi_status
-acpi_get_handle (
- acpi_handle parent,
- acpi_string pathname,
- acpi_handle *ret_handle)
+acpi_get_handle(acpi_handle parent,
+ acpi_string pathname, acpi_handle * ret_handle)
{
- acpi_status status;
- struct acpi_namespace_node *node = NULL;
- struct acpi_namespace_node *prefix_node = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ struct acpi_namespace_node *node = NULL;
+ struct acpi_namespace_node *prefix_node = NULL;
+ ACPI_FUNCTION_ENTRY();
/* Parameter Validation */
@@ -93,45 +86,47 @@ acpi_get_handle (
/* Convert a parent handle to a prefix node */
if (parent) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- prefix_node = acpi_ns_map_handle_to_node (parent);
+ prefix_node = acpi_ns_map_handle_to_node(parent);
if (!prefix_node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
}
/* Special case for root, since we can't search for it */
- if (ACPI_STRCMP (pathname, ACPI_NS_ROOT_PATH) == 0) {
- *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node);
+ if (ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH) == 0) {
+ *ret_handle =
+ acpi_ns_convert_entry_to_handle(acpi_gbl_root_node);
return (AE_OK);
}
/*
* Find the Node and convert to a handle
*/
- status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
- &node);
+ status =
+ acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
+ &node);
*ret_handle = NULL;
- if (ACPI_SUCCESS (status)) {
- *ret_handle = acpi_ns_convert_entry_to_handle (node);
+ if (ACPI_SUCCESS(status)) {
+ *ret_handle = acpi_ns_convert_entry_to_handle(node);
}
return (status);
}
-EXPORT_SYMBOL(acpi_get_handle);
+EXPORT_SYMBOL(acpi_get_handle);
/******************************************************************************
*
@@ -150,14 +145,10 @@ EXPORT_SYMBOL(acpi_get_handle);
******************************************************************************/
acpi_status
-acpi_get_name (
- acpi_handle handle,
- u32 name_type,
- struct acpi_buffer *buffer)
+acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
/* Parameter validation */
@@ -165,15 +156,15 @@ acpi_get_name (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_validate_buffer(buffer);
+ if (ACPI_FAILURE(status)) {
return (status);
}
if (name_type == ACPI_FULL_PATHNAME) {
/* Get the full pathname (From the namespace root) */
- status = acpi_ns_handle_to_pathname (handle, buffer);
+ status = acpi_ns_handle_to_pathname(handle, buffer);
return (status);
}
@@ -181,12 +172,12 @@ acpi_get_name (
* Wants the single segment ACPI name.
* Validate handle and convert to a namespace Node
*/
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -194,26 +185,25 @@ acpi_get_name (
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, ACPI_PATH_SEGMENT_LENGTH);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
+ if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/* Just copy the ACPI name from the Node and zero terminate it */
- ACPI_STRNCPY (buffer->pointer, acpi_ut_get_node_name (node),
- ACPI_NAME_SIZE);
- ((char *) buffer->pointer) [ACPI_NAME_SIZE] = 0;
+ ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
+ ACPI_NAME_SIZE);
+ ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
status = AE_OK;
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_name);
+EXPORT_SYMBOL(acpi_get_name);
/******************************************************************************
*
@@ -231,17 +221,14 @@ EXPORT_SYMBOL(acpi_get_name);
******************************************************************************/
acpi_status
-acpi_get_object_info (
- acpi_handle handle,
- struct acpi_buffer *buffer)
+acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- struct acpi_device_info *info;
- struct acpi_device_info *return_info;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ struct acpi_device_info *info;
+ struct acpi_device_info *return_info;
struct acpi_compatible_id_list *cid_list = NULL;
- acpi_size size;
-
+ acpi_size size;
/* Parameter validation */
@@ -249,37 +236,37 @@ acpi_get_object_info (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_validate_buffer(buffer);
+ if (ACPI_FAILURE(status)) {
return (status);
}
- info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_device_info));
+ info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
goto cleanup;
}
/* Init return structure */
- size = sizeof (struct acpi_device_info);
+ size = sizeof(struct acpi_device_info);
- info->type = node->type;
- info->name = node->name.integer;
+ info->type = node->type;
+ info->name = node->name.integer;
info->valid = 0;
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -297,73 +284,73 @@ acpi_get_object_info (
/* Execute the Device._HID method */
- status = acpi_ut_execute_HID (node, &info->hardware_id);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_HID(node, &info->hardware_id);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
- status = acpi_ut_execute_UID (node, &info->unique_id);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_UID(node, &info->unique_id);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_UID;
}
/* Execute the Device._CID method */
- status = acpi_ut_execute_CID (node, &cid_list);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_CID(node, &cid_list);
+ if (ACPI_SUCCESS(status)) {
size += ((acpi_size) cid_list->count - 1) *
- sizeof (struct acpi_compatible_id);
+ sizeof(struct acpi_compatible_id);
info->valid |= ACPI_VALID_CID;
}
/* Execute the Device._STA method */
- status = acpi_ut_execute_STA (node, &info->current_status);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_STA(node, &info->current_status);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_STA;
}
/* Execute the Device._ADR method */
- status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
- &info->address);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
+ &info->address);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_ADR;
}
/* Execute the Device._sx_d methods */
- status = acpi_ut_execute_sxds (node, info->highest_dstates);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ut_execute_sxds(node, info->highest_dstates);
+ if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_SXDS;
}
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (buffer, size);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_initialize_buffer(buffer, size);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Populate the return buffer */
return_info = buffer->pointer;
- ACPI_MEMCPY (return_info, info, sizeof (struct acpi_device_info));
+ ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info));
if (cid_list) {
- ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
+ ACPI_MEMCPY(&return_info->compatibility_id, cid_list,
+ cid_list->size);
}
-
-cleanup:
- ACPI_MEM_FREE (info);
+ cleanup:
+ ACPI_MEM_FREE(info);
if (cid_list) {
- ACPI_MEM_FREE (cid_list);
+ ACPI_MEM_FREE(cid_list);
}
return (status);
}
-EXPORT_SYMBOL(acpi_get_object_info);
+EXPORT_SYMBOL(acpi_get_object_info);
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index 363e1f6cfb18..0856d42e6909 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -47,9 +47,8 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_NAMESPACE
- ACPI_MODULE_NAME ("nsxfobj")
+ACPI_MODULE_NAME("nsxfobj")
/*******************************************************************************
*
@@ -63,15 +62,10 @@
* DESCRIPTION: This routine returns the type associatd with a particular handle
*
******************************************************************************/
-
-acpi_status
-acpi_get_type (
- acpi_handle handle,
- acpi_object_type *ret_type)
+acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
/* Parameter Validation */
@@ -88,27 +82,26 @@ acpi_get_type (
return (AE_OK);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
*ret_type = node->type;
-
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_type);
+EXPORT_SYMBOL(acpi_get_type);
/*******************************************************************************
*
@@ -124,14 +117,10 @@ EXPORT_SYMBOL(acpi_get_type);
*
******************************************************************************/
-acpi_status
-acpi_get_parent (
- acpi_handle handle,
- acpi_handle *ret_handle)
+acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
{
- struct acpi_namespace_node *node;
- acpi_status status;
-
+ struct acpi_namespace_node *node;
+ acpi_status status;
if (!ret_handle) {
return (AE_BAD_PARAMETER);
@@ -143,14 +132,14 @@ acpi_get_parent (
return (AE_NULL_ENTRY);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
/* Convert and validate the handle */
- node = acpi_ns_map_handle_to_node (handle);
+ node = acpi_ns_map_handle_to_node(handle);
if (!node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -159,22 +148,21 @@ acpi_get_parent (
/* Get the parent entry */
*ret_handle =
- acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node));
+ acpi_ns_convert_entry_to_handle(acpi_ns_get_parent_node(node));
/* Return exception if parent is null */
- if (!acpi_ns_get_parent_node (node)) {
+ if (!acpi_ns_get_parent_node(node)) {
status = AE_NULL_ENTRY;
}
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
-EXPORT_SYMBOL(acpi_get_parent);
+EXPORT_SYMBOL(acpi_get_parent);
/*******************************************************************************
*
@@ -195,17 +183,14 @@ EXPORT_SYMBOL(acpi_get_parent);
******************************************************************************/
acpi_status
-acpi_get_next_object (
- acpi_object_type type,
- acpi_handle parent,
- acpi_handle child,
- acpi_handle *ret_handle)
+acpi_get_next_object(acpi_object_type type,
+ acpi_handle parent,
+ acpi_handle child, acpi_handle * ret_handle)
{
- acpi_status status;
- struct acpi_namespace_node *node;
- struct acpi_namespace_node *parent_node = NULL;
- struct acpi_namespace_node *child_node = NULL;
-
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ struct acpi_namespace_node *parent_node = NULL;
+ struct acpi_namespace_node *child_node = NULL;
/* Parameter validation */
@@ -213,8 +198,8 @@ acpi_get_next_object (
return (AE_BAD_PARAMETER);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return (status);
}
@@ -223,17 +208,16 @@ acpi_get_next_object (
if (!child) {
/* Start search at the beginning of the specified scope */
- parent_node = acpi_ns_map_handle_to_node (parent);
+ parent_node = acpi_ns_map_handle_to_node(parent);
if (!parent_node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- }
- else {
+ } else {
/* Non-null handle, ignore the parent */
/* Convert and validate the handle */
- child_node = acpi_ns_map_handle_to_node (child);
+ child_node = acpi_ns_map_handle_to_node(child);
if (!child_node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
@@ -242,20 +226,19 @@ acpi_get_next_object (
/* Internal function does the real work */
- node = acpi_ns_get_next_node (type, parent_node, child_node);
+ node = acpi_ns_get_next_node(type, parent_node, child_node);
if (!node) {
status = AE_NOT_FOUND;
goto unlock_and_exit;
}
if (ret_handle) {
- *ret_handle = acpi_ns_convert_entry_to_handle (node);
+ *ret_handle = acpi_ns_convert_entry_to_handle(node);
}
+ unlock_and_exit:
-unlock_and_exit:
-
- (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a82834b32752..64b98e82feb7 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -34,16 +34,18 @@
#define ACPI_NUMA 0x80000000
#define _COMPONENT ACPI_NUMA
- ACPI_MODULE_NAME ("numa")
+ACPI_MODULE_NAME("numa")
-extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries);
+extern int __init acpi_table_parse_madt_family(enum acpi_table_id id,
+ unsigned long madt_size,
+ int entry_id,
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries);
-void __init
-acpi_table_print_srat_entry (
- acpi_table_entry_header *header)
+void __init acpi_table_print_srat_entry(acpi_table_entry_header * header)
{
- ACPI_FUNCTION_NAME ("acpi_table_print_srat_entry");
+ ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
if (!header)
return;
@@ -52,48 +54,55 @@ acpi_table_print_srat_entry (
case ACPI_SRAT_PROCESSOR_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
- {
- struct acpi_table_processor_affinity *p =
- (struct acpi_table_processor_affinity*) header;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
- p->apic_id, p->lsapic_eid, p->proximity_domain,
- p->flags.enabled?"enabled":"disabled"));
- }
-#endif /* ACPI_DEBUG_OUTPUT */
+ {
+ struct acpi_table_processor_affinity *p =
+ (struct acpi_table_processor_affinity *)header;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
+ p->apic_id, p->lsapic_eid,
+ p->proximity_domain,
+ p->flags.
+ enabled ? "enabled" : "disabled"));
+ }
+#endif /* ACPI_DEBUG_OUTPUT */
break;
case ACPI_SRAT_MEMORY_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
- {
- struct acpi_table_memory_affinity *p =
- (struct acpi_table_memory_affinity*) header;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
- p->base_addr_hi, p->base_addr_lo, p->length_hi, p->length_lo,
- p->memory_type, p->proximity_domain,
- p->flags.enabled ? "enabled" : "disabled",
- p->flags.hot_pluggable ? " hot-pluggable" : ""));
- }
-#endif /* ACPI_DEBUG_OUTPUT */
+ {
+ struct acpi_table_memory_affinity *p =
+ (struct acpi_table_memory_affinity *)header;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
+ p->base_addr_hi, p->base_addr_lo,
+ p->length_hi, p->length_lo,
+ p->memory_type, p->proximity_domain,
+ p->flags.
+ enabled ? "enabled" : "disabled",
+ p->flags.
+ hot_pluggable ? " hot-pluggable" :
+ ""));
+ }
+#endif /* ACPI_DEBUG_OUTPUT */
break;
default:
- printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n",
- header->type);
+ printk(KERN_WARNING PREFIX
+ "Found unsupported SRAT entry (type = 0x%x)\n",
+ header->type);
break;
}
}
-
-static int __init
-acpi_parse_slit (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_slit(unsigned long phys_addr, unsigned long size)
{
- struct acpi_table_slit *slit;
- u32 localities;
+ struct acpi_table_slit *slit;
+ u32 localities;
if (!phys_addr || !size)
return -EINVAL;
- slit = (struct acpi_table_slit *) __va(phys_addr);
+ slit = (struct acpi_table_slit *)__va(phys_addr);
/* downcast just for %llu vs %lu for i386/ia64 */
localities = (u32) slit->localities;
@@ -103,15 +112,13 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
return 0;
}
-
static int __init
-acpi_parse_processor_affinity (
- acpi_table_entry_header *header,
- const unsigned long end)
+acpi_parse_processor_affinity(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_processor_affinity *processor_affinity;
- processor_affinity = (struct acpi_table_processor_affinity*) header;
+ processor_affinity = (struct acpi_table_processor_affinity *)header;
if (!processor_affinity)
return -EINVAL;
@@ -123,15 +130,13 @@ acpi_parse_processor_affinity (
return 0;
}
-
static int __init
-acpi_parse_memory_affinity (
- acpi_table_entry_header *header,
- const unsigned long end)
+acpi_parse_memory_affinity(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_memory_affinity *memory_affinity;
- memory_affinity = (struct acpi_table_memory_affinity*) header;
+ memory_affinity = (struct acpi_table_memory_affinity *)header;
if (!memory_affinity)
return -EINVAL;
@@ -143,36 +148,30 @@ acpi_parse_memory_affinity (
return 0;
}
-
-static int __init
-acpi_parse_srat (unsigned long phys_addr, unsigned long size)
+static int __init acpi_parse_srat(unsigned long phys_addr, unsigned long size)
{
- struct acpi_table_srat *srat;
+ struct acpi_table_srat *srat;
if (!phys_addr || !size)
return -EINVAL;
- srat = (struct acpi_table_srat *) __va(phys_addr);
+ srat = (struct acpi_table_srat *)__va(phys_addr);
return 0;
}
-
int __init
-acpi_table_parse_srat (
- enum acpi_srat_entry_id id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_srat(enum acpi_srat_entry_id id,
+ acpi_madt_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
- id, handler, max_entries);
+ return acpi_table_parse_madt_family(ACPI_SRAT,
+ sizeof(struct acpi_table_srat), id,
+ handler, max_entries);
}
-
-int __init
-acpi_numa_init(void)
+int __init acpi_numa_init(void)
{
- int result;
+ int result;
/* SRAT: Static Resource Affinity Table */
result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat);
@@ -181,9 +180,7 @@ acpi_numa_init(void)
result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
acpi_parse_processor_affinity,
NR_CPUS);
- result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
- acpi_parse_memory_affinity,
- NR_NODE_MEMBLKS); // IA64 specific
+ result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific
}
/* SLIT: System Locality Information Table */
@@ -193,8 +190,7 @@ acpi_numa_init(void)
return 0;
}
-int
-acpi_get_pxm(acpi_handle h)
+int acpi_get_pxm(acpi_handle h)
{
unsigned long pxm;
acpi_status status;
@@ -207,7 +203,8 @@ acpi_get_pxm(acpi_handle h)
if (ACPI_SUCCESS(status))
return (int)pxm;
status = acpi_get_parent(handle, &phandle);
- } while(ACPI_SUCCESS(status));
+ } while (ACPI_SUCCESS(status));
return -1;
}
+
EXPORT_SYMBOL(acpi_get_pxm);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index bdd9f37f8101..d528c750a380 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -45,16 +45,12 @@
#include <linux/efi.h>
-
#define _COMPONENT ACPI_OS_SERVICES
-ACPI_MODULE_NAME ("osl")
-
+ACPI_MODULE_NAME("osl")
#define PREFIX "ACPI: "
-
-struct acpi_os_dpc
-{
- acpi_osd_exec_callback function;
- void *context;
+struct acpi_os_dpc {
+ acpi_osd_exec_callback function;
+ void *context;
};
#ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -69,9 +65,9 @@ int acpi_in_debugger;
EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
-#endif /*ENABLE_DEBUGGER*/
+#endif /*ENABLE_DEBUGGER */
-int acpi_specific_hotkey_enabled;
+int acpi_specific_hotkey_enabled = TRUE;
EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
static unsigned int acpi_irq_irq;
@@ -79,33 +75,29 @@ static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
-acpi_status
-acpi_os_initialize(void)
+acpi_status acpi_os_initialize(void)
{
return AE_OK;
}
-acpi_status
-acpi_os_initialize1(void)
+acpi_status acpi_os_initialize1(void)
{
/*
* Initialize PCI configuration space access, as we'll need to access
* it while walking the namespace (bus 0 and root bridges w/ _BBNs).
*/
-#ifdef CONFIG_ACPI_PCI
if (!raw_pci_ops) {
- printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n");
+ printk(KERN_ERR PREFIX
+ "Access to PCI configuration space unavailable\n");
return AE_NULL_ENTRY;
}
-#endif
kacpid_wq = create_singlethread_workqueue("kacpid");
BUG_ON(!kacpid_wq);
return AE_OK;
}
-acpi_status
-acpi_os_terminate(void)
+acpi_status acpi_os_terminate(void)
{
if (acpi_irq_handler) {
acpi_os_remove_interrupt_handler(acpi_irq_irq,
@@ -117,21 +109,20 @@ acpi_os_terminate(void)
return AE_OK;
}
-void
-acpi_os_printf(const char *fmt,...)
+void acpi_os_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
acpi_os_vprintf(fmt, args);
va_end(args);
}
+
EXPORT_SYMBOL(acpi_os_printf);
-void
-acpi_os_vprintf(const char *fmt, va_list args)
+void acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
-
+
vsprintf(buffer, fmt, args);
#ifdef ENABLE_DEBUGGER
@@ -145,37 +136,41 @@ acpi_os_vprintf(const char *fmt, va_list args)
#endif
}
-void *
-acpi_os_allocate(acpi_size size)
+extern int acpi_in_resume;
+void *acpi_os_allocate(acpi_size size)
{
- return kmalloc(size, GFP_KERNEL);
+ if (acpi_in_resume)
+ return kmalloc(size, GFP_ATOMIC);
+ else
+ return kmalloc(size, GFP_KERNEL);
}
-void
-acpi_os_free(void *ptr)
+void acpi_os_free(void *ptr)
{
kfree(ptr);
}
+
EXPORT_SYMBOL(acpi_os_free);
-acpi_status
-acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
+acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
{
if (efi_enabled) {
addr->pointer_type = ACPI_PHYSICAL_POINTER;
if (efi.acpi20)
addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi20);
+ (acpi_physical_address) virt_to_phys(efi.acpi20);
else if (efi.acpi)
addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi);
+ (acpi_physical_address) virt_to_phys(efi.acpi);
else {
- printk(KERN_ERR PREFIX "System description tables not found\n");
+ printk(KERN_ERR PREFIX
+ "System description tables not found\n");
return AE_NOT_FOUND;
}
} else {
if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
- printk(KERN_ERR PREFIX "System description tables not found\n");
+ printk(KERN_ERR PREFIX
+ "System description tables not found\n");
return AE_NOT_FOUND;
}
}
@@ -184,11 +179,12 @@ acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
}
acpi_status
-acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
+ void __iomem ** virt)
{
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
- *virt = (void __iomem *) phys_to_virt(phys);
+ *virt = (void __iomem *)phys_to_virt(phys);
} else {
*virt = ioremap(phys, size);
}
@@ -198,9 +194,9 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **vi
return AE_BAD_PARAMETER;
}
/*
- * ioremap checks to ensure this is in reserved space
- */
- *virt = ioremap((unsigned long) phys, size);
+ * ioremap checks to ensure this is in reserved space
+ */
+ *virt = ioremap((unsigned long)phys, size);
}
if (!*virt)
@@ -209,17 +205,16 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **vi
return AE_OK;
}
-void
-acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
+void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
iounmap(virt);
}
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
+acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
{
- if(!phys || !virt)
+ if (!phys || !virt)
return AE_BAD_PARAMETER;
*phys = virt_to_phys(virt);
@@ -233,16 +228,16 @@ acpi_os_get_physical_address(void *virt, acpi_physical_address *phys)
static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
acpi_status
-acpi_os_predefined_override (const struct acpi_predefined_names *init_val,
- acpi_string *new_val)
+acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
+ acpi_string * new_val)
{
if (!init_val || !new_val)
return AE_BAD_PARAMETER;
*new_val = NULL;
- if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
+ if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
- acpi_os_name);
+ acpi_os_name);
*new_val = acpi_os_name;
}
@@ -250,15 +245,15 @@ acpi_os_predefined_override (const struct acpi_predefined_names *init_val,
}
acpi_status
-acpi_os_table_override (struct acpi_table_header *existing_table,
- struct acpi_table_header **new_table)
+acpi_os_table_override(struct acpi_table_header * existing_table,
+ struct acpi_table_header ** new_table)
{
if (!existing_table || !new_table)
return AE_BAD_PARAMETER;
#ifdef CONFIG_ACPI_CUSTOM_DSDT
if (strncmp(existing_table->signature, "DSDT", 4) == 0)
- *new_table = (struct acpi_table_header*)AmlCode;
+ *new_table = (struct acpi_table_header *)AmlCode;
else
*new_table = NULL;
#else
@@ -267,14 +262,14 @@ acpi_os_table_override (struct acpi_table_header *existing_table,
return AE_OK;
}
-static irqreturn_t
-acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
+ return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
}
acpi_status
-acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context)
+acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
+ void *context)
{
unsigned int irq;
@@ -301,8 +296,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *conte
return AE_OK;
}
-acpi_status
-acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
+acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
{
if (irq) {
free_irq(irq, acpi_irq);
@@ -317,16 +311,15 @@ acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
* Running in interpreter thread context, safe to sleep
*/
-void
-acpi_os_sleep(acpi_integer ms)
+void acpi_os_sleep(acpi_integer ms)
{
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(((signed long) ms * HZ) / 1000);
+ schedule_timeout(((signed long)ms * HZ) / 1000);
}
+
EXPORT_SYMBOL(acpi_os_sleep);
-void
-acpi_os_stall(u32 us)
+void acpi_os_stall(u32 us)
{
while (us) {
u32 delay = 1000;
@@ -338,6 +331,7 @@ acpi_os_stall(u32 us)
us -= delay;
}
}
+
EXPORT_SYMBOL(acpi_os_stall);
/*
@@ -345,8 +339,7 @@ EXPORT_SYMBOL(acpi_os_stall);
* Returns 64-bit free-running, monotonically increasing timer
* with 100ns granularity
*/
-u64
-acpi_os_get_timer (void)
+u64 acpi_os_get_timer(void)
{
static u64 t;
@@ -363,27 +356,22 @@ acpi_os_get_timer (void)
return ++t;
}
-acpi_status
-acpi_os_read_port(
- acpi_io_address port,
- u32 *value,
- u32 width)
+acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
{
u32 dummy;
if (!value)
value = &dummy;
- switch (width)
- {
+ switch (width) {
case 8:
- *(u8*) value = inb(port);
+ *(u8 *) value = inb(port);
break;
case 16:
- *(u16*) value = inw(port);
+ *(u16 *) value = inw(port);
break;
case 32:
- *(u32*) value = inl(port);
+ *(u32 *) value = inl(port);
break;
default:
BUG();
@@ -391,16 +379,12 @@ acpi_os_read_port(
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_read_port);
-acpi_status
-acpi_os_write_port(
- acpi_io_address port,
- u32 value,
- u32 width)
+acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{
- switch (width)
- {
+ switch (width) {
case 8:
outb(value, port);
break;
@@ -416,40 +400,38 @@ acpi_os_write_port(
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_write_port);
acpi_status
-acpi_os_read_memory(
- acpi_physical_address phys_addr,
- u32 *value,
- u32 width)
+acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
{
- u32 dummy;
- void __iomem *virt_addr;
- int iomem = 0;
+ u32 dummy;
+ void __iomem *virt_addr;
+ int iomem = 0;
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
/* HACK ALERT! We can use readb/w/l on real memory too.. */
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
} else {
iomem = 1;
virt_addr = ioremap(phys_addr, width);
}
} else
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
if (!value)
value = &dummy;
switch (width) {
case 8:
- *(u8*) value = readb(virt_addr);
+ *(u8 *) value = readb(virt_addr);
break;
case 16:
- *(u16*) value = readw(virt_addr);
+ *(u16 *) value = readw(virt_addr);
break;
case 32:
- *(u32*) value = readl(virt_addr);
+ *(u32 *) value = readl(virt_addr);
break;
default:
BUG();
@@ -464,24 +446,21 @@ acpi_os_read_memory(
}
acpi_status
-acpi_os_write_memory(
- acpi_physical_address phys_addr,
- u32 value,
- u32 width)
+acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
- void __iomem *virt_addr;
- int iomem = 0;
+ void __iomem *virt_addr;
+ int iomem = 0;
if (efi_enabled) {
if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
/* HACK ALERT! We can use writeb/w/l on real memory too */
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
} else {
iomem = 1;
virt_addr = ioremap(phys_addr, width);
}
} else
- virt_addr = (void __iomem *) phys_to_virt(phys_addr);
+ virt_addr = (void __iomem *)phys_to_virt(phys_addr);
switch (width) {
case 8:
@@ -503,10 +482,9 @@ acpi_os_write_memory(
return AE_OK;
}
-#ifdef CONFIG_ACPI_PCI
-
acpi_status
-acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width)
+acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+ void *value, u32 width)
{
int result, size;
@@ -530,15 +508,17 @@ acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value
BUG_ON(!raw_pci_ops);
result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
- PCI_DEVFN(pci_id->device, pci_id->function),
- reg, size, value);
+ PCI_DEVFN(pci_id->device, pci_id->function),
+ reg, size, value);
return (result ? AE_ERROR : AE_OK);
}
+
EXPORT_SYMBOL(acpi_os_read_pci_configuration);
acpi_status
-acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width)
+acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
+ acpi_integer value, u32 width)
{
int result, size;
@@ -559,56 +539,62 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ
BUG_ON(!raw_pci_ops);
result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
- PCI_DEVFN(pci_id->device, pci_id->function),
- reg, size, value);
+ PCI_DEVFN(pci_id->device, pci_id->function),
+ reg, size, value);
return (result ? AE_ERROR : AE_OK);
}
/* TODO: Change code to take advantage of driver model more */
-static void
-acpi_os_derive_pci_id_2 (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id,
- int *is_bridge,
- u8 *bus_number)
+static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
+ acpi_handle chandle, /* current node */
+ struct acpi_pci_id **id,
+ int *is_bridge, u8 * bus_number)
{
- acpi_handle handle;
- struct acpi_pci_id *pci_id = *id;
- acpi_status status;
- unsigned long temp;
- acpi_object_type type;
- u8 tu8;
+ acpi_handle handle;
+ struct acpi_pci_id *pci_id = *id;
+ acpi_status status;
+ unsigned long temp;
+ acpi_object_type type;
+ u8 tu8;
acpi_get_parent(chandle, &handle);
if (handle != rhandle) {
- acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number);
+ acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
+ bus_number);
status = acpi_get_type(handle, &type);
- if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) )
+ if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
return;
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp);
+ status =
+ acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
+ &temp);
if (ACPI_SUCCESS(status)) {
- pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp));
- pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp));
+ pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
+ pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
if (*is_bridge)
pci_id->bus = *bus_number;
/* any nicer way to get bus number of bridge ? */
- status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8);
- if (ACPI_SUCCESS(status) &&
- ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
- status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8);
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
+ 8);
+ if (ACPI_SUCCESS(status)
+ && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x18,
+ &tu8, 8);
if (!ACPI_SUCCESS(status)) {
/* Certainly broken... FIX ME */
return;
}
*is_bridge = 1;
pci_id->bus = tu8;
- status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8);
+ status =
+ acpi_os_read_pci_configuration(pci_id, 0x19,
+ &tu8, 8);
if (ACPI_SUCCESS(status)) {
*bus_number = tu8;
}
@@ -618,11 +604,9 @@ acpi_os_derive_pci_id_2 (
}
}
-void
-acpi_os_derive_pci_id (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id)
+void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
+ acpi_handle chandle, /* current node */
+ struct acpi_pci_id **id)
{
int is_bridge = 1;
u8 bus_number = (*id)->bus;
@@ -630,49 +614,15 @@ acpi_os_derive_pci_id (
acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
}
-#else /*!CONFIG_ACPI_PCI*/
-
-acpi_status
-acpi_os_write_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- acpi_integer value,
- u32 width)
-{
- return AE_SUPPORT;
-}
-
-acpi_status
-acpi_os_read_pci_configuration (
- struct acpi_pci_id *pci_id,
- u32 reg,
- void *value,
- u32 width)
-{
- return AE_SUPPORT;
-}
-
-void
-acpi_os_derive_pci_id (
- acpi_handle rhandle, /* upper bound */
- acpi_handle chandle, /* current node */
- struct acpi_pci_id **id)
+static void acpi_os_execute_deferred(void *context)
{
-}
-
-#endif /*CONFIG_ACPI_PCI*/
+ struct acpi_os_dpc *dpc = NULL;
-static void
-acpi_os_execute_deferred (
- void *context)
-{
- struct acpi_os_dpc *dpc = NULL;
+ ACPI_FUNCTION_TRACE("os_execute_deferred");
- ACPI_FUNCTION_TRACE ("os_execute_deferred");
-
- dpc = (struct acpi_os_dpc *) context;
+ dpc = (struct acpi_os_dpc *)context;
if (!dpc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
return_VOID;
}
@@ -684,21 +634,21 @@ acpi_os_execute_deferred (
}
acpi_status
-acpi_os_queue_for_execution(
- u32 priority,
- acpi_osd_exec_callback function,
- void *context)
+acpi_os_queue_for_execution(u32 priority,
+ acpi_osd_exec_callback function, void *context)
{
- acpi_status status = AE_OK;
- struct acpi_os_dpc *dpc;
- struct work_struct *task;
+ acpi_status status = AE_OK;
+ struct acpi_os_dpc *dpc;
+ struct work_struct *task;
- ACPI_FUNCTION_TRACE ("os_queue_for_execution");
+ ACPI_FUNCTION_TRACE("os_queue_for_execution");
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Scheduling function [%p(%p)] for deferred execution.\n",
+ function, context));
if (!function)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
/*
* Allocate/initialize DPC structure. Note that this memory will be
@@ -711,146 +661,94 @@ acpi_os_queue_for_execution(
* from the same memory.
*/
- dpc = kmalloc(sizeof(struct acpi_os_dpc)+sizeof(struct work_struct), GFP_ATOMIC);
+ dpc =
+ kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
+ GFP_ATOMIC);
if (!dpc)
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
dpc->function = function;
dpc->context = context;
- task = (void *)(dpc+1);
- INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
+ task = (void *)(dpc + 1);
+ INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
if (!queue_work(kacpid_wq, task)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Call to queue_work() failed.\n"));
kfree(dpc);
status = AE_ERROR;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
+
EXPORT_SYMBOL(acpi_os_queue_for_execution);
-void
-acpi_os_wait_events_complete(
- void *context)
+void acpi_os_wait_events_complete(void *context)
{
flush_workqueue(kacpid_wq);
}
+
EXPORT_SYMBOL(acpi_os_wait_events_complete);
/*
* Allocate the memory for a spinlock and initialize it.
*/
-acpi_status
-acpi_os_create_lock (
- acpi_handle *out_handle)
+acpi_status acpi_os_create_lock(acpi_handle * out_handle)
{
spinlock_t *lock_ptr;
- ACPI_FUNCTION_TRACE ("os_create_lock");
+ ACPI_FUNCTION_TRACE("os_create_lock");
lock_ptr = acpi_os_allocate(sizeof(spinlock_t));
spin_lock_init(lock_ptr);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
*out_handle = lock_ptr;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*
* Deallocate the memory for a spinlock.
*/
-void
-acpi_os_delete_lock (
- acpi_handle handle)
+void acpi_os_delete_lock(acpi_handle handle)
{
- ACPI_FUNCTION_TRACE ("os_create_lock");
+ ACPI_FUNCTION_TRACE("os_create_lock");
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
acpi_os_free(handle);
return_VOID;
}
-/*
- * Acquire a spinlock.
- *
- * handle is a pointer to the spinlock_t.
- * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
- * that indicates whether we are at interrupt level.
- */
-void
-acpi_os_acquire_lock (
- acpi_handle handle,
- u32 flags)
-{
- ACPI_FUNCTION_TRACE ("os_acquire_lock");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle,
- ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
-
- if (flags & ACPI_NOT_ISR)
- ACPI_DISABLE_IRQS();
-
- spin_lock((spinlock_t *)handle);
-
- return_VOID;
-}
-
-
-/*
- * Release a spinlock. See above.
- */
-void
-acpi_os_release_lock (
- acpi_handle handle,
- u32 flags)
-{
- ACPI_FUNCTION_TRACE ("os_release_lock");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle,
- ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
-
- spin_unlock((spinlock_t *)handle);
-
- if (flags & ACPI_NOT_ISR)
- ACPI_ENABLE_IRQS();
-
- return_VOID;
-}
-
-
acpi_status
-acpi_os_create_semaphore(
- u32 max_units,
- u32 initial_units,
- acpi_handle *handle)
+acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
{
- struct semaphore *sem = NULL;
+ struct semaphore *sem = NULL;
- ACPI_FUNCTION_TRACE ("os_create_semaphore");
+ ACPI_FUNCTION_TRACE("os_create_semaphore");
sem = acpi_os_allocate(sizeof(struct semaphore));
if (!sem)
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
memset(sem, 0, sizeof(struct semaphore));
sema_init(sem, initial_units);
- *handle = (acpi_handle*)sem;
+ *handle = (acpi_handle *) sem;
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
+ *handle, initial_units));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_os_create_semaphore);
+EXPORT_SYMBOL(acpi_os_create_semaphore);
/*
* TODO: A better way to delete semaphores? Linux doesn't have a
@@ -859,25 +757,24 @@ EXPORT_SYMBOL(acpi_os_create_semaphore);
* we at least check for blocked threads and signal/cancel them?
*/
-acpi_status
-acpi_os_delete_semaphore(
- acpi_handle handle)
+acpi_status acpi_os_delete_semaphore(acpi_handle handle)
{
- struct semaphore *sem = (struct semaphore*) handle;
+ struct semaphore *sem = (struct semaphore *)handle;
- ACPI_FUNCTION_TRACE ("os_delete_semaphore");
+ ACPI_FUNCTION_TRACE("os_delete_semaphore");
if (!sem)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
- acpi_os_free(sem); sem = NULL;
+ acpi_os_free(sem);
+ sem = NULL;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_os_delete_semaphore);
+EXPORT_SYMBOL(acpi_os_delete_semaphore);
/*
* TODO: The kernel doesn't have a 'down_timeout' function -- had to
@@ -888,31 +785,27 @@ EXPORT_SYMBOL(acpi_os_delete_semaphore);
*
* TODO: Support for units > 1?
*/
-acpi_status
-acpi_os_wait_semaphore(
- acpi_handle handle,
- u32 units,
- u16 timeout)
+acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
{
- acpi_status status = AE_OK;
- struct semaphore *sem = (struct semaphore*)handle;
- int ret = 0;
+ acpi_status status = AE_OK;
+ struct semaphore *sem = (struct semaphore *)handle;
+ int ret = 0;
- ACPI_FUNCTION_TRACE ("os_wait_semaphore");
+ ACPI_FUNCTION_TRACE("os_wait_semaphore");
if (!sem || (units < 1))
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
if (units > 1)
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
+ handle, units, timeout));
if (in_atomic())
timeout = 0;
- switch (timeout)
- {
+ switch (timeout) {
/*
* No Wait:
* --------
@@ -920,8 +813,8 @@ acpi_os_wait_semaphore(
* acquire the semaphore if available otherwise return AE_TIME
* (a.k.a. 'would block').
*/
- case 0:
- if(down_trylock(sem))
+ case 0:
+ if (down_trylock(sem))
status = AE_TIME;
break;
@@ -929,7 +822,7 @@ acpi_os_wait_semaphore(
* Wait Indefinitely:
* ------------------
*/
- case ACPI_WAIT_FOREVER:
+ case ACPI_WAIT_FOREVER:
down(sem);
break;
@@ -937,11 +830,11 @@ acpi_os_wait_semaphore(
* Wait w/ Timeout:
* ----------------
*/
- default:
+ default:
// TODO: A better timeout algorithm?
{
int i = 0;
- static const int quantum_ms = 1000/HZ;
+ static const int quantum_ms = 1000 / HZ;
ret = down_trylock(sem);
for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
@@ -949,7 +842,7 @@ acpi_os_wait_semaphore(
schedule_timeout(1);
ret = down_trylock(sem);
}
-
+
if (ret != 0)
status = AE_TIME;
}
@@ -957,47 +850,48 @@ acpi_os_wait_semaphore(
}
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n",
- handle, units, timeout, acpi_format_exception(status)));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Failed to acquire semaphore[%p|%d|%d], %s\n",
+ handle, units, timeout,
+ acpi_format_exception(status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Acquired semaphore[%p|%d|%d]\n", handle,
+ units, timeout));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_os_wait_semaphore);
+EXPORT_SYMBOL(acpi_os_wait_semaphore);
/*
* TODO: Support for units > 1?
*/
-acpi_status
-acpi_os_signal_semaphore(
- acpi_handle handle,
- u32 units)
+acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
{
- struct semaphore *sem = (struct semaphore *) handle;
+ struct semaphore *sem = (struct semaphore *)handle;
- ACPI_FUNCTION_TRACE ("os_signal_semaphore");
+ ACPI_FUNCTION_TRACE("os_signal_semaphore");
if (!sem || (units < 1))
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
if (units > 1)
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units));
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
+ units));
up(sem);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
+
EXPORT_SYMBOL(acpi_os_signal_semaphore);
#ifdef ACPI_FUTURE_USAGE
-u32
-acpi_os_get_line(char *buffer)
+u32 acpi_os_get_line(char *buffer)
{
#ifdef ENABLE_DEBUGGER
@@ -1014,22 +908,21 @@ acpi_os_get_line(char *buffer)
return 0;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/* Assumes no unreadable holes inbetween */
-u8
-acpi_os_readable(void *ptr, acpi_size len)
+u8 acpi_os_readable(void *ptr, acpi_size len)
{
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
char tmp;
- return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);
+ return !__get_user(tmp, (char __user *)ptr)
+ && !__get_user(tmp, (char __user *)ptr + len - 1);
#endif
return 1;
}
#ifdef ACPI_FUTURE_USAGE
-u8
-acpi_os_writable(void *ptr, acpi_size len)
+u8 acpi_os_writable(void *ptr, acpi_size len)
{
/* could do dummy write (racy) or a kernel page table lookup.
The later may be difficult at early boot when kmap doesn't work yet. */
@@ -1037,8 +930,7 @@ acpi_os_writable(void *ptr, acpi_size len)
}
#endif
-u32
-acpi_os_get_thread_id (void)
+u32 acpi_os_get_thread_id(void)
{
if (!in_atomic())
return current->pid;
@@ -1046,13 +938,9 @@ acpi_os_get_thread_id (void)
return 0;
}
-acpi_status
-acpi_os_signal (
- u32 function,
- void *info)
+acpi_status acpi_os_signal(u32 function, void *info)
{
- switch (function)
- {
+ switch (function) {
case ACPI_SIGNAL_FATAL:
printk(KERN_ERR PREFIX "Fatal opcode executed\n");
break;
@@ -1072,13 +960,13 @@ acpi_os_signal (
return AE_OK;
}
+
EXPORT_SYMBOL(acpi_os_signal);
-static int __init
-acpi_os_name_setup(char *str)
+static int __init acpi_os_name_setup(char *str)
{
char *p = acpi_os_name;
- int count = ACPI_MAX_OVERRIDE_LEN-1;
+ int count = ACPI_MAX_OVERRIDE_LEN - 1;
if (!str || !*str)
return 0;
@@ -1094,7 +982,7 @@ acpi_os_name_setup(char *str)
*p = 0;
return 1;
-
+
}
__setup("acpi_os_name=", acpi_os_name_setup);
@@ -1104,16 +992,15 @@ __setup("acpi_os_name=", acpi_os_name_setup);
* empty string disables _OSI
* TBD additional string adds to _OSI
*/
-static int __init
-acpi_osi_setup(char *str)
+static int __init acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
- } else
- {
+ } else {
/* TBD */
- printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str);
+ printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
+ str);
}
return 1;
@@ -1122,8 +1009,7 @@ acpi_osi_setup(char *str)
__setup("acpi_osi=", acpi_osi_setup);
/* enable serialization to combat AE_ALREADY_EXISTS errors */
-static int __init
-acpi_serialize_setup(char *str)
+static int __init acpi_serialize_setup(char *str)
{
printk(KERN_INFO PREFIX "serialize enabled\n");
@@ -1143,8 +1029,7 @@ __setup("acpi_serialize", acpi_serialize_setup);
* Run-time events on the same GPE this flag is available
* to tell Linux to keep the wake-time GPEs enabled at run-time.
*/
-static int __init
-acpi_wake_gpes_always_on_setup(char *str)
+static int __init acpi_wake_gpes_always_on_setup(char *str)
{
printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
@@ -1155,14 +1040,13 @@ acpi_wake_gpes_always_on_setup(char *str)
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
-int __init
-acpi_hotkey_setup(char *str)
+static int __init acpi_hotkey_setup(char *str)
{
- acpi_specific_hotkey_enabled = TRUE;
+ acpi_specific_hotkey_enabled = FALSE;
return 1;
}
-__setup("acpi_specific_hotkey", acpi_hotkey_setup);
+__setup("acpi_generic_hotkey", acpi_hotkey_setup);
/*
* max_cstate is defined in the base kernel so modules can
@@ -1170,5 +1054,132 @@ __setup("acpi_specific_hotkey", acpi_hotkey_setup);
*/
unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
-
EXPORT_SYMBOL(max_cstate);
+
+/*
+ * Acquire a spinlock.
+ *
+ * handle is a pointer to the spinlock_t.
+ * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
+ * that indicates whether we are at interrupt level.
+ */
+
+unsigned long acpi_os_acquire_lock(acpi_handle handle)
+{
+ unsigned long flags;
+ spin_lock_irqsave((spinlock_t *) handle, flags);
+ return flags;
+}
+
+/*
+ * Release a spinlock. See above.
+ */
+
+void acpi_os_release_lock(acpi_handle handle, unsigned long flags)
+{
+ spin_unlock_irqrestore((spinlock_t *) handle, flags);
+}
+
+#ifndef ACPI_USE_LOCAL_CACHE
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_create_cache
+ *
+ * PARAMETERS: CacheName - Ascii name for the cache
+ * ObjectSize - Size of each cached object
+ * MaxDepth - Maximum depth of the cache (in objects)
+ * ReturnCache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
+{
+ *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
+ return AE_OK;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_purge_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
+{
+ (void)kmem_cache_shrink(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_delete_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ * cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
+{
+ (void)kmem_cache_destroy(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_release_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * Object - The object to be released
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ * the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
+{
+ kmem_cache_free(cache, object);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_acquire_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * ReturnObject - Where the object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ * the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(acpi_cache_t * cache)
+{
+ void *object = kmem_cache_alloc(cache, GFP_KERNEL);
+ WARN_ON(!object);
+ return object;
+}
+
+#endif
diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile
index bbdd286c660d..db24ee09cf11 100644
--- a/drivers/acpi/parser/Makefile
+++ b/drivers/acpi/parser/Makefile
@@ -2,7 +2,7 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
-obj-y := psargs.o psparse.o pstree.o pswalk.o \
+obj-y := psargs.o psparse.o psloop.o pstree.o pswalk.o \
psopcode.o psscope.o psutils.o psxface.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index b7ac68cc9e1c..5858188f94a6 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -41,25 +41,20 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psargs")
+ACPI_MODULE_NAME("psargs")
/* Local prototypes */
-
static u32
-acpi_ps_get_next_package_length (
- struct acpi_parse_state *parser_state);
-
-static union acpi_parse_object *
-acpi_ps_get_next_field (
- struct acpi_parse_state *parser_state);
+acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
+static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+ *parser_state);
/*******************************************************************************
*
@@ -75,49 +70,43 @@ acpi_ps_get_next_field (
******************************************************************************/
static u32
-acpi_ps_get_next_package_length (
- struct acpi_parse_state *parser_state)
+acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
{
- u32 encoded_length;
- u32 length = 0;
+ u32 encoded_length;
+ u32 length = 0;
+ ACPI_FUNCTION_TRACE("ps_get_next_package_length");
- ACPI_FUNCTION_TRACE ("ps_get_next_package_length");
-
-
- encoded_length = (u32) ACPI_GET8 (parser_state->aml);
+ encoded_length = (u32) ACPI_GET8(parser_state->aml);
parser_state->aml++;
- switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ {
- case 0: /* 1-byte encoding (bits 0-5) */
+ switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */
+ case 0: /* 1-byte encoding (bits 0-5) */
length = (encoded_length & 0x3F);
break;
+ case 1: /* 2-byte encoding (next byte + bits 0-3) */
- case 1: /* 2-byte encoding (next byte + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml++;
break;
+ case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
- case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml + 1) << 12) |
- (ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml + 1) << 12) |
+ (ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml += 2;
break;
+ case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
- case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
-
- length = ((ACPI_GET8 (parser_state->aml + 2) << 20) |
- (ACPI_GET8 (parser_state->aml + 1) << 12) |
- (ACPI_GET8 (parser_state->aml) << 04) |
- (encoded_length & 0x0F));
+ length = ((ACPI_GET8(parser_state->aml + 2) << 20) |
+ (ACPI_GET8(parser_state->aml + 1) << 12) |
+ (ACPI_GET8(parser_state->aml) << 04) |
+ (encoded_length & 0x0F));
parser_state->aml += 3;
break;
@@ -127,10 +116,9 @@ acpi_ps_get_next_package_length (
break;
}
- return_VALUE (length);
+ return_VALUE(length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_package_end
@@ -144,25 +132,21 @@ acpi_ps_get_next_package_length (
*
******************************************************************************/
-u8 *
-acpi_ps_get_next_package_end (
- struct acpi_parse_state *parser_state)
+u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
{
- u8 *start = parser_state->aml;
- acpi_native_uint length;
-
-
- ACPI_FUNCTION_TRACE ("ps_get_next_package_end");
+ u8 *start = parser_state->aml;
+ acpi_native_uint length;
+ ACPI_FUNCTION_TRACE("ps_get_next_package_end");
/* Function below changes parser_state->Aml */
- length = (acpi_native_uint) acpi_ps_get_next_package_length (parser_state);
+ length =
+ (acpi_native_uint) acpi_ps_get_next_package_length(parser_state);
- return_PTR (start + length); /* end of package */
+ return_PTR(start + length); /* end of package */
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_namestring
@@ -178,20 +162,16 @@ acpi_ps_get_next_package_end (
*
******************************************************************************/
-char *
-acpi_ps_get_next_namestring (
- struct acpi_parse_state *parser_state)
+char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
{
- u8 *start = parser_state->aml;
- u8 *end = parser_state->aml;
-
-
- ACPI_FUNCTION_TRACE ("ps_get_next_namestring");
+ u8 *start = parser_state->aml;
+ u8 *end = parser_state->aml;
+ ACPI_FUNCTION_TRACE("ps_get_next_namestring");
/* Handle multiple prefix characters */
- while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) {
+ while (acpi_ps_is_prefix_char(ACPI_GET8(end))) {
/* Include prefix '\\' or '^' */
end++;
@@ -199,7 +179,7 @@ acpi_ps_get_next_namestring (
/* Decode the path */
- switch (ACPI_GET8 (end)) {
+ switch (ACPI_GET8(end)) {
case 0:
/* null_name */
@@ -221,7 +201,7 @@ acpi_ps_get_next_namestring (
/* Multiple name segments, 4 chars each */
- end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE);
+ end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE);
break;
default:
@@ -232,11 +212,10 @@ acpi_ps_get_next_namestring (
break;
}
- parser_state->aml = (u8*) end;
- return_PTR ((char *) start);
+ parser_state->aml = (u8 *) end;
+ return_PTR((char *)start);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_namepath
@@ -259,24 +238,20 @@ acpi_ps_get_next_namestring (
******************************************************************************/
acpi_status
-acpi_ps_get_next_namepath (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *arg,
- u8 method_call)
+acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ union acpi_parse_object *arg, u8 method_call)
{
- char *path;
- union acpi_parse_object *name_op;
- acpi_status status = AE_OK;
- union acpi_operand_object *method_desc;
- struct acpi_namespace_node *node;
- union acpi_generic_state scope_info;
+ char *path;
+ union acpi_parse_object *name_op;
+ acpi_status status = AE_OK;
+ union acpi_operand_object *method_desc;
+ struct acpi_namespace_node *node;
+ union acpi_generic_state scope_info;
+ ACPI_FUNCTION_TRACE("ps_get_next_namepath");
- ACPI_FUNCTION_TRACE ("ps_get_next_namepath");
-
-
- path = acpi_ps_get_next_namestring (parser_state);
+ path = acpi_ps_get_next_namestring(parser_state);
/* Null path case is allowed */
@@ -296,49 +271,50 @@ acpi_ps_get_next_namepath (
* parent tree, but don't open a new scope -- we just want to lookup the
* object (MUST BE mode EXECUTE to perform upsearch)
*/
- status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE,
- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
- NULL, &node);
- if (ACPI_SUCCESS (status) && method_call) {
+ status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT |
+ ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
+ if (ACPI_SUCCESS(status) && method_call) {
if (node->type == ACPI_TYPE_METHOD) {
/* This name is actually a control method invocation */
- method_desc = acpi_ns_get_attached_object (node);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Control Method - %p Desc %p Path=%p\n",
- node, method_desc, path));
+ method_desc = acpi_ns_get_attached_object(node);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Desc %p Path=%p\n",
+ node, method_desc, path));
- name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
+ name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
if (!name_op) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Change arg into a METHOD CALL and attach name to it */
- acpi_ps_init_op (arg, AML_INT_METHODCALL_OP);
+ acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
name_op->common.value.name = path;
/* Point METHODCALL/NAME to the METHOD Node */
name_op->common.node = node;
- acpi_ps_append_arg (arg, name_op);
+ acpi_ps_append_arg(arg, name_op);
if (!method_desc) {
- ACPI_REPORT_ERROR ((
- "ps_get_next_namepath: Control Method %p has no attached object\n",
- node));
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node));
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Control Method - %p Args %X\n",
- node, method_desc->method.param_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Control Method - %p Args %X\n",
+ node,
+ method_desc->method.
+ param_count));
/* Get the number of arguments to expect */
- walk_state->arg_count = method_desc->method.param_count;
- return_ACPI_STATUS (AE_OK);
+ walk_state->arg_count =
+ method_desc->method.param_count;
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -348,25 +324,26 @@ acpi_ps_get_next_namepath (
*/
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/*
* 1) Any error other than NOT_FOUND is always severe
* 2) NOT_FOUND is only important if we are executing a method.
* 3) If executing a cond_ref_of opcode, NOT_FOUND is ok.
*/
- if ((((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) &&
- (status == AE_NOT_FOUND) &&
- (walk_state->op->common.aml_opcode != AML_COND_REF_OF_OP)) ||
-
- (status != AE_NOT_FOUND)) {
- ACPI_REPORT_NSERROR (path, status);
-
- acpi_os_printf ("search_node %p start_node %p return_node %p\n",
- scope_info.scope.node, parser_state->start_node, node);
-
-
- }
- else {
+ if ((((walk_state->
+ parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND)
+ && (walk_state->op->common.aml_opcode !=
+ AML_COND_REF_OF_OP))
+ || (status != AE_NOT_FOUND)) {
+ ACPI_REPORT_NSERROR(path, status);
+
+ acpi_os_printf
+ ("search_node %p start_node %p return_node %p\n",
+ scope_info.scope.node,
+ parser_state->start_node, node);
+
+ } else {
/*
* We got a NOT_FOUND during table load or we encountered
* a cond_ref_of(x) where the target does not exist.
@@ -381,13 +358,12 @@ acpi_ps_get_next_namepath (
* Regardless of success/failure above,
* Just initialize the Op with the pathname.
*/
- acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
+ acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
arg->common.value.name = path;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_simple_arg
@@ -403,87 +379,81 @@ acpi_ps_get_next_namepath (
******************************************************************************/
void
-acpi_ps_get_next_simple_arg (
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object *arg)
+acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object *arg)
{
- ACPI_FUNCTION_TRACE_U32 ("ps_get_next_simple_arg", arg_type);
-
+ ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
switch (arg_type) {
case ARGP_BYTEDATA:
- acpi_ps_init_op (arg, AML_BYTE_OP);
- arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml);
+ acpi_ps_init_op(arg, AML_BYTE_OP);
+ arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml);
parser_state->aml++;
break;
-
case ARGP_WORDDATA:
- acpi_ps_init_op (arg, AML_WORD_OP);
+ acpi_ps_init_op(arg, AML_WORD_OP);
/* Get 2 bytes from the AML stream */
- ACPI_MOVE_16_TO_32 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_16_TO_32(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 2;
break;
-
case ARGP_DWORDDATA:
- acpi_ps_init_op (arg, AML_DWORD_OP);
+ acpi_ps_init_op(arg, AML_DWORD_OP);
/* Get 4 bytes from the AML stream */
- ACPI_MOVE_32_TO_32 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_32_TO_32(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 4;
break;
-
case ARGP_QWORDDATA:
- acpi_ps_init_op (arg, AML_QWORD_OP);
+ acpi_ps_init_op(arg, AML_QWORD_OP);
/* Get 8 bytes from the AML stream */
- ACPI_MOVE_64_TO_64 (&arg->common.value.integer, parser_state->aml);
+ ACPI_MOVE_64_TO_64(&arg->common.value.integer,
+ parser_state->aml);
parser_state->aml += 8;
break;
-
case ARGP_CHARLIST:
- acpi_ps_init_op (arg, AML_STRING_OP);
- arg->common.value.string = (char *) parser_state->aml;
+ acpi_ps_init_op(arg, AML_STRING_OP);
+ arg->common.value.string = (char *)parser_state->aml;
- while (ACPI_GET8 (parser_state->aml) != '\0') {
+ while (ACPI_GET8(parser_state->aml) != '\0') {
parser_state->aml++;
}
parser_state->aml++;
break;
-
case ARGP_NAME:
case ARGP_NAMESTRING:
- acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP);
- arg->common.value.name = acpi_ps_get_next_namestring (parser_state);
+ acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
+ arg->common.value.name =
+ acpi_ps_get_next_namestring(parser_state);
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid arg_type %X\n", arg_type));
+ ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
break;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_field
@@ -496,24 +466,21 @@ acpi_ps_get_next_simple_arg (
*
******************************************************************************/
-static union acpi_parse_object *
-acpi_ps_get_next_field (
- struct acpi_parse_state *parser_state)
+static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
+ *parser_state)
{
- u32 aml_offset = (u32)
- ACPI_PTR_DIFF (parser_state->aml,
- parser_state->aml_start);
- union acpi_parse_object *field;
- u16 opcode;
- u32 name;
-
-
- ACPI_FUNCTION_TRACE ("ps_get_next_field");
+ u32 aml_offset = (u32)
+ ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->aml_start);
+ union acpi_parse_object *field;
+ u16 opcode;
+ u32 name;
+ ACPI_FUNCTION_TRACE("ps_get_next_field");
/* Determine field type */
- switch (ACPI_GET8 (parser_state->aml)) {
+ switch (ACPI_GET8(parser_state->aml)) {
default:
opcode = AML_INT_NAMEDFIELD_OP;
@@ -534,9 +501,9 @@ acpi_ps_get_next_field (
/* Allocate a new field op */
- field = acpi_ps_alloc_op (opcode);
+ field = acpi_ps_alloc_op(opcode);
if (!field) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
field->common.aml_offset = aml_offset;
@@ -548,33 +515,34 @@ acpi_ps_get_next_field (
/* Get the 4-character name */
- ACPI_MOVE_32_TO_32 (&name, parser_state->aml);
- acpi_ps_set_name (field, name);
+ ACPI_MOVE_32_TO_32(&name, parser_state->aml);
+ acpi_ps_set_name(field, name);
parser_state->aml += ACPI_NAME_SIZE;
/* Get the length which is encoded as a package length */
- field->common.value.size = acpi_ps_get_next_package_length (parser_state);
+ field->common.value.size =
+ acpi_ps_get_next_package_length(parser_state);
break;
-
case AML_INT_RESERVEDFIELD_OP:
/* Get the length which is encoded as a package length */
- field->common.value.size = acpi_ps_get_next_package_length (parser_state);
+ field->common.value.size =
+ acpi_ps_get_next_package_length(parser_state);
break;
-
case AML_INT_ACCESSFIELD_OP:
/*
* Get access_type and access_attrib and merge into the field Op
* access_type is first operand, access_attribute is second
*/
- field->common.value.integer = (ACPI_GET8 (parser_state->aml) << 8);
+ field->common.value.integer =
+ (ACPI_GET8(parser_state->aml) << 8);
parser_state->aml++;
- field->common.value.integer |= ACPI_GET8 (parser_state->aml);
+ field->common.value.integer |= ACPI_GET8(parser_state->aml);
parser_state->aml++;
break;
@@ -584,10 +552,9 @@ acpi_ps_get_next_field (
break;
}
- return_PTR (field);
+ return_PTR(field);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_next_arg
@@ -605,21 +572,17 @@ acpi_ps_get_next_field (
******************************************************************************/
acpi_status
-acpi_ps_get_next_arg (
- struct acpi_walk_state *walk_state,
- struct acpi_parse_state *parser_state,
- u32 arg_type,
- union acpi_parse_object **return_arg)
+acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
+ struct acpi_parse_state *parser_state,
+ u32 arg_type, union acpi_parse_object **return_arg)
{
- union acpi_parse_object *arg = NULL;
- union acpi_parse_object *prev = NULL;
- union acpi_parse_object *field;
- u32 subop;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_get_next_arg", parser_state);
+ union acpi_parse_object *arg = NULL;
+ union acpi_parse_object *prev = NULL;
+ union acpi_parse_object *field;
+ u32 subop;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state);
switch (arg_type) {
case ARGP_BYTEDATA:
@@ -631,37 +594,35 @@ acpi_ps_get_next_arg (
/* Constants, strings, and namestrings are all the same size */
- arg = acpi_ps_alloc_op (AML_BYTE_OP);
+ arg = acpi_ps_alloc_op(AML_BYTE_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
+ acpi_ps_get_next_simple_arg(parser_state, arg_type, arg);
break;
-
case ARGP_PKGLENGTH:
/* Package length, nothing returned */
- parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
+ parser_state->pkg_end =
+ acpi_ps_get_next_package_end(parser_state);
break;
-
case ARGP_FIELDLIST:
if (parser_state->aml < parser_state->pkg_end) {
/* Non-empty list */
while (parser_state->aml < parser_state->pkg_end) {
- field = acpi_ps_get_next_field (parser_state);
+ field = acpi_ps_get_next_field(parser_state);
if (!field) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
if (prev) {
prev->common.next = field;
- }
- else {
+ } else {
arg = field;
}
prev = field;
@@ -673,21 +634,21 @@ acpi_ps_get_next_arg (
}
break;
-
case ARGP_BYTELIST:
if (parser_state->aml < parser_state->pkg_end) {
/* Non-empty list */
- arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP);
+ arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Fill in bytelist data */
arg->common.value.size = (u32)
- ACPI_PTR_DIFF (parser_state->pkg_end, parser_state->aml);
+ ACPI_PTR_DIFF(parser_state->pkg_end,
+ parser_state->aml);
arg->named.data = parser_state->aml;
/* Skip to End of byte data */
@@ -696,32 +657,31 @@ acpi_ps_get_next_arg (
}
break;
-
case ARGP_TARGET:
case ARGP_SUPERNAME:
case ARGP_SIMPLENAME:
- subop = acpi_ps_peek_opcode (parser_state);
- if (subop == 0 ||
- acpi_ps_is_leading_char (subop) ||
- acpi_ps_is_prefix_char (subop)) {
+ subop = acpi_ps_peek_opcode(parser_state);
+ if (subop == 0 ||
+ acpi_ps_is_leading_char(subop) ||
+ acpi_ps_is_prefix_char(subop)) {
/* null_name or name_string */
- arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP);
+ arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
if (!arg) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_ps_get_next_namepath (walk_state, parser_state, arg, 0);
- }
- else {
+ status =
+ acpi_ps_get_next_namepath(walk_state, parser_state,
+ arg, 0);
+ } else {
/* Single complex argument, nothing returned */
walk_state->arg_count = 1;
}
break;
-
case ARGP_DATAOBJ:
case ARGP_TERMARG:
@@ -730,7 +690,6 @@ acpi_ps_get_next_arg (
walk_state->arg_count = 1;
break;
-
case ARGP_DATAOBJLIST:
case ARGP_TERMLIST:
case ARGP_OBJLIST:
@@ -742,14 +701,13 @@ acpi_ps_get_next_arg (
}
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid arg_type: %X\n", arg_type));
+ ACPI_REPORT_ERROR(("Invalid arg_type: %X\n", arg_type));
status = AE_AML_OPERAND_TYPE;
break;
}
*return_arg = arg;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
new file mode 100644
index 000000000000..088d33999d90
--- /dev/null
+++ b/drivers/acpi/parser/psloop.c
@@ -0,0 +1,874 @@
+/******************************************************************************
+ *
+ * Module Name: psloop - Main AML parse loop
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+/*
+ * Parse the AML and build an operation tree as most interpreters,
+ * like Perl, do. Parsing is done by hand rather than with a YACC
+ * generated parser to tightly constrain stack and dynamic memory
+ * usage. At the same time, parsing is kept flexible and the code
+ * fairly compact by parsing based on a list of AML opcode
+ * templates in aml_op_info[]
+ */
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/acdispat.h>
+#include <acpi/amlcode.h>
+
+#define _COMPONENT ACPI_PARSER
+ACPI_MODULE_NAME("psloop")
+
+static u32 acpi_gbl_depth = 0;
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_parse_loop
+ *
+ * PARAMETERS: walk_state - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
+ * a tree of ops.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
+{
+ acpi_status status = AE_OK;
+ acpi_status status2;
+ union acpi_parse_object *op = NULL; /* current op */
+ union acpi_parse_object *arg = NULL;
+ union acpi_parse_object *pre_op = NULL;
+ struct acpi_parse_state *parser_state;
+ u8 *aml_op_start = NULL;
+
+ ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state);
+
+ if (walk_state->descending_callback == NULL) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ parser_state = &walk_state->parser_state;
+ walk_state->arg_types = 0;
+
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
+
+ if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
+ /* We are restarting a preempted control method */
+
+ if (acpi_ps_has_completed_scope(parser_state)) {
+ /*
+ * We must check if a predicate to an IF or WHILE statement
+ * was just completed
+ */
+ if ((parser_state->scope->parse_scope.op) &&
+ ((parser_state->scope->parse_scope.op->common.
+ aml_opcode == AML_IF_OP)
+ || (parser_state->scope->parse_scope.op->common.
+ aml_opcode == AML_WHILE_OP))
+ && (walk_state->control_state)
+ && (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING)) {
+ /*
+ * A predicate was just completed, get the value of the
+ * predicate and branch based on that value
+ */
+ walk_state->op = NULL;
+ status =
+ acpi_ds_get_predicate_value(walk_state,
+ ACPI_TO_POINTER
+ (TRUE));
+ if (ACPI_FAILURE(status)
+ && ((status & AE_CODE_MASK) !=
+ AE_CODE_CONTROL)) {
+ if (status == AE_AML_NO_RETURN_VALUE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invoked method did not return a value, %s\n",
+ acpi_format_exception
+ (status)));
+
+ }
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "get_predicate Failed, %s\n",
+ acpi_format_exception
+ (status)));
+ return_ACPI_STATUS(status);
+ }
+
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ }
+
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Popped scope, Op=%p\n", op));
+ } else if (walk_state->prev_op) {
+ /* We were in the middle of an op */
+
+ op = walk_state->prev_op;
+ walk_state->arg_types = walk_state->prev_arg_types;
+ }
+ }
+#endif
+
+ /* Iterative parsing loop, while there is more AML to process: */
+
+ while ((parser_state->aml < parser_state->aml_end) || (op)) {
+ aml_op_start = parser_state->aml;
+ if (!op) {
+ /* Get the next opcode from the AML stream */
+
+ walk_state->aml_offset =
+ (u32) ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->aml_start);
+ walk_state->opcode = acpi_ps_peek_opcode(parser_state);
+
+ /*
+ * First cut to determine what we have found:
+ * 1) A valid AML opcode
+ * 2) A name string
+ * 3) An unknown/invalid opcode
+ */
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(walk_state->opcode);
+ switch (walk_state->op_info->class) {
+ case AML_CLASS_ASCII:
+ case AML_CLASS_PREFIX:
+ /*
+ * Starts with a valid prefix or ASCII char, this is a name
+ * string. Convert the bare name string to a namepath.
+ */
+ walk_state->opcode = AML_INT_NAMEPATH_OP;
+ walk_state->arg_types = ARGP_NAMESTRING;
+ break;
+
+ case AML_CLASS_UNKNOWN:
+
+ /* The opcode is unrecognized. Just skip unknown opcodes */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
+ walk_state->opcode,
+ parser_state->aml,
+ walk_state->aml_offset));
+
+ ACPI_DUMP_BUFFER(parser_state->aml, 128);
+
+ /* Assume one-byte bad opcode */
+
+ parser_state->aml++;
+ continue;
+
+ default:
+
+ /* Found opcode info, this is a normal opcode */
+
+ parser_state->aml +=
+ acpi_ps_get_opcode_size(walk_state->opcode);
+ walk_state->arg_types =
+ walk_state->op_info->parse_args;
+ break;
+ }
+
+ /* Create Op structure and append to parent's argument list */
+
+ if (walk_state->op_info->flags & AML_NAMED) {
+ /* Allocate a new pre_op if necessary */
+
+ if (!pre_op) {
+ pre_op =
+ acpi_ps_alloc_op(walk_state->
+ opcode);
+ if (!pre_op) {
+ status = AE_NO_MEMORY;
+ goto close_this_op;
+ }
+ }
+
+ pre_op->common.value.arg = NULL;
+ pre_op->common.aml_opcode = walk_state->opcode;
+
+ /*
+ * Get and append arguments until we find the node that contains
+ * the name (the type ARGP_NAME).
+ */
+ while (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)
+ &&
+ (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types) != ARGP_NAME)) {
+ status =
+ acpi_ps_get_next_arg(walk_state,
+ parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types),
+ &arg);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ acpi_ps_append_arg(pre_op, arg);
+ INCREMENT_ARG_LIST(walk_state->
+ arg_types);
+ }
+
+ /*
+ * Make sure that we found a NAME and didn't run out of
+ * arguments
+ */
+ if (!GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)) {
+ status = AE_AML_NO_OPERAND;
+ goto close_this_op;
+ }
+
+ /* We know that this arg is a name, move to next arg */
+
+ INCREMENT_ARG_LIST(walk_state->arg_types);
+
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ walk_state->op = NULL;
+
+ status =
+ walk_state->descending_callback(walk_state,
+ &op);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "During name lookup/catalog, %s\n",
+ acpi_format_exception
+ (status)));
+ goto close_this_op;
+ }
+
+ if (!op) {
+ continue;
+ }
+
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ acpi_ps_append_arg(op,
+ pre_op->common.value.arg);
+ acpi_gbl_depth++;
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ /*
+ * Defer final parsing of an operation_region body,
+ * because we don't have enough info in the first pass
+ * to parse it correctly (i.e., there may be method
+ * calls within the term_arg elements of the body.)
+ *
+ * However, we must continue parsing because
+ * the opregion is not a standalone package --
+ * we don't know where the end is at this point.
+ *
+ * (Length is unknown until parse of the body complete)
+ */
+ op->named.data = aml_op_start;
+ op->named.length = 0;
+ }
+ } else {
+ /* Not a named opcode, just allocate Op and append to parent */
+
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(walk_state->opcode);
+ op = acpi_ps_alloc_op(walk_state->opcode);
+ if (!op) {
+ status = AE_NO_MEMORY;
+ goto close_this_op;
+ }
+
+ if (walk_state->op_info->flags & AML_CREATE) {
+ /*
+ * Backup to beginning of create_xXXfield declaration
+ * body_length is unknown until we parse the body
+ */
+ op->named.data = aml_op_start;
+ op->named.length = 0;
+ }
+
+ acpi_ps_append_arg(acpi_ps_get_parent_scope
+ (parser_state), op);
+
+ if ((walk_state->descending_callback != NULL)) {
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ walk_state->op = op;
+
+ status =
+ walk_state->
+ descending_callback(walk_state,
+ &op);
+ status =
+ acpi_ps_next_parse_state(walk_state,
+ op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+ }
+ }
+
+ op->common.aml_offset = walk_state->aml_offset;
+
+ if (walk_state->op_info) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
+ (u32) op->common.aml_opcode,
+ walk_state->op_info->name, op,
+ parser_state->aml,
+ op->common.aml_offset));
+ }
+ }
+
+ /*
+ * Start arg_count at zero because we don't know if there are
+ * any args yet
+ */
+ walk_state->arg_count = 0;
+
+ /* Are there any arguments that must be processed? */
+
+ if (walk_state->arg_types) {
+ /* Get arguments */
+
+ switch (op->common.aml_opcode) {
+ case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
+ case AML_WORD_OP: /* AML_WORDDATA_ARG */
+ case AML_DWORD_OP: /* AML_DWORDATA_ARG */
+ case AML_QWORD_OP: /* AML_QWORDATA_ARG */
+ case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
+
+ /* Fill in constant or string argument directly */
+
+ acpi_ps_get_next_simple_arg(parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types), op);
+ break;
+
+ case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
+
+ status =
+ acpi_ps_get_next_namepath(walk_state,
+ parser_state, op,
+ 1);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ walk_state->arg_types = 0;
+ break;
+
+ default:
+ /*
+ * Op is not a constant or string, append each argument
+ * to the Op
+ */
+ while (GET_CURRENT_ARG_TYPE
+ (walk_state->arg_types)
+ && !walk_state->arg_count) {
+ walk_state->aml_offset = (u32)
+ ACPI_PTR_DIFF(parser_state->aml,
+ parser_state->
+ aml_start);
+
+ status =
+ acpi_ps_get_next_arg(walk_state,
+ parser_state,
+ GET_CURRENT_ARG_TYPE
+ (walk_state->
+ arg_types),
+ &arg);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+
+ if (arg) {
+ arg->common.aml_offset =
+ walk_state->aml_offset;
+ acpi_ps_append_arg(op, arg);
+ }
+ INCREMENT_ARG_LIST(walk_state->
+ arg_types);
+ }
+
+ /* Special processing for certain opcodes */
+
+ /* TBD (remove): Temporary mechanism to disable this code if needed */
+
+#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
+
+ if ((walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS1)
+ &&
+ ((walk_state->
+ parse_flags & ACPI_PARSE_DISASSEMBLE) ==
+ 0)) {
+ /*
+ * We want to skip If/Else/While constructs during Pass1
+ * because we want to actually conditionally execute the
+ * code during Pass2.
+ *
+ * Except for disassembly, where we always want to
+ * walk the If/Else/While packages
+ */
+ switch (op->common.aml_opcode) {
+ case AML_IF_OP:
+ case AML_ELSE_OP:
+ case AML_WHILE_OP:
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Pass1: Skipping an If/Else/While body\n"));
+
+ /* Skip body of if/else/while in pass 1 */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+ switch (op->common.aml_opcode) {
+ case AML_METHOD_OP:
+
+ /*
+ * Skip parsing of control method
+ * because we don't have enough info in the first pass
+ * to parse it correctly.
+ *
+ * Save the length and address of the body
+ */
+ op->named.data = parser_state->aml;
+ op->named.length =
+ (u32) (parser_state->pkg_end -
+ parser_state->aml);
+
+ /* Skip body of method */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+
+ case AML_BUFFER_OP:
+ case AML_PACKAGE_OP:
+ case AML_VAR_PACKAGE_OP:
+
+ if ((op->common.parent) &&
+ (op->common.parent->common.
+ aml_opcode == AML_NAME_OP)
+ && (walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS2)) {
+ /*
+ * Skip parsing of Buffers and Packages
+ * because we don't have enough info in the first pass
+ * to parse them correctly.
+ */
+ op->named.data = aml_op_start;
+ op->named.length =
+ (u32) (parser_state->
+ pkg_end -
+ aml_op_start);
+
+ /* Skip body */
+
+ parser_state->aml =
+ parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ }
+ break;
+
+ case AML_WHILE_OP:
+
+ if (walk_state->control_state) {
+ walk_state->control_state->
+ control.package_end =
+ parser_state->pkg_end;
+ }
+ break;
+
+ default:
+
+ /* No action for all other opcodes */
+ break;
+ }
+ break;
+ }
+ }
+
+ /* Check for arguments that need to be processed */
+
+ if (walk_state->arg_count) {
+ /*
+ * There are arguments (complex ones), push Op and
+ * prepare for argument
+ */
+ status = acpi_ps_push_scope(parser_state, op,
+ walk_state->arg_types,
+ walk_state->arg_count);
+ if (ACPI_FAILURE(status)) {
+ goto close_this_op;
+ }
+ op = NULL;
+ continue;
+ }
+
+ /*
+ * All arguments have been processed -- Op is complete,
+ * prepare for next
+ */
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+ if (walk_state->op_info->flags & AML_NAMED) {
+ if (acpi_gbl_depth) {
+ acpi_gbl_depth--;
+ }
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ /*
+ * Skip parsing of control method or opregion body,
+ * because we don't have enough info in the first pass
+ * to parse them correctly.
+ *
+ * Completed parsing an op_region declaration, we now
+ * know the length.
+ */
+ op->named.length =
+ (u32) (parser_state->aml - op->named.data);
+ }
+ }
+
+ if (walk_state->op_info->flags & AML_CREATE) {
+ /*
+ * Backup to beginning of create_xXXfield declaration (1 for
+ * Opcode)
+ *
+ * body_length is unknown until we parse the body
+ */
+ op->named.length =
+ (u32) (parser_state->aml - op->named.data);
+ }
+
+ /* This op complete, notify the dispatcher */
+
+ if (walk_state->ascending_callback != NULL) {
+ walk_state->op = op;
+ walk_state->opcode = op->common.aml_opcode;
+
+ status = walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op, status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+ }
+
+ close_this_op:
+ /*
+ * Finished one argument of the containing scope
+ */
+ parser_state->scope->parse_scope.arg_count--;
+
+ /* Finished with pre_op */
+
+ if (pre_op) {
+ acpi_ps_free_op(pre_op);
+ pre_op = NULL;
+ }
+
+ /* Close this Op (will result in parse subtree deletion) */
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+
+ switch (status) {
+ case AE_OK:
+ break;
+
+ case AE_CTRL_TRANSFER:
+
+ /* We are about to transfer to a called method. */
+
+ walk_state->prev_op = op;
+ walk_state->prev_arg_types = walk_state->arg_types;
+ return_ACPI_STATUS(status);
+
+ case AE_CTRL_END:
+
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ if (op) {
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.
+ aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status =
+ walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+
+ status2 =
+ acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+ }
+ status = AE_OK;
+ break;
+
+ case AE_CTRL_BREAK:
+ case AE_CTRL_CONTINUE:
+
+ /* Pop off scopes until we find the While */
+
+ while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ }
+
+ /* Close this iteration of the While loop */
+
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status = walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op, status);
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ op = NULL;
+
+ status = AE_OK;
+ break;
+
+ case AE_CTRL_TERMINATE:
+
+ status = AE_OK;
+
+ /* Clean up */
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+
+ default: /* All other non-AE_OK status */
+
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ /*
+ * TBD: Cleanup parse ops on error
+ */
+#if 0
+ if (op == NULL) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ }
+#endif
+ walk_state->prev_op = op;
+ walk_state->prev_arg_types = walk_state->arg_types;
+ return_ACPI_STATUS(status);
+ }
+
+ /* This scope complete? */
+
+ if (acpi_ps_has_completed_scope(parser_state)) {
+ acpi_ps_pop_scope(parser_state, &op,
+ &walk_state->arg_types,
+ &walk_state->arg_count);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Popped scope, Op=%p\n", op));
+ } else {
+ op = NULL;
+ }
+
+ } /* while parser_state->Aml */
+
+ /*
+ * Complete the last Op (if not completed), and clear the scope stack.
+ * It is easily possible to end an AML "package" with an unbounded number
+ * of open scopes (such as when several ASL blocks are closed with
+ * sequential closing braces). We want to terminate each one cleanly.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
+ op));
+ do {
+ if (op) {
+ if (walk_state->ascending_callback != NULL) {
+ walk_state->op = op;
+ walk_state->op_info =
+ acpi_ps_get_opcode_info(op->common.
+ aml_opcode);
+ walk_state->opcode = op->common.aml_opcode;
+
+ status =
+ walk_state->ascending_callback(walk_state);
+ status =
+ acpi_ps_next_parse_state(walk_state, op,
+ status);
+ if (status == AE_CTRL_PENDING) {
+ status = AE_OK;
+ goto close_this_op;
+ }
+
+ if (status == AE_CTRL_TERMINATE) {
+ status = AE_OK;
+
+ /* Clean up */
+ do {
+ if (op) {
+ status2 =
+ acpi_ps_complete_this_op
+ (walk_state, op);
+ if (ACPI_FAILURE
+ (status2)) {
+ return_ACPI_STATUS
+ (status2);
+ }
+ }
+
+ acpi_ps_pop_scope(parser_state,
+ &op,
+ &walk_state->
+ arg_types,
+ &walk_state->
+ arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+ }
+
+ else if (ACPI_FAILURE(status)) {
+ /* First error is most important */
+
+ (void)
+ acpi_ps_complete_this_op(walk_state,
+ op);
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ status2 = acpi_ps_complete_this_op(walk_state, op);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+ }
+
+ acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types,
+ &walk_state->arg_count);
+
+ } while (op);
+
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 5744673568c0..229ae86afe8b 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -41,16 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acopcode.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psopcode")
-
+ACPI_MODULE_NAME("psopcode")
/*******************************************************************************
*
@@ -62,7 +59,6 @@
* the operand type.
*
******************************************************************************/
-
/*
* Summary of opcode types/flags
*
@@ -180,156 +176,468 @@
AML_CREATE_QWORD_FIELD_OP
******************************************************************************/
-
-
/*
* Master Opcode information table. A summary of everything we know about each
* opcode, all in one place.
*/
-const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
-{
+const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/*! [Begin] no source code translation */
/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */
-/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
-/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
-/* 02 */ ACPI_OP ("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 03 */ ACPI_OP ("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 08 */ ACPI_OP ("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
-/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
-/* 0B */ ACPI_OP ("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
-/* 0C */ ACPI_OP ("Local0", ARGP_LOCAL0, ARGI_LOCAL0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0D */ ACPI_OP ("Local1", ARGP_LOCAL1, ARGI_LOCAL1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0E */ ACPI_OP ("Local2", ARGP_LOCAL2, ARGI_LOCAL2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 0F */ ACPI_OP ("Local3", ARGP_LOCAL3, ARGI_LOCAL3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 10 */ ACPI_OP ("Local4", ARGP_LOCAL4, ARGI_LOCAL4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 11 */ ACPI_OP ("Local5", ARGP_LOCAL5, ARGI_LOCAL5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 12 */ ACPI_OP ("Local6", ARGP_LOCAL6, ARGI_LOCAL6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 13 */ ACPI_OP ("Local7", ARGP_LOCAL7, ARGI_LOCAL7, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0),
-/* 14 */ ACPI_OP ("Arg0", ARGP_ARG0, ARGI_ARG0, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 15 */ ACPI_OP ("Arg1", ARGP_ARG1, ARGI_ARG1, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 16 */ ACPI_OP ("Arg2", ARGP_ARG2, ARGI_ARG2, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 17 */ ACPI_OP ("Arg3", ARGP_ARG3, ARGI_ARG3, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 18 */ ACPI_OP ("Arg4", ARGP_ARG4, ARGI_ARG4, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 19 */ ACPI_OP ("Arg5", ARGP_ARG5, ARGI_ARG5, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 1A */ ACPI_OP ("Arg6", ARGP_ARG6, ARGI_ARG6, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0),
-/* 1B */ ACPI_OP ("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 1C */ ACPI_OP ("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
-/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
-/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
-/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
-/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
-/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R),
-/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
-/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
-/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
-/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
-/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
-/* 3E */ ACPI_OP ("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 3F */ ACPI_OP ("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 40 */ ACPI_OP ("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 41 */ ACPI_OP ("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 42 */ ACPI_OP ("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
-/* 43 */ ACPI_OP ("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 44 */ ACPI_OP ("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+/* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP,
+ ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP,
+ ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+/* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
+ ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP,
+ ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+/* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP,
+ ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+/* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP,
+ ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
+/* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
+/* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
+/* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R),
+/* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R),
+/* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_2T_1R,
+ AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
+/* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+/* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP,
+ ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,
+ ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+/* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
+/* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+/* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R),
+/* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
+ AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
+/* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,
+ ARGI_CREATE_DWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP,
+ ARGI_CREATE_WORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP,
+ ARGI_CREATE_BYTE_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP,
+ ARGI_CREATE_BIT_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+/* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
+/* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
+/* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+/* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+/* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL,
+ AML_TYPE_CONTROL, AML_HAS_ARGS),
+/* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY,
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER,
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
/* Prefixed opcodes (Two-byte opcodes with a prefix op) */
-/* 46 */ ACPI_OP ("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 47 */ ACPI_OP ("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
-/* 48 */ ACPI_OP ("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 49 */ ACPI_OP ("CreateField", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_FIELD | AML_CREATE),
-/* 4A */ ACPI_OP ("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, AML_FLAGS_EXEC_1A_1T_0R),
-/* 4B */ ACPI_OP ("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4C */ ACPI_OP ("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4D */ ACPI_OP ("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
-/* 4E */ ACPI_OP ("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 4F */ ACPI_OP ("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
-/* 50 */ ACPI_OP ("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 51 */ ACPI_OP ("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 54 */ ACPI_OP ("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
-/* 55 */ ACPI_OP ("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
-/* 56 */ ACPI_OP ("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0),
-/* 57 */ ACPI_OP ("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R),
-/* 58 */ ACPI_OP ("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
-/* 59 */ ACPI_OP ("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
-/* 5A */ ACPI_OP ("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5B */ ACPI_OP ("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5C */ ACPI_OP ("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5D */ ACPI_OP ("ThermalZone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 5E */ ACPI_OP ("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
-/* 5F */ ACPI_OP ("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+/* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+/* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+/* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP,
+ ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
+ AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_FIELD | AML_CREATE),
+/* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
+ AML_FLAGS_EXEC_1A_1T_0R),
+/* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
+/* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R),
+/* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
+/* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+/* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
+/* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
+/* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
+ AML_FLAGS_EXEC_3A_0T_0R),
+/* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP,
+ ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
+/* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
+/* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
+ ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP,
+ ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP,
+ ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP,
+ ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
+/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
/* Internal opcodes that map to invalid AML opcodes */
-/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
-/* 63 */ ACPI_OP ("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE ),
-/* 64 */ ACPI_OP ("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, AML_TYPE_METHOD_CALL, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
-/* 65 */ ACPI_OP ("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0),
-/* 66 */ ACPI_OP ("-ReservedField-", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 67 */ ACPI_OP ("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED ),
-/* 68 */ ACPI_OP ("-AccessField-", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 69 */ ACPI_OP ("-StaticString", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
-/* 6A */ ACPI_OP ("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, AML_HAS_ARGS | AML_HAS_RETVAL),
-/* 6B */ ACPI_OP ("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
-/* 6C */ ACPI_OP ("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
-/* 6D */ ACPI_OP ("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+/* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+/* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP,
+ ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
+ AML_HAS_ARGS | AML_CONSTANT),
+/* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP,
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
+/* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP,
+ ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
+ AML_TYPE_METHOD_CALL,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
+/* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP,
+ ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, 0),
+/* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP,
+ ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP,
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+/* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP,
+ ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP,
+ ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+/* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
+ AML_HAS_ARGS | AML_HAS_RETVAL),
+/* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID,
+ AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
+ AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* ACPI 2.0 opcodes */
-/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT),
-/* 6F */ ACPI_OP ("Package /*Var*/", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER),
-/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
-/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
-/* 78 */ ACPI_OP ("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
-/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
-/* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
-/* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
-/* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
+/* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP,
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
+ /* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP,
+ ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE,
+ AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER),
+/* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,
+ ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,
+ ARGI_CREATE_QWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP,
+ ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+/* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+/* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
+ AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
+/* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+/* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
+ ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
+/* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE),
/* ACPI 3.0 opcodes */
-/* 7E */ ACPI_OP ("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_FLAGS_EXEC_0A_0T_1R)
+/* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+ AML_FLAGS_EXEC_0A_0T_1R)
/*! [End] no source code translation !*/
};
@@ -338,73 +646,70 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
* This table is directly indexed by the opcodes, and returns an
* index into the table above
*/
-static const u8 acpi_gbl_short_op_index[256] =
-{
+static const u8 acpi_gbl_short_op_index[256] = {
/* 0 1 2 3 4 5 6 7 */
/* 8 9 A B C D E F */
-/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
-/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
-/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
-/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
-/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
-/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
-/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
-/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
-/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
-/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
-/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
-/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
+/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
+/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
+/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
+/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
+/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
+/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
+/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
+/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
};
/*
* This table is indexed by the second opcode of the extended opcode
* pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
*/
-static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] =
-{
+static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
/* 0 1 2 3 4 5 6 7 */
/* 8 9 A B C D E F */
-/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
-/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
-/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-/* 0x88 */ 0x7C,
+/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
+/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
+/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */ 0x7C,
};
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_opcode_info
@@ -418,48 +723,36 @@ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] =
*
******************************************************************************/
-const struct acpi_opcode_info *
-acpi_ps_get_opcode_info (
- u16 opcode)
+const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
{
- ACPI_FUNCTION_NAME ("ps_get_opcode_info");
-
+ ACPI_FUNCTION_NAME("ps_get_opcode_info");
/*
* Detect normal 8-bit opcode or extended 16-bit opcode
*/
- switch ((u8) (opcode >> 8)) {
- case 0:
-
+ if (!(opcode & 0xFF00)) {
/* Simple (8-bit) opcode: 0-255, can't index beyond table */
- return (&acpi_gbl_aml_op_info [acpi_gbl_short_op_index [(u8) opcode]]);
-
- case AML_EXTOP:
-
- /* Extended (16-bit, prefix+opcode) opcode */
-
- if (((u8) opcode) <= MAX_EXTENDED_OPCODE) {
- return (&acpi_gbl_aml_op_info [acpi_gbl_long_op_index [(u8) opcode]]);
- }
-
- /* Else fall through to error case below */
- /*lint -fallthrough */
+ return (&acpi_gbl_aml_op_info
+ [acpi_gbl_short_op_index[(u8) opcode]]);
+ }
- default:
+ if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
+ (((u8) opcode) <= MAX_EXTENDED_OPCODE)) {
+ /* Valid extended (16-bit) opcode */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown AML opcode [%4.4X]\n", opcode));
- break;
+ return (&acpi_gbl_aml_op_info
+ [acpi_gbl_long_op_index[(u8) opcode]]);
}
+ /* Unknown AML opcode */
- /* Default is "unknown opcode" */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown AML opcode [%4.4X]\n", opcode));
- return (&acpi_gbl_aml_op_info [_UNK]);
+ return (&acpi_gbl_aml_op_info[_UNK]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_opcode_name
@@ -473,16 +766,13 @@ acpi_ps_get_opcode_info (
*
******************************************************************************/
-char *
-acpi_ps_get_opcode_name (
- u16 opcode)
+char *acpi_ps_get_opcode_name(u16 opcode)
{
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
- const struct acpi_opcode_info *op;
+ const struct acpi_opcode_info *op;
-
- op = acpi_ps_get_opcode_info (opcode);
+ op = acpi_ps_get_opcode_info(opcode);
/* Always guaranteed to return a valid pointer */
@@ -493,4 +783,3 @@ acpi_ps_get_opcode_name (
#endif
}
-
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index bbfdc1a58c27..76d4d640d83c 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
/*
* Parse the AML and build an operation tree as most interpreters,
* like Perl, do. Parsing is done by hand rather than with a YACC
@@ -59,28 +58,7 @@
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psparse")
-
-
-static u32 acpi_gbl_depth = 0;
-
-/* Local prototypes */
-
-static void
-acpi_ps_complete_this_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
-
-static acpi_status
-acpi_ps_next_parse_state (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_status callback_status);
-
-static acpi_status
-acpi_ps_parse_loop (
- struct acpi_walk_state *walk_state);
-
+ACPI_MODULE_NAME("psparse")
/*******************************************************************************
*
@@ -93,10 +71,7 @@ acpi_ps_parse_loop (
* DESCRIPTION: Get the size of the current opcode.
*
******************************************************************************/
-
-u32
-acpi_ps_get_opcode_size (
- u32 opcode)
+u32 acpi_ps_get_opcode_size(u32 opcode)
{
/* Extended (2-byte) opcode if > 255 */
@@ -110,7 +85,6 @@ acpi_ps_get_opcode_size (
return (1);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_peek_opcode
@@ -123,28 +97,24 @@ acpi_ps_get_opcode_size (
*
******************************************************************************/
-u16
-acpi_ps_peek_opcode (
- struct acpi_parse_state *parser_state)
+u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state)
{
- u8 *aml;
- u16 opcode;
-
+ u8 *aml;
+ u16 opcode;
aml = parser_state->aml;
- opcode = (u16) ACPI_GET8 (aml);
+ opcode = (u16) ACPI_GET8(aml);
- if (opcode == AML_EXTOP) {
- /* Extended opcode */
+ if (opcode == AML_EXTENDED_OP_PREFIX) {
+ /* Extended opcode, get the second opcode byte */
aml++;
- opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml));
+ opcode = (u16) ((opcode << 8) | ACPI_GET8(aml));
}
return (opcode);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_complete_this_op
@@ -152,47 +122,54 @@ acpi_ps_peek_opcode (
* PARAMETERS: walk_state - Current State
* Op - Op to complete
*
- * RETURN: None.
+ * RETURN: Status
*
* DESCRIPTION: Perform any cleanup at the completion of an Op.
*
******************************************************************************/
-static void
-acpi_ps_complete_this_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op)
+acpi_status
+acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
+ union acpi_parse_object * op)
{
- union acpi_parse_object *prev;
- union acpi_parse_object *next;
- const struct acpi_opcode_info *parent_info;
- union acpi_parse_object *replacement_op = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op);
+ union acpi_parse_object *prev;
+ union acpi_parse_object *next;
+ const struct acpi_opcode_info *parent_info;
+ union acpi_parse_object *replacement_op = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op);
/* Check for null Op, can happen if AML code is corrupt */
if (!op) {
- return_VOID;
+ return_ACPI_STATUS(AE_OK); /* OK for now */
}
/* Delete this op and the subtree below it if asked to */
- if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
- (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
- return_VOID;
+ if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) !=
+ ACPI_PARSE_DELETE_TREE)
+ || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
+ return_ACPI_STATUS(AE_OK);
}
/* Make sure that we only delete this subtree */
if (op->common.parent) {
+ prev = op->common.parent->common.value.arg;
+ if (!prev) {
+ /* Nothing more to do */
+
+ goto cleanup;
+ }
+
/*
* Check if we need to replace the operator and its subtree
* with a return value op (placeholder op)
*/
- parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
+ parent_info =
+ acpi_ps_get_opcode_info(op->common.parent->common.
+ aml_opcode);
switch (parent_info->class) {
case AML_CLASS_CONTROL:
@@ -204,9 +181,10 @@ acpi_ps_complete_this_op (
* These opcodes contain term_arg operands. The current
* op must be replaced by a placeholder return op
*/
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
break;
@@ -216,91 +194,117 @@ acpi_ps_complete_this_op (
* These opcodes contain term_arg operands. The current
* op must be replaced by a placeholder return op
*/
- if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
- (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+ if ((op->common.parent->common.aml_opcode ==
+ AML_REGION_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_DATA_REGION_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_BUFFER_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_PACKAGE_OP)
+ || (op->common.parent->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)) {
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
- }
-
- if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
- if ((op->common.aml_opcode == AML_BUFFER_OP) ||
- (op->common.aml_opcode == AML_PACKAGE_OP) ||
- (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
- replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
+ } else
+ if ((op->common.parent->common.aml_opcode ==
+ AML_NAME_OP)
+ && (walk_state->pass_number <=
+ ACPI_IMODE_LOAD_PASS2)) {
+ if ((op->common.aml_opcode == AML_BUFFER_OP)
+ || (op->common.aml_opcode == AML_PACKAGE_OP)
+ || (op->common.aml_opcode ==
+ AML_VAR_PACKAGE_OP)) {
+ replacement_op =
+ acpi_ps_alloc_op(op->common.
+ aml_opcode);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
- replacement_op->named.data = op->named.data;
- replacement_op->named.length = op->named.length;
+ replacement_op->named.data =
+ op->named.data;
+ replacement_op->named.length =
+ op->named.length;
}
}
break;
default:
- replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
+
+ replacement_op =
+ acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
}
/* We must unlink this op from the parent tree */
- prev = op->common.parent->common.value.arg;
if (prev == op) {
/* This op is the first in the list */
if (replacement_op) {
- replacement_op->common.parent = op->common.parent;
- replacement_op->common.value.arg = NULL;
- replacement_op->common.node = op->common.node;
- op->common.parent->common.value.arg = replacement_op;
- replacement_op->common.next = op->common.next;
- }
- else {
- op->common.parent->common.value.arg = op->common.next;
+ replacement_op->common.parent =
+ op->common.parent;
+ replacement_op->common.value.arg = NULL;
+ replacement_op->common.node = op->common.node;
+ op->common.parent->common.value.arg =
+ replacement_op;
+ replacement_op->common.next = op->common.next;
+ } else {
+ op->common.parent->common.value.arg =
+ op->common.next;
}
}
/* Search the parent list */
- else while (prev) {
- /* Traverse all siblings in the parent's argument list */
-
- next = prev->common.next;
- if (next == op) {
- if (replacement_op) {
- replacement_op->common.parent = op->common.parent;
- replacement_op->common.value.arg = NULL;
- replacement_op->common.node = op->common.node;
- prev->common.next = replacement_op;
- replacement_op->common.next = op->common.next;
- next = NULL;
- }
- else {
- prev->common.next = op->common.next;
- next = NULL;
+ else
+ while (prev) {
+ /* Traverse all siblings in the parent's argument list */
+
+ next = prev->common.next;
+ if (next == op) {
+ if (replacement_op) {
+ replacement_op->common.parent =
+ op->common.parent;
+ replacement_op->common.value.
+ arg = NULL;
+ replacement_op->common.node =
+ op->common.node;
+ prev->common.next =
+ replacement_op;
+ replacement_op->common.next =
+ op->common.next;
+ next = NULL;
+ } else {
+ prev->common.next =
+ op->common.next;
+ next = NULL;
+ }
}
+ prev = next;
}
- prev = next;
- }
}
-
-cleanup:
+ cleanup:
/* Now we can actually delete the subtree rooted at Op */
- acpi_ps_delete_parse_tree (op);
- return_VOID;
-}
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(AE_OK);
+ allocate_error:
+
+ /* Always delete the subtree, even on error */
+
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+}
/*******************************************************************************
*
@@ -317,18 +321,15 @@ cleanup:
*
******************************************************************************/
-static acpi_status
-acpi_ps_next_parse_state (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_status callback_status)
+acpi_status
+acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ acpi_status callback_status)
{
- struct acpi_parse_state *parser_state = &walk_state->parser_state;
- acpi_status status = AE_CTRL_PENDING;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_next_parse_state", op);
+ struct acpi_parse_state *parser_state = &walk_state->parser_state;
+ acpi_status status = AE_CTRL_PENDING;
+ ACPI_FUNCTION_TRACE_PTR("ps_next_parse_state", op);
switch (callback_status) {
case AE_CTRL_TERMINATE:
@@ -341,7 +342,6 @@ acpi_ps_next_parse_state (
status = AE_CTRL_TERMINATE;
break;
-
case AE_CTRL_BREAK:
parser_state->aml = walk_state->aml_last_while;
@@ -351,7 +351,6 @@ acpi_ps_next_parse_state (
case AE_CTRL_CONTINUE:
-
parser_state->aml = walk_state->aml_last_while;
status = AE_CTRL_CONTINUE;
break;
@@ -375,10 +374,9 @@ acpi_ps_next_parse_state (
* Predicate of an IF was true, and we are at the matching ELSE.
* Just close out this package
*/
- parser_state->aml = acpi_ps_get_next_package_end (parser_state);
+ parser_state->aml = acpi_ps_get_next_package_end(parser_state);
break;
-
case AE_CTRL_FALSE:
/*
@@ -396,7 +394,6 @@ acpi_ps_next_parse_state (
status = AE_CTRL_END;
break;
-
case AE_CTRL_TRANSFER:
/* A method call (invocation) -- transfer control */
@@ -404,14 +401,15 @@ acpi_ps_next_parse_state (
status = AE_CTRL_TRANSFER;
walk_state->prev_op = op;
walk_state->method_call_op = op;
- walk_state->method_call_node = (op->common.value.arg)->common.node;
+ walk_state->method_call_node =
+ (op->common.value.arg)->common.node;
/* Will return value (if any) be used by the caller? */
- walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
+ walk_state->return_used =
+ acpi_ds_is_result_used(op, walk_state);
break;
-
default:
status = callback_status;
@@ -421,667 +419,9 @@ acpi_ps_next_parse_state (
break;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_parse_loop
- *
- * PARAMETERS: walk_state - Current state
- *
- * RETURN: Status
- *
- * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
- * a tree of ops.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ps_parse_loop (
- struct acpi_walk_state *walk_state)
-{
- acpi_status status = AE_OK;
- union acpi_parse_object *op = NULL; /* current op */
- union acpi_parse_object *arg = NULL;
- union acpi_parse_object *pre_op = NULL;
- struct acpi_parse_state *parser_state;
- u8 *aml_op_start = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state);
-
- if (walk_state->descending_callback == NULL) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- parser_state = &walk_state->parser_state;
- walk_state->arg_types = 0;
-
-#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
-
- if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
- /* We are restarting a preempted control method */
-
- if (acpi_ps_has_completed_scope (parser_state)) {
- /*
- * We must check if a predicate to an IF or WHILE statement
- * was just completed
- */
- if ((parser_state->scope->parse_scope.op) &&
- ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) ||
- (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) &&
- (walk_state->control_state) &&
- (walk_state->control_state->common.state ==
- ACPI_CONTROL_PREDICATE_EXECUTING)) {
- /*
- * A predicate was just completed, get the value of the
- * predicate and branch based on that value
- */
- walk_state->op = NULL;
- status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE));
- if (ACPI_FAILURE (status) &&
- ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
- if (status == AE_AML_NO_RETURN_VALUE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invoked method did not return a value, %s\n",
- acpi_format_exception (status)));
-
- }
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "get_predicate Failed, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
- }
-
- status = acpi_ps_next_parse_state (walk_state, op, status);
- }
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
- }
- else if (walk_state->prev_op) {
- /* We were in the middle of an op */
-
- op = walk_state->prev_op;
- walk_state->arg_types = walk_state->prev_arg_types;
- }
- }
-#endif
-
- /* Iterative parsing loop, while there is more AML to process: */
-
- while ((parser_state->aml < parser_state->aml_end) || (op)) {
- aml_op_start = parser_state->aml;
- if (!op) {
- /* Get the next opcode from the AML stream */
-
- walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
- parser_state->aml_start);
- walk_state->opcode = acpi_ps_peek_opcode (parser_state);
-
- /*
- * First cut to determine what we have found:
- * 1) A valid AML opcode
- * 2) A name string
- * 3) An unknown/invalid opcode
- */
- walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
- switch (walk_state->op_info->class) {
- case AML_CLASS_ASCII:
- case AML_CLASS_PREFIX:
- /*
- * Starts with a valid prefix or ASCII char, this is a name
- * string. Convert the bare name string to a namepath.
- */
- walk_state->opcode = AML_INT_NAMEPATH_OP;
- walk_state->arg_types = ARGP_NAMESTRING;
- break;
-
- case AML_CLASS_UNKNOWN:
-
- /* The opcode is unrecognized. Just skip unknown opcodes */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
- walk_state->opcode, parser_state->aml, walk_state->aml_offset));
-
- ACPI_DUMP_BUFFER (parser_state->aml, 128);
-
- /* Assume one-byte bad opcode */
-
- parser_state->aml++;
- continue;
-
- default:
-
- /* Found opcode info, this is a normal opcode */
-
- parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
- walk_state->arg_types = walk_state->op_info->parse_args;
- break;
- }
-
- /* Create Op structure and append to parent's argument list */
-
- if (walk_state->op_info->flags & AML_NAMED) {
- /* Allocate a new pre_op if necessary */
-
- if (!pre_op) {
- pre_op = acpi_ps_alloc_op (walk_state->opcode);
- if (!pre_op) {
- status = AE_NO_MEMORY;
- goto close_this_op;
- }
- }
-
- pre_op->common.value.arg = NULL;
- pre_op->common.aml_opcode = walk_state->opcode;
-
- /*
- * Get and append arguments until we find the node that contains
- * the name (the type ARGP_NAME).
- */
- while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
- (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) {
- status = acpi_ps_get_next_arg (walk_state, parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- acpi_ps_append_arg (pre_op, arg);
- INCREMENT_ARG_LIST (walk_state->arg_types);
- }
-
- /*
- * Make sure that we found a NAME and didn't run out of
- * arguments
- */
- if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) {
- status = AE_AML_NO_OPERAND;
- goto close_this_op;
- }
-
- /* We know that this arg is a name, move to next arg */
-
- INCREMENT_ARG_LIST (walk_state->arg_types);
-
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- walk_state->op = NULL;
-
- status = walk_state->descending_callback (walk_state, &op);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "During name lookup/catalog, %s\n",
- acpi_format_exception (status)));
- goto close_this_op;
- }
-
- if (!op) {
- continue;
- }
-
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- acpi_ps_append_arg (op, pre_op->common.value.arg);
- acpi_gbl_depth++;
-
- if (op->common.aml_opcode == AML_REGION_OP) {
- /*
- * Defer final parsing of an operation_region body,
- * because we don't have enough info in the first pass
- * to parse it correctly (i.e., there may be method
- * calls within the term_arg elements of the body.)
- *
- * However, we must continue parsing because
- * the opregion is not a standalone package --
- * we don't know where the end is at this point.
- *
- * (Length is unknown until parse of the body complete)
- */
- op->named.data = aml_op_start;
- op->named.length = 0;
- }
- }
- else {
- /* Not a named opcode, just allocate Op and append to parent */
-
- walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
- op = acpi_ps_alloc_op (walk_state->opcode);
- if (!op) {
- status = AE_NO_MEMORY;
- goto close_this_op;
- }
-
- if (walk_state->op_info->flags & AML_CREATE) {
- /*
- * Backup to beginning of create_xXXfield declaration
- * body_length is unknown until we parse the body
- */
- op->named.data = aml_op_start;
- op->named.length = 0;
- }
-
- acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
-
- if ((walk_state->descending_callback != NULL)) {
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- walk_state->op = op;
-
- status = walk_state->descending_callback (walk_state, &op);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
- }
- }
-
- op->common.aml_offset = walk_state->aml_offset;
-
- if (walk_state->op_info) {
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
- (u32) op->common.aml_opcode, walk_state->op_info->name,
- op, parser_state->aml, op->common.aml_offset));
- }
- }
-
-
- /*
- * Start arg_count at zero because we don't know if there are
- * any args yet
- */
- walk_state->arg_count = 0;
-
- /* Are there any arguments that must be processed? */
-
- if (walk_state->arg_types) {
- /* Get arguments */
-
- switch (op->common.aml_opcode) {
- case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
- case AML_WORD_OP: /* AML_WORDDATA_ARG */
- case AML_DWORD_OP: /* AML_DWORDATA_ARG */
- case AML_QWORD_OP: /* AML_QWORDATA_ARG */
- case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
-
- /* Fill in constant or string argument directly */
-
- acpi_ps_get_next_simple_arg (parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
- break;
-
- case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
-
- status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- walk_state->arg_types = 0;
- break;
-
- default:
-
- /*
- * Op is not a constant or string, append each argument
- * to the Op
- */
- while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
- !walk_state->arg_count) {
- walk_state->aml_offset = (u32)
- ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start);
-
- status = acpi_ps_get_next_arg (walk_state, parser_state,
- GET_CURRENT_ARG_TYPE (walk_state->arg_types),
- &arg);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
-
- if (arg) {
- arg->common.aml_offset = walk_state->aml_offset;
- acpi_ps_append_arg (op, arg);
- }
- INCREMENT_ARG_LIST (walk_state->arg_types);
- }
-
- /* Special processing for certain opcodes */
-
- switch (op->common.aml_opcode) {
- case AML_METHOD_OP:
-
- /*
- * Skip parsing of control method
- * because we don't have enough info in the first pass
- * to parse it correctly.
- *
- * Save the length and address of the body
- */
- op->named.data = parser_state->aml;
- op->named.length = (u32) (parser_state->pkg_end -
- parser_state->aml);
-
- /* Skip body of method */
-
- parser_state->aml = parser_state->pkg_end;
- walk_state->arg_count = 0;
- break;
-
- case AML_BUFFER_OP:
- case AML_PACKAGE_OP:
- case AML_VAR_PACKAGE_OP:
-
- if ((op->common.parent) &&
- (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
- /*
- * Skip parsing of Buffers and Packages
- * because we don't have enough info in the first pass
- * to parse them correctly.
- */
- op->named.data = aml_op_start;
- op->named.length = (u32) (parser_state->pkg_end -
- aml_op_start);
-
- /* Skip body */
-
- parser_state->aml = parser_state->pkg_end;
- walk_state->arg_count = 0;
- }
- break;
-
- case AML_WHILE_OP:
-
- if (walk_state->control_state) {
- walk_state->control_state->control.package_end =
- parser_state->pkg_end;
- }
- break;
-
- default:
-
- /* No action for all other opcodes */
- break;
- }
- break;
- }
- }
-
- /* Check for arguments that need to be processed */
-
- if (walk_state->arg_count) {
- /*
- * There are arguments (complex ones), push Op and
- * prepare for argument
- */
- status = acpi_ps_push_scope (parser_state, op,
- walk_state->arg_types, walk_state->arg_count);
- if (ACPI_FAILURE (status)) {
- goto close_this_op;
- }
- op = NULL;
- continue;
- }
-
- /*
- * All arguments have been processed -- Op is complete,
- * prepare for next
- */
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- if (walk_state->op_info->flags & AML_NAMED) {
- if (acpi_gbl_depth) {
- acpi_gbl_depth--;
- }
-
- if (op->common.aml_opcode == AML_REGION_OP) {
- /*
- * Skip parsing of control method or opregion body,
- * because we don't have enough info in the first pass
- * to parse them correctly.
- *
- * Completed parsing an op_region declaration, we now
- * know the length.
- */
- op->named.length = (u32) (parser_state->aml - op->named.data);
- }
- }
-
- if (walk_state->op_info->flags & AML_CREATE) {
- /*
- * Backup to beginning of create_xXXfield declaration (1 for
- * Opcode)
- *
- * body_length is unknown until we parse the body
- */
- op->named.length = (u32) (parser_state->aml - op->named.data);
- }
-
- /* This op complete, notify the dispatcher */
-
- if (walk_state->ascending_callback != NULL) {
- walk_state->op = op;
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
- }
-
-
-close_this_op:
- /*
- * Finished one argument of the containing scope
- */
- parser_state->scope->parse_scope.arg_count--;
-
- /* Close this Op (will result in parse subtree deletion) */
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
- if (pre_op) {
- acpi_ps_free_op (pre_op);
- pre_op = NULL;
- }
-
- switch (status) {
- case AE_OK:
- break;
-
-
- case AE_CTRL_TRANSFER:
-
- /* We are about to transfer to a called method. */
-
- walk_state->prev_op = op;
- walk_state->prev_arg_types = walk_state->arg_types;
- return_ACPI_STATUS (status);
-
-
- case AE_CTRL_END:
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- if (op) {
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
- }
- status = AE_OK;
- break;
-
-
- case AE_CTRL_BREAK:
- case AE_CTRL_CONTINUE:
-
- /* Pop off scopes until we find the While */
-
- while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- }
-
- /* Close this iteration of the While loop */
-
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
-
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
-
- status = AE_OK;
- break;
-
-
- case AE_CTRL_TERMINATE:
-
- status = AE_OK;
-
- /* Clean up */
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
-
-
- default: /* All other non-AE_OK status */
-
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
-
- /*
- * TBD: Cleanup parse ops on error
- */
-#if 0
- if (op == NULL) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- }
-#endif
- walk_state->prev_op = op;
- walk_state->prev_arg_types = walk_state->arg_types;
- return_ACPI_STATUS (status);
- }
-
- /* This scope complete? */
-
- if (acpi_ps_has_completed_scope (parser_state)) {
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
- }
- else {
- op = NULL;
- }
-
- } /* while parser_state->Aml */
-
-
- /*
- * Complete the last Op (if not completed), and clear the scope stack.
- * It is easily possible to end an AML "package" with an unbounded number
- * of open scopes (such as when several ASL blocks are closed with
- * sequential closing braces). We want to terminate each one cleanly.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op));
- do {
- if (op) {
- if (walk_state->ascending_callback != NULL) {
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = walk_state->ascending_callback (walk_state);
- status = acpi_ps_next_parse_state (walk_state, op, status);
- if (status == AE_CTRL_PENDING) {
- status = AE_OK;
- goto close_this_op;
- }
-
- if (status == AE_CTRL_TERMINATE) {
- status = AE_OK;
-
- /* Clean up */
- do {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
-
- acpi_ps_pop_scope (parser_state, &op,
- &walk_state->arg_types, &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
- }
-
- else if (ACPI_FAILURE (status)) {
- acpi_ps_complete_this_op (walk_state, op);
- return_ACPI_STATUS (status);
- }
- }
-
- acpi_ps_complete_this_op (walk_state, op);
- }
-
- acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
- &walk_state->arg_count);
-
- } while (op);
-
- return_ACPI_STATUS (status);
-}
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_parse_aml
@@ -1095,34 +435,29 @@ close_this_op:
*
******************************************************************************/
-acpi_status
-acpi_ps_parse_aml (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
{
- acpi_status status;
- acpi_status terminate_status;
- struct acpi_thread_state *thread;
- struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
- struct acpi_walk_state *previous_walk_state;
+ acpi_status status;
+ struct acpi_thread_state *thread;
+ struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
+ struct acpi_walk_state *previous_walk_state;
+ ACPI_FUNCTION_TRACE("ps_parse_aml");
- ACPI_FUNCTION_TRACE ("ps_parse_aml");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Entered with walk_state=%p Aml=%p size=%X\n",
- walk_state, walk_state->parser_state.aml,
- walk_state->parser_state.aml_size));
-
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Entered with walk_state=%p Aml=%p size=%X\n",
+ walk_state, walk_state->parser_state.aml,
+ walk_state->parser_state.aml_size));
/* Create and initialize a new thread state */
- thread = acpi_ut_create_thread_state ();
+ thread = acpi_ut_create_thread_state();
if (!thread) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
walk_state->thread = thread;
- acpi_ds_push_walk_state (walk_state, thread);
+ acpi_ds_push_walk_state(walk_state, thread);
/*
* This global allows the AML debugger to get a handle to the currently
@@ -1134,130 +469,136 @@ acpi_ps_parse_aml (
* Execute the walk loop as long as there is a valid Walk State. This
* handles nested control method invocations without recursion.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state));
status = AE_OK;
while (walk_state) {
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* The parse_loop executes AML until the method terminates
* or calls another method.
*/
- status = acpi_ps_parse_loop (walk_state);
+ status = acpi_ps_parse_loop(walk_state);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Completed one call to walk loop, %s State=%p\n",
- acpi_format_exception (status), walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Completed one call to walk loop, %s State=%p\n",
+ acpi_format_exception(status), walk_state));
if (status == AE_CTRL_TRANSFER) {
/*
* A method call was detected.
* Transfer control to the called control method
*/
- status = acpi_ds_call_control_method (thread, walk_state, NULL);
+ status =
+ acpi_ds_call_control_method(thread, walk_state,
+ NULL);
/*
* If the transfer to the new method method call worked, a new walk
* state was created -- get it
*/
- walk_state = acpi_ds_get_current_walk_state (thread);
+ walk_state = acpi_ds_get_current_walk_state(thread);
continue;
- }
- else if (status == AE_CTRL_TERMINATE) {
+ } else if (status == AE_CTRL_TERMINATE) {
status = AE_OK;
- }
- else if ((status != AE_OK) && (walk_state->method_desc)) {
- ACPI_REPORT_METHOD_ERROR ("Method execution failed",
- walk_state->method_node, NULL, status);
+ } else if ((status != AE_OK) && (walk_state->method_desc)) {
+ ACPI_REPORT_METHOD_ERROR("Method execution failed",
+ walk_state->method_node, NULL,
+ status);
+
+ /* Ensure proper cleanup */
+
+ walk_state->parse_flags |= ACPI_PARSE_EXECUTE;
/* Check for possible multi-thread reentrancy problem */
if ((status == AE_ALREADY_EXISTS) &&
- (!walk_state->method_desc->method.semaphore)) {
+ (!walk_state->method_desc->method.semaphore)) {
/*
* This method is marked not_serialized, but it tried to create
* a named object, causing the second thread entrance to fail.
* We will workaround this by marking the method permanently
* as Serialized.
*/
- walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
+ walk_state->method_desc->method.method_flags |=
+ AML_METHOD_SERIALIZED;
walk_state->method_desc->method.concurrency = 1;
}
}
- if (walk_state->method_desc) {
- /* Decrement the thread count on the method parse tree */
-
- if (walk_state->method_desc->method.thread_count) {
- walk_state->method_desc->method.thread_count--;
- }
- }
-
/* We are done with this walk, move on to the parent if any */
- walk_state = acpi_ds_pop_walk_state (thread);
+ walk_state = acpi_ds_pop_walk_state(thread);
/* Reset the current scope to the beginning of scope stack */
- acpi_ds_scope_stack_clear (walk_state);
+ acpi_ds_scope_stack_clear(walk_state);
/*
* If we just returned from the execution of a control method,
* there's lots of cleanup to do
*/
- if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
- terminate_status = acpi_ds_terminate_control_method (walk_state);
- if (ACPI_FAILURE (terminate_status)) {
- ACPI_REPORT_ERROR ((
- "Could not terminate control method properly\n"));
+ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
+ ACPI_PARSE_EXECUTE) {
+ if (walk_state->method_desc) {
+ /* Decrement the thread count on the method parse tree */
- /* Ignore error and continue */
+ walk_state->method_desc->method.thread_count--;
}
+
+ acpi_ds_terminate_control_method(walk_state);
}
/* Delete this walk state and all linked control states */
- acpi_ps_cleanup_scope (&walk_state->parser_state);
+ acpi_ps_cleanup_scope(&walk_state->parser_state);
previous_walk_state = walk_state;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "return_value=%p, implicit_value=%p State=%p\n",
- walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "return_value=%p, implicit_value=%p State=%p\n",
+ walk_state->return_desc,
+ walk_state->implicit_return_obj, walk_state));
/* Check if we have restarted a preempted walk */
- walk_state = acpi_ds_get_current_walk_state (thread);
+ walk_state = acpi_ds_get_current_walk_state(thread);
if (walk_state) {
- if (ACPI_SUCCESS (status)) {
+ if (ACPI_SUCCESS(status)) {
/*
* There is another walk state, restart it.
* If the method return value is not used by the parent,
* The object is deleted
*/
if (!previous_walk_state->return_desc) {
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->implicit_return_obj);
- }
- else {
+ status =
+ acpi_ds_restart_control_method
+ (walk_state,
+ previous_walk_state->
+ implicit_return_obj);
+ } else {
/*
* We have a valid return value, delete any implicit
* return value.
*/
- acpi_ds_clear_implicit_return (previous_walk_state);
+ acpi_ds_clear_implicit_return
+ (previous_walk_state);
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->return_desc);
+ status =
+ acpi_ds_restart_control_method
+ (walk_state,
+ previous_walk_state->return_desc);
}
- if (ACPI_SUCCESS (status)) {
- walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
+ if (ACPI_SUCCESS(status)) {
+ walk_state->walk_type |=
+ ACPI_WALK_METHOD_RESTART;
}
- }
- else {
+ } else {
/* On error, delete any return object */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ acpi_ut_remove_reference(previous_walk_state->
+ return_desc);
}
}
@@ -1268,37 +609,36 @@ acpi_ps_parse_aml (
else if (previous_walk_state->caller_return_desc) {
if (previous_walk_state->implicit_return_obj) {
*(previous_walk_state->caller_return_desc) =
- previous_walk_state->implicit_return_obj;
- }
- else {
- /* NULL if no return value */
+ previous_walk_state->implicit_return_obj;
+ } else {
+ /* NULL if no return value */
*(previous_walk_state->caller_return_desc) =
- previous_walk_state->return_desc;
+ previous_walk_state->return_desc;
}
- }
- else {
+ } else {
if (previous_walk_state->return_desc) {
/* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ acpi_ut_remove_reference(previous_walk_state->
+ return_desc);
}
if (previous_walk_state->implicit_return_obj) {
/* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference (previous_walk_state->implicit_return_obj);
+ acpi_ut_remove_reference(previous_walk_state->
+ implicit_return_obj);
}
}
- acpi_ds_delete_walk_state (previous_walk_state);
+ acpi_ds_delete_walk_state(previous_walk_state);
}
/* Normal exit */
- acpi_ex_release_all_mutexes (thread);
- acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
+ acpi_ex_release_all_mutexes(thread);
+ acpi_ut_delete_generic_state(ACPI_CAST_PTR
+ (union acpi_generic_state, thread));
acpi_gbl_current_walk_list = prev_walk_list;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index 8dcd1b1e7131..1c953b6f1af1 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psscope")
-
+ACPI_MODULE_NAME("psscope")
/*******************************************************************************
*
@@ -60,16 +58,13 @@
* DESCRIPTION: Get parent of current op being parsed
*
******************************************************************************/
-
-union acpi_parse_object *
-acpi_ps_get_parent_scope (
- struct acpi_parse_state *parser_state)
+union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
+ *parser_state)
{
return (parser_state->scope->parse_scope.op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_has_completed_scope
@@ -84,17 +79,14 @@ acpi_ps_get_parent_scope (
*
******************************************************************************/
-u8
-acpi_ps_has_completed_scope (
- struct acpi_parse_state *parser_state)
+u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)
{
return ((u8)
- ((parser_state->aml >= parser_state->scope->parse_scope.arg_end ||
- !parser_state->scope->parse_scope.arg_count)));
+ ((parser_state->aml >= parser_state->scope->parse_scope.arg_end
+ || !parser_state->scope->parse_scope.arg_count)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_init_scope
@@ -109,34 +101,30 @@ acpi_ps_has_completed_scope (
******************************************************************************/
acpi_status
-acpi_ps_init_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *root_op)
+acpi_ps_init_scope(struct acpi_parse_state * parser_state,
+ union acpi_parse_object * root_op)
{
- union acpi_generic_state *scope;
+ union acpi_generic_state *scope;
+ ACPI_FUNCTION_TRACE_PTR("ps_init_scope", root_op);
- ACPI_FUNCTION_TRACE_PTR ("ps_init_scope", root_op);
-
-
- scope = acpi_ut_create_generic_state ();
+ scope = acpi_ut_create_generic_state();
if (!scope) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
- scope->parse_scope.op = root_op;
+ scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
+ scope->parse_scope.op = root_op;
scope->parse_scope.arg_count = ACPI_VAR_ARGS;
- scope->parse_scope.arg_end = parser_state->aml_end;
- scope->parse_scope.pkg_end = parser_state->aml_end;
+ scope->parse_scope.arg_end = parser_state->aml_end;
+ scope->parse_scope.pkg_end = parser_state->aml_end;
- parser_state->scope = scope;
- parser_state->start_op = root_op;
+ parser_state->scope = scope;
+ parser_state->start_op = root_op;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_push_scope
@@ -153,48 +141,42 @@ acpi_ps_init_scope (
******************************************************************************/
acpi_status
-acpi_ps_push_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object *op,
- u32 remaining_args,
- u32 arg_count)
+acpi_ps_push_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object *op,
+ u32 remaining_args, u32 arg_count)
{
- union acpi_generic_state *scope;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_push_scope", op);
+ union acpi_generic_state *scope;
+ ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op);
- scope = acpi_ut_create_generic_state ();
+ scope = acpi_ut_create_generic_state();
if (!scope) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
- scope->parse_scope.op = op;
+ scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
+ scope->parse_scope.op = op;
scope->parse_scope.arg_list = remaining_args;
scope->parse_scope.arg_count = arg_count;
scope->parse_scope.pkg_end = parser_state->pkg_end;
/* Push onto scope stack */
- acpi_ut_push_generic_state (&parser_state->scope, scope);
+ acpi_ut_push_generic_state(&parser_state->scope, scope);
if (arg_count == ACPI_VAR_ARGS) {
/* Multiple arguments */
scope->parse_scope.arg_end = parser_state->pkg_end;
- }
- else {
+ } else {
/* Single argument */
- scope->parse_scope.arg_end = ACPI_TO_POINTER (ACPI_MAX_PTR);
+ scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_pop_scope
@@ -212,48 +194,41 @@ acpi_ps_push_scope (
******************************************************************************/
void
-acpi_ps_pop_scope (
- struct acpi_parse_state *parser_state,
- union acpi_parse_object **op,
- u32 *arg_list,
- u32 *arg_count)
+acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
+ union acpi_parse_object **op, u32 * arg_list, u32 * arg_count)
{
- union acpi_generic_state *scope = parser_state->scope;
-
-
- ACPI_FUNCTION_TRACE ("ps_pop_scope");
+ union acpi_generic_state *scope = parser_state->scope;
+ ACPI_FUNCTION_TRACE("ps_pop_scope");
/* Only pop the scope if there is in fact a next scope */
if (scope->common.next) {
- scope = acpi_ut_pop_generic_state (&parser_state->scope);
+ scope = acpi_ut_pop_generic_state(&parser_state->scope);
/* return to parsing previous op */
- *op = scope->parse_scope.op;
- *arg_list = scope->parse_scope.arg_list;
- *arg_count = scope->parse_scope.arg_count;
+ *op = scope->parse_scope.op;
+ *arg_list = scope->parse_scope.arg_list;
+ *arg_count = scope->parse_scope.arg_count;
parser_state->pkg_end = scope->parse_scope.pkg_end;
/* All done with this scope state structure */
- acpi_ut_delete_generic_state (scope);
- }
- else {
+ acpi_ut_delete_generic_state(scope);
+ } else {
/* empty parse stack, prepare to fetch next opcode */
- *op = NULL;
+ *op = NULL;
*arg_list = 0;
*arg_count = 0;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "Popped Op %p Args %X\n", *op, *arg_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Popped Op %p Args %X\n", *op, *arg_count));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_cleanup_scope
@@ -267,15 +242,11 @@ acpi_ps_pop_scope (
*
******************************************************************************/
-void
-acpi_ps_cleanup_scope (
- struct acpi_parse_state *parser_state)
+void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state)
{
- union acpi_generic_state *scope;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state);
+ union acpi_generic_state *scope;
+ ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state);
if (!parser_state) {
return_VOID;
@@ -284,10 +255,9 @@ acpi_ps_cleanup_scope (
/* Delete anything on the scope stack */
while (parser_state->scope) {
- scope = acpi_ut_pop_generic_state (&parser_state->scope);
- acpi_ut_delete_generic_state (scope);
+ scope = acpi_ut_pop_generic_state(&parser_state->scope);
+ acpi_ut_delete_generic_state(scope);
}
return_VOID;
}
-
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index d5aafe73fca0..f0e755884eea 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -41,23 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("pstree")
+ACPI_MODULE_NAME("pstree")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
-union acpi_parse_object *
-acpi_ps_get_child (
- union acpi_parse_object *op);
+union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op);
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_arg
@@ -71,21 +66,16 @@ acpi_ps_get_child (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_arg (
- union acpi_parse_object *op,
- u32 argn)
+union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
{
- union acpi_parse_object *arg = NULL;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *arg = NULL;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_ENTRY();
/* Get the info structure for this opcode */
- op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
+ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Invalid opcode or ASCII character */
@@ -111,7 +101,6 @@ acpi_ps_get_arg (
return (arg);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_append_arg
@@ -126,16 +115,12 @@ acpi_ps_get_arg (
******************************************************************************/
void
-acpi_ps_append_arg (
- union acpi_parse_object *op,
- union acpi_parse_object *arg)
+acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
{
- union acpi_parse_object *prev_arg;
- const struct acpi_opcode_info *op_info;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *prev_arg;
+ const struct acpi_opcode_info *op_info;
+ ACPI_FUNCTION_ENTRY();
if (!op) {
return;
@@ -143,12 +128,11 @@ acpi_ps_append_arg (
/* Get the info structure for this opcode */
- op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
+ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
/* Invalid opcode */
- ACPI_REPORT_ERROR (("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n",
- op->common.aml_opcode));
+ ACPI_REPORT_ERROR(("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->common.aml_opcode));
return;
}
@@ -170,8 +154,7 @@ acpi_ps_append_arg (
prev_arg = prev_arg->common.next;
}
prev_arg->common.next = arg;
- }
- else {
+ } else {
/* No argument list, this will be the first argument */
op->common.value.arg = arg;
@@ -185,7 +168,6 @@ acpi_ps_append_arg (
}
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -201,18 +183,14 @@ acpi_ps_append_arg (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_depth_next (
- union acpi_parse_object *origin,
- union acpi_parse_object *op)
+union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
+ union acpi_parse_object *op)
{
- union acpi_parse_object *next = NULL;
- union acpi_parse_object *parent;
- union acpi_parse_object *arg;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent;
+ union acpi_parse_object *arg;
+ ACPI_FUNCTION_ENTRY();
if (!op) {
return (NULL);
@@ -220,7 +198,7 @@ acpi_ps_get_depth_next (
/* Look for an argument or child */
- next = acpi_ps_get_arg (op, 0);
+ next = acpi_ps_get_arg(op, 0);
if (next) {
return (next);
}
@@ -237,7 +215,7 @@ acpi_ps_get_depth_next (
parent = op->common.parent;
while (parent) {
- arg = acpi_ps_get_arg (parent, 0);
+ arg = acpi_ps_get_arg(parent, 0);
while (arg && (arg != origin) && (arg != op)) {
arg = arg->common.next;
}
@@ -261,7 +239,6 @@ acpi_ps_get_depth_next (
return (next);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -275,15 +252,11 @@ acpi_ps_get_depth_next (
*
******************************************************************************/
-union acpi_parse_object *
-acpi_ps_get_child (
- union acpi_parse_object *op)
+union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
{
- union acpi_parse_object *child = NULL;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_parse_object *child = NULL;
+ ACPI_FUNCTION_ENTRY();
switch (op->common.aml_opcode) {
case AML_SCOPE_OP:
@@ -292,10 +265,9 @@ acpi_ps_get_child (
case AML_THERMAL_ZONE_OP:
case AML_INT_METHODCALL_OP:
- child = acpi_ps_get_arg (op, 0);
+ child = acpi_ps_get_arg(op, 0);
break;
-
case AML_BUFFER_OP:
case AML_PACKAGE_OP:
case AML_METHOD_OP:
@@ -303,24 +275,21 @@ acpi_ps_get_child (
case AML_WHILE_OP:
case AML_FIELD_OP:
- child = acpi_ps_get_arg (op, 1);
+ child = acpi_ps_get_arg(op, 1);
break;
-
case AML_POWER_RES_OP:
case AML_INDEX_FIELD_OP:
- child = acpi_ps_get_arg (op, 2);
+ child = acpi_ps_get_arg(op, 2);
break;
-
case AML_PROCESSOR_OP:
case AML_BANK_FIELD_OP:
- child = acpi_ps_get_arg (op, 3);
+ child = acpi_ps_get_arg(op, 3);
break;
-
default:
/* All others have no children */
break;
@@ -330,5 +299,4 @@ acpi_ps_get_child (
}
#endif
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index a10f88715d43..2075efbb4324 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -41,14 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psutils")
-
+ACPI_MODULE_NAME("psutils")
/*******************************************************************************
*
@@ -61,15 +59,11 @@
* DESCRIPTION: Create a Scope and associated namepath op with the root name
*
******************************************************************************/
-
-union acpi_parse_object *
-acpi_ps_create_scope_op (
- void)
+union acpi_parse_object *acpi_ps_create_scope_op(void)
{
- union acpi_parse_object *scope_op;
+ union acpi_parse_object *scope_op;
-
- scope_op = acpi_ps_alloc_op (AML_SCOPE_OP);
+ scope_op = acpi_ps_alloc_op(AML_SCOPE_OP);
if (!scope_op) {
return (NULL);
}
@@ -78,7 +72,6 @@ acpi_ps_create_scope_op (
return (scope_op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_init_op
@@ -92,23 +85,19 @@ acpi_ps_create_scope_op (
*
******************************************************************************/
-void
-acpi_ps_init_op (
- union acpi_parse_object *op,
- u16 opcode)
+void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
op->common.data_type = ACPI_DESC_TYPE_PARSER;
op->common.aml_opcode = opcode;
- ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name,
- (acpi_ps_get_opcode_info (opcode))->name,
- sizeof (op->common.aml_op_name)));
+ ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name,
+ (acpi_ps_get_opcode_info
+ (opcode))->name,
+ sizeof(op->common.aml_op_name)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_alloc_op
@@ -123,29 +112,23 @@ acpi_ps_init_op (
*
******************************************************************************/
-union acpi_parse_object*
-acpi_ps_alloc_op (
- u16 opcode)
+union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
{
- union acpi_parse_object *op;
- const struct acpi_opcode_info *op_info;
- u8 flags = ACPI_PARSEOP_GENERIC;
-
+ union acpi_parse_object *op;
+ const struct acpi_opcode_info *op_info;
+ u8 flags = ACPI_PARSEOP_GENERIC;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- op_info = acpi_ps_get_opcode_info (opcode);
+ op_info = acpi_ps_get_opcode_info(opcode);
/* Determine type of parse_op required */
if (op_info->flags & AML_DEFER) {
flags = ACPI_PARSEOP_DEFERRED;
- }
- else if (op_info->flags & AML_NAMED) {
+ } else if (op_info->flags & AML_NAMED) {
flags = ACPI_PARSEOP_NAMED;
- }
- else if (opcode == AML_INT_BYTELIST_OP) {
+ } else if (opcode == AML_INT_BYTELIST_OP) {
flags = ACPI_PARSEOP_BYTELIST;
}
@@ -154,25 +137,25 @@ acpi_ps_alloc_op (
if (flags == ACPI_PARSEOP_GENERIC) {
/* The generic op (default) is by far the most common (16 to 1) */
- op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE);
- }
- else {
+ op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
+ memset(op, 0, sizeof(struct acpi_parse_obj_common));
+ } else {
/* Extended parseop */
- op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT);
+ op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache);
+ memset(op, 0, sizeof(struct acpi_parse_obj_named));
}
/* Initialize the Op */
if (op) {
- acpi_ps_init_op (op, opcode);
+ acpi_ps_init_op(op, opcode);
op->common.flags = flags;
}
return (op);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ps_free_op
@@ -186,53 +169,22 @@ acpi_ps_alloc_op (
*
******************************************************************************/
-void
-acpi_ps_free_op (
- union acpi_parse_object *op)
+void acpi_ps_free_op(union acpi_parse_object *op)
{
- ACPI_FUNCTION_NAME ("ps_free_op");
-
+ ACPI_FUNCTION_NAME("ps_free_op");
if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
+ op));
}
if (op->common.flags & ACPI_PARSEOP_GENERIC) {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op);
- }
- else {
- acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op);
+ (void)acpi_os_release_object(acpi_gbl_ps_node_cache, op);
+ } else {
+ (void)acpi_os_release_object(acpi_gbl_ps_node_ext_cache, op);
}
}
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_parse_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Free all objects that are on the parse cache list.
- *
- ******************************************************************************/
-
-void
-acpi_ps_delete_parse_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ps_delete_parse_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE);
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_PSNODE_EXT);
- return_VOID;
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: Utility functions
@@ -241,36 +193,27 @@ acpi_ps_delete_parse_cache (
*
******************************************************************************/
-
/*
* Is "c" a namestring lead character?
*/
-u8
-acpi_ps_is_leading_char (
- u32 c)
+u8 acpi_ps_is_leading_char(u32 c)
{
return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
}
-
/*
* Is "c" a namestring prefix character?
*/
-u8
-acpi_ps_is_prefix_char (
- u32 c)
+u8 acpi_ps_is_prefix_char(u32 c)
{
return ((u8) (c == '\\' || c == '^'));
}
-
/*
* Get op's name (4-byte name segment) or 0 if unnamed
*/
#ifdef ACPI_FUTURE_USAGE
-u32
-acpi_ps_get_name (
- union acpi_parse_object *op)
+u32 acpi_ps_get_name(union acpi_parse_object * op)
{
/* The "generic" object has no name associated with it */
@@ -283,16 +226,12 @@ acpi_ps_get_name (
return (op->named.name);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*
* Set op's name
*/
-void
-acpi_ps_set_name (
- union acpi_parse_object *op,
- u32 name)
+void acpi_ps_set_name(union acpi_parse_object *op, u32 name)
{
/* The "generic" object has no name associated with it */
@@ -303,4 +242,3 @@ acpi_ps_set_name (
op->named.name = name;
}
-
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 9d20cb2ceb51..08f2321b6ded 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("pswalk")
-
+ACPI_MODULE_NAME("pswalk")
/*******************************************************************************
*
@@ -60,18 +58,13 @@
* DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *subtree_root)
+void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
{
- union acpi_parse_object *op = subtree_root;
- union acpi_parse_object *next = NULL;
- union acpi_parse_object *parent = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
+ union acpi_parse_object *op = subtree_root;
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent = NULL;
+ ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root);
/* Visit all nodes in the subtree */
@@ -81,7 +74,7 @@ acpi_ps_delete_parse_tree (
if (op != parent) {
/* Look for an argument or child of the current op */
- next = acpi_ps_get_arg (op, 0);
+ next = acpi_ps_get_arg(op, 0);
if (next) {
/* Still going downward in tree (Op is not completed yet) */
@@ -95,7 +88,7 @@ acpi_ps_delete_parse_tree (
next = op->common.next;
parent = op->common.parent;
- acpi_ps_free_op (op);
+ acpi_ps_free_op(op);
/* If we are back to the starting point, the walk is complete. */
@@ -104,8 +97,7 @@ acpi_ps_delete_parse_tree (
}
if (next) {
op = next;
- }
- else {
+ } else {
op = parent;
}
}
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index dba893648e84..4dcbd443160e 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -41,24 +41,27 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psxface")
+ACPI_MODULE_NAME("psxface")
+
+/* Local Prototypes */
+static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
+static void
+acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action);
/*******************************************************************************
*
- * FUNCTION: acpi_psx_execute
+ * FUNCTION: acpi_ps_execute_method
*
* PARAMETERS: Info - Method info block, contains:
* Node - Method Node to execute
+ * obj_desc - Method object
* Parameters - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
* NULL if no parameters are being passed.
@@ -67,6 +70,7 @@
* parameter_type - Type of Parameter list
* return_object - Where to put method's return value (if
* any). If NULL, no value is returned.
+ * pass_number - Parse or execute pass
*
* RETURN: Status
*
@@ -74,173 +78,170 @@
*
******************************************************************************/
-acpi_status
-acpi_psx_execute (
- struct acpi_parameter_info *info)
+acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- u32 i;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
-
-
- ACPI_FUNCTION_TRACE ("psx_execute");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ps_execute_method");
- /* Validate the Node and get the attached object */
+ /* Validate the Info and method Node */
if (!info || !info->node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
- }
-
- obj_desc = acpi_ns_get_attached_object (info->node);
- if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
/* Init for new method, wait on concurrency semaphore */
- status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if ((info->parameter_type == ACPI_PARAM_ARGS) &&
- (info->parameters)) {
- /*
- * The caller "owns" the parameters, so give each one an extra
- * reference
- */
- for (i = 0; info->parameters[i]; i++) {
- acpi_ut_add_reference (info->parameters[i]);
- }
- }
+ /*
+ * The caller "owns" the parameters, so give each one an extra
+ * reference
+ */
+ acpi_ps_update_parameter_list(info, REF_INCREMENT);
/*
* 1) Perform the first pass parse of the method to enter any
- * named objects that it creates into the namespace
+ * named objects that it creates into the namespace
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Parse **** Entry=%p obj=%p\n",
- info->node, obj_desc));
-
- /* Create and init a Root Node */
-
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Parse **** Entry=%p obj=%p\n",
+ info->node, info->obj_desc));
+
+ info->pass_number = 1;
+ status = acpi_ps_execute_pass(info);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
/*
- * Get a new owner_id for objects created by this method. Namespace
- * objects (such as Operation Regions) can be created during the
- * first pass parse.
+ * 2) Execute the method. Performs second pass parse simultaneously
*/
- obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Execution **** Entry=%p obj=%p\n",
+ info->node, info->obj_desc));
- /* Create and initialize a new walk state */
+ info->pass_number = 3;
+ status = acpi_ps_execute_pass(info);
- walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
- }
+ cleanup:
+ /* Take away the extra reference that we gave the parameters above */
- status = acpi_ds_init_aml_walk (walk_state, op, info->node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 1);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
- }
+ acpi_ps_update_parameter_list(info, REF_DECREMENT);
- /* Parse the AML */
+ /* Exit now if error above */
- status = acpi_ps_parse_aml (walk_state);
- acpi_ps_delete_parse_tree (op);
- if (ACPI_FAILURE (status)) {
- goto cleanup1; /* Walk state is already deleted */
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
- * 2) Execute the method. Performs second pass parse simultaneously
+ * If the method has returned an object, signal this to the caller with
+ * a control exception code
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Execution **** Entry=%p obj=%p\n",
- info->node, obj_desc));
-
- /* Create and init a Root Node */
+ if (info->return_object) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Method returned obj_desc=%p\n",
+ info->return_object));
+ ACPI_DUMP_STACK_ENTRY(info->return_object);
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
+ status = AE_CTRL_RETURN_VALUE;
}
- /* Init new op with the method name and pointer back to the NS node */
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_update_parameter_list
+ *
+ * PARAMETERS: Info - See struct acpi_parameter_info
+ * (Used: parameter_type and Parameters)
+ * Action - Add or Remove reference
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Update reference count on all method parameter objects
+ *
+ ******************************************************************************/
- acpi_ps_set_name (op, info->node->name.integer);
- op->common.node = info->node;
+static void
+acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
+{
+ acpi_native_uint i;
- /* Create and initialize a new walk state */
+ if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+ /* Update reference count for each parameter */
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
- }
+ for (i = 0; info->parameters[i]; i++) {
+ /* Ignore errors, just do them all */
- status = acpi_ds_init_aml_walk (walk_state, op, info->node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, info, 3);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
+ (void)acpi_ut_update_object_reference(info->
+ parameters[i],
+ action);
+ }
}
+}
- /* The walk of the parse tree is where we actually execute the method */
-
- status = acpi_ps_parse_aml (walk_state);
- goto cleanup2; /* Walk state already deleted */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_execute_pass
+ *
+ * PARAMETERS: Info - See struct acpi_parameter_info
+ * (Used: pass_number, Node, and obj_desc)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Single AML pass: Parse or Execute a control method
+ *
+ ******************************************************************************/
+static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info)
+{
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
-cleanup3:
- acpi_ds_delete_walk_state (walk_state);
+ ACPI_FUNCTION_TRACE("ps_execute_pass");
-cleanup2:
- acpi_ps_delete_parse_tree (op);
+ /* Create and init a Root Node */
-cleanup1:
- if ((info->parameter_type == ACPI_PARAM_ARGS) &&
- (info->parameters)) {
- /* Take away the extra reference that we gave the parameters above */
+ op = acpi_ps_create_scope_op();
+ if (!op) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
- for (i = 0; info->parameters[i]; i++) {
- /* Ignore errors, just do them all */
+ /* Create and initialize a new walk state */
- (void) acpi_ut_update_object_reference (
- info->parameters[i], REF_DECREMENT);
- }
+ walk_state =
+ acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
+ NULL, NULL);
+ if (!walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ds_init_aml_walk(walk_state, op, info->node,
+ info->obj_desc->method.aml_start,
+ info->obj_desc->method.aml_length,
+ info->pass_number == 1 ? NULL : info,
+ info->pass_number);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
}
- /*
- * If the method has returned an object, signal this to the caller with
- * a control exception code
- */
- if (info->return_object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
- info->return_object));
- ACPI_DUMP_STACK_ENTRY (info->return_object);
-
- status = AE_CTRL_RETURN_VALUE;
- }
+ /* Parse the AML */
- return_ACPI_STATUS (status);
-}
+ status = acpi_ps_parse_aml(walk_state);
+ /* Walk state was deleted by parse_aml */
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 5148f3c10b5c..2a718df769b5 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -35,22 +35,17 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_bind")
+ACPI_MODULE_NAME("pci_bind")
struct acpi_pci_data {
- struct acpi_pci_id id;
- struct pci_bus *bus;
- struct pci_dev *dev;
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
+ struct pci_dev *dev;
};
-
-void
-acpi_pci_data_handler (
- acpi_handle handle,
- u32 function,
- void *context)
+static void acpi_pci_data_handler(acpi_handle handle, u32 function,
+ void *context)
{
ACPI_FUNCTION_TRACE("acpi_pci_data_handler");
@@ -59,7 +54,6 @@ acpi_pci_data_handler (
return_VOID;
}
-
/**
* acpi_get_pci_id
* ------------------
@@ -67,15 +61,12 @@ acpi_pci_data_handler (
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
* This typically occurs when resolving PCI operation region information.
*/
-acpi_status
-acpi_get_pci_id (
- acpi_handle handle,
- struct acpi_pci_id *id)
+acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
- struct acpi_pci_data *data = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_data *data = NULL;
ACPI_FUNCTION_TRACE("acpi_get_pci_id");
@@ -84,52 +75,50 @@ acpi_get_pci_id (
result = acpi_bus_get_device(handle, &device);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI Bus context for device %s\n",
- acpi_device_bid(device)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI Bus context for device %s\n",
+ acpi_device_bid(device)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
- status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
+ status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data);
if (ACPI_FAILURE(status) || !data) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI-PCI context for device %s\n",
- acpi_device_bid(device)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI-PCI context for device %s\n",
+ acpi_device_bid(device)));
return_ACPI_STATUS(status);
}
*id = data->id;
-
+
/*
- id->segment = data->id.segment;
- id->bus = data->id.bus;
- id->device = data->id.device;
- id->function = data->id.function;
- */
+ id->segment = data->id.segment;
+ id->bus = data->id.bus;
+ id->device = data->id.device;
+ id->function = data->id.function;
+ */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %s has PCI address %02x:%02x:%02x.%02x\n",
- acpi_device_bid(device), id->segment, id->bus,
- id->device, id->function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %s has PCI address %02x:%02x:%02x.%02x\n",
+ acpi_device_bid(device), id->segment, id->bus,
+ id->device, id->function));
return_ACPI_STATUS(AE_OK);
}
+
EXPORT_SYMBOL(acpi_get_pci_id);
-
-int
-acpi_pci_bind (
- struct acpi_device *device)
+int acpi_pci_bind(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- struct acpi_pci_data *pdata = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
- acpi_handle handle = NULL;
- struct pci_dev *dev;
- struct pci_bus *bus;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ struct acpi_pci_data *pdata = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
+ acpi_handle handle = NULL;
+ struct pci_dev *dev;
+ struct pci_bus *bus;
ACPI_FUNCTION_TRACE("acpi_pci_bind");
@@ -137,34 +126,34 @@ acpi_pci_bind (
return_VALUE(-EINVAL);
pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data){
- kfree (pathname);
+ if (!data) {
+ kfree(pathname);
return_VALUE(-ENOMEM);
}
memset(data, 0, sizeof(struct acpi_pci_data));
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
- pathname));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
+ pathname));
/*
* Segment & Bus
* -------------
* These are obtained via the parent device's ACPI-PCI context.
*/
- status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
- (void**) &pdata);
+ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
+ (void **)&pdata);
if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid ACPI-PCI context for parent device %s\n",
- acpi_device_bid(device->parent)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid ACPI-PCI context for parent device %s\n",
+ acpi_device_bid(device->parent)));
result = -ENODEV;
goto end;
}
@@ -181,8 +170,8 @@ acpi_pci_bind (
data->id.function = device->pnp.bus_address & 0xFFFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n",
- data->id.segment, data->id.bus, data->id.device,
- data->id.function));
+ data->id.segment, data->id.bus, data->id.device,
+ data->id.function));
/*
* TBD: Support slot devices (e.g. function=0xFFFF).
@@ -202,25 +191,25 @@ acpi_pci_bind (
if (bus) {
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->devfn == PCI_DEVFN(data->id.device,
- data->id.function)) {
+ data->id.function)) {
data->dev = dev;
break;
}
}
}
if (!data->dev) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
if (!data->dev->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
result = -ENODEV;
goto end;
}
@@ -232,10 +221,10 @@ acpi_pci_bind (
* facilitate callbacks for all of its children.
*/
if (data->dev->subordinate) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
- data->id.segment, data->id.bus,
- data->id.device, data->id.function));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
+ data->id.segment, data->id.bus,
+ data->id.device, data->id.function));
data->bus = data->dev->subordinate;
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
@@ -249,8 +238,8 @@ acpi_pci_bind (
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to attach ACPI-PCI context to device %s\n",
- acpi_device_bid(device)));
+ "Unable to attach ACPI-PCI context to device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -267,15 +256,15 @@ acpi_pci_bind (
*/
status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status)) {
- if (data->bus) /* PCI-PCI bridge */
- acpi_pci_irq_add_prt(device->handle, data->id.segment,
- data->bus->number);
- else /* non-bridge PCI device */
+ if (data->bus) /* PCI-PCI bridge */
acpi_pci_irq_add_prt(device->handle, data->id.segment,
- data->id.bus);
+ data->bus->number);
+ else /* non-bridge PCI device */
+ acpi_pci_irq_add_prt(device->handle, data->id.segment,
+ data->id.bus);
}
-end:
+ end:
kfree(pathname);
if (result)
kfree(data);
@@ -283,22 +272,21 @@ end:
return_VALUE(result);
}
-int acpi_pci_unbind(
- struct acpi_device *device)
+int acpi_pci_unbind(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_unbind");
if (!device || !device->parent)
return_VALUE(-EINVAL);
- pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
@@ -306,14 +294,16 @@ int acpi_pci_unbind(
buffer.pointer = pathname;
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
- pathname));
+ pathname));
kfree(pathname);
- status = acpi_get_data(device->handle, acpi_pci_data_handler, (void**)&data);
+ status =
+ acpi_get_data(device->handle, acpi_pci_data_handler,
+ (void **)&data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to get data from device %s\n",
- acpi_device_bid(device)));
+ "Unable to get data from device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -321,8 +311,8 @@ int acpi_pci_unbind(
status = acpi_detach_data(device->handle, acpi_pci_data_handler);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to detach data from device %s\n",
- acpi_device_bid(device)));
+ "Unable to detach data from device %s\n",
+ acpi_device_bid(device)));
result = -ENODEV;
goto end;
}
@@ -331,39 +321,37 @@ int acpi_pci_unbind(
}
kfree(data);
-end:
+ end:
return_VALUE(result);
}
-int
-acpi_pci_bind_root (
- struct acpi_device *device,
- struct acpi_pci_id *id,
- struct pci_bus *bus)
+int
+acpi_pci_bind_root(struct acpi_device *device,
+ struct acpi_pci_id *id, struct pci_bus *bus)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_pci_data *data = NULL;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_bind_root");
pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
- if (!device || !id || !bus){
+ if (!device || !id || !bus) {
kfree(pathname);
return_VALUE(-EINVAL);
}
data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data){
+ if (!data) {
kfree(pathname);
return_VALUE(-ENOMEM);
}
@@ -377,18 +365,18 @@ acpi_pci_bind_root (
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
- "%02x:%02x\n", pathname, id->segment, id->bus));
+ "%02x:%02x\n", pathname, id->segment, id->bus));
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to attach ACPI-PCI context to device %s\n",
- pathname));
+ "Unable to attach ACPI-PCI context to device %s\n",
+ pathname));
result = -ENODEV;
goto end;
}
-end:
+ end:
kfree(pathname);
if (result != 0)
kfree(data);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index bb973d2109a1..09567c2edcfb 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -38,26 +38,22 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_irq")
+ACPI_MODULE_NAME("pci_irq")
-static struct acpi_prt_list acpi_prt;
+static struct acpi_prt_list acpi_prt;
static DEFINE_SPINLOCK(acpi_prt_lock);
/* --------------------------------------------------------------------------
PCI IRQ Routing Table (PRT) Support
-------------------------------------------------------------------------- */
-static struct acpi_prt_entry *
-acpi_pci_irq_find_prt_entry (
- int segment,
- int bus,
- int device,
- int pin)
+static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
+ int bus,
+ int device, int pin)
{
- struct list_head *node = NULL;
- struct acpi_prt_entry *entry = NULL;
+ struct list_head *node = NULL;
+ struct acpi_prt_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
@@ -72,10 +68,10 @@ acpi_pci_irq_find_prt_entry (
spin_lock(&acpi_prt_lock);
list_for_each(node, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
- if ((segment == entry->id.segment)
- && (bus == entry->id.bus)
- && (device == entry->id.device)
- && (pin == entry->pin)) {
+ if ((segment == entry->id.segment)
+ && (bus == entry->id.bus)
+ && (device == entry->id.device)
+ && (pin == entry->pin)) {
spin_unlock(&acpi_prt_lock);
return_PTR(entry);
}
@@ -85,15 +81,11 @@ acpi_pci_irq_find_prt_entry (
return_PTR(NULL);
}
-
static int
-acpi_pci_irq_add_entry (
- acpi_handle handle,
- int segment,
- int bus,
- struct acpi_pci_routing_table *prt)
+acpi_pci_irq_add_entry(acpi_handle handle,
+ int segment, int bus, struct acpi_pci_routing_table *prt)
{
- struct acpi_prt_entry *entry = NULL;
+ struct acpi_prt_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_add_entry");
@@ -139,9 +131,10 @@ acpi_pci_irq_add_entry (
entry->link.index = prt->source_index;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
- " %02X:%02X:%02X[%c] -> %s[%d]\n",
- entry->id.segment, entry->id.bus, entry->id.device,
- ('A' + entry->pin), prt->source, entry->link.index));
+ " %02X:%02X:%02X[%c] -> %s[%d]\n",
+ entry->id.segment, entry->id.bus,
+ entry->id.device, ('A' + entry->pin), prt->source,
+ entry->link.index));
spin_lock(&acpi_prt_lock);
list_add_tail(&entry->node, &acpi_prt.entries);
@@ -151,38 +144,29 @@ acpi_pci_irq_add_entry (
return_VALUE(0);
}
-
static void
-acpi_pci_irq_del_entry (
- int segment,
- int bus,
- struct acpi_prt_entry *entry)
+acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry)
{
- if (segment == entry->id.segment && bus == entry->id.bus){
+ if (segment == entry->id.segment && bus == entry->id.bus) {
acpi_prt.count--;
list_del(&entry->node);
kfree(entry);
}
}
-
-int
-acpi_pci_irq_add_prt (
- acpi_handle handle,
- int segment,
- int bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
{
- acpi_status status = AE_OK;
- char *pathname = NULL;
- struct acpi_buffer buffer = {0, NULL};
- struct acpi_pci_routing_table *prt = NULL;
- struct acpi_pci_routing_table *entry = NULL;
- static int first_time = 1;
+ acpi_status status = AE_OK;
+ char *pathname = NULL;
+ struct acpi_buffer buffer = { 0, NULL };
+ struct acpi_pci_routing_table *prt = NULL;
+ struct acpi_pci_routing_table *entry = NULL;
+ static int first_time = 1;
ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
- pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if(!pathname)
+ pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ if (!pathname)
return_VALUE(-ENOMEM);
memset(pathname, 0, ACPI_PATHNAME_MAX);
@@ -202,7 +186,7 @@ acpi_pci_irq_add_prt (
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
- pathname);
+ pathname);
/*
* Evaluate this _PRT and add its entries to our global list (acpi_prt).
@@ -214,12 +198,12 @@ acpi_pci_irq_add_prt (
status = acpi_get_irq_routing_table(handle, &buffer);
if (status != AE_BUFFER_OVERFLOW) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
- acpi_format_exception(status)));
+ acpi_format_exception(status)));
return_VALUE(-ENODEV);
}
prt = kmalloc(buffer.length, GFP_KERNEL);
- if (!prt){
+ if (!prt) {
return_VALUE(-ENOMEM);
}
memset(prt, 0, buffer.length);
@@ -228,7 +212,7 @@ acpi_pci_irq_add_prt (
status = acpi_get_irq_routing_table(handle, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
- acpi_format_exception(status)));
+ acpi_format_exception(status)));
kfree(buffer.pointer);
return_VALUE(-ENODEV);
}
@@ -238,7 +222,7 @@ acpi_pci_irq_add_prt (
while (entry && (entry->length > 0)) {
acpi_pci_irq_add_entry(handle, segment, bus, entry);
entry = (struct acpi_pci_routing_table *)
- ((unsigned long) entry + entry->length);
+ ((unsigned long)entry + entry->length);
}
kfree(prt);
@@ -246,18 +230,18 @@ acpi_pci_irq_add_prt (
return_VALUE(0);
}
-void
-acpi_pci_irq_del_prt (int segment, int bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
{
- struct list_head *node = NULL, *n = NULL;
- struct acpi_prt_entry *entry = NULL;
+ struct list_head *node = NULL, *n = NULL;
+ struct acpi_prt_entry *entry = NULL;
- if (!acpi_prt.count) {
+ if (!acpi_prt.count) {
return;
}
- printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n",
- segment, bus);
+ printk(KERN_DEBUG
+ "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", segment,
+ bus);
spin_lock(&acpi_prt_lock);
list_for_each_safe(node, n, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
@@ -266,26 +250,27 @@ acpi_pci_irq_del_prt (int segment, int bus)
}
spin_unlock(&acpi_prt_lock);
}
+
/* --------------------------------------------------------------------------
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
-typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **);
+typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **);
static int
acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
- int *edge_level,
- int *active_high_low,
- char **link)
+ int *edge_level, int *active_high_low, char **link)
{
- int irq;
+ int irq;
ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq");
if (entry->link.handle) {
irq = acpi_pci_link_allocate_irq(entry->link.handle,
- entry->link.index, edge_level, active_high_low, link);
+ entry->link.index, edge_level,
+ active_high_low, link);
if (irq < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ link routing entry\n"));
return_VALUE(-1);
}
} else {
@@ -300,11 +285,9 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
static int
acpi_pci_free_irq(struct acpi_prt_entry *entry,
- int *edge_level,
- int *active_high_low,
- char **link)
+ int *edge_level, int *active_high_low, char **link)
{
- int irq;
+ int irq;
ACPI_FUNCTION_TRACE("acpi_pci_free_irq");
if (entry->link.handle) {
@@ -314,38 +297,36 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry,
}
return_VALUE(irq);
}
+
/*
* acpi_pci_irq_lookup
* success: return IRQ >= 0
* failure: return -1
*/
static int
-acpi_pci_irq_lookup (
- struct pci_bus *bus,
- int device,
- int pin,
- int *edge_level,
- int *active_high_low,
- char **link,
- irq_lookup_func func)
+acpi_pci_irq_lookup(struct pci_bus *bus,
+ int device,
+ int pin,
+ int *edge_level,
+ int *active_high_low, char **link, irq_lookup_func func)
{
- struct acpi_prt_entry *entry = NULL;
+ struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
int bus_nr = bus->number;
int ret;
ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
- segment, bus_nr, device, ('A' + pin)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
+ segment, bus_nr, device, ('A' + pin)));
- entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
+ entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
if (!entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
return_VALUE(-1);
}
-
+
ret = func(entry, edge_level, active_high_low, link);
return_VALUE(ret);
}
@@ -356,17 +337,14 @@ acpi_pci_irq_lookup (
* failure: return < 0
*/
static int
-acpi_pci_irq_derive (
- struct pci_dev *dev,
- int pin,
- int *edge_level,
- int *active_high_low,
- char **link,
- irq_lookup_func func)
+acpi_pci_irq_derive(struct pci_dev *dev,
+ int pin,
+ int *edge_level,
+ int *active_high_low, char **link, irq_lookup_func func)
{
- struct pci_dev *bridge = dev;
- int irq = -1;
- u8 bridge_pin = 0;
+ struct pci_dev *bridge = dev;
+ int irq = -1;
+ u8 bridge_pin = 0;
ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
@@ -383,28 +361,33 @@ acpi_pci_irq_derive (
if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
/* PC card has the same IRQ as its cardbridge */
- pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
+ pci_read_config_byte(bridge, PCI_INTERRUPT_PIN,
+ &bridge_pin);
if (!bridge_pin) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No interrupt pin configured for device %s\n", pci_name(bridge)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No interrupt pin configured for device %s\n",
+ pci_name(bridge)));
return_VALUE(-1);
}
/* Pin is from 0 to 3 */
- bridge_pin --;
+ bridge_pin--;
pin = bridge_pin;
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low, link, func);
+ pin, edge_level, active_high_low,
+ link, func);
}
if (irq < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev)));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to derive IRQ for device %s\n",
+ pci_name(dev)));
return_VALUE(-1);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
- irq, pci_name(dev), pci_name(bridge)));
+ irq, pci_name(dev), pci_name(bridge)));
return_VALUE(irq);
}
@@ -415,30 +398,32 @@ acpi_pci_irq_derive (
* failure: return < 0
*/
-int
-acpi_pci_irq_enable (
- struct pci_dev *dev)
+int acpi_pci_irq_enable(struct pci_dev *dev)
{
- int irq = 0;
- u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
- char *link = NULL;
+ int irq = 0;
+ u8 pin = 0;
+ int edge_level = ACPI_LEVEL_SENSITIVE;
+ int active_high_low = ACPI_ACTIVE_LOW;
+ char *link = NULL;
+ int rc;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
if (!dev)
return_VALUE(-EINVAL);
-
+
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(dev)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No interrupt pin configured for device %s\n",
+ pci_name(dev)));
return_VALUE(0);
}
pin--;
if (!dev->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) 'bus' field\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid (NULL) 'bus' field\n"));
return_VALUE(-ENODEV);
}
@@ -446,69 +431,76 @@ acpi_pci_irq_enable (
* First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
* values override any BIOS-assigned IRQs set during boot.
*/
- irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, &link, acpi_pci_allocate_irq);
+ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, &link,
+ acpi_pci_allocate_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &edge_level,
- &active_high_low, &link, acpi_pci_allocate_irq);
-
+ irq = acpi_pci_irq_derive(dev, pin, &edge_level,
+ &active_high_low, &link,
+ acpi_pci_allocate_irq);
+
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.
*/
if (irq < 0) {
printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
- pci_name(dev), ('A' + pin));
+ pci_name(dev), ('A' + pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
- acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
+ acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
+ ACPI_ACTIVE_LOW);
return_VALUE(0);
- }
- else {
+ } else {
printk("\n");
return_VALUE(0);
}
- }
+ }
- dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
+ rc = acpi_register_gsi(irq, edge_level, active_high_low);
+ if (rc < 0) {
+ printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed "
+ "to register GSI\n", pci_name(dev), ('A' + pin));
+ return_VALUE(rc);
+ }
+ dev->irq = rc;
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
- pci_name(dev), 'A' + pin);
+ pci_name(dev), 'A' + pin);
if (link)
printk("Link [%s] -> ", link);
printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
- (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
- dev->irq);
+ (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_pci_irq_enable);
+EXPORT_SYMBOL(acpi_pci_irq_enable);
/* FIXME: implement x86/x86_64 version */
-void __attribute__((weak)) acpi_unregister_gsi(u32 i) {}
+void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
+{
+}
-void
-acpi_pci_irq_disable (
- struct pci_dev *dev)
+void acpi_pci_irq_disable(struct pci_dev *dev)
{
- int gsi = 0;
- u8 pin = 0;
- int edge_level = ACPI_LEVEL_SENSITIVE;
- int active_high_low = ACPI_ACTIVE_LOW;
+ int gsi = 0;
+ u8 pin = 0;
+ int edge_level = ACPI_LEVEL_SENSITIVE;
+ int active_high_low = ACPI_ACTIVE_LOW;
ACPI_FUNCTION_TRACE("acpi_pci_irq_disable");
- if (!dev)
+ if (!dev || !dev->bus)
return_VOID;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -516,21 +508,20 @@ acpi_pci_irq_disable (
return_VOID;
pin--;
- if (!dev->bus)
- return_VOID;
-
/*
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
- gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
+ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, NULL,
+ acpi_pci_free_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (gsi < 0)
- gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
+ gsi = acpi_pci_irq_derive(dev, pin,
+ &edge_level, &active_high_low, NULL,
+ acpi_pci_free_irq);
if (gsi < 0)
return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 65cea07abbc3..82292b77e5c6 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -42,30 +42,26 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_link")
-
+ACPI_MODULE_NAME("pci_link")
#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
#define ACPI_PCI_LINK_HID "PNP0C0F"
#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
#define ACPI_PCI_LINK_FILE_INFO "info"
#define ACPI_PCI_LINK_FILE_STATUS "state"
-
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
-
-static int acpi_pci_link_add (struct acpi_device *device);
-static int acpi_pci_link_remove (struct acpi_device *device, int type);
+static int acpi_pci_link_add(struct acpi_device *device);
+static int acpi_pci_link_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_pci_link_driver = {
- .name = ACPI_PCI_LINK_DRIVER_NAME,
- .class = ACPI_PCI_LINK_CLASS,
- .ids = ACPI_PCI_LINK_HID,
- .ops = {
- .add = acpi_pci_link_add,
- .remove = acpi_pci_link_remove,
- },
+ .name = ACPI_PCI_LINK_DRIVER_NAME,
+ .class = ACPI_PCI_LINK_CLASS,
+ .ids = ACPI_PCI_LINK_HID,
+ .ops = {
+ .add = acpi_pci_link_add,
+ .remove = acpi_pci_link_remove,
+ },
};
/*
@@ -73,31 +69,30 @@ static struct acpi_driver acpi_pci_link_driver = {
* later even the link is disable. Instead, we just repick the active irq
*/
struct acpi_pci_link_irq {
- u8 active; /* Current IRQ */
- u8 edge_level; /* All IRQs */
- u8 active_high_low; /* All IRQs */
- u8 resource_type;
- u8 possible_count;
- u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
- u8 initialized:1;
- u8 reserved:7;
+ u8 active; /* Current IRQ */
+ u8 edge_level; /* All IRQs */
+ u8 active_high_low; /* All IRQs */
+ u8 resource_type;
+ u8 possible_count;
+ u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+ u8 initialized:1;
+ u8 reserved:7;
};
struct acpi_pci_link {
- struct list_head node;
- struct acpi_device *device;
- acpi_handle handle;
+ struct list_head node;
+ struct acpi_device *device;
+ acpi_handle handle;
struct acpi_pci_link_irq irq;
- int refcnt;
+ int refcnt;
};
static struct {
- int count;
- struct list_head entries;
-} acpi_link;
+ int count;
+ struct list_head entries;
+} acpi_link;
DECLARE_MUTEX(acpi_link_lock);
-
/* --------------------------------------------------------------------------
PCI Link Device Management
-------------------------------------------------------------------------- */
@@ -106,12 +101,10 @@ DECLARE_MUTEX(acpi_link_lock);
* set context (link) possible list from resource list
*/
static acpi_status
-acpi_pci_link_check_possible (
- struct acpi_resource *resource,
- void *context)
+acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
{
- struct acpi_pci_link *link = (struct acpi_pci_link *) context;
- u32 i = 0;
+ struct acpi_pci_link *link = (struct acpi_pci_link *)context;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
@@ -119,61 +112,68 @@ acpi_pci_link_check_possible (
case ACPI_RSTYPE_START_DPF:
return_ACPI_STATUS(AE_OK);
case ACPI_RSTYPE_IRQ:
- {
- struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
- }
- for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
- if (!p->interrupts[i]) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
- continue;
+ {
+ struct acpi_resource_irq *p = &resource->data.irq;
+ if (!p || !p->number_of_interrupts) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
}
- link->irq.possible[i] = p->interrupts[i];
- link->irq.possible_count++;
+ for (i = 0;
+ (i < p->number_of_interrupts
+ && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
+ if (!p->interrupts[i]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ %d\n",
+ p->interrupts[i]));
+ continue;
+ }
+ link->irq.possible[i] = p->interrupts[i];
+ link->irq.possible_count++;
+ }
+ link->irq.edge_level = p->edge_level;
+ link->irq.active_high_low = p->active_high_low;
+ link->irq.resource_type = ACPI_RSTYPE_IRQ;
+ break;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_IRQ;
- break;
- }
case ACPI_RSTYPE_EXT_IRQ:
- {
- struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Blank EXT IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
- }
- for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
- if (!p->interrupts[i]) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
- continue;
+ {
+ struct acpi_resource_ext_irq *p =
+ &resource->data.extended_irq;
+ if (!p || !p->number_of_interrupts) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank EXT IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ for (i = 0;
+ (i < p->number_of_interrupts
+ && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
+ if (!p->interrupts[i]) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid IRQ %d\n",
+ p->interrupts[i]));
+ continue;
+ }
+ link->irq.possible[i] = p->interrupts[i];
+ link->irq.possible_count++;
}
- link->irq.possible[i] = p->interrupts[i];
- link->irq.possible_count++;
+ link->irq.edge_level = p->edge_level;
+ link->irq.active_high_low = p->active_high_low;
+ link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
+ break;
}
- link->irq.edge_level = p->edge_level;
- link->irq.active_high_low = p->active_high_low;
- link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
- break;
- }
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Resource is not an IRQ entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Resource is not an IRQ entry\n"));
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
-
-static int
-acpi_pci_link_get_possible (
- struct acpi_pci_link *link)
+static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
{
- acpi_status status;
+ acpi_status status;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
@@ -181,62 +181,60 @@ acpi_pci_link_get_possible (
return_VALUE(-EINVAL);
status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
- acpi_pci_link_check_possible, link);
+ acpi_pci_link_check_possible, link);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
return_VALUE(-ENODEV);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Found %d possible IRQs\n", link->irq.possible_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found %d possible IRQs\n",
+ link->irq.possible_count));
return_VALUE(0);
}
-
static acpi_status
-acpi_pci_link_check_current (
- struct acpi_resource *resource,
- void *context)
+acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
{
- int *irq = (int *) context;
+ int *irq = (int *)context;
ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
switch (resource->id) {
case ACPI_RSTYPE_IRQ:
- {
- struct acpi_resource_irq *p = &resource->data.irq;
- if (!p || !p->number_of_interrupts) {
- /*
- * IRQ descriptors may have no IRQ# bits set,
- * particularly those those w/ _STA disabled
- */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Blank IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
+ {
+ struct acpi_resource_irq *p = &resource->data.irq;
+ if (!p || !p->number_of_interrupts) {
+ /*
+ * IRQ descriptors may have no IRQ# bits set,
+ * particularly those those w/ _STA disabled
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Blank IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ *irq = p->interrupts[0];
+ break;
}
- *irq = p->interrupts[0];
- break;
- }
case ACPI_RSTYPE_EXT_IRQ:
- {
- struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
- if (!p || !p->number_of_interrupts) {
- /*
- * extended IRQ descriptors must
- * return at least 1 IRQ
- */
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Blank EXT IRQ resource\n"));
- return_ACPI_STATUS(AE_OK);
+ {
+ struct acpi_resource_ext_irq *p =
+ &resource->data.extended_irq;
+ if (!p || !p->number_of_interrupts) {
+ /*
+ * extended IRQ descriptors must
+ * return at least 1 IRQ
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Blank EXT IRQ resource\n"));
+ return_ACPI_STATUS(AE_OK);
+ }
+ *irq = p->interrupts[0];
+ break;
}
- *irq = p->interrupts[0];
- break;
- }
default:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Resource isn't an IRQ\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n"));
return_ACPI_STATUS(AE_OK);
}
return_ACPI_STATUS(AE_CTRL_TERMINATE);
@@ -249,13 +247,11 @@ acpi_pci_link_check_current (
* 0 - success
* !0 - failure
*/
-static int
-acpi_pci_link_get_current (
- struct acpi_pci_link *link)
+static int acpi_pci_link_get_current(struct acpi_pci_link *link)
{
- int result = 0;
- acpi_status status = AE_OK;
- int irq = 0;
+ int result = 0;
+ acpi_status status = AE_OK;
+ int irq = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
@@ -269,7 +265,8 @@ acpi_pci_link_get_current (
/* Query _STA, set link->device->status */
result = acpi_bus_get_status(link->device);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to read status\n"));
goto end;
}
@@ -284,7 +281,7 @@ acpi_pci_link_get_current (
*/
status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
- acpi_pci_link_check_current, &irq);
+ acpi_pci_link_check_current, &irq);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
result = -ENODEV;
@@ -300,58 +297,61 @@ acpi_pci_link_get_current (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
-end:
+ end:
return_VALUE(result);
}
-static int
-acpi_pci_link_set (
- struct acpi_pci_link *link,
- int irq)
+static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
{
- int result = 0;
- acpi_status status = AE_OK;
+ int result = 0;
+ acpi_status status = AE_OK;
struct {
- struct acpi_resource res;
- struct acpi_resource end;
- } *resource;
- struct acpi_buffer buffer = {0, NULL};
+ struct acpi_resource res;
+ struct acpi_resource end;
+ } *resource;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_pci_link_set");
if (!link || !irq)
return_VALUE(-EINVAL);
- resource = kmalloc( sizeof(*resource)+1, GFP_KERNEL);
- if(!resource)
+ resource = kmalloc(sizeof(*resource) + 1, GFP_KERNEL);
+ if (!resource)
return_VALUE(-ENOMEM);
- memset(resource, 0, sizeof(*resource)+1);
- buffer.length = sizeof(*resource) +1;
+ memset(resource, 0, sizeof(*resource) + 1);
+ buffer.length = sizeof(*resource) + 1;
buffer.pointer = resource;
- switch(link->irq.resource_type) {
+ switch (link->irq.resource_type) {
case ACPI_RSTYPE_IRQ:
resource->res.id = ACPI_RSTYPE_IRQ;
resource->res.length = sizeof(struct acpi_resource);
resource->res.data.irq.edge_level = link->irq.edge_level;
- resource->res.data.irq.active_high_low = link->irq.active_high_low;
+ resource->res.data.irq.active_high_low =
+ link->irq.active_high_low;
if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->res.data.irq.shared_exclusive =
+ ACPI_EXCLUSIVE;
else
resource->res.data.irq.shared_exclusive = ACPI_SHARED;
resource->res.data.irq.number_of_interrupts = 1;
resource->res.data.irq.interrupts[0] = irq;
break;
-
+
case ACPI_RSTYPE_EXT_IRQ:
resource->res.id = ACPI_RSTYPE_EXT_IRQ;
resource->res.length = sizeof(struct acpi_resource);
- resource->res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
- resource->res.data.extended_irq.edge_level = link->irq.edge_level;
- resource->res.data.extended_irq.active_high_low = link->irq.active_high_low;
+ resource->res.data.extended_irq.producer_consumer =
+ ACPI_CONSUMER;
+ resource->res.data.extended_irq.edge_level =
+ link->irq.edge_level;
+ resource->res.data.extended_irq.active_high_low =
+ link->irq.active_high_low;
if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
- resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+ resource->res.data.irq.shared_exclusive =
+ ACPI_EXCLUSIVE;
else
resource->res.data.irq.shared_exclusive = ACPI_SHARED;
resource->res.data.extended_irq.number_of_interrupts = 1;
@@ -384,9 +384,9 @@ acpi_pci_link_set (
}
if (!link->device->status.enabled) {
printk(KERN_WARNING PREFIX
- "%s [%s] disabled and referenced, BIOS bug.\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device));
+ "%s [%s] disabled and referenced, BIOS bug.\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device));
}
/* Query _CRS, set link->irq.active */
@@ -404,22 +404,20 @@ acpi_pci_link_set (
* policy: when _CRS doesn't return what we just _SRS
* assume _SRS worked and override _CRS value.
*/
- printk(KERN_WARNING PREFIX
- "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device),
- link->irq.active, irq);
+ printk(KERN_WARNING PREFIX
+ "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device), link->irq.active, irq);
link->irq.active = irq;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
-
-end:
+
+ end:
kfree(resource);
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
PCI Link IRQ Management
-------------------------------------------------------------------------- */
@@ -469,8 +467,8 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
- PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
- PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
+ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
+ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
@@ -482,15 +480,14 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
- /* >IRQ15 */
+ /* >IRQ15 */
};
-int __init
-acpi_irq_penalty_init(void)
+int __init acpi_irq_penalty_init(void)
{
- struct list_head *node = NULL;
- struct acpi_pci_link *link = NULL;
- int i = 0;
+ struct list_head *node = NULL;
+ struct acpi_pci_link *link = NULL;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
@@ -501,7 +498,8 @@ acpi_irq_penalty_init(void)
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid link context\n"));
continue;
}
@@ -510,15 +508,20 @@ acpi_irq_penalty_init(void)
* useful for breaking ties.
*/
if (link->irq.possible_count) {
- int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
+ int penalty =
+ PIRQ_PENALTY_PCI_POSSIBLE /
+ link->irq.possible_count;
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
- acpi_irq_penalty[link->irq.possible[i]] += penalty;
+ acpi_irq_penalty[link->irq.
+ possible[i]] +=
+ penalty;
}
} else if (link->irq.active) {
- acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE;
+ acpi_irq_penalty[link->irq.active] +=
+ PIRQ_PENALTY_PCI_POSSIBLE;
}
}
/* Add a penalty for the SCI */
@@ -529,11 +532,10 @@ acpi_irq_penalty_init(void)
static int acpi_irq_balance; /* 0: static, 1: balance */
-static int acpi_pci_link_allocate(
- struct acpi_pci_link *link)
+static int acpi_pci_link_allocate(struct acpi_pci_link *link)
{
- int irq;
- int i;
+ int irq;
+ int i;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
@@ -557,7 +559,7 @@ static int acpi_pci_link_allocate(
if (i == link->irq.possible_count) {
if (acpi_strict)
printk(KERN_WARNING PREFIX "_CRS %d not found"
- " in _PRS\n", link->irq.active);
+ " in _PRS\n", link->irq.active);
link->irq.active = 0;
}
@@ -576,23 +578,25 @@ static int acpi_pci_link_allocate(
* the use of IRQs 9, 10, 11, and >15.
*/
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
- if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+ if (acpi_irq_penalty[irq] >
+ acpi_irq_penalty[link->irq.possible[i]])
irq = link->irq.possible[i];
}
}
/* Attempt to enable the link device at this IRQ. */
if (acpi_pci_link_set(link, irq)) {
- printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
- "Try pci=noacpi or acpi=off\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device));
+ printk(PREFIX
+ "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
+ "Try pci=noacpi or acpi=off\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device));
return_VALUE(-ENODEV);
} else {
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
- printk(PREFIX "%s [%s] enabled at IRQ %d\n",
- acpi_device_name(link->device),
- acpi_device_bid(link->device), link->irq.active);
+ printk(PREFIX "%s [%s] enabled at IRQ %d\n",
+ acpi_device_name(link->device),
+ acpi_device_bid(link->device), link->irq.active);
}
link->irq.initialized = 1;
@@ -607,16 +611,13 @@ static int acpi_pci_link_allocate(
*/
int
-acpi_pci_link_allocate_irq (
- acpi_handle handle,
- int index,
- int *edge_level,
- int *active_high_low,
- char **name)
+acpi_pci_link_allocate_irq(acpi_handle handle,
+ int index,
+ int *edge_level, int *active_high_low, char **name)
{
- int result = 0;
- struct acpi_device *device = NULL;
- struct acpi_pci_link *link = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_link *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq");
@@ -626,7 +627,7 @@ acpi_pci_link_allocate_irq (
return_VALUE(-1);
}
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
return_VALUE(-1);
@@ -643,20 +644,24 @@ acpi_pci_link_allocate_irq (
up(&acpi_link_lock);
return_VALUE(-1);
}
-
+
if (!link->irq.active) {
up(&acpi_link_lock);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
return_VALUE(-1);
}
- link->refcnt ++;
+ link->refcnt++;
up(&acpi_link_lock);
- if (edge_level) *edge_level = link->irq.edge_level;
- if (active_high_low) *active_high_low = link->irq.active_high_low;
- if (name) *name = acpi_device_bid(link->device);
+ if (edge_level)
+ *edge_level = link->irq.edge_level;
+ if (active_high_low)
+ *active_high_low = link->irq.active_high_low;
+ if (name)
+ *name = acpi_device_bid(link->device);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Link %s is referenced\n", acpi_device_bid(link->device)));
+ "Link %s is referenced\n",
+ acpi_device_bid(link->device)));
return_VALUE(link->irq.active);
}
@@ -664,12 +669,11 @@ acpi_pci_link_allocate_irq (
* We don't change link's irq information here. After it is reenabled, we
* continue use the info
*/
-int
-acpi_pci_link_free_irq(acpi_handle handle)
+int acpi_pci_link_free_irq(acpi_handle handle)
{
- struct acpi_device *device = NULL;
- struct acpi_pci_link *link = NULL;
- acpi_status result;
+ struct acpi_device *device = NULL;
+ struct acpi_pci_link *link = NULL;
+ acpi_status result;
ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq");
@@ -679,7 +683,7 @@ acpi_pci_link_free_irq(acpi_handle handle)
return_VALUE(-1);
}
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
return_VALUE(-1);
@@ -691,7 +695,6 @@ acpi_pci_link_free_irq(acpi_handle handle)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
return_VALUE(-1);
}
-
#ifdef FUTURE_USE
/*
* The Link reference count allows us to _DISable an unused link
@@ -702,10 +705,11 @@ acpi_pci_link_free_irq(acpi_handle handle)
* to prevent duplicate acpi_pci_link_set()
* which would harm some systems
*/
- link->refcnt --;
+ link->refcnt--;
#endif
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Link %s is dereferenced\n", acpi_device_bid(link->device)));
+ "Link %s is dereferenced\n",
+ acpi_device_bid(link->device)));
if (link->refcnt == 0) {
acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
@@ -713,18 +717,17 @@ acpi_pci_link_free_irq(acpi_handle handle)
up(&acpi_link_lock);
return_VALUE(link->irq.active);
}
+
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_pci_link_add (
- struct acpi_device *device)
+static int acpi_pci_link_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_pci_link *link = NULL;
- int i = 0;
- int found = 0;
+ int result = 0;
+ struct acpi_pci_link *link = NULL;
+ int i = 0;
+ int found = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_add");
@@ -751,13 +754,12 @@ acpi_pci_link_add (
acpi_pci_link_get_current(link);
printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
- acpi_device_bid(device));
+ acpi_device_bid(device));
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.active == link->irq.possible[i]) {
printk(" *%d", link->irq.possible[i]);
found = 1;
- }
- else
+ } else
printk(" %d", link->irq.possible[i]);
}
@@ -766,7 +768,7 @@ acpi_pci_link_add (
if (!found)
printk(" *%d", link->irq.active);
- if(!link->device->status.enabled)
+ if (!link->device->status.enabled)
printk(", disabled.");
printk("\n");
@@ -775,7 +777,7 @@ acpi_pci_link_add (
list_add_tail(&link->node, &acpi_link.entries);
acpi_link.count++;
-end:
+ end:
/* disable all links -- to be activated on use */
acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
up(&acpi_link_lock);
@@ -786,9 +788,7 @@ end:
return_VALUE(result);
}
-static int
-acpi_pci_link_resume(
- struct acpi_pci_link *link)
+static int acpi_pci_link_resume(struct acpi_pci_link *link)
{
ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
@@ -798,32 +798,33 @@ acpi_pci_link_resume(
return_VALUE(0);
}
-static int
-irqrouter_resume(
- struct sys_device *dev)
+/*
+ * FIXME: this is a workaround to avoid nasty warning. It will be removed
+ * after every device calls pci_disable_device in .resume.
+ */
+int acpi_in_resume;
+static int irqrouter_resume(struct sys_device *dev)
{
- struct list_head *node = NULL;
- struct acpi_pci_link *link = NULL;
+ struct list_head *node = NULL;
+ struct acpi_pci_link *link = NULL;
ACPI_FUNCTION_TRACE("irqrouter_resume");
+ acpi_in_resume = 1;
list_for_each(node, &acpi_link.entries) {
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid link context\n"));
+ "Invalid link context\n"));
continue;
}
acpi_pci_link_resume(link);
}
+ acpi_in_resume = 0;
return_VALUE(0);
}
-
-static int
-acpi_pci_link_remove (
- struct acpi_device *device,
- int type)
+static int acpi_pci_link_remove(struct acpi_device *device, int type)
{
struct acpi_pci_link *link = NULL;
@@ -832,7 +833,7 @@ acpi_pci_link_remove (
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- link = (struct acpi_pci_link *) acpi_driver_data(device);
+ link = (struct acpi_pci_link *)acpi_driver_data(device);
down(&acpi_link_lock);
list_del(&link->node);
@@ -854,14 +855,14 @@ static int __init acpi_irq_penalty_update(char *str, int used)
int retval;
int irq;
- retval = get_option(&str,&irq);
+ retval = get_option(&str, &irq);
if (!retval)
break; /* no number found */
if (irq < 0)
continue;
-
+
if (irq >= ACPI_MAX_IRQS)
continue;
@@ -900,6 +901,7 @@ static int __init acpi_irq_isa(char *str)
{
return acpi_irq_penalty_update(str, 1);
}
+
__setup("acpi_irq_isa=", acpi_irq_isa);
/*
@@ -911,6 +913,7 @@ static int __init acpi_irq_pci(char *str)
{
return acpi_irq_penalty_update(str, 0);
}
+
__setup("acpi_irq_pci=", acpi_irq_pci);
static int __init acpi_irq_nobalance_set(char *str)
@@ -918,6 +921,7 @@ static int __init acpi_irq_nobalance_set(char *str)
acpi_irq_balance = 0;
return 1;
}
+
__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
int __init acpi_irq_balance_set(char *str)
@@ -925,22 +929,20 @@ int __init acpi_irq_balance_set(char *str)
acpi_irq_balance = 1;
return 1;
}
-__setup("acpi_irq_balance", acpi_irq_balance_set);
+__setup("acpi_irq_balance", acpi_irq_balance_set);
/* FIXME: we will remove this interface after all drivers call pci_disable_device */
static struct sysdev_class irqrouter_sysdev_class = {
- set_kset_name("irqrouter"),
- .resume = irqrouter_resume,
+ set_kset_name("irqrouter"),
+ .resume = irqrouter_resume,
};
-
static struct sys_device device_irqrouter = {
- .id = 0,
- .cls = &irqrouter_sysdev_class,
+ .id = 0,
+ .cls = &irqrouter_sysdev_class,
};
-
static int __init irqrouter_init_sysfs(void)
{
int error;
@@ -955,12 +957,11 @@ static int __init irqrouter_init_sysfs(void)
error = sysdev_register(&device_irqrouter);
return_VALUE(error);
-}
+}
device_initcall(irqrouter_init_sysfs);
-
-static int __init acpi_pci_link_init (void)
+static int __init acpi_pci_link_init(void)
{
ACPI_FUNCTION_TRACE("acpi_pci_link_init");
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 5d2f77fcd50c..0fd9988c283d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -35,35 +35,32 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME ("pci_root")
-
+ACPI_MODULE_NAME("pci_root")
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_HID "PNP0A03"
#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
-
-static int acpi_pci_root_add (struct acpi_device *device);
-static int acpi_pci_root_remove (struct acpi_device *device, int type);
-static int acpi_pci_root_start (struct acpi_device *device);
+static int acpi_pci_root_add(struct acpi_device *device);
+static int acpi_pci_root_remove(struct acpi_device *device, int type);
+static int acpi_pci_root_start(struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = {
- .name = ACPI_PCI_ROOT_DRIVER_NAME,
- .class = ACPI_PCI_ROOT_CLASS,
- .ids = ACPI_PCI_ROOT_HID,
- .ops = {
- .add = acpi_pci_root_add,
- .remove = acpi_pci_root_remove,
- .start = acpi_pci_root_start,
- },
+ .name = ACPI_PCI_ROOT_DRIVER_NAME,
+ .class = ACPI_PCI_ROOT_CLASS,
+ .ids = ACPI_PCI_ROOT_HID,
+ .ops = {
+ .add = acpi_pci_root_add,
+ .remove = acpi_pci_root_remove,
+ .start = acpi_pci_root_start,
+ },
};
struct acpi_pci_root {
- struct list_head node;
- acpi_handle handle;
- struct acpi_pci_id id;
- struct pci_bus *bus;
+ struct list_head node;
+ acpi_handle handle;
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
};
static LIST_HEAD(acpi_pci_roots);
@@ -92,6 +89,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
return n;
}
+
EXPORT_SYMBOL(acpi_pci_register_driver);
void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
@@ -115,10 +113,11 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
driver->remove(root->handle);
}
}
+
EXPORT_SYMBOL(acpi_pci_unregister_driver);
static acpi_status
-get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
+get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
int *busnr = (int *)data;
struct acpi_resource_address64 address;
@@ -129,20 +128,21 @@ get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
return AE_OK;
acpi_resource_to_address64(resource, &address);
- if ((address.address_length > 0) &&
- (address.resource_type == ACPI_BUS_NUMBER_RANGE))
+ if ((address.address_length > 0) &&
+ (address.resource_type == ACPI_BUS_NUMBER_RANGE))
*busnr = address.min_address_range;
return AE_OK;
}
-static acpi_status
-try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
+static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
{
acpi_status status;
*busnum = -1;
- status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
+ status =
+ acpi_walk_resources(handle, METHOD_NAME__CRS,
+ get_root_bridge_busnr_callback, busnum);
if (ACPI_FAILURE(status))
return status;
/* Check if we really get a bus number from _CRS */
@@ -151,16 +151,14 @@ try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
return AE_OK;
}
-static int
-acpi_pci_root_add (
- struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device)
{
- int result = 0;
- struct acpi_pci_root *root = NULL;
- struct acpi_pci_root *tmp;
- acpi_status status = AE_OK;
- unsigned long value = 0;
- acpi_handle handle = NULL;
+ int result = 0;
+ struct acpi_pci_root *root = NULL;
+ struct acpi_pci_root *tmp;
+ acpi_status status = AE_OK;
+ unsigned long value = 0;
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_add");
@@ -188,15 +186,15 @@ acpi_pci_root_add (
* -------
* Obtained via _SEG, if exists, otherwise assumed to be zero (0).
*/
- status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
- &value);
+ status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
+ &value);
switch (status) {
case AE_OK:
root->id.segment = (u16) value;
break;
case AE_NOT_FOUND:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Assuming segment 0 (no _SEG)\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Assuming segment 0 (no _SEG)\n"));
root->id.segment = 0;
break;
default:
@@ -210,8 +208,8 @@ acpi_pci_root_add (
* ---
* Obtained via _BBN, if exists, otherwise assumed to be zero (0).
*/
- status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
- &value);
+ status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
+ &value);
switch (status) {
case AE_OK:
root->id.bus = (u16) value;
@@ -229,18 +227,19 @@ acpi_pci_root_add (
/* Some systems have wrong _BBN */
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == root->id.segment)
- && (tmp->id.bus == root->id.bus)) {
+ && (tmp->id.bus == root->id.bus)) {
int bus = 0;
acpi_status status;
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
status = try_get_root_bridge_busnr(root->handle, &bus);
if (ACPI_FAILURE(status))
break;
if (bus != root->id.bus) {
- printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
+ printk(KERN_INFO PREFIX
+ "PCI _CRS %d overrides _BBN 0\n", bus);
root->id.bus = bus;
}
break;
@@ -258,12 +257,12 @@ acpi_pci_root_add (
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
- /* TBD: Locking */
- list_add_tail(&root->node, &acpi_pci_roots);
+ /* TBD: Locking */
+ list_add_tail(&root->node, &acpi_pci_roots);
- printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
- acpi_device_name(device), acpi_device_bid(device),
- root->id.segment, root->id.bus);
+ printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ root->id.segment, root->id.bus);
/*
* Scan the Root Bridge
@@ -274,9 +273,9 @@ acpi_pci_root_add (
*/
root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
if (!root->bus) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bus %04x:%02x not present in PCI namespace\n",
- root->id.segment, root->id.bus));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->id.segment, root->id.bus));
result = -ENODEV;
goto end;
}
@@ -298,9 +297,9 @@ acpi_pci_root_add (
status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
result = acpi_pci_irq_add_prt(root->handle, root->id.segment,
- root->id.bus);
+ root->id.bus);
-end:
+ end:
if (result) {
if (!list_empty(&root->node))
list_del(&root->node);
@@ -310,11 +309,9 @@ end:
return_VALUE(result);
}
-static int
-acpi_pci_root_start (
- struct acpi_device *device)
+static int acpi_pci_root_start(struct acpi_device *device)
{
- struct acpi_pci_root *root;
+ struct acpi_pci_root *root;
ACPI_FUNCTION_TRACE("acpi_pci_root_start");
@@ -327,27 +324,23 @@ acpi_pci_root_start (
return_VALUE(-ENODEV);
}
-static int
-acpi_pci_root_remove (
- struct acpi_device *device,
- int type)
+static int acpi_pci_root_remove(struct acpi_device *device, int type)
{
- struct acpi_pci_root *root = NULL;
+ struct acpi_pci_root *root = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- root = (struct acpi_pci_root *) acpi_driver_data(device);
+ root = (struct acpi_pci_root *)acpi_driver_data(device);
kfree(root);
return_VALUE(0);
}
-
-static int __init acpi_pci_root_init (void)
+static int __init acpi_pci_root_init(void)
{
ACPI_FUNCTION_TRACE("acpi_pci_root_init");
@@ -355,8 +348,8 @@ static int __init acpi_pci_root_init (void)
return_VALUE(0);
/* DEBUG:
- acpi_dbg_layer = ACPI_PCI_COMPONENT;
- acpi_dbg_level = 0xFFFFFFFF;
+ acpi_dbg_layer = ACPI_PCI_COMPONENT;
+ acpi_dbg_level = 0xFFFFFFFF;
*/
if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
@@ -366,4 +359,3 @@ static int __init acpi_pci_root_init (void)
}
subsys_initcall(acpi_pci_root_init);
-
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 373a3a95bb4e..62a5595ed8bc 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -44,10 +44,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_POWER_COMPONENT
-ACPI_MODULE_NAME ("acpi_power")
-
+ACPI_MODULE_NAME("acpi_power")
#define ACPI_POWER_COMPONENT 0x00800000
#define ACPI_POWER_CLASS "power_resource"
#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver"
@@ -57,38 +55,36 @@ ACPI_MODULE_NAME ("acpi_power")
#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
-
-static int acpi_power_add (struct acpi_device *device);
-static int acpi_power_remove (struct acpi_device *device, int type);
+static int acpi_power_add(struct acpi_device *device);
+static int acpi_power_remove(struct acpi_device *device, int type);
static int acpi_power_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_power_driver = {
- .name = ACPI_POWER_DRIVER_NAME,
- .class = ACPI_POWER_CLASS,
- .ids = ACPI_POWER_HID,
- .ops = {
- .add = acpi_power_add,
- .remove = acpi_power_remove,
- },
+ .name = ACPI_POWER_DRIVER_NAME,
+ .class = ACPI_POWER_CLASS,
+ .ids = ACPI_POWER_HID,
+ .ops = {
+ .add = acpi_power_add,
+ .remove = acpi_power_remove,
+ },
};
-struct acpi_power_resource
-{
- acpi_handle handle;
- acpi_bus_id name;
- u32 system_level;
- u32 order;
- int state;
- int references;
+struct acpi_power_resource {
+ acpi_handle handle;
+ acpi_bus_id name;
+ u32 system_level;
+ u32 order;
+ int state;
+ int references;
};
-static struct list_head acpi_power_resource_list;
+static struct list_head acpi_power_resource_list;
static struct file_operations acpi_power_fops = {
- .open = acpi_power_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
@@ -96,12 +92,11 @@ static struct file_operations acpi_power_fops = {
-------------------------------------------------------------------------- */
static int
-acpi_power_get_context (
- acpi_handle handle,
- struct acpi_power_resource **resource)
+acpi_power_get_context(acpi_handle handle,
+ struct acpi_power_resource **resource)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_power_get_context");
@@ -111,24 +106,21 @@ acpi_power_get_context (
result = acpi_bus_get_device(handle, &device);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context [%p]\n",
- handle));
+ handle));
return_VALUE(result);
}
- *resource = (struct acpi_power_resource *) acpi_driver_data(device);
+ *resource = (struct acpi_power_resource *)acpi_driver_data(device);
if (!resource)
return_VALUE(-ENODEV);
return_VALUE(0);
}
-
-static int
-acpi_power_get_state (
- struct acpi_power_resource *resource)
+static int acpi_power_get_state(struct acpi_power_resource *resource)
{
- acpi_status status = AE_OK;
- unsigned long sta = 0;
+ acpi_status status = AE_OK;
+ unsigned long sta = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_state");
@@ -145,20 +137,16 @@ acpi_power_get_state (
resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- resource->name, resource->state?"on":"off"));
+ resource->name, resource->state ? "on" : "off"));
return_VALUE(0);
}
-
-static int
-acpi_power_get_list_state (
- struct acpi_handle_list *list,
- int *state)
+static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
- int result = 0;
+ int result = 0;
struct acpi_power_resource *resource = NULL;
- u32 i = 0;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_list_state");
@@ -167,7 +155,7 @@ acpi_power_get_list_state (
/* The state of the list is 'on' IFF all resources are 'on'. */
- for (i=0; i<list->count; i++) {
+ for (i = 0; i < list->count; i++) {
result = acpi_power_get_context(list->handles[i], &resource);
if (result)
return_VALUE(result);
@@ -182,19 +170,16 @@ acpi_power_get_list_state (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
- *state?"on":"off"));
+ *state ? "on" : "off"));
return_VALUE(result);
}
-
-static int
-acpi_power_on (
- acpi_handle handle)
+static int acpi_power_on(acpi_handle handle)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
struct acpi_power_resource *resource = NULL;
ACPI_FUNCTION_TRACE("acpi_power_on");
@@ -205,10 +190,10 @@ acpi_power_on (
resource->references++;
- if ((resource->references > 1)
- || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
+ if ((resource->references > 1)
+ || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
@@ -229,19 +214,16 @@ acpi_power_on (
device->power.state = ACPI_STATE_D0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
-
-static int
-acpi_power_off_device (
- acpi_handle handle)
+static int acpi_power_off_device(acpi_handle handle)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_device *device = NULL;
struct acpi_power_resource *resource = NULL;
ACPI_FUNCTION_TRACE("acpi_power_off_device");
@@ -254,15 +236,15 @@ acpi_power_off_device (
resource->references--;
if (resource->references) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Resource [%s] is still in use, dereferencing\n",
- device->pnp.bus_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Resource [%s] is still in use, dereferencing\n",
+ device->pnp.bus_id));
return_VALUE(0);
}
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
- device->pnp.bus_id));
+ device->pnp.bus_id));
return_VALUE(0);
}
@@ -283,7 +265,7 @@ acpi_power_off_device (
device->power.state = ACPI_STATE_D3;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
- resource->name));
+ resource->name));
return_VALUE(0);
}
@@ -293,13 +275,13 @@ acpi_power_off_device (
* 1. Power on the power resources required for the wakeup device
* 2. Enable _PSW (power state wake) for the device if present
*/
-int acpi_enable_wakeup_device_power (struct acpi_device *dev)
+int acpi_enable_wakeup_device_power(struct acpi_device *dev)
{
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ acpi_status status = AE_OK;
+ int i;
+ int ret = 0;
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
if (!dev || !dev->wakeup.flags.valid)
@@ -310,8 +292,8 @@ int acpi_enable_wakeup_device_power (struct acpi_device *dev)
for (i = 0; i < dev->wakeup.resources.count; i++) {
ret = acpi_power_on(dev->wakeup.resources.handles[i]);
if (ret) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error transition power state\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error transition power state\n"));
dev->wakeup.flags.valid = 0;
return_VALUE(-1);
}
@@ -333,20 +315,20 @@ int acpi_enable_wakeup_device_power (struct acpi_device *dev)
* 1. Disable _PSW (power state wake)
* 2. Shutdown down the power resources
*/
-int acpi_disable_wakeup_device_power (struct acpi_device *dev)
+int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
- union acpi_object arg = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg};
- acpi_status status = AE_OK;
- int i;
- int ret = 0;
+ union acpi_object arg = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg };
+ acpi_status status = AE_OK;
+ int i;
+ int ret = 0;
ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
if (!dev || !dev->wakeup.flags.valid)
return_VALUE(-1);
- arg.integer.value = 0;
+ arg.integer.value = 0;
/* Execute PSW */
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
@@ -359,8 +341,8 @@ int acpi_disable_wakeup_device_power (struct acpi_device *dev)
for (i = 0; i < dev->wakeup.resources.count; i++) {
ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
if (ret) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error transition power state\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error transition power state\n"));
dev->wakeup.flags.valid = 0;
return_VALUE(-1);
}
@@ -373,14 +355,12 @@ int acpi_disable_wakeup_device_power (struct acpi_device *dev)
Device Power Management
-------------------------------------------------------------------------- */
-int
-acpi_power_get_inferred_state (
- struct acpi_device *device)
+int acpi_power_get_inferred_state(struct acpi_device *device)
{
- int result = 0;
- struct acpi_handle_list *list = NULL;
- int list_state = 0;
- int i = 0;
+ int result = 0;
+ struct acpi_handle_list *list = NULL;
+ int list_state = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state");
@@ -393,7 +373,7 @@ acpi_power_get_inferred_state (
* We know a device's inferred power state when all the resources
* required for a given D-state are 'on'.
*/
- for (i=ACPI_STATE_D0; i<ACPI_STATE_D3; i++) {
+ for (i = ACPI_STATE_D0; i < ACPI_STATE_D3; i++) {
list = &device->power.states[i].resources;
if (list->count < 1)
continue;
@@ -413,23 +393,20 @@ acpi_power_get_inferred_state (
return_VALUE(0);
}
-
-int
-acpi_power_transition (
- struct acpi_device *device,
- int state)
+int acpi_power_transition(struct acpi_device *device, int state)
{
- int result = 0;
- struct acpi_handle_list *cl = NULL; /* Current Resources */
- struct acpi_handle_list *tl = NULL; /* Target Resources */
- int i = 0;
+ int result = 0;
+ struct acpi_handle_list *cl = NULL; /* Current Resources */
+ struct acpi_handle_list *tl = NULL; /* Target Resources */
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_power_transition");
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
return_VALUE(-EINVAL);
- if ((device->power.state < ACPI_STATE_D0) || (device->power.state > ACPI_STATE_D3))
+ if ((device->power.state < ACPI_STATE_D0)
+ || (device->power.state > ACPI_STATE_D3))
return_VALUE(-ENODEV);
cl = &device->power.states[device->power.state].resources;
@@ -448,7 +425,7 @@ acpi_power_transition (
* First we reference all power resources required in the target list
* (e.g. so the device doesn't lose power while transitioning).
*/
- for (i=0; i<tl->count; i++) {
+ for (i = 0; i < tl->count; i++) {
result = acpi_power_on(tl->handles[i]);
if (result)
goto end;
@@ -457,7 +434,7 @@ acpi_power_transition (
/*
* Then we dereference all power resources used in the current list.
*/
- for (i=0; i<cl->count; i++) {
+ for (i = 0; i < cl->count; i++) {
result = acpi_power_off_device(cl->handles[i]);
if (result)
goto end;
@@ -465,21 +442,20 @@ acpi_power_transition (
/* We shouldn't change the state till all above operations succeed */
device->power.state = state;
-end:
+ end:
if (result)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN,
- "Error transitioning device [%s] to D%d\n",
- device->pnp.bus_id, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Error transitioning device [%s] to D%d\n",
+ device->pnp.bus_id, state));
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
@@ -506,13 +482,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "system level: S%d\n"
- "order: %d\n"
- "reference count: %d\n",
- resource->system_level,
- resource->order,
- resource->references);
+ "order: %d\n"
+ "reference count: %d\n",
+ resource->system_level,
+ resource->order, resource->references);
-end:
+ end:
return_VALUE(0);
}
@@ -521,11 +496,9 @@ static int acpi_power_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_power_seq_show, PDE(inode)->data);
}
-static int
-acpi_power_add_fs (
- struct acpi_device *device)
+static int acpi_power_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_power_add_fs");
@@ -534,18 +507,18 @@ acpi_power_add_fs (
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_power_dir);
+ acpi_power_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
/* 'status' [R] */
entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_POWER_FILE_STATUS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_POWER_FILE_STATUS));
else {
entry->proc_fops = &acpi_power_fops;
entry->data = acpi_driver_data(device);
@@ -554,10 +527,7 @@ acpi_power_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_power_remove_fs (
- struct acpi_device *device)
+static int acpi_power_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
@@ -571,20 +541,17 @@ acpi_power_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_power_add (
- struct acpi_device *device)
+static int acpi_power_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
+ int result = 0;
+ acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
- union acpi_object acpi_object;
- struct acpi_buffer buffer = {sizeof(acpi_object), &acpi_object};
+ union acpi_object acpi_object;
+ struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
ACPI_FUNCTION_TRACE("acpi_power_add");
@@ -630,22 +597,18 @@ acpi_power_add (
result = acpi_power_add_fs(device);
if (result)
goto end;
-
+
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
- acpi_device_bid(device), resource->state?"on":"off");
+ acpi_device_bid(device), resource->state ? "on" : "off");
-end:
+ end:
if (result)
kfree(resource);
-
+
return_VALUE(result);
}
-
-static int
-acpi_power_remove (
- struct acpi_device *device,
- int type)
+static int acpi_power_remove(struct acpi_device *device, int type)
{
struct acpi_power_resource *resource = NULL;
@@ -654,7 +617,7 @@ acpi_power_remove (
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- resource = (struct acpi_power_resource *) acpi_driver_data(device);
+ resource = (struct acpi_power_resource *)acpi_driver_data(device);
acpi_power_remove_fs(device);
@@ -663,10 +626,9 @@ acpi_power_remove (
return_VALUE(0);
}
-
-static int __init acpi_power_init (void)
+static int __init acpi_power_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_power_init");
@@ -689,4 +651,3 @@ static int __init acpi_power_init (void)
}
subsys_initcall(acpi_power_init);
-
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index d56a439ac614..421792562642 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -58,7 +58,6 @@
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
@@ -75,59 +74,53 @@
#define ACPI_STA_PRESENT 0x00000001
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
+ACPI_MODULE_NAME("acpi_processor")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
MODULE_LICENSE("GPL");
-
-static int acpi_processor_add (struct acpi_device *device);
-static int acpi_processor_start (struct acpi_device *device);
-static int acpi_processor_remove (struct acpi_device *device, int type);
+static int acpi_processor_add(struct acpi_device *device);
+static int acpi_processor_start(struct acpi_device *device);
+static int acpi_processor_remove(struct acpi_device *device, int type);
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
-static void acpi_processor_notify ( acpi_handle handle, u32 event, void *data);
+static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
static struct acpi_driver acpi_processor_driver = {
- .name = ACPI_PROCESSOR_DRIVER_NAME,
- .class = ACPI_PROCESSOR_CLASS,
- .ids = ACPI_PROCESSOR_HID,
- .ops = {
- .add = acpi_processor_add,
- .remove = acpi_processor_remove,
- .start = acpi_processor_start,
- },
+ .name = ACPI_PROCESSOR_DRIVER_NAME,
+ .class = ACPI_PROCESSOR_CLASS,
+ .ids = ACPI_PROCESSOR_HID,
+ .ops = {
+ .add = acpi_processor_add,
+ .remove = acpi_processor_remove,
+ .start = acpi_processor_start,
+ },
};
#define INSTALL_NOTIFY_HANDLER 1
#define UNINSTALL_NOTIFY_HANDLER 2
-
static struct file_operations acpi_processor_info_fops = {
- .open = acpi_processor_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
-struct acpi_processor *processors[NR_CPUS];
+struct acpi_processor *processors[NR_CPUS];
struct acpi_processor_errata errata;
-
/* --------------------------------------------------------------------------
Errata Handling
-------------------------------------------------------------------------- */
-static int
-acpi_processor_errata_piix4 (
- struct pci_dev *dev)
+static int acpi_processor_errata_piix4(struct pci_dev *dev)
{
- u8 rev = 0;
- u8 value1 = 0;
- u8 value2 = 0;
+ u8 rev = 0;
+ u8 value1 = 0;
+ u8 value2 = 0;
ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
@@ -188,8 +181,8 @@ acpi_processor_errata_piix4 (
* DMA activity.
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB,
- PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
errata.piix4.bmisx = pci_resource_start(dev, 4);
pci_dev_put(dev);
@@ -205,8 +198,8 @@ acpi_processor_errata_piix4 (
* devices won't operate well if fast DMA is disabled.
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_0,
- PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB_0,
+ PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
pci_read_config_byte(dev, 0x76, &value1);
pci_read_config_byte(dev, 0x77, &value2);
@@ -220,21 +213,18 @@ acpi_processor_errata_piix4 (
if (errata.piix4.bmisx)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Bus master activity detection (BM-IDE) erratum enabled\n"));
+ "Bus master activity detection (BM-IDE) erratum enabled\n"));
if (errata.piix4.fdma)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Type-F DMA livelock erratum (C3 disabled)\n"));
+ "Type-F DMA livelock erratum (C3 disabled)\n"));
return_VALUE(0);
}
-
-int
-acpi_processor_errata (
- struct acpi_processor *pr)
+static int acpi_processor_errata(struct acpi_processor *pr)
{
- int result = 0;
- struct pci_dev *dev = NULL;
+ int result = 0;
+ struct pci_dev *dev = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_errata");
@@ -245,7 +235,8 @@ acpi_processor_errata (
* PIIX4
*/
dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
+ PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
+ PCI_ANY_ID, NULL);
if (dev) {
result = acpi_processor_errata_piix4(dev);
pci_dev_put(dev);
@@ -254,7 +245,6 @@ acpi_processor_errata (
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
Common ACPI processor fucntions
-------------------------------------------------------------------------- */
@@ -265,13 +255,13 @@ acpi_processor_errata (
*/
int acpi_processor_set_pdc(struct acpi_processor *pr,
- struct acpi_object_list *pdc_in)
+ struct acpi_object_list *pdc_in)
{
- acpi_status status = AE_OK;
- u32 arg0_buf[3];
- union acpi_object arg0 = {ACPI_TYPE_BUFFER};
- struct acpi_object_list no_object = {1, &arg0};
- struct acpi_object_list *pdc;
+ acpi_status status = AE_OK;
+ u32 arg0_buf[3];
+ union acpi_object arg0 = { ACPI_TYPE_BUFFER };
+ struct acpi_object_list no_object = { 1, &arg0 };
+ struct acpi_object_list *pdc;
ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
@@ -286,21 +276,21 @@ int acpi_processor_set_pdc(struct acpi_processor *pr,
status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
if ((ACPI_FAILURE(status)) && (pdc_in))
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Error evaluating _PDC, using legacy perf. control...\n"));
return_VALUE(status);
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_processor_dir = NULL;
+static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
@@ -308,40 +298,37 @@ static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "processor id: %d\n"
- "acpi id: %d\n"
- "bus mastering control: %s\n"
- "power management: %s\n"
- "throttling control: %s\n"
- "limit interface: %s\n",
- pr->id,
- pr->acpi_id,
- pr->flags.bm_control ? "yes" : "no",
- pr->flags.power ? "yes" : "no",
- pr->flags.throttling ? "yes" : "no",
- pr->flags.limit ? "yes" : "no");
-
-end:
+ "acpi id: %d\n"
+ "bus mastering control: %s\n"
+ "power management: %s\n"
+ "throttling control: %s\n"
+ "limit interface: %s\n",
+ pr->id,
+ pr->acpi_id,
+ pr->flags.bm_control ? "yes" : "no",
+ pr->flags.power ? "yes" : "no",
+ pr->flags.throttling ? "yes" : "no",
+ pr->flags.limit ? "yes" : "no");
+
+ end:
return_VALUE(0);
}
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_info_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-
-static int
-acpi_processor_add_fs (
- struct acpi_device *device)
+static int acpi_processor_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_processor_dir);
+ acpi_processor_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
@@ -349,11 +336,11 @@ acpi_processor_add_fs (
/* 'info' [R] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_INFO));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_INFO));
else {
entry->proc_fops = &acpi_processor_info_fops;
entry->data = acpi_driver_data(device);
@@ -362,11 +349,12 @@ acpi_processor_add_fs (
/* 'throttling' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_THROTTLING));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_THROTTLING));
else {
entry->proc_fops = &acpi_processor_throttling_fops;
entry->proc_fops->write = acpi_processor_write_throttling;
@@ -376,11 +364,12 @@ acpi_processor_add_fs (
/* 'limit' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_LIMIT));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_LIMIT));
else {
entry->proc_fops = &acpi_processor_limit_fops;
entry->proc_fops->write = acpi_processor_write_limit;
@@ -391,18 +380,17 @@ acpi_processor_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_processor_remove_fs (
- struct acpi_device *device)
+static int acpi_processor_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_processor_remove_fs");
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
+ acpi_device_dir(device));
remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
- acpi_device_dir(device));
- remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,acpi_device_dir(device));
+ acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
+ acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
acpi_device_dir(device) = NULL;
}
@@ -446,15 +434,13 @@ static u8 convert_acpiid_to_cpu(u8 acpi_id)
Driver Interface
-------------------------------------------------------------------------- */
-static int
-acpi_processor_get_info (
- struct acpi_processor *pr)
+static int acpi_processor_get_info(struct acpi_processor *pr)
{
- acpi_status status = 0;
- union acpi_object object = {0};
- struct acpi_buffer buffer = {sizeof(union acpi_object), &object};
- u8 cpu_index;
- static int cpu0_initialized;
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ u8 cpu_index;
+ static int cpu0_initialized;
ACPI_FUNCTION_TRACE("acpi_processor_get_info");
@@ -473,11 +459,10 @@ acpi_processor_get_info (
if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) {
pr->flags.bm_control = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Bus mastering arbitration control present\n"));
- }
- else
+ "Bus mastering arbitration control present\n"));
+ } else
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No bus mastering arbitration control\n"));
+ "No bus mastering arbitration control\n"));
/*
* Evalute the processor object. Note that it is common on SMP to
@@ -487,50 +472,51 @@ acpi_processor_get_info (
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error evaluating processor object\n"));
+ "Error evaluating processor object\n"));
return_VALUE(-ENODEV);
}
/*
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
- * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
*/
pr->acpi_id = object.processor.proc_id;
cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
- /* Handle UP system running SMP kernel, with no LAPIC in MADT */
- if ( !cpu0_initialized && (cpu_index == 0xff) &&
- (num_online_cpus() == 1)) {
- cpu_index = 0;
- }
-
- cpu0_initialized = 1;
-
- pr->id = cpu_index;
-
- /*
- * Extra Processor objects may be enumerated on MP systems with
- * less than the max # of CPUs. They should be ignored _iff
- * they are physically not present.
- */
- if (cpu_index >= NR_CPUS) {
- if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error getting cpuindex for acpiid 0x%x\n",
- pr->acpi_id));
- return_VALUE(-ENODEV);
- }
- }
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == 0xff) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (cpu_index >= NR_CPUS) {
+ if (ACPI_FAILURE
+ (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error getting cpuindex for acpiid 0x%x\n",
+ pr->acpi_id));
+ return_VALUE(-ENODEV);
+ }
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
- pr->acpi_id));
+ pr->acpi_id));
if (!object.processor.pblk_address)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
else if (object.processor.pblk_length != 6)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n",
- object.processor.pblk_length));
+ object.processor.pblk_length));
else {
pr->throttling.address = object.processor.pblk_address;
pr->throttling.duty_offset = acpi_fadt.duty_offset;
@@ -557,13 +543,11 @@ acpi_processor_get_info (
return_VALUE(0);
}
-static int
-acpi_processor_start(
- struct acpi_device *device)
+static int acpi_processor_start(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_processor *pr;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_start");
@@ -584,36 +568,30 @@ acpi_processor_start(
goto end;
status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
- acpi_processor_notify, pr);
+ acpi_processor_notify, pr);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing device notify handler\n"));
+ "Error installing device notify handler\n"));
}
acpi_processor_power_init(pr, device);
if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
- acpi_device_name(device), acpi_device_bid(device));
+ acpi_device_name(device), acpi_device_bid(device));
printk(" %d throttling states", pr->throttling.state_count);
printk(")\n");
}
-end:
+ end:
return_VALUE(result);
}
-
-
-static void
-acpi_processor_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_processor *pr = (struct acpi_processor *) data;
- struct acpi_device *device = NULL;
+ struct acpi_processor *pr = (struct acpi_processor *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_notify");
@@ -627,7 +605,7 @@ acpi_processor_notify (
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
acpi_processor_ppc_has_changed(pr);
acpi_bus_generate_event(device, event,
- pr->performance_platform_limit);
+ pr->performance_platform_limit);
break;
case ACPI_PROCESSOR_NOTIFY_POWER:
acpi_processor_cst_has_changed(pr);
@@ -635,19 +613,16 @@ acpi_processor_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_processor_add (
- struct acpi_device *device)
+static int acpi_processor_add(struct acpi_device *device)
{
- struct acpi_processor *pr = NULL;
+ struct acpi_processor *pr = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_add");
@@ -667,21 +642,17 @@ acpi_processor_add (
return_VALUE(0);
}
-
-static int
-acpi_processor_remove (
- struct acpi_device *device,
- int type)
+static int acpi_processor_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_processor *pr = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_processor *pr = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- pr = (struct acpi_processor *) acpi_driver_data(device);
+ pr = (struct acpi_processor *)acpi_driver_data(device);
if (pr->id >= NR_CPUS) {
kfree(pr);
@@ -696,10 +667,10 @@ acpi_processor_remove (
acpi_processor_power_exit(pr, device);
status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
- acpi_processor_notify);
+ acpi_processor_notify);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
}
acpi_processor_remove_fs(device);
@@ -718,33 +689,28 @@ acpi_processor_remove (
static int is_processor_present(acpi_handle handle);
-static int
-is_processor_present(
- acpi_handle handle)
+static int is_processor_present(acpi_handle handle)
{
- acpi_status status;
- unsigned long sta = 0;
+ acpi_status status;
+ unsigned long sta = 0;
ACPI_FUNCTION_TRACE("is_processor_present");
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Processor Device is not present\n"));
+ "Processor Device is not present\n"));
return_VALUE(0);
}
return_VALUE(1);
}
-
static
-int acpi_processor_device_add(
- acpi_handle handle,
- struct acpi_device **device)
+int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
{
- acpi_handle phandle;
- struct acpi_device *pdev;
- struct acpi_processor *pr;
+ acpi_handle phandle;
+ struct acpi_device *pdev;
+ struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_device_add");
@@ -766,21 +732,17 @@ int acpi_processor_device_add(
if (!pr)
return_VALUE(-ENODEV);
- if ((pr->id >=0) && (pr->id < NR_CPUS)) {
+ if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
}
return_VALUE(0);
}
-
static void
-acpi_processor_hotplug_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_processor *pr;
- struct acpi_device *device = NULL;
+ struct acpi_processor *pr;
+ struct acpi_device *device = NULL;
int result;
ACPI_FUNCTION_TRACE("acpi_processor_hotplug_notify");
@@ -789,8 +751,8 @@ acpi_processor_hotplug_notify (
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
printk("Processor driver received %s event\n",
- (event==ACPI_NOTIFY_BUS_CHECK)?
- "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ (event == ACPI_NOTIFY_BUS_CHECK) ?
+ "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
if (!is_processor_present(handle))
break;
@@ -799,14 +761,14 @@ acpi_processor_hotplug_notify (
result = acpi_processor_device_add(handle, &device);
if (result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to add the device\n"));
+ "Unable to add the device\n"));
break;
}
pr = acpi_driver_data(device);
if (!pr) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Driver data is NULL\n"));
+ "Driver data is NULL\n"));
break;
}
@@ -816,24 +778,27 @@ acpi_processor_hotplug_notify (
}
result = acpi_processor_start(device);
- if ((!result) && ((pr->id >=0) && (pr->id < NR_CPUS))) {
+ if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
kobject_hotplug(&device->kobj, KOBJ_ONLINE);
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Device [%s] failed to start\n",
- acpi_device_bid(device)));
+ "Device [%s] failed to start\n",
+ acpi_device_bid(device)));
}
- break;
+ break;
case ACPI_NOTIFY_EJECT_REQUEST:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,"received ACPI_NOTIFY_EJECT_REQUEST\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "received ACPI_NOTIFY_EJECT_REQUEST\n"));
if (acpi_bus_get_device(handle, &device)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Device don't exist, dropping EJECT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device don't exist, dropping EJECT\n"));
break;
}
pr = acpi_driver_data(device);
if (!pr) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Driver data is NULL, dropping EJECT\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Driver data is NULL, dropping EJECT\n"));
return_VOID;
}
@@ -842,7 +807,7 @@ acpi_processor_hotplug_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
@@ -851,45 +816,39 @@ acpi_processor_hotplug_notify (
static acpi_status
processor_walk_namespace_cb(acpi_handle handle,
- u32 lvl,
- void *context,
- void **rv)
+ u32 lvl, void *context, void **rv)
{
- acpi_status status;
+ acpi_status status;
int *action = context;
- acpi_object_type type = 0;
+ acpi_object_type type = 0;
status = acpi_get_type(handle, &type);
if (ACPI_FAILURE(status))
- return(AE_OK);
+ return (AE_OK);
if (type != ACPI_TYPE_PROCESSOR)
- return(AE_OK);
+ return (AE_OK);
- switch(*action) {
+ switch (*action) {
case INSTALL_NOTIFY_HANDLER:
acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- acpi_processor_hotplug_notify,
- NULL);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_processor_hotplug_notify,
+ NULL);
break;
case UNINSTALL_NOTIFY_HANDLER:
acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- acpi_processor_hotplug_notify);
+ ACPI_SYSTEM_NOTIFY,
+ acpi_processor_hotplug_notify);
break;
default:
break;
}
- return(AE_OK);
+ return (AE_OK);
}
-
-static acpi_status
-acpi_processor_hotadd_init(
- acpi_handle handle,
- int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
{
ACPI_FUNCTION_TRACE("acpi_processor_hotadd_init");
@@ -908,57 +867,47 @@ acpi_processor_hotadd_init(
return_VALUE(AE_OK);
}
-
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
{
if (cpu_online(pr->id)) {
- return(-EINVAL);
+ return (-EINVAL);
}
arch_unregister_cpu(pr->id);
acpi_unmap_lsapic(pr->id);
- return(0);
+ return (0);
}
#else
-static acpi_status
-acpi_processor_hotadd_init(
- acpi_handle handle,
- int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
{
return AE_ERROR;
}
-static int
-acpi_processor_handle_eject(struct acpi_processor *pr)
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
{
- return(-EINVAL);
+ return (-EINVAL);
}
#endif
-
static
void acpi_processor_install_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = INSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- processor_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ processor_walk_namespace_cb, &action, NULL);
#endif
}
-
static
void acpi_processor_uninstall_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = UNINSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- processor_walk_namespace_cb,
- &action, NULL);
+ ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ processor_walk_namespace_cb, &action, NULL);
#endif
}
@@ -968,10 +917,9 @@ void acpi_processor_uninstall_hotplug_notify(void)
* ACPI, but needs symbols from this driver
*/
-static int __init
-acpi_processor_init (void)
+static int __init acpi_processor_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_init");
@@ -998,9 +946,7 @@ acpi_processor_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_processor_exit (void)
+static void __exit acpi_processor_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_processor_exit");
@@ -1017,7 +963,6 @@ acpi_processor_exit (void)
return_VOID;
}
-
module_init(acpi_processor_init);
module_exit(acpi_processor_exit);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2c04740c6543..161db4acfb91 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -37,6 +37,7 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/moduleparam.h>
+#include <linux/sched.h> /* need_resched() */
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -48,15 +49,12 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
#define ACPI_PROCESSOR_FILE_POWER "power"
-
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
-
-static void (*pm_idle_save)(void);
+static void (*pm_idle_save) (void);
module_param(max_cstate, uint, 0644);
static unsigned int nocst = 0;
@@ -69,7 +67,8 @@ module_param(nocst, uint, 0000);
* 100 HZ: 0x0000000F: 4 jiffies = 40ms
* reduce history for more aggressive entry into C3
*/
-static unsigned int bm_history = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
+static unsigned int bm_history =
+ (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
module_param(bm_history, uint, 0644);
/* --------------------------------------------------------------------------
Power Management
@@ -87,34 +86,36 @@ static int set_max_cstate(struct dmi_system_id *id)
return 0;
printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate."
- " Override with \"processor.max_cstate=%d\"\n", id->ident,
- (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
+ " Override with \"processor.max_cstate=%d\"\n", id->ident,
+ (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
max_cstate = (long)id->driver_data;
return 0;
}
-
static struct dmi_system_id __initdata processor_power_dmi_table[] = {
- { set_max_cstate, "IBM ThinkPad R40e", {
- DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
- DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
- { set_max_cstate, "Medion 41700", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1},
- { set_max_cstate, "Clevo 5600D", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") },
- (void*)2},
+ {set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "1SET60WW")},
+ (void *)1},
+ {set_max_cstate, "Medion 41700", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "R01-A1J")}, (void *)1},
+ {set_max_cstate, "Clevo 5600D", {
+ DMI_MATCH(DMI_BIOS_VENDOR,
+ "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "SHE845M0.86C.0013.D.0302131307")},
+ (void *)2},
{},
};
-
-static inline u32
-ticks_elapsed (
- u32 t1,
- u32 t2)
+static inline u32 ticks_elapsed(u32 t1, u32 t2)
{
if (t2 >= t1)
return (t2 - t1);
@@ -124,13 +125,11 @@ ticks_elapsed (
return ((0xFFFFFFFF - t1) + t2);
}
-
static void
-acpi_processor_power_activate (
- struct acpi_processor *pr,
- struct acpi_processor_cx *new)
+acpi_processor_power_activate(struct acpi_processor *pr,
+ struct acpi_processor_cx *new)
{
- struct acpi_processor_cx *old;
+ struct acpi_processor_cx *old;
if (!pr || !new)
return;
@@ -139,7 +138,7 @@ acpi_processor_power_activate (
if (old)
old->promotion.count = 0;
- new->demotion.count = 0;
+ new->demotion.count = 0;
/* Cleanup from old state. */
if (old) {
@@ -147,7 +146,8 @@ acpi_processor_power_activate (
case ACPI_STATE_C3:
/* Disable bus master reload */
if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
- acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
+ ACPI_MTX_DO_NOT_LOCK);
break;
}
}
@@ -157,7 +157,8 @@ acpi_processor_power_activate (
case ACPI_STATE_C3:
/* Enable bus master reload */
if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
- acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1,
+ ACPI_MTX_DO_NOT_LOCK);
break;
}
@@ -166,17 +167,15 @@ acpi_processor_power_activate (
return;
}
+static atomic_t c3_cpu_count;
-static atomic_t c3_cpu_count;
-
-
-static void acpi_processor_idle (void)
+static void acpi_processor_idle(void)
{
- struct acpi_processor *pr = NULL;
+ struct acpi_processor *pr = NULL;
struct acpi_processor_cx *cx = NULL;
struct acpi_processor_cx *next_state = NULL;
- int sleep_ticks = 0;
- u32 t1, t2 = 0;
+ int sleep_ticks = 0;
+ u32 t1, t2 = 0;
pr = processors[raw_smp_processor_id()];
if (!pr)
@@ -208,8 +207,8 @@ static void acpi_processor_idle (void)
* for demotion.
*/
if (pr->flags.bm_check) {
- u32 bm_status = 0;
- unsigned long diff = jiffies - pr->power.bm_check_timestamp;
+ u32 bm_status = 0;
+ unsigned long diff = jiffies - pr->power.bm_check_timestamp;
if (diff > 32)
diff = 32;
@@ -223,11 +222,11 @@ static void acpi_processor_idle (void)
}
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
- &bm_status, ACPI_MTX_DO_NOT_LOCK);
+ &bm_status, ACPI_MTX_DO_NOT_LOCK);
if (bm_status) {
pr->power.bm_activity++;
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS,
- 1, ACPI_MTX_DO_NOT_LOCK);
+ 1, ACPI_MTX_DO_NOT_LOCK);
}
/*
* PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
@@ -236,7 +235,7 @@ static void acpi_processor_idle (void)
*/
else if (errata.piix4.bmisx) {
if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
- || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+ || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
pr->power.bm_activity++;
}
@@ -281,7 +280,7 @@ static void acpi_processor_idle (void)
else
safe_halt();
/*
- * TBD: Can't get time duration while in C1, as resumes
+ * TBD: Can't get time duration while in C1, as resumes
* go to an ISR rather than here. Need to instrument
* base interrupt handler.
*/
@@ -300,26 +299,27 @@ static void acpi_processor_idle (void)
/* Re-enable interrupts */
local_irq_enable();
/* Compute time (ticks) that we were actually asleep */
- sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+ sleep_ticks =
+ ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
break;
case ACPI_STATE_C3:
-
+
if (pr->flags.bm_check) {
if (atomic_inc_return(&c3_cpu_count) ==
- num_online_cpus()) {
+ num_online_cpus()) {
/*
* All CPUs are trying to go to C3
* Disable bus master arbitration
*/
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
- ACPI_MTX_DO_NOT_LOCK);
+ ACPI_MTX_DO_NOT_LOCK);
}
} else {
/* SMP with no shared cache... Invalidate cache */
ACPI_FLUSH_CPU_CACHE();
}
-
+
/* Get start time (ticks) */
t1 = inl(acpi_fadt.xpm_tmr_blk.address);
/* Invoke C3 */
@@ -331,13 +331,15 @@ static void acpi_processor_idle (void)
if (pr->flags.bm_check) {
/* Enable bus master arbitration */
atomic_dec(&c3_cpu_count);
- acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
+ ACPI_MTX_DO_NOT_LOCK);
}
/* Re-enable interrupts */
local_irq_enable();
/* Compute time (ticks) that we were actually asleep */
- sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+ sleep_ticks =
+ ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
break;
default:
@@ -359,15 +361,18 @@ static void acpi_processor_idle (void)
((cx->promotion.state - pr->power.states) <= max_cstate)) {
if (sleep_ticks > cx->promotion.threshold.ticks) {
cx->promotion.count++;
- cx->demotion.count = 0;
- if (cx->promotion.count >= cx->promotion.threshold.count) {
+ cx->demotion.count = 0;
+ if (cx->promotion.count >=
+ cx->promotion.threshold.count) {
if (pr->flags.bm_check) {
- if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) {
- next_state = cx->promotion.state;
+ if (!
+ (pr->power.bm_activity & cx->
+ promotion.threshold.bm)) {
+ next_state =
+ cx->promotion.state;
goto end;
}
- }
- else {
+ } else {
next_state = cx->promotion.state;
goto end;
}
@@ -392,7 +397,7 @@ static void acpi_processor_idle (void)
}
}
-end:
+ end:
/*
* Demote if current state exceeds max_cstate
*/
@@ -412,7 +417,7 @@ end:
return;
- easy_out:
+ easy_out:
/* do C1 instead of busy loop */
if (pm_idle_save)
pm_idle_save();
@@ -421,10 +426,7 @@ end:
return;
}
-
-static int
-acpi_processor_set_power_policy (
- struct acpi_processor *pr)
+static int acpi_processor_set_power_policy(struct acpi_processor *pr)
{
unsigned int i;
unsigned int state_is_set = 0;
@@ -432,7 +434,7 @@ acpi_processor_set_power_policy (
struct acpi_processor_cx *higher = NULL;
struct acpi_processor_cx *cx;
- ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy");
+ ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy");
if (!pr)
return_VALUE(-EINVAL);
@@ -447,7 +449,7 @@ acpi_processor_set_power_policy (
*/
/* startup state */
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
cx = &pr->power.states[i];
if (!cx->valid)
continue;
@@ -456,13 +458,13 @@ acpi_processor_set_power_policy (
pr->power.state = cx;
state_is_set++;
break;
- }
+ }
if (!state_is_set)
return_VALUE(-ENODEV);
/* demotion */
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
cx = &pr->power.states[i];
if (!cx->valid)
continue;
@@ -485,7 +487,7 @@ acpi_processor_set_power_policy (
continue;
if (higher) {
- cx->promotion.state = higher;
+ cx->promotion.state = higher;
cx->promotion.threshold.ticks = cx->latency_ticks;
if (cx->type >= ACPI_STATE_C2)
cx->promotion.threshold.count = 4;
@@ -498,11 +500,10 @@ acpi_processor_set_power_policy (
higher = cx;
}
- return_VALUE(0);
+ return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
{
int i;
@@ -543,15 +544,14 @@ static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr)
return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
{
int i;
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
+ memset(&(pr->power.states[i]), 0,
sizeof(struct acpi_processor_cx));
/* if info is obtained from pblk/fadt, type equals state */
@@ -567,14 +567,13 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
return_VALUE(0);
}
-
-static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
+static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
{
- acpi_status status = 0;
- acpi_integer count;
- int i;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *cst;
+ acpi_status status = 0;
+ acpi_integer count;
+ int i;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *cst;
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst");
@@ -583,20 +582,21 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
pr->power.count = 0;
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
+ memset(&(pr->power.states[i]), 0,
sizeof(struct acpi_processor_cx));
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n"));
return_VALUE(-ENODEV);
- }
+ }
- cst = (union acpi_object *) buffer.pointer;
+ cst = (union acpi_object *)buffer.pointer;
/* There must be at least 2 elements */
if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "not enough elements in _CST\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "not enough elements in _CST\n"));
status = -EFAULT;
goto end;
}
@@ -605,15 +605,19 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
/* Validate number of power states. */
if (count < 1 || count != cst->package.count - 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "count given by _CST is not valid\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "count given by _CST is not valid\n"));
status = -EFAULT;
goto end;
}
/* We support up to ACPI_PROCESSOR_MAX_POWER. */
if (count > ACPI_PROCESSOR_MAX_POWER) {
- printk(KERN_WARNING "Limiting number of power states to max (%d)\n", ACPI_PROCESSOR_MAX_POWER);
- printk(KERN_WARNING "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
+ printk(KERN_WARNING
+ "Limiting number of power states to max (%d)\n",
+ ACPI_PROCESSOR_MAX_POWER);
+ printk(KERN_WARNING
+ "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
count = ACPI_PROCESSOR_MAX_POWER;
}
@@ -628,29 +632,29 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
memset(&cx, 0, sizeof(cx));
- element = (union acpi_object *) &(cst->package.elements[i]);
+ element = (union acpi_object *)&(cst->package.elements[i]);
if (element->type != ACPI_TYPE_PACKAGE)
continue;
if (element->package.count != 4)
continue;
- obj = (union acpi_object *) &(element->package.elements[0]);
+ obj = (union acpi_object *)&(element->package.elements[0]);
if (obj->type != ACPI_TYPE_BUFFER)
continue;
- reg = (struct acpi_power_register *) obj->buffer.pointer;
+ reg = (struct acpi_power_register *)obj->buffer.pointer;
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
- (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
+ (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
continue;
cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
- 0 : reg->address;
+ 0 : reg->address;
/* There should be an easy way to extract an integer... */
- obj = (union acpi_object *) &(element->package.elements[1]);
+ obj = (union acpi_object *)&(element->package.elements[1]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -660,17 +664,16 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO))
continue;
- if ((cx.type < ACPI_STATE_C1) ||
- (cx.type > ACPI_STATE_C3))
+ if ((cx.type < ACPI_STATE_C1) || (cx.type > ACPI_STATE_C3))
continue;
- obj = (union acpi_object *) &(element->package.elements[2]);
+ obj = (union acpi_object *)&(element->package.elements[2]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
cx.latency = obj->integer.value;
- obj = (union acpi_object *) &(element->package.elements[3]);
+ obj = (union acpi_object *)&(element->package.elements[3]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -680,19 +683,19 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", pr->power.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
+ pr->power.count));
/* Validate number of power states discovered */
if (pr->power.count < 2)
status = -ENODEV;
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(status);
}
-
static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c2");
@@ -706,8 +709,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
*/
else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "latency too large [%d]\n",
- cx->latency));
+ "latency too large [%d]\n", cx->latency));
return_VOID;
}
@@ -721,10 +723,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
return_VOID;
}
-
-static void acpi_processor_power_verify_c3(
- struct acpi_processor *pr,
- struct acpi_processor_cx *cx)
+static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
+ struct acpi_processor_cx *cx)
{
static int bm_check_flag;
@@ -739,8 +739,7 @@ static void acpi_processor_power_verify_c3(
*/
else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "latency too large [%d]\n",
- cx->latency));
+ "latency too large [%d]\n", cx->latency));
return_VOID;
}
@@ -753,7 +752,7 @@ static void acpi_processor_power_verify_c3(
*/
else if (errata.piix4.fdma) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "C3 not supported on PIIX4 with Type-F DMA\n"));
+ "C3 not supported on PIIX4 with Type-F DMA\n"));
return_VOID;
}
@@ -770,7 +769,7 @@ static void acpi_processor_power_verify_c3(
/* bus mastering control is necessary */
if (!pr->flags.bm_control) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "C3 support requires bus mastering control\n"));
+ "C3 support requires bus mastering control\n"));
return_VOID;
}
} else {
@@ -780,12 +779,12 @@ static void acpi_processor_power_verify_c3(
*/
if (acpi_fadt.wb_invd != 1) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Cache invalidation should work properly"
- " for C3 to be enabled on SMP systems\n"));
+ "Cache invalidation should work properly"
+ " for C3 to be enabled on SMP systems\n"));
return_VOID;
}
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD,
- 0, ACPI_MTX_DO_NOT_LOCK);
+ 0, ACPI_MTX_DO_NOT_LOCK);
}
/*
@@ -800,13 +799,12 @@ static void acpi_processor_power_verify_c3(
return_VOID;
}
-
static int acpi_processor_power_verify(struct acpi_processor *pr)
{
unsigned int i;
unsigned int working = 0;
- for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
struct acpi_processor_cx *cx = &pr->power.states[i];
switch (cx->type) {
@@ -830,8 +828,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
return (working);
}
-static int acpi_processor_get_power_info (
- struct acpi_processor *pr)
+static int acpi_processor_get_power_info(struct acpi_processor *pr)
{
unsigned int i;
int result;
@@ -874,16 +871,16 @@ static int acpi_processor_get_power_info (
return_VALUE(0);
}
-int acpi_processor_cst_has_changed (struct acpi_processor *pr)
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_cst_has_changed");
if (!pr)
- return_VALUE(-EINVAL);
+ return_VALUE(-EINVAL);
- if ( nocst) {
+ if (nocst) {
return_VALUE(-ENODEV);
}
@@ -892,7 +889,7 @@ int acpi_processor_cst_has_changed (struct acpi_processor *pr)
/* Fall back to the default idle loop */
pm_idle = pm_idle_save;
- synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
+ synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
pr->flags.power = 0;
result = acpi_processor_get_power_info(pr);
@@ -906,8 +903,8 @@ int acpi_processor_cst_has_changed (struct acpi_processor *pr)
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- unsigned int i;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ unsigned int i;
ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show");
@@ -915,17 +912,17 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "active state: C%zd\n"
- "max_cstate: C%d\n"
- "bus master activity: %08x\n",
- pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate,
- (unsigned)pr->power.bm_activity);
+ "max_cstate: C%d\n"
+ "bus master activity: %08x\n",
+ pr->power.state ? pr->power.state - pr->power.states : 0,
+ max_cstate, (unsigned)pr->power.bm_activity);
seq_puts(seq, "states:\n");
for (i = 1; i <= pr->power.count; i++) {
seq_printf(seq, " %cC%d: ",
- (&pr->power.states[i] == pr->power.state?'*':' '), i);
+ (&pr->power.states[i] ==
+ pr->power.state ? '*' : ' '), i);
if (!pr->power.states[i].valid) {
seq_puts(seq, "<not supported>\n");
@@ -949,45 +946,46 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
if (pr->power.states[i].promotion.state)
seq_printf(seq, "promotion[C%zd] ",
- (pr->power.states[i].promotion.state -
- pr->power.states));
+ (pr->power.states[i].promotion.state -
+ pr->power.states));
else
seq_puts(seq, "promotion[--] ");
if (pr->power.states[i].demotion.state)
seq_printf(seq, "demotion[C%zd] ",
- (pr->power.states[i].demotion.state -
- pr->power.states));
+ (pr->power.states[i].demotion.state -
+ pr->power.states));
else
seq_puts(seq, "demotion[--] ");
seq_printf(seq, "latency[%03d] usage[%08d]\n",
- pr->power.states[i].latency,
- pr->power.states[i].usage);
+ pr->power.states[i].latency,
+ pr->power.states[i].usage);
}
-end:
+ end:
return_VALUE(0);
}
static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_power_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static struct file_operations acpi_processor_power_fops = {
- .open = acpi_processor_power_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_power_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device)
+int acpi_processor_power_init(struct acpi_processor *pr,
+ struct acpi_device *device)
{
- acpi_status status = 0;
- static int first_run = 0;
- struct proc_dir_entry *entry = NULL;
+ acpi_status status = 0;
+ static int first_run = 0;
+ struct proc_dir_entry *entry = NULL;
unsigned int i;
ACPI_FUNCTION_TRACE("acpi_processor_power_init");
@@ -995,7 +993,9 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
if (!first_run) {
dmi_check_system(processor_power_dmi_table);
if (max_cstate < ACPI_C_STATES_MAX)
- printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate);
+ printk(KERN_NOTICE
+ "ACPI: processor limited to max C-state %d\n",
+ max_cstate);
first_run++;
}
@@ -1003,7 +1003,8 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
return_VALUE(-EINVAL);
if (acpi_fadt.cst_cnt && !nocst) {
- status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
+ status =
+ acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Notifying BIOS of _CST ability failed\n"));
@@ -1023,7 +1024,8 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
for (i = 1; i <= pr->power.count; i++)
if (pr->power.states[i].valid)
- printk(" C%d[C%d]", i, pr->power.states[i].type);
+ printk(" C%d[C%d]", i,
+ pr->power.states[i].type);
printk(")\n");
if (pr->id == 0) {
@@ -1034,11 +1036,11 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
/* 'power' [R] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_POWER));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_POWER));
else {
entry->proc_fops = &acpi_processor_power_fops;
entry->data = acpi_driver_data(device);
@@ -1050,14 +1052,16 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev
return_VALUE(0);
}
-int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device)
+int acpi_processor_power_exit(struct acpi_processor *pr,
+ struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_processor_power_exit");
pr->flags.power_setup_done = 0;
if (acpi_device_dir(device))
- remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
+ remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
+ acpi_device_dir(device));
/* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0) {
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 1f0d6256302f..22c7bb66c200 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -26,7 +26,6 @@
*
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -42,14 +41,12 @@
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
-
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
static DECLARE_MUTEX(performance_sem);
@@ -69,8 +66,7 @@ static DECLARE_MUTEX(performance_sem);
static int acpi_processor_ppc_status = 0;
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
- unsigned long event,
- void *data)
+ unsigned long event, void *data)
{
struct cpufreq_policy *policy = data;
struct acpi_processor *pr;
@@ -85,7 +81,7 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
if (!pr || !pr->performance)
goto out;
- ppc = (unsigned int) pr->performance_platform_limit;
+ ppc = (unsigned int)pr->performance_platform_limit;
if (!ppc)
goto out;
@@ -93,26 +89,23 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
goto out;
cpufreq_verify_within_limits(policy, 0,
- pr->performance->states[ppc].core_frequency * 1000);
+ pr->performance->states[ppc].
+ core_frequency * 1000);
- out:
+ out:
up(&performance_sem);
return 0;
}
-
static struct notifier_block acpi_ppc_notifier_block = {
.notifier_call = acpi_processor_ppc_notifier,
};
-
-static int
-acpi_processor_get_platform_limit (
- struct acpi_processor* pr)
+static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
- acpi_status status = 0;
- unsigned long ppc = 0;
+ acpi_status status = 0;
+ unsigned long ppc = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
@@ -128,19 +121,17 @@ acpi_processor_get_platform_limit (
if (status != AE_NOT_FOUND)
acpi_processor_ppc_status |= PPC_IN_USE;
- if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
return_VALUE(-ENODEV);
}
- pr->performance_platform_limit = (int) ppc;
+ pr->performance_platform_limit = (int)ppc;
return_VALUE(0);
}
-
-int acpi_processor_ppc_has_changed(
- struct acpi_processor *pr)
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
{
int ret = acpi_processor_get_platform_limit(pr);
if (ret < 0)
@@ -149,44 +140,44 @@ int acpi_processor_ppc_has_changed(
return cpufreq_update_policy(pr->id);
}
-
-void acpi_processor_ppc_init(void) {
- if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
+void acpi_processor_ppc_init(void)
+{
+ if (!cpufreq_register_notifier
+ (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
acpi_processor_ppc_status |= PPC_REGISTERED;
else
- printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
+ printk(KERN_DEBUG
+ "Warning: Processor Platform Limit not supported.\n");
}
-
-void acpi_processor_ppc_exit(void) {
+void acpi_processor_ppc_exit(void)
+{
if (acpi_processor_ppc_status & PPC_REGISTERED)
- cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
acpi_processor_ppc_status &= ~PPC_REGISTERED;
}
-
-static int
-acpi_processor_get_performance_control (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_control(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *pct = NULL;
- union acpi_object obj = {0};
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *pct = NULL;
+ union acpi_object obj = { 0 };
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
- if(ACPI_FAILURE(status)) {
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
return_VALUE(-ENODEV);
}
- pct = (union acpi_object *) buffer.pointer;
+ pct = (union acpi_object *)buffer.pointer;
if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
- || (pct->package.count != 2)) {
+ || (pct->package.count != 2)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
result = -EFAULT;
goto end;
@@ -199,15 +190,15 @@ acpi_processor_get_performance_control (
obj = pct->package.elements[0];
if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ || (obj.buffer.length < sizeof(struct acpi_pct_register))
+ || (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid _PCT data (control_register)\n"));
+ "Invalid _PCT data (control_register)\n"));
result = -EFAULT;
goto end;
}
- memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
-
+ memcpy(&pr->performance->control_register, obj.buffer.pointer,
+ sizeof(struct acpi_pct_register));
/*
* status_register
@@ -216,44 +207,42 @@ acpi_processor_get_performance_control (
obj = pct->package.elements[1];
if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ || (obj.buffer.length < sizeof(struct acpi_pct_register))
+ || (obj.buffer.pointer == NULL)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Invalid _PCT data (status_register)\n"));
+ "Invalid _PCT data (status_register)\n"));
result = -EFAULT;
goto end;
}
- memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
+ memcpy(&pr->performance->status_register, obj.buffer.pointer,
+ sizeof(struct acpi_pct_register));
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(result);
}
-
-static int
-acpi_processor_get_performance_states (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_states(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"};
- struct acpi_buffer state = {0, NULL};
- union acpi_object *pss = NULL;
- int i;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
+ struct acpi_buffer state = { 0, NULL };
+ union acpi_object *pss = NULL;
+ int i;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
- if(ACPI_FAILURE(status)) {
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
return_VALUE(-ENODEV);
}
- pss = (union acpi_object *) buffer.pointer;
+ pss = (union acpi_object *)buffer.pointer;
if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
result = -EFAULT;
@@ -261,10 +250,12 @@ acpi_processor_get_performance_states (
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
- pss->package.count));
+ pss->package.count));
pr->performance->state_count = pss->package.count;
- pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
+ pr->performance->states =
+ kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
+ GFP_KERNEL);
if (!pr->performance->states) {
result = -ENOMEM;
goto end;
@@ -280,46 +271,44 @@ acpi_processor_get_performance_states (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
status = acpi_extract_package(&(pss->package.elements[i]),
- &format, &state);
+ &format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _PSS data\n"));
result = -EFAULT;
kfree(pr->performance->states);
goto end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
- i,
- (u32) px->core_frequency,
- (u32) px->power,
- (u32) px->transition_latency,
- (u32) px->bus_master_latency,
- (u32) px->control,
- (u32) px->status));
+ "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
+ i,
+ (u32) px->core_frequency,
+ (u32) px->power,
+ (u32) px->transition_latency,
+ (u32) px->bus_master_latency,
+ (u32) px->control, (u32) px->status));
if (!px->core_frequency) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _PSS data: freq is zero\n"));
result = -EFAULT;
kfree(pr->performance->states);
goto end;
}
}
-end:
+ end:
acpi_os_free(buffer.pointer);
return_VALUE(result);
}
-
-static int
-acpi_processor_get_performance_info (
- struct acpi_processor *pr)
+static int acpi_processor_get_performance_info(struct acpi_processor *pr)
{
- int result = 0;
- acpi_status status = AE_OK;
- acpi_handle handle = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
@@ -331,7 +320,7 @@ acpi_processor_get_performance_info (
status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "ACPI-based processor performance control unavailable\n"));
+ "ACPI-based processor performance control unavailable\n"));
return_VALUE(-ENODEV);
}
@@ -350,10 +339,10 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
-
-int acpi_processor_notify_smm(struct module *calling_module) {
- acpi_status status;
- static int is_done = 0;
+int acpi_processor_notify_smm(struct module *calling_module)
+{
+ acpi_status status;
+ static int is_done = 0;
ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
@@ -371,8 +360,7 @@ int acpi_processor_notify_smm(struct module *calling_module) {
if (is_done > 0) {
module_put(calling_module);
return_VALUE(0);
- }
- else if (is_done < 0) {
+ } else if (is_done < 0) {
module_put(calling_module);
return_VALUE(is_done);
}
@@ -380,28 +368,30 @@ int acpi_processor_notify_smm(struct module *calling_module) {
is_done = -EIO;
/* Can't write pstate_cnt to smi_cmd if either value is zero */
- if ((!acpi_fadt.smi_cmd) ||
- (!acpi_fadt.pstate_cnt)) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "No SMI port or pstate_cnt\n"));
+ if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_cnt\n"));
module_put(calling_module);
return_VALUE(0);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n",
+ acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
* it anyway, so we need to support it... */
if (acpi_fadt_is_v1) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Using v1.0 FADT reserved value for pstate_cnt\n"));
}
- status = acpi_os_write_port (acpi_fadt.smi_cmd,
- (u32) acpi_fadt.pstate_cnt, 8);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_write_port(acpi_fadt.smi_cmd,
+ (u32) acpi_fadt.pstate_cnt, 8);
+ if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Failed to write pstate_cnt [0x%x] to "
- "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
+ "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt,
+ acpi_fadt.smi_cmd));
module_put(calling_module);
return_VALUE(status);
}
@@ -415,24 +405,24 @@ int acpi_processor_notify_smm(struct module *calling_module) {
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_processor_notify_smm);
+EXPORT_SYMBOL(acpi_processor_notify_smm);
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_processor_perf_fops = {
- .open = acpi_processor_perf_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_perf_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- int i;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ int i;
ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
@@ -445,42 +435,40 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "state count: %d\n"
- "active state: P%d\n",
- pr->performance->state_count,
- pr->performance->state);
+ "active state: P%d\n",
+ pr->performance->state_count, pr->performance->state);
seq_puts(seq, "states:\n");
for (i = 0; i < pr->performance->state_count; i++)
- seq_printf(seq, " %cP%d: %d MHz, %d mW, %d uS\n",
- (i == pr->performance->state?'*':' '), i,
- (u32) pr->performance->states[i].core_frequency,
- (u32) pr->performance->states[i].power,
- (u32) pr->performance->states[i].transition_latency);
-
-end:
+ seq_printf(seq,
+ " %cP%d: %d MHz, %d mW, %d uS\n",
+ (i == pr->performance->state ? '*' : ' '), i,
+ (u32) pr->performance->states[i].core_frequency,
+ (u32) pr->performance->states[i].power,
+ (u32) pr->performance->states[i].transition_latency);
+
+ end:
return_VALUE(0);
}
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_perf_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_processor_write_performance (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_processor_write_performance(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *) m->private;
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
struct acpi_processor_performance *perf;
- char state_string[12] = {'\0'};
- unsigned int new_state = 0;
- struct cpufreq_policy policy;
+ char state_string[12] = { '\0' };
+ unsigned int new_state = 0;
+ struct cpufreq_policy policy;
ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
@@ -513,12 +501,10 @@ acpi_processor_write_performance (
return_VALUE(count);
}
-static void
-acpi_cpufreq_add_file (
- struct acpi_processor *pr)
+static void acpi_cpufreq_add_file(struct acpi_processor *pr)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_device *device = NULL;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
@@ -527,11 +513,12 @@ acpi_cpufreq_add_file (
/* add file 'performance' [R/W] */
entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_PERFORMANCE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_PERFORMANCE));
else {
entry->proc_fops = &acpi_processor_perf_fops;
entry->proc_fops->write = acpi_processor_write_performance;
@@ -541,11 +528,9 @@ acpi_cpufreq_add_file (
return_VOID;
}
-static void
-acpi_cpufreq_remove_file (
- struct acpi_processor *pr)
+static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
@@ -554,21 +539,25 @@ acpi_cpufreq_remove_file (
/* remove file 'performance' */
remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- acpi_device_dir(device));
+ acpi_device_dir(device));
return_VOID;
}
#else
-static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
-static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
-#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
-
+static void acpi_cpufreq_add_file(struct acpi_processor *pr)
+{
+ return;
+}
+static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
+{
+ return;
+}
+#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
int
-acpi_processor_register_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu)
+acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
{
struct acpi_processor *pr;
@@ -603,13 +592,12 @@ acpi_processor_register_performance (
up(&performance_sem);
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_processor_register_performance);
+EXPORT_SYMBOL(acpi_processor_register_performance);
void
-acpi_processor_unregister_performance (
- struct acpi_processor_performance * performance,
- unsigned int cpu)
+acpi_processor_unregister_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
{
struct acpi_processor *pr;
@@ -632,4 +620,5 @@ acpi_processor_unregister_performance (
return_VOID;
}
+
EXPORT_SYMBOL(acpi_processor_unregister_performance);
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 12bd980a12e9..37528c3b64b0 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -43,20 +43,16 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
/* --------------------------------------------------------------------------
Limit Interface
-------------------------------------------------------------------------- */
-
-static int
-acpi_processor_apply_limit (
- struct acpi_processor* pr)
+static int acpi_processor_apply_limit(struct acpi_processor *pr)
{
- int result = 0;
- u16 px = 0;
- u16 tx = 0;
+ int result = 0;
+ u16 px = 0;
+ u16 tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
@@ -80,19 +76,17 @@ acpi_processor_apply_limit (
pr->limit.state.px = px;
pr->limit.state.tx = tx;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n",
- pr->id,
- pr->limit.state.px,
- pr->limit.state.tx));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Processor [%d] limit set to (P%d:T%d)\n", pr->id,
+ pr->limit.state.px, pr->limit.state.tx));
-end:
+ end:
if (result)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
return_VALUE(result);
}
-
#ifdef CONFIG_CPU_FREQ
/* If a passive cooling situation is detected, primarily CPUfreq is used, as it
@@ -104,7 +98,6 @@ end:
static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
static unsigned int acpi_thermal_cpufreq_is_init = 0;
-
static int cpu_has_cpufreq(unsigned int cpu)
{
struct cpufreq_policy policy;
@@ -115,7 +108,6 @@ static int cpu_has_cpufreq(unsigned int cpu)
return 0;
}
-
static int acpi_thermal_cpufreq_increase(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
@@ -130,7 +122,6 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
return -ERANGE;
}
-
static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
@@ -145,11 +136,8 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
return -ERANGE;
}
-
-static int acpi_thermal_cpufreq_notifier(
- struct notifier_block *nb,
- unsigned long event,
- void *data)
+static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
{
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
@@ -157,68 +145,74 @@ static int acpi_thermal_cpufreq_notifier(
if (event != CPUFREQ_ADJUST)
goto out;
- max_freq = (policy->cpuinfo.max_freq * (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
+ max_freq =
+ (policy->cpuinfo.max_freq *
+ (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
cpufreq_verify_within_limits(policy, 0, max_freq);
- out:
+ out:
return 0;
}
-
static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
.notifier_call = acpi_thermal_cpufreq_notifier,
};
-
-void acpi_thermal_cpufreq_init(void) {
+void acpi_thermal_cpufreq_init(void)
+{
int i;
- for (i=0; i<NR_CPUS; i++)
+ for (i = 0; i < NR_CPUS; i++)
cpufreq_thermal_reduction_pctg[i] = 0;
- i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
if (!i)
acpi_thermal_cpufreq_is_init = 1;
}
-void acpi_thermal_cpufreq_exit(void) {
+void acpi_thermal_cpufreq_exit(void)
+{
if (acpi_thermal_cpufreq_is_init)
- cpufreq_unregister_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier
+ (&acpi_thermal_cpufreq_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
acpi_thermal_cpufreq_is_init = 0;
}
-#else /* ! CONFIG_CPU_FREQ */
-
-static int acpi_thermal_cpufreq_increase(unsigned int cpu) { return -ENODEV; }
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu) { return -ENODEV; }
+#else /* ! CONFIG_CPU_FREQ */
+static int acpi_thermal_cpufreq_increase(unsigned int cpu)
+{
+ return -ENODEV;
+}
+static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
+{
+ return -ENODEV;
+}
#endif
-
-int
-acpi_processor_set_thermal_limit (
- acpi_handle handle,
- int type)
+int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
{
- int result = 0;
- struct acpi_processor *pr = NULL;
- struct acpi_device *device = NULL;
- int tx = 0;
+ int result = 0;
+ struct acpi_processor *pr = NULL;
+ struct acpi_device *device = NULL;
+ int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
if ((type < ACPI_PROCESSOR_LIMIT_NONE)
- || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
+ || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
return_VALUE(-EINVAL);
result = acpi_bus_get_device(handle, &device);
if (result)
return_VALUE(result);
- pr = (struct acpi_processor *) acpi_driver_data(device);
+ pr = (struct acpi_processor *)acpi_driver_data(device);
if (!pr)
return_VALUE(-ENODEV);
@@ -250,12 +244,12 @@ acpi_processor_set_thermal_limit (
goto end;
else if (result == -ERANGE)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At maximum performance state\n"));
+ "At maximum performance state\n"));
if (pr->flags.throttling) {
if (tx == (pr->throttling.state_count - 1))
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At maximum throttling state\n"));
+ "At maximum throttling state\n"));
else
tx++;
}
@@ -267,7 +261,7 @@ acpi_processor_set_thermal_limit (
if (pr->flags.throttling) {
if (tx == 0)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At minimum throttling state\n"));
+ "At minimum throttling state\n"));
else {
tx--;
goto end;
@@ -277,12 +271,12 @@ acpi_processor_set_thermal_limit (
result = acpi_thermal_cpufreq_decrease(pr->id);
if (result == -ERANGE)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "At minimum performance state\n"));
+ "At minimum performance state\n"));
break;
}
-end:
+ end:
if (pr->flags.throttling) {
pr->limit.thermal.px = 0;
pr->limit.thermal.tx = tx;
@@ -293,18 +287,14 @@ end:
"Unable to set thermal limit\n"));
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
- pr->limit.thermal.px,
- pr->limit.thermal.tx));
+ pr->limit.thermal.px, pr->limit.thermal.tx));
} else
result = 0;
return_VALUE(result);
}
-
-int
-acpi_processor_get_limit_info (
- struct acpi_processor *pr)
+int acpi_processor_get_limit_info(struct acpi_processor *pr)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
@@ -317,12 +307,11 @@ acpi_processor_get_limit_info (
return_VALUE(0);
}
-
/* /proc interface */
static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show");
@@ -335,34 +324,32 @@ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "active limit: P%d:T%d\n"
- "user limit: P%d:T%d\n"
- "thermal limit: P%d:T%d\n",
- pr->limit.state.px, pr->limit.state.tx,
- pr->limit.user.px, pr->limit.user.tx,
- pr->limit.thermal.px, pr->limit.thermal.tx);
+ "user limit: P%d:T%d\n"
+ "thermal limit: P%d:T%d\n",
+ pr->limit.state.px, pr->limit.state.tx,
+ pr->limit.user.px, pr->limit.user.tx,
+ pr->limit.thermal.px, pr->limit.thermal.tx);
-end:
+ end:
return_VALUE(0);
}
static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_limit_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-ssize_t acpi_processor_write_limit (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+ssize_t acpi_processor_write_limit(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
- char limit_string[25] = {'\0'};
- int px = 0;
- int tx = 0;
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ char limit_string[25] = { '\0' };
+ int px = 0;
+ int tx = 0;
ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
@@ -396,11 +383,9 @@ ssize_t acpi_processor_write_limit (
return_VALUE(count);
}
-
struct file_operations acpi_processor_limit_fops = {
- .open = acpi_processor_limit_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_limit_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index be9f569d39d3..74a52d4e79ae 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -43,21 +43,17 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME ("acpi_processor")
-
+ACPI_MODULE_NAME("acpi_processor")
/* --------------------------------------------------------------------------
Throttling Control
-------------------------------------------------------------------------- */
-
-static int
-acpi_processor_get_throttling (
- struct acpi_processor *pr)
+static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
- int state = 0;
- u32 value = 0;
- u32 duty_mask = 0;
- u32 duty_value = 0;
+ int state = 0;
+ u32 value = 0;
+ u32 duty_mask = 0;
+ u32 duty_value = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_throttling");
@@ -86,7 +82,7 @@ acpi_processor_get_throttling (
duty_value >>= pr->throttling.duty_offset;
if (duty_value)
- state = pr->throttling.state_count-duty_value;
+ state = pr->throttling.state_count - duty_value;
}
pr->throttling.state = state;
@@ -94,20 +90,17 @@ acpi_processor_get_throttling (
local_irq_enable();
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling state is T%d (%d%% throttling applied)\n",
- state, pr->throttling.states[state].performance));
+ "Throttling state is T%d (%d%% throttling applied)\n",
+ state, pr->throttling.states[state].performance));
return_VALUE(0);
}
-
-int acpi_processor_set_throttling (
- struct acpi_processor *pr,
- int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
- u32 value = 0;
- u32 duty_mask = 0;
- u32 duty_value = 0;
+ u32 value = 0;
+ u32 duty_mask = 0;
+ u32 duty_value = 0;
ACPI_FUNCTION_TRACE("acpi_processor_set_throttling");
@@ -168,28 +161,26 @@ int acpi_processor_set_throttling (
local_irq_enable();
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling state set to T%d (%d%%)\n", state,
- (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
+ "Throttling state set to T%d (%d%%)\n", state,
+ (pr->throttling.states[state].performance ? pr->
+ throttling.states[state].performance / 10 : 0)));
return_VALUE(0);
}
-
-int
-acpi_processor_get_throttling_info (
- struct acpi_processor *pr)
+int acpi_processor_get_throttling_info(struct acpi_processor *pr)
{
- int result = 0;
- int step = 0;
- int i = 0;
+ int result = 0;
+ int step = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_throttling_info");
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
- pr->throttling.address,
- pr->throttling.duty_offset,
- pr->throttling.duty_width));
+ "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
+ pr->throttling.address,
+ pr->throttling.duty_offset,
+ pr->throttling.duty_width));
if (!pr)
return_VALUE(-EINVAL);
@@ -199,14 +190,12 @@ acpi_processor_get_throttling_info (
if (!pr->throttling.address) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
return_VALUE(0);
- }
- else if (!pr->throttling.duty_width) {
+ } else if (!pr->throttling.duty_width) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
return_VALUE(0);
}
/* TBD: Support duty_cycle values that span bit 4. */
- else if ((pr->throttling.duty_offset
- + pr->throttling.duty_width) > 4) {
+ else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n"));
return_VALUE(0);
}
@@ -218,7 +207,7 @@ acpi_processor_get_throttling_info (
*/
if (errata.piix4.throttle) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling not supported on PIIX4 A- or B-step\n"));
+ "Throttling not supported on PIIX4 A- or B-step\n"));
return_VALUE(0);
}
@@ -232,13 +221,13 @@ acpi_processor_get_throttling_info (
step = (1000 / pr->throttling.state_count);
- for (i=0; i<pr->throttling.state_count; i++) {
+ for (i = 0; i < pr->throttling.state_count; i++) {
pr->throttling.states[i].performance = step * i;
pr->throttling.states[i].power = step * i;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
- pr->throttling.state_count));
+ pr->throttling.state_count));
pr->flags.throttling = 1;
@@ -253,28 +242,29 @@ acpi_processor_get_throttling_info (
goto end;
if (pr->throttling.state) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n",
- pr->throttling.state));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Disabling throttling (was T%d)\n",
+ pr->throttling.state));
result = acpi_processor_set_throttling(pr, 0);
if (result)
goto end;
}
-end:
+ end:
if (result)
pr->flags.throttling = 0;
return_VALUE(result);
}
-
/* proc interface */
-static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset)
+static int acpi_processor_throttling_seq_show(struct seq_file *seq,
+ void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- int i = 0;
- int result = 0;
+ struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ int i = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_processor_throttling_seq_show");
@@ -289,41 +279,41 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset
result = acpi_processor_get_throttling(pr);
if (result) {
- seq_puts(seq, "Could not determine current throttling state.\n");
+ seq_puts(seq,
+ "Could not determine current throttling state.\n");
goto end;
}
seq_printf(seq, "state count: %d\n"
- "active state: T%d\n",
- pr->throttling.state_count,
- pr->throttling.state);
+ "active state: T%d\n",
+ pr->throttling.state_count, pr->throttling.state);
seq_puts(seq, "states:\n");
for (i = 0; i < pr->throttling.state_count; i++)
seq_printf(seq, " %cT%d: %02d%%\n",
- (i == pr->throttling.state?'*':' '), i,
- (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
+ (i == pr->throttling.state ? '*' : ' '), i,
+ (pr->throttling.states[i].performance ? pr->
+ throttling.states[i].performance / 10 : 0));
-end:
+ end:
return_VALUE(0);
}
-static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_throttling_open_fs(struct inode *inode,
+ struct file *file)
{
return single_open(file, acpi_processor_throttling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
-ssize_t acpi_processor_write_throttling (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+ssize_t acpi_processor_write_throttling(struct file * file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
- char state_string[12] = {'\0'};
+ int result = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ char state_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_processor_write_throttling");
@@ -336,7 +326,8 @@ ssize_t acpi_processor_write_throttling (
state_string[count] = '\0';
result = acpi_processor_set_throttling(pr,
- simple_strtoul(state_string, NULL, 0));
+ simple_strtoul(state_string,
+ NULL, 0));
if (result)
return_VALUE(result);
@@ -344,8 +335,8 @@ ssize_t acpi_processor_write_throttling (
}
struct file_operations acpi_processor_throttling_fops = {
- .open = acpi_processor_throttling_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_processor_throttling_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index 55d264771c48..23b54baa0cb2 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -41,13 +41,185 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsaddr")
+ACPI_MODULE_NAME("rsaddr")
+
+/* Local prototypes */
+static void
+acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags);
+
+static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource);
+
+static void
+acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags);
+
+static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_decode_general_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ * Flags - Actual flag byte
+ *
+ * RETURN: Decoded flag bits in resource struct
+ *
+ * DESCRIPTION: Decode a general flag byte to an address resource struct
+ *
+ ******************************************************************************/
+
+static void
+acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /* Producer / Consumer - flag bit[0] */
+
+ resource->address.producer_consumer = (u32) (flags & 0x01);
+
+ /* Decode (_DEC) - flag bit[1] */
+ resource->address.decode = (u32) ((flags >> 1) & 0x01);
+
+ /* Min Address Fixed (_MIF) - flag bit[2] */
+
+ resource->address.min_address_fixed = (u32) ((flags >> 2) & 0x01);
+
+ /* Max Address Fixed (_MAF) - flag bit[3] */
+
+ resource->address.max_address_fixed = (u32) ((flags >> 3) & 0x01);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_encode_general_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ *
+ * RETURN: Encoded general flag byte
+ *
+ * DESCRIPTION: Construct a general flag byte from an address resource struct
+ *
+ ******************************************************************************/
+
+static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource)
+{
+ u8 flags;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Producer / Consumer - flag bit[0] */
+
+ flags = (u8) (resource->address.producer_consumer & 0x01);
+
+ /* Decode (_DEC) - flag bit[1] */
+
+ flags |= (u8) ((resource->address.decode & 0x01) << 1);
+
+ /* Min Address Fixed (_MIF) - flag bit[2] */
+
+ flags |= (u8) ((resource->address.min_address_fixed & 0x01) << 2);
+
+ /* Max Address Fixed (_MAF) - flag bit[3] */
+
+ flags |= (u8) ((resource->address.max_address_fixed & 0x01) << 3);
+
+ return (flags);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_decode_specific_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ * Flags - Actual flag byte
+ *
+ * RETURN: Decoded flag bits in attribute struct
+ *
+ * DESCRIPTION: Decode a type-specific flag byte to an attribute struct.
+ * Type-specific flags are only defined for the Memory and IO
+ * resource types.
+ *
+ ******************************************************************************/
+
+static void
+acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
+ /* Write Status (_RW) - flag bit[0] */
+
+ resource->address.attribute.memory.read_write_attribute =
+ (u16) (flags & 0x01);
+
+ /* Memory Attributes (_MEM) - flag bits[2:1] */
+
+ resource->address.attribute.memory.cache_attribute =
+ (u16) ((flags >> 1) & 0x03);
+ } else if (resource->address.resource_type == ACPI_IO_RANGE) {
+ /* Ranges (_RNG) - flag bits[1:0] */
+
+ resource->address.attribute.io.range_attribute =
+ (u16) (flags & 0x03);
+
+ /* Translations (_TTP and _TRS) - flag bits[5:4] */
+
+ resource->address.attribute.io.translation_attribute =
+ (u16) ((flags >> 4) & 0x03);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_rs_encode_specific_flags
+ *
+ * PARAMETERS: Resource - Address resource data struct
+ *
+ * RETURN: Encoded type-specific flag byte
+ *
+ * DESCRIPTION: Construct a type-specific flag byte from an attribute struct.
+ * Type-specific flags are only defined for the Memory and IO
+ * resource types.
+ *
+ ******************************************************************************/
+
+static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource)
+{
+ u8 flags = 0;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (resource->address.resource_type == ACPI_MEMORY_RANGE) {
+ /* Write Status (_RW) - flag bit[0] */
+
+ flags = (u8)
+ (resource->address.attribute.memory.
+ read_write_attribute & 0x01);
+
+ /* Memory Attributes (_MEM) - flag bits[2:1] */
+
+ flags |= (u8)
+ ((resource->address.attribute.memory.
+ cache_attribute & 0x03) << 1);
+ } else if (resource->address.resource_type == ACPI_IO_RANGE) {
+ /* Ranges (_RNG) - flag bits[1:0] */
+
+ flags = (u8)
+ (resource->address.attribute.io.range_attribute & 0x03);
+
+ /* Translations (_TTP and _TRS) - flag bits[5:4] */
+
+ flags |= (u8)
+ ((resource->address.attribute.io.
+ translation_attribute & 0x03) << 4);
+ }
+
+ return (flags);
+}
/*******************************************************************************
*
@@ -71,34 +243,30 @@
******************************************************************************/
acpi_status
-acpi_rs_address16_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address16_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u32 index;
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_address16);
-
+ u32 index;
+ u16 temp16;
+ u8 temp8;
+ u8 *temp_ptr;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16);
- ACPI_FUNCTION_TRACE ("rs_address16_resource");
+ ACPI_FUNCTION_TRACE("rs_address16_resource");
-
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 13) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -112,7 +280,7 @@ acpi_rs_address16_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address16.resource_type = temp8;
@@ -120,73 +288,41 @@ acpi_rs_address16_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address16.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address16.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) {
- output_struct->data.address16.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
- output_struct->data.address16.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
- output_struct->data.address16.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address16.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == Address16.Data->resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
/* Get Granularity (Bytes 6-7) */
buffer += 1;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer);
/* Get min_address_range (Bytes 8-9) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 10-11) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 12-13) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset,
- buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 14-15) */
buffer += 2;
- ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer);
+ ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length,
+ buffer);
/* Resource Source Index (if present) */
@@ -205,8 +341,8 @@ acpi_rs_address16_resource (
if (*bytes_consumed > (16 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
- output_struct->data.address16.resource_source.index = (u32) temp8;
+ output_struct->data.address16.resource_source.index =
+ (u32) * buffer;
/* Point to the String */
@@ -215,28 +351,27 @@ acpi_rs_address16_resource (
/* Point the String pointer to the end of this structure */
output_struct->data.address16.resource_source.string_ptr =
- (char *)((u8 * )output_struct + struct_size);
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address16.resource_source.string_ptr;
+ output_struct->data.address16.resource_source.string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
-
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
- /* Add the terminating null */
-
- *temp_ptr = 0x00;
+ /* Add the terminating null and set the string length */
- output_struct->data.address16.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address16.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -244,10 +379,9 @@ acpi_rs_address16_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address16.resource_source.index = 0x00;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.address16.resource_source.index = 0;
output_struct->data.address16.resource_source.string_length = 0;
output_struct->data.address16.resource_source.string_ptr = NULL;
}
@@ -259,10 +393,9 @@ acpi_rs_address16_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address16_stream
@@ -280,24 +413,18 @@ acpi_rs_address16_resource (
******************************************************************************/
acpi_status
-acpi_rs_address16_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address16_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 *length_field;
- u8 temp8;
- char *temp_pointer = NULL;
- acpi_size actual_bytes;
-
-
- ACPI_FUNCTION_TRACE ("rs_address16_stream");
+ u8 *buffer = *output_buffer;
+ u8 *length_field;
+ acpi_size actual_bytes;
+ ACPI_FUNCTION_TRACE("rs_address16_stream");
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x88;
+ *buffer = ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE;
buffer += 1;
/* Save a pointer to the Length field - to be filled in later */
@@ -307,98 +434,74 @@ acpi_rs_address16_stream (
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address16.resource_type & 0x03);
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address16.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01);
-
- temp8 |= (linked_list->data.address16.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) {
- temp8 = (u8)
- (linked_list->data.address16.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address16.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
- temp8 = (u8)
- (linked_list->data.address16.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address16.attribute.io.translation_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity);
buffer += 2;
/* Set the address range minimum */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.min_address_range);
buffer += 2;
/* Set the address range maximum */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.max_address_range);
buffer += 2;
/* Set the address translation offset */
- ACPI_MOVE_32_TO_16 (buffer,
- &linked_list->data.address16.address_translation_offset);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.address16.
+ address_translation_offset);
buffer += 2;
/* Set the address length */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length);
buffer += 2;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address16.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address16.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address16.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address16.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
- /* Copy the string */
+ /* Copy the resource_source string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address16.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address16.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address16.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address16.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer);
+ actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer);
*bytes_consumed = actual_bytes;
/*
@@ -406,11 +509,10 @@ acpi_rs_address16_stream (
* minus the header size (3 bytes)
*/
actual_bytes -= 3;
- ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address32_resource
@@ -433,36 +535,30 @@ acpi_rs_address16_stream (
******************************************************************************/
acpi_status
-acpi_rs_address32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer;
- struct acpi_resource *output_struct= (void *) *output_buffer;
- u16 temp16;
- u8 temp8;
- u8 *temp_ptr;
- acpi_size struct_size;
- u32 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_address32_resource");
+ u16 temp16;
+ u8 temp8;
+ u8 *temp_ptr;
+ u32 index;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32);
+ ACPI_FUNCTION_TRACE("rs_address32_resource");
- buffer = byte_stream_buffer;
- struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32);
-
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 23) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -476,7 +572,7 @@ acpi_rs_address32_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address32.resource_type = temp8;
@@ -484,74 +580,41 @@ acpi_rs_address32_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address32.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address32.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) {
- output_struct->data.address32.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
-
- output_struct->data.address32.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
- output_struct->data.address32.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address32.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
/* Get Granularity (Bytes 6-9) */
buffer += 1;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer);
/* Get min_address_range (Bytes 10-13) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 14-17) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 18-21) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset,
- buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 22-25) */
buffer += 4;
- ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length,
+ buffer);
/* Resource Source Index (if present) */
@@ -568,9 +631,8 @@ acpi_rs_address32_resource (
if (*bytes_consumed > (26 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
output_struct->data.address32.resource_source.index =
- (u32) temp8;
+ (u32) * buffer;
/* Point to the String */
@@ -579,26 +641,27 @@ acpi_rs_address32_resource (
/* Point the String pointer to the end of this structure */
output_struct->data.address32.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address32.resource_source.string_ptr;
+ output_struct->data.address32.resource_source.string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
- /* Add the terminating null */
+ /* Add the terminating null and set the string length */
- *temp_ptr = 0x00;
- output_struct->data.address32.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address32.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -606,10 +669,9 @@ acpi_rs_address32_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address32.resource_source.index = 0x00;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.address32.resource_source.index = 0;
output_struct->data.address32.resource_source.string_length = 0;
output_struct->data.address32.resource_source.string_ptr = NULL;
}
@@ -621,10 +683,9 @@ acpi_rs_address32_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address32_stream
@@ -642,136 +703,105 @@ acpi_rs_address32_resource (
******************************************************************************/
acpi_status
-acpi_rs_address32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer;
- u16 *length_field;
- u8 temp8;
- char *temp_pointer;
-
-
- ACPI_FUNCTION_TRACE ("rs_address32_stream");
+ u8 *buffer;
+ u16 *length_field;
+ ACPI_FUNCTION_TRACE("rs_address32_stream");
buffer = *output_buffer;
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x87;
+ *buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address32.resource_type & 0x03);
-
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address32.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01);
- temp8 |= (linked_list->data.address32.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) {
- temp8 = (u8)
- (linked_list->data.address32.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address32.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
- temp8 = (u8)
- (linked_list->data.address32.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address32.attribute.io.translation_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity);
buffer += 4;
/* Set the address range minimum */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.min_address_range);
buffer += 4;
/* Set the address range maximum */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.max_address_range);
buffer += 4;
/* Set the address translation offset */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.address32.address_translation_offset);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.address32.
+ address_translation_offset);
buffer += 4;
/* Set the address length */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length);
buffer += 4;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address32.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address32.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address32.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address32.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
- /* Copy the string */
+ /* Copy the resource_source string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address32.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address32.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address32.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address32.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
- * minus the header size (3 bytes)
+ * minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address64_resource
@@ -794,38 +824,35 @@ acpi_rs_address32_stream (
******************************************************************************/
acpi_status
-acpi_rs_address64_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_address64_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16;
- u8 temp8;
- u8 resource_type;
- u8 *temp_ptr;
- acpi_size struct_size;
- u32 index;
-
+ u16 temp16;
+ u8 temp8;
+ u8 resource_type;
+ u8 *temp_ptr;
+ u32 index;
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64);
- ACPI_FUNCTION_TRACE ("rs_address64_resource");
+ ACPI_FUNCTION_TRACE("rs_address64_resource");
+ /* Get the Descriptor Type */
- buffer = byte_stream_buffer;
- struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
resource_type = *buffer;
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 43) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -839,7 +866,7 @@ acpi_rs_address64_resource (
/* Values 0-2 and 0xC0-0xFF are valid */
if ((temp8 > 2) && (temp8 < 0xC0)) {
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
output_struct->data.address64.resource_type = temp8;
@@ -847,48 +874,12 @@ acpi_rs_address64_resource (
/* Get the General Flags (Byte4) */
buffer += 1;
- temp8 = *buffer;
-
- /* Producer / Consumer */
-
- output_struct->data.address64.producer_consumer = temp8 & 0x01;
-
- /* Decode */
-
- output_struct->data.address64.decode = (temp8 >> 1) & 0x01;
-
- /* Min Address Fixed */
-
- output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01;
-
- /* Max Address Fixed */
-
- output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01;
+ acpi_rs_decode_general_flags(&output_struct->data, *buffer);
/* Get the Type Specific Flags (Byte5) */
buffer += 1;
- temp8 = *buffer;
-
- if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) {
- output_struct->data.address64.attribute.memory.read_write_attribute =
- (u16) (temp8 & 0x01);
-
- output_struct->data.address64.attribute.memory.cache_attribute =
- (u16) ((temp8 >> 1) & 0x03);
- }
- else {
- if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
- output_struct->data.address64.attribute.io.range_attribute =
- (u16) (temp8 & 0x03);
- output_struct->data.address64.attribute.io.translation_attribute =
- (u16) ((temp8 >> 4) & 0x03);
- }
- else {
- /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */
- /* Nothing needs to be filled in */
- }
- }
+ acpi_rs_decode_specific_flags(&output_struct->data, *buffer);
if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
/* Move past revision_id and Reserved byte */
@@ -899,30 +890,33 @@ acpi_rs_address64_resource (
/* Get Granularity (Bytes 6-13) or (Bytes 8-15) */
buffer += 1;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer);
/* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range,
+ buffer);
/* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range,
+ buffer);
/* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset,
- buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.
+ address_translation_offset, buffer);
/* Get address_length (Bytes 38-45) or (Bytes 40-47) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length,
+ buffer);
- output_struct->data.address64.resource_source.index = 0x00;
+ output_struct->data.address64.resource_source.index = 0;
output_struct->data.address64.resource_source.string_length = 0;
output_struct->data.address64.resource_source.string_ptr = NULL;
@@ -930,11 +924,9 @@ acpi_rs_address64_resource (
/* Get type_specific_attribute (Bytes 48-55) */
buffer += 8;
- ACPI_MOVE_64_TO_64 (
- &output_struct->data.address64.type_specific_attributes,
- buffer);
- }
- else {
+ ACPI_MOVE_64_TO_64(&output_struct->data.address64.
+ type_specific_attributes, buffer);
+ } else {
output_struct->data.address64.type_specific_attributes = 0;
/* Resource Source Index (if present) */
@@ -954,9 +946,8 @@ acpi_rs_address64_resource (
if (*bytes_consumed > (46 + 1)) {
/* Dereference the Index */
- temp8 = *buffer;
output_struct->data.address64.resource_source.index =
- (u32) temp8;
+ (u32) * buffer;
/* Point to the String */
@@ -964,29 +955,31 @@ acpi_rs_address64_resource (
/* Point the String pointer to the end of this structure */
- output_struct->data.address64.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ output_struct->data.address64.resource_source.
+ string_ptr =
+ (char *)((u8 *) output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.address64.resource_source.string_ptr;
+ output_struct->data.address64.resource_source.
+ string_ptr;
- /* Copy the string into the buffer */
+ /* Copy the resource_source string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
- temp_ptr += 1;
- buffer += 1;
- index += 1;
+ temp_ptr++;
+ buffer++;
+ index++;
}
/*
- * Add the terminating null
+ * Add the terminating null and set the string length
*/
- *temp_ptr = 0x00;
- output_struct->data.address64.resource_source.string_length =
- index + 1;
+ *temp_ptr = 0;
+ output_struct->data.address64.resource_source.
+ string_length = index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -994,7 +987,7 @@ acpi_rs_address64_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
}
}
@@ -1005,10 +998,9 @@ acpi_rs_address64_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_address64_stream
@@ -1026,132 +1018,101 @@ acpi_rs_address64_resource (
******************************************************************************/
acpi_status
-acpi_rs_address64_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_address64_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer;
- u16 *length_field;
- u8 temp8;
- char *temp_pointer;
-
-
- ACPI_FUNCTION_TRACE ("rs_address64_stream");
+ u8 *buffer;
+ u16 *length_field;
+ ACPI_FUNCTION_TRACE("rs_address64_stream");
buffer = *output_buffer;
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x8A;
+ *buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Resource Type (Memory, Io, bus_number) */
- temp8 = (u8) (linked_list->data.address64.resource_type & 0x03);
-
- *buffer = temp8;
+ *buffer = (u8) (linked_list->data.address64.resource_type & 0x03);
buffer += 1;
/* Set the general flags */
- temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01);
- temp8 |= (linked_list->data.address64.decode & 0x01) << 1;
- temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2;
- temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3;
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_general_flags(&linked_list->data);
buffer += 1;
/* Set the type specific flags */
- temp8 = 0;
-
- if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) {
- temp8 = (u8)
- (linked_list->data.address64.attribute.memory.read_write_attribute &
- 0x01);
-
- temp8 |=
- (linked_list->data.address64.attribute.memory.cache_attribute &
- 0x03) << 1;
- }
- else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
- temp8 = (u8)
- (linked_list->data.address64.attribute.io.range_attribute &
- 0x03);
- temp8 |=
- (linked_list->data.address64.attribute.io.range_attribute &
- 0x03) << 4;
- }
-
- *buffer = temp8;
+ *buffer = acpi_rs_encode_specific_flags(&linked_list->data);
buffer += 1;
/* Set the address space granularity */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity);
+ ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity);
buffer += 8;
/* Set the address range minimum */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.min_address_range);
buffer += 8;
/* Set the address range maximum */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.max_address_range);
buffer += 8;
/* Set the address translation offset */
- ACPI_MOVE_64_TO_64 (buffer,
- &linked_list->data.address64.address_translation_offset);
+ ACPI_MOVE_64_TO_64(buffer,
+ &linked_list->data.address64.
+ address_translation_offset);
buffer += 8;
/* Set the address length */
- ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length);
+ ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length);
buffer += 8;
/* Resource Source Index and Resource Source are optional */
- if (0 != linked_list->data.address64.resource_source.string_length) {
- temp8 = (u8) linked_list->data.address64.resource_source.index;
-
- *buffer = temp8;
+ if (linked_list->data.address64.resource_source.string_length) {
+ *buffer =
+ (u8) linked_list->data.address64.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
+ /* Copy the resource_source string */
- /* Copy the string */
-
- ACPI_STRCPY (temp_pointer,
- linked_list->data.address64.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.address64.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size)(ACPI_STRLEN (
- linked_list->data.address64.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.address64.resource_source.
+ string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
* minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 98176f2fcb5d..378f58390fc1 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -41,15 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rscalc")
-
+ACPI_MODULE_NAME("rscalc")
/*******************************************************************************
*
@@ -66,19 +64,15 @@
* the resource data.
*
******************************************************************************/
-
acpi_status
-acpi_rs_get_byte_stream_length (
- struct acpi_resource *linked_list,
- acpi_size *size_needed)
+acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list,
+ acpi_size * size_needed)
{
- acpi_size byte_stream_size_needed = 0;
- acpi_size segment_size;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length");
+ acpi_size byte_stream_size_needed = 0;
+ acpi_size segment_size;
+ u8 done = FALSE;
+ ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
while (!done) {
/* Init the variable that will hold the size to add to the total. */
@@ -145,11 +139,11 @@ acpi_rs_get_byte_stream_length (
*/
if (linked_list->data.vendor_specific.length > 7) {
segment_size = 3;
- }
- else {
+ } else {
segment_size = 1;
}
- segment_size += linked_list->data.vendor_specific.length;
+ segment_size +=
+ linked_list->data.vendor_specific.length;
break;
case ACPI_RSTYPE_END_TAG:
@@ -194,9 +188,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 16;
- if (linked_list->data.address16.resource_source.string_ptr) {
+ if (linked_list->data.address16.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address16.resource_source.string_length;
+ linked_list->data.address16.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -211,9 +207,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 26;
- if (linked_list->data.address32.resource_source.string_ptr) {
+ if (linked_list->data.address32.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address32.resource_source.string_length;
+ linked_list->data.address32.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -227,9 +225,11 @@ acpi_rs_get_byte_stream_length (
*/
segment_size = 46;
- if (linked_list->data.address64.resource_source.string_ptr) {
+ if (linked_list->data.address64.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.address64.resource_source.string_length;
+ linked_list->data.address64.resource_source.
+ string_length;
segment_size++;
}
break;
@@ -244,11 +244,14 @@ acpi_rs_get_byte_stream_length (
* Resource Source + 1 for the null.
*/
segment_size = 9 + (((acpi_size)
- linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
+ linked_list->data.extended_irq.
+ number_of_interrupts - 1) * 4);
- if (linked_list->data.extended_irq.resource_source.string_ptr) {
+ if (linked_list->data.extended_irq.resource_source.
+ string_ptr) {
segment_size +=
- linked_list->data.extended_irq.resource_source.string_length;
+ linked_list->data.extended_irq.
+ resource_source.string_length;
segment_size++;
}
break;
@@ -257,9 +260,9 @@ acpi_rs_get_byte_stream_length (
/* If we get here, everything is out of sync, exit with error */
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
- } /* switch (linked_list->Id) */
+ } /* switch (linked_list->Id) */
/* Update the total */
@@ -267,17 +270,16 @@ acpi_rs_get_byte_stream_length (
/* Point to the next object */
- linked_list = ACPI_PTR_ADD (struct acpi_resource,
- linked_list, linked_list->length);
+ linked_list = ACPI_PTR_ADD(struct acpi_resource,
+ linked_list, linked_list->length);
}
/* This is the data the caller needs */
*size_needed = byte_stream_size_needed;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_list_length
@@ -297,32 +299,28 @@ acpi_rs_get_byte_stream_length (
******************************************************************************/
acpi_status
-acpi_rs_get_list_length (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- acpi_size *size_needed)
+acpi_rs_get_list_length(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, acpi_size * size_needed)
{
- u32 buffer_size = 0;
- u32 bytes_parsed = 0;
- u8 number_of_interrupts = 0;
- u8 number_of_channels = 0;
- u8 resource_type;
- u32 structure_size;
- u32 bytes_consumed;
- u8 *buffer;
- u8 temp8;
- u16 temp16;
- u8 index;
- u8 additional_bytes;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_list_length");
-
+ u32 buffer_size = 0;
+ u32 bytes_parsed = 0;
+ u8 number_of_interrupts = 0;
+ u8 number_of_channels = 0;
+ u8 resource_type;
+ u32 structure_size;
+ u32 bytes_consumed;
+ u8 *buffer;
+ u8 temp8;
+ u16 temp16;
+ u8 index;
+ u8 additional_bytes;
+
+ ACPI_FUNCTION_TRACE("rs_get_list_length");
while (bytes_parsed < byte_stream_buffer_length) {
/* The next byte in the stream is the resource type */
- resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
+ resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
switch (resource_type) {
case ACPI_RDESC_TYPE_MEMORY_24:
@@ -331,10 +329,10 @@ acpi_rs_get_list_length (
*/
bytes_consumed = 12;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
break;
-
case ACPI_RDESC_TYPE_LARGE_VENDOR:
/*
* Vendor Defined Resource
@@ -342,38 +340,39 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
/* Ensure a 32-bit boundary for the structure */
- temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
+ temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
- (temp16 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
+ (temp16 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_MEMORY_32:
/*
* 32-Bit Memory Range Resource
*/
bytes_consumed = 20;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
break;
-
case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
/*
* 32-Bit Fixed Memory Resource
*/
bytes_consumed = 12;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_fixed_mem32);
break;
-
case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
@@ -381,13 +380,14 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_address64);
break;
-
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
@@ -395,7 +395,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -409,20 +409,19 @@ acpi_rs_get_list_length (
*/
if (43 < temp16) {
temp8 = (u8) (temp16 - 44);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 64-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
/*
* 32-Bit Address Resource
@@ -430,7 +429,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -444,20 +443,19 @@ acpi_rs_get_list_length (
*/
if (23 < temp16) {
temp8 = (u8) (temp16 - 24);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
/*
* 16-Bit Address Resource
@@ -465,7 +463,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -479,20 +477,19 @@ acpi_rs_get_list_length (
*/
if (13 < temp16) {
temp8 = (u8) (temp16 - 14);
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)
+ + (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
/*
* Extended IRQ
@@ -500,7 +497,7 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
++buffer;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
bytes_consumed = temp16 + 3;
@@ -527,21 +524,20 @@ acpi_rs_get_list_length (
*/
if (9 + additional_bytes < temp16) {
temp8 = (u8) (temp16 - (9 + additional_bytes));
- }
- else {
+ } else {
temp8 = 0;
}
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
- (additional_bytes * sizeof (u8)) +
- (temp8 * sizeof (u8));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) +
+ (additional_bytes * sizeof(u8)) +
+ (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_IRQ_FORMAT:
/*
* IRQ Resource.
@@ -550,10 +546,9 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
temp8 = *buffer;
- if(temp8 & 0x01) {
+ if (temp8 & 0x01) {
bytes_consumed = 4;
- }
- else {
+ } else {
bytes_consumed = 3;
}
@@ -563,7 +558,7 @@ acpi_rs_get_list_length (
/* Look at the number of bits set */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
for (index = 0; index < 16; index++) {
if (temp16 & 0x1) {
@@ -573,11 +568,11 @@ acpi_rs_get_list_length (
temp16 >>= 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
- (number_of_interrupts * sizeof (u32));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) +
+ (number_of_interrupts * sizeof(u32));
break;
-
case ACPI_RDESC_TYPE_DMA_FORMAT:
/*
* DMA Resource
@@ -593,19 +588,19 @@ acpi_rs_get_list_length (
temp8 = *buffer;
- for(index = 0; index < 8; index++) {
- if(temp8 & 0x1) {
+ for (index = 0; index < 8; index++) {
+ if (temp8 & 0x1) {
++number_of_channels;
}
temp8 >>= 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
- (number_of_channels * sizeof (u32));
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) +
+ (number_of_channels * sizeof(u32));
break;
-
case ACPI_RDESC_TYPE_START_DEPENDENT:
/*
* Start Dependent Functions Resource
@@ -614,17 +609,17 @@ acpi_rs_get_list_length (
buffer = byte_stream_buffer;
temp8 = *buffer;
- if(temp8 & 0x01) {
+ if (temp8 & 0x01) {
bytes_consumed = 2;
- }
- else {
+ } else {
bytes_consumed = 1;
}
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct
+ acpi_resource_start_dpf);
break;
-
case ACPI_RDESC_TYPE_END_DEPENDENT:
/*
* End Dependent Functions Resource
@@ -633,25 +628,24 @@ acpi_rs_get_list_length (
structure_size = ACPI_RESOURCE_LENGTH;
break;
-
case ACPI_RDESC_TYPE_IO_PORT:
/*
* IO Port Resource
*/
bytes_consumed = 8;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
break;
-
case ACPI_RDESC_TYPE_FIXED_IO_PORT:
/*
* Fixed IO Port Resource
*/
bytes_consumed = 4;
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
break;
-
case ACPI_RDESC_TYPE_SMALL_VENDOR:
/*
* Vendor Specific Resource
@@ -664,12 +658,12 @@ acpi_rs_get_list_length (
/* Ensure a 32-bit boundary for the structure */
- temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
- structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
- (temp8 * sizeof (u8));
+ temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8);
+ structure_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) +
+ (temp8 * sizeof(u8));
break;
-
case ACPI_RDESC_TYPE_END_TAG:
/*
* End Tag
@@ -679,18 +673,17 @@ acpi_rs_get_list_length (
byte_stream_buffer_length = bytes_parsed;
break;
-
default:
/*
* If we get here, everything is out of sync,
* exit with an error
*/
- return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
/* Update the return value and counter */
- buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
+ buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size);
bytes_parsed += bytes_consumed;
/* Set the byte stream to point to the next resource */
@@ -701,10 +694,9 @@ acpi_rs_get_list_length (
/* This is the data the caller needs */
*size_needed = buffer_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_pci_routing_table_length
@@ -723,22 +715,19 @@ acpi_rs_get_list_length (
******************************************************************************/
acpi_status
-acpi_rs_get_pci_routing_table_length (
- union acpi_operand_object *package_object,
- acpi_size *buffer_size_needed)
+acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
+ acpi_size * buffer_size_needed)
{
- u32 number_of_elements;
- acpi_size temp_size_needed = 0;
- union acpi_operand_object **top_object_list;
- u32 index;
- union acpi_operand_object *package_element;
- union acpi_operand_object **sub_object_list;
- u8 name_found;
- u32 table_index;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
+ u32 number_of_elements;
+ acpi_size temp_size_needed = 0;
+ union acpi_operand_object **top_object_list;
+ u32 index;
+ union acpi_operand_object *package_element;
+ union acpi_operand_object **sub_object_list;
+ u8 name_found;
+ u32 table_index;
+ ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length");
number_of_elements = package_object->package.count;
@@ -769,53 +758,51 @@ acpi_rs_get_pci_routing_table_length (
name_found = FALSE;
- for (table_index = 0; table_index < 4 && !name_found; table_index++) {
+ for (table_index = 0; table_index < 4 && !name_found;
+ table_index++) {
if ((ACPI_TYPE_STRING ==
- ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
-
- ((ACPI_TYPE_LOCAL_REFERENCE ==
- ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
-
- ((*sub_object_list)->reference.opcode ==
- AML_INT_NAMEPATH_OP))) {
+ ACPI_GET_OBJECT_TYPE(*sub_object_list))
+ ||
+ ((ACPI_TYPE_LOCAL_REFERENCE ==
+ ACPI_GET_OBJECT_TYPE(*sub_object_list))
+ && ((*sub_object_list)->reference.opcode ==
+ AML_INT_NAMEPATH_OP))) {
name_found = TRUE;
- }
- else {
+ } else {
/* Look at the next element */
sub_object_list++;
}
}
- temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
+ temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
/* Was a String type found? */
if (name_found) {
- if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
+ if (ACPI_GET_OBJECT_TYPE(*sub_object_list) ==
+ ACPI_TYPE_STRING) {
/*
* The length String.Length field does not include the
* terminating NULL, add 1
*/
temp_size_needed += ((acpi_size)
- (*sub_object_list)->string.length + 1);
+ (*sub_object_list)->string.
+ length + 1);
+ } else {
+ temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
}
- else {
- temp_size_needed += acpi_ns_get_pathname_length (
- (*sub_object_list)->reference.node);
- }
- }
- else {
+ } else {
/*
* If no name was found, then this is a NULL, which is
* translated as a u32 zero.
*/
- temp_size_needed += sizeof (u32);
+ temp_size_needed += sizeof(u32);
}
/* Round up the size since each element must be aligned */
- temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed);
+ temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed);
/* Point to the next union acpi_operand_object */
@@ -826,6 +813,7 @@ acpi_rs_get_pci_routing_table_length (
* Adding an extra element to the end of the list, essentially a
* NULL terminator
*/
- *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
- return_ACPI_STATUS (AE_OK);
+ *buffer_size_needed =
+ temp_size_needed + sizeof(struct acpi_pci_routing_table);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 8e0eae0d50bb..0911526b7ad8 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -41,15 +41,13 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#include <acpi/amlcode.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rscreate")
-
+ACPI_MODULE_NAME("rscreate")
/*******************************************************************************
*
@@ -68,24 +66,20 @@
* of device resources.
*
******************************************************************************/
-
acpi_status
-acpi_rs_create_resource_list (
- union acpi_operand_object *byte_stream_buffer,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer,
+ struct acpi_buffer *output_buffer)
{
- acpi_status status;
- u8 *byte_stream_start;
- acpi_size list_size_needed = 0;
- u32 byte_stream_buffer_length;
+ acpi_status status;
+ u8 *byte_stream_start;
+ acpi_size list_size_needed = 0;
+ u32 byte_stream_buffer_length;
+ ACPI_FUNCTION_TRACE("rs_create_resource_list");
- ACPI_FUNCTION_TRACE ("rs_create_resource_list");
-
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
- byte_stream_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_buffer = %p\n",
+ byte_stream_buffer));
/* Params already validated, so we don't re-validate here */
@@ -96,36 +90,39 @@ acpi_rs_create_resource_list (
* Pass the byte_stream_buffer into a module that can calculate
* the buffer size needed for the linked list
*/
- status = acpi_rs_get_list_length (byte_stream_start, byte_stream_buffer_length,
- &list_size_needed);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
- status, (u32) list_size_needed));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_get_list_length(byte_stream_start,
+ byte_stream_buffer_length,
+ &list_size_needed);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
+ status, (u32) list_size_needed));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, list_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(output_buffer, list_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Do the conversion */
- status = acpi_rs_byte_stream_to_list (byte_stream_start, byte_stream_buffer_length,
- output_buffer->pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_byte_stream_to_list(byte_stream_start,
+ byte_stream_buffer_length,
+ output_buffer->pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ output_buffer->pointer, (u32) output_buffer->length));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_create_pci_routing_table
@@ -148,44 +145,41 @@ acpi_rs_create_resource_list (
******************************************************************************/
acpi_status
-acpi_rs_create_pci_routing_table (
- union acpi_operand_object *package_object,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
+ struct acpi_buffer *output_buffer)
{
- u8 *buffer;
- union acpi_operand_object **top_object_list;
- union acpi_operand_object **sub_object_list;
- union acpi_operand_object *obj_desc;
- acpi_size buffer_size_needed = 0;
- u32 number_of_elements;
- u32 index;
- struct acpi_pci_routing_table *user_prt;
- struct acpi_namespace_node *node;
- acpi_status status;
- struct acpi_buffer path_buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_create_pci_routing_table");
-
+ u8 *buffer;
+ union acpi_operand_object **top_object_list;
+ union acpi_operand_object **sub_object_list;
+ union acpi_operand_object *obj_desc;
+ acpi_size buffer_size_needed = 0;
+ u32 number_of_elements;
+ u32 index;
+ struct acpi_pci_routing_table *user_prt;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ struct acpi_buffer path_buffer;
+
+ ACPI_FUNCTION_TRACE("rs_create_pci_routing_table");
/* Params already validated, so we don't re-validate here */
/* Get the required buffer length */
- status = acpi_rs_get_pci_routing_table_length (package_object,
- &buffer_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_pci_routing_table_length(package_object,
+ &buffer_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "buffer_size_needed = %X\n",
- (u32) buffer_size_needed));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n",
+ (u32) buffer_size_needed));
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, buffer_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -193,10 +187,10 @@ acpi_rs_create_pci_routing_table (
* should be a package that in turn contains an
* acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
*/
- top_object_list = package_object->package.elements;
+ top_object_list = package_object->package.elements;
number_of_elements = package_object->package.count;
- buffer = output_buffer->pointer;
- user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ buffer = output_buffer->pointer;
+ user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
/*
@@ -206,31 +200,34 @@ acpi_rs_create_pci_routing_table (
* be zero because we cleared the return buffer earlier
*/
buffer += user_prt->length;
- user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
/*
* Fill in the Length field with the information we have at this point.
* The minus four is to subtract the size of the u8 Source[4] member
* because it is added below.
*/
- user_prt->length = (sizeof (struct acpi_pci_routing_table) - 4);
+ user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
/* Each element of the top-level package must also be a package */
- if (ACPI_GET_OBJECT_TYPE (*top_object_list) != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X]) Need sub-package, found %s\n",
- index, acpi_ut_get_object_type_name (*top_object_list)));
- return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X]) Need sub-package, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (*top_object_list)));
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
/* Each sub-package must be of length 4 */
if ((*top_object_list)->package.count != 4) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X]) Need package of length 4, found length %d\n",
- index, (*top_object_list)->package.count));
- return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X]) Need package of length 4, found length %d\n",
+ index,
+ (*top_object_list)->package.count));
+ return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
}
/*
@@ -243,40 +240,43 @@ acpi_rs_create_pci_routing_table (
/* 1) First subobject: Dereference the PRT.Address */
obj_desc = sub_object_list[0];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->address = obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Address) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Address) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* 2) Second subobject: Dereference the PRT.Pin */
obj_desc = sub_object_list[1];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->pin = (u32) obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Pin) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Pin) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* 3) Third subobject: Dereference the PRT.source_name */
obj_desc = sub_object_list[2];
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need name, found reference op %X\n",
- index, obj_desc->reference.opcode));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Source) Need name, found reference op %X\n",
+ index,
+ obj_desc->reference.opcode));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
node = obj_desc->reference.node;
@@ -284,21 +284,23 @@ acpi_rs_create_pci_routing_table (
/* Use *remaining* length of the buffer as max for pathname */
path_buffer.length = output_buffer->length -
- (u32) ((u8 *) user_prt->source -
- (u8 *) output_buffer->pointer);
+ (u32) ((u8 *) user_prt->source -
+ (u8 *) output_buffer->pointer);
path_buffer.pointer = user_prt->source;
- status = acpi_ns_handle_to_pathname ((acpi_handle) node, &path_buffer);
+ status =
+ acpi_ns_handle_to_pathname((acpi_handle) node,
+ &path_buffer);
/* +1 to include null terminator */
- user_prt->length += (u32) ACPI_STRLEN (user_prt->source) + 1;
+ user_prt->length +=
+ (u32) ACPI_STRLEN(user_prt->source) + 1;
break;
-
case ACPI_TYPE_STRING:
- ACPI_STRCPY (user_prt->source, obj_desc->string.pointer);
+ ACPI_STRCPY(user_prt->source, obj_desc->string.pointer);
/*
* Add to the Length field the length of the string
@@ -307,7 +309,6 @@ acpi_rs_create_pci_routing_table (
user_prt->length += obj_desc->string.length + 1;
break;
-
case ACPI_TYPE_INTEGER:
/*
* If this is a number, then the Source Name is NULL, since the
@@ -315,33 +316,36 @@ acpi_rs_create_pci_routing_table (
*
* Add to the Length field the length of the u32 NULL
*/
- user_prt->length += sizeof (u32);
+ user_prt->length += sizeof(u32);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].Source) Need Ref/String/Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Now align the current length */
- user_prt->length = (u32) ACPI_ROUND_UP_to_64_bITS (user_prt->length);
+ user_prt->length =
+ (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length);
/* 4) Fourth subobject: Dereference the PRT.source_index */
obj_desc = sub_object_list[3];
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
user_prt->source_index = (u32) obj_desc->integer.value;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "(PRT[%X].source_index) Need Integer, found %s\n",
- index, acpi_ut_get_object_type_name (obj_desc)));
- return_ACPI_STATUS (AE_BAD_DATA);
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "(PRT[%X].source_index) Need Integer, found %s\n",
+ index,
+ acpi_ut_get_object_type_name
+ (obj_desc)));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Point to the next union acpi_operand_object in the top level package */
@@ -349,12 +353,11 @@ acpi_rs_create_pci_routing_table (
top_object_list++;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ output_buffer->pointer, (u32) output_buffer->length));
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_create_byte_stream
@@ -374,19 +377,16 @@ acpi_rs_create_pci_routing_table (
******************************************************************************/
acpi_status
-acpi_rs_create_byte_stream (
- struct acpi_resource *linked_list_buffer,
- struct acpi_buffer *output_buffer)
+acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer,
+ struct acpi_buffer *output_buffer)
{
- acpi_status status;
- acpi_size byte_stream_size_needed = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_create_byte_stream");
+ acpi_status status;
+ acpi_size byte_stream_size_needed = 0;
+ ACPI_FUNCTION_TRACE("rs_create_byte_stream");
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "linked_list_buffer = %p\n",
- linked_list_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
+ linked_list_buffer));
/*
* Params already validated, so we don't re-validate here
@@ -394,32 +394,35 @@ acpi_rs_create_byte_stream (
* Pass the linked_list_buffer into a module that calculates
* the buffer size needed for the byte stream.
*/
- status = acpi_rs_get_byte_stream_length (linked_list_buffer,
- &byte_stream_size_needed);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
- (u32) byte_stream_size_needed, acpi_format_exception (status)));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_byte_stream_length(linked_list_buffer,
+ &byte_stream_size_needed);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n",
+ (u32) byte_stream_size_needed,
+ acpi_format_exception(status)));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (output_buffer, byte_stream_size_needed);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_initialize_buffer(output_buffer, byte_stream_size_needed);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Do the conversion */
- status = acpi_rs_list_to_byte_stream (linked_list_buffer, byte_stream_size_needed,
- output_buffer->pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_rs_list_to_byte_stream(linked_list_buffer,
+ byte_stream_size_needed,
+ output_buffer->pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n",
- output_buffer->pointer, (u32) output_buffer->length));
- return_ACPI_STATUS (AE_OK);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ output_buffer->pointer, (u32) output_buffer->length));
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index 1935dab2ab51..75bd34d1783f 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -41,69 +41,40 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsdump")
+ACPI_MODULE_NAME("rsdump")
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/* Local prototypes */
+static void acpi_rs_dump_irq(union acpi_resource_data *data);
-static void
-acpi_rs_dump_irq (
- union acpi_resource_data *data);
-
-static void
-acpi_rs_dump_address16 (
- union acpi_resource_data *data);
-
-static void
-acpi_rs_dump_address32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address16(union acpi_resource_data *data);
-static void
-acpi_rs_dump_address64 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_dma (
- union acpi_resource_data *data);
+static void acpi_rs_dump_address64(union acpi_resource_data *data);
-static void
-acpi_rs_dump_io (
- union acpi_resource_data *data);
+static void acpi_rs_dump_dma(union acpi_resource_data *data);
-static void
-acpi_rs_dump_extended_irq (
- union acpi_resource_data *data);
+static void acpi_rs_dump_io(union acpi_resource_data *data);
-static void
-acpi_rs_dump_fixed_io (
- union acpi_resource_data *data);
+static void acpi_rs_dump_extended_irq(union acpi_resource_data *data);
-static void
-acpi_rs_dump_fixed_memory32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_fixed_io(union acpi_resource_data *data);
-static void
-acpi_rs_dump_memory24 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_memory32 (
- union acpi_resource_data *data);
+static void acpi_rs_dump_memory24(union acpi_resource_data *data);
-static void
-acpi_rs_dump_start_depend_fns (
- union acpi_resource_data *data);
+static void acpi_rs_dump_memory32(union acpi_resource_data *data);
-static void
-acpi_rs_dump_vendor_specific (
- union acpi_resource_data *data);
+static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data);
+static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data);
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_irq
@@ -116,39 +87,37 @@ acpi_rs_dump_vendor_specific (
*
******************************************************************************/
-static void
-acpi_rs_dump_irq (
- union acpi_resource_data *data)
+static void acpi_rs_dump_irq(union acpi_resource_data *data)
{
- struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("IRQ Resource\n");
+ acpi_os_printf("IRQ Resource\n");
- acpi_os_printf (" %s Triggered\n",
- ACPI_LEVEL_SENSITIVE == irq_data->edge_level ? "Level" : "Edge");
+ acpi_os_printf(" %s Triggered\n",
+ ACPI_LEVEL_SENSITIVE ==
+ irq_data->edge_level ? "Level" : "Edge");
- acpi_os_printf (" Active %s\n",
- ACPI_ACTIVE_LOW == irq_data->active_high_low ? "Low" : "High");
+ acpi_os_printf(" Active %s\n",
+ ACPI_ACTIVE_LOW ==
+ irq_data->active_high_low ? "Low" : "High");
- acpi_os_printf (" %s\n",
- ACPI_SHARED == irq_data->shared_exclusive ? "Shared" : "Exclusive");
+ acpi_os_printf(" %s\n",
+ ACPI_SHARED ==
+ irq_data->shared_exclusive ? "Shared" : "Exclusive");
- acpi_os_printf (" %X Interrupts ( ", irq_data->number_of_interrupts);
+ acpi_os_printf(" %X Interrupts ( ", irq_data->number_of_interrupts);
for (index = 0; index < irq_data->number_of_interrupts; index++) {
- acpi_os_printf ("%X ", irq_data->interrupts[index]);
+ acpi_os_printf("%X ", irq_data->interrupts[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_dma
@@ -161,75 +130,69 @@ acpi_rs_dump_irq (
*
******************************************************************************/
-static void
-acpi_rs_dump_dma (
- union acpi_resource_data *data)
+static void acpi_rs_dump_dma(union acpi_resource_data *data)
{
- struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("DMA Resource\n");
+ acpi_os_printf("DMA Resource\n");
switch (dma_data->type) {
case ACPI_COMPATIBILITY:
- acpi_os_printf (" Compatibility mode\n");
+ acpi_os_printf(" Compatibility mode\n");
break;
case ACPI_TYPE_A:
- acpi_os_printf (" Type A\n");
+ acpi_os_printf(" Type A\n");
break;
case ACPI_TYPE_B:
- acpi_os_printf (" Type B\n");
+ acpi_os_printf(" Type B\n");
break;
case ACPI_TYPE_F:
- acpi_os_printf (" Type F\n");
+ acpi_os_printf(" Type F\n");
break;
default:
- acpi_os_printf (" Invalid DMA type\n");
+ acpi_os_printf(" Invalid DMA type\n");
break;
}
- acpi_os_printf (" %sBus Master\n",
- ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
-
+ acpi_os_printf(" %sBus Master\n",
+ ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a ");
switch (dma_data->transfer) {
case ACPI_TRANSFER_8:
- acpi_os_printf (" 8-bit only transfer\n");
+ acpi_os_printf(" 8-bit only transfer\n");
break;
case ACPI_TRANSFER_8_16:
- acpi_os_printf (" 8 and 16-bit transfer\n");
+ acpi_os_printf(" 8 and 16-bit transfer\n");
break;
case ACPI_TRANSFER_16:
- acpi_os_printf (" 16 bit only transfer\n");
+ acpi_os_printf(" 16 bit only transfer\n");
break;
default:
- acpi_os_printf (" Invalid transfer preference\n");
+ acpi_os_printf(" Invalid transfer preference\n");
break;
}
- acpi_os_printf (" Number of Channels: %X ( ",
- dma_data->number_of_channels);
+ acpi_os_printf(" Number of Channels: %X ( ",
+ dma_data->number_of_channels);
for (index = 0; index < dma_data->number_of_channels; index++) {
- acpi_os_printf ("%X ", dma_data->channels[index]);
+ acpi_os_printf("%X ", dma_data->channels[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_start_depend_fns
@@ -242,58 +205,54 @@ acpi_rs_dump_dma (
*
******************************************************************************/
-static void
-acpi_rs_dump_start_depend_fns (
- union acpi_resource_data *data)
+static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data)
{
- struct acpi_resource_start_dpf *sdf_data = (struct acpi_resource_start_dpf *) data;
-
+ struct acpi_resource_start_dpf *sdf_data =
+ (struct acpi_resource_start_dpf *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- acpi_os_printf ("Start Dependent Functions Resource\n");
+ acpi_os_printf("Start Dependent Functions Resource\n");
switch (sdf_data->compatibility_priority) {
case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf (" Good configuration\n");
+ acpi_os_printf(" Good configuration\n");
break;
case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf (" Acceptable configuration\n");
+ acpi_os_printf(" Acceptable configuration\n");
break;
case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf (" Sub-optimal configuration\n");
+ acpi_os_printf(" Sub-optimal configuration\n");
break;
default:
- acpi_os_printf (" Invalid compatibility priority\n");
+ acpi_os_printf(" Invalid compatibility priority\n");
break;
}
- switch(sdf_data->performance_robustness) {
+ switch (sdf_data->performance_robustness) {
case ACPI_GOOD_CONFIGURATION:
- acpi_os_printf (" Good configuration\n");
+ acpi_os_printf(" Good configuration\n");
break;
case ACPI_ACCEPTABLE_CONFIGURATION:
- acpi_os_printf (" Acceptable configuration\n");
+ acpi_os_printf(" Acceptable configuration\n");
break;
case ACPI_SUB_OPTIMAL_CONFIGURATION:
- acpi_os_printf (" Sub-optimal configuration\n");
+ acpi_os_printf(" Sub-optimal configuration\n");
break;
default:
- acpi_os_printf (" Invalid performance robustness preference\n");
+ acpi_os_printf(" Invalid performance robustness preference\n");
break;
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_io
@@ -306,33 +265,30 @@ acpi_rs_dump_start_depend_fns (
*
******************************************************************************/
-static void
-acpi_rs_dump_io (
- union acpi_resource_data *data)
+static void acpi_rs_dump_io(union acpi_resource_data *data)
{
- struct acpi_resource_io *io_data = (struct acpi_resource_io *) data;
-
+ struct acpi_resource_io *io_data = (struct acpi_resource_io *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Io Resource\n");
- acpi_os_printf ("Io Resource\n");
+ acpi_os_printf(" %d bit decode\n",
+ ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
- acpi_os_printf (" %d bit decode\n",
- ACPI_DECODE_16 == io_data->io_decode ? 16 : 10);
+ acpi_os_printf(" Range minimum base: %08X\n",
+ io_data->min_base_address);
- acpi_os_printf (" Range minimum base: %08X\n", io_data->min_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ io_data->max_base_address);
- acpi_os_printf (" Range maximum base: %08X\n", io_data->max_base_address);
+ acpi_os_printf(" Alignment: %08X\n", io_data->alignment);
- acpi_os_printf (" Alignment: %08X\n", io_data->alignment);
-
- acpi_os_printf (" Range Length: %08X\n", io_data->range_length);
+ acpi_os_printf(" Range Length: %08X\n", io_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_fixed_io
@@ -345,25 +301,22 @@ acpi_rs_dump_io (
*
******************************************************************************/
-static void
-acpi_rs_dump_fixed_io (
- union acpi_resource_data *data)
+static void acpi_rs_dump_fixed_io(union acpi_resource_data *data)
{
- struct acpi_resource_fixed_io *fixed_io_data = (struct acpi_resource_fixed_io *) data;
-
+ struct acpi_resource_fixed_io *fixed_io_data =
+ (struct acpi_resource_fixed_io *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Fixed Io Resource\n");
+ acpi_os_printf(" Range base address: %08X",
+ fixed_io_data->base_address);
- acpi_os_printf ("Fixed Io Resource\n");
- acpi_os_printf (" Range base address: %08X", fixed_io_data->base_address);
-
- acpi_os_printf (" Range length: %08X", fixed_io_data->range_length);
+ acpi_os_printf(" Range length: %08X", fixed_io_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_vendor_specific
@@ -376,30 +329,26 @@ acpi_rs_dump_fixed_io (
*
******************************************************************************/
-static void
-acpi_rs_dump_vendor_specific (
- union acpi_resource_data *data)
+static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data)
{
- struct acpi_resource_vendor *vendor_data = (struct acpi_resource_vendor *) data;
- u16 index = 0;
-
+ struct acpi_resource_vendor *vendor_data =
+ (struct acpi_resource_vendor *)data;
+ u16 index = 0;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("Vendor Specific Resource\n");
- acpi_os_printf ("Vendor Specific Resource\n");
-
- acpi_os_printf (" Length: %08X\n", vendor_data->length);
+ acpi_os_printf(" Length: %08X\n", vendor_data->length);
for (index = 0; index < vendor_data->length; index++) {
- acpi_os_printf (" Byte %X: %08X\n",
- index, vendor_data->reserved[index]);
+ acpi_os_printf(" Byte %X: %08X\n",
+ index, vendor_data->reserved[index]);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_memory24
@@ -412,37 +361,33 @@ acpi_rs_dump_vendor_specific (
*
******************************************************************************/
-static void
-acpi_rs_dump_memory24 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_memory24(union acpi_resource_data *data)
{
- struct acpi_resource_mem24 *memory24_data = (struct acpi_resource_mem24 *) data;
-
+ struct acpi_resource_mem24 *memory24_data =
+ (struct acpi_resource_mem24 *)data;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ acpi_os_printf("24-Bit Memory Range Resource\n");
- acpi_os_printf ("24-Bit Memory Range Resource\n");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ memory24_data->read_write_attribute ?
+ "/Write" : " only");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory24_data->read_write_attribute ?
- "/Write" : " only");
+ acpi_os_printf(" Range minimum base: %08X\n",
+ memory24_data->min_base_address);
- acpi_os_printf (" Range minimum base: %08X\n",
- memory24_data->min_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ memory24_data->max_base_address);
- acpi_os_printf (" Range maximum base: %08X\n",
- memory24_data->max_base_address);
+ acpi_os_printf(" Alignment: %08X\n", memory24_data->alignment);
- acpi_os_printf (" Alignment: %08X\n", memory24_data->alignment);
-
- acpi_os_printf (" Range length: %08X\n", memory24_data->range_length);
+ acpi_os_printf(" Range length: %08X\n", memory24_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_memory32
@@ -455,37 +400,33 @@ acpi_rs_dump_memory24 (
*
******************************************************************************/
-static void
-acpi_rs_dump_memory32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_memory32(union acpi_resource_data *data)
{
- struct acpi_resource_mem32 *memory32_data = (struct acpi_resource_mem32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_mem32 *memory32_data =
+ (struct acpi_resource_mem32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Memory Range Resource\n");
+ acpi_os_printf("32-Bit Memory Range Resource\n");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- memory32_data->read_write_attribute ?
- "/Write" : " only");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ memory32_data->read_write_attribute ?
+ "/Write" : " only");
- acpi_os_printf (" Range minimum base: %08X\n",
- memory32_data->min_base_address);
+ acpi_os_printf(" Range minimum base: %08X\n",
+ memory32_data->min_base_address);
- acpi_os_printf (" Range maximum base: %08X\n",
- memory32_data->max_base_address);
+ acpi_os_printf(" Range maximum base: %08X\n",
+ memory32_data->max_base_address);
- acpi_os_printf (" Alignment: %08X\n", memory32_data->alignment);
+ acpi_os_printf(" Alignment: %08X\n", memory32_data->alignment);
- acpi_os_printf (" Range length: %08X\n", memory32_data->range_length);
+ acpi_os_printf(" Range length: %08X\n", memory32_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_fixed_memory32
@@ -498,33 +439,29 @@ acpi_rs_dump_memory32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_fixed_memory32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data)
{
- struct acpi_resource_fixed_mem32 *fixed_memory32_data =
- (struct acpi_resource_fixed_mem32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_fixed_mem32 *fixed_memory32_data =
+ (struct acpi_resource_fixed_mem32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Fixed Location Memory Range Resource\n");
+ acpi_os_printf("32-Bit Fixed Location Memory Range Resource\n");
- acpi_os_printf (" Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- fixed_memory32_data->read_write_attribute ? "/Write" : " Only");
+ acpi_os_printf(" Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ fixed_memory32_data->
+ read_write_attribute ? "/Write" : " Only");
- acpi_os_printf (" Range base address: %08X\n",
- fixed_memory32_data->range_base_address);
+ acpi_os_printf(" Range base address: %08X\n",
+ fixed_memory32_data->range_base_address);
- acpi_os_printf (" Range length: %08X\n",
- fixed_memory32_data->range_length);
+ acpi_os_printf(" Range length: %08X\n",
+ fixed_memory32_data->range_length);
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address16
@@ -537,134 +474,136 @@ acpi_rs_dump_fixed_memory32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address16 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address16(union acpi_resource_data *data)
{
- struct acpi_resource_address16 *address16_data = (struct acpi_resource_address16 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address16 *address16_data =
+ (struct acpi_resource_address16 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("16-Bit Address Space Resource\n");
- acpi_os_printf (" Resource Type: ");
+ acpi_os_printf("16-Bit Address Space Resource\n");
+ acpi_os_printf(" Resource Type: ");
switch (address16_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf ("Memory Range\n");
+ acpi_os_printf("Memory Range\n");
switch (address16_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address16_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address16_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf ("I/O Range\n");
+ acpi_os_printf("I/O Range\n");
switch (address16_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid range attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid range attribute\n");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address16_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address16_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf ("Bus Number Range\n");
+ acpi_os_printf("Bus Number Range\n");
break;
default:
- acpi_os_printf ("0x%2.2X\n", address16_data->resource_type);
+ acpi_os_printf("0x%2.2X\n", address16_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address16_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address16_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address16_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address16_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
- "" : "not");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ?
+ "" : "not");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
- "" : "not");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ?
+ "" : "not");
- acpi_os_printf (" Granularity: %08X\n",
- address16_data->granularity);
+ acpi_os_printf(" Granularity: %08X\n", address16_data->granularity);
- acpi_os_printf (" Address range min: %08X\n",
- address16_data->min_address_range);
+ acpi_os_printf(" Address range min: %08X\n",
+ address16_data->min_address_range);
- acpi_os_printf (" Address range max: %08X\n",
- address16_data->max_address_range);
+ acpi_os_printf(" Address range max: %08X\n",
+ address16_data->max_address_range);
- acpi_os_printf (" Address translation offset: %08X\n",
- address16_data->address_translation_offset);
+ acpi_os_printf(" Address translation offset: %08X\n",
+ address16_data->address_translation_offset);
- acpi_os_printf (" Address Length: %08X\n",
- address16_data->address_length);
+ acpi_os_printf(" Address Length: %08X\n",
+ address16_data->address_length);
if (0xFF != address16_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address16_data->resource_source.index);
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address16_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address16_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address16_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address32
@@ -677,134 +616,136 @@ acpi_rs_dump_address16 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address32 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address32(union acpi_resource_data *data)
{
- struct acpi_resource_address32 *address32_data = (struct acpi_resource_address32 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address32 *address32_data =
+ (struct acpi_resource_address32 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("32-Bit Address Space Resource\n");
+ acpi_os_printf("32-Bit Address Space Resource\n");
switch (address32_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf (" Resource Type: Memory Range\n");
+ acpi_os_printf(" Resource Type: Memory Range\n");
switch (address32_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address32_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address32_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf (" Resource Type: Io Range\n");
+ acpi_os_printf(" Resource Type: Io Range\n");
switch (address32_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid Range attribute");
+ acpi_os_printf
+ (" Type Specific: Invalid Range attribute");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address32_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address32_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf (" Resource Type: Bus Number Range\n");
+ acpi_os_printf(" Resource Type: Bus Number Range\n");
break;
default:
- acpi_os_printf (" Resource Type: 0x%2.2X\n",
- address32_data->resource_type);
+ acpi_os_printf(" Resource Type: 0x%2.2X\n",
+ address32_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address32_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address32_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address32_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address32_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Granularity: %08X\n",
- address32_data->granularity);
+ acpi_os_printf(" Granularity: %08X\n", address32_data->granularity);
- acpi_os_printf (" Address range min: %08X\n",
- address32_data->min_address_range);
+ acpi_os_printf(" Address range min: %08X\n",
+ address32_data->min_address_range);
- acpi_os_printf (" Address range max: %08X\n",
- address32_data->max_address_range);
+ acpi_os_printf(" Address range max: %08X\n",
+ address32_data->max_address_range);
- acpi_os_printf (" Address translation offset: %08X\n",
- address32_data->address_translation_offset);
+ acpi_os_printf(" Address translation offset: %08X\n",
+ address32_data->address_translation_offset);
- acpi_os_printf (" Address Length: %08X\n",
- address32_data->address_length);
+ acpi_os_printf(" Address Length: %08X\n",
+ address32_data->address_length);
- if(0xFF != address32_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address32_data->resource_source.index);
+ if (0xFF != address32_data->resource_source.index) {
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address32_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address32_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address32_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_address64
@@ -817,137 +758,142 @@ acpi_rs_dump_address32 (
*
******************************************************************************/
-static void
-acpi_rs_dump_address64 (
- union acpi_resource_data *data)
+static void acpi_rs_dump_address64(union acpi_resource_data *data)
{
- struct acpi_resource_address64 *address64_data = (struct acpi_resource_address64 *) data;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_address64 *address64_data =
+ (struct acpi_resource_address64 *)data;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("64-Bit Address Space Resource\n");
+ acpi_os_printf("64-Bit Address Space Resource\n");
switch (address64_data->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_os_printf (" Resource Type: Memory Range\n");
+ acpi_os_printf(" Resource Type: Memory Range\n");
switch (address64_data->attribute.memory.cache_attribute) {
case ACPI_NON_CACHEABLE_MEMORY:
- acpi_os_printf (" Type Specific: Noncacheable memory\n");
+ acpi_os_printf
+ (" Type Specific: Noncacheable memory\n");
break;
case ACPI_CACHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Cacheable memory\n");
+ acpi_os_printf(" Type Specific: Cacheable memory\n");
break;
case ACPI_WRITE_COMBINING_MEMORY:
- acpi_os_printf (" Type Specific: Write-combining memory\n");
+ acpi_os_printf
+ (" Type Specific: Write-combining memory\n");
break;
case ACPI_PREFETCHABLE_MEMORY:
- acpi_os_printf (" Type Specific: Prefetchable memory\n");
+ acpi_os_printf
+ (" Type Specific: Prefetchable memory\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid cache attribute\n");
+ acpi_os_printf
+ (" Type Specific: Invalid cache attribute\n");
break;
}
- acpi_os_printf (" Type Specific: Read%s\n",
- ACPI_READ_WRITE_MEMORY ==
- address64_data->attribute.memory.read_write_attribute ?
- "/Write" : " Only");
+ acpi_os_printf(" Type Specific: Read%s\n",
+ ACPI_READ_WRITE_MEMORY ==
+ address64_data->attribute.memory.
+ read_write_attribute ? "/Write" : " Only");
break;
case ACPI_IO_RANGE:
- acpi_os_printf (" Resource Type: Io Range\n");
+ acpi_os_printf(" Resource Type: Io Range\n");
switch (address64_data->attribute.io.range_attribute) {
case ACPI_NON_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: Non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: Non-ISA Io Addresses\n");
break;
case ACPI_ISA_ONLY_RANGES:
- acpi_os_printf (" Type Specific: ISA Io Addresses\n");
+ acpi_os_printf(" Type Specific: ISA Io Addresses\n");
break;
case ACPI_ENTIRE_RANGE:
- acpi_os_printf (" Type Specific: ISA and non-ISA Io Addresses\n");
+ acpi_os_printf
+ (" Type Specific: ISA and non-ISA Io Addresses\n");
break;
default:
- acpi_os_printf (" Type Specific: Invalid Range attribute");
+ acpi_os_printf
+ (" Type Specific: Invalid Range attribute");
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
- ACPI_SPARSE_TRANSLATION ==
- address64_data->attribute.io.translation_attribute ?
- "Sparse" : "Dense");
+ acpi_os_printf(" Type Specific: %s Translation\n",
+ ACPI_SPARSE_TRANSLATION ==
+ address64_data->attribute.io.
+ translation_attribute ? "Sparse" : "Dense");
break;
case ACPI_BUS_NUMBER_RANGE:
- acpi_os_printf (" Resource Type: Bus Number Range\n");
+ acpi_os_printf(" Resource Type: Bus Number Range\n");
break;
default:
- acpi_os_printf (" Resource Type: 0x%2.2X\n",
- address64_data->resource_type);
+ acpi_os_printf(" Resource Type: 0x%2.2X\n",
+ address64_data->resource_type);
break;
}
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == address64_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == address64_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s decode\n",
- ACPI_SUB_DECODE == address64_data->decode ?
- "Subtractive" : "Positive");
+ acpi_os_printf(" %s decode\n",
+ ACPI_SUB_DECODE == address64_data->decode ?
+ "Subtractive" : "Positive");
- acpi_os_printf (" Min address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Min address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Max address is %s fixed\n",
- ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
- "" : "not ");
+ acpi_os_printf(" Max address is %s fixed\n",
+ ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ?
+ "" : "not ");
- acpi_os_printf (" Granularity: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->granularity));
+ acpi_os_printf(" Granularity: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->granularity));
- acpi_os_printf (" Address range min: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->min_address_range));
+ acpi_os_printf(" Address range min: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->min_address_range));
- acpi_os_printf (" Address range max: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->max_address_range));
+ acpi_os_printf(" Address range max: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->max_address_range));
- acpi_os_printf (" Address translation offset: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->address_translation_offset));
+ acpi_os_printf(" Address translation offset: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->
+ address_translation_offset));
- acpi_os_printf (" Address Length: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->address_length));
+ acpi_os_printf(" Address Length: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->address_length));
- acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes));
+ acpi_os_printf(" Type Specific Attributes: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(address64_data->
+ type_specific_attributes));
if (0xFF != address64_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X\n",
- address64_data->resource_source.index);
+ acpi_os_printf(" Resource Source Index: %X\n",
+ address64_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s\n",
- address64_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s\n",
+ address64_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_extended_irq
@@ -960,55 +906,52 @@ acpi_rs_dump_address64 (
*
******************************************************************************/
-static void
-acpi_rs_dump_extended_irq (
- union acpi_resource_data *data)
+static void acpi_rs_dump_extended_irq(union acpi_resource_data *data)
{
- struct acpi_resource_ext_irq *ext_irq_data = (struct acpi_resource_ext_irq *) data;
- u8 index = 0;
-
-
- ACPI_FUNCTION_ENTRY ();
+ struct acpi_resource_ext_irq *ext_irq_data =
+ (struct acpi_resource_ext_irq *)data;
+ u8 index = 0;
+ ACPI_FUNCTION_ENTRY();
- acpi_os_printf ("Extended IRQ Resource\n");
+ acpi_os_printf("Extended IRQ Resource\n");
- acpi_os_printf (" Resource %s\n",
- ACPI_CONSUMER == ext_irq_data->producer_consumer ?
- "Consumer" : "Producer");
+ acpi_os_printf(" Resource %s\n",
+ ACPI_CONSUMER == ext_irq_data->producer_consumer ?
+ "Consumer" : "Producer");
- acpi_os_printf (" %s\n",
- ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
- "Level" : "Edge");
+ acpi_os_printf(" %s\n",
+ ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ?
+ "Level" : "Edge");
- acpi_os_printf (" Active %s\n",
- ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
- "low" : "high");
+ acpi_os_printf(" Active %s\n",
+ ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ?
+ "low" : "high");
- acpi_os_printf (" %s\n",
- ACPI_SHARED == ext_irq_data->shared_exclusive ?
- "Shared" : "Exclusive");
+ acpi_os_printf(" %s\n",
+ ACPI_SHARED == ext_irq_data->shared_exclusive ?
+ "Shared" : "Exclusive");
- acpi_os_printf (" Interrupts : %X ( ", ext_irq_data->number_of_interrupts);
+ acpi_os_printf(" Interrupts : %X ( ",
+ ext_irq_data->number_of_interrupts);
for (index = 0; index < ext_irq_data->number_of_interrupts; index++) {
- acpi_os_printf ("%X ", ext_irq_data->interrupts[index]);
+ acpi_os_printf("%X ", ext_irq_data->interrupts[index]);
}
- acpi_os_printf (")\n");
+ acpi_os_printf(")\n");
- if(0xFF != ext_irq_data->resource_source.index) {
- acpi_os_printf (" Resource Source Index: %X",
- ext_irq_data->resource_source.index);
+ if (0xFF != ext_irq_data->resource_source.index) {
+ acpi_os_printf(" Resource Source Index: %X",
+ ext_irq_data->resource_source.index);
- acpi_os_printf (" Resource Source: %s",
- ext_irq_data->resource_source.string_ptr);
+ acpi_os_printf(" Resource Source: %s",
+ ext_irq_data->resource_source.string_ptr);
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dump_resource_list
@@ -1021,92 +964,91 @@ acpi_rs_dump_extended_irq (
*
******************************************************************************/
-void
-acpi_rs_dump_resource_list (
- struct acpi_resource *resource)
+void acpi_rs_dump_resource_list(struct acpi_resource *resource)
{
- u8 count = 0;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u8 count = 0;
+ u8 done = FALSE;
+ ACPI_FUNCTION_ENTRY();
if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
while (!done) {
- acpi_os_printf ("Resource structure %X.\n", count++);
+ acpi_os_printf("Resource structure %X.\n", count++);
switch (resource->id) {
case ACPI_RSTYPE_IRQ:
- acpi_rs_dump_irq (&resource->data);
+ acpi_rs_dump_irq(&resource->data);
break;
case ACPI_RSTYPE_DMA:
- acpi_rs_dump_dma (&resource->data);
+ acpi_rs_dump_dma(&resource->data);
break;
case ACPI_RSTYPE_START_DPF:
- acpi_rs_dump_start_depend_fns (&resource->data);
+ acpi_rs_dump_start_depend_fns(&resource->data);
break;
case ACPI_RSTYPE_END_DPF:
- acpi_os_printf ("end_dependent_functions Resource\n");
- /* acpi_rs_dump_end_dependent_functions (Resource->Data);*/
+ acpi_os_printf
+ ("end_dependent_functions Resource\n");
+ /* acpi_rs_dump_end_dependent_functions (Resource->Data); */
break;
case ACPI_RSTYPE_IO:
- acpi_rs_dump_io (&resource->data);
+ acpi_rs_dump_io(&resource->data);
break;
case ACPI_RSTYPE_FIXED_IO:
- acpi_rs_dump_fixed_io (&resource->data);
+ acpi_rs_dump_fixed_io(&resource->data);
break;
case ACPI_RSTYPE_VENDOR:
- acpi_rs_dump_vendor_specific (&resource->data);
+ acpi_rs_dump_vendor_specific(&resource->data);
break;
case ACPI_RSTYPE_END_TAG:
- /*rs_dump_end_tag (Resource->Data);*/
- acpi_os_printf ("end_tag Resource\n");
+ /*rs_dump_end_tag (Resource->Data); */
+ acpi_os_printf("end_tag Resource\n");
done = TRUE;
break;
case ACPI_RSTYPE_MEM24:
- acpi_rs_dump_memory24 (&resource->data);
+ acpi_rs_dump_memory24(&resource->data);
break;
case ACPI_RSTYPE_MEM32:
- acpi_rs_dump_memory32 (&resource->data);
+ acpi_rs_dump_memory32(&resource->data);
break;
case ACPI_RSTYPE_FIXED_MEM32:
- acpi_rs_dump_fixed_memory32 (&resource->data);
+ acpi_rs_dump_fixed_memory32(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS16:
- acpi_rs_dump_address16 (&resource->data);
+ acpi_rs_dump_address16(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS32:
- acpi_rs_dump_address32 (&resource->data);
+ acpi_rs_dump_address32(&resource->data);
break;
case ACPI_RSTYPE_ADDRESS64:
- acpi_rs_dump_address64 (&resource->data);
+ acpi_rs_dump_address64(&resource->data);
break;
case ACPI_RSTYPE_EXT_IRQ:
- acpi_rs_dump_extended_irq (&resource->data);
+ acpi_rs_dump_extended_irq(&resource->data);
break;
default:
- acpi_os_printf ("Invalid resource type\n");
+ acpi_os_printf("Invalid resource type\n");
break;
}
- resource = ACPI_PTR_ADD (struct acpi_resource, resource, resource->length);
+ resource =
+ ACPI_PTR_ADD(struct acpi_resource, resource,
+ resource->length);
}
}
@@ -1125,36 +1067,38 @@ acpi_rs_dump_resource_list (
*
******************************************************************************/
-void
-acpi_rs_dump_irq_list (
- u8 *route_table)
+void acpi_rs_dump_irq_list(u8 * route_table)
{
- u8 *buffer = route_table;
- u8 count = 0;
- u8 done = FALSE;
- struct acpi_pci_routing_table *prt_element;
-
-
- ACPI_FUNCTION_ENTRY ();
+ u8 *buffer = route_table;
+ u8 count = 0;
+ u8 done = FALSE;
+ struct acpi_pci_routing_table *prt_element;
+ ACPI_FUNCTION_ENTRY();
if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) {
- prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ prt_element =
+ ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
while (!done) {
- acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++);
+ acpi_os_printf("PCI IRQ Routing Table structure %X.\n",
+ count++);
- acpi_os_printf (" Address: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (prt_element->address));
+ acpi_os_printf(" Address: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(prt_element->
+ address));
- acpi_os_printf (" Pin: %X\n", prt_element->pin);
+ acpi_os_printf(" Pin: %X\n", prt_element->pin);
- acpi_os_printf (" Source: %s\n", prt_element->source);
+ acpi_os_printf(" Source: %s\n", prt_element->source);
- acpi_os_printf (" source_index: %X\n", prt_element->source_index);
+ acpi_os_printf(" source_index: %X\n",
+ prt_element->source_index);
buffer += prt_element->length;
- prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer);
+ prt_element =
+ ACPI_CAST_PTR(struct acpi_pci_routing_table,
+ buffer);
if (0 == prt_element->length) {
done = TRUE;
}
@@ -1165,4 +1109,3 @@ acpi_rs_dump_irq_list (
}
#endif
-
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index 23a4d149fac8..d53bbe89e851 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsio")
-
+ACPI_MODULE_NAME("rsio")
/*******************************************************************************
*
@@ -69,24 +67,18 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_io);
-
-
- ACPI_FUNCTION_TRACE ("rs_io_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_io);
+ ACPI_FUNCTION_TRACE("rs_io_resource");
/* The number of bytes consumed are Constant */
@@ -104,14 +96,14 @@ acpi_rs_io_resource (
/* Check min_base Address */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.io.min_base_address = temp16;
/* Check max_base Address */
buffer += 2;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.io.max_base_address = temp16;
@@ -136,10 +128,9 @@ acpi_rs_io_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_io_resource
@@ -162,22 +153,18 @@ acpi_rs_io_resource (
******************************************************************************/
acpi_status
-acpi_rs_fixed_io_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_fixed_io_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_fixed_io);
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_io_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io);
+ ACPI_FUNCTION_TRACE("rs_fixed_io_resource");
/* The number of bytes consumed are Constant */
@@ -188,7 +175,7 @@ acpi_rs_fixed_io_resource (
/* Check Range Base Address */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.fixed_io.base_address = temp16;
@@ -206,10 +193,9 @@ acpi_rs_fixed_io_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_io_stream
@@ -227,18 +213,14 @@ acpi_rs_fixed_io_resource (
******************************************************************************/
acpi_status
-acpi_rs_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_io_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_io_stream");
/* The descriptor field is static */
@@ -256,14 +238,14 @@ acpi_rs_io_stream (
temp16 = (u16) linked_list->data.io.min_base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Range maximum base address */
temp16 = (u16) linked_list->data.io.max_base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the base alignment */
@@ -282,11 +264,10 @@ acpi_rs_io_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_io_stream
@@ -304,18 +285,14 @@ acpi_rs_io_stream (
******************************************************************************/
acpi_status
-acpi_rs_fixed_io_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_fixed_io_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_io_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_fixed_io_stream");
/* The descriptor field is static */
@@ -327,7 +304,7 @@ acpi_rs_fixed_io_stream (
temp16 = (u16) linked_list->data.fixed_io.base_address;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the range length */
@@ -339,11 +316,10 @@ acpi_rs_fixed_io_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dma_resource
@@ -366,23 +342,18 @@ acpi_rs_fixed_io_stream (
******************************************************************************/
acpi_status
-acpi_rs_dma_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_dma_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_dma);
-
-
- ACPI_FUNCTION_TRACE ("rs_dma_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u8 temp8 = 0;
+ u8 index;
+ u8 i;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma);
+ ACPI_FUNCTION_TRACE("rs_dma_resource");
/* The number of bytes consumed are Constant */
@@ -422,9 +393,9 @@ acpi_rs_dma_resource (
output_struct->data.dma.transfer = temp8 & 0x03;
if (0x03 == output_struct->data.dma.transfer) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid DMA.Transfer preference (3)\n"));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid DMA.Transfer preference (3)\n"));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Get bus master preference (Bit[2]) */
@@ -442,10 +413,9 @@ acpi_rs_dma_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_dma_stream
@@ -463,19 +433,15 @@ acpi_rs_dma_resource (
******************************************************************************/
acpi_status
-acpi_rs_dma_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_dma_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_dma_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_dma_stream");
/* The descriptor field is static */
@@ -486,8 +452,7 @@ acpi_rs_dma_stream (
/* Loop through all of the Channels and set the mask bits */
for (index = 0;
- index < linked_list->data.dma.number_of_channels;
- index++) {
+ index < linked_list->data.dma.number_of_channels; index++) {
temp16 = (u16) linked_list->data.dma.channels[index];
temp8 |= 0x1 << temp16;
}
@@ -506,7 +471,6 @@ acpi_rs_dma_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 8a2b630be45b..56043fee96cb 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsirq")
-
+ACPI_MODULE_NAME("rsirq")
/*******************************************************************************
*
@@ -69,26 +67,20 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 i;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_irq);
-
-
- ACPI_FUNCTION_TRACE ("rs_irq_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ u8 i;
+ acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq);
+ ACPI_FUNCTION_TRACE("rs_irq_resource");
/*
* The number of bytes consumed are contained in the descriptor
@@ -101,7 +93,7 @@ acpi_rs_irq_resource (
/* Point to the 16-bits of Bytes 1 and 2 */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.irq.number_of_interrupts = 0;
@@ -132,14 +124,18 @@ acpi_rs_irq_resource (
/* Check for HE, LL interrupts */
switch (temp8 & 0x09) {
- case 0x01: /* HE */
- output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE;
- output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH;
+ case 0x01: /* HE */
+ output_struct->data.irq.edge_level =
+ ACPI_EDGE_SENSITIVE;
+ output_struct->data.irq.active_high_low =
+ ACPI_ACTIVE_HIGH;
break;
- case 0x08: /* LL */
- output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE;
- output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW;
+ case 0x08: /* LL */
+ output_struct->data.irq.edge_level =
+ ACPI_LEVEL_SENSITIVE;
+ output_struct->data.irq.active_high_low =
+ ACPI_ACTIVE_LOW;
break;
default:
@@ -148,17 +144,16 @@ acpi_rs_irq_resource (
* are allowed (ACPI spec, section "IRQ Format")
* so 0x00 and 0x09 are illegal.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid interrupt polarity/trigger in resource list, %X\n",
- temp8));
- return_ACPI_STATUS (AE_BAD_DATA);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid interrupt polarity/trigger in resource list, %X\n",
+ temp8));
+ return_ACPI_STATUS(AE_BAD_DATA);
}
/* Check for sharable */
output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01;
- }
- else {
+ } else {
/*
* Assume Edge Sensitive, Active High, Non-Sharable
* per ACPI Specification
@@ -175,10 +170,9 @@ acpi_rs_irq_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_irq_stream
@@ -196,32 +190,27 @@ acpi_rs_irq_resource (
******************************************************************************/
acpi_status
-acpi_rs_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- u8 IRqinfo_byte_needed;
-
-
- ACPI_FUNCTION_TRACE ("rs_irq_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ u8 IRqinfo_byte_needed;
+ ACPI_FUNCTION_TRACE("rs_irq_stream");
/*
* The descriptor field is set based upon whether a third byte is
* needed to contain the IRQ Information.
*/
if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
- ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
+ ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low &&
+ ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) {
*buffer = 0x22;
IRqinfo_byte_needed = FALSE;
- }
- else {
+ } else {
*buffer = 0x23;
IRqinfo_byte_needed = TRUE;
}
@@ -231,14 +220,13 @@ acpi_rs_irq_stream (
/* Loop through all of the interrupts and set the mask bits */
- for(index = 0;
- index < linked_list->data.irq.number_of_interrupts;
- index++) {
+ for (index = 0;
+ index < linked_list->data.irq.number_of_interrupts; index++) {
temp8 = (u8) linked_list->data.irq.interrupts[index];
temp16 |= 0x1 << temp8;
}
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the IRQ Info byte if needed. */
@@ -246,13 +234,12 @@ acpi_rs_irq_stream (
if (IRqinfo_byte_needed) {
temp8 = 0;
temp8 = (u8) ((linked_list->data.irq.shared_exclusive &
- 0x01) << 4);
+ 0x01) << 4);
if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level &&
- ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
+ ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) {
temp8 |= 0x08;
- }
- else {
+ } else {
temp8 |= 0x01;
}
@@ -262,11 +249,10 @@ acpi_rs_irq_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_extended_irq_resource
@@ -289,34 +275,30 @@ acpi_rs_irq_stream (
******************************************************************************/
acpi_status
-acpi_rs_extended_irq_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_extended_irq_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 *temp_ptr;
- u8 index;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_ext_irq);
-
-
- ACPI_FUNCTION_TRACE ("rs_extended_irq_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 *temp_ptr;
+ u8 index;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq);
+ ACPI_FUNCTION_TRACE("rs_extended_irq_resource");
- /* Point past the Descriptor to get the number of bytes consumed */
+ /* Get the Descriptor Length field */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Validate minimum descriptor length */
if (temp16 < 6) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
*bytes_consumed = temp16 + 3;
@@ -338,7 +320,7 @@ acpi_rs_extended_irq_resource (
* - Edge/Level are defined opposite in the table vs the headers
*/
output_struct->data.extended_irq.edge_level =
- (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+ (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
/* Check Interrupt Polarity */
@@ -356,7 +338,7 @@ acpi_rs_extended_irq_resource (
/* Must have at least one IRQ */
if (temp8 < 1) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
}
output_struct->data.extended_irq.number_of_interrupts = temp8;
@@ -374,8 +356,8 @@ acpi_rs_extended_irq_resource (
/* Cycle through every IRQ in the table */
for (index = 0; index < temp8; index++) {
- ACPI_MOVE_32_TO_32 (
- &output_struct->data.extended_irq.interrupts[index], buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq.
+ interrupts[index], buffer);
/* Point to the next IRQ */
@@ -393,12 +375,13 @@ acpi_rs_extended_irq_resource (
* we add 1 to the length.
*/
if (*bytes_consumed >
- ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) +
- (5 + 1)) {
+ ((acpi_size) output_struct->data.extended_irq.number_of_interrupts *
+ 4) + (5 + 1)) {
/* Dereference the Index */
temp8 = *buffer;
- output_struct->data.extended_irq.resource_source.index = (u32) temp8;
+ output_struct->data.extended_irq.resource_source.index =
+ (u32) temp8;
/* Point to the String */
@@ -407,15 +390,15 @@ acpi_rs_extended_irq_resource (
/* Point the String pointer to the end of this structure. */
output_struct->data.extended_irq.resource_source.string_ptr =
- (char *)((char *) output_struct + struct_size);
+ (char *)((char *)output_struct + struct_size);
temp_ptr = (u8 *)
- output_struct->data.extended_irq.resource_source.string_ptr;
+ output_struct->data.extended_irq.resource_source.string_ptr;
/* Copy the string into the buffer */
index = 0;
- while (0x00 != *buffer) {
+ while (*buffer) {
*temp_ptr = *buffer;
temp_ptr += 1;
@@ -425,8 +408,9 @@ acpi_rs_extended_irq_resource (
/* Add the terminating null */
- *temp_ptr = 0x00;
- output_struct->data.extended_irq.resource_source.string_length = index + 1;
+ *temp_ptr = 0;
+ output_struct->data.extended_irq.resource_source.string_length =
+ index + 1;
/*
* In order for the struct_size to fall on a 32-bit boundary,
@@ -434,12 +418,13 @@ acpi_rs_extended_irq_resource (
* struct_size to the next 32-bit boundary.
*/
temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.extended_irq.resource_source.index = 0x00;
- output_struct->data.extended_irq.resource_source.string_length = 0;
- output_struct->data.extended_irq.resource_source.string_ptr = NULL;
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp8);
+ } else {
+ output_struct->data.extended_irq.resource_source.index = 0;
+ output_struct->data.extended_irq.resource_source.string_length =
+ 0;
+ output_struct->data.extended_irq.resource_source.string_ptr =
+ NULL;
}
/* Set the Length parameter */
@@ -449,10 +434,9 @@ acpi_rs_extended_irq_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_extended_irq_stream
@@ -470,35 +454,31 @@ acpi_rs_extended_irq_resource (
******************************************************************************/
acpi_status
-acpi_rs_extended_irq_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_extended_irq_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 *length_field;
- u8 temp8 = 0;
- u8 index;
- char *temp_pointer = NULL;
-
-
- ACPI_FUNCTION_TRACE ("rs_extended_irq_stream");
+ u8 *buffer = *output_buffer;
+ u16 *length_field;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_extended_irq_stream");
- /* The descriptor field is static */
+ /* Set the Descriptor Type field */
- *buffer = 0x89;
+ *buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT;
buffer += 1;
- /* Set a pointer to the Length field - to be filled in later */
+ /* Save a pointer to the Length field - to be filled in later */
- length_field = ACPI_CAST_PTR (u16, buffer);
+ length_field = ACPI_CAST_PTR(u16, buffer);
buffer += 2;
/* Set the Interrupt vector flags */
- temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01);
- temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
+ temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01);
+ temp8 |=
+ ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3);
/*
* Set the Interrupt Mode
@@ -527,43 +507,46 @@ acpi_rs_extended_irq_stream (
*buffer = temp8;
buffer += 1;
- for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts;
- index++) {
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.extended_irq.interrupts[index]);
+ for (index = 0;
+ index < linked_list->data.extended_irq.number_of_interrupts;
+ index++) {
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.extended_irq.
+ interrupts[index]);
buffer += 4;
}
/* Resource Source Index and Resource Source are optional */
if (0 != linked_list->data.extended_irq.resource_source.string_length) {
- *buffer = (u8) linked_list->data.extended_irq.resource_source.index;
+ *buffer =
+ (u8) linked_list->data.extended_irq.resource_source.index;
buffer += 1;
- temp_pointer = (char *) buffer;
-
/* Copy the string */
- ACPI_STRCPY (temp_pointer,
- linked_list->data.extended_irq.resource_source.string_ptr);
+ ACPI_STRCPY((char *)buffer,
+ linked_list->data.extended_irq.resource_source.
+ string_ptr);
/*
- * Buffer needs to be set to the length of the sting + one for the
+ * Buffer needs to be set to the length of the string + one for the
* terminating null
*/
- buffer += (acpi_size) (ACPI_STRLEN (
- linked_list->data.extended_irq.resource_source.string_ptr) + 1);
+ buffer +=
+ (acpi_size) (ACPI_STRLEN
+ (linked_list->data.extended_irq.
+ resource_source.string_ptr) + 1);
}
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
/*
* Set the length field to the number of bytes consumed
* minus the header size (3 bytes)
*/
*length_field = (u16) (*bytes_consumed - 3);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index db7bcb4e60e3..103eb31c284e 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rslist")
-
+ACPI_MODULE_NAME("rslist")
/*******************************************************************************
*
@@ -61,14 +59,10 @@
* a resource descriptor.
*
******************************************************************************/
-
-u8
-acpi_rs_get_resource_type (
- u8 resource_start_byte)
+u8 acpi_rs_get_resource_type(u8 resource_start_byte)
{
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
/* Determine if this is a small or large resource */
@@ -79,14 +73,12 @@ acpi_rs_get_resource_type (
return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK));
-
case ACPI_RDESC_TYPE_LARGE:
/* Large Resource Type -- All bits are valid */
return (resource_start_byte);
-
default:
/* Invalid type */
break;
@@ -95,7 +87,6 @@ acpi_rs_get_resource_type (
return (0xFF);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_byte_stream_to_list
@@ -113,176 +104,189 @@ acpi_rs_get_resource_type (
******************************************************************************/
acpi_status
-acpi_rs_byte_stream_to_list (
- u8 *byte_stream_buffer,
- u32 byte_stream_buffer_length,
- u8 *output_buffer)
+acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer,
+ u32 byte_stream_buffer_length, u8 * output_buffer)
{
- acpi_status status;
- acpi_size bytes_parsed = 0;
- u8 resource_type = 0;
- acpi_size bytes_consumed = 0;
- u8 *buffer = output_buffer;
- acpi_size structure_size = 0;
- u8 end_tag_processed = FALSE;
- struct acpi_resource *resource;
-
- ACPI_FUNCTION_TRACE ("rs_byte_stream_to_list");
-
-
- while (bytes_parsed < byte_stream_buffer_length &&
- !end_tag_processed) {
+ acpi_status status;
+ acpi_size bytes_parsed = 0;
+ u8 resource_type = 0;
+ acpi_size bytes_consumed = 0;
+ u8 *buffer = output_buffer;
+ acpi_size structure_size = 0;
+ u8 end_tag_processed = FALSE;
+ struct acpi_resource *resource;
+
+ ACPI_FUNCTION_TRACE("rs_byte_stream_to_list");
+
+ while (bytes_parsed < byte_stream_buffer_length && !end_tag_processed) {
/* The next byte in the stream is the resource type */
- resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
+ resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
switch (resource_type) {
case ACPI_RDESC_TYPE_MEMORY_24:
/*
* 24-Bit Memory Resource
*/
- status = acpi_rs_memory24_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_memory24_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_LARGE_VENDOR:
/*
* Vendor Defined Resource
*/
- status = acpi_rs_vendor_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_vendor_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_MEMORY_32:
/*
* 32-Bit Memory Range Resource
*/
- status = acpi_rs_memory32_range_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_memory32_range_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
/*
* 32-Bit Fixed Memory Resource
*/
- status = acpi_rs_fixed_memory32_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_fixed_memory32_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
*/
- status = acpi_rs_address64_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address64_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
/*
* 32-Bit Address Resource
*/
- status = acpi_rs_address32_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address32_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
/*
* 16-Bit Address Resource
*/
- status = acpi_rs_address16_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_address16_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
/*
* Extended IRQ
*/
- status = acpi_rs_extended_irq_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_extended_irq_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_IRQ_FORMAT:
/*
* IRQ Resource
*/
- status = acpi_rs_irq_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_irq_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_DMA_FORMAT:
/*
* DMA Resource
*/
- status = acpi_rs_dma_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_dma_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_START_DEPENDENT:
/*
* Start Dependent Functions Resource
*/
- status = acpi_rs_start_depend_fns_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_start_depend_fns_resource
+ (byte_stream_buffer, &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_END_DEPENDENT:
/*
* End Dependent Functions Resource
*/
- status = acpi_rs_end_depend_fns_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status =
+ acpi_rs_end_depend_fns_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_IO_PORT:
/*
* IO Port Resource
*/
- status = acpi_rs_io_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_io_resource(byte_stream_buffer,
+ &bytes_consumed, &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_FIXED_IO_PORT:
/*
* Fixed IO Port Resource
*/
- status = acpi_rs_fixed_io_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_fixed_io_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_SMALL_VENDOR:
/*
* Vendor Specific Resource
*/
- status = acpi_rs_vendor_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_vendor_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
case ACPI_RDESC_TYPE_END_TAG:
/*
* End Tag
*/
end_tag_processed = TRUE;
- status = acpi_rs_end_tag_resource (byte_stream_buffer,
- &bytes_consumed, &buffer, &structure_size);
+ status = acpi_rs_end_tag_resource(byte_stream_buffer,
+ &bytes_consumed,
+ &buffer,
+ &structure_size);
break;
-
default:
/*
* Invalid/Unknown resource type
@@ -291,8 +295,8 @@ acpi_rs_byte_stream_to_list (
break;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Update the return value and counter */
@@ -305,21 +309,21 @@ acpi_rs_byte_stream_to_list (
/* Set the Buffer to the next structure */
- resource = ACPI_CAST_PTR (struct acpi_resource, buffer);
- resource->length = (u32) ACPI_ALIGN_RESOURCE_SIZE (resource->length);
- buffer += ACPI_ALIGN_RESOURCE_SIZE (structure_size);
+ resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
+ resource->length =
+ (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
+ buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size);
}
/* Check the reason for exiting the while loop */
if (!end_tag_processed) {
- return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_list_to_byte_stream
@@ -342,19 +346,16 @@ acpi_rs_byte_stream_to_list (
******************************************************************************/
acpi_status
-acpi_rs_list_to_byte_stream (
- struct acpi_resource *linked_list,
- acpi_size byte_stream_size_needed,
- u8 *output_buffer)
+acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list,
+ acpi_size byte_stream_size_needed,
+ u8 * output_buffer)
{
- acpi_status status;
- u8 *buffer = output_buffer;
- acpi_size bytes_consumed = 0;
- u8 done = FALSE;
-
-
- ACPI_FUNCTION_TRACE ("rs_list_to_byte_stream");
+ acpi_status status;
+ u8 *buffer = output_buffer;
+ acpi_size bytes_consumed = 0;
+ u8 done = FALSE;
+ ACPI_FUNCTION_TRACE("rs_list_to_byte_stream");
while (!done) {
switch (linked_list->id) {
@@ -362,58 +363,72 @@ acpi_rs_list_to_byte_stream (
/*
* IRQ Resource
*/
- status = acpi_rs_irq_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_irq_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_DMA:
/*
* DMA Resource
*/
- status = acpi_rs_dma_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_dma_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_START_DPF:
/*
* Start Dependent Functions Resource
*/
- status = acpi_rs_start_depend_fns_stream (linked_list,
- &buffer, &bytes_consumed);
+ status = acpi_rs_start_depend_fns_stream(linked_list,
+ &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_END_DPF:
/*
* End Dependent Functions Resource
*/
- status = acpi_rs_end_depend_fns_stream (linked_list,
- &buffer, &bytes_consumed);
+ status = acpi_rs_end_depend_fns_stream(linked_list,
+ &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_IO:
/*
* IO Port Resource
*/
- status = acpi_rs_io_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_io_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_FIXED_IO:
/*
* Fixed IO Port Resource
*/
- status = acpi_rs_fixed_io_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_fixed_io_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_VENDOR:
/*
* Vendor Defined Resource
*/
- status = acpi_rs_vendor_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_vendor_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_END_TAG:
/*
* End Tag
*/
- status = acpi_rs_end_tag_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_end_tag_stream(linked_list, &buffer,
+ &bytes_consumed);
/* An End Tag indicates the end of the Resource Template */
@@ -424,55 +439,60 @@ acpi_rs_list_to_byte_stream (
/*
* 24-Bit Memory Resource
*/
- status = acpi_rs_memory24_stream (linked_list, &buffer, &bytes_consumed);
+ status =
+ acpi_rs_memory24_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_MEM32:
/*
* 32-Bit Memory Range Resource
*/
- status = acpi_rs_memory32_range_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_memory32_range_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_FIXED_MEM32:
/*
* 32-Bit Fixed Memory Resource
*/
- status = acpi_rs_fixed_memory32_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_fixed_memory32_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS16:
/*
* 16-Bit Address Descriptor Resource
*/
- status = acpi_rs_address16_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address16_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS32:
/*
* 32-Bit Address Descriptor Resource
*/
- status = acpi_rs_address32_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address32_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_ADDRESS64:
/*
* 64-Bit Address Descriptor Resource
*/
- status = acpi_rs_address64_stream (linked_list, &buffer,
- &bytes_consumed);
+ status = acpi_rs_address64_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
case ACPI_RSTYPE_EXT_IRQ:
/*
* Extended IRQ Resource
*/
- status = acpi_rs_extended_irq_stream (linked_list, &buffer,
- &bytes_consumed);
+ status =
+ acpi_rs_extended_irq_stream(linked_list, &buffer,
+ &bytes_consumed);
break;
default:
@@ -480,15 +500,15 @@ acpi_rs_list_to_byte_stream (
* If we get here, everything is out of sync,
* so exit with an error
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid descriptor type (%X) in resource list\n",
- linked_list->id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid descriptor type (%X) in resource list\n",
+ linked_list->id));
status = AE_BAD_DATA;
break;
}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Set the Buffer to point to the open byte */
@@ -497,10 +517,9 @@ acpi_rs_list_to_byte_stream (
/* Point to the next object */
- linked_list = ACPI_PTR_ADD (struct acpi_resource,
- linked_list, linked_list->length);
+ linked_list = ACPI_PTR_ADD(struct acpi_resource,
+ linked_list, linked_list->length);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
index 91d0207f01ac..daba1a1ed46d 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/resources/rsmemory.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsmemory")
-
+ACPI_MODULE_NAME("rsmemory")
/*******************************************************************************
*
@@ -69,30 +67,25 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_memory24_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_memory24_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_mem24);
-
-
- ACPI_FUNCTION_TRACE ("rs_memory24_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24);
+ ACPI_FUNCTION_TRACE("rs_memory24_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
output_struct->id = ACPI_RSTYPE_MEM24;
@@ -105,25 +98,25 @@ acpi_rs_memory24_resource (
/* Get min_base_address (Bytes 4-5) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.min_base_address = temp16;
/* Get max_base_address (Bytes 6-7) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.max_base_address = temp16;
/* Get Alignment (Bytes 8-9) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
output_struct->data.memory24.alignment = temp16;
/* Get range_length (Bytes 10-11) */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
output_struct->data.memory24.range_length = temp16;
/* Set the Length parameter */
@@ -133,10 +126,9 @@ acpi_rs_memory24_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory24_stream
@@ -154,18 +146,14 @@ acpi_rs_memory24_resource (
******************************************************************************/
acpi_status
-acpi_rs_memory24_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_memory24_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_memory24_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_memory24_stream");
/* The descriptor field is static */
@@ -175,7 +163,7 @@ acpi_rs_memory24_stream (
/* The length field is static */
temp16 = 0x09;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
@@ -186,31 +174,32 @@ acpi_rs_memory24_stream (
/* Set the Range minimum base address */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.min_base_address);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.memory24.min_base_address);
buffer += 2;
/* Set the Range maximum base address */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.max_base_address);
+ ACPI_MOVE_32_TO_16(buffer,
+ &linked_list->data.memory24.max_base_address);
buffer += 2;
/* Set the base alignment */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.alignment);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.alignment);
buffer += 2;
/* Set the range length */
- ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.range_length);
+ ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.range_length);
buffer += 2;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory32_range_resource
@@ -233,28 +222,24 @@ acpi_rs_memory24_stream (
******************************************************************************/
acpi_status
-acpi_rs_memory32_range_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_memory32_range_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_mem32);
-
-
- ACPI_FUNCTION_TRACE ("rs_memory32_range_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32);
+ ACPI_FUNCTION_TRACE("rs_memory32_range_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
@@ -279,22 +264,24 @@ acpi_rs_memory32_range_resource (
/* Get min_base_address (Bytes 4-7) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.min_base_address, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.min_base_address,
+ buffer);
buffer += 4;
/* Get max_base_address (Bytes 8-11) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.max_base_address, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.max_base_address,
+ buffer);
buffer += 4;
/* Get Alignment (Bytes 12-15) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.alignment, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.alignment, buffer);
buffer += 4;
/* Get range_length (Bytes 16-19) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.range_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.memory32.range_length, buffer);
/* Set the Length parameter */
@@ -303,10 +290,9 @@ acpi_rs_memory32_range_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_memory32_resource
@@ -329,27 +315,23 @@ acpi_rs_memory32_range_resource (
******************************************************************************/
acpi_status
-acpi_rs_fixed_memory32_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_fixed_mem32);
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_memory32_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32);
+ ACPI_FUNCTION_TRACE("rs_fixed_memory32_resource");
/* Point past the Descriptor to get the number of bytes consumed */
buffer += 1;
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
buffer += 2;
*bytes_consumed = (acpi_size) temp16 + 3;
@@ -364,13 +346,14 @@ acpi_rs_fixed_memory32_resource (
/* Get range_base_address (Bytes 4-7) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_base_address,
- buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.
+ range_base_address, buffer);
buffer += 4;
/* Get range_length (Bytes 8-11) */
- ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_length, buffer);
+ ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.range_length,
+ buffer);
/* Set the Length parameter */
@@ -379,10 +362,9 @@ acpi_rs_fixed_memory32_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_memory32_range_stream
@@ -400,18 +382,14 @@ acpi_rs_fixed_memory32_resource (
******************************************************************************/
acpi_status
-acpi_rs_memory32_range_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_memory32_range_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_memory32_range_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_memory32_range_stream");
/* The descriptor field is static */
@@ -422,7 +400,7 @@ acpi_rs_memory32_range_stream (
temp16 = 0x11;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
@@ -433,31 +411,32 @@ acpi_rs_memory32_range_stream (
/* Set the Range minimum base address */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.min_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.memory32.min_base_address);
buffer += 4;
/* Set the Range maximum base address */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.max_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.memory32.max_base_address);
buffer += 4;
/* Set the base alignment */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.alignment);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.alignment);
buffer += 4;
/* Set the range length */
- ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.range_length);
+ ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.range_length);
buffer += 4;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_fixed_memory32_stream
@@ -475,18 +454,14 @@ acpi_rs_memory32_range_stream (
******************************************************************************/
acpi_status
-acpi_rs_fixed_memory32_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_fixed_memory32_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_fixed_memory32_stream");
/* The descriptor field is static */
@@ -497,30 +472,31 @@ acpi_rs_fixed_memory32_stream (
temp16 = 0x09;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
/* Set the Information Byte */
- temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
+ temp8 =
+ (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01);
*buffer = temp8;
buffer += 1;
/* Set the Range base address */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.fixed_memory32.range_base_address);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.fixed_memory32.
+ range_base_address);
buffer += 4;
/* Set the range length */
- ACPI_MOVE_32_TO_32 (buffer,
- &linked_list->data.fixed_memory32.range_length);
+ ACPI_MOVE_32_TO_32(buffer,
+ &linked_list->data.fixed_memory32.range_length);
buffer += 4;
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index a1f1741f0d83..7a8a34e757f5 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -41,13 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsmisc")
-
+ACPI_MODULE_NAME("rsmisc")
/*******************************************************************************
*
@@ -69,20 +67,15 @@
* number of bytes consumed from the byte stream.
*
******************************************************************************/
-
acpi_status
-acpi_rs_end_tag_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_end_tag_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_tag_resource");
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+ ACPI_FUNCTION_TRACE("rs_end_tag_resource");
/* The number of bytes consumed is static */
@@ -99,10 +92,9 @@ acpi_rs_end_tag_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_tag_stream
@@ -120,17 +112,13 @@ acpi_rs_end_tag_resource (
******************************************************************************/
acpi_status
-acpi_rs_end_tag_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_end_tag_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_tag_stream");
+ u8 *buffer = *output_buffer;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_end_tag_stream");
/* The descriptor field is static */
@@ -148,11 +136,10 @@ acpi_rs_end_tag_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_vendor_resource
@@ -175,23 +162,19 @@ acpi_rs_end_tag_stream (
******************************************************************************/
acpi_status
-acpi_rs_vendor_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_vendor_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_vendor);
-
-
- ACPI_FUNCTION_TRACE ("rs_vendor_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor);
+ ACPI_FUNCTION_TRACE("rs_vendor_resource");
/* Dereference the Descriptor to find if this is a large or small item. */
@@ -204,7 +187,7 @@ acpi_rs_vendor_resource (
/* Dereference */
- ACPI_MOVE_16_TO_16 (&temp16, buffer);
+ ACPI_MOVE_16_TO_16(&temp16, buffer);
/* Calculate bytes consumed */
@@ -213,11 +196,10 @@ acpi_rs_vendor_resource (
/* Point to the first vendor byte */
buffer += 2;
- }
- else {
+ } else {
/* Small Item, dereference the size */
- temp16 = (u8)(*buffer & 0x07);
+ temp16 = (u8) (*buffer & 0x07);
/* Calculate bytes consumed */
@@ -241,7 +223,7 @@ acpi_rs_vendor_resource (
* calculate the length of the vendor string and expand the
* struct_size to the next 32-bit boundary.
*/
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp16);
+ struct_size += ACPI_ROUND_UP_to_32_bITS(temp16);
/* Set the Length parameter */
@@ -250,10 +232,9 @@ acpi_rs_vendor_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_vendor_stream
@@ -271,23 +252,19 @@ acpi_rs_vendor_resource (
******************************************************************************/
acpi_status
-acpi_rs_vendor_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_vendor_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u16 temp16 = 0;
- u8 temp8 = 0;
- u8 index;
-
-
- ACPI_FUNCTION_TRACE ("rs_vendor_stream");
+ u8 *buffer = *output_buffer;
+ u16 temp16 = 0;
+ u8 temp8 = 0;
+ u8 index;
+ ACPI_FUNCTION_TRACE("rs_vendor_stream");
/* Dereference the length to find if this is a large or small item. */
- if(linked_list->data.vendor_specific.length > 7) {
+ if (linked_list->data.vendor_specific.length > 7) {
/* Large Item, Set the descriptor field and length bytes */
*buffer = 0x84;
@@ -295,10 +272,9 @@ acpi_rs_vendor_stream (
temp16 = (u16) linked_list->data.vendor_specific.length;
- ACPI_MOVE_16_TO_16 (buffer, &temp16);
+ ACPI_MOVE_16_TO_16(buffer, &temp16);
buffer += 2;
- }
- else {
+ } else {
/* Small Item, Set the descriptor field */
temp8 = 0x70;
@@ -310,7 +286,8 @@ acpi_rs_vendor_stream (
/* Loop through all of the Vendor Specific fields */
- for (index = 0; index < linked_list->data.vendor_specific.length; index++) {
+ for (index = 0; index < linked_list->data.vendor_specific.length;
+ index++) {
temp8 = linked_list->data.vendor_specific.reserved[index];
*buffer = temp8;
@@ -319,11 +296,10 @@ acpi_rs_vendor_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_start_depend_fns_resource
@@ -346,21 +322,18 @@ acpi_rs_vendor_stream (
******************************************************************************/
acpi_status
-acpi_rs_start_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer,
+ acpi_size * structure_size)
{
- u8 *buffer = byte_stream_buffer;
- struct acpi_resource *output_struct = (void *) *output_buffer;
- u8 temp8 = 0;
- acpi_size struct_size = ACPI_SIZEOF_RESOURCE (
- struct acpi_resource_start_dpf);
-
-
- ACPI_FUNCTION_TRACE ("rs_start_depend_fns_resource");
+ u8 *buffer = byte_stream_buffer;
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ u8 temp8 = 0;
+ acpi_size struct_size =
+ ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf);
+ ACPI_FUNCTION_TRACE("rs_start_depend_fns_resource");
/* The number of bytes consumed are found in the descriptor (Bits:0-1) */
@@ -378,26 +351,27 @@ acpi_rs_start_depend_fns_resource (
/* Check Compatibility priority */
- output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03;
+ output_struct->data.start_dpf.compatibility_priority =
+ temp8 & 0x03;
if (3 == output_struct->data.start_dpf.compatibility_priority) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
}
/* Check Performance/Robustness preference */
- output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03;
+ output_struct->data.start_dpf.performance_robustness =
+ (temp8 >> 2) & 0x03;
if (3 == output_struct->data.start_dpf.performance_robustness) {
- return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
+ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
}
- }
- else {
+ } else {
output_struct->data.start_dpf.compatibility_priority =
- ACPI_ACCEPTABLE_CONFIGURATION;
+ ACPI_ACCEPTABLE_CONFIGURATION;
output_struct->data.start_dpf.performance_robustness =
- ACPI_ACCEPTABLE_CONFIGURATION;
+ ACPI_ACCEPTABLE_CONFIGURATION;
}
/* Set the Length parameter */
@@ -407,10 +381,9 @@ acpi_rs_start_depend_fns_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_depend_fns_resource
@@ -433,18 +406,14 @@ acpi_rs_start_depend_fns_resource (
******************************************************************************/
acpi_status
-acpi_rs_end_depend_fns_resource (
- u8 *byte_stream_buffer,
- acpi_size *bytes_consumed,
- u8 **output_buffer,
- acpi_size *structure_size)
+acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer,
+ acpi_size * bytes_consumed,
+ u8 ** output_buffer, acpi_size * structure_size)
{
- struct acpi_resource *output_struct = (void *) *output_buffer;
- acpi_size struct_size = ACPI_RESOURCE_LENGTH;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_depend_fns_resource");
+ struct acpi_resource *output_struct = (void *)*output_buffer;
+ acpi_size struct_size = ACPI_RESOURCE_LENGTH;
+ ACPI_FUNCTION_TRACE("rs_end_depend_fns_resource");
/* The number of bytes consumed is static */
@@ -461,10 +430,9 @@ acpi_rs_end_depend_fns_resource (
/* Return the final size of the structure */
*structure_size = struct_size;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_start_depend_fns_stream
@@ -483,39 +451,35 @@ acpi_rs_end_depend_fns_resource (
******************************************************************************/
acpi_status
-acpi_rs_start_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
- u8 temp8 = 0;
-
-
- ACPI_FUNCTION_TRACE ("rs_start_depend_fns_stream");
+ u8 *buffer = *output_buffer;
+ u8 temp8 = 0;
+ ACPI_FUNCTION_TRACE("rs_start_depend_fns_stream");
/*
* The descriptor field is set based upon whether a byte is needed
* to contain Priority data.
*/
if (ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.compatibility_priority &&
- ACPI_ACCEPTABLE_CONFIGURATION ==
- linked_list->data.start_dpf.performance_robustness) {
+ linked_list->data.start_dpf.compatibility_priority &&
+ ACPI_ACCEPTABLE_CONFIGURATION ==
+ linked_list->data.start_dpf.performance_robustness) {
*buffer = 0x30;
- }
- else {
+ } else {
*buffer = 0x31;
buffer += 1;
/* Set the Priority Byte Definition */
temp8 = 0;
- temp8 = (u8) ((linked_list->data.start_dpf.performance_robustness &
- 0x03) << 2);
- temp8 |= (linked_list->data.start_dpf.compatibility_priority &
- 0x03);
+ temp8 =
+ (u8) ((linked_list->data.start_dpf.
+ performance_robustness & 0x03) << 2);
+ temp8 |=
+ (linked_list->data.start_dpf.compatibility_priority & 0x03);
*buffer = temp8;
}
@@ -523,11 +487,10 @@ acpi_rs_start_depend_fns_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_end_depend_fns_stream
@@ -545,16 +508,12 @@ acpi_rs_start_depend_fns_stream (
******************************************************************************/
acpi_status
-acpi_rs_end_depend_fns_stream (
- struct acpi_resource *linked_list,
- u8 **output_buffer,
- acpi_size *bytes_consumed)
+acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list,
+ u8 ** output_buffer, acpi_size * bytes_consumed)
{
- u8 *buffer = *output_buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_end_depend_fns_stream");
+ u8 *buffer = *output_buffer;
+ ACPI_FUNCTION_TRACE("rs_end_depend_fns_stream");
/* The descriptor field is static */
@@ -563,7 +522,6 @@ acpi_rs_end_depend_fns_stream (
/* Return the number of bytes consumed in this operation */
- *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer);
- return_ACPI_STATUS (AE_OK);
+ *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 700cf7d65d76..4446778eaf79 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -41,15 +41,12 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acresrc.h>
-
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsutils")
-
+ACPI_MODULE_NAME("rsutils")
/*******************************************************************************
*
@@ -68,42 +65,36 @@
* and the contents of the callers buffer is undefined.
*
******************************************************************************/
-
acpi_status
-acpi_rs_get_prt_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_prt_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object (handle, METHOD_NAME__PRT,
- ACPI_BTYPE_PACKAGE, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
+ ACPI_BTYPE_PACKAGE, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Create a resource linked list from the byte stream buffer that comes
* back from the _CRS method execution.
*/
- status = acpi_rs_create_pci_routing_table (obj_desc, ret_buffer);
+ status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
/* On exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_crs_method_data
@@ -123,25 +114,21 @@ acpi_rs_get_prt_method_data (
******************************************************************************/
acpi_status
-acpi_rs_get_crs_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_crs_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object (handle, METHOD_NAME__CRS,
- ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
+ ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -149,15 +136,14 @@ acpi_rs_get_crs_method_data (
* byte stream buffer that comes back from the _CRS method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* on exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_rs_get_prs_method_data
@@ -178,25 +164,21 @@ acpi_rs_get_crs_method_data (
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_rs_get_prs_method_data (
- acpi_handle handle,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_prs_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object (handle, METHOD_NAME__PRS,
- ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
+ ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -204,15 +186,14 @@ acpi_rs_get_prs_method_data (
* byte stream buffer that comes back from the _CRS method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* on exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -234,25 +215,22 @@ acpi_rs_get_prs_method_data (
******************************************************************************/
acpi_status
-acpi_rs_get_method_data (
- acpi_handle handle,
- char *path,
- struct acpi_buffer *ret_buffer)
+acpi_rs_get_method_data(acpi_handle handle,
+ char *path, struct acpi_buffer *ret_buffer)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("rs_get_method_data");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("rs_get_method_data");
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object (handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -260,12 +238,12 @@ acpi_rs_get_method_data (
* byte stream buffer that comes back from the method
* execution.
*/
- status = acpi_rs_create_resource_list (obj_desc, ret_buffer);
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
/* On exit, we must delete the object returned by evaluate_object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -287,18 +265,14 @@ acpi_rs_get_method_data (
******************************************************************************/
acpi_status
-acpi_rs_set_srs_method_data (
- acpi_handle handle,
- struct acpi_buffer *in_buffer)
+acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[2];
- acpi_status status;
- struct acpi_buffer buffer;
-
-
- ACPI_FUNCTION_TRACE ("rs_set_srs_method_data");
+ struct acpi_parameter_info info;
+ union acpi_operand_object *params[2];
+ acpi_status status;
+ struct acpi_buffer buffer;
+ ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
/* Parameters guaranteed valid by caller */
@@ -310,24 +284,24 @@ acpi_rs_set_srs_method_data (
* Convert the linked list into a byte stream
*/
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_rs_create_byte_stream (in_buffer->pointer, &buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Init the param object */
- params[0] = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
if (!params[0]) {
- acpi_os_free (buffer.pointer);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Set up the parameter object */
- params[0]->buffer.length = (u32) buffer.length;
+ params[0]->buffer.length = (u32) buffer.length;
params[0]->buffer.pointer = buffer.pointer;
- params[0]->common.flags = AOPOBJ_DATA_VALID;
+ params[0]->common.flags = AOPOBJ_DATA_VALID;
params[1] = NULL;
info.node = handle;
@@ -336,18 +310,17 @@ acpi_rs_set_srs_method_data (
/* Execute the method, no return value */
- status = acpi_ns_evaluate_relative (METHOD_NAME__SRS, &info);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
+ if (ACPI_SUCCESS(status)) {
/* Delete any return object (especially if implicit_return is enabled) */
if (info.return_object) {
- acpi_ut_remove_reference (info.return_object);
+ acpi_ut_remove_reference(info.return_object);
}
}
/* Clean up and return the status from acpi_ns_evaluate_relative */
- acpi_ut_remove_reference (params[0]);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(params[0]);
+ return_ACPI_STATUS(status);
}
-
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 83c944b8b097..ee5a5c509199 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -47,10 +47,9 @@
#include <acpi/acresrc.h>
#define _COMPONENT ACPI_RESOURCES
- ACPI_MODULE_NAME ("rsxface")
+ACPI_MODULE_NAME("rsxface")
/* Local macros for 16,32-bit to 64-bit conversion */
-
#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)
#define ACPI_COPY_ADDRESS(out, in) \
ACPI_COPY_FIELD(out, in, resource_type); \
@@ -65,8 +64,6 @@
ACPI_COPY_FIELD(out, in, address_translation_offset); \
ACPI_COPY_FIELD(out, in, address_length); \
ACPI_COPY_FIELD(out, in, resource_source);
-
-
/*******************************************************************************
*
* FUNCTION: acpi_get_irq_routing_table
@@ -89,17 +86,13 @@
* the object indicated by the passed device_handle.
*
******************************************************************************/
-
acpi_status
-acpi_get_irq_routing_table (
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_irq_routing_table(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_irq_routing_table ");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table ");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -108,19 +101,18 @@ acpi_get_irq_routing_table (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prt_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_prt_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_current_resources
@@ -146,15 +138,12 @@ acpi_get_irq_routing_table (
******************************************************************************/
acpi_status
-acpi_get_current_resources (
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_current_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_current_resources");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -163,19 +152,19 @@ acpi_get_current_resources (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_crs_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_crs_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_current_resources);
+EXPORT_SYMBOL(acpi_get_current_resources);
/*******************************************************************************
*
@@ -200,15 +189,12 @@ EXPORT_SYMBOL(acpi_get_current_resources);
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_possible_resources (
- acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_possible_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_possible_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_possible_resources");
/*
* Must have a valid handle and buffer, So we have to have a handle
@@ -217,20 +203,20 @@ acpi_get_possible_resources (
* we'll be returning the needed buffer size, so keep going.
*/
if (!device_handle) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prs_method_data (device_handle, ret_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_prs_method_data(device_handle, ret_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_possible_resources);
-#endif /* ACPI_FUTURE_USAGE */
+EXPORT_SYMBOL(acpi_get_possible_resources);
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -252,37 +238,33 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
******************************************************************************/
acpi_status
-acpi_walk_resources (
- acpi_handle device_handle,
- char *path,
- ACPI_WALK_RESOURCE_CALLBACK user_function,
- void *context)
+acpi_walk_resources(acpi_handle device_handle,
+ char *path,
+ ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
{
- acpi_status status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- struct acpi_resource *resource;
- struct acpi_resource *buffer_end;
-
-
- ACPI_FUNCTION_TRACE ("acpi_walk_resources");
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_resource *resource;
+ struct acpi_resource *buffer_end;
+ ACPI_FUNCTION_TRACE("acpi_walk_resources");
if (!device_handle ||
- (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) &&
- ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
+ ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_rs_get_method_data (device_handle, path, &buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_rs_get_method_data(device_handle, path, &buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Setup pointers */
- resource = (struct acpi_resource *) buffer.pointer;
- buffer_end = ACPI_CAST_PTR (struct acpi_resource,
- ((u8 *) buffer.pointer + buffer.length));
+ resource = (struct acpi_resource *)buffer.pointer;
+ buffer_end = ACPI_CAST_PTR(struct acpi_resource,
+ ((u8 *) buffer.pointer + buffer.length));
/* Walk the resource list */
@@ -291,7 +273,7 @@ acpi_walk_resources (
break;
}
- status = user_function (resource, context);
+ status = user_function(resource, context);
switch (status) {
case AE_OK:
@@ -318,7 +300,7 @@ acpi_walk_resources (
/* Get the next resource descriptor */
- resource = ACPI_NEXT_RESOURCE (resource);
+ resource = ACPI_NEXT_RESOURCE(resource);
/* Check for end-of-buffer */
@@ -327,13 +309,13 @@ acpi_walk_resources (
}
}
-cleanup:
+ cleanup:
- acpi_os_free (buffer.pointer);
- return_ACPI_STATUS (status);
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_resources);
+EXPORT_SYMBOL(acpi_walk_resources);
/*******************************************************************************
*
@@ -354,30 +336,25 @@ EXPORT_SYMBOL(acpi_walk_resources);
******************************************************************************/
acpi_status
-acpi_set_current_resources (
- acpi_handle device_handle,
- struct acpi_buffer *in_buffer)
+acpi_set_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *in_buffer)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_set_current_resources");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_set_current_resources");
/* Must have a valid handle and buffer */
- if ((!device_handle) ||
- (!in_buffer) ||
- (!in_buffer->pointer) ||
- (!in_buffer->length)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((!device_handle) ||
+ (!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_rs_set_srs_method_data (device_handle, in_buffer);
- return_ACPI_STATUS (status);
+ status = acpi_rs_set_srs_method_data(device_handle, in_buffer);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_current_resources);
+EXPORT_SYMBOL(acpi_set_current_resources);
/******************************************************************************
*
@@ -398,41 +375,38 @@ EXPORT_SYMBOL(acpi_set_current_resources);
******************************************************************************/
acpi_status
-acpi_resource_to_address64 (
- struct acpi_resource *resource,
- struct acpi_resource_address64 *out)
+acpi_resource_to_address64(struct acpi_resource *resource,
+ struct acpi_resource_address64 *out)
{
- struct acpi_resource_address16 *address16;
- struct acpi_resource_address32 *address32;
-
+ struct acpi_resource_address16 *address16;
+ struct acpi_resource_address32 *address32;
switch (resource->id) {
case ACPI_RSTYPE_ADDRESS16:
- address16 = (struct acpi_resource_address16 *) &resource->data;
- ACPI_COPY_ADDRESS (out, address16);
+ address16 = (struct acpi_resource_address16 *)&resource->data;
+ ACPI_COPY_ADDRESS(out, address16);
break;
-
case ACPI_RSTYPE_ADDRESS32:
- address32 = (struct acpi_resource_address32 *) &resource->data;
- ACPI_COPY_ADDRESS (out, address32);
+ address32 = (struct acpi_resource_address32 *)&resource->data;
+ ACPI_COPY_ADDRESS(out, address32);
break;
-
case ACPI_RSTYPE_ADDRESS64:
/* Simple copy for 64 bit source */
- ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64));
+ ACPI_MEMCPY(out, &resource->data,
+ sizeof(struct acpi_resource_address64));
break;
-
default:
return (AE_BAD_PARAMETER);
}
return (AE_OK);
}
+
EXPORT_SYMBOL(acpi_resource_to_address64);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index cbcda30c172d..c6db591479de 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -9,14 +9,10 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("scan")
-
+ACPI_MODULE_NAME("scan")
#define STRUCT_TO_INT(s) (*((int*)&s))
-
-extern struct acpi_device *acpi_root;
-
+extern struct acpi_device *acpi_root;
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "ACPI_BUS"
@@ -27,13 +23,11 @@ static LIST_HEAD(acpi_device_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
-static int
-acpi_bus_trim(struct acpi_device *start,
- int rmdevice);
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice);
-static void acpi_device_release(struct kobject * kobj)
+static void acpi_device_release(struct kobject *kobj)
{
- struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
+ struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
if (dev->pnp.cid_list)
kfree(dev->pnp.cid_list);
kfree(dev);
@@ -41,34 +35,34 @@ static void acpi_device_release(struct kobject * kobj)
struct acpi_device_attribute {
struct attribute attr;
- ssize_t (*show)(struct acpi_device *, char *);
- ssize_t (*store)(struct acpi_device *, const char *, size_t);
+ ssize_t(*show) (struct acpi_device *, char *);
+ ssize_t(*store) (struct acpi_device *, const char *, size_t);
};
typedef void acpi_device_sysfs_files(struct kobject *,
- const struct attribute *);
+ const struct attribute *);
static void setup_sys_fs_device_files(struct acpi_device *dev,
- acpi_device_sysfs_files *func);
+ acpi_device_sysfs_files * func);
#define create_sysfs_device_files(dev) \
setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
#define remove_sysfs_device_files(dev) \
setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file)
-
#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr);
static ssize_t acpi_device_attr_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ struct attribute *attr, char *buf)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
return attribute->show ? attribute->show(device, buf) : -EIO;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t len)
+ struct attribute *attr, const char *buf,
+ size_t len)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
@@ -76,13 +70,13 @@ static ssize_t acpi_device_attr_store(struct kobject *kobj,
}
static struct sysfs_ops acpi_device_sysfs_ops = {
- .show = acpi_device_attr_show,
- .store = acpi_device_attr_store,
+ .show = acpi_device_attr_show,
+ .store = acpi_device_attr_store,
};
static struct kobj_type ktype_acpi_ns = {
- .sysfs_ops = &acpi_device_sysfs_ops,
- .release = acpi_device_release,
+ .sysfs_ops = &acpi_device_sysfs_ops,
+ .release = acpi_device_release,
};
static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
@@ -110,16 +104,16 @@ static struct kset_hotplug_ops namespace_hotplug_ops = {
};
static struct kset acpi_namespace_kset = {
- .kobj = {
- .name = "namespace",
- },
+ .kobj = {
+ .name = "namespace",
+ },
.subsys = &acpi_subsys,
- .ktype = &ktype_acpi_ns,
+ .ktype = &ktype_acpi_ns,
.hotplug_ops = &namespace_hotplug_ops,
};
-
-static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
+static void acpi_device_register(struct acpi_device *device,
+ struct acpi_device *parent)
{
/*
* Linkage
@@ -134,14 +128,14 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
spin_lock(&acpi_device_lock);
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
- list_add_tail(&device->g_list,&device->parent->g_list);
+ list_add_tail(&device->g_list, &device->parent->g_list);
} else
- list_add_tail(&device->g_list,&acpi_device_list);
+ list_add_tail(&device->g_list, &acpi_device_list);
if (device->wakeup.flags.valid)
- list_add_tail(&device->wakeup_list,&acpi_wakeup_device_list);
+ list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
spin_unlock(&acpi_device_lock);
- strlcpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
+ strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN);
if (parent)
device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns;
@@ -150,10 +144,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
create_sysfs_device_files(device);
}
-static int
-acpi_device_unregister (
- struct acpi_device *device,
- int type)
+static int acpi_device_unregister(struct acpi_device *device, int type)
{
spin_lock(&acpi_device_lock);
if (device->parent) {
@@ -172,11 +163,7 @@ acpi_device_unregister (
return 0;
}
-void
-acpi_bus_data_handler (
- acpi_handle handle,
- u32 function,
- void *context)
+void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
{
ACPI_FUNCTION_TRACE("acpi_bus_data_handler");
@@ -185,13 +172,11 @@ acpi_bus_data_handler (
return_VOID;
}
-static int
-acpi_bus_get_power_flags (
- struct acpi_device *device)
+static int acpi_bus_get_power_flags(struct acpi_device *device)
{
- acpi_status status = 0;
- acpi_handle handle = NULL;
- u32 i = 0;
+ acpi_status status = 0;
+ acpi_handle handle = NULL;
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags");
@@ -210,11 +195,11 @@ acpi_bus_get_power_flags (
*/
for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
struct acpi_device_power_state *ps = &device->power.states[i];
- char object_name[5] = {'_','P','R','0'+i,'\0'};
+ char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
/* Evaluate "_PRx" to se if power resources are referenced */
acpi_evaluate_reference(device->handle, object_name, NULL,
- &ps->resources);
+ &ps->resources);
if (ps->resources.count) {
device->power.flags.power_resources = 1;
ps->flags.valid = 1;
@@ -232,7 +217,7 @@ acpi_bus_get_power_flags (
if (ps->resources.count || ps->flags.explicit_set)
ps->flags.valid = 1;
- ps->power = -1; /* Unknown - driver assigned */
+ ps->power = -1; /* Unknown - driver assigned */
ps->latency = -1; /* Unknown - driver assigned */
}
@@ -249,13 +234,10 @@ acpi_bus_get_power_flags (
return_VALUE(0);
}
-int
-acpi_match_ids (
- struct acpi_device *device,
- char *ids)
+int acpi_match_ids(struct acpi_device *device, char *ids)
{
int error = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (device->flags.hardware_id)
if (strstr(ids, device->pnp.hardware_id))
@@ -266,27 +248,25 @@ acpi_match_ids (
int i;
/* compare multiple _CID entries against driver ids */
- for (i = 0; i < cid_list->count; i++)
- {
+ for (i = 0; i < cid_list->count; i++) {
if (strstr(ids, cid_list->id[i].value))
goto Done;
}
}
error = -ENOENT;
- Done:
+ Done:
if (buffer.pointer)
acpi_os_free(buffer.pointer);
return error;
}
static acpi_status
-acpi_bus_extract_wakeup_device_power_package (
- struct acpi_device *device,
- union acpi_object *package)
+acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
+ union acpi_object *package)
{
- int i = 0;
- union acpi_object *element = NULL;
+ int i = 0;
+ union acpi_object *element = NULL;
if (!device || !package || (package->package.count < 2))
return AE_BAD_PARAMETER;
@@ -296,14 +276,17 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_BAD_PARAMETER;
if (element->type == ACPI_TYPE_PACKAGE) {
if ((element->package.count < 2) ||
- (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) ||
- (element->package.elements[1].type != ACPI_TYPE_INTEGER))
+ (element->package.elements[0].type !=
+ ACPI_TYPE_LOCAL_REFERENCE)
+ || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
return AE_BAD_DATA;
- device->wakeup.gpe_device = element->package.elements[0].reference.handle;
- device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value;
- }else if (element->type == ACPI_TYPE_INTEGER) {
+ device->wakeup.gpe_device =
+ element->package.elements[0].reference.handle;
+ device->wakeup.gpe_number =
+ (u32) element->package.elements[1].integer.value;
+ } else if (element->type == ACPI_TYPE_INTEGER) {
device->wakeup.gpe_number = element->integer.value;
- }else
+ } else
return AE_BAD_DATA;
element = &(package->package.elements[1]);
@@ -316,9 +299,9 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_NO_MEMORY;
}
device->wakeup.resources.count = package->package.count - 2;
- for (i=0; i < device->wakeup.resources.count; i++) {
+ for (i = 0; i < device->wakeup.resources.count; i++) {
element = &(package->package.elements[i + 2]);
- if (element->type != ACPI_TYPE_ANY ) {
+ if (element->type != ACPI_TYPE_ANY) {
return AE_BAD_DATA;
}
@@ -328,13 +311,11 @@ acpi_bus_extract_wakeup_device_power_package (
return AE_OK;
}
-static int
-acpi_bus_get_wakeup_device_flags (
- struct acpi_device *device)
+static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
{
- acpi_status status = 0;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *package = NULL;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *package = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
@@ -345,21 +326,22 @@ acpi_bus_get_wakeup_device_flags (
goto end;
}
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
status = acpi_bus_extract_wakeup_device_power_package(device, package);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error extracting _PRW package\n"));
goto end;
}
acpi_os_free(buffer.pointer);
device->wakeup.flags.valid = 1;
- /* Power button, Lid switch always enable wakeup*/
+ /* Power button, Lid switch always enable wakeup */
if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
device->wakeup.flags.run_wake = 1;
-end:
+ end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
return_VALUE(0);
@@ -368,8 +350,8 @@ end:
/* --------------------------------------------------------------------------
ACPI hotplug sysfs device file support
-------------------------------------------------------------------------- */
-static ssize_t acpi_eject_store(struct acpi_device *device,
- const char *buf, size_t count);
+static ssize_t acpi_eject_store(struct acpi_device *device,
+ const char *buf, size_t count);
#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
static struct acpi_device_attribute acpi_device_attr_##_name = \
@@ -383,12 +365,11 @@ ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
* @func: function pointer to create or destroy the device file
*/
static void
-setup_sys_fs_device_files (
- struct acpi_device *dev,
- acpi_device_sysfs_files *func)
+setup_sys_fs_device_files(struct acpi_device *dev,
+ acpi_device_sysfs_files * func)
{
- acpi_status status;
- acpi_handle temp = NULL;
+ acpi_status status;
+ acpi_handle temp = NULL;
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
@@ -396,11 +377,10 @@ setup_sys_fs_device_files (
*/
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
- (*(func))(&dev->kobj,&acpi_device_attr_eject.attr);
+ (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr);
}
-static int
-acpi_eject_operation(acpi_handle handle, int lockable)
+static int acpi_eject_operation(acpi_handle handle, int lockable)
{
struct acpi_object_list arg_list;
union acpi_object arg;
@@ -429,27 +409,25 @@ acpi_eject_operation(acpi_handle handle, int lockable)
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) {
- return(-ENODEV);
+ return (-ENODEV);
}
- return(0);
+ return (0);
}
-
static ssize_t
acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
{
- int result;
- int ret = count;
- int islockable;
- acpi_status status;
- acpi_handle handle;
- acpi_object_type type = 0;
+ int result;
+ int ret = count;
+ int islockable;
+ acpi_status status;
+ acpi_handle handle;
+ acpi_object_type type = 0;
if ((!count) || (buf[0] != '1')) {
return -EINVAL;
}
-
#ifndef FORCE_EJECT
if (device->driver == NULL) {
ret = -ENODEV;
@@ -457,7 +435,7 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
}
#endif
status = acpi_get_type(device->handle, &type);
- if (ACPI_FAILURE(status) || (!device->flags.ejectable) ) {
+ if (ACPI_FAILURE(status) || (!device->flags.ejectable)) {
ret = -ENODEV;
goto err;
}
@@ -476,18 +454,15 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
if (result) {
ret = -EBUSY;
}
-err:
+ err:
return ret;
}
-
/* --------------------------------------------------------------------------
Performance Management
-------------------------------------------------------------------------- */
-static int
-acpi_bus_get_perf_flags (
- struct acpi_device *device)
+static int acpi_bus_get_perf_flags(struct acpi_device *device)
{
device->performance.state = ACPI_STATE_UNKNOWN;
return 0;
@@ -500,7 +475,6 @@ acpi_bus_get_perf_flags (
static LIST_HEAD(acpi_bus_drivers);
static DECLARE_MUTEX(acpi_bus_drivers_lock);
-
/**
* acpi_bus_match
* --------------
@@ -508,16 +482,13 @@ static DECLARE_MUTEX(acpi_bus_drivers_lock);
* matches the specified driver's criteria.
*/
static int
-acpi_bus_match (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
if (driver && driver->ops.match)
return driver->ops.match(device, driver);
return acpi_match_ids(device, driver->ids);
}
-
/**
* acpi_bus_driver_init
* --------------------
@@ -525,11 +496,9 @@ acpi_bus_match (
* driver is bound to a device. Invokes the driver's add() and start() ops.
*/
static int
-acpi_bus_driver_init (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_bus_driver_init");
@@ -553,13 +522,12 @@ acpi_bus_driver_init (
* upon possible configuration and currently allocated resources.
*/
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Driver successfully bound to device\n"));
return_VALUE(0);
}
-int
-acpi_start_single_object (
- struct acpi_device *device)
+static int acpi_start_single_object(struct acpi_device *device)
{
int result = 0;
struct acpi_driver *driver;
@@ -578,16 +546,17 @@ acpi_start_single_object (
return_VALUE(result);
}
-static int acpi_driver_attach(struct acpi_driver * drv)
+static int acpi_driver_attach(struct acpi_driver *drv)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
int count = 0;
ACPI_FUNCTION_TRACE("acpi_driver_attach");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, g_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, g_list);
if (dev->driver || !dev->status.present)
continue;
@@ -598,7 +567,8 @@ static int acpi_driver_attach(struct acpi_driver * drv)
acpi_start_single_object(dev);
atomic_inc(&drv->references);
count++;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found driver [%s] for device [%s]\n",
drv->name, dev->pnp.bus_id));
}
}
@@ -608,20 +578,21 @@ static int acpi_driver_attach(struct acpi_driver * drv)
return_VALUE(count);
}
-static int acpi_driver_detach(struct acpi_driver * drv)
+static int acpi_driver_detach(struct acpi_driver *drv)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_driver_detach");
spin_lock(&acpi_device_lock);
- list_for_each_safe(node,next,&acpi_device_list) {
- struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
+ list_for_each_safe(node, next, &acpi_device_list) {
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, g_list);
if (dev->driver == drv) {
spin_unlock(&acpi_device_lock);
if (drv->ops.remove)
- drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
+ drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL);
spin_lock(&acpi_device_lock);
dev->driver = NULL;
dev->driver_data = NULL;
@@ -640,9 +611,7 @@ static int acpi_driver_detach(struct acpi_driver * drv)
* number of devices that were claimed by the driver, or a negative
* error status for failure.
*/
-int
-acpi_bus_register_driver (
- struct acpi_driver *driver)
+int acpi_bus_register_driver(struct acpi_driver *driver)
{
int count;
@@ -661,8 +630,8 @@ acpi_bus_register_driver (
return_VALUE(count);
}
-EXPORT_SYMBOL(acpi_bus_register_driver);
+EXPORT_SYMBOL(acpi_bus_register_driver);
/**
* acpi_bus_unregister_driver
@@ -670,9 +639,7 @@ EXPORT_SYMBOL(acpi_bus_register_driver);
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
*/
-int
-acpi_bus_unregister_driver (
- struct acpi_driver *driver)
+int acpi_bus_unregister_driver(struct acpi_driver *driver)
{
int error = 0;
@@ -685,11 +652,12 @@ acpi_bus_unregister_driver (
spin_lock(&acpi_device_lock);
list_del_init(&driver->node);
spin_unlock(&acpi_device_lock);
- }
- } else
+ }
+ } else
error = -EINVAL;
return_VALUE(error);
}
+
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/**
@@ -698,18 +666,17 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver);
* Parses the list of registered drivers looking for a driver applicable for
* the specified device.
*/
-static int
-acpi_bus_find_driver (
- struct acpi_device *device)
+static int acpi_bus_find_driver(struct acpi_device *device)
{
- int result = 0;
- struct list_head * node, *next;
+ int result = 0;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_bus_find_driver");
spin_lock(&acpi_device_lock);
- list_for_each_safe(node,next,&acpi_bus_drivers) {
- struct acpi_driver * driver = container_of(node,struct acpi_driver,node);
+ list_for_each_safe(node, next, &acpi_bus_drivers) {
+ struct acpi_driver *driver =
+ container_of(node, struct acpi_driver, node);
atomic_inc(&driver->references);
spin_unlock(&acpi_device_lock);
@@ -723,21 +690,18 @@ acpi_bus_find_driver (
}
spin_unlock(&acpi_device_lock);
- Done:
+ Done:
return_VALUE(result);
}
-
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
-static int
-acpi_bus_get_flags (
- struct acpi_device *device)
+static int acpi_bus_get_flags(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- acpi_handle temp = NULL;
+ acpi_status status = AE_OK;
+ acpi_handle temp = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_get_flags");
@@ -788,11 +752,12 @@ acpi_bus_get_flags (
return_VALUE(0);
}
-static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_busid(struct acpi_device *device,
+ acpi_handle handle, int type)
{
- char bus_id[5] = {'?',0};
- struct acpi_buffer buffer = {sizeof(bus_id), bus_id};
- int i = 0;
+ char bus_id[5] = { '?', 0 };
+ struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
+ int i = 0;
/*
* Bus ID
@@ -824,21 +789,22 @@ static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handl
}
}
-static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent,
- acpi_handle handle, int type)
+static void acpi_device_set_id(struct acpi_device *device,
+ struct acpi_device *parent, acpi_handle handle,
+ int type)
{
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- char *hid = NULL;
- char *uid = NULL;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ char *hid = NULL;
+ char *uid = NULL;
struct acpi_compatible_id_list *cid_list = NULL;
- acpi_status status;
+ acpi_status status;
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
status = acpi_get_object_info(handle, &buffer);
if (ACPI_FAILURE(status)) {
- printk("%s: Error reading device info\n",__FUNCTION__);
+ printk("%s: Error reading device info\n", __FUNCTION__);
return;
}
@@ -904,7 +870,7 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device *
acpi_os_free(buffer.pointer);
}
-static int acpi_device_set_context(struct acpi_device * device, int type)
+static int acpi_device_set_context(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
int result = 0;
@@ -916,10 +882,10 @@ static int acpi_device_set_context(struct acpi_device * device, int type)
* to be careful with fixed-feature devices as they all attach to the
* root object.
*/
- if (type != ACPI_BUS_TYPE_POWER_BUTTON &&
+ if (type != ACPI_BUS_TYPE_POWER_BUTTON &&
type != ACPI_BUS_TYPE_SLEEP_BUTTON) {
status = acpi_attach_data(device->handle,
- acpi_bus_data_handler, device);
+ acpi_bus_data_handler, device);
if (ACPI_FAILURE(status)) {
printk("Error attaching device data\n");
@@ -929,12 +895,13 @@ static int acpi_device_set_context(struct acpi_device * device, int type)
return result;
}
-static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_debug_info(struct acpi_device *device,
+ acpi_handle handle, int type)
{
#ifdef CONFIG_ACPI_DEBUG_OUTPUT
- char *type_string = NULL;
- char name[80] = {'?','\0'};
- struct acpi_buffer buffer = {sizeof(name), name};
+ char *type_string = NULL;
+ char name[80] = { '?', '\0' };
+ struct acpi_buffer buffer = { sizeof(name), name };
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
@@ -968,18 +935,14 @@ static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle
}
printk(KERN_DEBUG "Found %s %s [%p]\n", type_string, name, handle);
-#endif /*CONFIG_ACPI_DEBUG_OUTPUT*/
+#endif /*CONFIG_ACPI_DEBUG_OUTPUT */
}
-
-static int
-acpi_bus_remove (
- struct acpi_device *dev,
- int rmdevice)
+static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
{
- int result = 0;
- struct acpi_driver *driver;
-
+ int result = 0;
+ struct acpi_driver *driver;
+
ACPI_FUNCTION_TRACE("acpi_bus_remove");
if (!dev)
@@ -1012,22 +975,18 @@ acpi_bus_remove (
if ((dev->parent) && (dev->parent->ops.unbind))
dev->parent->ops.unbind(dev);
}
-
+
acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
return_VALUE(0);
}
-
static int
-acpi_add_single_object (
- struct acpi_device **child,
- struct acpi_device *parent,
- acpi_handle handle,
- int type)
+acpi_add_single_object(struct acpi_device **child,
+ struct acpi_device *parent, acpi_handle handle, int type)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_add_single_object");
@@ -1044,7 +1003,7 @@ acpi_add_single_object (
device->handle = handle;
device->parent = parent;
- acpi_device_get_busid(device,handle,type);
+ acpi_device_get_busid(device, handle, type);
/*
* Flags
@@ -1092,7 +1051,7 @@ acpi_add_single_object (
* Hardware ID, Unique ID, & Bus Address
* -------------------------------------
*/
- acpi_device_set_id(device,parent,handle,type);
+ acpi_device_set_id(device, parent, handle, type);
/*
* Power Management
@@ -1104,7 +1063,7 @@ acpi_add_single_object (
goto end;
}
- /*
+ /*
* Wakeup device management
*-----------------------
*/
@@ -1124,12 +1083,12 @@ acpi_add_single_object (
goto end;
}
- if ((result = acpi_device_set_context(device,type)))
+ if ((result = acpi_device_set_context(device, type)))
goto end;
- acpi_device_get_debug_info(device,handle,type);
+ acpi_device_get_debug_info(device, handle, type);
- acpi_device_register(device,parent);
+ acpi_device_register(device, parent);
/*
* Bind _ADR-Based Devices
@@ -1154,7 +1113,7 @@ acpi_add_single_object (
*/
result = acpi_bus_find_driver(device);
-end:
+ end:
if (!result)
*child = device;
else {
@@ -1166,17 +1125,15 @@ end:
return_VALUE(result);
}
-
-static int acpi_bus_scan (struct acpi_device *start,
- struct acpi_bus_ops *ops)
+static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
{
- acpi_status status = AE_OK;
- struct acpi_device *parent = NULL;
- struct acpi_device *child = NULL;
- acpi_handle phandle = NULL;
- acpi_handle chandle = NULL;
- acpi_object_type type = 0;
- u32 level = 1;
+ acpi_status status = AE_OK;
+ struct acpi_device *parent = NULL;
+ struct acpi_device *child = NULL;
+ acpi_handle phandle = NULL;
+ acpi_handle chandle = NULL;
+ acpi_object_type type = 0;
+ u32 level = 1;
ACPI_FUNCTION_TRACE("acpi_bus_scan");
@@ -1185,7 +1142,7 @@ static int acpi_bus_scan (struct acpi_device *start,
parent = start;
phandle = start->handle;
-
+
/*
* Parse through the ACPI namespace, identify all 'devices', and
* create a new 'struct acpi_device' for each.
@@ -1193,7 +1150,7 @@ static int acpi_bus_scan (struct acpi_device *start,
while ((level > 0) && parent) {
status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
- chandle, &chandle);
+ chandle, &chandle);
/*
* If this scope is exhausted then move our way back up.
@@ -1243,12 +1200,12 @@ static int acpi_bus_scan (struct acpi_device *start,
if (ops->acpi_op_add)
status = acpi_add_single_object(&child, parent,
- chandle, type);
- else
+ chandle, type);
+ else
status = acpi_bus_get_device(chandle, &child);
- if (ACPI_FAILURE(status))
- continue;
+ if (ACPI_FAILURE(status))
+ continue;
if (ops->acpi_op_start) {
status = acpi_start_single_object(child);
@@ -1264,7 +1221,7 @@ static int acpi_bus_scan (struct acpi_device *start,
* which will be enumerated when the parent is inserted).
*
* TBD: Need notifications and other detection mechanisms
- * in place before we can fully implement this.
+ * in place before we can fully implement this.
*/
if (child->status.present) {
status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
@@ -1282,11 +1239,8 @@ static int acpi_bus_scan (struct acpi_device *start,
}
int
-acpi_bus_add (
- struct acpi_device **child,
- struct acpi_device *parent,
- acpi_handle handle,
- int type)
+acpi_bus_add(struct acpi_device **child,
+ struct acpi_device *parent, acpi_handle handle, int type)
{
int result;
struct acpi_bus_ops ops;
@@ -1301,11 +1255,10 @@ acpi_bus_add (
}
return_VALUE(result);
}
+
EXPORT_SYMBOL(acpi_bus_add);
-int
-acpi_bus_start (
- struct acpi_device *device)
+int acpi_bus_start(struct acpi_device *device)
{
int result;
struct acpi_bus_ops ops;
@@ -1323,26 +1276,25 @@ acpi_bus_start (
}
return_VALUE(result);
}
+
EXPORT_SYMBOL(acpi_bus_start);
-static int
-acpi_bus_trim(struct acpi_device *start,
- int rmdevice)
+static int acpi_bus_trim(struct acpi_device *start, int rmdevice)
{
- acpi_status status;
- struct acpi_device *parent, *child;
- acpi_handle phandle, chandle;
- acpi_object_type type;
- u32 level = 1;
- int err = 0;
-
- parent = start;
+ acpi_status status;
+ struct acpi_device *parent, *child;
+ acpi_handle phandle, chandle;
+ acpi_object_type type;
+ u32 level = 1;
+ int err = 0;
+
+ parent = start;
phandle = start->handle;
child = chandle = NULL;
while ((level > 0) && parent && (!err)) {
status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
- chandle, &chandle);
+ chandle, &chandle);
/*
* If this scope is exhausted then move our way back up.
@@ -1381,12 +1333,10 @@ acpi_bus_trim(struct acpi_device *start,
return err;
}
-static int
-acpi_bus_scan_fixed (
- struct acpi_device *root)
+static int acpi_bus_scan_fixed(struct acpi_device *root)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");
@@ -1398,14 +1348,16 @@ acpi_bus_scan_fixed (
*/
if (acpi_fadt.pwr_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
- NULL, ACPI_BUS_TYPE_POWER_BUTTON);
+ NULL,
+ ACPI_BUS_TYPE_POWER_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}
if (acpi_fadt.sleep_button == 0) {
result = acpi_add_single_object(&device, acpi_root,
- NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
+ NULL,
+ ACPI_BUS_TYPE_SLEEP_BUTTON);
if (!result)
result = acpi_start_single_object(device);
}
@@ -1413,7 +1365,6 @@ acpi_bus_scan_fixed (
return_VALUE(result);
}
-
static int __init acpi_scan_init(void)
{
int result;
@@ -1430,7 +1381,7 @@ static int __init acpi_scan_init(void)
* Create the root device in the bus's device tree
*/
result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
- ACPI_BUS_TYPE_SYSTEM);
+ ACPI_BUS_TYPE_SYSTEM);
if (result)
goto Done;
@@ -1450,7 +1401,7 @@ static int __init acpi_scan_init(void)
if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
- Done:
+ Done:
return_VALUE(result);
}
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 7249ba2b7a27..930427fc0c4b 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -23,7 +23,6 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
static struct pm_ops acpi_pm_ops;
-extern void do_suspend_lowlevel_s4bios(void);
extern void do_suspend_lowlevel(void);
static u32 acpi_suspend_states[] = {
@@ -98,8 +97,6 @@ static int acpi_pm_enter(suspend_state_t pm_state)
case PM_SUSPEND_DISK:
if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM)
status = acpi_enter_sleep_state(acpi_state);
- else
- do_suspend_lowlevel_s4bios();
break;
case PM_SUSPEND_MAX:
acpi_power_off();
@@ -161,7 +158,15 @@ int acpi_suspend(u32 acpi_state)
return -EINVAL;
}
+static int acpi_pm_state_valid(suspend_state_t pm_state)
+{
+ u32 acpi_state = acpi_suspend_states[pm_state];
+
+ return sleep_states[acpi_state];
+}
+
static struct pm_ops acpi_pm_ops = {
+ .valid = acpi_pm_state_valid,
.prepare = acpi_pm_prepare,
.enter = acpi_pm_enter,
.finish = acpi_pm_finish,
@@ -206,11 +211,6 @@ static int __init acpi_sleep_init(void)
printk(" S%d", i);
}
if (i == ACPI_STATE_S4) {
- if (acpi_gbl_FACS->S4bios_f) {
- sleep_states[i] = 1;
- printk(" S4bios");
- acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
- }
if (sleep_states[i])
acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
}
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index 186b182c5825..af7935a95bcc 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -21,9 +21,7 @@ int acpi_sleep_prepare(u32 acpi_state)
{
#ifdef CONFIG_ACPI_SLEEP
/* do we have a wakeup address for S2 and S3? */
- /* Here, we support only S4BIOS, those we set the wakeup address */
- /* S4OS is only supported for now via swsusp.. */
- if (acpi_state == ACPI_STATE_S3 || acpi_state == ACPI_STATE_S4) {
+ if (acpi_state == ACPI_STATE_S3) {
if (!acpi_wakeup_address) {
return -EFAULT;
}
@@ -55,7 +53,11 @@ void acpi_power_off(void)
static int acpi_shutdown(struct sys_device *x)
{
- return acpi_sleep_prepare(ACPI_STATE_S5);
+ if (system_state == SYSTEM_POWER_OFF) {
+ /* Prepare if we are going to power off the system */
+ return acpi_sleep_prepare(ACPI_STATE_S5);
+ }
+ return 0;
}
static struct sysdev_class acpi_sysclass = {
@@ -91,4 +93,4 @@ static int acpi_poweroff_init(void)
late_initcall(acpi_poweroff_init);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM */
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 1be99f0996d6..4696a85a98b9 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -13,29 +13,18 @@
#include "sleep.h"
-#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
-#define ACPI_SYSTEM_FILE_SLEEP "sleep"
-#endif
-
-#define ACPI_SYSTEM_FILE_ALARM "alarm"
-#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE "wakeup"
-
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("sleep")
-
+ACPI_MODULE_NAME("sleep")
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
-
static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{
- int i;
+ int i;
ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show");
for (i = 0; i <= ACPI_STATE_S5; i++) {
if (sleep_states[i]) {
- seq_printf(seq,"S%d ", i);
- if (i == ACPI_STATE_S4 && acpi_gbl_FACS->S4bios_f)
- seq_printf(seq, "S4bios ");
+ seq_printf(seq, "S%d ", i);
}
}
@@ -50,24 +39,21 @@ static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_system_write_sleep (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_sleep(struct file *file,
+ const char __user * buffer, size_t count, loff_t * ppos)
{
- char str[12];
- u32 state = 0;
- int error = 0;
+ char str[12];
+ u32 state = 0;
+ int error = 0;
if (count > sizeof(str) - 1)
goto Done;
- memset(str,0,sizeof(str));
+ memset(str, 0, sizeof(str));
if (copy_from_user(str, buffer, count))
return -EFAULT;
/* Check for S4 bios request */
- if (!strcmp(str,"4b")) {
+ if (!strcmp(str, "4b")) {
error = acpi_suspend(4);
goto Done;
}
@@ -79,17 +65,17 @@ acpi_system_write_sleep (
}
#endif
error = acpi_suspend(state);
- Done:
+ Done:
return error ? error : count;
}
-#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
+#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
{
- u32 sec, min, hr;
- u32 day, mo, yr;
- unsigned char rtc_control = 0;
- unsigned long flags;
+ u32 sec, min, hr;
+ u32 day, mo, yr;
+ unsigned char rtc_control = 0;
+ unsigned long flags;
ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
@@ -105,13 +91,14 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
/* ACPI spec: only low 6 its should be cared */
day = CMOS_READ(acpi_gbl_FADT->day_alrm) & 0x3F;
else
- day = CMOS_READ(RTC_DAY_OF_MONTH);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
if (acpi_gbl_FADT->mon_alrm)
mo = CMOS_READ(acpi_gbl_FADT->mon_alrm);
else
mo = CMOS_READ(RTC_MONTH);
if (acpi_gbl_FADT->century)
- yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR);
+ yr = CMOS_READ(acpi_gbl_FADT->century) * 100 +
+ CMOS_READ(RTC_YEAR);
else
yr = CMOS_READ(RTC_YEAR);
@@ -126,33 +113,33 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
BCD_TO_BIN(yr);
}
- /* we're trusting the FADT (see above)*/
+ /* we're trusting the FADT (see above) */
if (!acpi_gbl_FADT->century)
- /* If we're not trusting the FADT, we should at least make it
- * right for _this_ century... ehm, what is _this_ century?
- *
- * TBD:
- * ASAP: find piece of code in the kernel, e.g. star tracker driver,
- * which we can trust to determine the century correctly. Atom
- * watch driver would be nice, too...
- *
- * if that has not happened, change for first release in 2050:
- * if (yr<50)
- * yr += 2100;
- * else
- * yr += 2000; // current line of code
- *
- * if that has not happened either, please do on 2099/12/31:23:59:59
- * s/2000/2100
- *
- */
+ /* If we're not trusting the FADT, we should at least make it
+ * right for _this_ century... ehm, what is _this_ century?
+ *
+ * TBD:
+ * ASAP: find piece of code in the kernel, e.g. star tracker driver,
+ * which we can trust to determine the century correctly. Atom
+ * watch driver would be nice, too...
+ *
+ * if that has not happened, change for first release in 2050:
+ * if (yr<50)
+ * yr += 2100;
+ * else
+ * yr += 2000; // current line of code
+ *
+ * if that has not happened either, please do on 2099/12/31:23:59:59
+ * s/2000/2100
+ *
+ */
yr += 2000;
- seq_printf(seq,"%4.4u-", yr);
- (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
- (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
- (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
- (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
+ seq_printf(seq, "%4.4u-", yr);
+ (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
+ (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
+ (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
+ (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
(sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
return 0;
@@ -163,15 +150,11 @@ static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
}
-
-static int
-get_date_field (
- char **p,
- u32 *value)
+static int get_date_field(char **p, u32 * value)
{
- char *next = NULL;
- char *string_end = NULL;
- int result = -EINVAL;
+ char *next = NULL;
+ char *string_end = NULL;
+ int result = -EINVAL;
/*
* Try to find delimeter, only to insert null. The end of the
@@ -193,26 +176,22 @@ get_date_field (
return result;
}
-
static ssize_t
-acpi_system_write_alarm (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_alarm(struct file *file,
+ const char __user * buffer, size_t count, loff_t * ppos)
{
- int result = 0;
- char alarm_string[30] = {'\0'};
- char *p = alarm_string;
- u32 sec, min, hr, day, mo, yr;
- int adjust = 0;
- unsigned char rtc_control = 0;
+ int result = 0;
+ char alarm_string[30] = { '\0' };
+ char *p = alarm_string;
+ u32 sec, min, hr, day, mo, yr;
+ int adjust = 0;
+ unsigned char rtc_control = 0;
ACPI_FUNCTION_TRACE("acpi_system_write_alarm");
if (count > sizeof(alarm_string) - 1)
return_VALUE(-EINVAL);
-
+
if (copy_from_user(alarm_string, buffer, count))
return_VALUE(-EFAULT);
@@ -271,10 +250,10 @@ acpi_system_write_alarm (
}
if (adjust) {
- yr += CMOS_READ(RTC_YEAR);
- mo += CMOS_READ(RTC_MONTH);
+ yr += CMOS_READ(RTC_YEAR);
+ mo += CMOS_READ(RTC_MONTH);
day += CMOS_READ(RTC_DAY_OF_MONTH);
- hr += CMOS_READ(RTC_HOURS);
+ hr += CMOS_READ(RTC_HOURS);
min += CMOS_READ(RTC_MINUTES);
sec += CMOS_READ(RTC_SECONDS);
}
@@ -343,7 +322,7 @@ acpi_system_write_alarm (
if (acpi_gbl_FADT->mon_alrm)
CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm);
if (acpi_gbl_FADT->century)
- CMOS_WRITE(yr/100, acpi_gbl_FADT->century);
+ CMOS_WRITE(yr / 100, acpi_gbl_FADT->century);
/* enable the rtc alarm interrupt */
rtc_control |= RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
@@ -357,35 +336,33 @@ acpi_system_write_alarm (
*ppos += count;
result = 0;
-end:
+ end:
return_VALUE(result ? result : count);
}
-extern struct list_head acpi_wakeup_device_list;
+extern struct list_head acpi_wakeup_device_list;
extern spinlock_t acpi_device_lock;
static int
acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
seq_printf(seq, "Device Sleep state Status\n");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
spin_unlock(&acpi_device_lock);
- if (dev->wakeup.flags.run_wake)
- seq_printf(seq, "%4s %4d %8s\n",
- dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
- dev->wakeup.state.enabled ? "*enabled" : "*disabled");
- else
- seq_printf(seq, "%4s %4d %8s\n",
- dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
- dev->wakeup.state.enabled ? "enabled" : "disabled");
+ seq_printf(seq, "%4s %4d %s%8s\n",
+ dev->pnp.bus_id,
+ (u32) dev->wakeup.sleep_state,
+ dev->wakeup.flags.run_wake ? "*" : "",
+ dev->wakeup.state.enabled ? "enabled" : "disabled");
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
@@ -393,19 +370,18 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
}
static ssize_t
-acpi_system_write_wakeup_device (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_write_wakeup_device(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct list_head * node, * next;
- char strbuf[5];
- char str[5] = "";
- int len = count;
+ struct list_head *node, *next;
+ char strbuf[5];
+ char str[5] = "";
+ int len = count;
struct acpi_device *found_dev = NULL;
- if (len > 4) len = 4;
+ if (len > 4)
+ len = 4;
if (copy_from_user(strbuf, buffer, len))
return -EFAULT;
@@ -414,28 +390,36 @@ acpi_system_write_wakeup_device (
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
if (!strncmp(dev->pnp.bus_id, str, 4)) {
- dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
+ dev->wakeup.state.enabled =
+ dev->wakeup.state.enabled ? 0 : 1;
found_dev = dev;
break;
}
}
if (found_dev) {
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct
+ acpi_device,
+ wakeup_list);
if ((dev != found_dev) &&
- (dev->wakeup.gpe_number == found_dev->wakeup.gpe_number) &&
- (dev->wakeup.gpe_device == found_dev->wakeup.gpe_device)) {
- printk(KERN_WARNING "ACPI: '%s' and '%s' have the same GPE, "
- "can't disable/enable one seperately\n",
- dev->pnp.bus_id, found_dev->pnp.bus_id);
- dev->wakeup.state.enabled = found_dev->wakeup.state.enabled;
+ (dev->wakeup.gpe_number ==
+ found_dev->wakeup.gpe_number)
+ && (dev->wakeup.gpe_device ==
+ found_dev->wakeup.gpe_device)) {
+ printk(KERN_WARNING
+ "ACPI: '%s' and '%s' have the same GPE, "
+ "can't disable/enable one seperately\n",
+ dev->pnp.bus_id, found_dev->pnp.bus_id);
+ dev->wakeup.state.enabled =
+ found_dev->wakeup.state.enabled;
}
}
}
@@ -446,37 +430,37 @@ acpi_system_write_wakeup_device (
static int
acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_system_wakeup_device_seq_show,
+ PDE(inode)->data);
}
static struct file_operations acpi_system_wakeup_device_fops = {
- .open = acpi_system_wakeup_device_open_fs,
- .read = seq_read,
- .write = acpi_system_write_wakeup_device,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_wakeup_device_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_wakeup_device,
+ .llseek = seq_lseek,
+ .release = single_release,
};
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
static struct file_operations acpi_system_sleep_fops = {
- .open = acpi_system_sleep_open_fs,
- .read = seq_read,
- .write = acpi_system_write_sleep,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_sleep_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_sleep,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
+#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */
static struct file_operations acpi_system_alarm_fops = {
- .open = acpi_system_alarm_open_fs,
- .read = seq_read,
- .write = acpi_system_write_alarm,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_alarm_open_fs,
+ .read = seq_read,
+ .write = acpi_system_write_alarm,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
-static u32 rtc_handler(void * context)
+static u32 rtc_handler(void *context)
{
acpi_clear_event(ACPI_EVENT_RTC);
acpi_disable_event(ACPI_EVENT_RTC, 0);
@@ -486,28 +470,31 @@ static u32 rtc_handler(void * context)
static int acpi_sleep_proc_init(void)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
if (acpi_disabled)
return 0;
-
+
#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP
- /* 'sleep' [R/W]*/
- entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ /* 'sleep' [R/W] */
+ entry =
+ create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_sleep_fops;
#endif
/* 'alarm' [R/W] */
- entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ entry =
+ create_proc_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_alarm_fops;
- /* 'wakeup device' [R/W]*/
- entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+ /* 'wakeup device' [R/W] */
+ entry =
+ create_proc_entry("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_wakeup_device_fops;
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index d9b199969d5d..4134ed43d026 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -12,9 +12,9 @@
#include "sleep.h"
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("wakeup_devices")
+ACPI_MODULE_NAME("wakeup_devices")
-extern struct list_head acpi_wakeup_device_list;
+extern struct list_head acpi_wakeup_device_list;
extern spinlock_t acpi_device_lock;
#ifdef CONFIG_ACPI_SLEEP
@@ -25,22 +25,21 @@ extern spinlock_t acpi_device_lock;
* is higher than requested sleep level
*/
-void
-acpi_enable_wakeup_device_prep(
- u8 sleep_state)
+void acpi_enable_wakeup_device_prep(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
-
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.enabled ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
+
+ if (!dev->wakeup.flags.valid ||
+ !dev->wakeup.state.enabled ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
@@ -55,11 +54,9 @@ acpi_enable_wakeup_device_prep(
* @sleep_state: ACPI state
* Enable all wakup devices's GPE
*/
-void
-acpi_enable_wakeup_device(
- u8 sleep_state)
+void acpi_enable_wakeup_device(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
/*
* Caution: this routine must be invoked when interrupt is disabled
@@ -68,33 +65,35 @@ acpi_enable_wakeup_device(
ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_RUNTIME);
/* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_ISR);
spin_lock(&acpi_device_lock);
continue;
}
if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.enabled ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ !dev->wakeup.state.enabled ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
/* run-wake GPE has been enabled */
if (!dev->wakeup.flags.run_wake)
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_ISR);
dev->wakeup.state.active = 1;
spin_lock(&acpi_device_lock);
}
@@ -106,43 +105,43 @@ acpi_enable_wakeup_device(
* @sleep_state: ACPI state
* Disable all wakup devices's GPE and wakeup capability
*/
-void
-acpi_disable_wakeup_device (
- u8 sleep_state)
+void acpi_disable_wakeup_device(u8 sleep_state)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
/* Re-enable it, since set_gpe_type will disable it */
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
spin_lock(&acpi_device_lock);
continue;
}
- if (!dev->wakeup.flags.valid ||
- !dev->wakeup.state.active ||
- (sleep_state > (u32) dev->wakeup.sleep_state))
+ if (!dev->wakeup.flags.valid ||
+ !dev->wakeup.state.active ||
+ (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
spin_unlock(&acpi_device_lock);
acpi_disable_wakeup_device_power(dev);
/* Never disable run-wake GPE */
if (!dev->wakeup.flags.run_wake) {
- acpi_disable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
- acpi_clear_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_disable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_clear_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
}
dev->wakeup.state.active = 0;
spin_lock(&acpi_device_lock);
@@ -152,7 +151,7 @@ acpi_disable_wakeup_device (
static int __init acpi_wakeup_device_init(void)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
if (acpi_disabled)
return 0;
@@ -160,16 +159,18 @@ static int __init acpi_wakeup_device_init(void)
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
-
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
+
/* In case user doesn't load button driver */
if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
spin_unlock(&acpi_device_lock);
- acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
- acpi_enable_gpe(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_NOT_ISR);
+ acpi_set_gpe_type(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE_RUN);
+ acpi_enable_gpe(dev->wakeup.gpe_device,
+ dev->wakeup.gpe_number, ACPI_NOT_ISR);
dev->wakeup.state.enabled = 1;
spin_lock(&acpi_device_lock);
}
@@ -193,17 +194,19 @@ late_initcall(acpi_wakeup_device_init);
*/
void acpi_wakeup_gpe_poweroff_prepare(void)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device * dev = container_of(node,
- struct acpi_device, wakeup_list);
+ struct acpi_device *dev = container_of(node,
+ struct acpi_device,
+ wakeup_list);
/* The GPE can wakeup system from S5, don't touch it */
- if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5)
+ if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5)
continue;
/* acpi_set_gpe_type will automatically disable GPE */
acpi_set_gpe_type(dev->wakeup.gpe_device,
- dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+ dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_RUNTIME);
}
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 8925a6ca5f87..e4308c7a6743 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -30,10 +30,8 @@
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("acpi_system")
-
+ACPI_MODULE_NAME("acpi_system")
#define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
#define ACPI_SYSTEM_DEVICE_NAME "System"
@@ -41,15 +39,13 @@ ACPI_MODULE_NAME ("acpi_system")
#define ACPI_SYSTEM_FILE_EVENT "event"
#define ACPI_SYSTEM_FILE_DSDT "dsdt"
#define ACPI_SYSTEM_FILE_FADT "fadt"
-
-extern FADT_DESCRIPTOR acpi_fadt;
+extern FADT_DESCRIPTOR acpi_fadt;
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static int
-acpi_system_read_info (struct seq_file *seq, void *offset)
+static int acpi_system_read_info(struct seq_file *seq, void *offset)
{
ACPI_FUNCTION_TRACE("acpi_system_read_info");
@@ -63,28 +59,26 @@ static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
}
static struct file_operations acpi_system_info_ops = {
- .open = acpi_system_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_system_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static ssize_t acpi_system_read_dsdt (struct file*, char __user *, size_t, loff_t*);
+static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
+ loff_t *);
static struct file_operations acpi_system_dsdt_ops = {
- .read = acpi_system_read_dsdt,
+ .read = acpi_system_read_dsdt,
};
static ssize_t
-acpi_system_read_dsdt (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_dsdt(struct file *file,
+ char __user * buffer, size_t count, loff_t * ppos)
{
- acpi_status status = AE_OK;
- struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL};
- ssize_t res;
+ acpi_status status = AE_OK;
+ struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
+ ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
@@ -99,23 +93,20 @@ acpi_system_read_dsdt (
return_VALUE(res);
}
-
-static ssize_t acpi_system_read_fadt (struct file*, char __user *, size_t, loff_t*);
+static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
+ loff_t *);
static struct file_operations acpi_system_fadt_ops = {
- .read = acpi_system_read_fadt,
+ .read = acpi_system_read_fadt,
};
static ssize_t
-acpi_system_read_fadt (
- struct file *file,
- char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_system_read_fadt(struct file *file,
+ char __user * buffer, size_t count, loff_t * ppos)
{
- acpi_status status = AE_OK;
- struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL};
- ssize_t res;
+ acpi_status status = AE_OK;
+ struct acpi_buffer fadt = { ACPI_ALLOCATE_BUFFER, NULL };
+ ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
@@ -130,12 +121,11 @@ acpi_system_read_fadt (
return_VALUE(res);
}
-
-static int __init acpi_system_init (void)
+static int __init acpi_system_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry;
int error = 0;
- char * name;
+ char *name;
ACPI_FUNCTION_TRACE("acpi_system_init");
@@ -144,8 +134,7 @@ static int __init acpi_system_init (void)
/* 'info' [R] */
name = ACPI_SYSTEM_FILE_INFO;
- entry = create_proc_entry(name,
- S_IRUGO, acpi_root_dir);
+ entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
if (!entry)
goto Error;
else {
@@ -157,7 +146,7 @@ static int __init acpi_system_init (void)
entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_dsdt_ops;
- else
+ else
goto Error;
/* 'fadt' [R] */
@@ -168,12 +157,12 @@ static int __init acpi_system_init (void)
else
goto Error;
- Done:
+ Done:
return_VALUE(error);
- Error:
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' proc fs entry\n", name));
+ Error:
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' proc fs entry\n", name));
remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
@@ -183,5 +172,4 @@ static int __init acpi_system_init (void)
goto Done;
}
-
subsys_initcall(acpi_system_init);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index fb64bd5d2e18..a2bf25b05e1c 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -40,25 +40,25 @@
#define ACPI_MAX_TABLES 256
static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
- [ACPI_TABLE_UNKNOWN] = "????",
- [ACPI_APIC] = "APIC",
- [ACPI_BOOT] = "BOOT",
- [ACPI_DBGP] = "DBGP",
- [ACPI_DSDT] = "DSDT",
- [ACPI_ECDT] = "ECDT",
- [ACPI_ETDT] = "ETDT",
- [ACPI_FADT] = "FACP",
- [ACPI_FACS] = "FACS",
- [ACPI_OEMX] = "OEM",
- [ACPI_PSDT] = "PSDT",
- [ACPI_SBST] = "SBST",
- [ACPI_SLIT] = "SLIT",
- [ACPI_SPCR] = "SPCR",
- [ACPI_SRAT] = "SRAT",
- [ACPI_SSDT] = "SSDT",
- [ACPI_SPMI] = "SPMI",
- [ACPI_HPET] = "HPET",
- [ACPI_MCFG] = "MCFG",
+ [ACPI_TABLE_UNKNOWN] = "????",
+ [ACPI_APIC] = "APIC",
+ [ACPI_BOOT] = "BOOT",
+ [ACPI_DBGP] = "DBGP",
+ [ACPI_DSDT] = "DSDT",
+ [ACPI_ECDT] = "ECDT",
+ [ACPI_ETDT] = "ETDT",
+ [ACPI_FADT] = "FACP",
+ [ACPI_FACS] = "FACS",
+ [ACPI_OEMX] = "OEM",
+ [ACPI_PSDT] = "PSDT",
+ [ACPI_SBST] = "SBST",
+ [ACPI_SLIT] = "SLIT",
+ [ACPI_SPCR] = "SPCR",
+ [ACPI_SRAT] = "SRAT",
+ [ACPI_SSDT] = "SSDT",
+ [ACPI_SPMI] = "SPMI",
+ [ACPI_HPET] = "HPET",
+ [ACPI_MCFG] = "MCFG",
};
static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
@@ -66,52 +66,44 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
/* System Description Table (RSDT/XSDT) */
struct acpi_table_sdt {
- unsigned long pa;
- enum acpi_table_id id;
- unsigned long size;
+ unsigned long pa;
+ enum acpi_table_id id;
+ unsigned long size;
} __attribute__ ((packed));
-static unsigned long sdt_pa; /* Physical Address */
-static unsigned long sdt_count; /* Table count */
+static unsigned long sdt_pa; /* Physical Address */
+static unsigned long sdt_count; /* Table count */
-static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
+static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
-void
-acpi_table_print (
- struct acpi_table_header *header,
- unsigned long phys_addr)
+void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr)
{
- char *name = NULL;
+ char *name = NULL;
if (!header)
return;
/* Some table signatures aren't good table names */
- if (!strncmp((char *) &header->signature,
- acpi_table_signatures[ACPI_APIC],
- sizeof(header->signature))) {
+ if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[ACPI_APIC],
+ sizeof(header->signature))) {
name = "MADT";
- }
- else if (!strncmp((char *) &header->signature,
- acpi_table_signatures[ACPI_FADT],
- sizeof(header->signature))) {
+ } else if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[ACPI_FADT],
+ sizeof(header->signature))) {
name = "FADT";
- }
- else
+ } else
name = header->signature;
- printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
- name, header->revision, header->oem_id,
- header->oem_table_id, header->oem_revision,
- header->asl_compiler_id, header->asl_compiler_revision,
- (void *) phys_addr);
+ printk(KERN_DEBUG PREFIX
+ "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name,
+ header->revision, header->oem_id, header->oem_table_id,
+ header->oem_revision, header->asl_compiler_id,
+ header->asl_compiler_revision, (void *)phys_addr);
}
-
-void
-acpi_table_print_madt_entry (
- acpi_table_entry_header *header)
+void acpi_table_print_madt_entry(acpi_table_entry_header * header)
{
if (!header)
return;
@@ -119,113 +111,127 @@ acpi_table_print_madt_entry (
switch (header->type) {
case ACPI_MADT_LAPIC:
- {
- struct acpi_table_lapic *p =
- (struct acpi_table_lapic*) header;
- printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
- p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled");
- }
+ {
+ struct acpi_table_lapic *p =
+ (struct acpi_table_lapic *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
+ p->acpi_id, p->id,
+ p->flags.enabled ? "enabled" : "disabled");
+ }
break;
case ACPI_MADT_IOAPIC:
- {
- struct acpi_table_ioapic *p =
- (struct acpi_table_ioapic*) header;
- printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
- p->id, p->address, p->global_irq_base);
- }
+ {
+ struct acpi_table_ioapic *p =
+ (struct acpi_table_ioapic *)header;
+ printk(KERN_INFO PREFIX
+ "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
+ p->id, p->address, p->global_irq_base);
+ }
break;
case ACPI_MADT_INT_SRC_OVR:
- {
- struct acpi_table_int_src_ovr *p =
- (struct acpi_table_int_src_ovr*) header;
- printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
- p->bus, p->bus_irq, p->global_irq,
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger]);
- if(p->flags.reserved)
- printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
- p->flags.reserved);
+ {
+ struct acpi_table_int_src_ovr *p =
+ (struct acpi_table_int_src_ovr *)header;
+ printk(KERN_INFO PREFIX
+ "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
+ p->bus, p->bus_irq, p->global_irq,
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger]);
+ if (p->flags.reserved)
+ printk(KERN_INFO PREFIX
+ "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
+ p->flags.reserved);
- }
+ }
break;
case ACPI_MADT_NMI_SRC:
- {
- struct acpi_table_nmi_src *p =
- (struct acpi_table_nmi_src*) header;
- printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n",
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger], p->global_irq);
- }
+ {
+ struct acpi_table_nmi_src *p =
+ (struct acpi_table_nmi_src *)header;
+ printk(KERN_INFO PREFIX
+ "NMI_SRC (%s %s global_irq %d)\n",
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->global_irq);
+ }
break;
case ACPI_MADT_LAPIC_NMI:
- {
- struct acpi_table_lapic_nmi *p =
- (struct acpi_table_lapic_nmi*) header;
- printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
- p->acpi_id,
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger], p->lint);
- }
+ {
+ struct acpi_table_lapic_nmi *p =
+ (struct acpi_table_lapic_nmi *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
+ p->acpi_id,
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->lint);
+ }
break;
case ACPI_MADT_LAPIC_ADDR_OVR:
- {
- struct acpi_table_lapic_addr_ovr *p =
- (struct acpi_table_lapic_addr_ovr*) header;
- printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n",
- (void *) (unsigned long) p->address);
- }
+ {
+ struct acpi_table_lapic_addr_ovr *p =
+ (struct acpi_table_lapic_addr_ovr *)header;
+ printk(KERN_INFO PREFIX
+ "LAPIC_ADDR_OVR (address[%p])\n",
+ (void *)(unsigned long)p->address);
+ }
break;
case ACPI_MADT_IOSAPIC:
- {
- struct acpi_table_iosapic *p =
- (struct acpi_table_iosapic*) header;
- printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
- p->id, (void *) (unsigned long) p->address, p->global_irq_base);
- }
+ {
+ struct acpi_table_iosapic *p =
+ (struct acpi_table_iosapic *)header;
+ printk(KERN_INFO PREFIX
+ "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
+ p->id, (void *)(unsigned long)p->address,
+ p->global_irq_base);
+ }
break;
case ACPI_MADT_LSAPIC:
- {
- struct acpi_table_lsapic *p =
- (struct acpi_table_lsapic*) header;
- printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
- p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled");
- }
+ {
+ struct acpi_table_lsapic *p =
+ (struct acpi_table_lsapic *)header;
+ printk(KERN_INFO PREFIX
+ "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
+ p->acpi_id, p->id, p->eid,
+ p->flags.enabled ? "enabled" : "disabled");
+ }
break;
case ACPI_MADT_PLAT_INT_SRC:
- {
- struct acpi_table_plat_int_src *p =
- (struct acpi_table_plat_int_src*) header;
- printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
- mps_inti_flags_polarity[p->flags.polarity],
- mps_inti_flags_trigger[p->flags.trigger],
- p->type, p->id, p->eid, p->iosapic_vector, p->global_irq);
- }
+ {
+ struct acpi_table_plat_int_src *p =
+ (struct acpi_table_plat_int_src *)header;
+ printk(KERN_INFO PREFIX
+ "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
+ mps_inti_flags_polarity[p->flags.polarity],
+ mps_inti_flags_trigger[p->flags.trigger],
+ p->type, p->id, p->eid, p->iosapic_vector,
+ p->global_irq);
+ }
break;
default:
- printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n",
- header->type);
+ printk(KERN_WARNING PREFIX
+ "Found unsupported MADT entry (type = 0x%x)\n",
+ header->type);
break;
}
}
-
static int
-acpi_table_compute_checksum (
- void *table_pointer,
- unsigned long length)
+acpi_table_compute_checksum(void *table_pointer, unsigned long length)
{
- u8 *p = (u8 *) table_pointer;
- unsigned long remains = length;
- unsigned long sum = 0;
+ u8 *p = (u8 *) table_pointer;
+ unsigned long remains = length;
+ unsigned long sum = 0;
if (!p || !length)
return -EINVAL;
@@ -241,9 +247,8 @@ acpi_table_compute_checksum (
* for acpi_blacklisted(), acpi_table_get_sdt()
*/
int __init
-acpi_get_table_header_early (
- enum acpi_table_id id,
- struct acpi_table_header **header)
+acpi_get_table_header_early(enum acpi_table_id id,
+ struct acpi_table_header **header)
{
unsigned int i;
enum acpi_table_id temp_id;
@@ -260,7 +265,7 @@ acpi_get_table_header_early (
if (sdt_entry[i].id != temp_id)
continue;
*header = (void *)
- __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
if (!*header) {
printk(KERN_WARNING PREFIX "Unable to map %s\n",
acpi_table_signatures[temp_id]);
@@ -277,14 +282,17 @@ acpi_get_table_header_early (
/* Map the DSDT header via the pointer in the FADT */
if (id == ACPI_DSDT) {
- struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header;
+ struct fadt_descriptor_rev2 *fadt =
+ (struct fadt_descriptor_rev2 *)*header;
if (fadt->revision == 3 && fadt->Xdsdt) {
- *header = (void *) __acpi_map_table(fadt->Xdsdt,
- sizeof(struct acpi_table_header));
+ *header = (void *)__acpi_map_table(fadt->Xdsdt,
+ sizeof(struct
+ acpi_table_header));
} else if (fadt->V1_dsdt) {
- *header = (void *) __acpi_map_table(fadt->V1_dsdt,
- sizeof(struct acpi_table_header));
+ *header = (void *)__acpi_map_table(fadt->V1_dsdt,
+ sizeof(struct
+ acpi_table_header));
} else
*header = NULL;
@@ -296,21 +304,19 @@ acpi_get_table_header_early (
return 0;
}
-
int __init
-acpi_table_parse_madt_family (
- enum acpi_table_id id,
- unsigned long madt_size,
- int entry_id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_madt_family(enum acpi_table_id id,
+ unsigned long madt_size,
+ int entry_id,
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries)
{
- void *madt = NULL;
- acpi_table_entry_header *entry;
- unsigned int count = 0;
- unsigned long madt_end;
- unsigned int i;
+ void *madt = NULL;
+ acpi_table_entry_header *entry;
+ unsigned int count = 0;
+ unsigned long madt_end;
+ unsigned int i;
if (!handler)
return -EINVAL;
@@ -321,7 +327,7 @@ acpi_table_parse_madt_family (
if (sdt_entry[i].id != id)
continue;
madt = (void *)
- __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
if (!madt) {
printk(KERN_WARNING PREFIX "Unable to map %s\n",
acpi_table_signatures[id]);
@@ -336,21 +342,22 @@ acpi_table_parse_madt_family (
return -ENODEV;
}
- madt_end = (unsigned long) madt + sdt_entry[i].size;
+ madt_end = (unsigned long)madt + sdt_entry[i].size;
/* Parse all entries looking for a match. */
entry = (acpi_table_entry_header *)
- ((unsigned long) madt + madt_size);
+ ((unsigned long)madt + madt_size);
- while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
- if (entry->type == entry_id &&
- (!max_entries || count++ < max_entries))
+ while (((unsigned long)entry) + sizeof(acpi_table_entry_header) <
+ madt_end) {
+ if (entry->type == entry_id
+ && (!max_entries || count++ < max_entries))
if (handler(entry, madt_end))
return -EINVAL;
entry = (acpi_table_entry_header *)
- ((unsigned long) entry + entry->length);
+ ((unsigned long)entry + entry->length);
}
if (max_entries && count > max_entries) {
printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
@@ -361,25 +368,19 @@ acpi_table_parse_madt_family (
return count;
}
-
int __init
-acpi_table_parse_madt (
- enum acpi_madt_entry_id id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries)
+acpi_table_parse_madt(enum acpi_madt_entry_id id,
+ acpi_madt_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
- id, handler, max_entries);
+ return acpi_table_parse_madt_family(ACPI_APIC,
+ sizeof(struct acpi_table_madt), id,
+ handler, max_entries);
}
-
-int __init
-acpi_table_parse (
- enum acpi_table_id id,
- acpi_table_handler handler)
+int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler)
{
- int count = 0;
- unsigned int i = 0;
+ int count = 0;
+ unsigned int i = 0;
if (!handler)
return -EINVAL;
@@ -392,20 +393,18 @@ acpi_table_parse (
handler(sdt_entry[i].pa, sdt_entry[i].size);
else
- printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n",
- count, acpi_table_signatures[id]);
+ printk(KERN_WARNING PREFIX
+ "%d duplicate %s table ignored.\n", count,
+ acpi_table_signatures[id]);
}
return count;
}
-
-static int __init
-acpi_table_get_sdt (
- struct acpi_table_rsdp *rsdp)
+static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp)
{
struct acpi_table_header *header = NULL;
- unsigned int i, id = 0;
+ unsigned int i, id = 0;
if (!rsdp)
return -EINVAL;
@@ -413,24 +412,25 @@ acpi_table_get_sdt (
/* First check XSDT (but only on ACPI 2.0-compatible systems) */
if ((rsdp->revision >= 2) &&
- (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) {
-
- struct acpi_table_xsdt *mapped_xsdt = NULL;
+ (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) {
+
+ struct acpi_table_xsdt *mapped_xsdt = NULL;
- sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
+ sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address;
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
if (!header) {
- printk(KERN_WARNING PREFIX "Unable to map XSDT header\n");
+ printk(KERN_WARNING PREFIX
+ "Unable to map XSDT header\n");
return -ENODEV;
}
/* remap in the entire table before processing */
mapped_xsdt = (struct acpi_table_xsdt *)
- __acpi_map_table(sdt_pa, header->length);
+ __acpi_map_table(sdt_pa, header->length);
if (!mapped_xsdt) {
printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
return -ENODEV;
@@ -438,7 +438,8 @@ acpi_table_get_sdt (
header = &mapped_xsdt->header;
if (strncmp(header->signature, "XSDT", 4)) {
- printk(KERN_WARNING PREFIX "XSDT signature incorrect\n");
+ printk(KERN_WARNING PREFIX
+ "XSDT signature incorrect\n");
return -ENODEV;
}
@@ -447,36 +448,39 @@ acpi_table_get_sdt (
return -ENODEV;
}
- sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3;
+ sdt_count =
+ (header->length - sizeof(struct acpi_table_header)) >> 3;
if (sdt_count > ACPI_MAX_TABLES) {
- printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
- (sdt_count - ACPI_MAX_TABLES));
+ printk(KERN_WARNING PREFIX
+ "Truncated %lu XSDT entries\n",
+ (sdt_count - ACPI_MAX_TABLES));
sdt_count = ACPI_MAX_TABLES;
}
for (i = 0; i < sdt_count; i++)
- sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
+ sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i];
}
/* Then check RSDT */
else if (rsdp->rsdt_address) {
- struct acpi_table_rsdt *mapped_rsdt = NULL;
+ struct acpi_table_rsdt *mapped_rsdt = NULL;
sdt_pa = rsdp->rsdt_address;
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
if (!header) {
- printk(KERN_WARNING PREFIX "Unable to map RSDT header\n");
+ printk(KERN_WARNING PREFIX
+ "Unable to map RSDT header\n");
return -ENODEV;
}
/* remap in the entire table before processing */
mapped_rsdt = (struct acpi_table_rsdt *)
- __acpi_map_table(sdt_pa, header->length);
+ __acpi_map_table(sdt_pa, header->length);
if (!mapped_rsdt) {
printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
return -ENODEV;
@@ -484,7 +488,8 @@ acpi_table_get_sdt (
header = &mapped_rsdt->header;
if (strncmp(header->signature, "RSDT", 4)) {
- printk(KERN_WARNING PREFIX "RSDT signature incorrect\n");
+ printk(KERN_WARNING PREFIX
+ "RSDT signature incorrect\n");
return -ENODEV;
}
@@ -493,19 +498,22 @@ acpi_table_get_sdt (
return -ENODEV;
}
- sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2;
+ sdt_count =
+ (header->length - sizeof(struct acpi_table_header)) >> 2;
if (sdt_count > ACPI_MAX_TABLES) {
- printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
- (sdt_count - ACPI_MAX_TABLES));
+ printk(KERN_WARNING PREFIX
+ "Truncated %lu RSDT entries\n",
+ (sdt_count - ACPI_MAX_TABLES));
sdt_count = ACPI_MAX_TABLES;
}
for (i = 0; i < sdt_count; i++)
- sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
+ sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i];
}
else {
- printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n");
+ printk(KERN_WARNING PREFIX
+ "No System Description Table (RSDT/XSDT) specified in RSDP\n");
return -ENODEV;
}
@@ -515,18 +523,17 @@ acpi_table_get_sdt (
/* map in just the header */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_entry[i].pa,
- sizeof(struct acpi_table_header));
+ __acpi_map_table(sdt_entry[i].pa,
+ sizeof(struct acpi_table_header));
if (!header)
continue;
/* remap in the entire table before processing */
header = (struct acpi_table_header *)
- __acpi_map_table(sdt_entry[i].pa,
- header->length);
+ __acpi_map_table(sdt_entry[i].pa, header->length);
if (!header)
continue;
-
+
acpi_table_print(header, sdt_entry[i].pa);
if (acpi_table_compute_checksum(header, header->length)) {
@@ -537,9 +544,9 @@ acpi_table_get_sdt (
sdt_entry[i].size = header->length;
for (id = 0; id < ACPI_TABLE_COUNT; id++) {
- if (!strncmp((char *) &header->signature,
- acpi_table_signatures[id],
- sizeof(header->signature))) {
+ if (!strncmp((char *)&header->signature,
+ acpi_table_signatures[id],
+ sizeof(header->signature))) {
sdt_entry[i].id = id;
}
}
@@ -551,7 +558,7 @@ acpi_table_get_sdt (
* against. Unfortunately, we don't know the phys_addr, so just
* print 0. Maybe no one will notice.
*/
- if(!acpi_get_table_header_early(ACPI_DSDT, &header))
+ if (!acpi_get_table_header_early(ACPI_DSDT, &header))
acpi_table_print(header, 0);
return 0;
@@ -566,12 +573,11 @@ acpi_table_get_sdt (
* result: sdt_entry[] is initialized
*/
-int __init
-acpi_table_init (void)
+int __init acpi_table_init(void)
{
- struct acpi_table_rsdp *rsdp = NULL;
- unsigned long rsdp_phys = 0;
- int result = 0;
+ struct acpi_table_rsdp *rsdp = NULL;
+ unsigned long rsdp_phys = 0;
+ int result = 0;
/* Locate and map the Root System Description Table (RSDP) */
@@ -581,19 +587,25 @@ acpi_table_init (void)
return -ENODEV;
}
- rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys);
+ rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys);
if (!rsdp) {
printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
return -ENODEV;
}
- printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
- rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
+ printk(KERN_DEBUG PREFIX
+ "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
+ rsdp->revision, rsdp->oem_id, (void *)rsdp_phys);
if (rsdp->revision < 2)
- result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp));
+ result =
+ acpi_table_compute_checksum(rsdp,
+ sizeof(struct acpi_table_rsdp));
else
- result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length);
+ result =
+ acpi_table_compute_checksum(rsdp,
+ ((struct acpi20_table_rsdp *)
+ rsdp)->length);
if (result) {
printk(KERN_WARNING " >>> ERROR: Invalid checksum\n");
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index 92e0c31539be..a03939399fa9 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -46,28 +46,22 @@
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbconvrt")
+ACPI_MODULE_NAME("tbconvrt")
/* Local prototypes */
-
static void
-acpi_tb_init_generic_address (
- struct acpi_generic_address *new_gas_struct,
- u8 register_bit_width,
- acpi_physical_address address);
+acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
+ u8 register_bit_width,
+ acpi_physical_address address);
static void
-acpi_tb_convert_fadt1 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev1 *original_fadt);
+acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev1 *original_fadt);
static void
-acpi_tb_convert_fadt2 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev2 *original_fadt);
-
+acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev2 *original_fadt);
u8 acpi_fadt_is_v1;
EXPORT_SYMBOL(acpi_fadt_is_v1);
@@ -87,21 +81,19 @@ EXPORT_SYMBOL(acpi_fadt_is_v1);
******************************************************************************/
u32
-acpi_tb_get_table_count (
- struct rsdp_descriptor *RSDP,
- struct acpi_table_header *RSDT)
+acpi_tb_get_table_count(struct rsdp_descriptor *RSDP,
+ struct acpi_table_header *RSDT)
{
- u32 pointer_size;
+ u32 pointer_size;
+ ACPI_FUNCTION_ENTRY();
- ACPI_FUNCTION_ENTRY ();
+ /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
-
- if (RSDP->revision < 2) {
- pointer_size = sizeof (u32);
- }
- else {
- pointer_size = sizeof (u64);
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ pointer_size = sizeof(u32);
+ } else {
+ pointer_size = sizeof(u64);
}
/*
@@ -110,10 +102,10 @@ acpi_tb_get_table_count (
* pointers contained within the RSDT/XSDT. The size of the pointers
* is architecture-dependent.
*/
- return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size);
+ return ((RSDT->length -
+ sizeof(struct acpi_table_header)) / pointer_size);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_to_xsdt
@@ -126,64 +118,65 @@ acpi_tb_get_table_count (
*
******************************************************************************/
-acpi_status
-acpi_tb_convert_to_xsdt (
- struct acpi_table_desc *table_info)
+acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
{
- acpi_size table_size;
- u32 i;
- XSDT_DESCRIPTOR *new_table;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_size table_size;
+ u32 i;
+ XSDT_DESCRIPTOR *new_table;
+ ACPI_FUNCTION_ENTRY();
/* Compute size of the converted XSDT */
- table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) +
- sizeof (struct acpi_table_header);
+ table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) +
+ sizeof(struct acpi_table_header);
/* Allocate an XSDT */
- new_table = ACPI_MEM_CALLOCATE (table_size);
+ new_table = ACPI_MEM_CALLOCATE(table_size);
if (!new_table) {
return (AE_NO_MEMORY);
}
/* Copy the header and set the length */
- ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(new_table, table_info->pointer,
+ sizeof(struct acpi_table_header));
new_table->length = (u32) table_size;
/* Copy the table pointers */
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
- if (acpi_gbl_RSDP->revision < 2) {
- ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
- (ACPI_CAST_PTR (struct rsdt_descriptor_rev1,
- table_info->pointer))->table_offset_entry[i]);
- }
- else {
+ /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
+
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ ACPI_STORE_ADDRESS(new_table->table_offset_entry[i],
+ (ACPI_CAST_PTR
+ (struct rsdt_descriptor_rev1,
+ table_info->pointer))->
+ table_offset_entry[i]);
+ } else {
new_table->table_offset_entry[i] =
- (ACPI_CAST_PTR (XSDT_DESCRIPTOR,
- table_info->pointer))->table_offset_entry[i];
+ (ACPI_CAST_PTR(XSDT_DESCRIPTOR,
+ table_info->pointer))->
+ table_offset_entry[i];
}
}
/* Delete the original table (either mapped or in a buffer) */
- acpi_tb_delete_single_table (table_info);
+ acpi_tb_delete_single_table(table_info);
/* Point the table descriptor to the new table */
- table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table);
- table_info->length = table_size;
- table_info->allocation = ACPI_MEM_ALLOCATED;
+ table_info->pointer =
+ ACPI_CAST_PTR(struct acpi_table_header, new_table);
+ table_info->length = table_size;
+ table_info->allocation = ACPI_MEM_ALLOCATED;
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_generic_address
@@ -199,21 +192,19 @@ acpi_tb_convert_to_xsdt (
******************************************************************************/
static void
-acpi_tb_init_generic_address (
- struct acpi_generic_address *new_gas_struct,
- u8 register_bit_width,
- acpi_physical_address address)
+acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
+ u8 register_bit_width,
+ acpi_physical_address address)
{
- ACPI_STORE_ADDRESS (new_gas_struct->address, address);
+ ACPI_STORE_ADDRESS(new_gas_struct->address, address);
new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
new_gas_struct->register_bit_width = register_bit_width;
new_gas_struct->register_bit_offset = 0;
- new_gas_struct->access_width = 0;
+ new_gas_struct->access_width = 0;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt1
@@ -228,9 +219,8 @@ acpi_tb_init_generic_address (
******************************************************************************/
static void
-acpi_tb_convert_fadt1 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev1 *original_fadt)
+acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev1 *original_fadt)
{
/* ACPI 1.0 FACS */
@@ -243,12 +233,14 @@ acpi_tb_convert_fadt1 (
* The 2.0 table is an extension of the 1.0 table, so the entire 1.0
* table can be copied first, then expand some fields to 64 bits.
*/
- ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1));
+ ACPI_MEMCPY(local_fadt, original_fadt,
+ sizeof(struct fadt_descriptor_rev1));
/* Convert table pointers to 64-bit fields */
- ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
- ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
+ ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
+ local_fadt->V1_firmware_ctrl);
+ ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
/*
* System Interrupt Model isn't used in ACPI 2.0
@@ -283,17 +275,17 @@ acpi_tb_convert_fadt1 (
* It primarily adds the FADT reset mechanism.
*/
if ((original_fadt->revision == 2) &&
- (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) {
+ (original_fadt->length ==
+ sizeof(struct fadt_descriptor_rev2_minus))) {
/*
* Grab the entire generic address struct, plus the 1-byte reset value
* that immediately follows.
*/
- ACPI_MEMCPY (&local_fadt->reset_register,
- &(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus,
- original_fadt))->reset_register,
- sizeof (struct acpi_generic_address) + 1);
- }
- else {
+ ACPI_MEMCPY(&local_fadt->reset_register,
+ &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus,
+ original_fadt))->reset_register,
+ sizeof(struct acpi_generic_address) + 1);
+ } else {
/*
* Since there isn't any equivalence in 1.0 and since it is highly
* likely that a 1.0 system has legacy support.
@@ -304,43 +296,60 @@ acpi_tb_convert_fadt1 (
/*
* Convert the V1.0 block addresses to V2.0 GAS structures
*/
- acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
- acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len,
- (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
- acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0,
- (acpi_physical_address) local_fadt->V1_gpe0_blk);
- acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0,
- (acpi_physical_address) local_fadt->V1_gpe1_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1a_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1b_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1a_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm1b_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
+ local_fadt->pm2_cnt_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm2_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
+ local_fadt->pm_tm_len,
+ (acpi_physical_address) local_fadt->
+ V1_pm_tmr_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0,
+ (acpi_physical_address) local_fadt->
+ V1_gpe0_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0,
+ (acpi_physical_address) local_fadt->
+ V1_gpe1_blk);
/* Create separate GAS structs for the PM1 Enable registers */
- acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1a_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
- acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1b_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1b_evt_blk.
+ address +
+ ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len)));
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt2
@@ -356,14 +365,14 @@ acpi_tb_convert_fadt1 (
******************************************************************************/
static void
-acpi_tb_convert_fadt2 (
- struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev2 *original_fadt)
+acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev2 *original_fadt)
{
/* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
- ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev2));
+ ACPI_MEMCPY(local_fadt, original_fadt,
+ sizeof(struct fadt_descriptor_rev2));
/*
* "X" fields are optional extensions to the original V1.0 fields, so
@@ -371,86 +380,99 @@ acpi_tb_convert_fadt2 (
* is zero.
*/
if (!(local_fadt->xfirmware_ctrl)) {
- ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl,
- local_fadt->V1_firmware_ctrl);
+ ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
+ local_fadt->V1_firmware_ctrl);
}
if (!(local_fadt->Xdsdt)) {
- ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
+ ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
}
if (!(local_fadt->xpm1a_evt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk,
- local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1a_evt_blk);
}
if (!(local_fadt->xpm1b_evt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk,
- local_fadt->pm1_evt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
+ local_fadt->pm1_evt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1b_evt_blk);
}
if (!(local_fadt->xpm1a_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk,
- local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1a_cnt_blk);
}
if (!(local_fadt->xpm1b_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk,
- local_fadt->pm1_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
+ local_fadt->pm1_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm1b_cnt_blk);
}
if (!(local_fadt->xpm2_cnt_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk,
- local_fadt->pm2_cnt_len,
- (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
+ local_fadt->pm2_cnt_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm2_cnt_blk);
}
if (!(local_fadt->xpm_tmr_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk,
- local_fadt->pm_tm_len,
- (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
+ acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
+ local_fadt->pm_tm_len,
+ (acpi_physical_address)
+ local_fadt->V1_pm_tmr_blk);
}
if (!(local_fadt->xgpe0_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xgpe0_blk,
- 0, (acpi_physical_address) local_fadt->V1_gpe0_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe0_blk,
+ 0,
+ (acpi_physical_address)
+ local_fadt->V1_gpe0_blk);
}
if (!(local_fadt->xgpe1_blk.address)) {
- acpi_tb_init_generic_address (&local_fadt->xgpe1_blk,
- 0, (acpi_physical_address) local_fadt->V1_gpe1_blk);
+ acpi_tb_init_generic_address(&local_fadt->xgpe1_blk,
+ 0,
+ (acpi_physical_address)
+ local_fadt->V1_gpe1_blk);
}
/* Create separate GAS structs for the PM1 Enable registers */
- acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1a_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
acpi_gbl_xpm1a_enable.address_space_id =
- local_fadt->xpm1a_evt_blk.address_space_id;
+ local_fadt->xpm1a_evt_blk.address_space_id;
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
- acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
- (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
- (acpi_physical_address)
- (local_fadt->xpm1b_evt_blk.address +
- ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len),
+ (acpi_physical_address)
+ (local_fadt->xpm1b_evt_blk.
+ address +
+ ACPI_DIV_2(acpi_gbl_FADT->
+ pm1_evt_len)));
acpi_gbl_xpm1b_enable.address_space_id =
- local_fadt->xpm1b_evt_blk.address_space_id;
+ local_fadt->xpm1b_evt_blk.address_space_id;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_table_fadt
@@ -467,83 +489,76 @@ acpi_tb_convert_fadt2 (
*
******************************************************************************/
-acpi_status
-acpi_tb_convert_table_fadt (
- void)
+acpi_status acpi_tb_convert_table_fadt(void)
{
- struct fadt_descriptor_rev2 *local_fadt;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
+ struct fadt_descriptor_rev2 *local_fadt;
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_TRACE("tb_convert_table_fadt");
/*
* acpi_gbl_FADT is valid. Validate the FADT length. The table must be
* at least as long as the version 1.0 FADT
*/
- if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) {
- ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n",
- acpi_gbl_FADT->length));
- return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
+ if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) {
+ ACPI_REPORT_ERROR(("FADT is invalid, too short: 0x%X\n",
+ acpi_gbl_FADT->length));
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/* Allocate buffer for the ACPI 2.0(+) FADT */
- local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2));
+ local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2));
if (!local_fadt) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
- if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) {
+ if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) {
/* Length is too short to be a V2.0 table */
- ACPI_REPORT_WARNING ((
- "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
- acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
+ ACPI_REPORT_WARNING(("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", acpi_gbl_FADT->length, acpi_gbl_FADT->revision));
- acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
- }
- else {
+ acpi_tb_convert_fadt1(local_fadt,
+ (void *)acpi_gbl_FADT);
+ } else {
/* Valid V2.0 table */
- acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT);
+ acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT);
}
- }
- else {
+ } else {
/* Valid V1.0 table */
- acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
+ acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT);
}
/* Global FADT pointer will point to the new common V2.0 FADT */
acpi_gbl_FADT = local_fadt;
- acpi_gbl_FADT->length = sizeof (FADT_DESCRIPTOR);
+ acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR);
/* Free the original table */
table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
- acpi_tb_delete_single_table (table_desc);
+ acpi_tb_delete_single_table(table_desc);
/* Install the new table */
- table_desc->pointer = ACPI_CAST_PTR (struct acpi_table_header, acpi_gbl_FADT);
- table_desc->allocation = ACPI_MEM_ALLOCATED;
- table_desc->length = sizeof (struct fadt_descriptor_rev2);
+ table_desc->pointer =
+ ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT);
+ table_desc->allocation = ACPI_MEM_ALLOCATED;
+ table_desc->length = sizeof(struct fadt_descriptor_rev2);
/* Dump the entire FADT */
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Hex dump of common internal FADT, size %d (%X)\n",
- acpi_gbl_FADT->length, acpi_gbl_FADT->length));
- ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Hex dump of common internal FADT, size %d (%X)\n",
+ acpi_gbl_FADT->length, acpi_gbl_FADT->length));
+ ACPI_DUMP_BUFFER((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_build_common_facs
@@ -557,26 +572,21 @@ acpi_tb_convert_table_fadt (
*
******************************************************************************/
-acpi_status
-acpi_tb_build_common_facs (
- struct acpi_table_desc *table_info)
+acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
{
- ACPI_FUNCTION_TRACE ("tb_build_common_facs");
-
+ ACPI_FUNCTION_TRACE("tb_build_common_facs");
/* Absolute minimum length is 24, but the ACPI spec says 64 */
if (acpi_gbl_FACS->length < 24) {
- ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n",
- acpi_gbl_FACS->length));
- return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
+ ACPI_REPORT_ERROR(("Invalid FACS table length: 0x%X\n",
+ acpi_gbl_FACS->length));
+ return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
if (acpi_gbl_FACS->length < 64) {
- ACPI_REPORT_WARNING ((
- "FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
- acpi_gbl_FACS->length));
+ ACPI_REPORT_WARNING(("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", acpi_gbl_FACS->length));
}
/* Copy fields to the new FACS */
@@ -584,22 +594,22 @@ acpi_tb_build_common_facs (
acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
if ((acpi_gbl_RSDP->revision < 2) ||
- (acpi_gbl_FACS->length < 32) ||
- (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
+ (acpi_gbl_FACS->length < 32) ||
+ (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
/* ACPI 1.0 FACS or short table or optional X_ field is zero */
- acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64,
- &(acpi_gbl_FACS->firmware_waking_vector));
+ acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64,
+ &
+ (acpi_gbl_FACS->
+ firmware_waking_vector));
acpi_gbl_common_fACS.vector_width = 32;
- }
- else {
+ } else {
/* ACPI 2.0 FACS with valid X_ field */
- acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector;
+ acpi_gbl_common_fACS.firmware_waking_vector =
+ &acpi_gbl_FACS->xfirmware_waking_vector;
acpi_gbl_common_fACS.vector_width = 64;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
-
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 4ab2aadc6133..6acd5aeb093e 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -41,27 +41,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbget")
+ACPI_MODULE_NAME("tbget")
/* Local prototypes */
-
static acpi_status
-acpi_tb_get_this_table (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info);
+acpi_tb_get_this_table(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info);
static acpi_status
-acpi_tb_table_override (
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info);
-
+acpi_tb_table_override(struct acpi_table_header *header,
+ struct acpi_table_desc *table_info);
/*******************************************************************************
*
@@ -78,37 +72,34 @@ acpi_tb_table_override (
******************************************************************************/
acpi_status
-acpi_tb_get_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info)
+acpi_tb_get_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table");
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE("tb_get_table");
/* Get the header in order to get signature and table size */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n",
- header.length, acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get ACPI table (size %X), %s\n",
+ header.length,
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_header
@@ -127,16 +118,13 @@ acpi_tb_get_table (
******************************************************************************/
acpi_status
-acpi_tb_get_table_header (
- struct acpi_pointer *address,
- struct acpi_table_header *return_header)
+acpi_tb_get_table_header(struct acpi_pointer *address,
+ struct acpi_table_header *return_header)
{
- acpi_status status = AE_OK;
- struct acpi_table_header *header = NULL;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_header");
+ acpi_status status = AE_OK;
+ struct acpi_table_header *header = NULL;
+ ACPI_FUNCTION_TRACE("tb_get_table_header");
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -148,46 +136,42 @@ acpi_tb_get_table_header (
/* Pointer matches processor mode, copy the header */
- ACPI_MEMCPY (return_header, address->pointer.logical,
- sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(return_header, address->pointer.logical,
+ sizeof(struct acpi_table_header));
break;
-
case ACPI_LOGMODE_PHYSPTR:
- /* Create a logical address for the physical pointer*/
+ /* Create a logical address for the physical pointer */
- status = acpi_os_map_memory (address->pointer.physical,
- sizeof (struct acpi_table_header), (void *) &header);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not map memory at %8.8X%8.8X for length %X\n",
- ACPI_FORMAT_UINT64 (address->pointer.physical),
- sizeof (struct acpi_table_header)));
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address->pointer.physical,
+ sizeof(struct acpi_table_header),
+ (void *)&header);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_FORMAT_UINT64(address->pointer.physical), sizeof(struct acpi_table_header)));
+ return_ACPI_STATUS(status);
}
/* Copy header and delete mapping */
- ACPI_MEMCPY (return_header, header, sizeof (struct acpi_table_header));
- acpi_os_unmap_memory (header, sizeof (struct acpi_table_header));
+ ACPI_MEMCPY(return_header, header,
+ sizeof(struct acpi_table_header));
+ acpi_os_unmap_memory(header, sizeof(struct acpi_table_header));
break;
-
default:
- ACPI_REPORT_ERROR (("Invalid address flags %X\n",
- address->pointer_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_REPORT_ERROR(("Invalid address flags %X\n",
+ address->pointer_type));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
- return_header->signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
+ return_header->signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_body
@@ -209,37 +193,33 @@ acpi_tb_get_table_header (
******************************************************************************/
acpi_status
-acpi_tb_get_table_body (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_get_table_body(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_body");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_get_table_body");
if (!table_info || !address) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Attempt table override. */
- status = acpi_tb_table_override (header, table_info);
- if (ACPI_SUCCESS (status)) {
+ status = acpi_tb_table_override(header, table_info);
+ if (ACPI_SUCCESS(status)) {
/* Table was overridden by the host OS */
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* No override, get the original table */
- status = acpi_tb_get_this_table (address, header, table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_this_table(address, header, table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_table_override
@@ -255,61 +235,57 @@ acpi_tb_get_table_body (
******************************************************************************/
static acpi_status
-acpi_tb_table_override (
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_table_override(struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_header *new_table;
- acpi_status status;
- struct acpi_pointer address;
-
-
- ACPI_FUNCTION_TRACE ("tb_table_override");
+ struct acpi_table_header *new_table;
+ acpi_status status;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("tb_table_override");
/*
* The OSL will examine the header and decide whether to override this
* table. If it decides to override, a table will be returned in new_table,
* which we will then copy.
*/
- status = acpi_os_table_override (header, &new_table);
- if (ACPI_FAILURE (status)) {
+ status = acpi_os_table_override(header, &new_table);
+ if (ACPI_FAILURE(status)) {
/* Some severe error from the OSL, but we basically ignore it */
- ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ ACPI_REPORT_ERROR(("Could not override ACPI table, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
if (!new_table) {
/* No table override */
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* We have a new table to override the old one. Get a copy of
* the new one. We know that the new table has a logical pointer.
*/
- address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
address.pointer.logical = new_table;
- status = acpi_tb_get_this_table (&address, new_table, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not copy override ACPI table, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_this_table(&address, new_table, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not copy override ACPI table, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* Copy the table info */
- ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n",
- table_info->pointer->signature));
+ ACPI_REPORT_INFO(("Table [%4.4s] replaced by host OS\n",
+ table_info->pointer->signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_this_table
@@ -329,18 +305,15 @@ acpi_tb_table_override (
******************************************************************************/
static acpi_status
-acpi_tb_get_this_table (
- struct acpi_pointer *address,
- struct acpi_table_header *header,
- struct acpi_table_desc *table_info)
+acpi_tb_get_this_table(struct acpi_pointer *address,
+ struct acpi_table_header *header,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_header *full_table = NULL;
- u8 allocation;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_this_table");
+ struct acpi_table_header *full_table = NULL;
+ u8 allocation;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("tb_get_this_table");
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -352,38 +325,33 @@ acpi_tb_get_this_table (
/* Pointer matches processor mode, copy the table to a new buffer */
- full_table = ACPI_MEM_ALLOCATE (header->length);
+ full_table = ACPI_MEM_ALLOCATE(header->length);
if (!full_table) {
- ACPI_REPORT_ERROR ((
- "Could not allocate table memory for [%4.4s] length %X\n",
- header->signature, header->length));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_REPORT_ERROR(("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the entire table (including header) to the local buffer */
- ACPI_MEMCPY (full_table, address->pointer.logical, header->length);
+ ACPI_MEMCPY(full_table, address->pointer.logical,
+ header->length);
/* Save allocation type */
allocation = ACPI_MEM_ALLOCATED;
break;
-
case ACPI_LOGMODE_PHYSPTR:
/*
* Just map the table's physical memory
* into our address space.
*/
- status = acpi_os_map_memory (address->pointer.physical,
- (acpi_size) header->length, (void *) &full_table);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
- header->signature,
- ACPI_FORMAT_UINT64 (address->pointer.physical),
- header->length));
+ status = acpi_os_map_memory(address->pointer.physical,
+ (acpi_size) header->length,
+ (void *)&full_table);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64(address->pointer.physical), header->length));
return (status);
}
@@ -392,12 +360,11 @@ acpi_tb_get_this_table (
allocation = ACPI_MEM_MAPPED;
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n",
- address->pointer_type));
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid address flags %X\n",
+ address->pointer_type));
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -405,10 +372,10 @@ acpi_tb_get_this_table (
* even the ones whose signature we don't recognize
*/
if (table_info->type != ACPI_TABLE_FACS) {
- status = acpi_tb_verify_table_checksum (full_table);
+ status = acpi_tb_verify_table_checksum(full_table);
#if (!ACPI_CHECKSUM_ABORT)
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Ignore the error if configuration says so */
status = AE_OK;
@@ -418,19 +385,19 @@ acpi_tb_get_this_table (
/* Return values */
- table_info->pointer = full_table;
- table_info->length = (acpi_size) header->length;
- table_info->allocation = allocation;
+ table_info->pointer = full_table;
+ table_info->length = (acpi_size) header->length;
+ table_info->allocation = allocation;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
- full_table->signature,
- ACPI_FORMAT_UINT64 (address->pointer.physical), full_table));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
+ full_table->signature,
+ ACPI_FORMAT_UINT64(address->pointer.physical),
+ full_table));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_ptr
@@ -447,24 +414,20 @@ acpi_tb_get_this_table (
******************************************************************************/
acpi_status
-acpi_tb_get_table_ptr (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header **table_ptr_loc)
+acpi_tb_get_table_ptr(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header **table_ptr_loc)
{
- struct acpi_table_desc *table_desc;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_ptr");
+ struct acpi_table_desc *table_desc;
+ u32 i;
+ ACPI_FUNCTION_TRACE("tb_get_table_ptr");
if (!acpi_gbl_DSDT) {
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (table_type > ACPI_TABLE_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -476,15 +439,16 @@ acpi_tb_get_table_ptr (
*table_ptr_loc = NULL;
if (acpi_gbl_table_lists[table_type].next) {
- *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer;
+ *table_ptr_loc =
+ acpi_gbl_table_lists[table_type].next->pointer;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Check for instance out of range */
if (instance > acpi_gbl_table_lists[table_type].count) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Walk the list to get the desired table
@@ -503,6 +467,5 @@ acpi_tb_get_table_ptr (
*table_ptr_loc = table_desc->pointer;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index eea5b8cb5ebb..8d72343537e7 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -41,27 +41,21 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbgetall")
+ACPI_MODULE_NAME("tbgetall")
/* Local prototypes */
-
static acpi_status
-acpi_tb_get_primary_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info);
+acpi_tb_get_primary_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info);
static acpi_status
-acpi_tb_get_secondary_table (
- struct acpi_pointer *address,
- acpi_string signature,
- struct acpi_table_desc *table_info);
-
+acpi_tb_get_secondary_table(struct acpi_pointer *address,
+ acpi_string signature,
+ struct acpi_table_desc *table_info);
/*******************************************************************************
*
@@ -77,58 +71,54 @@ acpi_tb_get_secondary_table (
******************************************************************************/
static acpi_status
-acpi_tb_get_primary_table (
- struct acpi_pointer *address,
- struct acpi_table_desc *table_info)
+acpi_tb_get_primary_table(struct acpi_pointer *address,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_primary_table");
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE("tb_get_primary_table");
/* Ignore a NULL address in the RSDT */
if (!address->pointer.value) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Get the header in order to get signature and table size */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Clear the table_info */
- ACPI_MEMSET (table_info, 0, sizeof (struct acpi_table_desc));
+ ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc));
/*
* Check the table signature and make sure it is recognized.
* Also checks the header checksum
*/
table_info->pointer = &header;
- status = acpi_tb_recognize_table (table_info, ACPI_TABLE_PRIMARY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table */
- status = acpi_tb_install_table (table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_install_table(table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_secondary_table
@@ -143,32 +133,27 @@ acpi_tb_get_primary_table (
******************************************************************************/
static acpi_status
-acpi_tb_get_secondary_table (
- struct acpi_pointer *address,
- acpi_string signature,
- struct acpi_table_desc *table_info)
+acpi_tb_get_secondary_table(struct acpi_pointer *address,
+ acpi_string signature,
+ struct acpi_table_desc *table_info)
{
- acpi_status status;
- struct acpi_table_header header;
-
-
- ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature);
+ acpi_status status;
+ struct acpi_table_header header;
+ ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature);
/* Get the header in order to match the signature */
- status = acpi_tb_get_table_header (address, &header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_header(address, &header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Signature must match request */
- if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
- ACPI_REPORT_ERROR ((
- "Incorrect table signature - wanted [%s] found [%4.4s]\n",
- signature, header.signature));
- return_ACPI_STATUS (AE_BAD_SIGNATURE);
+ if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
+ ACPI_REPORT_ERROR(("Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature));
+ return_ACPI_STATUS(AE_BAD_SIGNATURE);
}
/*
@@ -176,25 +161,24 @@ acpi_tb_get_secondary_table (
* Also checks the header checksum
*/
table_info->pointer = &header;
- status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the entire table */
- status = acpi_tb_get_table_body (address, &header, table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(address, &header, table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table */
- status = acpi_tb_install_table (table_info);
- return_ACPI_STATUS (status);
+ status = acpi_tb_install_table(table_info);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_required_tables
@@ -214,23 +198,19 @@ acpi_tb_get_secondary_table (
*
******************************************************************************/
-acpi_status
-acpi_tb_get_required_tables (
- void)
+acpi_status acpi_tb_get_required_tables(void)
{
- acpi_status status = AE_OK;
- u32 i;
- struct acpi_table_desc table_info;
- struct acpi_pointer address;
-
+ acpi_status status = AE_OK;
+ u32 i;
+ struct acpi_table_desc table_info;
+ struct acpi_pointer address;
- ACPI_FUNCTION_TRACE ("tb_get_required_tables");
+ ACPI_FUNCTION_TRACE("tb_get_required_tables");
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
- acpi_gbl_rsdt_table_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
+ acpi_gbl_rsdt_table_count));
-
- address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
/*
* Loop through all table pointers found in RSDT.
@@ -243,84 +223,79 @@ acpi_tb_get_required_tables (
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
/* Get the table address from the common internal XSDT */
- address.pointer.value =
- acpi_gbl_XSDT->table_offset_entry[i];
+ address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
/*
* Get the tables needed by this subsystem (FADT and any SSDTs).
* NOTE: All other tables are completely ignored at this time.
*/
- status = acpi_tb_get_primary_table (&address, &table_info);
+ status = acpi_tb_get_primary_table(&address, &table_info);
if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
- ACPI_REPORT_WARNING (("%s, while getting table at %8.8X%8.8X\n",
- acpi_format_exception (status),
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ ACPI_REPORT_WARNING(("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception(status), ACPI_FORMAT_UINT64(address.pointer.value)));
}
}
/* We must have a FADT to continue */
if (!acpi_gbl_FADT) {
- ACPI_REPORT_ERROR (("No FADT present in RSDT/XSDT\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ ACPI_REPORT_ERROR(("No FADT present in RSDT/XSDT\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* Convert the FADT to a common format. This allows earlier revisions of
* the table to coexist with newer versions, using common access code.
*/
- status = acpi_tb_convert_table_fadt ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "Could not convert FADT to internal common format\n"));
- return_ACPI_STATUS (status);
+ status = acpi_tb_convert_table_fadt();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not convert FADT to internal common format\n"));
+ return_ACPI_STATUS(status);
}
/* Get the FACS (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl;
- status = acpi_tb_get_secondary_table (&address, FACS_SIG, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get/install the FACS, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get/install the FACS, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
* Create the common FACS pointer table
* (Contains pointers to the original table)
*/
- status = acpi_tb_build_common_facs (&table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_build_common_facs(&table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get/install the DSDT (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->Xdsdt;
- status = acpi_tb_get_secondary_table (&address, DSDT_SIG, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not get/install the DSDT\n"));
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not get/install the DSDT\n"));
+ return_ACPI_STATUS(status);
}
/* Set Integer Width (32/64) based upon DSDT revision */
- acpi_ut_set_integer_width (acpi_gbl_DSDT->revision);
+ acpi_ut_set_integer_width(acpi_gbl_DSDT->revision);
/* Dump the entire DSDT */
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
- "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
- acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width));
- ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
+ acpi_gbl_DSDT->length, acpi_gbl_DSDT->length,
+ acpi_gbl_integer_bit_width));
+ ACPI_DUMP_BUFFER((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
/* Always delete the RSDP mapping, we are done with it */
- acpi_tb_delete_tables_by_type (ACPI_TABLE_RSDP);
- return_ACPI_STATUS (status);
+ acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 629b64c8193d..10db8484e462 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -41,22 +41,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbinstal")
+ACPI_MODULE_NAME("tbinstal")
/* Local prototypes */
-
static acpi_status
-acpi_tb_match_signature (
- char *signature,
- struct acpi_table_desc *table_info,
- u8 search_type);
-
+acpi_tb_match_signature(char *signature,
+ struct acpi_table_desc *table_info, u8 search_type);
/*******************************************************************************
*
@@ -74,16 +68,12 @@ acpi_tb_match_signature (
******************************************************************************/
static acpi_status
-acpi_tb_match_signature (
- char *signature,
- struct acpi_table_desc *table_info,
- u8 search_type)
+acpi_tb_match_signature(char *signature,
+ struct acpi_table_desc *table_info, u8 search_type)
{
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("tb_match_signature");
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("tb_match_signature");
/* Search for a signature match among the known table types */
@@ -92,30 +82,30 @@ acpi_tb_match_signature (
continue;
}
- if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature,
- acpi_gbl_table_data[i].sig_length)) {
+ if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature,
+ acpi_gbl_table_data[i].sig_length)) {
/* Found a signature match, return index if requested */
if (table_info) {
table_info->type = (u8) i;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
- (char *) acpi_gbl_table_data[i].signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
+ (char *)acpi_gbl_table_data[i].
+ signature));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
- (char *) signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
+ (char *)signature));
- return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED);
+ return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_install_table
@@ -124,46 +114,52 @@ acpi_tb_match_signature (
*
* RETURN: Status
*
- * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must
- * already be loaded and validated.
- * Install the table into the global data structs.
+ * DESCRIPTION: Install the table into the global data structures.
*
******************************************************************************/
-acpi_status
-acpi_tb_install_table (
- struct acpi_table_desc *table_info)
+acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info)
{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE ("tb_install_table");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_install_table");
/* Lock tables while installing */
- status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n",
- table_info->pointer->signature, acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not acquire table mutex, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Ignore a table that is already installed. For example, some BIOS
+ * ASL code will repeatedly attempt to load the same SSDT.
+ */
+ status = acpi_tb_is_table_installed(table_info);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
}
/* Install the table into the global data structure */
- status = acpi_tb_init_table_descriptor (table_info->type, table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n",
- table_info->pointer->signature, acpi_format_exception (status)));
+ status = acpi_tb_init_table_descriptor(table_info->type, table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not install table [%4.4s], %s\n",
+ table_info->pointer->signature,
+ acpi_format_exception(status)));
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n",
- acpi_gbl_table_data[table_info->type].name, table_info->pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n",
+ acpi_gbl_table_data[table_info->type].name,
+ table_info->pointer));
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_recognize_table
@@ -186,22 +182,18 @@ acpi_tb_install_table (
******************************************************************************/
acpi_status
-acpi_tb_recognize_table (
- struct acpi_table_desc *table_info,
- u8 search_type)
+acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type)
{
- struct acpi_table_header *table_header;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("tb_recognize_table");
+ struct acpi_table_header *table_header;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_recognize_table");
/* Ensure that we have a valid table pointer */
- table_header = (struct acpi_table_header *) table_info->pointer;
+ table_header = (struct acpi_table_header *)table_info->pointer;
if (!table_header) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
@@ -212,25 +204,24 @@ acpi_tb_recognize_table (
* This can be any one of many valid ACPI tables, it just isn't one of
* the tables that is consumed by the core subsystem
*/
- status = acpi_tb_match_signature (table_header->signature,
- table_info, search_type);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_match_signature(table_header->signature,
+ table_info, search_type);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- status = acpi_tb_validate_table_header (table_header);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_validate_table_header(table_header);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Return the table type and length via the info struct */
table_info->length = (acpi_size) table_header->length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_table_descriptor
@@ -245,22 +236,27 @@ acpi_tb_recognize_table (
******************************************************************************/
acpi_status
-acpi_tb_init_table_descriptor (
- acpi_table_type table_type,
- struct acpi_table_desc *table_info)
+acpi_tb_init_table_descriptor(acpi_table_type table_type,
+ struct acpi_table_desc *table_info)
{
- struct acpi_table_list *list_head;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type);
+ struct acpi_table_list *list_head;
+ struct acpi_table_desc *table_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type);
/* Allocate a descriptor for this table */
- table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+ table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
if (!table_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Get a new owner ID for the table */
+
+ status = acpi_ut_allocate_owner_id(&table_desc->owner_id);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the table into the global data structure */
@@ -272,14 +268,14 @@ acpi_tb_init_table_descriptor (
* includes most ACPI tables such as the DSDT. 2) Multiple instances of
* the table are allowed. This includes SSDT and PSDTs.
*/
- if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) {
+ if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) {
/*
* Only one table allowed, and a table has alread been installed
* at this location, so return an error.
*/
if (list_head->next) {
- ACPI_MEM_FREE (table_desc);
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ ACPI_MEM_FREE(table_desc);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
table_desc->next = list_head->next;
@@ -290,8 +286,7 @@ acpi_tb_init_table_descriptor (
}
list_head->count++;
- }
- else {
+ } else {
/*
* Link the new table in to the list of tables of this type.
* Insert at the end of the list, order IS IMPORTANT.
@@ -302,8 +297,7 @@ acpi_tb_init_table_descriptor (
if (!list_head->next) {
list_head->next = table_desc;
- }
- else {
+ } else {
table_desc->next = list_head->next;
while (table_desc->next->next) {
@@ -318,15 +312,14 @@ acpi_tb_init_table_descriptor (
/* Finish initialization of the table descriptor */
- table_desc->type = (u8) table_type;
- table_desc->pointer = table_info->pointer;
- table_desc->length = table_info->length;
- table_desc->allocation = table_info->allocation;
- table_desc->aml_start = (u8 *) (table_desc->pointer + 1),
- table_desc->aml_length = (u32) (table_desc->length -
- (u32) sizeof (struct acpi_table_header));
- table_desc->table_id = acpi_ut_allocate_owner_id (
- ACPI_OWNER_TYPE_TABLE);
+ table_desc->type = (u8) table_type;
+ table_desc->pointer = table_info->pointer;
+ table_desc->length = table_info->length;
+ table_desc->allocation = table_info->allocation;
+ table_desc->aml_start = (u8 *) (table_desc->pointer + 1),
+ table_desc->aml_length = (u32) (table_desc->length -
+ (u32) sizeof(struct
+ acpi_table_header));
table_desc->loaded_into_namespace = FALSE;
/*
@@ -334,18 +327,18 @@ acpi_tb_init_table_descriptor (
* newly installed table
*/
if (acpi_gbl_table_data[table_type].global_ptr) {
- *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer;
+ *(acpi_gbl_table_data[table_type].global_ptr) =
+ table_info->pointer;
}
/* Return Data */
- table_info->table_id = table_desc->table_id;
- table_info->installed_desc = table_desc;
+ table_info->owner_id = table_desc->owner_id;
+ table_info->installed_desc = table_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_all_tables
@@ -358,23 +351,19 @@ acpi_tb_init_table_descriptor (
*
******************************************************************************/
-void
-acpi_tb_delete_all_tables (
- void)
+void acpi_tb_delete_all_tables(void)
{
- acpi_table_type type;
-
+ acpi_table_type type;
/*
* Free memory allocated for ACPI tables
* Memory can either be mapped or allocated
*/
for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) {
- acpi_tb_delete_tables_by_type (type);
+ acpi_tb_delete_tables_by_type(type);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_tables_by_type
@@ -388,23 +377,19 @@ acpi_tb_delete_all_tables (
*
******************************************************************************/
-void
-acpi_tb_delete_tables_by_type (
- acpi_table_type type)
+void acpi_tb_delete_tables_by_type(acpi_table_type type)
{
- struct acpi_table_desc *table_desc;
- u32 count;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type);
+ struct acpi_table_desc *table_desc;
+ u32 count;
+ u32 i;
+ ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type);
if (type > ACPI_TABLE_MAX) {
return_VOID;
}
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_TABLES))) {
+ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) {
return;
}
@@ -442,21 +427,20 @@ acpi_tb_delete_tables_by_type (
* 1) Get the head of the list
*/
table_desc = acpi_gbl_table_lists[type].next;
- count = acpi_gbl_table_lists[type].count;
+ count = acpi_gbl_table_lists[type].count;
/*
* 2) Walk the entire list, deleting both the allocated tables
* and the table descriptors
*/
for (i = 0; i < count; i++) {
- table_desc = acpi_tb_uninstall_table (table_desc);
+ table_desc = acpi_tb_uninstall_table(table_desc);
}
- (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_single_table
@@ -470,15 +454,12 @@ acpi_tb_delete_tables_by_type (
*
******************************************************************************/
-void
-acpi_tb_delete_single_table (
- struct acpi_table_desc *table_desc)
+void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc)
{
/* Must have a valid table descriptor and pointer */
- if ((!table_desc) ||
- (!table_desc->pointer)) {
+ if ((!table_desc) || (!table_desc->pointer)) {
return;
}
@@ -490,12 +471,12 @@ acpi_tb_delete_single_table (
case ACPI_MEM_ALLOCATED:
- ACPI_MEM_FREE (table_desc->pointer);
+ ACPI_MEM_FREE(table_desc->pointer);
break;
case ACPI_MEM_MAPPED:
- acpi_os_unmap_memory (table_desc->pointer, table_desc->length);
+ acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
break;
default:
@@ -503,7 +484,6 @@ acpi_tb_delete_single_table (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_uninstall_table
@@ -518,26 +498,22 @@ acpi_tb_delete_single_table (
*
******************************************************************************/
-struct acpi_table_desc *
-acpi_tb_uninstall_table (
- struct acpi_table_desc *table_desc)
+struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
+ *table_desc)
{
- struct acpi_table_desc *next_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc);
+ struct acpi_table_desc *next_desc;
+ ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc);
if (!table_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Unlink the descriptor from the doubly linked list */
if (table_desc->prev) {
table_desc->prev->next = table_desc->next;
- }
- else {
+ } else {
/* Is first on list, update list head */
acpi_gbl_table_lists[table_desc->type].next = table_desc->next;
@@ -549,16 +525,14 @@ acpi_tb_uninstall_table (
/* Free the memory allocated for the table itself */
- acpi_tb_delete_single_table (table_desc);
+ acpi_tb_delete_single_table(table_desc);
/* Free the table descriptor */
next_desc = table_desc->next;
- ACPI_MEM_FREE (table_desc);
+ ACPI_MEM_FREE(table_desc);
/* Return pointer to the next descriptor */
- return_PTR (next_desc);
+ return_PTR(next_desc);
}
-
-
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index b7ffe39c3626..ad0252c2f7db 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -41,14 +41,11 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbrsdt")
-
+ACPI_MODULE_NAME("tbrsdt")
/*******************************************************************************
*
@@ -61,18 +58,13 @@
* DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
*
******************************************************************************/
-
-acpi_status
-acpi_tb_verify_rsdp (
- struct acpi_pointer *address)
+acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
{
- struct acpi_table_desc table_info;
- acpi_status status;
- struct rsdp_descriptor *rsdp;
-
-
- ACPI_FUNCTION_TRACE ("tb_verify_rsdp");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ struct rsdp_descriptor *rsdp;
+ ACPI_FUNCTION_TRACE("tb_verify_rsdp");
switch (address->pointer_type) {
case ACPI_LOGICAL_POINTER:
@@ -84,73 +76,53 @@ acpi_tb_verify_rsdp (
/*
* Obtain access to the RSDP structure
*/
- status = acpi_os_map_memory (address->pointer.physical,
- sizeof (struct rsdp_descriptor),
- (void *) &rsdp);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address->pointer.physical,
+ sizeof(struct rsdp_descriptor),
+ (void *)&rsdp);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /*
- * The signature and checksum must both be correct
- */
- if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
- /* Nope, BAD Signature */
+ /* Verify RSDP signature and checksum */
- status = AE_BAD_SIGNATURE;
+ status = acpi_tb_validate_rsdp(rsdp);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- /* Check the standard checksum */
-
- if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
- status = AE_BAD_CHECKSUM;
- goto cleanup;
- }
-
- /* Check extended checksum if table version >= 2 */
-
- if (rsdp->revision >= 2) {
- if (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) {
- status = AE_BAD_CHECKSUM;
- goto cleanup;
- }
- }
-
/* The RSDP supplied is OK */
- table_info.pointer = ACPI_CAST_PTR (struct acpi_table_header, rsdp);
- table_info.length = sizeof (struct rsdp_descriptor);
- table_info.allocation = ACPI_MEM_MAPPED;
+ table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
+ table_info.length = sizeof(struct rsdp_descriptor);
+ table_info.allocation = ACPI_MEM_MAPPED;
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Save the RSDP in a global for easy access */
- acpi_gbl_RSDP = ACPI_CAST_PTR (struct rsdp_descriptor, table_info.pointer);
- return_ACPI_STATUS (status);
-
+ acpi_gbl_RSDP =
+ ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer);
+ return_ACPI_STATUS(status);
/* Error exit */
-cleanup:
+ cleanup:
if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
- acpi_os_unmap_memory (rsdp, sizeof (struct rsdp_descriptor));
+ acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor));
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_rsdt_address
@@ -159,35 +131,35 @@ cleanup:
*
* RETURN: None, Address
*
- * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the
- * version of the RSDP
+ * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the
+ * version of the RSDP and whether the XSDT pointer is valid
*
******************************************************************************/
-void
-acpi_tb_get_rsdt_address (
- struct acpi_pointer *out_address)
+void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address)
{
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ out_address->pointer_type =
+ acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
- out_address->pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
+ /* Use XSDT if it is present */
- /*
- * For RSDP revision 0 or 1, we use the RSDT.
- * For RSDP revision 2 (and above), we use the XSDT
- */
- if (acpi_gbl_RSDP->revision < 2) {
- out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address;
- }
- else {
+ if ((acpi_gbl_RSDP->revision >= 2) &&
+ acpi_gbl_RSDP->xsdt_physical_address) {
out_address->pointer.value =
- acpi_gbl_RSDP->xsdt_physical_address;
+ acpi_gbl_RSDP->xsdt_physical_address;
+ acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT;
+ } else {
+ /* No XSDT, use the RSDT */
+
+ out_address->pointer.value =
+ acpi_gbl_RSDP->rsdt_physical_address;
+ acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT;
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_validate_rsdt
@@ -200,50 +172,43 @@ acpi_tb_get_rsdt_address (
*
******************************************************************************/
-acpi_status
-acpi_tb_validate_rsdt (
- struct acpi_table_header *table_ptr)
+acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
{
- int no_match;
-
-
- ACPI_FUNCTION_NAME ("tb_validate_rsdt");
+ int no_match;
+ ACPI_FUNCTION_NAME("tb_validate_rsdt");
/*
- * For RSDP revision 0 or 1, we use the RSDT.
- * For RSDP revision 2 and above, we use the XSDT
+ * Search for appropriate signature, RSDT or XSDT
*/
- if (acpi_gbl_RSDP->revision < 2) {
- no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG,
- sizeof (RSDT_SIG) -1);
- }
- else {
- no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG,
- sizeof (XSDT_SIG) -1);
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG,
+ sizeof(RSDT_SIG) - 1);
+ } else {
+ no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG,
+ sizeof(XSDT_SIG) - 1);
}
if (no_match) {
/* Invalid RSDT or XSDT signature */
- ACPI_REPORT_ERROR ((
- "Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
+ ACPI_REPORT_ERROR(("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));
- ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20);
+ ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR,
- "RSDT/XSDT signature at %X (%p) is invalid\n",
- acpi_gbl_RSDP->rsdt_physical_address,
- (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address));
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR,
+ "RSDT/XSDT signature at %X (%p) is invalid\n",
+ acpi_gbl_RSDP->rsdt_physical_address,
+ (void *)(acpi_native_uint) acpi_gbl_RSDP->
+ rsdt_physical_address));
- if (acpi_gbl_RSDP->revision < 2) {
- ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n"))
- }
- else {
- ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n"))
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ ACPI_REPORT_ERROR(("Looking for RSDT\n"))
+ } else {
+ ACPI_REPORT_ERROR(("Looking for XSDT\n"))
}
- ACPI_DUMP_BUFFER ((char *) table_ptr, 48);
+ ACPI_DUMP_BUFFER((char *)table_ptr, 48);
return (AE_BAD_SIGNATURE);
}
@@ -251,7 +216,6 @@ acpi_tb_validate_rsdt (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_rsdt
@@ -264,66 +228,61 @@ acpi_tb_validate_rsdt (
*
******************************************************************************/
-acpi_status
-acpi_tb_get_table_rsdt (
- void)
+acpi_status acpi_tb_get_table_rsdt(void)
{
- struct acpi_table_desc table_info;
- acpi_status status;
- struct acpi_pointer address;
-
-
- ACPI_FUNCTION_TRACE ("tb_get_table_rsdt");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("tb_get_table_rsdt");
/* Get the RSDT/XSDT via the RSDP */
- acpi_tb_get_rsdt_address (&address);
+ acpi_tb_get_rsdt_address(&address);
table_info.type = ACPI_TABLE_XSDT;
- status = acpi_tb_get_table (&address, &table_info);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT/XSDT, %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_table(&address, &table_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not get the RSDT/XSDT, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
- acpi_gbl_RSDP,
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n",
+ acpi_gbl_RSDP,
+ ACPI_FORMAT_UINT64(address.pointer.value)));
/* Check the RSDT or XSDT signature */
- status = acpi_tb_validate_rsdt (table_info.pointer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_validate_rsdt(table_info.pointer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the number of tables defined in the RSDT or XSDT */
- acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP,
- table_info.pointer);
+ acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP,
+ table_info.pointer);
/* Convert and/or copy to an XSDT structure */
- status = acpi_tb_convert_to_xsdt (&table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_convert_to_xsdt(&table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_XSDT, &table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- acpi_gbl_XSDT = ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info.pointer);
+ acpi_gbl_XSDT = ACPI_CAST_PTR(XSDT_DESCRIPTOR, table_info.pointer);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index e69d01d443d2..4b2fbb592f49 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -41,23 +41,84 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbutils")
+ACPI_MODULE_NAME("tbutils")
/* Local prototypes */
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
acpi_status
-acpi_tb_handle_to_object (
- u16 table_id,
- struct acpi_table_desc **table_desc);
+acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc);
#endif
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_is_table_installed
+ *
+ * PARAMETERS: new_table_desc - Descriptor for new table being installed
+ *
+ * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed
+ *
+ * DESCRIPTION: Determine if an ACPI table is already installed
+ *
+ * MUTEX: Table data structures should be locked
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc)
+{
+ struct acpi_table_desc *table_desc;
+
+ ACPI_FUNCTION_TRACE("tb_is_table_installed");
+
+ /* Get the list descriptor and first table descriptor */
+
+ table_desc = acpi_gbl_table_lists[new_table_desc->type].next;
+
+ /* Examine all installed tables of this type */
+
+ while (table_desc) {
+ /*
+ * If the table lengths match, perform a full bytewise compare. This
+ * means that we will allow tables with duplicate oem_table_id(s), as
+ * long as the tables are different in some way.
+ *
+ * Checking if the table has been loaded into the namespace means that
+ * we don't check for duplicate tables during the initial installation
+ * of tables within the RSDT/XSDT.
+ */
+ if ((table_desc->loaded_into_namespace) &&
+ (table_desc->pointer->length ==
+ new_table_desc->pointer->length)
+ &&
+ (!ACPI_MEMCMP
+ ((const char *)table_desc->pointer,
+ (const char *)new_table_desc->pointer,
+ (acpi_size) new_table_desc->pointer->length))) {
+ /* Match: this table is already installed */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
+ "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n",
+ new_table_desc->pointer->signature,
+ new_table_desc->pointer->revision,
+ new_table_desc->pointer->
+ oem_table_id));
+
+ new_table_desc->owner_id = table_desc->owner_id;
+ new_table_desc->installed_desc = table_desc;
+
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ }
+
+ /* Get next table on the list */
+
+ table_desc = table_desc->next;
+ }
+
+ return_ACPI_STATUS(AE_OK);
+}
/*******************************************************************************
*
@@ -80,57 +141,55 @@ acpi_tb_handle_to_object (
******************************************************************************/
acpi_status
-acpi_tb_validate_table_header (
- struct acpi_table_header *table_header)
+acpi_tb_validate_table_header(struct acpi_table_header *table_header)
{
- acpi_name signature;
-
-
- ACPI_FUNCTION_NAME ("tb_validate_table_header");
+ acpi_name signature;
+ ACPI_FUNCTION_NAME("tb_validate_table_header");
/* Verify that this is a valid address */
- if (!acpi_os_readable (table_header, sizeof (struct acpi_table_header))) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Cannot read table header at %p\n", table_header));
+ if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cannot read table header at %p\n",
+ table_header));
return (AE_BAD_ADDRESS);
}
/* Ensure that the signature is 4 ASCII characters */
- ACPI_MOVE_32_TO_32 (&signature, table_header->signature);
- if (!acpi_ut_valid_acpi_name (signature)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Table signature at %p [%p] has invalid characters\n",
- table_header, &signature));
+ ACPI_MOVE_32_TO_32(&signature, table_header->signature);
+ if (!acpi_ut_valid_acpi_name(signature)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Table signature at %p [%p] has invalid characters\n",
+ table_header, &signature));
- ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n",
- (char *) &signature));
+ ACPI_REPORT_WARNING(("Invalid table signature found: [%4.4s]\n",
+ (char *)&signature));
- ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
+ ACPI_DUMP_BUFFER(table_header,
+ sizeof(struct acpi_table_header));
return (AE_BAD_SIGNATURE);
}
/* Validate the table length */
- if (table_header->length < sizeof (struct acpi_table_header)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid length in table header %p name %4.4s\n",
- table_header, (char *) &signature));
+ if (table_header->length < sizeof(struct acpi_table_header)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid length in table header %p name %4.4s\n",
+ table_header, (char *)&signature));
- ACPI_REPORT_WARNING (("Invalid table header length (0x%X) found\n",
- (u32) table_header->length));
+ ACPI_REPORT_WARNING(("Invalid table header length (0x%X) found\n", (u32) table_header->length));
- ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header));
+ ACPI_DUMP_BUFFER(table_header,
+ sizeof(struct acpi_table_header));
return (AE_BAD_HEADER);
}
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_verify_table_checksum
@@ -145,37 +204,31 @@ acpi_tb_validate_table_header (
******************************************************************************/
acpi_status
-acpi_tb_verify_table_checksum (
- struct acpi_table_header *table_header)
+acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
{
- u8 checksum;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("tb_verify_table_checksum");
+ u8 checksum;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("tb_verify_table_checksum");
/* Compute the checksum on the table */
- checksum = acpi_tb_checksum (table_header, table_header->length);
+ checksum =
+ acpi_tb_generate_checksum(table_header, table_header->length);
/* Return the appropriate exception */
if (checksum) {
- ACPI_REPORT_WARNING ((
- "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n",
- table_header->signature, (u32) table_header->checksum,
- (u32) checksum));
+ ACPI_REPORT_WARNING(("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", table_header->signature, (u32) table_header->checksum, (u32) checksum));
status = AE_BAD_CHECKSUM;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
- * FUNCTION: acpi_tb_checksum
+ * FUNCTION: acpi_tb_generate_checksum
*
* PARAMETERS: Buffer - Buffer to checksum
* Length - Size of the buffer
@@ -186,15 +239,11 @@ acpi_tb_verify_table_checksum (
*
******************************************************************************/
-u8
-acpi_tb_checksum (
- void *buffer,
- u32 length)
+u8 acpi_tb_generate_checksum(void *buffer, u32 length)
{
- const u8 *limit;
- const u8 *rover;
- u8 sum = 0;
-
+ const u8 *limit;
+ const u8 *rover;
+ u8 sum = 0;
if (buffer && length) {
/* Buffer and Length are valid */
@@ -208,7 +257,6 @@ acpi_tb_checksum (
return (sum);
}
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
/*******************************************************************************
*
@@ -224,16 +272,13 @@ acpi_tb_checksum (
******************************************************************************/
acpi_status
-acpi_tb_handle_to_object (
- u16 table_id,
- struct acpi_table_desc **return_table_desc)
+acpi_tb_handle_to_object(u16 table_id,
+ struct acpi_table_desc ** return_table_desc)
{
- u32 i;
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_NAME ("tb_handle_to_object");
+ u32 i;
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_NAME("tb_handle_to_object");
for (i = 0; i < ACPI_TABLE_MAX; i++) {
table_desc = acpi_gbl_table_lists[i].next;
@@ -247,9 +292,8 @@ acpi_tb_handle_to_object (
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "table_id=%X does not exist\n",
+ table_id));
return (AE_BAD_PARAMETER);
}
#endif
-
-
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 0c0b9085dbeb..3f96a4909aad 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -48,10 +48,8 @@
#include <acpi/acnamesp.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbxface")
-
+ACPI_MODULE_NAME("tbxface")
/*******************************************************************************
*
@@ -65,25 +63,20 @@
* provided RSDT
*
******************************************************************************/
-
-acpi_status
-acpi_load_tables (
- void)
+acpi_status acpi_load_tables(void)
{
- struct acpi_pointer rsdp_address;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_load_tables");
+ struct acpi_pointer rsdp_address;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_load_tables");
/* Get the RSDP */
- status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
- &rsdp_address);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
- acpi_format_exception (status)));
+ status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
+ &rsdp_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n",
+ acpi_format_exception(status)));
goto error_exit;
}
@@ -91,54 +84,47 @@ acpi_load_tables (
acpi_gbl_table_flags = rsdp_address.pointer_type;
- status = acpi_tb_verify_rsdp (&rsdp_address);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_verify_rsdp(&rsdp_address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status)));
goto error_exit;
}
/* Get the RSDT via the RSDP */
- status = acpi_tb_get_table_rsdt ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_table_rsdt();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status)));
goto error_exit;
}
/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */
- status = acpi_tb_get_required_tables ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR ((
- "acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
- acpi_format_exception (status)));
+ status = acpi_tb_get_required_tables();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status)));
goto error_exit;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
/* Load the namespace from the tables */
- status = acpi_ns_load_namespace ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
- acpi_format_exception (status)));
+ status = acpi_ns_load_namespace();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status)));
goto error_exit;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
+ error_exit:
+ ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n",
+ acpi_format_exception(status)));
-error_exit:
- ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
- acpi_format_exception (status)));
-
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -156,40 +142,49 @@ error_exit:
*
******************************************************************************/
-acpi_status
-acpi_load_table (
- struct acpi_table_header *table_ptr)
+acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
{
- acpi_status status;
- struct acpi_table_desc table_info;
- struct acpi_pointer address;
-
-
- ACPI_FUNCTION_TRACE ("acpi_load_table");
+ acpi_status status;
+ struct acpi_table_desc table_info;
+ struct acpi_pointer address;
+ ACPI_FUNCTION_TRACE("acpi_load_table");
if (!table_ptr) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Copy the table to a local buffer */
- address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
+ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
address.pointer.logical = table_ptr;
- status = acpi_tb_get_table_body (&address, table_ptr, &table_info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_body(&address, table_ptr, &table_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Check signature for a valid table type */
+
+ status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Install the new table into the local data structures */
- status = acpi_tb_install_table (&table_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_install_table(&table_info);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ /* Table already exists, no error */
+
+ status = AE_OK;
+ }
+
/* Free table allocated by acpi_tb_get_table_body */
- acpi_tb_delete_single_table (&table_info);
- return_ACPI_STATUS (status);
+ acpi_tb_delete_single_table(&table_info);
+ return_ACPI_STATUS(status);
}
/* Convert the table to common format if necessary */
@@ -197,31 +192,32 @@ acpi_load_table (
switch (table_info.type) {
case ACPI_TABLE_FADT:
- status = acpi_tb_convert_table_fadt ();
+ status = acpi_tb_convert_table_fadt();
break;
case ACPI_TABLE_FACS:
- status = acpi_tb_build_common_facs (&table_info);
+ status = acpi_tb_build_common_facs(&table_info);
break;
default:
/* Load table into namespace if it contains executable AML */
- status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node);
+ status =
+ acpi_ns_load_table(table_info.installed_desc,
+ acpi_gbl_root_node);
break;
}
- if (ACPI_FAILURE (status)) {
+ if (ACPI_FAILURE(status)) {
/* Uninstall table and free the buffer */
- (void) acpi_tb_uninstall_table (table_info.installed_desc);
+ (void)acpi_tb_uninstall_table(table_info.installed_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_unload_table
@@ -234,20 +230,16 @@ acpi_load_table (
*
******************************************************************************/
-acpi_status
-acpi_unload_table (
- acpi_table_type table_type)
+acpi_status acpi_unload_table(acpi_table_type table_type)
{
- struct acpi_table_desc *table_desc;
-
-
- ACPI_FUNCTION_TRACE ("acpi_unload_table");
+ struct acpi_table_desc *table_desc;
+ ACPI_FUNCTION_TRACE("acpi_unload_table");
/* Parameter validation */
if (table_type > ACPI_TABLE_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Find all tables of the requested type */
@@ -260,18 +252,17 @@ acpi_unload_table (
* "Scope" operator. Thus, we need to track ownership by an ID, not
* simply a position within the hierarchy
*/
- acpi_ns_delete_namespace_by_owner (table_desc->table_id);
-
+ acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
+ acpi_ut_release_owner_id(&table_desc->owner_id);
table_desc = table_desc->next;
}
/* Delete (or unmap) all tables of this type */
- acpi_tb_delete_tables_by_type (table_type);
- return_ACPI_STATUS (AE_OK);
+ acpi_tb_delete_tables_by_type(table_type);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_table_header
@@ -294,54 +285,49 @@ acpi_unload_table (
******************************************************************************/
acpi_status
-acpi_get_table_header (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_table_header *out_table_header)
+acpi_get_table_header(acpi_table_type table_type,
+ u32 instance, struct acpi_table_header *out_table_header)
{
- struct acpi_table_header *tbl_ptr;
- acpi_status status;
+ struct acpi_table_header *tbl_ptr;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_get_table_header");
- ACPI_FUNCTION_TRACE ("acpi_get_table_header");
-
-
- if ((instance == 0) ||
- (table_type == ACPI_TABLE_RSDP) ||
- (!out_table_header)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((instance == 0) ||
+ (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
- (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
- instance > 1)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((table_type > ACPI_TABLE_MAX) ||
+ (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
+ instance > 1)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get a pointer to the entire table */
- status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* The function will return a NULL pointer if the table is not loaded */
if (tbl_ptr == NULL) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Copy the header to the caller's buffer */
- ACPI_MEMCPY ((void *) out_table_header, (void *) tbl_ptr,
- sizeof (struct acpi_table_header));
+ ACPI_MEMCPY((void *)out_table_header, (void *)tbl_ptr,
+ sizeof(struct acpi_table_header));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -367,43 +353,39 @@ acpi_get_table_header (
******************************************************************************/
acpi_status
-acpi_get_table (
- acpi_table_type table_type,
- u32 instance,
- struct acpi_buffer *ret_buffer)
+acpi_get_table(acpi_table_type table_type,
+ u32 instance, struct acpi_buffer *ret_buffer)
{
- struct acpi_table_header *tbl_ptr;
- acpi_status status;
- acpi_size table_length;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_table");
+ struct acpi_table_header *tbl_ptr;
+ acpi_status status;
+ acpi_size table_length;
+ ACPI_FUNCTION_TRACE("acpi_get_table");
/* Parameter validation */
if (instance == 0) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer (ret_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(ret_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
- (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
- instance > 1)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((table_type > ACPI_TABLE_MAX) ||
+ (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
+ instance > 1)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Get a pointer to the entire table */
- status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -411,7 +393,7 @@ acpi_get_table (
* table is not loaded.
*/
if (tbl_ptr == NULL) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the table length */
@@ -419,23 +401,22 @@ acpi_get_table (
if (table_type == ACPI_TABLE_RSDP) {
/* RSD PTR is the only "table" without a header */
- table_length = sizeof (struct rsdp_descriptor);
- }
- else {
+ table_length = sizeof(struct rsdp_descriptor);
+ } else {
table_length = (acpi_size) tbl_ptr->length;
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (ret_buffer, table_length);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_initialize_buffer(ret_buffer, table_length);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Copy the table to the buffer */
- ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MEMCPY((void *)ret_buffer->pointer, (void *)tbl_ptr, table_length);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_table);
+EXPORT_SYMBOL(acpi_get_table);
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index dc3c3f6a9f62..3b8a7e063e8a 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -46,22 +46,56 @@
#include <acpi/acpi.h>
#include <acpi/actables.h>
-
#define _COMPONENT ACPI_TABLES
- ACPI_MODULE_NAME ("tbxfroot")
+ACPI_MODULE_NAME("tbxfroot")
/* Local prototypes */
-
static acpi_status
-acpi_tb_find_rsdp (
- struct acpi_table_desc *table_info,
- u32 flags);
+acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags);
-static u8 *
-acpi_tb_scan_memory_for_rsdp (
- u8 *start_address,
- u32 length);
+static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_validate_rsdp
+ *
+ * PARAMETERS: Rsdp - Pointer to unvalidated RSDP
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Validate the RSDP (ptr)
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * The signature and checksum must both be correct
+ */
+ if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) {
+ /* Nope, BAD Signature */
+
+ return (AE_BAD_SIGNATURE);
+ }
+
+ /* Check the standard checksum */
+
+ if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
+ return (AE_BAD_CHECKSUM);
+ }
+
+ /* Check extended checksum if table version >= 2 */
+
+ if ((rsdp->revision >= 2) &&
+ (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
+ 0)) {
+ return (AE_BAD_CHECKSUM);
+ }
+
+ return (AE_OK);
+}
/*******************************************************************************
*
@@ -80,28 +114,24 @@ acpi_tb_scan_memory_for_rsdp (
******************************************************************************/
acpi_status
-acpi_tb_find_table (
- char *signature,
- char *oem_id,
- char *oem_table_id,
- struct acpi_table_header **table_ptr)
+acpi_tb_find_table(char *signature,
+ char *oem_id,
+ char *oem_table_id, struct acpi_table_header ** table_ptr)
{
- acpi_status status;
- struct acpi_table_header *table;
-
-
- ACPI_FUNCTION_TRACE ("tb_find_table");
+ acpi_status status;
+ struct acpi_table_header *table;
+ ACPI_FUNCTION_TRACE("tb_find_table");
/* Validate string lengths */
- if ((ACPI_STRLEN (signature) > ACPI_NAME_SIZE) ||
- (ACPI_STRLEN (oem_id) > sizeof (table->oem_id)) ||
- (ACPI_STRLEN (oem_table_id) > sizeof (table->oem_table_id))) {
- return_ACPI_STATUS (AE_AML_STRING_LIMIT);
+ if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
+ (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
+ (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
+ return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
- if (!ACPI_STRNCMP (signature, DSDT_SIG, ACPI_NAME_SIZE)) {
+ if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
/*
* The DSDT pointer is contained in the FADT, not the RSDT.
* This code should suffice, because the only code that would perform
@@ -110,40 +140,36 @@ acpi_tb_find_table (
* If this becomes insufficient, the FADT will have to be found first.
*/
if (!acpi_gbl_DSDT) {
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
table = acpi_gbl_DSDT;
- }
- else {
+ } else {
/* Find the table */
- status = acpi_get_firmware_table (signature, 1,
- ACPI_LOGICAL_ADDRESSING, &table);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_get_firmware_table(signature, 1,
+ ACPI_LOGICAL_ADDRESSING,
+ &table);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Check oem_id and oem_table_id */
- if ((oem_id[0] && ACPI_STRNCMP (
- oem_id, table->oem_id,
- sizeof (table->oem_id))) ||
-
- (oem_table_id[0] && ACPI_STRNCMP (
- oem_table_id, table->oem_table_id,
- sizeof (table->oem_table_id)))) {
- return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND);
+ if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
+ sizeof(table->oem_id))) ||
+ (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
+ sizeof(table->oem_table_id)))) {
+ return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n",
- table->signature));
+ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
+ table->signature));
*table_ptr = table;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_table
@@ -164,34 +190,28 @@ acpi_tb_find_table (
******************************************************************************/
acpi_status
-acpi_get_firmware_table (
- acpi_string signature,
- u32 instance,
- u32 flags,
- struct acpi_table_header **table_pointer)
+acpi_get_firmware_table(acpi_string signature,
+ u32 instance,
+ u32 flags, struct acpi_table_header **table_pointer)
{
- acpi_status status;
- struct acpi_pointer address;
- struct acpi_table_header *header = NULL;
- struct acpi_table_desc *table_info = NULL;
- struct acpi_table_desc *rsdt_info;
- u32 table_count;
- u32 i;
- u32 j;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_firmware_table");
+ acpi_status status;
+ struct acpi_pointer address;
+ struct acpi_table_header *header = NULL;
+ struct acpi_table_desc *table_info = NULL;
+ struct acpi_table_desc *rsdt_info;
+ u32 table_count;
+ u32 i;
+ u32 j;
+ ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
/*
* Ensure that at least the table manager is initialized. We don't
* require that the entire ACPI subsystem is up for this interface.
* If we have a buffer, we must have a length too
*/
- if ((instance == 0) ||
- (!signature) ||
- (!table_pointer)) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ if ((instance == 0) || (!signature) || (!table_pointer)) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Ensure that we have a RSDP */
@@ -199,48 +219,41 @@ acpi_get_firmware_table (
if (!acpi_gbl_RSDP) {
/* Get the RSDP */
- status = acpi_os_get_root_pointer (flags, &address);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ status = acpi_os_get_root_pointer(flags, &address);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n"));
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Map and validate the RSDP */
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
- status = acpi_os_map_memory (address.pointer.physical,
- sizeof (struct rsdp_descriptor), (void *) &acpi_gbl_RSDP);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory(address.pointer.physical,
+ sizeof(struct
+ rsdp_descriptor),
+ (void *)&acpi_gbl_RSDP);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
acpi_gbl_RSDP = address.pointer.logical;
}
- /* The signature and checksum must both be correct */
-
- if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG,
- sizeof (RSDP_SIG)-1) != 0) {
- /* Nope, BAD Signature */
+ /* The RDSP signature and checksum must both be correct */
- return_ACPI_STATUS (AE_BAD_SIGNATURE);
- }
-
- if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
- /* Nope, BAD Checksum */
-
- return_ACPI_STATUS (AE_BAD_CHECKSUM);
+ status = acpi_tb_validate_rsdp(acpi_gbl_RSDP);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Get the RSDT address via the RSDP */
- acpi_tb_get_rsdt_address (&address);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
- acpi_gbl_RSDP,
- ACPI_FORMAT_UINT64 (address.pointer.value)));
+ acpi_tb_get_rsdt_address(&address);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
+ acpi_gbl_RSDP,
+ ACPI_FORMAT_UINT64(address.pointer.value)));
/* Insert processor_mode flags */
@@ -248,30 +261,30 @@ acpi_get_firmware_table (
/* Get and validate the RSDT */
- rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+ rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
if (!rsdt_info) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- status = acpi_tb_get_table (&address, rsdt_info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_get_table(&address, rsdt_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
- status = acpi_tb_validate_rsdt (rsdt_info->pointer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_validate_rsdt(rsdt_info->pointer);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Allocate a scratch table header and table descriptor */
- header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
+ header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header));
if (!header) {
status = AE_NO_MEMORY;
goto cleanup;
}
- table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc));
+ table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
if (!table_info) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -279,7 +292,8 @@ acpi_get_firmware_table (
/* Get the number of table pointers within the RSDT */
- table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
+ table_count =
+ acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer);
address.pointer_type = acpi_gbl_table_flags | flags;
/*
@@ -287,35 +301,42 @@ acpi_get_firmware_table (
* requested table
*/
for (i = 0, j = 0; i < table_count; i++) {
- /* Get the next table pointer, handle RSDT vs. XSDT */
-
- if (acpi_gbl_RSDP->revision < 2) {
- address.pointer.value = (ACPI_CAST_PTR (
- RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
- }
- else {
- address.pointer.value = (ACPI_CAST_PTR (
- XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
+ /*
+ * Get the next table pointer, handle RSDT vs. XSDT
+ * RSDT pointers are 32 bits, XSDT pointers are 64 bits
+ */
+ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
+ address.pointer.value =
+ (ACPI_CAST_PTR
+ (RSDT_DESCRIPTOR,
+ rsdt_info->pointer))->table_offset_entry[i];
+ } else {
+ address.pointer.value =
+ (ACPI_CAST_PTR
+ (XSDT_DESCRIPTOR,
+ rsdt_info->pointer))->table_offset_entry[i];
}
/* Get the table header */
- status = acpi_tb_get_table_header (&address, header);
- if (ACPI_FAILURE (status)) {
+ status = acpi_tb_get_table_header(&address, header);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Compare table signatures and table instance */
- if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
+ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
/* An instance of the table was found */
j++;
if (j >= instance) {
/* Found the correct instance, get the entire table */
- status = acpi_tb_get_table_body (&address, header, table_info);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_tb_get_table_body(&address, header,
+ table_info);
+ if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -329,22 +350,23 @@ acpi_get_firmware_table (
status = AE_NOT_EXIST;
-
-cleanup:
- acpi_os_unmap_memory (rsdt_info->pointer,
- (acpi_size) rsdt_info->pointer->length);
- ACPI_MEM_FREE (rsdt_info);
+ cleanup:
+ if (rsdt_info->pointer) {
+ acpi_os_unmap_memory(rsdt_info->pointer,
+ (acpi_size) rsdt_info->pointer->length);
+ }
+ ACPI_MEM_FREE(rsdt_info);
if (header) {
- ACPI_MEM_FREE (header);
+ ACPI_MEM_FREE(header);
}
if (table_info) {
- ACPI_MEM_FREE (table_info);
+ ACPI_MEM_FREE(table_info);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_firmware_table);
+EXPORT_SYMBOL(acpi_get_firmware_table);
/* TBD: Move to a new file */
@@ -363,35 +385,29 @@ EXPORT_SYMBOL(acpi_get_firmware_table);
*
******************************************************************************/
-acpi_status
-acpi_find_root_pointer (
- u32 flags,
- struct acpi_pointer *rsdp_address)
+acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
{
- struct acpi_table_desc table_info;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_find_root_pointer");
+ struct acpi_table_desc table_info;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
/* Get the RSDP */
- status = acpi_tb_find_rsdp (&table_info, flags);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "RSDP structure not found, %s Flags=%X\n",
- acpi_format_exception (status), flags));
+ status = acpi_tb_find_rsdp(&table_info, flags);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "RSDP structure not found, %s Flags=%X\n",
+ acpi_format_exception(status), flags));
- return_ACPI_STATUS (AE_NO_ACPI_TABLES);
+ return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
rsdp_address->pointer.physical = table_info.physical_address;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
@@ -405,68 +421,45 @@ acpi_find_root_pointer (
*
******************************************************************************/
-static u8 *
-acpi_tb_scan_memory_for_rsdp (
- u8 *start_address,
- u32 length)
+static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
{
- u8 *mem_rover;
- u8 *end_address;
- u8 checksum;
-
-
- ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp");
+ acpi_status status;
+ u8 *mem_rover;
+ u8 *end_address;
+ ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp");
end_address = start_address + length;
/* Search from given start address for the requested length */
for (mem_rover = start_address; mem_rover < end_address;
- mem_rover += ACPI_RSDP_SCAN_STEP) {
- /* The signature and checksum must both be correct */
-
- if (ACPI_STRNCMP ((char *) mem_rover,
- RSDP_SIG, sizeof (RSDP_SIG) - 1) != 0) {
- /* No signature match, keep looking */
-
- continue;
- }
-
- /* Signature matches, check the appropriate checksum */
-
- if ((ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover))->revision < 2) {
- /* ACPI version 1.0 */
-
- checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH);
- }
- else {
- /* Post ACPI 1.0, use extended_checksum */
-
- checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_XCHECKSUM_LENGTH);
+ mem_rover += ACPI_RSDP_SCAN_STEP) {
+ /* The RSDP signature and checksum must both be correct */
+
+ status =
+ acpi_tb_validate_rsdp(ACPI_CAST_PTR
+ (struct rsdp_descriptor, mem_rover));
+ if (ACPI_SUCCESS(status)) {
+ /* Sig and checksum valid, we have found a real RSDP */
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "RSDP located at physical address %p\n",
+ mem_rover));
+ return_PTR(mem_rover);
}
- if (checksum == 0) {
- /* Checksum valid, we have found a valid RSDP */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "RSDP located at physical address %p\n", mem_rover));
- return_PTR (mem_rover);
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Found an RSDP at physical address %p, but it has a bad checksum\n",
- mem_rover));
+ /* No sig match or bad checksum, keep searching */
}
/* Searched entire block, no RSDP was found */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Searched entire block, no valid RSDP was found.\n"));
- return_PTR (NULL);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Searched entire block from %p, valid RSDP was not found\n",
+ start_address));
+ return_PTR(NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_tb_find_rsdp
@@ -490,18 +483,14 @@ acpi_tb_scan_memory_for_rsdp (
******************************************************************************/
static acpi_status
-acpi_tb_find_rsdp (
- struct acpi_table_desc *table_info,
- u32 flags)
+acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
{
- u8 *table_ptr;
- u8 *mem_rover;
- u32 physical_address;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("tb_find_rsdp");
+ u8 *table_ptr;
+ u8 *mem_rover;
+ u32 physical_address;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("tb_find_rsdp");
/*
* Scan supports either logical addressing or physical addressing
@@ -509,23 +498,25 @@ acpi_tb_find_rsdp (
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
- status = acpi_os_map_memory (
- (acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
- ACPI_EBDA_PTR_LENGTH, (void *) &table_ptr);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH,
+ (void *)&table_ptr);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH));
+
+ return_ACPI_STATUS(status);
}
- ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+ ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
/* Convert segment part to physical address */
physical_address <<= 4;
- acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
+ acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
/* EBDA present? */
@@ -534,59 +525,67 @@ acpi_tb_find_rsdp (
* 1b) Search EBDA paragraphs (EBDa is required to be a
* minimum of 1_k length)
*/
- status = acpi_os_map_memory (
- (acpi_physical_address) physical_address,
- ACPI_EBDA_WINDOW_SIZE, (void *) &table_ptr);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- physical_address, ACPI_EBDA_WINDOW_SIZE));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ physical_address,
+ ACPI_EBDA_WINDOW_SIZE,
+ (void *)&table_ptr);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ physical_address,
+ ACPI_EBDA_WINDOW_SIZE));
+
+ return_ACPI_STATUS(status);
}
- mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr,
- ACPI_EBDA_WINDOW_SIZE);
- acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+ mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr,
+ ACPI_EBDA_WINDOW_SIZE);
+ acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
- physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+ physical_address +=
+ ACPI_PTR_DIFF(mem_rover, table_ptr);
table_info->physical_address =
- (acpi_physical_address) physical_address;
- return_ACPI_STATUS (AE_OK);
+ (acpi_physical_address) physical_address;
+ return_ACPI_STATUS(AE_OK);
}
}
/*
* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
*/
- status = acpi_os_map_memory (
- (acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
- ACPI_HI_RSDP_WINDOW_SIZE, (void *) &table_ptr);
-
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not map memory at %8.8X for length %X\n",
- ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
-
- return_ACPI_STATUS (status);
+ status = acpi_os_map_memory((acpi_physical_address)
+ ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE,
+ (void *)&table_ptr);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Could not map memory at %8.8X for length %X\n",
+ ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE));
+
+ return_ACPI_STATUS(status);
}
- mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
- acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(table_ptr,
+ ACPI_HI_RSDP_WINDOW_SIZE);
+ acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
physical_address =
- ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
+ ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
+ table_ptr);
table_info->physical_address =
- (acpi_physical_address) physical_address;
- return_ACPI_STATUS (AE_OK);
+ (acpi_physical_address) physical_address;
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -596,8 +595,8 @@ acpi_tb_find_rsdp (
else {
/* 1a) Get the location of the EBDA */
- ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
- physical_address <<= 4; /* Convert segment to physical address */
+ ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION);
+ physical_address <<= 4; /* Convert segment to physical address */
/* EBDA present? */
@@ -606,34 +605,38 @@ acpi_tb_find_rsdp (
* 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
* 1_k length)
*/
- mem_rover = acpi_tb_scan_memory_for_rsdp (
- ACPI_PHYSADDR_TO_PTR (physical_address),
- ACPI_EBDA_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
+ (physical_address),
+ ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
- /* Found it, return the physical address */
+ /* Return the physical address */
- table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
- return_ACPI_STATUS (AE_OK);
+ table_info->physical_address =
+ ACPI_TO_INTEGER(mem_rover);
+ return_ACPI_STATUS(AE_OK);
}
}
/* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
- mem_rover = acpi_tb_scan_memory_for_rsdp (
- ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
- ACPI_HI_RSDP_WINDOW_SIZE);
+ mem_rover =
+ acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
+ (ACPI_HI_RSDP_WINDOW_BASE),
+ ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
/* Found it, return the physical address */
- table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
- return_ACPI_STATUS (AE_OK);
+ table_info->physical_address =
+ ACPI_TO_INTEGER(mem_rover);
+ return_ACPI_STATUS(AE_OK);
}
}
- /* RSDP signature was not found */
+ /* A valid RSDP was not found */
- return_ACPI_STATUS (AE_NOT_FOUND);
+ ACPI_REPORT_ERROR(("No valid RSDP was found\n"));
+ return_ACPI_STATUS(AE_NOT_FOUND);
}
#endif
-
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 79c3a686bc44..a24847c08f7f 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -70,9 +70,9 @@
#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
#define _COMPONENT ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME ("acpi_thermal")
+ACPI_MODULE_NAME("acpi_thermal")
-MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -80,143 +80,145 @@ static int tzp;
module_param(tzp, int, 0);
MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
-
-static int acpi_thermal_add (struct acpi_device *device);
-static int acpi_thermal_remove (struct acpi_device *device, int type);
+static int acpi_thermal_add(struct acpi_device *device);
+static int acpi_thermal_remove(struct acpi_device *device, int type);
static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_trip_points (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_trip_points(struct file *,
+ const char __user *, size_t,
+ loff_t *);
static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_cooling_mode(struct file *,
+ const char __user *, size_t,
+ loff_t *);
static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_polling(struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
+ size_t, loff_t *);
static struct acpi_driver acpi_thermal_driver = {
- .name = ACPI_THERMAL_DRIVER_NAME,
- .class = ACPI_THERMAL_CLASS,
- .ids = ACPI_THERMAL_HID,
- .ops = {
- .add = acpi_thermal_add,
- .remove = acpi_thermal_remove,
- },
+ .name = ACPI_THERMAL_DRIVER_NAME,
+ .class = ACPI_THERMAL_CLASS,
+ .ids = ACPI_THERMAL_HID,
+ .ops = {
+ .add = acpi_thermal_add,
+ .remove = acpi_thermal_remove,
+ },
};
struct acpi_thermal_state {
- u8 critical:1;
- u8 hot:1;
- u8 passive:1;
- u8 active:1;
- u8 reserved:4;
- int active_index;
+ u8 critical:1;
+ u8 hot:1;
+ u8 passive:1;
+ u8 active:1;
+ u8 reserved:4;
+ int active_index;
};
struct acpi_thermal_state_flags {
- u8 valid:1;
- u8 enabled:1;
- u8 reserved:6;
+ u8 valid:1;
+ u8 enabled:1;
+ u8 reserved:6;
};
struct acpi_thermal_critical {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
+ unsigned long temperature;
};
struct acpi_thermal_hot {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
+ unsigned long temperature;
};
struct acpi_thermal_passive {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
- unsigned long tc1;
- unsigned long tc2;
- unsigned long tsp;
- struct acpi_handle_list devices;
+ unsigned long temperature;
+ unsigned long tc1;
+ unsigned long tc2;
+ unsigned long tsp;
+ struct acpi_handle_list devices;
};
struct acpi_thermal_active {
struct acpi_thermal_state_flags flags;
- unsigned long temperature;
- struct acpi_handle_list devices;
+ unsigned long temperature;
+ struct acpi_handle_list devices;
};
struct acpi_thermal_trips {
struct acpi_thermal_critical critical;
- struct acpi_thermal_hot hot;
+ struct acpi_thermal_hot hot;
struct acpi_thermal_passive passive;
struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
};
struct acpi_thermal_flags {
- u8 cooling_mode:1; /* _SCP */
- u8 devices:1; /* _TZD */
- u8 reserved:6;
+ u8 cooling_mode:1; /* _SCP */
+ u8 devices:1; /* _TZD */
+ u8 reserved:6;
};
struct acpi_thermal {
- acpi_handle handle;
- acpi_bus_id name;
- unsigned long temperature;
- unsigned long last_temperature;
- unsigned long polling_frequency;
- u8 cooling_mode;
- volatile u8 zombie;
+ acpi_handle handle;
+ acpi_bus_id name;
+ unsigned long temperature;
+ unsigned long last_temperature;
+ unsigned long polling_frequency;
+ u8 cooling_mode;
+ volatile u8 zombie;
struct acpi_thermal_flags flags;
struct acpi_thermal_state state;
struct acpi_thermal_trips trips;
- struct acpi_handle_list devices;
- struct timer_list timer;
+ struct acpi_handle_list devices;
+ struct timer_list timer;
};
static struct file_operations acpi_thermal_state_fops = {
- .open = acpi_thermal_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_temp_fops = {
- .open = acpi_thermal_temp_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_temp_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_trip_fops = {
- .open = acpi_thermal_trip_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_trip_points,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_trip_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_trip_points,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_cooling_fops = {
- .open = acpi_thermal_cooling_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_cooling_mode,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_cooling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_cooling_mode,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static struct file_operations acpi_thermal_polling_fops = {
- .open = acpi_thermal_polling_open_fs,
- .read = seq_read,
- .write = acpi_thermal_write_polling,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_thermal_polling_open_fs,
+ .read = seq_read,
+ .write = acpi_thermal_write_polling,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* --------------------------------------------------------------------------
Thermal Zone Management
-------------------------------------------------------------------------- */
-static int
-acpi_thermal_get_temperature (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
@@ -225,41 +227,39 @@ acpi_thermal_get_temperature (
tz->last_temperature = tz->temperature;
- status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
+ tz->temperature));
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_polling_frequency (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
if (!tz)
return_VALUE(-EINVAL);
- status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TZP", NULL,
+ &tz->polling_frequency);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
+ tz->polling_frequency));
return_VALUE(0);
}
-
-static int
-acpi_thermal_set_polling (
- struct acpi_thermal *tz,
- int seconds)
+static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
{
ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
@@ -268,21 +268,19 @@ acpi_thermal_set_polling (
tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Polling frequency set to %lu seconds\n",
+ tz->polling_frequency));
return_VALUE(0);
}
-
-static int
-acpi_thermal_set_cooling_mode (
- struct acpi_thermal *tz,
- int mode)
+static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
{
- acpi_status status = AE_OK;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list arg_list = {1, &arg0};
- acpi_handle handle = NULL;
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
+ acpi_handle handle = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
@@ -303,19 +301,16 @@ acpi_thermal_set_cooling_mode (
tz->cooling_mode = mode;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
- mode?"passive":"active"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
+ mode ? "passive" : "active"));
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_trip_points (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
- int i = 0;
+ acpi_status status = AE_OK;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
@@ -324,111 +319,128 @@ acpi_thermal_get_trip_points (
/* Critical Shutdown (required) */
- status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
- &tz->trips.critical.temperature);
+ status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
+ &tz->trips.critical.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.critical.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
return_VALUE(-ENODEV);
- }
- else {
+ } else {
tz->trips.critical.flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found critical threshold [%lu]\n",
+ tz->trips.critical.temperature));
}
/* Critical Sleep (optional) */
- status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_HOT", NULL,
+ &tz->trips.hot.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.hot.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
- }
- else {
+ } else {
tz->trips.hot.flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
+ tz->trips.hot.temperature));
}
/* Passive: Processors (optional) */
- status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, "_PSV", NULL,
+ &tz->trips.passive.temperature);
if (ACPI_FAILURE(status)) {
tz->trips.passive.flags.valid = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
- }
- else {
+ } else {
tz->trips.passive.flags.valid = 1;
- status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TC1", NULL,
+ &tz->trips.passive.tc1);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TC2", NULL,
+ &tz->trips.passive.tc2);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp);
+ status =
+ acpi_evaluate_integer(tz->handle, "_TSP", NULL,
+ &tz->trips.passive.tsp);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
- status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices);
+ status =
+ acpi_evaluate_reference(tz->handle, "_PSL", NULL,
+ &tz->trips.passive.devices);
if (ACPI_FAILURE(status))
tz->trips.passive.flags.valid = 0;
if (!tz->trips.passive.flags.valid)
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid passive threshold\n"));
else
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found passive threshold [%lu]\n",
+ tz->trips.passive.temperature));
}
/* Active: Fans, etc. (optional) */
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- char name[5] = {'_','A','C',('0'+i),'\0'};
+ char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
- status = acpi_evaluate_integer(tz->handle, name, NULL, &tz->trips.active[i].temperature);
+ status =
+ acpi_evaluate_integer(tz->handle, name, NULL,
+ &tz->trips.active[i].temperature);
if (ACPI_FAILURE(status))
break;
name[2] = 'L';
- status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices);
+ status =
+ acpi_evaluate_reference(tz->handle, name, NULL,
+ &tz->trips.active[i].devices);
if (ACPI_SUCCESS(status)) {
tz->trips.active[i].flags.valid = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature));
- }
- else
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found active threshold [%d]:[%lu]\n",
+ i, tz->trips.active[i].temperature));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid active threshold [%d]\n",
+ i));
}
return_VALUE(0);
}
-
-static int
-acpi_thermal_get_devices (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_devices(struct acpi_thermal *tz)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
if (!tz)
return_VALUE(-EINVAL);
- status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
+ status =
+ acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
return_VALUE(0);
}
-
-static int
-acpi_thermal_call_usermode (
- char *path)
+static int acpi_thermal_call_usermode(char *path)
{
- char *argv[2] = {NULL, NULL};
- char *envp[3] = {NULL, NULL, NULL};
+ char *argv[2] = { NULL, NULL };
+ char *envp[3] = { NULL, NULL, NULL };
ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
@@ -440,19 +452,16 @@ acpi_thermal_call_usermode (
/* minimal command environment */
envp[0] = "HOME=/";
envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
+
call_usermodehelper(argv[0], argv, envp, 0);
return_VALUE(0);
}
-
-static int
-acpi_thermal_critical (
- struct acpi_thermal *tz)
+static int acpi_thermal_critical(struct acpi_thermal *tz)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_critical");
@@ -462,29 +471,28 @@ acpi_thermal_critical (
if (tz->temperature >= tz->trips.critical.temperature) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
tz->trips.critical.flags.enabled = 1;
- }
- else if (tz->trips.critical.flags.enabled)
+ } else if (tz->trips.critical.flags.enabled)
tz->trips.critical.flags.enabled = 0;
result = acpi_bus_get_device(tz->handle, &device);
if (result)
return_VALUE(result);
- printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature));
- acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled);
+ printk(KERN_EMERG
+ "Critical temperature reached (%ld C), shutting down.\n",
+ KELVIN_TO_CELSIUS(tz->temperature));
+ acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL,
+ tz->trips.critical.flags.enabled);
acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
return_VALUE(0);
}
-
-static int
-acpi_thermal_hot (
- struct acpi_thermal *tz)
+static int acpi_thermal_hot(struct acpi_thermal *tz)
{
- int result = 0;
- struct acpi_device *device = NULL;
+ int result = 0;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_hot");
@@ -494,30 +502,27 @@ acpi_thermal_hot (
if (tz->temperature >= tz->trips.hot.temperature) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
tz->trips.hot.flags.enabled = 1;
- }
- else if (tz->trips.hot.flags.enabled)
+ } else if (tz->trips.hot.flags.enabled)
tz->trips.hot.flags.enabled = 0;
result = acpi_bus_get_device(tz->handle, &device);
if (result)
return_VALUE(result);
- acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled);
+ acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT,
+ tz->trips.hot.flags.enabled);
/* TBD: Call user-mode "sleep(S4)" function */
return_VALUE(0);
}
-
-static int
-acpi_thermal_passive (
- struct acpi_thermal *tz)
+static int acpi_thermal_passive(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
struct acpi_thermal_passive *passive = NULL;
- int trend = 0;
- int i = 0;
+ int trend = 0;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_passive");
@@ -534,25 +539,29 @@ acpi_thermal_passive (
* accordingly. Note that we assume symmetry.
*/
if (tz->temperature >= passive->temperature) {
- trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
- trend, passive->tc1, tz->temperature,
- tz->last_temperature, passive->tc2,
- tz->temperature, passive->temperature));
+ trend =
+ (passive->tc1 * (tz->temperature - tz->last_temperature)) +
+ (passive->tc2 * (tz->temperature - passive->temperature));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
+ trend, passive->tc1, tz->temperature,
+ tz->last_temperature, passive->tc2,
+ tz->temperature, passive->temperature));
tz->trips.passive.flags.enabled = 1;
/* Heating up? */
if (trend > 0)
- for (i=0; i<passive->devices.count; i++)
- acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_INCREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ acpi_processor_set_thermal_limit(passive->
+ devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_INCREMENT);
/* Cooling off? */
else if (trend < 0)
- for (i=0; i<passive->devices.count; i++)
- acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ acpi_processor_set_thermal_limit(passive->
+ devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_DECREMENT);
}
/*
@@ -563,37 +572,35 @@ acpi_thermal_passive (
* assume symmetry.
*/
else if (tz->trips.passive.flags.enabled) {
- for (i=0; i<passive->devices.count; i++)
- result = acpi_processor_set_thermal_limit(
- passive->devices.handles[i],
- ACPI_PROCESSOR_LIMIT_DECREMENT);
+ for (i = 0; i < passive->devices.count; i++)
+ result =
+ acpi_processor_set_thermal_limit(passive->devices.
+ handles[i],
+ ACPI_PROCESSOR_LIMIT_DECREMENT);
if (result == 1) {
tz->trips.passive.flags.enabled = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Disabling passive cooling (zone is cool)\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Disabling passive cooling (zone is cool)\n"));
}
}
return_VALUE(0);
}
-
-static int
-acpi_thermal_active (
- struct acpi_thermal *tz)
+static int acpi_thermal_active(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
struct acpi_thermal_active *active = NULL;
- int i = 0;
- int j = 0;
- unsigned long maxtemp = 0;
+ int i = 0;
+ int j = 0;
+ unsigned long maxtemp = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_active");
if (!tz)
return_VALUE(-EINVAL);
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
active = &(tz->trips.active[i]);
if (!active || !active->flags.valid)
@@ -607,16 +614,27 @@ acpi_thermal_active (
*/
if (tz->temperature >= active->temperature) {
if (active->temperature > maxtemp)
- tz->state.active_index = i, maxtemp = active->temperature;
+ tz->state.active_index = i, maxtemp =
+ active->temperature;
if (!active->flags.enabled) {
for (j = 0; j < active->devices.count; j++) {
- result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0);
+ result =
+ acpi_bus_set_power(active->devices.
+ handles[j],
+ ACPI_STATE_D0);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to turn cooling device [%p] 'on'\n",
+ active->
+ devices.
+ handles[j]));
continue;
}
active->flags.enabled = 1;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Cooling device [%p] now 'on'\n",
+ active->devices.
+ handles[j]));
}
}
}
@@ -628,13 +646,21 @@ acpi_thermal_active (
*/
else if (active->flags.enabled) {
for (j = 0; j < active->devices.count; j++) {
- result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3);
+ result =
+ acpi_bus_set_power(active->devices.
+ handles[j],
+ ACPI_STATE_D3);
if (result) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Unable to turn cooling device [%p] 'off'\n",
+ active->devices.
+ handles[j]));
continue;
}
active->flags.enabled = 0;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j]));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Cooling device [%p] now 'off'\n",
+ active->devices.handles[j]));
}
}
}
@@ -642,28 +668,22 @@ acpi_thermal_active (
return_VALUE(0);
}
+static void acpi_thermal_check(void *context);
-static void acpi_thermal_check (void *context);
-
-static void
-acpi_thermal_run (
- unsigned long data)
+static void acpi_thermal_run(unsigned long data)
{
struct acpi_thermal *tz = (struct acpi_thermal *)data;
if (!tz->zombie)
- acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_thermal_check, (void *) data);
+ acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+ acpi_thermal_check, (void *)data);
}
-
-static void
-acpi_thermal_check (
- void *data)
+static void acpi_thermal_check(void *data)
{
- int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *) data;
- unsigned long sleep_time = 0;
- int i = 0;
+ int result = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ unsigned long sleep_time = 0;
+ int i = 0;
struct acpi_thermal_state state;
ACPI_FUNCTION_TRACE("acpi_thermal_check");
@@ -678,9 +698,9 @@ acpi_thermal_check (
result = acpi_thermal_get_temperature(tz);
if (result)
return_VOID;
-
+
memset(&tz->state, 0, sizeof(tz->state));
-
+
/*
* Check Trip Points
* -----------------
@@ -690,14 +710,18 @@ acpi_thermal_check (
* individual policy decides when it is exited (e.g. hysteresis).
*/
if (tz->trips.critical.flags.valid)
- state.critical |= (tz->temperature >= tz->trips.critical.temperature);
+ state.critical |=
+ (tz->temperature >= tz->trips.critical.temperature);
if (tz->trips.hot.flags.valid)
state.hot |= (tz->temperature >= tz->trips.hot.temperature);
if (tz->trips.passive.flags.valid)
- state.passive |= (tz->temperature >= tz->trips.passive.temperature);
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
+ state.passive |=
+ (tz->temperature >= tz->trips.passive.temperature);
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
if (tz->trips.active[i].flags.valid)
- state.active |= (tz->temperature >= tz->trips.active[i].temperature);
+ state.active |=
+ (tz->temperature >=
+ tz->trips.active[i].temperature);
/*
* Invoke Policy
@@ -726,7 +750,7 @@ acpi_thermal_check (
tz->state.hot = 1;
if (tz->trips.passive.flags.enabled)
tz->state.passive = 1;
- for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
if (tz->trips.active[i].flags.enabled)
tz->state.active = 1;
@@ -744,8 +768,8 @@ acpi_thermal_check (
else if (tz->polling_frequency > 0)
sleep_time = tz->polling_frequency * 100;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
- tz->name, tz->temperature, sleep_time));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
+ tz->name, tz->temperature, sleep_time));
/*
* Schedule Next Poll
@@ -754,12 +778,11 @@ acpi_thermal_check (
if (!sleep_time) {
if (timer_pending(&(tz->timer)))
del_timer(&(tz->timer));
- }
- else {
+ } else {
if (timer_pending(&(tz->timer)))
mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
else {
- tz->timer.data = (unsigned long) tz;
+ tz->timer.data = (unsigned long)tz;
tz->timer.function = acpi_thermal_run;
tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
add_timer(&(tz->timer));
@@ -769,16 +792,15 @@ acpi_thermal_check (
return_VOID;
}
-
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_thermal_dir;
+static struct proc_dir_entry *acpi_thermal_dir;
static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
@@ -787,7 +809,8 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "state: ");
- if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
+ if (!tz->state.critical && !tz->state.hot && !tz->state.passive
+ && !tz->state.active)
seq_puts(seq, "ok\n");
else {
if (tz->state.critical)
@@ -801,7 +824,7 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "\n");
}
-end:
+ end:
return_VALUE(0);
}
@@ -810,11 +833,10 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
}
-
static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
{
- int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ int result = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
@@ -825,10 +847,10 @@ static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
if (result)
goto end;
- seq_printf(seq, "temperature: %ld C\n",
- KELVIN_TO_CELSIUS(tz->temperature));
+ seq_printf(seq, "temperature: %ld C\n",
+ KELVIN_TO_CELSIUS(tz->temperature));
-end:
+ end:
return_VALUE(0);
}
@@ -837,12 +859,11 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
}
-
static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
- int i = 0;
- int j = 0;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ int i = 0;
+ int j = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
@@ -851,21 +872,22 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
if (tz->trips.critical.flags.valid)
seq_printf(seq, "critical (S5): %ld C\n",
- KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
+ KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
if (tz->trips.hot.flags.valid)
seq_printf(seq, "hot (S4): %ld C\n",
- KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
+ KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
if (tz->trips.passive.flags.valid) {
- seq_printf(seq, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
- KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
- tz->trips.passive.tc1,
- tz->trips.passive.tc2,
- tz->trips.passive.tsp);
- for (j=0; j<tz->trips.passive.devices.count; j++) {
-
- seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]);
+ seq_printf(seq,
+ "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
+ tz->trips.passive.tc1, tz->trips.passive.tc2,
+ tz->trips.passive.tsp);
+ for (j = 0; j < tz->trips.passive.devices.count; j++) {
+
+ seq_printf(seq, "0x%p ",
+ tz->trips.passive.devices.handles[j]);
}
seq_puts(seq, "\n");
}
@@ -874,14 +896,15 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
if (!(tz->trips.active[i].flags.valid))
break;
seq_printf(seq, "active[%d]: %ld C: devices=",
- i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
- for (j = 0; j < tz->trips.active[i].devices.count; j++)
+ i,
+ KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
+ for (j = 0; j < tz->trips.active[i].devices.count; j++)
seq_printf(seq, "0x%p ",
- tz->trips.active[i].devices.handles[j]);
+ tz->trips.active[i].devices.handles[j]);
seq_puts(seq, "\n");
}
-end:
+ end:
return_VALUE(0);
}
@@ -891,30 +914,28 @@ static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
}
static ssize_t
-acpi_thermal_write_trip_points (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_trip_points(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- char *limit_string;
- int num, critical, hot, passive;
- int *active;
- int i = 0;
+ char *limit_string;
+ int num, critical, hot, passive;
+ int *active;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
- if(!limit_string)
+ if (!limit_string)
return_VALUE(-ENOMEM);
memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
- active = kmalloc(ACPI_THERMAL_MAX_ACTIVE *sizeof(int), GFP_KERNEL);
- if(!active)
+ active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
+ if (!active)
return_VALUE(-ENOMEM);
if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
@@ -922,20 +943,21 @@ acpi_thermal_write_trip_points (
count = -EINVAL;
goto end;
}
-
+
if (copy_from_user(limit_string, buffer, count)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
count = -EFAULT;
goto end;
}
-
+
limit_string[count] = '\0';
num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &critical, &hot, &passive,
- &active[0], &active[1], &active[2], &active[3], &active[4],
- &active[5], &active[6], &active[7], &active[8], &active[9]);
- if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
+ &critical, &hot, &passive,
+ &active[0], &active[1], &active[2], &active[3], &active[4],
+ &active[5], &active[6], &active[7], &active[8],
+ &active[9]);
+ if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
count = -EINVAL;
goto end;
@@ -949,17 +971,16 @@ acpi_thermal_write_trip_points (
break;
tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
}
-
-end:
+
+ end:
kfree(active);
kfree(limit_string);
return_VALUE(count);
}
-
static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
@@ -970,33 +991,31 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
seq_puts(seq, "<setting not supported>\n");
}
- if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL )
+ if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL)
seq_printf(seq, "cooling mode: critical\n");
else
seq_printf(seq, "cooling mode: %s\n",
- tz->cooling_mode?"passive":"active");
+ tz->cooling_mode ? "passive" : "active");
-end:
+ end:
return_VALUE(0);
}
static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_thermal_cooling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_thermal_write_cooling_mode (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_cooling_mode(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- int result = 0;
- char mode_string[12] = {'\0'};
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ int result = 0;
+ char mode_string[12] = { '\0' };
ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
@@ -1008,11 +1027,12 @@ acpi_thermal_write_cooling_mode (
if (copy_from_user(mode_string, buffer, count))
return_VALUE(-EFAULT);
-
+
mode_string[count] = '\0';
-
- result = acpi_thermal_set_cooling_mode(tz,
- simple_strtoul(mode_string, NULL, 0));
+
+ result = acpi_thermal_set_cooling_mode(tz,
+ simple_strtoul(mode_string, NULL,
+ 0));
if (result)
return_VALUE(result);
@@ -1021,10 +1041,9 @@ acpi_thermal_write_cooling_mode (
return_VALUE(count);
}
-
static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
@@ -1037,43 +1056,41 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
}
seq_printf(seq, "polling frequency: %lu seconds\n",
- (tz->polling_frequency / 10));
+ (tz->polling_frequency / 10));
-end:
+ end:
return_VALUE(0);
}
static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_thermal_polling_seq_show,
- PDE(inode)->data);
+ PDE(inode)->data);
}
static ssize_t
-acpi_thermal_write_polling (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *ppos)
+acpi_thermal_write_polling(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
- int result = 0;
- char polling_string[12] = {'\0'};
- int seconds = 0;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ int result = 0;
+ char polling_string[12] = { '\0' };
+ int seconds = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
if (!tz || (count > sizeof(polling_string) - 1))
return_VALUE(-EINVAL);
-
+
if (copy_from_user(polling_string, buffer, count))
return_VALUE(-EFAULT);
-
+
polling_string[count] = '\0';
seconds = simple_strtoul(polling_string, NULL, 0);
-
+
result = acpi_thermal_set_polling(tz, seconds);
if (result)
return_VALUE(result);
@@ -1083,18 +1100,15 @@ acpi_thermal_write_polling (
return_VALUE(count);
}
-
-static int
-acpi_thermal_add_fs (
- struct acpi_device *device)
+static int acpi_thermal_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_thermal_dir);
+ acpi_thermal_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -1102,11 +1116,11 @@ acpi_thermal_add_fs (
/* 'state' [R] */
entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_STATE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_STATE));
else {
entry->proc_fops = &acpi_thermal_state_fops;
entry->data = acpi_driver_data(device);
@@ -1115,11 +1129,11 @@ acpi_thermal_add_fs (
/* 'temperature' [R] */
entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
- S_IRUGO, acpi_device_dir(device));
+ S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_TEMPERATURE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_TEMPERATURE));
else {
entry->proc_fops = &acpi_thermal_temp_fops;
entry->data = acpi_driver_data(device);
@@ -1128,11 +1142,12 @@ acpi_thermal_add_fs (
/* 'trip_points' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_TRIP_POINTS));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_TRIP_POINTS));
else {
entry->proc_fops = &acpi_thermal_trip_fops;
entry->data = acpi_driver_data(device);
@@ -1141,11 +1156,12 @@ acpi_thermal_add_fs (
/* 'cooling_mode' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_COOLING_MODE));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_COOLING_MODE));
else {
entry->proc_fops = &acpi_thermal_cooling_fops;
entry->data = acpi_driver_data(device);
@@ -1154,11 +1170,12 @@ acpi_thermal_add_fs (
/* 'polling_frequency' [R/W] */
entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_THERMAL_FILE_POLLING_FREQ));
+ "Unable to create '%s' fs entry\n",
+ ACPI_THERMAL_FILE_POLLING_FREQ));
else {
entry->proc_fops = &acpi_thermal_polling_fops;
entry->data = acpi_driver_data(device);
@@ -1168,10 +1185,7 @@ acpi_thermal_add_fs (
return_VALUE(0);
}
-
-static int
-acpi_thermal_remove_fs (
- struct acpi_device *device)
+static int acpi_thermal_remove_fs(struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
@@ -1193,19 +1207,14 @@ acpi_thermal_remove_fs (
return_VALUE(0);
}
-
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
-static void
-acpi_thermal_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_thermal *tz = (struct acpi_thermal *) data;
- struct acpi_device *device = NULL;
+ struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_notify");
@@ -1231,19 +1240,16 @@ acpi_thermal_notify (
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-
-static int
-acpi_thermal_get_info (
- struct acpi_thermal *tz)
+static int acpi_thermal_get_info(struct acpi_thermal *tz)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
@@ -1262,20 +1268,24 @@ acpi_thermal_get_info (
/* Set the cooling mode [_SCP] to active cooling (default) */
result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
- if (!result)
+ if (!result)
tz->flags.cooling_mode = 1;
- else {
+ else {
/* Oh,we have not _SCP method.
- Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
+ Generally show cooling_mode by _ACx, _PSV,spec 12.2 */
tz->flags.cooling_mode = 0;
- if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
- if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
+ if (tz->trips.active[0].flags.valid
+ && tz->trips.passive.flags.valid) {
+ if (tz->trips.passive.temperature >
+ tz->trips.active[0].temperature)
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
- else
+ else
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
- } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+ } else if (!tz->trips.active[0].flags.valid
+ && tz->trips.passive.flags.valid) {
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
- } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
+ } else if (tz->trips.active[0].flags.valid
+ && !tz->trips.passive.flags.valid) {
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
} else {
/* _ACx and _PSV are optional, but _CRT is required */
@@ -1297,14 +1307,11 @@ acpi_thermal_get_info (
return_VALUE(0);
}
-
-static int
-acpi_thermal_add (
- struct acpi_device *device)
+static int acpi_thermal_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_thermal *tz = NULL;
+ int result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_thermal *tz = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_add");
@@ -1335,19 +1342,20 @@ acpi_thermal_add (
acpi_thermal_check(tz);
status = acpi_install_notify_handler(tz->handle,
- ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz);
+ ACPI_DEVICE_NOTIFY,
+ acpi_thermal_notify, tz);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
- acpi_device_name(device), acpi_device_bid(device),
- KELVIN_TO_CELSIUS(tz->temperature));
+ acpi_device_name(device), acpi_device_bid(device),
+ KELVIN_TO_CELSIUS(tz->temperature));
-end:
+ end:
if (result) {
acpi_thermal_remove_fs(device);
kfree(tz);
@@ -1356,21 +1364,17 @@ end:
return_VALUE(result);
}
-
-static int
-acpi_thermal_remove (
- struct acpi_device *device,
- int type)
+static int acpi_thermal_remove(struct acpi_device *device, int type)
{
- acpi_status status = AE_OK;
- struct acpi_thermal *tz = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_thermal *tz = NULL;
ACPI_FUNCTION_TRACE("acpi_thermal_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- tz = (struct acpi_thermal *) acpi_driver_data(device);
+ tz = (struct acpi_thermal *)acpi_driver_data(device);
/* avoid timer adding new defer task */
tz->zombie = 1;
@@ -1382,19 +1386,19 @@ acpi_thermal_remove (
del_timer_sync(&(tz->timer));
status = acpi_remove_notify_handler(tz->handle,
- ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_thermal_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
/* Terminate policy */
- if (tz->trips.passive.flags.valid
- && tz->trips.passive.flags.enabled) {
+ if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) {
tz->trips.passive.flags.enabled = 0;
acpi_thermal_passive(tz);
}
if (tz->trips.active[0].flags.valid
- && tz->trips.active[0].flags.enabled) {
+ && tz->trips.active[0].flags.enabled) {
tz->trips.active[0].flags.enabled = 0;
acpi_thermal_active(tz);
}
@@ -1405,11 +1409,9 @@ acpi_thermal_remove (
return_VALUE(0);
}
-
-static int __init
-acpi_thermal_init (void)
+static int __init acpi_thermal_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_thermal_init");
@@ -1427,9 +1429,7 @@ acpi_thermal_init (void)
return_VALUE(0);
}
-
-static void __exit
-acpi_thermal_exit (void)
+static void __exit acpi_thermal_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_thermal_exit");
@@ -1440,6 +1440,5 @@ acpi_thermal_exit (void)
return_VOID;
}
-
module_init(acpi_thermal_init);
module_exit(acpi_thermal_exit);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 73b1d8aeae9d..7fe0b7ae9733 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -100,8 +100,7 @@ MODULE_LICENSE("GPL");
/* utility
*/
-static __inline__ void
-_set_bit(u32* word, u32 mask, int value)
+static __inline__ void _set_bit(u32 * word, u32 mask, int value)
{
*word = (*word & ~mask) | (mask * value);
}
@@ -109,35 +108,32 @@ _set_bit(u32* word, u32 mask, int value)
/* acpi interface wrappers
*/
-static int
-is_valid_acpi_path(const char* methodName)
+static int is_valid_acpi_path(const char *methodName)
{
acpi_handle handle;
acpi_status status;
- status = acpi_get_handle(NULL, (char*)methodName, &handle);
+ status = acpi_get_handle(NULL, (char *)methodName, &handle);
return !ACPI_FAILURE(status);
}
-static int
-write_acpi_int(const char* methodName, int val)
+static int write_acpi_int(const char *methodName, int val)
{
struct acpi_object_list params;
union acpi_object in_objs[1];
acpi_status status;
- params.count = sizeof(in_objs)/sizeof(in_objs[0]);
+ params.count = sizeof(in_objs) / sizeof(in_objs[0]);
params.pointer = in_objs;
in_objs[0].type = ACPI_TYPE_INTEGER;
in_objs[0].integer.value = val;
- status = acpi_evaluate_object(NULL, (char*)methodName, &params, NULL);
+ status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
return (status == AE_OK);
}
#if 0
-static int
-read_acpi_int(const char* methodName, int* pVal)
+static int read_acpi_int(const char *methodName, int *pVal)
{
struct acpi_buffer results;
union acpi_object out_objs[1];
@@ -146,25 +142,24 @@ read_acpi_int(const char* methodName, int* pVal)
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(0, (char*)methodName, 0, &results);
+ status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
*pVal = out_objs[0].integer.value;
return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
}
#endif
-static const char* method_hci /*= 0*/;
+static const char *method_hci /*= 0*/ ;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
-static acpi_status
-hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
{
struct acpi_object_list params;
union acpi_object in_objs[HCI_WORDS];
struct acpi_buffer results;
- union acpi_object out_objs[HCI_WORDS+1];
+ union acpi_object out_objs[HCI_WORDS + 1];
acpi_status status;
int i;
@@ -178,8 +173,8 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(NULL, (char*)method_hci, &params,
- &results);
+ status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
+ &results);
if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
for (i = 0; i < out_objs->package.count; ++i) {
out[i] = out_objs->package.elements[i].integer.value;
@@ -195,8 +190,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
* may be useful (such as "not supported").
*/
-static acpi_status
-hci_write1(u32 reg, u32 in1, u32* result)
+static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
@@ -205,8 +199,7 @@ hci_write1(u32 reg, u32 in1, u32* result)
return status;
}
-static acpi_status
-hci_read1(u32 reg, u32* out1, u32* result)
+static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
@@ -216,26 +209,25 @@ hci_read1(u32 reg, u32* out1, u32* result)
return status;
}
-static struct proc_dir_entry* toshiba_proc_dir /*= 0*/;
-static int force_fan;
-static int last_key_event;
-static int key_event_valid;
+static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+static int force_fan;
+static int last_key_event;
+static int key_event_valid;
-typedef struct _ProcItem
-{
- const char* name;
- char* (*read_func)(char*);
- unsigned long (*write_func)(const char*, unsigned long);
+typedef struct _ProcItem {
+ const char *name;
+ char *(*read_func) (char *);
+ unsigned long (*write_func) (const char *, unsigned long);
} ProcItem;
/* proc file handlers
*/
static int
-dispatch_read(char* page, char** start, off_t off, int count, int* eof,
- ProcItem* item)
+dispatch_read(char *page, char **start, off_t off, int count, int *eof,
+ ProcItem * item)
{
- char* p = page;
+ char *p = page;
int len;
if (off == 0)
@@ -243,33 +235,35 @@ dispatch_read(char* page, char** start, off_t off, int count, int* eof,
/* ISSUE: I don't understand this code */
len = (p - page);
- if (len <= off+count) *eof = 1;
+ if (len <= off + count)
+ *eof = 1;
*start = page + off;
len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
return len;
}
static int
-dispatch_write(struct file* file, const char __user * buffer,
- unsigned long count, ProcItem* item)
+dispatch_write(struct file *file, const char __user * buffer,
+ unsigned long count, ProcItem * item)
{
int result;
- char* tmp_buffer;
+ char *tmp_buffer;
/* Arg buffer points to userspace memory, which can't be accessed
* directly. Since we're making a copy, zero-terminate the
* destination so that sscanf can be used on it safely.
*/
tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
- if(!tmp_buffer)
+ if (!tmp_buffer)
return -ENOMEM;
if (copy_from_user(tmp_buffer, buffer, count)) {
result = -EFAULT;
- }
- else {
+ } else {
tmp_buffer[count] = 0;
result = item->write_func(tmp_buffer, count);
}
@@ -277,8 +271,7 @@ dispatch_write(struct file* file, const char __user * buffer,
return result;
}
-static char*
-read_lcd(char* p)
+static char *read_lcd(char *p)
{
u32 hci_result;
u32 value;
@@ -288,7 +281,7 @@ read_lcd(char* p)
value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
p += sprintf(p, "brightness: %d\n", value);
p += sprintf(p, "brightness_levels: %d\n",
- HCI_LCD_BRIGHTNESS_LEVELS);
+ HCI_LCD_BRIGHTNESS_LEVELS);
} else {
printk(MY_ERR "Error reading LCD brightness\n");
}
@@ -296,14 +289,13 @@ read_lcd(char* p)
return p;
}
-static unsigned long
-write_lcd(const char* buffer, unsigned long count)
+static unsigned long write_lcd(const char *buffer, unsigned long count)
{
int value;
u32 hci_result;
if (sscanf(buffer, " brightness : %i", &value) == 1 &&
- value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
+ value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
value = value << HCI_LCD_BRIGHTNESS_SHIFT;
hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
if (hci_result != HCI_SUCCESS)
@@ -315,8 +307,7 @@ write_lcd(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_video(char* p)
+static char *read_video(char *p)
{
u32 hci_result;
u32 value;
@@ -325,7 +316,7 @@ read_video(char* p)
if (hci_result == HCI_SUCCESS) {
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
- int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
+ int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
p += sprintf(p, "lcd_out: %d\n", is_lcd);
p += sprintf(p, "crt_out: %d\n", is_crt);
p += sprintf(p, "tv_out: %d\n", is_tv);
@@ -336,8 +327,7 @@ read_video(char* p)
return p;
}
-static unsigned long
-write_video(const char* buffer, unsigned long count)
+static unsigned long write_video(const char *buffer, unsigned long count)
{
int value;
int remain = count;
@@ -363,7 +353,7 @@ write_video(const char* buffer, unsigned long count)
++buffer;
--remain;
}
- while (remain && *(buffer-1) != ';');
+ while (remain && *(buffer - 1) != ';');
}
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
@@ -386,8 +376,7 @@ write_video(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_fan(char* p)
+static char *read_fan(char *p)
{
u32 hci_result;
u32 value;
@@ -403,14 +392,13 @@ read_fan(char* p)
return p;
}
-static unsigned long
-write_fan(const char* buffer, unsigned long count)
+static unsigned long write_fan(const char *buffer, unsigned long count)
{
int value;
u32 hci_result;
if (sscanf(buffer, " force_on : %i", &value) == 1 &&
- value >= 0 && value <= 1) {
+ value >= 0 && value <= 1) {
hci_write1(HCI_FAN, value, &hci_result);
if (hci_result != HCI_SUCCESS)
return -EFAULT;
@@ -423,8 +411,7 @@ write_fan(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_keys(char* p)
+static char *read_keys(char *p)
{
u32 hci_result;
u32 value;
@@ -451,17 +438,15 @@ read_keys(char* p)
p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
-end:
+ end:
return p;
}
-static unsigned long
-write_keys(const char* buffer, unsigned long count)
+static unsigned long write_keys(const char *buffer, unsigned long count)
{
int value;
- if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 &&
- value == 0) {
+ if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) {
key_event_valid = 0;
} else {
return -EINVAL;
@@ -470,12 +455,11 @@ write_keys(const char* buffer, unsigned long count)
return count;
}
-static char*
-read_version(char* p)
+static char *read_version(char *p)
{
p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
p += sprintf(p, "proc_interface: %d\n",
- PROC_INTERFACE_VERSION);
+ PROC_INTERFACE_VERSION);
return p;
}
@@ -484,48 +468,45 @@ read_version(char* p)
#define PROC_TOSHIBA "toshiba"
-static ProcItem proc_items[] =
-{
- { "lcd" , read_lcd , write_lcd },
- { "video" , read_video , write_video },
- { "fan" , read_fan , write_fan },
- { "keys" , read_keys , write_keys },
- { "version" , read_version , NULL },
- { NULL }
+static ProcItem proc_items[] = {
+ {"lcd", read_lcd, write_lcd},
+ {"video", read_video, write_video},
+ {"fan", read_fan, write_fan},
+ {"keys", read_keys, write_keys},
+ {"version", read_version, NULL},
+ {NULL}
};
-static acpi_status __init
-add_device(void)
+static acpi_status __init add_device(void)
{
- struct proc_dir_entry* proc;
- ProcItem* item;
+ struct proc_dir_entry *proc;
+ ProcItem *item;
- for (item = proc_items; item->name; ++item)
- {
+ for (item = proc_items; item->name; ++item) {
proc = create_proc_read_entry(item->name,
- S_IFREG | S_IRUGO | S_IWUSR,
- toshiba_proc_dir, (read_proc_t*)dispatch_read, item);
+ S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir,
+ (read_proc_t *) dispatch_read,
+ item);
if (proc)
proc->owner = THIS_MODULE;
if (proc && item->write_func)
- proc->write_proc = (write_proc_t*)dispatch_write;
+ proc->write_proc = (write_proc_t *) dispatch_write;
}
return AE_OK;
}
-static acpi_status __exit
-remove_device(void)
+static acpi_status __exit remove_device(void)
{
- ProcItem* item;
+ ProcItem *item;
for (item = proc_items; item->name; ++item)
remove_proc_entry(item->name, toshiba_proc_dir);
return AE_OK;
}
-static int __init
-toshiba_acpi_init(void)
+static int __init toshiba_acpi_init(void)
{
acpi_status status = AE_OK;
u32 hci_result;
@@ -533,9 +514,9 @@ toshiba_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled){
+ if (!acpi_specific_hotkey_enabled) {
printk(MY_INFO "Using generic hotkey driver\n");
- return -ENODEV;
+ return -ENODEV;
}
/* simple device detection: look for HCI method */
if (is_valid_acpi_path(METHOD_HCI_1))
@@ -546,7 +527,7 @@ toshiba_acpi_init(void)
return -ENODEV;
printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
- TOSHIBA_ACPI_VERSION);
+ TOSHIBA_ACPI_VERSION);
printk(MY_INFO " HCI method: %s\n", method_hci);
force_fan = 0;
@@ -568,8 +549,7 @@ toshiba_acpi_init(void)
return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
}
-static void __exit
-toshiba_acpi_exit(void)
+static void __exit toshiba_acpi_exit(void)
{
remove_device();
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
index 939c447dd52a..e87108b7338a 100644
--- a/drivers/acpi/utilities/Makefile
+++ b/drivers/acpi/utilities/Makefile
@@ -3,6 +3,6 @@
#
obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
- utcopy.o utdelete.o utglobal.o utmath.o utobject.o
+ utcopy.o utdelete.o utglobal.o utmath.o utobject.o utstate.o utmutex.o utobject.o utcache.o
EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index c4e7f989a2bd..068450b36475 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Module Name: utalloc - local cache and memory allocation routines
+ * Module Name: utalloc - local memory allocation routines
*
*****************************************************************************/
@@ -41,232 +41,134 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utalloc")
+ACPI_MODULE_NAME("utalloc")
/* Local prototypes */
-
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-static struct acpi_debug_mem_block *
-acpi_ut_find_allocation (
- u32 list_id,
- void *allocation);
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
static acpi_status
-acpi_ut_track_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *address,
- acpi_size size,
- u8 alloc_type,
- u32 component,
- char *module,
- u32 line);
+acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
+ acpi_size size,
+ u8 alloc_type, u32 component, char *module, u32 line);
static acpi_status
-acpi_ut_remove_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *address,
- u32 component,
- char *module,
- u32 line);
-#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
+ u32 component, char *module, u32 line);
+#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+static acpi_status
+acpi_ut_create_list(char *list_name,
+ u16 object_size, struct acpi_memory_list **return_cache);
+#endif
/*******************************************************************************
*
- * FUNCTION: acpi_ut_release_to_cache
+ * FUNCTION: acpi_ut_create_caches
*
- * PARAMETERS: list_id - Memory list/cache ID
- * Object - The object to be released
+ * PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Release an object to the specified cache. If cache is full,
- * the object is deleted.
+ * DESCRIPTION: Create all local caches
*
******************************************************************************/
-void
-acpi_ut_release_to_cache (
- u32 list_id,
- void *object)
+acpi_status acpi_ut_create_caches(void)
{
- struct acpi_memory_list *cache_info;
-
+ acpi_status status;
- ACPI_FUNCTION_ENTRY ();
-
-
- cache_info = &acpi_gbl_memory_lists[list_id];
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- /* If walk cache is full, just free this wallkstate object */
+ /* Memory allocation lists */
- if (cache_info->cache_depth >= cache_info->max_cache_depth) {
- ACPI_MEM_FREE (object);
- ACPI_MEM_TRACKING (cache_info->total_freed++);
+ status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- /* Otherwise put this object back into the cache */
-
- else {
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
- return;
- }
-
- /* Mark the object as cached */
-
- ACPI_MEMSET (object, 0xCA, cache_info->object_size);
- ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED);
-
- /* Put the object at the head of the cache list */
-
- * (ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head;
- cache_info->list_head = object;
- cache_info->cache_depth++;
-
- (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
+ status =
+ acpi_ut_create_list("Acpi-Namespace",
+ sizeof(struct acpi_namespace_node),
+ &acpi_gbl_ns_node_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
-
-#else
-
- /* Object cache is disabled; just free the object */
-
- ACPI_MEM_FREE (object);
- ACPI_MEM_TRACKING (cache_info->total_freed++);
#endif
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_acquire_from_cache
- *
- * PARAMETERS: list_id - Memory list ID
- *
- * RETURN: A requested object. NULL if the object could not be
- * allocated.
- *
- * DESCRIPTION: Get an object from the specified cache. If cache is empty,
- * the object is allocated.
- *
- ******************************************************************************/
-
-void *
-acpi_ut_acquire_from_cache (
- u32 list_id)
-{
- struct acpi_memory_list *cache_info;
- void *object;
+ /* Object Caches, for frequently used objects */
- ACPI_FUNCTION_NAME ("ut_acquire_from_cache");
-
-
- cache_info = &acpi_gbl_memory_lists[list_id];
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
+ status =
+ acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state),
+ ACPI_MAX_STATE_CACHE_DEPTH,
+ &acpi_gbl_state_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- ACPI_MEM_TRACKING (cache_info->cache_requests++);
-
- /* Check the cache first */
-
- if (cache_info->list_head) {
- /* There is an object available, use it */
-
- object = cache_info->list_head;
- cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) object)[cache_info->link_offset])));
-
- ACPI_MEM_TRACKING (cache_info->cache_hits++);
- cache_info->cache_depth--;
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n",
- object, acpi_gbl_memory_lists[list_id].list_name));
-#endif
-
- if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
- }
-
- /* Clear (zero) the previously used Object */
-
- ACPI_MEMSET (object, 0, cache_info->object_size);
+ status =
+ acpi_os_create_cache("acpi_parse",
+ sizeof(struct acpi_parse_obj_common),
+ ACPI_MAX_PARSE_CACHE_DEPTH,
+ &acpi_gbl_ps_node_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- else {
- /* The cache is empty, create a new object */
-
- /* Avoid deadlock with ACPI_MEM_CALLOCATE */
-
- if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
- return (NULL);
- }
-
- object = ACPI_MEM_CALLOCATE (cache_info->object_size);
- ACPI_MEM_TRACKING (cache_info->total_allocated++);
+ status =
+ acpi_os_create_cache("acpi_parse_ext",
+ sizeof(struct acpi_parse_obj_named),
+ ACPI_MAX_EXTPARSE_CACHE_DEPTH,
+ &acpi_gbl_ps_node_ext_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
-#else
-
- /* Object cache is disabled; just allocate the object */
-
- object = ACPI_MEM_CALLOCATE (cache_info->object_size);
- ACPI_MEM_TRACKING (cache_info->total_allocated++);
-#endif
+ status =
+ acpi_os_create_cache("acpi_operand",
+ sizeof(union acpi_operand_object),
+ ACPI_MAX_OBJECT_CACHE_DEPTH,
+ &acpi_gbl_operand_cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- return (object);
+ return (AE_OK);
}
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
/*******************************************************************************
*
- * FUNCTION: acpi_ut_delete_generic_cache
+ * FUNCTION: acpi_ut_delete_caches
*
- * PARAMETERS: list_id - Memory list ID
+ * PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Free all objects within the requested cache.
+ * DESCRIPTION: Purge and delete all local caches
*
******************************************************************************/
-void
-acpi_ut_delete_generic_cache (
- u32 list_id)
+acpi_status acpi_ut_delete_caches(void)
{
- struct acpi_memory_list *cache_info;
- char *next;
-
- ACPI_FUNCTION_ENTRY ();
+ (void)acpi_os_delete_cache(acpi_gbl_state_cache);
+ acpi_gbl_state_cache = NULL;
+ (void)acpi_os_delete_cache(acpi_gbl_operand_cache);
+ acpi_gbl_operand_cache = NULL;
- cache_info = &acpi_gbl_memory_lists[list_id];
- while (cache_info->list_head) {
- /* Delete one cached state object */
+ (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache);
+ acpi_gbl_ps_node_cache = NULL;
- next = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) cache_info->list_head)[cache_info->link_offset])));
- ACPI_MEM_FREE (cache_info->list_head);
+ (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
+ acpi_gbl_ps_node_ext_cache = NULL;
- cache_info->list_head = next;
- cache_info->cache_depth--;
- }
+ return (AE_OK);
}
-#endif
-
/*******************************************************************************
*
@@ -280,9 +182,7 @@ acpi_ut_delete_generic_cache (
*
******************************************************************************/
-acpi_status
-acpi_ut_validate_buffer (
- struct acpi_buffer *buffer)
+acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
{
/* Obviously, the structure pointer must be valid */
@@ -293,9 +193,9 @@ acpi_ut_validate_buffer (
/* Special semantics for the length */
- if ((buffer->length == ACPI_NO_BUFFER) ||
- (buffer->length == ACPI_ALLOCATE_BUFFER) ||
- (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
+ if ((buffer->length == ACPI_NO_BUFFER) ||
+ (buffer->length == ACPI_ALLOCATE_BUFFER) ||
+ (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
return (AE_OK);
}
@@ -308,7 +208,6 @@ acpi_ut_validate_buffer (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_initialize_buffer
@@ -324,12 +223,10 @@ acpi_ut_validate_buffer (
******************************************************************************/
acpi_status
-acpi_ut_initialize_buffer (
- struct acpi_buffer *buffer,
- acpi_size required_length)
+acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
+ acpi_size required_length)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
switch (buffer->length) {
case ACPI_NO_BUFFER:
@@ -339,33 +236,30 @@ acpi_ut_initialize_buffer (
status = AE_BUFFER_OVERFLOW;
break;
-
case ACPI_ALLOCATE_BUFFER:
/* Allocate a new buffer */
- buffer->pointer = acpi_os_allocate (required_length);
+ buffer->pointer = acpi_os_allocate(required_length);
if (!buffer->pointer) {
return (AE_NO_MEMORY);
}
/* Clear the buffer */
- ACPI_MEMSET (buffer->pointer, 0, required_length);
+ ACPI_MEMSET(buffer->pointer, 0, required_length);
break;
-
case ACPI_ALLOCATE_LOCAL_BUFFER:
/* Allocate a new buffer with local interface to allow tracking */
- buffer->pointer = ACPI_MEM_CALLOCATE (required_length);
+ buffer->pointer = ACPI_MEM_CALLOCATE(required_length);
if (!buffer->pointer) {
return (AE_NO_MEMORY);
}
break;
-
default:
/* Existing buffer: Validate the size of the buffer */
@@ -377,7 +271,7 @@ acpi_ut_initialize_buffer (
/* Clear the buffer */
- ACPI_MEMSET (buffer->pointer, 0, required_length);
+ ACPI_MEMSET(buffer->pointer, 0, required_length);
break;
}
@@ -385,7 +279,6 @@ acpi_ut_initialize_buffer (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_allocate
@@ -401,41 +294,34 @@ acpi_ut_initialize_buffer (
*
******************************************************************************/
-void *
-acpi_ut_allocate (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
{
- void *allocation;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size);
+ void *allocation;
+ ACPI_FUNCTION_TRACE_U32("ut_allocate", size);
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_allocate: Attempt to allocate zero bytes\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_allocate: Attempt to allocate zero bytes\n"));
size = 1;
}
- allocation = acpi_os_allocate (size);
+ allocation = acpi_os_allocate(size);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_allocate: Could not allocate size %X\n", (u32) size));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_allocate: Could not allocate size %X\n",
+ (u32) size));
- return_PTR (NULL);
+ return_PTR(NULL);
}
- return_PTR (allocation);
+ return_PTR(allocation);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_callocate
@@ -451,43 +337,36 @@ acpi_ut_allocate (
*
******************************************************************************/
-void *
-acpi_ut_callocate (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line)
{
- void *allocation;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size);
+ void *allocation;
+ ACPI_FUNCTION_TRACE_U32("ut_callocate", size);
/* Check for an inadvertent size of zero bytes */
if (!size) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Attempt to allocate zero bytes\n"));
- return_PTR (NULL);
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Attempt to allocate zero bytes\n"));
+ return_PTR(NULL);
}
- allocation = acpi_os_allocate (size);
+ allocation = acpi_os_allocate(size);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Could not allocate size %X\n", (u32) size));
- return_PTR (NULL);
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Could not allocate size %X\n",
+ (u32) size));
+ return_PTR(NULL);
}
/* Clear the memory block */
- ACPI_MEMSET (allocation, 0, size);
- return_PTR (allocation);
+ ACPI_MEMSET(allocation, 0, size);
+ return_PTR(allocation);
}
-
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
/*
* These procedures are used for tracking memory leaks in the subsystem, and
@@ -500,6 +379,39 @@ acpi_ut_callocate (
* occurs in the body of acpi_ut_free.
*/
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_list
+ *
+ * PARAMETERS: cache_name - Ascii name for the cache
+ * object_size - Size of each cached object
+ * return_cache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a local memory list for tracking purposed
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_create_list(char *list_name,
+ u16 object_size, struct acpi_memory_list **return_cache)
+{
+ struct acpi_memory_list *cache;
+
+ cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+ if (!cache) {
+ return (AE_NO_MEMORY);
+ }
+
+ ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+
+ cache->list_name = list_name;
+ cache->object_size = object_size;
+
+ *return_cache = cache;
+ return (AE_OK);
+}
/*******************************************************************************
*
@@ -516,37 +428,33 @@ acpi_ut_callocate (
*
******************************************************************************/
-void *
-acpi_ut_allocate_and_track (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_allocate_and_track(acpi_size size,
+ u32 component, char *module, u32 line)
{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
- allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header),
- component, module, line);
+ allocation =
+ acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
if (!allocation) {
return (NULL);
}
- status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
- ACPI_MEM_MALLOC, component, module, line);
- if (ACPI_FAILURE (status)) {
- acpi_os_free (allocation);
+ status = acpi_ut_track_allocation(allocation, size,
+ ACPI_MEM_MALLOC, component, module,
+ line);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_free(allocation);
return (NULL);
}
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->current_total_size += (u32) size;
- return ((void *) &allocation->user_space);
+ return ((void *)&allocation->user_space);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_callocate_and_track
@@ -562,41 +470,38 @@ acpi_ut_allocate_and_track (
*
******************************************************************************/
-void *
-acpi_ut_callocate_and_track (
- acpi_size size,
- u32 component,
- char *module,
- u32 line)
+void *acpi_ut_callocate_and_track(acpi_size size,
+ u32 component, char *module, u32 line)
{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
- allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header),
- component, module, line);
+ allocation =
+ acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
if (!allocation) {
/* Report allocation error */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_callocate: Could not allocate size %X\n", (u32) size));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_callocate: Could not allocate size %X\n",
+ (u32) size));
return (NULL);
}
- status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
- ACPI_MEM_CALLOC, component, module, line);
- if (ACPI_FAILURE (status)) {
- acpi_os_free (allocation);
+ status = acpi_ut_track_allocation(allocation, size,
+ ACPI_MEM_CALLOC, component, module,
+ line);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_free(allocation);
return (NULL);
}
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->current_total_size += (u32) size;
- return ((void *) &allocation->user_space);
+ return ((void *)&allocation->user_space);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_free_and_track
@@ -613,53 +518,46 @@ acpi_ut_callocate_and_track (
******************************************************************************/
void
-acpi_ut_free_and_track (
- void *allocation,
- u32 component,
- char *module,
- u32 line)
+acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line)
{
- struct acpi_debug_mem_block *debug_block;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_free", allocation);
+ struct acpi_debug_mem_block *debug_block;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
if (NULL == allocation) {
- _ACPI_REPORT_ERROR (module, line, component,
- ("acpi_ut_free: Attempt to delete a NULL address\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("acpi_ut_free: Attempt to delete a NULL address\n"));
return_VOID;
}
- debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block,
- (((char *) allocation) - sizeof (struct acpi_debug_mem_header)));
+ debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
+ (((char *)allocation) -
+ sizeof(struct acpi_debug_mem_header)));
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size;
+ acpi_gbl_global_list->total_freed++;
+ acpi_gbl_global_list->current_total_size -= debug_block->size;
- status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block,
- component, module, line);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n",
- acpi_format_exception (status)));
+ status = acpi_ut_remove_allocation(debug_block,
+ component, module, line);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not free memory, %s\n",
+ acpi_format_exception(status)));
}
- acpi_os_free (debug_block);
+ acpi_os_free(debug_block);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_find_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
*
* RETURN: A list element if found; NULL otherwise.
*
@@ -667,22 +565,13 @@ acpi_ut_free_and_track (
*
******************************************************************************/
-static struct acpi_debug_mem_block *
-acpi_ut_find_allocation (
- u32 list_id,
- void *allocation)
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
{
- struct acpi_debug_mem_block *element;
-
+ struct acpi_debug_mem_block *element;
- ACPI_FUNCTION_ENTRY ();
-
-
- if (list_id > ACPI_MEM_LIST_MAX) {
- return (NULL);
- }
+ ACPI_FUNCTION_ENTRY();
- element = acpi_gbl_memory_lists[list_id].list_head;
+ element = acpi_gbl_global_list->list_head;
/* Search for the address. */
@@ -697,13 +586,11 @@ acpi_ut_find_allocation (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_track_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
* Size - Size of the allocation
* alloc_type - MEM_MALLOC or MEM_CALLOC
* Component - Component type of caller
@@ -717,64 +604,51 @@ acpi_ut_find_allocation (
******************************************************************************/
static acpi_status
-acpi_ut_track_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *allocation,
- acpi_size size,
- u8 alloc_type,
- u32 component,
- char *module,
- u32 line)
+acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
+ acpi_size size,
+ u8 alloc_type, u32 component, char *module, u32 line)
{
- struct acpi_memory_list *mem_list;
- struct acpi_debug_mem_block *element;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation);
+ struct acpi_memory_list *mem_list;
+ struct acpi_debug_mem_block *element;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ut_track_allocation", allocation);
- if (list_id > ACPI_MEM_LIST_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- mem_list = &acpi_gbl_memory_lists[list_id];
- status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ mem_list = acpi_gbl_global_list;
+ status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Search list for this address to make sure it is not already on the list.
* This will catch several kinds of problems.
*/
-
- element = acpi_ut_find_allocation (list_id, allocation);
+ element = acpi_ut_find_allocation(allocation);
if (element) {
- ACPI_REPORT_ERROR ((
- "ut_track_allocation: Allocation already present in list! (%p)\n",
- allocation));
+ ACPI_REPORT_ERROR(("ut_track_allocation: Allocation already present in list! (%p)\n", allocation));
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n",
- element, allocation));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Element %p Address %p\n",
+ element, allocation));
goto unlock_and_exit;
}
/* Fill in the instance data. */
- allocation->size = (u32) size;
+ allocation->size = (u32) size;
allocation->alloc_type = alloc_type;
allocation->component = component;
- allocation->line = line;
+ allocation->line = line;
- ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME);
- allocation->module[ACPI_MAX_MODULE_NAME-1] = 0;
+ ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
+ allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
/* Insert at list head */
if (mem_list->list_head) {
- ((struct acpi_debug_mem_block *)(mem_list->list_head))->previous = allocation;
+ ((struct acpi_debug_mem_block *)(mem_list->list_head))->
+ previous = allocation;
}
allocation->next = mem_list->list_head;
@@ -782,19 +656,16 @@ acpi_ut_track_allocation (
mem_list->list_head = allocation;
-
-unlock_and_exit:
- status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
- return_ACPI_STATUS (status);
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_remove_allocation
*
- * PARAMETERS: list_id - Memory list to search
- * Allocation - Address of allocated memory
+ * PARAMETERS: Allocation - Address of allocated memory
* Component - Component type of caller
* Module - Source file name of caller
* Line - Line number of caller
@@ -806,45 +677,34 @@ unlock_and_exit:
******************************************************************************/
static acpi_status
-acpi_ut_remove_allocation (
- u32 list_id,
- struct acpi_debug_mem_block *allocation,
- u32 component,
- char *module,
- u32 line)
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
+ u32 component, char *module, u32 line)
{
- struct acpi_memory_list *mem_list;
- acpi_status status;
-
+ struct acpi_memory_list *mem_list;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ut_remove_allocation");
+ ACPI_FUNCTION_TRACE("ut_remove_allocation");
-
- if (list_id > ACPI_MEM_LIST_MAX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- mem_list = &acpi_gbl_memory_lists[list_id];
+ mem_list = acpi_gbl_global_list;
if (NULL == mem_list->list_head) {
/* No allocations! */
- _ACPI_REPORT_ERROR (module, line, component,
- ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
+ _ACPI_REPORT_ERROR(module, line, component,
+ ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
- status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Unlink */
if (allocation->previous) {
(allocation->previous)->next = allocation->next;
- }
- else {
+ } else {
mem_list->list_head = allocation->next;
}
@@ -854,16 +714,15 @@ acpi_ut_remove_allocation (
/* Mark the segment as deleted */
- ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size);
+ ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
- allocation->size));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
+ allocation->size));
- status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
- return_ACPI_STATUS (status);
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dump_allocation_info
@@ -877,15 +736,13 @@ acpi_ut_remove_allocation (
******************************************************************************/
#ifdef ACPI_FUTURE_USAGE
-void
-acpi_ut_dump_allocation_info (
- void)
+void acpi_ut_dump_allocation_info(void)
{
/*
struct acpi_memory_list *mem_list;
*/
- ACPI_FUNCTION_TRACE ("ut_dump_allocation_info");
+ ACPI_FUNCTION_TRACE("ut_dump_allocation_info");
/*
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
@@ -898,7 +755,6 @@ acpi_ut_dump_allocation_info (
mem_list->max_concurrent_count,
ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
-
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
running_object_count,
@@ -909,7 +765,6 @@ acpi_ut_dump_allocation_info (
running_alloc_count,
ROUND_UP_TO_1K (running_alloc_size)));
-
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
("%30s: %4d (%3d Kb)\n", "Current Nodes",
acpi_gbl_current_node_count,
@@ -923,8 +778,7 @@ acpi_ut_dump_allocation_info (
*/
return_VOID;
}
-#endif /* ACPI_FUTURE_USAGE */
-
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
@@ -939,84 +793,87 @@ acpi_ut_dump_allocation_info (
*
******************************************************************************/
-void
-acpi_ut_dump_allocations (
- u32 component,
- char *module)
+void acpi_ut_dump_allocations(u32 component, char *module)
{
- struct acpi_debug_mem_block *element;
- union acpi_descriptor *descriptor;
- u32 num_outstanding = 0;
-
-
- ACPI_FUNCTION_TRACE ("ut_dump_allocations");
+ struct acpi_debug_mem_block *element;
+ union acpi_descriptor *descriptor;
+ u32 num_outstanding = 0;
+ ACPI_FUNCTION_TRACE("ut_dump_allocations");
/*
* Walk the allocation list.
*/
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_MEMORY))) {
+ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
return;
}
- element = acpi_gbl_memory_lists[0].list_head;
+ element = acpi_gbl_global_list->list_head;
while (element) {
if ((element->component & component) &&
- ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) {
+ ((module == NULL)
+ || (0 == ACPI_STRCMP(module, element->module)))) {
/* Ignore allocated objects that are in a cache */
- descriptor = ACPI_CAST_PTR (union acpi_descriptor, &element->user_space);
+ descriptor =
+ ACPI_CAST_PTR(union acpi_descriptor,
+ &element->user_space);
if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) {
- acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ",
- descriptor, element->size, element->module,
- element->line, acpi_ut_get_descriptor_name (descriptor));
+ acpi_os_printf("%p Len %04X %9.9s-%d [%s] ",
+ descriptor, element->size,
+ element->module, element->line,
+ acpi_ut_get_descriptor_name
+ (descriptor));
/* Most of the elements will be Operand objects. */
- switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(descriptor)) {
case ACPI_DESC_TYPE_OPERAND:
- acpi_os_printf ("%12.12s R%hd",
- acpi_ut_get_type_name (descriptor->object.common.type),
- descriptor->object.common.reference_count);
+ acpi_os_printf("%12.12s R%hd",
+ acpi_ut_get_type_name
+ (descriptor->object.
+ common.type),
+ descriptor->object.
+ common.reference_count);
break;
case ACPI_DESC_TYPE_PARSER:
- acpi_os_printf ("aml_opcode %04hX",
- descriptor->op.asl.aml_opcode);
+ acpi_os_printf("aml_opcode %04hX",
+ descriptor->op.asl.
+ aml_opcode);
break;
case ACPI_DESC_TYPE_NAMED:
- acpi_os_printf ("%4.4s",
- acpi_ut_get_node_name (&descriptor->node));
+ acpi_os_printf("%4.4s",
+ acpi_ut_get_node_name
+ (&descriptor->node));
break;
default:
break;
}
- acpi_os_printf ( "\n");
+ acpi_os_printf("\n");
num_outstanding++;
}
}
element = element->next;
}
- (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY);
+ (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
/* Print summary */
if (!num_outstanding) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No outstanding allocations.\n"));
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%d(%X) Outstanding allocations\n",
- num_outstanding, num_outstanding));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No outstanding allocations.\n"));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%d(%X) Outstanding allocations\n",
+ num_outstanding, num_outstanding));
}
return_VOID;
}
-#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
-
+#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
new file mode 100644
index 000000000000..93d48681d276
--- /dev/null
+++ b/drivers/acpi/utilities/utcache.c
@@ -0,0 +1,305 @@
+/******************************************************************************
+ *
+ * Module Name: utcache - local cache allocation routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utcache")
+
+#ifdef ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_create_cache
+ *
+ * PARAMETERS: cache_name - Ascii name for the cache
+ * object_size - Size of each cached object
+ * max_depth - Maximum depth of the cache (in objects)
+ * return_cache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+acpi_status
+acpi_os_create_cache(char *cache_name,
+ u16 object_size,
+ u16 max_depth, struct acpi_memory_list **return_cache)
+{
+ struct acpi_memory_list *cache;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache_name || !return_cache || (object_size < 16)) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Create the cache object */
+
+ cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+ if (!cache) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Populate the cache object and return it */
+
+ ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+ cache->link_offset = 8;
+ cache->list_name = cache_name;
+ cache->object_size = object_size;
+ cache->max_depth = max_depth;
+
+ *return_cache = cache;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_purge_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+{
+ char *next;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Walk the list of objects in this cache */
+
+ while (cache->list_head) {
+ /* Delete and unlink one cached state object */
+
+ next = *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)cache->
+ list_head)[cache->
+ link_offset])));
+ ACPI_MEM_FREE(cache->list_head);
+
+ cache->list_head = next;
+ cache->current_depth--;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_delete_cache
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ * cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Purge all objects in the cache */
+
+ status = acpi_os_purge_cache(cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Now we can delete the cache object */
+
+ acpi_os_free(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_release_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ * Object - The object to be released
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ * the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache || !object) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* If cache is full, just free this object */
+
+ if (cache->current_depth >= cache->max_depth) {
+ ACPI_MEM_FREE(object);
+ ACPI_MEM_TRACKING(cache->total_freed++);
+ }
+
+ /* Otherwise put this object back into the cache */
+
+ else {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Mark the object as cached */
+
+ ACPI_MEMSET(object, 0xCA, cache->object_size);
+ ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
+
+ /* Put the object at the head of the cache list */
+
+ *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)object)[cache->
+ link_offset]))) =
+ cache->list_head;
+ cache->list_head = object;
+ cache->current_depth++;
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_acquire_object
+ *
+ * PARAMETERS: Cache - Handle to cache object
+ *
+ * RETURN: the acquired object. NULL on error
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ * the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(struct acpi_memory_list *cache)
+{
+ acpi_status status;
+ void *object;
+
+ ACPI_FUNCTION_NAME("os_acquire_object");
+
+ if (!cache) {
+ return (NULL);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ ACPI_MEM_TRACKING(cache->requests++);
+
+ /* Check the cache first */
+
+ if (cache->list_head) {
+ /* There is an object available, use it */
+
+ object = cache->list_head;
+ cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)
+ object)[cache->
+ link_offset])));
+
+ cache->current_depth--;
+
+ ACPI_MEM_TRACKING(cache->hits++);
+ ACPI_MEM_TRACKING(ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Object %p from %s cache\n",
+ object, cache->list_name)));
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ /* Clear (zero) the previously used Object */
+
+ ACPI_MEMSET(object, 0, cache->object_size);
+ } else {
+ /* The cache is empty, create a new object */
+
+ ACPI_MEM_TRACKING(cache->total_allocated++);
+
+ /* Avoid deadlock with ACPI_MEM_CALLOCATE */
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ object = ACPI_MEM_CALLOCATE(cache->object_size);
+ if (!object) {
+ return (NULL);
+ }
+ }
+
+ return (object);
+}
+#endif /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 11e884957162..5442b32de611 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -41,59 +41,46 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utcopy")
+ACPI_MODULE_NAME("utcopy")
/* Local prototypes */
-
static acpi_status
-acpi_ut_copy_isimple_to_esimple (
- union acpi_operand_object *internal_object,
- union acpi_object *external_object,
- u8 *data_space,
- acpi_size *buffer_space_used);
+acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+ union acpi_object *external_object,
+ u8 * data_space, acpi_size * buffer_space_used);
static acpi_status
-acpi_ut_copy_ielement_to_ielement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
+acpi_ut_copy_ielement_to_ielement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context);
static acpi_status
-acpi_ut_copy_ipackage_to_epackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- acpi_size *space_used);
+acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
+ u8 * buffer, acpi_size * space_used);
static acpi_status
-acpi_ut_copy_esimple_to_isimple(
- union acpi_object *user_obj,
- union acpi_operand_object **return_obj);
+acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
+ union acpi_operand_object **return_obj);
static acpi_status
-acpi_ut_copy_simple_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc);
+acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc);
static acpi_status
-acpi_ut_copy_ielement_to_eelement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
+acpi_ut_copy_ielement_to_eelement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context);
static acpi_status
-acpi_ut_copy_ipackage_to_ipackage (
- union acpi_operand_object *source_obj,
- union acpi_operand_object *dest_obj,
- struct acpi_walk_state *walk_state);
-
+acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
+ union acpi_operand_object *dest_obj,
+ struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -116,17 +103,13 @@ acpi_ut_copy_ipackage_to_ipackage (
******************************************************************************/
static acpi_status
-acpi_ut_copy_isimple_to_esimple (
- union acpi_operand_object *internal_object,
- union acpi_object *external_object,
- u8 *data_space,
- acpi_size *buffer_space_used)
+acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
+ union acpi_object *external_object,
+ u8 * data_space, acpi_size * buffer_space_used)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_isimple_to_esimple");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple");
*buffer_space_used = 0;
@@ -135,54 +118,54 @@ acpi_ut_copy_isimple_to_esimple (
* package element)
*/
if (!internal_object) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Always clear the external object */
- ACPI_MEMSET (external_object, 0, sizeof (union acpi_object));
+ ACPI_MEMSET(external_object, 0, sizeof(union acpi_object));
/*
* In general, the external object will be the same type as
* the internal object
*/
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
/* However, only a limited number of external types are supported */
- switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(internal_object)) {
case ACPI_TYPE_STRING:
- external_object->string.pointer = (char *) data_space;
+ external_object->string.pointer = (char *)data_space;
external_object->string.length = internal_object->string.length;
- *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (
- (acpi_size) internal_object->string.length + 1);
-
- ACPI_MEMCPY ((void *) data_space,
- (void *) internal_object->string.pointer,
- (acpi_size) internal_object->string.length + 1);
+ *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
+ internal_object->
+ string.
+ length + 1);
+
+ ACPI_MEMCPY((void *)data_space,
+ (void *)internal_object->string.pointer,
+ (acpi_size) internal_object->string.length + 1);
break;
-
case ACPI_TYPE_BUFFER:
external_object->buffer.pointer = data_space;
external_object->buffer.length = internal_object->buffer.length;
- *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (
- internal_object->string.length);
+ *buffer_space_used =
+ ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
+ length);
- ACPI_MEMCPY ((void *) data_space,
- (void *) internal_object->buffer.pointer,
- internal_object->buffer.length);
+ ACPI_MEMCPY((void *)data_space,
+ (void *)internal_object->buffer.pointer,
+ internal_object->buffer.length);
break;
-
case ACPI_TYPE_INTEGER:
external_object->integer.value = internal_object->integer.value;
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
/*
@@ -199,41 +182,41 @@ acpi_ut_copy_isimple_to_esimple (
* to object containing a handle to an ACPI named object.
*/
external_object->type = ACPI_TYPE_ANY;
- external_object->reference.handle = internal_object->reference.node;
+ external_object->reference.handle =
+ internal_object->reference.node;
break;
}
break;
-
case ACPI_TYPE_PROCESSOR:
- external_object->processor.proc_id = internal_object->processor.proc_id;
- external_object->processor.pblk_address = internal_object->processor.address;
- external_object->processor.pblk_length = internal_object->processor.length;
+ external_object->processor.proc_id =
+ internal_object->processor.proc_id;
+ external_object->processor.pblk_address =
+ internal_object->processor.address;
+ external_object->processor.pblk_length =
+ internal_object->processor.length;
break;
-
case ACPI_TYPE_POWER:
external_object->power_resource.system_level =
- internal_object->power_resource.system_level;
+ internal_object->power_resource.system_level;
external_object->power_resource.resource_order =
- internal_object->power_resource.resource_order;
+ internal_object->power_resource.resource_order;
break;
-
default:
/*
* There is no corresponding external object type
*/
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ielement_to_eelement
@@ -247,25 +230,23 @@ acpi_ut_copy_isimple_to_esimple (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ielement_to_eelement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_copy_ielement_to_eelement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context)
{
- acpi_status status = AE_OK;
- struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
- acpi_size object_space;
- u32 this_index;
- union acpi_object *target_object;
+ acpi_status status = AE_OK;
+ struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
+ acpi_size object_space;
+ u32 this_index;
+ union acpi_object *target_object;
+ ACPI_FUNCTION_ENTRY();
- ACPI_FUNCTION_ENTRY ();
-
-
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
target_object = (union acpi_object *)
- &((union acpi_object *)(state->pkg.dest_object))->package.elements[this_index];
+ &((union acpi_object *)(state->pkg.dest_object))->package.
+ elements[this_index];
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -273,23 +254,24 @@ acpi_ut_copy_ielement_to_eelement (
/*
* This is a simple or null object
*/
- status = acpi_ut_copy_isimple_to_esimple (source_object,
- target_object, info->free_space, &object_space);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_copy_isimple_to_esimple(source_object,
+ target_object,
+ info->free_space,
+ &object_space);
+ if (ACPI_FAILURE(status)) {
return (status);
}
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/*
* Build the package object
*/
- target_object->type = ACPI_TYPE_PACKAGE;
- target_object->package.count = source_object->package.count;
+ target_object->type = ACPI_TYPE_PACKAGE;
+ target_object->package.count = source_object->package.count;
target_object->package.elements =
- ACPI_CAST_PTR (union acpi_object, info->free_space);
+ ACPI_CAST_PTR(union acpi_object, info->free_space);
/*
* Pass the new package object back to the package walk routine
@@ -300,22 +282,22 @@ acpi_ut_copy_ielement_to_eelement (
* Save space for the array of objects (Package elements)
* update the buffer length counter
*/
- object_space = ACPI_ROUND_UP_TO_NATIVE_WORD (
- (acpi_size) target_object->package.count *
- sizeof (union acpi_object));
+ object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
+ target_object->
+ package.count *
+ sizeof(union
+ acpi_object));
break;
-
default:
return (AE_BAD_PARAMETER);
}
- info->free_space += object_space;
- info->length += object_space;
+ info->free_space += object_space;
+ info->length += object_space;
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ipackage_to_epackage
@@ -336,55 +318,51 @@ acpi_ut_copy_ielement_to_eelement (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ipackage_to_epackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- acpi_size *space_used)
+acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
+ u8 * buffer, acpi_size * space_used)
{
- union acpi_object *external_object;
- acpi_status status;
- struct acpi_pkg_info info;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_ipackage_to_epackage");
+ union acpi_object *external_object;
+ acpi_status status;
+ struct acpi_pkg_info info;
+ ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage");
/*
* First package at head of the buffer
*/
- external_object = ACPI_CAST_PTR (union acpi_object, buffer);
+ external_object = ACPI_CAST_PTR(union acpi_object, buffer);
/*
* Free space begins right after the first package
*/
- info.length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
- info.free_space = buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
- sizeof (union acpi_object));
+ info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
+ info.free_space =
+ buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
info.object_space = 0;
info.num_packages = 1;
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
- external_object->package.count = internal_object->package.count;
- external_object->package.elements = ACPI_CAST_PTR (union acpi_object,
- info.free_space);
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
+ external_object->package.count = internal_object->package.count;
+ external_object->package.elements = ACPI_CAST_PTR(union acpi_object,
+ info.free_space);
/*
* Leave room for an array of ACPI_OBJECTS in the buffer
* and move the free space past it
*/
- info.length += (acpi_size) external_object->package.count *
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
+ info.length += (acpi_size) external_object->package.count *
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
info.free_space += external_object->package.count *
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object));
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
- status = acpi_ut_walk_package_tree (internal_object, external_object,
- acpi_ut_copy_ielement_to_eelement, &info);
+ status = acpi_ut_walk_package_tree(internal_object, external_object,
+ acpi_ut_copy_ielement_to_eelement,
+ &info);
*space_used = info.length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_iobject_to_eobject
@@ -400,44 +378,45 @@ acpi_ut_copy_ipackage_to_epackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_iobject_to_eobject (
- union acpi_operand_object *internal_object,
- struct acpi_buffer *ret_buffer)
+acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
+ struct acpi_buffer *ret_buffer)
{
- acpi_status status;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ut_copy_iobject_to_eobject");
- ACPI_FUNCTION_TRACE ("ut_copy_iobject_to_eobject");
-
-
- if (ACPI_GET_OBJECT_TYPE (internal_object) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) {
/*
* Package object: Copy all subobjects (including
* nested packages)
*/
- status = acpi_ut_copy_ipackage_to_epackage (internal_object,
- ret_buffer->pointer, &ret_buffer->length);
- }
- else {
+ status = acpi_ut_copy_ipackage_to_epackage(internal_object,
+ ret_buffer->pointer,
+ &ret_buffer->length);
+ } else {
/*
* Build a simple object (no nested objects)
*/
- status = acpi_ut_copy_isimple_to_esimple (internal_object,
- (union acpi_object *) ret_buffer->pointer,
- ((u8 *) ret_buffer->pointer +
- ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object))),
- &ret_buffer->length);
+ status = acpi_ut_copy_isimple_to_esimple(internal_object,
+ (union acpi_object *)
+ ret_buffer->pointer,
+ ((u8 *) ret_buffer->
+ pointer +
+ ACPI_ROUND_UP_TO_NATIVE_WORD
+ (sizeof
+ (union
+ acpi_object))),
+ &ret_buffer->length);
/*
* build simple does not include the object size in the length
* so we add it in here
*/
- ret_buffer->length += sizeof (union acpi_object);
+ ret_buffer->length += sizeof(union acpi_object);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_esimple_to_isimple
@@ -455,15 +434,12 @@ acpi_ut_copy_iobject_to_eobject (
******************************************************************************/
static acpi_status
-acpi_ut_copy_esimple_to_isimple (
- union acpi_object *external_object,
- union acpi_operand_object **ret_internal_object)
+acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
+ union acpi_operand_object **ret_internal_object)
{
- union acpi_operand_object *internal_object;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_esimple_to_isimple");
+ union acpi_operand_object *internal_object;
+ ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple");
/*
* Simple types supported are: String, Buffer, Integer
@@ -473,58 +449,57 @@ acpi_ut_copy_esimple_to_isimple (
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_INTEGER:
- internal_object = acpi_ut_create_internal_object (
- (u8) external_object->type);
+ internal_object = acpi_ut_create_internal_object((u8)
+ external_object->
+ type);
if (!internal_object) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
break;
default:
/* All other types are not supported */
- return_ACPI_STATUS (AE_SUPPORT);
+ return_ACPI_STATUS(AE_SUPPORT);
}
-
/* Must COPY string and buffer contents */
switch (external_object->type) {
case ACPI_TYPE_STRING:
internal_object->string.pointer =
- ACPI_MEM_CALLOCATE ((acpi_size) external_object->string.length + 1);
+ ACPI_MEM_CALLOCATE((acpi_size) external_object->string.
+ length + 1);
if (!internal_object->string.pointer) {
goto error_exit;
}
- ACPI_MEMCPY (internal_object->string.pointer,
- external_object->string.pointer,
- external_object->string.length);
+ ACPI_MEMCPY(internal_object->string.pointer,
+ external_object->string.pointer,
+ external_object->string.length);
internal_object->string.length = external_object->string.length;
break;
-
case ACPI_TYPE_BUFFER:
internal_object->buffer.pointer =
- ACPI_MEM_CALLOCATE (external_object->buffer.length);
+ ACPI_MEM_CALLOCATE(external_object->buffer.length);
if (!internal_object->buffer.pointer) {
goto error_exit;
}
- ACPI_MEMCPY (internal_object->buffer.pointer,
- external_object->buffer.pointer,
- external_object->buffer.length);
+ ACPI_MEMCPY(internal_object->buffer.pointer,
+ external_object->buffer.pointer,
+ external_object->buffer.length);
internal_object->buffer.length = external_object->buffer.length;
break;
-
case ACPI_TYPE_INTEGER:
- internal_object->integer.value = external_object->integer.value;
+ internal_object->integer.value = external_object->integer.value;
break;
default:
@@ -533,15 +508,13 @@ acpi_ut_copy_esimple_to_isimple (
}
*ret_internal_object = internal_object;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
- acpi_ut_remove_reference (internal_object);
- return_ACPI_STATUS (AE_NO_MEMORY);
+ error_exit:
+ acpi_ut_remove_reference(internal_object);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
-
#ifdef ACPI_FUTURE_IMPLEMENTATION
/* Code to convert packages that are parameters to control methods */
@@ -565,22 +538,18 @@ error_exit:
******************************************************************************/
static acpi_status
-acpi_ut_copy_epackage_to_ipackage (
- union acpi_operand_object *internal_object,
- u8 *buffer,
- u32 *space_used)
+acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
+ u8 * buffer, u32 * space_used)
{
- u8 *free_space;
- union acpi_object *external_object;
- u32 length = 0;
- u32 this_index;
- u32 object_space = 0;
- union acpi_operand_object *this_internal_obj;
- union acpi_object *this_external_obj;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_epackage_to_ipackage");
+ u8 *free_space;
+ union acpi_object *external_object;
+ u32 length = 0;
+ u32 this_index;
+ u32 object_space = 0;
+ union acpi_operand_object *this_internal_obj;
+ union acpi_object *this_external_obj;
+ ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage");
/*
* First package at head of the buffer
@@ -592,24 +561,22 @@ acpi_ut_copy_epackage_to_ipackage (
*/
free_space = buffer + sizeof(union acpi_object);
-
- external_object->type = ACPI_GET_OBJECT_TYPE (internal_object);
- external_object->package.count = internal_object->package.count;
- external_object->package.elements = (union acpi_object *)free_space;
+ external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
+ external_object->package.count = internal_object->package.count;
+ external_object->package.elements = (union acpi_object *)free_space;
/*
* Build an array of ACPI_OBJECTS in the buffer
* and move the free space past it
*/
- free_space += external_object->package.count * sizeof(union acpi_object);
-
+ free_space +=
+ external_object->package.count * sizeof(union acpi_object);
/* Call walk_package */
}
-#endif /* Future implementation */
-
+#endif /* Future implementation */
/*******************************************************************************
*
@@ -625,37 +592,35 @@ acpi_ut_copy_epackage_to_ipackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_eobject_to_iobject (
- union acpi_object *external_object,
- union acpi_operand_object **internal_object)
+acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
+ union acpi_operand_object **internal_object)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_eobject_to_iobject");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject");
if (external_object->type == ACPI_TYPE_PACKAGE) {
/*
* Packages as external input to control methods are not supported,
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Packages as parameters not implemented!\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Packages as parameters not implemented!\n"));
- return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
else {
/*
* Build a simple object (no nested objects)
*/
- status = acpi_ut_copy_esimple_to_isimple (external_object, internal_object);
+ status =
+ acpi_ut_copy_esimple_to_isimple(external_object,
+ internal_object);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_simple_object
@@ -671,83 +636,75 @@ acpi_ut_copy_eobject_to_iobject (
******************************************************************************/
static acpi_status
-acpi_ut_copy_simple_object (
- union acpi_operand_object *source_desc,
- union acpi_operand_object *dest_desc)
+acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
+ union acpi_operand_object *dest_desc)
{
- u16 reference_count;
- union acpi_operand_object *next_object;
-
+ u16 reference_count;
+ union acpi_operand_object *next_object;
/* Save fields from destination that we don't want to overwrite */
reference_count = dest_desc->common.reference_count;
next_object = dest_desc->common.next_object;
- /* Copy the entire source object over the destination object*/
+ /* Copy the entire source object over the destination object */
- ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
- sizeof (union acpi_operand_object));
+ ACPI_MEMCPY((char *)dest_desc, (char *)source_desc,
+ sizeof(union acpi_operand_object));
/* Restore the saved fields */
dest_desc->common.reference_count = reference_count;
dest_desc->common.next_object = next_object;
- /* Handle the objects with extra data */
+ /* New object is not static, regardless of source */
- switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
- case ACPI_TYPE_BUFFER:
+ dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
- dest_desc->buffer.node = NULL;
- dest_desc->common.flags = source_desc->common.flags;
+ /* Handle the objects with extra data */
+ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
+ case ACPI_TYPE_BUFFER:
/*
* Allocate and copy the actual buffer if and only if:
* 1) There is a valid buffer pointer
- * 2) The buffer is not static (not in an ACPI table) (in this case,
- * the actual pointer was already copied above)
+ * 2) The buffer has a length > 0
*/
if ((source_desc->buffer.pointer) &&
- (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- dest_desc->buffer.pointer = NULL;
-
- /* Create an actual buffer only if length > 0 */
-
- if (source_desc->buffer.length) {
- dest_desc->buffer.pointer =
- ACPI_MEM_ALLOCATE (source_desc->buffer.length);
- if (!dest_desc->buffer.pointer) {
- return (AE_NO_MEMORY);
- }
+ (source_desc->buffer.length)) {
+ dest_desc->buffer.pointer =
+ ACPI_MEM_ALLOCATE(source_desc->buffer.length);
+ if (!dest_desc->buffer.pointer) {
+ return (AE_NO_MEMORY);
+ }
- /* Copy the actual buffer data */
+ /* Copy the actual buffer data */
- ACPI_MEMCPY (dest_desc->buffer.pointer,
- source_desc->buffer.pointer,
- source_desc->buffer.length);
- }
+ ACPI_MEMCPY(dest_desc->buffer.pointer,
+ source_desc->buffer.pointer,
+ source_desc->buffer.length);
}
break;
case ACPI_TYPE_STRING:
-
/*
* Allocate and copy the actual string if and only if:
* 1) There is a valid string pointer
- * 2) The string is not static (not in an ACPI table) (in this case,
- * the actual pointer was already copied above)
+ * (Pointer to a NULL string is allowed)
*/
- if ((source_desc->string.pointer) &&
- (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+ if (source_desc->string.pointer) {
dest_desc->string.pointer =
- ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
+ ACPI_MEM_ALLOCATE((acpi_size) source_desc->string.
+ length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
- ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer,
- (acpi_size) source_desc->string.length + 1);
+ /* Copy the actual string data */
+
+ ACPI_MEMCPY(dest_desc->string.pointer,
+ source_desc->string.pointer,
+ (acpi_size) source_desc->string.length + 1);
}
break;
@@ -756,7 +713,7 @@ acpi_ut_copy_simple_object (
* We copied the reference object, so we now must add a reference
* to the object pointed to by the reference
*/
- acpi_ut_add_reference (source_desc->reference.object);
+ acpi_ut_add_reference(source_desc->reference.object);
break;
default:
@@ -767,7 +724,6 @@ acpi_ut_copy_simple_object (
return (AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ielement_to_ielement
@@ -781,24 +737,21 @@ acpi_ut_copy_simple_object (
******************************************************************************/
static acpi_status
-acpi_ut_copy_ielement_to_ielement (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_copy_ielement_to_ielement(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state,
+ void *context)
{
- acpi_status status = AE_OK;
- u32 this_index;
- union acpi_operand_object **this_target_ptr;
- union acpi_operand_object *target_object;
-
+ acpi_status status = AE_OK;
+ u32 this_index;
+ union acpi_operand_object **this_target_ptr;
+ union acpi_operand_object *target_object;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
-
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
this_target_ptr = (union acpi_operand_object **)
- &state->pkg.dest_object->package.elements[this_index];
+ &state->pkg.dest_object->package.elements[this_index];
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -809,34 +762,36 @@ acpi_ut_copy_ielement_to_ielement (
/*
* This is a simple object, just copy it
*/
- target_object = acpi_ut_create_internal_object (
- ACPI_GET_OBJECT_TYPE (source_object));
+ target_object =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE
+ (source_object));
if (!target_object) {
return (AE_NO_MEMORY);
}
- status = acpi_ut_copy_simple_object (source_object, target_object);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_copy_simple_object(source_object,
+ target_object);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
*this_target_ptr = target_object;
- }
- else {
+ } else {
/* Pass through a null element */
*this_target_ptr = NULL;
}
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/*
* This object is a package - go down another nesting level
* Create and build the package object
*/
- target_object = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+ target_object =
+ acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
if (!target_object) {
return (AE_NO_MEMORY);
}
@@ -848,8 +803,8 @@ acpi_ut_copy_ielement_to_ielement (
* Create the object array
*/
target_object->package.elements =
- ACPI_MEM_CALLOCATE (((acpi_size) source_object->package.count + 1) *
- sizeof (void *));
+ ACPI_MEM_CALLOCATE(((acpi_size) source_object->package.
+ count + 1) * sizeof(void *));
if (!target_object->package.elements) {
status = AE_NO_MEMORY;
goto error_exit;
@@ -866,19 +821,17 @@ acpi_ut_copy_ielement_to_ielement (
*this_target_ptr = target_object;
break;
-
default:
return (AE_BAD_PARAMETER);
}
return (status);
-error_exit:
- acpi_ut_remove_reference (target_object);
+ error_exit:
+ acpi_ut_remove_reference(target_object);
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_ipackage_to_ipackage
@@ -894,49 +847,46 @@ error_exit:
******************************************************************************/
static acpi_status
-acpi_ut_copy_ipackage_to_ipackage (
- union acpi_operand_object *source_obj,
- union acpi_operand_object *dest_obj,
- struct acpi_walk_state *walk_state)
+acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
+ union acpi_operand_object *dest_obj,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
+ acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE ("ut_copy_ipackage_to_ipackage");
+ ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_ipackage");
-
- dest_obj->common.type = ACPI_GET_OBJECT_TYPE (source_obj);
- dest_obj->common.flags = source_obj->common.flags;
+ dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj);
+ dest_obj->common.flags = source_obj->common.flags;
dest_obj->package.count = source_obj->package.count;
/*
* Create the object array and walk the source package tree
*/
- dest_obj->package.elements = ACPI_MEM_CALLOCATE (
- ((acpi_size) source_obj->package.count + 1) *
- sizeof (void *));
+ dest_obj->package.elements = ACPI_MEM_CALLOCATE(((acpi_size)
+ source_obj->package.
+ count +
+ 1) * sizeof(void *));
if (!dest_obj->package.elements) {
- ACPI_REPORT_ERROR (
- ("aml_build_copy_internal_package_object: Package allocation failure\n"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_REPORT_ERROR(("aml_build_copy_internal_package_object: Package allocation failure\n"));
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
* Copy the package element-by-element by walking the package "tree".
* This handles nested packages of arbitrary depth.
*/
- status = acpi_ut_walk_package_tree (source_obj, dest_obj,
- acpi_ut_copy_ielement_to_ielement, walk_state);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_walk_package_tree(source_obj, dest_obj,
+ acpi_ut_copy_ielement_to_ielement,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
/* On failure, delete the destination package object */
- acpi_ut_remove_reference (dest_obj);
+ acpi_ut_remove_reference(dest_obj);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_iobject_to_iobject
@@ -952,35 +902,31 @@ acpi_ut_copy_ipackage_to_ipackage (
******************************************************************************/
acpi_status
-acpi_ut_copy_iobject_to_iobject (
- union acpi_operand_object *source_desc,
- union acpi_operand_object **dest_desc,
- struct acpi_walk_state *walk_state)
+acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
+ union acpi_operand_object **dest_desc,
+ struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("ut_copy_iobject_to_iobject");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject");
/* Create the top level object */
- *dest_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (source_desc));
+ *dest_desc =
+ acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc));
if (!*dest_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the object and possible subobjects */
- if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_PACKAGE) {
- status = acpi_ut_copy_ipackage_to_ipackage (source_desc, *dest_desc,
- walk_state);
- }
- else {
- status = acpi_ut_copy_simple_object (source_desc, *dest_desc);
+ if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) {
+ status =
+ acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
+ walk_state);
+ } else {
+ status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
-
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 794c7df3f2ad..d80e92639932 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -46,15 +46,16 @@
#include <acpi/acpi.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utdebug")
-
+ACPI_MODULE_NAME("utdebug")
#ifdef ACPI_DEBUG_OUTPUT
+static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
+static char *acpi_gbl_fn_entry_str = "----Entry";
+static char *acpi_gbl_fn_exit_str = "----Exit-";
-static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF;
-static char *acpi_gbl_fn_entry_str = "----Entry";
-static char *acpi_gbl_fn_exit_str = "----Exit-";
+/* Local prototypes */
+static const char *acpi_ut_trim_function_name(const char *function_name);
/*******************************************************************************
*
@@ -68,17 +69,13 @@ static char *acpi_gbl_fn_exit_str = "----Exit-";
*
******************************************************************************/
-void
-acpi_ut_init_stack_ptr_trace (
- void)
+void acpi_ut_init_stack_ptr_trace(void)
{
- u32 current_sp;
-
+ u32 current_sp;
- acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF (&current_sp, NULL);
+ acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(&current_sp, NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_track_stack_ptr
@@ -91,14 +88,11 @@ acpi_ut_init_stack_ptr_trace (
*
******************************************************************************/
-void
-acpi_ut_track_stack_ptr (
- void)
+void acpi_ut_track_stack_ptr(void)
{
- acpi_size current_sp;
-
+ acpi_size current_sp;
- current_sp = ACPI_PTR_DIFF (&current_sp, NULL);
+ current_sp = ACPI_PTR_DIFF(&current_sp, NULL);
if (current_sp < acpi_gbl_lowest_stack_pointer) {
acpi_gbl_lowest_stack_pointer = current_sp;
@@ -109,6 +103,39 @@ acpi_ut_track_stack_ptr (
}
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_trim_function_name
+ *
+ * PARAMETERS: function_name - Ascii string containing a procedure name
+ *
+ * RETURN: Updated pointer to the function name
+ *
+ * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
+ * This allows compiler macros such as __FUNCTION__ to be used
+ * with no change to the debug output.
+ *
+ ******************************************************************************/
+
+static const char *acpi_ut_trim_function_name(const char *function_name)
+{
+
+ /* All Function names are longer than 4 chars, check is safe */
+
+ if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) {
+ /* This is the case where the original source has not been modified */
+
+ return (function_name + 4);
+ }
+
+ if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) {
+ /* This is the case where the source has been 'linuxized' */
+
+ return (function_name + 5);
+ }
+
+ return (function_name);
+}
/*******************************************************************************
*
@@ -116,10 +143,9 @@ acpi_ut_track_stack_ptr (
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number (for error output)
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Format - Printf format field
* ... - Optional printf arguments
*
@@ -130,36 +156,33 @@ acpi_ut_track_stack_ptr (
*
******************************************************************************/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_debug_print(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *format, ...)
{
- u32 thread_id;
- va_list args;
-
+ u32 thread_id;
+ va_list args;
/*
* Stay silent if the debug level or component ID is disabled
*/
if (!(requested_debug_level & acpi_dbg_level) ||
- !(dbg_info->component_id & acpi_dbg_layer)) {
+ !(component_id & acpi_dbg_layer)) {
return;
}
/*
* Thread tracking and context switch notification
*/
- thread_id = acpi_os_get_thread_id ();
+ thread_id = acpi_os_get_thread_id();
if (thread_id != acpi_gbl_prev_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
- acpi_os_printf (
- "\n**** Context Switch from TID %X to TID %X ****\n\n",
- acpi_gbl_prev_thread_id, thread_id);
+ acpi_os_printf
+ ("\n**** Context Switch from TID %X to TID %X ****\n\n",
+ acpi_gbl_prev_thread_id, thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
@@ -169,17 +192,18 @@ acpi_ut_debug_print (
* Display the module name, current line number, thread ID (if requested),
* current procedure nesting level, and the current procedure name
*/
- acpi_os_printf ("%8s-%04ld ", dbg_info->module_name, line_number);
+ acpi_os_printf("%8s-%04ld ", module_name, line_number);
if (ACPI_LV_THREADS & acpi_dbg_level) {
- acpi_os_printf ("[%04lX] ", thread_id);
+ acpi_os_printf("[%04lX] ", thread_id);
}
- acpi_os_printf ("[%02ld] %-22.22s: ",
- acpi_gbl_nesting_level, dbg_info->proc_name);
+ acpi_os_printf("[%02ld] %-22.22s: ",
+ acpi_gbl_nesting_level,
+ acpi_ut_trim_function_name(function_name));
- va_start (args, format);
- acpi_os_vprintf (format, args);
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
}
EXPORT_SYMBOL(acpi_ut_debug_print);
@@ -190,10 +214,9 @@ EXPORT_SYMBOL(acpi_ut_debug_print);
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Format - Printf format field
* ... - Optional printf arguments
*
@@ -204,37 +227,33 @@ EXPORT_SYMBOL(acpi_ut_debug_print);
*
******************************************************************************/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print_raw (
- u32 requested_debug_level,
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *format,
- ...)
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_debug_print_raw(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *format, ...)
{
- va_list args;
-
+ va_list args;
if (!(requested_debug_level & acpi_dbg_level) ||
- !(dbg_info->component_id & acpi_dbg_layer)) {
+ !(component_id & acpi_dbg_layer)) {
return;
}
- va_start (args, format);
- acpi_os_vprintf (format, args);
+ va_start(args, format);
+ acpi_os_vprintf(format, args);
}
-EXPORT_SYMBOL(acpi_ut_debug_print_raw);
+EXPORT_SYMBOL(acpi_ut_debug_print_raw);
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
*
* RETURN: None
*
@@ -244,29 +263,28 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw);
******************************************************************************/
void
-acpi_ut_trace (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info)
+acpi_ut_trace(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s\n", acpi_gbl_fn_entry_str);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s\n", acpi_gbl_fn_entry_str);
}
-EXPORT_SYMBOL(acpi_ut_trace);
+EXPORT_SYMBOL(acpi_ut_trace);
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_ptr
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Pointer - Pointer to display
*
* RETURN: None
@@ -277,28 +295,27 @@ EXPORT_SYMBOL(acpi_ut_trace);
******************************************************************************/
void
-acpi_ut_trace_ptr (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- void *pointer)
+acpi_ut_trace_ptr(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, void *pointer)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %p\n", acpi_gbl_fn_entry_str, pointer);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %p\n", acpi_gbl_fn_entry_str,
+ pointer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_str
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* String - Additional string to display
*
* RETURN: None
@@ -309,29 +326,28 @@ acpi_ut_trace_ptr (
******************************************************************************/
void
-acpi_ut_trace_str (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- char *string)
+acpi_ut_trace_str(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, char *string)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %s\n", acpi_gbl_fn_entry_str, string);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %s\n", acpi_gbl_fn_entry_str,
+ string);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_trace_u32
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Integer - Integer to display
*
* RETURN: None
@@ -342,29 +358,28 @@ acpi_ut_trace_str (
******************************************************************************/
void
-acpi_ut_trace_u32 (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u32 integer)
+acpi_ut_trace_u32(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u32 integer)
{
acpi_gbl_nesting_level++;
- acpi_ut_track_stack_ptr ();
+ acpi_ut_track_stack_ptr();
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %08X\n", acpi_gbl_fn_entry_str, integer);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %08X\n", acpi_gbl_fn_entry_str,
+ integer);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
*
* RETURN: None
*
@@ -374,28 +389,27 @@ acpi_ut_trace_u32 (
******************************************************************************/
void
-acpi_ut_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info)
+acpi_ut_exit(u32 line_number,
+ const char *function_name, char *module_name, u32 component_id)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s\n", acpi_gbl_fn_exit_str);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s\n", acpi_gbl_fn_exit_str);
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_exit);
+EXPORT_SYMBOL(acpi_ut_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_status_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Status - Exit status code
*
* RETURN: None
@@ -406,37 +420,38 @@ EXPORT_SYMBOL(acpi_ut_exit);
******************************************************************************/
void
-acpi_ut_status_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_status status)
+acpi_ut_status_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_status status)
{
- if (ACPI_SUCCESS (status)) {
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %s\n", acpi_gbl_fn_exit_str,
- acpi_format_exception (status));
- }
- else {
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s ****Exception****: %s\n", acpi_gbl_fn_exit_str,
- acpi_format_exception (status));
+ if (ACPI_SUCCESS(status)) {
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %s\n",
+ acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
+ } else {
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s ****Exception****: %s\n",
+ acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
}
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_status_exit);
+EXPORT_SYMBOL(acpi_ut_status_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_value_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Value - Value to be printed with exit msg
*
* RETURN: None
@@ -447,30 +462,29 @@ EXPORT_SYMBOL(acpi_ut_status_exit);
******************************************************************************/
void
-acpi_ut_value_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- acpi_integer value)
+acpi_ut_value_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, acpi_integer value)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str,
- ACPI_FORMAT_UINT64 (value));
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %8.8X%8.8X\n",
+ acpi_gbl_fn_exit_str, ACPI_FORMAT_UINT64(value));
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_value_exit);
+EXPORT_SYMBOL(acpi_ut_value_exit);
/*******************************************************************************
*
* FUNCTION: acpi_ut_ptr_exit
*
* PARAMETERS: line_number - Caller's line number
- * dbg_info - Contains:
- * proc_name - Caller's procedure name
- * module_name - Caller's module name
- * component_id - Caller's component ID
+ * function_name - Caller's procedure name
+ * module_name - Caller's module name
+ * component_id - Caller's component ID
* Ptr - Pointer to display
*
* RETURN: None
@@ -481,21 +495,20 @@ EXPORT_SYMBOL(acpi_ut_value_exit);
******************************************************************************/
void
-acpi_ut_ptr_exit (
- u32 line_number,
- struct acpi_debug_print_info *dbg_info,
- u8 *ptr)
+acpi_ut_ptr_exit(u32 line_number,
+ const char *function_name,
+ char *module_name, u32 component_id, u8 * ptr)
{
- acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info,
- "%s %p\n", acpi_gbl_fn_exit_str, ptr);
+ acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %p\n", acpi_gbl_fn_exit_str, ptr);
acpi_gbl_nesting_level--;
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dump_buffer
@@ -511,23 +524,17 @@ acpi_ut_ptr_exit (
*
******************************************************************************/
-void
-acpi_ut_dump_buffer (
- u8 *buffer,
- u32 count,
- u32 display,
- u32 component_id)
+void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
{
- acpi_native_uint i = 0;
- acpi_native_uint j;
- u32 temp32;
- u8 buf_char;
-
+ acpi_native_uint i = 0;
+ acpi_native_uint j;
+ u32 temp32;
+ u8 buf_char;
/* Only dump the buffer if tracing is enabled */
if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
- (component_id & acpi_dbg_layer))) {
+ (component_id & acpi_dbg_layer))) {
return;
}
@@ -540,7 +547,7 @@ acpi_ut_dump_buffer (
while (i < count) {
/* Print current offset */
- acpi_os_printf ("%6.4X: ", (u32) i);
+ acpi_os_printf("%6.4X: ", (u32) i);
/* Print 16 hex chars */
@@ -548,73 +555,66 @@ acpi_ut_dump_buffer (
if (i + j >= count) {
/* Dump fill spaces */
- acpi_os_printf ("%*s", ((display * 2) + 1), " ");
- j += display;
+ acpi_os_printf("%*s", ((display * 2) + 1), " ");
+ j += (acpi_native_uint) display;
continue;
}
switch (display) {
- default: /* Default is BYTE display */
+ default: /* Default is BYTE display */
- acpi_os_printf ("%02X ", buffer[i + j]);
+ acpi_os_printf("%02X ", buffer[i + j]);
break;
-
case DB_WORD_DISPLAY:
- ACPI_MOVE_16_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%04X ", temp32);
+ ACPI_MOVE_16_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%04X ", temp32);
break;
-
case DB_DWORD_DISPLAY:
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%08X ", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%08X ", temp32);
break;
-
case DB_QWORD_DISPLAY:
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j]);
- acpi_os_printf ("%08X", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j]);
+ acpi_os_printf("%08X", temp32);
- ACPI_MOVE_32_TO_32 (&temp32, &buffer[i + j + 4]);
- acpi_os_printf ("%08X ", temp32);
+ ACPI_MOVE_32_TO_32(&temp32, &buffer[i + j + 4]);
+ acpi_os_printf("%08X ", temp32);
break;
}
- j += display;
+ j += (acpi_native_uint) display;
}
/*
- * Print the ASCII equivalent characters
- * But watch out for the bad unprintable ones...
+ * Print the ASCII equivalent characters but watch out for the bad
+ * unprintable ones (printable chars are 0x20 through 0x7E)
*/
- acpi_os_printf (" ");
+ acpi_os_printf(" ");
for (j = 0; j < 16; j++) {
if (i + j >= count) {
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
return;
}
buf_char = buffer[i + j];
- if ((buf_char > 0x1F && buf_char < 0x2E) ||
- (buf_char > 0x2F && buf_char < 0x61) ||
- (buf_char > 0x60 && buf_char < 0x7F)) {
- acpi_os_printf ("%c", buf_char);
- }
- else {
- acpi_os_printf (".");
+ if (ACPI_IS_PRINT(buf_char)) {
+ acpi_os_printf("%c", buf_char);
+ } else {
+ acpi_os_printf(".");
}
}
/* Done with that line. */
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
i += 16;
}
return;
}
-
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index bc5403022681..2bc878f7a127 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -41,7 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
@@ -49,19 +48,13 @@
#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utdelete")
+ACPI_MODULE_NAME("utdelete")
/* Local prototypes */
+static void acpi_ut_delete_internal_obj(union acpi_operand_object *object);
static void
-acpi_ut_delete_internal_obj (
- union acpi_operand_object *object);
-
-static void
-acpi_ut_update_ref_count (
- union acpi_operand_object *object,
- u32 action);
-
+acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action);
/*******************************************************************************
*
@@ -76,18 +69,14 @@ acpi_ut_update_ref_count (
*
******************************************************************************/
-static void
-acpi_ut_delete_internal_obj (
- union acpi_operand_object *object)
+static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
{
- void *obj_pointer = NULL;
- union acpi_operand_object *handler_desc;
- union acpi_operand_object *second_desc;
- union acpi_operand_object *next_desc;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_delete_internal_obj", object);
+ void *obj_pointer = NULL;
+ union acpi_operand_object *handler_desc;
+ union acpi_operand_object *second_desc;
+ union acpi_operand_object *next_desc;
+ ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object);
if (!object) {
return_VOID;
@@ -97,11 +86,12 @@ acpi_ut_delete_internal_obj (
* Must delete or free any pointers within the object that are not
* actual ACPI objects (for example, a raw buffer pointer).
*/
- switch (ACPI_GET_OBJECT_TYPE (object)) {
+ switch (ACPI_GET_OBJECT_TYPE(object)) {
case ACPI_TYPE_STRING:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
- object, object->string.pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "**** String %p, ptr %p\n", object,
+ object->string.pointer));
/* Free the actual string buffer */
@@ -112,11 +102,11 @@ acpi_ut_delete_internal_obj (
}
break;
-
case ACPI_TYPE_BUFFER:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
- object, object->buffer.pointer));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "**** Buffer %p, ptr %p\n", object,
+ object->buffer.pointer));
/* Free the actual buffer */
@@ -127,11 +117,11 @@ acpi_ut_delete_internal_obj (
}
break;
-
case ACPI_TYPE_PACKAGE:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
- object->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ " **** Package of count %X\n",
+ object->package.count));
/*
* Elements of the package are not handled here, they are deleted
@@ -143,11 +133,11 @@ acpi_ut_delete_internal_obj (
obj_pointer = object->package.elements;
break;
-
case ACPI_TYPE_DEVICE:
if (object->device.gpe_block) {
- (void) acpi_ev_delete_gpe_block (object->device.gpe_block);
+ (void)acpi_ev_delete_gpe_block(object->device.
+ gpe_block);
}
/* Walk the handler list for this device */
@@ -155,54 +145,51 @@ acpi_ut_delete_internal_obj (
handler_desc = object->device.handler;
while (handler_desc) {
next_desc = handler_desc->address_space.next;
- acpi_ut_remove_reference (handler_desc);
+ acpi_ut_remove_reference(handler_desc);
handler_desc = next_desc;
}
break;
-
case ACPI_TYPE_MUTEX:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Mutex %p, Semaphore %p\n",
- object, object->mutex.semaphore));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Mutex %p, Semaphore %p\n",
+ object, object->mutex.semaphore));
- acpi_ex_unlink_mutex (object);
- (void) acpi_os_delete_semaphore (object->mutex.semaphore);
+ acpi_ex_unlink_mutex(object);
+ (void)acpi_os_delete_semaphore(object->mutex.semaphore);
break;
-
case ACPI_TYPE_EVENT:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Event %p, Semaphore %p\n",
- object, object->event.semaphore));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Event %p, Semaphore %p\n",
+ object, object->event.semaphore));
- (void) acpi_os_delete_semaphore (object->event.semaphore);
+ (void)acpi_os_delete_semaphore(object->event.semaphore);
object->event.semaphore = NULL;
break;
-
case ACPI_TYPE_METHOD:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Method %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Method %p\n", object));
/* Delete the method semaphore if it exists */
if (object->method.semaphore) {
- (void) acpi_os_delete_semaphore (object->method.semaphore);
+ (void)acpi_os_delete_semaphore(object->method.
+ semaphore);
object->method.semaphore = NULL;
}
break;
-
case ACPI_TYPE_REGION:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Region %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Region %p\n", object));
- second_desc = acpi_ns_get_secondary_object (object);
+ second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
/*
* Free the region_context if and only if the handler is one of the
@@ -211,32 +198,33 @@ acpi_ut_delete_internal_obj (
*/
handler_desc = object->region.handler;
if (handler_desc) {
- if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
- obj_pointer = second_desc->extra.region_context;
+ if (handler_desc->address_space.
+ hflags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
+ obj_pointer =
+ second_desc->extra.region_context;
}
- acpi_ut_remove_reference (handler_desc);
+ acpi_ut_remove_reference(handler_desc);
}
/* Now we can free the Extra object */
- acpi_ut_delete_object_desc (second_desc);
+ acpi_ut_delete_object_desc(second_desc);
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "***** Buffer Field %p\n", object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "***** Buffer Field %p\n", object));
- second_desc = acpi_ns_get_secondary_object (object);
+ second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
- acpi_ut_delete_object_desc (second_desc);
+ acpi_ut_delete_object_desc(second_desc);
}
break;
-
default:
break;
}
@@ -244,21 +232,20 @@ acpi_ut_delete_internal_obj (
/* Free any allocated memory (pointer within the object) found above */
if (obj_pointer) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
- obj_pointer));
- ACPI_MEM_FREE (obj_pointer);
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Deleting Object Subptr %p\n", obj_pointer));
+ ACPI_MEM_FREE(obj_pointer);
}
/* Now the object can be safely deleted */
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
- object, acpi_ut_get_object_type_name (object)));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
+ object, acpi_ut_get_object_type_name(object)));
- acpi_ut_delete_object_desc (object);
+ acpi_ut_delete_object_desc(object);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_delete_internal_object_list
@@ -272,29 +259,24 @@ acpi_ut_delete_internal_obj (
*
******************************************************************************/
-void
-acpi_ut_delete_internal_object_list (
- union acpi_operand_object **obj_list)
+void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list)
{
- union acpi_operand_object **internal_obj;
-
-
- ACPI_FUNCTION_TRACE ("ut_delete_internal_object_list");
+ union acpi_operand_object **internal_obj;
+ ACPI_FUNCTION_TRACE("ut_delete_internal_object_list");
/* Walk the null-terminated internal list */
for (internal_obj = obj_list; *internal_obj; internal_obj++) {
- acpi_ut_remove_reference (*internal_obj);
+ acpi_ut_remove_reference(*internal_obj);
}
/* Free the combined parameter pointer list and object array */
- ACPI_MEM_FREE (obj_list);
+ ACPI_MEM_FREE(obj_list);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_update_ref_count
@@ -309,16 +291,12 @@ acpi_ut_delete_internal_object_list (
******************************************************************************/
static void
-acpi_ut_update_ref_count (
- union acpi_operand_object *object,
- u32 action)
+acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
{
- u16 count;
- u16 new_count;
-
-
- ACPI_FUNCTION_NAME ("ut_update_ref_count");
+ u16 count;
+ u16 new_count;
+ ACPI_FUNCTION_NAME("ut_update_ref_count");
if (!object) {
return;
@@ -338,58 +316,55 @@ acpi_ut_update_ref_count (
new_count++;
object->common.reference_count = new_count;
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, [Incremented]\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, [Incremented]\n",
+ object, new_count));
break;
-
case REF_DECREMENT:
if (count < 1) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
+ object, new_count));
new_count = 0;
- }
- else {
+ } else {
new_count--;
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, [Decremented]\n",
- object, new_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, [Decremented]\n",
+ object, new_count));
}
- if (ACPI_GET_OBJECT_TYPE (object) == ACPI_TYPE_METHOD) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Method Obj %p Refs=%X, [Decremented]\n",
- object, new_count));
+ if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Method Obj %p Refs=%X, [Decremented]\n",
+ object, new_count));
}
object->common.reference_count = new_count;
if (new_count == 0) {
- acpi_ut_delete_internal_obj (object);
+ acpi_ut_delete_internal_obj(object);
}
break;
-
case REF_FORCE_DELETE:
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Refs=%X, Force delete! (Set to 0)\n",
- object, count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Refs=%X, Force delete! (Set to 0)\n",
+ object, count));
new_count = 0;
object->common.reference_count = new_count;
- acpi_ut_delete_internal_obj (object);
+ acpi_ut_delete_internal_obj(object);
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown action (%X)\n", action));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown action (%X)\n",
+ action));
break;
}
@@ -399,15 +374,14 @@ acpi_ut_update_ref_count (
*/
if (count > ACPI_MAX_REFERENCE_COUNT) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
- "**** Warning **** Large Reference Count (%X) in object %p\n\n",
- count, object));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "**** Warning **** Large Reference Count (%X) in object %p\n\n",
+ count, object));
}
return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_update_object_reference
@@ -431,65 +405,42 @@ acpi_ut_update_ref_count (
******************************************************************************/
acpi_status
-acpi_ut_update_object_reference (
- union acpi_operand_object *object,
- u16 action)
+acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
{
- acpi_status status;
- u32 i;
- union acpi_generic_state *state_list = NULL;
- union acpi_generic_state *state;
- union acpi_operand_object *tmp;
-
- ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object);
+ acpi_status status = AE_OK;
+ union acpi_generic_state *state_list = NULL;
+ union acpi_operand_object *next_object = NULL;
+ union acpi_generic_state *state;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object);
- /* Ignore a null object ptr */
+ while (object) {
+ /* Make sure that this isn't a namespace handle */
- if (!object) {
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Make sure that this isn't a namespace handle */
-
- if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Object %p is NS handle\n", object));
- return_ACPI_STATUS (AE_OK);
- }
-
- state = acpi_ut_create_update_state (object, action);
-
- while (state) {
- object = state->update.object;
- action = state->update.value;
- acpi_ut_delete_generic_state (state);
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Object %p is NS handle\n", object));
+ return_ACPI_STATUS(AE_OK);
+ }
/*
* All sub-objects must have their reference count incremented also.
* Different object types have different subobjects.
*/
- switch (ACPI_GET_OBJECT_TYPE (object)) {
+ switch (ACPI_GET_OBJECT_TYPE(object)) {
case ACPI_TYPE_DEVICE:
- tmp = object->device.system_notify;
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->device.system_notify = NULL;
- acpi_ut_update_ref_count (tmp, action);
-
- tmp = object->device.device_notify;
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->device.device_notify = NULL;
- acpi_ut_update_ref_count (tmp, action);
-
+ acpi_ut_update_ref_count(object->device.system_notify,
+ action);
+ acpi_ut_update_ref_count(object->device.device_notify,
+ action);
break;
-
case ACPI_TYPE_PACKAGE:
-
/*
- * We must update all the sub-objects of the package
- * (Each of whom may have their own sub-objects, etc.
+ * We must update all the sub-objects of the package,
+ * each of whom may have their own sub-objects.
*/
for (i = 0; i < object->package.count; i++) {
/*
@@ -497,116 +448,67 @@ acpi_ut_update_object_reference (
* Note: There can be null elements within the package,
* these are simply ignored
*/
- status = acpi_ut_create_update_state_and_push (
- object->package.elements[i], action, &state_list);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_create_update_state_and_push
+ (object->package.elements[i], action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->package.elements[i];
- if (tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->package.elements[i] = NULL;
}
break;
-
case ACPI_TYPE_BUFFER_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->buffer_field.buffer_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->buffer_field.buffer_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->buffer_field.buffer_obj = NULL;
+ next_object = object->buffer_field.buffer_obj;
break;
-
case ACPI_TYPE_LOCAL_REGION_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->field.region_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->field.region_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->field.region_obj = NULL;
- break;
-
+ next_object = object->field.region_obj;
+ break;
case ACPI_TYPE_LOCAL_BANK_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->bank_field.bank_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
+ next_object = object->bank_field.bank_obj;
+ status =
+ acpi_ut_create_update_state_and_push(object->
+ bank_field.
+ region_obj,
+ action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->bank_field.bank_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->bank_field.bank_obj = NULL;
-
- status = acpi_ut_create_update_state_and_push (
- object->bank_field.region_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->bank_field.region_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->bank_field.region_obj = NULL;
break;
-
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- status = acpi_ut_create_update_state_and_push (
- object->index_field.index_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
-
- tmp = object->index_field.index_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->index_field.index_obj = NULL;
-
- status = acpi_ut_create_update_state_and_push (
- object->index_field.data_obj, action, &state_list);
- if (ACPI_FAILURE (status)) {
+ next_object = object->index_field.index_obj;
+ status =
+ acpi_ut_create_update_state_and_push(object->
+ index_field.
+ data_obj,
+ action,
+ &state_list);
+ if (ACPI_FAILURE(status)) {
goto error_exit;
}
-
- tmp = object->index_field.data_obj;
- if ( tmp && (tmp->common.reference_count <= 1) && action == REF_DECREMENT)
- object->index_field.data_obj = NULL;
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
-
/*
* The target of an Index (a package, string, or buffer) must track
* changes to the ref count of the index.
*/
if (object->reference.opcode == AML_INDEX_OP) {
- status = acpi_ut_create_update_state_and_push (
- object->reference.object, action, &state_list);
- if (ACPI_FAILURE (status)) {
- goto error_exit;
- }
+ next_object = object->reference.object;
}
break;
-
case ACPI_TYPE_REGION:
default:
-
- /* No subobjects */
- break;
+ break; /* No subobjects */
}
/*
@@ -614,25 +516,31 @@ acpi_ut_update_object_reference (
* happen after we update the sub-objects in case this causes the
* main object to be deleted.
*/
- acpi_ut_update_ref_count (object, action);
+ acpi_ut_update_ref_count(object, action);
+ object = NULL;
/* Move on to the next object to be updated */
- state = acpi_ut_pop_generic_state (&state_list);
+ if (next_object) {
+ object = next_object;
+ next_object = NULL;
+ } else if (state_list) {
+ state = acpi_ut_pop_generic_state(&state_list);
+ object = state->update.object;
+ acpi_ut_delete_generic_state(state);
+ }
}
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
- ACPI_REPORT_ERROR (("Could not update object reference count, %s\n",
- acpi_format_exception (status)));
+ ACPI_REPORT_ERROR(("Could not update object reference count, %s\n",
+ acpi_format_exception(status)));
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_add_reference
@@ -646,31 +554,27 @@ error_exit:
*
******************************************************************************/
-void
-acpi_ut_add_reference (
- union acpi_operand_object *object)
+void acpi_ut_add_reference(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR ("ut_add_reference", object);
-
+ ACPI_FUNCTION_TRACE_PTR("ut_add_reference", object);
/* Ensure that we have a valid object */
- if (!acpi_ut_valid_internal_object (object)) {
+ if (!acpi_ut_valid_internal_object(object)) {
return_VOID;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Current Refs=%X [To Be Incremented]\n",
- object, object->common.reference_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Current Refs=%X [To Be Incremented]\n",
+ object, object->common.reference_count));
/* Increment the reference count */
- (void) acpi_ut_update_object_reference (object, REF_INCREMENT);
+ (void)acpi_ut_update_object_reference(object, REF_INCREMENT);
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_remove_reference
@@ -683,13 +587,10 @@ acpi_ut_add_reference (
*
******************************************************************************/
-void
-acpi_ut_remove_reference (
- union acpi_operand_object *object)
+void acpi_ut_remove_reference(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR ("ut_remove_reference", object);
-
+ ACPI_FUNCTION_TRACE_PTR("ut_remove_reference", object);
/*
* Allow a NULL pointer to be passed in, just ignore it. This saves
@@ -697,27 +598,25 @@ acpi_ut_remove_reference (
*
*/
if (!object ||
- (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED)) {
+ (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) {
return_VOID;
}
/* Ensure that we have a valid object */
- if (!acpi_ut_valid_internal_object (object)) {
+ if (!acpi_ut_valid_internal_object(object)) {
return_VOID;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
- "Obj %p Current Refs=%X [To Be Decremented]\n",
- object, object->common.reference_count));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Obj %p Current Refs=%X [To Be Decremented]\n",
+ object, object->common.reference_count));
/*
* Decrement the reference count, and only actually delete the object
* if the reference count becomes 0. (Must also decrement the ref count
* of all subobjects!)
*/
- (void) acpi_ut_update_object_reference (object, REF_DECREMENT);
+ (void)acpi_ut_update_object_reference(object, REF_DECREMENT);
return_VOID;
}
-
-
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 00046dd5d925..7b81d5ef3c32 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -41,28 +41,20 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("uteval")
+ACPI_MODULE_NAME("uteval")
/* Local prototypes */
-
static void
-acpi_ut_copy_id_string (
- char *destination,
- char *source,
- acpi_size max_length);
+acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length);
static acpi_status
-acpi_ut_translate_one_cid (
- union acpi_operand_object *obj_desc,
- struct acpi_compatible_id *one_cid);
-
+acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
+ struct acpi_compatible_id *one_cid);
/*******************************************************************************
*
@@ -77,37 +69,33 @@ acpi_ut_translate_one_cid (
*
******************************************************************************/
-acpi_status
-acpi_ut_osi_implementation (
- struct acpi_walk_state *walk_state)
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *string_desc;
- union acpi_operand_object *return_desc;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ut_osi_implementation");
+ union acpi_operand_object *string_desc;
+ union acpi_operand_object *return_desc;
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ut_osi_implementation");
/* Validate the string input argument */
string_desc = walk_state->arguments[0].object;
if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
- return_ACPI_STATUS (AE_TYPE);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Create a return object (Default value = 0) */
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Compare input string to table of supported strings */
for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
- if (!ACPI_STRCMP (string_desc->string.pointer,
- (char *) acpi_gbl_valid_osi_strings[i])) {
+ if (!ACPI_STRCMP(string_desc->string.pointer,
+ (char *)acpi_gbl_valid_osi_strings[i])) {
/* This string is supported */
return_desc->integer.value = 0xFFFFFFFF;
@@ -116,10 +104,9 @@ acpi_ut_osi_implementation (
}
walk_state->return_desc = return_desc;
- return_ACPI_STATUS (AE_CTRL_TERMINATE);
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_evaluate_object
@@ -140,19 +127,16 @@ acpi_ut_osi_implementation (
******************************************************************************/
acpi_status
-acpi_ut_evaluate_object (
- struct acpi_namespace_node *prefix_node,
- char *path,
- u32 expected_return_btypes,
- union acpi_operand_object **return_desc)
+acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
+ char *path,
+ u32 expected_return_btypes,
+ union acpi_operand_object **return_desc)
{
- struct acpi_parameter_info info;
- acpi_status status;
- u32 return_btype;
-
-
- ACPI_FUNCTION_TRACE ("ut_evaluate_object");
+ struct acpi_parameter_info info;
+ acpi_status status;
+ u32 return_btype;
+ ACPI_FUNCTION_TRACE("ut_evaluate_object");
info.node = prefix_node;
info.parameters = NULL;
@@ -160,36 +144,38 @@ acpi_ut_evaluate_object (
/* Evaluate the object/method */
- status = acpi_ns_evaluate_relative (path, &info);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_evaluate_relative(path, &info);
+ if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
- acpi_ut_get_node_name (prefix_node), path));
- }
- else {
- ACPI_REPORT_METHOD_ERROR ("Method execution failed",
- prefix_node, path, status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%4.4s.%s] was not found\n",
+ acpi_ut_get_node_name(prefix_node),
+ path));
+ } else {
+ ACPI_REPORT_METHOD_ERROR("Method execution failed",
+ prefix_node, path, status);
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Did we get a return object? */
if (!info.return_object) {
if (expected_return_btypes) {
- ACPI_REPORT_METHOD_ERROR ("No object was returned from",
- prefix_node, path, AE_NOT_EXIST);
+ ACPI_REPORT_METHOD_ERROR("No object was returned from",
+ prefix_node, path,
+ AE_NOT_EXIST);
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Map the return object type to the bitmapped type */
- switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(info.return_object)) {
case ACPI_TYPE_INTEGER:
return_btype = ACPI_BTYPE_INTEGER;
break;
@@ -211,41 +197,41 @@ acpi_ut_evaluate_object (
break;
}
- if ((acpi_gbl_enable_interpreter_slack) &&
- (!expected_return_btypes)) {
+ if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
/*
* We received a return object, but one was not expected. This can
* happen frequently if the "implicit return" feature is enabled.
* Just delete the return object and return AE_OK.
*/
- acpi_ut_remove_reference (info.return_object);
- return_ACPI_STATUS (AE_OK);
+ acpi_ut_remove_reference(info.return_object);
+ return_ACPI_STATUS(AE_OK);
}
/* Is the return object one of the expected types? */
if (!(expected_return_btypes & return_btype)) {
- ACPI_REPORT_METHOD_ERROR ("Return object type is incorrect",
- prefix_node, path, AE_TYPE);
+ ACPI_REPORT_METHOD_ERROR("Return object type is incorrect",
+ prefix_node, path, AE_TYPE);
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
- path, acpi_ut_get_object_type_name (info.return_object),
- expected_return_btypes));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Type returned from %s was incorrect: %s, expected Btypes: %X\n",
+ path,
+ acpi_ut_get_object_type_name(info.
+ return_object),
+ expected_return_btypes));
/* On error exit, we must delete the return object */
- acpi_ut_remove_reference (info.return_object);
- return_ACPI_STATUS (AE_TYPE);
+ acpi_ut_remove_reference(info.return_object);
+ return_ACPI_STATUS(AE_TYPE);
}
/* Object type is OK, return it */
*return_desc = info.return_object;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_evaluate_numeric_object
@@ -264,22 +250,19 @@ acpi_ut_evaluate_object (
******************************************************************************/
acpi_status
-acpi_ut_evaluate_numeric_object (
- char *object_name,
- struct acpi_namespace_node *device_node,
- acpi_integer *address)
+acpi_ut_evaluate_numeric_object(char *object_name,
+ struct acpi_namespace_node *device_node,
+ acpi_integer * address)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ut_evaluate_numeric_object");
+ ACPI_FUNCTION_TRACE("ut_evaluate_numeric_object");
-
- status = acpi_ut_evaluate_object (device_node, object_name,
- ACPI_BTYPE_INTEGER, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, object_name,
+ ACPI_BTYPE_INTEGER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the returned Integer */
@@ -288,11 +271,10 @@ acpi_ut_evaluate_numeric_object (
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
@@ -310,10 +292,7 @@ acpi_ut_evaluate_numeric_object (
******************************************************************************/
static void
-acpi_ut_copy_id_string (
- char *destination,
- char *source,
- acpi_size max_length)
+acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length)
{
/*
@@ -328,10 +307,9 @@ acpi_ut_copy_id_string (
/* Do the actual copy */
- ACPI_STRNCPY (destination, source, max_length);
+ ACPI_STRNCPY(destination, source, max_length);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
@@ -349,42 +327,39 @@ acpi_ut_copy_id_string (
******************************************************************************/
acpi_status
-acpi_ut_execute_HID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *hid)
+acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *hid)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ut_execute_HID");
+ ACPI_FUNCTION_TRACE("ut_execute_HID");
-
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__HID,
- ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Convert the Numeric HID to string */
- acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value);
- }
- else {
+ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
+ hid->value);
+ } else {
/* Copy the String HID from the returned object */
- acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer,
- sizeof (hid->value));
+ acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer,
+ sizeof(hid->value));
}
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_translate_one_cid
@@ -403,18 +378,17 @@ acpi_ut_execute_HID (
******************************************************************************/
static acpi_status
-acpi_ut_translate_one_cid (
- union acpi_operand_object *obj_desc,
- struct acpi_compatible_id *one_cid)
+acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
+ struct acpi_compatible_id *one_cid)
{
-
- switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
/* Convert the Numeric CID to string */
- acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value);
+ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
+ one_cid->value);
return (AE_OK);
case ACPI_TYPE_STRING:
@@ -425,8 +399,8 @@ acpi_ut_translate_one_cid (
/* Copy the String CID from the returned object */
- acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer,
- ACPI_MAX_CID_LENGTH);
+ acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer,
+ ACPI_MAX_CID_LENGTH);
return (AE_OK);
default:
@@ -435,7 +409,6 @@ acpi_ut_translate_one_cid (
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
@@ -453,45 +426,42 @@ acpi_ut_translate_one_cid (
******************************************************************************/
acpi_status
-acpi_ut_execute_CID (
- struct acpi_namespace_node *device_node,
- struct acpi_compatible_id_list **return_cid_list)
+acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
+ struct acpi_compatible_id_list ** return_cid_list)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u32 count;
- u32 size;
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u32 count;
+ u32 size;
struct acpi_compatible_id_list *cid_list;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_CID");
+ acpi_native_uint i;
+ ACPI_FUNCTION_TRACE("ut_execute_CID");
/* Evaluate the _CID method for this device */
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID,
- ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
- &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
+ | ACPI_BTYPE_PACKAGE, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Get the number of _CIDs returned */
count = 1;
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
}
/* Allocate a worst-case buffer for the _CIDs */
- size = (((count - 1) * sizeof (struct acpi_compatible_id)) +
- sizeof (struct acpi_compatible_id_list));
+ size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
+ sizeof(struct acpi_compatible_id_list));
- cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size);
+ cid_list = ACPI_MEM_CALLOCATE((acpi_size) size);
if (!cid_list) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Init CID list */
@@ -508,39 +478,38 @@ acpi_ut_execute_CID (
/* The _CID object can be either a single CID or a package (list) of CIDs */
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
/* Translate each package element */
for (i = 0; i < count; i++) {
- status = acpi_ut_translate_one_cid (obj_desc->package.elements[i],
- &cid_list->id[i]);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_translate_one_cid(obj_desc->package.
+ elements[i],
+ &cid_list->id[i]);
+ if (ACPI_FAILURE(status)) {
break;
}
}
- }
- else {
+ } else {
/* Only one CID, translate to a string */
- status = acpi_ut_translate_one_cid (obj_desc, cid_list->id);
+ status = acpi_ut_translate_one_cid(obj_desc, cid_list->id);
}
/* Cleanup on error */
- if (ACPI_FAILURE (status)) {
- ACPI_MEM_FREE (cid_list);
- }
- else {
+ if (ACPI_FAILURE(status)) {
+ ACPI_MEM_FREE(cid_list);
+ } else {
*return_cid_list = cid_list;
}
/* On exit, we must delete the _CID return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
@@ -558,42 +527,39 @@ acpi_ut_execute_CID (
******************************************************************************/
acpi_status
-acpi_ut_execute_UID (
- struct acpi_namespace_node *device_node,
- struct acpi_device_id *uid)
+acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
+ struct acpi_device_id *uid)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_UID");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ut_execute_UID");
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__UID,
- ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &obj_desc);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
+ ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
/* Convert the Numeric UID to string */
- acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value);
- }
- else {
+ acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
+ uid->value);
+ } else {
/* Copy the String UID from the returned object */
- acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer,
- sizeof (uid->value));
+ acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer,
+ sizeof(uid->value));
}
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_STA
@@ -611,30 +577,26 @@ acpi_ut_execute_UID (
******************************************************************************/
acpi_status
-acpi_ut_execute_STA (
- struct acpi_namespace_node *device_node,
- u32 *flags)
+acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
-
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ut_execute_STA");
+ ACPI_FUNCTION_TRACE("ut_execute_STA");
-
- status = acpi_ut_evaluate_object (device_node, METHOD_NAME__STA,
- ACPI_BTYPE_INTEGER, &obj_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
+ ACPI_BTYPE_INTEGER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
if (AE_NOT_FOUND == status) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "_STA on %4.4s was not found, assuming device is present\n",
- acpi_ut_get_node_name (device_node)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "_STA on %4.4s was not found, assuming device is present\n",
+ acpi_ut_get_node_name(device_node)));
*flags = 0x0F;
status = AE_OK;
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/* Extract the status flags */
@@ -643,11 +605,10 @@ acpi_ut_execute_STA (
/* On exit, we must delete the return object */
- acpi_ut_remove_reference (obj_desc);
- return_ACPI_STATUS (status);
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_Sxds
@@ -665,44 +626,45 @@ acpi_ut_execute_STA (
******************************************************************************/
acpi_status
-acpi_ut_execute_sxds (
- struct acpi_namespace_node *device_node,
- u8 *highest)
+acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
{
- union acpi_operand_object *obj_desc;
- acpi_status status;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ut_execute_Sxds");
for (i = 0; i < 4; i++) {
highest[i] = 0xFF;
- status = acpi_ut_evaluate_object (device_node,
- (char *) acpi_gbl_highest_dstate_names[i],
- ACPI_BTYPE_INTEGER, &obj_desc);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ut_evaluate_object(device_node,
+ (char *)
+ acpi_gbl_highest_dstate_names
+ [i], ACPI_BTYPE_INTEGER,
+ &obj_desc);
+ if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s on Device %4.4s, %s\n",
- (char *) acpi_gbl_highest_dstate_names[i],
- acpi_ut_get_node_name (device_node),
- acpi_format_exception (status)));
-
- return_ACPI_STATUS (status);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%s on Device %4.4s, %s\n",
+ (char *)
+ acpi_gbl_highest_dstate_names
+ [i],
+ acpi_ut_get_node_name
+ (device_node),
+ acpi_format_exception
+ (status)));
+
+ return_ACPI_STATUS(status);
}
- }
- else {
+ } else {
/* Extract the Dstate value */
highest[i] = (u8) obj_desc->integer.value;
/* Delete the return object */
- acpi_ut_remove_reference (obj_desc);
+ acpi_ut_remove_reference(obj_desc);
}
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index 4146019b543f..399e64b51886 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -48,8 +48,7 @@
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utglobal")
-
+ACPI_MODULE_NAME("utglobal")
/*******************************************************************************
*
@@ -63,17 +62,12 @@
* DESCRIPTION: This function translates an ACPI exception into an ASCII string.
*
******************************************************************************/
-
-const char *
-acpi_format_exception (
- acpi_status status)
+const char *acpi_format_exception(acpi_status status)
{
- acpi_status sub_status;
- const char *exception = NULL;
-
-
- ACPI_FUNCTION_NAME ("format_exception");
+ acpi_status sub_status;
+ const char *exception = NULL;
+ ACPI_FUNCTION_NAME("format_exception");
sub_status = (status & ~AE_CODE_MASK);
@@ -81,35 +75,39 @@ acpi_format_exception (
case AE_CODE_ENVIRONMENTAL:
if (sub_status <= AE_CODE_ENV_MAX) {
- exception = acpi_gbl_exception_names_env [sub_status];
+ exception = acpi_gbl_exception_names_env[sub_status];
}
break;
case AE_CODE_PROGRAMMER:
if (sub_status <= AE_CODE_PGM_MAX) {
- exception = acpi_gbl_exception_names_pgm [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_pgm[sub_status - 1];
}
break;
case AE_CODE_ACPI_TABLES:
if (sub_status <= AE_CODE_TBL_MAX) {
- exception = acpi_gbl_exception_names_tbl [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_tbl[sub_status - 1];
}
break;
case AE_CODE_AML:
if (sub_status <= AE_CODE_AML_MAX) {
- exception = acpi_gbl_exception_names_aml [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_aml[sub_status - 1];
}
break;
case AE_CODE_CONTROL:
if (sub_status <= AE_CODE_CTRL_MAX) {
- exception = acpi_gbl_exception_names_ctrl [sub_status -1];
+ exception =
+ acpi_gbl_exception_names_ctrl[sub_status - 1];
}
break;
@@ -120,16 +118,15 @@ acpi_format_exception (
if (!exception) {
/* Exception code was not recognized */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unknown exception code: 0x%8.8X\n", status));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unknown exception code: 0x%8.8X\n", status));
- return ((const char *) "UNKNOWN_STATUS_CODE");
+ return ((const char *)"UNKNOWN_STATUS_CODE");
}
- return ((const char *) exception);
+ return ((const char *)exception);
}
-
/*******************************************************************************
*
* Static global variable initialization.
@@ -142,34 +139,32 @@ acpi_format_exception (
*/
/* Debug switch - level and trace mask */
-u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
+u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
EXPORT_SYMBOL(acpi_dbg_level);
/* Debug switch - layer (component) mask */
-u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
+u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
EXPORT_SYMBOL(acpi_dbg_layer);
-u32 acpi_gbl_nesting_level = 0;
-
+u32 acpi_gbl_nesting_level = 0;
/* Debugger globals */
-u8 acpi_gbl_db_terminate_threads = FALSE;
-u8 acpi_gbl_abort_method = FALSE;
-u8 acpi_gbl_method_executing = FALSE;
+u8 acpi_gbl_db_terminate_threads = FALSE;
+u8 acpi_gbl_abort_method = FALSE;
+u8 acpi_gbl_method_executing = FALSE;
/* System flags */
-u32 acpi_gbl_startup_flags = 0;
+u32 acpi_gbl_startup_flags = 0;
/* System starts uninitialized */
-u8 acpi_gbl_shutdown = TRUE;
+u8 acpi_gbl_shutdown = TRUE;
-const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
+const u8 acpi_gbl_decode_to8bit[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
-const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
-{
+const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S0_",
"\\_S1_",
"\\_S2_",
@@ -178,8 +173,7 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COU
"\\_S5_"
};
-const char *acpi_gbl_highest_dstate_names[4] =
-{
+const char *acpi_gbl_highest_dstate_names[4] = {
"_S1D",
"_S2D",
"_S3D",
@@ -190,8 +184,7 @@ const char *acpi_gbl_highest_dstate_names[4] =
* Strings supported by the _OSI predefined (internal) method.
* When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
*/
-const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
-{
+const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
/* Operating System Vendor Strings */
"Linux",
@@ -209,7 +202,6 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
"Extended Address Space Descriptor"
};
-
/*******************************************************************************
*
* Namespace globals
@@ -225,74 +217,70 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
* 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
* perform a Notify() operation on it.
*/
-const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
-{ {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_SB_", ACPI_TYPE_DEVICE, NULL},
- {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
- {"_TZ_", ACPI_TYPE_THERMAL, NULL},
- {"_REV", ACPI_TYPE_INTEGER, (char *) ACPI_CA_SUPPORT_LEVEL},
- {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
- {"_GL_", ACPI_TYPE_MUTEX, (char *) 1},
+const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
+ { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_SB_", ACPI_TYPE_DEVICE, NULL},
+{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
+{"_TZ_", ACPI_TYPE_THERMAL, NULL},
+{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
+{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
+{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
- {"_OSI", ACPI_TYPE_METHOD, (char *) 1},
+{"_OSI", ACPI_TYPE_METHOD, (char *)1},
#endif
/* Table terminator */
- {NULL, ACPI_TYPE_ANY, NULL}
+{NULL, ACPI_TYPE_ANY, NULL}
};
/*
* Properties of the ACPI Object Types, both internal and external.
* The table is indexed by values of acpi_object_type
*/
-const u8 acpi_gbl_ns_properties[] =
-{
- ACPI_NS_NORMAL, /* 00 Any */
- ACPI_NS_NORMAL, /* 01 Number */
- ACPI_NS_NORMAL, /* 02 String */
- ACPI_NS_NORMAL, /* 03 Buffer */
- ACPI_NS_NORMAL, /* 04 Package */
- ACPI_NS_NORMAL, /* 05 field_unit */
- ACPI_NS_NEWSCOPE, /* 06 Device */
- ACPI_NS_NORMAL, /* 07 Event */
- ACPI_NS_NEWSCOPE, /* 08 Method */
- ACPI_NS_NORMAL, /* 09 Mutex */
- ACPI_NS_NORMAL, /* 10 Region */
- ACPI_NS_NEWSCOPE, /* 11 Power */
- ACPI_NS_NEWSCOPE, /* 12 Processor */
- ACPI_NS_NEWSCOPE, /* 13 Thermal */
- ACPI_NS_NORMAL, /* 14 buffer_field */
- ACPI_NS_NORMAL, /* 15 ddb_handle */
- ACPI_NS_NORMAL, /* 16 Debug Object */
- ACPI_NS_NORMAL, /* 17 def_field */
- ACPI_NS_NORMAL, /* 18 bank_field */
- ACPI_NS_NORMAL, /* 19 index_field */
- ACPI_NS_NORMAL, /* 20 Reference */
- ACPI_NS_NORMAL, /* 21 Alias */
- ACPI_NS_NORMAL, /* 22 method_alias */
- ACPI_NS_NORMAL, /* 23 Notify */
- ACPI_NS_NORMAL, /* 24 Address Handler */
- ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
- ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
- ACPI_NS_NEWSCOPE, /* 27 Scope */
- ACPI_NS_NORMAL, /* 28 Extra */
- ACPI_NS_NORMAL, /* 29 Data */
- ACPI_NS_NORMAL /* 30 Invalid */
+const u8 acpi_gbl_ns_properties[] = {
+ ACPI_NS_NORMAL, /* 00 Any */
+ ACPI_NS_NORMAL, /* 01 Number */
+ ACPI_NS_NORMAL, /* 02 String */
+ ACPI_NS_NORMAL, /* 03 Buffer */
+ ACPI_NS_NORMAL, /* 04 Package */
+ ACPI_NS_NORMAL, /* 05 field_unit */
+ ACPI_NS_NEWSCOPE, /* 06 Device */
+ ACPI_NS_NORMAL, /* 07 Event */
+ ACPI_NS_NEWSCOPE, /* 08 Method */
+ ACPI_NS_NORMAL, /* 09 Mutex */
+ ACPI_NS_NORMAL, /* 10 Region */
+ ACPI_NS_NEWSCOPE, /* 11 Power */
+ ACPI_NS_NEWSCOPE, /* 12 Processor */
+ ACPI_NS_NEWSCOPE, /* 13 Thermal */
+ ACPI_NS_NORMAL, /* 14 buffer_field */
+ ACPI_NS_NORMAL, /* 15 ddb_handle */
+ ACPI_NS_NORMAL, /* 16 Debug Object */
+ ACPI_NS_NORMAL, /* 17 def_field */
+ ACPI_NS_NORMAL, /* 18 bank_field */
+ ACPI_NS_NORMAL, /* 19 index_field */
+ ACPI_NS_NORMAL, /* 20 Reference */
+ ACPI_NS_NORMAL, /* 21 Alias */
+ ACPI_NS_NORMAL, /* 22 method_alias */
+ ACPI_NS_NORMAL, /* 23 Notify */
+ ACPI_NS_NORMAL, /* 24 Address Handler */
+ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
+ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
+ ACPI_NS_NEWSCOPE, /* 27 Scope */
+ ACPI_NS_NORMAL, /* 28 Extra */
+ ACPI_NS_NORMAL, /* 29 Data */
+ ACPI_NS_NORMAL /* 30 Invalid */
};
-
/* Hex to ASCII conversion table */
-static const char acpi_gbl_hex_to_ascii[] =
-{
- '0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'
+static const char acpi_gbl_hex_to_ascii[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_hex_to_ascii_char
@@ -307,16 +295,12 @@ static const char acpi_gbl_hex_to_ascii[] =
*
******************************************************************************/
-char
-acpi_ut_hex_to_ascii_char (
- acpi_integer integer,
- u32 position)
+char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position)
{
return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
}
-
/*******************************************************************************
*
* Table name globals
@@ -330,67 +314,139 @@ acpi_ut_hex_to_ascii_char (
*
******************************************************************************/
-struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
+struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
-struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] =
-{
+struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = {
/*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
- /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof (RSDP_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
- /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE},
- /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE},
- /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE},
- /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
- /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
- /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof (RSDT_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE},
+ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1,
+ ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
+ ,
+ /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *)&acpi_gbl_DSDT,
+ sizeof(DSDT_SIG) - 1,
+ ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *)&acpi_gbl_FADT,
+ sizeof(FADT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}
+ ,
+ /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *)&acpi_gbl_FACS,
+ sizeof(FACS_SIG) - 1,
+ ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE}
+ ,
+ /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof(PSDT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof(SSDT_SIG) - 1,
+ ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
+ ACPI_TABLE_EXECUTABLE}
+ ,
+ /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof(RSDT_SIG) - 1,
+ ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
+ ,
};
-
/******************************************************************************
*
* Event and Hardware globals
*
******************************************************************************/
-struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] =
-{
+struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = {
/* Name Parent Register Register Bit Position Register Bit Mask */
- /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_TIMER_STATUS, ACPI_BITMASK_TIMER_STATUS},
- /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_BUS_MASTER_STATUS, ACPI_BITMASK_BUS_MASTER_STATUS},
- /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_STATUS},
- /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_STATUS},
- /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS},
- /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS},
- /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS},
- /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS},
-
- /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE},
- /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
- /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_ENABLE},
- /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
- /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE},
- /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
- /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
-
- /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE},
- /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD},
- /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE},
- /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
- /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE_X, ACPI_BITMASK_SLEEP_TYPE_X},
- /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE},
-
- /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, ACPI_BITPOSITION_ARB_DISABLE, ACPI_BITMASK_ARB_DISABLE}
+ /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_TIMER_STATUS,
+ ACPI_BITMASK_TIMER_STATUS},
+ /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_BUS_MASTER_STATUS,
+ ACPI_BITMASK_BUS_MASTER_STATUS},
+ /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_GLOBAL_LOCK_STATUS,
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS},
+ /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_POWER_BUTTON_STATUS,
+ ACPI_BITMASK_POWER_BUTTON_STATUS},
+ /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_SLEEP_BUTTON_STATUS,
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS},
+ /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_RT_CLOCK_STATUS,
+ ACPI_BITMASK_RT_CLOCK_STATUS},
+ /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_WAKE_STATUS,
+ ACPI_BITMASK_WAKE_STATUS},
+ /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITPOSITION_PCIEXP_WAKE_STATUS,
+ ACPI_BITMASK_PCIEXP_WAKE_STATUS},
+
+ /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_TIMER_ENABLE,
+ ACPI_BITMASK_TIMER_ENABLE},
+ /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE,
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
+ /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_POWER_BUTTON_ENABLE,
+ ACPI_BITMASK_POWER_BUTTON_ENABLE},
+ /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE,
+ ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
+ /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_RT_CLOCK_ENABLE,
+ ACPI_BITMASK_RT_CLOCK_ENABLE},
+ /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
+ /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE,
+ ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE,
+ ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
+
+ /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SCI_ENABLE,
+ ACPI_BITMASK_SCI_ENABLE},
+ /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_BUS_MASTER_RLD,
+ ACPI_BITMASK_BUS_MASTER_RLD},
+ /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE,
+ ACPI_BITMASK_GLOBAL_LOCK_RELEASE},
+ /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_TYPE_X,
+ ACPI_BITMASK_SLEEP_TYPE_X},
+ /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_TYPE_X,
+ ACPI_BITMASK_SLEEP_TYPE_X},
+ /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL,
+ ACPI_BITPOSITION_SLEEP_ENABLE,
+ ACPI_BITMASK_SLEEP_ENABLE},
+
+ /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL,
+ ACPI_BITPOSITION_ARB_DISABLE,
+ ACPI_BITMASK_ARB_DISABLE}
};
-
-struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
-{
- /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, ACPI_BITREG_TIMER_ENABLE, ACPI_BITMASK_TIMER_STATUS, ACPI_BITMASK_TIMER_ENABLE},
- /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
- /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE},
- /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
- /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE},
+struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = {
+ /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS,
+ ACPI_BITREG_TIMER_ENABLE,
+ ACPI_BITMASK_TIMER_STATUS,
+ ACPI_BITMASK_TIMER_ENABLE},
+ /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS,
+ ACPI_BITREG_GLOBAL_LOCK_ENABLE,
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS,
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
+ /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS,
+ ACPI_BITREG_POWER_BUTTON_ENABLE,
+ ACPI_BITMASK_POWER_BUTTON_STATUS,
+ ACPI_BITMASK_POWER_BUTTON_ENABLE},
+ /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS,
+ ACPI_BITREG_SLEEP_BUTTON_ENABLE,
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS,
+ ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
+ /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS,
+ ACPI_BITREG_RT_CLOCK_ENABLE,
+ ACPI_BITMASK_RT_CLOCK_STATUS,
+ ACPI_BITMASK_RT_CLOCK_ENABLE},
};
/*******************************************************************************
@@ -407,8 +463,7 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVE
/* Region type decoding */
-const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
-{
+const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
"SystemMemory",
"SystemIO",
@@ -421,25 +476,18 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] =
/*! [End] no source code translation !*/
};
-
-char *
-acpi_ut_get_region_name (
- u8 space_id)
+char *acpi_ut_get_region_name(u8 space_id)
{
- if (space_id >= ACPI_USER_REGION_BEGIN)
- {
+ if (space_id >= ACPI_USER_REGION_BEGIN) {
return ("user_defined_region");
- }
- else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
- {
+ } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
return ("invalid_space_id");
}
- return ((char *) acpi_gbl_region_types[space_id]);
+ return ((char *)acpi_gbl_region_types[space_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_event_name
@@ -454,8 +502,7 @@ acpi_ut_get_region_name (
/* Event type decoding */
-static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] =
-{
+static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
"PM_Timer",
"global_lock",
"power_button",
@@ -463,21 +510,16 @@ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] =
"real_time_clock",
};
-
-char *
-acpi_ut_get_event_name (
- u32 event_id)
+char *acpi_ut_get_event_name(u32 event_id)
{
- if (event_id > ACPI_EVENT_MAX)
- {
+ if (event_id > ACPI_EVENT_MAX) {
return ("invalid_event_iD");
}
- return ((char *) acpi_gbl_event_types[event_id]);
+ return ((char *)acpi_gbl_event_types[event_id]);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_type_name
@@ -498,12 +540,11 @@ acpi_ut_get_event_name (
* when stored in a table it really means that we have thus far seen no
* evidence to indicate what type is actually going to be stored for this entry.
*/
-static const char acpi_gbl_bad_type[] = "UNDEFINED";
+static const char acpi_gbl_bad_type[] = "UNDEFINED";
/* Printable names of the ACPI object types */
-static const char *acpi_gbl_ns_type_names[] =
-{
+static const char *acpi_gbl_ns_type_names[] = {
/* 00 */ "Untyped",
/* 01 */ "Integer",
/* 02 */ "String",
@@ -537,35 +578,26 @@ static const char *acpi_gbl_ns_type_names[] =
/* 30 */ "Invalid"
};
-
-char *
-acpi_ut_get_type_name (
- acpi_object_type type)
+char *acpi_ut_get_type_name(acpi_object_type type)
{
- if (type > ACPI_TYPE_INVALID)
- {
- return ((char *) acpi_gbl_bad_type);
+ if (type > ACPI_TYPE_INVALID) {
+ return ((char *)acpi_gbl_bad_type);
}
- return ((char *) acpi_gbl_ns_type_names[type]);
+ return ((char *)acpi_gbl_ns_type_names[type]);
}
-
-char *
-acpi_ut_get_object_type_name (
- union acpi_operand_object *obj_desc)
+char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
{
- if (!obj_desc)
- {
+ if (!obj_desc) {
return ("[NULL Object Descriptor]");
}
- return (acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)));
+ return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_node_name
@@ -578,39 +610,31 @@ acpi_ut_get_object_type_name (
*
******************************************************************************/
-char *
-acpi_ut_get_node_name (
- void *object)
+char *acpi_ut_get_node_name(void *object)
{
- struct acpi_namespace_node *node = (struct acpi_namespace_node *) object;
-
+ struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
- if (!object)
- {
+ if (!object) {
return ("NULL");
}
/* Check for Root node */
- if ((object == ACPI_ROOT_OBJECT) ||
- (object == acpi_gbl_root_node))
- {
+ if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) {
return ("\"\\\" ");
}
/* Descriptor must be a namespace node */
- if (node->descriptor != ACPI_DESC_TYPE_NAMED)
- {
+ if (node->descriptor != ACPI_DESC_TYPE_NAMED) {
return ("####");
}
/* Name must be a valid ACPI name */
- if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
- {
+ if (!acpi_ut_valid_acpi_name(*(u32 *) node->name.ascii)) {
return ("????");
}
@@ -619,7 +643,6 @@ acpi_ut_get_node_name (
return (node->name.ascii);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_descriptor_name
@@ -634,8 +657,7 @@ acpi_ut_get_node_name (
/* Printable names of object descriptor types */
-static const char *acpi_gbl_desc_type_names[] =
-{
+static const char *acpi_gbl_desc_type_names[] = {
/* 00 */ "Invalid",
/* 01 */ "Cached",
/* 02 */ "State-Generic",
@@ -654,27 +676,22 @@ static const char *acpi_gbl_desc_type_names[] =
/* 15 */ "Node"
};
-
-char *
-acpi_ut_get_descriptor_name (
- void *object)
+char *acpi_ut_get_descriptor_name(void *object)
{
- if (!object)
- {
+ if (!object) {
return ("NULL OBJECT");
}
- if (ACPI_GET_DESCRIPTOR_TYPE (object) > ACPI_DESC_TYPE_MAX)
- {
- return ((char *) acpi_gbl_bad_type);
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
+ return ((char *)acpi_gbl_bad_type);
}
- return ((char *) acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE (object)]);
+ return ((char *)
+ acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
}
-
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
/*
* Strings and procedures used for debug only
@@ -693,13 +710,10 @@ acpi_ut_get_descriptor_name (
*
******************************************************************************/
-char *
-acpi_ut_get_mutex_name (
- u32 mutex_id)
+char *acpi_ut_get_mutex_name(u32 mutex_id)
{
- if (mutex_id > MAX_MUTEX)
- {
+ if (mutex_id > MAX_MUTEX) {
return ("Invalid Mutex ID");
}
@@ -707,7 +721,6 @@ acpi_ut_get_mutex_name (
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_object_type
@@ -720,13 +733,10 @@ acpi_ut_get_mutex_name (
*
******************************************************************************/
-u8
-acpi_ut_valid_object_type (
- acpi_object_type type)
+u8 acpi_ut_valid_object_type(acpi_object_type type)
{
- if (type > ACPI_TYPE_LOCAL_MAX)
- {
+ if (type > ACPI_TYPE_LOCAL_MAX) {
/* Note: Assumes all TYPEs are contiguous (external/local) */
return (FALSE);
@@ -735,74 +745,6 @@ acpi_ut_valid_object_type (
return (TRUE);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_allocate_owner_id
- *
- * PARAMETERS: id_type - Type of ID (method or table)
- *
- * DESCRIPTION: Allocate a table or method owner id
- *
- * NOTE: this algorithm has a wraparound problem at 64_k method invocations, and
- * should be revisited (TBD)
- *
- ******************************************************************************/
-
-acpi_owner_id
-acpi_ut_allocate_owner_id (
- u32 id_type)
-{
- acpi_owner_id owner_id = 0xFFFF;
-
-
- ACPI_FUNCTION_TRACE ("ut_allocate_owner_id");
-
-
- if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES)))
- {
- return (0);
- }
-
- switch (id_type)
- {
- case ACPI_OWNER_TYPE_TABLE:
-
- owner_id = acpi_gbl_next_table_owner_id;
- acpi_gbl_next_table_owner_id++;
-
- /* Check for wraparound */
-
- if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID)
- {
- acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
- ACPI_REPORT_WARNING (("Table owner ID wraparound\n"));
- }
- break;
-
-
- case ACPI_OWNER_TYPE_METHOD:
-
- owner_id = acpi_gbl_next_method_owner_id;
- acpi_gbl_next_method_owner_id++;
-
- if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID)
- {
- /* Check for wraparound */
-
- acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
- }
- break;
-
- default:
- break;
- }
-
- (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
- return_VALUE (owner_id);
-}
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_init_globals
@@ -816,129 +758,96 @@ acpi_ut_allocate_owner_id (
*
******************************************************************************/
-void
-acpi_ut_init_globals (
- void)
+void acpi_ut_init_globals(void)
{
- u32 i;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("ut_init_globals");
- ACPI_FUNCTION_TRACE ("ut_init_globals");
+ /* Create all memory caches */
-
- /* Memory allocation and cache lists */
-
- ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_generic_state *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_parse_object *) NULL)->common.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].link_offset = (u16) ACPI_PTR_DIFF (&(((union acpi_operand_object *) NULL)->cache.next), NULL);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].link_offset = (u16) ACPI_PTR_DIFF (&(((struct acpi_walk_state *) NULL)->next), NULL);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].object_size = sizeof (struct acpi_namespace_node);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].object_size = sizeof (union acpi_generic_state);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (struct acpi_parse_obj_common);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (struct acpi_parse_obj_named);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].object_size = sizeof (union acpi_operand_object);
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].object_size = sizeof (struct acpi_walk_state);
-
- acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].max_cache_depth = ACPI_MAX_STATE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].max_cache_depth = ACPI_MAX_PARSE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].max_cache_depth = ACPI_MAX_EXTPARSE_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].max_cache_depth = ACPI_MAX_OBJECT_CACHE_DEPTH;
- acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].max_cache_depth = ACPI_MAX_WALK_CACHE_DEPTH;
-
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].list_name = "Global Memory Allocation");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].list_name = "Namespace Nodes");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].list_name = "State Object Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].list_name = "Parse Node Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].list_name = "Extended Parse Node Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].list_name = "Operand Object Cache");
- ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].list_name = "Tree Walk Node Cache");
+ status = acpi_ut_create_caches();
+ if (ACPI_FAILURE(status)) {
+ return;
+ }
/* ACPI table structure */
- for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++)
- {
- acpi_gbl_table_lists[i].next = NULL;
- acpi_gbl_table_lists[i].count = 0;
+ for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+ acpi_gbl_table_lists[i].next = NULL;
+ acpi_gbl_table_lists[i].count = 0;
}
/* Mutex locked flags */
- for (i = 0; i < NUM_MUTEX; i++)
- {
- acpi_gbl_mutex_info[i].mutex = NULL;
- acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[i].use_count = 0;
+ for (i = 0; i < NUM_MUTEX; i++) {
+ acpi_gbl_mutex_info[i].mutex = NULL;
+ acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+ acpi_gbl_mutex_info[i].use_count = 0;
}
/* GPE support */
- acpi_gbl_gpe_xrupt_list_head = NULL;
- acpi_gbl_gpe_fadt_blocks[0] = NULL;
- acpi_gbl_gpe_fadt_blocks[1] = NULL;
+ acpi_gbl_gpe_xrupt_list_head = NULL;
+ acpi_gbl_gpe_fadt_blocks[0] = NULL;
+ acpi_gbl_gpe_fadt_blocks[1] = NULL;
/* Global notify handlers */
- acpi_gbl_system_notify.handler = NULL;
- acpi_gbl_device_notify.handler = NULL;
- acpi_gbl_exception_handler = NULL;
- acpi_gbl_init_handler = NULL;
+ acpi_gbl_system_notify.handler = NULL;
+ acpi_gbl_device_notify.handler = NULL;
+ acpi_gbl_exception_handler = NULL;
+ acpi_gbl_init_handler = NULL;
/* Global "typed" ACPI table pointers */
- acpi_gbl_RSDP = NULL;
- acpi_gbl_XSDT = NULL;
- acpi_gbl_FACS = NULL;
- acpi_gbl_FADT = NULL;
- acpi_gbl_DSDT = NULL;
+ acpi_gbl_RSDP = NULL;
+ acpi_gbl_XSDT = NULL;
+ acpi_gbl_FACS = NULL;
+ acpi_gbl_FADT = NULL;
+ acpi_gbl_DSDT = NULL;
/* Global Lock support */
- acpi_gbl_global_lock_acquired = FALSE;
- acpi_gbl_global_lock_thread_count = 0;
- acpi_gbl_global_lock_handle = 0;
+ acpi_gbl_global_lock_acquired = FALSE;
+ acpi_gbl_global_lock_thread_count = 0;
+ acpi_gbl_global_lock_handle = 0;
/* Miscellaneous variables */
- acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
- acpi_gbl_rsdp_original_location = 0;
- acpi_gbl_cm_single_step = FALSE;
- acpi_gbl_db_terminate_threads = FALSE;
- acpi_gbl_shutdown = FALSE;
- acpi_gbl_ns_lookup_count = 0;
- acpi_gbl_ps_find_count = 0;
- acpi_gbl_acpi_hardware_present = TRUE;
- acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID;
- acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID;
- acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
- acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
+ acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
+ acpi_gbl_rsdp_original_location = 0;
+ acpi_gbl_cm_single_step = FALSE;
+ acpi_gbl_db_terminate_threads = FALSE;
+ acpi_gbl_shutdown = FALSE;
+ acpi_gbl_ns_lookup_count = 0;
+ acpi_gbl_ps_find_count = 0;
+ acpi_gbl_acpi_hardware_present = TRUE;
+ acpi_gbl_owner_id_mask = 0;
+ acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
+ acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
/* Hardware oriented */
- acpi_gbl_events_initialized = FALSE;
- acpi_gbl_system_awake_and_running = TRUE;
+ acpi_gbl_events_initialized = FALSE;
+ acpi_gbl_system_awake_and_running = TRUE;
/* Namespace */
- acpi_gbl_root_node = NULL;
+ acpi_gbl_root_node = NULL;
acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
- acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
- acpi_gbl_root_node_struct.child = NULL;
- acpi_gbl_root_node_struct.peer = NULL;
- acpi_gbl_root_node_struct.object = NULL;
- acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
-
+ acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
+ acpi_gbl_root_node_struct.child = NULL;
+ acpi_gbl_root_node_struct.peer = NULL;
+ acpi_gbl_root_node_struct.object = NULL;
+ acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST;
#ifdef ACPI_DEBUG_OUTPUT
- acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
+ acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX;
#endif
return_VOID;
}
-
-
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index 7f3713889ff0..9dde82b0beaf 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -41,25 +41,18 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utinit")
+ACPI_MODULE_NAME("utinit")
/* Local prototypes */
-
static void
-acpi_ut_fadt_register_error (
- char *register_name,
- u32 value,
- acpi_size offset);
-
-static void acpi_ut_terminate (
- void);
+acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset);
+static void acpi_ut_terminate(void);
/*******************************************************************************
*
@@ -76,18 +69,14 @@ static void acpi_ut_terminate (
******************************************************************************/
static void
-acpi_ut_fadt_register_error (
- char *register_name,
- u32 value,
- acpi_size offset)
+acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset)
{
- ACPI_REPORT_WARNING (
- ("Invalid FADT value %s=%X at offset %X FADT=%p\n",
- register_name, value, (u32) offset, acpi_gbl_FADT));
+ ACPI_REPORT_WARNING(("Invalid FADT value %s=%X at offset %X FADT=%p\n",
+ register_name, value, (u32) offset,
+ acpi_gbl_FADT));
}
-
/******************************************************************************
*
* FUNCTION: acpi_ut_validate_fadt
@@ -100,9 +89,7 @@ acpi_ut_fadt_register_error (
*
******************************************************************************/
-acpi_status
-acpi_ut_validate_fadt (
- void)
+acpi_status acpi_ut_validate_fadt(void)
{
/*
@@ -110,64 +97,66 @@ acpi_ut_validate_fadt (
* but don't abort on any problems, just display error
*/
if (acpi_gbl_FADT->pm1_evt_len < 4) {
- acpi_ut_fadt_register_error ("PM1_EVT_LEN",
- (u32) acpi_gbl_FADT->pm1_evt_len,
- ACPI_FADT_OFFSET (pm1_evt_len));
+ acpi_ut_fadt_register_error("PM1_EVT_LEN",
+ (u32) acpi_gbl_FADT->pm1_evt_len,
+ ACPI_FADT_OFFSET(pm1_evt_len));
}
if (!acpi_gbl_FADT->pm1_cnt_len) {
- acpi_ut_fadt_register_error ("PM1_CNT_LEN", 0,
- ACPI_FADT_OFFSET (pm1_cnt_len));
+ acpi_ut_fadt_register_error("PM1_CNT_LEN", 0,
+ ACPI_FADT_OFFSET(pm1_cnt_len));
}
if (!acpi_gbl_FADT->xpm1a_evt_blk.address) {
- acpi_ut_fadt_register_error ("X_PM1a_EVT_BLK", 0,
- ACPI_FADT_OFFSET (xpm1a_evt_blk.address));
+ acpi_ut_fadt_register_error("X_PM1a_EVT_BLK", 0,
+ ACPI_FADT_OFFSET(xpm1a_evt_blk.
+ address));
}
if (!acpi_gbl_FADT->xpm1a_cnt_blk.address) {
- acpi_ut_fadt_register_error ("X_PM1a_CNT_BLK", 0,
- ACPI_FADT_OFFSET (xpm1a_cnt_blk.address));
+ acpi_ut_fadt_register_error("X_PM1a_CNT_BLK", 0,
+ ACPI_FADT_OFFSET(xpm1a_cnt_blk.
+ address));
}
if (!acpi_gbl_FADT->xpm_tmr_blk.address) {
- acpi_ut_fadt_register_error ("X_PM_TMR_BLK", 0,
- ACPI_FADT_OFFSET (xpm_tmr_blk.address));
+ acpi_ut_fadt_register_error("X_PM_TMR_BLK", 0,
+ ACPI_FADT_OFFSET(xpm_tmr_blk.
+ address));
}
if ((acpi_gbl_FADT->xpm2_cnt_blk.address &&
- !acpi_gbl_FADT->pm2_cnt_len)) {
- acpi_ut_fadt_register_error ("PM2_CNT_LEN",
- (u32) acpi_gbl_FADT->pm2_cnt_len,
- ACPI_FADT_OFFSET (pm2_cnt_len));
+ !acpi_gbl_FADT->pm2_cnt_len)) {
+ acpi_ut_fadt_register_error("PM2_CNT_LEN",
+ (u32) acpi_gbl_FADT->pm2_cnt_len,
+ ACPI_FADT_OFFSET(pm2_cnt_len));
}
if (acpi_gbl_FADT->pm_tm_len < 4) {
- acpi_ut_fadt_register_error ("PM_TM_LEN",
- (u32) acpi_gbl_FADT->pm_tm_len,
- ACPI_FADT_OFFSET (pm_tm_len));
+ acpi_ut_fadt_register_error("PM_TM_LEN",
+ (u32) acpi_gbl_FADT->pm_tm_len,
+ ACPI_FADT_OFFSET(pm_tm_len));
}
/* Length of GPE blocks must be a multiple of 2 */
if (acpi_gbl_FADT->xgpe0_blk.address &&
- (acpi_gbl_FADT->gpe0_blk_len & 1)) {
- acpi_ut_fadt_register_error ("(x)GPE0_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe0_blk_len,
- ACPI_FADT_OFFSET (gpe0_blk_len));
+ (acpi_gbl_FADT->gpe0_blk_len & 1)) {
+ acpi_ut_fadt_register_error("(x)GPE0_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe0_blk_len,
+ ACPI_FADT_OFFSET(gpe0_blk_len));
}
if (acpi_gbl_FADT->xgpe1_blk.address &&
- (acpi_gbl_FADT->gpe1_blk_len & 1)) {
- acpi_ut_fadt_register_error ("(x)GPE1_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe1_blk_len,
- ACPI_FADT_OFFSET (gpe1_blk_len));
+ (acpi_gbl_FADT->gpe1_blk_len & 1)) {
+ acpi_ut_fadt_register_error("(x)GPE1_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe1_blk_len,
+ ACPI_FADT_OFFSET(gpe1_blk_len));
}
return (AE_OK);
}
-
/******************************************************************************
*
* FUNCTION: acpi_ut_terminate
@@ -180,18 +169,14 @@ acpi_ut_validate_fadt (
*
******************************************************************************/
-static void
-acpi_ut_terminate (
- void)
+static void acpi_ut_terminate(void)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_block_info *next_gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
-
-
- ACPI_FUNCTION_TRACE ("ut_terminate");
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_block_info *next_gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
+ ACPI_FUNCTION_TRACE("ut_terminate");
/* Free global tables, etc. */
/* Free global GPE blocks and related info structures */
@@ -201,21 +186,20 @@ acpi_ut_terminate (
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
next_gpe_block = gpe_block->next;
- ACPI_MEM_FREE (gpe_block->event_info);
- ACPI_MEM_FREE (gpe_block->register_info);
- ACPI_MEM_FREE (gpe_block);
+ ACPI_MEM_FREE(gpe_block->event_info);
+ ACPI_MEM_FREE(gpe_block->register_info);
+ ACPI_MEM_FREE(gpe_block);
gpe_block = next_gpe_block;
}
next_gpe_xrupt_info = gpe_xrupt_info->next;
- ACPI_MEM_FREE (gpe_xrupt_info);
+ ACPI_MEM_FREE(gpe_xrupt_info);
gpe_xrupt_info = next_gpe_xrupt_info;
}
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_subsystem_shutdown
@@ -229,50 +213,45 @@ acpi_ut_terminate (
*
******************************************************************************/
-void
-acpi_ut_subsystem_shutdown (
- void)
+void acpi_ut_subsystem_shutdown(void)
{
- ACPI_FUNCTION_TRACE ("ut_subsystem_shutdown");
+ ACPI_FUNCTION_TRACE("ut_subsystem_shutdown");
/* Just exit if subsystem is already shutdown */
if (acpi_gbl_shutdown) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "ACPI Subsystem is already terminated\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "ACPI Subsystem is already terminated\n"));
return_VOID;
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Shutting down ACPI Subsystem...\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n"));
/* Close the acpi_event Handling */
- acpi_ev_terminate ();
+ acpi_ev_terminate();
/* Close the Namespace */
- acpi_ns_terminate ();
+ acpi_ns_terminate();
/* Close the globals */
- acpi_ut_terminate ();
+ acpi_ut_terminate();
/* Purge the local caches */
- (void) acpi_purge_cached_objects ();
+ (void)acpi_ut_delete_caches();
/* Debug only - display leftover memory allocation, if any */
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- acpi_ut_dump_allocations (ACPI_UINT32_MAX, NULL);
+ acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
#endif
return_VOID;
}
-
-
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
index 0d527c91543c..68a0a6f94129 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -41,19 +41,16 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utmath")
+ACPI_MODULE_NAME("utmath")
/*
* Support for double-precision integer divide. This code is included here
* in order to support kernel environments where the double-precision math
* library is not available.
*/
-
#ifndef ACPI_USE_NATIVE_DIVIDE
/*******************************************************************************
*
@@ -71,27 +68,22 @@
* 32-bit remainder.
*
******************************************************************************/
-
acpi_status
-acpi_ut_short_divide (
- acpi_integer dividend,
- u32 divisor,
- acpi_integer *out_quotient,
- u32 *out_remainder)
+acpi_ut_short_divide(acpi_integer dividend,
+ u32 divisor,
+ acpi_integer * out_quotient, u32 * out_remainder)
{
- union uint64_overlay dividend_ovl;
- union uint64_overlay quotient;
- u32 remainder32;
-
-
- ACPI_FUNCTION_TRACE ("ut_short_divide");
+ union uint64_overlay dividend_ovl;
+ union uint64_overlay quotient;
+ u32 remainder32;
+ ACPI_FUNCTION_TRACE("ut_short_divide");
/* Always check for a zero divisor */
if (divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
dividend_ovl.full = dividend;
@@ -100,9 +92,9 @@ acpi_ut_short_divide (
* The quotient is 64 bits, the remainder is always 32 bits,
* and is generated by the second divide.
*/
- ACPI_DIV_64_BY_32 (0, dividend_ovl.part.hi, divisor,
+ ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
quotient.part.hi, remainder32);
- ACPI_DIV_64_BY_32 (remainder32, dividend_ovl.part.lo, divisor,
+ ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
quotient.part.lo, remainder32);
/* Return only what was requested */
@@ -114,10 +106,9 @@ acpi_ut_short_divide (
*out_remainder = remainder32;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_divide
@@ -134,34 +125,30 @@ acpi_ut_short_divide (
******************************************************************************/
acpi_status
-acpi_ut_divide (
- acpi_integer in_dividend,
- acpi_integer in_divisor,
- acpi_integer *out_quotient,
- acpi_integer *out_remainder)
+acpi_ut_divide(acpi_integer in_dividend,
+ acpi_integer in_divisor,
+ acpi_integer * out_quotient, acpi_integer * out_remainder)
{
- union uint64_overlay dividend;
- union uint64_overlay divisor;
- union uint64_overlay quotient;
- union uint64_overlay remainder;
- union uint64_overlay normalized_dividend;
- union uint64_overlay normalized_divisor;
- u32 partial1;
- union uint64_overlay partial2;
- union uint64_overlay partial3;
-
-
- ACPI_FUNCTION_TRACE ("ut_divide");
-
+ union uint64_overlay dividend;
+ union uint64_overlay divisor;
+ union uint64_overlay quotient;
+ union uint64_overlay remainder;
+ union uint64_overlay normalized_dividend;
+ union uint64_overlay normalized_divisor;
+ u32 partial1;
+ union uint64_overlay partial2;
+ union uint64_overlay partial3;
+
+ ACPI_FUNCTION_TRACE("ut_divide");
/* Always check for a zero divisor */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
- divisor.full = in_divisor;
+ divisor.full = in_divisor;
dividend.full = in_dividend;
if (divisor.part.hi == 0) {
/*
@@ -174,9 +161,9 @@ acpi_ut_divide (
* The quotient is 64 bits, the remainder is always 32 bits,
* and is generated by the second divide.
*/
- ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor.part.lo,
+ ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
quotient.part.hi, partial1);
- ACPI_DIV_64_BY_32 (partial1, dividend.part.lo, divisor.part.lo,
+ ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
quotient.part.lo, remainder.part.lo);
}
@@ -185,23 +172,23 @@ acpi_ut_divide (
* 2) The general case where the divisor is a full 64 bits
* is more difficult
*/
- quotient.part.hi = 0;
+ quotient.part.hi = 0;
normalized_dividend = dividend;
normalized_divisor = divisor;
/* Normalize the operands (shift until the divisor is < 32 bits) */
do {
- ACPI_SHIFT_RIGHT_64 (normalized_divisor.part.hi,
- normalized_divisor.part.lo);
- ACPI_SHIFT_RIGHT_64 (normalized_dividend.part.hi,
- normalized_dividend.part.lo);
+ ACPI_SHIFT_RIGHT_64(normalized_divisor.part.hi,
+ normalized_divisor.part.lo);
+ ACPI_SHIFT_RIGHT_64(normalized_dividend.part.hi,
+ normalized_dividend.part.lo);
} while (normalized_divisor.part.hi != 0);
/* Partial divide */
- ACPI_DIV_64_BY_32 (normalized_dividend.part.hi,
+ ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
normalized_dividend.part.lo,
normalized_divisor.part.lo,
quotient.part.lo, partial1);
@@ -210,8 +197,9 @@ acpi_ut_divide (
* The quotient is always 32 bits, and simply requires adjustment.
* The 64-bit remainder must be generated.
*/
- partial1 = quotient.part.lo * divisor.part.hi;
- partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo;
+ partial1 = quotient.part.lo * divisor.part.hi;
+ partial2.full =
+ (acpi_integer) quotient.part.lo * divisor.part.lo;
partial3.full = (acpi_integer) partial2.part.hi + partial1;
remainder.part.hi = partial3.part.lo;
@@ -224,16 +212,15 @@ acpi_ut_divide (
quotient.part.lo--;
remainder.full -= divisor.full;
}
- }
- else {
+ } else {
quotient.part.lo--;
remainder.full -= divisor.full;
}
}
- remainder.full = remainder.full - dividend.full;
- remainder.part.hi = (u32) -((s32) remainder.part.hi);
- remainder.part.lo = (u32) -((s32) remainder.part.lo);
+ remainder.full = remainder.full - dividend.full;
+ remainder.part.hi = (u32) - ((s32) remainder.part.hi);
+ remainder.part.lo = (u32) - ((s32) remainder.part.lo);
if (remainder.part.lo) {
remainder.part.hi--;
@@ -250,11 +237,10 @@ acpi_ut_divide (
*out_remainder = remainder.full;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#else
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_short_divide, acpi_ut_divide
@@ -269,23 +255,19 @@ acpi_ut_divide (
* perform the divide.
*
******************************************************************************/
-
acpi_status
-acpi_ut_short_divide (
- acpi_integer in_dividend,
- u32 divisor,
- acpi_integer *out_quotient,
- u32 *out_remainder)
+acpi_ut_short_divide(acpi_integer in_dividend,
+ u32 divisor,
+ acpi_integer * out_quotient, u32 * out_remainder)
{
- ACPI_FUNCTION_TRACE ("ut_short_divide");
-
+ ACPI_FUNCTION_TRACE("ut_short_divide");
/* Always check for a zero divisor */
if (divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_short_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
/* Return only what was requested */
@@ -297,27 +279,23 @@ acpi_ut_short_divide (
*out_remainder = (u32) in_dividend % divisor;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
acpi_status
-acpi_ut_divide (
- acpi_integer in_dividend,
- acpi_integer in_divisor,
- acpi_integer *out_quotient,
- acpi_integer *out_remainder)
+acpi_ut_divide(acpi_integer in_dividend,
+ acpi_integer in_divisor,
+ acpi_integer * out_quotient, acpi_integer * out_remainder)
{
- ACPI_FUNCTION_TRACE ("ut_divide");
-
+ ACPI_FUNCTION_TRACE("ut_divide");
/* Always check for a zero divisor */
if (in_divisor == 0) {
- ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n"));
- return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO);
+ ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n"));
+ return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO);
}
-
/* Return only what was requested */
if (out_quotient) {
@@ -327,9 +305,7 @@ acpi_ut_divide (
*out_remainder = in_dividend % in_divisor;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
#endif
-
-
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index f6de4ed3d527..0c5abc536c7a 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -41,24 +41,130 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utmisc")
+ACPI_MODULE_NAME("utmisc")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_allocate_owner_id
+ *
+ * PARAMETERS: owner_id - Where the new owner ID is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
+ * track objects created by the table or method, to be deleted
+ * when the method exits or the table is unloaded.
+ *
+ ******************************************************************************/
+acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
+{
+ acpi_native_uint i;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
+
+ /* Guard against multiple allocations of ID to the same location */
+
+ if (*owner_id) {
+ ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n",
+ *owner_id));
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ }
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
-/* Local prototypes */
+ /* Find a free owner ID */
-static acpi_status
-acpi_ut_create_mutex (
- acpi_mutex_handle mutex_id);
+ for (i = 0; i < 32; i++) {
+ if (!(acpi_gbl_owner_id_mask & (1 << i))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
+ "Current owner_id mask: %8.8X New ID: %2.2X\n",
+ acpi_gbl_owner_id_mask,
+ (unsigned int)(i + 1)));
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id);
+ acpi_gbl_owner_id_mask |= (1 << i);
+ *owner_id = (acpi_owner_id) (i + 1);
+ goto exit;
+ }
+ }
+ /*
+ * If we are here, all owner_ids have been allocated. This probably should
+ * not happen since the IDs are reused after deallocation. The IDs are
+ * allocated upon table load (one per table) and method execution, and
+ * they are released when a table is unloaded or a method completes
+ * execution.
+ */
+ *owner_id = 0;
+ status = AE_OWNER_ID_LIMIT;
+ ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
+
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_release_owner_id
+ *
+ * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD
+ *
+ * RETURN: None. No error is returned because we are either exiting a
+ * control method or unloading a table. Either way, we would
+ * ignore any error anyway.
+ *
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32
+ *
+ ******************************************************************************/
+
+void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
+{
+ acpi_owner_id owner_id = *owner_id_ptr;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
+
+ /* Always clear the input owner_id (zero is an invalid ID) */
+
+ *owner_id_ptr = 0;
+
+ /* Zero is not a valid owner_iD */
+
+ if ((owner_id == 0) || (owner_id > 32)) {
+ ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
+ return_VOID;
+ }
+
+ /* Mutex for the global ID mask */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
+ }
+
+ /* Normalize the ID to zero */
+
+ owner_id--;
+
+ /* Free the owner ID only if it is valid */
+
+ if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
+ acpi_gbl_owner_id_mask ^= (1 << owner_id);
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ return_VOID;
+}
/*******************************************************************************
*
@@ -66,7 +172,7 @@ acpi_ut_delete_mutex (
*
* PARAMETERS: src_string - The source string to convert
*
- * RETURN: Converted src_string (same as input pointer)
+ * RETURN: None
*
* DESCRIPTION: Convert string to uppercase
*
@@ -74,26 +180,25 @@ acpi_ut_delete_mutex (
*
******************************************************************************/
-char *
-acpi_ut_strupr (
- char *src_string)
+void acpi_ut_strupr(char *src_string)
{
- char *string;
-
+ char *string;
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
+ if (!src_string) {
+ return;
+ }
/* Walk entire string, uppercasing the letters */
for (string = src_string; *string; string++) {
- *string = (char) ACPI_TOUPPER (*string);
+ *string = (char)ACPI_TOUPPER(*string);
}
- return (src_string);
+ return;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_print_string
@@ -108,85 +213,77 @@ acpi_ut_strupr (
*
******************************************************************************/
-void
-acpi_ut_print_string (
- char *string,
- u8 max_length)
+void acpi_ut_print_string(char *string, u8 max_length)
{
- u32 i;
-
+ u32 i;
if (!string) {
- acpi_os_printf ("<\"NULL STRING PTR\">");
+ acpi_os_printf("<\"NULL STRING PTR\">");
return;
}
- acpi_os_printf ("\"");
+ acpi_os_printf("\"");
for (i = 0; string[i] && (i < max_length); i++) {
/* Escape sequences */
switch (string[i]) {
case 0x07:
- acpi_os_printf ("\\a"); /* BELL */
+ acpi_os_printf("\\a"); /* BELL */
break;
case 0x08:
- acpi_os_printf ("\\b"); /* BACKSPACE */
+ acpi_os_printf("\\b"); /* BACKSPACE */
break;
case 0x0C:
- acpi_os_printf ("\\f"); /* FORMFEED */
+ acpi_os_printf("\\f"); /* FORMFEED */
break;
case 0x0A:
- acpi_os_printf ("\\n"); /* LINEFEED */
+ acpi_os_printf("\\n"); /* LINEFEED */
break;
case 0x0D:
- acpi_os_printf ("\\r"); /* CARRIAGE RETURN*/
+ acpi_os_printf("\\r"); /* CARRIAGE RETURN */
break;
case 0x09:
- acpi_os_printf ("\\t"); /* HORIZONTAL TAB */
+ acpi_os_printf("\\t"); /* HORIZONTAL TAB */
break;
case 0x0B:
- acpi_os_printf ("\\v"); /* VERTICAL TAB */
+ acpi_os_printf("\\v"); /* VERTICAL TAB */
break;
- case '\'': /* Single Quote */
- case '\"': /* Double Quote */
- case '\\': /* Backslash */
- acpi_os_printf ("\\%c", (int) string[i]);
+ case '\'': /* Single Quote */
+ case '\"': /* Double Quote */
+ case '\\': /* Backslash */
+ acpi_os_printf("\\%c", (int)string[i]);
break;
default:
/* Check for printable character or hex escape */
- if (ACPI_IS_PRINT (string[i]))
- {
+ if (ACPI_IS_PRINT(string[i])) {
/* This is a normal character */
- acpi_os_printf ("%c", (int) string[i]);
- }
- else
- {
+ acpi_os_printf("%c", (int)string[i]);
+ } else {
/* All others will be Hex escapes */
- acpi_os_printf ("\\x%2.2X", (s32) string[i]);
+ acpi_os_printf("\\x%2.2X", (s32) string[i]);
}
break;
}
}
- acpi_os_printf ("\"");
+ acpi_os_printf("\"");
if (i == max_length && string[i]) {
- acpi_os_printf ("...");
+ acpi_os_printf("...");
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_dword_byte_swap
@@ -199,22 +296,18 @@ acpi_ut_print_string (
*
******************************************************************************/
-u32
-acpi_ut_dword_byte_swap (
- u32 value)
+u32 acpi_ut_dword_byte_swap(u32 value)
{
union {
- u32 value;
- u8 bytes[4];
+ u32 value;
+ u8 bytes[4];
} out;
union {
- u32 value;
- u8 bytes[4];
+ u32 value;
+ u8 bytes[4];
} in;
-
- ACPI_FUNCTION_ENTRY ();
-
+ ACPI_FUNCTION_ENTRY();
in.value = value;
@@ -226,7 +319,6 @@ acpi_ut_dword_byte_swap (
return (out.value);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_set_integer_width
@@ -242,24 +334,20 @@ acpi_ut_dword_byte_swap (
*
******************************************************************************/
-void
-acpi_ut_set_integer_width (
- u8 revision)
+void acpi_ut_set_integer_width(u8 revision)
{
if (revision <= 1) {
acpi_gbl_integer_bit_width = 32;
acpi_gbl_integer_nybble_width = 8;
acpi_gbl_integer_byte_width = 4;
- }
- else {
+ } else {
acpi_gbl_integer_bit_width = 64;
acpi_gbl_integer_nybble_width = 16;
acpi_gbl_integer_byte_width = 8;
}
}
-
#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
*
@@ -277,17 +365,14 @@ acpi_ut_set_integer_width (
******************************************************************************/
void
-acpi_ut_display_init_pathname (
- u8 type,
- struct acpi_namespace_node *obj_handle,
- char *path)
+acpi_ut_display_init_pathname(u8 type,
+ struct acpi_namespace_node *obj_handle,
+ char *path)
{
- acpi_status status;
- struct acpi_buffer buffer;
-
-
- ACPI_FUNCTION_ENTRY ();
+ acpi_status status;
+ struct acpi_buffer buffer;
+ ACPI_FUNCTION_ENTRY();
/* Only print the path if the appropriate debug level is enabled */
@@ -298,8 +383,8 @@ acpi_ut_display_init_pathname (
/* Get the full pathname to the node */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_ns_handle_to_pathname (obj_handle, &buffer);
- if (ACPI_FAILURE (status)) {
+ status = acpi_ns_handle_to_pathname(obj_handle, &buffer);
+ if (ACPI_FAILURE(status)) {
return;
}
@@ -307,31 +392,30 @@ acpi_ut_display_init_pathname (
switch (type) {
case ACPI_TYPE_METHOD:
- acpi_os_printf ("Executing ");
+ acpi_os_printf("Executing ");
break;
default:
- acpi_os_printf ("Initializing ");
+ acpi_os_printf("Initializing ");
break;
}
/* Print the object type and pathname */
- acpi_os_printf ("%-12s %s",
- acpi_ut_get_type_name (type), (char *) buffer.pointer);
+ acpi_os_printf("%-12s %s",
+ acpi_ut_get_type_name(type), (char *)buffer.pointer);
/* Extra path is used to append names like _STA, _INI, etc. */
if (path) {
- acpi_os_printf (".%s", path);
+ acpi_os_printf(".%s", path);
}
- acpi_os_printf ("\n");
+ acpi_os_printf("\n");
- ACPI_MEM_FREE (buffer.pointer);
+ ACPI_MEM_FREE(buffer.pointer);
}
#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_name
@@ -347,25 +431,21 @@ acpi_ut_display_init_pathname (
*
******************************************************************************/
-u8
-acpi_ut_valid_acpi_name (
- u32 name)
+u8 acpi_ut_valid_acpi_name(u32 name)
{
- char *name_ptr = (char *) &name;
- char character;
- acpi_native_uint i;
-
-
- ACPI_FUNCTION_ENTRY ();
+ char *name_ptr = (char *)&name;
+ char character;
+ acpi_native_uint i;
+ ACPI_FUNCTION_ENTRY();
for (i = 0; i < ACPI_NAME_SIZE; i++) {
character = *name_ptr;
name_ptr++;
if (!((character == '_') ||
- (character >= 'A' && character <= 'Z') ||
- (character >= '0' && character <= '9'))) {
+ (character >= 'A' && character <= 'Z') ||
+ (character >= '0' && character <= '9'))) {
return (FALSE);
}
}
@@ -373,7 +453,6 @@ acpi_ut_valid_acpi_name (
return (TRUE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_acpi_character
@@ -386,19 +465,16 @@ acpi_ut_valid_acpi_name (
*
******************************************************************************/
-u8
-acpi_ut_valid_acpi_character (
- char character)
+u8 acpi_ut_valid_acpi_character(char character)
{
- ACPI_FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY();
- return ((u8) ((character == '_') ||
- (character >= 'A' && character <= 'Z') ||
- (character >= '0' && character <= '9')));
+ return ((u8) ((character == '_') ||
+ (character >= 'A' && character <= 'Z') ||
+ (character >= '0' && character <= '9')));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_strtoul64
@@ -415,18 +491,13 @@ acpi_ut_valid_acpi_character (
******************************************************************************/
acpi_status
-acpi_ut_strtoul64 (
- char *string,
- u32 base,
- acpi_integer *ret_integer)
+acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
{
- u32 this_digit = 0;
- acpi_integer return_value = 0;
- acpi_integer quotient;
-
-
- ACPI_FUNCTION_TRACE ("ut_stroul64");
+ u32 this_digit = 0;
+ acpi_integer return_value = 0;
+ acpi_integer quotient;
+ ACPI_FUNCTION_TRACE("ut_stroul64");
if ((!string) || !(*string)) {
goto error_exit;
@@ -440,12 +511,12 @@ acpi_ut_strtoul64 (
default:
/* Invalid Base */
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Skip over any white space in the buffer */
- while (ACPI_IS_SPACE (*string) || *string == '\t') {
+ while (ACPI_IS_SPACE(*string) || *string == '\t') {
string++;
}
@@ -454,12 +525,10 @@ acpi_ut_strtoul64 (
* determine if it is decimal or hexadecimal:
*/
if (base == 0) {
- if ((*string == '0') &&
- (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
base = 16;
string += 2;
- }
- else {
+ } else {
base = 10;
}
}
@@ -469,8 +538,7 @@ acpi_ut_strtoul64 (
* 0 or 0x, if they are present.
*/
if ((base == 16) &&
- (*string == '0') &&
- (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
string += 2;
}
@@ -483,25 +551,23 @@ acpi_ut_strtoul64 (
/* Main loop: convert the string to a 64-bit integer */
while (*string) {
- if (ACPI_IS_DIGIT (*string)) {
+ if (ACPI_IS_DIGIT(*string)) {
/* Convert ASCII 0-9 to Decimal value */
- this_digit = ((u8) *string) - '0';
- }
- else {
+ this_digit = ((u8) * string) - '0';
+ } else {
if (base == 10) {
/* Digit is out of range */
goto error_exit;
}
- this_digit = (u8) ACPI_TOUPPER (*string);
- if (ACPI_IS_XDIGIT ((char) this_digit)) {
+ this_digit = (u8) ACPI_TOUPPER(*string);
+ if (ACPI_IS_XDIGIT((char)this_digit)) {
/* Convert ASCII Hex char to value */
this_digit = this_digit - 'A' + 10;
- }
- else {
+ } else {
/*
* We allow non-hex chars, just stop now, same as end-of-string.
* See ACPI spec, string-to-integer conversion.
@@ -512,8 +578,10 @@ acpi_ut_strtoul64 (
/* Divide the digit into the correct position */
- (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit),
- base, &quotient, NULL);
+ (void)
+ acpi_ut_short_divide((ACPI_INTEGER_MAX -
+ (acpi_integer) this_digit), base,
+ &quotient, NULL);
if (return_value > quotient) {
goto error_exit;
}
@@ -526,335 +594,18 @@ acpi_ut_strtoul64 (
/* All done, normal exit */
*ret_integer = return_value;
- return_ACPI_STATUS (AE_OK);
-
+ return_ACPI_STATUS(AE_OK);
-error_exit:
+ error_exit:
/* Base was set/validated above */
if (base == 10) {
- return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
- }
- else {
- return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_mutex_initialize
- *
- * PARAMETERS: None.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create the system mutex objects.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_mutex_initialize (
- void)
-{
- u32 i;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_initialize");
-
-
- /*
- * Create each of the predefined mutex objects
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- status = acpi_ut_create_mutex (i);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
- }
-
- status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_mutex_terminate
- *
- * PARAMETERS: None.
- *
- * RETURN: None.
- *
- * DESCRIPTION: Delete all of the system mutex objects.
- *
- ******************************************************************************/
-
-void
-acpi_ut_mutex_terminate (
- void)
-{
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("ut_mutex_terminate");
-
-
- /*
- * Delete each predefined mutex object
- */
- for (i = 0; i < NUM_MUTEX; i++) {
- (void) acpi_ut_delete_mutex (i);
- }
-
- acpi_os_delete_lock (acpi_gbl_gpe_lock);
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be created
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a mutex object.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_create_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (!acpi_gbl_mutex_info[mutex_id].mutex) {
- status = acpi_os_create_semaphore (1, 1,
- &acpi_gbl_mutex_info[mutex_id].mutex);
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[mutex_id].use_count = 0;
- }
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be deleted
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete a mutex object.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_delete_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id);
-
-
- if (mutex_id > MAX_MUTEX) {
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex);
-
- acpi_gbl_mutex_info[mutex_id].mutex = NULL;
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- return_ACPI_STATUS (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_acquire_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be acquired
- *
- * RETURN: Status
- *
- * DESCRIPTION: Acquire a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_acquire_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 this_thread_id;
-
-
- ACPI_FUNCTION_NAME ("ut_acquire_mutex");
-
-
- if (mutex_id > MAX_MUTEX) {
- return (AE_BAD_PARAMETER);
- }
-
- this_thread_id = acpi_os_get_thread_id ();
-
-#ifdef ACPI_MUTEX_DEBUG
- {
- u32 i;
- /*
- * Mutex debug code, for internal debugging only.
- *
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than or equal to this one. If so, the thread has violated
- * the mutex ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] already acquired by this thread [%X]\n",
- acpi_ut_get_mutex_name (mutex_id), this_thread_id));
-
- return (AE_ALREADY_ACQUIRED);
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (i),
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_ACQUIRE_DEADLOCK);
- }
- }
- }
-#endif
-
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
- "Thread %X attempting to acquire Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex,
- 1, ACPI_WAIT_FOREVER);
- if (ACPI_SUCCESS (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
-
- acpi_gbl_mutex_info[mutex_id].use_count++;
- acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id;
- }
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not acquire Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
- }
-
- return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_release_mutex
- *
- * PARAMETERS: mutex_iD - ID of the mutex to be released
- *
- * RETURN: Status
- *
- * DESCRIPTION: Release a mutex object.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_release_mutex (
- acpi_mutex_handle mutex_id)
-{
- acpi_status status;
- u32 i;
- u32 this_thread_id;
-
-
- ACPI_FUNCTION_NAME ("ut_release_mutex");
-
-
- this_thread_id = acpi_os_get_thread_id ();
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
- "Thread %X releasing Mutex [%s]\n", this_thread_id,
- acpi_ut_get_mutex_name (mutex_id)));
-
- if (mutex_id > MAX_MUTEX) {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * Mutex must be acquired in order to release it!
- */
- if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Mutex [%s] is not acquired, cannot release\n",
- acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_NOT_ACQUIRED);
- }
-
- /*
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than this one. If so, the thread has violated the mutex
- * ordering rule. This indicates a coding error somewhere in
- * the ACPI subsystem code.
- */
- for (i = mutex_id; i < MAX_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
- if (i == mutex_id) {
- continue;
- }
-
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Invalid release order: owns [%s], releasing [%s]\n",
- acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));
-
- return (AE_RELEASE_DEADLOCK);
- }
- }
-
- /* Mark unlocked FIRST */
-
- acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
-
- status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1);
-
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Thread %X could not release Mutex [%s] %s\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id),
- acpi_format_exception (status)));
+ return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
+ } else {
+ return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
}
- else {
- ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
- this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
- }
-
- return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_update_state_and_push
@@ -870,16 +621,13 @@ acpi_ut_release_mutex (
******************************************************************************/
acpi_status
-acpi_ut_create_update_state_and_push (
- union acpi_operand_object *object,
- u16 action,
- union acpi_generic_state **state_list)
+acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
+ u16 action,
+ union acpi_generic_state **state_list)
{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
+ union acpi_generic_state *state;
+ ACPI_FUNCTION_ENTRY();
/* Ignore null objects; these are expected */
@@ -887,371 +635,15 @@ acpi_ut_create_update_state_and_push (
return (AE_OK);
}
- state = acpi_ut_create_update_state (object, action);
+ state = acpi_ut_create_update_state(object, action);
if (!state) {
return (AE_NO_MEMORY);
}
- acpi_ut_push_generic_state (state_list, state);
+ acpi_ut_push_generic_state(state_list, state);
return (AE_OK);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_pkg_state_and_push
- *
- * PARAMETERS: Object - Object to be added to the new state
- * Action - Increment/Decrement
- * state_list - List the state will be added to
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a new state and push it
- *
- ******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
-acpi_status
-acpi_ut_create_pkg_state_and_push (
- void *internal_object,
- void *external_object,
- u16 index,
- union acpi_generic_state **state_list)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_create_pkg_state (internal_object, external_object, index);
- if (!state) {
- return (AE_NO_MEMORY);
- }
-
- acpi_ut_push_generic_state (state_list, state);
- return (AE_OK);
-}
-#endif /* ACPI_FUTURE_USAGE */
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_push_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- * State - State object to push
- *
- * RETURN: None
- *
- * DESCRIPTION: Push a state object onto a state stack
- *
- ******************************************************************************/
-
-void
-acpi_ut_push_generic_state (
- union acpi_generic_state **list_head,
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_push_generic_state");
-
-
- /* Push the state object onto the front of the list (stack) */
-
- state->common.next = *list_head;
- *list_head = state;
-
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_pop_generic_state
- *
- * PARAMETERS: list_head - Head of the state stack
- *
- * RETURN: The popped state object
- *
- * DESCRIPTION: Pop a state object from a state stack
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_pop_generic_state (
- union acpi_generic_state **list_head)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_pop_generic_state");
-
-
- /* Remove the state object at the head of the list (stack) */
-
- state = *list_head;
- if (state) {
- /* Update the list head */
-
- *list_head = state->common.next;
- }
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_generic_state
- *
- * PARAMETERS: None
- *
- * RETURN: The new state object. NULL on failure.
- *
- * DESCRIPTION: Create a generic state object. Attempt to obtain one from
- * the global state cache; If none available, create a new one.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_generic_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_STATE);
-
- /* Initialize */
-
- if (state) {
- state->common.data_type = ACPI_DESC_TYPE_STATE;
- }
-
- return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_thread_state
- *
- * PARAMETERS: None
- *
- * RETURN: New Thread State. NULL on failure
- *
- * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
- * to track per-thread info during method execution
- *
- ******************************************************************************/
-
-struct acpi_thread_state *
-acpi_ut_create_thread_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_thread_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
- state->thread.thread_id = acpi_os_get_thread_id ();
-
- return_PTR ((struct acpi_thread_state *) state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_update_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
- * to update reference counts and delete complex objects such
- * as packages.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_update_state (
- union acpi_operand_object *object,
- u16 action)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_update_state", object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
- state->update.object = object;
- state->update.value = action;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_pkg_state
- *
- * PARAMETERS: Object - Initial Object to be installed in the state
- * Action - Update action to be performed
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Package State"
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_pkg_state (
- void *internal_object,
- void *external_object,
- u16 index)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_create_pkg_state", internal_object);
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the update struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
- state->pkg.source_object = (union acpi_operand_object *) internal_object;
- state->pkg.dest_object = external_object;
- state->pkg.index = index;
- state->pkg.num_packages = 1;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_control_state
- *
- * PARAMETERS: None
- *
- * RETURN: New state object, null on failure
- *
- * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
- * to support nested IF/WHILE constructs in the AML.
- *
- ******************************************************************************/
-
-union acpi_generic_state *
-acpi_ut_create_control_state (
- void)
-{
- union acpi_generic_state *state;
-
-
- ACPI_FUNCTION_TRACE ("ut_create_control_state");
-
-
- /* Create the generic state object */
-
- state = acpi_ut_create_generic_state ();
- if (!state) {
- return_PTR (NULL);
- }
-
- /* Init fields specific to the control struct */
-
- state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
- state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
-
- return_PTR (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state
- *
- * PARAMETERS: State - The state object to be deleted
- *
- * RETURN: None
- *
- * DESCRIPTION: Put a state object back into the global state cache. The object
- * is not actually freed at this time.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state (
- union acpi_generic_state *state)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state");
-
-
- acpi_ut_release_to_cache (ACPI_MEM_LIST_STATE, state);
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_generic_state_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_generic_state_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_generic_state_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_STATE);
- return_VOID;
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_walk_package_tree
@@ -1268,33 +660,29 @@ acpi_ut_delete_generic_state_cache (
******************************************************************************/
acpi_status
-acpi_ut_walk_package_tree (
- union acpi_operand_object *source_object,
- void *target_object,
- acpi_pkg_callback walk_callback,
- void *context)
+acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
+ void *target_object,
+ acpi_pkg_callback walk_callback, void *context)
{
- acpi_status status = AE_OK;
- union acpi_generic_state *state_list = NULL;
- union acpi_generic_state *state;
- u32 this_index;
- union acpi_operand_object *this_source_obj;
-
-
- ACPI_FUNCTION_TRACE ("ut_walk_package_tree");
+ acpi_status status = AE_OK;
+ union acpi_generic_state *state_list = NULL;
+ union acpi_generic_state *state;
+ u32 this_index;
+ union acpi_operand_object *this_source_obj;
+ ACPI_FUNCTION_TRACE("ut_walk_package_tree");
- state = acpi_ut_create_pkg_state (source_object, target_object, 0);
+ state = acpi_ut_create_pkg_state(source_object, target_object, 0);
if (!state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
while (state) {
/* Get one element of the package */
- this_index = state->pkg.index;
+ this_index = state->pkg.index;
this_source_obj = (union acpi_operand_object *)
- state->pkg.source_object->package.elements[this_index];
+ state->pkg.source_object->package.elements[this_index];
/*
* Check for:
@@ -1305,16 +693,20 @@ acpi_ut_walk_package_tree (
* case below.
*/
if ((!this_source_obj) ||
- (ACPI_GET_DESCRIPTOR_TYPE (this_source_obj) != ACPI_DESC_TYPE_OPERAND) ||
- (ACPI_GET_OBJECT_TYPE (this_source_obj) != ACPI_TYPE_PACKAGE)) {
- status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj,
- state, context);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
+ ACPI_DESC_TYPE_OPERAND)
+ || (ACPI_GET_OBJECT_TYPE(this_source_obj) !=
+ ACPI_TYPE_PACKAGE)) {
+ status =
+ walk_callback(ACPI_COPY_TYPE_SIMPLE,
+ this_source_obj, state, context);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
state->pkg.index++;
- while (state->pkg.index >= state->pkg.source_object->package.count) {
+ while (state->pkg.index >=
+ state->pkg.source_object->package.count) {
/*
* We've handled all of the objects at this level, This means
* that we have just completed a package. That package may
@@ -1322,8 +714,8 @@ acpi_ut_walk_package_tree (
*
* Delete this state and pop the previous state (package).
*/
- acpi_ut_delete_generic_state (state);
- state = acpi_ut_pop_generic_state (&state_list);
+ acpi_ut_delete_generic_state(state);
+ state = acpi_ut_pop_generic_state(&state_list);
/* Finished when there are no more states */
@@ -1333,7 +725,7 @@ acpi_ut_walk_package_tree (
* package just add the length of the package objects
* and exit
*/
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
@@ -1342,35 +734,35 @@ acpi_ut_walk_package_tree (
*/
state->pkg.index++;
}
- }
- else {
+ } else {
/* This is a subobject of type package */
- status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj,
- state, context);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ walk_callback(ACPI_COPY_TYPE_PACKAGE,
+ this_source_obj, state, context);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Push the current state and create a new one
* The callback above returned a new target package object.
*/
- acpi_ut_push_generic_state (&state_list, state);
- state = acpi_ut_create_pkg_state (this_source_obj,
- state->pkg.this_target_obj, 0);
+ acpi_ut_push_generic_state(&state_list, state);
+ state = acpi_ut_create_pkg_state(this_source_obj,
+ state->pkg.
+ this_target_obj, 0);
if (!state) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
}
}
/* We should never get here */
- return_ACPI_STATUS (AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_INTERNAL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_generate_checksum
@@ -1384,23 +776,18 @@ acpi_ut_walk_package_tree (
*
******************************************************************************/
-u8
-acpi_ut_generate_checksum (
- u8 *buffer,
- u32 length)
+u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
{
- u32 i;
- signed char sum = 0;
-
+ u32 i;
+ signed char sum = 0;
for (i = 0; i < length; i++) {
- sum = (signed char) (sum + buffer[i]);
+ sum = (signed char)(sum + buffer[i]);
}
return ((u8) (0 - sum));
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_resource_end_tag
@@ -1413,17 +800,13 @@ acpi_ut_generate_checksum (
*
******************************************************************************/
-
-u8 *
-acpi_ut_get_resource_end_tag (
- union acpi_operand_object *obj_desc)
+u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
{
- u8 buffer_byte;
- u8 *buffer;
- u8 *end_buffer;
-
+ u8 buffer_byte;
+ u8 *buffer;
+ u8 *end_buffer;
- buffer = obj_desc->buffer.pointer;
+ buffer = obj_desc->buffer.pointer;
end_buffer = buffer + obj_desc->buffer.length;
while (buffer < end_buffer) {
@@ -1431,12 +814,12 @@ acpi_ut_get_resource_end_tag (
if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
/* Large Descriptor - Length is next 2 bytes */
- buffer += ((*(buffer+1) | (*(buffer+2) << 8)) + 3);
- }
- else {
+ buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
+ } else {
/* Small Descriptor. End Tag will be found here */
- if ((buffer_byte & ACPI_RDESC_SMALL_MASK) == ACPI_RDESC_TYPE_END_TAG) {
+ if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
+ ACPI_RDESC_TYPE_END_TAG) {
/* Found the end tag descriptor, all done. */
return (buffer);
@@ -1453,7 +836,6 @@ acpi_ut_get_resource_end_tag (
return (NULL);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_error
@@ -1468,17 +850,12 @@ acpi_ut_get_resource_end_tag (
*
******************************************************************************/
-void
-acpi_ut_report_error (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_warning
@@ -1494,16 +871,12 @@ acpi_ut_report_error (
******************************************************************************/
void
-acpi_ut_report_warning (
- char *module_name,
- u32 line_number,
- u32 component_id)
+acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_report_info
@@ -1518,14 +891,8 @@ acpi_ut_report_warning (
*
******************************************************************************/
-void
-acpi_ut_report_info (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
{
- acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number);
+ acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
}
-
-
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
new file mode 100644
index 000000000000..90134c56ece9
--- /dev/null
+++ b/drivers/acpi/utilities/utmutex.c
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ *
+ * Module Name: utmutex - local mutex support
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utmutex")
+
+/* Local prototypes */
+static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
+
+static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_mutex_initialize
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create the system mutex objects.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_mutex_initialize(void)
+{
+ u32 i;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ut_mutex_initialize");
+
+ /*
+ * Create each of the predefined mutex objects
+ */
+ for (i = 0; i < NUM_MUTEX; i++) {
+ status = acpi_ut_create_mutex(i);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ status = acpi_os_create_lock(&acpi_gbl_gpe_lock);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_mutex_terminate
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete all of the system mutex objects.
+ *
+ ******************************************************************************/
+
+void acpi_ut_mutex_terminate(void)
+{
+ u32 i;
+
+ ACPI_FUNCTION_TRACE("ut_mutex_terminate");
+
+ /*
+ * Delete each predefined mutex object
+ */
+ for (i = 0; i < NUM_MUTEX; i++) {
+ (void)acpi_ut_delete_mutex(i);
+ }
+
+ acpi_os_delete_lock(acpi_gbl_gpe_lock);
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be created
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a mutex object.
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE_U32("ut_create_mutex", mutex_id);
+
+ if (mutex_id > MAX_MUTEX) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ if (!acpi_gbl_mutex_info[mutex_id].mutex) {
+ status = acpi_os_create_semaphore(1, 1,
+ &acpi_gbl_mutex_info
+ [mutex_id].mutex);
+ acpi_gbl_mutex_info[mutex_id].thread_id =
+ ACPI_MUTEX_NOT_ACQUIRED;
+ acpi_gbl_mutex_info[mutex_id].use_count = 0;
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_delete_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be deleted
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete a mutex object.
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id);
+
+ if (mutex_id > MAX_MUTEX) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ status = acpi_os_delete_semaphore(acpi_gbl_mutex_info[mutex_id].mutex);
+
+ acpi_gbl_mutex_info[mutex_id].mutex = NULL;
+ acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_acquire_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be acquired
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Acquire a mutex object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+ u32 this_thread_id;
+
+ ACPI_FUNCTION_NAME("ut_acquire_mutex");
+
+ if (mutex_id > MAX_MUTEX) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ this_thread_id = acpi_os_get_thread_id();
+
+#ifdef ACPI_MUTEX_DEBUG
+ {
+ u32 i;
+ /*
+ * Mutex debug code, for internal debugging only.
+ *
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than or equal to this one. If so, the thread has violated
+ * the mutex ordering rule. This indicates a coding error somewhere in
+ * the ACPI subsystem code.
+ */
+ for (i = mutex_id; i < MAX_MUTEX; i++) {
+ if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (i == mutex_id) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Mutex [%s] already acquired by this thread [%X]\n",
+ acpi_ut_get_mutex_name
+ (mutex_id),
+ this_thread_id));
+
+ return (AE_ALREADY_ACQUIRED);
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name
+ (mutex_id)));
+
+ return (AE_ACQUIRE_DEADLOCK);
+ }
+ }
+ }
+#endif
+
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X attempting to acquire Mutex [%s]\n",
+ this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
+
+ status = acpi_os_wait_semaphore(acpi_gbl_mutex_info[mutex_id].mutex,
+ 1, ACPI_WAIT_FOREVER);
+ if (ACPI_SUCCESS(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X acquired Mutex [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
+
+ acpi_gbl_mutex_info[mutex_id].use_count++;
+ acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Thread %X could not acquire Mutex [%s] %s\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id),
+ acpi_format_exception(status)));
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_release_mutex
+ *
+ * PARAMETERS: mutex_iD - ID of the mutex to be released
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Release a mutex object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
+{
+ acpi_status status;
+ u32 this_thread_id;
+
+ ACPI_FUNCTION_NAME("ut_release_mutex");
+
+ this_thread_id = acpi_os_get_thread_id();
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X releasing Mutex [%s]\n", this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
+
+ if (mutex_id > MAX_MUTEX) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Mutex must be acquired in order to release it!
+ */
+ if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Mutex [%s] is not acquired, cannot release\n",
+ acpi_ut_get_mutex_name(mutex_id)));
+
+ return (AE_NOT_ACQUIRED);
+ }
+#ifdef ACPI_MUTEX_DEBUG
+ {
+ u32 i;
+ /*
+ * Mutex debug code, for internal debugging only.
+ *
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than this one. If so, the thread has violated the mutex
+ * ordering rule. This indicates a coding error somewhere in
+ * the ACPI subsystem code.
+ */
+ for (i = mutex_id; i < MAX_MUTEX; i++) {
+ if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
+ if (i == mutex_id) {
+ continue;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid release order: owns [%s], releasing [%s]\n",
+ acpi_ut_get_mutex_name(i),
+ acpi_ut_get_mutex_name
+ (mutex_id)));
+
+ return (AE_RELEASE_DEADLOCK);
+ }
+ }
+ }
+#endif
+
+ /* Mark unlocked FIRST */
+
+ acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+ status =
+ acpi_os_signal_semaphore(acpi_gbl_mutex_info[mutex_id].mutex, 1);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Thread %X could not release Mutex [%s] %s\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id),
+ acpi_format_exception(status)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+ "Thread %X released Mutex [%s]\n",
+ this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
+ }
+
+ return (status);
+}
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index cd3899b9cc5a..3015e1540053 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -41,34 +41,26 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/amlcode.h>
-
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utobject")
+ACPI_MODULE_NAME("utobject")
/* Local prototypes */
-
static acpi_status
-acpi_ut_get_simple_object_size (
- union acpi_operand_object *obj,
- acpi_size *obj_length);
+acpi_ut_get_simple_object_size(union acpi_operand_object *obj,
+ acpi_size * obj_length);
static acpi_status
-acpi_ut_get_package_object_size (
- union acpi_operand_object *obj,
- acpi_size *obj_length);
+acpi_ut_get_package_object_size(union acpi_operand_object *obj,
+ acpi_size * obj_length);
static acpi_status
-acpi_ut_get_element_length (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context);
-
+acpi_ut_get_element_length(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state, void *context);
/*******************************************************************************
*
@@ -91,26 +83,25 @@ acpi_ut_get_element_length (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_internal_object_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id,
- acpi_object_type type)
+union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
+ u32 line_number,
+ u32 component_id,
+ acpi_object_type
+ type)
{
- union acpi_operand_object *object;
- union acpi_operand_object *second_object;
-
-
- ACPI_FUNCTION_TRACE_STR ("ut_create_internal_object_dbg",
- acpi_ut_get_type_name (type));
+ union acpi_operand_object *object;
+ union acpi_operand_object *second_object;
+ ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg",
+ acpi_ut_get_type_name(type));
/* Allocate the raw object descriptor */
- object = acpi_ut_allocate_object_desc_dbg (module_name, line_number, component_id);
+ object =
+ acpi_ut_allocate_object_desc_dbg(module_name, line_number,
+ component_id);
if (!object) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
switch (type) {
@@ -119,11 +110,12 @@ acpi_ut_create_internal_object_dbg (
/* These types require a secondary object */
- second_object = acpi_ut_allocate_object_desc_dbg (module_name,
- line_number, component_id);
+ second_object = acpi_ut_allocate_object_desc_dbg(module_name,
+ line_number,
+ component_id);
if (!second_object) {
- acpi_ut_delete_object_desc (object);
- return_PTR (NULL);
+ acpi_ut_delete_object_desc(object);
+ return_PTR(NULL);
}
second_object->common.type = ACPI_TYPE_LOCAL_EXTRA;
@@ -149,10 +141,9 @@ acpi_ut_create_internal_object_dbg (
/* Any per-type initialization should go here */
- return_PTR (object);
+ return_PTR(object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_buffer_object
@@ -165,22 +156,18 @@ acpi_ut_create_internal_object_dbg (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_buffer_object (
- acpi_size buffer_size)
+union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
{
- union acpi_operand_object *buffer_desc;
- u8 *buffer = NULL;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size);
+ union acpi_operand_object *buffer_desc;
+ u8 *buffer = NULL;
+ ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size);
/* Create a new Buffer object */
- buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
if (!buffer_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Create an actual buffer only if size > 0 */
@@ -188,12 +175,11 @@ acpi_ut_create_buffer_object (
if (buffer_size > 0) {
/* Allocate the actual buffer */
- buffer = ACPI_MEM_CALLOCATE (buffer_size);
+ buffer = ACPI_MEM_CALLOCATE(buffer_size);
if (!buffer) {
- ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n",
- (u32) buffer_size));
- acpi_ut_remove_reference (buffer_desc);
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("create_buffer: could not allocate size %X\n", (u32) buffer_size));
+ acpi_ut_remove_reference(buffer_desc);
+ return_PTR(NULL);
}
}
@@ -205,10 +191,9 @@ acpi_ut_create_buffer_object (
/* Return the new buffer descriptor */
- return_PTR (buffer_desc);
+ return_PTR(buffer_desc);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_string_object
@@ -223,34 +208,29 @@ acpi_ut_create_buffer_object (
*
******************************************************************************/
-union acpi_operand_object *
-acpi_ut_create_string_object (
- acpi_size string_size)
+union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
{
- union acpi_operand_object *string_desc;
- char *string;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ut_create_string_object", string_size);
+ union acpi_operand_object *string_desc;
+ char *string;
+ ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size);
/* Create a new String object */
- string_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
+ string_desc = acpi_ut_create_internal_object(ACPI_TYPE_STRING);
if (!string_desc) {
- return_PTR (NULL);
+ return_PTR(NULL);
}
/*
* Allocate the actual string buffer -- (Size + 1) for NULL terminator.
* NOTE: Zero-length strings are NULL terminated
*/
- string = ACPI_MEM_CALLOCATE (string_size + 1);
+ string = ACPI_MEM_CALLOCATE(string_size + 1);
if (!string) {
- ACPI_REPORT_ERROR (("create_string: could not allocate size %X\n",
- (u32) string_size));
- acpi_ut_remove_reference (string_desc);
- return_PTR (NULL);
+ ACPI_REPORT_ERROR(("create_string: could not allocate size %X\n", (u32) string_size));
+ acpi_ut_remove_reference(string_desc);
+ return_PTR(NULL);
}
/* Complete string object initialization */
@@ -260,10 +240,9 @@ acpi_ut_create_string_object (
/* Return the new string descriptor */
- return_PTR (string_desc);
+ return_PTR(string_desc);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_valid_internal_object
@@ -276,24 +255,21 @@ acpi_ut_create_string_object (
*
******************************************************************************/
-u8
-acpi_ut_valid_internal_object (
- void *object)
+u8 acpi_ut_valid_internal_object(void *object)
{
- ACPI_FUNCTION_NAME ("ut_valid_internal_object");
-
+ ACPI_FUNCTION_NAME("ut_valid_internal_object");
/* Check for a null pointer */
if (!object) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Null Object Ptr\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n"));
return (FALSE);
}
/* Check the descriptor type field */
- switch (ACPI_GET_DESCRIPTOR_TYPE (object)) {
+ switch (ACPI_GET_DESCRIPTOR_TYPE(object)) {
case ACPI_DESC_TYPE_OPERAND:
/* The object appears to be a valid union acpi_operand_object */
@@ -301,16 +277,15 @@ acpi_ut_valid_internal_object (
return (TRUE);
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "%p is not not an ACPI operand obj [%s]\n",
- object, acpi_ut_get_descriptor_name (object)));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "%p is not not an ACPI operand obj [%s]\n",
+ object, acpi_ut_get_descriptor_name(object)));
break;
}
return (FALSE);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_allocate_object_desc_dbg
@@ -326,37 +301,31 @@ acpi_ut_valid_internal_object (
*
******************************************************************************/
-void *
-acpi_ut_allocate_object_desc_dbg (
- char *module_name,
- u32 line_number,
- u32 component_id)
+void *acpi_ut_allocate_object_desc_dbg(char *module_name,
+ u32 line_number, u32 component_id)
{
- union acpi_operand_object *object;
+ union acpi_operand_object *object;
+ ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg");
- ACPI_FUNCTION_TRACE ("ut_allocate_object_desc_dbg");
-
-
- object = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_OPERAND);
+ object = acpi_os_acquire_object(acpi_gbl_operand_cache);
if (!object) {
- _ACPI_REPORT_ERROR (module_name, line_number, component_id,
- ("Could not allocate an object descriptor\n"));
+ _ACPI_REPORT_ERROR(module_name, line_number, component_id,
+ ("Could not allocate an object descriptor\n"));
- return_PTR (NULL);
+ return_PTR(NULL);
}
/* Mark the descriptor type */
+ memset(object, 0, sizeof(union acpi_operand_object));
+ ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
- ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_OPERAND);
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
+ object, (u32) sizeof(union acpi_operand_object)));
- ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
- object, (u32) sizeof (union acpi_operand_object)));
-
- return_PTR (object);
+ return_PTR(object);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_delete_object_desc
@@ -369,54 +338,22 @@ acpi_ut_allocate_object_desc_dbg (
*
******************************************************************************/
-void
-acpi_ut_delete_object_desc (
- union acpi_operand_object *object)
+void acpi_ut_delete_object_desc(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR ("ut_delete_object_desc", object);
-
+ ACPI_FUNCTION_TRACE_PTR("ut_delete_object_desc", object);
/* Object must be an union acpi_operand_object */
- if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "%p is not an ACPI Operand object [%s]\n", object,
- acpi_ut_get_descriptor_name (object)));
+ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "%p is not an ACPI Operand object [%s]\n",
+ object, acpi_ut_get_descriptor_name(object)));
return_VOID;
}
- acpi_ut_release_to_cache (ACPI_MEM_LIST_OPERAND, object);
-
- return_VOID;
-}
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_delete_object_cache
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Purge the global state object cache. Used during subsystem
- * termination.
- *
- ******************************************************************************/
-
-void
-acpi_ut_delete_object_cache (
- void)
-{
- ACPI_FUNCTION_TRACE ("ut_delete_object_cache");
-
-
- acpi_ut_delete_generic_cache (ACPI_MEM_LIST_OPERAND);
+ (void)acpi_os_release_object(acpi_gbl_operand_cache, object);
return_VOID;
}
-#endif
-
/*******************************************************************************
*
@@ -436,16 +373,13 @@ acpi_ut_delete_object_cache (
******************************************************************************/
static acpi_status
-acpi_ut_get_simple_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_size length;
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ut_get_simple_object_size", internal_object);
+ acpi_size length;
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object);
/*
* Handle a null object (Could be a uninitialized package
@@ -453,18 +387,18 @@ acpi_ut_get_simple_object_size (
*/
if (!internal_object) {
*obj_length = 0;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/* Start with the length of the Acpi object */
- length = sizeof (union acpi_object);
+ length = sizeof(union acpi_object);
- if (ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) {
/* Object is a named object (reference), just return the length */
- *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD (length);
- return_ACPI_STATUS (status);
+ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
+ return_ACPI_STATUS(status);
}
/*
@@ -473,19 +407,17 @@ acpi_ut_get_simple_object_size (
* must be accessed bytewise or there may be alignment problems on
* certain processors
*/
- switch (ACPI_GET_OBJECT_TYPE (internal_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(internal_object)) {
case ACPI_TYPE_STRING:
length += (acpi_size) internal_object->string.length + 1;
break;
-
case ACPI_TYPE_BUFFER:
length += (acpi_size) internal_object->buffer.length;
break;
-
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_POWER:
@@ -495,7 +427,6 @@ acpi_ut_get_simple_object_size (
*/
break;
-
case ACPI_TYPE_LOCAL_REFERENCE:
switch (internal_object->reference.opcode) {
@@ -505,8 +436,10 @@ acpi_ut_get_simple_object_size (
* Get the actual length of the full pathname to this object.
* The reference will be converted to the pathname to the object
*/
- length += ACPI_ROUND_UP_TO_NATIVE_WORD (
- acpi_ns_get_pathname_length (internal_object->reference.node));
+ length +=
+ ACPI_ROUND_UP_TO_NATIVE_WORD
+ (acpi_ns_get_pathname_length
+ (internal_object->reference.node));
break;
default:
@@ -516,19 +449,21 @@ acpi_ut_get_simple_object_size (
* Notably, Locals and Args are not supported, but this may be
* required eventually.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Unsupported Reference opcode=%X in object %p\n",
- internal_object->reference.opcode, internal_object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported Reference opcode=%X in object %p\n",
+ internal_object->reference.opcode,
+ internal_object));
status = AE_TYPE;
break;
}
break;
-
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported type=%X in object %p\n",
- ACPI_GET_OBJECT_TYPE (internal_object), internal_object));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unsupported type=%X in object %p\n",
+ ACPI_GET_OBJECT_TYPE(internal_object),
+ internal_object));
status = AE_TYPE;
break;
}
@@ -539,11 +474,10 @@ acpi_ut_get_simple_object_size (
* on a machine word boundary. (preventing alignment faults on some
* machines.)
*/
- *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD (length);
- return_ACPI_STATUS (status);
+ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_element_length
@@ -557,16 +491,13 @@ acpi_ut_get_simple_object_size (
******************************************************************************/
static acpi_status
-acpi_ut_get_element_length (
- u8 object_type,
- union acpi_operand_object *source_object,
- union acpi_generic_state *state,
- void *context)
+acpi_ut_get_element_length(u8 object_type,
+ union acpi_operand_object *source_object,
+ union acpi_generic_state *state, void *context)
{
- acpi_status status = AE_OK;
- struct acpi_pkg_info *info = (struct acpi_pkg_info *) context;
- acpi_size object_space;
-
+ acpi_status status = AE_OK;
+ struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
+ acpi_size object_space;
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
@@ -575,15 +506,16 @@ acpi_ut_get_element_length (
* Simple object - just get the size (Null object/entry is handled
* here also) and sum it into the running package length
*/
- status = acpi_ut_get_simple_object_size (source_object, &object_space);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_get_simple_object_size(source_object,
+ &object_space);
+ if (ACPI_FAILURE(status)) {
return (status);
}
info->length += object_space;
break;
-
case ACPI_COPY_TYPE_PACKAGE:
/* Package object - nothing much to do here, let the walk handle it */
@@ -592,7 +524,6 @@ acpi_ut_get_element_length (
state->pkg.this_target_obj = NULL;
break;
-
default:
/* No other types allowed */
@@ -603,7 +534,6 @@ acpi_ut_get_element_length (
return (status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_package_object_size
@@ -622,25 +552,22 @@ acpi_ut_get_element_length (
******************************************************************************/
static acpi_status
-acpi_ut_get_package_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_status status;
- struct acpi_pkg_info info;
+ acpi_status status;
+ struct acpi_pkg_info info;
+ ACPI_FUNCTION_TRACE_PTR("ut_get_package_object_size", internal_object);
- ACPI_FUNCTION_TRACE_PTR ("ut_get_package_object_size", internal_object);
-
-
- info.length = 0;
+ info.length = 0;
info.object_space = 0;
info.num_packages = 1;
- status = acpi_ut_walk_package_tree (internal_object, NULL,
- acpi_ut_get_element_length, &info);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_walk_package_tree(internal_object, NULL,
+ acpi_ut_get_element_length, &info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
@@ -648,16 +575,15 @@ acpi_ut_get_package_object_size (
* just add the length of the package objects themselves.
* Round up to the next machine word.
*/
- info.length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (union acpi_object)) *
- (acpi_size) info.num_packages;
+ info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
+ (acpi_size) info.num_packages;
/* Return the total package length */
*obj_length = info.length;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_object_size
@@ -673,25 +599,23 @@ acpi_ut_get_package_object_size (
******************************************************************************/
acpi_status
-acpi_ut_get_object_size (
- union acpi_operand_object *internal_object,
- acpi_size *obj_length)
+acpi_ut_get_object_size(union acpi_operand_object *internal_object,
+ acpi_size * obj_length)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if ((ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_OPERAND) &&
- (ACPI_GET_OBJECT_TYPE (internal_object) == ACPI_TYPE_PACKAGE)) {
- status = acpi_ut_get_package_object_size (internal_object, obj_length);
- }
- else {
- status = acpi_ut_get_simple_object_size (internal_object, obj_length);
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) ==
+ ACPI_DESC_TYPE_OPERAND)
+ && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) {
+ status =
+ acpi_ut_get_package_object_size(internal_object,
+ obj_length);
+ } else {
+ status =
+ acpi_ut_get_simple_object_size(internal_object, obj_length);
}
return (status);
}
-
-
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
new file mode 100644
index 000000000000..c1cb27583be8
--- /dev/null
+++ b/drivers/acpi/utilities/utstate.c
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ *
+ * Module Name: utstate - state object support procedures
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utstate")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_pkg_state_and_push
+ *
+ * PARAMETERS: Object - Object to be added to the new state
+ * Action - Increment/Decrement
+ * state_list - List the state will be added to
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a new state and push it
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ut_create_pkg_state_and_push(void *internal_object,
+ void *external_object,
+ u16 index,
+ union acpi_generic_state ** state_list)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_ENTRY();
+
+ state =
+ acpi_ut_create_pkg_state(internal_object, external_object, index);
+ if (!state) {
+ return (AE_NO_MEMORY);
+ }
+
+ acpi_ut_push_generic_state(state_list, state);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_push_generic_state
+ *
+ * PARAMETERS: list_head - Head of the state stack
+ * State - State object to push
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Push a state object onto a state stack
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_push_generic_state(union acpi_generic_state **list_head,
+ union acpi_generic_state *state)
+{
+ ACPI_FUNCTION_TRACE("ut_push_generic_state");
+
+ /* Push the state object onto the front of the list (stack) */
+
+ state->common.next = *list_head;
+ *list_head = state;
+
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_pop_generic_state
+ *
+ * PARAMETERS: list_head - Head of the state stack
+ *
+ * RETURN: The popped state object
+ *
+ * DESCRIPTION: Pop a state object from a state stack
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
+ **list_head)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE("ut_pop_generic_state");
+
+ /* Remove the state object at the head of the list (stack) */
+
+ state = *list_head;
+ if (state) {
+ /* Update the list head */
+
+ *list_head = state->common.next;
+ }
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_generic_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: The new state object. NULL on failure.
+ *
+ * DESCRIPTION: Create a generic state object. Attempt to obtain one from
+ * the global state cache; If none available, create a new one.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_generic_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_ENTRY();
+
+ state = acpi_os_acquire_object(acpi_gbl_state_cache);
+ if (state) {
+ /* Initialize */
+ memset(state, 0, sizeof(union acpi_generic_state));
+ state->common.data_type = ACPI_DESC_TYPE_STATE;
+ }
+
+ return (state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_thread_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: New Thread State. NULL on failure
+ *
+ * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used
+ * to track per-thread info during method execution
+ *
+ ******************************************************************************/
+
+struct acpi_thread_state *acpi_ut_create_thread_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE("ut_create_thread_state");
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
+ state->thread.thread_id = acpi_os_get_thread_id();
+
+ return_PTR((struct acpi_thread_state *)state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_update_state
+ *
+ * PARAMETERS: Object - Initial Object to be installed in the state
+ * Action - Update action to be performed
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
+ * to update reference counts and delete complex objects such
+ * as packages.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
+ *object, u16 action)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object);
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
+ state->update.object = object;
+ state->update.value = action;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_pkg_state
+ *
+ * PARAMETERS: Object - Initial Object to be installed in the state
+ * Action - Update action to be performed
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create a "Package State"
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
+ void *external_object,
+ u16 index)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object);
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the update struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
+ state->pkg.source_object = (union acpi_operand_object *)internal_object;
+ state->pkg.dest_object = external_object;
+ state->pkg.index = index;
+ state->pkg.num_packages = 1;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_control_state
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: New state object, null on failure
+ *
+ * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
+ * to support nested IF/WHILE constructs in the AML.
+ *
+ ******************************************************************************/
+
+union acpi_generic_state *acpi_ut_create_control_state(void)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_TRACE("ut_create_control_state");
+
+ /* Create the generic state object */
+
+ state = acpi_ut_create_generic_state();
+ if (!state) {
+ return_PTR(NULL);
+ }
+
+ /* Init fields specific to the control struct */
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
+ state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
+
+ return_PTR(state);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_delete_generic_state
+ *
+ * PARAMETERS: State - The state object to be deleted
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Put a state object back into the global state cache. The object
+ * is not actually freed at this time.
+ *
+ ******************************************************************************/
+
+void acpi_ut_delete_generic_state(union acpi_generic_state *state)
+{
+ ACPI_FUNCTION_TRACE("ut_delete_generic_state");
+
+ (void)acpi_os_release_object(acpi_gbl_state_cache, state);
+ return_VOID;
+}
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index e8803d810656..f06bd5e5e9d1 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -46,13 +46,10 @@
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
#include <acpi/acdebug.h>
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME ("utxface")
-
+ACPI_MODULE_NAME("utxface")
/*******************************************************************************
*
@@ -66,61 +63,54 @@
* called, so any early initialization belongs here.
*
******************************************************************************/
-
-acpi_status
-acpi_initialize_subsystem (
- void)
+acpi_status acpi_initialize_subsystem(void)
{
- acpi_status status;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_initialize_subsystem");
- ACPI_FUNCTION_TRACE ("acpi_initialize_subsystem");
+ ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
+ /* Initialize the OS-Dependent layer */
- ACPI_DEBUG_EXEC (acpi_ut_init_stack_ptr_trace ());
-
+ status = acpi_os_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("OSD failed to initialize, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
+ }
/* Initialize all globals used by the subsystem */
- acpi_ut_init_globals ();
-
- /* Initialize the OS-Dependent layer */
-
- status = acpi_os_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("OSD failed to initialize, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
- }
+ acpi_ut_init_globals();
/* Create the default mutex objects */
- status = acpi_ut_mutex_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Global mutex creation failure, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ut_mutex_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Global mutex creation failure, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/*
* Initialize the namespace manager and
* the root of the namespace tree
*/
- status = acpi_ns_root_initialize ();
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Namespace initialization failure, %s\n",
- acpi_format_exception (status)));
- return_ACPI_STATUS (status);
+ status = acpi_ns_root_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Namespace initialization failure, %s\n",
+ acpi_format_exception(status)));
+ return_ACPI_STATUS(status);
}
/* If configured, initialize the AML debugger */
- ACPI_DEBUGGER_EXEC (status = acpi_db_initialize ());
+ ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_enable_subsystem
@@ -134,41 +124,39 @@ acpi_initialize_subsystem (
*
******************************************************************************/
-acpi_status
-acpi_enable_subsystem (
- u32 flags)
+acpi_status acpi_enable_subsystem(u32 flags)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_enable_subsystem");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_enable_subsystem");
/*
* We must initialize the hardware before we can enable ACPI.
* The values from the FADT are validated here.
*/
if (!(flags & ACPI_NO_HARDWARE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI hardware\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI hardware\n"));
- status = acpi_hw_initialize ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_hw_initialize();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Enable ACPI mode */
if (!(flags & ACPI_NO_ACPI_ENABLE)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Going into ACPI mode\n"));
acpi_gbl_original_mode = acpi_hw_get_mode();
- status = acpi_enable ();
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_enable failed.\n"));
- return_ACPI_STATUS (status);
+ status = acpi_enable();
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "acpi_enable failed.\n"));
+ return_ACPI_STATUS(status);
}
}
@@ -178,12 +166,12 @@ acpi_enable_subsystem (
* install_address_space_handler interface.
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Installing default address space handlers\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing default address space handlers\n"));
- status = acpi_ev_install_region_handlers ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_region_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -196,28 +184,28 @@ acpi_enable_subsystem (
* execution!
*/
if (!(flags & ACPI_NO_EVENT_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI events\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI events\n"));
- status = acpi_ev_initialize_events ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_initialize_events();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
/* Install the SCI handler and Global Lock handler */
if (!(flags & ACPI_NO_HANDLER_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Installing SCI/GL handlers\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing SCI/GL handlers\n"));
- status = acpi_ev_install_xrupt_handlers ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_install_xrupt_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -233,15 +221,11 @@ acpi_enable_subsystem (
*
******************************************************************************/
-acpi_status
-acpi_initialize_objects (
- u32 flags)
+acpi_status acpi_initialize_objects(u32 flags)
{
- acpi_status status = AE_OK;
-
-
- ACPI_FUNCTION_TRACE ("acpi_initialize_objects");
+ acpi_status status = AE_OK;
+ ACPI_FUNCTION_TRACE("acpi_initialize_objects");
/*
* Run all _REG methods
@@ -251,12 +235,12 @@ acpi_initialize_objects (
* contain executable AML (see call to acpi_ns_initialize_objects below).
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Executing _REG op_region methods\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Executing _REG op_region methods\n"));
- status = acpi_ev_initialize_op_regions ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ev_initialize_op_regions();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -266,12 +250,12 @@ acpi_initialize_objects (
* objects: operation_regions, buffer_fields, Buffers, and Packages.
*/
if (!(flags & ACPI_NO_OBJECT_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Completing Initialization of ACPI Objects\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Completing Initialization of ACPI Objects\n"));
- status = acpi_ns_initialize_objects ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_initialize_objects();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -280,12 +264,12 @@ acpi_initialize_objects (
* This runs the _STA and _INI methods.
*/
if (!(flags & ACPI_NO_DEVICE_INIT)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "[Init] Initializing ACPI Devices\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI Devices\n"));
- status = acpi_ns_initialize_devices ();
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ns_initialize_devices();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
}
@@ -294,13 +278,12 @@ acpi_initialize_objects (
* the table load filled them up more than they will be at runtime --
* thus wasting non-paged memory.
*/
- status = acpi_purge_cached_objects ();
+ status = acpi_purge_cached_objects();
acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_terminate
@@ -313,15 +296,11 @@ acpi_initialize_objects (
*
******************************************************************************/
-acpi_status
-acpi_terminate (
- void)
+acpi_status acpi_terminate(void)
{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE ("acpi_terminate");
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("acpi_terminate");
/* Terminate the AML Debugger if present */
@@ -329,28 +308,25 @@ acpi_terminate (
/* Shutdown and free all resources */
- acpi_ut_subsystem_shutdown ();
-
+ acpi_ut_subsystem_shutdown();
/* Free the mutex objects */
- acpi_ut_mutex_terminate ();
-
+ acpi_ut_mutex_terminate();
#ifdef ACPI_DEBUGGER
/* Shut down the debugger */
- acpi_db_terminate ();
+ acpi_db_terminate();
#endif
/* Now we can shutdown the OS-dependent layer */
- status = acpi_os_terminate ();
- return_ACPI_STATUS (status);
+ status = acpi_os_terminate();
+ return_ACPI_STATUS(status);
}
-
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -366,20 +342,16 @@ acpi_terminate (
*
******************************************************************************/
-acpi_status
-acpi_subsystem_status (
- void)
+acpi_status acpi_subsystem_status(void)
{
if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) {
return (AE_OK);
- }
- else {
+ } else {
return (AE_ERROR);
}
}
-
/*******************************************************************************
*
* FUNCTION: acpi_get_system_info
@@ -398,64 +370,60 @@ acpi_subsystem_status (
*
******************************************************************************/
-acpi_status
-acpi_get_system_info (
- struct acpi_buffer *out_buffer)
+acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
{
- struct acpi_system_info *info_ptr;
- acpi_status status;
- u32 i;
-
-
- ACPI_FUNCTION_TRACE ("acpi_get_system_info");
+ struct acpi_system_info *info_ptr;
+ acpi_status status;
+ u32 i;
+ ACPI_FUNCTION_TRACE("acpi_get_system_info");
/* Parameter validation */
- status = acpi_ut_validate_buffer (out_buffer);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status = acpi_ut_validate_buffer(out_buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Validate/Allocate/Clear caller buffer */
- status = acpi_ut_initialize_buffer (out_buffer, sizeof (struct acpi_system_info));
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ status =
+ acpi_ut_initialize_buffer(out_buffer,
+ sizeof(struct acpi_system_info));
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
* Populate the return buffer
*/
- info_ptr = (struct acpi_system_info *) out_buffer->pointer;
+ info_ptr = (struct acpi_system_info *)out_buffer->pointer;
- info_ptr->acpi_ca_version = ACPI_CA_VERSION;
+ info_ptr->acpi_ca_version = ACPI_CA_VERSION;
/* System flags (ACPI capabilities) */
- info_ptr->flags = ACPI_SYS_MODE_ACPI;
+ info_ptr->flags = ACPI_SYS_MODE_ACPI;
/* Timer resolution - 24 or 32 bits */
if (!acpi_gbl_FADT) {
info_ptr->timer_resolution = 0;
- }
- else if (acpi_gbl_FADT->tmr_val_ext == 0) {
+ } else if (acpi_gbl_FADT->tmr_val_ext == 0) {
info_ptr->timer_resolution = 24;
- }
- else {
+ } else {
info_ptr->timer_resolution = 32;
}
/* Clear the reserved fields */
- info_ptr->reserved1 = 0;
- info_ptr->reserved2 = 0;
+ info_ptr->reserved1 = 0;
+ info_ptr->reserved2 = 0;
/* Current debug levels */
- info_ptr->debug_layer = acpi_dbg_layer;
- info_ptr->debug_level = acpi_dbg_level;
+ info_ptr->debug_layer = acpi_dbg_layer;
+ info_ptr->debug_level = acpi_dbg_level;
/* Current status of the ACPI tables, per table type */
@@ -464,10 +432,10 @@ acpi_get_system_info (
info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_system_info);
+EXPORT_SYMBOL(acpi_get_system_info);
/*****************************************************************************
*
@@ -485,9 +453,7 @@ EXPORT_SYMBOL(acpi_get_system_info);
****************************************************************************/
acpi_status
-acpi_install_initialization_handler (
- acpi_init_handler handler,
- u32 function)
+acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
{
if (!handler) {
@@ -502,7 +468,7 @@ acpi_install_initialization_handler (
return AE_OK;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
/*****************************************************************************
*
@@ -516,19 +482,13 @@ acpi_install_initialization_handler (
*
****************************************************************************/
-acpi_status
-acpi_purge_cached_objects (
- void)
+acpi_status acpi_purge_cached_objects(void)
{
- ACPI_FUNCTION_TRACE ("acpi_purge_cached_objects");
-
-
-#ifdef ACPI_ENABLE_OBJECT_CACHE
- acpi_ut_delete_generic_state_cache ();
- acpi_ut_delete_object_cache ();
- acpi_ds_delete_walk_state_cache ();
- acpi_ps_delete_parse_cache ();
-#endif
+ ACPI_FUNCTION_TRACE("acpi_purge_cached_objects");
- return_ACPI_STATUS (AE_OK);
+ (void)acpi_os_purge_cache(acpi_gbl_state_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_operand_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);
+ (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 1ce2047c3804..6458c47f7ac2 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -30,15 +30,12 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("acpi_utils")
-
+ACPI_MODULE_NAME("acpi_utils")
/* --------------------------------------------------------------------------
Object Evaluation Helpers
-------------------------------------------------------------------------- */
-
#ifdef ACPI_DEBUG_OUTPUT
#define acpi_util_eval_error(h,p,s) {\
char prefix[80] = {'\0'};\
@@ -49,26 +46,24 @@ ACPI_MODULE_NAME ("acpi_utils")
#else
#define acpi_util_eval_error(h,p,s)
#endif
-
-
acpi_status
-acpi_extract_package (
- union acpi_object *package,
- struct acpi_buffer *format,
- struct acpi_buffer *buffer)
+acpi_extract_package(union acpi_object *package,
+ struct acpi_buffer *format, struct acpi_buffer *buffer)
{
- u32 size_required = 0;
- u32 tail_offset = 0;
- char *format_string = NULL;
- u32 format_count = 0;
- u32 i = 0;
- u8 *head = NULL;
- u8 *tail = NULL;
+ u32 size_required = 0;
+ u32 tail_offset = 0;
+ char *format_string = NULL;
+ u32 format_count = 0;
+ u32 i = 0;
+ u8 *head = NULL;
+ u8 *tail = NULL;
ACPI_FUNCTION_TRACE("acpi_extract_package");
- if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n"));
+ if (!package || (package->type != ACPI_TYPE_PACKAGE)
+ || (package->package.count < 1)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid 'package' argument\n"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -82,18 +77,20 @@ acpi_extract_package (
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- format_count = (format->length/sizeof(char)) - 1;
+ format_count = (format->length / sizeof(char)) - 1;
if (format_count > package->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Format specifies more objects [%d] than exist in package [%d].",
+ format_count, package->package.count));
return_ACPI_STATUS(AE_BAD_DATA);
}
- format_string = (char*)format->pointer;
+ format_string = (char *)format->pointer;
/*
* Calculate size_required.
*/
- for (i=0; i<format_count; i++) {
+ for (i = 0; i < format_count; i++) {
union acpi_object *element = &(package->package.elements[i]);
@@ -110,11 +107,15 @@ acpi_extract_package (
tail_offset += sizeof(acpi_integer);
break;
case 'S':
- size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char);
- tail_offset += sizeof(char*);
+ size_required +=
+ sizeof(char *) + sizeof(acpi_integer) +
+ sizeof(char);
+ tail_offset += sizeof(char *);
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid package element [%d]: got number, expecing [%c].\n",
+ i, format_string[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
@@ -124,15 +125,22 @@ acpi_extract_package (
case ACPI_TYPE_BUFFER:
switch (format_string[i]) {
case 'S':
- size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char);
- tail_offset += sizeof(char*);
+ size_required +=
+ sizeof(char *) +
+ (element->string.length * sizeof(char)) +
+ sizeof(char);
+ tail_offset += sizeof(char *);
break;
case 'B':
- size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8));
- tail_offset += sizeof(u8*);
+ size_required +=
+ sizeof(u8 *) +
+ (element->buffer.length * sizeof(u8));
+ tail_offset += sizeof(u8 *);
break;
default:
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i]));
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Invalid package element [%d] got string/buffer, expecing [%c].\n",
+ i, format_string[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
@@ -140,7 +148,9 @@ acpi_extract_package (
case ACPI_TYPE_PACKAGE:
default:
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found unsupported element at index=%d\n",
+ i));
/* TBD: handle nested packages... */
return_ACPI_STATUS(AE_SUPPORT);
break;
@@ -153,8 +163,7 @@ acpi_extract_package (
if (buffer->length < size_required) {
buffer->length = size_required;
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
- }
- else if (buffer->length != size_required || !buffer->pointer) {
+ } else if (buffer->length != size_required || !buffer->pointer) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -164,7 +173,7 @@ acpi_extract_package (
/*
* Extract package data.
*/
- for (i=0; i<format_count; i++) {
+ for (i = 0; i < format_count; i++) {
u8 **pointer = NULL;
union acpi_object *element = &(package->package.elements[i]);
@@ -178,14 +187,16 @@ acpi_extract_package (
case ACPI_TYPE_INTEGER:
switch (format_string[i]) {
case 'N':
- *((acpi_integer*)head) = element->integer.value;
+ *((acpi_integer *) head) =
+ element->integer.value;
head += sizeof(acpi_integer);
break;
case 'S':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- *((acpi_integer*)tail) = element->integer.value;
- head += sizeof(acpi_integer*);
+ *((acpi_integer *) tail) =
+ element->integer.value;
+ head += sizeof(acpi_integer *);
tail += sizeof(acpi_integer);
/* NULL terminate string */
*tail = (char)0;
@@ -201,20 +212,22 @@ acpi_extract_package (
case ACPI_TYPE_BUFFER:
switch (format_string[i]) {
case 'S':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- memcpy(tail, element->string.pointer, element->string.length);
- head += sizeof(char*);
+ memcpy(tail, element->string.pointer,
+ element->string.length);
+ head += sizeof(char *);
tail += element->string.length * sizeof(char);
/* NULL terminate string */
*tail = (char)0;
tail += sizeof(char);
break;
case 'B':
- pointer = (u8**)head;
+ pointer = (u8 **) head;
*pointer = tail;
- memcpy(tail, element->buffer.pointer, element->buffer.length);
- head += sizeof(u8*);
+ memcpy(tail, element->buffer.pointer,
+ element->buffer.length);
+ head += sizeof(u8 *);
tail += element->buffer.length * sizeof(u8);
break;
default:
@@ -233,19 +246,17 @@ acpi_extract_package (
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_extract_package);
+EXPORT_SYMBOL(acpi_extract_package);
acpi_status
-acpi_evaluate_integer (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- unsigned long *data)
+acpi_evaluate_integer(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments, unsigned long *data)
{
- acpi_status status = AE_OK;
- union acpi_object *element;
- struct acpi_buffer buffer = {0,NULL};
+ acpi_status status = AE_OK;
+ union acpi_object *element;
+ struct acpi_buffer buffer = { 0, NULL };
ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
@@ -253,7 +264,7 @@ acpi_evaluate_integer (
return_ACPI_STATUS(AE_BAD_PARAMETER);
element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if(!element)
+ if (!element)
return_ACPI_STATUS(AE_NO_MEMORY);
memset(element, 0, sizeof(union acpi_object));
@@ -277,20 +288,18 @@ acpi_evaluate_integer (
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_evaluate_integer);
+EXPORT_SYMBOL(acpi_evaluate_integer);
#if 0
acpi_status
-acpi_evaluate_string (
- acpi_handle handle,
- acpi_string pathname,
- acpi_object_list *arguments,
- acpi_string *data)
+acpi_evaluate_string(acpi_handle handle,
+ acpi_string pathname,
+ acpi_object_list * arguments, acpi_string * data)
{
- acpi_status status = AE_OK;
- acpi_object *element = NULL;
- acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_status status = AE_OK;
+ acpi_object *element = NULL;
+ acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
ACPI_FUNCTION_TRACE("acpi_evaluate_string");
@@ -305,9 +314,9 @@ acpi_evaluate_string (
element = (acpi_object *) buffer.pointer;
- if ((element->type != ACPI_TYPE_STRING)
- || (element->type != ACPI_TYPE_BUFFER)
- || !element->string.length) {
+ if ((element->type != ACPI_TYPE_STRING)
+ || (element->type != ACPI_TYPE_BUFFER)
+ || !element->string.length) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
return_ACPI_STATUS(AE_BAD_DATA);
}
@@ -329,19 +338,17 @@ acpi_evaluate_string (
}
#endif
-
acpi_status
-acpi_evaluate_reference (
- acpi_handle handle,
- acpi_string pathname,
- struct acpi_object_list *arguments,
- struct acpi_handle_list *list)
+acpi_evaluate_reference(acpi_handle handle,
+ acpi_string pathname,
+ struct acpi_object_list *arguments,
+ struct acpi_handle_list *list)
{
- acpi_status status = AE_OK;
- union acpi_object *package = NULL;
- union acpi_object *element = NULL;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- u32 i = 0;
+ acpi_status status = AE_OK;
+ union acpi_object *package = NULL;
+ union acpi_object *element = NULL;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ u32 i = 0;
ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
@@ -355,28 +362,28 @@ acpi_evaluate_reference (
if (ACPI_FAILURE(status))
goto end;
- package = (union acpi_object *) buffer.pointer;
+ package = (union acpi_object *)buffer.pointer;
if ((buffer.length == 0) || !package) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "No return object (len %X ptr %p)\n",
- (unsigned)buffer.length, package));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "No return object (len %X ptr %p)\n",
+ (unsigned)buffer.length, package));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
}
if (package->type != ACPI_TYPE_PACKAGE) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Expecting a [Package], found type %X\n",
- package->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting a [Package], found type %X\n",
+ package->type));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
}
if (!package->package.count) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "[Package] has zero elements (%p)\n",
- package));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "[Package] has zero elements (%p)\n",
+ package));
status = AE_BAD_DATA;
acpi_util_eval_error(handle, pathname, status);
goto end;
@@ -395,9 +402,9 @@ acpi_evaluate_reference (
if (element->type != ACPI_TYPE_ANY) {
status = AE_BAD_DATA;
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Expecting a [Reference] package element, found type %X\n",
- element->type));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Expecting a [Reference] package element, found type %X\n",
+ element->type));
acpi_util_eval_error(handle, pathname, status);
break;
}
@@ -406,10 +413,10 @@ acpi_evaluate_reference (
list->handles[i] = element->reference.handle;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
- list->handles[i]));
+ list->handles[i]));
}
-end:
+ end:
if (ACPI_FAILURE(status)) {
list->count = 0;
//kfree(list->handles);
@@ -419,5 +426,5 @@ end:
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_evaluate_reference);
+EXPORT_SYMBOL(acpi_evaluate_reference);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 2cf264fd52e0..e383d6109ae1 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -53,21 +53,20 @@
#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
-
#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
#define ACPI_VIDEO_HEAD_END (~0u)
-
#define _COMPONENT ACPI_VIDEO_COMPONENT
-ACPI_MODULE_NAME ("acpi_video")
+ACPI_MODULE_NAME("acpi_video")
-MODULE_AUTHOR("Bruno Ducrot");
+ MODULE_AUTHOR("Bruno Ducrot");
MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
MODULE_LICENSE("GPL");
-static int acpi_video_bus_add (struct acpi_device *device);
-static int acpi_video_bus_remove (struct acpi_device *device, int type);
-static int acpi_video_bus_match (struct acpi_device *device, struct acpi_driver *driver);
+static int acpi_video_bus_add(struct acpi_device *device);
+static int acpi_video_bus_remove(struct acpi_device *device, int type);
+static int acpi_video_bus_match(struct acpi_device *device,
+ struct acpi_driver *driver);
static struct acpi_driver acpi_video_bus = {
.name = ACPI_VIDEO_DRIVER_NAME,
@@ -76,187 +75,192 @@ static struct acpi_driver acpi_video_bus = {
.add = acpi_video_bus_add,
.remove = acpi_video_bus_remove,
.match = acpi_video_bus_match,
- },
+ },
};
struct acpi_video_bus_flags {
- u8 multihead:1; /* can switch video heads */
- u8 rom:1; /* can retrieve a video rom */
- u8 post:1; /* can configure the head to */
- u8 reserved:5;
+ u8 multihead:1; /* can switch video heads */
+ u8 rom:1; /* can retrieve a video rom */
+ u8 post:1; /* can configure the head to */
+ u8 reserved:5;
};
struct acpi_video_bus_cap {
- u8 _DOS:1; /*Enable/Disable output switching*/
- u8 _DOD:1; /*Enumerate all devices attached to display adapter*/
- u8 _ROM:1; /*Get ROM Data*/
- u8 _GPD:1; /*Get POST Device*/
- u8 _SPD:1; /*Set POST Device*/
- u8 _VPO:1; /*Video POST Options*/
- u8 reserved:2;
+ u8 _DOS:1; /*Enable/Disable output switching */
+ u8 _DOD:1; /*Enumerate all devices attached to display adapter */
+ u8 _ROM:1; /*Get ROM Data */
+ u8 _GPD:1; /*Get POST Device */
+ u8 _SPD:1; /*Set POST Device */
+ u8 _VPO:1; /*Video POST Options */
+ u8 reserved:2;
};
-struct acpi_video_device_attrib{
- u32 display_index:4; /* A zero-based instance of the Display*/
- u32 display_port_attachment:4; /*This field differenates displays type*/
- u32 display_type:4; /*Describe the specific type in use*/
- u32 vendor_specific:4; /*Chipset Vendor Specifi*/
- u32 bios_can_detect:1; /*BIOS can detect the device*/
- u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
- the VGA device.*/
- u32 pipe_id:3; /*For VGA multiple-head devices.*/
- u32 reserved:10; /*Must be 0*/
- u32 device_id_scheme:1; /*Device ID Scheme*/
+struct acpi_video_device_attrib {
+ u32 display_index:4; /* A zero-based instance of the Display */
+ u32 display_port_attachment:4; /*This field differenates displays type */
+ u32 display_type:4; /*Describe the specific type in use */
+ u32 vendor_specific:4; /*Chipset Vendor Specifi */
+ u32 bios_can_detect:1; /*BIOS can detect the device */
+ u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
+ the VGA device. */
+ u32 pipe_id:3; /*For VGA multiple-head devices. */
+ u32 reserved:10; /*Must be 0 */
+ u32 device_id_scheme:1; /*Device ID Scheme */
};
struct acpi_video_enumerated_device {
union {
u32 int_val;
- struct acpi_video_device_attrib attrib;
+ struct acpi_video_device_attrib attrib;
} value;
struct acpi_video_device *bind_info;
};
struct acpi_video_bus {
- acpi_handle handle;
- u8 dos_setting;
+ acpi_handle handle;
+ u8 dos_setting;
struct acpi_video_enumerated_device *attached_array;
- u8 attached_count;
- struct acpi_video_bus_cap cap;
+ u8 attached_count;
+ struct acpi_video_bus_cap cap;
struct acpi_video_bus_flags flags;
- struct semaphore sem;
- struct list_head video_device_list;
- struct proc_dir_entry *dir;
+ struct semaphore sem;
+ struct list_head video_device_list;
+ struct proc_dir_entry *dir;
};
struct acpi_video_device_flags {
- u8 crt:1;
- u8 lcd:1;
- u8 tvout:1;
- u8 bios:1;
- u8 unknown:1;
- u8 reserved:3;
+ u8 crt:1;
+ u8 lcd:1;
+ u8 tvout:1;
+ u8 bios:1;
+ u8 unknown:1;
+ u8 reserved:3;
};
struct acpi_video_device_cap {
- u8 _ADR:1; /*Return the unique ID */
- u8 _BCL:1; /*Query list of brightness control levels supported*/
- u8 _BCM:1; /*Set the brightness level*/
- u8 _DDC:1; /*Return the EDID for this device*/
- u8 _DCS:1; /*Return status of output device*/
- u8 _DGS:1; /*Query graphics state*/
- u8 _DSS:1; /*Device state set*/
- u8 _reserved:1;
+ u8 _ADR:1; /*Return the unique ID */
+ u8 _BCL:1; /*Query list of brightness control levels supported */
+ u8 _BCM:1; /*Set the brightness level */
+ u8 _DDC:1; /*Return the EDID for this device */
+ u8 _DCS:1; /*Return status of output device */
+ u8 _DGS:1; /*Query graphics state */
+ u8 _DSS:1; /*Device state set */
+ u8 _reserved:1;
};
struct acpi_video_device_brightness {
- int curr;
- int count;
- int *levels;
+ int curr;
+ int count;
+ int *levels;
};
struct acpi_video_device {
- acpi_handle handle;
- unsigned long device_id;
- struct acpi_video_device_flags flags;
- struct acpi_video_device_cap cap;
- struct list_head entry;
- struct acpi_video_bus *video;
- struct acpi_device *dev;
+ acpi_handle handle;
+ unsigned long device_id;
+ struct acpi_video_device_flags flags;
+ struct acpi_video_device_cap cap;
+ struct list_head entry;
+ struct acpi_video_bus *video;
+ struct acpi_device *dev;
struct acpi_video_device_brightness *brightness;
};
-
/* bus */
static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_info_fops = {
- .open = acpi_video_bus_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_ROM_fops = {
- .open = acpi_video_bus_ROM_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_ROM_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_bus_POST_info_fops = {
- .open = acpi_video_bus_POST_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_POST_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_POST_fops = {
- .open = acpi_video_bus_POST_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_POST_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-
static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_video_bus_DOS_fops = {
- .open = acpi_video_bus_DOS_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_bus_DOS_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
/* device */
-static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_info_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_info_fops = {
- .open = acpi_video_device_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_state_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_state_fops = {
- .open = acpi_video_device_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_brightness_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_brightness_fops = {
- .open = acpi_video_device_brightness_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_brightness_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file);
+static int acpi_video_device_EDID_open_fs(struct inode *inode,
+ struct file *file);
static struct file_operations acpi_video_device_EDID_fops = {
- .open = acpi_video_device_EDID_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ .open = acpi_video_device_EDID_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
-static char device_decode[][30] = {
+static char device_decode[][30] = {
"motherboard VGA device",
"PCI VGA device",
"AGP VGA device",
"UNKNOWN",
};
-static void acpi_video_device_notify ( acpi_handle handle, u32 event, void *data);
-static void acpi_video_device_rebind( struct acpi_video_bus *video);
-static void acpi_video_device_bind( struct acpi_video_bus *video, struct acpi_video_device *device);
+static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
+static void acpi_video_device_rebind(struct acpi_video_bus *video);
+static void acpi_video_device_bind(struct acpi_video_bus *video,
+ struct acpi_video_device *device);
static int acpi_video_device_enumerate(struct acpi_video_bus *video);
-static int acpi_video_switch_output( struct acpi_video_bus *video, int event);
-static int acpi_video_get_next_level( struct acpi_video_device *device, u32 level_current,u32 event);
-static void acpi_video_switch_brightness ( struct acpi_video_device *device, int event);
-
+static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
+static int acpi_video_get_next_level(struct acpi_video_device *device,
+ u32 level_current, u32 event);
+static void acpi_video_switch_brightness(struct acpi_video_device *device,
+ int event);
/* --------------------------------------------------------------------------
Video Management
@@ -265,11 +269,9 @@ static void acpi_video_switch_brightness ( struct acpi_video_device *device, int
/* device */
static int
-acpi_video_device_query (
- struct acpi_video_device *device,
- unsigned long *state)
+acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_query");
status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
@@ -277,11 +279,10 @@ acpi_video_device_query (
}
static int
-acpi_video_device_get_state (
- struct acpi_video_device *device,
- unsigned long *state)
+acpi_video_device_get_state(struct acpi_video_device *device,
+ unsigned long *state)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_get_state");
@@ -291,31 +292,28 @@ acpi_video_device_get_state (
}
static int
-acpi_video_device_set_state (
- struct acpi_video_device *device,
- int state)
+acpi_video_device_set_state(struct acpi_video_device *device, int state)
{
- int status;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
+ unsigned long ret;
ACPI_FUNCTION_TRACE("acpi_video_device_set_state");
arg0.integer.value = state;
- status = acpi_evaluate_integer(device->handle, "_DSS", &args, NULL);
+ status = acpi_evaluate_integer(device->handle, "_DSS", &args, &ret);
return_VALUE(status);
}
static int
-acpi_video_device_lcd_query_levels (
- struct acpi_video_device *device,
- union acpi_object **levels)
+acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
+ union acpi_object **levels)
{
- int status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *obj;
-
+ int status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_query_levels");
@@ -324,7 +322,7 @@ acpi_video_device_lcd_query_levels (
status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
if (!ACPI_SUCCESS(status))
return_VALUE(status);
- obj = (union acpi_object *) buffer.pointer;
+ obj = (union acpi_object *)buffer.pointer;
if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
status = -EFAULT;
@@ -335,7 +333,7 @@ acpi_video_device_lcd_query_levels (
return_VALUE(0);
-err:
+ err:
if (buffer.pointer)
kfree(buffer.pointer);
@@ -343,13 +341,11 @@ err:
}
static int
-acpi_video_device_lcd_set_level (
- struct acpi_video_device *device,
- int level)
+acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
{
- int status;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_set_level");
@@ -361,11 +357,10 @@ acpi_video_device_lcd_set_level (
}
static int
-acpi_video_device_lcd_get_level_current (
- struct acpi_video_device *device,
- unsigned long *level)
+acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
+ unsigned long *level)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_device_lcd_get_level_current");
status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
@@ -374,16 +369,14 @@ acpi_video_device_lcd_get_level_current (
}
static int
-acpi_video_device_EDID (
- struct acpi_video_device *device,
- union acpi_object **edid,
- ssize_t length)
+acpi_video_device_EDID(struct acpi_video_device *device,
+ union acpi_object **edid, ssize_t length)
{
- int status;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *obj;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *obj;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_device_get_EDID");
@@ -402,7 +395,7 @@ acpi_video_device_EDID (
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- obj = (union acpi_object *) buffer.pointer;
+ obj = (union acpi_object *)buffer.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER)
*edid = obj;
@@ -415,18 +408,15 @@ acpi_video_device_EDID (
return_VALUE(status);
}
-
/* bus */
static int
-acpi_video_bus_set_POST (
- struct acpi_video_bus *video,
- unsigned long option)
+acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
{
- int status;
- unsigned long tmp;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ int status;
+ unsigned long tmp;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_bus_set_POST");
@@ -434,15 +424,13 @@ acpi_video_bus_set_POST (
status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
if (ACPI_SUCCESS(status))
- status = tmp ? (-EINVAL):(AE_OK);
+ status = tmp ? (-EINVAL) : (AE_OK);
return_VALUE(status);
}
static int
-acpi_video_bus_get_POST (
- struct acpi_video_bus *video,
- unsigned long *id)
+acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
{
int status;
@@ -454,11 +442,10 @@ acpi_video_bus_get_POST (
}
static int
-acpi_video_bus_POST_options (
- struct acpi_video_bus *video,
- unsigned long *options)
+acpi_video_bus_POST_options(struct acpi_video_bus *video,
+ unsigned long *options)
{
- int status;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_options");
status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
@@ -489,18 +476,15 @@ acpi_video_bus_POST_options (
*/
static int
-acpi_video_bus_DOS(
- struct acpi_video_bus *video,
- int bios_flag,
- int lcd_flag)
+acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
{
- acpi_integer status = 0;
- union acpi_object arg0 = {ACPI_TYPE_INTEGER};
- struct acpi_object_list args = {1, &arg0};
+ acpi_integer status = 0;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
ACPI_FUNCTION_TRACE("acpi_video_bus_DOS");
- if (bios_flag < 0 || bios_flag >3 || lcd_flag < 0 || lcd_flag > 1){
+ if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
status = -1;
goto Failed;
}
@@ -508,7 +492,7 @@ acpi_video_bus_DOS(
video->dos_setting = arg0.integer.value;
acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
-Failed:
+ Failed:
return_VALUE(status);
}
@@ -523,10 +507,9 @@ Failed:
* device.
*/
-static void
-acpi_video_device_find_cap (struct acpi_video_device *device)
+static void acpi_video_device_find_cap(struct acpi_video_device *device)
{
- acpi_integer status;
+ acpi_integer status;
acpi_handle h_dummy1;
int i;
union acpi_object *obj = NULL;
@@ -534,27 +517,27 @@ acpi_video_device_find_cap (struct acpi_video_device *device)
ACPI_FUNCTION_TRACE("acpi_video_device_find_cap");
- memset( &device->cap, 0, 4);
+ memset(&device->cap, 0, 4);
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
device->cap._ADR = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
- device->cap._BCL= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
+ device->cap._BCL = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
- device->cap._BCM= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
+ device->cap._BCM = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
- device->cap._DDC= 1;
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
+ device->cap._DDC = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
device->cap._DCS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
device->cap._DGS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
device->cap._DSS = 1;
}
@@ -563,34 +546,38 @@ acpi_video_device_find_cap (struct acpi_video_device *device)
if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
int count = 0;
union acpi_object *o;
-
+
br = kmalloc(sizeof(*br), GFP_KERNEL);
if (!br) {
printk(KERN_ERR "can't allocate memory\n");
} else {
memset(br, 0, sizeof(*br));
br->levels = kmalloc(obj->package.count *
- sizeof *(br->levels), GFP_KERNEL);
+ sizeof *(br->levels), GFP_KERNEL);
if (!br->levels)
goto out;
for (i = 0; i < obj->package.count; i++) {
- o = (union acpi_object *) &obj->package.elements[i];
+ o = (union acpi_object *)&obj->package.
+ elements[i];
if (o->type != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid data\n"));
continue;
}
br->levels[count] = (u32) o->integer.value;
count++;
}
-out:
+ out:
if (count < 2) {
kfree(br->levels);
kfree(br);
} else {
br->count = count;
device->brightness = br;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "found %d brightness levels\n",
+ count));
}
}
}
@@ -610,28 +597,27 @@ out:
* Find out all required AML method defined under the video bus device.
*/
-static void
-acpi_video_bus_find_cap (struct acpi_video_bus *video)
+static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
{
- acpi_handle h_dummy1;
+ acpi_handle h_dummy1;
- memset(&video->cap ,0, 4);
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
+ memset(&video->cap, 0, 4);
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
video->cap._DOS = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
video->cap._DOD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
video->cap._ROM = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
video->cap._GPD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
video->cap._SPD = 1;
}
- if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
+ if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
video->cap._VPO = 1;
}
}
@@ -641,12 +627,9 @@ acpi_video_bus_find_cap (struct acpi_video_bus *video)
* support the desired features
*/
-static int
-acpi_video_bus_check (
- struct acpi_video_bus *video)
+static int acpi_video_bus_check(struct acpi_video_bus *video)
{
- acpi_status status = -ENOENT;
-
+ acpi_status status = -ENOENT;
ACPI_FUNCTION_TRACE("acpi_video_bus_check");
@@ -658,19 +641,19 @@ acpi_video_bus_check (
*/
/* Does this device able to support video switching ? */
- if(video->cap._DOS){
+ if (video->cap._DOS) {
video->flags.multihead = 1;
status = 0;
}
/* Does this device able to retrieve a retrieve a video ROM ? */
- if(video->cap._ROM){
+ if (video->cap._ROM) {
video->flags.rom = 1;
status = 0;
}
/* Does this device able to configure which video device to POST ? */
- if(video->cap._GPD && video->cap._SPD && video->cap._VPO){
+ if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
video->flags.post = 1;
status = 0;
}
@@ -682,16 +665,14 @@ acpi_video_bus_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-static struct proc_dir_entry *acpi_video_dir;
+static struct proc_dir_entry *acpi_video_dir;
/* video devices */
-static int
-acpi_video_device_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_device_info_seq_show");
@@ -709,30 +690,25 @@ acpi_video_device_info_seq_show (
else
seq_printf(seq, "UNKNOWN\n");
- seq_printf(seq,"known by bios: %s\n",
- dev->flags.bios ? "yes":"no");
+ seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_device_info_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_info_seq_show,
PDE(inode)->data);
}
-static int
-acpi_video_device_state_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
{
- int status;
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- unsigned long state;
+ int status;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ unsigned long state;
ACPI_FUNCTION_TRACE("acpi_video_device_state_seq_show");
@@ -753,31 +729,27 @@ acpi_video_device_state_seq_show (
else
seq_printf(seq, "<not supported>\n");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_device_state_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_state_seq_show,
PDE(inode)->data);
}
static ssize_t
-acpi_video_device_write_state (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_device_write_state(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
- char str[12] = {0};
- u32 state = 0;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ char str[12] = { 0 };
+ u32 state = 0;
ACPI_FUNCTION_TRACE("acpi_video_device_write_state");
@@ -789,7 +761,7 @@ acpi_video_device_write_state (
str[count] = 0;
state = simple_strtoul(str, NULL, 0);
- state &= ((1ul<<31) | (1ul<<30) | (1ul<<0));
+ state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
status = acpi_video_device_set_state(dev, state);
@@ -800,12 +772,11 @@ acpi_video_device_write_state (
}
static int
-acpi_video_device_brightness_seq_show (
- struct seq_file *seq,
- void *offset)
+acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- int i;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_brightness_seq_show");
@@ -823,26 +794,22 @@ acpi_video_device_brightness_seq_show (
}
static int
-acpi_video_device_brightness_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_brightness_seq_show,
PDE(inode)->data);
}
static ssize_t
-acpi_video_device_write_brightness (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_device_write_brightness(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
- char str[4] = {0};
- unsigned int level = 0;
- int i;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ char str[4] = { 0 };
+ unsigned int level = 0;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
@@ -854,14 +821,15 @@ acpi_video_device_write_brightness (
str[count] = 0;
level = simple_strtoul(str, NULL, 0);
-
+
if (level > 100)
return_VALUE(-EFAULT);
/* validate though the list of available levels */
for (i = 0; i < dev->brightness->count; i++)
if (level == dev->brightness->levels[i]) {
- if (ACPI_SUCCESS(acpi_video_device_lcd_set_level(dev, level)))
+ if (ACPI_SUCCESS
+ (acpi_video_device_lcd_set_level(dev, level)))
dev->brightness->curr = level;
break;
}
@@ -869,24 +837,22 @@ acpi_video_device_write_brightness (
return_VALUE(count);
}
-static int
-acpi_video_device_EDID_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
- int status;
- int i;
- union acpi_object *edid = NULL;
+ struct acpi_video_device *dev =
+ (struct acpi_video_device *)seq->private;
+ int status;
+ int i;
+ union acpi_object *edid = NULL;
ACPI_FUNCTION_TRACE("acpi_video_device_EDID_seq_show");
if (!dev)
goto out;
- status = acpi_video_device_EDID (dev, &edid, 128);
+ status = acpi_video_device_EDID(dev, &edid, 128);
if (ACPI_FAILURE(status)) {
- status = acpi_video_device_EDID (dev, &edid, 256);
+ status = acpi_video_device_EDID(dev, &edid, 256);
}
if (ACPI_FAILURE(status)) {
@@ -898,7 +864,7 @@ acpi_video_device_EDID_seq_show (
seq_putc(seq, edid->buffer.pointer[i]);
}
-out:
+ out:
if (!edid)
seq_printf(seq, "<not supported>\n");
else
@@ -908,20 +874,15 @@ out:
}
static int
-acpi_video_device_EDID_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_device_EDID_seq_show,
PDE(inode)->data);
}
-
-static int
-acpi_video_device_add_fs (
- struct acpi_device *device)
+static int acpi_video_device_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
+ struct proc_dir_entry *entry = NULL;
struct acpi_video_device *vid_dev;
ACPI_FUNCTION_TRACE("acpi_video_device_add_fs");
@@ -929,13 +890,13 @@ acpi_video_device_add_fs (
if (!device)
return_VALUE(-ENODEV);
- vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
+ vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
if (!vid_dev)
return_VALUE(-ENODEV);
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- vid_dev->video->dir);
+ vid_dev->video->dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
acpi_device_dir(device)->owner = THIS_MODULE;
@@ -945,7 +906,7 @@ acpi_video_device_add_fs (
entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'info' fs entry\n"));
+ "Unable to create 'info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_info_fops;
entry->data = acpi_driver_data(device);
@@ -953,10 +914,12 @@ acpi_video_device_add_fs (
}
/* 'state' [R/W] */
- entry = create_proc_entry("state", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'state' fs entry\n"));
+ "Unable to create 'state' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_state_fops;
entry->proc_fops->write = acpi_video_device_write_state;
@@ -965,10 +928,12 @@ acpi_video_device_add_fs (
}
/* 'brightness' [R/W] */
- entry = create_proc_entry("brightness", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'brightness' fs entry\n"));
+ "Unable to create 'brightness' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_brightness_fops;
entry->proc_fops->write = acpi_video_device_write_brightness;
@@ -980,7 +945,7 @@ acpi_video_device_add_fs (
entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create 'brightness' fs entry\n"));
+ "Unable to create 'brightness' fs entry\n"));
else {
entry->proc_fops = &acpi_video_device_EDID_fops;
entry->data = acpi_driver_data(device);
@@ -990,14 +955,12 @@ acpi_video_device_add_fs (
return_VALUE(0);
}
-static int
-acpi_video_device_remove_fs (
- struct acpi_device *device)
+static int acpi_video_device_remove_fs(struct acpi_device *device)
{
struct acpi_video_device *vid_dev;
ACPI_FUNCTION_TRACE("acpi_video_device_remove_fs");
- vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
+ vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
return_VALUE(-ENODEV);
@@ -1006,22 +969,17 @@ acpi_video_device_remove_fs (
remove_proc_entry("state", acpi_device_dir(device));
remove_proc_entry("brightness", acpi_device_dir(device));
remove_proc_entry("EDID", acpi_device_dir(device));
- remove_proc_entry(acpi_device_bid(device),
- vid_dev->video->dir);
+ remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
acpi_device_dir(device) = NULL;
}
return_VALUE(0);
}
-
/* video bus */
-static int
-acpi_video_bus_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_info_seq_show");
@@ -1029,30 +987,25 @@ acpi_video_bus_info_seq_show (
goto end;
seq_printf(seq, "Switching heads: %s\n",
- video->flags.multihead ? "yes":"no");
+ video->flags.multihead ? "yes" : "no");
seq_printf(seq, "Video ROM: %s\n",
- video->flags.rom ? "yes":"no");
+ video->flags.rom ? "yes" : "no");
seq_printf(seq, "Device to be POSTed on boot: %s\n",
- video->flags.post ? "yes":"no");
+ video->flags.post ? "yes" : "no");
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_info_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_info_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_info_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_ROM_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_ROM_seq_show");
@@ -1062,26 +1015,20 @@ acpi_video_bus_ROM_seq_show (
printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
seq_printf(seq, "<TODO>\n");
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_ROM_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
}
-static int
-acpi_video_bus_POST_info_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
- unsigned long options;
- int status;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ unsigned long options;
+ int status;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_info_seq_show");
@@ -1091,8 +1038,10 @@ acpi_video_bus_POST_info_seq_show (
status = acpi_video_bus_POST_options(video, &options);
if (ACPI_SUCCESS(status)) {
if (!(options & 1)) {
- printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n");
- printk(KERN_WARNING PREFIX "This indicate a BIOS bug. Please contact the manufacturer.\n");
+ printk(KERN_WARNING PREFIX
+ "The motherboard VGA device is not listed as a possible POST device.\n");
+ printk(KERN_WARNING PREFIX
+ "This indicate a BIOS bug. Please contact the manufacturer.\n");
}
printk("%lx\n", options);
seq_printf(seq, "can POST: <intgrated video>");
@@ -1103,89 +1052,74 @@ acpi_video_bus_POST_info_seq_show (
seq_putc(seq, '\n');
} else
seq_printf(seq, "<not supported>\n");
-end:
+ end:
return_VALUE(0);
}
static int
-acpi_video_bus_POST_info_open_fs (
- struct inode *inode,
- struct file *file)
+acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_POST_info_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_POST_info_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_POST_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
- int status;
- unsigned long id;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ int status;
+ unsigned long id;
ACPI_FUNCTION_TRACE("acpi_video_bus_POST_seq_show");
if (!video)
goto end;
- status = acpi_video_bus_get_POST (video, &id);
+ status = acpi_video_bus_get_POST(video, &id);
if (!ACPI_SUCCESS(status)) {
seq_printf(seq, "<not supported>\n");
goto end;
}
- seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
+ seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
-end:
+ end:
return_VALUE(0);
}
-static int
-acpi_video_bus_DOS_seq_show (
- struct seq_file *seq,
- void *offset)
+static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
ACPI_FUNCTION_TRACE("acpi_video_bus_DOS_seq_show");
- seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting );
+ seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
return_VALUE(0);
}
-static int
-acpi_video_bus_POST_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
{
- return single_open(file, acpi_video_bus_POST_seq_show, PDE(inode)->data);
+ return single_open(file, acpi_video_bus_POST_seq_show,
+ PDE(inode)->data);
}
-static int
-acpi_video_bus_DOS_open_fs (
- struct inode *inode,
- struct file *file)
+static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
}
static ssize_t
-acpi_video_bus_write_POST (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_bus_write_POST(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
- char str[12] = {0};
- unsigned long opt, options;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ char str[12] = { 0 };
+ unsigned long opt, options;
ACPI_FUNCTION_TRACE("acpi_video_bus_write_POST");
-
if (!video || count + 1 > sizeof str)
return_VALUE(-EINVAL);
@@ -1205,32 +1139,28 @@ acpi_video_bus_write_POST (
options |= 1;
if (options & (1ul << opt)) {
- status = acpi_video_bus_set_POST (video, opt);
+ status = acpi_video_bus_set_POST(video, opt);
if (!ACPI_SUCCESS(status))
return_VALUE(-EFAULT);
}
-
return_VALUE(count);
}
static ssize_t
-acpi_video_bus_write_DOS (
- struct file *file,
- const char __user *buffer,
- size_t count,
- loff_t *data)
+acpi_video_bus_write_DOS(struct file *file,
+ const char __user * buffer,
+ size_t count, loff_t * data)
{
- int status;
- struct seq_file *m = (struct seq_file *) file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
- char str[12] = {0};
- unsigned long opt;
+ int status;
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ char str[12] = { 0 };
+ unsigned long opt;
ACPI_FUNCTION_TRACE("acpi_video_bus_write_DOS");
-
if (!video || count + 1 > sizeof str)
return_VALUE(-EINVAL);
@@ -1242,7 +1172,7 @@ acpi_video_bus_write_DOS (
if (opt > 7)
return_VALUE(-EFAULT);
- status = acpi_video_bus_DOS (video, opt & 0x3, (opt & 0x4)>>2);
+ status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
if (!ACPI_SUCCESS(status))
return_VALUE(-EFAULT);
@@ -1250,20 +1180,18 @@ acpi_video_bus_write_DOS (
return_VALUE(count);
}
-static int
-acpi_video_bus_add_fs (
- struct acpi_device *device)
+static int acpi_video_bus_add_fs(struct acpi_device *device)
{
- struct proc_dir_entry *entry = NULL;
- struct acpi_video_bus *video;
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_add_fs");
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
- acpi_video_dir);
+ acpi_video_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
video->dir = acpi_device_dir(device);
@@ -1273,7 +1201,8 @@ acpi_video_bus_add_fs (
/* 'info' [R] */
entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'info' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_info_fops;
entry->data = acpi_driver_data(device);
@@ -1283,7 +1212,8 @@ acpi_video_bus_add_fs (
/* 'ROM' [R] */
entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'ROM' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'ROM' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_ROM_fops;
entry->data = acpi_driver_data(device);
@@ -1291,9 +1221,11 @@ acpi_video_bus_add_fs (
}
/* 'POST_info' [R] */
- entry = create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
+ entry =
+ create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST_info' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'POST_info' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_POST_info_fops;
entry->data = acpi_driver_data(device);
@@ -1301,9 +1233,12 @@ acpi_video_bus_add_fs (
}
/* 'POST' [R/W] */
- entry = create_proc_entry("POST", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
+ acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'POST' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_POST_fops;
entry->proc_fops->write = acpi_video_bus_write_POST;
@@ -1312,9 +1247,12 @@ acpi_video_bus_add_fs (
}
/* 'DOS' [R/W] */
- entry = create_proc_entry("DOS", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
+ entry =
+ create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
+ acpi_device_dir(device));
if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'DOS' fs entry\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create 'DOS' fs entry\n"));
else {
entry->proc_fops = &acpi_video_bus_DOS_fops;
entry->proc_fops->write = acpi_video_bus_write_DOS;
@@ -1325,15 +1263,13 @@ acpi_video_bus_add_fs (
return_VALUE(0);
}
-static int
-acpi_video_bus_remove_fs (
- struct acpi_device *device)
+static int acpi_video_bus_remove_fs(struct acpi_device *device)
{
- struct acpi_video_bus *video;
+ struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_remove_fs");
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
if (acpi_device_dir(device)) {
remove_proc_entry("info", acpi_device_dir(device));
@@ -1341,8 +1277,7 @@ acpi_video_bus_remove_fs (
remove_proc_entry("POST_info", acpi_device_dir(device));
remove_proc_entry("POST", acpi_device_dir(device));
remove_proc_entry("DOS", acpi_device_dir(device));
- remove_proc_entry(acpi_device_bid(device),
- acpi_video_dir);
+ remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
acpi_device_dir(device) = NULL;
}
@@ -1356,20 +1291,20 @@ acpi_video_bus_remove_fs (
/* device interface */
static int
-acpi_video_bus_get_one_device (
- struct acpi_device *device,
- struct acpi_video_bus *video)
+acpi_video_bus_get_one_device(struct acpi_device *device,
+ struct acpi_video_bus *video)
{
- unsigned long device_id;
- int status, result;
- struct acpi_video_device *data;
+ unsigned long device_id;
+ int status, result;
+ struct acpi_video_device *data;
ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
if (!device || !video)
return_VALUE(-EINVAL);
- status = acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+ status =
+ acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
if (ACPI_SUCCESS(status)) {
data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
@@ -1401,15 +1336,17 @@ acpi_video_bus_get_one_device (
data->flags.unknown = 1;
break;
}
-
+
acpi_video_device_bind(video, data);
acpi_video_device_find_cap(data);
status = acpi_install_notify_handler(data->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_device_notify, data);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_device_notify,
+ data);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
@@ -1423,7 +1360,7 @@ acpi_video_bus_get_one_device (
return_VALUE(0);
}
-end:
+ end:
return_VALUE(-ENOENT);
}
@@ -1437,15 +1374,15 @@ end:
* Enumerate the video device list of the video bus,
* bind the ids with the corresponding video devices
* under the video bus.
- */
+ */
-static void
-acpi_video_device_rebind( struct acpi_video_bus *video)
+static void acpi_video_device_rebind(struct acpi_video_bus *video)
{
- struct list_head * node, * next;
+ struct list_head *node, *next;
list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device * dev = container_of(node, struct acpi_video_device, entry);
- acpi_video_device_bind( video, dev);
+ struct acpi_video_device *dev =
+ container_of(node, struct acpi_video_device, entry);
+ acpi_video_device_bind(video, dev);
}
}
@@ -1460,21 +1397,21 @@ acpi_video_device_rebind( struct acpi_video_bus *video)
*
* Bind the ids with the corresponding video devices
* under the video bus.
- */
+ */
static void
-acpi_video_device_bind( struct acpi_video_bus *video,
- struct acpi_video_device *device)
+acpi_video_device_bind(struct acpi_video_bus *video,
+ struct acpi_video_device *device)
{
- int i;
+ int i;
ACPI_FUNCTION_TRACE("acpi_video_device_bind");
#define IDS_VAL(i) video->attached_array[i].value.int_val
#define IDS_BIND(i) video->attached_array[i].bind_info
-
- for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
- i < video->attached_count; i++) {
- if (device->device_id == (IDS_VAL(i)& 0xffff)) {
+
+ for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
+ i < video->attached_count; i++) {
+ if (device->device_id == (IDS_VAL(i) & 0xffff)) {
IDS_BIND(i) = device;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
}
@@ -1492,17 +1429,17 @@ acpi_video_device_bind( struct acpi_video_bus *video,
*
* Call _DOD to enumerate all devices attached to display adapter
*
- */
+ */
static int acpi_video_device_enumerate(struct acpi_video_bus *video)
{
- int status;
- int count;
- int i;
+ int status;
+ int count;
+ int i;
struct acpi_video_enumerated_device *active_device_list;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *dod = NULL;
- union acpi_object *obj;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *dod = NULL;
+ union acpi_object *obj;
ACPI_FUNCTION_TRACE("acpi_video_device_enumerate");
@@ -1512,7 +1449,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
return_VALUE(status);
}
- dod = (union acpi_object *) buffer.pointer;
+ dod = (union acpi_object *)buffer.pointer;
if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
status = -EFAULT;
@@ -1520,11 +1457,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
- dod->package.count));
+ dod->package.count));
- active_device_list= kmalloc(
- (1+dod->package.count)*sizeof(struct acpi_video_enumerated_device),
- GFP_KERNEL);
+ active_device_list = kmalloc((1 +
+ dod->package.count) *
+ sizeof(struct
+ acpi_video_enumerated_device),
+ GFP_KERNEL);
if (!active_device_list) {
status = -ENOMEM;
@@ -1533,25 +1472,28 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
count = 0;
for (i = 0; i < dod->package.count; i++) {
- obj = (union acpi_object *) &dod->package.elements[i];
+ obj = (union acpi_object *)&dod->package.elements[i];
if (obj->type != ACPI_TYPE_INTEGER) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
- active_device_list[i].value.int_val = ACPI_VIDEO_HEAD_INVALID;
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid _DOD data\n"));
+ active_device_list[i].value.int_val =
+ ACPI_VIDEO_HEAD_INVALID;
}
active_device_list[i].value.int_val = obj->integer.value;
active_device_list[i].bind_info = NULL;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int) obj->integer.value));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
+ (int)obj->integer.value));
count++;
}
active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
- if(video->attached_array)
+ if (video->attached_array)
kfree(video->attached_array);
-
+
video->attached_array = active_device_list;
video->attached_count = count;
-out:
+ out:
acpi_os_free(buffer.pointer);
return_VALUE(status);
}
@@ -1567,17 +1509,14 @@ out:
* 1. Find out the current active output device.
* 2. Identify the next output device to switch
* 3. call _DSS to do actual switch.
- */
+ */
-static int
-acpi_video_switch_output(
- struct acpi_video_bus *video,
- int event)
+static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
{
- struct list_head * node, * next;
- struct acpi_video_device *dev=NULL;
- struct acpi_video_device *dev_next=NULL;
- struct acpi_video_device *dev_prev=NULL;
+ struct list_head *node, *next;
+ struct acpi_video_device *dev = NULL;
+ struct acpi_video_device *dev_next = NULL;
+ struct acpi_video_device *dev_prev = NULL;
unsigned long state;
int status = 0;
@@ -1586,15 +1525,19 @@ acpi_video_switch_output(
list_for_each_safe(node, next, &video->video_device_list) {
dev = container_of(node, struct acpi_video_device, entry);
status = acpi_video_device_get_state(dev, &state);
- if (state & 0x2){
- dev_next = container_of(node->next, struct acpi_video_device, entry);
- dev_prev = container_of(node->prev, struct acpi_video_device, entry);
+ if (state & 0x2) {
+ dev_next =
+ container_of(node->next, struct acpi_video_device,
+ entry);
+ dev_prev =
+ container_of(node->prev, struct acpi_video_device,
+ entry);
goto out;
}
}
dev_next = container_of(node->next, struct acpi_video_device, entry);
dev_prev = container_of(node->prev, struct acpi_video_device, entry);
-out:
+ out:
switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE:
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
@@ -1611,21 +1554,16 @@ out:
return_VALUE(status);
}
-static int
-acpi_video_get_next_level(
- struct acpi_video_device *device,
- u32 level_current,
- u32 event)
+static int
+acpi_video_get_next_level(struct acpi_video_device *device,
+ u32 level_current, u32 event)
{
- /*Fix me*/
+ /*Fix me */
return level_current;
}
-
static void
-acpi_video_switch_brightness (
- struct acpi_video_device *device,
- int event)
+acpi_video_switch_brightness(struct acpi_video_device *device, int event)
{
unsigned long level_current, level_next;
acpi_video_device_lcd_get_level_current(device, &level_current);
@@ -1634,26 +1572,27 @@ acpi_video_switch_brightness (
}
static int
-acpi_video_bus_get_devices (
- struct acpi_video_bus *video,
- struct acpi_device *device)
+acpi_video_bus_get_devices(struct acpi_video_bus *video,
+ struct acpi_device *device)
{
- int status = 0;
- struct list_head *node, *next;
+ int status = 0;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_video_get_devices");
acpi_video_device_enumerate(video);
list_for_each_safe(node, next, &device->children) {
- struct acpi_device *dev = list_entry(node, struct acpi_device, node);
+ struct acpi_device *dev =
+ list_entry(node, struct acpi_device, node);
if (!dev)
continue;
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Cant attach device\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Cant attach device\n"));
continue;
}
@@ -1661,10 +1600,9 @@ acpi_video_bus_get_devices (
return_VALUE(status);
}
-static int
-acpi_video_bus_put_one_device(
- struct acpi_video_device *device)
+static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
{
+ acpi_status status;
struct acpi_video_bus *video;
ACPI_FUNCTION_TRACE("acpi_video_bus_put_one_device");
@@ -1679,26 +1617,33 @@ acpi_video_bus_put_one_device(
up(&video->sem);
acpi_video_device_remove_fs(device->dev);
+ status = acpi_remove_notify_handler(device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_device_notify);
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error removing notify handler\n"));
+
return_VALUE(0);
}
-static int
-acpi_video_bus_put_devices (
- struct acpi_video_bus *video)
+static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{
- int status;
- struct list_head *node, *next;
+ int status;
+ struct list_head *node, *next;
ACPI_FUNCTION_TRACE("acpi_video_bus_put_devices");
list_for_each_safe(node, next, &video->video_device_list) {
- struct acpi_video_device *data = list_entry(node, struct acpi_video_device, entry);
+ struct acpi_video_device *data =
+ list_entry(node, struct acpi_video_device, entry);
if (!data)
continue;
status = acpi_video_bus_put_one_device(data);
- if(ACPI_FAILURE(status))
- printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n");
+ if (ACPI_FAILURE(status))
+ printk(KERN_WARNING PREFIX
+ "hhuuhhuu bug in acpi video driver.\n");
if (data->brightness)
kfree(data->brightness);
@@ -1711,28 +1656,20 @@ acpi_video_bus_put_devices (
/* acpi_video interface */
-static int
-acpi_video_bus_start_devices(
- struct acpi_video_bus *video)
+static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
{
return acpi_video_bus_DOS(video, 1, 0);
}
-static int
-acpi_video_bus_stop_devices(
- struct acpi_video_bus *video)
+static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
{
return acpi_video_bus_DOS(video, 0, 1);
}
-static void
-acpi_video_bus_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *) data;
- struct acpi_device *device = NULL;
+ struct acpi_video_bus *video = (struct acpi_video_bus *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_notify");
printk("video bus notify\n");
@@ -1757,30 +1694,27 @@ acpi_video_bus_notify (
acpi_bus_generate_event(device, event, 0);
break;
- case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed.*/
- case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
- case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
+ case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
acpi_video_switch_output(video, event);
acpi_bus_generate_event(device, event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static void
-acpi_video_device_notify (
- acpi_handle handle,
- u32 event,
- void *data)
+static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_device *video_device = (struct acpi_video_device *) data;
- struct acpi_device *device = NULL;
+ struct acpi_video_device *video_device =
+ (struct acpi_video_device *)data;
+ struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_video_device_notify");
@@ -1792,36 +1726,34 @@ acpi_video_device_notify (
return_VOID;
switch (event) {
- case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
- case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
+ case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
+ case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
acpi_bus_generate_event(device, event, 0);
break;
- case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
- case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
- case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
- case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
- case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
- acpi_video_switch_brightness (video_device, event);
+ case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
+ case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
+ case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
+ case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
+ case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
+ acpi_video_switch_brightness(video_device, event);
acpi_bus_generate_event(device, event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Unsupported event [0x%x]\n", event));
+ "Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
-static int
-acpi_video_bus_add (
- struct acpi_device *device)
+static int acpi_video_bus_add(struct acpi_device *device)
{
- int result = 0;
- acpi_status status = 0;
- struct acpi_video_bus *video = NULL;
+ int result = 0;
+ acpi_status status = 0;
+ struct acpi_video_bus *video = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_add");
-
+
if (!device)
return_VALUE(-EINVAL);
@@ -1851,21 +1783,22 @@ acpi_video_bus_add (
acpi_video_bus_start_devices(video);
status = acpi_install_notify_handler(video->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify, video);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error installing notify handler\n"));
+ "Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
- ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
- video->flags.multihead ? "yes":"no",
- video->flags.rom ? "yes":"no",
- video->flags.post ? "yes":"no");
+ ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
+ video->flags.multihead ? "yes" : "no",
+ video->flags.rom ? "yes" : "no",
+ video->flags.post ? "yes" : "no");
-end:
+ end:
if (result) {
acpi_video_bus_remove_fs(device);
kfree(video);
@@ -1874,28 +1807,26 @@ end:
return_VALUE(result);
}
-static int
-acpi_video_bus_remove (
- struct acpi_device *device,
- int type)
+static int acpi_video_bus_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_video_bus *video = NULL;
+ acpi_status status = 0;
+ struct acpi_video_bus *video = NULL;
ACPI_FUNCTION_TRACE("acpi_video_bus_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
- video = (struct acpi_video_bus *) acpi_driver_data(device);
+ video = (struct acpi_video_bus *)acpi_driver_data(device);
acpi_video_bus_stop_devices(video);
status = acpi_remove_notify_handler(video->handle,
- ACPI_DEVICE_NOTIFY, acpi_video_bus_notify);
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error removing notify handler\n"));
+ "Error removing notify handler\n"));
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
@@ -1907,15 +1838,12 @@ acpi_video_bus_remove (
return_VALUE(0);
}
-
static int
-acpi_video_bus_match (
- struct acpi_device *device,
- struct acpi_driver *driver)
+acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
{
- acpi_handle h_dummy1;
- acpi_handle h_dummy2;
- acpi_handle h_dummy3;
+ acpi_handle h_dummy1;
+ acpi_handle h_dummy2;
+ acpi_handle h_dummy3;
ACPI_FUNCTION_TRACE("acpi_video_bus_match");
@@ -1941,22 +1869,19 @@ acpi_video_bus_match (
ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
return_VALUE(0);
-
return_VALUE(-ENODEV);
}
-
-static int __init
-acpi_video_init (void)
+static int __init acpi_video_init(void)
{
- int result = 0;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_video_init");
/*
- acpi_dbg_level = 0xFFFFFFFF;
- acpi_dbg_layer = 0x08000000;
- */
+ acpi_dbg_level = 0xFFFFFFFF;
+ acpi_dbg_layer = 0x08000000;
+ */
acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
if (!acpi_video_dir)
@@ -1972,8 +1897,7 @@ acpi_video_init (void)
return_VALUE(0);
}
-static void __exit
-acpi_video_exit (void)
+static void __exit acpi_video_exit(void)
{
ACPI_FUNCTION_TRACE("acpi_video_exit");
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 73c6b85299c1..4b6bf19c39c0 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -513,7 +513,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) {
// VC layer stats
atomic_inc(&atm_vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
// end of our responsability
atm_vcc->push (atm_vcc, skb);
return;
@@ -795,7 +795,7 @@ static void drain_rx_pools (amb_dev * dev) {
}
static inline void fill_rx_pool (amb_dev * dev, unsigned char pool,
- unsigned int __nocast priority)
+ gfp_t priority)
{
rx_in rx;
amb_rxq * rxq;
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index f2f01cb82cb4..57f1810fdccd 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -325,7 +325,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
result = -ENOBUFS;
goto done;
}
- do_gettimeofday(&new_skb->stamp);
+ __net_timestamp(new_skb);
memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
out_vcc->push(out_vcc,new_skb);
atomic_inc(&vcc->stats->tx);
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 10da36934769..c13c4d736ef5 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -537,7 +537,7 @@ static int rx_aal0(struct atm_vcc *vcc)
return 0;
}
skb_put(skb,length);
- skb->stamp = eni_vcc->timestamp;
+ skb_set_timestamp(skb, &eni_vcc->timestamp);
DPRINTK("got len %ld\n",length);
if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1;
eni_vcc->rxing++;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index b078fa548ebf..7f7ec288824d 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -815,7 +815,7 @@ static void process_incoming (struct fs_dev *dev, struct queue *q)
skb_put (skb, qe->p1 & 0xffff);
ATM_SKB(skb)->vcc = atm_vcc;
atomic_inc(&atm_vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb);
atm_vcc->push (atm_vcc, skb);
fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe);
@@ -1374,8 +1374,7 @@ static void reset_chip (struct fs_dev *dev)
}
}
-static void __devinit *aligned_kmalloc (int size, unsigned int __nocast flags,
- int alignment)
+static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment)
{
void *t;
@@ -1466,7 +1465,7 @@ static inline int nr_buffers_in_freepool (struct fs_dev *dev, struct freepool *f
working again after that... -- REW */
static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
- unsigned int __nocast gfp_flags)
+ gfp_t gfp_flags)
{
struct FS_BPENTRY *qe, *ne;
struct sk_buff *skb;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 5f702199543a..14f6a6201da3 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -178,14 +178,12 @@ fore200e_irq_itoa(int irq)
static void*
-fore200e_kmalloc(int size, int flags)
+fore200e_kmalloc(int size, gfp_t flags)
{
- void* chunk = kmalloc(size, flags);
+ void *chunk = kzalloc(size, flags);
- if (chunk)
- memset(chunk, 0x00, size);
- else
- printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
+ if (!chunk)
+ printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
return chunk;
}
@@ -1176,7 +1174,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
return -ENOMEM;
}
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#ifdef FORE200E_52BYTE_AAL0_SDU
if (cell_header) {
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 28250c9b32d6..fde9334059af 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1886,7 +1886,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
if (rx_skb_reserve > 0)
skb_reserve(skb, rx_skb_reserve);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
for (iov = he_vcc->iov_head;
iov < he_vcc->iov_tail; ++iov) {
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 924a2c8988bd..0cded0468003 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1034,7 +1034,7 @@ static void rx_schedule (hrz_dev * dev, int irq) {
struct atm_vcc * vcc = ATM_SKB(skb)->vcc;
// VC layer stats
atomic_inc(&vcc->stats->rx);
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
// end of our responsability
vcc->push (vcc, skb);
}
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index b8c260ed4b27..0aabfc2a59d9 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -50,10 +50,8 @@ static void idt77105_stats_timer_func(unsigned long);
static void idt77105_restart_timer_func(unsigned long);
-static struct timer_list stats_timer =
- TIMER_INITIALIZER(idt77105_stats_timer_func, 0, 0);
-static struct timer_list restart_timer =
- TIMER_INITIALIZER(idt77105_restart_timer_func, 0, 0);
+static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func, 0, 0);
+static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func, 0, 0);
static int start_timer = 1;
static struct idt77105_priv *idt77105_all = NULL;
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 30b7e990ed0b..b4a76cade646 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -1101,7 +1101,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
cell, ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
@@ -1179,7 +1179,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
skb_trim(skb, len);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
@@ -1201,7 +1201,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
skb_trim(skb, len);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
@@ -1340,7 +1340,7 @@ idt77252_rx_raw(struct idt77252_dev *card)
ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index a43575acb2c1..2e2e50e1167a 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -79,7 +79,7 @@ static IADEV *ia_dev[8];
static struct atm_dev *_ia_dev[8];
static int iadev_count;
static void ia_led_timer(unsigned long arg);
-static struct timer_list ia_timer = TIMER_INITIALIZER(ia_led_timer, 0, 0);
+static DEFINE_TIMER(ia_timer, ia_led_timer, 0, 0);
static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index ffe3afa723b8..51ec14787293 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1427,7 +1427,7 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
skb_put(skb, size);
vcc_rx_memcpy(skb->data, lvcc, size);
ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
atomic_inc(&lvcc->rx.atmvcc->stats->rx);
out:
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index b2a7b754fd14..c57e20dcb0f8 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -214,8 +214,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev);
static void __devinit ns_init_card_error(ns_dev *card, int error);
static scq_info *get_scq(int size, u32 scd);
static void free_scq(scq_info *scq, struct atm_vcc *vcc);
-static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
- u32 handle2, u32 addr2);
+static void push_rxbufs(ns_dev *, struct sk_buff *);
static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
static int ns_open(struct atm_vcc *vcc);
static void ns_close(struct atm_vcc *vcc);
@@ -766,6 +765,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
}
@@ -786,9 +786,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
/* Due to the implementation of push_rxbufs() this is 1, not 0 */
if (j == 1)
{
@@ -822,9 +823,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
/* Test for strange behaviour which leads to crashes */
if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min)
@@ -852,6 +854,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
ns_init_card_error(card, error);
return error;
}
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++;
}
@@ -1078,12 +1081,18 @@ static void free_scq(scq_info *scq, struct atm_vcc *vcc)
/* The handles passed must be pointers to the sk_buff containing the small
or large buffer(s) cast to u32. */
-static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
- u32 handle2, u32 addr2)
+static void push_rxbufs(ns_dev *card, struct sk_buff *skb)
{
+ struct ns_skb_cb *cb = NS_SKB_CB(skb);
+ u32 handle1, addr1;
+ u32 handle2, addr2;
u32 stat;
unsigned long flags;
+ /* *BARF* */
+ handle2 = addr2 = 0;
+ handle1 = (u32)skb;
+ addr1 = (u32)virt_to_bus(skb->data);
#ifdef GENERAL_DEBUG
if (!addr1)
@@ -1093,7 +1102,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
stat = readl(card->membase + STAT);
card->sbfqc = ns_stat_sfbqc_get(stat);
card->lbfqc = ns_stat_lfbqc_get(stat);
- if (type == BUF_SM)
+ if (cb->buf_type == BUF_SM)
{
if (!addr2)
{
@@ -1111,7 +1120,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
}
}
}
- else /* type == BUF_LG */
+ else /* buf_type == BUF_LG */
{
if (!addr2)
{
@@ -1132,26 +1141,26 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
if (addr2)
{
- if (type == BUF_SM)
+ if (cb->buf_type == BUF_SM)
{
if (card->sbfqc >= card->sbnr.max)
{
- skb_unlink((struct sk_buff *) handle1);
+ skb_unlink((struct sk_buff *) handle1, &card->sbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle1);
- skb_unlink((struct sk_buff *) handle2);
+ skb_unlink((struct sk_buff *) handle2, &card->sbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle2);
return;
}
else
card->sbfqc += 2;
}
- else /* (type == BUF_LG) */
+ else /* (buf_type == BUF_LG) */
{
if (card->lbfqc >= card->lbnr.max)
{
- skb_unlink((struct sk_buff *) handle1);
+ skb_unlink((struct sk_buff *) handle1, &card->lbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle1);
- skb_unlink((struct sk_buff *) handle2);
+ skb_unlink((struct sk_buff *) handle2, &card->lbpool.queue);
dev_kfree_skb_any((struct sk_buff *) handle2);
return;
}
@@ -1166,12 +1175,12 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
writel(handle2, card->membase + DR2);
writel(addr1, card->membase + DR1);
writel(handle1, card->membase + DR0);
- writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD);
+ writel(NS_CMD_WRITE_FREEBUFQ | cb->buf_type, card->membase + CMD);
spin_unlock_irqrestore(&card->res_lock, flags);
XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index,
- (type == BUF_SM ? "small" : "large"), addr1, addr2);
+ (cb->buf_type == BUF_SM ? "small" : "large"), addr1, addr2);
}
if (!card->efbie && card->sbfqc >= card->sbnr.min &&
@@ -1322,9 +1331,10 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
card->efbie = 0;
break;
}
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
card->sbfqc = i;
process_rsq(card);
@@ -1348,9 +1358,10 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
card->efbie = 0;
break;
}
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
card->lbfqc = i;
process_rsq(card);
@@ -2202,7 +2213,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
memcpy(sb->tail, cell, ATM_CELL_PAYLOAD);
skb_put(sb, ATM_CELL_PAYLOAD);
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
cell += ATM_CELL_PAYLOAD;
@@ -2227,6 +2238,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
recycle_rx_buf(card, skb);
return;
}
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
}
else
if (--card->iovpool.count < card->iovnr.min)
@@ -2234,6 +2246,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
struct sk_buff *new_iovb;
if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL)
{
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
skb_queue_tail(&card->iovpool.queue, new_iovb);
card->iovpool.count++;
}
@@ -2264,7 +2277,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
if (NS_SKB(iovb)->iovcnt == 1)
{
- if (skb->list != &card->sbpool.queue)
+ if (NS_SKB_CB(skb)->buf_type != BUF_SM)
{
printk("nicstar%d: Expected a small buffer, and this is not one.\n",
card->index);
@@ -2278,7 +2291,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
}
else /* NS_SKB(iovb)->iovcnt >= 2 */
{
- if (skb->list != &card->lbpool.queue)
+ if (NS_SKB_CB(skb)->buf_type != BUF_LG)
{
printk("nicstar%d: Expected a large buffer, and this is not one.\n",
card->index);
@@ -2322,8 +2335,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
/* skb points to a small buffer */
if (!atm_charge(vcc, skb->truesize))
{
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
+ push_rxbufs(card, skb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2334,7 +2346,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
skb->destructor = ns_sb_destructor;
#endif /* NS_USE_DESTRUCTORS */
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
}
@@ -2350,8 +2362,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
{
if (!atm_charge(vcc, sb->truesize))
{
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2362,21 +2373,19 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
sb->destructor = ns_sb_destructor;
#endif /* NS_USE_DESTRUCTORS */
ATM_SKB(sb)->vcc = vcc;
- do_gettimeofday(&sb->stamp);
+ __net_timestamp(sb);
vcc->push(vcc, sb);
atomic_inc(&vcc->stats->rx);
}
- push_rxbufs(card, BUF_LG, (u32) skb,
- (u32) virt_to_bus(skb->data), 0, 0);
+ push_rxbufs(card, skb);
}
else /* len > NS_SMBUFSIZE, the usual case */
{
if (!atm_charge(vcc, skb->truesize))
{
- push_rxbufs(card, BUF_LG, (u32) skb,
- (u32) virt_to_bus(skb->data), 0, 0);
+ push_rxbufs(card, skb);
atomic_inc(&vcc->stats->rx_drop);
}
else
@@ -2389,13 +2398,12 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
memcpy(skb->data, sb->data, NS_SMBUFSIZE);
skb_put(skb, len - NS_SMBUFSIZE);
ATM_SKB(skb)->vcc = vcc;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
}
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
}
@@ -2430,6 +2438,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
card->hbpool.count++;
}
}
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
}
else
if (--card->hbpool.count < card->hbnr.min)
@@ -2437,6 +2446,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
struct sk_buff *new_hb;
if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
{
+ NS_SKB_CB(new_hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, new_hb);
card->hbpool.count++;
}
@@ -2444,6 +2454,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
{
if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
{
+ NS_SKB_CB(new_hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, new_hb);
card->hbpool.count++;
}
@@ -2473,8 +2484,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
remaining = len - iov->iov_len;
iov++;
/* Free the small buffer */
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),
- 0, 0);
+ push_rxbufs(card, sb);
/* Copy all large buffers to the huge buffer and free them */
for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)
@@ -2485,8 +2495,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
skb_put(hb, tocopy);
iov++;
remaining -= tocopy;
- push_rxbufs(card, BUF_LG, (u32) lb,
- (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
#ifdef EXTRA_DEBUG
if (remaining != 0 || hb->len != len)
@@ -2496,7 +2505,7 @@ static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe)
#ifdef NS_USE_DESTRUCTORS
hb->destructor = ns_hb_destructor;
#endif /* NS_USE_DESTRUCTORS */
- do_gettimeofday(&hb->stamp);
+ __net_timestamp(hb);
vcc->push(vcc, hb);
atomic_inc(&vcc->stats->rx);
}
@@ -2527,9 +2536,10 @@ static void ns_sb_destructor(struct sk_buff *sb)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL)
break;
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
} while (card->sbfqc < card->sbnr.min);
}
@@ -2550,9 +2560,10 @@ static void ns_lb_destructor(struct sk_buff *lb)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL)
break;
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
} while (card->lbfqc < card->lbnr.min);
}
@@ -2569,6 +2580,7 @@ static void ns_hb_destructor(struct sk_buff *hb)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL)
break;
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
}
@@ -2577,45 +2589,25 @@ static void ns_hb_destructor(struct sk_buff *hb)
#endif /* NS_USE_DESTRUCTORS */
-
static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb)
{
- if (skb->list == &card->sbpool.queue)
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0);
- else if (skb->list == &card->lbpool.queue)
- push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0);
- else
- {
- printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
- dev_kfree_skb_any(skb);
- }
-}
+ struct ns_skb_cb *cb = NS_SKB_CB(skb);
+ if (unlikely(cb->buf_type == BUF_NONE)) {
+ printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
+ dev_kfree_skb_any(skb);
+ } else
+ push_rxbufs(card, skb);
+}
static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count)
{
- struct sk_buff *skb;
-
- for (; count > 0; count--)
- {
- skb = (struct sk_buff *) (iov++)->iov_base;
- if (skb->list == &card->sbpool.queue)
- push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
- else if (skb->list == &card->lbpool.queue)
- push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data),
- 0, 0);
- else
- {
- printk("nicstar%d: What kind of rx buffer is this?\n", card->index);
- dev_kfree_skb_any(skb);
- }
- }
+ while (count-- > 0)
+ recycle_rx_buf(card, (struct sk_buff *) (iov++)->iov_base);
}
-
static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb)
{
if (card->iovpool.count < card->iovnr.max)
@@ -2631,7 +2623,7 @@ static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb)
static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
{
- skb_unlink(sb);
+ skb_unlink(sb, &card->sbpool.queue);
#ifdef NS_USE_DESTRUCTORS
if (card->sbfqc < card->sbnr.min)
#else
@@ -2640,10 +2632,10 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) new_sb,
- (u32) virt_to_bus(new_sb->data), 0, 0);
+ push_rxbufs(card, new_sb);
}
}
if (card->sbfqc < card->sbnr.init)
@@ -2652,10 +2644,10 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
struct sk_buff *new_sb;
if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, new_sb);
skb_reserve(new_sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) new_sb,
- (u32) virt_to_bus(new_sb->data), 0, 0);
+ push_rxbufs(card, new_sb);
}
}
}
@@ -2664,7 +2656,7 @@ static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb)
static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
{
- skb_unlink(lb);
+ skb_unlink(lb, &card->lbpool.queue);
#ifdef NS_USE_DESTRUCTORS
if (card->lbfqc < card->lbnr.min)
#else
@@ -2673,10 +2665,10 @@ static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) new_lb,
- (u32) virt_to_bus(new_lb->data), 0, 0);
+ push_rxbufs(card, new_lb);
}
}
if (card->lbfqc < card->lbnr.init)
@@ -2685,10 +2677,10 @@ static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb)
struct sk_buff *new_lb;
if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
{
+ NS_SKB_CB(new_lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, new_lb);
skb_reserve(new_lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) new_lb,
- (u32) virt_to_bus(new_lb->data), 0, 0);
+ push_rxbufs(card, new_lb);
}
}
}
@@ -2880,9 +2872,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
if (sb == NULL)
return -ENOMEM;
+ NS_SKB_CB(sb)->buf_type = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
- push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0);
+ push_rxbufs(card, sb);
}
break;
@@ -2894,9 +2887,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
if (lb == NULL)
return -ENOMEM;
+ NS_SKB_CB(lb)->buf_type = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
- push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0);
+ push_rxbufs(card, lb);
}
break;
@@ -2923,6 +2917,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL)
return -ENOMEM;
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
ns_grab_int_lock(card, flags);
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
@@ -2953,6 +2948,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
if (iovb == NULL)
return -ENOMEM;
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
ns_grab_int_lock(card, flags);
skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++;
@@ -2979,17 +2975,12 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
}
-
static void which_list(ns_dev *card, struct sk_buff *skb)
{
- printk("It's a %s buffer.\n", skb->list == &card->sbpool.queue ?
- "small" : skb->list == &card->lbpool.queue ? "large" :
- skb->list == &card->hbpool.queue ? "huge" :
- skb->list == &card->iovpool.queue ? "iovec" : "unknown");
+ printk("skb buf_type: 0x%08x\n", NS_SKB_CB(skb)->buf_type);
}
-
static void ns_poll(unsigned long arg)
{
int i;
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
index ea83c46c8ba5..5997bcb45b59 100644
--- a/drivers/atm/nicstar.h
+++ b/drivers/atm/nicstar.h
@@ -103,8 +103,14 @@
#define NS_IOREMAP_SIZE 4096
-#define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */
-#define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */
+/*
+ * BUF_XX distinguish the Rx buffers depending on their (small/large) size.
+ * BUG_SM and BUG_LG are both used by the driver and the device.
+ * BUF_NONE is only used by the driver.
+ */
+#define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */
+#define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */
+#define BUF_NONE 0xffffffff /* Software only: */
#define NS_HBUFSIZE 65568 /* Size of max. AAL5 PDU */
#define NS_MAX_IOVECS (2 + (65568 - NS_SMBUFSIZE) / \
@@ -684,6 +690,12 @@ enum ns_regs
/* Device driver structures ***************************************************/
+struct ns_skb_cb {
+ u32 buf_type; /* BUF_SM/BUF_LG/BUF_NONE */
+};
+
+#define NS_SKB_CB(skb) ((struct ns_skb_cb *)((skb)->cb))
+
typedef struct tsq_info
{
void *org;
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index a2b236a966e0..55959e4d1cb7 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -400,7 +400,7 @@ unsigned long *x;
EVENT("error code 0x%x/0x%x\n",(here[3] & uPD98401_AAL5_ES) >>
uPD98401_AAL5_ES_SHIFT,error);
skb = ((struct rx_buffer_head *) bus_to_virt(here[2]))->skb;
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#if 0
printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3],
((unsigned *) skb->data)[-2],((unsigned *) skb->data)[-1],
@@ -417,10 +417,12 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]);
chan = (here[3] & uPD98401_AAL5_CHAN) >>
uPD98401_AAL5_CHAN_SHIFT;
if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) {
+ int pos;
vcc = zatm_dev->rx_map[chan];
- if (skb == zatm_dev->last_free[ZATM_VCC(vcc)->pool])
- zatm_dev->last_free[ZATM_VCC(vcc)->pool] = NULL;
- skb_unlink(skb);
+ pos = ZATM_VCC(vcc)->pool;
+ if (skb == zatm_dev->last_free[pos])
+ zatm_dev->last_free[pos] = NULL;
+ skb_unlink(skb, zatm_dev->pool + pos);
}
else {
printk(KERN_ERR DEV_LABEL "(itf %d): RX indication "
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 66d9c4643fc1..f12898d53078 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -7,6 +7,7 @@ obj-y := core.o sys.o bus.o dd.o \
obj-y += power/
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
+obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ec615d854be9..2a7d7ae83e1e 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -19,14 +19,31 @@
#include <linux/list.h>
#include <linux/module.h>
+#include "base.h"
+
/* This is a private structure used to tie the classdev and the
* container .. it should never be visible outside this file */
struct internal_container {
- struct list_head node;
+ struct klist_node node;
struct attribute_container *cont;
struct class_device classdev;
};
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
/**
* attribute_container_classdev_to_container - given a classdev, return the container
*
@@ -57,7 +74,8 @@ int
attribute_container_register(struct attribute_container *cont)
{
INIT_LIST_HEAD(&cont->node);
- INIT_LIST_HEAD(&cont->containers);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
down(&attribute_container_mutex);
list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +95,13 @@ attribute_container_unregister(struct attribute_container *cont)
{
int retval = -EBUSY;
down(&attribute_container_mutex);
- if (!list_empty(&cont->containers))
+ spin_lock(&cont->containers.k_lock);
+ if (!list_empty(&cont->containers.k_list))
goto out;
retval = 0;
list_del(&cont->node);
out:
+ spin_unlock(&cont->containers.k_lock);
up(&attribute_container_mutex);
return retval;
@@ -134,13 +154,13 @@ attribute_container_add_device(struct device *dev,
if (!cont->match(cont, dev))
continue;
- ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
continue;
}
- memset(ic, 0, sizeof(struct internal_container));
- INIT_LIST_HEAD(&ic->node);
+
ic->cont = cont;
class_device_initialize(&ic->classdev);
ic->classdev.dev = get_device(dev);
@@ -151,11 +171,22 @@ attribute_container_add_device(struct device *dev,
fn(cont, dev, &ic->classdev);
else
attribute_container_add_class_device(&ic->classdev);
- list_add_tail(&ic->node, &cont->containers);
+ klist_add_tail(&ic->node, &cont->containers);
}
up(&attribute_container_mutex);
}
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+ for (klist_iter_init(head, iter); (pos = ({ \
+ struct klist_node *n = klist_next(iter); \
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
+ }) ) != NULL; )
+
+
/**
* attribute_container_remove_device - make device eligible for removal.
*
@@ -182,17 +213,19 @@ attribute_container_remove_device(struct device *dev,
down(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
- struct internal_container *ic, *tmp;
+ struct internal_container *ic;
+ struct klist_iter iter;
if (attribute_container_no_classdevs(cont))
continue;
if (!cont->match(cont, dev))
continue;
- list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
if (dev != ic->classdev.dev)
continue;
- list_del(&ic->node);
+ klist_del(&ic->node);
if (fn)
fn(cont, dev, &ic->classdev);
else {
@@ -225,12 +258,18 @@ attribute_container_device_trigger(struct device *dev,
down(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
- struct internal_container *ic, *tmp;
+ struct internal_container *ic;
+ struct klist_iter iter;
if (!cont->match(cont, dev))
continue;
- list_for_each_entry_safe(ic, tmp, &cont->containers, node) {
+ if (attribute_container_no_classdevs(cont)) {
+ fn(cont, dev, NULL);
+ continue;
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
if (dev == ic->classdev.dev)
fn(cont, dev, &ic->classdev);
}
@@ -368,6 +407,36 @@ attribute_container_class_device_del(struct class_device *classdev)
}
EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont: the container
+ * @dev: the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct class_device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (ic->classdev.dev == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+ break;
+ }
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
int __init
attribute_container_init(void)
{
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 783752b68a9a..e3b548d46cff 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -1,3 +1,15 @@
+
+/* initialisation functions */
+
+extern int devices_init(void);
+extern int buses_init(void);
+extern int classes_init(void);
+extern int firmware_init(void);
+extern int platform_bus_init(void);
+extern int system_bus_init(void);
+extern int cpu_dev_init(void);
+extern int attribute_container_init(void);
+
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 96fe2f956754..03204bfd17af 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -156,7 +156,9 @@ static ssize_t driver_unbind(struct device_driver *drv,
device_release_driver(dev);
err = count;
}
- return err;
+ if (err)
+ return err;
+ return count;
}
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
@@ -180,7 +182,9 @@ static ssize_t driver_bind(struct device_driver *drv,
up(&dev->sem);
put_device(dev);
}
- return err;
+ if (err)
+ return err;
+ return count;
}
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
@@ -356,7 +360,7 @@ int bus_add_device(struct device * dev)
if (bus) {
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
device_attach(dev);
- klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+ klist_add_tail(&dev->knode_bus, &bus->klist_devices);
error = device_add_attrs(bus, dev);
if (!error) {
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
@@ -444,7 +448,7 @@ int bus_add_driver(struct device_driver * drv)
}
driver_attach(drv);
- klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
+ klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
@@ -564,6 +568,36 @@ static void bus_remove_attrs(struct bus_type * bus)
}
}
+static void klist_devices_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_bus);
+
+ get_device(dev);
+}
+
+static void klist_devices_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_bus);
+
+ put_device(dev);
+}
+
+static void klist_drivers_get(struct klist_node *n)
+{
+ struct device_driver *drv = container_of(n, struct device_driver,
+ knode_bus);
+
+ get_driver(drv);
+}
+
+static void klist_drivers_put(struct klist_node *n)
+{
+ struct device_driver *drv = container_of(n, struct device_driver,
+ knode_bus);
+
+ put_driver(drv);
+}
+
/**
* bus_register - register a bus with the system.
* @bus: bus.
@@ -598,8 +632,8 @@ int bus_register(struct bus_type * bus)
if (retval)
goto bus_drivers_fail;
- klist_init(&bus->klist_devices);
- klist_init(&bus->klist_drivers);
+ klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
+ klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
bus_add_attrs(bus);
pr_debug("bus type '%s' registered\n", bus->name);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 479c12570881..db65fd0babe9 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -17,6 +17,7 @@
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -99,7 +100,8 @@ struct class * class_get(struct class * cls)
void class_put(struct class * cls)
{
- subsys_put(&cls->subsys);
+ if (cls)
+ subsys_put(&cls->subsys);
}
@@ -165,14 +167,25 @@ void class_unregister(struct class * cls)
static void class_create_release(struct class *cls)
{
+ pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
kfree(cls);
}
static void class_device_create_release(struct class_device *class_dev)
{
+ pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
kfree(class_dev);
}
+/* needed to allow these devices to have parent class devices */
+static int class_device_create_hotplug(struct class_device *class_dev,
+ char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
+ return 0;
+}
+
/**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
@@ -189,12 +202,11 @@ struct class *class_create(struct module *owner, char *name)
struct class *cls;
int retval;
- cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
- memset(cls, 0x00, sizeof(struct class));
cls->name = name;
cls->owner = owner;
@@ -299,10 +311,15 @@ static void class_dev_release(struct kobject * kobj)
pr_debug("device class '%s': release.\n", cd->class_id);
- if (cls->release)
+ kfree(cd->devt_attr);
+ cd->devt_attr = NULL;
+
+ if (cd->release)
+ cd->release(cd);
+ else if (cls->release)
cls->release(cd);
else {
- printk(KERN_ERR "Device class '%s' does not have a release() function, "
+ printk(KERN_ERR "Class Device '%s' does not have a release() function, "
"it is broken and must be fixed.\n",
cd->class_id);
WARN_ON(1);
@@ -380,14 +397,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
buffer = &buffer[length];
buffer_size -= length;
- if (class_dev->class->hotplug) {
- /* have the bus specific function add its stuff */
- retval = class_dev->class->hotplug (class_dev, envp, num_envp,
- buffer, buffer_size);
- if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
- __FUNCTION__, retval);
- }
+ if (class_dev->hotplug) {
+ /* have the class device specific function add its stuff */
+ retval = class_dev->hotplug(class_dev, envp, num_envp,
+ buffer, buffer_size);
+ if (retval)
+ pr_debug("class_dev->hotplug() returned %d\n", retval);
+ } else if (class_dev->class->hotplug) {
+ /* have the class specific function add its stuff */
+ retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+ buffer, buffer_size);
+ if (retval)
+ pr_debug("class->hotplug() returned %d\n", retval);
}
return retval;
@@ -440,6 +461,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
return print_dev_t(buf, class_dev->devt);
}
+static ssize_t store_uevent(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ return count;
+}
+
void class_device_initialize(struct class_device *class_dev)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -447,73 +475,109 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD(&class_dev->node);
}
+static char *make_class_name(struct class_device *class_dev)
+{
+ char *name;
+ int size;
+
+ size = strlen(class_dev->class->name) +
+ strlen(kobject_name(&class_dev->kobj)) + 2;
+
+ name = kmalloc(size, GFP_KERNEL);
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ strcpy(name, class_dev->class->name);
+ strcat(name, ":");
+ strcat(name, kobject_name(&class_dev->kobj));
+ return name;
+}
+
int class_device_add(struct class_device *class_dev)
{
- struct class * parent = NULL;
- struct class_interface * class_intf;
- int error;
+ struct class *parent_class = NULL;
+ struct class_device *parent_class_dev = NULL;
+ struct class_interface *class_intf;
+ char *class_name = NULL;
+ int error = -EINVAL;
class_dev = class_device_get(class_dev);
if (!class_dev)
return -EINVAL;
- if (!strlen(class_dev->class_id)) {
- error = -EINVAL;
+ if (!strlen(class_dev->class_id))
goto register_done;
- }
- parent = class_get(class_dev->class);
+ parent_class = class_get(class_dev->class);
+ if (!parent_class)
+ goto register_done;
+ parent_class_dev = class_device_get(class_dev->parent);
pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id);
/* first, register with generic layer. */
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
- if (parent)
- class_dev->kobj.parent = &parent->subsys.kset.kobj;
+ if (parent_class_dev)
+ class_dev->kobj.parent = &parent_class_dev->kobj;
+ else
+ class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
- if ((error = kobject_add(&class_dev->kobj)))
+ error = kobject_add(&class_dev->kobj);
+ if (error)
goto register_done;
/* add the needed attributes to this device */
+ class_dev->uevent_attr.attr.name = "uevent";
+ class_dev->uevent_attr.attr.mode = S_IWUSR;
+ class_dev->uevent_attr.attr.owner = parent_class->owner;
+ class_dev->uevent_attr.store = store_uevent;
+ class_device_create_file(class_dev, &class_dev->uevent_attr);
+
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
- attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
}
- memset(attr, sizeof(*attr), 0x00);
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
- attr->attr.owner = parent->owner;
+ attr->attr.owner = parent_class->owner;
attr->show = show_dev;
- attr->store = NULL;
class_device_create_file(class_dev, attr);
class_dev->devt_attr = attr;
}
class_device_add_attrs(class_dev);
- if (class_dev->dev)
+ if (class_dev->dev) {
+ class_name = make_class_name(class_dev);
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
+ sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+ class_name);
+ }
+
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
- if (parent) {
- down(&parent->sem);
- list_add_tail(&class_dev->node, &parent->children);
- list_for_each_entry(class_intf, &parent->interfaces, node)
+ if (parent_class) {
+ down(&parent_class->sem);
+ list_add_tail(&class_dev->node, &parent_class->children);
+ list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->add)
- class_intf->add(class_dev);
- up(&parent->sem);
+ class_intf->add(class_dev, class_intf);
+ up(&parent_class->sem);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
register_done:
- if (error && parent)
- class_put(parent);
+ if (error) {
+ class_put(parent_class);
+ class_device_put(parent_class_dev);
+ }
class_device_put(class_dev);
+ kfree(class_name);
return error;
}
@@ -526,21 +590,28 @@ int class_device_register(struct class_device *class_dev)
/**
* class_device_create - creates a class device and registers it with sysfs
* @cs: pointer to the struct class that this device should be registered to.
+ * @parent: pointer to the parent struct class_device of this new device, if any.
* @dev: the dev_t for the char device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
*
* This function can be used by char device classes. A struct
* class_device will be created in sysfs, registered to the specified
- * class. A "dev" file will be created, showing the dev_t for the
- * device. The pointer to the struct class_device will be returned from
- * the call. Any further sysfs files that might be required can be
- * created using this pointer.
+ * class.
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct class_device is passed in, the newly
+ * created struct class_device will be a child of that device in sysfs.
+ * The pointer to the struct class_device will be returned from the
+ * call. Any further sysfs files that might be required can be created
+ * using this pointer.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
-struct class_device *class_device_create(struct class *cls, dev_t devt,
+struct class_device *class_device_create(struct class *cls,
+ struct class_device *parent,
+ dev_t devt,
struct device *device, char *fmt, ...)
{
va_list args;
@@ -550,16 +621,18 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
if (cls == NULL || IS_ERR(cls))
goto error;
- class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
if (!class_dev) {
retval = -ENOMEM;
goto error;
}
- memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->devt = devt;
class_dev->dev = device;
class_dev->class = cls;
+ class_dev->parent = parent;
+ class_dev->release = class_device_create_release;
+ class_dev->hotplug = class_device_create_hotplug;
va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -577,32 +650,36 @@ error:
void class_device_del(struct class_device *class_dev)
{
- struct class * parent = class_dev->class;
- struct class_interface * class_intf;
+ struct class *parent_class = class_dev->class;
+ struct class_device *parent_device = class_dev->parent;
+ struct class_interface *class_intf;
+ char *class_name = NULL;
- if (parent) {
- down(&parent->sem);
+ if (parent_class) {
+ down(&parent_class->sem);
list_del_init(&class_dev->node);
- list_for_each_entry(class_intf, &parent->interfaces, node)
+ list_for_each_entry(class_intf, &parent_class->interfaces, node)
if (class_intf->remove)
- class_intf->remove(class_dev);
- up(&parent->sem);
+ class_intf->remove(class_dev, class_intf);
+ up(&parent_class->sem);
}
- if (class_dev->dev)
+ if (class_dev->dev) {
+ class_name = make_class_name(class_dev);
sysfs_remove_link(&class_dev->kobj, "device");
- if (class_dev->devt_attr) {
- class_device_remove_file(class_dev, class_dev->devt_attr);
- kfree(class_dev->devt_attr);
- class_dev->devt_attr = NULL;
+ sysfs_remove_link(&class_dev->dev->kobj, class_name);
}
+ class_device_remove_file(class_dev, &class_dev->uevent_attr);
+ if (class_dev->devt_attr)
+ class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj);
- if (parent)
- class_put(parent);
+ class_device_put(parent_device);
+ class_put(parent_class);
+ kfree(class_name);
}
void class_device_unregister(struct class_device *class_dev)
@@ -642,6 +719,7 @@ void class_device_destroy(struct class *cls, dev_t devt)
int class_device_rename(struct class_device *class_dev, char *new_name)
{
int error = 0;
+ char *old_class_name = NULL, *new_class_name = NULL;
class_dev = class_device_get(class_dev);
if (!class_dev)
@@ -650,12 +728,24 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
new_name);
+ if (class_dev->dev)
+ old_class_name = make_class_name(class_dev);
+
strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
error = kobject_rename(&class_dev->kobj, new_name);
+ if (class_dev->dev) {
+ new_class_name = make_class_name(class_dev);
+ sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+ new_class_name);
+ sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
+ }
class_device_put(class_dev);
+ kfree(old_class_name);
+ kfree(new_class_name);
+
return error;
}
@@ -668,7 +758,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
void class_device_put(struct class_device *class_dev)
{
- kobject_put(&class_dev->kobj);
+ if (class_dev)
+ kobject_put(&class_dev->kobj);
}
@@ -688,7 +779,7 @@ int class_interface_register(struct class_interface *class_intf)
list_add_tail(&class_intf->node, &parent->interfaces);
if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node)
- class_intf->add(class_dev);
+ class_intf->add(class_dev, class_intf);
}
up(&parent->sem);
@@ -707,7 +798,7 @@ void class_interface_unregister(struct class_interface *class_intf)
list_del_init(&class_intf->node);
if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node)
- class_intf->remove(class_dev);
+ class_intf->remove(class_dev, class_intf);
}
up(&parent->sem);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index efe03a024a5b..8615b42b517a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
.hotplug = dev_hotplug,
};
+static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ return count;
+}
+
/**
* device_subsys - structure to be registered with kobject core.
*/
@@ -191,6 +198,20 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
}
}
+static void klist_children_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_parent);
+
+ get_device(dev);
+}
+
+static void klist_children_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_parent);
+
+ put_device(dev);
+}
+
/**
* device_initialize - init device structure.
@@ -207,9 +228,11 @@ void device_initialize(struct device *dev)
{
kobj_set_kset_s(dev, devices_subsys);
kobject_init(&dev->kobj);
- klist_init(&dev->klist_children);
+ klist_init(&dev->klist_children, klist_children_get,
+ klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem);
+ device_init_wakeup(dev, 0);
}
/**
@@ -243,13 +266,21 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj)))
goto Error;
+
+ dev->uevent_attr.attr.name = "uevent";
+ dev->uevent_attr.attr.mode = S_IWUSR;
+ if (dev->driver)
+ dev->uevent_attr.attr.owner = dev->driver->owner;
+ dev->uevent_attr.store = store_uevent;
+ device_create_file(dev, &dev->uevent_attr);
+
kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
goto BusError;
if (parent)
- klist_add_tail(&parent->klist_children, &dev->knode_parent);
+ klist_add_tail(&dev->knode_parent, &parent->klist_children);
/* notify platform of device entry */
if (platform_notify)
@@ -334,6 +365,7 @@ void device_del(struct device * dev)
if (parent)
klist_del(&dev->knode_parent);
+ device_remove_file(dev, &dev->uevent_attr);
/* Notify the platform of the removal, in case they
* need to do anything...
@@ -375,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
/**
* device_for_each_child - device child iterator.
- * @dev: parent struct device.
+ * @parent: parent struct device.
* @data: data for the callback.
* @fn: function to be called for each device.
*
- * Iterate over @dev's child devices, and call @fn for each,
+ * Iterate over @parent's child devices, and call @fn for each,
* passing it @data.
*
* We check the return of @fn each time. If it returns anything
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index b79badd0f158..a95844790f7b 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -9,12 +9,15 @@
#include <linux/topology.h>
#include <linux/device.h>
+#include "base.h"
struct sysdev_class cpu_sysdev_class = {
set_kset_name("cpu"),
};
EXPORT_SYMBOL(cpu_sysdev_class);
+static struct sys_device *cpu_sys_devices[NR_CPUS];
+
#ifdef CONFIG_HOTPLUG_CPU
int __attribute__((weak)) smp_prepare_cpu (int cpu)
{
@@ -63,6 +66,7 @@ static void __devinit register_cpu_control(struct cpu *cpu)
}
void unregister_cpu(struct cpu *cpu, struct node *root)
{
+ int logical_cpu = cpu->sysdev.id;
if (root)
sysfs_remove_link(&root->sysdev.kobj,
@@ -70,7 +74,7 @@ void unregister_cpu(struct cpu *cpu, struct node *root)
sysdev_remove_file(&cpu->sysdev, &attr_online);
sysdev_unregister(&cpu->sysdev);
-
+ cpu_sys_devices[logical_cpu] = NULL;
return;
}
#else /* ... !CONFIG_HOTPLUG_CPU */
@@ -102,10 +106,19 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
kobject_name(&cpu->sysdev.kobj));
if (!error && !cpu->no_control)
register_cpu_control(cpu);
+ if (!error)
+ cpu_sys_devices[num] = &cpu->sysdev;
return error;
}
-
+struct sys_device *get_cpu_sysdev(int cpu)
+{
+ if (cpu < NR_CPUS)
+ return cpu_sys_devices[cpu];
+ else
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_cpu_sysdev);
int __init cpu_dev_init(void)
{
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 16323f9cbff0..3565e9795301 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -40,9 +40,12 @@
*/
void device_bind_driver(struct device * dev)
{
+ if (klist_node_attached(&dev->knode_driver))
+ return;
+
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
- klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+ klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index c4aebf2f522d..e2f64f91ed05 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -156,7 +156,7 @@ dma_pool_create (const char *name, struct device *dev,
static struct dma_page *
-pool_alloc_page (struct dma_pool *pool, unsigned int __nocast mem_flags)
+pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags)
{
struct dma_page *page;
int mapsize;
@@ -262,7 +262,7 @@ dma_pool_destroy (struct dma_pool *pool)
* If such a memory block can't be allocated, null is returned.
*/
void *
-dma_pool_alloc (struct dma_pool *pool, int mem_flags, dma_addr_t *handle)
+dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle)
{
unsigned long flags;
struct dma_page *page;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 291c5954a3af..161f3a390d90 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
/**
* driver_for_each_device - Iterator for devices bound to a driver.
* @drv: Driver we're iterating.
+ * @start: Device to begin with
* @data: Data to pass to the callback.
* @fn: Function to call for each device.
*
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
/**
* driver_find_device - device iterator for locating a particular device.
- * @driver: The device's driver
+ * @drv: The device's driver
* @start: Device to begin with
* @data: Data to pass to match function
* @match: Callback function to check device
@@ -142,6 +143,19 @@ void put_driver(struct device_driver * drv)
kobject_put(&drv->kobj);
}
+static void klist_devices_get(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_driver);
+
+ get_device(dev);
+}
+
+static void klist_devices_put(struct klist_node *n)
+{
+ struct device *dev = container_of(n, struct device, knode_driver);
+
+ put_device(dev);
+}
/**
* driver_register - register driver with bus
@@ -157,7 +171,7 @@ void put_driver(struct device_driver * drv)
*/
int driver_register(struct device_driver * drv)
{
- klist_init(&drv->klist_devices);
+ klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
index 88ab044932f2..cb1b98ae0d58 100644
--- a/drivers/base/firmware.c
+++ b/drivers/base/firmware.c
@@ -11,6 +11,9 @@
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/device.h>
+
+#include "base.h"
static decl_subsys(firmware, NULL, NULL);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 652281402c92..98f6c02d6790 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -28,6 +28,7 @@ enum {
FW_STATUS_DONE,
FW_STATUS_ABORT,
FW_STATUS_READY,
+ FW_STATUS_READY_NOHOTPLUG,
};
static int loading_timeout = 10; /* In seconds */
@@ -61,14 +62,16 @@ firmware_timeout_show(struct class *class, char *buf)
}
/**
- * firmware_timeout_store:
- * Description:
+ * firmware_timeout_store - set number of seconds to wait for firmware
+ * @class: device class pointer
+ * @buf: buffer to scan for timeout value
+ * @count: number of bytes in @buf
+ *
* Sets the number of seconds to wait for the firmware. Once
- * this expires an error will be return to the driver and no
+ * this expires an error will be returned to the driver and no
* firmware will be provided.
*
- * Note: zero means 'wait for ever'
- *
+ * Note: zero means 'wait forever'.
**/
static ssize_t
firmware_timeout_store(struct class *class, const char *buf, size_t count)
@@ -122,12 +125,15 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
}
/**
- * firmware_loading_store: - loading control file
- * Description:
+ * firmware_loading_store - set value in the 'loading' control file
+ * @class_dev: class_device pointer
+ * @buf: buffer to scan for loading control value
+ * @count: number of bytes in @buf
+ *
* The relevant values are:
*
* 1: Start a load, discarding any previous partial load.
- * 0: Conclude the load and handle the data to the driver code.
+ * 0: Conclude the load and hand the data to the driver code.
* -1: Conclude the load with an error and discard any written data.
**/
static ssize_t
@@ -200,6 +206,7 @@ out:
up(&fw_lock);
return ret_count;
}
+
static int
fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
{
@@ -226,11 +233,13 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
}
/**
- * firmware_data_write:
- *
- * Description:
+ * firmware_data_write - write method for firmware
+ * @kobj: kobject for the class_device
+ * @buffer: buffer being written
+ * @offset: buffer offset for write in total data store area
+ * @count: buffer size
*
- * Data written to the 'data' attribute will be later handled to
+ * Data written to the 'data' attribute will be later handed to
* the driver as a firmware image.
**/
static ssize_t
@@ -263,6 +272,7 @@ out:
up(&fw_lock);
return retval;
}
+
static struct bin_attribute firmware_attr_data_tmpl = {
.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
.size = 0,
@@ -300,9 +310,9 @@ fw_register_class_device(struct class_device **class_dev_p,
const char *fw_name, struct device *device)
{
int retval;
- struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+ struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
- struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+ struct class_device *class_dev = kzalloc(sizeof(*class_dev),
GFP_KERNEL);
*class_dev_p = NULL;
@@ -312,8 +322,6 @@ fw_register_class_device(struct class_device **class_dev_p,
retval = -ENOMEM;
goto error_kfree;
}
- memset(fw_priv, 0, sizeof (*fw_priv));
- memset(class_dev, 0, sizeof (*class_dev));
init_completion(&fw_priv->completion);
fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -344,7 +352,7 @@ error_kfree:
static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
- const char *fw_name, struct device *device)
+ const char *fw_name, struct device *device, int hotplug)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -376,7 +384,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
goto error_unreg;
}
- set_bit(FW_STATUS_READY, &fw_priv->status);
+ if (hotplug)
+ set_bit(FW_STATUS_READY, &fw_priv->status);
+ else
+ set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
*class_dev_p = class_dev;
goto out;
@@ -386,21 +397,9 @@ out:
return retval;
}
-/**
- * request_firmware: - request firmware to hotplug and wait for it
- * Description:
- * @firmware will be used to return a firmware image by the name
- * of @name for device @device.
- *
- * Should be called from user context where sleeping is allowed.
- *
- * @name will be use as $FIRMWARE in the hotplug environment and
- * should be distinctive enough not to be confused with any other
- * firmware image for this or any other device.
- **/
-int
-request_firmware(const struct firmware **firmware_p, const char *name,
- struct device *device)
+static int
+_request_firmware(const struct firmware **firmware_p, const char *name,
+ struct device *device, int hotplug)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -410,31 +409,33 @@ request_firmware(const struct firmware **firmware_p, const char *name,
if (!firmware_p)
return -EINVAL;
- *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
__FUNCTION__);
retval = -ENOMEM;
goto out;
}
- memset(firmware, 0, sizeof (*firmware));
- retval = fw_setup_class_device(firmware, &class_dev, name, device);
+ retval = fw_setup_class_device(firmware, &class_dev, name, device,
+ hotplug);
if (retval)
goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev);
- if (loading_timeout > 0) {
- fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
- add_timer(&fw_priv->timeout);
- }
-
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
- wait_for_completion(&fw_priv->completion);
- set_bit(FW_STATUS_DONE, &fw_priv->status);
+ if (hotplug) {
+ if (loading_timeout > 0) {
+ fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
+ add_timer(&fw_priv->timeout);
+ }
- del_timer_sync(&fw_priv->timeout);
+ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ wait_for_completion(&fw_priv->completion);
+ set_bit(FW_STATUS_DONE, &fw_priv->status);
+ del_timer_sync(&fw_priv->timeout);
+ } else
+ wait_for_completion(&fw_priv->completion);
down(&fw_lock);
if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -455,7 +456,31 @@ out:
}
/**
+ * request_firmware: - request firmware to hotplug and wait for it
+ * @firmware_p: pointer to firmware image
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ *
+ * @firmware_p will be used to return a firmware image by the name
+ * of @name for device @device.
+ *
+ * Should be called from user context where sleeping is allowed.
+ *
+ * @name will be used as $FIRMWARE in the hotplug environment and
+ * should be distinctive enough not to be confused with any other
+ * firmware image for this or any other device.
+ **/
+int
+request_firmware(const struct firmware **firmware_p, const char *name,
+ struct device *device)
+{
+ int hotplug = 1;
+ return _request_firmware(firmware_p, name, device, hotplug);
+}
+
+/**
* release_firmware: - release the resource associated with a firmware image
+ * @fw: firmware resource to release
**/
void
release_firmware(const struct firmware *fw)
@@ -468,8 +493,10 @@ release_firmware(const struct firmware *fw)
/**
* register_firmware: - provide a firmware image for later usage
+ * @name: name of firmware image file
+ * @data: buffer pointer for the firmware image
+ * @size: size of the data buffer area
*
- * Description:
* Make sure that @data will be available by requesting firmware @name.
*
* Note: This will not be possible until some kind of persistence
@@ -491,6 +518,7 @@ struct firmware_work {
struct device *device;
void *context;
void (*cont)(const struct firmware *fw, void *context);
+ int hotplug;
};
static int
@@ -503,7 +531,8 @@ request_firmware_work_func(void *arg)
return 0;
}
daemonize("%s/%s", "firmware", fw_work->name);
- request_firmware(&fw, fw_work->name, fw_work->device);
+ _request_firmware(&fw, fw_work->name, fw_work->device,
+ fw_work->hotplug);
fw_work->cont(fw, fw_work->context);
release_firmware(fw);
module_put(fw_work->module);
@@ -512,22 +541,23 @@ request_firmware_work_func(void *arg)
}
/**
- * request_firmware_nowait:
+ * request_firmware_nowait: asynchronous version of request_firmware
+ * @module: module requesting the firmware
+ * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ * is non-zero else the firmware copy must be done manually.
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ * @context: will be passed over to @cont, and
+ * @fw may be %NULL if firmware request fails.
+ * @cont: function will be called asynchronously when the firmware
+ * request is over.
*
- * Description:
* Asynchronous variant of request_firmware() for contexts where
* it is not possible to sleep.
- *
- * @cont will be called asynchronously when the firmware request is over.
- *
- * @context will be passed over to @cont.
- *
- * @fw may be %NULL if firmware request fails.
- *
**/
int
request_firmware_nowait(
- struct module *module,
+ struct module *module, int hotplug,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
@@ -548,6 +578,7 @@ request_firmware_nowait(
.device = device,
.context = context,
.cont = cont,
+ .hotplug = hotplug,
};
ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/init.c b/drivers/base/init.c
index a76ae5a221f3..c648914b9cde 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -9,15 +9,10 @@
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
-extern int devices_init(void);
-extern int buses_init(void);
-extern int classes_init(void);
-extern int firmware_init(void);
-extern int platform_bus_init(void);
-extern int system_bus_init(void);
-extern int cpu_dev_init(void);
-extern int attribute_container_init(void);
/**
* driver_init - initialize driver model.
*
@@ -39,5 +34,6 @@ void __init driver_init(void)
platform_bus_init();
system_bus_init();
cpu_dev_init();
+ memory_dev_init();
attribute_container_init();
}
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 2f455d86793c..b449dae6f0d3 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -135,7 +135,7 @@ retry:
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
- struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+ struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
int i;
if ((p == NULL) || (base == NULL)) {
@@ -144,7 +144,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
return NULL;
}
- memset(base, 0, sizeof(struct probe));
base->dev = 1;
base->range = ~0;
base->get = base_probe;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
new file mode 100644
index 000000000000..b7ddd651d664
--- /dev/null
+++ b/drivers/base/memory.c
@@ -0,0 +1,452 @@
+/*
+ * drivers/base/memory.c - basic Memory class support
+ *
+ * Written by Matt Tolentino <matthew.e.tolentino@intel.com>
+ * Dave Hansen <haveblue@us.ibm.com>
+ *
+ * This file provides the necessary infrastructure to represent
+ * a SPARSEMEM-memory-model system's physical memory in /sysfs.
+ * All arch-independent code that assumes MEMORY_HOTPLUG requires
+ * SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
+ */
+
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h> /* capable() */
+#include <linux/topology.h>
+#include <linux/device.h>
+#include <linux/memory.h>
+#include <linux/kobject.h>
+#include <linux/memory_hotplug.h>
+#include <linux/mm.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+
+#define MEMORY_CLASS_NAME "memory"
+
+static struct sysdev_class memory_sysdev_class = {
+ set_kset_name(MEMORY_CLASS_NAME),
+};
+EXPORT_SYMBOL(memory_sysdev_class);
+
+static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
+{
+ return MEMORY_CLASS_NAME;
+}
+
+static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ int retval = 0;
+
+ return retval;
+}
+
+static struct kset_hotplug_ops memory_hotplug_ops = {
+ .name = memory_hotplug_name,
+ .hotplug = memory_hotplug,
+};
+
+static struct notifier_block *memory_chain;
+
+static int register_memory_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&memory_chain, nb);
+}
+
+static void unregister_memory_notifier(struct notifier_block *nb)
+{
+ notifier_chain_unregister(&memory_chain, nb);
+}
+
+/*
+ * register_memory - Setup a sysfs device for a memory block
+ */
+static int
+register_memory(struct memory_block *memory, struct mem_section *section,
+ struct node *root)
+{
+ int error;
+
+ memory->sysdev.cls = &memory_sysdev_class;
+ memory->sysdev.id = __section_nr(section);
+
+ error = sysdev_register(&memory->sysdev);
+
+ if (root && !error)
+ error = sysfs_create_link(&root->sysdev.kobj,
+ &memory->sysdev.kobj,
+ kobject_name(&memory->sysdev.kobj));
+
+ return error;
+}
+
+static void
+unregister_memory(struct memory_block *memory, struct mem_section *section,
+ struct node *root)
+{
+ BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
+ BUG_ON(memory->sysdev.id != __section_nr(section));
+
+ sysdev_unregister(&memory->sysdev);
+ if (root)
+ sysfs_remove_link(&root->sysdev.kobj,
+ kobject_name(&memory->sysdev.kobj));
+}
+
+/*
+ * use this as the physical section index that this memsection
+ * uses.
+ */
+
+static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
+{
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+ return sprintf(buf, "%08lx\n", mem->phys_index);
+}
+
+/*
+ * online, offline, going offline, etc.
+ */
+static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+{
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+ ssize_t len = 0;
+
+ /*
+ * We can probably put these states in a nice little array
+ * so that they're not open-coded
+ */
+ switch (mem->state) {
+ case MEM_ONLINE:
+ len = sprintf(buf, "online\n");
+ break;
+ case MEM_OFFLINE:
+ len = sprintf(buf, "offline\n");
+ break;
+ case MEM_GOING_OFFLINE:
+ len = sprintf(buf, "going-offline\n");
+ break;
+ default:
+ len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
+ mem->state);
+ WARN_ON(1);
+ break;
+ }
+
+ return len;
+}
+
+static inline int memory_notify(unsigned long val, void *v)
+{
+ return notifier_call_chain(&memory_chain, val, v);
+}
+
+/*
+ * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
+ * OK to have direct references to sparsemem variables in here.
+ */
+static int
+memory_block_action(struct memory_block *mem, unsigned long action)
+{
+ int i;
+ unsigned long psection;
+ unsigned long start_pfn, start_paddr;
+ struct page *first_page;
+ int ret;
+ int old_state = mem->state;
+
+ psection = mem->phys_index;
+ first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+
+ /*
+ * The probe routines leave the pages reserved, just
+ * as the bootmem code does. Make sure they're still
+ * that way.
+ */
+ if (action == MEM_ONLINE) {
+ for (i = 0; i < PAGES_PER_SECTION; i++) {
+ if (PageReserved(first_page+i))
+ continue;
+
+ printk(KERN_WARNING "section number %ld page number %d "
+ "not reserved, was it already online? \n",
+ psection, i);
+ return -EBUSY;
+ }
+ }
+
+ switch (action) {
+ case MEM_ONLINE:
+ start_pfn = page_to_pfn(first_page);
+ ret = online_pages(start_pfn, PAGES_PER_SECTION);
+ break;
+ case MEM_OFFLINE:
+ mem->state = MEM_GOING_OFFLINE;
+ memory_notify(MEM_GOING_OFFLINE, NULL);
+ start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
+ ret = remove_memory(start_paddr,
+ PAGES_PER_SECTION << PAGE_SHIFT);
+ if (ret) {
+ mem->state = old_state;
+ break;
+ }
+ memory_notify(MEM_MAPPING_INVALID, NULL);
+ break;
+ default:
+ printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+ __FUNCTION__, mem, action, action);
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+ /*
+ * For now, only notify on successful memory operations
+ */
+ if (!ret)
+ memory_notify(action, NULL);
+
+ return ret;
+}
+
+static int memory_block_change_state(struct memory_block *mem,
+ unsigned long to_state, unsigned long from_state_req)
+{
+ int ret = 0;
+ down(&mem->state_sem);
+
+ if (mem->state != from_state_req) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = memory_block_action(mem, to_state);
+ if (!ret)
+ mem->state = to_state;
+
+out:
+ up(&mem->state_sem);
+ return ret;
+}
+
+static ssize_t
+store_mem_state(struct sys_device *dev, const char *buf, size_t count)
+{
+ struct memory_block *mem;
+ unsigned int phys_section_nr;
+ int ret = -EINVAL;
+
+ mem = container_of(dev, struct memory_block, sysdev);
+ phys_section_nr = mem->phys_index;
+
+ if (!valid_section_nr(phys_section_nr))
+ goto out;
+
+ if (!strncmp(buf, "online", min((int)count, 6)))
+ ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+ else if(!strncmp(buf, "offline", min((int)count, 7)))
+ ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+out:
+ if (ret)
+ return ret;
+ return count;
+}
+
+/*
+ * phys_device is a bad name for this. What I really want
+ * is a way to differentiate between memory ranges that
+ * are part of physical devices that constitute
+ * a complete removable unit or fru.
+ * i.e. do these ranges belong to the same physical device,
+ * s.t. if I offline all of these sections I can then
+ * remove the physical device?
+ */
+static ssize_t show_phys_device(struct sys_device *dev, char *buf)
+{
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+ return sprintf(buf, "%d\n", mem->phys_device);
+}
+
+static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
+static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
+
+#define mem_create_simple_file(mem, attr_name) \
+ sysdev_create_file(&mem->sysdev, &attr_##attr_name)
+#define mem_remove_simple_file(mem, attr_name) \
+ sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
+
+/*
+ * Block size attribute stuff
+ */
+static ssize_t
+print_block_size(struct class *class, char *buf)
+{
+ return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
+}
+
+static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
+
+static int block_size_init(void)
+{
+ sysfs_create_file(&memory_sysdev_class.kset.kobj,
+ &class_attr_block_size_bytes.attr);
+ return 0;
+}
+
+/*
+ * Some architectures will have custom drivers to do this, and
+ * will not need to do it from userspace. The fake hot-add code
+ * as well as ppc64 will do all of their discovery in userspace
+ * and will require this interface.
+ */
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+static ssize_t
+memory_probe_store(struct class *class, const char __user *buf, size_t count)
+{
+ u64 phys_addr;
+ int ret;
+
+ phys_addr = simple_strtoull(buf, NULL, 0);
+
+ ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
+
+ if (ret)
+ count = ret;
+
+ return count;
+}
+static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
+
+static int memory_probe_init(void)
+{
+ sysfs_create_file(&memory_sysdev_class.kset.kobj,
+ &class_attr_probe.attr);
+ return 0;
+}
+#else
+#define memory_probe_init(...) do {} while (0)
+#endif
+
+/*
+ * Note that phys_device is optional. It is here to allow for
+ * differentiation between which *physical* devices each
+ * section belongs to...
+ */
+
+static int add_memory_block(unsigned long node_id, struct mem_section *section,
+ unsigned long state, int phys_device)
+{
+ struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ int ret = 0;
+
+ if (!mem)
+ return -ENOMEM;
+
+ mem->phys_index = __section_nr(section);
+ mem->state = state;
+ init_MUTEX(&mem->state_sem);
+ mem->phys_device = phys_device;
+
+ ret = register_memory(mem, section, NULL);
+ if (!ret)
+ ret = mem_create_simple_file(mem, phys_index);
+ if (!ret)
+ ret = mem_create_simple_file(mem, state);
+ if (!ret)
+ ret = mem_create_simple_file(mem, phys_device);
+
+ return ret;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+static struct memory_block *find_memory_block(struct mem_section *section)
+{
+ struct kobject *kobj;
+ struct sys_device *sysdev;
+ struct memory_block *mem;
+ char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+ /*
+ * This only works because we know that section == sysdev->id
+ * slightly redundant with sysdev_register()
+ */
+ sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+
+ kobj = kset_find_obj(&memory_sysdev_class.kset, name);
+ if (!kobj)
+ return NULL;
+
+ sysdev = container_of(kobj, struct sys_device, kobj);
+ mem = container_of(sysdev, struct memory_block, sysdev);
+
+ return mem;
+}
+
+int remove_memory_block(unsigned long node_id, struct mem_section *section,
+ int phys_device)
+{
+ struct memory_block *mem;
+
+ mem = find_memory_block(section);
+ mem_remove_simple_file(mem, phys_index);
+ mem_remove_simple_file(mem, state);
+ mem_remove_simple_file(mem, phys_device);
+ unregister_memory(mem, section, NULL);
+
+ return 0;
+}
+
+/*
+ * need an interface for the VM to add new memory regions,
+ * but without onlining it.
+ */
+int register_new_memory(struct mem_section *section)
+{
+ return add_memory_block(0, section, MEM_OFFLINE, 0);
+}
+
+int unregister_memory_section(struct mem_section *section)
+{
+ if (!valid_section(section))
+ return -EINVAL;
+
+ return remove_memory_block(0, section, 0);
+}
+
+/*
+ * Initialize the sysfs support for memory devices...
+ */
+int __init memory_dev_init(void)
+{
+ unsigned int i;
+ int ret;
+
+ memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
+ ret = sysdev_class_register(&memory_sysdev_class);
+
+ /*
+ * Create entries for memory sections that were found
+ * during boot and have been initialized
+ */
+ for (i = 0; i < NR_MEM_SECTIONS; i++) {
+ if (!valid_section_nr(i))
+ continue;
+ add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+ }
+
+ memory_probe_init();
+ block_size_init();
+
+ return ret;
+}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 904b27caf697..16c513aa4d48 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -39,13 +39,25 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
int n;
int nid = dev->id;
struct sysinfo i;
+ struct page_state ps;
unsigned long inactive;
unsigned long active;
unsigned long free;
si_meminfo_node(&i, nid);
+ get_page_state_node(&ps, nid);
__get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
+ /* Check for negative values in these approximate counters */
+ if ((long)ps.nr_dirty < 0)
+ ps.nr_dirty = 0;
+ if ((long)ps.nr_writeback < 0)
+ ps.nr_writeback = 0;
+ if ((long)ps.nr_mapped < 0)
+ ps.nr_mapped = 0;
+ if ((long)ps.nr_slab < 0)
+ ps.nr_slab = 0;
+
n = sprintf(buf, "\n"
"Node %d MemTotal: %8lu kB\n"
"Node %d MemFree: %8lu kB\n"
@@ -55,7 +67,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
"Node %d HighTotal: %8lu kB\n"
"Node %d HighFree: %8lu kB\n"
"Node %d LowTotal: %8lu kB\n"
- "Node %d LowFree: %8lu kB\n",
+ "Node %d LowFree: %8lu kB\n"
+ "Node %d Dirty: %8lu kB\n"
+ "Node %d Writeback: %8lu kB\n"
+ "Node %d Mapped: %8lu kB\n"
+ "Node %d Slab: %8lu kB\n",
nid, K(i.totalram),
nid, K(i.freeram),
nid, K(i.totalram - i.freeram),
@@ -64,7 +80,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
nid, K(i.totalhigh),
nid, K(i.freehigh),
nid, K(i.totalram - i.totalhigh),
- nid, K(i.freeram - i.freehigh));
+ nid, K(i.freeram - i.freehigh),
+ nid, K(ps.nr_dirty),
+ nid, K(ps.nr_writeback),
+ nid, K(ps.nr_mapped),
+ nid, K(ps.nr_slab));
n += hugetlb_report_node_meminfo(nid, buf + n);
return n;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3a5f4c991797..d597c922af11 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -10,12 +10,15 @@
* information.
*/
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/bootmem.h>
#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "base.h"
struct device platform_bus = {
.bus_id = "platform",
@@ -225,13 +228,12 @@ struct platform_device *platform_device_register_simple(char *name, unsigned int
struct platform_object *pobj;
int retval;
- pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+ pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);
if (!pobj) {
retval = -ENOMEM;
goto error;
}
- memset(pobj, 0, sizeof(*pobj));
pobj->pdev.name = name;
pobj->pdev.id = id;
pobj->pdev.dev.release = platform_device_release_simple;
@@ -280,13 +282,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
{
int ret = 0;
- if (dev->driver && dev->driver->suspend) {
- ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
- if (ret == 0)
- ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
- if (ret == 0)
- ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
- }
+ if (dev->driver && dev->driver->suspend)
+ ret = dev->driver->suspend(dev, state);
+
return ret;
}
@@ -294,13 +292,9 @@ static int platform_resume(struct device * dev)
{
int ret = 0;
- if (dev->driver && dev->driver->resume) {
- ret = dev->driver->resume(dev, RESUME_POWER_ON);
- if (ret == 0)
- ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
- if (ret == 0)
- ret = dev->driver->resume(dev, RESUME_ENABLE);
- }
+ if (dev->driver && dev->driver->resume)
+ ret = dev->driver->resume(dev);
+
return ret;
}
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 15e6a8f951f1..0d2e101e4f15 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
DECLARE_MUTEX(dpm_sem);
DECLARE_MUTEX(dpm_list_sem);
-/*
- * PM Reference Counting.
- */
-
-static inline void device_pm_hold(struct device * dev)
-{
- if (dev)
- atomic_inc(&dev->power.pm_users);
-}
-
-static inline void device_pm_release(struct device * dev)
-{
- if (dev)
- atomic_dec(&dev->power.pm_users);
-}
-
-
/**
* device_pm_set_parent - Specify power dependency.
* @dev: Device who needs power.
@@ -62,10 +45,8 @@ static inline void device_pm_release(struct device * dev)
void device_pm_set_parent(struct device * dev, struct device * parent)
{
- struct device * old_parent = dev->power.pm_parent;
- device_pm_release(old_parent);
- dev->power.pm_parent = parent;
- device_pm_hold(parent);
+ put_device(dev->power.pm_parent);
+ dev->power.pm_parent = get_device(parent);
}
EXPORT_SYMBOL_GPL(device_pm_set_parent);
@@ -75,7 +56,6 @@ int device_pm_add(struct device * dev)
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
- atomic_set(&dev->power.pm_users, 0);
down(&dpm_list_sem);
list_add_tail(&dev->power.entry, &dpm_active);
device_pm_set_parent(dev, dev->parent);
@@ -91,7 +71,7 @@ void device_pm_remove(struct device * dev)
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
down(&dpm_list_sem);
dpm_sysfs_remove(dev);
- device_pm_release(dev->power.pm_parent);
+ put_device(dev->power.pm_parent);
list_del_init(&dev->power.entry);
up(&dpm_list_sem);
}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 2e700d795cf1..fb3d35a9e101 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -67,9 +67,6 @@ extern int suspend_device(struct device *, pm_message_t);
* runtime.c
*/
-extern int dpm_runtime_suspend(struct device *, pm_message_t);
-extern void dpm_runtime_resume(struct device *);
-
#else /* CONFIG_PM */
@@ -82,14 +79,4 @@ static inline void device_pm_remove(struct device * dev)
}
-static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
-{
- return 0;
-}
-
-static inline void dpm_runtime_resume(struct device * dev)
-{
-
-}
-
#endif
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index bdd96b03b885..0a7aa07b9a2a 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -26,11 +26,11 @@ int resume_device(struct device * dev)
down(&dev->sem);
if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
+ && dev->power.pm_parent->power.power_state.event) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
- dev->power.power_state,
+ dev->power.power_state.event,
dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
+ dev->power.pm_parent->power.power_state.event);
}
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
@@ -54,7 +54,7 @@ void dpm_resume(void)
list_add_tail(entry, &dpm_active);
up(&dpm_list_sem);
- if (!dev->power.prev_state)
+ if (!dev->power.prev_state.event)
resume_device(dev);
down(&dpm_list_sem);
put_device(dev);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 325962d80191..adbc3148c039 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -13,10 +13,10 @@
static void runtime_resume(struct device * dev)
{
dev_dbg(dev, "resuming\n");
- if (!dev->power.power_state)
+ if (!dev->power.power_state.event)
return;
if (!resume_device(dev))
- dev->power.power_state = 0;
+ dev->power.power_state = PMSG_ON;
}
@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device * dev)
runtime_resume(dev);
up(&dpm_sem);
}
+EXPORT_SYMBOL(dpm_runtime_resume);
/**
@@ -49,10 +50,10 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
int error = 0;
down(&dpm_sem);
- if (dev->power.power_state == state)
+ if (dev->power.power_state.event == state.event)
goto Done;
- if (dev->power.power_state)
+ if (dev->power.power_state.event)
runtime_resume(dev);
if (!(error = suspend_device(dev, state)))
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 2ccee3763acf..50501764d050 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,22 +40,22 @@ int suspend_device(struct device * dev, pm_message_t state)
int error = 0;
down(&dev->sem);
- if (dev->power.power_state) {
+ if (dev->power.power_state.event) {
dev_dbg(dev, "PM: suspend %d-->%d\n",
- dev->power.power_state, state);
+ dev->power.power_state.event, state.event);
}
if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
+ && dev->power.pm_parent->power.power_state.event) {
dev_err(dev,
"PM: suspend %d->%d, parent %s already %d\n",
- dev->power.power_state, state,
+ dev->power.power_state.event, state.event,
dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
+ dev->power.pm_parent->power.power_state.event);
}
dev->power.prev_state = dev->power.power_state;
- if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
+ if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index f82b3df9545f..89c57875f3e5 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -26,19 +26,19 @@
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
- return sprintf(buf, "%u\n", dev->power.power_state);
+ return sprintf(buf, "%u\n", dev->power.power_state.event);
}
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
- u32 state;
+ pm_message_t state;
char * rest;
int error = 0;
- state = simple_strtoul(buf, &rest, 10);
+ state.event = simple_strtoul(buf, &rest, 10);
if (*rest)
return -EINVAL;
- if (state)
+ if (state.event)
error = dpm_runtime_suspend(dev, state);
else
dpm_runtime_resume(dev);
@@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
static DEVICE_ATTR(state, 0644, state_show, state_store);
+/*
+ * wakeup - Report/change current wakeup option for device
+ *
+ * Some devices support "wakeup" events, which are hardware signals
+ * used to activate devices from suspended or low power states. Such
+ * devices have one of three values for the sysfs power/wakeup file:
+ *
+ * + "enabled\n" to issue the events;
+ * + "disabled\n" not to do so; or
+ * + "\n" for temporary or permanent inability to issue wakeup.
+ *
+ * (For example, unconfigured USB devices can't issue wakeups.)
+ *
+ * Familiar examples of devices that can issue wakeup events include
+ * keyboards and mice (both PS2 and USB styles), power buttons, modems,
+ * "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
+ * will wake the entire system from a suspend state; others may just
+ * wake up the device (if the system as a whole is already active).
+ * Some wakeup events use normal IRQ lines; other use special out
+ * of band signaling.
+ *
+ * It is the responsibility of device drivers to enable (or disable)
+ * wakeup signaling as part of changing device power states, respecting
+ * the policy choices provided through the driver model.
+ *
+ * Devices may not be able to generate wakeup events from all power
+ * states. Also, the events may be ignored in some configurations;
+ * for example, they might need help from other devices that aren't
+ * active, or which may have wakeup disabled. Some drivers rely on
+ * wakeup events internally (unless they are disabled), keeping
+ * their hardware in low power modes whenever they're unused. This
+ * saves runtime power, without requiring system-wide sleep states.
+ */
+
+static const char enabled[] = "enabled";
+static const char disabled[] = "disabled";
+
+static ssize_t
+wake_show(struct device * dev, struct device_attribute *attr, char * buf)
+{
+ return sprintf(buf, "%s\n", device_can_wakeup(dev)
+ ? (device_may_wakeup(dev) ? enabled : disabled)
+ : "");
+}
+
+static ssize_t
+wake_store(struct device * dev, struct device_attribute *attr,
+ const char * buf, size_t n)
+{
+ char *cp;
+ int len = n;
+
+ if (!device_can_wakeup(dev))
+ return -EINVAL;
+
+ cp = memchr(buf, '\n', n);
+ if (cp)
+ len = cp - buf;
+ if (len == sizeof enabled - 1
+ && strncmp(buf, enabled, sizeof enabled - 1) == 0)
+ device_set_wakeup_enable(dev, 1);
+ else if (len == sizeof disabled - 1
+ && strncmp(buf, disabled, sizeof disabled - 1) == 0)
+ device_set_wakeup_enable(dev, 0);
+ else
+ return -EINVAL;
+ return n;
+}
+
+static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
+
+
static struct attribute * power_attrs[] = {
&dev_attr_state.attr,
+ &dev_attr_wakeup.attr,
NULL,
};
static struct attribute_group pm_attr_group = {
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 214b96435409..66ed8f2fece5 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pm.h>
+#include <asm/semaphore.h>
extern struct subsystem devices_subsys;
@@ -288,6 +289,27 @@ void sysdev_shutdown(void)
up(&sysdev_drivers_lock);
}
+static void __sysdev_resume(struct sys_device *dev)
+{
+ struct sysdev_class *cls = dev->cls;
+ struct sysdev_driver *drv;
+
+ /* First, call the class-specific one */
+ if (cls->resume)
+ cls->resume(dev);
+
+ /* Call auxillary drivers next. */
+ list_for_each_entry(drv, &cls->drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+
+ /* Call global drivers. */
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
+ if (drv->resume)
+ drv->resume(dev);
+ }
+}
/**
* sysdev_suspend - Suspend all system devices.
@@ -305,38 +327,93 @@ void sysdev_shutdown(void)
int sysdev_suspend(pm_message_t state)
{
struct sysdev_class * cls;
+ struct sys_device *sysdev, *err_dev;
+ struct sysdev_driver *drv, *err_drv;
+ int ret;
pr_debug("Suspending System Devices\n");
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
kset.kobj.entry) {
- struct sys_device * sysdev;
pr_debug("Suspending type '%s':\n",
kobject_name(&cls->kset.kobj));
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto gbl_driver;
+ }
}
/* Call auxillary drivers next. */
list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->suspend)
- drv->suspend(sysdev, state);
+ if (drv->suspend) {
+ ret = drv->suspend(sysdev, state);
+ if (ret)
+ goto aux_driver;
+ }
}
/* Now call the generic one */
- if (cls->suspend)
- cls->suspend(sysdev, state);
+ if (cls->suspend) {
+ ret = cls->suspend(sysdev, state);
+ if (ret)
+ goto cls_driver;
+ }
}
}
return 0;
+ /* resume current sysdev */
+cls_driver:
+ drv = NULL;
+ printk(KERN_ERR "Class suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+
+aux_driver:
+ if (drv)
+ printk(KERN_ERR "Class driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &cls->drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ drv = NULL;
+
+gbl_driver:
+ if (drv)
+ printk(KERN_ERR "sysdev driver suspend failed for %s\n",
+ kobject_name(&sysdev->kobj));
+ list_for_each_entry(err_drv, &sysdev_drivers, entry) {
+ if (err_drv == drv)
+ break;
+ if (err_drv->resume)
+ err_drv->resume(sysdev);
+ }
+ /* resume other sysdevs in current class */
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ if (err_dev == sysdev)
+ break;
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ __sysdev_resume(err_dev);
+ }
+
+ /* resume other classes */
+ list_for_each_entry_continue(cls, &system_subsys.kset.list,
+ kset.kobj.entry) {
+ list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ __sysdev_resume(err_dev);
+ }
+ }
+ return ret;
}
@@ -362,25 +439,9 @@ int sysdev_resume(void)
kobject_name(&cls->kset.kobj));
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver * drv;
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
- /* First, call the class-specific one */
- if (cls->resume)
- cls->resume(sysdev);
-
- /* Call auxillary drivers next. */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
- /* Call global drivers. */
- list_for_each_entry(drv, &sysdev_drivers, entry) {
- if (drv->resume)
- drv->resume(sysdev);
- }
-
+ __sysdev_resume(sysdev);
}
}
return 0;
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 6c2b447a3336..f25e7c6b2d27 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -7,7 +7,7 @@
* This file is licensed under GPLv2
*
* The basic idea here is to allow any "device controller" (which
- * would most often be a Host Bus Adapter" to use the services of one
+ * would most often be a Host Bus Adapter to use the services of one
* or more tranport classes for performing transport specific
* services. Transport specific services are things that the generic
* command layer doesn't want to know about (speed settings, line
@@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
}
EXPORT_SYMBOL_GPL(transport_class_unregister);
-static int anon_transport_dummy_function(struct device *dev)
+static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
/* do nothing */
return 0;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
struct class_device *classdev)
{
struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
if (tclass->setup)
- tclass->setup(dev);
+ tclass->setup(tcont, dev, classdev);
return 0;
}
@@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
EXPORT_SYMBOL_GPL(transport_add_device);
static int transport_configure(struct attribute_container *cont,
- struct device *dev)
+ struct device *dev,
+ struct class_device *cdev)
{
struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
if (tclass->configure)
- tclass->configure(dev);
+ tclass->configure(tcont, dev, cdev);
return 0;
}
@@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
*/
void transport_configure_device(struct device *dev)
{
- attribute_container_trigger(dev, transport_configure);
+ attribute_container_device_trigger(dev, transport_configure);
}
EXPORT_SYMBOL_GPL(transport_configure_device);
@@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
struct transport_class *tclass = class_to_transport_class(cont->class);
if (tclass->remove)
- tclass->remove(dev);
+ tclass->remove(tcont, dev, classdev);
if (tclass->remove != anon_transport_dummy_function) {
if (tcont->statistics)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b594768b0241..51b0af1cebee 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -6,7 +6,7 @@ menu "Block devices"
config BLK_DEV_FD
tristate "Normal floppy disk support"
- depends on (!ARCH_S390 && !M68K && !IA64 && !UML && !ARM) || Q40 || (SUN3X && BROKEN) || ARCH_RPC || ARCH_EBSA285
+ depends on ARCH_MAY_HAVE_PC_FDC
---help---
If you want to use the floppy disk drive(s) of your PC under Linux,
say Y. Information about this driver, especially important for IBM
@@ -408,54 +408,12 @@ config BLK_DEV_INITRD
"real" root file system, etc. See <file:Documentation/initrd.txt>
for details.
-config INITRAMFS_SOURCE
- string "Initramfs source file(s)"
- default ""
- help
- This can be either a single cpio archive with a .cpio suffix or a
- space-separated list of directories and files for building the
- initramfs image. A cpio archive should contain a filesystem archive
- to be used as an initramfs image. Directories should contain a
- filesystem layout to be included in the initramfs image. Files
- should contain entries according to the format described by the
- "usr/gen_init_cpio" program in the kernel tree.
-
- When multiple directories and files are specified then the
- initramfs image will be the aggregate of all of them.
-
- See <file:Documentation/early-userspace/README for more details.
-
- If you are not sure, leave it blank.
-
-config INITRAMFS_ROOT_UID
- int "User ID to map to 0 (user root)"
- depends on INITRAMFS_SOURCE!=""
- default "0"
- help
- This setting is only meaningful if the INITRAMFS_SOURCE is
- contains a directory. Setting this user ID (UID) to something
- other than "0" will cause all files owned by that UID to be
- owned by user root in the initial ramdisk image.
-
- If you are not sure, leave it set to "0".
-
-config INITRAMFS_ROOT_GID
- int "Group ID to map to 0 (group root)"
- depends on INITRAMFS_SOURCE!=""
- default "0"
- help
- This setting is only meaningful if the INITRAMFS_SOURCE is
- contains a directory. Setting this group ID (GID) to something
- other than "0" will cause all files owned by that GID to be
- owned by group root in the initial ramdisk image.
-
- If you are not sure, leave it set to "0".
#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64
#for instance.
config LBD
bool "Support for Large Block Devices"
- depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH || UML
+ depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
help
Say Y here if you want to attach large (bigger than 2TB) discs to
your machine, or if you want to have a raid or loopback device
diff --git a/drivers/block/Kconfig.iosched b/drivers/block/Kconfig.iosched
index 6070a480600b..5b90d2fa63b8 100644
--- a/drivers/block/Kconfig.iosched
+++ b/drivers/block/Kconfig.iosched
@@ -38,4 +38,32 @@ config IOSCHED_CFQ
among all processes in the system. It should provide a fair
working environment, suitable for desktop systems.
+choice
+ prompt "Default I/O scheduler"
+ default DEFAULT_AS
+ help
+ Select the I/O scheduler which will be used by default for all
+ block devices.
+
+ config DEFAULT_AS
+ bool "Anticipatory" if IOSCHED_AS
+
+ config DEFAULT_DEADLINE
+ bool "Deadline" if IOSCHED_DEADLINE
+
+ config DEFAULT_CFQ
+ bool "CFQ" if IOSCHED_CFQ
+
+ config DEFAULT_NOOP
+ bool "No-op"
+
+endchoice
+
+config DEFAULT_IOSCHED
+ string
+ default "anticipatory" if DEFAULT_AS
+ default "deadline" if DEFAULT_DEADLINE
+ default "cfq" if DEFAULT_CFQ
+ default "noop" if DEFAULT_NOOP
+
endmenu
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index ce933de48084..0e1f34fef0c8 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -371,7 +371,7 @@ static int acsi_revalidate (struct gendisk *disk);
/************************* End of Prototypes **************************/
-struct timer_list acsi_timer = TIMER_INITIALIZER(acsi_times_out, 0, 0);
+DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
#ifdef CONFIG_ATARI_SLM
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index e3be8c31a74c..a5c1c8e871ec 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -268,7 +268,7 @@ static int slm_get_pagesize( int device, int *w, int *h );
/************************* End of Prototypes **************************/
-static struct timer_list slm_timer = TIMER_INITIALIZER(slm_test_ready, 0, 0);
+static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
static struct file_operations slm_fops = {
.owner = THIS_MODULE,
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 721ba8086043..881c48d941b7 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
-#define VERSION "10"
+#define VERSION "14"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
@@ -7,12 +7,12 @@
* default is 16, which is 15 partitions plus the whole disk
*/
#ifndef AOE_PARTITIONS
-#define AOE_PARTITIONS 16
+#define AOE_PARTITIONS (16)
#endif
-#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor))
-#define AOEMAJOR(sysminor) ((sysminor) / 10)
-#define AOEMINOR(sysminor) ((sysminor) % 10)
+#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
+#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
+#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
#define WHITESPACE " \t\v\f\n"
enum {
@@ -83,7 +83,7 @@ enum {
enum {
MAXATADATA = 1024,
- NPERSHELF = 10,
+ NPERSHELF = 16, /* number of slots per shelf address */
FREETAG = -1,
MIN_BUFS = 8,
};
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 45a243096187..41ae0ede619a 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -224,7 +224,7 @@ aoechr_init(void)
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_device_create(aoe_class,
+ class_device_create(aoe_class, NULL,
MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index b5be4b7d7b5b..326ca3876b68 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <asm/unaligned.h>
#include "aoe.h"
#define TIMERTICK (HZ / 10)
@@ -311,16 +312,16 @@ ataid_complete(struct aoedev *d, unsigned char *id)
u16 n;
/* word 83: command set supported */
- n = le16_to_cpup((__le16 *) &id[83<<1]);
+ n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
/* word 86: command set/feature enabled */
- n |= le16_to_cpup((__le16 *) &id[86<<1]);
+ n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
if (n & (1<<10)) { /* bit 10: LBA 48 */
d->flags |= DEVFL_EXT;
/* word 100: number lba48 sectors */
- ssize = le64_to_cpup((__le64 *) &id[100<<1]);
+ ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
/* set as in ide-disk.c:init_idedisk_capacity */
d->geo.cylinders = ssize;
@@ -331,12 +332,12 @@ ataid_complete(struct aoedev *d, unsigned char *id)
d->flags &= ~DEVFL_EXT;
/* number lba28 sectors */
- ssize = le32_to_cpup((__le32 *) &id[60<<1]);
+ ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
/* NOTE: obsolete in ATA 6 */
- d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]);
- d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]);
- d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]);
+ d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
+ d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
+ d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
}
d->ssize = ssize;
d->geo.start = 0;
@@ -467,16 +468,11 @@ aoecmd_ata_rsp(struct sk_buff *skb)
unsigned long duration = jiffies - buf->start_time;
unsigned long n_sect = buf->bio->bi_size >> 9;
struct gendisk *disk = d->gd;
+ const int rw = bio_data_dir(buf->bio);
- if (bio_data_dir(buf->bio) == WRITE) {
- disk_stat_inc(disk, writes);
- disk_stat_add(disk, write_ticks, duration);
- disk_stat_add(disk, write_sectors, n_sect);
- } else {
- disk_stat_inc(disk, reads);
- disk_stat_add(disk, read_ticks, duration);
- disk_stat_add(disk, read_sectors, n_sect);
- }
+ disk_stat_inc(disk, ios[rw]);
+ disk_stat_add(disk, ticks[rw], duration);
+ disk_stat_add(disk, sectors[rw], n_sect);
disk_stat_add(disk, io_ticks, duration);
n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
bio_endio(buf->bio, buf->bio->bi_size, n);
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 6e231c5a1199..ded33ba31acc 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -35,7 +35,7 @@ aoedev_newdev(ulong nframes)
struct aoedev *d;
struct frame *f, *e;
- d = kcalloc(1, sizeof *d, GFP_ATOMIC);
+ d = kzalloc(sizeof *d, GFP_ATOMIC);
if (d == NULL)
return NULL;
f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 9e6f51c528b0..4be976940f69 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -120,7 +120,7 @@ aoenet_xmit(struct sk_buff *sl)
* (1) len doesn't include the header by default. I want this.
*/
static int
-aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt)
+aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
{
struct aoe_hdr *h;
u32 n;
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index 95c0a3690b0f..c6744ff38294 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -98,7 +98,6 @@ struct as_data {
struct as_rq *next_arq[2]; /* next in sort order */
sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */
- struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned long exit_prob; /* probability a task will exit while
@@ -239,6 +238,25 @@ static struct io_context *as_get_io_context(void)
return ioc;
}
+static void as_put_io_context(struct as_rq *arq)
+{
+ struct as_io_context *aic;
+
+ if (unlikely(!arq->io_context))
+ return;
+
+ aic = arq->io_context->aic;
+
+ if (arq->is_sync == REQ_SYNC && aic) {
+ spin_lock(&aic->lock);
+ set_bit(AS_TASK_IORUNNING, &aic->state);
+ aic->last_end_request = jiffies;
+ spin_unlock(&aic->lock);
+ }
+
+ put_io_context(arq->io_context);
+}
+
/*
* the back merge hash support functions
*/
@@ -261,14 +279,6 @@ static inline void as_del_arq_hash(struct as_rq *arq)
__as_del_arq_hash(arq);
}
-static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
-{
- as_del_arq_hash(arq);
-
- if (q->last_merge == arq->request)
- q->last_merge = NULL;
-}
-
static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
@@ -312,7 +322,7 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
BUG_ON(!arq->on_hash);
if (!rq_mergeable(__rq)) {
- as_remove_merge_hints(ad->q, arq);
+ as_del_arq_hash(arq);
continue;
}
@@ -950,23 +960,12 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
WARN_ON(!list_empty(&rq->queuelist));
- if (arq->state == AS_RQ_PRESCHED) {
- WARN_ON(arq->io_context);
- goto out;
- }
-
- if (arq->state == AS_RQ_MERGED)
- goto out_ioc;
-
if (arq->state != AS_RQ_REMOVED) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
goto out;
}
- if (!blk_fs_request(rq))
- goto out;
-
if (ad->changed_batch && ad->nr_dispatched == 1) {
kblockd_schedule_work(&ad->antic_work);
ad->changed_batch = 0;
@@ -1001,21 +1000,7 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
}
}
-out_ioc:
- if (!arq->io_context)
- goto out;
-
- if (arq->is_sync == REQ_SYNC) {
- struct as_io_context *aic = arq->io_context->aic;
- if (aic) {
- spin_lock(&aic->lock);
- set_bit(AS_TASK_IORUNNING, &aic->state);
- aic->last_end_request = jiffies;
- spin_unlock(&aic->lock);
- }
- }
-
- put_io_context(arq->io_context);
+ as_put_io_context(arq);
out:
arq->state = AS_RQ_POSTSCHED;
}
@@ -1047,73 +1032,11 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq)
ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
list_del_init(&arq->fifo);
- as_remove_merge_hints(q, arq);
+ as_del_arq_hash(arq);
as_del_arq_rb(ad, arq);
}
/*
- * as_remove_dispatched_request is called to remove a request which has gone
- * to the dispatch list.
- */
-static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
-{
- struct as_rq *arq = RQ_DATA(rq);
- struct as_io_context *aic;
-
- if (!arq) {
- WARN_ON(1);
- return;
- }
-
- WARN_ON(arq->state != AS_RQ_DISPATCHED);
- WARN_ON(ON_RB(&arq->rb_node));
- if (arq->io_context && arq->io_context->aic) {
- aic = arq->io_context->aic;
- if (aic) {
- WARN_ON(!atomic_read(&aic->nr_dispatched));
- atomic_dec(&aic->nr_dispatched);
- }
- }
-}
-
-/*
- * as_remove_request is called when a driver has finished with a request.
- * This should be only called for dispatched requests, but for some reason
- * a POWER4 box running hwscan it does not.
- */
-static void as_remove_request(request_queue_t *q, struct request *rq)
-{
- struct as_rq *arq = RQ_DATA(rq);
-
- if (unlikely(arq->state == AS_RQ_NEW))
- goto out;
-
- if (ON_RB(&arq->rb_node)) {
- if (arq->state != AS_RQ_QUEUED) {
- printk("arq->state %d\n", arq->state);
- WARN_ON(1);
- goto out;
- }
- /*
- * We'll lose the aliased request(s) here. I don't think this
- * will ever happen, but if it does, hopefully someone will
- * report it.
- */
- WARN_ON(!list_empty(&rq->queuelist));
- as_remove_queued_request(q, rq);
- } else {
- if (arq->state != AS_RQ_DISPATCHED) {
- printk("arq->state %d\n", arq->state);
- WARN_ON(1);
- goto out;
- }
- as_remove_dispatched_request(q, rq);
- }
-out:
- arq->state = AS_RQ_REMOVED;
-}
-
-/*
* as_fifo_expired returns 0 if there are no expired reads on the fifo,
* 1 otherwise. It is ratelimited so that we only perform the check once per
* `fifo_expire' interval. Otherwise a large number of expired requests
@@ -1165,7 +1088,6 @@ static inline int as_batch_expired(struct as_data *ad)
static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
{
struct request *rq = arq->request;
- struct list_head *insert;
const int data_dir = arq->is_sync;
BUG_ON(!ON_RB(&arq->rb_node));
@@ -1198,13 +1120,13 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
/*
* take it off the sort and fifo list, add to dispatch queue
*/
- insert = ad->dispatch->prev;
-
while (!list_empty(&rq->queuelist)) {
struct request *__rq = list_entry_rq(rq->queuelist.next);
struct as_rq *__arq = RQ_DATA(__rq);
- list_move_tail(&__rq->queuelist, ad->dispatch);
+ list_del(&__rq->queuelist);
+
+ elv_dispatch_add_tail(ad->q, __rq);
if (__arq->io_context && __arq->io_context->aic)
atomic_inc(&__arq->io_context->aic->nr_dispatched);
@@ -1218,7 +1140,8 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
as_remove_queued_request(ad->q, rq);
WARN_ON(arq->state != AS_RQ_QUEUED);
- list_add(&rq->queuelist, insert);
+ elv_dispatch_sort(ad->q, rq);
+
arq->state = AS_RQ_DISPATCHED;
if (arq->io_context && arq->io_context->aic)
atomic_inc(&arq->io_context->aic->nr_dispatched);
@@ -1230,12 +1153,42 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
* read/write expire, batch expire, etc, and moves it to the dispatch
* queue. Returns 1 if a request was found, 0 otherwise.
*/
-static int as_dispatch_request(struct as_data *ad)
+static int as_dispatch_request(request_queue_t *q, int force)
{
+ struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq;
const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+ if (unlikely(force)) {
+ /*
+ * Forced dispatch, accounting is useless. Reset
+ * accounting states and dump fifo_lists. Note that
+ * batch_data_dir is reset to REQ_SYNC to avoid
+ * screwing write batch accounting as write batch
+ * accounting occurs on W->R transition.
+ */
+ int dispatched = 0;
+
+ ad->batch_data_dir = REQ_SYNC;
+ ad->changed_batch = 0;
+ ad->new_batch = 0;
+
+ while (ad->next_arq[REQ_SYNC]) {
+ as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+ dispatched++;
+ }
+ ad->last_check_fifo[REQ_SYNC] = jiffies;
+
+ while (ad->next_arq[REQ_ASYNC]) {
+ as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+ dispatched++;
+ }
+ ad->last_check_fifo[REQ_ASYNC] = jiffies;
+
+ return dispatched;
+ }
+
/* Signal that the write batch was uncontended, so we can't time it */
if (ad->batch_data_dir == REQ_ASYNC && !reads) {
if (ad->current_write_count == 0 || !writes)
@@ -1359,20 +1312,6 @@ fifo_expired:
return 1;
}
-static struct request *as_next_request(request_queue_t *q)
-{
- struct as_data *ad = q->elevator->elevator_data;
- struct request *rq = NULL;
-
- /*
- * if there are still requests on the dispatch queue, grab the first
- */
- if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
- rq = list_entry_rq(ad->dispatch->next);
-
- return rq;
-}
-
/*
* Add arq to a list behind alias
*/
@@ -1404,17 +1343,26 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia
/*
* Don't want to have to handle merges.
*/
- as_remove_merge_hints(ad->q, arq);
+ as_del_arq_hash(arq);
+ arq->request->flags |= REQ_NOMERGE;
}
/*
* add arq to rbtree and fifo
*/
-static void as_add_request(struct as_data *ad, struct as_rq *arq)
+static void as_add_request(request_queue_t *q, struct request *rq)
{
+ struct as_data *ad = q->elevator->elevator_data;
+ struct as_rq *arq = RQ_DATA(rq);
struct as_rq *alias;
int data_dir;
+ if (arq->state != AS_RQ_PRESCHED) {
+ printk("arq->state: %d\n", arq->state);
+ WARN_ON(1);
+ }
+ arq->state = AS_RQ_NEW;
+
if (rq_data_dir(arq->request) == READ
|| current->flags&PF_SYNCWRITE)
arq->is_sync = 1;
@@ -1437,12 +1385,8 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq)
arq->expires = jiffies + ad->fifo_expire[data_dir];
list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
- if (rq_mergeable(arq->request)) {
+ if (rq_mergeable(arq->request))
as_add_arq_hash(ad, arq);
-
- if (!ad->q->last_merge)
- ad->q->last_merge = arq->request;
- }
as_update_arq(ad, arq); /* keep state machine up to date */
} else {
@@ -1463,96 +1407,24 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq)
arq->state = AS_RQ_QUEUED;
}
-static void as_deactivate_request(request_queue_t *q, struct request *rq)
+static void as_activate_request(request_queue_t *q, struct request *rq)
{
- struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- if (arq) {
- if (arq->state == AS_RQ_REMOVED) {
- arq->state = AS_RQ_DISPATCHED;
- if (arq->io_context && arq->io_context->aic)
- atomic_inc(&arq->io_context->aic->nr_dispatched);
- }
- } else
- WARN_ON(blk_fs_request(rq)
- && (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
-
- /* Stop anticipating - let this request get through */
- as_antic_stop(ad);
-}
-
-/*
- * requeue the request. The request has not been completed, nor is it a
- * new request, so don't touch accounting.
- */
-static void as_requeue_request(request_queue_t *q, struct request *rq)
-{
- as_deactivate_request(q, rq);
- list_add(&rq->queuelist, &q->queue_head);
-}
-
-/*
- * Account a request that is inserted directly onto the dispatch queue.
- * arq->io_context->aic->nr_dispatched should not need to be incremented
- * because only new requests should come through here: requeues go through
- * our explicit requeue handler.
- */
-static void as_account_queued_request(struct as_data *ad, struct request *rq)
-{
- if (blk_fs_request(rq)) {
- struct as_rq *arq = RQ_DATA(rq);
- arq->state = AS_RQ_DISPATCHED;
- ad->nr_dispatched++;
- }
+ WARN_ON(arq->state != AS_RQ_DISPATCHED);
+ arq->state = AS_RQ_REMOVED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_dec(&arq->io_context->aic->nr_dispatched);
}
-static void
-as_insert_request(request_queue_t *q, struct request *rq, int where)
+static void as_deactivate_request(request_queue_t *q, struct request *rq)
{
- struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- if (arq) {
- if (arq->state != AS_RQ_PRESCHED) {
- printk("arq->state: %d\n", arq->state);
- WARN_ON(1);
- }
- arq->state = AS_RQ_NEW;
- }
-
- /* barriers must flush the reorder queue */
- if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
- && where == ELEVATOR_INSERT_SORT)) {
- WARN_ON(1);
- where = ELEVATOR_INSERT_BACK;
- }
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (ad->next_arq[REQ_SYNC])
- as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
-
- while (ad->next_arq[REQ_ASYNC])
- as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
-
- list_add_tail(&rq->queuelist, ad->dispatch);
- as_account_queued_request(ad, rq);
- as_antic_stop(ad);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, ad->dispatch);
- as_account_queued_request(ad, rq);
- as_antic_stop(ad);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- as_add_request(ad, arq);
- break;
- default:
- BUG();
- return;
- }
+ WARN_ON(arq->state != AS_RQ_REMOVED);
+ arq->state = AS_RQ_DISPATCHED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
}
/*
@@ -1565,12 +1437,8 @@ static int as_queue_empty(request_queue_t *q)
{
struct as_data *ad = q->elevator->elevator_data;
- if (!list_empty(&ad->fifo_list[REQ_ASYNC])
- || !list_empty(&ad->fifo_list[REQ_SYNC])
- || !list_empty(ad->dispatch))
- return 0;
-
- return 1;
+ return list_empty(&ad->fifo_list[REQ_ASYNC])
+ && list_empty(&ad->fifo_list[REQ_SYNC]);
}
static struct request *
@@ -1608,15 +1476,6 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
int ret;
/*
- * try last_merge to avoid going to hash
- */
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
- /*
* see if the merge hash can satisfy a back merge
*/
__rq = as_find_arq_hash(ad, bio->bi_sector);
@@ -1644,9 +1503,6 @@ as_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- if (rq_mergeable(__rq))
- q->last_merge = __rq;
-out_insert:
if (ret) {
if (rq_mergeable(__rq))
as_hot_arq_hash(ad, RQ_DATA(__rq));
@@ -1693,9 +1549,6 @@ static void as_merged_request(request_queue_t *q, struct request *req)
* behind the disk head. We currently don't bother adjusting.
*/
}
-
- if (arq->on_hash)
- q->last_merge = req;
}
static void
@@ -1763,6 +1616,7 @@ as_merged_requests(request_queue_t *q, struct request *req,
* kill knowledge of next, this one is a goner
*/
as_remove_queued_request(q, next);
+ as_put_io_context(anext);
anext->state = AS_RQ_MERGED;
}
@@ -1782,7 +1636,7 @@ static void as_work_handler(void *data)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
- if (as_next_request(q))
+ if (!as_queue_empty(q))
q->request_fn(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -1797,7 +1651,9 @@ static void as_put_request(request_queue_t *q, struct request *rq)
return;
}
- if (arq->state != AS_RQ_POSTSCHED && arq->state != AS_RQ_PRESCHED) {
+ if (unlikely(arq->state != AS_RQ_POSTSCHED &&
+ arq->state != AS_RQ_PRESCHED &&
+ arq->state != AS_RQ_MERGED)) {
printk("arq->state %d\n", arq->state);
WARN_ON(1);
}
@@ -1807,7 +1663,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
}
static int as_set_request(request_queue_t *q, struct request *rq,
- struct bio *bio, int gfp_mask)
+ struct bio *bio, gfp_t gfp_mask)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1907,7 +1763,6 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
ad->sort_list[REQ_SYNC] = RB_ROOT;
ad->sort_list[REQ_ASYNC] = RB_ROOT;
- ad->dispatch = &q->queue_head;
ad->fifo_expire[REQ_SYNC] = default_read_expire;
ad->fifo_expire[REQ_ASYNC] = default_write_expire;
ad->antic_expire = default_antic_expire;
@@ -2072,10 +1927,9 @@ static struct elevator_type iosched_as = {
.elevator_merge_fn = as_merge,
.elevator_merged_fn = as_merged_request,
.elevator_merge_req_fn = as_merged_requests,
- .elevator_next_req_fn = as_next_request,
- .elevator_add_req_fn = as_insert_request,
- .elevator_remove_req_fn = as_remove_request,
- .elevator_requeue_req_fn = as_requeue_request,
+ .elevator_dispatch_fn = as_dispatch_request,
+ .elevator_add_req_fn = as_add_request,
+ .elevator_activate_req_fn = as_activate_request,
.elevator_deactivate_req_fn = as_deactivate_request,
.elevator_queue_empty_fn = as_queue_empty,
.elevator_completed_req_fn = as_completed_request,
@@ -2119,8 +1973,8 @@ static int __init as_init(void)
static void __exit as_exit(void)
{
- kmem_cache_destroy(arq_pool);
elv_unregister(&iosched_as);
+ kmem_cache_destroy(arq_pool);
}
module_init(as_init);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index db05a5a99f35..22bda05fc693 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -371,16 +371,10 @@ static int floppy_release( struct inode * inode, struct file * filp );
/************************* End of Prototypes **************************/
-static struct timer_list motor_off_timer =
- TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
-static struct timer_list readtrack_timer =
- TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
-
-static struct timer_list timeout_timer =
- TIMER_INITIALIZER(fd_times_out, 0, 0);
-
-static struct timer_list fd_timer =
- TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
static inline void start_motor_off_timer(void)
{
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 418b1469d75d..486b6e1c7dfb 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -47,14 +47,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.8)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600 P800 E400 E300");
+ " SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -83,12 +83,22 @@ static const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x4091, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
0x103C, 0x3225, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
0x103c, 0x3223, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3231, 0, 0, 0},
+ 0x103c, 0x3234, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3233, 0, 0, 0},
+ 0x103c, 0x3235, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3211, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3212, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3213, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3214, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3215, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -111,8 +121,13 @@ static struct board_type products[] = {
{ 0x40910E11, "Smart Array 6i", &SA5_access},
{ 0x3225103C, "Smart Array P600", &SA5_access},
{ 0x3223103C, "Smart Array P800", &SA5_access},
- { 0x3231103C, "Smart Array E400", &SA5_access},
- { 0x3233103C, "Smart Array E300", &SA5_access},
+ { 0x3234103C, "Smart Array P400", &SA5_access},
+ { 0x3235103C, "Smart Array P400i", &SA5_access},
+ { 0x3211103C, "Smart Array E200i", &SA5_access},
+ { 0x3212103C, "Smart Array E200", &SA5_access},
+ { 0x3213103C, "Smart Array E200i", &SA5_access},
+ { 0x3214103C, "Smart Array E200i", &SA5_access},
+ { 0x3215103C, "Smart Array E200i", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
@@ -140,15 +155,26 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
-static int deregister_disk(struct gendisk *disk);
-static int register_new_disk(ctlr_info_t *h);
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
+static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+ int withirq, unsigned int *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, unsigned int total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
+ drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+ unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
+ int cmd_type);
+
+static void fail_all_cmds(unsigned long ctlr);
#ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
@@ -265,7 +291,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
for(i=0; i<=h->highest_lun; i++) {
drv = &h->drv[i];
- if (drv->block_size == 0)
+ if (drv->heads == 0)
continue;
vol_sz = drv->nr_blocks;
@@ -363,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL;
memset(c, 0, sizeof(CommandList_struct));
+ c->cmdindex = -1;
+
c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle);
@@ -393,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct);
h->nr_allocs++;
+
+ c->cmdindex = i;
}
c->busaddr = (__u32) cmd_dma_handle;
@@ -453,6 +483,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
+ if (host->busy_initializing || drv->busy_configuring)
+ return -EBUSY;
/*
* Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. Root is also allowed to open any
@@ -796,10 +828,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return(0);
}
case CCISS_DEREGDISK:
- return deregister_disk(disk);
+ return rebuild_lun_table(host, disk);
case CCISS_REGNEWD:
- return register_new_disk(host);
+ return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU:
{
@@ -1143,48 +1175,323 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
-static int deregister_disk(struct gendisk *disk)
+/* This function will check the usage_count of the drive to be updated/added.
+ * If the usage_count is zero then the drive information will be updated and
+ * the disk will be re-registered with the kernel. If not then it will be
+ * left alone for the next reboot. The exception to this is disk 0 which
+ * will always be left registered with the kernel since it is also the
+ * controller node. Any changes to disk 0 will show up on the next
+ * reboot.
+*/
+static void cciss_update_drive_info(int ctlr, int drv_index)
+ {
+ ctlr_info_t *h = hba[ctlr];
+ struct gendisk *disk;
+ ReadCapdata_struct *size_buff = NULL;
+ InquiryData_struct *inq_buff = NULL;
+ unsigned int block_size;
+ unsigned int total_size;
+ unsigned long flags = 0;
+ int ret = 0;
+
+ /* if the disk already exists then deregister it before proceeding*/
+ if (h->drv[drv_index].raid_level != -1){
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ h->drv[drv_index].busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ ret = deregister_disk(h->gendisk[drv_index],
+ &h->drv[drv_index], 0);
+ h->drv[drv_index].busy_configuring = 0;
+ }
+
+ /* If the disk is in use return */
+ if (ret)
+ return;
+
+
+ /* Get information about the disk and modify the driver sturcture */
+ size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL)
+ goto mem_msg;
+ inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL)
+ goto mem_msg;
+
+ cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ &total_size, &block_size);
+ cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+ inq_buff, &h->drv[drv_index]);
+
+ ++h->num_luns;
+ disk = h->gendisk[drv_index];
+ set_capacity(disk, h->drv[drv_index].nr_blocks);
+
+
+ /* if it's the controller it's already added */
+ if (drv_index){
+ disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+
+ /* Set up queue information */
+ disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
+ blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
+
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+
+ blk_queue_max_sectors(disk->queue, 512);
+
+ disk->queue->queuedata = hba[ctlr];
+
+ blk_queue_hardsect_size(disk->queue,
+ hba[ctlr]->drv[drv_index].block_size);
+
+ h->drv[drv_index].queue = disk->queue;
+ add_disk(disk);
+ }
+
+freeret:
+ kfree(size_buff);
+ kfree(inq_buff);
+ return;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will find the first index of the controllers drive array
+ * that has a -1 for the raid_level and will return that index. This is
+ * where new drives will be added. If the index to be returned is greater
+ * than the highest_lun index for the controller then highest_lun is set
+ * to this new index. If there are no available indexes then -1 is returned.
+*/
+static int cciss_find_free_drive_index(int ctlr)
{
+ int i;
+
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if (hba[ctlr]->drv[i].raid_level == -1){
+ if (i > hba[ctlr]->highest_lun)
+ hba[ctlr]->highest_lun = i;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* This function will add and remove logical drives from the Logical
+ * drive array of the controller and maintain persistancy of ordering
+ * so that mount points are preserved until the next reboot. This allows
+ * for the removal of logical drives in the middle of the drive array
+ * without a re-ordering of those drives.
+ * INPUT
+ * h = The controller to perform the operations on
+ * del_disk = The disk to remove if specified. If the value given
+ * is NULL then no disk is removed.
+*/
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
+{
+ int ctlr = h->ctlr;
+ int num_luns;
+ ReportLunData_struct *ld_buff = NULL;
+ drive_info_struct *drv = NULL;
+ int return_code;
+ int listlength = 0;
+ int i;
+ int drv_found;
+ int drv_index = 0;
+ __u32 lunid = 0;
unsigned long flags;
+
+ /* Set busy_configuring flag for this operation */
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ if (h->num_luns >= CISS_MAX_LUN){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EINVAL;
+ }
+
+ if (h->busy_configuring){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EBUSY;
+ }
+ h->busy_configuring = 1;
+
+ /* if del_disk is NULL then we are being called to add a new disk
+ * and update the logical drive table. If it is not NULL then
+ * we will check if the disk is in use or not.
+ */
+ if (del_disk != NULL){
+ drv = get_drv(del_disk);
+ drv->busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return_code = deregister_disk(del_disk, drv, 1);
+ drv->busy_configuring = 0;
+ h->busy_configuring = 0;
+ return return_code;
+ } else {
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ if (ld_buff == NULL)
+ goto mem_msg;
+
+ return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
+ sizeof(ReportLunData_struct), 0, 0, 0,
+ TYPE_CMD);
+
+ if (return_code == IO_OK){
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
+ listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+ } else{ /* reading number of logical volumes failed */
+ printk(KERN_WARNING "cciss: report logical volume"
+ " command failed\n");
+ listlength = 0;
+ goto freeret;
+ }
+
+ num_luns = listlength / 8; /* 8 bytes per entry */
+ if (num_luns > CISS_MAX_LUN){
+ num_luns = CISS_MAX_LUN;
+ printk(KERN_WARNING "cciss: more luns configured"
+ " on controller than can be handled by"
+ " this driver.\n");
+ }
+
+ /* Compare controller drive array to drivers drive array.
+ * Check for updates in the drive information and any new drives
+ * on the controller.
+ */
+ for (i=0; i < num_luns; i++){
+ int j;
+
+ drv_found = 0;
+
+ lunid = (0xff &
+ (unsigned int)(ld_buff->LUN[i][3])) << 24;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][2])) << 16;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ lunid |= 0xff &
+ (unsigned int)(ld_buff->LUN[i][0]);
+
+ /* Find if the LUN is already in the drive array
+ * of the controller. If so then update its info
+ * if not is use. If it does not exist then find
+ * the first free index and add it.
+ */
+ for (j=0; j <= h->highest_lun; j++){
+ if (h->drv[j].LunID == lunid){
+ drv_index = j;
+ drv_found = 1;
+ }
+ }
+
+ /* check if the drive was found already in the array */
+ if (!drv_found){
+ drv_index = cciss_find_free_drive_index(ctlr);
+ if (drv_index == -1)
+ goto freeret;
+
+ }
+ h->drv[drv_index].LunID = lunid;
+ cciss_update_drive_info(ctlr, drv_index);
+ } /* end for */
+ } /* end else */
+
+freeret:
+ kfree(ld_buff);
+ h->busy_configuring = 0;
+ /* We return -1 here to tell the ACU that we have registered/updated
+ * all of the drives that we can and to keep it from calling us
+ * additional times.
+ */
+ return -1;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will deregister the disk and it's queue from the
+ * kernel. It must be called with the controller lock held and the
+ * drv structures busy_configuring flag set. It's parameters are:
+ *
+ * disk = This is the disk to be deregistered
+ * drv = This is the drive_info_struct associated with the disk to be
+ * deregistered. It contains information about the disk used
+ * by the driver.
+ * clear_all = This flag determines whether or not the disk information
+ * is going to be completely cleared out and the highest_lun
+ * reset. Sometimes we want to clear out information about
+ * the disk in preperation for re-adding it. In this case
+ * the highest_lun should be left unchanged and the LunID
+ * should not be cleared.
+*/
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+ int clear_all)
+{
ctlr_info_t *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
- int ctlr = h->ctlr;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
/* make sure logical volume is NOT is use */
- if( drv->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if(clear_all || (h->gendisk[0] == disk)) {
+ if (drv->usage_count > 1)
return -EBUSY;
}
- drv->usage_count++;
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ else
+ if( drv->usage_count > 0 )
+ return -EBUSY;
- /* invalidate the devices and deregister the disk */
- if (disk->flags & GENHD_FL_UP)
+ /* invalidate the devices and deregister the disk. If it is disk
+ * zero do not deregister it but just zero out it's values. This
+ * allows us to delete disk zero but keep the controller registered.
+ */
+ if (h->gendisk[0] != disk){
+ if (disk->flags & GENHD_FL_UP){
+ blk_cleanup_queue(disk->queue);
del_gendisk(disk);
+ drv->queue = NULL;
+ }
+ }
+
+ --h->num_luns;
+ /* zero out the disk size info */
+ drv->nr_blocks = 0;
+ drv->block_size = 0;
+ drv->heads = 0;
+ drv->sectors = 0;
+ drv->cylinders = 0;
+ drv->raid_level = -1; /* This can be used as a flag variable to
+ * indicate that this element of the drive
+ * array is free.
+ */
+
+ if (clear_all){
/* check to see if it was the last disk */
if (drv == h->drv + h->highest_lun) {
/* if so, find the new hightest lun */
int i, newhighest =-1;
for(i=0; i<h->highest_lun; i++) {
/* if the disk has size > 0, it is available */
- if (h->drv[i].nr_blocks)
+ if (h->drv[i].heads)
newhighest = i;
}
h->highest_lun = newhighest;
-
}
- --h->num_luns;
- /* zero out the disk size info */
- drv->nr_blocks = 0;
- drv->block_size = 0;
- drv->cylinders = 0;
+
drv->LunID = 0;
+ }
return(0);
}
+
static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
size_t size,
unsigned int use_unit_num, /* 0: address the controller,
@@ -1420,8 +1727,10 @@ case CMD_HARDWARE_ERR:
}
}
/* unlock the buffers from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(h, c, 0);
return(return_status);
@@ -1495,164 +1804,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
return;
}
-static int register_new_disk(ctlr_info_t *h)
-{
- struct gendisk *disk;
- int ctlr = h->ctlr;
- int i;
- int num_luns;
- int logvol;
- int new_lun_found = 0;
- int new_lun_index = 0;
- int free_index_found = 0;
- int free_index = 0;
- ReportLunData_struct *ld_buff = NULL;
- ReadCapdata_struct *size_buff = NULL;
- InquiryData_struct *inq_buff = NULL;
- int return_code;
- int listlength = 0;
- __u32 lunid = 0;
- unsigned int block_size;
- unsigned int total_size;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- /* if we have no space in our disk array left to add anything */
- if( h->num_luns >= CISS_MAX_LUN)
- return -EINVAL;
-
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
- if (ld_buff == NULL)
- goto mem_msg;
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- goto mem_msg;
-
- return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
- sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
-
- if( return_code == IO_OK)
- {
-
- // printk("LUN Data\n--------------------------\n");
-
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
- listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
- } else /* reading number of logical volumes failed */
- {
- printk(KERN_WARNING "cciss: report logical volume"
- " command failed\n");
- listlength = 0;
- goto free_err;
- }
- num_luns = listlength / 8; // 8 bytes pre entry
- if (num_luns > CISS_MAX_LUN)
- {
- num_luns = CISS_MAX_LUN;
- }
-#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
- ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
- ld_buff->LUNListLength[3], num_luns);
-#endif
- for(i=0; i< num_luns; i++)
- {
- int j;
- int lunID_found = 0;
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
- lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-
- /* check to see if this is a new lun */
- for(j=0; j <= h->highest_lun; j++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
- lunid);
-#endif /* CCISS_DEBUG */
- if (h->drv[j].LunID == lunid)
- {
- lunID_found = 1;
- break;
- }
-
- }
- if( lunID_found == 1)
- continue;
- else
- { /* It is the new lun we have been looking for */
-#ifdef CCISS_DEBUG
- printk("new lun found at %d\n", i);
-#endif /* CCISS_DEBUG */
- new_lun_index = i;
- new_lun_found = 1;
- break;
- }
- }
- if (!new_lun_found)
- {
- printk(KERN_WARNING "cciss: New Logical Volume not found\n");
- goto free_err;
- }
- /* Now find the free index */
- for(i=0; i <CISS_MAX_LUN; i++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking Index %d\n", i);
-#endif /* CCISS_DEBUG */
- if(h->drv[i].LunID == 0)
- {
-#ifdef CCISS_DEBUG
- printk("free index found at %d\n", i);
-#endif /* CCISS_DEBUG */
- free_index_found = 1;
- free_index = i;
- break;
- }
- }
- if (!free_index_found)
- {
- printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
- goto free_err;
- }
-
- logvol = free_index;
- h->drv[logvol].LunID = lunid;
- /* there could be gaps in lun numbers, track hightest */
- if(h->highest_lun < lunid)
- h->highest_lun = logvol;
- cciss_read_capacity(ctlr, logvol, size_buff, 1,
- &total_size, &block_size);
- cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
- inq_buff, &h->drv[logvol]);
- h->drv[logvol].usage_count = 0;
- ++h->num_luns;
- /* setup partitions per disk */
- disk = h->gendisk[logvol];
- set_capacity(disk, h->drv[logvol].nr_blocks);
- /* if it's the controller it's already added */
- if(logvol)
- add_disk(disk);
-freeret:
- kfree(ld_buff);
- kfree(size_buff);
- kfree(inq_buff);
- return (logvol);
-mem_msg:
- printk(KERN_ERR "cciss: out of memory\n");
-free_err:
- logvol = -1;
- goto freeret;
-}
-
static int cciss_revalidate(struct gendisk *disk)
{
ctlr_info_t *h = get_host(disk);
@@ -1713,10 +1864,9 @@ static unsigned long pollcomplete(int ctlr)
for (i = 20 * HZ; i > 0; i--) {
done = hba[ctlr]->access.command_completed(hba[ctlr]);
- if (done == FIFO_EMPTY) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } else
+ if (done == FIFO_EMPTY)
+ schedule_timeout_uninterruptible(1);
+ else
return (done);
}
/* Invalid address to tell caller we ran out of time */
@@ -1860,8 +2010,10 @@ resend_cmd1:
cleanup1:
/* unlock the data buffer from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(info_p, c, 1);
return (status);
}
@@ -2112,7 +2264,11 @@ queue:
/* fill in the request */
drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode
- c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
+ /* got command from pool, so use the command block index instead */
+ /* for direct lookups. */
+ /* The first 2 bits are reserved for controller error reporting. */
+ c->Header.Tag.lower = (c->cmdindex << 3);
+ c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
@@ -2187,7 +2343,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
ctlr_info_t *h = dev_id;
CommandList_struct *c;
unsigned long flags;
- __u32 a, a1;
+ __u32 a, a1, a2;
int j;
int start_queue = h->next_to_run;
@@ -2205,10 +2361,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{
a1 = a;
+ if ((a & 0x04)) {
+ a2 = (a >> 3);
+ if (a2 >= NR_CMDS) {
+ printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+ fail_all_cmds(h->ctlr);
+ return IRQ_HANDLED;
+ }
+
+ c = h->cmd_pool + a2;
+ a = c->busaddr;
+
+ } else {
a &= ~3;
- if ((c = h->cmpQ) == NULL)
- {
- printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
+ if ((c = h->cmpQ) == NULL) {
+ printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
continue;
}
while(c->busaddr != a) {
@@ -2216,6 +2383,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
if (c == h->cmpQ)
break;
}
+ }
/*
* If we've found the command, take it off the
* completion Q and free it
@@ -2635,12 +2803,16 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
- for(i=0; i< hba[cntl_num]->num_luns; i++)
+// for(i=0; i< hba[cntl_num]->num_luns; i++)
+ for(i=0; i < CISS_MAX_LUN; i++)
{
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ if (i < hba[cntl_num]->num_luns){
+ lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+ << 24;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+ << 16;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+ << 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
hba[cntl_num]->drv[i].LunID = lunid;
@@ -2648,13 +2820,18 @@ static void cciss_getgeometry(int cntl_num)
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
- ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2],
- ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
+ ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+ ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+ hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
&total_size, &block_size);
- cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
- inq_buff, &hba[cntl_num]->drv[i]);
+ cciss_geometry_inquiry(cntl_num, i, 0, total_size,
+ block_size, inq_buff, &hba[cntl_num]->drv[i]);
+ } else {
+ /* initialize raid_level to indicate a free space */
+ hba[cntl_num]->drv[i].raid_level = -1;
+ }
}
kfree(ld_buff);
kfree(size_buff);
@@ -2728,6 +2905,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
i = alloc_cciss_hba();
if(i < 0)
return (-1);
+
+ hba[i]->busy_initializing = 1;
+
if (cciss_pci_init(hba[i], pdev) != 0)
goto clean1;
@@ -2808,6 +2988,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
cciss_procinit(i);
+ hba[i]->busy_initializing = 0;
for(j=0; j < NWD; j++) { /* mfm */
drive_info_struct *drv = &(hba[i]->drv[j]);
@@ -2870,6 +3051,7 @@ clean2:
clean1:
release_io_mem(hba[i]);
free_hba(i);
+ hba[i]->busy_initializing = 0;
return(-1);
}
@@ -2914,9 +3096,10 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
- if (disk->flags & GENHD_FL_UP)
- blk_cleanup_queue(disk->queue);
+ if (disk->flags & GENHD_FL_UP) {
del_gendisk(disk);
+ blk_cleanup_queue(disk->queue);
+ }
}
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
@@ -2965,5 +3148,43 @@ static void __exit cciss_cleanup(void)
remove_proc_entry("cciss", proc_root_driver);
}
+static void fail_all_cmds(unsigned long ctlr)
+{
+ /* If we get here, the board is apparently dead. */
+ ctlr_info_t *h = hba[ctlr];
+ CommandList_struct *c;
+ unsigned long flags;
+
+ printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
+ h->alive = 0; /* the controller apparently died... */
+
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+ pci_disable_device(h->pdev); /* Make sure it is really dead. */
+
+ /* move everything off the request queue onto the completed queue */
+ while( (c = h->reqQ) != NULL ) {
+ removeQ(&(h->reqQ), c);
+ h->Qdepth--;
+ addQ (&(h->cmpQ), c);
+ }
+
+ /* Now, fail everything on the completed queue with a HW error */
+ while( (c = h->cmpQ) != NULL ) {
+ removeQ(&h->cmpQ, c);
+ c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+ if (c->cmd_type == CMD_RWREQ) {
+ complete_command(h, c, 0);
+ } else if (c->cmd_type == CMD_IOCTL_PEND)
+ complete(c->waiting);
+#ifdef CONFIG_CISS_SCSI_TAPE
+ else if (c->cmd_type == CMD_SCSI)
+ complete_scsi_command(c, 0, 0);
+#endif
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ return;
+}
+
module_init(cciss_init);
module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 566587d0a500..ef277baee9fd 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct
int heads;
int sectors;
int cylinders;
- int raid_level;
+ int raid_level; /* set to -1 to indicate that
+ * the drive is not in use/configured
+ */
+ int busy_configuring; /*This is set when the drive is being removed
+ *to prevent it from being opened or it's queue
+ *from being started.
+ */
} drive_info_struct;
struct ctlr_info
@@ -83,6 +89,7 @@ struct ctlr_info
int nr_allocs;
int nr_frees;
int busy_configuring;
+ int busy_initializing;
/* This element holds the zero based queue number of the last
* queue to be started. It is used for fairness.
@@ -94,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif
+ unsigned char alive;
};
/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a88817623..53fea549ba8b 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04
#define CMD_MSG_TIMEOUT 0x05
+/* This structure needs to be divisible by 8 for new
+ * indexing method.
+ */
+#define PADSIZE (sizeof(long) - 4)
typedef struct _CommandList_struct {
CommandListHeader_struct Header;
RequestBlock_struct Request;
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr;
int cmd_type;
+ long cmdindex;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
struct request * rq;
struct completion *waiting;
int retry_count;
-#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd;
-#endif
+ char pad[PADSIZE];
} CommandList_struct;
//Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3caed58a..ec27976a57da 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -28,13 +28,17 @@
through the array controller. Note in particular, neither
physical nor logical disks are presented through the scsi layer. */
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/atomic.h>
+
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#include <asm/atomic.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
#include "cciss_scsi.h"
@@ -93,6 +97,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd;
ErrorInfo_struct Err;
__u32 busaddr;
+ __u32 pad;
};
#pragma pack()
@@ -877,7 +882,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
- InquiryData_struct *buf)
+ unsigned char *buf, unsigned char bufsize)
{
int rc;
CommandList_struct *cp;
@@ -900,11 +905,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
cdb[1] = 0;
cdb[2] = 0;
cdb[3] = 0;
- cdb[4] = sizeof(*buf) & 0xff;
+ cdb[4] = bufsize;
cdb[5] = 0;
rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
- 6, (unsigned char *) buf,
- sizeof(*buf), XFER_READ);
+ 6, buf, bufsize, XFER_READ);
if (rc != 0) return rc; /* something went wrong */
@@ -1000,9 +1004,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
that though.
*/
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
ReportLunData_struct *ld_buff;
- InquiryData_struct *inq_buff;
+ unsigned char *inq_buff;
unsigned char scsi3addr[8];
ctlr_info_t *c;
__u32 num_luns=0;
@@ -1020,7 +1025,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
return;
}
memset(ld_buff, 0, reportlunsize);
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
@@ -1051,19 +1056,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
/* for each physical lun, do an inquiry */
if (ld_buff->LUN[i][3] & 0xC0) continue;
- memset(inq_buff, 0, sizeof(InquiryData_struct));
+ 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) != 0)
- {
+ if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 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->data_byte[0] & 0x1f);
+ devtype = (inq_buff[0] & 0x1f);
switch (devtype)
{
+ case 0x05: /* CD-ROM */ {
+
+ /* We don't *really* support actual CD-ROM devices,
+ * just this "One Button Disaster Recovery" tape drive
+ * which temporarily pretends to be a CD-ROM drive.
+ * So we check that the device is really an OBDR tape
+ * device by checking for "$DR-10" in bytes 43-48 of
+ * the inquiry data.
+ */
+ char obdr_sig[7];
+
+ strncpy(obdr_sig, &inq_buff[43], 6);
+ obdr_sig[6] = '\0';
+ if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+ /* Not OBDR device, ignore it. */
+ break;
+ }
+ /* fall through . . . */
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1148,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
int buflen, datalen;
ctlr_info_t *ci;
+ int i;
int cntl_num;
@@ -1136,8 +1159,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
cntl_num = ci->ctlr; /* Get our index into the hba[] array */
if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
- buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no);
-
+ buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
+ cntl_num, sh->host_no);
+
+ /* this information is needed by apps to know which cciss
+ device corresponds to which scsi host number without
+ having to open a scsi target device node. The device
+ information is not a duplicate of /proc/scsi/scsi because
+ the two may be out of sync due to scsi hotplug, rather
+ this info is for an app to be able to use to know how to
+ get them back in sync. */
+
+ for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
+ struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
+ buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ sh->host_no, sd->bus, sd->target, sd->lun,
+ sd->devtype,
+ sd->scsi3addr[0], sd->scsi3addr[1],
+ sd->scsi3addr[2], sd->scsi3addr[3],
+ sd->scsi3addr[4], sd->scsi3addr[5],
+ sd->scsi3addr[6], sd->scsi3addr[7]);
+ }
datalen = buflen - offset;
if (datalen < 0) { /* they're reading past EOF. */
datalen = 0;
@@ -1399,7 +1442,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
CPQ_TAPE_LOCK(ctlr, flags);
size = sprintf(buffer + *len,
- " Sequential access devices: %d\n\n",
+ "Sequential access devices: %d\n\n",
ccissscsi[ctlr].ndevices);
CPQ_TAPE_UNLOCK(ctlr, flags);
*pos += size; *len += size;
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 2435a7c99b2b..ecacca9c877e 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -47,7 +47,7 @@ static int cfq_slice_idle = HZ / 100;
/*
* disable queueing at the driver/hardware level
*/
-static int cfq_max_depth = 1;
+static int cfq_max_depth = 2;
/*
* for the hash of cfqq inside the cfqd
@@ -84,7 +84,6 @@ static int cfq_max_depth = 1;
(node)->rb_left = NULL; \
} while (0)
#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL)
-#define ON_RB(node) ((node)->rb_color != RB_NONE)
#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node)
#define rq_rb_key(rq) (rq)->sector
@@ -271,10 +270,7 @@ CFQ_CFQQ_FNS(expired);
#undef CFQ_CFQQ_FNS
enum cfq_rq_state_flags {
- CFQ_CRQ_FLAG_in_flight = 0,
- CFQ_CRQ_FLAG_in_driver,
- CFQ_CRQ_FLAG_is_sync,
- CFQ_CRQ_FLAG_requeued,
+ CFQ_CRQ_FLAG_is_sync = 0,
};
#define CFQ_CRQ_FNS(name) \
@@ -291,14 +287,11 @@ static inline int cfq_crq_##name(const struct cfq_rq *crq) \
return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \
}
-CFQ_CRQ_FNS(in_flight);
-CFQ_CRQ_FNS(in_driver);
CFQ_CRQ_FNS(is_sync);
-CFQ_CRQ_FNS(requeued);
#undef CFQ_CRQ_FNS
static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
-static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
+static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
static void cfq_put_cfqd(struct cfq_data *cfqd);
#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
@@ -311,14 +304,6 @@ static inline void cfq_del_crq_hash(struct cfq_rq *crq)
hlist_del_init(&crq->hash);
}
-static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
-{
- cfq_del_crq_hash(crq);
-
- if (q->last_merge == crq->request)
- q->last_merge = NULL;
-}
-
static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
{
const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
@@ -347,18 +332,13 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
return NULL;
}
-static inline int cfq_pending_requests(struct cfq_data *cfqd)
-{
- return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
-}
-
/*
* scheduler run of queue, if there are requests pending and no one in the
* driver that will restart queueing
*/
static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
{
- if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
+ if (!cfqd->rq_in_driver && cfqd->busy_queues)
kblockd_schedule_work(&cfqd->unplug_work);
}
@@ -366,7 +346,7 @@ static int cfq_queue_empty(request_queue_t *q)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- return !cfq_pending_requests(cfqd);
+ return !cfqd->busy_queues;
}
/*
@@ -385,9 +365,10 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
return crq2;
if (crq2 == NULL)
return crq1;
- if (cfq_crq_requeued(crq1))
+
+ if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
return crq1;
- if (cfq_crq_requeued(crq2))
+ else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
return crq2;
s1 = crq1->request->sector;
@@ -455,10 +436,7 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
struct rb_node *rbnext, *rbprev;
- rbnext = NULL;
- if (ON_RB(&last->rb_node))
- rbnext = rb_next(&last->rb_node);
- if (!rbnext) {
+ if (!(rbnext = rb_next(&last->rb_node))) {
rbnext = rb_first(&cfqq->sort_list);
if (rbnext == &last->rb_node)
rbnext = NULL;
@@ -539,13 +517,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
* the pending list according to last request service
*/
static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
BUG_ON(cfq_cfqq_on_rr(cfqq));
cfq_mark_cfqq_on_rr(cfqq);
cfqd->busy_queues++;
- cfq_resort_rr_list(cfqq, requeue);
+ cfq_resort_rr_list(cfqq, 0);
}
static inline void
@@ -565,22 +543,19 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
static inline void cfq_del_crq_rb(struct cfq_rq *crq)
{
struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int sync = cfq_crq_is_sync(crq);
- if (ON_RB(&crq->rb_node)) {
- struct cfq_data *cfqd = cfqq->cfqd;
- const int sync = cfq_crq_is_sync(crq);
-
- BUG_ON(!cfqq->queued[sync]);
- cfqq->queued[sync]--;
+ BUG_ON(!cfqq->queued[sync]);
+ cfqq->queued[sync]--;
- cfq_update_next_crq(crq);
+ cfq_update_next_crq(crq);
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- RB_CLEAR_COLOR(&crq->rb_node);
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ RB_CLEAR_COLOR(&crq->rb_node);
- if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
- cfq_del_cfqq_rr(cfqd, cfqq);
- }
+ if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+ cfq_del_cfqq_rr(cfqd, cfqq);
}
static struct cfq_rq *
@@ -621,12 +596,12 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
* if that happens, put the alias on the dispatch list
*/
while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
- cfq_dispatch_sort(cfqd->queue, __alias);
+ cfq_dispatch_insert(cfqd->queue, __alias);
rb_insert_color(&crq->rb_node, &cfqq->sort_list);
if (!cfq_cfqq_on_rr(cfqq))
- cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
+ cfq_add_cfqq_rr(cfqd, cfqq);
/*
* check if this request is a better next-serve candidate
@@ -637,10 +612,8 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
static inline void
cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
{
- if (ON_RB(&crq->rb_node)) {
- rb_erase(&crq->rb_node, &cfqq->sort_list);
- cfqq->queued[cfq_crq_is_sync(crq)]--;
- }
+ rb_erase(&crq->rb_node, &cfqq->sort_list);
+ cfqq->queued[cfq_crq_is_sync(crq)]--;
cfq_add_crq_rb(crq);
}
@@ -670,49 +643,28 @@ out:
return NULL;
}
-static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
+static void cfq_activate_request(request_queue_t *q, struct request *rq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- struct cfq_rq *crq = RQ_DATA(rq);
- if (crq) {
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- if (cfq_crq_in_driver(crq)) {
- cfq_clear_crq_in_driver(crq);
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
- }
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
-
- cfq_clear_crq_in_flight(crq);
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
- }
- cfq_mark_crq_requeued(crq);
- }
+ cfqd->rq_in_driver++;
}
-/*
- * make sure the service time gets corrected on reissue of this request
- */
-static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
{
- cfq_deactivate_request(q, rq);
- list_add(&rq->queuelist, &q->queue_head);
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+
+ WARN_ON(!cfqd->rq_in_driver);
+ cfqd->rq_in_driver--;
}
-static void cfq_remove_request(request_queue_t *q, struct request *rq)
+static void cfq_remove_request(struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- if (crq) {
- list_del_init(&rq->queuelist);
- cfq_del_crq_rb(crq);
- cfq_remove_merge_hints(q, crq);
-
- }
+ list_del_init(&rq->queuelist);
+ cfq_del_crq_rb(crq);
+ cfq_del_crq_hash(crq);
}
static int
@@ -722,12 +674,6 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_BACK_MERGE;
@@ -742,8 +688,6 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- q->last_merge = __rq;
-out_insert:
*req = __rq;
return ret;
}
@@ -756,14 +700,12 @@ static void cfq_merged_request(request_queue_t *q, struct request *req)
cfq_del_crq_hash(crq);
cfq_add_crq_hash(cfqd, crq);
- if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
+ if (rq_rb_key(req) != crq->rb_key) {
struct cfq_queue *cfqq = crq->cfq_queue;
cfq_update_next_crq(crq);
cfq_reposition_crq_rb(cfqq, crq);
}
-
- q->last_merge = req;
}
static void
@@ -779,7 +721,7 @@ cfq_merged_requests(request_queue_t *q, struct request *rq,
time_before(next->start_time, rq->start_time))
list_move(&rq->queuelist, &next->queuelist);
- cfq_remove_request(q, next);
+ cfq_remove_request(next);
}
static inline void
@@ -986,53 +928,15 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
return 1;
}
-/*
- * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
- * this function sector sorts the selected request to minimize seeks. we start
- * at cfqd->last_sector, not 0.
- */
-static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
+static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq = crq->cfq_queue;
- struct list_head *head = &q->queue_head, *entry = head;
- struct request *__rq;
- sector_t last;
-
- list_del(&crq->request->queuelist);
-
- last = cfqd->last_sector;
- list_for_each_entry_reverse(__rq, head, queuelist) {
- struct cfq_rq *__crq = RQ_DATA(__rq);
-
- if (blk_barrier_rq(__rq))
- break;
- if (!blk_fs_request(__rq))
- break;
- if (cfq_crq_requeued(__crq))
- break;
-
- if (__rq->sector <= crq->request->sector)
- break;
- if (__rq->sector > last && crq->request->sector < last) {
- last = crq->request->sector + crq->request->nr_sectors;
- break;
- }
- entry = &__rq->queuelist;
- }
-
- cfqd->last_sector = last;
cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
-
- cfq_del_crq_rb(crq);
- cfq_remove_merge_hints(q, crq);
-
- cfq_mark_crq_in_flight(crq);
- cfq_clear_crq_requeued(crq);
-
+ cfq_remove_request(crq->request);
cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
- list_add_tail(&crq->request->queuelist, entry);
+ elv_dispatch_sort(q, crq->request);
}
/*
@@ -1153,7 +1057,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
/*
* finally, insert request into driver dispatch list
*/
- cfq_dispatch_sort(cfqd->queue, crq);
+ cfq_dispatch_insert(cfqd->queue, crq);
cfqd->dispatch_slice++;
dispatched++;
@@ -1188,7 +1092,7 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
static int
-cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
+cfq_dispatch_requests(request_queue_t *q, int force)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_queue *cfqq;
@@ -1198,12 +1102,25 @@ cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
cfqq = cfq_select_queue(cfqd, force);
if (cfqq) {
+ int max_dispatch;
+
+ /*
+ * if idle window is disabled, allow queue buildup
+ */
+ if (!cfq_cfqq_idle_window(cfqq) &&
+ cfqd->rq_in_driver >= cfqd->cfq_max_depth)
+ return 0;
+
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
- if (cfq_class_idle(cfqq))
- max_dispatch = 1;
+ if (!force) {
+ max_dispatch = cfqd->cfq_quantum;
+ if (cfq_class_idle(cfqq))
+ max_dispatch = 1;
+ } else
+ max_dispatch = INT_MAX;
return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
}
@@ -1211,93 +1128,6 @@ cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
return 0;
}
-static inline void cfq_account_dispatch(struct cfq_rq *crq)
-{
- struct cfq_queue *cfqq = crq->cfq_queue;
- struct cfq_data *cfqd = cfqq->cfqd;
-
- if (unlikely(!blk_fs_request(crq->request)))
- return;
-
- /*
- * accounted bit is necessary since some drivers will call
- * elv_next_request() many times for the same request (eg ide)
- */
- if (cfq_crq_in_driver(crq))
- return;
-
- cfq_mark_crq_in_driver(crq);
- cfqd->rq_in_driver++;
-}
-
-static inline void
-cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
-{
- struct cfq_data *cfqd = cfqq->cfqd;
- unsigned long now;
-
- if (!cfq_crq_in_driver(crq))
- return;
-
- now = jiffies;
-
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
-
- if (!cfq_class_idle(cfqq))
- cfqd->last_end_request = now;
-
- if (!cfq_cfqq_dispatched(cfqq)) {
- if (cfq_cfqq_on_rr(cfqq)) {
- cfqq->service_last = now;
- cfq_resort_rr_list(cfqq, 0);
- }
- if (cfq_cfqq_expired(cfqq)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
- }
-
- if (cfq_crq_is_sync(crq))
- crq->io_context->last_end_request = now;
-}
-
-static struct request *cfq_next_request(request_queue_t *q)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
- struct request *rq;
-
- if (!list_empty(&q->queue_head)) {
- struct cfq_rq *crq;
-dispatch:
- rq = list_entry_rq(q->queue_head.next);
-
- crq = RQ_DATA(rq);
- if (crq) {
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_crq_in_driver(crq) &&
- !cfq_cfqq_idle_window(cfqq) &&
- !blk_barrier_rq(rq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return NULL;
-
- cfq_remove_merge_hints(q, crq);
- cfq_account_dispatch(crq);
- }
-
- return rq;
- }
-
- if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
- goto dispatch;
-
- return NULL;
-}
-
/*
* task holds one reference to the queue, dropped when task exits. each crq
* in-flight on this queue also holds a reference, dropped when crq is freed.
@@ -1416,7 +1246,7 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
}
static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
+cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
@@ -1511,7 +1341,7 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
static struct cfq_queue *
cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1572,7 +1402,7 @@ out:
* cfqq, so we don't need to worry about it disappearing
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
@@ -1769,18 +1599,23 @@ static void
cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq)
{
- const int sync = cfq_crq_is_sync(crq);
+ struct cfq_io_context *cic;
cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
- if (sync) {
- struct cfq_io_context *cic = crq->io_context;
+ /*
+ * we never wait for an async request and we don't allow preemption
+ * of an async request. so just return early
+ */
+ if (!cfq_crq_is_sync(crq))
+ return;
- cfq_update_io_thinktime(cfqd, cic);
- cfq_update_idle_window(cfqd, cfqq, cic);
+ cic = crq->io_context;
- cic->last_queue = jiffies;
- }
+ cfq_update_io_thinktime(cfqd, cic);
+ cfq_update_idle_window(cfqd, cfqq, cic);
+
+ cic->last_queue = jiffies;
if (cfqq == cfqd->active_queue) {
/*
@@ -1805,8 +1640,9 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
}
}
-static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
+static void cfq_insert_request(request_queue_t *q, struct request *rq)
{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_rq *crq = RQ_DATA(rq);
struct cfq_queue *cfqq = crq->cfq_queue;
@@ -1816,66 +1652,43 @@ static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
list_add_tail(&rq->queuelist, &cfqq->fifo);
- if (rq_mergeable(rq)) {
+ if (rq_mergeable(rq))
cfq_add_crq_hash(cfqd, crq);
- if (!cfqd->queue->last_merge)
- cfqd->queue->last_merge = rq;
- }
-
cfq_crq_enqueued(cfqd, cfqq, crq);
}
-static void
-cfq_insert_request(request_queue_t *q, struct request *rq, int where)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (cfq_dispatch_requests(q, INT_MAX, 1))
- ;
- list_add_tail(&rq->queuelist, &q->queue_head);
- /*
- * If we were idling with pending requests on
- * inactive cfqqs, force dispatching will
- * remove the idle timer and the queue won't
- * be kicked by __make_request() afterward.
- * Kick it here.
- */
- cfq_schedule_dispatch(cfqd);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, &q->queue_head);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- cfq_enqueue(cfqd, rq);
- break;
- default:
- printk("%s: bad insert point %d\n", __FUNCTION__,where);
- return;
- }
-}
-
static void cfq_completed_request(request_queue_t *q, struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
- struct cfq_queue *cfqq;
+ struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int sync = cfq_crq_is_sync(crq);
+ unsigned long now;
- if (unlikely(!blk_fs_request(rq)))
- return;
+ now = jiffies;
- cfqq = crq->cfq_queue;
+ WARN_ON(!cfqd->rq_in_driver);
+ WARN_ON(!cfqq->on_dispatch[sync]);
+ cfqd->rq_in_driver--;
+ cfqq->on_dispatch[sync]--;
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
+ if (!cfq_class_idle(cfqq))
+ cfqd->last_end_request = now;
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
+ if (!cfq_cfqq_dispatched(cfqq)) {
+ if (cfq_cfqq_on_rr(cfqq)) {
+ cfqq->service_last = now;
+ cfq_resort_rr_list(cfqq, 0);
+ }
+ if (cfq_cfqq_expired(cfqq)) {
+ __cfq_slice_expired(cfqd, cfqq, 0);
+ cfq_schedule_dispatch(cfqd);
+ }
}
- cfq_account_completion(cfqq, crq);
+ if (cfq_crq_is_sync(crq))
+ crq->io_context->last_end_request = now;
}
static struct request *
@@ -2064,7 +1877,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
*/
static int
cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
@@ -2107,9 +1920,6 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
INIT_HLIST_NODE(&crq->hash);
crq->cfq_queue = cfqq;
crq->io_context = cic;
- cfq_clear_crq_in_flight(crq);
- cfq_clear_crq_in_driver(crq);
- cfq_clear_crq_requeued(crq);
if (rw == READ || process_sync(tsk))
cfq_mark_crq_is_sync(crq);
@@ -2190,7 +2000,7 @@ static void cfq_idle_slice_timer(unsigned long data)
* only expire and reinvoke request handler, if there are
* other queues with pending requests
*/
- if (!cfq_pending_requests(cfqd)) {
+ if (!cfqd->busy_queues) {
cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
add_timer(&cfqd->idle_slice_timer);
goto out_cont;
@@ -2249,10 +2059,8 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
if (!atomic_dec_and_test(&cfqd->ref))
return;
- blk_put_queue(q);
-
cfq_shutdown_timer_wq(cfqd);
- q->elevator->elevator_data = NULL;
+ blk_put_queue(q);
mempool_destroy(cfqd->crq_pool);
kfree(cfqd->crq_hash);
@@ -2565,10 +2373,9 @@ static struct elevator_type iosched_cfq = {
.elevator_merge_fn = cfq_merge,
.elevator_merged_fn = cfq_merged_request,
.elevator_merge_req_fn = cfq_merged_requests,
- .elevator_next_req_fn = cfq_next_request,
+ .elevator_dispatch_fn = cfq_dispatch_requests,
.elevator_add_req_fn = cfq_insert_request,
- .elevator_remove_req_fn = cfq_remove_request,
- .elevator_requeue_req_fn = cfq_requeue_request,
+ .elevator_activate_req_fn = cfq_activate_request,
.elevator_deactivate_req_fn = cfq_deactivate_request,
.elevator_queue_empty_fn = cfq_queue_empty,
.elevator_completed_req_fn = cfq_completed_request,
@@ -2609,28 +2416,8 @@ static int __init cfq_init(void)
static void __exit cfq_exit(void)
{
- struct task_struct *g, *p;
- unsigned long flags;
-
- read_lock_irqsave(&tasklist_lock, flags);
-
- /*
- * iterate each process in the system, removing our io_context
- */
- do_each_thread(g, p) {
- struct io_context *ioc = p->io_context;
-
- if (ioc && ioc->cic) {
- ioc->cic->exit(ioc->cic);
- cfq_free_io_context(ioc->cic);
- ioc->cic = NULL;
- }
- } while_each_thread(g, p);
-
- read_unlock_irqrestore(&tasklist_lock, flags);
-
- cfq_slab_kill();
elv_unregister(&iosched_cfq);
+ cfq_slab_kill();
}
module_init(cfq_init);
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
index 5be6f998d8c5..3d4261c39f16 100644
--- a/drivers/block/cryptoloop.c
+++ b/drivers/block/cryptoloop.c
@@ -57,9 +57,11 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
mode = strsep(&cmsp, "-");
if (mode == NULL || strcmp(mode, "cbc") == 0)
- tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC);
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
else if (strcmp(mode, "ecb") == 0)
- tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB);
+ tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL)
return -EINVAL;
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index ff5201e02153..7929471d7df7 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -50,7 +50,6 @@ struct deadline_data {
* next in sort order. read, write or both are NULL
*/
struct deadline_rq *next_drq[2];
- struct list_head *dispatch; /* driver dispatch queue */
struct list_head *hash; /* request hash */
unsigned int batching; /* number of sequential requests made */
sector_t last_sector; /* head position */
@@ -113,15 +112,6 @@ static inline void deadline_del_drq_hash(struct deadline_rq *drq)
__deadline_del_drq_hash(drq);
}
-static void
-deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq)
-{
- deadline_del_drq_hash(drq);
-
- if (q->last_merge == drq->request)
- q->last_merge = NULL;
-}
-
static inline void
deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
@@ -239,10 +229,9 @@ deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
dd->next_drq[data_dir] = rb_entry_drq(rbnext);
}
- if (ON_RB(&drq->rb_node)) {
- rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
- RB_CLEAR(&drq->rb_node);
- }
+ BUG_ON(!ON_RB(&drq->rb_node));
+ rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
+ RB_CLEAR(&drq->rb_node);
}
static struct request *
@@ -286,7 +275,7 @@ deadline_find_first_drq(struct deadline_data *dd, int data_dir)
/*
* add drq to rbtree and fifo
*/
-static inline void
+static void
deadline_add_request(struct request_queue *q, struct request *rq)
{
struct deadline_data *dd = q->elevator->elevator_data;
@@ -301,12 +290,8 @@ deadline_add_request(struct request_queue *q, struct request *rq)
drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
- if (rq_mergeable(rq)) {
+ if (rq_mergeable(rq))
deadline_add_drq_hash(dd, drq);
-
- if (!q->last_merge)
- q->last_merge = rq;
- }
}
/*
@@ -315,14 +300,11 @@ deadline_add_request(struct request_queue *q, struct request *rq)
static void deadline_remove_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
+ struct deadline_data *dd = q->elevator->elevator_data;
- if (drq) {
- struct deadline_data *dd = q->elevator->elevator_data;
-
- list_del_init(&drq->fifo);
- deadline_remove_merge_hints(q, drq);
- deadline_del_drq_rb(dd, drq);
- }
+ list_del_init(&drq->fifo);
+ deadline_del_drq_rb(dd, drq);
+ deadline_del_drq_hash(drq);
}
static int
@@ -333,15 +315,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
int ret;
/*
- * try last_merge to avoid going to hash
- */
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE) {
- __rq = q->last_merge;
- goto out_insert;
- }
-
- /*
* see if the merge hash can satisfy a back merge
*/
__rq = deadline_find_drq_hash(dd, bio->bi_sector);
@@ -373,8 +346,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
- q->last_merge = __rq;
-out_insert:
if (ret)
deadline_hot_drq_hash(dd, RQ_DATA(__rq));
*req = __rq;
@@ -399,8 +370,6 @@ static void deadline_merged_request(request_queue_t *q, struct request *req)
deadline_del_drq_rb(dd, drq);
deadline_add_drq_rb(dd, drq);
}
-
- q->last_merge = req;
}
static void
@@ -452,7 +421,7 @@ deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
request_queue_t *q = drq->request->q;
deadline_remove_request(q, drq->request);
- list_add_tail(&drq->request->queuelist, dd->dispatch);
+ elv_dispatch_add_tail(q, drq->request);
}
/*
@@ -502,23 +471,21 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
* deadline_dispatch_requests selects the best request according to
* read/write expire, fifo_batch, etc
*/
-static int deadline_dispatch_requests(struct deadline_data *dd)
+static int deadline_dispatch_requests(request_queue_t *q, int force)
{
+ struct deadline_data *dd = q->elevator->elevator_data;
const int reads = !list_empty(&dd->fifo_list[READ]);
const int writes = !list_empty(&dd->fifo_list[WRITE]);
struct deadline_rq *drq;
- int data_dir, other_dir;
+ int data_dir;
/*
* batches are currently reads XOR writes
*/
- drq = NULL;
-
- if (dd->next_drq[READ])
- drq = dd->next_drq[READ];
-
if (dd->next_drq[WRITE])
drq = dd->next_drq[WRITE];
+ else
+ drq = dd->next_drq[READ];
if (drq) {
/* we have a "next request" */
@@ -544,7 +511,6 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
goto dispatch_writes;
data_dir = READ;
- other_dir = WRITE;
goto dispatch_find_request;
}
@@ -560,7 +526,6 @@ dispatch_writes:
dd->starved = 0;
data_dir = WRITE;
- other_dir = READ;
goto dispatch_find_request;
}
@@ -602,65 +567,12 @@ dispatch_request:
return 1;
}
-static struct request *deadline_next_request(request_queue_t *q)
-{
- struct deadline_data *dd = q->elevator->elevator_data;
- struct request *rq;
-
- /*
- * if there are still requests on the dispatch queue, grab the first one
- */
- if (!list_empty(dd->dispatch)) {
-dispatch:
- rq = list_entry_rq(dd->dispatch->next);
- return rq;
- }
-
- if (deadline_dispatch_requests(dd))
- goto dispatch;
-
- return NULL;
-}
-
-static void
-deadline_insert_request(request_queue_t *q, struct request *rq, int where)
-{
- struct deadline_data *dd = q->elevator->elevator_data;
-
- /* barriers must flush the reorder queue */
- if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
- && where == ELEVATOR_INSERT_SORT))
- where = ELEVATOR_INSERT_BACK;
-
- switch (where) {
- case ELEVATOR_INSERT_BACK:
- while (deadline_dispatch_requests(dd))
- ;
- list_add_tail(&rq->queuelist, dd->dispatch);
- break;
- case ELEVATOR_INSERT_FRONT:
- list_add(&rq->queuelist, dd->dispatch);
- break;
- case ELEVATOR_INSERT_SORT:
- BUG_ON(!blk_fs_request(rq));
- deadline_add_request(q, rq);
- break;
- default:
- printk("%s: bad insert point %d\n", __FUNCTION__,where);
- return;
- }
-}
-
static int deadline_queue_empty(request_queue_t *q)
{
struct deadline_data *dd = q->elevator->elevator_data;
- if (!list_empty(&dd->fifo_list[WRITE])
- || !list_empty(&dd->fifo_list[READ])
- || !list_empty(dd->dispatch))
- return 0;
-
- return 1;
+ return list_empty(&dd->fifo_list[WRITE])
+ && list_empty(&dd->fifo_list[READ]);
}
static struct request *
@@ -738,7 +650,6 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
dd->sort_list[READ] = RB_ROOT;
dd->sort_list[WRITE] = RB_ROOT;
- dd->dispatch = &q->queue_head;
dd->fifo_expire[READ] = read_expire;
dd->fifo_expire[WRITE] = write_expire;
dd->writes_starved = writes_starved;
@@ -753,15 +664,13 @@ static void deadline_put_request(request_queue_t *q, struct request *rq)
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(rq);
- if (drq) {
- mempool_free(drq, dd->drq_pool);
- rq->elevator_private = NULL;
- }
+ mempool_free(drq, dd->drq_pool);
+ rq->elevator_private = NULL;
}
static int
deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq;
@@ -922,9 +831,8 @@ static struct elevator_type iosched_deadline = {
.elevator_merge_fn = deadline_merge,
.elevator_merged_fn = deadline_merged_request,
.elevator_merge_req_fn = deadline_merged_requests,
- .elevator_next_req_fn = deadline_next_request,
- .elevator_add_req_fn = deadline_insert_request,
- .elevator_remove_req_fn = deadline_remove_request,
+ .elevator_dispatch_fn = deadline_dispatch_requests,
+ .elevator_add_req_fn = deadline_add_request,
.elevator_queue_empty_fn = deadline_queue_empty,
.elevator_former_req_fn = deadline_former_request,
.elevator_latter_req_fn = deadline_latter_request,
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 98f0126a2deb..d4a49a3df829 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/compiler.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -83,21 +84,11 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_try_merge);
-inline int elv_try_last_merge(request_queue_t *q, struct bio *bio)
-{
- if (q->last_merge)
- return elv_try_merge(q->last_merge, bio);
-
- return ELEVATOR_NO_MERGE;
-}
-EXPORT_SYMBOL(elv_try_last_merge);
-
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e = NULL;
struct list_head *entry;
- spin_lock_irq(&elv_list_lock);
list_for_each(entry, &elv_list) {
struct elevator_type *__e;
@@ -108,7 +99,6 @@ static struct elevator_type *elevator_find(const char *name)
break;
}
}
- spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -120,12 +110,15 @@ static void elevator_put(struct elevator_type *e)
static struct elevator_type *elevator_get(const char *name)
{
- struct elevator_type *e = elevator_find(name);
+ struct elevator_type *e;
- if (!e)
- return NULL;
- if (!try_module_get(e->elevator_owner))
- return NULL;
+ spin_lock_irq(&elv_list_lock);
+
+ e = elevator_find(name);
+ if (e && !try_module_get(e->elevator_owner))
+ e = NULL;
+
+ spin_unlock_irq(&elv_list_lock);
return e;
}
@@ -139,8 +132,6 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e,
eq->ops = &e->ops;
eq->elevator_type = e;
- INIT_LIST_HEAD(&q->queue_head);
- q->last_merge = NULL;
q->elevator = eq;
if (eq->ops->elevator_init_fn)
@@ -153,23 +144,20 @@ static char chosen_elevator[16];
static void elevator_setup_default(void)
{
+ struct elevator_type *e;
+
/*
- * check if default is set and exists
+ * If default has not been set, use the compiled-in selection.
*/
- if (chosen_elevator[0] && elevator_find(chosen_elevator))
- return;
-
-#if defined(CONFIG_IOSCHED_AS)
- strcpy(chosen_elevator, "anticipatory");
-#elif defined(CONFIG_IOSCHED_DEADLINE)
- strcpy(chosen_elevator, "deadline");
-#elif defined(CONFIG_IOSCHED_CFQ)
- strcpy(chosen_elevator, "cfq");
-#elif defined(CONFIG_IOSCHED_NOOP)
- strcpy(chosen_elevator, "noop");
-#else
-#error "You must build at least 1 IO scheduler into the kernel"
-#endif
+ if (!chosen_elevator[0])
+ strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
+
+ /*
+ * If the given scheduler is not available, fall back to no-op.
+ */
+ if (!(e = elevator_find(chosen_elevator)))
+ strcpy(chosen_elevator, "noop");
+ elevator_put(e);
}
static int __init elevator_setup(char *str)
@@ -186,6 +174,11 @@ int elevator_init(request_queue_t *q, char *name)
struct elevator_queue *eq;
int ret = 0;
+ INIT_LIST_HEAD(&q->queue_head);
+ q->last_merge = NULL;
+ q->end_sector = 0;
+ q->boundary_rq = NULL;
+
elevator_setup_default();
if (!name)
@@ -220,9 +213,52 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
+/*
+ * Insert rq into dispatch queue of q. Queue lock must be held on
+ * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be
+ * appended to the dispatch queue. To be used by specific elevators.
+ */
+void elv_dispatch_sort(request_queue_t *q, struct request *rq)
+{
+ sector_t boundary;
+ struct list_head *entry;
+
+ if (q->last_merge == rq)
+ q->last_merge = NULL;
+
+ boundary = q->end_sector;
+
+ list_for_each_prev(entry, &q->queue_head) {
+ struct request *pos = list_entry_rq(entry);
+
+ if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
+ break;
+ if (rq->sector >= boundary) {
+ if (pos->sector < boundary)
+ continue;
+ } else {
+ if (pos->sector >= boundary)
+ break;
+ }
+ if (rq->sector >= pos->sector)
+ break;
+ }
+
+ list_add(&rq->queuelist, entry);
+}
+
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
+ int ret;
+
+ if (q->last_merge) {
+ ret = elv_try_merge(q->last_merge, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ *req = q->last_merge;
+ return ret;
+ }
+ }
if (e->ops->elevator_merge_fn)
return e->ops->elevator_merge_fn(q, req, bio);
@@ -236,6 +272,8 @@ void elv_merged_request(request_queue_t *q, struct request *rq)
if (e->ops->elevator_merged_fn)
e->ops->elevator_merged_fn(q, rq);
+
+ q->last_merge = rq;
}
void elv_merge_requests(request_queue_t *q, struct request *rq,
@@ -243,20 +281,13 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
{
elevator_t *e = q->elevator;
- if (q->last_merge == next)
- q->last_merge = NULL;
-
if (e->ops->elevator_merge_req_fn)
e->ops->elevator_merge_req_fn(q, rq, next);
+
+ q->last_merge = rq;
}
-/*
- * For careful internal use by the block layer. Essentially the same as
- * a requeue in that it tells the io scheduler that this request is not
- * active in the driver or hardware anymore, but we don't want the request
- * added back to the scheduler. Function is not exported.
- */
-void elv_deactivate_request(request_queue_t *q, struct request *rq)
+void elv_requeue_request(request_queue_t *q, struct request *rq)
{
elevator_t *e = q->elevator;
@@ -264,19 +295,14 @@ void elv_deactivate_request(request_queue_t *q, struct request *rq)
* it already went through dequeue, we need to decrement the
* in_flight count again
*/
- if (blk_account_rq(rq))
+ if (blk_account_rq(rq)) {
q->in_flight--;
+ if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+ }
rq->flags &= ~REQ_STARTED;
- if (e->ops->elevator_deactivate_req_fn)
- e->ops->elevator_deactivate_req_fn(q, rq);
-}
-
-void elv_requeue_request(request_queue_t *q, struct request *rq)
-{
- elv_deactivate_request(q, rq);
-
/*
* if this is the flush, requeue the original instead and drop the flush
*/
@@ -285,31 +311,27 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
rq = rq->end_io_data;
}
- /*
- * the request is prepped and may have some resources allocated.
- * allowing unprepped requests to pass this one may cause resource
- * deadlock. turn on softbarrier.
- */
- rq->flags |= REQ_SOFTBARRIER;
-
- /*
- * if iosched has an explicit requeue hook, then use that. otherwise
- * just put the request at the front of the queue
- */
- if (q->elevator->ops->elevator_requeue_req_fn)
- q->elevator->ops->elevator_requeue_req_fn(q, rq);
- else
- __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
}
void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
- /*
- * barriers implicitly indicate back insertion
- */
- if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) &&
- where == ELEVATOR_INSERT_SORT)
+ if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
+ /*
+ * barriers implicitly indicate back insertion
+ */
+ if (where == ELEVATOR_INSERT_SORT)
+ where = ELEVATOR_INSERT_BACK;
+
+ /*
+ * this request is scheduling boundary, update end_sector
+ */
+ if (blk_fs_request(rq)) {
+ q->end_sector = rq_end_sector(rq);
+ q->boundary_rq = rq;
+ }
+ } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
where = ELEVATOR_INSERT_BACK;
if (plug)
@@ -317,23 +339,59 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
rq->q = q;
- if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
- q->elevator->ops->elevator_add_req_fn(q, rq, where);
+ switch (where) {
+ case ELEVATOR_INSERT_FRONT:
+ rq->flags |= REQ_SOFTBARRIER;
- if (blk_queue_plugged(q)) {
- int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- - q->in_flight;
+ list_add(&rq->queuelist, &q->queue_head);
+ break;
- if (nrq >= q->unplug_thresh)
- __generic_unplug_device(q);
- }
- } else
+ case ELEVATOR_INSERT_BACK:
+ rq->flags |= REQ_SOFTBARRIER;
+
+ while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+ ;
+ list_add_tail(&rq->queuelist, &q->queue_head);
+ /*
+ * We kick the queue here for the following reasons.
+ * - The elevator might have returned NULL previously
+ * to delay requests and returned them now. As the
+ * queue wasn't empty before this request, ll_rw_blk
+ * won't run the queue on return, resulting in hang.
+ * - Usually, back inserted requests won't be merged
+ * with anything. There's no point in delaying queue
+ * processing.
+ */
+ blk_remove_plug(q);
+ q->request_fn(q);
+ break;
+
+ case ELEVATOR_INSERT_SORT:
+ BUG_ON(!blk_fs_request(rq));
+ rq->flags |= REQ_SORTED;
+ if (q->last_merge == NULL && rq_mergeable(rq))
+ q->last_merge = rq;
/*
- * if drain is set, store the request "locally". when the drain
- * is finished, the requests will be handed ordered to the io
- * scheduler
+ * Some ioscheds (cfq) run q->request_fn directly, so
+ * rq cannot be accessed after calling
+ * elevator_add_req_fn.
*/
- list_add_tail(&rq->queuelist, &q->drain_list);
+ q->elevator->ops->elevator_add_req_fn(q, rq);
+ break;
+
+ default:
+ printk(KERN_ERR "%s: bad insertion point %d\n",
+ __FUNCTION__, where);
+ BUG();
+ }
+
+ if (blk_queue_plugged(q)) {
+ int nrq = q->rq.count[READ] + q->rq.count[WRITE]
+ - q->in_flight;
+
+ if (nrq >= q->unplug_thresh)
+ __generic_unplug_device(q);
+ }
}
void elv_add_request(request_queue_t *q, struct request *rq, int where,
@@ -348,13 +406,19 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
static inline struct request *__elv_next_request(request_queue_t *q)
{
- struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+ struct request *rq;
+
+ if (unlikely(list_empty(&q->queue_head) &&
+ !q->elevator->ops->elevator_dispatch_fn(q, 0)))
+ return NULL;
+
+ rq = list_entry_rq(q->queue_head.next);
/*
* if this is a barrier write and the device has to issue a
* flush sequence to support it, check how far we are
*/
- if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+ if (blk_fs_request(rq) && blk_barrier_rq(rq)) {
BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
if (q->ordered == QUEUE_ORDERED_FLUSH &&
@@ -371,15 +435,30 @@ struct request *elv_next_request(request_queue_t *q)
int ret;
while ((rq = __elv_next_request(q)) != NULL) {
- /*
- * just mark as started even if we don't start it, a request
- * that has been delayed should not be passed by new incoming
- * requests
- */
- rq->flags |= REQ_STARTED;
+ if (!(rq->flags & REQ_STARTED)) {
+ elevator_t *e = q->elevator;
- if (rq == q->last_merge)
- q->last_merge = NULL;
+ /*
+ * This is the first time the device driver
+ * sees this request (possibly after
+ * requeueing). Notify IO scheduler.
+ */
+ if (blk_sorted_rq(rq) &&
+ e->ops->elevator_activate_req_fn)
+ e->ops->elevator_activate_req_fn(q, rq);
+
+ /*
+ * just mark as started even if we don't start
+ * it, a request that has been delayed should
+ * not be passed by new incoming requests
+ */
+ rq->flags |= REQ_STARTED;
+ }
+
+ if (!q->boundary_rq || q->boundary_rq == rq) {
+ q->end_sector = rq_end_sector(rq);
+ q->boundary_rq = NULL;
+ }
if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
break;
@@ -391,9 +470,9 @@ struct request *elv_next_request(request_queue_t *q)
/*
* the request may have been (partially) prepped.
* we need to keep this request in the front to
- * avoid resource deadlock. turn on softbarrier.
+ * avoid resource deadlock. REQ_STARTED will
+ * prevent other fs requests from passing this one.
*/
- rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
@@ -416,42 +495,32 @@ struct request *elv_next_request(request_queue_t *q)
return rq;
}
-void elv_remove_request(request_queue_t *q, struct request *rq)
+void elv_dequeue_request(request_queue_t *q, struct request *rq)
{
- elevator_t *e = q->elevator;
+ BUG_ON(list_empty(&rq->queuelist));
+
+ list_del_init(&rq->queuelist);
/*
* the time frame between a request being removed from the lists
* and to it is freed is accounted as io that is in progress at
- * the driver side. note that we only account requests that the
- * driver has seen (REQ_STARTED set), to avoid false accounting
- * for request-request merges
+ * the driver side.
*/
if (blk_account_rq(rq))
q->in_flight++;
-
- /*
- * the main clearing point for q->last_merge is on retrieval of
- * request by driver (it calls elv_next_request()), but it _can_
- * also happen here if a request is added to the queue but later
- * deleted without ever being given to driver (merged with another
- * request).
- */
- if (rq == q->last_merge)
- q->last_merge = NULL;
-
- if (e->ops->elevator_remove_req_fn)
- e->ops->elevator_remove_req_fn(q, rq);
}
int elv_queue_empty(request_queue_t *q)
{
elevator_t *e = q->elevator;
+ if (!list_empty(&q->queue_head))
+ return 0;
+
if (e->ops->elevator_queue_empty_fn)
return e->ops->elevator_queue_empty_fn(q);
- return list_empty(&q->queue_head);
+ return 1;
}
struct request *elv_latter_request(request_queue_t *q, struct request *rq)
@@ -487,7 +556,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
}
int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
elevator_t *e = q->elevator;
@@ -523,11 +592,11 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
/*
* request is released from the driver, io must be done
*/
- if (blk_account_rq(rq))
+ if (blk_account_rq(rq)) {
q->in_flight--;
-
- if (e->ops->elevator_completed_req_fn)
- e->ops->elevator_completed_req_fn(q, rq);
+ if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
+ e->ops->elevator_completed_req_fn(q, rq);
+ }
}
int elv_register_queue(struct request_queue *q)
@@ -555,10 +624,9 @@ void elv_unregister_queue(struct request_queue *q)
int elv_register(struct elevator_type *e)
{
+ spin_lock_irq(&elv_list_lock);
if (elevator_find(e->elevator_name))
BUG();
-
- spin_lock_irq(&elv_list_lock);
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
@@ -572,6 +640,27 @@ EXPORT_SYMBOL_GPL(elv_register);
void elv_unregister(struct elevator_type *e)
{
+ struct task_struct *g, *p;
+
+ /*
+ * Iterate every thread in the process to remove the io contexts.
+ */
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ struct io_context *ioc = p->io_context;
+ if (ioc && ioc->cic) {
+ ioc->cic->exit(ioc->cic);
+ ioc->cic->dtor(ioc->cic);
+ ioc->cic = NULL;
+ }
+ if (ioc && ioc->aic) {
+ ioc->aic->exit(ioc->aic);
+ ioc->aic->dtor(ioc->aic);
+ ioc->aic = NULL;
+ }
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+
spin_lock_irq(&elv_list_lock);
list_del_init(&e->list);
spin_unlock_irq(&elv_list_lock);
@@ -582,25 +671,36 @@ EXPORT_SYMBOL_GPL(elv_unregister);
* switch to new_e io scheduler. be careful not to introduce deadlocks -
* we don't free the old io scheduler, before we have allocated what we
* need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason. we also do an intermediate
- * switch to noop to ensure safety with stack-allocated requests, since they
- * don't originate from the block layer allocator. noop is safe here, because
- * it never needs to touch the elevator itself for completion events. DRAIN
- * flags will make sure we don't touch it for additions either.
+ * one, if the new one fails init for some reason.
*/
static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
{
- elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
- struct elevator_type *noop_elevator = NULL;
- elevator_t *old_elevator;
+ elevator_t *old_elevator, *e;
+ /*
+ * Allocate new elevator
+ */
+ e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
if (!e)
goto error;
/*
- * first step, drain requests from the block freelist
+ * Turn on BYPASS and drain all requests w/ elevator private data
*/
- blk_wait_queue_drained(q, 0);
+ spin_lock_irq(q->queue_lock);
+
+ set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+
+ while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+ ;
+
+ while (q->rq.elvpriv) {
+ spin_unlock_irq(q->queue_lock);
+ msleep(10);
+ spin_lock_irq(q->queue_lock);
+ }
+
+ spin_unlock_irq(q->queue_lock);
/*
* unregister old elevator data
@@ -609,18 +709,6 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
old_elevator = q->elevator;
/*
- * next step, switch to noop since it uses no private rq structures
- * and doesn't allocate any memory for anything. then wait for any
- * non-fs requests in-flight
- */
- noop_elevator = elevator_get("noop");
- spin_lock_irq(q->queue_lock);
- elevator_attach(q, noop_elevator, e);
- spin_unlock_irq(q->queue_lock);
-
- blk_wait_queue_drained(q, 1);
-
- /*
* attach and start new elevator
*/
if (elevator_attach(q, new_e, e))
@@ -630,11 +718,10 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
goto fail_register;
/*
- * finally exit old elevator and start queue again
+ * finally exit old elevator and turn off BYPASS.
*/
elevator_exit(old_elevator);
- blk_finish_queue_drain(q);
- elevator_put(noop_elevator);
+ clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
return;
fail_register:
@@ -643,13 +730,13 @@ fail_register:
* one again (along with re-adding the sysfs dir)
*/
elevator_exit(e);
+ e = NULL;
fail:
q->elevator = old_elevator;
elv_register_queue(q);
- blk_finish_queue_drain(q);
+ clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+ kfree(e);
error:
- if (noop_elevator)
- elevator_put(noop_elevator);
elevator_put(new_e);
printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
}
@@ -671,8 +758,10 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
return -EINVAL;
}
- if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name))
+ if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
+ elevator_put(e);
return count;
+ }
elevator_switch(q, e);
return count;
@@ -701,11 +790,12 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
+EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
-EXPORT_SYMBOL(elv_remove_request);
+EXPORT_SYMBOL(elv_dequeue_request);
EXPORT_SYMBOL(elv_queue_empty);
EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f0c1084b840f..5eadbb9d4d71 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -177,7 +177,7 @@ static int print_unex = 1;
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/buffer_head.h> /* for invalidate_buffers() */
/*
@@ -493,6 +493,8 @@ static struct floppy_struct user_params[N_DRIVE];
static sector_t floppy_sizes[256];
+static char floppy_device_name[] = "floppy";
+
/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
@@ -626,7 +628,7 @@ static inline void debugt(const char *message) { }
#endif /* DEBUGT */
typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
static const char *timeout_message;
@@ -1010,7 +1012,7 @@ static void schedule_bh(void (*handler) (void))
schedule_work(&floppy_work);
}
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
static void cancel_activity(void)
{
@@ -4191,18 +4193,24 @@ static int __init floppy_setup(char *str)
static int have_no_fdc = -ENODEV;
+static ssize_t floppy_cmos_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *p;
+ int drive;
+
+ p = container_of(dev, struct platform_device,dev);
+ drive = p->id;
+ return sprintf(buf, "%X\n", UDP->cmos);
+}
+DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
static void floppy_device_release(struct device *dev)
{
complete(&device_release);
}
-static struct platform_device floppy_device = {
- .name = "floppy",
- .id = 0,
- .dev = {
- .release = floppy_device_release,
- }
-};
+static struct platform_device floppy_device[N_DRIVE];
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{
@@ -4370,20 +4378,26 @@ static int __init floppy_init(void)
goto out_flush_work;
}
- err = platform_device_register(&floppy_device);
- if (err)
- goto out_flush_work;
-
for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive)))
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
+
+ floppy_device[drive].name = floppy_device_name;
+ floppy_device[drive].id = drive;
+ floppy_device[drive].dev.release = floppy_device_release;
+
+ err = platform_device_register(&floppy_device[drive]);
+ if (err)
+ goto out_flush_work;
+
+ device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
/* to be cleaned up... */
disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
- disks[drive]->driverfs_dev = &floppy_device.dev;
+ disks[drive]->driverfs_dev = &floppy_device[drive].dev;
add_disk(disks[drive]);
}
@@ -4603,10 +4617,11 @@ void cleanup_module(void)
fdc_state[FDC(drive)].version != FDC_NONE) {
del_gendisk(disks[drive]);
unregister_devfs_entries(drive);
+ device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+ platform_device_unregister(&floppy_device[drive]);
}
put_disk(disks[drive]);
}
- platform_device_unregister(&floppy_device);
devfs_remove("floppy");
del_timer_sync(&fd_timeout);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 47fd3659a061..54aec4a1ae13 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -45,7 +45,7 @@ int get_blkdev_list(char *p, int used)
struct blk_major_name *n;
int i, len;
- len = sprintf(p, "\nBlock devices:\n");
+ len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n");
down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
@@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
return ret;
}
+static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char *page, size_t count)
+{
+ struct gendisk *disk = to_disk(kobj);
+ struct disk_attribute *disk_attr =
+ container_of(attr,struct disk_attribute,attr);
+ ssize_t ret = 0;
+
+ if (disk_attr->store)
+ ret = disk_attr->store(disk, page, count);
+ return ret;
+}
+
static struct sysfs_ops disk_sysfs_ops = {
.show = &disk_attr_show,
+ .store = &disk_attr_store,
};
+static ssize_t disk_uevent_store(struct gendisk * disk,
+ const char *buf, size_t count)
+{
+ kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ return count;
+}
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
{
dev_t base = MKDEV(disk->major, disk->first_minor);
@@ -371,17 +391,20 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
"%8u %8u %8llu %8u "
"%8u %8u %8u"
"\n",
- disk_stat_read(disk, reads), disk_stat_read(disk, read_merges),
- (unsigned long long)disk_stat_read(disk, read_sectors),
- jiffies_to_msecs(disk_stat_read(disk, read_ticks)),
- disk_stat_read(disk, writes),
- disk_stat_read(disk, write_merges),
- (unsigned long long)disk_stat_read(disk, write_sectors),
- jiffies_to_msecs(disk_stat_read(disk, write_ticks)),
+ disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]),
+ (unsigned long long)disk_stat_read(disk, sectors[0]),
+ jiffies_to_msecs(disk_stat_read(disk, ticks[0])),
+ disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]),
+ (unsigned long long)disk_stat_read(disk, sectors[1]),
+ jiffies_to_msecs(disk_stat_read(disk, ticks[1])),
disk->in_flight,
jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
}
+static struct disk_attribute disk_attr_uevent = {
+ .attr = {.name = "uevent", .mode = S_IWUSR },
+ .store = disk_uevent_store
+};
static struct disk_attribute disk_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
.show = disk_dev_read
@@ -404,6 +427,7 @@ static struct disk_attribute disk_attr_stat = {
};
static struct attribute * default_attrs[] = {
+ &disk_attr_uevent.attr,
&disk_attr_dev.attr,
&disk_attr_range.attr,
&disk_attr_removable.attr,
@@ -558,12 +582,12 @@ static int diskstats_show(struct seq_file *s, void *v)
preempt_enable();
seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
gp->major, n + gp->first_minor, disk_name(gp, n, buf),
- disk_stat_read(gp, reads), disk_stat_read(gp, read_merges),
- (unsigned long long)disk_stat_read(gp, read_sectors),
- jiffies_to_msecs(disk_stat_read(gp, read_ticks)),
- disk_stat_read(gp, writes), disk_stat_read(gp, write_merges),
- (unsigned long long)disk_stat_read(gp, write_sectors),
- jiffies_to_msecs(disk_stat_read(gp, write_ticks)),
+ disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
+ (unsigned long long)disk_stat_read(gp, sectors[0]),
+ jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
+ disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]),
+ (unsigned long long)disk_stat_read(gp, sectors[1]),
+ jiffies_to_msecs(disk_stat_read(gp, ticks[1])),
gp->in_flight,
jiffies_to_msecs(disk_stat_read(gp, io_ticks)),
jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
@@ -576,8 +600,8 @@ static int diskstats_show(struct seq_file *s, void *v)
seq_printf(s, "%4d %4d %s %u %u %u %u\n",
gp->major, n + gp->first_minor + 1,
disk_name(gp, n + 1, buf),
- hd->reads, hd->read_sectors,
- hd->writes, hd->write_sectors);
+ hd->ios[0], hd->sectors[0],
+ hd->ios[1], hd->sectors[1]);
}
return 0;
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 692a5fced76e..2747741677fb 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -235,8 +235,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
* set defaults
*/
q->nr_requests = BLKDEV_MAX_RQ;
- q->max_phys_segments = MAX_PHYS_SEGMENTS;
- q->max_hw_segments = MAX_HW_SEGMENTS;
+ blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+ blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
q->make_request_fn = mfn;
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
@@ -263,8 +263,6 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_activity_fn(q, NULL, NULL);
-
- INIT_LIST_HEAD(&q->drain_list);
}
EXPORT_SYMBOL(blk_queue_make_request);
@@ -284,6 +282,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
rq->special = NULL;
rq->data_len = 0;
rq->data = NULL;
+ rq->nr_phys_segments = 0;
rq->sense = NULL;
rq->end_io = NULL;
rq->end_io_data = NULL;
@@ -352,6 +351,8 @@ static void blk_pre_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
+ elv_completed_request(q, flush_rq);
+
rq->flags |= REQ_BAR_PREFLUSH;
if (!flush_rq->errors)
@@ -368,6 +369,8 @@ static void blk_post_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
+ elv_completed_request(q, flush_rq);
+
rq->flags |= REQ_BAR_POSTFLUSH;
q->end_flush_fn(q, flush_rq);
@@ -407,8 +410,6 @@ struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
if (!list_empty(&rq->queuelist))
blkdev_dequeue_request(rq);
- elv_deactivate_request(q, rq);
-
flush_rq->end_io_data = rq;
flush_rq->end_io = blk_pre_flush_end_io;
@@ -719,7 +720,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
{
struct blk_queue_tag *bqt = q->queue_tags;
- if (unlikely(bqt == NULL || tag >= bqt->max_depth))
+ if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
return NULL;
return bqt->tag_index[tag];
@@ -798,6 +799,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
memset(tag_index, 0, depth * sizeof(struct request *));
memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
+ tags->real_max_depth = depth;
tags->max_depth = depth;
tags->tag_index = tag_index;
tags->tag_map = tag_map;
@@ -872,11 +874,22 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
return -ENXIO;
/*
+ * if we already have large enough real_max_depth. just
+ * adjust max_depth. *NOTE* as requests with tag value
+ * between new_depth and real_max_depth can be in-flight, tag
+ * map can not be shrunk blindly here.
+ */
+ if (new_depth <= bqt->real_max_depth) {
+ bqt->max_depth = new_depth;
+ return 0;
+ }
+
+ /*
* save the old state info, so we can copy it back
*/
tag_index = bqt->tag_index;
tag_map = bqt->tag_map;
- max_depth = bqt->max_depth;
+ max_depth = bqt->real_max_depth;
if (init_tag_map(q, bqt, new_depth))
return -ENOMEM;
@@ -913,7 +926,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
BUG_ON(tag == -1);
- if (unlikely(tag >= bqt->max_depth))
+ if (unlikely(tag >= bqt->real_max_depth))
/*
* This can happen after tag depth has been reduced.
* FIXME: how about a warning or info message here?
@@ -1027,6 +1040,7 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
static char *rq_flags[] = {
"REQ_RW",
"REQ_FAILFAST",
+ "REQ_SORTED",
"REQ_SOFTBARRIER",
"REQ_HARDBARRIER",
"REQ_CMD",
@@ -1034,6 +1048,7 @@ static char *rq_flags[] = {
"REQ_STARTED",
"REQ_DONTPREP",
"REQ_QUEUED",
+ "REQ_ELVPRIV",
"REQ_PC",
"REQ_BLOCK_PC",
"REQ_SENSE",
@@ -1624,9 +1639,9 @@ static int blk_init_free_list(request_queue_t *q)
rl->count[READ] = rl->count[WRITE] = 0;
rl->starved[READ] = rl->starved[WRITE] = 0;
+ rl->elvpriv = 0;
init_waitqueue_head(&rl->wait[READ]);
init_waitqueue_head(&rl->wait[WRITE]);
- init_waitqueue_head(&rl->drain);
rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
mempool_free_slab, request_cachep, q->node);
@@ -1639,13 +1654,13 @@ static int blk_init_free_list(request_queue_t *q)
static int __make_request(request_queue_t *, struct bio *);
-request_queue_t *blk_alloc_queue(int gfp_mask)
+request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
{
return blk_alloc_queue_node(gfp_mask, -1);
}
EXPORT_SYMBOL(blk_alloc_queue);
-request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
{
request_queue_t *q;
@@ -1769,12 +1784,14 @@ EXPORT_SYMBOL(blk_get_queue);
static inline void blk_free_request(request_queue_t *q, struct request *rq)
{
- elv_put_request(q, rq);
+ if (rq->flags & REQ_ELVPRIV)
+ elv_put_request(q, rq);
mempool_free(rq, q->rq.rq_pool);
}
static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
+ int priv, gfp_t gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
@@ -1787,11 +1804,15 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
*/
rq->flags = rw;
- if (!elv_set_request(q, rq, bio, gfp_mask))
- return rq;
+ if (priv) {
+ if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
+ mempool_free(rq, q->rq.rq_pool);
+ return NULL;
+ }
+ rq->flags |= REQ_ELVPRIV;
+ }
- mempool_free(rq, q->rq.rq_pool);
- return NULL;
+ return rq;
}
/*
@@ -1847,22 +1868,18 @@ static void __freed_request(request_queue_t *q, int rw)
* A request has just been released. Account for it, update the full and
* congestion status, wake up any waiters. Called under q->queue_lock.
*/
-static void freed_request(request_queue_t *q, int rw)
+static void freed_request(request_queue_t *q, int rw, int priv)
{
struct request_list *rl = &q->rq;
rl->count[rw]--;
+ if (priv)
+ rl->elvpriv--;
__freed_request(q, rw);
if (unlikely(rl->starved[rw ^ 1]))
__freed_request(q, rw ^ 1);
-
- if (!rl->count[READ] && !rl->count[WRITE]) {
- smp_mb();
- if (unlikely(waitqueue_active(&rl->drain)))
- wake_up(&rl->drain);
- }
}
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
@@ -1872,14 +1889,12 @@ static void freed_request(request_queue_t *q, int rw)
* Returns !NULL on success, with queue_lock *not held*.
*/
static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
struct io_context *ioc = current_io_context(GFP_ATOMIC);
-
- if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
- goto out;
+ int priv;
if (rl->count[rw]+1 >= q->nr_requests) {
/*
@@ -1924,9 +1939,14 @@ get_rq:
rl->starved[rw] = 0;
if (rl->count[rw] >= queue_congestion_on_threshold(q))
set_queue_congested(q, rw);
+
+ priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+ if (priv)
+ rl->elvpriv++;
+
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, bio, gfp_mask);
+ rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
if (!rq) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -1936,7 +1956,7 @@ get_rq:
* wait queue, but this is pretty rare.
*/
spin_lock_irq(q->queue_lock);
- freed_request(q, rw);
+ freed_request(q, rw, priv);
/*
* in the very unlikely event that allocation failed and no
@@ -2006,7 +2026,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
return rq;
}
-struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
+struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
{
struct request *rq;
@@ -2103,7 +2123,7 @@ EXPORT_SYMBOL(blk_insert_request);
/**
* blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
* @q: request queue where request should be inserted
- * @rw: READ or WRITE data
+ * @rq: request structure to fill
* @ubuf: the user buffer
* @len: length of user data
*
@@ -2120,21 +2140,19 @@ EXPORT_SYMBOL(blk_insert_request);
* original bio must be passed back in to blk_rq_unmap_user() for proper
* unmapping.
*/
-struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
- unsigned int len)
+int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+ unsigned int len)
{
unsigned long uaddr;
- struct request *rq;
struct bio *bio;
+ int reading;
if (len > (q->max_sectors << 9))
- return ERR_PTR(-EINVAL);
- if ((!len && ubuf) || (len && !ubuf))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
+ if (!len || !ubuf)
+ return -EINVAL;
- rq = blk_get_request(q, rw, __GFP_WAIT);
- if (!rq)
- return ERR_PTR(-ENOMEM);
+ reading = rq_data_dir(rq) == READ;
/*
* if alignment requirement is satisfied, map in user pages for
@@ -2142,9 +2160,9 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
*/
uaddr = (unsigned long) ubuf;
if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
- bio = bio_map_user(q, NULL, uaddr, len, rw == READ);
+ bio = bio_map_user(q, NULL, uaddr, len, reading);
else
- bio = bio_copy_user(q, uaddr, len, rw == READ);
+ bio = bio_copy_user(q, uaddr, len, reading);
if (!IS_ERR(bio)) {
rq->bio = rq->biotail = bio;
@@ -2152,28 +2170,70 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
rq->buffer = rq->data = NULL;
rq->data_len = len;
- return rq;
+ return 0;
}
/*
* bio is the err-ptr
*/
- blk_put_request(rq);
- return (struct request *) bio;
+ return PTR_ERR(bio);
}
EXPORT_SYMBOL(blk_rq_map_user);
/**
+ * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage
+ * @q: request queue where request should be inserted
+ * @rq: request to map data to
+ * @iov: pointer to the iovec
+ * @iov_count: number of elements in the iovec
+ *
+ * Description:
+ * Data will be mapped directly for zero copy io, if possible. Otherwise
+ * a kernel bounce buffer is used.
+ *
+ * A matching blk_rq_unmap_user() must be issued at the end of io, while
+ * still in process context.
+ *
+ * Note: The mapped bio may need to be bounced through blk_queue_bounce()
+ * before being submitted to the device, as pages mapped may be out of
+ * reach. It's the callers responsibility to make sure this happens. The
+ * original bio must be passed back in to blk_rq_unmap_user() for proper
+ * unmapping.
+ */
+int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+ struct sg_iovec *iov, int iov_count)
+{
+ struct bio *bio;
+
+ if (!iov || iov_count <= 0)
+ return -EINVAL;
+
+ /* we don't allow misaligned data like bio_map_user() does. If the
+ * user is using sg, they're expected to know the alignment constraints
+ * and respect them accordingly */
+ bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ);
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+ rq->bio = rq->biotail = bio;
+ blk_rq_bio_prep(q, rq, bio);
+ rq->buffer = rq->data = NULL;
+ rq->data_len = bio->bi_size;
+ return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_user_iov);
+
+/**
* blk_rq_unmap_user - unmap a request with user data
- * @rq: request to be unmapped
- * @bio: bio for the request
+ * @bio: bio to be unmapped
* @ulen: length of user buffer
*
* Description:
- * Unmap a request previously mapped by blk_rq_map_user().
+ * Unmap a bio previously mapped by blk_rq_map_user().
*/
-int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
+int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
{
int ret = 0;
@@ -2184,31 +2244,89 @@ int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
ret = bio_uncopy_user(bio);
}
- blk_put_request(rq);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(blk_rq_unmap_user);
/**
+ * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage
+ * @q: request queue where request should be inserted
+ * @rq: request to fill
+ * @kbuf: the kernel buffer
+ * @len: length of user data
+ * @gfp_mask: memory allocation flags
+ */
+int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+ unsigned int len, gfp_t gfp_mask)
+{
+ struct bio *bio;
+
+ if (len > (q->max_sectors << 9))
+ return -EINVAL;
+ if (!len || !kbuf)
+ return -EINVAL;
+
+ bio = bio_map_kern(q, kbuf, len, gfp_mask);
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+ if (rq_data_dir(rq) == WRITE)
+ bio->bi_rw |= (1 << BIO_RW);
+
+ rq->bio = rq->biotail = bio;
+ blk_rq_bio_prep(q, rq, bio);
+
+ rq->buffer = rq->data = NULL;
+ rq->data_len = len;
+ return 0;
+}
+
+EXPORT_SYMBOL(blk_rq_map_kern);
+
+/**
+ * blk_execute_rq_nowait - insert a request into queue for execution
+ * @q: queue to insert the request in
+ * @bd_disk: matching gendisk
+ * @rq: request to insert
+ * @at_head: insert request at head or tail of queue
+ * @done: I/O completion handler
+ *
+ * Description:
+ * Insert a fully prepared request at the back of the io scheduler queue
+ * for execution. Don't wait for completion.
+ */
+void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
+ struct request *rq, int at_head,
+ void (*done)(struct request *))
+{
+ int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+
+ rq->rq_disk = bd_disk;
+ rq->flags |= REQ_NOMERGE;
+ rq->end_io = done;
+ elv_add_request(q, rq, where, 1);
+ generic_unplug_device(q);
+}
+
+/**
* blk_execute_rq - insert a request into queue for execution
* @q: queue to insert the request in
* @bd_disk: matching gendisk
* @rq: request to insert
+ * @at_head: insert request at head or tail of queue
*
* Description:
* Insert a fully prepared request at the back of the io scheduler queue
- * for execution.
+ * for execution and wait for completion.
*/
int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
- struct request *rq)
+ struct request *rq, int at_head)
{
DECLARE_COMPLETION(wait);
char sense[SCSI_SENSE_BUFFERSIZE];
int err = 0;
- rq->rq_disk = bd_disk;
-
/*
* we need an extra reference to the request, so we can look at
* it after io completion
@@ -2221,11 +2339,8 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
rq->sense_len = 0;
}
- rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
- rq->end_io = blk_end_sync_rq;
- elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
- generic_unplug_device(q);
+ blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
wait_for_completion(&wait);
rq->waiting = NULL;
@@ -2272,16 +2387,9 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
if (!blk_fs_request(rq) || !rq->rq_disk)
return;
- if (rw == READ) {
- __disk_stat_add(rq->rq_disk, read_sectors, nr_sectors);
- if (!new_io)
- __disk_stat_inc(rq->rq_disk, read_merges);
- } else if (rw == WRITE) {
- __disk_stat_add(rq->rq_disk, write_sectors, nr_sectors);
- if (!new_io)
- __disk_stat_inc(rq->rq_disk, write_merges);
- }
- if (new_io) {
+ if (!new_io) {
+ __disk_stat_inc(rq->rq_disk, merges[rw]);
+ } else {
disk_round_stats(rq->rq_disk);
rq->rq_disk->in_flight++;
}
@@ -2325,13 +2433,15 @@ void disk_round_stats(struct gendisk *disk)
{
unsigned long now = jiffies;
- __disk_stat_add(disk, time_in_queue,
- disk->in_flight * (now - disk->stamp));
- disk->stamp = now;
+ if (now == disk->stamp)
+ return;
- if (disk->in_flight)
- __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
- disk->stamp_idle = now;
+ if (disk->in_flight) {
+ __disk_stat_add(disk, time_in_queue,
+ disk->in_flight * (now - disk->stamp));
+ __disk_stat_add(disk, io_ticks, (now - disk->stamp));
+ }
+ disk->stamp = now;
}
/*
@@ -2346,6 +2456,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
if (unlikely(--req->ref_count))
return;
+ elv_completed_request(q, req);
+
req->rq_status = RQ_INACTIVE;
req->rl = NULL;
@@ -2355,26 +2467,25 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
*/
if (rl) {
int rw = rq_data_dir(req);
-
- elv_completed_request(q, req);
+ int priv = req->flags & REQ_ELVPRIV;
BUG_ON(!list_empty(&req->queuelist));
blk_free_request(q, req);
- freed_request(q, rw);
+ freed_request(q, rw, priv);
}
}
void blk_put_request(struct request *req)
{
+ unsigned long flags;
+ request_queue_t *q = req->q;
+
/*
- * if req->rl isn't set, this request didnt originate from the
- * block layer, so it's safe to just disregard it
+ * Gee, IDE calls in w/ NULL q. Fix IDE and remove the
+ * following if (q) test.
*/
- if (req->rl) {
- unsigned long flags;
- request_queue_t *q = req->q;
-
+ if (q) {
spin_lock_irqsave(q->queue_lock, flags);
__blk_put_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2673,113 +2784,16 @@ static inline void blk_partition_remap(struct bio *bio)
if (bdev != bdev->bd_contains) {
struct hd_struct *p = bdev->bd_part;
+ const int rw = bio_data_dir(bio);
+
+ p->sectors[rw] += bio_sectors(bio);
+ p->ios[rw]++;
- switch (bio_data_dir(bio)) {
- case READ:
- p->read_sectors += bio_sectors(bio);
- p->reads++;
- break;
- case WRITE:
- p->write_sectors += bio_sectors(bio);
- p->writes++;
- break;
- }
bio->bi_sector += p->start_sect;
bio->bi_bdev = bdev->bd_contains;
}
}
-void blk_finish_queue_drain(request_queue_t *q)
-{
- struct request_list *rl = &q->rq;
- struct request *rq;
- int requeued = 0;
-
- spin_lock_irq(q->queue_lock);
- clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
- while (!list_empty(&q->drain_list)) {
- rq = list_entry_rq(q->drain_list.next);
-
- list_del_init(&rq->queuelist);
- elv_requeue_request(q, rq);
- requeued++;
- }
-
- if (requeued)
- q->request_fn(q);
-
- spin_unlock_irq(q->queue_lock);
-
- wake_up(&rl->wait[0]);
- wake_up(&rl->wait[1]);
- wake_up(&rl->drain);
-}
-
-static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch)
-{
- int wait = rl->count[READ] + rl->count[WRITE];
-
- if (dispatch)
- wait += !list_empty(&q->queue_head);
-
- return wait;
-}
-
-/*
- * We rely on the fact that only requests allocated through blk_alloc_request()
- * have io scheduler private data structures associated with them. Any other
- * type of request (allocated on stack or through kmalloc()) should not go
- * to the io scheduler core, but be attached to the queue head instead.
- */
-void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch)
-{
- struct request_list *rl = &q->rq;
- DEFINE_WAIT(wait);
-
- spin_lock_irq(q->queue_lock);
- set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
- while (wait_drain(q, rl, wait_dispatch)) {
- prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE);
-
- if (wait_drain(q, rl, wait_dispatch)) {
- __generic_unplug_device(q);
- spin_unlock_irq(q->queue_lock);
- io_schedule();
- spin_lock_irq(q->queue_lock);
- }
-
- finish_wait(&rl->drain, &wait);
- }
-
- spin_unlock_irq(q->queue_lock);
-}
-
-/*
- * block waiting for the io scheduler being started again.
- */
-static inline void block_wait_queue_running(request_queue_t *q)
-{
- DEFINE_WAIT(wait);
-
- while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
- struct request_list *rl = &q->rq;
-
- prepare_to_wait_exclusive(&rl->drain, &wait,
- TASK_UNINTERRUPTIBLE);
-
- /*
- * re-check the condition. avoids using prepare_to_wait()
- * in the fast path (queue is running)
- */
- if (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))
- io_schedule();
-
- finish_wait(&rl->drain, &wait);
- }
-}
-
static void handle_bad_sector(struct bio *bio)
{
char b[BDEVNAME_SIZE];
@@ -2875,8 +2889,6 @@ end_io:
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
- block_wait_queue_running(q);
-
/*
* If this device has partitions, remap block n
* of partition p to block n+start(p) of the disk.
@@ -3023,6 +3035,12 @@ static int __end_that_request_first(struct request *req, int uptodate,
(unsigned long long)req->sector);
}
+ if (blk_fs_request(req) && req->rq_disk) {
+ const int rw = rq_data_dir(req);
+
+ __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
+ }
+
total_bytes = bio_nbytes = 0;
while ((bio = req->bio) != NULL) {
int nbytes;
@@ -3151,16 +3169,10 @@ void end_that_request_last(struct request *req)
if (disk && blk_fs_request(req)) {
unsigned long duration = jiffies - req->start_time;
- switch (rq_data_dir(req)) {
- case WRITE:
- __disk_stat_inc(disk, writes);
- __disk_stat_add(disk, write_ticks, duration);
- break;
- case READ:
- __disk_stat_inc(disk, reads);
- __disk_stat_add(disk, read_ticks, duration);
- break;
- }
+ const int rw = rq_data_dir(req);
+
+ __disk_stat_inc(disk, ios[rw]);
+ __disk_stat_add(disk, ticks[rw], duration);
disk_round_stats(disk);
disk->in_flight--;
}
@@ -3285,7 +3297,7 @@ void exit_io_context(void)
* but since the current task itself holds a reference, the context can be
* used in general code, so long as it stays within `current` context.
*/
-struct io_context *current_io_context(int gfp_flags)
+struct io_context *current_io_context(gfp_t gfp_flags)
{
struct task_struct *tsk = current;
struct io_context *ret;
@@ -3316,7 +3328,7 @@ EXPORT_SYMBOL(current_io_context);
*
* This is always called in the context of the task which submitted the I/O.
*/
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *get_io_context(gfp_t gfp_flags)
{
struct io_context *ret;
ret = current_io_context(gfp_flags);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b35e08876dd4..96c664af8d06 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -881,7 +881,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
{
struct file *filp = lo->lo_backing_file;
- int gfp = lo->old_gfp_mask;
+ gfp_t gfp = lo->old_gfp_mask;
if (lo->lo_state != Lo_bound)
return -ENXIO;
diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c
index b1730b62c37e..e54f006e7e60 100644
--- a/drivers/block/noop-iosched.c
+++ b/drivers/block/noop-iosched.c
@@ -7,57 +7,20 @@
#include <linux/module.h>
#include <linux/init.h>
-/*
- * See if we can find a request that this buffer can be coalesced with.
- */
-static int elevator_noop_merge(request_queue_t *q, struct request **req,
- struct bio *bio)
-{
- int ret;
-
- ret = elv_try_last_merge(q, bio);
- if (ret != ELEVATOR_NO_MERGE)
- *req = q->last_merge;
-
- return ret;
-}
-
-static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
- struct request *next)
-{
- list_del_init(&next->queuelist);
-}
-
-static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
- int where)
+static void elevator_noop_add_request(request_queue_t *q, struct request *rq)
{
- if (where == ELEVATOR_INSERT_FRONT)
- list_add(&rq->queuelist, &q->queue_head);
- else
- list_add_tail(&rq->queuelist, &q->queue_head);
-
- /*
- * new merges must not precede this barrier
- */
- if (rq->flags & REQ_HARDBARRIER)
- q->last_merge = NULL;
- else if (!q->last_merge)
- q->last_merge = rq;
+ rq->flags |= REQ_NOMERGE;
+ elv_dispatch_add_tail(q, rq);
}
-static struct request *elevator_noop_next_request(request_queue_t *q)
+static int elevator_noop_dispatch(request_queue_t *q, int force)
{
- if (!list_empty(&q->queue_head))
- return list_entry_rq(q->queue_head.next);
-
- return NULL;
+ return 0;
}
static struct elevator_type elevator_noop = {
.ops = {
- .elevator_merge_fn = elevator_noop_merge,
- .elevator_merge_req_fn = elevator_noop_merge_requests,
- .elevator_next_req_fn = elevator_noop_next_request,
+ .elevator_dispatch_fn = elevator_noop_dispatch,
.elevator_add_req_fn = elevator_noop_add_request,
},
.elevator_name = "noop",
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 1fef136c0e41..ce94aa11f6a7 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -29,6 +29,7 @@
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/sched.h> /* TASK_* */
#ifdef CONFIG_PARPORT_MODULE
#define CONFIG_PARPORT
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 7289f67e9568..ac5ba462710b 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -516,8 +516,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
static void pcd_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pcd_reset(struct pcd_unit *cd)
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 060b1f2a91dd..e9746af29b9f 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -507,8 +507,7 @@ static void pf_eject(struct pf_unit *pf)
static void pf_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
/* the ATAPI standard actually specifies the contents of all 7 registers
@@ -751,6 +750,14 @@ static int pf_ready(void)
static struct request_queue *pf_queue;
+static void pf_end_request(int uptodate)
+{
+ if (pf_req) {
+ end_request(pf_req, uptodate);
+ pf_req = NULL;
+ }
+}
+
static void do_pf_request(request_queue_t * q)
{
if (pf_busy)
@@ -766,7 +773,7 @@ repeat:
pf_count = pf_req->current_nr_sectors;
if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
@@ -781,7 +788,7 @@ repeat:
pi_do_claimed(pf_current->pi, do_pf_write);
else {
pf_busy = 0;
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
}
@@ -799,9 +806,7 @@ static int pf_next_buf(void)
if (!pf_count)
return 1;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, 1);
- pf_count = pf_req->current_nr_sectors;
- pf_buf = pf_req->buffer;
+ pf_end_request(1);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
return 1;
}
@@ -811,7 +816,7 @@ static inline void next_request(int success)
unsigned long saved_flags;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, success);
+ pf_end_request(success);
pf_busy = 0;
do_pf_request(pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 84d8e291ed96..6f5df0fad703 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -162,6 +162,8 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
#include <linux/mtio.h>
#include <linux/pg.h>
#include <linux/device.h>
+#include <linux/sched.h> /* current, TASK_* */
+#include <linux/jiffies.h>
#include <asm/uaccess.h>
@@ -276,8 +278,7 @@ static inline u8 DRIVE(struct pg *dev)
static void pg_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg)
@@ -675,7 +676,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_device_create(pg_class, MKDEV(major, unit),
+ class_device_create(pg_class, NULL, MKDEV(major, unit),
NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5fe8ee86f095..715ae5dc88fb 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -146,6 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
#include <linux/slab.h>
#include <linux/mtio.h>
#include <linux/device.h>
+#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
#include <asm/uaccess.h>
@@ -383,8 +384,7 @@ static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *
static void pt_sleep(int cs)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(cs);
+ schedule_timeout_interruptible(cs);
}
static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
@@ -972,7 +972,7 @@ static int __init pt_init(void)
devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_device_create(pt_class, MKDEV(major, unit),
+ class_device_create(pt_class, NULL, MKDEV(major, unit),
NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR,
@@ -981,7 +981,7 @@ static int __init pt_init(void)
class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class;
}
- class_device_create(pt_class, MKDEV(major, unit + 128),
+ class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR,
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7b838342f0a3..a280e679b1ca 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -5,29 +5,41 @@
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
- * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
- * DVD-RW devices (aka an exercise in block layer masturbation)
+ * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
+ * DVD-RAM devices.
*
+ * Theory of operation:
*
- * TODO: (circa order of when I will fix it)
- * - Only able to write on CD-RW media right now.
- * - check host application code on media and set it in write page
- * - interface for UDF <-> packet to negotiate a new location when a write
- * fails.
- * - handle OPC, especially for -RW media
+ * At the lowest level, there is the standard driver for the CD/DVD device,
+ * typically ide-cd.c or sr.c. This driver can handle read and write requests,
+ * but it doesn't know anything about the special restrictions that apply to
+ * packet writing. One restriction is that write requests must be aligned to
+ * packet boundaries on the physical media, and the size of a write request
+ * must be equal to the packet size. Another restriction is that a
+ * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
+ * command, if the previous command was a write.
*
- * Theory of operation:
+ * The purpose of the packet writing driver is to hide these restrictions from
+ * higher layers, such as file systems, and present a block device that can be
+ * randomly read and written using 2kB-sized blocks.
+ *
+ * The lowest layer in the packet writing driver is the packet I/O scheduler.
+ * Its data is defined by the struct packet_iosched and includes two bio
+ * queues with pending read and write requests. These queues are processed
+ * by the pkt_iosched_process_queue() function. The write requests in this
+ * queue are already properly aligned and sized. This layer is responsible for
+ * issuing the flush cache commands and scheduling the I/O in a good order.
*
- * We use a custom make_request_fn function that forwards reads directly to
- * the underlying CD device. Write requests are either attached directly to
- * a live packet_data object, or simply stored sequentially in a list for
- * later processing by the kcdrwd kernel thread. This driver doesn't use
- * any elevator functionally as defined by the elevator_s struct, but the
- * underlying CD device uses a standard elevator.
+ * The next layer transforms unaligned write requests to aligned writes. This
+ * transformation requires reading missing pieces of data from the underlying
+ * block device, assembling the pieces to full packets and queuing them to the
+ * packet I/O scheduler.
*
- * This strategy makes it possible to do very late merging of IO requests.
- * A new bio sent to pkt_make_request can be merged with a live packet_data
- * object even if the object is in the data gathering state.
+ * At the top layer there is a custom make_request_fn function that forwards
+ * read requests directly to the iosched queue and puts write requests in the
+ * unaligned write queue. A kernel thread performs the necessary read
+ * gathering to convert the unaligned writes to aligned writes and then feeds
+ * them to the packet I/O scheduler.
*
*************************************************************************/
@@ -100,10 +112,9 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
goto no_bio;
bio_init(bio);
- bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL);
+ bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
if (!bvl)
goto no_bvl;
- memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec));
bio->bi_max_vecs = nr_iovecs;
bio->bi_io_vec = bvl;
@@ -125,10 +136,9 @@ static struct packet_data *pkt_alloc_packet_data(void)
int i;
struct packet_data *pkt;
- pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+ pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!pkt)
goto no_pkt;
- memset(pkt, 0, sizeof(struct packet_data));
pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
if (!pkt->w_bio)
@@ -219,7 +229,7 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
return 1;
}
-static void *pkt_rb_alloc(unsigned int __nocast gfp_mask, void *data)
+static void *pkt_rb_alloc(gfp_t gfp_mask, void *data)
{
return kmalloc(sizeof(struct pkt_rb_node), gfp_mask);
}
@@ -659,7 +669,6 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
- BUG_ON(offs > PAGE_SIZE);
offs = 0;
p++;
}
@@ -724,12 +733,6 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 0);
atomic_set(&pkt->io_errors, 0);
- if (pkt->cache_valid) {
- VPRINTK("pkt_gather_data: zone %llx cached\n",
- (unsigned long long)pkt->sector);
- goto out_account;
- }
-
/*
* Figure out which frames we need to read before we can write.
*/
@@ -738,6 +741,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
+ pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
BUG_ON(first_frame < 0);
BUG_ON(first_frame + num_frames > pkt->frames);
for (f = first_frame; f < first_frame + num_frames; f++)
@@ -745,6 +749,12 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
}
spin_unlock(&pkt->lock);
+ if (pkt->cache_valid) {
+ VPRINTK("pkt_gather_data: zone %llx cached\n",
+ (unsigned long long)pkt->sector);
+ goto out_account;
+ }
+
/*
* Schedule reads for missing parts of the packet.
*/
@@ -778,7 +788,6 @@ out_account:
frames_read, (unsigned long long)pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
- pd->stats.secs_w += pd->settings.size;
}
/*
@@ -794,10 +803,11 @@ static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zo
list_del_init(&pkt->list);
if (pkt->sector != zone)
pkt->cache_valid = 0;
- break;
+ return pkt;
}
}
- return pkt;
+ BUG();
+ return NULL;
}
static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -941,12 +951,10 @@ try_next_bio:
}
pkt = pkt_get_packet_data(pd, zone);
- BUG_ON(!pkt);
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
pkt->frames = pd->settings.size >> 2;
- BUG_ON(pkt->frames > PACKET_MAX_SIZE);
pkt->write_size = 0;
/*
@@ -1636,6 +1644,10 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
printk("pktcdvd: detected zero packet size!\n");
pd->settings.size = 128;
}
+ if (pd->settings.size > PACKET_MAX_SECTORS) {
+ printk("pktcdvd: packet size is too big\n");
+ return -ENXIO;
+ }
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -2070,7 +2082,7 @@ static int pkt_close(struct inode *inode, struct file *file)
}
-static void *psd_pool_alloc(unsigned int __nocast gfp_mask, void *data)
+static void *psd_pool_alloc(gfp_t gfp_mask, void *data)
{
return kmalloc(sizeof(struct packet_stacked_data), gfp_mask);
}
@@ -2198,7 +2210,6 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
* No matching packet found. Store the bio in the work queue.
*/
node = mempool_alloc(pd->rb_pool, GFP_NOIO);
- BUG_ON(!node);
node->bio = bio;
spin_lock(&pd->lock);
BUG_ON(pd->bio_queue_size < 0);
@@ -2406,7 +2417,6 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
- BUG_ON(!pd);
switch (cmd) {
/*
@@ -2477,10 +2487,9 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
return -EBUSY;
}
- pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
+ pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
return ret;
- memset(pd, 0, sizeof(struct pktcdvd_device));
pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
if (!pd->rb_pool)
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 29548784cb7b..29d1518be72a 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -99,8 +99,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
static int no_int_yet;
static int ps2esdi_drives;
static u_short io_base;
-static struct timer_list esdi_timer =
- TIMER_INITIALIZER(ps2esdi_reset_timer, 0, 0);
+static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
static int reset_status;
static int ps2esdi_slot = -1;
static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 145c1fbffe01..68c60a5bcdab 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -348,7 +348,7 @@ static int rd_open(struct inode *inode, struct file *filp)
struct block_device *bdev = inode->i_bdev;
struct address_space *mapping;
unsigned bsize;
- int gfp_mask;
+ gfp_t gfp_mask;
inode = igrab(bdev->bd_inode);
rd_bdev[unit] = bdev;
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 681871ca5d60..382dea7b224c 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -123,6 +123,7 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_read(READ_12),
safe_for_read(READ_16),
safe_for_read(READ_BUFFER),
+ safe_for_read(READ_DEFECT_DATA),
safe_for_read(READ_LONG),
safe_for_read(INQUIRY),
safe_for_read(MODE_SENSE),
@@ -167,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_write(WRITE_VERIFY_12),
safe_for_write(WRITE_16),
safe_for_write(WRITE_LONG),
+ safe_for_write(WRITE_LONG_2),
safe_for_write(ERASE),
safe_for_write(GPCMD_MODE_SELECT_10),
safe_for_write(MODE_SELECT),
@@ -199,15 +201,15 @@ static int verify_command(struct file *file, unsigned char *cmd)
return 0;
}
+ /* And root can do any command.. */
+ if (capable(CAP_SYS_RAWIO))
+ return 0;
+
if (!type) {
cmd_type[cmd[0]] = CMD_WARNED;
printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]);
}
- /* And root can do any command.. */
- if (capable(CAP_SYS_RAWIO))
- return 0;
-
/* Otherwise fail it with an "Operation not permitted" */
return -EPERM;
}
@@ -216,7 +218,7 @@ static int sg_io(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
{
unsigned long start_time;
- int reading, writing;
+ int writing = 0, ret = 0;
struct request *rq;
struct bio *bio;
char sense[SCSI_SENSE_BUFFERSIZE];
@@ -231,38 +233,48 @@ static int sg_io(struct file *file, request_queue_t *q,
if (verify_command(file, cmd))
return -EPERM;
- /*
- * we'll do that later
- */
- if (hdr->iovec_count)
- return -EOPNOTSUPP;
-
if (hdr->dxfer_len > (q->max_sectors << 9))
return -EIO;
- reading = writing = 0;
- if (hdr->dxfer_len) {
+ if (hdr->dxfer_len)
switch (hdr->dxfer_direction) {
default:
return -EINVAL;
case SG_DXFER_TO_FROM_DEV:
- reading = 1;
- /* fall through */
case SG_DXFER_TO_DEV:
writing = 1;
break;
case SG_DXFER_FROM_DEV:
- reading = 1;
break;
}
- rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp,
- hdr->dxfer_len);
+ rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
+ if (!rq)
+ return -ENOMEM;
+
+ if (hdr->iovec_count) {
+ const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+ struct sg_iovec *iov;
+
+ iov = kmalloc(size, GFP_KERNEL);
+ if (!iov) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(iov, hdr->dxferp, size)) {
+ kfree(iov);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
+ kfree(iov);
+ } else if (hdr->dxfer_len)
+ ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
- } else
- rq = blk_get_request(q, READ, __GFP_WAIT);
+ if (ret)
+ goto out;
/*
* fill in request structure
@@ -298,7 +310,7 @@ static int sg_io(struct file *file, request_queue_t *q,
* (if he doesn't check that is his problem).
* N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
- blk_execute_rq(q, bd_disk, rq);
+ blk_execute_rq(q, bd_disk, rq, 0);
/* write to all output members */
hdr->status = 0xff & rq->errors;
@@ -320,12 +332,14 @@ static int sg_io(struct file *file, request_queue_t *q,
hdr->sb_len_wr = len;
}
- if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len))
- return -EFAULT;
+ if (blk_rq_unmap_user(bio, hdr->dxfer_len))
+ ret = -EFAULT;
/* may not have succeeded, but output values written to control
* structure (struct sg_io_hdr). */
- return 0;
+out:
+ blk_put_request(rq);
+ return ret;
}
#define OMAX_SB_LEN 16 /* For backward compatibility */
@@ -408,7 +422,7 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
- blk_execute_rq(q, bd_disk, rq);
+ blk_execute_rq(q, bd_disk, rq, 0);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len && rq->sense) {
@@ -561,7 +575,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
rq->cmd[0] = GPCMD_START_STOP_UNIT;
rq->cmd[4] = 0x02 + (close != 0);
rq->cmd_len = 6;
- err = blk_execute_rq(q, bd_disk, rq);
+ err = blk_execute_rq(q, bd_disk, rq, 0);
blk_put_request(rq);
break;
default:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index e5f7494c00ee..e425ad3eebba 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -834,8 +834,7 @@ static int fd_eject(struct floppy_state *fs)
break;
}
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (swim3_readbit(fs, DISK_IN) == 0)
break;
}
@@ -906,8 +905,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
break;
}
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0))
@@ -992,8 +990,7 @@ static int floppy_revalidate(struct gendisk *disk)
if (signal_pending(current))
break;
swim3_select(fs, RELAX);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
|| swim3_readbit(fs, DISK_IN) == 0;
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index a1283f6dc018..89e3c2f8b776 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -338,8 +338,7 @@ static int swimiop_eject(struct floppy_state *fs)
err = -EINTR;
break;
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
release_drive(fs);
return cmd->error;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index d57007b92f77..1ded3b433459 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1,7 +1,7 @@
/*
* sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
*
- * Copyright 2004 Red Hat, Inc.
+ * Copyright 2004-2005 Red Hat, Inc.
*
* Author/maintainer: Jeff Garzik <jgarzik@pobox.com>
*
@@ -31,10 +31,6 @@
#include <asm/semaphore.h>
#include <asm/uaccess.h>
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SATA SX8 block driver");
-
#if 0
#define CARM_DEBUG
#define CARM_VERBOSE_DEBUG
@@ -45,9 +41,35 @@ MODULE_DESCRIPTION("Promise SATA SX8 block driver");
#undef CARM_NDEBUG
#define DRV_NAME "sx8"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "1.0"
#define PFX DRV_NAME ": "
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 block driver");
+MODULE_VERSION(DRV_VERSION);
+
+/*
+ * SX8 hardware has a single message queue for all ATA ports.
+ * When this driver was written, the hardware (firmware?) would
+ * corrupt data eventually, if more than one request was outstanding.
+ * As one can imagine, having 8 ports bottlenecking on a single
+ * command hurts performance.
+ *
+ * Based on user reports, later versions of the hardware (firmware?)
+ * seem to be able to survive with more than one command queued.
+ *
+ * Therefore, we default to the safe option -- 1 command -- but
+ * allow the user to increase this.
+ *
+ * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
+ * but problems seem to occur when you exceed ~30, even on newer hardware.
+ */
+static int max_queue = 1;
+module_param(max_queue, int, 0444);
+MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
+
+
#define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN)
/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
@@ -90,12 +112,10 @@ enum {
/* command message queue limits */
CARM_MAX_REQ = 64, /* max command msgs per host */
- CARM_MAX_Q = 1, /* one command at a time */
CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */
/* S/G limits, host-wide and per-request */
CARM_MAX_REQ_SG = 32, /* max s/g entries per request */
- CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
CARM_MAX_HOST_SG = 600, /* max s/g entries per host */
CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */
@@ -181,6 +201,10 @@ enum {
FL_DYN_MAJOR = (1 << 17),
};
+enum {
+ CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
+};
+
enum scatter_gather_types {
SGT_32BIT = 0,
SGT_64BIT = 1,
@@ -218,7 +242,6 @@ static const char *state_name[] = {
struct carm_port {
unsigned int port_no;
- unsigned int n_queued;
struct gendisk *disk;
struct carm_host *host;
@@ -448,7 +471,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
if (msg_size <= msg_sizes[i])
return i;
-
+
return -ENOENT;
}
@@ -509,7 +532,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
return NULL;
- for (i = 0; i < CARM_MAX_Q; i++)
+ for (i = 0; i < max_queue; i++)
if ((host->msg_alloc & (1ULL << i)) == 0) {
struct carm_request *crq = &host->req[i];
crq->port = NULL;
@@ -521,14 +544,14 @@ static struct carm_request *carm_get_request(struct carm_host *host)
assert(host->n_msgs <= CARM_MAX_REQ);
return crq;
}
-
+
DPRINTK("no request available, returning NULL\n");
return NULL;
}
static int carm_put_request(struct carm_host *host, struct carm_request *crq)
{
- assert(crq->tag < CARM_MAX_Q);
+ assert(crq->tag < max_queue);
if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
return -EINVAL; /* tried to clear a tag that was not active */
@@ -791,7 +814,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
int is_ok)
{
carm_end_request_queued(host, crq, is_ok);
- if (CARM_MAX_Q == 1)
+ if (max_queue == 1)
carm_round_robin(host);
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
(host->hw_sg_used <= CARM_SG_LOW_WATER)) {
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index a026567f5d18..bfb23d543ff7 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -16,9 +16,10 @@
* -- verify the 13 conditions and do bulk resets
* -- kill last_pipe and simply do two-state clearing on both pipes
* -- verify protocol (bulk) from USB descriptors (maybe...)
- * -- highmem and sg
+ * -- highmem
* -- move top_sense and work_bcs into separate allocations (if they survive)
* for cache purists and esoteric architectures.
+ * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ?
* -- prune comments, they are too volumnous
* -- Exterminate P3 printks
* -- Resove XXX's
@@ -171,7 +172,7 @@ struct bulk_cs_wrap {
*/
struct ub_dev;
-#define UB_MAX_REQ_SG 1
+#define UB_MAX_REQ_SG 9 /* cdrecord requires 32KB and maybe a header */
#define UB_MAX_SECTORS 64
/*
@@ -234,13 +235,10 @@ struct ub_scsi_cmd {
int stat_count; /* Retries getting status. */
- /*
- * We do not support transfers from highmem pages
- * because the underlying USB framework does not do what we need.
- */
- char *data; /* Requested buffer */
unsigned int len; /* Requested length */
- // struct scatterlist sgv[UB_MAX_REQ_SG];
+ unsigned int current_sg;
+ unsigned int nsg; /* sgv[nsg] */
+ struct scatterlist sgv[UB_MAX_REQ_SG];
struct ub_lun *lun;
void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
@@ -389,17 +387,18 @@ struct ub_dev {
struct bulk_cs_wrap work_bcs;
struct usb_ctrlrequest work_cr;
+ int sg_stat[6];
struct ub_scsi_trace tr;
};
/*
*/
static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq);
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq);
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -407,6 +406,7 @@ static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
static void ub_scsi_action(unsigned long _dev);
static void ub_scsi_dispatch(struct ub_dev *sc);
static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc);
static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -500,7 +500,8 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
}
}
-static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
+static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
+ char *page)
{
struct usb_interface *intf;
struct ub_dev *sc;
@@ -523,6 +524,14 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, c
cnt += sprintf(page + cnt,
"qlen %d qmax %d\n",
sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+ cnt += sprintf(page + cnt,
+ "sg %d %d %d %d %d .. %d\n",
+ sc->sg_stat[0],
+ sc->sg_stat[1],
+ sc->sg_stat[2],
+ sc->sg_stat[3],
+ sc->sg_stat[4],
+ sc->sg_stat[5]);
list_for_each (p, &sc->luns) {
lun = list_entry(p, struct ub_lun, link);
@@ -744,20 +753,20 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
* The request function is our main entry point
*/
-static void ub_bd_rq_fn(request_queue_t *q)
+static void ub_request_fn(request_queue_t *q)
{
struct ub_lun *lun = q->queuedata;
struct request *rq;
while ((rq = elv_next_request(q)) != NULL) {
- if (ub_bd_rq_fn_1(lun, rq) != 0) {
+ if (ub_request_fn_1(lun, rq) != 0) {
blk_stop_queue(q);
break;
}
}
}
-static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
+static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
{
struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
@@ -774,9 +783,8 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
blkdev_dequeue_request(rq);
-
if (blk_pc_request(rq)) {
- rc = ub_cmd_build_packet(sc, cmd, rq);
+ rc = ub_cmd_build_packet(sc, lun, cmd, rq);
} else {
rc = ub_cmd_build_block(sc, lun, cmd, rq);
}
@@ -791,7 +799,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
cmd->back = rq;
cmd->tag = sc->tagcnt++;
- if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
+ if (ub_submit_scsi(sc, cmd) != 0) {
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
return 0;
@@ -804,58 +812,31 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq)
{
int ub_dir;
-#if 0 /* We use rq->buffer for now */
- struct scatterlist *sg;
int n_elem;
-#endif
unsigned int block, nblks;
if (rq_data_dir(rq) == WRITE)
ub_dir = UB_DIR_WRITE;
else
ub_dir = UB_DIR_READ;
+ cmd->dir = ub_dir;
/*
* get scatterlist from block layer
*/
-#if 0 /* We use rq->buffer for now */
- sg = &cmd->sgv[0];
- n_elem = blk_rq_map_sg(q, rq, sg);
+ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
if (n_elem <= 0) {
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- blk_start_queue(q);
- return 0; /* request with no s/g entries? */
+ printk(KERN_INFO "%s: failed request map (%d)\n",
+ sc->name, n_elem); /* P3 */
+ return -1; /* request with no s/g entries? */
}
-
- if (n_elem != 1) { /* Paranoia */
+ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- blk_start_queue(q);
- return 0;
- }
-#endif
-
- /*
- * XXX Unfortunately, this check does not work. It is quite possible
- * to get bogus non-null rq->buffer if you allow sg by mistake.
- */
- if (rq->buffer == NULL) {
- /*
- * This must not happen if we set the queue right.
- * The block level must create bounce buffers for us.
- */
- static int do_print = 1;
- if (do_print) {
- printk(KERN_WARNING "%s: unmapped block request"
- " flags 0x%lx sectors %lu\n",
- sc->name, rq->flags, rq->nr_sectors);
- do_print = 0;
- }
return -1;
}
+ cmd->nsg = n_elem;
+ sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
/*
* build the command
@@ -876,30 +857,15 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb[8] = nblks;
cmd->cdb_len = 10;
- cmd->dir = ub_dir;
- cmd->data = rq->buffer;
cmd->len = rq->nr_sectors * 512;
return 0;
}
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq)
+static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq)
{
-
- if (rq->data_len != 0 && rq->data == NULL) {
- static int do_print = 1;
- if (do_print) {
- printk(KERN_WARNING "%s: unmapped packet request"
- " flags 0x%lx length %d\n",
- sc->name, rq->flags, rq->data_len);
- do_print = 0;
- }
- return -1;
- }
-
- memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
- cmd->cdb_len = rq->cmd_len;
+ int n_elem;
if (rq->data_len == 0) {
cmd->dir = UB_DIR_NONE;
@@ -908,8 +874,29 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
cmd->dir = UB_DIR_WRITE;
else
cmd->dir = UB_DIR_READ;
+
+ }
+
+ /*
+ * get scatterlist from block layer
+ */
+ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
+ if (n_elem < 0) {
+ printk(KERN_INFO "%s: failed request map (%d)\n",
+ sc->name, n_elem); /* P3 */
+ return -1;
+ }
+ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
+ printk(KERN_WARNING "%s: request with %d segments\n",
+ sc->name, n_elem);
+ return -1;
}
- cmd->data = rq->data;
+ cmd->nsg = n_elem;
+ sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+
+ memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
+ cmd->cdb_len = rq->cmd_len;
+
cmd->len = rq->data_len;
return 0;
@@ -919,24 +906,34 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct request *rq = cmd->back;
struct ub_lun *lun = cmd->lun;
- struct gendisk *disk = lun->disk;
- request_queue_t *q = disk->queue;
int uptodate;
- if (blk_pc_request(rq)) {
- /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
- memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
- rq->sense_len = UB_SENSE_SIZE;
- }
-
- if (cmd->error == 0)
+ if (cmd->error == 0) {
uptodate = 1;
- else
+
+ if (blk_pc_request(rq)) {
+ if (cmd->act_len >= rq->data_len)
+ rq->data_len = 0;
+ else
+ rq->data_len -= cmd->act_len;
+ }
+ } else {
uptodate = 0;
+ if (blk_pc_request(rq)) {
+ /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
+ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
+ rq->sense_len = UB_SENSE_SIZE;
+ if (sc->top_sense[0] != 0)
+ rq->errors = SAM_STAT_CHECK_CONDITION;
+ else
+ rq->errors = DID_ERROR << 16;
+ }
+ }
+
ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
- blk_start_queue(q);
+ blk_start_queue(lun->disk->queue);
}
static void ub_end_rq(struct request *rq, int uptodate)
@@ -1014,7 +1011,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->send_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
/* Fill what we shouldn't be filling, because usb-storage did so. */
sc->work_urb.actual_length = 0;
@@ -1023,7 +1019,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
- printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
ub_complete(&sc->work_done);
return rc;
}
@@ -1103,7 +1098,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs;
- int pipe;
int rc;
if (atomic_read(&sc->poison)) {
@@ -1195,47 +1189,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
if (urb->status != 0) {
- printk("ub: cmd #%d cmd status (%d)\n", cmd->tag, urb->status); /* P3 */
goto Bad_End;
}
if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
- printk("ub: cmd #%d xferred %d\n", cmd->tag, urb->actual_length); /* P3 */
/* XXX Must do reset here to unconfuse the device */
goto Bad_End;
}
- if (cmd->dir == UB_DIR_NONE) {
+ if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) {
ub_state_stat(sc, cmd);
return;
}
- UB_INIT_COMPLETION(sc->work_done);
-
- if (cmd->dir == UB_DIR_READ)
- pipe = sc->recv_bulk_pipe;
- else
- pipe = sc->send_bulk_pipe;
- sc->last_pipe = pipe;
- usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
- cmd->data, cmd->len, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
- sc->work_urb.actual_length = 0;
- sc->work_urb.error_count = 0;
- sc->work_urb.status = 0;
-
- if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- /* XXX Clear stalls */
- printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
- ub_complete(&sc->work_done);
- ub_state_done(sc, cmd, rc);
- return;
- }
-
- sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
- add_timer(&sc->work_timer);
-
- cmd->state = UB_CMDST_DATA;
- ub_cmdtr_state(sc, cmd);
+ // udelay(125); // usb-storage has this
+ ub_data_start(sc, cmd);
} else if (cmd->state == UB_CMDST_DATA) {
if (urb->status == -EPIPE) {
@@ -1257,16 +1224,22 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if (urb->status == -EOVERFLOW) {
/*
* A babble? Failure, but we must transfer CSW now.
+ * XXX This is going to end in perpetual babble. Reset.
*/
cmd->error = -EOVERFLOW; /* A cheap trick... */
- } else {
- if (urb->status != 0)
- goto Bad_End;
+ ub_state_stat(sc, cmd);
+ return;
}
+ if (urb->status != 0)
+ goto Bad_End;
- cmd->act_len = urb->actual_length;
+ cmd->act_len += urb->actual_length;
ub_cmdtr_act_len(sc, cmd);
+ if (++cmd->current_sg < cmd->nsg) {
+ ub_data_start(sc, cmd);
+ return;
+ }
ub_state_stat(sc, cmd);
} else if (cmd->state == UB_CMDST_STAT) {
@@ -1401,6 +1374,44 @@ Bad_End: /* Little Excel is dead */
/*
* Factorization helper for the command state machine:
+ * Initiate a data segment transfer.
+ */
+static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+ struct scatterlist *sg = &cmd->sgv[cmd->current_sg];
+ int pipe;
+ int rc;
+
+ UB_INIT_COMPLETION(sc->work_done);
+
+ if (cmd->dir == UB_DIR_READ)
+ pipe = sc->recv_bulk_pipe;
+ else
+ pipe = sc->send_bulk_pipe;
+ sc->last_pipe = pipe;
+ usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
+ page_address(sg->page) + sg->offset, sg->length,
+ ub_urb_complete, sc);
+ sc->work_urb.actual_length = 0;
+ sc->work_urb.error_count = 0;
+ sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ /* XXX Clear stalls */
+ ub_complete(&sc->work_done);
+ ub_state_done(sc, cmd, rc);
+ return;
+ }
+
+ sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
+ add_timer(&sc->work_timer);
+
+ cmd->state = UB_CMDST_DATA;
+ ub_cmdtr_state(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
* Finish the command.
*/
static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
@@ -1426,7 +1437,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->recv_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
&sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1484,6 +1494,7 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct ub_scsi_cmd *scmd;
+ struct scatterlist *sg;
int rc;
if (cmd->cdb[0] == REQUEST_SENSE) {
@@ -1492,12 +1503,17 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
}
scmd = &sc->top_rqs_cmd;
+ memset(scmd, 0, sizeof(struct ub_scsi_cmd));
scmd->cdb[0] = REQUEST_SENSE;
scmd->cdb[4] = UB_SENSE_SIZE;
scmd->cdb_len = 6;
scmd->dir = UB_DIR_READ;
scmd->state = UB_CMDST_INIT;
- scmd->data = sc->top_sense;
+ scmd->nsg = 1;
+ sg = &scmd->sgv[0];
+ sg->page = virt_to_page(sc->top_sense);
+ sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
+ sg->length = UB_SENSE_SIZE;
scmd->len = UB_SENSE_SIZE;
scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
@@ -1541,7 +1557,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
- sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -1560,7 +1575,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
*/
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
{
- unsigned char *sense = scmd->data;
+ unsigned char *sense = sc->top_sense;
struct ub_scsi_cmd *cmd;
/*
@@ -1852,6 +1867,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret)
{
struct ub_scsi_cmd *cmd;
+ struct scatterlist *sg;
char *p;
enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };
unsigned long flags;
@@ -1872,7 +1888,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb_len = 10;
cmd->dir = UB_DIR_READ;
cmd->state = UB_CMDST_INIT;
- cmd->data = p;
+ cmd->nsg = 1;
+ sg = &cmd->sgv[0];
+ sg->page = virt_to_page(p);
+ sg->offset = (unsigned long)p & (PAGE_SIZE-1);
+ sg->length = 8;
cmd->len = 8;
cmd->lun = lun;
cmd->done = ub_probe_done;
@@ -1973,17 +1993,16 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
(unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
- sc->work_urb.transfer_flags = 0;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
if (rc == -EPIPE) {
- printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+ printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n",
sc->name); /* P3 */
} else {
- printk(KERN_WARNING
+ printk(KERN_NOTICE
"%s: Unable to submit GetMaxLUN (%d)\n",
sc->name, rc);
}
@@ -2001,6 +2020,18 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
del_timer_sync(&timer);
usb_kill_urb(&sc->work_urb);
+ if ((rc = sc->work_urb.status) < 0) {
+ if (rc == -EPIPE) {
+ printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+ sc->name); /* P3 */
+ } else {
+ printk(KERN_NOTICE
+ "%s: Error at GetMaxLUN (%d)\n",
+ sc->name, rc);
+ }
+ goto err_io;
+ }
+
if (sc->work_urb.actual_length != 1) {
printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
sc->work_urb.actual_length); /* P3 */
@@ -2021,6 +2052,7 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
kfree(p);
return nluns;
+err_io:
err_submit:
kfree(p);
err_alloc:
@@ -2053,7 +2085,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
- sc->work_urb.transfer_flags = 0;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
@@ -2186,8 +2217,10 @@ static int ub_probe(struct usb_interface *intf,
* This is needed to clear toggles. It is a problem only if we do
* `rmmod ub && modprobe ub` without disconnects, but we like that.
*/
+#if 0 /* iPod Mini fails if we do this (big white iPod works) */
ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+#endif
/*
* The way this is used by the startup code is a little specific.
@@ -2214,10 +2247,10 @@ static int ub_probe(struct usb_interface *intf,
for (i = 0; i < 3; i++) {
if ((rc = ub_sync_getmaxlun(sc)) < 0) {
/*
- * Some devices (i.e. Iomega Zip100) need this --
- * apparently the bulk pipes get STALLed when the
- * GetMaxLUN request is processed.
- * XXX I have a ZIP-100, verify it does this.
+ * This segment is taken from usb-storage. They say
+ * that ZIP-100 needs this, but my own ZIP-100 works
+ * fine without this.
+ * Still, it does not seem to hurt anything.
*/
if (rc == -EPIPE) {
ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
@@ -2286,10 +2319,10 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
disk->fops = &ub_bd_fops;
disk->private_data = lun;
- disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */
+ disk->driverfs_dev = &sc->intf->dev;
rc = -ENOMEM;
- if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
+ if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL)
goto err_blkqinit;
disk->queue = q;
@@ -2439,9 +2472,6 @@ static int __init ub_init(void)
{
int rc;
- /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
- sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
-
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
devfs_mk_dir(DEVFS_NAME);
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0c4c121d2e79..0f48301342da 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -34,6 +34,7 @@
* - set initialised bit then.
*/
+//#define DEBUG /* uncomment if you want debugging info (pr_debug) */
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -58,10 +59,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#define PRINTK(x...) do {} while (0)
-#define dprintk(x...) do {} while (0)
-/*#define dprintk(x...) printk(x) */
-
#define MM_MAXCARDS 4
#define MM_RAHEAD 2 /* two sectors */
#define MM_BLKSIZE 1024 /* 1k blocks */
@@ -299,7 +296,7 @@ static void mm_start_io(struct cardinfo *card)
/* make the last descriptor end the chain */
page = &card->mm_pages[card->Active];
- PRINTK("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
+ pr_debug("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
desc = &page->desc[page->cnt-1];
desc->control_bits |= cpu_to_le32(DMASCR_CHAIN_COMP_EN);
@@ -532,7 +529,7 @@ static void process_page(unsigned long data)
activate(card);
} else {
/* haven't finished with this one yet */
- PRINTK("do some more\n");
+ pr_debug("do some more\n");
mm_start_io(card);
}
out_unlock:
@@ -555,7 +552,7 @@ static void process_page(unsigned long data)
static int mm_make_request(request_queue_t *q, struct bio *bio)
{
struct cardinfo *card = q->queuedata;
- PRINTK("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
+ pr_debug("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
spin_lock_irq(&card->lock);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 46e56a25d2c8..2d518aa2720a 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -45,10 +45,10 @@
#include <asm/uaccess.h>
#include <asm/vio.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/vio.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/vio.h>
MODULE_DESCRIPTION("iSeries Virtual DASD");
MODULE_AUTHOR("Dave Boutcher");
@@ -776,15 +776,18 @@ static int viodasd_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viodasd_device_table[] __devinitdata = {
{ "viodasd", "" },
- { 0, }
+ { "", "" }
};
-
MODULE_DEVICE_TABLE(vio, viodasd_device_table);
+
static struct vio_driver viodasd_driver = {
- .name = "viodasd",
.id_table = viodasd_device_table,
.probe = viodasd_probe,
- .remove = viodasd_remove
+ .remove = viodasd_remove,
+ .driver = {
+ .name = "viodasd",
+ .owner = THIS_MODULE,
+ }
};
/*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 1676033da6c6..68b6d7b154cf 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -47,6 +47,7 @@
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -62,7 +63,7 @@ static int xd[5] = { -1,-1,-1,-1, };
#define XD_DONT_USE_DMA 0 /* Initial value. may be overriden using
"nodma" module option */
-#define XD_INIT_DISK_DELAY (30*HZ/1000) /* 30 ms delay during disk initialization */
+#define XD_INIT_DISK_DELAY (30) /* 30 ms delay during disk initialization */
/* Above may need to be increased if a problem with the 2nd drive detection
(ST11M controller) or resetting a controller (WD) appears */
@@ -529,10 +530,8 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
int success;
xdc_busy = 1;
- while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry))
+ schedule_timeout_uninterruptible(1);
xdc_busy = 0;
return (success);
}
@@ -633,14 +632,12 @@ static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
for (i = 0; i < XD_MAXDRIVES; i++) {
xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
if (!xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT*8)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep_interruptible(XD_INIT_DISK_DELAY);
init_drive(count);
count++;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep_interruptible(XD_INIT_DISK_DELAY);
}
}
return (count);
@@ -761,8 +758,7 @@ static void __init xd_wd_init_controller (unsigned int address)
outb(0,XD_RESET); /* reset the controller */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep(XD_INIT_DISK_DELAY);
}
static void __init xd_wd_init_drive (u_char drive)
@@ -936,8 +932,7 @@ If you need non-standard settings use the xd=... command */
xd_maxsectors = 0x01;
outb(0,XD_RESET); /* reset the controller */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(XD_INIT_DISK_DELAY);
+ msleep(XD_INIT_DISK_DELAY);
}
static void __init xd_xebec_init_drive (u_char drive)
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 007f6a662439..bb5e8d665a2a 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -296,7 +296,7 @@ z2_open( struct inode *inode, struct file *filp )
return 0;
err_out_kfree:
- kfree( z2ram_map );
+ kfree(z2ram_map);
err_out:
return rc;
}
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 543f93e0f23f..b9fbe6e7f9ae 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
-config BT_HCIUART_BCSP_TXCRC
- bool "Transmit CRC with every BCSP packet"
- depends on BT_HCIUART_BCSP
- help
- If you say Y here, a 16-bit CRC checksum will be transmitted along with
- every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
- This increases reliability, but slightly reduces efficiency.
-
config BT_HCIBCM203X
tristate "HCI BCM203x USB driver"
depends on USB
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index c42d7e6ac1c5..1e9db0156ea7 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -158,7 +158,7 @@ static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
if (err) {
BT_ERR("%s bulk tx submit failed urb %p err %d",
bfusb->hdev->name, urb, err);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
usb_free_urb(urb);
} else
atomic_inc(&bfusb->pending_tx);
@@ -212,7 +212,7 @@ static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
read_lock(&bfusb->lock);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
skb_queue_tail(&bfusb->completed_q, skb);
bfusb_tx_wakeup(bfusb);
@@ -253,7 +253,7 @@ static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
if (err) {
BT_ERR("%s bulk rx submit failed urb %p err %d",
bfusb->hdev->name, urb, err);
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
kfree_skb(skb);
usb_free_urb(urb);
}
@@ -330,7 +330,7 @@ static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *
}
skb->dev = (void *) bfusb->hdev;
- skb->pkt_type = pkt_type;
+ bt_cb(skb)->pkt_type = pkt_type;
bfusb->reassembly = skb;
} else {
@@ -398,7 +398,7 @@ static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
buf += len;
}
- skb_unlink(skb);
+ skb_unlink(skb, &bfusb->pending_q);
kfree_skb(skb);
bfusb_rx_submit(bfusb, urb);
@@ -485,7 +485,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
unsigned char buf[3];
int sent = 0, size, count;
- BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len);
+ BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!hdev) {
BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -497,7 +497,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
bfusb = (struct bfusb *) hdev->driver_data;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -510,7 +510,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
count = skb->len;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index bd2ec7e284cc..26fe9c0e1d20 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -270,7 +270,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
if (!(skb = skb_dequeue(&(info->txq))))
break;
- if (skb->pkt_type & 0x80) {
+ if (bt_cb(skb)->pkt_type & 0x80) {
/* Disable RTS */
info->ctrl_reg |= REG_CONTROL_RTS;
outb(info->ctrl_reg, iobase + REG_CONTROL);
@@ -288,13 +288,13 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
/* Mark the buffer as dirty */
clear_bit(ready_bit, &(info->tx_state));
- if (skb->pkt_type & 0x80) {
+ if (bt_cb(skb)->pkt_type & 0x80) {
DECLARE_WAIT_QUEUE_HEAD(wq);
DEFINE_WAIT(wait);
unsigned char baud_reg;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case PKT_BAUD_RATE_460800:
baud_reg = REG_CONTROL_BAUD_RATE_460800;
break;
@@ -410,9 +410,9 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = buf[i];
+ bt_cb(info->rx_skb)->pkt_type = buf[i];
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case 0x00:
/* init packet */
@@ -444,7 +444,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
default:
/* unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
@@ -586,21 +586,21 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
switch (baud) {
case 460800:
cmd[4] = 0x00;
- skb->pkt_type = PKT_BAUD_RATE_460800;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_460800;
break;
case 230400:
cmd[4] = 0x01;
- skb->pkt_type = PKT_BAUD_RATE_230400;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_230400;
break;
case 115200:
cmd[4] = 0x02;
- skb->pkt_type = PKT_BAUD_RATE_115200;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_115200;
break;
case 57600:
/* Fall through... */
default:
cmd[4] = 0x03;
- skb->pkt_type = PKT_BAUD_RATE_57600;
+ bt_cb(skb)->pkt_type = PKT_BAUD_RATE_57600;
break;
}
@@ -680,7 +680,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
info = (bluecard_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -693,7 +693,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
bluecard_write_wakeup(info);
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 2771c861f185..0db0400519c9 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -105,7 +105,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
hci_recv_frame(skb);
}
break;
@@ -117,7 +117,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_SCODATA_PKT;
+ bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
hci_recv_frame(skb);
}
break;
@@ -129,7 +129,7 @@ static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int c
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *) data->hdev;
- skb->pkt_type = HCI_VENDOR_PKT;
+ bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
hci_recv_frame(skb);
}
break;
@@ -190,7 +190,7 @@ static int bpa10x_recv_event(struct bpa10x_data *data, unsigned char *buf, int s
}
skb->dev = (void *) data->hdev;
- skb->pkt_type = pkt_type;
+ bt_cb(skb)->pkt_type = pkt_type;
memcpy(skb_put(skb, size), buf, size);
@@ -307,7 +307,8 @@ unlock:
read_unlock(&data->lock);
}
-static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe, size_t size, int flags, void *data)
+static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe,
+ size_t size, gfp_t flags, void *data)
{
struct urb *urb;
struct usb_ctrlrequest *cr;
@@ -367,11 +368,8 @@ static inline void bpa10x_free_urb(struct urb *urb)
if (!urb)
return;
- if (urb->setup_packet)
- kfree(urb->setup_packet);
-
- if (urb->transfer_buffer)
- kfree(urb->transfer_buffer);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
usb_free_urb(urb);
}
@@ -490,7 +488,7 @@ static int bpa10x_send_frame(struct sk_buff *skb)
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
struct bpa10x_data *data;
- BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len);
+ BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
if (!hdev) {
BT_ERR("Frame for unknown HCI device");
@@ -503,9 +501,9 @@ static int bpa10x_send_frame(struct sk_buff *skb)
data = hdev->driver_data;
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
skb_queue_tail(&data->cmd_queue, skb);
@@ -552,6 +550,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (ignore)
return -ENODEV;
+ if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
+ return -ENODEV;
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate data structure");
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index adf1750ea58d..2e0338d80f32 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -259,11 +259,11 @@ static void bt3c_receive(bt3c_info_t *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = inb(iobase + DATA_L);
+ bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L);
inb(iobase + DATA_H);
- //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);
+ //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@@ -282,7 +282,7 @@ static void bt3c_receive(bt3c_info_t *info)
default:
/* Unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
@@ -439,7 +439,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
info = (bt3c_info_t *) (hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -452,7 +452,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
spin_lock_irqsave(&(info->lock), flags);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index e4c59fdc0e12..89486ea7a021 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -211,9 +211,9 @@ static void btuart_receive(btuart_info_t *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type = inb(iobase + UART_RX);
+ bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@@ -232,7 +232,7 @@ static void btuart_receive(btuart_info_t *info)
default:
/* Unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
@@ -447,7 +447,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
info = (btuart_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -460,7 +460,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
};
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&(info->txq), skb);
btuart_write_wakeup(info);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index e39868c3da48..84c1f8839422 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -251,7 +251,7 @@ static void dtl1_receive(dtl1_info_t *info)
info->rx_count = nsh->len + (nsh->len & 0x0001);
break;
case RECV_WAIT_DATA:
- info->rx_skb->pkt_type = nsh->type;
+ bt_cb(info->rx_skb)->pkt_type = nsh->type;
/* remove PAD byte if it exists */
if (nsh->len & 0x0001) {
@@ -262,7 +262,7 @@ static void dtl1_receive(dtl1_info_t *info)
/* remove NSH */
skb_pull(info->rx_skb, NSHL);
- switch (info->rx_skb->pkt_type) {
+ switch (bt_cb(info->rx_skb)->pkt_type) {
case 0x80:
/* control data for the Nokia Card */
dtl1_control(info, info->rx_skb);
@@ -272,12 +272,12 @@ static void dtl1_receive(dtl1_info_t *info)
case 0x84:
/* send frame to the HCI layer */
info->rx_skb->dev = (void *) info->hdev;
- info->rx_skb->pkt_type &= 0x0f;
+ bt_cb(info->rx_skb)->pkt_type &= 0x0f;
hci_recv_frame(info->rx_skb);
break;
default:
/* unknown packet */
- BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
kfree_skb(info->rx_skb);
break;
}
@@ -410,7 +410,7 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)
info = (dtl1_info_t *)(hdev->driver_data);
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
nsh.type = 0x81;
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index c0ed213fc857..0a4761415ac3 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -1,35 +1,27 @@
-/*
- BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
- Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
- Based on
- hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
- ABCSP by Carl Orsborn <cjo@csr.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $
+ *
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2002-2003 Fabrizio Gennari <fabrizio.gennari@philips.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.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
+ *
*/
-#define VERSION "0.2"
-
#include <linux/config.h>
#include <linux/module.h>
@@ -52,18 +44,56 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+
#include "hci_uart.h"
-#include "hci_bcsp.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
+#define VERSION "0.3"
+
+static int txcrc = 1;
static int hciextn = 1;
+#define BCSP_TXWINSIZE 4
+
+#define BCSP_ACK_PKT 0x05
+#define BCSP_LE_PKT 0x06
+
+struct bcsp_struct {
+ struct sk_buff_head unack; /* Unack'ed packets queue */
+ struct sk_buff_head rel; /* Reliable packets queue */
+ struct sk_buff_head unrel; /* Unreliable packets queue */
+
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+ u8 rxseq_txack; /* rxseq == txack. */
+ u8 rxack; /* Last packet sent by us that the peer ack'ed */
+ struct timer_list tbcsp;
+
+ enum {
+ BCSP_W4_PKT_DELIMITER,
+ BCSP_W4_PKT_START,
+ BCSP_W4_BCSP_HDR,
+ BCSP_W4_DATA,
+ BCSP_W4_CRC
+ } rx_state;
+
+ enum {
+ BCSP_ESCSTATE_NOESC,
+ BCSP_ESCSTATE_ESC
+ } rx_esc_state;
+
+ u8 use_crc;
+ u16 message_crc;
+ u8 txack_req; /* Do we need to send ack's to the peer? */
+
+ /* Reliable packet sequence number - used to assign seq to each rel pkt. */
+ u8 msgq_txseq;
+};
+
/* ---- BCSP CRC calculation ---- */
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
@@ -113,6 +143,7 @@ static u16 bcsp_crc_reverse(u16 crc)
rev |= (crc & 1);
crc = crc >> 1;
}
+
return (rev);
}
@@ -121,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc)
static void bcsp_slip_msgdelim(struct sk_buff *skb)
{
const char pkt_delim = 0xc0;
+
memcpy(skb_put(skb, 1), &pkt_delim, 1);
}
@@ -151,7 +183,7 @@ static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
return 0;
}
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&bcsp->rel, skb);
@@ -175,11 +207,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
{
struct sk_buff *nskb;
u8 hdr[4], chan;
- int rel, i;
-
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
-#endif
+ int rel, i;
switch (pkt_type) {
case HCI_ACLDATA_PKT:
@@ -229,7 +258,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
if (!nskb)
return NULL;
- nskb->pkt_type = pkt_type;
+ bt_cb(nskb)->pkt_type = pkt_type;
bcsp_slip_msgdelim(nskb);
@@ -242,9 +271,9 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- hdr[0] |= 0x40;
-#endif
+
+ if (bcsp->use_crc)
+ hdr[0] |= 0x40;
hdr[1] = ((len << 4) & 0xff) | chan;
hdr[2] = len >> 4;
@@ -253,25 +282,25 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* Put BCSP header */
for (i = 0; i < 4; i++) {
bcsp_slip_one_byte(nskb, hdr[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
-#endif
+
+ if (bcsp->use_crc)
+ bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
}
/* Put payload */
for (i = 0; i < len; i++) {
bcsp_slip_one_byte(nskb, data[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
- bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
-#endif
+
+ if (bcsp->use_crc)
+ bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
/* Put CRC */
- bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
- bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
- bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
-#endif
+ if (bcsp->use_crc) {
+ bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
+ bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
+ bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
+ }
bcsp_slip_msgdelim(nskb);
return nskb;
@@ -288,7 +317,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
since they have priority */
if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) {
- struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type);
+ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
if (nskb) {
kfree_skb(skb);
return nskb;
@@ -305,7 +334,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
spin_lock_irqsave(&bcsp->unack.lock, flags);
if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
- struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type);
+ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
if (nskb) {
__skb_queue_tail(&bcsp->unack, skb);
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
@@ -319,7 +348,6 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
-
/* We could not send a reliable packet, either because there are
none or because there are too many unack'ed pkts. Did we receive
any packets we have not acknowledged yet ? */
@@ -365,7 +393,7 @@ 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, bcsp->unack.qlen, (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++) {
@@ -376,8 +404,10 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
kfree_skb(skb);
skb = nskb;
}
+
if (bcsp->unack.qlen == 0)
del_timer(&bcsp->tbcsp);
+
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
if (i != pkts_to_be_removed)
@@ -403,7 +433,7 @@ static void bcsp_handle_le_pkt(struct hci_uart *hu)
if (!nskb)
return;
memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4);
- nskb->pkt_type = BCSP_LE_PKT;
+ bt_cb(nskb)->pkt_type = BCSP_LE_PKT;
skb_queue_head(&bcsp->unrel, nskb);
hci_uart_tx_wakeup(hu);
@@ -485,14 +515,14 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
bcsp_pkt_cull(bcsp);
if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&
bcsp->rx_skb->data[0] & 0x80) {
- bcsp->rx_skb->pkt_type = HCI_ACLDATA_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&
bcsp->rx_skb->data[0] & 0x80) {
- bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {
- bcsp->rx_skb->pkt_type = HCI_SCODATA_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_SCODATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
!(bcsp->rx_skb->data[0] & 0x80)) {
@@ -514,7 +544,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
hdr.evt = 0xff;
hdr.plen = bcsp->rx_skb->len;
memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
- bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;
+ bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
hci_recv_frame(bcsp->rx_skb);
} else {
@@ -532,6 +562,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
hci_recv_frame(bcsp->rx_skb);
}
+
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
bcsp->rx_skb = NULL;
}
@@ -600,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
BT_ERR ("Checksum failed: computed %04x received %04x",
bcsp_crc_reverse(bcsp->message_crc),
- (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
- bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
+ (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
+ bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
kfree_skb(bcsp->rx_skb);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
@@ -635,7 +666,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
bcsp->rx_count = 4;
bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
BCSP_CRC_INIT(bcsp->message_crc);
-
+
/* Do not increment ptr or decrement count
* Allocate packet. Max len of a BCSP pkt=
* 0xFFF (payload) +4 (header) +2 (crc) */
@@ -700,6 +731,9 @@ static int bcsp_open(struct hci_uart *hu)
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
+ if (txcrc)
+ bcsp->use_crc = 1;
+
return 0;
}
@@ -720,18 +754,19 @@ static int bcsp_close(struct hci_uart *hu)
}
static struct hci_uart_proto bcsp = {
- .id = HCI_UART_BCSP,
- .open = bcsp_open,
- .close = bcsp_close,
- .enqueue = bcsp_enqueue,
- .dequeue = bcsp_dequeue,
- .recv = bcsp_recv,
- .flush = bcsp_flush
+ .id = HCI_UART_BCSP,
+ .open = bcsp_open,
+ .close = bcsp_close,
+ .enqueue = bcsp_enqueue,
+ .dequeue = bcsp_dequeue,
+ .recv = bcsp_recv,
+ .flush = bcsp_flush
};
int bcsp_init(void)
{
int err = hci_uart_register_proto(&bcsp);
+
if (!err)
BT_INFO("HCI BCSP protocol initialized");
else
@@ -745,5 +780,8 @@ int bcsp_deinit(void)
return hci_uart_unregister_proto(&bcsp);
}
+module_param(txcrc, bool, 0644);
+MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
+
module_param(hciextn, bool, 0644);
MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
diff --git a/drivers/bluetooth/hci_bcsp.h b/drivers/bluetooth/hci_bcsp.h
deleted file mode 100644
index a2b3bb92274b..000000000000
--- a/drivers/bluetooth/hci_bcsp.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
- Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
- Based on
- hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
- ABCSP by Carl Orsborn <cjo@csr.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_bcsp.h,v 1.2 2002/09/26 05:05:14 maxk Exp $
- */
-
-#ifndef __HCI_BCSP_H__
-#define __HCI_BCSP_H__
-
-#define BCSP_TXWINSIZE 4
-
-#define BCSP_ACK_PKT 0x05
-#define BCSP_LE_PKT 0x06
-
-struct bcsp_struct {
- struct sk_buff_head unack; /* Unack'ed packets queue */
- struct sk_buff_head rel; /* Reliable packets queue */
- struct sk_buff_head unrel; /* Unreliable packets queue */
-
- unsigned long rx_count;
- struct sk_buff *rx_skb;
- u8 rxseq_txack; /* rxseq == txack. */
- u8 rxack; /* Last packet sent by us that the peer ack'ed */
- struct timer_list tbcsp;
-
- enum {
- BCSP_W4_PKT_DELIMITER,
- BCSP_W4_PKT_START,
- BCSP_W4_BCSP_HDR,
- BCSP_W4_DATA,
- BCSP_W4_CRC
- } rx_state;
-
- enum {
- BCSP_ESCSTATE_NOESC,
- BCSP_ESCSTATE_ESC
- } rx_esc_state;
-
- u16 message_crc;
- u8 txack_req; /* Do we need to send ack's to the peer? */
-
- /* Reliable packet sequence number - used to assign seq to each rel pkt. */
- u8 msgq_txseq;
-};
-
-#endif /* __HCI_BCSP_H__ */
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index ade94a57bb11..12e369a66fc2 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -1,33 +1,27 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI UART(H4) protocol.
*
- * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.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
+ *
*/
-#define VERSION "1.2"
#include <linux/config.h>
#include <linux/module.h>
@@ -51,26 +45,41 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+
#include "hci_uart.h"
-#include "hci_h4.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
+#define VERSION "1.2"
+
+struct h4_struct {
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+ struct sk_buff_head txq;
+};
+
+/* H4 receiver States */
+#define H4_W4_PACKET_TYPE 0
+#define H4_W4_EVENT_HDR 1
+#define H4_W4_ACL_HDR 2
+#define H4_W4_SCO_HDR 3
+#define H4_W4_DATA 4
+
/* Initialize protocol */
static int h4_open(struct hci_uart *hu)
{
struct h4_struct *h4;
-
+
BT_DBG("hu %p", hu);
-
+
h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
if (!h4)
return -ENOMEM;
+
memset(h4, 0, sizeof(*h4));
skb_queue_head_init(&h4->txq);
@@ -85,7 +94,9 @@ static int h4_flush(struct hci_uart *hu)
struct h4_struct *h4 = hu->priv;
BT_DBG("hu %p", hu);
+
skb_queue_purge(&h4->txq);
+
return 0;
}
@@ -93,16 +104,19 @@ static int h4_flush(struct hci_uart *hu)
static int h4_close(struct hci_uart *hu)
{
struct h4_struct *h4 = hu->priv;
+
hu->priv = NULL;
BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
+
if (h4->rx_skb)
kfree_skb(h4->rx_skb);
hu->priv = NULL;
kfree(h4);
+
return 0;
}
@@ -114,8 +128,9 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
- memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&h4->txq, skb);
+
return 0;
}
@@ -124,8 +139,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
register int room = skb_tailroom(h4->rx_skb);
BT_DBG("len %d room %d", len, room);
+
if (!len) {
- BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
hci_recv_frame(h4->rx_skb);
} else if (len > room) {
BT_ERR("Data length is too large");
@@ -139,6 +154,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
h4->rx_count = 0;
+
return 0;
}
@@ -169,8 +185,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
case H4_W4_DATA:
BT_DBG("Complete data");
- BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
-
hci_recv_frame(h4->rx_skb);
h4->rx_state = H4_W4_PACKET_TYPE;
@@ -233,6 +247,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
ptr++; count--;
continue;
};
+
ptr++; count--;
/* Allocate packet */
@@ -243,9 +258,11 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
h4->rx_count = 0;
return 0;
}
+
h4->rx_skb->dev = (void *) hu->hdev;
- h4->rx_skb->pkt_type = type;
+ bt_cb(h4->rx_skb)->pkt_type = type;
}
+
return count;
}
@@ -256,23 +273,24 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
}
static struct hci_uart_proto h4p = {
- .id = HCI_UART_H4,
- .open = h4_open,
- .close = h4_close,
- .recv = h4_recv,
- .enqueue = h4_enqueue,
- .dequeue = h4_dequeue,
- .flush = h4_flush,
+ .id = HCI_UART_H4,
+ .open = h4_open,
+ .close = h4_close,
+ .recv = h4_recv,
+ .enqueue = h4_enqueue,
+ .dequeue = h4_dequeue,
+ .flush = h4_flush,
};
-
+
int h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
+
if (!err)
BT_INFO("HCI H4 protocol initialized");
else
BT_ERR("HCI H4 protocol registration failed");
-
+
return err;
}
diff --git a/drivers/bluetooth/hci_h4.h b/drivers/bluetooth/hci_h4.h
deleted file mode 100644
index b95ff54bfd47..000000000000
--- a/drivers/bluetooth/hci_h4.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
- */
-
-#ifdef __KERNEL__
-struct h4_struct {
- unsigned long rx_state;
- unsigned long rx_count;
- struct sk_buff *rx_skb;
- struct sk_buff_head txq;
-};
-
-/* H4 receiver States */
-#define H4_W4_PACKET_TYPE 0
-#define H4_W4_EVENT_HDR 1
-#define H4_W4_ACL_HDR 2
-#define H4_W4_SCO_HDR 3
-#define H4_W4_DATA 4
-
-#endif /* __KERNEL__ */
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index f766bc22c6bb..4a775f6ea390 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -1,33 +1,27 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI UART driver.
*
- * $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.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
+ *
*/
-#define VERSION "2.1"
#include <linux/config.h>
#include <linux/module.h>
@@ -57,10 +51,10 @@
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
+#define VERSION "2.2"
+
static int reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
@@ -74,6 +68,7 @@ int hci_uart_register_proto(struct hci_uart_proto *p)
return -EEXIST;
hup[p->id] = p;
+
return 0;
}
@@ -86,6 +81,7 @@ int hci_uart_unregister_proto(struct hci_uart_proto *p)
return -EINVAL;
hup[p->id] = NULL;
+
return 0;
}
@@ -93,13 +89,14 @@ static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
{
if (id >= HCI_UART_MAX_PROTO)
return NULL;
+
return hup[id];
}
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
{
struct hci_dev *hdev = hu->hdev;
-
+
/* Update HCI stat counters */
switch (pkt_type) {
case HCI_COMMAND_PKT:
@@ -119,10 +116,12 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{
struct sk_buff *skb = hu->tx_skb;
+
if (!skb)
skb = hu->proto->dequeue(hu);
else
hu->tx_skb = NULL;
+
return skb;
}
@@ -131,7 +130,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
struct tty_struct *tty = hu->tty;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
-
+
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
return 0;
@@ -144,7 +143,7 @@ restart:
while ((skb = hci_uart_dequeue(hu))) {
int len;
-
+
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
len = tty->driver->write(tty, skb->data, skb->len);
hdev->stat.byte_tx += len;
@@ -154,11 +153,11 @@ restart:
hu->tx_skb = skb;
break;
}
-
- hci_uart_tx_complete(hu, skb->pkt_type);
+
+ hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
kfree_skb(skb);
- }
-
+ }
+
if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
goto restart;
@@ -175,6 +174,7 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Nothing to do for UART driver */
set_bit(HCI_RUNNING, &hdev->flags);
+
return 0;
}
@@ -231,11 +231,12 @@ static int hci_uart_send_frame(struct sk_buff *skb)
hu = (struct hci_uart *) hdev->driver_data;
tty = hu->tty;
- BT_DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len);
+ BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
hu->proto->enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
+
return 0;
}
@@ -243,7 +244,8 @@ static void hci_uart_destruct(struct hci_dev *hdev)
{
struct hci_uart *hu;
- if (!hdev) return;
+ if (!hdev)
+ return;
BT_DBG("%s", hdev->name);
@@ -274,6 +276,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
BT_ERR("Can't allocate controll structure");
return -ENFILE;
}
+
memset(hu, 0, sizeof(struct hci_uart));
tty->disc_data = hu;
@@ -282,8 +285,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)
spin_lock_init(&hu->rx_lock);
/* Flush any pending characters in the driver and line discipline. */
+
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
open path is before the ldisc is referencable */
+
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
@@ -374,13 +379,13 @@ static int hci_uart_tty_room (struct tty_struct *tty)
static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
{
struct hci_uart *hu = (void *)tty->disc_data;
-
+
if (!hu || tty != hu->tty)
return;
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
return;
-
+
spin_lock(&hu->rx_lock);
hu->proto->recv(hu, (void *) data, count);
hu->hdev->stat.byte_rx += count;
@@ -431,8 +436,8 @@ static int hci_uart_register_dev(struct hci_uart *hu)
static int hci_uart_set_proto(struct hci_uart *hu, int id)
{
struct hci_uart_proto *p;
- int err;
-
+ int err;
+
p = hci_uart_get_proto(id);
if (!p)
return -EPROTONOSUPPORT;
@@ -448,6 +453,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
p->close(hu);
return err;
}
+
return 0;
}
@@ -465,7 +471,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
* Return Value: Command dependent
*/
static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct hci_uart *hu = (void *)tty->disc_data;
int err = 0;
@@ -485,14 +491,14 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return err;
}
tty->low_latency = 1;
- } else
+ } else
return -EBUSY;
case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->proto->id;
return -EUNATCH;
-
+
default:
err = n_tty_ioctl(tty, file, cmd, arg);
break;
@@ -504,28 +510,24 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
/*
* We don't provide read/write/poll interface for user space.
*/
-static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr)
+static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
+ unsigned char __user *buf, size_t nr)
{
return 0;
}
-static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
+
+static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *data, size_t count)
{
return 0;
}
-static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
+
+static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
+ struct file *filp, poll_table *wait)
{
return 0;
}
-#ifdef CONFIG_BT_HCIUART_H4
-int h4_init(void);
-int h4_deinit(void);
-#endif
-#ifdef CONFIG_BT_HCIUART_BCSP
-int bcsp_init(void);
-int bcsp_deinit(void);
-#endif
-
static int __init hci_uart_init(void)
{
static struct tty_ldisc hci_uart_ldisc;
@@ -536,18 +538,18 @@ static int __init hci_uart_init(void)
/* Register the tty discipline */
memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
- hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
- hci_uart_ldisc.name = "n_hci";
- hci_uart_ldisc.open = hci_uart_tty_open;
- hci_uart_ldisc.close = hci_uart_tty_close;
- hci_uart_ldisc.read = hci_uart_tty_read;
- hci_uart_ldisc.write = hci_uart_tty_write;
- hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
- hci_uart_ldisc.poll = hci_uart_tty_poll;
- hci_uart_ldisc.receive_room= hci_uart_tty_room;
- hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
- hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
- hci_uart_ldisc.owner = THIS_MODULE;
+ hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
+ hci_uart_ldisc.name = "n_hci";
+ hci_uart_ldisc.open = hci_uart_tty_open;
+ hci_uart_ldisc.close = hci_uart_tty_close;
+ hci_uart_ldisc.read = hci_uart_tty_read;
+ hci_uart_ldisc.write = hci_uart_tty_write;
+ hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
+ hci_uart_ldisc.poll = hci_uart_tty_poll;
+ hci_uart_ldisc.receive_room = hci_uart_tty_room;
+ hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
+ hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
+ hci_uart_ldisc.owner = THIS_MODULE;
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
BT_ERR("HCI line discipline registration failed. (%d)", err);
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 0a57d72790ec..b250e6789dee 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -1,32 +1,29 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * $Id: hci_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
+ *
+ * Bluetooth HCI UART driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.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 N_HCI
+#ifndef N_HCI
#define N_HCI 15
#endif
@@ -42,7 +39,6 @@
#define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3
-#ifdef __KERNEL__
struct hci_uart;
struct hci_uart_proto {
@@ -56,27 +52,35 @@ struct hci_uart_proto {
};
struct hci_uart {
- struct tty_struct *tty;
- struct hci_dev *hdev;
- unsigned long flags;
+ struct tty_struct *tty;
+ struct hci_dev *hdev;
+ unsigned long flags;
- struct hci_uart_proto *proto;
- void *priv;
-
- struct sk_buff *tx_skb;
- unsigned long tx_state;
- spinlock_t rx_lock;
+ struct hci_uart_proto *proto;
+ void *priv;
+
+ struct sk_buff *tx_skb;
+ unsigned long tx_state;
+ spinlock_t rx_lock;
};
/* HCI_UART flag bits */
-#define HCI_UART_PROTO_SET 0
+#define HCI_UART_PROTO_SET 0
/* TX states */
-#define HCI_UART_SENDING 1
-#define HCI_UART_TX_WAKEUP 2
+#define HCI_UART_SENDING 1
+#define HCI_UART_TX_WAKEUP 2
int hci_uart_register_proto(struct hci_uart_proto *p);
int hci_uart_unregister_proto(struct hci_uart_proto *p);
int hci_uart_tx_wakeup(struct hci_uart *hu);
-#endif /* __KERNEL__ */
+#ifdef CONFIG_BT_HCIUART_H4
+int h4_init(void);
+int h4_deinit(void);
+#endif
+
+#ifdef CONFIG_BT_HCIUART_BCSP
+int bcsp_init(void);
+int bcsp_deinit(void);
+#endif
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index b120ecf7b8c9..6756cb20b753 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -57,8 +57,6 @@
#ifndef CONFIG_BT_HCIUSB_DEBUG
#undef BT_DBG
#define BT_DBG(D...)
-#undef BT_DMP
-#define BT_DMP(D...)
#endif
#ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
@@ -67,13 +65,15 @@
#endif
static int ignore = 0;
+static int ignore_csr = 0;
+static int ignore_sniffer = 0;
static int reset = 0;
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 2;
#endif
-#define VERSION "2.8"
+#define VERSION "2.9"
static struct usb_driver hci_usb_driver;
@@ -100,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = {
MODULE_DEVICE_TABLE (usb, bluetooth_ids);
static struct usb_device_id blacklist_ids[] = {
+ /* CSR BlueCore devices */
+ { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
+
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
@@ -110,6 +113,9 @@ static struct usb_device_id blacklist_ids[] = {
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
+ /* Kensington Bluetooth USB adapter */
+ { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
+
/* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
@@ -126,7 +132,7 @@ static struct usb_device_id blacklist_ids[] = {
{ } /* Terminating entry */
};
-static struct _urb *_urb_alloc(int isoc, int gfp)
+static struct _urb *_urb_alloc(int isoc, gfp_t gfp)
{
struct _urb *_urb = kmalloc(sizeof(struct _urb) +
sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
@@ -387,10 +393,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
urb = &_urb->urb;
BT_DBG("%s freeing _urb %p type %d urb %p",
husb->hdev->name, _urb, _urb->type, urb);
- if (urb->setup_packet)
- kfree(urb->setup_packet);
- if (urb->transfer_buffer)
- kfree(urb->transfer_buffer);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
_urb_free(_urb);
}
@@ -444,7 +448,7 @@ static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct usb_ctrlrequest *dr;
struct urb *urb;
@@ -452,7 +456,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
_urb = _urb_alloc(0, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
if (!dr) {
@@ -480,7 +484,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct urb *urb;
int pipe;
@@ -488,7 +492,7 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
_urb = _urb_alloc(0, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
}
urb = &_urb->urb;
@@ -506,14 +510,14 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
#ifdef CONFIG_BT_HCIUSB_SCO
static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
{
- struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+ struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
struct urb *urb;
if (!_urb) {
_urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
if (!_urb)
return -ENOMEM;
- _urb->type = skb->pkt_type;
+ _urb->type = bt_cb(skb)->pkt_type;
}
BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
@@ -602,11 +606,11 @@ static int hci_usb_send_frame(struct sk_buff *skb)
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len);
+ BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
husb = (struct hci_usb *) hdev->driver_data;
- switch (skb->pkt_type) {
+ switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@@ -628,7 +632,7 @@ static int hci_usb_send_frame(struct sk_buff *skb)
read_lock(&husb->completion_lock);
- skb_queue_tail(__transmit_q(husb, skb->pkt_type), skb);
+ skb_queue_tail(__transmit_q(husb, bt_cb(skb)->pkt_type), skb);
hci_usb_tx_wakeup(husb);
read_unlock(&husb->completion_lock);
@@ -683,7 +687,7 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int c
return -ENOMEM;
}
skb->dev = (void *) husb->hdev;
- skb->pkt_type = type;
+ bt_cb(skb)->pkt_type = type;
__reassembly(husb, type) = skb;
@@ -703,6 +707,7 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int c
if (!scb->expect) {
/* Complete frame */
__reassembly(husb, type) = NULL;
+ bt_cb(skb)->pkt_type = type;
hci_recv_frame(skb);
}
@@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (ignore || id->driver_info & HCI_IGNORE)
return -ENODEV;
+ if (ignore_csr && id->driver_info & HCI_CSR)
+ return -ENODEV;
+
+ if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
+ return -ENODEV;
+
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
@@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+module_param(ignore_csr, bool, 0644);
+MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
+
+module_param(ignore_sniffer, bool, 0644);
+MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
+
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 29936b43d4f8..37100a6ea1a8 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -31,9 +31,10 @@
#define HCI_IGNORE 0x01
#define HCI_RESET 0x02
#define HCI_DIGIANSWER 0x04
-#define HCI_SNIFFER 0x08
-#define HCI_BROKEN_ISOC 0x10
+#define HCI_CSR 0x08
+#define HCI_SNIFFER 0x10
#define HCI_BCM92035 0x20
+#define HCI_BROKEN_ISOC 0x40
#define HCI_MAX_IFACE_NUM 3
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index f9b956fb2b8b..52cbd45c308f 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -1,229 +1,220 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
/*
- * Bluetooth HCI virtual device driver.
*
- * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $
+ * Bluetooth virtual HCI driver
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.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
+ *
*/
-#define VERSION "1.1"
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
+#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/miscdevice.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#include "hci_vhci.h"
-/* HCI device part */
+#ifndef CONFIG_BT_HCIVHCI_DEBUG
+#undef BT_DBG
+#define BT_DBG(D...)
+#endif
+
+#define VERSION "1.2"
+
+static int minor = MISC_DYNAMIC_MINOR;
+
+struct vhci_data {
+ struct hci_dev *hdev;
+
+ unsigned long flags;
+
+ wait_queue_head_t read_wait;
+ struct sk_buff_head readq;
+
+ struct fasync_struct *fasync;
+};
-static int hci_vhci_open(struct hci_dev *hdev)
+#define VHCI_FASYNC 0x0010
+
+static struct miscdevice vhci_miscdev;
+
+static int vhci_open_dev(struct hci_dev *hdev)
{
set_bit(HCI_RUNNING, &hdev->flags);
- return 0;
-}
-static int hci_vhci_flush(struct hci_dev *hdev)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
- skb_queue_purge(&hci_vhci->readq);
return 0;
}
-static int hci_vhci_close(struct hci_dev *hdev)
+static int vhci_close_dev(struct hci_dev *hdev)
{
+ struct vhci_data *vhci = hdev->driver_data;
+
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
- hci_vhci_flush(hdev);
+ skb_queue_purge(&vhci->readq);
+
return 0;
}
-static void hci_vhci_destruct(struct hci_dev *hdev)
+static int vhci_flush(struct hci_dev *hdev)
{
- struct hci_vhci_struct *vhci;
+ struct vhci_data *vhci = hdev->driver_data;
- if (!hdev) return;
+ skb_queue_purge(&vhci->readq);
- vhci = (struct hci_vhci_struct *) hdev->driver_data;
- kfree(vhci);
+ return 0;
}
-static int hci_vhci_send_frame(struct sk_buff *skb)
+static int vhci_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
- struct hci_vhci_struct *hci_vhci;
+ struct vhci_data *vhci;
if (!hdev) {
- BT_ERR("Frame for uknown device (hdev=NULL)");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
+ vhci = hdev->driver_data;
+
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+ skb_queue_tail(&vhci->readq, skb);
- memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
- skb_queue_tail(&hci_vhci->readq, skb);
+ if (vhci->flags & VHCI_FASYNC)
+ kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
- if (hci_vhci->flags & VHCI_FASYNC)
- kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN);
- wake_up_interruptible(&hci_vhci->read_wait);
+ wake_up_interruptible(&vhci->read_wait);
return 0;
}
-/* Character device part */
-
-/* Poll */
-static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
-
- poll_wait(file, &hci_vhci->read_wait, wait);
-
- if (!skb_queue_empty(&hci_vhci->readq))
- return POLLIN | POLLRDNORM;
-
- return POLLOUT | POLLWRNORM;
+static void vhci_destruct(struct hci_dev *hdev)
+{
+ kfree(hdev->driver_data);
}
-/* Get packet from user space buffer(already verified) */
-static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char __user *buf, size_t count)
+static inline ssize_t vhci_get_user(struct vhci_data *vhci,
+ const char __user *buf, size_t count)
{
struct sk_buff *skb;
if (count > HCI_MAX_FRAME_SIZE)
return -EINVAL;
- if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
+ skb = bt_skb_alloc(count, GFP_KERNEL);
+ if (!skb)
return -ENOMEM;
-
+
if (copy_from_user(skb_put(skb, count), buf, count)) {
kfree_skb(skb);
return -EFAULT;
}
- skb->dev = (void *) hci_vhci->hdev;
- skb->pkt_type = *((__u8 *) skb->data);
+ skb->dev = (void *) vhci->hdev;
+ bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
hci_recv_frame(skb);
return count;
-}
-
-/* Write */
-static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf,
- size_t count, loff_t *pos)
-{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
-
- if (!access_ok(VERIFY_READ, buf, count))
- return -EFAULT;
-
- return hci_vhci_get_user(hci_vhci, buf, count);
}
-/* Put packet to user space buffer(already verified) */
-static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci,
- struct sk_buff *skb, char __user *buf,
- int count)
+static inline ssize_t vhci_put_user(struct vhci_data *vhci,
+ struct sk_buff *skb, char __user *buf, int count)
{
- int len = count, total = 0;
char __user *ptr = buf;
+ int len, total = 0;
+
+ len = min_t(unsigned int, skb->len, count);
- len = min_t(unsigned int, skb->len, len);
if (copy_to_user(ptr, skb->data, len))
return -EFAULT;
+
total += len;
- hci_vhci->hdev->stat.byte_tx += len;
- switch (skb->pkt_type) {
- case HCI_COMMAND_PKT:
- hci_vhci->hdev->stat.cmd_tx++;
- break;
+ vhci->hdev->stat.byte_tx += len;
- case HCI_ACLDATA_PKT:
- hci_vhci->hdev->stat.acl_tx++;
- break;
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ vhci->hdev->stat.cmd_tx++;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ vhci->hdev->stat.acl_tx++;
+ break;
- case HCI_SCODATA_PKT:
- hci_vhci->hdev->stat.cmd_tx++;
- break;
+ case HCI_SCODATA_PKT:
+ vhci->hdev->stat.cmd_tx++;
+ break;
};
return total;
}
-/* Read */
-static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
+static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
DECLARE_WAITQUEUE(wait, current);
+ struct vhci_data *vhci = file->private_data;
struct sk_buff *skb;
ssize_t ret = 0;
- add_wait_queue(&hci_vhci->read_wait, &wait);
+ add_wait_queue(&vhci->read_wait, &wait);
while (count) {
set_current_state(TASK_INTERRUPTIBLE);
- /* Read frames from device queue */
- if (!(skb = skb_dequeue(&hci_vhci->readq))) {
+ skb = skb_dequeue(&vhci->readq);
+ if (!skb) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
+
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
- /* Nothing to read, let's sleep */
schedule();
continue;
}
if (access_ok(VERIFY_WRITE, buf, count))
- ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
+ ret = vhci_put_user(vhci, skb, buf, count);
else
ret = -EFAULT;
@@ -231,84 +222,90 @@ static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t c
break;
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&hci_vhci->read_wait, &wait);
+ remove_wait_queue(&vhci->read_wait, &wait);
return ret;
}
-static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
+static ssize_t vhci_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *pos)
{
- return -ESPIPE;
-}
+ struct vhci_data *vhci = file->private_data;
-static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- return -EINVAL;
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ return vhci_get_user(vhci, buf, count);
}
-static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
+static unsigned int vhci_poll(struct file *file, poll_table *wait)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
- int ret;
+ struct vhci_data *vhci = file->private_data;
- if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
- return ret;
-
- if (on)
- hci_vhci->flags |= VHCI_FASYNC;
- else
- hci_vhci->flags &= ~VHCI_FASYNC;
+ poll_wait(file, &vhci->read_wait, wait);
- return 0;
+ if (!skb_queue_empty(&vhci->readq))
+ return POLLIN | POLLRDNORM;
+
+ return POLLOUT | POLLWRNORM;
}
-static int hci_vhci_chr_open(struct inode *inode, struct file * file)
+static int vhci_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct hci_vhci_struct *hci_vhci = NULL;
+ return -EINVAL;
+}
+
+static int vhci_open(struct inode *inode, struct file *file)
+{
+ struct vhci_data *vhci;
struct hci_dev *hdev;
- if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
+ vhci = kmalloc(sizeof(struct vhci_data), GFP_KERNEL);
+ if (!vhci)
return -ENOMEM;
- memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
+ memset(vhci, 0, sizeof(struct vhci_data));
- skb_queue_head_init(&hci_vhci->readq);
- init_waitqueue_head(&hci_vhci->read_wait);
+ skb_queue_head_init(&vhci->readq);
+ init_waitqueue_head(&vhci->read_wait);
- /* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- kfree(hci_vhci);
+ kfree(vhci);
return -ENOMEM;
}
- hci_vhci->hdev = hdev;
+ vhci->hdev = hdev;
hdev->type = HCI_VHCI;
- hdev->driver_data = hci_vhci;
+ hdev->driver_data = vhci;
+ SET_HCIDEV_DEV(hdev, vhci_miscdev.dev);
- hdev->open = hci_vhci_open;
- hdev->close = hci_vhci_close;
- hdev->flush = hci_vhci_flush;
- hdev->send = hci_vhci_send_frame;
- hdev->destruct = hci_vhci_destruct;
+ hdev->open = vhci_open_dev;
+ hdev->close = vhci_close_dev;
+ hdev->flush = vhci_flush;
+ hdev->send = vhci_send_frame;
+ hdev->destruct = vhci_destruct;
hdev->owner = THIS_MODULE;
-
+
if (hci_register_dev(hdev) < 0) {
- kfree(hci_vhci);
+ BT_ERR("Can't register HCI device");
+ kfree(vhci);
hci_free_dev(hdev);
return -EBUSY;
}
- file->private_data = hci_vhci;
- return nonseekable_open(inode, file);
+ file->private_data = vhci;
+
+ return nonseekable_open(inode, file);
}
-static int hci_vhci_chr_close(struct inode *inode, struct file *file)
+static int vhci_release(struct inode *inode, struct file *file)
{
- struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
- struct hci_dev *hdev = hci_vhci->hdev;
+ struct vhci_data *vhci = file->private_data;
+ struct hci_dev *hdev = vhci->hdev;
if (hci_unregister_dev(hdev) < 0) {
BT_ERR("Can't unregister HCI device %s", hdev->name);
@@ -317,48 +314,71 @@ static int hci_vhci_chr_close(struct inode *inode, struct file *file)
hci_free_dev(hdev);
file->private_data = NULL;
+
return 0;
}
-static struct file_operations hci_vhci_fops = {
- .owner = THIS_MODULE,
- .llseek = hci_vhci_chr_lseek,
- .read = hci_vhci_chr_read,
- .write = hci_vhci_chr_write,
- .poll = hci_vhci_chr_poll,
- .ioctl = hci_vhci_chr_ioctl,
- .open = hci_vhci_chr_open,
- .release = hci_vhci_chr_close,
- .fasync = hci_vhci_chr_fasync
+static int vhci_fasync(int fd, struct file *file, int on)
+{
+ struct vhci_data *vhci = file->private_data;
+ int err;
+
+ err = fasync_helper(fd, file, on, &vhci->fasync);
+ if (err < 0)
+ return err;
+
+ if (on)
+ vhci->flags |= VHCI_FASYNC;
+ else
+ vhci->flags &= ~VHCI_FASYNC;
+
+ return 0;
+}
+
+static struct file_operations vhci_fops = {
+ .owner = THIS_MODULE,
+ .llseek = vhci_llseek,
+ .read = vhci_read,
+ .write = vhci_write,
+ .poll = vhci_poll,
+ .ioctl = vhci_ioctl,
+ .open = vhci_open,
+ .release = vhci_release,
+ .fasync = vhci_fasync,
};
-static struct miscdevice hci_vhci_miscdev=
-{
- VHCI_MINOR,
- "hci_vhci",
- &hci_vhci_fops
+static struct miscdevice vhci_miscdev= {
+ .name = "vhci",
+ .fops = &vhci_fops,
};
-static int __init hci_vhci_init(void)
+static int __init vhci_init(void)
{
- BT_INFO("VHCI driver ver %s", VERSION);
+ BT_INFO("Virtual HCI driver ver %s", VERSION);
- if (misc_register(&hci_vhci_miscdev)) {
- BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
+ vhci_miscdev.minor = minor;
+
+ if (misc_register(&vhci_miscdev) < 0) {
+ BT_ERR("Can't register misc device with minor %d", minor);
return -EIO;
}
return 0;
}
-static void hci_vhci_cleanup(void)
+static void __exit vhci_exit(void)
{
- misc_deregister(&hci_vhci_miscdev);
+ if (misc_deregister(&vhci_miscdev) < 0)
+ BT_ERR("Can't unregister misc device with minor %d", minor);
}
-module_init(hci_vhci_init);
-module_exit(hci_vhci_cleanup);
+module_init(vhci_init);
+module_exit(vhci_exit);
+
+module_param(minor, int, 0444);
+MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
-MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_vhci.h b/drivers/bluetooth/hci_vhci.h
deleted file mode 100644
index 53b11f9ef76d..000000000000
--- a/drivers/bluetooth/hci_vhci.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
-
- Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
- 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 OF THIRD PARTY RIGHTS.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL 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.
-
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
- SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_vhci.h,v 1.1.1.1 2002/03/08 21:03:15 maxk Exp $
- */
-
-#ifndef __HCI_VHCI_H
-#define __HCI_VHCI_H
-
-#ifdef __KERNEL__
-
-struct hci_vhci_struct {
- struct hci_dev *hdev;
- __u32 flags;
- wait_queue_head_t read_wait;
- struct sk_buff_head readq;
- struct fasync_struct *fasync;
-};
-
-/* VHCI device flags */
-#define VHCI_FASYNC 0x0010
-
-#endif /* __KERNEL__ */
-
-#define VHCI_DEV "/dev/vhci"
-#define VHCI_MINOR 250
-
-#endif /* __HCI_VHCI_H */
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index 43bf1e5dc38a..ce4a1ce59d6a 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -297,7 +297,7 @@ static char azt_auto_eject = AZT_AUTO_EJECT;
static int AztTimeout, AztTries;
static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static struct timer_list delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(delay_timer, NULL, 0, 0);
static struct azt_DiskInfo DiskInfo;
static struct azt_Toc Toc[MAX_TRACKS];
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index beaa561f2ed8..153960348414 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!q)
return -ENXIO;
+ rq = blk_get_request(q, READ, GFP_KERNEL);
+ if (!rq)
+ return -ENOMEM;
+
cdi->last_sense = 0;
while (nframes) {
@@ -2108,9 +2112,9 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
len = nr * CD_FRAMESIZE_RAW;
- rq = blk_rq_map_user(q, READ, ubuf, len);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
+ ret = blk_rq_map_user(q, rq, ubuf, len);
+ if (ret)
+ break;
memset(rq->cmd, 0, sizeof(rq->cmd));
rq->cmd[0] = GPCMD_READ_CD;
@@ -2132,13 +2136,13 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (rq->bio)
blk_queue_bounce(q, &rq->bio);
- if (blk_execute_rq(q, cdi->disk, rq)) {
+ if (blk_execute_rq(q, cdi->disk, rq, 0)) {
struct request_sense *s = rq->sense;
ret = -EIO;
cdi->last_sense = s->sense_key;
}
- if (blk_rq_unmap_user(rq, bio, len))
+ if (blk_rq_unmap_user(bio, len))
ret = -EFAULT;
if (ret)
@@ -2149,6 +2153,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
ubuf += len;
}
+ blk_put_request(rq);
return ret;
}
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index 7eac10e63b23..ad5464ab99bc 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -146,7 +146,7 @@ static int AudioStart_f;
static int AudioEnd_m;
static int AudioEnd_f;
-static struct timer_list gscd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
static DEFINE_SPINLOCK(gscd_lock);
static struct request_queue *gscd_queue;
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index 351a01dd503a..0b0eab4f40fa 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -264,7 +264,7 @@ static inline int flag_low(int flag, unsigned long timeout)
static int sleep_timeout; /* max # of ticks to sleep */
static DECLARE_WAIT_QUEUE_HEAD(waitq);
static void sleep_timer(unsigned long data);
-static struct timer_list delay_timer = TIMER_INITIALIZER(sleep_timer, 0, 0);
+static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
static DEFINE_SPINLOCK(optcd_lock);
static struct request_queue *opt_queue;
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 452d34675159..466e9c2974bd 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -742,13 +742,10 @@ static struct sbpcd_drive *current_drive = D_S;
unsigned long cli_sti; /* for saving the processor flags */
#endif
/*==========================================================================*/
-static struct timer_list delay_timer =
- TIMER_INITIALIZER(mark_timeout_delay, 0, 0);
-static struct timer_list data_timer =
- TIMER_INITIALIZER(mark_timeout_data, 0, 0);
+static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
+static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
#if 0
-static struct timer_list audio_timer =
- TIMER_INITIALIZER(mark_timeout_audio, 0, 0);
+static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
#endif
/*==========================================================================*/
/*
@@ -830,8 +827,7 @@ static void mark_timeout_audio(u_long i)
static void sbp_sleep(u_int time)
{
sti();
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(time);
+ schedule_timeout_interruptible(time);
sti();
}
/*==========================================================================*/
@@ -4219,7 +4215,8 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
- if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf);
+ if (current_drive->sbp_audsiz>0)
+ vfree(current_drive->aud_buf);
current_drive->aud_buf=NULL;
current_drive->sbp_audsiz=arg;
@@ -5913,7 +5910,8 @@ static void sbpcd_exit(void)
put_disk(D_S[j].disk);
devfs_remove("sbp/c0t%d", j);
vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
+ if (D_S[j].sbp_audsiz>0)
+ vfree(D_S[j].aud_buf);
if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
{
msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 4e7a342ec36f..74b1cadbf161 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -151,7 +151,7 @@ static struct sjcd_stat statistic;
/*
* Timer.
*/
-static struct timer_list sjcd_delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
#define SJCD_SET_TIMER( func, tmout ) \
( sjcd_delay_timer.expires = jiffies+tmout, \
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 9f22e8f1f6c0..e65659926432 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -1478,8 +1478,7 @@ static int __init sony535_init(void)
/* look for the CD-ROM, follows the procedure in the DOS driver */
inb(select_unit_reg);
/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((HZ+17)*40/18);
+ schedule_timeout_interruptible((HZ+17)*40/18);
inb(result_reg);
outb(0, read_status_reg); /* does a reset? */
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 38dd9ffbe8bc..b5191780ecca 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -46,9 +46,9 @@
#include <asm/vio.h>
#include <asm/scatterlist.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/vio.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/vio.h>
#define VIOCD_DEVICE "iseries/vcd"
#define VIOCD_DEVICE_DEVFS "iseries/vcd"
@@ -734,15 +734,18 @@ static int viocd_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viocd_device_table[] __devinitdata = {
{ "viocd", "" },
- { 0, }
+ { "", "" }
};
-
MODULE_DEVICE_TABLE(vio, viocd_device_table);
+
static struct vio_driver viocd_driver = {
- .name = "viocd",
.id_table = viocd_device_table,
.probe = viocd_probe,
- .remove = viocd_remove
+ .remove = viocd_remove,
+ .driver = {
+ .name = "viocd",
+ .owner = THIS_MODULE,
+ }
};
static int __init viocd_init(void)
diff --git a/drivers/char/.gitignore b/drivers/char/.gitignore
new file mode 100644
index 000000000000..2b6b1d772ed7
--- /dev/null
+++ b/drivers/char/.gitignore
@@ -0,0 +1,3 @@
+consolemap_deftbl.c
+defkeymap.c
+
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4f27e5519296..fdf4370db994 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -138,7 +138,7 @@ config CYZ_INTR
config DIGIEPCA
tristate "Digiboard Intelligent Async Support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
---help---
This is a driver for Digi International's Xx, Xeve, and Xem series
of cards which provide multiple serial ports. You would need
@@ -661,7 +661,7 @@ config HW_RANDOM
config NVRAM
tristate "/dev/nvram support"
- depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM
+ depends on ATARI || X86 || ARM || GENERIC_NVRAM
---help---
If you say Y here and create a character special file /dev/nvram
with major number 10 and minor number 144 using mknod ("man mknod"),
@@ -735,7 +735,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !PPC64
+ depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -842,8 +842,7 @@ config SONYPI
config TANBAC_TB0219
tristate "TANBAC TB0219 base board support"
- depends TANBAC_TB0229
-
+ depends TANBAC_TB022X
menu "Ftape, the floppy tape device driver"
@@ -986,7 +985,7 @@ config MAX_RAW_DEVS
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86_64 || X86 || IA64 || PPC64 || ARCH_S390
+ depends on X86 || IA64 || PPC64 || ARCH_S390
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
@@ -1002,5 +1001,17 @@ config MMTIMER
source "drivers/char/tpm/Kconfig"
+config TELCLOCK
+ tristate "Telecom clock driver for MPBL0010 ATCA SBC"
+ depends on EXPERIMENTAL
+ default n
+ help
+ The telecom clock device is specific to the MPBL0010 ATCA computer and
+ allows direct userspace access to the configuration of the telecom clock
+ configuration settings. This device is used for hardware synchronization
+ across the ATCA backplane fabric. Upon loading, the driver exports a
+ sysfs directory, /sys/devices/platform/telco_clock, with a number of
+ files for controlling the behavior of this hardware.
+
endmenu
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 08f69287ea36..4aeae687e88a 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_TELCLOCK) += tlclk.o
obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_MWAVE) += mwave/
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 7f8c1b53b754..486ed8a11b59 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -27,7 +27,7 @@ config AGP
config AGP_ALI
tristate "ALI chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
---help---
This option gives you AGP support for the GLX component of
XFree86 4.x on the following ALi chipsets. The supported chipsets
@@ -45,7 +45,7 @@ config AGP_ALI
config AGP_ATI
tristate "ATI chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
---help---
This option gives you AGP support for the GLX component of
XFree86 4.x on the ATI RadeonIGP family of chipsets.
@@ -55,7 +55,7 @@ config AGP_ATI
config AGP_AMD
tristate "AMD Irongate, 761, and 762 chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
@@ -91,7 +91,7 @@ config AGP_INTEL
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
XFree86 4.x on the following NVIDIA chipsets. The supported chipsets
@@ -99,7 +99,7 @@ config AGP_NVIDIA
config AGP_SIS
tristate "SiS chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
XFree86 4.x on Silicon Integrated Systems [SiS] chipsets.
@@ -111,14 +111,14 @@ config AGP_SIS
config AGP_SWORKS
tristate "Serverworks LE/HE chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
Say Y here to support the Serverworks AGP card. See
<http://www.serverworks.com/> for product descriptions and images.
config AGP_VIA
tristate "VIA chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
@@ -154,7 +154,7 @@ config AGP_UNINORTH
config AGP_EFFICEON
tristate "Transmeta Efficeon support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86_32
help
This option gives you AGP support for the Transmeta Efficeon
series processors with integrated northbridges.
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 9c9c9c2247ce..b02fc2267159 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -7,6 +7,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <asm/page.h> /* PAGE_SIZE */
#include "agp.h"
#define ALI_AGPCTRL 0xb8
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 59f589d733f9..0e6c3a31d344 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <asm/page.h> /* PAGE_SIZE */
#include "agp.h"
/* Will need to be increased if AMD64 ever goes >8-way. */
@@ -429,7 +430,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
struct pci_dev *dev1;
int i;
unsigned size = amd64_fetch_size();
- printk(KERN_INFO "Setting up ULi AGP. \n");
+ printk(KERN_INFO "Setting up ULi AGP.\n");
dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0));
if (dev1 == NULL) {
printk(KERN_INFO PFX "Detected a ULi chipset, "
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index e572ced9100a..0b6e72642d6e 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -6,6 +6,8 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/agp_backend.h>
#include <asm/agp.h>
#include "agp.h"
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 4d4e602fdc7e..82b43c541c8d 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -206,10 +206,9 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
bridge->driver->cleanup();
if (bridge->driver->free_gatt_table)
bridge->driver->free_gatt_table(bridge);
- if (bridge->key_list) {
- vfree(bridge->key_list);
- bridge->key_list = NULL;
- }
+
+ vfree(bridge->key_list);
+ bridge->key_list = NULL;
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f0079e991bdc..ac9da0ca36b7 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -319,7 +319,6 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
- info->mode = bridge->mode;
info->aper_base = bridge->gart_bus_addr;
info->aper_size = agp_return_size();
info->max_memory = bridge->max_memory_agp;
@@ -356,7 +355,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
return -EINVAL;
if (curr->is_bound == TRUE) {
- printk (KERN_INFO PFX "memory %p is already bound!\n", curr);
+ printk(KERN_INFO PFX "memory %p is already bound!\n", curr);
return -EINVAL;
}
if (curr->is_flushed == FALSE) {
@@ -391,7 +390,7 @@ int agp_unbind_memory(struct agp_memory *curr)
return -EINVAL;
if (curr->is_bound != TRUE) {
- printk (KERN_INFO PFX "memory %p was not bound!\n", curr);
+ printk(KERN_INFO PFX "memory %p was not bound!\n", curr);
return -EINVAL;
}
@@ -415,7 +414,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
u32 tmp;
if (*requested_mode & AGP2_RESERVED_MASK) {
- printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP2_RESERVED_MASK;
}
@@ -423,7 +422,7 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
tmp = *requested_mode & 7;
switch (tmp) {
case 0:
- printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
+ printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
*requested_mode |= AGPSTAT2_1X;
break;
case 1:
@@ -493,18 +492,18 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
u32 tmp;
if (*requested_mode & AGP3_RESERVED_MASK) {
- printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP3_RESERVED_MASK;
}
/* Check the speed bits make sense. */
tmp = *requested_mode & 7;
if (tmp == 0) {
- printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
+ printk(KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
*requested_mode |= AGPSTAT3_4X;
}
if (tmp >= 3) {
- printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
+ printk(KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
*requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
}
@@ -533,7 +532,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
* AGP2.x 4x -> AGP3.0 4x.
*/
if (*requested_mode & AGPSTAT2_4X) {
- printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
+ printk(KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~AGPSTAT2_4X;
*requested_mode |= AGPSTAT3_4X;
@@ -544,7 +543,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
* but have been passed an AGP 2.x mode.
* Convert AGP 1x,2x,4x -> AGP 3.0 4x.
*/
- printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
+ printk(KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
*requested_mode |= AGPSTAT3_4X;
@@ -554,13 +553,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
if (!(*bridge_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
- printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
+ printk(KERN_INFO PFX "%s requested AGPx8 but bridge not capable.\n", current->comm);
return;
}
if (!(*vga_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
- printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
+ printk(KERN_INFO PFX "%s requested AGPx8 but graphic card not capable.\n", current->comm);
return;
}
/* All set, bridge & device can do AGP x8*/
@@ -578,13 +577,13 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
*bridge_agpstat |= AGPSTAT3_4X;
else {
- printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
+ printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
"[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
origbridge, origvga, *bridge_agpstat, *vga_agpstat);
if (!(*bridge_agpstat & AGPSTAT3_4X))
- printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
+ printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
if (!(*vga_agpstat & AGPSTAT3_4X))
- printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+ printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
return;
}
}
@@ -622,7 +621,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
for (;;) {
device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
if (!device) {
- printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+ printk(KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
return 0;
}
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
@@ -734,7 +733,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
pci_write_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, temp);
- printk (KERN_INFO PFX "Device is in legacy mode,"
+ printk(KERN_INFO PFX "Device is in legacy mode,"
" falling back to 2.x\n");
}
}
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 99762b6c19ae..de5d6d212674 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -252,7 +252,7 @@ hp_zx1_configure (void)
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
- writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK);
+ writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
readl(hp->ioc_regs+HP_ZX1_IMASK);
writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
readl(hp->ioc_regs+HP_ZX1_IBASE);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 94943298c03e..a2d9e5e48bbe 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -10,6 +10,8 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/agp_backend.h>
#include "agp.h"
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index c9ac731504f2..40083241804e 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <linux/agp_backend.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include "agp.h"
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index d3aa159c9dec..7957fc91f6ad 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/agp_backend.h>
#include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioca_provider.h>
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index a9fb12c20eb7..71ea59a1dbeb 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -5,6 +5,8 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/agp_backend.h>
#include "agp.h"
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 2a36561eec68..a124f8c5d062 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2053,10 +2053,6 @@ static int __init rs_init(void)
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
- /*
- if(state->port && check_region(state->port,REGION_LENGTH(state)))
- continue;
- */
printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
state->line);
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 11f9ee581124..927a5bbe112c 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -172,7 +172,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
void cleanup_module(void)
{
- int i;
+ unsigned int i;
misc_deregister(&ac_miscdev);
@@ -195,7 +195,7 @@ int __init applicom_init(void)
int i, numisa = 0;
struct pci_dev *dev = NULL;
void __iomem *RamIO;
- int boardno;
+ int boardno, ret;
printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
@@ -294,7 +294,8 @@ int __init applicom_init(void)
}
if (!numisa)
- printk(KERN_WARNING"ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem);
+ printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found "
+ "at mem 0x%lx\n", mem);
fin:
init_waitqueue_head(&FlagSleepRec);
@@ -304,7 +305,11 @@ int __init applicom_init(void)
DeviceErrorCount = 0;
if (numboards) {
- misc_register(&ac_miscdev);
+ ret = misc_register(&ac_miscdev);
+ if (ret) {
+ printk(KERN_WARNING "ac.o: Unable to register misc device\n");
+ goto out;
+ }
for (i = 0; i < MAX_BOARD; i++) {
int serial;
char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
@@ -337,6 +342,17 @@ int __init applicom_init(void)
else
return -ENXIO;
+
+out:
+ for (i = 0; i < MAX_BOARD; i++) {
+ if (!apbs[i].RamIO)
+ continue;
+ if (apbs[i].irq)
+ free_irq(apbs[i].irq, &dummy);
+ iounmap(apbs[i].RamIO);
+ }
+ pci_disable_device(dev);
+ return ret;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 6a5337bf0936..c7f818cd7b02 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -281,7 +281,7 @@ static char rcsid[] =
* make sure "cyc" appears in all kernel messages; all soft interrupts
* handled by same routine; recognize out-of-band reception; comment
* out some diagnostic messages; leave RTS/CTS flow control to hardware;
- * fix race condition in -Z buffer management; only -Y needs to explictly
+ * fix race condition in -Z buffer management; only -Y needs to explicitly
* flush chars; tidy up some startup messages;
*
* Revision 1.36.4.18 1996/07/25 18:57:31 bentson
@@ -865,7 +865,7 @@ static void cyz_poll(unsigned long);
static long cyz_polling_cycle = CZ_DEF_POLL;
static int cyz_timeron = 0;
-static struct timer_list cyz_timerlist = TIMER_INITIALIZER(cyz_poll, 0, 0);
+static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
#else /* CONFIG_CYZ_INTR */
static void cyz_rx_restart(unsigned long);
diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h
index 184378d23f8c..94d4eab5d3ca 100644
--- a/drivers/char/digi1.h
+++ b/drivers/char/digi1.h
@@ -1,46 +1,46 @@
/* Definitions for DigiBoard ditty(1) command. */
#if !defined(TIOCMODG)
-#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */
-#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */
+#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */
+#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */
#endif
#if !defined(TIOCMSET)
-#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */
-#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */
+#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */
+#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */
#endif
#if !defined(TIOCMBIC)
-#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */
-#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */
+#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */
+#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */
#endif
#if !defined(TIOCSDTR)
-#define TIOCSDTR ('e'<<8) | 0 /* set DTR */
-#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */
+#define TIOCSDTR (('e'<<8) | 0) /* set DTR */
+#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */
#endif
/************************************************************************
* Ioctl command arguments for DIGI parameters.
************************************************************************/
-#define DIGI_GETA ('e'<<8) | 94 /* Read params */
+#define DIGI_GETA (('e'<<8) | 94) /* Read params */
-#define DIGI_SETA ('e'<<8) | 95 /* Set params */
-#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */
-#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */
+#define DIGI_SETA (('e'<<8) | 95) /* Set params */
+#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */
+#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */
-#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */
+#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */
/* control characters */
-#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */
+#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */
/* control characters */
-#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */
+#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */
/* flow control chars */
-#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */
+#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */
/* flow control chars */
-#define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */
-#define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */
-#define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */
+#define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */
+#define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */
+#define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */
struct digiflow_struct
{
diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h
index c47d7fcb8400..3c1f1922c798 100644
--- a/drivers/char/digiFep1.h
+++ b/drivers/char/digiFep1.h
@@ -13,88 +13,88 @@
struct global_data
{
- volatile ushort cin;
- volatile ushort cout;
- volatile ushort cstart;
- volatile ushort cmax;
- volatile ushort ein;
- volatile ushort eout;
- volatile ushort istart;
- volatile ushort imax;
+ u16 cin;
+ u16 cout;
+ u16 cstart;
+ u16 cmax;
+ u16 ein;
+ u16 eout;
+ u16 istart;
+ u16 imax;
};
struct board_chan
{
- int filler1;
- int filler2;
- volatile ushort tseg;
- volatile ushort tin;
- volatile ushort tout;
- volatile ushort tmax;
-
- volatile ushort rseg;
- volatile ushort rin;
- volatile ushort rout;
- volatile ushort rmax;
-
- volatile ushort tlow;
- volatile ushort rlow;
- volatile ushort rhigh;
- volatile ushort incr;
-
- volatile ushort etime;
- volatile ushort edelay;
- volatile unchar *dev;
-
- volatile ushort iflag;
- volatile ushort oflag;
- volatile ushort cflag;
- volatile ushort gmask;
-
- volatile ushort col;
- volatile ushort delay;
- volatile ushort imask;
- volatile ushort tflush;
-
- int filler3;
- int filler4;
- int filler5;
- int filler6;
-
- volatile unchar num;
- volatile unchar ract;
- volatile unchar bstat;
- volatile unchar tbusy;
- volatile unchar iempty;
- volatile unchar ilow;
- volatile unchar idata;
- volatile unchar eflag;
-
- volatile unchar tflag;
- volatile unchar rflag;
- volatile unchar xmask;
- volatile unchar xval;
- volatile unchar mstat;
- volatile unchar mchange;
- volatile unchar mint;
- volatile unchar lstat;
-
- volatile unchar mtran;
- volatile unchar orun;
- volatile unchar startca;
- volatile unchar stopca;
- volatile unchar startc;
- volatile unchar stopc;
- volatile unchar vnext;
- volatile unchar hflow;
-
- volatile unchar fillc;
- volatile unchar ochar;
- volatile unchar omask;
-
- unchar filler7;
- unchar filler8[28];
+ u32 filler1;
+ u32 filler2;
+ u16 tseg;
+ u16 tin;
+ u16 tout;
+ u16 tmax;
+
+ u16 rseg;
+ u16 rin;
+ u16 rout;
+ u16 rmax;
+
+ u16 tlow;
+ u16 rlow;
+ u16 rhigh;
+ u16 incr;
+
+ u16 etime;
+ u16 edelay;
+ unchar *dev;
+
+ u16 iflag;
+ u16 oflag;
+ u16 cflag;
+ u16 gmask;
+
+ u16 col;
+ u16 delay;
+ u16 imask;
+ u16 tflush;
+
+ u32 filler3;
+ u32 filler4;
+ u32 filler5;
+ u32 filler6;
+
+ u8 num;
+ u8 ract;
+ u8 bstat;
+ u8 tbusy;
+ u8 iempty;
+ u8 ilow;
+ u8 idata;
+ u8 eflag;
+
+ u8 tflag;
+ u8 rflag;
+ u8 xmask;
+ u8 xval;
+ u8 mstat;
+ u8 mchange;
+ u8 mint;
+ u8 lstat;
+
+ u8 mtran;
+ u8 orun;
+ u8 startca;
+ u8 stopca;
+ u8 startc;
+ u8 stopc;
+ u8 vnext;
+ u8 hflow;
+
+ u8 fillc;
+ u8 ochar;
+ u8 omask;
+
+ u8 filler7;
+ u8 filler8[28];
};
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 123417e43040..56ace9d5e2ae 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -23,13 +23,6 @@ config DRM_TDFX
Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
graphics card. If M is selected, the module will be called tdfx.
-config DRM_GAMMA
- tristate "3dlabs GMX 2000"
- depends on DRM && BROKEN
- help
- This is the old gamma driver, please tell me if it might actually
- work.
-
config DRM_R128
tristate "ATI Rage 128"
depends on DRM && PCI
@@ -82,7 +75,7 @@ endchoice
config DRM_MGA
tristate "Matrox g200/g400"
- depends on DRM && AGP
+ depends on DRM
help
Choose this option if you have a Matrox G200, G400 or G450 graphics
card. If M is selected, the module will be called mga. AGP
@@ -103,3 +96,10 @@ config DRM_VIA
Choose this option if you have a Via unichrome or compatible video
chipset. If M is selected the module will be called via.
+config DRM_SAVAGE
+ tristate "Savage video cards"
+ depends on DRM
+ help
+ Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+ chipset. If M is selected the module will be called savage.
+
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index ddd941045b1f..e41060c76226 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -8,16 +8,16 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
drm_sysfs.o
-gamma-objs := gamma_drv.o gamma_dma.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
i810-objs := i810_drv.o i810_dma.o
i830-objs := i830_drv.o i830_dma.o i830_irq.o
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_ds.o sis_mm.o
+savage-objs := savage_drv.o savage_bci.o savage_state.o
via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
ifeq ($(CONFIG_COMPAT),y)
@@ -29,7 +29,6 @@ i915-objs += i915_ioc32.o
endif
obj-$(CONFIG_DRM) += drm.o
-obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
obj-$(CONFIG_DRM_R128) += r128.o
obj-$(CONFIG_DRM_RADEON)+= radeon.o
@@ -39,5 +38,7 @@ obj-$(CONFIG_DRM_I830) += i830.o
obj-$(CONFIG_DRM_I915) += i915.o
obj-$(CONFIG_DRM_FFB) += ffb.o
obj-$(CONFIG_DRM_SIS) += sis.o
+obj-$(CONFIG_DRM_SAVAGE)+= savage.o
obj-$(CONFIG_DRM_VIA) +=via.o
+
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 0aec5ef481b8..6d3fec160bff 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -1,5 +1,5 @@
/**
- * \file ati_pcigart.h
+ * \file ati_pcigart.c
* ATI PCI GART support
*
* \author Gareth Hughes <gareth@valinux.com>
@@ -52,85 +52,91 @@
# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
-static unsigned long drm_ati_alloc_pcigart_table( void )
+static unsigned long drm_ati_alloc_pcigart_table(void)
{
unsigned long address;
struct page *page;
int i;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
- if ( address == 0UL ) {
+ address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER);
+ if (address == 0UL) {
return 0;
}
- page = virt_to_page( address );
+ page = virt_to_page(address);
- for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
get_page(page);
- SetPageReserved( page );
+ SetPageReserved(page);
}
- DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
+ DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
return address;
}
-static void drm_ati_free_pcigart_table( unsigned long address )
+static void drm_ati_free_pcigart_table(unsigned long address)
{
struct page *page;
int i;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- page = virt_to_page( address );
+ page = virt_to_page(address);
- for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
__put_page(page);
- ClearPageReserved( page );
+ ClearPageReserved(page);
}
- free_pages( address, ATI_PCIGART_TABLE_ORDER );
+ free_pages(address, ATI_PCIGART_TABLE_ORDER);
}
-int drm_ati_pcigart_cleanup( drm_device_t *dev,
- unsigned long addr,
- dma_addr_t bus_addr)
+int drm_ati_pcigart_cleanup(drm_device_t * dev,
+ drm_ati_pcigart_info * gart_info)
{
drm_sg_mem_t *entry = dev->sg;
unsigned long pages;
int i;
/* we need to support large memory configurations */
- if ( !entry ) {
- DRM_ERROR( "no scatter/gather memory!\n" );
+ if (!entry) {
+ DRM_ERROR("no scatter/gather memory!\n");
return 0;
}
- if ( bus_addr ) {
- pci_unmap_single(dev->pdev, bus_addr,
- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
- PCI_DMA_TODEVICE);
+ if (gart_info->bus_addr) {
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+ pci_unmap_single(dev->pdev, gart_info->bus_addr,
+ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+ }
- pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
- ? entry->pages : ATI_MAX_PCIGART_PAGES;
+ pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
+ ? entry->pages : ATI_MAX_PCIGART_PAGES;
- for ( i = 0 ; i < pages ; i++ ) {
- if ( !entry->busaddr[i] ) break;
+ for (i = 0; i < pages; i++) {
+ if (!entry->busaddr[i])
+ break;
pci_unmap_single(dev->pdev, entry->busaddr[i],
PAGE_SIZE, PCI_DMA_TODEVICE);
}
+
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+ gart_info->bus_addr = 0;
}
- if ( addr ) {
- drm_ati_free_pcigart_table( addr );
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
+ && gart_info->addr) {
+ drm_ati_free_pcigart_table(gart_info->addr);
+ gart_info->addr = 0;
}
return 1;
}
+
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-int drm_ati_pcigart_init( drm_device_t *dev,
- unsigned long *addr,
- dma_addr_t *bus_addr)
+int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
{
drm_sg_mem_t *entry = dev->sg;
unsigned long address = 0;
@@ -138,48 +144,57 @@ int drm_ati_pcigart_init( drm_device_t *dev,
u32 *pci_gart, page_base, bus_address = 0;
int i, j, ret = 0;
- if ( !entry ) {
- DRM_ERROR( "no scatter/gather memory!\n" );
+ if (!entry) {
+ DRM_ERROR("no scatter/gather memory!\n");
goto done;
}
- address = drm_ati_alloc_pcigart_table();
- if ( !address ) {
- DRM_ERROR( "cannot allocate PCI GART page!\n" );
- goto done;
- }
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+ DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
- if ( !dev->pdev ) {
- DRM_ERROR( "PCI device unknown!\n" );
- goto done;
- }
+ address = drm_ati_alloc_pcigart_table();
+ if (!address) {
+ DRM_ERROR("cannot allocate PCI GART page!\n");
+ goto done;
+ }
- bus_address = pci_map_single(dev->pdev, (void *)address,
- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
- PCI_DMA_TODEVICE);
- if (bus_address == 0) {
- DRM_ERROR( "unable to map PCIGART pages!\n" );
- drm_ati_free_pcigart_table( address );
- address = 0;
- goto done;
+ if (!dev->pdev) {
+ DRM_ERROR("PCI device unknown!\n");
+ goto done;
+ }
+
+ bus_address = pci_map_single(dev->pdev, (void *)address,
+ ATI_PCIGART_TABLE_PAGES *
+ PAGE_SIZE, PCI_DMA_TODEVICE);
+ if (bus_address == 0) {
+ DRM_ERROR("unable to map PCIGART pages!\n");
+ drm_ati_free_pcigart_table(address);
+ address = 0;
+ goto done;
+ }
+ } else {
+ address = gart_info->addr;
+ bus_address = gart_info->bus_addr;
+ DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
+ bus_address, address);
}
- pci_gart = (u32 *)address;
+ pci_gart = (u32 *) address;
- pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
- ? entry->pages : ATI_MAX_PCIGART_PAGES;
+ pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
+ ? entry->pages : ATI_MAX_PCIGART_PAGES;
- memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+ memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32));
- for ( i = 0 ; i < pages ; i++ ) {
+ for (i = 0; i < pages; i++) {
/* we need to support large memory configurations */
entry->busaddr[i] = pci_map_single(dev->pdev,
- page_address( entry->pagelist[i] ),
- PAGE_SIZE,
- PCI_DMA_TODEVICE);
+ page_address(entry->
+ pagelist[i]),
+ PAGE_SIZE, PCI_DMA_TODEVICE);
if (entry->busaddr[i] == 0) {
- DRM_ERROR( "unable to map PCIGART pages!\n" );
- drm_ati_pcigart_cleanup( dev, address, bus_address );
+ DRM_ERROR("unable to map PCIGART pages!\n");
+ drm_ati_pcigart_cleanup(dev, gart_info);
address = 0;
bus_address = 0;
goto done;
@@ -187,7 +202,11 @@ int drm_ati_pcigart_init( drm_device_t *dev,
page_base = (u32) entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
- *pci_gart++ = cpu_to_le32( page_base );
+ if (gart_info->is_pcie)
+ *pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc;
+ else
+ *pci_gart = cpu_to_le32(page_base);
+ *pci_gart++;
page_base += ATI_PCIGART_PAGE_SIZE;
}
}
@@ -200,9 +219,10 @@ int drm_ati_pcigart_init( drm_device_t *dev,
mb();
#endif
-done:
- *addr = address;
- *bus_addr = bus_address;
+ done:
+ gart_info->addr = address;
+ gart_info->bus_addr = bus_address;
return ret;
}
+
EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index e8371dd87fbc..64d6237fdd0b 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -1,7 +1,7 @@
/**
- * \file drm.h
+ * \file drm.h
* Header for the Direct Rendering Manager
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
*
* \par Acknowledgments:
@@ -33,7 +33,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-
#ifndef _DRM_H_
#define _DRM_H_
@@ -56,7 +55,7 @@
#define ioctl(a,b,c) xf86ioctl(a,b,c)
#else
#include <sys/ioccom.h>
-#endif /* __FreeBSD__ && xf86ioctl */
+#endif /* __FreeBSD__ && xf86ioctl */
#define DRM_IOCTL_NR(n) ((n) & 0xff)
#define DRM_IOC_VOID IOC_VOID
#define DRM_IOC_READ IOC_OUT
@@ -97,16 +96,14 @@
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
-
-typedef unsigned long drm_handle_t;
-typedef unsigned int drm_context_t;
-typedef unsigned int drm_drawable_t;
-typedef unsigned int drm_magic_t;
-
+typedef unsigned int drm_handle_t;
+typedef unsigned int drm_context_t;
+typedef unsigned int drm_drawable_t;
+typedef unsigned int drm_magic_t;
/**
* Cliprect.
- *
+ *
* \warning: If you change this structure, make sure you change
* XF86DRIClipRectRec in the server as well
*
@@ -114,22 +111,21 @@ typedef unsigned int drm_magic_t;
* backwards-compatibility reasons.
*/
typedef struct drm_clip_rect {
- unsigned short x1;
- unsigned short y1;
- unsigned short x2;
- unsigned short y2;
+ unsigned short x1;
+ unsigned short y1;
+ unsigned short x2;
+ unsigned short y2;
} drm_clip_rect_t;
-
/**
* Texture region,
*/
typedef struct drm_tex_region {
- unsigned char next;
- unsigned char prev;
- unsigned char in_use;
- unsigned char padding;
- unsigned int age;
+ unsigned char next;
+ unsigned char prev;
+ unsigned char in_use;
+ unsigned char padding;
+ unsigned int age;
} drm_tex_region_t;
/**
@@ -141,28 +137,26 @@ typedef struct drm_tex_region {
*/
typedef struct drm_hw_lock {
__volatile__ unsigned int lock; /**< lock variable */
- char padding[60]; /**< Pad to cache line */
+ char padding[60]; /**< Pad to cache line */
} drm_hw_lock_t;
-
/**
* DRM_IOCTL_VERSION ioctl argument type.
- *
+ *
* \sa drmGetVersion().
*/
typedef struct drm_version {
- int version_major; /**< Major version */
- int version_minor; /**< Minor version */
- int version_patchlevel;/**< Patch level */
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel; /**< Patch level */
size_t name_len; /**< Length of name buffer */
- char __user *name; /**< Name of driver */
+ char __user *name; /**< Name of driver */
size_t date_len; /**< Length of date buffer */
- char __user *date; /**< User-space buffer to hold date */
+ char __user *date; /**< User-space buffer to hold date */
size_t desc_len; /**< Length of desc buffer */
- char __user *desc; /**< User-space buffer to hold desc */
+ char __user *desc; /**< User-space buffer to hold desc */
} drm_version_t;
-
/**
* DRM_IOCTL_GET_UNIQUE ioctl argument type.
*
@@ -170,21 +164,18 @@ typedef struct drm_version {
*/
typedef struct drm_unique {
size_t unique_len; /**< Length of unique */
- char __user *unique; /**< Unique name for driver instantiation */
+ char __user *unique; /**< Unique name for driver instantiation */
} drm_unique_t;
-
typedef struct drm_list {
- int count; /**< Length of user-space structures */
- drm_version_t __user *version;
+ int count; /**< Length of user-space structures */
+ drm_version_t __user *version;
} drm_list_t;
-
typedef struct drm_block {
- int unused;
+ int unused;
} drm_block_t;
-
/**
* DRM_IOCTL_CONTROL ioctl argument type.
*
@@ -196,43 +187,40 @@ typedef struct drm_control {
DRM_RM_COMMAND,
DRM_INST_HANDLER,
DRM_UNINST_HANDLER
- } func;
- int irq;
+ } func;
+ int irq;
} drm_control_t;
-
/**
* Type of memory to map.
*/
typedef enum drm_map_type {
- _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
- _DRM_REGISTERS = 1, /**< no caching, no core dump */
- _DRM_SHM = 2, /**< shared, cached */
- _DRM_AGP = 3, /**< AGP/GART */
- _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
+ _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
+ _DRM_REGISTERS = 1, /**< no caching, no core dump */
+ _DRM_SHM = 2, /**< shared, cached */
+ _DRM_AGP = 3, /**< AGP/GART */
+ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
+ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
} drm_map_type_t;
-
/**
* Memory mapping flags.
*/
typedef enum drm_map_flags {
- _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
- _DRM_READ_ONLY = 0x02,
- _DRM_LOCKED = 0x04, /**< shared, cached, locked */
- _DRM_KERNEL = 0x08, /**< kernel requires access */
+ _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
+ _DRM_READ_ONLY = 0x02,
+ _DRM_LOCKED = 0x04, /**< shared, cached, locked */
+ _DRM_KERNEL = 0x08, /**< kernel requires access */
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
- _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
- _DRM_REMOVABLE = 0x40 /**< Removable mapping */
+ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
+ _DRM_REMOVABLE = 0x40 /**< Removable mapping */
} drm_map_flags_t;
-
typedef struct drm_ctx_priv_map {
- unsigned int ctx_id; /**< Context requesting private mapping */
- void *handle; /**< Handle of map */
+ unsigned int ctx_id; /**< Context requesting private mapping */
+ void *handle; /**< Handle of map */
} drm_ctx_priv_map_t;
-
/**
* DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
* argument type.
@@ -240,30 +228,28 @@ typedef struct drm_ctx_priv_map {
* \sa drmAddMap().
*/
typedef struct drm_map {
- unsigned long offset; /**< Requested physical address (0 for SAREA)*/
- unsigned long size; /**< Requested physical size (bytes) */
- drm_map_type_t type; /**< Type of memory to map */
+ unsigned long offset; /**< Requested physical address (0 for SAREA)*/
+ unsigned long size; /**< Requested physical size (bytes) */
+ drm_map_type_t type; /**< Type of memory to map */
drm_map_flags_t flags; /**< Flags */
- void *handle; /**< User-space: "Handle" to pass to mmap() */
+ void *handle; /**< User-space: "Handle" to pass to mmap() */
/**< Kernel-space: kernel-virtual address */
- int mtrr; /**< MTRR slot used */
- /* Private data */
+ int mtrr; /**< MTRR slot used */
+ /* Private data */
} drm_map_t;
-
/**
* DRM_IOCTL_GET_CLIENT ioctl argument type.
*/
typedef struct drm_client {
- int idx; /**< Which client desired? */
- int auth; /**< Is client authenticated? */
- unsigned long pid; /**< Process ID */
- unsigned long uid; /**< User ID */
- unsigned long magic; /**< Magic */
- unsigned long iocs; /**< Ioctl count */
+ int idx; /**< Which client desired? */
+ int auth; /**< Is client authenticated? */
+ unsigned long pid; /**< Process ID */
+ unsigned long uid; /**< User ID */
+ unsigned long magic; /**< Magic */
+ unsigned long iocs; /**< Ioctl count */
} drm_client_t;
-
typedef enum {
_DRM_STAT_LOCK,
_DRM_STAT_OPENS,
@@ -281,63 +267,58 @@ typedef enum {
_DRM_STAT_DMA, /**< DMA */
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
_DRM_STAT_MISSED /**< Missed DMA opportunity */
-
- /* Add to the *END* of the list */
+ /* Add to the *END* of the list */
} drm_stat_type_t;
-
/**
* DRM_IOCTL_GET_STATS ioctl argument type.
*/
typedef struct drm_stats {
unsigned long count;
struct {
- unsigned long value;
+ unsigned long value;
drm_stat_type_t type;
} data[15];
} drm_stats_t;
-
/**
* Hardware locking flags.
*/
typedef enum drm_lock_flags {
- _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
- _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
- _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
- _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
- /* These *HALT* flags aren't supported yet
- -- they will be used to support the
- full-screen DGA-like mode. */
+ _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
+ /* These *HALT* flags aren't supported yet
+ -- they will be used to support the
+ full-screen DGA-like mode. */
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
} drm_lock_flags_t;
-
/**
* DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
- *
+ *
* \sa drmGetLock() and drmUnlock().
*/
typedef struct drm_lock {
- int context;
+ int context;
drm_lock_flags_t flags;
} drm_lock_t;
-
/**
* DMA flags
*
- * \warning
+ * \warning
* These values \e must match xf86drm.h.
*
* \sa drm_dma.
*/
-typedef enum drm_dma_flags {
- /* Flags for DMA buffer dispatch */
- _DRM_DMA_BLOCK = 0x01, /**<
+typedef enum drm_dma_flags {
+ /* Flags for DMA buffer dispatch */
+ _DRM_DMA_BLOCK = 0x01, /**<
* Block until buffer dispatched.
- *
+ *
* \note The buffer may not yet have
* been processed by the hardware --
* getting a hardware lock with the
@@ -346,78 +327,73 @@ typedef enum drm_dma_flags {
* processed.
*/
_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
- _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
- /* Flags for DMA buffer request */
- _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
- _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
- _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
+ /* Flags for DMA buffer request */
+ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
} drm_dma_flags_t;
-
/**
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
*
* \sa drmAddBufs().
*/
typedef struct drm_buf_desc {
- int count; /**< Number of buffers of this size */
- int size; /**< Size in bytes */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
enum {
- _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
- _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
- _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
- } flags;
- unsigned long agp_start; /**<
+ _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
+ _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
+ } flags;
+ unsigned long agp_start; /**<
* Start address of where the AGP buffers are
* in the AGP aperture
*/
} drm_buf_desc_t;
-
/**
* DRM_IOCTL_INFO_BUFS ioctl argument type.
*/
typedef struct drm_buf_info {
- int count; /**< Entries in list */
+ int count; /**< Entries in list */
drm_buf_desc_t __user *list;
} drm_buf_info_t;
-
/**
* DRM_IOCTL_FREE_BUFS ioctl argument type.
*/
typedef struct drm_buf_free {
- int count;
- int __user *list;
+ int count;
+ int __user *list;
} drm_buf_free_t;
-
/**
* Buffer information
*
* \sa drm_buf_map.
*/
typedef struct drm_buf_pub {
- int idx; /**< Index into the master buffer list */
- int total; /**< Buffer size */
- int used; /**< Amount of buffer in use (for DMA) */
- void __user *address; /**< Address of buffer */
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ void __user *address; /**< Address of buffer */
} drm_buf_pub_t;
-
/**
* DRM_IOCTL_MAP_BUFS ioctl argument type.
*/
typedef struct drm_buf_map {
- int count; /**< Length of the buffer list */
- void __user *virtual; /**< Mmap'd area in user-virtual */
+ int count; /**< Length of the buffer list */
+ void __user *virtual; /**< Mmap'd area in user-virtual */
drm_buf_pub_t __user *list; /**< Buffer information */
} drm_buf_map_t;
-
/**
* DRM_IOCTL_DMA ioctl argument type.
*
@@ -426,61 +402,55 @@ typedef struct drm_buf_map {
* \sa drmDMA().
*/
typedef struct drm_dma {
- int context; /**< Context handle */
- int send_count; /**< Number of buffers to send */
- int __user *send_indices; /**< List of handles to buffers */
- int __user *send_sizes; /**< Lengths of data to send */
+ int context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ int __user *send_indices; /**< List of handles to buffers */
+ int __user *send_sizes; /**< Lengths of data to send */
drm_dma_flags_t flags; /**< Flags */
- int request_count; /**< Number of buffers requested */
- int request_size; /**< Desired size for buffers */
- int __user *request_indices; /**< Buffer information */
- int __user *request_sizes;
- int granted_count; /**< Number of buffers granted */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size for buffers */
+ int __user *request_indices; /**< Buffer information */
+ int __user *request_sizes;
+ int granted_count; /**< Number of buffers granted */
} drm_dma_t;
-
typedef enum {
_DRM_CONTEXT_PRESERVED = 0x01,
- _DRM_CONTEXT_2DONLY = 0x02
+ _DRM_CONTEXT_2DONLY = 0x02
} drm_ctx_flags_t;
-
/**
* DRM_IOCTL_ADD_CTX ioctl argument type.
*
* \sa drmCreateContext() and drmDestroyContext().
*/
typedef struct drm_ctx {
- drm_context_t handle;
+ drm_context_t handle;
drm_ctx_flags_t flags;
} drm_ctx_t;
-
/**
* DRM_IOCTL_RES_CTX ioctl argument type.
*/
typedef struct drm_ctx_res {
- int count;
- drm_ctx_t __user *contexts;
+ int count;
+ drm_ctx_t __user *contexts;
} drm_ctx_res_t;
-
/**
* DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
*/
typedef struct drm_draw {
- drm_drawable_t handle;
+ drm_drawable_t handle;
} drm_draw_t;
-
/**
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
*/
typedef struct drm_auth {
- drm_magic_t magic;
+ drm_magic_t magic;
} drm_auth_t;
-
/**
* DRM_IOCTL_IRQ_BUSID ioctl argument type.
*
@@ -493,24 +463,20 @@ typedef struct drm_irq_busid {
int funcnum; /**< function number */
} drm_irq_busid_t;
-
typedef enum {
- _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
- _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
- _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
+ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
} drm_vblank_seq_type_t;
-
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
-
struct drm_wait_vblank_request {
drm_vblank_seq_type_t type;
unsigned int sequence;
unsigned long signal;
};
-
struct drm_wait_vblank_reply {
drm_vblank_seq_type_t type;
unsigned int sequence;
@@ -518,7 +484,6 @@ struct drm_wait_vblank_reply {
long tval_usec;
};
-
/**
* DRM_IOCTL_WAIT_VBLANK ioctl argument type.
*
@@ -529,7 +494,6 @@ typedef union drm_wait_vblank {
struct drm_wait_vblank_reply reply;
} drm_wait_vblank_t;
-
/**
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
*
@@ -539,7 +503,6 @@ typedef struct drm_agp_mode {
unsigned long mode; /**< AGP mode */
} drm_agp_mode_t;
-
/**
* DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
*
@@ -548,22 +511,20 @@ typedef struct drm_agp_mode {
typedef struct drm_agp_buffer {
unsigned long size; /**< In bytes -- will round to page boundary */
unsigned long handle; /**< Used for binding / unbinding */
- unsigned long type; /**< Type of memory to allocate */
- unsigned long physical; /**< Physical used by i810 */
+ unsigned long type; /**< Type of memory to allocate */
+ unsigned long physical; /**< Physical used by i810 */
} drm_agp_buffer_t;
-
/**
* DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
*
* \sa drmAgpBind() and drmAgpUnbind().
*/
typedef struct drm_agp_binding {
- unsigned long handle; /**< From drm_agp_buffer */
+ unsigned long handle; /**< From drm_agp_buffer */
unsigned long offset; /**< In bytes -- will round to page boundary */
} drm_agp_binding_t;
-
/**
* DRM_IOCTL_AGP_INFO ioctl argument type.
*
@@ -572,20 +533,19 @@ typedef struct drm_agp_binding {
* drmAgpVendorId() and drmAgpDeviceId().
*/
typedef struct drm_agp_info {
- int agp_version_major;
- int agp_version_minor;
- unsigned long mode;
- unsigned long aperture_base; /* physical address */
- unsigned long aperture_size; /* bytes */
- unsigned long memory_allowed; /* bytes */
- unsigned long memory_used;
-
- /* PCI information */
+ int agp_version_major;
+ int agp_version_minor;
+ unsigned long mode;
+ unsigned long aperture_base; /* physical address */
+ unsigned long aperture_size; /* bytes */
+ unsigned long memory_allowed; /* bytes */
+ unsigned long memory_used;
+
+ /* PCI information */
unsigned short id_vendor;
unsigned short id_device;
} drm_agp_info_t;
-
/**
* DRM_IOCTL_SG_ALLOC ioctl argument type.
*/
@@ -604,7 +564,6 @@ typedef struct drm_set_version {
int drm_dd_minor;
} drm_set_version_t;
-
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 5df09cc8c6db..3dc3c9d79ae4 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -1,7 +1,7 @@
/**
- * \file drmP.h
+ * \file drmP.h
* Private header for Direct Rendering Manager
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -43,7 +43,7 @@
* before static inline funcs in wait.h. Doing this so we
* can build the DRM (part of PI DRI). 4/21/2000 S + B */
#include <asm/current.h>
-#endif /* __alpha__ */
+#endif /* __alpha__ */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -53,13 +53,12 @@
#include <linux/init.h>
#include <linux/file.h>
#include <linux/pci.h>
-#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/smp_lock.h> /* For (un)lock_kernel */
#include <linux/mm.h>
#include <linux/cdev.h>
#if defined(__alpha__) || defined(__powerpc__)
-#include <asm/pgtable.h> /* For pte_wrprotect */
+#include <asm/pgtable.h> /* For pte_wrprotect */
#endif
#include <asm/io.h>
#include <asm/mman.h>
@@ -96,6 +95,7 @@
#define DRIVER_IRQ_SHARED 0x80
#define DRIVER_IRQ_VBL 0x100
#define DRIVER_DMA_QUEUE 0x200
+#define DRIVER_FB_DMA 0x400
/***********************************************************************/
/** \name Begin the DRM... */
@@ -108,7 +108,6 @@
#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
#define DRM_LOOPING_LIMIT 5000000
-#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
@@ -138,16 +137,15 @@
#define DRM_MEM_CTXLIST 21
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
-
-/*@}*/
+/*@}*/
/***********************************************************************/
/** \name Backward compatibility section */
/*@{*/
#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(x)
+#define MODULE_LICENSE(x)
#endif
#ifndef preempt_disable
@@ -155,47 +153,17 @@
#define preempt_enable()
#endif
-#ifndef pte_offset_map
+#ifndef pte_offset_map
#define pte_offset_map pte_offset
#define pte_unmap(pte)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
-static inline struct page * vmalloc_to_page(void * vmalloc_addr)
-{
- unsigned long addr = (unsigned long) vmalloc_addr;
- struct page *page = NULL;
- pgd_t *pgd = pgd_offset_k(addr);
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, addr);
- if (!pmd_none(*pmd)) {
- preempt_disable();
- ptep = pte_offset_map(pmd, addr);
- pte = *ptep;
- if (pte_present(pte))
- page = pte_page(pte);
- pte_unmap(ptep);
- preempt_enable();
- }
- }
- return page;
-}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define DRM_RPR_ARG(vma)
-#else
#define DRM_RPR_ARG(vma) vma,
-#endif
#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
/*@}*/
-
/***********************************************************************/
/** \name Macros to make printk easier */
/*@{*/
@@ -224,7 +192,7 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr)
/**
* Debug output.
- *
+ *
* \param fmt printf() like format string.
* \param arg arguments
*/
@@ -252,14 +220,13 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr)
/*@}*/
-
/***********************************************************************/
/** \name Internal types and structures */
/*@{*/
-#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
-#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
+#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
+#define DRM_MIN(a,b) min(a,b)
+#define DRM_MAX(a,b) max(a,b)
#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
@@ -304,7 +271,7 @@ do { \
if ( copy_to_user( name, value, len ) ) \
return -EFAULT; \
}
-
+
/**
* Ioctl function type.
*
@@ -313,25 +280,25 @@ do { \
* \param cmd command.
* \param arg argument.
*/
-typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
+typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
unsigned long arg);
typedef struct drm_ioctl_desc {
- drm_ioctl_t *func;
- int auth_needed;
- int root_only;
+ drm_ioctl_t *func;
+ int auth_needed;
+ int root_only;
} drm_ioctl_desc_t;
typedef struct drm_devstate {
- pid_t owner; /**< X server pid holding x_lock */
+ pid_t owner; /**< X server pid holding x_lock */
} drm_devstate_t;
typedef struct drm_magic_entry {
- drm_magic_t magic;
- struct drm_file *priv;
+ drm_magic_t magic;
+ struct drm_file *priv;
struct drm_magic_entry *next;
} drm_magic_entry_t;
@@ -342,111 +309,110 @@ typedef struct drm_magic_head {
typedef struct drm_vma_entry {
struct vm_area_struct *vma;
- struct drm_vma_entry *next;
- pid_t pid;
+ struct drm_vma_entry *next;
+ pid_t pid;
} drm_vma_entry_t;
/**
* DMA buffer.
*/
typedef struct drm_buf {
- int idx; /**< Index into master buflist */
- int total; /**< Buffer size */
- int order; /**< log-base-2(total) */
- int used; /**< Amount of buffer in use (for DMA) */
- unsigned long offset; /**< Byte offset (used internally) */
- void *address; /**< Address of buffer */
- unsigned long bus_address; /**< Bus address of buffer */
- struct drm_buf *next; /**< Kernel-only: used for free list */
- __volatile__ int waiting; /**< On kernel DMA queue */
- __volatile__ int pending; /**< On hardware DMA queue */
+ int idx; /**< Index into master buflist */
+ int total; /**< Buffer size */
+ int order; /**< log-base-2(total) */
+ int used; /**< Amount of buffer in use (for DMA) */
+ unsigned long offset; /**< Byte offset (used internally) */
+ void *address; /**< Address of buffer */
+ unsigned long bus_address; /**< Bus address of buffer */
+ struct drm_buf *next; /**< Kernel-only: used for free list */
+ __volatile__ int waiting; /**< On kernel DMA queue */
+ __volatile__ int pending; /**< On hardware DMA queue */
wait_queue_head_t dma_wait; /**< Processes waiting */
- struct file *filp; /**< Pointer to holding file descr */
- int context; /**< Kernel queue for this buffer */
- int while_locked;/**< Dispatch this buffer while locked */
+ struct file *filp; /**< Pointer to holding file descr */
+ int context; /**< Kernel queue for this buffer */
+ int while_locked; /**< Dispatch this buffer while locked */
enum {
- DRM_LIST_NONE = 0,
- DRM_LIST_FREE = 1,
- DRM_LIST_WAIT = 2,
- DRM_LIST_PEND = 3,
- DRM_LIST_PRIO = 4,
+ DRM_LIST_NONE = 0,
+ DRM_LIST_FREE = 1,
+ DRM_LIST_WAIT = 2,
+ DRM_LIST_PEND = 3,
+ DRM_LIST_PRIO = 4,
DRM_LIST_RECLAIM = 5
- } list; /**< Which list we're on */
+ } list; /**< Which list we're on */
- int dev_priv_size; /**< Size of buffer private storage */
- void *dev_private; /**< Per-buffer private storage */
+ int dev_priv_size; /**< Size of buffer private storage */
+ void *dev_private; /**< Per-buffer private storage */
} drm_buf_t;
-
/** bufs is one longer than it has to be */
typedef struct drm_waitlist {
- int count; /**< Number of possible buffers */
- drm_buf_t **bufs; /**< List of pointers to buffers */
- drm_buf_t **rp; /**< Read pointer */
- drm_buf_t **wp; /**< Write pointer */
- drm_buf_t **end; /**< End pointer */
- spinlock_t read_lock;
- spinlock_t write_lock;
+ int count; /**< Number of possible buffers */
+ drm_buf_t **bufs; /**< List of pointers to buffers */
+ drm_buf_t **rp; /**< Read pointer */
+ drm_buf_t **wp; /**< Write pointer */
+ drm_buf_t **end; /**< End pointer */
+ spinlock_t read_lock;
+ spinlock_t write_lock;
} drm_waitlist_t;
typedef struct drm_freelist {
- int initialized; /**< Freelist in use */
- atomic_t count; /**< Number of free buffers */
- drm_buf_t *next; /**< End pointer */
+ int initialized; /**< Freelist in use */
+ atomic_t count; /**< Number of free buffers */
+ drm_buf_t *next; /**< End pointer */
wait_queue_head_t waiting; /**< Processes waiting on free bufs */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
- atomic_t wfh; /**< If waiting for high mark */
- spinlock_t lock;
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ atomic_t wfh; /**< If waiting for high mark */
+ spinlock_t lock;
} drm_freelist_t;
/**
* Buffer entry. There is one of this for each buffer size order.
*/
typedef struct drm_buf_entry {
- int buf_size; /**< size */
- int buf_count; /**< number of buffers */
- drm_buf_t *buflist; /**< buffer list */
- int seg_count;
- int page_order;
- unsigned long *seglist;
-
- drm_freelist_t freelist;
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ drm_buf_t *buflist; /**< buffer list */
+ int seg_count;
+ int page_order;
+ unsigned long *seglist;
+
+ drm_freelist_t freelist;
} drm_buf_entry_t;
/** File private data */
typedef struct drm_file {
- int authenticated;
- int minor;
- pid_t pid;
- uid_t uid;
- drm_magic_t magic;
- unsigned long ioctl_count;
- struct drm_file *next;
- struct drm_file *prev;
- struct drm_head *head;
- int remove_auth_on_close;
- unsigned long lock_count;
- void *driver_priv;
+ int authenticated;
+ int minor;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct drm_file *next;
+ struct drm_file *prev;
+ struct drm_head *head;
+ int remove_auth_on_close;
+ unsigned long lock_count;
+ void *driver_priv;
} drm_file_t;
/** Wait queue */
typedef struct drm_queue {
- atomic_t use_count; /**< Outstanding uses (+1) */
- atomic_t finalization; /**< Finalization in progress */
- atomic_t block_count; /**< Count of processes waiting */
- atomic_t block_read; /**< Queue blocked for reads */
+ atomic_t use_count; /**< Outstanding uses (+1) */
+ atomic_t finalization; /**< Finalization in progress */
+ atomic_t block_count; /**< Count of processes waiting */
+ atomic_t block_read; /**< Queue blocked for reads */
wait_queue_head_t read_queue; /**< Processes waiting on block_read */
- atomic_t block_write; /**< Queue blocked for writes */
+ atomic_t block_write; /**< Queue blocked for writes */
wait_queue_head_t write_queue; /**< Processes waiting on block_write */
#if 1
- atomic_t total_queued; /**< Total queued statistic */
- atomic_t total_flushed;/**< Total flushes statistic */
- atomic_t total_locks; /**< Total locks statistics */
+ atomic_t total_queued; /**< Total queued statistic */
+ atomic_t total_flushed; /**< Total flushes statistic */
+ atomic_t total_locks; /**< Total locks statistics */
#endif
- drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
- drm_waitlist_t waitlist; /**< Pending buffers */
+ drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
+ drm_waitlist_t waitlist; /**< Pending buffers */
wait_queue_head_t flush_queue; /**< Processes waiting until flush */
} drm_queue_t;
@@ -454,10 +420,10 @@ typedef struct drm_queue {
* Lock data.
*/
typedef struct drm_lock_data {
- drm_hw_lock_t *hw_lock; /**< Hardware lock */
- struct file *filp; /**< File descr of lock holder (0=kernel) */
+ drm_hw_lock_t *hw_lock; /**< Hardware lock */
+ struct file *filp; /**< File descr of lock holder (0=kernel) */
wait_queue_head_t lock_queue; /**< Queue of blocked processes */
- unsigned long lock_time; /**< Time of last lock in jiffies */
+ unsigned long lock_time; /**< Time of last lock in jiffies */
} drm_lock_data_t;
/**
@@ -465,28 +431,29 @@ typedef struct drm_lock_data {
*/
typedef struct drm_device_dma {
- drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
- int buf_count; /**< total number of buffers */
- drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
- int seg_count;
- int page_count; /**< number of pages */
- unsigned long *pagelist; /**< page list */
- unsigned long byte_count;
+ drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
+ int buf_count; /**< total number of buffers */
+ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+ int seg_count;
+ int page_count; /**< number of pages */
+ unsigned long *pagelist; /**< page list */
+ unsigned long byte_count;
enum {
_DRM_DMA_USE_AGP = 0x01,
- _DRM_DMA_USE_SG = 0x02
+ _DRM_DMA_USE_SG = 0x02,
+ _DRM_DMA_USE_FB = 0x04
} flags;
} drm_device_dma_t;
-/**
+/**
* AGP memory entry. Stored as a doubly linked list.
*/
typedef struct drm_agp_mem {
- unsigned long handle; /**< handle */
- DRM_AGP_MEM *memory;
- unsigned long bound; /**< address */
- int pages;
+ unsigned long handle; /**< handle */
+ DRM_AGP_MEM *memory;
+ unsigned long bound; /**< address */
+ int pages;
struct drm_agp_mem *prev; /**< previous entry */
struct drm_agp_mem *next; /**< next entry */
} drm_agp_mem_t;
@@ -497,40 +464,47 @@ typedef struct drm_agp_mem {
* \sa drm_agp_init() and drm_device::agp.
*/
typedef struct drm_agp_head {
- DRM_AGP_KERN agp_info; /**< AGP device information */
- drm_agp_mem_t *memory; /**< memory entries */
- unsigned long mode; /**< AGP mode */
- struct agp_bridge_data *bridge;
- int enabled; /**< whether the AGP bus as been enabled */
- int acquired; /**< whether the AGP device has been acquired */
- unsigned long base;
- int agp_mtrr;
- int cant_use_aperture;
- unsigned long page_mask;
+ DRM_AGP_KERN agp_info; /**< AGP device information */
+ drm_agp_mem_t *memory; /**< memory entries */
+ unsigned long mode; /**< AGP mode */
+ struct agp_bridge_data *bridge;
+ int enabled; /**< whether the AGP bus as been enabled */
+ int acquired; /**< whether the AGP device has been acquired */
+ unsigned long base;
+ int agp_mtrr;
+ int cant_use_aperture;
+ unsigned long page_mask;
} drm_agp_head_t;
/**
* Scatter-gather memory.
*/
typedef struct drm_sg_mem {
- unsigned long handle;
- void *virtual;
- int pages;
- struct page **pagelist;
- dma_addr_t *busaddr;
+ unsigned long handle;
+ void *virtual;
+ int pages;
+ struct page **pagelist;
+ dma_addr_t *busaddr;
} drm_sg_mem_t;
typedef struct drm_sigdata {
- int context;
+ int context;
drm_hw_lock_t *lock;
} drm_sigdata_t;
+typedef struct drm_dma_handle {
+ dma_addr_t busaddr;
+ void *vaddr;
+ size_t size;
+} drm_dma_handle_t;
+
/**
* Mappings list
*/
typedef struct drm_map_list {
- struct list_head head; /**< list head */
- drm_map_t *map; /**< mapping */
+ struct list_head head; /**< list head */
+ drm_map_t *map; /**< mapping */
+ unsigned int user_token;
} drm_map_list_t;
typedef drm_map_t drm_local_map_t;
@@ -539,19 +513,28 @@ typedef drm_map_t drm_local_map_t;
* Context handle list
*/
typedef struct drm_ctx_list {
- struct list_head head; /**< list head */
- drm_context_t handle; /**< context handle */
- drm_file_t *tag; /**< associated fd private data */
+ struct list_head head; /**< list head */
+ drm_context_t handle; /**< context handle */
+ drm_file_t *tag; /**< associated fd private data */
} drm_ctx_list_t;
-
typedef struct drm_vbl_sig {
- struct list_head head;
- unsigned int sequence;
- struct siginfo info;
- struct task_struct *task;
+ struct list_head head;
+ unsigned int sequence;
+ struct siginfo info;
+ struct task_struct *task;
} drm_vbl_sig_t;
+/* location of GART table */
+#define DRM_ATI_GART_MAIN 1
+#define DRM_ATI_GART_FB 2
+
+typedef struct ati_pcigart_info {
+ int gart_table_location;
+ int is_pcie;
+ unsigned long addr;
+ dma_addr_t bus_addr;
+} drm_ati_pcigart_info;
/**
* DRM driver structure. This structure represent the common code for
@@ -561,34 +544,51 @@ typedef struct drm_vbl_sig {
struct drm_device;
struct drm_driver {
- int (*preinit)(struct drm_device *, unsigned long flags);
- void (*prerelease)(struct drm_device *, struct file *filp);
- void (*pretakedown)(struct drm_device *);
- int (*postcleanup)(struct drm_device *);
- int (*presetup)(struct drm_device *);
- int (*postsetup)(struct drm_device *);
- int (*dma_ioctl)( DRM_IOCTL_ARGS );
- int (*open_helper)(struct drm_device *, drm_file_t *);
- void (*free_filp_priv)(struct drm_device *, drm_file_t *);
- void (*release)(struct drm_device *, struct file *filp);
- void (*dma_ready)(struct drm_device *);
- int (*dma_quiescent)(struct drm_device *);
- int (*context_ctor)(struct drm_device *dev, int context);
- int (*context_dtor)(struct drm_device *dev, int context);
- int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
- void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
- int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+ int (*preinit) (struct drm_device *, unsigned long flags);
+ void (*prerelease) (struct drm_device *, struct file * filp);
+ void (*pretakedown) (struct drm_device *);
+ int (*postcleanup) (struct drm_device *);
+ int (*presetup) (struct drm_device *);
+ int (*postsetup) (struct drm_device *);
+ int (*dma_ioctl) (DRM_IOCTL_ARGS);
+ int (*open_helper) (struct drm_device *, drm_file_t *);
+ void (*free_filp_priv) (struct drm_device *, drm_file_t *);
+ void (*release) (struct drm_device *, struct file * filp);
+ void (*dma_ready) (struct drm_device *);
+ int (*dma_quiescent) (struct drm_device *);
+ int (*context_ctor) (struct drm_device * dev, int context);
+ int (*context_dtor) (struct drm_device * dev, int context);
+ int (*kernel_context_switch) (struct drm_device * dev, int old,
+ int new);
+ void (*kernel_context_switch_unlock) (struct drm_device * dev,
+ drm_lock_t * lock);
+ int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
+
+ /**
+ * Called by \c drm_device_is_agp. Typically used to determine if a
+ * card is really attached to AGP or not.
+ *
+ * \param dev DRM device handle
+ *
+ * \returns
+ * One of three values is returned depending on whether or not the
+ * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
+ * (return of 1), or may or may not be AGP (return of 2).
+ */
+ int (*device_is_agp) (struct drm_device * dev);
+
/* these have to be filled in */
- int (*postinit)(struct drm_device *, unsigned long flags);
- irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
- void (*irq_preinstall)(struct drm_device *dev);
- void (*irq_postinstall)(struct drm_device *dev);
- void (*irq_uninstall)(struct drm_device *dev);
- void (*reclaim_buffers)(struct drm_device *dev, struct file *filp);
- unsigned long (*get_map_ofs)(drm_map_t *map);
- unsigned long (*get_reg_ofs)(struct drm_device *dev);
- void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
- int (*version)(drm_version_t *version);
+
+ int (*postinit) (struct drm_device *, unsigned long flags);
+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ void (*irq_preinstall) (struct drm_device * dev);
+ void (*irq_postinstall) (struct drm_device * dev);
+ void (*irq_uninstall) (struct drm_device * dev);
+ void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
+ unsigned long (*get_map_ofs) (drm_map_t * map);
+ unsigned long (*get_reg_ofs) (struct drm_device * dev);
+ void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
+ int (*version) (drm_version_t * version);
u32 driver_features;
int dev_priv_size;
drm_ioctl_desc_t *ioctls;
@@ -615,131 +615,125 @@ typedef struct drm_head {
* may contain multiple heads.
*/
typedef struct drm_device {
- char *unique; /**< Unique identifier: e.g., busid */
- int unique_len; /**< Length of unique field */
- char *devname; /**< For /proc/interrupts */
- int if_version; /**< Highest interface version set */
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ char *devname; /**< For /proc/interrupts */
+ int if_version; /**< Highest interface version set */
- int blocked; /**< Blocked due to VC switch? */
+ int blocked; /**< Blocked due to VC switch? */
/** \name Locks */
- /*@{*/
- spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
- struct semaphore struct_sem; /**< For others */
- /*@}*/
+ /*@{ */
+ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+ struct semaphore struct_sem; /**< For others */
+ /*@} */
/** \name Usage Counters */
- /*@{*/
- int open_count; /**< Outstanding files open */
- atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
- atomic_t vma_count; /**< Outstanding vma areas open */
- int buf_use; /**< Buffers in use -- cannot alloc */
- atomic_t buf_alloc; /**< Buffer allocation in progress */
- /*@}*/
+ /*@{ */
+ int open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /**< Buffer allocation in progress */
+ /*@} */
/** \name Performance counters */
- /*@{*/
- unsigned long counters;
- drm_stat_type_t types[15];
- atomic_t counts[15];
- /*@}*/
+ /*@{ */
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
+ /*@} */
/** \name Authentication */
- /*@{*/
- drm_file_t *file_first; /**< file list head */
- drm_file_t *file_last; /**< file list tail */
- drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
- /*@}*/
+ /*@{ */
+ drm_file_t *file_first; /**< file list head */
+ drm_file_t *file_last; /**< file list tail */
+ drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
+ /*@} */
/** \name Memory management */
- /*@{*/
- drm_map_list_t *maplist; /**< Linked list of regions */
- int map_count; /**< Number of mappable regions */
+ /*@{ */
+ drm_map_list_t *maplist; /**< Linked list of regions */
+ int map_count; /**< Number of mappable regions */
/** \name Context handle management */
- /*@{*/
- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
- int ctx_count; /**< Number of context handles */
- struct semaphore ctxlist_sem; /**< For ctxlist */
+ /*@{ */
+ drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+ int ctx_count; /**< Number of context handles */
+ struct semaphore ctxlist_sem; /**< For ctxlist */
- drm_map_t **context_sareas; /**< per-context SAREA's */
- int max_context;
+ drm_map_t **context_sareas; /**< per-context SAREA's */
+ int max_context;
- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
- drm_lock_data_t lock; /**< Information on hardware lock */
- /*@}*/
+ drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+ drm_lock_data_t lock; /**< Information on hardware lock */
+ /*@} */
/** \name DMA queues (contexts) */
- /*@{*/
- int queue_count; /**< Number of active DMA queues */
- int queue_reserved; /**< Number of reserved DMA queues */
- int queue_slots; /**< Actual length of queuelist */
- drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
- drm_device_dma_t *dma; /**< Optional pointer for DMA support */
- /*@}*/
+ /*@{ */
+ int queue_count; /**< Number of active DMA queues */
+ int queue_reserved; /**< Number of reserved DMA queues */
+ int queue_slots; /**< Actual length of queuelist */
+ drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
+ drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+ /*@} */
/** \name Context support */
- /*@{*/
- int irq; /**< Interrupt used by board */
- int irq_enabled; /**< True if irq handler is enabled */
+ /*@{ */
+ int irq; /**< Interrupt used by board */
+ int irq_enabled; /**< True if irq handler is enabled */
__volatile__ long context_flag; /**< Context swapping flag */
__volatile__ long interrupt_flag; /**< Interruption handler flag */
__volatile__ long dma_flag; /**< DMA dispatch flag */
struct timer_list timer; /**< Timer for delaying ctx switch */
- wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
- int last_checked; /**< Last context checked for DMA */
- int last_context; /**< Last current context */
- unsigned long last_switch; /**< jiffies at last context switch */
- /*@}*/
-
- struct work_struct work;
+ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+ int last_checked; /**< Last context checked for DMA */
+ int last_context; /**< Last current context */
+ unsigned long last_switch; /**< jiffies at last context switch */
+ /*@} */
+
+ struct work_struct work;
/** \name VBLANK IRQ support */
- /*@{*/
-
- wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
- atomic_t vbl_received;
- spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
- unsigned int vbl_pending;
-
- /*@}*/
- cycles_t ctx_start;
- cycles_t lck_start;
-
- char buf[DRM_BSZ]; /**< Output buffer */
- char *buf_rp; /**< Read pointer */
- char *buf_wp; /**< Write pointer */
- char *buf_end; /**< End pointer */
+ /*@{ */
+
+ wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
+ atomic_t vbl_received;
+ spinlock_t vbl_lock;
+ drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
+ unsigned int vbl_pending;
+
+ /*@} */
+ cycles_t ctx_start;
+ cycles_t lck_start;
+
struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
wait_queue_head_t buf_readers; /**< Processes waiting to read */
wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
- drm_agp_head_t *agp; /**< AGP data */
+ drm_agp_head_t *agp; /**< AGP data */
- struct pci_dev *pdev; /**< PCI device structure */
- int pci_domain; /**< PCI bus domain number */
- int pci_bus; /**< PCI bus number */
- int pci_slot; /**< PCI slot number */
- int pci_func; /**< PCI function number */
+ struct pci_dev *pdev; /**< PCI device structure */
+ int pci_domain; /**< PCI bus domain number */
+ int pci_bus; /**< PCI bus number */
+ int pci_slot; /**< PCI slot number */
+ int pci_func; /**< PCI function number */
#ifdef __alpha__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
- struct pci_controler *hose;
-#else
struct pci_controller *hose;
#endif
-#endif
- drm_sg_mem_t *sg; /**< Scatter gather memory */
- unsigned long *ctx_bitmap; /**< context bitmap */
- void *dev_private; /**< device private data */
- drm_sigdata_t sigdata; /**< For block_all_signals */
- sigset_t sigmask;
-
- struct drm_driver *driver;
- drm_local_map_t *agp_buffer_map;
+ drm_sg_mem_t *sg; /**< Scatter gather memory */
+ unsigned long *ctx_bitmap; /**< context bitmap */
+ void *dev_private; /**< device private data */
+ drm_sigdata_t sigdata; /**< For block_all_signals */
+ sigset_t sigmask;
+
+ struct drm_driver *driver;
+ drm_local_map_t *agp_buffer_map;
+ unsigned int agp_buffer_token;
drm_head_t primary; /**< primary screen head */
} drm_device_t;
-static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
+static __inline__ int drm_core_check_feature(struct drm_device *dev,
+ int feature)
{
return ((dev->driver->driver_features & feature) ? 1 : 0);
}
@@ -747,7 +741,7 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature
#if __OS_HAS_AGP
static inline int drm_core_has_AGP(struct drm_device *dev)
{
- return drm_core_check_feature(dev, DRIVER_USE_AGP);
+ return drm_core_check_feature(dev, DRIVER_USE_AGP);
}
#else
#define drm_core_has_AGP(dev) (0)
@@ -756,7 +750,7 @@ static inline int drm_core_has_AGP(struct drm_device *dev)
#if __OS_HAS_MTRR
static inline int drm_core_has_MTRR(struct drm_device *dev)
{
- return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+ return drm_core_check_feature(dev, DRIVER_USE_MTRR);
}
#else
#define drm_core_has_MTRR(dev) (0)
@@ -767,221 +761,229 @@ static inline int drm_core_has_MTRR(struct drm_device *dev)
/*@{*/
/* Misc. support (drm_init.h) */
-extern int drm_flags;
-extern void drm_parse_options( char *s );
-extern int drm_cpu_valid( void );
+extern int drm_flags;
+extern void drm_parse_options(char *s);
+extern int drm_cpu_valid(void);
/* Driver support (drm_drv.h) */
-extern int drm_init(struct drm_driver *driver);
-extern void drm_exit(struct drm_driver *driver);
-extern int drm_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern long drm_compat_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_takedown(drm_device_t * dev);
+extern int drm_init(struct drm_driver *driver);
+extern void drm_exit(struct drm_driver *driver);
+extern int drm_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern long drm_compat_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_takedown(drm_device_t * dev);
/* Device support (drm_fops.h) */
-extern int drm_open(struct inode *inode, struct file *filp);
-extern int drm_stub_open(struct inode *inode, struct file *filp);
-extern int drm_flush(struct file *filp);
-extern int drm_fasync(int fd, struct file *filp, int on);
-extern int drm_release(struct inode *inode, struct file *filp);
+extern int drm_open(struct inode *inode, struct file *filp);
+extern int drm_stub_open(struct inode *inode, struct file *filp);
+extern int drm_flush(struct file *filp);
+extern int drm_fasync(int fd, struct file *filp, int on);
+extern int drm_release(struct inode *inode, struct file *filp);
/* Mapping support (drm_vm.h) */
-extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
-extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
+extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
+extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
/* Memory management support (drm_memory.h) */
#include "drm_memory.h"
-extern void drm_mem_init(void);
-extern int drm_mem_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size,
- int area);
+extern void drm_mem_init(void);
+extern int drm_mem_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
extern unsigned long drm_alloc_pages(int order, int area);
-extern void drm_free_pages(unsigned long address, int order,
- int area);
-extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev);
-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
- drm_device_t *dev);
-extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
-
-extern DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
-extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
-extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
-extern int drm_unbind_agp(DRM_AGP_MEM *handle);
+extern void drm_free_pages(unsigned long address, int order, int area);
+extern void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev);
+extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
+ drm_device_t * dev);
+extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
+
+extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
+extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
+extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+extern int drm_unbind_agp(DRM_AGP_MEM * handle);
/* Misc. IOCTL support (drm_ioctl.h) */
-extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_getunique(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_setunique(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_getmap(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_getclient(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_getstats(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_setversion(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getunique(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_setunique(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getmap(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getclient(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getstats(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_setversion(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Context IOCTL support (drm_context.h) */
-extern int drm_resctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_addctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_modctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_getctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_switchctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_newctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_rmctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-extern int drm_ctxbitmap_init( drm_device_t *dev );
-extern void drm_ctxbitmap_cleanup( drm_device_t *dev );
-extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle );
-
-extern int drm_setsareactx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_getsareactx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
+extern int drm_resctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_addctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_modctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_newctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_rmctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int drm_ctxbitmap_init(drm_device_t * dev);
+extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
+extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
+
+extern int drm_setsareactx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_getsareactx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Drawable IOCTL support (drm_drawable.h) */
-extern int drm_adddraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_rmdraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
+extern int drm_adddraw(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_rmdraw(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Authentication IOCTL support (drm_auth.h) */
-extern int drm_getmagic(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_authmagic(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+extern int drm_getmagic(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_authmagic(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
- /* Placeholder for ioctls past */
-extern int drm_noop(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+ /* Placeholder for ioctls past */
+extern int drm_noop(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Locking IOCTL support (drm_lock.h) */
-extern int drm_lock(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_unlock(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_lock_take(__volatile__ unsigned int *lock,
- unsigned int context);
-extern int drm_lock_free(drm_device_t *dev,
- __volatile__ unsigned int *lock,
- unsigned int context);
+extern int drm_lock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_unlock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context);
+extern int drm_lock_free(drm_device_t * dev,
+ __volatile__ unsigned int *lock, unsigned int context);
/* Buffer management support (drm_bufs.h) */
-extern int drm_order( unsigned long size );
-extern int drm_addmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_rmmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_addbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_infobufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_markbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_freebufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_mapbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
+extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
+extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
+extern int drm_addmap(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_local_map_t ** map_ptr);
+extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_rmmap(drm_device_t * dev, drm_local_map_t * map);
+extern int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map);
+extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int drm_order(unsigned long size);
+extern int drm_addbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_infobufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_markbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_freebufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_mapbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern unsigned long drm_get_resource_start(drm_device_t * dev,
+ unsigned int resource);
+extern unsigned long drm_get_resource_len(drm_device_t * dev,
+ unsigned int resource);
/* DMA support (drm_dma.h) */
-extern int drm_dma_setup(drm_device_t *dev);
-extern void drm_dma_takedown(drm_device_t *dev);
-extern void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
-extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
+extern int drm_dma_setup(drm_device_t * dev);
+extern void drm_dma_takedown(drm_device_t * dev);
+extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf);
+extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
/* IRQ support (drm_irq.h) */
-extern int drm_control( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int drm_irq_uninstall( drm_device_t *dev );
-extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS );
-extern void drm_driver_irq_preinstall( drm_device_t *dev );
-extern void drm_driver_irq_postinstall( drm_device_t *dev );
-extern void drm_driver_irq_uninstall( drm_device_t *dev );
-
-extern int drm_wait_vblank(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals( drm_device_t *dev );
+extern int drm_control(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_irq_uninstall(drm_device_t * dev);
+extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+extern void drm_driver_irq_preinstall(drm_device_t * dev);
+extern void drm_driver_irq_postinstall(drm_device_t * dev);
+extern void drm_driver_irq_uninstall(drm_device_t * dev);
+
+extern int drm_wait_vblank(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(drm_device_t * dev);
/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
-extern int drm_agp_acquire(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern void drm_agp_do_release(drm_device_t *dev);
-extern int drm_agp_release(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_enable(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_alloc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
-extern int drm_agp_free_memory(DRM_AGP_MEM *handle);
-extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
-extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
+extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
+extern int drm_agp_acquire(drm_device_t * dev);
+extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_release(drm_device_t * dev);
+extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode);
+extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);
+extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_unbind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_agp_bind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,
+ size_t pages, u32 type);
+extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
+extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
+extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
/* Stub support (drm_stub.h) */
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
- struct drm_driver *driver);
+ struct drm_driver *driver);
extern int drm_put_dev(drm_device_t * dev);
extern int drm_put_head(drm_head_t * head);
-extern unsigned int drm_debug;
-extern unsigned int drm_cards_limit;
+extern unsigned int drm_debug;
+extern unsigned int drm_cards_limit;
extern drm_head_t **drm_heads;
extern struct drm_sysfs_class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
/* Proc support (drm_proc.h) */
-extern int drm_proc_init(drm_device_t *dev,
- int minor,
- struct proc_dir_entry *root,
- struct proc_dir_entry **dev_root);
-extern int drm_proc_cleanup(int minor,
- struct proc_dir_entry *root,
- struct proc_dir_entry *dev_root);
+extern int drm_proc_init(drm_device_t * dev,
+ int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry **dev_root);
+extern int drm_proc_cleanup(int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry *dev_root);
/* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(drm_sg_mem_t *entry);
-extern int drm_sg_alloc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int drm_sg_free(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
- /* ATI PCIGART support (ati_pcigart.h) */
-extern int drm_ati_pcigart_init(drm_device_t *dev,
- unsigned long *addr,
- dma_addr_t *bus_addr);
-extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
- unsigned long addr,
- dma_addr_t bus_addr);
-
-extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
- size_t align, dma_addr_t maxaddr,
- dma_addr_t * busaddr);
-
-extern void drm_pci_free(drm_device_t * dev, size_t size,
- void *vaddr, dma_addr_t busaddr);
+extern void drm_sg_cleanup(drm_sg_mem_t * entry);
+extern int drm_sg_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_sg_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+ /* ATI PCIGART support (ati_pcigart.h) */
+extern int drm_ati_pcigart_init(drm_device_t * dev,
+ drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
+ drm_ati_pcigart_info * gart_info);
+
+extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+ size_t align, dma_addr_t maxaddr);
+extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
/* sysfs support (drm_sysfs.c) */
struct drm_sysfs_class;
@@ -994,35 +996,52 @@ extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
const char *fmt, ...);
extern void drm_sysfs_device_remove(dev_t dev);
-
/* Inline replacements for DRM_IOREMAP macros */
-static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+static __inline__ void drm_core_ioremap(struct drm_map *map,
+ struct drm_device *dev)
{
- map->handle = drm_ioremap( map->offset, map->size, dev );
+ map->handle = drm_ioremap(map->offset, map->size, dev);
}
-static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
+static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
+ struct drm_device *dev)
{
map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
}
-static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+static __inline__ void drm_core_ioremapfree(struct drm_map *map,
+ struct drm_device *dev)
{
- if ( map->handle && map->size )
- drm_ioremapfree( map->handle, map->size, dev );
+ if (map->handle && map->size)
+ drm_ioremapfree(map->handle, map->size, dev);
}
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
+ unsigned int token)
{
- struct list_head *_list;
- list_for_each( _list, &dev->maplist->head ) {
- drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
- if ( _entry->map &&
- _entry->map->offset == offset ) {
- return _entry->map;
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head)
+ if (_entry->user_token == token)
+ return _entry->map;
+ return NULL;
+}
+
+static __inline__ int drm_device_is_agp(drm_device_t * dev)
+{
+ if (dev->driver->device_is_agp != NULL) {
+ int err = (*dev->driver->device_is_agp) (dev);
+
+ if (err != 2) {
+ return err;
}
}
- return NULL;
+
+ return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
+}
+
+static __inline__ int drm_device_is_pcie(drm_device_t * dev)
+{
+ return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
}
static __inline__ void drm_core_dropmap(struct drm_map *map)
@@ -1055,8 +1074,12 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
/*@}*/
-extern unsigned long drm_core_get_map_ofs(drm_map_t *map);
+extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
-#endif /* __KERNEL__ */
+#ifndef pci_pretty_name
+#define pci_pretty_name(dev) ""
+#endif
+
+#endif /* __KERNEL__ */
#endif
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 8d94c0b5fa44..2b6453a9ffce 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -1,7 +1,7 @@
/**
- * \file drm_agpsupport.h
+ * \file drm_agpsupport.h
* DRM support for AGP/GART backend
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -37,7 +37,7 @@
#if __OS_HAS_AGP
/**
- * AGP information ioctl.
+ * Get AGP information.
*
* \param inode device inode.
* \param filp file pointer.
@@ -48,51 +48,57 @@
* Verifies the AGP device has been initialized and acquired and fills in the
* drm_agp_info structure with the information in drm_agp_head::agp_info.
*/
-int drm_agp_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- DRM_AGP_KERN *kern;
- drm_agp_info_t info;
+ DRM_AGP_KERN *kern;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- kern = &dev->agp->agp_info;
- info.agp_version_major = kern->version.major;
- info.agp_version_minor = kern->version.minor;
- info.mode = kern->mode;
- info.aperture_base = kern->aper_base;
- info.aperture_size = kern->aper_size * 1024 * 1024;
- info.memory_allowed = kern->max_memory << PAGE_SHIFT;
- info.memory_used = kern->current_memory << PAGE_SHIFT;
- info.id_vendor = kern->device->vendor;
- info.id_device = kern->device->device;
-
- if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info)))
+ kern = &dev->agp->agp_info;
+ info->agp_version_major = kern->version.major;
+ info->agp_version_minor = kern->version.minor;
+ info->mode = kern->mode;
+ info->aperture_base = kern->aper_base;
+ info->aperture_size = kern->aper_size * 1024 * 1024;
+ info->memory_allowed = kern->max_memory << PAGE_SHIFT;
+ info->memory_used = kern->current_memory << PAGE_SHIFT;
+ info->id_vendor = kern->device->vendor;
+ info->id_device = kern->device->device;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(drm_agp_info);
+
+int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_info_t info;
+ int err;
+
+ err = drm_agp_info(dev, &info);
+ if (err)
+ return err;
+
+ if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
return -EFAULT;
return 0;
}
/**
- * Acquire the AGP device (ioctl).
+ * Acquire the AGP device.
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or a negative number on failure.
+ * \param dev DRM device that is to acquire AGP
+ * \return zero on success or a negative number on failure.
*
* Verifies the AGP device hasn't been acquired before and calls
- * agp_acquire().
+ * \c agp_backend_acquire.
*/
-int drm_agp_acquire(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_acquire(drm_device_t * dev)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
-
if (!dev->agp)
return -ENODEV;
if (dev->agp->acquired)
@@ -103,8 +109,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
return 0;
}
+EXPORT_SYMBOL(drm_agp_acquire);
+
/**
- * Release the AGP device (ioctl).
+ * Acquire the AGP device (ioctl).
*
* \param inode device inode.
* \param filp file pointer.
@@ -112,64 +120,82 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
* \param arg user argument.
* \return zero on success or a negative number on failure.
*
- * Verifies the AGP device has been acquired and calls agp_backend_release().
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
*/
-int drm_agp_release(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ return drm_agp_acquire((drm_device_t *) priv->head->dev);
+}
+
+/**
+ * Release the AGP device.
+ *
+ * \param dev DRM device that is to release AGP
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
+int drm_agp_release(drm_device_t * dev)
+{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
-
}
-/**
- * Release the AGP device.
- *
- * Calls agp_backend_release().
- */
-void drm_agp_do_release(drm_device_t *dev)
+EXPORT_SYMBOL(drm_agp_release);
+
+int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- agp_backend_release(dev->agp->bridge);
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+
+ return drm_agp_release(dev);
}
/**
* Enable the AGP bus.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_agp_mode structure.
+ *
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
* \return zero on success or a negative number on failure.
*
* Verifies the AGP device has been acquired but not enabled, and calls
- * agp_enable().
+ * \c agp_enable.
*/
-int drm_agp_enable(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_mode_t mode;
-
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode)))
- return -EFAULT;
-
- dev->agp->mode = mode.mode;
+ dev->agp->mode = mode.mode;
agp_enable(dev->agp->bridge, mode.mode);
- dev->agp->base = dev->agp->agp_info.aper_base;
+ dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1;
return 0;
}
+EXPORT_SYMBOL(drm_agp_enable);
+
+int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_mode_t mode;
+
+ if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+ return -EFAULT;
+
+ return drm_agp_enable(dev, mode);
+}
+
/**
* Allocate AGP memory.
*
@@ -178,20 +204,20 @@ int drm_agp_enable(struct inode *inode, struct file *filp,
* \param cmd command.
* \param arg pointer to a drm_agp_buffer structure.
* \return zero on success or a negative number on failure.
- *
+ *
* Verifies the AGP device is present and has been acquired, allocates the
* memory via alloc_agp() and creates a drm_agp_mem entry for it.
*/
int drm_agp_alloc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
- drm_agp_mem_t *entry;
- DRM_AGP_MEM *memory;
- unsigned long pages;
- u32 type;
+ drm_agp_mem_t *entry;
+ DRM_AGP_MEM *memory;
+ unsigned long pages;
+ u32 type;
drm_agp_buffer_t __user *argp = (void __user *)arg;
if (!dev->agp || !dev->agp->acquired)
@@ -201,31 +227,31 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
return -ENOMEM;
- memset(entry, 0, sizeof(*entry));
+ memset(entry, 0, sizeof(*entry));
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request.type;
- if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
+ if (!(memory = drm_alloc_agp(dev, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM;
}
- entry->handle = (unsigned long)memory->key + 1;
- entry->memory = memory;
- entry->bound = 0;
- entry->pages = pages;
- entry->prev = NULL;
- entry->next = dev->agp->memory;
+ entry->handle = (unsigned long)memory->key + 1;
+ entry->memory = memory;
+ entry->bound = 0;
+ entry->pages = pages;
+ entry->prev = NULL;
+ entry->next = dev->agp->memory;
if (dev->agp->memory)
dev->agp->memory->prev = entry;
dev->agp->memory = entry;
- request.handle = entry->handle;
+ request.handle = entry->handle;
request.physical = memory->physical;
if (copy_to_user(argp, &request, sizeof(request))) {
- dev->agp->memory = entry->next;
+ dev->agp->memory = entry->next;
dev->agp->memory->prev = NULL;
drm_free_agp(memory, pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
@@ -240,11 +266,11 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
* \param dev DRM device structure.
* \param handle AGP memory handle.
* \return pointer to the drm_agp_mem structure associated with \p handle.
- *
+ *
* Walks through drm_agp_head::memory until finding a matching handle.
*/
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
- unsigned long handle)
+static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
+ unsigned long handle)
{
drm_agp_mem_t *entry;
@@ -268,17 +294,18 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
* entry and passes it to the unbind_agp() function.
*/
int drm_agp_unbind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
- drm_agp_mem_t *entry;
+ drm_agp_mem_t *entry;
int ret;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
@@ -286,7 +313,7 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
return -EINVAL;
ret = drm_unbind_agp(entry->memory);
if (ret == 0)
- entry->bound = 0;
+ entry->bound = 0;
return ret;
}
@@ -304,18 +331,19 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
* it to bind_agp() function.
*/
int drm_agp_bind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
- drm_agp_mem_t *entry;
- int retcode;
- int page;
+ drm_agp_mem_t *entry;
+ int retcode;
+ int page;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
@@ -345,16 +373,17 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
* and unlinks from the doubly linked list it's inserted in.
*/
int drm_agp_free(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
- drm_agp_mem_t *entry;
+ drm_agp_mem_t *entry;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&request, (drm_agp_buffer_t __user *)arg, sizeof(request)))
+ if (copy_from_user
+ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
@@ -380,9 +409,9 @@ int drm_agp_free(struct inode *inode, struct file *filp,
* \return pointer to a drm_agp_head structure.
*
*/
-drm_agp_head_t *drm_agp_init(drm_device_t *dev)
+drm_agp_head_t *drm_agp_init(drm_device_t * dev)
{
- drm_agp_head_t *head = NULL;
+ drm_agp_head_t *head = NULL;
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
return NULL;
@@ -403,25 +432,21 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
return NULL;
}
head->memory = NULL;
-#if LINUX_VERSION_CODE <= 0x020408
- head->cant_use_aperture = 0;
- head->page_mask = ~(0xfff);
-#else
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
-#endif
return head;
}
/** Calls agp_allocate_memory() */
-DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
+DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
+ size_t pages, u32 type)
{
return agp_allocate_memory(bridge, pages, type);
}
/** Calls agp_free_memory() */
-int drm_agp_free_memory(DRM_AGP_MEM *handle)
+int drm_agp_free_memory(DRM_AGP_MEM * handle)
{
if (!handle)
return 0;
@@ -430,19 +455,21 @@ int drm_agp_free_memory(DRM_AGP_MEM *handle)
}
/** Calls agp_bind_memory() */
-int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
+int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
{
if (!handle)
return -EINVAL;
return agp_bind_memory(handle, start);
}
+EXPORT_SYMBOL(drm_agp_bind_memory);
+
/** Calls agp_unbind_memory() */
-int drm_agp_unbind_memory(DRM_AGP_MEM *handle)
+int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
{
if (!handle)
return -EINVAL;
return agp_unbind_memory(handle);
}
-#endif /* __OS_HAS_AGP */
+#endif /* __OS_HAS_AGP */
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index dd140bca8f71..a47b502bc7cc 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -1,5 +1,5 @@
/**
- * \file drm_auth.h
+ * \file drm_auth.c
* IOCTLs for authentication
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -46,7 +46,7 @@
*/
static int drm_hash_magic(drm_magic_t magic)
{
- return magic & (DRM_HASH_SIZE-1);
+ return magic & (DRM_HASH_SIZE - 1);
}
/**
@@ -59,11 +59,11 @@ static int drm_hash_magic(drm_magic_t magic)
* the one with matching magic number, while holding the drm_device::struct_sem
* lock.
*/
-static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
+static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
{
- drm_file_t *retval = NULL;
+ drm_file_t *retval = NULL;
drm_magic_entry_t *pt;
- int hash = drm_hash_magic(magic);
+ int hash = drm_hash_magic(magic);
down(&dev->struct_sem);
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
@@ -78,7 +78,7 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
/**
* Adds a magic number.
- *
+ *
* \param dev DRM device.
* \param priv file private data.
* \param magic magic number.
@@ -87,28 +87,30 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
* associated the magic number hash key in drm_device::magiclist, while holding
* the drm_device::struct_sem lock.
*/
-static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
+static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
+ drm_magic_t magic)
{
- int hash;
+ int hash;
drm_magic_entry_t *entry;
DRM_DEBUG("%d\n", magic);
- hash = drm_hash_magic(magic);
- entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
- if (!entry) return -ENOMEM;
+ hash = drm_hash_magic(magic);
+ entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
+ if (!entry)
+ return -ENOMEM;
memset(entry, 0, sizeof(*entry));
entry->magic = magic;
- entry->priv = priv;
- entry->next = NULL;
+ entry->priv = priv;
+ entry->next = NULL;
down(&dev->struct_sem);
if (dev->magiclist[hash].tail) {
dev->magiclist[hash].tail->next = entry;
- dev->magiclist[hash].tail = entry;
+ dev->magiclist[hash].tail = entry;
} else {
- dev->magiclist[hash].head = entry;
- dev->magiclist[hash].tail = entry;
+ dev->magiclist[hash].head = entry;
+ dev->magiclist[hash].tail = entry;
}
up(&dev->struct_sem);
@@ -117,19 +119,18 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
/**
* Remove a magic number.
- *
+ *
* \param dev DRM device.
* \param magic magic number.
*
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_sem lock.
*/
-static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
+static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
{
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
- int hash;
-
+ int hash;
DRM_DEBUG("%d\n", magic);
hash = drm_hash_magic(magic);
@@ -171,21 +172,22 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
* filp.
*/
int drm_getmagic(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
static drm_magic_t sequence = 0;
static DEFINE_SPINLOCK(lock);
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_auth_t auth;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_auth_t auth;
- /* Find unique magic */
+ /* Find unique magic */
if (priv->magic) {
auth.magic = priv->magic;
} else {
do {
spin_lock(&lock);
- if (!sequence) ++sequence; /* reserve 0 */
+ if (!sequence)
+ ++sequence; /* reserve 0 */
auth.magic = sequence++;
spin_unlock(&lock);
} while (drm_find_file(dev, auth.magic));
@@ -194,7 +196,7 @@ int drm_getmagic(struct inode *inode, struct file *filp,
}
DRM_DEBUG("%u\n", auth.magic);
- if (copy_to_user((drm_auth_t __user *)arg, &auth, sizeof(auth)))
+ if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
return -EFAULT;
return 0;
}
@@ -211,14 +213,14 @@ int drm_getmagic(struct inode *inode, struct file *filp,
* Checks if \p filp is associated with the magic number passed in \arg.
*/
int drm_authmagic(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_auth_t auth;
- drm_file_t *file;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_auth_t auth;
+ drm_file_t *file;
- if (copy_from_user(&auth, (drm_auth_t __user *)arg, sizeof(auth)))
+ if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
return -EFAULT;
DRM_DEBUG("%u\n", auth.magic);
if ((file = drm_find_file(dev, auth.magic))) {
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 4c6191d231b8..319bdea8de8a 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -1,7 +1,7 @@
/**
- * \file drm_bufs.h
+ * \file drm_bufs.c
* Generic buffer template
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -36,37 +36,72 @@
#include <linux/vmalloc.h>
#include "drmP.h"
-/**
- * Compute size order. Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- *
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order( unsigned long size )
+unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)
{
- int order;
- unsigned long tmp;
+ return pci_resource_start(dev->pdev, resource);
+}
- for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
- ;
+EXPORT_SYMBOL(drm_get_resource_start);
- if (size & (size - 1))
- ++order;
+unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)
+{
+ return pci_resource_len(dev->pdev, resource);
+}
- return order;
+EXPORT_SYMBOL(drm_get_resource_len);
+
+static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
+ drm_local_map_t * map)
+{
+ struct list_head *list;
+
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+ if (entry->map && map->type == entry->map->type &&
+ entry->map->offset == map->offset) {
+ return entry;
+ }
+ }
+
+ return NULL;
}
-EXPORT_SYMBOL(drm_order);
-#ifdef CONFIG_COMPAT
/*
- * Used to allocate 32-bit handles for _DRM_SHM regions
- * The 0x10000000 value is chosen to be out of the way of
- * FB/register and GART physical addresses.
+ * Used to allocate 32-bit handles for mappings.
*/
-static unsigned int map32_handle = 0x10000000;
+#define START_RANGE 0x10000000
+#define END_RANGE 0x40000000
+
+#ifdef _LP64
+static __inline__ unsigned int HandleID(unsigned long lhandle,
+ drm_device_t * dev)
+{
+ static unsigned int map32_handle = START_RANGE;
+ unsigned int hash;
+
+ if (lhandle & 0xffffffff00000000) {
+ hash = map32_handle;
+ map32_handle += PAGE_SIZE;
+ if (map32_handle > END_RANGE)
+ map32_handle = START_RANGE;
+ } else
+ hash = lhandle;
+
+ while (1) {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->user_token == hash)
+ break;
+ }
+ if (&_entry->head == &dev->maplist->head)
+ return hash;
+
+ hash += PAGE_SIZE;
+ map32_handle += PAGE_SIZE;
+ }
+}
+#else
+# define HandleID(x,dev) (unsigned int)(x)
#endif
/**
@@ -82,86 +117,100 @@ static unsigned int map32_handle = 0x10000000;
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel.
*/
-int drm_addmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_map_list_t ** maplist)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_map_t *map;
- drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list;
+ drm_dma_handle_t *dmah;
- if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
-
- map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
- if ( !map )
+ map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
+ if (!map)
return -ENOMEM;
- if ( copy_from_user( map, argp, sizeof(*map) ) ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
- return -EFAULT;
- }
+ map->offset = offset;
+ map->size = size;
+ map->flags = flags;
+ map->type = type;
/* Only allow shared memory to be removable since we only keep enough
* book keeping information about shared memory to allow for removal
* when processes fork.
*/
- if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+ if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
- DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
- map->offset, map->size, map->type );
- if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ map->offset, map->size, map->type);
+ if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
- map->mtrr = -1;
+ map->mtrr = -1;
map->handle = NULL;
- switch ( map->type ) {
+ switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
- if ( map->offset + map->size < map->offset ||
- map->offset < virt_to_phys(high_memory) ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
+ if (map->offset + map->size < map->offset ||
+ map->offset < virt_to_phys(high_memory)) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
#endif
#ifdef __alpha__
map->offset += dev->hose->mem_space->start;
#endif
+ /* Some drivers preinitialize some maps, without the X Server
+ * needing to be aware of it. Therefore, we just return success
+ * when the server tries to create a duplicate map.
+ */
+ list = drm_find_matching_map(dev, map);
+ if (list != NULL) {
+ if (list->map->size != map->size) {
+ DRM_DEBUG("Matching maps of type %d with "
+ "mismatched sizes, (%ld vs %ld)\n",
+ map->type, map->size,
+ list->map->size);
+ list->map->size = map->size;
+ }
+
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ *maplist = list;
+ return 0;
+ }
+
if (drm_core_has_MTRR(dev)) {
- if ( map->type == _DRM_FRAME_BUFFER ||
- (map->flags & _DRM_WRITE_COMBINING) ) {
- map->mtrr = mtrr_add( map->offset, map->size,
- MTRR_TYPE_WRCOMB, 1 );
+ if (map->type == _DRM_FRAME_BUFFER ||
+ (map->flags & _DRM_WRITE_COMBINING)) {
+ map->mtrr = mtrr_add(map->offset, map->size,
+ MTRR_TYPE_WRCOMB, 1);
}
}
if (map->type == _DRM_REGISTERS)
- map->handle = drm_ioremap( map->offset, map->size,
- dev );
+ map->handle = drm_ioremap(map->offset, map->size, dev);
break;
case _DRM_SHM:
map->handle = vmalloc_32(map->size);
- DRM_DEBUG( "%lu %d %p\n",
- map->size, drm_order( map->size ), map->handle );
- if ( !map->handle ) {
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_DEBUG("%lu %d %p\n",
+ map->size, drm_order(map->size), map->handle);
+ if (!map->handle) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -ENOMEM;
}
map->offset = (unsigned long)map->handle;
- if ( map->flags & _DRM_CONTAINS_LOCK ) {
+ if (map->flags & _DRM_CONTAINS_LOCK) {
/* Prevent a 2nd X Server from creating a 2nd lock */
if (dev->lock.hw_lock != NULL) {
- vfree( map->handle );
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+ vfree(map->handle);
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EBUSY;
}
- dev->sigdata.lock =
- dev->lock.hw_lock = map->handle; /* Pointer to lock */
+ dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */
}
break;
case _DRM_AGP:
@@ -170,7 +219,7 @@ int drm_addmap( struct inode *inode, struct file *filp,
map->offset += dev->hose->mem_space->start;
#endif
map->offset += dev->agp->base;
- map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+ map->mtrr = dev->agp->agp_mtrr; /* for getmap */
}
break;
case _DRM_SCATTER_GATHER:
@@ -178,16 +227,29 @@ int drm_addmap( struct inode *inode, struct file *filp,
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
- map->offset += dev->sg->handle;
+ map->offset += (unsigned long)dev->sg->virtual;
+ break;
+ case _DRM_CONSISTENT:
+ /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+ * As we're limiting the address to 2^32-1 (or less),
+ * casting it down to 32 bits is no problem, but we
+ * need to point to a 64bit variable first. */
+ dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+ if (!dmah) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+ map->handle = dmah->vaddr;
+ map->offset = (unsigned long)dmah->busaddr;
+ kfree(dmah);
break;
-
default:
- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
- if(!list) {
+ if (!list) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
@@ -196,22 +258,64 @@ int drm_addmap( struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_add(&list->head, &dev->maplist->head);
-#ifdef CONFIG_COMPAT
- /* Assign a 32-bit handle for _DRM_SHM mappings */
+ /* Assign a 32-bit handle */
/* We do it here so that dev->struct_sem protects the increment */
- if (map->type == _DRM_SHM)
- map->offset = map32_handle += PAGE_SIZE;
-#endif
- up(&dev->struct_sem);
+ list->user_token = HandleID(map->type == _DRM_SHM
+ ? (unsigned long)map->handle
+ : map->offset, dev);
+ up(&dev->struct_sem);
+
+ *maplist = list;
+ return 0;
+}
+
+int drm_addmap(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+ drm_map_flags_t flags, drm_local_map_t ** map_ptr)
+{
+ drm_map_list_t *list;
+ int rc;
+
+ rc = drm_addmap_core(dev, offset, size, type, flags, &list);
+ if (!rc)
+ *map_ptr = list->map;
+ return rc;
+}
+
+EXPORT_SYMBOL(drm_addmap);
- if ( copy_to_user( argp, map, sizeof(*map) ) )
+int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_map_t map;
+ drm_map_list_t *maplist;
+ drm_map_t __user *argp = (void __user *)arg;
+ int err;
+
+ if (!(filp->f_mode & 3))
+ return -EACCES; /* Require read/write */
+
+ if (copy_from_user(&map, argp, sizeof(map))) {
return -EFAULT;
- if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
+ }
+
+ err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
+ &maplist);
+
+ if (err)
+ return err;
+
+ if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+ return -EFAULT;
+
+ /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
+ if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle))
return -EFAULT;
return 0;
}
-
/**
* Remove a map private from list and deallocate resources if the mapping
* isn't in use.
@@ -226,86 +330,144 @@ int drm_addmap( struct inode *inode, struct file *filp,
* its being used, and free any associate resource (such as MTRR's) if it's not
* being on use.
*
- * \sa addmap().
+ * \sa drm_addmap
*/
-int drm_rmmap(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
struct list_head *list;
drm_map_list_t *r_list = NULL;
- drm_vma_entry_t *pt, *prev;
- drm_map_t *map;
+ drm_dma_handle_t dmah;
+
+ /* Find the list entry for the map and remove it */
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+
+ if (r_list->map == map) {
+ list_del(list);
+ drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+ break;
+ }
+ }
+
+ /* List has wrapped around to the head pointer, or it's empty and we
+ * didn't find anything.
+ */
+ if (list == (&dev->maplist->head)) {
+ return -EINVAL;
+ }
+
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ drm_ioremapfree(map->handle, map->size, dev);
+ /* FALLTHROUGH */
+ case _DRM_FRAME_BUFFER:
+ if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+ int retcode;
+ retcode = mtrr_del(map->mtrr, map->offset, map->size);
+ DRM_DEBUG("mtrr_del=%d\n", retcode);
+ }
+ break;
+ case _DRM_SHM:
+ vfree(map->handle);
+ break;
+ case _DRM_AGP:
+ case _DRM_SCATTER_GATHER:
+ break;
+ case _DRM_CONSISTENT:
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ __drm_pci_free(dev, &dmah);
+ break;
+ }
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(drm_rmmap_locked);
+
+int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
+{
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_rmmap_locked(dev, map);
+ up(&dev->struct_sem);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(drm_rmmap);
+
+/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
+ * the last close of the device, and this is necessary for cleanup when things
+ * exit uncleanly. Therefore, having userland manually remove mappings seems
+ * like a pointless exercise since they're going away anyway.
+ *
+ * One use case might be after addmap is allowed for normal users for SHM and
+ * gets used by drivers that the server doesn't need to care about. This seems
+ * unlikely.
+ */
+int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_map_t request;
- int found_maps = 0;
+ drm_local_map_t *map = NULL;
+ struct list_head *list;
+ int ret;
- if (copy_from_user(&request, (drm_map_t __user *)arg,
- sizeof(request))) {
+ if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
return -EFAULT;
}
down(&dev->struct_sem);
- list = &dev->maplist->head;
list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
- if(r_list->map &&
- r_list->map->offset == (unsigned long) request.handle &&
- r_list->map->flags & _DRM_REMOVABLE) break;
+ if (r_list->map &&
+ r_list->user_token == (unsigned long)request.handle &&
+ r_list->map->flags & _DRM_REMOVABLE) {
+ map = r_list->map;
+ break;
+ }
}
/* List has wrapped around to the head pointer, or its empty we didn't
* find anything.
*/
- if(list == (&dev->maplist->head)) {
+ if (list == (&dev->maplist->head)) {
up(&dev->struct_sem);
return -EINVAL;
}
- map = r_list->map;
- list_del(list);
- drm_free(list, sizeof(*list), DRM_MEM_MAPS);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
- if (pt->vma->vm_private_data == map) found_maps++;
- }
+ if (!map)
+ return -EINVAL;
- if(!found_maps) {
- switch (map->type) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev)) {
- if (map->mtrr >= 0) {
- int retcode;
- retcode = mtrr_del(map->mtrr,
- map->offset,
- map->size);
- DRM_DEBUG("mtrr_del = %d\n", retcode);
- }
- }
- drm_ioremapfree(map->handle, map->size, dev);
- break;
- case _DRM_SHM:
- vfree(map->handle);
- break;
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- break;
- }
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ /* Register and framebuffer maps are permanent */
+ if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+ up(&dev->struct_sem);
+ return 0;
}
+
+ ret = drm_rmmap_locked(dev, map);
+
up(&dev->struct_sem);
- return 0;
+
+ return ret;
}
/**
* Cleanup after an error on one of the addbufs() functions.
*
+ * \param dev DRM device.
* \param entry buffer entry where the error occurred.
*
* Frees any pages and buffers associated with the given entry.
*/
-static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
+static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
{
int i;
@@ -313,30 +475,27 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
for (i = 0; i < entry->seg_count; i++) {
if (entry->seglist[i]) {
drm_free_pages(entry->seglist[i],
- entry->page_order,
- DRM_MEM_DMA);
+ entry->page_order, DRM_MEM_DMA);
}
}
drm_free(entry->seglist,
- entry->seg_count *
- sizeof(*entry->seglist),
- DRM_MEM_SEGS);
+ entry->seg_count *
+ sizeof(*entry->seglist), DRM_MEM_SEGS);
entry->seg_count = 0;
}
- if (entry->buf_count) {
- for (i = 0; i < entry->buf_count; i++) {
+ if (entry->buf_count) {
+ for (i = 0; i < entry->buf_count; i++) {
if (entry->buflist[i].dev_private) {
drm_free(entry->buflist[i].dev_private,
- entry->buflist[i].dev_priv_size,
- DRM_MEM_BUFS);
+ entry->buflist[i].dev_priv_size,
+ DRM_MEM_BUFS);
}
}
drm_free(entry->buflist,
- entry->buf_count *
- sizeof(*entry->buflist),
- DRM_MEM_BUFS);
+ entry->buf_count *
+ sizeof(*entry->buflist), DRM_MEM_BUFS);
entry->buf_count = 0;
}
@@ -344,25 +503,19 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
#if __OS_HAS_AGP
/**
- * Add AGP buffers for DMA transfers (ioctl).
+ * Add AGP buffers for DMA transfers.
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param dev drm_device_t to which the buffers are to be added.
+ * \param request pointer to a drm_buf_desc_t describing the request.
* \return zero on success or a negative number on failure.
- *
+ *
* After some sanity checks creates a drm_buf structure for each buffer and
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
-static int drm_addbufs_agp( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
drm_buf_entry_t *entry;
drm_buf_t *buf;
unsigned long offset;
@@ -376,158 +529,148 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp,
int byte_count;
int i;
drm_buf_t **temp_buflist;
- drm_buf_desc_t __user *argp = (void __user *)arg;
- if ( !dma ) return -EINVAL;
-
- if ( copy_from_user( &request, argp,
- sizeof(request) ) )
- return -EFAULT;
+ if (!dma)
+ return -EINVAL;
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
- alignment = (request.flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
- agp_offset = dev->agp->base + request.agp_start;
-
- DRM_DEBUG( "count: %d\n", count );
- DRM_DEBUG( "order: %d\n", order );
- DRM_DEBUG( "size: %d\n", size );
- DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
- DRM_DEBUG( "alignment: %d\n", alignment );
- DRM_DEBUG( "page_order: %d\n", page_order );
- DRM_DEBUG( "total: %d\n", total );
-
- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
-
- spin_lock( &dev->count_lock );
- if ( dev->buf_use ) {
- spin_unlock( &dev->count_lock );
+ agp_offset = dev->agp->base + request->agp_start;
+
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ if (dev->queue_count)
+ return -EBUSY; /* Not while in use */
+
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
return -EBUSY;
}
- atomic_inc( &dev->buf_alloc );
- spin_unlock( &dev->count_lock );
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
- down( &dev->struct_sem );
+ down(&dev->struct_sem);
entry = &dma->bufs[order];
- if ( entry->buf_count ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
- return -ENOMEM; /* May only call once for each order */
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
- DRM_MEM_BUFS );
- if ( !entry->buflist ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
entry->buf_size = size;
entry->page_order = page_order;
offset = 0;
- while ( entry->buf_count < count ) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
+ while (entry->buf_count < count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
- buf->offset = (dma->byte_count + offset);
+ buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
buf->address = (void *)(agp_offset + offset);
- buf->next = NULL;
+ buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
- init_waitqueue_head( &buf->dma_wait );
- buf->filp = NULL;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->filp = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc( buf->dev_priv_size,
- DRM_MEM_BUFS );
- if(!buf->dev_private) {
+ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
- drm_cleanup_buf_error(dev,entry);
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( buf->dev_private, 0, buf->dev_priv_size );
+ memset(buf->dev_private, 0, buf->dev_priv_size);
- DRM_DEBUG( "buffer %d @ %p\n",
- entry->buf_count, buf->address );
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
offset += alignment;
entry->buf_count++;
byte_count += PAGE_SIZE << page_order;
}
- DRM_DEBUG( "byte_count: %d\n", byte_count );
+ DRM_DEBUG("byte_count: %d\n", byte_count);
- temp_buflist = drm_realloc( dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist),
- DRM_MEM_BUFS );
- if(!temp_buflist) {
+ temp_buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ if (!temp_buflist) {
/* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev,entry);
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
dma->buflist = temp_buflist;
- for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ for (i = 0; i < entry->buf_count; i++) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
dma->buf_count += entry->buf_count;
dma->byte_count += byte_count;
- DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
- DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
-
- up( &dev->struct_sem );
+ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- request.count = entry->buf_count;
- request.size = size;
+ up(&dev->struct_sem);
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
dma->flags = _DRM_DMA_USE_AGP;
- atomic_dec( &dev->buf_alloc );
+ atomic_dec(&dev->buf_alloc);
return 0;
}
-#endif /* __OS_HAS_AGP */
-static int drm_addbufs_pci( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+EXPORT_SYMBOL(drm_addbufs_agp);
+#endif /* __OS_HAS_AGP */
+
+int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
int count;
int order;
int size;
@@ -543,183 +686,175 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
int page_count;
unsigned long *temp_pagelist;
drm_buf_t **temp_buflist;
- drm_buf_desc_t __user *argp = (void __user *)arg;
- if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
- if ( !dma ) return -EINVAL;
-
- if ( copy_from_user( &request, argp, sizeof(request) ) )
- return -EFAULT;
+ if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
+ return -EINVAL;
+ if (!dma)
+ return -EINVAL;
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
- DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
- request.count, request.size, size,
- order, dev->queue_count );
+ DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+ request->count, request->size, size, order, dev->queue_count);
- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ if (dev->queue_count)
+ return -EBUSY; /* Not while in use */
- alignment = (request.flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
- spin_lock( &dev->count_lock );
- if ( dev->buf_use ) {
- spin_unlock( &dev->count_lock );
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
return -EBUSY;
}
- atomic_inc( &dev->buf_alloc );
- spin_unlock( &dev->count_lock );
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
- down( &dev->struct_sem );
+ down(&dev->struct_sem);
entry = &dma->bufs[order];
- if ( entry->buf_count ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
- DRM_MEM_BUFS );
- if ( !entry->buflist ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
-
- entry->seglist = drm_alloc( count * sizeof(*entry->seglist),
- DRM_MEM_SEGS );
- if ( !entry->seglist ) {
- drm_free( entry->buflist,
- count * sizeof(*entry->buflist),
- DRM_MEM_BUFS );
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
+ DRM_MEM_SEGS);
+ if (!entry->seglist) {
+ drm_free(entry->buflist,
+ count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
+ memset(entry->seglist, 0, count * sizeof(*entry->seglist));
/* Keep the original pagelist until we know all the allocations
* have succeeded
*/
- temp_pagelist = drm_alloc( (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES );
+ temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
if (!temp_pagelist) {
- drm_free( entry->buflist,
- count * sizeof(*entry->buflist),
- DRM_MEM_BUFS );
- drm_free( entry->seglist,
- count * sizeof(*entry->seglist),
- DRM_MEM_SEGS );
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_free(entry->buflist,
+ count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+ drm_free(entry->seglist,
+ count * sizeof(*entry->seglist), DRM_MEM_SEGS);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
memcpy(temp_pagelist,
- dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist));
- DRM_DEBUG( "pagelist: %d entries\n",
- dma->page_count + (count << page_order) );
+ dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
+ DRM_DEBUG("pagelist: %d entries\n",
+ dma->page_count + (count << page_order));
- entry->buf_size = size;
+ entry->buf_size = size;
entry->page_order = page_order;
byte_count = 0;
page_count = 0;
- while ( entry->buf_count < count ) {
- page = drm_alloc_pages( page_order, DRM_MEM_DMA );
- if ( !page ) {
+ while (entry->buf_count < count) {
+ page = drm_alloc_pages(page_order, DRM_MEM_DMA);
+ if (!page) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
- drm_free( temp_pagelist,
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES );
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_free(temp_pagelist,
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
entry->seglist[entry->seg_count++] = page;
- for ( i = 0 ; i < (1 << page_order) ; i++ ) {
- DRM_DEBUG( "page %d @ 0x%08lx\n",
- dma->page_count + page_count,
- page + PAGE_SIZE * i );
+ for (i = 0; i < (1 << page_order); i++) {
+ DRM_DEBUG("page %d @ 0x%08lx\n",
+ dma->page_count + page_count,
+ page + PAGE_SIZE * i);
temp_pagelist[dma->page_count + page_count++]
- = page + PAGE_SIZE * i;
+ = page + PAGE_SIZE * i;
}
- for ( offset = 0 ;
- offset + size <= total && entry->buf_count < count ;
- offset += alignment, ++entry->buf_count ) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
- buf->offset = (dma->byte_count + byte_count + offset);
+ for (offset = 0;
+ offset + size <= total && entry->buf_count < count;
+ offset += alignment, ++entry->buf_count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+ buf->offset = (dma->byte_count + byte_count + offset);
buf->address = (void *)(page + offset);
- buf->next = NULL;
+ buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
- init_waitqueue_head( &buf->dma_wait );
- buf->filp = NULL;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->filp = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc( buf->dev_priv_size,
- DRM_MEM_BUFS );
- if(!buf->dev_private) {
+ buf->dev_private = drm_alloc(buf->dev_priv_size,
+ DRM_MEM_BUFS);
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
- drm_cleanup_buf_error(dev,entry);
- drm_free( temp_pagelist,
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES );
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ drm_free(temp_pagelist,
+ (dma->page_count +
+ (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( buf->dev_private, 0, buf->dev_priv_size );
+ memset(buf->dev_private, 0, buf->dev_priv_size);
- DRM_DEBUG( "buffer %d @ %p\n",
- entry->buf_count, buf->address );
+ DRM_DEBUG("buffer %d @ %p\n",
+ entry->buf_count, buf->address);
}
byte_count += PAGE_SIZE << page_order;
}
- temp_buflist = drm_realloc( dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist),
- DRM_MEM_BUFS );
+ temp_buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist), DRM_MEM_BUFS);
if (!temp_buflist) {
/* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev,entry);
- drm_free( temp_pagelist,
- (dma->page_count + (count << page_order))
- * sizeof(*dma->pagelist),
- DRM_MEM_PAGES );
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ drm_free(temp_pagelist,
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
dma->buflist = temp_buflist;
- for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ for (i = 0; i < entry->buf_count; i++) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
@@ -728,8 +863,8 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
*/
if (dma->page_count) {
drm_free(dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
+ dma->page_count * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
}
dma->pagelist = temp_pagelist;
@@ -738,27 +873,21 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
- up( &dev->struct_sem );
-
- request.count = entry->buf_count;
- request.size = size;
+ up(&dev->struct_sem);
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
- atomic_dec( &dev->buf_alloc );
+ atomic_dec(&dev->buf_alloc);
return 0;
}
-static int drm_addbufs_sg( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+EXPORT_SYMBOL(drm_addbufs_pci);
+
+static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t __user *argp = (void __user *)arg;
- drm_buf_desc_t request;
drm_buf_entry_t *entry;
drm_buf_t *buf;
unsigned long offset;
@@ -773,147 +902,298 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
int i;
drm_buf_t **temp_buflist;
- if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
-
- if ( !dma ) return -EINVAL;
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
- if ( copy_from_user( &request, argp, sizeof(request) ) )
- return -EFAULT;
+ if (!dma)
+ return -EINVAL;
- count = request.count;
- order = drm_order( request.size );
+ count = request->count;
+ order = drm_order(request->size);
size = 1 << order;
- alignment = (request.flags & _DRM_PAGE_ALIGN)
- ? PAGE_ALIGN(size) : size;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
- agp_offset = request.agp_start;
-
- DRM_DEBUG( "count: %d\n", count );
- DRM_DEBUG( "order: %d\n", order );
- DRM_DEBUG( "size: %d\n", size );
- DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
- DRM_DEBUG( "alignment: %d\n", alignment );
- DRM_DEBUG( "page_order: %d\n", page_order );
- DRM_DEBUG( "total: %d\n", total );
-
- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
-
- spin_lock( &dev->count_lock );
- if ( dev->buf_use ) {
- spin_unlock( &dev->count_lock );
+ agp_offset = request->agp_start;
+
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ if (dev->queue_count)
+ return -EBUSY; /* Not while in use */
+
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
return -EBUSY;
}
- atomic_inc( &dev->buf_alloc );
- spin_unlock( &dev->count_lock );
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
- down( &dev->struct_sem );
+ down(&dev->struct_sem);
entry = &dma->bufs[order];
- if ( entry->buf_count ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
- return -ENOMEM; /* May only call once for each order */
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
}
if (count < 0 || count > 4096) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -EINVAL;
}
- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
- DRM_MEM_BUFS );
- if ( !entry->buflist ) {
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
entry->buf_size = size;
entry->page_order = page_order;
offset = 0;
- while ( entry->buf_count < count ) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
+ while (entry->buf_count < count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
- buf->offset = (dma->byte_count + offset);
+ buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset + dev->sg->handle);
- buf->next = NULL;
+ buf->address = (void *)(agp_offset + offset
+ + (unsigned long)dev->sg->virtual);
+ buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
- init_waitqueue_head( &buf->dma_wait );
- buf->filp = NULL;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->filp = NULL;
buf->dev_priv_size = dev->driver->dev_priv_size;
- buf->dev_private = drm_alloc( buf->dev_priv_size,
- DRM_MEM_BUFS );
- if(!buf->dev_private) {
+ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
- drm_cleanup_buf_error(dev,entry);
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- memset( buf->dev_private, 0, buf->dev_priv_size );
+ memset(buf->dev_private, 0, buf->dev_priv_size);
- DRM_DEBUG( "buffer %d @ %p\n",
- entry->buf_count, buf->address );
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
offset += alignment;
entry->buf_count++;
byte_count += PAGE_SIZE << page_order;
}
- DRM_DEBUG( "byte_count: %d\n", byte_count );
+ DRM_DEBUG("byte_count: %d\n", byte_count);
- temp_buflist = drm_realloc( dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- (dma->buf_count + entry->buf_count)
- * sizeof(*dma->buflist),
- DRM_MEM_BUFS );
- if(!temp_buflist) {
+ temp_buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ if (!temp_buflist) {
/* Free the entry because it isn't valid */
- drm_cleanup_buf_error(dev,entry);
- up( &dev->struct_sem );
- atomic_dec( &dev->buf_alloc );
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
dma->buflist = temp_buflist;
- for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ for (i = 0; i < entry->buf_count; i++) {
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
dma->buf_count += entry->buf_count;
dma->byte_count += byte_count;
- DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
- DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- up( &dev->struct_sem );
+ up(&dev->struct_sem);
- request.count = entry->buf_count;
- request.size = size;
-
- if ( copy_to_user( argp, &request, sizeof(request) ) )
- return -EFAULT;
+ request->count = entry->buf_count;
+ request->size = size;
dma->flags = _DRM_DMA_USE_SG;
- atomic_dec( &dev->buf_alloc );
+ atomic_dec(&dev->buf_alloc);
+ return 0;
+}
+
+static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+
+ if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
+
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
+
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = request->agp_start;
+
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ if (dev->queue_count)
+ return -EBUSY; /* Not while in use */
+
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
+
+ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
+
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while (entry->buf_count < count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+ temp_buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev, entry);
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+ up(&dev->struct_sem);
+
+ request->count = entry->buf_count;
+ request->size = size;
+
+ dma->flags = _DRM_DMA_USE_FB;
+
+ atomic_dec(&dev->buf_alloc);
return 0;
}
@@ -931,31 +1211,40 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
* addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
* PCI memory respectively.
*/
-int drm_addbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_buf_desc_t request;
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
-
+ int ret;
+
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
- sizeof(request) ) )
+ if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
+ sizeof(request)))
return -EFAULT;
#if __OS_HAS_AGP
- if ( request.flags & _DRM_AGP_BUFFER )
- return drm_addbufs_agp( inode, filp, cmd, arg );
+ if (request.flags & _DRM_AGP_BUFFER)
+ ret = drm_addbufs_agp(dev, &request);
else
#endif
- if ( request.flags & _DRM_SG_BUFFER )
- return drm_addbufs_sg( inode, filp, cmd, arg );
+ if (request.flags & _DRM_SG_BUFFER)
+ ret = drm_addbufs_sg(dev, &request);
+ else if (request.flags & _DRM_FB_BUFFER)
+ ret = drm_addbufs_fb(dev, &request);
else
- return drm_addbufs_pci( inode, filp, cmd, arg );
-}
+ ret = drm_addbufs_pci(dev, &request);
+ if (ret == 0) {
+ if (copy_to_user((void __user *)arg, &request, sizeof(request))) {
+ ret = -EFAULT;
+ }
+ }
+ return ret;
+}
/**
* Get information about the buffer mappings.
@@ -974,8 +1263,8 @@ int drm_addbufs( struct inode *inode, struct file *filp,
* lock, preventing of allocating more buffers after this call. Information
* about each requested buffer is then copied into user space.
*/
-int drm_infobufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_infobufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -988,58 +1277,61 @@ int drm_infobufs( struct inode *inode, struct file *filp,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if ( !dma ) return -EINVAL;
+ if (!dma)
+ return -EINVAL;
- spin_lock( &dev->count_lock );
- if ( atomic_read( &dev->buf_alloc ) ) {
- spin_unlock( &dev->count_lock );
+ spin_lock(&dev->count_lock);
+ if (atomic_read(&dev->buf_alloc)) {
+ spin_unlock(&dev->count_lock);
return -EBUSY;
}
++dev->buf_use; /* Can't allocate more after this call */
- spin_unlock( &dev->count_lock );
+ spin_unlock(&dev->count_lock);
- if ( copy_from_user( &request, argp, sizeof(request) ) )
+ if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
- for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
- if ( dma->bufs[i].buf_count ) ++count;
+ for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+ if (dma->bufs[i].buf_count)
+ ++count;
}
- DRM_DEBUG( "count = %d\n", count );
+ DRM_DEBUG("count = %d\n", count);
- if ( request.count >= count ) {
- for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
- if ( dma->bufs[i].buf_count ) {
- drm_buf_desc_t __user *to = &request.list[count];
+ if (request.count >= count) {
+ for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+ if (dma->bufs[i].buf_count) {
+ drm_buf_desc_t __user *to =
+ &request.list[count];
drm_buf_entry_t *from = &dma->bufs[i];
drm_freelist_t *list = &dma->bufs[i].freelist;
- if ( copy_to_user( &to->count,
- &from->buf_count,
- sizeof(from->buf_count) ) ||
- copy_to_user( &to->size,
- &from->buf_size,
- sizeof(from->buf_size) ) ||
- copy_to_user( &to->low_mark,
- &list->low_mark,
- sizeof(list->low_mark) ) ||
- copy_to_user( &to->high_mark,
- &list->high_mark,
- sizeof(list->high_mark) ) )
+ if (copy_to_user(&to->count,
+ &from->buf_count,
+ sizeof(from->buf_count)) ||
+ copy_to_user(&to->size,
+ &from->buf_size,
+ sizeof(from->buf_size)) ||
+ copy_to_user(&to->low_mark,
+ &list->low_mark,
+ sizeof(list->low_mark)) ||
+ copy_to_user(&to->high_mark,
+ &list->high_mark,
+ sizeof(list->high_mark)))
return -EFAULT;
- DRM_DEBUG( "%d %d %d %d %d\n",
- i,
- dma->bufs[i].buf_count,
- dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark );
+ DRM_DEBUG("%d %d %d %d %d\n",
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].buf_size,
+ dma->bufs[i].freelist.low_mark,
+ dma->bufs[i].freelist.high_mark);
++count;
}
}
}
request.count = count;
- if ( copy_to_user( argp, &request, sizeof(request) ) )
+ if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
@@ -1059,8 +1351,8 @@ int drm_infobufs( struct inode *inode, struct file *filp,
*
* \note This ioctl is deprecated and mostly never used.
*/
-int drm_markbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_markbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1072,44 +1364,45 @@ int drm_markbufs( struct inode *inode, struct file *filp,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if ( !dma ) return -EINVAL;
+ if (!dma)
+ return -EINVAL;
- if ( copy_from_user( &request,
- (drm_buf_desc_t __user *)arg,
- sizeof(request) ) )
+ if (copy_from_user(&request,
+ (drm_buf_desc_t __user *) arg, sizeof(request)))
return -EFAULT;
- DRM_DEBUG( "%d, %d, %d\n",
- request.size, request.low_mark, request.high_mark );
- order = drm_order( request.size );
- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+ DRM_DEBUG("%d, %d, %d\n",
+ request.size, request.low_mark, request.high_mark);
+ order = drm_order(request.size);
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
entry = &dma->bufs[order];
- if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
+ if (request.low_mark < 0 || request.low_mark > entry->buf_count)
return -EINVAL;
- if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+ if (request.high_mark < 0 || request.high_mark > entry->buf_count)
return -EINVAL;
- entry->freelist.low_mark = request.low_mark;
+ entry->freelist.low_mark = request.low_mark;
entry->freelist.high_mark = request.high_mark;
return 0;
}
/**
- * Unreserve the buffers in list, previously reserved using drmDMA.
+ * Unreserve the buffers in list, previously reserved using drmDMA.
*
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
* \param arg pointer to a drm_buf_free structure.
* \return zero on success or a negative number on failure.
- *
+ *
* Calls free_buffer() for each used buffer.
* This function is primarily used for debugging.
*/
-int drm_freebufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_freebufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1122,31 +1415,29 @@ int drm_freebufs( struct inode *inode, struct file *filp,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if ( !dma ) return -EINVAL;
+ if (!dma)
+ return -EINVAL;
- if ( copy_from_user( &request,
- (drm_buf_free_t __user *)arg,
- sizeof(request) ) )
+ if (copy_from_user(&request,
+ (drm_buf_free_t __user *) arg, sizeof(request)))
return -EFAULT;
- DRM_DEBUG( "%d\n", request.count );
- for ( i = 0 ; i < request.count ; i++ ) {
- if ( copy_from_user( &idx,
- &request.list[i],
- sizeof(idx) ) )
+ DRM_DEBUG("%d\n", request.count);
+ for (i = 0; i < request.count; i++) {
+ if (copy_from_user(&idx, &request.list[i], sizeof(idx)))
return -EFAULT;
- if ( idx < 0 || idx >= dma->buf_count ) {
- DRM_ERROR( "Index %d (of %d max)\n",
- idx, dma->buf_count - 1 );
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("Index %d (of %d max)\n",
+ idx, dma->buf_count - 1);
return -EINVAL;
}
buf = dma->buflist[idx];
- if ( buf->filp != filp ) {
- DRM_ERROR( "Process %d freeing buffer not owned\n",
- current->pid );
+ if (buf->filp != filp) {
+ DRM_ERROR("Process %d freeing buffer not owned\n",
+ current->pid);
return -EINVAL;
}
- drm_free_buffer( dev, buf );
+ drm_free_buffer(dev, buf);
}
return 0;
@@ -1165,8 +1456,8 @@ int drm_freebufs( struct inode *inode, struct file *filp,
* about each buffer into user space. The PCI buffers are already mapped on the
* addbufs_pci() call.
*/
-int drm_mapbufs( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_mapbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1182,100 +1473,109 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if ( !dma ) return -EINVAL;
+ if (!dma)
+ return -EINVAL;
- spin_lock( &dev->count_lock );
- if ( atomic_read( &dev->buf_alloc ) ) {
- spin_unlock( &dev->count_lock );
+ spin_lock(&dev->count_lock);
+ if (atomic_read(&dev->buf_alloc)) {
+ spin_unlock(&dev->count_lock);
return -EBUSY;
}
dev->buf_use++; /* Can't allocate more after this call */
- spin_unlock( &dev->count_lock );
+ spin_unlock(&dev->count_lock);
- if ( copy_from_user( &request, argp, sizeof(request) ) )
+ if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
- if ( request.count >= dma->buf_count ) {
- if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
- (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
+ if (request.count >= dma->buf_count) {
+ if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+ || (drm_core_check_feature(dev, DRIVER_SG)
+ && (dma->flags & _DRM_DMA_USE_SG))
+ || (drm_core_check_feature(dev, DRIVER_FB_DMA)
+ && (dma->flags & _DRM_DMA_USE_FB))) {
drm_map_t *map = dev->agp_buffer_map;
+ unsigned long token = dev->agp_buffer_token;
- if ( !map ) {
+ if (!map) {
retcode = -EINVAL;
goto done;
}
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
- down_write( &current->mm->mmap_sem );
-#endif
- virtual = do_mmap( filp, 0, map->size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- (unsigned long)map->offset );
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
- up_write( &current->mm->mmap_sem );
-#endif
+ down_write(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, map->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, token);
+ up_write(&current->mm->mmap_sem);
} else {
-#if LINUX_VERSION_CODE <= 0x020402
- down( &current->mm->mmap_sem );
-#else
- down_write( &current->mm->mmap_sem );
-#endif
- virtual = do_mmap( filp, 0, dma->byte_count,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, 0 );
-#if LINUX_VERSION_CODE <= 0x020402
- up( &current->mm->mmap_sem );
-#else
- up_write( &current->mm->mmap_sem );
-#endif
+ down_write(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, dma->byte_count,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, 0);
+ up_write(&current->mm->mmap_sem);
}
- if ( virtual > -1024UL ) {
+ if (virtual > -1024UL) {
/* Real error */
retcode = (signed long)virtual;
goto done;
}
request.virtual = (void __user *)virtual;
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
- if ( copy_to_user( &request.list[i].idx,
- &dma->buflist[i]->idx,
- sizeof(request.list[0].idx) ) ) {
+ for (i = 0; i < dma->buf_count; i++) {
+ if (copy_to_user(&request.list[i].idx,
+ &dma->buflist[i]->idx,
+ sizeof(request.list[0].idx))) {
retcode = -EFAULT;
goto done;
}
- if ( copy_to_user( &request.list[i].total,
- &dma->buflist[i]->total,
- sizeof(request.list[0].total) ) ) {
+ if (copy_to_user(&request.list[i].total,
+ &dma->buflist[i]->total,
+ sizeof(request.list[0].total))) {
retcode = -EFAULT;
goto done;
}
- if ( copy_to_user( &request.list[i].used,
- &zero,
- sizeof(zero) ) ) {
+ if (copy_to_user(&request.list[i].used,
+ &zero, sizeof(zero))) {
retcode = -EFAULT;
goto done;
}
- address = virtual + dma->buflist[i]->offset; /* *** */
- if ( copy_to_user( &request.list[i].address,
- &address,
- sizeof(address) ) ) {
+ address = virtual + dma->buflist[i]->offset; /* *** */
+ if (copy_to_user(&request.list[i].address,
+ &address, sizeof(address))) {
retcode = -EFAULT;
goto done;
}
}
}
- done:
+ done:
request.count = dma->buf_count;
- DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
+ DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
- if ( copy_to_user( argp, &request, sizeof(request) ) )
+ if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return retcode;
}
+/**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+int drm_order(unsigned long size)
+{
+ int order;
+ unsigned long tmp;
+
+ for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
+
+ if (size & (size - 1))
+ ++order;
+
+ return order;
+}
+
+EXPORT_SYMBOL(drm_order);
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index a7cfabd1ca2e..bdd168d88f49 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -1,7 +1,7 @@
/**
- * \file drm_context.h
+ * \file drm_context.c
* IOCTLs for generic contexts
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -56,25 +56,26 @@
* in drm_device::context_sareas, while holding the drm_device::struct_sem
* lock.
*/
-void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle )
+void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
{
- if ( ctx_handle < 0 ) goto failed;
- if ( !dev->ctx_bitmap ) goto failed;
+ if (ctx_handle < 0)
+ goto failed;
+ if (!dev->ctx_bitmap)
+ goto failed;
- if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
+ if (ctx_handle < DRM_MAX_CTXBITMAP) {
down(&dev->struct_sem);
- clear_bit( ctx_handle, dev->ctx_bitmap );
+ clear_bit(ctx_handle, dev->ctx_bitmap);
dev->context_sareas[ctx_handle] = NULL;
up(&dev->struct_sem);
return;
}
-failed:
- DRM_ERROR( "Attempt to free invalid context handle: %d\n",
- ctx_handle );
- return;
+ failed:
+ DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
+ return;
}
-/**
+/**
* Context bitmap allocation.
*
* \param dev DRM device.
@@ -84,29 +85,33 @@ failed:
* drm_device::context_sareas to accommodate the new entry while holding the
* drm_device::struct_sem lock.
*/
-static int drm_ctxbitmap_next( drm_device_t *dev )
+static int drm_ctxbitmap_next(drm_device_t * dev)
{
int bit;
- if(!dev->ctx_bitmap) return -1;
+ if (!dev->ctx_bitmap)
+ return -1;
down(&dev->struct_sem);
- bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
- if ( bit < DRM_MAX_CTXBITMAP ) {
- set_bit( bit, dev->ctx_bitmap );
- DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
- if((bit+1) > dev->max_context) {
- dev->max_context = (bit+1);
- if(dev->context_sareas) {
+ bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
+ if (bit < DRM_MAX_CTXBITMAP) {
+ set_bit(bit, dev->ctx_bitmap);
+ DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
+ if ((bit + 1) > dev->max_context) {
+ dev->max_context = (bit + 1);
+ if (dev->context_sareas) {
drm_map_t **ctx_sareas;
ctx_sareas = drm_realloc(dev->context_sareas,
- (dev->max_context - 1) *
- sizeof(*dev->context_sareas),
- dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
- if(!ctx_sareas) {
+ (dev->max_context -
+ 1) *
+ sizeof(*dev->
+ context_sareas),
+ dev->max_context *
+ sizeof(*dev->
+ context_sareas),
+ DRM_MEM_MAPS);
+ if (!ctx_sareas) {
clear_bit(bit, dev->ctx_bitmap);
up(&dev->struct_sem);
return -1;
@@ -115,11 +120,11 @@ static int drm_ctxbitmap_next( drm_device_t *dev )
dev->context_sareas[bit] = NULL;
} else {
/* max_context == 1 at this point */
- dev->context_sareas = drm_alloc(
- dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
- if(!dev->context_sareas) {
+ dev->context_sareas =
+ drm_alloc(dev->max_context *
+ sizeof(*dev->context_sareas),
+ DRM_MEM_MAPS);
+ if (!dev->context_sareas) {
clear_bit(bit, dev->ctx_bitmap);
up(&dev->struct_sem);
return -1;
@@ -142,26 +147,26 @@ static int drm_ctxbitmap_next( drm_device_t *dev )
* Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
* the drm_device::struct_sem lock.
*/
-int drm_ctxbitmap_init( drm_device_t *dev )
+int drm_ctxbitmap_init(drm_device_t * dev)
{
int i;
- int temp;
+ int temp;
down(&dev->struct_sem);
- dev->ctx_bitmap = (unsigned long *) drm_alloc( PAGE_SIZE,
- DRM_MEM_CTXBITMAP );
- if ( dev->ctx_bitmap == NULL ) {
+ dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
+ DRM_MEM_CTXBITMAP);
+ if (dev->ctx_bitmap == NULL) {
up(&dev->struct_sem);
return -ENOMEM;
}
- memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
+ memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
dev->context_sareas = NULL;
dev->max_context = -1;
up(&dev->struct_sem);
- for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
- temp = drm_ctxbitmap_next( dev );
- DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ temp = drm_ctxbitmap_next(dev);
+ DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
}
return 0;
@@ -175,14 +180,14 @@ int drm_ctxbitmap_init( drm_device_t *dev )
* Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
* the drm_device::struct_sem lock.
*/
-void drm_ctxbitmap_cleanup( drm_device_t *dev )
+void drm_ctxbitmap_cleanup(drm_device_t * dev)
{
down(&dev->struct_sem);
- if( dev->context_sareas ) drm_free( dev->context_sareas,
- sizeof(*dev->context_sareas) *
- dev->max_context,
- DRM_MEM_MAPS );
- drm_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
+ if (dev->context_sareas)
+ drm_free(dev->context_sareas,
+ sizeof(*dev->context_sareas) *
+ dev->max_context, DRM_MEM_MAPS);
+ drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
up(&dev->struct_sem);
}
@@ -194,7 +199,7 @@ void drm_ctxbitmap_cleanup( drm_device_t *dev )
/**
* Get per-context SAREA.
- *
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
@@ -205,19 +210,21 @@ void drm_ctxbitmap_cleanup( drm_device_t *dev )
* returns its handle.
*/
int drm_getsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
drm_ctx_priv_map_t request;
drm_map_t *map;
+ drm_map_list_t *_entry;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
down(&dev->struct_sem);
- if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
+ if (dev->max_context < 0
+ || request.ctx_id >= (unsigned)dev->max_context) {
up(&dev->struct_sem);
return -EINVAL;
}
@@ -225,7 +232,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
map = dev->context_sareas[request.ctx_id];
up(&dev->struct_sem);
- request.handle = (void *) map->offset;
+ request.handle = NULL;
+ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->map == map) {
+ request.handle =
+ (void *)(unsigned long)_entry->user_token;
+ break;
+ }
+ }
+ if (request.handle == NULL)
+ return -EINVAL;
+
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
@@ -233,7 +250,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
/**
* Set per-context SAREA.
- *
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
@@ -244,37 +261,37 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* drm_device::context_sareas with it.
*/
int drm_setsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t request;
drm_map_t *map = NULL;
drm_map_list_t *r_list = NULL;
struct list_head *list;
if (copy_from_user(&request,
- (drm_ctx_priv_map_t __user *)arg,
- sizeof(request)))
+ (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
return -EFAULT;
down(&dev->struct_sem);
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
if (r_list->map
- && r_list->map->offset == (unsigned long) request.handle)
+ && r_list->user_token == (unsigned long)request.handle)
goto found;
}
-bad:
+ bad:
up(&dev->struct_sem);
return -EINVAL;
-found:
+ found:
map = r_list->map;
- if (!map) goto bad;
+ if (!map)
+ goto bad;
if (dev->max_context < 0)
goto bad;
- if (request.ctx_id >= (unsigned) dev->max_context)
+ if (request.ctx_id >= (unsigned)dev->max_context)
goto bad;
dev->context_sareas[request.ctx_id] = map;
up(&dev->struct_sem);
@@ -297,22 +314,21 @@ found:
*
* Attempt to set drm_device::context_flag.
*/
-int drm_context_switch( drm_device_t *dev, int old, int new )
+static int drm_context_switch(drm_device_t * dev, int old, int new)
{
- if ( test_and_set_bit( 0, &dev->context_flag ) ) {
- DRM_ERROR( "Reentering -- FIXME\n" );
- return -EBUSY;
- }
-
+ if (test_and_set_bit(0, &dev->context_flag)) {
+ DRM_ERROR("Reentering -- FIXME\n");
+ return -EBUSY;
+ }
- DRM_DEBUG( "Context switch from %d to %d\n", old, new );
+ DRM_DEBUG("Context switch from %d to %d\n", old, new);
- if ( new == dev->last_context ) {
- clear_bit( 0, &dev->context_flag );
- return 0;
- }
+ if (new == dev->last_context) {
+ clear_bit(0, &dev->context_flag);
+ return 0;
+ }
- return 0;
+ return 0;
}
/**
@@ -326,22 +342,22 @@ int drm_context_switch( drm_device_t *dev, int old, int new )
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
-static int drm_context_switch_complete( drm_device_t *dev, int new )
+static int drm_context_switch_complete(drm_device_t * dev, int new)
{
- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
- dev->last_switch = jiffies;
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
- if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
- DRM_ERROR( "Lock isn't held after context switch\n" );
- }
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("Lock isn't held after context switch\n");
+ }
- /* If a context switch is ever initiated
- when the kernel holds the lock, release
- that lock here. */
- clear_bit( 0, &dev->context_flag );
- wake_up( &dev->context_wait );
+ /* If a context switch is ever initiated
+ when the kernel holds the lock, release
+ that lock here. */
+ clear_bit(0, &dev->context_flag);
+ wake_up(&dev->context_wait);
- return 0;
+ return 0;
}
/**
@@ -353,29 +369,28 @@ static int drm_context_switch_complete( drm_device_t *dev, int new )
* \param arg user argument pointing to a drm_ctx_res structure.
* \return zero on success or a negative number on failure.
*/
-int drm_resctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_resctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_ctx_res_t res;
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
int i;
- if ( copy_from_user( &res, argp, sizeof(res) ) )
+ if (copy_from_user(&res, argp, sizeof(res)))
return -EFAULT;
- if ( res.count >= DRM_RESERVED_CONTEXTS ) {
- memset( &ctx, 0, sizeof(ctx) );
- for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+ if (res.count >= DRM_RESERVED_CONTEXTS) {
+ memset(&ctx, 0, sizeof(ctx));
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- if ( copy_to_user( &res.contexts[i],
- &i, sizeof(i) ) )
+ if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))
return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- if ( copy_to_user( argp, &res, sizeof(res) ) )
+ if (copy_to_user(argp, &res, sizeof(res)))
return -EFAULT;
return 0;
}
@@ -391,58 +406,57 @@ int drm_resctx( struct inode *inode, struct file *filp,
*
* Get a new handle for the context and copy to userspace.
*/
-int drm_addctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_addctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_ctx_list_t * ctx_entry;
+ drm_ctx_list_t *ctx_entry;
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
- if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
+ if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
- ctx.handle = drm_ctxbitmap_next( dev );
- if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
- /* Skip kernel's context and get a new one. */
- ctx.handle = drm_ctxbitmap_next( dev );
+ ctx.handle = drm_ctxbitmap_next(dev);
+ if (ctx.handle == DRM_KERNEL_CONTEXT) {
+ /* Skip kernel's context and get a new one. */
+ ctx.handle = drm_ctxbitmap_next(dev);
}
- DRM_DEBUG( "%d\n", ctx.handle );
- if ( ctx.handle == -1 ) {
- DRM_DEBUG( "Not enough free contexts.\n" );
- /* Should this return -EBUSY instead? */
+ DRM_DEBUG("%d\n", ctx.handle);
+ if (ctx.handle == -1) {
+ DRM_DEBUG("Not enough free contexts.\n");
+ /* Should this return -EBUSY instead? */
return -ENOMEM;
}
- if ( ctx.handle != DRM_KERNEL_CONTEXT )
- {
+ if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_ctor)
dev->driver->context_ctor(dev, ctx.handle);
}
- ctx_entry = drm_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
- if ( !ctx_entry ) {
+ ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
+ if (!ctx_entry) {
DRM_DEBUG("out of memory\n");
return -ENOMEM;
}
- INIT_LIST_HEAD( &ctx_entry->head );
+ INIT_LIST_HEAD(&ctx_entry->head);
ctx_entry->handle = ctx.handle;
ctx_entry->tag = priv;
- down( &dev->ctxlist_sem );
- list_add( &ctx_entry->head, &dev->ctxlist->head );
+ down(&dev->ctxlist_sem);
+ list_add(&ctx_entry->head, &dev->ctxlist->head);
++dev->ctx_count;
- up( &dev->ctxlist_sem );
+ up(&dev->ctxlist_sem);
- if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
+ if (copy_to_user(argp, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
-int drm_modctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_modctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
/* This does nothing */
return 0;
@@ -457,19 +471,19 @@ int drm_modctx( struct inode *inode, struct file *filp,
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*/
-int drm_getctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_getctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
- if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
+ if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
/* This is 0, because we don't handle any context flags */
ctx.flags = 0;
- if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
+ if (copy_to_user(argp, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
@@ -485,18 +499,18 @@ int drm_getctx( struct inode *inode, struct file *filp,
*
* Calls context_switch().
*/
-int drm_switchctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
- DRM_DEBUG( "%d\n", ctx.handle );
- return drm_context_switch( dev, dev->last_context, ctx.handle );
+ DRM_DEBUG("%d\n", ctx.handle);
+ return drm_context_switch(dev, dev->last_context, ctx.handle);
}
/**
@@ -510,18 +524,18 @@ int drm_switchctx( struct inode *inode, struct file *filp,
*
* Calls context_switch_complete().
*/
-int drm_newctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_newctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
- DRM_DEBUG( "%d\n", ctx.handle );
- drm_context_switch_complete( dev, ctx.handle );
+ DRM_DEBUG("%d\n", ctx.handle);
+ drm_context_switch_complete(dev, ctx.handle);
return 0;
}
@@ -537,42 +551,41 @@ int drm_newctx( struct inode *inode, struct file *filp,
*
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
*/
-int drm_rmctx( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_rmctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
- DRM_DEBUG( "%d\n", ctx.handle );
- if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
+ DRM_DEBUG("%d\n", ctx.handle);
+ if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {
priv->remove_auth_on_close = 1;
}
- if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+ if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx.handle);
- drm_ctxbitmap_free( dev, ctx.handle );
+ drm_ctxbitmap_free(dev, ctx.handle);
}
- down( &dev->ctxlist_sem );
- if ( !list_empty( &dev->ctxlist->head ) ) {
+ down(&dev->ctxlist_sem);
+ if (!list_empty(&dev->ctxlist->head)) {
drm_ctx_list_t *pos, *n;
- list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
- if ( pos->handle == ctx.handle ) {
- list_del( &pos->head );
- drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ if (pos->handle == ctx.handle) {
+ list_del(&pos->head);
+ drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
--dev->ctx_count;
}
}
}
- up( &dev->ctxlist_sem );
+ up(&dev->ctxlist_sem);
return 0;
}
/*@}*/
-
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 4a28c053c98b..2afab95ca036 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -1,5 +1,5 @@
/**
- * \file drm_dma.h
+ * \file drm_dma.c
* DMA IOCTL and function support
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -37,23 +37,23 @@
/**
* Initialize the DMA data.
- *
+ *
* \param dev DRM device.
* \return zero on success or a negative value on failure.
*
* Allocate and initialize a drm_device_dma structure.
*/
-int drm_dma_setup( drm_device_t *dev )
+int drm_dma_setup(drm_device_t * dev)
{
int i;
- dev->dma = drm_alloc( sizeof(*dev->dma), DRM_MEM_DRIVER );
- if ( !dev->dma )
+ dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
+ if (!dev->dma)
return -ENOMEM;
- memset( dev->dma, 0, sizeof(*dev->dma) );
+ memset(dev->dma, 0, sizeof(*dev->dma));
- for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
+ for (i = 0; i <= DRM_MAX_ORDER; i++)
memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
return 0;
@@ -67,14 +67,15 @@ int drm_dma_setup( drm_device_t *dev )
* Free all pages associated with DMA buffers, the buffers and pages lists, and
* finally the the drm_device::dma structure itself.
*/
-void drm_dma_takedown(drm_device_t *dev)
+void drm_dma_takedown(drm_device_t * dev)
{
- drm_device_dma_t *dma = dev->dma;
- int i, j;
+ drm_device_dma_t *dma = dev->dma;
+ int i, j;
- if (!dma) return;
+ if (!dma)
+ return;
- /* Clear dma buffers */
+ /* Clear dma buffers */
for (i = 0; i <= DRM_MAX_ORDER; i++) {
if (dma->bufs[i].seg_count) {
DRM_DEBUG("order %d: buf_count = %d,"
@@ -85,64 +86,63 @@ void drm_dma_takedown(drm_device_t *dev)
for (j = 0; j < dma->bufs[i].seg_count; j++) {
if (dma->bufs[i].seglist[j]) {
drm_free_pages(dma->bufs[i].seglist[j],
- dma->bufs[i].page_order,
- DRM_MEM_DMA);
+ dma->bufs[i].page_order,
+ DRM_MEM_DMA);
}
}
drm_free(dma->bufs[i].seglist,
- dma->bufs[i].seg_count
- * sizeof(*dma->bufs[0].seglist),
- DRM_MEM_SEGS);
+ dma->bufs[i].seg_count
+ * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
}
- if (dma->bufs[i].buf_count) {
- for (j = 0; j < dma->bufs[i].buf_count; j++) {
+ if (dma->bufs[i].buf_count) {
+ for (j = 0; j < dma->bufs[i].buf_count; j++) {
if (dma->bufs[i].buflist[j].dev_private) {
- drm_free(dma->bufs[i].buflist[j].dev_private,
- dma->bufs[i].buflist[j].dev_priv_size,
- DRM_MEM_BUFS);
+ drm_free(dma->bufs[i].buflist[j].
+ dev_private,
+ dma->bufs[i].buflist[j].
+ dev_priv_size, DRM_MEM_BUFS);
}
}
- drm_free(dma->bufs[i].buflist,
- dma->bufs[i].buf_count *
- sizeof(*dma->bufs[0].buflist),
- DRM_MEM_BUFS);
+ drm_free(dma->bufs[i].buflist,
+ dma->bufs[i].buf_count *
+ sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
}
}
if (dma->buflist) {
drm_free(dma->buflist,
- dma->buf_count * sizeof(*dma->buflist),
- DRM_MEM_BUFS);
+ dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
}
if (dma->pagelist) {
drm_free(dma->pagelist,
- dma->page_count * sizeof(*dma->pagelist),
- DRM_MEM_PAGES);
+ dma->page_count * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
}
drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
dev->dma = NULL;
}
-
/**
* Free a buffer.
*
* \param dev DRM device.
* \param buf buffer to free.
- *
+ *
* Resets the fields of \p buf.
*/
-void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
+void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
{
- if (!buf) return;
+ if (!buf)
+ return;
- buf->waiting = 0;
- buf->pending = 0;
- buf->filp = NULL;
- buf->used = 0;
+ buf->waiting = 0;
+ buf->pending = 0;
+ buf->filp = NULL;
+ buf->used = 0;
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
+ if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
+ && waitqueue_active(&buf->dma_wait)) {
wake_up_interruptible(&buf->dma_wait);
}
}
@@ -154,12 +154,13 @@ void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
*
* Frees each buffer associated with \p filp not already on the hardware.
*/
-void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
+void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp)
{
drm_device_dma_t *dma = dev->dma;
- int i;
+ int i;
- if (!dma) return;
+ if (!dma)
+ return;
for (i = 0; i < dma->buf_count; i++) {
if (dma->buflist[i]->filp == filp) {
switch (dma->buflist[i]->list) {
@@ -176,5 +177,5 @@ void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
}
}
}
-EXPORT_SYMBOL(drm_core_reclaim_buffers);
+EXPORT_SYMBOL(drm_core_reclaim_buffers);
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index e8e8e42be4c7..7857453c4f48 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -1,5 +1,5 @@
/**
- * \file drm_drawable.h
+ * \file drm_drawable.c
* IOCTLs for drawables
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -37,20 +37,20 @@
/** No-op. */
int drm_adddraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_draw_t draw;
draw.handle = 0; /* NOOP */
DRM_DEBUG("%d\n", draw.handle);
- if (copy_to_user((drm_draw_t __user *)arg, &draw, sizeof(draw)))
+ if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw)))
return -EFAULT;
return 0;
}
/** No-op. */
int drm_rmdraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
return 0; /* NOOP */
}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 3333c250c4d9..4dff7554eb08 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -1,5 +1,5 @@
/**
- * \file drm_drv.h
+ * \file drm_drv.c
* Generic driver template
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -55,67 +55,67 @@ static int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/** Ioctl table */
-static drm_ioctl_desc_t drm_ioctls[] = {
- [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 },
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
+static drm_ioctl_desc_t drm_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, 0, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, 0, 1},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, 1, 1},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, 1, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, 1, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, 1, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, 1, 1},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, 1, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, 1, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, 1, 0},
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
- [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1},
#if __OS_HAS_AGP
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind, 1, 1},
#endif
- [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0},
};
#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
@@ -127,21 +127,20 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* Frees every resource in \p dev.
*
- * \sa drm_device and setup().
+ * \sa drm_device
*/
-int drm_takedown( drm_device_t *dev )
+int drm_takedown(drm_device_t * dev)
{
drm_magic_entry_t *pt, *next;
- drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list, *list_next;
drm_vma_entry_t *vma, *vma_next;
int i;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
if (dev->driver->pretakedown)
- dev->driver->pretakedown(dev);
+ dev->driver->pretakedown(dev);
+ DRM_DEBUG("driver pretakedown completed\n");
if (dev->unique) {
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -149,126 +148,95 @@ int drm_takedown( drm_device_t *dev )
dev->unique_len = 0;
}
- if ( dev->irq_enabled ) drm_irq_uninstall( dev );
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
- down( &dev->struct_sem );
- del_timer( &dev->timer );
+ down(&dev->struct_sem);
+ del_timer(&dev->timer);
- /* Clear pid list */
- for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
- for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
+ /* Clear pid list */
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ for (pt = dev->magiclist[i].head; pt; pt = next) {
next = pt->next;
- drm_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
+ drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
}
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
}
- /* Clear AGP information */
+ /* Clear AGP information */
if (drm_core_has_AGP(dev) && dev->agp) {
drm_agp_mem_t *entry;
drm_agp_mem_t *nexte;
- /* Remove AGP resources, but leave dev->agp
- intact until drv_cleanup is called. */
- for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
+ /* Remove AGP resources, but leave dev->agp
+ intact until drv_cleanup is called. */
+ for (entry = dev->agp->memory; entry; entry = nexte) {
nexte = entry->next;
- if ( entry->bound ) drm_unbind_agp( entry->memory );
- drm_free_agp( entry->memory, entry->pages );
- drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
+ if (entry->bound)
+ drm_unbind_agp(entry->memory);
+ drm_free_agp(entry->memory, entry->pages);
+ drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
}
dev->agp->memory = NULL;
- if ( dev->agp->acquired ) drm_agp_do_release(dev);
+ if (dev->agp->acquired)
+ drm_agp_release(dev);
dev->agp->acquired = 0;
- dev->agp->enabled = 0;
+ dev->agp->enabled = 0;
+ }
+ if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+ drm_sg_cleanup(dev->sg);
+ dev->sg = NULL;
}
- /* Clear vma list (only built for debugging) */
- if ( dev->vmalist ) {
- for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
+ /* Clear vma list (only built for debugging) */
+ if (dev->vmalist) {
+ for (vma = dev->vmalist; vma; vma = vma_next) {
vma_next = vma->next;
- drm_free( vma, sizeof(*vma), DRM_MEM_VMAS );
+ drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
}
dev->vmalist = NULL;
}
- if( dev->maplist ) {
- list_for_each_safe( list, list_next, &dev->maplist->head ) {
- r_list = (drm_map_list_t *)list;
-
- if ( ( map = r_list->map ) ) {
- switch ( map->type ) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (drm_core_has_MTRR(dev)) {
- if ( map->mtrr >= 0 ) {
- int retcode;
- retcode = mtrr_del( map->mtrr,
- map->offset,
- map->size );
- DRM_DEBUG( "mtrr_del=%d\n", retcode );
- }
- }
- drm_ioremapfree( map->handle, map->size, dev );
- break;
- case _DRM_SHM:
- vfree(map->handle);
- break;
-
- case _DRM_AGP:
- /* Do nothing here, because this is all
- * handled in the AGP/GART driver.
- */
- break;
- case _DRM_SCATTER_GATHER:
- /* Handle it */
- if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
- drm_sg_cleanup(dev->sg);
- dev->sg = NULL;
- }
- break;
- }
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- }
- list_del( list );
- drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
- }
- drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
- dev->maplist = NULL;
- }
-
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
- for ( i = 0 ; i < dev->queue_count ; i++ ) {
- if ( dev->queuelist[i] ) {
- drm_free( dev->queuelist[i],
- sizeof(*dev->queuelist[0]),
- DRM_MEM_QUEUES );
+ if (dev->maplist) {
+ while (!list_empty(&dev->maplist->head)) {
+ struct list_head *list = dev->maplist->head.next;
+ r_list = list_entry(list, drm_map_list_t, head);
+ drm_rmmap_locked(dev, r_list->map);
+ }
+ }
+
+ if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
+ for (i = 0; i < dev->queue_count; i++) {
+ if (dev->queuelist[i]) {
+ drm_free(dev->queuelist[i],
+ sizeof(*dev->queuelist[0]),
+ DRM_MEM_QUEUES);
dev->queuelist[i] = NULL;
}
}
- drm_free( dev->queuelist,
- dev->queue_slots * sizeof(*dev->queuelist),
- DRM_MEM_QUEUES );
+ drm_free(dev->queuelist,
+ dev->queue_slots * sizeof(*dev->queuelist),
+ DRM_MEM_QUEUES);
dev->queuelist = NULL;
}
dev->queue_count = 0;
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- drm_dma_takedown( dev );
+ drm_dma_takedown(dev);
- if ( dev->lock.hw_lock ) {
- dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
+ if (dev->lock.hw_lock) {
+ dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
dev->lock.filp = NULL;
- wake_up_interruptible( &dev->lock.lock_queue );
+ wake_up_interruptible(&dev->lock.lock_queue);
}
- up( &dev->struct_sem );
+ up(&dev->struct_sem);
+ DRM_DEBUG("takedown completed\n");
return 0;
}
-
-
/**
* Module initialization. Called via init_module at module load time, or via
* linux/init/main.c (this is not currently supported).
@@ -278,26 +246,28 @@ int drm_takedown( drm_device_t *dev )
* Initializes an array of drm_device structures, and attempts to
* initialize all available devices, using consecutive minors, registering the
* stubs and initializing the AGP device.
- *
+ *
* Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
* after the initialization for driver customization.
*/
-int drm_init( struct drm_driver *driver )
+int drm_init(struct drm_driver *driver)
{
struct pci_dev *pdev = NULL;
struct pci_device_id *pid;
int i;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
drm_mem_init();
- for (i=0; driver->pci_driver.id_table[i].vendor != 0; i++) {
+ for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
-
- pdev=NULL;
- /* pass back in pdev to account for multiple identical cards */
- while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
+
+ pdev = NULL;
+ /* pass back in pdev to account for multiple identical cards */
+ while ((pdev =
+ pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
+ pid->subdevice, pdev)) != NULL) {
/* stealth mode requires a manual probe */
pci_dev_get(pdev);
drm_get_dev(pdev, pid, driver);
@@ -305,57 +275,63 @@ int drm_init( struct drm_driver *driver )
}
return 0;
}
+
EXPORT_SYMBOL(drm_init);
/**
* Called via cleanup_module() at module unload time.
*
* Cleans up all DRM device, calling takedown().
- *
- * \sa drm_init().
+ *
+ * \sa drm_init
*/
-static void drm_cleanup( drm_device_t *dev )
+static void drm_cleanup(drm_device_t * dev)
{
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
if (!dev) {
DRM_ERROR("cleanup called no dev\n");
return;
}
- drm_takedown( dev );
+ drm_takedown(dev);
+
+ if (dev->maplist) {
+ drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ }
+
+ drm_ctxbitmap_cleanup(dev);
- drm_ctxbitmap_cleanup( dev );
-
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
dev->agp && dev->agp->agp_mtrr >= 0) {
int retval;
- retval = mtrr_del( dev->agp->agp_mtrr,
- dev->agp->agp_info.aper_base,
- dev->agp->agp_info.aper_size*1024*1024 );
- DRM_DEBUG( "mtrr_del=%d\n", retval );
+ retval = mtrr_del(dev->agp->agp_mtrr,
+ dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size * 1024 * 1024);
+ DRM_DEBUG("mtrr_del=%d\n", retval);
}
-
- if (drm_core_has_AGP(dev) && dev->agp ) {
- drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+
+ if (drm_core_has_AGP(dev) && dev->agp) {
+ drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
dev->agp = NULL;
}
if (dev->driver->postcleanup)
dev->driver->postcleanup(dev);
-
+
drm_put_head(&dev->primary);
- if ( drm_put_dev(dev) )
- DRM_ERROR( "Cannot unload module\n" );
+ if (drm_put_dev(dev))
+ DRM_ERROR("Cannot unload module\n");
}
-void drm_exit (struct drm_driver *driver)
+void drm_exit(struct drm_driver *driver)
{
int i;
drm_device_t *dev = NULL;
drm_head_t *head;
-
- DRM_DEBUG( "\n" );
+
+ DRM_DEBUG("\n");
for (i = 0; i < drm_cards_limit; i++) {
head = drm_heads[i];
@@ -363,9 +339,9 @@ void drm_exit (struct drm_driver *driver)
continue;
if (!head->dev)
continue;
- if (head->dev->driver!=driver)
+ if (head->dev->driver != driver)
continue;
- dev=head->dev;
+ dev = head->dev;
}
if (dev) {
/* release the pci driver */
@@ -373,71 +349,70 @@ void drm_exit (struct drm_driver *driver)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
}
- DRM_INFO( "Module unloaded\n" );
+ DRM_INFO("Module unloaded\n");
}
+
EXPORT_SYMBOL(drm_exit);
/** File operations structure */
static struct file_operations drm_stub_fops = {
.owner = THIS_MODULE,
- .open = drm_stub_open
+ .open = drm_stub_open
};
static int __init drm_core_init(void)
{
int ret = -ENOMEM;
-
- drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
- drm_heads = drm_calloc(drm_cards_limit,
- sizeof(*drm_heads), DRM_MEM_STUB);
- if(!drm_heads)
+
+ drm_cards_limit =
+ (drm_cards_limit <
+ DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
+ drm_heads =
+ drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
+ if (!drm_heads)
goto err_p1;
-
+
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
goto err_p1;
-
+
drm_class = drm_sysfs_create(THIS_MODULE, "drm");
if (IS_ERR(drm_class)) {
- printk (KERN_ERR "DRM: Error creating drm class.\n");
+ printk(KERN_ERR "DRM: Error creating drm class.\n");
ret = PTR_ERR(drm_class);
goto err_p2;
}
- drm_proc_root = create_proc_entry("dri", S_IFDIR, NULL);
+ drm_proc_root = proc_mkdir("dri", NULL);
if (!drm_proc_root) {
DRM_ERROR("Cannot create /proc/dri\n");
ret = -1;
goto err_p3;
}
-
- DRM_INFO( "Initialized %s %d.%d.%d %s\n",
- CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL,
- CORE_DATE);
+
+ DRM_INFO("Initialized %s %d.%d.%d %s\n",
+ CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
return 0;
-err_p3:
+ err_p3:
drm_sysfs_destroy(drm_class);
-err_p2:
+ err_p2:
unregister_chrdev(DRM_MAJOR, "drm");
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
-err_p1:
+ err_p1:
return ret;
}
-static void __exit drm_core_exit (void)
+static void __exit drm_core_exit(void)
{
remove_proc_entry("dri", NULL);
drm_sysfs_destroy(drm_class);
unregister_chrdev(DRM_MAJOR, "drm");
- drm_free(drm_heads, sizeof(*drm_heads) *
- drm_cards_limit, DRM_MEM_STUB);
+ drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
}
-
-module_init( drm_core_init );
-module_exit( drm_core_exit );
-
+module_init(drm_core_init);
+module_exit(drm_core_exit);
/**
* Get version information
@@ -450,8 +425,8 @@ module_exit( drm_core_exit );
*
* Fills in the version information in \p arg.
*/
-static int drm_version( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int drm_version(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -459,21 +434,19 @@ static int drm_version( struct inode *inode, struct file *filp,
drm_version_t version;
int ret;
- if ( copy_from_user( &version, argp, sizeof(version) ) )
+ if (copy_from_user(&version, argp, sizeof(version)))
return -EFAULT;
/* version is a required function to return the personality module version */
if ((ret = dev->driver->version(&version)))
return ret;
-
- if ( copy_to_user( argp, &version, sizeof(version) ) )
+
+ if (copy_to_user(argp, &version, sizeof(version)))
return -EFAULT;
return 0;
}
-
-
-/**
+/**
* Called whenever a process performs an ioctl on /dev/drm.
*
* \param inode device inode.
@@ -485,8 +458,8 @@ static int drm_version( struct inode *inode, struct file *filp,
* Looks up the ioctl function in the ::ioctls table, checking for root
* previleges if so required, and dispatches to the respective function.
*/
-int drm_ioctl( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -495,40 +468,43 @@ int drm_ioctl( struct inode *inode, struct file *filp,
unsigned int nr = DRM_IOCTL_NR(cmd);
int retcode = -EINVAL;
- atomic_inc( &dev->ioctl_count );
- atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
+ atomic_inc(&dev->ioctl_count);
+ atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++priv->ioctl_count;
- DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
- current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
- priv->authenticated );
-
+ DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+ current->pid, cmd, nr,
+ (long)old_encode_dev(priv->head->device),
+ priv->authenticated);
+
if (nr < DRIVER_IOCTL_COUNT)
ioctl = &drm_ioctls[nr];
- else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+ else if ((nr >= DRM_COMMAND_BASE)
+ && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
else
goto err_i1;
-
+
func = ioctl->func;
/* is there a local override? */
if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
func = dev->driver->dma_ioctl;
-
- if ( !func ) {
- DRM_DEBUG( "no function\n" );
+
+ if (!func) {
+ DRM_DEBUG("no function\n");
retcode = -EINVAL;
- } else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
- ( ioctl->auth_needed && !priv->authenticated ) ) {
+ } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) ||
+ (ioctl->auth_needed && !priv->authenticated)) {
retcode = -EACCES;
} else {
- retcode = func( inode, filp, cmd, arg );
+ retcode = func(inode, filp, cmd, arg);
}
-
-err_i1:
- atomic_dec( &dev->ioctl_count );
- if (retcode) DRM_DEBUG( "ret = %x\n", retcode);
+
+ err_i1:
+ atomic_dec(&dev->ioctl_count);
+ if (retcode)
+ DRM_DEBUG("ret = %x\n", retcode);
return retcode;
}
-EXPORT_SYMBOL(drm_ioctl);
+EXPORT_SYMBOL(drm_ioctl);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 10e64fde8d78..bf0a740122bf 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -1,7 +1,7 @@
/**
- * \file drm_fops.h
+ * \file drm_fops.c
* File operations for DRM
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Daryll Strauss <daryll@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
@@ -37,55 +37,48 @@
#include "drmP.h"
#include <linux/poll.h>
-static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev);
+static int drm_open_helper(struct inode *inode, struct file *filp,
+ drm_device_t * dev);
-static int drm_setup( drm_device_t *dev )
+static int drm_setup(drm_device_t * dev)
{
int i;
int ret;
- if (dev->driver->presetup)
- {
- ret=dev->driver->presetup(dev);
- if (ret!=0)
+ if (dev->driver->presetup) {
+ ret = dev->driver->presetup(dev);
+ if (ret != 0)
return ret;
}
- atomic_set( &dev->ioctl_count, 0 );
- atomic_set( &dev->vma_count, 0 );
+ atomic_set(&dev->ioctl_count, 0);
+ atomic_set(&dev->vma_count, 0);
dev->buf_use = 0;
- atomic_set( &dev->buf_alloc, 0 );
+ atomic_set(&dev->buf_alloc, 0);
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- {
- i = drm_dma_setup( dev );
- if ( i < 0 )
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
+ i = drm_dma_setup(dev);
+ if (i < 0)
return i;
}
- for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
- atomic_set( &dev->counts[i], 0 );
+ for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+ atomic_set(&dev->counts[i], 0);
- for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
dev->magiclist[i].head = NULL;
dev->magiclist[i].tail = NULL;
}
- dev->maplist = drm_alloc(sizeof(*dev->maplist),
- DRM_MEM_MAPS);
- if(dev->maplist == NULL) return -ENOMEM;
- memset(dev->maplist, 0, sizeof(*dev->maplist));
- INIT_LIST_HEAD(&dev->maplist->head);
-
- dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
- DRM_MEM_CTXLIST);
- if(dev->ctxlist == NULL) return -ENOMEM;
+ dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
+ if (dev->ctxlist == NULL)
+ return -ENOMEM;
memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
INIT_LIST_HEAD(&dev->ctxlist->head);
dev->vmalist = NULL;
dev->sigdata.lock = dev->lock.hw_lock = NULL;
- init_waitqueue_head( &dev->lock.lock_queue );
+ init_waitqueue_head(&dev->lock.lock_queue);
dev->queue_count = 0;
dev->queue_reserved = 0;
dev->queue_slots = 0;
@@ -97,24 +90,21 @@ static int drm_setup( drm_device_t *dev )
dev->last_context = 0;
dev->last_switch = 0;
dev->last_checked = 0;
- init_waitqueue_head( &dev->context_wait );
+ init_waitqueue_head(&dev->context_wait);
dev->if_version = 0;
dev->ctx_start = 0;
dev->lck_start = 0;
- dev->buf_rp = dev->buf;
- dev->buf_wp = dev->buf;
- dev->buf_end = dev->buf + DRM_BSZ;
dev->buf_async = NULL;
- init_waitqueue_head( &dev->buf_readers );
- init_waitqueue_head( &dev->buf_writers );
+ init_waitqueue_head(&dev->buf_readers);
+ init_waitqueue_head(&dev->buf_writers);
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/*
* The kernel's context could be created here, but is now created
- * in drm_dma_enqueue. This is more resource-efficient for
+ * in drm_dma_enqueue. This is more resource-efficient for
* hardware that does not do DMA, but may mean that
* drm_select_queue fails between the time the interrupt is
* initialized and the time the queues are initialized.
@@ -127,7 +117,7 @@ static int drm_setup( drm_device_t *dev )
/**
* Open file.
- *
+ *
* \param inode device inode
* \param filp file pointer.
* \return zero on success or a negative number on failure.
@@ -136,7 +126,7 @@ static int drm_setup( drm_device_t *dev )
* increments the device open count. If the open count was previous at zero,
* i.e., it's the first that the device is open, then calls setup().
*/
-int drm_open( struct inode *inode, struct file *filp )
+int drm_open(struct inode *inode, struct file *filp)
{
drm_device_t *dev = NULL;
int minor = iminor(inode);
@@ -144,26 +134,27 @@ int drm_open( struct inode *inode, struct file *filp )
if (!((minor >= 0) && (minor < drm_cards_limit)))
return -ENODEV;
-
+
if (!drm_heads[minor])
return -ENODEV;
if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
-
- retcode = drm_open_helper( inode, filp, dev );
- if ( !retcode ) {
- atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
- spin_lock( &dev->count_lock );
- if ( !dev->open_count++ ) {
- spin_unlock( &dev->count_lock );
- return drm_setup( dev );
+
+ retcode = drm_open_helper(inode, filp, dev);
+ if (!retcode) {
+ atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+ spin_lock(&dev->count_lock);
+ if (!dev->open_count++) {
+ spin_unlock(&dev->count_lock);
+ return drm_setup(dev);
}
- spin_unlock( &dev->count_lock );
+ spin_unlock(&dev->count_lock);
}
return retcode;
}
+
EXPORT_SYMBOL(drm_open);
/**
@@ -178,7 +169,7 @@ EXPORT_SYMBOL(drm_open);
* data from its list and free it. Decreases the open count and if it reaches
* zero calls takedown().
*/
-int drm_release( struct inode *inode, struct file *filp )
+int drm_release(struct inode *inode, struct file *filp)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev;
@@ -187,7 +178,7 @@ int drm_release( struct inode *inode, struct file *filp )
lock_kernel();
dev = priv->head->dev;
- DRM_DEBUG( "open_count = %d\n", dev->open_count );
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
if (dev->driver->prerelease)
dev->driver->prerelease(dev, filp);
@@ -196,194 +187,199 @@ int drm_release( struct inode *inode, struct file *filp )
* Begin inline drm_release
*/
- DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ current->pid, (long)old_encode_dev(priv->head->device),
+ dev->open_count);
+
+ if (priv->lock_count && dev->lock.hw_lock &&
+ _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
+ dev->lock.filp == filp) {
+ DRM_DEBUG("File %p released, freeing lock for context %d\n",
+ filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
- if ( priv->lock_count && dev->lock.hw_lock &&
- _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
- dev->lock.filp == filp ) {
- DRM_DEBUG( "File %p released, freeing lock for context %d\n",
- filp,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
-
if (dev->driver->release)
dev->driver->release(dev, filp);
- drm_lock_free( dev, &dev->lock.hw_lock->lock,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
+ drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
- /* FIXME: may require heavy-handed reset of
- hardware at this point, possibly
- processed via a callback to the X
- server. */
- }
- else if ( dev->driver->release && priv->lock_count && dev->lock.hw_lock ) {
+ /* FIXME: may require heavy-handed reset of
+ hardware at this point, possibly
+ processed via a callback to the X
+ server. */
+ } else if (dev->driver->release && priv->lock_count
+ && dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */
- DECLARE_WAITQUEUE( entry, current );
+ DECLARE_WAITQUEUE(entry, current);
- add_wait_queue( &dev->lock.lock_queue, &entry );
+ add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
- if ( !dev->lock.hw_lock ) {
+ if (!dev->lock.hw_lock) {
/* Device has been unregistered */
retcode = -EINTR;
break;
}
- if ( drm_lock_take( &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT ) ) {
- dev->lock.filp = filp;
+ if (drm_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
break; /* Got lock */
}
- /* Contention */
+ /* Contention */
schedule();
- if ( signal_pending( current ) ) {
+ if (signal_pending(current)) {
retcode = -ERESTARTSYS;
break;
}
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue( &dev->lock.lock_queue, &entry );
- if( !retcode ) {
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
+ if (!retcode) {
if (dev->driver->release)
dev->driver->release(dev, filp);
- drm_lock_free( dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT );
+ drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT);
}
}
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->release)
- {
+
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)
+ && !dev->driver->release) {
dev->driver->reclaim_buffers(dev, filp);
}
- drm_fasync( -1, filp, 0 );
+ drm_fasync(-1, filp, 0);
- down( &dev->ctxlist_sem );
- if ( dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
+ down(&dev->ctxlist_sem);
+ if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
drm_ctx_list_t *pos, *n;
- list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
- if ( pos->tag == priv &&
- pos->handle != DRM_KERNEL_CONTEXT ) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ if (pos->tag == priv &&
+ pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
- dev->driver->context_dtor(dev, pos->handle);
+ dev->driver->context_dtor(dev,
+ pos->handle);
- drm_ctxbitmap_free( dev, pos->handle );
+ drm_ctxbitmap_free(dev, pos->handle);
- list_del( &pos->head );
- drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ list_del(&pos->head);
+ drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
--dev->ctx_count;
}
}
}
- up( &dev->ctxlist_sem );
+ up(&dev->ctxlist_sem);
- down( &dev->struct_sem );
- if ( priv->remove_auth_on_close == 1 ) {
+ down(&dev->struct_sem);
+ if (priv->remove_auth_on_close == 1) {
drm_file_t *temp = dev->file_first;
- while ( temp ) {
+ while (temp) {
temp->authenticated = 0;
temp = temp->next;
}
}
- if ( priv->prev ) {
+ if (priv->prev) {
priv->prev->next = priv->next;
} else {
- dev->file_first = priv->next;
+ dev->file_first = priv->next;
}
- if ( priv->next ) {
+ if (priv->next) {
priv->next->prev = priv->prev;
} else {
- dev->file_last = priv->prev;
+ dev->file_last = priv->prev;
}
- up( &dev->struct_sem );
-
+ up(&dev->struct_sem);
+
if (dev->driver->free_filp_priv)
dev->driver->free_filp_priv(dev, priv);
- drm_free( priv, sizeof(*priv), DRM_MEM_FILES );
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
/* ========================================================
* End inline drm_release
*/
- atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
- spin_lock( &dev->count_lock );
- if ( !--dev->open_count ) {
- if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
- DRM_ERROR( "Device busy: %d %d\n",
- atomic_read( &dev->ioctl_count ),
- dev->blocked );
- spin_unlock( &dev->count_lock );
+ atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
+ spin_lock(&dev->count_lock);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+ DRM_ERROR("Device busy: %d %d\n",
+ atomic_read(&dev->ioctl_count), dev->blocked);
+ spin_unlock(&dev->count_lock);
unlock_kernel();
return -EBUSY;
}
- spin_unlock( &dev->count_lock );
+ spin_unlock(&dev->count_lock);
unlock_kernel();
- return drm_takedown( dev );
+ return drm_takedown(dev);
}
- spin_unlock( &dev->count_lock );
+ spin_unlock(&dev->count_lock);
unlock_kernel();
return retcode;
}
+
EXPORT_SYMBOL(drm_release);
/**
- * Called whenever a process opens /dev/drm.
+ * Called whenever a process opens /dev/drm.
*
* \param inode device inode.
* \param filp file pointer.
* \param dev device.
* \return zero on success or a negative number on failure.
- *
+ *
* Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev.
*/
-static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
+static int drm_open_helper(struct inode *inode, struct file *filp,
+ drm_device_t * dev)
{
- int minor = iminor(inode);
- drm_file_t *priv;
+ int minor = iminor(inode);
+ drm_file_t *priv;
int ret;
- if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
- if (!drm_cpu_valid()) return -EINVAL;
+ if (filp->f_flags & O_EXCL)
+ return -EBUSY; /* No exclusive opens */
+ if (!drm_cpu_valid())
+ return -EINVAL;
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
- if(!priv) return -ENOMEM;
+ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ if (!priv)
+ return -ENOMEM;
memset(priv, 0, sizeof(*priv));
- filp->private_data = priv;
- priv->uid = current->euid;
- priv->pid = current->pid;
- priv->minor = minor;
- priv->head = drm_heads[minor];
- priv->ioctl_count = 0;
+ filp->private_data = priv;
+ priv->uid = current->euid;
+ priv->pid = current->pid;
+ priv->minor = minor;
+ priv->head = drm_heads[minor];
+ priv->ioctl_count = 0;
priv->authenticated = capable(CAP_SYS_ADMIN);
- priv->lock_count = 0;
+ priv->lock_count = 0;
if (dev->driver->open_helper) {
- ret=dev->driver->open_helper(dev, priv);
+ ret = dev->driver->open_helper(dev, priv);
if (ret < 0)
goto out_free;
}
down(&dev->struct_sem);
if (!dev->file_last) {
- priv->next = NULL;
- priv->prev = NULL;
+ priv->next = NULL;
+ priv->prev = NULL;
dev->file_first = priv;
- dev->file_last = priv;
+ dev->file_last = priv;
} else {
- priv->next = NULL;
- priv->prev = dev->file_last;
+ priv->next = NULL;
+ priv->prev = dev->file_last;
dev->file_last->next = priv;
- dev->file_last = priv;
+ dev->file_last = priv;
}
up(&dev->struct_sem);
@@ -400,42 +396,48 @@ static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t
}
if (!dev->hose) {
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
- if (b) dev->hose = b->sysdata;
+ if (b)
+ dev->hose = b->sysdata;
}
}
#endif
return 0;
-out_free:
+ out_free:
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
- filp->private_data=NULL;
+ filp->private_data = NULL;
return ret;
}
/** No-op. */
int drm_flush(struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
+ current->pid, (long)old_encode_dev(priv->head->device),
+ dev->open_count);
return 0;
}
+
EXPORT_SYMBOL(drm_flush);
/** No-op. */
int drm_fasync(int fd, struct file *filp, int on)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- int retcode;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ int retcode;
- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->head->device));
+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
+ (long)old_encode_dev(priv->head->device));
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
- if (retcode < 0) return retcode;
+ if (retcode < 0)
+ return retcode;
return 0;
}
+
EXPORT_SYMBOL(drm_fasync);
/** No-op. */
@@ -443,5 +445,5 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{
return 0;
}
-EXPORT_SYMBOL(drm_poll);
+EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c
index 62883b749e97..754b934715c4 100644
--- a/drivers/char/drm/drm_init.c
+++ b/drivers/char/drm/drm_init.c
@@ -1,5 +1,5 @@
/**
- * \file drm_init.h
+ * \file drm_init.c
* Setup/Cleanup for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -43,10 +43,11 @@
int drm_cpu_valid(void)
{
#if defined(__i386__)
- if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
+ if (boot_cpu_data.x86 == 3)
+ return 0; /* No cmpxchg on a 386 */
#endif
#if defined(__sparc__) && !defined(__sparc_v9__)
- return 0; /* No cmpxchg before v9 sparc. */
+ return 0; /* No cmpxchg before v9 sparc. */
#endif
return 1;
}
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index 8087a9636399..dd91ff6b474c 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -68,15 +68,15 @@
#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
typedef struct drm_version_32 {
- int version_major; /**< Major version */
- int version_minor; /**< Minor version */
- int version_patchlevel;/**< Patch level */
- u32 name_len; /**< Length of name buffer */
- u32 name; /**< Name of driver */
- u32 date_len; /**< Length of date buffer */
- u32 date; /**< User-space buffer to hold date */
- u32 desc_len; /**< Length of desc buffer */
- u32 desc; /**< User-space buffer to hold desc */
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel; /**< Patch level */
+ u32 name_len; /**< Length of name buffer */
+ u32 name; /**< Name of driver */
+ u32 date_len; /**< Length of date buffer */
+ u32 date; /**< User-space buffer to hold date */
+ u32 desc_len; /**< Length of desc buffer */
+ u32 desc; /**< User-space buffer to hold desc */
} drm_version32_t;
static int compat_drm_version(struct file *file, unsigned int cmd,
@@ -86,7 +86,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
drm_version_t __user *version;
int err;
- if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
+ if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
return -EFAULT;
version = compat_alloc_user_space(sizeof(*version));
@@ -104,7 +104,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_VERSION, (unsigned long) version);
+ DRM_IOCTL_VERSION, (unsigned long)version);
if (err)
return err;
@@ -116,7 +116,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
|| __get_user(v32.desc_len, &version->desc_len))
return -EFAULT;
- if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
+ if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
return -EFAULT;
return 0;
}
@@ -133,25 +133,25 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
drm_unique_t __user *u;
int err;
- if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+ if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
return -EFAULT;
u = compat_alloc_user_space(sizeof(*u));
if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
return -EFAULT;
if (__put_user(uq32.unique_len, &u->unique_len)
- || __put_user((void __user *)(unsigned long) uq32.unique,
+ || __put_user((void __user *)(unsigned long)uq32.unique,
&u->unique))
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
+ DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
if (err)
return err;
if (__get_user(uq32.unique_len, &u->unique_len))
return -EFAULT;
- if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
+ if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
return -EFAULT;
return 0;
}
@@ -162,28 +162,28 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
drm_unique32_t uq32;
drm_unique_t __user *u;
- if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+ if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
return -EFAULT;
u = compat_alloc_user_space(sizeof(*u));
if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
return -EFAULT;
if (__put_user(uq32.unique_len, &u->unique_len)
- || __put_user((void __user *)(unsigned long) uq32.unique,
+ || __put_user((void __user *)(unsigned long)uq32.unique,
&u->unique))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
+ DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
}
typedef struct drm_map32 {
- u32 offset; /**< Requested physical address (0 for SAREA)*/
- u32 size; /**< Requested physical size (bytes) */
- drm_map_type_t type; /**< Type of memory to map */
+ u32 offset; /**< Requested physical address (0 for SAREA)*/
+ u32 size; /**< Requested physical size (bytes) */
+ drm_map_type_t type; /**< Type of memory to map */
drm_map_flags_t flags; /**< Flags */
- u32 handle; /**< User-space: "Handle" to pass to mmap() */
- int mtrr; /**< MTRR slot used */
+ u32 handle; /**< User-space: "Handle" to pass to mmap() */
+ int mtrr; /**< MTRR slot used */
} drm_map32_t;
static int compat_drm_getmap(struct file *file, unsigned int cmd,
@@ -205,7 +205,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_GET_MAP, (unsigned long) map);
+ DRM_IOCTL_GET_MAP, (unsigned long)map);
if (err)
return err;
@@ -217,7 +217,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
|| __get_user(m32.mtrr, &map->mtrr))
return -EFAULT;
- m32.handle = (unsigned long) handle;
+ m32.handle = (unsigned long)handle;
if (copy_to_user(argp, &m32, sizeof(m32)))
return -EFAULT;
return 0;
@@ -246,7 +246,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_ADD_MAP, (unsigned long) map);
+ DRM_IOCTL_ADD_MAP, (unsigned long)map);
if (err)
return err;
@@ -255,8 +255,8 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
|| __get_user(handle, &map->handle))
return -EFAULT;
- m32.handle = (unsigned long) handle;
- if (m32.handle != (unsigned long) handle && printk_ratelimit())
+ m32.handle = (unsigned long)handle;
+ if (m32.handle != (unsigned long)handle && printk_ratelimit())
printk(KERN_ERR "compat_drm_addmap truncated handle"
" %p for type %d offset %x\n",
handle, m32.type, m32.offset);
@@ -280,20 +280,20 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
map = compat_alloc_user_space(sizeof(*map));
if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
return -EFAULT;
- if (__put_user((void *)(unsigned long) handle, &map->handle))
+ if (__put_user((void *)(unsigned long)handle, &map->handle))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RM_MAP, (unsigned long) map);
+ DRM_IOCTL_RM_MAP, (unsigned long)map);
}
typedef struct drm_client32 {
- int idx; /**< Which client desired? */
- int auth; /**< Is client authenticated? */
- u32 pid; /**< Process ID */
- u32 uid; /**< User ID */
- u32 magic; /**< Magic */
- u32 iocs; /**< Ioctl count */
+ int idx; /**< Which client desired? */
+ int auth; /**< Is client authenticated? */
+ u32 pid; /**< Process ID */
+ u32 uid; /**< User ID */
+ u32 magic; /**< Magic */
+ u32 iocs; /**< Ioctl count */
} drm_client32_t;
static int compat_drm_getclient(struct file *file, unsigned int cmd,
@@ -314,7 +314,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_GET_CLIENT, (unsigned long) client);
+ DRM_IOCTL_GET_CLIENT, (unsigned long)client);
if (err)
return err;
@@ -351,7 +351,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_GET_STATS, (unsigned long) stats);
+ DRM_IOCTL_GET_STATS, (unsigned long)stats);
if (err)
return err;
@@ -368,12 +368,12 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
}
typedef struct drm_buf_desc32 {
- int count; /**< Number of buffers of this size */
- int size; /**< Size in bytes */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
- int flags;
- u32 agp_start; /**< Start address in the AGP aperture */
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ int flags;
+ u32 agp_start; /**< Start address in the AGP aperture */
} drm_buf_desc32_t;
static int compat_drm_addbufs(struct file *file, unsigned int cmd,
@@ -395,7 +395,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
+ DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
if (err)
return err;
@@ -427,12 +427,12 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
+ DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
}
typedef struct drm_buf_info32 {
- int count; /**< Entries in list */
- u32 list;
+ int count; /**< Entries in list */
+ u32 list;
} drm_buf_info32_t;
static int compat_drm_infobufs(struct file *file, unsigned int cmd,
@@ -451,7 +451,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
return -EFAULT;
count = req32.count;
- to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
+ to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
if (count < 0)
count = 0;
if (count > 0
@@ -469,7 +469,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_INFO_BUFS, (unsigned long) request);
+ DRM_IOCTL_INFO_BUFS, (unsigned long)request);
if (err)
return err;
@@ -488,16 +488,16 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
}
typedef struct drm_buf_pub32 {
- int idx; /**< Index into the master buffer list */
- int total; /**< Buffer size */
- int used; /**< Amount of buffer in use (for DMA) */
- u32 address; /**< Address of buffer */
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ u32 address; /**< Address of buffer */
} drm_buf_pub32_t;
typedef struct drm_buf_map32 {
- int count; /**< Length of the buffer list */
- u32 virtual; /**< Mmap'd area in user-virtual */
- u32 list; /**< Buffer information */
+ int count; /**< Length of the buffer list */
+ u32 virtual; /**< Mmap'd area in user-virtual */
+ u32 list; /**< Buffer information */
} drm_buf_map32_t;
static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
@@ -531,7 +531,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_MAP_BUFS, (unsigned long) request);
+ DRM_IOCTL_MAP_BUFS, (unsigned long)request);
if (err)
return err;
@@ -542,21 +542,21 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
if (__copy_in_user(&list32[i], &list[i],
offsetof(drm_buf_pub_t, address))
|| __get_user(addr, &list[i].address)
- || __put_user((unsigned long) addr,
+ || __put_user((unsigned long)addr,
&list32[i].address))
return -EFAULT;
if (__put_user(actual, &argp->count)
|| __get_user(addr, &request->virtual)
- || __put_user((unsigned long) addr, &argp->virtual))
+ || __put_user((unsigned long)addr, &argp->virtual))
return -EFAULT;
return 0;
}
typedef struct drm_buf_free32 {
- int count;
- u32 list;
+ int count;
+ u32 list;
} drm_buf_free32_t;
static int compat_drm_freebufs(struct file *file, unsigned int cmd,
@@ -573,17 +573,17 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
return -EFAULT;
if (__put_user(req32.count, &request->count)
- || __put_user((int __user *)(unsigned long) req32.list,
+ || __put_user((int __user *)(unsigned long)req32.list,
&request->list))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_FREE_BUFS, (unsigned long) request);
+ DRM_IOCTL_FREE_BUFS, (unsigned long)request);
}
typedef struct drm_ctx_priv_map32 {
- unsigned int ctx_id; /**< Context requesting private mapping */
- u32 handle; /**< Handle of map */
+ unsigned int ctx_id; /**< Context requesting private mapping */
+ u32 handle; /**< Handle of map */
} drm_ctx_priv_map32_t;
static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
@@ -600,12 +600,12 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
return -EFAULT;
if (__put_user(req32.ctx_id, &request->ctx_id)
- || __put_user((void *)(unsigned long) req32.handle,
+ || __put_user((void *)(unsigned long)req32.handle,
&request->handle))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
+ DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
}
static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
@@ -628,20 +628,20 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
+ DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
if (err)
return err;
if (__get_user(handle, &request->handle)
- || __put_user((unsigned long) handle, &argp->handle))
+ || __put_user((unsigned long)handle, &argp->handle))
return -EFAULT;
return 0;
}
typedef struct drm_ctx_res32 {
- int count;
- u32 contexts;
+ int count;
+ u32 contexts;
} drm_ctx_res32_t;
static int compat_drm_resctx(struct file *file, unsigned int cmd,
@@ -659,12 +659,12 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
return -EFAULT;
if (__put_user(res32.count, &res->count)
- || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
+ || __put_user((drm_ctx_t __user *) (unsigned long)res32.contexts,
&res->contexts))
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RES_CTX, (unsigned long) res);
+ DRM_IOCTL_RES_CTX, (unsigned long)res);
if (err)
return err;
@@ -676,23 +676,23 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
}
typedef struct drm_dma32 {
- int context; /**< Context handle */
- int send_count; /**< Number of buffers to send */
- u32 send_indices; /**< List of handles to buffers */
- u32 send_sizes; /**< Lengths of data to send */
+ int context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ u32 send_indices; /**< List of handles to buffers */
+ u32 send_sizes; /**< Lengths of data to send */
drm_dma_flags_t flags; /**< Flags */
- int request_count; /**< Number of buffers requested */
- int request_size; /**< Desired size for buffers */
- u32 request_indices; /**< Buffer information */
- u32 request_sizes;
- int granted_count; /**< Number of buffers granted */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size for buffers */
+ u32 request_indices; /**< Buffer information */
+ u32 request_sizes;
+ int granted_count; /**< Number of buffers granted */
} drm_dma32_t;
static int compat_drm_dma(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_dma32_t d32;
- drm_dma32_t __user *argp = (void __user *) arg;
+ drm_dma32_t __user *argp = (void __user *)arg;
drm_dma_t __user *d;
int err;
@@ -705,20 +705,20 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
if (__put_user(d32.context, &d->context)
|| __put_user(d32.send_count, &d->send_count)
- || __put_user((int __user *)(unsigned long) d32.send_indices,
+ || __put_user((int __user *)(unsigned long)d32.send_indices,
&d->send_indices)
- || __put_user((int __user *)(unsigned long) d32.send_sizes,
+ || __put_user((int __user *)(unsigned long)d32.send_sizes,
&d->send_sizes)
|| __put_user(d32.flags, &d->flags)
|| __put_user(d32.request_count, &d->request_count)
- || __put_user((int __user *)(unsigned long) d32.request_indices,
+ || __put_user((int __user *)(unsigned long)d32.request_indices,
&d->request_indices)
- || __put_user((int __user *)(unsigned long) d32.request_sizes,
+ || __put_user((int __user *)(unsigned long)d32.request_sizes,
&d->request_sizes))
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_DMA, (unsigned long) d);
+ DRM_IOCTL_DMA, (unsigned long)d);
if (err)
return err;
@@ -751,19 +751,19 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
+ DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
}
typedef struct drm_agp_info32 {
- int agp_version_major;
- int agp_version_minor;
- u32 mode;
- u32 aperture_base; /* physical address */
- u32 aperture_size; /* bytes */
- u32 memory_allowed; /* bytes */
- u32 memory_used;
-
- /* PCI information */
+ int agp_version_major;
+ int agp_version_minor;
+ u32 mode;
+ u32 aperture_base; /* physical address */
+ u32 aperture_size; /* bytes */
+ u32 memory_allowed; /* bytes */
+ u32 memory_used;
+
+ /* PCI information */
unsigned short id_vendor;
unsigned short id_device;
} drm_agp_info32_t;
@@ -781,7 +781,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_INFO, (unsigned long) info);
+ DRM_IOCTL_AGP_INFO, (unsigned long)info);
if (err)
return err;
@@ -806,7 +806,7 @@ typedef struct drm_agp_buffer32 {
u32 size; /**< In bytes -- will round to page boundary */
u32 handle; /**< Used for binding / unbinding */
u32 type; /**< Type of memory to allocate */
- u32 physical; /**< Physical used by i810 */
+ u32 physical; /**< Physical used by i810 */
} drm_agp_buffer32_t;
static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
@@ -827,7 +827,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
+ DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
if (err)
return err;
@@ -835,7 +835,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
|| __get_user(req32.physical, &request->physical)
|| copy_to_user(argp, &req32, sizeof(req32))) {
drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_FREE, (unsigned long) request);
+ DRM_IOCTL_AGP_FREE, (unsigned long)request);
return -EFAULT;
}
@@ -856,7 +856,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_FREE, (unsigned long) request);
+ DRM_IOCTL_AGP_FREE, (unsigned long)request);
}
typedef struct drm_agp_binding32 {
@@ -881,7 +881,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_BIND, (unsigned long) request);
+ DRM_IOCTL_AGP_BIND, (unsigned long)request);
}
static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
@@ -898,9 +898,9 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
+ DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
}
-#endif /* __OS_HAS_AGP */
+#endif /* __OS_HAS_AGP */
typedef struct drm_scatter_gather32 {
u32 size; /**< In bytes -- will round to page boundary */
@@ -923,7 +923,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_SG_ALLOC, (unsigned long) request);
+ DRM_IOCTL_SG_ALLOC, (unsigned long)request);
if (err)
return err;
@@ -950,7 +950,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_SG_FREE, (unsigned long) request);
+ DRM_IOCTL_SG_FREE, (unsigned long)request);
}
struct drm_wait_vblank_request32 {
@@ -990,7 +990,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
return -EFAULT;
err = drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
+ DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
if (err)
return err;
@@ -1059,11 +1059,12 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
lock_kernel(); /* XXX for now */
if (fn != NULL)
- ret = (*fn)(filp, cmd, arg);
+ ret = (*fn) (filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
}
+
EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 39afda0ccabe..9b0feba6b063 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -1,5 +1,5 @@
/**
- * \file drm_ioctl.h
+ * \file drm_ioctl.c
* IOCTL processing for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -40,7 +40,7 @@
/**
* Get the bus id.
- *
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
@@ -50,12 +50,12 @@
* Copies the bus id from drm_device::unique into user space.
*/
int drm_getunique(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_unique_t __user *argp = (void __user *)arg;
- drm_unique_t u;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_unique_t __user *argp = (void __user *)arg;
+ drm_unique_t u;
if (copy_from_user(&u, argp, sizeof(u)))
return -EFAULT;
@@ -71,7 +71,7 @@ int drm_getunique(struct inode *inode, struct file *filp,
/**
* Set the bus id.
- *
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
@@ -84,34 +84,39 @@ int drm_getunique(struct inode *inode, struct file *filp,
* version 1.1 or greater.
*/
int drm_setunique(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_unique_t u;
- int domain, bus, slot, func, ret;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_unique_t u;
+ int domain, bus, slot, func, ret;
- if (dev->unique_len || dev->unique) return -EBUSY;
+ if (dev->unique_len || dev->unique)
+ return -EBUSY;
- if (copy_from_user(&u, (drm_unique_t __user *)arg, sizeof(u)))
+ if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
return -EFAULT;
- if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
+ if (!u.unique_len || u.unique_len > 1024)
+ return -EINVAL;
dev->unique_len = u.unique_len;
- dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
- if(!dev->unique) return -ENOMEM;
+ dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
+ if (!dev->unique)
+ return -ENOMEM;
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
return -EFAULT;
dev->unique[dev->unique_len] = '\0';
- dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + strlen(dev->unique) + 2,
- DRM_MEM_DRIVER);
+ dev->devname =
+ drm_alloc(strlen(dev->driver->pci_driver.name) +
+ strlen(dev->unique) + 2, DRM_MEM_DRIVER);
if (!dev->devname)
return -ENOMEM;
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
+ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ dev->unique);
/* Return error if the busid submitted doesn't match the device's actual
* busid.
@@ -121,18 +126,16 @@ int drm_setunique(struct inode *inode, struct file *filp,
return DRM_ERR(EINVAL);
domain = bus >> 8;
bus &= 0xff;
-
+
if ((domain != dev->pci_domain) ||
(bus != dev->pci_bus) ||
- (slot != dev->pci_slot) ||
- (func != dev->pci_func))
+ (slot != dev->pci_slot) || (func != dev->pci_func))
return -EINVAL;
return 0;
}
-static int
-drm_set_busid(drm_device_t *dev)
+static int drm_set_busid(drm_device_t * dev)
{
if (dev->unique != NULL)
return EBUSY;
@@ -143,19 +146,20 @@ drm_set_busid(drm_device_t *dev)
return ENOMEM;
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
- dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+ dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
- dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 2,
- DRM_MEM_DRIVER);
+ dev->devname =
+ drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
+ 2, DRM_MEM_DRIVER);
if (dev->devname == NULL)
return ENOMEM;
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
+ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ dev->unique);
return 0;
}
-
/**
* Get a mapping information.
*
@@ -163,23 +167,23 @@ drm_set_busid(drm_device_t *dev)
* \param filp file pointer.
* \param cmd command.
* \param arg user argument, pointing to a drm_map structure.
- *
+ *
* \return zero on success or a negative number on failure.
*
* Searches for the mapping with the specified offset and copies its information
* into userspace
*/
-int drm_getmap( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_getmap(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t __user *argp = (void __user *)arg;
- drm_map_t map;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_map_t __user *argp = (void __user *)arg;
+ drm_map_t map;
drm_map_list_t *r_list = NULL;
struct list_head *list;
- int idx;
- int i;
+ int idx;
+ int i;
if (copy_from_user(&map, argp, sizeof(map)))
return -EFAULT;
@@ -193,26 +197,27 @@ int drm_getmap( struct inode *inode, struct file *filp,
i = 0;
list_for_each(list, &dev->maplist->head) {
- if(i == idx) {
+ if (i == idx) {
r_list = list_entry(list, drm_map_list_t, head);
break;
}
i++;
}
- if(!r_list || !r_list->map) {
+ if (!r_list || !r_list->map) {
up(&dev->struct_sem);
return -EINVAL;
}
map.offset = r_list->map->offset;
- map.size = r_list->map->size;
- map.type = r_list->map->type;
- map.flags = r_list->map->flags;
- map.handle = r_list->map->handle;
- map.mtrr = r_list->map->mtrr;
+ map.size = r_list->map->size;
+ map.type = r_list->map->type;
+ map.flags = r_list->map->flags;
+ map.handle = (void *)(unsigned long)r_list->user_token;
+ map.mtrr = r_list->map->mtrr;
up(&dev->struct_sem);
- if (copy_to_user(argp, &map, sizeof(map))) return -EFAULT;
+ if (copy_to_user(argp, &map, sizeof(map)))
+ return -EFAULT;
return 0;
}
@@ -223,83 +228,81 @@ int drm_getmap( struct inode *inode, struct file *filp,
* \param filp file pointer.
* \param cmd command.
* \param arg user argument, pointing to a drm_client structure.
- *
+ *
* \return zero on success or a negative number on failure.
*
* Searches for the client with the specified index and copies its information
* into userspace
*/
-int drm_getclient( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_getclient(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_client_t __user *argp = (void __user *)arg;
drm_client_t client;
- drm_file_t *pt;
- int idx;
- int i;
+ drm_file_t *pt;
+ int idx;
+ int i;
if (copy_from_user(&client, argp, sizeof(client)))
return -EFAULT;
idx = client.idx;
down(&dev->struct_sem);
- for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
- ;
+ for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
if (!pt) {
up(&dev->struct_sem);
return -EINVAL;
}
- client.auth = pt->authenticated;
- client.pid = pt->pid;
- client.uid = pt->uid;
+ client.auth = pt->authenticated;
+ client.pid = pt->pid;
+ client.uid = pt->uid;
client.magic = pt->magic;
- client.iocs = pt->ioctl_count;
+ client.iocs = pt->ioctl_count;
up(&dev->struct_sem);
- if (copy_to_user((drm_client_t __user *)arg, &client, sizeof(client)))
+ if (copy_to_user((drm_client_t __user *) arg, &client, sizeof(client)))
return -EFAULT;
return 0;
}
-/**
- * Get statistics information.
- *
+/**
+ * Get statistics information.
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
* \param arg user argument, pointing to a drm_stats structure.
- *
+ *
* \return zero on success or a negative number on failure.
*/
-int drm_getstats( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_getstats(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_stats_t stats;
- int i;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_stats_t stats;
+ int i;
memset(&stats, 0, sizeof(stats));
-
+
down(&dev->struct_sem);
for (i = 0; i < dev->counters; i++) {
if (dev->types[i] == _DRM_STAT_LOCK)
stats.data[i].value
- = (dev->lock.hw_lock
- ? dev->lock.hw_lock->lock : 0);
- else
+ = (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
+ else
stats.data[i].value = atomic_read(&dev->counts[i]);
- stats.data[i].type = dev->types[i];
+ stats.data[i].type = dev->types[i];
}
-
+
stats.count = dev->counters;
up(&dev->struct_sem);
- if (copy_to_user((drm_stats_t __user *)arg, &stats, sizeof(stats)))
+ if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
@@ -352,7 +355,8 @@ int drm_setversion(DRM_IOCTL_ARGS)
if (sv.drm_dd_major != -1) {
if (sv.drm_dd_major != version.version_major ||
- sv.drm_dd_minor < 0 || sv.drm_dd_minor > version.version_minor)
+ sv.drm_dd_minor < 0
+ || sv.drm_dd_minor > version.version_minor)
return EINVAL;
if (dev->driver->set_version)
@@ -363,7 +367,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
/** No-op ioctl. */
int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
DRM_DEBUG("\n");
return 0;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index cdd4aecd25e2..b0d4b236e837 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -1,5 +1,5 @@
/**
- * \file drm_irq.h
+ * \file drm_irq.c
* IRQ support
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -39,19 +39,19 @@
/**
* Get interrupt from bus id.
- *
+ *
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
* \param arg user argument, pointing to a drm_irq_busid structure.
* \return zero on success or a negative number on failure.
- *
+ *
* Finds the PCI device with the specified bus id and gets its IRQ number.
* This IOCTL is deprecated, and will now return EINVAL for any busid not equal
* to that of the device that this DRM instance attached to.
*/
int drm_irq_by_busid(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -66,14 +66,12 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
if ((p.busnum >> 8) != dev->pci_domain ||
(p.busnum & 0xff) != dev->pci_bus ||
- p.devnum != dev->pci_slot ||
- p.funcnum != dev->pci_func)
+ p.devnum != dev->pci_slot || p.funcnum != dev->pci_func)
return -EINVAL;
p.irq = dev->irq;
- DRM_DEBUG("%d:%d:%d => IRQ %d\n",
- p.busnum, p.devnum, p.funcnum, p.irq);
+ DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq);
if (copy_to_user(argp, &p, sizeof(p)))
return -EFAULT;
return 0;
@@ -89,61 +87,61 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
* before and after the installation.
*/
-static int drm_irq_install( drm_device_t *dev )
+static int drm_irq_install(drm_device_t * dev)
{
int ret;
- unsigned long sh_flags=0;
+ unsigned long sh_flags = 0;
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
- if ( dev->irq == 0 )
+ if (dev->irq == 0)
return -EINVAL;
- down( &dev->struct_sem );
+ down(&dev->struct_sem);
/* Driver must have been initialized */
- if ( !dev->dev_private ) {
- up( &dev->struct_sem );
+ if (!dev->dev_private) {
+ up(&dev->struct_sem);
return -EINVAL;
}
- if ( dev->irq_enabled ) {
- up( &dev->struct_sem );
+ if (dev->irq_enabled) {
+ up(&dev->struct_sem);
return -EBUSY;
}
dev->irq_enabled = 1;
- up( &dev->struct_sem );
+ up(&dev->struct_sem);
- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+ DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, 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.head );
-
+
+ spin_lock_init(&dev->vbl_lock);
+
+ INIT_LIST_HEAD(&dev->vbl_sigs.head);
+
dev->vbl_pending = 0;
}
- /* Before installing handler */
+ /* Before installing handler */
dev->driver->irq_preinstall(dev);
- /* Install handler */
+ /* Install handler */
if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
sh_flags = SA_SHIRQ;
-
- ret = request_irq( dev->irq, dev->driver->irq_handler,
- sh_flags, dev->devname, dev );
- if ( ret < 0 ) {
- down( &dev->struct_sem );
+
+ ret = request_irq(dev->irq, dev->driver->irq_handler,
+ sh_flags, dev->devname, dev);
+ if (ret < 0) {
+ down(&dev->struct_sem);
dev->irq_enabled = 0;
- up( &dev->struct_sem );
+ up(&dev->struct_sem);
return ret;
}
- /* After installing handler */
+ /* After installing handler */
dev->driver->irq_postinstall(dev);
return 0;
@@ -156,29 +154,30 @@ static int drm_irq_install( drm_device_t *dev )
*
* Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
*/
-int drm_irq_uninstall( drm_device_t *dev )
+int drm_irq_uninstall(drm_device_t * dev)
{
int irq_enabled;
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
- down( &dev->struct_sem );
+ down(&dev->struct_sem);
irq_enabled = dev->irq_enabled;
dev->irq_enabled = 0;
- up( &dev->struct_sem );
+ up(&dev->struct_sem);
- if ( !irq_enabled )
+ if (!irq_enabled)
return -EINVAL;
- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+ DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
dev->driver->irq_uninstall(dev);
- free_irq( dev->irq, dev );
+ free_irq(dev->irq, dev);
return 0;
}
+
EXPORT_SYMBOL(drm_irq_uninstall);
/**
@@ -192,30 +191,30 @@ EXPORT_SYMBOL(drm_irq_uninstall);
*
* Calls irq_install() or irq_uninstall() according to \p arg.
*/
-int drm_control( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_control(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_control_t ctl;
-
+
/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
- if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
+ if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
return -EFAULT;
- switch ( ctl.func ) {
+ switch (ctl.func) {
case DRM_INST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
ctl.irq != dev->irq)
return -EINVAL;
- return drm_irq_install( dev );
+ return drm_irq_install(dev);
case DRM_UNINST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0;
- return drm_irq_uninstall( dev );
+ return drm_irq_uninstall(dev);
default:
return -EINVAL;
}
@@ -230,7 +229,7 @@ int drm_control( struct inode *inode, struct file *filp,
* \param data user argument, pointing to a drm_wait_vblank structure.
* \return zero on success or a negative number on failure.
*
- * Verifies the IRQ is installed.
+ * Verifies the IRQ is installed.
*
* If a signal is requested checks if this task has already scheduled the same signal
* for the same vblank sequence number - nothing to be done in
@@ -240,7 +239,7 @@ int drm_control( struct inode *inode, struct file *filp,
*
* If a signal is not requested, then calls vblank_wait().
*/
-int drm_wait_vblank( DRM_IOCTL_ARGS )
+int drm_wait_vblank(DRM_IOCTL_ARGS)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -256,11 +255,11 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
if (!dev->irq)
return -EINVAL;
- DRM_COPY_FROM_USER_IOCTL( vblwait, argp, sizeof(vblwait) );
+ DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait));
- switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
+ switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
case _DRM_VBLANK_RELATIVE:
- vblwait.request.sequence += atomic_read( &dev->vbl_received );
+ vblwait.request.sequence += atomic_read(&dev->vbl_received);
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
case _DRM_VBLANK_ABSOLUTE:
break;
@@ -269,64 +268,68 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
}
flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
-
- if ( flags & _DRM_VBLANK_SIGNAL ) {
+
+ if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
drm_vbl_sig_t *vbl_sig;
-
- vblwait.reply.sequence = atomic_read( &dev->vbl_received );
- spin_lock_irqsave( &dev->vbl_lock, irqflags );
+ vblwait.reply.sequence = atomic_read(&dev->vbl_received);
+
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Check if this task has already scheduled the same signal
* for the same vblank sequence number; nothing to be done in
* that case
*/
- list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
+ list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) {
if (vbl_sig->sequence == vblwait.request.sequence
&& vbl_sig->info.si_signo == vblwait.request.signal
- && vbl_sig->task == current)
- {
- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+ && vbl_sig->task == current) {
+ spin_unlock_irqrestore(&dev->vbl_lock,
+ irqflags);
goto done;
}
}
- if ( dev->vbl_pending >= 100 ) {
- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+ if (dev->vbl_pending >= 100) {
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
return -EBUSY;
}
dev->vbl_pending++;
- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- if ( !( vbl_sig = drm_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
+ if (!
+ (vbl_sig =
+ drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
return -ENOMEM;
}
- memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
+ memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
vbl_sig->sequence = vblwait.request.sequence;
vbl_sig->info.si_signo = vblwait.request.signal;
vbl_sig->task = current;
- spin_lock_irqsave( &dev->vbl_lock, irqflags );
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
- list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
+ list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head);
- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
} else {
if (dev->driver->vblank_wait)
- ret = dev->driver->vblank_wait( dev, &vblwait.request.sequence );
+ ret =
+ dev->driver->vblank_wait(dev,
+ &vblwait.request.sequence);
- do_gettimeofday( &now );
+ do_gettimeofday(&now);
vblwait.reply.tval_sec = now.tv_sec;
vblwait.reply.tval_usec = now.tv_usec;
}
-done:
- DRM_COPY_TO_USER_IOCTL( argp, vblwait, sizeof(vblwait) );
+ done:
+ DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait));
return ret;
}
@@ -340,31 +343,31 @@ done:
*
* If a signal is not requested, then calls vblank_wait().
*/
-void drm_vbl_send_signals( drm_device_t *dev )
+void drm_vbl_send_signals(drm_device_t * dev)
{
struct list_head *list, *tmp;
drm_vbl_sig_t *vbl_sig;
- unsigned int vbl_seq = atomic_read( &dev->vbl_received );
+ unsigned int vbl_seq = atomic_read(&dev->vbl_received);
unsigned long flags;
- spin_lock_irqsave( &dev->vbl_lock, flags );
+ spin_lock_irqsave(&dev->vbl_lock, flags);
- list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
- vbl_sig = list_entry( list, drm_vbl_sig_t, head );
- if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+ list_for_each_safe(list, tmp, &dev->vbl_sigs.head) {
+ vbl_sig = list_entry(list, drm_vbl_sig_t, 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 );
+ send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info,
+ vbl_sig->task);
- list_del( list );
+ list_del(list);
- drm_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
+ drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER);
dev->vbl_pending--;
}
}
- spin_unlock_irqrestore( &dev->vbl_lock, flags );
+ spin_unlock_irqrestore(&dev->vbl_lock, flags);
}
-EXPORT_SYMBOL(drm_vbl_send_signals);
-
+EXPORT_SYMBOL(drm_vbl_send_signals);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index 4702d863bcc6..b276ae8a6633 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -1,7 +1,7 @@
/**
- * \file drm_lock.h
+ * \file drm_lock.c
* IOCTLs for locking
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -35,12 +35,12 @@
#include "drmP.h"
-static int drm_lock_transfer(drm_device_t *dev,
+static int drm_lock_transfer(drm_device_t * dev,
__volatile__ unsigned int *lock,
unsigned int context);
static int drm_notifier(void *priv);
-/**
+/**
* Lock ioctl.
*
* \param inode device inode.
@@ -51,91 +51,89 @@ static int drm_notifier(void *priv);
*
* Add the current task to the lock wait queue, and attempt to take to lock.
*/
-int drm_lock( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_lock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- DECLARE_WAITQUEUE( entry, current );
- drm_lock_t lock;
- int ret = 0;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ DECLARE_WAITQUEUE(entry, current);
+ drm_lock_t lock;
+ int ret = 0;
++priv->lock_count;
- if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
+ if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
return -EFAULT;
- if ( lock.context == DRM_KERNEL_CONTEXT ) {
- DRM_ERROR( "Process %d using kernel context %d\n",
- current->pid, lock.context );
- return -EINVAL;
- }
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
+ return -EINVAL;
+ }
- DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock.context, current->pid,
- dev->lock.hw_lock->lock, lock.flags );
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, current->pid,
+ dev->lock.hw_lock->lock, lock.flags);
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
- if ( lock.context < 0 )
+ if (lock.context < 0)
return -EINVAL;
- add_wait_queue( &dev->lock.lock_queue, &entry );
+ add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
- if ( !dev->lock.hw_lock ) {
+ if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
break;
}
- if ( drm_lock_take( &dev->lock.hw_lock->lock,
- lock.context ) ) {
- dev->lock.filp = filp;
+ if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
+ dev->lock.filp = filp;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
- break; /* Got lock */
+ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+ break; /* Got lock */
}
-
+
/* Contention */
schedule();
- if ( signal_pending( current ) ) {
+ if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue( &dev->lock.lock_queue, &entry );
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
- sigemptyset( &dev->sigmask );
- sigaddset( &dev->sigmask, SIGSTOP );
- sigaddset( &dev->sigmask, SIGTSTP );
- sigaddset( &dev->sigmask, SIGTTIN );
- sigaddset( &dev->sigmask, SIGTTOU );
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
dev->sigdata.context = lock.context;
- dev->sigdata.lock = dev->lock.hw_lock;
- block_all_signals( drm_notifier,
- &dev->sigdata, &dev->sigmask );
-
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
dev->driver->dma_ready(dev);
-
- if ( dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
+
+ if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT))
return dev->driver->dma_quiescent(dev);
-
- /* dev->driver->kernel_context_switch isn't used by any of the x86
+
+ /* dev->driver->kernel_context_switch isn't used by any of the x86
* drivers but is used by the Sparc driver.
*/
-
- if (dev->driver->kernel_context_switch &&
+
+ if (dev->driver->kernel_context_switch &&
dev->last_context != lock.context) {
- dev->driver->kernel_context_switch(dev, dev->last_context,
- lock.context);
+ dev->driver->kernel_context_switch(dev, dev->last_context,
+ lock.context);
}
- DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
- return ret;
+ return ret;
}
-/**
+/**
* Unlock ioctl.
*
* \param inode device inode.
@@ -146,23 +144,23 @@ int drm_lock( struct inode *inode, struct file *filp,
*
* Transfer and free the lock.
*/
-int drm_unlock( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_unlock(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_lock_t lock;
- if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
+ if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
return -EFAULT;
- if ( lock.context == DRM_KERNEL_CONTEXT ) {
- DRM_ERROR( "Process %d using kernel context %d\n",
- current->pid, lock.context );
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
return -EINVAL;
}
- atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
+ atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
/* kernel_context_switch isn't used by any of the x86 drm
* modules but is required by the Sparc driver.
@@ -170,12 +168,12 @@ int drm_unlock( struct inode *inode, struct file *filp,
if (dev->driver->kernel_context_switch_unlock)
dev->driver->kernel_context_switch_unlock(dev, &lock);
else {
- drm_lock_transfer( dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT );
-
- if ( drm_lock_free( dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT ) ) {
- DRM_ERROR( "\n" );
+ drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT);
+
+ if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
}
}
@@ -198,8 +196,10 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
do {
old = *lock;
- if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
- else new = context | _DRM_LOCK_HELD;
+ if (old & _DRM_LOCK_HELD)
+ new = old | _DRM_LOCK_CONT;
+ else
+ new = context | _DRM_LOCK_HELD;
prev = cmpxchg(lock, old, new);
} while (prev != old);
if (_DRM_LOCKING_CONTEXT(old) == context) {
@@ -212,7 +212,7 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
}
}
if (new == (context | _DRM_LOCK_HELD)) {
- /* Have lock */
+ /* Have lock */
return 1;
}
return 0;
@@ -220,8 +220,8 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
/**
* This takes a lock forcibly and hands it to context. Should ONLY be used
- * inside *_unlock to give lock to kernel before calling *_dma_schedule.
- *
+ * inside *_unlock to give lock to kernel before calling *_dma_schedule.
+ *
* \param dev DRM device.
* \param lock lock pointer.
* \param context locking context.
@@ -230,7 +230,7 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
* Resets the lock file pointer.
* Marks the lock as held by the given context, via the \p cmpxchg instruction.
*/
-static int drm_lock_transfer(drm_device_t *dev,
+static int drm_lock_transfer(drm_device_t * dev,
__volatile__ unsigned int *lock,
unsigned int context)
{
@@ -238,8 +238,8 @@ static int drm_lock_transfer(drm_device_t *dev,
dev->lock.filp = NULL;
do {
- old = *lock;
- new = context | _DRM_LOCK_HELD;
+ old = *lock;
+ new = context | _DRM_LOCK_HELD;
prev = cmpxchg(lock, old, new);
} while (prev != old);
return 1;
@@ -247,30 +247,29 @@ static int drm_lock_transfer(drm_device_t *dev,
/**
* Free lock.
- *
+ *
* \param dev DRM device.
* \param lock lock.
* \param context context.
- *
+ *
* Resets the lock file pointer.
* Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
* waiting on the lock queue.
*/
-int drm_lock_free(drm_device_t *dev,
- __volatile__ unsigned int *lock, unsigned int context)
+int drm_lock_free(drm_device_t * dev,
+ __volatile__ unsigned int *lock, unsigned int context)
{
unsigned int old, new, prev;
dev->lock.filp = NULL;
do {
- old = *lock;
- new = 0;
+ old = *lock;
+ new = 0;
prev = cmpxchg(lock, old, new);
} while (prev != old);
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
DRM_ERROR("%d freed heavyweight lock held by %d\n",
- context,
- _DRM_LOCKING_CONTEXT(old));
+ context, _DRM_LOCKING_CONTEXT(old));
return 1;
}
wake_up_interruptible(&dev->lock.lock_queue);
@@ -290,19 +289,19 @@ int drm_lock_free(drm_device_t *dev,
*/
static int drm_notifier(void *priv)
{
- drm_sigdata_t *s = (drm_sigdata_t *)priv;
- unsigned int old, new, prev;
-
+ drm_sigdata_t *s = (drm_sigdata_t *) priv;
+ unsigned int old, new, prev;
- /* Allow signal delivery if lock isn't held */
+ /* Allow signal delivery if lock isn't held */
if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
- || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
+ || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
+ return 1;
- /* Otherwise, set flag to force call to
- drmUnlock */
+ /* Otherwise, set flag to force call to
+ drmUnlock */
do {
- old = s->lock->lock;
- new = old | _DRM_LOCK_CONT;
+ old = s->lock->lock;
+ new = old | _DRM_LOCK_CONT;
prev = cmpxchg(&s->lock->lock, old, new);
} while (prev != old);
return 0;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index ace3d42f4407..2c74155aa84f 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -1,12 +1,12 @@
-/**
- * \file drm_memory.h
+/**
+ * \file drm_memory.c
* Memory management wrappers for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
-/*
+/*
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -48,7 +48,7 @@ void drm_mem_init(void)
/**
* Called when "/proc/dri/%dev%/mem" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -57,10 +57,10 @@ void drm_mem_init(void)
* \param data private data.
* \return number of written bytes.
*
- * No-op.
+ * No-op.
*/
int drm_mem_info(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
+ int len, int *eof, void *data)
{
return 0;
}
@@ -70,7 +70,8 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
{
void *pt;
- if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL;
+ if (!(pt = kmalloc(size, GFP_KERNEL)))
+ return NULL;
if (oldpt && oldsize) {
memcpy(pt, oldpt, oldsize);
kfree(oldpt);
@@ -90,21 +91,20 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
unsigned long drm_alloc_pages(int order, int area)
{
unsigned long address;
- unsigned long bytes = PAGE_SIZE << order;
+ unsigned long bytes = PAGE_SIZE << order;
unsigned long addr;
- unsigned int sz;
+ unsigned int sz;
address = __get_free_pages(GFP_KERNEL, order);
- if (!address)
+ if (!address)
return 0;
- /* Zero */
+ /* Zero */
memset((void *)address, 0, bytes);
- /* Reserve */
+ /* Reserve */
for (addr = address, sz = bytes;
- sz > 0;
- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
SetPageReserved(virt_to_page(addr));
}
@@ -113,7 +113,7 @@ unsigned long drm_alloc_pages(int order, int area)
/**
* Free pages.
- *
+ *
* \param address address of the pages to free.
* \param order size order.
* \param area memory area. (Not used.)
@@ -124,45 +124,51 @@ void drm_free_pages(unsigned long address, int order, int area)
{
unsigned long bytes = PAGE_SIZE << order;
unsigned long addr;
- unsigned int sz;
+ unsigned int sz;
- if (!address)
+ if (!address)
return;
/* Unreserve */
for (addr = address, sz = bytes;
- sz > 0;
- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
}
free_pages(address, order);
}
-
#if __OS_HAS_AGP
/** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
{
- return drm_agp_allocate_memory(bridge, pages, type);
+ return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
}
+EXPORT_SYMBOL(drm_alloc_agp);
+
/** Wrapper around agp_free_memory() */
-int drm_free_agp(DRM_AGP_MEM *handle, int pages)
+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)
+int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
{
return drm_agp_bind_memory(handle, start);
}
+EXPORT_SYMBOL(drm_bind_agp);
+
/** Wrapper around agp_unbind_memory() */
-int drm_unbind_agp(DRM_AGP_MEM *handle)
+int drm_unbind_agp(DRM_AGP_MEM * handle)
{
return drm_agp_unbind_memory(handle);
}
-#endif /* agp */
-#endif /* debug_memory */
+
+EXPORT_SYMBOL(drm_unbind_agp);
+#endif /* agp */
+#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index 422b94268709..3732a61c3762 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -1,12 +1,12 @@
-/**
- * \file drm_memory.h
+/**
+ * \file drm_memory.h
* Memory management wrappers for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
-/*
+/*
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -40,7 +40,7 @@
/**
* Cut down version of drm_memory_debug.h, which used to be called
- * drm_memory.h.
+ * drm_memory.h.
*/
#if __OS_HAS_AGP
@@ -60,8 +60,8 @@
/*
* Find the drm_map that covers the range [offset, offset+size).
*/
-static inline drm_map_t *
-drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
{
struct list_head *list;
drm_map_list_t *r_list;
@@ -72,16 +72,18 @@ drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
map = r_list->map;
if (!map)
continue;
- if (map->offset <= offset && (offset + size) <= (map->offset + map->size))
+ if (map->offset <= offset
+ && (offset + size) <= (map->offset + map->size))
return map;
}
return NULL;
}
-static inline void *
-agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
{
- unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE;
+ unsigned long *phys_addr_map, i, num_pages =
+ PAGE_ALIGN(size) / PAGE_SIZE;
struct drm_agp_mem *agpmem;
struct page **page_map;
void *addr;
@@ -94,7 +96,8 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
if (agpmem->bound <= offset
- && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size))
+ && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+ (offset + size))
break;
if (!agpmem)
return NULL;
@@ -109,7 +112,8 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
if (!page_map)
return NULL;
- phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ phys_addr_map =
+ agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
for (i = 0; i < num_pages; ++i)
page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
@@ -118,36 +122,38 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
return addr;
}
-static inline unsigned long
-drm_follow_page (void *vaddr)
+static inline unsigned long drm_follow_page(void *vaddr)
{
- pgd_t *pgd = pgd_offset_k((unsigned long) vaddr);
- pud_t *pud = pud_offset(pgd, (unsigned long) vaddr);
- pmd_t *pmd = pmd_offset(pud, (unsigned long) vaddr);
- pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr);
+ pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
+ pud_t *pud = pud_offset(pgd, (unsigned long)vaddr);
+ pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr);
+ pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr);
return pte_pfn(*ptep) << PAGE_SHIFT;
}
-#else /* __OS_HAS_AGP */
+#else /* __OS_HAS_AGP */
-static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
{
- return NULL;
+ return NULL;
}
-static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
{
- return NULL;
+ return NULL;
}
-static inline unsigned long drm_follow_page (void *vaddr)
+static inline unsigned long drm_follow_page(void *vaddr)
{
- return 0;
+ return 0;
}
#endif
-static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
+static inline void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
{
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
drm_map_t *map = drm_lookup_map(offset, size, dev);
@@ -158,8 +164,8 @@ static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_de
return ioremap(offset, size);
}
-static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
- drm_device_t *dev)
+static inline void *drm_ioremap_nocache(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
{
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
drm_map_t *map = drm_lookup_map(offset, size, dev);
@@ -170,7 +176,8 @@ static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size
return ioremap_nocache(offset, size);
}
-static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
+static inline void drm_ioremapfree(void *pt, unsigned long size,
+ drm_device_t * dev)
{
/*
* This is a bit ugly. It would be much cleaner if the DRM API would use separate
@@ -178,12 +185,12 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
* a future revision of the interface...
*/
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
- && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
- {
+ && ((unsigned long)pt >= VMALLOC_START
+ && (unsigned long)pt < VMALLOC_END)) {
unsigned long offset;
drm_map_t *map;
- offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK);
+ offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
map = drm_lookup_map(offset, size, dev);
if (map && map->type == _DRM_AGP) {
vunmap(pt);
@@ -193,5 +200,3 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
iounmap(pt);
}
-
-
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 2c82e69a7fd2..4542353195bd 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -1,5 +1,5 @@
/**
- * \file drm_memory.h
+ * \file drm_memory.h
* Memory management wrappers for DRM.
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -35,75 +35,75 @@
#include "drmP.h"
typedef struct drm_mem_stats {
- const char *name;
- int succeed_count;
- int free_count;
- int fail_count;
- unsigned long bytes_allocated;
- unsigned long bytes_freed;
+ const char *name;
+ int succeed_count;
+ int free_count;
+ int fail_count;
+ unsigned long bytes_allocated;
+ unsigned long bytes_freed;
} drm_mem_stats_t;
static DEFINE_SPINLOCK(DRM(mem_lock));
-static unsigned long DRM(ram_available) = 0; /* In pages */
-static unsigned long DRM(ram_used) = 0;
-static drm_mem_stats_t DRM(mem_stats)[] = {
- [DRM_MEM_DMA] = { "dmabufs" },
- [DRM_MEM_SAREA] = { "sareas" },
- [DRM_MEM_DRIVER] = { "driver" },
- [DRM_MEM_MAGIC] = { "magic" },
- [DRM_MEM_IOCTLS] = { "ioctltab" },
- [DRM_MEM_MAPS] = { "maplist" },
- [DRM_MEM_VMAS] = { "vmalist" },
- [DRM_MEM_BUFS] = { "buflist" },
- [DRM_MEM_SEGS] = { "seglist" },
- [DRM_MEM_PAGES] = { "pagelist" },
- [DRM_MEM_FILES] = { "files" },
- [DRM_MEM_QUEUES] = { "queues" },
- [DRM_MEM_CMDS] = { "commands" },
- [DRM_MEM_MAPPINGS] = { "mappings" },
- [DRM_MEM_BUFLISTS] = { "buflists" },
- [DRM_MEM_AGPLISTS] = { "agplist" },
- [DRM_MEM_SGLISTS] = { "sglist" },
- [DRM_MEM_TOTALAGP] = { "totalagp" },
- [DRM_MEM_BOUNDAGP] = { "boundagp" },
- [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
- [DRM_MEM_CTXLIST] = { "ctxlist" },
- [DRM_MEM_STUB] = { "stub" },
- { NULL, 0, } /* Last entry must be null */
+static unsigned long DRM(ram_available) = 0; /* In pages */
+static unsigned long DRM(ram_used) = 0;
+static drm_mem_stats_t DRM(mem_stats)[] =
+{
+ [DRM_MEM_DMA] = {
+ "dmabufs"},[DRM_MEM_SAREA] = {
+ "sareas"},[DRM_MEM_DRIVER] = {
+ "driver"},[DRM_MEM_MAGIC] = {
+ "magic"},[DRM_MEM_IOCTLS] = {
+ "ioctltab"},[DRM_MEM_MAPS] = {
+ "maplist"},[DRM_MEM_VMAS] = {
+ "vmalist"},[DRM_MEM_BUFS] = {
+ "buflist"},[DRM_MEM_SEGS] = {
+ "seglist"},[DRM_MEM_PAGES] = {
+ "pagelist"},[DRM_MEM_FILES] = {
+ "files"},[DRM_MEM_QUEUES] = {
+ "queues"},[DRM_MEM_CMDS] = {
+ "commands"},[DRM_MEM_MAPPINGS] = {
+ "mappings"},[DRM_MEM_BUFLISTS] = {
+ "buflists"},[DRM_MEM_AGPLISTS] = {
+ "agplist"},[DRM_MEM_SGLISTS] = {
+ "sglist"},[DRM_MEM_TOTALAGP] = {
+ "totalagp"},[DRM_MEM_BOUNDAGP] = {
+ "boundagp"},[DRM_MEM_CTXBITMAP] = {
+ "ctxbitmap"},[DRM_MEM_CTXLIST] = {
+ "ctxlist"},[DRM_MEM_STUB] = {
+ "stub"}, {
+ NULL, 0,} /* Last entry must be null */
};
-void DRM(mem_init)(void)
-{
+void DRM(mem_init) (void) {
drm_mem_stats_t *mem;
- struct sysinfo si;
+ struct sysinfo si;
for (mem = DRM(mem_stats); mem->name; ++mem) {
- mem->succeed_count = 0;
- mem->free_count = 0;
- mem->fail_count = 0;
+ mem->succeed_count = 0;
+ mem->free_count = 0;
+ mem->fail_count = 0;
mem->bytes_allocated = 0;
- mem->bytes_freed = 0;
+ mem->bytes_freed = 0;
}
si_meminfo(&si);
DRM(ram_available) = si.totalram;
- DRM(ram_used) = 0;
+ DRM(ram_used) = 0;
}
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
-static int DRM(_mem_info)(char *buf, char **start, off_t offset,
- int request, int *eof, void *data)
-{
+static int DRM(_mem_info) (char *buf, char **start, off_t offset,
+ int request, int *eof, void *data) {
drm_mem_stats_t *pt;
- int len = 0;
+ int len = 0;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
return 0;
}
- *eof = 0;
+ *eof = 0;
*start = &buf[offset];
DRM_PROC_PRINT(" total counts "
@@ -129,24 +129,23 @@ static int DRM(_mem_info)(char *buf, char **start, off_t offset,
- (long)pt->bytes_freed);
}
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
-int DRM(mem_info)(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
-{
+int DRM(mem_info) (char *buf, char **start, off_t offset,
+ int len, int *eof, void *data) {
int ret;
spin_lock(&DRM(mem_lock));
- ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
+ ret = DRM(_mem_info) (buf, start, offset, len, eof, data);
spin_unlock(&DRM(mem_lock));
return ret;
}
-void *DRM(alloc)(size_t size, int area)
-{
+void *DRM(alloc) (size_t size, int area) {
void *pt;
if (!size) {
@@ -167,40 +166,40 @@ void *DRM(alloc)(size_t size, int area)
return pt;
}
-void *DRM(calloc)(size_t nmemb, size_t size, int area)
-{
+void *DRM(calloc) (size_t nmemb, size_t size, int area) {
void *addr;
- addr = DRM(alloc)(nmemb * size, area);
+ addr = DRM(alloc) (nmemb * size, area);
if (addr != NULL)
memset((void *)addr, 0, size * nmemb);
return addr;
}
-void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
-{
+void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) {
void *pt;
- if (!(pt = DRM(alloc)(size, area))) return NULL;
+ if (!(pt = DRM(alloc) (size, area)))
+ return NULL;
if (oldpt && oldsize) {
memcpy(pt, oldpt, oldsize);
- DRM(free)(oldpt, oldsize, area);
+ DRM(free) (oldpt, oldsize, area);
}
return pt;
}
-void DRM(free)(void *pt, size_t size, int area)
-{
+void DRM(free) (void *pt, size_t size, int area) {
int alloc_count;
int free_count;
- if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
- else kfree(pt);
+ if (!pt)
+ DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+ else
+ kfree(pt);
spin_lock(&DRM(mem_lock));
DRM(mem_stats)[area].bytes_freed += size;
- free_count = ++DRM(mem_stats)[area].free_count;
- alloc_count = DRM(mem_stats)[area].succeed_count;
+ free_count = ++DRM(mem_stats)[area].free_count;
+ alloc_count = DRM(mem_stats)[area].succeed_count;
spin_unlock(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
@@ -208,12 +207,11 @@ void DRM(free)(void *pt, size_t size, int area)
}
}
-unsigned long DRM(alloc_pages)(int order, int area)
-{
+unsigned long DRM(alloc_pages) (int order, int area) {
unsigned long address;
- unsigned long bytes = PAGE_SIZE << order;
+ unsigned long bytes = PAGE_SIZE << order;
unsigned long addr;
- unsigned int sz;
+ unsigned int sz;
spin_lock(&DRM(mem_lock));
if ((DRM(ram_used) >> PAGE_SHIFT)
@@ -233,48 +231,44 @@ unsigned long DRM(alloc_pages)(int order, int area)
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[area].succeed_count;
DRM(mem_stats)[area].bytes_allocated += bytes;
- DRM(ram_used) += bytes;
+ DRM(ram_used) += bytes;
spin_unlock(&DRM(mem_lock));
-
- /* Zero outside the lock */
+ /* Zero outside the lock */
memset((void *)address, 0, bytes);
- /* Reserve */
+ /* Reserve */
for (addr = address, sz = bytes;
- sz > 0;
- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
SetPageReserved(virt_to_page(addr));
}
return address;
}
-void DRM(free_pages)(unsigned long address, int order, int area)
-{
+void DRM(free_pages) (unsigned long address, int order, int area) {
unsigned long bytes = PAGE_SIZE << order;
- int alloc_count;
- int free_count;
+ int alloc_count;
+ int free_count;
unsigned long addr;
- unsigned int sz;
+ unsigned int sz;
if (!address) {
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
} else {
- /* Unreserve */
+ /* Unreserve */
for (addr = address, sz = bytes;
- sz > 0;
- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
}
free_pages(address, order);
}
spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[area].free_count;
- alloc_count = DRM(mem_stats)[area].succeed_count;
+ free_count = ++DRM(mem_stats)[area].free_count;
+ alloc_count = DRM(mem_stats)[area].succeed_count;
DRM(mem_stats)[area].bytes_freed += bytes;
- DRM(ram_used) -= bytes;
+ DRM(ram_used) -= bytes;
spin_unlock(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(area,
@@ -283,8 +277,8 @@ void DRM(free_pages)(unsigned long address, int order, int area)
}
}
-void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
-{
+void *DRM(ioremap) (unsigned long offset, unsigned long size,
+ drm_device_t * dev) {
void *pt;
if (!size) {
@@ -306,8 +300,8 @@ void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
return pt;
}
-void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
-{
+void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
+ drm_device_t * dev) {
void *pt;
if (!size) {
@@ -329,8 +323,7 @@ void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_
return pt;
}
-void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
-{
+void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
int alloc_count;
int free_count;
@@ -342,8 +335,8 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
spin_lock(&DRM(mem_lock));
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
- free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
- alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+ free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
spin_unlock(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
@@ -354,8 +347,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
#if __OS_HAS_AGP
-DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
-{
+DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
DRM_AGP_MEM *handle;
if (!pages) {
@@ -363,11 +355,11 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
return NULL;
}
- if ((handle = DRM(agp_allocate_memory)(pages, type))) {
+ if ((handle = DRM(agp_allocate_memory) (pages, type))) {
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
- += pages << PAGE_SHIFT;
+ += pages << PAGE_SHIFT;
spin_unlock(&DRM(mem_lock));
return handle;
}
@@ -377,11 +369,10 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
return NULL;
}
-int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
-{
- int alloc_count;
- int free_count;
- int retval = -EINVAL;
+int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
+ int alloc_count;
+ int free_count;
+ int retval = -EINVAL;
if (!handle) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
@@ -389,12 +380,12 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
return retval;
}
- if (DRM(agp_free_memory)(handle)) {
+ if (DRM(agp_free_memory) (handle)) {
spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
- alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+ free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
- += pages << PAGE_SHIFT;
+ += pages << PAGE_SHIFT;
spin_unlock(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
@@ -406,8 +397,7 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
return retval;
}
-int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
-{
+int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
int retcode = -EINVAL;
if (!handle) {
@@ -416,11 +406,11 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
return retcode;
}
- if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
+ if (!(retcode = DRM(agp_bind_memory) (handle, start))) {
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
- += handle->page_count << PAGE_SHIFT;
+ += handle->page_count << PAGE_SHIFT;
spin_unlock(&DRM(mem_lock));
return retcode;
}
@@ -430,8 +420,7 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
return retcode;
}
-int DRM(unbind_agp)(DRM_AGP_MEM *handle)
-{
+int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
int alloc_count;
int free_count;
int retcode = -EINVAL;
@@ -442,12 +431,13 @@ int DRM(unbind_agp)(DRM_AGP_MEM *handle)
return retcode;
}
- if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
+ if ((retcode = DRM(agp_unbind_memory) (handle)))
+ return retcode;
spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
+ free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
- += handle->page_count << PAGE_SHIFT;
+ += handle->page_count << PAGE_SHIFT;
spin_unlock(&DRM(mem_lock));
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index b14cd370dea5..d51aeb4966f4 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -3,7 +3,6 @@
* OS abstraction macros.
*/
-
#include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h>
@@ -47,25 +46,25 @@
#else
/* define some dummy types for non AGP supporting kernels */
struct no_agp_kern {
- unsigned long aper_base;
- unsigned long aper_size;
+ unsigned long aper_base;
+ unsigned long aper_size;
};
#define DRM_AGP_MEM int
#define DRM_AGP_KERN struct no_agp_kern
#endif
#if !(__OS_HAS_MTRR)
-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
- unsigned int type, char increment)
+static __inline__ int mtrr_add(unsigned long base, unsigned long size,
+ unsigned int type, char increment)
{
return -ENODEV;
}
-static __inline__ int mtrr_del (int reg, unsigned long base,
- unsigned long size)
+static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
{
return -ENODEV;
}
+
#define MTRR_TYPE_WRCOMB 1
#endif
@@ -99,7 +98,7 @@ static __inline__ int mtrr_del (int reg, unsigned long base,
#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
-/**
+/**
* Get the pointer to the SAREA.
*
* Searches the SAREA on the mapping lists and points drm_device::sarea to it.
@@ -143,7 +142,5 @@ do { \
remove_wait_queue(&(queue), &entry); \
} while (0)
-
#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
-
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 192e8762571c..1fd7ff164817 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -46,11 +46,11 @@
/**
* \brief Allocate a PCI consistent memory block, for DMA.
*/
-void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
- dma_addr_t maxaddr, dma_addr_t * busaddr)
+drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+ dma_addr_t maxaddr)
{
- void *address;
-#if DRM_DEBUG_MEMORY
+ drm_dma_handle_t *dmah;
+#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
spin_lock(&drm_mem_lock);
@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
return NULL;
}
- address = pci_alloc_consistent(dev->pdev, size, busaddr);
+ dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+ if (!dmah)
+ return NULL;
+
+ dmah->size = size;
+ dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
-#if DRM_DEBUG_MEMORY
- if (address == NULL) {
+#ifdef DRM_DEBUG_MEMORY
+ if (dmah->vaddr == NULL) {
spin_lock(&drm_mem_lock);
++drm_mem_stats[area].fail_count;
spin_unlock(&drm_mem_lock);
+ kfree(dmah);
return NULL;
}
@@ -90,37 +96,42 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
drm_ram_used += size;
spin_unlock(&drm_mem_lock);
#else
- if (address == NULL)
+ if (dmah->vaddr == NULL) {
+ kfree(dmah);
return NULL;
+ }
#endif
- memset(address, 0, size);
+ memset(dmah->vaddr, 0, size);
- return address;
+ return dmah;
}
+
EXPORT_SYMBOL(drm_pci_alloc);
/**
- * \brief Free a PCI consistent memory block.
+ * \brief Free a PCI consistent memory block with freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
*/
-void
-drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
+void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
{
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
int alloc_count;
int free_count;
#endif
- if (!vaddr) {
-#if DRM_DEBUG_MEMORY
+ if (!dmah->vaddr) {
+#ifdef DRM_DEBUG_MEMORY
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif
} else {
- pci_free_consistent(dev->pdev, size, vaddr, busaddr);
+ pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
+ dmah->busaddr);
}
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
spin_lock(&drm_mem_lock);
free_count = ++drm_mem_stats[area].free_count;
alloc_count = drm_mem_stats[area].succeed_count;
@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
#endif
}
+
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+{
+ __drm_pci_free(dev, dmah);
+ kfree(dmah);
+}
+
EXPORT_SYMBOL(drm_pci_free);
/*@}*/
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 70ca4fa55c9d..d66dc55e29a0 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -25,6 +25,8 @@
{0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
{0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
{0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
+ {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+ {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
{0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
@@ -33,7 +35,17 @@
{0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+ {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
@@ -56,6 +68,7 @@
{0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
{0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
@@ -116,9 +129,10 @@
{0, 0, 0}
#define mga_PCI_IDS \
- {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+ {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+ {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \
+ {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \
{0, 0, 0}
#define mach64_PCI_IDS \
@@ -162,9 +176,10 @@
#define viadrv_PCI_IDS \
{0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
#define i810_PCI_IDS \
@@ -181,33 +196,30 @@
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
-#define gamma_PCI_IDS \
- {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0, 0, 0}
-
#define savage_PCI_IDS \
- {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+ {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+ {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+ {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+ {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+ {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+ {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+ {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+ {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+ {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+ {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
+ {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
{0, 0, 0}
#define ffb_PCI_IDS \
@@ -222,11 +234,3 @@
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
-
-#define viadrv_PCI_IDS \
- {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0, 0, 0}
-
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 4774087d2e9e..3f452f763f0f 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -1,5 +1,5 @@
/**
- * \file drm_proc.h
+ * \file drm_proc.c
* /proc support for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -39,19 +39,19 @@
#include "drmP.h"
-static int drm_name_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-static int drm_vm_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-static int drm_clients_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-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_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_vm_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+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);
#if DRM_DEBUG_CODE
-static int drm_vma_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
+static int drm_vma_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
#endif
/**
@@ -59,18 +59,21 @@ 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*/
+ int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
} 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}, {
+ "mem", drm_mem_info}, {
+ "vm", drm_vm_info}, {
+ "clients", drm_clients_info}, {
+ "queues", drm_queues_info}, {
+ "bufs", drm_bufs_info},
#if DRM_DEBUG_CODE
- { "vma", drm_vma_info },
+ {
+ "vma", drm_vma_info},
#endif
};
+
#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
/**
@@ -81,21 +84,20 @@ static struct drm_proc_list {
* \param root DRI proc dir entry.
* \param dev_root resulting DRI device proc dir entry.
* \return root entry pointer on success, or NULL on failure.
- *
+ *
* Create the DRI proc root entry "/proc/dri", the device proc root entry
* "/proc/dri/%minor%/", and each entry in proc_list as
* "/proc/dri/%minor%/%name%".
*/
-int drm_proc_init(drm_device_t *dev, int minor,
- struct proc_dir_entry *root,
- struct proc_dir_entry **dev_root)
+int drm_proc_init(drm_device_t * dev, int minor,
+ struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
{
struct proc_dir_entry *ent;
- int i, j;
- char name[64];
+ int i, j;
+ char name[64];
sprintf(name, "%d", minor);
- *dev_root = create_proc_entry(name, S_IFDIR, root);
+ *dev_root = proc_mkdir(name, root);
if (!*dev_root) {
DRM_ERROR("Cannot create /proc/dri/%s\n", name);
return -1;
@@ -103,7 +105,7 @@ int drm_proc_init(drm_device_t *dev, int minor,
for (i = 0; i < DRM_PROC_ENTRIES; i++) {
ent = create_proc_entry(drm_proc_list[i].name,
- S_IFREG|S_IRUGO, *dev_root);
+ S_IFREG | S_IRUGO, *dev_root);
if (!ent) {
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
name, drm_proc_list[i].name);
@@ -114,13 +116,12 @@ int drm_proc_init(drm_device_t *dev, int minor,
return -1;
}
ent->read_proc = drm_proc_list[i].f;
- ent->data = dev;
+ ent->data = dev;
}
return 0;
}
-
/**
* Cleanup the proc filesystem resources.
*
@@ -132,12 +133,13 @@ int drm_proc_init(drm_device_t *dev, int minor,
* Remove all proc entries created by proc_init().
*/
int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
- struct proc_dir_entry *dev_root)
+ struct proc_dir_entry *dev_root)
{
- int i;
+ int i;
char name[64];
- if (!root || !dev_root) return 0;
+ if (!root || !dev_root)
+ return 0;
for (i = 0; i < DRM_PROC_ENTRIES; i++)
remove_proc_entry(drm_proc_list[i].name, dev_root);
@@ -149,7 +151,7 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
/**
* Called when "/proc/dri/.../name" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -157,14 +159,14 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
* \param eof whether there is no more data to return.
* \param data private data.
* \return number of written bytes.
- *
+ *
* Prints the device name together with the bus id if available.
*/
static int drm_name_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -172,23 +174,26 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
if (dev->unique) {
DRM_PROC_PRINT("%s %s %s\n",
- dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
+ dev->driver->pci_driver.name,
+ pci_name(dev->pdev), dev->unique);
} else {
- DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
+ DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
+ pci_name(dev->pdev));
}
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
/**
* Called when "/proc/dri/.../vm" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -196,24 +201,24 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
* \param eof whether there is no more data to return.
* \param data private data.
* \return number of written bytes.
- *
+ *
* Prints information about all mappings in drm_device::maplist.
*/
static int drm__vm_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
- drm_map_t *map;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
+ drm_map_t *map;
drm_map_list_t *r_list;
struct list_head *list;
- /* Hardcoded from _DRM_FRAME_BUFFER,
- _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
- _DRM_SCATTER_GATHER. */
- const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
- const char *type;
- int i;
+ /* Hardcoded from _DRM_FRAME_BUFFER,
+ _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
+ _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+ const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
+ const char *type;
+ int i;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -221,33 +226,35 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
DRM_PROC_PRINT("slot offset size type flags "
"address mtrr\n\n");
i = 0;
- if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
+ if (dev->maplist != NULL)
+ list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
- if(!map) continue;
- if (map->type < 0 || map->type > 4) type = "??";
- else type = types[map->type];
- DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
+ if (!map)
+ continue;
+ if (map->type < 0 || map->type > 5)
+ type = "??";
+ else
+ type = types[map->type];
+ DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
i,
map->offset,
- map->size,
- type,
- map->flags,
- (unsigned long)map->handle);
+ map->size, type, map->flags, r_list->user_token);
if (map->mtrr < 0) {
DRM_PROC_PRINT("none\n");
} else {
DRM_PROC_PRINT("%4d\n", map->mtrr);
}
i++;
- }
+ }
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
@@ -256,10 +263,10 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
* Simply calls _vm_info() while holding the drm_device::struct_sem lock.
*/
static int drm_vm_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int ret;
+ drm_device_t *dev = (drm_device_t *) data;
+ int ret;
down(&dev->struct_sem);
ret = drm__vm_info(buf, start, offset, request, eof, data);
@@ -269,7 +276,7 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
/**
* Called when "/proc/dri/.../queues" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -279,12 +286,12 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
* \return number of written bytes.
*/
static int drm__queues_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data)
+ int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
- int i;
- drm_queue_t *q;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
+ int i;
+ drm_queue_t *q;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -292,7 +299,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
DRM_PROC_PRINT(" ctx/flags use fin"
" blk/rw/rwf wait flushed queued"
@@ -310,14 +317,17 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
atomic_read(&q->block_count),
atomic_read(&q->block_read) ? 'r' : '-',
atomic_read(&q->block_write) ? 'w' : '-',
- waitqueue_active(&q->read_queue) ? 'r':'-',
- waitqueue_active(&q->write_queue) ? 'w':'-',
- waitqueue_active(&q->flush_queue) ? 'f':'-',
+ waitqueue_active(&q->read_queue) ? 'r' : '-',
+ waitqueue_active(&q->
+ write_queue) ? 'w' : '-',
+ waitqueue_active(&q->
+ flush_queue) ? 'f' : '-',
DRM_BUFCOUNT(&q->waitlist));
atomic_dec(&q->use_count);
}
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
@@ -326,10 +336,10 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
* Simply calls _queues_info() while holding the drm_device::struct_sem lock.
*/
static int drm_queues_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int ret;
+ drm_device_t *dev = (drm_device_t *) data;
+ int ret;
down(&dev->struct_sem);
ret = drm__queues_info(buf, start, offset, request, eof, data);
@@ -339,7 +349,7 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
/**
* Called when "/proc/dri/.../bufs" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -349,12 +359,12 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
* \return number of written bytes.
*/
static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
drm_device_dma_t *dma = dev->dma;
- int i;
+ int i;
if (!dma || offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -362,7 +372,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
for (i = 0; i <= DRM_MAX_ORDER; i++) {
@@ -375,19 +385,21 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
.freelist.count),
dma->bufs[i].seg_count,
dma->bufs[i].seg_count
- *(1 << dma->bufs[i].page_order),
+ * (1 << dma->bufs[i].page_order),
(dma->bufs[i].seg_count
* (1 << dma->bufs[i].page_order))
* PAGE_SIZE / 1024);
}
DRM_PROC_PRINT("\n");
for (i = 0; i < dma->buf_count; i++) {
- if (i && !(i%32)) DRM_PROC_PRINT("\n");
+ if (i && !(i % 32))
+ DRM_PROC_PRINT("\n");
DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
}
DRM_PROC_PRINT("\n");
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
@@ -396,10 +408,10 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
* Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
*/
static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int ret;
+ drm_device_t *dev = (drm_device_t *) data;
+ int ret;
down(&dev->struct_sem);
ret = drm__bufs_info(buf, start, offset, request, eof, data);
@@ -409,7 +421,7 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
/**
* Called when "/proc/dri/.../clients" is read.
- *
+ *
* \param buf output buffer.
* \param start start of output data.
* \param offset requested start offset.
@@ -419,11 +431,11 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
* \return number of written bytes.
*/
static int drm__clients_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data)
+ int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
- drm_file_t *priv;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
+ drm_file_t *priv;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -431,7 +443,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
for (priv = dev->file_first; priv; priv = priv->next) {
@@ -439,12 +451,11 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
priv->authenticated ? 'y' : 'n',
priv->minor,
priv->pid,
- priv->uid,
- priv->magic,
- priv->ioctl_count);
+ priv->uid, priv->magic, priv->ioctl_count);
}
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
@@ -453,10 +464,10 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
* Simply calls _clients_info() while holding the drm_device::struct_sem lock.
*/
static int drm_clients_info(char *buf, char **start, off_t offset,
- int request, int *eof, void *data)
+ int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int ret;
+ drm_device_t *dev = (drm_device_t *) data;
+ int ret;
down(&dev->struct_sem);
ret = drm__clients_info(buf, start, offset, request, eof, data);
@@ -467,14 +478,14 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
#if DRM_DEBUG_CODE
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int len = 0;
- drm_vma_entry_t *pt;
+ drm_device_t *dev = (drm_device_t *) data;
+ int len = 0;
+ drm_vma_entry_t *pt;
struct vm_area_struct *vma;
#if defined(__i386__)
- unsigned int pgprot;
+ unsigned int pgprot;
#endif
if (offset > DRM_PROC_LIMIT) {
@@ -483,51 +494,53 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
}
*start = &buf[offset];
- *eof = 0;
+ *eof = 0;
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
atomic_read(&dev->vma_count),
high_memory, virt_to_phys(high_memory));
for (pt = dev->vmalist; pt; pt = pt->next) {
- if (!(vma = pt->vma)) continue;
+ if (!(vma = pt->vma))
+ continue;
DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
pt->pid,
vma->vm_start,
vma->vm_end,
- vma->vm_flags & VM_READ ? 'r' : '-',
- vma->vm_flags & VM_WRITE ? 'w' : '-',
- vma->vm_flags & VM_EXEC ? 'x' : '-',
+ vma->vm_flags & VM_READ ? 'r' : '-',
+ vma->vm_flags & VM_WRITE ? 'w' : '-',
+ vma->vm_flags & VM_EXEC ? 'x' : '-',
vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
- vma->vm_flags & VM_LOCKED ? 'l' : '-',
- vma->vm_flags & VM_IO ? 'i' : '-',
+ vma->vm_flags & VM_LOCKED ? 'l' : '-',
+ vma->vm_flags & VM_IO ? 'i' : '-',
VM_OFFSET(vma));
#if defined(__i386__)
pgprot = pgprot_val(vma->vm_page_prot);
DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
- pgprot & _PAGE_PRESENT ? 'p' : '-',
- pgprot & _PAGE_RW ? 'w' : 'r',
- pgprot & _PAGE_USER ? 'u' : 's',
- pgprot & _PAGE_PWT ? 't' : 'b',
- pgprot & _PAGE_PCD ? 'u' : 'c',
+ pgprot & _PAGE_PRESENT ? 'p' : '-',
+ pgprot & _PAGE_RW ? 'w' : 'r',
+ pgprot & _PAGE_USER ? 'u' : 's',
+ pgprot & _PAGE_PWT ? 't' : 'b',
+ pgprot & _PAGE_PCD ? 'u' : 'c',
pgprot & _PAGE_ACCESSED ? 'a' : '-',
- pgprot & _PAGE_DIRTY ? 'd' : '-',
- pgprot & _PAGE_PSE ? 'm' : 'k',
- pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
+ pgprot & _PAGE_DIRTY ? 'd' : '-',
+ pgprot & _PAGE_PSE ? 'm' : 'k',
+ pgprot & _PAGE_GLOBAL ? 'g' : 'l');
#endif
DRM_PROC_PRINT("\n");
}
- if (len > request + offset) return request;
+ if (len > request + offset)
+ return request;
*eof = 1;
return len - offset;
}
static int drm_vma_info(char *buf, char **start, off_t offset, int request,
- int *eof, void *data)
+ int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *)data;
- int ret;
+ drm_device_t *dev = (drm_device_t *) data;
+ int ret;
down(&dev->struct_sem);
ret = drm__vma_info(buf, start, offset, request, eof, data);
@@ -535,5 +548,3 @@ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
return ret;
}
#endif
-
-
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
index de782ed2f03a..e94297b751b8 100644
--- a/drivers/char/drm/drm_sarea.h
+++ b/drivers/char/drm/drm_sarea.h
@@ -1,5 +1,5 @@
/**
- * \file drm_sarea.h
+ * \file drm_sarea.h
* \brief SAREA definitions
*
* \author Michel Dänzer <michel@daenzer.net>
@@ -38,7 +38,7 @@
#if defined(__alpha__)
#define SAREA_MAX 0x2000
#elif defined(__ia64__)
-#define SAREA_MAX 0x10000 /* 64kB */
+#define SAREA_MAX 0x10000 /* 64kB */
#else
/* Intel 830M driver needs at least 8k SAREA */
#define SAREA_MAX 0x2000
@@ -51,28 +51,28 @@
/** SAREA drawable */
typedef struct drm_sarea_drawable {
- unsigned int stamp;
- unsigned int flags;
+ unsigned int stamp;
+ unsigned int flags;
} drm_sarea_drawable_t;
/** SAREA frame */
typedef struct drm_sarea_frame {
- unsigned int x;
- unsigned int y;
- unsigned int width;
- unsigned int height;
- unsigned int fullscreen;
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned int fullscreen;
} drm_sarea_frame_t;
/** SAREA */
typedef struct drm_sarea {
/** first thing is always the DRM locking structure */
- drm_hw_lock_t lock;
+ drm_hw_lock_t lock;
/** \todo Use readers/writer lock for drm_sarea::drawable_lock */
- drm_hw_lock_t drawable_lock;
- drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
- drm_sarea_frame_t frame; /**< frame */
- drm_context_t dummy_context;
+ drm_hw_lock_t drawable_lock;
+ drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
+ drm_sarea_frame_t frame; /**< frame */
+ drm_context_t dummy_context;
} drm_sarea_t;
-#endif /* _DRM_SAREA_H_ */
+#endif /* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 54fddb6ea2d1..ce81bf248200 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -1,5 +1,5 @@
/**
- * \file drm_scatter.h
+ * \file drm_scatter.c
* IOCTLs to manage scatter/gather memory
*
* \author Gareth Hughes <gareth@valinux.com>
@@ -37,32 +37,34 @@
#define DEBUG_SCATTER 0
-void drm_sg_cleanup( drm_sg_mem_t *entry )
+void drm_sg_cleanup(drm_sg_mem_t * entry)
{
struct page *page;
int i;
- for ( i = 0 ; i < entry->pages ; i++ ) {
+ for (i = 0; i < entry->pages; i++) {
page = entry->pagelist[i];
- if ( page )
- ClearPageReserved( page );
+ if (page)
+ ClearPageReserved(page);
}
- vfree( entry->virtual );
-
- drm_free( entry->busaddr,
- entry->pages * sizeof(*entry->busaddr),
- DRM_MEM_PAGES );
- drm_free( entry->pagelist,
- entry->pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES );
- drm_free( entry,
- sizeof(*entry),
- DRM_MEM_SGLISTS );
+ vfree(entry->virtual);
+
+ drm_free(entry->busaddr,
+ entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
+ drm_free(entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
+ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
}
-int drm_sg_alloc( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+#ifdef _LP64
+# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
+#else
+# define ScatterHandle(x) (unsigned int)(x)
+#endif
+
+int drm_sg_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -71,74 +73,70 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
drm_sg_mem_t *entry;
unsigned long pages, i, j;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
if (!drm_core_check_feature(dev, DRIVER_SG))
return -EINVAL;
- if ( dev->sg )
+ if (dev->sg)
return -EINVAL;
- if ( copy_from_user( &request, argp, sizeof(request) ) )
+ if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
- entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
- if ( !entry )
+ entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
+ if (!entry)
return -ENOMEM;
- memset( entry, 0, sizeof(*entry) );
+ memset(entry, 0, sizeof(*entry));
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
- DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
+ DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages);
entry->pages = pages;
- entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES );
- if ( !entry->pagelist ) {
- drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS );
+ entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES);
+ if (!entry->pagelist) {
+ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
return -ENOMEM;
}
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
- entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr),
- DRM_MEM_PAGES );
- if ( !entry->busaddr ) {
- drm_free( entry->pagelist,
- entry->pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES );
- drm_free( entry,
- sizeof(*entry),
- DRM_MEM_SGLISTS );
+ entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
+ DRM_MEM_PAGES);
+ if (!entry->busaddr) {
+ drm_free(entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES);
+ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
return -ENOMEM;
}
- memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
-
- entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
- if ( !entry->virtual ) {
- drm_free( entry->busaddr,
- entry->pages * sizeof(*entry->busaddr),
- DRM_MEM_PAGES );
- drm_free( entry->pagelist,
- entry->pages * sizeof(*entry->pagelist),
- DRM_MEM_PAGES );
- drm_free( entry,
- sizeof(*entry),
- DRM_MEM_SGLISTS );
+ memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
+
+ entry->virtual = vmalloc_32(pages << PAGE_SHIFT);
+ if (!entry->virtual) {
+ drm_free(entry->busaddr,
+ entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
+ drm_free(entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES);
+ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
return -ENOMEM;
}
/* This also forces the mapping of COW pages, so our page list
* will be valid. Please don't remove it...
*/
- memset( entry->virtual, 0, pages << PAGE_SHIFT );
+ memset(entry->virtual, 0, pages << PAGE_SHIFT);
- entry->handle = (unsigned long)entry->virtual;
+ entry->handle = ScatterHandle((unsigned long)entry->virtual);
- DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
- DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
+ DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
+ DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual);
- for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+ for (i = (unsigned long)entry->virtual, j = 0; j < pages;
+ i += PAGE_SIZE, j++) {
entry->pagelist[j] = vmalloc_to_page((void *)i);
if (!entry->pagelist[j])
goto failed;
@@ -147,8 +145,8 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
request.handle = entry->handle;
- if ( copy_to_user( argp, &request, sizeof(request) ) ) {
- drm_sg_cleanup( entry );
+ if (copy_to_user(argp, &request, sizeof(request))) {
+ drm_sg_cleanup(entry);
return -EFAULT;
}
@@ -159,50 +157,50 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
* versa.
*/
{
- int error = 0;
+ int error = 0;
- for ( i = 0 ; i < pages ; i++ ) {
- unsigned long *tmp;
+ for (i = 0; i < pages; i++) {
+ unsigned long *tmp;
- tmp = page_address( entry->pagelist[i] );
- for ( j = 0 ;
- j < PAGE_SIZE / sizeof(unsigned long) ;
- j++, tmp++ ) {
- *tmp = 0xcafebabe;
- }
- tmp = (unsigned long *)((u8 *)entry->virtual +
- (PAGE_SIZE * i));
- for( j = 0 ;
- j < PAGE_SIZE / sizeof(unsigned long) ;
- j++, tmp++ ) {
- if ( *tmp != 0xcafebabe && error == 0 ) {
- error = 1;
- DRM_ERROR( "Scatter allocation error, "
- "pagelist does not match "
- "virtual mapping\n" );
+ tmp = page_address(entry->pagelist[i]);
+ for (j = 0;
+ j < PAGE_SIZE / sizeof(unsigned long);
+ j++, tmp++) {
+ *tmp = 0xcafebabe;
+ }
+ tmp = (unsigned long *)((u8 *) entry->virtual +
+ (PAGE_SIZE * i));
+ for (j = 0;
+ j < PAGE_SIZE / sizeof(unsigned long);
+ j++, tmp++) {
+ if (*tmp != 0xcafebabe && error == 0) {
+ error = 1;
+ DRM_ERROR("Scatter allocation error, "
+ "pagelist does not match "
+ "virtual mapping\n");
+ }
+ }
+ tmp = page_address(entry->pagelist[i]);
+ for (j = 0;
+ j < PAGE_SIZE / sizeof(unsigned long);
+ j++, tmp++) {
+ *tmp = 0;
}
}
- tmp = page_address( entry->pagelist[i] );
- for(j = 0 ;
- j < PAGE_SIZE / sizeof(unsigned long) ;
- j++, tmp++) {
- *tmp = 0;
- }
- }
- if (error == 0)
- DRM_ERROR( "Scatter allocation matches pagelist\n" );
+ if (error == 0)
+ DRM_ERROR("Scatter allocation matches pagelist\n");
}
#endif
return 0;
- failed:
- drm_sg_cleanup( entry );
+ failed:
+ drm_sg_cleanup(entry);
return -ENOMEM;
}
-int drm_sg_free( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+int drm_sg_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -212,20 +210,20 @@ int drm_sg_free( struct inode *inode, struct file *filp,
if (!drm_core_check_feature(dev, DRIVER_SG))
return -EINVAL;
- if ( copy_from_user( &request,
- (drm_scatter_gather_t __user *)arg,
- sizeof(request) ) )
+ if (copy_from_user(&request,
+ (drm_scatter_gather_t __user *) arg,
+ sizeof(request)))
return -EFAULT;
entry = dev->sg;
dev->sg = NULL;
- if ( !entry || entry->handle != request.handle )
+ if (!entry || entry->handle != request.handle)
return -EINVAL;
- DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
+ DRM_DEBUG("sg free virtual = %p\n", entry->virtual);
- drm_sg_cleanup( entry );
+ drm_sg_cleanup(entry);
return 0;
}
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 48829a1a086a..60b6f8e8bf69 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -37,35 +37,37 @@
#include "drm_core.h"
unsigned int drm_cards_limit = 16; /* Enough for one machine */
-unsigned int drm_debug = 0; /* 1 to enable debug output */
+unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
-MODULE_AUTHOR( CORE_AUTHOR );
-MODULE_DESCRIPTION( CORE_DESC );
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
MODULE_PARM_DESC(debug, "Enable debug output");
module_param_named(cards_limit, drm_cards_limit, int, 0444);
-module_param_named(debug, drm_debug, int, 0666);
+module_param_named(debug, drm_debug, int, 0600);
drm_head_t **drm_heads;
struct drm_sysfs_class *drm_class;
struct proc_dir_entry *drm_proc_root;
-static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
+static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ struct drm_driver *driver)
{
int retcode;
spin_lock_init(&dev->count_lock);
- init_timer( &dev->timer );
- sema_init( &dev->struct_sem, 1 );
- sema_init( &dev->ctxlist_sem, 1 );
+ init_timer(&dev->timer);
+ sema_init(&dev->struct_sem, 1);
+ sema_init(&dev->ctxlist_sem, 1);
- dev->pdev = pdev;
+ dev->pdev = pdev;
#ifdef __alpha__
- dev->hose = pdev->sysdata;
+ dev->hose = pdev->sysdata;
dev->pci_domain = dev->hose->bus->number;
#else
dev->pci_domain = 0;
@@ -75,46 +77,53 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
dev->pci_func = PCI_FUNC(pdev->devfn);
dev->irq = pdev->irq;
+ dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ if (dev->maplist == NULL)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&dev->maplist->head);
+
/* the DRM has 6 basic counters */
dev->counters = 6;
- dev->types[0] = _DRM_STAT_LOCK;
- dev->types[1] = _DRM_STAT_OPENS;
- dev->types[2] = _DRM_STAT_CLOSES;
- dev->types[3] = _DRM_STAT_IOCTLS;
- dev->types[4] = _DRM_STAT_LOCKS;
- dev->types[5] = _DRM_STAT_UNLOCKS;
+ dev->types[0] = _DRM_STAT_LOCK;
+ dev->types[1] = _DRM_STAT_OPENS;
+ dev->types[2] = _DRM_STAT_CLOSES;
+ dev->types[3] = _DRM_STAT_IOCTLS;
+ dev->types[4] = _DRM_STAT_LOCKS;
+ dev->types[5] = _DRM_STAT_UNLOCKS;
dev->driver = driver;
-
+
if (dev->driver->preinit)
if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
- dev->agp = drm_agp_init(dev);
- if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
- DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+ if (drm_device_is_agp(dev))
+ dev->agp = drm_agp_init(dev);
+ if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+ && (dev->agp == NULL)) {
+ DRM_ERROR("Cannot initialize the agpgart module.\n");
retcode = -EINVAL;
goto error_out_unreg;
}
if (drm_core_has_MTRR(dev)) {
if (dev->agp)
- dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
- dev->agp->agp_info.aper_size*1024*1024,
- MTRR_TYPE_WRCOMB,
- 1 );
+ dev->agp->agp_mtrr =
+ mtrr_add(dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size *
+ 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
}
}
- retcode = drm_ctxbitmap_init( dev );
- if( retcode ) {
- DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+ retcode = drm_ctxbitmap_init(dev);
+ if (retcode) {
+ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
goto error_out_unreg;
}
return 0;
-
-error_out_unreg:
+
+ error_out_unreg:
drm_takedown(dev);
return retcode;
}
@@ -134,7 +143,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
int minor = iminor(inode);
int err = -ENODEV;
struct file_operations *old_fops;
-
+
DRM_DEBUG("\n");
if (!((minor >= 0) && (minor < drm_cards_limit)))
@@ -142,7 +151,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
if (!drm_heads[minor])
return -ENODEV;
-
+
if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
@@ -168,7 +177,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
* create the proc init entry via proc_init(). This routines assigns
* minor numbers to secondary heads of multi-headed cards
*/
-static int drm_get_head(drm_device_t *dev, drm_head_t *head)
+static int drm_get_head(drm_device_t * dev, drm_head_t * head)
{
drm_head_t **heads = drm_heads;
int ret;
@@ -178,26 +187,27 @@ static int drm_get_head(drm_device_t *dev, drm_head_t *head)
for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
if (!*heads) {
-
+
*head = (drm_head_t) {
- .dev = dev,
- .device = MKDEV(DRM_MAJOR, minor),
- .minor = minor,
- };
-
- if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
- printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
+ .dev = dev,.device =
+ MKDEV(DRM_MAJOR, minor),.minor = minor,};
+
+ if ((ret =
+ drm_proc_init(dev, minor, drm_proc_root,
+ &head->dev_root))) {
+ printk(KERN_ERR
+ "DRM: Failed to initialize /proc/dri.\n");
goto err_g1;
}
-
head->dev_class = drm_sysfs_device_add(drm_class,
MKDEV(DRM_MAJOR,
minor),
&dev->pdev->dev,
"card%d", minor);
if (IS_ERR(head->dev_class)) {
- printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
+ printk(KERN_ERR
+ "DRM: Error sysfs_device_add.\n");
ret = PTR_ERR(head->dev_class);
goto err_g2;
}
@@ -209,13 +219,14 @@ static int drm_get_head(drm_device_t *dev, drm_head_t *head)
}
DRM_ERROR("out of minors\n");
return -ENOMEM;
-err_g2:
+ err_g2:
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
-err_g1:
- *head = (drm_head_t) {.dev = NULL};
+ err_g1:
+ *head = (drm_head_t) {
+ .dev = NULL};
return ret;
}
-
+
/**
* Register.
*
@@ -228,7 +239,7 @@ err_g1:
* Try and register, if we fail to register, backout previous work.
*/
int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
- struct drm_driver *driver)
+ struct drm_driver *driver)
{
drm_device_t *dev;
int ret;
@@ -255,10 +266,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return 0;
-err_g1:
+ err_g1:
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
return ret;
}
+
EXPORT_SYMBOL(drm_get_dev);
/**
@@ -299,19 +311,19 @@ int drm_put_dev(drm_device_t * dev)
* last minor released.
*
*/
-int drm_put_head(drm_head_t *head)
+int drm_put_head(drm_head_t * head)
{
int minor = head->minor;
-
+
DRM_DEBUG("release secondary minor %d\n", minor);
-
+
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
-
- *head = (drm_head_t){.dev = NULL};
+
+ *head = (drm_head_t) {
+ .dev = NULL};
drm_heads[minor] = NULL;
-
+
return 0;
}
-
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 2fc10c4bbcdf..6d3449761914 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -15,8 +15,11 @@
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
#include "drm_core.h"
+#include "drmP.h"
struct drm_sysfs_class {
struct class_device_attribute attr;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 621220f3f372..3f73aa774c80 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -1,7 +1,7 @@
/**
- * \file drm_vm.h
+ * \file drm_vm.c
* Memory mapping for DRM
- *
+ *
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
@@ -47,82 +47,87 @@ static void drm_vm_close(struct vm_area_struct *vma);
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
- *
+ *
* Find the right map and if it's AGP memory find the real physical page to
* map, get the page, increment the use count and return it.
*/
#if __OS_HAS_AGP
static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
- unsigned long address)
+ unsigned long address)
{
- drm_file_t *priv = vma->vm_file->private_data;
+ drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
+ drm_map_t *map = NULL;
+ drm_map_list_t *r_list;
struct list_head *list;
/*
- * Find the right map
- */
+ * Find the right map
+ */
if (!drm_core_has_AGP(dev))
goto vm_nopage_error;
- if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
+ if (!dev->agp || !dev->agp->cant_use_aperture)
+ goto vm_nopage_error;
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
- if (!map) continue;
- if (map->offset == VM_OFFSET(vma)) break;
+ if (!map)
+ continue;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
}
if (map && map->type == _DRM_AGP) {
unsigned long offset = address - vma->vm_start;
- unsigned long baddr = VM_OFFSET(vma) + offset;
+ unsigned long baddr = map->offset + offset;
struct drm_agp_mem *agpmem;
struct page *page;
#ifdef __alpha__
/*
- * Adjust to a bus-relative address
- */
+ * Adjust to a bus-relative address
+ */
baddr -= dev->hose->mem_space->start;
#endif
/*
- * It's AGP memory - find the real physical page to map
- */
- for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+ * It's AGP memory - find the real physical page to map
+ */
+ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
if (agpmem->bound <= baddr &&
- agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
+ agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
break;
}
- if (!agpmem) goto vm_nopage_error;
+ if (!agpmem)
+ goto vm_nopage_error;
/*
- * Get the page, inc the use count, and return it
- */
+ * Get the page, inc the use count, and return it
+ */
offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
page = virt_to_page(__va(agpmem->memory->memory[offset]));
get_page(page);
- DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
- baddr, __va(agpmem->memory->memory[offset]), offset,
- page_count(page));
+ DRM_DEBUG
+ ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
+ baddr, __va(agpmem->memory->memory[offset]), offset,
+ page_count(page));
return page;
- }
-vm_nopage_error:
- return NOPAGE_SIGBUS; /* Disallow mremap */
+ }
+ vm_nopage_error:
+ return NOPAGE_SIGBUS; /* Disallow mremap */
}
-#else /* __OS_HAS_AGP */
+#else /* __OS_HAS_AGP */
static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
- unsigned long address)
+ unsigned long address)
{
return NOPAGE_SIGBUS;
}
-#endif /* __OS_HAS_AGP */
+#endif /* __OS_HAS_AGP */
/**
* \c nopage method for shared virtual memory.
@@ -130,24 +135,27 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
- *
+ *
* Get the the mapping, find the real physical page to map, get the page, and
* return it.
*/
static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
- unsigned long address)
+ unsigned long address)
{
- drm_map_t *map = (drm_map_t *)vma->vm_private_data;
- unsigned long offset;
- unsigned long i;
- struct page *page;
+ drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+ unsigned long offset;
+ unsigned long i;
+ struct page *page;
- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
- if (!map) return NOPAGE_OOM; /* Nothing allocated */
+ if (address > vma->vm_end)
+ return NOPAGE_SIGBUS; /* Disallow mremap */
+ if (!map)
+ return NOPAGE_OOM; /* Nothing allocated */
- offset = address - vma->vm_start;
+ offset = address - vma->vm_start;
i = (unsigned long)map->handle + offset;
- page = vmalloc_to_page((void *)i);
+ page = (map->type == _DRM_CONSISTENT) ?
+ virt_to_page((void *)i) : vmalloc_to_page((void *)i);
if (!page)
return NOPAGE_OOM;
get_page(page);
@@ -156,19 +164,18 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
return page;
}
-
/**
* \c close method for shared virtual memory.
- *
+ *
* \param vma virtual memory area.
- *
+ *
* Deletes map information if we are the last
* person to close a mapping and it's not in the global maplist.
*/
static void drm_vm_shm_close(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *pt, *prev, *next;
drm_map_t *map;
drm_map_list_t *r_list;
@@ -184,7 +191,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
down(&dev->struct_sem);
for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
next = pt->next;
- if (pt->vma->vm_private_data == map) found_maps++;
+ if (pt->vma->vm_private_data == map)
+ found_maps++;
if (pt->vma == vma) {
if (prev) {
prev->next = pt->next;
@@ -197,8 +205,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
}
}
/* We were the only map that was found */
- if(found_maps == 1 &&
- map->flags & _DRM_REMOVABLE) {
+ if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
/* Check to see if we are in the maplist, if we are not, then
* we delete this mappings information.
*/
@@ -206,10 +213,13 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
list = &dev->maplist->head;
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
- if (r_list->map == map) found_maps++;
+ if (r_list->map == map)
+ found_maps++;
}
- if(!found_maps) {
+ if (!found_maps) {
+ drm_dma_handle_t dmah;
+
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
@@ -228,6 +238,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
case _DRM_AGP:
case _DRM_SCATTER_GATHER:
break;
+ case _DRM_CONSISTENT:
+ dmah.vaddr = map->handle;
+ dmah.busaddr = map->offset;
+ dmah.size = map->size;
+ __drm_pci_free(dev, &dmah);
+ break;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
}
@@ -241,27 +257,29 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
- *
+ *
* Determine the page number from the page offset and get it from drm_device_dma::pagelist.
*/
static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
- unsigned long address)
+ unsigned long address)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
- unsigned long offset;
- unsigned long page_nr;
- struct page *page;
-
- if (!dma) return NOPAGE_SIGBUS; /* Error */
- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
- if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
-
- offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
- page_nr = offset >> PAGE_SHIFT;
- page = virt_to_page((dma->pagelist[page_nr] +
- (offset & (~PAGE_MASK))));
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_device_dma_t *dma = dev->dma;
+ unsigned long offset;
+ unsigned long page_nr;
+ struct page *page;
+
+ if (!dma)
+ return NOPAGE_SIGBUS; /* Error */
+ if (address > vma->vm_end)
+ return NOPAGE_SIGBUS; /* Disallow mremap */
+ if (!dma->pagelist)
+ return NOPAGE_OOM; /* Nothing allocated */
+
+ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
+ page_nr = offset >> PAGE_SHIFT;
+ page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
get_page(page);
@@ -275,13 +293,13 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
- *
+ *
* Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
*/
static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
- unsigned long address)
+ unsigned long address)
{
- drm_map_t *map = (drm_map_t *)vma->vm_private_data;
+ drm_map_t *map = (drm_map_t *) vma->vm_private_data;
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
drm_sg_mem_t *entry = dev->sg;
@@ -290,13 +308,15 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
unsigned long page_offset;
struct page *page;
- if (!entry) return NOPAGE_SIGBUS; /* Error */
- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
- if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
-
+ if (!entry)
+ return NOPAGE_SIGBUS; /* Error */
+ if (address > vma->vm_end)
+ return NOPAGE_SIGBUS; /* Disallow mremap */
+ if (!entry->pagelist)
+ return NOPAGE_OOM; /* Nothing allocated */
offset = address - vma->vm_start;
- map_offset = map->offset - dev->sg->handle;
+ map_offset = map->offset - (unsigned long)dev->sg->virtual;
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
page = entry->pagelist[page_offset];
get_page(page);
@@ -304,107 +324,78 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
return page;
}
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
-
static struct page *drm_vm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type) {
- if (type) *type = VM_FAULT_MINOR;
- return drm_do_vm_nopage(vma, address);
-}
-
-static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type) {
- if (type) *type = VM_FAULT_MINOR;
- return drm_do_vm_shm_nopage(vma, address);
-}
-
-static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type) {
- if (type) *type = VM_FAULT_MINOR;
- return drm_do_vm_dma_nopage(vma, address);
-}
-
-static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type) {
- if (type) *type = VM_FAULT_MINOR;
- return drm_do_vm_sg_nopage(vma, address);
-}
-
-#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */
-
-static struct page *drm_vm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
+ unsigned long address, int *type)
+{
+ if (type)
+ *type = VM_FAULT_MINOR;
return drm_do_vm_nopage(vma, address);
}
static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
+ unsigned long address, int *type)
+{
+ if (type)
+ *type = VM_FAULT_MINOR;
return drm_do_vm_shm_nopage(vma, address);
}
static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
+ unsigned long address, int *type)
+{
+ if (type)
+ *type = VM_FAULT_MINOR;
return drm_do_vm_dma_nopage(vma, address);
}
static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int unused) {
+ unsigned long address, int *type)
+{
+ if (type)
+ *type = VM_FAULT_MINOR;
return drm_do_vm_sg_nopage(vma, address);
}
-#endif
-
-
/** AGP virtual memory operations */
-static struct vm_operations_struct drm_vm_ops = {
+static struct vm_operations_struct drm_vm_ops = {
.nopage = drm_vm_nopage,
- .open = drm_vm_open,
- .close = drm_vm_close,
+ .open = drm_vm_open,
+ .close = drm_vm_close,
};
/** Shared virtual memory operations */
-static struct vm_operations_struct drm_vm_shm_ops = {
+static struct vm_operations_struct drm_vm_shm_ops = {
.nopage = drm_vm_shm_nopage,
- .open = drm_vm_open,
- .close = drm_vm_shm_close,
+ .open = drm_vm_open,
+ .close = drm_vm_shm_close,
};
/** DMA virtual memory operations */
-static struct vm_operations_struct drm_vm_dma_ops = {
+static struct vm_operations_struct drm_vm_dma_ops = {
.nopage = drm_vm_dma_nopage,
- .open = drm_vm_open,
- .close = drm_vm_close,
+ .open = drm_vm_open,
+ .close = drm_vm_close,
};
/** Scatter-gather virtual memory operations */
-static struct vm_operations_struct drm_vm_sg_ops = {
+static struct vm_operations_struct drm_vm_sg_ops = {
.nopage = drm_vm_sg_nopage,
- .open = drm_vm_open,
- .close = drm_vm_close,
+ .open = drm_vm_open,
+ .close = drm_vm_close,
};
-
/**
* \c open method for shared virtual memory.
- *
+ *
* \param vma virtual memory area.
- *
+ *
* Create a new drm_vma_entry structure as the \p vma private data entry and
* add it to drm_device::vmalist.
*/
static void drm_vm_open(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *vma_entry;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -414,26 +405,26 @@ static void drm_vm_open(struct vm_area_struct *vma)
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
down(&dev->struct_sem);
- vma_entry->vma = vma;
+ vma_entry->vma = vma;
vma_entry->next = dev->vmalist;
- vma_entry->pid = current->pid;
- dev->vmalist = vma_entry;
+ vma_entry->pid = current->pid;
+ dev->vmalist = vma_entry;
up(&dev->struct_sem);
}
}
/**
* \c close method for all virtual memory types.
- *
+ *
* \param vma virtual memory area.
- *
+ *
* Search the \p vma private data entry in drm_device::vmalist, unlink it, and
* free it.
*/
static void drm_vm_close(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *pt, *prev;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -461,47 +452,44 @@ static void drm_vm_close(struct vm_area_struct *vma)
* \param filp file pointer.
* \param vma virtual memory area.
* \return zero on success or a negative number on failure.
- *
+ *
* Sets the virtual memory area operations structure to vm_dma_ops, the file
* pointer, and calls vm_open().
*/
static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
drm_device_dma_t *dma;
- unsigned long length = vma->vm_end - vma->vm_start;
+ unsigned long length = vma->vm_end - vma->vm_start;
lock_kernel();
- dev = priv->head->dev;
- dma = dev->dma;
+ dev = priv->head->dev;
+ dma = dev->dma;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
- /* Length must match exact page count */
+ /* Length must match exact page count */
if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
unlock_kernel();
return -EINVAL;
}
unlock_kernel();
- vma->vm_ops = &drm_vm_dma_ops;
+ vma->vm_ops = &drm_vm_dma_ops;
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
- vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
+ vma->vm_flags |= VM_RESERVED; /* Don't swap */
- vma->vm_file = filp; /* Needed for drm_vm_open() */
+ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma);
return 0;
}
-unsigned long drm_core_get_map_ofs(drm_map_t *map)
+unsigned long drm_core_get_map_ofs(drm_map_t * map)
{
return map->offset;
}
+
EXPORT_SYMBOL(drm_core_get_map_ofs);
unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
@@ -512,6 +500,7 @@ unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
return 0;
#endif
}
+
EXPORT_SYMBOL(drm_core_get_reg_ofs);
/**
@@ -520,7 +509,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
* \param filp file pointer.
* \param vma virtual memory area.
* \return zero on success or a negative number on failure.
- *
+ *
* If the virtual memory area has no offset associated with it then it's a DMA
* area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
* checks that the restricted flag is not set, sets the virtual memory operations
@@ -529,17 +518,18 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
*/
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
- unsigned long offset = 0;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_map_t *map = NULL;
+ drm_map_list_t *r_list;
+ unsigned long offset = 0;
struct list_head *list;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
- if ( !priv->authenticated ) return -EACCES;
+ if (!priv->authenticated)
+ return -EACCES;
/* We check for "dma". On Apple's UniNorth, it's valid to have
* the AGP mapped at physical address 0
@@ -547,134 +537,128 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
*/
if (!VM_OFFSET(vma)
#if __OS_HAS_AGP
- && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
+ && (!dev->agp
+ || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
#endif
)
return drm_mmap_dma(filp, vma);
- /* A sequential search of a linked list is
- fine here because: 1) there will only be
- about 5-10 entries in the list and, 2) a
- DRI client only has to do this mapping
- once, so it doesn't have to be optimized
- for performance, even if the list was a
- bit longer. */
+ /* A sequential search of a linked list is
+ fine here because: 1) there will only be
+ about 5-10 entries in the list and, 2) a
+ DRI client only has to do this mapping
+ once, so it doesn't have to be optimized
+ for performance, even if the list was a
+ bit longer. */
list_for_each(list, &dev->maplist->head) {
- unsigned long off;
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
- if (!map) continue;
- off = dev->driver->get_map_ofs(map);
- if (off == VM_OFFSET(vma)) break;
+ if (!map)
+ continue;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
}
- if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
+ if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
- /* Check for valid size. */
- if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
+ /* Check for valid size. */
+ if (map->size != vma->vm_end - vma->vm_start)
+ return -EINVAL;
if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
#if defined(__i386__) || defined(__x86_64__)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
#else
- /* Ye gads this is ugly. With more thought
- we could move this up higher and use
- `protection_map' instead. */
- vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
- __pte(pgprot_val(vma->vm_page_prot)))));
+ /* Ye gads this is ugly. With more thought
+ we could move this up higher and use
+ `protection_map' instead. */
+ vma->vm_page_prot =
+ __pgprot(pte_val
+ (pte_wrprotect
+ (__pte(pgprot_val(vma->vm_page_prot)))));
#endif
}
switch (map->type) {
- case _DRM_AGP:
- if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
- /*
- * On some platforms we can't talk to bus dma address from the CPU, so for
- * memory of type DRM_AGP, we'll deal with sorting out the real physical
- * pages and mappings in nopage()
- */
+ case _DRM_AGP:
+ if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
+ /*
+ * On some platforms we can't talk to bus dma address from the CPU, so for
+ * memory of type DRM_AGP, we'll deal with sorting out the real physical
+ * pages and mappings in nopage()
+ */
#if defined(__powerpc__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
#endif
- vma->vm_ops = &drm_vm_ops;
- break;
- }
- /* fall through to _DRM_FRAME_BUFFER... */
+ vma->vm_ops = &drm_vm_ops;
+ break;
+ }
+ /* fall through to _DRM_FRAME_BUFFER... */
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
- if (VM_OFFSET(vma) >= __pa(high_memory)) {
#if defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
- }
+ if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+ pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+ }
#elif defined(__powerpc__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+ if (map->type == _DRM_REGISTERS)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED;
#endif
- vma->vm_flags |= VM_IO; /* not in core dump */
- }
+ vma->vm_flags |= VM_IO; /* not in core dump */
#if defined(__ia64__)
- if (efi_range_is_wc(vma->vm_start, vma->vm_end -
- vma->vm_start))
+ if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
vma->vm_page_prot =
- pgprot_writecombine(vma->vm_page_prot);
+ pgprot_writecombine(vma->vm_page_prot);
else
- vma->vm_page_prot =
- pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif
offset = dev->driver->get_reg_ofs(dev);
#ifdef __sparc__
if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
- (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ (map->offset + offset) >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
#else
if (io_remap_pfn_range(vma, vma->vm_start,
- (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ (map->offset + offset) >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
#endif
- return -EAGAIN;
+ return -EAGAIN;
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%lx\n",
map->type,
- vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
+ vma->vm_start, vma->vm_end, map->offset + offset);
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
+ case _DRM_CONSISTENT:
+ /* Consistent memory is really like shared memory. It's only
+ * allocate in a different way */
vma->vm_ops = &drm_vm_shm_ops;
vma->vm_private_data = (void *)map;
- /* Don't let this area swap. Change when
- DRM_KERNEL advisory is supported. */
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED;
-#else
+ /* Don't let this area swap. Change when
+ DRM_KERNEL advisory is supported. */
vma->vm_flags |= VM_RESERVED;
-#endif
break;
case _DRM_SCATTER_GATHER:
vma->vm_ops = &drm_vm_sg_ops;
vma->vm_private_data = (void *)map;
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED;
-#else
vma->vm_flags |= VM_RESERVED;
-#endif
- break;
+ break;
default:
return -EINVAL; /* This should never happen. */
}
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
- vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
- vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
+ vma->vm_flags |= VM_RESERVED; /* Don't swap */
- vma->vm_file = filp; /* Needed for drm_vm_open() */
+ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma);
return 0;
}
+
EXPORT_SYMBOL(drm_mmap);
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
index f51812078010..8a6cc2751bc9 100644
--- a/drivers/char/drm/ffb_context.c
+++ b/drivers/char/drm/ffb_context.c
@@ -15,8 +15,7 @@
#include "ffb_drv.h"
-static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
-{
+static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) {
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
int i;
@@ -37,7 +36,7 @@ static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
return i + 1;
}
-static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
+static void ffb_save_context(ffb_dev_priv_t * fpriv, int idx)
{
ffb_fbcPtr ffb = fpriv->regs;
struct ffb_hw_context *ctx;
@@ -94,36 +93,36 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
/* Capture rendering attributes. */
- ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
- ctx->wid = upa_readl(&ffb->wid); /* Current WID */
- ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
- ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
- ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
- ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
- ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
- ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
+ ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
+ ctx->wid = upa_readl(&ffb->wid); /* Current WID */
+ ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
+ ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
+ ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
+ ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
+ ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
+ ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */
ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */
ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */
ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */
- ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
- ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
- ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
- ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
- ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
+ ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
+ ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
+ ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
+ ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
+ ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */
ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */
- ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
- ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
- ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
+ ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
+ ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
+ ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */
- ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
- ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
- ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
- ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
- ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
- ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
- ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
+ ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
+ ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
+ ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
+ ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
+ ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
+ ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
+ ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
/* Auxiliary Clips. */
ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
@@ -135,9 +134,9 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
- ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
- ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
- ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
+ ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
+ ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
+ ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */
/* These registers/features only exist on FFB2 and later chips. */
@@ -145,12 +144,12 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */
ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */
ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */
- ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
- ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
- ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
- ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
- ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
- ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
+ ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
+ ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
+ ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
+ ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
+ ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
+ ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
/* And stencil/stencilctl only exists on FFB2+ and later
* due to the introduction of 3DRAM-III.
@@ -170,7 +169,7 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
ctx->ucsr = upa_readl(&ffb->ucsr);
}
-static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
+static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx)
{
ffb_fbcPtr ffb = fpriv->regs;
struct ffb_hw_context *ctx;
@@ -193,7 +192,7 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
upa_writel(ctx->ppc, &ffb->ppc);
upa_writel(ctx->wid, &ffb->wid);
- upa_writel(ctx->fg, &ffb->fg);
+ upa_writel(ctx->fg, &ffb->fg);
upa_writel(ctx->bg, &ffb->bg);
upa_writel(ctx->xclip, &ffb->xclip);
upa_writel(ctx->fbc, &ffb->fbc);
@@ -237,36 +236,36 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
/* Restore rendering attributes. */
- upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
- upa_writel(ctx->wid, &ffb->wid); /* Current WID */
- upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
- upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
- upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
- upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
- upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
- upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
+ upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
+ upa_writel(ctx->wid, &ffb->wid); /* Current WID */
+ upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
+ upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
+ upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
+ upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
+ upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
+ upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */
upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */
upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */
upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */
- upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
- upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
- upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
- upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
- upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
+ upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
+ upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
+ upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
+ upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
+ upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */
upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */
- upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
- upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
- upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
+ upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
+ upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
+ upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */
- upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
- upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
- upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
- upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
- upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
- upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
- upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
+ upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
+ upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
+ upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
+ upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
+ upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
+ upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
+ upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
/* Auxiliary Clips. */
upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
@@ -278,9 +277,9 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
- upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
- upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
- upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
+ upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
+ upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
+ upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */
/* These registers/features only exist on FFB2 and later chips. */
@@ -354,91 +353,87 @@ static void FFBWait(ffb_fbcPtr ffb)
} while (--limit);
}
-int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
+int ffb_driver_context_switch(drm_device_t * dev, int old, int new)
{
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
#ifdef DRM_DMA_HISTOGRAM
- dev->ctx_start = get_cycles();
+ dev->ctx_start = get_cycles();
#endif
-
- DRM_DEBUG("Context switch from %d to %d\n", old, new);
- if (new == dev->last_context ||
- dev->last_context == 0) {
+ DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+ if (new == dev->last_context || dev->last_context == 0) {
dev->last_context = new;
- return 0;
+ return 0;
}
-
+
FFBWait(fpriv->regs);
ffb_save_context(fpriv, old);
ffb_restore_context(fpriv, old, new);
FFBWait(fpriv->regs);
-
+
dev->last_context = new;
- return 0;
+ return 0;
}
int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_ctx_res_t res;
- drm_ctx_t ctx;
- int i;
+ drm_ctx_res_t res;
+ drm_ctx_t ctx;
+ int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- if (copy_from_user(&res, (drm_ctx_res_t __user *)arg, sizeof(res)))
+ if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res)))
return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- if (copy_to_user(&res.contexts[i],
- &i,
- sizeof(i)))
+ if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- if (copy_to_user((drm_ctx_res_t __user *)arg, &res, sizeof(res)))
+ if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res)))
return -EFAULT;
return 0;
}
-
int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
int idx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
- idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
+ idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
if (idx < 0)
return -ENFILE;
DRM_DEBUG("%d\n", ctx.handle);
ctx.handle = idx;
- if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
+ if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
struct ffb_hw_context *hwctx;
drm_ctx_t ctx;
int idx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
idx = ctx.handle;
@@ -458,16 +453,16 @@ int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
}
int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
struct ffb_hw_context *hwctx;
drm_ctx_t ctx;
int idx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
idx = ctx.handle;
@@ -483,31 +478,31 @@ int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
else
ctx.flags = 0;
- if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
+ if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
return -EFAULT;
return 0;
}
-int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+int ffb_driver_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
}
int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_ctx_t ctx;
+ drm_ctx_t ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -515,15 +510,15 @@ int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
}
int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_ctx_t ctx;
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ drm_ctx_t ctx;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
int idx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -544,7 +539,8 @@ void ffb_set_context_ioctls(void)
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func =
+ ffb_driver_switchctx;
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index ec614fff8f04..5c121d6df9f2 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -33,13 +33,13 @@ typedef struct _ffb_position_t {
static ffb_position_t *ffb_position;
-static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
+static void get_ffb_type(ffb_dev_priv_t * ffb_priv, int instance)
{
volatile unsigned char *strap_bits;
unsigned char val;
strap_bits = (volatile unsigned char *)
- (ffb_priv->card_phys_base + 0x00200000UL);
+ (ffb_priv->card_phys_base + 0x00200000UL);
/* Don't ask, you have to read the value twice for whatever
* reason to get correct contents.
@@ -61,7 +61,8 @@ static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
break;
case (0x1 << 5) | (0x0 << 3):
ffb_priv->ffb_type = ffb2_prototype;
- printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance);
+ printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n",
+ instance);
break;
case (0x1 << 5) | (0x1 << 3):
ffb_priv->ffb_type = ffb2_vertical;
@@ -81,12 +82,13 @@ static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
break;
default:
ffb_priv->ffb_type = ffb2_vertical;
- printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val);
+ printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n",
+ instance, val);
break;
};
}
-static void ffb_apply_upa_parent_ranges(int parent,
+static void ffb_apply_upa_parent_ranges(int parent,
struct linux_prom64_registers *regs)
{
struct linux_prom64_ranges ranges[PROMREG_MAX];
@@ -97,7 +99,8 @@ static void ffb_apply_upa_parent_ranges(int parent,
if (strcmp(name, "upa") != 0)
return;
- len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
+ len =
+ prom_getproperty(parent, "ranges", (void *)ranges, sizeof(ranges));
if (len <= 0)
return;
@@ -117,11 +120,11 @@ static void ffb_apply_upa_parent_ranges(int parent,
return;
}
-static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
+static int ffb_init_one(drm_device_t * dev, int prom_node, int parent_node,
int instance)
{
- struct linux_prom64_registers regs[2*PROMREG_MAX];
- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+ struct linux_prom64_registers regs[2 * PROMREG_MAX];
+ ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
int i;
ffb_priv->prom_node = prom_node;
@@ -132,34 +135,31 @@ static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
ffb_apply_upa_parent_ranges(parent_node, &regs[0]);
ffb_priv->card_phys_base = regs[0].phys_addr;
ffb_priv->regs = (ffb_fbcPtr)
- (regs[0].phys_addr + 0x00600000UL);
+ (regs[0].phys_addr + 0x00600000UL);
get_ffb_type(ffb_priv, instance);
for (i = 0; i < FFB_MAX_CTXS; i++)
ffb_priv->hw_state[i] = NULL;
-
+
return 0;
}
static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
- drm_map_list_t *r_list;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+ drm_map_list_t *r_list;
struct list_head *list;
- drm_map_t *map;
+ drm_map_t *map;
if (!priv || (dev = priv->dev) == NULL)
return NULL;
list_for_each(list, &dev->maplist->head) {
- unsigned long uoff;
-
- r_list = (drm_map_list_t *)list;
+ r_list = (drm_map_list_t *) list;
map = r_list->map;
if (!map)
continue;
- uoff = (map->offset & 0xffffffff);
- if (uoff == off)
+ if (r_list->user_token == off)
return map;
}
@@ -169,8 +169,7 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
unsigned long ffb_get_unmapped_area(struct file *filp,
unsigned long hint,
unsigned long len,
- unsigned long pgoff,
- unsigned long flags)
+ unsigned long pgoff, unsigned long flags)
{
drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
unsigned long addr = -ENOMEM;
@@ -178,8 +177,7 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
if (!map)
return get_unmapped_area(NULL, hint, len, pgoff, flags);
- if (map->type == _DRM_FRAME_BUFFER ||
- map->type == _DRM_REGISTERS) {
+ if (map->type == _DRM_FRAME_BUFFER || map->type == _DRM_REGISTERS) {
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
#else
@@ -190,7 +188,7 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
if (!(addr & ~PAGE_MASK)) {
- unsigned long kvirt = (unsigned long) map->handle;
+ unsigned long kvirt = (unsigned long)map->handle;
if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
unsigned long koff, aoff;
@@ -210,9 +208,9 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
return addr;
}
-static int ffb_presetup(drm_device_t *dev)
+static int ffb_presetup(drm_device_t * dev)
{
- ffb_dev_priv_t *ffb_priv;
+ ffb_dev_priv_t *ffb_priv;
int ret = 0;
int i = 0;
@@ -227,14 +225,11 @@ static int ffb_presetup(drm_device_t *dev)
memset(ffb_priv, 0, sizeof(*ffb_priv));
dev->dev_private = ffb_priv;
- ret = ffb_init_one(dev,
- ffb_position[i].node,
- ffb_position[i].root,
- i);
+ ret = ffb_init_one(dev, ffb_position[i].node, ffb_position[i].root, i);
return ret;
}
-static void ffb_driver_release(drm_device_t *dev, struct file *filp)
+static void ffb_driver_release(drm_device_t * dev, struct file *filp)
{
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
@@ -242,84 +237,82 @@ static void ffb_driver_release(drm_device_t *dev, struct file *filp)
idx = context - 1;
if (fpriv &&
- context != DRM_KERNEL_CONTEXT &&
- fpriv->hw_state[idx] != NULL) {
+ context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) {
kfree(fpriv->hw_state[idx]);
fpriv->hw_state[idx] = NULL;
- }
+ }
}
-static void ffb_driver_pretakedown(drm_device_t *dev)
+static void ffb_driver_pretakedown(drm_device_t * dev)
{
- if (dev->dev_private) kfree(dev->dev_private);
+ if (dev->dev_private)
+ kfree(dev->dev_private);
}
-static int ffb_driver_postcleanup(drm_device_t *dev)
+static int ffb_driver_postcleanup(drm_device_t * dev)
{
- if (ffb_position != NULL) kfree(ffb_position);
+ if (ffb_position != NULL)
+ kfree(ffb_position);
return 0;
}
-static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
+static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev,
+ drm_lock_t * lock)
{
dev->lock.filp = 0;
{
__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
unsigned int old, new, prev, ctx;
-
+
ctx = lock->context;
do {
- old = *plock;
- new = ctx;
+ old = *plock;
+ new = ctx;
prev = cmpxchg(plock, old, new);
} while (prev != old);
}
wake_up_interruptible(&dev->lock.lock_queue);
}
-static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
+static unsigned long ffb_driver_get_map_ofs(drm_map_t * map)
{
return (map->offset & 0xffffffff);
}
-static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
+static unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev)
{
- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
-
- if (ffb_priv)
- return ffb_priv->card_phys_base;
-
- return 0;
+ ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
+
+ if (ffb_priv)
+ return ffb_priv->card_phys_base;
+
+ return 0;
}
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->minor
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE, dev->minor);
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
static drm_ioctl_desc_t ioctls[] = {
-
+
};
static struct drm_driver driver = {
@@ -338,14 +331,15 @@ static struct drm_driver driver = {
.ioctls = ioctls,
.num_ioctls = DRM_ARRAY_SIZE(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,
+ }
+ ,
};
static int __init ffb_init(void)
@@ -360,6 +354,6 @@ static void __exit ffb_exit(void)
module_init(ffb_init);
module_exit(ffb_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
index 8bf7f1e143f1..582afa6dd2b4 100644
--- a/drivers/char/drm/ffb_drv.h
+++ b/drivers/char/drm/ffb_drv.h
@@ -5,7 +5,7 @@
*/
/* Auxilliary clips. */
-typedef struct {
+typedef struct {
volatile unsigned int min;
volatile unsigned int max;
} ffb_auxclip, *ffb_auxclipPtr;
@@ -15,172 +15,265 @@ typedef struct _ffb_fbc {
/* Next vertex registers, on the right we list which drawops
* use said register and the logical name the register has in
* that context.
- */ /* DESCRIPTION DRAWOP(NAME) */
-/*0x00*/unsigned int pad1[3]; /* Reserved */
-/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */
-/*0x10*/volatile unsigned int red; /* RED */
-/*0x14*/volatile unsigned int green; /* GREEN */
-/*0x18*/volatile unsigned int blue; /* BLUE */
-/*0x1c*/volatile unsigned int z; /* DEPTH */
-/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */
- /* aadot(DYF) */
- /* ddline(DYF) */
- /* aaline(DYF) */
-/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */
- /* aadot(DXF) */
- /* ddline(DXF) */
- /* aaline(DXF) */
-/*0x28*/unsigned int pad2[2]; /* Reserved */
-/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */
- /* aaline(RYF) */
- /* triangle(RYF) */
-/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */
- /* aaline(RXF) */
- /* triangle(RXF) */
-/*0x38*/unsigned int pad3[2]; /* Reserved */
-/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */
-/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */
-/*0x48*/unsigned int pad4[2]; /* Reserved */
-/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */
-/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */
-/*0x58*/unsigned int pad5[2]; /* Reserved */
-/*0x60*/volatile unsigned int by; /* Y brline(RYI) */
- /* fastfill(OP) */
- /* polygon(YI) */
- /* rectangle(YI) */
- /* bcopy(SRCY) */
- /* vscroll(SRCY) */
-/*0x64*/volatile unsigned int bx; /* X brline(RXI) */
- /* polygon(XI) */
- /* rectangle(XI) */
- /* bcopy(SRCX) */
- /* vscroll(SRCX) */
- /* fastfill(GO) */
-/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */
- /* bcopy(DSRY) */
- /* vscroll(DSRY) */
-/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */
- /* bcopy(DSTX) */
- /* vscroll(DSTX) */
-/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */
- /* dot(DYI) */
- /* polygon(ETYI) */
- /* Height fastfill(H) */
- /* bcopy(H) */
- /* vscroll(H) */
- /* Y count fastfill(NY) */
-/*0x74*/volatile unsigned int bw; /* X dot(DXI) */
- /* brline(DXI) */
- /* polygon(ETXI) */
- /* fastfill(W) */
- /* bcopy(W) */
- /* vscroll(W) */
- /* fastfill(NX) */
-/*0x78*/unsigned int pad6[2]; /* Reserved */
-/*0x80*/unsigned int pad7[32]; /* Reserved */
-
+ *//* DESCRIPTION DRAWOP(NAME) */
+ /*0x00*/ unsigned int pad1[3];
+ /* Reserved */
+ /*0x0c*/ volatile unsigned int alpha;
+ /* ALPHA Transparency */
+ /*0x10*/ volatile unsigned int red;
+ /* RED */
+ /*0x14*/ volatile unsigned int green;
+ /* GREEN */
+ /*0x18*/ volatile unsigned int blue;
+ /* BLUE */
+ /*0x1c*/ volatile unsigned int z;
+ /* DEPTH */
+ /*0x20*/ volatile unsigned int y;
+ /* Y triangle(DOYF) */
+ /* aadot(DYF) */
+ /* ddline(DYF) */
+ /* aaline(DYF) */
+ /*0x24*/ volatile unsigned int x;
+ /* X triangle(DOXF) */
+ /* aadot(DXF) */
+ /* ddline(DXF) */
+ /* aaline(DXF) */
+ /*0x28*/ unsigned int pad2[2];
+ /* Reserved */
+ /*0x30*/ volatile unsigned int ryf;
+ /* Y (alias to DOYF) ddline(RYF) */
+ /* aaline(RYF) */
+ /* triangle(RYF) */
+ /*0x34*/ volatile unsigned int rxf;
+ /* X ddline(RXF) */
+ /* aaline(RXF) */
+ /* triangle(RXF) */
+ /*0x38*/ unsigned int pad3[2];
+ /* Reserved */
+ /*0x40*/ volatile unsigned int dmyf;
+ /* Y (alias to DOYF) triangle(DMYF) */
+ /*0x44*/ volatile unsigned int dmxf;
+ /* X triangle(DMXF) */
+ /*0x48*/ unsigned int pad4[2];
+ /* Reserved */
+ /*0x50*/ volatile unsigned int ebyi;
+ /* Y (alias to RYI) polygon(EBYI) */
+ /*0x54*/ volatile unsigned int ebxi;
+ /* X polygon(EBXI) */
+ /*0x58*/ unsigned int pad5[2];
+ /* Reserved */
+ /*0x60*/ volatile unsigned int by;
+ /* Y brline(RYI) */
+ /* fastfill(OP) */
+ /* polygon(YI) */
+ /* rectangle(YI) */
+ /* bcopy(SRCY) */
+ /* vscroll(SRCY) */
+ /*0x64*/ volatile unsigned int bx;
+ /* X brline(RXI) */
+ /* polygon(XI) */
+ /* rectangle(XI) */
+ /* bcopy(SRCX) */
+ /* vscroll(SRCX) */
+ /* fastfill(GO) */
+ /*0x68*/ volatile unsigned int dy;
+ /* destination Y fastfill(DSTY) */
+ /* bcopy(DSRY) */
+ /* vscroll(DSRY) */
+ /*0x6c*/ volatile unsigned int dx;
+ /* destination X fastfill(DSTX) */
+ /* bcopy(DSTX) */
+ /* vscroll(DSTX) */
+ /*0x70*/ volatile unsigned int bh;
+ /* Y (alias to RYI) brline(DYI) */
+ /* dot(DYI) */
+ /* polygon(ETYI) */
+ /* Height fastfill(H) */
+ /* bcopy(H) */
+ /* vscroll(H) */
+ /* Y count fastfill(NY) */
+ /*0x74*/ volatile unsigned int bw;
+ /* X dot(DXI) */
+ /* brline(DXI) */
+ /* polygon(ETXI) */
+ /* fastfill(W) */
+ /* bcopy(W) */
+ /* vscroll(W) */
+ /* fastfill(NX) */
+ /*0x78*/ unsigned int pad6[2];
+ /* Reserved */
+ /*0x80*/ unsigned int pad7[32];
+ /* Reserved */
+
/* Setup Unit's vertex state register */
-/*100*/ volatile unsigned int suvtx;
-/*104*/ unsigned int pad8[63]; /* Reserved */
-
+/*100*/ volatile unsigned int suvtx;
+ /*104*/ unsigned int pad8[63];
+ /* Reserved */
+
/* Frame Buffer Control Registers */
-/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */
-/*204*/ volatile unsigned int wid; /* Current WID */
-/*208*/ volatile unsigned int fg; /* FG data */
-/*20c*/ volatile unsigned int bg; /* BG data */
-/*210*/ volatile unsigned int consty; /* Constant Y */
-/*214*/ volatile unsigned int constz; /* Constant Z */
-/*218*/ volatile unsigned int xclip; /* X Clip */
-/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */
-/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */
-/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */
-/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */
-/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */
-/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */
-/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */
-/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */
-/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */
-/*240*/ unsigned int pad9; /* Reserved */
-/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */
-/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */
-/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */
-/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */
-/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */
-/*258*/ volatile unsigned int rop; /* Raster OPeration */
-/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */
-/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */
-/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */
-/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */
-/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */
-/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */
-/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */
-/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */
-/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */
-/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */
-/*284*/ volatile unsigned int pick; /* Picking Control */
-/*288*/ volatile unsigned int fillmode; /* FillMode */
-/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */
-/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */
-/*294*/ volatile unsigned int xpmask; /* X PlaneMask */
-/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */
-/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */
-/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */
-
+ /*200*/ volatile unsigned int ppc;
+ /* Pixel Processor Control */
+ /*204*/ volatile unsigned int wid;
+ /* Current WID */
+ /*208*/ volatile unsigned int fg;
+ /* FG data */
+ /*20c*/ volatile unsigned int bg;
+ /* BG data */
+ /*210*/ volatile unsigned int consty;
+ /* Constant Y */
+ /*214*/ volatile unsigned int constz;
+ /* Constant Z */
+ /*218*/ volatile unsigned int xclip;
+ /* X Clip */
+ /*21c*/ volatile unsigned int dcss;
+ /* Depth Cue Scale Slope */
+ /*220*/ volatile unsigned int vclipmin;
+ /* Viewclip XY Min Bounds */
+ /*224*/ volatile unsigned int vclipmax;
+ /* Viewclip XY Max Bounds */
+ /*228*/ volatile unsigned int vclipzmin;
+ /* Viewclip Z Min Bounds */
+ /*22c*/ volatile unsigned int vclipzmax;
+ /* Viewclip Z Max Bounds */
+ /*230*/ volatile unsigned int dcsf;
+ /* Depth Cue Scale Front Bound */
+ /*234*/ volatile unsigned int dcsb;
+ /* Depth Cue Scale Back Bound */
+ /*238*/ volatile unsigned int dczf;
+ /* Depth Cue Z Front */
+ /*23c*/ volatile unsigned int dczb;
+ /* Depth Cue Z Back */
+ /*240*/ unsigned int pad9;
+ /* Reserved */
+ /*244*/ volatile unsigned int blendc;
+ /* Alpha Blend Control */
+ /*248*/ volatile unsigned int blendc1;
+ /* Alpha Blend Color 1 */
+ /*24c*/ volatile unsigned int blendc2;
+ /* Alpha Blend Color 2 */
+ /*250*/ volatile unsigned int fbramitc;
+ /* FB RAM Interleave Test Control */
+ /*254*/ volatile unsigned int fbc;
+ /* Frame Buffer Control */
+ /*258*/ volatile unsigned int rop;
+ /* Raster OPeration */
+ /*25c*/ volatile unsigned int cmp;
+ /* Frame Buffer Compare */
+ /*260*/ volatile unsigned int matchab;
+ /* Buffer AB Match Mask */
+ /*264*/ volatile unsigned int matchc;
+ /* Buffer C(YZ) Match Mask */
+ /*268*/ volatile unsigned int magnab;
+ /* Buffer AB Magnitude Mask */
+ /*26c*/ volatile unsigned int magnc;
+ /* Buffer C(YZ) Magnitude Mask */
+ /*270*/ volatile unsigned int fbcfg0;
+ /* Frame Buffer Config 0 */
+ /*274*/ volatile unsigned int fbcfg1;
+ /* Frame Buffer Config 1 */
+ /*278*/ volatile unsigned int fbcfg2;
+ /* Frame Buffer Config 2 */
+ /*27c*/ volatile unsigned int fbcfg3;
+ /* Frame Buffer Config 3 */
+ /*280*/ volatile unsigned int ppcfg;
+ /* Pixel Processor Config */
+ /*284*/ volatile unsigned int pick;
+ /* Picking Control */
+ /*288*/ volatile unsigned int fillmode;
+ /* FillMode */
+ /*28c*/ volatile unsigned int fbramwac;
+ /* FB RAM Write Address Control */
+ /*290*/ volatile unsigned int pmask;
+ /* RGB PlaneMask */
+ /*294*/ volatile unsigned int xpmask;
+ /* X PlaneMask */
+ /*298*/ volatile unsigned int ypmask;
+ /* Y PlaneMask */
+ /*29c*/ volatile unsigned int zpmask;
+ /* Z PlaneMask */
+ /*2a0*/ ffb_auxclip auxclip[4];
+ /* Auxilliary Viewport Clip */
+
/* New 3dRAM III support regs */
-/*2c0*/ volatile unsigned int rawblend2;
-/*2c4*/ volatile unsigned int rawpreblend;
-/*2c8*/ volatile unsigned int rawstencil;
-/*2cc*/ volatile unsigned int rawstencilctl;
-/*2d0*/ volatile unsigned int threedram1;
-/*2d4*/ volatile unsigned int threedram2;
-/*2d8*/ volatile unsigned int passin;
-/*2dc*/ volatile unsigned int rawclrdepth;
-/*2e0*/ volatile unsigned int rawpmask;
-/*2e4*/ volatile unsigned int rawcsrc;
-/*2e8*/ volatile unsigned int rawmatch;
-/*2ec*/ volatile unsigned int rawmagn;
-/*2f0*/ volatile unsigned int rawropblend;
-/*2f4*/ volatile unsigned int rawcmp;
-/*2f8*/ volatile unsigned int rawwac;
-/*2fc*/ volatile unsigned int fbramid;
-
-/*300*/ volatile unsigned int drawop; /* Draw OPeration */
-/*304*/ unsigned int pad10[2]; /* Reserved */
-/*30c*/ volatile unsigned int lpat; /* Line Pattern control */
-/*310*/ unsigned int pad11; /* Reserved */
-/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */
-/*318*/ volatile unsigned int fontw; /* Font Width */
-/*31c*/ volatile unsigned int fontinc; /* Font Increment */
-/*320*/ volatile unsigned int font; /* Font bits */
-/*324*/ unsigned int pad12[3]; /* Reserved */
-/*330*/ volatile unsigned int blend2;
-/*334*/ volatile unsigned int preblend;
-/*338*/ volatile unsigned int stencil;
-/*33c*/ volatile unsigned int stencilctl;
+/*2c0*/ volatile unsigned int rawblend2;
+/*2c4*/ volatile unsigned int rawpreblend;
+/*2c8*/ volatile unsigned int rawstencil;
+/*2cc*/ volatile unsigned int rawstencilctl;
+/*2d0*/ volatile unsigned int threedram1;
+/*2d4*/ volatile unsigned int threedram2;
+/*2d8*/ volatile unsigned int passin;
+/*2dc*/ volatile unsigned int rawclrdepth;
+/*2e0*/ volatile unsigned int rawpmask;
+/*2e4*/ volatile unsigned int rawcsrc;
+/*2e8*/ volatile unsigned int rawmatch;
+/*2ec*/ volatile unsigned int rawmagn;
+/*2f0*/ volatile unsigned int rawropblend;
+/*2f4*/ volatile unsigned int rawcmp;
+/*2f8*/ volatile unsigned int rawwac;
+/*2fc*/ volatile unsigned int fbramid;
+
+ /*300*/ volatile unsigned int drawop;
+ /* Draw OPeration */
+ /*304*/ unsigned int pad10[2];
+ /* Reserved */
+ /*30c*/ volatile unsigned int lpat;
+ /* Line Pattern control */
+ /*310*/ unsigned int pad11;
+ /* Reserved */
+ /*314*/ volatile unsigned int fontxy;
+ /* XY Font coordinate */
+ /*318*/ volatile unsigned int fontw;
+ /* Font Width */
+ /*31c*/ volatile unsigned int fontinc;
+ /* Font Increment */
+ /*320*/ volatile unsigned int font;
+ /* Font bits */
+ /*324*/ unsigned int pad12[3];
+ /* Reserved */
+/*330*/ volatile unsigned int blend2;
+/*334*/ volatile unsigned int preblend;
+/*338*/ volatile unsigned int stencil;
+/*33c*/ volatile unsigned int stencilctl;
-/*340*/ unsigned int pad13[4]; /* Reserved */
-/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */
-/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */
-/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */
-/*35c*/ volatile unsigned int widpmask;
-/*360*/ volatile unsigned int dcs2;
-/*364*/ volatile unsigned int dcs3;
-/*368*/ volatile unsigned int dcs4;
-/*36c*/ unsigned int pad14; /* Reserved */
-/*370*/ volatile unsigned int dcd2;
-/*374*/ volatile unsigned int dcd3;
-/*378*/ volatile unsigned int dcd4;
-/*37c*/ unsigned int pad15; /* Reserved */
-/*380*/ volatile unsigned int pattern[32]; /* area Pattern */
-/*400*/ unsigned int pad16[8]; /* Reserved */
-/*420*/ volatile unsigned int reset; /* chip RESET */
-/*424*/ unsigned int pad17[247]; /* Reserved */
-/*800*/ volatile unsigned int devid; /* Device ID */
-/*804*/ unsigned int pad18[63]; /* Reserved */
-/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */
-/*904*/ unsigned int pad19[31]; /* Reserved */
-/*980*/ volatile unsigned int mer; /* Mode Enable Register */
-/*984*/ unsigned int pad20[1439]; /* Reserved */
+ /*340*/ unsigned int pad13[4];
+ /* Reserved */
+ /*350*/ volatile unsigned int dcss1;
+ /* Depth Cue Scale Slope 1 */
+ /*354*/ volatile unsigned int dcss2;
+ /* Depth Cue Scale Slope 2 */
+ /*358*/ volatile unsigned int dcss3;
+ /* Depth Cue Scale Slope 3 */
+/*35c*/ volatile unsigned int widpmask;
+/*360*/ volatile unsigned int dcs2;
+/*364*/ volatile unsigned int dcs3;
+/*368*/ volatile unsigned int dcs4;
+ /*36c*/ unsigned int pad14;
+ /* Reserved */
+/*370*/ volatile unsigned int dcd2;
+/*374*/ volatile unsigned int dcd3;
+/*378*/ volatile unsigned int dcd4;
+ /*37c*/ unsigned int pad15;
+ /* Reserved */
+ /*380*/ volatile unsigned int pattern[32];
+ /* area Pattern */
+ /*400*/ unsigned int pad16[8];
+ /* Reserved */
+ /*420*/ volatile unsigned int reset;
+ /* chip RESET */
+ /*424*/ unsigned int pad17[247];
+ /* Reserved */
+ /*800*/ volatile unsigned int devid;
+ /* Device ID */
+ /*804*/ unsigned int pad18[63];
+ /* Reserved */
+ /*900*/ volatile unsigned int ucsr;
+ /* User Control & Status Register */
+ /*904*/ unsigned int pad19[31];
+ /* Reserved */
+ /*980*/ volatile unsigned int mer;
+ /* Mode Enable Register */
+ /*984*/ unsigned int pad20[1439];
+ /* Reserved */
} ffb_fbc, *ffb_fbcPtr;
struct ffb_hw_context {
@@ -263,16 +356,16 @@ enum ffb_chip_type {
typedef struct ffb_dev_priv {
/* Misc software state. */
- int prom_node;
- enum ffb_chip_type ffb_type;
- u64 card_phys_base;
- struct miscdevice miscdev;
+ int prom_node;
+ enum ffb_chip_type ffb_type;
+ u64 card_phys_base;
+ struct miscdevice miscdev;
/* Controller registers. */
- ffb_fbcPtr regs;
+ ffb_fbcPtr regs;
/* Context table. */
- struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
+ struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
} ffb_dev_priv_t;
extern unsigned long ffb_get_unmapped_area(struct file *filp,
@@ -283,4 +376,4 @@ extern unsigned long ffb_get_unmapped_area(struct file *filp,
extern void ffb_set_context_ioctls(void);
extern drm_ioctl_desc_t DRM(ioctls)[];
-extern int ffb_driver_context_switch(drm_device_t *dev, int old, int new);
+extern int ffb_driver_context_switch(drm_device_t * dev, int old, int new);
diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
deleted file mode 100644
index d11b507f87ee..000000000000
--- a/drivers/char/drm/gamma_context.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * VA LINUX SYSTEMS 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- * ChangeLog:
- * 2001-11-16 Torsten Duwe <duwe@caldera.de>
- * added context constructor/destructor hooks,
- * needed by SiS driver's memory management.
- */
-
-/* ================================================================
- * Old-style context support -- only used by gamma.
- */
-
-
-/* The drm_read and drm_write_string code (especially that which manages
- the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
- DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
-
-ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int left;
- int avail;
- int send;
- int cur;
-
- DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
-
- while (dev->buf_rp == dev->buf_wp) {
- DRM_DEBUG(" sleeping\n");
- if (filp->f_flags & O_NONBLOCK) {
- return -EAGAIN;
- }
- interruptible_sleep_on(&dev->buf_readers);
- if (signal_pending(current)) {
- DRM_DEBUG(" interrupted\n");
- return -ERESTARTSYS;
- }
- DRM_DEBUG(" awake\n");
- }
-
- left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
- avail = DRM_BSZ - left;
- send = DRM_MIN(avail, count);
-
- while (send) {
- if (dev->buf_wp > dev->buf_rp) {
- cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
- } else {
- cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
- }
- if (copy_to_user(buf, dev->buf_rp, cur))
- return -EFAULT;
- dev->buf_rp += cur;
- if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
- send -= cur;
- }
-
- wake_up_interruptible(&dev->buf_writers);
- return DRM_MIN(avail, count);
-}
-
-
-/* In an incredibly convoluted setup, the kernel module actually calls
- * back into the X server to perform context switches on behalf of the
- * 3d clients.
- */
-int DRM(write_string)(drm_device_t *dev, const char *s)
-{
- int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
- int send = strlen(s);
- int count;
-
- DRM_DEBUG("%d left, %d to send (%p, %p)\n",
- left, send, dev->buf_rp, dev->buf_wp);
-
- if (left == 1 || dev->buf_wp != dev->buf_rp) {
- DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
- left,
- dev->buf_wp,
- dev->buf_rp);
- }
-
- while (send) {
- if (dev->buf_wp >= dev->buf_rp) {
- count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
- if (count == left) --count; /* Leave a hole */
- } else {
- count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
- }
- strncpy(dev->buf_wp, s, count);
- dev->buf_wp += count;
- if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
- send -= count;
- }
-
- if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
-
- DRM_DEBUG("waking\n");
- wake_up_interruptible(&dev->buf_readers);
- return 0;
-}
-
-unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
-
- poll_wait(filp, &dev->buf_readers, wait);
- if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
- return 0;
-}
-
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
-{
- char buf[64];
- drm_queue_t *q;
-
- if (test_and_set_bit(0, &dev->context_flag)) {
- DRM_ERROR("Reentering -- FIXME\n");
- return -EBUSY;
- }
-
- DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
- if (new >= dev->queue_count) {
- clear_bit(0, &dev->context_flag);
- return -EINVAL;
- }
-
- if (new == dev->last_context) {
- clear_bit(0, &dev->context_flag);
- return 0;
- }
-
- q = dev->queuelist[new];
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- atomic_dec(&q->use_count);
- clear_bit(0, &dev->context_flag);
- return -EINVAL;
- }
-
- /* This causes the X server to wake up & do a bunch of hardware
- * interaction to actually effect the context switch.
- */
- sprintf(buf, "C %d %d\n", old, new);
- DRM(write_string)(dev, buf);
-
- atomic_dec(&q->use_count);
-
- return 0;
-}
-
-int DRM(context_switch_complete)(drm_device_t *dev, int new)
-{
- drm_device_dma_t *dma = dev->dma;
-
- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
- dev->last_switch = jiffies;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("Lock isn't held after context switch\n");
- }
-
- if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
- if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("Cannot free lock\n");
- }
- }
-
- clear_bit(0, &dev->context_flag);
- wake_up_interruptible(&dev->context_wait);
-
- return 0;
-}
-
-static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
-{
- DRM_DEBUG("\n");
-
- if (atomic_read(&q->use_count) != 1
- || atomic_read(&q->finalization)
- || atomic_read(&q->block_count)) {
- DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
- atomic_read(&q->use_count),
- atomic_read(&q->finalization),
- atomic_read(&q->block_count));
- }
-
- atomic_set(&q->finalization, 0);
- atomic_set(&q->block_count, 0);
- atomic_set(&q->block_read, 0);
- atomic_set(&q->block_write, 0);
- atomic_set(&q->total_queued, 0);
- atomic_set(&q->total_flushed, 0);
- atomic_set(&q->total_locks, 0);
-
- init_waitqueue_head(&q->write_queue);
- init_waitqueue_head(&q->read_queue);
- init_waitqueue_head(&q->flush_queue);
-
- q->flags = ctx->flags;
-
- DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
-
- return 0;
-}
-
-
-/* drm_alloc_queue:
-PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
- disappear (so all deallocation must be done after IOCTLs are off)
- 2) dev->queue_count < dev->queue_slots
- 3) dev->queuelist[i].use_count == 0 and
- dev->queuelist[i].finalization == 0 if i not in use
-POST: 1) dev->queuelist[i].use_count == 1
- 2) dev->queue_count < dev->queue_slots */
-
-static int DRM(alloc_queue)(drm_device_t *dev)
-{
- int i;
- drm_queue_t *queue;
- int oldslots;
- int newslots;
- /* Check for a free queue */
- for (i = 0; i < dev->queue_count; i++) {
- atomic_inc(&dev->queuelist[i]->use_count);
- if (atomic_read(&dev->queuelist[i]->use_count) == 1
- && !atomic_read(&dev->queuelist[i]->finalization)) {
- DRM_DEBUG("%d (free)\n", i);
- return i;
- }
- atomic_dec(&dev->queuelist[i]->use_count);
- }
- /* Allocate a new queue */
- down(&dev->struct_sem);
-
- queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES);
- memset(queue, 0, sizeof(*queue));
- atomic_set(&queue->use_count, 1);
-
- ++dev->queue_count;
- if (dev->queue_count >= dev->queue_slots) {
- oldslots = dev->queue_slots * sizeof(*dev->queuelist);
- if (!dev->queue_slots) dev->queue_slots = 1;
- dev->queue_slots *= 2;
- newslots = dev->queue_slots * sizeof(*dev->queuelist);
-
- dev->queuelist = DRM(realloc)(dev->queuelist,
- oldslots,
- newslots,
- DRM_MEM_QUEUES);
- if (!dev->queuelist) {
- up(&dev->struct_sem);
- DRM_DEBUG("out of memory\n");
- return -ENOMEM;
- }
- }
- dev->queuelist[dev->queue_count-1] = queue;
-
- up(&dev->struct_sem);
- DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
- return dev->queue_count - 1;
-}
-
-int DRM(resctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_ctx_res_t __user *argp = (void __user *)arg;
- drm_ctx_res_t res;
- drm_ctx_t ctx;
- int i;
-
- DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- if (copy_from_user(&res, argp, sizeof(res)))
- return -EFAULT;
- if (res.count >= DRM_RESERVED_CONTEXTS) {
- memset(&ctx, 0, sizeof(ctx));
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- ctx.handle = i;
- if (copy_to_user(&res.contexts[i],
- &i,
- sizeof(i)))
- return -EFAULT;
- }
- }
- res.count = DRM_RESERVED_CONTEXTS;
- if (copy_to_user(argp, &res, sizeof(res)))
- return -EFAULT;
- return 0;
-}
-
-int DRM(addctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_ctx_t __user *argp = (void __user *)arg;
-
- if (copy_from_user(&ctx, argp, sizeof(ctx)))
- return -EFAULT;
- if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
- /* Init kernel's context and get a new one. */
- DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
- ctx.handle = DRM(alloc_queue)(dev);
- }
- DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
- DRM_DEBUG("%d\n", ctx.handle);
- if (copy_to_user(argp, &ctx, sizeof(ctx)))
- return -EFAULT;
- return 0;
-}
-
-int DRM(modctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_queue_t *q;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
-
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- if (DRM_BUFCOUNT(&q->waitlist)) {
- atomic_dec(&q->use_count);
- return -EBUSY;
- }
-
- q->flags = ctx.flags;
-
- atomic_dec(&q->use_count);
- return 0;
-}
-
-int DRM(getctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
- drm_queue_t *q;
-
- if (copy_from_user(&ctx, argp, sizeof(ctx)))
- return -EFAULT;
-
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- ctx.flags = q->flags;
- atomic_dec(&q->use_count);
-
- if (copy_to_user(argp, &ctx, sizeof(ctx)))
- return -EFAULT;
-
- return 0;
-}
-
-int DRM(switchctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
- return DRM(context_switch)(dev, dev->last_context, ctx.handle);
-}
-
-int DRM(newctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
- DRM(context_switch_complete)(dev, ctx.handle);
-
- return 0;
-}
-
-int DRM(rmctx)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_t ctx;
- drm_queue_t *q;
- drm_buf_t *buf;
-
- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
- return -EFAULT;
- DRM_DEBUG("%d\n", ctx.handle);
-
- if (ctx.handle >= dev->queue_count) return -EINVAL;
- q = dev->queuelist[ctx.handle];
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
-
- atomic_inc(&q->finalization); /* Mark queue in finalization state */
- atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
- finalization) */
-
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
- /* Remove queued buffers */
- while ((buf = DRM(waitlist_get)(&q->waitlist))) {
- DRM(free_buffer)(dev, buf);
- }
- clear_bit(0, &dev->interrupt_flag);
-
- /* Wakeup blocked processes */
- wake_up_interruptible(&q->read_queue);
- wake_up_interruptible(&q->write_queue);
- wake_up_interruptible(&q->flush_queue);
-
- /* Finalization over. Queue is made
- available when both use_count and
- finalization become 0, which won't
- happen until all the waiting processes
- stop waiting. */
- atomic_dec(&q->finalization);
- return 0;
-}
-
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
deleted file mode 100644
index e486fb8d31e9..000000000000
--- a/drivers/char/drm/gamma_dma.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * PRECISION INSIGHT 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include <linux/interrupt.h> /* For task queue support */
-#include <linux/delay.h>
-
-static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
- unsigned long length)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- mb();
- while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_DMAADDRESS, address);
-
- while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
-}
-
-void gamma_dma_quiescent_single(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
- GAMMA_WRITE(GAMMA_SYNC, 0);
-
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_quiescent_dual(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
- GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
- GAMMA_WRITE(GAMMA_SYNC, 0);
-
- /* Read from first MX */
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-
- /* Read from second MX */
- do {
- while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
- cpu_relax();
- } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_ready(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- while (GAMMA_READ(GAMMA_DMACOUNT))
- cpu_relax();
-}
-
-static inline int gamma_dma_is_ready(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- return (!GAMMA_READ(GAMMA_DMACOUNT));
-}
-
-irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
-{
- drm_device_t *dev = (drm_device_t *)arg;
- drm_device_dma_t *dma = dev->dma;
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- /* FIXME: should check whether we're actually interested in the interrupt? */
- atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
- GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
- GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
- if (gamma_dma_is_ready(dev)) {
- /* Free previous buffer */
- if (test_and_set_bit(0, &dev->dma_flag))
- return IRQ_HANDLED;
- if (dma->this_buffer) {
- gamma_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = NULL;
- }
- clear_bit(0, &dev->dma_flag);
-
- /* Dispatch new buffer */
- schedule_work(&dev->work);
- }
- return IRQ_HANDLED;
-}
-
-/* Only called by gamma_dma_schedule. */
-static int gamma_do_dma(drm_device_t *dev, int locked)
-{
- unsigned long address;
- unsigned long length;
- drm_buf_t *buf;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
-
- if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
-
-
- if (!dma->next_buffer) {
- DRM_ERROR("No next_buffer\n");
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- buf = dma->next_buffer;
- /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
- /* So we pass the buffer index value into the physical page offset */
- address = buf->idx << 12;
- length = buf->used;
-
- DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
- buf->context, buf->idx, length);
-
- if (buf->list == DRM_LIST_RECLAIM) {
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return 0;
- }
-
- if (!gamma_dma_is_ready(dev)) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
-
- if (buf->while_locked) {
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("Dispatching buffer %d from pid %d"
- " \"while locked\", but no lock held\n",
- buf->idx, current->pid);
- }
- } else {
- if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
- }
-
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- /* PRE: dev->last_context != buf->context */
- if (DRM(context_switch)(dev, dev->last_context,
- buf->context)) {
- DRM(clear_next_buffer)(dev);
- DRM(free_buffer)(dev, buf);
- }
- retcode = -EBUSY;
- goto cleanup;
-
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- }
-
- gamma_clear_next_buffer(dev);
- buf->pending = 1;
- buf->waiting = 0;
- buf->list = DRM_LIST_PEND;
-
- /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
- address = buf->idx << 12;
-
- gamma_dma_dispatch(dev, address, length);
- gamma_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = buf;
-
- atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
- atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
- if (!buf->while_locked && !dev->context_flag && !locked) {
- if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
- }
-cleanup:
-
- clear_bit(0, &dev->dma_flag);
-
-
- return retcode;
-}
-
-static void gamma_dma_timer_bh(unsigned long dev)
-{
- gamma_dma_schedule((drm_device_t *)dev, 0);
-}
-
-void gamma_irq_immediate_bh(void *dev)
-{
- gamma_dma_schedule(dev, 0);
-}
-
-int gamma_dma_schedule(drm_device_t *dev, int locked)
-{
- int next;
- drm_queue_t *q;
- drm_buf_t *buf;
- int retcode = 0;
- int processed = 0;
- int missed;
- int expire = 20;
- drm_device_dma_t *dma = dev->dma;
-
- if (test_and_set_bit(0, &dev->interrupt_flag)) {
- /* Not reentrant */
- atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
- return -EBUSY;
- }
- missed = atomic_read(&dev->counts[10]);
-
-
-again:
- if (dev->context_flag) {
- clear_bit(0, &dev->interrupt_flag);
- return -EBUSY;
- }
- if (dma->next_buffer) {
- /* Unsent buffer that was previously
- selected, but that couldn't be sent
- because the lock could not be obtained
- or the DMA engine wasn't ready. Try
- again. */
- if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
- } else {
- do {
- next = gamma_select_queue(dev, gamma_dma_timer_bh);
- if (next >= 0) {
- q = dev->queuelist[next];
- buf = gamma_waitlist_get(&q->waitlist);
- dma->next_buffer = buf;
- dma->next_queue = q;
- if (buf && buf->list == DRM_LIST_RECLAIM) {
- gamma_clear_next_buffer(dev);
- gamma_free_buffer(dev, buf);
- }
- }
- } while (next >= 0 && !dma->next_buffer);
- if (dma->next_buffer) {
- if (!(retcode = gamma_do_dma(dev, locked))) {
- ++processed;
- }
- }
- }
-
- if (--expire) {
- if (missed != atomic_read(&dev->counts[10])) {
- if (gamma_dma_is_ready(dev)) goto again;
- }
- if (processed && gamma_dma_is_ready(dev)) {
- processed = 0;
- goto again;
- }
- }
-
- clear_bit(0, &dev->interrupt_flag);
-
- return retcode;
-}
-
-static int gamma_dma_priority(struct file *filp,
- drm_device_t *dev, drm_dma_t *d)
-{
- unsigned long address;
- unsigned long length;
- int must_free = 0;
- int retcode = 0;
- int i;
- int idx;
- drm_buf_t *buf;
- drm_buf_t *last_buf = NULL;
- drm_device_dma_t *dma = dev->dma;
- int *send_indices = NULL;
- int *send_sizes = NULL;
-
- DECLARE_WAITQUEUE(entry, current);
-
- /* Turn off interrupt handling */
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- schedule();
- if (signal_pending(current)) return -EINTR;
- }
- if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
- while (!gamma_lock_take(&dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
- ++must_free;
- }
-
- send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
- DRM_MEM_DRIVER);
- if (send_indices == NULL)
- return -ENOMEM;
- if (copy_from_user(send_indices, d->send_indices,
- d->send_count * sizeof(*send_indices))) {
- retcode = -EFAULT;
- goto cleanup;
- }
-
- send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
- DRM_MEM_DRIVER);
- if (send_sizes == NULL)
- return -ENOMEM;
- if (copy_from_user(send_sizes, d->send_sizes,
- d->send_count * sizeof(*send_sizes))) {
- retcode = -EFAULT;
- goto cleanup;
- }
-
- for (i = 0; i < d->send_count; i++) {
- idx = send_indices[i];
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- send_indices[i], dma->buf_count - 1);
- continue;
- }
- buf = dma->buflist[ idx ];
- if (buf->filp != filp) {
- DRM_ERROR("Process %d using buffer not owned\n",
- current->pid);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using buffer on list %d\n",
- current->pid, buf->list);
- retcode = -EINVAL;
- goto cleanup;
- }
- /* This isn't a race condition on
- buf->list, since our concern is the
- buffer reclaim during the time the
- process closes the /dev/drm? handle, so
- it can't also be doing DMA. */
- buf->list = DRM_LIST_PRIO;
- buf->used = send_sizes[i];
- buf->context = d->context;
- buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
- address = (unsigned long)buf->address;
- length = buf->used;
- if (!length) {
- DRM_ERROR("0 length buffer\n");
- }
- if (buf->pending) {
- DRM_ERROR("Sending pending buffer:"
- " buffer %d, offset %d\n",
- send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
- }
- if (buf->waiting) {
- DRM_ERROR("Sending waiting buffer:"
- " buffer %d, offset %d\n",
- send_indices[i], i);
- retcode = -EINVAL;
- goto cleanup;
- }
- buf->pending = 1;
-
- if (dev->last_context != buf->context
- && !(dev->queuelist[buf->context]->flags
- & _DRM_CONTEXT_PRESERVED)) {
- add_wait_queue(&dev->context_wait, &entry);
- current->state = TASK_INTERRUPTIBLE;
- /* PRE: dev->last_context != buf->context */
- DRM(context_switch)(dev, dev->last_context,
- buf->context);
- /* POST: we will wait for the context
- switch and will dispatch on a later call
- when dev->last_context == buf->context.
- NOTE WE HOLD THE LOCK THROUGHOUT THIS
- TIME! */
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&dev->context_wait, &entry);
- if (signal_pending(current)) {
- retcode = -EINTR;
- goto cleanup;
- }
- if (dev->last_context != buf->context) {
- DRM_ERROR("Context mismatch: %d %d\n",
- dev->last_context,
- buf->context);
- }
- }
-
- gamma_dma_dispatch(dev, address, length);
- atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
- atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
- if (last_buf) {
- gamma_free_buffer(dev, last_buf);
- }
- last_buf = buf;
- }
-
-
-cleanup:
- if (last_buf) {
- gamma_dma_ready(dev);
- gamma_free_buffer(dev, last_buf);
- }
- if (send_indices)
- DRM(free)(send_indices, d->send_count * sizeof(*send_indices),
- DRM_MEM_DRIVER);
- if (send_sizes)
- DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes),
- DRM_MEM_DRIVER);
-
- if (must_free && !dev->context_flag) {
- if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
- }
- clear_bit(0, &dev->interrupt_flag);
- return retcode;
-}
-
-static int gamma_dma_send_buffers(struct file *filp,
- drm_device_t *dev, drm_dma_t *d)
-{
- DECLARE_WAITQUEUE(entry, current);
- drm_buf_t *last_buf = NULL;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
- int send_index;
-
- if (get_user(send_index, &d->send_indices[d->send_count-1]))
- return -EFAULT;
-
- if (d->flags & _DRM_DMA_BLOCK) {
- last_buf = dma->buflist[send_index];
- add_wait_queue(&last_buf->dma_wait, &entry);
- }
-
- if ((retcode = gamma_dma_enqueue(filp, d))) {
- if (d->flags & _DRM_DMA_BLOCK)
- remove_wait_queue(&last_buf->dma_wait, &entry);
- return retcode;
- }
-
- gamma_dma_schedule(dev, 0);
-
- if (d->flags & _DRM_DMA_BLOCK) {
- DRM_DEBUG("%d waiting\n", current->pid);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!last_buf->waiting && !last_buf->pending)
- break; /* finished */
- schedule();
- if (signal_pending(current)) {
- retcode = -EINTR; /* Can't restart */
- break;
- }
- }
- current->state = TASK_RUNNING;
- DRM_DEBUG("%d running\n", current->pid);
- remove_wait_queue(&last_buf->dma_wait, &entry);
- if (!retcode
- || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
- if (!waitqueue_active(&last_buf->dma_wait)) {
- gamma_free_buffer(dev, last_buf);
- }
- }
- if (retcode) {
- DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",
- d->context,
- last_buf->waiting,
- last_buf->pending,
- (long)DRM_WAITCOUNT(dev, d->context),
- last_buf->idx,
- last_buf->list,
- current->pid);
- }
- }
- return retcode;
-}
-
-int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_device_dma_t *dma = dev->dma;
- int retcode = 0;
- drm_dma_t __user *argp = (void __user *)arg;
- drm_dma_t d;
-
- if (copy_from_user(&d, argp, sizeof(d)))
- return -EFAULT;
-
- if (d.send_count < 0 || d.send_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
- current->pid, d.send_count, dma->buf_count);
- return -EINVAL;
- }
-
- if (d.request_count < 0 || d.request_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
- current->pid, d.request_count, dma->buf_count);
- return -EINVAL;
- }
-
- if (d.send_count) {
- if (d.flags & _DRM_DMA_PRIORITY)
- retcode = gamma_dma_priority(filp, dev, &d);
- else
- retcode = gamma_dma_send_buffers(filp, dev, &d);
- }
-
- d.granted_count = 0;
-
- if (!retcode && d.request_count) {
- retcode = gamma_dma_get_buffers(filp, &d);
- }
-
- DRM_DEBUG("%d returning, granted = %d\n",
- current->pid, d.granted_count);
- if (copy_to_user(argp, &d, sizeof(d)))
- return -EFAULT;
-
- return retcode;
-}
-
-/* =============================================================
- * DMA initialization, cleanup
- */
-
-static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
-{
- drm_gamma_private_t *dev_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
- int i;
- struct list_head *list;
- unsigned long *pgt;
-
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
- DRM_MEM_DRIVER );
- if ( !dev_priv )
- return -ENOMEM;
-
- dev->dev_private = (void *)dev_priv;
-
- memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
-
- dev_priv->num_rast = init->num_rast;
-
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
- if( r_list->map &&
- r_list->map->type == _DRM_SHM &&
- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
- dev_priv->sarea = r_list->map;
- break;
- }
- }
-
- dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
- dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
- dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
- dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
-
- dev_priv->sarea_priv = (drm_gamma_sarea_t *)
- ((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
-
- if (init->pcimode) {
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- pgt = buf->address;
-
- for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
- buf = dma->buflist[i];
- *pgt = virt_to_phys((void*)buf->address) | 0x07;
- pgt++;
- }
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- } else {
- dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- drm_core_ioremap( dev->agp_buffer_map, dev);
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
- pgt = buf->address;
-
- for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
- buf = dma->buflist[i];
- *pgt = (unsigned long)buf->address + 0x07;
- pgt++;
- }
-
- buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
- GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
- }
- while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
- GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
- GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
-
- return 0;
-}
-
-int gamma_do_cleanup_dma( drm_device_t *dev )
-{
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- /* Make sure interrupts are disabled here because the uninstall ioctl
- * may not have been called from userspace and after dev_private
- * is freed, it's too late.
- */
- if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- if ( dev->irq_enabled )
- DRM(irq_uninstall)(dev);
-
- if ( dev->dev_private ) {
-
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
-
- DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
- }
-
- return 0;
-}
-
-int gamma_dma_init( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_gamma_init_t init;
-
- LOCK_TEST_WITH_RETURN( dev, filp );
-
- if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )
- return -EFAULT;
-
- switch ( init.func ) {
- case GAMMA_INIT_DMA:
- return gamma_do_init_dma( dev, &init );
- case GAMMA_CLEANUP_DMA:
- return gamma_do_cleanup_dma( dev );
- }
-
- return -EINVAL;
-}
-
-static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
-{
- drm_device_dma_t *dma = dev->dma;
- unsigned int *screenbuf;
-
- DRM_DEBUG( "%s\n", __FUNCTION__ );
-
- /* We've DRM_RESTRICTED this DMA buffer */
-
- screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
-
-#if 0
- *buffer++ = 0x180; /* Tag (FilterMode) */
- *buffer++ = 0x200; /* Allow FBColor through */
- *buffer++ = 0x53B; /* Tag */
- *buffer++ = copy->Pitch;
- *buffer++ = 0x53A; /* Tag */
- *buffer++ = copy->SrcAddress;
- *buffer++ = 0x539; /* Tag */
- *buffer++ = copy->WidthHeight; /* Initiates transfer */
- *buffer++ = 0x53C; /* Tag - DMAOutputAddress */
- *buffer++ = virt_to_phys((void*)screenbuf);
- *buffer++ = 0x53D; /* Tag - DMAOutputCount */
- *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
-
- /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
- /* Now put it back to the screen */
-
- *buffer++ = 0x180; /* Tag (FilterMode) */
- *buffer++ = 0x400; /* Allow Sync through */
- *buffer++ = 0x538; /* Tag - DMARectangleReadTarget */
- *buffer++ = 0x155; /* FBSourceData | count */
- *buffer++ = 0x537; /* Tag */
- *buffer++ = copy->Pitch;
- *buffer++ = 0x536; /* Tag */
- *buffer++ = copy->DstAddress;
- *buffer++ = 0x535; /* Tag */
- *buffer++ = copy->WidthHeight; /* Initiates transfer */
- *buffer++ = 0x530; /* Tag - DMAAddr */
- *buffer++ = virt_to_phys((void*)screenbuf);
- *buffer++ = 0x531;
- *buffer++ = copy->Count; /* initiates DMA transfer of color data */
-#endif
-
- /* need to dispatch it now */
-
- return 0;
-}
-
-int gamma_dma_copy( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_gamma_copy_t copy;
-
- if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )
- return -EFAULT;
-
- return gamma_do_copy_dma( dev, &copy );
-}
-
-/* =============================================================
- * Per Context SAREA Support
- */
-
-int gamma_getsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_priv_map_t __user *argp = (void __user *)arg;
- drm_ctx_priv_map_t request;
- drm_map_t *map;
-
- if (copy_from_user(&request, argp, sizeof(request)))
- return -EFAULT;
-
- down(&dev->struct_sem);
- if ((int)request.ctx_id >= dev->max_context) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
-
- map = dev->context_sareas[request.ctx_id];
- up(&dev->struct_sem);
-
- request.handle = map->handle;
- if (copy_to_user(argp, &request, sizeof(request)))
- return -EFAULT;
- return 0;
-}
-
-int gamma_setsareactx(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_ctx_priv_map_t request;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
- struct list_head *list;
-
- if (copy_from_user(&request,
- (drm_ctx_priv_map_t __user *)arg,
- sizeof(request)))
- return -EFAULT;
-
- down(&dev->struct_sem);
- r_list = NULL;
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
- if(r_list->map &&
- r_list->map->handle == request.handle) break;
- }
- if (list == &(dev->maplist->head)) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
- map = r_list->map;
- up(&dev->struct_sem);
-
- if (!map) return -EINVAL;
-
- down(&dev->struct_sem);
- if ((int)request.ctx_id >= dev->max_context) {
- up(&dev->struct_sem);
- return -EINVAL;
- }
- dev->context_sareas[request.ctx_id] = map;
- up(&dev->struct_sem);
- return 0;
-}
-
-void gamma_driver_irq_preinstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 );
- GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );
-}
-
-void gamma_driver_irq_postinstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 );
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 );
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 );
-}
-
-void gamma_driver_irq_uninstall( drm_device_t *dev ) {
- drm_gamma_private_t *dev_priv =
- (drm_gamma_private_t *)dev->dev_private;
- if (!dev_priv)
- return;
-
- while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
- cpu_relax();
-
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 );
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 );
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 );
-}
-
-extern drm_ioctl_desc_t DRM(ioctls)[];
-
-static int gamma_driver_preinit(drm_device_t *dev)
-{
- /* reset the finish ioctl */
- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
- return 0;
-}
-
-static void gamma_driver_pretakedown(drm_device_t *dev)
-{
- gamma_do_cleanup_dma(dev);
-}
-
-static void gamma_driver_dma_ready(drm_device_t *dev)
-{
- gamma_dma_ready(dev);
-}
-
-static int gamma_driver_dma_quiescent(drm_device_t *dev)
-{
- drm_gamma_private_t *dev_priv = (
- drm_gamma_private_t *)dev->dev_private;
- if (dev_priv->num_rast == 2)
- gamma_dma_quiescent_dual(dev);
- else gamma_dma_quiescent_single(dev);
- return 0;
-}
-
-void gamma_driver_register_fns(drm_device_t *dev)
-{
- dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
- DRM(fops).read = gamma_fops_read;
- DRM(fops).poll = gamma_fops_poll;
- dev->driver.preinit = gamma_driver_preinit;
- dev->driver.pretakedown = gamma_driver_pretakedown;
- dev->driver.dma_ready = gamma_driver_dma_ready;
- dev->driver.dma_quiescent = gamma_driver_dma_quiescent;
- dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;
- dev->driver.dma_flush_unblock = gamma_flush_unblock;
-}
diff --git a/drivers/char/drm/gamma_drm.h b/drivers/char/drm/gamma_drm.h
deleted file mode 100644
index 20819ded0e15..000000000000
--- a/drivers/char/drm/gamma_drm.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _GAMMA_DRM_H_
-#define _GAMMA_DRM_H_
-
-typedef struct _drm_gamma_tex_region {
- unsigned char next, prev; /* indices to form a circular LRU */
- unsigned char in_use; /* owned by a client, or free? */
- int age; /* tracked by clients to update local LRU's */
-} drm_gamma_tex_region_t;
-
-typedef struct {
- unsigned int GDeltaMode;
- unsigned int GDepthMode;
- unsigned int GGeometryMode;
- unsigned int GTransformMode;
-} drm_gamma_context_regs_t;
-
-typedef struct _drm_gamma_sarea {
- drm_gamma_context_regs_t context_state;
-
- unsigned int dirty;
-
-
- /* Maintain an LRU of contiguous regions of texture space. If
- * you think you own a region of texture memory, and it has an
- * age different to the one you set, then you are mistaken and
- * it has been stolen by another client. If global texAge
- * hasn't changed, there is no need to walk the list.
- *
- * These regions can be used as a proxy for the fine-grained
- * texture information of other clients - by maintaining them
- * in the same lru which is used to age their own textures,
- * clients have an approximate lru for the whole of global
- * texture space, and can make informed decisions as to which
- * areas to kick out. There is no need to choose whether to
- * kick out your own texture or someone else's - simply eject
- * them all in LRU order.
- */
-
-#define GAMMA_NR_TEX_REGIONS 64
- drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1];
- /* Last elt is sentinal */
- int texAge; /* last time texture was uploaded */
- int last_enqueue; /* last time a buffer was enqueued */
- int last_dispatch; /* age of the most recently dispatched buffer */
- int last_quiescent; /* */
- int ctxOwner; /* last context to upload state */
-
- int vertex_prim;
-} drm_gamma_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmGamma.h)
- */
-
-/* Gamma specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)
-#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t)
-
-typedef struct drm_gamma_copy {
- unsigned int DMAOutputAddress;
- unsigned int DMAOutputCount;
- unsigned int DMAReadGLINTSource;
- unsigned int DMARectangleWriteAddress;
- unsigned int DMARectangleWriteLinePitch;
- unsigned int DMARectangleWrite;
- unsigned int DMARectangleReadAddress;
- unsigned int DMARectangleReadLinePitch;
- unsigned int DMARectangleRead;
- unsigned int DMARectangleReadTarget;
-} drm_gamma_copy_t;
-
-typedef struct drm_gamma_init {
- enum {
- GAMMA_INIT_DMA = 0x01,
- GAMMA_CLEANUP_DMA = 0x02
- } func;
-
- int sarea_priv_offset;
- int pcimode;
- unsigned int mmio0;
- unsigned int mmio1;
- unsigned int mmio2;
- unsigned int mmio3;
- unsigned int buffers_offset;
- int num_rast;
-} drm_gamma_init_t;
-
-#endif /* _GAMMA_DRM_H_ */
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
deleted file mode 100644
index e7e64b62792a..000000000000
--- a/drivers/char/drm/gamma_drv.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan 4 08:58:31 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * PRECISION INSIGHT 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-#include <linux/config.h>
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "gamma_context.h" /* NOTE! */
-#include "drm_dma.h"
-#include "gamma_old_dma.h" /* NOTE */
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "gamma_lists.h" /* NOTE */
-#include "drm_lock.h"
-#include "gamma_lock.h" /* NOTE */
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
deleted file mode 100644
index 146fcc6253cd..000000000000
--- a/drivers/char/drm/gamma_drv.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * PRECISION INSIGHT 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#ifndef _GAMMA_DRV_H_
-#define _GAMMA_DRV_H_
-
-typedef struct drm_gamma_private {
- drm_gamma_sarea_t *sarea_priv;
- drm_map_t *sarea;
- drm_map_t *mmio0;
- drm_map_t *mmio1;
- drm_map_t *mmio2;
- drm_map_t *mmio3;
- int num_rast;
-} drm_gamma_private_t;
-
- /* gamma_dma.c */
-extern int gamma_dma_init( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int gamma_dma_copy( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-extern int gamma_do_cleanup_dma( drm_device_t *dev );
-extern void gamma_dma_ready(drm_device_t *dev);
-extern void gamma_dma_quiescent_single(drm_device_t *dev);
-extern void gamma_dma_quiescent_dual(drm_device_t *dev);
-
- /* gamma_dma.c */
-extern int gamma_dma_schedule(drm_device_t *dev, int locked);
-extern int gamma_dma(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int gamma_find_devices(void);
-extern int gamma_found(void);
-
-/* Gamma-specific code pulled from drm_fops.h:
- */
-extern int DRM(finish)(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int DRM(flush_unblock)(drm_device_t *dev, int context,
- drm_lock_flags_t flags);
-extern int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
- drm_lock_flags_t flags);
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-extern void DRM(clear_next_buffer)(drm_device_t *dev);
-extern int DRM(select_queue)(drm_device_t *dev,
- void (*wrapper)(unsigned long));
-extern int DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma);
-extern int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma);
-
-
-/* Gamma-specific code pulled from drm_lists.h (now renamed gamma_lists.h):
- */
-extern int DRM(waitlist_create)(drm_waitlist_t *bl, int count);
-extern int DRM(waitlist_destroy)(drm_waitlist_t *bl);
-extern int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
-extern drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl);
-extern int DRM(freelist_create)(drm_freelist_t *bl, int count);
-extern int DRM(freelist_destroy)(drm_freelist_t *bl);
-extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
- drm_buf_t *buf);
-extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
-
-/* externs for gamma changes to the ops */
-extern struct file_operations DRM(fops);
-extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
-extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
-
-
-#define GLINT_DRI_BUF_COUNT 256
-
-#define GAMMA_OFF(reg) \
- ((reg < 0x1000) \
- ? reg \
- : ((reg < 0x10000) \
- ? (reg - 0x1000) \
- : ((reg < 0x11000) \
- ? (reg - 0x10000) \
- : (reg - 0x11000))))
-
-#define GAMMA_BASE(reg) ((unsigned long) \
- ((reg < 0x1000) ? dev_priv->mmio0->handle : \
- ((reg < 0x10000) ? dev_priv->mmio1->handle : \
- ((reg < 0x11000) ? dev_priv->mmio2->handle : \
- dev_priv->mmio3->handle))))
-#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg))
-#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
-#define GAMMA_READ(reg) GAMMA_DEREF(reg)
-#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
-
-#define GAMMA_BROADCASTMASK 0x9378
-#define GAMMA_COMMANDINTENABLE 0x0c48
-#define GAMMA_DMAADDRESS 0x0028
-#define GAMMA_DMACOUNT 0x0030
-#define GAMMA_FILTERMODE 0x8c00
-#define GAMMA_GCOMMANDINTFLAGS 0x0c50
-#define GAMMA_GCOMMANDMODE 0x0c40
-#define GAMMA_QUEUED_DMA_MODE 1<<1
-#define GAMMA_GCOMMANDSTATUS 0x0c60
-#define GAMMA_GDELAYTIMER 0x0c38
-#define GAMMA_GDMACONTROL 0x0060
-#define GAMMA_USE_AGP 1<<1
-#define GAMMA_GINTENABLE 0x0808
-#define GAMMA_GINTFLAGS 0x0810
-#define GAMMA_INFIFOSPACE 0x0018
-#define GAMMA_OUTFIFOWORDS 0x0020
-#define GAMMA_OUTPUTFIFO 0x2000
-#define GAMMA_SYNC 0x8c40
-#define GAMMA_SYNC_TAG 0x0188
-#define GAMMA_PAGETABLEADDR 0x0C00
-#define GAMMA_PAGETABLELENGTH 0x0C08
-
-#define GAMMA_PASSTHROUGH 0x1FE
-#define GAMMA_DMAADDRTAG 0x530
-#define GAMMA_DMACOUNTTAG 0x531
-#define GAMMA_COMMANDINTTAG 0x532
-
-#endif
diff --git a/drivers/char/drm/gamma_lists.h b/drivers/char/drm/gamma_lists.h
deleted file mode 100644
index 2d93f412b96b..000000000000
--- a/drivers/char/drm/gamma_lists.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
- * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * VA LINUX SYSTEMS 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-
-
-int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
-{
- if (bl->count) return -EINVAL;
-
- bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
- DRM_MEM_BUFLISTS);
-
- if(!bl->bufs) return -ENOMEM;
- memset(bl->bufs, 0, sizeof(*bl->bufs));
- bl->count = count;
- bl->rp = bl->bufs;
- bl->wp = bl->bufs;
- bl->end = &bl->bufs[bl->count+1];
- spin_lock_init(&bl->write_lock);
- spin_lock_init(&bl->read_lock);
- return 0;
-}
-
-int DRM(waitlist_destroy)(drm_waitlist_t *bl)
-{
- if (bl->rp != bl->wp) return -EINVAL;
- if (bl->bufs) DRM(free)(bl->bufs,
- (bl->count + 2) * sizeof(*bl->bufs),
- DRM_MEM_BUFLISTS);
- bl->count = 0;
- bl->bufs = NULL;
- bl->rp = NULL;
- bl->wp = NULL;
- bl->end = NULL;
- return 0;
-}
-
-int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
-{
- int left;
- unsigned long flags;
-
- left = DRM_LEFTCOUNT(bl);
- if (!left) {
- DRM_ERROR("Overflow while adding buffer %d from filp %p\n",
- buf->idx, buf->filp);
- return -EINVAL;
- }
- buf->list = DRM_LIST_WAIT;
-
- spin_lock_irqsave(&bl->write_lock, flags);
- *bl->wp = buf;
- if (++bl->wp >= bl->end) bl->wp = bl->bufs;
- spin_unlock_irqrestore(&bl->write_lock, flags);
-
- return 0;
-}
-
-drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
-{
- drm_buf_t *buf;
- unsigned long flags;
-
- spin_lock_irqsave(&bl->read_lock, flags);
- buf = *bl->rp;
- if (bl->rp == bl->wp) {
- spin_unlock_irqrestore(&bl->read_lock, flags);
- return NULL;
- }
- if (++bl->rp >= bl->end) bl->rp = bl->bufs;
- spin_unlock_irqrestore(&bl->read_lock, flags);
-
- return buf;
-}
-
-int DRM(freelist_create)(drm_freelist_t *bl, int count)
-{
- atomic_set(&bl->count, 0);
- bl->next = NULL;
- init_waitqueue_head(&bl->waiting);
- bl->low_mark = 0;
- bl->high_mark = 0;
- atomic_set(&bl->wfh, 0);
- spin_lock_init(&bl->lock);
- ++bl->initialized;
- return 0;
-}
-
-int DRM(freelist_destroy)(drm_freelist_t *bl)
-{
- atomic_set(&bl->count, 0);
- bl->next = NULL;
- return 0;
-}
-
-int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
-{
- drm_device_dma_t *dma = dev->dma;
-
- if (!dma) {
- DRM_ERROR("No DMA support\n");
- return 1;
- }
-
- if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
- DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
- buf->idx, buf->waiting, buf->pending, buf->list);
- }
- if (!bl) return 1;
- buf->list = DRM_LIST_FREE;
-
- spin_lock(&bl->lock);
- buf->next = bl->next;
- bl->next = buf;
- spin_unlock(&bl->lock);
-
- atomic_inc(&bl->count);
- if (atomic_read(&bl->count) > dma->buf_count) {
- DRM_ERROR("%d of %d buffers free after addition of %d\n",
- atomic_read(&bl->count), dma->buf_count, buf->idx);
- return 1;
- }
- /* Check for high water mark */
- if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
- atomic_set(&bl->wfh, 0);
- wake_up_interruptible(&bl->waiting);
- }
- return 0;
-}
-
-static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
-{
- drm_buf_t *buf;
-
- if (!bl) return NULL;
-
- /* Get buffer */
- spin_lock(&bl->lock);
- if (!bl->next) {
- spin_unlock(&bl->lock);
- return NULL;
- }
- buf = bl->next;
- bl->next = bl->next->next;
- spin_unlock(&bl->lock);
-
- atomic_dec(&bl->count);
- buf->next = NULL;
- buf->list = DRM_LIST_NONE;
- if (buf->waiting || buf->pending) {
- DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
- buf->idx, buf->waiting, buf->pending, buf->list);
- }
-
- return buf;
-}
-
-drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
-{
- drm_buf_t *buf = NULL;
- DECLARE_WAITQUEUE(entry, current);
-
- if (!bl || !bl->initialized) return NULL;
-
- /* Check for low water mark */
- if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
- atomic_set(&bl->wfh, 1);
- if (atomic_read(&bl->wfh)) {
- if (block) {
- add_wait_queue(&bl->waiting, &entry);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!atomic_read(&bl->wfh)
- && (buf = DRM(freelist_try)(bl))) break;
- schedule();
- if (signal_pending(current)) break;
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&bl->waiting, &entry);
- }
- return buf;
- }
-
- return DRM(freelist_try)(bl);
-}
-
diff --git a/drivers/char/drm/gamma_lock.h b/drivers/char/drm/gamma_lock.h
deleted file mode 100644
index ddec67e4ed16..000000000000
--- a/drivers/char/drm/gamma_lock.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * VA LINUX SYSTEMS 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code extracted from drm_lock.h:
- */
-static int DRM(flush_queue)(drm_device_t *dev, int context)
-{
- DECLARE_WAITQUEUE(entry, current);
- int ret = 0;
- drm_queue_t *q = dev->queuelist[context];
-
- DRM_DEBUG("\n");
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) > 1) {
- atomic_inc(&q->block_write);
- add_wait_queue(&q->flush_queue, &entry);
- atomic_inc(&q->block_count);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!DRM_BUFCOUNT(&q->waitlist)) break;
- schedule();
- if (signal_pending(current)) {
- ret = -EINTR; /* Can't restart */
- break;
- }
- }
- atomic_dec(&q->block_count);
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->flush_queue, &entry);
- }
- atomic_dec(&q->use_count);
-
- /* NOTE: block_write is still incremented!
- Use drm_flush_unlock_queue to decrement. */
- return ret;
-}
-
-static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
-{
- drm_queue_t *q = dev->queuelist[context];
-
- DRM_DEBUG("\n");
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) > 1) {
- if (atomic_read(&q->block_write)) {
- atomic_dec(&q->block_write);
- wake_up_interruptible(&q->write_queue);
- }
- }
- atomic_dec(&q->use_count);
- return 0;
-}
-
-int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
- drm_lock_flags_t flags)
-{
- int ret = 0;
- int i;
-
- DRM_DEBUG("\n");
-
- if (flags & _DRM_LOCK_FLUSH) {
- ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
- if (!ret) ret = DRM(flush_queue)(dev, context);
- }
- if (flags & _DRM_LOCK_FLUSH_ALL) {
- for (i = 0; !ret && i < dev->queue_count; i++) {
- ret = DRM(flush_queue)(dev, i);
- }
- }
- return ret;
-}
-
-int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
-{
- int ret = 0;
- int i;
-
- DRM_DEBUG("\n");
-
- if (flags & _DRM_LOCK_FLUSH) {
- ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
- if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
- }
- if (flags & _DRM_LOCK_FLUSH_ALL) {
- for (i = 0; !ret && i < dev->queue_count; i++) {
- ret = DRM(flush_unblock_queue)(dev, i);
- }
- }
-
- return ret;
-}
-
-int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int ret = 0;
- drm_lock_t lock;
-
- DRM_DEBUG("\n");
-
- if (copy_from_user(&lock, (drm_lock_t __user *)arg, sizeof(lock)))
- return -EFAULT;
- ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
- DRM(flush_unblock)(dev, lock.context, lock.flags);
- return ret;
-}
diff --git a/drivers/char/drm/gamma_old_dma.h b/drivers/char/drm/gamma_old_dma.h
deleted file mode 100644
index abdd454aab9f..000000000000
--- a/drivers/char/drm/gamma_old_dma.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * 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, 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
- * VA LINUX SYSTEMS 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:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-
-void DRM(clear_next_buffer)(drm_device_t *dev)
-{
- drm_device_dma_t *dma = dev->dma;
-
- dma->next_buffer = NULL;
- if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
- wake_up_interruptible(&dma->next_queue->flush_queue);
- }
- dma->next_queue = NULL;
-}
-
-int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
-{
- int i;
- int candidate = -1;
- int j = jiffies;
-
- if (!dev) {
- DRM_ERROR("No device\n");
- return -1;
- }
- if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
- /* This only happens between the time the
- interrupt is initialized and the time
- the queues are initialized. */
- return -1;
- }
-
- /* Doing "while locked" DMA? */
- if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
- return DRM_KERNEL_CONTEXT;
- }
-
- /* If there are buffers on the last_context
- queue, and we have not been executing
- this context very long, continue to
- execute this context. */
- if (dev->last_switch <= j
- && dev->last_switch + DRM_TIME_SLICE > j
- && DRM_WAITCOUNT(dev, dev->last_context)) {
- return dev->last_context;
- }
-
- /* Otherwise, find a candidate */
- for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
- if (DRM_WAITCOUNT(dev, i)) {
- candidate = dev->last_checked = i;
- break;
- }
- }
-
- if (candidate < 0) {
- for (i = 0; i < dev->queue_count; i++) {
- if (DRM_WAITCOUNT(dev, i)) {
- candidate = dev->last_checked = i;
- break;
- }
- }
- }
-
- if (wrapper
- && candidate >= 0
- && candidate != dev->last_context
- && dev->last_switch <= j
- && dev->last_switch + DRM_TIME_SLICE > j) {
- if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
- del_timer(&dev->timer);
- dev->timer.function = wrapper;
- dev->timer.data = (unsigned long)dev;
- dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
- add_timer(&dev->timer);
- }
- return -1;
- }
-
- return candidate;
-}
-
-
-int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int i;
- drm_queue_t *q;
- drm_buf_t *buf;
- int idx;
- int while_locked = 0;
- drm_device_dma_t *dma = dev->dma;
- int *ind;
- int err;
- DECLARE_WAITQUEUE(entry, current);
-
- DRM_DEBUG("%d\n", d->send_count);
-
- if (d->flags & _DRM_DMA_WHILE_LOCKED) {
- int context = dev->lock.hw_lock->lock;
-
- if (!_DRM_LOCK_IS_HELD(context)) {
- DRM_ERROR("No lock held during \"while locked\""
- " request\n");
- return -EINVAL;
- }
- if (d->context != _DRM_LOCKING_CONTEXT(context)
- && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
- DRM_ERROR("Lock held by %d while %d makes"
- " \"while locked\" request\n",
- _DRM_LOCKING_CONTEXT(context),
- d->context);
- return -EINVAL;
- }
- q = dev->queuelist[DRM_KERNEL_CONTEXT];
- while_locked = 1;
- } else {
- q = dev->queuelist[d->context];
- }
-
-
- atomic_inc(&q->use_count);
- if (atomic_read(&q->block_write)) {
- add_wait_queue(&q->write_queue, &entry);
- atomic_inc(&q->block_count);
- for (;;) {
- current->state = TASK_INTERRUPTIBLE;
- if (!atomic_read(&q->block_write)) break;
- schedule();
- if (signal_pending(current)) {
- atomic_dec(&q->use_count);
- remove_wait_queue(&q->write_queue, &entry);
- return -EINTR;
- }
- }
- atomic_dec(&q->block_count);
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->write_queue, &entry);
- }
-
- ind = DRM(alloc)(d->send_count * sizeof(int), DRM_MEM_DRIVER);
- if (!ind)
- return -ENOMEM;
-
- if (copy_from_user(ind, d->send_indices, d->send_count * sizeof(int))) {
- err = -EFAULT;
- goto out;
- }
-
- err = -EINVAL;
- for (i = 0; i < d->send_count; i++) {
- idx = ind[i];
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- ind[i], dma->buf_count - 1);
- goto out;
- }
- buf = dma->buflist[ idx ];
- if (buf->filp != filp) {
- DRM_ERROR("Process %d using buffer not owned\n",
- current->pid);
- goto out;
- }
- if (buf->list != DRM_LIST_NONE) {
- DRM_ERROR("Process %d using buffer %d on list %d\n",
- current->pid, buf->idx, buf->list);
- goto out;
- }
- buf->used = ind[i];
- buf->while_locked = while_locked;
- buf->context = d->context;
- if (!buf->used) {
- DRM_ERROR("Queueing 0 length buffer\n");
- }
- if (buf->pending) {
- DRM_ERROR("Queueing pending buffer:"
- " buffer %d, offset %d\n",
- ind[i], i);
- goto out;
- }
- if (buf->waiting) {
- DRM_ERROR("Queueing waiting buffer:"
- " buffer %d, offset %d\n",
- ind[i], i);
- goto out;
- }
- buf->waiting = 1;
- if (atomic_read(&q->use_count) == 1
- || atomic_read(&q->finalization)) {
- DRM(free_buffer)(dev, buf);
- } else {
- DRM(waitlist_put)(&q->waitlist, buf);
- atomic_inc(&q->total_queued);
- }
- }
- atomic_dec(&q->use_count);
-
- return 0;
-
-out:
- DRM(free)(ind, d->send_count * sizeof(int), DRM_MEM_DRIVER);
- atomic_dec(&q->use_count);
- return err;
-}
-
-static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
- int order)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int i;
- drm_buf_t *buf;
- drm_device_dma_t *dma = dev->dma;
-
- for (i = d->granted_count; i < d->request_count; i++) {
- buf = DRM(freelist_get)(&dma->bufs[order].freelist,
- d->flags & _DRM_DMA_WAIT);
- if (!buf) break;
- if (buf->pending || buf->waiting) {
- DRM_ERROR("Free buffer %d in use: filp %p (w%d, p%d)\n",
- buf->idx,
- buf->filp,
- buf->waiting,
- buf->pending);
- }
- buf->filp = filp;
- if (copy_to_user(&d->request_indices[i],
- &buf->idx,
- sizeof(buf->idx)))
- return -EFAULT;
-
- if (copy_to_user(&d->request_sizes[i],
- &buf->total,
- sizeof(buf->total)))
- return -EFAULT;
-
- ++d->granted_count;
- }
- return 0;
-}
-
-
-int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma)
-{
- int order;
- int retcode = 0;
- int tmp_order;
-
- order = DRM(order)(dma->request_size);
-
- dma->granted_count = 0;
- retcode = DRM(dma_get_buffers_of_order)(filp, dma, order);
-
- if (dma->granted_count < dma->request_count
- && (dma->flags & _DRM_DMA_SMALLER_OK)) {
- for (tmp_order = order - 1;
- !retcode
- && dma->granted_count < dma->request_count
- && tmp_order >= DRM_MIN_ORDER;
- --tmp_order) {
-
- retcode = DRM(dma_get_buffers_of_order)(filp, dma,
- tmp_order);
- }
- }
-
- if (dma->granted_count < dma->request_count
- && (dma->flags & _DRM_DMA_LARGER_OK)) {
- for (tmp_order = order + 1;
- !retcode
- && dma->granted_count < dma->request_count
- && tmp_order <= DRM_MAX_ORDER;
- ++tmp_order) {
-
- retcode = DRM(dma_get_buffers_of_order)(filp, dma,
- tmp_order);
- }
- }
- return 0;
-}
-
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 18e0b7622893..dba502373da1 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -45,107 +45,101 @@
#define I810_BUF_UNMAPPED 0
#define I810_BUF_MAPPED 1
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
-static drm_buf_t *i810_freelist_get(drm_device_t *dev)
+static drm_buf_t *i810_freelist_get(drm_device_t * dev)
{
- drm_device_dma_t *dma = dev->dma;
- int i;
- int used;
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+ int used;
/* Linear search might not be the best solution */
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
- used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
+ used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
I810_BUF_CLIENT);
if (used == I810_BUF_FREE) {
return buf;
}
}
- return NULL;
+ return NULL;
}
/* This should only be called if the buffer is not sent to the hardware
* yet, the hardware updates in use for us once its on the ring buffer.
*/
-static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
{
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- int used;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ int used;
- /* In use is already a pointer */
- used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+ /* In use is already a pointer */
+ used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
if (used != I810_BUF_CLIENT) {
- DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
- return -EINVAL;
+ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+ return -EINVAL;
}
- return 0;
+ return 0;
}
static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
- drm_i810_private_t *dev_priv;
- drm_buf_t *buf;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+ drm_i810_private_t *dev_priv;
+ drm_buf_t *buf;
drm_i810_buf_priv_t *buf_priv;
lock_kernel();
- dev = priv->head->dev;
+ dev = priv->head->dev;
dev_priv = dev->dev_private;
- buf = dev_priv->mmap_buffer;
+ buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
vma->vm_flags |= (VM_IO | VM_DONTCOPY);
vma->vm_file = filp;
- buf_priv->currently_mapped = I810_BUF_MAPPED;
+ buf_priv->currently_mapped = I810_BUF_MAPPED;
unlock_kernel();
if (io_remap_pfn_range(vma, vma->vm_start,
- VM_OFFSET(vma) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot)) return -EAGAIN;
+ VM_OFFSET(vma) >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
return 0;
}
static struct file_operations i810_buffer_fops = {
- .open = drm_open,
- .flush = drm_flush,
+ .open = drm_open,
+ .flush = drm_flush,
.release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = i810_mmap_buffers,
- .fasync = drm_fasync,
+ .ioctl = drm_ioctl,
+ .mmap = i810_mmap_buffers,
+ .fasync = drm_fasync,
};
-static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
+static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- drm_i810_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ struct file_operations *old_fops;
int retcode = 0;
- if (buf_priv->currently_mapped == I810_BUF_MAPPED)
+ if (buf_priv->currently_mapped == I810_BUF_MAPPED)
return -EINVAL;
- down_write( &current->mm->mmap_sem );
+ down_write(&current->mm->mmap_sem);
old_fops = filp->f_op;
filp->f_op = &i810_buffer_fops;
dev_priv->mmap_buffer = buf;
buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- buf->bus_address);
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, buf->bus_address);
dev_priv->mmap_buffer = NULL;
filp->f_op = old_fops;
if ((unsigned long)buf_priv->virtual > -1024UL) {
@@ -154,12 +148,12 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
retcode = (signed int)buf_priv->virtual;
buf_priv->virtual = NULL;
}
- up_write( &current->mm->mmap_sem );
+ up_write(&current->mm->mmap_sem);
return retcode;
}
-static int i810_unmap_buffer(drm_buf_t *buf)
+static int i810_unmap_buffer(drm_buf_t * buf)
{
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int retcode = 0;
@@ -173,43 +167,43 @@ static int i810_unmap_buffer(drm_buf_t *buf)
(size_t) buf->total);
up_write(&current->mm->mmap_sem);
- buf_priv->currently_mapped = I810_BUF_UNMAPPED;
- buf_priv->virtual = NULL;
+ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ buf_priv->virtual = NULL;
return retcode;
}
-static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
+static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
struct file *filp)
{
- drm_buf_t *buf;
+ drm_buf_t *buf;
drm_i810_buf_priv_t *buf_priv;
int retcode = 0;
buf = i810_freelist_get(dev);
if (!buf) {
retcode = -ENOMEM;
- DRM_DEBUG("retcode=%d\n", retcode);
+ DRM_DEBUG("retcode=%d\n", retcode);
return retcode;
}
retcode = i810_map_buffer(buf, filp);
if (retcode) {
i810_freelist_put(dev, buf);
- DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+ DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
return retcode;
}
buf->filp = filp;
buf_priv = buf->dev_private;
d->granted = 1;
- d->request_idx = buf->idx;
- d->request_size = buf->total;
- d->virtual = buf_priv->virtual;
+ d->request_idx = buf->idx;
+ d->request_size = buf->total;
+ d->virtual = buf_priv->virtual;
return retcode;
}
-static int i810_dma_cleanup(drm_device_t *dev)
+static int i810_dma_cleanup(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -222,164 +216,167 @@ static int i810_dma_cleanup(drm_device_t *dev)
if (dev->dev_private) {
int i;
- drm_i810_private_t *dev_priv =
- (drm_i810_private_t *) dev->dev_private;
+ drm_i810_private_t *dev_priv =
+ (drm_i810_private_t *) dev->dev_private;
if (dev_priv->ring.virtual_start) {
- drm_ioremapfree((void *) dev_priv->ring.virtual_start,
- dev_priv->ring.Size, dev);
+ drm_ioremapfree((void *)dev_priv->ring.virtual_start,
+ dev_priv->ring.Size, dev);
}
- if (dev_priv->hw_status_page) {
- pci_free_consistent(dev->pdev, PAGE_SIZE,
+ if (dev_priv->hw_status_page) {
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
dev_priv->hw_status_page,
dev_priv->dma_status_page);
- /* Need to rewrite hardware status page */
- I810_WRITE(0x02080, 0x1ffff000);
+ /* Need to rewrite hardware status page */
+ I810_WRITE(0x02080, 0x1ffff000);
}
- drm_free(dev->dev_private, sizeof(drm_i810_private_t),
+ drm_free(dev->dev_private, sizeof(drm_i810_private_t),
DRM_MEM_DRIVER);
- dev->dev_private = NULL;
+ dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
+ drm_buf_t *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- if ( buf_priv->kernel_virtual && buf->total )
- drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
+ if (buf_priv->kernel_virtual && buf->total)
+ drm_ioremapfree(buf_priv->kernel_virtual,
+ buf->total, dev);
}
}
- return 0;
+ return 0;
}
-static int i810_wait_ring(drm_device_t *dev, int n)
+static int i810_wait_ring(drm_device_t * dev, int n)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
- int iters = 0;
- unsigned long end;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+ int iters = 0;
+ unsigned long end;
unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- end = jiffies + (HZ*3);
- while (ring->space < n) {
- ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- ring->space = ring->head - (ring->tail+8);
- if (ring->space < 0) ring->space += ring->Size;
-
+ end = jiffies + (HZ * 3);
+ while (ring->space < n) {
+ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->Size;
+
if (ring->head != last_head) {
- end = jiffies + (HZ*3);
+ end = jiffies + (HZ * 3);
last_head = ring->head;
}
-
- iters++;
+
+ iters++;
if (time_before(end, jiffies)) {
- DRM_ERROR("space: %d wanted %d\n", ring->space, n);
- DRM_ERROR("lockup\n");
- goto out_wait_ring;
+ DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+ DRM_ERROR("lockup\n");
+ goto out_wait_ring;
}
udelay(1);
}
-out_wait_ring:
- return iters;
+ out_wait_ring:
+ return iters;
}
-static void i810_kernel_lost_context(drm_device_t *dev)
+static void i810_kernel_lost_context(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
- ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- ring->tail = I810_READ(LP_RING + RING_TAIL);
- ring->space = ring->head - (ring->tail+8);
- if (ring->space < 0) ring->space += ring->Size;
+ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->tail = I810_READ(LP_RING + RING_TAIL);
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->Size;
}
-static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
+static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
{
- drm_device_dma_t *dma = dev->dma;
- int my_idx = 24;
- u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
- int i;
+ drm_device_dma_t *dma = dev->dma;
+ int my_idx = 24;
+ u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
+ int i;
if (dma->buf_count > 1019) {
- /* Not enough space in the status page for the freelist */
- return -EINVAL;
+ /* Not enough space in the status page for the freelist */
+ return -EINVAL;
}
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- buf_priv->in_use = hw_status++;
- buf_priv->my_use_idx = my_idx;
- my_idx += 4;
+ buf_priv->in_use = hw_status++;
+ buf_priv->my_use_idx = my_idx;
+ my_idx += 4;
- *buf_priv->in_use = I810_BUF_FREE;
+ *buf_priv->in_use = I810_BUF_FREE;
buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
- buf->total, dev);
+ buf->total, dev);
}
return 0;
}
-static int i810_dma_initialize(drm_device_t *dev,
- drm_i810_private_t *dev_priv,
- drm_i810_init_t *init)
+static int i810_dma_initialize(drm_device_t * dev,
+ drm_i810_private_t * dev_priv,
+ drm_i810_init_t * init)
{
struct list_head *list;
- memset(dev_priv, 0, sizeof(drm_i810_private_t));
+ memset(dev_priv, 0, sizeof(drm_i810_private_t));
list_for_each(list, &dev->maplist->head) {
drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
if (r_list->map &&
r_list->map->type == _DRM_SHM &&
- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+ r_list->map->flags & _DRM_CONTAINS_LOCK) {
dev_priv->sarea_map = r_list->map;
- break;
- }
- }
+ break;
+ }
+ }
if (!dev_priv->sarea_map) {
dev->dev_private = (void *)dev_priv;
- i810_dma_cleanup(dev);
- DRM_ERROR("can not find sarea!\n");
- return -EINVAL;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find sarea!\n");
+ return -EINVAL;
}
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
if (!dev_priv->mmio_map) {
dev->dev_private = (void *)dev_priv;
- i810_dma_cleanup(dev);
- DRM_ERROR("can not find mmio map!\n");
- return -EINVAL;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+ return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
- i810_dma_cleanup(dev);
- DRM_ERROR("can not find dma buffer map!\n");
- return -EINVAL;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not find dma buffer map!\n");
+ return -EINVAL;
}
dev_priv->sarea_priv = (drm_i810_sarea_t *)
- ((u8 *)dev_priv->sarea_map->handle +
- init->sarea_priv_offset);
+ ((u8 *) dev_priv->sarea_map->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.Start = init->ring_start;
+ dev_priv->ring.End = init->ring_end;
+ dev_priv->ring.Size = init->ring_size;
- dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
- init->ring_start,
- init->ring_size, dev);
+ dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
+ init->ring_start,
+ init->ring_size, dev);
- if (dev_priv->ring.virtual_start == NULL) {
- dev->dev_private = (void *) dev_priv;
- i810_dma_cleanup(dev);
- DRM_ERROR("can not ioremap virtual address for"
+ if (dev_priv->ring.virtual_start == NULL) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
- return -ENOMEM;
+ return -ENOMEM;
}
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
dev_priv->w = init->w;
dev_priv->h = init->h;
@@ -395,33 +392,33 @@ static int i810_dma_initialize(drm_device_t *dev,
dev_priv->back_di1 = init->back_offset | init->pitch_bits;
dev_priv->zi1 = init->depth_offset | init->pitch_bits;
- /* Program Hardware Status Page */
- dev_priv->hw_status_page =
- pci_alloc_consistent(dev->pdev, PAGE_SIZE,
- &dev_priv->dma_status_page);
- if (!dev_priv->hw_status_page) {
+ /* Program Hardware Status Page */
+ dev_priv->hw_status_page =
+ pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+ &dev_priv->dma_status_page);
+ if (!dev_priv->hw_status_page) {
dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
I810_WRITE(0x02080, dev_priv->dma_status_page);
- DRM_DEBUG("Enabled hardware status page\n");
+ DRM_DEBUG("Enabled hardware status page\n");
- /* Now we need to init our freelist */
+ /* Now we need to init our freelist */
if (i810_freelist_init(dev, dev_priv) != 0) {
dev->dev_private = (void *)dev_priv;
- i810_dma_cleanup(dev);
- DRM_ERROR("Not enough space in the status page for"
+ i810_dma_cleanup(dev);
+ DRM_ERROR("Not enough space in the status page for"
" the freelist\n");
- return -ENOMEM;
+ return -ENOMEM;
}
dev->dev_private = (void *)dev_priv;
- return 0;
+ return 0;
}
/* i810 DRM version 1.1 used a smaller init structure with different
@@ -435,12 +432,12 @@ static int i810_dma_initialize(drm_device_t *dev,
* If it isn't then we have a v1.1 client. Fix up params.
* If it is, then we have a 1.2 client... get the rest of the data.
*/
-static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
+static int i810_dma_init_compat(drm_i810_init_t * init, unsigned long arg)
{
/* Get v1.1 init data */
- if (copy_from_user(init, (drm_i810_pre12_init_t __user *)arg,
- sizeof(drm_i810_pre12_init_t))) {
+ if (copy_from_user(init, (drm_i810_pre12_init_t __user *) arg,
+ sizeof(drm_i810_pre12_init_t))) {
return -EFAULT;
}
@@ -448,7 +445,7 @@ static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
/* This is a v1.2 client, just get the v1.2 init data */
DRM_INFO("Using POST v1.2 init.\n");
- if (copy_from_user(init, (drm_i810_init_t __user *)arg,
+ if (copy_from_user(init, (drm_i810_init_t __user *) arg,
sizeof(drm_i810_init_t))) {
return -EFAULT;
}
@@ -456,246 +453,239 @@ static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
/* This is a v1.1 client, fix the params */
DRM_INFO("Using PRE v1.2 init.\n");
- init->pitch_bits = init->h;
- init->pitch = init->w;
- init->h = init->overlay_physical;
- init->w = init->overlay_offset;
- init->overlay_physical = 0;
- init->overlay_offset = 0;
+ init->pitch_bits = init->h;
+ init->pitch = init->w;
+ init->h = init->overlay_physical;
+ init->w = init->overlay_offset;
+ init->overlay_physical = 0;
+ init->overlay_offset = 0;
}
return 0;
}
static int i810_dma_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv;
- drm_i810_init_t init;
- int retcode = 0;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_i810_private_t *dev_priv;
+ drm_i810_init_t init;
+ int retcode = 0;
/* Get only the init func */
- if (copy_from_user(&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
+ if (copy_from_user
+ (&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
return -EFAULT;
- switch(init.func) {
- case I810_INIT_DMA:
- /* This case is for backward compatibility. It
- * handles XFree 4.1.0 and 4.2.0, and has to
- * do some parameter checking as described below.
- * It will someday go away.
- */
- retcode = i810_dma_init_compat(&init, arg);
- if (retcode)
- return retcode;
-
- dev_priv = drm_alloc(sizeof(drm_i810_private_t),
- DRM_MEM_DRIVER);
- if (dev_priv == NULL)
- return -ENOMEM;
- retcode = i810_dma_initialize(dev, dev_priv, &init);
- break;
-
- default:
- case I810_INIT_DMA_1_4:
- DRM_INFO("Using v1.4 init.\n");
- if (copy_from_user(&init, (drm_i810_init_t __user *)arg,
- sizeof(drm_i810_init_t))) {
- return -EFAULT;
- }
- dev_priv = drm_alloc(sizeof(drm_i810_private_t),
- DRM_MEM_DRIVER);
- if (dev_priv == NULL)
- return -ENOMEM;
- retcode = i810_dma_initialize(dev, dev_priv, &init);
- break;
-
- case I810_CLEANUP_DMA:
- DRM_INFO("DMA Cleanup\n");
- retcode = i810_dma_cleanup(dev);
- break;
+ switch (init.func) {
+ case I810_INIT_DMA:
+ /* This case is for backward compatibility. It
+ * handles XFree 4.1.0 and 4.2.0, and has to
+ * do some parameter checking as described below.
+ * It will someday go away.
+ */
+ retcode = i810_dma_init_compat(&init, arg);
+ if (retcode)
+ return retcode;
+
+ dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+ DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+ retcode = i810_dma_initialize(dev, dev_priv, &init);
+ break;
+
+ default:
+ case I810_INIT_DMA_1_4:
+ DRM_INFO("Using v1.4 init.\n");
+ if (copy_from_user(&init, (drm_i810_init_t __user *) arg,
+ sizeof(drm_i810_init_t))) {
+ return -EFAULT;
+ }
+ dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+ DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+ retcode = i810_dma_initialize(dev, dev_priv, &init);
+ break;
+
+ case I810_CLEANUP_DMA:
+ DRM_INFO("DMA Cleanup\n");
+ retcode = i810_dma_cleanup(dev);
+ break;
}
- return retcode;
+ return retcode;
}
-
-
/* Most efficient way to verify state for the i810 is as it is
* emitted. Non-conformant state is silently dropped.
*
* Use 'volatile' & local var tmp to force the emitted values to be
* identical to the verified ones.
*/
-static void i810EmitContextVerified( drm_device_t *dev,
- volatile unsigned int *code )
+static void i810EmitContextVerified(drm_device_t * dev,
+ volatile unsigned int *code)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
+ BEGIN_LP_RING(I810_CTX_SETUP_SIZE);
- OUT_RING( GFX_OP_COLOR_FACTOR );
- OUT_RING( code[I810_CTXREG_CF1] );
+ OUT_RING(GFX_OP_COLOR_FACTOR);
+ OUT_RING(code[I810_CTXREG_CF1]);
- OUT_RING( GFX_OP_STIPPLE );
- OUT_RING( code[I810_CTXREG_ST1] );
+ OUT_RING(GFX_OP_STIPPLE);
+ OUT_RING(code[I810_CTXREG_ST1]);
- for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
+ for (i = 4; i < I810_CTX_SETUP_SIZE; i++) {
tmp = code[i];
- if ((tmp & (7<<29)) == (3<<29) &&
- (tmp & (0x1f<<24)) < (0x1d<<24))
- {
- OUT_RING( tmp );
+ if ((tmp & (7 << 29)) == (3 << 29) &&
+ (tmp & (0x1f << 24)) < (0x1d << 24)) {
+ OUT_RING(tmp);
j++;
- }
- else printk("constext state dropped!!!\n");
+ } else
+ printk("constext state dropped!!!\n");
}
if (j & 1)
- OUT_RING( 0 );
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-static void i810EmitTexVerified( drm_device_t *dev,
- volatile unsigned int *code )
+static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
+ BEGIN_LP_RING(I810_TEX_SETUP_SIZE);
- OUT_RING( GFX_OP_MAP_INFO );
- OUT_RING( code[I810_TEXREG_MI1] );
- OUT_RING( code[I810_TEXREG_MI2] );
- OUT_RING( code[I810_TEXREG_MI3] );
+ OUT_RING(GFX_OP_MAP_INFO);
+ OUT_RING(code[I810_TEXREG_MI1]);
+ OUT_RING(code[I810_TEXREG_MI2]);
+ OUT_RING(code[I810_TEXREG_MI3]);
- for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
+ for (i = 4; i < I810_TEX_SETUP_SIZE; i++) {
tmp = code[i];
- if ((tmp & (7<<29)) == (3<<29) &&
- (tmp & (0x1f<<24)) < (0x1d<<24))
- {
- OUT_RING( tmp );
+ if ((tmp & (7 << 29)) == (3 << 29) &&
+ (tmp & (0x1f << 24)) < (0x1d << 24)) {
+ OUT_RING(tmp);
j++;
- }
- else printk("texture state dropped!!!\n");
+ } else
+ printk("texture state dropped!!!\n");
}
if (j & 1)
- OUT_RING( 0 );
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-
/* Need to do some additional checking when setting the dest buffer.
*/
-static void i810EmitDestVerified( drm_device_t *dev,
- volatile unsigned int *code )
+static void i810EmitDestVerified(drm_device_t * dev,
+ volatile unsigned int *code)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+ BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
tmp = code[I810_DESTREG_DI1];
if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
- OUT_RING( CMD_OP_DESTBUFFER_INFO );
- OUT_RING( tmp );
+ OUT_RING(CMD_OP_DESTBUFFER_INFO);
+ OUT_RING(tmp);
} else
- DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
- tmp, dev_priv->front_di1, dev_priv->back_di1);
+ DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+ tmp, dev_priv->front_di1, dev_priv->back_di1);
/* invarient:
*/
- OUT_RING( CMD_OP_Z_BUFFER_INFO );
- OUT_RING( dev_priv->zi1 );
+ OUT_RING(CMD_OP_Z_BUFFER_INFO);
+ OUT_RING(dev_priv->zi1);
- OUT_RING( GFX_OP_DESTBUFFER_VARS );
- OUT_RING( code[I810_DESTREG_DV1] );
+ OUT_RING(GFX_OP_DESTBUFFER_VARS);
+ OUT_RING(code[I810_DESTREG_DV1]);
- OUT_RING( GFX_OP_DRAWRECT_INFO );
- OUT_RING( code[I810_DESTREG_DR1] );
- OUT_RING( code[I810_DESTREG_DR2] );
- OUT_RING( code[I810_DESTREG_DR3] );
- OUT_RING( code[I810_DESTREG_DR4] );
- OUT_RING( 0 );
+ OUT_RING(GFX_OP_DRAWRECT_INFO);
+ OUT_RING(code[I810_DESTREG_DR1]);
+ OUT_RING(code[I810_DESTREG_DR2]);
+ OUT_RING(code[I810_DESTREG_DR3]);
+ OUT_RING(code[I810_DESTREG_DR4]);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-
-
-static void i810EmitState( drm_device_t *dev )
+static void i810EmitState(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
-
+
DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
if (dirty & I810_UPLOAD_BUFFERS) {
- i810EmitDestVerified( dev, sarea_priv->BufferState );
+ i810EmitDestVerified(dev, sarea_priv->BufferState);
sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
}
if (dirty & I810_UPLOAD_CTX) {
- i810EmitContextVerified( dev, sarea_priv->ContextState );
+ i810EmitContextVerified(dev, sarea_priv->ContextState);
sarea_priv->dirty &= ~I810_UPLOAD_CTX;
}
if (dirty & I810_UPLOAD_TEX0) {
- i810EmitTexVerified( dev, sarea_priv->TexState[0] );
+ i810EmitTexVerified(dev, sarea_priv->TexState[0]);
sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
}
if (dirty & I810_UPLOAD_TEX1) {
- i810EmitTexVerified( dev, sarea_priv->TexState[1] );
+ i810EmitTexVerified(dev, sarea_priv->TexState[1]);
sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
}
}
-
-
/* need to verify
*/
-static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
- unsigned int clear_color,
- unsigned int clear_zval )
+static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_zval)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = 2;
int i;
RING_LOCALS;
-
- if ( dev_priv->current_page == 1 ) {
- unsigned int tmp = flags;
-
+
+ if (dev_priv->current_page == 1) {
+ unsigned int tmp = flags;
+
flags &= ~(I810_FRONT | I810_BACK);
- if (tmp & I810_FRONT) flags |= I810_BACK;
- if (tmp & I810_BACK) flags |= I810_FRONT;
+ if (tmp & I810_FRONT)
+ flags |= I810_BACK;
+ if (tmp & I810_BACK)
+ flags |= I810_FRONT;
}
- i810_kernel_lost_context(dev);
+ i810_kernel_lost_context(dev);
- if (nbox > I810_NR_SAREA_CLIPRECTS)
- nbox = I810_NR_SAREA_CLIPRECTS;
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
- for (i = 0 ; i < nbox ; i++, pbox++) {
+ for (i = 0; i < nbox; i++, pbox++) {
unsigned int x = pbox->x1;
unsigned int y = pbox->y1;
unsigned int width = (pbox->x2 - x) * cpp;
@@ -704,52 +694,48 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
- pbox->x2 > dev_priv->w ||
- pbox->y2 > dev_priv->h)
+ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
continue;
- if ( flags & I810_FRONT ) {
- BEGIN_LP_RING( 6 );
- OUT_RING( BR00_BITBLT_CLIENT |
- BR00_OP_COLOR_BLT | 0x3 );
- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
- OUT_RING( (height << 16) | width );
- OUT_RING( start );
- OUT_RING( clear_color );
- OUT_RING( 0 );
+ if (flags & I810_FRONT) {
+ BEGIN_LP_RING(6);
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+ OUT_RING((height << 16) | width);
+ OUT_RING(start);
+ OUT_RING(clear_color);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
- if ( flags & I810_BACK ) {
- BEGIN_LP_RING( 6 );
- OUT_RING( BR00_BITBLT_CLIENT |
- BR00_OP_COLOR_BLT | 0x3 );
- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
- OUT_RING( (height << 16) | width );
- OUT_RING( dev_priv->back_offset + start );
- OUT_RING( clear_color );
- OUT_RING( 0 );
+ if (flags & I810_BACK) {
+ BEGIN_LP_RING(6);
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+ OUT_RING((height << 16) | width);
+ OUT_RING(dev_priv->back_offset + start);
+ OUT_RING(clear_color);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
- if ( flags & I810_DEPTH ) {
- BEGIN_LP_RING( 6 );
- OUT_RING( BR00_BITBLT_CLIENT |
- BR00_OP_COLOR_BLT | 0x3 );
- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
- OUT_RING( (height << 16) | width );
- OUT_RING( dev_priv->depth_offset + start );
- OUT_RING( clear_zval );
- OUT_RING( 0 );
+ if (flags & I810_DEPTH) {
+ BEGIN_LP_RING(6);
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+ OUT_RING((height << 16) | width);
+ OUT_RING(dev_priv->depth_offset + start);
+ OUT_RING(clear_zval);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
}
}
-static void i810_dma_dispatch_swap( drm_device_t *dev )
+static void i810_dma_dispatch_swap(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
@@ -759,75 +745,71 @@ static void i810_dma_dispatch_swap( drm_device_t *dev )
DRM_DEBUG("swapbuffers\n");
- i810_kernel_lost_context(dev);
+ i810_kernel_lost_context(dev);
- if (nbox > I810_NR_SAREA_CLIPRECTS)
- nbox = I810_NR_SAREA_CLIPRECTS;
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
- for (i = 0 ; i < nbox; i++, pbox++)
- {
+ for (i = 0; i < nbox; i++, pbox++) {
unsigned int w = pbox->x2 - pbox->x1;
unsigned int h = pbox->y2 - pbox->y1;
- unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
+ unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch;
unsigned int start = dst;
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
- pbox->x2 > dev_priv->w ||
- pbox->y2 > dev_priv->h)
+ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
continue;
- BEGIN_LP_RING( 6 );
- OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
- OUT_RING( pitch | (0xCC << 16));
- OUT_RING( (h << 16) | (w * cpp));
+ BEGIN_LP_RING(6);
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+ OUT_RING(pitch | (0xCC << 16));
+ OUT_RING((h << 16) | (w * cpp));
if (dev_priv->current_page == 0)
- OUT_RING(dev_priv->front_offset + start);
+ OUT_RING(dev_priv->front_offset + start);
else
- OUT_RING(dev_priv->back_offset + start);
- OUT_RING( pitch );
+ OUT_RING(dev_priv->back_offset + start);
+ OUT_RING(pitch);
if (dev_priv->current_page == 0)
- OUT_RING(dev_priv->back_offset + start);
+ OUT_RING(dev_priv->back_offset + start);
else
- OUT_RING(dev_priv->front_offset + start);
+ OUT_RING(dev_priv->front_offset + start);
ADVANCE_LP_RING();
}
}
-
-static void i810_dma_dispatch_vertex(drm_device_t *dev,
- drm_buf_t *buf,
- int discard,
- int used)
+static void i810_dma_dispatch_vertex(drm_device_t * dev,
+ drm_buf_t * buf, int discard, int used)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_clip_rect_t *box = sarea_priv->boxes;
- int nbox = sarea_priv->nbox;
+ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_clip_rect_t *box = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
unsigned long address = (unsigned long)buf->bus_address;
unsigned long start = address - dev->agp->base;
int i = 0;
- RING_LOCALS;
+ RING_LOCALS;
- i810_kernel_lost_context(dev);
+ i810_kernel_lost_context(dev);
- if (nbox > I810_NR_SAREA_CLIPRECTS)
+ if (nbox > I810_NR_SAREA_CLIPRECTS)
nbox = I810_NR_SAREA_CLIPRECTS;
- if (used > 4*1024)
+ if (used > 4 * 1024)
used = 0;
if (sarea_priv->dirty)
- i810EmitState( dev );
+ i810EmitState(dev);
if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
- *(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2)));
+ *(u32 *) buf_priv->kernel_virtual =
+ ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
if (used & 4) {
- *(u32 *)((u32)buf_priv->kernel_virtual + used) = 0;
+ *(u32 *) ((u32) buf_priv->kernel_virtual + used) = 0;
used += 4;
}
@@ -838,19 +820,20 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
do {
if (i < nbox) {
BEGIN_LP_RING(4);
- OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
- SC_ENABLE );
- OUT_RING( GFX_OP_SCISSOR_INFO );
- OUT_RING( box[i].x1 | (box[i].y1<<16) );
- OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
+ OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
+ SC_ENABLE);
+ OUT_RING(GFX_OP_SCISSOR_INFO);
+ OUT_RING(box[i].x1 | (box[i].y1 << 16));
+ OUT_RING((box[i].x2 -
+ 1) | ((box[i].y2 - 1) << 16));
ADVANCE_LP_RING();
}
BEGIN_LP_RING(4);
- OUT_RING( CMD_OP_BATCH_BUFFER );
- OUT_RING( start | BB1_PROTECTED );
- OUT_RING( start + used - 4 );
- OUT_RING( 0 );
+ OUT_RING(CMD_OP_BATCH_BUFFER);
+ OUT_RING(start | BB1_PROTECTED);
+ OUT_RING(start + used - 4);
+ OUT_RING(0);
ADVANCE_LP_RING();
} while (++i < nbox);
@@ -859,59 +842,59 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
if (discard) {
dev_priv->counter++;
- (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
- I810_BUF_HARDWARE);
+ (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+ I810_BUF_HARDWARE);
BEGIN_LP_RING(8);
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( 20 );
- OUT_RING( dev_priv->counter );
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( buf_priv->my_use_idx );
- OUT_RING( I810_BUF_FREE );
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(20);
+ OUT_RING(dev_priv->counter);
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(buf_priv->my_use_idx);
+ OUT_RING(I810_BUF_FREE);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
}
-static void i810_dma_dispatch_flip( drm_device_t *dev )
+static void i810_dma_dispatch_flip(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
int pitch = dev_priv->pitch;
RING_LOCALS;
- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
- __FUNCTION__,
- dev_priv->current_page,
- dev_priv->sarea_priv->pf_current_page);
-
- i810_kernel_lost_context(dev);
+ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page,
+ dev_priv->sarea_priv->pf_current_page);
- BEGIN_LP_RING( 2 );
- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
- OUT_RING( 0 );
+ i810_kernel_lost_context(dev);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0);
ADVANCE_LP_RING();
- BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+ BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
/* On i815 at least ASYNC is buggy */
/* pitch<<5 is from 11.2.8 p158,
its the pitch / 8 then left shifted 8,
so (pitch >> 3) << 8 */
- OUT_RING( CMD_OP_FRONTBUFFER_INFO | (pitch<<5) /*| ASYNC_FLIP */ );
- if ( dev_priv->current_page == 0 ) {
- OUT_RING( dev_priv->back_offset );
+ OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ );
+ if (dev_priv->current_page == 0) {
+ OUT_RING(dev_priv->back_offset);
dev_priv->current_page = 1;
} else {
- OUT_RING( dev_priv->front_offset );
+ OUT_RING(dev_priv->front_offset);
dev_priv->current_page = 0;
}
OUT_RING(0);
ADVANCE_LP_RING();
BEGIN_LP_RING(2);
- OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );
- OUT_RING( 0 );
+ OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP);
+ OUT_RING(0);
ADVANCE_LP_RING();
/* Increment the frame counter. The client-side 3D driver must
@@ -922,46 +905,46 @@ static void i810_dma_dispatch_flip( drm_device_t *dev )
}
-static void i810_dma_quiescent(drm_device_t *dev)
+static void i810_dma_quiescent(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
- RING_LOCALS;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
/* printk("%s\n", __FUNCTION__); */
- i810_kernel_lost_context(dev);
+ i810_kernel_lost_context(dev);
- BEGIN_LP_RING(4);
- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
- OUT_RING( 0 );
- ADVANCE_LP_RING();
+ BEGIN_LP_RING(4);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
- i810_wait_ring( dev, dev_priv->ring.Size - 8 );
+ i810_wait_ring(dev, dev_priv->ring.Size - 8);
}
-static int i810_flush_queue(drm_device_t *dev)
+static int i810_flush_queue(drm_device_t * dev)
{
- drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
drm_device_dma_t *dma = dev->dma;
- int i, ret = 0;
- RING_LOCALS;
-
+ int i, ret = 0;
+ RING_LOCALS;
+
/* printk("%s\n", __FUNCTION__); */
- i810_kernel_lost_context(dev);
+ i810_kernel_lost_context(dev);
- BEGIN_LP_RING(2);
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
- ADVANCE_LP_RING();
+ BEGIN_LP_RING(2);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
- i810_wait_ring( dev, dev_priv->ring.Size - 8 );
+ i810_wait_ring(dev, dev_priv->ring.Size - 8);
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
I810_BUF_FREE);
@@ -972,24 +955,27 @@ static int i810_flush_queue(drm_device_t *dev)
DRM_DEBUG("still on client\n");
}
- return ret;
+ return ret;
}
/* Must be called with the lock held */
-void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
+void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
{
drm_device_dma_t *dma = dev->dma;
- int i;
+ int i;
- if (!dma) return;
- if (!dev->dev_private) return;
- if (!dma->buflist) return;
+ if (!dma)
+ return;
+ if (!dev->dev_private)
+ return;
+ if (!dma->buflist)
+ return;
- i810_flush_queue(dev);
+ i810_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
if (buf->filp == filp && buf_priv) {
int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
@@ -998,7 +984,7 @@ void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
if (used == I810_BUF_CLIENT)
DRM_DEBUG("reclaimed from client\n");
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
- buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
}
}
}
@@ -1006,29 +992,29 @@ void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
static int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
- i810_flush_queue(dev);
- return 0;
+ i810_flush_queue(dev);
+ return 0;
}
-
static int i810_dma_vertex(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
- dev_priv->sarea_priv;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
drm_i810_vertex_t vertex;
- if (copy_from_user(&vertex, (drm_i810_vertex_t __user *)arg, sizeof(vertex)))
+ if (copy_from_user
+ (&vertex, (drm_i810_vertex_t __user *) arg, sizeof(vertex)))
return -EFAULT;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1036,48 +1022,46 @@ static int i810_dma_vertex(struct inode *inode, struct file *filp,
DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
vertex.idx, vertex.used, vertex.discard);
- if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
return -EINVAL;
- i810_dma_dispatch_vertex( dev,
- dma->buflist[ vertex.idx ],
- vertex.discard, vertex.used );
+ i810_dma_dispatch_vertex(dev,
+ dma->buflist[vertex.idx],
+ vertex.discard, vertex.used);
- atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
+ atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
atomic_inc(&dev->counts[_DRM_STAT_DMA]);
- sarea_priv->last_enqueue = dev_priv->counter-1;
- sarea_priv->last_dispatch = (int) hw_status[5];
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
-
-
static int i810_clear_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_i810_clear_t clear;
- if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))
+ if (copy_from_user
+ (&clear, (drm_i810_clear_t __user *) arg, sizeof(clear)))
return -EFAULT;
LOCK_TEST_WITH_RETURN(dev, filp);
- /* GH: Someone's doing nasty things... */
- if (!dev->dev_private) {
- return -EINVAL;
- }
+ /* GH: Someone's doing nasty things... */
+ if (!dev->dev_private) {
+ return -EINVAL;
+ }
- i810_dma_dispatch_clear( dev, clear.flags,
- clear.clear_color,
- clear.clear_depth );
- return 0;
+ i810_dma_dispatch_clear(dev, clear.flags,
+ clear.clear_color, clear.clear_depth);
+ return 0;
}
static int i810_swap_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1086,37 +1070,37 @@ static int i810_swap_bufs(struct inode *inode, struct file *filp,
LOCK_TEST_WITH_RETURN(dev, filp);
- i810_dma_dispatch_swap( dev );
- return 0;
+ i810_dma_dispatch_swap(dev);
+ return 0;
}
static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
- dev_priv->sarea_priv;
-
- sarea_priv->last_dispatch = (int) hw_status[5];
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+
+ sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- int retcode = 0;
- drm_i810_dma_t d;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
- dev_priv->sarea_priv;
-
- if (copy_from_user(&d, (drm_i810_dma_t __user *)arg, sizeof(d)))
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ int retcode = 0;
+ drm_i810_dma_t d;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+
+ if (copy_from_user(&d, (drm_i810_dma_t __user *) arg, sizeof(d)))
return -EFAULT;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1128,29 +1112,29 @@ static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
- if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
+ if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
return -EFAULT;
- sarea_priv->last_dispatch = (int) hw_status[5];
+ sarea_priv->last_dispatch = (int)hw_status[5];
return retcode;
}
static int i810_copybuf(struct inode *inode,
- struct file *filp, unsigned int cmd, unsigned long arg)
+ struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
}
static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
}
-static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
- unsigned int last_render)
+static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
+ unsigned int last_render)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
@@ -1162,19 +1146,17 @@ static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
i810_kernel_lost_context(dev);
- u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
- I810_BUF_HARDWARE);
+ u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
if (u != I810_BUF_CLIENT) {
DRM_DEBUG("MC found buffer that isn't mine!\n");
}
- if (used > 4*1024)
+ if (used > 4 * 1024)
used = 0;
sarea_priv->dirty = 0x7f;
- DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
- address, used);
+ DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n", address, used);
dev_priv->counter++;
DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
@@ -1185,46 +1167,45 @@ static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
if (used & 4) {
- *(u32 *)((u32)buf_priv->virtual + used) = 0;
+ *(u32 *) ((u32) buf_priv->virtual + used) = 0;
used += 4;
}
i810_unmap_buffer(buf);
}
BEGIN_LP_RING(4);
- OUT_RING( CMD_OP_BATCH_BUFFER );
- OUT_RING( start | BB1_PROTECTED );
- OUT_RING( start + used - 4 );
- OUT_RING( 0 );
+ OUT_RING(CMD_OP_BATCH_BUFFER);
+ OUT_RING(start | BB1_PROTECTED);
+ OUT_RING(start + used - 4);
+ OUT_RING(0);
ADVANCE_LP_RING();
-
BEGIN_LP_RING(8);
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( buf_priv->my_use_idx );
- OUT_RING( I810_BUF_FREE );
- OUT_RING( 0 );
-
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( 16 );
- OUT_RING( last_render );
- OUT_RING( 0 );
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(buf_priv->my_use_idx);
+ OUT_RING(I810_BUF_FREE);
+ OUT_RING(0);
+
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(16);
+ OUT_RING(last_render);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
static int i810_dma_mc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
- dev_priv->sarea_priv;
+ dev_priv->sarea_priv;
drm_i810_mc_t mc;
- if (copy_from_user(&mc, (drm_i810_mc_t __user *)arg, sizeof(mc)))
+ if (copy_from_user(&mc, (drm_i810_mc_t __user *) arg, sizeof(mc)))
return -EFAULT;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1233,12 +1214,12 @@ static int i810_dma_mc(struct inode *inode, struct file *filp,
return -EINVAL;
i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
- mc.last_render );
+ mc.last_render);
atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
atomic_inc(&dev->counts[_DRM_STAT_DMA]);
- sarea_priv->last_enqueue = dev_priv->counter-1;
- sarea_priv->last_dispatch = (int) hw_status[5];
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
@@ -1248,22 +1229,23 @@ static int i810_rstatus(struct inode *inode, struct file *filp,
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
- return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
+ return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
}
static int i810_ov0_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
drm_i810_overlay_t data;
data.offset = dev_priv->overlay_offset;
data.physical = dev_priv->overlay_physical;
- if (copy_to_user((drm_i810_overlay_t __user *)arg,&data,sizeof(data)))
+ if (copy_to_user
+ ((drm_i810_overlay_t __user *) arg, &data, sizeof(data)))
return -EFAULT;
return 0;
}
@@ -1273,7 +1255,7 @@ static int i810_fstatus(struct inode *inode, struct file *filp,
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1281,47 +1263,46 @@ static int i810_fstatus(struct inode *inode, struct file *filp,
}
static int i810_ov0_flip(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
//Tell the overlay to update
- I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
+ I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
return 0;
}
-
/* Not sure why this isn't set all the time:
- */
-static void i810_do_init_pageflip( drm_device_t *dev )
+ */
+static void i810_do_init_pageflip(drm_device_t * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
-
+
DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv->page_flipping = 1;
dev_priv->current_page = 0;
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static int i810_do_cleanup_pageflip( drm_device_t *dev )
+static int i810_do_cleanup_pageflip(drm_device_t * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
if (dev_priv->current_page != 0)
- i810_dma_dispatch_flip( dev );
+ i810_dma_dispatch_flip(dev);
dev_priv->page_flipping = 0;
return 0;
}
static int i810_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1331,19 +1312,19 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp,
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv->page_flipping)
- i810_do_init_pageflip( dev );
+ if (!dev_priv->page_flipping)
+ i810_do_init_pageflip(dev);
- i810_dma_dispatch_flip( dev );
- return 0;
+ i810_dma_dispatch_flip(dev);
+ return 0;
}
-void i810_driver_pretakedown(drm_device_t *dev)
+void i810_driver_pretakedown(drm_device_t * dev)
{
- i810_dma_cleanup( dev );
+ i810_dma_cleanup(dev);
}
-void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1353,33 +1334,49 @@ void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
}
}
-void i810_driver_release(drm_device_t *dev, struct file *filp)
+void i810_driver_release(drm_device_t * dev, struct file *filp)
{
i810_reclaim_buffers(dev, filp);
}
-int i810_driver_dma_quiescent(drm_device_t *dev)
+int i810_driver_dma_quiescent(drm_device_t * dev)
{
- i810_dma_quiescent( dev );
+ i810_dma_quiescent(dev);
return 0;
}
drm_ioctl_desc_t i810_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I810_INIT)] = { i810_dma_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_CLEAR)] = { i810_clear_bufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_FLUSH)] = { i810_flush_ioctl, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_GETAGE)] = { i810_getage, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_GETBUF)] = { i810_getbuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_SWAP)] = { i810_swap_bufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_COPY)] = { i810_copybuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = { i810_docopy, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = { i810_ov0_info, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = { i810_fstatus, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_MC)] = { i810_dma_mc, 1, 1 },
- [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = { i810_rstatus, 1, 0 },
- [DRM_IOCTL_NR(DRM_I810_FLIP)] = { i810_flip_bufs, 1, 0 }
+ [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, 1, 1},
+ [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, 1, 0},
+ [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, 1, 0}
};
int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i810 is AGP.
+ */
+int i810_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
index 73ac40563b1d..2deb925a94f3 100644
--- a/drivers/char/drm/i810_drm.h
+++ b/drivers/char/drm/i810_drm.h
@@ -19,21 +19,20 @@
#define I810_LOG_MIN_TEX_REGION_SIZE 16
#endif
-#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
-#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
#define I810_UPLOAD_CTX 0x4
#define I810_UPLOAD_BUFFERS 0x8
#define I810_UPLOAD_TEX0 0x10
#define I810_UPLOAD_TEX1 0x20
#define I810_UPLOAD_CLIPRECTS 0x40
-
/* Indices into buf.Setup where various bits of state are mirrored per
* context and per buffer. These can be fired at the card as a unit,
* or in a piecewise fashion as required.
*/
-/* Destbuffer state
+/* Destbuffer state
* - backbuffer linear offset and pitch -- invarient in the current dri
* - zbuffer linear offset and pitch -- also invarient
* - drawing origin in back and depth buffers.
@@ -55,13 +54,13 @@
/* Context state
*/
#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
-#define I810_CTXREG_CF1 1
-#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+#define I810_CTXREG_CF1 1
+#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
#define I810_CTXREG_ST1 3
#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
-#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
@@ -74,14 +73,14 @@
#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
-#define I810_CTX_SETUP_SIZE 20
+#define I810_CTX_SETUP_SIZE 20
/* Texture state (per tex unit)
*/
#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
-#define I810_TEXREG_MI1 1
-#define I810_TEXREG_MI2 2
-#define I810_TEXREG_MI3 3
+#define I810_TEXREG_MI1 1
+#define I810_TEXREG_MI2 2
+#define I810_TEXREG_MI3 3
#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
@@ -98,7 +97,7 @@ typedef enum _drm_i810_init_func {
I810_INIT_DMA = 0x01,
I810_CLEANUP_DMA = 0x02,
I810_INIT_DMA_1_4 = 0x03
- } drm_i810_init_func_t;
+} drm_i810_init_func_t;
/* This is the init structure after v1.2 */
typedef struct _drm_i810_init {
@@ -122,7 +121,7 @@ typedef struct _drm_i810_init {
unsigned int w;
unsigned int h;
unsigned int pitch;
- unsigned int pitch_bits;
+ unsigned int pitch_bits;
} drm_i810_init_t;
/* This is the init structure prior to v1.2 */
@@ -140,23 +139,23 @@ typedef struct _drm_i810_pre12_init {
unsigned int w;
unsigned int h;
unsigned int pitch;
- unsigned int pitch_bits;
+ unsigned int pitch_bits;
} drm_i810_pre12_init_t;
/* Warning: If you change the SAREA structure you must change the Xserver
* structure as well */
typedef struct _drm_i810_tex_region {
- unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char next, prev; /* indices to form a circular LRU */
unsigned char in_use; /* owned by a client, or free? */
int age; /* tracked by clients to update local LRU's */
} drm_i810_tex_region_t;
typedef struct _drm_i810_sarea {
- unsigned int ContextState[I810_CTX_SETUP_SIZE];
- unsigned int BufferState[I810_DEST_SETUP_SIZE];
- unsigned int TexState[2][I810_TEX_SETUP_SIZE];
- unsigned int dirty;
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
unsigned int nbox;
drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
@@ -174,22 +173,22 @@ typedef struct _drm_i810_sarea {
* texture space, and can make informed decisions as to which
* areas to kick out. There is no need to choose whether to
* kick out your own texture or someone else's - simply eject
- * them all in LRU order.
+ * them all in LRU order.
*/
-
- drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
- /* Last elt is sentinal */
- int texAge; /* last time texture was uploaded */
- int last_enqueue; /* last time a buffer was enqueued */
+
+ drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS + 1];
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+ int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
- int last_quiescent; /* */
+ int last_quiescent; /* */
int ctxOwner; /* last context to upload state */
int vertex_prim;
- int pf_enabled; /* is pageflipping allowed? */
+ int pf_enabled; /* is pageflipping allowed? */
int pf_active;
- int pf_current_page; /* which buffer is being displayed? */
+ int pf_current_page; /* which buffer is being displayed? */
} drm_i810_sarea_t;
/* WARNING: If you change any of these defines, make sure to change the
@@ -243,13 +242,13 @@ typedef struct _drm_i810_clear {
* new set of cliprects.
*/
typedef struct _drm_i810_vertex {
- int idx; /* buffer index */
+ int idx; /* buffer index */
int used; /* nr bytes in use */
int discard; /* client is finished with the buffer? */
} drm_i810_vertex_t;
typedef struct _drm_i810_copy_t {
- int idx; /* buffer index */
+ int idx; /* buffer index */
int used; /* nr bytes in use */
void *address; /* Address to copy from */
} drm_i810_copy_t;
@@ -264,7 +263,6 @@ typedef struct _drm_i810_copy_t {
#define PR_RECTS (0x7<<18)
#define PR_MASK (0x7<<18)
-
typedef struct drm_i810_dma {
void *virtual;
int request_idx;
@@ -273,17 +271,16 @@ typedef struct drm_i810_dma {
} drm_i810_dma_t;
typedef struct _drm_i810_overlay_t {
- unsigned int offset; /* Address of the Overlay Regs */
+ unsigned int offset; /* Address of the Overlay Regs */
unsigned int physical;
} drm_i810_overlay_t;
typedef struct _drm_i810_mc {
- int idx; /* buffer index */
- int used; /* nr bytes in use */
- int num_blocks; /* number of GFXBlocks */
- int *length; /* List of lengths for GFXBlocks (FUTURE)*/
- unsigned int last_render; /* Last Render Request */
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int num_blocks; /* number of GFXBlocks */
+ int *length; /* List of lengths for GFXBlocks (FUTURE) */
+ unsigned int last_render; /* Last Render Request */
} drm_i810_mc_t;
-
-#endif /* _I810_DRM_H_ */
+#endif /* _I810_DRM_H_ */
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
index ff51b3259af9..070cef6c2b46 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -38,7 +38,7 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
/* i810 has 4 more counters */
dev->counters += 4;
@@ -46,29 +46,27 @@ static int postinit( struct drm_device *dev, unsigned long flags )
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
-
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -76,14 +74,14 @@ static struct pci_device_id pciidlist[] = {
i810_PCI_IDS
};
-extern drm_ioctl_desc_t i810_ioctls[];
-extern int i810_max_ioctl;
-
static struct drm_driver driver = {
- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
.dev_priv_size = sizeof(drm_i810_buf_priv_t),
.pretakedown = i810_driver_pretakedown,
.prerelease = i810_driver_prerelease,
+ .device_is_agp = i810_driver_device_is_agp,
.release = i810_driver_release,
.dma_quiescent = i810_driver_dma_quiescent,
.reclaim_buffers = i810_reclaim_buffers,
@@ -93,18 +91,20 @@ static struct drm_driver driver = {
.version = version,
.ioctls = i810_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,
+ }
+ ,
};
static int __init i810_init(void)
@@ -121,6 +121,6 @@ static void __exit i810_exit(void)
module_init(i810_init);
module_exit(i810_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index 1b40538d1725..c78f36aaa2f0 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -56,14 +56,14 @@
#define DRIVER_PATCHLEVEL 0
typedef struct drm_i810_buf_priv {
- u32 *in_use;
- int my_use_idx;
+ u32 *in_use;
+ int my_use_idx;
int currently_mapped;
void *virtual;
void *kernel_virtual;
} drm_i810_buf_priv_t;
-typedef struct _drm_i810_ring_buffer{
+typedef struct _drm_i810_ring_buffer {
int tail_mask;
unsigned long Start;
unsigned long End;
@@ -79,16 +79,15 @@ typedef struct drm_i810_private {
drm_map_t *mmio_map;
drm_i810_sarea_t *sarea_priv;
- drm_i810_ring_buffer_t ring;
+ drm_i810_ring_buffer_t ring;
- void *hw_status_page;
- unsigned long counter;
+ void *hw_status_page;
+ unsigned long counter;
dma_addr_t dma_status_page;
drm_buf_t *mmap_buffer;
-
u32 front_di1, back_di1, zi1;
int back_offset;
@@ -97,7 +96,7 @@ typedef struct drm_i810_private {
int overlay_physical;
int w, h;
int pitch;
- int back_pitch;
+ int back_pitch;
int depth_pitch;
int do_boxes;
@@ -107,19 +106,23 @@ typedef struct drm_i810_private {
int page_flipping;
wait_queue_head_t irq_queue;
- atomic_t irq_received;
- atomic_t irq_emitted;
-
- int front_offset;
+ atomic_t irq_received;
+ atomic_t irq_emitted;
+
+ int front_offset;
} drm_i810_private_t;
/* i810_dma.c */
-extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
+extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
-extern int i810_driver_dma_quiescent(drm_device_t *dev);
-extern void i810_driver_release(drm_device_t *dev, struct file *filp);
-extern void i810_driver_pretakedown(drm_device_t *dev);
-extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i810_driver_dma_quiescent(drm_device_t * dev);
+extern void i810_driver_release(drm_device_t * dev, struct file *filp);
+extern void i810_driver_pretakedown(drm_device_t * dev);
+extern void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+extern int i810_driver_device_is_agp(drm_device_t * dev);
+
+extern drm_ioctl_desc_t i810_ioctls[];
+extern int i810_max_ioctl;
#define I810_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
@@ -169,7 +172,6 @@ extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
#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)
@@ -228,8 +230,8 @@ extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
#define BR00_OP_SRC_COPY_BLT 0x10C00000
#define BR13_SOLID_PATTERN 0x80000000
-#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-#define WAIT_FOR_PLANE_A_FLIP (1<<2)
+#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define WAIT_FOR_PLANE_A_FLIP (1<<2)
#define WAIT_FOR_VBLANK (1<<3)
#endif
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index dc7733035864..dc94f1914425 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -11,11 +11,11 @@
* 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
@@ -47,108 +47,104 @@
#define I830_BUF_UNMAPPED 0
#define I830_BUF_MAPPED 1
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
-static drm_buf_t *i830_freelist_get(drm_device_t *dev)
+static drm_buf_t *i830_freelist_get(drm_device_t * dev)
{
- drm_device_dma_t *dma = dev->dma;
- int i;
- int used;
-
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+ int used;
+
/* Linear search might not be the best solution */
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
- used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
+ used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
I830_BUF_CLIENT);
- if(used == I830_BUF_FREE) {
+ if (used == I830_BUF_FREE) {
return buf;
}
}
- return NULL;
+ return NULL;
}
/* This should only be called if the buffer is not sent to the hardware
* yet, the hardware updates in use for us once its on the ring buffer.
*/
-static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+static int i830_freelist_put(drm_device_t * dev, drm_buf_t * buf)
{
- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- int used;
-
- /* In use is already a pointer */
- used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
- if(used != I830_BUF_CLIENT) {
- DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
- return -EINVAL;
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ int used;
+
+ /* In use is already a pointer */
+ used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
+ if (used != I830_BUF_CLIENT) {
+ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+ return -EINVAL;
}
-
- return 0;
+
+ return 0;
}
static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
- drm_i830_private_t *dev_priv;
- drm_buf_t *buf;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+ drm_i830_private_t *dev_priv;
+ drm_buf_t *buf;
drm_i830_buf_priv_t *buf_priv;
lock_kernel();
- dev = priv->head->dev;
+ dev = priv->head->dev;
dev_priv = dev->dev_private;
- buf = dev_priv->mmap_buffer;
+ buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
-
+
vma->vm_flags |= (VM_IO | VM_DONTCOPY);
vma->vm_file = filp;
-
- buf_priv->currently_mapped = I830_BUF_MAPPED;
+
+ buf_priv->currently_mapped = I830_BUF_MAPPED;
unlock_kernel();
if (io_remap_pfn_range(vma, vma->vm_start,
- VM_OFFSET(vma) >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot)) return -EAGAIN;
+ VM_OFFSET(vma) >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
return 0;
}
static struct file_operations i830_buffer_fops = {
- .open = drm_open,
- .flush = drm_flush,
+ .open = drm_open,
+ .flush = drm_flush,
.release = drm_release,
- .ioctl = drm_ioctl,
- .mmap = i830_mmap_buffers,
- .fasync = drm_fasync,
+ .ioctl = drm_ioctl,
+ .mmap = i830_mmap_buffers,
+ .fasync = drm_fasync,
};
-static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
+static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- drm_i830_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ struct file_operations *old_fops;
unsigned long virtual;
int retcode = 0;
- if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
+ if (buf_priv->currently_mapped == I830_BUF_MAPPED)
+ return -EINVAL;
- down_write( &current->mm->mmap_sem );
+ down_write(&current->mm->mmap_sem);
old_fops = filp->f_op;
filp->f_op = &i830_buffer_fops;
dev_priv->mmap_buffer = buf;
- virtual = do_mmap(filp, 0, buf->total, PROT_READ|PROT_WRITE,
- MAP_SHARED, buf->bus_address);
+ virtual = do_mmap(filp, 0, buf->total, PROT_READ | PROT_WRITE,
+ MAP_SHARED, buf->bus_address);
dev_priv->mmap_buffer = NULL;
filp->f_op = old_fops;
- if (IS_ERR((void *)virtual)) { /* ugh */
+ if (IS_ERR((void *)virtual)) { /* ugh */
/* Real error */
DRM_ERROR("mmap error\n");
retcode = virtual;
@@ -156,17 +152,17 @@ static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
} else {
buf_priv->virtual = (void __user *)virtual;
}
- up_write( &current->mm->mmap_sem );
+ up_write(&current->mm->mmap_sem);
return retcode;
}
-static int i830_unmap_buffer(drm_buf_t *buf)
+static int i830_unmap_buffer(drm_buf_t * buf)
{
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
int retcode = 0;
- if(buf_priv->currently_mapped != I830_BUF_MAPPED)
+ if (buf_priv->currently_mapped != I830_BUF_MAPPED)
return -EINVAL;
down_write(&current->mm->mmap_sem);
@@ -175,43 +171,43 @@ static int i830_unmap_buffer(drm_buf_t *buf)
(size_t) buf->total);
up_write(&current->mm->mmap_sem);
- buf_priv->currently_mapped = I830_BUF_UNMAPPED;
- buf_priv->virtual = NULL;
+ buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+ buf_priv->virtual = NULL;
return retcode;
}
-static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
+static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
struct file *filp)
{
- drm_buf_t *buf;
+ drm_buf_t *buf;
drm_i830_buf_priv_t *buf_priv;
int retcode = 0;
buf = i830_freelist_get(dev);
if (!buf) {
retcode = -ENOMEM;
- DRM_DEBUG("retcode=%d\n", retcode);
+ DRM_DEBUG("retcode=%d\n", retcode);
return retcode;
}
-
+
retcode = i830_map_buffer(buf, filp);
- if(retcode) {
+ if (retcode) {
i830_freelist_put(dev, buf);
- DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+ DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
return retcode;
}
buf->filp = filp;
- buf_priv = buf->dev_private;
+ buf_priv = buf->dev_private;
d->granted = 1;
- d->request_idx = buf->idx;
- d->request_size = buf->total;
- d->virtual = buf_priv->virtual;
+ d->request_idx = buf->idx;
+ d->request_size = buf->total;
+ d->virtual = buf_priv->virtual;
return retcode;
}
-static int i830_dma_cleanup(drm_device_t *dev)
+static int i830_dma_cleanup(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -219,147 +215,152 @@ static int i830_dma_cleanup(drm_device_t *dev)
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
if (dev->dev_private) {
int i;
- drm_i830_private_t *dev_priv =
- (drm_i830_private_t *) dev->dev_private;
-
- if (dev_priv->ring.virtual_start) {
- drm_ioremapfree((void *) dev_priv->ring.virtual_start,
- dev_priv->ring.Size, dev);
+ drm_i830_private_t *dev_priv =
+ (drm_i830_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start) {
+ drm_ioremapfree((void *)dev_priv->ring.virtual_start,
+ dev_priv->ring.Size, dev);
}
- if (dev_priv->hw_status_page) {
+ if (dev_priv->hw_status_page) {
pci_free_consistent(dev->pdev, PAGE_SIZE,
dev_priv->hw_status_page,
dev_priv->dma_status_page);
- /* Need to rewrite hardware status page */
- I830_WRITE(0x02080, 0x1ffff000);
+ /* Need to rewrite hardware status page */
+ I830_WRITE(0x02080, 0x1ffff000);
}
- drm_free(dev->dev_private, sizeof(drm_i830_private_t),
+ drm_free(dev->dev_private, sizeof(drm_i830_private_t),
DRM_MEM_DRIVER);
- dev->dev_private = NULL;
+ dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
+ drm_buf_t *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- if ( buf_priv->kernel_virtual && buf->total )
- drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
+ if (buf_priv->kernel_virtual && buf->total)
+ drm_ioremapfree(buf_priv->kernel_virtual,
+ buf->total, dev);
}
}
- return 0;
+ return 0;
}
-int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
+int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
- int iters = 0;
- unsigned long end;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+ int iters = 0;
+ unsigned long end;
unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- end = jiffies + (HZ*3);
- while (ring->space < n) {
- ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- ring->space = ring->head - (ring->tail+8);
- if (ring->space < 0) ring->space += ring->Size;
-
+ end = jiffies + (HZ * 3);
+ while (ring->space < n) {
+ ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->Size;
+
if (ring->head != last_head) {
- end = jiffies + (HZ*3);
+ end = jiffies + (HZ * 3);
last_head = ring->head;
}
-
- iters++;
- if(time_before(end, jiffies)) {
- DRM_ERROR("space: %d wanted %d\n", ring->space, n);
- DRM_ERROR("lockup\n");
- goto out_wait_ring;
+
+ iters++;
+ if (time_before(end, jiffies)) {
+ DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+ DRM_ERROR("lockup\n");
+ goto out_wait_ring;
}
udelay(1);
dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
}
-out_wait_ring:
- return iters;
+ out_wait_ring:
+ return iters;
}
-static void i830_kernel_lost_context(drm_device_t *dev)
+static void i830_kernel_lost_context(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-
- ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
- ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
- ring->space = ring->head - (ring->tail+8);
- if (ring->space < 0) ring->space += ring->Size;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+
+ ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+ ring->space = ring->head - (ring->tail + 8);
+ if (ring->space < 0)
+ ring->space += ring->Size;
if (ring->head == ring->tail)
dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
}
-static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
+static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
{
- drm_device_dma_t *dma = dev->dma;
- int my_idx = 36;
- u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
- int i;
-
- if(dma->buf_count > 1019) {
- /* Not enough space in the status page for the freelist */
- return -EINVAL;
+ drm_device_dma_t *dma = dev->dma;
+ int my_idx = 36;
+ u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
+ int i;
+
+ if (dma->buf_count > 1019) {
+ /* Not enough space in the status page for the freelist */
+ return -EINVAL;
}
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- buf_priv->in_use = hw_status++;
- buf_priv->my_use_idx = my_idx;
- my_idx += 4;
+ buf_priv->in_use = hw_status++;
+ buf_priv->my_use_idx = my_idx;
+ my_idx += 4;
- *buf_priv->in_use = I830_BUF_FREE;
+ *buf_priv->in_use = I830_BUF_FREE;
- buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
- buf->total, dev);
+ buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
+ buf->total, dev);
}
return 0;
}
-static int i830_dma_initialize(drm_device_t *dev,
- drm_i830_private_t *dev_priv,
- drm_i830_init_t *init)
+static int i830_dma_initialize(drm_device_t * dev,
+ drm_i830_private_t * dev_priv,
+ drm_i830_init_t * init)
{
struct list_head *list;
- memset(dev_priv, 0, sizeof(drm_i830_private_t));
+ memset(dev_priv, 0, sizeof(drm_i830_private_t));
list_for_each(list, &dev->maplist->head) {
drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
- if( r_list->map &&
+ if (r_list->map &&
r_list->map->type == _DRM_SHM &&
- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+ r_list->map->flags & _DRM_CONTAINS_LOCK) {
dev_priv->sarea_map = r_list->map;
- break;
- }
- }
+ break;
+ }
+ }
- if(!dev_priv->sarea_map) {
+ if (!dev_priv->sarea_map) {
dev->dev_private = (void *)dev_priv;
i830_dma_cleanup(dev);
DRM_ERROR("can not find sarea!\n");
return -EINVAL;
}
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
- if(!dev_priv->mmio_map) {
+ if (!dev_priv->mmio_map) {
dev->dev_private = (void *)dev_priv;
i830_dma_cleanup(dev);
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- if(!dev->agp_buffer_map) {
+ if (!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
i830_dma_cleanup(dev);
DRM_ERROR("can not find dma buffer map!\n");
@@ -367,27 +368,26 @@ static int i830_dma_initialize(drm_device_t *dev,
}
dev_priv->sarea_priv = (drm_i830_sarea_t *)
- ((u8 *)dev_priv->sarea_map->handle +
- init->sarea_priv_offset);
+ ((u8 *) dev_priv->sarea_map->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.Start = init->ring_start;
+ dev_priv->ring.End = init->ring_end;
+ dev_priv->ring.Size = init->ring_size;
- dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
- init->ring_start,
- init->ring_size, dev);
+ dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
+ init->ring_start,
+ init->ring_size, dev);
- if (dev_priv->ring.virtual_start == NULL) {
- dev->dev_private = (void *) dev_priv;
- i830_dma_cleanup(dev);
- DRM_ERROR("can not ioremap virtual address for"
+ if (dev_priv->ring.virtual_start == NULL) {
+ dev->dev_private = (void *)dev_priv;
+ i830_dma_cleanup(dev);
+ DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
- return -ENOMEM;
+ return -ENOMEM;
}
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
dev_priv->w = init->w;
dev_priv->h = init->h;
dev_priv->pitch = init->pitch;
@@ -399,10 +399,10 @@ static int i830_dma_initialize(drm_device_t *dev,
dev_priv->back_di1 = init->back_offset | init->pitch_bits;
dev_priv->zi1 = init->depth_offset | init->pitch_bits;
- DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
+ DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
- DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
- DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
+ DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
+ DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
dev_priv->cpp = init->cpp;
/* We are using separate values as placeholders for mechanisms for
@@ -414,63 +414,64 @@ static int i830_dma_initialize(drm_device_t *dev,
dev_priv->do_boxes = 0;
dev_priv->use_mi_batchbuffer_start = 0;
- /* Program Hardware Status Page */
- dev_priv->hw_status_page =
- pci_alloc_consistent(dev->pdev, PAGE_SIZE,
- &dev_priv->dma_status_page);
- if (!dev_priv->hw_status_page) {
+ /* Program Hardware Status Page */
+ dev_priv->hw_status_page =
+ pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+ &dev_priv->dma_status_page);
+ if (!dev_priv->hw_status_page) {
dev->dev_private = (void *)dev_priv;
i830_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
- I830_WRITE(0x02080, dev_priv->dma_status_page);
+
+ I830_WRITE(0x02080, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
-
- /* Now we need to init our freelist */
- if(i830_freelist_init(dev, dev_priv) != 0) {
+
+ /* Now we need to init our freelist */
+ if (i830_freelist_init(dev, dev_priv) != 0) {
dev->dev_private = (void *)dev_priv;
- i830_dma_cleanup(dev);
- DRM_ERROR("Not enough space in the status page for"
+ i830_dma_cleanup(dev);
+ DRM_ERROR("Not enough space in the status page for"
" the freelist\n");
- return -ENOMEM;
+ return -ENOMEM;
}
dev->dev_private = (void *)dev_priv;
- return 0;
+ return 0;
}
static int i830_dma_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_i830_private_t *dev_priv;
- drm_i830_init_t init;
- int retcode = 0;
-
- if (copy_from_user(&init, (void * __user) arg, sizeof(init)))
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv;
+ drm_i830_init_t init;
+ int retcode = 0;
+
+ if (copy_from_user(&init, (void *__user)arg, sizeof(init)))
return -EFAULT;
-
- switch(init.func) {
- case I830_INIT_DMA:
- dev_priv = drm_alloc(sizeof(drm_i830_private_t),
- DRM_MEM_DRIVER);
- if(dev_priv == NULL) return -ENOMEM;
- retcode = i830_dma_initialize(dev, dev_priv, &init);
- break;
- case I830_CLEANUP_DMA:
- retcode = i830_dma_cleanup(dev);
- break;
- default:
- retcode = -EINVAL;
- break;
+
+ switch (init.func) {
+ case I830_INIT_DMA:
+ dev_priv = drm_alloc(sizeof(drm_i830_private_t),
+ DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+ retcode = i830_dma_initialize(dev, dev_priv, &init);
+ break;
+ case I830_CLEANUP_DMA:
+ retcode = i830_dma_cleanup(dev);
+ break;
+ default:
+ retcode = -EINVAL;
+ break;
}
-
- return retcode;
+
+ return retcode;
}
#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
@@ -480,92 +481,89 @@ static int i830_dma_init(struct inode *inode, struct file *filp,
/* Most efficient way to verify state for the i830 is as it is
* emitted. Non-conformant state is silently dropped.
*/
-static void i830EmitContextVerified( drm_device_t *dev,
- unsigned int *code )
+static void i830EmitContextVerified(drm_device_t * dev, unsigned int *code)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
+ BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
- for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
+ for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
tmp = code[i];
- if ((tmp & (7<<29)) == CMD_3D &&
- (tmp & (0x1f<<24)) < (0x1d<<24)) {
- OUT_RING( tmp );
+ if ((tmp & (7 << 29)) == CMD_3D &&
+ (tmp & (0x1f << 24)) < (0x1d << 24)) {
+ OUT_RING(tmp);
j++;
} else {
DRM_ERROR("Skipping %d\n", i);
}
}
- OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD );
- OUT_RING( code[I830_CTXREG_BLENDCOLR] );
+ OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
+ OUT_RING(code[I830_CTXREG_BLENDCOLR]);
j += 2;
- for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) {
+ for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
tmp = code[i];
- if ((tmp & (7<<29)) == CMD_3D &&
- (tmp & (0x1f<<24)) < (0x1d<<24)) {
- OUT_RING( tmp );
+ if ((tmp & (7 << 29)) == CMD_3D &&
+ (tmp & (0x1f << 24)) < (0x1d << 24)) {
+ OUT_RING(tmp);
j++;
} else {
DRM_ERROR("Skipping %d\n", i);
}
}
- OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD );
- OUT_RING( code[I830_CTXREG_MCSB1] );
+ OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
+ OUT_RING(code[I830_CTXREG_MCSB1]);
j += 2;
- if (j & 1)
- OUT_RING( 0 );
+ if (j & 1)
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code )
+static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
- (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) ==
- (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
-
- BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
-
- OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
- OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
- OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
- OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
- OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
- OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
-
- for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
+ (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
+ (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
+
+ BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
+
+ OUT_RING(code[I830_TEXREG_MI0]); /* TM0LI */
+ OUT_RING(code[I830_TEXREG_MI1]); /* TM0S0 */
+ OUT_RING(code[I830_TEXREG_MI2]); /* TM0S1 */
+ OUT_RING(code[I830_TEXREG_MI3]); /* TM0S2 */
+ OUT_RING(code[I830_TEXREG_MI4]); /* TM0S3 */
+ OUT_RING(code[I830_TEXREG_MI5]); /* TM0S4 */
+
+ for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
tmp = code[i];
- OUT_RING( tmp );
+ OUT_RING(tmp);
j++;
- }
+ }
- if (j & 1)
- OUT_RING( 0 );
+ if (j & 1)
+ OUT_RING(0);
ADVANCE_LP_RING();
- }
- else
+ } else
printk("rejected packet %x\n", code[0]);
}
-static void i830EmitTexBlendVerified( drm_device_t *dev,
- unsigned int *code,
- unsigned int num)
+static void i830EmitTexBlendVerified(drm_device_t * dev,
+ unsigned int *code, unsigned int num)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
@@ -573,59 +571,54 @@ static void i830EmitTexBlendVerified( drm_device_t *dev,
if (!num)
return;
- BEGIN_LP_RING( num + 1 );
+ BEGIN_LP_RING(num + 1);
- for ( i = 0 ; i < num ; i++ ) {
+ for (i = 0; i < num; i++) {
tmp = code[i];
- OUT_RING( tmp );
+ OUT_RING(tmp);
j++;
}
- if (j & 1)
- OUT_RING( 0 );
+ if (j & 1)
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-static void i830EmitTexPalette( drm_device_t *dev,
- unsigned int *palette,
- int number,
- int is_shared )
+static void i830EmitTexPalette(drm_device_t * dev,
+ unsigned int *palette, int number, int is_shared)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
int i;
RING_LOCALS;
return;
- BEGIN_LP_RING( 258 );
+ BEGIN_LP_RING(258);
- if(is_shared == 1) {
+ if (is_shared == 1) {
OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
- MAP_PALETTE_NUM(0) |
- MAP_PALETTE_BOTH);
+ MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
} else {
OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
}
- for(i = 0; i < 256; i++) {
+ for (i = 0; i < 256; i++) {
OUT_RING(palette[i]);
}
OUT_RING(0);
- /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
+ /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
*/
}
/* Need to do some additional checking when setting the dest buffer.
*/
-static void i830EmitDestVerified( drm_device_t *dev,
- unsigned int *code )
-{
- drm_i830_private_t *dev_priv = dev->dev_private;
+static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
+{
+ drm_i830_private_t *dev_priv = dev->dev_private;
unsigned int tmp;
RING_LOCALS;
- BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
-
+ BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
tmp = code[I830_DESTREG_CBUFADDR];
if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
@@ -634,18 +627,18 @@ static void i830EmitDestVerified( drm_device_t *dev,
OUT_RING(0);
}
- OUT_RING( CMD_OP_DESTBUFFER_INFO );
- OUT_RING( BUF_3D_ID_COLOR_BACK |
- BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
- BUF_3D_USE_FENCE);
- OUT_RING( tmp );
- OUT_RING( 0 );
-
- OUT_RING( CMD_OP_DESTBUFFER_INFO );
- OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
- BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
- OUT_RING( dev_priv->zi1 );
- OUT_RING( 0 );
+ OUT_RING(CMD_OP_DESTBUFFER_INFO);
+ OUT_RING(BUF_3D_ID_COLOR_BACK |
+ BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
+ BUF_3D_USE_FENCE);
+ OUT_RING(tmp);
+ OUT_RING(0);
+
+ OUT_RING(CMD_OP_DESTBUFFER_INFO);
+ OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
+ BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
+ OUT_RING(dev_priv->zi1);
+ OUT_RING(0);
} else {
DRM_ERROR("bad di1 %x (allow %x or %x)\n",
tmp, dev_priv->front_di1, dev_priv->back_di1);
@@ -654,83 +647,80 @@ static void i830EmitDestVerified( drm_device_t *dev,
/* invarient:
*/
+ OUT_RING(GFX_OP_DESTBUFFER_VARS);
+ OUT_RING(code[I830_DESTREG_DV1]);
- OUT_RING( GFX_OP_DESTBUFFER_VARS );
- OUT_RING( code[I830_DESTREG_DV1] );
-
- OUT_RING( GFX_OP_DRAWRECT_INFO );
- OUT_RING( code[I830_DESTREG_DR1] );
- OUT_RING( code[I830_DESTREG_DR2] );
- OUT_RING( code[I830_DESTREG_DR3] );
- OUT_RING( code[I830_DESTREG_DR4] );
+ OUT_RING(GFX_OP_DRAWRECT_INFO);
+ OUT_RING(code[I830_DESTREG_DR1]);
+ OUT_RING(code[I830_DESTREG_DR2]);
+ OUT_RING(code[I830_DESTREG_DR3]);
+ OUT_RING(code[I830_DESTREG_DR4]);
/* Need to verify this */
tmp = code[I830_DESTREG_SENABLE];
- if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
- OUT_RING( tmp );
+ if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
+ OUT_RING(tmp);
} else {
DRM_ERROR("bad scissor enable\n");
- OUT_RING( 0 );
+ OUT_RING(0);
}
- OUT_RING( GFX_OP_SCISSOR_RECT );
- OUT_RING( code[I830_DESTREG_SR1] );
- OUT_RING( code[I830_DESTREG_SR2] );
- OUT_RING( 0 );
+ OUT_RING(GFX_OP_SCISSOR_RECT);
+ OUT_RING(code[I830_DESTREG_SR1]);
+ OUT_RING(code[I830_DESTREG_SR2]);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
-static void i830EmitStippleVerified( drm_device_t *dev,
- unsigned int *code )
+static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- BEGIN_LP_RING( 2 );
- OUT_RING( GFX_OP_STIPPLE );
- OUT_RING( code[1] );
- ADVANCE_LP_RING();
+ BEGIN_LP_RING(2);
+ OUT_RING(GFX_OP_STIPPLE);
+ OUT_RING(code[1]);
+ ADVANCE_LP_RING();
}
-
-static void i830EmitState( drm_device_t *dev )
+static void i830EmitState(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
if (dirty & I830_UPLOAD_BUFFERS) {
- i830EmitDestVerified( dev, sarea_priv->BufferState );
+ i830EmitDestVerified(dev, sarea_priv->BufferState);
sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
}
if (dirty & I830_UPLOAD_CTX) {
- i830EmitContextVerified( dev, sarea_priv->ContextState );
+ i830EmitContextVerified(dev, sarea_priv->ContextState);
sarea_priv->dirty &= ~I830_UPLOAD_CTX;
}
if (dirty & I830_UPLOAD_TEX0) {
- i830EmitTexVerified( dev, sarea_priv->TexState[0] );
+ i830EmitTexVerified(dev, sarea_priv->TexState[0]);
sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
}
if (dirty & I830_UPLOAD_TEX1) {
- i830EmitTexVerified( dev, sarea_priv->TexState[1] );
+ i830EmitTexVerified(dev, sarea_priv->TexState[1]);
sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
}
if (dirty & I830_UPLOAD_TEXBLEND0) {
- i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
- sarea_priv->TexBlendStateWordsUsed[0]);
+ i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
+ sarea_priv->TexBlendStateWordsUsed[0]);
sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
}
if (dirty & I830_UPLOAD_TEXBLEND1) {
- i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
- sarea_priv->TexBlendStateWordsUsed[1]);
+ i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
+ sarea_priv->TexBlendStateWordsUsed[1]);
sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
}
@@ -763,36 +753,32 @@ static void i830EmitState( drm_device_t *dev )
/* 1.3:
*/
if (dirty & I830_UPLOAD_STIPPLE) {
- i830EmitStippleVerified( dev,
- sarea_priv->StippleState);
+ i830EmitStippleVerified(dev, sarea_priv->StippleState);
sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
}
if (dirty & I830_UPLOAD_TEX2) {
- i830EmitTexVerified( dev, sarea_priv->TexState2 );
+ i830EmitTexVerified(dev, sarea_priv->TexState2);
sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
}
if (dirty & I830_UPLOAD_TEX3) {
- i830EmitTexVerified( dev, sarea_priv->TexState3 );
+ i830EmitTexVerified(dev, sarea_priv->TexState3);
sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
}
-
if (dirty & I830_UPLOAD_TEXBLEND2) {
- i830EmitTexBlendVerified(
- dev,
- sarea_priv->TexBlendState2,
- sarea_priv->TexBlendStateWordsUsed2);
+ i830EmitTexBlendVerified(dev,
+ sarea_priv->TexBlendState2,
+ sarea_priv->TexBlendStateWordsUsed2);
sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
}
if (dirty & I830_UPLOAD_TEXBLEND3) {
- i830EmitTexBlendVerified(
- dev,
- sarea_priv->TexBlendState3,
- sarea_priv->TexBlendStateWordsUsed3);
+ i830EmitTexBlendVerified(dev,
+ sarea_priv->TexBlendState3,
+ sarea_priv->TexBlendStateWordsUsed3);
sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
}
}
@@ -801,97 +787,96 @@ static void i830EmitState( drm_device_t *dev )
* Performance monitoring functions
*/
-static void i830_fill_box( drm_device_t *dev,
- int x, int y, int w, int h,
- int r, int g, int b )
+static void i830_fill_box(drm_device_t * dev,
+ int x, int y, int w, int h, int r, int g, int b)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
u32 color;
unsigned int BR13, CMD;
RING_LOCALS;
- BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
+ BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
CMD = XY_COLOR_BLT_CMD;
x += dev_priv->sarea_priv->boxes[0].x1;
y += dev_priv->sarea_priv->boxes[0].y1;
if (dev_priv->cpp == 4) {
- BR13 |= (1<<25);
+ BR13 |= (1 << 25);
CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
} else {
color = (((r & 0xf8) << 8) |
- ((g & 0xfc) << 3) |
- ((b & 0xf8) >> 3));
+ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
}
- BEGIN_LP_RING( 6 );
- OUT_RING( CMD );
- OUT_RING( BR13 );
- OUT_RING( (y << 16) | x );
- OUT_RING( ((y+h) << 16) | (x+w) );
+ BEGIN_LP_RING(6);
+ OUT_RING(CMD);
+ OUT_RING(BR13);
+ OUT_RING((y << 16) | x);
+ OUT_RING(((y + h) << 16) | (x + w));
- if ( dev_priv->current_page == 1 ) {
- OUT_RING( dev_priv->front_offset );
- } else {
- OUT_RING( dev_priv->back_offset );
- }
+ if (dev_priv->current_page == 1) {
+ OUT_RING(dev_priv->front_offset);
+ } else {
+ OUT_RING(dev_priv->back_offset);
+ }
- OUT_RING( color );
+ OUT_RING(color);
ADVANCE_LP_RING();
}
-static void i830_cp_performance_boxes( drm_device_t *dev )
+static void i830_cp_performance_boxes(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
/* Purple box for page flipping
*/
- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP )
- i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
+ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
+ i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
/* Red box if we have to wait for idle at any point
*/
- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT )
- i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
+ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
+ i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
/* Blue box: lost context?
*/
- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT )
- i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
+ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
+ i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
/* Yellow box for texture swaps
*/
- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD )
- i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
+ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
+ i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
/* Green box if hardware never idles (as far as we can tell)
*/
- if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) )
- i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
+ if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
+ i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
-
- /* Draw bars indicating number of buffers allocated
+ /* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
if (dev_priv->dma_used) {
int bar = dev_priv->dma_used / 10240;
- if (bar > 100) bar = 100;
- if (bar < 1) bar = 1;
- i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
+ if (bar > 100)
+ bar = 100;
+ if (bar < 1)
+ bar = 1;
+ i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
dev_priv->dma_used = 0;
}
dev_priv->sarea_priv->perf_boxes = 0;
}
-static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
+static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
unsigned int clear_color,
unsigned int clear_zval,
unsigned int clear_depthmask)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
@@ -900,90 +885,90 @@ static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
unsigned int BR13, CMD, D_CMD;
RING_LOCALS;
-
- if ( dev_priv->current_page == 1 ) {
+ if (dev_priv->current_page == 1) {
unsigned int tmp = flags;
flags &= ~(I830_FRONT | I830_BACK);
- if ( tmp & I830_FRONT ) flags |= I830_BACK;
- if ( tmp & I830_BACK ) flags |= I830_FRONT;
+ if (tmp & I830_FRONT)
+ flags |= I830_BACK;
+ if (tmp & I830_BACK)
+ flags |= I830_FRONT;
}
- i830_kernel_lost_context(dev);
+ i830_kernel_lost_context(dev);
- switch(cpp) {
- case 2:
- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+ switch (cpp) {
+ case 2:
+ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
case 4:
- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
- CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
+ CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
D_CMD = XY_COLOR_BLT_CMD;
- if(clear_depthmask & 0x00ffffff)
+ if (clear_depthmask & 0x00ffffff)
D_CMD |= XY_COLOR_BLT_WRITE_RGB;
- if(clear_depthmask & 0xff000000)
+ if (clear_depthmask & 0xff000000)
D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
break;
default:
- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
}
- if (nbox > I830_NR_SAREA_CLIPRECTS)
- nbox = I830_NR_SAREA_CLIPRECTS;
+ if (nbox > I830_NR_SAREA_CLIPRECTS)
+ nbox = I830_NR_SAREA_CLIPRECTS;
- for (i = 0 ; i < nbox ; i++, pbox++) {
+ for (i = 0; i < nbox; i++, pbox++) {
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
- pbox->x2 > dev_priv->w ||
- pbox->y2 > dev_priv->h)
+ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
continue;
- if ( flags & I830_FRONT ) {
- DRM_DEBUG("clear front\n");
- BEGIN_LP_RING( 6 );
- OUT_RING( CMD );
- OUT_RING( BR13 );
- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
- OUT_RING( dev_priv->front_offset );
- OUT_RING( clear_color );
+ if (flags & I830_FRONT) {
+ DRM_DEBUG("clear front\n");
+ BEGIN_LP_RING(6);
+ OUT_RING(CMD);
+ OUT_RING(BR13);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING((pbox->y2 << 16) | pbox->x2);
+ OUT_RING(dev_priv->front_offset);
+ OUT_RING(clear_color);
ADVANCE_LP_RING();
}
- if ( flags & I830_BACK ) {
+ if (flags & I830_BACK) {
DRM_DEBUG("clear back\n");
- BEGIN_LP_RING( 6 );
- OUT_RING( CMD );
- OUT_RING( BR13 );
- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
- OUT_RING( dev_priv->back_offset );
- OUT_RING( clear_color );
+ BEGIN_LP_RING(6);
+ OUT_RING(CMD);
+ OUT_RING(BR13);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING((pbox->y2 << 16) | pbox->x2);
+ OUT_RING(dev_priv->back_offset);
+ OUT_RING(clear_color);
ADVANCE_LP_RING();
}
- if ( flags & I830_DEPTH ) {
+ if (flags & I830_DEPTH) {
DRM_DEBUG("clear depth\n");
- BEGIN_LP_RING( 6 );
- OUT_RING( D_CMD );
- OUT_RING( BR13 );
- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
- OUT_RING( dev_priv->depth_offset );
- OUT_RING( clear_zval );
+ BEGIN_LP_RING(6);
+ OUT_RING(D_CMD);
+ OUT_RING(BR13);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING((pbox->y2 << 16) | pbox->x2);
+ OUT_RING(dev_priv->depth_offset);
+ OUT_RING(clear_zval);
ADVANCE_LP_RING();
}
}
}
-static void i830_dma_dispatch_swap( drm_device_t *dev )
+static void i830_dma_dispatch_swap(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
@@ -994,202 +979,192 @@ static void i830_dma_dispatch_swap( drm_device_t *dev )
DRM_DEBUG("swapbuffers\n");
- i830_kernel_lost_context(dev);
+ i830_kernel_lost_context(dev);
if (dev_priv->do_boxes)
- i830_cp_performance_boxes( dev );
+ i830_cp_performance_boxes(dev);
- switch(cpp) {
- case 2:
- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+ switch (cpp) {
+ case 2:
+ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
+ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
}
+ if (nbox > I830_NR_SAREA_CLIPRECTS)
+ nbox = I830_NR_SAREA_CLIPRECTS;
- if (nbox > I830_NR_SAREA_CLIPRECTS)
- nbox = I830_NR_SAREA_CLIPRECTS;
-
- for (i = 0 ; i < nbox; i++, pbox++)
- {
+ for (i = 0; i < nbox; i++, pbox++) {
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
- pbox->x2 > dev_priv->w ||
- pbox->y2 > dev_priv->h)
+ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
continue;
-
+
DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
- pbox->x1, pbox->y1,
- pbox->x2, pbox->y2);
+ pbox->x1, pbox->y1, pbox->x2, pbox->y2);
- BEGIN_LP_RING( 8 );
- OUT_RING( CMD );
- OUT_RING( BR13 );
- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+ BEGIN_LP_RING(8);
+ OUT_RING(CMD);
+ OUT_RING(BR13);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING((pbox->y2 << 16) | pbox->x2);
- if (dev_priv->current_page == 0)
- OUT_RING( dev_priv->front_offset );
+ if (dev_priv->current_page == 0)
+ OUT_RING(dev_priv->front_offset);
else
- OUT_RING( dev_priv->back_offset );
+ OUT_RING(dev_priv->back_offset);
- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
- OUT_RING( BR13 & 0xffff );
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING(BR13 & 0xffff);
- if (dev_priv->current_page == 0)
- OUT_RING( dev_priv->back_offset );
+ if (dev_priv->current_page == 0)
+ OUT_RING(dev_priv->back_offset);
else
- OUT_RING( dev_priv->front_offset );
+ OUT_RING(dev_priv->front_offset);
ADVANCE_LP_RING();
}
}
-static void i830_dma_dispatch_flip( drm_device_t *dev )
+static void i830_dma_dispatch_flip(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
- __FUNCTION__,
- dev_priv->current_page,
- dev_priv->sarea_priv->pf_current_page);
+ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page,
+ dev_priv->sarea_priv->pf_current_page);
- i830_kernel_lost_context(dev);
+ i830_kernel_lost_context(dev);
if (dev_priv->do_boxes) {
dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
- i830_cp_performance_boxes( dev );
+ i830_cp_performance_boxes(dev);
}
-
- BEGIN_LP_RING( 2 );
- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
- OUT_RING( 0 );
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0);
ADVANCE_LP_RING();
- BEGIN_LP_RING( 6 );
- OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );
- OUT_RING( 0 );
- if ( dev_priv->current_page == 0 ) {
- OUT_RING( dev_priv->back_offset );
+ BEGIN_LP_RING(6);
+ OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+ OUT_RING(0);
+ if (dev_priv->current_page == 0) {
+ OUT_RING(dev_priv->back_offset);
dev_priv->current_page = 1;
} else {
- OUT_RING( dev_priv->front_offset );
+ OUT_RING(dev_priv->front_offset);
dev_priv->current_page = 0;
}
OUT_RING(0);
ADVANCE_LP_RING();
-
- BEGIN_LP_RING( 2 );
- OUT_RING( MI_WAIT_FOR_EVENT |
- MI_WAIT_FOR_PLANE_A_FLIP );
- OUT_RING( 0 );
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+ OUT_RING(0);
ADVANCE_LP_RING();
-
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static void i830_dma_dispatch_vertex(drm_device_t *dev,
- drm_buf_t *buf,
- int discard,
- int used)
+static void i830_dma_dispatch_vertex(drm_device_t * dev,
+ drm_buf_t * buf, int discard, int used)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_clip_rect_t *box = sarea_priv->boxes;
- int nbox = sarea_priv->nbox;
+ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_clip_rect_t *box = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
unsigned long address = (unsigned long)buf->bus_address;
- unsigned long start = address - dev->agp->base;
+ unsigned long start = address - dev->agp->base;
int i = 0, u;
- RING_LOCALS;
+ RING_LOCALS;
- i830_kernel_lost_context(dev);
+ i830_kernel_lost_context(dev);
- if (nbox > I830_NR_SAREA_CLIPRECTS)
+ if (nbox > I830_NR_SAREA_CLIPRECTS)
nbox = I830_NR_SAREA_CLIPRECTS;
if (discard) {
- u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+ u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
I830_BUF_HARDWARE);
- if(u != I830_BUF_CLIENT) {
+ if (u != I830_BUF_CLIENT) {
DRM_DEBUG("xxxx 2\n");
}
}
- if (used > 4*1023)
+ if (used > 4 * 1023)
used = 0;
if (sarea_priv->dirty)
- i830EmitState( dev );
+ i830EmitState(dev);
- DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
+ DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
address, used, nbox);
- dev_priv->counter++;
- DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter);
- DRM_DEBUG( "i830_dma_dispatch\n");
- DRM_DEBUG( "start : %lx\n", start);
- DRM_DEBUG( "used : %d\n", used);
- DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4);
+ dev_priv->counter++;
+ DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
+ DRM_DEBUG("i830_dma_dispatch\n");
+ DRM_DEBUG("start : %lx\n", start);
+ DRM_DEBUG("used : %d\n", used);
+ DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
u32 *vp = buf_priv->kernel_virtual;
vp[0] = (GFX_OP_PRIMITIVE |
- sarea_priv->vertex_prim |
- ((used/4)-2));
+ sarea_priv->vertex_prim | ((used / 4) - 2));
if (dev_priv->use_mi_batchbuffer_start) {
- vp[used/4] = MI_BATCH_BUFFER_END;
- used += 4;
+ vp[used / 4] = MI_BATCH_BUFFER_END;
+ used += 4;
}
-
+
if (used & 4) {
- vp[used/4] = 0;
+ vp[used / 4] = 0;
used += 4;
}
i830_unmap_buffer(buf);
}
-
+
if (used) {
do {
if (i < nbox) {
BEGIN_LP_RING(6);
- OUT_RING( GFX_OP_DRAWRECT_INFO );
- OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
- OUT_RING( box[i].x1 | (box[i].y1<<16) );
- OUT_RING( box[i].x2 | (box[i].y2<<16) );
- OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
- OUT_RING( 0 );
+ OUT_RING(GFX_OP_DRAWRECT_INFO);
+ OUT_RING(sarea_priv->
+ BufferState[I830_DESTREG_DR1]);
+ OUT_RING(box[i].x1 | (box[i].y1 << 16));
+ OUT_RING(box[i].x2 | (box[i].y2 << 16));
+ OUT_RING(sarea_priv->
+ BufferState[I830_DESTREG_DR4]);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
if (dev_priv->use_mi_batchbuffer_start) {
BEGIN_LP_RING(2);
- OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
- OUT_RING( start | MI_BATCH_NON_SECURE );
+ OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+ OUT_RING(start | MI_BATCH_NON_SECURE);
ADVANCE_LP_RING();
- }
- else {
+ } else {
BEGIN_LP_RING(4);
- OUT_RING( MI_BATCH_BUFFER );
- OUT_RING( start | MI_BATCH_NON_SECURE );
- OUT_RING( start + used - 4 );
- OUT_RING( 0 );
+ OUT_RING(MI_BATCH_BUFFER);
+ OUT_RING(start | MI_BATCH_NON_SECURE);
+ OUT_RING(start + used - 4);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
@@ -1199,61 +1174,60 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
if (discard) {
dev_priv->counter++;
- (void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
- I830_BUF_HARDWARE);
+ (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+ I830_BUF_HARDWARE);
BEGIN_LP_RING(8);
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( 20 );
- OUT_RING( dev_priv->counter );
- OUT_RING( CMD_STORE_DWORD_IDX );
- OUT_RING( buf_priv->my_use_idx );
- OUT_RING( I830_BUF_FREE );
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(20);
+ OUT_RING(dev_priv->counter);
+ OUT_RING(CMD_STORE_DWORD_IDX);
+ OUT_RING(buf_priv->my_use_idx);
+ OUT_RING(I830_BUF_FREE);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
ADVANCE_LP_RING();
}
}
-
-static void i830_dma_quiescent(drm_device_t *dev)
+static void i830_dma_quiescent(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
- RING_LOCALS;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
- i830_kernel_lost_context(dev);
+ i830_kernel_lost_context(dev);
- BEGIN_LP_RING(4);
- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
- OUT_RING( 0 );
- ADVANCE_LP_RING();
+ BEGIN_LP_RING(4);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
- i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
+ i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
}
-static int i830_flush_queue(drm_device_t *dev)
+static int i830_flush_queue(drm_device_t * dev)
{
- drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
drm_device_dma_t *dma = dev->dma;
- int i, ret = 0;
- RING_LOCALS;
-
- i830_kernel_lost_context(dev);
-
- BEGIN_LP_RING(2);
- OUT_RING( CMD_REPORT_HEAD );
- OUT_RING( 0 );
- ADVANCE_LP_RING();
-
- i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
-
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
- int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
+ int i, ret = 0;
+ RING_LOCALS;
+
+ i830_kernel_lost_context(dev);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(CMD_REPORT_HEAD);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+ int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
I830_BUF_FREE);
if (used == I830_BUF_HARDWARE)
@@ -1262,62 +1236,66 @@ static int i830_flush_queue(drm_device_t *dev)
DRM_DEBUG("still on client\n");
}
- return ret;
+ return ret;
}
/* Must be called with the lock held */
-void i830_reclaim_buffers(drm_device_t *dev, struct file *filp)
+void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
{
drm_device_dma_t *dma = dev->dma;
- int i;
+ int i;
- if (!dma) return;
- if (!dev->dev_private) return;
- if (!dma->buflist) return;
+ if (!dma)
+ return;
+ if (!dev->dev_private)
+ return;
+ if (!dma->buflist)
+ return;
- i830_flush_queue(dev);
+ i830_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[ i ];
- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
+ drm_buf_t *buf = dma->buflist[i];
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
if (buf->filp == filp && buf_priv) {
- int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+ int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
I830_BUF_FREE);
if (used == I830_BUF_CLIENT)
DRM_DEBUG("reclaimed from client\n");
- if(buf_priv->currently_mapped == I830_BUF_MAPPED)
- buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+ if (buf_priv->currently_mapped == I830_BUF_MAPPED)
+ buf_priv->currently_mapped = I830_BUF_UNMAPPED;
}
}
}
-static int i830_flush_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
- i830_flush_queue(dev);
- return 0;
+ i830_flush_queue(dev);
+ return 0;
}
static int i830_dma_vertex(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
- dev_priv->sarea_priv;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+ dev_priv->sarea_priv;
drm_i830_vertex_t vertex;
- if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))
+ if (copy_from_user
+ (&vertex, (drm_i830_vertex_t __user *) arg, sizeof(vertex)))
return -EFAULT;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1325,15 +1303,16 @@ static int i830_dma_vertex(struct inode *inode, struct file *filp,
DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
vertex.idx, vertex.used, vertex.discard);
- if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
+ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+ return -EINVAL;
- i830_dma_dispatch_vertex( dev,
- dma->buflist[ vertex.idx ],
- vertex.discard, vertex.used );
+ i830_dma_dispatch_vertex(dev,
+ dma->buflist[vertex.idx],
+ vertex.discard, vertex.used);
+
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
- sarea_priv->last_enqueue = dev_priv->counter-1;
- sarea_priv->last_dispatch = (int) hw_status[5];
-
return 0;
}
@@ -1344,9 +1323,10 @@ static int i830_clear_bufs(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->head->dev;
drm_i830_clear_t clear;
- if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
+ if (copy_from_user
+ (&clear, (drm_i830_clear_t __user *) arg, sizeof(clear)))
return -EFAULT;
-
+
LOCK_TEST_WITH_RETURN(dev, filp);
/* GH: Someone's doing nasty things... */
@@ -1354,11 +1334,10 @@ static int i830_clear_bufs(struct inode *inode, struct file *filp,
return -EINVAL;
}
- i830_dma_dispatch_clear( dev, clear.flags,
- clear.clear_color,
- clear.clear_depth,
- clear.clear_depthmask);
- return 0;
+ i830_dma_dispatch_clear(dev, clear.flags,
+ clear.clear_color,
+ clear.clear_depth, clear.clear_depthmask);
+ return 0;
}
static int i830_swap_bufs(struct inode *inode, struct file *filp,
@@ -1366,20 +1345,18 @@ static int i830_swap_bufs(struct inode *inode, struct file *filp,
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
-
+
DRM_DEBUG("i830_swap_bufs\n");
LOCK_TEST_WITH_RETURN(dev, filp);
- i830_dma_dispatch_swap( dev );
- return 0;
+ i830_dma_dispatch_swap(dev);
+ return 0;
}
-
-
/* Not sure why this isn't set all the time:
- */
-static void i830_do_init_pageflip( drm_device_t *dev )
+ */
+static void i830_do_init_pageflip(drm_device_t * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1389,20 +1366,20 @@ static void i830_do_init_pageflip( drm_device_t *dev )
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static int i830_do_cleanup_pageflip( drm_device_t *dev )
+static int i830_do_cleanup_pageflip(drm_device_t * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
if (dev_priv->current_page != 0)
- i830_dma_dispatch_flip( dev );
+ i830_dma_dispatch_flip(dev);
dev_priv->page_flipping = 0;
return 0;
}
static int i830_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
@@ -1412,45 +1389,45 @@ static int i830_flip_bufs(struct inode *inode, struct file *filp,
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv->page_flipping)
- i830_do_init_pageflip( dev );
+ if (!dev_priv->page_flipping)
+ i830_do_init_pageflip(dev);
- i830_dma_dispatch_flip( dev );
- return 0;
+ i830_dma_dispatch_flip(dev);
+ return 0;
}
static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
- dev_priv->sarea_priv;
-
- sarea_priv->last_dispatch = (int) hw_status[5];
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+ dev_priv->sarea_priv;
+
+ sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- int retcode = 0;
- drm_i830_dma_t d;
- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
- u32 *hw_status = dev_priv->hw_status_page;
- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
- dev_priv->sarea_priv;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ int retcode = 0;
+ drm_i830_dma_t d;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+ dev_priv->sarea_priv;
DRM_DEBUG("getbuf\n");
- if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))
+ if (copy_from_user(&d, (drm_i830_dma_t __user *) arg, sizeof(d)))
return -EFAULT;
-
+
LOCK_TEST_WITH_RETURN(dev, filp);
-
+
d.granted = 0;
retcode = i830_dma_get_buffer(dev, &d, filp);
@@ -1458,46 +1435,45 @@ static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
- if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
+ if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
return -EFAULT;
- sarea_priv->last_dispatch = (int) hw_status[5];
+ sarea_priv->last_dispatch = (int)hw_status[5];
return retcode;
}
static int i830_copybuf(struct inode *inode,
- struct file *filp, unsigned int cmd, unsigned long arg)
+ struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
}
static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
return 0;
}
-
-
-static int i830_getparam( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int i830_getparam(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_getparam_t param;
int value;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return -EINVAL;
}
- if (copy_from_user(&param, (drm_i830_getparam_t __user *)arg, sizeof(param) ))
+ if (copy_from_user
+ (&param, (drm_i830_getparam_t __user *) arg, sizeof(param)))
return -EFAULT;
- switch( param.param ) {
+ switch (param.param) {
case I830_PARAM_IRQ_ACTIVE:
value = dev->irq_enabled;
break;
@@ -1505,32 +1481,32 @@ static int i830_getparam( struct inode *inode, struct file *filp,
return -EINVAL;
}
- if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (copy_to_user(param.value, &value, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return -EFAULT;
}
-
+
return 0;
}
-
-static int i830_setparam( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg )
+static int i830_setparam(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_setparam_t param;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return -EINVAL;
}
- if (copy_from_user(&param, (drm_i830_setparam_t __user *)arg, sizeof(param) ))
+ if (copy_from_user
+ (&param, (drm_i830_setparam_t __user *) arg, sizeof(param)))
return -EFAULT;
- switch( param.param ) {
+ switch (param.param) {
case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
dev_priv->use_mi_batchbuffer_start = param.value;
break;
@@ -1541,13 +1517,12 @@ static int i830_setparam( struct inode *inode, struct file *filp,
return 0;
}
-
-void i830_driver_pretakedown(drm_device_t *dev)
+void i830_driver_pretakedown(drm_device_t * dev)
{
- i830_dma_cleanup( dev );
+ i830_dma_cleanup(dev);
}
-void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1557,32 +1532,48 @@ void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
}
}
-void i830_driver_release(drm_device_t *dev, struct file *filp)
+void i830_driver_release(drm_device_t * dev, struct file *filp)
{
i830_reclaim_buffers(dev, filp);
}
-int i830_driver_dma_quiescent(drm_device_t *dev)
+int i830_driver_dma_quiescent(drm_device_t * dev)
{
- i830_dma_quiescent( dev );
+ i830_dma_quiescent(dev);
return 0;
}
drm_ioctl_desc_t i830_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I830_INIT)] = { i830_dma_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_I830_VERTEX)] = { i830_dma_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_CLEAR)] = { i830_clear_bufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_GETAGE)] = { i830_getage, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_GETBUF)] = { i830_getbuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_SWAP)] = { i830_swap_bufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_COPY)] = { i830_copybuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = { i830_docopy, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_FLIP)] = { i830_flip_bufs, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam, 1, 0 },
- [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam, 1, 0 }
+ [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, 1, 0}
};
int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i8xx is AGP.
+ */
+int i830_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
index 03382c0beee3..66dd75027967 100644
--- a/drivers/char/drm/i830_drm.h
+++ b/drivers/char/drm/i830_drm.h
@@ -33,14 +33,14 @@
#define I830_UPLOAD_CTX 0x1
#define I830_UPLOAD_BUFFERS 0x2
#define I830_UPLOAD_CLIPRECTS 0x4
-#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
-#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
-#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
-#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
-#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
-#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
-#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
-#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
+#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
+#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
+#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
+#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
+#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
+#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
+#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
+#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2))
#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2))
#define I830_UPLOAD_TEXIMAGE_MASK 0xff00
@@ -65,7 +65,7 @@
* or in a piecewise fashion as required.
*/
-/* Destbuffer state
+/* Destbuffer state
* - backbuffer linear offset and pitch -- invarient in the current dri
* - zbuffer linear offset and pitch -- also invarient
* - drawing origin in back and depth buffers.
@@ -103,7 +103,7 @@
#define I830_CTXREG_AA 9
#define I830_CTXREG_FOGCOLOR 10
#define I830_CTXREG_BLENDCOLR0 11
-#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
+#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
#define I830_CTXREG_VF 13
#define I830_CTXREG_VF2 14
#define I830_CTXREG_MCSB0 15
@@ -111,12 +111,11 @@
#define I830_CTX_SETUP_SIZE 17
/* 1.3: Stipple state
- */
+ */
#define I830_STPREG_ST0 0
#define I830_STPREG_ST1 1
#define I830_STP_SETUP_SIZE 2
-
/* Texture state (per tex unit)
*/
@@ -132,23 +131,23 @@
#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
#define I830_TEX_SETUP_SIZE 10
-#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
#define I830_TEXREG_TM0S0 1
#define I830_TEXREG_TM0S1 2
#define I830_TEXREG_TM0S2 3
#define I830_TEXREG_TM0S3 4
#define I830_TEXREG_TM0S4 5
-#define I830_TEXREG_NOP0 6 /* noop */
-#define I830_TEXREG_NOP1 7 /* noop */
-#define I830_TEXREG_NOP2 8 /* noop */
-#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
+#define I830_TEXREG_NOP0 6 /* noop */
+#define I830_TEXREG_NOP1 7 /* noop */
+#define I830_TEXREG_NOP2 8 /* noop */
+#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
#define __I830_TEX_SETUP_SIZE 10
#define I830_FRONT 0x1
#define I830_BACK 0x2
#define I830_DEPTH 0x4
-#endif /* _I830_DEFINES_ */
+#endif /* _I830_DEFINES_ */
typedef struct _drm_i830_init {
enum {
@@ -177,19 +176,19 @@ typedef struct _drm_i830_init {
* structure as well */
typedef struct _drm_i830_tex_region {
- unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char next, prev; /* indices to form a circular LRU */
unsigned char in_use; /* owned by a client, or free? */
int age; /* tracked by clients to update local LRU's */
} drm_i830_tex_region_t;
typedef struct _drm_i830_sarea {
unsigned int ContextState[I830_CTX_SETUP_SIZE];
- unsigned int BufferState[I830_DEST_SETUP_SIZE];
+ unsigned int BufferState[I830_DEST_SETUP_SIZE];
unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
unsigned int Palette[2][256];
- unsigned int dirty;
+ unsigned int dirty;
unsigned int nbox;
drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
@@ -207,26 +206,26 @@ typedef struct _drm_i830_sarea {
* texture space, and can make informed decisions as to which
* areas to kick out. There is no need to choose whether to
* kick out your own texture or someone else's - simply eject
- * them all in LRU order.
+ * them all in LRU order.
*/
- drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS+1];
- /* Last elt is sentinal */
- int texAge; /* last time texture was uploaded */
- int last_enqueue; /* last time a buffer was enqueued */
+ drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+ int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
- int last_quiescent; /* */
+ int last_quiescent; /* */
int ctxOwner; /* last context to upload state */
int vertex_prim;
- int pf_enabled; /* is pageflipping allowed? */
- int pf_active;
- int pf_current_page; /* which buffer is being displayed? */
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active;
+ int pf_current_page; /* which buffer is being displayed? */
+
+ int perf_boxes; /* performance boxes to be displayed */
- int perf_boxes; /* performance boxes to be displayed */
-
- /* Here's the state for texunits 2,3:
+ /* Here's the state for texunits 2,3:
*/
unsigned int TexState2[I830_TEX_SETUP_SIZE];
unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
@@ -241,12 +240,11 @@ typedef struct _drm_i830_sarea {
/* Flags for perf_boxes
*/
-#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
-#define I830_BOX_FLIP 0x2 /* populated by kernel */
-#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
-#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
-#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
-
+#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
+#define I830_BOX_FLIP 0x2 /* populated by kernel */
+#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
/* I830 specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
@@ -289,23 +287,21 @@ typedef struct _drm_i830_clear {
unsigned int clear_depthmask;
} drm_i830_clear_t;
-
-
/* These may be placeholders if we have more cliprects than
* I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
* false, indicating that the buffer will be dispatched again with a
* new set of cliprects.
*/
typedef struct _drm_i830_vertex {
- int idx; /* buffer index */
+ int idx; /* buffer index */
int used; /* nr bytes in use */
int discard; /* client is finished with the buffer? */
} drm_i830_vertex_t;
typedef struct _drm_i830_copy_t {
- int idx; /* buffer index */
+ int idx; /* buffer index */
int used; /* nr bytes in use */
- void __user *address; /* Address to copy from */
+ void __user *address; /* Address to copy from */
} drm_i830_copy_t;
typedef struct drm_i830_dma {
@@ -315,7 +311,6 @@ typedef struct drm_i830_dma {
int granted;
} drm_i830_dma_t;
-
/* 1.3: Userspace can request & wait on irq's:
*/
typedef struct drm_i830_irq_emit {
@@ -326,7 +321,6 @@ typedef struct drm_i830_irq_wait {
int irq_seq;
} drm_i830_irq_wait_t;
-
/* 1.3: New ioctl to query kernel params:
*/
#define I830_PARAM_IRQ_ACTIVE 1
@@ -336,7 +330,6 @@ typedef struct drm_i830_getparam {
int __user *value;
} drm_i830_getparam_t;
-
/* 1.3: New ioctl to set kernel params:
*/
#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
@@ -346,5 +339,4 @@ typedef struct drm_i830_setparam {
int value;
} drm_i830_setparam_t;
-
-#endif /* _I830_DRM_H_ */
+#endif /* _I830_DRM_H_ */
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index bc36be76b8b2..acd821e8fe4d 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -40,36 +40,34 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ;
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
-
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -77,17 +75,17 @@ static struct pci_device_id pciidlist[] = {
i830_PCI_IDS
};
-extern drm_ioctl_desc_t i830_ioctls[];
-extern int i830_max_ioctl;
-
static struct drm_driver driver = {
- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
#if USE_IRQS
.driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
#endif
.dev_priv_size = sizeof(drm_i830_buf_priv_t),
.pretakedown = i830_driver_pretakedown,
.prerelease = i830_driver_prerelease,
+ .device_is_agp = i830_driver_device_is_agp,
.release = i830_driver_release,
.dma_quiescent = i830_driver_dma_quiescent,
.reclaim_buffers = i830_reclaim_buffers,
@@ -103,18 +101,19 @@ static struct drm_driver driver = {
.version = version,
.ioctls = i830_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,
+ }
};
@@ -132,6 +131,6 @@ static void __exit i830_exit(void)
module_init(i830_init);
module_exit(i830_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index df7746131dea..bc4bd49fb0cc 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -11,11 +11,11 @@
* 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
@@ -63,14 +63,14 @@
#define USE_IRQS 0
typedef struct drm_i830_buf_priv {
- u32 *in_use;
- int my_use_idx;
+ u32 *in_use;
+ int my_use_idx;
int currently_mapped;
void __user *virtual;
void *kernel_virtual;
} drm_i830_buf_priv_t;
-typedef struct _drm_i830_ring_buffer{
+typedef struct _drm_i830_ring_buffer {
int tail_mask;
unsigned long Start;
unsigned long End;
@@ -86,17 +86,17 @@ typedef struct drm_i830_private {
drm_map_t *mmio_map;
drm_i830_sarea_t *sarea_priv;
- drm_i830_ring_buffer_t ring;
+ drm_i830_ring_buffer_t ring;
- void * hw_status_page;
- unsigned long counter;
+ void *hw_status_page;
+ unsigned long counter;
dma_addr_t dma_status_page;
drm_buf_t *mmap_buffer;
-
+
u32 front_di1, back_di1, zi1;
-
+
int back_offset;
int depth_offset;
int front_offset;
@@ -113,42 +113,39 @@ typedef struct drm_i830_private {
int page_flipping;
wait_queue_head_t irq_queue;
- atomic_t irq_received;
- atomic_t irq_emitted;
+ atomic_t irq_received;
+ atomic_t irq_emitted;
int use_mi_batchbuffer_start;
} drm_i830_private_t;
+extern drm_ioctl_desc_t i830_ioctls[];
+extern int i830_max_ioctl;
+
/* i830_dma.c */
-extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
+extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp);
/* i830_irq.c */
-extern int i830_irq_emit( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int i830_irq_wait( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
-extern void i830_driver_irq_preinstall( drm_device_t *dev );
-extern void i830_driver_irq_postinstall( drm_device_t *dev );
-extern void i830_driver_irq_uninstall( drm_device_t *dev );
-extern void i830_driver_pretakedown(drm_device_t *dev);
-extern void i830_driver_release(drm_device_t *dev, struct file *filp);
-extern int i830_driver_dma_quiescent(drm_device_t *dev);
-extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
-
-#define I830_BASE(reg) ((unsigned long) \
- dev_priv->mmio_map->handle)
-#define I830_ADDR(reg) (I830_BASE(reg) + reg)
-#define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg)
-#define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg))
-#define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg))
-#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg)
-#define I830_READ16(reg) I830_DEREF16(reg)
-#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
-
-
+extern int i830_irq_emit(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int i830_irq_wait(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i830_driver_irq_preinstall(drm_device_t * dev);
+extern void i830_driver_irq_postinstall(drm_device_t * dev);
+extern void i830_driver_irq_uninstall(drm_device_t * dev);
+extern void i830_driver_pretakedown(drm_device_t * dev);
+extern void i830_driver_release(drm_device_t * dev, struct file *filp);
+extern int i830_driver_dma_quiescent(drm_device_t * dev);
+extern void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+extern int i830_driver_device_is_agp(drm_device_t * dev);
+
+#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
+#define I830_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
+#define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
+#define I830_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
#define I830_VERBOSE 0
@@ -167,7 +164,6 @@ extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
virt = dev_priv->ring.virtual_start; \
} while (0)
-
#define OUT_RING(n) do { \
if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
*(volatile unsigned int *)(virt + outring) = n; \
@@ -183,8 +179,7 @@ extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
I830_WRITE(LP_RING + RING_TAIL, outring); \
} while(0)
-extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
-
+extern int i830_wait_ring(drm_device_t * dev, int n, const char *caller);
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
@@ -199,7 +194,6 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
#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)
@@ -212,7 +206,6 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
-
#define LP_RING 0x2030
#define HP_RING 0x2040
#define RING_TAIL 0x00
@@ -224,7 +217,7 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
#define RING_START 0x08
#define START_ADDR 0x0xFFFFF000
#define RING_LEN 0x0C
-#define RING_NR_PAGES 0x001FF000
+#define RING_NR_PAGES 0x001FF000
#define RING_REPORT_MASK 0x00000006
#define RING_REPORT_64K 0x00000002
#define RING_REPORT_128K 0x00000004
@@ -290,10 +283,9 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
#define MI_BATCH_NON_SECURE (1)
#define MI_WAIT_FOR_EVENT ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#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))
#endif
-
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index a5923e5d0a77..5841f7674956 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -9,11 +9,11 @@
* 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
@@ -33,28 +33,27 @@
#include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h>
-
-irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *)arg;
- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
- u16 temp;
+ drm_device_t *dev = (drm_device_t *) arg;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ u16 temp;
- temp = I830_READ16(I830REG_INT_IDENTITY_R);
+ temp = I830_READ16(I830REG_INT_IDENTITY_R);
DRM_DEBUG("%x\n", temp);
- if ( !( temp & 2 ) )
+ if (!(temp & 2))
return IRQ_NONE;
- I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
+ I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
atomic_inc(&dev_priv->irq_received);
- wake_up_interruptible(&dev_priv->irq_queue);
+ wake_up_interruptible(&dev_priv->irq_queue);
return IRQ_HANDLED;
}
-static int i830_emit_irq(drm_device_t *dev)
+static int i830_emit_irq(drm_device_t * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -63,27 +62,25 @@ static int i830_emit_irq(drm_device_t *dev)
atomic_inc(&dev_priv->irq_emitted);
- BEGIN_LP_RING(2);
- OUT_RING( 0 );
- OUT_RING( GFX_OP_USER_INTERRUPT );
- ADVANCE_LP_RING();
+ BEGIN_LP_RING(2);
+ OUT_RING(0);
+ OUT_RING(GFX_OP_USER_INTERRUPT);
+ ADVANCE_LP_RING();
return atomic_read(&dev_priv->irq_emitted);
}
-
-static int i830_wait_irq(drm_device_t *dev, int irq_nr)
+static int i830_wait_irq(drm_device_t * dev, int irq_nr)
{
- drm_i830_private_t *dev_priv =
- (drm_i830_private_t *)dev->dev_private;
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
DECLARE_WAITQUEUE(entry, current);
- unsigned long end = jiffies + HZ*3;
+ unsigned long end = jiffies + HZ * 3;
int ret = 0;
DRM_DEBUG("%s\n", __FUNCTION__);
- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
- return 0;
+ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+ return 0;
dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
@@ -91,21 +88,21 @@ static int i830_wait_irq(drm_device_t *dev, int irq_nr)
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
- break;
- if((signed)(end - jiffies) <= 0) {
+ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+ break;
+ if ((signed)(end - jiffies) <= 0) {
DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
- I830_READ16( I830REG_INT_IDENTITY_R ),
- I830_READ16( I830REG_INT_MASK_R ),
- I830_READ16( I830REG_INT_ENABLE_R ),
- I830_READ16( I830REG_HWSTAM ));
+ I830_READ16(I830REG_INT_IDENTITY_R),
+ I830_READ16(I830REG_INT_MASK_R),
+ I830_READ16(I830REG_INT_ENABLE_R),
+ I830_READ16(I830REG_HWSTAM));
- ret = -EBUSY; /* Lockup? Missed irq? */
+ ret = -EBUSY; /* Lockup? Missed irq? */
break;
}
- schedule_timeout(HZ*3);
- if (signal_pending(current)) {
- ret = -EINTR;
+ schedule_timeout(HZ * 3);
+ if (signal_pending(current)) {
+ ret = -EINTR;
break;
}
}
@@ -115,89 +112,87 @@ static int i830_wait_irq(drm_device_t *dev, int irq_nr)
return ret;
}
-
/* Needs the lock as it touches the ring.
*/
-int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg )
+int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_emit_t emit;
int result;
LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return -EINVAL;
}
- if (copy_from_user( &emit, (drm_i830_irq_emit_t __user *)arg, sizeof(emit) ))
+ if (copy_from_user
+ (&emit, (drm_i830_irq_emit_t __user *) arg, sizeof(emit)))
return -EFAULT;
- result = i830_emit_irq( dev );
+ result = i830_emit_irq(dev);
- if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (copy_to_user(emit.irq_seq, &result, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return -EFAULT;
}
return 0;
}
-
/* Doesn't need the hardware lock.
*/
-int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg )
+int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_wait_t irqwait;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return -EINVAL;
}
- if (copy_from_user( &irqwait, (drm_i830_irq_wait_t __user *)arg,
- sizeof(irqwait) ))
+ if (copy_from_user(&irqwait, (drm_i830_irq_wait_t __user *) arg,
+ sizeof(irqwait)))
return -EFAULT;
- return i830_wait_irq( dev, irqwait.irq_seq );
+ return i830_wait_irq(dev, irqwait.irq_seq);
}
-
/* drm_dma.h hooks
*/
-void i830_driver_irq_preinstall( drm_device_t *dev ) {
- drm_i830_private_t *dev_priv =
- (drm_i830_private_t *)dev->dev_private;
+void i830_driver_irq_preinstall(drm_device_t * dev)
+{
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
- I830_WRITE16( I830REG_HWSTAM, 0xffff );
- I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
- I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+ I830_WRITE16(I830REG_HWSTAM, 0xffff);
+ I830_WRITE16(I830REG_INT_MASK_R, 0x0);
+ I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
atomic_set(&dev_priv->irq_received, 0);
atomic_set(&dev_priv->irq_emitted, 0);
init_waitqueue_head(&dev_priv->irq_queue);
}
-void i830_driver_irq_postinstall( drm_device_t *dev ) {
- drm_i830_private_t *dev_priv =
- (drm_i830_private_t *)dev->dev_private;
+void i830_driver_irq_postinstall(drm_device_t * dev)
+{
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
- I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
+ I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
}
-void i830_driver_irq_uninstall( drm_device_t *dev ) {
- drm_i830_private_t *dev_priv =
- (drm_i830_private_t *)dev->dev_private;
+void i830_driver_irq_uninstall(drm_device_t * dev)
+{
+ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
if (!dev_priv)
return;
- I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
- I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+ I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
+ I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
}
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index acf9e52a9507..f3aa0c370127 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -85,25 +85,24 @@ static int i915_dma_cleanup(drm_device_t * dev)
* is freed, it's too late.
*/
if (dev->irq)
- drm_irq_uninstall (dev);
+ drm_irq_uninstall(dev);
if (dev->dev_private) {
drm_i915_private_t *dev_priv =
(drm_i915_private_t *) dev->dev_private;
if (dev_priv->ring.virtual_start) {
- drm_core_ioremapfree( &dev_priv->ring.map, dev);
+ drm_core_ioremapfree(&dev_priv->ring.map, dev);
}
- if (dev_priv->hw_status_page) {
- drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
- dev_priv->dma_status_page);
+ if (dev_priv->status_page_dmah) {
+ drm_pci_free(dev, dev_priv->status_page_dmah);
/* Need to rewrite hardware status page */
I915_WRITE(0x02080, 0x1ffff000);
}
- drm_free (dev->dev_private, sizeof(drm_i915_private_t),
- DRM_MEM_DRIVER);
+ drm_free(dev->dev_private, sizeof(drm_i915_private_t),
+ DRM_MEM_DRIVER);
dev->dev_private = NULL;
}
@@ -147,7 +146,7 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->ring.map.flags = 0;
dev_priv->ring.map.mtrr = 0;
- drm_core_ioremap( &dev_priv->ring.map, dev );
+ drm_core_ioremap(&dev_priv->ring.map, dev);
if (dev_priv->ring.map.handle == NULL) {
dev->dev_private = (void *)dev_priv;
@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */
- dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff,
- &dev_priv->dma_status_page);
+ dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
+ 0xffffffff);
- if (!dev_priv->hw_status_page) {
+ if (!dev_priv->status_page_dmah) {
dev->dev_private = (void *)dev_priv;
i915_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return DRM_ERR(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);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
@@ -242,8 +243,8 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
switch (init.func) {
case I915_INIT_DMA:
- dev_priv = drm_alloc (sizeof(drm_i915_private_t),
- DRM_MEM_DRIVER);
+ dev_priv = drm_alloc(sizeof(drm_i915_private_t),
+ DRM_MEM_DRIVER);
if (dev_priv == NULL)
return DRM_ERR(ENOMEM);
retcode = i915_initialize(dev, dev_priv, &init);
@@ -296,7 +297,7 @@ static int do_validate_cmd(int cmd)
case 0x1c:
return 1;
case 0x1d:
- switch ((cmd>>16)&0xff) {
+ switch ((cmd >> 16) & 0xff) {
case 0x3:
return (cmd & 0x1f) + 2;
case 0x4:
@@ -698,20 +699,20 @@ static int i915_setparam(DRM_IOCTL_ARGS)
return 0;
}
-void i915_driver_pretakedown(drm_device_t *dev)
+void i915_driver_pretakedown(drm_device_t * dev)
{
- if ( dev->dev_private ) {
+ if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
- i915_mem_takedown( &(dev_priv->agp_heap) );
- }
- i915_dma_cleanup( dev );
+ i915_mem_takedown(&(dev_priv->agp_heap));
+ }
+ i915_dma_cleanup(dev);
}
-void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
{
- if ( dev->dev_private ) {
+ if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
- i915_mem_release( dev, filp, dev_priv->agp_heap );
+ i915_mem_release(dev, filp, dev_priv->agp_heap);
}
}
@@ -731,3 +732,19 @@ drm_ioctl_desc_t i915_ioctls[] = {
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i9x5 is AGP.
+ */
+int i915_driver_device_is_agp(drm_device_t * dev)
+{
+ return 1;
+}
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 1f59d3fc79bc..0508240f4e3b 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -34,36 +34,34 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ;
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
-
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -71,14 +69,13 @@ static struct pci_device_id pciidlist[] = {
i915_PCI_IDS
};
-extern drm_ioctl_desc_t i915_ioctls[];
-extern int i915_max_ioctl;
-
static struct drm_driver driver = {
- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.pretakedown = i915_driver_pretakedown,
.prerelease = i915_driver_prerelease,
+ .device_is_agp = i915_driver_device_is_agp,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
@@ -90,21 +87,21 @@ static struct drm_driver driver = {
.version = version,
.ioctls = i915_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,
#ifdef CONFIG_COMPAT
- .compat_ioctl = i915_compat_ioctl,
+ .compat_ioctl = i915_compat_ioctl,
#endif
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ }
};
static int __init i915_init(void)
@@ -121,6 +118,6 @@ static void __exit i915_exit(void)
module_init(i915_init);
module_exit(i915_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 9c37d2367dd5..17e457c73dc7 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -79,9 +79,10 @@ typedef struct drm_i915_private {
drm_i915_sarea_t *sarea_priv;
drm_i915_ring_buffer_t ring;
+ drm_dma_handle_t *status_page_dmah;
void *hw_status_page;
- unsigned long counter;
dma_addr_t dma_status_page;
+ unsigned long counter;
int back_offset;
int front_offset;
@@ -98,19 +99,23 @@ typedef struct drm_i915_private {
struct mem_block *agp_heap;
} drm_i915_private_t;
+extern drm_ioctl_desc_t i915_ioctls[];
+extern int i915_max_ioctl;
+
/* i915_dma.c */
extern void i915_kernel_lost_context(drm_device_t * dev);
-extern void i915_driver_pretakedown(drm_device_t *dev);
-extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern void i915_driver_pretakedown(drm_device_t * dev);
+extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(drm_device_t * dev);
/* i915_irq.c */
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(drm_device_t *dev);
-extern void i915_driver_irq_postinstall(drm_device_t *dev);
-extern void i915_driver_irq_uninstall(drm_device_t *dev);
+extern void i915_driver_irq_preinstall(drm_device_t * dev);
+extern void i915_driver_irq_postinstall(drm_device_t * dev);
+extern void i915_driver_irq_uninstall(drm_device_t * dev);
/* i915_mem.c */
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
@@ -123,7 +128,6 @@ extern void i915_mem_release(drm_device_t * dev,
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
-
#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)
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
index fe009e1b3a3f..2218a946ec87 100644
--- a/drivers/char/drm/i915_ioc32.c
+++ b/drivers/char/drm/i915_ioc32.c
@@ -3,7 +3,7 @@
*
* 32-bit ioctl compatibility routines for the i915 DRM.
*
- * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
+ * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
*
*
* Copyright (C) Paul Mackerras 2005
@@ -42,51 +42,55 @@ typedef struct _drm_i915_batchbuffer32 {
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
int num_cliprects; /* mulitpass with multiple cliprects? */
- u32 cliprects; /* pointer to userspace cliprects */
+ u32 cliprects; /* pointer to userspace cliprects */
} drm_i915_batchbuffer32_t;
static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
drm_i915_batchbuffer32_t batchbuffer32;
drm_i915_batchbuffer_t __user *batchbuffer;
-
- if (copy_from_user(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
+
+ if (copy_from_user
+ (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
return -EFAULT;
-
+
batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
|| __put_user(batchbuffer32.start, &batchbuffer->start)
|| __put_user(batchbuffer32.used, &batchbuffer->used)
|| __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
|| __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
- || __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects)
+ || __put_user(batchbuffer32.num_cliprects,
+ &batchbuffer->num_cliprects)
|| __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
&batchbuffer->cliprects))
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_I915_BATCHBUFFER, (unsigned long) batchbuffer);
+ DRM_IOCTL_I915_BATCHBUFFER,
+ (unsigned long)batchbuffer);
}
typedef struct _drm_i915_cmdbuffer32 {
- u32 buf; /* pointer to userspace command buffer */
+ u32 buf; /* pointer to userspace command buffer */
int sz; /* nr bytes in buf */
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
int num_cliprects; /* mulitpass with multiple cliprects? */
- u32 cliprects; /* pointer to userspace cliprects */
+ u32 cliprects; /* pointer to userspace cliprects */
} drm_i915_cmdbuffer32_t;
static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
drm_i915_cmdbuffer32_t cmdbuffer32;
drm_i915_cmdbuffer_t __user *cmdbuffer;
-
- if (copy_from_user(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
+
+ if (copy_from_user
+ (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
return -EFAULT;
-
+
cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
|| __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
@@ -98,9 +102,9 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
|| __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
&cmdbuffer->cliprects))
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_I915_CMDBUFFER, (unsigned long) cmdbuffer);
+ DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
}
typedef struct drm_i915_irq_emit32 {
@@ -108,12 +112,12 @@ typedef struct drm_i915_irq_emit32 {
} drm_i915_irq_emit32_t;
static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
drm_i915_irq_emit32_t req32;
drm_i915_irq_emit_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -123,7 +127,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_I915_IRQ_EMIT, (unsigned long) request);
+ DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
}
typedef struct drm_i915_getparam32 {
int param;
@@ -131,12 +135,12 @@ typedef struct drm_i915_getparam32 {
} drm_i915_getparam32_t;
static int compat_i915_getparam(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
drm_i915_getparam32_t req32;
drm_i915_getparam_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -147,7 +151,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_I915_GETPARAM, (unsigned long) request);
+ DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
}
typedef struct drm_i915_mem_alloc32 {
@@ -158,12 +162,12 @@ typedef struct drm_i915_mem_alloc32 {
} drm_i915_mem_alloc32_t;
static int compat_i915_alloc(struct file *file, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
drm_i915_mem_alloc32_t req32;
drm_i915_mem_alloc_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -176,10 +180,9 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_I915_ALLOC, (unsigned long) request);
+ DRM_IOCTL_I915_ALLOC, (unsigned long)request);
}
-
drm_ioctl_compat_t *i915_compat_ioctls[] = {
[DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
[DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
@@ -197,8 +200,7 @@ drm_ioctl_compat_t *i915_compat_ioctls[] = {
* \param arg user argument.
* \return zero on success or negative number on failure.
*/
-long i915_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned int nr = DRM_IOCTL_NR(cmd);
drm_ioctl_compat_t *fn = NULL;
@@ -206,13 +208,13 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd,
if (nr < DRM_COMMAND_BASE)
return drm_compat_ioctl(filp, cmd, arg);
-
+
if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
lock_kernel(); /* XXX for now */
if (fn != NULL)
- ret = (*fn)(filp, cmd, arg);
+ ret = (*fn) (filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 9b1698f521be..13176d136a99 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -86,7 +86,7 @@ static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
}
/* Very simple allocator for agp memory, working on a static range
- * already mapped into each client's address space.
+ * already mapped into each client's address space.
*/
static struct mem_block *split_block(struct mem_block *p, int start, int size,
@@ -94,7 +94,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ struct mem_block *newblock =
+ drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
if (!newblock)
goto out;
newblock->start = start;
@@ -110,7 +111,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
/* Maybe cut off the end of an existing block */
if (size < p->size) {
- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ struct mem_block *newblock =
+ drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
if (!newblock)
goto out;
newblock->start = start + size;
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 832eaf8a5068..70dc7f64b7b9 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -23,58 +23,61 @@
* 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.
+ */
+
+/**
+ * \file mga_dma.c
+ * DMA support for MGA G200 / G400.
*
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Jeff Hartmann <jhartmann@valinux.com>
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- * Rewritten by:
- * Gareth Hughes <gareth@valinux.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Jeff Hartmann <jhartmann@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
*/
#include "drmP.h"
#include "drm.h"
+#include "drm_sarea.h"
#include "mga_drm.h"
#include "mga_drv.h"
#define MGA_DEFAULT_USEC_TIMEOUT 10000
#define MGA_FREELIST_DEBUG 0
-static int mga_do_cleanup_dma( drm_device_t *dev );
+static int mga_do_cleanup_dma(drm_device_t * dev);
/* ================================================================
* Engine control
*/
-int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
+int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
{
u32 status = 0;
int i;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
- if ( status == MGA_ENDPRDMASTS ) {
- MGA_WRITE8( MGA_CRTC_INDEX, 0 );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+ if (status == MGA_ENDPRDMASTS) {
+ MGA_WRITE8(MGA_CRTC_INDEX, 0);
return 0;
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if MGA_DMA_DEBUG
- DRM_ERROR( "failed!\n" );
- DRM_INFO( " status=0x%08x\n", status );
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x\n", status);
#endif
return DRM_ERR(EBUSY);
}
-static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
+static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/* The primary DMA stream should look like new right about now.
*/
@@ -97,24 +100,25 @@ static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
* Primary DMA stream
*/
-void mga_do_dma_flush( drm_mga_private_t *dev_priv )
+void mga_do_dma_flush(drm_mga_private_t * dev_priv)
{
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
u32 head, tail;
u32 status = 0;
int i;
- DMA_LOCALS;
- DRM_DEBUG( "\n" );
-
- /* We need to wait so that we can do an safe flush */
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
- if ( status == MGA_ENDPRDMASTS ) break;
- DRM_UDELAY( 1 );
+ DMA_LOCALS;
+ DRM_DEBUG("\n");
+
+ /* We need to wait so that we can do an safe flush */
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+ if (status == MGA_ENDPRDMASTS)
+ break;
+ DRM_UDELAY(1);
}
- if ( primary->tail == primary->last_flush ) {
- DRM_DEBUG( " bailing out...\n" );
+ if (primary->tail == primary->last_flush) {
+ DRM_DEBUG(" bailing out...\n");
return;
}
@@ -124,48 +128,46 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv )
* actually (partially?) reads the first of these commands.
* See page 4-16 in the G400 manual, middle of the page or so.
*/
- BEGIN_DMA( 1 );
+ BEGIN_DMA(1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
ADVANCE_DMA();
primary->last_flush = primary->tail;
- head = MGA_READ( MGA_PRIMADDRESS );
+ head = MGA_READ(MGA_PRIMADDRESS);
- if ( head <= tail ) {
+ if (head <= tail) {
primary->space = primary->size - primary->tail;
} else {
primary->space = head - tail;
}
- DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset );
- DRM_DEBUG( " tail = 0x%06lx\n", tail - dev_priv->primary->offset );
- DRM_DEBUG( " space = 0x%06x\n", primary->space );
+ DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset);
+ DRM_DEBUG(" tail = 0x%06lx\n", tail - dev_priv->primary->offset);
+ DRM_DEBUG(" space = 0x%06x\n", primary->space);
mga_flush_write_combine();
- MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
- DRM_DEBUG( "done.\n" );
+ DRM_DEBUG("done.\n");
}
-void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
+void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
{
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
u32 head, tail;
DMA_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
BEGIN_DMA_WRAP();
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
ADVANCE_DMA();
@@ -175,45 +177,43 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
primary->last_flush = 0;
primary->last_wrap++;
- head = MGA_READ( MGA_PRIMADDRESS );
+ head = MGA_READ(MGA_PRIMADDRESS);
- if ( head == dev_priv->primary->offset ) {
+ if (head == dev_priv->primary->offset) {
primary->space = primary->size;
} else {
primary->space = head - dev_priv->primary->offset;
}
- DRM_DEBUG( " head = 0x%06lx\n",
- head - dev_priv->primary->offset );
- DRM_DEBUG( " tail = 0x%06x\n", primary->tail );
- DRM_DEBUG( " wrap = %d\n", primary->last_wrap );
- DRM_DEBUG( " space = 0x%06x\n", primary->space );
+ DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset);
+ DRM_DEBUG(" tail = 0x%06x\n", primary->tail);
+ DRM_DEBUG(" wrap = %d\n", primary->last_wrap);
+ DRM_DEBUG(" space = 0x%06x\n", primary->space);
mga_flush_write_combine();
- MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
- set_bit( 0, &primary->wrapped );
- DRM_DEBUG( "done.\n" );
+ set_bit(0, &primary->wrapped);
+ DRM_DEBUG("done.\n");
}
-void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
+void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
{
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
u32 head = dev_priv->primary->offset;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
sarea_priv->last_wrap++;
- DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap );
+ DRM_DEBUG(" wrap = %d\n", sarea_priv->last_wrap);
mga_flush_write_combine();
- MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
+ MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
- clear_bit( 0, &primary->wrapped );
- DRM_DEBUG( "done.\n" );
+ clear_bit(0, &primary->wrapped);
+ DRM_DEBUG("done.\n");
}
-
/* ================================================================
* Freelist management
*/
@@ -222,63 +222,61 @@ void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
#define MGA_BUFFER_FREE 0
#if MGA_FREELIST_DEBUG
-static void mga_freelist_print( drm_device_t *dev )
+static void mga_freelist_print(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *entry;
- DRM_INFO( "\n" );
- DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
- dev_priv->sarea_priv->last_dispatch,
- (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
- dev_priv->primary->offset) );
- DRM_INFO( "current freelist:\n" );
-
- for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
- DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n",
- entry, entry->buf->idx, entry->age.head,
- entry->age.head - dev_priv->primary->offset );
+ DRM_INFO("\n");
+ DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
+ dev_priv->sarea_priv->last_dispatch,
+ (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
+ dev_priv->primary->offset));
+ DRM_INFO("current freelist:\n");
+
+ for (entry = dev_priv->head->next; entry; entry = entry->next) {
+ DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n",
+ entry, entry->buf->idx, entry->age.head,
+ entry->age.head - dev_priv->primary->offset);
}
- DRM_INFO( "\n" );
+ DRM_INFO("\n");
}
#endif
-static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
+static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_freelist_t *entry;
int i;
- DRM_DEBUG( "count=%d\n", dma->buf_count );
+ DRM_DEBUG("count=%d\n", dma->buf_count);
- dev_priv->head = drm_alloc( sizeof(drm_mga_freelist_t),
- DRM_MEM_DRIVER );
- if ( dev_priv->head == NULL )
+ dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ if (dev_priv->head == NULL)
return DRM_ERR(ENOMEM);
- memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
- SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
+ memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
+ SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
- buf_priv = buf->dev_private;
+ buf_priv = buf->dev_private;
- entry = drm_alloc( sizeof(drm_mga_freelist_t),
- DRM_MEM_DRIVER );
- if ( entry == NULL )
+ entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ if (entry == NULL)
return DRM_ERR(ENOMEM);
- memset( entry, 0, sizeof(drm_mga_freelist_t) );
+ memset(entry, 0, sizeof(drm_mga_freelist_t));
entry->next = dev_priv->head->next;
entry->prev = dev_priv->head;
- SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+ SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
entry->buf = buf;
- if ( dev_priv->head->next != NULL )
+ if (dev_priv->head->next != NULL)
dev_priv->head->next->prev = entry;
- if ( entry->next == NULL )
+ if (entry->next == NULL)
dev_priv->tail = entry;
buf_priv->list_entry = entry;
@@ -291,17 +289,17 @@ static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
return 0;
}
-static void mga_freelist_cleanup( drm_device_t *dev )
+static void mga_freelist_cleanup(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *entry;
drm_mga_freelist_t *next;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
entry = dev_priv->head;
- while ( entry ) {
+ while (entry) {
next = entry->next;
- drm_free( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
+ drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
entry = next;
}
@@ -311,71 +309,69 @@ static void mga_freelist_cleanup( drm_device_t *dev )
#if 0
/* FIXME: Still needed?
*/
-static void mga_freelist_reset( drm_device_t *dev )
+static void mga_freelist_reset(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
int i;
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
- buf_priv = buf->dev_private;
- SET_AGE( &buf_priv->list_entry->age,
- MGA_BUFFER_FREE, 0 );
+ buf_priv = buf->dev_private;
+ SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
}
}
#endif
-static drm_buf_t *mga_freelist_get( drm_device_t *dev )
+static drm_buf_t *mga_freelist_get(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *next;
drm_mga_freelist_t *prev;
drm_mga_freelist_t *tail = dev_priv->tail;
u32 head, wrap;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- head = MGA_READ( MGA_PRIMADDRESS );
+ head = MGA_READ(MGA_PRIMADDRESS);
wrap = dev_priv->sarea_priv->last_wrap;
- DRM_DEBUG( " tail=0x%06lx %d\n",
- tail->age.head ?
- tail->age.head - dev_priv->primary->offset : 0,
- tail->age.wrap );
- DRM_DEBUG( " head=0x%06lx %d\n",
- head - dev_priv->primary->offset, wrap );
+ DRM_DEBUG(" tail=0x%06lx %d\n",
+ tail->age.head ?
+ tail->age.head - dev_priv->primary->offset : 0,
+ tail->age.wrap);
+ DRM_DEBUG(" head=0x%06lx %d\n",
+ head - dev_priv->primary->offset, wrap);
- if ( TEST_AGE( &tail->age, head, wrap ) ) {
+ if (TEST_AGE(&tail->age, head, wrap)) {
prev = dev_priv->tail->prev;
next = dev_priv->tail;
prev->next = NULL;
next->prev = next->next = NULL;
dev_priv->tail = prev;
- SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
+ SET_AGE(&next->age, MGA_BUFFER_USED, 0);
return next->buf;
}
- DRM_DEBUG( "returning NULL!\n" );
+ DRM_DEBUG("returning NULL!\n");
return NULL;
}
-int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
+int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
drm_mga_freelist_t *head, *entry, *prev;
- DRM_DEBUG( "age=0x%06lx wrap=%d\n",
- buf_priv->list_entry->age.head -
- dev_priv->primary->offset,
- buf_priv->list_entry->age.wrap );
+ DRM_DEBUG("age=0x%06lx wrap=%d\n",
+ buf_priv->list_entry->age.head -
+ dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
entry = buf_priv->list_entry;
head = dev_priv->head;
- if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
- SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+ if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
+ SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
prev = dev_priv->tail;
prev->next = entry;
entry->prev = prev;
@@ -391,43 +387,406 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
return 0;
}
-
/* ================================================================
* DMA initialization, cleanup
*/
-static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
+int mga_driver_preinit(drm_device_t * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
- int ret;
- DRM_DEBUG( "\n" );
- dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
- if ( !dev_priv )
+ dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ if (!dev_priv)
return DRM_ERR(ENOMEM);
- memset( dev_priv, 0, sizeof(drm_mga_private_t) );
-
- dev_priv->chipset = init->chipset;
+ dev->dev_private = (void *)dev_priv;
+ memset(dev_priv, 0, sizeof(drm_mga_private_t));
dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+ dev_priv->chipset = flags;
+
+ return 0;
+}
+
+#if __OS_HAS_AGP
+/**
+ * Bootstrap the driver for AGP DMA.
+ *
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory. If not, the microcode may as well always be put in PCI
+ * memory.
+ *
+ * \todo
+ * This routine needs to set dma_bs->agp_mode to the mode actually configured
+ * in the hardware. Looking just at the Linux AGP driver code, I don't see
+ * an easy way to determine this.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
+ */
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+ unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ int err;
+ unsigned offset;
+ const unsigned secondary_size = dma_bs->secondary_bin_count
+ * dma_bs->secondary_bin_size;
+ const unsigned agp_size = (dma_bs->agp_size << 20);
+ drm_buf_desc_t req;
+ drm_agp_mode_t mode;
+ drm_agp_info_t info;
+
+ /* Acquire AGP. */
+ err = drm_agp_acquire(dev);
+ if (err) {
+ DRM_ERROR("Unable to acquire AGP\n");
+ return err;
+ }
+
+ err = drm_agp_info(dev, &info);
+ if (err) {
+ DRM_ERROR("Unable to get AGP info\n");
+ return err;
+ }
+
+ mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
+ err = drm_agp_enable(dev, mode);
+ if (err) {
+ DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+ return err;
+ }
+
+ /* In addition to the usual AGP mode configuration, the G200 AGP cards
+ * need to have the AGP mode "manually" set.
+ */
+
+ if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+ if (mode.mode & 0x02) {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+ } else {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+ }
+ }
+
+ /* Allocate and bind AGP memory. */
+ dev_priv->agp_pages = agp_size / PAGE_SIZE;
+ dev_priv->agp_mem = drm_alloc_agp(dev, dev_priv->agp_pages, 0);
+ if (dev_priv->agp_mem == NULL) {
+ dev_priv->agp_pages = 0;
+ DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+ dma_bs->agp_size);
+ return DRM_ERR(ENOMEM);
+ }
+
+ err = drm_bind_agp(dev_priv->agp_mem, 0);
+ if (err) {
+ DRM_ERROR("Unable to bind AGP memory\n");
+ return err;
+ }
+
+ /* Make drm_addbufs happy by not trying to create a mapping for less
+ * than a page.
+ */
+ if (warp_size < PAGE_SIZE)
+ warp_size = PAGE_SIZE;
+
+ offset = 0;
+ err = drm_addmap(dev, offset, warp_size,
+ _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);
+ if (err) {
+ DRM_ERROR("Unable to map WARP microcode\n");
+ return err;
+ }
+
+ offset += warp_size;
+ err = drm_addmap(dev, offset, dma_bs->primary_size,
+ _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);
+ if (err) {
+ DRM_ERROR("Unable to map primary DMA region\n");
+ return err;
+ }
+
+ offset += dma_bs->primary_size;
+ err = drm_addmap(dev, offset, secondary_size,
+ _DRM_AGP, 0, &dev->agp_buffer_map);
+ if (err) {
+ DRM_ERROR("Unable to map secondary DMA region\n");
+ return err;
+ }
+
+ (void)memset(&req, 0, sizeof(req));
+ req.count = dma_bs->secondary_bin_count;
+ req.size = dma_bs->secondary_bin_size;
+ req.flags = _DRM_AGP_BUFFER;
+ req.agp_start = offset;
+
+ err = drm_addbufs_agp(dev, &req);
+ if (err) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+ }
+
+ offset += secondary_size;
+ err = drm_addmap(dev, offset, agp_size - offset,
+ _DRM_AGP, 0, &dev_priv->agp_textures);
+ if (err) {
+ DRM_ERROR("Unable to map AGP texture region\n");
+ return err;
+ }
+
+ drm_core_ioremap(dev_priv->warp, dev);
+ drm_core_ioremap(dev_priv->primary, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+
+ if (!dev_priv->warp->handle ||
+ !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
+ DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
+ dev_priv->warp->handle, dev_priv->primary->handle,
+ dev->agp_buffer_map->handle);
+ return DRM_ERR(ENOMEM);
+ }
+
+ dev_priv->dma_access = MGA_PAGPXFER;
+ dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+ DRM_INFO("Initialized card for AGP DMA.\n");
+ return 0;
+}
+#else
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ return -EINVAL;
+}
+#endif
+
+/**
+ * Bootstrap the driver for PCI DMA.
+ *
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better. The size should be rounded up to the nearest page size, then
+ * decrease the request size by a single page each pass through the loop.
+ *
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+ unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ unsigned int primary_size;
+ unsigned int bin_count;
+ int err;
+ drm_buf_desc_t req;
+
+ if (dev->dma == NULL) {
+ DRM_ERROR("dev->dma is NULL\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ /* Make drm_addbufs happy by not trying to create a mapping for less
+ * than a page.
+ */
+ if (warp_size < PAGE_SIZE)
+ warp_size = PAGE_SIZE;
+
+ /* The proper alignment is 0x100 for this mapping */
+ err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
+ _DRM_READ_ONLY, &dev_priv->warp);
+ if (err != 0) {
+ DRM_ERROR("Unable to create mapping for WARP microcode\n");
+ return err;
+ }
+
+ /* Other than the bottom two bits being used to encode other
+ * information, there don't appear to be any restrictions on the
+ * alignment of the primary or secondary DMA buffers.
+ */
+
+ for (primary_size = dma_bs->primary_size; primary_size != 0;
+ primary_size >>= 1) {
+ /* The proper alignment for this mapping is 0x04 */
+ err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+ _DRM_READ_ONLY, &dev_priv->primary);
+ if (!err)
+ break;
+ }
+
+ if (err != 0) {
+ DRM_ERROR("Unable to allocate primary DMA region\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ if (dev_priv->primary->size != dma_bs->primary_size) {
+ DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+ dma_bs->primary_size,
+ (unsigned)dev_priv->primary->size);
+ dma_bs->primary_size = dev_priv->primary->size;
+ }
+
+ for (bin_count = dma_bs->secondary_bin_count; bin_count > 0;
+ bin_count--) {
+ (void)memset(&req, 0, sizeof(req));
+ req.count = bin_count;
+ req.size = dma_bs->secondary_bin_size;
+
+ err = drm_addbufs_pci(dev, &req);
+ if (!err) {
+ break;
+ }
+ }
- if ( init->sgram ) {
+ if (bin_count == 0) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+ }
+
+ if (bin_count != dma_bs->secondary_bin_count) {
+ DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
+ "to %u.\n", dma_bs->secondary_bin_count, bin_count);
+
+ dma_bs->secondary_bin_count = bin_count;
+ }
+
+ dev_priv->dma_access = 0;
+ dev_priv->wagp_enable = 0;
+
+ dma_bs->agp_mode = 0;
+
+ DRM_INFO("Initialized card for PCI DMA.\n");
+ return 0;
+}
+
+static int mga_do_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+{
+ const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+ int err;
+ drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ dev_priv->used_new_dma_init = 1;
+
+ /* The first steps are the same for both PCI and AGP based DMA. Map
+ * the cards MMIO registers and map a status page.
+ */
+ err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
+ _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
+ if (err) {
+ DRM_ERROR("Unable to map MMIO region\n");
+ return err;
+ }
+
+ err = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
+ _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+ &dev_priv->status);
+ if (err) {
+ DRM_ERROR("Unable to map status region\n");
+ return err;
+ }
+
+ /* The DMA initialization procedure is slightly different for PCI and
+ * AGP cards. AGP cards just allocate a large block of AGP memory and
+ * carve off portions of it for internal uses. The remaining memory
+ * is returned to user-mode to be used for AGP textures.
+ */
+ if (is_agp) {
+ err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+ }
+
+ /* If we attempted to initialize the card for AGP DMA but failed,
+ * clean-up any mess that may have been created.
+ */
+
+ if (err) {
+ mga_do_cleanup_dma(dev);
+ }
+
+ /* Not only do we want to try and initialized PCI cards for PCI DMA,
+ * but we also try to initialized AGP cards that could not be
+ * initialized for AGP DMA. This covers the case where we have an AGP
+ * card in a system with an unsupported AGP chipset. In that case the
+ * card will be detected as AGP, but we won't be able to allocate any
+ * AGP memory, etc.
+ */
+
+ if (!is_agp || err) {
+ err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+ }
+
+ return err;
+}
+
+int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_dma_bootstrap_t bootstrap;
+ int err;
+
+ DRM_COPY_FROM_USER_IOCTL(bootstrap,
+ (drm_mga_dma_bootstrap_t __user *) data,
+ sizeof(bootstrap));
+
+ err = mga_do_dma_bootstrap(dev, &bootstrap);
+ if (!err) {
+ static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
+ const drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ if (dev_priv->agp_textures != NULL) {
+ bootstrap.texture_handle =
+ dev_priv->agp_textures->offset;
+ bootstrap.texture_size = dev_priv->agp_textures->size;
+ } else {
+ bootstrap.texture_handle = 0;
+ bootstrap.texture_size = 0;
+ }
+
+ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
+ if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,
+ sizeof(bootstrap))) {
+ err = DRM_ERR(EFAULT);
+ }
+ } else {
+ mga_do_cleanup_dma(dev);
+ }
+
+ return err;
+}
+
+static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+{
+ drm_mga_private_t *dev_priv;
+ int ret;
+ DRM_DEBUG("\n");
+
+ dev_priv = dev->dev_private;
+
+ if (init->sgram) {
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
} else {
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
}
- dev_priv->maccess = init->maccess;
+ dev_priv->maccess = init->maccess;
- dev_priv->fb_cpp = init->fb_cpp;
- dev_priv->front_offset = init->front_offset;
- dev_priv->front_pitch = init->front_pitch;
- dev_priv->back_offset = init->back_offset;
- dev_priv->back_pitch = init->back_pitch;
+ dev_priv->fb_cpp = init->fb_cpp;
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
- dev_priv->depth_cpp = init->depth_cpp;
- dev_priv->depth_offset = init->depth_offset;
- dev_priv->depth_pitch = init->depth_pitch;
+ dev_priv->depth_cpp = init->depth_cpp;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
/* FIXME: Need to support AGP textures...
*/
@@ -436,108 +795,88 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
DRM_GETSAREA();
- if(!dev_priv->sarea) {
- DRM_ERROR( "failed to find sarea!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ if (!dev_priv->sarea) {
+ DRM_ERROR("failed to find sarea!\n");
return DRM_ERR(EINVAL);
}
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- if(!dev_priv->mmio) {
- DRM_ERROR( "failed to find mmio region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->status = drm_core_findmap(dev, init->status_offset);
- if(!dev_priv->status) {
- DRM_ERROR( "failed to find status page!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
- if(!dev_priv->warp) {
- DRM_ERROR( "failed to find warp microcode region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
- if(!dev_priv->primary) {
- DRM_ERROR( "failed to find primary dma region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
- }
- dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- if(!dev->agp_buffer_map) {
- DRM_ERROR( "failed to find dma buffer region!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
- return DRM_ERR(EINVAL);
+ if (!dev_priv->used_new_dma_init) {
+
+ dev_priv->dma_access = MGA_PAGPXFER;
+ dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+ dev_priv->status = drm_core_findmap(dev, init->status_offset);
+ if (!dev_priv->status) {
+ DRM_ERROR("failed to find status page!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio) {
+ DRM_ERROR("failed to find mmio region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
+ if (!dev_priv->warp) {
+ DRM_ERROR("failed to find warp microcode region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
+ if (!dev_priv->primary) {
+ DRM_ERROR("failed to find primary dma region!\n");
+ return DRM_ERR(EINVAL);
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map =
+ drm_core_findmap(dev, init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("failed to find dma buffer region!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ drm_core_ioremap(dev_priv->warp, dev);
+ drm_core_ioremap(dev_priv->primary, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
}
dev_priv->sarea_priv =
- (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
-
- drm_core_ioremap( dev_priv->warp, dev );
- drm_core_ioremap( dev_priv->primary, dev );
- drm_core_ioremap( dev->agp_buffer_map, dev );
-
- if(!dev_priv->warp->handle ||
- !dev_priv->primary->handle ||
- !dev->agp_buffer_map->handle ) {
- DRM_ERROR( "failed to ioremap agp regions!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ if (!dev_priv->warp->handle ||
+ !dev_priv->primary->handle ||
+ ((dev_priv->dma_access != 0) &&
+ ((dev->agp_buffer_map == NULL) ||
+ (dev->agp_buffer_map->handle == NULL)))) {
+ DRM_ERROR("failed to ioremap agp regions!\n");
return DRM_ERR(ENOMEM);
}
- ret = mga_warp_install_microcode( dev_priv );
- if ( ret < 0 ) {
- DRM_ERROR( "failed to install WARP ucode!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ ret = mga_warp_install_microcode(dev_priv);
+ if (ret < 0) {
+ DRM_ERROR("failed to install WARP ucode!\n");
return ret;
}
- ret = mga_warp_init( dev_priv );
- if ( ret < 0 ) {
- DRM_ERROR( "failed to init WARP engine!\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ ret = mga_warp_init(dev_priv);
+ if (ret < 0) {
+ DRM_ERROR("failed to init WARP engine!\n");
return ret;
}
- dev_priv->prim.status = (u32 *)dev_priv->status->handle;
+ dev_priv->prim.status = (u32 *) dev_priv->status->handle;
- mga_do_wait_for_idle( dev_priv );
+ mga_do_wait_for_idle(dev_priv);
/* Init the primary DMA registers.
*/
- MGA_WRITE( MGA_PRIMADDRESS,
- dev_priv->primary->offset | MGA_DMA_GENERAL );
+ MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
#if 0
- MGA_WRITE( MGA_PRIMPTR,
- virt_to_bus((void *)dev_priv->prim.status) |
- MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
- MGA_PRIMPTREN1 ); /* DWGSYNC */
+ MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
+ MGA_PRIMPTREN1); /* DWGSYNC */
#endif
- dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
- dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
+ dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
+ dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
+ dev_priv->primary->size);
dev_priv->prim.size = dev_priv->primary->size;
@@ -557,142 +896,176 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
dev_priv->sarea_priv->last_frame.head = 0;
dev_priv->sarea_priv->last_frame.wrap = 0;
- if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
- DRM_ERROR( "could not initialize freelist\n" );
- /* Assign dev_private so we can do cleanup. */
- dev->dev_private = (void *)dev_priv;
- mga_do_cleanup_dma( dev );
+ if (mga_freelist_init(dev, dev_priv) < 0) {
+ DRM_ERROR("could not initialize freelist\n");
return DRM_ERR(ENOMEM);
}
- /* Make dev_private visable to others. */
- dev->dev_private = (void *)dev_priv;
return 0;
}
-static int mga_do_cleanup_dma( drm_device_t *dev )
+static int mga_do_cleanup_dma(drm_device_t * dev)
{
- DRM_DEBUG( "\n" );
+ int err = 0;
+ DRM_DEBUG("\n");
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
- if ( dev->dev_private ) {
+ if (dev->dev_private) {
drm_mga_private_t *dev_priv = dev->dev_private;
- if ( dev_priv->warp != NULL )
- drm_core_ioremapfree( dev_priv->warp, dev );
- if ( dev_priv->primary != NULL )
- drm_core_ioremapfree( dev_priv->primary, dev );
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
+ if ((dev_priv->warp != NULL)
+ && (dev_priv->warp->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->warp, dev);
+
+ if ((dev_priv->primary != NULL)
+ && (dev_priv->primary->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->primary, dev);
+
+ if (dev->agp_buffer_map != NULL)
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
- if ( dev_priv->head != NULL ) {
- mga_freelist_cleanup( dev );
+ if (dev_priv->used_new_dma_init) {
+#if __OS_HAS_AGP
+ if (dev_priv->agp_mem != NULL) {
+ dev_priv->agp_textures = NULL;
+ drm_unbind_agp(dev_priv->agp_mem);
+
+ drm_free_agp(dev_priv->agp_mem,
+ dev_priv->agp_pages);
+ dev_priv->agp_pages = 0;
+ dev_priv->agp_mem = NULL;
+ }
+
+ if ((dev->agp != NULL) && dev->agp->acquired) {
+ err = drm_agp_release(dev);
+ }
+#endif
+ dev_priv->used_new_dma_init = 0;
}
- drm_free( dev->dev_private, sizeof(drm_mga_private_t),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ dev_priv->warp = NULL;
+ dev_priv->primary = NULL;
+ dev_priv->mmio = NULL;
+ dev_priv->status = NULL;
+ dev_priv->sarea = NULL;
+ dev_priv->sarea_priv = NULL;
+ dev->agp_buffer_map = NULL;
+
+ memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+ dev_priv->warp_pipe = 0;
+ memset(dev_priv->warp_pipe_phys, 0,
+ sizeof(dev_priv->warp_pipe_phys));
+
+ if (dev_priv->head != NULL) {
+ mga_freelist_cleanup(dev);
+ }
}
- return 0;
+ return err;
}
-int mga_dma_init( DRM_IOCTL_ARGS )
+int mga_dma_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_init_t init;
+ int err;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) );
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
+ sizeof(init));
- switch ( init.func ) {
+ switch (init.func) {
case MGA_INIT_DMA:
- return mga_do_init_dma( dev, &init );
+ err = mga_do_init_dma(dev, &init);
+ if (err) {
+ (void)mga_do_cleanup_dma(dev);
+ }
+ return err;
case MGA_CLEANUP_DMA:
- return mga_do_cleanup_dma( dev );
+ return mga_do_cleanup_dma(dev);
}
return DRM_ERR(EINVAL);
}
-
/* ================================================================
* Primary DMA stream management
*/
-int mga_dma_flush( DRM_IOCTL_ARGS )
+int mga_dma_flush(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
drm_lock_t lock;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t __user *)data, sizeof(lock) );
+ DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
+ sizeof(lock));
- DRM_DEBUG( "%s%s%s\n",
- (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
- (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
- (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
+ DRM_DEBUG("%s%s%s\n",
+ (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+ (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+ (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
- WRAP_WAIT_WITH_RETURN( dev_priv );
+ WRAP_WAIT_WITH_RETURN(dev_priv);
- if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
- mga_do_dma_flush( dev_priv );
+ if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
+ mga_do_dma_flush(dev_priv);
}
- if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
#if MGA_DMA_DEBUG
- int ret = mga_do_wait_for_idle( dev_priv );
- if ( ret < 0 )
- DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
+ int ret = mga_do_wait_for_idle(dev_priv);
+ if (ret < 0)
+ DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
return ret;
#else
- return mga_do_wait_for_idle( dev_priv );
+ return mga_do_wait_for_idle(dev_priv);
#endif
} else {
return 0;
}
}
-int mga_dma_reset( DRM_IOCTL_ARGS )
+int mga_dma_reset(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- return mga_do_dma_reset( dev_priv );
+ return mga_do_dma_reset(dev_priv);
}
-
/* ================================================================
* DMA buffer management
*/
-static int mga_dma_get_buffers( DRMFILE filp,
- drm_device_t *dev, drm_dma_t *d )
+static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
{
drm_buf_t *buf;
int i;
- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
- buf = mga_freelist_get( dev );
- if ( !buf ) return DRM_ERR(EAGAIN);
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = mga_freelist_get(dev);
+ if (!buf)
+ return DRM_ERR(EAGAIN);
buf->filp = filp;
- if ( DRM_COPY_TO_USER( &d->request_indices[i],
- &buf->idx, sizeof(buf->idx) ) )
+ if (DRM_COPY_TO_USER(&d->request_indices[i],
+ &buf->idx, sizeof(buf->idx)))
return DRM_ERR(EFAULT);
- if ( DRM_COPY_TO_USER( &d->request_sizes[i],
- &buf->total, sizeof(buf->total) ) )
+ if (DRM_COPY_TO_USER(&d->request_sizes[i],
+ &buf->total, sizeof(buf->total)))
return DRM_ERR(EFAULT);
d->granted_count++;
@@ -700,55 +1073,69 @@ static int mga_dma_get_buffers( DRMFILE filp,
return 0;
}
-int mga_dma_buffers( DRM_IOCTL_ARGS )
+int mga_dma_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
drm_dma_t __user *argp = (void __user *)data;
drm_dma_t d;
int ret = 0;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
+ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
/* Please don't send us buffers.
*/
- if ( d.send_count != 0 ) {
- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
- DRM_CURRENTPID, d.send_count );
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d.send_count);
return DRM_ERR(EINVAL);
}
/* We'll send you buffers.
*/
- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
- DRM_CURRENTPID, d.request_count, dma->buf_count );
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d.request_count, dma->buf_count);
return DRM_ERR(EINVAL);
}
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
d.granted_count = 0;
- if ( d.request_count ) {
- ret = mga_dma_get_buffers( filp, dev, &d );
+ if (d.request_count) {
+ ret = mga_dma_get_buffers(filp, dev, &d);
}
- DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
+ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
return ret;
}
-void mga_driver_pretakedown(drm_device_t *dev)
+/**
+ * Called just before the module is unloaded.
+ */
+int mga_driver_postcleanup(drm_device_t * dev)
+{
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+
+ return 0;
+}
+
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_pretakedown(drm_device_t * dev)
{
- mga_do_cleanup_dma( dev );
+ mga_do_cleanup_dma(dev);
}
-int mga_driver_dma_quiescent(drm_device_t *dev)
+int mga_driver_dma_quiescent(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
- return mga_do_wait_for_idle( dev_priv );
+ return mga_do_wait_for_idle(dev_priv);
}
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
index 521d4451d012..44d1293e2947 100644
--- a/drivers/char/drm/mga_drm.h
+++ b/drivers/char/drm/mga_drm.h
@@ -44,10 +44,10 @@
/* WARP pipe flags
*/
-#define MGA_F 0x1 /* fog */
-#define MGA_A 0x2 /* alpha */
-#define MGA_S 0x4 /* specular */
-#define MGA_T2 0x8 /* multitexture */
+#define MGA_F 0x1 /* fog */
+#define MGA_A 0x2 /* alpha */
+#define MGA_S 0x4 /* specular */
+#define MGA_T2 0x8 /* multitexture */
#define MGA_WARP_TGZ 0
#define MGA_WARP_TGZF (MGA_F)
@@ -66,14 +66,15 @@
#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
-#define MGA_MAX_G200_PIPES 8 /* no multitex */
+#define MGA_MAX_G200_PIPES 8 /* no multitex */
#define MGA_MAX_G400_PIPES 16
#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
-#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
+#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
#define MGA_CARD_TYPE_G200 1
#define MGA_CARD_TYPE_G400 2
-
+#define MGA_CARD_TYPE_G450 3 /* not currently used */
+#define MGA_CARD_TYPE_G550 4
#define MGA_FRONT 0x1
#define MGA_BACK 0x2
@@ -85,14 +86,14 @@
#define MGA_UPLOAD_TEX0 0x2
#define MGA_UPLOAD_TEX1 0x4
#define MGA_UPLOAD_PIPE 0x8
-#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
-#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
+#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
+#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
#define MGA_UPLOAD_2D 0x40
-#define MGA_WAIT_AGE 0x80 /* handled client-side */
-#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
+#define MGA_WAIT_AGE 0x80 /* handled client-side */
+#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
#if 0
-#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
- quiescent */
+#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
+ quiescent */
#endif
/* 32 buffers of 64k each, total 2 meg.
@@ -119,8 +120,7 @@
#define DRM_MGA_IDLE_RETRY 2048
-#endif /* __MGA_SAREA_DEFINES__ */
-
+#endif /* __MGA_SAREA_DEFINES__ */
/* Setup registers for 3D context
*/
@@ -164,25 +164,25 @@ typedef struct {
/* General aging mechanism
*/
typedef struct {
- unsigned int head; /* Position of head pointer */
- unsigned int wrap; /* Primary DMA wrap count */
+ unsigned int head; /* Position of head pointer */
+ unsigned int wrap; /* Primary DMA wrap count */
} drm_mga_age_t;
typedef struct _drm_mga_sarea {
/* The channel for communication of state information to the kernel
* on firing a vertex dma buffer.
*/
- drm_mga_context_regs_t context_state;
- drm_mga_server_regs_t server_state;
- drm_mga_texture_regs_t tex_state[2];
- unsigned int warp_pipe;
- unsigned int dirty;
- unsigned int vertsize;
+ drm_mga_context_regs_t context_state;
+ drm_mga_server_regs_t server_state;
+ drm_mga_texture_regs_t tex_state[2];
+ unsigned int warp_pipe;
+ unsigned int dirty;
+ unsigned int vertsize;
/* The current cliprects, or a subset thereof.
*/
- drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
- unsigned int nbox;
+ drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
/* Information about the most recently used 3d drawable. The
* client fills in the req_* fields, the server fills in the
@@ -191,18 +191,18 @@ typedef struct _drm_mga_sarea {
* The client clears the exported_drawable field before
* clobbering the boxes data.
*/
- unsigned int req_drawable; /* the X drawable id */
- unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
+ unsigned int req_drawable; /* the X drawable id */
+ unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
- unsigned int exported_drawable;
+ unsigned int exported_drawable;
unsigned int exported_index;
- unsigned int exported_stamp;
- unsigned int exported_buffers;
- unsigned int exported_nfront;
- unsigned int exported_nback;
+ unsigned int exported_stamp;
+ unsigned int exported_buffers;
+ unsigned int exported_nfront;
+ unsigned int exported_nback;
int exported_back_x, exported_front_x, exported_w;
int exported_back_y, exported_front_y, exported_h;
- drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+ drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
/* Counters for aging textures and for client-side throttling.
*/
@@ -210,25 +210,20 @@ typedef struct _drm_mga_sarea {
unsigned int last_wrap;
drm_mga_age_t last_frame;
- unsigned int last_enqueue; /* last time a buffer was enqueued */
+ unsigned int last_enqueue; /* last time a buffer was enqueued */
unsigned int last_dispatch; /* age of the most recently dispatched buffer */
- unsigned int last_quiescent; /* */
+ unsigned int last_quiescent; /* */
/* LRU lists for texture memory in agp space and on the card.
*/
- drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
+ drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
unsigned int texAge[MGA_NR_TEX_HEAPS];
/* Mechanism to validate card state.
*/
- int ctxOwner;
+ int ctxOwner;
} drm_mga_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmMga.h)
- */
-
/* MGA specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
@@ -243,6 +238,13 @@ typedef struct _drm_mga_sarea {
#define DRM_MGA_BLIT 0x08
#define DRM_MGA_GETPARAM 0x09
+/* 3.2:
+ * ioctls for operating on fences.
+ */
+#define DRM_MGA_SET_FENCE 0x0a
+#define DRM_MGA_WAIT_FENCE 0x0b
+#define DRM_MGA_DMA_BOOTSTRAP 0x0c
+
#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
@@ -253,35 +255,38 @@ typedef struct _drm_mga_sarea {
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
+#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
typedef struct _drm_mga_warp_index {
- int installed;
- unsigned long phys_addr;
- int size;
+ int installed;
+ unsigned long phys_addr;
+ int size;
} drm_mga_warp_index_t;
typedef struct drm_mga_init {
- enum {
- MGA_INIT_DMA = 0x01,
- MGA_CLEANUP_DMA = 0x02
+ enum {
+ MGA_INIT_DMA = 0x01,
+ MGA_CLEANUP_DMA = 0x02
} func;
- unsigned long sarea_priv_offset;
+ unsigned long sarea_priv_offset;
int chipset;
- int sgram;
+ int sgram;
unsigned int maccess;
- unsigned int fb_cpp;
+ unsigned int fb_cpp;
unsigned int front_offset, front_pitch;
- unsigned int back_offset, back_pitch;
+ unsigned int back_offset, back_pitch;
- unsigned int depth_cpp;
- unsigned int depth_offset, depth_pitch;
+ unsigned int depth_cpp;
+ unsigned int depth_offset, depth_pitch;
- unsigned int texture_offset[MGA_NR_TEX_HEAPS];
- unsigned int texture_size[MGA_NR_TEX_HEAPS];
+ unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+ unsigned int texture_size[MGA_NR_TEX_HEAPS];
unsigned long fb_offset;
unsigned long mmio_offset;
@@ -291,12 +296,67 @@ typedef struct drm_mga_init {
unsigned long buffers_offset;
} drm_mga_init_t;
-typedef struct drm_mga_fullscreen {
- enum {
- MGA_INIT_FULLSCREEN = 0x01,
- MGA_CLEANUP_FULLSCREEN = 0x02
- } func;
-} drm_mga_fullscreen_t;
+typedef struct drm_mga_dma_bootstrap {
+ /**
+ * \name AGP texture region
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
+ * be filled in with the actual AGP texture settings.
+ *
+ * \warning
+ * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
+ * is zero, it means that PCI memory (most likely through the use of
+ * an IOMMU) is being used for "AGP" textures.
+ */
+ /*@{ */
+ unsigned long texture_handle; /**< Handle used to map AGP textures. */
+ uint32_t texture_size; /**< Size of the AGP texture region. */
+ /*@} */
+
+ /**
+ * Requested size of the primary DMA region.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ */
+ uint32_t primary_size;
+
+ /**
+ * Requested number of secondary DMA buffers.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual number of secondary DMA buffers
+ * allocated. Particularly when PCI DMA is used, this may be
+ * (subtantially) less than the number requested.
+ */
+ uint32_t secondary_bin_count;
+
+ /**
+ * Requested size of each secondary DMA buffer.
+ *
+ * While the kernel \b is free to reduce
+ * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
+ * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
+ */
+ uint32_t secondary_bin_size;
+
+ /**
+ * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X,
+ * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is
+ * zero, it means that PCI DMA should be used, even if AGP is
+ * possible.
+ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ * (i.e., PCI DMA was used), this value will be zero.
+ */
+ uint32_t agp_mode;
+
+ /**
+ * Desired AGP GART size, measured in megabytes.
+ */
+ uint8_t agp_size;
+} drm_mga_dma_bootstrap_t;
typedef struct drm_mga_clear {
unsigned int flags;
@@ -307,16 +367,16 @@ typedef struct drm_mga_clear {
} drm_mga_clear_t;
typedef struct drm_mga_vertex {
- int idx; /* buffer to queue */
- int used; /* bytes in use */
- int discard; /* client finished with buffer? */
+ int idx; /* buffer to queue */
+ int used; /* bytes in use */
+ int discard; /* client finished with buffer? */
} drm_mga_vertex_t;
typedef struct drm_mga_indices {
- int idx; /* buffer to queue */
+ int idx; /* buffer to queue */
unsigned int start;
unsigned int end;
- int discard; /* client finished with buffer? */
+ int discard; /* client finished with buffer? */
} drm_mga_indices_t;
typedef struct drm_mga_iload {
@@ -332,15 +392,23 @@ typedef struct _drm_mga_blit {
int src_pitch, dst_pitch;
int delta_sx, delta_sy;
int delta_dx, delta_dy;
- int height, ydir; /* flip image vertically */
+ int height, ydir; /* flip image vertically */
int source_pitch, dest_pitch;
} drm_mga_blit_t;
/* 3.1: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
+ * client any other way.
*/
#define MGA_PARAM_IRQ_NR 1
+/* 3.2: Query the actual card type. The DDX only distinguishes between
+ * G200 chips and non-G200 chips, which it calls G400. It turns out that
+ * there are some very sublte differences between the G4x0 chips and the G550
+ * chips. Using this parameter query, a client-side driver can detect the
+ * difference between a G4x0 and a G550.
+ */
+#define MGA_PARAM_CARD_TYPE 2
+
typedef struct drm_mga_getparam {
int param;
void __user *value;
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 844cca9cb29d..0cc7c305a7f6 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -35,38 +35,42 @@
#include "mga_drm.h"
#include "mga_drv.h"
-
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int mga_driver_device_is_agp(drm_device_t * dev);
+static int postinit(struct drm_device *dev, unsigned long flags)
{
+ drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
+ dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
+
dev->counters += 3;
dev->types[6] = _DRM_STAT_IRQ;
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -74,13 +78,16 @@ static struct pci_device_id pciidlist[] = {
mga_PCI_IDS
};
-extern drm_ioctl_desc_t mga_ioctls[];
-extern int mga_max_ioctl;
-
static struct drm_driver driver = {
- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+ DRIVER_IRQ_VBL,
+ .preinit = mga_driver_preinit,
+ .postcleanup = mga_driver_postcleanup,
.pretakedown = mga_driver_pretakedown,
.dma_quiescent = mga_driver_dma_quiescent,
+ .device_is_agp = mga_driver_device_is_agp,
.vblank_wait = mga_driver_vblank_wait,
.irq_preinstall = mga_driver_irq_preinstall,
.irq_postinstall = mga_driver_irq_postinstall,
@@ -94,21 +101,21 @@ 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,
+ }
};
static int __init mga_init(void)
@@ -125,6 +132,40 @@ static void __exit mga_exit(void)
module_init(mga_init);
module_exit(mga_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * In addition to the usual tests performed by \c drm_device_is_agp, this
+ * function detects PCI G450 cards that appear to the system exactly like
+ * AGP G450 cards.
+ *
+ * \param dev The device to be tested.
+ *
+ * \returns
+ * If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
+ */
+static int mga_driver_device_is_agp(drm_device_t * dev)
+{
+ const struct pci_dev *const pdev = dev->pdev;
+
+ /* There are PCI versions of the G450. These cards have the
+ * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+ * bridge chip. We detect these cards, which are not currently
+ * supported by this driver, by looking at the device ID of the
+ * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the
+ * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+ * device.
+ */
+
+ if ((pdev->device == 0x0525)
+ && (pdev->bus->self->vendor == 0x3388)
+ && (pdev->bus->self->device == 0x0021)) {
+ return 0;
+ }
+
+ return 2;
+}
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 9412e2816eb7..461728e6a58a 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -38,10 +38,10 @@
#define DRIVER_NAME "mga"
#define DRIVER_DESC "Matrox G200/G400"
-#define DRIVER_DATE "20021029"
+#define DRIVER_DATE "20050607"
#define DRIVER_MAJOR 3
-#define DRIVER_MINOR 1
+#define DRIVER_MINOR 2
#define DRIVER_PATCHLEVEL 0
typedef struct drm_mga_primary_buffer {
@@ -62,14 +62,14 @@ typedef struct drm_mga_primary_buffer {
} drm_mga_primary_buffer_t;
typedef struct drm_mga_freelist {
- struct drm_mga_freelist *next;
- struct drm_mga_freelist *prev;
+ struct drm_mga_freelist *next;
+ struct drm_mga_freelist *prev;
drm_mga_age_t age;
- drm_buf_t *buf;
+ drm_buf_t *buf;
} drm_mga_freelist_t;
typedef struct {
- drm_mga_freelist_t *list_entry;
+ drm_mga_freelist_t *list_entry;
int discard;
int dispatched;
} drm_mga_buf_priv_t;
@@ -78,8 +78,8 @@ typedef struct drm_mga_private {
drm_mga_primary_buffer_t prim;
drm_mga_sarea_t *sarea_priv;
- drm_mga_freelist_t *head;
- drm_mga_freelist_t *tail;
+ drm_mga_freelist_t *head;
+ drm_mga_freelist_t *tail;
unsigned int warp_pipe;
unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
@@ -87,9 +87,43 @@ typedef struct drm_mga_private {
int chipset;
int usec_timeout;
+ /**
+ * If set, the new DMA initialization sequence was used. This is
+ * primarilly used to select how the driver should uninitialized its
+ * internal DMA structures.
+ */
+ int used_new_dma_init;
+
+ /**
+ * If AGP memory is used for DMA buffers, this will be the value
+ * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer).
+ */
+ u32 dma_access;
+
+ /**
+ * If AGP memory is used for DMA buffers, this will be the value
+ * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI
+ * transfer).
+ */
+ u32 wagp_enable;
+
+ /**
+ * \name MMIO region parameters.
+ *
+ * \sa drm_mga_private_t::mmio
+ */
+ /*@{ */
+ u32 mmio_base; /**< Bus address of base of MMIO. */
+ u32 mmio_size; /**< Size of the MMIO region. */
+ /*@} */
+
u32 clear_cmd;
u32 maccess;
+ wait_queue_head_t fence_queue;
+ atomic_t last_fence_retired;
+ u32 next_fence_to_post;
+
unsigned int fb_cpp;
unsigned int front_offset;
unsigned int front_pitch;
@@ -108,35 +142,46 @@ typedef struct drm_mga_private {
drm_local_map_t *status;
drm_local_map_t *warp;
drm_local_map_t *primary;
- drm_local_map_t *buffers;
drm_local_map_t *agp_textures;
+
+ DRM_AGP_MEM *agp_mem;
+ unsigned int agp_pages;
} drm_mga_private_t;
+extern drm_ioctl_desc_t mga_ioctls[];
+extern int mga_max_ioctl;
+
/* mga_dma.c */
-extern int mga_dma_init( DRM_IOCTL_ARGS );
-extern int mga_dma_flush( DRM_IOCTL_ARGS );
-extern int mga_dma_reset( DRM_IOCTL_ARGS );
-extern int mga_dma_buffers( DRM_IOCTL_ARGS );
-extern void mga_driver_pretakedown(drm_device_t *dev);
-extern int mga_driver_dma_quiescent(drm_device_t *dev);
+extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags);
+extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
+extern int mga_dma_init(DRM_IOCTL_ARGS);
+extern int mga_dma_flush(DRM_IOCTL_ARGS);
+extern int mga_dma_reset(DRM_IOCTL_ARGS);
+extern int mga_dma_buffers(DRM_IOCTL_ARGS);
+extern int mga_driver_postcleanup(drm_device_t * dev);
+extern void mga_driver_pretakedown(drm_device_t * dev);
+extern int mga_driver_dma_quiescent(drm_device_t * dev);
-extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
+extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
-extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
-extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
-extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
+extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
-extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
+extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
/* mga_warp.c */
-extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
-extern int mga_warp_init( drm_mga_private_t *dev_priv );
-
-extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
-extern void mga_driver_irq_preinstall( drm_device_t *dev );
-extern void mga_driver_irq_postinstall( drm_device_t *dev );
-extern void mga_driver_irq_uninstall( drm_device_t *dev );
+extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+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_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern void mga_driver_irq_preinstall(drm_device_t * dev);
+extern void mga_driver_irq_postinstall(drm_device_t * dev);
+extern void mga_driver_irq_uninstall(drm_device_t * dev);
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -154,7 +199,7 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
-static inline u32 _MGA_READ(u32 *addr)
+static inline u32 _MGA_READ(u32 * addr)
{
DRM_MEMORYBARRIER();
return *(volatile u32 *)addr;
@@ -176,8 +221,6 @@ static inline u32 _MGA_READ(u32 *addr)
#define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
#define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
-
-
/* ================================================================
* Helper macross...
*/
@@ -185,7 +228,7 @@ static inline u32 _MGA_READ(u32 *addr)
#define MGA_EMIT_STATE( dev_priv, dirty ) \
do { \
if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) { \
- if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { \
+ if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) { \
mga_g400_emit_state( dev_priv ); \
} else { \
mga_g200_emit_state( dev_priv ); \
@@ -219,7 +262,6 @@ do { \
} \
} while (0)
-
/* ================================================================
* Primary DMA command stream
*/
@@ -304,7 +346,6 @@ do { \
write += DMA_BLOCK_SIZE; \
} while (0)
-
/* Buffer aging via primary DMA stream head pointer.
*/
@@ -331,7 +372,6 @@ do { \
} \
} while (0)
-
#define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \
MGA_DWGENGSTS | \
MGA_ENDPRDMASTS)
@@ -340,8 +380,6 @@ do { \
#define MGA_DMA_DEBUG 0
-
-
/* A reduced set of the mga registers.
*/
#define MGA_CRTC_INDEX 0x1fd4
@@ -527,6 +565,12 @@ do { \
*/
#define MGA_EXEC 0x0100
+/* AGP PLL encoding (for G200 only).
+ */
+#define MGA_AGP_PLL 0x1e4c
+# define MGA_AGP2XPLL_DISABLE (0 << 0)
+# define MGA_AGP2XPLL_ENABLE (1 << 0)
+
/* Warp registers
*/
#define MGA_WR0 0x2d00
@@ -596,7 +640,6 @@ do { \
# define MGA_G400_WR_MAGIC (1 << 6)
# define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */
-
#define MGA_ILOAD_ALIGN 64
#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
@@ -631,10 +674,10 @@ do { \
/* Simple idle test.
*/
-static __inline__ int mga_is_idle( drm_mga_private_t *dev_priv )
+static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
{
- u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
- return ( status == MGA_ENDPRDMASTS );
+ u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+ return (status == MGA_ENDPRDMASTS);
}
#endif
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index bc745cfa2095..24a9d4e86af0 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -39,17 +39,17 @@
typedef struct drm32_mga_init {
int func;
- u32 sarea_priv_offset;
+ u32 sarea_priv_offset;
int chipset;
- int sgram;
+ int sgram;
unsigned int maccess;
- unsigned int fb_cpp;
+ unsigned int fb_cpp;
unsigned int front_offset, front_pitch;
- unsigned int back_offset, back_pitch;
- unsigned int depth_cpp;
- unsigned int depth_offset, depth_pitch;
- unsigned int texture_offset[MGA_NR_TEX_HEAPS];
- unsigned int texture_size[MGA_NR_TEX_HEAPS];
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_cpp;
+ unsigned int depth_offset, depth_pitch;
+ unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+ unsigned int texture_size[MGA_NR_TEX_HEAPS];
u32 fb_offset;
u32 mmio_offset;
u32 status_offset;
@@ -64,10 +64,10 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
drm_mga_init32_t init32;
drm_mga_init_t __user *init;
int err = 0, i;
-
+
if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
return -EFAULT;
-
+
init = compat_alloc_user_space(sizeof(*init));
if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
|| __put_user(init32.func, &init->func)
@@ -90,48 +90,114 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
|| __put_user(init32.primary_offset, &init->primary_offset)
|| __put_user(init32.buffers_offset, &init->buffers_offset))
return -EFAULT;
-
- for (i=0; i<MGA_NR_TEX_HEAPS; i++)
- {
- err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]);
- err |= __put_user(init32.texture_size[i], &init->texture_size[i]);
+
+ for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
+ err |=
+ __put_user(init32.texture_offset[i],
+ &init->texture_offset[i]);
+ err |=
+ __put_user(init32.texture_size[i], &init->texture_size[i]);
}
if (err)
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_MGA_INIT, (unsigned long) init);
+ DRM_IOCTL_MGA_INIT, (unsigned long)init);
}
-
typedef struct drm_mga_getparam32 {
int param;
u32 value;
} drm_mga_getparam32_t;
-
static int compat_mga_getparam(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_mga_getparam32_t getparam32;
drm_mga_getparam_t __user *getparam;
-
+
if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
return -EFAULT;
getparam = compat_alloc_user_space(sizeof(*getparam));
if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
|| __put_user(getparam32.param, &getparam->param)
- || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
+ || __put_user((void __user *)(unsigned long)getparam32.value,
+ &getparam->value))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
}
+typedef struct drm_mga_drm_bootstrap32 {
+ u32 texture_handle;
+ u32 texture_size;
+ u32 primary_size;
+ u32 secondary_bin_count;
+ u32 secondary_bin_size;
+ u32 agp_mode;
+ u8 agp_size;
+} drm_mga_dma_bootstrap32_t;
+
+static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_mga_dma_bootstrap32_t dma_bootstrap32;
+ drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+ int err;
+
+ if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
+ if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
+ || __put_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __put_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __put_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __put_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __put_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+ || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+ (unsigned long)dma_bootstrap);
+ if (err)
+ return err;
+
+ if (__get_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __get_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __get_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __get_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __get_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+ || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ return 0;
+}
+
drm_ioctl_compat_t *mga_compat_ioctls[] = {
[DRM_MGA_INIT] = compat_mga_init,
[DRM_MGA_GETPARAM] = compat_mga_getparam,
+ [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
};
/**
@@ -143,8 +209,7 @@ drm_ioctl_compat_t *mga_compat_ioctls[] = {
* \param arg user argument.
* \return zero on success or negative number on failure.
*/
-long mga_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned int nr = DRM_IOCTL_NR(cmd);
drm_ioctl_compat_t *fn = NULL;
@@ -152,13 +217,13 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd,
if (nr < DRM_COMMAND_BASE)
return drm_compat_ioctl(filp, cmd, arg);
-
+
if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
lock_kernel(); /* XXX for now */
if (fn != NULL)
- ret = (*fn)(filp, cmd, arg);
+ ret = (*fn) (filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index bc0b6b5d43a6..eb9644024172 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -1,7 +1,7 @@
/* 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
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
@@ -35,68 +35,114 @@
#include "mga_drm.h"
#include "mga_drv.h"
-irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *) arg;
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
int status;
+ int handled = 0;
+
+ status = MGA_READ(MGA_STATUS);
- status = MGA_READ( MGA_STATUS );
-
/* VBLANK interrupt */
- if ( status & MGA_VLINEPEN ) {
- MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
+ 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 );
+ drm_vbl_send_signals(dev);
+ handled = 1;
+ }
+
+ /* SOFTRAP interrupt */
+ if (status & MGA_SOFTRAPEN) {
+ 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
+ * have to write to MGA_PRIMEND to re-start the DMA operation.
+ */
+ if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
+ MGA_WRITE(MGA_PRIMEND, prim_end);
+ }
+
+ atomic_inc(&dev_priv->last_fence_retired);
+ DRM_WAKEUP(&dev_priv->fence_queue);
+ handled = 1;
+ }
+
+ if (handled) {
return IRQ_HANDLED;
}
return IRQ_NONE;
}
-int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
{
unsigned int cur_vblank;
int ret = 0;
/* 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...
+ * using vertical blanks...
*/
- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
- - *sequence ) <= (1<<23) ) );
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received))
+ - *sequence) <= (1 << 23)));
*sequence = cur_vblank;
return ret;
}
-void mga_driver_irq_preinstall( drm_device_t *dev ) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ unsigned int cur_fence;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+ * using fences.
+ */
+ DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+ (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
+ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_fence;
+
+ return ret;
+}
+
+void mga_driver_irq_preinstall(drm_device_t * dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
/* Disable *all* interrupts */
- MGA_WRITE( MGA_IEN, 0 );
+ MGA_WRITE(MGA_IEN, 0);
/* Clear bits if they're already high */
- MGA_WRITE( MGA_ICLEAR, ~0 );
+ MGA_WRITE(MGA_ICLEAR, ~0);
}
-void mga_driver_irq_postinstall( drm_device_t *dev ) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+void mga_driver_irq_postinstall(drm_device_t * dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+ DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
- /* Turn on VBL interrupt */
- MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+ /* Turn on vertical blank interrupt and soft trap interrupt. */
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
}
-void mga_driver_irq_uninstall( drm_device_t *dev ) {
- drm_mga_private_t *dev_priv =
- (drm_mga_private_t *)dev->dev_private;
+void mga_driver_irq_uninstall(drm_device_t * dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
if (!dev_priv)
return;
/* Disable *all* interrupts */
- MGA_WRITE( MGA_IEN, 0 );
+ MGA_WRITE(MGA_IEN, 0);
+
+ dev->irq_enabled = 0;
}
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 3c7a8f5ba501..47f54b5ae956 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -41,121 +41,110 @@
* DMA hardware state programming functions
*/
-static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
- drm_clip_rect_t *box )
+static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
+ drm_clip_rect_t * box)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
unsigned int pitch = dev_priv->front_pitch;
DMA_LOCALS;
- BEGIN_DMA( 2 );
+ BEGIN_DMA(2);
/* Force reset of DWGCTL on G400 (eliminates clip disable bit).
*/
- if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
- DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl,
- MGA_LEN + MGA_EXEC, 0x80000000,
- MGA_DWGCTL, ctx->dwgctl,
- MGA_LEN + MGA_EXEC, 0x80000000 );
+ if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+ DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000,
+ MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000);
}
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_CXBNDRY, (box->x2 << 16) | box->x1,
- MGA_YTOP, box->y1 * pitch,
- MGA_YBOT, box->y2 * pitch );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+ MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
ADVANCE_DMA();
}
-static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
DMA_LOCALS;
- BEGIN_DMA( 3 );
+ BEGIN_DMA(3);
- DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
- MGA_MACCESS, ctx->maccess,
- MGA_PLNWT, ctx->plnwt,
- MGA_DWGCTL, ctx->dwgctl );
+ DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+ MGA_MACCESS, ctx->maccess,
+ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
- DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
- MGA_FOGCOL, ctx->fogcolor,
- MGA_WFLAG, ctx->wflag,
- MGA_ZORG, dev_priv->depth_offset );
+ DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+ MGA_FOGCOL, ctx->fogcolor,
+ MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
- DMA_BLOCK( MGA_FCOL, ctx->fcol,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_FCOL, ctx->fcol,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
ADVANCE_DMA();
}
-static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
DMA_LOCALS;
- BEGIN_DMA( 4 );
+ BEGIN_DMA(4);
- DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
- MGA_MACCESS, ctx->maccess,
- MGA_PLNWT, ctx->plnwt,
- MGA_DWGCTL, ctx->dwgctl );
+ DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+ MGA_MACCESS, ctx->maccess,
+ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
- DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
- MGA_FOGCOL, ctx->fogcolor,
- MGA_WFLAG, ctx->wflag,
- MGA_ZORG, dev_priv->depth_offset );
+ DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+ MGA_FOGCOL, ctx->fogcolor,
+ MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
- DMA_BLOCK( MGA_WFLAG1, ctx->wflag,
- MGA_TDUALSTAGE0, ctx->tdualstage0,
- MGA_TDUALSTAGE1, ctx->tdualstage1,
- MGA_FCOL, ctx->fcol );
+ DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
+ MGA_TDUALSTAGE0, ctx->tdualstage0,
+ MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
- DMA_BLOCK( MGA_STENCIL, ctx->stencil,
- MGA_STENCILCTL, ctx->stencilctl,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_STENCIL, ctx->stencil,
+ MGA_STENCILCTL, ctx->stencilctl,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
ADVANCE_DMA();
}
-static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
DMA_LOCALS;
- BEGIN_DMA( 4 );
+ BEGIN_DMA(4);
- DMA_BLOCK( MGA_TEXCTL2, tex->texctl2,
- MGA_TEXCTL, tex->texctl,
- MGA_TEXFILTER, tex->texfilter,
- MGA_TEXBORDERCOL, tex->texbordercol );
+ DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol);
- DMA_BLOCK( MGA_TEXORG, tex->texorg,
- MGA_TEXORG1, tex->texorg1,
- MGA_TEXORG2, tex->texorg2,
- MGA_TEXORG3, tex->texorg3 );
+ DMA_BLOCK(MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
- MGA_TEXWIDTH, tex->texwidth,
- MGA_TEXHEIGHT, tex->texheight,
- MGA_WR24, tex->texwidth );
+ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
- DMA_BLOCK( MGA_WR34, tex->texheight,
- MGA_TEXTRANS, 0x0000ffff,
- MGA_TEXTRANSHIGH, 0x0000ffff,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_WR34, tex->texheight,
+ MGA_TEXTRANS, 0x0000ffff,
+ MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
ADVANCE_DMA();
}
-static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
@@ -164,42 +153,38 @@ static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
/* tex->texctl, tex->texctl2); */
- BEGIN_DMA( 6 );
+ BEGIN_DMA(6);
- DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
- MGA_TEXCTL, tex->texctl,
- MGA_TEXFILTER, tex->texfilter,
- MGA_TEXBORDERCOL, tex->texbordercol );
+ DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol);
- DMA_BLOCK( MGA_TEXORG, tex->texorg,
- MGA_TEXORG1, tex->texorg1,
- MGA_TEXORG2, tex->texorg2,
- MGA_TEXORG3, tex->texorg3 );
+ DMA_BLOCK(MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
- MGA_TEXWIDTH, tex->texwidth,
- MGA_TEXHEIGHT, tex->texheight,
- MGA_WR49, 0x00000000 );
+ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
- DMA_BLOCK( MGA_WR57, 0x00000000,
- MGA_WR53, 0x00000000,
- MGA_WR61, 0x00000000,
- MGA_WR52, MGA_G400_WR_MAGIC );
+ DMA_BLOCK(MGA_WR57, 0x00000000,
+ MGA_WR53, 0x00000000,
+ MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
- DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC,
- MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
- MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
+ MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
+ MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
+ MGA_DMAPAD, 0x00000000);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_TEXTRANS, 0x0000ffff,
- MGA_TEXTRANSHIGH, 0x0000ffff );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
ADVANCE_DMA();
}
-static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
@@ -208,69 +193,64 @@ static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */
/* tex->texctl, tex->texctl2); */
- BEGIN_DMA( 5 );
+ BEGIN_DMA(5);
- DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 |
- MGA_MAP1_ENABLE |
- MGA_G400_TC2_MAGIC),
- MGA_TEXCTL, tex->texctl,
- MGA_TEXFILTER, tex->texfilter,
- MGA_TEXBORDERCOL, tex->texbordercol );
+ DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
+ MGA_MAP1_ENABLE |
+ MGA_G400_TC2_MAGIC),
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol);
- DMA_BLOCK( MGA_TEXORG, tex->texorg,
- MGA_TEXORG1, tex->texorg1,
- MGA_TEXORG2, tex->texorg2,
- MGA_TEXORG3, tex->texorg3 );
+ DMA_BLOCK(MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
- MGA_TEXWIDTH, tex->texwidth,
- MGA_TEXHEIGHT, tex->texheight,
- MGA_WR49, 0x00000000 );
+ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
- DMA_BLOCK( MGA_WR57, 0x00000000,
- MGA_WR53, 0x00000000,
- MGA_WR61, 0x00000000,
- MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC );
+ DMA_BLOCK(MGA_WR57, 0x00000000,
+ MGA_WR53, 0x00000000,
+ MGA_WR61, 0x00000000,
+ MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
- DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
- MGA_TEXTRANS, 0x0000ffff,
- MGA_TEXTRANSHIGH, 0x0000ffff,
- MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC );
+ DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
+ MGA_TEXTRANS, 0x0000ffff,
+ MGA_TEXTRANSHIGH, 0x0000ffff,
+ MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
ADVANCE_DMA();
}
-static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->warp_pipe;
DMA_LOCALS;
- BEGIN_DMA( 3 );
+ BEGIN_DMA(3);
- DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND,
- MGA_WVRTXSZ, 0x00000007,
- MGA_WFLAG, 0x00000000,
- MGA_WR24, 0x00000000 );
+ DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
+ MGA_WVRTXSZ, 0x00000007,
+ MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
- DMA_BLOCK( MGA_WR25, 0x00000100,
- MGA_WR34, 0x00000000,
- MGA_WR42, 0x0000ffff,
- MGA_WR60, 0x0000ffff );
+ DMA_BLOCK(MGA_WR25, 0x00000100,
+ MGA_WR34, 0x00000000,
+ MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
/* Padding required to to hardware bug.
*/
- DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
- MGA_WMODE_START |
- MGA_WAGP_ENABLE) );
+ DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START | dev_priv->wagp_enable));
ADVANCE_DMA();
}
-static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->warp_pipe;
@@ -278,145 +258,139 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
/* printk("mga_g400_emit_pipe %x\n", pipe); */
- BEGIN_DMA( 10 );
+ BEGIN_DMA(10);
- DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
- if ( pipe & MGA_T2 ) {
- DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ if (pipe & MGA_T2) {
+ DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
- DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x1e000000 );
+ DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x1e000000);
} else {
- if ( dev_priv->warp_pipe & MGA_T2 ) {
+ if (dev_priv->warp_pipe & MGA_T2) {
/* Flush the WARP pipe */
- DMA_BLOCK( MGA_YDST, 0x00000000,
- MGA_FXLEFT, 0x00000000,
- MGA_FXRIGHT, 0x00000001,
- MGA_DWGCTL, MGA_DWGCTL_FLUSH );
-
- DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001,
- MGA_DWGSYNC, 0x00007000,
- MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
- MGA_LEN + MGA_EXEC, 0x00000000 );
-
- DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX |
- MGA_G400_TC2_MAGIC),
- MGA_LEN + MGA_EXEC, 0x00000000,
- MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_YDST, 0x00000000,
+ MGA_FXLEFT, 0x00000000,
+ MGA_FXRIGHT, 0x00000001,
+ MGA_DWGCTL, MGA_DWGCTL_FLUSH);
+
+ DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
+ MGA_DWGSYNC, 0x00007000,
+ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+ MGA_LEN + MGA_EXEC, 0x00000000);
+
+ DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
+ MGA_G400_TC2_MAGIC),
+ MGA_LEN + MGA_EXEC, 0x00000000,
+ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+ MGA_DMAPAD, 0x00000000);
}
- DMA_BLOCK( MGA_WVRTXSZ, 0x00001807,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
- DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x00000000,
- MGA_WACCEPTSEQ, 0x18000000 );
+ DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x18000000);
}
- DMA_BLOCK( MGA_WFLAG, 0x00000000,
- MGA_WFLAG1, 0x00000000,
- MGA_WR56, MGA_G400_WR56_MAGIC,
- MGA_DMAPAD, 0x00000000 );
+ DMA_BLOCK(MGA_WFLAG, 0x00000000,
+ MGA_WFLAG1, 0x00000000,
+ MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
- DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0 */
- MGA_WR57, 0x00000000, /* tex0 */
- MGA_WR53, 0x00000000, /* tex1 */
- MGA_WR61, 0x00000000 ); /* tex1 */
+ DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */
+ MGA_WR57, 0x00000000, /* tex0 */
+ MGA_WR53, 0x00000000, /* tex1 */
+ MGA_WR61, 0x00000000); /* tex1 */
- DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
- MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
- MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
- MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */
+ DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
+ MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
+ MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
+ MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */
/* Padding required to to hardware bug */
- DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_DMAPAD, 0xffffffff,
- MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
- MGA_WMODE_START |
- MGA_WAGP_ENABLE) );
+ DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START | dev_priv->wagp_enable));
ADVANCE_DMA();
}
-static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
+static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
- if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
- mga_g200_emit_pipe( dev_priv );
+ if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+ mga_g200_emit_pipe(dev_priv);
dev_priv->warp_pipe = sarea_priv->warp_pipe;
}
- if ( dirty & MGA_UPLOAD_CONTEXT ) {
- mga_g200_emit_context( dev_priv );
+ if (dirty & MGA_UPLOAD_CONTEXT) {
+ mga_g200_emit_context(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
}
- if ( dirty & MGA_UPLOAD_TEX0 ) {
- mga_g200_emit_tex0( dev_priv );
+ if (dirty & MGA_UPLOAD_TEX0) {
+ mga_g200_emit_tex0(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
}
}
-static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
+static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
int multitex = sarea_priv->warp_pipe & MGA_T2;
- if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
- mga_g400_emit_pipe( dev_priv );
+ if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+ mga_g400_emit_pipe(dev_priv);
dev_priv->warp_pipe = sarea_priv->warp_pipe;
}
- if ( dirty & MGA_UPLOAD_CONTEXT ) {
- mga_g400_emit_context( dev_priv );
+ if (dirty & MGA_UPLOAD_CONTEXT) {
+ mga_g400_emit_context(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
}
- if ( dirty & MGA_UPLOAD_TEX0 ) {
- mga_g400_emit_tex0( dev_priv );
+ if (dirty & MGA_UPLOAD_TEX0) {
+ mga_g400_emit_tex0(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
}
- if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
- mga_g400_emit_tex1( dev_priv );
+ if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+ mga_g400_emit_tex1(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
}
}
-
/* ================================================================
* SAREA state verification
*/
/* Disallow all write destinations except the front and backbuffer.
*/
-static int mga_verify_context( drm_mga_private_t *dev_priv )
+static int mga_verify_context(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
- if ( ctx->dstorg != dev_priv->front_offset &&
- ctx->dstorg != dev_priv->back_offset ) {
- DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n",
- ctx->dstorg, dev_priv->front_offset,
- dev_priv->back_offset );
+ if (ctx->dstorg != dev_priv->front_offset &&
+ ctx->dstorg != dev_priv->back_offset) {
+ DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
+ ctx->dstorg, dev_priv->front_offset,
+ dev_priv->back_offset);
ctx->dstorg = 0;
return DRM_ERR(EINVAL);
}
@@ -426,7 +400,7 @@ static int mga_verify_context( drm_mga_private_t *dev_priv )
/* Disallow texture reads from PCI space.
*/
-static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
+static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
@@ -434,9 +408,8 @@ static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
- if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
- DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
- tex->texorg, unit );
+ if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
+ DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
tex->texorg = 0;
return DRM_ERR(EINVAL);
}
@@ -444,73 +417,70 @@ static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
return 0;
}
-static int mga_verify_state( drm_mga_private_t *dev_priv )
+static int mga_verify_state(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
int ret = 0;
- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
- if ( dirty & MGA_UPLOAD_CONTEXT )
- ret |= mga_verify_context( dev_priv );
+ if (dirty & MGA_UPLOAD_CONTEXT)
+ ret |= mga_verify_context(dev_priv);
- if ( dirty & MGA_UPLOAD_TEX0 )
- ret |= mga_verify_tex( dev_priv, 0 );
+ if (dirty & MGA_UPLOAD_TEX0)
+ ret |= mga_verify_tex(dev_priv, 0);
- if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
- if ( dirty & MGA_UPLOAD_TEX1 )
- ret |= mga_verify_tex( dev_priv, 1 );
+ if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+ if (dirty & MGA_UPLOAD_TEX1)
+ ret |= mga_verify_tex(dev_priv, 1);
- if ( dirty & MGA_UPLOAD_PIPE )
- ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
+ if (dirty & MGA_UPLOAD_PIPE)
+ ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
} else {
- if ( dirty & MGA_UPLOAD_PIPE )
- ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
+ if (dirty & MGA_UPLOAD_PIPE)
+ ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
}
- return ( ret == 0 );
+ return (ret == 0);
}
-static int mga_verify_iload( drm_mga_private_t *dev_priv,
- unsigned int dstorg, unsigned int length )
+static int mga_verify_iload(drm_mga_private_t * dev_priv,
+ unsigned int dstorg, unsigned int length)
{
- if ( dstorg < dev_priv->texture_offset ||
- dstorg + length > (dev_priv->texture_offset +
- dev_priv->texture_size) ) {
- DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
+ if (dstorg < dev_priv->texture_offset ||
+ dstorg + length > (dev_priv->texture_offset +
+ dev_priv->texture_size)) {
+ DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
return DRM_ERR(EINVAL);
}
- if ( length & MGA_ILOAD_MASK ) {
- DRM_ERROR( "*** bad iload length: 0x%x\n",
- length & MGA_ILOAD_MASK );
+ if (length & MGA_ILOAD_MASK) {
+ DRM_ERROR("*** bad iload length: 0x%x\n",
+ length & MGA_ILOAD_MASK);
return DRM_ERR(EINVAL);
}
return 0;
}
-static int mga_verify_blit( drm_mga_private_t *dev_priv,
- unsigned int srcorg, unsigned int dstorg )
+static int mga_verify_blit(drm_mga_private_t * dev_priv,
+ unsigned int srcorg, unsigned int dstorg)
{
- if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
- (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
- DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
- srcorg, dstorg );
+ if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+ (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
+ DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
return DRM_ERR(EINVAL);
}
return 0;
}
-
/* ================================================================
*
*/
-static void mga_dma_dispatch_clear( drm_device_t *dev,
- drm_mga_clear_t *clear )
+static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -519,92 +489,86 @@ static void mga_dma_dispatch_clear( drm_device_t *dev,
int nbox = sarea_priv->nbox;
int i;
DMA_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- BEGIN_DMA( 1 );
+ BEGIN_DMA(1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DWGSYNC, 0x00007100,
- MGA_DWGSYNC, 0x00007000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
ADVANCE_DMA();
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
drm_clip_rect_t *box = &pbox[i];
u32 height = box->y2 - box->y1;
- DRM_DEBUG( " from=%d,%d to=%d,%d\n",
- box->x1, box->y1, box->x2, box->y2 );
+ DRM_DEBUG(" from=%d,%d to=%d,%d\n",
+ box->x1, box->y1, box->x2, box->y2);
- if ( clear->flags & MGA_FRONT ) {
- BEGIN_DMA( 2 );
+ if (clear->flags & MGA_FRONT) {
+ BEGIN_DMA(2);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, clear->color_mask,
- MGA_YDSTLEN, (box->y1 << 16) | height,
- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->color_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_FCOL, clear->clear_color,
- MGA_DSTORG, dev_priv->front_offset,
- MGA_DWGCTL + MGA_EXEC,
- dev_priv->clear_cmd );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_color,
+ MGA_DSTORG, dev_priv->front_offset,
+ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
ADVANCE_DMA();
}
+ if (clear->flags & MGA_BACK) {
+ BEGIN_DMA(2);
- if ( clear->flags & MGA_BACK ) {
- BEGIN_DMA( 2 );
-
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, clear->color_mask,
- MGA_YDSTLEN, (box->y1 << 16) | height,
- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->color_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_FCOL, clear->clear_color,
- MGA_DSTORG, dev_priv->back_offset,
- MGA_DWGCTL + MGA_EXEC,
- dev_priv->clear_cmd );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_color,
+ MGA_DSTORG, dev_priv->back_offset,
+ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
ADVANCE_DMA();
}
- if ( clear->flags & MGA_DEPTH ) {
- BEGIN_DMA( 2 );
+ if (clear->flags & MGA_DEPTH) {
+ BEGIN_DMA(2);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, clear->depth_mask,
- MGA_YDSTLEN, (box->y1 << 16) | height,
- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->depth_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_FCOL, clear->clear_depth,
- MGA_DSTORG, dev_priv->depth_offset,
- MGA_DWGCTL + MGA_EXEC,
- dev_priv->clear_cmd );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_depth,
+ MGA_DSTORG, dev_priv->depth_offset,
+ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
ADVANCE_DMA();
}
}
- BEGIN_DMA( 1 );
+ BEGIN_DMA(1);
/* Force reset of DWGCTL */
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, ctx->plnwt,
- MGA_DWGCTL, ctx->dwgctl );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
ADVANCE_DMA();
FLUSH_DMA();
}
-static void mga_dma_dispatch_swap( drm_device_t *dev )
+static void mga_dma_dispatch_swap(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -613,56 +577,52 @@ static void mga_dma_dispatch_swap( drm_device_t *dev )
int nbox = sarea_priv->nbox;
int i;
DMA_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
sarea_priv->last_frame.head = dev_priv->prim.tail;
sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
- BEGIN_DMA( 4 + nbox );
+ BEGIN_DMA(4 + nbox);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DWGSYNC, 0x00007100,
- MGA_DWGSYNC, 0x00007000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
- DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset,
- MGA_MACCESS, dev_priv->maccess,
- MGA_SRCORG, dev_priv->back_offset,
- MGA_AR5, dev_priv->front_pitch );
+ DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
+ MGA_MACCESS, dev_priv->maccess,
+ MGA_SRCORG, dev_priv->back_offset,
+ MGA_AR5, dev_priv->front_pitch);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, 0xffffffff,
- MGA_DWGCTL, MGA_DWGCTL_COPY );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
drm_clip_rect_t *box = &pbox[i];
u32 height = box->y2 - box->y1;
u32 start = box->y1 * dev_priv->front_pitch;
- DRM_DEBUG( " from=%d,%d to=%d,%d\n",
- box->x1, box->y1, box->x2, box->y2 );
+ DRM_DEBUG(" from=%d,%d to=%d,%d\n",
+ box->x1, box->y1, box->x2, box->y2);
- DMA_BLOCK( MGA_AR0, start + box->x2 - 1,
- MGA_AR3, start + box->x1,
- MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
- MGA_YDSTLEN + MGA_EXEC,
- (box->y1 << 16) | height );
+ DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
+ MGA_AR3, start + box->x1,
+ MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+ MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
}
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, ctx->plnwt,
- MGA_SRCORG, dev_priv->front_offset,
- MGA_DWGCTL, ctx->dwgctl );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
ADVANCE_DMA();
FLUSH_DMA();
- DRM_DEBUG( "%s... done.\n", __FUNCTION__ );
+ DRM_DEBUG("%s... done.\n", __FUNCTION__);
}
-static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
+static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -671,46 +631,46 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
u32 length = (u32) buf->used;
int i = 0;
DMA_LOCALS;
- DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used );
+ DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used);
- if ( buf->used ) {
+ if (buf->used) {
buf_priv->dispatched = 1;
- MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
+ MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
do {
- if ( i < sarea_priv->nbox ) {
- mga_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
+ if (i < sarea_priv->nbox) {
+ mga_emit_clip_rect(dev_priv,
+ &sarea_priv->boxes[i]);
}
- BEGIN_DMA( 1 );
+ BEGIN_DMA(1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_SECADDRESS, (address |
- MGA_DMA_VERTEX),
- MGA_SECEND, ((address + length) |
- MGA_PAGPXFER) );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SECADDRESS, (address |
+ MGA_DMA_VERTEX),
+ MGA_SECEND, ((address + length) |
+ dev_priv->dma_access));
ADVANCE_DMA();
- } while ( ++i < sarea_priv->nbox );
+ } while (++i < sarea_priv->nbox);
}
- if ( buf_priv->discard ) {
- AGE_BUFFER( buf_priv );
+ if (buf_priv->discard) {
+ AGE_BUFFER(buf_priv);
buf->pending = 0;
buf->used = 0;
buf_priv->dispatched = 0;
- mga_freelist_put( dev, buf );
+ mga_freelist_put(dev, buf);
}
FLUSH_DMA();
}
-static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
- unsigned int start, unsigned int end )
+static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+ unsigned int start, unsigned int end)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -718,38 +678,38 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
u32 address = (u32) buf->bus_address;
int i = 0;
DMA_LOCALS;
- DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end );
+ DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end);
- if ( start != end ) {
+ if (start != end) {
buf_priv->dispatched = 1;
- MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
+ MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
do {
- if ( i < sarea_priv->nbox ) {
- mga_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
+ if (i < sarea_priv->nbox) {
+ mga_emit_clip_rect(dev_priv,
+ &sarea_priv->boxes[i]);
}
- BEGIN_DMA( 1 );
+ BEGIN_DMA(1);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_SETUPADDRESS, address + start,
- MGA_SETUPEND, ((address + end) |
- MGA_PAGPXFER) );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SETUPADDRESS, address + start,
+ MGA_SETUPEND, ((address + end) |
+ dev_priv->dma_access));
ADVANCE_DMA();
- } while ( ++i < sarea_priv->nbox );
+ } while (++i < sarea_priv->nbox);
}
- if ( buf_priv->discard ) {
- AGE_BUFFER( buf_priv );
+ if (buf_priv->discard) {
+ AGE_BUFFER(buf_priv);
buf->pending = 0;
buf->used = 0;
buf_priv->dispatched = 0;
- mga_freelist_put( dev, buf );
+ mga_freelist_put(dev, buf);
}
FLUSH_DMA();
@@ -758,61 +718,55 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
/* This copies a 64 byte aligned agp region to the frambuffer with a
* standard blit, the ioctl needs to do checking.
*/
-static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
- unsigned int dstorg, unsigned int length )
+static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
+ unsigned int dstorg, unsigned int length)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
- u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
+ u32 srcorg =
+ buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
u32 y2;
DMA_LOCALS;
- DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
+ DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
y2 = length / 64;
- BEGIN_DMA( 5 );
+ BEGIN_DMA(5);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DWGSYNC, 0x00007100,
- MGA_DWGSYNC, 0x00007000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
- DMA_BLOCK( MGA_DSTORG, dstorg,
- MGA_MACCESS, 0x00000000,
- MGA_SRCORG, srcorg,
- MGA_AR5, 64 );
+ DMA_BLOCK(MGA_DSTORG, dstorg,
+ MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
- DMA_BLOCK( MGA_PITCH, 64,
- MGA_PLNWT, 0xffffffff,
- MGA_DMAPAD, 0x00000000,
- MGA_DWGCTL, MGA_DWGCTL_COPY );
+ DMA_BLOCK(MGA_PITCH, 64,
+ MGA_PLNWT, 0xffffffff,
+ MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
- DMA_BLOCK( MGA_AR0, 63,
- MGA_AR3, 0,
- MGA_FXBNDRY, (63 << 16) | 0,
- MGA_YDSTLEN + MGA_EXEC, y2 );
+ DMA_BLOCK(MGA_AR0, 63,
+ MGA_AR3, 0,
+ MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
- DMA_BLOCK( MGA_PLNWT, ctx->plnwt,
- MGA_SRCORG, dev_priv->front_offset,
- MGA_PITCH, dev_priv->front_pitch,
- MGA_DWGSYNC, 0x00007000 );
+ DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
+ MGA_SRCORG, dev_priv->front_offset,
+ MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
ADVANCE_DMA();
- AGE_BUFFER( buf_priv );
+ AGE_BUFFER(buf_priv);
buf->pending = 0;
buf->used = 0;
buf_priv->dispatched = 0;
- mga_freelist_put( dev, buf );
+ mga_freelist_put(dev, buf);
FLUSH_DMA();
}
-static void mga_dma_dispatch_blit( drm_device_t *dev,
- drm_mga_blit_t *blit )
+static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -821,26 +775,24 @@ static void mga_dma_dispatch_blit( drm_device_t *dev,
int nbox = sarea_priv->nbox;
u32 scandir = 0, i;
DMA_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- BEGIN_DMA( 4 + nbox );
+ BEGIN_DMA(4 + nbox);
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_DMAPAD, 0x00000000,
- MGA_DWGSYNC, 0x00007100,
- MGA_DWGSYNC, 0x00007000 );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
- DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY,
- MGA_PLNWT, blit->planemask,
- MGA_SRCORG, blit->srcorg,
- MGA_DSTORG, blit->dstorg );
+ DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
+ MGA_PLNWT, blit->planemask,
+ MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
- DMA_BLOCK( MGA_SGN, scandir,
- MGA_MACCESS, dev_priv->maccess,
- MGA_AR5, blit->ydir * blit->src_pitch,
- MGA_PITCH, blit->dst_pitch );
+ DMA_BLOCK(MGA_SGN, scandir,
+ MGA_MACCESS, dev_priv->maccess,
+ MGA_AR5, blit->ydir * blit->src_pitch,
+ MGA_PITCH, blit->dst_pitch);
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
int srcx = pbox[i].x1 + blit->delta_sx;
int srcy = pbox[i].y1 + blit->delta_sy;
int dstx = pbox[i].x1 + blit->delta_dx;
@@ -849,52 +801,51 @@ static void mga_dma_dispatch_blit( drm_device_t *dev,
int w = pbox[i].x2 - pbox[i].x1 - 1;
int start;
- if ( blit->ydir == -1 ) {
+ if (blit->ydir == -1) {
srcy = blit->height - srcy - 1;
}
start = srcy * blit->src_pitch + srcx;
- DMA_BLOCK( MGA_AR0, start + w,
- MGA_AR3, start,
- MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
- MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
+ DMA_BLOCK(MGA_AR0, start + w,
+ MGA_AR3, start,
+ MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
+ MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
}
/* Do something to flush AGP?
*/
/* Force reset of DWGCTL */
- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
- MGA_PLNWT, ctx->plnwt,
- MGA_PITCH, dev_priv->front_pitch,
- MGA_DWGCTL, ctx->dwgctl );
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
ADVANCE_DMA();
}
-
/* ================================================================
*
*/
-static int mga_dma_clear( DRM_IOCTL_ARGS )
+static int mga_dma_clear(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_clear_t clear;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t __user *)data, sizeof(clear) );
+ DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data,
+ sizeof(clear));
- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_clear( dev, &clear );
+ mga_dma_dispatch_clear(dev, &clear);
/* Make sure we restore the 3D state next time.
*/
@@ -903,20 +854,20 @@ static int mga_dma_clear( DRM_IOCTL_ARGS )
return 0;
}
-static int mga_dma_swap( DRM_IOCTL_ARGS )
+static int mga_dma_swap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_swap( dev );
+ mga_dma_dispatch_swap(dev);
/* Make sure we restore the 3D state next time.
*/
@@ -925,7 +876,7 @@ static int mga_dma_swap( DRM_IOCTL_ARGS )
return 0;
}
-static int mga_dma_vertex( DRM_IOCTL_ARGS )
+static int mga_dma_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -934,37 +885,38 @@ static int mga_dma_vertex( DRM_IOCTL_ARGS )
drm_mga_buf_priv_t *buf_priv;
drm_mga_vertex_t vertex;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( vertex,
- (drm_mga_vertex_t __user *)data,
- sizeof(vertex) );
+ DRM_COPY_FROM_USER_IOCTL(vertex,
+ (drm_mga_vertex_t __user *) data,
+ sizeof(vertex));
- if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL);
+ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+ return DRM_ERR(EINVAL);
buf = dma->buflist[vertex.idx];
buf_priv = buf->dev_private;
buf->used = vertex.used;
buf_priv->discard = vertex.discard;
- if ( !mga_verify_state( dev_priv ) ) {
- if ( vertex.discard ) {
- if ( buf_priv->dispatched == 1 )
- AGE_BUFFER( buf_priv );
+ if (!mga_verify_state(dev_priv)) {
+ if (vertex.discard) {
+ if (buf_priv->dispatched == 1)
+ AGE_BUFFER(buf_priv);
buf_priv->dispatched = 0;
- mga_freelist_put( dev, buf );
+ mga_freelist_put(dev, buf);
}
return DRM_ERR(EINVAL);
}
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_vertex( dev, buf );
+ mga_dma_dispatch_vertex(dev, buf);
return 0;
}
-static int mga_dma_indices( DRM_IOCTL_ARGS )
+static int mga_dma_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -973,37 +925,38 @@ static int mga_dma_indices( DRM_IOCTL_ARGS )
drm_mga_buf_priv_t *buf_priv;
drm_mga_indices_t indices;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( indices,
- (drm_mga_indices_t __user *)data,
- sizeof(indices) );
+ DRM_COPY_FROM_USER_IOCTL(indices,
+ (drm_mga_indices_t __user *) data,
+ sizeof(indices));
- if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL);
+ if (indices.idx < 0 || indices.idx > dma->buf_count)
+ return DRM_ERR(EINVAL);
buf = dma->buflist[indices.idx];
buf_priv = buf->dev_private;
buf_priv->discard = indices.discard;
- if ( !mga_verify_state( dev_priv ) ) {
- if ( indices.discard ) {
- if ( buf_priv->dispatched == 1 )
- AGE_BUFFER( buf_priv );
+ if (!mga_verify_state(dev_priv)) {
+ if (indices.discard) {
+ if (buf_priv->dispatched == 1)
+ AGE_BUFFER(buf_priv);
buf_priv->dispatched = 0;
- mga_freelist_put( dev, buf );
+ mga_freelist_put(dev, buf);
}
return DRM_ERR(EINVAL);
}
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
+ mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
return 0;
}
-static int mga_dma_iload( DRM_IOCTL_ARGS )
+static int mga_dma_iload(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -1011,32 +964,34 @@ static int mga_dma_iload( DRM_IOCTL_ARGS )
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_iload_t iload;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t __user *)data, sizeof(iload) );
+ DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data,
+ sizeof(iload));
#if 0
- if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
- if ( MGA_DMA_DEBUG )
- DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
+ if (mga_do_wait_for_idle(dev_priv) < 0) {
+ if (MGA_DMA_DEBUG)
+ DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
return DRM_ERR(EBUSY);
}
#endif
- if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL);
+ if (iload.idx < 0 || iload.idx > dma->buf_count)
+ return DRM_ERR(EINVAL);
buf = dma->buflist[iload.idx];
buf_priv = buf->dev_private;
- if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
- mga_freelist_put( dev, buf );
+ if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) {
+ mga_freelist_put(dev, buf);
return DRM_ERR(EINVAL);
}
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
+ mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length);
/* Make sure we restore the 3D state next time.
*/
@@ -1045,27 +1000,28 @@ static int mga_dma_iload( DRM_IOCTL_ARGS )
return 0;
}
-static int mga_dma_blit( DRM_IOCTL_ARGS )
+static int mga_dma_blit(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_blit_t blit;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t __user *)data, sizeof(blit) );
+ DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data,
+ sizeof(blit));
- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
- if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
+ if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg))
return DRM_ERR(EINVAL);
- WRAP_TEST_WITH_RETURN( dev_priv );
+ WRAP_TEST_WITH_RETURN(dev_priv);
- mga_dma_dispatch_blit( dev, &blit );
+ mga_dma_dispatch_blit(dev, &blit);
/* Make sure we restore the 3D state next time.
*/
@@ -1074,50 +1030,116 @@ static int mga_dma_blit( DRM_IOCTL_ARGS )
return 0;
}
-static int mga_getparam( DRM_IOCTL_ARGS )
+static int mga_getparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_getparam_t param;
int value;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t __user *)data,
- sizeof(param) );
+ DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data,
+ sizeof(param));
- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
- switch( param.param ) {
+ switch (param.param) {
case MGA_PARAM_IRQ_NR:
value = dev->irq;
break;
+ case MGA_PARAM_CARD_TYPE:
+ value = dev_priv->chipset;
+ break;
default:
return DRM_ERR(EINVAL);
}
- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return DRM_ERR(EFAULT);
}
-
+
+ return 0;
+}
+
+static int mga_set_fence(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u32 temp;
+ DMA_LOCALS;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+ /* I would normal do this assignment in the declaration of temp,
+ * but dev_priv may be NULL.
+ */
+
+ temp = dev_priv->next_fence_to_post;
+ dev_priv->next_fence_to_post++;
+
+ BEGIN_DMA(1);
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
+ ADVANCE_DMA();
+
+ if (DRM_COPY_TO_USER((u32 __user *) data, &temp, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ return 0;
+}
+
+static int mga_wait_fence(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u32 fence;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32));
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+ mga_driver_fence_wait(dev, &fence);
+
+ if (DRM_COPY_TO_USER((u32 __user *) data, &fence, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+
return 0;
}
drm_ioctl_desc_t mga_ioctls[] = {
- [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 },
- [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1},
};
int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/mga_ucode.h b/drivers/char/drm/mga_ucode.h
index fa0f82ec9fa0..b611e27470e1 100644
--- a/drivers/char/drm/mga_ucode.h
+++ b/drivers/char/drm/mga_ucode.h
@@ -40,11606 +40,11606 @@
static unsigned char warp_g200_tgz[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x72, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x72, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x60, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x60, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x03, 0x80, 0x0A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x0A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x57, 0x39, 0x20, 0xE9,
-0x28, 0x19, 0x60, 0xEC,
+ 0x57, 0x39, 0x20, 0xE9,
+ 0x28, 0x19, 0x60, 0xEC,
-0x2B, 0x32, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0xB3, 0x05,
-0x00, 0xE0,
-0x16, 0x28, 0x20, 0xE9,
+ 0xB3, 0x05,
+ 0x00, 0xE0,
+ 0x16, 0x28, 0x20, 0xE9,
-0x23, 0x3B, 0x33, 0xAD,
-0x1E, 0x2B, 0x20, 0xE9,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x1E, 0x2B, 0x20, 0xE9,
-0x1C, 0x80, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x85, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x85, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x84, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x84, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x82, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x82, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x7F, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x7F, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgza[] = {
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x7D, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x7D, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x6B, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x6B, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2D, 0x44, 0x4C, 0xB6,
-0x25, 0x44, 0x54, 0xB6,
+ 0x2D, 0x44, 0x4C, 0xB6,
+ 0x25, 0x44, 0x54, 0xB6,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x2D, 0x20,
-0x25, 0x20,
-0x07, 0xC0, 0x44, 0xC6,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x07, 0xC0, 0x44, 0xC6,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x1F, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x3F, 0x3D, 0x5D, 0x9F,
-0x00, 0xE0,
-0x07, 0x20,
+ 0x3F, 0x3D, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x07, 0x20,
-0x00, 0x80, 0x00, 0xE8,
-0x28, 0x19, 0x60, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x28, 0x19, 0x60, 0xEC,
-0xB3, 0x05,
-0x00, 0xE0,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x05,
+ 0x00, 0xE0,
+ 0x00, 0x80, 0x00, 0xE8,
-0x23, 0x3B, 0x33, 0xAD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0x26, 0x1F, 0xDF,
-0x9D, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x26, 0x1F, 0xDF,
+ 0x9D, 0x1F, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x9E, 0x3F, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x9E, 0x3F, 0x4F, 0xE9,
-0x07, 0x07, 0x1F, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x07, 0x07, 0x1F, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x9C, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x7A, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x7A, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x79, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x79, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x77, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x77, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x74, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x74, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzaf[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x83, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x83, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x6F, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x6F, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0D, 0x21, 0x1A, 0xB6,
-0x05, 0x21, 0x31, 0xB6,
+ 0x0D, 0x21, 0x1A, 0xB6,
+ 0x05, 0x21, 0x31, 0xB6,
-0x2D, 0x44, 0x4C, 0xB6,
-0x25, 0x44, 0x54, 0xB6,
+ 0x2D, 0x44, 0x4C, 0xB6,
+ 0x25, 0x44, 0x54, 0xB6,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x0D, 0x20,
-0x05, 0x20,
-0x2F, 0xC0, 0x21, 0xC6,
+ 0x0D, 0x20,
+ 0x05, 0x20,
+ 0x2F, 0xC0, 0x21, 0xC6,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x00, 0xE0,
-0x25, 0x20,
-0x07, 0xC0, 0x44, 0xC6,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x07, 0xC0, 0x44, 0xC6,
-0x17, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x2D, 0x20,
+ 0x17, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x2D, 0x20,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x1F, 0x62, 0x57, 0x9F,
-0x00, 0xE0,
-0x07, 0x20,
+ 0x1F, 0x62, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x07, 0x20,
-0x3F, 0x3D, 0x5D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0x3D, 0x5D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x28, 0x19, 0x60, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x28, 0x19, 0x60, 0xEC,
-0xB3, 0x05,
-0x00, 0xE0,
-0x17, 0x26, 0x17, 0xDF,
+ 0xB3, 0x05,
+ 0x00, 0xE0,
+ 0x17, 0x26, 0x17, 0xDF,
-0x23, 0x3B, 0x33, 0xAD,
-0x35, 0x17, 0x4F, 0xE9,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x35, 0x17, 0x4F, 0xE9,
-0x1F, 0x26, 0x1F, 0xDF,
-0x9D, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x26, 0x1F, 0xDF,
+ 0x9D, 0x1F, 0x4F, 0xE9,
-0x9E, 0x3F, 0x4F, 0xE9,
-0x39, 0x37, 0x4F, 0xE9,
+ 0x9E, 0x3F, 0x4F, 0xE9,
+ 0x39, 0x37, 0x4F, 0xE9,
-0x2F, 0x2F, 0x17, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x2F, 0x2F, 0x17, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0x07, 0x07, 0x1F, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x07, 0x07, 0x1F, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0x31, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x9C, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x74, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x74, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x73, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x73, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x71, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x71, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6E, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x6E, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzf[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x7F, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x7F, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x6B, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x6B, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0D, 0x21, 0x1A, 0xB6,
-0x05, 0x21, 0x31, 0xB6,
+ 0x0D, 0x21, 0x1A, 0xB6,
+ 0x05, 0x21, 0x31, 0xB6,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x0D, 0x20,
-0x05, 0x20,
-0x2F, 0xC0, 0x21, 0xC6,
+ 0x0D, 0x20,
+ 0x05, 0x20,
+ 0x2F, 0xC0, 0x21, 0xC6,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x17, 0x50, 0x56, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x17, 0x50, 0x56, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x00, 0x80, 0x00, 0xE8,
-0x28, 0x19, 0x60, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x28, 0x19, 0x60, 0xEC,
-0xB3, 0x05,
-0x00, 0xE0,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x05,
+ 0x00, 0xE0,
+ 0x00, 0x80, 0x00, 0xE8,
-0x23, 0x3B, 0x33, 0xAD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x17, 0x26, 0x17, 0xDF,
-0x35, 0x17, 0x4F, 0xE9,
+ 0x17, 0x26, 0x17, 0xDF,
+ 0x35, 0x17, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x39, 0x37, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x39, 0x37, 0x4F, 0xE9,
-0x2F, 0x2F, 0x17, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x2F, 0x2F, 0x17, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x31, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x78, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x78, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x77, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x77, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x75, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x75, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x72, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x72, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzs[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x8B, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x77, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x77, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2D, 0x21, 0x1A, 0xB0,
-0x25, 0x21, 0x31, 0xB0,
+ 0x2D, 0x21, 0x1A, 0xB0,
+ 0x25, 0x21, 0x31, 0xB0,
-0x0D, 0x21, 0x1A, 0xB2,
-0x05, 0x21, 0x31, 0xB2,
+ 0x0D, 0x21, 0x1A, 0xB2,
+ 0x05, 0x21, 0x31, 0xB2,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x2D, 0x20,
-0x25, 0x20,
-0x05, 0x20,
-0x0D, 0x20,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x05, 0x20,
+ 0x0D, 0x20,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x2F, 0xC0, 0x21, 0xC0,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x2F, 0xC0, 0x21, 0xC0,
-0x16, 0x42, 0x56, 0x9F,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x16, 0x42, 0x56, 0x9F,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x1E, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x21, 0x31, 0xB4,
-0x2D, 0x21, 0x1A, 0xB4,
+ 0x25, 0x21, 0x31, 0xB4,
+ 0x2D, 0x21, 0x1A, 0xB4,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0x05,
-0x00, 0xE0,
-0x28, 0x19, 0x60, 0xEC,
+ 0x33, 0x05,
+ 0x00, 0xE0,
+ 0x28, 0x19, 0x60, 0xEC,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x23, 0x3B, 0x33, 0xAD,
-0x1E, 0x26, 0x1E, 0xDF,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x1E, 0x26, 0x1E, 0xDF,
-0xA7, 0x1E, 0x4F, 0xE9,
-0x17, 0x26, 0x16, 0xDF,
+ 0xA7, 0x1E, 0x4F, 0xE9,
+ 0x17, 0x26, 0x16, 0xDF,
-0x2D, 0x20,
-0x00, 0xE0,
-0xA8, 0x3F, 0x4F, 0xE9,
+ 0x2D, 0x20,
+ 0x00, 0xE0,
+ 0xA8, 0x3F, 0x4F, 0xE9,
-0x2F, 0x2F, 0x1E, 0xAF,
-0x25, 0x20,
-0x00, 0xE0,
+ 0x2F, 0x2F, 0x1E, 0xAF,
+ 0x25, 0x20,
+ 0x00, 0xE0,
-0xA4, 0x16, 0x4F, 0xE9,
-0x0F, 0xC0, 0x21, 0xC2,
+ 0xA4, 0x16, 0x4F, 0xE9,
+ 0x0F, 0xC0, 0x21, 0xC2,
-0xA6, 0x80, 0x4F, 0xE9,
-0x1F, 0x62, 0x57, 0x9F,
+ 0xA6, 0x80, 0x4F, 0xE9,
+ 0x1F, 0x62, 0x57, 0x9F,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0xE0,
-0x8F, 0x20,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x8F, 0x20,
-0xA5, 0x37, 0x4F, 0xE9,
-0x0F, 0x17, 0x0F, 0xAF,
+ 0xA5, 0x37, 0x4F, 0xE9,
+ 0x0F, 0x17, 0x0F, 0xAF,
-0x06, 0xC0, 0x21, 0xC4,
-0x00, 0x80, 0x00, 0xE8,
+ 0x06, 0xC0, 0x21, 0xC4,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0xA3, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0xA3, 0x80, 0x4F, 0xE9,
-0x06, 0x20,
-0x00, 0xE0,
-0x1F, 0x26, 0x1F, 0xDF,
+ 0x06, 0x20,
+ 0x00, 0xE0,
+ 0x1F, 0x26, 0x1F, 0xDF,
-0xA1, 0x1F, 0x4F, 0xE9,
-0xA2, 0x3F, 0x4F, 0xE9,
+ 0xA1, 0x1F, 0x4F, 0xE9,
+ 0xA2, 0x3F, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x06, 0x06, 0x1F, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x06, 0x06, 0x1F, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x6C, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x6C, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6B, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x6B, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x69, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x69, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x66, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzsa[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x8F, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x8F, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x7B, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x7B, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2D, 0x21, 0x1A, 0xB0,
-0x25, 0x21, 0x31, 0xB0,
+ 0x2D, 0x21, 0x1A, 0xB0,
+ 0x25, 0x21, 0x31, 0xB0,
-0x0D, 0x21, 0x1A, 0xB2,
-0x05, 0x21, 0x31, 0xB2,
+ 0x0D, 0x21, 0x1A, 0xB2,
+ 0x05, 0x21, 0x31, 0xB2,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x2D, 0x20,
-0x25, 0x20,
-0x05, 0x20,
-0x0D, 0x20,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x05, 0x20,
+ 0x0D, 0x20,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x2F, 0xC0, 0x21, 0xC0,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x2F, 0xC0, 0x21, 0xC0,
-0x16, 0x42, 0x56, 0x9F,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x16, 0x42, 0x56, 0x9F,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x1E, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x21, 0x31, 0xB4,
-0x2D, 0x21, 0x1A, 0xB4,
+ 0x25, 0x21, 0x31, 0xB4,
+ 0x2D, 0x21, 0x1A, 0xB4,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0x05,
-0x00, 0xE0,
-0x28, 0x19, 0x60, 0xEC,
+ 0x33, 0x05,
+ 0x00, 0xE0,
+ 0x28, 0x19, 0x60, 0xEC,
-0x0D, 0x44, 0x4C, 0xB6,
-0x05, 0x44, 0x54, 0xB6,
+ 0x0D, 0x44, 0x4C, 0xB6,
+ 0x05, 0x44, 0x54, 0xB6,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x23, 0x3B, 0x33, 0xAD,
-0x1E, 0x26, 0x1E, 0xDF,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x1E, 0x26, 0x1E, 0xDF,
-0xA7, 0x1E, 0x4F, 0xE9,
-0x17, 0x26, 0x16, 0xDF,
+ 0xA7, 0x1E, 0x4F, 0xE9,
+ 0x17, 0x26, 0x16, 0xDF,
-0x2D, 0x20,
-0x00, 0xE0,
-0xA8, 0x3F, 0x4F, 0xE9,
+ 0x2D, 0x20,
+ 0x00, 0xE0,
+ 0xA8, 0x3F, 0x4F, 0xE9,
-0x2F, 0x2F, 0x1E, 0xAF,
-0x25, 0x20,
-0x00, 0xE0,
+ 0x2F, 0x2F, 0x1E, 0xAF,
+ 0x25, 0x20,
+ 0x00, 0xE0,
-0xA4, 0x16, 0x4F, 0xE9,
-0x0F, 0xC0, 0x21, 0xC2,
+ 0xA4, 0x16, 0x4F, 0xE9,
+ 0x0F, 0xC0, 0x21, 0xC2,
-0xA6, 0x80, 0x4F, 0xE9,
-0x1F, 0x62, 0x57, 0x9F,
+ 0xA6, 0x80, 0x4F, 0xE9,
+ 0x1F, 0x62, 0x57, 0x9F,
-0x0D, 0x20,
-0x05, 0x20,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x20,
+ 0x05, 0x20,
+ 0x00, 0x80, 0x00, 0xE8,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0xE0,
-0x0F, 0x20,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x0F, 0x20,
-0x17, 0x50, 0x56, 0x9F,
-0xA5, 0x37, 0x4F, 0xE9,
+ 0x17, 0x50, 0x56, 0x9F,
+ 0xA5, 0x37, 0x4F, 0xE9,
-0x06, 0xC0, 0x21, 0xC4,
-0x0F, 0x17, 0x0F, 0xAF,
+ 0x06, 0xC0, 0x21, 0xC4,
+ 0x0F, 0x17, 0x0F, 0xAF,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2F, 0xC0, 0x44, 0xC6,
-0xA3, 0x80, 0x4F, 0xE9,
+ 0x2F, 0xC0, 0x44, 0xC6,
+ 0xA3, 0x80, 0x4F, 0xE9,
-0x06, 0x20,
-0x00, 0xE0,
-0x1F, 0x26, 0x1F, 0xDF,
+ 0x06, 0x20,
+ 0x00, 0xE0,
+ 0x1F, 0x26, 0x1F, 0xDF,
-0x17, 0x26, 0x17, 0xDF,
-0x9D, 0x17, 0x4F, 0xE9,
+ 0x17, 0x26, 0x17, 0xDF,
+ 0x9D, 0x17, 0x4F, 0xE9,
-0xA1, 0x1F, 0x4F, 0xE9,
-0xA2, 0x3F, 0x4F, 0xE9,
+ 0xA1, 0x1F, 0x4F, 0xE9,
+ 0xA2, 0x3F, 0x4F, 0xE9,
-0x06, 0x06, 0x1F, 0xAF,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0x06, 0x06, 0x1F, 0xAF,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x9E, 0x37, 0x4F, 0xE9,
-0x2F, 0x17, 0x2F, 0xAF,
+ 0x9E, 0x37, 0x4F, 0xE9,
+ 0x2F, 0x17, 0x2F, 0xAF,
-0xA0, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x9C, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x68, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x68, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x67, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x67, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x65, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x65, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x62, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x62, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzsaf[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x94, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x94, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x80, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x80, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2D, 0x21, 0x1A, 0xB0,
-0x25, 0x21, 0x31, 0xB0,
+ 0x2D, 0x21, 0x1A, 0xB0,
+ 0x25, 0x21, 0x31, 0xB0,
-0x0D, 0x21, 0x1A, 0xB2,
-0x05, 0x21, 0x31, 0xB2,
+ 0x0D, 0x21, 0x1A, 0xB2,
+ 0x05, 0x21, 0x31, 0xB2,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x2D, 0x20,
-0x25, 0x20,
-0x05, 0x20,
-0x0D, 0x20,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x05, 0x20,
+ 0x0D, 0x20,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x2F, 0xC0, 0x21, 0xC0,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x2F, 0xC0, 0x21, 0xC0,
-0x16, 0x42, 0x56, 0x9F,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x16, 0x42, 0x56, 0x9F,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x1E, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x21, 0x31, 0xB4,
-0x2D, 0x21, 0x1A, 0xB4,
+ 0x25, 0x21, 0x31, 0xB4,
+ 0x2D, 0x21, 0x1A, 0xB4,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0x05,
-0x00, 0xE0,
-0x28, 0x19, 0x60, 0xEC,
+ 0x33, 0x05,
+ 0x00, 0xE0,
+ 0x28, 0x19, 0x60, 0xEC,
-0x0D, 0x21, 0x1A, 0xB6,
-0x05, 0x21, 0x31, 0xB6,
+ 0x0D, 0x21, 0x1A, 0xB6,
+ 0x05, 0x21, 0x31, 0xB6,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x23, 0x3B, 0x33, 0xAD,
-0x1E, 0x26, 0x1E, 0xDF,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x1E, 0x26, 0x1E, 0xDF,
-0xA7, 0x1E, 0x4F, 0xE9,
-0x17, 0x26, 0x16, 0xDF,
+ 0xA7, 0x1E, 0x4F, 0xE9,
+ 0x17, 0x26, 0x16, 0xDF,
-0x2D, 0x20,
-0x00, 0xE0,
-0xA8, 0x3F, 0x4F, 0xE9,
+ 0x2D, 0x20,
+ 0x00, 0xE0,
+ 0xA8, 0x3F, 0x4F, 0xE9,
-0x2F, 0x2F, 0x1E, 0xAF,
-0x25, 0x20,
-0x00, 0xE0,
+ 0x2F, 0x2F, 0x1E, 0xAF,
+ 0x25, 0x20,
+ 0x00, 0xE0,
-0xA4, 0x16, 0x4F, 0xE9,
-0x0F, 0xC0, 0x21, 0xC2,
+ 0xA4, 0x16, 0x4F, 0xE9,
+ 0x0F, 0xC0, 0x21, 0xC2,
-0xA6, 0x80, 0x4F, 0xE9,
-0x1F, 0x62, 0x57, 0x9F,
+ 0xA6, 0x80, 0x4F, 0xE9,
+ 0x1F, 0x62, 0x57, 0x9F,
-0x0D, 0x20,
-0x05, 0x20,
-0x2F, 0xC0, 0x21, 0xC6,
+ 0x0D, 0x20,
+ 0x05, 0x20,
+ 0x2F, 0xC0, 0x21, 0xC6,
-0x2D, 0x44, 0x4C, 0xB6,
-0x25, 0x44, 0x54, 0xB6,
+ 0x2D, 0x44, 0x4C, 0xB6,
+ 0x25, 0x44, 0x54, 0xB6,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0xE0,
-0x0F, 0x20,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x0F, 0x20,
-0x2D, 0x20,
-0x25, 0x20,
-0x07, 0xC0, 0x44, 0xC6,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x07, 0xC0, 0x44, 0xC6,
-0x17, 0x50, 0x56, 0x9F,
-0xA5, 0x37, 0x4F, 0xE9,
+ 0x17, 0x50, 0x56, 0x9F,
+ 0xA5, 0x37, 0x4F, 0xE9,
-0x06, 0xC0, 0x21, 0xC4,
-0x0F, 0x17, 0x0F, 0xAF,
+ 0x06, 0xC0, 0x21, 0xC4,
+ 0x0F, 0x17, 0x0F, 0xAF,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1E, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x3E, 0x3D, 0x5D, 0x9F,
-0x00, 0xE0,
-0x07, 0x20,
+ 0x3E, 0x3D, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x07, 0x20,
-0x2F, 0x20,
-0x00, 0xE0,
-0xA3, 0x0F, 0x4F, 0xE9,
+ 0x2F, 0x20,
+ 0x00, 0xE0,
+ 0xA3, 0x0F, 0x4F, 0xE9,
-0x06, 0x20,
-0x00, 0xE0,
-0x1F, 0x26, 0x1F, 0xDF,
+ 0x06, 0x20,
+ 0x00, 0xE0,
+ 0x1F, 0x26, 0x1F, 0xDF,
-0x17, 0x26, 0x17, 0xDF,
-0xA1, 0x1F, 0x4F, 0xE9,
+ 0x17, 0x26, 0x17, 0xDF,
+ 0xA1, 0x1F, 0x4F, 0xE9,
-0x1E, 0x26, 0x1E, 0xDF,
-0x9D, 0x1E, 0x4F, 0xE9,
+ 0x1E, 0x26, 0x1E, 0xDF,
+ 0x9D, 0x1E, 0x4F, 0xE9,
-0x35, 0x17, 0x4F, 0xE9,
-0xA2, 0x3F, 0x4F, 0xE9,
+ 0x35, 0x17, 0x4F, 0xE9,
+ 0xA2, 0x3F, 0x4F, 0xE9,
-0x06, 0x06, 0x1F, 0xAF,
-0x39, 0x37, 0x4F, 0xE9,
+ 0x06, 0x06, 0x1F, 0xAF,
+ 0x39, 0x37, 0x4F, 0xE9,
-0x2F, 0x2F, 0x17, 0xAF,
-0x07, 0x07, 0x1E, 0xAF,
+ 0x2F, 0x2F, 0x17, 0xAF,
+ 0x07, 0x07, 0x1E, 0xAF,
-0xA0, 0x80, 0x4F, 0xE9,
-0x9E, 0x3E, 0x4F, 0xE9,
+ 0xA0, 0x80, 0x4F, 0xE9,
+ 0x9E, 0x3E, 0x4F, 0xE9,
-0x31, 0x80, 0x4F, 0xE9,
-0x9C, 0x80, 0x4F, 0xE9,
+ 0x31, 0x80, 0x4F, 0xE9,
+ 0x9C, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x63, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x63, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x62, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x62, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x60, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x60, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x5D, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x5D, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g200_tgzsf[] = {
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x98, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x98, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x81, 0x04,
-0x89, 0x04,
-0x01, 0x04,
-0x09, 0x04,
+ 0x81, 0x04,
+ 0x89, 0x04,
+ 0x01, 0x04,
+ 0x09, 0x04,
-0xC9, 0x41, 0xC0, 0xEC,
-0x11, 0x04,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC0, 0xEC,
+ 0x11, 0x04,
+ 0x00, 0xE0,
-0x41, 0xCC, 0x41, 0xCD,
-0x49, 0xCC, 0x49, 0xCD,
+ 0x41, 0xCC, 0x41, 0xCD,
+ 0x49, 0xCC, 0x49, 0xCD,
-0xD1, 0x41, 0xC0, 0xEC,
-0x51, 0xCC, 0x51, 0xCD,
+ 0xD1, 0x41, 0xC0, 0xEC,
+ 0x51, 0xCC, 0x51, 0xCD,
-0x80, 0x04,
-0x10, 0x04,
-0x08, 0x04,
-0x00, 0xE0,
+ 0x80, 0x04,
+ 0x10, 0x04,
+ 0x08, 0x04,
+ 0x00, 0xE0,
-0x00, 0xCC, 0xC0, 0xCD,
-0xD1, 0x49, 0xC0, 0xEC,
+ 0x00, 0xCC, 0xC0, 0xCD,
+ 0xD1, 0x49, 0xC0, 0xEC,
-0x8A, 0x1F, 0x20, 0xE9,
-0x8B, 0x3F, 0x20, 0xE9,
+ 0x8A, 0x1F, 0x20, 0xE9,
+ 0x8B, 0x3F, 0x20, 0xE9,
-0x41, 0x3C, 0x41, 0xAD,
-0x49, 0x3C, 0x49, 0xAD,
+ 0x41, 0x3C, 0x41, 0xAD,
+ 0x49, 0x3C, 0x49, 0xAD,
-0x10, 0xCC, 0x10, 0xCD,
-0x08, 0xCC, 0x08, 0xCD,
+ 0x10, 0xCC, 0x10, 0xCD,
+ 0x08, 0xCC, 0x08, 0xCD,
-0xB9, 0x41, 0x49, 0xBB,
-0x1F, 0xF0, 0x41, 0xCD,
+ 0xB9, 0x41, 0x49, 0xBB,
+ 0x1F, 0xF0, 0x41, 0xCD,
-0x51, 0x3C, 0x51, 0xAD,
-0x00, 0x98, 0x80, 0xE9,
+ 0x51, 0x3C, 0x51, 0xAD,
+ 0x00, 0x98, 0x80, 0xE9,
-0x8F, 0x80, 0x07, 0xEA,
-0x24, 0x1F, 0x20, 0xE9,
+ 0x8F, 0x80, 0x07, 0xEA,
+ 0x24, 0x1F, 0x20, 0xE9,
-0x21, 0x45, 0x80, 0xE8,
-0x1A, 0x4D, 0x80, 0xE8,
+ 0x21, 0x45, 0x80, 0xE8,
+ 0x1A, 0x4D, 0x80, 0xE8,
-0x31, 0x55, 0x80, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x55, 0x80, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0x41, 0x49, 0xBD,
-0x1D, 0x41, 0x51, 0xBD,
+ 0x15, 0x41, 0x49, 0xBD,
+ 0x1D, 0x41, 0x51, 0xBD,
-0x2E, 0x41, 0x2A, 0xB8,
-0x34, 0x53, 0xA0, 0xE8,
+ 0x2E, 0x41, 0x2A, 0xB8,
+ 0x34, 0x53, 0xA0, 0xE8,
-0x15, 0x30,
-0x1D, 0x30,
-0x58, 0xE3,
-0x00, 0xE0,
+ 0x15, 0x30,
+ 0x1D, 0x30,
+ 0x58, 0xE3,
+ 0x00, 0xE0,
-0xB5, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0xB5, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x24, 0x43, 0xA0, 0xE8,
-0x2C, 0x4B, 0xA0, 0xE8,
+ 0x24, 0x43, 0xA0, 0xE8,
+ 0x2C, 0x4B, 0xA0, 0xE8,
-0x15, 0x72,
-0x09, 0xE3,
-0x00, 0xE0,
-0x1D, 0x72,
+ 0x15, 0x72,
+ 0x09, 0xE3,
+ 0x00, 0xE0,
+ 0x1D, 0x72,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0x97, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0x97, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x6C, 0x64, 0xC8, 0xEC,
-0x98, 0xE1,
-0xB5, 0x05,
+ 0x6C, 0x64, 0xC8, 0xEC,
+ 0x98, 0xE1,
+ 0xB5, 0x05,
-0xBD, 0x05,
-0x2E, 0x30,
-0x32, 0xC0, 0xA0, 0xE8,
+ 0xBD, 0x05,
+ 0x2E, 0x30,
+ 0x32, 0xC0, 0xA0, 0xE8,
-0x33, 0xC0, 0xA0, 0xE8,
-0x74, 0x64, 0xC8, 0xEC,
+ 0x33, 0xC0, 0xA0, 0xE8,
+ 0x74, 0x64, 0xC8, 0xEC,
-0x40, 0x3C, 0x40, 0xAD,
-0x32, 0x6A,
-0x2A, 0x30,
+ 0x40, 0x3C, 0x40, 0xAD,
+ 0x32, 0x6A,
+ 0x2A, 0x30,
-0x20, 0x73,
-0x33, 0x6A,
-0x00, 0xE0,
-0x28, 0x73,
+ 0x20, 0x73,
+ 0x33, 0x6A,
+ 0x00, 0xE0,
+ 0x28, 0x73,
-0x1C, 0x72,
-0x83, 0xE2,
-0x7B, 0x80, 0x15, 0xEA,
+ 0x1C, 0x72,
+ 0x83, 0xE2,
+ 0x7B, 0x80, 0x15, 0xEA,
-0xB8, 0x3D, 0x28, 0xDF,
-0x30, 0x35, 0x20, 0xDF,
+ 0xB8, 0x3D, 0x28, 0xDF,
+ 0x30, 0x35, 0x20, 0xDF,
-0x40, 0x30,
-0x00, 0xE0,
-0xCC, 0xE2,
-0x64, 0x72,
+ 0x40, 0x30,
+ 0x00, 0xE0,
+ 0xCC, 0xE2,
+ 0x64, 0x72,
-0x25, 0x42, 0x52, 0xBF,
-0x2D, 0x42, 0x4A, 0xBF,
+ 0x25, 0x42, 0x52, 0xBF,
+ 0x2D, 0x42, 0x4A, 0xBF,
-0x30, 0x2E, 0x30, 0xDF,
-0x38, 0x2E, 0x38, 0xDF,
+ 0x30, 0x2E, 0x30, 0xDF,
+ 0x38, 0x2E, 0x38, 0xDF,
-0x18, 0x1D, 0x45, 0xE9,
-0x1E, 0x15, 0x45, 0xE9,
+ 0x18, 0x1D, 0x45, 0xE9,
+ 0x1E, 0x15, 0x45, 0xE9,
-0x2B, 0x49, 0x51, 0xBD,
-0x00, 0xE0,
-0x1F, 0x73,
+ 0x2B, 0x49, 0x51, 0xBD,
+ 0x00, 0xE0,
+ 0x1F, 0x73,
-0x38, 0x38, 0x40, 0xAF,
-0x30, 0x30, 0x40, 0xAF,
+ 0x38, 0x38, 0x40, 0xAF,
+ 0x30, 0x30, 0x40, 0xAF,
-0x24, 0x1F, 0x24, 0xDF,
-0x1D, 0x32, 0x20, 0xE9,
+ 0x24, 0x1F, 0x24, 0xDF,
+ 0x1D, 0x32, 0x20, 0xE9,
-0x2C, 0x1F, 0x2C, 0xDF,
-0x1A, 0x33, 0x20, 0xE9,
+ 0x2C, 0x1F, 0x2C, 0xDF,
+ 0x1A, 0x33, 0x20, 0xE9,
-0xB0, 0x10,
-0x08, 0xE3,
-0x40, 0x10,
-0xB8, 0x10,
+ 0xB0, 0x10,
+ 0x08, 0xE3,
+ 0x40, 0x10,
+ 0xB8, 0x10,
-0x26, 0xF0, 0x30, 0xCD,
-0x2F, 0xF0, 0x38, 0xCD,
+ 0x26, 0xF0, 0x30, 0xCD,
+ 0x2F, 0xF0, 0x38, 0xCD,
-0x2B, 0x80, 0x20, 0xE9,
-0x2A, 0x80, 0x20, 0xE9,
+ 0x2B, 0x80, 0x20, 0xE9,
+ 0x2A, 0x80, 0x20, 0xE9,
-0xA6, 0x20,
-0x88, 0xE2,
-0x00, 0xE0,
-0xAF, 0x20,
+ 0xA6, 0x20,
+ 0x88, 0xE2,
+ 0x00, 0xE0,
+ 0xAF, 0x20,
-0x28, 0x2A, 0x26, 0xAF,
-0x20, 0x2A, 0xC0, 0xAF,
+ 0x28, 0x2A, 0x26, 0xAF,
+ 0x20, 0x2A, 0xC0, 0xAF,
-0x34, 0x1F, 0x34, 0xDF,
-0x46, 0x24, 0x46, 0xDF,
+ 0x34, 0x1F, 0x34, 0xDF,
+ 0x46, 0x24, 0x46, 0xDF,
-0x28, 0x30, 0x80, 0xBF,
-0x20, 0x38, 0x80, 0xBF,
+ 0x28, 0x30, 0x80, 0xBF,
+ 0x20, 0x38, 0x80, 0xBF,
-0x47, 0x24, 0x47, 0xDF,
-0x4E, 0x2C, 0x4E, 0xDF,
+ 0x47, 0x24, 0x47, 0xDF,
+ 0x4E, 0x2C, 0x4E, 0xDF,
-0x4F, 0x2C, 0x4F, 0xDF,
-0x56, 0x34, 0x56, 0xDF,
+ 0x4F, 0x2C, 0x4F, 0xDF,
+ 0x56, 0x34, 0x56, 0xDF,
-0x28, 0x15, 0x28, 0xDF,
-0x20, 0x1D, 0x20, 0xDF,
+ 0x28, 0x15, 0x28, 0xDF,
+ 0x20, 0x1D, 0x20, 0xDF,
-0x57, 0x34, 0x57, 0xDF,
-0x00, 0xE0,
-0x1D, 0x05,
+ 0x57, 0x34, 0x57, 0xDF,
+ 0x00, 0xE0,
+ 0x1D, 0x05,
-0x04, 0x80, 0x10, 0xEA,
-0x89, 0xE2,
-0x2B, 0x30,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x89, 0xE2,
+ 0x2B, 0x30,
-0x3F, 0xC1, 0x1D, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0xC1, 0x1D, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x68,
-0xBF, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x68,
+ 0xBF, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x20, 0xC0, 0x20, 0xAF,
-0x28, 0x05,
-0x97, 0x74,
+ 0x20, 0xC0, 0x20, 0xAF,
+ 0x28, 0x05,
+ 0x97, 0x74,
-0x00, 0xE0,
-0x2A, 0x10,
-0x16, 0xC0, 0x20, 0xE9,
+ 0x00, 0xE0,
+ 0x2A, 0x10,
+ 0x16, 0xC0, 0x20, 0xE9,
-0x04, 0x80, 0x10, 0xEA,
-0x8C, 0xE2,
-0x95, 0x05,
+ 0x04, 0x80, 0x10, 0xEA,
+ 0x8C, 0xE2,
+ 0x95, 0x05,
-0x28, 0xC1, 0x28, 0xAD,
-0x1F, 0xC1, 0x15, 0xBD,
+ 0x28, 0xC1, 0x28, 0xAD,
+ 0x1F, 0xC1, 0x15, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA8, 0x67,
-0x9F, 0x6B,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA8, 0x67,
+ 0x9F, 0x6B,
+ 0x00, 0x80, 0x00, 0xE8,
-0x28, 0xC0, 0x28, 0xAD,
-0x1D, 0x25,
-0x20, 0x05,
+ 0x28, 0xC0, 0x28, 0xAD,
+ 0x1D, 0x25,
+ 0x20, 0x05,
-0x28, 0x32, 0x80, 0xAD,
-0x40, 0x2A, 0x40, 0xBD,
+ 0x28, 0x32, 0x80, 0xAD,
+ 0x40, 0x2A, 0x40, 0xBD,
-0x1C, 0x80, 0x20, 0xE9,
-0x20, 0x33, 0x20, 0xAD,
+ 0x1C, 0x80, 0x20, 0xE9,
+ 0x20, 0x33, 0x20, 0xAD,
-0x20, 0x73,
-0x00, 0xE0,
-0xB6, 0x49, 0x51, 0xBB,
+ 0x20, 0x73,
+ 0x00, 0xE0,
+ 0xB6, 0x49, 0x51, 0xBB,
-0x26, 0x2F, 0xB0, 0xE8,
-0x19, 0x20, 0x20, 0xE9,
+ 0x26, 0x2F, 0xB0, 0xE8,
+ 0x19, 0x20, 0x20, 0xE9,
-0x35, 0x20, 0x35, 0xDF,
-0x3D, 0x20, 0x3D, 0xDF,
+ 0x35, 0x20, 0x35, 0xDF,
+ 0x3D, 0x20, 0x3D, 0xDF,
-0x15, 0x20, 0x15, 0xDF,
-0x1D, 0x20, 0x1D, 0xDF,
+ 0x15, 0x20, 0x15, 0xDF,
+ 0x1D, 0x20, 0x1D, 0xDF,
-0x26, 0xD0, 0x26, 0xCD,
-0x29, 0x49, 0x2A, 0xB8,
+ 0x26, 0xD0, 0x26, 0xCD,
+ 0x29, 0x49, 0x2A, 0xB8,
-0x26, 0x40, 0x80, 0xBD,
-0x3B, 0x48, 0x50, 0xBD,
+ 0x26, 0x40, 0x80, 0xBD,
+ 0x3B, 0x48, 0x50, 0xBD,
-0x3E, 0x54, 0x57, 0x9F,
-0x00, 0xE0,
-0x82, 0xE1,
+ 0x3E, 0x54, 0x57, 0x9F,
+ 0x00, 0xE0,
+ 0x82, 0xE1,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x26, 0x30,
-0x29, 0x30,
-0x48, 0x3C, 0x48, 0xAD,
+ 0x26, 0x30,
+ 0x29, 0x30,
+ 0x48, 0x3C, 0x48, 0xAD,
-0x2B, 0x72,
-0xC2, 0xE1,
-0x2C, 0xC0, 0x44, 0xC2,
+ 0x2B, 0x72,
+ 0xC2, 0xE1,
+ 0x2C, 0xC0, 0x44, 0xC2,
-0x05, 0x24, 0x34, 0xBF,
-0x0D, 0x24, 0x2C, 0xBF,
+ 0x05, 0x24, 0x34, 0xBF,
+ 0x0D, 0x24, 0x2C, 0xBF,
-0x2D, 0x46, 0x4E, 0xBF,
-0x25, 0x46, 0x56, 0xBF,
+ 0x2D, 0x46, 0x4E, 0xBF,
+ 0x25, 0x46, 0x56, 0xBF,
-0x20, 0x1D, 0x6F, 0x8F,
-0x32, 0x3E, 0x5F, 0xE9,
+ 0x20, 0x1D, 0x6F, 0x8F,
+ 0x32, 0x3E, 0x5F, 0xE9,
-0x3E, 0x50, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x30,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x30,
-0x1E, 0x8F, 0x51, 0x9F,
-0x33, 0x1E, 0x5F, 0xE9,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x33, 0x1E, 0x5F, 0xE9,
-0x05, 0x44, 0x54, 0xB2,
-0x0D, 0x44, 0x4C, 0xB2,
+ 0x05, 0x44, 0x54, 0xB2,
+ 0x0D, 0x44, 0x4C, 0xB2,
-0x19, 0xC0, 0xB0, 0xE8,
-0x34, 0xC0, 0x44, 0xC4,
+ 0x19, 0xC0, 0xB0, 0xE8,
+ 0x34, 0xC0, 0x44, 0xC4,
-0x33, 0x73,
-0x00, 0xE0,
-0x3E, 0x62, 0x57, 0x9F,
+ 0x33, 0x73,
+ 0x00, 0xE0,
+ 0x3E, 0x62, 0x57, 0x9F,
-0x1E, 0xAF, 0x59, 0x9F,
-0x00, 0xE0,
-0x0D, 0x20,
+ 0x1E, 0xAF, 0x59, 0x9F,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
-0x84, 0x3E, 0x58, 0xE9,
-0x28, 0x1D, 0x6F, 0x8F,
+ 0x84, 0x3E, 0x58, 0xE9,
+ 0x28, 0x1D, 0x6F, 0x8F,
-0x05, 0x20,
-0x00, 0xE0,
-0x85, 0x1E, 0x58, 0xE9,
+ 0x05, 0x20,
+ 0x00, 0xE0,
+ 0x85, 0x1E, 0x58, 0xE9,
-0x9B, 0x3B, 0x33, 0xDF,
-0x20, 0x20, 0x42, 0xAF,
+ 0x9B, 0x3B, 0x33, 0xDF,
+ 0x20, 0x20, 0x42, 0xAF,
-0x30, 0x42, 0x56, 0x9F,
-0x80, 0x3E, 0x57, 0xE9,
+ 0x30, 0x42, 0x56, 0x9F,
+ 0x80, 0x3E, 0x57, 0xE9,
-0x3F, 0x8F, 0x51, 0x9F,
-0x30, 0x80, 0x5F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x30, 0x80, 0x5F, 0xE9,
-0x28, 0x28, 0x24, 0xAF,
-0x81, 0x1E, 0x57, 0xE9,
+ 0x28, 0x28, 0x24, 0xAF,
+ 0x81, 0x1E, 0x57, 0xE9,
-0x05, 0x47, 0x57, 0xBF,
-0x0D, 0x47, 0x4F, 0xBF,
+ 0x05, 0x47, 0x57, 0xBF,
+ 0x0D, 0x47, 0x4F, 0xBF,
-0x88, 0x80, 0x58, 0xE9,
-0x1B, 0x29, 0x1B, 0xDF,
+ 0x88, 0x80, 0x58, 0xE9,
+ 0x1B, 0x29, 0x1B, 0xDF,
-0x30, 0x1D, 0x6F, 0x8F,
-0x3A, 0x30, 0x4F, 0xE9,
+ 0x30, 0x1D, 0x6F, 0x8F,
+ 0x3A, 0x30, 0x4F, 0xE9,
-0x1C, 0x30, 0x26, 0xDF,
-0x09, 0xE3,
-0x3B, 0x05,
+ 0x1C, 0x30, 0x26, 0xDF,
+ 0x09, 0xE3,
+ 0x3B, 0x05,
-0x3E, 0x50, 0x56, 0x9F,
-0x3B, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x50, 0x56, 0x9F,
+ 0x3B, 0x3F, 0x4F, 0xE9,
-0x1E, 0x8F, 0x51, 0x9F,
-0x00, 0xE0,
-0xAC, 0x20,
+ 0x1E, 0x8F, 0x51, 0x9F,
+ 0x00, 0xE0,
+ 0xAC, 0x20,
-0x2D, 0x44, 0x4C, 0xB4,
-0x2C, 0x1C, 0xC0, 0xAF,
+ 0x2D, 0x44, 0x4C, 0xB4,
+ 0x2C, 0x1C, 0xC0, 0xAF,
-0x25, 0x44, 0x54, 0xB4,
-0x00, 0xE0,
-0xC8, 0x30,
+ 0x25, 0x44, 0x54, 0xB4,
+ 0x00, 0xE0,
+ 0xC8, 0x30,
-0x30, 0x46, 0x30, 0xAF,
-0x1B, 0x1B, 0x48, 0xAF,
+ 0x30, 0x46, 0x30, 0xAF,
+ 0x1B, 0x1B, 0x48, 0xAF,
-0x00, 0xE0,
-0x25, 0x20,
-0x38, 0x2C, 0x4F, 0xE9,
+ 0x00, 0xE0,
+ 0x25, 0x20,
+ 0x38, 0x2C, 0x4F, 0xE9,
-0x86, 0x80, 0x57, 0xE9,
-0x38, 0x1D, 0x6F, 0x8F,
+ 0x86, 0x80, 0x57, 0xE9,
+ 0x38, 0x1D, 0x6F, 0x8F,
-0x28, 0x74,
-0x00, 0xE0,
-0x0D, 0x44, 0x4C, 0xB0,
+ 0x28, 0x74,
+ 0x00, 0xE0,
+ 0x0D, 0x44, 0x4C, 0xB0,
-0x05, 0x44, 0x54, 0xB0,
-0x2D, 0x20,
-0x9B, 0x10,
+ 0x05, 0x44, 0x54, 0xB0,
+ 0x2D, 0x20,
+ 0x9B, 0x10,
-0x82, 0x3E, 0x57, 0xE9,
-0x32, 0xF0, 0x1B, 0xCD,
+ 0x82, 0x3E, 0x57, 0xE9,
+ 0x32, 0xF0, 0x1B, 0xCD,
-0x1E, 0xBD, 0x59, 0x9F,
-0x83, 0x1E, 0x57, 0xE9,
+ 0x1E, 0xBD, 0x59, 0x9F,
+ 0x83, 0x1E, 0x57, 0xE9,
-0x38, 0x47, 0x38, 0xAF,
-0x34, 0x20,
-0x2A, 0x30,
+ 0x38, 0x47, 0x38, 0xAF,
+ 0x34, 0x20,
+ 0x2A, 0x30,
-0x00, 0xE0,
-0x0D, 0x20,
-0x32, 0x20,
-0x05, 0x20,
+ 0x00, 0xE0,
+ 0x0D, 0x20,
+ 0x32, 0x20,
+ 0x05, 0x20,
-0x87, 0x80, 0x57, 0xE9,
-0x1F, 0x54, 0x57, 0x9F,
+ 0x87, 0x80, 0x57, 0xE9,
+ 0x1F, 0x54, 0x57, 0x9F,
-0x17, 0x42, 0x56, 0x9F,
-0x00, 0xE0,
-0x3B, 0x6A,
+ 0x17, 0x42, 0x56, 0x9F,
+ 0x00, 0xE0,
+ 0x3B, 0x6A,
-0x3F, 0x8F, 0x51, 0x9F,
-0x37, 0x1E, 0x4F, 0xE9,
+ 0x3F, 0x8F, 0x51, 0x9F,
+ 0x37, 0x1E, 0x4F, 0xE9,
-0x37, 0x32, 0x2A, 0xAF,
-0x00, 0xE0,
-0x32, 0x00,
+ 0x37, 0x32, 0x2A, 0xAF,
+ 0x00, 0xE0,
+ 0x32, 0x00,
-0x00, 0x80, 0x00, 0xE8,
-0x27, 0xC0, 0x44, 0xC0,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x27, 0xC0, 0x44, 0xC0,
-0x36, 0x1F, 0x4F, 0xE9,
-0x1F, 0x1F, 0x26, 0xDF,
+ 0x36, 0x1F, 0x4F, 0xE9,
+ 0x1F, 0x1F, 0x26, 0xDF,
-0x37, 0x1B, 0x37, 0xBF,
-0x17, 0x26, 0x17, 0xDF,
+ 0x37, 0x1B, 0x37, 0xBF,
+ 0x17, 0x26, 0x17, 0xDF,
-0x3E, 0x17, 0x4F, 0xE9,
-0x3F, 0x3F, 0x4F, 0xE9,
+ 0x3E, 0x17, 0x4F, 0xE9,
+ 0x3F, 0x3F, 0x4F, 0xE9,
-0x34, 0x1F, 0x34, 0xAF,
-0x2B, 0x05,
-0xA7, 0x20,
+ 0x34, 0x1F, 0x34, 0xAF,
+ 0x2B, 0x05,
+ 0xA7, 0x20,
-0x33, 0x2B, 0x37, 0xDF,
-0x27, 0x17, 0xC0, 0xAF,
+ 0x33, 0x2B, 0x37, 0xDF,
+ 0x27, 0x17, 0xC0, 0xAF,
-0x34, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x34, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2D, 0x21, 0x1A, 0xB0,
-0x25, 0x21, 0x31, 0xB0,
+ 0x2D, 0x21, 0x1A, 0xB0,
+ 0x25, 0x21, 0x31, 0xB0,
-0x0D, 0x21, 0x1A, 0xB2,
-0x05, 0x21, 0x31, 0xB2,
+ 0x0D, 0x21, 0x1A, 0xB2,
+ 0x05, 0x21, 0x31, 0xB2,
-0x03, 0x80, 0x2A, 0xEA,
-0x17, 0xC1, 0x2B, 0xBD,
+ 0x03, 0x80, 0x2A, 0xEA,
+ 0x17, 0xC1, 0x2B, 0xBD,
-0x2D, 0x20,
-0x25, 0x20,
-0x05, 0x20,
-0x0D, 0x20,
+ 0x2D, 0x20,
+ 0x25, 0x20,
+ 0x05, 0x20,
+ 0x0D, 0x20,
-0xB3, 0x68,
-0x97, 0x25,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0x68,
+ 0x97, 0x25,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0xC0, 0x33, 0xAF,
-0x2F, 0xC0, 0x21, 0xC0,
+ 0x33, 0xC0, 0x33, 0xAF,
+ 0x2F, 0xC0, 0x21, 0xC0,
-0x16, 0x42, 0x56, 0x9F,
-0x3C, 0x27, 0x4F, 0xE9,
+ 0x16, 0x42, 0x56, 0x9F,
+ 0x3C, 0x27, 0x4F, 0xE9,
-0x1E, 0x62, 0x57, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1E, 0x62, 0x57, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x21, 0x31, 0xB4,
-0x2D, 0x21, 0x1A, 0xB4,
+ 0x25, 0x21, 0x31, 0xB4,
+ 0x2D, 0x21, 0x1A, 0xB4,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x33, 0x05,
-0x00, 0xE0,
-0x28, 0x19, 0x60, 0xEC,
+ 0x33, 0x05,
+ 0x00, 0xE0,
+ 0x28, 0x19, 0x60, 0xEC,
-0x0D, 0x21, 0x1A, 0xB6,
-0x05, 0x21, 0x31, 0xB6,
+ 0x0D, 0x21, 0x1A, 0xB6,
+ 0x05, 0x21, 0x31, 0xB6,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0xE0,
-0x2F, 0x20,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0xE0,
+ 0x2F, 0x20,
-0x23, 0x3B, 0x33, 0xAD,
-0x1E, 0x26, 0x1E, 0xDF,
+ 0x23, 0x3B, 0x33, 0xAD,
+ 0x1E, 0x26, 0x1E, 0xDF,
-0xA7, 0x1E, 0x4F, 0xE9,
-0x17, 0x26, 0x16, 0xDF,
+ 0xA7, 0x1E, 0x4F, 0xE9,
+ 0x17, 0x26, 0x16, 0xDF,
-0x2D, 0x20,
-0x00, 0xE0,
-0xA8, 0x3F, 0x4F, 0xE9,
+ 0x2D, 0x20,
+ 0x00, 0xE0,
+ 0xA8, 0x3F, 0x4F, 0xE9,
-0x2F, 0x2F, 0x1E, 0xAF,
-0x25, 0x20,
-0x00, 0xE0,
+ 0x2F, 0x2F, 0x1E, 0xAF,
+ 0x25, 0x20,
+ 0x00, 0xE0,
-0xA4, 0x16, 0x4F, 0xE9,
-0x0F, 0xC0, 0x21, 0xC2,
+ 0xA4, 0x16, 0x4F, 0xE9,
+ 0x0F, 0xC0, 0x21, 0xC2,
-0xA6, 0x80, 0x4F, 0xE9,
-0x1F, 0x62, 0x57, 0x9F,
+ 0xA6, 0x80, 0x4F, 0xE9,
+ 0x1F, 0x62, 0x57, 0x9F,
-0x0D, 0x20,
-0x05, 0x20,
-0x2F, 0xC0, 0x21, 0xC6,
+ 0x0D, 0x20,
+ 0x05, 0x20,
+ 0x2F, 0xC0, 0x21, 0xC6,
-0x3F, 0x2F, 0x5D, 0x9F,
-0x00, 0xE0,
-0x0F, 0x20,
+ 0x3F, 0x2F, 0x5D, 0x9F,
+ 0x00, 0xE0,
+ 0x0F, 0x20,
-0x17, 0x50, 0x56, 0x9F,
-0xA5, 0x37, 0x4F, 0xE9,
+ 0x17, 0x50, 0x56, 0x9F,
+ 0xA5, 0x37, 0x4F, 0xE9,
-0x06, 0xC0, 0x21, 0xC4,
-0x0F, 0x17, 0x0F, 0xAF,
+ 0x06, 0xC0, 0x21, 0xC4,
+ 0x0F, 0x17, 0x0F, 0xAF,
-0x37, 0x0F, 0x5C, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x37, 0x0F, 0x5C, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2F, 0x20,
-0x00, 0xE0,
-0xA3, 0x80, 0x4F, 0xE9,
+ 0x2F, 0x20,
+ 0x00, 0xE0,
+ 0xA3, 0x80, 0x4F, 0xE9,
-0x06, 0x20,
-0x00, 0xE0,
-0x1F, 0x26, 0x1F, 0xDF,
+ 0x06, 0x20,
+ 0x00, 0xE0,
+ 0x1F, 0x26, 0x1F, 0xDF,
-0x17, 0x26, 0x17, 0xDF,
-0x35, 0x17, 0x4F, 0xE9,
+ 0x17, 0x26, 0x17, 0xDF,
+ 0x35, 0x17, 0x4F, 0xE9,
-0xA1, 0x1F, 0x4F, 0xE9,
-0xA2, 0x3F, 0x4F, 0xE9,
+ 0xA1, 0x1F, 0x4F, 0xE9,
+ 0xA2, 0x3F, 0x4F, 0xE9,
-0x06, 0x06, 0x1F, 0xAF,
-0x39, 0x37, 0x4F, 0xE9,
+ 0x06, 0x06, 0x1F, 0xAF,
+ 0x39, 0x37, 0x4F, 0xE9,
-0x2F, 0x2F, 0x17, 0xAF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x2F, 0x2F, 0x17, 0xAF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xA0, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA0, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x31, 0x80, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x80, 0x4F, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x57, 0x39, 0x20, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x57, 0x39, 0x20, 0xE9,
-0x16, 0x28, 0x20, 0xE9,
-0x1D, 0x3B, 0x20, 0xE9,
+ 0x16, 0x28, 0x20, 0xE9,
+ 0x1D, 0x3B, 0x20, 0xE9,
-0x1E, 0x2B, 0x20, 0xE9,
-0x2B, 0x32, 0x20, 0xE9,
+ 0x1E, 0x2B, 0x20, 0xE9,
+ 0x2B, 0x32, 0x20, 0xE9,
-0x1C, 0x23, 0x20, 0xE9,
-0x57, 0x36, 0x20, 0xE9,
+ 0x1C, 0x23, 0x20, 0xE9,
+ 0x57, 0x36, 0x20, 0xE9,
-0x00, 0x80, 0xA0, 0xE9,
-0x40, 0x40, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x40, 0x40, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x90, 0xE2,
-0x00, 0xE0,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x90, 0xE2,
+ 0x00, 0xE0,
-0x68, 0xFF, 0x20, 0xEA,
-0x19, 0xC8, 0xC1, 0xCD,
+ 0x68, 0xFF, 0x20, 0xEA,
+ 0x19, 0xC8, 0xC1, 0xCD,
-0x1F, 0xD7, 0x18, 0xBD,
-0x3F, 0xD7, 0x22, 0xBD,
+ 0x1F, 0xD7, 0x18, 0xBD,
+ 0x3F, 0xD7, 0x22, 0xBD,
-0x9F, 0x41, 0x49, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9F, 0x41, 0x49, 0xBD,
+ 0x00, 0x80, 0x00, 0xE8,
-0x25, 0x41, 0x49, 0xBD,
-0x2D, 0x41, 0x51, 0xBD,
+ 0x25, 0x41, 0x49, 0xBD,
+ 0x2D, 0x41, 0x51, 0xBD,
-0x0D, 0x80, 0x07, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x0D, 0x80, 0x07, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x35, 0x40, 0x48, 0xBD,
-0x3D, 0x40, 0x50, 0xBD,
+ 0x35, 0x40, 0x48, 0xBD,
+ 0x3D, 0x40, 0x50, 0xBD,
-0x00, 0x80, 0x00, 0xE8,
-0x25, 0x30,
-0x2D, 0x30,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x25, 0x30,
+ 0x2D, 0x30,
-0x35, 0x30,
-0xB5, 0x30,
-0xBD, 0x30,
-0x3D, 0x30,
+ 0x35, 0x30,
+ 0xB5, 0x30,
+ 0xBD, 0x30,
+ 0x3D, 0x30,
-0x9C, 0xA7, 0x5B, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x9C, 0xA7, 0x5B, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x67, 0xFF, 0x0A, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x67, 0xFF, 0x0A, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC9, 0x41, 0xC8, 0xEC,
-0x42, 0xE1,
-0x00, 0xE0,
+ 0xC9, 0x41, 0xC8, 0xEC,
+ 0x42, 0xE1,
+ 0x00, 0xE0,
-0x65, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x65, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0xC8, 0x40, 0xC0, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC8, 0x40, 0xC0, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x62, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0x62, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
};
static unsigned char warp_g400_t2gz[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x78, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x78, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x69, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x69, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x25, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x25, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x44, 0x54, 0xB4,
-0x1A, 0x44, 0x64, 0xB4,
+ 0x2A, 0x44, 0x54, 0xB4,
+ 0x1A, 0x44, 0x64, 0xB4,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x9F, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x9F, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xBE, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xBE, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x7D, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x7D, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gza[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x7C, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x7C, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x6D, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x6D, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x29, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x29, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0F, 0xCF, 0x74, 0xC6,
-0x3D, 0xCF, 0x74, 0xC2,
+ 0x0F, 0xCF, 0x74, 0xC6,
+ 0x3D, 0xCF, 0x74, 0xC2,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x0F, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB4,
-0x02, 0x44, 0x64, 0xB4,
+ 0x0A, 0x44, 0x54, 0xB4,
+ 0x02, 0x44, 0x64, 0xB4,
-0x2A, 0x44, 0x54, 0xB6,
-0x1A, 0x44, 0x64, 0xB6,
+ 0x2A, 0x44, 0x54, 0xB6,
+ 0x1A, 0x44, 0x64, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x9B, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x9B, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xBA, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xBA, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x79, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x79, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzaf[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x81, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x81, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x72, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x72, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x37, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x37, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x2E, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x2E, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x0F, 0xCF, 0x74, 0xC6,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x0F, 0xCF, 0x74, 0xC6,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x0F, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB4,
-0x02, 0x44, 0x64, 0xB4,
+ 0x0A, 0x44, 0x54, 0xB4,
+ 0x02, 0x44, 0x64, 0xB4,
-0x2A, 0x44, 0x54, 0xB6,
-0x1A, 0x44, 0x64, 0xB6,
+ 0x2A, 0x44, 0x54, 0xB6,
+ 0x1A, 0x44, 0x64, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x3D, 0xCF, 0x75, 0xC6,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3D, 0xCF, 0x75, 0xC6,
+ 0x00, 0x80, 0x00, 0xE8,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x0A, 0x45, 0x55, 0xB6,
-0x02, 0x45, 0x65, 0xB6,
+ 0x0A, 0x45, 0x55, 0xB6,
+ 0x02, 0x45, 0x65, 0xB6,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x31, 0x3D, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x38, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x96, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x96, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xB5, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB5, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x74, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x74, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzf[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x7D, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x7D, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x6E, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x6E, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x39, 0xE5, 0x2C, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x88, 0x73, 0x5E, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0F, 0xCF, 0x75, 0xC6,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x0F, 0xCF, 0x75, 0xC6,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x28, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x28, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x31, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x31, 0x0F, 0x20, 0xE9,
-0x0A, 0x44, 0x54, 0xB4,
-0x02, 0x44, 0x64, 0xB4,
+ 0x0A, 0x44, 0x54, 0xB4,
+ 0x02, 0x44, 0x64, 0xB4,
-0x2A, 0x45, 0x55, 0xB6,
-0x1A, 0x45, 0x65, 0xB6,
+ 0x2A, 0x45, 0x55, 0xB6,
+ 0x1A, 0x45, 0x65, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x39, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x9A, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x9A, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xBB, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xBB, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x78, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x78, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzs[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x85, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x85, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x76, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x76, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x0F, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x0F, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x31, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x31, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0F, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB4,
-0x1A, 0x44, 0x64, 0xB4,
+ 0x2A, 0x44, 0x54, 0xB4,
+ 0x1A, 0x44, 0x64, 0xB4,
-0x0A, 0x45, 0x55, 0xB0,
-0x02, 0x45, 0x65, 0xB0,
+ 0x0A, 0x45, 0x55, 0xB0,
+ 0x02, 0x45, 0x65, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x2A, 0x45, 0x55, 0xB2,
-0x1A, 0x45, 0x65, 0xB2,
+ 0x2A, 0x45, 0x55, 0xB2,
+ 0x1A, 0x45, 0x65, 0xB2,
-0x0A, 0x45, 0x55, 0xB4,
-0x02, 0x45, 0x65, 0xB4,
+ 0x0A, 0x45, 0x55, 0xB4,
+ 0x02, 0x45, 0x65, 0xB4,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0xA7, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA7, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x92, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x92, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xB2, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB2, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x70, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x70, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzsa[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x8A, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x8A, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x7B, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x7B, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x0F, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x0F, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x36, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x36, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0F, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB4,
-0x1A, 0x44, 0x64, 0xB4,
+ 0x2A, 0x44, 0x54, 0xB4,
+ 0x1A, 0x44, 0x64, 0xB4,
-0x0A, 0x45, 0x55, 0xB0,
-0x02, 0x45, 0x65, 0xB0,
+ 0x0A, 0x45, 0x55, 0xB0,
+ 0x02, 0x45, 0x65, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x55, 0xB2,
-0x1A, 0x45, 0x65, 0xB2,
+ 0x2A, 0x45, 0x55, 0xB2,
+ 0x1A, 0x45, 0x65, 0xB2,
-0x0A, 0x45, 0x55, 0xB4,
-0x02, 0x45, 0x65, 0xB4,
+ 0x0A, 0x45, 0x55, 0xB4,
+ 0x02, 0x45, 0x65, 0xB4,
-0x0F, 0xCF, 0x74, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x74, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x44, 0x54, 0xB6,
-0x1A, 0x44, 0x64, 0xB6,
+ 0x2A, 0x44, 0x54, 0xB6,
+ 0x1A, 0x44, 0x64, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x8D, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x8D, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xAD, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xAD, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x6B, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x6B, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzsaf[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x8E, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x8E, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x7F, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x7F, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x0F, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x0F, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x3A, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x3A, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0F, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB4,
-0x1A, 0x44, 0x64, 0xB4,
+ 0x2A, 0x44, 0x54, 0xB4,
+ 0x1A, 0x44, 0x64, 0xB4,
-0x0A, 0x45, 0x55, 0xB0,
-0x02, 0x45, 0x65, 0xB0,
+ 0x0A, 0x45, 0x55, 0xB0,
+ 0x02, 0x45, 0x65, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x55, 0xB2,
-0x1A, 0x45, 0x65, 0xB2,
+ 0x2A, 0x45, 0x55, 0xB2,
+ 0x1A, 0x45, 0x65, 0xB2,
-0x0A, 0x45, 0x55, 0xB4,
-0x02, 0x45, 0x65, 0xB4,
+ 0x0A, 0x45, 0x55, 0xB4,
+ 0x02, 0x45, 0x65, 0xB4,
-0x0F, 0xCF, 0x74, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x74, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x44, 0x54, 0xB6,
-0x1A, 0x44, 0x64, 0xB6,
+ 0x2A, 0x44, 0x54, 0xB6,
+ 0x1A, 0x44, 0x64, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x0A, 0x45, 0x55, 0xB6,
-0x02, 0x45, 0x65, 0xB6,
+ 0x0A, 0x45, 0x55, 0xB6,
+ 0x02, 0x45, 0x65, 0xB6,
-0x3D, 0xCF, 0x75, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x75, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x31, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x31, 0x3D, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x38, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x89, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x89, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xA9, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xA9, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x67, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x67, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_t2gzsf[] = {
-0x00, 0x8A, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x8A, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x0A, 0x40, 0x50, 0xBF,
-0x2A, 0x40, 0x60, 0xBF,
+ 0x0A, 0x40, 0x50, 0xBF,
+ 0x2A, 0x40, 0x60, 0xBF,
-0x32, 0x41, 0x51, 0xBF,
-0x3A, 0x41, 0x61, 0xBF,
+ 0x32, 0x41, 0x51, 0xBF,
+ 0x3A, 0x41, 0x61, 0xBF,
-0xC3, 0x6B,
-0xD3, 0x6B,
-0x00, 0x8A, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xD3, 0x6B,
+ 0x00, 0x8A, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x53, 0xA0, 0xE8,
-0xAD, 0xEE, 0x23, 0x9F,
-0x00, 0xE0,
-0x51, 0x04,
+ 0xAD, 0xEE, 0x23, 0x9F,
+ 0x00, 0xE0,
+ 0x51, 0x04,
-0x90, 0xE2,
-0x61, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x61, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x51, 0x41, 0xE0, 0xEC,
-0x39, 0x67, 0xB1, 0xE8,
+ 0x51, 0x41, 0xE0, 0xEC,
+ 0x39, 0x67, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x63, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x63, 0xA0, 0xE8,
-0x61, 0x41, 0xE0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x61, 0x41, 0xE0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x8A, 0x80, 0x15, 0xEA,
-0x10, 0x04,
-0x20, 0x04,
+ 0x8A, 0x80, 0x15, 0xEA,
+ 0x10, 0x04,
+ 0x20, 0x04,
-0x61, 0x51, 0xE0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x61, 0x51, 0xE0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x52, 0xBF,
-0x0F, 0x52, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x52, 0xBF,
+ 0x0F, 0x52, 0xA0, 0xE8,
-0x1A, 0x42, 0x62, 0xBF,
-0x1E, 0x51, 0x60, 0xEA,
+ 0x1A, 0x42, 0x62, 0xBF,
+ 0x1E, 0x51, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x0E, 0x61, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x0E, 0x61, 0x60, 0xEA,
-0x32, 0x40, 0x50, 0xBD,
-0x22, 0x40, 0x60, 0xBD,
+ 0x32, 0x40, 0x50, 0xBD,
+ 0x22, 0x40, 0x60, 0xBD,
-0x12, 0x41, 0x51, 0xBD,
-0x3A, 0x41, 0x61, 0xBD,
+ 0x12, 0x41, 0x51, 0xBD,
+ 0x3A, 0x41, 0x61, 0xBD,
-0xBF, 0x2F, 0x0E, 0xBD,
-0x97, 0xE2,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x0E, 0xBD,
+ 0x97, 0xE2,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x35, 0x48, 0xB1, 0xE8,
-0x3D, 0x59, 0xB1, 0xE8,
+ 0x35, 0x48, 0xB1, 0xE8,
+ 0x3D, 0x59, 0xB1, 0xE8,
-0x46, 0x31, 0x46, 0xBF,
-0x56, 0x31, 0x56, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x66, 0x31, 0x66, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x66, 0x31, 0x66, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
-0x67, 0x39, 0x67, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
+ 0x67, 0x39, 0x67, 0xBF,
-0x7B, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x7B, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x35, 0x00,
-0x3D, 0x00,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x35, 0x00,
+ 0x3D, 0x00,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0x8D, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0x8D, 0x2F, 0x1E, 0xBD,
-0x43, 0x75, 0xF8, 0xEC,
-0x35, 0x20,
-0x3D, 0x20,
+ 0x43, 0x75, 0xF8, 0xEC,
+ 0x35, 0x20,
+ 0x3D, 0x20,
-0x43, 0x43, 0x2D, 0xDF,
-0x53, 0x53, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x53, 0x53, 0x2D, 0xDF,
-0xAE, 0x1E, 0x0E, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x0E, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x48, 0x35, 0x48, 0xBF,
-0x58, 0x35, 0x58, 0xBF,
+ 0x48, 0x35, 0x48, 0xBF,
+ 0x58, 0x35, 0x58, 0xBF,
-0x68, 0x35, 0x68, 0xBF,
-0x49, 0x3D, 0x49, 0xBF,
+ 0x68, 0x35, 0x68, 0xBF,
+ 0x49, 0x3D, 0x49, 0xBF,
-0x59, 0x3D, 0x59, 0xBF,
-0x69, 0x3D, 0x69, 0xBF,
+ 0x59, 0x3D, 0x59, 0xBF,
+ 0x69, 0x3D, 0x69, 0xBF,
-0x63, 0x63, 0x2D, 0xDF,
-0x4D, 0x7D, 0xF8, 0xEC,
+ 0x63, 0x63, 0x2D, 0xDF,
+ 0x4D, 0x7D, 0xF8, 0xEC,
-0x59, 0xE3,
-0x00, 0xE0,
-0xB8, 0x38, 0x33, 0xBF,
+ 0x59, 0xE3,
+ 0x00, 0xE0,
+ 0xB8, 0x38, 0x33, 0xBF,
-0x2D, 0x73,
-0x30, 0x76,
-0x18, 0x3A, 0x41, 0xE9,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x18, 0x3A, 0x41, 0xE9,
-0x3F, 0x53, 0xA0, 0xE8,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x3F, 0x53, 0xA0, 0xE8,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x63, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x63, 0xA0, 0xE8,
-0x50, 0x70, 0xF8, 0xEC,
-0x2B, 0x50, 0x3C, 0xE9,
+ 0x50, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x50, 0x3C, 0xE9,
-0x1F, 0x0F, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x0F, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x59, 0x78, 0xF8, 0xEC,
-0x00, 0x80, 0x00, 0xE8,
+ 0x59, 0x78, 0xF8, 0xEC,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x46, 0x37, 0x46, 0xDF,
-0x56, 0x3F, 0x56, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x56, 0x3F, 0x56, 0xDF,
-0x2B, 0x40, 0x3D, 0xE9,
-0x66, 0x3D, 0x66, 0xDF,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x66, 0x3D, 0x66, 0xDF,
-0x1D, 0x32, 0x41, 0xE9,
-0x67, 0x3D, 0x67, 0xDF,
+ 0x1D, 0x32, 0x41, 0xE9,
+ 0x67, 0x3D, 0x67, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3F, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3F, 0x57, 0xDF,
-0x2A, 0x40, 0x20, 0xE9,
-0x59, 0x3F, 0x59, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x59, 0x3F, 0x59, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x69, 0x3D, 0x69, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x69, 0x3D, 0x69, 0xDF,
-0x48, 0x37, 0x48, 0xDF,
-0x58, 0x3F, 0x58, 0xDF,
+ 0x48, 0x37, 0x48, 0xDF,
+ 0x58, 0x3F, 0x58, 0xDF,
-0x68, 0x3D, 0x68, 0xDF,
-0x49, 0x37, 0x49, 0xDF,
+ 0x68, 0x3D, 0x68, 0xDF,
+ 0x49, 0x37, 0x49, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x0F, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x0F, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x54, 0xB0,
-0x02, 0x44, 0x64, 0xB0,
+ 0x0A, 0x44, 0x54, 0xB0,
+ 0x02, 0x44, 0x64, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB2,
-0x1A, 0x44, 0x64, 0xB2,
+ 0x2A, 0x44, 0x54, 0xB2,
+ 0x1A, 0x44, 0x64, 0xB2,
-0x36, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x36, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0F, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x54, 0xB4,
-0x1A, 0x44, 0x64, 0xB4,
+ 0x2A, 0x44, 0x54, 0xB4,
+ 0x1A, 0x44, 0x64, 0xB4,
-0x0A, 0x45, 0x55, 0xB0,
-0x02, 0x45, 0x65, 0xB0,
+ 0x0A, 0x45, 0x55, 0xB0,
+ 0x02, 0x45, 0x65, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x55, 0xB2,
-0x1A, 0x45, 0x65, 0xB2,
+ 0x2A, 0x45, 0x55, 0xB2,
+ 0x1A, 0x45, 0x65, 0xB2,
-0x0A, 0x45, 0x55, 0xB4,
-0x02, 0x45, 0x65, 0xB4,
+ 0x0A, 0x45, 0x55, 0xB4,
+ 0x02, 0x45, 0x65, 0xB4,
-0x0F, 0xCF, 0x75, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0F, 0xCF, 0x75, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x31, 0x0F, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x31, 0x0F, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x45, 0x55, 0xB6,
-0x1A, 0x45, 0x65, 0xB6,
+ 0x2A, 0x45, 0x55, 0xB6,
+ 0x1A, 0x45, 0x65, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x56, 0xBF,
-0x1A, 0x46, 0x66, 0xBF,
+ 0x2A, 0x46, 0x56, 0xBF,
+ 0x1A, 0x46, 0x66, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x0A, 0x47, 0x57, 0xBF,
-0x02, 0x47, 0x67, 0xBF,
+ 0x0A, 0x47, 0x57, 0xBF,
+ 0x02, 0x47, 0x67, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x53, 0xBF,
-0x1A, 0x43, 0x63, 0xBF,
+ 0x2A, 0x43, 0x53, 0xBF,
+ 0x1A, 0x43, 0x63, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x39, 0x4F, 0xE9,
-0x0A, 0x48, 0x58, 0xBF,
-0x02, 0x48, 0x68, 0xBF,
+ 0x0A, 0x48, 0x58, 0xBF,
+ 0x02, 0x48, 0x68, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x2A, 0x49, 0x59, 0xBF,
-0x1A, 0x49, 0x69, 0xBF,
+ 0x2A, 0x49, 0x59, 0xBF,
+ 0x1A, 0x49, 0x69, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x82, 0x30, 0x57, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x82, 0x30, 0x57, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x83, 0x38, 0x57, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x83, 0x38, 0x57, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x84, 0x31, 0x5E, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x84, 0x31, 0x5E, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x85, 0x39, 0x5E, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x85, 0x39, 0x5E, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
-0x8B, 0x3E, 0xBF, 0xEA,
+ 0x87, 0x77, 0x57, 0xE9,
+ 0x8B, 0x3E, 0xBF, 0xEA,
-0x80, 0x30, 0x57, 0xE9,
-0x81, 0x38, 0x57, 0xE9,
+ 0x80, 0x30, 0x57, 0xE9,
+ 0x81, 0x38, 0x57, 0xE9,
-0x82, 0x31, 0x57, 0xE9,
-0x86, 0x78, 0x57, 0xE9,
+ 0x82, 0x31, 0x57, 0xE9,
+ 0x86, 0x78, 0x57, 0xE9,
-0x83, 0x39, 0x57, 0xE9,
-0x87, 0x79, 0x57, 0xE9,
+ 0x83, 0x39, 0x57, 0xE9,
+ 0x87, 0x79, 0x57, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
-0x8A, 0x34, 0x20, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
+ 0x8A, 0x34, 0x20, 0xE9,
-0x8B, 0x3C, 0x20, 0xE9,
-0x37, 0x50, 0x60, 0xBD,
+ 0x8B, 0x3C, 0x20, 0xE9,
+ 0x37, 0x50, 0x60, 0xBD,
-0x57, 0x0D, 0x20, 0xE9,
-0x35, 0x51, 0x61, 0xBD,
+ 0x57, 0x0D, 0x20, 0xE9,
+ 0x35, 0x51, 0x61, 0xBD,
-0x2B, 0x50, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x50, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x0E, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x0E, 0x77,
-0x24, 0x51, 0x20, 0xE9,
-0x8D, 0xFF, 0x20, 0xEA,
+ 0x24, 0x51, 0x20, 0xE9,
+ 0x8D, 0xFF, 0x20, 0xEA,
-0x16, 0x0E, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x0E, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x0B, 0x46, 0xA0, 0xE8,
-0x1B, 0x56, 0xA0, 0xE8,
+ 0x0B, 0x46, 0xA0, 0xE8,
+ 0x1B, 0x56, 0xA0, 0xE8,
-0x2B, 0x66, 0xA0, 0xE8,
-0x0C, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x66, 0xA0, 0xE8,
+ 0x0C, 0x47, 0xA0, 0xE8,
-0x1C, 0x57, 0xA0, 0xE8,
-0x2C, 0x67, 0xA0, 0xE8,
+ 0x1C, 0x57, 0xA0, 0xE8,
+ 0x2C, 0x67, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x57, 0x80, 0x57, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x57, 0x80, 0x57, 0xCF,
-0x66, 0x33, 0x66, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x66, 0x33, 0x66, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x67, 0x3B, 0x67, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x67, 0x3B, 0x67, 0xCF,
-0x0B, 0x48, 0xA0, 0xE8,
-0x1B, 0x58, 0xA0, 0xE8,
+ 0x0B, 0x48, 0xA0, 0xE8,
+ 0x1B, 0x58, 0xA0, 0xE8,
-0x2B, 0x68, 0xA0, 0xE8,
-0x0C, 0x49, 0xA0, 0xE8,
+ 0x2B, 0x68, 0xA0, 0xE8,
+ 0x0C, 0x49, 0xA0, 0xE8,
-0x1C, 0x59, 0xA0, 0xE8,
-0x2C, 0x69, 0xA0, 0xE8,
+ 0x1C, 0x59, 0xA0, 0xE8,
+ 0x2C, 0x69, 0xA0, 0xE8,
-0x0B, 0x00,
-0x1B, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x0B, 0x00,
+ 0x1B, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x0C, 0x00,
-0x1C, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x0C, 0x00,
+ 0x1C, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x0B, 0x65,
-0x1B, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x0B, 0x65,
+ 0x1B, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x0C, 0x65,
-0x1C, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x0C, 0x65,
+ 0x1C, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x0B, 0x1B, 0x60, 0xEC,
-0x34, 0xD7, 0x34, 0xAD,
+ 0x0B, 0x1B, 0x60, 0xEC,
+ 0x34, 0xD7, 0x34, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x0C, 0x1C, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x0C, 0x1C, 0x60, 0xEC,
-0x3C, 0xD7, 0x3C, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3C, 0xD7, 0x3C, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x0B, 0x2B, 0xDE, 0xE8,
-0x1B, 0x80, 0xDE, 0xE8,
+ 0x0B, 0x2B, 0xDE, 0xE8,
+ 0x1B, 0x80, 0xDE, 0xE8,
-0x34, 0x80, 0x34, 0xBD,
-0x3C, 0x80, 0x3C, 0xBD,
+ 0x34, 0x80, 0x34, 0xBD,
+ 0x3C, 0x80, 0x3C, 0xBD,
-0x33, 0xD7, 0x0B, 0xBD,
-0x3B, 0xD7, 0x1B, 0xBD,
+ 0x33, 0xD7, 0x0B, 0xBD,
+ 0x3B, 0xD7, 0x1B, 0xBD,
-0x48, 0x80, 0x48, 0xCF,
-0x59, 0x80, 0x59, 0xCF,
+ 0x48, 0x80, 0x48, 0xCF,
+ 0x59, 0x80, 0x59, 0xCF,
-0x68, 0x33, 0x68, 0xCF,
-0x49, 0x3B, 0x49, 0xCF,
+ 0x68, 0x33, 0x68, 0xCF,
+ 0x49, 0x3B, 0x49, 0xCF,
-0xAD, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xAD, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x58, 0x33, 0x58, 0xCF,
-0x69, 0x3B, 0x69, 0xCF,
+ 0x58, 0x33, 0x58, 0xCF,
+ 0x69, 0x3B, 0x69, 0xCF,
-0x6B, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x6B, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgz[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x58, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x58, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x4A, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x4A, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x1D, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x1D, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x44, 0x4C, 0xB4,
-0x1A, 0x44, 0x54, 0xB4,
+ 0x2A, 0x44, 0x4C, 0xB4,
+ 0x1A, 0x44, 0x54, 0xB4,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0xAF, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0xAF, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xD6, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xD6, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x9D, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x9D, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgza[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x5C, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x5C, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x4E, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x4E, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x27, 0xCF, 0x74, 0xC6,
-0x3D, 0xCF, 0x74, 0xC2,
+ 0x27, 0xCF, 0x74, 0xC6,
+ 0x3D, 0xCF, 0x74, 0xC2,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x20, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x20, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x27, 0x20, 0xE9,
-0x0A, 0x44, 0x4C, 0xB4,
-0x02, 0x44, 0x54, 0xB4,
+ 0x0A, 0x44, 0x4C, 0xB4,
+ 0x02, 0x44, 0x54, 0xB4,
-0x2A, 0x44, 0x4C, 0xB6,
-0x1A, 0x44, 0x54, 0xB6,
+ 0x2A, 0x44, 0x4C, 0xB6,
+ 0x1A, 0x44, 0x54, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0xAB, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0xAB, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xD3, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xD3, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x99, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x99, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzaf[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x61, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x61, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x53, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x53, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x31, 0x53, 0x2F, 0x9F,
-0x34, 0x37, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x34, 0x37, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x26, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x26, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x27, 0xCF, 0x74, 0xC6,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x27, 0xCF, 0x74, 0xC6,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x27, 0x20, 0xE9,
-0x0A, 0x44, 0x4C, 0xB4,
-0x02, 0x44, 0x54, 0xB4,
+ 0x0A, 0x44, 0x4C, 0xB4,
+ 0x02, 0x44, 0x54, 0xB4,
-0x2A, 0x44, 0x4C, 0xB6,
-0x1A, 0x44, 0x54, 0xB6,
+ 0x2A, 0x44, 0x4C, 0xB6,
+ 0x1A, 0x44, 0x54, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x3D, 0xCF, 0x75, 0xC6,
-0x00, 0x80, 0x00, 0xE8,
+ 0x3D, 0xCF, 0x75, 0xC6,
+ 0x00, 0x80, 0x00, 0xE8,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x0A, 0x45, 0x4D, 0xB6,
-0x02, 0x45, 0x55, 0xB6,
+ 0x0A, 0x45, 0x4D, 0xB6,
+ 0x02, 0x45, 0x55, 0xB6,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x31, 0x3D, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0xA6, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0xA6, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xCD, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xCD, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x94, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x94, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzf[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x5D, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x5D, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x4F, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x4F, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x3D, 0xCF, 0x74, 0xC0,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x39, 0xE5, 0x2C, 0x9F,
-0x34, 0x80, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x34, 0x80, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x88, 0x73, 0x5E, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x27, 0xCF, 0x75, 0xC6,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x27, 0xCF, 0x75, 0xC6,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x20, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x20, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x3D, 0xCF, 0x74, 0xC2,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x74, 0xC2,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x31, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x31, 0x27, 0x20, 0xE9,
-0x0A, 0x44, 0x4C, 0xB4,
-0x02, 0x44, 0x54, 0xB4,
+ 0x0A, 0x44, 0x4C, 0xB4,
+ 0x02, 0x44, 0x54, 0xB4,
-0x2A, 0x45, 0x4D, 0xB6,
-0x1A, 0x45, 0x55, 0xB6,
+ 0x2A, 0x45, 0x4D, 0xB6,
+ 0x1A, 0x45, 0x55, 0xB6,
-0x39, 0xE5, 0x2C, 0x9F,
-0x38, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x38, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0xAA, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0xAA, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xD3, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xD3, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x98, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x98, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzs[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x65, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x65, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x57, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x57, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x27, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x27, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x29, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x29, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x27, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB4,
-0x1A, 0x44, 0x54, 0xB4,
+ 0x2A, 0x44, 0x4C, 0xB4,
+ 0x1A, 0x44, 0x54, 0xB4,
-0x0A, 0x45, 0x4D, 0xB0,
-0x02, 0x45, 0x55, 0xB0,
+ 0x0A, 0x45, 0x4D, 0xB0,
+ 0x02, 0x45, 0x55, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x2A, 0x45, 0x4D, 0xB2,
-0x1A, 0x45, 0x55, 0xB2,
+ 0x2A, 0x45, 0x4D, 0xB2,
+ 0x1A, 0x45, 0x55, 0xB2,
-0x0A, 0x45, 0x4D, 0xB4,
-0x02, 0x45, 0x55, 0xB4,
+ 0x0A, 0x45, 0x4D, 0xB4,
+ 0x02, 0x45, 0x55, 0xB4,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x0A, 0x20,
+ 0x02, 0x20,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0xA7, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA7, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0xA2, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0xA2, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xCA, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xCA, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x90, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x90, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzsa[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x6A, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x6A, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x5C, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x5C, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x27, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x27, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x2E, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x2E, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x27, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB4,
-0x1A, 0x44, 0x54, 0xB4,
+ 0x2A, 0x44, 0x4C, 0xB4,
+ 0x1A, 0x44, 0x54, 0xB4,
-0x0A, 0x45, 0x4D, 0xB0,
-0x02, 0x45, 0x55, 0xB0,
+ 0x0A, 0x45, 0x4D, 0xB0,
+ 0x02, 0x45, 0x55, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x4D, 0xB2,
-0x1A, 0x45, 0x55, 0xB2,
+ 0x2A, 0x45, 0x4D, 0xB2,
+ 0x1A, 0x45, 0x55, 0xB2,
-0x0A, 0x45, 0x4D, 0xB4,
-0x02, 0x45, 0x55, 0xB4,
+ 0x0A, 0x45, 0x4D, 0xB4,
+ 0x02, 0x45, 0x55, 0xB4,
-0x27, 0xCF, 0x74, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x74, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x44, 0x4C, 0xB6,
-0x1A, 0x44, 0x54, 0xB6,
+ 0x2A, 0x44, 0x4C, 0xB6,
+ 0x1A, 0x44, 0x54, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0x9D, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0x9D, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xC5, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC5, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x8B, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x8B, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzsaf[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x6E, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x6E, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x60, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x60, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x27, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x27, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x32, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x32, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x27, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB4,
-0x1A, 0x44, 0x54, 0xB4,
+ 0x2A, 0x44, 0x4C, 0xB4,
+ 0x1A, 0x44, 0x54, 0xB4,
-0x0A, 0x45, 0x4D, 0xB0,
-0x02, 0x45, 0x55, 0xB0,
+ 0x0A, 0x45, 0x4D, 0xB0,
+ 0x02, 0x45, 0x55, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x4D, 0xB2,
-0x1A, 0x45, 0x55, 0xB2,
+ 0x2A, 0x45, 0x4D, 0xB2,
+ 0x1A, 0x45, 0x55, 0xB2,
-0x0A, 0x45, 0x4D, 0xB4,
-0x02, 0x45, 0x55, 0xB4,
+ 0x0A, 0x45, 0x4D, 0xB4,
+ 0x02, 0x45, 0x55, 0xB4,
-0x27, 0xCF, 0x74, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x74, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x9C, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9C, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x44, 0x4C, 0xB6,
-0x1A, 0x44, 0x54, 0xB6,
+ 0x2A, 0x44, 0x4C, 0xB6,
+ 0x1A, 0x44, 0x54, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x0A, 0x45, 0x4D, 0xB6,
-0x02, 0x45, 0x55, 0xB6,
+ 0x0A, 0x45, 0x4D, 0xB6,
+ 0x02, 0x45, 0x55, 0xB6,
-0x3D, 0xCF, 0x75, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x3D, 0xCF, 0x75, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x31, 0x3D, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x31, 0x3D, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x9D, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x9D, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x9E, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x9E, 0x39, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x30, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x30, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x38, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x38, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0x99, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0x99, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xC1, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC1, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x87, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x87, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
static unsigned char warp_g400_tgzsf[] = {
-0x00, 0x88, 0x98, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x88, 0x98, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
-0xFF, 0x80, 0xC0, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
+ 0xFF, 0x80, 0xC0, 0xE9,
+ 0x00, 0x80, 0x00, 0xE8,
-0x22, 0x40, 0x48, 0xBF,
-0x2A, 0x40, 0x50, 0xBF,
+ 0x22, 0x40, 0x48, 0xBF,
+ 0x2A, 0x40, 0x50, 0xBF,
-0x32, 0x41, 0x49, 0xBF,
-0x3A, 0x41, 0x51, 0xBF,
+ 0x32, 0x41, 0x49, 0xBF,
+ 0x3A, 0x41, 0x51, 0xBF,
-0xC3, 0x6B,
-0xCB, 0x6B,
-0x00, 0x88, 0x98, 0xE9,
+ 0xC3, 0x6B,
+ 0xCB, 0x6B,
+ 0x00, 0x88, 0x98, 0xE9,
-0x73, 0x7B, 0xC8, 0xEC,
-0x96, 0xE2,
-0x41, 0x04,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x96, 0xE2,
+ 0x41, 0x04,
-0x7B, 0x43, 0xA0, 0xE8,
-0x73, 0x4B, 0xA0, 0xE8,
+ 0x7B, 0x43, 0xA0, 0xE8,
+ 0x73, 0x4B, 0xA0, 0xE8,
-0xAD, 0xEE, 0x29, 0x9F,
-0x00, 0xE0,
-0x49, 0x04,
+ 0xAD, 0xEE, 0x29, 0x9F,
+ 0x00, 0xE0,
+ 0x49, 0x04,
-0x90, 0xE2,
-0x51, 0x04,
-0x31, 0x46, 0xB1, 0xE8,
+ 0x90, 0xE2,
+ 0x51, 0x04,
+ 0x31, 0x46, 0xB1, 0xE8,
-0x49, 0x41, 0xC0, 0xEC,
-0x39, 0x57, 0xB1, 0xE8,
+ 0x49, 0x41, 0xC0, 0xEC,
+ 0x39, 0x57, 0xB1, 0xE8,
-0x00, 0x04,
-0x46, 0xE2,
-0x73, 0x53, 0xA0, 0xE8,
+ 0x00, 0x04,
+ 0x46, 0xE2,
+ 0x73, 0x53, 0xA0, 0xE8,
-0x51, 0x41, 0xC0, 0xEC,
-0x31, 0x00,
-0x39, 0x00,
+ 0x51, 0x41, 0xC0, 0xEC,
+ 0x31, 0x00,
+ 0x39, 0x00,
-0x6A, 0x80, 0x15, 0xEA,
-0x08, 0x04,
-0x10, 0x04,
+ 0x6A, 0x80, 0x15, 0xEA,
+ 0x08, 0x04,
+ 0x10, 0x04,
-0x51, 0x49, 0xC0, 0xEC,
-0x2F, 0x41, 0x60, 0xEA,
+ 0x51, 0x49, 0xC0, 0xEC,
+ 0x2F, 0x41, 0x60, 0xEA,
-0x31, 0x20,
-0x39, 0x20,
-0x1F, 0x42, 0xA0, 0xE8,
+ 0x31, 0x20,
+ 0x39, 0x20,
+ 0x1F, 0x42, 0xA0, 0xE8,
-0x2A, 0x42, 0x4A, 0xBF,
-0x27, 0x4A, 0xA0, 0xE8,
+ 0x2A, 0x42, 0x4A, 0xBF,
+ 0x27, 0x4A, 0xA0, 0xE8,
-0x1A, 0x42, 0x52, 0xBF,
-0x1E, 0x49, 0x60, 0xEA,
+ 0x1A, 0x42, 0x52, 0xBF,
+ 0x1E, 0x49, 0x60, 0xEA,
-0x73, 0x7B, 0xC8, 0xEC,
-0x26, 0x51, 0x60, 0xEA,
+ 0x73, 0x7B, 0xC8, 0xEC,
+ 0x26, 0x51, 0x60, 0xEA,
-0x32, 0x40, 0x48, 0xBD,
-0x22, 0x40, 0x50, 0xBD,
+ 0x32, 0x40, 0x48, 0xBD,
+ 0x22, 0x40, 0x50, 0xBD,
-0x12, 0x41, 0x49, 0xBD,
-0x3A, 0x41, 0x51, 0xBD,
+ 0x12, 0x41, 0x49, 0xBD,
+ 0x3A, 0x41, 0x51, 0xBD,
-0xBF, 0x2F, 0x26, 0xBD,
-0x00, 0xE0,
-0x7B, 0x72,
+ 0xBF, 0x2F, 0x26, 0xBD,
+ 0x00, 0xE0,
+ 0x7B, 0x72,
-0x32, 0x20,
-0x22, 0x20,
-0x12, 0x20,
-0x3A, 0x20,
+ 0x32, 0x20,
+ 0x22, 0x20,
+ 0x12, 0x20,
+ 0x3A, 0x20,
-0x46, 0x31, 0x46, 0xBF,
-0x4E, 0x31, 0x4E, 0xBF,
+ 0x46, 0x31, 0x46, 0xBF,
+ 0x4E, 0x31, 0x4E, 0xBF,
-0xB3, 0xE2, 0x2D, 0x9F,
-0x00, 0x80, 0x00, 0xE8,
+ 0xB3, 0xE2, 0x2D, 0x9F,
+ 0x00, 0x80, 0x00, 0xE8,
-0x56, 0x31, 0x56, 0xBF,
-0x47, 0x39, 0x47, 0xBF,
+ 0x56, 0x31, 0x56, 0xBF,
+ 0x47, 0x39, 0x47, 0xBF,
-0x4F, 0x39, 0x4F, 0xBF,
-0x57, 0x39, 0x57, 0xBF,
+ 0x4F, 0x39, 0x4F, 0xBF,
+ 0x57, 0x39, 0x57, 0xBF,
-0x5C, 0x80, 0x07, 0xEA,
-0x24, 0x41, 0x20, 0xE9,
+ 0x5C, 0x80, 0x07, 0xEA,
+ 0x24, 0x41, 0x20, 0xE9,
-0x42, 0x73, 0xF8, 0xEC,
-0x00, 0xE0,
-0x2D, 0x73,
+ 0x42, 0x73, 0xF8, 0xEC,
+ 0x00, 0xE0,
+ 0x2D, 0x73,
-0x33, 0x72,
-0x0C, 0xE3,
-0xA5, 0x2F, 0x1E, 0xBD,
+ 0x33, 0x72,
+ 0x0C, 0xE3,
+ 0xA5, 0x2F, 0x1E, 0xBD,
-0x43, 0x43, 0x2D, 0xDF,
-0x4B, 0x4B, 0x2D, 0xDF,
+ 0x43, 0x43, 0x2D, 0xDF,
+ 0x4B, 0x4B, 0x2D, 0xDF,
-0xAE, 0x1E, 0x26, 0xBD,
-0x58, 0xE3,
-0x33, 0x66,
+ 0xAE, 0x1E, 0x26, 0xBD,
+ 0x58, 0xE3,
+ 0x33, 0x66,
-0x53, 0x53, 0x2D, 0xDF,
-0x00, 0x80, 0x00, 0xE8,
+ 0x53, 0x53, 0x2D, 0xDF,
+ 0x00, 0x80, 0x00, 0xE8,
-0xB8, 0x38, 0x33, 0xBF,
-0x00, 0xE0,
-0x59, 0xE3,
+ 0xB8, 0x38, 0x33, 0xBF,
+ 0x00, 0xE0,
+ 0x59, 0xE3,
-0x1E, 0x12, 0x41, 0xE9,
-0x1A, 0x22, 0x41, 0xE9,
+ 0x1E, 0x12, 0x41, 0xE9,
+ 0x1A, 0x22, 0x41, 0xE9,
-0x2B, 0x40, 0x3D, 0xE9,
-0x3F, 0x4B, 0xA0, 0xE8,
+ 0x2B, 0x40, 0x3D, 0xE9,
+ 0x3F, 0x4B, 0xA0, 0xE8,
-0x2D, 0x73,
-0x30, 0x76,
-0x05, 0x80, 0x3D, 0xEA,
+ 0x2D, 0x73,
+ 0x30, 0x76,
+ 0x05, 0x80, 0x3D, 0xEA,
-0x37, 0x43, 0xA0, 0xE8,
-0x3D, 0x53, 0xA0, 0xE8,
+ 0x37, 0x43, 0xA0, 0xE8,
+ 0x3D, 0x53, 0xA0, 0xE8,
-0x48, 0x70, 0xF8, 0xEC,
-0x2B, 0x48, 0x3C, 0xE9,
+ 0x48, 0x70, 0xF8, 0xEC,
+ 0x2B, 0x48, 0x3C, 0xE9,
-0x1F, 0x27, 0xBC, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x1F, 0x27, 0xBC, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
-0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x00, 0x80, 0x00, 0xE8,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
-0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
+ 0x15, 0xC0, 0x20, 0xE9,
-0x18, 0x3A, 0x41, 0xE9,
-0x1D, 0x32, 0x41, 0xE9,
+ 0x18, 0x3A, 0x41, 0xE9,
+ 0x1D, 0x32, 0x41, 0xE9,
-0x2A, 0x40, 0x20, 0xE9,
-0x56, 0x3D, 0x56, 0xDF,
+ 0x2A, 0x40, 0x20, 0xE9,
+ 0x56, 0x3D, 0x56, 0xDF,
-0x46, 0x37, 0x46, 0xDF,
-0x4E, 0x3F, 0x4E, 0xDF,
+ 0x46, 0x37, 0x46, 0xDF,
+ 0x4E, 0x3F, 0x4E, 0xDF,
-0x16, 0x30, 0x20, 0xE9,
-0x4F, 0x3F, 0x4F, 0xDF,
+ 0x16, 0x30, 0x20, 0xE9,
+ 0x4F, 0x3F, 0x4F, 0xDF,
-0x47, 0x37, 0x47, 0xDF,
-0x57, 0x3D, 0x57, 0xDF,
+ 0x47, 0x37, 0x47, 0xDF,
+ 0x57, 0x3D, 0x57, 0xDF,
-0x32, 0x32, 0x2D, 0xDF,
-0x22, 0x22, 0x2D, 0xDF,
+ 0x32, 0x32, 0x2D, 0xDF,
+ 0x22, 0x22, 0x2D, 0xDF,
-0x12, 0x12, 0x2D, 0xDF,
-0x3A, 0x3A, 0x2D, 0xDF,
+ 0x12, 0x12, 0x2D, 0xDF,
+ 0x3A, 0x3A, 0x2D, 0xDF,
-0x27, 0xCF, 0x74, 0xC2,
-0x37, 0xCF, 0x74, 0xC4,
+ 0x27, 0xCF, 0x74, 0xC2,
+ 0x37, 0xCF, 0x74, 0xC4,
-0x0A, 0x44, 0x4C, 0xB0,
-0x02, 0x44, 0x54, 0xB0,
+ 0x0A, 0x44, 0x4C, 0xB0,
+ 0x02, 0x44, 0x54, 0xB0,
-0x3D, 0xCF, 0x74, 0xC0,
-0x34, 0x37, 0x20, 0xE9,
+ 0x3D, 0xCF, 0x74, 0xC0,
+ 0x34, 0x37, 0x20, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x38, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x38, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3C, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3C, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB2,
-0x1A, 0x44, 0x54, 0xB2,
+ 0x2A, 0x44, 0x4C, 0xB2,
+ 0x1A, 0x44, 0x54, 0xB2,
-0x2E, 0x80, 0x3A, 0xEA,
-0x0A, 0x20,
-0x02, 0x20,
+ 0x2E, 0x80, 0x3A, 0xEA,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x27, 0xCF, 0x75, 0xC0,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x75, 0xC0,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x30, 0x50, 0x2E, 0x9F,
-0x32, 0x31, 0x5F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x32, 0x31, 0x5F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x33, 0x39, 0x5F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x33, 0x39, 0x5F, 0xE9,
-0x3D, 0xCF, 0x75, 0xC2,
-0x37, 0xCF, 0x75, 0xC4,
+ 0x3D, 0xCF, 0x75, 0xC2,
+ 0x37, 0xCF, 0x75, 0xC4,
-0x31, 0x53, 0x2F, 0x9F,
-0xA6, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA6, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA3, 0x3D, 0x20, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA3, 0x3D, 0x20, 0xE9,
-0x2A, 0x44, 0x4C, 0xB4,
-0x1A, 0x44, 0x54, 0xB4,
+ 0x2A, 0x44, 0x4C, 0xB4,
+ 0x1A, 0x44, 0x54, 0xB4,
-0x0A, 0x45, 0x4D, 0xB0,
-0x02, 0x45, 0x55, 0xB0,
+ 0x0A, 0x45, 0x4D, 0xB0,
+ 0x02, 0x45, 0x55, 0xB0,
-0x88, 0x73, 0x5E, 0xE9,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x88, 0x73, 0x5E, 0xE9,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA0, 0x37, 0x20, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA0, 0x37, 0x20, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x3E, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x3E, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x3F, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x3F, 0x38, 0x4F, 0xE9,
-0x30, 0x50, 0x2E, 0x9F,
-0x3A, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x3A, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x3B, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x3B, 0x39, 0x4F, 0xE9,
-0x2A, 0x45, 0x4D, 0xB2,
-0x1A, 0x45, 0x55, 0xB2,
+ 0x2A, 0x45, 0x4D, 0xB2,
+ 0x1A, 0x45, 0x55, 0xB2,
-0x0A, 0x45, 0x4D, 0xB4,
-0x02, 0x45, 0x55, 0xB4,
+ 0x0A, 0x45, 0x4D, 0xB4,
+ 0x02, 0x45, 0x55, 0xB4,
-0x27, 0xCF, 0x75, 0xC6,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x27, 0xCF, 0x75, 0xC6,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0xA7, 0x30, 0x4F, 0xE9,
-0x0A, 0x20,
-0x02, 0x20,
+ 0xA7, 0x30, 0x4F, 0xE9,
+ 0x0A, 0x20,
+ 0x02, 0x20,
-0x31, 0x53, 0x2F, 0x9F,
-0x31, 0x27, 0x20, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x31, 0x27, 0x20, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA8, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA8, 0x38, 0x4F, 0xE9,
-0x2A, 0x45, 0x4D, 0xB6,
-0x1A, 0x45, 0x55, 0xB6,
+ 0x2A, 0x45, 0x4D, 0xB6,
+ 0x1A, 0x45, 0x55, 0xB6,
-0x30, 0x50, 0x2E, 0x9F,
-0x36, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x36, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x37, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x37, 0x39, 0x4F, 0xE9,
-0x00, 0x80, 0x00, 0xE8,
-0x2A, 0x20,
-0x1A, 0x20,
+ 0x00, 0x80, 0x00, 0xE8,
+ 0x2A, 0x20,
+ 0x1A, 0x20,
-0x2A, 0x46, 0x4E, 0xBF,
-0x1A, 0x46, 0x56, 0xBF,
+ 0x2A, 0x46, 0x4E, 0xBF,
+ 0x1A, 0x46, 0x56, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA4, 0x31, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA4, 0x31, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA5, 0x39, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA5, 0x39, 0x4F, 0xE9,
-0x0A, 0x47, 0x4F, 0xBF,
-0x02, 0x47, 0x57, 0xBF,
+ 0x0A, 0x47, 0x4F, 0xBF,
+ 0x02, 0x47, 0x57, 0xBF,
-0x31, 0x53, 0x2F, 0x9F,
-0xA1, 0x30, 0x4F, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0xA1, 0x30, 0x4F, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0xA2, 0x38, 0x4F, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0xA2, 0x38, 0x4F, 0xE9,
-0x2A, 0x43, 0x4B, 0xBF,
-0x1A, 0x43, 0x53, 0xBF,
+ 0x2A, 0x43, 0x4B, 0xBF,
+ 0x1A, 0x43, 0x53, 0xBF,
-0x30, 0x50, 0x2E, 0x9F,
-0x35, 0x31, 0x4F, 0xE9,
+ 0x30, 0x50, 0x2E, 0x9F,
+ 0x35, 0x31, 0x4F, 0xE9,
-0x38, 0x21, 0x2C, 0x9F,
-0x39, 0x39, 0x4F, 0xE9,
+ 0x38, 0x21, 0x2C, 0x9F,
+ 0x39, 0x39, 0x4F, 0xE9,
-0x31, 0x53, 0x2F, 0x9F,
-0x80, 0x31, 0x57, 0xE9,
+ 0x31, 0x53, 0x2F, 0x9F,
+ 0x80, 0x31, 0x57, 0xE9,
-0x39, 0xE5, 0x2C, 0x9F,
-0x81, 0x39, 0x57, 0xE9,
+ 0x39, 0xE5, 0x2C, 0x9F,
+ 0x81, 0x39, 0x57, 0xE9,
-0x37, 0x48, 0x50, 0xBD,
-0x8A, 0x36, 0x20, 0xE9,
+ 0x37, 0x48, 0x50, 0xBD,
+ 0x8A, 0x36, 0x20, 0xE9,
-0x86, 0x76, 0x57, 0xE9,
-0x8B, 0x3E, 0x20, 0xE9,
+ 0x86, 0x76, 0x57, 0xE9,
+ 0x8B, 0x3E, 0x20, 0xE9,
-0x82, 0x30, 0x57, 0xE9,
-0x87, 0x77, 0x57, 0xE9,
+ 0x82, 0x30, 0x57, 0xE9,
+ 0x87, 0x77, 0x57, 0xE9,
-0x83, 0x38, 0x57, 0xE9,
-0x35, 0x49, 0x51, 0xBD,
+ 0x83, 0x38, 0x57, 0xE9,
+ 0x35, 0x49, 0x51, 0xBD,
-0x84, 0x31, 0x5E, 0xE9,
-0x30, 0x1F, 0x5F, 0xE9,
+ 0x84, 0x31, 0x5E, 0xE9,
+ 0x30, 0x1F, 0x5F, 0xE9,
-0x85, 0x39, 0x5E, 0xE9,
-0x57, 0x25, 0x20, 0xE9,
+ 0x85, 0x39, 0x5E, 0xE9,
+ 0x57, 0x25, 0x20, 0xE9,
-0x2B, 0x48, 0x20, 0xE9,
-0x1D, 0x37, 0xE1, 0xEA,
+ 0x2B, 0x48, 0x20, 0xE9,
+ 0x1D, 0x37, 0xE1, 0xEA,
-0x1E, 0x35, 0xE1, 0xEA,
-0x00, 0xE0,
-0x26, 0x77,
+ 0x1E, 0x35, 0xE1, 0xEA,
+ 0x00, 0xE0,
+ 0x26, 0x77,
-0x24, 0x49, 0x20, 0xE9,
-0x9D, 0xFF, 0x20, 0xEA,
+ 0x24, 0x49, 0x20, 0xE9,
+ 0x9D, 0xFF, 0x20, 0xEA,
-0x16, 0x26, 0x20, 0xE9,
-0x57, 0x2E, 0xBF, 0xEA,
+ 0x16, 0x26, 0x20, 0xE9,
+ 0x57, 0x2E, 0xBF, 0xEA,
-0x1C, 0x46, 0xA0, 0xE8,
-0x23, 0x4E, 0xA0, 0xE8,
+ 0x1C, 0x46, 0xA0, 0xE8,
+ 0x23, 0x4E, 0xA0, 0xE8,
-0x2B, 0x56, 0xA0, 0xE8,
-0x1D, 0x47, 0xA0, 0xE8,
+ 0x2B, 0x56, 0xA0, 0xE8,
+ 0x1D, 0x47, 0xA0, 0xE8,
-0x24, 0x4F, 0xA0, 0xE8,
-0x2C, 0x57, 0xA0, 0xE8,
+ 0x24, 0x4F, 0xA0, 0xE8,
+ 0x2C, 0x57, 0xA0, 0xE8,
-0x1C, 0x00,
-0x23, 0x00,
-0x2B, 0x00,
-0x00, 0xE0,
+ 0x1C, 0x00,
+ 0x23, 0x00,
+ 0x2B, 0x00,
+ 0x00, 0xE0,
-0x1D, 0x00,
-0x24, 0x00,
-0x2C, 0x00,
-0x00, 0xE0,
+ 0x1D, 0x00,
+ 0x24, 0x00,
+ 0x2C, 0x00,
+ 0x00, 0xE0,
-0x1C, 0x65,
-0x23, 0x65,
-0x2B, 0x65,
-0x00, 0xE0,
+ 0x1C, 0x65,
+ 0x23, 0x65,
+ 0x2B, 0x65,
+ 0x00, 0xE0,
-0x1D, 0x65,
-0x24, 0x65,
-0x2C, 0x65,
-0x00, 0xE0,
+ 0x1D, 0x65,
+ 0x24, 0x65,
+ 0x2C, 0x65,
+ 0x00, 0xE0,
-0x1C, 0x23, 0x60, 0xEC,
-0x36, 0xD7, 0x36, 0xAD,
+ 0x1C, 0x23, 0x60, 0xEC,
+ 0x36, 0xD7, 0x36, 0xAD,
-0x2B, 0x80, 0x60, 0xEC,
-0x1D, 0x24, 0x60, 0xEC,
+ 0x2B, 0x80, 0x60, 0xEC,
+ 0x1D, 0x24, 0x60, 0xEC,
-0x3E, 0xD7, 0x3E, 0xAD,
-0x2C, 0x80, 0x60, 0xEC,
+ 0x3E, 0xD7, 0x3E, 0xAD,
+ 0x2C, 0x80, 0x60, 0xEC,
-0x1C, 0x2B, 0xDE, 0xE8,
-0x23, 0x80, 0xDE, 0xE8,
+ 0x1C, 0x2B, 0xDE, 0xE8,
+ 0x23, 0x80, 0xDE, 0xE8,
-0x36, 0x80, 0x36, 0xBD,
-0x3E, 0x80, 0x3E, 0xBD,
+ 0x36, 0x80, 0x36, 0xBD,
+ 0x3E, 0x80, 0x3E, 0xBD,
-0x33, 0xD7, 0x1C, 0xBD,
-0x3B, 0xD7, 0x23, 0xBD,
+ 0x33, 0xD7, 0x1C, 0xBD,
+ 0x3B, 0xD7, 0x23, 0xBD,
-0x46, 0x80, 0x46, 0xCF,
-0x4F, 0x80, 0x4F, 0xCF,
+ 0x46, 0x80, 0x46, 0xCF,
+ 0x4F, 0x80, 0x4F, 0xCF,
-0x56, 0x33, 0x56, 0xCF,
-0x47, 0x3B, 0x47, 0xCF,
+ 0x56, 0x33, 0x56, 0xCF,
+ 0x47, 0x3B, 0x47, 0xCF,
-0xC5, 0xFF, 0x20, 0xEA,
-0x00, 0x80, 0x00, 0xE8,
+ 0xC5, 0xFF, 0x20, 0xEA,
+ 0x00, 0x80, 0x00, 0xE8,
-0x4E, 0x33, 0x4E, 0xCF,
-0x57, 0x3B, 0x57, 0xCF,
+ 0x4E, 0x33, 0x4E, 0xCF,
+ 0x57, 0x3B, 0x57, 0xCF,
-0x8B, 0xFF, 0x20, 0xEA,
-0x57, 0xC0, 0xBF, 0xEA,
+ 0x8B, 0xFF, 0x20, 0xEA,
+ 0x57, 0xC0, 0xBF, 0xEA,
-0x00, 0x80, 0xA0, 0xE9,
-0x00, 0x00, 0xD8, 0xEC,
+ 0x00, 0x80, 0xA0, 0xE9,
+ 0x00, 0x00, 0xD8, 0xEC,
};
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
index 0a3a0cc700dc..d67f4925fbac 100644
--- a/drivers/char/drm/mga_warp.c
+++ b/drivers/char/drm/mga_warp.c
@@ -33,8 +33,7 @@
#include "mga_drv.h"
#include "mga_ucode.h"
-
-#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
+#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
#define WARP_UCODE_SIZE( which ) \
((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
@@ -48,125 +47,109 @@ do { \
vcbase += WARP_UCODE_SIZE( which ); \
} while (0)
-
-static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
+static const unsigned int mga_warp_g400_microcode_size =
+ (WARP_UCODE_SIZE(warp_g400_tgz) +
+ WARP_UCODE_SIZE(warp_g400_tgza) +
+ WARP_UCODE_SIZE(warp_g400_tgzaf) +
+ WARP_UCODE_SIZE(warp_g400_tgzf) +
+ WARP_UCODE_SIZE(warp_g400_tgzs) +
+ WARP_UCODE_SIZE(warp_g400_tgzsa) +
+ WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+ WARP_UCODE_SIZE(warp_g400_tgzsf) +
+ WARP_UCODE_SIZE(warp_g400_t2gz) +
+ WARP_UCODE_SIZE(warp_g400_t2gza) +
+ WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+ WARP_UCODE_SIZE(warp_g400_t2gzf) +
+ WARP_UCODE_SIZE(warp_g400_t2gzs) +
+ WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+ WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
+
+static const unsigned int mga_warp_g200_microcode_size =
+ (WARP_UCODE_SIZE(warp_g200_tgz) +
+ WARP_UCODE_SIZE(warp_g200_tgza) +
+ WARP_UCODE_SIZE(warp_g200_tgzaf) +
+ WARP_UCODE_SIZE(warp_g200_tgzf) +
+ WARP_UCODE_SIZE(warp_g200_tgzs) +
+ WARP_UCODE_SIZE(warp_g200_tgzsa) +
+ WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
+
+unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
{
- unsigned int size;
-
- size = ( WARP_UCODE_SIZE( warp_g400_tgz ) +
- WARP_UCODE_SIZE( warp_g400_tgza ) +
- WARP_UCODE_SIZE( warp_g400_tgzaf ) +
- WARP_UCODE_SIZE( warp_g400_tgzf ) +
- WARP_UCODE_SIZE( warp_g400_tgzs ) +
- WARP_UCODE_SIZE( warp_g400_tgzsa ) +
- WARP_UCODE_SIZE( warp_g400_tgzsaf ) +
- WARP_UCODE_SIZE( warp_g400_tgzsf ) +
- WARP_UCODE_SIZE( warp_g400_t2gz ) +
- WARP_UCODE_SIZE( warp_g400_t2gza ) +
- WARP_UCODE_SIZE( warp_g400_t2gzaf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzs ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsa ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsaf ) +
- WARP_UCODE_SIZE( warp_g400_t2gzsf ) );
-
- size = PAGE_ALIGN( size );
-
- DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
- return size;
+ switch (dev_priv->chipset) {
+ case MGA_CARD_TYPE_G400:
+ case MGA_CARD_TYPE_G550:
+ return PAGE_ALIGN(mga_warp_g400_microcode_size);
+ case MGA_CARD_TYPE_G200:
+ return PAGE_ALIGN(mga_warp_g200_microcode_size);
+ default:
+ return 0;
+ }
}
-static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
+static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
{
- unsigned int size;
-
- size = ( WARP_UCODE_SIZE( warp_g200_tgz ) +
- WARP_UCODE_SIZE( warp_g200_tgza ) +
- WARP_UCODE_SIZE( warp_g200_tgzaf ) +
- WARP_UCODE_SIZE( warp_g200_tgzf ) +
- WARP_UCODE_SIZE( warp_g200_tgzs ) +
- WARP_UCODE_SIZE( warp_g200_tgzsa ) +
- WARP_UCODE_SIZE( warp_g200_tgzsaf ) +
- WARP_UCODE_SIZE( warp_g200_tgzsf ) );
+ unsigned char *vcbase = dev_priv->warp->handle;
+ unsigned long pcbase = dev_priv->warp->offset;
- size = PAGE_ALIGN( size );
+ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+ WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
+ WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
+ WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
+ WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
+ WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
+ WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
+ WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
+ WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
+
+ WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
+ WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
+ WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
+ WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
+ WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
+ WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
+ WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
+ WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
- DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
- return size;
+ return 0;
}
-static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
+static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
{
unsigned char *vcbase = dev_priv->warp->handle;
unsigned long pcbase = dev_priv->warp->offset;
- unsigned int size;
- size = mga_warp_g400_microcode_size( dev_priv );
- if ( size > dev_priv->warp->size ) {
- DRM_ERROR( "microcode too large! (%u > %lu)\n",
- size, dev_priv->warp->size );
- return DRM_ERR(ENOMEM);
- }
+ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
- memset( dev_priv->warp_pipe_phys, 0,
- sizeof(dev_priv->warp_pipe_phys) );
-
- WARP_UCODE_INSTALL( warp_g400_tgz, MGA_WARP_TGZ );
- WARP_UCODE_INSTALL( warp_g400_tgzf, MGA_WARP_TGZF );
- WARP_UCODE_INSTALL( warp_g400_tgza, MGA_WARP_TGZA );
- WARP_UCODE_INSTALL( warp_g400_tgzaf, MGA_WARP_TGZAF );
- WARP_UCODE_INSTALL( warp_g400_tgzs, MGA_WARP_TGZS );
- WARP_UCODE_INSTALL( warp_g400_tgzsf, MGA_WARP_TGZSF );
- WARP_UCODE_INSTALL( warp_g400_tgzsa, MGA_WARP_TGZSA );
- WARP_UCODE_INSTALL( warp_g400_tgzsaf, MGA_WARP_TGZSAF );
-
- WARP_UCODE_INSTALL( warp_g400_t2gz, MGA_WARP_T2GZ );
- WARP_UCODE_INSTALL( warp_g400_t2gzf, MGA_WARP_T2GZF );
- WARP_UCODE_INSTALL( warp_g400_t2gza, MGA_WARP_T2GZA );
- WARP_UCODE_INSTALL( warp_g400_t2gzaf, MGA_WARP_T2GZAF );
- WARP_UCODE_INSTALL( warp_g400_t2gzs, MGA_WARP_T2GZS );
- WARP_UCODE_INSTALL( warp_g400_t2gzsf, MGA_WARP_T2GZSF );
- WARP_UCODE_INSTALL( warp_g400_t2gzsa, MGA_WARP_T2GZSA );
- WARP_UCODE_INSTALL( warp_g400_t2gzsaf, MGA_WARP_T2GZSAF );
+ WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+ WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+ WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+ WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+ WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+ WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+ WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+ WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
return 0;
}
-static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
+int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
{
- unsigned char *vcbase = dev_priv->warp->handle;
- unsigned long pcbase = dev_priv->warp->offset;
- unsigned int size;
+ const unsigned int size = mga_warp_microcode_size(dev_priv);
- size = mga_warp_g200_microcode_size( dev_priv );
- if ( size > dev_priv->warp->size ) {
- DRM_ERROR( "microcode too large! (%u > %lu)\n",
- size, dev_priv->warp->size );
+ DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+ if (size > dev_priv->warp->size) {
+ DRM_ERROR("microcode too large! (%u > %lu)\n",
+ size, dev_priv->warp->size);
return DRM_ERR(ENOMEM);
}
- memset( dev_priv->warp_pipe_phys, 0,
- sizeof(dev_priv->warp_pipe_phys) );
-
- WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ );
- WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF );
- WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA );
- WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF );
- WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS );
- WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF );
- WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA );
- WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF );
-
- return 0;
-}
-
-int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
-{
- switch ( dev_priv->chipset ) {
+ switch (dev_priv->chipset) {
case MGA_CARD_TYPE_G400:
- return mga_warp_install_g400_microcode( dev_priv );
+ case MGA_CARD_TYPE_G550:
+ return mga_warp_install_g400_microcode(dev_priv);
case MGA_CARD_TYPE_G200:
- return mga_warp_install_g200_microcode( dev_priv );
+ return mga_warp_install_g200_microcode(dev_priv);
default:
return DRM_ERR(EINVAL);
}
@@ -174,35 +157,35 @@ int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
-int mga_warp_init( drm_mga_private_t *dev_priv )
+int mga_warp_init(drm_mga_private_t * dev_priv)
{
u32 wmisc;
/* FIXME: Get rid of these damned magic numbers...
*/
- switch ( dev_priv->chipset ) {
+ switch (dev_priv->chipset) {
case MGA_CARD_TYPE_G400:
- MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND );
- MGA_WRITE( MGA_WGETMSB, 0x00000E00 );
- MGA_WRITE( MGA_WVRTXSZ, 0x00001807 );
- MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 );
+ case MGA_CARD_TYPE_G550:
+ MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
+ MGA_WRITE(MGA_WGETMSB, 0x00000E00);
+ MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
+ MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
break;
case MGA_CARD_TYPE_G200:
- MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
- MGA_WRITE( MGA_WGETMSB, 0x1606 );
- MGA_WRITE( MGA_WVRTXSZ, 7 );
+ MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
+ MGA_WRITE(MGA_WGETMSB, 0x1606);
+ MGA_WRITE(MGA_WVRTXSZ, 7);
break;
default:
return DRM_ERR(EINVAL);
}
- MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
- MGA_WMASTER_ENABLE |
- MGA_WCACHEFLUSH_ENABLE) );
- wmisc = MGA_READ( MGA_WMISC );
- if ( wmisc != WMISC_EXPECTED ) {
- DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
- wmisc, WMISC_EXPECTED );
+ MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
+ MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
+ wmisc = MGA_READ(MGA_WMISC);
+ if (wmisc != WMISC_EXPECTED) {
+ DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
+ wmisc, WMISC_EXPECTED);
return DRM_ERR(EINVAL);
}
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 08ed8d01d9d9..7452753d4d01 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -80,7 +80,7 @@ static u32 r128_cce_microcode[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static int R128_READ_PLL(drm_device_t *dev, int addr)
+static int R128_READ_PLL(drm_device_t * dev, int addr)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -89,106 +89,105 @@ static int R128_READ_PLL(drm_device_t *dev, int addr)
}
#if R128_FIFO_DEBUG
-static void r128_status( drm_r128_private_t *dev_priv )
+static void r128_status(drm_r128_private_t * dev_priv)
{
- printk( "GUI_STAT = 0x%08x\n",
- (unsigned int)R128_READ( R128_GUI_STAT ) );
- printk( "PM4_STAT = 0x%08x\n",
- (unsigned int)R128_READ( R128_PM4_STAT ) );
- printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
- (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
- printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
- (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
- printk( "PM4_MICRO_CNTL = 0x%08x\n",
- (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
- printk( "PM4_BUFFER_CNTL = 0x%08x\n",
- (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
+ printk("GUI_STAT = 0x%08x\n",
+ (unsigned int)R128_READ(R128_GUI_STAT));
+ printk("PM4_STAT = 0x%08x\n",
+ (unsigned int)R128_READ(R128_PM4_STAT));
+ printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
+ (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
+ printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
+ (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
+ printk("PM4_MICRO_CNTL = 0x%08x\n",
+ (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
+ printk("PM4_BUFFER_CNTL = 0x%08x\n",
+ (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
}
#endif
-
/* ================================================================
* Engine, FIFO control
*/
-static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
+static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
{
u32 tmp;
int i;
- tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
- R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
+ tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
+ R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
return 0;
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if R128_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
+ DRM_ERROR("failed!\n");
#endif
return DRM_ERR(EBUSY);
}
-static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
+static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
{
int i;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
- if ( slots >= entries ) return 0;
- DRM_UDELAY( 1 );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+ if (slots >= entries)
+ return 0;
+ DRM_UDELAY(1);
}
#if R128_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
+ DRM_ERROR("failed!\n");
#endif
return DRM_ERR(EBUSY);
}
-static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
+static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
{
int i, ret;
- ret = r128_do_wait_for_fifo( dev_priv, 64 );
- if ( ret ) return ret;
+ ret = r128_do_wait_for_fifo(dev_priv, 64);
+ if (ret)
+ return ret;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
- r128_do_pixcache_flush( dev_priv );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+ r128_do_pixcache_flush(dev_priv);
return 0;
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if R128_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
+ DRM_ERROR("failed!\n");
#endif
return DRM_ERR(EBUSY);
}
-
/* ================================================================
* CCE control, initialization
*/
/* Load the microcode for the CCE */
-static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
+static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
{
int i;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- r128_do_wait_for_idle( dev_priv );
+ r128_do_wait_for_idle(dev_priv);
- R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
- for ( i = 0 ; i < 256 ; i++ ) {
- R128_WRITE( R128_PM4_MICROCODE_DATAH,
- r128_cce_microcode[i * 2] );
- R128_WRITE( R128_PM4_MICROCODE_DATAL,
- r128_cce_microcode[i * 2 + 1] );
+ R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
+ for (i = 0; i < 256; i++) {
+ R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
+ R128_WRITE(R128_PM4_MICROCODE_DATAL,
+ r128_cce_microcode[i * 2 + 1]);
}
}
@@ -196,51 +195,51 @@ static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
* prior to a wait for idle, as it informs the engine that the command
* stream is ending.
*/
-static void r128_do_cce_flush( drm_r128_private_t *dev_priv )
+static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
{
u32 tmp;
- tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE;
- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp );
+ tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
}
/* Wait for the CCE to go idle.
*/
-int r128_do_cce_idle( drm_r128_private_t *dev_priv )
+int r128_do_cce_idle(drm_r128_private_t * dev_priv)
{
int i;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
- int pm4stat = R128_READ( R128_PM4_STAT );
- if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
- dev_priv->cce_fifo_size ) &&
- !(pm4stat & (R128_PM4_BUSY |
- R128_PM4_GUI_ACTIVE)) ) {
- return r128_do_pixcache_flush( dev_priv );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
+ int pm4stat = R128_READ(R128_PM4_STAT);
+ if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
+ dev_priv->cce_fifo_size) &&
+ !(pm4stat & (R128_PM4_BUSY |
+ R128_PM4_GUI_ACTIVE))) {
+ return r128_do_pixcache_flush(dev_priv);
}
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if R128_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
- r128_status( dev_priv );
+ DRM_ERROR("failed!\n");
+ r128_status(dev_priv);
#endif
return DRM_ERR(EBUSY);
}
/* Start the Concurrent Command Engine.
*/
-static void r128_do_cce_start( drm_r128_private_t *dev_priv )
+static void r128_do_cce_start(drm_r128_private_t * dev_priv)
{
- r128_do_wait_for_idle( dev_priv );
+ r128_do_wait_for_idle(dev_priv);
- R128_WRITE( R128_PM4_BUFFER_CNTL,
- dev_priv->cce_mode | dev_priv->ring.size_l2qw
- | R128_PM4_BUFFER_CNTL_NOUPDATE );
- R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
- R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
+ R128_WRITE(R128_PM4_BUFFER_CNTL,
+ dev_priv->cce_mode | dev_priv->ring.size_l2qw
+ | R128_PM4_BUFFER_CNTL_NOUPDATE);
+ R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */
+ R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
dev_priv->cce_running = 1;
}
@@ -249,10 +248,10 @@ static void r128_do_cce_start( drm_r128_private_t *dev_priv )
* commands, so you must wait for the CCE command stream to complete
* before calling this routine.
*/
-static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
+static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
{
- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
- R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+ R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
dev_priv->ring.tail = 0;
}
@@ -260,121 +259,120 @@ static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
* commands, so you must flush the command stream and wait for the CCE
* to go idle before calling this routine.
*/
-static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
+static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
{
- R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
- R128_WRITE( R128_PM4_BUFFER_CNTL,
- R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
+ R128_WRITE(R128_PM4_MICRO_CNTL, 0);
+ R128_WRITE(R128_PM4_BUFFER_CNTL,
+ R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
dev_priv->cce_running = 0;
}
/* Reset the engine. This will stop the CCE if it is running.
*/
-static int r128_do_engine_reset( drm_device_t *dev )
+static int r128_do_engine_reset(drm_device_t * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
- r128_do_pixcache_flush( dev_priv );
+ r128_do_pixcache_flush(dev_priv);
- clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
- mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
+ clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
+ mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
- R128_WRITE_PLL( R128_MCLK_CNTL,
- mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
+ R128_WRITE_PLL(R128_MCLK_CNTL,
+ mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
- gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
+ gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
/* Taken from the sample code - do not change */
- R128_WRITE( R128_GEN_RESET_CNTL,
- gen_reset_cntl | R128_SOFT_RESET_GUI );
- R128_READ( R128_GEN_RESET_CNTL );
- R128_WRITE( R128_GEN_RESET_CNTL,
- gen_reset_cntl & ~R128_SOFT_RESET_GUI );
- R128_READ( R128_GEN_RESET_CNTL );
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+ R128_READ(R128_GEN_RESET_CNTL);
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
+ R128_READ(R128_GEN_RESET_CNTL);
- R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
- R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
- R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
+ R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
+ R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
/* Reset the CCE ring */
- r128_do_cce_reset( dev_priv );
+ r128_do_cce_reset(dev_priv);
/* The CCE is no longer running after an engine reset */
dev_priv->cce_running = 0;
/* Reset any pending vertex, indirect buffers */
- r128_freelist_reset( dev );
+ r128_freelist_reset(dev);
return 0;
}
-static void r128_cce_init_ring_buffer( drm_device_t *dev,
- drm_r128_private_t *dev_priv )
+static void r128_cce_init_ring_buffer(drm_device_t * dev,
+ drm_r128_private_t * dev_priv)
{
u32 ring_start;
u32 tmp;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/* The manual (p. 2) says this address is in "VM space". This
* means it's an offset from the start of AGP space.
*/
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci )
+ if (!dev_priv->is_pci)
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
else
#endif
- ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
+ ring_start = dev_priv->cce_ring->offset -
+ (unsigned long)dev->sg->virtual;
- R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
+ R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
- R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
+ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+ R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
/* Set watermark control */
- R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
- ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
- | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
- | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
- | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) );
+ R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
+ ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
+ | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
+ | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
+ | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
/* Force read. Why? Because it's in the examples... */
- R128_READ( R128_PM4_BUFFER_ADDR );
+ R128_READ(R128_PM4_BUFFER_ADDR);
/* Turn on bus mastering */
- tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS;
- R128_WRITE( R128_BUS_CNTL, tmp );
+ tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
+ R128_WRITE(R128_BUS_CNTL, tmp);
}
-static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
+static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
{
drm_r128_private_t *dev_priv;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
- if ( dev_priv == NULL )
+ dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
return DRM_ERR(ENOMEM);
- memset( dev_priv, 0, sizeof(drm_r128_private_t) );
+ memset(dev_priv, 0, sizeof(drm_r128_private_t));
dev_priv->is_pci = init->is_pci;
- if ( dev_priv->is_pci && !dev->sg ) {
- DRM_ERROR( "PCI GART memory not allocated!\n" );
+ if (dev_priv->is_pci && !dev->sg) {
+ DRM_ERROR("PCI GART memory not allocated!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
dev_priv->usec_timeout = init->usec_timeout;
- if ( dev_priv->usec_timeout < 1 ||
- dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
- DRM_DEBUG( "TIMEOUT problem!\n" );
+ if (dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
+ DRM_DEBUG("TIMEOUT problem!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
@@ -382,23 +380,23 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
/* GH: Simple idle check.
*/
- atomic_set( &dev_priv->idle_count, 0 );
+ atomic_set(&dev_priv->idle_count, 0);
/* We don't support anything other than bus-mastering ring mode,
* but the ring can be in either AGP or PCI space for the ring
* read pointer.
*/
- if ( ( init->cce_mode != R128_PM4_192BM ) &&
- ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
- ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
- ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
- DRM_DEBUG( "Bad cce_mode!\n" );
+ if ((init->cce_mode != R128_PM4_192BM) &&
+ (init->cce_mode != R128_PM4_128BM_64INDBM) &&
+ (init->cce_mode != R128_PM4_64BM_128INDBM) &&
+ (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
+ DRM_DEBUG("Bad cce_mode!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
- switch ( init->cce_mode ) {
+ switch (init->cce_mode) {
case R128_PM4_NONPM4:
dev_priv->cce_fifo_size = 0;
break;
@@ -419,7 +417,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
break;
}
- switch ( init->fb_bpp ) {
+ switch (init->fb_bpp) {
case 16:
dev_priv->color_fmt = R128_DATATYPE_RGB565;
break;
@@ -428,12 +426,12 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
break;
}
- dev_priv->front_offset = init->front_offset;
- dev_priv->front_pitch = init->front_pitch;
- dev_priv->back_offset = init->back_offset;
- dev_priv->back_pitch = init->back_pitch;
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
- switch ( init->depth_bpp ) {
+ switch (init->depth_bpp) {
case 16:
dev_priv->depth_fmt = R128_DATATYPE_RGB565;
break;
@@ -443,217 +441,223 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
break;
}
- dev_priv->depth_offset = init->depth_offset;
- dev_priv->depth_pitch = init->depth_pitch;
- dev_priv->span_offset = init->span_offset;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+ dev_priv->span_offset = init->span_offset;
- dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) |
+ dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
(dev_priv->front_offset >> 5));
- dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch/8) << 21) |
+ dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
(dev_priv->back_offset >> 5));
- dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
+ dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
(dev_priv->depth_offset >> 5) |
R128_DST_TILE);
- dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
+ dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
(dev_priv->span_offset >> 5));
DRM_GETSAREA();
-
- if(!dev_priv->sarea) {
+
+ if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- if(!dev_priv->mmio) {
+ if (!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
- if(!dev_priv->cce_ring) {
+ if (!dev_priv->cce_ring) {
DRM_ERROR("could not find cce ring region!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
- if(!dev_priv->ring_rptr) {
+ if (!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- if(!dev->agp_buffer_map) {
+ if (!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
- if ( !dev_priv->is_pci ) {
- dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset);
- if(!dev_priv->agp_textures) {
+ if (!dev_priv->is_pci) {
+ dev_priv->agp_textures =
+ drm_core_findmap(dev, init->agp_textures_offset);
+ if (!dev_priv->agp_textures) {
DRM_ERROR("could not find agp texture region!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(EINVAL);
}
}
dev_priv->sarea_priv =
- (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
+ (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+ init->sarea_priv_offset);
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- drm_core_ioremap( dev_priv->cce_ring, dev );
- drm_core_ioremap( dev_priv->ring_rptr, dev );
- drm_core_ioremap( dev->agp_buffer_map, dev );
- if(!dev_priv->cce_ring->handle ||
- !dev_priv->ring_rptr->handle ||
- !dev->agp_buffer_map->handle) {
+ if (!dev_priv->is_pci) {
+ drm_core_ioremap(dev_priv->cce_ring, dev);
+ drm_core_ioremap(dev_priv->ring_rptr, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+ if (!dev_priv->cce_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev->agp_buffer_map->handle) {
DRM_ERROR("Could not ioremap agp regions!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(ENOMEM);
}
} else
#endif
{
- dev_priv->cce_ring->handle =
- (void *)dev_priv->cce_ring->offset;
+ dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle =
- (void *)dev_priv->ring_rptr->offset;
- dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
+ (void *)dev_priv->ring_rptr->offset;
+ dev->agp_buffer_map->handle =
+ (void *)dev->agp_buffer_map->offset;
}
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci )
+ if (!dev_priv->is_pci)
dev_priv->cce_buffers_offset = dev->agp->base;
else
#endif
- dev_priv->cce_buffers_offset = dev->sg->handle;
+ dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
- dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
- dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
+ dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
+ dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
+ init->ring_size / sizeof(u32));
dev_priv->ring.size = init->ring_size;
- dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+ dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
- dev_priv->ring.tail_mask =
- (dev_priv->ring.size / sizeof(u32)) - 1;
+ dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
dev_priv->ring.high_mark = 128;
dev_priv->sarea_priv->last_frame = 0;
- R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
+ R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
dev_priv->sarea_priv->last_dispatch = 0;
- R128_WRITE( R128_LAST_DISPATCH_REG,
- dev_priv->sarea_priv->last_dispatch );
+ R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
#if __OS_HAS_AGP
- if ( dev_priv->is_pci ) {
+ if (dev_priv->is_pci) {
#endif
- if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
- &dev_priv->bus_pci_gart) ) {
- DRM_ERROR( "failed to init PCI GART!\n" );
+ dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+ dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;
+ dev_priv->gart_info.is_pcie = 0;
+ if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+ DRM_ERROR("failed to init PCI GART!\n");
dev->dev_private = (void *)dev_priv;
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
return DRM_ERR(ENOMEM);
}
- R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
+ R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
#if __OS_HAS_AGP
}
#endif
- r128_cce_init_ring_buffer( dev, dev_priv );
- r128_cce_load_microcode( dev_priv );
+ r128_cce_init_ring_buffer(dev, dev_priv);
+ r128_cce_load_microcode(dev_priv);
dev->dev_private = (void *)dev_priv;
- r128_do_engine_reset( dev );
+ r128_do_engine_reset(dev);
return 0;
}
-int r128_do_cleanup_cce( drm_device_t *dev )
+int r128_do_cleanup_cce(drm_device_t * dev)
{
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
- if ( dev->dev_private ) {
+ if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- if ( dev_priv->cce_ring != NULL )
- drm_core_ioremapfree( dev_priv->cce_ring, dev );
- if ( dev_priv->ring_rptr != NULL )
- drm_core_ioremapfree( dev_priv->ring_rptr, dev );
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
+ if (!dev_priv->is_pci) {
+ if (dev_priv->cce_ring != NULL)
+ drm_core_ioremapfree(dev_priv->cce_ring, dev);
+ if (dev_priv->ring_rptr != NULL)
+ drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+ if (dev->agp_buffer_map != NULL)
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
} else
#endif
{
- if (!drm_ati_pcigart_cleanup( dev,
- dev_priv->phys_pci_gart,
- dev_priv->bus_pci_gart ))
- DRM_ERROR( "failed to cleanup PCI GART!\n" );
+ if (dev_priv->gart_info.bus_addr)
+ if (!drm_ati_pcigart_cleanup(dev,
+ &dev_priv->
+ gart_info))
+ DRM_ERROR
+ ("failed to cleanup PCI GART!\n");
}
- drm_free( dev->dev_private, sizeof(drm_r128_private_t),
- DRM_MEM_DRIVER );
+ drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+ DRM_MEM_DRIVER);
dev->dev_private = NULL;
}
return 0;
}
-int r128_cce_init( DRM_IOCTL_ARGS )
+int r128_cce_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_init_t init;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t __user *)data, sizeof(init) );
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data,
+ sizeof(init));
- switch ( init.func ) {
+ switch (init.func) {
case R128_INIT_CCE:
- return r128_do_init_cce( dev, &init );
+ return r128_do_init_cce(dev, &init);
case R128_CLEANUP_CCE:
- return r128_do_cleanup_cce( dev );
+ return r128_do_cleanup_cce(dev);
}
return DRM_ERR(EINVAL);
}
-int r128_cce_start( DRM_IOCTL_ARGS )
+int r128_cce_start(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
- DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
+ if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
+ DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
return 0;
}
- r128_do_cce_start( dev_priv );
+ r128_do_cce_start(dev_priv);
return 0;
}
@@ -661,61 +665,63 @@ int r128_cce_start( DRM_IOCTL_ARGS )
/* Stop the CCE. The engine must have been idled before calling this
* routine.
*/
-int r128_cce_stop( DRM_IOCTL_ARGS )
+int r128_cce_stop(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_cce_stop_t stop;
int ret;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *)data, sizeof(stop) );
+ DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data,
+ sizeof(stop));
/* Flush any pending CCE commands. This ensures any outstanding
* commands are exectuted by the engine before we turn it off.
*/
- if ( stop.flush ) {
- r128_do_cce_flush( dev_priv );
+ if (stop.flush) {
+ r128_do_cce_flush(dev_priv);
}
/* If we fail to make the engine go idle, we return an error
* code so that the DRM ioctl wrapper can try again.
*/
- if ( stop.idle ) {
- ret = r128_do_cce_idle( dev_priv );
- if ( ret ) return ret;
+ if (stop.idle) {
+ ret = r128_do_cce_idle(dev_priv);
+ if (ret)
+ return ret;
}
/* Finally, we can turn off the CCE. If the engine isn't idle,
* we will get some dropped triangles as they won't be fully
* rendered before the CCE is shut down.
*/
- r128_do_cce_stop( dev_priv );
+ r128_do_cce_stop(dev_priv);
/* Reset the engine */
- r128_do_engine_reset( dev );
+ r128_do_engine_reset(dev);
return 0;
}
/* Just reset the CCE ring. Called as part of an X Server engine reset.
*/
-int r128_cce_reset( DRM_IOCTL_ARGS )
+int r128_cce_reset(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_DEBUG("%s called before init done\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- r128_do_cce_reset( dev_priv );
+ r128_do_cce_reset(dev_priv);
/* The CCE is no longer running after an engine reset */
dev_priv->cce_running = 0;
@@ -723,37 +729,36 @@ int r128_cce_reset( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_idle( DRM_IOCTL_ARGS )
+int r128_cce_idle(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( dev_priv->cce_running ) {
- r128_do_cce_flush( dev_priv );
+ if (dev_priv->cce_running) {
+ r128_do_cce_flush(dev_priv);
}
- return r128_do_cce_idle( dev_priv );
+ return r128_do_cce_idle(dev_priv);
}
-int r128_engine_reset( DRM_IOCTL_ARGS )
+int r128_engine_reset(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- return r128_do_engine_reset( dev );
+ return r128_do_engine_reset(dev);
}
-int r128_fullscreen( DRM_IOCTL_ARGS )
+int r128_fullscreen(DRM_IOCTL_ARGS)
{
return DRM_ERR(EINVAL);
}
-
/* ================================================================
* Freelist management
*/
@@ -761,7 +766,7 @@ int r128_fullscreen( DRM_IOCTL_ARGS )
#define R128_BUFFER_FREE 0
#if 0
-static int r128_freelist_init( drm_device_t *dev )
+static int r128_freelist_init(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -770,27 +775,26 @@ static int r128_freelist_init( drm_device_t *dev )
drm_r128_freelist_t *entry;
int i;
- dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
- DRM_MEM_DRIVER );
- if ( dev_priv->head == NULL )
+ dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+ if (dev_priv->head == NULL)
return DRM_ERR(ENOMEM);
- memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
+ memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
dev_priv->head->age = R128_BUFFER_USED;
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- entry = drm_alloc( sizeof(drm_r128_freelist_t),
- DRM_MEM_DRIVER );
- if ( !entry ) return DRM_ERR(ENOMEM);
+ entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+ if (!entry)
+ return DRM_ERR(ENOMEM);
entry->age = R128_BUFFER_FREE;
entry->buf = buf;
entry->prev = dev_priv->head;
entry->next = dev_priv->head->next;
- if ( !entry->next )
+ if (!entry->next)
dev_priv->tail = entry;
buf_priv->discard = 0;
@@ -799,7 +803,7 @@ static int r128_freelist_init( drm_device_t *dev )
dev_priv->head->next = entry;
- if ( dev_priv->head->next )
+ if (dev_priv->head->next)
dev_priv->head->next->prev = entry;
}
@@ -808,7 +812,7 @@ static int r128_freelist_init( drm_device_t *dev )
}
#endif
-static drm_buf_t *r128_freelist_get( drm_device_t *dev )
+static drm_buf_t *r128_freelist_get(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -818,20 +822,20 @@ static drm_buf_t *r128_freelist_get( drm_device_t *dev )
/* FIXME: Optimize -- use freelist code */
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- if ( buf->filp == 0 )
+ if (buf->filp == 0)
return buf;
}
- for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- u32 done_age = R128_READ( R128_LAST_DISPATCH_REG );
+ for (t = 0; t < dev_priv->usec_timeout; t++) {
+ u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- if ( buf->pending && buf_priv->age <= done_age ) {
+ if (buf->pending && buf_priv->age <= done_age) {
/* The buffer has been processed, so it
* can now be used.
*/
@@ -839,63 +843,63 @@ static drm_buf_t *r128_freelist_get( drm_device_t *dev )
return buf;
}
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
- DRM_DEBUG( "returning NULL!\n" );
+ DRM_DEBUG("returning NULL!\n");
return NULL;
}
-void r128_freelist_reset( drm_device_t *dev )
+void r128_freelist_reset(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
int i;
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[i];
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->age = 0;
}
}
-
/* ================================================================
* CCE command submission
*/
-int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
+int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
{
drm_r128_ring_buffer_t *ring = &dev_priv->ring;
int i;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- r128_update_ring_snapshot( dev_priv );
- if ( ring->space >= n )
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ r128_update_ring_snapshot(dev_priv);
+ if (ring->space >= n)
return 0;
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
/* FIXME: This is being ignored... */
- DRM_ERROR( "failed!\n" );
+ DRM_ERROR("failed!\n");
return DRM_ERR(EBUSY);
}
-static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
+static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
{
int i;
drm_buf_t *buf;
- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
- buf = r128_freelist_get( dev );
- if ( !buf ) return DRM_ERR(EAGAIN);
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = r128_freelist_get(dev);
+ if (!buf)
+ return DRM_ERR(EAGAIN);
buf->filp = filp;
- if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
- sizeof(buf->idx) ) )
+ if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+ sizeof(buf->idx)))
return DRM_ERR(EFAULT);
- if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
- sizeof(buf->total) ) )
+ if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+ sizeof(buf->total)))
return DRM_ERR(EFAULT);
d->granted_count++;
@@ -903,7 +907,7 @@ static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
return 0;
}
-int r128_cce_buffers( DRM_IOCTL_ARGS )
+int r128_cce_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -911,33 +915,33 @@ int r128_cce_buffers( DRM_IOCTL_ARGS )
drm_dma_t __user *argp = (void __user *)data;
drm_dma_t d;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
+ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
/* Please don't send us buffers.
*/
- if ( d.send_count != 0 ) {
- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
- DRM_CURRENTPID, d.send_count );
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d.send_count);
return DRM_ERR(EINVAL);
}
/* We'll send you buffers.
*/
- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
- DRM_CURRENTPID, d.request_count, dma->buf_count );
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d.request_count, dma->buf_count);
return DRM_ERR(EINVAL);
}
d.granted_count = 0;
- if ( d.request_count ) {
- ret = r128_cce_get_buffers( filp, dev, &d );
+ if (d.request_count) {
+ ret = r128_cce_get_buffers(filp, dev, &d);
}
- DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d) );
+ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
return ret;
}
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 0cba17d1e0ff..5ddc03202411 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -93,7 +93,7 @@
#define R128_MAX_TEXTURE_LEVELS 11
#define R128_MAX_TEXTURE_UNITS 2
-#endif /* __R128_SAREA_DEFINES__ */
+#endif /* __R128_SAREA_DEFINES__ */
typedef struct {
/* Context state - can be written in one large chunk */
@@ -140,7 +140,6 @@ typedef struct {
unsigned int tex_border_color;
} drm_r128_texture_regs_t;
-
typedef struct drm_r128_sarea {
/* The channel for communication of state information to the kernel
* on firing a vertex buffer.
@@ -161,14 +160,13 @@ typedef struct drm_r128_sarea {
unsigned int last_frame;
unsigned int last_dispatch;
- drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
unsigned int tex_age[R128_NR_TEX_HEAPS];
int ctx_owner;
- int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
- int pfCurrentPage; /* which buffer is being displayed? */
+ int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
+ int pfCurrentPage; /* which buffer is being displayed? */
} drm_r128_sarea_t;
-
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmR128.h)
*/
@@ -215,12 +213,12 @@ typedef struct drm_r128_sarea {
#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
-#define DRM_IOCTL_R128_GETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
+#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP)
typedef struct drm_r128_init {
enum {
- R128_INIT_CCE = 0x01,
+ R128_INIT_CCE = 0x01,
R128_CLEANUP_CCE = 0x02
} func;
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
@@ -278,9 +276,9 @@ typedef struct drm_r128_clear {
typedef struct drm_r128_vertex {
int prim;
- int idx; /* Index of vertex buffer */
- int count; /* Number of vertices in buffer */
- int discard; /* Client finished with buffer? */
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
} drm_r128_vertex_t;
typedef struct drm_r128_indices {
@@ -288,7 +286,7 @@ typedef struct drm_r128_indices {
int idx;
int start;
int end;
- int discard; /* Client finished with buffer? */
+ int discard; /* Client finished with buffer? */
} drm_r128_indices_t;
typedef struct drm_r128_blit {
@@ -302,10 +300,10 @@ typedef struct drm_r128_blit {
typedef struct drm_r128_depth {
enum {
- R128_WRITE_SPAN = 0x01,
- R128_WRITE_PIXELS = 0x02,
- R128_READ_SPAN = 0x03,
- R128_READ_PIXELS = 0x04
+ R128_WRITE_SPAN = 0x01,
+ R128_WRITE_PIXELS = 0x02,
+ R128_READ_SPAN = 0x03,
+ R128_READ_PIXELS = 0x04
} func;
int n;
int __user *x;
@@ -327,13 +325,13 @@ typedef struct drm_r128_indirect {
typedef struct drm_r128_fullscreen {
enum {
- R128_INIT_FULLSCREEN = 0x01,
+ R128_INIT_FULLSCREEN = 0x01,
R128_CLEANUP_FULLSCREEN = 0x02
} func;
} drm_r128_fullscreen_t;
/* 2.3: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
+ * client any other way.
*/
#define R128_PARAM_IRQ_NR 1
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index bc446da1b210..1661e7351402 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -37,30 +37,28 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -68,11 +66,11 @@ static struct pci_device_id pciidlist[] = {
r128_PCI_IDS
};
-extern drm_ioctl_desc_t r128_ioctls[];
-extern int r128_max_ioctl;
-
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_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+ DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
.prerelease = r128_driver_prerelease,
.pretakedown = r128_driver_pretakedown,
@@ -89,21 +87,22 @@ 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,
+ }
};
static int __init r128_init(void)
@@ -120,6 +119,6 @@ static void __exit r128_exit(void)
module_init(r128_init);
module_exit(r128_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 0fb687c9505e..5c79e40eb88f 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -52,14 +52,13 @@
#define DRIVER_MINOR 5
#define DRIVER_PATCHLEVEL 0
-
#define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR )
typedef struct drm_r128_freelist {
- unsigned int age;
- drm_buf_t *buf;
- struct drm_r128_freelist *next;
- struct drm_r128_freelist *prev;
+ unsigned int age;
+ drm_buf_t *buf;
+ struct drm_r128_freelist *next;
+ struct drm_r128_freelist *prev;
} drm_r128_freelist_t;
typedef struct drm_r128_ring_buffer {
@@ -83,13 +82,11 @@ typedef struct drm_r128_private {
int cce_fifo_size;
int cce_running;
- drm_r128_freelist_t *head;
- drm_r128_freelist_t *tail;
+ drm_r128_freelist_t *head;
+ drm_r128_freelist_t *tail;
int usec_timeout;
int is_pci;
- unsigned long phys_pci_gart;
- dma_addr_t bus_pci_gart;
unsigned long cce_buffers_offset;
atomic_t idle_count;
@@ -120,6 +117,7 @@ typedef struct drm_r128_private {
drm_local_map_t *cce_ring;
drm_local_map_t *ring_rptr;
drm_local_map_t *agp_textures;
+ drm_ati_pcigart_info gart_info;
} drm_r128_private_t;
typedef struct drm_r128_buf_priv {
@@ -127,34 +125,37 @@ typedef struct drm_r128_buf_priv {
int prim;
int discard;
int dispatched;
- drm_r128_freelist_t *list_entry;
+ drm_r128_freelist_t *list_entry;
} drm_r128_buf_priv_t;
+extern drm_ioctl_desc_t r128_ioctls[];
+extern int r128_max_ioctl;
+
/* r128_cce.c */
-extern int r128_cce_init( DRM_IOCTL_ARGS );
-extern int r128_cce_start( DRM_IOCTL_ARGS );
-extern int r128_cce_stop( DRM_IOCTL_ARGS );
-extern int r128_cce_reset( DRM_IOCTL_ARGS );
-extern int r128_cce_idle( DRM_IOCTL_ARGS );
-extern int r128_engine_reset( DRM_IOCTL_ARGS );
-extern int r128_fullscreen( DRM_IOCTL_ARGS );
-extern int r128_cce_buffers( DRM_IOCTL_ARGS );
+extern int r128_cce_init(DRM_IOCTL_ARGS);
+extern int r128_cce_start(DRM_IOCTL_ARGS);
+extern int r128_cce_stop(DRM_IOCTL_ARGS);
+extern int r128_cce_reset(DRM_IOCTL_ARGS);
+extern int r128_cce_idle(DRM_IOCTL_ARGS);
+extern int r128_engine_reset(DRM_IOCTL_ARGS);
+extern int r128_fullscreen(DRM_IOCTL_ARGS);
+extern int r128_cce_buffers(DRM_IOCTL_ARGS);
-extern void r128_freelist_reset( drm_device_t *dev );
+extern void r128_freelist_reset(drm_device_t * dev);
-extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
+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( drm_device_t *dev );
+extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
+extern int r128_do_cleanup_cce(drm_device_t * dev);
-extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
-extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS );
-extern void r128_driver_irq_preinstall( drm_device_t *dev );
-extern void r128_driver_irq_postinstall( drm_device_t *dev );
-extern void r128_driver_irq_uninstall( drm_device_t *dev );
-extern void r128_driver_pretakedown(drm_device_t *dev);
-extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+extern void r128_driver_irq_preinstall(drm_device_t * dev);
+extern void r128_driver_irq_postinstall(drm_device_t * dev);
+extern void r128_driver_irq_uninstall(drm_device_t * dev);
+extern void r128_driver_pretakedown(drm_device_t * dev);
+extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp);
extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -266,7 +267,6 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
# define R128_EVENT_CRTC_OFFSET (1 << 0)
#define R128_WINDOW_XY_OFFSET 0x1bcc
-
/* CCE registers
*/
#define R128_PM4_BUFFER_OFFSET 0x0700
@@ -317,7 +317,6 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
#define R128_PM4_FIFO_DATA_EVEN 0x1000
#define R128_PM4_FIFO_DATA_ODD 0x1004
-
/* CCE command packets
*/
#define R128_CCE_PACKET0 0x00000000
@@ -395,7 +394,6 @@ do { \
R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
} while (0)
-
#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
((n) << 16) | ((reg) >> 2))
#define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
@@ -404,13 +402,11 @@ do { \
#define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
(pkt) | ((n) << 16))
-
-static __inline__ void
-r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
+static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
{
drm_r128_ring_buffer_t *ring = &dev_priv->ring;
- ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
- if ( ring->space <= 0 )
+ ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
+ if (ring->space <= 0)
ring->space += ring->size;
}
@@ -451,7 +447,6 @@ do { \
OUT_RING( R128_EVENT_CRTC_OFFSET ); \
} while (0)
-
/* ================================================================
* Ring control
*/
@@ -521,4 +516,4 @@ do { \
write &= tail_mask; \
} while (0)
-#endif /* __R128_DRV_H__ */
+#endif /* __R128_DRV_H__ */
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
index 60598ef9475a..1e2e367b8b82 100644
--- a/drivers/char/drm/r128_ioc32.c
+++ b/drivers/char/drm/r128_ioc32.c
@@ -65,10 +65,10 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
{
drm_r128_init32_t init32;
drm_r128_init_t __user *init;
-
+
if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
return -EFAULT;
-
+
init = compat_alloc_user_space(sizeof(*init));
if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
|| __put_user(init32.func, &init->func)
@@ -92,14 +92,14 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
|| __put_user(init32.ring_offset, &init->ring_offset)
|| __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
|| __put_user(init32.buffers_offset, &init->buffers_offset)
- || __put_user(init32.agp_textures_offset, &init->agp_textures_offset))
+ || __put_user(init32.agp_textures_offset,
+ &init->agp_textures_offset))
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_R128_INIT, (unsigned long)init);
}
-
typedef struct drm_r128_depth32 {
int func;
int n;
@@ -124,13 +124,15 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
|| __put_user(depth32.n, &depth->n)
|| __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
|| __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
- || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, &depth->buffer)
- || __put_user((unsigned char __user *)(unsigned long)depth32.mask, &depth->mask))
+ || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
+ &depth->buffer)
+ || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
+ &depth->mask))
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
-
+ DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+
}
typedef struct drm_r128_stipple32 {
@@ -148,7 +150,8 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
stipple = compat_alloc_user_space(sizeof(*stipple));
if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
- || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, &stipple->mask))
+ || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
+ &stipple->mask))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
@@ -172,9 +175,10 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
getparam = compat_alloc_user_space(sizeof(*getparam));
if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
|| __put_user(getparam32.param, &getparam->param)
- || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
+ || __put_user((void __user *)(unsigned long)getparam32.value,
+ &getparam->value))
return -EFAULT;
-
+
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
}
@@ -195,8 +199,7 @@ drm_ioctl_compat_t *r128_compat_ioctls[] = {
* \param arg user argument.
* \return zero on success or negative number on failure.
*/
-long r128_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned int nr = DRM_IOCTL_NR(cmd);
drm_ioctl_compat_t *fn = NULL;
@@ -210,7 +213,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd,
lock_kernel(); /* XXX for now */
if (fn != NULL)
- ret = (*fn)(filp, cmd, arg);
+ ret = (*fn) (filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 643a30785fe5..27eb0e31bd3b 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -1,7 +1,7 @@
/* r128_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
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
@@ -35,68 +35,67 @@
#include "r128_drm.h"
#include "r128_drv.h"
-irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *) arg;
- drm_r128_private_t *dev_priv =
- (drm_r128_private_t *)dev->dev_private;
+ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
int status;
- status = R128_READ( R128_GEN_INT_STATUS );
-
+ status = R128_READ(R128_GEN_INT_STATUS);
+
/* VBLANK interrupt */
- if ( status & R128_CRTC_VBLANK_INT ) {
- R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+ 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 );
+ drm_vbl_send_signals(dev);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
-int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
{
unsigned int cur_vblank;
int ret = 0;
/* 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...
+ * using vertical blanks...
*/
- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
- - *sequence ) <= (1<<23) ) );
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received))
+ - *sequence) <= (1 << 23)));
*sequence = cur_vblank;
return ret;
}
-void r128_driver_irq_preinstall( drm_device_t *dev ) {
- drm_r128_private_t *dev_priv =
- (drm_r128_private_t *)dev->dev_private;
+void r128_driver_irq_preinstall(drm_device_t * dev)
+{
+ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
/* Disable *all* interrupts */
- R128_WRITE( R128_GEN_INT_CNTL, 0 );
+ R128_WRITE(R128_GEN_INT_CNTL, 0);
/* Clear vblank bit if it's already high */
- R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
}
-void r128_driver_irq_postinstall( drm_device_t *dev ) {
- drm_r128_private_t *dev_priv =
- (drm_r128_private_t *)dev->dev_private;
+void r128_driver_irq_postinstall(drm_device_t * 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 );
+ R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
}
-void r128_driver_irq_uninstall( drm_device_t *dev ) {
- drm_r128_private_t *dev_priv =
- (drm_r128_private_t *)dev->dev_private;
+void r128_driver_irq_uninstall(drm_device_t * dev)
+{
+ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
if (!dev_priv)
return;
/* Disable *all* interrupts */
- R128_WRITE( R128_GEN_INT_CNTL, 0 );
+ R128_WRITE(R128_GEN_INT_CNTL, 0);
}
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 426a71c049d9..14479cc08a57 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -32,235 +32,233 @@
#include "r128_drm.h"
#include "r128_drv.h"
-
/* ================================================================
* CCE hardware state programming functions
*/
-static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
- drm_clip_rect_t *boxes, int count )
+static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
+ drm_clip_rect_t * boxes, int count)
{
u32 aux_sc_cntl = 0x00000000;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
+ BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
- if ( count >= 1 ) {
- OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
- OUT_RING( boxes[0].x1 );
- OUT_RING( boxes[0].x2 - 1 );
- OUT_RING( boxes[0].y1 );
- OUT_RING( boxes[0].y2 - 1 );
+ if (count >= 1) {
+ OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
+ OUT_RING(boxes[0].x1);
+ OUT_RING(boxes[0].x2 - 1);
+ OUT_RING(boxes[0].y1);
+ OUT_RING(boxes[0].y2 - 1);
aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
}
- if ( count >= 2 ) {
- OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
- OUT_RING( boxes[1].x1 );
- OUT_RING( boxes[1].x2 - 1 );
- OUT_RING( boxes[1].y1 );
- OUT_RING( boxes[1].y2 - 1 );
+ if (count >= 2) {
+ OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
+ OUT_RING(boxes[1].x1);
+ OUT_RING(boxes[1].x2 - 1);
+ OUT_RING(boxes[1].y1);
+ OUT_RING(boxes[1].y2 - 1);
aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
}
- if ( count >= 3 ) {
- OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
- OUT_RING( boxes[2].x1 );
- OUT_RING( boxes[2].x2 - 1 );
- OUT_RING( boxes[2].y1 );
- OUT_RING( boxes[2].y2 - 1 );
+ if (count >= 3) {
+ OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
+ OUT_RING(boxes[2].x1);
+ OUT_RING(boxes[2].x2 - 1);
+ OUT_RING(boxes[2].y1);
+ OUT_RING(boxes[2].y2 - 1);
aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
}
- OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
- OUT_RING( aux_sc_cntl );
+ OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
+ OUT_RING(aux_sc_cntl);
ADVANCE_RING();
}
-static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
- OUT_RING( ctx->scale_3d_cntl );
+ OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
+ OUT_RING(ctx->scale_3d_cntl);
ADVANCE_RING();
}
-static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
-
- BEGIN_RING( 13 );
-
- OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
- OUT_RING( ctx->dst_pitch_offset_c );
- OUT_RING( ctx->dp_gui_master_cntl_c );
- OUT_RING( ctx->sc_top_left_c );
- OUT_RING( ctx->sc_bottom_right_c );
- OUT_RING( ctx->z_offset_c );
- OUT_RING( ctx->z_pitch_c );
- OUT_RING( ctx->z_sten_cntl_c );
- OUT_RING( ctx->tex_cntl_c );
- OUT_RING( ctx->misc_3d_state_cntl_reg );
- OUT_RING( ctx->texture_clr_cmp_clr_c );
- OUT_RING( ctx->texture_clr_cmp_msk_c );
- OUT_RING( ctx->fog_color_c );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+ BEGIN_RING(13);
+
+ OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
+ OUT_RING(ctx->dst_pitch_offset_c);
+ OUT_RING(ctx->dp_gui_master_cntl_c);
+ OUT_RING(ctx->sc_top_left_c);
+ OUT_RING(ctx->sc_bottom_right_c);
+ OUT_RING(ctx->z_offset_c);
+ OUT_RING(ctx->z_pitch_c);
+ OUT_RING(ctx->z_sten_cntl_c);
+ OUT_RING(ctx->tex_cntl_c);
+ OUT_RING(ctx->misc_3d_state_cntl_reg);
+ OUT_RING(ctx->texture_clr_cmp_clr_c);
+ OUT_RING(ctx->texture_clr_cmp_msk_c);
+ OUT_RING(ctx->fog_color_c);
ADVANCE_RING();
}
-static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 3 );
+ BEGIN_RING(3);
- OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
- OUT_RING( ctx->setup_cntl );
- OUT_RING( ctx->pm4_vc_fpu_setup );
+ OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
+ OUT_RING(ctx->setup_cntl);
+ OUT_RING(ctx->pm4_vc_fpu_setup);
ADVANCE_RING();
}
-static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 5 );
+ BEGIN_RING(5);
- OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
- OUT_RING( ctx->dp_write_mask );
+ OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+ OUT_RING(ctx->dp_write_mask);
- OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
- OUT_RING( ctx->sten_ref_mask_c );
- OUT_RING( ctx->plane_3d_mask_c );
+ OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
+ OUT_RING(ctx->sten_ref_mask_c);
+ OUT_RING(ctx->plane_3d_mask_c);
ADVANCE_RING();
}
-static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
- OUT_RING( ctx->window_xy_offset );
+ OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
+ OUT_RING(ctx->window_xy_offset);
ADVANCE_RING();
}
-static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
int i;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
+ BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
- OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
- 2 + R128_MAX_TEXTURE_LEVELS ) );
- OUT_RING( tex->tex_cntl );
- OUT_RING( tex->tex_combine_cntl );
- OUT_RING( ctx->tex_size_pitch_c );
- for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
- OUT_RING( tex->tex_offset[i] );
+ OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
+ 2 + R128_MAX_TEXTURE_LEVELS));
+ OUT_RING(tex->tex_cntl);
+ OUT_RING(tex->tex_combine_cntl);
+ OUT_RING(ctx->tex_size_pitch_c);
+ for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+ OUT_RING(tex->tex_offset[i]);
}
- OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
- OUT_RING( ctx->constant_color_c );
- OUT_RING( tex->tex_border_color );
+ OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
+ OUT_RING(ctx->constant_color_c);
+ OUT_RING(tex->tex_border_color);
ADVANCE_RING();
}
-static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
int i;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+ DRM_DEBUG(" %s\n", __FUNCTION__);
- BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
+ BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
- OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
- 1 + R128_MAX_TEXTURE_LEVELS ) );
- OUT_RING( tex->tex_cntl );
- OUT_RING( tex->tex_combine_cntl );
- for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
- OUT_RING( tex->tex_offset[i] );
+ OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
+ OUT_RING(tex->tex_cntl);
+ OUT_RING(tex->tex_combine_cntl);
+ for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+ OUT_RING(tex->tex_offset[i]);
}
- OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
- OUT_RING( tex->tex_border_color );
+ OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
+ OUT_RING(tex->tex_border_color);
ADVANCE_RING();
}
-static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
- DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+ DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
- if ( dirty & R128_UPLOAD_CORE ) {
- r128_emit_core( dev_priv );
+ if (dirty & R128_UPLOAD_CORE) {
+ r128_emit_core(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_CORE;
}
- if ( dirty & R128_UPLOAD_CONTEXT ) {
- r128_emit_context( dev_priv );
+ if (dirty & R128_UPLOAD_CONTEXT) {
+ r128_emit_context(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
}
- if ( dirty & R128_UPLOAD_SETUP ) {
- r128_emit_setup( dev_priv );
+ if (dirty & R128_UPLOAD_SETUP) {
+ r128_emit_setup(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
}
- if ( dirty & R128_UPLOAD_MASKS ) {
- r128_emit_masks( dev_priv );
+ if (dirty & R128_UPLOAD_MASKS) {
+ r128_emit_masks(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
}
- if ( dirty & R128_UPLOAD_WINDOW ) {
- r128_emit_window( dev_priv );
+ if (dirty & R128_UPLOAD_WINDOW) {
+ r128_emit_window(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
}
- if ( dirty & R128_UPLOAD_TEX0 ) {
- r128_emit_tex0( dev_priv );
+ if (dirty & R128_UPLOAD_TEX0) {
+ r128_emit_tex0(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
}
- if ( dirty & R128_UPLOAD_TEX1 ) {
- r128_emit_tex1( dev_priv );
+ if (dirty & R128_UPLOAD_TEX1) {
+ r128_emit_tex1(dev_priv);
sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
}
@@ -270,26 +268,23 @@ static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
}
-
#if R128_PERFORMANCE_BOXES
/* ================================================================
* Performance monitoring functions
*/
-static void r128_clear_box( drm_r128_private_t *dev_priv,
- int x, int y, int w, int h,
- int r, int g, int b )
+static void r128_clear_box(drm_r128_private_t * dev_priv,
+ int x, int y, int w, int h, int r, int g, int b)
{
u32 pitch, offset;
u32 fb_bpp, color;
RING_LOCALS;
- switch ( dev_priv->fb_bpp ) {
+ switch (dev_priv->fb_bpp) {
case 16:
fb_bpp = R128_GMC_DST_16BPP;
color = (((r & 0xf8) << 8) |
- ((g & 0xfc) << 3) |
- ((b & 0xf8) >> 3));
+ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
break;
case 24:
fb_bpp = R128_GMC_DST_24BPP;
@@ -297,7 +292,7 @@ static void r128_clear_box( drm_r128_private_t *dev_priv,
break;
case 32:
fb_bpp = R128_GMC_DST_32BPP;
- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
break;
default:
return;
@@ -306,60 +301,58 @@ static void r128_clear_box( drm_r128_private_t *dev_priv,
offset = dev_priv->back_offset;
pitch = dev_priv->back_pitch >> 3;
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- fb_bpp |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ fb_bpp |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
- OUT_RING( (pitch << 21) | (offset >> 5) );
- OUT_RING( color );
+ OUT_RING((pitch << 21) | (offset >> 5));
+ OUT_RING(color);
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
-static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
+static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
{
- if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
- r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+ if (atomic_read(&dev_priv->idle_count) == 0) {
+ r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
} else {
- atomic_set( &dev_priv->idle_count, 0 );
+ atomic_set(&dev_priv->idle_count, 0);
}
}
#endif
-
/* ================================================================
* CCE command dispatch functions
*/
-static void r128_print_dirty( const char *msg, unsigned int flags )
+static void r128_print_dirty(const char *msg, unsigned int flags)
{
- DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
- msg,
- flags,
- (flags & R128_UPLOAD_CORE) ? "core, " : "",
- (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
- (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
- (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
- (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
- (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
- (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
- (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
- (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+ DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & R128_UPLOAD_CORE) ? "core, " : "",
+ (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+ (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+ (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+ (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+ (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+ (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+ (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
}
-static void r128_cce_dispatch_clear( drm_device_t *dev,
- drm_r128_clear_t *clear )
+static void r128_cce_dispatch_clear(drm_device_t * dev,
+ drm_r128_clear_t * clear)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -368,102 +361,103 @@ static void r128_cce_dispatch_clear( drm_device_t *dev,
unsigned int flags = clear->flags;
int i;
RING_LOCALS;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
unsigned int tmp = flags;
flags &= ~(R128_FRONT | R128_BACK);
- if ( tmp & R128_FRONT ) flags |= R128_BACK;
- if ( tmp & R128_BACK ) flags |= R128_FRONT;
+ if (tmp & R128_FRONT)
+ flags |= R128_BACK;
+ if (tmp & R128_BACK)
+ flags |= R128_FRONT;
}
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
int x = pbox[i].x1;
int y = pbox[i].y1;
int w = pbox[i].x2 - x;
int h = pbox[i].y2 - y;
- DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
- pbox[i].x1, pbox[i].y1, pbox[i].x2,
- pbox[i].y2, flags );
+ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+ pbox[i].x1, pbox[i].y1, pbox[i].x2,
+ pbox[i].y2, flags);
- if ( flags & (R128_FRONT | R128_BACK) ) {
- BEGIN_RING( 2 );
+ if (flags & (R128_FRONT | R128_BACK)) {
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
- OUT_RING( clear->color_mask );
+ OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+ OUT_RING(clear->color_mask);
ADVANCE_RING();
}
- if ( flags & R128_FRONT ) {
- BEGIN_RING( 6 );
+ if (flags & R128_FRONT) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->color_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS);
- OUT_RING( dev_priv->front_pitch_offset_c );
- OUT_RING( clear->clear_color );
+ OUT_RING(dev_priv->front_pitch_offset_c);
+ OUT_RING(clear->clear_color);
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
- if ( flags & R128_BACK ) {
- BEGIN_RING( 6 );
+ if (flags & R128_BACK) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->color_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS);
- OUT_RING( dev_priv->back_pitch_offset_c );
- OUT_RING( clear->clear_color );
+ OUT_RING(dev_priv->back_pitch_offset_c);
+ OUT_RING(clear->clear_color);
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
- if ( flags & R128_DEPTH ) {
- BEGIN_RING( 6 );
+ if (flags & R128_DEPTH) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( clear->clear_depth );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(clear->clear_depth);
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
}
}
-static void r128_cce_dispatch_swap( drm_device_t *dev )
+static void r128_cce_dispatch_swap(drm_device_t * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -471,48 +465,46 @@ static void r128_cce_dispatch_swap( drm_device_t *dev )
drm_clip_rect_t *pbox = sarea_priv->boxes;
int i;
RING_LOCALS;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
#if R128_PERFORMANCE_BOXES
/* Do some trivial performance monitoring...
*/
- r128_cce_performance_boxes( dev_priv );
+ r128_cce_performance_boxes(dev_priv);
#endif
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
int x = pbox[i].x1;
int y = pbox[i].y1;
int w = pbox[i].x2 - x;
int h = pbox[i].y2 - y;
- BEGIN_RING( 7 );
+ BEGIN_RING(7);
- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
- R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_NONE |
- (dev_priv->color_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_S |
- R128_DP_SRC_SOURCE_MEMORY |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
/* Make this work even if front & back are flipped:
*/
if (dev_priv->current_page == 0) {
- OUT_RING( dev_priv->back_pitch_offset_c );
- OUT_RING( dev_priv->front_pitch_offset_c );
- }
- else {
- OUT_RING( dev_priv->front_pitch_offset_c );
- OUT_RING( dev_priv->back_pitch_offset_c );
+ OUT_RING(dev_priv->back_pitch_offset_c);
+ OUT_RING(dev_priv->front_pitch_offset_c);
+ } else {
+ OUT_RING(dev_priv->front_pitch_offset_c);
+ OUT_RING(dev_priv->back_pitch_offset_c);
}
- OUT_RING( (x << 16) | y );
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
@@ -523,38 +515,37 @@ static void r128_cce_dispatch_swap( drm_device_t *dev )
*/
dev_priv->sarea_priv->last_frame++;
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
- OUT_RING( dev_priv->sarea_priv->last_frame );
+ OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+ OUT_RING(dev_priv->sarea_priv->last_frame);
ADVANCE_RING();
}
-static void r128_cce_dispatch_flip( drm_device_t *dev )
+static void r128_cce_dispatch_flip(drm_device_t * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
- __FUNCTION__,
- dev_priv->current_page,
- dev_priv->sarea_priv->pfCurrentPage);
+ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
#if R128_PERFORMANCE_BOXES
/* Do some trivial performance monitoring...
*/
- r128_cce_performance_boxes( dev_priv );
+ r128_cce_performance_boxes(dev_priv);
#endif
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
R128_WAIT_UNTIL_PAGE_FLIPPED();
- OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
+ OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
- if ( dev_priv->current_page == 0 ) {
- OUT_RING( dev_priv->back_offset );
+ if (dev_priv->current_page == 0) {
+ OUT_RING(dev_priv->back_offset);
} else {
- OUT_RING( dev_priv->front_offset );
+ OUT_RING(dev_priv->front_offset);
}
ADVANCE_RING();
@@ -565,18 +556,17 @@ static void r128_cce_dispatch_flip( drm_device_t *dev )
*/
dev_priv->sarea_priv->last_frame++;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
- 1 - dev_priv->current_page;
+ 1 - dev_priv->current_page;
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
- OUT_RING( dev_priv->sarea_priv->last_frame );
+ OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+ OUT_RING(dev_priv->sarea_priv->last_frame);
ADVANCE_RING();
}
-static void r128_cce_dispatch_vertex( drm_device_t *dev,
- drm_buf_t *buf )
+static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -587,50 +577,50 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
int prim = buf_priv->prim;
int i = 0;
RING_LOCALS;
- DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
+ DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
- if ( 0 )
- r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+ if (0)
+ r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
- if ( buf->used ) {
+ if (buf->used) {
buf_priv->dispatched = 1;
- if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
- r128_emit_state( dev_priv );
+ if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+ r128_emit_state(dev_priv);
}
do {
/* Emit the next set of up to three cliprects */
- if ( i < sarea_priv->nbox ) {
- r128_emit_clip_rects( dev_priv,
- &sarea_priv->boxes[i],
- sarea_priv->nbox - i );
+ if (i < sarea_priv->nbox) {
+ r128_emit_clip_rects(dev_priv,
+ &sarea_priv->boxes[i],
+ sarea_priv->nbox - i);
}
/* Emit the vertex buffer rendering commands */
- BEGIN_RING( 5 );
+ BEGIN_RING(5);
- OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
- OUT_RING( offset );
- OUT_RING( size );
- OUT_RING( format );
- OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
- (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
+ OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
+ OUT_RING(offset);
+ OUT_RING(size);
+ OUT_RING(format);
+ OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+ (size << R128_CCE_VC_CNTL_NUM_SHIFT));
ADVANCE_RING();
i += 3;
- } while ( i < sarea_priv->nbox );
+ } while (i < sarea_priv->nbox);
}
- if ( buf_priv->discard ) {
+ if (buf_priv->discard) {
buf_priv->age = dev_priv->sarea_priv->last_dispatch;
/* Emit the vertex buffer age */
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
- OUT_RING( buf_priv->age );
+ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+ OUT_RING(buf_priv->age);
ADVANCE_RING();
@@ -646,17 +636,15 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev,
sarea_priv->nbox = 0;
}
-static void r128_cce_dispatch_indirect( drm_device_t *dev,
- drm_buf_t *buf,
- int start, int end )
+static void r128_cce_dispatch_indirect(drm_device_t * dev,
+ drm_buf_t * buf, int start, int end)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
RING_LOCALS;
- DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
- buf->idx, start, end );
+ DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
- if ( start != end ) {
+ if (start != end) {
int offset = buf->bus_address + start;
int dwords = (end - start + 3) / sizeof(u32);
@@ -664,33 +652,33 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
* dwords, so if we've been given an odd number we must
* pad the data with a Type-2 CCE packet.
*/
- if ( dwords & 1 ) {
+ if (dwords & 1) {
u32 *data = (u32 *)
- ((char *)dev->agp_buffer_map->handle
- + buf->offset + start);
- data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
+ ((char *)dev->agp_buffer_map->handle
+ + buf->offset + start);
+ data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
}
buf_priv->dispatched = 1;
/* Fire off the indirect buffer */
- BEGIN_RING( 3 );
+ BEGIN_RING(3);
- OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
- OUT_RING( offset );
- OUT_RING( dwords );
+ OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
+ OUT_RING(offset);
+ OUT_RING(dwords);
ADVANCE_RING();
}
- if ( buf_priv->discard ) {
+ if (buf_priv->discard) {
buf_priv->age = dev_priv->sarea_priv->last_dispatch;
/* Emit the indirect buffer age */
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
- OUT_RING( buf_priv->age );
+ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+ OUT_RING(buf_priv->age);
ADVANCE_RING();
@@ -703,10 +691,9 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
dev_priv->sarea_priv->last_dispatch++;
}
-static void r128_cce_dispatch_indices( drm_device_t *dev,
- drm_buf_t *buf,
- int start, int end,
- int count )
+static void r128_cce_dispatch_indices(drm_device_t * dev,
+ drm_buf_t * buf,
+ int start, int end, int count)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -718,62 +705,62 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
int dwords;
int i = 0;
RING_LOCALS;
- DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+ DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
- if ( 0 )
- r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
+ if (0)
+ r128_print_dirty("dispatch_indices", sarea_priv->dirty);
- if ( start != end ) {
+ if (start != end) {
buf_priv->dispatched = 1;
- if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
- r128_emit_state( dev_priv );
+ if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+ r128_emit_state(dev_priv);
}
dwords = (end - start + 3) / sizeof(u32);
- data = (u32 *)((char *)dev->agp_buffer_map->handle
- + buf->offset + start);
+ data = (u32 *) ((char *)dev->agp_buffer_map->handle
+ + buf->offset + start);
- data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
- dwords-2 ) );
+ data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
+ dwords - 2));
- data[1] = cpu_to_le32( offset );
- data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
- data[3] = cpu_to_le32( format );
- data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
- (count << 16)) );
+ data[1] = cpu_to_le32(offset);
+ data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
+ data[3] = cpu_to_le32(format);
+ data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+ (count << 16)));
- if ( count & 0x1 ) {
+ if (count & 0x1) {
#ifdef __LITTLE_ENDIAN
- data[dwords-1] &= 0x0000ffff;
+ data[dwords - 1] &= 0x0000ffff;
#else
- data[dwords-1] &= 0xffff0000;
+ data[dwords - 1] &= 0xffff0000;
#endif
}
do {
/* Emit the next set of up to three cliprects */
- if ( i < sarea_priv->nbox ) {
- r128_emit_clip_rects( dev_priv,
- &sarea_priv->boxes[i],
- sarea_priv->nbox - i );
+ if (i < sarea_priv->nbox) {
+ r128_emit_clip_rects(dev_priv,
+ &sarea_priv->boxes[i],
+ sarea_priv->nbox - i);
}
- r128_cce_dispatch_indirect( dev, buf, start, end );
+ r128_cce_dispatch_indirect(dev, buf, start, end);
i += 3;
- } while ( i < sarea_priv->nbox );
+ } while (i < sarea_priv->nbox);
}
- if ( buf_priv->discard ) {
+ if (buf_priv->discard) {
buf_priv->age = dev_priv->sarea_priv->last_dispatch;
/* Emit the vertex buffer age */
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
- OUT_RING( buf_priv->age );
+ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+ OUT_RING(buf_priv->age);
ADVANCE_RING();
@@ -788,9 +775,8 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
sarea_priv->nbox = 0;
}
-static int r128_cce_dispatch_blit( DRMFILE filp,
- drm_device_t *dev,
- drm_r128_blit_t *blit )
+static int r128_cce_dispatch_blit(DRMFILE filp,
+ drm_device_t * dev, drm_r128_blit_t * blit)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_device_dma_t *dma = dev->dma;
@@ -799,13 +785,13 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
u32 *data;
int dword_shift, dwords;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/* The compiler won't optimize away a division by a variable,
* even if the only legal values are powers of two. Thus, we'll
* use a shift instead.
*/
- switch ( blit->format ) {
+ switch (blit->format) {
case R128_DATATYPE_ARGB8888:
dword_shift = 0;
break;
@@ -821,7 +807,7 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
dword_shift = 2;
break;
default:
- DRM_ERROR( "invalid blit format %d\n", blit->format );
+ DRM_ERROR("invalid blit format %d\n", blit->format);
return DRM_ERR(EINVAL);
}
@@ -830,10 +816,10 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
* data from the host data blit, otherwise part of the texture
* image may be corrupted.
*/
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
- OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
+ OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+ OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
ADVANCE_RING();
@@ -842,13 +828,13 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
buf = dma->buflist[blit->idx];
buf_priv = buf->dev_private;
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", blit->idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", blit->idx);
return DRM_ERR(EINVAL);
}
@@ -856,45 +842,43 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
dwords = (blit->width * blit->height) >> dword_shift;
- data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset);
-
- data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
- data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_NONE |
- (blit->format << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_S |
- R128_DP_SRC_SOURCE_HOST_DATA |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_AUX_CLIP_DIS |
- R128_GMC_WR_MSK_DIS) );
-
- data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
- data[3] = cpu_to_le32( 0xffffffff );
- data[4] = cpu_to_le32( 0xffffffff );
- data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
- data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
- data[7] = cpu_to_le32( dwords );
+ data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+
+ data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
+ data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (blit->format << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_HOST_DATA |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
+
+ data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
+ data[3] = cpu_to_le32(0xffffffff);
+ data[4] = cpu_to_le32(0xffffffff);
+ data[5] = cpu_to_le32((blit->y << 16) | blit->x);
+ data[6] = cpu_to_le32((blit->height << 16) | blit->width);
+ data[7] = cpu_to_le32(dwords);
buf->used = (dwords + 8) * sizeof(u32);
- r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
+ r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
/* Flush the pixel cache after the blit completes. This ensures
* the texture data is written out to memory before rendering
* continues.
*/
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
- OUT_RING( R128_PC_FLUSH_GUI );
+ OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+ OUT_RING(R128_PC_FLUSH_GUI);
ADVANCE_RING();
return 0;
}
-
/* ================================================================
* Tiled depth buffer management
*
@@ -902,8 +886,8 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
* have hardware stencil support.
*/
-static int r128_cce_dispatch_write_span( drm_device_t *dev,
- drm_r128_depth_t *depth )
+static int r128_cce_dispatch_write_span(drm_device_t * dev,
+ drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int count, x, y;
@@ -911,95 +895,95 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev,
u8 *mask;
int i, buffer_size, mask_size;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
count = depth->n;
if (count > 4096 || count <= 0)
return DRM_ERR(EMSGSIZE);
- if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
+ if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
return DRM_ERR(EFAULT);
}
- if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
+ if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
return DRM_ERR(EFAULT);
}
buffer_size = depth->n * sizeof(u32);
- buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
- if ( buffer == NULL )
+ buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+ if (buffer == NULL)
return DRM_ERR(ENOMEM);
- if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
- drm_free( buffer, buffer_size, DRM_MEM_BUFS);
+ if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
mask_size = depth->n * sizeof(u8);
- if ( depth->mask ) {
- mask = drm_alloc( mask_size, DRM_MEM_BUFS );
- if ( mask == NULL ) {
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+ if (depth->mask) {
+ mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+ if (mask == NULL) {
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
- if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
- drm_free( mask, mask_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ drm_free(mask, mask_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- for ( i = 0 ; i < count ; i++, x++ ) {
- if ( mask[i] ) {
- BEGIN_RING( 6 );
+ for (i = 0; i < count; i++, x++) {
+ if (mask[i]) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( buffer[i] );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(buffer[i]);
- OUT_RING( (x << 16) | y );
- OUT_RING( (1 << 16) | 1 );
+ OUT_RING((x << 16) | y);
+ OUT_RING((1 << 16) | 1);
ADVANCE_RING();
}
}
- drm_free( mask, mask_size, DRM_MEM_BUFS );
+ drm_free(mask, mask_size, DRM_MEM_BUFS);
} else {
- for ( i = 0 ; i < count ; i++, x++ ) {
- BEGIN_RING( 6 );
+ for (i = 0; i < count; i++, x++) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( buffer[i] );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(buffer[i]);
- OUT_RING( (x << 16) | y );
- OUT_RING( (1 << 16) | 1 );
+ OUT_RING((x << 16) | y);
+ OUT_RING((1 << 16) | 1);
ADVANCE_RING();
}
}
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return 0;
}
-static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
- drm_r128_depth_t *depth )
+static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+ drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int count, *x, *y;
@@ -1007,7 +991,7 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
u8 *mask;
int i, xbuf_size, ybuf_size, buffer_size, mask_size;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
count = depth->n;
if (count > 4096 || count <= 0)
@@ -1015,270 +999,266 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
xbuf_size = count * sizeof(*x);
ybuf_size = count * sizeof(*y);
- x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
- if ( x == NULL ) {
+ x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+ if (x == NULL) {
return DRM_ERR(ENOMEM);
}
- y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
- if ( y == NULL ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+ y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+ if (y == NULL) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
- if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
buffer_size = depth->n * sizeof(u32);
- buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
- if ( buffer == NULL ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+ if (buffer == NULL) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
- if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- if ( depth->mask ) {
+ if (depth->mask) {
mask_size = depth->n * sizeof(u8);
- mask = drm_alloc( mask_size, DRM_MEM_BUFS );
- if ( mask == NULL ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+ mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+ if (mask == NULL) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
- if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
- drm_free( mask, mask_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ drm_free(mask, mask_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- for ( i = 0 ; i < count ; i++ ) {
- if ( mask[i] ) {
- BEGIN_RING( 6 );
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( buffer[i] );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(buffer[i]);
- OUT_RING( (x[i] << 16) | y[i] );
- OUT_RING( (1 << 16) | 1 );
+ OUT_RING((x[i] << 16) | y[i]);
+ OUT_RING((1 << 16) | 1);
ADVANCE_RING();
}
}
- drm_free( mask, mask_size, DRM_MEM_BUFS );
+ drm_free(mask, mask_size, DRM_MEM_BUFS);
} else {
- for ( i = 0 ; i < count ; i++ ) {
- BEGIN_RING( 6 );
+ for (i = 0; i < count; i++) {
+ BEGIN_RING(6);
- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_P |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( buffer[i] );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(buffer[i]);
- OUT_RING( (x[i] << 16) | y[i] );
- OUT_RING( (1 << 16) | 1 );
+ OUT_RING((x[i] << 16) | y[i]);
+ OUT_RING((1 << 16) | 1);
ADVANCE_RING();
}
}
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
return 0;
}
-static int r128_cce_dispatch_read_span( drm_device_t *dev,
- drm_r128_depth_t *depth )
+static int r128_cce_dispatch_read_span(drm_device_t * dev,
+ drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int count, x, y;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
count = depth->n;
if (count > 4096 || count <= 0)
return DRM_ERR(EMSGSIZE);
- if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
+ if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
return DRM_ERR(EFAULT);
}
- if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
+ if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
return DRM_ERR(EFAULT);
}
- BEGIN_RING( 7 );
+ BEGIN_RING(7);
- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
- R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_NONE |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_S |
- R128_DP_SRC_SOURCE_MEMORY |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( dev_priv->span_pitch_offset_c );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(dev_priv->span_pitch_offset_c);
- OUT_RING( (x << 16) | y );
- OUT_RING( (0 << 16) | 0 );
- OUT_RING( (count << 16) | 1 );
+ OUT_RING((x << 16) | y);
+ OUT_RING((0 << 16) | 0);
+ OUT_RING((count << 16) | 1);
ADVANCE_RING();
return 0;
}
-static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
- drm_r128_depth_t *depth )
+static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+ drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int count, *x, *y;
int i, xbuf_size, ybuf_size;
RING_LOCALS;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
count = depth->n;
if (count > 4096 || count <= 0)
return DRM_ERR(EMSGSIZE);
- if ( count > dev_priv->depth_pitch ) {
+ if (count > dev_priv->depth_pitch) {
count = dev_priv->depth_pitch;
}
xbuf_size = count * sizeof(*x);
ybuf_size = count * sizeof(*y);
- x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
- if ( x == NULL ) {
+ x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+ if (x == NULL) {
return DRM_ERR(ENOMEM);
}
- y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
- if ( y == NULL ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+ y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+ if (y == NULL) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
- if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return DRM_ERR(EFAULT);
}
- for ( i = 0 ; i < count ; i++ ) {
- BEGIN_RING( 7 );
+ for (i = 0; i < count; i++) {
+ BEGIN_RING(7);
- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
- R128_GMC_DST_PITCH_OFFSET_CNTL |
- R128_GMC_BRUSH_NONE |
- (dev_priv->depth_fmt << 8) |
- R128_GMC_SRC_DATATYPE_COLOR |
- R128_ROP3_S |
- R128_DP_SRC_SOURCE_MEMORY |
- R128_GMC_CLR_CMP_CNTL_DIS |
- R128_GMC_WR_MSK_DIS );
+ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
- OUT_RING( dev_priv->depth_pitch_offset_c );
- OUT_RING( dev_priv->span_pitch_offset_c );
+ OUT_RING(dev_priv->depth_pitch_offset_c);
+ OUT_RING(dev_priv->span_pitch_offset_c);
- OUT_RING( (x[i] << 16) | y[i] );
- OUT_RING( (i << 16) | 0 );
- OUT_RING( (1 << 16) | 1 );
+ OUT_RING((x[i] << 16) | y[i]);
+ OUT_RING((i << 16) | 0);
+ OUT_RING((1 << 16) | 1);
ADVANCE_RING();
}
- drm_free( x, xbuf_size, DRM_MEM_BUFS );
- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ drm_free(y, ybuf_size, DRM_MEM_BUFS);
return 0;
}
-
/* ================================================================
* Polygon stipple
*/
-static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int i;
RING_LOCALS;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- BEGIN_RING( 33 );
+ BEGIN_RING(33);
- OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
- for ( i = 0 ; i < 32 ; i++ ) {
- OUT_RING( stipple[i] );
+ OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
+ for (i = 0; i < 32; i++) {
+ OUT_RING(stipple[i]);
}
ADVANCE_RING();
}
-
/* ================================================================
* IOCTL functions
*/
-static int r128_cce_clear( DRM_IOCTL_ARGS )
+static int r128_cce_clear(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_r128_clear_t clear;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t __user *) data,
- sizeof(clear) );
+ DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data,
+ sizeof(clear));
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
- r128_cce_dispatch_clear( dev, &clear );
+ r128_cce_dispatch_clear(dev, &clear);
COMMIT_RING();
/* Make sure we restore the 3D state next time.
@@ -1288,17 +1268,17 @@ static int r128_cce_clear( DRM_IOCTL_ARGS )
return 0;
}
-static int r128_do_init_pageflip( drm_device_t *dev )
+static int r128_do_init_pageflip(drm_device_t * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
- dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
+ dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
+ dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
- R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
- R128_WRITE( R128_CRTC_OFFSET_CNTL,
- dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
+ R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
+ R128_WRITE(R128_CRTC_OFFSET_CNTL,
+ dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
dev_priv->page_flipping = 1;
dev_priv->current_page = 0;
@@ -1307,16 +1287,16 @@ static int r128_do_init_pageflip( drm_device_t *dev )
return 0;
}
-static int r128_do_cleanup_pageflip( drm_device_t *dev )
+static int r128_do_cleanup_pageflip(drm_device_t * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
- R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+ R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
+ R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
if (dev_priv->current_page != 0) {
- r128_cce_dispatch_flip( dev );
+ r128_cce_dispatch_flip(dev);
COMMIT_RING();
}
@@ -1325,43 +1305,43 @@ static int r128_do_cleanup_pageflip( drm_device_t *dev )
}
/* Swapping and flipping are different operations, need different ioctls.
- * They can & should be intermixed to support multiple 3d windows.
+ * They can & should be intermixed to support multiple 3d windows.
*/
-static int r128_cce_flip( DRM_IOCTL_ARGS )
+static int r128_cce_flip(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- if (!dev_priv->page_flipping)
- r128_do_init_pageflip( dev );
+ if (!dev_priv->page_flipping)
+ r128_do_init_pageflip(dev);
- r128_cce_dispatch_flip( dev );
+ r128_cce_dispatch_flip(dev);
COMMIT_RING();
return 0;
}
-static int r128_cce_swap( DRM_IOCTL_ARGS )
+static int r128_cce_swap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
- DRM_DEBUG( "%s\n", __FUNCTION__ );
+ DRM_DEBUG("%s\n", __FUNCTION__);
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
- r128_cce_dispatch_swap( dev );
+ r128_cce_dispatch_swap(dev);
dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS);
@@ -1369,7 +1349,7 @@ static int r128_cce_swap( DRM_IOCTL_ARGS )
return 0;
}
-static int r128_cce_vertex( DRM_IOCTL_ARGS )
+static int r128_cce_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1378,44 +1358,43 @@ static int r128_cce_vertex( DRM_IOCTL_ARGS )
drm_r128_buf_priv_t *buf_priv;
drm_r128_vertex_t vertex;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t __user *) data,
- sizeof(vertex) );
+ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data,
+ sizeof(vertex));
- DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
- DRM_CURRENTPID,
- vertex.idx, vertex.count, vertex.discard );
+ DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+ DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- vertex.idx, dma->buf_count - 1 );
+ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- if ( vertex.prim < 0 ||
- vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
- DRM_ERROR( "buffer prim %d\n", vertex.prim );
+ if (vertex.prim < 0 ||
+ vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+ DRM_ERROR("buffer prim %d\n", vertex.prim);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf = dma->buflist[vertex.idx];
buf_priv = buf->dev_private;
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
return DRM_ERR(EINVAL);
}
@@ -1423,13 +1402,13 @@ static int r128_cce_vertex( DRM_IOCTL_ARGS )
buf_priv->prim = vertex.prim;
buf_priv->discard = vertex.discard;
- r128_cce_dispatch_vertex( dev, buf );
+ r128_cce_dispatch_vertex(dev, buf);
COMMIT_RING();
return 0;
}
-static int r128_cce_indices( DRM_IOCTL_ARGS )
+static int r128_cce_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1439,55 +1418,54 @@ static int r128_cce_indices( DRM_IOCTL_ARGS )
drm_r128_indices_t elts;
int count;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t __user *) data,
- sizeof(elts) );
+ DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data,
+ sizeof(elts));
- DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
- elts.idx, elts.start, elts.end, elts.discard );
+ DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
+ elts.idx, elts.start, elts.end, elts.discard);
- if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- elts.idx, dma->buf_count - 1 );
+ if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ elts.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- if ( elts.prim < 0 ||
- elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
- DRM_ERROR( "buffer prim %d\n", elts.prim );
+ if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+ DRM_ERROR("buffer prim %d\n", elts.prim);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf = dma->buflist[elts.idx];
buf_priv = buf->dev_private;
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", elts.idx);
return DRM_ERR(EINVAL);
}
count = (elts.end - elts.start) / sizeof(u16);
elts.start -= R128_INDEX_PRIM_OFFSET;
- if ( elts.start & 0x7 ) {
- DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+ if (elts.start & 0x7) {
+ DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
return DRM_ERR(EINVAL);
}
- if ( elts.start < buf->used ) {
- DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+ if (elts.start < buf->used) {
+ DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
return DRM_ERR(EINVAL);
}
@@ -1495,13 +1473,13 @@ static int r128_cce_indices( DRM_IOCTL_ARGS )
buf_priv->prim = elts.prim;
buf_priv->discard = elts.discard;
- r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
+ r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count);
COMMIT_RING();
return 0;
}
-static int r128_cce_blit( DRM_IOCTL_ARGS )
+static int r128_cce_blit(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -1509,55 +1487,55 @@ static int r128_cce_blit( DRM_IOCTL_ARGS )
drm_r128_blit_t blit;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t __user *) data,
- sizeof(blit) );
+ DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data,
+ sizeof(blit));
- DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
+ DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx);
- if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- blit.idx, dma->buf_count - 1 );
+ if (blit.idx < 0 || blit.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ blit.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
- ret = r128_cce_dispatch_blit( filp, dev, &blit );
+ ret = r128_cce_dispatch_blit(filp, dev, &blit);
COMMIT_RING();
return ret;
}
-static int r128_cce_depth( DRM_IOCTL_ARGS )
+static int r128_cce_depth(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_depth_t depth;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t __user *) data,
- sizeof(depth) );
+ DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data,
+ sizeof(depth));
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
ret = DRM_ERR(EINVAL);
- switch ( depth.func ) {
+ switch (depth.func) {
case R128_WRITE_SPAN:
- ret = r128_cce_dispatch_write_span( dev, &depth );
+ ret = r128_cce_dispatch_write_span(dev, &depth);
break;
case R128_WRITE_PIXELS:
- ret = r128_cce_dispatch_write_pixels( dev, &depth );
+ ret = r128_cce_dispatch_write_pixels(dev, &depth);
break;
case R128_READ_SPAN:
- ret = r128_cce_dispatch_read_span( dev, &depth );
+ ret = r128_cce_dispatch_read_span(dev, &depth);
break;
case R128_READ_PIXELS:
- ret = r128_cce_dispatch_read_pixels( dev, &depth );
+ ret = r128_cce_dispatch_read_pixels(dev, &depth);
break;
}
@@ -1565,31 +1543,30 @@ static int r128_cce_depth( DRM_IOCTL_ARGS )
return ret;
}
-static int r128_cce_stipple( DRM_IOCTL_ARGS )
+static int r128_cce_stipple(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_stipple_t stipple;
u32 mask[32];
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t __user *) data,
- sizeof(stipple) );
+ DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data,
+ sizeof(stipple));
- if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
- 32 * sizeof(u32) ) )
- return DRM_ERR( EFAULT );
+ if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
+ return DRM_ERR(EFAULT);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- r128_cce_dispatch_stipple( dev, mask );
+ r128_cce_dispatch_stipple(dev, mask);
COMMIT_RING();
return 0;
}
-static int r128_cce_indirect( DRM_IOCTL_ARGS )
+static int r128_cce_indirect(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1601,47 +1578,46 @@ static int r128_cce_indirect( DRM_IOCTL_ARGS )
RING_LOCALS;
#endif
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t __user *) data,
- sizeof(indirect) );
+ DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data,
+ sizeof(indirect));
- DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
- indirect.idx, indirect.start,
- indirect.end, indirect.discard );
+ DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
+ indirect.idx, indirect.start, indirect.end, indirect.discard);
- if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- indirect.idx, dma->buf_count - 1 );
+ if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ indirect.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
buf = dma->buflist[indirect.idx];
buf_priv = buf->dev_private;
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", indirect.idx);
return DRM_ERR(EINVAL);
}
- if ( indirect.start < buf->used ) {
- DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
- indirect.start, buf->used );
+ if (indirect.start < buf->used) {
+ DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+ indirect.start, buf->used);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf->used = indirect.end;
buf_priv->discard = indirect.discard;
@@ -1650,7 +1626,7 @@ static int r128_cce_indirect( DRM_IOCTL_ARGS )
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2D acceleration commands is processed.
*/
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
#endif
@@ -1659,30 +1635,30 @@ static int r128_cce_indirect( DRM_IOCTL_ARGS )
* X server. This is insecure and is thus only available to
* privileged clients.
*/
- r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+ r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end);
COMMIT_RING();
return 0;
}
-static int r128_getparam( DRM_IOCTL_ARGS )
+static int r128_getparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_getparam_t param;
int value;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t __user *)data,
- sizeof(param) );
+ DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data,
+ sizeof(param));
- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
- switch( param.param ) {
+ switch (param.param) {
case R128_PARAM_IRQ_NR:
value = dev->irq;
break;
@@ -1690,47 +1666,47 @@ static int r128_getparam( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return DRM_ERR(EFAULT);
}
-
+
return 0;
}
-void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
{
- if ( dev->dev_private ) {
+ if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
- if ( dev_priv->page_flipping ) {
- r128_do_cleanup_pageflip( dev );
+ if (dev_priv->page_flipping) {
+ r128_do_cleanup_pageflip(dev);
}
- }
+ }
}
-void r128_driver_pretakedown(drm_device_t *dev)
+void r128_driver_pretakedown(drm_device_t * dev)
{
- r128_do_cleanup_cce( dev );
+ r128_do_cleanup_cce(dev);
}
drm_ioctl_desc_t r128_ioctls[] = {
- [DRM_IOCTL_NR(DRM_R128_INIT)] = { r128_cce_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_R128_CCE_START)] = { r128_cce_start, 1, 1 },
- [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 },
- [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 },
- [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_RESET)] = { r128_engine_reset, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_SWAP)] = { r128_cce_swap, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_FLIP)] = { r128_cce_flip, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_CLEAR)] = { r128_cce_clear, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_VERTEX)] = { r128_cce_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_INDICES)] = { r128_cce_indices, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_BLIT)] = { r128_cce_blit, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_DEPTH)] = { r128_cce_depth, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 },
- [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 },
- [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = { r128_getparam, 1, 0 },
+ [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, 1, 1},
+ [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, 1, 1},
+ [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, 1, 1},
+ [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, 1, 1},
+ [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, 1, 0},
};
int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
new file mode 100644
index 000000000000..3a1ac5f78b43
--- /dev/null
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -0,0 +1,823 @@
+/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002.
+ * Copyright (C) 2004 Nicolai Haehnle.
+ * All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * 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
+ * PRECISION INSIGHT 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:
+ * Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+#define R300_SIMULTANEOUS_CLIPRECTS 4
+
+/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
+ */
+static const int r300_cliprect_cntl[4] = {
+ 0xAAAA,
+ 0xEEEE,
+ 0xFEFE,
+ 0xFFFE
+};
+
+/**
+ * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
+ * buffer, starting with index n.
+ */
+static int r300_emit_cliprects(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf, int n)
+{
+ drm_clip_rect_t box;
+ int nr;
+ int i;
+ RING_LOCALS;
+
+ nr = cmdbuf->nbox - n;
+ if (nr > R300_SIMULTANEOUS_CLIPRECTS)
+ nr = R300_SIMULTANEOUS_CLIPRECTS;
+
+ DRM_DEBUG("%i cliprects\n", nr);
+
+ if (nr) {
+ BEGIN_RING(6 + nr * 2);
+ OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
+
+ for (i = 0; i < nr; ++i) {
+ if (DRM_COPY_FROM_USER_UNCHECKED
+ (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
+ DRM_ERROR("copy cliprect faulted\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ box.x1 =
+ (box.x1 +
+ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.y1 =
+ (box.y1 +
+ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.x2 =
+ (box.x2 +
+ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+ box.y2 =
+ (box.y2 +
+ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+
+ OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
+ (box.y1 << R300_CLIPRECT_Y_SHIFT));
+ OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
+ (box.y2 << R300_CLIPRECT_Y_SHIFT));
+ }
+
+ OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
+
+ /* TODO/SECURITY: Force scissors to a safe value, otherwise the
+ * client might be able to trample over memory.
+ * The impact should be very limited, but I'd rather be safe than
+ * sorry.
+ */
+ OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
+ OUT_RING(0);
+ OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
+ ADVANCE_RING();
+ } else {
+ /* Why we allow zero cliprect rendering:
+ * There are some commands in a command buffer that must be submitted
+ * even when there are no cliprects, e.g. DMA buffer discard
+ * or state setting (though state setting could be avoided by
+ * simulating a loss of context).
+ *
+ * Now since the cmdbuf interface is so chaotic right now (and is
+ * bound to remain that way for a bit until things settle down),
+ * it is basically impossible to filter out the commands that are
+ * necessary and those that aren't.
+ *
+ * So I choose the safe way and don't do any filtering at all;
+ * instead, I simply set up the engine so that all rendering
+ * can't produce any fragments.
+ */
+ BEGIN_RING(2);
+ OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
+ ADVANCE_RING();
+ }
+
+ return 0;
+}
+
+static u8 r300_reg_flags[0x10000 >> 2];
+
+void r300_init_reg_flags(void)
+{
+ int i;
+ memset(r300_reg_flags, 0, 0x10000 >> 2);
+#define ADD_RANGE_MARK(reg, count,mark) \
+ for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
+ r300_reg_flags[i]|=(mark);
+
+#define MARK_SAFE 1
+#define MARK_CHECK_OFFSET 2
+
+#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
+
+ /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
+ ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
+ ADD_RANGE(0x2080, 1);
+ ADD_RANGE(R300_SE_VTE_CNTL, 2);
+ ADD_RANGE(0x2134, 2);
+ ADD_RANGE(0x2140, 1);
+ ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
+ ADD_RANGE(0x21DC, 1);
+ ADD_RANGE(0x221C, 1);
+ ADD_RANGE(0x2220, 4);
+ ADD_RANGE(0x2288, 1);
+ ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
+ ADD_RANGE(R300_GB_ENABLE, 1);
+ ADD_RANGE(R300_GB_MSPOS0, 5);
+ ADD_RANGE(R300_TX_ENABLE, 1);
+ ADD_RANGE(0x4200, 4);
+ ADD_RANGE(0x4214, 1);
+ ADD_RANGE(R300_RE_POINTSIZE, 1);
+ ADD_RANGE(0x4230, 3);
+ ADD_RANGE(R300_RE_LINE_CNT, 1);
+ ADD_RANGE(0x4238, 1);
+ ADD_RANGE(0x4260, 3);
+ ADD_RANGE(0x4274, 4);
+ ADD_RANGE(0x4288, 5);
+ ADD_RANGE(0x42A0, 1);
+ ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
+ ADD_RANGE(0x42B4, 1);
+ ADD_RANGE(R300_RE_CULL_CNTL, 1);
+ ADD_RANGE(0x42C0, 2);
+ ADD_RANGE(R300_RS_CNTL_0, 2);
+ ADD_RANGE(R300_RS_INTERP_0, 8);
+ ADD_RANGE(R300_RS_ROUTE_0, 8);
+ ADD_RANGE(0x43A4, 2);
+ ADD_RANGE(0x43E8, 1);
+ ADD_RANGE(R300_PFS_CNTL_0, 3);
+ ADD_RANGE(R300_PFS_NODE_0, 4);
+ ADD_RANGE(R300_PFS_TEXI_0, 64);
+ ADD_RANGE(0x46A4, 5);
+ ADD_RANGE(R300_PFS_INSTR0_0, 64);
+ ADD_RANGE(R300_PFS_INSTR1_0, 64);
+ ADD_RANGE(R300_PFS_INSTR2_0, 64);
+ ADD_RANGE(R300_PFS_INSTR3_0, 64);
+ ADD_RANGE(0x4BC0, 1);
+ ADD_RANGE(0x4BC8, 3);
+ ADD_RANGE(R300_PP_ALPHA_TEST, 2);
+ ADD_RANGE(0x4BD8, 1);
+ ADD_RANGE(R300_PFS_PARAM_0_X, 64);
+ ADD_RANGE(0x4E00, 1);
+ ADD_RANGE(R300_RB3D_CBLEND, 2);
+ ADD_RANGE(R300_RB3D_COLORMASK, 1);
+ ADD_RANGE(0x4E10, 3);
+ ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
+ ADD_RANGE(0x4E50, 9);
+ ADD_RANGE(0x4E88, 1);
+ ADD_RANGE(0x4EA0, 2);
+ ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
+ ADD_RANGE(0x4F10, 4);
+ ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
+ ADD_RANGE(0x4F28, 1);
+ ADD_RANGE(0x4F30, 2);
+ ADD_RANGE(0x4F44, 1);
+ ADD_RANGE(0x4F54, 1);
+
+ ADD_RANGE(R300_TX_FILTER_0, 16);
+ ADD_RANGE(R300_TX_UNK1_0, 16);
+ ADD_RANGE(R300_TX_SIZE_0, 16);
+ ADD_RANGE(R300_TX_FORMAT_0, 16);
+ /* Texture offset is dangerous and needs more checking */
+ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
+ ADD_RANGE(R300_TX_UNK4_0, 16);
+ ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
+
+ /* Sporadic registers used as primitives are emitted */
+ ADD_RANGE(0x4f18, 1);
+ ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
+ ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
+ ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
+
+}
+
+static __inline__ int r300_check_range(unsigned reg, int count)
+{
+ int i;
+ if (reg & ~0xffff)
+ return -1;
+ for (i = (reg >> 2); i < (reg >> 2) + count; i++)
+ if (r300_reg_flags[i] != MARK_SAFE)
+ return 1;
+ return 0;
+}
+
+ /* we expect offsets passed to the framebuffer to be either within video memory or
+ within AGP space */
+static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv,
+ u32 offset)
+{
+ /* we realy want to check against end of video aperture
+ but this value is not being kept.
+ This code is correct for now (does the same thing as the
+ code that sets MC_FB_LOCATION) in radeon_cp.c */
+ if ((offset >= dev_priv->fb_location) &&
+ (offset < dev_priv->gart_vm_start))
+ return 0;
+ if ((offset >= dev_priv->gart_vm_start) &&
+ (offset < dev_priv->gart_vm_start + dev_priv->gart_size))
+ return 0;
+ return 1;
+}
+
+static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
+ dev_priv,
+ drm_radeon_kcmd_buffer_t
+ * cmdbuf,
+ drm_r300_cmd_header_t
+ header)
+{
+ int reg;
+ int sz;
+ int i;
+ int values[64];
+ RING_LOCALS;
+
+ sz = header.packet0.count;
+ reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+ if ((sz > 64) || (sz < 0)) {
+ DRM_ERROR
+ ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
+ reg, sz);
+ return DRM_ERR(EINVAL);
+ }
+ for (i = 0; i < sz; i++) {
+ values[i] = ((int *)cmdbuf->buf)[i];
+ switch (r300_reg_flags[(reg >> 2) + i]) {
+ case MARK_SAFE:
+ break;
+ case MARK_CHECK_OFFSET:
+ if (r300_check_offset(dev_priv, (u32) values[i])) {
+ DRM_ERROR
+ ("Offset failed range check (reg=%04x sz=%d)\n",
+ reg, sz);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("Register %04x failed check as flag=%02x\n",
+ reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ BEGIN_RING(1 + sz);
+ OUT_RING(CP_PACKET0(reg, sz - 1));
+ OUT_RING_TABLE(values, sz);
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz * 4;
+ cmdbuf->bufsz -= sz * 4;
+
+ return 0;
+}
+
+/**
+ * Emits a packet0 setting arbitrary registers.
+ * Called by r300_do_cp_cmdbuf.
+ *
+ * Note that checks are performed on contents and addresses of the registers
+ */
+static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int reg;
+ int sz;
+ RING_LOCALS;
+
+ sz = header.packet0.count;
+ reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+ if (!sz)
+ return 0;
+
+ if (sz * 4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ if (reg + sz * 4 >= 0x10000) {
+ DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
+ sz);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (r300_check_range(reg, sz)) {
+ /* go and check everything */
+ return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
+ header);
+ }
+ /* the rest of the data is safe to emit, whatever the values the user passed */
+
+ BEGIN_RING(1 + sz);
+ OUT_RING(CP_PACKET0(reg, sz - 1));
+ OUT_RING_TABLE((int *)cmdbuf->buf, sz);
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz * 4;
+ cmdbuf->bufsz -= sz * 4;
+
+ return 0;
+}
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int sz;
+ int addr;
+ RING_LOCALS;
+
+ sz = header.vpu.count;
+ addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
+
+ if (!sz)
+ return 0;
+ if (sz * 16 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_RING(5 + sz * 4);
+ /* Wait for VAP to come to senses.. */
+ /* there is no need to emit it multiple times, (only once before VAP is programmed,
+ but this optimization is for later */
+ OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
+ OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
+ OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
+ OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz * 16;
+ cmdbuf->bufsz -= sz * 16;
+
+ return 0;
+}
+
+/**
+ * Emit a clear packet from userspace.
+ * Called by r300_emit_packet3.
+ */
+static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf)
+{
+ RING_LOCALS;
+
+ if (8 * 4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_RING(10);
+ OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
+ OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
+ (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+ OUT_RING_TABLE((int *)cmdbuf->buf, 8);
+ ADVANCE_RING();
+
+ cmdbuf->buf += 8 * 4;
+ cmdbuf->bufsz -= 8 * 4;
+
+ return 0;
+}
+
+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf,
+ u32 header)
+{
+ int count, i, k;
+#define MAX_ARRAY_PACKET 64
+ u32 payload[MAX_ARRAY_PACKET];
+ u32 narrays;
+ RING_LOCALS;
+
+ count = (header >> 16) & 0x3fff;
+
+ if ((count + 1) > MAX_ARRAY_PACKET) {
+ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+ count);
+ return DRM_ERR(EINVAL);
+ }
+ memset(payload, 0, MAX_ARRAY_PACKET * 4);
+ memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
+
+ /* carefully check packet contents */
+
+ narrays = payload[0];
+ k = 0;
+ i = 1;
+ while ((k < narrays) && (i < (count + 1))) {
+ i++; /* skip attribute field */
+ if (r300_check_offset(dev_priv, payload[i])) {
+ DRM_ERROR
+ ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+ k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ if (k == narrays)
+ break;
+ /* have one more to process, they come in pairs */
+ if (r300_check_offset(dev_priv, payload[i])) {
+ DRM_ERROR
+ ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+ k, i);
+ return DRM_ERR(EINVAL);
+ }
+ k++;
+ i++;
+ }
+ /* do the counts match what we expect ? */
+ if ((k != narrays) || (i != (count + 1))) {
+ DRM_ERROR
+ ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+ k, i, narrays, count + 1);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* all clear, output packet */
+
+ BEGIN_RING(count + 2);
+ OUT_RING(header);
+ OUT_RING_TABLE(payload, count + 1);
+ ADVANCE_RING();
+
+ cmdbuf->buf += (count + 2) * 4;
+ cmdbuf->bufsz -= (count + 2) * 4;
+
+ return 0;
+}
+
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf)
+{
+ u32 header;
+ int count;
+ RING_LOCALS;
+
+ if (4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ /* Fixme !! This simply emits a packet without much checking.
+ We need to be smarter. */
+
+ /* obtain first word - actual packet3 header */
+ header = *(u32 *) cmdbuf->buf;
+
+ /* Is it packet 3 ? */
+ if ((header >> 30) != 0x3) {
+ DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+ }
+
+ count = (header >> 16) & 0x3fff;
+
+ /* Check again now that we know how much data to expect */
+ if ((count + 2) * 4 > cmdbuf->bufsz) {
+ DRM_ERROR
+ ("Expected packet3 of length %d but have only %d bytes left\n",
+ (count + 2) * 4, cmdbuf->bufsz);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* Is it a packet type we know about ? */
+ switch (header & 0xff00) {
+ case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
+ return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+
+ case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
+ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
+ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
+ case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
+ case RADEON_WAIT_FOR_IDLE:
+ case RADEON_CP_NOP:
+ /* these packets are safe */
+ break;
+ default:
+ DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+ }
+
+ BEGIN_RING(count + 2);
+ OUT_RING(header);
+ OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+ ADVANCE_RING();
+
+ cmdbuf->buf += (count + 2) * 4;
+ cmdbuf->bufsz -= (count + 2) * 4;
+
+ return 0;
+}
+
+/**
+ * Emit a rendering packet3 from userspace.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ int n;
+ int ret;
+ char *orig_buf = cmdbuf->buf;
+ int orig_bufsz = cmdbuf->bufsz;
+
+ /* This is a do-while-loop so that we run the interior at least once,
+ * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
+ */
+ n = 0;
+ do {
+ if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
+ ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
+ if (ret)
+ return ret;
+
+ cmdbuf->buf = orig_buf;
+ cmdbuf->bufsz = orig_bufsz;
+ }
+
+ switch (header.packet3.packet) {
+ case R300_CMD_PACKET3_CLEAR:
+ DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
+ ret = r300_emit_clear(dev_priv, cmdbuf);
+ if (ret) {
+ DRM_ERROR("r300_emit_clear failed\n");
+ return ret;
+ }
+ break;
+
+ case R300_CMD_PACKET3_RAW:
+ DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
+ ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
+ if (ret) {
+ DRM_ERROR("r300_emit_raw_packet3 failed\n");
+ return ret;
+ }
+ break;
+
+ default:
+ DRM_ERROR("bad packet3 type %i at %p\n",
+ header.packet3.packet,
+ cmdbuf->buf - sizeof(header));
+ return DRM_ERR(EINVAL);
+ }
+
+ n += R300_SIMULTANEOUS_CLIPRECTS;
+ } while (n < cmdbuf->nbox);
+
+ return 0;
+}
+
+/* Some of the R300 chips seem to be extremely touchy about the two registers
+ * that are configured in r300_pacify.
+ * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
+ * sends a command buffer that contains only state setting commands and a
+ * vertex program/parameter upload sequence, this will eventually lead to a
+ * lockup, unless the sequence is bracketed by calls to r300_pacify.
+ * So we should take great care to *always* call r300_pacify before
+ * *anything* 3D related, and again afterwards. This is what the
+ * call bracket in r300_do_cp_cmdbuf is for.
+ */
+
+/**
+ * Emit the sequence to pacify R300.
+ */
+static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)
+{
+ RING_LOCALS;
+
+ BEGIN_RING(6);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(0xa);
+ OUT_RING(CP_PACKET0(0x4f18, 0));
+ OUT_RING(0x3);
+ OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
+ OUT_RING(0x0);
+ ADVANCE_RING();
+}
+
+/**
+ * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
+ * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
+ * be careful about how this function is called.
+ */
+static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+
+ buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+ buf->pending = 1;
+ buf->used = 0;
+}
+
+/**
+ * Parses and validates a user-supplied command buffer and emits appropriate
+ * commands on the DMA ring buffer.
+ * Called by the ioctl handler function radeon_cp_cmdbuf.
+ */
+int r300_do_cp_cmdbuf(drm_device_t * dev,
+ DRMFILE filp,
+ drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf = NULL;
+ int emit_dispatch_age = 0;
+ int ret = 0;
+
+ DRM_DEBUG("\n");
+
+ /* See the comment above r300_emit_begin3d for why this call must be here,
+ * and what the cleanup gotos are for. */
+ r300_pacify(dev_priv);
+
+ if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
+ ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
+ if (ret)
+ goto cleanup;
+ }
+
+ while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+ int idx;
+ drm_r300_cmd_header_t header;
+
+ header.u = *(unsigned int *)cmdbuf->buf;
+
+ cmdbuf->buf += sizeof(header);
+ cmdbuf->bufsz -= sizeof(header);
+
+ switch (header.header.cmd_type) {
+ case R300_CMD_PACKET0:
+ DRM_DEBUG("R300_CMD_PACKET0\n");
+ ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_packet0 failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_VPU:
+ DRM_DEBUG("R300_CMD_VPU\n");
+ ret = r300_emit_vpu(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_vpu failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_PACKET3:
+ DRM_DEBUG("R300_CMD_PACKET3\n");
+ ret = r300_emit_packet3(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_packet3 failed\n");
+ goto cleanup;
+ }
+ break;
+
+ case R300_CMD_END3D:
+ DRM_DEBUG("R300_CMD_END3D\n");
+ /* TODO:
+ Ideally userspace driver should not need to issue this call,
+ i.e. the drm driver should issue it automatically and prevent
+ lockups.
+
+ In practice, we do not understand why this call is needed and what
+ it does (except for some vague guesses that it has to do with cache
+ coherence) and so the user space driver does it.
+
+ Once we are sure which uses prevent lockups the code could be moved
+ into the kernel and the userspace driver will not
+ need to use this command.
+
+ Note that issuing this command does not hurt anything
+ except, possibly, performance */
+ r300_pacify(dev_priv);
+ break;
+
+ case R300_CMD_CP_DELAY:
+ /* simple enough, we can do it here */
+ DRM_DEBUG("R300_CMD_CP_DELAY\n");
+ {
+ int i;
+ RING_LOCALS;
+
+ BEGIN_RING(header.delay.count);
+ for (i = 0; i < header.delay.count; i++)
+ OUT_RING(RADEON_CP_PACKET2);
+ ADVANCE_RING();
+ }
+ break;
+
+ case R300_CMD_DMA_DISCARD:
+ DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+ idx = header.dma.buf_idx;
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ idx, dma->buf_count - 1);
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+
+ buf = dma->buflist[idx];
+ if (buf->filp != filp || buf->pending) {
+ DRM_ERROR("bad buffer %p %p %d\n",
+ buf->filp, filp, buf->pending);
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+
+ emit_dispatch_age = 1;
+ r300_discard_buffer(dev, buf);
+ break;
+
+ case R300_CMD_WAIT:
+ /* simple enough, we can do it here */
+ DRM_DEBUG("R300_CMD_WAIT\n");
+ if (header.wait.flags == 0)
+ break; /* nothing to do */
+
+ {
+ RING_LOCALS;
+
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING((header.wait.flags & 0xf) << 14);
+ ADVANCE_RING();
+ }
+ break;
+
+ default:
+ DRM_ERROR("bad cmd_type %i at %p\n",
+ header.header.cmd_type,
+ cmdbuf->buf - sizeof(header));
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+ }
+ }
+
+ DRM_DEBUG("END\n");
+
+ cleanup:
+ r300_pacify(dev_priv);
+
+ /* We emit the vertex buffer age here, outside the pacifier "brackets"
+ * for two reasons:
+ * (1) This may coalesce multiple age emissions into a single one and
+ * (2) more importantly, some chips lock up hard when scratch registers
+ * are written inside the pacifier bracket.
+ */
+ if (emit_dispatch_age) {
+ RING_LOCALS;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING(2);
+ RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
+ ADVANCE_RING();
+ }
+
+ COMMIT_RING();
+
+ return ret;
+}
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
new file mode 100644
index 000000000000..e5b73c002394
--- /dev/null
+++ b/drivers/char/drm/r300_reg.h
@@ -0,0 +1,1406 @@
+/**************************************************************************
+
+Copyright (C) 2004-2005 Nicolai Haehnle et al.
+
+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
+on 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 AUTHOR(S) AND/OR THEIR 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 _R300_REG_H
+#define _R300_REG_H
+
+#define R300_MC_INIT_MISC_LAT_TIMER 0x180
+# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28
+
+#define R300_MC_INIT_GFX_LAT_TIMER 0x154
+# define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28
+
+/*
+This file contains registers and constants for the R300. They have been
+found mostly by examining command buffers captured using glxtest, as well
+as by extrapolating some known registers and constants from the R200.
+
+I am fairly certain that they are correct unless stated otherwise in comments.
+*/
+
+#define R300_SE_VPORT_XSCALE 0x1D98
+#define R300_SE_VPORT_XOFFSET 0x1D9C
+#define R300_SE_VPORT_YSCALE 0x1DA0
+#define R300_SE_VPORT_YOFFSET 0x1DA4
+#define R300_SE_VPORT_ZSCALE 0x1DA8
+#define R300_SE_VPORT_ZOFFSET 0x1DAC
+
+/* This register is written directly and also starts data section in many 3d CP_PACKET3's */
+#define R300_VAP_VF_CNTL 0x2084
+
+# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0
+# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0)
+# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0)
+# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0)
+
+# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4
+ /* State based - direct writes to registers trigger vertex generation */
+# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4)
+
+ /* I don't think I saw these three used.. */
+# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6
+# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9
+# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10
+
+ /* index size - when not set the indices are assumed to be 16 bit */
+# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
+ /* number of vertices */
+# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
+
+/* BEGIN: Wild guesses */
+#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090
+# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
+
+#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+/* END */
+
+#define R300_SE_VTE_CNTL 0x20b0
+# define R300_VPORT_X_SCALE_ENA 0x00000001
+# define R300_VPORT_X_OFFSET_ENA 0x00000002
+# define R300_VPORT_Y_SCALE_ENA 0x00000004
+# define R300_VPORT_Y_OFFSET_ENA 0x00000008
+# define R300_VPORT_Z_SCALE_ENA 0x00000010
+# define R300_VPORT_Z_OFFSET_ENA 0x00000020
+# define R300_VTX_XY_FMT 0x00000100
+# define R300_VTX_Z_FMT 0x00000200
+# define R300_VTX_W0_FMT 0x00000400
+# define R300_VTX_W0_NORMALIZE 0x00000800
+# define R300_VTX_ST_DENORMALIZED 0x00001000
+
+/* BEGIN: Vertex data assembly - lots of uncertainties */
+/* gap */
+/* Where do we get our vertex data?
+//
+// Vertex data either comes either from immediate mode registers or from
+// vertex arrays.
+// There appears to be no mixed mode (though we can force the pitch of
+// vertex arrays to 0, effectively reusing the same element over and over
+// again).
+//
+// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+// if these registers influence vertex array processing.
+//
+// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+//
+// In both cases, vertex attributes are then passed through INPUT_ROUTE.
+
+// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+// into the vertex processor's input registers.
+// The first word routes the first input, the second word the second, etc.
+// The corresponding input is routed into the register with the given index.
+// The list is ended by a word with INPUT_ROUTE_END set.
+//
+// Always set COMPONENTS_4 in immediate mode. */
+
+#define R300_VAP_INPUT_ROUTE_0_0 0x2150
+# define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0)
+# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
+# define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8
+# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
+# define R300_VAP_INPUT_ROUTE_END (1 << 13)
+# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
+#define R300_VAP_INPUT_ROUTE_0_1 0x2154
+#define R300_VAP_INPUT_ROUTE_0_2 0x2158
+#define R300_VAP_INPUT_ROUTE_0_3 0x215C
+#define R300_VAP_INPUT_ROUTE_0_4 0x2160
+#define R300_VAP_INPUT_ROUTE_0_5 0x2164
+#define R300_VAP_INPUT_ROUTE_0_6 0x2168
+#define R300_VAP_INPUT_ROUTE_0_7 0x216C
+
+/* gap */
+/* Notes:
+// - always set up to produce at least two attributes:
+// if vertex program uses only position, fglrx will set normal, too
+// - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */
+#define R300_VAP_INPUT_CNTL_0 0x2180
+# define R300_INPUT_CNTL_0_COLOR 0x00000001
+#define R300_VAP_INPUT_CNTL_1 0x2184
+# define R300_INPUT_CNTL_POS 0x00000001
+# define R300_INPUT_CNTL_NORMAL 0x00000002
+# define R300_INPUT_CNTL_COLOR 0x00000004
+# define R300_INPUT_CNTL_TC0 0x00000400
+# define R300_INPUT_CNTL_TC1 0x00000800
+# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
+# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
+# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
+# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
+# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
+# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
+
+/* gap */
+/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
+// are set to a swizzling bit pattern, other words are 0.
+//
+// In immediate mode, the pattern is always set to xyzw. In vertex array
+// mode, the swizzling pattern is e.g. used to set zw components in texture
+// coordinates with only tweo components. */
+#define R300_VAP_INPUT_ROUTE_1_0 0x21E0
+# define R300_INPUT_ROUTE_SELECT_X 0
+# define R300_INPUT_ROUTE_SELECT_Y 1
+# define R300_INPUT_ROUTE_SELECT_Z 2
+# define R300_INPUT_ROUTE_SELECT_W 3
+# define R300_INPUT_ROUTE_SELECT_ZERO 4
+# define R300_INPUT_ROUTE_SELECT_ONE 5
+# define R300_INPUT_ROUTE_SELECT_MASK 7
+# define R300_INPUT_ROUTE_X_SHIFT 0
+# define R300_INPUT_ROUTE_Y_SHIFT 3
+# define R300_INPUT_ROUTE_Z_SHIFT 6
+# define R300_INPUT_ROUTE_W_SHIFT 9
+# define R300_INPUT_ROUTE_ENABLE (15 << 12)
+#define R300_VAP_INPUT_ROUTE_1_1 0x21E4
+#define R300_VAP_INPUT_ROUTE_1_2 0x21E8
+#define R300_VAP_INPUT_ROUTE_1_3 0x21EC
+#define R300_VAP_INPUT_ROUTE_1_4 0x21F0
+#define R300_VAP_INPUT_ROUTE_1_5 0x21F4
+#define R300_VAP_INPUT_ROUTE_1_6 0x21F8
+#define R300_VAP_INPUT_ROUTE_1_7 0x21FC
+
+/* END */
+
+/* gap */
+/* BEGIN: Upload vertex program and data
+// The programmable vertex shader unit has a memory bank of unknown size
+// that can be written to in 16 byte units by writing the address into
+// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+//
+// Pointers into the memory bank are always in multiples of 16 bytes.
+//
+// The memory bank is divided into areas with fixed meaning.
+//
+// Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+// whereas the difference between known addresses suggests size 512.
+//
+// Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+// Native reported limits and the VPI layout suggest size 256, whereas
+// difference between known addresses suggests size 512.
+//
+// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+// floating point pointsize. The exact purpose of this state is uncertain,
+// as there is also the R300_RE_POINTSIZE register.
+//
+// Multiple vertex programs and parameter sets can be loaded at once,
+// which could explain the size discrepancy. */
+#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200
+# define R300_PVS_UPLOAD_PROGRAM 0x00000000
+# define R300_PVS_UPLOAD_PARAMETERS 0x00000200
+# define R300_PVS_UPLOAD_POINTSIZE 0x00000406
+/* gap */
+#define R300_VAP_PVS_UPLOAD_DATA 0x2208
+/* END */
+
+/* gap */
+/* I do not know the purpose of this register. However, I do know that
+// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+// for normal rendering. */
+#define R300_VAP_UNKNOWN_221C 0x221C
+# define R300_221C_NORMAL 0x00000000
+# define R300_221C_CLEAR 0x0001C000
+
+/* gap */
+/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
+// rendering commands and overwriting vertex program parameters.
+// Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+// avoids bugs caused by still running shaders reading bad data from memory. */
+#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
+
+/* Absolutely no clue what this register is about. */
+#define R300_VAP_UNKNOWN_2288 0x2288
+# define R300_2288_R300 0x00750000 /* -- nh */
+# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+
+/* gap */
+/* Addresses are relative to the vertex program instruction area of the
+// memory bank. PROGRAM_END points to the last instruction of the active
+// program
+//
+// The meaning of the two UNKNOWN fields is obviously not known. However,
+// experiments so far have shown that both *must* point to an instruction
+// inside the vertex program, otherwise the GPU locks up.
+// fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
+// Most likely this is used to ignore rest of the program in cases where group of verts arent visible.
+// For some reason this "section" is sometimes accepted other instruction that have
+// no relationship with position calculations.
+*/
+#define R300_VAP_PVS_CNTL_1 0x22D0
+# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
+# define R300_PVS_CNTL_1_POS_END_SHIFT 10
+# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20
+/* Addresses are relative the the vertex program parameters area. */
+#define R300_VAP_PVS_CNTL_2 0x22D4
+# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
+# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16
+#define R300_VAP_PVS_CNTL_3 0x22D8
+# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10
+# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
+
+/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
+// immediate vertices */
+#define R300_VAP_VTX_COLOR_R 0x2464
+#define R300_VAP_VTX_COLOR_G 0x2468
+#define R300_VAP_VTX_COLOR_B 0x246C
+#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_Y_1 0x2494
+#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
+#define R300_VAP_VTX_POS_0_Y_2 0x24A4
+#define R300_VAP_VTX_POS_0_Z_2 0x24A8
+#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */
+
+/* gap */
+
+/* These are values from r300_reg/r300_reg.h - they are known to be correct
+ and are here so we can use one register file instead of several
+ - Vladimir */
+#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000
+# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16)
+
+#define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004
+ /* each of the following is 3 bits wide, specifies number
+ of components */
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+
+/* UNK30 seems to enables point to quad transformation on textures
+ (or something closely related to that).
+ This bit is rather fatal at the time being due to lackings at pixel shader side */
+#define R300_GB_ENABLE 0x4008
+# define R300_GB_POINT_STUFF_ENABLE (1<<0)
+# define R300_GB_LINE_STUFF_ENABLE (1<<1)
+# define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2)
+# define R300_GB_STENCIL_AUTO_ENABLE (1<<4)
+# define R300_GB_UNK30 (1<<30)
+ /* each of the following is 2 bits wide */
+#define R300_GB_TEX_REPLICATE 0
+#define R300_GB_TEX_ST 1
+#define R300_GB_TEX_STR 2
+# define R300_GB_TEX0_SOURCE_SHIFT 16
+# define R300_GB_TEX1_SOURCE_SHIFT 18
+# define R300_GB_TEX2_SOURCE_SHIFT 20
+# define R300_GB_TEX3_SOURCE_SHIFT 22
+# define R300_GB_TEX4_SOURCE_SHIFT 24
+# define R300_GB_TEX5_SOURCE_SHIFT 26
+# define R300_GB_TEX6_SOURCE_SHIFT 28
+# define R300_GB_TEX7_SOURCE_SHIFT 30
+
+/* MSPOS - positions for multisample antialiasing (?) */
+#define R300_GB_MSPOS0 0x4010
+ /* shifts - each of the fields is 4 bits */
+# define R300_GB_MSPOS0__MS_X0_SHIFT 0
+# define R300_GB_MSPOS0__MS_Y0_SHIFT 4
+# define R300_GB_MSPOS0__MS_X1_SHIFT 8
+# define R300_GB_MSPOS0__MS_Y1_SHIFT 12
+# define R300_GB_MSPOS0__MS_X2_SHIFT 16
+# define R300_GB_MSPOS0__MS_Y2_SHIFT 20
+# define R300_GB_MSPOS0__MSBD0_Y 24
+# define R300_GB_MSPOS0__MSBD0_X 28
+
+#define R300_GB_MSPOS1 0x4014
+# define R300_GB_MSPOS1__MS_X3_SHIFT 0
+# define R300_GB_MSPOS1__MS_Y3_SHIFT 4
+# define R300_GB_MSPOS1__MS_X4_SHIFT 8
+# define R300_GB_MSPOS1__MS_Y4_SHIFT 12
+# define R300_GB_MSPOS1__MS_X5_SHIFT 16
+# define R300_GB_MSPOS1__MS_Y5_SHIFT 20
+# define R300_GB_MSPOS1__MSBD1 24
+
+#define R300_GB_TILE_CONFIG 0x4018
+# define R300_GB_TILE_ENABLE (1<<0)
+# define R300_GB_TILE_PIPE_COUNT_RV300 0
+# define R300_GB_TILE_PIPE_COUNT_R300 (3<<1)
+# define R300_GB_TILE_PIPE_COUNT_R420 (7<<1)
+# define R300_GB_TILE_SIZE_8 0
+# define R300_GB_TILE_SIZE_16 (1<<4)
+# define R300_GB_TILE_SIZE_32 (2<<4)
+# define R300_GB_SUPER_SIZE_1 (0<<6)
+# define R300_GB_SUPER_SIZE_2 (1<<6)
+# define R300_GB_SUPER_SIZE_4 (2<<6)
+# define R300_GB_SUPER_SIZE_8 (3<<6)
+# define R300_GB_SUPER_SIZE_16 (4<<6)
+# define R300_GB_SUPER_SIZE_32 (5<<6)
+# define R300_GB_SUPER_SIZE_64 (6<<6)
+# define R300_GB_SUPER_SIZE_128 (7<<6)
+# define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */
+# define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */
+# define R300_GB_SUPER_TILE_A 0
+# define R300_GB_SUPER_TILE_B (1<<15)
+# define R300_GB_SUBPIXEL_1_12 0
+# define R300_GB_SUBPIXEL_1_16 (1<<16)
+
+#define R300_GB_FIFO_SIZE 0x4024
+ /* each of the following is 2 bits wide */
+#define R300_GB_FIFO_SIZE_32 0
+#define R300_GB_FIFO_SIZE_64 1
+#define R300_GB_FIFO_SIZE_128 2
+#define R300_GB_FIFO_SIZE_256 3
+# define R300_SC_IFIFO_SIZE_SHIFT 0
+# define R300_SC_TZFIFO_SIZE_SHIFT 2
+# define R300_SC_BFIFO_SIZE_SHIFT 4
+
+# define R300_US_OFIFO_SIZE_SHIFT 12
+# define R300_US_WFIFO_SIZE_SHIFT 14
+ /* the following use the same constants as above, but meaning is
+ is times 2 (i.e. instead of 32 words it means 64 */
+# define R300_RS_TFIFO_SIZE_SHIFT 6
+# define R300_RS_CFIFO_SIZE_SHIFT 8
+# define R300_US_RAM_SIZE_SHIFT 10
+ /* watermarks, 3 bits wide */
+# define R300_RS_HIGHWATER_COL_SHIFT 16
+# define R300_RS_HIGHWATER_TEX_SHIFT 19
+# define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */
+# define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24
+
+#define R300_GB_SELECT 0x401C
+# define R300_GB_FOG_SELECT_C0A 0
+# define R300_GB_FOG_SELECT_C1A 1
+# define R300_GB_FOG_SELECT_C2A 2
+# define R300_GB_FOG_SELECT_C3A 3
+# define R300_GB_FOG_SELECT_1_1_W 4
+# define R300_GB_FOG_SELECT_Z 5
+# define R300_GB_DEPTH_SELECT_Z 0
+# define R300_GB_DEPTH_SELECT_1_1_W (1<<3)
+# define R300_GB_W_SELECT_1_W 0
+# define R300_GB_W_SELECT_1 (1<<4)
+
+#define R300_GB_AA_CONFIG 0x4020
+# define R300_AA_ENABLE 0x01
+# define R300_AA_SUBSAMPLES_2 0
+# define R300_AA_SUBSAMPLES_3 (1<<1)
+# define R300_AA_SUBSAMPLES_4 (2<<1)
+# define R300_AA_SUBSAMPLES_6 (3<<1)
+
+/* END */
+
+/* gap */
+/* The upper enable bits are guessed, based on fglrx reported limits. */
+#define R300_TX_ENABLE 0x4104
+# define R300_TX_ENABLE_0 (1 << 0)
+# define R300_TX_ENABLE_1 (1 << 1)
+# define R300_TX_ENABLE_2 (1 << 2)
+# define R300_TX_ENABLE_3 (1 << 3)
+# define R300_TX_ENABLE_4 (1 << 4)
+# define R300_TX_ENABLE_5 (1 << 5)
+# define R300_TX_ENABLE_6 (1 << 6)
+# define R300_TX_ENABLE_7 (1 << 7)
+# define R300_TX_ENABLE_8 (1 << 8)
+# define R300_TX_ENABLE_9 (1 << 9)
+# define R300_TX_ENABLE_10 (1 << 10)
+# define R300_TX_ENABLE_11 (1 << 11)
+# define R300_TX_ENABLE_12 (1 << 12)
+# define R300_TX_ENABLE_13 (1 << 13)
+# define R300_TX_ENABLE_14 (1 << 14)
+# define R300_TX_ENABLE_15 (1 << 15)
+
+/* The pointsize is given in multiples of 6. The pointsize can be
+// enormous: Clear() renders a single point that fills the entire
+// framebuffer. */
+#define R300_RE_POINTSIZE 0x421C
+# define R300_POINTSIZE_Y_SHIFT 0
+# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
+# define R300_POINTSIZE_X_SHIFT 16
+# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
+# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6)
+
+/* The line width is given in multiples of 6.
+ In default mode lines are classified as vertical lines.
+ HO: horizontal
+ VE: vertical or horizontal
+ HO & VE: no classification
+*/
+#define R300_RE_LINE_CNT 0x4234
+# define R300_LINESIZE_SHIFT 0
+# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
+# define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6)
+# define R300_LINE_CNT_HO (1 << 16)
+# define R300_LINE_CNT_VE (1 << 17)
+
+/* Some sort of scale or clamp value for texcoordless textures. */
+#define R300_RE_UNK4238 0x4238
+
+#define R300_RE_SHADE_MODEL 0x4278
+# define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa
+# define R300_RE_SHADE_MODEL_FLAT 0x39595
+
+/* Dangerous */
+#define R300_RE_POLYGON_MODE 0x4288
+# define R300_PM_ENABLED (1 << 0)
+# define R300_PM_FRONT_POINT (0 << 0)
+# define R300_PM_BACK_POINT (0 << 0)
+# define R300_PM_FRONT_LINE (1 << 4)
+# define R300_PM_FRONT_FILL (1 << 5)
+# define R300_PM_BACK_LINE (1 << 7)
+# define R300_PM_BACK_FILL (1 << 8)
+
+/* Not sure why there are duplicate of factor and constant values.
+ My best guess so far is that there are seperate zbiases for test and write.
+ Ordering might be wrong.
+ Some of the tests indicate that fgl has a fallback implementation of zbias
+ via pixel shaders. */
+#define R300_RE_ZBIAS_T_FACTOR 0x42A4
+#define R300_RE_ZBIAS_T_CONSTANT 0x42A8
+#define R300_RE_ZBIAS_W_FACTOR 0x42AC
+#define R300_RE_ZBIAS_W_CONSTANT 0x42B0
+
+/* This register needs to be set to (1<<1) for RV350 to correctly
+ perform depth test (see --vb-triangles in r300_demo)
+ Don't know about other chips. - Vladimir
+ This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT).
+ One to enable depth test and one for depth write.
+ Yet this doesnt explain why depth writes work ...
+ */
+#define R300_RE_OCCLUSION_CNTL 0x42B4
+# define R300_OCCLUSION_ON (1<<1)
+
+#define R300_RE_CULL_CNTL 0x42B8
+# define R300_CULL_FRONT (1 << 0)
+# define R300_CULL_BACK (1 << 1)
+# define R300_FRONT_FACE_CCW (0 << 2)
+# define R300_FRONT_FACE_CW (1 << 2)
+
+/* BEGIN: Rasterization / Interpolators - many guesses
+// 0_UNKNOWN_18 has always been set except for clear operations.
+// TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+// on the vertex program, *not* the fragment program) */
+#define R300_RS_CNTL_0 0x4300
+# define R300_RS_CNTL_TC_CNT_SHIFT 2
+# define R300_RS_CNTL_TC_CNT_MASK (7 << 2)
+# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */
+# define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18)
+/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+#define R300_RS_CNTL_1 0x4304
+
+/* gap */
+/* Only used for texture coordinates.
+// Use the source field to route texture coordinate input from the vertex program
+// to the desired interpolator. Note that the source field is relative to the
+// outputs the vertex program *actually* writes. If a vertex program only writes
+// texcoord[1], this will be source index 0.
+// Set INTERP_USED on all interpolators that produce data used by the
+// fragment program. INTERP_USED looks like a swizzling mask, but
+// I haven't seen it used that way.
+//
+// Note: The _UNKNOWN constants are always set in their respective register.
+// I don't know if this is necessary. */
+#define R300_RS_INTERP_0 0x4310
+#define R300_RS_INTERP_1 0x4314
+# define R300_RS_INTERP_1_UNKNOWN 0x40
+#define R300_RS_INTERP_2 0x4318
+# define R300_RS_INTERP_2_UNKNOWN 0x80
+#define R300_RS_INTERP_3 0x431C
+# define R300_RS_INTERP_3_UNKNOWN 0xC0
+#define R300_RS_INTERP_4 0x4320
+#define R300_RS_INTERP_5 0x4324
+#define R300_RS_INTERP_6 0x4328
+#define R300_RS_INTERP_7 0x432C
+# define R300_RS_INTERP_SRC_SHIFT 2
+# define R300_RS_INTERP_SRC_MASK (7 << 2)
+# define R300_RS_INTERP_USED 0x00D10000
+
+/* These DWORDs control how vertex data is routed into fragment program
+// registers, after interpolators. */
+#define R300_RS_ROUTE_0 0x4330
+#define R300_RS_ROUTE_1 0x4334
+#define R300_RS_ROUTE_2 0x4338
+#define R300_RS_ROUTE_3 0x433C /* GUESS */
+#define R300_RS_ROUTE_4 0x4340 /* GUESS */
+#define R300_RS_ROUTE_5 0x4344 /* GUESS */
+#define R300_RS_ROUTE_6 0x4348 /* GUESS */
+#define R300_RS_ROUTE_7 0x434C /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_0 0
+# define R300_RS_ROUTE_SOURCE_INTERP_1 1
+# define R300_RS_ROUTE_SOURCE_INTERP_2 2
+# define R300_RS_ROUTE_SOURCE_INTERP_3 3
+# define R300_RS_ROUTE_SOURCE_INTERP_4 4
+# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
+# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
+# define R300_RS_ROUTE_DEST_SHIFT 6
+# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
+
+/* Special handling for color: When the fragment program uses color,
+// the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+// color register index. */
+# define R300_RS_ROUTE_0_COLOR (1 << 14)
+# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17
+# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
+/* As above, but for secondary color */
+# define R300_RS_ROUTE_1_COLOR1 (1 << 14)
+# define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
+# define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17)
+# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11)
+/* END */
+
+/* BEGIN: Scissors and cliprects
+// There are four clipping rectangles. Their corner coordinates are inclusive.
+// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+// on whether the pixel is inside cliprects 0-3, respectively. For example,
+// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+// the number 3 (binary 0011).
+// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+// the pixel is rasterized.
+//
+// In addition to this, there is a scissors rectangle. Only pixels inside the
+// scissors rectangle are drawn. (coordinates are inclusive)
+//
+// For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+// for the purpose of clipping and scissors. */
+#define R300_RE_CLIPRECT_TL_0 0x43B0
+#define R300_RE_CLIPRECT_BR_0 0x43B4
+#define R300_RE_CLIPRECT_TL_1 0x43B8
+#define R300_RE_CLIPRECT_BR_1 0x43BC
+#define R300_RE_CLIPRECT_TL_2 0x43C0
+#define R300_RE_CLIPRECT_BR_2 0x43C4
+#define R300_RE_CLIPRECT_TL_3 0x43C8
+#define R300_RE_CLIPRECT_BR_3 0x43CC
+# define R300_CLIPRECT_OFFSET 1440
+# define R300_CLIPRECT_MASK 0x1FFF
+# define R300_CLIPRECT_X_SHIFT 0
+# define R300_CLIPRECT_X_MASK (0x1FFF << 0)
+# define R300_CLIPRECT_Y_SHIFT 13
+# define R300_CLIPRECT_Y_MASK (0x1FFF << 13)
+#define R300_RE_CLIPRECT_CNTL 0x43D0
+# define R300_CLIP_OUT (1 << 0)
+# define R300_CLIP_0 (1 << 1)
+# define R300_CLIP_1 (1 << 2)
+# define R300_CLIP_10 (1 << 3)
+# define R300_CLIP_2 (1 << 4)
+# define R300_CLIP_20 (1 << 5)
+# define R300_CLIP_21 (1 << 6)
+# define R300_CLIP_210 (1 << 7)
+# define R300_CLIP_3 (1 << 8)
+# define R300_CLIP_30 (1 << 9)
+# define R300_CLIP_31 (1 << 10)
+# define R300_CLIP_310 (1 << 11)
+# define R300_CLIP_32 (1 << 12)
+# define R300_CLIP_320 (1 << 13)
+# define R300_CLIP_321 (1 << 14)
+# define R300_CLIP_3210 (1 << 15)
+
+/* gap */
+#define R300_RE_SCISSORS_TL 0x43E0
+#define R300_RE_SCISSORS_BR 0x43E4
+# define R300_SCISSORS_OFFSET 1440
+# define R300_SCISSORS_X_SHIFT 0
+# define R300_SCISSORS_X_MASK (0x1FFF << 0)
+# define R300_SCISSORS_Y_SHIFT 13
+# define R300_SCISSORS_Y_MASK (0x1FFF << 13)
+/* END */
+
+/* BEGIN: Texture specification
+// The texture specification dwords are grouped by meaning and not by texture unit.
+// This means that e.g. the offset for texture image unit N is found in register
+// TX_OFFSET_0 + (4*N) */
+#define R300_TX_FILTER_0 0x4400
+# define R300_TX_REPEAT 0
+# define R300_TX_MIRRORED 1
+# define R300_TX_CLAMP 4
+# define R300_TX_CLAMP_TO_EDGE 2
+# define R300_TX_CLAMP_TO_BORDER 6
+# define R300_TX_WRAP_S_SHIFT 0
+# define R300_TX_WRAP_S_MASK (7 << 0)
+# define R300_TX_WRAP_T_SHIFT 3
+# define R300_TX_WRAP_T_MASK (7 << 3)
+# define R300_TX_WRAP_Q_SHIFT 6
+# define R300_TX_WRAP_Q_MASK (7 << 6)
+# define R300_TX_MAG_FILTER_NEAREST (1 << 9)
+# define R300_TX_MAG_FILTER_LINEAR (2 << 9)
+# define R300_TX_MAG_FILTER_MASK (3 << 9)
+# define R300_TX_MIN_FILTER_NEAREST (1 << 11)
+# define R300_TX_MIN_FILTER_LINEAR (2 << 11)
+# define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11)
+# define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11)
+# define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11)
+# define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11)
+
+/* NOTE: NEAREST doesnt seem to exist.
+ Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ anisotropy modes because that would void selected mag filter */
+# define R300_TX_MIN_FILTER_ANISO_NEAREST ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_LINEAR ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
+# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) )
+# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21)
+# define R300_TX_MAX_ANISO_2_TO_1 (2 << 21)
+# define R300_TX_MAX_ANISO_4_TO_1 (4 << 21)
+# define R300_TX_MAX_ANISO_8_TO_1 (6 << 21)
+# define R300_TX_MAX_ANISO_16_TO_1 (8 << 21)
+# define R300_TX_MAX_ANISO_MASK (14 << 21)
+
+#define R300_TX_UNK1_0 0x4440
+# define R300_LOD_BIAS_MASK 0x1fff
+
+#define R300_TX_SIZE_0 0x4480
+# define R300_TX_WIDTHMASK_SHIFT 0
+# define R300_TX_WIDTHMASK_MASK (2047 << 0)
+# define R300_TX_HEIGHTMASK_SHIFT 11
+# define R300_TX_HEIGHTMASK_MASK (2047 << 11)
+# define R300_TX_UNK23 (1 << 23)
+# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */
+# define R300_TX_SIZE_MASK (15 << 26)
+#define R300_TX_FORMAT_0 0x44C0
+ /* The interpretation of the format word by Wladimir van der Laan */
+ /* The X, Y, Z and W refer to the layout of the components.
+ They are given meanings as R, G, B and Alpha by the swizzle
+ specification */
+# define R300_TX_FORMAT_X8 0x0
+# define R300_TX_FORMAT_X16 0x1
+# define R300_TX_FORMAT_Y4X4 0x2
+# define R300_TX_FORMAT_Y8X8 0x3
+# define R300_TX_FORMAT_Y16X16 0x4
+# define R300_TX_FORMAT_Z3Y3X2 0x5
+# define R300_TX_FORMAT_Z5Y6X5 0x6
+# define R300_TX_FORMAT_Z6Y5X5 0x7
+# define R300_TX_FORMAT_Z11Y11X10 0x8
+# define R300_TX_FORMAT_Z10Y11X11 0x9
+# define R300_TX_FORMAT_W4Z4Y4X4 0xA
+# define R300_TX_FORMAT_W1Z5Y5X5 0xB
+# define R300_TX_FORMAT_W8Z8Y8X8 0xC
+# define R300_TX_FORMAT_W2Z10Y10X10 0xD
+# define R300_TX_FORMAT_W16Z16Y16X16 0xE
+# define R300_TX_FORMAT_DXT1 0xF
+# define R300_TX_FORMAT_DXT3 0x10
+# define R300_TX_FORMAT_DXT5 0x11
+# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
+# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
+# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
+# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
+ /* 0x16 - some 16 bit green format.. ?? */
+# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */
+
+ /* gap */
+ /* Floating point formats */
+ /* Note - hardware supports both 16 and 32 bit floating point */
+# define R300_TX_FORMAT_FL_I16 0x18
+# define R300_TX_FORMAT_FL_I16A16 0x19
+# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A
+# define R300_TX_FORMAT_FL_I32 0x1B
+# define R300_TX_FORMAT_FL_I32A32 0x1C
+# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D
+ /* alpha modes, convenience mostly */
+ /* if you have alpha, pick constant appropriate to the
+ number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
+# define R300_TX_FORMAT_ALPHA_1CH 0x000
+# define R300_TX_FORMAT_ALPHA_2CH 0x200
+# define R300_TX_FORMAT_ALPHA_4CH 0x600
+# define R300_TX_FORMAT_ALPHA_NONE 0xA00
+ /* Swizzling */
+ /* constants */
+# define R300_TX_FORMAT_X 0
+# define R300_TX_FORMAT_Y 1
+# define R300_TX_FORMAT_Z 2
+# define R300_TX_FORMAT_W 3
+# define R300_TX_FORMAT_ZERO 4
+# define R300_TX_FORMAT_ONE 5
+# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */
+
+# define R300_TX_FORMAT_B_SHIFT 18
+# define R300_TX_FORMAT_G_SHIFT 15
+# define R300_TX_FORMAT_R_SHIFT 12
+# define R300_TX_FORMAT_A_SHIFT 9
+ /* Convenience macro to take care of layout and swizzling */
+# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) (\
+ ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
+ | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
+ | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
+ | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
+ | (R300_TX_FORMAT_##FMT) \
+ )
+ /* These can be ORed with result of R300_EASY_TX_FORMAT() */
+ /* We don't really know what they do. Take values from a constant color ? */
+# define R300_TX_FORMAT_CONST_X (1<<5)
+# define R300_TX_FORMAT_CONST_Y (2<<5)
+# define R300_TX_FORMAT_CONST_Z (4<<5)
+# define R300_TX_FORMAT_CONST_W (8<<5)
+
+# define R300_TX_FORMAT_YUV_MODE 0x00800000
+
+#define R300_TX_OFFSET_0 0x4540
+/* BEGIN: Guess from R200 */
+# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
+# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
+# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0)
+# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+# define R300_TXO_OFFSET_MASK 0xffffffe0
+# define R300_TXO_OFFSET_SHIFT 5
+/* END */
+#define R300_TX_UNK4_0 0x4580
+#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
+
+/* END */
+
+/* BEGIN: Fragment program instruction set
+// Fragment programs are written directly into register space.
+// There are separate instruction streams for texture instructions and ALU
+// instructions.
+// In order to synchronize these streams, the program is divided into up
+// to 4 nodes. Each node begins with a number of TEX operations, followed
+// by a number of ALU operations.
+// The first node can have zero TEX ops, all subsequent nodes must have at least
+// one TEX ops.
+// All nodes must have at least one ALU op.
+//
+// The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+// 1 node, a value of 3 means 4 nodes.
+// The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+// offsets into the respective instruction streams, while *_END points to the
+// last instruction relative to this offset. */
+#define R300_PFS_CNTL_0 0x4600
+# define R300_PFS_CNTL_LAST_NODES_SHIFT 0
+# define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0)
+# define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3)
+#define R300_PFS_CNTL_1 0x4604
+/* There is an unshifted value here which has so far always been equal to the
+// index of the highest used temporary register. */
+#define R300_PFS_CNTL_2 0x4608
+# define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0
+# define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0)
+# define R300_PFS_CNTL_ALU_END_SHIFT 6
+# define R300_PFS_CNTL_ALU_END_MASK (63 << 0)
+# define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12
+# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
+# define R300_PFS_CNTL_TEX_END_SHIFT 18
+# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
+
+/* gap */
+/* Nodes are stored backwards. The last active node is always stored in
+// PFS_NODE_3.
+// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+// first node is stored in NODE_2, the second node is stored in NODE_3.
+//
+// Offsets are relative to the master offset from PFS_CNTL_2.
+// LAST_NODE is set for the last node, and only for the last node. */
+#define R300_PFS_NODE_0 0x4610
+#define R300_PFS_NODE_1 0x4614
+#define R300_PFS_NODE_2 0x4618
+#define R300_PFS_NODE_3 0x461C
+# define R300_PFS_NODE_ALU_OFFSET_SHIFT 0
+# define R300_PFS_NODE_ALU_OFFSET_MASK (63 << 0)
+# define R300_PFS_NODE_ALU_END_SHIFT 6
+# define R300_PFS_NODE_ALU_END_MASK (63 << 6)
+# define R300_PFS_NODE_TEX_OFFSET_SHIFT 12
+# define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12)
+# define R300_PFS_NODE_TEX_END_SHIFT 17
+# define R300_PFS_NODE_TEX_END_MASK (31 << 17)
+# define R300_PFS_NODE_LAST_NODE (1 << 22)
+
+/* TEX
+// As far as I can tell, texture instructions cannot write into output
+// registers directly. A subsequent ALU instruction is always necessary,
+// even if it's just MAD o0, r0, 1, 0 */
+#define R300_PFS_TEXI_0 0x4620
+# define R300_FPITX_SRC_SHIFT 0
+# define R300_FPITX_SRC_MASK (31 << 0)
+# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */
+# define R300_FPITX_DST_SHIFT 6
+# define R300_FPITX_DST_MASK (31 << 6)
+# define R300_FPITX_IMAGE_SHIFT 11
+# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */
+/* Unsure if these are opcodes, or some kind of bitfield, but this is how
+ * they were set when I checked
+ */
+# define R300_FPITX_OPCODE_SHIFT 15
+# define R300_FPITX_OP_TEX 1
+# define R300_FPITX_OP_TXP 3
+# define R300_FPITX_OP_TXB 4
+
+/* ALU
+// The ALU instructions register blocks are enumerated according to the order
+// in which fglrx. I assume there is space for 64 instructions, since
+// each block has space for a maximum of 64 DWORDs, and this matches reported
+// native limits.
+//
+// The basic functional block seems to be one MAD for each color and alpha,
+// and an adder that adds all components after the MUL.
+// - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+// - DP4: Use OUTC_DP4, OUTA_DP4
+// - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+// - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+// - CMP: If ARG2 < 0, return ARG1, else return ARG0
+// - FLR: use FRC+MAD
+// - XPD: use MAD+MAD
+// - SGE, SLT: use MAD+CMP
+// - RSQ: use ABS modifier for argument
+// - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP)
+// into color register
+// - apparently, there's no quick DST operation
+// - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+// - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+// - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+//
+// Operand selection
+// First stage selects three sources from the available registers and
+// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+// fglrx sorts the three source fields: Registers before constants,
+// lower indices before higher indices; I do not know whether this is necessary.
+// fglrx fills unused sources with "read constant 0"
+// According to specs, you cannot select more than two different constants.
+//
+// Second stage selects the operands from the sources. This is defined in
+// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+// zero and one.
+// Swizzling and negation happens in this stage, as well.
+//
+// Important: Color and alpha seem to be mostly separate, i.e. their sources
+// selection appears to be fully independent (the register storage is probably
+// physically split into a color and an alpha section).
+// However (because of the apparent physical split), there is some interaction
+// WRT swizzling. If, for example, you want to load an R component into an
+// Alpha operand, this R component is taken from a *color* source, not from
+// an alpha source. The corresponding register doesn't even have to appear in
+// the alpha sources list. (I hope this alll makes sense to you)
+//
+// Destination selection
+// The destination register index is in FPI1 (color) and FPI3 (alpha) together
+// with enable bits.
+// There are separate enable bits for writing into temporary registers
+// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT).
+// You can write to both at once, or not write at all (the same index
+// must be used for both).
+//
+// Note: There is a special form for LRP
+// - Argument order is the same as in ARB_fragment_program.
+// - Operation is MAD
+// - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+// - Set FPI0/FPI2_SPECIAL_LRP
+// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */
+#define R300_PFS_INSTR1_0 0x46C0
+# define R300_FPI1_SRC0C_SHIFT 0
+# define R300_FPI1_SRC0C_MASK (31 << 0)
+# define R300_FPI1_SRC0C_CONST (1 << 5)
+# define R300_FPI1_SRC1C_SHIFT 6
+# define R300_FPI1_SRC1C_MASK (31 << 6)
+# define R300_FPI1_SRC1C_CONST (1 << 11)
+# define R300_FPI1_SRC2C_SHIFT 12
+# define R300_FPI1_SRC2C_MASK (31 << 12)
+# define R300_FPI1_SRC2C_CONST (1 << 17)
+# define R300_FPI1_DSTC_SHIFT 18
+# define R300_FPI1_DSTC_MASK (31 << 18)
+# define R300_FPI1_DSTC_REG_X (1 << 23)
+# define R300_FPI1_DSTC_REG_Y (1 << 24)
+# define R300_FPI1_DSTC_REG_Z (1 << 25)
+# define R300_FPI1_DSTC_OUTPUT_X (1 << 26)
+# define R300_FPI1_DSTC_OUTPUT_Y (1 << 27)
+# define R300_FPI1_DSTC_OUTPUT_Z (1 << 28)
+
+#define R300_PFS_INSTR3_0 0x47C0
+# define R300_FPI3_SRC0A_SHIFT 0
+# define R300_FPI3_SRC0A_MASK (31 << 0)
+# define R300_FPI3_SRC0A_CONST (1 << 5)
+# define R300_FPI3_SRC1A_SHIFT 6
+# define R300_FPI3_SRC1A_MASK (31 << 6)
+# define R300_FPI3_SRC1A_CONST (1 << 11)
+# define R300_FPI3_SRC2A_SHIFT 12
+# define R300_FPI3_SRC2A_MASK (31 << 12)
+# define R300_FPI3_SRC2A_CONST (1 << 17)
+# define R300_FPI3_DSTA_SHIFT 18
+# define R300_FPI3_DSTA_MASK (31 << 18)
+# define R300_FPI3_DSTA_REG (1 << 23)
+# define R300_FPI3_DSTA_OUTPUT (1 << 24)
+
+#define R300_PFS_INSTR0_0 0x48C0
+# define R300_FPI0_ARGC_SRC0C_XYZ 0
+# define R300_FPI0_ARGC_SRC0C_XXX 1
+# define R300_FPI0_ARGC_SRC0C_YYY 2
+# define R300_FPI0_ARGC_SRC0C_ZZZ 3
+# define R300_FPI0_ARGC_SRC1C_XYZ 4
+# define R300_FPI0_ARGC_SRC1C_XXX 5
+# define R300_FPI0_ARGC_SRC1C_YYY 6
+# define R300_FPI0_ARGC_SRC1C_ZZZ 7
+# define R300_FPI0_ARGC_SRC2C_XYZ 8
+# define R300_FPI0_ARGC_SRC2C_XXX 9
+# define R300_FPI0_ARGC_SRC2C_YYY 10
+# define R300_FPI0_ARGC_SRC2C_ZZZ 11
+# define R300_FPI0_ARGC_SRC0A 12
+# define R300_FPI0_ARGC_SRC1A 13
+# define R300_FPI0_ARGC_SRC2A 14
+# define R300_FPI0_ARGC_SRC1C_LRP 15
+# define R300_FPI0_ARGC_ZERO 20
+# define R300_FPI0_ARGC_ONE 21
+# define R300_FPI0_ARGC_HALF 22 /* GUESS */
+# define R300_FPI0_ARGC_SRC0C_YZX 23
+# define R300_FPI0_ARGC_SRC1C_YZX 24
+# define R300_FPI0_ARGC_SRC2C_YZX 25
+# define R300_FPI0_ARGC_SRC0C_ZXY 26
+# define R300_FPI0_ARGC_SRC1C_ZXY 27
+# define R300_FPI0_ARGC_SRC2C_ZXY 28
+# define R300_FPI0_ARGC_SRC0CA_WZY 29
+# define R300_FPI0_ARGC_SRC1CA_WZY 30
+# define R300_FPI0_ARGC_SRC2CA_WZY 31
+
+# define R300_FPI0_ARG0C_SHIFT 0
+# define R300_FPI0_ARG0C_MASK (31 << 0)
+# define R300_FPI0_ARG0C_NEG (1 << 5)
+# define R300_FPI0_ARG0C_ABS (1 << 6)
+# define R300_FPI0_ARG1C_SHIFT 7
+# define R300_FPI0_ARG1C_MASK (31 << 7)
+# define R300_FPI0_ARG1C_NEG (1 << 12)
+# define R300_FPI0_ARG1C_ABS (1 << 13)
+# define R300_FPI0_ARG2C_SHIFT 14
+# define R300_FPI0_ARG2C_MASK (31 << 14)
+# define R300_FPI0_ARG2C_NEG (1 << 19)
+# define R300_FPI0_ARG2C_ABS (1 << 20)
+# define R300_FPI0_SPECIAL_LRP (1 << 21)
+# define R300_FPI0_OUTC_MAD (0 << 23)
+# define R300_FPI0_OUTC_DP3 (1 << 23)
+# define R300_FPI0_OUTC_DP4 (2 << 23)
+# define R300_FPI0_OUTC_MIN (4 << 23)
+# define R300_FPI0_OUTC_MAX (5 << 23)
+# define R300_FPI0_OUTC_CMP (8 << 23)
+# define R300_FPI0_OUTC_FRC (9 << 23)
+# define R300_FPI0_OUTC_REPL_ALPHA (10 << 23)
+# define R300_FPI0_OUTC_SAT (1 << 30)
+# define R300_FPI0_UNKNOWN_31 (1 << 31)
+
+#define R300_PFS_INSTR2_0 0x49C0
+# define R300_FPI2_ARGA_SRC0C_X 0
+# define R300_FPI2_ARGA_SRC0C_Y 1
+# define R300_FPI2_ARGA_SRC0C_Z 2
+# define R300_FPI2_ARGA_SRC1C_X 3
+# define R300_FPI2_ARGA_SRC1C_Y 4
+# define R300_FPI2_ARGA_SRC1C_Z 5
+# define R300_FPI2_ARGA_SRC2C_X 6
+# define R300_FPI2_ARGA_SRC2C_Y 7
+# define R300_FPI2_ARGA_SRC2C_Z 8
+# define R300_FPI2_ARGA_SRC0A 9
+# define R300_FPI2_ARGA_SRC1A 10
+# define R300_FPI2_ARGA_SRC2A 11
+# define R300_FPI2_ARGA_SRC1A_LRP 15
+# define R300_FPI2_ARGA_ZERO 16
+# define R300_FPI2_ARGA_ONE 17
+# define R300_FPI2_ARGA_HALF 18 /* GUESS */
+
+# define R300_FPI2_ARG0A_SHIFT 0
+# define R300_FPI2_ARG0A_MASK (31 << 0)
+# define R300_FPI2_ARG0A_NEG (1 << 5)
+# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */
+# define R300_FPI2_ARG1A_SHIFT 7
+# define R300_FPI2_ARG1A_MASK (31 << 7)
+# define R300_FPI2_ARG1A_NEG (1 << 12)
+# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */
+# define R300_FPI2_ARG2A_SHIFT 14
+# define R300_FPI2_ARG2A_MASK (31 << 14)
+# define R300_FPI2_ARG2A_NEG (1 << 19)
+# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */
+# define R300_FPI2_SPECIAL_LRP (1 << 21)
+# define R300_FPI2_OUTA_MAD (0 << 23)
+# define R300_FPI2_OUTA_DP4 (1 << 23)
+# define R300_FPI2_OUTA_MIN (2 << 23)
+# define R300_FPI2_OUTA_MAX (3 << 23)
+# define R300_FPI2_OUTA_CMP (6 << 23)
+# define R300_FPI2_OUTA_FRC (7 << 23)
+# define R300_FPI2_OUTA_EX2 (8 << 23)
+# define R300_FPI2_OUTA_LG2 (9 << 23)
+# define R300_FPI2_OUTA_RCP (10 << 23)
+# define R300_FPI2_OUTA_RSQ (11 << 23)
+# define R300_FPI2_OUTA_SAT (1 << 30)
+# define R300_FPI2_UNKNOWN_31 (1 << 31)
+/* END */
+
+/* gap */
+#define R300_PP_ALPHA_TEST 0x4BD4
+# define R300_REF_ALPHA_MASK 0x000000ff
+# define R300_ALPHA_TEST_FAIL (0 << 8)
+# define R300_ALPHA_TEST_LESS (1 << 8)
+# define R300_ALPHA_TEST_LEQUAL (3 << 8)
+# define R300_ALPHA_TEST_EQUAL (2 << 8)
+# define R300_ALPHA_TEST_GEQUAL (6 << 8)
+# define R300_ALPHA_TEST_GREATER (4 << 8)
+# define R300_ALPHA_TEST_NEQUAL (5 << 8)
+# define R300_ALPHA_TEST_PASS (7 << 8)
+# define R300_ALPHA_TEST_OP_MASK (7 << 8)
+# define R300_ALPHA_TEST_ENABLE (1 << 11)
+
+/* gap */
+/* Fragment program parameters in 7.16 floating point */
+#define R300_PFS_PARAM_0_X 0x4C00
+#define R300_PFS_PARAM_0_Y 0x4C04
+#define R300_PFS_PARAM_0_Z 0x4C08
+#define R300_PFS_PARAM_0_W 0x4C0C
+/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */
+#define R300_PFS_PARAM_31_X 0x4DF0
+#define R300_PFS_PARAM_31_Y 0x4DF4
+#define R300_PFS_PARAM_31_Z 0x4DF8
+#define R300_PFS_PARAM_31_W 0x4DFC
+
+/* Notes:
+// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application
+// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same
+// function (both registers are always set up completely in any case)
+// - Most blend flags are simply copied from R200 and not tested yet */
+#define R300_RB3D_CBLEND 0x4E04
+#define R300_RB3D_ABLEND 0x4E08
+ /* the following only appear in CBLEND */
+# define R300_BLEND_ENABLE (1 << 0)
+# define R300_BLEND_UNKNOWN (3 << 1)
+# define R300_BLEND_NO_SEPARATE (1 << 3)
+ /* the following are shared between CBLEND and ABLEND */
+# define R300_FCN_MASK (3 << 12)
+# define R300_COMB_FCN_ADD_CLAMP (0 << 12)
+# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12)
+# define R300_COMB_FCN_SUB_CLAMP (2 << 12)
+# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12)
+# define R300_SRC_BLEND_GL_ZERO (32 << 16)
+# define R300_SRC_BLEND_GL_ONE (33 << 16)
+# define R300_SRC_BLEND_GL_SRC_COLOR (34 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
+# define R300_SRC_BLEND_GL_DST_COLOR (36 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
+# define R300_SRC_BLEND_GL_SRC_ALPHA (38 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
+# define R300_SRC_BLEND_GL_DST_ALPHA (40 << 16)
+# define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
+# define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16)
+# define R300_SRC_BLEND_MASK (63 << 16)
+# define R300_DST_BLEND_GL_ZERO (32 << 24)
+# define R300_DST_BLEND_GL_ONE (33 << 24)
+# define R300_DST_BLEND_GL_SRC_COLOR (34 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
+# define R300_DST_BLEND_GL_DST_COLOR (36 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
+# define R300_DST_BLEND_GL_SRC_ALPHA (38 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
+# define R300_DST_BLEND_GL_DST_ALPHA (40 << 24)
+# define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
+# define R300_DST_BLEND_MASK (63 << 24)
+#define R300_RB3D_COLORMASK 0x4E0C
+# define R300_COLORMASK0_B (1<<0)
+# define R300_COLORMASK0_G (1<<1)
+# define R300_COLORMASK0_R (1<<2)
+# define R300_COLORMASK0_A (1<<3)
+
+/* gap */
+#define R300_RB3D_COLOROFFSET0 0x4E28
+# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
+#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
+#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
+#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
+/* gap */
+/* Bit 16: Larger tiles
+// Bit 17: 4x2 tiles
+// Bit 18: Extremely weird tile like, but some pixels duplicated? */
+#define R300_RB3D_COLORPITCH0 0x4E38
+# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+# define R300_COLOR_FORMAT_RGB565 (2 << 22)
+# define R300_COLOR_FORMAT_ARGB8888 (3 << 22)
+#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
+#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
+#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
+
+/* gap */
+/* Guess by Vladimir.
+// Set to 0A before 3D operations, set to 02 afterwards. */
+#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C
+# define R300_RB3D_DSTCACHE_02 0x00000002
+# define R300_RB3D_DSTCACHE_0A 0x0000000A
+
+/* gap */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */
+/* Bit (1<<8) is the "test" bit. so plain write is 6 - vd */
+#define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00
+# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */
+# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */
+# define R300_RB3D_Z_TEST 0x00000012
+# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
+# define R300_RB3D_Z_WRITE_ONLY 0x00000006
+
+# define R300_RB3D_Z_TEST 0x00000012
+# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
+# define R300_RB3D_Z_WRITE_ONLY 0x00000006
+# define R300_RB3D_STENCIL_ENABLE 0x00000001
+
+#define R300_RB3D_ZSTENCIL_CNTL_1 0x4F04
+ /* functions */
+# define R300_ZS_NEVER 0
+# define R300_ZS_LESS 1
+# define R300_ZS_LEQUAL 2
+# define R300_ZS_EQUAL 3
+# define R300_ZS_GEQUAL 4
+# define R300_ZS_GREATER 5
+# define R300_ZS_NOTEQUAL 6
+# define R300_ZS_ALWAYS 7
+# define R300_ZS_MASK 7
+ /* operations */
+# define R300_ZS_KEEP 0
+# define R300_ZS_ZERO 1
+# define R300_ZS_REPLACE 2
+# define R300_ZS_INCR 3
+# define R300_ZS_DECR 4
+# define R300_ZS_INVERT 5
+# define R300_ZS_INCR_WRAP 6
+# define R300_ZS_DECR_WRAP 7
+
+ /* front and back refer to operations done for front
+ and back faces, i.e. separate stencil function support */
+# define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT 0
+# define R300_RB3D_ZS1_FRONT_FUNC_SHIFT 3
+# define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT 6
+# define R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT 9
+# define R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT 12
+# define R300_RB3D_ZS1_BACK_FUNC_SHIFT 15
+# define R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT 18
+# define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT 21
+# define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT 24
+
+#define R300_RB3D_ZSTENCIL_CNTL_2 0x4F08
+# define R300_RB3D_ZS2_STENCIL_REF_SHIFT 0
+# define R300_RB3D_ZS2_STENCIL_MASK 0xFF
+# define R300_RB3D_ZS2_STENCIL_MASK_SHIFT 8
+# define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT 16
+
+/* gap */
+
+#define R300_RB3D_ZSTENCIL_FORMAT 0x4F10
+# define R300_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+# define R300_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+
+/* gap */
+#define R300_RB3D_DEPTHOFFSET 0x4F20
+#define R300_RB3D_DEPTHPITCH 0x4F24
+# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+
+/* BEGIN: Vertex program instruction set
+// Every instruction is four dwords long:
+// DWORD 0: output and opcode
+// DWORD 1: first argument
+// DWORD 2: second argument
+// DWORD 3: third argument
+//
+// Notes:
+// - ABS r, a is implemented as MAX r, a, -a
+// - MOV is implemented as ADD to zero
+// - XPD is implemented as MUL + MAD
+// - FLR is implemented as FRC + ADD
+// - apparently, fglrx tries to schedule instructions so that there is at least
+// one instruction between the write to a temporary and the first read
+// from said temporary; however, violations of this scheduling are allowed
+// - register indices seem to be unrelated with OpenGL aliasing to conventional state
+// - only one attribute and one parameter can be loaded at a time; however, the
+// same attribute/parameter can be used for more than one argument
+// - the second software argument for POW is the third hardware argument (no idea why)
+// - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+//
+// There is some magic surrounding LIT:
+// The single argument is replicated across all three inputs, but swizzled:
+// First argument: xyzy
+// Second argument: xyzx
+// Third argument: xyzw
+// Whenever the result is used later in the fragment program, fglrx forces x and w
+// to be 1.0 in the input selection; I don't know whether this is strictly necessary */
+#define R300_VPI_OUT_OP_DOT (1 << 0)
+#define R300_VPI_OUT_OP_MUL (2 << 0)
+#define R300_VPI_OUT_OP_ADD (3 << 0)
+#define R300_VPI_OUT_OP_MAD (4 << 0)
+#define R300_VPI_OUT_OP_DST (5 << 0)
+#define R300_VPI_OUT_OP_FRC (6 << 0)
+#define R300_VPI_OUT_OP_MAX (7 << 0)
+#define R300_VPI_OUT_OP_MIN (8 << 0)
+#define R300_VPI_OUT_OP_SGE (9 << 0)
+#define R300_VPI_OUT_OP_SLT (10 << 0)
+#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_EXP (65 << 0)
+#define R300_VPI_OUT_OP_LOG (66 << 0)
+#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_LIT (68 << 0)
+#define R300_VPI_OUT_OP_POW (69 << 0)
+#define R300_VPI_OUT_OP_RCP (70 << 0)
+#define R300_VPI_OUT_OP_RSQ (72 << 0)
+#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_EX2 (75 << 0)
+#define R300_VPI_OUT_OP_LG2 (76 << 0)
+#define R300_VPI_OUT_OP_MAD_2 (128 << 0)
+#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */
+
+#define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8)
+#define R300_VPI_OUT_REG_CLASS_MASK (31 << 8)
+
+#define R300_VPI_OUT_REG_INDEX_SHIFT 13
+#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */
+
+#define R300_VPI_OUT_WRITE_X (1 << 20)
+#define R300_VPI_OUT_WRITE_Y (1 << 21)
+#define R300_VPI_OUT_WRITE_Z (1 << 22)
+#define R300_VPI_OUT_WRITE_W (1 << 23)
+
+#define R300_VPI_IN_REG_CLASS_TEMPORARY (0 << 0)
+#define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0)
+#define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0)
+#define R300_VPI_IN_REG_CLASS_NONE (9 << 0)
+#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */
+
+#define R300_VPI_IN_REG_INDEX_SHIFT 5
+#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */
+
+/* The R300 can select components from the input register arbitrarily.
+// Use the following constants, shifted by the component shift you
+// want to select */
+#define R300_VPI_IN_SELECT_X 0
+#define R300_VPI_IN_SELECT_Y 1
+#define R300_VPI_IN_SELECT_Z 2
+#define R300_VPI_IN_SELECT_W 3
+#define R300_VPI_IN_SELECT_ZERO 4
+#define R300_VPI_IN_SELECT_ONE 5
+#define R300_VPI_IN_SELECT_MASK 7
+
+#define R300_VPI_IN_X_SHIFT 13
+#define R300_VPI_IN_Y_SHIFT 16
+#define R300_VPI_IN_Z_SHIFT 19
+#define R300_VPI_IN_W_SHIFT 22
+
+#define R300_VPI_IN_NEG_X (1 << 25)
+#define R300_VPI_IN_NEG_Y (1 << 26)
+#define R300_VPI_IN_NEG_Z (1 << 27)
+#define R300_VPI_IN_NEG_W (1 << 28)
+/* END */
+
+//BEGIN: Packet 3 commands
+
+// A primitive emission dword.
+#define R300_PRIM_TYPE_NONE (0 << 0)
+#define R300_PRIM_TYPE_POINT (1 << 0)
+#define R300_PRIM_TYPE_LINE (2 << 0)
+#define R300_PRIM_TYPE_LINE_STRIP (3 << 0)
+#define R300_PRIM_TYPE_TRI_LIST (4 << 0)
+#define R300_PRIM_TYPE_TRI_FAN (5 << 0)
+#define R300_PRIM_TYPE_TRI_STRIP (6 << 0)
+#define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0)
+#define R300_PRIM_TYPE_RECT_LIST (8 << 0)
+#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200)
+#define R300_PRIM_TYPE_LINE_LOOP (12 << 0)
+#define R300_PRIM_TYPE_QUADS (13 << 0)
+#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0)
+#define R300_PRIM_TYPE_POLYGON (15 << 0)
+#define R300_PRIM_TYPE_MASK 0xF
+#define R300_PRIM_WALK_IND (1 << 4)
+#define R300_PRIM_WALK_LIST (2 << 4)
+#define R300_PRIM_WALK_RING (3 << 4)
+#define R300_PRIM_WALK_MASK (3 << 4)
+#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200)
+#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS
+#define R300_PRIM_NUM_VERTICES_SHIFT 16
+
+// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+// Two parameter dwords:
+// 0. The first parameter appears to be always 0
+// 1. The second parameter is a standard primitive emission dword.
+#define R300_PACKET3_3D_DRAW_VBUF 0x00002800
+
+// Specify the full set of vertex arrays as (address, stride).
+// The first parameter is the number of vertex arrays specified.
+// The rest of the command is a variable length list of blocks, where
+// each block is three dwords long and specifies two arrays.
+// The first dword of a block is split into two words, the lower significant
+// word refers to the first array, the more significant word to the second
+// array in the block.
+// The low byte of each word contains the size of an array entry in dwords,
+// the high byte contains the stride of the array.
+// The second dword of a block contains the pointer to the first array,
+// the third dword of a block contains the pointer to the second array.
+// Note that if the total number of arrays is odd, the third dword of
+// the last block is omitted.
+#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00
+
+#define R300_PACKET3_INDX_BUFFER 0x00003300
+# define R300_EB_UNK1_SHIFT 24
+# define R300_EB_UNK1 (0x80<<24)
+# define R300_EB_UNK2 0x0810
+#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600
+
+//END
+
+#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 20bcf872b348..03839ea31092 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -32,791 +32,791 @@
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
+#include "r300_reg.h"
#define RADEON_FIFO_DEBUG 0
-static int radeon_do_cleanup_cp( drm_device_t *dev );
+static int radeon_do_cleanup_cp(drm_device_t * dev);
/* CP microcode (from ATI) */
static u32 R200_cp_microcode[][2] = {
- { 0x21007000, 0000000000 },
- { 0x20007000, 0000000000 },
- { 0x000000ab, 0x00000004 },
- { 0x000000af, 0x00000004 },
- { 0x66544a49, 0000000000 },
- { 0x49494174, 0000000000 },
- { 0x54517d83, 0000000000 },
- { 0x498d8b64, 0000000000 },
- { 0x49494949, 0000000000 },
- { 0x49da493c, 0000000000 },
- { 0x49989898, 0000000000 },
- { 0xd34949d5, 0000000000 },
- { 0x9dc90e11, 0000000000 },
- { 0xce9b9b9b, 0000000000 },
- { 0x000f0000, 0x00000016 },
- { 0x352e232c, 0000000000 },
- { 0x00000013, 0x00000004 },
- { 0x000f0000, 0x00000016 },
- { 0x352e272c, 0000000000 },
- { 0x000f0001, 0x00000016 },
- { 0x3239362f, 0000000000 },
- { 0x000077ef, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x00000020, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00061000, 0x00000002 },
- { 0x00000020, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00061000, 0x00000002 },
- { 0x00000020, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00000016, 0x00000004 },
- { 0x0003802a, 0x00000002 },
- { 0x040067e0, 0x00000002 },
- { 0x00000016, 0x00000004 },
- { 0x000077e0, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x000037e1, 0x00000002 },
- { 0x040067e1, 0x00000006 },
- { 0x000077e0, 0x00000002 },
- { 0x000077e1, 0x00000002 },
- { 0x000077e1, 0x00000006 },
- { 0xffffffff, 0000000000 },
- { 0x10000000, 0000000000 },
- { 0x0003802a, 0x00000002 },
- { 0x040067e0, 0x00000006 },
- { 0x00007675, 0x00000002 },
- { 0x00007676, 0x00000002 },
- { 0x00007677, 0x00000002 },
- { 0x00007678, 0x00000006 },
- { 0x0003802b, 0x00000002 },
- { 0x04002676, 0x00000002 },
- { 0x00007677, 0x00000002 },
- { 0x00007678, 0x00000006 },
- { 0x0000002e, 0x00000018 },
- { 0x0000002e, 0x00000018 },
- { 0000000000, 0x00000006 },
- { 0x0000002f, 0x00000018 },
- { 0x0000002f, 0x00000018 },
- { 0000000000, 0x00000006 },
- { 0x01605000, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x00098000, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x64c0603d, 0x00000004 },
- { 0x00080000, 0x00000016 },
- { 0000000000, 0000000000 },
- { 0x0400251d, 0x00000002 },
- { 0x00007580, 0x00000002 },
- { 0x00067581, 0x00000002 },
- { 0x04002580, 0x00000002 },
- { 0x00067581, 0x00000002 },
- { 0x00000046, 0x00000004 },
- { 0x00005000, 0000000000 },
- { 0x00061000, 0x00000002 },
- { 0x0000750e, 0x00000002 },
- { 0x00019000, 0x00000002 },
- { 0x00011055, 0x00000014 },
- { 0x00000055, 0x00000012 },
- { 0x0400250f, 0x00000002 },
- { 0x0000504a, 0x00000004 },
- { 0x00007565, 0x00000002 },
- { 0x00007566, 0x00000002 },
- { 0x00000051, 0x00000004 },
- { 0x01e655b4, 0x00000002 },
- { 0x4401b0dc, 0x00000002 },
- { 0x01c110dc, 0x00000002 },
- { 0x2666705d, 0x00000018 },
- { 0x040c2565, 0x00000002 },
- { 0x0000005d, 0x00000018 },
- { 0x04002564, 0x00000002 },
- { 0x00007566, 0x00000002 },
- { 0x00000054, 0x00000004 },
- { 0x00401060, 0x00000008 },
- { 0x00101000, 0x00000002 },
- { 0x000d80ff, 0x00000002 },
- { 0x00800063, 0x00000008 },
- { 0x000f9000, 0x00000002 },
- { 0x000e00ff, 0x00000002 },
- { 0000000000, 0x00000006 },
- { 0x00000080, 0x00000018 },
- { 0x00000054, 0x00000004 },
- { 0x00007576, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x00009000, 0x00000002 },
- { 0x00041000, 0x00000002 },
- { 0x0c00350e, 0x00000002 },
- { 0x00049000, 0x00000002 },
- { 0x00051000, 0x00000002 },
- { 0x01e785f8, 0x00000002 },
- { 0x00200000, 0x00000002 },
- { 0x00600073, 0x0000000c },
- { 0x00007563, 0x00000002 },
- { 0x006075f0, 0x00000021 },
- { 0x20007068, 0x00000004 },
- { 0x00005068, 0x00000004 },
- { 0x00007576, 0x00000002 },
- { 0x00007577, 0x00000002 },
- { 0x0000750e, 0x00000002 },
- { 0x0000750f, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00600076, 0x0000000c },
- { 0x006075f0, 0x00000021 },
- { 0x000075f8, 0x00000002 },
- { 0x00000076, 0x00000004 },
- { 0x000a750e, 0x00000002 },
- { 0x0020750f, 0x00000002 },
- { 0x00600079, 0x00000004 },
- { 0x00007570, 0x00000002 },
- { 0x00007571, 0x00000002 },
- { 0x00007572, 0x00000006 },
- { 0x00005000, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00007568, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x00000084, 0x0000000c },
- { 0x00058000, 0x00000002 },
- { 0x0c607562, 0x00000002 },
- { 0x00000086, 0x00000004 },
- { 0x00600085, 0x00000004 },
- { 0x400070dd, 0000000000 },
- { 0x000380dd, 0x00000002 },
- { 0x00000093, 0x0000001c },
- { 0x00065095, 0x00000018 },
- { 0x040025bb, 0x00000002 },
- { 0x00061096, 0x00000018 },
- { 0x040075bc, 0000000000 },
- { 0x000075bb, 0x00000002 },
- { 0x000075bc, 0000000000 },
- { 0x00090000, 0x00000006 },
- { 0x00090000, 0x00000002 },
- { 0x000d8002, 0x00000006 },
- { 0x00005000, 0x00000002 },
- { 0x00007821, 0x00000002 },
- { 0x00007800, 0000000000 },
- { 0x00007821, 0x00000002 },
- { 0x00007800, 0000000000 },
- { 0x01665000, 0x00000002 },
- { 0x000a0000, 0x00000002 },
- { 0x000671cc, 0x00000002 },
- { 0x0286f1cd, 0x00000002 },
- { 0x000000a3, 0x00000010 },
- { 0x21007000, 0000000000 },
- { 0x000000aa, 0x0000001c },
- { 0x00065000, 0x00000002 },
- { 0x000a0000, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x000b0000, 0x00000002 },
- { 0x38067000, 0x00000002 },
- { 0x000a00a6, 0x00000004 },
- { 0x20007000, 0000000000 },
- { 0x01200000, 0x00000002 },
- { 0x20077000, 0x00000002 },
- { 0x01200000, 0x00000002 },
- { 0x20007000, 0000000000 },
- { 0x00061000, 0x00000002 },
- { 0x0120751b, 0x00000002 },
- { 0x8040750a, 0x00000002 },
- { 0x8040750b, 0x00000002 },
- { 0x00110000, 0x00000002 },
- { 0x000380dd, 0x00000002 },
- { 0x000000bd, 0x0000001c },
- { 0x00061096, 0x00000018 },
- { 0x844075bd, 0x00000002 },
- { 0x00061095, 0x00000018 },
- { 0x840075bb, 0x00000002 },
- { 0x00061096, 0x00000018 },
- { 0x844075bc, 0x00000002 },
- { 0x000000c0, 0x00000004 },
- { 0x804075bd, 0x00000002 },
- { 0x800075bb, 0x00000002 },
- { 0x804075bc, 0x00000002 },
- { 0x00108000, 0x00000002 },
- { 0x01400000, 0x00000002 },
- { 0x006000c4, 0x0000000c },
- { 0x20c07000, 0x00000020 },
- { 0x000000c6, 0x00000012 },
- { 0x00800000, 0x00000006 },
- { 0x0080751d, 0x00000006 },
- { 0x000025bb, 0x00000002 },
- { 0x000040c0, 0x00000004 },
- { 0x0000775c, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00661000, 0x00000002 },
- { 0x0460275d, 0x00000020 },
- { 0x00004000, 0000000000 },
- { 0x00007999, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00661000, 0x00000002 },
- { 0x0460299b, 0x00000020 },
- { 0x00004000, 0000000000 },
- { 0x01e00830, 0x00000002 },
- { 0x21007000, 0000000000 },
- { 0x00005000, 0x00000002 },
- { 0x00038042, 0x00000002 },
- { 0x040025e0, 0x00000002 },
- { 0x000075e1, 0000000000 },
- { 0x00000001, 0000000000 },
- { 0x000380d9, 0x00000002 },
- { 0x04007394, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
+ {0x21007000, 0000000000},
+ {0x20007000, 0000000000},
+ {0x000000ab, 0x00000004},
+ {0x000000af, 0x00000004},
+ {0x66544a49, 0000000000},
+ {0x49494174, 0000000000},
+ {0x54517d83, 0000000000},
+ {0x498d8b64, 0000000000},
+ {0x49494949, 0000000000},
+ {0x49da493c, 0000000000},
+ {0x49989898, 0000000000},
+ {0xd34949d5, 0000000000},
+ {0x9dc90e11, 0000000000},
+ {0xce9b9b9b, 0000000000},
+ {0x000f0000, 0x00000016},
+ {0x352e232c, 0000000000},
+ {0x00000013, 0x00000004},
+ {0x000f0000, 0x00000016},
+ {0x352e272c, 0000000000},
+ {0x000f0001, 0x00000016},
+ {0x3239362f, 0000000000},
+ {0x000077ef, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x00000020, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00061000, 0x00000002},
+ {0x00000020, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00061000, 0x00000002},
+ {0x00000020, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00000016, 0x00000004},
+ {0x0003802a, 0x00000002},
+ {0x040067e0, 0x00000002},
+ {0x00000016, 0x00000004},
+ {0x000077e0, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x000037e1, 0x00000002},
+ {0x040067e1, 0x00000006},
+ {0x000077e0, 0x00000002},
+ {0x000077e1, 0x00000002},
+ {0x000077e1, 0x00000006},
+ {0xffffffff, 0000000000},
+ {0x10000000, 0000000000},
+ {0x0003802a, 0x00000002},
+ {0x040067e0, 0x00000006},
+ {0x00007675, 0x00000002},
+ {0x00007676, 0x00000002},
+ {0x00007677, 0x00000002},
+ {0x00007678, 0x00000006},
+ {0x0003802b, 0x00000002},
+ {0x04002676, 0x00000002},
+ {0x00007677, 0x00000002},
+ {0x00007678, 0x00000006},
+ {0x0000002e, 0x00000018},
+ {0x0000002e, 0x00000018},
+ {0000000000, 0x00000006},
+ {0x0000002f, 0x00000018},
+ {0x0000002f, 0x00000018},
+ {0000000000, 0x00000006},
+ {0x01605000, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x00098000, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x64c0603d, 0x00000004},
+ {0x00080000, 0x00000016},
+ {0000000000, 0000000000},
+ {0x0400251d, 0x00000002},
+ {0x00007580, 0x00000002},
+ {0x00067581, 0x00000002},
+ {0x04002580, 0x00000002},
+ {0x00067581, 0x00000002},
+ {0x00000046, 0x00000004},
+ {0x00005000, 0000000000},
+ {0x00061000, 0x00000002},
+ {0x0000750e, 0x00000002},
+ {0x00019000, 0x00000002},
+ {0x00011055, 0x00000014},
+ {0x00000055, 0x00000012},
+ {0x0400250f, 0x00000002},
+ {0x0000504a, 0x00000004},
+ {0x00007565, 0x00000002},
+ {0x00007566, 0x00000002},
+ {0x00000051, 0x00000004},
+ {0x01e655b4, 0x00000002},
+ {0x4401b0dc, 0x00000002},
+ {0x01c110dc, 0x00000002},
+ {0x2666705d, 0x00000018},
+ {0x040c2565, 0x00000002},
+ {0x0000005d, 0x00000018},
+ {0x04002564, 0x00000002},
+ {0x00007566, 0x00000002},
+ {0x00000054, 0x00000004},
+ {0x00401060, 0x00000008},
+ {0x00101000, 0x00000002},
+ {0x000d80ff, 0x00000002},
+ {0x00800063, 0x00000008},
+ {0x000f9000, 0x00000002},
+ {0x000e00ff, 0x00000002},
+ {0000000000, 0x00000006},
+ {0x00000080, 0x00000018},
+ {0x00000054, 0x00000004},
+ {0x00007576, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x00009000, 0x00000002},
+ {0x00041000, 0x00000002},
+ {0x0c00350e, 0x00000002},
+ {0x00049000, 0x00000002},
+ {0x00051000, 0x00000002},
+ {0x01e785f8, 0x00000002},
+ {0x00200000, 0x00000002},
+ {0x00600073, 0x0000000c},
+ {0x00007563, 0x00000002},
+ {0x006075f0, 0x00000021},
+ {0x20007068, 0x00000004},
+ {0x00005068, 0x00000004},
+ {0x00007576, 0x00000002},
+ {0x00007577, 0x00000002},
+ {0x0000750e, 0x00000002},
+ {0x0000750f, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00600076, 0x0000000c},
+ {0x006075f0, 0x00000021},
+ {0x000075f8, 0x00000002},
+ {0x00000076, 0x00000004},
+ {0x000a750e, 0x00000002},
+ {0x0020750f, 0x00000002},
+ {0x00600079, 0x00000004},
+ {0x00007570, 0x00000002},
+ {0x00007571, 0x00000002},
+ {0x00007572, 0x00000006},
+ {0x00005000, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00007568, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x00000084, 0x0000000c},
+ {0x00058000, 0x00000002},
+ {0x0c607562, 0x00000002},
+ {0x00000086, 0x00000004},
+ {0x00600085, 0x00000004},
+ {0x400070dd, 0000000000},
+ {0x000380dd, 0x00000002},
+ {0x00000093, 0x0000001c},
+ {0x00065095, 0x00000018},
+ {0x040025bb, 0x00000002},
+ {0x00061096, 0x00000018},
+ {0x040075bc, 0000000000},
+ {0x000075bb, 0x00000002},
+ {0x000075bc, 0000000000},
+ {0x00090000, 0x00000006},
+ {0x00090000, 0x00000002},
+ {0x000d8002, 0x00000006},
+ {0x00005000, 0x00000002},
+ {0x00007821, 0x00000002},
+ {0x00007800, 0000000000},
+ {0x00007821, 0x00000002},
+ {0x00007800, 0000000000},
+ {0x01665000, 0x00000002},
+ {0x000a0000, 0x00000002},
+ {0x000671cc, 0x00000002},
+ {0x0286f1cd, 0x00000002},
+ {0x000000a3, 0x00000010},
+ {0x21007000, 0000000000},
+ {0x000000aa, 0x0000001c},
+ {0x00065000, 0x00000002},
+ {0x000a0000, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x000b0000, 0x00000002},
+ {0x38067000, 0x00000002},
+ {0x000a00a6, 0x00000004},
+ {0x20007000, 0000000000},
+ {0x01200000, 0x00000002},
+ {0x20077000, 0x00000002},
+ {0x01200000, 0x00000002},
+ {0x20007000, 0000000000},
+ {0x00061000, 0x00000002},
+ {0x0120751b, 0x00000002},
+ {0x8040750a, 0x00000002},
+ {0x8040750b, 0x00000002},
+ {0x00110000, 0x00000002},
+ {0x000380dd, 0x00000002},
+ {0x000000bd, 0x0000001c},
+ {0x00061096, 0x00000018},
+ {0x844075bd, 0x00000002},
+ {0x00061095, 0x00000018},
+ {0x840075bb, 0x00000002},
+ {0x00061096, 0x00000018},
+ {0x844075bc, 0x00000002},
+ {0x000000c0, 0x00000004},
+ {0x804075bd, 0x00000002},
+ {0x800075bb, 0x00000002},
+ {0x804075bc, 0x00000002},
+ {0x00108000, 0x00000002},
+ {0x01400000, 0x00000002},
+ {0x006000c4, 0x0000000c},
+ {0x20c07000, 0x00000020},
+ {0x000000c6, 0x00000012},
+ {0x00800000, 0x00000006},
+ {0x0080751d, 0x00000006},
+ {0x000025bb, 0x00000002},
+ {0x000040c0, 0x00000004},
+ {0x0000775c, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00661000, 0x00000002},
+ {0x0460275d, 0x00000020},
+ {0x00004000, 0000000000},
+ {0x00007999, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00661000, 0x00000002},
+ {0x0460299b, 0x00000020},
+ {0x00004000, 0000000000},
+ {0x01e00830, 0x00000002},
+ {0x21007000, 0000000000},
+ {0x00005000, 0x00000002},
+ {0x00038042, 0x00000002},
+ {0x040025e0, 0x00000002},
+ {0x000075e1, 0000000000},
+ {0x00000001, 0000000000},
+ {0x000380d9, 0x00000002},
+ {0x04007394, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
};
-
static u32 radeon_cp_microcode[][2] = {
- { 0x21007000, 0000000000 },
- { 0x20007000, 0000000000 },
- { 0x000000b4, 0x00000004 },
- { 0x000000b8, 0x00000004 },
- { 0x6f5b4d4c, 0000000000 },
- { 0x4c4c427f, 0000000000 },
- { 0x5b568a92, 0000000000 },
- { 0x4ca09c6d, 0000000000 },
- { 0xad4c4c4c, 0000000000 },
- { 0x4ce1af3d, 0000000000 },
- { 0xd8afafaf, 0000000000 },
- { 0xd64c4cdc, 0000000000 },
- { 0x4cd10d10, 0000000000 },
- { 0x000f0000, 0x00000016 },
- { 0x362f242d, 0000000000 },
- { 0x00000012, 0x00000004 },
- { 0x000f0000, 0x00000016 },
- { 0x362f282d, 0000000000 },
- { 0x000380e7, 0x00000002 },
- { 0x04002c97, 0x00000002 },
- { 0x000f0001, 0x00000016 },
- { 0x333a3730, 0000000000 },
- { 0x000077ef, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x00000021, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00061000, 0x00000002 },
- { 0x00000021, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00061000, 0x00000002 },
- { 0x00000021, 0x0000001a },
- { 0x00004000, 0x0000001e },
- { 0x00000017, 0x00000004 },
- { 0x0003802b, 0x00000002 },
- { 0x040067e0, 0x00000002 },
- { 0x00000017, 0x00000004 },
- { 0x000077e0, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x000037e1, 0x00000002 },
- { 0x040067e1, 0x00000006 },
- { 0x000077e0, 0x00000002 },
- { 0x000077e1, 0x00000002 },
- { 0x000077e1, 0x00000006 },
- { 0xffffffff, 0000000000 },
- { 0x10000000, 0000000000 },
- { 0x0003802b, 0x00000002 },
- { 0x040067e0, 0x00000006 },
- { 0x00007675, 0x00000002 },
- { 0x00007676, 0x00000002 },
- { 0x00007677, 0x00000002 },
- { 0x00007678, 0x00000006 },
- { 0x0003802c, 0x00000002 },
- { 0x04002676, 0x00000002 },
- { 0x00007677, 0x00000002 },
- { 0x00007678, 0x00000006 },
- { 0x0000002f, 0x00000018 },
- { 0x0000002f, 0x00000018 },
- { 0000000000, 0x00000006 },
- { 0x00000030, 0x00000018 },
- { 0x00000030, 0x00000018 },
- { 0000000000, 0x00000006 },
- { 0x01605000, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x00098000, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x64c0603e, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00080000, 0x00000016 },
- { 0000000000, 0000000000 },
- { 0x0400251d, 0x00000002 },
- { 0x00007580, 0x00000002 },
- { 0x00067581, 0x00000002 },
- { 0x04002580, 0x00000002 },
- { 0x00067581, 0x00000002 },
- { 0x00000049, 0x00000004 },
- { 0x00005000, 0000000000 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x0000750e, 0x00000002 },
- { 0x00019000, 0x00000002 },
- { 0x00011055, 0x00000014 },
- { 0x00000055, 0x00000012 },
- { 0x0400250f, 0x00000002 },
- { 0x0000504f, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00007565, 0x00000002 },
- { 0x00007566, 0x00000002 },
- { 0x00000058, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x01e655b4, 0x00000002 },
- { 0x4401b0e4, 0x00000002 },
- { 0x01c110e4, 0x00000002 },
- { 0x26667066, 0x00000018 },
- { 0x040c2565, 0x00000002 },
- { 0x00000066, 0x00000018 },
- { 0x04002564, 0x00000002 },
- { 0x00007566, 0x00000002 },
- { 0x0000005d, 0x00000004 },
- { 0x00401069, 0x00000008 },
- { 0x00101000, 0x00000002 },
- { 0x000d80ff, 0x00000002 },
- { 0x0080006c, 0x00000008 },
- { 0x000f9000, 0x00000002 },
- { 0x000e00ff, 0x00000002 },
- { 0000000000, 0x00000006 },
- { 0x0000008f, 0x00000018 },
- { 0x0000005b, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00007576, 0x00000002 },
- { 0x00065000, 0x00000002 },
- { 0x00009000, 0x00000002 },
- { 0x00041000, 0x00000002 },
- { 0x0c00350e, 0x00000002 },
- { 0x00049000, 0x00000002 },
- { 0x00051000, 0x00000002 },
- { 0x01e785f8, 0x00000002 },
- { 0x00200000, 0x00000002 },
- { 0x0060007e, 0x0000000c },
- { 0x00007563, 0x00000002 },
- { 0x006075f0, 0x00000021 },
- { 0x20007073, 0x00000004 },
- { 0x00005073, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00007576, 0x00000002 },
- { 0x00007577, 0x00000002 },
- { 0x0000750e, 0x00000002 },
- { 0x0000750f, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00600083, 0x0000000c },
- { 0x006075f0, 0x00000021 },
- { 0x000075f8, 0x00000002 },
- { 0x00000083, 0x00000004 },
- { 0x000a750e, 0x00000002 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x0020750f, 0x00000002 },
- { 0x00600086, 0x00000004 },
- { 0x00007570, 0x00000002 },
- { 0x00007571, 0x00000002 },
- { 0x00007572, 0x00000006 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00005000, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00007568, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x00000095, 0x0000000c },
- { 0x00058000, 0x00000002 },
- { 0x0c607562, 0x00000002 },
- { 0x00000097, 0x00000004 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x00600096, 0x00000004 },
- { 0x400070e5, 0000000000 },
- { 0x000380e6, 0x00000002 },
- { 0x040025c5, 0x00000002 },
- { 0x000380e5, 0x00000002 },
- { 0x000000a8, 0x0000001c },
- { 0x000650aa, 0x00000018 },
- { 0x040025bb, 0x00000002 },
- { 0x000610ab, 0x00000018 },
- { 0x040075bc, 0000000000 },
- { 0x000075bb, 0x00000002 },
- { 0x000075bc, 0000000000 },
- { 0x00090000, 0x00000006 },
- { 0x00090000, 0x00000002 },
- { 0x000d8002, 0x00000006 },
- { 0x00007832, 0x00000002 },
- { 0x00005000, 0x00000002 },
- { 0x000380e7, 0x00000002 },
- { 0x04002c97, 0x00000002 },
- { 0x00007820, 0x00000002 },
- { 0x00007821, 0x00000002 },
- { 0x00007800, 0000000000 },
- { 0x01200000, 0x00000002 },
- { 0x20077000, 0x00000002 },
- { 0x01200000, 0x00000002 },
- { 0x20007000, 0x00000002 },
- { 0x00061000, 0x00000002 },
- { 0x0120751b, 0x00000002 },
- { 0x8040750a, 0x00000002 },
- { 0x8040750b, 0x00000002 },
- { 0x00110000, 0x00000002 },
- { 0x000380e5, 0x00000002 },
- { 0x000000c6, 0x0000001c },
- { 0x000610ab, 0x00000018 },
- { 0x844075bd, 0x00000002 },
- { 0x000610aa, 0x00000018 },
- { 0x840075bb, 0x00000002 },
- { 0x000610ab, 0x00000018 },
- { 0x844075bc, 0x00000002 },
- { 0x000000c9, 0x00000004 },
- { 0x804075bd, 0x00000002 },
- { 0x800075bb, 0x00000002 },
- { 0x804075bc, 0x00000002 },
- { 0x00108000, 0x00000002 },
- { 0x01400000, 0x00000002 },
- { 0x006000cd, 0x0000000c },
- { 0x20c07000, 0x00000020 },
- { 0x000000cf, 0x00000012 },
- { 0x00800000, 0x00000006 },
- { 0x0080751d, 0x00000006 },
- { 0000000000, 0000000000 },
- { 0x0000775c, 0x00000002 },
- { 0x00a05000, 0x00000002 },
- { 0x00661000, 0x00000002 },
- { 0x0460275d, 0x00000020 },
- { 0x00004000, 0000000000 },
- { 0x01e00830, 0x00000002 },
- { 0x21007000, 0000000000 },
- { 0x6464614d, 0000000000 },
- { 0x69687420, 0000000000 },
- { 0x00000073, 0000000000 },
- { 0000000000, 0000000000 },
- { 0x00005000, 0x00000002 },
- { 0x000380d0, 0x00000002 },
- { 0x040025e0, 0x00000002 },
- { 0x000075e1, 0000000000 },
- { 0x00000001, 0000000000 },
- { 0x000380e0, 0x00000002 },
- { 0x04002394, 0x00000002 },
- { 0x00005000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0x00000008, 0000000000 },
- { 0x00000004, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
+ {0x21007000, 0000000000},
+ {0x20007000, 0000000000},
+ {0x000000b4, 0x00000004},
+ {0x000000b8, 0x00000004},
+ {0x6f5b4d4c, 0000000000},
+ {0x4c4c427f, 0000000000},
+ {0x5b568a92, 0000000000},
+ {0x4ca09c6d, 0000000000},
+ {0xad4c4c4c, 0000000000},
+ {0x4ce1af3d, 0000000000},
+ {0xd8afafaf, 0000000000},
+ {0xd64c4cdc, 0000000000},
+ {0x4cd10d10, 0000000000},
+ {0x000f0000, 0x00000016},
+ {0x362f242d, 0000000000},
+ {0x00000012, 0x00000004},
+ {0x000f0000, 0x00000016},
+ {0x362f282d, 0000000000},
+ {0x000380e7, 0x00000002},
+ {0x04002c97, 0x00000002},
+ {0x000f0001, 0x00000016},
+ {0x333a3730, 0000000000},
+ {0x000077ef, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x00000021, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00061000, 0x00000002},
+ {0x00000021, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00061000, 0x00000002},
+ {0x00000021, 0x0000001a},
+ {0x00004000, 0x0000001e},
+ {0x00000017, 0x00000004},
+ {0x0003802b, 0x00000002},
+ {0x040067e0, 0x00000002},
+ {0x00000017, 0x00000004},
+ {0x000077e0, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x000037e1, 0x00000002},
+ {0x040067e1, 0x00000006},
+ {0x000077e0, 0x00000002},
+ {0x000077e1, 0x00000002},
+ {0x000077e1, 0x00000006},
+ {0xffffffff, 0000000000},
+ {0x10000000, 0000000000},
+ {0x0003802b, 0x00000002},
+ {0x040067e0, 0x00000006},
+ {0x00007675, 0x00000002},
+ {0x00007676, 0x00000002},
+ {0x00007677, 0x00000002},
+ {0x00007678, 0x00000006},
+ {0x0003802c, 0x00000002},
+ {0x04002676, 0x00000002},
+ {0x00007677, 0x00000002},
+ {0x00007678, 0x00000006},
+ {0x0000002f, 0x00000018},
+ {0x0000002f, 0x00000018},
+ {0000000000, 0x00000006},
+ {0x00000030, 0x00000018},
+ {0x00000030, 0x00000018},
+ {0000000000, 0x00000006},
+ {0x01605000, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x00098000, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x64c0603e, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00080000, 0x00000016},
+ {0000000000, 0000000000},
+ {0x0400251d, 0x00000002},
+ {0x00007580, 0x00000002},
+ {0x00067581, 0x00000002},
+ {0x04002580, 0x00000002},
+ {0x00067581, 0x00000002},
+ {0x00000049, 0x00000004},
+ {0x00005000, 0000000000},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x0000750e, 0x00000002},
+ {0x00019000, 0x00000002},
+ {0x00011055, 0x00000014},
+ {0x00000055, 0x00000012},
+ {0x0400250f, 0x00000002},
+ {0x0000504f, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00007565, 0x00000002},
+ {0x00007566, 0x00000002},
+ {0x00000058, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x01e655b4, 0x00000002},
+ {0x4401b0e4, 0x00000002},
+ {0x01c110e4, 0x00000002},
+ {0x26667066, 0x00000018},
+ {0x040c2565, 0x00000002},
+ {0x00000066, 0x00000018},
+ {0x04002564, 0x00000002},
+ {0x00007566, 0x00000002},
+ {0x0000005d, 0x00000004},
+ {0x00401069, 0x00000008},
+ {0x00101000, 0x00000002},
+ {0x000d80ff, 0x00000002},
+ {0x0080006c, 0x00000008},
+ {0x000f9000, 0x00000002},
+ {0x000e00ff, 0x00000002},
+ {0000000000, 0x00000006},
+ {0x0000008f, 0x00000018},
+ {0x0000005b, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00007576, 0x00000002},
+ {0x00065000, 0x00000002},
+ {0x00009000, 0x00000002},
+ {0x00041000, 0x00000002},
+ {0x0c00350e, 0x00000002},
+ {0x00049000, 0x00000002},
+ {0x00051000, 0x00000002},
+ {0x01e785f8, 0x00000002},
+ {0x00200000, 0x00000002},
+ {0x0060007e, 0x0000000c},
+ {0x00007563, 0x00000002},
+ {0x006075f0, 0x00000021},
+ {0x20007073, 0x00000004},
+ {0x00005073, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00007576, 0x00000002},
+ {0x00007577, 0x00000002},
+ {0x0000750e, 0x00000002},
+ {0x0000750f, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00600083, 0x0000000c},
+ {0x006075f0, 0x00000021},
+ {0x000075f8, 0x00000002},
+ {0x00000083, 0x00000004},
+ {0x000a750e, 0x00000002},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x0020750f, 0x00000002},
+ {0x00600086, 0x00000004},
+ {0x00007570, 0x00000002},
+ {0x00007571, 0x00000002},
+ {0x00007572, 0x00000006},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00005000, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00007568, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x00000095, 0x0000000c},
+ {0x00058000, 0x00000002},
+ {0x0c607562, 0x00000002},
+ {0x00000097, 0x00000004},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x00600096, 0x00000004},
+ {0x400070e5, 0000000000},
+ {0x000380e6, 0x00000002},
+ {0x040025c5, 0x00000002},
+ {0x000380e5, 0x00000002},
+ {0x000000a8, 0x0000001c},
+ {0x000650aa, 0x00000018},
+ {0x040025bb, 0x00000002},
+ {0x000610ab, 0x00000018},
+ {0x040075bc, 0000000000},
+ {0x000075bb, 0x00000002},
+ {0x000075bc, 0000000000},
+ {0x00090000, 0x00000006},
+ {0x00090000, 0x00000002},
+ {0x000d8002, 0x00000006},
+ {0x00007832, 0x00000002},
+ {0x00005000, 0x00000002},
+ {0x000380e7, 0x00000002},
+ {0x04002c97, 0x00000002},
+ {0x00007820, 0x00000002},
+ {0x00007821, 0x00000002},
+ {0x00007800, 0000000000},
+ {0x01200000, 0x00000002},
+ {0x20077000, 0x00000002},
+ {0x01200000, 0x00000002},
+ {0x20007000, 0x00000002},
+ {0x00061000, 0x00000002},
+ {0x0120751b, 0x00000002},
+ {0x8040750a, 0x00000002},
+ {0x8040750b, 0x00000002},
+ {0x00110000, 0x00000002},
+ {0x000380e5, 0x00000002},
+ {0x000000c6, 0x0000001c},
+ {0x000610ab, 0x00000018},
+ {0x844075bd, 0x00000002},
+ {0x000610aa, 0x00000018},
+ {0x840075bb, 0x00000002},
+ {0x000610ab, 0x00000018},
+ {0x844075bc, 0x00000002},
+ {0x000000c9, 0x00000004},
+ {0x804075bd, 0x00000002},
+ {0x800075bb, 0x00000002},
+ {0x804075bc, 0x00000002},
+ {0x00108000, 0x00000002},
+ {0x01400000, 0x00000002},
+ {0x006000cd, 0x0000000c},
+ {0x20c07000, 0x00000020},
+ {0x000000cf, 0x00000012},
+ {0x00800000, 0x00000006},
+ {0x0080751d, 0x00000006},
+ {0000000000, 0000000000},
+ {0x0000775c, 0x00000002},
+ {0x00a05000, 0x00000002},
+ {0x00661000, 0x00000002},
+ {0x0460275d, 0x00000020},
+ {0x00004000, 0000000000},
+ {0x01e00830, 0x00000002},
+ {0x21007000, 0000000000},
+ {0x6464614d, 0000000000},
+ {0x69687420, 0000000000},
+ {0x00000073, 0000000000},
+ {0000000000, 0000000000},
+ {0x00005000, 0x00000002},
+ {0x000380d0, 0x00000002},
+ {0x040025e0, 0x00000002},
+ {0x000075e1, 0000000000},
+ {0x00000001, 0000000000},
+ {0x000380e0, 0x00000002},
+ {0x04002394, 0x00000002},
+ {0x00005000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0x00000008, 0000000000},
+ {0x00000004, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
};
static u32 R300_cp_microcode[][2] = {
- { 0x4200e000, 0000000000 },
- { 0x4000e000, 0000000000 },
- { 0x000000af, 0x00000008 },
- { 0x000000b3, 0x00000008 },
- { 0x6c5a504f, 0000000000 },
- { 0x4f4f497a, 0000000000 },
- { 0x5a578288, 0000000000 },
- { 0x4f91906a, 0000000000 },
- { 0x4f4f4f4f, 0000000000 },
- { 0x4fe24f44, 0000000000 },
- { 0x4f9c9c9c, 0000000000 },
- { 0xdc4f4fde, 0000000000 },
- { 0xa1cd4f4f, 0000000000 },
- { 0xd29d9d9d, 0000000000 },
- { 0x4f0f9fd7, 0000000000 },
- { 0x000ca000, 0x00000004 },
- { 0x000d0012, 0x00000038 },
- { 0x0000e8b4, 0x00000004 },
- { 0x000d0014, 0x00000038 },
- { 0x0000e8b6, 0x00000004 },
- { 0x000d0016, 0x00000038 },
- { 0x0000e854, 0x00000004 },
- { 0x000d0018, 0x00000038 },
- { 0x0000e855, 0x00000004 },
- { 0x000d001a, 0x00000038 },
- { 0x0000e856, 0x00000004 },
- { 0x000d001c, 0x00000038 },
- { 0x0000e857, 0x00000004 },
- { 0x000d001e, 0x00000038 },
- { 0x0000e824, 0x00000004 },
- { 0x000d0020, 0x00000038 },
- { 0x0000e825, 0x00000004 },
- { 0x000d0022, 0x00000038 },
- { 0x0000e830, 0x00000004 },
- { 0x000d0024, 0x00000038 },
- { 0x0000f0c0, 0x00000004 },
- { 0x000d0026, 0x00000038 },
- { 0x0000f0c1, 0x00000004 },
- { 0x000d0028, 0x00000038 },
- { 0x0000f041, 0x00000004 },
- { 0x000d002a, 0x00000038 },
- { 0x0000f184, 0x00000004 },
- { 0x000d002c, 0x00000038 },
- { 0x0000f185, 0x00000004 },
- { 0x000d002e, 0x00000038 },
- { 0x0000f186, 0x00000004 },
- { 0x000d0030, 0x00000038 },
- { 0x0000f187, 0x00000004 },
- { 0x000d0032, 0x00000038 },
- { 0x0000f180, 0x00000004 },
- { 0x000d0034, 0x00000038 },
- { 0x0000f393, 0x00000004 },
- { 0x000d0036, 0x00000038 },
- { 0x0000f38a, 0x00000004 },
- { 0x000d0038, 0x00000038 },
- { 0x0000f38e, 0x00000004 },
- { 0x0000e821, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x00000043, 0x00000018 },
- { 0x00cce800, 0x00000004 },
- { 0x001b0001, 0x00000004 },
- { 0x08004800, 0x00000004 },
- { 0x001b0001, 0x00000004 },
- { 0x08004800, 0x00000004 },
- { 0x001b0001, 0x00000004 },
- { 0x08004800, 0x00000004 },
- { 0x0000003a, 0x00000008 },
- { 0x0000a000, 0000000000 },
- { 0x02c0a000, 0x00000004 },
- { 0x000ca000, 0x00000004 },
- { 0x00130000, 0x00000004 },
- { 0x000c2000, 0x00000004 },
- { 0xc980c045, 0x00000008 },
- { 0x2000451d, 0x00000004 },
- { 0x0000e580, 0x00000004 },
- { 0x000ce581, 0x00000004 },
- { 0x08004580, 0x00000004 },
- { 0x000ce581, 0x00000004 },
- { 0x0000004c, 0x00000008 },
- { 0x0000a000, 0000000000 },
- { 0x000c2000, 0x00000004 },
- { 0x0000e50e, 0x00000004 },
- { 0x00032000, 0x00000004 },
- { 0x00022056, 0x00000028 },
- { 0x00000056, 0x00000024 },
- { 0x0800450f, 0x00000004 },
- { 0x0000a050, 0x00000008 },
- { 0x0000e565, 0x00000004 },
- { 0x0000e566, 0x00000004 },
- { 0x00000057, 0x00000008 },
- { 0x03cca5b4, 0x00000004 },
- { 0x05432000, 0x00000004 },
- { 0x00022000, 0x00000004 },
- { 0x4ccce063, 0x00000030 },
- { 0x08274565, 0x00000004 },
- { 0x00000063, 0x00000030 },
- { 0x08004564, 0x00000004 },
- { 0x0000e566, 0x00000004 },
- { 0x0000005a, 0x00000008 },
- { 0x00802066, 0x00000010 },
- { 0x00202000, 0x00000004 },
- { 0x001b00ff, 0x00000004 },
- { 0x01000069, 0x00000010 },
- { 0x001f2000, 0x00000004 },
- { 0x001c00ff, 0x00000004 },
- { 0000000000, 0x0000000c },
- { 0x00000085, 0x00000030 },
- { 0x0000005a, 0x00000008 },
- { 0x0000e576, 0x00000004 },
- { 0x000ca000, 0x00000004 },
- { 0x00012000, 0x00000004 },
- { 0x00082000, 0x00000004 },
- { 0x1800650e, 0x00000004 },
- { 0x00092000, 0x00000004 },
- { 0x000a2000, 0x00000004 },
- { 0x000f0000, 0x00000004 },
- { 0x00400000, 0x00000004 },
- { 0x00000079, 0x00000018 },
- { 0x0000e563, 0x00000004 },
- { 0x00c0e5f9, 0x000000c2 },
- { 0x0000006e, 0x00000008 },
- { 0x0000a06e, 0x00000008 },
- { 0x0000e576, 0x00000004 },
- { 0x0000e577, 0x00000004 },
- { 0x0000e50e, 0x00000004 },
- { 0x0000e50f, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x0000007c, 0x00000018 },
- { 0x00c0e5f9, 0x000000c2 },
- { 0x0000007c, 0x00000008 },
- { 0x0014e50e, 0x00000004 },
- { 0x0040e50f, 0x00000004 },
- { 0x00c0007f, 0x00000008 },
- { 0x0000e570, 0x00000004 },
- { 0x0000e571, 0x00000004 },
- { 0x0000e572, 0x0000000c },
- { 0x0000a000, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x0000e568, 0x00000004 },
- { 0x000c2000, 0x00000004 },
- { 0x00000089, 0x00000018 },
- { 0x000b0000, 0x00000004 },
- { 0x18c0e562, 0x00000004 },
- { 0x0000008b, 0x00000008 },
- { 0x00c0008a, 0x00000008 },
- { 0x000700e4, 0x00000004 },
- { 0x00000097, 0x00000038 },
- { 0x000ca099, 0x00000030 },
- { 0x080045bb, 0x00000004 },
- { 0x000c209a, 0x00000030 },
- { 0x0800e5bc, 0000000000 },
- { 0x0000e5bb, 0x00000004 },
- { 0x0000e5bc, 0000000000 },
- { 0x00120000, 0x0000000c },
- { 0x00120000, 0x00000004 },
- { 0x001b0002, 0x0000000c },
- { 0x0000a000, 0x00000004 },
- { 0x0000e821, 0x00000004 },
- { 0x0000e800, 0000000000 },
- { 0x0000e821, 0x00000004 },
- { 0x0000e82e, 0000000000 },
- { 0x02cca000, 0x00000004 },
- { 0x00140000, 0x00000004 },
- { 0x000ce1cc, 0x00000004 },
- { 0x050de1cd, 0x00000004 },
- { 0x000000a7, 0x00000020 },
- { 0x4200e000, 0000000000 },
- { 0x000000ae, 0x00000038 },
- { 0x000ca000, 0x00000004 },
- { 0x00140000, 0x00000004 },
- { 0x000c2000, 0x00000004 },
- { 0x00160000, 0x00000004 },
- { 0x700ce000, 0x00000004 },
- { 0x001400aa, 0x00000008 },
- { 0x4000e000, 0000000000 },
- { 0x02400000, 0x00000004 },
- { 0x400ee000, 0x00000004 },
- { 0x02400000, 0x00000004 },
- { 0x4000e000, 0000000000 },
- { 0x000c2000, 0x00000004 },
- { 0x0240e51b, 0x00000004 },
- { 0x0080e50a, 0x00000005 },
- { 0x0080e50b, 0x00000005 },
- { 0x00220000, 0x00000004 },
- { 0x000700e4, 0x00000004 },
- { 0x000000c1, 0x00000038 },
- { 0x000c209a, 0x00000030 },
- { 0x0880e5bd, 0x00000005 },
- { 0x000c2099, 0x00000030 },
- { 0x0800e5bb, 0x00000005 },
- { 0x000c209a, 0x00000030 },
- { 0x0880e5bc, 0x00000005 },
- { 0x000000c4, 0x00000008 },
- { 0x0080e5bd, 0x00000005 },
- { 0x0000e5bb, 0x00000005 },
- { 0x0080e5bc, 0x00000005 },
- { 0x00210000, 0x00000004 },
- { 0x02800000, 0x00000004 },
- { 0x00c000c8, 0x00000018 },
- { 0x4180e000, 0x00000040 },
- { 0x000000ca, 0x00000024 },
- { 0x01000000, 0x0000000c },
- { 0x0100e51d, 0x0000000c },
- { 0x000045bb, 0x00000004 },
- { 0x000080c4, 0x00000008 },
- { 0x0000f3ce, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x00cc2000, 0x00000004 },
- { 0x08c053cf, 0x00000040 },
- { 0x00008000, 0000000000 },
- { 0x0000f3d2, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x00cc2000, 0x00000004 },
- { 0x08c053d3, 0x00000040 },
- { 0x00008000, 0000000000 },
- { 0x0000f39d, 0x00000004 },
- { 0x0140a000, 0x00000004 },
- { 0x00cc2000, 0x00000004 },
- { 0x08c0539e, 0x00000040 },
- { 0x00008000, 0000000000 },
- { 0x03c00830, 0x00000004 },
- { 0x4200e000, 0000000000 },
- { 0x0000a000, 0x00000004 },
- { 0x200045e0, 0x00000004 },
- { 0x0000e5e1, 0000000000 },
- { 0x00000001, 0000000000 },
- { 0x000700e1, 0x00000004 },
- { 0x0800e394, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
- { 0000000000, 0000000000 },
+ {0x4200e000, 0000000000},
+ {0x4000e000, 0000000000},
+ {0x000000af, 0x00000008},
+ {0x000000b3, 0x00000008},
+ {0x6c5a504f, 0000000000},
+ {0x4f4f497a, 0000000000},
+ {0x5a578288, 0000000000},
+ {0x4f91906a, 0000000000},
+ {0x4f4f4f4f, 0000000000},
+ {0x4fe24f44, 0000000000},
+ {0x4f9c9c9c, 0000000000},
+ {0xdc4f4fde, 0000000000},
+ {0xa1cd4f4f, 0000000000},
+ {0xd29d9d9d, 0000000000},
+ {0x4f0f9fd7, 0000000000},
+ {0x000ca000, 0x00000004},
+ {0x000d0012, 0x00000038},
+ {0x0000e8b4, 0x00000004},
+ {0x000d0014, 0x00000038},
+ {0x0000e8b6, 0x00000004},
+ {0x000d0016, 0x00000038},
+ {0x0000e854, 0x00000004},
+ {0x000d0018, 0x00000038},
+ {0x0000e855, 0x00000004},
+ {0x000d001a, 0x00000038},
+ {0x0000e856, 0x00000004},
+ {0x000d001c, 0x00000038},
+ {0x0000e857, 0x00000004},
+ {0x000d001e, 0x00000038},
+ {0x0000e824, 0x00000004},
+ {0x000d0020, 0x00000038},
+ {0x0000e825, 0x00000004},
+ {0x000d0022, 0x00000038},
+ {0x0000e830, 0x00000004},
+ {0x000d0024, 0x00000038},
+ {0x0000f0c0, 0x00000004},
+ {0x000d0026, 0x00000038},
+ {0x0000f0c1, 0x00000004},
+ {0x000d0028, 0x00000038},
+ {0x0000f041, 0x00000004},
+ {0x000d002a, 0x00000038},
+ {0x0000f184, 0x00000004},
+ {0x000d002c, 0x00000038},
+ {0x0000f185, 0x00000004},
+ {0x000d002e, 0x00000038},
+ {0x0000f186, 0x00000004},
+ {0x000d0030, 0x00000038},
+ {0x0000f187, 0x00000004},
+ {0x000d0032, 0x00000038},
+ {0x0000f180, 0x00000004},
+ {0x000d0034, 0x00000038},
+ {0x0000f393, 0x00000004},
+ {0x000d0036, 0x00000038},
+ {0x0000f38a, 0x00000004},
+ {0x000d0038, 0x00000038},
+ {0x0000f38e, 0x00000004},
+ {0x0000e821, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x00000043, 0x00000018},
+ {0x00cce800, 0x00000004},
+ {0x001b0001, 0x00000004},
+ {0x08004800, 0x00000004},
+ {0x001b0001, 0x00000004},
+ {0x08004800, 0x00000004},
+ {0x001b0001, 0x00000004},
+ {0x08004800, 0x00000004},
+ {0x0000003a, 0x00000008},
+ {0x0000a000, 0000000000},
+ {0x02c0a000, 0x00000004},
+ {0x000ca000, 0x00000004},
+ {0x00130000, 0x00000004},
+ {0x000c2000, 0x00000004},
+ {0xc980c045, 0x00000008},
+ {0x2000451d, 0x00000004},
+ {0x0000e580, 0x00000004},
+ {0x000ce581, 0x00000004},
+ {0x08004580, 0x00000004},
+ {0x000ce581, 0x00000004},
+ {0x0000004c, 0x00000008},
+ {0x0000a000, 0000000000},
+ {0x000c2000, 0x00000004},
+ {0x0000e50e, 0x00000004},
+ {0x00032000, 0x00000004},
+ {0x00022056, 0x00000028},
+ {0x00000056, 0x00000024},
+ {0x0800450f, 0x00000004},
+ {0x0000a050, 0x00000008},
+ {0x0000e565, 0x00000004},
+ {0x0000e566, 0x00000004},
+ {0x00000057, 0x00000008},
+ {0x03cca5b4, 0x00000004},
+ {0x05432000, 0x00000004},
+ {0x00022000, 0x00000004},
+ {0x4ccce063, 0x00000030},
+ {0x08274565, 0x00000004},
+ {0x00000063, 0x00000030},
+ {0x08004564, 0x00000004},
+ {0x0000e566, 0x00000004},
+ {0x0000005a, 0x00000008},
+ {0x00802066, 0x00000010},
+ {0x00202000, 0x00000004},
+ {0x001b00ff, 0x00000004},
+ {0x01000069, 0x00000010},
+ {0x001f2000, 0x00000004},
+ {0x001c00ff, 0x00000004},
+ {0000000000, 0x0000000c},
+ {0x00000085, 0x00000030},
+ {0x0000005a, 0x00000008},
+ {0x0000e576, 0x00000004},
+ {0x000ca000, 0x00000004},
+ {0x00012000, 0x00000004},
+ {0x00082000, 0x00000004},
+ {0x1800650e, 0x00000004},
+ {0x00092000, 0x00000004},
+ {0x000a2000, 0x00000004},
+ {0x000f0000, 0x00000004},
+ {0x00400000, 0x00000004},
+ {0x00000079, 0x00000018},
+ {0x0000e563, 0x00000004},
+ {0x00c0e5f9, 0x000000c2},
+ {0x0000006e, 0x00000008},
+ {0x0000a06e, 0x00000008},
+ {0x0000e576, 0x00000004},
+ {0x0000e577, 0x00000004},
+ {0x0000e50e, 0x00000004},
+ {0x0000e50f, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x0000007c, 0x00000018},
+ {0x00c0e5f9, 0x000000c2},
+ {0x0000007c, 0x00000008},
+ {0x0014e50e, 0x00000004},
+ {0x0040e50f, 0x00000004},
+ {0x00c0007f, 0x00000008},
+ {0x0000e570, 0x00000004},
+ {0x0000e571, 0x00000004},
+ {0x0000e572, 0x0000000c},
+ {0x0000a000, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x0000e568, 0x00000004},
+ {0x000c2000, 0x00000004},
+ {0x00000089, 0x00000018},
+ {0x000b0000, 0x00000004},
+ {0x18c0e562, 0x00000004},
+ {0x0000008b, 0x00000008},
+ {0x00c0008a, 0x00000008},
+ {0x000700e4, 0x00000004},
+ {0x00000097, 0x00000038},
+ {0x000ca099, 0x00000030},
+ {0x080045bb, 0x00000004},
+ {0x000c209a, 0x00000030},
+ {0x0800e5bc, 0000000000},
+ {0x0000e5bb, 0x00000004},
+ {0x0000e5bc, 0000000000},
+ {0x00120000, 0x0000000c},
+ {0x00120000, 0x00000004},
+ {0x001b0002, 0x0000000c},
+ {0x0000a000, 0x00000004},
+ {0x0000e821, 0x00000004},
+ {0x0000e800, 0000000000},
+ {0x0000e821, 0x00000004},
+ {0x0000e82e, 0000000000},
+ {0x02cca000, 0x00000004},
+ {0x00140000, 0x00000004},
+ {0x000ce1cc, 0x00000004},
+ {0x050de1cd, 0x00000004},
+ {0x000000a7, 0x00000020},
+ {0x4200e000, 0000000000},
+ {0x000000ae, 0x00000038},
+ {0x000ca000, 0x00000004},
+ {0x00140000, 0x00000004},
+ {0x000c2000, 0x00000004},
+ {0x00160000, 0x00000004},
+ {0x700ce000, 0x00000004},
+ {0x001400aa, 0x00000008},
+ {0x4000e000, 0000000000},
+ {0x02400000, 0x00000004},
+ {0x400ee000, 0x00000004},
+ {0x02400000, 0x00000004},
+ {0x4000e000, 0000000000},
+ {0x000c2000, 0x00000004},
+ {0x0240e51b, 0x00000004},
+ {0x0080e50a, 0x00000005},
+ {0x0080e50b, 0x00000005},
+ {0x00220000, 0x00000004},
+ {0x000700e4, 0x00000004},
+ {0x000000c1, 0x00000038},
+ {0x000c209a, 0x00000030},
+ {0x0880e5bd, 0x00000005},
+ {0x000c2099, 0x00000030},
+ {0x0800e5bb, 0x00000005},
+ {0x000c209a, 0x00000030},
+ {0x0880e5bc, 0x00000005},
+ {0x000000c4, 0x00000008},
+ {0x0080e5bd, 0x00000005},
+ {0x0000e5bb, 0x00000005},
+ {0x0080e5bc, 0x00000005},
+ {0x00210000, 0x00000004},
+ {0x02800000, 0x00000004},
+ {0x00c000c8, 0x00000018},
+ {0x4180e000, 0x00000040},
+ {0x000000ca, 0x00000024},
+ {0x01000000, 0x0000000c},
+ {0x0100e51d, 0x0000000c},
+ {0x000045bb, 0x00000004},
+ {0x000080c4, 0x00000008},
+ {0x0000f3ce, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x00cc2000, 0x00000004},
+ {0x08c053cf, 0x00000040},
+ {0x00008000, 0000000000},
+ {0x0000f3d2, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x00cc2000, 0x00000004},
+ {0x08c053d3, 0x00000040},
+ {0x00008000, 0000000000},
+ {0x0000f39d, 0x00000004},
+ {0x0140a000, 0x00000004},
+ {0x00cc2000, 0x00000004},
+ {0x08c0539e, 0x00000040},
+ {0x00008000, 0000000000},
+ {0x03c00830, 0x00000004},
+ {0x4200e000, 0000000000},
+ {0x0000a000, 0x00000004},
+ {0x200045e0, 0x00000004},
+ {0x0000e5e1, 0000000000},
+ {0x00000001, 0000000000},
+ {0x000700e1, 0x00000004},
+ {0x0800e394, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
+ {0000000000, 0000000000},
};
-static int RADEON_READ_PLL(drm_device_t *dev, int addr)
+static int RADEON_READ_PLL(drm_device_t * dev, int addr)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -824,145 +824,148 @@ static int RADEON_READ_PLL(drm_device_t *dev, int addr)
return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
}
+static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr)
+{
+ RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
+ return RADEON_READ(RADEON_PCIE_DATA);
+}
+
#if RADEON_FIFO_DEBUG
-static void radeon_status( drm_radeon_private_t *dev_priv )
+static void radeon_status(drm_radeon_private_t * dev_priv)
{
- printk( "%s:\n", __FUNCTION__ );
- printk( "RBBM_STATUS = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
- printk( "CP_RB_RTPR = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
- printk( "CP_RB_WTPR = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
- printk( "AIC_CNTL = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
- printk( "AIC_STAT = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
- printk( "AIC_PT_BASE = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
- printk( "TLB_ADDR = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
- printk( "TLB_DATA = 0x%08x\n",
- (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
+ printk("%s:\n", __FUNCTION__);
+ printk("RBBM_STATUS = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
+ printk("CP_RB_RTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
+ printk("CP_RB_WTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
+ printk("AIC_CNTL = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
+ printk("AIC_STAT = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_AIC_STAT));
+ printk("AIC_PT_BASE = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
+ printk("TLB_ADDR = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
+ printk("TLB_DATA = 0x%08x\n",
+ (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
}
#endif
-
/* ================================================================
* Engine, FIFO control
*/
-static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
+static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
{
u32 tmp;
int i;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
+ tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
tmp |= RADEON_RB2D_DC_FLUSH_ALL;
- RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
+ RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp);
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
- & RADEON_RB2D_DC_BUSY) ) {
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
+ & RADEON_RB2D_DC_BUSY)) {
return 0;
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if RADEON_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
- radeon_status( dev_priv );
+ DRM_ERROR("failed!\n");
+ radeon_status(dev_priv);
#endif
return DRM_ERR(EBUSY);
}
-static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
- int entries )
+static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
{
int i;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
- & RADEON_RBBM_FIFOCNT_MASK );
- if ( slots >= entries ) return 0;
- DRM_UDELAY( 1 );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ int slots = (RADEON_READ(RADEON_RBBM_STATUS)
+ & RADEON_RBBM_FIFOCNT_MASK);
+ if (slots >= entries)
+ return 0;
+ DRM_UDELAY(1);
}
#if RADEON_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
- radeon_status( dev_priv );
+ DRM_ERROR("failed!\n");
+ radeon_status(dev_priv);
#endif
return DRM_ERR(EBUSY);
}
-static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
+static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
{
int i, ret;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- ret = radeon_do_wait_for_fifo( dev_priv, 64 );
- if ( ret ) return ret;
+ ret = radeon_do_wait_for_fifo(dev_priv, 64);
+ if (ret)
+ return ret;
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- if ( !(RADEON_READ( RADEON_RBBM_STATUS )
- & RADEON_RBBM_ACTIVE) ) {
- radeon_do_pixcache_flush( dev_priv );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ if (!(RADEON_READ(RADEON_RBBM_STATUS)
+ & RADEON_RBBM_ACTIVE)) {
+ radeon_do_pixcache_flush(dev_priv);
return 0;
}
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
#if RADEON_FIFO_DEBUG
- DRM_ERROR( "failed!\n" );
- radeon_status( dev_priv );
+ DRM_ERROR("failed!\n");
+ radeon_status(dev_priv);
#endif
return DRM_ERR(EBUSY);
}
-
/* ================================================================
* CP control, initialization
*/
/* Load the microcode for the CP */
-static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
+static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
{
int i;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- radeon_do_wait_for_idle( dev_priv );
+ radeon_do_wait_for_idle(dev_priv);
- RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
+ RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
- if (dev_priv->microcode_version==UCODE_R200) {
+ if (dev_priv->microcode_version == UCODE_R200) {
DRM_INFO("Loading R200 Microcode\n");
- for ( i = 0 ; i < 256 ; i++ )
- {
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
- R200_cp_microcode[i][1] );
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
- R200_cp_microcode[i][0] );
+ for (i = 0; i < 256; i++) {
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+ R200_cp_microcode[i][1]);
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+ R200_cp_microcode[i][0]);
}
- } else if (dev_priv->microcode_version==UCODE_R300) {
+ } else if (dev_priv->microcode_version == UCODE_R300) {
DRM_INFO("Loading R300 Microcode\n");
- for ( i = 0 ; i < 256 ; i++ )
- {
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
- R300_cp_microcode[i][1] );
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
- R300_cp_microcode[i][0] );
+ for (i = 0; i < 256; i++) {
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+ R300_cp_microcode[i][1]);
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+ R300_cp_microcode[i][0]);
}
} else {
- for ( i = 0 ; i < 256 ; i++ ) {
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
- radeon_cp_microcode[i][1] );
- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
- radeon_cp_microcode[i][0] );
+ for (i = 0; i < 256; i++) {
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+ radeon_cp_microcode[i][1]);
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+ radeon_cp_microcode[i][0]);
}
}
}
@@ -971,25 +974,25 @@ static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
* prior to a wait for idle, as it informs the engine that the command
* stream is ending.
*/
-static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
+static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
{
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
#if 0
u32 tmp;
- tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
- RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
+ tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
+ RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
#endif
}
/* Wait for the CP to go idle.
*/
-int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
+int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
{
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
RADEON_PURGE_CACHE();
RADEON_PURGE_ZCACHE();
@@ -998,23 +1001,23 @@ int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
ADVANCE_RING();
COMMIT_RING();
- return radeon_do_wait_for_idle( dev_priv );
+ return radeon_do_wait_for_idle(dev_priv);
}
/* Start the Command Processor.
*/
-static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
+static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
{
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- radeon_do_wait_for_idle( dev_priv );
+ radeon_do_wait_for_idle(dev_priv);
- RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
+ RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
dev_priv->cp_running = 1;
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
RADEON_PURGE_CACHE();
RADEON_PURGE_ZCACHE();
@@ -1028,14 +1031,14 @@ static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
* commands, so you must wait for the CP command stream to complete
* before calling this routine.
*/
-static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
+static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
{
u32 cur_read_ptr;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
- RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
- SET_RING_HEAD( dev_priv, cur_read_ptr );
+ cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+ RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+ SET_RING_HEAD(dev_priv, cur_read_ptr);
dev_priv->ring.tail = cur_read_ptr;
}
@@ -1043,132 +1046,132 @@ static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
* commands, so you must flush the command stream and wait for the CP
* to go idle before calling this routine.
*/
-static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
+static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
{
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
+ RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
dev_priv->cp_running = 0;
}
/* Reset the engine. This will stop the CP if it is running.
*/
-static int radeon_do_engine_reset( drm_device_t *dev )
+static int radeon_do_engine_reset(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
- DRM_DEBUG( "\n" );
-
- radeon_do_pixcache_flush( dev_priv );
-
- clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
- mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
-
- RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
- RADEON_FORCEON_MCLKA |
- RADEON_FORCEON_MCLKB |
- RADEON_FORCEON_YCLKA |
- RADEON_FORCEON_YCLKB |
- RADEON_FORCEON_MC |
- RADEON_FORCEON_AIC ) );
-
- rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
+ DRM_DEBUG("\n");
- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
- RADEON_SOFT_RESET_CP |
+ radeon_do_pixcache_flush(dev_priv);
+
+ clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
+ mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
+
+ RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
+ RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_MCLKB |
+ RADEON_FORCEON_YCLKA |
+ RADEON_FORCEON_YCLKB |
+ RADEON_FORCEON_MC |
+ RADEON_FORCEON_AIC));
+
+ rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+ RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB));
+ RADEON_READ(RADEON_RBBM_SOFT_RESET);
+ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+ ~(RADEON_SOFT_RESET_CP |
RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP |
RADEON_SOFT_RESET_E2 |
- RADEON_SOFT_RESET_RB ) );
- RADEON_READ( RADEON_RBBM_SOFT_RESET );
- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
- ~( RADEON_SOFT_RESET_CP |
- RADEON_SOFT_RESET_HI |
- RADEON_SOFT_RESET_SE |
- RADEON_SOFT_RESET_RE |
- RADEON_SOFT_RESET_PP |
- RADEON_SOFT_RESET_E2 |
- RADEON_SOFT_RESET_RB ) ) );
- RADEON_READ( RADEON_RBBM_SOFT_RESET );
-
-
- RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
- RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset );
+ RADEON_SOFT_RESET_RB)));
+ RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+ RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+ RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
+ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
/* Reset the CP ring */
- radeon_do_cp_reset( dev_priv );
+ radeon_do_cp_reset(dev_priv);
/* The CP is no longer running after an engine reset */
dev_priv->cp_running = 0;
/* Reset any pending vertex, indirect buffers */
- radeon_freelist_reset( dev );
+ radeon_freelist_reset(dev);
return 0;
}
-static void radeon_cp_init_ring_buffer( drm_device_t *dev,
- drm_radeon_private_t *dev_priv )
+static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+ drm_radeon_private_t * dev_priv)
{
u32 ring_start, cur_read_ptr;
u32 tmp;
/* Initialize the memory controller */
- RADEON_WRITE( RADEON_MC_FB_LOCATION,
- ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
- | ( dev_priv->fb_location >> 16 ) );
+ RADEON_WRITE(RADEON_MC_FB_LOCATION,
+ ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+ | (dev_priv->fb_location >> 16));
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- RADEON_WRITE( RADEON_MC_AGP_LOCATION,
- (((dev_priv->gart_vm_start - 1 +
- dev_priv->gart_size) & 0xffff0000) |
- (dev_priv->gart_vm_start >> 16)) );
+ if (!dev_priv->is_pci) {
+ RADEON_WRITE(RADEON_MC_AGP_LOCATION,
+ (((dev_priv->gart_vm_start - 1 +
+ dev_priv->gart_size) & 0xffff0000) |
+ (dev_priv->gart_vm_start >> 16)));
ring_start = (dev_priv->cp_ring->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
- } else
+ } else
#endif
ring_start = (dev_priv->cp_ring->offset
- - dev->sg->handle
+ - (unsigned long)dev->sg->virtual
+ dev_priv->gart_vm_start);
- RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
+ RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
/* Set the write pointer delay */
- RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
+ RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
/* Initialize the ring buffer's read and write pointers */
- cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
- RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
- SET_RING_HEAD( dev_priv, cur_read_ptr );
+ cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+ RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+ SET_RING_HEAD(dev_priv, cur_read_ptr);
dev_priv->ring.tail = cur_read_ptr;
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
- dev_priv->ring_rptr->offset
- - dev->agp->base
- + dev_priv->gart_vm_start);
+ if (!dev_priv->is_pci) {
+ /* set RADEON_AGP_BASE here instead of relying on X from user space */
+ RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
+ RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
+ dev_priv->ring_rptr->offset
+ - dev->agp->base + dev_priv->gart_vm_start);
} else
#endif
{
drm_sg_mem_t *entry = dev->sg;
unsigned long tmp_ofs, page_ofs;
- tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+ tmp_ofs = dev_priv->ring_rptr->offset -
+ (unsigned long)dev->sg->virtual;
page_ofs = tmp_ofs >> PAGE_SHIFT;
- RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
- entry->busaddr[page_ofs]);
- DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
- (unsigned long) entry->busaddr[page_ofs],
- entry->handle + tmp_ofs );
+ RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
+ DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
+ (unsigned long)entry->busaddr[page_ofs],
+ entry->handle + tmp_ofs);
}
/* Initialize the scratch register pointer. This will cause
@@ -1178,127 +1181,168 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
* We simply put this behind the ring read pointer, this works
* with PCI GART as well as (whatever kind of) AGP GART
*/
- RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
- + RADEON_SCRATCH_REG_OFFSET );
+ RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
+ + RADEON_SCRATCH_REG_OFFSET);
dev_priv->scratch = ((__volatile__ u32 *)
dev_priv->ring_rptr->handle +
(RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
- RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+ RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
/* Writeback doesn't seem to work everywhere, test it first */
- DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
- RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+ DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
+ RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
- for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
- if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
+ for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
+ if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
+ 0xdeadbeef)
break;
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
- if ( tmp < dev_priv->usec_timeout ) {
+ if (tmp < dev_priv->usec_timeout) {
dev_priv->writeback_works = 1;
- DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+ DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);
} else {
dev_priv->writeback_works = 0;
- DRM_DEBUG( "writeback test failed\n" );
+ DRM_DEBUG("writeback test failed\n");
+ }
+ if (radeon_no_wb == 1) {
+ dev_priv->writeback_works = 0;
+ DRM_DEBUG("writeback forced off\n");
}
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
- RADEON_WRITE( RADEON_LAST_FRAME_REG,
- dev_priv->sarea_priv->last_frame );
+ RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
- RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
- dev_priv->sarea_priv->last_dispatch );
+ RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
+ dev_priv->sarea_priv->last_dispatch);
dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
- RADEON_WRITE( RADEON_LAST_CLEAR_REG,
- dev_priv->sarea_priv->last_clear );
+ RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
/* Set ring buffer size */
#ifdef __BIG_ENDIAN
- RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
+ RADEON_WRITE(RADEON_CP_RB_CNTL,
+ dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
#else
- RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+ RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
#endif
- radeon_do_wait_for_idle( dev_priv );
+ radeon_do_wait_for_idle(dev_priv);
/* Turn on bus mastering */
- tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
- RADEON_WRITE( RADEON_BUS_CNTL, tmp );
+ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
/* Sync everything up */
- RADEON_WRITE( RADEON_ISYNC_CNTL,
- (RADEON_ISYNC_ANY2D_IDLE3D |
- RADEON_ISYNC_ANY3D_IDLE2D |
- RADEON_ISYNC_WAIT_IDLEGUI |
- RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
+ RADEON_WRITE(RADEON_ISYNC_CNTL,
+ (RADEON_ISYNC_ANY2D_IDLE3D |
+ RADEON_ISYNC_ANY3D_IDLE2D |
+ RADEON_ISYNC_WAIT_IDLEGUI |
+ RADEON_ISYNC_CPSCRATCH_IDLEGUI));
+}
+
+/* Enable or disable PCI-E GART on the chip */
+static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
+{
+ u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
+ if (on) {
+
+ DRM_DEBUG("programming pcie %08X %08lX %08X\n",
+ dev_priv->gart_vm_start,
+ (long)dev_priv->gart_info.bus_addr,
+ dev_priv->gart_size);
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
+ dev_priv->gart_vm_start);
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
+ dev_priv->gart_info.bus_addr);
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
+ dev_priv->gart_vm_start);
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
+ dev_priv->gart_vm_start +
+ dev_priv->gart_size - 1);
+
+ RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */
+
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+ RADEON_PCIE_TX_GART_EN);
+ } else {
+ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+ tmp & ~RADEON_PCIE_TX_GART_EN);
+ }
}
/* Enable or disable PCI GART on the chip */
-static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
+static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
{
- u32 tmp = RADEON_READ( RADEON_AIC_CNTL );
+ u32 tmp = RADEON_READ(RADEON_AIC_CNTL);
+
+ if (dev_priv->flags & CHIP_IS_PCIE) {
+ radeon_set_pciegart(dev_priv, on);
+ return;
+ }
- if ( on ) {
- RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
+ if (on) {
+ RADEON_WRITE(RADEON_AIC_CNTL,
+ tmp | RADEON_PCIGART_TRANSLATE_EN);
/* set PCI GART page-table base address
*/
- RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
+ RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
/* set address range for PCI address translate
*/
- RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start );
- RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
- + dev_priv->gart_size - 1);
+ RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
+ RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
+ + dev_priv->gart_size - 1);
/* Turn off AGP aperture -- is this required for PCI GART?
*/
- RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
- RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
+ RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */
+ RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */
} else {
- RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
+ RADEON_WRITE(RADEON_AIC_CNTL,
+ tmp & ~RADEON_PCIGART_TRANSLATE_EN);
}
}
-static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
+static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
{
drm_radeon_private_t *dev_priv = dev->dev_private;;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
dev_priv->is_pci = init->is_pci;
- if ( dev_priv->is_pci && !dev->sg ) {
- DRM_ERROR( "PCI GART memory not allocated!\n" );
+ if (dev_priv->is_pci && !dev->sg) {
+ DRM_ERROR("PCI GART memory not allocated!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->usec_timeout = init->usec_timeout;
- if ( dev_priv->usec_timeout < 1 ||
- dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
- DRM_DEBUG( "TIMEOUT problem!\n" );
+ if (dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
+ DRM_DEBUG("TIMEOUT problem!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- switch(init->func) {
+ switch (init->func) {
case RADEON_INIT_R200_CP:
- dev_priv->microcode_version=UCODE_R200;
+ dev_priv->microcode_version = UCODE_R200;
break;
case RADEON_INIT_R300_CP:
- dev_priv->microcode_version=UCODE_R300;
+ dev_priv->microcode_version = UCODE_R300;
break;
default:
- dev_priv->microcode_version=UCODE_R100;
+ dev_priv->microcode_version = UCODE_R100;
}
-
+
dev_priv->do_boxes = 0;
dev_priv->cp_mode = init->cp_mode;
@@ -1306,15 +1350,15 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
* but the ring can be in either AGP or PCI space for the ring
* read pointer.
*/
- if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
- ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
- DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
+ if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
+ (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
+ DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- switch ( init->fb_bpp ) {
+ switch (init->fb_bpp) {
case 16:
dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
break;
@@ -1323,12 +1367,12 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
break;
}
- dev_priv->front_offset = init->front_offset;
- dev_priv->front_pitch = init->front_pitch;
- dev_priv->back_offset = init->back_offset;
- dev_priv->back_pitch = init->back_pitch;
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
- switch ( init->depth_bpp ) {
+ switch (init->depth_bpp) {
case 16:
dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
break;
@@ -1337,8 +1381,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
break;
}
- dev_priv->depth_offset = init->depth_offset;
- dev_priv->depth_pitch = init->depth_pitch;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
/* Hardware state for depth clears. Remove this if/when we no
* longer clear the depth buffer with a 3D rectangle. Hard-code
@@ -1347,16 +1391,16 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
*/
dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
(dev_priv->color_fmt << 10) |
- (dev_priv->microcode_version == UCODE_R100 ? RADEON_ZBLOCK16 : 0));
+ (dev_priv->microcode_version ==
+ UCODE_R100 ? RADEON_ZBLOCK16 : 0));
- dev_priv->depth_clear.rb3d_zstencilcntl =
- (dev_priv->depth_fmt |
- RADEON_Z_TEST_ALWAYS |
- RADEON_STENCIL_TEST_ALWAYS |
- RADEON_STENCIL_S_FAIL_REPLACE |
- RADEON_STENCIL_ZPASS_REPLACE |
- RADEON_STENCIL_ZFAIL_REPLACE |
- RADEON_Z_WRITE_ENABLE);
+ dev_priv->depth_clear.rb3d_zstencilcntl =
+ (dev_priv->depth_fmt |
+ RADEON_Z_TEST_ALWAYS |
+ RADEON_STENCIL_TEST_ALWAYS |
+ RADEON_STENCIL_S_FAIL_REPLACE |
+ RADEON_STENCIL_ZPASS_REPLACE |
+ RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
RADEON_BFACE_SOLID |
@@ -1378,8 +1422,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->ring_rptr_offset = init->ring_rptr_offset;
dev_priv->buffers_offset = init->buffers_offset;
dev_priv->gart_textures_offset = init->gart_textures_offset;
-
- if(!dev_priv->sarea) {
+
+ if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
@@ -1387,37 +1431,39 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
}
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- if(!dev_priv->mmio) {
+ if (!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
- if(!dev_priv->cp_ring) {
+ if (!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
- if(!dev_priv->ring_rptr) {
+ if (!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
- if(!dev->agp_buffer_map) {
+ if (!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- if ( init->gart_textures_offset ) {
- dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
- if ( !dev_priv->gart_textures ) {
+ if (init->gart_textures_offset) {
+ dev_priv->gart_textures =
+ drm_core_findmap(dev, init->gart_textures_offset);
+ if (!dev_priv->gart_textures) {
DRM_ERROR("could not find GART texture region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
@@ -1426,17 +1472,17 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
}
dev_priv->sarea_priv =
- (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
+ (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+ init->sarea_priv_offset);
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- drm_core_ioremap( dev_priv->cp_ring, dev );
- drm_core_ioremap( dev_priv->ring_rptr, dev );
- drm_core_ioremap( dev->agp_buffer_map, dev );
- if(!dev_priv->cp_ring->handle ||
- !dev_priv->ring_rptr->handle ||
- !dev->agp_buffer_map->handle) {
+ if (!dev_priv->is_pci) {
+ drm_core_ioremap(dev_priv->cp_ring, dev);
+ drm_core_ioremap(dev_priv->ring_rptr, dev);
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+ if (!dev_priv->cp_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev->agp_buffer_map->handle) {
DRM_ERROR("could not find ioremap agp regions!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
@@ -1445,217 +1491,251 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
} else
#endif
{
- dev_priv->cp_ring->handle =
- (void *)dev_priv->cp_ring->offset;
+ dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
dev_priv->ring_rptr->handle =
- (void *)dev_priv->ring_rptr->offset;
- dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
-
- DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
- dev_priv->cp_ring->handle );
- DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
- dev_priv->ring_rptr->handle );
- DRM_DEBUG( "dev->agp_buffer_map->handle %p\n",
- dev->agp_buffer_map->handle );
+ (void *)dev_priv->ring_rptr->offset;
+ dev->agp_buffer_map->handle =
+ (void *)dev->agp_buffer_map->offset;
+
+ DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
+ dev_priv->cp_ring->handle);
+ DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
+ dev_priv->ring_rptr->handle);
+ DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
+ dev->agp_buffer_map->handle);
}
- dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
- & 0xffff ) << 16;
-
- dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
- ( ( dev_priv->front_offset
- + dev_priv->fb_location ) >> 10 ) );
+ dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
+ & 0xffff) << 16;
- dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
- ( ( dev_priv->back_offset
- + dev_priv->fb_location ) >> 10 ) );
+ dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
+ ((dev_priv->front_offset
+ + dev_priv->fb_location) >> 10));
- dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
- ( ( dev_priv->depth_offset
- + dev_priv->fb_location ) >> 10 ) );
+ dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
+ ((dev_priv->back_offset
+ + dev_priv->fb_location) >> 10));
+ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
+ ((dev_priv->depth_offset
+ + dev_priv->fb_location) >> 10));
dev_priv->gart_size = init->gart_size;
dev_priv->gart_vm_start = dev_priv->fb_location
- + RADEON_READ( RADEON_CONFIG_APER_SIZE );
+ + RADEON_READ(RADEON_CONFIG_APER_SIZE);
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci )
+ if (!dev_priv->is_pci)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- - dev->agp->base
- + dev_priv->gart_vm_start);
+ - dev->agp->base
+ + dev_priv->gart_vm_start);
else
#endif
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- - dev->sg->handle
- + dev_priv->gart_vm_start);
-
- DRM_DEBUG( "dev_priv->gart_size %d\n",
- dev_priv->gart_size );
- DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n",
- dev_priv->gart_vm_start );
- DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n",
- dev_priv->gart_buffers_offset );
-
- dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
- dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
+ - (unsigned long)dev->sg->virtual
+ + dev_priv->gart_vm_start);
+
+ DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
+ DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
+ DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
+ dev_priv->gart_buffers_offset);
+
+ dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
+ dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+ init->ring_size / sizeof(u32));
dev_priv->ring.size = init->ring_size;
- dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+ dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
- dev_priv->ring.tail_mask =
- (dev_priv->ring.size / sizeof(u32)) - 1;
+ dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
+ if (!dev_priv->is_pci) {
/* Turn off PCI GART */
- radeon_set_pcigart( dev_priv, 0 );
+ radeon_set_pcigart(dev_priv, 0);
} else
#endif
{
- if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
- &dev_priv->bus_pci_gart)) {
- DRM_ERROR( "failed to init PCI GART!\n" );
+ /* if we have an offset set from userspace */
+ if (dev_priv->pcigart_offset) {
+ dev_priv->gart_info.bus_addr =
+ dev_priv->pcigart_offset + dev_priv->fb_location;
+ dev_priv->gart_info.addr =
+ (unsigned long)drm_ioremap(dev_priv->gart_info.
+ bus_addr,
+ RADEON_PCIGART_TABLE_SIZE,
+ dev);
+
+ dev_priv->gart_info.is_pcie =
+ !!(dev_priv->flags & CHIP_IS_PCIE);
+ dev_priv->gart_info.gart_table_location =
+ DRM_ATI_GART_FB;
+
+ DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",
+ dev_priv->gart_info.addr,
+ dev_priv->pcigart_offset);
+ } else {
+ dev_priv->gart_info.gart_table_location =
+ DRM_ATI_GART_MAIN;
+ dev_priv->gart_info.addr =
+ dev_priv->gart_info.bus_addr = 0;
+ if (dev_priv->flags & CHIP_IS_PCIE) {
+ DRM_ERROR
+ ("Cannot use PCI Express without GART in FB memory\n");
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+ DRM_ERROR("failed to init PCI GART!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
/* Turn on PCI GART */
- radeon_set_pcigart( dev_priv, 1 );
+ radeon_set_pcigart(dev_priv, 1);
}
- radeon_cp_load_microcode( dev_priv );
- radeon_cp_init_ring_buffer( dev, dev_priv );
+ radeon_cp_load_microcode(dev_priv);
+ radeon_cp_init_ring_buffer(dev, dev_priv);
dev_priv->last_buf = 0;
dev->dev_private = (void *)dev_priv;
- radeon_do_engine_reset( dev );
+ radeon_do_engine_reset(dev);
return 0;
}
-static int radeon_do_cleanup_cp( drm_device_t *dev )
+static int radeon_do_cleanup_cp(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
- if ( dev_priv->cp_ring != NULL )
- drm_core_ioremapfree( dev_priv->cp_ring, dev );
- if ( dev_priv->ring_rptr != NULL )
- drm_core_ioremapfree( dev_priv->ring_rptr, dev );
- if ( dev->agp_buffer_map != NULL )
- {
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
+ if (!dev_priv->is_pci) {
+ if (dev_priv->cp_ring != NULL)
+ drm_core_ioremapfree(dev_priv->cp_ring, dev);
+ if (dev_priv->ring_rptr != NULL)
+ drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+ if (dev->agp_buffer_map != NULL) {
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
dev->agp_buffer_map = NULL;
}
} else
#endif
{
- if (!drm_ati_pcigart_cleanup( dev,
- dev_priv->phys_pci_gart,
- dev_priv->bus_pci_gart ))
- DRM_ERROR( "failed to cleanup PCI GART!\n" );
+ if (dev_priv->gart_info.bus_addr)
+ if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
+ DRM_ERROR("failed to cleanup PCI GART!\n");
+
+ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
+ drm_ioremapfree((void *)dev_priv->gart_info.addr,
+ RADEON_PCIGART_TABLE_SIZE, dev);
+ dev_priv->gart_info.addr = 0;
+ }
}
-
+
/* only clear to the start of flags */
memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
return 0;
}
-/* This code will reinit the Radeon CP hardware after a resume from disc.
- * AFAIK, it would be very difficult to pickle the state at suspend time, so
+/* This code will reinit the Radeon CP hardware after a resume from disc.
+ * AFAIK, it would be very difficult to pickle the state at suspend time, so
* here we make sure that all Radeon hardware initialisation is re-done without
* affecting running applications.
*
* Charl P. Botha <http://cpbotha.net>
*/
-static int radeon_do_resume_cp( drm_device_t *dev )
+static int radeon_do_resume_cp(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- if ( !dev_priv ) {
- DRM_ERROR( "Called with no initialization\n" );
- return DRM_ERR( EINVAL );
+ if (!dev_priv) {
+ DRM_ERROR("Called with no initialization\n");
+ return DRM_ERR(EINVAL);
}
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __OS_HAS_AGP
- if ( !dev_priv->is_pci ) {
+ if (!dev_priv->is_pci) {
/* Turn off PCI GART */
- radeon_set_pcigart( dev_priv, 0 );
+ radeon_set_pcigart(dev_priv, 0);
} else
#endif
{
/* Turn on PCI GART */
- radeon_set_pcigart( dev_priv, 1 );
+ radeon_set_pcigart(dev_priv, 1);
}
- radeon_cp_load_microcode( dev_priv );
- radeon_cp_init_ring_buffer( dev, dev_priv );
+ radeon_cp_load_microcode(dev_priv);
+ radeon_cp_init_ring_buffer(dev, dev_priv);
- radeon_do_engine_reset( dev );
+ radeon_do_engine_reset(dev);
DRM_DEBUG("radeon_do_resume_cp() complete\n");
return 0;
}
-
-int radeon_cp_init( DRM_IOCTL_ARGS )
+int radeon_cp_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_init_t init;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data,
+ sizeof(init));
- DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t __user *)data, sizeof(init) );
+ if (init.func == RADEON_INIT_R300_CP)
+ r300_init_reg_flags();
- switch ( init.func ) {
+ switch (init.func) {
case RADEON_INIT_CP:
case RADEON_INIT_R200_CP:
case RADEON_INIT_R300_CP:
- return radeon_do_init_cp( dev, &init );
+ return radeon_do_init_cp(dev, &init);
case RADEON_CLEANUP_CP:
- return radeon_do_cleanup_cp( dev );
+ return radeon_do_cleanup_cp(dev);
}
return DRM_ERR(EINVAL);
}
-int radeon_cp_start( DRM_IOCTL_ARGS )
+int radeon_cp_start(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( dev_priv->cp_running ) {
- DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
+ if (dev_priv->cp_running) {
+ DRM_DEBUG("%s while CP running\n", __FUNCTION__);
return 0;
}
- if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
- DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
- __FUNCTION__, dev_priv->cp_mode );
+ if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
+ DRM_DEBUG("%s called with bogus CP mode (%d)\n",
+ __FUNCTION__, dev_priv->cp_mode);
return 0;
}
- radeon_do_cp_start( dev_priv );
+ radeon_do_cp_start(dev_priv);
return 0;
}
@@ -1663,17 +1743,18 @@ int radeon_cp_start( DRM_IOCTL_ARGS )
/* Stop the CP. The engine must have been idled before calling this
* routine.
*/
-int radeon_cp_stop( DRM_IOCTL_ARGS )
+int radeon_cp_stop(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_cp_stop_t stop;
int ret;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t __user *)data, sizeof(stop) );
+ DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data,
+ sizeof(stop));
if (!dev_priv->cp_running)
return 0;
@@ -1681,32 +1762,32 @@ int radeon_cp_stop( DRM_IOCTL_ARGS )
/* Flush any pending CP commands. This ensures any outstanding
* commands are exectuted by the engine before we turn it off.
*/
- if ( stop.flush ) {
- radeon_do_cp_flush( dev_priv );
+ if (stop.flush) {
+ radeon_do_cp_flush(dev_priv);
}
/* If we fail to make the engine go idle, we return an error
* code so that the DRM ioctl wrapper can try again.
*/
- if ( stop.idle ) {
- ret = radeon_do_cp_idle( dev_priv );
- if ( ret ) return ret;
+ if (stop.idle) {
+ ret = radeon_do_cp_idle(dev_priv);
+ if (ret)
+ return ret;
}
/* Finally, we can turn off the CP. If the engine isn't idle,
* we will get some dropped triangles as they won't be fully
* rendered before the CP is shut down.
*/
- radeon_do_cp_stop( dev_priv );
+ radeon_do_cp_stop(dev_priv);
/* Reset the engine */
- radeon_do_engine_reset( dev );
+ radeon_do_engine_reset(dev);
return 0;
}
-
-void radeon_do_release( drm_device_t *dev )
+void radeon_do_release(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int i, ret;
@@ -1714,7 +1795,7 @@ void radeon_do_release( drm_device_t *dev )
if (dev_priv) {
if (dev_priv->cp_running) {
/* Stop the cp */
- while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
+ while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
#ifdef __linux__
schedule();
@@ -1722,47 +1803,49 @@ void radeon_do_release( drm_device_t *dev )
tsleep(&ret, PZERO, "rdnrel", 1);
#endif
}
- radeon_do_cp_stop( dev_priv );
- radeon_do_engine_reset( dev );
+ radeon_do_cp_stop(dev_priv);
+ radeon_do_engine_reset(dev);
}
/* Disable *all* interrupts */
if (dev_priv->mmio) /* remove this after permanent addmaps */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
- if (dev_priv->mmio) {/* remove all surfaces */
+ if (dev_priv->mmio) { /* remove all surfaces */
for (i = 0; i < RADEON_MAX_SURFACES; i++) {
- RADEON_WRITE(RADEON_SURFACE0_INFO + 16*i, 0);
- RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*i, 0);
- RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*i, 0);
+ RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
+ RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
+ 16 * i, 0);
+ RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
+ 16 * i, 0);
}
}
/* Free memory heap structures */
- radeon_mem_takedown( &(dev_priv->gart_heap) );
- radeon_mem_takedown( &(dev_priv->fb_heap) );
+ radeon_mem_takedown(&(dev_priv->gart_heap));
+ radeon_mem_takedown(&(dev_priv->fb_heap));
/* deallocate kernel resources */
- radeon_do_cleanup_cp( dev );
+ radeon_do_cleanup_cp(dev);
}
}
/* Just reset the CP ring. Called as part of an X Server engine reset.
*/
-int radeon_cp_reset( DRM_IOCTL_ARGS )
+int radeon_cp_reset(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_DEBUG("%s called before init done\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- radeon_do_cp_reset( dev_priv );
+ radeon_do_cp_reset(dev_priv);
/* The CP is no longer running after an engine reset */
dev_priv->cp_running = 0;
@@ -1770,50 +1853,47 @@ int radeon_cp_reset( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_idle( DRM_IOCTL_ARGS )
+int radeon_cp_idle(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- return radeon_do_cp_idle( dev_priv );
+ return radeon_do_cp_idle(dev_priv);
}
/* Added by Charl P. Botha to call radeon_do_resume_cp().
*/
-int radeon_cp_resume( DRM_IOCTL_ARGS )
+int radeon_cp_resume(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
return radeon_do_resume_cp(dev);
}
-
-int radeon_engine_reset( DRM_IOCTL_ARGS )
+int radeon_engine_reset(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- return radeon_do_engine_reset( dev );
+ return radeon_do_engine_reset(dev);
}
-
/* ================================================================
* Fullscreen mode
*/
/* KW: Deprecated to say the least:
*/
-int radeon_fullscreen( DRM_IOCTL_ARGS )
+int radeon_fullscreen(DRM_IOCTL_ARGS)
{
return 0;
}
-
/* ================================================================
* Freelist management
*/
@@ -1822,20 +1902,20 @@ int radeon_fullscreen( DRM_IOCTL_ARGS )
* bufs until freelist code is used. Note this hides a problem with
* the scratch register * (used to keep track of last buffer
* completed) being written to before * the last buffer has actually
- * completed rendering.
+ * completed rendering.
*
* KW: It's also a good way to find free buffers quickly.
*
* KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
* sleep. However, bugs in older versions of radeon_accel.c mean that
* we essentially have to do this, else old clients will break.
- *
+ *
* However, it does leave open a potential deadlock where all the
* buffers are held by other clients, which can't release them because
- * they can't get the lock.
+ * they can't get the lock.
*/
-drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+drm_buf_t *radeon_freelist_get(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1844,19 +1924,19 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
int i, t;
int start;
- if ( ++dev_priv->last_buf >= dma->buf_count )
+ if (++dev_priv->last_buf >= dma->buf_count)
dev_priv->last_buf = 0;
start = dev_priv->last_buf;
- for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
- u32 done_age = GET_SCRATCH( 1 );
- DRM_DEBUG("done_age = %d\n",done_age);
- for ( i = start ; i < dma->buf_count ; i++ ) {
+ for (t = 0; t < dev_priv->usec_timeout; t++) {
+ u32 done_age = GET_SCRATCH(1);
+ DRM_DEBUG("done_age = %d\n", done_age);
+ for (i = start; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- if ( buf->filp == 0 || (buf->pending &&
- buf_priv->age <= done_age) ) {
+ if (buf->filp == 0 || (buf->pending &&
+ buf_priv->age <= done_age)) {
dev_priv->stats.requested_bufs++;
buf->pending = 0;
return buf;
@@ -1865,16 +1945,17 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
}
if (t) {
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
dev_priv->stats.freelist_loops++;
}
}
- DRM_DEBUG( "returning NULL!\n" );
+ DRM_DEBUG("returning NULL!\n");
return NULL;
}
+
#if 0
-drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+drm_buf_t *radeon_freelist_get(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1884,18 +1965,18 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
int start;
u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
- if ( ++dev_priv->last_buf >= dma->buf_count )
+ if (++dev_priv->last_buf >= dma->buf_count)
dev_priv->last_buf = 0;
start = dev_priv->last_buf;
dev_priv->stats.freelist_loops++;
-
- for ( t = 0 ; t < 2 ; t++ ) {
- for ( i = start ; i < dma->buf_count ; i++ ) {
+
+ for (t = 0; t < 2; t++) {
+ for (i = start; i < dma->buf_count; i++) {
buf = dma->buflist[i];
buf_priv = buf->dev_private;
- if ( buf->filp == 0 || (buf->pending &&
- buf_priv->age <= done_age) ) {
+ if (buf->filp == 0 || (buf->pending &&
+ buf_priv->age <= done_age)) {
dev_priv->stats.requested_bufs++;
buf->pending = 0;
return buf;
@@ -1908,73 +1989,74 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
}
#endif
-void radeon_freelist_reset( drm_device_t *dev )
+void radeon_freelist_reset(drm_device_t * dev)
{
drm_device_dma_t *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
int i;
dev_priv->last_buf = 0;
- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[i];
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->age = 0;
}
}
-
/* ================================================================
* CP command submission
*/
-int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
+int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
{
drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
int i;
- u32 last_head = GET_RING_HEAD( dev_priv );
+ u32 last_head = GET_RING_HEAD(dev_priv);
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- u32 head = GET_RING_HEAD( dev_priv );
+ for (i = 0; i < dev_priv->usec_timeout; i++) {
+ u32 head = GET_RING_HEAD(dev_priv);
ring->space = (head - ring->tail) * sizeof(u32);
- if ( ring->space <= 0 )
+ if (ring->space <= 0)
ring->space += ring->size;
- if ( ring->space > n )
+ if (ring->space > n)
return 0;
-
+
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
if (head != last_head)
i = 0;
last_head = head;
- DRM_UDELAY( 1 );
+ DRM_UDELAY(1);
}
/* FIXME: This return value is ignored in the BEGIN_RING macro! */
#if RADEON_FIFO_DEBUG
- radeon_status( dev_priv );
- DRM_ERROR( "failed!\n" );
+ radeon_status(dev_priv);
+ DRM_ERROR("failed!\n");
#endif
return DRM_ERR(EBUSY);
}
-static int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
+static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
+ drm_dma_t * d)
{
int i;
drm_buf_t *buf;
- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
- buf = radeon_freelist_get( dev );
- if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = radeon_freelist_get(dev);
+ if (!buf)
+ return DRM_ERR(EBUSY); /* NOTE: broken client */
buf->filp = filp;
- if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
- sizeof(buf->idx) ) )
+ if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+ sizeof(buf->idx)))
return DRM_ERR(EFAULT);
- if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
- sizeof(buf->total) ) )
+ if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+ sizeof(buf->total)))
return DRM_ERR(EFAULT);
d->granted_count++;
@@ -1982,7 +2064,7 @@ static int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d
return 0;
}
-int radeon_cp_buffers( DRM_IOCTL_ARGS )
+int radeon_cp_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -1990,33 +2072,33 @@ int radeon_cp_buffers( DRM_IOCTL_ARGS )
drm_dma_t __user *argp = (void __user *)data;
drm_dma_t d;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
+ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
/* Please don't send us buffers.
*/
- if ( d.send_count != 0 ) {
- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
- DRM_CURRENTPID, d.send_count );
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d.send_count);
return DRM_ERR(EINVAL);
}
/* We'll send you buffers.
*/
- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
- DRM_CURRENTPID, d.request_count, dma->buf_count );
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d.request_count, dma->buf_count);
return DRM_ERR(EINVAL);
}
d.granted_count = 0;
- if ( d.request_count ) {
- ret = radeon_cp_get_buffers( filp, dev, &d );
+ if (d.request_count) {
+ ret = radeon_cp_get_buffers(filp, dev, &d);
}
- DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
+ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
return ret;
}
@@ -2039,15 +2121,46 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
case CHIP_RV200:
case CHIP_R200:
case CHIP_R300:
+ case CHIP_R420:
dev_priv->flags |= CHIP_HAS_HIERZ;
break;
default:
- /* all other chips have no hierarchical z buffer */
+ /* all other chips have no hierarchical z buffer */
break;
}
+
+ if (drm_device_is_agp(dev))
+ dev_priv->flags |= CHIP_IS_AGP;
+
+ if (drm_device_is_pcie(dev))
+ dev_priv->flags |= CHIP_IS_PCIE;
+
+ DRM_DEBUG("%s card detected\n",
+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
return ret;
}
+int radeon_presetup(struct drm_device *dev)
+{
+ int ret;
+ drm_local_map_t *map;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+ drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+ _DRM_READ_ONLY, &dev_priv->mmio);
+ if (ret != 0)
+ return ret;
+
+ ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
+ drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
+ _DRM_WRITE_COMBINING, &map);
+ if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
int radeon_driver_postcleanup(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index c1e62d047989..1cd81a671a36 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -57,78 +57,77 @@
#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
-#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
+#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
#define RADEON_REQUIRE_QUIESCENCE 0x00010000
-#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
+#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
#define RADEON_UPLOAD_ALL 0x003effff
#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff
-
/* New style per-packet identifiers for use in cmd_buffer ioctl with
* the RADEON_EMIT_PACKET command. Comments relate new packets to old
* state bits and the packet size:
*/
-#define RADEON_EMIT_PP_MISC 0 /* context/7 */
-#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
-#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
-#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
-#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
-#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
-#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
-#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
-#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
-#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
-#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
-#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
-#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
-#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
-#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
-#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
-#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
-#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
-#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
-#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
-#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
-#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
-#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
-#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
-#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
-#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
-#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
-#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
-#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
-#define R200_EMIT_VAP_CTL 32 /* vap/1 */
-#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
-#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
-#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
-#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
-#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
-#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
-#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
-#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
-#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
-#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
-#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
-#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
-#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
-#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
-#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
-#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
-#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
-#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
-#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
-#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
-#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
-#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
-#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
-#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
-#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
-#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
-#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
-#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
+#define RADEON_EMIT_PP_MISC 0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
+#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
+#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
+#define R200_EMIT_VAP_CTL 32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
#define R200_EMIT_PP_CUBIC_FACES_0 61
#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
#define R200_EMIT_PP_CUBIC_FACES_1 63
@@ -153,48 +152,102 @@
#define RADEON_EMIT_PP_CUBIC_FACES_2 82
#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83
#define R200_EMIT_PP_TRI_PERF_CNTL 84
-#define RADEON_MAX_STATE_PACKETS 85
+#define R200_EMIT_PP_AFS_0 85
+#define R200_EMIT_PP_AFS_1 86
+#define R200_EMIT_ATF_TFACTOR 87
+#define R200_EMIT_PP_TXCTLALL_0 88
+#define R200_EMIT_PP_TXCTLALL_1 89
+#define R200_EMIT_PP_TXCTLALL_2 90
+#define R200_EMIT_PP_TXCTLALL_3 91
+#define R200_EMIT_PP_TXCTLALL_4 92
+#define R200_EMIT_PP_TXCTLALL_5 93
+#define RADEON_MAX_STATE_PACKETS 94
/* Commands understood by cmd_buffer ioctl. More can be added but
* obviously these can't be removed or changed:
*/
-#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
-#define RADEON_CMD_SCALARS 2 /* emit scalar data */
-#define RADEON_CMD_VECTORS 3 /* emit vector data */
-#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
-#define RADEON_CMD_PACKET3 5 /* emit hw packet */
-#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
-#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
-#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
- * doesn't make the cpu wait, just
- * the graphics hardware */
-
+#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS 2 /* emit scalar data */
+#define RADEON_CMD_VECTORS 3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3 5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
+#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
+ * doesn't make the cpu wait, just
+ * the graphics hardware */
typedef union {
int i;
- struct {
+ struct {
unsigned char cmd_type, pad0, pad1, pad2;
} header;
- struct {
+ struct {
unsigned char cmd_type, packet_id, pad0, pad1;
} packet;
- struct {
- unsigned char cmd_type, offset, stride, count;
+ struct {
+ unsigned char cmd_type, offset, stride, count;
} scalars;
- struct {
- unsigned char cmd_type, offset, stride, count;
+ struct {
+ unsigned char cmd_type, offset, stride, count;
} vectors;
- struct {
- unsigned char cmd_type, buf_idx, pad0, pad1;
+ struct {
+ unsigned char cmd_type, buf_idx, pad0, pad1;
} dma;
- struct {
- unsigned char cmd_type, flags, pad0, pad1;
+ struct {
+ unsigned char cmd_type, flags, pad0, pad1;
} wait;
} drm_radeon_cmd_header_t;
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
+/* Allowed parameters for R300_CMD_PACKET3
+ */
+#define R300_CMD_PACKET3_CLEAR 0
+#define R300_CMD_PACKET3_RAW 1
+
+/* Commands understood by cmd_buffer ioctl for R300.
+ * The interface has not been stabilized, so some of these may be removed
+ * and eventually reordered before stabilization.
+ */
+#define R300_CMD_PACKET0 1
+#define R300_CMD_VPU 2 /* emit vertex program upload */
+#define R300_CMD_PACKET3 3 /* emit a packet3 */
+#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */
+#define R300_CMD_CP_DELAY 5
+#define R300_CMD_DMA_DISCARD 6
+#define R300_CMD_WAIT 7
+# define R300_WAIT_2D 0x1
+# define R300_WAIT_3D 0x2
+# define R300_WAIT_2D_CLEAN 0x3
+# define R300_WAIT_3D_CLEAN 0x4
+
+typedef union {
+ unsigned int u;
+ struct {
+ unsigned char cmd_type, pad0, pad1, pad2;
+ } header;
+ struct {
+ unsigned char cmd_type, count, reglo, reghi;
+ } packet0;
+ struct {
+ unsigned char cmd_type, count, adrlo, adrhi;
+ } vpu;
+ struct {
+ unsigned char cmd_type, packet, pad0, pad1;
+ } packet3;
+ struct {
+ unsigned char cmd_type, packet;
+ unsigned short count; /* amount of packet2 to emit */
+ } delay;
+ struct {
+ unsigned char cmd_type, buf_idx, pad0, pad1;
+ } dma;
+ struct {
+ unsigned char cmd_type, flags, pad0, pad1;
+ } wait;
+} drm_r300_cmd_header_t;
#define RADEON_FRONT 0x1
#define RADEON_BACK 0x2
@@ -246,7 +299,7 @@ typedef union {
#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
-#endif /* __RADEON_SAREA_DEFINES__ */
+#endif /* __RADEON_SAREA_DEFINES__ */
typedef struct {
unsigned int red;
@@ -257,7 +310,7 @@ typedef struct {
typedef struct {
/* Context state */
- unsigned int pp_misc; /* 0x1c14 */
+ unsigned int pp_misc; /* 0x1c14 */
unsigned int pp_fog_color;
unsigned int re_solid_color;
unsigned int rb3d_blendcntl;
@@ -265,7 +318,7 @@ typedef struct {
unsigned int rb3d_depthpitch;
unsigned int rb3d_zstencilcntl;
- unsigned int pp_cntl; /* 0x1c38 */
+ unsigned int pp_cntl; /* 0x1c38 */
unsigned int rb3d_cntl;
unsigned int rb3d_coloroffset;
unsigned int re_width_height;
@@ -273,27 +326,27 @@ typedef struct {
unsigned int se_cntl;
/* Vertex format state */
- unsigned int se_coord_fmt; /* 0x1c50 */
+ unsigned int se_coord_fmt; /* 0x1c50 */
/* Line state */
- unsigned int re_line_pattern; /* 0x1cd0 */
+ unsigned int re_line_pattern; /* 0x1cd0 */
unsigned int re_line_state;
- unsigned int se_line_width; /* 0x1db8 */
+ unsigned int se_line_width; /* 0x1db8 */
/* Bumpmap state */
- unsigned int pp_lum_matrix; /* 0x1d00 */
+ unsigned int pp_lum_matrix; /* 0x1d00 */
- unsigned int pp_rot_matrix_0; /* 0x1d58 */
+ unsigned int pp_rot_matrix_0; /* 0x1d58 */
unsigned int pp_rot_matrix_1;
/* Mask state */
- unsigned int rb3d_stencilrefmask; /* 0x1d7c */
+ unsigned int rb3d_stencilrefmask; /* 0x1d7c */
unsigned int rb3d_ropcntl;
unsigned int rb3d_planemask;
/* Viewport state */
- unsigned int se_vport_xscale; /* 0x1d98 */
+ unsigned int se_vport_xscale; /* 0x1d98 */
unsigned int se_vport_xoffset;
unsigned int se_vport_yscale;
unsigned int se_vport_yoffset;
@@ -301,20 +354,19 @@ typedef struct {
unsigned int se_vport_zoffset;
/* Setup state */
- unsigned int se_cntl_status; /* 0x2140 */
+ unsigned int se_cntl_status; /* 0x2140 */
/* Misc state */
- unsigned int re_top_left; /* 0x26c0 */
+ unsigned int re_top_left; /* 0x26c0 */
unsigned int re_misc;
} drm_radeon_context_regs_t;
typedef struct {
/* Zbias state */
- unsigned int se_zbias_factor; /* 0x1dac */
+ unsigned int se_zbias_factor; /* 0x1dac */
unsigned int se_zbias_constant;
} drm_radeon_context2_regs_t;
-
/* Setup registers for each texture unit
*/
typedef struct {
@@ -332,11 +384,10 @@ typedef struct {
unsigned int finish;
unsigned int prim:8;
unsigned int stateidx:8;
- unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
- unsigned int vc_format; /* vertex format */
+ unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
+ unsigned int vc_format; /* vertex format */
} drm_radeon_prim_t;
-
typedef struct {
drm_radeon_context_regs_t context;
drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
@@ -344,7 +395,6 @@ typedef struct {
unsigned int dirty;
} drm_radeon_state_t;
-
typedef struct {
/* The channel for communication of state information to the
* kernel on firing a vertex buffer with either of the
@@ -367,16 +417,16 @@ typedef struct {
unsigned int last_dispatch;
unsigned int last_clear;
- drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+ drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+ 1];
unsigned int tex_age[RADEON_NR_TEX_HEAPS];
int ctx_owner;
- int pfState; /* number of 3d windows (0,1,2ormore) */
- int pfCurrentPage; /* which buffer is being displayed? */
- int crtc2_base; /* CRTC2 frame offset */
+ int pfState; /* number of 3d windows (0,1,2ormore) */
+ int pfCurrentPage; /* which buffer is being displayed? */
+ int crtc2_base; /* CRTC2 frame offset */
int tiling_enabled; /* set by drm, read by 2d + 3d clients */
} drm_radeon_sarea_t;
-
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmRadeon.h)
*
@@ -386,15 +436,15 @@ typedef struct {
/* Radeon specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
-#define DRM_RADEON_CP_INIT 0x00
-#define DRM_RADEON_CP_START 0x01
+#define DRM_RADEON_CP_INIT 0x00
+#define DRM_RADEON_CP_START 0x01
#define DRM_RADEON_CP_STOP 0x02
#define DRM_RADEON_CP_RESET 0x03
#define DRM_RADEON_CP_IDLE 0x04
-#define DRM_RADEON_RESET 0x05
+#define DRM_RADEON_RESET 0x05
#define DRM_RADEON_FULLSCREEN 0x06
-#define DRM_RADEON_SWAP 0x07
-#define DRM_RADEON_CLEAR 0x08
+#define DRM_RADEON_SWAP 0x07
+#define DRM_RADEON_CLEAR 0x08
#define DRM_RADEON_VERTEX 0x09
#define DRM_RADEON_INDICES 0x0A
#define DRM_RADEON_NOT_USED
@@ -445,7 +495,7 @@ typedef struct {
typedef struct drm_radeon_init {
enum {
- RADEON_INIT_CP = 0x01,
+ RADEON_INIT_CP = 0x01,
RADEON_CLEANUP_CP = 0x02,
RADEON_INIT_R200_CP = 0x03,
RADEON_INIT_R300_CP = 0x04
@@ -478,7 +528,7 @@ typedef struct drm_radeon_cp_stop {
typedef struct drm_radeon_fullscreen {
enum {
- RADEON_INIT_FULLSCREEN = 0x01,
+ RADEON_INIT_FULLSCREEN = 0x01,
RADEON_CLEANUP_FULLSCREEN = 0x02
} func;
} drm_radeon_fullscreen_t;
@@ -499,15 +549,15 @@ typedef struct drm_radeon_clear {
unsigned int clear_color;
unsigned int clear_depth;
unsigned int color_mask;
- unsigned int depth_mask; /* misnamed field: should be stencil */
+ unsigned int depth_mask; /* misnamed field: should be stencil */
drm_radeon_clear_rect_t __user *depth_boxes;
} drm_radeon_clear_t;
typedef struct drm_radeon_vertex {
int prim;
- int idx; /* Index of vertex buffer */
- int count; /* Number of vertices in buffer */
- int discard; /* Client finished with buffer? */
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
} drm_radeon_vertex_t;
typedef struct drm_radeon_indices {
@@ -515,7 +565,7 @@ typedef struct drm_radeon_indices {
int idx;
int start;
int end;
- int discard; /* Client finished with buffer? */
+ int discard; /* Client finished with buffer? */
} drm_radeon_indices_t;
/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
@@ -523,8 +573,8 @@ typedef struct drm_radeon_indices {
* - supports driver change to emit native primitives
*/
typedef struct drm_radeon_vertex2 {
- int idx; /* Index of vertex buffer */
- int discard; /* Client finished with buffer? */
+ int idx; /* Index of vertex buffer */
+ int discard; /* Client finished with buffer? */
int nr_states;
drm_radeon_state_t __user *state;
int nr_prims;
@@ -532,10 +582,10 @@ typedef struct drm_radeon_vertex2 {
} drm_radeon_vertex2_t;
/* v1.3 - obsoletes drm_radeon_vertex2
- * - allows arbitarily large cliprect list
+ * - allows arbitarily large cliprect list
* - allows updating of tcl packet, vector and scalar state
* - allows memory-efficient description of state updates
- * - allows state to be emitted without a primitive
+ * - allows state to be emitted without a primitive
* (for clears, ctx switches)
* - allows more than one dma buffer to be referenced per ioctl
* - supports tcl driver
@@ -549,7 +599,7 @@ typedef struct drm_radeon_cmd_buffer {
} drm_radeon_cmd_buffer_t;
typedef struct drm_radeon_tex_image {
- unsigned int x, y; /* Blit coordinates */
+ unsigned int x, y; /* Blit coordinates */
unsigned int width, height;
const void __user *data;
} drm_radeon_tex_image_t;
@@ -558,7 +608,7 @@ typedef struct drm_radeon_texture {
unsigned int offset;
int pitch;
int format;
- int width; /* Texture image coordinates */
+ int width; /* Texture image coordinates */
int height;
drm_radeon_tex_image_t __user *image;
} drm_radeon_texture_t;
@@ -574,19 +624,18 @@ typedef struct drm_radeon_indirect {
int discard;
} drm_radeon_indirect_t;
-
/* 1.3: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
+ * client any other way.
*/
-#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
+#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
#define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 4
/* Added with DRM version 1.6. */
#define RADEON_PARAM_IRQ_NR 5
-#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
+#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
/* Added with DRM version 1.8. */
-#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
+#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
#define RADEON_PARAM_STATUS_HANDLE 8
#define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10
@@ -617,10 +666,9 @@ typedef struct drm_radeon_mem_free {
typedef struct drm_radeon_mem_init_heap {
int region;
int size;
- int start;
+ int start;
} drm_radeon_mem_init_heap_t;
-
/* 1.6: Userspace can request & wait on irq's:
*/
typedef struct drm_radeon_irq_emit {
@@ -631,18 +679,18 @@ typedef struct drm_radeon_irq_wait {
int irq_seq;
} drm_radeon_irq_wait_t;
-
/* 1.10: Clients tell the DRM where they think the framebuffer is located in
* the card's address space, via a new generic ioctl to set parameters
*/
typedef struct drm_radeon_setparam {
unsigned int param;
- int64_t value;
+ int64_t value;
} drm_radeon_setparam_t;
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
+#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
/* 1.14: Clients can allocate/free a surface
*/
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 18e4e5b0952f..ee49670d8162 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -29,7 +29,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-
#include <linux/config.h>
#include "drmP.h"
#include "drm.h"
@@ -38,30 +37,33 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+int radeon_no_wb;
+
+MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
+module_param_named(no_wb, radeon_no_wb, int, 0444);
+
+static int postinit(struct drm_device *dev, unsigned long flags)
{
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -69,13 +71,14 @@ static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
-extern drm_ioctl_desc_t radeon_ioctls[];
-extern int radeon_max_ioctl;
-
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_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+ DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
+ DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.preinit = radeon_driver_preinit,
+ .presetup = radeon_presetup,
.postcleanup = radeon_driver_postcleanup,
.prerelease = radeon_driver_prerelease,
.pretakedown = radeon_driver_pretakedown,
@@ -94,21 +97,22 @@ static struct drm_driver driver = {
.ioctls = radeon_ioctls,
.dma_ioctl = radeon_cp_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 = radeon_compat_ioctl,
+ .compat_ioctl = radeon_compat_ioctl,
#endif
- },
+ }
+ ,
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ }
};
static int __init radeon_init(void)
@@ -125,6 +129,6 @@ static void __exit radeon_exit(void)
module_init(radeon_init);
module_exit(radeon_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 771aa80a5e8c..120ee5a8ebcc 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
-#define DRIVER_DATE "20050311"
+#define DRIVER_DATE "20050911"
/* Interface history:
*
@@ -68,7 +68,7 @@
* 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
* Add texture rectangle support for r100.
* 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
- * clients use to tell the DRM where they think the framebuffer is
+ * clients use to tell the DRM where they think the framebuffer is
* located in the card's address space
* 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
* and GL_EXT_blend_[func|equation]_separate on r200
@@ -82,9 +82,15 @@
* - Add support for r100 cube maps
* 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
* texture filtering on r200
+ * 1.17- Add initial support for R300 (3D).
+ * 1.18- Add support for GL_ATI_fragment_shader, new packets
+ * R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces
+ * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
+ * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
+ * 1.19- Add support for gart table in FB memory and PCIE r300
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 16
+#define DRIVER_MINOR 19
#define DRIVER_PATCHLEVEL 0
#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
@@ -106,7 +112,9 @@ enum radeon_family {
CHIP_RV280,
CHIP_R300,
CHIP_RS300,
+ CHIP_R350,
CHIP_RV350,
+ CHIP_R420,
CHIP_LAST,
};
@@ -126,14 +134,15 @@ enum radeon_chip_flags {
CHIP_IS_IGP = 0x00020000UL,
CHIP_SINGLE_CRTC = 0x00040000UL,
CHIP_IS_AGP = 0x00080000UL,
- CHIP_HAS_HIERZ = 0x00100000UL,
+ CHIP_HAS_HIERZ = 0x00100000UL,
+ CHIP_IS_PCIE = 0x00200000UL,
};
typedef struct drm_radeon_freelist {
- unsigned int age;
- drm_buf_t *buf;
- struct drm_radeon_freelist *next;
- struct drm_radeon_freelist *prev;
+ unsigned int age;
+ drm_buf_t *buf;
+ struct drm_radeon_freelist *next;
+ struct drm_radeon_freelist *prev;
} drm_radeon_freelist_t;
typedef struct drm_radeon_ring_buffer {
@@ -195,8 +204,8 @@ typedef struct drm_radeon_private {
int cp_mode;
int cp_running;
- drm_radeon_freelist_t *head;
- drm_radeon_freelist_t *tail;
+ drm_radeon_freelist_t *head;
+ drm_radeon_freelist_t *tail;
int last_buf;
volatile u32 *scratch;
int writeback_works;
@@ -206,8 +215,6 @@ typedef struct drm_radeon_private {
int microcode_version;
int is_pci;
- unsigned long phys_pci_gart;
- dma_addr_t bus_pci_gart;
struct {
u32 boxes;
@@ -239,7 +246,7 @@ typedef struct drm_radeon_private {
u32 depth_pitch_offset;
drm_radeon_depth_clear_t depth_clear;
-
+
unsigned long fb_offset;
unsigned long mmio_offset;
unsigned long ring_offset;
@@ -257,11 +264,14 @@ typedef struct drm_radeon_private {
struct mem_block *fb_heap;
/* SW interrupt */
- wait_queue_head_t swi_queue;
- atomic_t swi_emitted;
+ wait_queue_head_t swi_queue;
+ atomic_t swi_emitted;
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
- struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
+ struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
+
+ unsigned long pcigart_offset;
+ drm_ati_pcigart_info gart_info;
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
@@ -271,55 +281,77 @@ typedef struct drm_radeon_buf_priv {
u32 age;
} drm_radeon_buf_priv_t;
+typedef struct drm_radeon_kcmd_buffer {
+ int bufsz;
+ char *buf;
+ int nbox;
+ drm_clip_rect_t __user *boxes;
+} drm_radeon_kcmd_buffer_t;
+
+extern int radeon_no_wb;
+extern drm_ioctl_desc_t radeon_ioctls[];
+extern int radeon_max_ioctl;
+
/* radeon_cp.c */
-extern int radeon_cp_init( DRM_IOCTL_ARGS );
-extern int radeon_cp_start( DRM_IOCTL_ARGS );
-extern int radeon_cp_stop( DRM_IOCTL_ARGS );
-extern int radeon_cp_reset( DRM_IOCTL_ARGS );
-extern int radeon_cp_idle( DRM_IOCTL_ARGS );
-extern int radeon_cp_resume( DRM_IOCTL_ARGS );
-extern int radeon_engine_reset( DRM_IOCTL_ARGS );
-extern int radeon_fullscreen( DRM_IOCTL_ARGS );
-extern int radeon_cp_buffers( DRM_IOCTL_ARGS );
+extern int radeon_cp_init(DRM_IOCTL_ARGS);
+extern int radeon_cp_start(DRM_IOCTL_ARGS);
+extern int radeon_cp_stop(DRM_IOCTL_ARGS);
+extern int radeon_cp_reset(DRM_IOCTL_ARGS);
+extern int radeon_cp_idle(DRM_IOCTL_ARGS);
+extern int radeon_cp_resume(DRM_IOCTL_ARGS);
+extern int radeon_engine_reset(DRM_IOCTL_ARGS);
+extern int radeon_fullscreen(DRM_IOCTL_ARGS);
+extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
-extern void radeon_freelist_reset( drm_device_t *dev );
-extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
+extern void radeon_freelist_reset(drm_device_t * dev);
+extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
-extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
+extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
-extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
+extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
+extern int radeon_presetup(struct drm_device *dev);
extern int radeon_driver_postcleanup(struct drm_device *dev);
-extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
-extern int radeon_mem_free( DRM_IOCTL_ARGS );
-extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
-extern void radeon_mem_takedown( struct mem_block **heap );
-extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
+extern int radeon_mem_alloc(DRM_IOCTL_ARGS);
+extern int radeon_mem_free(DRM_IOCTL_ARGS);
+extern int radeon_mem_init_heap(DRM_IOCTL_ARGS);
+extern void radeon_mem_takedown(struct mem_block **heap);
+extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap);
/* radeon_irq.c */
-extern int radeon_irq_emit( DRM_IOCTL_ARGS );
-extern int radeon_irq_wait( DRM_IOCTL_ARGS );
-
-extern void radeon_do_release(drm_device_t *dev);
-extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
-extern void radeon_driver_irq_preinstall( drm_device_t *dev );
-extern void radeon_driver_irq_postinstall( drm_device_t *dev );
-extern void radeon_driver_irq_uninstall( drm_device_t *dev );
-extern void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp);
-extern void radeon_driver_pretakedown(drm_device_t *dev);
-extern int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv);
-extern void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv);
-
-extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
-extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
-extern int radeon_postcleanup( struct drm_device *dev );
+extern int radeon_irq_emit(DRM_IOCTL_ARGS);
+extern int radeon_irq_wait(DRM_IOCTL_ARGS);
+
+extern void radeon_do_release(drm_device_t * dev);
+extern int radeon_driver_vblank_wait(drm_device_t * dev,
+ unsigned int *sequence);
+extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+extern void radeon_driver_irq_preinstall(drm_device_t * dev);
+extern void radeon_driver_irq_postinstall(drm_device_t * dev);
+extern void radeon_driver_irq_uninstall(drm_device_t * dev);
+extern void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+extern void radeon_driver_pretakedown(drm_device_t * dev);
+extern int radeon_driver_open_helper(drm_device_t * dev,
+ drm_file_t * filp_priv);
+extern void radeon_driver_free_filp_priv(drm_device_t * dev,
+ drm_file_t * filp_priv);
+
+extern int radeon_preinit(struct drm_device *dev, unsigned long flags);
+extern int radeon_postinit(struct drm_device *dev, unsigned long flags);
+extern int radeon_postcleanup(struct drm_device *dev);
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
+/* r300_cmdbuf.c */
+extern void r300_init_reg_flags(void);
+
+extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
+ drm_file_t * filp_priv,
+ drm_radeon_kcmd_buffer_t * cmdbuf);
+
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
@@ -328,8 +360,6 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_BOX_WAIT_IDLE 0x8
#define RADEON_BOX_TEXTURE_LOAD 0x10
-
-
/* Register definitions, register access macros and drmAddMap constants
* for Radeon kernel driver.
*/
@@ -357,6 +387,30 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_CRTC2_OFFSET 0x0324
#define RADEON_CRTC2_OFFSET_CNTL 0x0328
+#define RADEON_PCIE_INDEX 0x0030
+#define RADEON_PCIE_DATA 0x0034
+#define RADEON_PCIE_TX_GART_CNTL 0x10
+# define RADEON_PCIE_TX_GART_EN (1 << 0)
+# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0<<1)
+# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1<<1)
+# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3<<1)
+# define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0<<3)
+# define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1<<3)
+# define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1<<5)
+# define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1<<8)
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
+#define RADEON_PCIE_TX_GART_BASE 0x13
+#define RADEON_PCIE_TX_GART_START_LO 0x14
+#define RADEON_PCIE_TX_GART_START_HI 0x15
+#define RADEON_PCIE_TX_GART_END_LO 0x16
+#define RADEON_PCIE_TX_GART_END_HI 0x17
+
+#define RADEON_MPP_TB_CONFIG 0x01c0
+#define RADEON_MEM_CNTL 0x0140
+#define RADEON_MEM_SDRAM_MODE_REG 0x0158
+#define RADEON_AGP_BASE 0x0170
+
#define RADEON_RB3D_COLOROFFSET 0x1c40
#define RADEON_RB3D_COLORPITCH 0x1c48
@@ -399,7 +453,6 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
-
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
@@ -607,7 +660,6 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
-
/* CP registers */
#define RADEON_CP_ME_RAM_ADDR 0x07d4
#define RADEON_CP_ME_RAM_RADDR 0x07d8
@@ -651,16 +703,27 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_CP_PACKET1 0x40000000
#define RADEON_CP_PACKET2 0x80000000
#define RADEON_CP_PACKET3 0xC0000000
+# define RADEON_CP_NOP 0x00001000
+# define RADEON_CP_NEXT_CHAR 0x00001900
+# define RADEON_CP_PLY_NEXTSCAN 0x00001D00
+# define RADEON_CP_SET_SCISSORS 0x00001E00
+ /* GEN_INDX_PRIM is unsupported starting with R300 */
# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
# define RADEON_WAIT_FOR_IDLE 0x00002600
# define RADEON_3D_DRAW_VBUF 0x00002800
# define RADEON_3D_DRAW_IMMD 0x00002900
# define RADEON_3D_DRAW_INDX 0x00002A00
+# define RADEON_CP_LOAD_PALETTE 0x00002C00
# define RADEON_3D_LOAD_VBPNTR 0x00002F00
# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000
# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100
# define RADEON_3D_CLEAR_ZMASK 0x00003200
+# define RADEON_CP_INDX_BUFFER 0x00003300
+# define RADEON_CP_3D_DRAW_VBUF_2 0x00003400
+# define RADEON_CP_3D_DRAW_IMMD_2 0x00003500
+# define RADEON_CP_3D_DRAW_INDX_2 0x00003600
# define RADEON_3D_CLEAR_HIZ 0x00003700
+# define RADEON_CP_3D_CLEAR_CMASK 0x00003802
# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
# define RADEON_CNTL_PAINT_MULTI 0x00009A00
# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
@@ -728,19 +791,19 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define R200_PP_TXCBLEND_5 0x2f50
#define R200_PP_TXCBLEND_6 0x2f60
#define R200_PP_TXCBLEND_7 0x2f70
-#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268
+#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268
#define R200_PP_TFACTOR_0 0x2ee0
#define R200_SE_VTX_FMT_0 0x2088
#define R200_SE_VAP_CNTL 0x2080
#define R200_SE_TCL_MATRIX_SEL_0 0x2230
-#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8
-#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0
-#define R200_PP_TXFILTER_5 0x2ca0
-#define R200_PP_TXFILTER_4 0x2c80
-#define R200_PP_TXFILTER_3 0x2c60
-#define R200_PP_TXFILTER_2 0x2c40
-#define R200_PP_TXFILTER_1 0x2c20
-#define R200_PP_TXFILTER_0 0x2c00
+#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8
+#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0
+#define R200_PP_TXFILTER_5 0x2ca0
+#define R200_PP_TXFILTER_4 0x2c80
+#define R200_PP_TXFILTER_3 0x2c60
+#define R200_PP_TXFILTER_2 0x2c40
+#define R200_PP_TXFILTER_1 0x2c20
+#define R200_PP_TXFILTER_0 0x2c00
#define R200_PP_TXOFFSET_5 0x2d78
#define R200_PP_TXOFFSET_4 0x2d60
#define R200_PP_TXOFFSET_3 0x2d48
@@ -794,13 +857,13 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define R200_RE_SCISSOR_TL_0 0x1cd8
#define R200_RE_SCISSOR_TL_1 0x1ce0
#define R200_RE_SCISSOR_TL_2 0x1ce8
-#define R200_RB3D_DEPTHXY_OFFSET 0x1d60
+#define R200_RB3D_DEPTHXY_OFFSET 0x1d60
#define R200_RE_AUX_SCISSOR_CNTL 0x26f0
#define R200_SE_VTX_STATE_CNTL 0x2180
#define R200_RE_POINTSIZE 0x2648
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
-#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
+#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
#define RADEON_PP_TEX_SIZE_1 0x1d0c
#define RADEON_PP_TEX_SIZE_2 0x1d14
@@ -821,7 +884,7 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b
#define R200_3D_DRAW_IMMD_2 0xC0003500
#define R200_SE_VTX_FMT_1 0x208c
-#define R200_RE_CNTL 0x1c50
+#define R200_RE_CNTL 0x1c50
#define R200_RB3D_BLENDCOLOR 0x3218
@@ -829,6 +892,9 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define R200_PP_TRI_PERF 0x2cf8
+#define R200_PP_AFS_0 0x2f80
+#define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */
+
/* Constants */
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
@@ -843,6 +909,8 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
#define RADEON_RING_HIGH_MARK 128
+#define RADEON_PCIGART_TABLE_SIZE (32*1024)
+
#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
@@ -855,6 +923,13 @@ do { \
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
} while (0)
+#define RADEON_WRITE_PCIE( addr, val ) \
+do { \
+ RADEON_WRITE8( RADEON_PCIE_INDEX, \
+ ((addr) & 0xff)); \
+ RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \
+} while (0)
+
#define CP_PACKET0( reg, n ) \
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CP_PACKET0_TABLE( reg, n ) \
@@ -866,7 +941,6 @@ do { \
#define CP_PACKET3( pkt, n ) \
(RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
-
/* ================================================================
* Engine control helper macros
*/
@@ -915,12 +989,11 @@ do { \
OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
} while (0)
-
/* ================================================================
* Misc helper macros
*/
-/* Perfbox functionality only.
+/* Perfbox functionality only.
*/
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
do { \
@@ -957,7 +1030,6 @@ do { \
OUT_RING( age ); \
} while (0)
-
/* ================================================================
* Ring control
*/
@@ -1018,7 +1090,6 @@ do { \
OUT_RING( val ); \
} while (0)
-
#define OUT_RING_TABLE( tab, sz ) do { \
int _size = (sz); \
int *_tab = (int *)(tab); \
@@ -1043,5 +1114,4 @@ do { \
write &= mask; \
} while (0)
-
-#endif /* __RADEON_DRV_H__ */
+#endif /* __RADEON_DRV_H__ */
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index bfe612215fb3..fef4a2b84c1e 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -94,7 +94,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
+ DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
}
typedef struct drm_radeon_clear32 {
@@ -102,8 +102,8 @@ typedef struct drm_radeon_clear32 {
unsigned int clear_color;
unsigned int clear_depth;
unsigned int color_mask;
- unsigned int depth_mask; /* misnamed field: should be stencil */
- u32 depth_boxes;
+ unsigned int depth_mask; /* misnamed field: should be stencil */
+ u32 depth_boxes;
} drm_radeon_clear32_t;
static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
@@ -127,7 +127,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
+ DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
}
typedef struct drm_radeon_stipple32 {
@@ -137,7 +137,7 @@ typedef struct drm_radeon_stipple32 {
static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
unsigned long arg)
{
- drm_radeon_stipple32_t __user *argp = (void __user *) arg;
+ drm_radeon_stipple32_t __user *argp = (void __user *)arg;
drm_radeon_stipple_t __user *request;
u32 mask;
@@ -146,16 +146,16 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
- || __put_user((unsigned int __user *)(unsigned long) mask,
+ || __put_user((unsigned int __user *)(unsigned long)mask,
&request->mask))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
+ DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
}
typedef struct drm_radeon_tex_image32 {
- unsigned int x, y; /* Blit coordinates */
+ unsigned int x, y; /* Blit coordinates */
unsigned int width, height;
u32 data;
} drm_radeon_tex_image32_t;
@@ -164,7 +164,7 @@ typedef struct drm_radeon_texture32 {
unsigned int offset;
int pitch;
int format;
- int width; /* Texture image coordinates */
+ int width; /* Texture image coordinates */
int height;
u32 image;
} drm_radeon_texture32_t;
@@ -177,7 +177,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
drm_radeon_tex_image32_t img32;
drm_radeon_tex_image_t __user *image;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
if (req32.image == 0)
return -EINVAL;
@@ -206,12 +206,12 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
+ DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
}
typedef struct drm_radeon_vertex2_32 {
- int idx; /* Index of vertex buffer */
- int discard; /* Client finished with buffer? */
+ int idx; /* Index of vertex buffer */
+ int discard; /* Client finished with buffer? */
int nr_states;
u32 state;
int nr_prims;
@@ -224,7 +224,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
drm_radeon_vertex2_32_t req32;
drm_radeon_vertex2_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -240,7 +240,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
+ DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
}
typedef struct drm_radeon_cmd_buffer32 {
@@ -256,7 +256,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
drm_radeon_cmd_buffer32_t req32;
drm_radeon_cmd_buffer_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -270,7 +270,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
+ DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
}
typedef struct drm_radeon_getparam32 {
@@ -284,7 +284,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
drm_radeon_getparam32_t req32;
drm_radeon_getparam_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -295,7 +295,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
+ DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
}
typedef struct drm_radeon_mem_alloc32 {
@@ -311,7 +311,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
drm_radeon_mem_alloc32_t req32;
drm_radeon_mem_alloc_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -324,7 +324,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
+ DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
}
typedef struct drm_radeon_irq_emit32 {
@@ -337,7 +337,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
drm_radeon_irq_emit32_t req32;
drm_radeon_irq_emit_t __user *request;
- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
@@ -347,7 +347,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
- DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
+ DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
}
drm_ioctl_compat_t *radeon_compat_ioctls[] = {
@@ -371,8 +371,7 @@ drm_ioctl_compat_t *radeon_compat_ioctls[] = {
* \param arg user argument.
* \return zero on success or negative number on failure.
*/
-long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
+long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned int nr = DRM_IOCTL_NR(cmd);
drm_ioctl_compat_t *fn = NULL;
@@ -386,7 +385,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
lock_kernel(); /* XXX for now */
if (fn != NULL)
- ret = (*fn)(filp, cmd, arg);
+ ret = (*fn) (filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 40474a65f56d..d60519de887b 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -1,7 +1,7 @@
/* radeon_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
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
@@ -35,7 +35,8 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+ u32 mask)
{
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
if (irqs)
@@ -61,37 +62,37 @@ static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u3
* tied to dma at all, this is just a hangover from dri prehistory.
*/
-irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *) arg;
- drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
- u32 stat;
+ drm_radeon_private_t *dev_priv =
+ (drm_radeon_private_t *) dev->dev_private;
+ u32 stat;
/* 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 |
+ stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
RADEON_CRTC_VBLANK_STAT));
if (!stat)
return IRQ_NONE;
/* SW interrupt */
if (stat & RADEON_SW_INT_TEST) {
- DRM_WAKEUP( &dev_priv->swi_queue );
+ DRM_WAKEUP(&dev_priv->swi_queue);
}
/* VBLANK interrupt */
if (stat & RADEON_CRTC_VBLANK_STAT) {
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals( dev );
+ drm_vbl_send_signals(dev);
}
return IRQ_HANDLED;
}
-static int radeon_emit_irq(drm_device_t *dev)
+static int radeon_emit_irq(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int ret;
@@ -100,42 +101,41 @@ static int radeon_emit_irq(drm_device_t *dev)
atomic_inc(&dev_priv->swi_emitted);
ret = atomic_read(&dev_priv->swi_emitted);
- BEGIN_RING( 4 );
- OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
- OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
- ADVANCE_RING();
- COMMIT_RING();
+ BEGIN_RING(4);
+ OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
+ OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
+ ADVANCE_RING();
+ COMMIT_RING();
return ret;
}
-
-static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
+static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
{
- drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
+ drm_radeon_private_t *dev_priv =
+ (drm_radeon_private_t *) dev->dev_private;
int ret = 0;
- if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)
- return 0;
+ if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
+ return 0;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
- RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
+ DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
+ RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
return ret;
}
-int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
{
- drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
+ drm_radeon_private_t *dev_priv =
+ (drm_radeon_private_t *) dev->dev_private;
unsigned int cur_vblank;
int ret = 0;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
@@ -145,101 +145,100 @@ int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
/* 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...
+ * using vertical blanks...
*/
- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
- - *sequence ) <= (1<<23) ) );
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received))
+ - *sequence) <= (1 << 23)));
*sequence = cur_vblank;
return ret;
}
-
/* Needs the lock as it touches the ring.
*/
-int radeon_irq_emit( DRM_IOCTL_ARGS )
+int radeon_irq_emit(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_irq_emit_t emit;
int result;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t __user *)data,
- sizeof(emit) );
+ DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data,
+ sizeof(emit));
- result = radeon_emit_irq( dev );
+ result = radeon_emit_irq(dev);
- if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return DRM_ERR(EFAULT);
}
return 0;
}
-
/* Doesn't need the hardware lock.
*/
-int radeon_irq_wait( DRM_IOCTL_ARGS )
+int radeon_irq_wait(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_irq_wait_t irqwait;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t __user*)data,
- sizeof(irqwait) );
+ DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data,
+ sizeof(irqwait));
- return radeon_wait_irq( dev, irqwait.irq_seq );
+ return radeon_wait_irq(dev, irqwait.irq_seq);
}
-
/* drm_dma.h hooks
*/
-void radeon_driver_irq_preinstall( drm_device_t *dev ) {
+void radeon_driver_irq_preinstall(drm_device_t * dev)
+{
drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
+ (drm_radeon_private_t *) dev->dev_private;
- /* Disable *all* interrupts */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+ /* Disable *all* interrupts */
+ 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));
}
-void radeon_driver_irq_postinstall( drm_device_t *dev ) {
+void radeon_driver_irq_postinstall(drm_device_t * dev)
+{
drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
+ (drm_radeon_private_t *) dev->dev_private;
- atomic_set(&dev_priv->swi_emitted, 0);
- DRM_INIT_WAITQUEUE( &dev_priv->swi_queue );
+ atomic_set(&dev_priv->swi_emitted, 0);
+ DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
/* Turn on SW and VBL ints */
- RADEON_WRITE( RADEON_GEN_INT_CNTL,
- RADEON_CRTC_VBLANK_MASK |
- RADEON_SW_INT_ENABLE );
+ RADEON_WRITE(RADEON_GEN_INT_CNTL,
+ RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
}
-void radeon_driver_irq_uninstall( drm_device_t *dev ) {
+void radeon_driver_irq_uninstall(drm_device_t * dev)
+{
drm_radeon_private_t *dev_priv =
- (drm_radeon_private_t *)dev->dev_private;
+ (drm_radeon_private_t *) dev->dev_private;
if (!dev_priv)
return;
/* Disable *all* interrupts */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
}
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
index 134f894e6e4b..030a6fad0d86 100644
--- a/drivers/char/drm/radeon_mem.c
+++ b/drivers/char/drm/radeon_mem.c
@@ -1,7 +1,7 @@
/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*-
*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
- *
+ *
* The Weather Channel (TM) funded Tungsten Graphics to develop the
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
@@ -35,16 +35,17 @@
#include "radeon_drv.h"
/* Very simple allocator for GART memory, working on a static range
- * already mapped into each client's address space.
+ * already mapped into each client's address space.
*/
static struct mem_block *split_block(struct mem_block *p, int start, int size,
- DRMFILE filp )
+ DRMFILE filp)
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
- if (!newblock)
+ struct mem_block *newblock =
+ drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+ if (!newblock)
goto out;
newblock->start = start;
newblock->size = p->size - (start - p->start);
@@ -56,10 +57,11 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
p->size -= newblock->size;
p = newblock;
}
-
+
/* Maybe cut off the end of an existing block */
if (size < p->size) {
- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
+ struct mem_block *newblock =
+ drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
if (!newblock)
goto out;
newblock->start = start + size;
@@ -72,40 +74,39 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
p->size = size;
}
- out:
+ out:
/* Our block is in the middle */
p->filp = filp;
return p;
}
-static struct mem_block *alloc_block( struct mem_block *heap, int size,
- int align2, DRMFILE filp )
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+ int align2, DRMFILE filp)
{
struct mem_block *p;
- int mask = (1 << align2)-1;
+ int mask = (1 << align2) - 1;
list_for_each(p, heap) {
int start = (p->start + mask) & ~mask;
if (p->filp == 0 && start + size <= p->start + p->size)
- return split_block( p, start, size, filp );
+ return split_block(p, start, size, filp);
}
return NULL;
}
-static struct mem_block *find_block( struct mem_block *heap, int start )
+static struct mem_block *find_block(struct mem_block *heap, int start)
{
struct mem_block *p;
list_for_each(p, heap)
- if (p->start == start)
- return p;
+ if (p->start == start)
+ return p;
return NULL;
}
-
-static void free_block( struct mem_block *p )
+static void free_block(struct mem_block *p)
{
p->filp = NULL;
@@ -117,7 +118,7 @@ static void free_block( struct mem_block *p )
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q), DRM_MEM_BUFS );
+ drm_free(q, sizeof(*q), DRM_MEM_BUFS);
}
if (p->prev->filp == 0) {
@@ -125,7 +126,7 @@ static void free_block( struct mem_block *p )
q->size += p->size;
q->next = p->next;
q->next->prev = q;
- drm_free(p, sizeof(*q), DRM_MEM_BUFS );
+ drm_free(p, sizeof(*q), DRM_MEM_BUFS);
}
}
@@ -133,14 +134,14 @@ static void free_block( struct mem_block *p )
*/
static int init_heap(struct mem_block **heap, int start, int size)
{
- struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS );
+ struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
- if (!blocks)
+ if (!blocks)
return DRM_ERR(ENOMEM);
-
- *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS );
+
+ *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
if (!*heap) {
- drm_free( blocks, sizeof(*blocks), DRM_MEM_BUFS );
+ drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
return DRM_ERR(ENOMEM);
}
@@ -149,16 +150,15 @@ static int init_heap(struct mem_block **heap, int start, int size)
blocks->filp = NULL;
blocks->next = blocks->prev = *heap;
- memset( *heap, 0, sizeof(**heap) );
- (*heap)->filp = (DRMFILE) -1;
+ memset(*heap, 0, sizeof(**heap));
+ (*heap)->filp = (DRMFILE) - 1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
}
-
/* Free all blocks associated with the releasing file.
*/
-void radeon_mem_release( DRMFILE filp, struct mem_block *heap )
+void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
{
struct mem_block *p;
@@ -166,7 +166,7 @@ void radeon_mem_release( DRMFILE filp, struct mem_block *heap )
return;
list_for_each(p, heap) {
- if (p->filp == filp)
+ if (p->filp == filp)
p->filp = NULL;
}
@@ -179,40 +179,37 @@ void radeon_mem_release( DRMFILE filp, struct mem_block *heap )
p->size += q->size;
p->next = q->next;
p->next->prev = p;
- drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
+ drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
}
}
}
/* Shutdown.
*/
-void radeon_mem_takedown( struct mem_block **heap )
+void radeon_mem_takedown(struct mem_block **heap)
{
struct mem_block *p;
-
+
if (!*heap)
return;
- for (p = (*heap)->next ; p != *heap ; ) {
+ for (p = (*heap)->next; p != *heap;) {
struct mem_block *q = p;
p = p->next;
- drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
+ drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
}
- drm_free( *heap, sizeof(**heap),DRM_MEM_DRIVER );
+ drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
*heap = NULL;
}
-
-
/* IOCTL HANDLERS */
-static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
- int region )
+static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
{
- switch( region ) {
+ switch (region) {
case RADEON_MEM_REGION_GART:
- return &dev_priv->gart_heap;
+ return &dev_priv->gart_heap;
case RADEON_MEM_REGION_FB:
return &dev_priv->fb_heap;
default:
@@ -220,103 +217,98 @@ static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
}
}
-int radeon_mem_alloc( DRM_IOCTL_ARGS )
+int radeon_mem_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_alloc_t alloc;
struct mem_block *block, **heap;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t __user *)data,
- sizeof(alloc) );
+ DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data,
+ sizeof(alloc));
- heap = get_heap( dev_priv, alloc.region );
+ heap = get_heap(dev_priv, alloc.region);
if (!heap || !*heap)
return DRM_ERR(EFAULT);
-
+
/* Make things easier on ourselves: all allocations at least
* 4k aligned.
*/
if (alloc.alignment < 12)
alloc.alignment = 12;
- block = alloc_block( *heap, alloc.size, alloc.alignment,
- filp );
+ block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
- if (!block)
+ if (!block)
return DRM_ERR(ENOMEM);
- if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start,
- sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return DRM_ERR(EFAULT);
}
-
+
return 0;
}
-
-
-int radeon_mem_free( DRM_IOCTL_ARGS )
+int radeon_mem_free(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_free_t memfree;
struct mem_block *block, **heap;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t __user *)data,
- sizeof(memfree) );
+ DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+ sizeof(memfree));
- heap = get_heap( dev_priv, memfree.region );
+ heap = get_heap(dev_priv, memfree.region);
if (!heap || !*heap)
return DRM_ERR(EFAULT);
-
- block = find_block( *heap, memfree.region_offset );
+
+ block = find_block(*heap, memfree.region_offset);
if (!block)
return DRM_ERR(EFAULT);
if (block->filp != filp)
return DRM_ERR(EPERM);
- free_block( block );
+ free_block(block);
return 0;
}
-int radeon_mem_init_heap( DRM_IOCTL_ARGS )
+int radeon_mem_init_heap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_mem_init_heap_t initheap;
struct mem_block **heap;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t __user *)data,
- sizeof(initheap) );
+ DRM_COPY_FROM_USER_IOCTL(initheap,
+ (drm_radeon_mem_init_heap_t __user *) data,
+ sizeof(initheap));
- heap = get_heap( dev_priv, initheap.region );
- if (!heap)
+ heap = get_heap(dev_priv, initheap.region);
+ if (!heap)
return DRM_ERR(EFAULT);
-
+
if (*heap) {
DRM_ERROR("heap already initialized?");
return DRM_ERR(EFAULT);
}
-
- return init_heap( heap, initheap.start, initheap.size );
-}
-
+ return init_heap(heap, initheap.start, initheap.size);
+}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 1f79e249146c..231ac1438c69 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -37,51 +37,58 @@
* Helper functions for client state checking and fixup
*/
-static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- u32 *offset ) {
+static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
+ dev_priv,
+ drm_file_t * filp_priv,
+ u32 *offset)
+{
u32 off = *offset;
struct drm_radeon_driver_file_fields *radeon_priv;
- if ( off >= dev_priv->fb_location &&
- off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+ if (off >= dev_priv->fb_location &&
+ off < (dev_priv->gart_vm_start + dev_priv->gart_size))
return 0;
radeon_priv = filp_priv->driver_priv;
off += radeon_priv->radeon_fb_delta;
- DRM_DEBUG( "offset fixed up to 0x%x\n", off );
+ DRM_DEBUG("offset fixed up to 0x%x\n", off);
- if ( off < dev_priv->fb_location ||
- off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
- return DRM_ERR( EINVAL );
+ if (off < dev_priv->fb_location ||
+ off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
+ return DRM_ERR(EINVAL);
*offset = off;
return 0;
}
-static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- int id,
- u32 __user *data ) {
- switch ( id ) {
+static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
+ dev_priv,
+ drm_file_t * filp_priv,
+ int id, u32 *data)
+{
+ switch (id) {
case RADEON_EMIT_PP_MISC:
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &data[( RADEON_RB3D_DEPTHOFFSET
- - RADEON_PP_MISC ) / 4] ) ) {
- DRM_ERROR( "Invalid depth buffer offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &data[(RADEON_RB3D_DEPTHOFFSET
+ -
+ RADEON_PP_MISC) /
+ 4])) {
+ DRM_ERROR("Invalid depth buffer offset\n");
+ return DRM_ERR(EINVAL);
}
break;
case RADEON_EMIT_PP_CNTL:
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &data[( RADEON_RB3D_COLOROFFSET
- - RADEON_PP_CNTL ) / 4] ) ) {
- DRM_ERROR( "Invalid colour buffer offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &data[(RADEON_RB3D_COLOROFFSET
+ -
+ RADEON_PP_CNTL) /
+ 4])) {
+ DRM_ERROR("Invalid colour buffer offset\n");
+ return DRM_ERR(EINVAL);
}
break;
@@ -91,21 +98,23 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case R200_EMIT_PP_TXOFFSET_3:
case R200_EMIT_PP_TXOFFSET_4:
case R200_EMIT_PP_TXOFFSET_5:
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &data[0] ) ) {
- DRM_ERROR( "Invalid R200 texture offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &data[0])) {
+ DRM_ERROR("Invalid R200 texture offset\n");
+ return DRM_ERR(EINVAL);
}
break;
case RADEON_EMIT_PP_TXFILTER_0:
case RADEON_EMIT_PP_TXFILTER_1:
case RADEON_EMIT_PP_TXFILTER_2:
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &data[( RADEON_PP_TXOFFSET_0
- - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
- DRM_ERROR( "Invalid R100 texture offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &data[(RADEON_PP_TXOFFSET_0
+ -
+ RADEON_PP_TXFILTER_0) /
+ 4])) {
+ DRM_ERROR("Invalid R100 texture offset\n");
+ return DRM_ERR(EINVAL);
}
break;
@@ -114,17 +123,18 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case R200_EMIT_PP_CUBIC_OFFSETS_2:
case R200_EMIT_PP_CUBIC_OFFSETS_3:
case R200_EMIT_PP_CUBIC_OFFSETS_4:
- case R200_EMIT_PP_CUBIC_OFFSETS_5: {
- int i;
- for ( i = 0; i < 5; i++ ) {
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &data[i] ) ) {
- DRM_ERROR( "Invalid R200 cubic texture offset\n" );
- return DRM_ERR( EINVAL );
+ case R200_EMIT_PP_CUBIC_OFFSETS_5:{
+ int i;
+ for (i = 0; i < 5; i++) {
+ if (radeon_check_and_fixup_offset
+ (dev_priv, filp_priv, &data[i])) {
+ DRM_ERROR
+ ("Invalid R200 cubic texture offset\n");
+ return DRM_ERR(EINVAL);
+ }
}
+ break;
}
- break;
- }
case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
@@ -207,247 +217,259 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case RADEON_EMIT_PP_CUBIC_FACES_1:
case RADEON_EMIT_PP_CUBIC_FACES_2:
case R200_EMIT_PP_TRI_PERF_CNTL:
+ case R200_EMIT_PP_AFS_0:
+ case R200_EMIT_PP_AFS_1:
+ case R200_EMIT_ATF_TFACTOR:
+ case R200_EMIT_PP_TXCTLALL_0:
+ case R200_EMIT_PP_TXCTLALL_1:
+ case R200_EMIT_PP_TXCTLALL_2:
+ case R200_EMIT_PP_TXCTLALL_3:
+ case R200_EMIT_PP_TXCTLALL_4:
+ case R200_EMIT_PP_TXCTLALL_5:
/* These packets don't contain memory offsets */
break;
default:
- DRM_ERROR( "Unknown state packet ID %d\n", id );
- return DRM_ERR( EINVAL );
+ DRM_ERROR("Unknown state packet ID %d\n", id);
+ return DRM_ERR(EINVAL);
}
return 0;
}
-static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- drm_radeon_cmd_buffer_t *cmdbuf,
- unsigned int *cmdsz ) {
+static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+ dev_priv,
+ drm_file_t * filp_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
+ unsigned int *cmdsz)
+{
u32 *cmd = (u32 *) cmdbuf->buf;
- *cmdsz = 2 + ( ( cmd[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+ *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
- if ( ( cmd[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
- DRM_ERROR( "Not a type 3 packet\n" );
- return DRM_ERR( EINVAL );
+ if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
+ DRM_ERROR("Not a type 3 packet\n");
+ return DRM_ERR(EINVAL);
}
- if ( 4 * *cmdsz > cmdbuf->bufsz ) {
- DRM_ERROR( "Packet size larger than size of data provided\n" );
- return DRM_ERR( EINVAL );
+ if (4 * *cmdsz > cmdbuf->bufsz) {
+ DRM_ERROR("Packet size larger than size of data provided\n");
+ return DRM_ERR(EINVAL);
}
/* Check client state and fix it up if necessary */
- if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+ if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */
u32 offset;
- if ( cmd[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
- | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+ | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[2] << 10;
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
- DRM_ERROR( "Invalid first packet offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset
+ (dev_priv, filp_priv, &offset)) {
+ DRM_ERROR("Invalid first packet offset\n");
+ return DRM_ERR(EINVAL);
}
- cmd[2] = ( cmd[2] & 0xffc00000 ) | offset >> 10;
+ cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
}
- if ( ( cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
- ( cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+ (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[3] << 10;
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
- DRM_ERROR( "Invalid second packet offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset
+ (dev_priv, filp_priv, &offset)) {
+ DRM_ERROR("Invalid second packet offset\n");
+ return DRM_ERR(EINVAL);
}
- cmd[3] = ( cmd[3] & 0xffc00000 ) | offset >> 10;
+ cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
}
}
return 0;
}
-
/* ================================================================
* CP hardware state programming functions
*/
-static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
- drm_clip_rect_t *box )
+static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+ drm_clip_rect_t * box)
{
RING_LOCALS;
- DRM_DEBUG( " box: x1=%d y1=%d x2=%d y2=%d\n",
- box->x1, box->y1, box->x2, box->y2 );
+ DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n",
+ box->x1, box->y1, box->x2, box->y2);
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
- OUT_RING( (box->y1 << 16) | box->x1 );
- OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
- OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
+ OUT_RING((box->y1 << 16) | box->x1);
+ OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
+ OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
ADVANCE_RING();
}
/* Emit 1.1 state
*/
-static int radeon_emit_state( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- drm_radeon_context_regs_t *ctx,
- drm_radeon_texture_regs_t *tex,
- unsigned int dirty )
+static int radeon_emit_state(drm_radeon_private_t * dev_priv,
+ drm_file_t * filp_priv,
+ drm_radeon_context_regs_t * ctx,
+ drm_radeon_texture_regs_t * tex,
+ unsigned int dirty)
{
RING_LOCALS;
- DRM_DEBUG( "dirty=0x%08x\n", dirty );
+ DRM_DEBUG("dirty=0x%08x\n", dirty);
- if ( dirty & RADEON_UPLOAD_CONTEXT ) {
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &ctx->rb3d_depthoffset ) ) {
- DRM_ERROR( "Invalid depth buffer offset\n" );
- return DRM_ERR( EINVAL );
+ if (dirty & RADEON_UPLOAD_CONTEXT) {
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &ctx->rb3d_depthoffset)) {
+ DRM_ERROR("Invalid depth buffer offset\n");
+ return DRM_ERR(EINVAL);
}
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &ctx->rb3d_coloroffset ) ) {
- DRM_ERROR( "Invalid depth buffer offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &ctx->rb3d_coloroffset)) {
+ DRM_ERROR("Invalid depth buffer offset\n");
+ return DRM_ERR(EINVAL);
}
- BEGIN_RING( 14 );
- OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
- OUT_RING( ctx->pp_misc );
- OUT_RING( ctx->pp_fog_color );
- OUT_RING( ctx->re_solid_color );
- OUT_RING( ctx->rb3d_blendcntl );
- OUT_RING( ctx->rb3d_depthoffset );
- OUT_RING( ctx->rb3d_depthpitch );
- OUT_RING( ctx->rb3d_zstencilcntl );
- OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
- OUT_RING( ctx->pp_cntl );
- OUT_RING( ctx->rb3d_cntl );
- OUT_RING( ctx->rb3d_coloroffset );
- OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
- OUT_RING( ctx->rb3d_colorpitch );
+ BEGIN_RING(14);
+ OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
+ OUT_RING(ctx->pp_misc);
+ OUT_RING(ctx->pp_fog_color);
+ OUT_RING(ctx->re_solid_color);
+ OUT_RING(ctx->rb3d_blendcntl);
+ OUT_RING(ctx->rb3d_depthoffset);
+ OUT_RING(ctx->rb3d_depthpitch);
+ OUT_RING(ctx->rb3d_zstencilcntl);
+ OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
+ OUT_RING(ctx->pp_cntl);
+ OUT_RING(ctx->rb3d_cntl);
+ OUT_RING(ctx->rb3d_coloroffset);
+ OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
+ OUT_RING(ctx->rb3d_colorpitch);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_VERTFMT ) {
- BEGIN_RING( 2 );
- OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
- OUT_RING( ctx->se_coord_fmt );
+ if (dirty & RADEON_UPLOAD_VERTFMT) {
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
+ OUT_RING(ctx->se_coord_fmt);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_LINE ) {
- BEGIN_RING( 5 );
- OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
- OUT_RING( ctx->re_line_pattern );
- OUT_RING( ctx->re_line_state );
- OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
- OUT_RING( ctx->se_line_width );
+ if (dirty & RADEON_UPLOAD_LINE) {
+ BEGIN_RING(5);
+ OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
+ OUT_RING(ctx->re_line_pattern);
+ OUT_RING(ctx->re_line_state);
+ OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
+ OUT_RING(ctx->se_line_width);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
- BEGIN_RING( 5 );
- OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
- OUT_RING( ctx->pp_lum_matrix );
- OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
- OUT_RING( ctx->pp_rot_matrix_0 );
- OUT_RING( ctx->pp_rot_matrix_1 );
+ if (dirty & RADEON_UPLOAD_BUMPMAP) {
+ BEGIN_RING(5);
+ OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
+ OUT_RING(ctx->pp_lum_matrix);
+ OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
+ OUT_RING(ctx->pp_rot_matrix_0);
+ OUT_RING(ctx->pp_rot_matrix_1);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_MASKS ) {
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
- OUT_RING( ctx->rb3d_stencilrefmask );
- OUT_RING( ctx->rb3d_ropcntl );
- OUT_RING( ctx->rb3d_planemask );
+ if (dirty & RADEON_UPLOAD_MASKS) {
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
+ OUT_RING(ctx->rb3d_stencilrefmask);
+ OUT_RING(ctx->rb3d_ropcntl);
+ OUT_RING(ctx->rb3d_planemask);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
- BEGIN_RING( 7 );
- OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
- OUT_RING( ctx->se_vport_xscale );
- OUT_RING( ctx->se_vport_xoffset );
- OUT_RING( ctx->se_vport_yscale );
- OUT_RING( ctx->se_vport_yoffset );
- OUT_RING( ctx->se_vport_zscale );
- OUT_RING( ctx->se_vport_zoffset );
+ if (dirty & RADEON_UPLOAD_VIEWPORT) {
+ BEGIN_RING(7);
+ OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
+ OUT_RING(ctx->se_vport_xscale);
+ OUT_RING(ctx->se_vport_xoffset);
+ OUT_RING(ctx->se_vport_yscale);
+ OUT_RING(ctx->se_vport_yoffset);
+ OUT_RING(ctx->se_vport_zscale);
+ OUT_RING(ctx->se_vport_zoffset);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_SETUP ) {
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
- OUT_RING( ctx->se_cntl );
- OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
- OUT_RING( ctx->se_cntl_status );
+ if (dirty & RADEON_UPLOAD_SETUP) {
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
+ OUT_RING(ctx->se_cntl);
+ OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
+ OUT_RING(ctx->se_cntl_status);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_MISC ) {
- BEGIN_RING( 2 );
- OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
- OUT_RING( ctx->re_misc );
+ if (dirty & RADEON_UPLOAD_MISC) {
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
+ OUT_RING(ctx->re_misc);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_TEX0 ) {
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &tex[0].pp_txoffset ) ) {
- DRM_ERROR( "Invalid texture offset for unit 0\n" );
- return DRM_ERR( EINVAL );
+ if (dirty & RADEON_UPLOAD_TEX0) {
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &tex[0].pp_txoffset)) {
+ DRM_ERROR("Invalid texture offset for unit 0\n");
+ return DRM_ERR(EINVAL);
}
- BEGIN_RING( 9 );
- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
- OUT_RING( tex[0].pp_txfilter );
- OUT_RING( tex[0].pp_txformat );
- OUT_RING( tex[0].pp_txoffset );
- OUT_RING( tex[0].pp_txcblend );
- OUT_RING( tex[0].pp_txablend );
- OUT_RING( tex[0].pp_tfactor );
- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
- OUT_RING( tex[0].pp_border_color );
+ BEGIN_RING(9);
+ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
+ OUT_RING(tex[0].pp_txfilter);
+ OUT_RING(tex[0].pp_txformat);
+ OUT_RING(tex[0].pp_txoffset);
+ OUT_RING(tex[0].pp_txcblend);
+ OUT_RING(tex[0].pp_txablend);
+ OUT_RING(tex[0].pp_tfactor);
+ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
+ OUT_RING(tex[0].pp_border_color);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_TEX1 ) {
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &tex[1].pp_txoffset ) ) {
- DRM_ERROR( "Invalid texture offset for unit 1\n" );
- return DRM_ERR( EINVAL );
+ if (dirty & RADEON_UPLOAD_TEX1) {
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &tex[1].pp_txoffset)) {
+ DRM_ERROR("Invalid texture offset for unit 1\n");
+ return DRM_ERR(EINVAL);
}
- BEGIN_RING( 9 );
- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
- OUT_RING( tex[1].pp_txfilter );
- OUT_RING( tex[1].pp_txformat );
- OUT_RING( tex[1].pp_txoffset );
- OUT_RING( tex[1].pp_txcblend );
- OUT_RING( tex[1].pp_txablend );
- OUT_RING( tex[1].pp_tfactor );
- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
- OUT_RING( tex[1].pp_border_color );
+ BEGIN_RING(9);
+ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
+ OUT_RING(tex[1].pp_txfilter);
+ OUT_RING(tex[1].pp_txformat);
+ OUT_RING(tex[1].pp_txoffset);
+ OUT_RING(tex[1].pp_txcblend);
+ OUT_RING(tex[1].pp_txablend);
+ OUT_RING(tex[1].pp_tfactor);
+ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
+ OUT_RING(tex[1].pp_border_color);
ADVANCE_RING();
}
- if ( dirty & RADEON_UPLOAD_TEX2 ) {
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
- &tex[2].pp_txoffset ) ) {
- DRM_ERROR( "Invalid texture offset for unit 2\n" );
- return DRM_ERR( EINVAL );
+ if (dirty & RADEON_UPLOAD_TEX2) {
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+ &tex[2].pp_txoffset)) {
+ DRM_ERROR("Invalid texture offset for unit 2\n");
+ return DRM_ERR(EINVAL);
}
- BEGIN_RING( 9 );
- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
- OUT_RING( tex[2].pp_txfilter );
- OUT_RING( tex[2].pp_txformat );
- OUT_RING( tex[2].pp_txoffset );
- OUT_RING( tex[2].pp_txcblend );
- OUT_RING( tex[2].pp_txablend );
- OUT_RING( tex[2].pp_tfactor );
- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
- OUT_RING( tex[2].pp_border_color );
+ BEGIN_RING(9);
+ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
+ OUT_RING(tex[2].pp_txfilter);
+ OUT_RING(tex[2].pp_txformat);
+ OUT_RING(tex[2].pp_txoffset);
+ OUT_RING(tex[2].pp_txcblend);
+ OUT_RING(tex[2].pp_txablend);
+ OUT_RING(tex[2].pp_tfactor);
+ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
+ OUT_RING(tex[2].pp_border_color);
ADVANCE_RING();
}
@@ -456,129 +478,137 @@ static int radeon_emit_state( drm_radeon_private_t *dev_priv,
/* Emit 1.2 state
*/
-static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- drm_radeon_state_t *state )
+static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
+ drm_file_t * filp_priv,
+ drm_radeon_state_t * state)
{
RING_LOCALS;
if (state->dirty & RADEON_UPLOAD_ZBIAS) {
- BEGIN_RING( 3 );
- OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
- OUT_RING( state->context2.se_zbias_factor );
- OUT_RING( state->context2.se_zbias_constant );
+ BEGIN_RING(3);
+ OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
+ OUT_RING(state->context2.se_zbias_factor);
+ OUT_RING(state->context2.se_zbias_constant);
ADVANCE_RING();
}
- return radeon_emit_state( dev_priv, filp_priv, &state->context,
- state->tex, state->dirty );
+ return radeon_emit_state(dev_priv, filp_priv, &state->context,
+ state->tex, state->dirty);
}
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
* 1.3 cmdbuffers allow all previous state to be updated as well as
- * the tcl scalar and vector areas.
+ * the tcl scalar and vector areas.
*/
-static struct {
- int start;
- int len;
+static struct {
+ int start;
+ int len;
const char *name;
} packet[RADEON_MAX_STATE_PACKETS] = {
- { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
- { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
- { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
- { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
- { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
- { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
- { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
- { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
- { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
- { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
- { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
- { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
- { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
- { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
- { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
- { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
- { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
- { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
- { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
- { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
- { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
- { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
- { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
- { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
- { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
- { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
- { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
- { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
- { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
- { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
- { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
- { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
- { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
- { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
- { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
- { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
- { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
- { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
- { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
- { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
- { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
- { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
- { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
- { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
- { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
- { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
- { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
- { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
- { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
- { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
- { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
- { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" },
- { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" },
- { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" },
- { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" },
- { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" },
- { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" },
- { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" },
- { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" },
- { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" },
- { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
- { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
- { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
- { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
- { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
- { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
- { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
- { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
- { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
- { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
- { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
- { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
- { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
- { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
- { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
- { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
- { R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
- { R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
- { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
- { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
- { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
- { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
- { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
- { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
- { R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+ {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
+ {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
+ {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
+ {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
+ {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
+ {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
+ {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
+ {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
+ {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
+ {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
+ {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
+ {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
+ {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
+ {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
+ {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
+ {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
+ {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
+ {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
+ {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
+ {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
+ {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
+ "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
+ {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
+ {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
+ {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
+ {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
+ {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
+ {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
+ {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
+ {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
+ {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
+ {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
+ {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
+ {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
+ {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
+ {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
+ {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
+ {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
+ {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
+ {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
+ {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
+ {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
+ {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
+ {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
+ {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
+ {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
+ {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
+ {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
+ {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
+ {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
+ {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+ {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
+ {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
+ {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
+ {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
+ {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
+ {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
+ {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
+ {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
+ {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
+ {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
+ {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
+ "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
+ {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
+ {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+ {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
+ {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
+ {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
+ {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
+ {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
+ {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
+ {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
+ {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
+ {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
+ {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
+ {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
+ {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
+ {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
+ {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
+ {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
+ {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+ {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+ {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+ {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+ {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+ {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+ {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+ {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
+ {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
+ {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
+ {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
+ {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
+ {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
+ {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
+ {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
+ {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
};
-
-
/* ================================================================
* Performance monitoring functions
*/
-static void radeon_clear_box( drm_radeon_private_t *dev_priv,
- int x, int y, int w, int h,
- int r, int g, int b )
+static void radeon_clear_box(drm_radeon_private_t * dev_priv,
+ int x, int y, int w, int h, int r, int g, int b)
{
u32 color;
RING_LOCALS;
@@ -586,49 +616,47 @@ static void radeon_clear_box( drm_radeon_private_t *dev_priv,
x += dev_priv->sarea_priv->boxes[0].x1;
y += dev_priv->sarea_priv->boxes[0].y1;
- switch ( dev_priv->color_fmt ) {
+ switch (dev_priv->color_fmt) {
case RADEON_COLOR_FORMAT_RGB565:
color = (((r & 0xf8) << 8) |
- ((g & 0xfc) << 3) |
- ((b & 0xf8) >> 3));
+ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
break;
case RADEON_COLOR_FORMAT_ARGB8888:
default:
- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
break;
}
- BEGIN_RING( 4 );
- RADEON_WAIT_UNTIL_3D_IDLE();
- OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
- OUT_RING( 0xffffffff );
+ BEGIN_RING(4);
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+ OUT_RING(0xffffffff);
ADVANCE_RING();
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_P |
- RADEON_GMC_CLR_CMP_CNTL_DIS );
+ OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
+ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
- OUT_RING( dev_priv->front_pitch_offset );
- } else {
- OUT_RING( dev_priv->back_pitch_offset );
- }
+ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+ OUT_RING(dev_priv->front_pitch_offset);
+ } else {
+ OUT_RING(dev_priv->back_pitch_offset);
+ }
- OUT_RING( color );
+ OUT_RING(color);
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
-static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
+static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
{
/* Collapse various things into a wait flag -- trying to
* guess if userspase slept -- better just to have them tell us.
@@ -644,50 +672,50 @@ static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
/* Purple box for page flipping
*/
- if ( dev_priv->stats.boxes & RADEON_BOX_FLIP )
- radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
+ if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
+ radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
/* Red box if we have to wait for idle at any point
*/
- if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE )
- radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
+ if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
+ radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
/* Blue box: lost context?
*/
/* Yellow box for texture swaps
*/
- if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD )
- radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
+ if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
+ radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
/* Green box if hardware never idles (as far as we can tell)
*/
- if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) )
- radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
-
+ if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
+ radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
- /* Draw bars indicating number of buffers allocated
+ /* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
if (dev_priv->stats.requested_bufs) {
if (dev_priv->stats.requested_bufs > 100)
dev_priv->stats.requested_bufs = 100;
- radeon_clear_box( dev_priv, 4, 16,
- dev_priv->stats.requested_bufs, 4,
- 196, 128, 128 );
+ radeon_clear_box(dev_priv, 4, 16,
+ dev_priv->stats.requested_bufs, 4,
+ 196, 128, 128);
}
- memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
+ memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
}
+
/* ================================================================
* CP command dispatch functions
*/
-static void radeon_cp_dispatch_clear( drm_device_t *dev,
- drm_radeon_clear_t *clear,
- drm_radeon_clear_rect_t *depth_boxes )
+static void radeon_cp_dispatch_clear(drm_device_t * dev,
+ drm_radeon_clear_t * clear,
+ drm_radeon_clear_rect_t * depth_boxes)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -695,32 +723,34 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
unsigned int flags = clear->flags;
- u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
+ u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
int i;
RING_LOCALS;
- DRM_DEBUG( "flags = 0x%x\n", flags );
+ DRM_DEBUG("flags = 0x%x\n", flags);
dev_priv->stats.clears++;
- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
unsigned int tmp = flags;
flags &= ~(RADEON_FRONT | RADEON_BACK);
- if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
- if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT;
+ if (tmp & RADEON_FRONT)
+ flags |= RADEON_BACK;
+ if (tmp & RADEON_BACK)
+ flags |= RADEON_FRONT;
}
- if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
+ if (flags & (RADEON_FRONT | RADEON_BACK)) {
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
/* Ensure the 3D stream is idle before doing a
* 2D fill to clear the front or back buffer.
*/
RADEON_WAIT_UNTIL_3D_IDLE();
-
- OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
- OUT_RING( clear->color_mask );
+
+ OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+ OUT_RING(clear->color_mask);
ADVANCE_RING();
@@ -728,121 +758,130 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
*/
dev_priv->sarea_priv->ctx_owner = 0;
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
int x = pbox[i].x1;
int y = pbox[i].y1;
int w = pbox[i].x2 - x;
int h = pbox[i].y2 - y;
- DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
- x, y, w, h, flags );
-
- if ( flags & RADEON_FRONT ) {
- BEGIN_RING( 6 );
-
- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_P |
- RADEON_GMC_CLR_CMP_CNTL_DIS );
-
- OUT_RING( dev_priv->front_pitch_offset );
- OUT_RING( clear->clear_color );
-
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
-
+ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+ x, y, w, h, flags);
+
+ if (flags & RADEON_FRONT) {
+ BEGIN_RING(6);
+
+ OUT_RING(CP_PACKET3
+ (RADEON_CNTL_PAINT_MULTI, 4));
+ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->
+ color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+ OUT_RING(dev_priv->front_pitch_offset);
+ OUT_RING(clear->clear_color);
+
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
+
ADVANCE_RING();
}
-
- if ( flags & RADEON_BACK ) {
- BEGIN_RING( 6 );
-
- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_SOLID_COLOR |
- (dev_priv->color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_P |
- RADEON_GMC_CLR_CMP_CNTL_DIS );
-
- OUT_RING( dev_priv->back_pitch_offset );
- OUT_RING( clear->clear_color );
-
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+
+ if (flags & RADEON_BACK) {
+ BEGIN_RING(6);
+
+ OUT_RING(CP_PACKET3
+ (RADEON_CNTL_PAINT_MULTI, 4));
+ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->
+ color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+ OUT_RING(dev_priv->back_pitch_offset);
+ OUT_RING(clear->clear_color);
+
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
}
}
-
+
/* hyper z clear */
/* no docs available, based on reverse engeneering by Stephane Marchesin */
- if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) && (flags & RADEON_CLEAR_FASTZ)) {
+ if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
+ && (flags & RADEON_CLEAR_FASTZ)) {
int i;
- int depthpixperline = dev_priv->depth_fmt==RADEON_DEPTH_FORMAT_16BIT_INT_Z?
- (dev_priv->depth_pitch / 2): (dev_priv->depth_pitch / 4);
-
+ int depthpixperline =
+ dev_priv->depth_fmt ==
+ RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
+ 2) : (dev_priv->
+ depth_pitch / 4);
+
u32 clearmask;
u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
- ((clear->depth_mask & 0xff) << 24);
-
-
+ ((clear->depth_mask & 0xff) << 24);
+
/* Make sure we restore the 3D state next time.
* we haven't touched any "normal" state - still need this?
*/
dev_priv->sarea_priv->ctx_owner = 0;
- if ((dev_priv->flags & CHIP_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) {
- /* FIXME : reverse engineer that for Rx00 cards */
- /* FIXME : the mask supposedly contains low-res z values. So can't set
- just to the max (0xff? or actually 0x3fff?), need to take z clear
- value into account? */
- /* pattern seems to work for r100, though get slight
- rendering errors with glxgears. If hierz is not enabled for r100,
- only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
- other ones are ignored, and the same clear mask can be used. That's
- very different behaviour than R200 which needs different clear mask
- and different number of tiles to clear if hierz is enabled or not !?!
- */
- clearmask = (0xff<<22)|(0xff<<6)| 0x003f003f;
- }
- else {
- /* clear mask : chooses the clearing pattern.
- rv250: could be used to clear only parts of macrotiles
- (but that would get really complicated...)?
- bit 0 and 1 (either or both of them ?!?!) are used to
- not clear tile (or maybe one of the bits indicates if the tile is
- compressed or not), bit 2 and 3 to not clear tile 1,...,.
- Pattern is as follows:
- | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
- bits -------------------------------------------------
- | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
- rv100: clearmask covers 2x8 4x1 tiles, but one clear still
- covers 256 pixels ?!?
- */
+ if ((dev_priv->flags & CHIP_HAS_HIERZ)
+ && (flags & RADEON_USE_HIERZ)) {
+ /* FIXME : reverse engineer that for Rx00 cards */
+ /* FIXME : the mask supposedly contains low-res z values. So can't set
+ just to the max (0xff? or actually 0x3fff?), need to take z clear
+ value into account? */
+ /* pattern seems to work for r100, though get slight
+ rendering errors with glxgears. If hierz is not enabled for r100,
+ only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
+ other ones are ignored, and the same clear mask can be used. That's
+ very different behaviour than R200 which needs different clear mask
+ and different number of tiles to clear if hierz is enabled or not !?!
+ */
+ clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
+ } else {
+ /* clear mask : chooses the clearing pattern.
+ rv250: could be used to clear only parts of macrotiles
+ (but that would get really complicated...)?
+ bit 0 and 1 (either or both of them ?!?!) are used to
+ not clear tile (or maybe one of the bits indicates if the tile is
+ compressed or not), bit 2 and 3 to not clear tile 1,...,.
+ Pattern is as follows:
+ | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
+ bits -------------------------------------------------
+ | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
+ rv100: clearmask covers 2x8 4x1 tiles, but one clear still
+ covers 256 pixels ?!?
+ */
clearmask = 0x0;
}
- BEGIN_RING( 8 );
+ BEGIN_RING(8);
RADEON_WAIT_UNTIL_2D_IDLE();
- OUT_RING_REG( RADEON_RB3D_DEPTHCLEARVALUE,
- tempRB3D_DEPTHCLEARVALUE);
+ OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
+ tempRB3D_DEPTHCLEARVALUE);
/* what offset is this exactly ? */
- OUT_RING_REG( RADEON_RB3D_ZMASKOFFSET, 0 );
+ OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
/* need ctlstat, otherwise get some strange black flickering */
- OUT_RING_REG( RADEON_RB3D_ZCACHE_CTLSTAT, RADEON_RB3D_ZC_FLUSH_ALL );
+ OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
+ RADEON_RB3D_ZC_FLUSH_ALL);
ADVANCE_RING();
for (i = 0; i < nbox; i++) {
int tileoffset, nrtilesx, nrtilesy, j;
/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
- if ((dev_priv->flags&CHIP_HAS_HIERZ) && !(dev_priv->microcode_version==UCODE_R200)) {
+ if ((dev_priv->flags & CHIP_HAS_HIERZ)
+ && !(dev_priv->microcode_version == UCODE_R200)) {
/* FIXME : figure this out for r200 (when hierz is enabled). Or
maybe r200 actually doesn't need to put the low-res z value into
the tile cache like r100, but just needs to clear the hi-level z-buffer?
@@ -850,59 +889,74 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
R100 seems to operate on 2x1 8x8 tiles, but...
odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
problematic with resolutions which are not 64 pix aligned? */
- tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 6;
- nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
- nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+ tileoffset =
+ ((pbox[i].y1 >> 3) * depthpixperline +
+ pbox[i].x1) >> 6;
+ nrtilesx =
+ ((pbox[i].x2 & ~63) -
+ (pbox[i].x1 & ~63)) >> 4;
+ nrtilesy =
+ (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
for (j = 0; j <= nrtilesy; j++) {
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET3
+ (RADEON_3D_CLEAR_ZMASK, 2));
/* first tile */
- OUT_RING( tileoffset * 8 );
+ OUT_RING(tileoffset * 8);
/* the number of tiles to clear */
- OUT_RING( nrtilesx + 4 );
+ OUT_RING(nrtilesx + 4);
/* clear mask : chooses the clearing pattern. */
- OUT_RING( clearmask );
+ OUT_RING(clearmask);
ADVANCE_RING();
tileoffset += depthpixperline >> 6;
}
- }
- else if (dev_priv->microcode_version==UCODE_R200) {
+ } else if (dev_priv->microcode_version == UCODE_R200) {
/* works for rv250. */
/* find first macro tile (8x2 4x4 z-pixels on rv250) */
- tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 5;
- nrtilesx = (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
- nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+ tileoffset =
+ ((pbox[i].y1 >> 3) * depthpixperline +
+ pbox[i].x1) >> 5;
+ nrtilesx =
+ (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
+ nrtilesy =
+ (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
for (j = 0; j <= nrtilesy; j++) {
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET3
+ (RADEON_3D_CLEAR_ZMASK, 2));
/* first tile */
/* judging by the first tile offset needed, could possibly
directly address/clear 4x4 tiles instead of 8x2 * 4x4
macro tiles, though would still need clear mask for
right/bottom if truely 4x4 granularity is desired ? */
- OUT_RING( tileoffset * 16 );
+ OUT_RING(tileoffset * 16);
/* the number of tiles to clear */
- OUT_RING( nrtilesx + 1 );
+ OUT_RING(nrtilesx + 1);
/* clear mask : chooses the clearing pattern. */
- OUT_RING( clearmask );
+ OUT_RING(clearmask);
ADVANCE_RING();
tileoffset += depthpixperline >> 5;
}
- }
- else { /* rv 100 */
+ } else { /* rv 100 */
/* rv100 might not need 64 pix alignment, who knows */
/* offsets are, hmm, weird */
- tileoffset = ((pbox[i].y1 >> 4) * depthpixperline + pbox[i].x1) >> 6;
- nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
- nrtilesy = (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
+ tileoffset =
+ ((pbox[i].y1 >> 4) * depthpixperline +
+ pbox[i].x1) >> 6;
+ nrtilesx =
+ ((pbox[i].x2 & ~63) -
+ (pbox[i].x1 & ~63)) >> 4;
+ nrtilesy =
+ (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
for (j = 0; j <= nrtilesy; j++) {
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
- OUT_RING( tileoffset * 128 );
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET3
+ (RADEON_3D_CLEAR_ZMASK, 2));
+ OUT_RING(tileoffset * 128);
/* the number of tiles to clear */
- OUT_RING( nrtilesx + 4 );
+ OUT_RING(nrtilesx + 4);
/* clear mask : chooses the clearing pattern. */
- OUT_RING( clearmask );
+ OUT_RING(clearmask);
ADVANCE_RING();
tileoffset += depthpixperline >> 6;
}
@@ -910,18 +964,19 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
}
/* TODO don't always clear all hi-level z tiles */
- if ((dev_priv->flags & CHIP_HAS_HIERZ) && (dev_priv->microcode_version==UCODE_R200)
- && (flags & RADEON_USE_HIERZ))
- /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
- /* FIXME : the mask supposedly contains low-res z values. So can't set
- just to the max (0xff? or actually 0x3fff?), need to take z clear
- value into account? */
+ if ((dev_priv->flags & CHIP_HAS_HIERZ)
+ && (dev_priv->microcode_version == UCODE_R200)
+ && (flags & RADEON_USE_HIERZ))
+ /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
+ /* FIXME : the mask supposedly contains low-res z values. So can't set
+ just to the max (0xff? or actually 0x3fff?), need to take z clear
+ value into account? */
{
- BEGIN_RING( 4 );
- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_HIZ, 2 ) );
- OUT_RING( 0x0 ); /* First tile */
- OUT_RING( 0x3cc0 );
- OUT_RING( (0xff<<22)|(0xff<<6)| 0x003f003f);
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
+ OUT_RING(0x0); /* First tile */
+ OUT_RING(0x3cc0);
+ OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
ADVANCE_RING();
}
}
@@ -956,30 +1011,27 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
tempSE_CNTL = depth_clear->se_cntl;
-
-
/* Disable TCL */
- tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
- (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
+ tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
+ (0x9 <<
+ SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
tempRB3D_PLANEMASK = 0x0;
tempRE_AUX_SCISSOR_CNTL = 0x0;
tempSE_VTE_CNTL =
- SE_VTE_CNTL__VTX_XY_FMT_MASK |
- SE_VTE_CNTL__VTX_Z_FMT_MASK;
+ SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
- /* Vertex format (X, Y, Z, W)*/
+ /* Vertex format (X, Y, Z, W) */
tempSE_VTX_FMT_0 =
- SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
- SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
+ SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
+ SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
tempSE_VTX_FMT_1 = 0x0;
-
- /*
- * Depth buffer specific enables
+ /*
+ * Depth buffer specific enables
*/
if (flags & RADEON_DEPTH) {
/* Enable depth buffer */
@@ -989,12 +1041,12 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
}
- /*
+ /*
* Stencil buffer specific enables
*/
- if ( flags & RADEON_STENCIL ) {
- tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
- tempRB3D_STENCILREFMASK = clear->depth_mask;
+ if (flags & RADEON_STENCIL) {
+ tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
+ tempRB3D_STENCILREFMASK = clear->depth_mask;
} else {
tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
tempRB3D_STENCILREFMASK = 0x00000000;
@@ -1002,79 +1054,75 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
if (flags & RADEON_USE_COMP_ZBUF) {
tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
- RADEON_Z_DECOMPRESSION_ENABLE;
+ RADEON_Z_DECOMPRESSION_ENABLE;
}
if (flags & RADEON_USE_HIERZ) {
tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
}
- BEGIN_RING( 26 );
+ BEGIN_RING(26);
RADEON_WAIT_UNTIL_2D_IDLE();
- OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
- OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
- OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
- OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
- tempRB3D_ZSTENCILCNTL );
- OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
- tempRB3D_STENCILREFMASK );
- OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
- OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
- OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
- OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
- OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
- OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
- OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL,
- tempRE_AUX_SCISSOR_CNTL );
+ OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
+ OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
+ OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
+ OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+ OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
+ tempRB3D_STENCILREFMASK);
+ OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
+ OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
+ OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
+ OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
+ OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
+ OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
+ OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
ADVANCE_RING();
/* Make sure we restore the 3D state next time.
*/
dev_priv->sarea_priv->ctx_owner = 0;
- for ( i = 0 ; i < nbox ; i++ ) {
-
- /* Funny that this should be required --
+ for (i = 0; i < nbox; i++) {
+
+ /* Funny that this should be required --
* sets top-left?
*/
- radeon_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
-
- BEGIN_RING( 14 );
- OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
- OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
- RADEON_PRIM_WALK_RING |
- (3 << RADEON_NUM_VERTICES_SHIFT)) );
- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x3f800000 );
- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x3f800000 );
- OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x3f800000 );
+ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+ BEGIN_RING(14);
+ OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
+ OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+ RADEON_PRIM_WALK_RING |
+ (3 << RADEON_NUM_VERTICES_SHIFT)));
+ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x3f800000);
+ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x3f800000);
+ OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x3f800000);
ADVANCE_RING();
}
- }
- else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
+ } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
rb3d_cntl = depth_clear->rb3d_cntl;
- if ( flags & RADEON_DEPTH ) {
- rb3d_cntl |= RADEON_Z_ENABLE;
+ if (flags & RADEON_DEPTH) {
+ rb3d_cntl |= RADEON_Z_ENABLE;
} else {
rb3d_cntl &= ~RADEON_Z_ENABLE;
}
- if ( flags & RADEON_STENCIL ) {
- rb3d_cntl |= RADEON_STENCIL_ENABLE;
- rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
+ if (flags & RADEON_STENCIL) {
+ rb3d_cntl |= RADEON_STENCIL_ENABLE;
+ rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
} else {
rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
rb3d_stencilrefmask = 0x00000000;
@@ -1082,66 +1130,61 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
if (flags & RADEON_USE_COMP_ZBUF) {
tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
- RADEON_Z_DECOMPRESSION_ENABLE;
+ RADEON_Z_DECOMPRESSION_ENABLE;
}
if (flags & RADEON_USE_HIERZ) {
tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
}
- BEGIN_RING( 13 );
+ BEGIN_RING(13);
RADEON_WAIT_UNTIL_2D_IDLE();
- OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
- OUT_RING( 0x00000000 );
- OUT_RING( rb3d_cntl );
-
- OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL );
- OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
- rb3d_stencilrefmask );
- OUT_RING_REG( RADEON_RB3D_PLANEMASK,
- 0x00000000 );
- OUT_RING_REG( RADEON_SE_CNTL,
- depth_clear->se_cntl );
+ OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
+ OUT_RING(0x00000000);
+ OUT_RING(rb3d_cntl);
+
+ OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+ OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
+ OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
+ OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
ADVANCE_RING();
/* Make sure we restore the 3D state next time.
*/
dev_priv->sarea_priv->ctx_owner = 0;
- for ( i = 0 ; i < nbox ; i++ ) {
-
- /* Funny that this should be required --
+ for (i = 0; i < nbox; i++) {
+
+ /* Funny that this should be required --
* sets top-left?
*/
- radeon_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
-
- BEGIN_RING( 15 );
-
- OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
- OUT_RING( RADEON_VTX_Z_PRESENT |
- RADEON_VTX_PKCOLOR_PRESENT);
- OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
- RADEON_PRIM_WALK_RING |
- RADEON_MAOS_ENABLE |
- RADEON_VTX_FMT_RADEON_MODE |
- (3 << RADEON_NUM_VERTICES_SHIFT)) );
-
-
- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x0 );
-
- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x0 );
-
- OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
- OUT_RING( 0x0 );
+ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+ BEGIN_RING(15);
+
+ OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
+ OUT_RING(RADEON_VTX_Z_PRESENT |
+ RADEON_VTX_PKCOLOR_PRESENT);
+ OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+ RADEON_PRIM_WALK_RING |
+ RADEON_MAOS_ENABLE |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (3 << RADEON_NUM_VERTICES_SHIFT)));
+
+ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x0);
+
+ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x0);
+
+ OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+ OUT_RING(0x0);
ADVANCE_RING();
}
@@ -1153,15 +1196,15 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
*/
dev_priv->sarea_priv->last_clear++;
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
- RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
+ RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
}
-static void radeon_cp_dispatch_swap( drm_device_t *dev )
+static void radeon_cp_dispatch_swap(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -1169,59 +1212,55 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
drm_clip_rect_t *pbox = sarea_priv->boxes;
int i;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
/* Do some trivial performance monitoring...
*/
if (dev_priv->do_boxes)
- radeon_cp_performance_boxes( dev_priv );
-
+ radeon_cp_performance_boxes(dev_priv);
/* Wait for the 3D stream to idle before dispatching the bitblt.
* This will prevent data corruption between the two streams.
*/
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
- for ( i = 0 ; i < nbox ; i++ ) {
+ for (i = 0; i < nbox; i++) {
int x = pbox[i].x1;
int y = pbox[i].y1;
int w = pbox[i].x2 - x;
int h = pbox[i].y2 - y;
- DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
- x, y, w, h );
-
- BEGIN_RING( 7 );
-
- OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
- OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- (dev_priv->color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_MEMORY |
- RADEON_GMC_CLR_CMP_CNTL_DIS |
- RADEON_GMC_WR_MSK_DIS );
-
+ DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
+
+ BEGIN_RING(7);
+
+ OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+
/* Make this work even if front & back are flipped:
*/
if (dev_priv->current_page == 0) {
- OUT_RING( dev_priv->back_pitch_offset );
- OUT_RING( dev_priv->front_pitch_offset );
- }
- else {
- OUT_RING( dev_priv->front_pitch_offset );
- OUT_RING( dev_priv->back_pitch_offset );
+ OUT_RING(dev_priv->back_pitch_offset);
+ OUT_RING(dev_priv->front_pitch_offset);
+ } else {
+ OUT_RING(dev_priv->front_pitch_offset);
+ OUT_RING(dev_priv->back_pitch_offset);
}
- OUT_RING( (x << 16) | y );
- OUT_RING( (x << 16) | y );
- OUT_RING( (w << 16) | h );
+ OUT_RING((x << 16) | y);
+ OUT_RING((x << 16) | y);
+ OUT_RING((w << 16) | h);
ADVANCE_RING();
}
@@ -1232,44 +1271,43 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
*/
dev_priv->sarea_priv->last_frame++;
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
- RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+ RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
}
-static void radeon_cp_dispatch_flip( drm_device_t *dev )
+static void radeon_cp_dispatch_flip(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
+ drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
int offset = (dev_priv->current_page == 1)
- ? dev_priv->front_offset : dev_priv->back_offset;
+ ? dev_priv->front_offset : dev_priv->back_offset;
RING_LOCALS;
- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
- __FUNCTION__,
- dev_priv->current_page,
- dev_priv->sarea_priv->pfCurrentPage);
+ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+ __FUNCTION__,
+ dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
/* Do some trivial performance monitoring...
*/
if (dev_priv->do_boxes) {
dev_priv->stats.boxes |= RADEON_BOX_FLIP;
- radeon_cp_performance_boxes( dev_priv );
+ radeon_cp_performance_boxes(dev_priv);
}
/* Update the frame offsets for both CRTCs
*/
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
RADEON_WAIT_UNTIL_3D_IDLE();
- OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
- + sarea->frame.x
- * ( dev_priv->color_fmt - 2 ) ) & ~7 )
- + offset );
- OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
- + offset );
+ OUT_RING_REG(RADEON_CRTC_OFFSET,
+ ((sarea->frame.y * dev_priv->front_pitch +
+ sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
+ + offset);
+ OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+ + offset);
ADVANCE_RING();
@@ -1279,16 +1317,16 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
*/
dev_priv->sarea_priv->last_frame++;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
- 1 - dev_priv->current_page;
+ 1 - dev_priv->current_page;
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
- RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+ RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
ADVANCE_RING();
}
-static int bad_prim_vertex_nr( int primitive, int nr )
+static int bad_prim_vertex_nr(int primitive, int nr)
{
switch (primitive & RADEON_PRIM_TYPE_MASK) {
case RADEON_PRIM_TYPE_NONE:
@@ -1308,24 +1346,21 @@ static int bad_prim_vertex_nr( int primitive, int nr )
return nr < 3;
default:
return 1;
- }
+ }
}
-
-
typedef struct {
unsigned int start;
unsigned int finish;
unsigned int prim;
unsigned int numverts;
- unsigned int offset;
- unsigned int vc_format;
+ unsigned int offset;
+ unsigned int vc_format;
} drm_radeon_tcl_prim_t;
-static void radeon_cp_dispatch_vertex( drm_device_t *dev,
- drm_buf_t *buf,
- drm_radeon_tcl_prim_t *prim )
-
+static void radeon_cp_dispatch_vertex(drm_device_t * dev,
+ drm_buf_t * buf,
+ drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -1337,45 +1372,39 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
prim->prim,
- prim->vc_format,
- prim->start,
- prim->finish,
- prim->numverts);
+ prim->vc_format, prim->start, prim->finish, prim->numverts);
- if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
- DRM_ERROR( "bad prim %x numverts %d\n",
- prim->prim, prim->numverts );
+ if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
+ DRM_ERROR("bad prim %x numverts %d\n",
+ prim->prim, prim->numverts);
return;
}
do {
/* Emit the next cliprect */
- if ( i < nbox ) {
- radeon_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
+ if (i < nbox) {
+ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
}
/* Emit the vertex buffer rendering commands */
- BEGIN_RING( 5 );
+ BEGIN_RING(5);
- OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
- OUT_RING( offset );
- OUT_RING( numverts );
- OUT_RING( prim->vc_format );
- OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
- RADEON_COLOR_ORDER_RGBA |
- RADEON_VTX_FMT_RADEON_MODE |
- (numverts << RADEON_NUM_VERTICES_SHIFT) );
+ OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
+ OUT_RING(offset);
+ OUT_RING(numverts);
+ OUT_RING(prim->vc_format);
+ OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (numverts << RADEON_NUM_VERTICES_SHIFT));
ADVANCE_RING();
i++;
- } while ( i < nbox );
+ } while (i < nbox);
}
-
-
-static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
+static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1384,24 +1413,22 @@ static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
/* Emit the vertex buffer age */
- BEGIN_RING( 2 );
- RADEON_DISPATCH_AGE( buf_priv->age );
+ BEGIN_RING(2);
+ RADEON_DISPATCH_AGE(buf_priv->age);
ADVANCE_RING();
buf->pending = 1;
buf->used = 0;
}
-static void radeon_cp_dispatch_indirect( drm_device_t *dev,
- drm_buf_t *buf,
- int start, int end )
+static void radeon_cp_dispatch_indirect(drm_device_t * dev,
+ drm_buf_t * buf, int start, int end)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
- buf->idx, start, end );
+ DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
- if ( start != end ) {
+ if (start != end) {
int offset = (dev_priv->gart_buffers_offset
+ buf->offset + start);
int dwords = (end - start + 3) / sizeof(u32);
@@ -1410,28 +1437,27 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
* dwords, so if we've been given an odd number we must
* pad the data with a Type-2 CP packet.
*/
- if ( dwords & 1 ) {
+ if (dwords & 1) {
u32 *data = (u32 *)
- ((char *)dev->agp_buffer_map->handle
- + buf->offset + start);
+ ((char *)dev->agp_buffer_map->handle
+ + buf->offset + start);
data[dwords++] = RADEON_CP_PACKET2;
}
/* Fire off the indirect buffer */
- BEGIN_RING( 3 );
+ BEGIN_RING(3);
- OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
- OUT_RING( offset );
- OUT_RING( dwords );
+ OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
+ OUT_RING(offset);
+ OUT_RING(dwords);
ADVANCE_RING();
}
}
-
-static void radeon_cp_dispatch_indices( drm_device_t *dev,
- drm_buf_t *elt_buf,
- drm_radeon_tcl_prim_t *prim )
+static void radeon_cp_dispatch_indices(drm_device_t * dev,
+ drm_buf_t * elt_buf,
+ drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -1446,30 +1472,24 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
prim->prim,
prim->vc_format,
- prim->start,
- prim->finish,
- prim->offset,
- prim->numverts);
-
- if (bad_prim_vertex_nr( prim->prim, count )) {
- DRM_ERROR( "bad prim %x count %d\n",
- prim->prim, count );
+ prim->start, prim->finish, prim->offset, prim->numverts);
+
+ if (bad_prim_vertex_nr(prim->prim, count)) {
+ DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
return;
}
-
- if ( start >= prim->finish ||
- (prim->start & 0x7) ) {
- DRM_ERROR( "buffer prim %d\n", prim->prim );
+ if (start >= prim->finish || (prim->start & 0x7)) {
+ DRM_ERROR("buffer prim %d\n", prim->prim);
return;
}
dwords = (prim->finish - prim->start + 3) / sizeof(u32);
- data = (u32 *)((char *)dev->agp_buffer_map->handle +
- elt_buf->offset + prim->start);
+ data = (u32 *) ((char *)dev->agp_buffer_map->handle +
+ elt_buf->offset + prim->start);
- data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+ data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
data[1] = offset;
data[2] = prim->numverts;
data[3] = prim->vc_format;
@@ -1477,28 +1497,26 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
RADEON_PRIM_WALK_IND |
RADEON_COLOR_ORDER_RGBA |
RADEON_VTX_FMT_RADEON_MODE |
- (count << RADEON_NUM_VERTICES_SHIFT) );
+ (count << RADEON_NUM_VERTICES_SHIFT));
do {
- if ( i < nbox )
- radeon_emit_clip_rect( dev_priv,
- &sarea_priv->boxes[i] );
+ if (i < nbox)
+ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
- radeon_cp_dispatch_indirect( dev, elt_buf,
- prim->start,
- prim->finish );
+ radeon_cp_dispatch_indirect(dev, elt_buf,
+ prim->start, prim->finish);
i++;
- } while ( i < nbox );
+ } while (i < nbox);
}
-#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
+#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
-static int radeon_cp_dispatch_texture( DRMFILE filp,
- drm_device_t *dev,
- drm_radeon_texture_t *tex,
- drm_radeon_tex_image_t *image )
+static int radeon_cp_dispatch_texture(DRMFILE filp,
+ drm_device_t * dev,
+ drm_radeon_texture_t * tex,
+ drm_radeon_tex_image_t * image)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_file_t *filp_priv;
@@ -1506,17 +1524,18 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
u32 format;
u32 *buffer;
const u8 __user *data;
- int size, dwords, tex_width, blit_width;
+ int size, dwords, tex_width, blit_width, spitch;
u32 height;
int i;
u32 texpitch, microtile;
+ u32 offset;
RING_LOCALS;
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
- DRM_ERROR( "Invalid destination offset\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
+ DRM_ERROR("Invalid destination offset\n");
+ return DRM_ERR(EINVAL);
}
dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
@@ -1525,27 +1544,16 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
* up with the texture data from the host data blit, otherwise
* part of the texture image may be corrupted.
*/
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
RADEON_FLUSH_CACHE();
RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
-#ifdef __BIG_ENDIAN
- /* The Mesa texture functions provide the data in little endian as the
- * chip wants it, but we need to compensate for the fact that the CP
- * ring gets byte-swapped
- */
- BEGIN_RING( 2 );
- OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
- ADVANCE_RING();
-#endif
-
-
/* The compiler won't optimize away a division by a variable,
* even if the only legal values are powers of two. Thus, we'll
* use a shift instead.
*/
- switch ( tex->format ) {
+ switch (tex->format) {
case RADEON_TXFORMAT_ARGB8888:
case RADEON_TXFORMAT_RGBA8888:
format = RADEON_COLOR_FORMAT_ARGB8888;
@@ -1569,9 +1577,13 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
blit_width = image->width * 1;
break;
default:
- DRM_ERROR( "invalid texture format %d\n", tex->format );
+ DRM_ERROR("invalid texture format %d\n", tex->format);
return DRM_ERR(EINVAL);
}
+ spitch = blit_width >> 6;
+ if (spitch == 0 && image->height > 1)
+ return DRM_ERR(EINVAL);
+
texpitch = tex->pitch;
if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
microtile = 1;
@@ -1580,69 +1592,50 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
/* we got tiled coordinates, untile them */
image->x *= 2;
}
- }
- else microtile = 0;
+ } else
+ microtile = 0;
- DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
+ DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
do {
- DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
- tex->offset >> 10, tex->pitch, tex->format,
- image->x, image->y, image->width, image->height );
+ DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+ tex->offset >> 10, tex->pitch, tex->format,
+ image->x, image->y, image->width, image->height);
/* Make a copy of some parameters in case we have to
* update them for a multi-pass texture blit.
*/
height = image->height;
data = (const u8 __user *)image->data;
-
+
size = height * blit_width;
- if ( size > RADEON_MAX_TEXTURE_SIZE ) {
+ if (size > RADEON_MAX_TEXTURE_SIZE) {
height = RADEON_MAX_TEXTURE_SIZE / blit_width;
size = height * blit_width;
- } else if ( size < 4 && size > 0 ) {
+ } else if (size < 4 && size > 0) {
size = 4;
- } else if ( size == 0 ) {
+ } else if (size == 0) {
return 0;
}
- buf = radeon_freelist_get( dev );
- if ( 0 && !buf ) {
- radeon_do_cp_idle( dev_priv );
- buf = radeon_freelist_get( dev );
+ buf = radeon_freelist_get(dev);
+ if (0 && !buf) {
+ radeon_do_cp_idle(dev_priv);
+ buf = radeon_freelist_get(dev);
}
- if ( !buf ) {
+ if (!buf) {
DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
- if (DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ))
+ if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
return DRM_ERR(EFAULT);
return DRM_ERR(EAGAIN);
}
-
/* Dispatch the indirect buffer.
*/
- buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
+ buffer =
+ (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
dwords = size / 4;
- buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
- buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- (format << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_HOST_DATA |
- RADEON_GMC_CLR_CMP_CNTL_DIS |
- RADEON_GMC_WR_MSK_DIS);
-
- buffer[2] = (texpitch << 22) | (tex->offset >> 10);
- buffer[3] = 0xffffffff;
- buffer[4] = 0xffffffff;
- buffer[5] = (image->y << 16) | image->x;
- buffer[6] = (height << 16) | image->width;
- buffer[7] = dwords;
- buffer += 8;
-
-
if (microtile) {
/* texture micro tiling in use, minimum texture width is thus 16 bytes.
@@ -1656,20 +1649,26 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
if (tex->height == 1) {
if (tex_width >= 64 || tex_width <= 16) {
if (DRM_COPY_FROM_USER(buffer, data,
- tex_width * sizeof(u32))) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ tex_width *
+ sizeof(u32))) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
} else if (tex_width == 32) {
- if (DRM_COPY_FROM_USER(buffer, data, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer, data, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
- if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer + 8, data + 16, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
}
@@ -1682,9 +1681,11 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
}
} else if (tex_width < 16) {
for (i = 0; i < tex->height; i++) {
- if (DRM_COPY_FROM_USER(buffer, data, tex_width)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer, data, tex_width)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
buffer += 4;
@@ -1694,35 +1695,42 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
/* TODO: make sure this works when not fitting in one buffer
(i.e. 32bytes x 2048...) */
for (i = 0; i < tex->height; i += 2) {
- if (DRM_COPY_FROM_USER(buffer, data, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer, data, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
data += 16;
- if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer + 8, data, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
data += 16;
- if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer + 4, data, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
data += 16;
- if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) {
- DRM_ERROR("EFAULT on pad, %d bytes\n",
- tex_width);
+ if (DRM_COPY_FROM_USER
+ (buffer + 12, data, 16)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
data += 16;
buffer += 16;
}
}
- }
- else {
+ } else {
if (tex_width >= 32) {
/* Texture image width is larger than the minimum, so we
* can upload it directly.
@@ -1738,9 +1746,12 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
* need to pad out each image scanline to the minimum
* width.
*/
- for (i = 0 ; i < tex->height ; i++) {
- if (DRM_COPY_FROM_USER(buffer, data, tex_width )) {
- DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width);
+ for (i = 0; i < tex->height; i++) {
+ if (DRM_COPY_FROM_USER
+ (buffer, data, tex_width)) {
+ DRM_ERROR
+ ("EFAULT on pad, %d bytes\n",
+ tex_width);
return DRM_ERR(EFAULT);
}
buffer += 8;
@@ -1750,9 +1761,27 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
}
buf->filp = filp;
- buf->used = (dwords + 8) * sizeof(u32);
- radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
- radeon_cp_discard_buffer( dev, buf );
+ buf->used = size;
+ offset = dev_priv->gart_buffers_offset + buf->offset;
+ BEGIN_RING(9);
+ OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (format << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+ OUT_RING((spitch << 22) | (offset >> 10));
+ OUT_RING((texpitch << 22) | (tex->offset >> 10));
+ OUT_RING(0);
+ OUT_RING((image->x << 16) | image->y);
+ OUT_RING((image->width << 16) | height);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+ ADVANCE_RING();
+
+ radeon_cp_discard_buffer(dev, buf);
/* Update the input parameters for next time */
image->y += height;
@@ -1764,62 +1793,62 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
* the texture data is written out to memory before rendering
* continues.
*/
- BEGIN_RING( 4 );
+ BEGIN_RING(4);
RADEON_FLUSH_CACHE();
RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
return 0;
}
-
-static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int i;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- BEGIN_RING( 35 );
+ BEGIN_RING(35);
- OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
- OUT_RING( 0x00000000 );
+ OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
+ OUT_RING(0x00000000);
- OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
- for ( i = 0 ; i < 32 ; i++ ) {
- OUT_RING( stipple[i] );
+ OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
+ for (i = 0; i < 32; i++) {
+ OUT_RING(stipple[i]);
}
ADVANCE_RING();
}
-static void radeon_apply_surface_regs(int surf_index, drm_radeon_private_t *dev_priv)
+static void radeon_apply_surface_regs(int surf_index,
+ drm_radeon_private_t * dev_priv)
{
if (!dev_priv->mmio)
return;
radeon_do_cp_idle(dev_priv);
- RADEON_WRITE(RADEON_SURFACE0_INFO + 16*surf_index,
- dev_priv->surfaces[surf_index].flags);
- RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*surf_index,
- dev_priv->surfaces[surf_index].lower);
- RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*surf_index,
- dev_priv->surfaces[surf_index].upper);
+ RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
+ dev_priv->surfaces[surf_index].flags);
+ RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
+ dev_priv->surfaces[surf_index].lower);
+ RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
+ dev_priv->surfaces[surf_index].upper);
}
-
/* Allocates a virtual surface
- * doesn't always allocate a real surface, will stretch an existing
+ * doesn't always allocate a real surface, will stretch an existing
* surface when possible.
*
* Note that refcount can be at most 2, since during a free refcount=3
* might mean we have to allocate a new surface which might not always
* be available.
- * For example : we allocate three contigous surfaces ABC. If B is
+ * For example : we allocate three contigous surfaces ABC. If B is
* freed, we suddenly need two surfaces to store A and C, which might
* not always be available.
*/
-static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *dev_priv, DRMFILE filp)
+static int alloc_surface(drm_radeon_surface_alloc_t * new,
+ drm_radeon_private_t * dev_priv, DRMFILE filp)
{
struct radeon_virt_surface *s;
int i;
@@ -1831,34 +1860,37 @@ static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *
/* sanity check */
if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
- ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != RADEON_SURF_ADDRESS_FIXED_MASK) ||
- ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
+ ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
+ RADEON_SURF_ADDRESS_FIXED_MASK)
+ || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
return -1;
/* make sure there is no overlap with existing surfaces */
for (i = 0; i < RADEON_MAX_SURFACES; i++) {
if ((dev_priv->surfaces[i].refcount != 0) &&
- (( (new_lower >= dev_priv->surfaces[i].lower) &&
- (new_lower < dev_priv->surfaces[i].upper) ) ||
- ( (new_lower < dev_priv->surfaces[i].lower) &&
- (new_upper > dev_priv->surfaces[i].lower) )) ){
- return -1;}
+ (((new_lower >= dev_priv->surfaces[i].lower) &&
+ (new_lower < dev_priv->surfaces[i].upper)) ||
+ ((new_lower < dev_priv->surfaces[i].lower) &&
+ (new_upper > dev_priv->surfaces[i].lower)))) {
+ return -1;
+ }
}
/* find a virtual surface */
- for (i = 0; i < 2*RADEON_MAX_SURFACES; i++)
+ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
if (dev_priv->virt_surfaces[i].filp == 0)
break;
- if (i == 2*RADEON_MAX_SURFACES) {
- return -1;}
+ if (i == 2 * RADEON_MAX_SURFACES) {
+ return -1;
+ }
virt_surface_index = i;
/* try to reuse an existing surface */
for (i = 0; i < RADEON_MAX_SURFACES; i++) {
/* extend before */
if ((dev_priv->surfaces[i].refcount == 1) &&
- (new->flags == dev_priv->surfaces[i].flags) &&
- (new_upper + 1 == dev_priv->surfaces[i].lower)) {
+ (new->flags == dev_priv->surfaces[i].flags) &&
+ (new_upper + 1 == dev_priv->surfaces[i].lower)) {
s = &(dev_priv->virt_surfaces[virt_surface_index]);
s->surface_index = i;
s->lower = new_lower;
@@ -1873,8 +1905,8 @@ static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *
/* extend after */
if ((dev_priv->surfaces[i].refcount == 1) &&
- (new->flags == dev_priv->surfaces[i].flags) &&
- (new_lower == dev_priv->surfaces[i].upper + 1)) {
+ (new->flags == dev_priv->surfaces[i].flags) &&
+ (new_lower == dev_priv->surfaces[i].upper + 1)) {
s = &(dev_priv->virt_surfaces[virt_surface_index]);
s->surface_index = i;
s->lower = new_lower;
@@ -1910,26 +1942,34 @@ static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *
return -1;
}
-static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower)
+static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
+ int lower)
{
struct radeon_virt_surface *s;
int i;
/* find the virtual surface */
- for(i = 0; i < 2*RADEON_MAX_SURFACES; i++) {
+ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
s = &(dev_priv->virt_surfaces[i]);
if (s->filp) {
if ((lower == s->lower) && (filp == s->filp)) {
- if (dev_priv->surfaces[s->surface_index].lower == s->lower)
- dev_priv->surfaces[s->surface_index].lower = s->upper;
+ if (dev_priv->surfaces[s->surface_index].
+ lower == s->lower)
+ dev_priv->surfaces[s->surface_index].
+ lower = s->upper;
- if (dev_priv->surfaces[s->surface_index].upper == s->upper)
- dev_priv->surfaces[s->surface_index].upper = s->lower;
+ if (dev_priv->surfaces[s->surface_index].
+ upper == s->upper)
+ dev_priv->surfaces[s->surface_index].
+ upper = s->lower;
dev_priv->surfaces[s->surface_index].refcount--;
- if (dev_priv->surfaces[s->surface_index].refcount == 0)
- dev_priv->surfaces[s->surface_index].flags = 0;
+ if (dev_priv->surfaces[s->surface_index].
+ refcount == 0)
+ dev_priv->surfaces[s->surface_index].
+ flags = 0;
s->filp = NULL;
- radeon_apply_surface_regs(s->surface_index, dev_priv);
+ radeon_apply_surface_regs(s->surface_index,
+ dev_priv);
return 0;
}
}
@@ -1937,13 +1977,14 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower)
return 1;
}
-static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t *dev_priv)
+static void radeon_surfaces_release(DRMFILE filp,
+ drm_radeon_private_t * dev_priv)
{
int i;
- for( i = 0; i < 2*RADEON_MAX_SURFACES; i++)
- {
+ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
if (dev_priv->virt_surfaces[i].filp == filp)
- free_surface(filp, dev_priv, dev_priv->virt_surfaces[i].lower);
+ free_surface(filp, dev_priv,
+ dev_priv->virt_surfaces[i].lower);
}
}
@@ -1957,12 +1998,13 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS)
drm_radeon_surface_alloc_t alloc;
if (!dev_priv) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *)data,
- sizeof(alloc));
+ DRM_COPY_FROM_USER_IOCTL(alloc,
+ (drm_radeon_surface_alloc_t __user *) data,
+ sizeof(alloc));
if (alloc_surface(&alloc, dev_priv, filp) == -1)
return DRM_ERR(EINVAL);
@@ -1977,12 +2019,12 @@ static int radeon_surface_free(DRM_IOCTL_ARGS)
drm_radeon_surface_free_t memfree;
if (!dev_priv) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *)data,
- sizeof(memfree) );
+ DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+ sizeof(memfree));
if (free_surface(filp, dev_priv, memfree.address))
return DRM_ERR(EINVAL);
@@ -1990,51 +2032,52 @@ static int radeon_surface_free(DRM_IOCTL_ARGS)
return 0;
}
-static int radeon_cp_clear( DRM_IOCTL_ARGS )
+static int radeon_cp_clear(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_radeon_clear_t clear;
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t __user *)data,
- sizeof(clear) );
+ DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
+ sizeof(clear));
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
- if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes,
- sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
+ if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
+ sarea_priv->nbox * sizeof(depth_boxes[0])))
return DRM_ERR(EFAULT);
- radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
+ radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
COMMIT_RING();
return 0;
}
-
/* Not sure why this isn't set all the time:
- */
-static int radeon_do_init_pageflip( drm_device_t *dev )
+ */
+static int radeon_do_init_pageflip(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- BEGIN_RING( 6 );
+ BEGIN_RING(6);
RADEON_WAIT_UNTIL_3D_IDLE();
- OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
- OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
- OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
- OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
+ OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
+ OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
+ RADEON_CRTC_OFFSET_FLIP_CNTL);
+ OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
+ OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
+ RADEON_CRTC_OFFSET_FLIP_CNTL);
ADVANCE_RING();
dev_priv->page_flipping = 1;
@@ -2047,62 +2090,62 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
/* Called whenever a client dies, from drm_release.
* NOTE: Lock isn't necessarily held when this is called!
*/
-static int radeon_do_cleanup_pageflip( drm_device_t *dev )
+static int radeon_do_cleanup_pageflip(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
if (dev_priv->current_page != 0)
- radeon_cp_dispatch_flip( dev );
+ radeon_cp_dispatch_flip(dev);
dev_priv->page_flipping = 0;
return 0;
}
/* Swapping and flipping are different operations, need different ioctls.
- * They can & should be intermixed to support multiple 3d windows.
+ * They can & should be intermixed to support multiple 3d windows.
*/
-static int radeon_cp_flip( DRM_IOCTL_ARGS )
+static int radeon_cp_flip(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
- LOCK_TEST_WITH_RETURN( dev, filp );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ if (!dev_priv->page_flipping)
+ radeon_do_init_pageflip(dev);
- if (!dev_priv->page_flipping)
- radeon_do_init_pageflip( dev );
-
- radeon_cp_dispatch_flip( dev );
+ radeon_cp_dispatch_flip(dev);
COMMIT_RING();
return 0;
}
-static int radeon_cp_swap( DRM_IOCTL_ARGS )
+static int radeon_cp_swap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- DRM_DEBUG( "\n" );
+ DRM_DEBUG("\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
- radeon_cp_dispatch_swap( dev );
+ radeon_cp_dispatch_swap(dev);
dev_priv->sarea_priv->ctx_owner = 0;
COMMIT_RING();
return 0;
}
-static int radeon_cp_vertex( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2113,55 +2156,53 @@ static int radeon_cp_vertex( DRM_IOCTL_ARGS )
drm_radeon_vertex_t vertex;
drm_radeon_tcl_prim_t prim;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
- sizeof(vertex) );
+ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
+ sizeof(vertex));
- DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
- DRM_CURRENTPID,
- vertex.idx, vertex.count, vertex.discard );
+ DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+ DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- vertex.idx, dma->buf_count - 1 );
+ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- if ( vertex.prim < 0 ||
- vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
- DRM_ERROR( "buffer prim %d\n", vertex.prim );
+ if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+ DRM_ERROR("buffer prim %d\n", vertex.prim);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf = dma->buflist[vertex.idx];
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
return DRM_ERR(EINVAL);
}
/* Build up a prim_t record:
*/
if (vertex.count) {
- buf->used = vertex.count; /* not used? */
-
- if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- if ( radeon_emit_state( dev_priv, filp_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty ) ) {
- DRM_ERROR( "radeon_emit_state failed\n" );
- return DRM_ERR( EINVAL );
+ buf->used = vertex.count; /* not used? */
+
+ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+ if (radeon_emit_state(dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty)) {
+ DRM_ERROR("radeon_emit_state failed\n");
+ return DRM_ERR(EINVAL);
}
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
@@ -2171,23 +2212,23 @@ static int radeon_cp_vertex( DRM_IOCTL_ARGS )
}
prim.start = 0;
- prim.finish = vertex.count; /* unused */
+ prim.finish = vertex.count; /* unused */
prim.prim = vertex.prim;
prim.numverts = vertex.count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
-
- radeon_cp_dispatch_vertex( dev, buf, &prim );
+
+ radeon_cp_dispatch_vertex(dev, buf, &prim);
}
if (vertex.discard) {
- radeon_cp_discard_buffer( dev, buf );
+ radeon_cp_discard_buffer(dev, buf);
}
COMMIT_RING();
return 0;
}
-static int radeon_cp_indices( DRM_IOCTL_ARGS )
+static int radeon_cp_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2199,69 +2240,67 @@ static int radeon_cp_indices( DRM_IOCTL_ARGS )
drm_radeon_tcl_prim_t prim;
int count;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t __user *)data,
- sizeof(elts) );
+ DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
+ sizeof(elts));
- DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n",
- DRM_CURRENTPID,
- elts.idx, elts.start, elts.end, elts.discard );
+ DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
+ DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
- if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- elts.idx, dma->buf_count - 1 );
+ if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ elts.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- if ( elts.prim < 0 ||
- elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
- DRM_ERROR( "buffer prim %d\n", elts.prim );
+ if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+ DRM_ERROR("buffer prim %d\n", elts.prim);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf = dma->buflist[elts.idx];
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", elts.idx);
return DRM_ERR(EINVAL);
}
count = (elts.end - elts.start) / sizeof(u16);
elts.start -= RADEON_INDEX_PRIM_OFFSET;
- if ( elts.start & 0x7 ) {
- DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+ if (elts.start & 0x7) {
+ DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
return DRM_ERR(EINVAL);
}
- if ( elts.start < buf->used ) {
- DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+ if (elts.start < buf->used) {
+ DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
return DRM_ERR(EINVAL);
}
buf->used = elts.end;
- if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- if ( radeon_emit_state( dev_priv, filp_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty ) ) {
- DRM_ERROR( "radeon_emit_state failed\n" );
- return DRM_ERR( EINVAL );
+ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+ if (radeon_emit_state(dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty)) {
+ DRM_ERROR("radeon_emit_state failed\n");
+ return DRM_ERR(EINVAL);
}
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
@@ -2270,26 +2309,25 @@ static int radeon_cp_indices( DRM_IOCTL_ARGS )
RADEON_REQUIRE_QUIESCENCE);
}
-
/* Build up a prim_t record:
*/
prim.start = elts.start;
- prim.finish = elts.end;
+ prim.finish = elts.end;
prim.prim = elts.prim;
prim.offset = 0; /* offset from start of dma buffers */
- prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
prim.vc_format = dev_priv->sarea_priv->vc_format;
-
- radeon_cp_dispatch_indices( dev, buf, &prim );
+
+ radeon_cp_dispatch_indices(dev, buf, &prim);
if (elts.discard) {
- radeon_cp_discard_buffer( dev, buf );
+ radeon_cp_discard_buffer(dev, buf);
}
COMMIT_RING();
return 0;
}
-static int radeon_cp_texture( DRM_IOCTL_ARGS )
+static int radeon_cp_texture(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2297,53 +2335,54 @@ static int radeon_cp_texture( DRM_IOCTL_ARGS )
drm_radeon_tex_image_t image;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t __user *)data, sizeof(tex) );
+ DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
+ sizeof(tex));
- if ( tex.image == NULL ) {
- DRM_ERROR( "null texture image!\n" );
+ if (tex.image == NULL) {
+ DRM_ERROR("null texture image!\n");
return DRM_ERR(EINVAL);
}
- if ( DRM_COPY_FROM_USER( &image,
- (drm_radeon_tex_image_t __user *)tex.image,
- sizeof(image) ) )
+ if (DRM_COPY_FROM_USER(&image,
+ (drm_radeon_tex_image_t __user *) tex.image,
+ sizeof(image)))
return DRM_ERR(EFAULT);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
- ret = radeon_cp_dispatch_texture( filp, dev, &tex, &image );
+ ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
COMMIT_RING();
return ret;
}
-static int radeon_cp_stipple( DRM_IOCTL_ARGS )
+static int radeon_cp_stipple(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_stipple_t stipple;
u32 mask[32];
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t __user *)data,
- sizeof(stipple) );
+ DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
+ sizeof(stipple));
- if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) )
+ if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
return DRM_ERR(EFAULT);
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
- radeon_cp_dispatch_stipple( dev, mask );
+ radeon_cp_dispatch_stipple(dev, mask);
COMMIT_RING();
return 0;
}
-static int radeon_cp_indirect( DRM_IOCTL_ARGS )
+static int radeon_cp_indirect(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2352,53 +2391,53 @@ static int radeon_cp_indirect( DRM_IOCTL_ARGS )
drm_radeon_indirect_t indirect;
RING_LOCALS;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t __user *)data,
- sizeof(indirect) );
+ DRM_COPY_FROM_USER_IOCTL(indirect,
+ (drm_radeon_indirect_t __user *) data,
+ sizeof(indirect));
- DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
- indirect.idx, indirect.start,
- indirect.end, indirect.discard );
+ DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
+ indirect.idx, indirect.start, indirect.end, indirect.discard);
- if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- indirect.idx, dma->buf_count - 1 );
+ if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ indirect.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
buf = dma->buflist[indirect.idx];
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", indirect.idx);
return DRM_ERR(EINVAL);
}
- if ( indirect.start < buf->used ) {
- DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
- indirect.start, buf->used );
+ if (indirect.start < buf->used) {
+ DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+ indirect.start, buf->used);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf->used = indirect.end;
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2D acceleration commands is processed.
*/
- BEGIN_RING( 2 );
+ BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
@@ -2408,17 +2447,16 @@ static int radeon_cp_indirect( DRM_IOCTL_ARGS )
* X server. This is insecure and is thus only available to
* privileged clients.
*/
- radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+ radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
if (indirect.discard) {
- radeon_cp_discard_buffer( dev, buf );
+ radeon_cp_discard_buffer(dev, buf);
}
-
COMMIT_RING();
return 0;
}
-static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2430,65 +2468,64 @@ static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
int i;
unsigned char laststate;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t __user *)data,
- sizeof(vertex) );
+ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
+ sizeof(vertex));
- DRM_DEBUG( "pid=%d index=%d discard=%d\n",
- DRM_CURRENTPID,
- vertex.idx, vertex.discard );
+ DRM_DEBUG("pid=%d index=%d discard=%d\n",
+ DRM_CURRENTPID, vertex.idx, vertex.discard);
- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- vertex.idx, dma->buf_count - 1 );
+ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1);
return DRM_ERR(EINVAL);
}
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
buf = dma->buflist[vertex.idx];
- if ( buf->filp != filp ) {
- DRM_ERROR( "process %d using buffer owned by %p\n",
- DRM_CURRENTPID, buf->filp );
+ if (buf->filp != filp) {
+ DRM_ERROR("process %d using buffer owned by %p\n",
+ DRM_CURRENTPID, buf->filp);
return DRM_ERR(EINVAL);
}
- if ( buf->pending ) {
- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ if (buf->pending) {
+ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
return DRM_ERR(EINVAL);
}
-
+
if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
return DRM_ERR(EINVAL);
- for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
+ for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
drm_radeon_prim_t prim;
drm_radeon_tcl_prim_t tclprim;
-
- if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) )
+
+ if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
return DRM_ERR(EFAULT);
-
- if ( prim.stateidx != laststate ) {
- drm_radeon_state_t state;
-
- if ( DRM_COPY_FROM_USER( &state,
- &vertex.state[prim.stateidx],
- sizeof(state) ) )
+
+ if (prim.stateidx != laststate) {
+ drm_radeon_state_t state;
+
+ if (DRM_COPY_FROM_USER(&state,
+ &vertex.state[prim.stateidx],
+ sizeof(state)))
return DRM_ERR(EFAULT);
- if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
- DRM_ERROR( "radeon_emit_state2 failed\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
+ DRM_ERROR("radeon_emit_state2 failed\n");
+ return DRM_ERR(EINVAL);
}
laststate = prim.stateidx;
@@ -2499,42 +2536,40 @@ static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
tclprim.prim = prim.prim;
tclprim.vc_format = prim.vc_format;
- if ( prim.prim & RADEON_PRIM_WALK_IND ) {
+ if (prim.prim & RADEON_PRIM_WALK_IND) {
tclprim.offset = prim.numverts * 64;
- tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+ tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
- radeon_cp_dispatch_indices( dev, buf, &tclprim );
+ radeon_cp_dispatch_indices(dev, buf, &tclprim);
} else {
tclprim.numverts = prim.numverts;
- tclprim.offset = 0; /* not used */
+ tclprim.offset = 0; /* not used */
- radeon_cp_dispatch_vertex( dev, buf, &tclprim );
+ radeon_cp_dispatch_vertex(dev, buf, &tclprim);
}
-
+
if (sarea_priv->nbox == 1)
sarea_priv->nbox = 0;
}
- if ( vertex.discard ) {
- radeon_cp_discard_buffer( dev, buf );
+ if (vertex.discard) {
+ radeon_cp_discard_buffer(dev, buf);
}
COMMIT_RING();
return 0;
}
-
-static int radeon_emit_packets(
- drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- drm_radeon_cmd_header_t header,
- drm_radeon_cmd_buffer_t *cmdbuf )
+static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
+ drm_file_t * filp_priv,
+ drm_radeon_cmd_header_t header,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int id = (int)header.packet.packet_id;
int sz, reg;
int *data = (int *)cmdbuf->buf;
RING_LOCALS;
-
+
if (id >= RADEON_MAX_STATE_PACKETS)
return DRM_ERR(EINVAL);
@@ -2542,18 +2577,18 @@ static int radeon_emit_packets(
reg = packet[id].start;
if (sz * sizeof(int) > cmdbuf->bufsz) {
- DRM_ERROR( "Packet size provided larger than data provided\n" );
+ DRM_ERROR("Packet size provided larger than data provided\n");
return DRM_ERR(EINVAL);
}
- if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
- DRM_ERROR( "Packet verification failed\n" );
- return DRM_ERR( EINVAL );
+ if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
+ DRM_ERROR("Packet verification failed\n");
+ return DRM_ERR(EINVAL);
}
- BEGIN_RING(sz+1);
- OUT_RING( CP_PACKET0( reg, (sz-1) ) );
- OUT_RING_TABLE( data, sz );
+ BEGIN_RING(sz + 1);
+ OUT_RING(CP_PACKET0(reg, (sz - 1)));
+ OUT_RING_TABLE(data, sz);
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
@@ -2561,21 +2596,20 @@ static int radeon_emit_packets(
return 0;
}
-static __inline__ int radeon_emit_scalars(
- drm_radeon_private_t *dev_priv,
- drm_radeon_cmd_header_t header,
- drm_radeon_cmd_buffer_t *cmdbuf )
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
+ drm_radeon_cmd_header_t header,
+ drm_radeon_kcmd_buffer_t * cmdbuf)
{
int sz = header.scalars.count;
int start = header.scalars.offset;
int stride = header.scalars.stride;
RING_LOCALS;
- BEGIN_RING( 3+sz );
- OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
- OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
- OUT_RING_TABLE( cmdbuf->buf, sz );
+ BEGIN_RING(3 + sz);
+ OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+ OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+ OUT_RING_TABLE(cmdbuf->buf, sz);
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
@@ -2584,42 +2618,40 @@ static __inline__ int radeon_emit_scalars(
/* God this is ugly
*/
-static __inline__ int radeon_emit_scalars2(
- drm_radeon_private_t *dev_priv,
- drm_radeon_cmd_header_t header,
- drm_radeon_cmd_buffer_t *cmdbuf )
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
+ drm_radeon_cmd_header_t header,
+ drm_radeon_kcmd_buffer_t * cmdbuf)
{
int sz = header.scalars.count;
int start = ((unsigned int)header.scalars.offset) + 0x100;
int stride = header.scalars.stride;
RING_LOCALS;
- BEGIN_RING( 3+sz );
- OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
- OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
- OUT_RING_TABLE( cmdbuf->buf, sz );
+ BEGIN_RING(3 + sz);
+ OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+ OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+ OUT_RING_TABLE(cmdbuf->buf, sz);
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
return 0;
}
-static __inline__ int radeon_emit_vectors(
- drm_radeon_private_t *dev_priv,
- drm_radeon_cmd_header_t header,
- drm_radeon_cmd_buffer_t *cmdbuf )
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
+ drm_radeon_cmd_header_t header,
+ drm_radeon_kcmd_buffer_t * cmdbuf)
{
int sz = header.vectors.count;
int start = header.vectors.offset;
int stride = header.vectors.stride;
RING_LOCALS;
- BEGIN_RING( 3+sz );
- OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
- OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
- OUT_RING_TABLE( cmdbuf->buf, sz );
+ BEGIN_RING(3 + sz);
+ OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+ OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+ OUT_RING_TABLE(cmdbuf->buf, sz);
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
@@ -2627,10 +2659,9 @@ static __inline__ int radeon_emit_vectors(
return 0;
}
-
-static int radeon_emit_packet3( drm_device_t *dev,
- drm_file_t *filp_priv,
- drm_radeon_cmd_buffer_t *cmdbuf )
+static int radeon_emit_packet3(drm_device_t * dev,
+ drm_file_t * filp_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int cmdsz;
@@ -2639,14 +2670,14 @@ static int radeon_emit_packet3( drm_device_t *dev,
DRM_DEBUG("\n");
- if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
- cmdbuf, &cmdsz ) ) ) {
- DRM_ERROR( "Packet verification failed\n" );
+ if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+ cmdbuf, &cmdsz))) {
+ DRM_ERROR("Packet verification failed\n");
return ret;
}
- BEGIN_RING( cmdsz );
- OUT_RING_TABLE( cmdbuf->buf, cmdsz );
+ BEGIN_RING(cmdsz);
+ OUT_RING_TABLE(cmdbuf->buf, cmdsz);
ADVANCE_RING();
cmdbuf->buf += cmdsz * 4;
@@ -2654,11 +2685,10 @@ static int radeon_emit_packet3( drm_device_t *dev,
return 0;
}
-
-static int radeon_emit_packet3_cliprect( drm_device_t *dev,
- drm_file_t *filp_priv,
- drm_radeon_cmd_buffer_t *cmdbuf,
- int orig_nbox )
+static int radeon_emit_packet3_cliprect(drm_device_t * dev,
+ drm_file_t * filp_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
+ int orig_nbox)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
@@ -2670,9 +2700,9 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
DRM_DEBUG("\n");
- if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
- cmdbuf, &cmdsz ) ) ) {
- DRM_ERROR( "Packet verification failed\n" );
+ if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+ cmdbuf, &cmdsz))) {
+ DRM_ERROR("Packet verification failed\n");
return ret;
}
@@ -2680,8 +2710,8 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
goto out;
do {
- if ( i < cmdbuf->nbox ) {
- if (DRM_COPY_FROM_USER( &box, &boxes[i], sizeof(box) ))
+ if (i < cmdbuf->nbox) {
+ if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
return DRM_ERR(EFAULT);
/* FIXME The second and subsequent times round
* this loop, send a WAIT_UNTIL_3D_IDLE before
@@ -2695,30 +2725,29 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
* the correct place to fix it but this works
* around it until I can figure that out - Tim
* Smith */
- if ( i ) {
- BEGIN_RING( 2 );
+ if (i) {
+ BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
}
- radeon_emit_clip_rect( dev_priv, &box );
+ radeon_emit_clip_rect(dev_priv, &box);
}
-
- BEGIN_RING( cmdsz );
- OUT_RING_TABLE( cmdbuf->buf, cmdsz );
+
+ BEGIN_RING(cmdsz);
+ OUT_RING_TABLE(cmdbuf->buf, cmdsz);
ADVANCE_RING();
- } while ( ++i < cmdbuf->nbox );
- if (cmdbuf->nbox == 1)
+ } while (++i < cmdbuf->nbox);
+ if (cmdbuf->nbox == 1)
cmdbuf->nbox = 0;
- out:
+ out:
cmdbuf->buf += cmdsz * 4;
cmdbuf->bufsz -= cmdsz * 4;
return 0;
}
-
-static int radeon_emit_wait( drm_device_t *dev, int flags )
+static int radeon_emit_wait(drm_device_t * dev, int flags)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -2726,18 +2755,18 @@ static int radeon_emit_wait( drm_device_t *dev, int flags )
DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
switch (flags) {
case RADEON_WAIT_2D:
- BEGIN_RING( 2 );
- RADEON_WAIT_UNTIL_2D_IDLE();
+ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
break;
case RADEON_WAIT_3D:
- BEGIN_RING( 2 );
- RADEON_WAIT_UNTIL_3D_IDLE();
+ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
break;
- case RADEON_WAIT_2D|RADEON_WAIT_3D:
- BEGIN_RING( 2 );
- RADEON_WAIT_UNTIL_IDLE();
+ case RADEON_WAIT_2D | RADEON_WAIT_3D:
+ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
break;
default:
@@ -2747,7 +2776,7 @@ static int radeon_emit_wait( drm_device_t *dev, int flags )
return 0;
}
-static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
+static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2755,27 +2784,28 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf = NULL;
int idx;
- drm_radeon_cmd_buffer_t cmdbuf;
+ drm_radeon_kcmd_buffer_t cmdbuf;
drm_radeon_cmd_header_t header;
int orig_nbox, orig_bufsz;
- char *kbuf=NULL;
+ char *kbuf = NULL;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t __user *)data,
- sizeof(cmdbuf) );
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf,
+ (drm_radeon_cmd_buffer_t __user *) data,
+ sizeof(cmdbuf));
- RING_SPACE_TEST_WITH_RETURN( dev_priv );
- VB_AGE_TEST_WITH_RETURN( dev_priv );
+ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+ VB_AGE_TEST_WITH_RETURN(dev_priv);
- if (cmdbuf.bufsz > 64*1024 || cmdbuf.bufsz<0) {
+ if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
return DRM_ERR(EINVAL);
}
@@ -2788,7 +2818,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
if (kbuf == NULL)
return DRM_ERR(ENOMEM);
- if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
+ if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) {
drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
return DRM_ERR(EFAULT);
}
@@ -2797,16 +2827,28 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
orig_nbox = cmdbuf.nbox;
- while ( cmdbuf.bufsz >= sizeof(header) ) {
+ if (dev_priv->microcode_version == UCODE_R300) {
+ int temp;
+ temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
+
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+ return temp;
+ }
+
+ /* microcode_version != r300 */
+ while (cmdbuf.bufsz >= sizeof(header)) {
header.i = *(int *)cmdbuf.buf;
cmdbuf.buf += sizeof(header);
cmdbuf.bufsz -= sizeof(header);
switch (header.header.cmd_type) {
- case RADEON_CMD_PACKET:
+ case RADEON_CMD_PACKET:
DRM_DEBUG("RADEON_CMD_PACKET\n");
- if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
+ if (radeon_emit_packets
+ (dev_priv, filp_priv, header, &cmdbuf)) {
DRM_ERROR("radeon_emit_packets failed\n");
goto err;
}
@@ -2814,7 +2856,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_SCALARS:
DRM_DEBUG("RADEON_CMD_SCALARS\n");
- if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
+ if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
DRM_ERROR("radeon_emit_scalars failed\n");
goto err;
}
@@ -2822,7 +2864,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_VECTORS:
DRM_DEBUG("RADEON_CMD_VECTORS\n");
- if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
+ if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
DRM_ERROR("radeon_emit_vectors failed\n");
goto err;
}
@@ -2831,25 +2873,25 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_DMA_DISCARD:
DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
idx = header.dma.buf_idx;
- if ( idx < 0 || idx >= dma->buf_count ) {
- DRM_ERROR( "buffer index %d (of %d max)\n",
- idx, dma->buf_count - 1 );
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("buffer index %d (of %d max)\n",
+ idx, dma->buf_count - 1);
goto err;
}
buf = dma->buflist[idx];
- if ( buf->filp != filp || buf->pending ) {
- DRM_ERROR( "bad buffer %p %p %d\n",
- buf->filp, filp, buf->pending);
+ if (buf->filp != filp || buf->pending) {
+ DRM_ERROR("bad buffer %p %p %d\n",
+ buf->filp, filp, buf->pending);
goto err;
}
- radeon_cp_discard_buffer( dev, buf );
+ radeon_cp_discard_buffer(dev, buf);
break;
case RADEON_CMD_PACKET3:
DRM_DEBUG("RADEON_CMD_PACKET3\n");
- if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
+ if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
DRM_ERROR("radeon_emit_packet3 failed\n");
goto err;
}
@@ -2857,7 +2899,8 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_PACKET3_CLIP:
DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
- if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
+ if (radeon_emit_packet3_cliprect
+ (dev, filp_priv, &cmdbuf, orig_nbox)) {
DRM_ERROR("radeon_emit_packet3_clip failed\n");
goto err;
}
@@ -2865,7 +2908,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_SCALARS2:
DRM_DEBUG("RADEON_CMD_SCALARS2\n");
- if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
+ if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
DRM_ERROR("radeon_emit_scalars2 failed\n");
goto err;
}
@@ -2873,13 +2916,13 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_WAIT:
DRM_DEBUG("RADEON_CMD_WAIT\n");
- if (radeon_emit_wait( dev, header.wait.flags )) {
+ if (radeon_emit_wait(dev, header.wait.flags)) {
DRM_ERROR("radeon_emit_wait failed\n");
goto err;
}
break;
default:
- DRM_ERROR("bad cmd_type %d at %p\n",
+ DRM_ERROR("bad cmd_type %d at %p\n",
header.header.cmd_type,
cmdbuf.buf - sizeof(header));
goto err;
@@ -2893,45 +2936,43 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
COMMIT_RING();
return 0;
-err:
+ err:
if (orig_bufsz != 0)
drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
return DRM_ERR(EINVAL);
}
-
-
-static int radeon_cp_getparam( DRM_IOCTL_ARGS )
+static int radeon_cp_getparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_getparam_t param;
int value;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t __user *)data,
- sizeof(param) );
+ DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
+ sizeof(param));
- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
- switch( param.param ) {
+ switch (param.param) {
case RADEON_PARAM_GART_BUFFER_OFFSET:
value = dev_priv->gart_buffers_offset;
break;
case RADEON_PARAM_LAST_FRAME:
dev_priv->stats.last_frame_reads++;
- value = GET_SCRATCH( 0 );
+ value = GET_SCRATCH(0);
break;
case RADEON_PARAM_LAST_DISPATCH:
- value = GET_SCRATCH( 1 );
+ value = GET_SCRATCH(1);
break;
case RADEON_PARAM_LAST_CLEAR:
dev_priv->stats.last_clear_reads++;
- value = GET_SCRATCH( 2 );
+ value = GET_SCRATCH(2);
break;
case RADEON_PARAM_IRQ_NR:
value = dev->irq;
@@ -2946,15 +2987,15 @@ static int radeon_cp_getparam( DRM_IOCTL_ARGS )
value = dev_priv->ring_rptr_offset;
break;
#if BITS_PER_LONG == 32
- /*
- * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
- * pointer which can't fit into an int-sized variable. According to
- * Michel Dänzer, the ioctl() is only used on embedded platforms, so
- * not supporting it shouldn't be a problem. If the same functionality
- * is needed on 64-bit platforms, a new ioctl() would have to be added,
- * so backwards-compatibility for the embedded platforms can be
- * maintained. --davidm 4-Feb-2004.
- */
+ /*
+ * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
+ * pointer which can't fit into an int-sized variable. According to
+ * Michel Dänzer, the ioctl() is only used on embedded platforms, so
+ * not supporting it shouldn't be a problem. If the same functionality
+ * is needed on 64-bit platforms, a new ioctl() would have to be added,
+ * so backwards-compatibility for the embedded platforms can be
+ * maintained. --davidm 4-Feb-2004.
+ */
case RADEON_PARAM_SAREA_HANDLE:
/* The lock is the first dword in the sarea. */
value = (long)dev->lock.hw_lock;
@@ -2967,53 +3008,56 @@ static int radeon_cp_getparam( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
- DRM_ERROR( "copy_to_user\n" );
+ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+ DRM_ERROR("copy_to_user\n");
return DRM_ERR(EFAULT);
}
-
+
return 0;
}
-static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+static int radeon_cp_setparam(DRM_IOCTL_ARGS)
+{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_file_t *filp_priv;
drm_radeon_setparam_t sp;
struct drm_radeon_driver_file_fields *radeon_priv;
- if ( !dev_priv ) {
- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
- return DRM_ERR( EINVAL );
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
}
- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
- DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t __user * )data,
- sizeof( sp ) );
+ DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
+ sizeof(sp));
- switch( sp.param ) {
+ switch (sp.param) {
case RADEON_SETPARAM_FB_LOCATION:
radeon_priv = filp_priv->driver_priv;
radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
break;
case RADEON_SETPARAM_SWITCH_TILING:
if (sp.value == 0) {
- DRM_DEBUG( "color tiling disabled\n" );
+ DRM_DEBUG("color tiling disabled\n");
dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
dev_priv->sarea_priv->tiling_enabled = 0;
- }
- else if (sp.value == 1) {
- DRM_DEBUG( "color tiling enabled\n" );
+ } else if (sp.value == 1) {
+ DRM_DEBUG("color tiling enabled\n");
dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
dev_priv->sarea_priv->tiling_enabled = 1;
}
- break;
+ break;
+ case RADEON_SETPARAM_PCIGART_LOCATION:
+ dev_priv->pcigart_offset = sp.value;
+ break;
default:
- DRM_DEBUG( "Invalid parameter %d\n", sp.param );
- return DRM_ERR( EINVAL );
+ DRM_DEBUG("Invalid parameter %d\n", sp.param);
+ return DRM_ERR(EINVAL);
}
return 0;
@@ -3025,78 +3069,80 @@ static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
-void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
{
- if ( dev->dev_private ) {
- drm_radeon_private_t *dev_priv = dev->dev_private;
- if ( dev_priv->page_flipping ) {
- radeon_do_cleanup_pageflip( dev );
- }
- radeon_mem_release( filp, dev_priv->gart_heap );
- radeon_mem_release( filp, dev_priv->fb_heap );
+ if (dev->dev_private) {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ if (dev_priv->page_flipping) {
+ radeon_do_cleanup_pageflip(dev);
+ }
+ radeon_mem_release(filp, dev_priv->gart_heap);
+ radeon_mem_release(filp, dev_priv->fb_heap);
radeon_surfaces_release(filp, dev_priv);
- }
+ }
}
-void radeon_driver_pretakedown(drm_device_t *dev)
+void radeon_driver_pretakedown(drm_device_t * dev)
{
radeon_do_release(dev);
}
-int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
+int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_driver_file_fields *radeon_priv;
-
- radeon_priv = (struct drm_radeon_driver_file_fields *)drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
-
+
+ radeon_priv =
+ (struct drm_radeon_driver_file_fields *)
+ drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+
if (!radeon_priv)
return -ENOMEM;
filp_priv->driver_priv = radeon_priv;
- if ( dev_priv )
+ if (dev_priv)
radeon_priv->radeon_fb_delta = dev_priv->fb_location;
else
radeon_priv->radeon_fb_delta = 0;
return 0;
}
-
-void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
+void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
{
- struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
-
- drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+ struct drm_radeon_driver_file_fields *radeon_priv =
+ filp_priv->driver_priv;
+
+ drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
}
drm_ioctl_desc_t radeon_ioctls[] = {
- [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FREE)] = { radeon_mem_free, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = { radeon_mem_init_heap,1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = { radeon_surface_free, 1, 0 }
+ [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
};
int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
new file mode 100644
index 000000000000..6d10515795cc
--- /dev/null
+++ b/drivers/char/drm/savage_bci.c
@@ -0,0 +1,1099 @@
+/* savage_bci.c -- BCI support for Savage
+ *
+ * Copyright 2004 Felix Kuehling
+ * 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 FELIX KUEHLING 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 "savage_drm.h"
+#include "savage_drv.h"
+
+/* Need a long timeout for shadow status updates can take a while
+ * and so can waiting for events when the queue is full. */
+#define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */
+#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
+#define SAVAGE_FREELIST_DEBUG 0
+
+static int
+savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
+{
+ uint32_t mask = dev_priv->status_used_mask;
+ uint32_t threshold = dev_priv->bci_threshold_hi;
+ uint32_t status;
+ int i;
+
+#if SAVAGE_BCI_DEBUG
+ if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold)
+ DRM_ERROR("Trying to emit %d words "
+ "(more than guaranteed space in COB)\n", n);
+#endif
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ DRM_MEMORYBARRIER();
+ status = dev_priv->status_ptr[0];
+ if ((status & mask) < threshold)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, threshold=0x%08x\n", status, threshold);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n)
+{
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_STATUS_WORD0);
+ if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x\n", status);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n)
+{
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0);
+ if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x\n", status);
+#endif
+ return DRM_ERR(EBUSY);
+}
+
+/*
+ * Waiting for events.
+ *
+ * The BIOSresets the event tag to 0 on mode changes. Therefore we
+ * never emit 0 to the event tag. If we find a 0 event tag we know the
+ * BIOS stomped on it and return success assuming that the BIOS waited
+ * for engine idle.
+ *
+ * Note: if the Xserver uses the event tag it has to follow the same
+ * rule. Otherwise there may be glitches every 2^16 events.
+ */
+static int
+savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
+{
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+ DRM_MEMORYBARRIER();
+ status = dev_priv->status_ptr[1];
+ if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+ (status & 0xffff) == 0)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+ return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e)
+{
+ uint32_t status;
+ int i;
+
+ for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+ status = SAVAGE_READ(SAVAGE_STATUS_WORD1);
+ if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+ (status & 0xffff) == 0)
+ return 0;
+ DRM_UDELAY(1);
+ }
+
+#if SAVAGE_BCI_DEBUG
+ DRM_ERROR("failed!\n");
+ DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+ return DRM_ERR(EBUSY);
+}
+
+uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+ unsigned int flags)
+{
+ uint16_t count;
+ BCI_LOCALS;
+
+ if (dev_priv->status_ptr) {
+ /* coordinate with Xserver */
+ count = dev_priv->status_ptr[1023];
+ if (count < dev_priv->event_counter)
+ dev_priv->event_wrap++;
+ } else {
+ count = dev_priv->event_counter;
+ }
+ count = (count + 1) & 0xffff;
+ if (count == 0) {
+ count++; /* See the comment above savage_wait_event_*. */
+ dev_priv->event_wrap++;
+ }
+ dev_priv->event_counter = count;
+ if (dev_priv->status_ptr)
+ dev_priv->status_ptr[1023] = (uint32_t) count;
+
+ if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
+ unsigned int wait_cmd = BCI_CMD_WAIT;
+ if ((flags & SAVAGE_WAIT_2D))
+ wait_cmd |= BCI_CMD_WAIT_2D;
+ if ((flags & SAVAGE_WAIT_3D))
+ wait_cmd |= BCI_CMD_WAIT_3D;
+ BEGIN_BCI(2);
+ BCI_WRITE(wait_cmd);
+ } else {
+ BEGIN_BCI(1);
+ }
+ BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t) count);
+
+ return count;
+}
+
+/*
+ * Freelist management
+ */
+static int savage_freelist_init(drm_device_t * dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_savage_buf_priv_t *entry;
+ int i;
+ DRM_DEBUG("count=%d\n", dma->buf_count);
+
+ dev_priv->head.next = &dev_priv->tail;
+ dev_priv->head.prev = NULL;
+ dev_priv->head.buf = NULL;
+
+ dev_priv->tail.next = NULL;
+ dev_priv->tail.prev = &dev_priv->head;
+ dev_priv->tail.buf = NULL;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ entry = buf->dev_private;
+
+ SET_AGE(&entry->age, 0, 0);
+ entry->buf = buf;
+
+ entry->next = dev_priv->head.next;
+ entry->prev = &dev_priv->head;
+ dev_priv->head.next->prev = entry;
+ dev_priv->head.next = entry;
+ }
+
+ return 0;
+}
+
+static drm_buf_t *savage_freelist_get(drm_device_t * dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
+ uint16_t event;
+ unsigned int wrap;
+ DRM_DEBUG("\n");
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ event = dev_priv->status_ptr[1] & 0xffff;
+ else
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ DRM_DEBUG(" tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
+ DRM_DEBUG(" head=0x%04x %d\n", event, wrap);
+
+ if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) {
+ drm_savage_buf_priv_t *next = tail->next;
+ drm_savage_buf_priv_t *prev = tail->prev;
+ prev->next = next;
+ next->prev = prev;
+ tail->next = tail->prev = NULL;
+ return tail->buf;
+ }
+
+ DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf);
+ return NULL;
+}
+
+void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
+
+ DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap);
+
+ if (entry->next != NULL || entry->prev != NULL) {
+ DRM_ERROR("entry already on freelist.\n");
+ return;
+ }
+
+ prev = &dev_priv->head;
+ next = prev->next;
+ prev->next = entry;
+ next->prev = entry;
+ entry->prev = prev;
+ entry->next = next;
+}
+
+/*
+ * Command DMA
+ */
+static int savage_dma_init(drm_savage_private_t * dev_priv)
+{
+ unsigned int i;
+
+ dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
+ (SAVAGE_DMA_PAGE_SIZE * 4);
+ dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
+ dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+ if (dev_priv->dma_pages == NULL)
+ return DRM_ERR(ENOMEM);
+
+ for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ SET_AGE(&dev_priv->last_dma_age, 0, 0);
+
+ dev_priv->first_dma_page = 0;
+ dev_priv->current_dma_page = 0;
+
+ return 0;
+}
+
+void savage_dma_reset(drm_savage_private_t * dev_priv)
+{
+ uint16_t event;
+ unsigned int wrap, i;
+ event = savage_bci_emit_event(dev_priv, 0);
+ wrap = dev_priv->event_wrap;
+ for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ SET_AGE(&dev_priv->last_dma_age, event, wrap);
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page)
+{
+ uint16_t event;
+ unsigned int wrap;
+
+ /* Faked DMA buffer pages don't age. */
+ if (dev_priv->cmd_dma == &dev_priv->fake_dma)
+ return;
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ event = dev_priv->status_ptr[1] & 0xffff;
+ else
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ if (dev_priv->dma_pages[page].age.wrap > wrap ||
+ (dev_priv->dma_pages[page].age.wrap == wrap &&
+ dev_priv->dma_pages[page].age.event > event)) {
+ if (dev_priv->wait_evnt(dev_priv,
+ dev_priv->dma_pages[page].age.event)
+ < 0)
+ DRM_ERROR("wait_evnt failed!\n");
+ }
+}
+
+uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, unsigned int n)
+{
+ unsigned int cur = dev_priv->current_dma_page;
+ unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
+ dev_priv->dma_pages[cur].used;
+ unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE - 1) /
+ SAVAGE_DMA_PAGE_SIZE;
+ uint32_t *dma_ptr;
+ unsigned int i;
+
+ DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",
+ cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
+
+ if (cur + nr_pages < dev_priv->nr_dma_pages) {
+ dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+ cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+ if (n < rest)
+ rest = n;
+ dev_priv->dma_pages[cur].used += rest;
+ n -= rest;
+ cur++;
+ } else {
+ dev_priv->dma_flush(dev_priv);
+ nr_pages =
+ (n + SAVAGE_DMA_PAGE_SIZE - 1) / SAVAGE_DMA_PAGE_SIZE;
+ for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
+ dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle;
+ dev_priv->first_dma_page = cur = 0;
+ }
+ for (i = cur; nr_pages > 0; ++i, --nr_pages) {
+#if SAVAGE_DMA_DEBUG
+ if (dev_priv->dma_pages[i].used) {
+ DRM_ERROR("unflushed page %u: used=%u\n",
+ i, dev_priv->dma_pages[i].used);
+ }
+#endif
+ if (n > SAVAGE_DMA_PAGE_SIZE)
+ dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;
+ else
+ dev_priv->dma_pages[i].used = n;
+ n -= SAVAGE_DMA_PAGE_SIZE;
+ }
+ dev_priv->current_dma_page = --i;
+
+ DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",
+ i, dev_priv->dma_pages[i].used, n);
+
+ savage_dma_wait(dev_priv, dev_priv->current_dma_page);
+
+ return dma_ptr;
+}
+
+static void savage_dma_flush(drm_savage_private_t * dev_priv)
+{
+ unsigned int first = dev_priv->first_dma_page;
+ unsigned int cur = dev_priv->current_dma_page;
+ uint16_t event;
+ unsigned int wrap, pad, align, len, i;
+ unsigned long phys_addr;
+ BCI_LOCALS;
+
+ if (first == cur &&
+ dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
+ return;
+
+ /* pad length to multiples of 2 entries
+ * align start of next DMA block to multiles of 8 entries */
+ pad = -dev_priv->dma_pages[cur].used & 1;
+ align = -(dev_priv->dma_pages[cur].used + pad) & 7;
+
+ DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "
+ "pad=%u, align=%u\n",
+ first, cur, dev_priv->dma_pages[first].flushed,
+ dev_priv->dma_pages[cur].used, pad, align);
+
+ /* pad with noops */
+ if (pad) {
+ uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+ cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+ dev_priv->dma_pages[cur].used += pad;
+ while (pad != 0) {
+ *dma_ptr++ = BCI_CMD_WAIT;
+ pad--;
+ }
+ }
+
+ DRM_MEMORYBARRIER();
+
+ /* do flush ... */
+ phys_addr = dev_priv->cmd_dma->offset +
+ (first * SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[first].flushed) * 4;
+ len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
+ dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed;
+
+ DRM_DEBUG("phys_addr=%lx, len=%u\n",
+ phys_addr | dev_priv->dma_type, len);
+
+ BEGIN_BCI(3);
+ BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);
+ BCI_WRITE(phys_addr | dev_priv->dma_type);
+ BCI_DMA(len);
+
+ /* fix alignment of the start of the next block */
+ dev_priv->dma_pages[cur].used += align;
+
+ /* age DMA pages */
+ event = savage_bci_emit_event(dev_priv, 0);
+ wrap = dev_priv->event_wrap;
+ for (i = first; i < cur; ++i) {
+ SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+ /* age the current page only when it's full */
+ if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {
+ SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);
+ dev_priv->dma_pages[cur].used = 0;
+ dev_priv->dma_pages[cur].flushed = 0;
+ /* advance to next page */
+ cur++;
+ if (cur == dev_priv->nr_dma_pages)
+ cur = 0;
+ dev_priv->first_dma_page = dev_priv->current_dma_page = cur;
+ } else {
+ dev_priv->first_dma_page = cur;
+ dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;
+ }
+ SET_AGE(&dev_priv->last_dma_age, event, wrap);
+
+ DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,
+ dev_priv->dma_pages[cur].used,
+ dev_priv->dma_pages[cur].flushed);
+}
+
+static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
+{
+ unsigned int i, j;
+ BCI_LOCALS;
+
+ if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
+ dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
+ return;
+
+ DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",
+ dev_priv->first_dma_page, dev_priv->current_dma_page,
+ dev_priv->dma_pages[dev_priv->current_dma_page].used);
+
+ for (i = dev_priv->first_dma_page;
+ i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
+ ++i) {
+ uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+ i * SAVAGE_DMA_PAGE_SIZE;
+#if SAVAGE_DMA_DEBUG
+ /* Sanity check: all pages except the last one must be full. */
+ if (i < dev_priv->current_dma_page &&
+ dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {
+ DRM_ERROR("partial DMA page %u: used=%u",
+ i, dev_priv->dma_pages[i].used);
+ }
+#endif
+ BEGIN_BCI(dev_priv->dma_pages[i].used);
+ for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {
+ BCI_WRITE(dma_ptr[j]);
+ }
+ dev_priv->dma_pages[i].used = 0;
+ }
+
+ /* reset to first page */
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+/*
+ * Initalize mappings. On Savage4 and SavageIX the alignment
+ * and size of the aperture is not suitable for automatic MTRR setup
+ * in drm_addmap. Therefore we do it manually before the maps are
+ * initialized. We also need to take care of deleting the MTRRs in
+ * postcleanup.
+ */
+int savage_preinit(drm_device_t * dev, unsigned long chipset)
+{
+ drm_savage_private_t *dev_priv;
+ unsigned long mmio_base, fb_base, fb_size, aperture_base;
+ /* fb_rsrc and aper_rsrc aren't really used currently, but still exist
+ * in case we decide we need information on the BAR for BSD in the
+ * future.
+ */
+ unsigned int fb_rsrc, aper_rsrc;
+ int ret = 0;
+
+ dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+
+ memset(dev_priv, 0, sizeof(drm_savage_private_t));
+ dev->dev_private = (void *)dev_priv;
+ dev_priv->chipset = (enum savage_family)chipset;
+
+ dev_priv->mtrr[0].handle = -1;
+ dev_priv->mtrr[1].handle = -1;
+ dev_priv->mtrr[2].handle = -1;
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ fb_rsrc = 0;
+ fb_base = drm_get_resource_start(dev, 0);
+ fb_size = SAVAGE_FB_SIZE_S3;
+ mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
+ aper_rsrc = 0;
+ aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+ /* this should always be true */
+ if (drm_get_resource_len(dev, 0) == 0x08000000) {
+ /* Don't make MMIO write-cobining! We need 3
+ * MTRRs. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x01000000;
+ dev_priv->mtrr[0].handle =
+ mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB,
+ 1);
+ dev_priv->mtrr[1].base = fb_base + 0x02000000;
+ dev_priv->mtrr[1].size = 0x02000000;
+ dev_priv->mtrr[1].handle =
+ mtrr_add(dev_priv->mtrr[1].base,
+ dev_priv->mtrr[1].size, MTRR_TYPE_WRCOMB,
+ 1);
+ dev_priv->mtrr[2].base = fb_base + 0x04000000;
+ dev_priv->mtrr[2].size = 0x04000000;
+ dev_priv->mtrr[2].handle =
+ mtrr_add(dev_priv->mtrr[2].base,
+ dev_priv->mtrr[2].size, MTRR_TYPE_WRCOMB,
+ 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 0));
+ }
+ } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
+ fb_size = SAVAGE_FB_SIZE_S4;
+ aper_rsrc = 1;
+ aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+ /* this should always be true */
+ if (drm_get_resource_len(dev, 1) == 0x08000000) {
+ /* Can use one MTRR to cover both fb and
+ * aperture. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x08000000;
+ dev_priv->mtrr[0].handle =
+ mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB,
+ 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 1));
+ }
+ } else {
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
+ fb_size = drm_get_resource_len(dev, 1);
+ aper_rsrc = 2;
+ aperture_base = drm_get_resource_start(dev, 2);
+ /* Automatic MTRR setup will do the right thing. */
+ }
+
+ ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,
+ _DRM_READ_ONLY, &dev_priv->mmio);
+ if (ret)
+ return ret;
+
+ ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,
+ _DRM_WRITE_COMBINING, &dev_priv->fb);
+ if (ret)
+ return ret;
+
+ ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+ _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+ &dev_priv->aperture);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+/*
+ * Delete MTRRs and free device-private data.
+ */
+int savage_postcleanup(drm_device_t * dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ if (dev_priv->mtrr[i].handle >= 0)
+ mtrr_del(dev_priv->mtrr[i].handle,
+ dev_priv->mtrr[i].base,
+ dev_priv->mtrr[i].size);
+
+ drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+
+ return 0;
+}
+
+static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+ if (init->fb_bpp != 16 && init->fb_bpp != 32) {
+ DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->depth_bpp != 16 && init->depth_bpp != 32) {
+ DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->dma_type != SAVAGE_DMA_AGP &&
+ init->dma_type != SAVAGE_DMA_PCI) {
+ DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->cob_size = init->cob_size;
+ dev_priv->bci_threshold_lo = init->bci_threshold_lo;
+ dev_priv->bci_threshold_hi = init->bci_threshold_hi;
+ dev_priv->dma_type = init->dma_type;
+
+ dev_priv->fb_bpp = init->fb_bpp;
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
+ dev_priv->depth_bpp = init->depth_bpp;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+
+ dev_priv->texture_offset = init->texture_offset;
+ dev_priv->texture_size = init->texture_size;
+
+ DRM_GETSAREA();
+ if (!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (init->status_offset != 0) {
+ dev_priv->status = drm_core_findmap(dev, init->status_offset);
+ if (!dev_priv->status) {
+ DRM_ERROR("could not find shadow status region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->status = NULL;
+ }
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {
+ dev->agp_buffer_map = drm_core_findmap(dev,
+ init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("could not find DMA buffer region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ drm_core_ioremap(dev->agp_buffer_map, dev);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("failed to ioremap DMA buffer region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ }
+ if (init->agp_textures_offset) {
+ dev_priv->agp_textures =
+ drm_core_findmap(dev, init->agp_textures_offset);
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->agp_textures = NULL;
+ }
+
+ if (init->cmd_dma_offset) {
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ DRM_ERROR("command DMA not supported on "
+ "Savage3D/MX/IX.\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (dev->dma && dev->dma->buflist) {
+ DRM_ERROR("command and vertex DMA not supported "
+ "at the same time.\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
+ if (!dev_priv->cmd_dma) {
+ DRM_ERROR("could not find command DMA region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
+ if (dev_priv->cmd_dma->type != _DRM_AGP) {
+ DRM_ERROR("AGP command DMA region is not a "
+ "_DRM_AGP map!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ drm_core_ioremap(dev_priv->cmd_dma, dev);
+ if (!dev_priv->cmd_dma->handle) {
+ DRM_ERROR("failed to ioremap command "
+ "DMA region!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
+ DRM_ERROR("PCI command DMA region is not a "
+ "_DRM_CONSISTENT map!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ dev_priv->cmd_dma = NULL;
+ }
+
+ dev_priv->dma_flush = savage_dma_flush;
+ if (!dev_priv->cmd_dma) {
+ DRM_DEBUG("falling back to faked command DMA.\n");
+ dev_priv->fake_dma.offset = 0;
+ dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
+ dev_priv->fake_dma.type = _DRM_SHM;
+ dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
+ DRM_MEM_DRIVER);
+ if (!dev_priv->fake_dma.handle) {
+ DRM_ERROR("could not allocate faked DMA buffer!\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->cmd_dma = &dev_priv->fake_dma;
+ dev_priv->dma_flush = savage_fake_dma_flush;
+ }
+
+ dev_priv->sarea_priv =
+ (drm_savage_sarea_t *) ((uint8_t *) dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ /* setup bitmap descriptors */
+ {
+ unsigned int color_tile_format;
+ unsigned int depth_tile_format;
+ unsigned int front_stride, back_stride, depth_stride;
+ if (dev_priv->chipset <= S3_SAVAGE4) {
+ color_tile_format = dev_priv->fb_bpp == 16 ?
+ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ depth_tile_format = dev_priv->depth_bpp == 16 ?
+ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ } else {
+ color_tile_format = SAVAGE_BD_TILE_DEST;
+ depth_tile_format = SAVAGE_BD_TILE_DEST;
+ }
+ front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8);
+ back_stride = dev_priv->back_pitch / (dev_priv->fb_bpp / 8);
+ depth_stride =
+ dev_priv->depth_pitch / (dev_priv->depth_bpp / 8);
+
+ dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+ dev_priv->back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+ dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
+ (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
+ (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
+ }
+
+ /* setup status and bci ptr */
+ dev_priv->event_counter = 0;
+ dev_priv->event_wrap = 0;
+ dev_priv->bci_ptr = (volatile uint32_t *)
+ ((uint8_t *) dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
+ } else {
+ dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4;
+ }
+ if (dev_priv->status != NULL) {
+ dev_priv->status_ptr =
+ (volatile uint32_t *)dev_priv->status->handle;
+ dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
+ dev_priv->wait_evnt = savage_bci_wait_event_shadow;
+ dev_priv->status_ptr[1023] = dev_priv->event_counter;
+ } else {
+ dev_priv->status_ptr = NULL;
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ dev_priv->wait_fifo = savage_bci_wait_fifo_s3d;
+ } else {
+ dev_priv->wait_fifo = savage_bci_wait_fifo_s4;
+ }
+ dev_priv->wait_evnt = savage_bci_wait_event_reg;
+ }
+
+ /* cliprect functions */
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset))
+ dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d;
+ else
+ dev_priv->emit_clip_rect = savage_emit_clip_rect_s4;
+
+ if (savage_freelist_init(dev) < 0) {
+ DRM_ERROR("could not initialize freelist\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+
+ if (savage_dma_init(dev_priv) < 0) {
+ DRM_ERROR("could not initialize command DMA\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+ }
+
+ return 0;
+}
+
+int savage_do_cleanup_bci(drm_device_t * dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+ if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
+ if (dev_priv->fake_dma.handle)
+ drm_free(dev_priv->fake_dma.handle,
+ SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+ } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
+ dev_priv->cmd_dma->type == _DRM_AGP &&
+ dev_priv->dma_type == SAVAGE_DMA_AGP)
+ drm_core_ioremapfree(dev_priv->cmd_dma, dev);
+
+ if (dev_priv->dma_type == SAVAGE_DMA_AGP &&
+ dev->agp_buffer_map && dev->agp_buffer_map->handle) {
+ drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ /* make sure the next instance (which may be running
+ * in PCI mode) doesn't try to use an old
+ * agp_buffer_map. */
+ dev->agp_buffer_map = NULL;
+ }
+
+ if (dev_priv->dma_pages)
+ drm_free(dev_priv->dma_pages,
+ sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
+ DRM_MEM_DRIVER);
+
+ return 0;
+}
+
+static int savage_bci_init(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_init_t init;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *) data,
+ sizeof(init));
+
+ switch (init.func) {
+ case SAVAGE_INIT_BCI:
+ return savage_do_init_bci(dev, &init);
+ case SAVAGE_CLEANUP_BCI:
+ return savage_do_cleanup_bci(dev);
+ }
+
+ return DRM_ERR(EINVAL);
+}
+
+static int savage_bci_event_emit(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_event_emit_t event;
+
+ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *) data,
+ sizeof(event));
+
+ event.count = savage_bci_emit_event(dev_priv, event.flags);
+ event.count |= dev_priv->event_wrap << 16;
+ DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *) data)->
+ count, event.count, sizeof(event.count));
+ return 0;
+}
+
+static int savage_bci_event_wait(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_event_wait_t event;
+ unsigned int event_e, hw_e;
+ unsigned int event_w, hw_w;
+
+ DRM_DEBUG("\n");
+
+ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *) data,
+ sizeof(event));
+
+ UPDATE_EVENT_COUNTER();
+ if (dev_priv->status_ptr)
+ hw_e = dev_priv->status_ptr[1] & 0xffff;
+ else
+ hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ hw_w = dev_priv->event_wrap;
+ if (hw_e > dev_priv->event_counter)
+ hw_w--; /* hardware hasn't passed the last wrap yet */
+
+ event_e = event.count & 0xffff;
+ event_w = event.count >> 16;
+
+ /* Don't need to wait if
+ * - event counter wrapped since the event was emitted or
+ * - the hardware has advanced up to or over the event to wait for.
+ */
+ if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e))
+ return 0;
+ else
+ return dev_priv->wait_evnt(dev_priv, event_e);
+}
+
+/*
+ * DMA buffer management
+ */
+
+static int savage_bci_get_buffers(DRMFILE filp, drm_device_t * dev,
+ drm_dma_t * d)
+{
+ drm_buf_t *buf;
+ int i;
+
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = savage_freelist_get(dev);
+ if (!buf)
+ return DRM_ERR(EAGAIN);
+
+ buf->filp = filp;
+
+ if (DRM_COPY_TO_USER(&d->request_indices[i],
+ &buf->idx, sizeof(buf->idx)))
+ return DRM_ERR(EFAULT);
+ if (DRM_COPY_TO_USER(&d->request_sizes[i],
+ &buf->total, sizeof(buf->total)))
+ return DRM_ERR(EFAULT);
+
+ d->granted_count++;
+ }
+ return 0;
+}
+
+int savage_bci_buffers(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_dma_t d;
+ int ret = 0;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *) data, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d.send_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* We'll send you buffers.
+ */
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d.request_count, dma->buf_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ d.granted_count = 0;
+
+ if (d.request_count) {
+ ret = savage_bci_get_buffers(filp, dev, &d);
+ }
+
+ DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *) data, d, sizeof(d));
+
+ return ret;
+}
+
+void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ if (!dma)
+ return;
+ if (!dev_priv)
+ return;
+ if (!dma->buflist)
+ return;
+
+ /*i830_flush_queue(dev); */
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_savage_buf_priv_t *buf_priv = buf->dev_private;
+
+ if (buf->filp == filp && buf_priv &&
+ buf_priv->next == NULL && buf_priv->prev == NULL) {
+ uint16_t event;
+ DRM_DEBUG("reclaimed from client\n");
+ event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+ SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+ savage_freelist_put(dev, buf);
+ }
+ }
+
+ drm_core_reclaim_buffers(dev, filp);
+}
+
+drm_ioctl_desc_t savage_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, 1, 0},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, 1, 0},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, 1, 0},
+};
+
+int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
new file mode 100644
index 000000000000..e1148e8e7994
--- /dev/null
+++ b/drivers/char/drm/savage_drm.h
@@ -0,0 +1,210 @@
+/* savage_drm.h -- Public header for the savage driver
+ *
+ * Copyright 2004 Felix Kuehling
+ * 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 FELIX KUEHLING 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 __SAVAGE_DRM_H__
+#define __SAVAGE_DRM_H__
+
+#ifndef __SAVAGE_SAREA_DEFINES__
+#define __SAVAGE_SAREA_DEFINES__
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define SAVAGE_CARD_HEAP 0
+#define SAVAGE_AGP_HEAP 1
+#define SAVAGE_NR_TEX_HEAPS 2
+#define SAVAGE_NR_TEX_REGIONS 16
+#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
+
+#endif /* __SAVAGE_SAREA_DEFINES__ */
+
+typedef struct _drm_savage_sarea {
+ /* LRU lists for texture memory in agp space and on the card.
+ */
+ drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
+ 1];
+ unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
+
+ /* Mechanism to validate card state.
+ */
+ int ctxOwner;
+} drm_savage_sarea_t, *drm_savage_sarea_ptr;
+
+/* Savage-specific ioctls
+ */
+#define DRM_SAVAGE_BCI_INIT 0x00
+#define DRM_SAVAGE_BCI_CMDBUF 0x01
+#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02
+#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03
+
+#define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
+#define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
+#define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
+#define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
+
+#define SAVAGE_DMA_PCI 1
+#define SAVAGE_DMA_AGP 3
+typedef struct drm_savage_init {
+ enum {
+ SAVAGE_INIT_BCI = 1,
+ SAVAGE_CLEANUP_BCI = 2
+ } func;
+ unsigned int sarea_priv_offset;
+
+ /* some parameters */
+ unsigned int cob_size;
+ unsigned int bci_threshold_lo, bci_threshold_hi;
+ unsigned int dma_type;
+
+ /* frame buffer layout */
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ /* local textures */
+ unsigned int texture_offset;
+ unsigned int texture_size;
+
+ /* physical locations of non-permanent maps */
+ unsigned long status_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+ unsigned long cmd_dma_offset;
+} drm_savage_init_t;
+
+typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
+typedef struct drm_savage_cmdbuf {
+ /* command buffer in client's address space */
+ drm_savage_cmd_header_t __user *cmd_addr;
+ unsigned int size; /* size of the command buffer in 64bit units */
+
+ unsigned int dma_idx; /* DMA buffer index to use */
+ int discard; /* discard DMA buffer when done */
+ /* vertex buffer in client's address space */
+ unsigned int __user *vb_addr;
+ unsigned int vb_size; /* size of client vertex buffer in bytes */
+ unsigned int vb_stride; /* stride of vertices in 32bit words */
+ /* boxes in client's address space */
+ drm_clip_rect_t __user *box_addr;
+ unsigned int nbox; /* number of clipping boxes */
+} drm_savage_cmdbuf_t;
+
+#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */
+#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */
+#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */
+typedef struct drm_savage_event {
+ unsigned int count;
+ unsigned int flags;
+} drm_savage_event_emit_t, drm_savage_event_wait_t;
+
+/* Commands for the cmdbuf ioctl
+ */
+#define SAVAGE_CMD_STATE 0 /* a range of state registers */
+#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */
+#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */
+#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */
+#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */
+#define SAVAGE_CMD_CLEAR 5 /* clear buffers */
+#define SAVAGE_CMD_SWAP 6 /* swap buffers */
+
+/* Primitive types
+*/
+#define SAVAGE_PRIM_TRILIST 0 /* triangle list */
+#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */
+#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */
+#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat
+ * shading on s3d */
+
+/* Skip flags (vertex format)
+ */
+#define SAVAGE_SKIP_Z 0x01
+#define SAVAGE_SKIP_W 0x02
+#define SAVAGE_SKIP_C0 0x04
+#define SAVAGE_SKIP_C1 0x08
+#define SAVAGE_SKIP_S0 0x10
+#define SAVAGE_SKIP_T0 0x20
+#define SAVAGE_SKIP_ST0 0x30
+#define SAVAGE_SKIP_S1 0x40
+#define SAVAGE_SKIP_T1 0x80
+#define SAVAGE_SKIP_ST1 0xc0
+#define SAVAGE_SKIP_ALL_S3D 0x3f
+#define SAVAGE_SKIP_ALL_S4 0xff
+
+/* Buffer names for clear command
+ */
+#define SAVAGE_FRONT 0x1
+#define SAVAGE_BACK 0x2
+#define SAVAGE_DEPTH 0x4
+
+/* 64-bit command header
+ */
+union drm_savage_cmd_header {
+ struct {
+ unsigned char cmd; /* command */
+ unsigned char pad0;
+ unsigned short pad1;
+ unsigned short pad2;
+ unsigned short pad3;
+ } cmd; /* generic */
+ struct {
+ unsigned char cmd;
+ unsigned char global; /* need idle engine? */
+ unsigned short count; /* number of consecutive registers */
+ unsigned short start; /* first register */
+ unsigned short pad3;
+ } state; /* SAVAGE_CMD_STATE */
+ struct {
+ unsigned char cmd;
+ unsigned char prim; /* primitive type */
+ unsigned short skip; /* vertex format (skip flags) */
+ unsigned short count; /* number of vertices */
+ unsigned short start; /* first vertex in DMA/vertex buffer */
+ } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
+ struct {
+ unsigned char cmd;
+ unsigned char prim;
+ unsigned short skip;
+ unsigned short count; /* number of indices that follow */
+ unsigned short pad3;
+ } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
+ struct {
+ unsigned char cmd;
+ unsigned char pad0;
+ unsigned short pad1;
+ unsigned int flags;
+ } clear0; /* SAVAGE_CMD_CLEAR */
+ struct {
+ unsigned int mask;
+ unsigned int value;
+ } clear1; /* SAVAGE_CMD_CLEAR data */
+};
+
+#endif
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
new file mode 100644
index 000000000000..22d799cde41c
--- /dev/null
+++ b/drivers/char/drm/savage_drv.c
@@ -0,0 +1,107 @@
+/* savage_drv.c -- Savage driver for Linux
+ *
+ * Copyright 2004 Felix Kuehling
+ * 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 FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+#include "drm_pciids.h"
+
+static int postinit(struct drm_device *dev, unsigned long flags)
+{
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
+ return 0;
+}
+
+static int version(drm_version_t * version)
+{
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+}
+
+static struct pci_device_id pciidlist[] = {
+ savage_PCI_IDS
+};
+
+static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
+ .dev_priv_size = sizeof(drm_savage_buf_priv_t),
+ .preinit = savage_preinit,
+ .postinit = postinit,
+ .postcleanup = savage_postcleanup,
+ .reclaim_buffers = savage_reclaim_buffers,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .version = version,
+ .ioctls = savage_ioctls,
+ .dma_ioctl = savage_bci_buffers,
+ .fops = {
+ .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,
+ }
+};
+
+static int __init savage_init(void)
+{
+ driver.num_ioctls = savage_max_ioctl;
+ return drm_init(&driver);
+}
+
+static void __exit savage_exit(void)
+{
+ drm_exit(&driver);
+}
+
+module_init(savage_init);
+module_exit(savage_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
new file mode 100644
index 000000000000..a4b0fa998a95
--- /dev/null
+++ b/drivers/char/drm/savage_drv.h
@@ -0,0 +1,582 @@
+/* savage_drv.h -- Private header for the savage driver
+ *
+ * Copyright 2004 Felix Kuehling
+ * 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 FELIX KUEHLING 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 __SAVAGE_DRV_H__
+#define __SAVAGE_DRV_H__
+
+#define DRIVER_AUTHOR "Felix Kuehling"
+
+#define DRIVER_NAME "savage"
+#define DRIVER_DESC "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
+#define DRIVER_DATE "20050313"
+
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 4
+#define DRIVER_PATCHLEVEL 1
+/* Interface history:
+ *
+ * 1.x The DRM driver from the VIA/S3 code drop, basically a dummy
+ * 2.0 The first real DRM
+ * 2.1 Scissors registers managed by the DRM, 3D operations clipped by
+ * cliprects of the cmdbuf ioctl
+ * 2.2 Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
+ * 2.3 Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
+ * wide and thus very long lived (unlikely to ever wrap). The size
+ * in the struct was 32 bits before, but only 16 bits were used
+ * 2.4 Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
+ * actually used
+ */
+
+typedef struct drm_savage_age {
+ uint16_t event;
+ unsigned int wrap;
+} drm_savage_age_t;
+
+typedef struct drm_savage_buf_priv {
+ struct drm_savage_buf_priv *next;
+ struct drm_savage_buf_priv *prev;
+ drm_savage_age_t age;
+ drm_buf_t *buf;
+} drm_savage_buf_priv_t;
+
+typedef struct drm_savage_dma_page {
+ drm_savage_age_t age;
+ unsigned int used, flushed;
+} drm_savage_dma_page_t;
+#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
+/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
+ * size of 16kbytes or 4k entries. Minimum requirement would be
+ * 10kbytes for 255 40-byte vertices in one drawing command. */
+#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
+
+/* interesting bits of hardware state that are saved in dev_priv */
+typedef union {
+ struct drm_savage_common_state {
+ uint32_t vbaddr;
+ } common;
+ struct {
+ unsigned char pad[sizeof(struct drm_savage_common_state)];
+ uint32_t texctrl, texaddr;
+ uint32_t scstart, new_scstart;
+ uint32_t scend, new_scend;
+ } s3d;
+ struct {
+ unsigned char pad[sizeof(struct drm_savage_common_state)];
+ uint32_t texdescr, texaddr0, texaddr1;
+ uint32_t drawctrl0, new_drawctrl0;
+ uint32_t drawctrl1, new_drawctrl1;
+ } s4;
+} drm_savage_state_t;
+
+/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
+enum savage_family {
+ S3_UNKNOWN = 0,
+ S3_SAVAGE3D,
+ S3_SAVAGE_MX,
+ S3_SAVAGE4,
+ S3_PROSAVAGE,
+ S3_TWISTER,
+ S3_PROSAVAGEDDR,
+ S3_SUPERSAVAGE,
+ S3_SAVAGE2000,
+ S3_LAST
+};
+
+extern drm_ioctl_desc_t savage_ioctls[];
+extern int savage_max_ioctl;
+
+#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
+ || (chip==S3_PROSAVAGE) \
+ || (chip==S3_TWISTER) \
+ || (chip==S3_PROSAVAGEDDR))
+
+#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \
+ ||(chip==S3_PROSAVAGEDDR))
+
+/* flags */
+#define SAVAGE_IS_AGP 1
+
+typedef struct drm_savage_private {
+ drm_savage_sarea_t *sarea_priv;
+
+ drm_savage_buf_priv_t head, tail;
+
+ /* who am I? */
+ enum savage_family chipset;
+
+ unsigned int cob_size;
+ unsigned int bci_threshold_lo, bci_threshold_hi;
+ unsigned int dma_type;
+
+ /* frame buffer layout */
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ /* bitmap descriptors for swap and clear */
+ unsigned int front_bd, back_bd, depth_bd;
+
+ /* local textures */
+ unsigned int texture_offset;
+ unsigned int texture_size;
+
+ /* memory regions in physical memory */
+ drm_local_map_t *sarea;
+ drm_local_map_t *mmio;
+ drm_local_map_t *fb;
+ drm_local_map_t *aperture;
+ drm_local_map_t *status;
+ drm_local_map_t *agp_textures;
+ drm_local_map_t *cmd_dma;
+ drm_local_map_t fake_dma;
+
+ struct {
+ int handle;
+ unsigned long base, size;
+ } mtrr[3];
+
+ /* BCI and status-related stuff */
+ volatile uint32_t *status_ptr, *bci_ptr;
+ uint32_t status_used_mask;
+ uint16_t event_counter;
+ unsigned int event_wrap;
+
+ /* Savage4 command DMA */
+ drm_savage_dma_page_t *dma_pages;
+ unsigned int nr_dma_pages, first_dma_page, current_dma_page;
+ drm_savage_age_t last_dma_age;
+
+ /* saved hw state for global/local check on S3D */
+ uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
+ /* and for scissors (global, so don't emit if not changed) */
+ uint32_t hw_scissors_start, hw_scissors_end;
+
+ drm_savage_state_t state;
+
+ /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
+ unsigned int waiting;
+
+ /* config/hardware-dependent function pointers */
+ int (*wait_fifo) (struct drm_savage_private * dev_priv, unsigned int n);
+ int (*wait_evnt) (struct drm_savage_private * dev_priv, uint16_t e);
+ /* Err, there is a macro wait_event in include/linux/wait.h.
+ * Avoid unwanted macro expansion. */
+ void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
+ drm_clip_rect_t * pbox);
+ void (*dma_flush) (struct drm_savage_private * dev_priv);
+} drm_savage_private_t;
+
+/* ioctls */
+extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS);
+extern int savage_bci_buffers(DRM_IOCTL_ARGS);
+
+/* BCI functions */
+extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+ unsigned int flags);
+extern void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern void savage_dma_reset(drm_savage_private_t * dev_priv);
+extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
+extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
+ unsigned int n);
+extern int savage_preinit(drm_device_t * dev, unsigned long chipset);
+extern int savage_postcleanup(drm_device_t * dev);
+extern int savage_do_cleanup_bci(drm_device_t * dev);
+extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
+
+/* state functions */
+extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
+ drm_clip_rect_t * pbox);
+extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
+ drm_clip_rect_t * pbox);
+
+#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
+#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
+#define SAVAGE_MMIO_SIZE 0x00080000 /* 512kB */
+#define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */
+#define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */
+
+#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region
+ * inside the MMIO region */
+#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip
+ * BCI FIFO */
+
+/*
+ * MMIO registers
+ */
+#define SAVAGE_STATUS_WORD0 0x48C00
+#define SAVAGE_STATUS_WORD1 0x48C04
+#define SAVAGE_ALT_STATUS_WORD0 0x48C60
+
+#define SAVAGE_FIFO_USED_MASK_S3D 0x0001ffff
+#define SAVAGE_FIFO_USED_MASK_S4 0x001fffff
+
+/* Copied from savage_bci.h in the 2D driver with some renaming. */
+
+/* Bitmap descriptors */
+#define SAVAGE_BD_STRIDE_SHIFT 0
+#define SAVAGE_BD_BPP_SHIFT 16
+#define SAVAGE_BD_TILE_SHIFT 24
+#define SAVAGE_BD_BW_DISABLE (1<<28)
+/* common: */
+#define SAVAGE_BD_TILE_LINEAR 0
+/* savage4, MX, IX, 3D */
+#define SAVAGE_BD_TILE_16BPP 2
+#define SAVAGE_BD_TILE_32BPP 3
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_BD_TILE_DEST 1
+#define SAVAGE_BD_TILE_TEXTURE 2
+/* GBD - BCI enable */
+/* savage4, MX, IX, 3D */
+#define SAVAGE_GBD_BCI_ENABLE 8
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_GBD_BCI_ENABLE_TWISTER 0
+
+#define SAVAGE_GBD_BIG_ENDIAN 4
+#define SAVAGE_GBD_LITTLE_ENDIAN 0
+#define SAVAGE_GBD_64 1
+
+/* Global Bitmap Descriptor */
+#define SAVAGE_BCI_GLB_BD_LOW 0x8168
+#define SAVAGE_BCI_GLB_BD_HIGH 0x816C
+
+/*
+ * BCI registers
+ */
+/* Savage4/Twister/ProSavage 3D registers */
+#define SAVAGE_DRAWLOCALCTRL_S4 0x1e
+#define SAVAGE_TEXPALADDR_S4 0x1f
+#define SAVAGE_TEXCTRL0_S4 0x20
+#define SAVAGE_TEXCTRL1_S4 0x21
+#define SAVAGE_TEXADDR0_S4 0x22
+#define SAVAGE_TEXADDR1_S4 0x23
+#define SAVAGE_TEXBLEND0_S4 0x24
+#define SAVAGE_TEXBLEND1_S4 0x25
+#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
+#define SAVAGE_TEXDESCR_S4 0x27
+#define SAVAGE_FOGTABLE_S4 0x28
+#define SAVAGE_FOGCTRL_S4 0x30
+#define SAVAGE_STENCILCTRL_S4 0x31
+#define SAVAGE_ZBUFCTRL_S4 0x32
+#define SAVAGE_ZBUFOFF_S4 0x33
+#define SAVAGE_DESTCTRL_S4 0x34
+#define SAVAGE_DRAWCTRL0_S4 0x35
+#define SAVAGE_DRAWCTRL1_S4 0x36
+#define SAVAGE_ZWATERMARK_S4 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S4 0x38
+#define SAVAGE_TEXBLENDCOLOR_S4 0x39
+/* Savage3D/MX/IX 3D registers */
+#define SAVAGE_TEXPALADDR_S3D 0x18
+#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
+#define SAVAGE_TEXADDR_S3D 0x1A
+#define SAVAGE_TEXDESCR_S3D 0x1B
+#define SAVAGE_TEXCTRL_S3D 0x1C
+#define SAVAGE_FOGTABLE_S3D 0x20
+#define SAVAGE_FOGCTRL_S3D 0x30
+#define SAVAGE_DRAWCTRL_S3D 0x31
+#define SAVAGE_ZBUFCTRL_S3D 0x32
+#define SAVAGE_ZBUFOFF_S3D 0x33
+#define SAVAGE_DESTCTRL_S3D 0x34
+#define SAVAGE_SCSTART_S3D 0x35
+#define SAVAGE_SCEND_S3D 0x36
+#define SAVAGE_ZWATERMARK_S3D 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
+/* common stuff */
+#define SAVAGE_VERTBUFADDR 0x3e
+#define SAVAGE_BITPLANEWTMASK 0xd7
+#define SAVAGE_DMABUFADDR 0x51
+
+/* texture enable bits (needed for tex addr checking) */
+#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */
+#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */
+#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */
+
+/* Global fields in Savage4/Twister/ProSavage 3D registers:
+ *
+ * All texture registers and DrawLocalCtrl are local. All other
+ * registers are global. */
+
+/* Global fields in Savage3D/MX/IX 3D registers:
+ *
+ * All texture registers are local. DrawCtrl and ZBufCtrl are
+ * partially local. All other registers are global.
+ *
+ * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
+ * ZBufCtrl global fields: zCmpFunc, zBufEn
+ */
+#define SAVAGE_DRAWCTRL_S3D_GLOBAL 0x03f3c00c
+#define SAVAGE_ZBUFCTRL_S3D_GLOBAL 0x00000027
+
+/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
+ */
+#define SAVAGE_SCISSOR_MASK_S4 0x00fff7ff
+#define SAVAGE_SCISSOR_MASK_S3D 0x07ff07ff
+
+/*
+ * BCI commands
+ */
+#define BCI_CMD_NOP 0x40000000
+#define BCI_CMD_RECT 0x48000000
+#define BCI_CMD_RECT_XP 0x01000000
+#define BCI_CMD_RECT_YP 0x02000000
+#define BCI_CMD_SCANLINE 0x50000000
+#define BCI_CMD_LINE 0x5C000000
+#define BCI_CMD_LINE_LAST_PIXEL 0x58000000
+#define BCI_CMD_BYTE_TEXT 0x63000000
+#define BCI_CMD_NT_BYTE_TEXT 0x67000000
+#define BCI_CMD_BIT_TEXT 0x6C000000
+#define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR 0x00008000
+
+#define BCI_CMD_CLIP_NONE 0x00000000
+#define BCI_CMD_CLIP_CURRENT 0x00002000
+#define BCI_CMD_CLIP_LR 0x00004000
+#define BCI_CMD_CLIP_NEW 0x00006000
+
+#define BCI_CMD_DEST_GBD 0x00000000
+#define BCI_CMD_DEST_PBD 0x00000800
+#define BCI_CMD_DEST_PBD_NEW 0x00000C00
+#define BCI_CMD_DEST_SBD 0x00001000
+#define BCI_CMD_DEST_SBD_NEW 0x00001400
+
+#define BCI_CMD_SRC_TRANSPARENT 0x00000200
+#define BCI_CMD_SRC_SOLID 0x00000000
+#define BCI_CMD_SRC_GBD 0x00000020
+#define BCI_CMD_SRC_COLOR 0x00000040
+#define BCI_CMD_SRC_MONO 0x00000060
+#define BCI_CMD_SRC_PBD_COLOR 0x00000080
+#define BCI_CMD_SRC_PBD_MONO 0x000000A0
+#define BCI_CMD_SRC_PBD_COLOR_NEW 0x000000C0
+#define BCI_CMD_SRC_PBD_MONO_NEW 0x000000E0
+#define BCI_CMD_SRC_SBD_COLOR 0x00000100
+#define BCI_CMD_SRC_SBD_MONO 0x00000120
+#define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140
+#define BCI_CMD_SRC_SBD_MONO_NEW 0x00000160
+
+#define BCI_CMD_PAT_TRANSPARENT 0x00000010
+#define BCI_CMD_PAT_NONE 0x00000000
+#define BCI_CMD_PAT_COLOR 0x00000002
+#define BCI_CMD_PAT_MONO 0x00000003
+#define BCI_CMD_PAT_PBD_COLOR 0x00000004
+#define BCI_CMD_PAT_PBD_MONO 0x00000005
+#define BCI_CMD_PAT_PBD_COLOR_NEW 0x00000006
+#define BCI_CMD_PAT_PBD_MONO_NEW 0x00000007
+#define BCI_CMD_PAT_SBD_COLOR 0x00000008
+#define BCI_CMD_PAT_SBD_MONO 0x00000009
+#define BCI_CMD_PAT_SBD_COLOR_NEW 0x0000000A
+#define BCI_CMD_PAT_SBD_MONO_NEW 0x0000000B
+
+#define BCI_BD_BW_DISABLE 0x10000000
+#define BCI_BD_TILE_MASK 0x03000000
+#define BCI_BD_TILE_NONE 0x00000000
+#define BCI_BD_TILE_16 0x02000000
+#define BCI_BD_TILE_32 0x03000000
+#define BCI_BD_GET_BPP(bd) (((bd) >> 16) & 0xFF)
+#define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF)
+#define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF))
+
+#define BCI_CMD_SET_REGISTER 0x96000000
+
+#define BCI_CMD_WAIT 0xC0000000
+#define BCI_CMD_WAIT_3D 0x00010000
+#define BCI_CMD_WAIT_2D 0x00020000
+
+#define BCI_CMD_UPDATE_EVENT_TAG 0x98000000
+
+#define BCI_CMD_DRAW_PRIM 0x80000000
+#define BCI_CMD_DRAW_INDEXED_PRIM 0x88000000
+#define BCI_CMD_DRAW_CONT 0x01000000
+#define BCI_CMD_DRAW_TRILIST 0x00000000
+#define BCI_CMD_DRAW_TRISTRIP 0x02000000
+#define BCI_CMD_DRAW_TRIFAN 0x04000000
+#define BCI_CMD_DRAW_SKIPFLAGS 0x000000ff
+#define BCI_CMD_DRAW_NO_Z 0x00000001
+#define BCI_CMD_DRAW_NO_W 0x00000002
+#define BCI_CMD_DRAW_NO_CD 0x00000004
+#define BCI_CMD_DRAW_NO_CS 0x00000008
+#define BCI_CMD_DRAW_NO_U0 0x00000010
+#define BCI_CMD_DRAW_NO_V0 0x00000020
+#define BCI_CMD_DRAW_NO_UV0 0x00000030
+#define BCI_CMD_DRAW_NO_U1 0x00000040
+#define BCI_CMD_DRAW_NO_V1 0x00000080
+#define BCI_CMD_DRAW_NO_UV1 0x000000c0
+
+#define BCI_CMD_DMA 0xa8000000
+
+#define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF)
+#define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_CLIP_LR(l, r) ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l) ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r) ((((b) << 16) | (r)) & 0x0FFF0FFF)
+
+#define BCI_LINE_X_Y(x, y) (((y) << 16) | ((x) & 0xFFFF))
+#define BCI_LINE_STEPS(diag, axi) (((axi) << 16) | ((diag) & 0xFFFF))
+#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
+ (((maj) & 0x1FFF) | \
+ ((ym) ? 1<<13 : 0) | \
+ ((xp) ? 1<<14 : 0) | \
+ ((yp) ? 1<<15 : 0) | \
+ ((err) << 16))
+
+/*
+ * common commands
+ */
+#define BCI_SET_REGISTERS( first, n ) \
+ BCI_WRITE(BCI_CMD_SET_REGISTER | \
+ ((uint32_t)(n) & 0xff) << 16 | \
+ ((uint32_t)(first) & 0xffff))
+#define DMA_SET_REGISTERS( first, n ) \
+ DMA_WRITE(BCI_CMD_SET_REGISTER | \
+ ((uint32_t)(n) & 0xff) << 16 | \
+ ((uint32_t)(first) & 0xffff))
+
+#define BCI_DRAW_PRIMITIVE(n, type, skip) \
+ BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+ ((n) << 16))
+#define DMA_DRAW_PRIMITIVE(n, type, skip) \
+ DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+ ((n) << 16))
+
+#define BCI_DRAW_INDICES_S3D(n, type, i0) \
+ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
+ ((n) << 16) | (i0))
+
+#define BCI_DRAW_INDICES_S4(n, type, skip) \
+ BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
+ (skip) | ((n) << 16))
+
+#define BCI_DMA(n) \
+ BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
+
+/*
+ * access to MMIO
+ */
+#define SAVAGE_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
+#define SAVAGE_WRITE(reg) DRM_WRITE32( dev_priv->mmio, (reg) )
+
+/*
+ * access to the burst command interface (BCI)
+ */
+#define SAVAGE_BCI_DEBUG 1
+
+#define BCI_LOCALS volatile uint32_t *bci_ptr;
+
+#define BEGIN_BCI( n ) do { \
+ dev_priv->wait_fifo(dev_priv, (n)); \
+ bci_ptr = dev_priv->bci_ptr; \
+} while(0)
+
+#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
+
+#define BCI_COPY_FROM_USER(src,n) do { \
+ unsigned int i; \
+ for (i = 0; i < n; ++i) { \
+ uint32_t val; \
+ DRM_GET_USER_UNCHECKED(val, &((uint32_t*)(src))[i]); \
+ BCI_WRITE(val); \
+ } \
+} while(0)
+
+/*
+ * command DMA support
+ */
+#define SAVAGE_DMA_DEBUG 1
+
+#define DMA_LOCALS uint32_t *dma_ptr;
+
+#define BEGIN_DMA( n ) do { \
+ unsigned int cur = dev_priv->current_dma_page; \
+ unsigned int rest = SAVAGE_DMA_PAGE_SIZE - \
+ dev_priv->dma_pages[cur].used; \
+ if ((n) > rest) { \
+ dma_ptr = savage_dma_alloc(dev_priv, (n)); \
+ } else { /* fast path for small allocations */ \
+ dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + \
+ cur * SAVAGE_DMA_PAGE_SIZE + \
+ dev_priv->dma_pages[cur].used; \
+ if (dev_priv->dma_pages[cur].used == 0) \
+ savage_dma_wait(dev_priv, cur); \
+ dev_priv->dma_pages[cur].used += (n); \
+ } \
+} while(0)
+
+#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
+
+#define DMA_COPY_FROM_USER(src,n) do { \
+ DRM_COPY_FROM_USER_UNCHECKED(dma_ptr, (src), (n)*4); \
+ dma_ptr += n; \
+} while(0)
+
+#if SAVAGE_DMA_DEBUG
+#define DMA_COMMIT() do { \
+ unsigned int cur = dev_priv->current_dma_page; \
+ uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle + \
+ cur * SAVAGE_DMA_PAGE_SIZE + \
+ dev_priv->dma_pages[cur].used; \
+ if (dma_ptr != expected) { \
+ DRM_ERROR("DMA allocation and use don't match: " \
+ "%p != %p\n", expected, dma_ptr); \
+ savage_dma_reset(dev_priv); \
+ } \
+} while(0)
+#else
+#define DMA_COMMIT() do {/* nothing */} while(0)
+#endif
+
+#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
+
+/* Buffer aging via event tag
+ */
+
+#define UPDATE_EVENT_COUNTER( ) do { \
+ if (dev_priv->status_ptr) { \
+ uint16_t count; \
+ /* coordinate with Xserver */ \
+ count = dev_priv->status_ptr[1023]; \
+ if (count < dev_priv->event_counter) \
+ dev_priv->event_wrap++; \
+ dev_priv->event_counter = count; \
+ } \
+} while(0)
+
+#define SET_AGE( age, e, w ) do { \
+ (age)->event = e; \
+ (age)->wrap = w; \
+} while(0)
+
+#define TEST_AGE( age, e, w ) \
+ ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
+
+#endif /* __SAVAGE_DRV_H__ */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
new file mode 100644
index 000000000000..e87a5d59b99c
--- /dev/null
+++ b/drivers/char/drm/savage_state.c
@@ -0,0 +1,1161 @@
+/* savage_state.c -- State and drawing support for Savage
+ *
+ * Copyright 2004 Felix Kuehling
+ * 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 FELIX KUEHLING 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 "savage_drm.h"
+#include "savage_drv.h"
+
+void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
+ drm_clip_rect_t * pbox)
+{
+ uint32_t scstart = dev_priv->state.s3d.new_scstart;
+ uint32_t scend = dev_priv->state.s3d.new_scend;
+ scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
+ ((uint32_t) pbox->x1 & 0x000007ff) |
+ (((uint32_t) pbox->y1 << 16) & 0x07ff0000);
+ scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
+ (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
+ ((((uint32_t) pbox->y2 - 1) << 16) & 0x07ff0000);
+ if (scstart != dev_priv->state.s3d.scstart ||
+ scend != dev_priv->state.s3d.scend) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
+ DMA_WRITE(scstart);
+ DMA_WRITE(scend);
+ dev_priv->state.s3d.scstart = scstart;
+ dev_priv->state.s3d.scend = scend;
+ dev_priv->waiting = 1;
+ DMA_COMMIT();
+ }
+}
+
+void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
+ drm_clip_rect_t * pbox)
+{
+ uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
+ uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
+ drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
+ ((uint32_t) pbox->x1 & 0x000007ff) |
+ (((uint32_t) pbox->y1 << 12) & 0x00fff000);
+ drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
+ (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
+ ((((uint32_t) pbox->y2 - 1) << 12) & 0x00fff000);
+ if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
+ drawctrl1 != dev_priv->state.s4.drawctrl1) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
+ DMA_WRITE(drawctrl0);
+ DMA_WRITE(drawctrl1);
+ dev_priv->state.s4.drawctrl0 = drawctrl0;
+ dev_priv->state.s4.drawctrl1 = drawctrl1;
+ dev_priv->waiting = 1;
+ DMA_COMMIT();
+ }
+}
+
+static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
+ uint32_t addr)
+{
+ if ((addr & 6) != 2) { /* reserved bits */
+ DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ if (!(addr & 1)) { /* local */
+ addr &= ~7;
+ if (addr < dev_priv->texture_offset ||
+ addr >= dev_priv->texture_offset + dev_priv->texture_size) {
+ DRM_ERROR
+ ("bad texAddr%d %08x (local addr out of range)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ } else { /* AGP */
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ addr &= ~7;
+ if (addr < dev_priv->agp_textures->offset ||
+ addr >= (dev_priv->agp_textures->offset +
+ dev_priv->agp_textures->size)) {
+ DRM_ERROR
+ ("bad texAddr%d %08x (AGP addr out of range)\n",
+ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+#define SAVE_STATE(reg,where) \
+ if(start <= reg && start+count > reg) \
+ DRM_GET_USER_UNCHECKED(dev_priv->state.where, &regs[reg-start])
+#define SAVE_STATE_MASK(reg,where,mask) do { \
+ if(start <= reg && start+count > reg) { \
+ uint32_t tmp; \
+ DRM_GET_USER_UNCHECKED(tmp, &regs[reg-start]); \
+ dev_priv->state.where = (tmp & (mask)) | \
+ (dev_priv->state.where & ~(mask)); \
+ } \
+} while (0)
+static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
+ unsigned int start, unsigned int count,
+ const uint32_t __user * regs)
+{
+ if (start < SAVAGE_TEXPALADDR_S3D ||
+ start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+ start, start + count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+ SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
+ ~SAVAGE_SCISSOR_MASK_S3D);
+ SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend,
+ ~SAVAGE_SCISSOR_MASK_S3D);
+
+ /* if any texture regs were changed ... */
+ if (start <= SAVAGE_TEXCTRL_S3D &&
+ start + count > SAVAGE_TEXPALADDR_S3D) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
+ SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
+ if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
+ return savage_verify_texaddr(dev_priv, 0,
+ dev_priv->state.s3d.
+ texaddr);
+ }
+
+ return 0;
+}
+
+static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
+ unsigned int start, unsigned int count,
+ const uint32_t __user * regs)
+{
+ int ret = 0;
+
+ if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
+ start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+ start, start + count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+ SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
+ ~SAVAGE_SCISSOR_MASK_S4);
+ SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1,
+ ~SAVAGE_SCISSOR_MASK_S4);
+
+ /* if any texture regs were changed ... */
+ if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
+ SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
+ SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
+ ret |=
+ savage_verify_texaddr(dev_priv, 0,
+ dev_priv->state.s4.texaddr0);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
+ ret |=
+ savage_verify_texaddr(dev_priv, 1,
+ dev_priv->state.s4.texaddr1);
+ }
+
+ return ret;
+}
+
+#undef SAVE_STATE
+#undef SAVE_STATE_MASK
+
+static int savage_dispatch_state(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const uint32_t __user * regs)
+{
+ unsigned int count = cmd_header->state.count;
+ unsigned int start = cmd_header->state.start;
+ unsigned int count2 = 0;
+ unsigned int bci_size;
+ int ret;
+ DMA_LOCALS;
+
+ if (!count)
+ return 0;
+
+ if (DRM_VERIFYAREA_READ(regs, count * 4))
+ return DRM_ERR(EFAULT);
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ ret = savage_verify_state_s3d(dev_priv, start, count, regs);
+ if (ret != 0)
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_SCSTART_S3D) {
+ if (start + count > SAVAGE_SCEND_S3D + 1)
+ count2 = count - (SAVAGE_SCEND_S3D + 1 - start);
+ if (start + count > SAVAGE_SCSTART_S3D)
+ count = SAVAGE_SCSTART_S3D - start;
+ } else if (start <= SAVAGE_SCEND_S3D) {
+ if (start + count > SAVAGE_SCEND_S3D + 1) {
+ count -= SAVAGE_SCEND_S3D + 1 - start;
+ start = SAVAGE_SCEND_S3D + 1;
+ } else
+ return 0;
+ }
+ } else {
+ ret = savage_verify_state_s4(dev_priv, start, count, regs);
+ if (ret != 0)
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_DRAWCTRL0_S4) {
+ if (start + count > SAVAGE_DRAWCTRL1_S4 + 1)
+ count2 =
+ count - (SAVAGE_DRAWCTRL1_S4 + 1 - start);
+ if (start + count > SAVAGE_DRAWCTRL0_S4)
+ count = SAVAGE_DRAWCTRL0_S4 - start;
+ } else if (start <= SAVAGE_DRAWCTRL1_S4) {
+ if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) {
+ count -= SAVAGE_DRAWCTRL1_S4 + 1 - start;
+ start = SAVAGE_DRAWCTRL1_S4 + 1;
+ } else
+ return 0;
+ }
+ }
+
+ bci_size = count + (count + 254) / 255 + count2 + (count2 + 254) / 255;
+
+ if (cmd_header->state.global) {
+ BEGIN_DMA(bci_size + 1);
+ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ dev_priv->waiting = 1;
+ } else {
+ BEGIN_DMA(bci_size);
+ }
+
+ do {
+ while (count > 0) {
+ unsigned int n = count < 255 ? count : 255;
+ DMA_SET_REGISTERS(start, n);
+ DMA_COPY_FROM_USER(regs, n);
+ count -= n;
+ start += n;
+ regs += n;
+ }
+ start += 2;
+ regs += 2;
+ count = count2;
+ count2 = 0;
+ } while (count);
+
+ DMA_COMMIT();
+
+ return 0;
+}
+
+static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const drm_buf_t * dmabuf)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+ unsigned int skip = cmd_header->prim.skip;
+ unsigned int n = cmd_header->prim.count;
+ unsigned int start = cmd_header->prim.start;
+ unsigned int i;
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+ DRM_ERROR("called without dma buffers!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR
+ ("wrong number of vertices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+ DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (start + n > dmabuf->total / 32) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+ start, start + n - 1, dmabuf->total / 32);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* Vertex DMA doesn't work with command DMA at the same time,
+ * so we use BCI_... to submit commands here. Flush buffered
+ * faked DMA first. */
+ DMA_FLUSH();
+
+ if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+ BEGIN_BCI(2);
+ BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+ BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+ dev_priv->state.common.vbaddr = dmabuf->bus_address;
+ }
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+ /* Workaround for what looks like a hardware bug. If a
+ * WAIT_3D_IDLE was emitted some time before the
+ * indexed drawing command then the engine will lock
+ * up. There are two known workarounds:
+ * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+ BEGIN_BCI(63);
+ for (i = 0; i < 63; ++i)
+ BCI_WRITE(BCI_CMD_WAIT);
+ dev_priv->waiting = 0;
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 indices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ if (reorder) {
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = { -1, -1, -1 };
+ reorder[start % 3] = 2;
+
+ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, start + 2);
+
+ for (i = start + 1; i + 1 < start + count; i += 2)
+ BCI_WRITE((i + reorder[i % 3]) |
+ ((i + 1 +
+ reorder[(i + 1) % 3]) << 16));
+ if (i < start + count)
+ BCI_WRITE(i + reorder[i % 3]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, start);
+
+ for (i = start + 1; i + 1 < start + count; i += 2)
+ BCI_WRITE(i | ((i + 1) << 16));
+ if (i < start + count)
+ BCI_WRITE(i);
+ } else {
+ BEGIN_BCI((count + 2 + 1) / 2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+ for (i = start; i + 1 < start + count; i += 2)
+ BCI_WRITE(i | ((i + 1) << 16));
+ if (i < start + count)
+ BCI_WRITE(i);
+ }
+
+ start += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const uint32_t __user * vtxbuf,
+ unsigned int vb_size, unsigned int vb_stride)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+ unsigned int skip = cmd_header->prim.skip;
+ unsigned int n = cmd_header->prim.count;
+ unsigned int start = cmd_header->prim.start;
+ unsigned int vtx_size;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR
+ ("wrong number of vertices %u in TRIFAN/STRIP\n",
+ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip > SAVAGE_SKIP_ALL_S3D) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+ vtx_size, vb_stride);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (start + n > vb_size / (vb_stride * 4)) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+ start, start + n - 1, vb_size / (vb_stride * 4));
+ return DRM_ERR(EINVAL);
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 vertices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ if (reorder) {
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = { -1, -1, -1 };
+ reorder[start % 3] = 2;
+
+ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = start; i < start + count; ++i) {
+ unsigned int j = i + reorder[i % 3];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ if (vb_stride == vtx_size) {
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start],
+ vtx_size * count);
+ } else {
+ for (i = start; i < start + count; ++i) {
+ DMA_COPY_FROM_USER(&vtxbuf
+ [vb_stride * i],
+ vtx_size);
+ }
+ }
+
+ DMA_COMMIT();
+ }
+
+ start += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const uint16_t __user * usr_idx,
+ const drm_buf_t * dmabuf)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+ unsigned int skip = cmd_header->idx.skip;
+ unsigned int n = cmd_header->idx.count;
+ unsigned int i;
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+ DRM_ERROR("called without dma buffers!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR
+ ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+ DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ /* Vertex DMA doesn't work with command DMA at the same time,
+ * so we use BCI_... to submit commands here. Flush buffered
+ * faked DMA first. */
+ DMA_FLUSH();
+
+ if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+ BEGIN_BCI(2);
+ BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+ BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+ dev_priv->state.common.vbaddr = dmabuf->bus_address;
+ }
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+ /* Workaround for what looks like a hardware bug. If a
+ * WAIT_3D_IDLE was emitted some time before the
+ * indexed drawing command then the engine will lock
+ * up. There are two known workarounds:
+ * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+ BEGIN_BCI(63);
+ for (i = 0; i < 63; ++i)
+ BCI_WRITE(BCI_CMD_WAIT);
+ dev_priv->waiting = 0;
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 indices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ /* Is it ok to allocate 510 bytes on the stack in an ioctl? */
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);
+ for (i = 0; i < count; ++i) {
+ if (idx[i] > dmabuf->total / 32) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+ i, idx[i], dmabuf->total / 32);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (reorder) {
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = { 2, -1, -1 };
+
+ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
+
+ for (i = 1; i + 1 < count; i += 2)
+ BCI_WRITE(idx[i + reorder[i % 3]] |
+ (idx[i + 1 + reorder[(i + 1) % 3]] <<
+ 16));
+ if (i < count)
+ BCI_WRITE(idx[i + reorder[i % 3]]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
+
+ for (i = 1; i + 1 < count; i += 2)
+ BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ } else {
+ BEGIN_BCI((count + 2 + 1) / 2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+ for (i = 0; i + 1 < count; i += 2)
+ BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ }
+
+ usr_idx += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const uint16_t __user * usr_idx,
+ const uint32_t __user * vtxbuf,
+ unsigned int vb_size, unsigned int vb_stride)
+{
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+ unsigned int skip = cmd_header->idx.skip;
+ unsigned int n = cmd_header->idx.count;
+ unsigned int vtx_size;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (!n)
+ return 0;
+
+ switch (prim) {
+ case SAVAGE_PRIM_TRILIST_201:
+ reorder = 1;
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+ DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+ DRM_ERROR
+ ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ default:
+ DRM_ERROR("invalid primitive type %u\n", prim);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip > SAVAGE_SKIP_ALL_S3D) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+ vtx_size, vb_stride);
+ return DRM_ERR(EINVAL);
+ }
+
+ prim <<= 25;
+ while (n != 0) {
+ /* Can emit up to 255 vertices (85 triangles) at once. */
+ unsigned int count = n > 255 ? 255 : n;
+ /* Is it ok to allocate 510 bytes on the stack in an ioctl? */
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);
+ for (i = 0; i < count; ++i) {
+ if (idx[i] > vb_size / (vb_stride * 4)) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+ i, idx[i], vb_size / (vb_stride * 4));
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ if (reorder) {
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+ int reorder[3] = { 2, -1, -1 };
+
+ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i + reorder[i % 3]];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i];
+ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ }
+
+ usr_idx += count;
+ n -= count;
+
+ prim |= BCI_CMD_DRAW_CONT;
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t * cmd_header,
+ const drm_savage_cmd_header_t __user * data,
+ unsigned int nbox,
+ const drm_clip_rect_t __user * usr_boxes)
+{
+ unsigned int flags = cmd_header->clear0.flags, mask, value;
+ unsigned int clear_cmd;
+ unsigned int i, nbufs;
+ DMA_LOCALS;
+
+ if (nbox == 0)
+ return 0;
+
+ DRM_GET_USER_UNCHECKED(mask, &data->clear1.mask);
+ DRM_GET_USER_UNCHECKED(value, &data->clear1.value);
+
+ clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+ BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
+ BCI_CMD_SET_ROP(clear_cmd, 0xCC);
+
+ nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
+ ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0);
+ if (nbufs == 0)
+ return 0;
+
+ if (mask != 0xffffffff) {
+ /* set mask */
+ BEGIN_DMA(2);
+ DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+ DMA_WRITE(mask);
+ DMA_COMMIT();
+ }
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ unsigned int x, y, w, h;
+ unsigned int buf;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+ x = box.x1, y = box.y1;
+ w = box.x2 - box.x1;
+ h = box.y2 - box.y1;
+ BEGIN_DMA(nbufs * 6);
+ for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
+ if (!(flags & buf))
+ continue;
+ DMA_WRITE(clear_cmd);
+ switch (buf) {
+ case SAVAGE_FRONT:
+ DMA_WRITE(dev_priv->front_offset);
+ DMA_WRITE(dev_priv->front_bd);
+ break;
+ case SAVAGE_BACK:
+ DMA_WRITE(dev_priv->back_offset);
+ DMA_WRITE(dev_priv->back_bd);
+ break;
+ case SAVAGE_DEPTH:
+ DMA_WRITE(dev_priv->depth_offset);
+ DMA_WRITE(dev_priv->depth_bd);
+ break;
+ }
+ DMA_WRITE(value);
+ DMA_WRITE(BCI_X_Y(x, y));
+ DMA_WRITE(BCI_W_H(w, h));
+ }
+ DMA_COMMIT();
+ }
+ if (mask != 0xffffffff) {
+ /* reset mask */
+ BEGIN_DMA(2);
+ DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+ DMA_WRITE(0xffffffff);
+ DMA_COMMIT();
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
+ unsigned int nbox,
+ const drm_clip_rect_t __user * usr_boxes)
+{
+ unsigned int swap_cmd;
+ unsigned int i;
+ DMA_LOCALS;
+
+ if (nbox == 0)
+ return 0;
+
+ swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+ BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
+ BCI_CMD_SET_ROP(swap_cmd, 0xCC);
+
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+
+ BEGIN_DMA(6);
+ DMA_WRITE(swap_cmd);
+ DMA_WRITE(dev_priv->back_offset);
+ DMA_WRITE(dev_priv->back_bd);
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+ DMA_WRITE(BCI_W_H(box.x2 - box.x1, box.y2 - box.y1));
+ DMA_COMMIT();
+ }
+
+ return 0;
+}
+
+static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
+ const drm_savage_cmd_header_t __user * start,
+ const drm_savage_cmd_header_t __user * end,
+ const drm_buf_t * dmabuf,
+ const unsigned int __user * usr_vtxbuf,
+ unsigned int vb_size, unsigned int vb_stride,
+ unsigned int nbox,
+ const drm_clip_rect_t __user * usr_boxes)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+ const drm_savage_cmd_header_t __user *usr_cmdbuf;
+ DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));
+ dev_priv->emit_clip_rect(dev_priv, &box);
+
+ usr_cmdbuf = start;
+ while (usr_cmdbuf < end) {
+ drm_savage_cmd_header_t cmd_header;
+ DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
+ sizeof(cmd_header));
+ usr_cmdbuf++;
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_DMA_PRIM:
+ ret =
+ savage_dispatch_dma_prim(dev_priv,
+ &cmd_header,
+ dmabuf);
+ break;
+ case SAVAGE_CMD_VB_PRIM:
+ ret =
+ savage_dispatch_vb_prim(dev_priv,
+ &cmd_header,
+ (const uint32_t
+ __user *)
+ usr_vtxbuf, vb_size,
+ vb_stride);
+ break;
+ case SAVAGE_CMD_DMA_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+ ret =
+ savage_dispatch_dma_idx(dev_priv,
+ &cmd_header,
+ (const uint16_t
+ __user *)
+ usr_cmdbuf, dmabuf);
+ usr_cmdbuf += j;
+ break;
+ case SAVAGE_CMD_VB_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+ ret =
+ savage_dispatch_vb_idx(dev_priv,
+ &cmd_header,
+ (const uint16_t
+ __user *)usr_cmdbuf,
+ (const uint32_t
+ __user *)usr_vtxbuf,
+ vb_size, vb_stride);
+ usr_cmdbuf += j;
+ break;
+ default:
+ /* What's the best return code? EFAULT? */
+ DRM_ERROR("IMPLEMENTATION ERROR: "
+ "non-drawing-command %d\n",
+ cmd_header.cmd.cmd);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *dmabuf;
+ drm_savage_cmdbuf_t cmdbuf;
+ drm_savage_cmd_header_t __user *usr_cmdbuf;
+ drm_savage_cmd_header_t __user *first_draw_cmd;
+ unsigned int __user *usr_vtxbuf;
+ drm_clip_rect_t __user *usr_boxes;
+ unsigned int i, j;
+ int ret = 0;
+
+ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *) data,
+ sizeof(cmdbuf));
+
+ if (dma && dma->buflist) {
+ if (cmdbuf.dma_idx > dma->buf_count) {
+ DRM_ERROR
+ ("vertex buffer index %u out of range (0-%u)\n",
+ cmdbuf.dma_idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+ dmabuf = dma->buflist[cmdbuf.dma_idx];
+ } else {
+ dmabuf = NULL;
+ }
+
+ usr_cmdbuf = (drm_savage_cmd_header_t __user *) cmdbuf.cmd_addr;
+ usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr;
+ usr_boxes = (drm_clip_rect_t __user *) cmdbuf.box_addr;
+ if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size * 8)) ||
+ (cmdbuf.vb_size && DRM_VERIFYAREA_READ(usr_vtxbuf, cmdbuf.vb_size))
+ || (cmdbuf.nbox
+ && DRM_VERIFYAREA_READ(usr_boxes,
+ cmdbuf.nbox * sizeof(drm_clip_rect_t))))
+ return DRM_ERR(EFAULT);
+
+ /* Make sure writes to DMA buffers are finished before sending
+ * DMA commands to the graphics hardware. */
+ DRM_MEMORYBARRIER();
+
+ /* Coming from user space. Don't know if the Xserver has
+ * emitted wait commands. Assuming the worst. */
+ dev_priv->waiting = 1;
+
+ i = 0;
+ first_draw_cmd = NULL;
+ while (i < cmdbuf.size) {
+ drm_savage_cmd_header_t cmd_header;
+ DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
+ sizeof(cmd_header));
+ usr_cmdbuf++;
+ i++;
+
+ /* Group drawing commands with same state to minimize
+ * iterations over clip rects. */
+ j = 0;
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_DMA_IDX:
+ case SAVAGE_CMD_VB_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ if (i + j > cmdbuf.size) {
+ DRM_ERROR("indexed drawing command extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ /* fall through */
+ case SAVAGE_CMD_DMA_PRIM:
+ case SAVAGE_CMD_VB_PRIM:
+ if (!first_draw_cmd)
+ first_draw_cmd = usr_cmdbuf - 1;
+ usr_cmdbuf += j;
+ i += j;
+ break;
+ default:
+ if (first_draw_cmd) {
+ ret =
+ savage_dispatch_draw(dev_priv,
+ first_draw_cmd,
+ usr_cmdbuf - 1, dmabuf,
+ usr_vtxbuf,
+ cmdbuf.vb_size,
+ cmdbuf.vb_stride,
+ cmdbuf.nbox,
+ usr_boxes);
+ if (ret != 0)
+ return ret;
+ first_draw_cmd = NULL;
+ }
+ }
+ if (first_draw_cmd)
+ continue;
+
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_STATE:
+ j = (cmd_header.state.count + 1) / 2;
+ if (i + j > cmdbuf.size) {
+ DRM_ERROR("command SAVAGE_CMD_STATE extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ ret = savage_dispatch_state(dev_priv, &cmd_header,
+ (uint32_t __user *)
+ usr_cmdbuf);
+ usr_cmdbuf += j;
+ i += j;
+ break;
+ case SAVAGE_CMD_CLEAR:
+ if (i + 1 > cmdbuf.size) {
+ DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
+ "beyond end of command buffer\n");
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+ ret = savage_dispatch_clear(dev_priv, &cmd_header,
+ usr_cmdbuf,
+ cmdbuf.nbox, usr_boxes);
+ usr_cmdbuf++;
+ i++;
+ break;
+ case SAVAGE_CMD_SWAP:
+ ret = savage_dispatch_swap(dev_priv,
+ cmdbuf.nbox, usr_boxes);
+ break;
+ default:
+ DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+
+ if (ret != 0) {
+ DMA_FLUSH();
+ return ret;
+ }
+ }
+
+ if (first_draw_cmd) {
+ ret =
+ savage_dispatch_draw(dev_priv, first_draw_cmd, usr_cmdbuf,
+ dmabuf, usr_vtxbuf, cmdbuf.vb_size,
+ cmdbuf.vb_stride, cmdbuf.nbox,
+ usr_boxes);
+ if (ret != 0) {
+ DMA_FLUSH();
+ return ret;
+ }
+ }
+
+ DMA_FLUSH();
+
+ if (dmabuf && cmdbuf.discard) {
+ drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
+ uint16_t event;
+ event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+ SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+ savage_freelist_put(dev, dmabuf);
+ }
+
+ return 0;
+}
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
index e99c3a43abbc..8f273da76ddb 100644
--- a/drivers/char/drm/sis_drm.h
+++ b/drivers/char/drm/sis_drm.h
@@ -39,4 +39,4 @@ typedef struct {
unsigned int offset, size;
} drm_sis_fb_t;
-#endif /* __SIS_DRM_H__ */
+#endif /* __SIS_DRM_H__ */
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index f441714faae3..3cef10643a8f 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -10,11 +10,11 @@
* 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
@@ -31,31 +31,29 @@
#include "sis_drv.h"
#include "drm_pciids.h"
-
-static int postinit( struct drm_device *dev, unsigned long flags )
+
+static int postinit(struct drm_device *dev, unsigned long flags)
{
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -63,9 +61,6 @@ static struct pci_device_id pciidlist[] = {
sisdrv_PCI_IDS
};
-extern drm_ioctl_desc_t sis_ioctls[];
-extern int sis_max_ioctl;
-
static struct drm_driver driver = {
.driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
.context_ctor = sis_init_context,
@@ -77,18 +72,18 @@ static struct drm_driver driver = {
.version = version,
.ioctls = sis_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,
+ }
};
static int __init sis_init(void)
@@ -105,6 +100,6 @@ static void __exit sis_exit(void)
module_init(sis_init);
module_exit(sis_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 5be36b5caec9..b1fddad83a93 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -10,11 +10,11 @@
* 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
@@ -22,7 +22,7 @@
* 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 _SIS_DRV_H_
@@ -46,7 +46,10 @@ typedef struct drm_sis_private {
memHeap_t *FBHeap;
} drm_sis_private_t;
-extern int sis_init_context(drm_device_t *dev, int context);
-extern int sis_final_context(drm_device_t *dev, int context);
+extern int sis_init_context(drm_device_t * dev, int context);
+extern int sis_final_context(drm_device_t * dev, int context);
+
+extern drm_ioctl_desc_t sis_ioctls[];
+extern int sis_max_ioctl;
#endif
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
index e37ed8ce48df..2e485d482943 100644
--- a/drivers/char/drm/sis_ds.c
+++ b/drivers/char/drm/sis_ds.c
@@ -10,11 +10,11 @@
* 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
@@ -22,10 +22,10 @@
* 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:
* Sung-Ching Lin <sclin@sis.com.tw>
- *
+ *
*/
#include "drmP.h"
@@ -41,13 +41,13 @@ set_t *setInit(void)
int i;
set_t *set;
- set = (set_t *)drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+ set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
if (set != NULL) {
for (i = 0; i < SET_SIZE; i++) {
- set->list[i].free_next = i + 1;
+ set->list[i].free_next = i + 1;
set->list[i].alloc_next = -1;
}
- set->list[SET_SIZE-1].free_next = -1;
+ set->list[SET_SIZE - 1].free_next = -1;
set->free = 0;
set->alloc = -1;
set->trace = -1;
@@ -55,10 +55,10 @@ set_t *setInit(void)
return set;
}
-int setAdd(set_t *set, ITEM_TYPE item)
+int setAdd(set_t * set, ITEM_TYPE item)
{
int free = set->free;
-
+
if (free != -1) {
set->list[free].val = item;
set->free = set->list[free].free_next;
@@ -67,16 +67,16 @@ int setAdd(set_t *set, ITEM_TYPE item)
}
set->list[free].alloc_next = set->alloc;
- set->alloc = free;
- set->list[free].free_next = -1;
+ set->alloc = free;
+ set->list[free].free_next = -1;
return 1;
}
-int setDel(set_t *set, ITEM_TYPE item)
+int setDel(set_t * set, ITEM_TYPE item)
{
int alloc = set->alloc;
- int prev = -1;
+ int prev = -1;
while (alloc != -1) {
if (set->list[alloc].val == item) {
@@ -103,7 +103,7 @@ int setDel(set_t *set, ITEM_TYPE item)
/* setFirst -> setAdd -> setNext is wrong */
-int setFirst(set_t *set, ITEM_TYPE *item)
+int setFirst(set_t * set, ITEM_TYPE * item)
{
if (set->alloc == -1)
return 0;
@@ -114,7 +114,7 @@ int setFirst(set_t *set, ITEM_TYPE *item)
return 1;
}
-int setNext(set_t *set, ITEM_TYPE *item)
+int setNext(set_t * set, ITEM_TYPE * item)
{
if (set->trace == -1)
return 0;
@@ -125,7 +125,7 @@ int setNext(set_t *set, ITEM_TYPE *item)
return 1;
}
-int setDestroy(set_t *set)
+int setDestroy(set_t * set)
{
drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
@@ -149,35 +149,34 @@ int setDestroy(set_t *set)
* 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
- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
*
*/
#define ISFREE(bptr) ((bptr)->free)
-memHeap_t *mmInit(int ofs,
- int size)
+memHeap_t *mmInit(int ofs, int size)
{
PMemBlock blocks;
if (size <= 0)
return NULL;
- blocks = (TMemBlock *)drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+ blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
if (blocks != NULL) {
blocks->ofs = ofs;
blocks->size = size;
blocks->free = 1;
- return (memHeap_t *)blocks;
+ return (memHeap_t *) blocks;
} else
return NULL;
}
/* Checks if a pointer 'b' is part of the heap 'heap' */
-int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
+int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
{
TMemBlock *p;
@@ -194,16 +193,16 @@ int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
return 0;
}
-static TMemBlock* SliceBlock(TMemBlock *p,
- int startofs, int size,
+static TMemBlock *SliceBlock(TMemBlock * p,
+ int startofs, int size,
int reserved, int alignment)
{
TMemBlock *newblock;
/* break left */
if (startofs > p->ofs) {
- newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
- DRM_MEM_DRIVER);
+ newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+ DRM_MEM_DRIVER);
newblock->ofs = startofs;
newblock->size = p->size - (startofs - p->ofs);
newblock->free = 1;
@@ -215,8 +214,8 @@ static TMemBlock* SliceBlock(TMemBlock *p,
/* break right */
if (size < p->size) {
- newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
- DRM_MEM_DRIVER);
+ newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+ DRM_MEM_DRIVER);
newblock->ofs = startofs + size;
newblock->size = p->size - size;
newblock->free = 1;
@@ -232,37 +231,37 @@ static TMemBlock* SliceBlock(TMemBlock *p,
return p;
}
-PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
+PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
{
- int mask,startofs, endofs;
+ int mask, startofs, endofs;
TMemBlock *p;
-
+
if (heap == NULL || align2 < 0 || size <= 0)
return NULL;
- mask = (1 << align2)-1;
+ mask = (1 << align2) - 1;
startofs = 0;
- p = (TMemBlock *)heap;
+ p = (TMemBlock *) heap;
while (p != NULL) {
if (ISFREE(p)) {
startofs = (p->ofs + mask) & ~mask;
- if ( startofs < startSearch ) {
+ if (startofs < startSearch) {
startofs = startSearch;
}
- endofs = startofs+size;
- if (endofs <= (p->ofs+p->size))
+ endofs = startofs + size;
+ if (endofs <= (p->ofs + p->size))
break;
}
p = p->next;
}
if (p == NULL)
return NULL;
- p = SliceBlock(p,startofs,size,0,mask+1);
+ p = SliceBlock(p, startofs, size, 0, mask + 1);
p->heap = heap;
return p;
}
-static __inline__ int Join2Blocks(TMemBlock *p)
+static __inline__ int Join2Blocks(TMemBlock * p)
{
if (p->free && p->next && p->next->free) {
TMemBlock *q = p->next;
@@ -295,7 +294,6 @@ int mmFreeMem(PMemBlock b)
p->free = 1;
Join2Blocks(p);
if (prev)
- Join2Blocks(prev);
+ Join2Blocks(prev);
return 0;
}
-
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
index 171ee75afa57..da850b4f5440 100644
--- a/drivers/char/drm/sis_ds.h
+++ b/drivers/char/drm/sis_ds.h
@@ -10,11 +10,11 @@
* 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
@@ -22,10 +22,10 @@
* 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:
* Sung-Ching Lin <sclin@sis.com.tw>
- *
+ *
*/
#ifndef __SIS_DS_H__
@@ -50,11 +50,11 @@ typedef struct {
} set_t;
set_t *setInit(void);
-int setAdd(set_t *set, ITEM_TYPE item);
-int setDel(set_t *set, ITEM_TYPE item);
-int setFirst(set_t *set, ITEM_TYPE *item);
-int setNext(set_t *set, ITEM_TYPE *item);
-int setDestroy(set_t *set);
+int setAdd(set_t * set, ITEM_TYPE item);
+int setDel(set_t * set, ITEM_TYPE item);
+int setFirst(set_t * set, ITEM_TYPE * item);
+int setNext(set_t * set, ITEM_TYPE * item);
+int setDestroy(set_t * set);
/*
* GLX Hardware Device Driver common code
@@ -73,9 +73,9 @@ int setDestroy(set_t *set);
* 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
- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
*
*/
@@ -83,7 +83,7 @@ int setDestroy(set_t *set);
struct mem_block_t {
struct mem_block_t *next;
struct mem_block_t *heap;
- int ofs,size;
+ int ofs, size;
int align;
unsigned int free:1;
unsigned int reserved:1;
@@ -109,11 +109,11 @@ static __inline__ void mmMarkReserved(PMemBlock b)
b->reserved = 1;
}
-/*
+/*
* input: total size in bytes
* return: a heap pointer if OK, NULL if error
*/
-memHeap_t *mmInit( int ofs, int size );
+memHeap_t *mmInit(int ofs, int size);
/*
* Allocate 'size' bytes with 2^align2 bytes alignment,
@@ -125,21 +125,21 @@ memHeap_t *mmInit( int ofs, int size );
* startSearch = linear offset from start of heap to begin search
* return: pointer to the allocated block, 0 if error
*/
-PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
+PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
/*
* Returns 1 if the block 'b' is part of the heap 'heap'
*/
-int mmBlockInHeap( PMemBlock heap, PMemBlock b );
+int mmBlockInHeap(PMemBlock heap, PMemBlock b);
/*
* Free block starts at offset
* input: pointer to a block
* return: 0 if OK, -1 if error
*/
-int mmFreeMem( PMemBlock b );
+int mmFreeMem(PMemBlock b);
/* For debuging purpose. */
-void mmDumpMemInfo( memHeap_t *mmInit );
+void mmDumpMemInfo(memHeap_t * mmInit);
-#endif /* __SIS_DS_H__ */
+#endif /* __SIS_DS_H__ */
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 6610c5576d22..a8529728fa63 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -10,11 +10,11 @@
* 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
@@ -22,10 +22,10 @@
* 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:
* Sung-Ching Lin <sclin@sis.com.tw>
- *
+ *
*/
#include "drmP.h"
@@ -37,25 +37,23 @@
#endif
#define MAX_CONTEXT 100
-#define VIDEO_TYPE 0
+#define VIDEO_TYPE 0
#define AGP_TYPE 1
typedef struct {
int used;
int context;
- set_t *sets[2]; /* 0 for video, 1 for AGP */
+ set_t *sets[2]; /* 0 for video, 1 for AGP */
} sis_context_t;
static sis_context_t global_ppriv[MAX_CONTEXT];
-
static int add_alloc_set(int context, int type, unsigned int val)
{
int i, retval = 0;
-
+
for (i = 0; i < MAX_CONTEXT; i++) {
- if (global_ppriv[i].used && global_ppriv[i].context == context)
- {
+ if (global_ppriv[i].used && global_ppriv[i].context == context) {
retval = setAdd(global_ppriv[i].sets[type], val);
break;
}
@@ -64,12 +62,11 @@ static int add_alloc_set(int context, int type, unsigned int val)
}
static int del_alloc_set(int context, int type, unsigned int val)
-{
+{
int i, retval = 0;
for (i = 0; i < MAX_CONTEXT; i++) {
- if (global_ppriv[i].used && global_ppriv[i].context == context)
- {
+ if (global_ppriv[i].used && global_ppriv[i].context == context) {
retval = setDel(global_ppriv[i].sets[type], val);
break;
}
@@ -77,15 +74,15 @@ static int del_alloc_set(int context, int type, unsigned int val)
return retval;
}
-/* fb management via fb device */
+/* fb management via fb device */
#if defined(__linux__) && defined(CONFIG_FB_SIS)
-static int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init(DRM_IOCTL_ARGS)
{
return 0;
}
-static int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
drm_sis_mem_t fb;
struct sis_memreq req;
@@ -105,7 +102,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS )
sis_free(req.offset);
retval = DRM_ERR(EINVAL);
}
- } else {
+ } else {
fb.offset = 0;
fb.size = 0;
fb.free = 0;
@@ -118,19 +115,19 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS )
return retval;
}
-static int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free(DRM_IOCTL_ARGS)
{
drm_sis_mem_t fb;
int retval = 0;
- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
+ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
if (!fb.free)
return DRM_ERR(EINVAL);
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
retval = DRM_ERR(EINVAL);
- sis_free((u32)fb.free);
+ sis_free((u32) fb.free);
DRM_DEBUG("free fb, offset = %lu\n", fb.free);
@@ -149,17 +146,17 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
* X driver/sisfb HW- Command-
* framebuffer memory DRI heap Cursor queue
*/
-static int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
drm_sis_fb_t fb;
- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *)data, sizeof(fb));
+ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
if (dev_priv == NULL) {
dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
- DRM_MEM_DRIVER);
+ DRM_MEM_DRIVER);
dev_priv = dev->dev_private;
if (dev_priv == NULL)
return ENOMEM;
@@ -175,7 +172,7 @@ static int sis_fb_init( DRM_IOCTL_ARGS )
return 0;
}
-static int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -186,9 +183,9 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS )
if (dev_priv == NULL || dev_priv->FBHeap == NULL)
return DRM_ERR(EINVAL);
-
+
DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
-
+
block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
if (block) {
/* TODO */
@@ -196,7 +193,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS )
fb.free = (unsigned long)block;
if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
DRM_DEBUG("adding to allocation set fails\n");
- mmFreeMem((PMemBlock)fb.free);
+ mmFreeMem((PMemBlock) fb.free);
retval = DRM_ERR(EINVAL);
}
} else {
@@ -212,7 +209,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS )
return retval;
}
-static int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -221,14 +218,14 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
if (dev_priv == NULL || dev_priv->FBHeap == NULL)
return DRM_ERR(EINVAL);
- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
+ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
- if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
+ if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
return DRM_ERR(EINVAL);
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
return DRM_ERR(EINVAL);
- mmFreeMem((PMemBlock)fb.free);
+ mmFreeMem((PMemBlock) fb.free);
DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
@@ -237,9 +234,9 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
#endif
-/* agp memory management */
+/* agp memory management */
-static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -247,7 +244,7 @@ static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
if (dev_priv == NULL) {
dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
- DRM_MEM_DRIVER);
+ DRM_MEM_DRIVER);
dev_priv = dev->dev_private;
if (dev_priv == NULL)
return ENOMEM;
@@ -256,16 +253,17 @@ static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
if (dev_priv->AGPHeap != NULL)
return DRM_ERR(EINVAL);
- DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *)data, sizeof(agp));
+ DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
+ sizeof(agp));
dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
-
+
return 0;
}
-static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -273,12 +271,12 @@ static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
drm_sis_mem_t agp;
PMemBlock block;
int retval = 0;
-
+
if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
return DRM_ERR(EINVAL);
-
+
DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
-
+
block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
if (block) {
/* TODO */
@@ -286,10 +284,10 @@ static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
agp.free = (unsigned long)block;
if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
DRM_DEBUG("adding to allocation set fails\n");
- mmFreeMem((PMemBlock)agp.free);
+ mmFreeMem((PMemBlock) agp.free);
retval = -1;
}
- } else {
+ } else {
agp.offset = 0;
agp.size = 0;
agp.free = 0;
@@ -302,7 +300,7 @@ static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
return retval;
}
-static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -311,12 +309,13 @@ static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
return DRM_ERR(EINVAL);
- DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *)data, sizeof(agp));
+ DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
+ sizeof(agp));
- if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
+ if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
return DRM_ERR(EINVAL);
- mmFreeMem((PMemBlock)agp.free);
+ mmFreeMem((PMemBlock) agp.free);
if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
return DRM_ERR(EINVAL);
@@ -329,31 +328,30 @@ int sis_init_context(struct drm_device *dev, int context)
{
int i;
- for (i = 0; i < MAX_CONTEXT ; i++) {
+ for (i = 0; i < MAX_CONTEXT; i++) {
if (global_ppriv[i].used &&
(global_ppriv[i].context == context))
break;
}
if (i >= MAX_CONTEXT) {
- for (i = 0; i < MAX_CONTEXT ; i++) {
+ for (i = 0; i < MAX_CONTEXT; i++) {
if (!global_ppriv[i].used) {
global_ppriv[i].context = context;
global_ppriv[i].used = 1;
global_ppriv[i].sets[0] = setInit();
global_ppriv[i].sets[1] = setInit();
DRM_DEBUG("init allocation set, socket=%d, "
- "context = %d\n", i, context);
+ "context = %d\n", i, context);
break;
}
}
if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
- (global_ppriv[i].sets[1] == NULL))
- {
+ (global_ppriv[i].sets[1] == NULL)) {
return 0;
}
}
-
+
return 1;
}
@@ -361,7 +359,7 @@ int sis_final_context(struct drm_device *dev, int context)
{
int i;
- for (i=0; i<MAX_CONTEXT; i++) {
+ for (i = 0; i < MAX_CONTEXT; i++) {
if (global_ppriv[i].used &&
(global_ppriv[i].context == context))
break;
@@ -382,7 +380,7 @@ int sis_final_context(struct drm_device *dev, int context)
#if defined(__linux__) && defined(CONFIG_FB_SIS)
sis_free(item);
#else
- mmFreeMem((PMemBlock)item);
+ mmFreeMem((PMemBlock) item);
#endif
retval = setNext(set, &item);
}
@@ -393,25 +391,24 @@ int sis_final_context(struct drm_device *dev, int context)
retval = setFirst(set, &item);
while (retval) {
DRM_DEBUG("free agp memory 0x%x\n", item);
- mmFreeMem((PMemBlock)item);
+ mmFreeMem((PMemBlock) item);
retval = setNext(set, &item);
}
setDestroy(set);
- global_ppriv[i].used = 0;
- }
-
+ global_ppriv[i].used = 0;
+ }
+
return 1;
}
drm_ioctl_desc_t sis_ioctls[] = {
- [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = { sis_fb_alloc, 1, 0 },
- [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = { sis_fb_free, 1, 0 },
- [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = { sis_ioctl_agp_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 },
- [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = { sis_ioctl_agp_free, 1, 0 },
- [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = { sis_fb_init, 1, 1 }
+ [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, 1, 0},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, 1, 0},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, 1, 0},
+ [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, 1, 1}
};
int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
-
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
index 0e7943e6efea..c275cbb6e9ce 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -36,30 +36,28 @@
#include "drm_pciids.h"
-static int postinit( struct drm_device *dev, unsigned long flags )
+static int postinit(struct drm_device *dev, unsigned long flags)
{
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- dev->primary.minor,
- pci_pretty_name(dev->pdev)
- );
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+ );
return 0;
}
-static int version( drm_version_t *version )
+static int version(drm_version_t * version)
{
int len;
version->version_major = DRIVER_MAJOR;
version->version_minor = DRIVER_MINOR;
version->version_patchlevel = DRIVER_PATCHLEVEL;
- DRM_COPY( version->name, DRIVER_NAME );
- DRM_COPY( version->date, DRIVER_DATE );
- DRM_COPY( version->desc, DRIVER_DESC );
+ DRM_COPY(version->name, DRIVER_NAME);
+ DRM_COPY(version->date, DRIVER_DATE);
+ DRM_COPY(version->desc, DRIVER_DESC);
return 0;
}
@@ -75,18 +73,18 @@ static struct drm_driver driver = {
.postinit = postinit,
.version = version,
.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,
+ }
};
static int __init tdfx_init(void)
@@ -102,6 +100,6 @@ static void __exit tdfx_exit(void)
module_init(tdfx_init);
module_exit(tdfx_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
index cf61bb514db1..462375d543b9 100644
--- a/drivers/char/drm/via_3d_reg.h
+++ b/drivers/char/drm/via_3d_reg.h
@@ -1643,7 +1643,6 @@
#define HC_HAGPBpID_STOP 0x00000002
#define HC_HAGPBpH_MASK 0x00ffffff
-
#define VIA_VIDEO_HEADER5 0xFE040000
#define VIA_VIDEO_HEADER6 0xFE050000
#define VIA_VIDEO_HEADER7 0xFE060000
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 4f60f7f4193d..d4b1766608b0 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -1,11 +1,11 @@
/* via_dma.c -- DMA support for the VIA Unichrome/Pro
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
* All Rights Reserved.
- *
+ *
* Copyright 2004 The Unichrome project.
* All Rights Reserved.
*
@@ -23,14 +23,14 @@
* 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
+ * 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:
- * Tungsten Graphics,
- * Erdi Chen,
+ * Authors:
+ * Tungsten Graphics,
+ * Erdi Chen,
* Thomas Hellstrom.
*/
@@ -61,34 +61,31 @@
dev_priv->dma_low +=8; \
}
-#define via_flush_write_combine() DRM_MEMORYBARRIER()
+#define via_flush_write_combine() DRM_MEMORYBARRIER()
#define VIA_OUT_RING_QW(w1,w2) \
*vb++ = (w1); \
*vb++ = (w2); \
- dev_priv->dma_low += 8;
+ dev_priv->dma_low += 8;
static void via_cmdbuf_start(drm_via_private_t * dev_priv);
static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
static int via_wait_idle(drm_via_private_t * dev_priv);
-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
-
+static void via_pad_cache(drm_via_private_t * dev_priv, int qwords);
/*
* Free space in command buffer.
*/
-static uint32_t
-via_cmdbuf_space(drm_via_private_t *dev_priv)
+static uint32_t via_cmdbuf_space(drm_via_private_t * dev_priv)
{
- uint32_t agp_base = dev_priv->dma_offset +
- (uint32_t) dev_priv->agpAddr;
+ uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
- return ((hw_addr <= dev_priv->dma_low) ?
- (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
+
+ return ((hw_addr <= dev_priv->dma_low) ?
+ (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
(hw_addr - dev_priv->dma_low));
}
@@ -96,15 +93,13 @@ via_cmdbuf_space(drm_via_private_t *dev_priv)
* How much does the command regulator lag behind?
*/
-static uint32_t
-via_cmdbuf_lag(drm_via_private_t *dev_priv)
+static uint32_t via_cmdbuf_lag(drm_via_private_t * dev_priv)
{
- uint32_t agp_base = dev_priv->dma_offset +
- (uint32_t) dev_priv->agpAddr;
+ uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
- return ((hw_addr <= dev_priv->dma_low) ?
- (dev_priv->dma_low - hw_addr) :
+
+ return ((hw_addr <= dev_priv->dma_low) ?
+ (dev_priv->dma_low - hw_addr) :
(dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
}
@@ -121,20 +116,20 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
uint32_t count;
hw_addr_ptr = dev_priv->hw_addr_ptr;
cur_addr = dev_priv->dma_low;
- next_addr = cur_addr + size + 512*1024;
+ next_addr = cur_addr + size + 512 * 1024;
count = 1000000;
do {
- hw_addr = *hw_addr_ptr - agp_base;
+ hw_addr = *hw_addr_ptr - agp_base;
if (count-- == 0) {
- DRM_ERROR("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
- hw_addr, cur_addr, next_addr);
+ DRM_ERROR
+ ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+ hw_addr, cur_addr, next_addr);
return -1;
}
} while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
return 0;
}
-
/*
* Checks whether buffer head has reach the end. Rewind the ring buffer
* when necessary.
@@ -145,7 +140,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
unsigned int size)
{
- if ((dev_priv->dma_low + size + 4*CMDBUF_ALIGNMENT_SIZE) > dev_priv->dma_high) {
+ if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
+ dev_priv->dma_high) {
via_cmdbuf_rewind(dev_priv);
}
if (via_cmdbuf_wait(dev_priv, size) != 0) {
@@ -159,7 +155,7 @@ int via_dma_cleanup(drm_device_t * dev)
{
if (dev->dev_private) {
drm_via_private_t *dev_priv =
- (drm_via_private_t *) dev->dev_private;
+ (drm_via_private_t *) dev->dev_private;
if (dev_priv->ring.virtual_start) {
via_cmdbuf_reset(dev_priv);
@@ -189,7 +185,7 @@ static int via_initialize(drm_device_t * dev,
}
if (!dev->agp || !dev->agp->base) {
- DRM_ERROR("%s called with no agp memory available\n",
+ DRM_ERROR("%s called with no agp memory available\n",
__FUNCTION__);
return DRM_ERR(EFAULT);
}
@@ -247,10 +243,10 @@ int via_dma_init(DRM_IOCTL_ARGS)
else
retcode = via_dma_cleanup(dev);
break;
- case VIA_DMA_INITIALIZED:
- retcode = (dev_priv->ring.virtual_start != NULL) ?
- 0: DRM_ERR( EFAULT );
- break;
+ case VIA_DMA_INITIALIZED:
+ retcode = (dev_priv->ring.virtual_start != NULL) ?
+ 0 : DRM_ERR(EFAULT);
+ break;
default:
retcode = DRM_ERR(EINVAL);
break;
@@ -259,8 +255,6 @@ int via_dma_init(DRM_IOCTL_ARGS)
return retcode;
}
-
-
static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
{
drm_via_private_t *dev_priv;
@@ -277,8 +271,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
if (cmd->size > VIA_PCI_BUF_SIZE) {
return DRM_ERR(ENOMEM);
- }
-
+ }
if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
return DRM_ERR(EFAULT);
@@ -289,19 +282,19 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
* copy it to AGP memory when ready.
*/
-
- if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {
+ if ((ret =
+ via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+ cmd->size, dev, 1))) {
return ret;
}
-
-
+
vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
if (vb == NULL) {
return DRM_ERR(EAGAIN);
}
memcpy(vb, dev_priv->pci_buf, cmd->size);
-
+
dev_priv->dma_low += cmd->size;
/*
@@ -310,7 +303,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
*/
if (cmd->size < 0x100)
- via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
+ via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
via_cmdbuf_pause(dev_priv);
return 0;
@@ -330,7 +323,7 @@ int via_flush_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
return via_driver_dma_quiescent(dev);
}
@@ -341,7 +334,7 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
drm_via_cmdbuffer_t cmdbuf;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
@@ -356,8 +349,9 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-extern int
-via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size);
+extern int
+via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+ unsigned int size);
static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
drm_via_cmdbuffer_t * cmd)
{
@@ -366,15 +360,19 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
if (cmd->size > VIA_PCI_BUF_SIZE) {
return DRM_ERR(ENOMEM);
- }
+ }
if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
return DRM_ERR(EFAULT);
-
- if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 0))) {
+
+ if ((ret =
+ via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+ cmd->size, dev, 0))) {
return ret;
}
-
- ret = via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, cmd->size);
+
+ ret =
+ via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
+ cmd->size);
return ret;
}
@@ -384,7 +382,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
drm_via_cmdbuffer_t cmdbuf;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
@@ -400,17 +398,15 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-
static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
uint32_t * vb, int qw_count)
{
- for (; qw_count > 0; --qw_count) {
+ for (; qw_count > 0; --qw_count) {
VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
}
return vb;
}
-
/*
* This function is used internally by ring buffer mangement code.
*
@@ -426,7 +422,7 @@ static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
* modifying the pause address stored in the buffer itself. If
* the regulator has already paused, restart it.
*/
-static int via_hook_segment(drm_via_private_t *dev_priv,
+static int via_hook_segment(drm_via_private_t * dev_priv,
uint32_t pause_addr_hi, uint32_t pause_addr_lo,
int no_pci_fire)
{
@@ -434,7 +430,7 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
via_flush_write_combine();
- while(! *(via_get_dma(dev_priv)-1));
+ while (!*(via_get_dma(dev_priv) - 1)) ;
*dev_priv->last_pause_ptr = pause_addr_lo;
via_flush_write_combine();
@@ -443,55 +439,53 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
* Not sure it is needed.
*/
- while(! *dev_priv->last_pause_ptr);
+ while (!*dev_priv->last_pause_ptr) ;
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
- while(! *dev_priv->last_pause_ptr);
-
+ while (!*dev_priv->last_pause_ptr) ;
paused = 0;
- count = 20;
+ count = 20;
- while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
+ while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
if ((count <= 8) && (count >= 0)) {
uint32_t rgtr, ptr;
rgtr = *(dev_priv->hw_addr_ptr);
- ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
- dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
- CMDBUF_ALIGNMENT_SIZE;
+ ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
+ CMDBUF_ALIGNMENT_SIZE;
if (rgtr <= ptr) {
- DRM_ERROR("Command regulator\npaused at count %d, address %x, "
- "while current pause address is %x.\n"
- "Please mail this message to "
- "<unichrome-devel@lists.sourceforge.net>\n",
- count, rgtr, ptr);
+ DRM_ERROR
+ ("Command regulator\npaused at count %d, address %x, "
+ "while current pause address is %x.\n"
+ "Please mail this message to "
+ "<unichrome-devel@lists.sourceforge.net>\n", count,
+ rgtr, ptr);
}
}
-
+
if (paused && !no_pci_fire) {
- uint32_t rgtr,ptr;
+ uint32_t rgtr, ptr;
uint32_t ptr_low;
count = 1000000;
- while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) && count--);
-
+ while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
+ && count--) ;
+
rgtr = *(dev_priv->hw_addr_ptr);
- ptr = ((char *)paused_at - dev_priv->dma_ptr) +
- dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
+ ptr = ((char *)paused_at - dev_priv->dma_ptr) +
+ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
- ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ?
- ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
+ ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
+ ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
if (rgtr <= ptr && rgtr >= ptr_low) {
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
- }
+ }
}
return paused;
}
-
-
static int via_wait_idle(drm_via_private_t * dev_priv)
{
int count = 10000000;
@@ -502,9 +496,8 @@ static int via_wait_idle(drm_via_private_t * dev_priv)
}
static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
- uint32_t addr, uint32_t *cmd_addr_hi,
- uint32_t *cmd_addr_lo,
- int skip_wait)
+ uint32_t addr, uint32_t * cmd_addr_hi,
+ uint32_t * cmd_addr_lo, int skip_wait)
{
uint32_t agp_base;
uint32_t cmd_addr, addr_lo, addr_hi;
@@ -512,31 +505,26 @@ static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
uint32_t qw_pad_count;
if (!skip_wait)
- via_cmdbuf_wait(dev_priv, 2*CMDBUF_ALIGNMENT_SIZE);
+ via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
vb = via_get_dma(dev_priv);
- VIA_OUT_RING_QW( HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
- (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
+ VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+ (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
- ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+ ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
-
- cmd_addr = (addr) ? addr :
- agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+ cmd_addr = (addr) ? addr :
+ agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
(cmd_addr & HC_HAGPBpL_MASK));
addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
- VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi,
- *cmd_addr_lo = addr_lo);
+ VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
return vb;
}
-
-
-
static void via_cmdbuf_start(drm_via_private_t * dev_priv)
{
uint32_t pause_addr_lo, pause_addr_hi;
@@ -545,7 +533,6 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
uint32_t command;
uint32_t agp_base;
-
dev_priv->dma_low = 0;
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
@@ -557,12 +544,12 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
((end_addr & 0xff000000) >> 16));
- dev_priv->last_pause_ptr =
- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
- &pause_addr_hi, & pause_addr_lo, 1) - 1;
+ dev_priv->last_pause_ptr =
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+ &pause_addr_hi, &pause_addr_lo, 1) - 1;
via_flush_write_combine();
- while(! *dev_priv->last_pause_ptr);
+ while (!*dev_priv->last_pause_ptr) ;
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, command);
@@ -575,14 +562,14 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
}
-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
{
uint32_t *vb;
via_cmdbuf_wait(dev_priv, qwords + 2);
vb = via_get_dma(dev_priv);
- VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
- via_align_buffer(dev_priv,vb,qwords);
+ VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
+ via_align_buffer(dev_priv, vb, qwords);
}
static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
@@ -590,10 +577,9 @@ static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
uint32_t *vb = via_get_dma(dev_priv);
SetReg2DAGP(0x0C, (0 | (0 << 16)));
SetReg2DAGP(0x10, 0 | (0 << 16));
- SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
+ SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
}
-
static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
{
uint32_t agp_base;
@@ -603,11 +589,10 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
uint32_t dma_low_save1, dma_low_save2;
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
- via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+ via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
&jump_addr_lo, 0);
-
- dev_priv->dma_wrap = dev_priv->dma_low;
+ dev_priv->dma_wrap = dev_priv->dma_low;
/*
* Wrap command buffer to the beginning.
@@ -619,11 +604,12 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
}
via_dummy_bitblt(dev_priv);
- via_dummy_bitblt(dev_priv);
+ via_dummy_bitblt(dev_priv);
- last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
- &pause_addr_lo, 0) -1;
- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ last_pause_ptr =
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0) - 1;
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
&pause_addr_lo, 0);
*last_pause_ptr = pause_addr_lo;
@@ -638,23 +624,23 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
* does not seem to get updated immediately when a jump occurs.
*/
- last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
- &pause_addr_lo, 0) -1;
- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ last_pause_ptr =
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0) - 1;
+ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
&pause_addr_lo, 0);
*last_pause_ptr = pause_addr_lo;
dma_low_save2 = dev_priv->dma_low;
- dev_priv->dma_low = dma_low_save1;
- via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
+ dev_priv->dma_low = dma_low_save1;
+ via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
dev_priv->dma_low = dma_low_save2;
- via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+ via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
}
-
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
{
- via_cmdbuf_jump(dev_priv);
+ via_cmdbuf_jump(dev_priv);
}
static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
@@ -662,10 +648,9 @@ static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
uint32_t pause_addr_lo, pause_addr_hi;
via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
- via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+ via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
}
-
static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
{
via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
@@ -681,8 +666,7 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
* User interface to the space and lag functions.
*/
-int
-via_cmdbuf_size(DRM_IOCTL_ARGS)
+int via_cmdbuf_size(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_cmdbuf_size_t d_siz;
@@ -691,7 +675,7 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
drm_via_private_t *dev_priv;
DRM_DEBUG("via cmdbuf_size\n");
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -704,12 +688,12 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
sizeof(d_siz));
-
count = 1000000;
tmp_size = d_siz.size;
- switch(d_siz.func) {
+ switch (d_siz.func) {
case VIA_CMDBUF_SPACE:
- while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size) && count--) {
+ while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size)
+ && count--) {
if (!d_siz.wait) {
break;
}
@@ -720,7 +704,8 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
}
break;
case VIA_CMDBUF_LAG:
- while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size) && count--) {
+ while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size)
+ && count--) {
if (!d_siz.wait) {
break;
}
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index be346bb0a26a..ebde9206115e 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -149,7 +149,7 @@ typedef struct _drm_via_dma_init {
enum {
VIA_INIT_DMA = 0x01,
VIA_CLEANUP_DMA = 0x02,
- VIA_DMA_INITIALIZED = 0x03
+ VIA_DMA_INITIALIZED = 0x03
} func;
unsigned long offset;
@@ -212,7 +212,7 @@ typedef enum {
#define VIA_IRQ_FLAGS_MASK 0xF0000000
-struct drm_via_wait_irq_request{
+struct drm_via_wait_irq_request {
unsigned irq;
via_irq_seq_type_t type;
uint32_t sequence;
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
index 275eefc79221..016665e0c69f 100644
--- a/drivers/char/drm/via_drv.c
+++ b/drivers/char/drm/via_drv.c
@@ -93,18 +93,18 @@ static struct drm_driver driver = {
.ioctls = ioctls,
.num_ioctls = DRM_ARRAY_SIZE(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,
+ }
};
static int __init via_init(void)
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 4eaa8b7c4c96..7d5daf43797e 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -40,8 +40,6 @@
#define VIA_FIRE_BUF_SIZE 1024
#define VIA_NUM_IRQS 2
-
-
typedef struct drm_via_ring_buffer {
drm_map_t map;
char *virtual_start;
@@ -55,7 +53,7 @@ typedef struct drm_via_irq {
uint32_t enable_mask;
wait_queue_head_t irq_queue;
} drm_via_irq_t;
-
+
typedef struct drm_via_private {
drm_via_sarea_t *sarea_priv;
drm_map_t *sarea;
@@ -71,9 +69,9 @@ typedef struct drm_via_private {
volatile uint32_t *last_pause_ptr;
volatile uint32_t *hw_addr_ptr;
drm_via_ring_buffer_t ring;
- struct timeval last_vblank;
- int last_vblank_valid;
- unsigned usec_per_vblank;
+ struct timeval last_vblank;
+ int last_vblank_valid;
+ unsigned usec_per_vblank;
drm_via_state_t hc_state;
char pci_buf[VIA_PCI_BUF_SIZE];
const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -82,8 +80,8 @@ typedef struct drm_via_private {
drm_via_irq_t via_irqs[VIA_NUM_IRQS];
unsigned num_irqs;
maskarray_t *irq_masks;
- uint32_t irq_enable_mask;
- uint32_t irq_pending_mask;
+ uint32_t irq_enable_mask;
+ uint32_t irq_pending_mask;
} drm_via_private_t;
/* VIA MMIO register access */
@@ -110,9 +108,11 @@ extern void via_driver_irq_uninstall(drm_device_t * dev);
extern int via_dma_cleanup(drm_device_t * dev);
extern void via_init_command_verifier(void);
extern int via_driver_dma_quiescent(drm_device_t * 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 int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+ unsigned int size);
#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index e8027f3a93b0..d023add1929b 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -54,23 +54,26 @@
/*
* Device-specific IRQs go here. This type might need to be extended with
* the register if there are multiple IRQ control registers.
- * Currently we activate the HQV interrupts of Unichrome Pro group A.
+ * Currently we activate the HQV interrupts of Unichrome Pro group A.
*/
static maskarray_t via_pro_group_a_irqs[] = {
- {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000 },
- {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 }};
-static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
-
-static maskarray_t via_unichrome_irqs[] = {};
-static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
-
-
-static unsigned time_diff(struct timeval *now,struct timeval *then)
+ {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
+ 0x00000000},
+ {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
+ 0x00000000}
+};
+static int via_num_pro_group_a =
+ sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+
+static maskarray_t via_unichrome_irqs[] = { };
+static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+
+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);
+ return (now->tv_usec >= then->tv_usec) ?
+ now->tv_usec - then->tv_usec :
+ 1000000 - (then->tv_usec - now->tv_usec);
}
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -86,38 +89,37 @@ 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)) {
+ if (!(atomic_read(&dev->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;
+ if (dev_priv->last_vblank_valid) {
+ dev_priv->usec_per_vblank =
+ 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->vbl_received) & 0xFF)) {
DRM_DEBUG("US per vblank is: %u\n",
- dev_priv->usec_per_vblank);
+ dev_priv->usec_per_vblank);
}
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
handled = 1;
}
-
- for (i=0; i<dev_priv->num_irqs; ++i) {
+ for (i = 0; i < dev_priv->num_irqs; ++i) {
if (status & cur_irq->pending_mask) {
- atomic_inc( &cur_irq->irq_received );
- DRM_WAKEUP( &cur_irq->irq_queue );
+ atomic_inc(&cur_irq->irq_received);
+ DRM_WAKEUP(&cur_irq->irq_queue);
handled = 1;
}
cur_irq++;
}
-
+
/* Acknowlege interrupts */
VIA_WRITE(VIA_REG_INTERRUPT, status);
-
if (handled)
return IRQ_HANDLED;
else
@@ -131,7 +133,7 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
if (dev_priv) {
/* Acknowlege interrupts */
status = VIA_READ(VIA_REG_INTERRUPT);
- VIA_WRITE(VIA_REG_INTERRUPT, status |
+ VIA_WRITE(VIA_REG_INTERRUPT, status |
dev_priv->irq_pending_mask);
}
}
@@ -158,12 +160,12 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
(((cur_vblank = atomic_read(&dev->vbl_received)) -
*sequence) <= (1 << 23)));
-
+
*sequence = cur_vblank;
return ret;
}
-static int
+static int
via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
@@ -180,27 +182,29 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
return DRM_ERR(EINVAL);
}
- if (irq >= dev_priv->num_irqs ) {
- DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
+ if (irq >= dev_priv->num_irqs) {
+ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
+ irq);
return DRM_ERR(EINVAL);
}
-
+
cur_irq += irq;
if (masks[irq][2] && !force_sequence) {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
- ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4]));
+ ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
+ masks[irq][4]));
cur_irq_sequence = atomic_read(&cur_irq->irq_received);
} else {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
- (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) -
- *sequence) <= (1 << 23)));
+ (((cur_irq_sequence =
+ atomic_read(&cur_irq->irq_received)) -
+ *sequence) <= (1 << 23)));
}
*sequence = cur_irq_sequence;
return ret;
}
-
/*
* drm_dma.h hooks
*/
@@ -219,29 +223,29 @@ void via_driver_irq_preinstall(drm_device_t * dev)
dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
dev_priv->irq_masks = (dev_priv->pro_group_a) ?
- via_pro_group_a_irqs : via_unichrome_irqs;
+ via_pro_group_a_irqs : via_unichrome_irqs;
dev_priv->num_irqs = (dev_priv->pro_group_a) ?
- via_num_pro_group_a : via_num_unichrome;
-
- for(i=0; i < dev_priv->num_irqs; ++i) {
+ via_num_pro_group_a : via_num_unichrome;
+
+ for (i = 0; i < dev_priv->num_irqs; ++i) {
atomic_set(&cur_irq->irq_received, 0);
- cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+ cur_irq->enable_mask = dev_priv->irq_masks[i][0];
cur_irq->pending_mask = dev_priv->irq_masks[i][1];
- DRM_INIT_WAITQUEUE( &cur_irq->irq_queue );
+ DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
dev_priv->irq_enable_mask |= cur_irq->enable_mask;
dev_priv->irq_pending_mask |= cur_irq->pending_mask;
cur_irq++;
-
+
DRM_DEBUG("Initializing IRQ %d\n", i);
}
-
- dev_priv->last_vblank_valid = 0;
+
+ dev_priv->last_vblank_valid = 0;
// Clear VSync interrupt regs
status = VIA_READ(VIA_REG_INTERRUPT);
- VIA_WRITE(VIA_REG_INTERRUPT, status &
+ VIA_WRITE(VIA_REG_INTERRUPT, status &
~(dev_priv->irq_enable_mask));
-
+
/* Clear bits if they're already high */
viadrv_acknowledge_irqs(dev_priv);
}
@@ -262,7 +266,7 @@ void via_driver_irq_postinstall(drm_device_t * dev)
VIA_WRITE8(0x83d4, 0x11);
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
-
+
}
}
@@ -280,7 +284,7 @@ void via_driver_irq_uninstall(drm_device_t * dev)
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
status = VIA_READ(VIA_REG_INTERRUPT);
- VIA_WRITE(VIA_REG_INTERRUPT, status &
+ VIA_WRITE(VIA_REG_INTERRUPT, status &
~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
}
}
@@ -302,7 +306,7 @@ int via_wait_irq(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
if (irqwait.request.irq >= dev_priv->num_irqs) {
- DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
+ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
irqwait.request.irq);
return DRM_ERR(EINVAL);
}
@@ -320,7 +324,7 @@ int via_wait_irq(DRM_IOCTL_ARGS)
}
if (irqwait.request.type & VIA_IRQ_SIGNAL) {
- DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
+ DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
__FUNCTION__);
return DRM_ERR(EINVAL);
}
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index bb171139e737..6bd6ac52ad1b 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -66,7 +66,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
dev_priv->agpAddr = init->agpAddr;
- via_init_futex( dev_priv );
+ via_init_futex(dev_priv);
dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
dev->dev_private = (void *)dev_priv;
@@ -107,5 +107,3 @@ int via_map_init(DRM_IOCTL_ARGS)
return -EINVAL;
}
-
-
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 13921f3c0ec2..3baddacdff26 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -81,7 +81,8 @@ int via_agp_init(DRM_IOCTL_ARGS)
AgpHeap = via_mmInit(agp.offset, agp.size);
- DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);
+ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset,
+ (unsigned long)agp.size);
return 0;
}
@@ -97,7 +98,8 @@ int via_fb_init(DRM_IOCTL_ARGS)
FBHeap = via_mmInit(fb.offset, fb.size);
- DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);
+ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset,
+ (unsigned long)fb.size);
return 0;
}
@@ -134,8 +136,8 @@ int via_init_context(struct drm_device *dev, int context)
}
int via_final_context(struct drm_device *dev, int context)
-{
- int i;
+{
+ int i;
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
for (i = 0; i < MAX_CONTEXT; i++)
@@ -171,14 +173,13 @@ int via_final_context(struct drm_device *dev, int context)
via_setDestroy(set);
global_ppriv[i].used = 0;
}
- via_release_futex(dev_priv, context);
-
-
+ via_release_futex(dev_priv, context);
+
#if defined(__linux__)
/* Linux specific until context tracking code gets ported to BSD */
/* Last context, perform cleanup */
if (dev->ctx_count == 1 && dev->dev_private) {
- DRM_DEBUG("Last Context\n");
+ DRM_DEBUG("Last Context\n");
if (dev->irq)
drm_irq_uninstall(dev);
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 07923b0c7a97..4ac495f297f7 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -28,7 +28,6 @@
* be very slow.
*/
-
#include "via_3d_reg.h"
#include "drmP.h"
#include "drm.h"
@@ -36,7 +35,7 @@
#include "via_verifier.h"
#include "via_drv.h"
-typedef enum{
+typedef enum {
state_command,
state_header2,
state_header1,
@@ -45,8 +44,7 @@ typedef enum{
state_error
} verifier_state_t;
-
-typedef enum{
+typedef enum {
no_check = 0,
check_for_header2,
check_for_header1,
@@ -74,16 +72,16 @@ typedef enum{
check_for_vertex_count,
check_number_texunits,
forbidden_command
-}hazard_t;
+} hazard_t;
/*
* Associates each hazard above with a possible multi-command
* sequence. For example an address that is split over multiple
- * commands and that needs to be checked at the first command
+ * commands and that needs to be checked at the first command
* that does not include any part of the address.
*/
-static drm_via_sequence_t seqs[] = {
+static drm_via_sequence_t seqs[] = {
no_sequence,
no_sequence,
no_sequence,
@@ -110,14 +108,12 @@ static drm_via_sequence_t seqs[] = {
tex_address,
no_sequence
};
-
-typedef struct{
+
+typedef struct {
unsigned int code;
hazard_t hz;
} hz_init_t;
-
-
static hz_init_t init_table1[] = {
{0xf2, check_for_header2_err},
{0xf0, check_for_header1_err},
@@ -169,8 +165,6 @@ static hz_init_t init_table1[] = {
{0x7D, check_for_vertex_count}
};
-
-
static hz_init_t init_table2[] = {
{0xf2, check_for_header2_err},
{0xf0, check_for_header1_err},
@@ -235,49 +229,49 @@ static hz_init_t init_table3[] = {
{0xcc, check_for_dummy},
{0x00, check_number_texunits}
};
-
-
-static hazard_t table1[256];
-static hazard_t table2[256];
-static hazard_t table3[256];
-
+static hazard_t table1[256];
+static hazard_t table2[256];
+static hazard_t table3[256];
static __inline__ int
-eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
+eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
{
if ((*buf - buf_end) >= num_words) {
*buf += num_words;
return 0;
- }
+ }
DRM_ERROR("Illegal termination of DMA command buffer\n");
return 1;
}
-
/*
* Partially stolen from drm_memory.h
*/
-static __inline__ drm_map_t *
-via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size,
- drm_device_t *dev)
+static __inline__ drm_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
+ unsigned long offset,
+ unsigned long size,
+ drm_device_t * dev)
{
struct list_head *list;
drm_map_list_t *r_list;
drm_map_t *map = seq->map_cache;
- if (map && map->offset <= offset && (offset + size) <= (map->offset + map->size)) {
+ if (map && map->offset <= offset
+ && (offset + size) <= (map->offset + map->size)) {
return map;
}
-
+
list_for_each(list, &dev->maplist->head) {
r_list = (drm_map_list_t *) list;
map = r_list->map;
if (!map)
continue;
- if (map->offset <= offset && (offset + size) <= (map->offset + map->size) &&
- !(map->flags & _DRM_RESTRICTED) && (map->type == _DRM_AGP)) {
+ if (map->offset <= offset
+ && (offset + size) <= (map->offset + map->size)
+ && !(map->flags & _DRM_RESTRICTED)
+ && (map->type == _DRM_AGP)) {
seq->map_cache = map;
return map;
}
@@ -285,54 +279,60 @@ via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned lon
return NULL;
}
-
/*
- * Require that all AGP texture levels reside in the same AGP map which should
+ * Require that all AGP texture levels reside in the same AGP map which should
* be mappable by the client. This is not a big restriction.
- * FIXME: To actually enforce this security policy strictly, drm_rmmap
- * would have to wait for dma quiescent before removing an AGP map.
+ * FIXME: To actually enforce this security policy strictly, drm_rmmap
+ * would have to wait for dma quiescent before removing an AGP map.
* The via_drm_lookup_agp_map call in reality seems to take
* very little CPU time.
*/
-
-static __inline__ int
-finish_current_sequence(drm_via_state_t *cur_seq)
+static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
{
- switch(cur_seq->unfinished) {
+ switch (cur_seq->unfinished) {
case z_address:
DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
break;
case dest_address:
- DRM_DEBUG("Destination start address is 0x%x\n", cur_seq->d_addr);
+ DRM_DEBUG("Destination start address is 0x%x\n",
+ cur_seq->d_addr);
break;
case tex_address:
- if (cur_seq->agp_texture) {
- unsigned start = cur_seq->tex_level_lo[cur_seq->texture];
+ if (cur_seq->agp_texture) {
+ unsigned start =
+ cur_seq->tex_level_lo[cur_seq->texture];
unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
- unsigned long lo=~0, hi=0, tmp;
+ unsigned long lo = ~0, hi = 0, tmp;
uint32_t *addr, *pitch, *height, tex;
unsigned i;
- if (end > 9) end = 9;
- if (start > 9) start = 9;
+ if (end > 9)
+ end = 9;
+ if (start > 9)
+ start = 9;
- addr =&(cur_seq->t_addr[tex = cur_seq->texture][start]);
+ addr =
+ &(cur_seq->t_addr[tex = cur_seq->texture][start]);
pitch = &(cur_seq->pitch[tex][start]);
height = &(cur_seq->height[tex][start]);
- for (i=start; i<= end; ++i) {
+ for (i = start; i <= end; ++i) {
tmp = *addr++;
- if (tmp < lo) lo = tmp;
+ if (tmp < lo)
+ lo = tmp;
tmp += (*height++ << *pitch++);
- if (tmp > hi) hi = tmp;
+ if (tmp > hi)
+ hi = tmp;
}
- if (! via_drm_lookup_agp_map (cur_seq, lo, hi - lo, cur_seq->dev)) {
- DRM_ERROR("AGP texture is not in allowed map\n");
+ if (!via_drm_lookup_agp_map
+ (cur_seq, lo, hi - lo, cur_seq->dev)) {
+ DRM_ERROR
+ ("AGP texture is not in allowed map\n");
return 2;
}
- }
+ }
break;
default:
break;
@@ -341,73 +341,84 @@ finish_current_sequence(drm_via_state_t *cur_seq)
return 0;
}
-static __inline__ int
-investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
+static __inline__ int
+investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
{
register uint32_t tmp, *tmp_addr;
if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
int ret;
- if ((ret = finish_current_sequence(cur_seq))) return ret;
+ if ((ret = finish_current_sequence(cur_seq)))
+ return ret;
}
- switch(hz) {
+ switch (hz) {
case check_for_header2:
- if (cmd == HALCYON_HEADER2) return 1;
+ if (cmd == HALCYON_HEADER2)
+ return 1;
return 0;
case check_for_header1:
- if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
+ if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ return 1;
return 0;
case check_for_header2_err:
- if (cmd == HALCYON_HEADER2) return 1;
+ if (cmd == HALCYON_HEADER2)
+ return 1;
DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
break;
case check_for_header1_err:
- if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
+ if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ return 1;
DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
break;
case check_for_fire:
- if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) return 1;
+ if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
+ return 1;
DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
break;
case check_for_dummy:
- if (HC_DUMMY == cmd) return 0;
+ if (HC_DUMMY == cmd)
+ return 0;
DRM_ERROR("Illegal DMA HC_DUMMY command\n");
break;
case check_for_dd:
- if (0xdddddddd == cmd) return 0;
+ if (0xdddddddd == cmd)
+ return 0;
DRM_ERROR("Illegal DMA 0xdddddddd command\n");
break;
case check_z_buffer_addr0:
cur_seq->unfinished = z_address;
cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
- (cmd & 0x00FFFFFF);
+ (cmd & 0x00FFFFFF);
return 0;
case check_z_buffer_addr1:
cur_seq->unfinished = z_address;
cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
- ((cmd & 0xFF) << 24);
+ ((cmd & 0xFF) << 24);
return 0;
case check_z_buffer_addr_mode:
cur_seq->unfinished = z_address;
- if ((cmd & 0x0000C000) == 0) return 0;
+ if ((cmd & 0x0000C000) == 0)
+ return 0;
DRM_ERROR("Attempt to place Z buffer in system memory\n");
return 2;
case check_destination_addr0:
cur_seq->unfinished = dest_address;
cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
- (cmd & 0x00FFFFFF);
+ (cmd & 0x00FFFFFF);
return 0;
case check_destination_addr1:
cur_seq->unfinished = dest_address;
cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
- ((cmd & 0xFF) << 24);
+ ((cmd & 0xFF) << 24);
return 0;
case check_destination_addr_mode:
cur_seq->unfinished = dest_address;
- if ((cmd & 0x0000C000) == 0) return 0;
- DRM_ERROR("Attempt to place 3D drawing buffer in system memory\n");
- return 2;
+ if ((cmd & 0x0000C000) == 0)
+ return 0;
+ DRM_ERROR
+ ("Attempt to place 3D drawing buffer in system memory\n");
+ return 2;
case check_texture_addr0:
cur_seq->unfinished = tex_address;
tmp = (cmd >> 24);
@@ -433,9 +444,11 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
case check_texture_addr3:
cur_seq->unfinished = tex_address;
tmp = ((cmd >> 24) - 0x2B);
- cur_seq->pitch[cur_seq->texture][tmp] = (cmd & 0x00F00000) >> 20;
+ cur_seq->pitch[cur_seq->texture][tmp] =
+ (cmd & 0x00F00000) >> 20;
if (!tmp && (cmd & 0x000FFFFF)) {
- DRM_ERROR("Unimplemented texture level 0 pitch mode.\n");
+ DRM_ERROR
+ ("Unimplemented texture level 0 pitch mode.\n");
return 2;
}
return 0;
@@ -449,7 +462,7 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
cur_seq->unfinished = tex_address;
/*
* Texture width. We don't care since we have the pitch.
- */
+ */
return 0;
case check_texture_addr7:
cur_seq->unfinished = tex_address;
@@ -465,25 +478,26 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
cur_seq->unfinished = tex_address;
tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
- tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+ tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
tmp_addr[6] = 1 << (cmd & 0x0000000F);
return 0;
case check_texture_addr_mode:
cur_seq->unfinished = tex_address;
- if ( 2 == (tmp = cmd & 0x00000003)) {
- DRM_ERROR("Attempt to fetch texture from system memory.\n");
+ if (2 == (tmp = cmd & 0x00000003)) {
+ DRM_ERROR
+ ("Attempt to fetch texture from system memory.\n");
return 2;
}
cur_seq->agp_texture = (tmp == 3);
- cur_seq->tex_palette_size[cur_seq->texture] =
- (cmd >> 16) & 0x000000007;
+ cur_seq->tex_palette_size[cur_seq->texture] =
+ (cmd >> 16) & 0x000000007;
return 0;
case check_for_vertex_count:
cur_seq->vertex_count = cmd & 0x0000FFFF;
return 0;
case check_number_texunits:
- cur_seq->multitex = (cmd >> 3) & 1;
+ cur_seq->multitex = (cmd >> 3) & 1;
return 0;
default:
DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
@@ -492,25 +506,27 @@ investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
return 2;
}
-
static __inline__ int
-via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
- drm_via_state_t *cur_seq)
+via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
+ drm_via_state_t * cur_seq)
{
- drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;
- uint32_t a_fire, bcmd , dw_count;
+ drm_via_private_t *dev_priv =
+ (drm_via_private_t *) cur_seq->dev->dev_private;
+ uint32_t a_fire, bcmd, dw_count;
int ret = 0;
int have_fire;
const uint32_t *buf = *buffer;
- while(buf < buf_end) {
- have_fire = 0;
+ while (buf < buf_end) {
+ have_fire = 0;
if ((buf_end - buf) < 2) {
- DRM_ERROR("Unexpected termination of primitive list.\n");
+ DRM_ERROR
+ ("Unexpected termination of primitive list.\n");
ret = 1;
break;
}
- if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) break;
+ if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
+ break;
bcmd = *buf++;
if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
@@ -518,43 +534,56 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
ret = 1;
break;
}
- a_fire = *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK;
-
+ a_fire =
+ *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
+ HC_HE3Fire_MASK;
+
/*
* How many dwords per vertex ?
- */
-
+ */
+
if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
DRM_ERROR("Illegal B command vertex data for AGP.\n");
ret = 1;
break;
- }
+ }
dw_count = 0;
- if (bcmd & (1 << 7)) dw_count += (cur_seq->multitex) ? 2:1;
- if (bcmd & (1 << 8)) dw_count += (cur_seq->multitex) ? 2:1;
- if (bcmd & (1 << 9)) dw_count++;
- if (bcmd & (1 << 10)) dw_count++;
- if (bcmd & (1 << 11)) dw_count++;
- if (bcmd & (1 << 12)) dw_count++;
- if (bcmd & (1 << 13)) dw_count++;
- if (bcmd & (1 << 14)) dw_count++;
-
- while(buf < buf_end) {
+ if (bcmd & (1 << 7))
+ dw_count += (cur_seq->multitex) ? 2 : 1;
+ if (bcmd & (1 << 8))
+ dw_count += (cur_seq->multitex) ? 2 : 1;
+ if (bcmd & (1 << 9))
+ dw_count++;
+ if (bcmd & (1 << 10))
+ dw_count++;
+ if (bcmd & (1 << 11))
+ dw_count++;
+ if (bcmd & (1 << 12))
+ dw_count++;
+ if (bcmd & (1 << 13))
+ dw_count++;
+ if (bcmd & (1 << 14))
+ dw_count++;
+
+ while (buf < buf_end) {
if (*buf == a_fire) {
- if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) {
+ if (dev_priv->num_fire_offsets >=
+ VIA_FIRE_BUF_SIZE) {
DRM_ERROR("Fire offset buffer full.\n");
ret = 1;
break;
}
- dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;
- have_fire = 1;
+ dev_priv->fire_offsets[dev_priv->
+ num_fire_offsets++] =
+ buf;
+ have_fire = 1;
buf++;
- if (buf < buf_end && *buf == a_fire)
+ if (buf < buf_end && *buf == a_fire)
buf++;
break;
}
- if ((*buf == HALCYON_HEADER2) ||
+ if ((*buf == HALCYON_HEADER2) ||
((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
DRM_ERROR("Missing Vertex Fire command, "
"Stray Vertex Fire command or verifier "
@@ -576,18 +605,14 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
ret = 1;
break;
}
- }
+ }
*buffer = buf;
return ret;
}
-
-
-
-
static __inline__ verifier_state_t
-via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
- drm_via_state_t *hc_state)
+via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
+ drm_via_state_t * hc_state)
{
uint32_t cmd;
int hz_mode;
@@ -595,17 +620,17 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
const uint32_t *buf = *buffer;
const hazard_t *hz_table;
-
if ((buf_end - buf) < 2) {
- DRM_ERROR("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+ DRM_ERROR
+ ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
return state_error;
}
buf++;
cmd = (*buf++ & 0xFFFF0000) >> 16;
- switch(cmd) {
+ switch (cmd) {
case HC_ParaType_CmdVdata:
- if (via_check_prim_list(&buf, buf_end, hc_state ))
+ if (via_check_prim_list(&buf, buf_end, hc_state))
return state_error;
*buffer = buf;
return state_command;
@@ -650,13 +675,13 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
*/
DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
- "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
- cmd, *(buf -2));
+ "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+ cmd, *(buf - 2));
*buffer = buf;
return state_error;
}
- while(buf < buf_end) {
+ while (buf < buf_end) {
cmd = *buf++;
if ((hz = hz_table[cmd >> 24])) {
if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
@@ -666,7 +691,7 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
}
return state_error;
}
- } else if (hc_state->unfinished &&
+ } else if (hc_state->unfinished &&
finish_current_sequence(hc_state)) {
return state_error;
}
@@ -679,64 +704,65 @@ via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
}
static __inline__ verifier_state_t
-via_parse_header2( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end,
- int *fire_count)
+via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
+ const uint32_t * buf_end, int *fire_count)
{
uint32_t cmd;
const uint32_t *buf = *buffer;
- const uint32_t *next_fire;
+ const uint32_t *next_fire;
int burst = 0;
next_fire = dev_priv->fire_offsets[*fire_count];
buf++;
cmd = (*buf & 0xFFFF0000) >> 16;
VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
- switch(cmd) {
+ switch (cmd) {
case HC_ParaType_CmdVdata:
while ((buf < buf_end) &&
- (*fire_count < dev_priv->num_fire_offsets) &&
- (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB ) {
- while(buf <= next_fire) {
- VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
+ (*fire_count < dev_priv->num_fire_offsets) &&
+ (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
+ while (buf <= next_fire) {
+ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+ (burst & 63), *buf++);
burst += 4;
}
- if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+ if ((buf < buf_end)
+ && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
buf++;
- if (++(*fire_count) < dev_priv->num_fire_offsets)
+ if (++(*fire_count) < dev_priv->num_fire_offsets)
next_fire = dev_priv->fire_offsets[*fire_count];
}
break;
default:
- while(buf < buf_end) {
-
- if ( *buf == HC_HEADER2 ||
- (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
- (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
- (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6 ) break;
-
- VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
- burst +=4;
+ while (buf < buf_end) {
+
+ if (*buf == HC_HEADER2 ||
+ (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+ (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+ (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+ break;
+
+ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+ (burst & 63), *buf++);
+ burst += 4;
}
}
*buffer = buf;
return state_command;
}
-
-
-static __inline__ int
-verify_mmio_address( uint32_t address)
+static __inline__ int verify_mmio_address(uint32_t address)
{
- if ((address > 0x3FF) && (address < 0xC00 )) {
+ if ((address > 0x3FF) && (address < 0xC00)) {
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access 3D- or command burst area.\n");
return 1;
} else if ((address > 0xCFF) && (address < 0x1300)) {
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access PCI DMA area.\n");
- return 1;
- } else if (address > 0x13FF ) {
+ return 1;
+ } else if (address > 0x13FF) {
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access VGA registers.\n");
return 1;
@@ -745,7 +771,8 @@ verify_mmio_address( uint32_t address)
}
static __inline__ int
-verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dwords)
+verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
+ uint32_t dwords)
{
const uint32_t *buf = *buffer;
@@ -762,10 +789,9 @@ verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dw
*buffer = buf;
return 0;
}
-
static __inline__ verifier_state_t
-via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
{
uint32_t cmd;
const uint32_t *buf = *buffer;
@@ -774,21 +800,21 @@ via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
while (buf < buf_end) {
cmd = *buf;
if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
- (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+ (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
break;
DRM_ERROR("Invalid HALCYON_HEADER1 command. "
"Attempt to access 3D- or command burst area.\n");
ret = state_error;
break;
} else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
break;
DRM_ERROR("Invalid HALCYON_HEADER1 command. "
"Attempt to access VGA registers.\n");
ret = state_error;
- break;
- } else {
+ break;
+ } else {
buf += 2;
}
}
@@ -797,15 +823,17 @@ via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
}
static __inline__ verifier_state_t
-via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
+ const uint32_t * buf_end)
{
register uint32_t cmd;
const uint32_t *buf = *buffer;
while (buf < buf_end) {
cmd = *buf;
- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) break;
- VIA_WRITE( (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+ break;
+ VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
buf++;
}
*buffer = buf;
@@ -813,7 +841,7 @@ via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const u
}
static __inline__ verifier_state_t
-via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
{
uint32_t data;
const uint32_t *buf = *buffer;
@@ -836,41 +864,41 @@ via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
DRM_ERROR("Illegal header5 header data\n");
return state_error;
}
- if (eat_words(&buf, buf_end, data))
+ if (eat_words(&buf, buf_end, data))
return state_error;
- if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+ if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
return state_error;
*buffer = buf;
return state_command;
-
-}
+
+}
static __inline__ verifier_state_t
-via_parse_vheader5( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
+ const uint32_t * buf_end)
{
- uint32_t addr, count, i;
+ uint32_t addr, count, i;
const uint32_t *buf = *buffer;
-
+
addr = *buf++ & ~VIA_VIDEOMASK;
i = count = *buf;
buf += 3;
- while(i--) {
+ while (i--) {
VIA_WRITE(addr, *buf++);
}
- if (count & 3) buf += 4 - (count & 3);
+ if (count & 3)
+ buf += 4 - (count & 3);
*buffer = buf;
- return state_command;
-}
-
+ return state_command;
+}
static __inline__ verifier_state_t
-via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
+via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
{
uint32_t data;
const uint32_t *buf = *buffer;
uint32_t i;
-
if (buf_end - buf < 4) {
DRM_ERROR("Illegal termination of video header6 command\n");
return state_error;
@@ -889,7 +917,7 @@ via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
DRM_ERROR("Illegal termination of video header6 command\n");
return state_error;
}
- for (i=0; i<data; ++i) {
+ for (i = 0; i < data; ++i) {
if (verify_mmio_address(*buf++))
return state_error;
buf++;
@@ -899,42 +927,42 @@ via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
return state_error;
*buffer = buf;
return state_command;
-}
+}
static __inline__ verifier_state_t
-via_parse_vheader6( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
+via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
+ const uint32_t * buf_end)
{
- uint32_t addr, count, i;
+ uint32_t addr, count, i;
const uint32_t *buf = *buffer;
i = count = *++buf;
buf += 3;
- while(i--) {
+ while (i--) {
addr = *buf++;
VIA_WRITE(addr, *buf++);
}
count <<= 1;
- if (count & 3) buf += 4 - (count & 3);
+ if (count & 3)
+ buf += 4 - (count & 3);
*buffer = buf;
return state_command;
-}
-
-
+}
-int
-via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev,
- int agp)
+int
+via_verify_command_stream(const uint32_t * buf, unsigned int size,
+ drm_device_t * dev, int agp)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
drm_via_state_t *hc_state = &dev_priv->hc_state;
drm_via_state_t saved_state = *hc_state;
uint32_t cmd;
- const uint32_t *buf_end = buf + ( size >> 2 );
+ const uint32_t *buf_end = buf + (size >> 2);
verifier_state_t state = state_command;
int pro_group_a = dev_priv->pro_group_a;
-
+
hc_state->dev = dev;
hc_state->unfinished = no_sequence;
hc_state->map_cache = NULL;
@@ -946,38 +974,41 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t
switch (state) {
case state_header2:
- state = via_check_header2( &buf, buf_end, hc_state );
+ state = via_check_header2(&buf, buf_end, hc_state);
break;
case state_header1:
- state = via_check_header1( &buf, buf_end );
+ state = via_check_header1(&buf, buf_end);
break;
case state_vheader5:
- state = via_check_vheader5( &buf, buf_end );
+ state = via_check_vheader5(&buf, buf_end);
break;
case state_vheader6:
- state = via_check_vheader6( &buf, buf_end );
+ state = via_check_vheader6(&buf, buf_end);
break;
case state_command:
- if (HALCYON_HEADER2 == (cmd = *buf))
+ if (HALCYON_HEADER2 == (cmd = *buf))
state = state_header2;
- else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
state = state_header1;
- else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+ else if (pro_group_a
+ && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
state = state_vheader5;
- else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+ else if (pro_group_a
+ && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
state = state_vheader6;
else {
- DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
- cmd);
+ DRM_ERROR
+ ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+ cmd);
state = state_error;
}
break;
case state_error:
default:
*hc_state = saved_state;
- return DRM_ERR(EINVAL);
+ return DRM_ERR(EINVAL);
}
- }
+ }
if (state == state_error) {
*hc_state = saved_state;
return DRM_ERR(EINVAL);
@@ -985,77 +1016,81 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t
return 0;
}
-int
-via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size)
+int
+via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+ unsigned int size)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
uint32_t cmd;
- const uint32_t *buf_end = buf + ( size >> 2 );
+ const uint32_t *buf_end = buf + (size >> 2);
verifier_state_t state = state_command;
int fire_count = 0;
-
+
while (buf < buf_end) {
switch (state) {
case state_header2:
- state = via_parse_header2( dev_priv, &buf, buf_end, &fire_count );
+ state =
+ via_parse_header2(dev_priv, &buf, buf_end,
+ &fire_count);
break;
case state_header1:
- state = via_parse_header1( dev_priv, &buf, buf_end );
+ state = via_parse_header1(dev_priv, &buf, buf_end);
break;
case state_vheader5:
- state = via_parse_vheader5( dev_priv, &buf, buf_end );
+ state = via_parse_vheader5(dev_priv, &buf, buf_end);
break;
case state_vheader6:
- state = via_parse_vheader6( dev_priv, &buf, buf_end );
+ state = via_parse_vheader6(dev_priv, &buf, buf_end);
break;
case state_command:
- if (HALCYON_HEADER2 == (cmd = *buf))
+ if (HALCYON_HEADER2 == (cmd = *buf))
state = state_header2;
- else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
state = state_header1;
else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
state = state_vheader5;
else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
state = state_vheader6;
else {
- DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
- cmd);
+ DRM_ERROR
+ ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+ cmd);
state = state_error;
}
break;
case state_error:
default:
- return DRM_ERR(EINVAL);
+ return DRM_ERR(EINVAL);
}
- }
+ }
if (state == state_error) {
return DRM_ERR(EINVAL);
}
return 0;
}
-
-
-static void
+static void
setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
{
int i;
- for(i=0; i<256; ++i) {
+ for (i = 0; i < 256; ++i) {
table[i] = forbidden_command;
}
- for(i=0; i<size; ++i) {
+ for (i = 0; i < size; ++i) {
table[init_table[i].code] = init_table[i].hz;
}
}
-void
-via_init_command_verifier( void )
+void via_init_command_verifier(void)
{
- setup_hazard_table(init_table1, table1, sizeof(init_table1) / sizeof(hz_init_t));
- setup_hazard_table(init_table2, table2, sizeof(init_table2) / sizeof(hz_init_t));
- setup_hazard_table(init_table3, table3, sizeof(init_table3) / sizeof(hz_init_t));
+ setup_hazard_table(init_table1, table1,
+ sizeof(init_table1) / sizeof(hz_init_t));
+ setup_hazard_table(init_table2, table2,
+ sizeof(init_table2) / sizeof(hz_init_t));
+ setup_hazard_table(init_table3, table3,
+ sizeof(init_table3) / sizeof(hz_init_t));
}
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index a8e13592620f..eb4eda344345 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -26,23 +26,21 @@
#ifndef _VIA_VERIFIER_H_
#define _VIA_VERIFIER_H_
-typedef enum{
- no_sequence = 0,
+typedef enum {
+ no_sequence = 0,
z_address,
dest_address,
tex_address
-}drm_via_sequence_t;
+} drm_via_sequence_t;
-
-
-typedef struct{
+typedef struct {
unsigned texture;
- uint32_t z_addr;
- uint32_t d_addr;
- uint32_t t_addr[2][10];
+ uint32_t z_addr;
+ uint32_t d_addr;
+ uint32_t t_addr[2][10];
uint32_t pitch[2][10];
uint32_t height[2][10];
- uint32_t tex_level_lo[2];
+ uint32_t tex_level_lo[2];
uint32_t tex_level_hi[2];
uint32_t tex_palette_size[2];
drm_via_sequence_t unfinished;
@@ -55,7 +53,7 @@ typedef struct{
const uint32_t *buf_start;
} drm_via_state_t;
-extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
- drm_device_t *dev, int agp);
+extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
+ drm_device_t * dev, int agp);
#endif
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
index 1e2d444587bf..7fab9fbdf424 100644
--- a/drivers/char/drm/via_video.c
+++ b/drivers/char/drm/via_video.c
@@ -29,8 +29,7 @@
#include "via_drm.h"
#include "via_drv.h"
-void
-via_init_futex(drm_via_private_t *dev_priv)
+void via_init_futex(drm_via_private_t * dev_priv)
{
unsigned int i;
@@ -42,30 +41,28 @@ via_init_futex(drm_via_private_t *dev_priv)
}
}
-void
-via_cleanup_futex(drm_via_private_t *dev_priv)
+void via_cleanup_futex(drm_via_private_t * dev_priv)
{
-}
+}
-void
-via_release_futex(drm_via_private_t *dev_priv, int context)
+void via_release_futex(drm_via_private_t * dev_priv, int context)
{
unsigned int i;
volatile int *lock;
- for (i=0; i < VIA_NR_XVMC_LOCKS; ++i) {
- lock = (int *) XVMCLOCKPTR(dev_priv->sarea_priv, i);
- if ( (_DRM_LOCKING_CONTEXT( *lock ) == context)) {
- if (_DRM_LOCK_IS_HELD( *lock ) && (*lock & _DRM_LOCK_CONT)) {
- DRM_WAKEUP( &(dev_priv->decoder_queue[i]));
+ for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+ lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+ if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
+ if (_DRM_LOCK_IS_HELD(*lock)
+ && (*lock & _DRM_LOCK_CONT)) {
+ DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
}
*lock = 0;
}
- }
-}
+ }
+}
-int
-via_decoder_futex(DRM_IOCTL_ARGS)
+int via_decoder_futex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_via_futex_t fx;
@@ -95,4 +92,3 @@ via_decoder_futex(DRM_IOCTL_ARGS)
}
return 0;
}
-
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 26271e3ca823..8693835cb2d5 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -515,7 +515,7 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+ class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 6025e1866c7e..b7a0e4d6b934 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -6,6 +6,8 @@
For technical support please email digiLinux@dgii.com or
call Digi tech support at (612) 912-3456
+ ** This driver is no longer supported by Digi **
+
Much of this design and code came from epca.c which was
copyright (C) 1994, 1995 Troy De Jongh, and subsquently
modified by David Nugent, Christoph Lameter, Mike McLagan.
@@ -43,31 +45,19 @@
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif /* CONFIG_PCI */
-
-#define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2)
-#define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2)
-
-#ifdef ENABLE_PCI
+#include <linux/spinlock.h>
#include <linux/pci.h>
#include "digiPCI.h"
-#endif /* ENABLE_PCI */
+
#include "digi1.h"
#include "digiFep1.h"
#include "epca.h"
#include "epcaconfig.h"
-#if BITS_PER_LONG != 32
-# error FIXME: this driver only works on 32-bit platforms
-#endif
-
/* ---------------------- Begin defines ------------------------ */
-#define VERSION "1.3.0.1-LK"
+#define VERSION "1.3.0.1-LK2.6"
/* This major needs to be submitted to Linux to join the majors list */
@@ -81,13 +71,17 @@
/* ----------------- Begin global definitions ------------------- */
-static char mesg[100];
static int nbdevs, num_cards, liloconfig;
static int digi_poller_inhibited = 1 ;
static int setup_error_code;
static int invalid_lilo_config;
+/* The ISA boards do window flipping into the same spaces so its only sane
+ with a single lock. It's still pretty efficient */
+
+static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED;
+
/* -----------------------------------------------------------------------
MAXBOARDS is typically 12, but ISA and EISA cards are restricted to
7 below.
@@ -129,58 +123,58 @@ static struct timer_list epca_timer;
configured.
----------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win);
-static inline void memwinoff(struct board_info *b, unsigned int win);
-static inline void globalwinon(struct channel *ch);
-static inline void rxwinon(struct channel *ch);
-static inline void txwinon(struct channel *ch);
-static inline void memoff(struct channel *ch);
-static inline void assertgwinon(struct channel *ch);
-static inline void assertmemoff(struct channel *ch);
+static void memwinon(struct board_info *b, unsigned int win);
+static void memwinoff(struct board_info *b, unsigned int win);
+static void globalwinon(struct channel *ch);
+static void rxwinon(struct channel *ch);
+static void txwinon(struct channel *ch);
+static void memoff(struct channel *ch);
+static void assertgwinon(struct channel *ch);
+static void assertmemoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for cx_like products --- */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxem_globalwinon(struct channel *ch);
-static inline void pcxem_rxwinon(struct channel *ch);
-static inline void pcxem_txwinon(struct channel *ch);
-static inline void pcxem_memoff(struct channel *ch);
+static void pcxem_memwinon(struct board_info *b, unsigned int win);
+static void pcxem_memwinoff(struct board_info *b, unsigned int win);
+static void pcxem_globalwinon(struct channel *ch);
+static void pcxem_rxwinon(struct channel *ch);
+static void pcxem_txwinon(struct channel *ch);
+static void pcxem_memoff(struct channel *ch);
/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxe_globalwinon(struct channel *ch);
-static inline void pcxe_rxwinon(struct channel *ch);
-static inline void pcxe_txwinon(struct channel *ch);
-static inline void pcxe_memoff(struct channel *ch);
+static void pcxe_memwinon(struct board_info *b, unsigned int win);
+static void pcxe_memwinoff(struct board_info *b, unsigned int win);
+static void pcxe_globalwinon(struct channel *ch);
+static void pcxe_rxwinon(struct channel *ch);
+static void pcxe_txwinon(struct channel *ch);
+static void pcxe_memoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
/* Note : pc64xe and pcxi share the same windowing routines */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxi_globalwinon(struct channel *ch);
-static inline void pcxi_rxwinon(struct channel *ch);
-static inline void pcxi_txwinon(struct channel *ch);
-static inline void pcxi_memoff(struct channel *ch);
+static void pcxi_memwinon(struct board_info *b, unsigned int win);
+static void pcxi_memwinoff(struct board_info *b, unsigned int win);
+static void pcxi_globalwinon(struct channel *ch);
+static void pcxi_rxwinon(struct channel *ch);
+static void pcxi_txwinon(struct channel *ch);
+static void pcxi_memoff(struct channel *ch);
/* - Begin 'specific' do nothing memory functions needed for some cards - */
-static inline void dummy_memwinon(struct board_info *b, unsigned int win);
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win);
-static inline void dummy_globalwinon(struct channel *ch);
-static inline void dummy_rxwinon(struct channel *ch);
-static inline void dummy_txwinon(struct channel *ch);
-static inline void dummy_memoff(struct channel *ch);
-static inline void dummy_assertgwinon(struct channel *ch);
-static inline void dummy_assertmemoff(struct channel *ch);
+static void dummy_memwinon(struct board_info *b, unsigned int win);
+static void dummy_memwinoff(struct board_info *b, unsigned int win);
+static void dummy_globalwinon(struct channel *ch);
+static void dummy_rxwinon(struct channel *ch);
+static void dummy_txwinon(struct channel *ch);
+static void dummy_memoff(struct channel *ch);
+static void dummy_assertgwinon(struct channel *ch);
+static void dummy_assertmemoff(struct channel *ch);
/* ------------------- Begin declare functions ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *);
-static inline void pc_sched_event(struct channel *, int);
+static struct channel *verifyChannel(struct tty_struct *);
+static void pc_sched_event(struct channel *, int);
static void epca_error(int, char *);
static void pc_close(struct tty_struct *, struct file *);
static void shutdown(struct channel *);
@@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty);
static void digi_send_break(struct channel *ch, int msec);
static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
void epca_setup(char *, int *);
-void console_print(const char *);
static int get_termio(struct tty_struct *, struct termio __user *);
static int pc_write(struct tty_struct *, const unsigned char *, int);
-int pc_init(void);
-
-#ifdef ENABLE_PCI
+static int pc_init(void);
static int init_PCI(void);
-#endif /* ENABLE_PCI */
/* ------------------------------------------------------------------
@@ -237,41 +227,41 @@ static int init_PCI(void);
making direct calls deserves what they get.
-------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win)
+static void memwinon(struct board_info *b, unsigned int win)
{
(b->memwinon)(b, win);
}
-static inline void memwinoff(struct board_info *b, unsigned int win)
+static void memwinoff(struct board_info *b, unsigned int win)
{
(b->memwinoff)(b, win);
}
-static inline void globalwinon(struct channel *ch)
+static void globalwinon(struct channel *ch)
{
(ch->board->globalwinon)(ch);
}
-static inline void rxwinon(struct channel *ch)
+static void rxwinon(struct channel *ch)
{
(ch->board->rxwinon)(ch);
}
-static inline void txwinon(struct channel *ch)
+static void txwinon(struct channel *ch)
{
(ch->board->txwinon)(ch);
}
-static inline void memoff(struct channel *ch)
+static void memoff(struct channel *ch)
{
(ch->board->memoff)(ch);
}
-static inline void assertgwinon(struct channel *ch)
+static void assertgwinon(struct channel *ch)
{
(ch->board->assertgwinon)(ch);
}
-static inline void assertmemoff(struct channel *ch)
+static void assertmemoff(struct channel *ch)
{
(ch->board->assertmemoff)(ch);
}
@@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch)
and CX series cards.
------------------------------------------------------------ */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win)
+static void pcxem_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN|win, (int)b->port + 1);
+ outb_p(FEPWIN|win, b->port + 1);
}
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win)
+static void pcxem_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(0, (int)b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxem_globalwinon(struct channel *ch)
+static void pcxem_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxem_rxwinon(struct channel *ch)
+static void pcxem_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxem_txwinon(struct channel *ch)
+static void pcxem_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxem_memoff(struct channel *ch)
+static void pcxem_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port + 1);
}
/* ----------------- Begin pcxe memory window stuff ------------------ */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win)
+static void pcxe_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN | win, (int)b->port + 1);
+ outb_p(FEPWIN | win, b->port + 1);
}
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win)
+static void pcxe_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM,
- (int)b->port + 1);
- outb_p(0, (int)b->port + 1);
+ outb_p(inb(b->port) & ~FEPMEM,
+ b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxe_globalwinon(struct channel *ch)
+static void pcxe_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxe_rxwinon(struct channel *ch)
+static void pcxe_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxe_txwinon(struct channel *ch)
+static void pcxe_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxe_memoff(struct channel *ch)
+static void pcxe_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port);
outb_p(0, (int)ch->board->port + 1);
@@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch)
/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win)
+static void pcxi_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) | FEPMEM, (int)b->port);
+ outb_p(inb(b->port) | FEPMEM, b->port);
}
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win)
+static void pcxi_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port);
+ outb_p(inb(b->port) & ~FEPMEM, b->port);
}
-static inline void pcxi_globalwinon(struct channel *ch)
+static void pcxi_globalwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_rxwinon(struct channel *ch)
+static void pcxi_rxwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_txwinon(struct channel *ch)
+static void pcxi_txwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_memoff(struct channel *ch)
+static void pcxi_memoff(struct channel *ch)
{
- outb_p(0, (int)ch->board->port);
+ outb_p(0, ch->board->port);
}
-static inline void pcxi_assertgwinon(struct channel *ch)
+static void pcxi_assertgwinon(struct channel *ch)
{
- epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off");
+ epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
}
-static inline void pcxi_assertmemoff(struct channel *ch)
+static void pcxi_assertmemoff(struct channel *ch)
{
- epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on");
+ epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
}
@@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch)
may or may not do anything.
---------------------------------------------------------------------------*/
-static inline void dummy_memwinon(struct board_info *b, unsigned int win)
+static void dummy_memwinon(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win)
+static void dummy_memwinoff(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_globalwinon(struct channel *ch)
+static void dummy_globalwinon(struct channel *ch)
{
}
-static inline void dummy_rxwinon(struct channel *ch)
+static void dummy_rxwinon(struct channel *ch)
{
}
-static inline void dummy_txwinon(struct channel *ch)
+static void dummy_txwinon(struct channel *ch)
{
}
-static inline void dummy_memoff(struct channel *ch)
+static void dummy_memoff(struct channel *ch)
{
}
-static inline void dummy_assertgwinon(struct channel *ch)
+static void dummy_assertgwinon(struct channel *ch)
{
}
-static inline void dummy_assertmemoff(struct channel *ch)
+static void dummy_assertmemoff(struct channel *ch)
{
}
/* ----------------- Begin verifyChannel function ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *tty)
+static struct channel *verifyChannel(struct tty_struct *tty)
{ /* Begin verifyChannel */
-
/* --------------------------------------------------------------------
This routine basically provides a sanity check. It insures that
the channel returned is within the proper range of addresses as
well as properly initialized. If some bogus info gets passed in
through tty->driver_data this should catch it.
- --------------------------------------------------------------------- */
-
- if (tty)
- { /* Begin if tty */
-
- register struct channel *ch = (struct channel *)tty->driver_data;
-
- if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs]))
- {
+ --------------------------------------------------------------------- */
+ if (tty) {
+ struct channel *ch = (struct channel *)tty->driver_data;
+ if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
if (ch->magic == EPCA_MAGIC)
return ch;
}
-
- } /* End if tty */
-
- /* Else return a NULL for invalid */
+ }
return NULL;
} /* End verifyChannel */
/* ------------------ Begin pc_sched_event ------------------------- */
-static inline void pc_sched_event(struct channel *ch, int event)
-{ /* Begin pc_sched_event */
-
-
+static void pc_sched_event(struct channel *ch, int event)
+{
/* ----------------------------------------------------------------------
We call this to schedule interrupt processing on some event. The
kernel sees our request and calls the related routine in OUR driver.
-------------------------------------------------------------------------*/
-
ch->event |= 1 << event;
schedule_work(&ch->tqueue);
-
-
} /* End pc_sched_event */
/* ------------------ Begin epca_error ------------------------- */
static void epca_error(int line, char *msg)
-{ /* Begin epca_error */
-
+{
printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
- return;
-
-} /* End epca_error */
+}
/* ------------------ Begin pc_close ------------------------- */
static void pc_close(struct tty_struct * tty, struct file * filp)
-{ /* Begin pc_close */
-
+{
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
- save_flags(flags);
- cli();
-
- if (tty_hung_up_p(filp))
- {
- restore_flags(flags);
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
+ spin_lock_irqsave(&epca_lock, flags);
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
}
-
/* Check to see if the channel is open more than once */
- if (ch->count-- > 1)
- { /* Begin channel is open more than once */
-
+ if (ch->count-- > 1) {
+ /* Begin channel is open more than once */
/* -------------------------------------------------------------
Return without doing anything. Someone might still be using
the channel.
---------------------------------------------------------------- */
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
} /* End channel is open more than once */
/* Port open only once go ahead with shutdown & reset */
-
- if (ch->count < 0)
- {
- ch->count = 0;
- }
+ if (ch->count < 0)
+ BUG();
/* ---------------------------------------------------------------
Let the rest of the driver know the channel is being closed.
This becomes important if an open is attempted before close
is finished.
------------------------------------------------------------------ */
-
ch->asyncflags |= ASYNC_CLOSING;
-
tty->closing = 1;
- if (ch->asyncflags & ASYNC_INITIALIZED)
- {
+ spin_unlock_irqrestore(&epca_lock, flags);
+
+ if (ch->asyncflags & ASYNC_INITIALIZED) {
/* Setup an event to indicate when the transmit buffer empties */
setup_empty_event(tty, ch);
tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
}
-
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+
+ spin_lock_irqsave(&epca_lock, flags);
tty->closing = 0;
ch->event = 0;
ch->tty = NULL;
+ spin_unlock_irqrestore(&epca_lock, flags);
- if (ch->blocked_open)
- { /* Begin if blocked_open */
-
+ if (ch->blocked_open) { /* Begin if blocked_open */
if (ch->close_delay)
- {
msleep_interruptible(jiffies_to_msecs(ch->close_delay));
- }
-
wake_up_interruptible(&ch->open_wait);
-
} /* End if blocked_open */
-
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
ASYNC_CLOSING);
wake_up_interruptible(&ch->close_wait);
-
-
- restore_flags(flags);
-
} /* End if ch != NULL */
-
} /* End pc_close */
/* ------------------ Begin shutdown ------------------------- */
@@ -586,15 +534,14 @@ static void shutdown(struct channel *ch)
unsigned long flags;
struct tty_struct *tty;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
- save_flags(flags);
- cli();
- globalwinon(ch);
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
bc = ch->brdchan;
/* ------------------------------------------------------------------
@@ -604,20 +551,17 @@ static void shutdown(struct channel *ch)
--------------------------------------------------------------------- */
if (bc)
- bc->idata = 0;
-
+ writeb(0, &bc->idata);
tty = ch->tty;
/* ----------------------------------------------------------------
If we're a modem control device and HUPCL is on, drop RTS & DTR.
------------------------------------------------------------------ */
- if (tty->termios->c_cflag & HUPCL)
- {
+ if (tty->termios->c_cflag & HUPCL) {
ch->omodem &= ~(ch->m_rts | ch->m_dtr);
fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
}
-
memoff(ch);
/* ------------------------------------------------------------------
@@ -628,7 +572,7 @@ static void shutdown(struct channel *ch)
/* Prevent future Digi programmed interrupts from coming active */
ch->asyncflags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End shutdown */
@@ -636,7 +580,6 @@ static void shutdown(struct channel *ch)
static void pc_hangup(struct tty_struct *tty)
{ /* Begin pc_hangup */
-
struct channel *ch;
/* ---------------------------------------------------------
@@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
unsigned long flags;
- save_flags(flags);
- cli();
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+ spin_lock_irqsave(&epca_lock, flags);
ch->tty = NULL;
ch->event = 0;
ch->count = 0;
- restore_flags(flags);
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&ch->open_wait);
-
} /* End if ch != NULL */
} /* End pc_hangup */
@@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty)
static int pc_write(struct tty_struct * tty,
const unsigned char *buf, int bytesAvailable)
{ /* Begin pc_write */
-
- register unsigned int head, tail;
- register int dataLen;
- register int size;
- register int amountCopied;
-
-
+ unsigned int head, tail;
+ int dataLen;
+ int size;
+ int amountCopied;
struct channel *ch;
unsigned long flags;
int remain;
- volatile struct board_chan *bc;
-
+ struct board_chan __iomem *bc;
/* ----------------------------------------------------------------
pc_write is primarily called directly by the kernel routine
@@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty,
bc = ch->brdchan;
size = ch->txbufsize;
-
amountCopied = 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- head = bc->tin & (size - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (size - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
tail &= (size - 1);
/* If head >= tail, head has not wrapped around. */
- if (head >= tail)
- { /* Begin head has not wrapped */
-
+ if (head >= tail) { /* Begin head has not wrapped */
/* ---------------------------------------------------------------
remain (much like dataLen above) represents the total amount of
space available on the card for data. Here dataLen represents
@@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty,
buffer. This is important because a memcpy cannot be told to
automatically wrap around when it hits the buffer end.
------------------------------------------------------------------ */
-
dataLen = size - head;
remain = size - (head - tail) - 1;
-
- } /* End head has not wrapped */
- else
- { /* Begin head has wrapped around */
+ } else { /* Begin head has wrapped around */
remain = tail - head - 1;
dataLen = remain;
} /* End head has wrapped around */
-
/* -------------------------------------------------------------------
Check the space on the card. If we have more data than
space; reduce the amount of data to fit the space.
---------------------------------------------------------------------- */
-
bytesAvailable = min(remain, bytesAvailable);
-
txwinon(ch);
while (bytesAvailable > 0)
{ /* Begin while there is data to copy onto card */
@@ -761,32 +685,27 @@ static int pc_write(struct tty_struct * tty,
------------------------------------------------------------------- */
dataLen = min(bytesAvailable, dataLen);
- memcpy(ch->txptr + head, buf, dataLen);
+ memcpy_toio(ch->txptr + head, buf, dataLen);
buf += dataLen;
head += dataLen;
amountCopied += dataLen;
bytesAvailable -= dataLen;
- if (head >= size)
- {
+ if (head >= size) {
head = 0;
dataLen = tail;
}
-
} /* End while there is data to copy onto card */
-
ch->statusflags |= TXBUSY;
globalwinon(ch);
- bc->tin = head;
+ writew(head, &bc->tin);
- if ((ch->statusflags & LOWWAIT) == 0)
- {
+ if ((ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
return(amountCopied);
} /* End pc_write */
@@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty,
static void pc_put_char(struct tty_struct *tty, unsigned char c)
{ /* Begin pc_put_char */
-
-
pc_write(tty, &c, 1);
- return;
-
} /* End pc_put_char */
/* ------------------ Begin pc_write_room ------------------------- */
@@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
unsigned int head, tail;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
remain = 0;
@@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- {
- save_flags(flags);
- cli();
+ if ((ch = verifyChannel(tty)) != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- head = bc->tin & (ch->txbufsize - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
/* Wrap tail if necessary */
tail &= (ch->txbufsize - 1);
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
- if (remain && (ch->statusflags & LOWWAIT) == 0)
- {
+ if (remain && (ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
/* Return how much room is left on card */
return remain;
@@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
int remain;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
@@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
if ((ch = verifyChannel(tty)) == NULL)
return(0);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- tail = bc->tout;
- head = bc->tin;
- ctail = ch->mailbox->cout;
+ tail = readw(&bc->tout);
+ head = readw(&bc->tin);
+ ctail = readw(&ch->mailbox->cout);
- if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
+ if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
chars = 0;
- else
- { /* Begin if some space on the card has been used */
-
- head = bc->tin & (ch->txbufsize - 1);
+ else { /* Begin if some space on the card has been used */
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
tail &= (ch->txbufsize - 1);
-
/* --------------------------------------------------------------
The logic here is basically opposite of the above pc_write_room
here we are finding the amount of bytes in the buffer filled.
Not the amount of bytes empty.
------------------------------------------------------------------- */
-
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
-
chars = (int)(ch->txbufsize - remain);
-
/* -------------------------------------------------------------
Make it possible to wakeup anything waiting for output
in tty_ioctl.c, etc.
@@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
If not already set. Setup an event to indicate when the
transmit buffer empties
----------------------------------------------------------------- */
-
if (!(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
} /* End if some space on the card has been used */
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
/* Return number of characters residing on card. */
return(chars);
@@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty)
unsigned int tail;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
-
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
if ((ch = verifyChannel(tty)) == NULL)
return;
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
-
bc = ch->brdchan;
- tail = bc->tout;
-
+ tail = readw(&bc->tout);
/* Have FEP move tout pointer; effectively flushing transmit buffer */
-
fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
-
} /* End pc_flush_buffer */
/* ------------------ Begin pc_flush_chars ---------------------- */
static void pc_flush_chars(struct tty_struct *tty)
{ /* Begin pc_flush_chars */
-
struct channel * ch;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- {
+ if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
-
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* ----------------------------------------------------------------
If not already set and the transmitter is busy setup an event
to indicate when the transmit empties.
------------------------------------------------------------------- */
-
if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
} /* End pc_flush_chars */
/* ------------------ Begin block_til_ready ---------------------- */
@@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty)
static int block_til_ready(struct tty_struct *tty,
struct file *filp, struct channel *ch)
{ /* Begin block_til_ready */
-
DECLARE_WAITQUEUE(wait,current);
int retval, do_clocal = 0;
unsigned long flags;
-
- if (tty_hung_up_p(filp))
- {
+ if (tty_hung_up_p(filp)) {
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
@@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty,
If the device is in the middle of being closed, then block
until it's done, and then try again.
-------------------------------------------------------------------- */
- if (ch->asyncflags & ASYNC_CLOSING)
- {
+ if (ch->asyncflags & ASYNC_CLOSING) {
interruptible_sleep_on(&ch->close_wait);
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
@@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty,
return -ERESTARTSYS;
}
- if (filp->f_flags & O_NONBLOCK)
- {
+ if (filp->f_flags & O_NONBLOCK) {
/* -----------------------------------------------------------------
If non-blocking mode is set, then make the check up front
and then exit.
-------------------------------------------------------------------- */
-
ch->asyncflags |= 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 */
+ /* Block waiting for the carrier detect and the line to become free */
retval = 0;
add_wait_queue(&ch->open_wait, &wait);
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* We dec count so that pc_close will know when to free things */
if (!tty_hung_up_p(filp))
ch->count--;
-
- restore_flags(flags);
-
ch->blocked_open++;
-
while(1)
{ /* Begin forever while */
-
set_current_state(TASK_INTERRUPTIBLE);
-
if (tty_hung_up_p(filp) ||
!(ch->asyncflags & ASYNC_INITIALIZED))
{
@@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty,
retval = -ERESTARTSYS;
break;
}
-
if (!(ch->asyncflags & ASYNC_CLOSING) &&
(do_clocal || (ch->imodem & ch->dcd)))
break;
-
- if (signal_pending(current))
- {
+ if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
-
+ spin_unlock_irqrestore(&epca_lock, flags);
/* ---------------------------------------------------------------
Allow someone else to be scheduled. We will occasionally go
through this loop until one of the above conditions change.
@@ -1091,25 +949,23 @@ static int block_til_ready(struct tty_struct *tty,
prevent this loop from hogging the cpu.
------------------------------------------------------------------ */
schedule();
+ spin_lock_irqsave(&epca_lock, flags);
} /* End forever while */
current->state = TASK_RUNNING;
remove_wait_queue(&ch->open_wait, &wait);
- cli();
if (!tty_hung_up_p(filp))
ch->count++;
- restore_flags(flags);
-
ch->blocked_open--;
+ spin_unlock_irqrestore(&epca_lock, flags);
+
if (retval)
return retval;
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
return 0;
-
} /* End block_til_ready */
/* ------------------ Begin pc_open ---------------------- */
@@ -1120,17 +976,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
struct channel *ch;
unsigned long flags;
int line, retval, boardnum;
- volatile struct board_chan *bc;
- volatile unsigned int head;
+ struct board_chan __iomem *bc;
+ unsigned int head;
line = tty->index;
- if (line < 0 || line >= nbdevs)
- {
- printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n");
- tty->driver_data = NULL;
- return(-ENODEV);
- }
-
+ if (line < 0 || line >= nbdevs)
+ return -ENODEV;
ch = &digi_channels[line];
boardnum = ch->boardnum;
@@ -1143,78 +994,61 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
goes here.
---------------------------------------------------------------------- */
- if (invalid_lilo_config)
- {
+ if (invalid_lilo_config) {
if (setup_error_code & INVALID_BOARD_TYPE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board type specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
if (setup_error_code & INVALID_NUM_PORTS)
- printk(KERN_ERR "<Error> - pc_open: Invalid number of ports specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
if (setup_error_code & INVALID_MEM_BASE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board memory address specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
if (setup_error_code & INVALID_PORT_BASE)
- printk(KERN_ERR "<Error> - pc_open: Invalid board port address specified in LILO command\n");
-
+ printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
if (setup_error_code & INVALID_BOARD_STATUS)
- printk(KERN_ERR "<Error> - pc_open: Invalid board status specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
if (setup_error_code & INVALID_ALTPIN)
- printk(KERN_ERR "<Error> - pc_open: Invalid board altpin specified in LILO command\n");
-
+ printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
tty->driver_data = NULL; /* Mark this device as 'down' */
- return(-ENODEV);
+ return -ENODEV;
}
-
- if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED))
- {
+ if (boardnum >= num_cards || boards[boardnum].status == DISABLED) {
tty->driver_data = NULL; /* Mark this device as 'down' */
return(-ENODEV);
}
- if (( bc = ch->brdchan) == 0)
- {
+ if ((bc = ch->brdchan) == 0) {
tty->driver_data = NULL;
- return(-ENODEV);
+ return -ENODEV;
}
+ spin_lock_irqsave(&epca_lock, flags);
/* ------------------------------------------------------------------
Every time a channel is opened, increment a counter. This is
necessary because we do not wish to flush and shutdown the channel
until the last app holding the channel open, closes it.
--------------------------------------------------------------------- */
-
ch->count++;
-
/* ----------------------------------------------------------------
Set a kernel structures pointer to our local channel
structure. This way we can get to it when passed only
a tty struct.
------------------------------------------------------------------ */
-
tty->driver_data = ch;
-
/* ----------------------------------------------------------------
If this is the first time the channel has been opened, initialize
the tty->termios struct otherwise let pc_close handle it.
-------------------------------------------------------------------- */
-
- save_flags(flags);
- cli();
-
globalwinon(ch);
ch->statusflags = 0;
/* Save boards current modem status */
- ch->imodem = bc->mstat;
+ ch->imodem = readb(&bc->mstat);
/* ----------------------------------------------------------------
Set receive head and tail ptrs to each other. This indicates
no data available to read.
----------------------------------------------------------------- */
- head = bc->rin;
- bc->rout = head;
+ head = readw(&bc->rin);
+ writew(head, &bc->rout);
/* Set the channels associated tty structure */
ch->tty = tty;
@@ -1224,122 +1058,74 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
issues, etc.... It effect both control flags and input flags.
-------------------------------------------------------------------- */
epcaparam(tty,ch);
-
ch->asyncflags |= ASYNC_INITIALIZED;
memoff(ch);
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
retval = block_til_ready(tty, filp, ch);
if (retval)
- {
return retval;
- }
-
/* -------------------------------------------------------------
Set this again in case a hangup set it to zero while this
open() was waiting for the line...
--------------------------------------------------------------- */
+ spin_lock_irqsave(&epca_lock, flags);
ch->tty = tty;
-
- save_flags(flags);
- cli();
globalwinon(ch);
-
/* Enable Digi Data events */
- bc->idata = 1;
-
+ writeb(1, &bc->idata);
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
return 0;
-
} /* End pc_open */
-#ifdef MODULE
static int __init epca_module_init(void)
{ /* Begin init_module */
-
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- pc_init();
-
- restore_flags(flags);
-
- return(0);
+ return pc_init();
}
module_init(epca_module_init);
-#endif
-#ifdef ENABLE_PCI
static struct pci_driver epca_driver;
-#endif
-
-#ifdef MODULE
-/* -------------------- Begin cleanup_module ---------------------- */
static void __exit epca_module_exit(void)
{
-
int count, crd;
struct board_info *bd;
struct channel *ch;
- unsigned long flags;
del_timer_sync(&epca_timer);
- save_flags(flags);
- cli();
-
if ((tty_unregister_driver(pc_driver)) ||
(tty_unregister_driver(pc_info)))
{
- printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
- restore_flags(flags);
+ printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
return;
}
put_tty_driver(pc_driver);
put_tty_driver(pc_info);
- for (crd = 0; crd < num_cards; crd++)
- { /* Begin for each card */
-
+ for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */
bd = &boards[crd];
-
if (!bd)
{ /* Begin sanity check */
printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
return;
} /* End sanity check */
-
- ch = card_ptr[crd];
-
+ ch = card_ptr[crd];
for (count = 0; count < bd->numports; count++, ch++)
{ /* Begin for each port */
-
- if (ch)
- {
+ if (ch) {
if (ch->tty)
tty_hangup(ch->tty);
kfree(ch->tmp_buf);
}
-
} /* End for each port */
} /* End for each card */
-
-#ifdef ENABLE_PCI
pci_unregister_driver (&epca_driver);
-#endif
-
- restore_flags(flags);
-
}
+
module_exit(epca_module_exit);
-#endif /* MODULE */
static struct tty_operations pc_ops = {
.open = pc_open,
@@ -1371,34 +1157,15 @@ static struct tty_operations info_ops = {
/* ------------------ Begin pc_init ---------------------- */
-int __init pc_init(void)
+static int __init pc_init(void)
{ /* Begin pc_init */
-
- /* ----------------------------------------------------------------
- pc_init is called by the operating system during boot up prior to
- any open calls being made. In the older versions of Linux (Prior
- to 2.0.0) an entry is made into tty_io.c. A pointer to the last
- memory location (from kernel space) used (kmem_start) is passed
- to pc_init. It is pc_inits responsibility to modify this value
- for any memory that the Digi driver might need and then return
- this value to the operating system. For example if the driver
- wishes to allocate 1K of kernel memory, pc_init would return
- (kmem_start + 1024). This memory (Between kmem_start and kmem_start
- + 1024) would then be available for use exclusively by the driver.
- In this case our driver does not allocate any of this kernel
- memory.
- ------------------------------------------------------------------*/
-
- ulong flags;
int crd;
struct board_info *bd;
unsigned char board_id = 0;
-#ifdef ENABLE_PCI
int pci_boards_found, pci_count;
pci_count = 0;
-#endif /* ENABLE_PCI */
pc_driver = alloc_tty_driver(MAX_ALLOC);
if (!pc_driver)
@@ -1416,8 +1183,7 @@ int __init pc_init(void)
Note : If LILO has ran epca_setup then epca_setup will handle defining
num_cards as well as copying the data into the board structure.
-------------------------------------------------------------------------- */
- if (!liloconfig)
- { /* Begin driver has been configured via. epcaconfig */
+ if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */
nbdevs = NBDEVS;
num_cards = NUMCARDS;
@@ -1440,8 +1206,6 @@ int __init pc_init(void)
printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
-#ifdef ENABLE_PCI
-
/* ------------------------------------------------------------------
NOTE : This code assumes that the number of ports found in
the boards array is correct. This could be wrong if
@@ -1467,8 +1231,6 @@ int __init pc_init(void)
pci_boards_found += init_PCI();
num_cards += pci_boards_found;
-#endif /* ENABLE_PCI */
-
pc_driver->owner = THIS_MODULE;
pc_driver->name = "ttyD";
pc_driver->devfs_name = "tts/D";
@@ -1499,9 +1261,6 @@ int __init pc_init(void)
tty_set_operations(pc_info, &info_ops);
- save_flags(flags);
- cli();
-
for (crd = 0; crd < num_cards; crd++)
{ /* Begin for each card */
@@ -1610,11 +1369,7 @@ int __init pc_init(void)
if ((board_id & 0x30) == 0x30)
bd->memory_seg = 0x8000;
- } /* End it is an XI card */
- else
- {
- printk(KERN_ERR "<Error> - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
- }
+ } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
break;
} /* End switch on bd->type */
@@ -1634,9 +1389,6 @@ int __init pc_init(void)
init_timer(&epca_timer);
epca_timer.function = epcapoll;
mod_timer(&epca_timer, jiffies + HZ/25);
-
- restore_flags(flags);
-
return 0;
} /* End pc_init */
@@ -1647,10 +1399,10 @@ static void post_fep_init(unsigned int crd)
{ /* Begin post_fep_init */
int i;
- unchar *memaddr;
- volatile struct global_data *gd;
+ void __iomem *memaddr;
+ struct global_data __iomem *gd;
struct board_info *bd;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch;
int shrinkmem = 0, lowwater ;
@@ -1669,9 +1421,7 @@ static void post_fep_init(unsigned int crd)
after DIGI_INIT has been called will return the proper values.
------------------------------------------------------------------- */
- if (bd->type >= PCIXEM) /* If the board in question is PCI */
- { /* Begin get PCI number of ports */
-
+ if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
/* --------------------------------------------------------------------
Below we use XEMPORTS as a memory offset regardless of which PCI
card it is. This is because all of the supported PCI cards have
@@ -1685,15 +1435,15 @@ static void post_fep_init(unsigned int crd)
(FYI - The id should be located at 0x1ac (And may use up to 4 bytes
if the box in question is a XEM or CX)).
------------------------------------------------------------------------ */
-
- bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long)
- (bd->re_map_membase + XEMPORTS));
-
-
+ /* PCI cards are already remapped at this point ISA are not */
+ bd->numports = readw(bd->re_map_membase + XEMPORTS);
epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
nbdevs += (bd->numports);
-
- } /* End get PCI number of ports */
+ } else {
+ /* Fix up the mappings for ISA/EISA etc */
+ /* FIXME: 64K - can we be smarter ? */
+ bd->re_map_membase = ioremap(bd->membase, 0x10000);
+ }
if (crd != 0)
card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
@@ -1701,19 +1451,9 @@ static void post_fep_init(unsigned int crd)
card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
ch = card_ptr[crd];
-
-
epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
- memaddr = (unchar *)bd->re_map_membase;
-
- /*
- The below command is necessary because newer kernels (2.1.x and
- up) do not have a 1:1 virtual to physical mapping. The below
- call adjust for that.
- */
-
- memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
+ memaddr = bd->re_map_membase;
/* -----------------------------------------------------------------
The below assignment will set bc to point at the BEGINING of
@@ -1721,7 +1461,7 @@ static void post_fep_init(unsigned int crd)
8 and 64 of these structures.
-------------------------------------------------------------------- */
- bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
+ bc = memaddr + CHANSTRUCT;
/* -------------------------------------------------------------------
The below assignment will set gd to point at the BEGINING of
@@ -1730,20 +1470,18 @@ static void post_fep_init(unsigned int crd)
pointer begins at 0xd10.
---------------------------------------------------------------------- */
- gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
+ gd = memaddr + GLOBAL;
/* --------------------------------------------------------------------
XEPORTS (address 0xc22) points at the number of channels the
card supports. (For 64XE, XI, XEM, and XR use 0xc02)
----------------------------------------------------------------------- */
- if (((bd->type == PCXEVE) | (bd->type == PCXE)) &&
- (*(ushort *)((ulong)memaddr + XEPORTS) < 3))
+ if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
shrinkmem = 1;
if (bd->type < PCIXEM)
if (!request_region((int)bd->port, 4, board_desc[bd->type]))
return;
-
memwinon(bd, 0);
/* --------------------------------------------------------------------
@@ -1753,17 +1491,17 @@ static void post_fep_init(unsigned int crd)
/* For every port on the card do ..... */
- for (i = 0; i < bd->numports; i++, ch++, bc++)
- { /* Begin for each port */
+ for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */
+ unsigned long flags;
+ u16 tseg, rseg;
ch->brdchan = bc;
ch->mailbox = gd;
INIT_WORK(&ch->tqueue, do_softint, ch);
ch->board = &boards[crd];
- switch (bd->type)
- { /* Begin switch bd->type */
-
+ spin_lock_irqsave(&epca_lock, flags);
+ switch (bd->type) {
/* ----------------------------------------------------------------
Since some of the boards use different bitmaps for their
control signals we cannot hard code these values and retain
@@ -1796,14 +1534,12 @@ static void post_fep_init(unsigned int crd)
} /* End switch bd->type */
- if (boards[crd].altpin)
- {
+ if (boards[crd].altpin) {
ch->dsr = ch->m_dcd;
ch->dcd = ch->m_dsr;
ch->digiext.digi_flags |= DIGI_ALTPIN;
}
- else
- {
+ else {
ch->dcd = ch->m_dcd;
ch->dsr = ch->m_dsr;
}
@@ -1813,57 +1549,58 @@ static void post_fep_init(unsigned int crd)
ch->magic = EPCA_MAGIC;
ch->tty = NULL;
- if (shrinkmem)
- {
+ if (shrinkmem) {
fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
shrinkmem = 0;
}
- switch (bd->type)
- { /* Begin switch bd->type */
+ tseg = readw(&bc->tseg);
+ rseg = readw(&bc->rseg);
+
+ switch (bd->type) {
case PCIXEM:
case PCIXRJ:
case PCIXR:
/* Cover all the 2MEG cards */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEM:
case EISAXEM:
/* Cover all the 32K windowed cards */
/* Mask equal to window size - 1 */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEVE:
case PCXE:
- ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff);
- ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9);
- ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff);
- ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 );
+ ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+ ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
break;
case PCXI:
case PC64XE:
- ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4);
- ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4);
+ ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+ ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
ch->txwin = ch->rxwin = 0;
break;
} /* End switch bd->type */
ch->txbufhead = 0;
- ch->txbufsize = bc->tmax + 1;
+ ch->txbufsize = readw(&bc->tmax) + 1;
ch->rxbufhead = 0;
- ch->rxbufsize = bc->rmax + 1;
+ ch->rxbufsize = readw(&bc->rmax) + 1;
lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
@@ -1878,13 +1615,13 @@ static void post_fep_init(unsigned int crd)
fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
- bc->edelay = 100;
- bc->idata = 1;
+ writew(100, &bc->edelay);
+ writeb(1, &bc->idata);
- ch->startc = bc->startc;
- ch->stopc = bc->stopc;
- ch->startca = bc->startca;
- ch->stopca = bc->stopca;
+ ch->startc = readb(&bc->startc);
+ ch->stopc = readb(&bc->stopc);
+ ch->startca = readb(&bc->startca);
+ ch->stopca = readb(&bc->stopca);
ch->fepcflag = 0;
ch->fepiflag = 0;
@@ -1899,27 +1636,23 @@ static void post_fep_init(unsigned int crd)
ch->blocked_open = 0;
init_waitqueue_head(&ch->open_wait);
init_waitqueue_head(&ch->close_wait);
+
+ spin_unlock_irqrestore(&epca_lock, flags);
+
ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
- if (!(ch->tmp_buf))
- {
+ if (!ch->tmp_buf) {
printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i);
release_region((int)bd->port, 4);
while(i-- > 0)
kfree((ch--)->tmp_buf);
return;
- }
- else
+ } else
memset((void *)ch->tmp_buf,0,ch->txbufsize);
} /* End for each port */
printk(KERN_INFO
"Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
- sprintf(mesg,
- "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
- VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
- console_print(mesg);
-
memwinoff(bd, 0);
} /* End post_fep_init */
@@ -1943,9 +1676,6 @@ static void epcapoll(unsigned long ignored)
buffer empty) and acts on those events.
----------------------------------------------------------------------- */
- save_flags(flags);
- cli();
-
for (crd = 0; crd < num_cards; crd++)
{ /* Begin for each card */
@@ -1961,6 +1691,8 @@ static void epcapoll(unsigned long ignored)
some legacy boards.
---------------------------------------------------------------- */
+ spin_lock_irqsave(&epca_lock, flags);
+
assertmemoff(ch);
globalwinon(ch);
@@ -1970,21 +1702,19 @@ static void epcapoll(unsigned long ignored)
the transmit or receive queue.
------------------------------------------------------------------- */
- head = ch->mailbox->ein;
- tail = ch->mailbox->eout;
+ head = readw(&ch->mailbox->ein);
+ tail = readw(&ch->mailbox->eout);
/* If head isn't equal to tail we have an event */
if (head != tail)
doevent(crd);
-
memoff(ch);
- } /* End for each card */
+ spin_unlock_irqrestore(&epca_lock, flags);
+ } /* End for each card */
mod_timer(&epca_timer, jiffies + (HZ / 25));
-
- restore_flags(flags);
} /* End epcapoll */
/* --------------------- Begin doevent ------------------------ */
@@ -1992,53 +1722,42 @@ static void epcapoll(unsigned long ignored)
static void doevent(int crd)
{ /* Begin doevent */
- volatile unchar *eventbuf;
+ void __iomem *eventbuf;
struct channel *ch, *chan0;
static struct tty_struct *tty;
- volatile struct board_info *bd;
- volatile struct board_chan *bc;
- register volatile unsigned int tail, head;
- register int event, channel;
- register int mstat, lstat;
+ struct board_info *bd;
+ struct board_chan __iomem *bc;
+ unsigned int tail, head;
+ int event, channel;
+ int mstat, lstat;
/* -------------------------------------------------------------------
This subroutine is called by epcapoll when an event is detected
in the event queue. This routine responds to those events.
--------------------------------------------------------------------- */
-
bd = &boards[crd];
chan0 = card_ptr[crd];
epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-
assertgwinon(chan0);
-
- while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein))
+ while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein)))
{ /* Begin while something in event queue */
-
assertgwinon(chan0);
-
- eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART));
-
+ eventbuf = bd->re_map_membase + tail + ISTART;
/* Get the channel the event occurred on */
- channel = eventbuf[0];
-
+ channel = readb(eventbuf);
/* Get the actual event code that occurred */
- event = eventbuf[1];
-
+ event = readb(eventbuf + 1);
/* ----------------------------------------------------------------
The two assignments below get the current modem status (mstat)
and the previous modem status (lstat). These are useful becuase
an event could signal a change in modem signals itself.
------------------------------------------------------------------- */
-
- mstat = eventbuf[2];
- lstat = eventbuf[3];
+ mstat = readb(eventbuf + 2);
+ lstat = readb(eventbuf + 3);
ch = chan0 + channel;
-
- if ((unsigned)channel >= bd->numports || !ch)
- {
+ if ((unsigned)channel >= bd->numports || !ch) {
if (channel >= bd->numports)
ch = chan0;
bc = ch->brdchan;
@@ -2048,97 +1767,53 @@ static void doevent(int crd)
if ((bc = ch->brdchan) == NULL)
goto next;
- if (event & DATA_IND)
- { /* Begin DATA_IND */
-
+ if (event & DATA_IND) { /* Begin DATA_IND */
receive_data(ch);
assertgwinon(ch);
-
} /* End DATA_IND */
/* else *//* Fix for DCD transition missed bug */
- if (event & MODEMCHG_IND)
- { /* Begin MODEMCHG_IND */
-
+ if (event & MODEMCHG_IND) { /* Begin MODEMCHG_IND */
/* A modem signal change has been indicated */
-
ch->imodem = mstat;
-
- if (ch->asyncflags & ASYNC_CHECK_CD)
- {
+ if (ch->asyncflags & ASYNC_CHECK_CD) {
if (mstat & ch->dcd) /* We are now receiving dcd */
wake_up_interruptible(&ch->open_wait);
else
pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
}
-
} /* End MODEMCHG_IND */
-
tty = ch->tty;
- if (tty)
- { /* Begin if valid tty */
-
- if (event & BREAK_IND)
- { /* Begin if BREAK_IND */
-
+ if (tty) { /* Begin if valid tty */
+ if (event & BREAK_IND) { /* Begin if BREAK_IND */
/* A break has been indicated */
-
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_BREAK;
-
*tty->flip.char_buf_ptr++ = 0;
-
tty_schedule_flip(tty);
-
- } /* End if BREAK_IND */
- else
- if (event & LOWTX_IND)
- { /* Begin LOWTX_IND */
-
+ } else if (event & LOWTX_IND) { /* Begin LOWTX_IND */
if (ch->statusflags & LOWWAIT)
{ /* Begin if LOWWAIT */
-
ch->statusflags &= ~LOWWAIT;
tty_wakeup(tty);
wake_up_interruptible(&tty->write_wait);
-
} /* End if LOWWAIT */
-
- } /* End LOWTX_IND */
- else
- if (event & EMPTYTX_IND)
- { /* Begin EMPTYTX_IND */
-
+ } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */
/* This event is generated by setup_empty_event */
-
ch->statusflags &= ~TXBUSY;
- if (ch->statusflags & EMPTYWAIT)
- { /* Begin if EMPTYWAIT */
-
+ if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */
ch->statusflags &= ~EMPTYWAIT;
tty_wakeup(tty);
-
wake_up_interruptible(&tty->write_wait);
-
} /* End if EMPTYWAIT */
-
} /* End EMPTYTX_IND */
-
} /* End if valid tty */
-
-
next:
globalwinon(ch);
-
- if (!bc)
- printk(KERN_ERR "<Error> - bc == NULL in doevent!\n");
- else
- bc->idata = 1;
-
- chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4);
+ BUG_ON(!bc);
+ writew(1, &bc->idata);
+ writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
globalwinon(chan0);
-
} /* End while something in event queue */
-
} /* End doevent */
/* --------------------- Begin fepcmd ------------------------ */
@@ -2146,8 +1821,7 @@ static void doevent(int crd)
static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
int byte2, int ncmds, int bytecmd)
{ /* Begin fepcmd */
-
- unchar *memaddr;
+ unchar __iomem *memaddr;
unsigned int head, cmdTail, cmdStart, cmdMax;
long count;
int n;
@@ -2155,93 +1829,57 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
/* This is the routine in which commands may be passed to the card. */
if (ch->board->status == DISABLED)
- {
return;
- }
-
assertgwinon(ch);
-
/* Remember head (As well as max) is just an offset not a base addr */
- head = ch->mailbox->cin;
-
+ head = readw(&ch->mailbox->cin);
/* cmdStart is a base address */
- cmdStart = ch->mailbox->cstart;
-
+ cmdStart = readw(&ch->mailbox->cstart);
/* ------------------------------------------------------------------
We do the addition below because we do not want a max pointer
relative to cmdStart. We want a max pointer that points at the
physical end of the command queue.
-------------------------------------------------------------------- */
-
- cmdMax = (cmdStart + 4 + (ch->mailbox->cmax));
-
+ cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
memaddr = ch->board->re_map_membase;
- /*
- The below command is necessary because newer kernels (2.1.x and
- up) do not have a 1:1 virtual to physical mapping. The below
- call adjust for that.
- */
-
- memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr);
-
- if (head >= (cmdMax - cmdStart) || (head & 03))
- {
- printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__,
- cmd, head);
- printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__,
- cmdMax, cmdStart);
+ if (head >= (cmdMax - cmdStart) || (head & 03)) {
+ printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head);
+ printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart);
return;
}
-
- if (bytecmd)
- {
- *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
-
- *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
+ if (bytecmd) {
+ writeb(cmd, memaddr + head + cmdStart + 0);
+ writeb(ch->channelnum, memaddr + head + cmdStart + 1);
/* Below word_or_byte is bits to set */
- *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte;
+ writeb(word_or_byte, memaddr + head + cmdStart + 2);
/* Below byte2 is bits to reset */
- *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2;
-
- }
- else
- {
- *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd;
- *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum;
- *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte;
+ writeb(byte2, memaddr + head + cmdStart + 3);
+ } else {
+ writeb(cmd, memaddr + head + cmdStart + 0);
+ writeb(ch->channelnum, memaddr + head + cmdStart + 1);
+ writeb(word_or_byte, memaddr + head + cmdStart + 2);
}
-
head = (head + 4) & (cmdMax - cmdStart - 4);
- ch->mailbox->cin = head;
-
+ writew(head, &ch->mailbox->cin);
count = FEPTIMEOUT;
- for (;;)
- { /* Begin forever loop */
-
+ for (;;) { /* Begin forever loop */
count--;
- if (count == 0)
- {
+ if (count == 0) {
printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
return;
}
-
- head = ch->mailbox->cin;
- cmdTail = ch->mailbox->cout;
-
+ head = readw(&ch->mailbox->cin);
+ cmdTail = readw(&ch->mailbox->cout);
n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-
/* ----------------------------------------------------------
Basically this will break when the FEP acknowledges the
command by incrementing cmdTail (Making it equal to head).
------------------------------------------------------------- */
-
if (n <= ncmds * (sizeof(short) * 4))
break; /* Well nearly forever :-) */
-
} /* End forever loop */
-
} /* End fepcmd */
/* ---------------------------------------------------------------------
@@ -2255,11 +1893,9 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
{ /* Begin termios2digi_h */
-
unsigned res = 0;
- if (cflag & CRTSCTS)
- {
+ if (cflag & CRTSCTS) {
ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
res |= ((ch->m_cts) | (ch->m_rts));
}
@@ -2295,7 +1931,6 @@ static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
INPCK | ISTRIP|IXON|IXANY|IXOFF);
-
if (ch->digiext.digi_flags & DIGI_AIXON)
res |= IAIXON;
return res;
@@ -2308,28 +1943,15 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
{ /* Begin termios2digi_c */
unsigned res = 0;
-
-#ifdef SPEED_HACK
- /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
- if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200;
- if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600;
-#endif /* SPEED_HACK */
-
- if (cflag & CBAUDEX)
- { /* Begin detected CBAUDEX */
-
+ if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */
ch->digiext.digi_flags |= DIGI_FAST;
-
/* -------------------------------------------------------------
HUPCL bit is used by FEP to indicate fast baud
table is to be used.
----------------------------------------------------------------- */
-
res |= FEP_HUPCL;
-
} /* End detected CBAUDEX */
else ch->digiext.digi_flags &= ~DIGI_FAST;
-
/* -------------------------------------------------------------------
CBAUD has bit position 0x1000 set these days to indicate Linux
baud rate remap. Digi hardware can't handle the bit assignment.
@@ -2337,7 +1959,6 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
bit out.
---------------------------------------------------------------------- */
res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-
/* -------------------------------------------------------------
This gets a little confusing. The Digi cards have their own
representation of c_cflags controling baud rate. For the most
@@ -2357,10 +1978,8 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
should be checked for a screened out prior to termios2digi_c
returning. Since CLOCAL isn't used by the board this can be
ignored as long as the returned value is used only by Digi hardware.
- ----------------------------------------------------------------- */
-
- if (cflag & CBAUDEX)
- {
+ ----------------------------------------------------------------- */
+ if (cflag & CBAUDEX) {
/* -------------------------------------------------------------
The below code is trying to guarantee that only baud rates
115200 and 230400 are remapped. We use exclusive or because
@@ -2371,138 +1990,96 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
(!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
- {
res += 1;
- }
}
-
return res;
} /* End termios2digi_c */
/* --------------------- Begin epcaparam ----------------------- */
+/* Caller must hold the locks */
static void epcaparam(struct tty_struct *tty, struct channel *ch)
{ /* Begin epcaparam */
unsigned int cmdHead;
struct termios *ts;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned mval, hflow, cflag, iflag;
bc = ch->brdchan;
epcaassert(bc !=0, "bc out of range");
assertgwinon(ch);
-
ts = tty->termios;
-
- if ((ts->c_cflag & CBAUD) == 0)
- { /* Begin CBAUD detected */
-
- cmdHead = bc->rin;
- bc->rout = cmdHead;
- cmdHead = bc->tin;
-
+ if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */
+ cmdHead = readw(&bc->rin);
+ writew(cmdHead, &bc->rout);
+ cmdHead = readw(&bc->tin);
/* Changing baud in mid-stream transmission can be wonderful */
/* ---------------------------------------------------------------
Flush current transmit buffer by setting cmdTail pointer (tout)
to cmdHead pointer (tin). Hopefully the transmit buffer is empty.
----------------------------------------------------------------- */
-
fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
mval = 0;
-
- } /* End CBAUD detected */
- else
- { /* Begin CBAUD not detected */
-
+ } else { /* Begin CBAUD not detected */
/* -------------------------------------------------------------------
c_cflags have changed but that change had nothing to do with BAUD.
Propagate the change to the card.
---------------------------------------------------------------------- */
-
cflag = termios2digi_c(ch, ts->c_cflag);
-
- if (cflag != ch->fepcflag)
- {
+ if (cflag != ch->fepcflag) {
ch->fepcflag = cflag;
/* Set baud rate, char size, stop bits, parity */
fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
}
-
-
/* ----------------------------------------------------------------
If the user has not forced CLOCAL and if the device is not a
CALLOUT device (Which is always CLOCAL) we set flags such that
the driver will wait on carrier detect.
------------------------------------------------------------------- */
-
if (ts->c_cflag & CLOCAL)
- { /* Begin it is a cud device or a ttyD device with CLOCAL on */
ch->asyncflags &= ~ASYNC_CHECK_CD;
- } /* End it is a cud device or a ttyD device with CLOCAL on */
else
- { /* Begin it is a ttyD device */
ch->asyncflags |= ASYNC_CHECK_CD;
- } /* End it is a ttyD device */
-
mval = ch->m_dtr | ch->m_rts;
-
} /* End CBAUD not detected */
-
iflag = termios2digi_i(ch, ts->c_iflag);
-
/* Check input mode flags */
-
- if (iflag != ch->fepiflag)
- {
+ if (iflag != ch->fepiflag) {
ch->fepiflag = iflag;
-
/* ---------------------------------------------------------------
Command sets channels iflag structure on the board. Such things
as input soft flow control, handling of parity errors, and
break handling are all set here.
------------------------------------------------------------------- */
-
/* break handling, parity handling, input stripping, flow control chars */
fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
}
-
/* ---------------------------------------------------------------
Set the board mint value for this channel. This will cause hardware
events to be generated each time the DCD signal (Described in mint)
changes.
------------------------------------------------------------------- */
- bc->mint = ch->dcd;
-
+ writeb(ch->dcd, &bc->mint);
if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
if (ch->digiext.digi_flags & DIGI_FORCEDCD)
- bc->mint = 0;
-
- ch->imodem = bc->mstat;
-
+ writeb(0, &bc->mint);
+ ch->imodem = readb(&bc->mstat);
hflow = termios2digi_h(ch, ts->c_cflag);
-
- if (hflow != ch->hflow)
- {
+ if (hflow != ch->hflow) {
ch->hflow = hflow;
-
/* --------------------------------------------------------------
Hard flow control has been selected but the board is not
using it. Activate hard flow control now.
----------------------------------------------------------------- */
-
fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
}
-
-
mval ^= ch->modemfake & (mval ^ ch->modem);
- if (ch->omodem ^ mval)
- {
+ if (ch->omodem ^ mval) {
ch->omodem = mval;
-
/* --------------------------------------------------------------
The below command sets the DTR and RTS mstat structure. If
hard flow control is NOT active these changes will drive the
@@ -2514,87 +2091,65 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
/* First reset DTR & RTS; then set them */
fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-
}
-
- if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)
- {
+ if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
ch->fepstartc = ch->startc;
ch->fepstopc = ch->stopc;
-
/* ------------------------------------------------------------
The XON / XOFF characters have changed; propagate these
changes to the card.
--------------------------------------------------------------- */
-
fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
}
-
- if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)
- {
+ if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
ch->fepstartca = ch->startca;
ch->fepstopca = ch->stopca;
-
/* ---------------------------------------------------------------
Similar to the above, this time the auxilarly XON / XOFF
characters have changed; propagate these changes to the card.
------------------------------------------------------------------ */
-
fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
-
} /* End epcaparam */
/* --------------------- Begin receive_data ----------------------- */
-
+/* Caller holds lock */
static void receive_data(struct channel *ch)
{ /* Begin receive_data */
unchar *rptr;
struct termios *ts = NULL;
struct tty_struct *tty;
- volatile struct board_chan *bc;
- register int dataToRead, wrapgap, bytesAvailable;
- register unsigned int tail, head;
+ struct board_chan __iomem *bc;
+ int dataToRead, wrapgap, bytesAvailable;
+ unsigned int tail, head;
unsigned int wrapmask;
int rc;
-
/* ---------------------------------------------------------------
This routine is called by doint when a receive data event
has taken place.
------------------------------------------------------------------- */
globalwinon(ch);
-
if (ch->statusflags & RXSTOPPED)
return;
-
tty = ch->tty;
if (tty)
ts = tty->termios;
-
bc = ch->brdchan;
-
- if (!bc)
- {
- printk(KERN_ERR "<Error> - bc is NULL in receive_data!\n");
- return;
- }
-
+ BUG_ON(!bc);
wrapmask = ch->rxbufsize - 1;
/* ---------------------------------------------------------------------
Get the head and tail pointers to the receiver queue. Wrap the
head pointer if it has reached the end of the buffer.
------------------------------------------------------------------------ */
-
- head = bc->rin;
+ head = readw(&bc->rin);
head &= wrapmask;
- tail = bc->rout & wrapmask;
+ tail = readw(&bc->rout) & wrapmask;
bytesAvailable = (head - tail) & wrapmask;
-
if (bytesAvailable == 0)
return;
@@ -2602,73 +2157,53 @@ static void receive_data(struct channel *ch)
If CREAD bit is off or device not open, set TX tail to head
--------------------------------------------------------------------- */
- if (!tty || !ts || !(ts->c_cflag & CREAD))
- {
- bc->rout = head;
+ if (!tty || !ts || !(ts->c_cflag & CREAD)) {
+ writew(head, &bc->rout);
return;
}
if (tty->flip.count == TTY_FLIPBUF_SIZE)
return;
- if (bc->orun)
- {
- bc->orun = 0;
- printk(KERN_WARNING "overrun! DigiBoard device %s\n",tty->name);
+ if (readb(&bc->orun)) {
+ writeb(0, &bc->orun);
+ printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
}
-
rxwinon(ch);
rptr = tty->flip.char_buf_ptr;
rc = tty->flip.count;
-
- while (bytesAvailable > 0)
- { /* Begin while there is data on the card */
-
+ while (bytesAvailable > 0) { /* Begin while there is data on the card */
wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-
/* ---------------------------------------------------------------
Even if head has wrapped around only report the amount of
data to be equal to the size - tail. Remember memcpy can't
automaticly wrap around the receive buffer.
----------------------------------------------------------------- */
-
dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
-
/* --------------------------------------------------------------
Make sure we don't overflow the buffer
----------------------------------------------------------------- */
-
if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
dataToRead = TTY_FLIPBUF_SIZE - rc;
-
if (dataToRead == 0)
break;
-
/* ---------------------------------------------------------------
Move data read from our card into the line disciplines buffer
for translation if necessary.
------------------------------------------------------------------ */
-
- if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr)
- printk(KERN_ERR "<Error> - receive_data : memcpy failed\n");
-
+ memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
rc += dataToRead;
rptr += dataToRead;
tail = (tail + dataToRead) & wrapmask;
bytesAvailable -= dataToRead;
-
} /* End while there is data on the card */
-
-
tty->flip.count = rc;
tty->flip.char_buf_ptr = rptr;
globalwinon(ch);
- bc->rout = tail;
-
+ writew(tail, &bc->rout);
/* Must be called with global data */
tty_schedule_flip(ch->tty);
return;
-
} /* End receive_data */
static int info_ioctl(struct tty_struct *tty, struct file * file,
@@ -2676,17 +2211,15 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
{
switch (cmd)
{ /* Begin switch cmd */
-
case DIGI_GETINFO:
{ /* Begin case DIGI_GETINFO */
-
struct digi_info di ;
int brd;
- getUser(brd, (unsigned int __user *)arg);
-
- if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
- return (-ENODEV);
+ if(get_user(brd, (unsigned int __user *)arg))
+ return -EFAULT;
+ if (brd < 0 || brd >= num_cards || num_cards == 0)
+ return -ENODEV;
memset(&di, 0, sizeof(di));
@@ -2694,8 +2227,9 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
di.status = boards[brd].status;
di.type = boards[brd].type ;
di.numports = boards[brd].numports ;
- di.port = boards[brd].port ;
- di.membase = boards[brd].membase ;
+ /* Legacy fixups - just move along nothing to see */
+ di.port = (unsigned char *)boards[brd].port ;
+ di.membase = (unsigned char *)boards[brd].membase ;
if (copy_to_user((void __user *)arg, &di, sizeof (di)))
return -EFAULT;
@@ -2709,39 +2243,29 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
int brd = arg & 0xff000000 >> 16 ;
unsigned char state = arg & 0xff ;
- if ((brd < 0) || (brd >= num_cards))
- {
- printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
+ if (brd < 0 || brd >= num_cards) {
+ printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
return (-ENODEV);
}
-
digi_poller_inhibited = state ;
break ;
-
} /* End case DIGI_POLLER */
case DIGI_INIT:
{ /* Begin case DIGI_INIT */
-
/* ------------------------------------------------------------
This call is made by the apps to complete the initilization
of the board(s). This routine is responsible for setting
the card to its initial state and setting the drivers control
fields to the sutianle settings for the card in question.
---------------------------------------------------------------- */
-
int crd ;
for (crd = 0; crd < num_cards; crd++)
post_fep_init (crd);
-
break ;
-
} /* End case DIGI_INIT */
-
-
default:
- return -ENOIOCTLCMD;
-
+ return -ENOTTY;
} /* End switch cmd */
return (0) ;
}
@@ -2750,43 +2274,33 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
struct channel *ch = (struct channel *) tty->driver_data;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int mstat, mflag = 0;
unsigned long flags;
if (ch)
bc = ch->brdchan;
else
- {
- printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n");
- return(-EINVAL);
- }
+ return -EINVAL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- mstat = bc->mstat;
+ mstat = readb(&bc->mstat);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
if (mstat & ch->m_dtr)
mflag |= TIOCM_DTR;
-
if (mstat & ch->m_rts)
mflag |= TIOCM_RTS;
-
if (mstat & ch->m_cts)
mflag |= TIOCM_CTS;
-
if (mstat & ch->dsr)
mflag |= TIOCM_DSR;
-
if (mstat & ch->m_ri)
mflag |= TIOCM_RI;
-
if (mstat & ch->dcd)
mflag |= TIOCM_CD;
-
return mflag;
}
@@ -2796,13 +2310,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
struct channel *ch = (struct channel *) tty->driver_data;
unsigned long flags;
- if (!ch) {
- printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n");
- return(-EINVAL);
- }
+ if (!ch)
+ return -EINVAL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
/*
* I think this modemfake stuff is broken. It doesn't
* correctly reflect the behaviour desired by the TIOCM*
@@ -2824,17 +2335,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
ch->modemfake |= ch->m_dtr;
ch->modem &= ~ch->m_dtr;
}
-
globalwinon(ch);
-
/* --------------------------------------------------------------
The below routine generally sets up parity, baud, flow control
issues, etc.... It effect both control flags and input flags.
------------------------------------------------------------------ */
-
epcaparam(tty,ch);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
return 0;
}
@@ -2847,19 +2355,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
- volatile struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch = (struct channel *) tty->driver_data;
void __user *argp = (void __user *)arg;
if (ch)
bc = ch->brdchan;
else
- {
- printk(KERN_ERR "<Error> - ch is NULL in pc_ioctl!\n");
- return(-EINVAL);
- }
-
- save_flags(flags);
+ return -EINVAL;
/* -------------------------------------------------------------------
For POSIX compliance we need to add more ioctls. See tty_ioctl.c
@@ -2871,46 +2374,39 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
{ /* Begin switch cmd */
case TCGETS:
- if (copy_to_user(argp,
- tty->termios, sizeof(struct termios)))
+ if (copy_to_user(argp, tty->termios, sizeof(struct termios)))
return -EFAULT;
- return(0);
-
+ return 0;
case TCGETA:
return get_termio(tty, argp);
-
case TCSBRK: /* SVID version: non-zero arg --> no break */
-
retval = tty_check_change(tty);
if (retval)
return retval;
-
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
if (!arg)
digi_send_break(ch, HZ/4); /* 1/4 second */
return 0;
-
case TCSBRKP: /* support for POSIX tcsendbreak() */
-
retval = tty_check_change(tty);
if (retval)
return retval;
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
return 0;
-
case TIOCGSOFTCAR:
if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
return -EFAULT;
return 0;
-
case TIOCSSOFTCAR:
{
unsigned int value;
@@ -2922,75 +2418,63 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
(value ? CLOCAL : 0));
return 0;
}
-
case TIOCMODG:
mflag = pc_tiocmget(tty, file);
if (put_user(mflag, (unsigned long __user *)argp))
return -EFAULT;
break;
-
case TIOCMODS:
if (get_user(mstat, (unsigned __user *)argp))
return -EFAULT;
return pc_tiocmset(tty, file, mstat, ~mstat);
-
case TIOCSDTR:
+ spin_lock_irqsave(&epca_lock, flags);
ch->omodem |= ch->m_dtr;
- cli();
globalwinon(ch);
fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
case TIOCCDTR:
+ spin_lock_irqsave(&epca_lock, flags);
ch->omodem &= ~ch->m_dtr;
- cli();
globalwinon(ch);
fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
-
case DIGI_GETA:
if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
return -EFAULT;
break;
-
case DIGI_SETAW:
case DIGI_SETAF:
- if ((cmd) == (DIGI_SETAW))
- {
+ if (cmd == DIGI_SETAW) {
/* Setup an event to indicate when the transmit buffer empties */
-
+ spin_lock_irqsave(&epca_lock, flags);
setup_empty_event(tty,ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
tty_wait_until_sent(tty, 0);
- }
- else
- {
+ } else {
/* ldisc lock already held in ioctl */
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
}
-
/* Fall Thru */
-
case DIGI_SETA:
if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
return -EFAULT;
- if (ch->digiext.digi_flags & DIGI_ALTPIN)
- {
+ if (ch->digiext.digi_flags & DIGI_ALTPIN) {
ch->dcd = ch->m_dsr;
ch->dsr = ch->m_dcd;
- }
- else
- {
+ } else {
ch->dcd = ch->m_dcd;
ch->dsr = ch->m_dsr;
}
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
/* -----------------------------------------------------------------
@@ -3000,25 +2484,22 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
epcaparam(tty,ch);
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
break;
case DIGI_GETFLOW:
case DIGI_GETAFLOW:
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- if ((cmd) == (DIGI_GETFLOW))
- {
- dflow.startc = bc->startc;
- dflow.stopc = bc->stopc;
- }
- else
- {
- dflow.startc = bc->startca;
- dflow.stopc = bc->stopca;
+ if (cmd == DIGI_GETFLOW) {
+ dflow.startc = readb(&bc->startc);
+ dflow.stopc = readb(&bc->stopc);
+ } else {
+ dflow.startc = readb(&bc->startca);
+ dflow.stopc = readb(&bc->stopca);
}
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
if (copy_to_user(argp, &dflow, sizeof(dflow)))
return -EFAULT;
@@ -3026,13 +2507,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
case DIGI_SETAFLOW:
case DIGI_SETFLOW:
- if ((cmd) == (DIGI_SETFLOW))
- {
+ if (cmd == DIGI_SETFLOW) {
startc = ch->startc;
stopc = ch->stopc;
- }
- else
- {
+ } else {
startc = ch->startca;
stopc = ch->stopca;
}
@@ -3040,40 +2518,31 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
if (copy_from_user(&dflow, argp, sizeof(dflow)))
return -EFAULT;
- if (dflow.startc != startc || dflow.stopc != stopc)
- { /* Begin if setflow toggled */
- cli();
+ if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- if ((cmd) == (DIGI_SETFLOW))
- {
+ if (cmd == DIGI_SETFLOW) {
ch->fepstartc = ch->startc = dflow.startc;
ch->fepstopc = ch->stopc = dflow.stopc;
fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
- }
- else
- {
+ } else {
ch->fepstartca = ch->startca = dflow.startc;
ch->fepstopca = ch->stopca = dflow.stopc;
fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
}
- if (ch->statusflags & TXSTOPPED)
+ if (ch->statusflags & TXSTOPPED)
pc_start(tty);
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if setflow toggled */
break;
-
default:
return -ENOIOCTLCMD;
-
} /* End switch cmd */
-
return 0;
-
} /* End pc_ioctl */
/* --------------------- Begin pc_set_termios ----------------------- */
@@ -3083,20 +2552,16 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
- save_flags(flags);
- cli();
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
epcaparam(tty, ch);
memoff(ch);
+ spin_unlock_irqrestore(&epca_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
((tty->termios->c_cflag & CRTSCTS) == 0))
@@ -3106,8 +2571,6 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
(tty->termios->c_cflag & CLOCAL))
wake_up_interruptible(&ch->open_wait);
- restore_flags(flags);
-
} /* End if channel valid */
} /* End pc_set_termios */
@@ -3116,29 +2579,18 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
static void do_softint(void *private_)
{ /* Begin do_softint */
-
struct channel *ch = (struct channel *) private_;
-
-
/* Called in response to a modem change event */
-
- if (ch && ch->magic == EPCA_MAGIC)
- { /* Begin EPCA_MAGIC */
-
+ if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */
struct tty_struct *tty = ch->tty;
- if (tty && tty->driver_data)
- {
- if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event))
- { /* Begin if clear_bit */
-
+ if (tty && tty->driver_data) {
+ if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
wake_up_interruptible(&ch->open_wait);
ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-
} /* End if clear_bit */
}
-
} /* End EPCA_MAGIC */
} /* End do_softint */
@@ -3154,82 +2606,49 @@ static void pc_stop(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if valid channel */
-
- save_flags(flags);
- cli();
-
- if ((ch->statusflags & TXSTOPPED) == 0)
- { /* Begin if transmit stop requested */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if valid channel */
+ spin_lock_irqsave(&epca_lock, flags);
+ if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
globalwinon(ch);
-
/* STOP transmitting now !! */
-
fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-
ch->statusflags |= TXSTOPPED;
memoff(ch);
-
} /* End if transmit stop requested */
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if valid channel */
-
} /* End pc_stop */
/* --------------------- Begin pc_start ----------------------- */
static void pc_start(struct tty_struct *tty)
{ /* Begin pc_start */
-
struct channel *ch;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
unsigned long flags;
-
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* Just in case output was resumed because of a change in Digi-flow */
- if (ch->statusflags & TXSTOPPED)
- { /* Begin transmit resume requested */
-
- volatile struct board_chan *bc;
-
+ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */
+ struct board_chan __iomem *bc;
globalwinon(ch);
bc = ch->brdchan;
if (ch->statusflags & LOWWAIT)
- bc->ilow = 1;
-
+ writeb(1, &bc->ilow);
/* Okay, you can start transmitting again... */
-
fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-
ch->statusflags &= ~TXSTOPPED;
memoff(ch);
-
} /* End transmit resume requested */
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_start */
/* ------------------------------------------------------------------
@@ -3244,86 +2663,55 @@ ______________________________________________________________________ */
static void pc_throttle(struct tty_struct * tty)
{ /* Begin pc_throttle */
-
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
-
- save_flags(flags);
- cli();
-
- if ((ch->statusflags & RXSTOPPED) == 0)
- {
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
+ spin_lock_irqsave(&epca_lock, flags);
+ if ((ch->statusflags & RXSTOPPED) == 0) {
globalwinon(ch);
fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-
ch->statusflags |= RXSTOPPED;
memoff(ch);
}
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_throttle */
/* --------------------- Begin unthrottle ----------------------- */
static void pc_unthrottle(struct tty_struct *tty)
{ /* Begin pc_unthrottle */
-
struct channel *ch;
unsigned long flags;
- volatile struct board_chan *bc;
-
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if channel valid */
-
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */
/* Just in case output was resumed because of a change in Digi-flow */
- save_flags(flags);
- cli();
-
- if (ch->statusflags & RXSTOPPED)
- {
-
+ spin_lock_irqsave(&epca_lock, flags);
+ if (ch->statusflags & RXSTOPPED) {
globalwinon(ch);
- bc = ch->brdchan;
fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-
ch->statusflags &= ~RXSTOPPED;
memoff(ch);
}
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End if channel valid */
-
} /* End pc_unthrottle */
/* --------------------- Begin digi_send_break ----------------------- */
void digi_send_break(struct channel *ch, int msec)
{ /* Begin digi_send_break */
-
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
-
/* --------------------------------------------------------------------
Maybe I should send an infinite break here, schedule() for
msec amount of time, and then stop the break. This way,
@@ -3331,36 +2719,28 @@ void digi_send_break(struct channel *ch, int msec)
to be called (i.e. via an ioctl()) more than once in msec amount
of time. Try this for now...
------------------------------------------------------------------------ */
-
fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
memoff(ch);
-
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End digi_send_break */
/* --------------------- Begin setup_empty_event ----------------------- */
+/* Caller MUST hold the lock */
+
static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
{ /* Begin setup_empty_event */
- volatile struct board_chan *bc = ch->brdchan;
- unsigned long int flags;
+ struct board_chan __iomem *bc = ch->brdchan;
- save_flags(flags);
- cli();
globalwinon(ch);
ch->statusflags |= EMPTYWAIT;
-
/* ------------------------------------------------------------------
When set the iempty flag request a event to be generated when the
transmit buffer is empty (If there is no BREAK in progress).
--------------------------------------------------------------------- */
-
- bc->iempty = 1;
+ writeb(1, &bc->iempty);
memoff(ch);
- restore_flags(flags);
-
} /* End setup_empty_event */
/* --------------------- Begin get_termio ----------------------- */
@@ -3369,10 +2749,10 @@ static int get_termio(struct tty_struct * tty, struct termio __user * termio)
{ /* Begin get_termio */
return kernel_termios_to_user_termio(termio, tty->termios);
} /* End get_termio */
+
/* ---------------------- Begin epca_setup -------------------------- */
void epca_setup(char *str, int *ints)
{ /* Begin epca_setup */
-
struct board_info board;
int index, loop, last;
char *temp, *t2;
@@ -3394,49 +2774,41 @@ void epca_setup(char *str, int *ints)
for (last = 0, index = 1; index <= ints[0]; index++)
switch(index)
{ /* Begin parse switch */
-
case 1:
board.status = ints[index];
-
/* ---------------------------------------------------------
We check for 2 (As opposed to 1; because 2 is a flag
instructing the driver to ignore epcaconfig.) For this
reason we check for 2.
------------------------------------------------------------ */
- if (board.status == 2)
- { /* Begin ignore epcaconfig as well as lilo cmd line */
+ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
nbdevs = 0;
num_cards = 0;
return;
} /* End ignore epcaconfig as well as lilo cmd line */
- if (board.status > 2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board status 0x%x\n", board.status);
+ if (board.status > 2) {
+ printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_STATUS;
return;
}
last = index;
break;
-
case 2:
board.type = ints[index];
- if (board.type >= PCIXEM)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board type 0x%x\n", board.type);
+ if (board.type >= PCIXEM) {
+ printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_TYPE;
return;
}
last = index;
break;
-
case 3:
board.altpin = ints[index];
- if (board.altpin > 1)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board altpin 0x%x\n", board.altpin);
+ if (board.altpin > 1) {
+ printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
invalid_lilo_config = 1;
setup_error_code |= INVALID_ALTPIN;
return;
@@ -3446,9 +2818,8 @@ void epca_setup(char *str, int *ints)
case 4:
board.numports = ints[index];
- if ((board.numports < 2) || (board.numports > 256))
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board numports 0x%x\n", board.numports);
+ if (board.numports < 2 || board.numports > 256) {
+ printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
invalid_lilo_config = 1;
setup_error_code |= INVALID_NUM_PORTS;
return;
@@ -3458,10 +2829,9 @@ void epca_setup(char *str, int *ints)
break;
case 5:
- board.port = (unsigned char *)ints[index];
- if (ints[index] <= 0)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
+ board.port = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
invalid_lilo_config = 1;
setup_error_code |= INVALID_PORT_BASE;
return;
@@ -3470,10 +2840,9 @@ void epca_setup(char *str, int *ints)
break;
case 6:
- board.membase = (unsigned char *)ints[index];
- if (ints[index] <= 0)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+ board.membase = ints[index];
+ if (ints[index] <= 0) {
+ printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
invalid_lilo_config = 1;
setup_error_code |= INVALID_MEM_BASE;
return;
@@ -3487,21 +2856,16 @@ void epca_setup(char *str, int *ints)
} /* End parse switch */
- while (str && *str)
- { /* Begin while there is a string arg */
-
+ while (str && *str) { /* Begin while there is a string arg */
/* find the next comma or terminator */
temp = str;
-
/* While string is not null, and a comma hasn't been found */
while (*temp && (*temp != ','))
temp++;
-
if (!*temp)
temp = NULL;
else
*temp++ = 0;
-
/* Set index to the number of args + 1 */
index = last + 1;
@@ -3511,12 +2875,10 @@ void epca_setup(char *str, int *ints)
len = strlen(str);
if (strncmp("Disable", str, len) == 0)
board.status = 0;
- else
- if (strncmp("Enable", str, len) == 0)
+ else if (strncmp("Enable", str, len) == 0)
board.status = 1;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid status %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_STATUS;
return;
@@ -3525,22 +2887,17 @@ void epca_setup(char *str, int *ints)
break;
case 2:
-
for(loop = 0; loop < EPCA_NUM_TYPES; loop++)
if (strcmp(board_desc[loop], str) == 0)
break;
-
-
/* ---------------------------------------------------------------
If the index incremented above refers to a legitamate board
type set it here.
------------------------------------------------------------------*/
-
if (index < EPCA_NUM_TYPES)
board.type = loop;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid board type: %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_BOARD_TYPE;
return;
@@ -3552,12 +2909,10 @@ void epca_setup(char *str, int *ints)
len = strlen(str);
if (strncmp("Disable", str, len) == 0)
board.altpin = 0;
- else
- if (strncmp("Enable", str, len) == 0)
+ else if (strncmp("Enable", str, len) == 0)
board.altpin = 1;
- else
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid altpin %s\n", str);
+ else {
+ printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_ALTPIN;
return;
@@ -3570,9 +2925,8 @@ void epca_setup(char *str, int *ints)
while (isdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid port count %s\n", str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_NUM_PORTS;
return;
@@ -3601,15 +2955,14 @@ void epca_setup(char *str, int *ints)
while (isxdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid i/o address %s\n", str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_PORT_BASE;
return;
}
- board.port = (unsigned char *)simple_strtoul(str, NULL, 16);
+ board.port = simple_strtoul(str, NULL, 16);
last = index;
break;
@@ -3618,52 +2971,38 @@ void epca_setup(char *str, int *ints)
while (isxdigit(*t2))
t2++;
- if (*t2)
- {
- printk(KERN_ERR "<Error> - epca_setup: Invalid memory base %s\n",str);
+ if (*t2) {
+ printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
invalid_lilo_config = 1;
setup_error_code |= INVALID_MEM_BASE;
return;
}
-
- board.membase = (unsigned char *)simple_strtoul(str, NULL, 16);
+ board.membase = simple_strtoul(str, NULL, 16);
last = index;
break;
-
default:
- printk(KERN_ERR "PC/Xx: Too many string parms\n");
+ printk(KERN_ERR "epca: Too many string parms\n");
return;
}
str = temp;
-
} /* End while there is a string arg */
-
- if (last < 6)
- {
- printk(KERN_ERR "PC/Xx: Insufficient parms specified\n");
+ if (last < 6) {
+ printk(KERN_ERR "epca: Insufficient parms specified\n");
return;
}
/* I should REALLY validate the stuff here */
-
/* Copies our local copy of board into boards */
memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
-
-
/* Does this get called once per lilo arg are what ? */
-
printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
num_cards, board_desc[board.type],
board.numports, (int)board.port, (unsigned int) board.membase);
-
num_cards++;
-
} /* End epca_setup */
-
-#ifdef ENABLE_PCI
/* ------------------------ Begin init_PCI --------------------------- */
enum epic_board_types {
@@ -3685,7 +3024,6 @@ static struct {
{ PCIXRJ, 2, },
};
-
static int __devinit epca_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3711,10 +3049,8 @@ static int __devinit epca_init_one (struct pci_dev *pdev,
boards[board_idx].status = ENABLED;
boards[board_idx].type = epca_info_tbl[info_idx].board_type;
boards[board_idx].numports = 0x0;
- boards[board_idx].port =
- (unsigned char *)((char *) addr + PCI_IO_OFFSET);
- boards[board_idx].membase =
- (unsigned char *)((char *) addr);
+ boards[board_idx].port = addr + PCI_IO_OFFSET;
+ boards[board_idx].membase = addr;
if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
@@ -3775,15 +3111,14 @@ static struct pci_device_id epca_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
int __init init_PCI (void)
-{ /* Begin init_PCI */
+{ /* Begin init_PCI */
memset (&epca_driver, 0, sizeof (epca_driver));
+ epca_driver.owner = THIS_MODULE;
epca_driver.name = "epca";
epca_driver.id_table = epca_pci_tbl;
epca_driver.probe = epca_init_one;
return pci_register_driver(&epca_driver);
-} /* End init_PCI */
-
-#endif /* ENABLE_PCI */
+}
MODULE_LICENSE("GPL");
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
index 52205ef71314..456d6c8f94a8 100644
--- a/drivers/char/epca.h
+++ b/drivers/char/epca.h
@@ -85,73 +85,73 @@ static char *board_desc[] =
struct channel
{
long magic;
- unchar boardnum;
- unchar channelnum;
- unchar omodem; /* FEP output modem status */
- unchar imodem; /* FEP input modem status */
- unchar modemfake; /* Modem values to be forced */
- unchar modem; /* Force values */
- unchar hflow;
- unchar dsr;
- unchar dcd;
- unchar m_rts ; /* The bits used in whatever FEP */
- unchar m_dcd ; /* is indiginous to this board to */
- unchar m_dsr ; /* represent each of the physical */
- unchar m_cts ; /* handshake lines */
- unchar m_ri ;
- unchar m_dtr ;
- unchar stopc;
- unchar startc;
- unchar stopca;
- unchar startca;
- unchar fepstopc;
- unchar fepstartc;
- unchar fepstopca;
- unchar fepstartca;
- unchar txwin;
- unchar rxwin;
- ushort fepiflag;
- ushort fepcflag;
- ushort fepoflag;
- ushort txbufhead;
- ushort txbufsize;
- ushort rxbufhead;
- ushort rxbufsize;
+ unsigned char boardnum;
+ unsigned char channelnum;
+ unsigned char omodem; /* FEP output modem status */
+ unsigned char imodem; /* FEP input modem status */
+ unsigned char modemfake; /* Modem values to be forced */
+ unsigned char modem; /* Force values */
+ unsigned char hflow;
+ unsigned char dsr;
+ unsigned char dcd;
+ unsigned char m_rts ; /* The bits used in whatever FEP */
+ unsigned char m_dcd ; /* is indiginous to this board to */
+ unsigned char m_dsr ; /* represent each of the physical */
+ unsigned char m_cts ; /* handshake lines */
+ unsigned char m_ri ;
+ unsigned char m_dtr ;
+ unsigned char stopc;
+ unsigned char startc;
+ unsigned char stopca;
+ unsigned char startca;
+ unsigned char fepstopc;
+ unsigned char fepstartc;
+ unsigned char fepstopca;
+ unsigned char fepstartca;
+ unsigned char txwin;
+ unsigned char rxwin;
+ unsigned short fepiflag;
+ unsigned short fepcflag;
+ unsigned short fepoflag;
+ unsigned short txbufhead;
+ unsigned short txbufsize;
+ unsigned short rxbufhead;
+ unsigned short rxbufsize;
int close_delay;
int count;
int blocked_open;
- ulong event;
+ unsigned long event;
int asyncflags;
uint dev;
- ulong statusflags;
- ulong c_iflag;
- ulong c_cflag;
- ulong c_lflag;
- ulong c_oflag;
- unchar *txptr;
- unchar *rxptr;
- unchar *tmp_buf;
+ unsigned long statusflags;
+ unsigned long c_iflag;
+ unsigned long c_cflag;
+ unsigned long c_lflag;
+ unsigned long c_oflag;
+ unsigned char __iomem *txptr;
+ unsigned char __iomem *rxptr;
+ unsigned char *tmp_buf;
struct board_info *board;
- volatile struct board_chan *brdchan;
+ struct board_chan __iomem *brdchan;
struct digi_struct digiext;
struct tty_struct *tty;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
- struct work_struct tqueue;
- volatile struct global_data *mailbox;
+ struct work_struct tqueue;
+ struct global_data __iomem *mailbox;
};
struct board_info
{
- unchar status;
- unchar type;
- unchar altpin;
- ushort numports;
- unchar *port;
- unchar *membase;
- unchar __iomem *re_map_port;
- unchar *re_map_membase;
- ulong memory_seg;
+ unsigned char status;
+ unsigned char type;
+ unsigned char altpin;
+ unsigned short numports;
+ unsigned long port;
+ unsigned long membase;
+ void __iomem *re_map_port;
+ void __iomem *re_map_membase;
+ unsigned long memory_seg;
void ( * memwinon ) (struct board_info *, unsigned int) ;
void ( * memwinoff ) (struct board_info *, unsigned int) ;
void ( * globalwinon ) (struct channel *) ;
@@ -160,6 +160,6 @@ struct board_info
void ( * memoff ) (struct channel *) ;
void ( * assertgwinon ) (struct channel *) ;
void ( * assertmemoff ) (struct channel *) ;
- unchar poller_inhibited ;
+ unsigned char poller_inhibited ;
};
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 1704a2a57048..b2e0928e8428 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -387,10 +387,8 @@ int fdc_interrupt_wait(unsigned int time)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&ftape_wait_intr, &wait);
- while (!ft_interrupt_seen && timeout) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
+ while (!ft_interrupt_seen && timeout)
+ timeout = schedule_timeout_interruptible(timeout);
spin_lock_irq(&current->sighand->siglock);
current->blocked = old_sigmask;
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index 5745b74044ec..821357ce7e0e 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -331,27 +331,27 @@ KERN_INFO
zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) {
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"qft%i", i);
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR,
"nqft%i", i);
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR,
"zqft%i", i);
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR,
"nzqft%i", i);
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR,
"rawqft%i", i);
- class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+ class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR,
"nrawqft%i", i);
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 81d811edf3c5..66e53dd450ff 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,7 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#endif /* not MODULE */
-#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+#if defined(CONFIG_X86)
# define HAVE_MONOTONIC
# define TIMER_FREQ 1000000000ULL
#elif defined(CONFIG_ARCH_S390)
@@ -149,8 +149,7 @@ static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
static void hangcheck_fire(unsigned long);
-static struct timer_list hangcheck_ticktock =
- TIMER_INITIALIZER(hangcheck_fire, 0, 0);
+static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
static void hangcheck_fire(unsigned long data)
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 762fa430fb5b..3808d9572619 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -44,12 +44,14 @@
/*
* The High Precision Event Timer driver.
* This driver is closely modelled after the rtc.c driver.
- * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
+ * http://www.intel.com/hardwaredesign/hpetspec.htm
*/
#define HPET_USER_FREQ (64)
#define HPET_DRIFT (500)
-static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
+#define HPET_RANGE_SIZE 1024 /* from HPET spec */
+
+static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
/* A lock for concurrent access by app and isr hpet activity. */
static DEFINE_SPINLOCK(hpet_lock);
@@ -78,7 +80,7 @@ struct hpets {
struct hpet __iomem *hp_hpet;
unsigned long hp_hpet_phys;
struct time_interpolator *hp_interpolator;
- unsigned long hp_period;
+ unsigned long long hp_tick_freq;
unsigned long hp_delta;
unsigned int hp_ntimer;
unsigned int hp_which;
@@ -90,6 +92,7 @@ static struct hpets *hpets;
#define HPET_OPEN 0x0001
#define HPET_IE 0x0002 /* interrupt enabled */
#define HPET_PERIODIC 0x0004
+#define HPET_SHARED_IRQ 0x0008
#if BITS_PER_LONG == 64
#define write_counter(V, MC) writeq(V, MC)
@@ -100,14 +103,14 @@ static struct hpets *hpets;
#endif
#ifndef readq
-static unsigned long long __inline readq(void __iomem *addr)
+static inline unsigned long long readq(void __iomem *addr)
{
return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
}
#endif
#ifndef writeq
-static void __inline writeq(unsigned long long v, void __iomem *addr)
+static inline void writeq(unsigned long long v, void __iomem *addr)
{
writel(v & 0xffffffff, addr);
writel(v >> 32, addr + 4);
@@ -120,6 +123,11 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
unsigned long isr;
devp = data;
+ isr = 1 << (devp - devp->hd_hpets->hp_dev);
+
+ if ((devp->hd_flags & HPET_SHARED_IRQ) &&
+ !(isr & readl(&devp->hd_hpet->hpet_isr)))
+ return IRQ_NONE;
spin_lock(&hpet_lock);
devp->hd_irqdata++;
@@ -137,8 +145,8 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
&devp->hd_timer->hpet_compare);
}
- isr = (1 << (devp - devp->hd_hpets->hp_dev));
- writeq(isr, &devp->hd_hpet->hpet_isr);
+ if (devp->hd_flags & HPET_SHARED_IRQ)
+ writel(isr, &devp->hd_hpet->hpet_isr);
spin_unlock(&hpet_lock);
spin_lock(&hpet_task_lock);
@@ -273,11 +281,11 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- addr = __pa(addr);
if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
- printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
+ printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
+ __FUNCTION__);
return -EAGAIN;
}
@@ -365,7 +373,9 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
hpet = devp->hd_hpet;
hpetp = devp->hd_hpets;
- v = readq(&timer->hpet_config);
+ if (!devp->hd_ireqfreq)
+ return -EIO;
+
spin_lock_irq(&hpet_lock);
if (devp->hd_flags & HPET_IE) {
@@ -374,16 +384,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
}
devp->hd_flags |= HPET_IE;
+
+ if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK)
+ devp->hd_flags |= HPET_SHARED_IRQ;
spin_unlock_irq(&hpet_lock);
- t = readq(&timer->hpet_config);
irq = devp->hd_hdwirq;
if (irq) {
- sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
+ unsigned long irq_flags;
- if (request_irq
- (irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) {
+ sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
+ irq_flags = devp->hd_flags & HPET_SHARED_IRQ
+ ? SA_SHIRQ : SA_INTERRUPT;
+ if (request_irq(irq, hpet_interrupt, irq_flags,
+ devp->hd_name, (void *)devp)) {
printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
irq = 0;
}
@@ -417,20 +432,24 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
}
- isr = (1 << (devp - hpets->hp_dev));
- writeq(isr, &hpet->hpet_isr);
+ if (devp->hd_flags & HPET_SHARED_IRQ) {
+ isr = 1 << (devp - devp->hd_hpets->hp_dev);
+ writel(isr, &hpet->hpet_isr);
+ }
writeq(g, &timer->hpet_config);
local_irq_restore(flags);
return 0;
}
-static inline unsigned long hpet_time_div(unsigned long dis)
+/* converts Hz to number of timer ticks */
+static inline unsigned long hpet_time_div(struct hpets *hpets,
+ unsigned long dis)
{
- unsigned long long m = 1000000000000000ULL;
+ unsigned long long m;
+ m = hpets->hp_tick_freq + (dis >> 1);
do_div(m, dis);
-
return (unsigned long)m;
}
@@ -478,14 +497,21 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
{
struct hpet_info info;
- info.hi_ireqfreq = hpet_time_div(hpetp->hp_period *
- devp->hd_ireqfreq);
+ if (devp->hd_ireqfreq)
+ info.hi_ireqfreq =
+ hpet_time_div(hpetp, devp->hd_ireqfreq);
+ else
+ info.hi_ireqfreq = 0;
info.hi_flags =
readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
- info.hi_hpet = devp->hd_hpets->hp_which;
- info.hi_timer = devp - devp->hd_hpets->hp_dev;
- if (copy_to_user((void __user *)arg, &info, sizeof(info)))
- err = -EFAULT;
+ info.hi_hpet = hpetp->hp_which;
+ info.hi_timer = devp - hpetp->hp_dev;
+ if (kernel)
+ memcpy((void *)arg, &info, sizeof(info));
+ else
+ if (copy_to_user((void __user *)arg, &info,
+ sizeof(info)))
+ err = -EFAULT;
break;
}
case HPET_EPI:
@@ -517,12 +543,12 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
break;
}
- if (arg & (arg - 1)) {
+ if (!arg) {
err = -EINVAL;
break;
}
- devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg);
+ devp->hd_ireqfreq = hpet_time_div(hpetp, arg);
}
return err;
@@ -540,6 +566,17 @@ static struct file_operations hpet_fops = {
.mmap = hpet_mmap,
};
+static int hpet_is_known(struct hpet_data *hdp)
+{
+ struct hpets *hpetp;
+
+ for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+ if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
+ return 1;
+
+ return 0;
+}
+
EXPORT_SYMBOL(hpet_alloc);
EXPORT_SYMBOL(hpet_register);
EXPORT_SYMBOL(hpet_unregister);
@@ -564,6 +601,8 @@ int hpet_register(struct hpet_task *tp, int periodic)
return -EINVAL;
}
+ tp->ht_opaque = NULL;
+
spin_lock_irq(&hpet_task_lock);
spin_lock(&hpet_lock);
@@ -703,16 +742,15 @@ static void hpet_register_interpolator(struct hpets *hpetp)
#ifdef CONFIG_TIME_INTERPOLATION
struct time_interpolator *ti;
- ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+ ti = kzalloc(sizeof(*ti), GFP_KERNEL);
if (!ti)
return;
- memset(ti, 0, sizeof(*ti));
ti->source = TIME_SOURCE_MMIO64;
ti->shift = 10;
ti->addr = &hpetp->hp_hpet->hpet_mc;
- ti->frequency = hpet_time_div(hpets->hp_period);
- ti->drift = ti->frequency * HPET_DRIFT / 1000000;
+ ti->frequency = hpetp->hp_tick_freq;
+ ti->drift = HPET_DRIFT;
ti->mask = -1;
hpetp->hp_interpolator = ti;
@@ -744,11 +782,11 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
if (!timer)
return 0;
- hpet = hpets->hp_hpet;
+ hpet = hpetp->hp_hpet;
t = read_counter(&timer->hpet_compare);
i = 0;
- count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE);
+ count = hpet_time_div(hpetp, TICK_CALIBRATE);
local_irq_save(flags);
@@ -772,28 +810,29 @@ int hpet_alloc(struct hpet_data *hdp)
struct hpets *hpetp;
size_t siz;
struct hpet __iomem *hpet;
- static struct hpets *last = (struct hpets *)0;
- unsigned long ns;
+ static struct hpets *last = NULL;
+ unsigned long period;
+ unsigned long long temp;
/*
* hpet_alloc can be called by platform dependent code.
- * if platform dependent code has allocated the hpet
- * ACPI also reports hpet, then we catch it here.
+ * If platform dependent code has allocated the hpet that
+ * ACPI has also reported, then we catch it here.
*/
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (hpetp->hp_hpet == hdp->hd_address)
- return 0;
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
+ __FUNCTION__);
+ return 0;
+ }
siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
sizeof(struct hpet_dev));
- hpetp = kmalloc(siz, GFP_KERNEL);
+ hpetp = kzalloc(siz, GFP_KERNEL);
if (!hpetp)
return -ENOMEM;
- memset(hpetp, 0, siz);
-
hpetp->hp_which = hpet_nhpet++;
hpetp->hp_hpet = hdp->hd_address;
hpetp->hp_hpet_phys = hdp->hd_phys_address;
@@ -823,21 +862,23 @@ int hpet_alloc(struct hpet_data *hdp)
last = hpetp;
- hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
- HPET_COUNTER_CLK_PERIOD_SHIFT;
+ period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
+ HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */
+ temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */
+ temp += period >> 1; /* round */
+ do_div(temp, period);
+ hpetp->hp_tick_freq = temp; /* ticks per second */
- printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
- hpetp->hp_which, hdp->hd_phys_address,
+ printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s",
+ hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address,
hpetp->hp_ntimer > 1 ? "s" : "");
for (i = 0; i < hpetp->hp_ntimer; i++)
printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
printk("\n");
- ns = hpetp->hp_period; /* femptoseconds, 10^-15 */
- ns /= 1000000; /* convert to nanoseconds, 10^-9 */
- printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
- hpetp->hp_which, ns, hpetp->hp_ntimer,
- cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
+ 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);
mcfg = readq(&hpet->hpet_config);
if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
@@ -846,13 +887,10 @@ int hpet_alloc(struct hpet_data *hdp)
writeq(mcfg, &hpet->hpet_config);
}
- for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
- i++, hpet_ntimer++, devp++) {
- unsigned long v;
+ for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) {
struct hpet_timer __iomem *timer;
timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
- v = readq(&timer->hpet_config);
devp->hd_hpets = hpetp;
devp->hd_hpet = hpet;
@@ -881,7 +919,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
struct hpet_data *hdp;
acpi_status status;
struct acpi_resource_address64 addr;
- struct hpets *hpetp;
hdp = data;
@@ -894,9 +931,29 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
hdp->hd_phys_address = addr.min_address_range;
hdp->hd_address = ioremap(addr.min_address_range, size);
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
- if (hpetp->hp_hpet == hdp->hd_address)
- return -EBUSY;
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+ __FUNCTION__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return -EBUSY;
+ }
+ } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
+ struct acpi_resource_fixed_mem32 *fixmem32;
+
+ fixmem32 = &res->data.fixed_memory32;
+ if (!fixmem32)
+ return -EINVAL;
+
+ hdp->hd_phys_address = fixmem32->range_base_address;
+ hdp->hd_address = ioremap(fixmem32->range_base_address,
+ HPET_RANGE_SIZE);
+
+ if (hpet_is_known(hdp)) {
+ printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+ __FUNCTION__, hdp->hd_phys_address);
+ iounmap(hdp->hd_address);
+ return -EBUSY;
+ }
} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
struct acpi_resource_ext_irq *irqp;
int i;
@@ -906,11 +963,15 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
if (irqp->number_of_interrupts > 0) {
hdp->hd_nirqs = irqp->number_of_interrupts;
- for (i = 0; i < hdp->hd_nirqs; i++)
- hdp->hd_irq[i] =
+ for (i = 0; i < hdp->hd_nirqs; i++) {
+ int rc =
acpi_register_gsi(irqp->interrupts[i],
irqp->edge_level,
irqp->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ hdp->hd_irq[i] = rc;
+ }
}
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index cddb789902db..f92177634677 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -839,9 +839,6 @@ int __init hvc_init(void)
hvc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvc_driver, &hvc_ops);
- if (tty_register_driver(hvc_driver))
- panic("Couldn't register hvc console driver\n");
-
/* Always start the kthread because there can be hotplug vty adapters
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
@@ -851,6 +848,9 @@ int __init hvc_init(void)
return -EIO;
}
+ if (tty_register_driver(hvc_driver))
+ panic("Couldn't register hvc console driver\n");
+
return 0;
}
module_init(hvc_init);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index 60bb9152b832..f5212eb2b41d 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -39,7 +39,7 @@ char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = {
{"serial", "hvterm1"},
- { NULL, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, hvc_driver_table);
@@ -95,11 +95,11 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
}
static struct vio_driver hvc_vio_driver = {
- .name = hvc_driver_name,
.id_table = hvc_driver_table,
.probe = hvc_vio_probe,
.remove = hvc_vio_remove,
.driver = {
+ .name = hvc_driver_name,
.owner = THIS_MODULE,
}
};
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 3236d2404905..53dc77c760fc 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -527,7 +527,7 @@ static int khvcsd(void *unused)
static struct vio_device_id hvcs_driver_table[] __devinitdata= {
{"serial-server", "hvterm2"},
- { NULL, }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
@@ -720,10 +720,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
};
static struct vio_driver hvcs_vio_driver = {
- .name = hvcs_driver_name,
.id_table = hvcs_driver_table,
.probe = hvcs_probe,
.remove = hvcs_remove,
+ .driver = {
+ .name = hvcs_driver_name,
+ .owner = THIS_MODULE,
+ }
};
/* Only called from hvcs_get_pi please */
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 3480535a09c5..6f673d2de0b1 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -513,10 +513,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
return ret ? : -EAGAIN;
if(need_resched())
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
+ schedule_timeout_interruptible(1);
else
udelay(200); /* FIXME: We could poll for 250uS ?? */
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 82c5f30375ac..ba85eb1b6ec7 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -655,8 +655,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
timeout--; // So negative values == forever
if (!in_interrupt()) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1); // short nap
+ schedule_timeout_interruptible(1); // short nap
} else {
// we cannot sched/sleep in interrrupt silly
return 0;
@@ -1132,8 +1131,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user )
ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2);
+ schedule_timeout_interruptible(2);
if (signal_pending(current)) {
break;
}
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index cf0cd58d6305..d815d197dc3e 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -120,7 +120,6 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <asm/serial.h>
#include <asm/uaccess.h>
@@ -255,7 +254,7 @@ static unsigned long bh_counter = 0;
* selected, the board is serviced periodically to see if anything needs doing.
*/
#define POLL_TIMEOUT (jiffies + 1)
-static struct timer_list PollTimer = TIMER_INITIALIZER(ip2_poll, 0, 0);
+static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
static char TimerOn;
#ifdef IP2DEBUG_TRACE
@@ -722,8 +721,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
- 4 * i), NULL, "ipl%d", i);
+ class_device_create(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i),
+ NULL, "ipl%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/ipl%d", i);
@@ -733,8 +733,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
goto out_class;
}
- class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
- 4 * i + 1), NULL, "stat%d", i);
+ class_device_create(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+ NULL, "stat%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/stat%d", i);
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 5ce9c6269033..33862670e285 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -31,8 +31,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_BT_VERSION "v33"
-
static int bt_debug = 0x00; /* Production value 0, see following flags */
#define BT_DEBUG_ENABLE 1
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
{
unsigned int i;
- if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1;
+ if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+ return -1;
if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
return -2;
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt,
if (bt_debug & BT_DEBUG_MSG) {
printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
- for (i = 0; i < size; i ++) printk (" %02x", data[i]);
+ for (i = 0; i < size; i ++)
+ printk (" %02x", data[i]);
printk("\n");
}
bt->write_data[0] = size + 1; /* all data plus seq byte */
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt,
} else {
data[0] = bt->read_data[1];
data[1] = bt->read_data[3];
- if (length < msg_len) bt->truncated = 1;
+ if (length < msg_len)
+ bt->truncated = 1;
if (bt->truncated) { /* can be set in read_all_bytes() */
data[2] = IPMI_ERR_MSG_TRUNCATED;
msg_len = 3;
- } else memcpy(data + 2, bt->read_data + 4, msg_len - 2);
+ } else
+ memcpy(data + 2, bt->read_data + 4, msg_len - 2);
if (bt_debug & BT_DEBUG_MSG) {
printk (KERN_WARNING "BT: res (raw)");
- for (i = 0; i < msg_len; i++) printk(" %02x", data[i]);
+ for (i = 0; i < msg_len; i++)
+ printk(" %02x", data[i]);
printk ("\n");
}
}
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt,
static void reset_flags(struct si_sm_data *bt)
{
- if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY);
- if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
+ if (BT_STATUS & BT_H_BUSY)
+ BT_CONTROL(BT_H_BUSY);
+ if (BT_STATUS & BT_B_BUSY)
+ BT_CONTROL(BT_B_BUSY);
BT_CONTROL(BT_CLR_WR_PTR);
BT_CONTROL(BT_SMS_ATN);
#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt)
BT_CONTROL(BT_H_BUSY);
BT_CONTROL(BT_B2H_ATN);
BT_CONTROL(BT_CLR_RD_PTR);
- for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST;
+ for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++)
+ BMC2HOST;
BT_CONTROL(BT_H_BUSY);
}
#endif
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt)
printk (" %02x", bt->write_data[i]);
printk ("\n");
}
- for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]);
+ for (i = 0; i < bt->write_count; i++)
+ HOST2BMC(bt->write_data[i]);
}
static inline int read_all_bytes(struct si_sm_data *bt)
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
bt->truncated = 1;
return 1; /* let next XACTION START clean it up */
}
- for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST;
+ for (i = 1; i <= bt->read_count; i++)
+ bt->read_data[i] = BMC2HOST;
bt->read_count++; /* account for the length byte */
if (bt_debug & BT_DEBUG_MSG) {
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
return 1;
- if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: "
+ if (bt_debug & BT_DEBUG_MSG)
+ printk(KERN_WARNING "BT: bad packet: "
"want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
bt->write_data[1], bt->write_data[2], bt->write_data[3],
bt->read_data[1], bt->read_data[2], bt->read_data[3]);
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
time);
bt->last_state = bt->state;
- if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED;
+ if (bt->state == BT_STATE_HOSED)
+ return SI_SM_HOSED;
if (bt->state != BT_STATE_IDLE) { /* do timeout test */
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
/* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
(noticed in ipmi_smic_sm.c January 2004) */
- if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100;
+ if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
+ time = 100;
bt->timeout -= time;
if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
error_recovery(bt, "timed out");
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
BT_CONTROL(BT_H_BUSY);
break;
}
- if (status & BT_B2H_ATN) break;
+ if (status & BT_B2H_ATN)
+ break;
bt->state = BT_STATE_WRITE_BYTES;
return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
case BT_STATE_WRITE_BYTES:
- if (status & (BT_B_BUSY | BT_H2B_ATN)) break;
+ if (status & (BT_B_BUSY | BT_H2B_ATN))
+ break;
BT_CONTROL(BT_CLR_WR_PTR);
write_all_bytes(bt);
BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
- if (status & (BT_H2B_ATN | BT_B_BUSY)) break;
+ if (status & (BT_H2B_ATN | BT_B_BUSY))
+ break;
bt->state = BT_STATE_B2H_WAIT;
/* fall through with status */
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
case BT_STATE_B2H_WAIT:
- if (!(status & BT_B2H_ATN)) break;
+ if (!(status & BT_B2H_ATN))
+ break;
/* Assume ordered, uncached writes: no need to wait */
- if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */
+ if (!(status & BT_H_BUSY))
+ BT_CONTROL(BT_H_BUSY); /* set */
BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */
BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */
i = read_all_bytes(bt);
BT_CONTROL(BT_H_BUSY); /* clear */
- if (!i) break; /* Try this state again */
+ if (!i) /* Try this state again */
+ break;
bt->state = BT_STATE_READ_END;
return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
#ifdef MAKE_THIS_TRUE_IF_NECESSARY
- if (status & BT_H_BUSY) break;
+ if (status & BT_H_BUSY)
+ break;
#endif
bt->seq++;
bt->state = BT_STATE_IDLE;
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
break;
case BT_STATE_RESET3:
- if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY;
+ if (bt->timeout > 0)
+ return SI_SM_CALL_WITH_DELAY;
bt->state = BT_STATE_RESTART; /* printk in debug modes */
break;
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt)
but that's what you get from reading a bogus address, so we
test that first. The calling routine uses negative logic. */
- if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1;
+ if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
+ return 1;
reset_flags(bt);
return 0;
}
@@ -501,7 +521,6 @@ static int bt_size(void)
struct si_sm_handlers bt_smi_handlers =
{
- .version = IPMI_BT_VERSION,
.init_data = bt_init_data,
.start_transaction = bt_start_transaction,
.get_result = bt_get_result,
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index e0a53570fea1..7c0684deea06 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -47,8 +47,6 @@
#include <linux/device.h>
#include <linux/compat.h>
-#define IPMI_DEVINTF_VERSION "v33"
-
struct ipmi_file_private
{
ipmi_user_t user;
@@ -411,6 +409,7 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
+ /* The next four are legacy, not per-channel. */
case IPMICTL_SET_MY_ADDRESS_CMD:
{
unsigned int val;
@@ -420,22 +419,25 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
- ipmi_set_my_address(priv->user, val);
- rv = 0;
+ rv = ipmi_set_my_address(priv->user, 0, val);
break;
}
case IPMICTL_GET_MY_ADDRESS_CMD:
{
- unsigned int val;
+ unsigned int val;
+ unsigned char rval;
+
+ rv = ipmi_get_my_address(priv->user, 0, &rval);
+ if (rv)
+ break;
- val = ipmi_get_my_address(priv->user);
+ val = rval;
if (copy_to_user(arg, &val, sizeof(val))) {
rv = -EFAULT;
break;
}
- rv = 0;
break;
}
@@ -448,24 +450,94 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
- ipmi_set_my_LUN(priv->user, val);
- rv = 0;
+ rv = ipmi_set_my_LUN(priv->user, 0, val);
break;
}
case IPMICTL_GET_MY_LUN_CMD:
{
- unsigned int val;
+ unsigned int val;
+ unsigned char rval;
- val = ipmi_get_my_LUN(priv->user);
+ rv = ipmi_get_my_LUN(priv->user, 0, &rval);
+ if (rv)
+ break;
+
+ val = rval;
+
+ if (copy_to_user(arg, &val, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+ break;
+ }
+
+ case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ return ipmi_set_my_address(priv->user, val.channel, val.value);
+ break;
+ }
+
+ case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
+ if (rv)
+ break;
+
+ if (copy_to_user(arg, &val, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+ break;
+ }
+
+ case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
+ break;
+ }
+
+ case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
+ {
+ struct ipmi_channel_lun_address_set val;
+
+ if (copy_from_user(&val, arg, sizeof(val))) {
+ rv = -EFAULT;
+ break;
+ }
+
+ rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
+ if (rv)
+ break;
if (copy_to_user(arg, &val, sizeof(val))) {
rv = -EFAULT;
break;
}
- rv = 0;
break;
}
+
case IPMICTL_SET_TIMING_PARMS_CMD:
{
struct ipmi_timing_parms parms;
@@ -663,7 +735,8 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
case COMPAT_IPMICTL_RECEIVE_MSG:
case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
{
- struct ipmi_recv *precv64, recv64;
+ struct ipmi_recv __user *precv64;
+ struct ipmi_recv recv64;
if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
return -EFAULT;
@@ -676,7 +749,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
? IPMICTL_RECEIVE_MSG
: IPMICTL_RECEIVE_MSG_TRUNC),
- (long) precv64);
+ (unsigned long) precv64);
if (rc != 0)
return rc;
@@ -725,7 +798,7 @@ static void ipmi_new_smi(int if_num)
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
- class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
+ class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
@@ -748,8 +821,7 @@ static __init int init_ipmi_devintf(void)
if (ipmi_major < 0)
return -EINVAL;
- printk(KERN_INFO "ipmi device interface version "
- IPMI_DEVINTF_VERSION "\n");
+ printk(KERN_INFO "ipmi device interface\n");
ipmi_class = class_create(THIS_MODULE, "ipmi");
if (IS_ERR(ipmi_class)) {
@@ -792,3 +864,5 @@ static __exit void cleanup_ipmi(void)
module_exit(cleanup_ipmi);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index 48cce24329be..d21853a594a3 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -42,8 +42,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_KCS_VERSION "v33"
-
/* Set this if you want a printout of why the state machine was hosed
when it gets hosed. */
#define DEBUG_HOSED_REASON
@@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs)
struct si_sm_handlers kcs_smi_handlers =
{
- .version = IPMI_KCS_VERSION,
.init_data = init_kcs_data,
.start_transaction = start_kcs_transaction,
.get_result = get_kcs_result,
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e16c13fe698d..32fa82c78c73 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -47,7 +47,8 @@
#include <linux/proc_fs.h>
#define PFX "IPMI message handler: "
-#define IPMI_MSGHANDLER_VERSION "v33"
+
+#define IPMI_DRIVER_VERSION "36.0"
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
@@ -116,7 +117,7 @@ struct seq_table
do { \
seq = ((msgid >> 26) & 0x3f); \
seqid = (msgid & 0x3fffff); \
- } while(0)
+ } while (0)
#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
@@ -124,6 +125,14 @@ struct ipmi_channel
{
unsigned char medium;
unsigned char protocol;
+
+ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
+ but may be changed by the user. */
+ unsigned char address;
+
+ /* My LUN. This should generally stay the SMS LUN, but just in
+ case... */
+ unsigned char lun;
};
#ifdef CONFIG_PROC_FS
@@ -135,7 +144,7 @@ struct ipmi_proc_entry
#endif
#define IPMI_IPMB_NUM_SEQ 64
-#define IPMI_MAX_CHANNELS 8
+#define IPMI_MAX_CHANNELS 16
struct ipmi_smi
{
/* What interface number are we? */
@@ -193,20 +202,6 @@ struct ipmi_smi
struct list_head waiting_events;
unsigned int waiting_events_count; /* How many events in queue? */
- /* This will be non-null if someone registers to receive all
- IPMI commands (this is for interface emulation). There
- may not be any things in the cmd_rcvrs list above when
- this is registered. */
- ipmi_user_t all_cmd_rcvr;
-
- /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
- but may be changed by the user. */
- unsigned char my_address;
-
- /* My LUN. This should generally stay the SMS LUN, but just in
- case... */
- unsigned char my_lun;
-
/* The event receiver for my BMC, only really used at panic
shutdown as a place to store this. */
unsigned char event_receiver;
@@ -218,7 +213,7 @@ struct ipmi_smi
interface comes in with a NULL user, call this routine with
it. Note that the message will still be freed by the
caller. This only works on the system interface. */
- void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
+ void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);
/* When we are scanning the channels for an SMI, this will
tell which channel we are scanning. */
@@ -325,7 +320,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
down_read(&interfaces_sem);
down_write(&smi_watchers_sem);
list_add(&(watcher->link), &smi_watchers);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] != NULL) {
watcher->new_smi(i);
}
@@ -458,7 +453,27 @@ unsigned int ipmi_addr_length(int addr_type)
static void deliver_response(struct ipmi_recv_msg *msg)
{
- msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
+ if (! msg->user) {
+ ipmi_smi_t intf = msg->user_msg_data;
+ unsigned long flags;
+
+ /* Special handling for NULL users. */
+ if (intf->null_user_handler) {
+ intf->null_user_handler(intf, msg);
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->handled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
+ } else {
+ /* No handler, so give up. */
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->unhandled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
+ }
+ ipmi_free_recv_msg(msg);
+ } else {
+ msg->user->handler->ipmi_recv_hndl(msg,
+ msg->user->handler_data);
+ }
}
/* Find the next sequence number not being used and add the given
@@ -475,9 +490,9 @@ static int intf_next_seq(ipmi_smi_t intf,
int rv = 0;
unsigned int i;
- for (i=intf->curr_seq;
+ for (i = intf->curr_seq;
(i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
- i=(i+1)%IPMI_IPMB_NUM_SEQ)
+ i = (i+1)%IPMI_IPMB_NUM_SEQ)
{
if (! intf->seq_table[i].inuse)
break;
@@ -712,7 +727,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user)
/* Remove the user from the interfaces sequence table. */
spin_lock_irqsave(&(user->intf->seq_lock), flags);
- for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
if (user->intf->seq_table[i].inuse
&& (user->intf->seq_table[i].recv_msg->user == user))
{
@@ -766,26 +781,44 @@ void ipmi_get_version(ipmi_user_t user,
*minor = user->intf->version_minor;
}
-void ipmi_set_my_address(ipmi_user_t user,
- unsigned char address)
+int ipmi_set_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char address)
{
- user->intf->my_address = address;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ user->intf->channels[channel].address = address;
+ return 0;
}
-unsigned char ipmi_get_my_address(ipmi_user_t user)
+int ipmi_get_my_address(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *address)
{
- return user->intf->my_address;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *address = user->intf->channels[channel].address;
+ return 0;
}
-void ipmi_set_my_LUN(ipmi_user_t user,
- unsigned char LUN)
+int ipmi_set_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char LUN)
{
- user->intf->my_lun = LUN & 0x3;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ user->intf->channels[channel].lun = LUN & 0x3;
+ return 0;
}
-unsigned char ipmi_get_my_LUN(ipmi_user_t user)
+int ipmi_get_my_LUN(ipmi_user_t user,
+ unsigned int channel,
+ unsigned char *address)
{
- return user->intf->my_lun;
+ if (channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *address = user->intf->channels[channel].lun;
+ return 0;
}
int ipmi_set_gets_events(ipmi_user_t user, int val)
@@ -828,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t user,
read_lock(&(user->intf->users_lock));
write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
- if (user->intf->all_cmd_rcvr != NULL) {
- rv = -EBUSY;
- goto out_unlock;
- }
-
/* Make sure the command/netfn is not already registered. */
list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {
if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
@@ -847,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
rcvr->user = user;
list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
}
- out_unlock:
+
write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
read_unlock(&(user->intf->users_lock));
@@ -1213,7 +1241,7 @@ static inline int i_ipmi_request(ipmi_user_t user,
unsigned char ipmb_seq;
long seqid;
- if (addr->channel > IPMI_NUM_CHANNELS) {
+ if (addr->channel >= IPMI_NUM_CHANNELS) {
spin_lock_irqsave(&intf->counter_lock, flags);
intf->sent_invalid_commands++;
spin_unlock_irqrestore(&intf->counter_lock, flags);
@@ -1331,7 +1359,7 @@ static inline int i_ipmi_request(ipmi_user_t user,
#ifdef DEBUG_MSGING
{
int m;
- for (m=0; m<smi_msg->data_size; m++)
+ for (m = 0; m < smi_msg->data_size; m++)
printk(" %2.2x", smi_msg->data[m]);
printk("\n");
}
@@ -1346,6 +1374,18 @@ static inline int i_ipmi_request(ipmi_user_t user,
return rv;
}
+static int check_addr(ipmi_smi_t intf,
+ struct ipmi_addr *addr,
+ unsigned char *saddr,
+ unsigned char *lun)
+{
+ if (addr->channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
+ *lun = intf->channels[addr->channel].lun;
+ *saddr = intf->channels[addr->channel].address;
+ return 0;
+}
+
int ipmi_request_settime(ipmi_user_t user,
struct ipmi_addr *addr,
long msgid,
@@ -1355,6 +1395,14 @@ int ipmi_request_settime(ipmi_user_t user,
int retries,
unsigned int retry_time_ms)
{
+ unsigned char saddr, lun;
+ int rv;
+
+ if (! user)
+ return -EINVAL;
+ rv = check_addr(user->intf, addr, &saddr, &lun);
+ if (rv)
+ return rv;
return i_ipmi_request(user,
user->intf,
addr,
@@ -1363,8 +1411,8 @@ int ipmi_request_settime(ipmi_user_t user,
user_msg_data,
NULL, NULL,
priority,
- user->intf->my_address,
- user->intf->my_lun,
+ saddr,
+ lun,
retries,
retry_time_ms);
}
@@ -1378,6 +1426,14 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
struct ipmi_recv_msg *supplied_recv,
int priority)
{
+ unsigned char saddr, lun;
+ int rv;
+
+ if (! user)
+ return -EINVAL;
+ rv = check_addr(user->intf, addr, &saddr, &lun);
+ if (rv)
+ return rv;
return i_ipmi_request(user,
user->intf,
addr,
@@ -1387,8 +1443,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
supplied_smi,
supplied_recv,
priority,
- user->intf->my_address,
- user->intf->my_lun,
+ saddr,
+ lun,
-1, 0);
}
@@ -1397,8 +1453,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off,
{
char *out = (char *) page;
ipmi_smi_t intf = data;
+ int i;
+ int rv= 0;
- return sprintf(out, "%x\n", intf->my_address);
+ for (i = 0; i < IPMI_MAX_CHANNELS; i++)
+ rv += sprintf(out+rv, "%x ", intf->channels[i].address);
+ out[rv-1] = '\n'; /* Replace the final space with a newline */
+ out[rv] = '\0';
+ rv++;
+ return rv;
}
static int version_file_read_proc(char *page, char **start, off_t off,
@@ -1588,29 +1651,30 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan)
(struct ipmi_addr *) &si,
0,
&msg,
- NULL,
+ intf,
NULL,
NULL,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
-1, 0);
}
static void
-channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
int rv = 0;
int chan;
- if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
{
/* It's the one we want */
- if (msg->rsp[2] != 0) {
+ if (msg->msg.data[0] != 0) {
/* Got an error from the channel, just go on. */
- if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {
+ if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
/* If the MC does not support this
command, that is legal. We just
assume it has one IPMB at channel
@@ -1627,13 +1691,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
}
goto next_channel;
}
- if (msg->rsp_size < 6) {
+ if (msg->msg.data_len < 4) {
/* Message not big enough, just go on. */
goto next_channel;
}
chan = intf->curr_channel;
- intf->channels[chan].medium = msg->rsp[4] & 0x7f;
- intf->channels[chan].protocol = msg->rsp[5] & 0x1f;
+ intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
+ intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
next_channel:
intf->curr_channel++;
@@ -1691,22 +1755,24 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
rv = -ENOMEM;
down_write(&interfaces_sem);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == NULL) {
new_intf->intf_num = i;
new_intf->version_major = version_major;
new_intf->version_minor = version_minor;
- if (slave_addr == 0)
- new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
- else
- new_intf->my_address = slave_addr;
- new_intf->my_lun = 2; /* the SMS LUN. */
+ for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
+ new_intf->channels[j].address
+ = IPMI_BMC_SLAVE_ADDR;
+ new_intf->channels[j].lun = 2;
+ }
+ if (slave_addr != 0)
+ new_intf->channels[0].address = slave_addr;
rwlock_init(&(new_intf->users_lock));
INIT_LIST_HEAD(&(new_intf->users));
new_intf->handlers = handlers;
new_intf->send_info = send_info;
spin_lock_init(&(new_intf->seq_lock));
- for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
new_intf->seq_table[j].inuse = 0;
new_intf->seq_table[j].seqid = 0;
}
@@ -1722,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
rwlock_init(&(new_intf->cmd_rcvr_lock));
init_waitqueue_head(&new_intf->waitq);
INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
- new_intf->all_cmd_rcvr = NULL;
spin_lock_init(&(new_intf->counter_lock));
@@ -1814,7 +1879,7 @@ static void clean_up_interface_data(ipmi_smi_t intf)
free_recv_msg_list(&(intf->waiting_events));
free_cmd_rcvr_list(&(intf->cmd_rcvrs));
- for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
if ((intf->seq_table[i].inuse)
&& (intf->seq_table[i].recv_msg))
{
@@ -1833,7 +1898,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
down_write(&interfaces_sem);
if (list_empty(&(intf->users)))
{
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == intf) {
remove_proc_entries(intf);
spin_lock_irqsave(&interfaces_lock, flags);
@@ -1960,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
read_lock(&(intf->cmd_rcvr_lock));
- if (intf->all_cmd_rcvr) {
- user = intf->all_cmd_rcvr;
- } else {
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
+ /* Find the command/netfn. */
+ list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+ user = rcvr->user;
+ break;
}
}
read_unlock(&(intf->cmd_rcvr_lock));
@@ -1985,7 +2046,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
msg->data[3] = msg->rsp[6];
msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
- msg->data[6] = intf->my_address;
+ msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
/* rqseq/lun */
msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
msg->data[8] = msg->rsp[8]; /* cmd */
@@ -1997,7 +2058,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
{
int m;
printk("Invalid command:");
- for (m=0; m<msg->data_size; m++)
+ for (m = 0; m < msg->data_size; m++)
printk(" %2.2x", msg->data[m]);
printk("\n");
}
@@ -2145,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
read_lock(&(intf->cmd_rcvr_lock));
- if (intf->all_cmd_rcvr) {
- user = intf->all_cmd_rcvr;
- } else {
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
+ /* Find the command/netfn. */
+ list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+ user = rcvr->user;
+ break;
}
}
read_unlock(&(intf->cmd_rcvr_lock));
@@ -2330,6 +2387,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
unsigned long flags;
recv_msg = (struct ipmi_recv_msg *) msg->user_data;
+ if (recv_msg == NULL)
+ {
+ printk(KERN_WARNING"IPMI message received with no owner. This\n"
+ "could be because of a malformed message, or\n"
+ "because of a hardware error. Contact your\n"
+ "hardware vender for assistance\n");
+ return 0;
+ }
/* Make sure the user still exists. */
list_for_each_entry(user, &(intf->users), link) {
@@ -2340,19 +2405,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
}
}
- if (!found) {
- /* Special handling for NULL users. */
- if (!recv_msg->user && intf->null_user_handler){
- intf->null_user_handler(intf, msg);
- spin_lock_irqsave(&intf->counter_lock, flags);
- intf->handled_local_responses++;
- spin_unlock_irqrestore(&intf->counter_lock, flags);
- }else{
- /* The user for the message went away, so give up. */
- spin_lock_irqsave(&intf->counter_lock, flags);
- intf->unhandled_local_responses++;
- spin_unlock_irqrestore(&intf->counter_lock, flags);
- }
+ if ((! found) && recv_msg->user) {
+ /* The user for the message went away, so give up. */
+ spin_lock_irqsave(&intf->counter_lock, flags);
+ intf->unhandled_local_responses++;
+ spin_unlock_irqrestore(&intf->counter_lock, flags);
ipmi_free_recv_msg(recv_msg);
} else {
struct ipmi_system_interface_addr *smi_addr;
@@ -2392,7 +2449,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
#ifdef DEBUG_MSGING
int m;
printk("Recv:");
- for (m=0; m<msg->rsp_size; m++)
+ for (m = 0; m < msg->rsp_size; m++)
printk(" %2.2x", msg->rsp[m]);
printk("\n");
#endif
@@ -2563,7 +2620,7 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
if (!list_empty(&(intf->waiting_msgs))) {
list_add_tail(&(msg->link), &(intf->waiting_msgs));
- spin_unlock(&(intf->waiting_msgs_lock));
+ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
goto out_unlock;
}
spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
@@ -2572,9 +2629,9 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
if (rv > 0) {
/* Could not handle the message now, just add it to a
list to handle later. */
- spin_lock(&(intf->waiting_msgs_lock));
+ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
list_add_tail(&(msg->link), &(intf->waiting_msgs));
- spin_unlock(&(intf->waiting_msgs_lock));
+ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
} else if (rv == 0) {
ipmi_free_smi_msg(msg);
}
@@ -2626,7 +2683,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
{
int m;
printk("Resend: ");
- for (m=0; m<smi_msg->data_size; m++)
+ for (m = 0; m < smi_msg->data_size; m++)
printk(" %2.2x", smi_msg->data[m]);
printk("\n");
}
@@ -2647,7 +2704,7 @@ ipmi_timeout_handler(long timeout_period)
INIT_LIST_HEAD(&timeouts);
spin_lock(&interfaces_lock);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2672,7 +2729,7 @@ ipmi_timeout_handler(long timeout_period)
have timed out, putting them in the timeouts
list. */
spin_lock_irqsave(&(intf->seq_lock), flags);
- for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
struct seq_table *ent = &(intf->seq_table[j]);
if (!ent->inuse)
continue;
@@ -2712,7 +2769,7 @@ ipmi_timeout_handler(long timeout_period)
spin_unlock(&intf->counter_lock);
smi_msg = smi_from_recv_msg(intf,
ent->recv_msg, j, ent->seqid);
- if(!smi_msg)
+ if (! smi_msg)
continue;
spin_unlock_irqrestore(&(intf->seq_lock),flags);
@@ -2743,7 +2800,7 @@ static void ipmi_request_event(void)
int i;
spin_lock(&interfaces_lock);
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2838,28 +2895,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
}
#ifdef CONFIG_IPMI_PANIC_STRING
-static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
- if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
- && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD)
+ && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
{
/* A get event receiver command, save it. */
- intf->event_receiver = msg->rsp[3];
- intf->event_receiver_lun = msg->rsp[4] & 0x3;
+ intf->event_receiver = msg->msg.data[1];
+ intf->event_receiver_lun = msg->msg.data[2] & 0x3;
}
}
-static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
- if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
- && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
- && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+ && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD)
+ && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
{
/* A get device id command, save if we are an event
receiver or generator. */
- intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
- intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
+ intf->local_sel_device = (msg->msg.data[6] >> 2) & 1;
+ intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
}
}
#endif
@@ -2903,7 +2962,7 @@ static void send_panic_events(char *str)
recv_msg.done = dummy_recv_done_handler;
/* For every registered interface, send the event. */
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -2915,12 +2974,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* Don't retry, and don't wait. */
}
@@ -2930,7 +2989,7 @@ static void send_panic_events(char *str)
if (!str)
return;
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
char *p = str;
struct ipmi_ipmb_addr *ipmb;
int j;
@@ -2961,12 +3020,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* Don't retry, and don't wait. */
if (intf->local_event_generator) {
@@ -2981,12 +3040,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* no retry, and no wait. */
}
intf->null_user_handler = NULL;
@@ -2996,7 +3055,7 @@ static void send_panic_events(char *str)
be zero, and it must not be my address. */
if (((intf->event_receiver & 1) == 0)
&& (intf->event_receiver != 0)
- && (intf->event_receiver != intf->my_address))
+ && (intf->event_receiver != intf->channels[0].address))
{
/* The event receiver is valid, send an IPMB
message. */
@@ -3031,7 +3090,7 @@ static void send_panic_events(char *str)
data[0] = 0;
data[1] = 0;
data[2] = 0xf0; /* OEM event without timestamp. */
- data[3] = intf->my_address;
+ data[3] = intf->channels[0].address;
data[4] = j++; /* sequence # */
/* Always give 11 bytes, so strncpy will fill
it with zeroes for me. */
@@ -3043,12 +3102,12 @@ static void send_panic_events(char *str)
&addr,
0,
&msg,
- NULL,
+ intf,
&smi_msg,
&recv_msg,
0,
- intf->my_address,
- intf->my_lun,
+ intf->channels[0].address,
+ intf->channels[0].lun,
0, 1); /* no retry, and no wait. */
}
}
@@ -3070,7 +3129,7 @@ static int panic_event(struct notifier_block *this,
has_paniced = 1;
/* For every registered interface, set it to run to completion. */
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
if (intf == NULL)
continue;
@@ -3099,9 +3158,9 @@ static int ipmi_init_msghandler(void)
return 0;
printk(KERN_INFO "ipmi message handler version "
- IPMI_MSGHANDLER_VERSION "\n");
+ IPMI_DRIVER_VERSION "\n");
- for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
ipmi_interfaces[i] = NULL;
}
@@ -3171,6 +3230,9 @@ module_exit(cleanup_ipmi);
module_init(ipmi_init_msghandler_mod);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface.");
+MODULE_VERSION(IPMI_DRIVER_VERSION);
EXPORT_SYMBOL(ipmi_create_user);
EXPORT_SYMBOL(ipmi_destroy_user);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index f951c30236c9..f66947722e12 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -42,7 +42,6 @@
#include <linux/ipmi_smi.h>
#define PFX "IPMI poweroff: "
-#define IPMI_POWEROFF_VERSION "v33"
/* Where to we insert our poweroff function? */
extern void (*pm_power_off)(void);
@@ -53,16 +52,17 @@ extern void (*pm_power_off)(void);
#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
/* the IPMI data command */
-static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+static int poweroff_powercycle;
/* parameter definition to allow user to flag power cycle */
-module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
-MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+module_param(poweroff_powercycle, int, 0644);
+MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
/* Stuff from the get device id command. */
static unsigned int mfg_id;
static unsigned int prod_id;
static unsigned char capabilities;
+static unsigned char ipmi_version;
/* We use our own messages for this operation, we don't let the system
allocate them, since we may be in a panic situation. The whole
@@ -338,6 +338,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
}
/*
+ * ipmi_dell_chassis_detect()
+ * Dell systems with IPMI < 1.5 don't set the chassis capability bit
+ * but they can handle a chassis poweroff or powercycle command.
+ */
+
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static int ipmi_dell_chassis_detect (ipmi_user_t user)
+{
+ const char ipmi_version_major = ipmi_version & 0xF;
+ const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
+ const char mfr[3]=DELL_IANA_MFR_ID;
+ if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
+ ipmi_version_major <= 1 &&
+ ipmi_version_minor < 5)
+ return 1;
+ return 0;
+}
+
+/*
* Standard chassis support
*/
@@ -366,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
powercyclefailed:
printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
- ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
+ (poweroff_powercycle ? "cycle" : "down"));
/*
* Power down
*/
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
- data[0] = poweroff_control;
+ if (poweroff_powercycle)
+ data[0] = IPMI_CHASSIS_POWER_CYCLE;
+ else
+ data[0] = IPMI_CHASSIS_POWER_DOWN;
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
(struct ipmi_addr *) &smi_addr,
&send_msg);
if (rv) {
- switch (poweroff_control) {
- case IPMI_CHASSIS_POWER_CYCLE:
- /* power cycle failed, default to power down */
- printk(KERN_ERR PFX "Unable to send chassis power " \
- "cycle message, IPMI error 0x%x\n", rv);
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- goto powercyclefailed;
-
- case IPMI_CHASSIS_POWER_DOWN:
- default:
- printk(KERN_ERR PFX "Unable to send chassis power " \
- "down message, IPMI error 0x%x\n", rv);
- break;
+ if (poweroff_powercycle) {
+ /* power cycle failed, default to power down */
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "cycle message, IPMI error 0x%x\n", rv);
+ poweroff_powercycle = 0;
+ goto powercyclefailed;
}
- }
- return;
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "down message, IPMI error 0x%x\n", rv);
+ }
}
@@ -414,6 +430,9 @@ static struct poweroff_function poweroff_functions[] = {
{ .platform_type = "CPI1",
.detect = ipmi_cpi1_detect,
.poweroff_func = ipmi_poweroff_cpi1 },
+ { .platform_type = "chassis",
+ .detect = ipmi_dell_chassis_detect,
+ .poweroff_func = ipmi_poweroff_chassis },
/* Chassis should generally be last, other things should override
it. */
{ .platform_type = "chassis",
@@ -499,10 +518,11 @@ static void ipmi_po_new_smi(int if_num)
prod_id = (halt_recv_msg.msg.data[10]
| (halt_recv_msg.msg.data[11] << 8));
capabilities = halt_recv_msg.msg.data[6];
+ ipmi_version = halt_recv_msg.msg.data[5];
/* Scan for a poweroff method */
- for (i=0; i<NUM_PO_FUNCS; i++) {
+ for (i = 0; i < NUM_PO_FUNCS; i++) {
if (poweroff_functions[i].detect(ipmi_user))
goto found;
}
@@ -538,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher =
#ifdef CONFIG_PROC_FS
-/* displays properties to proc */
-static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
- poweroff_control);
-}
+#include <linux/sysctl.h>
+
+static ctl_table ipmi_table[] = {
+ { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE,
+ .procname = "poweroff_powercycle",
+ .data = &poweroff_powercycle,
+ .maxlen = sizeof(poweroff_powercycle),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec },
+ { }
+};
-/* process property writes from proc */
-static int proc_write_chassctrl(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int rv = count;
- unsigned int newval = 0;
-
- sscanf(buffer, "%d", &newval);
- switch (newval) {
- case IPMI_CHASSIS_POWER_CYCLE:
- printk(KERN_INFO PFX "power cycle is now enabled\n");
- poweroff_control = newval;
- break;
-
- case IPMI_CHASSIS_POWER_DOWN:
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- break;
-
- default:
- rv = -EINVAL;
- break;
- }
+static ctl_table ipmi_dir_table[] = {
+ { .ctl_name = DEV_IPMI,
+ .procname = "ipmi",
+ .mode = 0555,
+ .child = ipmi_table },
+ { }
+};
- return rv;
-}
+static ctl_table ipmi_root_table[] = {
+ { .ctl_name = CTL_DEV,
+ .procname = "dev",
+ .mode = 0555,
+ .child = ipmi_dir_table },
+ { }
+};
+
+static struct ctl_table_header *ipmi_table_header;
#endif /* CONFIG_PROC_FS */
/*
@@ -578,42 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer,
*/
static int ipmi_poweroff_init (void)
{
- int rv;
- struct proc_dir_entry *file;
+ int rv;
printk ("Copyright (C) 2004 MontaVista Software -"
- " IPMI Powerdown via sys_reboot version "
- IPMI_POWEROFF_VERSION ".\n");
-
- switch (poweroff_control) {
- case IPMI_CHASSIS_POWER_CYCLE:
- printk(KERN_INFO PFX "Power cycle is enabled.\n");
- break;
-
- case IPMI_CHASSIS_POWER_DOWN:
- default:
- poweroff_control = IPMI_CHASSIS_POWER_DOWN;
- break;
+ " IPMI Powerdown via sys_reboot.\n");
+
+ if (poweroff_powercycle)
+ printk(KERN_INFO PFX "Power cycle is enabled.\n");
+
+#ifdef CONFIG_PROC_FS
+ ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);
+ if (!ipmi_table_header) {
+ printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
+ rv = -ENOMEM;
+ goto out_err;
}
+#endif
+#ifdef CONFIG_PROC_FS
rv = ipmi_smi_watcher_register(&smi_watcher);
+#endif
if (rv) {
+ unregister_sysctl_table(ipmi_table_header);
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
goto out_err;
}
-#ifdef CONFIG_PROC_FS
- file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
- if (!file) {
- printk(KERN_ERR PFX "Unable to create proc power control\n");
- } else {
- file->nlink = 1;
- file->read_proc = proc_read_chassctrl;
- file->write_proc = proc_write_chassctrl;
- file->owner = THIS_MODULE;
- }
-#endif
-
out_err:
return rv;
}
@@ -624,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void)
int rv;
#ifdef CONFIG_PROC_FS
- remove_proc_entry("poweroff_control", proc_ipmi_root);
+ unregister_sysctl_table(ipmi_table_header);
#endif
ipmi_smi_watcher_unregister(&smi_watcher);
@@ -642,3 +648,5 @@ module_exit(ipmi_poweroff_cleanup);
module_init(ipmi_poweroff_init);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a44b97304e95..b6e5cbfb09f8 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -61,11 +61,11 @@
# endif
static inline void add_usec_to_timer(struct timer_list *t, long v)
{
- t->sub_expires += nsec_to_arch_cycle(v * 1000);
- while (t->sub_expires >= arch_cycles_per_jiffy)
+ t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000);
+ while (t->arch_cycle_expires >= arch_cycles_per_jiffy)
{
t->expires++;
- t->sub_expires -= arch_cycles_per_jiffy;
+ t->arch_cycle_expires -= arch_cycles_per_jiffy;
}
}
#endif
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v)
#include <asm/io.h>
#include "ipmi_si_sm.h"
#include <linux/init.h>
-
-#define IPMI_SI_VERSION "v33"
+#include <linux/dmi.h>
/* Measure times between events in the driver. */
#undef DEBUG_TIMING
@@ -109,6 +108,21 @@ enum si_type {
SI_KCS, SI_SMIC, SI_BT
};
+struct ipmi_device_id {
+ unsigned char device_id;
+ unsigned char device_revision;
+ unsigned char firmware_revision_1;
+ unsigned char firmware_revision_2;
+ unsigned char ipmi_version;
+ unsigned char additional_device_support;
+ unsigned char manufacturer_id[3];
+ unsigned char product_id[2];
+ unsigned char aux_firmware_revision[4];
+} __attribute__((packed));
+
+#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
+#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
+
struct smi_info
{
ipmi_smi_t intf;
@@ -131,12 +145,24 @@ struct smi_info
void (*irq_cleanup)(struct smi_info *info);
unsigned int io_size;
+ /* Per-OEM handler, called from handle_flags().
+ Returns 1 when handle_flags() needs to be re-run
+ or 0 indicating it set si_state itself.
+ */
+ int (*oem_data_avail_handler)(struct smi_info *smi_info);
+
/* Flags from the last GET_MSG_FLAGS command, used when an ATTN
is set to hold the flags until we are done handling everything
from the flags. */
#define RECEIVE_MSG_AVAIL 0x01
#define EVENT_MSG_BUFFER_FULL 0x02
#define WDT_PRE_TIMEOUT_INT 0x08
+#define OEM0_DATA_AVAIL 0x20
+#define OEM1_DATA_AVAIL 0x40
+#define OEM2_DATA_AVAIL 0x80
+#define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \
+ OEM1_DATA_AVAIL | \
+ OEM2_DATA_AVAIL)
unsigned char msg_flags;
/* If set to true, this will request events the next time the
@@ -175,11 +201,7 @@ struct smi_info
interrupts. */
int interrupt_disabled;
- unsigned char ipmi_si_dev_rev;
- unsigned char ipmi_si_fw_rev_major;
- unsigned char ipmi_si_fw_rev_minor;
- unsigned char ipmi_version_major;
- unsigned char ipmi_version_minor;
+ struct ipmi_device_id device_id;
/* Slave address, could be reported from DMI. */
unsigned char slave_addr;
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
entry = smi_info->xmit_msgs.next;
}
- if (!entry) {
+ if (! entry) {
smi_info->curr_msg = NULL;
rv = SI_SM_IDLE;
} else {
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info)
memory, we will re-enable the interrupt. */
static inline void disable_si_irq(struct smi_info *smi_info)
{
- if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+ if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
disable_irq_nosync(smi_info->irq);
smi_info->interrupt_disabled = 1;
}
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info)
static void handle_flags(struct smi_info *smi_info)
{
+ retry:
if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
/* Watchdog pre-timeout */
spin_lock(&smi_info->count_lock);
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
/* Messages available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (!smi_info->curr_msg) {
+ if (! smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
/* Events available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (!smi_info->curr_msg) {
+ if (! smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info)
smi_info->curr_msg->data,
smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_EVENTS;
+ } else if (smi_info->msg_flags & OEM_DATA_AVAIL) {
+ if (smi_info->oem_data_avail_handler)
+ if (smi_info->oem_data_avail_handler(smi_info))
+ goto retry;
} else {
smi_info->si_state = SI_NORMAL;
}
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
#endif
switch (smi_info->si_state) {
case SI_NORMAL:
- if (!smi_info->curr_msg)
+ if (! smi_info->curr_msg)
break;
smi_info->curr_msg->rsp_size
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info)
#if defined(CONFIG_HIGH_RES_TIMERS)
unsigned long flags;
unsigned long jiffies_now;
+ unsigned long seq;
if (del_timer(&(smi_info->si_timer))) {
/* If we don't delete the timer, then it will go off
immediately, anyway. So we only process if we
actually delete the timer. */
- /* We already have irqsave on, so no need for it
- here. */
- read_lock(&xtime_lock);
- jiffies_now = jiffies;
- smi_info->si_timer.expires = jiffies_now;
- smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now);
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ jiffies_now = jiffies;
+ smi_info->si_timer.expires = jiffies_now;
+ smi_info->si_timer.arch_cycle_expires
+ = get_arch_cycles(jiffies_now);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data)
/* If the state machine asks for a short delay, then shorten
the timer timeout. */
if (smi_result == SI_SM_CALL_WITH_DELAY) {
+#if defined(CONFIG_HIGH_RES_TIMERS)
+ unsigned long seq;
+#endif
spin_lock_irqsave(&smi_info->count_lock, flags);
smi_info->short_timeouts++;
spin_unlock_irqrestore(&smi_info->count_lock, flags);
#if defined(CONFIG_HIGH_RES_TIMERS)
- read_lock(&xtime_lock);
- smi_info->si_timer.expires = jiffies;
- smi_info->si_timer.sub_expires
- = get_arch_cycles(smi_info->si_timer.expires);
- read_unlock(&xtime_lock);
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ smi_info->si_timer.expires = jiffies;
+ smi_info->si_timer.arch_cycle_expires
+ = get_arch_cycles(smi_info->si_timer.expires);
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
#else
smi_info->si_timer.expires = jiffies + 1;
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data)
spin_unlock_irqrestore(&smi_info->count_lock, flags);
smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
#if defined(CONFIG_HIGH_RES_TIMERS)
- smi_info->si_timer.sub_expires = 0;
+ smi_info->si_timer.arch_cycle_expires = 0;
#endif
}
@@ -986,7 +1019,7 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
#define IPMI_MEM_ADDR_SPACE 1
#define IPMI_IO_ADDR_SPACE 2
-#if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI)
+#if defined(CONFIG_ACPI) || defined(CONFIG_X86) || defined(CONFIG_PCI)
static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
{
int i;
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info)
{
int rv;
- if (!info->irq)
+ if (! info->irq)
return 0;
if (info->si_type == SI_BT) {
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info)
SA_INTERRUPT,
DEVICE_NAME,
info);
- if (!rv)
+ if (! rv)
/* Enable the interrupt in the BT interface. */
info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info)
static void std_irq_cleanup(struct smi_info *info)
{
- if (!info->irq)
+ if (! info->irq)
return;
if (info->si_type == SI_BT)
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info)
unsigned int *addr = info->io.info;
int mapsize;
- if (!addr || (!*addr))
+ if (! addr || (! *addr))
return -ENODEV;
info->io_cleanup = port_cleanup;
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
{
struct smi_info *info;
- if (!ports[intf_num])
+ if (! ports[intf_num])
return -ENODEV;
- if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
+ if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
ports[intf_num]))
return -ENODEV;
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n");
return -ENOMEM;
}
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
info->io.info = &(ports[intf_num]);
info->io.addr = NULL;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = regsizes[intf_num];
- if (!info->io.regsize)
+ if (! info->io.regsize)
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
info->irq = 0;
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info)
unsigned long *addr = info->io.info;
int mapsize;
- if (!addr || (!*addr))
+ if (! addr || (! *addr))
return -ENODEV;
info->io_cleanup = mem_cleanup;
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
{
struct smi_info *info;
- if (!addrs[intf_num])
+ if (! addrs[intf_num])
return -ENODEV;
- if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
+ if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
addrs[intf_num]))
return -ENODEV;
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n");
return -ENOMEM;
}
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
info->io.info = &addrs[intf_num];
info->io.addr = NULL;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = regsizes[intf_num];
- if (!info->io.regsize)
+ if (! info->io.regsize)
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
info->irq = 0;
@@ -1362,7 +1395,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
}
-#ifdef CONFIG_ACPI_INTERPRETER
+#ifdef CONFIG_ACPI
#include <linux/acpi.h>
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
{
acpi_status status;
- if (!info->irq)
+ if (! info->irq)
return 0;
/* FIXME - is level triggered right? */
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
static void acpi_gpe_irq_cleanup(struct smi_info *info)
{
- if (!info->irq)
+ if (! info->irq)
return;
acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe);
@@ -1484,6 +1517,9 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
char *io_type;
u8 addr_space;
+ if (acpi_disabled)
+ return -ENODEV;
+
if (acpi_failure)
return -ENODEV;
@@ -1504,10 +1540,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
addr_space = IPMI_MEM_ADDR_SPACE;
else
addr_space = IPMI_IO_ADDR_SPACE;
- if (!is_new_interface(-1, addr_space, spmi->addr.address))
+ if (! is_new_interface(-1, addr_space, spmi->addr.address))
return -ENODEV;
- if (!spmi->addr.register_bit_width) {
+ if (! spmi->addr.register_bit_width) {
acpi_failure = 1;
return -ENODEV;
}
@@ -1534,7 +1570,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
return -ENOMEM;
}
@@ -1610,22 +1646,15 @@ typedef struct dmi_ipmi_data
static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
static int dmi_data_entries;
-typedef struct dmi_header
-{
- u8 type;
- u8 length;
- u16 handle;
-} dmi_header_t;
-
-static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
+static int __init decode_dmi(struct dmi_header *dm, int intf_num)
{
- u8 __iomem *data = (u8 __iomem *)dm;
+ u8 *data = (u8 *)dm;
unsigned long base_addr;
u8 reg_spacing;
- u8 len = readb(&dm->length);
+ u8 len = dm->length;
dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- ipmi_data->type = readb(&data[4]);
+ ipmi_data->type = data[4];
memcpy(&base_addr, data+8, sizeof(unsigned long));
if (len >= 0x11) {
@@ -1640,12 +1669,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
}
/* If bit 4 of byte 0x10 is set, then the lsb for the address
is odd. */
- ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
+ ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
- ipmi_data->irq = readb(&data[0x11]);
+ ipmi_data->irq = data[0x11];
/* The top two bits of byte 0x10 hold the register spacing. */
- reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
+ reg_spacing = (data[0x10] & 0xC0) >> 6;
switch(reg_spacing){
case 0x00: /* Byte boundaries */
ipmi_data->offset = 1;
@@ -1673,7 +1702,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
ipmi_data->offset = 1;
}
- ipmi_data->slave_addr = readb(&data[6]);
+ ipmi_data->slave_addr = data[6];
if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
dmi_data_entries++;
@@ -1685,94 +1714,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
return -1;
}
-static int dmi_table(u32 base, int len, int num)
+static void __init dmi_find_bmc(void)
{
- u8 __iomem *buf;
- struct dmi_header __iomem *dm;
- u8 __iomem *data;
- int i=1;
- int status=-1;
+ struct dmi_device *dev = NULL;
int intf_num = 0;
- buf = ioremap(base, len);
- if(buf==NULL)
- return -1;
-
- data = buf;
-
- while(i<num && (data - buf) < len)
- {
- dm=(dmi_header_t __iomem *)data;
-
- if((data-buf+readb(&dm->length)) >= len)
- break;
-
- if (readb(&dm->type) == 38) {
- if (decode_dmi(dm, intf_num) == 0) {
- intf_num++;
- if (intf_num >= SI_MAX_DRIVERS)
- break;
- }
- }
-
- data+=readb(&dm->length);
- while((data-buf) < len && (readb(data)||readb(data+1)))
- data++;
- data+=2;
- i++;
- }
- iounmap(buf);
-
- return status;
-}
-
-static inline int dmi_checksum(u8 *buf)
-{
- u8 sum=0;
- int a;
-
- for(a=0; a<15; a++)
- sum+=buf[a];
- return (sum==0);
-}
-
-static int dmi_decode(void)
-{
- u8 buf[15];
- u32 fp=0xF0000;
-
-#ifdef CONFIG_SIMNOW
- return -1;
-#endif
-
- while(fp < 0xFFFFF)
- {
- isa_memcpy_fromio(buf, fp, 15);
- if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
- {
- u16 num=buf[13]<<8|buf[12];
- u16 len=buf[7]<<8|buf[6];
- u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+ while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
+ if (intf_num >= SI_MAX_DRIVERS)
+ break;
- if(dmi_table(base, len, num) == 0)
- return 0;
- }
- fp+=16;
+ decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
}
-
- return -1;
}
static int try_init_smbios(int intf_num, struct smi_info **new_info)
{
- struct smi_info *info;
- dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- char *io_type;
+ struct smi_info *info;
+ dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
+ char *io_type;
if (intf_num >= dmi_data_entries)
return -ENODEV;
- switch(ipmi_data->type) {
+ switch (ipmi_data->type) {
case 0x01: /* KCS */
si_type[intf_num] = "kcs";
break;
@@ -1787,7 +1751,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n");
return -ENOMEM;
}
@@ -1811,7 +1775,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
regspacings[intf_num] = ipmi_data->offset;
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
@@ -1853,14 +1817,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
pci_smic_checked = 1;
- if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID,
- NULL)))
- ;
- else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) &&
- pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)
- fe_rmc = 1;
- else
- return -ENODEV;
+ pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL);
+ if (! pci_dev) {
+ pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL);
+ if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID))
+ fe_rmc = 1;
+ else
+ return -ENODEV;
+ }
error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr);
if (error)
@@ -1873,7 +1837,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
}
/* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */
- if (!(base_addr & 0x0001))
+ if (! (base_addr & 0x0001))
{
pci_dev_put(pci_dev);
printk(KERN_ERR
@@ -1883,17 +1847,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
}
base_addr &= 0xFFFE;
- if (!fe_rmc)
+ if (! fe_rmc)
/* Data register starts at base address + 1 in eRMC */
++base_addr;
- if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
+ if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
pci_dev_put(pci_dev);
return -ENODEV;
}
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
+ if (! info) {
pci_dev_put(pci_dev);
printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n");
return -ENOMEM;
@@ -1904,7 +1868,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
ports[intf_num] = base_addr;
info->io.info = &(ports[intf_num]);
info->io.regspacing = regspacings[intf_num];
- if (!info->io.regspacing)
+ if (! info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
@@ -1925,7 +1889,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
static int try_init_plug_and_play(int intf_num, struct smi_info **new_info)
{
#ifdef CONFIG_PCI
- if (find_pci_smic(intf_num, new_info)==0)
+ if (find_pci_smic(intf_num, new_info) == 0)
return 0;
#endif
/* Include other methods here. */
@@ -1943,7 +1907,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
int rv = 0;
resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
- if (!resp)
+ if (! resp)
return -ENOMEM;
/* Do a Get Device ID command, since it comes back with some
@@ -1956,8 +1920,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
for (;;)
{
if (smi_result == SI_SM_CALL_WITH_DELAY) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
smi_result = smi_info->handlers->event(
smi_info->si_sm, 100);
}
@@ -1992,11 +1955,8 @@ static int try_get_dev_id(struct smi_info *smi_info)
}
/* Record info from the get device id, in case we need it. */
- smi_info->ipmi_si_dev_rev = resp[4] & 0xf;
- smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f;
- smi_info->ipmi_si_fw_rev_minor = resp[6];
- smi_info->ipmi_version_major = resp[7] & 0xf;
- smi_info->ipmi_version_minor = resp[7] >> 4;
+ memcpy(&smi_info->device_id, &resp[3],
+ min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id)));
out:
kfree(resp);
@@ -2028,7 +1988,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
struct smi_info *smi = data;
out += sprintf(out, "interrupts_enabled: %d\n",
- smi->irq && !smi->interrupt_disabled);
+ smi->irq && ! smi->interrupt_disabled);
out += sprintf(out, "short_timeouts: %ld\n",
smi->short_timeouts);
out += sprintf(out, "long_timeouts: %ld\n",
@@ -2057,6 +2017,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
return (out - ((char *) page));
}
+/*
+ * oem_data_avail_to_receive_msg_avail
+ * @info - smi_info structure with msg_flags set
+ *
+ * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL
+ * Returns 1 indicating need to re-run handle_flags().
+ */
+static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
+{
+ smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) |
+ RECEIVE_MSG_AVAIL);
+ return 1;
+}
+
+/*
+ * setup_dell_poweredge_oem_data_handler
+ * @info - smi_info.device_id must be populated
+ *
+ * Systems that match, but have firmware version < 1.40 may assert
+ * OEM0_DATA_AVAIL on their own, without being told via Set Flags that
+ * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL
+ * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags
+ * as RECEIVE_MSG_AVAIL instead.
+ *
+ * As Dell has no plans to release IPMI 1.5 firmware that *ever*
+ * assert the OEM[012] bits, and if it did, the driver would have to
+ * change to handle that properly, we don't actually check for the
+ * firmware version.
+ * Device ID = 0x20 BMC on PowerEdge 8G servers
+ * Device Revision = 0x80
+ * Firmware Revision1 = 0x01 BMC version 1.40
+ * Firmware Revision2 = 0x40 BCD encoded
+ * IPMI Version = 0x51 IPMI 1.5
+ * Manufacturer ID = A2 02 00 Dell IANA
+ *
+ */
+#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20
+#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
+#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
+{
+ struct ipmi_device_id *id = &smi_info->device_id;
+ const char mfr[3]=DELL_IANA_MFR_ID;
+ if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))
+ && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID)
+ && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV)
+ && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION))
+ {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+ }
+}
+
+/*
+ * setup_oem_data_handler
+ * @info - smi_info.device_id must be filled in already
+ *
+ * Fills in smi_info.device_id.oem_data_available_handler
+ * when we know what function to use there.
+ */
+
+static void setup_oem_data_handler(struct smi_info *smi_info)
+{
+ setup_dell_poweredge_oem_data_handler(smi_info);
+}
+
/* Returns 0 if initialized, or negative on an error. */
static int init_one_smi(int intf_num, struct smi_info **smi)
{
@@ -2067,20 +2094,16 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
rv = try_init_mem(intf_num, &new_smi);
if (rv)
rv = try_init_port(intf_num, &new_smi);
-#ifdef CONFIG_ACPI_INTERPRETER
- if ((rv) && (si_trydefaults)) {
+#ifdef CONFIG_ACPI
+ if (rv && si_trydefaults)
rv = try_init_acpi(intf_num, &new_smi);
- }
#endif
#ifdef CONFIG_X86
- if ((rv) && (si_trydefaults)) {
+ if (rv && si_trydefaults)
rv = try_init_smbios(intf_num, &new_smi);
- }
#endif
- if ((rv) && (si_trydefaults)) {
+ if (rv && si_trydefaults)
rv = try_init_plug_and_play(intf_num, &new_smi);
- }
-
if (rv)
return rv;
@@ -2090,7 +2113,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->si_sm = NULL;
new_smi->handlers = NULL;
- if (!new_smi->irq_setup) {
+ if (! new_smi->irq_setup) {
new_smi->irq = irqs[intf_num];
new_smi->irq_setup = std_irq_setup;
new_smi->irq_cleanup = std_irq_cleanup;
@@ -2124,7 +2147,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Allocate the state machine's data and initialize it. */
new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
- if (!new_smi->si_sm) {
+ if (! new_smi->si_sm) {
printk(" Could not allocate state machine memory\n");
rv = -ENOMEM;
goto out_err;
@@ -2155,6 +2178,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
if (rv)
goto out_err;
+ setup_oem_data_handler(new_smi);
+
/* Try to claim any interrupts. */
new_smi->irq_setup(new_smi);
@@ -2188,8 +2213,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
rv = ipmi_register_smi(&handlers,
new_smi,
- new_smi->ipmi_version_major,
- new_smi->ipmi_version_minor,
+ ipmi_version_major(&new_smi->device_id),
+ ipmi_version_minor(&new_smi->device_id),
new_smi->slave_addr,
&(new_smi->intf));
if (rv) {
@@ -2230,10 +2255,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Wait for the timer to stop. This avoids problems with race
conditions removing the timer here. */
- while (!new_smi->timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (!new_smi->timer_stopped)
+ schedule_timeout_uninterruptible(1);
out_err:
if (new_smi->intf)
@@ -2270,7 +2293,7 @@ static __init int init_ipmi_si(void)
/* Parse out the si_type string into its components. */
str = si_type_str;
if (*str != '\0') {
- for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) {
+ for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) {
si_type[i] = str;
str = strchr(str, ',');
if (str) {
@@ -2282,22 +2305,14 @@ static __init int init_ipmi_si(void)
}
}
- printk(KERN_INFO "IPMI System Interface driver version "
- IPMI_SI_VERSION);
- if (kcs_smi_handlers.version)
- printk(", KCS version %s", kcs_smi_handlers.version);
- if (smic_smi_handlers.version)
- printk(", SMIC version %s", smic_smi_handlers.version);
- if (bt_smi_handlers.version)
- printk(", BT version %s", bt_smi_handlers.version);
- printk("\n");
+ printk(KERN_INFO "IPMI System Interface driver.\n");
#ifdef CONFIG_X86
- dmi_decode();
+ dmi_find_bmc();
#endif
rv = init_one_smi(0, &(smi_infos[pos]));
- if (rv && !ports[0] && si_trydefaults) {
+ if (rv && ! ports[0] && si_trydefaults) {
/* If we are trying defaults and the initial port is
not set, then set it. */
si_type[0] = "kcs";
@@ -2319,7 +2334,7 @@ static __init int init_ipmi_si(void)
if (rv == 0)
pos++;
- for (i=1; i < SI_MAX_PARMS; i++) {
+ for (i = 1; i < SI_MAX_PARMS; i++) {
rv = init_one_smi(i, &(smi_infos[pos]));
if (rv == 0)
pos++;
@@ -2361,17 +2376,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
/* Wait for the timer to stop. This avoids problems with race
conditions removing the timer here. */
- while (!to_clean->timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (!to_clean->timer_stopped)
+ schedule_timeout_uninterruptible(1);
/* Interrupts and timeouts are stopped, now make sure the
interface is in a clean state. */
- while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) {
+ while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
poll(to_clean);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
rv = ipmi_unregister_smi(to_clean->intf);
@@ -2392,13 +2404,15 @@ static __exit void cleanup_ipmi_si(void)
{
int i;
- if (!initialized)
+ if (! initialized)
return;
- for (i=0; i<SI_MAX_DRIVERS; i++) {
+ for (i = 0; i < SI_MAX_DRIVERS; i++) {
cleanup_one_si(smi_infos[i]);
}
}
module_exit(cleanup_ipmi_si);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces.");
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
index ae18747e670b..add2aa2732f0 100644
--- a/drivers/char/ipmi/ipmi_smic_sm.c
+++ b/drivers/char/ipmi/ipmi_smic_sm.c
@@ -46,8 +46,6 @@
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-#define IPMI_SMIC_VERSION "v33"
-
/* smic_debug is a bit-field
* SMIC_DEBUG_ENABLE - turned on for now
* SMIC_DEBUG_MSG - commands and their responses
@@ -588,7 +586,6 @@ static int smic_size(void)
struct si_sm_handlers smic_smi_handlers =
{
- .version = IPMI_SMIC_VERSION,
.init_data = init_smic_data,
.start_transaction = start_smic_transaction,
.get_result = smic_get_result,
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index d35a953961cb..2da64bf7469c 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -53,8 +53,6 @@
#define PFX "IPMI Watchdog: "
-#define IPMI_WATCHDOG_VERSION "v33"
-
/*
* The IPMI command/response information for the watchdog timer.
*/
@@ -259,7 +257,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
data[1] = 0;
WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
- if (pretimeout > 0) {
+ if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) {
WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
data[2] = pretimeout;
} else {
@@ -659,19 +657,18 @@ static ssize_t ipmi_read(struct file *file,
static int ipmi_open(struct inode *ino, struct file *filep)
{
- switch (iminor(ino))
- {
- case WATCHDOG_MINOR:
- if(test_and_set_bit(0, &ipmi_wdog_open))
+ switch (iminor(ino)) {
+ case WATCHDOG_MINOR:
+ if (test_and_set_bit(0, &ipmi_wdog_open))
return -EBUSY;
- /* Don't start the timer now, let it start on the
- first heartbeat. */
- ipmi_start_timer_on_heartbeat = 1;
- return nonseekable_open(ino, filep);
+ /* Don't start the timer now, let it start on the
+ first heartbeat. */
+ ipmi_start_timer_on_heartbeat = 1;
+ return nonseekable_open(ino, filep);
- default:
- return (-ENODEV);
+ default:
+ return (-ENODEV);
}
}
@@ -817,15 +814,19 @@ static void ipmi_register_watchdog(int ipmi_intf)
static int
ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
{
+ /* If we are not expecting a timeout, ignore it. */
+ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
+ return NOTIFY_DONE;
+
/* If no one else handled the NMI, we assume it was the IPMI
watchdog. */
- if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
+ if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {
+ /* On some machines, the heartbeat will give
+ an error and not work unless we re-enable
+ the timer. So do so. */
+ pretimeout_since_last_heartbeat = 1;
panic(PFX "pre-timeout");
-
- /* On some machines, the heartbeat will give
- an error and not work unless we re-enable
- the timer. So do so. */
- pretimeout_since_last_heartbeat = 1;
+ }
return NOTIFY_DONE;
}
@@ -924,9 +925,6 @@ static int __init ipmi_wdog_init(void)
{
int rv;
- printk(KERN_INFO PFX "driver version "
- IPMI_WATCHDOG_VERSION "\n");
-
if (strcmp(action, "reset") == 0) {
action_val = WDOG_TIMEOUT_RESET;
} else if (strcmp(action, "none") == 0) {
@@ -1011,6 +1009,8 @@ static int __init ipmi_wdog_init(void)
register_reboot_notifier(&wdog_reboot_notifier);
notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
+ printk(KERN_INFO PFX "driver initialized\n");
+
return 0;
}
@@ -1037,10 +1037,8 @@ static __exit void ipmi_unregister_watchdog(void)
/* Wait to make sure the message makes it out. The lower layer has
pointers to our buffers, we want to make sure they are done before
we release our memory. */
- while (atomic_read(&set_timeout_tofree)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while (atomic_read(&set_timeout_tofree))
+ schedule_timeout_uninterruptible(1);
/* Disconnect from IPMI. */
rv = ipmi_destroy_user(watchdog_user);
@@ -1062,3 +1060,5 @@ static void __exit ipmi_wdog_exit(void)
module_exit(ipmi_wdog_exit);
module_init(ipmi_wdog_init);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
+MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface.");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 52a073eee201..e3ddbdb85a2f 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -780,7 +780,7 @@ static struct file_operations stli_fsiomem = {
* much cheaper on host cpu than using interrupts. It turns out to
* not increase character latency by much either...
*/
-static struct timer_list stli_timerlist = TIMER_INITIALIZER(stli_poll, 0, 0);
+static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
static int stli_timeron;
@@ -5246,7 +5246,8 @@ int __init stli_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i);
- class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+ class_device_create(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i);
}
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 523fd3c8bbaa..449d029ad4f4 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -14,7 +14,7 @@
* `Sticky' modifier keys, 951006.
*
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
- *
+ *
* Modified to provide 'generic' keyboard support by Hamish Macdonald
* Merge with the m68k keyboard driver and split-off of the PC low-level
* parts by Geert Uytterhoeven, May 1997
@@ -52,7 +52,7 @@ extern void ctrl_alt_del(void);
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
* This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the keypad
+ * of PARISC machines however there is no NumLock key and everyone expects the keypad
* to be used for numbers.
*/
@@ -76,17 +76,17 @@ void compute_shiftstate(void);
k_meta, k_ascii, k_lock, k_lowercase,\
k_slock, k_dead2, k_ignore, k_ignore
-typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
+typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag, struct pt_regs *regs);
static k_handler_fn K_HANDLERS;
static k_handler_fn *k_handler[16] = { K_HANDLERS };
#define FN_HANDLERS\
- fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
- fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
- fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
- fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
- fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
+ fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
+ fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
+ fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
+ fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
+ fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs);
static fn_handler_fn FN_HANDLERS;
@@ -159,13 +159,13 @@ static int sysrq_alt;
*/
int getkeycode(unsigned int scancode)
{
- struct list_head * node;
+ struct list_head *node;
struct input_dev *dev = NULL;
- list_for_each(node,&kbd_handler.h_list) {
- struct input_handle * handle = to_handle_h(node);
- if (handle->dev->keycodesize) {
- dev = handle->dev;
+ list_for_each(node, &kbd_handler.h_list) {
+ struct input_handle *handle = to_handle_h(node);
+ if (handle->dev->keycodesize) {
+ dev = handle->dev;
break;
}
}
@@ -181,15 +181,15 @@ int getkeycode(unsigned int scancode)
int setkeycode(unsigned int scancode, unsigned int keycode)
{
- struct list_head * node;
+ struct list_head *node;
struct input_dev *dev = NULL;
unsigned int i, oldkey;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
- if (handle->dev->keycodesize) {
- dev = handle->dev;
- break;
+ if (handle->dev->keycodesize) {
+ dev = handle->dev;
+ break;
}
}
@@ -200,7 +200,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
return -EINVAL;
if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
- if (keycode >> (dev->keycodesize * 8))
+ if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
return -EINVAL;
oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -216,11 +216,11 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
}
/*
- * Making beeps and bells.
+ * Making beeps and bells.
*/
static void kd_nosound(unsigned long ignored)
{
- struct list_head * node;
+ struct list_head *node;
list_for_each(node,&kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
@@ -233,17 +233,16 @@ static void kd_nosound(unsigned long ignored)
}
}
-static struct timer_list kd_mksound_timer =
- TIMER_INITIALIZER(kd_nosound, 0, 0);
+static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
void kd_mksound(unsigned int hz, unsigned int ticks)
{
- struct list_head * node;
+ struct list_head *node;
del_timer(&kd_mksound_timer);
if (hz) {
- list_for_each_prev(node,&kbd_handler.h_list) {
+ list_for_each_prev(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
@@ -338,19 +337,19 @@ static void to_utf8(struct vc_data *vc, ushort c)
if (c < 0x80)
/* 0******* */
put_queue(vc, c);
- else if (c < 0x800) {
+ else if (c < 0x800) {
/* 110***** 10****** */
- put_queue(vc, 0xc0 | (c >> 6));
+ put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
- } else {
+ } else {
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
- }
+ }
}
-/*
+/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
* undefined, so that shiftkey release is seen
@@ -361,7 +360,7 @@ void compute_shiftstate(void)
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
-
+
for (i = 0; i < ARRAY_SIZE(key_down); i++) {
if (!key_down[i])
@@ -500,9 +499,9 @@ static void fn_dec_console(struct vc_data *vc, struct pt_regs *regs)
if (want_console != -1)
cur = want_console;
- for (i = cur-1; i != cur; i--) {
+ for (i = cur - 1; i != cur; i--) {
if (i == -1)
- i = MAX_NR_CONSOLES-1;
+ i = MAX_NR_CONSOLES - 1;
if (vc_cons_allocated(i))
break;
}
@@ -568,9 +567,9 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
{
- if (spawnpid)
- if(kill_proc(spawnpid, spawnsig, 1))
- spawnpid = 0;
+ if (spawnpid)
+ if (kill_proc(spawnpid, spawnsig, 1))
+ spawnpid = 0;
}
static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
@@ -604,8 +603,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag, struct
return;
if (value >= ARRAY_SIZE(fn_handler))
return;
- if ((kbd->kbdmode == VC_RAW ||
- kbd->kbdmode == VC_MEDIUMRAW) &&
+ if ((kbd->kbdmode == VC_RAW ||
+ kbd->kbdmode == VC_MEDIUMRAW) &&
value != KVAL(K_SAK))
return; /* SAK is allowed even in raw mode */
fn_handler[value](vc, regs);
@@ -895,11 +894,11 @@ static inline unsigned char getleds(void)
static void kbd_bh(unsigned long dummy)
{
- struct list_head * node;
+ struct list_head *node;
unsigned char leds = getleds();
if (leds != ledstate) {
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle * handle = to_handle_h(node);
input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
@@ -964,11 +963,11 @@ static int sparc_l1_a_state = 0;
extern void sun_do_break(void);
#endif
-static int emulate_raw(struct vc_data *vc, unsigned int keycode,
+static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ return -1;
switch (keycode) {
case KEY_PAUSE:
@@ -982,7 +981,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
case KEY_HANJA:
if (!up_flag) put_queue(vc, 0xf2);
return 0;
- }
+ }
if (keycode == KEY_SYSRQ && sysrq_alt) {
put_queue(vc, 0x54 | up_flag);
@@ -1105,11 +1104,12 @@ static void kbd_keycode(unsigned int keycode, int down,
else
clear_bit(keycode, key_down);
- if (rep && (!vc_kbd_mode(kbd, VC_REPEAT) || (tty &&
- (!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) {
+ if (rep &&
+ (!vc_kbd_mode(kbd, VC_REPEAT) ||
+ (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
/*
* Don't repeat a key if the input buffers are not empty and the
- * characters get aren't echoed locally. This makes key repeat
+ * characters get aren't echoed locally. This makes key repeat
* usable with slow applications and under heavy loads.
*/
return;
@@ -1131,7 +1131,8 @@ static void kbd_keycode(unsigned int keycode, int down,
type = KTYP(keysym);
if (type < 0xf0) {
- if (down && !raw_mode) to_utf8(vc, keysym);
+ if (down && !raw_mode)
+ to_utf8(vc, keysym);
return;
}
@@ -1155,7 +1156,7 @@ static void kbd_keycode(unsigned int keycode, int down,
kbd->slockstate = 0;
}
-static void kbd_event(struct input_handle *handle, unsigned int event_type,
+static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int event_code, int value)
{
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
@@ -1167,15 +1168,13 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
schedule_console_callback();
}
-static char kbd_name[] = "kbd";
-
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
* likes it, it can open it and get events from it. In this (kbd_connect)
* function, we should decide which VT to bind that keyboard to initially.
*/
-static struct input_handle *kbd_connect(struct input_handler *handler,
+static struct input_handle *kbd_connect(struct input_handler *handler,
struct input_dev *dev,
struct input_device_id *id)
{
@@ -1183,18 +1182,19 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
- if (test_bit(i, dev->keybit)) break;
+ if (test_bit(i, dev->keybit))
+ break;
- if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit))
+ if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
- handle->name = kbd_name;
+ handle->name = "kbd";
input_open_device(handle);
kbd_refresh_leds(handle);
@@ -1213,11 +1213,11 @@ static struct input_device_id kbd_ids[] = {
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_KEY) },
},
-
+
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT(EV_SND) },
- },
+ },
{ }, /* Terminating entry */
};
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index cf01a720eb2e..29963d8be667 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -575,8 +575,8 @@ static inline int button_pressed(void)
static int lcd_waiters = 0;
-static long lcd_read(struct inode *inode, struct file *file, char *buf,
- unsigned long count)
+static ssize_t lcd_read(struct file *file, char *buf,
+ size_t count, loff_t *ofs)
{
long buttons_now;
@@ -613,10 +613,15 @@ static struct miscdevice lcd_dev = {
static int lcd_init(void)
{
+ int ret;
unsigned long data;
pr_info("%s\n", LCD_DRIVER);
- misc_register(&lcd_dev);
+ ret = misc_register(&lcd_dev);
+ if (ret) {
+ printk(KERN_WARNING LCD "Unable to register misc device.\n");
+ return ret;
+ }
/* Check region? Naaah! Just snarf it up. */
/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
index 878a95280e87..a8d4ae737158 100644
--- a/drivers/char/lcd.h
+++ b/drivers/char/lcd.h
@@ -22,7 +22,7 @@ static int timeout(volatile unsigned long);
#define MAX_IDLE_TIME 120
struct lcd_display {
- unsigned long buttons;
+ unsigned buttons;
int size1;
int size2;
unsigned char line1[LCD_CHARS_PER_LINE];
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 59eebe5a035f..e57260525293 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -128,6 +128,7 @@
#include <linux/console.h>
#include <linux/device.h>
#include <linux/wait.h>
+#include <linux/jiffies.h>
#include <linux/parport.h>
#undef LP_STATS
@@ -307,7 +308,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
(LP_F(minor) & LP_ABORT));
#ifdef LP_STATS
- if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+ if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
lp_table[minor].runchars = 0;
lp_table[minor].lastcall = jiffies;
@@ -804,7 +805,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+ class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 115dbb35334b..c268ee04b2aa 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -750,7 +750,7 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
dev->soft = NULL;
- soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL);
+ soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL);
if (soft == NULL)
return -ENOMEM;
@@ -830,6 +830,9 @@ static int __init mbcs_init(void)
{
int rv;
+ if (!ia64_platform_is("sn2"))
+ return -ENODEV;
+
// Put driver into chrdevs[]. Get major number.
rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops);
if (rv < 0) {
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 42187381506b..91dd669273e0 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -35,10 +35,6 @@
# include <linux/efi.h>
#endif
-#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
-extern void tapechar_init(void);
-#endif
-
/*
* Architectures vary in how they handle caching for addresses
* outside of main memory.
@@ -235,9 +231,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
#if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-
- vma->vm_page_prot = phys_mem_access_prot(file, offset,
+ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
#elif defined(pgprot_noncached)
@@ -261,7 +255,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
{
- unsigned long long val;
+ unsigned long pfn;
+
+ /* Turn a kernel-virtual address into a physical page frame */
+ pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
+
/*
* RED-PEN: on some architectures there is more mapped memory
* than available in mem_map which pfn_valid checks
@@ -269,10 +267,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
*
* RED-PEN: vmalloc is not supported right now.
*/
- if (!pfn_valid(vma->vm_pgoff))
+ if (!pfn_valid(pfn))
return -EIO;
- val = (u64)vma->vm_pgoff << PAGE_SHIFT;
- vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
+
+ vma->vm_pgoff = pfn;
return mmap_mem(file, vma);
}
@@ -920,7 +918,8 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) {
- class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
+ class_device_create(mem_class, NULL,
+ MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name);
devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 931efd58f87a..3e4c0414a01a 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -63,8 +63,6 @@ static DECLARE_MUTEX(misc_sem);
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
-extern int rtc_DP8570A_init(void);
-extern int rtc_MK48T08_init(void);
extern int pmu_device_init(void);
#ifdef CONFIG_PROC_FS
@@ -236,7 +234,7 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->class = class_device_create(misc_class, dev, misc->dev,
+ misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
"%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
@@ -303,12 +301,7 @@ static int __init misc_init(void)
misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
-#ifdef CONFIG_MVME16x
- rtc_MK48T08_init();
-#endif
-#ifdef CONFIG_BVME6000
- rtc_DP8570A_init();
-#endif
+
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 12006182f575..78c89a3e7825 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -441,7 +441,7 @@ static irqreturn_t
mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
- mmtimer_t *base = timers + cpuid_to_cnodeid(smp_processor_id()) *
+ mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
NUM_COMPARATORS;
unsigned long expires = 0;
int result = IRQ_NONE;
@@ -608,7 +608,7 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
*/
preempt_disable();
- nodeid = cpuid_to_cnodeid(smp_processor_id());
+ nodeid = cpu_to_node(smp_processor_id());
base = timers + nodeid * NUM_COMPARATORS;
retry:
/* Don't use an allocated timer, or a deleted one that's pending */
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 95f7046ff059..79e490ef2cf2 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -339,7 +339,7 @@ static int __init moxa_init(void)
init_MUTEX(&moxaBuffSem);
moxaDriver->owner = THIS_MODULE;
- moxaDriver->name = "ttya";
+ moxaDriver->name = "ttyMX";
moxaDriver->devfs_name = "tts/a";
moxaDriver->major = ttymajor;
moxaDriver->minor_start = 0;
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index 613aed9e1840..d1fe05e83882 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -53,6 +53,8 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/sched.h> /* cond_resched() */
+
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d568991ac6b3..8666171e187b 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -57,6 +57,7 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+#include <linux/serial_8250.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
@@ -410,8 +411,8 @@ static ssize_t mwave_write(struct file *file, const char __user *buf,
static int register_serial_portandirq(unsigned int port, int irq)
{
- struct serial_struct serial;
-
+ struct uart_port uart;
+
switch ( port ) {
case 0x3f8:
case 0x2f8:
@@ -442,12 +443,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
} /* switch */
/* irq is okay */
- memset(&serial, 0, sizeof(serial));
- serial.port = port;
- serial.irq = irq;
- serial.flags = ASYNC_SHARE_IRQ;
-
- return register_serial(&serial);
+ memset(&uart, 0, sizeof(struct uart_port));
+
+ uart.uartclk = 1843200;
+ uart.iobase = port;
+ uart.irq = irq;
+ uart.iotype = UPIO_PORT;
+ uart.flags = UPF_SHARE_IRQ;
+ return serial8250_register_port(&uart);
}
@@ -523,7 +526,7 @@ static void mwave_exit(void)
#endif
if ( pDrvData->sLine >= 0 ) {
- unregister_serial(pDrvData->sLine);
+ serial8250_unregister_port(pDrvData->sLine);
}
if (pDrvData->bMwaveDevRegistered) {
misc_deregister(&mwave_misc_dev);
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index f022f0944434..45d012d85e8c 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -63,7 +63,6 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
@@ -1059,8 +1058,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
*/
timeout = jiffies + HZ;
while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(5);
+ schedule_timeout_interruptible(5);
if (time_after(jiffies, timeout))
break;
}
@@ -1081,10 +1079,8 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
info->event = 0;
info->tty = NULL;
if (info->blocked_open) {
- if (info->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
- }
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
}
@@ -1802,8 +1798,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ schedule_timeout_interruptible(char_time);
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 2291a87e8ada..853c98cee64f 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -229,8 +229,8 @@ static int __init r3964_init(void)
TRACE_L("line discipline %d registered", N_R3964);
TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags,
tty_ldisc_N_R3964.num);
- TRACE_L("open=%x", (int)tty_ldisc_N_R3964.open);
- TRACE_L("tty_ldisc_N_R3964 = %x", (int)&tty_ldisc_N_R3964);
+ TRACE_L("open=%p", tty_ldisc_N_R3964.open);
+ TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
}
else
{
@@ -267,8 +267,8 @@ static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH
spin_unlock_irqrestore(&pInfo->lock, flags);
- TRACE_Q("add_tx_queue %x, length %d, tx_first = %x",
- (int)pHeader, pHeader->length, (int)pInfo->tx_first );
+ TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
+ pHeader, pHeader->length, pInfo->tx_first );
}
static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
@@ -285,10 +285,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
return;
#ifdef DEBUG_QUEUE
- printk("r3964: remove_from_tx_queue: %x, length %d - ",
- (int)pHeader, (int)pHeader->length );
+ printk("r3964: remove_from_tx_queue: %p, length %u - ",
+ pHeader, pHeader->length );
for(pDump=pHeader;pDump;pDump=pDump->next)
- printk("%x ", (int)pDump);
+ printk("%p ", pDump);
printk("\n");
#endif
@@ -319,10 +319,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
spin_unlock_irqrestore(&pInfo->lock, flags);
kfree(pHeader);
- TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader);
+ TRACE_M("remove_from_tx_queue - kfree %p",pHeader);
- TRACE_Q("remove_from_tx_queue: tx_first = %x, tx_last = %x",
- (int)pInfo->tx_first, (int)pInfo->tx_last );
+ TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
+ pInfo->tx_first, pInfo->tx_last );
}
static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
@@ -346,9 +346,9 @@ static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH
spin_unlock_irqrestore(&pInfo->lock, flags);
- TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d",
- (int)pHeader, pHeader->length,
- (int)pInfo->rx_first, pInfo->blocks_in_rx_queue);
+ TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
+ pHeader, pHeader->length,
+ pInfo->rx_first, pInfo->blocks_in_rx_queue);
}
static void remove_from_rx_queue(struct r3964_info *pInfo,
@@ -360,10 +360,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
if(pHeader==NULL)
return;
- TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
- (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
- TRACE_Q("remove_from_rx_queue: %x, length %d",
- (int)pHeader, (int)pHeader->length );
+ TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+ pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
+ TRACE_Q("remove_from_rx_queue: %p, length %u",
+ pHeader, pHeader->length );
spin_lock_irqsave(&pInfo->lock, flags);
@@ -401,10 +401,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
spin_unlock_irqrestore(&pInfo->lock, flags);
kfree(pHeader);
- TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader);
+ TRACE_M("remove_from_rx_queue - kfree %p",pHeader);
- TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
- (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
+ TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+ pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
}
static void put_char(struct r3964_info *pInfo, unsigned char ch)
@@ -506,8 +506,8 @@ static void transmit_block(struct r3964_info *pInfo)
if(tty->driver->write_room)
room=tty->driver->write_room(tty);
- TRACE_PS("transmit_block %x, room %d, length %d",
- (int)pBlock, room, pBlock->length);
+ TRACE_PS("transmit_block %p, room %d, length %d",
+ pBlock, room, pBlock->length);
while(pInfo->tx_position < pBlock->length)
{
@@ -588,7 +588,7 @@ static void on_receive_block(struct r3964_info *pInfo)
/* prepare struct r3964_block_header: */
pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL);
- TRACE_M("on_receive_block - kmalloc %x",(int)pBlock);
+ TRACE_M("on_receive_block - kmalloc %p",pBlock);
if(pBlock==NULL)
return;
@@ -695,7 +695,7 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c)
{
TRACE_PE("IDLE - got STX but no space in rx_queue!");
pInfo->state=R3964_WAIT_FOR_RX_BUF;
- mod_timer(&pInfo->tmr, R3964_TO_NO_BUF);
+ mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF);
break;
}
start_receiving:
@@ -705,7 +705,7 @@ start_receiving:
pInfo->last_rx = 0;
pInfo->flags &= ~R3964_ERROR;
pInfo->state=R3964_RECEIVING;
- mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
+ mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
pInfo->nRetry = 0;
put_char(pInfo, DLE);
flush(pInfo);
@@ -732,7 +732,7 @@ start_receiving:
if(pInfo->flags & R3964_BCC)
{
pInfo->state = R3964_WAIT_FOR_BCC;
- mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
+ mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
}
else
{
@@ -744,7 +744,7 @@ start_receiving:
pInfo->last_rx = c;
char_to_buf:
pInfo->rx_buf[pInfo->rx_position++] = c;
- mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
+ mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
}
}
/* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
@@ -868,11 +868,11 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
if(pMsg)
{
kfree(pMsg);
- TRACE_M("enable_signals - msg kfree %x",(int)pMsg);
+ TRACE_M("enable_signals - msg kfree %p",pMsg);
}
}
kfree(pClient);
- TRACE_M("enable_signals - kfree %x",(int)pClient);
+ TRACE_M("enable_signals - kfree %p",pClient);
return 0;
}
}
@@ -890,7 +890,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
{
/* add client to client list */
pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL);
- TRACE_M("enable_signals - kmalloc %x",(int)pClient);
+ TRACE_M("enable_signals - kmalloc %p",pClient);
if(pClient==NULL)
return -ENOMEM;
@@ -954,7 +954,7 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
queue_the_message:
pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
- TRACE_M("add_msg - kmalloc %x",(int)pMsg);
+ TRACE_M("add_msg - kmalloc %p",pMsg);
if(pMsg==NULL) {
return;
}
@@ -1067,11 +1067,11 @@ static int r3964_open(struct tty_struct *tty)
struct r3964_info *pInfo;
TRACE_L("open");
- TRACE_L("tty=%x, PID=%d, disc_data=%x",
- (int)tty, current->pid, (int)tty->disc_data);
+ TRACE_L("tty=%p, PID=%d, disc_data=%p",
+ tty, current->pid, tty->disc_data);
pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL);
- TRACE_M("r3964_open - info kmalloc %x",(int)pInfo);
+ TRACE_M("r3964_open - info kmalloc %p",pInfo);
if(!pInfo)
{
@@ -1080,26 +1080,26 @@ static int r3964_open(struct tty_struct *tty)
}
pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
- TRACE_M("r3964_open - rx_buf kmalloc %x",(int)pInfo->rx_buf);
+ TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf);
if(!pInfo->rx_buf)
{
printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
kfree(pInfo);
- TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+ TRACE_M("r3964_open - info kfree %p",pInfo);
return -ENOMEM;
}
pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
- TRACE_M("r3964_open - tx_buf kmalloc %x",(int)pInfo->tx_buf);
+ TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf);
if(!pInfo->tx_buf)
{
printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
kfree(pInfo->rx_buf);
- TRACE_M("r3964_open - rx_buf kfree %x",(int)pInfo->rx_buf);
+ TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf);
kfree(pInfo);
- TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+ TRACE_M("r3964_open - info kfree %p",pInfo);
return -ENOMEM;
}
@@ -1154,11 +1154,11 @@ static void r3964_close(struct tty_struct *tty)
if(pMsg)
{
kfree(pMsg);
- TRACE_M("r3964_close - msg kfree %x",(int)pMsg);
+ TRACE_M("r3964_close - msg kfree %p",pMsg);
}
}
kfree(pClient);
- TRACE_M("r3964_close - client kfree %x",(int)pClient);
+ TRACE_M("r3964_close - client kfree %p",pClient);
pClient=pNext;
}
/* Remove jobs from tx_queue: */
@@ -1177,11 +1177,11 @@ static void r3964_close(struct tty_struct *tty)
/* Free buffers: */
wake_up_interruptible(&pInfo->read_wait);
kfree(pInfo->rx_buf);
- TRACE_M("r3964_close - rx_buf kfree %x",(int)pInfo->rx_buf);
+ TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf);
kfree(pInfo->tx_buf);
- TRACE_M("r3964_close - tx_buf kfree %x",(int)pInfo->tx_buf);
+ TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf);
kfree(pInfo);
- TRACE_M("r3964_close - info kfree %x",(int)pInfo);
+ TRACE_M("r3964_close - info kfree %p",pInfo);
}
static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
@@ -1234,7 +1234,7 @@ repeat:
count = sizeof(struct r3964_client_message);
kfree(pMsg);
- TRACE_M("r3964_read - msg kfree %x",(int)pMsg);
+ TRACE_M("r3964_read - msg kfree %p",pMsg);
if (copy_to_user(buf,&theMsg, count))
return -EFAULT;
@@ -1279,7 +1279,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
* Allocate a buffer for the data and copy it from the buffer with header prepended
*/
new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL);
- TRACE_M("r3964_write - kmalloc %x",(int)new_data);
+ TRACE_M("r3964_write - kmalloc %p",new_data);
if (new_data == NULL) {
if (pInfo->flags & R3964_DEBUG)
{
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 09103b3d8f05..c556f4d3ccd7 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -62,7 +62,7 @@
static inline unsigned char *alloc_buf(void)
{
- int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
if (PAGE_SIZE != N_TTY_BUF_SIZE)
return kmalloc(N_TTY_BUF_SIZE, prio);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 7a0c74648124..02d7f046c10a 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/pcmcia/synclink_cs.c
*
- * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.34 2005/09/08 13:20:54 paulkf Exp $
*
* Device driver for Microgate SyncLink PC Card
* multiprotocol serial adapter.
@@ -472,7 +472,7 @@ module_param_array(dosyncppp, int, NULL, 0);
MODULE_LICENSE("GPL");
static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.26 $";
+static char *driver_version = "$Revision: 4.34 $";
static struct tty_driver *serial_driver;
@@ -1457,6 +1457,8 @@ static int startup(MGSLPC_INFO * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
init_timer(&info->tx_timer);
info->tx_timer.data = (unsigned long)info;
info->tx_timer.function = tx_timeout;
@@ -1946,9 +1948,13 @@ static int get_stats(MGSLPC_INFO * info, struct mgsl_icount __user *user_icount)
int err;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("get_params(%s)\n", info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err)
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
+ }
return 0;
}
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 0e22880432bc..306ee0f091a4 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,7 +752,7 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
+ class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
}
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index da32889d22c0..49f3997fd251 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -149,15 +149,14 @@ static int pty_write_room(struct tty_struct *tty)
static int pty_chars_in_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
- ssize_t (*chars_in_buffer)(struct tty_struct *);
int count;
/* We should get the line discipline lock for "tty->link" */
- if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer))
+ if (!to || !to->ldisc.chars_in_buffer)
return 0;
/* The ldisc must report 0 if no characters available to be read */
- count = chars_in_buffer(to);
+ count = to->ldisc.chars_in_buffer(to);
if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c
index 40a3cf62e1a8..601d09baf9d7 100644
--- a/drivers/char/qtronix.c
+++ b/drivers/char/qtronix.c
@@ -591,6 +591,11 @@ static int __init psaux_init(void)
return retval;
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+ if (!queue) {
+ misc_deregister(&psaux_mouse);
+ return -ENOMEM;
+ }
+
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
init_waitqueue_head(&queue->proc_list);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 6b11d6b2129f..7999da25fe40 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1589,6 +1589,40 @@ u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dp
EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
#endif
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
+/* Similar to secure_tcp_sequence_number but generate a 48 bit value
+ * bit's 32-47 increase every key exchange
+ * 0-31 hash(source, dest)
+ */
+u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport)
+{
+ struct timeval tv;
+ u64 seq;
+ __u32 hash[4];
+ struct keydata *keyptr = get_keyptr();
+
+ hash[0] = saddr;
+ hash[1] = daddr;
+ hash[2] = (sport << 16) + dport;
+ hash[3] = keyptr->secret[11];
+
+ seq = half_md4_transform(hash, keyptr->secret);
+ seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
+
+ do_gettimeofday(&tv);
+ seq += tv.tv_usec + tv.tv_sec * 1000000;
+ seq &= (1ull << 48) - 1;
+#if 0
+ printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
+ saddr, daddr, sport, dport, seq);
+#endif
+ return seq;
+}
+
+EXPORT_SYMBOL(secure_dccp_sequence_number);
+#endif
+
#endif /* CONFIG_INET */
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index f13e5de02207..30e4cbe16bb0 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -128,7 +128,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+ class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
}
@@ -307,7 +307,7 @@ static int __init raw_init(void)
unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error;
}
- class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+ class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO,
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5b1d3680c8ab..928b850cc679 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -256,7 +256,6 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
static int sReadAiopID(ByteIO_t io);
static int sReadAiopNumChan(WordIO_t io);
-#ifdef MODULE
MODULE_AUTHOR("Theodore Ts'o");
MODULE_DESCRIPTION("Comtrol RocketPort driver");
module_param(board1, ulong, 0);
@@ -288,17 +287,14 @@ MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc1
module_param_array(pc104_4, ulong, NULL, 0);
MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
-int rp_init(void);
+static int rp_init(void);
static void rp_cleanup_module(void);
module_init(rp_init);
module_exit(rp_cleanup_module);
-#endif
-#ifdef MODULE_LICENSE
MODULE_LICENSE("Dual BSD/GPL");
-#endif
/*************************************************************************/
/* Module code starts here */
@@ -2378,7 +2374,7 @@ static struct tty_operations rocket_ops = {
/*
* The module "startup" routine; it's run when the module is loaded.
*/
-int __init rp_init(void)
+static int __init rp_init(void)
{
int retval, pci_boards_found, isa_boards_found, i;
@@ -2502,7 +2498,6 @@ int __init rp_init(void)
return 0;
}
-#ifdef MODULE
static void rp_cleanup_module(void)
{
@@ -2530,7 +2525,6 @@ static void rp_cleanup_module(void)
if (controller)
release_region(controller, 4);
}
-#endif
/***************************************************************************
Function: sInitController
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index d8f9e94ae475..63fff7c1244a 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -938,10 +938,9 @@ found:
/*
* XXX Interrupt pin #7 in Espresso is shared between RTC and
- * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
- * is asking for trouble with add-on boards. Change to SA_SHIRQ.
+ * PCI Slot 2 INTA# (and some INTx# in Slot 1).
*/
- if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+ if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) {
/*
* Standard way for sparc to print irq's is to use
* __irq_itoa(). I think for EBus it's ok to use %d.
@@ -1209,6 +1208,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
+ unsigned long uip_watchdog = jiffies;
unsigned char ctrl;
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_year;
@@ -1224,8 +1224,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
* Once the read clears, read the RTC time (again via ioctl). Easy.
*/
- if (rtc_is_updating() != 0)
- msleep(20);
+ while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
+ barrier();
+ cpu_relax();
+ }
/*
* Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index ed867db550a9..d724c0de4f28 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -20,7 +20,7 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
@@ -519,30 +519,28 @@ static struct timespec s3c2410_rtc_delta;
static int ticnt_save;
-static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state)
{
struct rtc_time tm;
struct timespec time;
time.tv_nsec = 0;
- if (level == SUSPEND_POWER_DOWN) {
- /* save TICNT for anyone using periodic interrupts */
+ /* save TICNT for anyone using periodic interrupts */
- ticnt_save = readb(S3C2410_TICNT);
+ ticnt_save = readb(S3C2410_TICNT);
- /* calculate time delta for suspend */
+ /* calculate time delta for suspend */
- s3c2410_rtc_gettime(&tm);
- rtc_tm_to_time(&tm, &time.tv_sec);
- save_time_delta(&s3c2410_rtc_delta, &time);
- s3c2410_rtc_enable(dev, 0);
- }
+ s3c2410_rtc_gettime(&tm);
+ rtc_tm_to_time(&tm, &time.tv_sec);
+ save_time_delta(&s3c2410_rtc_delta, &time);
+ s3c2410_rtc_enable(dev, 0);
return 0;
}
-static int s3c2410_rtc_resume(struct device *dev, u32 level)
+static int s3c2410_rtc_resume(struct device *dev)
{
struct rtc_time tm;
struct timespec time;
@@ -564,6 +562,7 @@ static int s3c2410_rtc_resume(struct device *dev, u32 level)
static struct device_driver s3c2410_rtcdrv = {
.name = "s3c2410-rtc",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = s3c2410_rtc_probe,
.remove = s3c2410_rtc_remove,
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 6b4e9d155f50..dda30e42ec79 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -790,7 +790,7 @@ static int __init a2232board_init(void)
}
- printk("Total: %d A2232 boards initialized.\n.", nr_a2232); /* Some status report if no card was found */
+ printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
a2232_init_portstructs();
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 261a41bf6d02..0e7d216e7eb0 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -377,7 +377,7 @@ scdrv_init(void)
dev_t first_dev, dev;
nasid_t event_nasid = ia64_sn_get_console_nasid();
- if (alloc_chrdev_region(&first_dev, 0, numionodes,
+ if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
SYSCTL_BASENAME) < 0) {
printk("%s: failed to register SN system controller device\n",
__FUNCTION__);
@@ -385,7 +385,7 @@ scdrv_init(void)
}
snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
- for (cnode = 0; cnode < numionodes; cnode++) {
+ for (cnode = 0; cnode < num_cnodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
devnamep = devname;
format_module_id(devnamep, geo_module(geoid),
@@ -437,7 +437,7 @@ scdrv_init(void)
continue;
}
- class_device_create(snsc_class, dev, NULL,
+ class_device_create(snsc_class, NULL, dev, NULL,
"%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index d692af57213a..baaa365285fa 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/byteorder/generic.h>
#include <asm/sn/sn_sal.h>
+#include <asm/unaligned.h>
#include "snsc.h"
static struct subch_data_s *event_sd;
@@ -62,13 +63,16 @@ static int
scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
{
char *desc_end;
+ __be32 from_buf;
/* record event source address */
- *src = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *src = be32_to_cpup(&from_buf);
event += 4; /* move on to event code */
/* record the system controller's event code */
- *code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *code = be32_to_cpup(&from_buf);
event += 4; /* move on to event arguments */
/* how many arguments are in the packet? */
@@ -82,7 +86,8 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
/* not an integer argument, so give up */
return -1;
}
- *esp_code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *esp_code = be32_to_cpup(&from_buf);
event += 4;
/* parse out the event description */
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index cefbe985e55c..d05067dcea01 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -48,6 +48,7 @@
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/kfifo.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -98,12 +99,13 @@ MODULE_PARM_DESC(useinput,
#define SONYPI_DEVICE_MODEL_TYPE1 1
#define SONYPI_DEVICE_MODEL_TYPE2 2
+#define SONYPI_DEVICE_MODEL_TYPE3 3
/* type1 models use those */
#define SONYPI_IRQ_PORT 0x8034
#define SONYPI_IRQ_SHIFT 22
-#define SONYPI_BASE 0x50
-#define SONYPI_G10A (SONYPI_BASE+0x14)
+#define SONYPI_TYPE1_BASE 0x50
+#define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14)
#define SONYPI_TYPE1_REGION_SIZE 0x08
#define SONYPI_TYPE1_EVTYPE_OFFSET 0x04
@@ -114,6 +116,13 @@ MODULE_PARM_DESC(useinput,
#define SONYPI_TYPE2_REGION_SIZE 0x20
#define SONYPI_TYPE2_EVTYPE_OFFSET 0x12
+/* type3 series specifics */
+#define SONYPI_TYPE3_BASE 0x40
+#define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */
+#define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */
+#define SONYPI_TYPE3_REGION_SIZE 0x20
+#define SONYPI_TYPE3_EVTYPE_OFFSET 0x12
+
/* battery / brightness addresses */
#define SONYPI_BAT_FLAGS 0x81
#define SONYPI_LCD_LIGHT 0x96
@@ -159,6 +168,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = {
{ 0x0, 0x0 }
};
+/* same as in type 2 models */
+static struct sonypi_ioport_list *sonypi_type3_ioport_list =
+ sonypi_type2_ioport_list;
+
/* The set of possible interrupts */
struct sonypi_irq_list {
u16 irq;
@@ -180,6 +193,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
{ 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */
};
+/* same as in type2 models */
+static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list;
+
#define SONYPI_CAMERA_BRIGHTNESS 0
#define SONYPI_CAMERA_CONTRAST 1
#define SONYPI_CAMERA_HUE 2
@@ -223,6 +239,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
#define SONYPI_MEYE_MASK 0x00000400
#define SONYPI_MEMORYSTICK_MASK 0x00000800
#define SONYPI_BATTERY_MASK 0x00001000
+#define SONYPI_WIRELESS_MASK 0x00002000
struct sonypi_event {
u8 data;
@@ -305,6 +322,13 @@ static struct sonypi_event sonypi_blueev[] = {
{ 0, 0 }
};
+/* The set of possible wireless events */
+static struct sonypi_event sonypi_wlessev[] = {
+ { 0x59, SONYPI_EVENT_WIRELESS_ON },
+ { 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+ { 0, 0 }
+};
+
/* The set of possible back button events */
static struct sonypi_event sonypi_backev[] = {
{ 0x20, SONYPI_EVENT_BACK_PRESSED },
@@ -383,7 +407,6 @@ static struct sonypi_eventtypes {
{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
- { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
@@ -391,15 +414,17 @@ static struct sonypi_eventtypes {
{ SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+ { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
{ 0 }
};
#define SONYPI_BUF_SIZE 128
-/* The name of the devices for the input device drivers */
-#define SONYPI_JOG_INPUTNAME "Sony Vaio Jogdial"
-#define SONYPI_KEY_INPUTNAME "Sony Vaio Keys"
-
/* Correspondance table between sonypi events and input layer events */
static struct {
int sonypiev;
@@ -462,8 +487,8 @@ static struct sonypi_device {
struct fasync_struct *fifo_async;
int open_count;
int model;
- struct input_dev input_jog_dev;
- struct input_dev input_key_dev;
+ struct input_dev *input_jog_dev;
+ struct input_dev *input_key_dev;
struct work_struct input_work;
struct kfifo *input_fifo;
spinlock_t input_fifo_lock;
@@ -563,6 +588,23 @@ static void sonypi_type2_srs(void)
udelay(10);
}
+static void sonypi_type3_srs(void)
+{
+ u16 v16;
+ u8 v8;
+
+ /* This model type uses the same initialiazation of
+ * the embedded controller as the type2 models. */
+ sonypi_type2_srs();
+
+ /* Initialization of PCI config space of the LPC interface bridge. */
+ v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01;
+ pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16);
+ pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8);
+ v8 = (v8 & 0xCF) | 0x10;
+ pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8);
+}
+
/* Disables the device - this comes from the AML code in the ACPI bios */
static void sonypi_type1_dis(void)
{
@@ -587,6 +629,13 @@ static void sonypi_type2_dis(void)
printk(KERN_WARNING "ec_write failed\n");
}
+static void sonypi_type3_dis(void)
+{
+ sonypi_type2_dis();
+ udelay(10);
+ pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0);
+}
+
static u8 sonypi_call1(u8 dev)
{
u8 v1, v2;
@@ -727,8 +776,8 @@ static void input_keyrelease(void *data)
static void sonypi_report_input_event(u8 event)
{
- struct input_dev *jog_dev = &sonypi_device.input_jog_dev;
- struct input_dev *key_dev = &sonypi_device.input_key_dev;
+ struct input_dev *jog_dev = sonypi_device.input_jog_dev;
+ struct input_dev *key_dev = sonypi_device.input_key_dev;
struct sonypi_keypress kp = { NULL };
int i;
@@ -1067,10 +1116,17 @@ static struct miscdevice sonypi_misc_device = {
static void sonypi_enable(unsigned int camera_on)
{
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
- sonypi_type2_srs();
- else
+ switch (sonypi_device.model) {
+ case SONYPI_DEVICE_MODEL_TYPE1:
sonypi_type1_srs();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE2:
+ sonypi_type2_srs();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE3:
+ sonypi_type3_srs();
+ break;
+ }
sonypi_call1(0x82);
sonypi_call2(0x81, 0xff);
@@ -1094,29 +1150,35 @@ static int sonypi_disable(void)
if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
outb(0xf1, 0xb2);
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
- sonypi_type2_dis();
- else
+ switch (sonypi_device.model) {
+ case SONYPI_DEVICE_MODEL_TYPE1:
sonypi_type1_dis();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE2:
+ sonypi_type2_dis();
+ break;
+ case SONYPI_DEVICE_MODEL_TYPE3:
+ sonypi_type3_dis();
+ break;
+ }
+
return 0;
}
#ifdef CONFIG_PM
static int old_camera_power;
-static int sonypi_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sonypi_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_DISABLE) {
- old_camera_power = sonypi_device.camera_power;
- sonypi_disable();
- }
+ old_camera_power = sonypi_device.camera_power;
+ sonypi_disable();
+
return 0;
}
-static int sonypi_resume(struct device *dev, u32 level)
+static int sonypi_resume(struct device *dev)
{
- if (level == RESUME_ENABLE)
- sonypi_enable(old_camera_power);
+ sonypi_enable(old_camera_power);
return 0;
}
#endif
@@ -1136,6 +1198,47 @@ static struct device_driver sonypi_driver = {
.shutdown = sonypi_shutdown,
};
+static int __devinit sonypi_create_input_devices(void)
+{
+ struct input_dev *jog_dev;
+ struct input_dev *key_dev;
+ int i;
+
+ sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
+ if (!jog_dev)
+ return -ENOMEM;
+
+ jog_dev->name = "Sony Vaio Jogdial";
+ jog_dev->id.bustype = BUS_ISA;
+ jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+ jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
+ jog_dev->relbit[0] = BIT(REL_WHEEL);
+
+ sonypi_device.input_key_dev = key_dev = input_allocate_device();
+ if (!key_dev) {
+ input_free_device(jog_dev);
+ sonypi_device.input_jog_dev = NULL;
+ return -ENOMEM;
+ }
+
+ key_dev->name = "Sony Vaio Keys";
+ key_dev->id.bustype = BUS_ISA;
+ key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+ /* Initialize the Input Drivers: special keys */
+ key_dev->evbit[0] = BIT(EV_KEY);
+ for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
+ if (sonypi_inputkeys[i].inputev)
+ set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
+
+ input_register_device(jog_dev);
+ input_register_device(key_dev);
+
+ return 0;
+}
+
static int __devinit sonypi_probe(void)
{
int i, ret;
@@ -1143,12 +1246,16 @@ static int __devinit sonypi_probe(void)
struct sonypi_irq_list *irq_list;
struct pci_dev *pcidev;
- pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
+ else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+ else
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
sonypi_device.dev = pcidev;
- sonypi_device.model = pcidev ?
- SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2;
spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
@@ -1176,16 +1283,22 @@ static int __devinit sonypi_probe(void)
goto out_miscreg;
}
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
+
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
+ ioport_list = sonypi_type1_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
+ sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
+ irq_list = sonypi_type1_irq_list;
+ } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
ioport_list = sonypi_type2_ioport_list;
sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET;
irq_list = sonypi_type2_irq_list;
} else {
- ioport_list = sonypi_type1_ioport_list;
- sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
- sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
- irq_list = sonypi_type1_irq_list;
+ ioport_list = sonypi_type3_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE;
+ sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET;
+ irq_list = sonypi_type3_irq_list;
}
for (i = 0; ioport_list[i].port1; i++) {
@@ -1221,34 +1334,10 @@ static int __devinit sonypi_probe(void)
}
if (useinput) {
- /* Initialize the Input Drivers: jogdial */
- int i;
- sonypi_device.input_jog_dev.evbit[0] =
- BIT(EV_KEY) | BIT(EV_REL);
- sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
- BIT(BTN_MIDDLE);
- sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
- sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME;
- sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
- sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
-
- input_register_device(&sonypi_device.input_jog_dev);
- printk(KERN_INFO "%s input method installed.\n",
- sonypi_device.input_jog_dev.name);
-
- /* Initialize the Input Drivers: special keys */
- sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY);
- for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
- if (sonypi_inputkeys[i].inputev)
- set_bit(sonypi_inputkeys[i].inputev,
- sonypi_device.input_key_dev.keybit);
- sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME;
- sonypi_device.input_key_dev.id.bustype = BUS_ISA;
- sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
- input_register_device(&sonypi_device.input_key_dev);
- printk(KERN_INFO "%s input method installed.\n",
- sonypi_device.input_key_dev.name);
+ ret = sonypi_create_input_devices();
+ if (ret)
+ goto out_inputdevices;
spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo =
@@ -1274,11 +1363,10 @@ static int __devinit sonypi_probe(void)
printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
"v%s.\n", SONYPI_DRIVER_VERSION);
- printk(KERN_INFO "sonypi: detected %s model, "
+ printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
"compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
- (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
- "type1" : "type2",
+ sonypi_device.model,
verbose,
fnkeyinit ? "on" : "off",
camera ? "on" : "off",
@@ -1299,8 +1387,9 @@ static int __devinit sonypi_probe(void)
out_platformdev:
kfifo_free(sonypi_device.input_fifo);
out_infifo:
- input_unregister_device(&sonypi_device.input_key_dev);
- input_unregister_device(&sonypi_device.input_jog_dev);
+ input_unregister_device(sonypi_device.input_key_dev);
+ input_unregister_device(sonypi_device.input_jog_dev);
+out_inputdevices:
free_irq(sonypi_device.irq, sonypi_irq);
out_reqirq:
release_region(sonypi_device.ioport1, sonypi_device.region_size);
@@ -1326,8 +1415,8 @@ static void __devexit sonypi_remove(void)
platform_device_unregister(sonypi_device.pdev);
if (useinput) {
- input_unregister_device(&sonypi_device.input_key_dev);
- input_unregister_device(&sonypi_device.input_jog_dev);
+ input_unregister_device(sonypi_device.input_key_dev);
+ input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo);
}
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 50e0b612a8a2..352547eabf7b 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -38,19 +38,19 @@
*
* Revision 1.0: April 1st 1997.
* Initial release for alpha testing.
- * Revision 1.1: April 14th 1997.
- * Incorporated Richard Hudsons suggestions,
+ * Revision 1.1: April 14th 1997.
+ * Incorporated Richard Hudsons suggestions,
* removed some debugging printk's.
* Revision 1.2: April 15th 1997.
* Ported to 2.1.x kernels.
- * Revision 1.3: April 17th 1997
- * Backported to 2.0. (Compatibility macros).
+ * Revision 1.3: April 17th 1997
+ * Backported to 2.0. (Compatibility macros).
* Revision 1.4: April 18th 1997
- * Fixed DTR/RTS bug that caused the card to indicate
- * "don't send data" to a modem after the password prompt.
+ * Fixed DTR/RTS bug that caused the card to indicate
+ * "don't send data" to a modem after the password prompt.
* Fixed bug for premature (fake) interrupts.
* Revision 1.5: April 19th 1997
- * fixed a minor typo in the header file, cleanup a little.
+ * fixed a minor typo in the header file, cleanup a little.
* performance warnings are now MAXed at once per minute.
* Revision 1.6: May 23 1997
* Changed the specialix=... format to include interrupt.
@@ -60,10 +60,10 @@
* port to linux-2.1.43 kernel.
* Revision 1.9: Oct 9 1998
* Added stuff for the IO8+/PCI version.
- * Revision 1.10: Oct 22 1999 / Jan 21 2000.
- * Added stuff for setserial.
+ * Revision 1.10: Oct 22 1999 / Jan 21 2000.
+ * Added stuff for setserial.
* Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
- *
+ *
*/
#define VERSION "1.11"
@@ -154,7 +154,7 @@ static int sx_poll = HZ;
-/*
+/*
* The following defines are mostly for testing purposes. But if you need
* some nice reporting in your syslog, you can define them also.
*/
@@ -188,7 +188,7 @@ static DECLARE_MUTEX(tmp_buf_sem);
static unsigned long baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 0,
+ 9600, 19200, 38400, 57600, 115200, 0,
};
static struct specialix_board sx_board[SX_NBOARD] = {
@@ -216,7 +216,7 @@ static inline int sx_paranoia_check(struct specialix_port const * port,
KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
static const char *badinfo =
KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
-
+
if (!port) {
printk(badinfo, name, routine);
return 1;
@@ -231,9 +231,9 @@ static inline int sx_paranoia_check(struct specialix_port const * port,
/*
- *
+ *
* Service functions for specialix IO8+ driver.
- *
+ *
*/
/* Get board number from pointer */
@@ -246,7 +246,7 @@ static inline int board_No (struct specialix_board * bp)
/* Get port number from pointer */
static inline int port_No (struct specialix_port const * port)
{
- return SX_PORT(port - sx_port);
+ return SX_PORT(port - sx_port);
}
@@ -309,7 +309,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
return;
udelay (1);
}
-
+
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
}
@@ -329,7 +329,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
return;
udelay (1);
}
-
+
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
}
@@ -338,34 +338,28 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
* specialix IO8+ IO range functions.
*/
-static inline int sx_check_io_range(struct specialix_board * bp)
+static inline int sx_request_io_range(struct specialix_board * bp)
{
- return check_region (bp->base, SX_IO_SPACE);
-}
-
-
-static inline void sx_request_io_range(struct specialix_board * bp)
-{
- request_region(bp->base,
- bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE,
- "specialix IO8+" );
+ return request_region(bp->base,
+ bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
+ "specialix IO8+") == NULL;
}
static inline void sx_release_io_range(struct specialix_board * bp)
{
- release_region(bp->base,
+ release_region(bp->base,
bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
}
-
+
/* Must be called with enabled interrupts */
-/* Ugly. Very ugly. Don't use this for anything else than initialization
+/* Ugly. Very ugly. Don't use this for anything else than initialization
code */
static inline void sx_long_delay(unsigned long delay)
{
unsigned long i;
-
+
for (i = jiffies + delay; time_after(i, jiffies); ) ;
}
@@ -378,7 +372,7 @@ static int sx_set_irq ( struct specialix_board *bp)
int i;
unsigned long flags;
- if (bp->flags & SX_BOARD_IS_PCI)
+ if (bp->flags & SX_BOARD_IS_PCI)
return 1;
switch (bp->irq) {
/* In the same order as in the docs... */
@@ -420,7 +414,7 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
/* Set RegAckEn */
sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
-
+
/* Setting up prescaler. We need 4 ticks per 1 ms */
scaler = SX_OSCFREQ/SPECIALIX_TPS;
@@ -448,7 +442,7 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
spin_lock_irqsave(&bp->lock, flags);
for (i=0, t=0;i<8;i++) {
sx_out_off (bp, CD186x_CAR, i);
- if (sx_in_off (bp, reg) & bit)
+ if (sx_in_off (bp, reg) & bit)
t |= 1 << i;
}
spin_unlock_irqrestore(&bp->lock, flags);
@@ -472,7 +466,7 @@ void missed_irq (unsigned long data)
spin_unlock_irqrestore(&bp->lock, flags);
if (irq) {
printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
- sx_interrupt (((struct specialix_board *)data)->irq,
+ sx_interrupt (((struct specialix_board *)data)->irq,
(void*)data, NULL);
}
missed_irq_timer.expires = jiffies + sx_poll;
@@ -495,7 +489,7 @@ static int sx_probe(struct specialix_board *bp)
func_enter();
- if (sx_check_io_range(bp)) {
+ if (sx_request_io_range(bp)) {
func_exit();
return 1;
}
@@ -509,15 +503,16 @@ static int sx_probe(struct specialix_board *bp)
short_pause ();
val2 = sx_in_off(bp, CD186x_PPRL);
-
+
if ((val1 != 0x5a) || (val2 != 0xa5)) {
printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
board_No(bp), bp->base);
+ sx_release_io_range(bp);
func_exit();
return 1;
}
- /* Check the DSR lines that Specialix uses as board
+ /* Check the DSR lines that Specialix uses as board
identification */
val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
@@ -532,6 +527,7 @@ static int sx_probe(struct specialix_board *bp)
if (val1 != val2) {
printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
board_No(bp), val2, bp->base, val1);
+ sx_release_io_range(bp);
func_exit();
return 1;
}
@@ -546,7 +542,7 @@ static int sx_probe(struct specialix_board *bp)
sx_wait_CCR(bp);
sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
- sx_long_delay(HZ/20);
+ sx_long_delay(HZ/20);
irqs = probe_irq_off(irqs);
dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
@@ -561,14 +557,15 @@ static int sx_probe(struct specialix_board *bp)
}
dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
- val1, val2, val3);
-
+ val1, val2, val3);
+
}
-
+
#if 0
if (irqs <= 0) {
printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
board_No(bp), bp->base);
+ sx_release_io_range(bp);
func_exit();
return 1;
}
@@ -579,19 +576,20 @@ static int sx_probe(struct specialix_board *bp)
#endif
/* Reset CD186x again */
if (!sx_init_CD186x(bp)) {
+ sx_release_io_range(bp);
func_exit();
- return -EIO;
+ return 1;
}
sx_request_io_range(bp);
bp->flags |= SX_BOARD_PRESENT;
-
+
/* Chip revcode pkgtype
GFRCR SRCR bit 7
CD180 rev B 0x81 0
CD180 rev C 0x82 0
CD1864 rev A 0x82 1
- CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
+ CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
CD1865 rev B 0x84 1
-- Thanks to Gwen Wang, Cirrus Logic.
*/
@@ -623,8 +621,8 @@ static int sx_probe(struct specialix_board *bp)
return 0;
}
-/*
- *
+/*
+ *
* Interrupt processing routines.
* */
@@ -657,7 +655,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
return port;
}
}
- printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
+ printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
board_No(bp), what, channel);
return NULL;
}
@@ -681,7 +679,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
tty = port->tty;
dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n",
port, tty->flip.count, TTY_FLIPBUF_SIZE);
-
+
status = sx_in(bp, CD186x_RCSR);
dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
@@ -707,30 +705,30 @@ static inline void sx_receive_exc(struct specialix_board * bp)
return;
}
if (status & RCSR_TOUT) {
- printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
+ printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
board_No(bp), port_No(port));
func_exit();
return;
-
+
} else if (status & RCSR_BREAK) {
dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
*tty->flip.flag_buf_ptr++ = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
-
- } else if (status & RCSR_PE)
+
+ } else if (status & RCSR_PE)
*tty->flip.flag_buf_ptr++ = TTY_PARITY;
-
- else if (status & RCSR_FE)
+
+ else if (status & RCSR_FE)
*tty->flip.flag_buf_ptr++ = TTY_FRAME;
-
+
else if (status & RCSR_OE)
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-
+
else
*tty->flip.flag_buf_ptr++ = 0;
-
+
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
schedule_delayed_work(&tty->flip.work, 1);
@@ -746,18 +744,18 @@ static inline void sx_receive(struct specialix_board * bp)
unsigned char count;
func_enter();
-
+
if (!(port = sx_get_port(bp, "Receive"))) {
dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
func_exit();
return;
}
tty = port->tty;
-
+
count = sx_in(bp, CD186x_RDCR);
dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
port->hits[count > 8 ? 9 : count]++;
-
+
while (count--) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
@@ -787,7 +785,7 @@ static inline void sx_transmit(struct specialix_board * bp)
}
dprintk (SX_DEBUG_TX, "port: %p\n", port);
tty = port->tty;
-
+
if (port->IER & IER_TXEMPTY) {
/* FIFO drained */
sx_out(bp, CD186x_CAR, port_No(port));
@@ -796,7 +794,7 @@ static inline void sx_transmit(struct specialix_board * bp)
func_exit();
return;
}
-
+
if ((port->xmit_cnt <= 0 && !port->break_length)
|| tty->stopped || tty->hw_stopped) {
sx_out(bp, CD186x_CAR, port_No(port));
@@ -805,7 +803,7 @@ static inline void sx_transmit(struct specialix_board * bp)
func_exit();
return;
}
-
+
if (port->break_length) {
if (port->break_length > 0) {
if (port->COR2 & COR2_ETC) {
@@ -831,7 +829,7 @@ static inline void sx_transmit(struct specialix_board * bp)
func_exit();
return;
}
-
+
count = CD186x_NFIFO;
do {
sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
@@ -839,7 +837,7 @@ static inline void sx_transmit(struct specialix_board * bp)
if (--port->xmit_cnt <= 0)
break;
} while (--count > 0);
-
+
if (port->xmit_cnt <= 0) {
sx_out(bp, CD186x_CAR, port_No(port));
port->IER &= ~IER_TXRDY;
@@ -862,9 +860,9 @@ static inline void sx_check_modem(struct specialix_board * bp)
dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
if (!(port = sx_get_port(bp, "Modem")))
return;
-
+
tty = port->tty;
-
+
mcr = sx_in(bp, CD186x_MCR);
printk ("mcr = %02x.\n", mcr);
@@ -879,7 +877,7 @@ static inline void sx_check_modem(struct specialix_board * bp)
schedule_work(&port->tqueue_hangup);
}
}
-
+
#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
if (mcr & MCR_CTSCHG) {
if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
@@ -906,7 +904,7 @@ static inline void sx_check_modem(struct specialix_board * bp)
sx_out(bp, CD186x_IER, port->IER);
}
#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
-
+
/* Clear change bits */
sx_out(bp, CD186x_MCR, 0);
}
@@ -940,7 +938,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
(SRSR_RREQint |
SRSR_TREQint |
- SRSR_MREQint)))) {
+ SRSR_MREQint)))) {
if (status & SRSR_RREQint) {
ack = sx_in(bp, CD186x_RRAR);
@@ -951,7 +949,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
else
printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
board_No(bp), status, ack);
-
+
} else if (status & SRSR_TREQint) {
ack = sx_in(bp, CD186x_TRAR);
@@ -963,13 +961,13 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} else if (status & SRSR_MREQint) {
ack = sx_in(bp, CD186x_MRAR);
- if (ack == (SX_ID | GIVR_IT_MODEM))
+ if (ack == (SX_ID | GIVR_IT_MODEM))
sx_check_modem(bp);
else
printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
board_No(bp), status, ack);
-
- }
+
+ }
sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
}
@@ -1026,7 +1024,7 @@ static inline int sx_setup_board(struct specialix_board * bp)
{
int error;
- if (bp->flags & SX_BOARD_ACTIVE)
+ if (bp->flags & SX_BOARD_ACTIVE)
return 0;
if (bp->flags & SX_BOARD_IS_PCI)
@@ -1034,7 +1032,7 @@ static inline int sx_setup_board(struct specialix_board * bp)
else
error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
- if (error)
+ if (error)
return error;
turn_ints_on (bp);
@@ -1055,7 +1053,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp)
}
bp->flags &= ~SX_BOARD_ACTIVE;
-
+
dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
bp->irq, board_No (bp));
free_irq(bp->irq, bp);
@@ -1068,7 +1066,7 @@ static inline void sx_shutdown_board(struct specialix_board *bp)
/*
- * Setting up port characteristics.
+ * Setting up port characteristics.
* Must be called with disabled interrupts
*/
static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
@@ -1103,10 +1101,10 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
spin_unlock_irqrestore(&bp->lock, flags);
dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
baud = C_BAUD(tty);
-
+
if (baud & CBAUDEX) {
baud &= ~CBAUDEX;
- if (baud < 1 || baud > 2)
+ if (baud < 1 || baud > 2)
port->tty->termios->c_cflag &= ~CBAUDEX;
else
baud += 15;
@@ -1117,8 +1115,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
baud += 2;
}
-
-
+
+
if (!baud_table[baud]) {
/* Drop DTR & exit */
dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
@@ -1127,7 +1125,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_MSVR, port->MSVR );
spin_unlock_irqrestore(&bp->lock, flags);
- }
+ }
else
dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
return;
@@ -1137,9 +1135,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
port ->MSVR |= MSVR_DTR;
}
}
-
+
/*
- * Now we must calculate some speed depended things
+ * Now we must calculate some speed depended things
*/
/* Set baud rate for port */
@@ -1152,7 +1150,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
CD186x_TPC/2) / CD186x_TPC);
- if ((tmp < 0x10) && time_before(again, jiffies)) {
+ if ((tmp < 0x10) && time_before(again, jiffies)) {
again = jiffies + HZ * 60;
/* Page 48 of version 2.0 of the CL-CD1865 databook */
if (tmp >= 12) {
@@ -1164,27 +1162,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
"Warning: overstressing Cirrus chip. "
"This might not work.\n"
- "Read specialix.txt for more info.\n",
+ "Read specialix.txt for more info.\n",
port_No (port), tmp);
}
}
spin_lock_irqsave(&bp->lock, flags);
- sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
- sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
- sx_out(bp, CD186x_RBPRL, tmp & 0xff);
+ sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
+ sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
+ sx_out(bp, CD186x_RBPRL, tmp & 0xff);
sx_out(bp, CD186x_TBPRL, tmp & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
if (port->custom_divisor) {
baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
baud = ( baud + 5 ) / 10;
- } else
+ } else
baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
/* Two timer ticks seems enough to wakeup something like SLIP driver */
- tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
+ tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
SERIAL_XMIT_SIZE - 1 : tmp);
-
+
/* Receiver timeout will be transmission time for 1.5 chars */
tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
tmp = (tmp > 0xff) ? 0xff : tmp;
@@ -1205,29 +1203,29 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
cor1 |= COR1_8BITS;
break;
}
-
- if (C_CSTOPB(tty))
+
+ if (C_CSTOPB(tty))
cor1 |= COR1_2SB;
-
+
cor1 |= COR1_IGNORE;
if (C_PARENB(tty)) {
cor1 |= COR1_NORMPAR;
- if (C_PARODD(tty))
+ if (C_PARODD(tty))
cor1 |= COR1_ODDP;
- if (I_INPCK(tty))
+ if (I_INPCK(tty))
cor1 &= ~COR1_IGNORE;
}
/* Set marking of some errors */
port->mark_mask = RCSR_OE | RCSR_TOUT;
- if (I_INPCK(tty))
+ if (I_INPCK(tty))
port->mark_mask |= RCSR_FE | RCSR_PE;
- if (I_BRKINT(tty) || I_PARMRK(tty))
+ if (I_BRKINT(tty) || I_PARMRK(tty))
port->mark_mask |= RCSR_BREAK;
- if (I_IGNPAR(tty))
+ if (I_IGNPAR(tty))
port->mark_mask &= ~(RCSR_FE | RCSR_PE);
if (I_IGNBRK(tty)) {
port->mark_mask &= ~RCSR_BREAK;
- if (I_IGNPAR(tty))
+ if (I_IGNPAR(tty))
/* Real raw mode. Ignore all */
port->mark_mask &= ~RCSR_OE;
}
@@ -1241,7 +1239,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
spin_unlock_irqrestore(&bp->lock, flags);
#else
- port->COR2 |= COR2_CTSAE;
+ port->COR2 |= COR2_CTSAE;
#endif
}
/* Enable Software Flow Control. FIXME: I'm not sure about this */
@@ -1264,11 +1262,11 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
mcor1 |= MCOR1_CDZD;
mcor2 |= MCOR2_CDOD;
}
-
- if (C_CREAD(tty))
+
+ if (C_CREAD(tty))
/* Enable receiver */
port->IER |= IER_RXD;
-
+
/* Set input FIFO size (1-8 bytes) */
cor3 |= sx_rxfifo;
/* Setting up CD186x channel registers */
@@ -1311,11 +1309,11 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
func_exit();
return 0;
}
-
+
if (!port->xmit_buf) {
/* We may sleep in get_zeroed_page() */
unsigned long tmp;
-
+
if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
func_exit();
return -ENOMEM;
@@ -1328,10 +1326,10 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
}
port->xmit_buf = (unsigned char *) tmp;
}
-
+
spin_lock_irqsave(&port->lock, flags);
- if (port->tty)
+ if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
@@ -1340,7 +1338,7 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
spin_unlock_irqrestore(&port->lock, flags);
-
+
func_exit();
return 0;
}
@@ -1352,14 +1350,14 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
struct tty_struct *tty;
int i;
unsigned long flags;
-
+
func_enter();
if (!(port->flags & ASYNC_INITIALIZED)) {
func_exit();
return;
}
-
+
if (sx_debug & SX_DEBUG_FIFO) {
dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
board_No(bp), port_No(port), port->overrun);
@@ -1394,13 +1392,13 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
port->flags &= ~ASYNC_INITIALIZED;
-
- if (!bp->count)
+
+ if (!bp->count)
sx_shutdown_board(bp);
func_exit();
}
-
+
static int block_til_ready(struct tty_struct *tty, struct file * filp,
struct specialix_port *port)
{
@@ -1427,7 +1425,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
return -ERESTARTSYS;
}
}
-
+
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
@@ -1477,7 +1475,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
- retval = -ERESTARTSYS;
+ retval = -ERESTARTSYS;
break;
}
if (!(port->flags & ASYNC_CLOSING) &&
@@ -1506,7 +1504,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
port->flags |= ASYNC_NORMAL_ACTIVE;
func_exit();
return 0;
-}
+}
static int sx_open(struct tty_struct * tty, struct file * filp)
@@ -1526,7 +1524,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
func_exit();
return -ENODEV;
}
-
+
bp = &sx_board[board];
port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
port->overrun = 0;
@@ -1557,7 +1555,7 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
func_enter();
return error;
}
-
+
if ((error = block_til_ready(tty, filp, port))) {
func_enter();
return error;
@@ -1574,7 +1572,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
struct specialix_board *bp;
unsigned long flags;
unsigned long timeout;
-
+
func_enter();
if (!port || sx_paranoia_check(port, tty->name, "close")) {
func_exit();
@@ -1587,7 +1585,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
func_exit();
return;
}
-
+
bp = port_Board(port);
if ((tty->count == 1) && (port->count != 1)) {
printk(KERN_ERR "sx%d: sx_close: bad port count;"
@@ -1607,7 +1605,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
port->flags |= ASYNC_CLOSING;
/*
- * Now we wait for the transmit buffer to clear; and we notify
+ * Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
@@ -1681,7 +1679,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
-static int sx_write(struct tty_struct * tty,
+static int sx_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
@@ -1694,7 +1692,7 @@ static int sx_write(struct tty_struct * tty,
func_exit();
return 0;
}
-
+
bp = port_Board(port);
if (!tty || !port->xmit_buf || !tmp_buf) {
@@ -1824,7 +1822,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
func_enter();
-
+
if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
func_exit();
return 0;
@@ -1881,13 +1879,13 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
port_No(port), status, sx_in (bp, CD186x_CAR));
dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
if (SX_CRTSCTS(port->tty)) {
- result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
+ result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
| ((status & MSVR_DTR) ? TIOCM_RTS : 0)
| ((status & MSVR_CD) ? TIOCM_CAR : 0)
|/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
} else {
- result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
+ result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
| ((status & MSVR_CD) ? TIOCM_CAR : 0)
|/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
@@ -1955,7 +1953,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
{
struct specialix_board *bp = port_Board(port);
unsigned long flags;
-
+
func_enter();
spin_lock_irqsave (&port->lock, flags);
@@ -1996,8 +1994,8 @@ static inline int sx_set_serial_info(struct specialix_port * port,
func_enter();
return -EFAULT;
}
-
-#if 0
+
+#if 0
if ((tmp.irq != bp->irq) ||
(tmp.port != bp->base) ||
(tmp.type != PORT_CIRRUS) ||
@@ -2008,12 +2006,12 @@ static inline int sx_set_serial_info(struct specialix_port * port,
func_exit();
return -EINVAL;
}
-#endif
+#endif
change_speed = ((port->flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
change_speed |= (tmp.custom_divisor != port->custom_divisor);
-
+
if (!capable(CAP_SYS_ADMIN)) {
if ((tmp.close_delay != port->close_delay) ||
(tmp.closing_wait != port->closing_wait) ||
@@ -2045,7 +2043,7 @@ static inline int sx_get_serial_info(struct specialix_port * port,
{
struct serial_struct tmp;
struct specialix_board *bp = port_Board(port);
-
+
func_enter();
/*
@@ -2074,7 +2072,7 @@ static inline int sx_get_serial_info(struct specialix_port * port,
}
-static int sx_ioctl(struct tty_struct * tty, struct file * filp,
+static int sx_ioctl(struct tty_struct * tty, struct file * filp,
unsigned int cmd, unsigned long arg)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
@@ -2087,7 +2085,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
func_exit();
return -ENODEV;
}
-
+
switch (cmd) {
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
@@ -2129,7 +2127,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
case TIOCGSERIAL:
func_exit();
return sx_get_serial_info(port, argp);
- case TIOCSSERIAL:
+ case TIOCSSERIAL:
func_exit();
return sx_set_serial_info(port, argp);
default:
@@ -2153,16 +2151,16 @@ static void sx_throttle(struct tty_struct * tty)
func_exit();
return;
}
-
+
bp = port_Board(port);
-
+
/* Use DTR instead of RTS ! */
- if (SX_CRTSCTS (tty))
+ if (SX_CRTSCTS (tty))
port->MSVR &= ~MSVR_DTR;
else {
/* Auch!!! I think the system shouldn't call this then. */
/* Or maybe we're supposed (allowed?) to do our side of hw
- handshake anyway, even when hardware handshake is off.
+ handshake anyway, even when hardware handshake is off.
When you see this in your logs, please report.... */
printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
port_No (port));
@@ -2193,14 +2191,14 @@ static void sx_unthrottle(struct tty_struct * tty)
unsigned long flags;
func_enter();
-
+
if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
func_exit();
return;
}
-
+
bp = port_Board(port);
-
+
spin_lock_irqsave(&port->lock, flags);
/* XXXX Use DTR INSTEAD???? */
if (SX_CRTSCTS(tty)) {
@@ -2234,14 +2232,14 @@ static void sx_stop(struct tty_struct * tty)
unsigned long flags;
func_enter();
-
+
if (sx_paranoia_check(port, tty->name, "sx_stop")) {
func_exit();
return;
}
bp = port_Board(port);
-
+
spin_lock_irqsave(&port->lock, flags);
port->IER &= ~IER_TXRDY;
spin_lock_irqsave(&bp->lock, flags);
@@ -2261,14 +2259,14 @@ static void sx_start(struct tty_struct * tty)
unsigned long flags;
func_enter();
-
+
if (sx_paranoia_check(port, tty->name, "sx_start")) {
func_exit();
return;
}
-
+
bp = port_Board(port);
-
+
spin_lock_irqsave(&port->lock, flags);
if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
port->IER |= IER_TXRDY;
@@ -2290,13 +2288,13 @@ static void sx_start(struct tty_struct * tty)
*
* serial interrupt routine -> (workqueue) ->
* do_sx_hangup() -> tty->hangup() -> sx_hangup()
- *
+ *
*/
static void do_sx_hangup(void *private_)
{
struct specialix_port *port = (struct specialix_port *) private_;
struct tty_struct *tty;
-
+
func_enter();
tty = port->tty;
@@ -2319,9 +2317,9 @@ static void sx_hangup(struct tty_struct * tty)
func_exit();
return;
}
-
+
bp = port_Board(port);
-
+
sx_shutdown_port(bp, port);
spin_lock_irqsave(&port->lock, flags);
port->event = 0;
@@ -2346,10 +2344,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
struct specialix_board * bp;
-
+
if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
return;
-
+
if (tty->termios->c_cflag == old_termios->c_cflag &&
tty->termios->c_iflag == old_termios->c_iflag)
return;
@@ -2420,7 +2418,7 @@ static int sx_init_drivers(void)
func_exit();
return 1;
}
-
+
if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
printk(KERN_ERR "sx: Couldn't get free page.\n");
put_tty_driver(specialix_driver);
@@ -2457,7 +2455,7 @@ static int sx_init_drivers(void)
init_waitqueue_head(&sx_port[i].close_wait);
spin_lock_init(&sx_port[i].lock);
}
-
+
func_exit();
return 0;
}
@@ -2472,8 +2470,8 @@ static void sx_release_drivers(void)
func_exit();
}
-/*
- * This routine must be called by kernel at boot time
+/*
+ * This routine must be called by kernel at boot time
*/
static int __init specialix_init(void)
{
@@ -2489,7 +2487,7 @@ static int __init specialix_init(void)
#else
printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
#endif
-
+
for (i = 0; i < SX_NBOARD; i++)
sx_board[i].lock = SPIN_LOCK_UNLOCKED;
@@ -2498,7 +2496,7 @@ static int __init specialix_init(void)
return -EIO;
}
- for (i = 0; i < SX_NBOARD; i++)
+ for (i = 0; i < SX_NBOARD; i++)
if (sx_board[i].base && !sx_probe(&sx_board[i]))
found++;
@@ -2512,8 +2510,8 @@ static int __init specialix_init(void)
i++;
continue;
}
- pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_IO8,
+ pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+ PCI_DEVICE_ID_SPECIALIX_IO8,
pdev);
if (!pdev) break;
@@ -2557,10 +2555,10 @@ module_param(sx_poll, int, 0);
/*
* You can setup up to 4 boards.
* by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
- * You should specify the IRQs too in that case "irq=....,...".
- *
+ * You should specify the IRQs too in that case "irq=....,...".
+ *
* More than 4 boards in one computer is not possible, as the card can
- * only use 4 different interrupts.
+ * only use 4 different interrupts.
*
*/
static int __init specialix_init_module(void)
@@ -2583,16 +2581,16 @@ static int __init specialix_init_module(void)
return specialix_init();
}
-
+
static void __exit specialix_exit_module(void)
{
int i;
-
+
func_enter();
sx_release_drivers();
for (i = 0; i < SX_NBOARD; i++)
- if (sx_board[i].flags & SX_BOARD_PRESENT)
+ if (sx_board[i].flags & SX_BOARD_PRESENT)
sx_release_io_range(&sx_board[i]);
#ifdef SPECIALIX_TIMER
del_timer (&missed_irq_timer);
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 951545a6ef2d..1c686414e0a1 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -3095,7 +3095,9 @@ static int __init stl_init(void)
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i);
- class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+ class_device_create(stallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i), NULL,
+ "staliomem%d", i);
}
stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 37c8bea8e2b0..0133dc0e25d0 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/synclink.c
*
- * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
+ * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
* high speed multiprotocol serial adapters.
@@ -141,9 +141,9 @@ static MGSL_PARAMS default_params = {
typedef struct _DMABUFFERENTRY
{
u32 phys_addr; /* 32-bit flat physical address of data buffer */
- u16 count; /* buffer size/data count */
- u16 status; /* Control/status field */
- u16 rcc; /* character count field */
+ volatile u16 count; /* buffer size/data count */
+ volatile u16 status; /* Control/status field */
+ volatile u16 rcc; /* character count field */
u16 reserved; /* padding required by 16C32 */
u32 link; /* 32-bit flat link to next buffer entry */
char *virt_addr; /* virtual address of data buffer */
@@ -896,7 +896,7 @@ module_param_array(txdmabufs, int, NULL, 0);
module_param_array(txholdbufs, int, NULL, 0);
static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.28 $";
+static char *driver_version = "$Revision: 4.37 $";
static int synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent);
@@ -912,6 +912,7 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
MODULE_LICENSE("GPL");
static struct pci_driver synclink_pci_driver = {
+ .owner = THIS_MODULE,
.name = "synclink",
.id_table = synclink_pci_tbl,
.probe = synclink_init_one,
@@ -1814,6 +1815,8 @@ static int startup(struct mgsl_struct * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
init_timer(&info->tx_timer);
info->tx_timer.data = (unsigned long)info;
info->tx_timer.function = mgsl_tx_timeout;
@@ -2470,12 +2473,12 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *
printk("%s(%d):mgsl_get_params(%s)\n",
__FILE__,__LINE__, info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):mgsl_get_stats(%s) user buffer copy failed\n",
- __FILE__,__LINE__,info->device_name);
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
}
return 0;
@@ -6149,6 +6152,11 @@ static void usc_set_async_mode( struct mgsl_struct *info )
usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
}
+ if (info->params.loopback) {
+ info->loopback_bits = 0x300;
+ outw(0x0300, info->io_base + CCAR);
+ }
+
} /* end of usc_set_async_mode() */
/* usc_loopback_frame()
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ec949e4c070f..f185724448b1 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
*
* Device driver for Microgate SyncLink Multiport
* high speed multiprotocol serial adapter.
@@ -55,7 +55,6 @@
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <asm/serial.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
@@ -487,7 +486,7 @@ module_param_array(maxframe, int, NULL, 0);
module_param_array(dosyncppp, int, NULL, 0);
static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.34 $";
+static char *driver_version = "$Revision: 4.38 $";
static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -501,6 +500,7 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
MODULE_LICENSE("GPL");
static struct pci_driver synclinkmp_pci_driver = {
+ .owner = THIS_MODULE,
.name = "synclinkmp",
.id_table = synclinkmp_pci_tbl,
.probe = synclinkmp_init_one,
@@ -556,7 +556,6 @@ static int set_txidle(SLMP_INFO *info, int idle_mode);
static int tx_enable(SLMP_INFO *info, int enable);
static int tx_abort(SLMP_INFO *info);
static int rx_enable(SLMP_INFO *info, int enable);
-static int map_status(int signals);
static int modem_input_wait(SLMP_INFO *info,int arg);
static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
@@ -645,7 +644,7 @@ static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation le
static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes
static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x00800029;
+static u32 lcr1_brdr_value = 0x00800028;
static u32 read_ahead_count = 8;
@@ -2750,6 +2749,8 @@ static int startup(SLMP_INFO * info)
info->pending_bh = 0;
+ memset(&info->icount, 0, sizeof(info->icount));
+
/* program hardware for current parameters */
reset_port(info);
@@ -2953,12 +2954,12 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
printk("%s(%d):%s get_params()\n",
__FILE__,__LINE__, info->device_name);
- COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):%s get_stats() user buffer copy failed\n",
- __FILE__,__LINE__,info->device_name);
- return -EFAULT;
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+ if (err)
+ return -EFAULT;
}
return 0;
@@ -3109,16 +3110,6 @@ static int rx_enable(SLMP_INFO * info, int enable)
return 0;
}
-static int map_status(int signals)
-{
- /* Map status bits to API event bits */
-
- return ((signals & SerialSignal_DSR) ? MgslEvent_DsrActive : MgslEvent_DsrInactive) +
- ((signals & SerialSignal_CTS) ? MgslEvent_CtsActive : MgslEvent_CtsInactive) +
- ((signals & SerialSignal_DCD) ? MgslEvent_DcdActive : MgslEvent_DcdInactive) +
- ((signals & SerialSignal_RI) ? MgslEvent_RiActive : MgslEvent_RiInactive);
-}
-
/* wait for specified event to occur
*/
static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
@@ -3145,7 +3136,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
/* return immediately if state matches requested events */
get_signals(info);
- s = map_status(info->serial_signals);
+ s = info->serial_signals;
events = mask &
( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
@@ -4489,11 +4480,13 @@ void async_mode(SLMP_INFO *info)
/* MD2, Mode Register 2
*
* 07..02 Reserved, must be 0
- * 01..00 CNCT<1..0> Channel connection, 0=normal
+ * 01..00 CNCT<1..0> Channel connection, 00=normal 11=local loopback
*
* 0000 0000
*/
RegValue = 0x00;
+ if (info->params.loopback)
+ RegValue |= (BIT1 + BIT0);
write_reg(info, MD2, RegValue);
/* RXS, Receive clock source
@@ -4574,9 +4567,6 @@ void async_mode(SLMP_INFO *info)
write_reg(info, IE2, info->ie2_value);
set_rate( info, info->params.data_rate * 16 );
-
- if (info->params.loopback)
- enable_loopback(info,1);
}
/* Program the SCA for HDLC communications.
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index eb7058cbf015..24355b23b2ca 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index ec78d2f161f7..41a94bc79f67 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out;
}
- class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
+ class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
TIPAR_MINOR + nr), NULL, "par%d", nr);
/* Use devfs, tree: /dev/ticables/par/[0..2] */
err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
new file mode 100644
index 000000000000..12167c04fa4c
--- /dev/null
+++ b/drivers/char/tlclk.c
@@ -0,0 +1,897 @@
+/*
+ * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010
+ *
+ * Copyright (C) 2005 Kontron Canada
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT. 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.
+ *
+ * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current
+ * Maintainer <mark.gross@intel.com>
+ *
+ * Description : This is the TELECOM CLOCK module driver for the ATCA
+ * MPCBL0010 ATCA computer.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/delay.h> /* udelay */
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <asm/io.h> /* inb/outb */
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
+MODULE_LICENSE("GPL");
+
+/*Hardware Reset of the PLL */
+#define RESET_ON 0x00
+#define RESET_OFF 0x01
+
+/* MODE SELECT */
+#define NORMAL_MODE 0x00
+#define HOLDOVER_MODE 0x10
+#define FREERUN_MODE 0x20
+
+/* FILTER SELECT */
+#define FILTER_6HZ 0x04
+#define FILTER_12HZ 0x00
+
+/* SELECT REFERENCE FREQUENCY */
+#define REF_CLK1_8kHz 0x00
+#define REF_CLK2_19_44MHz 0x02
+
+/* Select primary or secondary redundant clock */
+#define PRIMARY_CLOCK 0x00
+#define SECONDARY_CLOCK 0x01
+
+/* CLOCK TRANSMISSION DEFINE */
+#define CLK_8kHz 0xff
+#define CLK_16_384MHz 0xfb
+
+#define CLK_1_544MHz 0x00
+#define CLK_2_048MHz 0x01
+#define CLK_4_096MHz 0x02
+#define CLK_6_312MHz 0x03
+#define CLK_8_192MHz 0x04
+#define CLK_19_440MHz 0x06
+
+#define CLK_8_592MHz 0x08
+#define CLK_11_184MHz 0x09
+#define CLK_34_368MHz 0x0b
+#define CLK_44_736MHz 0x0a
+
+/* RECEIVED REFERENCE */
+#define AMC_B1 0
+#define AMC_B2 1
+
+/* HARDWARE SWITCHING DEFINE */
+#define HW_ENABLE 0x80
+#define HW_DISABLE 0x00
+
+/* HARDWARE SWITCHING MODE DEFINE */
+#define PLL_HOLDOVER 0x40
+#define LOST_CLOCK 0x00
+
+/* ALARMS DEFINE */
+#define UNLOCK_MASK 0x10
+#define HOLDOVER_MASK 0x20
+#define SEC_LOST_MASK 0x40
+#define PRI_LOST_MASK 0x80
+
+/* INTERRUPT CAUSE DEFINE */
+
+#define PRI_LOS_01_MASK 0x01
+#define PRI_LOS_10_MASK 0x02
+
+#define SEC_LOS_01_MASK 0x04
+#define SEC_LOS_10_MASK 0x08
+
+#define HOLDOVER_01_MASK 0x10
+#define HOLDOVER_10_MASK 0x20
+
+#define UNLOCK_01_MASK 0x40
+#define UNLOCK_10_MASK 0x80
+
+struct tlclk_alarms {
+ __u32 lost_clocks;
+ __u32 lost_primary_clock;
+ __u32 lost_secondary_clock;
+ __u32 primary_clock_back;
+ __u32 secondary_clock_back;
+ __u32 switchover_primary;
+ __u32 switchover_secondary;
+ __u32 pll_holdover;
+ __u32 pll_end_holdover;
+ __u32 pll_lost_sync;
+ __u32 pll_sync;
+};
+/* Telecom clock I/O register definition */
+#define TLCLK_BASE 0xa08
+#define TLCLK_REG0 TLCLK_BASE
+#define TLCLK_REG1 (TLCLK_BASE+1)
+#define TLCLK_REG2 (TLCLK_BASE+2)
+#define TLCLK_REG3 (TLCLK_BASE+3)
+#define TLCLK_REG4 (TLCLK_BASE+4)
+#define TLCLK_REG5 (TLCLK_BASE+5)
+#define TLCLK_REG6 (TLCLK_BASE+6)
+#define TLCLK_REG7 (TLCLK_BASE+7)
+
+#define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port)
+
+/* 0 = Dynamic allocation of the major device number */
+#define TLCLK_MAJOR 0
+
+/* sysfs interface definition:
+Upon loading the driver will create a sysfs directory under
+/sys/devices/platform/telco_clock.
+
+This directory exports the following interfaces. There operation is
+documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
+alarms :
+current_ref :
+enable_clk3a_output :
+enable_clk3b_output :
+enable_clka0_output :
+enable_clka1_output :
+enable_clkb0_output :
+enable_clkb1_output :
+filter_select :
+hardware_switching :
+hardware_switching_mode :
+interrupt_switch :
+mode_select :
+refalign :
+reset :
+select_amcb1_transmit_clock :
+select_amcb2_transmit_clock :
+select_redundant_clock :
+select_ref_frequency :
+test_mode :
+
+All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
+has the same effect as echo 0x99 > refalign.
+*/
+
+static unsigned int telclk_interrupt;
+
+static int int_events; /* Event that generate a interrupt */
+static int got_event; /* if events processing have been done */
+
+static void switchover_timeout(unsigned long data);
+static struct timer_list switchover_timer =
+ TIMER_INITIALIZER(switchover_timeout , 0, 0);
+
+static struct tlclk_alarms *alarm_events;
+
+static DEFINE_SPINLOCK(event_lock);
+
+static int tlclk_major = TLCLK_MAJOR;
+
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static int tlclk_open(struct inode *inode, struct file *filp)
+{
+ int result;
+
+ /* Make sure there is no interrupt pending while
+ * initialising interrupt handler */
+ inb(TLCLK_REG6);
+
+ /* This device is wired through the FPGA IO space of the ATCA blade
+ * we can't share this IRQ */
+ result = request_irq(telclk_interrupt, &tlclk_interrupt,
+ SA_INTERRUPT, "telco_clock", tlclk_interrupt);
+ if (result == -EBUSY) {
+ printk(KERN_ERR "telco_clock: Interrupt can't be reserved!\n");
+ return -EBUSY;
+ }
+ inb(TLCLK_REG6); /* Clear interrupt events */
+
+ return 0;
+}
+
+static int tlclk_release(struct inode *inode, struct file *filp)
+{
+ free_irq(telclk_interrupt, tlclk_interrupt);
+
+ return 0;
+}
+
+ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ if (count < sizeof(struct tlclk_alarms))
+ return -EIO;
+
+ wait_event_interruptible(wq, got_event);
+ if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
+ return -EFAULT;
+
+ memset(alarm_events, 0, sizeof(struct tlclk_alarms));
+ got_event = 0;
+
+ return sizeof(struct tlclk_alarms);
+}
+
+ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ return 0;
+}
+
+static struct file_operations tlclk_fops = {
+ .read = tlclk_read,
+ .write = tlclk_write,
+ .open = tlclk_open,
+ .release = tlclk_release,
+
+};
+
+static struct miscdevice tlclk_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "telco_clock",
+ .fops = &tlclk_fops,
+};
+
+static ssize_t show_current_ref(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long ret_val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_lock, flags);
+ ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
+
+
+static ssize_t show_interrupt_switch(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long ret_val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_lock, flags);
+ ret_val = inb(TLCLK_REG6);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(interrupt_switch, S_IRUGO,
+ show_interrupt_switch, NULL);
+
+static ssize_t show_alarms(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long ret_val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_lock, flags);
+ ret_val = (inb(TLCLK_REG2) & 0xf0);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static ssize_t store_enable_clk3b_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
+ store_enable_clk3b_output);
+
+static ssize_t store_enable_clk3a_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
+ store_enable_clk3a_output);
+
+static ssize_t store_enable_clkb1_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
+ store_enable_clkb1_output);
+
+
+static ssize_t store_enable_clka1_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
+ store_enable_clka1_output);
+
+static ssize_t store_enable_clkb0_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
+ store_enable_clkb0_output);
+
+static ssize_t store_enable_clka0_output(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
+ store_enable_clka0_output);
+
+static ssize_t store_test_mode(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode);
+
+static ssize_t store_select_amcb2_transmit_clock(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned char val;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+ SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
+ SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+ } else if (val >= CLK_8_592MHz) {
+ SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
+ switch (val) {
+ case CLK_8_592MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ break;
+ case CLK_11_184MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+ break;
+ case CLK_34_368MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+ break;
+ case CLK_44_736MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ break;
+ }
+ } else
+ SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
+
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
+ store_select_amcb2_transmit_clock);
+
+static ssize_t store_select_amcb1_transmit_clock(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+ SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
+ SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+ } else if (val >= CLK_8_592MHz) {
+ SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
+ switch (val) {
+ case CLK_8_592MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ break;
+ case CLK_11_184MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+ break;
+ case CLK_34_368MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+ break;
+ case CLK_44_736MHz:
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ break;
+ }
+ } else
+ SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
+ store_select_amcb1_transmit_clock);
+
+static ssize_t store_select_redundant_clock(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
+ store_select_redundant_clock);
+
+static ssize_t store_select_ref_frequency(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
+ store_select_ref_frequency);
+
+static ssize_t store_filter_select(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
+
+static ssize_t store_hardware_switching_mode(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
+ store_hardware_switching_mode);
+
+static ssize_t store_hardware_switching(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
+ store_hardware_switching);
+
+static ssize_t store_refalign (struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+ udelay(2);
+ SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
+ udelay(2);
+ SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
+
+static ssize_t store_mode_select (struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
+
+static ssize_t store_reset (struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
+
+static struct attribute *tlclk_sysfs_entries[] = {
+ &dev_attr_current_ref.attr,
+ &dev_attr_interrupt_switch.attr,
+ &dev_attr_alarms.attr,
+ &dev_attr_enable_clk3a_output.attr,
+ &dev_attr_enable_clk3b_output.attr,
+ &dev_attr_enable_clkb1_output.attr,
+ &dev_attr_enable_clka1_output.attr,
+ &dev_attr_enable_clkb0_output.attr,
+ &dev_attr_enable_clka0_output.attr,
+ &dev_attr_test_mode.attr,
+ &dev_attr_select_amcb1_transmit_clock.attr,
+ &dev_attr_select_amcb2_transmit_clock.attr,
+ &dev_attr_select_redundant_clock.attr,
+ &dev_attr_select_ref_frequency.attr,
+ &dev_attr_filter_select.attr,
+ &dev_attr_hardware_switching_mode.attr,
+ &dev_attr_hardware_switching.attr,
+ &dev_attr_refalign.attr,
+ &dev_attr_mode_select.attr,
+ &dev_attr_reset.attr,
+ NULL
+};
+
+static struct attribute_group tlclk_attribute_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = tlclk_sysfs_entries,
+};
+
+static struct platform_device *tlclk_device;
+
+static int __init tlclk_init(void)
+{
+ int ret;
+
+ ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
+ if (ret < 0) {
+ printk(KERN_ERR "telco_clock: can't get major! %d\n", tlclk_major);
+ return ret;
+ }
+ alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
+ if (!alarm_events)
+ goto out1;
+
+ /* Read telecom clock IRQ number (Set by BIOS) */
+ if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
+ printk(KERN_ERR "tlclk: request_region failed! 0x%X\n",
+ TLCLK_BASE);
+ ret = -EBUSY;
+ goto out2;
+ }
+ telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
+
+ if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
+ printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw\n",
+ telclk_interrupt);
+ ret = -ENXIO;
+ goto out3;
+ }
+
+ init_timer(&switchover_timer);
+
+ ret = misc_register(&tlclk_miscdev);
+ if (ret < 0) {
+ printk(KERN_ERR " misc_register retruns %d\n", ret);
+ ret = -EBUSY;
+ goto out3;
+ }
+
+ tlclk_device = platform_device_register_simple("telco_clock",
+ -1, NULL, 0);
+ if (!tlclk_device) {
+ printk(KERN_ERR " platform_device_register retruns 0x%X\n",
+ (unsigned int) tlclk_device);
+ ret = -EBUSY;
+ goto out4;
+ }
+
+ ret = sysfs_create_group(&tlclk_device->dev.kobj,
+ &tlclk_attribute_group);
+ if (ret) {
+ printk(KERN_ERR "failed to create sysfs device attributes\n");
+ sysfs_remove_group(&tlclk_device->dev.kobj,
+ &tlclk_attribute_group);
+ goto out5;
+ }
+
+ return 0;
+out5:
+ platform_device_unregister(tlclk_device);
+out4:
+ misc_deregister(&tlclk_miscdev);
+out3:
+ release_region(TLCLK_BASE, 8);
+out2:
+ kfree(alarm_events);
+out1:
+ unregister_chrdev(tlclk_major, "telco_clock");
+ return ret;
+}
+
+static void __exit tlclk_cleanup(void)
+{
+ sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group);
+ platform_device_unregister(tlclk_device);
+ misc_deregister(&tlclk_miscdev);
+ unregister_chrdev(tlclk_major, "telco_clock");
+
+ release_region(TLCLK_BASE, 8);
+ del_timer_sync(&switchover_timer);
+ kfree(alarm_events);
+
+}
+
+static void switchover_timeout(unsigned long data)
+{
+ if ((data & 1)) {
+ if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+ alarm_events->switchover_primary++;
+ } else {
+ if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+ alarm_events->switchover_secondary++;
+ }
+
+ /* Alarm processing is done, wake up read task */
+ del_timer(&switchover_timer);
+ got_event = 1;
+ wake_up(&wq);
+}
+
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_lock, flags);
+ /* Read and clear interrupt events */
+ int_events = inb(TLCLK_REG6);
+
+ /* Primary_Los changed from 0 to 1 ? */
+ if (int_events & PRI_LOS_01_MASK) {
+ if (inb(TLCLK_REG2) & SEC_LOST_MASK)
+ alarm_events->lost_clocks++;
+ else
+ alarm_events->lost_primary_clock++;
+ }
+
+ /* Primary_Los changed from 1 to 0 ? */
+ if (int_events & PRI_LOS_10_MASK) {
+ alarm_events->primary_clock_back++;
+ SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
+ }
+ /* Secondary_Los changed from 0 to 1 ? */
+ if (int_events & SEC_LOS_01_MASK) {
+ if (inb(TLCLK_REG2) & PRI_LOST_MASK)
+ alarm_events->lost_clocks++;
+ else
+ alarm_events->lost_secondary_clock++;
+ }
+ /* Secondary_Los changed from 1 to 0 ? */
+ if (int_events & SEC_LOS_10_MASK) {
+ alarm_events->secondary_clock_back++;
+ SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
+ }
+ if (int_events & HOLDOVER_10_MASK)
+ alarm_events->pll_end_holdover++;
+
+ if (int_events & UNLOCK_01_MASK)
+ alarm_events->pll_lost_sync++;
+
+ if (int_events & UNLOCK_10_MASK)
+ alarm_events->pll_sync++;
+
+ /* Holdover changed from 0 to 1 ? */
+ if (int_events & HOLDOVER_01_MASK) {
+ alarm_events->pll_holdover++;
+
+ /* TIMEOUT in ~10ms */
+ switchover_timer.expires = jiffies + msecs_to_jiffies(10);
+ switchover_timer.data = inb(TLCLK_REG1);
+ add_timer(&switchover_timer);
+ } else {
+ got_event = 1;
+ wake_up(&wq);
+ }
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+module_init(tlclk_init);
+module_exit(tlclk_cleanup);
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 94a3b3e20bf9..b58adfe3ed19 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -17,6 +17,8 @@ config TCG_TPM
obtained at: <http://sourceforge.net/projects/trousers>. To
compile this driver as a module, choose M here; the module
will be called tpm. If unsure, say N.
+ Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
+ and CONFIG_PNPACPI.
config TCG_NSC
tristate "National Semiconductor TPM Interface"
@@ -36,12 +38,13 @@ config TCG_ATMEL
as a module, choose M here; the module will be called tpm_atmel.
config TCG_INFINEON
- tristate "Infineon Technologies SLD 9630 TPM Interface"
- depends on TCG_TPM
+ tristate "Infineon Technologies TPM Interface"
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from Infineon Technologies
- say Yes and it will be accessible from within Linux. To
- compile this driver as a module, choose M here; the module
+ (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
+ will be accessible from within Linux.
+ To compile this driver as a module, choose M here; the module
will be called tpm_infineon.
Further information on this driver and the supported hardware
can be found at http://www.prosec.rub.de/tpm
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 049d128ae7f0..303f15880466 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -64,7 +64,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"invalid count value %x %zx \n", count, bufsiz);
return -E2BIG;
}
@@ -72,21 +72,21 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
down(&chip->tpm_mutex);
if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
stop = jiffies + 2 * 60 * HZ;
do {
- u8 status = inb(chip->vendor->base + 1);
+ u8 status = chip->vendor->status(chip);
if ((status & chip->vendor->req_complete_mask) ==
chip->vendor->req_complete_val) {
goto out_recv;
}
if ((status == chip->vendor->req_canceled)) {
- dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+ dev_err(chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
@@ -97,14 +97,14 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
chip->vendor->cancel(chip);
- dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+ dev_err(chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
out:
up(&chip->tpm_mutex);
@@ -139,15 +139,14 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
__be32 index;
char *str = buf;
- struct tpm_chip *chip =
- pci_get_drvdata(to_pci_dev(dev));
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
memcpy(data, cap_pcr, sizeof(cap_pcr));
if ((len = tpm_transmit(chip, data, sizeof(data)))
< CAP_PCR_RESULT_SIZE) {
- dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
"attempting to determine the number of PCRS\n",
be32_to_cpu(*((__be32 *) (data + 6))));
return 0;
@@ -161,9 +160,10 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
memcpy(data + 10, &index, 4);
if ((len = tpm_transmit(chip, data, sizeof(data)))
< READ_PCR_RESULT_SIZE){
- dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+ dev_dbg(chip->dev, "A TPM error (%d) occurred"
" attempting to read PCR %d of %d\n",
- be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+ be32_to_cpu(*((__be32 *) (data + 6))),
+ i, num_pcrs);
goto out;
}
str += sprintf(str, "PCR-%02d: ", i);
@@ -191,21 +191,19 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
int i, rc;
char *str = buf;
- struct tpm_chip *chip =
- pci_get_drvdata(to_pci_dev(dev));
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
- data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+ data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
if (!data)
return -ENOMEM;
memcpy(data, readpubek, sizeof(readpubek));
- memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
READ_PUBEK_RESULT_SIZE) {
- dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
"attempting to read the PUBEK\n",
be32_to_cpu(*((__be32 *) (data + 6))));
rc = 0;
@@ -245,7 +243,6 @@ out:
kfree(data);
return rc;
}
-
EXPORT_SYMBOL_GPL(tpm_show_pubek);
#define CAP_VER_RESULT_SIZE 18
@@ -274,8 +271,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
ssize_t len;
char *str = buf;
- struct tpm_chip *chip =
- pci_get_drvdata(to_pci_dev(dev));
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
@@ -315,7 +311,6 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
-
/*
* Device file system interface to the TPM
*/
@@ -339,21 +334,20 @@ int tpm_open(struct inode *inode, struct file *file)
}
if (chip->num_opens) {
- dev_dbg(&chip->pci_dev->dev,
- "Another process owns this TPM\n");
+ dev_dbg(chip->dev, "Another process owns this TPM\n");
rc = -EBUSY;
goto err_out;
}
chip->num_opens++;
- pci_dev_get(chip->pci_dev);
+ 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--;
- pci_dev_put(chip->pci_dev);
+ put_device(chip->dev);
return -ENOMEM;
}
@@ -366,7 +360,6 @@ err_out:
spin_unlock(&driver_lock);
return rc;
}
-
EXPORT_SYMBOL_GPL(tpm_open);
int tpm_release(struct inode *inode, struct file *file)
@@ -378,15 +371,14 @@ int tpm_release(struct inode *inode, struct file *file)
chip->num_opens--;
del_singleshot_timer_sync(&chip->user_read_timer);
atomic_set(&chip->data_pending, 0);
- pci_dev_put(chip->pci_dev);
+ put_device(chip->dev);
kfree(chip->data_buffer);
spin_unlock(&driver_lock);
return 0;
}
-
EXPORT_SYMBOL_GPL(tpm_release);
-ssize_t tpm_write(struct file * file, const char __user * buf,
+ssize_t tpm_write(struct file *file, const char __user *buf,
size_t size, loff_t * off)
{
struct tpm_chip *chip = file->private_data;
@@ -422,7 +414,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
EXPORT_SYMBOL_GPL(tpm_write);
-ssize_t tpm_read(struct file * file, char __user * buf,
+ssize_t tpm_read(struct file * file, char __user *buf,
size_t size, loff_t * off)
{
struct tpm_chip *chip = file->private_data;
@@ -444,15 +436,14 @@ ssize_t tpm_read(struct file * file, char __user * buf,
return ret_size;
}
-
EXPORT_SYMBOL_GPL(tpm_read);
-void __devexit tpm_remove(struct pci_dev *pci_dev)
+void tpm_remove_hardware(struct device *dev)
{
- struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL) {
- dev_err(&pci_dev->dev, "No device data found\n");
+ dev_err(dev, "No device data found\n");
return;
}
@@ -462,22 +453,20 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
spin_unlock(&driver_lock);
- pci_set_drvdata(pci_dev, NULL);
+ dev_set_drvdata(dev, NULL);
misc_deregister(&chip->vendor->miscdev);
kfree(chip->vendor->miscdev.name);
- sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
+ sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
- pci_disable_device(pci_dev);
-
- dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
+ !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
kfree(chip);
- pci_dev_put(pci_dev);
+ put_device(dev);
}
-
-EXPORT_SYMBOL_GPL(tpm_remove);
+EXPORT_SYMBOL_GPL(tpm_remove_hardware);
static u8 savestate[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
@@ -489,32 +478,30 @@ static u8 savestate[] = {
* We are about to suspend. Save the TPM state
* so that it can be restored.
*/
-int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
+int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
{
- struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
tpm_transmit(chip, savestate, sizeof(savestate));
return 0;
}
-
EXPORT_SYMBOL_GPL(tpm_pm_suspend);
/*
* Resume from a power safe. The BIOS already restored
* the TPM state.
*/
-int tpm_pm_resume(struct pci_dev *pci_dev)
+int tpm_pm_resume(struct device *dev)
{
- struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
return 0;
}
-
EXPORT_SYMBOL_GPL(tpm_pm_resume);
/*
@@ -524,8 +511,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-int tpm_register_hardware(struct pci_dev *pci_dev,
- struct tpm_vendor_specific *entry)
+int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
{
#define DEVNAME_SIZE 7
@@ -534,12 +520,10 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
int i, j;
/* Driver specific per-device data */
- chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
- memset(chip, 0, sizeof(struct tpm_chip));
-
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
INIT_LIST_HEAD(&chip->list);
@@ -563,8 +547,7 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
dev_num_search_complete:
if (chip->dev_num < 0) {
- dev_err(&pci_dev->dev,
- "No available tpm device numbers\n");
+ dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
return -ENODEV;
} else if (chip->dev_num == 0)
@@ -576,15 +559,15 @@ dev_num_search_complete:
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor->miscdev.name = devname;
- chip->vendor->miscdev.dev = &(pci_dev->dev);
- chip->pci_dev = pci_dev_get(pci_dev);
+ chip->vendor->miscdev.dev = dev;
+ chip->dev = get_device(dev);
if (misc_register(&chip->vendor->miscdev)) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
chip->vendor->miscdev.name,
chip->vendor->miscdev.minor);
- pci_dev_put(pci_dev);
+ put_device(dev);
kfree(chip);
dev_mask[i] &= !(1 << j);
return -ENODEV;
@@ -592,17 +575,16 @@ dev_num_search_complete:
spin_lock(&driver_lock);
- pci_set_drvdata(pci_dev, chip);
+ dev_set_drvdata(dev, chip);
list_add(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
- sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
+ sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
return 0;
}
-
EXPORT_SYMBOL_GPL(tpm_register_hardware);
MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 373b41f6b460..99a60496ecc6 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
enum tpm_timeout {
TPM_TIMEOUT = 5, /* msecs */
@@ -55,12 +56,13 @@ struct tpm_vendor_specific {
int (*recv) (struct tpm_chip *, u8 *, size_t);
int (*send) (struct tpm_chip *, u8 *, size_t);
void (*cancel) (struct tpm_chip *);
+ u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
};
struct tpm_chip {
- struct pci_dev *pci_dev; /* PCI device stuff */
+ struct device *dev; /* Device stuff */
int dev_num; /* /dev/tpm# */
int num_opens; /* only one allowed */
@@ -91,13 +93,13 @@ static inline void tpm_write_index(int base, int index, int value)
outb(value & 0xFF, base+1);
}
-extern int tpm_register_hardware(struct pci_dev *,
+extern int tpm_register_hardware(struct device *,
struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
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 *);
-extern void __devexit tpm_remove(struct pci_dev *);
-extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
-extern int tpm_pm_resume(struct pci_dev *);
+extern void tpm_remove_hardware(struct device *);
+extern int tpm_pm_suspend(struct device *, pm_message_t);
+extern int tpm_pm_resume(struct device *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index cc2cc77fd174..32e01450c425 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/platform_device.h>
#include "tpm.h"
/* Atmel definitions */
@@ -40,7 +41,7 @@ enum tpm_atmel_read_status {
ATML_STATUS_READY = 0x08
};
-static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
u8 status, *hdr = buf;
u32 size;
@@ -54,7 +55,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
for (i = 0; i < 6; i++) {
status = inb(chip->vendor->base + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"error reading header\n");
return -EIO;
}
@@ -66,12 +67,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
size = be32_to_cpu(*native_size);
if (count < size) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
status = inb(chip->vendor->base + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"error reading data\n");
return -EIO;
}
@@ -83,7 +84,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
for (; i < size; i++) {
status = inb(chip->vendor->base + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"error reading data\n");
return -EIO;
}
@@ -93,20 +94,20 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
/* make sure data available is gone */
status = inb(chip->vendor->base + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
- dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+ dev_err(chip->dev, "data available is stuck\n");
return -EIO;
}
return size;
}
-static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
int i;
- dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+ dev_dbg(chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
- dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+ dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
outb(buf[i], chip->vendor->base);
}
@@ -118,6 +119,11 @@ static void tpm_atml_cancel(struct tpm_chip *chip)
outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
}
+static u8 tpm_atml_status(struct tpm_chip *chip)
+{
+ return inb(chip->vendor->base + 1);
+}
+
static struct file_operations atmel_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -137,7 +143,7 @@ static struct attribute* atmel_attrs[] = {
&dev_attr_pcrs.attr,
&dev_attr_caps.attr,
&dev_attr_cancel.attr,
- 0,
+ NULL,
};
static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
@@ -146,6 +152,7 @@ static struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
+ .status = tpm_atml_status,
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
.req_complete_val = ATML_STATUS_DATA_AVAIL,
.req_canceled = ATML_STATUS_READY,
@@ -153,83 +160,94 @@ static struct tpm_vendor_specific tpm_atmel = {
.miscdev = { .fops = &atmel_ops, },
};
-static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static struct platform_device *pdev;
+
+static void __devexit tpm_atml_remove(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip) {
+ release_region(chip->vendor->base, 2);
+ tpm_remove_hardware(chip->dev);
+ }
+}
+
+static struct device_driver atml_drv = {
+ .name = "tpm_atmel",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
{
- u8 version[4];
int rc = 0;
int lo, hi;
- if (pci_enable_device(pci_dev))
- return -EIO;
+ driver_register(&atml_drv);
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
tpm_atmel.base = (hi<<8)|lo;
- dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
/* verify that it is an Atmel part */
if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
|| tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
- rc = -ENODEV;
- goto out_err;
+ return -ENODEV;
}
- /* query chip for its version number */
- if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
- version[1] = tpm_read_index(TPM_ADDR, 0x01);
- version[2] = tpm_read_index(TPM_ADDR, 0x02);
- version[3] = tpm_read_index(TPM_ADDR, 0x03);
- } else {
- dev_info(&pci_dev->dev, "version query failed\n");
- rc = -ENODEV;
- goto out_err;
+ /* verify chip version number is 1.1 */
+ if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) ||
+ (tpm_read_index(TPM_ADDR, 0x01) != 0x01 ))
+ return -ENODEV;
+
+ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if ( !pdev )
+ return -ENOMEM;
+
+ pdev->name = "tpm_atmel0";
+ pdev->id = -1;
+ pdev->num_resources = 0;
+ pdev->dev.release = tpm_atml_remove;
+ pdev->dev.driver = &atml_drv;
+
+ if ((rc = platform_device_register(pdev)) < 0) {
+ kfree(pdev);
+ pdev = NULL;
+ return rc;
}
- if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
- goto out_err;
+ if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) {
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ return -EBUSY;
+ }
- dev_info(&pci_dev->dev,
- "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
- version[2], version[3]);
+ if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) {
+ release_region(tpm_atmel.base, 2);
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ return rc;
+ }
+ dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n",
+ tpm_atmel.base);
return 0;
-out_err:
- pci_disable_device(pci_dev);
- return rc;
-}
-
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
- {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
- {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
-
-static struct pci_driver atmel_pci_driver = {
- .name = "tpm_atmel",
- .id_table = tpm_pci_tbl,
- .probe = tpm_atml_init,
- .remove = __devexit_p(tpm_remove),
- .suspend = tpm_pm_suspend,
- .resume = tpm_pm_resume,
-};
-
-static int __init init_atmel(void)
-{
- return pci_register_driver(&atmel_pci_driver);
}
static void __exit cleanup_atmel(void)
{
- pci_unregister_driver(&atmel_pci_driver);
+ if (pdev) {
+ tpm_atml_remove(&pdev->dev);
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ }
+
+ driver_unregister(&atml_drv);
}
module_init(init_atmel);
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 0e3241645c19..8198dbb7370f 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -1,10 +1,11 @@
/*
* Description:
* Device Driver for the Infineon Technologies
- * SLD 9630 TT Trusted Platform Module
+ * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
* Specifications at www.trustedcomputinggroup.org
*
* Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
+ * Sirrix AG - security technologies, http://www.sirrix.com and
* Applied Data Security Group, Ruhr-University Bochum, Germany
* Project-Homepage: http://www.prosec.rub.de/tpm
*
@@ -12,9 +13,9 @@
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
- *
*/
+#include <linux/pnp.h>
#include "tpm.h"
/* Infineon specific definitions */
@@ -26,8 +27,13 @@
#define TPM_MSLEEP_TIME 3
/* gives number of max. msleep()-calls before throwing timeout */
#define TPM_MAX_TRIES 5000
-#define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1
-#define TPM_DATA (TPM_ADDR + 1) & 0xff
+#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
+
+/* These values will be filled after PnP-call */
+static int TPM_INF_DATA;
+static int TPM_INF_ADDR;
+static int TPM_INF_BASE;
+static int TPM_INF_PORT_LEN;
/* TPM header definitions */
enum infineon_tpm_header {
@@ -139,11 +145,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
}
if (i == TPM_MAX_TRIES) { /* timeout occurs */
if (wait_for_bit == STAT_XFE)
- dev_err(&chip->pci_dev->dev,
- "Timeout in wait(STAT_XFE)\n");
+ dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
if (wait_for_bit == STAT_RDA)
- dev_err(&chip->pci_dev->dev,
- "Timeout in wait(STAT_RDA)\n");
+ dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
return -EIO;
}
return 0;
@@ -166,7 +170,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
static void tpm_wtx(struct tpm_chip *chip)
{
number_of_wtx++;
- dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n",
+ dev_info(chip->dev, "Granting WTX (%02d / %02d)\n",
number_of_wtx, TPM_MAX_WTX_PACKAGES);
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX);
@@ -177,7 +181,7 @@ static void tpm_wtx(struct tpm_chip *chip)
static void tpm_wtx_abort(struct tpm_chip *chip)
{
- dev_info(&chip->pci_dev->dev, "Aborting WTX\n");
+ dev_info(chip->dev, "Aborting WTX\n");
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX_ABORT);
wait_and_send(chip, 0x00);
@@ -202,7 +206,7 @@ recv_begin:
}
if (buf[0] != TPM_VL_VER) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"Wrong transport protocol implementation!\n");
return -EIO;
}
@@ -217,8 +221,7 @@ recv_begin:
}
if ((size == 0x6D00) && (buf[1] == 0x80)) {
- dev_err(&chip->pci_dev->dev,
- "Error handling on vendor layer!\n");
+ dev_err(chip->dev, "Error handling on vendor layer!\n");
return -EIO;
}
@@ -230,7 +233,7 @@ recv_begin:
}
if (buf[1] == TPM_CTRL_WTX) {
- dev_info(&chip->pci_dev->dev, "WTX-package received\n");
+ dev_info(chip->dev, "WTX-package received\n");
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
tpm_wtx(chip);
goto recv_begin;
@@ -241,14 +244,14 @@ recv_begin:
}
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
- dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n");
+ dev_info(chip->dev, "WTX-abort acknowledged\n");
return size;
}
if (buf[1] == TPM_CTRL_ERROR) {
- dev_err(&chip->pci_dev->dev, "ERROR-package received:\n");
+ dev_err(chip->dev, "ERROR-package received:\n");
if (buf[4] == TPM_INF_NAK)
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"-> Negative acknowledgement"
" - retransmit command!\n");
return -EIO;
@@ -267,7 +270,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
ret = empty_fifo(chip, 1);
if (ret) {
- dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n");
+ dev_err(chip->dev, "Timeout while clearing FIFO\n");
return -EIO;
}
@@ -305,12 +308,18 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
static void tpm_inf_cancel(struct tpm_chip *chip)
{
- /* Nothing yet!
- This has something to do with the internal functions
- of the TPM. Abort isn't really necessary...
+ /*
+ Since we are using the legacy mode to communicate
+ with the TPM, we have no cancel functions, but have
+ a workaround for interrupting the TPM through WTX.
*/
}
+static u8 tpm_inf_status(struct tpm_chip *chip)
+{
+ return inb(chip->vendor->base + STAT);
+}
+
static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
@@ -339,129 +348,175 @@ static struct tpm_vendor_specific tpm_inf = {
.recv = tpm_inf_recv,
.send = tpm_inf_send,
.cancel = tpm_inf_cancel,
+ .status = tpm_inf_status,
.req_complete_mask = 0,
.req_complete_val = 0,
.attr_group = &inf_attr_grp,
.miscdev = {.fops = &inf_ops,},
};
-static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static const struct pnp_device_id tpm_pnp_tbl[] = {
+ /* Infineon TPMs */
+ {"IFX0101", 0},
+ {"IFX0102", 0},
+ {"", 0}
+};
+
+MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
+
+static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
+ const struct pnp_device_id *dev_id)
{
int rc = 0;
u8 iol, ioh;
int vendorid[2];
int version[2];
int productid[2];
-
- if (pci_enable_device(pci_dev))
- return -EIO;
-
- dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
+ char chipname[20];
+
+ /* read IO-ports through PnP */
+ if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+ !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
+ TPM_INF_ADDR = pnp_port_start(dev, 0);
+ TPM_INF_DATA = (TPM_INF_ADDR + 1);
+ TPM_INF_BASE = pnp_port_start(dev, 1);
+ TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
+ if (!TPM_INF_PORT_LEN)
+ return -EINVAL;
+ dev_info(&dev->dev, "Found %s with ID %s\n",
+ dev->name, dev_id->id);
+ if (!((TPM_INF_BASE >> 8) & 0xff))
+ return -EINVAL;
+ /* publish my base address and request region */
+ tpm_inf.base = TPM_INF_BASE;
+ if (request_region
+ (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+ release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ return -EINVAL;
+ }
+ } else {
+ return -EINVAL;
+ }
/* query chip for its vendor, its version number a.s.o. */
- outb(ENABLE_REGISTER_PAIR, TPM_ADDR);
- outb(IDVENL, TPM_ADDR);
- vendorid[1] = inb(TPM_DATA);
- outb(IDVENH, TPM_ADDR);
- vendorid[0] = inb(TPM_DATA);
- outb(IDPDL, TPM_ADDR);
- productid[1] = inb(TPM_DATA);
- outb(IDPDH, TPM_ADDR);
- productid[0] = inb(TPM_DATA);
- outb(CHIP_ID1, TPM_ADDR);
- version[1] = inb(TPM_DATA);
- outb(CHIP_ID2, TPM_ADDR);
- version[0] = inb(TPM_DATA);
-
- if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) {
-
- /* read IO-ports from TPM */
- outb(IOLIMH, TPM_ADDR);
- ioh = inb(TPM_DATA);
- outb(IOLIML, TPM_ADDR);
- iol = inb(TPM_DATA);
- tpm_inf.base = (ioh << 8) | iol;
-
- if (tpm_inf.base == 0) {
- dev_err(&pci_dev->dev, "No IO-ports set!\n");
- pci_disable_device(pci_dev);
- return -ENODEV;
+ outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
+ outb(IDVENL, TPM_INF_ADDR);
+ vendorid[1] = inb(TPM_INF_DATA);
+ outb(IDVENH, TPM_INF_ADDR);
+ vendorid[0] = inb(TPM_INF_DATA);
+ outb(IDPDL, TPM_INF_ADDR);
+ productid[1] = inb(TPM_INF_DATA);
+ outb(IDPDH, TPM_INF_ADDR);
+ productid[0] = inb(TPM_INF_DATA);
+ outb(CHIP_ID1, TPM_INF_ADDR);
+ version[1] = inb(TPM_INF_DATA);
+ outb(CHIP_ID2, TPM_INF_ADDR);
+ version[0] = inb(TPM_INF_DATA);
+
+ switch ((productid[0] << 8) | productid[1]) {
+ case 6:
+ snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)");
+ break;
+ case 11:
+ snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)");
+ break;
+ default:
+ snprintf(chipname, sizeof(chipname), " (unknown chip)");
+ break;
+ }
+
+ if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
+
+ /* configure TPM with IO-ports */
+ outb(IOLIMH, TPM_INF_ADDR);
+ outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+ outb(IOLIML, TPM_INF_ADDR);
+ outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+
+ /* control if IO-ports are set correctly */
+ outb(IOLIMH, TPM_INF_ADDR);
+ ioh = inb(TPM_INF_DATA);
+ outb(IOLIML, TPM_INF_ADDR);
+ iol = inb(TPM_INF_DATA);
+
+ if ((ioh << 8 | iol) != tpm_inf.base) {
+ dev_err(&dev->dev,
+ "Could not set IO-ports to %04x\n",
+ tpm_inf.base);
+ release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ return -EIO;
}
/* activate register */
- outb(TPM_DAR, TPM_ADDR);
- outb(0x01, TPM_DATA);
- outb(DISABLE_REGISTER_PAIR, TPM_ADDR);
+ outb(TPM_DAR, TPM_INF_ADDR);
+ outb(0x01, TPM_INF_DATA);
+ outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
/* disable RESET, LP and IRQC */
outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
/* Finally, we're done, print some infos */
- dev_info(&pci_dev->dev, "TPM found: "
+ dev_info(&dev->dev, "TPM found: "
+ "config base 0x%x, "
"io base 0x%x, "
"chip version %02x%02x, "
"vendor id %x%x (Infineon), "
"product id %02x%02x"
"%s\n",
- tpm_inf.base,
+ TPM_INF_ADDR,
+ TPM_INF_BASE,
version[0], version[1],
vendorid[0], vendorid[1],
- productid[0], productid[1], ((productid[0] == 0)
- && (productid[1] ==
- 6)) ?
- " (SLD 9630 TT 1.1)" : "");
+ productid[0], productid[1], chipname);
- rc = tpm_register_hardware(pci_dev, &tpm_inf);
+ rc = tpm_register_hardware(&dev->dev, &tpm_inf);
if (rc < 0) {
- pci_disable_device(pci_dev);
+ release_region(tpm_inf.base, TPM_INF_PORT_LEN);
return -ENODEV;
}
return 0;
} else {
- dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
- pci_disable_device(pci_dev);
+ dev_info(&dev->dev, "No Infineon TPM found!\n");
return -ENODEV;
}
}
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)},
- {0,}
-};
+static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
+{
+ struct tpm_chip *chip = pnp_get_drvdata(dev);
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+ if (chip) {
+ release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+ tpm_remove_hardware(chip->dev);
+ }
+}
-static struct pci_driver inf_pci_driver = {
- .name = "tpm_inf",
- .id_table = tpm_pci_tbl,
- .probe = tpm_inf_probe,
- .remove = __devexit_p(tpm_remove),
- .suspend = tpm_pm_suspend,
- .resume = tpm_pm_resume,
+static struct pnp_driver tpm_inf_pnp = {
+ .name = "tpm_inf_pnp",
+ .driver = {
+ .owner = THIS_MODULE,
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+ },
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_inf_pnp_probe,
+ .remove = tpm_inf_pnp_remove,
};
static int __init init_inf(void)
{
- return pci_register_driver(&inf_pci_driver);
+ return pnp_register_driver(&tpm_inf_pnp);
}
static void __exit cleanup_inf(void)
{
- pci_unregister_driver(&inf_pci_driver);
+ pnp_unregister_driver(&tpm_inf_pnp);
}
module_init(init_inf);
module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
-MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT");
-MODULE_VERSION("1.4");
+MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
+MODULE_VERSION("1.6");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index b4127348c063..8d125c974a2d 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/platform_device.h>
#include "tpm.h"
/* National definitions */
@@ -111,7 +112,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
}
while (time_before(jiffies, stop));
- dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+ dev_info(chip->dev, "wait for ready failed\n");
return -EBUSY;
}
@@ -127,12 +128,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
- dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+ dev_err(chip->dev, "F0 timeout\n");
return -EIO;
}
if ((data =
inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
- dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+ dev_err(chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
}
@@ -141,7 +142,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
for (p = buffer; p < &buffer[count]; p++) {
if (wait_for_stat
(chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"OBF timeout (while reading data)\n");
return -EIO;
}
@@ -152,11 +153,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
if ((data & NSC_STATUS_F0) == 0 &&
(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
- dev_err(&chip->pci_dev->dev, "F0 not set\n");
+ dev_err(chip->dev, "F0 not set\n");
return -EIO;
}
if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
}
@@ -187,19 +188,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ dev_err(chip->dev, "IBF timeout\n");
return -EIO;
}
outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
- dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+ dev_err(chip->dev, "IBR timeout\n");
return -EIO;
}
for (i = 0; i < count; i++) {
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(&chip->pci_dev->dev,
+ dev_err(chip->dev,
"IBF timeout (while writing data)\n");
return -EIO;
}
@@ -207,7 +208,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ dev_err(chip->dev, "IBF timeout\n");
return -EIO;
}
outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
@@ -220,6 +221,11 @@ static void tpm_nsc_cancel(struct tpm_chip *chip)
outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
}
+static u8 tpm_nsc_status(struct tpm_chip *chip)
+{
+ return inb(chip->vendor->base + NSC_STATUS);
+}
+
static struct file_operations nsc_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -239,7 +245,7 @@ static struct attribute * nsc_attrs[] = {
&dev_attr_pcrs.attr,
&dev_attr_caps.attr,
&dev_attr_cancel.attr,
- 0,
+ NULL,
};
static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
@@ -248,6 +254,7 @@ static struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
+ .status = tpm_nsc_status,
.req_complete_mask = NSC_STATUS_OBF,
.req_complete_val = NSC_STATUS_OBF,
.req_canceled = NSC_STATUS_RDY,
@@ -255,16 +262,32 @@ static struct tpm_vendor_specific tpm_nsc = {
.miscdev = { .fops = &nsc_ops, },
};
-static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static struct platform_device *pdev = NULL;
+
+static void __devexit tpm_nsc_remove(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if ( chip ) {
+ release_region(chip->vendor->base, 2);
+ tpm_remove_hardware(chip->dev);
+ }
+}
+
+static struct device_driver nsc_drv = {
+ .name = "tpm_nsc",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
{
int rc = 0;
int lo, hi;
int nscAddrBase = TPM_ADDR;
-
- if (pci_enable_device(pci_dev))
- return -EIO;
+ driver_register(&nsc_drv);
/* select PM channel 1 */
tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
@@ -273,37 +296,71 @@ static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
(tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
- if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
- rc = -ENODEV;
- goto out_err;
- }
+ if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6)
+ return -ENODEV;
}
hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
tpm_nsc.base = (hi<<8) | lo;
- dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
- dev_dbg(&pci_dev->dev,
+ /* enable the DPM module */
+ tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
+
+ pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if ( !pdev )
+ return -ENOMEM;
+
+ memset(pdev, 0, sizeof(struct platform_device));
+
+ pdev->name = "tpm_nscl0";
+ pdev->id = -1;
+ pdev->num_resources = 0;
+ pdev->dev.release = tpm_nsc_remove;
+ pdev->dev.driver = &nsc_drv;
+
+ if ((rc=platform_device_register(pdev)) < 0) {
+ kfree(pdev);
+ pdev = NULL;
+ return rc;
+ }
+
+ if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ return -EBUSY;
+ }
+
+ if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) {
+ release_region(tpm_nsc.base, 2);
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ return rc;
+ }
+
+ dev_dbg(&pdev->dev, "NSC TPM detected\n");
+ dev_dbg(&pdev->dev,
"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
tpm_read_index(nscAddrBase,0x27));
- dev_dbg(&pci_dev->dev,
+ dev_dbg(&pdev->dev,
"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
- dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+ dev_dbg(&pdev->dev, "NSC IO Base0 0x%x\n",
(tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
- dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+ dev_dbg(&pdev->dev, "NSC IO Base1 0x%x\n",
(tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
- dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+ dev_dbg(&pdev->dev, "NSC Interrupt number and wakeup 0x%x\n",
tpm_read_index(nscAddrBase,0x70));
- dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+ dev_dbg(&pdev->dev, "NSC IRQ type select 0x%x\n",
tpm_read_index(nscAddrBase,0x71));
- dev_dbg(&pci_dev->dev,
+ dev_dbg(&pdev->dev,
"NSC DMA channel select0 0x%x, select1 0x%x\n",
tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
- dev_dbg(&pci_dev->dev,
+ dev_dbg(&pdev->dev,
"NSC Config "
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
@@ -312,55 +369,23 @@ static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
- dev_info(&pci_dev->dev,
+ dev_info(&pdev->dev,
"NSC TPM revision %d\n",
tpm_read_index(nscAddrBase, 0x27) & 0x1F);
- /* enable the DPM module */
- tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
-
- if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
- goto out_err;
-
return 0;
-
-out_err:
- pci_disable_device(pci_dev);
- return rc;
-}
-
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
- {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
- {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
-
-static struct pci_driver nsc_pci_driver = {
- .name = "tpm_nsc",
- .id_table = tpm_pci_tbl,
- .probe = tpm_nsc_init,
- .remove = __devexit_p(tpm_remove),
- .suspend = tpm_pm_suspend,
- .resume = tpm_pm_resume,
-};
-
-static int __init init_nsc(void)
-{
- return pci_register_driver(&nsc_pci_driver);
}
static void __exit cleanup_nsc(void)
{
- pci_unregister_driver(&nsc_pci_driver);
+ if (pdev) {
+ tpm_nsc_remove(&pdev->dev);
+ platform_device_unregister(pdev);
+ kfree(pdev);
+ pdev = NULL;
+ }
+
+ driver_unregister(&nsc_drv);
}
module_init(init_nsc);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6e4be3bb2d89..c586bfa852ee 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -153,7 +153,6 @@ static int tty_release(struct inode *, struct file *);
int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int tty_fasync(int fd, struct file * filp, int on);
-extern void rs_360_init(void);
static void release_mem(struct tty_struct *tty, int idx);
@@ -470,21 +469,19 @@ static void tty_ldisc_enable(struct tty_struct *tty)
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
{
- int retval = 0;
- struct tty_ldisc o_ldisc;
+ int retval = 0;
+ struct tty_ldisc o_ldisc;
char buf[64];
int work;
unsigned long flags;
struct tty_ldisc *ld;
+ struct tty_struct *o_tty;
if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
return -EINVAL;
restart:
- if (tty->ldisc.num == ldisc)
- return 0; /* We are already in the desired discipline */
-
ld = tty_ldisc_get(ldisc);
/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
/* Cyrus Durgin <cider@speakeasy.org> */
@@ -495,45 +492,74 @@ restart:
if (ld == NULL)
return -EINVAL;
- o_ldisc = tty->ldisc;
-
tty_wait_until_sent(tty, 0);
+ if (tty->ldisc.num == ldisc) {
+ tty_ldisc_put(ldisc);
+ return 0;
+ }
+
+ o_ldisc = tty->ldisc;
+ o_tty = tty->link;
+
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
* prevents anyone taking a reference once it is clear.
* We need the lock to avoid racing reference takers.
*/
-
+
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if(tty->ldisc.refcount)
- {
- /* Free the new ldisc we grabbed. Must drop the lock
- first. */
+ if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+ if(tty->ldisc.refcount) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ /*
+ * There are several reasons we may be busy, including
+ * random momentary I/O traffic. We must therefore
+ * retry. We could distinguish between blocking ops
+ * and retries if we made tty_ldisc_wait() smarter. That
+ * is up for discussion.
+ */
+ if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ if(o_tty && o_tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(ldisc);
+ if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ }
+
+ /* if the TTY_LDISC bit is set, then we are racing against another ldisc change */
+
+ if (!test_bit(TTY_LDISC, &tty->flags)) {
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
tty_ldisc_put(ldisc);
- /*
- * There are several reasons we may be busy, including
- * random momentary I/O traffic. We must therefore
- * retry. We could distinguish between blocking ops
- * and retries if we made tty_ldisc_wait() smarter. That
- * is up for discussion.
- */
- if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
+ ld = tty_ldisc_ref_wait(tty);
+ tty_ldisc_deref(ld);
goto restart;
}
- clear_bit(TTY_LDISC, &tty->flags);
+
+ clear_bit(TTY_LDISC, &tty->flags);
clear_bit(TTY_DONT_FLIP, &tty->flags);
+ if (o_tty) {
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ clear_bit(TTY_DONT_FLIP, &o_tty->flags);
+ }
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
+
/*
* From this point on we know nobody has an ldisc
* usage reference, nor can they obtain one until
* we say so later on.
*/
-
+
work = cancel_delayed_work(&tty->flip.work);
/*
* Wait for ->hangup_work and ->flip.work handlers to terminate
@@ -584,10 +610,12 @@ restart:
*/
tty_ldisc_enable(tty);
+ if (o_tty)
+ tty_ldisc_enable(o_tty);
/* Restart it in case no characters kick it off. Safe if
already running */
- if(work)
+ if (work)
schedule_delayed_work(&tty->flip.work, 1);
return retval;
}
@@ -781,7 +809,7 @@ static void do_tty_hangup(void *data)
check_tty_count(tty, "do_tty_hangup");
file_list_lock();
/* This breaks for file handles being sent over AF_UNIX sockets ? */
- list_for_each_entry(filp, &tty->tty_files, f_list) {
+ list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
if (filp->f_op->write == redirected_tty_write)
cons_filp = filp;
if (filp->f_op->write != tty_write)
@@ -2426,6 +2454,7 @@ static void __do_SAK(void *arg)
int i;
struct file *filp;
struct tty_ldisc *disc;
+ struct fdtable *fdt;
if (!tty)
return;
@@ -2451,8 +2480,9 @@ static void __do_SAK(void *arg)
}
task_lock(p);
if (p->files) {
- spin_lock(&p->files->file_lock);
- for (i=0; i < p->files->max_fds; i++) {
+ rcu_read_lock();
+ fdt = files_fdtable(p->files);
+ for (i=0; i < fdt->max_fds; i++) {
filp = fcheck_files(p->files, i);
if (!filp)
continue;
@@ -2465,7 +2495,7 @@ static void __do_SAK(void *arg)
break;
}
}
- spin_unlock(&p->files->file_lock);
+ rcu_read_unlock();
}
task_unlock(p);
} while_each_task_pid(session, PIDTYPE_SID, p);
@@ -2698,7 +2728,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
pty_line_name(driver, index, name);
else
tty_line_name(driver, index, name);
- class_device_create(tty_class, dev, device, name);
+ class_device_create(tty_class, NULL, dev, device, "%s", name);
}
/**
@@ -2911,11 +2941,6 @@ void __init console_init(void)
#ifdef CONFIG_EARLY_PRINTK
disable_early_printk();
#endif
-#ifdef CONFIG_SERIAL_68360
- /* This is not a console initcall. I know not what it's doing here.
- So I haven't moved it. dwmw2 */
- rs_360_init();
-#endif
call = __con_initcall_start;
while (call < __con_initcall_end) {
(*call)();
@@ -2958,14 +2983,14 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
- class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+ class_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");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
- class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+ class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2973,7 +2998,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
- class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+ class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -2982,7 +3007,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
- class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+ class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 79c2928a8817..f66c7ad6fd38 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -484,8 +484,10 @@ void vcs_make_devfs(struct tty_struct *tty)
devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
S_IFCHR|S_IRUSR|S_IWUSR,
"vcc/a%u", tty->index + 1);
- class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
- class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ NULL, "vcs%u", tty->index + 1);
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_devfs(struct tty_struct *tty)
{
@@ -503,7 +505,7 @@ int __init vcs_init(void)
devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
- class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 44f5fb4a46ef..98601c7d04a9 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -44,12 +44,12 @@
#include <linux/tty_flip.h>
#include <linux/sysrq.h>
-#include <asm/iSeries/vio.h>
+#include <asm/iseries/vio.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvCall.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/hv_call_event.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call.h>
#ifdef CONFIG_VT
#error You must turn off CONFIG_VT to use CONFIG_VIOCONS
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 4764b4f9555d..867cc4e418c7 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -29,7 +29,7 @@
*
* All tape operations are performed by sending messages back and forth to
* the OS/400 partition. The format of the messages is defined in
- * iSeries/vio.h
+ * iseries/vio.h
*/
#include <linux/config.h>
#include <linux/version.h>
@@ -54,10 +54,10 @@
#include <asm/ioctls.h>
#include <asm/vio.h>
-#include <asm/iSeries/vio.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/HvLpConfig.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/hv_call_event.h>
+#include <asm/iseries/hv_lp_config.h>
#define VIOTAPE_VERSION "1.2"
#define VIOTAPE_MAXREQ 1
@@ -956,9 +956,9 @@ 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;
- class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i);
- class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
NULL, "iseries!nvt%d", i);
devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
"iseries/vt%d", i);
@@ -991,15 +991,18 @@ static int viotape_remove(struct vio_dev *vdev)
*/
static struct vio_device_id viotape_device_table[] __devinitdata = {
{ "viotape", "" },
- { 0, }
+ { "", "" }
};
-
MODULE_DEVICE_TABLE(vio, viotape_device_table);
+
static struct vio_driver viotape_driver = {
- .name = "viotape",
.id_table = viotape_device_table,
.probe = viotape_probe,
- .remove = viotape_remove
+ .remove = viotape_remove,
+ .driver = {
+ .name = "viotape",
+ .owner = THIS_MODULE,
+ }
};
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 683278bc5241..94641085faf8 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
index a6dbe4da030c..5e3292df69d8 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/char/vr41xx_rtc.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 30d96739fb23..e91268e86833 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
/* used by selection: complement pointer position */
void complement_pos(struct vc_data *vc, int offset)
{
- static unsigned short *p;
+ static int old_offset = -1;
static unsigned short old;
static unsigned short oldx, oldy;
WARN_CONSOLE_UNLOCKED();
- if (p) {
- scr_writew(old, p);
+ if (old_offset != -1 && old_offset >= 0 &&
+ old_offset < vc->vc_screenbuf_size) {
+ scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
}
- if (offset == -1)
- p = NULL;
- else {
+
+ old_offset = offset;
+
+ if (offset != -1 && offset >= 0 &&
+ offset < vc->vc_screenbuf_size) {
unsigned short new;
+ unsigned short *p;
p = screenpos(vc, offset, 1);
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
@@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset)
vc->vc_sw->con_putc(vc, new, oldy, oldx);
}
}
+
}
static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -746,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+ unsigned int end;
unsigned short *newscreen;
WARN_CONSOLE_UNLOCKED();
@@ -789,20 +795,45 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
old_origin = vc->vc_origin;
new_origin = (long) newscreen;
new_scr_end = new_origin + new_screen_size;
- if (new_rows < old_rows)
- old_origin += (old_rows - new_rows) * old_row_size;
+
+ if (vc->vc_y > new_rows) {
+ if (old_rows - vc->vc_y < new_rows) {
+ /*
+ * Cursor near the bottom, copy contents from the
+ * bottom of buffer
+ */
+ old_origin += (old_rows - new_rows) * old_row_size;
+ end = vc->vc_scr_end;
+ } else {
+ /*
+ * Cursor is in no man's land, copy 1/2 screenful
+ * from the top and bottom of cursor position
+ */
+ old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+ end = old_origin + (old_row_size * new_rows);
+ }
+ } else
+ /*
+ * Cursor near the top, copy contents from the top of buffer
+ */
+ end = (old_rows > new_rows) ? old_origin +
+ (old_row_size * new_rows) :
+ vc->vc_scr_end;
update_attr(vc);
- while (old_origin < vc->vc_scr_end) {
- scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
+ while (old_origin < end) {
+ scr_memcpyw((unsigned short *) new_origin,
+ (unsigned short *) old_origin, rlth);
if (rrem)
- scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
+ scr_memsetw((void *)(new_origin + rlth),
+ vc->vc_video_erase_char, rrem);
old_origin += old_row_size;
new_origin += new_row_size;
}
if (new_scr_end > new_origin)
- scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+ scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+ new_scr_end - new_origin);
if (vc->vc_kmalloced)
kfree(vc->vc_screenbuf);
vc->vc_screenbuf = newscreen;
@@ -2272,7 +2303,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
ret = paste_selection(tty);
break;
case TIOCL_UNBLANKSCREEN:
+ acquire_console_sem();
unblank_screen();
+ release_console_sem();
break;
case TIOCL_SELLOADLUT:
ret = sel_loadlut(p);
@@ -2317,8 +2350,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
}
break;
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+ acquire_console_sem();
ignore_poke = 1;
do_blank_screen(0);
+ release_console_sem();
break;
case TIOCL_BLANKEDSCREEN:
ret = console_blanked;
@@ -2433,7 +2468,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
int ret = 0;
acquire_console_sem();
- if (tty->count == 1) {
+ if (tty->driver_data == NULL) {
ret = vc_allocate(currcons);
if (ret == 0) {
struct vc_data *vc = vc_cons[currcons].d;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 1d44f69e1fda..003dda147cd0 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -192,6 +192,9 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
int i, j, k;
int ret;
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ return -EPERM;
+
kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
if (!kbs) {
ret = -ENOMEM;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index b53e2e2b5aee..344001b45af9 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -84,6 +84,17 @@ config 977_WATCHDOG
Not sure? It's safe to say N.
+config IXP2000_WATCHDOG
+ tristate "IXP2000 Watchdog"
+ depends on WATCHDOG && ARCH_IXP2000
+ help
+ Say Y here if to include support for the watchdog timer
+ in the Intel IXP2000(2400, 2800, 2850) network processors.
+ This driver can be built as a module by choosing M. The module
+ will be called ixp2000_wdt.
+
+ Say N if you are unsure.
+
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on WATCHDOG && ARCH_IXP4XX
@@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG
Say N if you are unsure.
-config IXP2000_WATCHDOG
- tristate "IXP2000 Watchdog"
- depends on WATCHDOG && ARCH_IXP2000
- help
- Say Y here if to include support for the watchdog timer
- in the Intel IXP2000(2400, 2800, 2850) network processors.
- This driver can be built as a module by choosing M. The module
- will be called ixp2000_wdt.
-
- Say N if you are unsure.
-
config S3C2410_WATCHDOG
tristate "S3C2410 Watchdog"
depends on WATCHDOG && ARCH_S3C2410
@@ -139,6 +139,15 @@ config SA1100_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called sa1100_wdt.
+config MPCORE_WATCHDOG
+ tristate "MPcore watchdog"
+ depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+ help
+ Watchdog timer embedded into the MPcore system.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mpcore_wdt.
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
@@ -224,6 +233,16 @@ config IB700_WDT
Most people will say N.
+config IBMASR
+ tristate "IBM Automatic Server Restart"
+ depends on WATCHDOG && X86
+ help
+ This is the driver for the IBM Automatic Server Restart watchdog
+ timer builtin into some eServer xSeries machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmasr.
+
config WAFER_WDT
tristate "ICP Wafer 5823 Single Board Computer Watchdog"
depends on WATCHDOG && X86
@@ -234,6 +253,16 @@ config WAFER_WDT
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
+config I6300ESB_WDT
+ tristate "Intel 6300ESB Timer/Watchdog"
+ depends on WATCHDOG && X86 && PCI
+ ---help---
+ Hardware driver for the watchdog timer built into the Intel
+ 6300ESB controller hub.
+
+ To compile this driver as a module, choose M here: the
+ module will be called i6300esb.
+
config I8XX_TCO
tristate "Intel i8xx TCO Timer/Watchdog"
depends on WATCHDOG && (X86 || IA64) && PCI
@@ -289,6 +318,19 @@ config 60XX_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called sbc60xxwdt.
+config SBC8360_WDT
+ tristate "SBC8360 Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+
+ This is the driver for the hardware watchdog on the SBC8360 Single
+ Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc8360.ko.
+
+ Most people will say N.
+
config CPU5_WDT
tristate "SMA CPU5 Watchdog"
depends on WATCHDOG && X86
@@ -327,6 +369,19 @@ config W83877F_WDT
Most people will say N.
+config W83977F_WDT
+ tristate "W83977F (PCM-5335) Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the hardware watchdog on the W83977F I/O chip
+ as used in AAEON's PCM-5335 SBC (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 w83977f_wdt.
+
config MACHZ_WDT
tristate "ZF MachZ Watchdog"
depends on WATCHDOG && X86
@@ -346,6 +401,28 @@ config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config MV64X60_WDT
+ tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+ depends on WATCHDOG && MV64X60
+
+config BOOKE_WDT
+ tristate "PowerPC Book-E Watchdog Timer"
+ depends on WATCHDOG && (BOOKE || 4xx)
+ ---help---
+ Please see Documentation/watchdog/watchdog-api.txt for
+ more information.
+
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on WATCHDOG && PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
# MIPS Architecture
config INDYDOG
@@ -414,16 +491,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# ppc64 RTAS watchdog
-config WATCHDOG_RTAS
- tristate "RTAS watchdog"
- depends on WATCHDOG && PPC_RTAS
- help
- This driver adds watchdog support for the RTAS watchdog.
-
- To compile this driver as a module, choose M here. The module
- will be called wdrtas.
-
#
# ISA-based Watchdog Cards
#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index c1838834ea7f..cfd0a3987710 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -2,42 +2,74 @@
# Makefile for the WatchDog device drivers.
#
+# Only one watchdog can succeed. We probe the ISA/PCI/USB based
+# watchdog-cards first, then the architecture specific watchdog
+# drivers and then the architecture independant "softdog" driver.
+# This means that if your ISA/PCI/USB card isn't detected that
+# you can fall back to an architecture specific driver and if
+# that also fails then you can fall back to the software watchdog
+# to give you some cover.
+
+# ISA-based Watchdog Cards
obj-$(CONFIG_PCWATCHDOG) += pcwd.o
-obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
-obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
-obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
-obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
-obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_WDT) += wdt.o
+
+# PCI-based Watchdog Cards
+obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
obj-$(CONFIG_WDTPCI) += wdt_pci.o
+
+# USB-based Watchdog Cards
+obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
+
+# ARM Architecture
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
-obj-$(CONFIG_MACHZ_WDT) += machzwd.o
-obj-$(CONFIG_SH_WDT) += shwdt.o
+obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
-obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
-obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
-obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
-obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
-obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+
+# X86 (i386 + ia64 + x86_64) Architecture
+obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
-obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
+obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
+obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
+obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
+obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
+obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
+obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
-obj-$(CONFIG_INDYDOG) += indydog.o
-obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
-obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
-obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
-obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
+obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
+obj-$(CONFIG_MACHZ_WDT) += machzwd.o
+
+# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
+
+# PPC64 Architecture
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-# Only one watchdog can succeed. We probe the hardware watchdog
-# drivers first, then the softdog driver. This means if your hardware
-# watchdog dies or is 'borrowed' for some reason the software watchdog
-# still gives you some cover.
+# MIPS Architecture
+obj-$(CONFIG_INDYDOG) += indydog.o
+
+# S390 Architecture
+
+# SUPERH Architecture
+obj-$(CONFIG_SH_WDT) += shwdt.o
+
+# SPARC64 Architecture
+# Architecture Independant
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
new file mode 100644
index 000000000000..abc30cca6645
--- /dev/null
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -0,0 +1,192 @@
+/*
+ * drivers/char/watchdog/booke_wdt.c
+ *
+ * Watchdog timer for PowerPC Book-E systems
+ *
+ * Author: Matthew McClintock
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/notifier.h>
+#include <linux/watchdog.h>
+
+#include <asm/reg_booke.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot.
+ * Also, the wdt_period sets the watchdog timer period timeout.
+ * For E500 cpus the wdt_period sets which bit changing from 0->1 will
+ * trigger a watchog timeout. This watchdog timeout will occur 3 times, the
+ * first time nothing will happen, the second time a watchdog exception will
+ * occur, and the final time the board will reset.
+ */
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */
+#else
+#define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */
+#endif /* for timing information */
+
+u32 booke_wdt_enabled = 0;
+u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
+#else
+#define WDTP(x) (TCR_WP(x))
+#endif
+
+/*
+ * booke_wdt_enable:
+ */
+static __inline__ void booke_wdt_enable(void)
+{
+ u32 val;
+
+ val = mfspr(SPRN_TCR);
+ val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
+
+ mtspr(SPRN_TCR, val);
+}
+
+/*
+ * booke_wdt_ping:
+ */
+static __inline__ void booke_wdt_ping(void)
+{
+ mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
+}
+
+/*
+ * booke_wdt_write:
+ */
+static ssize_t booke_wdt_write (struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ booke_wdt_ping();
+ return count;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "PowerPC Book-E Watchdog",
+};
+
+/*
+ * booke_wdt_ioctl:
+ */
+static int booke_wdt_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ u32 tmp = 0;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user ((struct watchdog_info *) arg, &ident,
+ sizeof(struct watchdog_info)))
+ return -EFAULT;
+ case WDIOC_GETSTATUS:
+ return put_user(ident.options, (u32 *) arg);
+ case WDIOC_GETBOOTSTATUS:
+ /* XXX: something is clearing TSR */
+ tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
+ /* returns 1 if last reset was caused by the WDT */
+ return (tmp ? 1 : 0);
+ case WDIOC_KEEPALIVE:
+ booke_wdt_ping();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(booke_wdt_period, (u32 *) arg))
+ return -EFAULT;
+ mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(booke_wdt_period, (u32 *) arg);
+ case WDIOC_SETOPTIONS:
+ if (get_user(tmp, (u32 *) arg))
+ return -EINVAL;
+ if (tmp == WDIOS_ENABLECARD) {
+ booke_wdt_ping();
+ break;
+ } else
+ return -EINVAL;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+/*
+ * booke_wdt_open:
+ */
+static int booke_wdt_open (struct inode *inode, struct file *file)
+{
+ if (booke_wdt_enabled == 0) {
+ booke_wdt_enabled = 1;
+ booke_wdt_enable();
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+ booke_wdt_period);
+ }
+
+ return 0;
+}
+
+static struct file_operations booke_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = booke_wdt_write,
+ .ioctl = booke_wdt_ioctl,
+ .open = booke_wdt_open,
+};
+
+static struct miscdevice booke_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &booke_wdt_fops,
+};
+
+static void __exit booke_wdt_exit(void)
+{
+ misc_deregister(&booke_wdt_miscdev);
+}
+
+/*
+ * booke_wdt_init:
+ */
+static int __init booke_wdt_init(void)
+{
+ int ret = 0;
+
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
+ ident.firmware_version = cpu_specs[0].pvr_value;
+
+ ret = misc_register(&booke_wdt_miscdev);
+ if (ret) {
+ printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ return ret;
+ }
+
+ if (booke_wdt_enabled == 1) {
+ printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+ booke_wdt_period);
+ booke_wdt_enable();
+ }
+
+ return ret;
+}
+device_initcall(booke_wdt_init);
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index 2865dac0a813..e75045fe2641 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
new file mode 100644
index 000000000000..93785f13242e
--- /dev/null
+++ b/drivers/char/watchdog/i6300esb.c
@@ -0,0 +1,527 @@
+/*
+ * i6300esb: Watchdog timer driver for Intel 6300ESB chipset
+ *
+ * (c) Copyright 2004 Google Inc.
+ * (c) Copyright 2005 David Härdeman <david@2gen.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.
+ *
+ * based on i810-tco.c which is in turn based on softdog.c
+ *
+ * The timer is implemented in the following I/O controller hubs:
+ * (See the intel documentation on http://developer.intel.com.)
+ * 6300ESB chip : document number 300641-003
+ *
+ * 2004YYZZ Ross Biro
+ * Initial version 0.01
+ * 2004YYZZ Ross Biro
+ * Version 0.02
+ * 20050210 David Härdeman <david@2gen.com>
+ * Ported driver to kernel 2.6
+ */
+
+/*
+ * Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG 0x60 /* Config register */
+#define ESB_LOCK_REG 0x68 /* WDT lock register */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */
+#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */
+#define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */
+#define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */
+#define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */
+#define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */
+
+/* Magic constants */
+#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
+#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+ writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+ writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+ u8 val;
+
+ /* Enable or Enable + Lock? */
+ val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+ u8 val;
+
+ spin_lock(&esb_lock);
+ /* First, reset timers as suggested by the docs */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* Then disable the WDT */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+ spin_unlock(&esb_lock);
+
+ /* Returns 0 if the timer was disabled, non-zero otherwise */
+ return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+ spin_lock(&esb_lock);
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* FIXME: Do we need to flush anything here? */
+ spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+ u32 val;
+
+ if (time < 0x1 || time > (2 * 0x03ff))
+ return -EINVAL;
+
+ spin_lock(&esb_lock);
+
+ /* We shift by 9, so if we are passed a value of 1 sec,
+ * val will be 1 << 9 = 512, then write that to two
+ * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+ */
+ val = time << 9;
+
+ /* Write timer 1 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER1_REG);
+
+ /* Write timer 2 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER2_REG);
+
+ /* Reload */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+ /* FIXME: Do we need to flush everything out? */
+
+ /* Done */
+ heartbeat = time;
+ spin_unlock(&esb_lock);
+ return 0;
+}
+
+static int esb_timer_read (void)
+{
+ u32 count;
+
+ /* This isn't documented, and doesn't take into
+ * acount which stage is running, but it looks
+ * like a 20 bit count down, so we might as well report it.
+ */
+ pci_read_config_dword(esb_pci, 0x64, &count);
+ return (int)count;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &timer_alive))
+ return -EBUSY;
+
+ /* Reload and activate timer */
+ esb_timer_keepalive ();
+ esb_timer_start ();
+
+ return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+ /* Shut off the timer. */
+ if (esb_expect_close == 42) {
+ esb_timer_stop ();
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ esb_timer_keepalive ();
+ }
+ clear_bit(0, &timer_alive);
+ esb_expect_close = 0;
+ return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+ size_t len, loff_t * ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* note: just in case someone wrote the magic character
+ * five months ago... */
+ esb_expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if(get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ esb_expect_close = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ esb_timer_keepalive ();
+ }
+ return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int new_options, retval = -EINVAL;
+ int new_heartbeat;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = ESB_MODULE_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof (ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user (esb_timer_read(), p);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user (triggered, p);
+
+ case WDIOC_KEEPALIVE:
+ esb_timer_keepalive ();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ {
+ if (get_user (new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ esb_timer_stop ();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ esb_timer_keepalive ();
+ esb_timer_start ();
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ {
+ if (get_user(new_heartbeat, p))
+ return -EFAULT;
+
+ if (esb_timer_set_heartbeat(new_heartbeat))
+ return -EINVAL;
+
+ esb_timer_keepalive ();
+ /* Fall */
+ }
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT) {
+ /* Turn the WDT off */
+ esb_timer_stop ();
+ }
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations esb_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = esb_write,
+ .ioctl = esb_ioctl,
+ .open = esb_open,
+ .release = esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+ .notifier_call = esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+ { 0, }, /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ * Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+ u8 val1;
+ unsigned short val2;
+
+ struct pci_dev *dev = NULL;
+ /*
+ * Find the PCI device
+ */
+
+ for_each_pci_dev(dev) {
+ if (pci_match_id(esb_pci_tbl, dev)) {
+ esb_pci = dev;
+ break;
+ }
+ }
+
+ if (esb_pci) {
+ if (pci_enable_device(esb_pci)) {
+ printk (KERN_ERR PFX "failed to enable device\n");
+ goto err_devput;
+ }
+
+ if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+ printk (KERN_ERR PFX "failed to request region\n");
+ goto err_disable;
+ }
+
+ BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+ pci_resource_len(esb_pci, 0));
+ if (BASEADDR == NULL) {
+ /* Something's wrong here, BASEADDR has to be set */
+ printk (KERN_ERR PFX "failed to get BASEADDR\n");
+ goto err_release;
+ }
+
+ /*
+ * The watchdog has two timers, it can be setup so that the
+ * expiry of timer1 results in an interrupt and the expiry of
+ * timer2 results in a reboot. We set it to not generate
+ * any interrupts as there is not much we can do with it
+ * right now.
+ *
+ * We also enable reboots and set the timer frequency to
+ * the PCI clock divided by 2^15 (approx 1KHz).
+ */
+ pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+ /* Check that the WDT isn't already locked */
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+ if (val1 & ESB_WDT_LOCK)
+ printk (KERN_WARNING PFX "nowayout already set\n");
+
+ /* Set the timer to watchdog mode and disable it for now */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+ /* Check if the watchdog was previously triggered */
+ esb_unlock_registers();
+ val2 = readw(ESB_RELOAD_REG);
+ triggered = (val2 & (0x01 << 9) >> 9);
+
+ /* Reset trigger flag and timers */
+ esb_unlock_registers();
+ writew((0x11 << 8), ESB_RELOAD_REG);
+
+ /* Done */
+ return 1;
+
+err_release:
+ pci_release_region(esb_pci, 0);
+err_disable:
+ pci_disable_device(esb_pci);
+err_devput:
+ pci_dev_put(esb_pci);
+ }
+ return 0;
+}
+
+static int __init watchdog_init (void)
+{
+ int ret;
+
+ spin_lock_init(&esb_lock);
+
+ /* Check whether or not the hardware watchdog is there */
+ if (!esb_getdevice () || esb_pci == NULL)
+ return -ENODEV;
+
+ /* Check that the heartbeat value is within it's range ; if not reset to the default */
+ if (esb_timer_set_heartbeat (heartbeat)) {
+ esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+ heartbeat);
+ }
+
+ ret = register_reboot_notifier(&esb_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ ret);
+ goto err_unmap;
+ }
+
+ ret = misc_register(&esb_miscdev);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_notifier;
+ }
+
+ esb_timer_stop ();
+
+ printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+ BASEADDR, heartbeat, nowayout);
+
+ return 0;
+
+err_notifier:
+ unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+ iounmap(BASEADDR);
+/* err_release: */
+ pci_release_region(esb_pci, 0);
+/* err_disable: */
+ pci_disable_device(esb_pci);
+/* err_devput: */
+ pci_dev_put(esb_pci);
+ return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ esb_timer_stop ();
+
+ /* Deregister */
+ misc_deregister(&esb_miscdev);
+ unregister_reboot_notifier(&esb_notifier);
+ iounmap(BASEADDR);
+ pci_release_region(esb_pci, 0);
+ pci_disable_device(esb_pci);
+ pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index f975dab1ddf9..a13395e2c372 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -1,5 +1,5 @@
/*
- * i8xx_tco 0.07: TCO timer driver for i8xx chipsets
+ * i8xx_tco: TCO timer driver for i8xx chipsets
*
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
* 20050128 Wim Van Sebroeck <wim@iguana.be>
* 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
* chipsets. Also added support for the "undocumented" ICH7 chipset.
+ * 20050807 Wim Van Sebroeck <wim@iguana.be>
+ * 0.08 Make sure that the watchdog is only "armed" when started.
+ * (Kernel Bug 4251)
*/
/*
@@ -87,7 +90,7 @@
#include "i8xx_tco.h"
/* Module and version information */
-#define TCO_VERSION "0.07"
+#define TCO_VERSION "0.08"
#define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": "
@@ -125,10 +128,18 @@ static int tco_timer_start (void)
unsigned char val;
spin_lock(&tco_lock);
+
+ /* disable chipset's NO_REBOOT bit */
+ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
+ val &= 0xfd;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
+
+ /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
val = inb (TCO1_CNT + 1);
val &= 0xf7;
outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1);
+
spin_unlock(&tco_lock);
if (val & 0x08)
@@ -138,13 +149,20 @@ static int tco_timer_start (void)
static int tco_timer_stop (void)
{
- unsigned char val;
+ unsigned char val, val1;
spin_lock(&tco_lock);
+ /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
val = inb (TCO1_CNT + 1);
val |= 0x08;
outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1);
+
+ /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
+ val1 |= 0x02;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
spin_unlock(&tco_lock);
if ((val & 0x08) == 0)
@@ -155,6 +173,7 @@ static int tco_timer_stop (void)
static int tco_timer_keepalive (void)
{
spin_lock(&tco_lock);
+ /* Reload the timer by writing to the TCO Timer Reload register */
outb (0x01, TCO1_RLD);
spin_unlock(&tco_lock);
return 0;
@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
printk (KERN_ERR PFX "failed to get TCOBASE address\n");
return 0;
}
- /*
- * Check chipset's NO_REBOOT bit
- */
+
+ /* Check chipset's NO_REBOOT bit */
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
if (val1 & 0x02) {
val1 &= 0xfd;
@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
return 0; /* Cannot reset NO_REBOOT bit */
}
}
+ /* Disable reboots untill the watchdog starts */
+ val1 |= 0x02;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
/* Set the TCO_EN bit in SMI_EN register */
if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -505,17 +527,10 @@ out:
static void __exit watchdog_cleanup (void)
{
- u8 val;
-
/* Stop the timer before we leave */
if (!nowayout)
tco_timer_stop ();
- /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
- pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
- val |= 0x02;
- pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
-
/* Deregister */
misc_deregister (&i8xx_tco_miscdev);
unregister_reboot_notifier(&i8xx_tco_notifier);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
new file mode 100644
index 000000000000..294c474ae485
--- /dev/null
+++ b/drivers/char/watchdog/ibmasr.c
@@ -0,0 +1,405 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+ ASMTYPE_UNKNOWN,
+ ASMTYPE_TOPAZ,
+ ASMTYPE_JASPER,
+ ASMTYPE_PEARL,
+ ASMTYPE_JUNIPER,
+ ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET 4
+#define TOPAZ_ASR_TOGGLE 0x40
+#define TOPAZ_ASR_DISABLE 0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE 0xe04
+#define PEARL_WRITE 0xe06
+#define PEARL_READ 0xe07
+
+#define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET 0x38
+
+#define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+ unsigned char reg;
+
+ if (asr_type == ASMTYPE_TOPAZ) {
+ /* asr_write_addr == asr_read_addr */
+ reg = inb(asr_read_addr);
+ outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+ asr_read_addr);
+ } else {
+ /*
+ * First make sure the hardware timer is reset by toggling
+ * ASR hardware timer line.
+ */
+ asr_toggle();
+
+ reg = inb(asr_read_addr);
+ outb(reg & ~asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ if (asr_type == ASMTYPE_TOPAZ)
+ /* asr_write_addr == asr_read_addr */
+ outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+ asr_read_addr);
+ else {
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+ unsigned char low, high;
+ const char *type = "";
+
+ asr_length = 1;
+
+ switch (asr_type) {
+ case ASMTYPE_TOPAZ:
+ /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+ outb(0x07, 0x2e);
+ outb(0x07, 0x2f);
+
+ /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x60, 0x2e);
+ high = inb(0x2f);
+
+ /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x61, 0x2e);
+ low = inb(0x2f);
+
+ asr_base = (high << 16) | low;
+ asr_read_addr = asr_write_addr =
+ asr_base + TOPAZ_ASR_REG_OFFSET;
+ asr_length = 5;
+
+ break;
+
+ case ASMTYPE_JASPER:
+ type = "Jaspers ";
+
+ /* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/* spin_lock_irqsave(&pci_config_lock, flags);*/
+
+ /* Select the SuperIO chip in the PCI I/O port register */
+ outl(0x8000f858, 0xcf8);
+
+ /*
+ * Read the base address for the SuperIO chip.
+ * Only the lower 16 bits are valid, but the address is word
+ * aligned so the last bit must be masked off.
+ */
+ asr_base = inl(0xcfc) & 0xfffe;
+
+/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+ asr_read_addr = asr_write_addr =
+ asr_base + JASPER_ASR_REG_OFFSET;
+ asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+ asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+ break;
+
+ case ASMTYPE_PEARL:
+ type = "Pearls ";
+ asr_base = PEARL_BASE;
+ asr_read_addr = PEARL_READ;
+ asr_write_addr = PEARL_WRITE;
+ asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+ asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+ asr_length = 4;
+ break;
+
+ case ASMTYPE_JUNIPER:
+ type = "Junipers ";
+ asr_base = JUNIPER_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+ break;
+
+ case ASMTYPE_SPRUCE:
+ type = "Spruce's ";
+ asr_base = SPRUCE_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+ asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+ break;
+ }
+
+ if (!request_region(asr_base, asr_length, "ibmasr")) {
+ printk(KERN_ERR PFX "address %#x already in use\n",
+ asr_base);
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+ return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ asr_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ asr_expect_close = 42;
+ }
+ }
+ asr_toggle();
+ }
+ return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "IBM ASR"
+ };
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int heartbeat;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ?
+ -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ asr_toggle();
+ return 0;
+
+ /*
+ * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+ * and WDIOC_GETTIMEOUT always returns 256.
+ */
+ case WDIOC_GETTIMEOUT:
+ heartbeat = 256;
+ return put_user(heartbeat, p);
+
+ case WDIOC_SETOPTIONS: {
+ int new_options, retval = -EINVAL;
+
+ if (get_user(new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ asr_disable();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ asr_enable();
+ asr_toggle();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+ if(test_and_set_bit(0, &asr_is_open))
+ return -EBUSY;
+
+ asr_toggle();
+ asr_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+ if (asr_expect_close == 42)
+ asr_disable();
+ else {
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ asr_toggle();
+ }
+ clear_bit(0, &asr_is_open);
+ asr_expect_close = 0;
+ return 0;
+}
+
+static struct file_operations asr_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = asr_write,
+ .ioctl = asr_ioctl,
+ .open = asr_open,
+ .release = asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &asr_fops,
+};
+
+
+struct ibmasr_id {
+ const char *desc;
+ int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+ { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+ { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+ { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+ { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+ { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+ { NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+ struct ibmasr_id *id;
+ int rc;
+
+ for (id = ibmasr_id_table; id->desc; id++) {
+ if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+ asr_type = id->type;
+ break;
+ }
+ }
+
+ if (!asr_type)
+ return -ENODEV;
+
+ rc = misc_register(&asr_miscdev);
+ if (rc < 0) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ return rc;
+ }
+
+ rc = asr_get_base_address();
+ if (rc) {
+ misc_deregister(&asr_miscdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+ if (!nowayout)
+ asr_disable();
+
+ misc_deregister(&asr_miscdev);
+
+ release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index e7640bc4904b..0cfb9b9c4a4b 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -182,7 +182,7 @@ static struct file_operations ixp2000_wdt_fops =
static struct miscdevice ixp2000_wdt_miscdev =
{
.minor = WATCHDOG_MINOR,
- .name = "IXP2000 Watchdog",
+ .name = "watchdog",
.fops = &ixp2000_wdt_fops,
};
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index 8d916afbf4fa..b5be8b11104a 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -176,7 +176,7 @@ static struct file_operations ixp4xx_wdt_fops =
static struct miscdevice ixp4xx_wdt_miscdev =
{
.minor = WATCHDOG_MINOR,
- .name = "IXP4xx Watchdog",
+ .name = "watchdog",
.fops = &ixp4xx_wdt_fops,
};
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index c9b301dccec3..d8dede575402 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -45,6 +45,8 @@
#include <linux/fs.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -59,7 +61,7 @@ static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
static int watchdog_port;
static int mixcomwd_timer_alive;
-static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0);
static char expect_close;
static int nowayout = WATCHDOG_NOWAYOUT;
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
new file mode 100644
index 000000000000..da631c114fd1
--- /dev/null
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -0,0 +1,437 @@
+/*
+ * Watchdog driver for the mpcore watchdog timer
+ *
+ * (c) Copyright 2004 ARM Limited
+ *
+ * Based on the SoftDog driver:
+ * (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@lxorguk.ukuu.org.uk>
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware/arm_twd.h>
+#include <asm/uaccess.h>
+
+struct mpcore_wdt {
+ unsigned long timer_alive;
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+ unsigned int perturb;
+ char expect_close;
+};
+
+static struct platform_device *mpcore_wdt_dev;
+
+extern unsigned int mpcore_timer_rate;
+
+#define TIMER_MARGIN 60
+static int mpcore_margin = TIMER_MARGIN;
+module_param(mpcore_margin, int, 0);
+MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+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) ")");
+
+#define ONLY_TESTING 0
+static int mpcore_noboot = ONLY_TESTING;
+module_param(mpcore_noboot, int, 0);
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+
+/*
+ * This is the interrupt handler. Note that we only use this
+ * in testing mode, so don't actually do a reboot here.
+ */
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
+{
+ struct mpcore_wdt *wdt = arg;
+
+ /* Check it really was our interrupt */
+ if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
+ dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
+
+ /* Clear the interrupt on the watchdog */
+ writel(1, wdt->base + TWD_WDOG_INTSTAT);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * mpcore_wdt_keepalive - reload the timer
+ *
+ * Note that the spec says a DIFFERENT value must be written to the reload
+ * register each time. The "perturb" variable deals with this by adding 1
+ * to the count every other time the function is called.
+ */
+static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
+{
+ unsigned int count;
+
+ /* Assume prescale is set to 256 */
+ count = (mpcore_timer_rate / 256) * mpcore_margin;
+
+ /* Reload the counter */
+ writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
+
+ wdt->perturb = wdt->perturb ? 0 : 1;
+}
+
+static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
+{
+ writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
+ writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
+ writel(0x0, wdt->base + TWD_WDOG_CONTROL);
+}
+
+static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+{
+ dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+ /* This loads the count register but does NOT start the count yet */
+ mpcore_wdt_keepalive(wdt);
+
+ if (mpcore_noboot) {
+ /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+ writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+ } else {
+ /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+ writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+ }
+}
+
+static int mpcore_wdt_set_heartbeat(int t)
+{
+ if (t < 0x0001 || t > 0xFFFF)
+ return -EINVAL;
+
+ mpcore_margin = t;
+ return 0;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+static int mpcore_wdt_open(struct inode *inode, struct file *file)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(&mpcore_wdt_dev->dev);
+
+ if (test_and_set_bit(0, &wdt->timer_alive))
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ file->private_data = wdt;
+
+ /*
+ * Activate timer
+ */
+ mpcore_wdt_start(wdt);
+
+ return nonseekable_open(inode, file);
+}
+
+static int mpcore_wdt_release(struct inode *inode, struct file *file)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (wdt->expect_close == 42) {
+ mpcore_wdt_stop(wdt);
+ } else {
+ dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
+ mpcore_wdt_keepalive(wdt);
+ }
+ clear_bit(0, &wdt->timer_alive);
+ wdt->expect_close = 0;
+ return 0;
+}
+
+static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ /*
+ * Refresh the timer.
+ */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ wdt->expect_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ wdt->expect_close = 42;
+ }
+ }
+ mpcore_wdt_keepalive(wdt);
+ }
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "MPcore Watchdog",
+};
+
+static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mpcore_wdt *wdt = file->private_data;
+ int ret;
+ union {
+ struct watchdog_info ident;
+ int i;
+ } uarg;
+
+ if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+ return -ENOIOCTLCMD;
+
+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+ if (ret)
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ uarg.ident = ident;
+ ret = 0;
+ break;
+
+ case WDIOC_SETOPTIONS:
+ ret = -EINVAL;
+ if (uarg.i & WDIOS_DISABLECARD) {
+ mpcore_wdt_stop(wdt);
+ ret = 0;
+ }
+ if (uarg.i & WDIOS_ENABLECARD) {
+ mpcore_wdt_start(wdt);
+ ret = 0;
+ }
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ uarg.i = 0;
+ ret = 0;
+ break;
+
+ case WDIOC_KEEPALIVE:
+ mpcore_wdt_keepalive(wdt);
+ ret = 0;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ ret = mpcore_wdt_set_heartbeat(uarg.i);
+ if (ret)
+ break;
+
+ mpcore_wdt_keepalive(wdt);
+ /* Fall */
+ case WDIOC_GETTIMEOUT:
+ uarg.i = mpcore_margin;
+ ret = 0;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+ ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
+ if (ret)
+ ret = -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * System shutdown handler. Turn off the watchdog if we're
+ * restarting or halting the system.
+ */
+static void mpcore_wdt_shutdown(struct device *_dev)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(_dev);
+
+ if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
+ mpcore_wdt_stop(wdt);
+}
+
+/*
+ * Kernel Interfaces
+ */
+static struct file_operations mpcore_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mpcore_wdt_write,
+ .ioctl = mpcore_wdt_ioctl,
+ .open = mpcore_wdt_open,
+ .release = mpcore_wdt_release,
+};
+
+static struct miscdevice mpcore_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mpcore_wdt_fops,
+};
+
+static int __devinit mpcore_wdt_probe(struct device *_dev)
+{
+ struct platform_device *dev = to_platform_device(_dev);
+ struct mpcore_wdt *wdt;
+ struct resource *res;
+ int ret;
+
+ /* We only accept one device, and it must have an id of -1 */
+ if (dev->id != -1)
+ return -ENODEV;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
+ if (!wdt) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+ memset(wdt, 0, sizeof(struct mpcore_wdt));
+
+ wdt->dev = &dev->dev;
+ wdt->irq = platform_get_irq(dev, 0);
+ wdt->base = ioremap(res->start, res->end - res->start + 1);
+ if (!wdt->base) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ mpcore_wdt_miscdev.dev = &dev->dev;
+ ret = misc_register(&mpcore_wdt_miscdev);
+ if (ret) {
+ dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_misc;
+ }
+
+ ret = request_irq(wdt->irq, mpcore_wdt_fire, SA_INTERRUPT, "mpcore_wdt", wdt);
+ if (ret) {
+ dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
+ goto err_irq;
+ }
+
+ mpcore_wdt_stop(wdt);
+ dev_set_drvdata(&dev->dev, wdt);
+ mpcore_wdt_dev = dev;
+
+ return 0;
+
+ err_irq:
+ misc_deregister(&mpcore_wdt_miscdev);
+ err_misc:
+ iounmap(wdt->base);
+ err_free:
+ kfree(wdt);
+ err_out:
+ return ret;
+}
+
+static int __devexit mpcore_wdt_remove(struct device *dev)
+{
+ struct mpcore_wdt *wdt = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ misc_deregister(&mpcore_wdt_miscdev);
+
+ mpcore_wdt_dev = NULL;
+
+ free_irq(wdt->irq, wdt);
+ iounmap(wdt->base);
+ kfree(wdt);
+ return 0;
+}
+
+static struct device_driver mpcore_wdt_driver = {
+ .owner = THIS_MODULE,
+ .name = "mpcore_wdt",
+ .bus = &platform_bus_type,
+ .probe = mpcore_wdt_probe,
+ .remove = __devexit_p(mpcore_wdt_remove),
+ .shutdown = mpcore_wdt_shutdown,
+};
+
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+
+static int __init mpcore_wdt_init(void)
+{
+ /*
+ * Check that the margin value is within it's range;
+ * if not reset to the default
+ */
+ if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
+ mpcore_wdt_set_heartbeat(TIMER_MARGIN);
+ printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
+ TIMER_MARGIN);
+ }
+
+ printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+
+ return driver_register(&mpcore_wdt_driver);
+}
+
+static void __exit mpcore_wdt_exit(void)
+{
+ driver_unregister(&mpcore_wdt_driver);
+}
+
+module_init(mpcore_wdt_init);
+module_exit(mpcore_wdt_exit);
+
+MODULE_AUTHOR("ARM Limited");
+MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
new file mode 100644
index 000000000000..119b3c541d95
--- /dev/null
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -0,0 +1,255 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required. This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+
+#include <asm/mv64x60.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* MV64x60 WDC (config) register access definitions */
+#define MV64x60_WDC_CTL1_MASK (3 << 24)
+#define MV64x60_WDC_CTL1(val) ((val & 3) << 24)
+#define MV64x60_WDC_CTL2_MASK (3 << 26)
+#define MV64x60_WDC_CTL2(val) ((val & 3) << 26)
+
+/* Flags bits */
+#define MV64x60_WDOG_FLAG_OPENED 0
+#define MV64x60_WDOG_FLAG_ENABLED 1
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *mv64x60_regs;
+static int mv64x60_wdt_timeout;
+
+static void mv64x60_wdt_reg_write(u32 val)
+{
+ /* Allow write only to CTL1 / CTL2 fields, retaining values in
+ * other fields.
+ */
+ u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
+ data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
+ data |= val;
+ writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+}
+
+static void mv64x60_wdt_service(void)
+{
+ /* Write 01 followed by 10 to CTL2 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+}
+
+static void mv64x60_wdt_handler_disable(void)
+{
+ if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+ }
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+ if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+ }
+}
+
+static int mv64x60_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+ return -EBUSY;
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_enable();
+
+ nonseekable_open(inode, file);
+
+ return 0;
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+ mv64x60_wdt_service();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+ mv64x60_wdt_handler_disable();
+#endif
+
+ clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
+
+ return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t * ppos)
+{
+ if (len)
+ mv64x60_wdt_service();
+
+ return len;
+}
+
+static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int timeout;
+ void __user *argp = (void __user *)arg;
+ static struct watchdog_info info = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "MV64x60 watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(wdt_status, (int __user *)argp))
+ return -EFAULT;
+ wdt_status &= ~WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_GETTEMP:
+ return -EOPNOTSUPP;
+
+ case WDIOC_SETOPTIONS:
+ return -EOPNOTSUPP;
+
+ case WDIOC_KEEPALIVE:
+ mv64x60_wdt_service();
+ wdt_status |= WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ return -EOPNOTSUPP;
+
+ case WDIOC_GETTIMEOUT:
+ timeout = mv64x60_wdt_timeout * HZ;
+ if (put_user(timeout, (int __user *)argp))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static struct file_operations mv64x60_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mv64x60_wdt_write,
+ .ioctl = mv64x60_wdt_ioctl,
+ .open = mv64x60_wdt_open,
+ .release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct device *dev)
+{
+ struct platform_device *pd = to_platform_device(dev);
+ struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data;
+ int bus_clk = 133;
+
+ mv64x60_wdt_timeout = 10;
+ if (pdata) {
+ mv64x60_wdt_timeout = pdata->timeout;
+ bus_clk = pdata->bus_clk;
+ }
+
+ mv64x60_regs = mv64x60_get_bridge_vbase();
+
+ writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
+ mv64x60_regs + MV64x60_WDT_WDC);
+
+ return misc_register(&mv64x60_wdt_miscdev);
+}
+
+static int __devexit mv64x60_wdt_remove(struct device *dev)
+{
+ misc_deregister(&mv64x60_wdt_miscdev);
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_disable();
+
+ return 0;
+}
+
+static struct device_driver mv64x60_wdt_driver = {
+ .owner = THIS_MODULE,
+ .name = MV64x60_WDT_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64x60_wdt_probe,
+ .remove = __devexit_p(mv64x60_wdt_remove),
+};
+
+static struct platform_device *mv64x60_wdt_dev;
+
+static int __init mv64x60_wdt_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+ mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
+ -1, NULL, 0);
+ if (IS_ERR(mv64x60_wdt_dev)) {
+ ret = PTR_ERR(mv64x60_wdt_dev);
+ goto out;
+ }
+
+ ret = driver_register(&mv64x60_wdt_driver);
+ out:
+ return ret;
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+ driver_unregister(&mv64x60_wdt_driver);
+ platform_device_unregister(mv64x60_wdt_dev);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 427ad51b7a35..37c9e13ad3ac 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,7 +66,7 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/reboot.h>
-
+#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */
#include <asm/uaccess.h>
#include <asm/io.h>
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 2b13afb09c5d..d9ef55bdf88a 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -1,7 +1,7 @@
/*
* Berkshire PCI-PC Watchdog Card Driver
*
- * (c) Copyright 2003 Wim Van Sebroeck <wim@iguana.be>.
+ * (c) Copyright 2003-2005 Wim Van Sebroeck <wim@iguana.be>.
*
* Based on source code of the following authors:
* Ken Hollis <kenji@bitgate.com>,
@@ -21,7 +21,9 @@
*/
/*
- * A bells and whistles driver is available from http://www.pcwd.de/
+ * A bells and whistles driver is available from:
+ * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/
+ *
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
@@ -29,27 +31,29 @@
* Includes, defines, variables, module parameters, ...
*/
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/pci.h> /* For pci functions */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
+#include <asm/io.h> /* For inb/outb/... */
/* Module and version information */
-#define WATCHDOG_VERSION "1.01"
-#define WATCHDOG_DATE "15 Mar 2005"
+#define WATCHDOG_VERSION "1.02"
+#define WATCHDOG_DATE "03 Sep 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
@@ -68,19 +72,30 @@
* These are the defines that describe the control status bits for the
* PCI-PC Watchdog card.
*/
-#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */
-#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */
-#define WD_PCI_TTRP 0x04 /* Temperature Trip status */
+/* Port 1 : Control Status #1 */
+#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */
+#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */
+#define WD_PCI_TTRP 0x04 /* Temperature Trip status */
+#define WD_PCI_RL2A 0x08 /* Relay 2 Active */
+#define WD_PCI_RL1A 0x10 /* Relay 1 Active */
+#define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip/reset */
+#define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */
+/* Port 2 : Control Status #2 */
+#define WD_PCI_WDIS 0x10 /* Watchdog Disable */
+#define WD_PCI_ENTP 0x20 /* Enable Temperature Trip Reset */
+#define WD_PCI_WRSP 0x40 /* Watchdog wrote response */
+#define WD_PCI_PCMD 0x80 /* PC has sent command */
/* according to documentation max. time to process a command for the pci
* watchdog card is 100 ms, so we give it 150 ms to do it's job */
#define PCI_COMMAND_TIMEOUT 150
/* Watchdog's internal commands */
-#define CMD_GET_STATUS 0x04
-#define CMD_GET_FIRMWARE_VERSION 0x08
-#define CMD_READ_WATCHDOG_TIMEOUT 0x18
-#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19
+#define CMD_GET_STATUS 0x04
+#define CMD_GET_FIRMWARE_VERSION 0x08
+#define CMD_READ_WATCHDOG_TIMEOUT 0x18
+#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19
+#define CMD_GET_CLEAR_RESET_COUNT 0x84
/* We can only use 1 card due to the /dev/watchdog restriction */
static int cards_found;
@@ -89,15 +104,22 @@ static int cards_found;
static int temp_panic;
static unsigned long is_active;
static char expect_release;
-static struct {
- int supports_temp; /* Wether or not the card has a temperature device */
- int boot_status; /* The card's boot status */
- unsigned long io_addr; /* The cards I/O address */
- spinlock_t io_lock;
- struct pci_dev *pdev;
+static struct { /* this is private data for each PCI-PC watchdog card */
+ int supports_temp; /* Wether or not the card has a temperature device */
+ int boot_status; /* The card's boot status */
+ unsigned long io_addr; /* The cards I/O address */
+ spinlock_t io_lock; /* the lock for io operations */
+ struct pci_dev *pdev; /* the PCI-device */
} pcipcwd_private;
/* module parameters */
+#define QUIET 0 /* Default */
+#define VERBOSE 1 /* Verbose */
+#define DEBUG 2 /* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */
static int heartbeat = WATCHDOG_HEARTBEAT;
module_param(heartbeat, int, 0);
@@ -115,6 +137,10 @@ static int send_command(int cmd, int *msb, int *lsb)
{
int got_response, count;
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n",
+ cmd, *msb, *lsb);
+
spin_lock(&pcipcwd_private.io_lock);
/* If a command requires data it should be written first.
* Data for commands with 8 bits of data should be written to port 4.
@@ -129,10 +155,19 @@ static int send_command(int cmd, int *msb, int *lsb)
/* wait till the pci card processed the command, signaled by
* the WRSP bit in port 2 and give it a max. timeout of
* PCI_COMMAND_TIMEOUT to process */
- got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40;
+ got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) {
mdelay(1);
- got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40;
+ got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
+ }
+
+ if (debug >= DEBUG) {
+ if (got_response) {
+ printk(KERN_DEBUG PFX "time to process command was: %d ms\n",
+ count);
+ } else {
+ printk(KERN_DEBUG PFX "card did not respond on command!\n");
+ }
}
if (got_response) {
@@ -142,12 +177,66 @@ static int send_command(int cmd, int *msb, int *lsb)
/* clear WRSP bit */
inb_p(pcipcwd_private.io_addr + 6);
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
+ cmd, *msb, *lsb);
}
+
spin_unlock(&pcipcwd_private.io_lock);
return got_response;
}
+static inline void pcipcwd_check_temperature_support(void)
+{
+ if (inb_p(pcipcwd_private.io_addr) != 0xF0)
+ pcipcwd_private.supports_temp = 1;
+}
+
+static int pcipcwd_get_option_switches(void)
+{
+ int option_switches;
+
+ option_switches = inb_p(pcipcwd_private.io_addr + 3);
+ return option_switches;
+}
+
+static void pcipcwd_show_card_info(void)
+{
+ int got_fw_rev, fw_rev_major, fw_rev_minor;
+ char fw_ver_str[20]; /* The cards firmware version */
+ int option_switches;
+
+ got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
+ if (got_fw_rev) {
+ sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
+ } else {
+ sprintf(fw_ver_str, "<card no answer>");
+ }
+
+ /* Get switch settings */
+ option_switches = pcipcwd_get_option_switches();
+
+ printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n",
+ (int) pcipcwd_private.io_addr, fw_ver_str,
+ (pcipcwd_private.supports_temp ? "with" : "without"));
+
+ printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+ option_switches,
+ ((option_switches & 0x10) ? "ON" : "OFF"),
+ ((option_switches & 0x08) ? "ON" : "OFF"));
+
+ if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
+ printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n");
+
+ if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
+ printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
+
+ if (pcipcwd_private.boot_status == 0)
+ printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+}
+
static int pcipcwd_start(void)
{
int stat_reg;
@@ -159,11 +248,14 @@ static int pcipcwd_start(void)
stat_reg = inb_p(pcipcwd_private.io_addr + 2);
spin_unlock(&pcipcwd_private.io_lock);
- if (stat_reg & 0x10) {
+ if (stat_reg & WD_PCI_WDIS) {
printk(KERN_ERR PFX "Card timer not enabled\n");
return -1;
}
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog started\n");
+
return 0;
}
@@ -181,18 +273,25 @@ static int pcipcwd_stop(void)
stat_reg = inb_p(pcipcwd_private.io_addr + 2);
spin_unlock(&pcipcwd_private.io_lock);
- if (!(stat_reg & 0x10)) {
+ if (!(stat_reg & WD_PCI_WDIS)) {
printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
return -1;
}
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
return 0;
}
static int pcipcwd_keepalive(void)
{
/* Re-trigger watchdog by writing to port 0 */
- outb_p(0x42, pcipcwd_private.io_addr);
+ outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
return 0;
}
@@ -208,29 +307,64 @@ static int pcipcwd_set_heartbeat(int t)
send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb);
heartbeat = t;
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+ heartbeat);
+
return 0;
}
static int pcipcwd_get_status(int *status)
{
- int new_status;
+ int control_status;
*status=0;
- new_status = inb_p(pcipcwd_private.io_addr + 1);
- if (new_status & WD_PCI_WTRP)
+ control_status = inb_p(pcipcwd_private.io_addr + 1);
+ if (control_status & WD_PCI_WTRP)
*status |= WDIOF_CARDRESET;
- if (new_status & WD_PCI_TTRP) {
+ if (control_status & WD_PCI_TTRP) {
*status |= WDIOF_OVERHEAT;
if (temp_panic)
panic(PFX "Temperature overheat trip!\n");
}
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n",
+ control_status);
+
return 0;
}
static int pcipcwd_clear_status(void)
{
- outb_p(0x01, pcipcwd_private.io_addr + 1);
+ int control_status;
+ int msb;
+ int reset_counter;
+
+ if (debug >= VERBOSE)
+ printk(KERN_INFO PFX "clearing watchdog trip status & LED\n");
+
+ control_status = inb_p(pcipcwd_private.io_addr + 1);
+
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+ printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+ (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
+ }
+
+ /* clear trip status & LED and keep mode of relay 2 */
+ outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1);
+
+ /* clear reset counter */
+ msb=0;
+ reset_counter=0xff;
+ send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
+
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "reset count was: 0x%02x\n",
+ reset_counter);
+ }
+
return 0;
}
@@ -240,11 +374,18 @@ static int pcipcwd_get_temperature(int *temperature)
if (!pcipcwd_private.supports_temp)
return -ENODEV;
+ *temperature = inb_p(pcipcwd_private.io_addr);
+
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
- *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32;
+ *temperature = (*temperature * 9 / 5) + 32;
+
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "temperature is: %d F\n",
+ *temperature);
+ }
return 0;
}
@@ -254,7 +395,7 @@ static int pcipcwd_get_temperature(int *temperature)
*/
static ssize_t pcipcwd_write(struct file *file, const char __user *data,
- size_t len, loff_t *ppos)
+ size_t len, loff_t *ppos)
{
/* See if we got the magic character 'V' and reload the timer */
if (len) {
@@ -335,12 +476,14 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
- pcipcwd_stop();
+ if (pcipcwd_stop())
+ return -EIO;
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
- pcipcwd_start();
+ if (pcipcwd_start())
+ return -EIO;
retval = 0;
}
@@ -377,8 +520,11 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
static int pcipcwd_open(struct inode *inode, struct file *file)
{
/* /dev/watchdog can only be opened once */
- if (test_and_set_bit(0, &is_active))
+ if (test_and_set_bit(0, &is_active)) {
+ if (debug >= VERBOSE)
+ printk(KERN_ERR PFX "Attempt to open already opened device.\n");
return -EBUSY;
+ }
/* Activate */
pcipcwd_start();
@@ -488,19 +634,10 @@ static struct notifier_block pcipcwd_notifier = {
* Init & exit routines
*/
-static inline void check_temperature_support(void)
-{
- if (inb_p(pcipcwd_private.io_addr) != 0xF0)
- pcipcwd_private.supports_temp = 1;
-}
-
static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int ret = -EIO;
- int got_fw_rev, fw_rev_major, fw_rev_minor;
- char fw_ver_str[20];
- char option_switches;
cards_found++;
if (cards_found == 1)
@@ -542,36 +679,10 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
pcipcwd_stop();
/* Check whether or not the card supports the temperature device */
- check_temperature_support();
-
- /* Get the Firmware Version */
- got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
- if (got_fw_rev) {
- sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
- } else {
- sprintf(fw_ver_str, "<card no answer>");
- }
+ pcipcwd_check_temperature_support();
- /* Get switch settings */
- option_switches = inb_p(pcipcwd_private.io_addr + 3);
-
- printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n",
- (int) pcipcwd_private.io_addr, fw_ver_str,
- (pcipcwd_private.supports_temp ? "with" : "without"));
-
- printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
- option_switches,
- ((option_switches & 0x10) ? "ON" : "OFF"),
- ((option_switches & 0x08) ? "ON" : "OFF"));
-
- if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
- printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n");
-
- if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
- printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
-
- if (pcipcwd_private.boot_status == 0)
- printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+ /* Show info about the card itself */
+ pcipcwd_show_card_info();
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if (pcipcwd_set_heartbeat(heartbeat)) {
@@ -644,6 +755,7 @@ static struct pci_device_id pcipcwd_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
static struct pci_driver pcipcwd_driver = {
+ .owner = THIS_MODULE,
.name = WATCHDOG_NAME,
.id_table = pcipcwd_pci_tbl,
.probe = pcipcwd_card_init,
@@ -652,7 +764,7 @@ static struct pci_driver pcipcwd_driver = {
static int __init pcipcwd_init_module(void)
{
- spin_lock_init (&pcipcwd_private.io_lock);
+ spin_lock_init(&pcipcwd_private.io_lock);
return pci_register_driver(&pcipcwd_driver);
}
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index f85ac898a49a..751cb77b0715 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -27,7 +27,10 @@
* Fixed tmr_count / wdt_count confusion
* Added configurable debug
*
- * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code
+ * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code
+ *
+ * 25-Jan-2005 DA Added suspend/resume support
+ * Replaced reboot notifier with .shutdown method
*
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
@@ -40,10 +43,8 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
@@ -317,20 +318,6 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file,
}
}
-/*
- * Notifier for system down
- */
-
-static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- if(code==SYS_DOWN || code==SYS_HALT) {
- /* Turn the WDT off */
- s3c2410wdt_stop();
- }
- return NOTIFY_DONE;
-}
-
/* kernel interface */
static struct file_operations s3c2410wdt_fops = {
@@ -348,10 +335,6 @@ static struct miscdevice s3c2410wdt_miscdev = {
.fops = &s3c2410wdt_fops,
};
-static struct notifier_block s3c2410wdt_notifier = {
- .notifier_call = s3c2410wdt_notify_sys,
-};
-
/* interrupt handler code */
static irqreturn_t s3c2410wdt_irq(int irqno, void *param,
@@ -432,18 +415,10 @@ static int s3c2410wdt_probe(struct device *dev)
}
}
- ret = register_reboot_notifier(&s3c2410wdt_notifier);
- if (ret) {
- printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n",
- ret);
- return ret;
- }
-
ret = misc_register(&s3c2410wdt_miscdev);
if (ret) {
printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
- unregister_reboot_notifier(&s3c2410wdt_notifier);
return ret;
}
@@ -479,15 +454,60 @@ static int s3c2410wdt_remove(struct device *dev)
return 0;
}
+static void s3c2410wdt_shutdown(struct device *dev)
+{
+ s3c2410wdt_stop();
+}
+
+#ifdef CONFIG_PM
+
+static unsigned long wtcon_save;
+static unsigned long wtdat_save;
+
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state)
+{
+ /* Save watchdog state, and turn it off. */
+ wtcon_save = readl(wdt_base + S3C2410_WTCON);
+ wtdat_save = readl(wdt_base + S3C2410_WTDAT);
+
+ /* Note that WTCNT doesn't need to be saved. */
+ s3c2410wdt_stop();
+
+ return 0;
+}
+
+static int s3c2410wdt_resume(struct device *dev)
+{
+ /* Restore watchdog state. */
+
+ writel(wtdat_save, wdt_base + S3C2410_WTDAT);
+ writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
+ writel(wtcon_save, wdt_base + S3C2410_WTCON);
+
+ printk(KERN_INFO PFX "watchdog %sabled\n",
+ (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+
+ return 0;
+}
+
+#else
+#define s3c2410wdt_suspend NULL
+#define s3c2410wdt_resume NULL
+#endif /* CONFIG_PM */
+
+
static struct device_driver s3c2410wdt_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2410-wdt",
.bus = &platform_bus_type,
.probe = s3c2410wdt_probe,
.remove = s3c2410wdt_remove,
+ .shutdown = s3c2410wdt_shutdown,
+ .suspend = s3c2410wdt_suspend,
+ .resume = s3c2410wdt_resume,
};
-
static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
static int __init watchdog_init(void)
@@ -499,13 +519,13 @@ static int __init watchdog_init(void)
static void __exit watchdog_exit(void)
{
driver_unregister(&s3c2410wdt_driver);
- unregister_reboot_notifier(&s3c2410wdt_notifier);
}
module_init(watchdog_init);
module_exit(watchdog_exit);
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, "
+ "Dimitry Andric <dimitry.andric@tomtom.com>");
MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
new file mode 100644
index 000000000000..c6cbf808d8c2
--- /dev/null
+++ b/drivers/char/watchdog/sbc8360.c
@@ -0,0 +1,414 @@
+/*
+ * SBC8360 Watchdog driver
+ *
+ * (c) Copyright 2005 Webcon, Inc.
+ *
+ * Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ * on acquirewdt.c which is based on wdt.c.
+ *
+ * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ * Based on advantechwdt.c which is based on acquirewdt.c which
+ * is based on wdt.c.
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * Based on acquirewdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (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>
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H. To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ * N
+ * M | 1 2 3 4
+ * --|----------------------------------
+ * 0 | 0.5s 5s 50s 100s
+ * 1 | 1s 10s 100s 200s
+ * 2 | 1.5s 15s 150s 300s
+ * 3 | 2s 20s 200s 400s
+ * 4 | 2.5s 25s 250s 500s
+ * 5 | 3s 30s 300s 600s
+ * 6 | 3.5s 35s 350s 700s
+ * 7 | 4s 40s 400s 800s
+ * 8 | 4.5s 45s 450s 900s
+ * 9 | 5s 50s 500s 1000s
+ * A | 5.5s 55s 550s 1100s
+ * B | 6s 60s 600s 1200s
+ * C | 6.5s 65s 650s 1300s
+ * D | 7s 70s 700s 1400s
+ * E | 7.5s 75s 750s 1500s
+ * F | 8s 80s 800s 1600s
+ *
+ * Another way to say the same things is:
+ * For N=1, Timeout = (M+1) * 0.5s
+ * For N=2, Timeout = (M+1) * 5s
+ * For N=3, Timeout = (M+1) * 50s
+ * For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+ {0, 1}, /* 0 = 0.5s */
+ {1, 1}, /* 1 = 1s */
+ {2, 1}, /* 2 = 1.5s */
+ {3, 1}, /* 3 = 2s */
+ {4, 1}, /* 4 = 2.5s */
+ {5, 1}, /* 5 = 3s */
+ {6, 1}, /* 6 = 3.5s */
+ {7, 1}, /* 7 = 4s */
+ {8, 1}, /* 8 = 4.5s */
+ {9, 1}, /* 9 = 5s */
+ {0xA, 1}, /* 10 = 5.5s */
+ {0xB, 1}, /* 11 = 6s */
+ {0xC, 1}, /* 12 = 6.5s */
+ {0xD, 1}, /* 13 = 7s */
+ {0xE, 1}, /* 14 = 7.5s */
+ {0xF, 1}, /* 15 = 8s */
+ {0, 2}, /* 16 = 5s */
+ {1, 2}, /* 17 = 10s */
+ {2, 2}, /* 18 = 15s */
+ {3, 2}, /* 19 = 20s */
+ {4, 2}, /* 20 = 25s */
+ {5, 2}, /* 21 = 30s */
+ {6, 2}, /* 22 = 35s */
+ {7, 2}, /* 23 = 40s */
+ {8, 2}, /* 24 = 45s */
+ {9, 2}, /* 25 = 50s */
+ {0xA, 2}, /* 26 = 55s */
+ {0xB, 2}, /* 27 = 60s */
+ {0xC, 2}, /* 28 = 65s */
+ {0xD, 2}, /* 29 = 70s */
+ {0xE, 2}, /* 30 = 75s */
+ {0xF, 2}, /* 31 = 80s */
+ {0, 3}, /* 32 = 50s */
+ {1, 3}, /* 33 = 100s */
+ {2, 3}, /* 34 = 150s */
+ {3, 3}, /* 35 = 200s */
+ {4, 3}, /* 36 = 250s */
+ {5, 3}, /* 37 = 300s */
+ {6, 3}, /* 38 = 350s */
+ {7, 3}, /* 39 = 400s */
+ {8, 3}, /* 40 = 450s */
+ {9, 3}, /* 41 = 500s */
+ {0xA, 3}, /* 42 = 550s */
+ {0xB, 3}, /* 43 = 600s */
+ {0xC, 3}, /* 44 = 650s */
+ {0xD, 3}, /* 45 = 700s */
+ {0xE, 3}, /* 46 = 750s */
+ {0xF, 3}, /* 47 = 800s */
+ {0, 4}, /* 48 = 100s */
+ {1, 4}, /* 49 = 200s */
+ {2, 4}, /* 50 = 300s */
+ {3, 4}, /* 51 = 400s */
+ {4, 4}, /* 52 = 500s */
+ {5, 4}, /* 53 = 600s */
+ {6, 4}, /* 54 = 700s */
+ {7, 4}, /* 55 = 800s */
+ {8, 4}, /* 56 = 900s */
+ {9, 4}, /* 57 = 1000s */
+ {0xA, 4}, /* 58 = 1100s */
+ {0xB, 4}, /* 59 = 1200s */
+ {0xC, 4}, /* 60 = 1300s */
+ {0xD, 4}, /* 61 = 1400s */
+ {0xE, 4}, /* 62 = 1500s */
+ {0xF, 4} /* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 27);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+ /* Enable the watchdog */
+ outb(0x0A, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ outb(0x0B, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Set timeout multiplier */
+ outb(wd_multiplier, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+ /* Write the base timer register */
+ outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ 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;
+ }
+ }
+ sbc8360_ping();
+ }
+ return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (test_and_set_bit(0, &sbc8360_is_open)) {
+ spin_unlock(&sbc8360_lock);
+ return -EBUSY;
+ }
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate and ping once to start the countdown */
+ spin_unlock(&sbc8360_lock);
+ sbc8360_activate();
+ sbc8360_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (expect_close == 42)
+ outb(0, SBC8360_ENABLE);
+ else
+ printk(KERN_CRIT PFX
+ "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
+
+ clear_bit(0, &sbc8360_is_open);
+ expect_close = 0;
+ spin_unlock(&sbc8360_lock);
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Disable the SBC8360 Watchdog */
+ outb(0, SBC8360_ENABLE);
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations sbc8360_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = sbc8360_write,
+ .open = sbc8360_open,
+ .release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &sbc8360_fops,
+};
+
+/*
+ * The SBC8360 needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+ .notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+ int res;
+ unsigned long int mseconds = 60000;
+
+ spin_lock_init(&sbc8360_lock);
+ res = misc_register(&sbc8360_miscdev);
+ if (res) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ goto out_nomisc;
+ }
+
+ if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+ printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+ SBC8360_ENABLE);
+ res = -EIO;
+ goto out_noenablereg;
+ }
+ if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+ printk(KERN_ERR PFX
+ "BASETIME method I/O %X is not available.\n",
+ SBC8360_BASETIME);
+ res = -EIO;
+ goto out_nobasetimereg;
+ }
+
+ res = register_reboot_notifier(&sbc8360_notifier);
+ if (res) {
+ printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+ goto out_noreboot;
+ }
+
+ if (timeout < 0 || timeout > 63) {
+ printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+ res = -EINVAL;
+ goto out_noreboot;
+ }
+
+ wd_margin = wd_times[timeout][0];
+ wd_multiplier = wd_times[timeout][1];
+
+ if (wd_multiplier == 1)
+ mseconds = (wd_margin + 1) * 500;
+ else if (wd_multiplier == 2)
+ mseconds = (wd_margin + 1) * 5000;
+ else if (wd_multiplier == 3)
+ mseconds = (wd_margin + 1) * 50000;
+ else if (wd_multiplier == 4)
+ mseconds = (wd_margin + 1) * 100000;
+
+ /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+ printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+ return 0;
+
+ out_noreboot:
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+ out_noenablereg:
+ out_nobasetimereg:
+ misc_deregister(&sbc8360_miscdev);
+ out_nomisc:
+ return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+ misc_deregister(&sbc8360_miscdev);
+ unregister_reboot_notifier(&sbc8360_notifier);
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of sbc8360.c */
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index 72501be79b0c..4ee9974ad8cb 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -63,6 +63,7 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index c4568569f3a8..b4a102a2d7e3 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -206,7 +206,7 @@ static struct file_operations scx200_wdt_fops = {
static struct miscdevice scx200_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
- .name = NAME,
+ .name = "watchdog",
.fops = &scx200_wdt_fops,
};
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index 4d7ed931f5c6..a91edaf3a350 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -47,6 +47,8 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
+
#include <asm/uaccess.h>
#define PFX "SoftDog: "
@@ -77,7 +79,7 @@ static void watchdog_fire(unsigned long);
static struct timer_list watchdog_ticktock =
TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long timer_alive;
+static unsigned long driver_open, orphan_timer;
static char expect_close;
@@ -87,6 +89,9 @@ static char expect_close;
static void watchdog_fire(unsigned long data)
{
+ if (test_and_clear_bit(0, &orphan_timer))
+ module_put(THIS_MODULE);
+
if (soft_noboot)
printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
else
@@ -128,9 +133,9 @@ static int softdog_set_heartbeat(int t)
static int softdog_open(struct inode *inode, struct file *file)
{
- if(test_and_set_bit(0, &timer_alive))
+ if (test_and_set_bit(0, &driver_open))
return -EBUSY;
- if (nowayout)
+ if (!test_and_clear_bit(0, &orphan_timer))
__module_get(THIS_MODULE);
/*
* Activate timer
@@ -147,11 +152,13 @@ static int softdog_release(struct inode *inode, struct file *file)
*/
if (expect_close == 42) {
softdog_stop();
+ module_put(THIS_MODULE);
} else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ set_bit(0, &orphan_timer);
softdog_keepalive();
}
- clear_bit(0, &timer_alive);
+ clear_bit(0, &driver_open);
expect_close = 0;
return 0;
}
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 465e0fd0423d..d15ca9a3986f 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -93,6 +93,12 @@ w83627hf_init(void)
w83627hf_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 */
@@ -353,5 +359,5 @@ module_exit(wdt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
-MODULE_DESCRIPTION("w38627hf WDT driver");
+MODULE_DESCRIPTION("w83627hf WDT driver");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
new file mode 100644
index 000000000000..a7ff64c8921f
--- /dev/null
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -0,0 +1,543 @@
+/*
+ * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on w83877f_wdt.c by Scott Jennings,
+ * and wdt977.c by Woody Suwalski
+ *
+ * -----------------------
+ *
+ * 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/config.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 <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION "1.00"
+#define WATCHDOG_NAME "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x3F0
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
+#define DEFAULT_TIMEOUT 45 /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutW; /* timeout in watchdog counter units */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 has the timeout in watchdog counter units.
+ * F3 is set to enable watchdog LED blink at timeout.
+ * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /* Set device Aux2 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+ * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+ * Map GP16 at pin 119.
+ * In test mode watch the bit 0 on F4 to indicate "triggered" or
+ * check watchdog LED on SBC.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ unsigned pin_map;
+
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x0A,IO_DATA_PORT);
+ outb_p(0x2C,IO_INDEX_PORT);
+ pin_map = inb_p(IO_DATA_PORT);
+ pin_map |= 0x10;
+ pin_map &= ~(0x20);
+ outb_p(0x2C,IO_INDEX_PORT);
+ outb_p(pin_map,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+
+ /* Set device Aux1 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "activated.\n");
+
+ return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 is reset to its default value (watchdog timer disabled).
+ * F3 is reset to its default state.
+ * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0xFF,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
+ * Gp13 (in reg E3) as inputs.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "shutdown.\n");
+
+ return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to kick watchdog reg F2 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+ int tmrval;
+
+ /*
+ * Convert seconds to watchdog counter time units, rounding up.
+ * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
+ * value. This information is supplied in the PCM-5335 manual and was
+ * checked by me on a real board. This is a bit strange because W83977f
+ * datasheet says counter unit is in minutes!
+ */
+ if (t < 15)
+ return -EINVAL;
+
+ tmrval = ((t + 15) + 29) / 30;
+
+ if (tmrval > 255)
+ return -EINVAL;
+
+ /*
+ * timeout is the timeout in seconds,
+ * timeoutW is the timeout in watchdog counter units.
+ */
+ timeoutW = tmrval;
+ timeout = (timeoutW * 30) - 15;
+ return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+ int new_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to read watchdog reg F4 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ new_status = inb_p(IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status = 0;
+ if (new_status & 1)
+ *status |= WDIOF_CARDRESET;
+
+ return 0;
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ /* If the watchdog is alive we don't need to start it again */
+ if( test_and_set_bit(0, &timer_alive) )
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (expect_close == 42)
+ {
+ wdt_stop();
+ clear_bit(0, &timer_alive);
+ } else {
+ wdt_keepalive();
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ }
+ expect_close = 0;
+ return 0;
+}
+
+/*
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @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 we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if(count)
+ {
+ if (!nowayout)
+ {
+ size_t ofs;
+
+ /* note: just in case someone wrote the magic character long ago */
+ expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for(ofs = 0; ofs != count; ofs++)
+ {
+ char c;
+ if (get_user(c, buf + ofs))
+ return -EFAULT;
+ if (c == 'V') {
+ expect_close = 42;
+ }
+ }
+ }
+
+ /* someone wrote to us, we should restart timer */
+ wdt_keepalive();
+ }
+ return count;
+}
+
+/*
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @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.
+ */
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int status;
+ int new_options, retval = -EINVAL;
+ int new_timeout;
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ uarg.i = (int __user *)arg;
+
+ switch(cmd)
+ {
+ default:
+ return -ENOIOCTLCMD;
+
+ 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;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ wdt_stop();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ wdt_start();
+ retval = 0;
+ }
+
+ return retval;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+
+ if (wdt_set_timeout(new_timeout))
+ return -EINVAL;
+
+ wdt_keepalive();
+ /* Fall */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, uarg.i);
+
+ }
+}
+
+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 struct file_operations wdt_fops=
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .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 w83977f_wdt_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO PFX DRIVER_VERSION);
+
+ spin_lock_init(&spinlock);
+
+ /*
+ * Check that the timeout value is within it's range ;
+ * if not reset to the default
+ */
+ if (wdt_set_timeout(timeout)) {
+ wdt_set_timeout(DEFAULT_TIMEOUT);
+ printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+ DEFAULT_TIMEOUT);
+ }
+
+ if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+ {
+ printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ IO_INDEX_PORT);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ 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_region;
+ }
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ rc);
+ goto err_out_miscdev;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+ timeout, nowayout, testmode);
+
+ return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt_miscdev);
+err_out_region:
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+ wdt_stop();
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 4b3311993d48..dc9370f6c348 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -711,6 +711,7 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
static struct pci_driver wdtpci_driver = {
+ .owner = THIS_MODULE,
.name = "wdt_pci",
.id_table = wdtpci_pci_tbl,
.probe = wdtpci_init_one,
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
new file mode 100644
index 000000000000..0bc2059c1e08
--- /dev/null
+++ b/drivers/connector/Kconfig
@@ -0,0 +1,13 @@
+menu "Connector - unified userspace <-> kernelspace linker"
+
+config CONNECTOR
+ tristate "Connector - unified userspace <-> kernelspace linker"
+ depends on NET
+ ---help---
+ This is unified userspace <-> kernelspace connector working on top
+ of the netlink socket protocol.
+
+ Connector support can also be built as a module. If so, the module
+ will be called cn.ko.
+
+endmenu
diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile
new file mode 100644
index 000000000000..12ca79e8234d
--- /dev/null
+++ b/drivers/connector/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_CONNECTOR) += cn.o
+
+cn-y += cn_queue.o connector.o
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
new file mode 100644
index 000000000000..9f2f00d82917
--- /dev/null
+++ b/drivers/connector/cn_queue.c
@@ -0,0 +1,179 @@
+/*
+ * cn_queue.c
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/suspend.h>
+#include <linux/connector.h>
+#include <linux/delay.h>
+
+void cn_queue_wrapper(void *data)
+{
+ struct cn_callback_data *d = data;
+
+ d->callback(d->callback_priv);
+
+ d->destruct_data(d->ddata);
+ d->ddata = NULL;
+
+ kfree(d->free);
+}
+
+static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
+{
+ struct cn_callback_entry *cbq;
+
+ cbq = kzalloc(sizeof(*cbq), GFP_KERNEL);
+ if (!cbq) {
+ printk(KERN_ERR "Failed to create new callback queue.\n");
+ return NULL;
+ }
+
+ snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
+ memcpy(&cbq->id.id, id, sizeof(struct cb_id));
+ cbq->data.callback = callback;
+
+ INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
+ return cbq;
+}
+
+static void cn_queue_free_callback(struct cn_callback_entry *cbq)
+{
+ cancel_delayed_work(&cbq->work);
+ flush_workqueue(cbq->pdev->cn_queue);
+
+ kfree(cbq);
+}
+
+int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
+{
+ return ((i1->idx == i2->idx) && (i1->val == i2->val));
+}
+
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
+{
+ struct cn_callback_entry *cbq, *__cbq;
+ int found = 0;
+
+ cbq = cn_queue_alloc_callback_entry(name, id, callback);
+ if (!cbq)
+ return -ENOMEM;
+
+ atomic_inc(&dev->refcnt);
+ cbq->pdev = dev;
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
+ if (cn_cb_equal(&__cbq->id.id, id)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ list_add_tail(&cbq->callback_entry, &dev->queue_list);
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (found) {
+ atomic_dec(&dev->refcnt);
+ cn_queue_free_callback(cbq);
+ return -EINVAL;
+ }
+
+ cbq->nls = dev->nls;
+ cbq->seq = 0;
+ cbq->group = cbq->id.id.idx;
+
+ return 0;
+}
+
+void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
+{
+ struct cn_callback_entry *cbq, *n;
+ int found = 0;
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
+ if (cn_cb_equal(&cbq->id.id, id)) {
+ list_del(&cbq->callback_entry);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (found) {
+ cn_queue_free_callback(cbq);
+ atomic_dec_and_test(&dev->refcnt);
+ }
+}
+
+struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+{
+ struct cn_queue_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ snprintf(dev->name, sizeof(dev->name), "%s", name);
+ atomic_set(&dev->refcnt, 0);
+ INIT_LIST_HEAD(&dev->queue_list);
+ spin_lock_init(&dev->queue_lock);
+
+ dev->nls = nls;
+ dev->netlink_groups = 0;
+
+ dev->cn_queue = create_workqueue(dev->name);
+ if (!dev->cn_queue) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+
+void cn_queue_free_dev(struct cn_queue_dev *dev)
+{
+ struct cn_callback_entry *cbq, *n;
+
+ flush_workqueue(dev->cn_queue);
+ destroy_workqueue(dev->cn_queue);
+
+ spin_lock_bh(&dev->queue_lock);
+ list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)
+ list_del(&cbq->callback_entry);
+ spin_unlock_bh(&dev->queue_lock);
+
+ while (atomic_read(&dev->refcnt)) {
+ printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+ dev->name, atomic_read(&dev->refcnt));
+ msleep(1000);
+ }
+
+ kfree(dev);
+ dev = NULL;
+}
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
new file mode 100644
index 000000000000..505677fb3157
--- /dev/null
+++ b/drivers/connector/connector.c
@@ -0,0 +1,488 @@
+/*
+ * connector.c
+ *
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/moduleparam.h>
+#include <linux/connector.h>
+
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+
+static u32 cn_idx = CN_IDX_CONNECTOR;
+static u32 cn_val = CN_VAL_CONNECTOR;
+
+module_param(cn_idx, uint, 0);
+module_param(cn_val, uint, 0);
+MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
+MODULE_PARM_DESC(cn_val, "Connector's main device val.");
+
+static DECLARE_MUTEX(notify_lock);
+static LIST_HEAD(notify_list);
+
+static struct cn_dev cdev;
+
+int cn_already_initialized = 0;
+
+/*
+ * msg->seq and msg->ack are used to determine message genealogy.
+ * When someone sends message it puts there locally unique sequence
+ * and random acknowledge numbers. Sequence number may be copied into
+ * nlmsghdr->nlmsg_seq too.
+ *
+ * Sequence number is incremented with each message to be sent.
+ *
+ * If we expect reply to our message then the sequence number in
+ * received message MUST be the same as in original message, and
+ * acknowledge number MUST be the same + 1.
+ *
+ * If we receive a message and its sequence number is not equal to the
+ * one we are expecting then it is a new message.
+ *
+ * If we receive a message and its sequence number is the same as one
+ * we are expecting but it's acknowledgement number is not equal to
+ * the acknowledgement number in the original message + 1, then it is
+ * a new message.
+ *
+ */
+int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
+{
+ struct cn_callback_entry *__cbq;
+ unsigned int size;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct cn_msg *data;
+ struct cn_dev *dev = &cdev;
+ u32 group = 0;
+ int found = 0;
+
+ if (!__group) {
+ spin_lock_bh(&dev->cbdev->queue_lock);
+ list_for_each_entry(__cbq, &dev->cbdev->queue_list,
+ callback_entry) {
+ if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
+ found = 1;
+ group = __cbq->group;
+ }
+ }
+ spin_unlock_bh(&dev->cbdev->queue_lock);
+
+ if (!found)
+ return -ENODEV;
+ } else {
+ group = __group;
+ }
+
+ size = NLMSG_SPACE(sizeof(*msg) + msg->len);
+
+ skb = alloc_skb(size, gfp_mask);
+ if (!skb)
+ return -ENOMEM;
+
+ nlh = NLMSG_PUT(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh));
+
+ data = NLMSG_DATA(nlh);
+
+ memcpy(data, msg, sizeof(*data) + msg->len);
+
+ NETLINK_CB(skb).dst_group = group;
+
+ netlink_broadcast(dev->nls, skb, 0, group, gfp_mask);
+
+ return 0;
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/*
+ * Callback helper - queues work and setup destructor for given data.
+ */
+static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
+{
+ struct cn_callback_entry *__cbq;
+ struct cn_dev *dev = &cdev;
+ int err = -ENODEV;
+
+ spin_lock_bh(&dev->cbdev->queue_lock);
+ list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
+ if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
+ if (likely(!test_bit(0, &__cbq->work.pending) &&
+ __cbq->data.ddata == NULL)) {
+ __cbq->data.callback_priv = msg;
+
+ __cbq->data.ddata = data;
+ __cbq->data.destruct_data = destruct_data;
+
+ if (queue_work(dev->cbdev->cn_queue,
+ &__cbq->work))
+ err = 0;
+ } else {
+ struct work_struct *w;
+ struct cn_callback_data *d;
+
+ w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
+ if (w) {
+ d = (struct cn_callback_data *)(w+1);
+
+ d->callback_priv = msg;
+ d->callback = __cbq->data.callback;
+ d->ddata = data;
+ d->destruct_data = destruct_data;
+ d->free = w;
+
+ INIT_LIST_HEAD(&w->entry);
+ w->pending = 0;
+ w->func = &cn_queue_wrapper;
+ w->data = d;
+ init_timer(&w->timer);
+
+ if (queue_work(dev->cbdev->cn_queue, w))
+ err = 0;
+ else {
+ kfree(w);
+ err = -EINVAL;
+ }
+ } else
+ err = -ENOMEM;
+ }
+ break;
+ }
+ }
+ spin_unlock_bh(&dev->cbdev->queue_lock);
+
+ return err;
+}
+
+/*
+ * Skb receive helper - checks skb and msg size and calls callback
+ * helper.
+ */
+static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ u32 pid, uid, seq, group;
+ struct cn_msg *msg;
+
+ pid = NETLINK_CREDS(skb)->pid;
+ uid = NETLINK_CREDS(skb)->uid;
+ seq = nlh->nlmsg_seq;
+ group = NETLINK_CB((skb)).dst_group;
+ msg = NLMSG_DATA(nlh);
+
+ return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+}
+
+/*
+ * Main netlink receiving function.
+ *
+ * It checks skb and netlink header sizes and calls the skb receive
+ * helper with a shared skb.
+ */
+static void cn_rx_skb(struct sk_buff *__skb)
+{
+ struct nlmsghdr *nlh;
+ u32 len;
+ int err;
+ struct sk_buff *skb;
+
+ skb = skb_get(__skb);
+
+ if (skb->len >= NLMSG_SPACE(0)) {
+ nlh = (struct nlmsghdr *)skb->data;
+
+ if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
+ skb->len < nlh->nlmsg_len ||
+ nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
+ kfree_skb(skb);
+ goto out;
+ }
+
+ len = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (len > skb->len)
+ len = skb->len;
+
+ err = __cn_rx_skb(skb, nlh);
+ if (err < 0)
+ kfree_skb(skb);
+ }
+
+out:
+ kfree_skb(__skb);
+}
+
+/*
+ * Netlink socket input callback - dequeues the skbs and calls the
+ * main netlink receiving function.
+ */
+static void cn_input(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
+ cn_rx_skb(skb);
+}
+
+/*
+ * Notification routing.
+ *
+ * Gets id and checks if there are notification request for it's idx
+ * and val. If there are such requests notify the listeners with the
+ * given notify event.
+ *
+ */
+static void cn_notify(struct cb_id *id, u32 notify_event)
+{
+ struct cn_ctl_entry *ent;
+
+ down(&notify_lock);
+ list_for_each_entry(ent, &notify_list, notify_entry) {
+ int i;
+ struct cn_notify_req *req;
+ struct cn_ctl_msg *ctl = ent->msg;
+ int idx_found, val_found;
+
+ idx_found = val_found = 0;
+
+ req = (struct cn_notify_req *)ctl->data;
+ for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
+ if (id->idx >= req->first &&
+ id->idx < req->first + req->range) {
+ idx_found = 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
+ if (id->val >= req->first &&
+ id->val < req->first + req->range) {
+ val_found = 1;
+ break;
+ }
+ }
+
+ if (idx_found && val_found) {
+ struct cn_msg m = { .ack = notify_event, };
+
+ memcpy(&m.id, id, sizeof(m.id));
+ cn_netlink_send(&m, ctl->group, GFP_KERNEL);
+ }
+ }
+ up(&notify_lock);
+}
+
+/*
+ * Callback add routing - adds callback with given ID and name.
+ * If there is registered callback with the same ID it will not be added.
+ *
+ * May sleep.
+ */
+int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
+{
+ int err;
+ struct cn_dev *dev = &cdev;
+
+ err = cn_queue_add_callback(dev->cbdev, name, id, callback);
+ if (err)
+ return err;
+
+ cn_notify(id, 0);
+
+ return 0;
+}
+
+/*
+ * Callback remove routing - removes callback
+ * with given ID.
+ * If there is no registered callback with given
+ * ID nothing happens.
+ *
+ * May sleep while waiting for reference counter to become zero.
+ */
+void cn_del_callback(struct cb_id *id)
+{
+ struct cn_dev *dev = &cdev;
+
+ cn_queue_del_callback(dev->cbdev, id);
+ cn_notify(id, 1);
+}
+
+/*
+ * Checks two connector's control messages to be the same.
+ * Returns 1 if they are the same or if the first one is corrupted.
+ */
+static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
+{
+ int i;
+ struct cn_notify_req *req1, *req2;
+
+ if (m1->idx_notify_num != m2->idx_notify_num)
+ return 0;
+
+ if (m1->val_notify_num != m2->val_notify_num)
+ return 0;
+
+ if (m1->len != m2->len)
+ return 0;
+
+ if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
+ m1->len)
+ return 1;
+
+ req1 = (struct cn_notify_req *)m1->data;
+ req2 = (struct cn_notify_req *)m2->data;
+
+ for (i = 0; i < m1->idx_notify_num; ++i) {
+ if (req1->first != req2->first || req1->range != req2->range)
+ return 0;
+ req1++;
+ req2++;
+ }
+
+ for (i = 0; i < m1->val_notify_num; ++i) {
+ if (req1->first != req2->first || req1->range != req2->range)
+ return 0;
+ req1++;
+ req2++;
+ }
+
+ return 1;
+}
+
+/*
+ * Main connector device's callback.
+ *
+ * Used for notification of a request's processing.
+ */
+static void cn_callback(void *data)
+{
+ struct cn_msg *msg = data;
+ struct cn_ctl_msg *ctl;
+ struct cn_ctl_entry *ent;
+ u32 size;
+
+ if (msg->len < sizeof(*ctl))
+ return;
+
+ ctl = (struct cn_ctl_msg *)msg->data;
+
+ size = (sizeof(*ctl) + ((ctl->idx_notify_num +
+ ctl->val_notify_num) *
+ sizeof(struct cn_notify_req)));
+
+ if (msg->len != size)
+ return;
+
+ if (ctl->len + sizeof(*ctl) != msg->len)
+ return;
+
+ /*
+ * Remove notification.
+ */
+ if (ctl->group == 0) {
+ struct cn_ctl_entry *n;
+
+ down(&notify_lock);
+ list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
+ if (cn_ctl_msg_equals(ent->msg, ctl)) {
+ list_del(&ent->notify_entry);
+ kfree(ent);
+ }
+ }
+ up(&notify_lock);
+
+ return;
+ }
+
+ size += sizeof(*ent);
+
+ ent = kzalloc(size, GFP_KERNEL);
+ if (!ent)
+ return;
+
+ ent->msg = (struct cn_ctl_msg *)(ent + 1);
+
+ memcpy(ent->msg, ctl, size - sizeof(*ent));
+
+ down(&notify_lock);
+ list_add(&ent->notify_entry, &notify_list);
+ up(&notify_lock);
+}
+
+static int __init cn_init(void)
+{
+ struct cn_dev *dev = &cdev;
+ int err;
+
+ dev->input = cn_input;
+ dev->id.idx = cn_idx;
+ dev->id.val = cn_val;
+
+ dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
+ CN_NETLINK_USERS + 0xf,
+ dev->input, THIS_MODULE);
+ if (!dev->nls)
+ return -EIO;
+
+ dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
+ if (!dev->cbdev) {
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+ return -EINVAL;
+ }
+
+ err = cn_add_callback(&dev->id, "connector", &cn_callback);
+ if (err) {
+ cn_queue_free_dev(dev->cbdev);
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+ return -EINVAL;
+ }
+
+ cn_already_initialized = 1;
+
+ return 0;
+}
+
+static void __exit cn_fini(void)
+{
+ struct cn_dev *dev = &cdev;
+
+ cn_already_initialized = 0;
+
+ cn_del_callback(&dev->id);
+ cn_queue_free_dev(dev->cbdev);
+ if (dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+}
+
+module_init(cn_init);
+module_exit(cn_fini);
+
+EXPORT_SYMBOL_GPL(cn_add_callback);
+EXPORT_SYMBOL_GPL(cn_del_callback);
+EXPORT_SYMBOL_GPL(cn_netlink_send);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 10b014982381..6c6121b85a54 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -4,6 +4,9 @@
* Copyright (C) 2001 Russell King
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
+ * Oct 2005 - Ashok Raj <ashok.raj@intel.com>
+ * Added handling for CPU hotplug
+ *
* 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.
@@ -36,13 +39,6 @@ static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
static DEFINE_SPINLOCK(cpufreq_driver_lock);
-/* we keep a copy of all ->add'ed CPU's struct sys_device here;
- * as it is only accessed in ->add and ->remove, no lock or reference
- * count is necessary.
- */
-static struct sys_device *cpu_sys_devices[NR_CPUS];
-
-
/* internal prototypes */
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static void handle_update(void *data);
@@ -574,6 +570,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
unsigned long flags;
unsigned int j;
+ if (cpu_is_offline(cpu))
+ return 0;
+
cpufreq_debug_disable_ratelimit();
dprintk("adding CPU %u\n", cpu);
@@ -582,7 +581,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
* CPU because it is in the same boat. */
policy = cpufreq_cpu_get(cpu);
if (unlikely(policy)) {
- cpu_sys_devices[cpu] = sys_dev;
dprintk("CPU already managed, adding link\n");
sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq");
cpufreq_debug_enable_ratelimit();
@@ -627,7 +625,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
ret = kobject_register(&policy->kobj);
if (ret)
- goto err_out;
+ goto err_out_driver_exit;
/* set up files for this cpu device */
drv_attr = cpufreq_driver->attr;
@@ -657,7 +655,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
}
module_put(cpufreq_driver->owner);
- cpu_sys_devices[cpu] = sys_dev;
dprintk("initialization complete\n");
cpufreq_debug_enable_ratelimit();
@@ -673,12 +670,16 @@ err_out_unregister:
kobject_unregister(&policy->kobj);
wait_for_completion(&policy->kobj_unregister);
+err_out_driver_exit:
+ if (cpufreq_driver->exit)
+ cpufreq_driver->exit(policy);
+
err_out:
kfree(policy);
nomem_out:
module_put(cpufreq_driver->owner);
- module_out:
+module_out:
cpufreq_debug_enable_ratelimit();
return ret;
}
@@ -694,6 +695,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
unsigned int cpu = sys_dev->id;
unsigned long flags;
struct cpufreq_policy *data;
+ struct sys_device *cpu_sys_dev;
#ifdef CONFIG_SMP
unsigned int j;
#endif
@@ -706,7 +708,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
if (!data) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- cpu_sys_devices[cpu] = NULL;
cpufreq_debug_enable_ratelimit();
return -EINVAL;
}
@@ -721,14 +722,12 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
dprintk("removing link\n");
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
sysfs_remove_link(&sys_dev->kobj, "cpufreq");
- cpu_sys_devices[cpu] = NULL;
cpufreq_cpu_put(data);
cpufreq_debug_enable_ratelimit();
return 0;
}
#endif
- cpu_sys_devices[cpu] = NULL;
if (!kobject_get(&data->kobj)) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -757,7 +756,8 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);
- sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq");
+ cpu_sys_dev = get_cpu_sysdev(j);
+ sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data);
}
}
@@ -768,7 +768,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
down(&data->lock);
if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
- cpufreq_driver->target = NULL;
up(&data->lock);
kobject_unregister(&data->kobj);
@@ -1115,17 +1114,30 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int relation)
{
int retval = -EINVAL;
- lock_cpu_hotplug();
+
+ /*
+ * Converted the lock_cpu_hotplug to preempt_disable()
+ * and preempt_enable(). This is a bit kludgy and relies on how cpu
+ * hotplug works. All we need is a guarantee that cpu hotplug won't make
+ * progress on any cpu. Once we do preempt_disable(), this would ensure
+ * that hotplug threads don't get onto this cpu, thereby delaying
+ * the cpu remove process.
+ *
+ * We removed the lock_cpu_hotplug since we need to call this function
+ * via cpu hotplug callbacks, which result in locking the cpu hotplug
+ * thread itself. Agree this is not very clean, cpufreq community
+ * could improve this if required. - Ashok Raj <ashok.raj@intel.com>
+ */
+ preempt_disable();
dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
target_freq, relation);
if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
- unlock_cpu_hotplug();
+ preempt_enable();
return retval;
}
EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
-
int cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -1412,6 +1424,45 @@ int cpufreq_update_policy(unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_update_policy);
+static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ struct cpufreq_policy *policy;
+ struct sys_device *sys_dev;
+
+ sys_dev = get_cpu_sysdev(cpu);
+
+ if (sys_dev) {
+ switch (action) {
+ case CPU_ONLINE:
+ cpufreq_add_dev(sys_dev);
+ break;
+ case CPU_DOWN_PREPARE:
+ /*
+ * We attempt to put this cpu in lowest frequency
+ * possible before going down. This will permit
+ * hardware-managed P-State to switch other related
+ * threads to min or higher speeds if possible.
+ */
+ policy = cpufreq_cpu_data[cpu];
+ if (policy) {
+ cpufreq_driver_target(policy, policy->min,
+ CPUFREQ_RELATION_H);
+ }
+ break;
+ case CPU_DEAD:
+ cpufreq_remove_dev(sys_dev);
+ break;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_cpu_notifier =
+{
+ .notifier_call = cpufreq_cpu_callback,
+};
/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
@@ -1472,6 +1523,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
}
if (!ret) {
+ register_cpu_notifier(&cpufreq_cpu_notifier);
dprintk("driver %s up and running\n", driver_data->name);
cpufreq_debug_enable_ratelimit();
}
@@ -1503,6 +1555,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
dprintk("unregistering driver %s\n", driver->name);
sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
+ unregister_cpu_notifier(&cpufreq_cpu_notifier);
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index e1df376e709e..2ed5c4363b53 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -315,9 +315,9 @@ static void dbs_check_cpu(int cpu)
policy = this_dbs_info->cur_policy;
if ( init_flag == 0 ) {
- for ( /* NULL */; init_flag < NR_CPUS; init_flag++ ) {
- dbs_info = &per_cpu(cpu_dbs_info, init_flag);
- requested_freq[cpu] = dbs_info->cur_policy->cur;
+ for_each_online_cpu(j) {
+ dbs_info = &per_cpu(cpu_dbs_info, j);
+ requested_freq[j] = dbs_info->cur_policy->cur;
}
init_flag = 1;
}
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 741b6b191e6a..3597f25d5efa 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -19,6 +19,7 @@
#include <linux/percpu.h>
#include <linux/kobject.h>
#include <linux/spinlock.h>
+#include <linux/notifier.h>
#include <asm/cputime.h>
static spinlock_t cpufreq_stats_lock;
@@ -298,6 +299,27 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
return 0;
}
+static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ cpufreq_update_policy(cpu);
+ break;
+ case CPU_DEAD:
+ cpufreq_stats_free_table(cpu);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_stat_cpu_notifier =
+{
+ .notifier_call = cpufreq_stat_cpu_callback,
+};
+
static struct notifier_block notifier_policy_block = {
.notifier_call = cpufreq_stat_notifier_policy
};
@@ -311,6 +333,7 @@ __init cpufreq_stats_init(void)
{
int ret;
unsigned int cpu;
+
spin_lock_init(&cpufreq_stats_lock);
if ((ret = cpufreq_register_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER)))
@@ -323,20 +346,31 @@ __init cpufreq_stats_init(void)
return ret;
}
- for_each_cpu(cpu)
- cpufreq_update_policy(cpu);
+ register_cpu_notifier(&cpufreq_stat_cpu_notifier);
+ lock_cpu_hotplug();
+ for_each_online_cpu(cpu) {
+ cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
+ (void *)(long)cpu);
+ }
+ unlock_cpu_hotplug();
return 0;
}
static void
__exit cpufreq_stats_exit(void)
{
unsigned int cpu;
+
cpufreq_unregister_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
cpufreq_unregister_notifier(&notifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
- for_each_cpu(cpu)
- cpufreq_stats_free_table(cpu);
+ unregister_cpu_notifier(&cpufreq_stat_cpu_notifier);
+ lock_cpu_hotplug();
+ for_each_online_cpu(cpu) {
+ cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD,
+ (void *)(long)cpu);
+ }
+ unlock_cpu_hotplug();
}
MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 094835cce321..4263935443cc 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -2,7 +2,7 @@ menu "Hardware crypto devices"
config CRYPTO_DEV_PADLOCK
tristate "Support for VIA PadLock ACE"
- depends on CRYPTO && X86 && !X86_64
+ depends on CRYPTO && X86_32
help
Some VIA processors come with an integrated crypto engine
(so called VIA PadLock ACE, Advanced Cryptography Engine)
diff --git a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
index 15677f20bd85..0f97a0cb0ff4 100644
--- a/drivers/eisa/virtual_root.c
+++ b/drivers/eisa/virtual_root.c
@@ -9,7 +9,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/eisa.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 5d961f5e0ca0..e4710d1d1f9d 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1004,8 +1004,8 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
return FAILED;
}
fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
- return SUCCESS;
#endif
+ return SUCCESS;
}
static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 5b29c3b2a331..b6815c6c29a2 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -58,4 +58,30 @@ config EFI_PCDP
See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf>
+config DELL_RBU
+ tristate "BIOS update support for DELL systems via sysfs"
+ select FW_LOADER
+ help
+ Say m if you want to have the option of updating the BIOS for your
+ DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
+ supporting application to comunicate with the BIOS regarding the new
+ image for the image update to take effect.
+ See <file:Documentation/dell_rbu.txt> for more details on the driver.
+
+config DCDBAS
+ tristate "Dell Systems Management Base Driver"
+ depends on X86
+ help
+ The Dell Systems Management Base Driver provides a sysfs interface
+ for systems management software to perform System Management
+ Interrupts (SMIs) and Host Control Actions (system power cycle or
+ power off after OS shutdown) on certain Dell systems.
+
+ See <file:Documentation/dcdbas.txt> for more details on the driver
+ and the Dell systems on which Dell systems management software makes
+ use of this driver.
+
+ Say Y or M here to enable the driver for use by Dell systems
+ management software such as Dell OpenManage.
+
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 90fd0b26db8b..85429979d0db 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -4,3 +4,5 @@
obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
+obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+obj-$(CONFIG_DCDBAS) += dcdbas.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
new file mode 100644
index 000000000000..8ed6ddbb9c5d
--- /dev/null
+++ b/drivers/firmware/dcdbas.c
@@ -0,0 +1,596 @@
+/*
+ * dcdbas.c: Dell Systems Management Base Driver
+ *
+ * The Dell Systems Management Base Driver provides a sysfs interface for
+ * systems management software to perform System Management Interrupts (SMIs)
+ * and Host Control Actions (power cycle or power off after OS shutdown) on
+ * Dell systems.
+ *
+ * See Documentation/dcdbas.txt for more information.
+ *
+ * Copyright (C) 1995-2005 Dell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 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/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#include "dcdbas.h"
+
+#define DRIVER_NAME "dcdbas"
+#define DRIVER_VERSION "5.6.0-1"
+#define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
+
+static struct platform_device *dcdbas_pdev;
+
+static u8 *smi_data_buf;
+static dma_addr_t smi_data_buf_handle;
+static unsigned long smi_data_buf_size;
+static u32 smi_data_buf_phys_addr;
+static DECLARE_MUTEX(smi_data_lock);
+
+static unsigned int host_control_action;
+static unsigned int host_control_smi_type;
+static unsigned int host_control_on_shutdown;
+
+/**
+ * smi_data_buf_free: free SMI data buffer
+ */
+static void smi_data_buf_free(void)
+{
+ if (!smi_data_buf)
+ return;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+ __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+ smi_data_buf_handle);
+ smi_data_buf = NULL;
+ smi_data_buf_handle = 0;
+ smi_data_buf_phys_addr = 0;
+ smi_data_buf_size = 0;
+}
+
+/**
+ * smi_data_buf_realloc: grow SMI data buffer if needed
+ */
+static int smi_data_buf_realloc(unsigned long size)
+{
+ void *buf;
+ dma_addr_t handle;
+
+ if (smi_data_buf_size >= size)
+ return 0;
+
+ if (size > MAX_SMI_DATA_BUF_SIZE)
+ return -EINVAL;
+
+ /* new buffer is needed */
+ buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
+ if (!buf) {
+ dev_dbg(&dcdbas_pdev->dev,
+ "%s: failed to allocate memory size %lu\n",
+ __FUNCTION__, size);
+ return -ENOMEM;
+ }
+ /* memory zeroed by dma_alloc_coherent */
+
+ if (smi_data_buf)
+ memcpy(buf, smi_data_buf, smi_data_buf_size);
+
+ /* free any existing buffer */
+ smi_data_buf_free();
+
+ /* set up new buffer for use */
+ smi_data_buf = buf;
+ smi_data_buf_handle = handle;
+ smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
+ smi_data_buf_size = size;
+
+ dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+ __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+ return 0;
+}
+
+static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
+}
+
+static ssize_t smi_data_buf_size_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%lu\n", smi_data_buf_size);
+}
+
+static ssize_t smi_data_buf_size_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long buf_size;
+ ssize_t ret;
+
+ buf_size = simple_strtoul(buf, NULL, 10);
+
+ /* make sure SMI data buffer is at least buf_size */
+ down(&smi_data_lock);
+ ret = smi_data_buf_realloc(buf_size);
+ up(&smi_data_lock);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
+ size_t count)
+{
+ size_t max_read;
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ if (pos >= smi_data_buf_size) {
+ ret = 0;
+ goto out;
+ }
+
+ max_read = smi_data_buf_size - pos;
+ ret = min(max_read, count);
+ memcpy(buf, smi_data_buf + pos, ret);
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
+ size_t count)
+{
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ ret = smi_data_buf_realloc(pos + count);
+ if (ret)
+ goto out;
+
+ memcpy(smi_data_buf + pos, buf, count);
+ ret = count;
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+static ssize_t host_control_action_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_action);
+}
+
+static ssize_t host_control_action_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+
+ /* make sure buffer is available for host control command */
+ down(&smi_data_lock);
+ ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
+ up(&smi_data_lock);
+ if (ret)
+ return ret;
+
+ host_control_action = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+static ssize_t host_control_smi_type_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_smi_type);
+}
+
+static ssize_t host_control_smi_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ host_control_smi_type = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+static ssize_t host_control_on_shutdown_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", host_control_on_shutdown);
+}
+
+static ssize_t host_control_on_shutdown_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+/**
+ * smi_request: generate SMI request
+ *
+ * Called with smi_data_lock.
+ */
+static int smi_request(struct smi_cmd *smi_cmd)
+{
+ cpumask_t old_mask;
+ int ret = 0;
+
+ if (smi_cmd->magic != SMI_CMD_MAGIC) {
+ dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+ __FUNCTION__);
+ return -EBADR;
+ }
+
+ /* SMI requires CPU 0 */
+ old_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(0));
+ if (smp_processor_id() != 0) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+ __FUNCTION__);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* generate SMI */
+ asm volatile (
+ "outb %b0,%w1"
+ : /* no output args */
+ : "a" (smi_cmd->command_code),
+ "d" (smi_cmd->command_address),
+ "b" (smi_cmd->ebx),
+ "c" (smi_cmd->ecx)
+ : "memory"
+ );
+
+out:
+ set_cpus_allowed(current, old_mask);
+ return ret;
+}
+
+/**
+ * smi_request_store:
+ *
+ * The valid values are:
+ * 0: zero SMI data buffer
+ * 1: generate calling interface SMI
+ * 2: generate raw SMI
+ *
+ * User application writes smi_cmd to smi_data before telling driver
+ * to generate SMI.
+ */
+static ssize_t smi_request_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct smi_cmd *smi_cmd;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ ssize_t ret;
+
+ down(&smi_data_lock);
+
+ if (smi_data_buf_size < sizeof(struct smi_cmd)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ smi_cmd = (struct smi_cmd *)smi_data_buf;
+
+ switch (val) {
+ case 2:
+ /* Raw SMI */
+ ret = smi_request(smi_cmd);
+ if (!ret)
+ ret = count;
+ break;
+ case 1:
+ /* Calling Interface SMI */
+ smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
+ ret = smi_request(smi_cmd);
+ if (!ret)
+ ret = count;
+ break;
+ case 0:
+ memset(smi_data_buf, 0, smi_data_buf_size);
+ ret = count;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+out:
+ up(&smi_data_lock);
+ return ret;
+}
+
+/**
+ * host_control_smi: generate host control SMI
+ *
+ * Caller must set up the host control command in smi_data_buf.
+ */
+static int host_control_smi(void)
+{
+ struct apm_cmd *apm_cmd;
+ u8 *data;
+ unsigned long flags;
+ u32 num_ticks;
+ s8 cmd_status;
+ u8 index;
+
+ apm_cmd = (struct apm_cmd *)smi_data_buf;
+ apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
+
+ switch (host_control_smi_type) {
+ case HC_SMITYPE_TYPE1:
+ spin_lock_irqsave(&rtc_lock, flags);
+ /* write SMI data buffer physical address */
+ data = (u8 *)&smi_data_buf_phys_addr;
+ for (index = PE1300_CMOS_CMD_STRUCT_PTR;
+ index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
+ index++, data++) {
+ outb(index,
+ (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
+ outb(*data,
+ (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
+ }
+
+ /* first set status to -1 as called by spec */
+ cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
+ outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
+
+ /* generate SMM call */
+ outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ /* wait a few to see if it executed */
+ num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+ while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
+ == ESM_STATUS_CMD_UNSUCCESSFUL) {
+ num_ticks--;
+ if (num_ticks == EXPIRED_TIMER)
+ return -ETIME;
+ }
+ break;
+
+ case HC_SMITYPE_TYPE2:
+ case HC_SMITYPE_TYPE3:
+ spin_lock_irqsave(&rtc_lock, flags);
+ /* write SMI data buffer physical address */
+ data = (u8 *)&smi_data_buf_phys_addr;
+ for (index = PE1400_CMOS_CMD_STRUCT_PTR;
+ index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
+ index++, data++) {
+ outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
+ outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
+ }
+
+ /* generate SMM call */
+ if (host_control_smi_type == HC_SMITYPE_TYPE3)
+ outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+ else
+ outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
+
+ /* restore RTC index pointer since it was written to above */
+ CMOS_READ(RTC_REG_C);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ /* read control port back to serialize write */
+ cmd_status = inb(PE1400_APM_CONTROL_PORT);
+
+ /* wait a few to see if it executed */
+ num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+ while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
+ num_ticks--;
+ if (num_ticks == EXPIRED_TIMER)
+ return -ETIME;
+ }
+ break;
+
+ default:
+ dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+ __FUNCTION__, host_control_smi_type);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+/**
+ * dcdbas_host_control: initiate host control
+ *
+ * This function is called by the driver after the system has
+ * finished shutting down if the user application specified a
+ * host control action to perform on shutdown. It is safe to
+ * use smi_data_buf at this point because the system has finished
+ * shutting down and no userspace apps are running.
+ */
+static void dcdbas_host_control(void)
+{
+ struct apm_cmd *apm_cmd;
+ u8 action;
+
+ if (host_control_action == HC_ACTION_NONE)
+ return;
+
+ action = host_control_action;
+ host_control_action = HC_ACTION_NONE;
+
+ if (!smi_data_buf) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__);
+ return;
+ }
+
+ if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+ __FUNCTION__);
+ return;
+ }
+
+ apm_cmd = (struct apm_cmd *)smi_data_buf;
+
+ /* power off takes precedence */
+ if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
+ apm_cmd->command = ESM_APM_POWER_CYCLE;
+ apm_cmd->reserved = 0;
+ *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
+ host_control_smi();
+ } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
+ apm_cmd->command = ESM_APM_POWER_CYCLE;
+ apm_cmd->reserved = 0;
+ *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
+ host_control_smi();
+ }
+}
+
+/**
+ * dcdbas_reboot_notify: handle reboot notification for host control
+ */
+static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+ void *unused)
+{
+ static unsigned int notify_cnt = 0;
+
+ switch (code) {
+ case SYS_DOWN:
+ case SYS_HALT:
+ case SYS_POWER_OFF:
+ if (host_control_on_shutdown) {
+ /* firmware is going to perform host control action */
+ if (++notify_cnt == 2) {
+ printk(KERN_WARNING
+ "Please wait for shutdown "
+ "action to complete...\n");
+ dcdbas_host_control();
+ }
+ /*
+ * register again and initiate the host control
+ * action on the second notification to allow
+ * everyone that registered to be notified
+ */
+ register_reboot_notifier(nb);
+ }
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block dcdbas_reboot_nb = {
+ .notifier_call = dcdbas_reboot_notify,
+ .next = NULL,
+ .priority = 0
+};
+
+static DCDBAS_BIN_ATTR_RW(smi_data);
+
+static struct bin_attribute *dcdbas_bin_attrs[] = {
+ &bin_attr_smi_data,
+ NULL
+};
+
+static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
+static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
+static DCDBAS_DEV_ATTR_WO(smi_request);
+static DCDBAS_DEV_ATTR_RW(host_control_action);
+static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
+static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
+
+static struct device_attribute *dcdbas_dev_attrs[] = {
+ &dev_attr_smi_data_buf_size,
+ &dev_attr_smi_data_buf_phys_addr,
+ &dev_attr_smi_request,
+ &dev_attr_host_control_action,
+ &dev_attr_host_control_smi_type,
+ &dev_attr_host_control_on_shutdown,
+ NULL
+};
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+ int i;
+
+ host_control_action = HC_ACTION_NONE;
+ host_control_smi_type = HC_SMITYPE_NONE;
+
+ dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (IS_ERR(dcdbas_pdev))
+ return PTR_ERR(dcdbas_pdev);
+
+ /*
+ * BIOS SMI calls require buffer addresses be in 32-bit address space.
+ * This is done by setting the DMA mask below.
+ */
+ dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
+ dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
+
+ register_reboot_notifier(&dcdbas_reboot_nb);
+
+ for (i = 0; dcdbas_bin_attrs[i]; i++)
+ sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
+ dcdbas_bin_attrs[i]);
+
+ for (i = 0; dcdbas_dev_attrs[i]; i++)
+ device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
+
+ dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
+ DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+ return 0;
+}
+
+/**
+ * dcdbas_exit: perform driver cleanup
+ */
+static void __exit dcdbas_exit(void)
+{
+ platform_device_unregister(dcdbas_pdev);
+ unregister_reboot_notifier(&dcdbas_reboot_nb);
+ smi_data_buf_free();
+}
+
+module_init(dcdbas_init);
+module_exit(dcdbas_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Dell Inc.");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
new file mode 100644
index 000000000000..58a85182b3e8
--- /dev/null
+++ b/drivers/firmware/dcdbas.h
@@ -0,0 +1,107 @@
+/*
+ * dcdbas.h: Definitions for Dell Systems Management Base driver
+ *
+ * Copyright (C) 1995-2005 Dell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 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.
+ */
+
+#ifndef _DCDBAS_H_
+#define _DCDBAS_H_
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define MAX_SMI_DATA_BUF_SIZE (256 * 1024)
+
+#define HC_ACTION_NONE (0)
+#define HC_ACTION_HOST_CONTROL_POWEROFF BIT(1)
+#define HC_ACTION_HOST_CONTROL_POWERCYCLE BIT(2)
+
+#define HC_SMITYPE_NONE (0)
+#define HC_SMITYPE_TYPE1 (1)
+#define HC_SMITYPE_TYPE2 (2)
+#define HC_SMITYPE_TYPE3 (3)
+
+#define ESM_APM_CMD (0x0A0)
+#define ESM_APM_POWER_CYCLE (0x10)
+#define ESM_STATUS_CMD_UNSUCCESSFUL (-1)
+
+#define CMOS_BASE_PORT (0x070)
+#define CMOS_PAGE1_INDEX_PORT (0)
+#define CMOS_PAGE1_DATA_PORT (1)
+#define CMOS_PAGE2_INDEX_PORT_PIIX4 (2)
+#define CMOS_PAGE2_DATA_PORT_PIIX4 (3)
+#define PE1400_APM_CONTROL_PORT (0x0B0)
+#define PCAT_APM_CONTROL_PORT (0x0B2)
+#define PCAT_APM_STATUS_PORT (0x0B3)
+#define PE1300_CMOS_CMD_STRUCT_PTR (0x38)
+#define PE1400_CMOS_CMD_STRUCT_PTR (0x70)
+
+#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN (14)
+#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM (16)
+
+#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING (10000)
+#define EXPIRED_TIMER (0)
+
+#define SMI_CMD_MAGIC (0x534D4931)
+
+#define DCDBAS_DEV_ATTR_RW(_name) \
+ DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
+
+#define DCDBAS_DEV_ATTR_RO(_name) \
+ DEVICE_ATTR(_name,0400,_name##_show,NULL);
+
+#define DCDBAS_DEV_ATTR_WO(_name) \
+ DEVICE_ATTR(_name,0200,NULL,_name##_store);
+
+#define DCDBAS_BIN_ATTR_RW(_name) \
+struct bin_attribute bin_attr_##_name = { \
+ .attr = { .name = __stringify(_name), \
+ .mode = 0600, \
+ .owner = THIS_MODULE }, \
+ .read = _name##_read, \
+ .write = _name##_write, \
+}
+
+struct smi_cmd {
+ __u32 magic;
+ __u32 ebx;
+ __u32 ecx;
+ __u16 command_address;
+ __u8 command_code;
+ __u8 reserved;
+ __u8 command_buffer[1];
+} __attribute__ ((packed));
+
+struct apm_cmd {
+ __u8 command;
+ __s8 status;
+ __u16 reserved;
+ union {
+ struct {
+ __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
+ } __attribute__ ((packed)) shortreq;
+
+ struct {
+ __u16 num_sg_entries;
+ struct {
+ __u32 size;
+ __u64 addr;
+ } __attribute__ ((packed))
+ sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
+ } __attribute__ ((packed)) longreq;
+ } __attribute__ ((packed)) parameters;
+} __attribute__ ((packed));
+
+#endif /* _DCDBAS_H_ */
+
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
new file mode 100644
index 000000000000..125929c9048f
--- /dev/null
+++ b/drivers/firmware/dell_rbu.c
@@ -0,0 +1,695 @@
+/*
+ * dell_rbu.c
+ * Bios Update driver for Dell systems
+ * Author: Dell Inc
+ * Abhay Salunke <abhay_salunke@dell.com>
+ *
+ * Copyright (C) 2005 Dell Inc.
+ *
+ * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
+ * creating entries in the /sys file systems on Linux 2.6 and higher
+ * kernels. The driver supports two mechanism to update the BIOS namely
+ * contiguous and packetized. Both these methods still require having some
+ * application to set the CMOS bit indicating the BIOS to update itself
+ * after a reboot.
+ *
+ * Contiguous method:
+ * This driver writes the incoming data in a monolithic image by allocating
+ * contiguous physical pages large enough to accommodate the incoming BIOS
+ * image size.
+ *
+ * Packetized method:
+ * The driver writes the incoming packet image by allocating a new packet
+ * on every time the packet data is written. This driver requires an
+ * application to break the BIOS image in to fixed sized packet chunks.
+ *
+ * See Documentation/dell_rbu.txt for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 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/version.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+
+MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
+MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("3.0");
+
+#define BIOS_SCAN_LIMIT 0xffffffff
+#define MAX_IMAGE_LENGTH 16
+static struct _rbu_data {
+ void *image_update_buffer;
+ unsigned long image_update_buffer_size;
+ unsigned long bios_image_size;
+ int image_update_ordernum;
+ int dma_alloc;
+ spinlock_t lock;
+ unsigned long packet_read_count;
+ unsigned long num_packets;
+ unsigned long packetsize;
+ unsigned long imagesize;
+ int entry_created;
+} rbu_data;
+
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
+MODULE_PARM_DESC(image_type,
+ "BIOS image type. choose- mono or packet or init");
+
+struct packet_data {
+ struct list_head list;
+ size_t length;
+ void *data;
+ int ordernum;
+};
+
+static struct packet_data packet_data_head;
+
+static struct platform_device *rbu_device;
+static int context;
+static dma_addr_t dell_rbu_dmaaddr;
+
+static void init_packet_head(void)
+{
+ INIT_LIST_HEAD(&packet_data_head.list);
+ rbu_data.packet_read_count = 0;
+ rbu_data.num_packets = 0;
+ rbu_data.packetsize = 0;
+ rbu_data.imagesize = 0;
+}
+
+static int create_packet(void *data, size_t length)
+{
+ struct packet_data *newpacket;
+ int ordernum = 0;
+
+ pr_debug("create_packet: entry \n");
+
+ if (!rbu_data.packetsize) {
+ pr_debug("create_packet: packetsize not specified\n");
+ return -EINVAL;
+ }
+ spin_unlock(&rbu_data.lock);
+ newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
+ spin_lock(&rbu_data.lock);
+
+ if (!newpacket) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ ordernum = get_order(length);
+ /*
+ * there is no upper limit on memory
+ * address for packetized mechanism
+ */
+ spin_unlock(&rbu_data.lock);
+ newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
+ ordernum);
+ spin_lock(&rbu_data.lock);
+
+ pr_debug("create_packet: newpacket %p\n", newpacket->data);
+
+ if (!newpacket->data) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
+ kfree(newpacket);
+ return -ENOMEM;
+ }
+
+ newpacket->ordernum = ordernum;
+ ++rbu_data.num_packets;
+ /*
+ * initialize the newly created packet headers
+ */
+ INIT_LIST_HEAD(&newpacket->list);
+ list_add_tail(&newpacket->list, &packet_data_head.list);
+ /*
+ * packets may not have fixed size
+ */
+ newpacket->length = length;
+
+ memcpy(newpacket->data, data, length);
+
+ pr_debug("create_packet: exit \n");
+
+ return 0;
+}
+
+static int packetize_data(void *data, size_t length)
+{
+ int rc = 0;
+ int done = 0;
+ int packet_length;
+ u8 *temp;
+ u8 *end = (u8 *) data + length;
+ pr_debug("packetize_data: data length %d\n", length);
+ if (!rbu_data.packetsize) {
+ printk(KERN_WARNING
+ "dell_rbu: packetsize not specified\n");
+ return -EIO;
+ }
+
+ temp = (u8 *) data;
+
+ /* packetize the hunk */
+ while (!done) {
+ if ((temp + rbu_data.packetsize) < end)
+ packet_length = rbu_data.packetsize;
+ else {
+ /* this is the last packet */
+ packet_length = end - temp;
+ done = 1;
+ }
+
+ if ((rc = create_packet(temp, packet_length)))
+ return rc;
+
+ pr_debug("%lu:%lu\n", temp, (end - temp));
+ temp += packet_length;
+ }
+
+ rbu_data.imagesize = length;
+
+ return rc;
+}
+
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+ int length, int bytes_read, int *list_read_count)
+{
+ void *ptemp_buf;
+ struct packet_data *newpacket = NULL;
+ int bytes_copied = 0;
+ int j = 0;
+
+ newpacket = list_entry(ptemp_list, struct packet_data, list);
+ *list_read_count += newpacket->length;
+
+ if (*list_read_count > bytes_read) {
+ /* point to the start of unread data */
+ j = newpacket->length - (*list_read_count - bytes_read);
+ /* point to the offset in the packet buffer */
+ ptemp_buf = (u8 *) newpacket->data + j;
+ /*
+ * check if there is enough room in
+ * * the incoming buffer
+ */
+ if (length > (*list_read_count - bytes_read))
+ /*
+ * copy what ever is there in this
+ * packet and move on
+ */
+ bytes_copied = (*list_read_count - bytes_read);
+ else
+ /* copy the remaining */
+ bytes_copied = length;
+ memcpy(data, ptemp_buf, bytes_copied);
+ }
+ return bytes_copied;
+}
+
+static int packet_read_list(char *data, size_t * pread_length)
+{
+ struct list_head *ptemp_list;
+ int temp_count = 0;
+ int bytes_copied = 0;
+ int bytes_read = 0;
+ int remaining_bytes = 0;
+ char *pdest = data;
+
+ /* check if we have any packets */
+ if (0 == rbu_data.num_packets)
+ return -ENOMEM;
+
+ remaining_bytes = *pread_length;
+ bytes_read = rbu_data.packet_read_count;
+
+ ptemp_list = (&packet_data_head.list)->next;
+ while (!list_empty(ptemp_list)) {
+ bytes_copied = do_packet_read(pdest, ptemp_list,
+ remaining_bytes, bytes_read, &temp_count);
+ remaining_bytes -= bytes_copied;
+ bytes_read += bytes_copied;
+ pdest += bytes_copied;
+ /*
+ * check if we reached end of buffer before reaching the
+ * last packet
+ */
+ if (remaining_bytes == 0)
+ break;
+
+ ptemp_list = ptemp_list->next;
+ }
+ /*finally set the bytes read */
+ *pread_length = bytes_read - rbu_data.packet_read_count;
+ rbu_data.packet_read_count = bytes_read;
+ return 0;
+}
+
+static void packet_empty_list(void)
+{
+ struct list_head *ptemp_list;
+ struct list_head *pnext_list;
+ struct packet_data *newpacket;
+
+ ptemp_list = (&packet_data_head.list)->next;
+ while (!list_empty(ptemp_list)) {
+ newpacket =
+ list_entry(ptemp_list, struct packet_data, list);
+ pnext_list = ptemp_list->next;
+ list_del(ptemp_list);
+ ptemp_list = pnext_list;
+ /*
+ * zero out the RBU packet memory before freeing
+ * to make sure there are no stale RBU packets left in memory
+ */
+ memset(newpacket->data, 0, rbu_data.packetsize);
+ free_pages((unsigned long) newpacket->data,
+ newpacket->ordernum);
+ kfree(newpacket);
+ }
+ rbu_data.packet_read_count = 0;
+ rbu_data.num_packets = 0;
+ rbu_data.imagesize = 0;
+}
+
+/*
+ * img_update_free: Frees the buffer allocated for storing BIOS image
+ * Always called with lock held and returned with lock held
+ */
+static void img_update_free(void)
+{
+ if (!rbu_data.image_update_buffer)
+ return;
+ /*
+ * zero out this buffer before freeing it to get rid of any stale
+ * BIOS image copied in memory.
+ */
+ memset(rbu_data.image_update_buffer, 0,
+ rbu_data.image_update_buffer_size);
+ if (rbu_data.dma_alloc == 1)
+ dma_free_coherent(NULL, rbu_data.bios_image_size,
+ rbu_data.image_update_buffer, dell_rbu_dmaaddr);
+ else
+ free_pages((unsigned long) rbu_data.image_update_buffer,
+ rbu_data.image_update_ordernum);
+
+ /*
+ * Re-initialize the rbu_data variables after a free
+ */
+ rbu_data.image_update_ordernum = -1;
+ rbu_data.image_update_buffer = NULL;
+ rbu_data.image_update_buffer_size = 0;
+ rbu_data.bios_image_size = 0;
+ rbu_data.dma_alloc = 0;
+}
+
+/*
+ * img_update_realloc: This function allocates the contiguous pages to
+ * accommodate the requested size of data. The memory address and size
+ * values are stored globally and on every call to this function the new
+ * size is checked to see if more data is required than the existing size.
+ * If true the previous memory is freed and new allocation is done to
+ * accommodate the new size. If the incoming size is less then than the
+ * already allocated size, then that memory is reused. This function is
+ * called with lock held and returns with lock held.
+ */
+static int img_update_realloc(unsigned long size)
+{
+ unsigned char *image_update_buffer = NULL;
+ unsigned long rc;
+ unsigned long img_buf_phys_addr;
+ int ordernum;
+ int dma_alloc = 0;
+
+ /*
+ * check if the buffer of sufficient size has been
+ * already allocated
+ */
+ if (rbu_data.image_update_buffer_size >= size) {
+ /*
+ * check for corruption
+ */
+ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+ printk(KERN_ERR "dell_rbu:%s: corruption "
+ "check failed\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ /*
+ * we have a valid pre-allocated buffer with
+ * sufficient size
+ */
+ return 0;
+ }
+
+ /*
+ * free any previously allocated buffer
+ */
+ img_update_free();
+
+ spin_unlock(&rbu_data.lock);
+
+ ordernum = get_order(size);
+ image_update_buffer =
+ (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
+
+ img_buf_phys_addr =
+ (unsigned long) virt_to_phys(image_update_buffer);
+
+ if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+ free_pages((unsigned long) image_update_buffer, ordernum);
+ ordernum = -1;
+ image_update_buffer = dma_alloc_coherent(NULL, size,
+ &dell_rbu_dmaaddr, GFP_KERNEL);
+ dma_alloc = 1;
+ }
+
+ spin_lock(&rbu_data.lock);
+
+ if (image_update_buffer != NULL) {
+ rbu_data.image_update_buffer = image_update_buffer;
+ rbu_data.image_update_buffer_size = size;
+ rbu_data.bios_image_size =
+ rbu_data.image_update_buffer_size;
+ rbu_data.image_update_ordernum = ordernum;
+ rbu_data.dma_alloc = dma_alloc;
+ rc = 0;
+ } else {
+ pr_debug("Not enough memory for image update:"
+ "size = %ld\n", size);
+ rc = -ENOMEM;
+ }
+
+ return rc;
+}
+
+static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
+{
+ int retval;
+ size_t bytes_left;
+ size_t data_length;
+ char *ptempBuf = buffer;
+
+ /* check to see if we have something to return */
+ if (rbu_data.num_packets == 0) {
+ pr_debug("read_packet_data: no packets written\n");
+ retval = -ENOMEM;
+ goto read_rbu_data_exit;
+ }
+
+ if (pos > rbu_data.imagesize) {
+ retval = 0;
+ printk(KERN_WARNING "dell_rbu:read_packet_data: "
+ "data underrun\n");
+ goto read_rbu_data_exit;
+ }
+
+ bytes_left = rbu_data.imagesize - pos;
+ data_length = min(bytes_left, count);
+
+ if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
+ goto read_rbu_data_exit;
+
+ if ((pos + count) > rbu_data.imagesize) {
+ rbu_data.packet_read_count = 0;
+ /* this was the last copy */
+ retval = bytes_left;
+ } else
+ retval = count;
+
+ read_rbu_data_exit:
+ return retval;
+}
+
+static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
+{
+ unsigned char *ptemp = NULL;
+ size_t bytes_left = 0;
+ size_t data_length = 0;
+ ssize_t ret_count = 0;
+
+ /* check to see if we have something to return */
+ if ((rbu_data.image_update_buffer == NULL) ||
+ (rbu_data.bios_image_size == 0)) {
+ pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
+ "bios_image_size %lu\n",
+ rbu_data.image_update_buffer,
+ rbu_data.bios_image_size);
+ ret_count = -ENOMEM;
+ goto read_rbu_data_exit;
+ }
+
+ if (pos > rbu_data.bios_image_size) {
+ ret_count = 0;
+ goto read_rbu_data_exit;
+ }
+
+ bytes_left = rbu_data.bios_image_size - pos;
+ data_length = min(bytes_left, count);
+
+ ptemp = rbu_data.image_update_buffer;
+ memcpy(buffer, (ptemp + pos), data_length);
+
+ if ((pos + count) > rbu_data.bios_image_size)
+ /* this was the last copy */
+ ret_count = bytes_left;
+ else
+ ret_count = count;
+ read_rbu_data_exit:
+ return ret_count;
+}
+
+static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ ssize_t ret_count = 0;
+
+ spin_lock(&rbu_data.lock);
+
+ if (!strcmp(image_type, "mono"))
+ ret_count = read_rbu_mono_data(buffer, pos, count);
+ else if (!strcmp(image_type, "packet"))
+ ret_count = read_packet_data(buffer, pos, count);
+ else
+ pr_debug("read_rbu_data: invalid image type specified\n");
+
+ spin_unlock(&rbu_data.lock);
+ return ret_count;
+}
+
+static void callbackfn_rbu(const struct firmware *fw, void *context)
+{
+ int rc = 0;
+
+ if (!fw || !fw->size) {
+ rbu_data.entry_created = 0;
+ return;
+ }
+
+ spin_lock(&rbu_data.lock);
+ if (!strcmp(image_type, "mono")) {
+ if (!img_update_realloc(fw->size))
+ memcpy(rbu_data.image_update_buffer,
+ fw->data, fw->size);
+ } else if (!strcmp(image_type, "packet")) {
+ /*
+ * we need to free previous packets if a
+ * new hunk of packets needs to be downloaded
+ */
+ packet_empty_list();
+ if (packetize_data(fw->data, fw->size))
+ /* Incase something goes wrong when we are
+ * in middle of packetizing the data, we
+ * need to free up whatever packets might
+ * have been created before we quit.
+ */
+ packet_empty_list();
+ } else
+ pr_debug("invalid image type specified.\n");
+ spin_unlock(&rbu_data.lock);
+
+ rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
+ if (rc)
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait failed"
+ " %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
+}
+
+static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int size = 0;
+ if (!pos)
+ size = sprintf(buffer, "%s\n", image_type);
+ return size;
+}
+
+static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int rc = count;
+ int req_firm_rc = 0;
+ int i;
+ spin_lock(&rbu_data.lock);
+ /*
+ * Find the first newline or space
+ */
+ for (i = 0; i < count; ++i)
+ if (buffer[i] == '\n' || buffer[i] == ' ') {
+ buffer[i] = '\0';
+ break;
+ }
+ if (i == count)
+ buffer[count] = '\0';
+
+ if (strstr(buffer, "mono"))
+ strcpy(image_type, "mono");
+ else if (strstr(buffer, "packet"))
+ strcpy(image_type, "packet");
+ else if (strstr(buffer, "init")) {
+ /*
+ * If due to the user error the driver gets in a bad
+ * state where even though it is loaded , the
+ * /sys/class/firmware/dell_rbu entries are missing.
+ * to cover this situation the user can recreate entries
+ * by writing init to image_type.
+ */
+ if (!rbu_data.entry_created) {
+ spin_unlock(&rbu_data.lock);
+ req_firm_rc = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_NOHOTPLUG, "dell_rbu",
+ &rbu_device->dev, &context,
+ callbackfn_rbu);
+ if (req_firm_rc) {
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait"
+ " failed %d\n", __FUNCTION__, rc);
+ rc = -EIO;
+ } else
+ rbu_data.entry_created = 1;
+
+ spin_lock(&rbu_data.lock);
+ }
+ } else {
+ printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+ spin_unlock(&rbu_data.lock);
+ return -EINVAL;
+ }
+
+ /* we must free all previous allocations */
+ packet_empty_list();
+ img_update_free();
+ spin_unlock(&rbu_data.lock);
+
+ return rc;
+}
+
+static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int size = 0;
+ if (!pos) {
+ spin_lock(&rbu_data.lock);
+ size = sprintf(buffer, "%lu\n", rbu_data.packetsize);
+ spin_unlock(&rbu_data.lock);
+ }
+ return size;
+}
+
+static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ unsigned long temp;
+ spin_lock(&rbu_data.lock);
+ packet_empty_list();
+ sscanf(buffer, "%lu", &temp);
+ if (temp < 0xffffffff)
+ rbu_data.packetsize = temp;
+
+ spin_unlock(&rbu_data.lock);
+ return count;
+}
+
+static struct bin_attribute rbu_data_attr = {
+ .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+ .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+ .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+ .read = read_rbu_image_type,
+ .write = write_rbu_image_type,
+};
+
+static struct bin_attribute rbu_packet_size_attr = {
+ .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+ .read = read_rbu_packet_size,
+ .write = write_rbu_packet_size,
+};
+
+static int __init dcdrbu_init(void)
+{
+ int rc = 0;
+ spin_lock_init(&rbu_data.lock);
+
+ init_packet_head();
+ rbu_device =
+ platform_device_register_simple("dell_rbu", -1, NULL, 0);
+ if (!rbu_device) {
+ printk(KERN_ERR
+ "dell_rbu:%s:platform_device_register_simple "
+ "failed\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+ sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+ sysfs_create_bin_file(&rbu_device->dev.kobj,
+ &rbu_packet_size_attr);
+
+ rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
+ if (rc)
+ printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
+ " failed %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
+
+ return rc;
+
+}
+
+static __exit void dcdrbu_exit(void)
+{
+ spin_lock(&rbu_data.lock);
+ packet_empty_list();
+ img_update_free();
+ spin_unlock(&rbu_data.lock);
+ platform_device_unregister(rbu_device);
+}
+
+module_exit(dcdrbu_exit);
+module_init(dcdrbu_init);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 140d5f851a5b..db358cfa7cbf 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -12,12 +12,20 @@ config HWMON
of a system. Most modern motherboards include such a device. It
can include temperature sensors, voltage sensors, fan speed
sensors and various additional features such as the ability to
- control the speed of the fans.
+ control the speed of the fans. If you want this support you
+ should say Y here and also to the specific driver(s) for your
+ sensors chip(s) below.
+
+ This support can also be built as a module. If so, the module
+ will be called hwmon.
+
+config HWMON_VID
+ tristate
+ default n
config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -30,7 +38,7 @@ config SENSORS_ADM1021
config SENSORS_ADM1025
tristate "Analog Devices ADM1025 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM1025
and Philips NE1619 sensor chips.
@@ -41,7 +49,7 @@ config SENSORS_ADM1025
config SENSORS_ADM1026
tristate "Analog Devices ADM1026 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM1026
sensor chip.
@@ -52,7 +60,6 @@ config SENSORS_ADM1026
config SENSORS_ADM1031
tristate "Analog Devices ADM1031 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1031
and ADM1030 sensor chips.
@@ -63,7 +70,7 @@ config SENSORS_ADM1031
config SENSORS_ADM9240
tristate "Analog Devices ADM9240 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Analog Devices ADM9240,
Dallas DS1780, National Semiconductor LM81 sensor chips.
@@ -74,7 +81,7 @@ config SENSORS_ADM9240
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for the ASB100 Bach sensor
chip found on some Asus mainboards.
@@ -85,7 +92,7 @@ config SENSORS_ASB100
config SENSORS_ATXP1
tristate "Attansic ATXP1 VID controller"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for the Attansic ATXP1 VID
controller.
@@ -99,7 +106,6 @@ config SENSORS_ATXP1
config SENSORS_DS1621
tristate "Dallas Semiconductor DS1621 and DS1625"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1621 and DS1625 sensor chips.
@@ -110,7 +116,6 @@ config SENSORS_DS1621
config SENSORS_FSCHER
tristate "FSC Hermes"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Fujitsu Siemens
Computers Hermes sensor chips.
@@ -121,7 +126,6 @@ config SENSORS_FSCHER
config SENSORS_FSCPOS
tristate "FSC Poseidon"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Fujitsu Siemens
Computers Poseidon sensor chips.
@@ -132,7 +136,6 @@ config SENSORS_FSCPOS
config SENSORS_GL518SM
tristate "Genesys Logic GL518SM"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for Genesys Logic GL518SM
sensor chips.
@@ -143,7 +146,7 @@ config SENSORS_GL518SM
config SENSORS_GL520SM
tristate "Genesys Logic GL520SM"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for Genesys Logic GL520SM
sensor chips.
@@ -154,7 +157,8 @@ config SENSORS_GL520SM
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for ITE IT87xx sensor chips
and clones: SiS960.
@@ -165,7 +169,6 @@ config SENSORS_IT87
config SENSORS_LM63
tristate "National Semiconductor LM63"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the National Semiconductor
LM63 remote diode digital temperature sensor with integrated fan
@@ -178,7 +181,6 @@ config SENSORS_LM63
config SENSORS_LM75
tristate "National Semiconductor LM75 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM75
sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
@@ -194,7 +196,6 @@ config SENSORS_LM75
config SENSORS_LM77
tristate "National Semiconductor LM77"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM77
sensor chips.
@@ -205,7 +206,8 @@ config SENSORS_LM77
config SENSORS_LM78
tristate "National Semiconductor LM78 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM78,
LM78-J and LM79.
@@ -216,7 +218,6 @@ config SENSORS_LM78
config SENSORS_LM80
tristate "National Semiconductor LM80"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM80 sensor chips.
@@ -227,7 +228,6 @@ config SENSORS_LM80
config SENSORS_LM83
tristate "National Semiconductor LM83"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM83 sensor chips.
@@ -238,7 +238,7 @@ config SENSORS_LM83
config SENSORS_LM85
tristate "National Semiconductor LM85 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM85
sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
@@ -249,7 +249,7 @@ config SENSORS_LM85
config SENSORS_LM87
tristate "National Semiconductor LM87"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
+ select HWMON_VID
help
If you say yes here you get support for National Semiconductor LM87
sensor chips.
@@ -260,7 +260,6 @@ config SENSORS_LM87
config SENSORS_LM90
tristate "National Semiconductor LM90 and compatibles"
depends on HWMON && I2C
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM90,
LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
@@ -275,7 +274,6 @@ config SENSORS_LM90
config SENSORS_LM92
tristate "National Semiconductor LM92 and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM92
and Maxim MAX6635 sensor chips.
@@ -286,7 +284,6 @@ config SENSORS_LM92
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for MAX1619 sensor chip.
@@ -296,8 +293,8 @@ config SENSORS_MAX1619
config SENSORS_PC87360
tristate "National Semiconductor PC87360 family"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get access to the hardware monitoring
functions of the National Semiconductor PC8736x Super-I/O chips.
@@ -311,7 +308,6 @@ config SENSORS_PC87360
config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595"
depends on HWMON && I2C && PCI && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated sensors in
@@ -323,7 +319,6 @@ config SENSORS_SIS5595
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated fan
@@ -336,7 +331,6 @@ config SENSORS_SMSC47M1
config SENSORS_SMSC47B397
tristate "SMSC LPC47B397-NC"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the SMSC LPC47B397-NC
@@ -348,7 +342,6 @@ config SENSORS_SMSC47B397
config SENSORS_VIA686A
tristate "VIA686A"
depends on HWMON && I2C && PCI
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get support for the integrated sensors in
@@ -360,7 +353,8 @@ config SENSORS_VIA686A
config SENSORS_W83781D
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
depends on HWMON && I2C
- select I2C_SENSOR
+ select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for the Winbond W8378x series
of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
@@ -369,10 +363,18 @@ config SENSORS_W83781D
This driver can also be built as a module. If so, the module
will be called w83781d.
+config SENSORS_W83792D
+ tristate "Winbond W83792D"
+ depends on HWMON && I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Winbond W83792D chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83792d.
+
config SENSORS_W83L785TS
tristate "Winbond W83L785TS-S"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the Winbond W83L785TS-S
sensor chip, which is used on the Asus A7N8X, among other
@@ -384,8 +386,8 @@ config SENSORS_W83L785TS
config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
+ select HWMON_VID
help
If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -396,7 +398,6 @@ config SENSORS_W83627HF
config SENSORS_W83627EHF
tristate "Winbond W83627EHF"
depends on HWMON && I2C && EXPERIMENTAL
- select I2C_SENSOR
select I2C_ISA
help
If you say yes here you get preliminary support for the hardware
@@ -404,9 +405,28 @@ config SENSORS_W83627EHF
Only fan and temperature inputs are supported at the moment, while
the chip does much more than that.
+ This driver also supports the W83627EHG, which is the lead-free
+ version of the W83627EHF.
+
This driver can also be built as a module. If so, the module
will be called w83627ehf.
+config SENSORS_HDAPS
+ tristate "IBM Hard Drive Active Protection System (hdaps)"
+ depends on HWMON && INPUT && X86
+ default n
+ help
+ This driver provides support for the IBM Hard Drive Active Protection
+ System (hdaps), which provides an accelerometer and other misc. data.
+ ThinkPads starting with the R50, T41, and X40 are supported. The
+ accelerometer data is readable via sysfs.
+
+ This driver also provides an absolute input class device, allowing
+ the laptop to act as a pinball machine-esque joystick.
+
+ Say Y here if you have an applicable laptop and want to experience
+ the awesome power of hdaps.
+
config HWMON_DEBUG_CHIP
bool "Hardware Monitoring Chip debugging messages"
depends on HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 2781403a0236..f7d6a2f61ee7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -2,9 +2,13 @@
# Makefile for sensor chip drivers.
#
+obj-$(CONFIG_HWMON) += hwmon.o
+obj-$(CONFIG_HWMON_VID) += hwmon-vid.o
+
# asb100, then w83781d go first, as they can override other drivers' addresses.
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
+obj-$(CONFIG_SENSORS_W83792D) += w83792d.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
@@ -18,6 +22,7 @@ obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
+obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index d2c774c32f45..8102876c7c3f 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -24,7 +24,8 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
@@ -32,10 +33,9 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
/* adm1021 constants specified below */
@@ -89,6 +89,7 @@ clearing it. Weird, ey? --Phil */
/* Each client has this additional data */
struct adm1021_data {
struct i2c_client client;
+ struct class_device *class_dev;
enum chips type;
struct semaphore update_lock;
@@ -120,7 +121,7 @@ static int adm1021_write_value(struct i2c_client *client, u8 reg,
static struct adm1021_data *adm1021_update_device(struct device *dev);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
-static int read_only = 0;
+static int read_only;
/* This is the driver that will be inserted */
@@ -185,7 +186,7 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1021_detect);
+ return i2c_probe(adapter, &addr_data, adm1021_detect);
}
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -196,15 +197,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
const char *type_name = "";
- /* Make sure we aren't probing the ISA bus!! This is just a safety check
- at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
- if (i2c_is_isa_adapter(adapter)) {
- dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
- return 0;
- }
-#endif
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto error0;
@@ -212,11 +204,10 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1021_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error0;
}
- memset(data, 0, sizeof(struct adm1021_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -295,6 +286,12 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
adm1021_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error2;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
@@ -305,6 +302,8 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error2:
+ i2c_detach_client(new_client);
error1:
kfree(data);
error0:
@@ -322,14 +321,15 @@ static void adm1021_init_client(struct i2c_client *client)
static int adm1021_detach_client(struct i2c_client *client)
{
+ struct adm1021_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index e452d0daf906..3ec12421694f 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -50,8 +50,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -60,13 +61,12 @@
*/
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_2(adm1025, ne1619);
+I2C_CLIENT_INSMOD_2(adm1025, ne1619);
/*
* The ADM1025 registers
@@ -132,6 +132,7 @@ static struct i2c_driver adm1025_driver = {
struct adm1025_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -312,7 +313,7 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1025_detect);
+ return i2c_probe(adapter, &addr_data, adm1025_detect);
}
/*
@@ -330,11 +331,10 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1025_data));
/* The common I2C client data is placed right before the
ADM1025-specific data. */
@@ -416,6 +416,12 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
adm1025_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -452,6 +458,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -464,7 +472,7 @@ static void adm1025_init_client(struct i2c_client *client)
struct adm1025_data *data = i2c_get_clientdata(client);
int i;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/*
* Set high limits
@@ -502,15 +510,15 @@ static void adm1025_init_client(struct i2c_client *client)
static int adm1025_detach_client(struct i2c_client *client)
{
+ struct adm1025_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 4fa17c76eea2..e0f56549d1d8 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -28,16 +28,16 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(adm1026);
+I2C_CLIENT_INSMOD_1(adm1026);
static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
@@ -259,6 +259,7 @@ struct pwm_data {
struct adm1026_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -314,22 +315,24 @@ static struct i2c_driver adm1026_driver = {
.detach_client = adm1026_detach_client,
};
-int adm1026_attach_adapter(struct i2c_adapter *adapter)
+static int adm1026_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON)) {
return 0;
}
- return i2c_detect(adapter, &addr_data, adm1026_detect);
+ return i2c_probe(adapter, &addr_data, adm1026_detect);
}
-int adm1026_detach_client(struct i2c_client *client)
+static int adm1026_detach_client(struct i2c_client *client)
{
+ struct adm1026_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(client);
+ kfree(data);
return 0;
}
-int adm1026_read_value(struct i2c_client *client, u8 reg)
+static int adm1026_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -343,7 +346,7 @@ int adm1026_read_value(struct i2c_client *client, u8 reg)
return res;
}
-int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
+static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
{
int res;
@@ -357,7 +360,7 @@ int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
return res;
}
-void adm1026_init_client(struct i2c_client *client)
+static void adm1026_init_client(struct i2c_client *client)
{
int value, i;
struct adm1026_data *data = i2c_get_clientdata(client);
@@ -457,7 +460,7 @@ void adm1026_init_client(struct i2c_client *client)
}
}
-void adm1026_print_gpio(struct i2c_client *client)
+static void adm1026_print_gpio(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
@@ -489,7 +492,7 @@ void adm1026_print_gpio(struct i2c_client *client)
}
}
-void adm1026_fixup_gpio(struct i2c_client *client)
+static void adm1026_fixup_gpio(struct i2c_client *client)
{
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
@@ -1449,8 +1452,8 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
-int adm1026_detect(struct i2c_adapter *adapter, int address,
- int kind)
+static int adm1026_detect(struct i2c_adapter *adapter, int address,
+ int kind)
{
int company, verstep;
struct i2c_client *new_client;
@@ -1467,13 +1470,11 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
client structure, even though we cannot fill it completely yet.
But it allows us to access adm1026_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1026_data));
-
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
@@ -1549,12 +1550,18 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
goto exitfree;
/* Set the VRM version */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/* Initialize the ADM1026 chip */
adm1026_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exitdetach;
+ }
+
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
@@ -1690,8 +1697,10 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
return 0;
/* Error out and cleanup code */
+exitdetach:
+ i2c_detach_client(new_client);
exitfree:
- kfree(new_client);
+ kfree(data);
exit:
return err;
}
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 9168e983ca1d..7c545d5eee45 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -26,7 +26,8 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Following macros takes channel parameter starting from 0 to 2 */
#define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr))
@@ -59,16 +60,16 @@
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(adm1030, adm1031);
+I2C_CLIENT_INSMOD_2(adm1030, adm1031);
typedef u8 auto_chan_table_t[8][2];
/* Each client has this additional data */
struct adm1031_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
int chip_type;
char valid; /* !=0 if following fields are valid */
@@ -725,10 +726,10 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm1031_detect);
+ return i2c_probe(adapter, &addr_data, adm1031_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -739,11 +740,10 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm1031_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -788,6 +788,12 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
adm1031_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -833,19 +839,24 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
- kfree(new_client);
+ kfree(data);
exit:
return err;
}
static int adm1031_detach_client(struct i2c_client *client)
{
+ struct adm1031_data *data = i2c_get_clientdata(client);
int ret;
+
+ hwmon_device_unregister(data->class_dev);
if ((ret = i2c_detach_client(client)) != 0) {
return ret;
}
- kfree(client);
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 5c68e9c311aa..11dc95f8a17e 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -45,17 +45,17 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
/* Insmod parameters */
-SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
/* ADM9240 registers */
#define ADM9240_REG_MAN_ID 0x3e
@@ -70,8 +70,7 @@ SENSORS_INSMOD_3(adm9240, ds1780, lm81);
#define ADM9240_REG_INT(nr) (0x41 + (nr))
#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
#define ADM9240_REG_TEMP 0x27
-#define ADM9240_REG_TEMP_HIGH 0x39
-#define ADM9240_REG_TEMP_HYST 0x3a
+#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */
#define ADM9240_REG_ANALOG_OUT 0x19
#define ADM9240_REG_CHASSIS_CLEAR 0x46
#define ADM9240_REG_VID_FAN_DIV 0x47
@@ -150,6 +149,7 @@ static struct i2c_driver adm9240_driver = {
struct adm9240_data {
enum chips type;
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid;
unsigned long last_updated_measure;
@@ -162,177 +162,155 @@ struct adm9240_data {
u8 fan_min[2]; /* rw fan1_min */
u8 fan_div[2]; /* rw fan1_div, read-only accessor */
s16 temp; /* ro temp1_input, 9-bit sign-extended */
- s8 temp_high; /* rw temp1_max */
- s8 temp_hyst; /* rw temp1_max_hyst */
+ s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */
u16 alarms; /* ro alarms */
u8 aout; /* rw aout_output */
u8 vid; /* ro vid */
u8 vrm; /* -- vrm set on startup, no accessor */
};
-/* i2c byte read/write interface */
-static int adm9240_read_value(struct i2c_client *client, u8 reg)
+/*** sysfs accessors ***/
+
+/* temperature */
+static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
- return i2c_smbus_read_byte_data(client, reg);
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
}
-static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
- return i2c_smbus_write_byte_data(client, reg, value);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
}
-/*** sysfs accessors ***/
+static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[attr->index] = TEMP_TO_REG(val);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
+ data->temp_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
-/* temperature */
-#define show_temp(value, scale) \
-static ssize_t show_##value(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct adm9240_data *data = adm9240_update_device(dev); \
- return sprintf(buf, "%d\n", data->value * scale); \
-}
-show_temp(temp_high, 1000);
-show_temp(temp_hyst, 1000);
-show_temp(temp, 500); /* 0.5'C per bit */
-
-#define set_temp(value, reg) \
-static ssize_t set_##value(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct adm9240_data *data = adm9240_update_device(dev); \
- long temp = simple_strtoul(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->value = TEMP_TO_REG(temp); \
- adm9240_write_value(client, reg, data->value); \
- up(&data->update_lock); \
- return count; \
-}
-
-set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
-set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
-
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
- show_temp_high, set_temp_high);
-static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
- show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+ show_max, set_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+ show_max, set_max, 1);
/* voltage */
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
+ attr->index));
}
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
+ attr->index));
}
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
+ attr->index));
}
-static ssize_t set_in_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_min[nr] = IN_TO_REG(val, nr);
- adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+ data->in_min[attr->index] = IN_TO_REG(val, attr->index);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
+ data->in_min[attr->index]);
up(&data->update_lock);
return count;
}
-static ssize_t set_in_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_max[nr] = IN_TO_REG(val, nr);
- adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+ data->in_max[attr->index] = IN_TO_REG(val, attr->index);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
+ data->in_max[attr->index]);
up(&data->update_lock);
return count;
}
-#define show_in_offset(offset) \
-static ssize_t show_in##offset(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in(dev, buf, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
-static ssize_t show_in##offset##_min(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in_min(dev, buf, offset); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return show_in_max(dev, buf, offset); \
-} \
-static ssize_t \
-set_in##offset##_min(struct device *dev, \
- struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t \
-set_in##offset##_max(struct device *dev, \
- struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in##offset##_max, set_in##offset##_max);
-
-show_in_offset(0);
-show_in_offset(1);
-show_in_offset(2);
-show_in_offset(3);
-show_in_offset(4);
-show_in_offset(5);
+#define vin(nr) \
+static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, \
+ show_in, NULL, nr); \
+static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, nr); \
+static SENSOR_DEVICE_ATTR(in##nr##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, nr);
+
+vin(0);
+vin(1);
+vin(2);
+vin(3);
+vin(4);
+vin(5);
/* fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
- 1 << data->fan_div[nr]));
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
+ 1 << data->fan_div[attr->index]));
}
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
- 1 << data->fan_div[nr]));
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
+ 1 << data->fan_div[attr->index]));
}
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adm9240_data *data = adm9240_update_device(dev);
- return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+ return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
}
/* write new fan div, callers must hold data->update_lock */
@@ -341,16 +319,16 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
{
u8 reg, old, shift = (nr + 2) * 2;
- reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
old = (reg >> shift) & 3;
reg &= ~(3 << shift);
reg |= (fan_div << shift);
- adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
dev_dbg(&client->dev, "fan%d clock divider changed from %u "
"to %u\n", nr + 1, 1 << old, 1 << fan_div);
}
-/*
+/*
* set fan speed low limit:
*
* - value is zero: disable fan speed low limit alarm
@@ -361,12 +339,15 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
* - otherwise: select fan clock divider to suit fan speed low limit,
* measurement code may adjust registers to ensure fan speed reading
*/
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
+ int nr = attr->index;
u8 new_div;
down(&data->update_lock);
@@ -406,50 +387,27 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
data->fan_div[nr] = new_div;
adm9240_write_fan_div(client, nr, new_div);
}
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+ i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
data->fan_min[nr]);
up(&data->update_lock);
return count;
}
-#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_div (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_min (struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
-return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
-return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
- show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
- show_fan_##offset##_div, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_min, set_fan_##offset##_min);
-
-show_fan_offset(1);
-show_fan_offset(2);
+#define fan(nr) \
+static SENSOR_DEVICE_ATTR(fan##nr##_input, S_IRUGO, \
+ show_fan, NULL, nr - 1); \
+static SENSOR_DEVICE_ATTR(fan##nr##_div, S_IRUGO, \
+ show_fan_div, NULL, nr - 1); \
+static SENSOR_DEVICE_ATTR(fan##nr##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, nr - 1);
+
+fan(1);
+fan(2);
/* alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
@@ -457,7 +415,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* vid */
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -465,13 +424,16 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
/* analog output */
-static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_aout(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm9240_data *data = adm9240_update_device(dev);
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
}
-static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
@@ -479,20 +441,23 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const
down(&data->update_lock);
data->aout = AOUT_TO_REG(val);
- adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
up(&data->update_lock);
return count;
}
static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
/* chassis_clear */
-static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t chassis_clear(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned long val = simple_strtol(buf, NULL, 10);
if (val == 1) {
- adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_CHASSIS_CLEAR, 0x80);
dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
}
return count;
@@ -513,11 +478,10 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct adm9240_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -533,7 +497,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind < 0) {
/* verify chip: reg address should match i2c address */
- if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+ if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
!= address) {
dev_err(&adapter->dev, "detect fail: address match, "
"0x%02x\n", address);
@@ -541,8 +505,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* check known chip manufacturer */
- man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
-
+ man_id = i2c_smbus_read_byte_data(new_client,
+ ADM9240_REG_MAN_ID);
if (man_id == 0x23) {
kind = adm9240;
} else if (man_id == 0xda) {
@@ -556,7 +520,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* successful detect, print chip info */
- die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+ die_rev = i2c_smbus_read_byte_data(new_client,
+ ADM9240_REG_DIE_REV);
dev_info(&adapter->dev, "found %s revision %u\n",
man_id == 0x23 ? "ADM9240" :
man_id == 0xda ? "DS1780" : "LM81", die_rev);
@@ -582,41 +547,76 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
adm9240_init_client(new_client);
/* populate sysfs filesystem */
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_in5_max.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_div);
- device_create_file(&new_client->dev, &dev_attr_fan1_min);
- device_create_file(&new_client->dev, &dev_attr_fan2_input);
- device_create_file(&new_client->dev, &dev_attr_fan2_div);
- device_create_file(&new_client->dev, &dev_attr_fan2_min);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max_hyst.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_div.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan2_min.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_aout_output);
device_create_file(&new_client->dev, &dev_attr_chassis_clear);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
return 0;
+
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
- kfree(new_client);
+ kfree(data);
exit:
return err;
}
@@ -625,30 +625,30 @@ static int adm9240_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, adm9240_detect);
+ return i2c_probe(adapter, &addr_data, adm9240_detect);
}
static int adm9240_detach_client(struct i2c_client *client)
{
+ struct adm9240_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
static void adm9240_init_client(struct i2c_client *client)
{
struct adm9240_data *data = i2c_get_clientdata(client);
- u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
- u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+ u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG);
+ u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3;
- data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+ data->vrm = vid_which_vrm(); /* need this to report vid as mV */
dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
data->vrm % 10);
@@ -663,18 +663,22 @@ static void adm9240_init_client(struct i2c_client *client)
for (i = 0; i < 6; i++)
{
- adm9240_write_value(client,
+ i2c_smbus_write_byte_data(client,
ADM9240_REG_IN_MIN(i), 0);
- adm9240_write_value(client,
+ i2c_smbus_write_byte_data(client,
ADM9240_REG_IN_MAX(i), 255);
}
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
- adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
- adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
- adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_FAN_MIN(0), 255);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_FAN_MIN(1), 255);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_TEMP_MAX(0), 127);
+ i2c_smbus_write_byte_data(client,
+ ADM9240_REG_TEMP_MAX(1), 127);
/* start measurement cycle */
- adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
dev_info(&client->dev, "cold start: config was 0x%02x "
"mode %u\n", conf, mode);
@@ -695,25 +699,25 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
for (i = 0; i < 6; i++) /* read voltages */
{
- data->in[i] = adm9240_read_value(client,
+ data->in[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN(i));
}
- data->alarms = adm9240_read_value(client,
+ data->alarms = i2c_smbus_read_byte_data(client,
ADM9240_REG_INT(0)) |
- adm9240_read_value(client,
+ i2c_smbus_read_byte_data(client,
ADM9240_REG_INT(1)) << 8;
/* read temperature: assume temperature changes less than
* 0.5'C per two measurement cycles thus ignore possible
* but unlikely aliasing error on lsb reading. --Grant */
- data->temp = ((adm9240_read_value(client,
+ data->temp = ((i2c_smbus_read_byte_data(client,
ADM9240_REG_TEMP) << 8) |
- adm9240_read_value(client,
+ i2c_smbus_read_byte_data(client,
ADM9240_REG_TEMP_CONF)) / 128;
for (i = 0; i < 2; i++) /* read fans */
{
- data->fan[i] = adm9240_read_value(client,
+ data->fan[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN(i));
/* adjust fan clock divider on overflow */
@@ -738,30 +742,30 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
for (i = 0; i < 6; i++)
{
- data->in_min[i] = adm9240_read_value(client,
+ data->in_min[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN_MIN(i));
- data->in_max[i] = adm9240_read_value(client,
+ data->in_max[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN_MAX(i));
}
for (i = 0; i < 2; i++)
{
- data->fan_min[i] = adm9240_read_value(client,
+ data->fan_min[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN_MIN(i));
}
- data->temp_high = adm9240_read_value(client,
- ADM9240_REG_TEMP_HIGH);
- data->temp_hyst = adm9240_read_value(client,
- ADM9240_REG_TEMP_HYST);
+ data->temp_max[0] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(0));
+ data->temp_max[1] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(1));
/* read fan divs and 5-bit VID */
- i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
data->fan_div[0] = (i >> 4) & 3;
data->fan_div[1] = (i >> 6) & 3;
data->vid = i & 0x0f;
- data->vid |= (adm9240_read_value(client,
+ data->vid |= (i2c_smbus_read_byte_data(client,
ADM9240_REG_VID4) & 1) << 4;
/* read analog out */
- data->aout = adm9240_read_value(client,
+ data->aout = i2c_smbus_read_byte_data(client,
ADM9240_REG_ANALOG_OUT);
data->last_updated_config = jiffies;
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 70d996d6fe0a..52c469722a65 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -39,8 +39,9 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include "lm75.h"
@@ -54,11 +55,8 @@
/* I2C addresses to scan */
static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
-/* ISA addresses to scan (none) */
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
/* Insmod parameters */
-SENSORS_INSMOD_1(asb100);
+I2C_CLIENT_INSMOD_1(asb100);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
@@ -183,6 +181,7 @@ static u8 DIV_TO_REG(long val)
dynamically allocated, at the same time the client itself is allocated. */
struct asb100_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -621,7 +620,7 @@ static int asb100_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, asb100_detect);
+ return i2c_probe(adapter, &addr_data, asb100_detect);
}
static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
@@ -630,19 +629,17 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
int i, id, err;
struct asb100_data *data = i2c_get_clientdata(new_client);
- data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[0])) {
err = -ENOMEM;
goto ERROR_SC_0;
}
- memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
- data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[1])) {
err = -ENOMEM;
goto ERROR_SC_1;
}
- memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
id = i2c_adapter_id(adapter);
@@ -714,14 +711,6 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *new_client;
struct asb100_data *data;
- /* asb100 is SMBus only */
- if (i2c_is_isa_adapter(adapter)) {
- pr_debug("asb100.o: detect failed, "
- "cannot attach to legacy adapter!\n");
- err = -ENODEV;
- goto ERROR0;
- }
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, "
"smbus byte data not supported!\n");
@@ -733,12 +722,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access asb100_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
- pr_debug("asb100.o: detect failed, kmalloc failed!\n");
+ if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
+ pr_debug("asb100.o: detect failed, kzalloc failed!\n");
err = -ENOMEM;
goto ERROR0;
}
- memset(data, 0, sizeof(struct asb100_data));
new_client = &data->client;
init_MUTEX(&data->lock);
@@ -821,6 +809,12 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file_in(new_client, 0);
device_create_file_in(new_client, 1);
device_create_file_in(new_client, 2);
@@ -847,6 +841,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR3:
+ i2c_detach_client(data->lm75[1]);
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[1]);
+ kfree(data->lm75[0]);
ERROR2:
i2c_detach_client(new_client);
ERROR1:
@@ -857,21 +856,23 @@ ERROR0:
static int asb100_detach_client(struct i2c_client *client)
{
+ struct asb100_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "client deregistration failed; "
- "client not detached.\n");
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_get_clientdata(client)==NULL) {
- /* subclients */
+ /* main client */
+ if (data)
+ kfree(data);
+
+ /* subclient */
+ else
kfree(client);
- } else {
- /* main client */
- kfree(i2c_get_clientdata(client));
- }
return 0;
}
@@ -969,7 +970,7 @@ static void asb100_init_client(struct i2c_client *client)
vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
vid = vid_from_reg(vid, data->vrm);
/* Start monitoring */
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index fca3fc1cef72..53324f56404e 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -23,8 +23,9 @@
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -40,9 +41,8 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
#define ATXP1_GPIO1MASK 0x0f
static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-SENSORS_INSMOD_1(atxp1);
+I2C_CLIENT_INSMOD_1(atxp1);
static int atxp1_attach_adapter(struct i2c_adapter * adapter);
static int atxp1_detach_client(struct i2c_client * client);
@@ -59,6 +59,7 @@ static struct i2c_driver atxp1_driver = {
struct atxp1_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
unsigned long last_updated;
u8 valid;
@@ -252,7 +253,9 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, &atxp1_detect);
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, &atxp1_detect);
};
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -265,12 +268,11 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct atxp1_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -295,7 +297,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Get VRM */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if ((data->vrm != 90) && (data->vrm != 91)) {
dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
@@ -317,6 +319,12 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_free;
}
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_gpio1);
device_create_file(&new_client->dev, &dev_attr_gpio2);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
@@ -326,6 +334,8 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -334,14 +344,17 @@ exit:
static int atxp1_detach_client(struct i2c_client * client)
{
+ struct atxp1_data * data = i2c_get_clientdata(client);
int err;
+ hwmon_device_unregister(data->class_dev);
+
err = i2c_detach_client(client);
if (err)
dev_err(&client->dev, "Failed to detach client.\n");
else
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return err;
};
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 5360d58804f6..34f71b7c7f37 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -26,16 +26,16 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include "lm75.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(ds1621);
+I2C_CLIENT_INSMOD_1(ds1621);
static int polarity = -1;
module_param(polarity, int, 0);
MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
@@ -71,6 +71,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
/* Each client has this additional data */
struct ds1621_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -179,12 +180,14 @@ static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, ds1621_detect);
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, ds1621_detect);
}
-/* This function is called by i2c_detect */
-int ds1621_detect(struct i2c_adapter *adapter, int address,
- int kind)
+/* This function is called by i2c_probe */
+static int ds1621_detect(struct i2c_adapter *adapter, int address,
+ int kind)
{
int conf, temp;
struct i2c_client *new_client;
@@ -199,11 +202,10 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
/* 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 ds1621_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct ds1621_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -250,6 +252,12 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
ds1621_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -259,6 +267,8 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
+ exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -267,15 +277,15 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
static int ds1621_detach_client(struct i2c_client *client)
{
+ struct ds1621_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index da411741c2c5..a02e1c34c757 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -31,20 +31,20 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
*/
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(fscher);
+I2C_CLIENT_INSMOD_1(fscher);
/*
* The FSCHER registers
@@ -132,6 +132,7 @@ static struct i2c_driver fscher_driver = {
struct fscher_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -287,7 +288,7 @@ static int fscher_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, fscher_detect);
+ return i2c_probe(adapter, &addr_data, fscher_detect);
}
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -302,11 +303,10 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
/* 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 i2c_smbus_read_byte_data. */
- if (!(data = kmalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct fscher_data));
/* The common I2C client data is placed right before the
* Hermes-specific data. */
@@ -341,6 +341,12 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
fscher_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file_revision(new_client);
device_create_file_alarms(new_client);
device_create_file_control(new_client);
@@ -360,6 +366,8 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -368,15 +376,15 @@ exit:
static int fscher_detach_client(struct i2c_client *client)
{
+ struct fscher_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 270015b626ad..64e4edc64f8d 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -34,19 +34,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
*/
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(fscpos);
+I2C_CLIENT_INSMOD_1(fscpos);
/*
* The FSCPOS registers
@@ -113,6 +113,7 @@ static struct i2c_driver fscpos_driver = {
*/
struct fscpos_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* 0 until following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -167,7 +168,7 @@ static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
"experience to the module author.\n");
/* Supported value: 2 (clears the status) */
- fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2);
+ fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2);
return count;
}
@@ -434,10 +435,10 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, fscpos_detect);
+ return i2c_probe(adapter, &addr_data, fscpos_detect);
}
-int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
+static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct fscpos_data *data;
@@ -452,11 +453,10 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
* But it allows us to access fscpos_{read,write}_value.
*/
- if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct fscpos_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -496,6 +496,12 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_event);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -526,6 +532,8 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -534,14 +542,14 @@ exit:
static int fscpos_detach_client(struct i2c_client *client)
{
+ struct fscpos_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, client"
- " not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 6bedf729dcf5..2f178dbe3d87 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -41,14 +41,14 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
+I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
/* Many GL518 constants specified below */
@@ -117,6 +117,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
/* Each client has this additional data */
struct gl518_data {
struct i2c_client client;
+ struct class_device *class_dev;
enum chips type;
struct semaphore update_lock;
@@ -346,7 +347,7 @@ static int gl518_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, gl518_detect);
+ return i2c_probe(adapter, &addr_data, gl518_detect);
}
static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -364,11 +365,10 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access gl518_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct gl518_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -419,6 +419,12 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
gl518_init_client((struct i2c_client *) new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -450,6 +456,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -477,16 +485,15 @@ static void gl518_init_client(struct i2c_client *client)
static int gl518_detach_client(struct i2c_client *client)
{
+ struct gl518_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
- return err;
- }
+ hwmon_device_unregister(data->class_dev);
- kfree(i2c_get_clientdata(client));
+ if ((err = i2c_detach_client(client)))
+ return err;
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 80ae8d30c2af..c39ba1239426 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -26,8 +26,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Type of the extra sensor */
static unsigned short extra_sensor_type;
@@ -36,10 +37,9 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(gl520sm);
+I2C_CLIENT_INSMOD_1(gl520sm);
/* Many GL520 constants specified below
One of the inputs can be configured as either temp or voltage.
@@ -120,6 +120,7 @@ static struct i2c_driver gl520_driver = {
/* Client data */
struct gl520_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until the following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -518,7 +519,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, gl520_detect);
+ return i2c_probe(adapter, &addr_data, gl520_detect);
}
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -535,11 +536,10 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access gl520_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct gl520_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -571,6 +571,12 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
gl520_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file_vid(new_client, 0);
device_create_file_in(new_client, 0);
@@ -592,6 +598,8 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -608,7 +616,7 @@ static void gl520_init_client(struct i2c_client *client)
conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
data->alarm_mask = 0xff;
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if (extra_sensor_type == 1)
conf &= ~0x10;
@@ -639,15 +647,15 @@ static void gl520_init_client(struct i2c_client *client)
static int gl520_detach_client(struct i2c_client *client)
{
+ struct gl520_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
new file mode 100644
index 000000000000..1e5dfc7805e2
--- /dev/null
+++ b/drivers/hwmon/hdaps.c
@@ -0,0 +1,614 @@
+/*
+ * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
+ *
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
+ * starting with the R40, T41, and X40. It provides a basic two-axis
+ * accelerometer and other data, such as the device's temperature.
+ *
+ * This driver is based on the document by Mark A. Smith available at
+ * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
+ * and error.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
+#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */
+
+#define HDAPS_PORT_STATE 0x1611 /* device state */
+#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
+#define HDAPS_PORT_XPOS 0x1614 /* x-axis position */
+#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */
+#define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */
+#define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */
+#define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */
+#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
+#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
+
+#define STATE_FRESH 0x50 /* accelerometer data is fresh */
+
+#define KEYBD_MASK 0x20 /* set if keyboard activity */
+#define MOUSE_MASK 0x40 /* set if mouse activity */
+#define KEYBD_ISSET(n) (!! (n & KEYBD_MASK)) /* keyboard used? */
+#define MOUSE_ISSET(n) (!! (n & MOUSE_MASK)) /* mouse used? */
+
+#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
+#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
+
+#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
+#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
+
+static struct timer_list hdaps_timer;
+static struct platform_device *pdev;
+static unsigned int hdaps_invert;
+static u8 km_activity;
+static int rest_x;
+static int rest_y;
+
+static DECLARE_MUTEX(hdaps_sem);
+
+/*
+ * __get_latch - Get the value from a given port. Callers must hold hdaps_sem.
+ */
+static inline u8 __get_latch(u16 port)
+{
+ return inb(port) & 0xff;
+}
+
+/*
+ * __check_latch - Check a port latch for a given value. Returns zero if the
+ * port contains the given value. Callers must hold hdaps_sem.
+ */
+static inline int __check_latch(u16 port, u8 val)
+{
+ if (__get_latch(port) == val)
+ return 0;
+ return -EINVAL;
+}
+
+/*
+ * __wait_latch - Wait up to 100us for a port latch to get a certain value,
+ * returning zero if the value is obtained. Callers must hold hdaps_sem.
+ */
+static int __wait_latch(u16 port, u8 val)
+{
+ unsigned int i;
+
+ for (i = 0; i < 20; i++) {
+ if (!__check_latch(port, val))
+ return 0;
+ udelay(5);
+ }
+
+ return -EIO;
+}
+
+/*
+ * __device_refresh - request a refresh from the accelerometer. Does not wait
+ * for refresh to complete. Callers must hold hdaps_sem.
+ */
+static void __device_refresh(void)
+{
+ udelay(200);
+ if (inb(0x1604) != STATE_FRESH) {
+ outb(0x11, 0x1610);
+ outb(0x01, 0x161f);
+ }
+}
+
+/*
+ * __device_refresh_sync - request a synchronous refresh from the
+ * accelerometer. We wait for the refresh to complete. Returns zero if
+ * successful and nonzero on error. Callers must hold hdaps_sem.
+ */
+static int __device_refresh_sync(void)
+{
+ __device_refresh();
+ return __wait_latch(0x1604, STATE_FRESH);
+}
+
+/*
+ * __device_complete - indicate to the accelerometer that we are done reading
+ * data, and then initiate an async refresh. Callers must hold hdaps_sem.
+ */
+static inline void __device_complete(void)
+{
+ inb(0x161f);
+ inb(0x1604);
+ __device_refresh();
+}
+
+/*
+ * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
+ * the given pointer. Returns zero on success or a negative error on failure.
+ * Can sleep.
+ */
+static int hdaps_readb_one(unsigned int port, u8 *val)
+{
+ int ret;
+
+ down(&hdaps_sem);
+
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ ret = __device_refresh_sync();
+ if (ret)
+ goto out;
+
+ *val = inb(port);
+ __device_complete();
+
+out:
+ up(&hdaps_sem);
+ return ret;
+}
+
+/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
+static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
+ int *x, int *y)
+{
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ if (__device_refresh_sync())
+ return -EIO;
+
+ *y = inw(port2);
+ *x = inw(port1);
+ km_activity = inb(HDAPS_PORT_KMACT);
+ __device_complete();
+
+ /* if hdaps_invert is set, negate the two values */
+ if (hdaps_invert) {
+ *x = -*x;
+ *y = -*y;
+ }
+
+ return 0;
+}
+
+/*
+ * hdaps_read_pair - reads the values from a pair of ports, placing the values
+ * in the given pointers. Returns zero on success. Can sleep.
+ */
+static int hdaps_read_pair(unsigned int port1, unsigned int port2,
+ int *val1, int *val2)
+{
+ int ret;
+
+ down(&hdaps_sem);
+ ret = __hdaps_read_pair(port1, port2, val1, val2);
+ up(&hdaps_sem);
+
+ return ret;
+}
+
+/*
+ * hdaps_device_init - initialize the accelerometer. Returns zero on success
+ * and negative error code on failure. Can sleep.
+ */
+static int hdaps_device_init(void)
+{
+ int total, ret = -ENXIO;
+
+ down(&hdaps_sem);
+
+ outb(0x13, 0x1610);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+
+ /*
+ * Most ThinkPads return 0x01.
+ *
+ * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops
+ * have "inverted" axises.
+ *
+ * The 0x02 value occurs when the chip has been previously initialized.
+ */
+ if (__check_latch(0x1611, 0x03) &&
+ __check_latch(0x1611, 0x02) &&
+ __check_latch(0x1611, 0x01))
+ goto out;
+
+ printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
+ __get_latch(0x1611));
+
+ outb(0x17, 0x1610);
+ outb(0x81, 0x1611);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ if (__wait_latch(0x1611, 0x00))
+ goto out;
+ if (__wait_latch(0x1612, 0x60))
+ goto out;
+ if (__wait_latch(0x1613, 0x00))
+ goto out;
+ outb(0x14, 0x1610);
+ outb(0x01, 0x1611);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ outb(0x10, 0x1610);
+ outb(0xc8, 0x1611);
+ outb(0x00, 0x1612);
+ outb(0x02, 0x1613);
+ outb(0x01, 0x161f);
+ if (__wait_latch(0x161f, 0x00))
+ goto out;
+ if (__device_refresh_sync())
+ goto out;
+ if (__wait_latch(0x1611, 0x00))
+ goto out;
+
+ /* we have done our dance, now let's wait for the applause */
+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+ int x, y;
+
+ /* a read of the device helps push it into action */
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+ if (!__wait_latch(0x1611, 0x02)) {
+ ret = 0;
+ break;
+ }
+
+ msleep(INIT_WAIT_MSECS);
+ }
+
+out:
+ up(&hdaps_sem);
+ return ret;
+}
+
+
+/* Device model stuff */
+
+static int hdaps_probe(struct device *dev)
+{
+ int ret;
+
+ ret = hdaps_device_init();
+ if (ret)
+ return ret;
+
+ printk(KERN_INFO "hdaps: device successfully initialized.\n");
+ return 0;
+}
+
+static int hdaps_resume(struct device *dev)
+{
+ return hdaps_device_init();
+}
+
+static struct device_driver hdaps_driver = {
+ .name = "hdaps",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .probe = hdaps_probe,
+ .resume = hdaps_resume
+};
+
+/* Input class stuff */
+
+static struct input_dev hdaps_idev = {
+ .name = "hdaps",
+ .evbit = { BIT(EV_ABS) },
+ .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
+ .absmin = { [ABS_X] = -256, [ABS_Y] = -256 },
+ .absmax = { [ABS_X] = 256, [ABS_Y] = 256 },
+ .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+ .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+};
+
+/*
+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+ int x, y;
+
+ /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
+ if (down_trylock(&hdaps_sem)) {
+ mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
+ return;
+ }
+
+ if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+ goto out;
+
+ input_report_abs(&hdaps_idev, ABS_X, x - rest_x);
+ input_report_abs(&hdaps_idev, ABS_Y, y - rest_y);
+ input_sync(&hdaps_idev);
+
+ mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
+
+out:
+ up(&hdaps_sem);
+}
+
+
+/* Sysfs Files */
+
+static ssize_t hdaps_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret, x, y;
+
+ ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_variance_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret, x, y;
+
+ ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_temp1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 temp;
+ int ret;
+
+ ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_temp2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 temp;
+ int ret;
+
+ ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_keyboard_activity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
+}
+
+static ssize_t hdaps_mouse_activity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
+}
+
+static ssize_t hdaps_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t hdaps_calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ down(&hdaps_sem);
+ hdaps_calibrate();
+ up(&hdaps_sem);
+
+ return count;
+}
+
+static ssize_t hdaps_invert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", hdaps_invert);
+}
+
+static ssize_t hdaps_invert_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int invert;
+
+ if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0))
+ return -EINVAL;
+
+ hdaps_invert = invert;
+ hdaps_calibrate();
+
+ return count;
+}
+
+static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
+static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
+static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
+static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
+static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
+static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
+static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
+static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
+
+static struct attribute *hdaps_attributes[] = {
+ &dev_attr_position.attr,
+ &dev_attr_variance.attr,
+ &dev_attr_temp1.attr,
+ &dev_attr_temp2.attr,
+ &dev_attr_keyboard_activity.attr,
+ &dev_attr_mouse_activity.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_invert.attr,
+ NULL,
+};
+
+static struct attribute_group hdaps_attribute_group = {
+ .attrs = hdaps_attributes,
+};
+
+
+/* Module stuff */
+
+/* hdaps_dmi_match - found a match. return one, short-circuiting the hunt. */
+static int hdaps_dmi_match(struct dmi_system_id *id)
+{
+ printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
+ return 1;
+}
+
+/* hdaps_dmi_match_invert - found an inverted match. */
+static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+{
+ hdaps_invert = 1;
+ printk(KERN_INFO "hdaps: inverting axis readings.\n");
+ return hdaps_dmi_match(id);
+}
+
+#define HDAPS_DMI_MATCH_NORMAL(model) { \
+ .ident = "IBM " model, \
+ .callback = hdaps_dmi_match, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_PRODUCT_VERSION, model) \
+ } \
+}
+
+#define HDAPS_DMI_MATCH_INVERT(model) { \
+ .ident = "IBM " model, \
+ .callback = hdaps_dmi_match_invert, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_PRODUCT_VERSION, model) \
+ } \
+}
+
+static int __init hdaps_init(void)
+{
+ int ret;
+
+ /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
+ struct dmi_system_id hdaps_whitelist[] = {
+ HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
+ HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
+ HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
+ { .ident = NULL }
+ };
+
+ if (!dmi_check_system(hdaps_whitelist)) {
+ printk(KERN_WARNING "hdaps: supported laptop not found!\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
+ ret = -ENXIO;
+ goto out;
+ }
+
+ ret = driver_register(&hdaps_driver);
+ if (ret)
+ goto out_region;
+
+ pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ ret = PTR_ERR(pdev);
+ goto out_driver;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
+ if (ret)
+ goto out_device;
+
+ /* initial calibrate for the input device */
+ hdaps_calibrate();
+
+ /* initialize the input class */
+ hdaps_idev.dev = &pdev->dev;
+ input_register_device(&hdaps_idev);
+
+ /* start up our timer for the input device */
+ init_timer(&hdaps_timer);
+ hdaps_timer.function = hdaps_mousedev_poll;
+ hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
+ add_timer(&hdaps_timer);
+
+ printk(KERN_INFO "hdaps: driver successfully loaded.\n");
+ return 0;
+
+out_device:
+ platform_device_unregister(pdev);
+out_driver:
+ driver_unregister(&hdaps_driver);
+out_region:
+ release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+out:
+ printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
+ return ret;
+}
+
+static void __exit hdaps_exit(void)
+{
+ del_timer_sync(&hdaps_timer);
+ input_unregister_device(&hdaps_idev);
+ sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+ platform_device_unregister(pdev);
+ driver_unregister(&hdaps_driver);
+ release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+
+ printk(KERN_INFO "hdaps: driver unloaded.\n");
+}
+
+module_init(hdaps_init);
+module_exit(hdaps_exit);
+
+module_param_named(invert, hdaps_invert, bool, 0);
+MODULE_PARM_DESC(invert, "invert data along each axis");
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
new file mode 100644
index 000000000000..312769ad4dab
--- /dev/null
+++ b/drivers/hwmon/hwmon-vid.c
@@ -0,0 +1,189 @@
+/*
+ hwmon-vid.c - VID/VRM/VRD voltage conversions
+
+ Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+
+ Partly imported from i2c-vid.h of the lm_sensors project
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon-vid.h>
+
+/*
+ Common code for decoding VID pins.
+
+ References:
+
+ For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
+ available at http://developer.intel.com/.
+
+ For VRD 10.0 and up, "VRD x.y Design Guide",
+ available at http://developer.intel.com/.
+
+ AMD Opteron processors don't follow the Intel specifications.
+ I'm going to "make up" 2.4 as the spec number for the Opterons.
+ No good reason just a mnemonic for the 24x Opteron processor
+ series.
+
+ Opteron VID encoding is:
+ 00000 = 1.550 V
+ 00001 = 1.525 V
+ . . . .
+ 11110 = 0.800 V
+ 11111 = 0.000 V (off)
+*/
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+ val is the 4-, 5- or 6-bit VID code.
+ Returned value is in mV to avoid floating point in the kernel. */
+int vid_from_reg(int val, int vrm)
+{
+ int vid;
+
+ switch(vrm) {
+
+ case 0:
+ return 0;
+
+ case 100: /* VRD 10.0 */
+ if((val & 0x1f) == 0x1f)
+ return 0;
+ if((val & 0x1f) <= 0x09 || val == 0x0a)
+ vid = 10875 - (val & 0x1f) * 250;
+ else
+ vid = 18625 - (val & 0x1f) * 250;
+ if(val & 0x20)
+ vid -= 125;
+ vid /= 10; /* only return 3 dec. places for now */
+ return vid;
+
+ case 24: /* Opteron processor */
+ return(val == 0x1f ? 0 : 1550 - val * 25);
+
+ case 91: /* VRM 9.1 */
+ case 90: /* VRM 9.0 */
+ return(val == 0x1f ? 0 :
+ 1850 - val * 25);
+
+ case 85: /* VRM 8.5 */
+ return((val & 0x10 ? 25 : 0) +
+ ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+ ((val & 0x0f) * 50));
+
+ case 84: /* VRM 8.4 */
+ val &= 0x0f;
+ /* fall through */
+ default: /* VRM 8.2 */
+ return(val == 0x1f ? 0 :
+ val & 0x10 ? 5100 - (val) * 100 :
+ 2050 - (val) * 50);
+ }
+}
+
+
+/*
+ After this point is the code to automatically determine which
+ VRM/VRD specification should be used depending on the CPU.
+*/
+
+struct vrm_model {
+ u8 vendor;
+ u8 eff_family;
+ u8 eff_model;
+ int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+ {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
+ {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
+ {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
+ {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */
+ {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
+ {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
+ {X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */
+ {X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */
+ {X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */
+ {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
+ {X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */
+ {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
+ {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
+};
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+ int i = 0;
+
+ while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+ if (vrm_models[i].vendor==vendor)
+ if ((vrm_models[i].eff_family==eff_family)
+ && ((vrm_models[i].eff_model==eff_model) ||
+ (vrm_models[i].eff_model==ANY)))
+ return vrm_models[i].vrm_type;
+ i++;
+ }
+
+ return 0;
+}
+
+int vid_which_vrm(void)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+ u32 eax;
+ u8 eff_family, eff_model;
+ int vrm_ret;
+
+ if (c->x86 < 6) /* Any CPU with family lower than 6 */
+ return 0; /* doesn't have VID and/or CPUID */
+
+ eax = cpuid_eax(1);
+ eff_family = ((eax & 0x00000F00)>>8);
+ eff_model = ((eax & 0x000000F0)>>4);
+ if (eff_family == 0xF) { /* use extended model & family */
+ eff_family += ((eax & 0x00F00000)>>20);
+ eff_model += ((eax & 0x000F0000)>>16)<<4;
+ }
+ vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+ if (vrm_ret == 0)
+ printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
+ "x86 CPU\n");
+ return vrm_ret;
+}
+
+/* and now something completely different for the non-x86 world */
+#else
+int vid_which_vrm(void)
+{
+ printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
+ return 0;
+}
+#endif
+
+EXPORT_SYMBOL(vid_from_reg);
+EXPORT_SYMBOL(vid_which_vrm);
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("hwmon-vid driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
new file mode 100644
index 000000000000..6f48579799b5
--- /dev/null
+++ b/drivers/hwmon/hwmon.c
@@ -0,0 +1,98 @@
+/*
+ hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+ This file defines the sysfs class "hwmon", for use by sensors drivers.
+
+ Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.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 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+#include <linux/hwmon.h>
+
+#define HWMON_ID_PREFIX "hwmon"
+#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
+
+static struct class *hwmon_class;
+
+static DEFINE_IDR(hwmon_idr);
+
+/**
+ * hwmon_device_register - register w/ hwmon sysfs class
+ * @dev: the device to register
+ *
+ * hwmon_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct class_device *hwmon_device_register(struct device *dev)
+{
+ struct class_device *cdev;
+ int id;
+
+ if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)
+ return ERR_PTR(-ENOMEM);
+
+ if (idr_get_new(&hwmon_idr, NULL, &id) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ id = id & MAX_ID_MASK;
+ cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
+ HWMON_ID_FORMAT, id);
+
+ if (IS_ERR(cdev))
+ idr_remove(&hwmon_idr, id);
+
+ return cdev;
+}
+
+/**
+ * hwmon_device_unregister - removes the previously registered class device
+ *
+ * @cdev: the class device to destroy
+ */
+void hwmon_device_unregister(struct class_device *cdev)
+{
+ int id;
+
+ if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) {
+ class_device_unregister(cdev);
+ idr_remove(&hwmon_idr, id);
+ } else
+ dev_dbg(cdev->dev,
+ "hwmon_device_unregister() failed: bad class ID!\n");
+}
+
+static int __init hwmon_init(void)
+{
+ hwmon_class = class_create(THIS_MODULE, "hwmon");
+ if (IS_ERR(hwmon_class)) {
+ printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
+ return PTR_ERR(hwmon_class);
+ }
+ return 0;
+}
+
+static void __exit hwmon_exit(void)
+{
+ class_destroy(hwmon_class);
+}
+
+module_init(hwmon_init);
+module_exit(hwmon_exit);
+
+EXPORT_SYMBOL_GPL(hwmon_device_register);
+EXPORT_SYMBOL_GPL(hwmon_device_unregister);
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index db20c9e47393..6c41e25e670b 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -2,7 +2,7 @@
it87.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring.
- Supports: IT8705F Super I/O chip w/LPC interface & SMBus
+ Supports: IT8705F Super I/O chip w/LPC interface
IT8712F Super I/O chip w/LPC interface & SMBus
Sis950 A clone of the IT8705F
@@ -36,19 +36,21 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address;
/* Insmod parameters */
-SENSORS_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_2(it87, it8712);
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
@@ -192,6 +194,7 @@ static int DIV_TO_REG(int val)
allocated. */
struct it87_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -218,7 +221,7 @@ struct it87_data {
static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_find(int *address);
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
static int it87_detach_client(struct i2c_client *client);
@@ -239,6 +242,14 @@ static struct i2c_driver it87_driver = {
.detach_client = it87_detach_client,
};
+static struct i2c_driver it87_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "it87-isa",
+ .attach_adapter = it87_isa_attach_adapter,
+ .detach_client = it87_detach_client,
+};
+
+
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -686,11 +697,16 @@ static int it87_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, it87_detect);
+ return i2c_probe(adapter, &addr_data, it87_detect);
}
-/* SuperIO detection - will change normal_isa[0] if a chip is found */
-static int it87_find(int *address)
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return it87_detect(adapter, isa_address, -1);
+}
+
+/* SuperIO detection - will change isa_address if a chip is found */
+static int __init it87_find(unsigned short *address)
{
int err = -ENODEV;
@@ -721,8 +737,8 @@ exit:
return err;
}
-/* This function is called by i2c_detect */
-int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
struct i2c_client *new_client;
@@ -738,45 +754,17 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, IT87_EXTENT, it87_driver.name))
+ if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
goto ERROR0;
- /* Probe whether there is anything available on this address. Already
- done for SMBus and Super-I/O clients */
- if (kind < 0) {
- if (is_isa && !chip_type) {
-#define REALLY_SLOW_IO
- /* We need the timeouts for at least some IT87-like chips. But only
- if we read 'undefined' registers. */
- i = inb_p(address + 1);
- if (inb_p(address + 2) != i
- || inb_p(address + 3) != i
- || inb_p(address + 7) != i) {
- err = -ENODEV;
- goto ERROR1;
- }
-#undef REALLY_SLOW_IO
-
- /* Let's just hope nothing breaks here */
- i = inb_p(address + 5) & 0x7f;
- outb_p(~i & 0x7f, address + 5);
- if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
- outb_p(i, address + 5);
- err = -ENODEV;
- goto ERROR1;
- }
- }
- }
-
- /* OK. For now, we presume we have a valid client. We now create the
+ /* For now, we presume we have a valid client. We create the
client structure, even though we cannot fill it completely yet.
But it allows us to access it87_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct it87_data));
new_client = &data->client;
if (is_isa)
@@ -784,7 +772,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
- new_client->driver = &it87_driver;
+ new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -840,6 +828,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
it87_init_client(new_client, data);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
@@ -897,13 +891,15 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->type == it8712) {
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
device_create_file_vrm(new_client);
device_create_file_vid(new_client);
}
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
@@ -915,17 +911,17 @@ ERROR0:
static int it87_detach_client(struct i2c_client *client)
{
+ struct it87_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
if(i2c_is_isa_client(client))
release_region(client->addr, IT87_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -1158,16 +1154,26 @@ static struct it87_data *it87_update_device(struct device *dev)
static int __init sm_it87_init(void)
{
- int addr;
+ int res;
+
+ res = i2c_add_driver(&it87_driver);
+ if (res)
+ return res;
- if (!it87_find(&addr)) {
- normal_isa[0] = addr;
+ if (!it87_find(&isa_address)) {
+ res = i2c_isa_add_driver(&it87_isa_driver);
+ if (res) {
+ i2c_del_driver(&it87_driver);
+ return res;
+ }
}
- return i2c_add_driver(&it87_driver);
+
+ return 0;
}
static void __exit sm_it87_exit(void)
{
+ i2c_isa_del_driver(&it87_isa_driver);
i2c_del_driver(&it87_driver);
}
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 7c6f9ea5a254..954ec2497249 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -42,8 +42,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -51,13 +52,12 @@
*/
static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm63);
+I2C_CLIENT_INSMOD_1(lm63);
/*
* The LM63 registers
@@ -152,6 +152,7 @@ static struct i2c_driver lm63_driver = {
struct lm63_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -358,7 +359,7 @@ static int lm63_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm63_detect);
+ return i2c_probe(adapter, &addr_data, lm63_detect);
}
/*
@@ -374,11 +375,10 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm63_data));
/* The common I2C client data is placed right before the
LM63-specific data. */
@@ -437,6 +437,12 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
lm63_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
if (data->config & 0x04) { /* tachometer enabled */
device_create_file(&new_client->dev,
&sensor_dev_attr_fan1_input.dev_attr);
@@ -462,6 +468,8 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -505,15 +513,15 @@ static void lm63_init_client(struct i2c_client *client)
static int lm63_detach_client(struct i2c_client *client)
{
+ struct lm63_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 5be164ed278e..d70f4c8fc1e6 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -23,17 +23,17 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include "lm75.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm75);
+I2C_CLIENT_INSMOD_1(lm75);
/* Many LM75 constants specified below */
@@ -46,6 +46,7 @@ SENSORS_INSMOD_1(lm75);
/* Each client has this additional data */
struct lm75_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -107,10 +108,10 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm75_detect);
+ return i2c_probe(adapter, &addr_data, lm75_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
@@ -119,16 +120,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
const char *name = "";
- /* Make sure we aren't probing the ISA bus!! This is just a safety check
- at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
- if (i2c_is_isa_adapter(adapter)) {
- dev_dbg(&adapter->dev,
- "lm75_detect called for an ISA bus adapter?!?\n");
- goto exit;
- }
-#endif
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
goto exit;
@@ -136,11 +127,10 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
/* 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 lm75_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm75_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -208,12 +198,20 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
lm75_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -222,8 +220,10 @@ exit:
static int lm75_detach_client(struct i2c_client *client)
{
+ struct lm75_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -251,8 +251,12 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
static void lm75_init_client(struct i2c_client *client)
{
- /* Initialize the LM75 chip */
- lm75_write_value(client, LM75_REG_CONF, 0);
+ int reg;
+
+ /* Enable if in shutdown mode */
+ reg = lm75_read_value(client, LM75_REG_CONF);
+ if (reg >= 0 && (reg & 0x01))
+ lm75_write_value(client, LM75_REG_CONF, reg & 0xfe);
}
static struct lm75_data *lm75_update_device(struct device *dev)
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h
index 63e3f2fb4c21..af7dc650ee15 100644
--- a/drivers/hwmon/lm75.h
+++ b/drivers/hwmon/lm75.h
@@ -25,7 +25,7 @@
which contains this code, we don't worry about the wasted space.
*/
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
/* straight from the datasheet */
#define LM75_TEMP_MIN (-55000)
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index b98f44952997..9380fda7dcd1 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -30,15 +30,14 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm77);
+I2C_CLIENT_INSMOD_1(lm77);
/* The LM77 registers */
#define LM77_REG_TEMP 0x00
@@ -51,6 +50,7 @@ SENSORS_INSMOD_1(lm77);
/* Each client has this additional data */
struct lm77_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
@@ -208,10 +208,10 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm77_detect);
+ return i2c_probe(adapter, &addr_data, lm77_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -226,11 +226,10 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
/* 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 lm77_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm77_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -317,6 +316,12 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
lm77_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -327,6 +332,8 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -335,8 +342,10 @@ exit:
static int lm77_detach_client(struct i2c_client *client)
{
+ struct lm77_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 29241469dcba..bde0cda9477e 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -23,7 +23,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
/* Addresses to scan */
@@ -31,10 +34,10 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29,
0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
/* Insmod parameters */
-SENSORS_INSMOD_3(lm78, lm78j, lm79);
+I2C_CLIENT_INSMOD_2(lm78, lm79);
/* Many LM78 constants specified below */
@@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val)
return val * 1000;
}
-/* VID: mV
- REG: (see doc/vid) */
-static inline int VID_FROM_REG(u8 val)
-{
- return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
-}
-
#define DIV_FROM_REG(val) (1 << (val))
/* There are some complications in a module like this. First off, LM78 chips
@@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val)
allocated. */
struct lm78_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -156,6 +153,7 @@ struct lm78_data {
static int lm78_attach_adapter(struct i2c_adapter *adapter);
+static int lm78_isa_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);
@@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = {
.detach_client = lm78_detach_client,
};
+static struct i2c_driver lm78_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm78-isa",
+ .attach_adapter = lm78_isa_attach_adapter,
+ .detach_client = lm78_detach_client,
+};
+
+
/* 7 Voltages */
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
@@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
- return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
+ return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
@@ -465,11 +471,16 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm78_detect);
+ return i2c_probe(adapter, &addr_data, lm78_detect);
+}
+
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return lm78_detect(adapter, isa_address, -1);
}
-/* This function is called by i2c_detect */
-int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, err;
struct i2c_client *new_client;
@@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
+ if (!request_region(address, LM78_EXTENT,
+ lm78_isa_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -528,11 +540,10 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access lm78_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct lm78_data));
new_client = &data->client;
if (is_isa)
@@ -540,7 +551,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
- new_client->driver = &lm78_driver;
+ new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -559,10 +570,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Determine the chip type. */
if (kind <= 0) {
i = lm78_read_value(new_client, LM78_REG_CHIPID);
- if (i == 0x00 || i == 0x20)
+ if (i == 0x00 || i == 0x20 /* LM78 */
+ || i == 0x40) /* LM78-J */
kind = lm78;
- else if (i == 0x40)
- kind = lm78j;
else if ((i & 0xfe) == 0xc0)
kind = lm79;
else {
@@ -578,8 +588,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == lm78) {
client_name = "lm78";
- } else if (kind == lm78j) {
- client_name = "lm78-j";
} else if (kind == lm79) {
client_name = "lm79";
}
@@ -605,6 +613,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -643,6 +657,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
@@ -654,18 +670,18 @@ ERROR0:
static int lm78_detach_client(struct i2c_client *client)
{
+ struct lm78_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
if(i2c_is_isa_client(client))
release_region(client->addr, LM78_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -709,7 +725,6 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
-/* Called when we have found a new LM78. It should set limits, etc. */
static void lm78_init_client(struct i2c_client *client)
{
u8 config = lm78_read_value(client, LM78_REG_CONFIG);
@@ -777,18 +792,31 @@ static struct lm78_data *lm78_update_device(struct device *dev)
static int __init sm_lm78_init(void)
{
- return i2c_add_driver(&lm78_driver);
+ int res;
+
+ res = i2c_add_driver(&lm78_driver);
+ if (res)
+ return res;
+
+ res = i2c_isa_add_driver(&lm78_isa_driver);
+ if (res) {
+ i2c_del_driver(&lm78_driver);
+ return res;
+ }
+
+ return 0;
}
static void __exit sm_lm78_exit(void)
{
+ i2c_isa_del_driver(&lm78_isa_driver);
i2c_del_driver(&lm78_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
+MODULE_DESCRIPTION("LM78/LM79 driver");
MODULE_LICENSE("GPL");
module_init(sm_lm78_init);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 8100595feb44..c359fdea211e 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -26,15 +26,15 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm80);
+I2C_CLIENT_INSMOD_1(lm80);
/* Many LM80 constants specified below */
@@ -107,6 +107,7 @@ static inline long TEMP_FROM_REG(u16 temp)
struct lm80_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -389,10 +390,10 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm80_detect);
+ return i2c_probe(adapter, &addr_data, lm80_detect);
}
-int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, cur;
struct i2c_client *new_client;
@@ -406,11 +407,10 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* 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 lm80_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm80_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -451,6 +451,12 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
@@ -487,6 +493,8 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
kfree(data);
exit:
@@ -495,15 +503,15 @@ exit:
static int lm80_detach_client(struct i2c_client *client)
{
+ struct lm80_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index a49008b444c8..9a70611a9f69 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -32,8 +32,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -45,13 +46,12 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm83);
+I2C_CLIENT_INSMOD_1(lm83);
/*
* The LM83 registers
@@ -138,6 +138,7 @@ static struct i2c_driver lm83_driver = {
struct lm83_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -212,7 +213,7 @@ static int lm83_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm83_detect);
+ return i2c_probe(adapter, &addr_data, lm83_detect);
}
/*
@@ -229,11 +230,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm83_data));
/* The common I2C client data is placed right after the
* LM83-specific data. */
@@ -312,6 +312,12 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&new_client->dev,
@@ -340,6 +346,8 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -348,15 +356,15 @@ exit:
static int lm83_detach_client(struct i2c_client *client)
{
+ struct lm83_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index b4d7fd418264..d1070ed2bee6 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -28,15 +28,15 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
+I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
/* The LM85 registers */
@@ -281,15 +281,6 @@ static int ZONE_TO_REG( int zone )
#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
-/* i2c-vid.h defines vid_from_reg() */
-#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
-
-/* Unlike some other drivers we DO NOT set initial limits. Use
- * the config file to set limits. Some users have reported
- * motherboards shutting down when we set limits in a previous
- * version of the driver.
- */
-
/* Chip sampling rates
*
* Some sensors are not updated more frequently than once per second
@@ -339,6 +330,7 @@ struct lm85_autofan {
struct lm85_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -1015,14 +1007,14 @@ temp_auto(1);
temp_auto(2);
temp_auto(3);
-int lm85_attach_adapter(struct i2c_adapter *adapter)
+static int lm85_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm85_detect);
+ return i2c_probe(adapter, &addr_data, lm85_detect);
}
-int lm85_detect(struct i2c_adapter *adapter, int address,
+static int lm85_detect(struct i2c_adapter *adapter, int address,
int kind)
{
int company, verstep ;
@@ -1031,11 +1023,6 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
int err = 0;
const char *type_name = "";
- if (i2c_is_isa_adapter(adapter)) {
- /* This chip has no ISA interface */
- goto ERROR0 ;
- };
-
if (!i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */
@@ -1046,11 +1033,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
client structure, even though we cannot fill it completely yet.
But it allows us to access lm85_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
- memset(data, 0, sizeof(struct lm85_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1160,12 +1146,18 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
goto ERROR1;
/* Set the VRM version */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
/* Initialize the LM85 chip */
lm85_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR2;
+ }
+
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan3_input);
@@ -1235,21 +1227,25 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
return 0;
/* Error out and cleanup code */
+ ERROR2:
+ i2c_detach_client(new_client);
ERROR1:
kfree(data);
ERROR0:
return err;
}
-int lm85_detach_client(struct i2c_client *client)
+static int lm85_detach_client(struct i2c_client *client)
{
+ struct lm85_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->class_dev);
i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
-int lm85_read_value(struct i2c_client *client, u8 reg)
+static int lm85_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -1279,7 +1275,7 @@ int lm85_read_value(struct i2c_client *client, u8 reg)
return res ;
}
-int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+static int lm85_write_value(struct i2c_client *client, u8 reg, int value)
{
int res ;
@@ -1308,7 +1304,7 @@ int lm85_write_value(struct i2c_client *client, u8 reg, int value)
return res ;
}
-void lm85_init_client(struct i2c_client *client)
+static void lm85_init_client(struct i2c_client *client)
{
int value;
struct lm85_data *data = i2c_get_clientdata(client);
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 1921ed1af182..eeec18177861 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -57,8 +57,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
/*
* Addresses to scan
@@ -66,13 +67,12 @@
*/
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(lm87);
+I2C_CLIENT_INSMOD_1(lm87);
/*
* The LM87 registers
@@ -175,6 +175,7 @@ static struct i2c_driver lm87_driver = {
struct lm87_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -537,7 +538,7 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm87_detect);
+ return i2c_probe(adapter, &addr_data, lm87_detect);
}
/*
@@ -553,11 +554,10 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm87_data));
/* The common I2C client data is placed right before the
LM87-specific data. */
@@ -608,6 +608,12 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
data->in_scale[7] = 1875;
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in1_max);
@@ -673,6 +679,8 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -685,7 +693,7 @@ static void lm87_init_client(struct i2c_client *client)
u8 config;
data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
config = lm87_read_value(client, LM87_REG_CONFIG);
if (!(config & 0x01)) {
@@ -719,15 +727,15 @@ static void lm87_init_client(struct i2c_client *client)
static int lm87_detach_client(struct i2c_client *client)
{
+ struct lm87_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index a67dcadf7cb0..83cf2e1b09f5 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -31,7 +31,7 @@
* 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://products.analog.com/products/info.asp?product=ADM1032
+ * 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.
*
@@ -49,7 +49,7 @@
* register values are decoded differently) it is ignored by this
* driver. Complete datasheet can be obtained from Analog's website
* at:
- * http://products.analog.com/products/info.asp?product=ADT7461
+ * http://www.analog.com/en/prod/0,2877,ADT7461,00.html
*
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
@@ -75,27 +75,27 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
/*
* Addresses to scan
* Address is fully defined internally and cannot be changed except for
* MAX6659.
- * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
- * LM89-1, and LM99-1 have address 0x4d.
+ * 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.
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
- * ADT7461 always has address 0x4c.
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
+I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
/*
* The LM90 registers
@@ -200,6 +200,7 @@ static struct i2c_driver lm90_driver = {
struct lm90_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -344,15 +345,79 @@ static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+/* pec used for ADM1032 only */
+static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
+}
+
+static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ long val = simple_strtol(buf, NULL, 10);
+
+ switch (val) {
+ case 0:
+ client->flags &= ~I2C_CLIENT_PEC;
+ break;
+ case 1:
+ client->flags |= I2C_CLIENT_PEC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
+
/*
* Real code
*/
+/* The ADM1032 supports PEC but not on write byte transactions, so we need
+ to explicitely ask for a transaction without PEC. */
+static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
+{
+ return i2c_smbus_xfer(client->adapter, client->addr,
+ client->flags & ~I2C_CLIENT_PEC,
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+}
+
+/* It is assumed that client->update_lock is held (unless we are in
+ detection or initialization steps). This matters when PEC is enabled,
+ because we don't want the address pointer to change between the write
+ byte and the read byte transactions. */
+static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
+{
+ int err;
+
+ if (client->flags & I2C_CLIENT_PEC) {
+ err = adm1032_write_byte(client, reg);
+ if (err >= 0)
+ err = i2c_smbus_read_byte(client);
+ } else
+ err = i2c_smbus_read_byte_data(client, reg);
+
+ if (err < 0) {
+ dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
+ reg, err);
+ return err;
+ }
+ *value = err;
+
+ return 0;
+}
+
static int lm90_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm90_detect);
+ return i2c_probe(adapter, &addr_data, lm90_detect);
}
/*
@@ -369,11 +434,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm90_data));
/* The common I2C client data is placed right before the
LM90-specific data. */
@@ -402,20 +466,22 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind < 0) { /* detection and identification */
u8 man_id, chip_id, reg_config1, reg_convrate;
- man_id = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_MAN_ID);
- chip_id = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CHIP_ID);
- reg_config1 = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONFIG1);
- reg_convrate = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONVRATE);
+ if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
+ &man_id) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
+ &chip_id) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
+ &reg_config1) < 0
+ || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
+ &reg_convrate) < 0)
+ goto exit_free;
if (man_id == 0x01) { /* National Semiconductor */
u8 reg_config2;
- reg_config2 = i2c_smbus_read_byte_data(new_client,
- LM90_REG_R_CONFIG2);
+ if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
+ &reg_config2) < 0)
+ goto exit_free;
if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00
@@ -434,14 +500,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
}
} else
if (man_id == 0x41) { /* Analog Devices */
- if (address == 0x4C
- && (chip_id & 0xF0) == 0x40 /* ADM1032 */
+ if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
&& (reg_config1 & 0x3F) == 0x00
&& reg_convrate <= 0x0A) {
kind = adm1032;
} else
- if (address == 0x4c
- && chip_id == 0x51 /* ADT7461 */
+ if (chip_id == 0x51 /* ADT7461 */
&& (reg_config1 & 0x1F) == 0x00 /* check compat mode */
&& reg_convrate <= 0x0A) {
kind = adt7461;
@@ -476,6 +540,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm90";
} else if (kind == adm1032) {
name = "adm1032";
+ /* The ADM1032 supports PEC, but only if combined
+ transactions are not used. */
+ if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+ new_client->flags |= I2C_CLIENT_PEC;
} else if (kind == lm99) {
name = "lm99";
} else if (kind == lm86) {
@@ -500,6 +568,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
lm90_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&new_client->dev,
@@ -522,8 +596,13 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
&sensor_dev_attr_temp2_crit_hyst.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
+ if (new_client->flags & I2C_CLIENT_PEC)
+ device_create_file(&new_client->dev, &dev_attr_pec);
+
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -539,7 +618,10 @@ static void lm90_init_client(struct i2c_client *client)
*/
i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
5); /* 2 Hz */
- config = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+ if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
+ dev_warn(&client->dev, "Initialization failed!\n");
+ return;
+ }
if (config & 0x40)
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
config & 0xBF); /* run */
@@ -547,15 +629,15 @@ static void lm90_init_client(struct i2c_client *client)
static int lm90_detach_client(struct i2c_client *client)
{
+ struct lm90_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -567,21 +649,15 @@ static struct lm90_data *lm90_update_device(struct device *dev)
down(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
- u8 oldh, newh;
+ u8 oldh, newh, l;
dev_dbg(&client->dev, "Updating lm90 data.\n");
- data->temp8[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_TEMP);
- data->temp8[1] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_LOW);
- data->temp8[2] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_HIGH);
- data->temp8[3] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_CRIT);
- data->temp8[4] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_CRIT);
- data->temp_hyst = i2c_smbus_read_byte_data(client,
- LM90_REG_R_TCRIT_HYST);
+ 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_TCRIT_HYST, &data->temp_hyst);
/*
* There is a trick here. We have to read two registers to
@@ -597,36 +673,20 @@ static struct lm90_data *lm90_update_device(struct device *dev)
* then we have a valid reading. Else we have to read the low
* byte again, and now we believe we have a correct reading.
*/
- oldh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- data->temp11[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
- newh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- if (newh != oldh) {
- data->temp11[0] = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
-#ifdef DEBUG
- oldh = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPH);
- /* oldh is actually newer */
- if (newh != oldh)
- dev_warn(&client->dev, "Remote temperature may be "
- "wrong.\n");
-#endif
- }
- data->temp11[0] |= (newh << 8);
-
- data->temp11[1] = (i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWH) << 8) +
- i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWL);
- data->temp11[2] = (i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_HIGHH) << 8) +
- i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_HIGHL);
- data->alarms = i2c_smbus_read_byte_data(client,
- LM90_REG_R_STATUS);
+ 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;
+ lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
data->last_updated = jiffies;
data->valid = 1;
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 215c8e40ffdd..7a4b3701ed1a 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -44,17 +44,16 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
/* The LM92 and MAX6635 have 2 two-state pins for address selection,
resulting in 4 possible addresses. */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(lm92);
+I2C_CLIENT_INSMOD_1(lm92);
/* The LM92 registers */
#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
@@ -96,6 +95,7 @@ static struct i2c_driver lm92_driver;
/* Client data (each client gets its own) */
struct lm92_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -300,11 +300,10 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
| I2C_FUNC_SMBUS_WORD_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct lm92_data));
/* Fill in enough client fields so that we can read from the chip,
which is required for identication */
@@ -359,6 +358,12 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
lm92_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
@@ -370,6 +375,8 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -380,20 +387,20 @@ static int lm92_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, lm92_detect);
+ return i2c_probe(adapter, &addr_data, lm92_detect);
}
static int lm92_detach_client(struct i2c_client *client)
{
+ struct lm92_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 3c159f1d49ee..6a82ffae1bfd 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -31,20 +31,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
0x4c, 0x4d, 0x4e,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(max1619);
+I2C_CLIENT_INSMOD_1(max1619);
/*
* The MAX1619 registers
@@ -104,6 +103,7 @@ static struct i2c_driver max1619_driver = {
struct max1619_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -179,7 +179,7 @@ static int max1619_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, max1619_detect);
+ return i2c_probe(adapter, &addr_data, max1619_detect);
}
/*
@@ -197,11 +197,10 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct max1619_data));
/* The common I2C client data is placed right before the
MAX1619-specific data. */
@@ -275,6 +274,12 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
max1619_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
@@ -285,6 +290,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -308,15 +315,15 @@ static void max1619_init_client(struct i2c_client *client)
static int max1619_detach_client(struct i2c_client *client)
{
+ struct max1619_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index fa4032d53b79..17f745a23d04 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -38,23 +38,19 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{ NULL }};
static u8 devid;
-static unsigned int extra_isa[3];
+static unsigned short address;
+static unsigned short extra_isa[3];
static u8 confreg[4];
enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .forces = forces,
-};
static int init = 1;
module_param(init, int, 0);
@@ -186,6 +182,7 @@ static inline u8 PWM_TO_REG(int val, int inv)
struct pc87360_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
@@ -224,8 +221,7 @@ struct pc87360_data {
* Functions declaration
*/
-static int pc87360_attach_adapter(struct i2c_adapter *adapter);
-static int pc87360_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pc87360_detect(struct i2c_adapter *adapter);
static int pc87360_detach_client(struct i2c_client *client);
static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
@@ -242,8 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
static struct i2c_driver pc87360_driver = {
.owner = THIS_MODULE,
.name = "pc87360",
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = pc87360_attach_adapter,
+ .attach_adapter = pc87360_detect,
.detach_client = pc87360_detach_client,
};
@@ -251,168 +246,178 @@ static struct i2c_driver pc87360_driver = {
* Sysfs stuff
*/
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
+ FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
+ FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ FAN_DIV_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct pc87360_data *data = i2c_get_clientdata(client);
long fan_min = simple_strtol(buf, NULL, 10);
down(&data->update_lock);
- fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[nr]));
+ fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
/* If it wouldn't fit, change clock divisor */
while (fan_min > 255
- && (data->fan_status[nr] & 0x60) != 0x60) {
+ && (data->fan_status[attr->index] & 0x60) != 0x60) {
fan_min >>= 1;
- data->fan[nr] >>= 1;
- data->fan_status[nr] += 0x20;
+ data->fan[attr->index] >>= 1;
+ data->fan_status[attr->index] += 0x20;
}
- data->fan_min[nr] = fan_min > 255 ? 255 : fan_min;
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(nr),
- data->fan_min[nr]);
+ data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index),
+ data->fan_min[attr->index]);
/* Write new divider, preserve alarm bits */
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(nr),
- data->fan_status[nr] & 0xF9);
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
+ data->fan_status[attr->index] & 0xF9);
up(&data->update_lock);
return count;
}
#define show_and_set_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
- FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
- FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- return set_fan_min(dev, buf, count, offset-1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
- show_fan##offset##_input, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
- show_fan##offset##_min, set_fan##offset##_min); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
- show_fan##offset##_div, NULL); \
-static DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
- show_fan##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
+ show_fan_min, set_fan_min, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+ show_fan_div, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
+ show_fan_status, NULL, offset-1);
show_and_set_fan(1)
show_and_set_fan(2)
show_and_set_fan(3)
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n",
+ PWM_FROM_REG(data->pwm[attr->index],
+ FAN_CONFIG_INVERT(data->fan_conf,
+ attr->index)));
+}
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->pwm[attr->index] = PWM_TO_REG(val,
+ FAN_CONFIG_INVERT(data->fan_conf, attr->index));
+ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
+ data->pwm[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_pwm(offset) \
-static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", \
- PWM_FROM_REG(data->pwm[offset-1], \
- FAN_CONFIG_INVERT(data->fan_conf, \
- offset-1))); \
-} \
-static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->pwm[offset-1] = PWM_TO_REG(val, \
- FAN_CONFIG_INVERT(data->fan_conf, offset-1)); \
- pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(offset-1), \
- data->pwm[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
- show_pwm##offset, set_pwm##offset);
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
+ show_pwm, set_pwm, offset-1);
show_and_set_pwm(1)
show_and_set_pwm(2)
show_and_set_pwm(3)
+static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+ data->in_vref));
+}
+static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
+ data->in_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[attr->index] = IN_TO_REG(val,
+ data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
+ data->in_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
- data->in_vref)); \
-} \
-static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", data->in_status[offset]); \
-} \
-static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_min[offset] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MIN, \
- data->in_min[offset]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_max[offset] = IN_TO_REG(val, \
- data->in_vref); \
- pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MAX, \
- data->in_max[offset]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
- show_in##offset##_input, NULL); \
-static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
- show_in##offset##_max, set_in##offset##_max); \
-static DEVICE_ATTR(in##offset##_status, S_IRUGO, \
- show_in##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in_input, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
+ show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
+ show_in_max, set_in_max, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \
+ show_in_status, NULL, offset);
show_and_set_in(0)
show_and_set_in(1)
show_and_set_in(2)
@@ -425,88 +430,97 @@ show_and_set_in(8)
show_and_set_in(9)
show_and_set_in(10)
+static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+ data->in_vref));
+}
+static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
+ data->in_vref));
+}
+static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
+ data->in_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
+ data->in_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
+ pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
+ data->in_crit[attr->index-11]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_therm(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
- data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%u\n", data->in_status[offset+7]); \
-} \
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_min[offset+7] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MIN, \
- data->in_min[offset+7]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_max[offset+7] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MAX, \
- data->in_max[offset+7]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->in_crit[offset-4] = IN_TO_REG(val, data->in_vref); \
- pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_CRIT, \
- data->in_crit[offset-4]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
- show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
- show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
- show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
- show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_therm_input, NULL, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+ show_therm_min, set_therm_min, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+ show_therm_max, set_therm_max, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+ show_therm_crit, set_therm_crit, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+ show_therm_status, NULL, 11+offset-4);
show_and_set_therm(4)
show_and_set_therm(5)
show_and_set_therm(6)
@@ -539,84 +553,93 @@ static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
+}
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
+}
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
+}
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index]));
+}
+static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87360_data *data = pc87360_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_status[attr->index]);
+}
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
+ data->temp_min[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
+ data->temp_max[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pc87360_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_crit[attr->index] = TEMP_TO_REG(val);
+ pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
+ data->temp_crit[attr->index]);
+ up(&data->update_lock);
+ return count;
+}
+
#define show_and_set_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
-}\
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
-}\
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct pc87360_data *data = pc87360_update_device(dev); \
- return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
-}\
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_min[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MIN, \
- data->temp_min[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_max[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MAX, \
- data->temp_max[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct pc87360_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->temp_crit[offset-1] = TEMP_TO_REG(val); \
- pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_CRIT, \
- data->temp_crit[offset-1]); \
- up(&data->update_lock); \
- return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
- show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
- show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
- show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
- show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+ show_temp_min, set_temp_min, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+ show_temp_max, set_temp_max, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+ show_temp_crit, set_temp_crit, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+ show_temp_status, NULL, offset-1);
show_and_set_temp(1)
show_and_set_temp(2)
show_and_set_temp(3)
@@ -632,12 +655,7 @@ static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
* Device detection, registration and update
*/
-static int pc87360_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_detect(adapter, &addr_data, pc87360_detect);
-}
-
-static int pc87360_find(int sioaddr, u8 *devid, int *address)
+static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
{
u16 val;
int i;
@@ -683,7 +701,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
continue;
}
- address[i] = val;
+ addresses[i] = val;
if (i==0) { /* Fans */
confreg[0] = superio_inb(sioaddr, 0xF0);
@@ -727,9 +745,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
return 0;
}
-/* We don't really care about the address.
- Read from extra_isa instead. */
-int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pc87360_detect(struct i2c_adapter *adapter)
{
int i;
struct i2c_client *new_client;
@@ -738,12 +754,8 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
const char *name = "pc87360";
int use_thermistors = 0;
- if (!i2c_is_isa_adapter(adapter))
- return -ENODEV;
-
- if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
+ if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
return -ENOMEM;
- memset(data, 0x00, sizeof(struct pc87360_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -838,51 +850,57 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
if (data->innr) {
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in6_input);
- device_create_file(&new_client->dev, &dev_attr_in7_input);
- device_create_file(&new_client->dev, &dev_attr_in8_input);
- device_create_file(&new_client->dev, &dev_attr_in9_input);
- device_create_file(&new_client->dev, &dev_attr_in10_input);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in6_min);
- device_create_file(&new_client->dev, &dev_attr_in7_min);
- device_create_file(&new_client->dev, &dev_attr_in8_min);
- device_create_file(&new_client->dev, &dev_attr_in9_min);
- device_create_file(&new_client->dev, &dev_attr_in10_min);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_in6_max);
- device_create_file(&new_client->dev, &dev_attr_in7_max);
- device_create_file(&new_client->dev, &dev_attr_in8_max);
- device_create_file(&new_client->dev, &dev_attr_in9_max);
- device_create_file(&new_client->dev, &dev_attr_in10_max);
- device_create_file(&new_client->dev, &dev_attr_in0_status);
- device_create_file(&new_client->dev, &dev_attr_in1_status);
- device_create_file(&new_client->dev, &dev_attr_in2_status);
- device_create_file(&new_client->dev, &dev_attr_in3_status);
- device_create_file(&new_client->dev, &dev_attr_in4_status);
- device_create_file(&new_client->dev, &dev_attr_in5_status);
- device_create_file(&new_client->dev, &dev_attr_in6_status);
- device_create_file(&new_client->dev, &dev_attr_in7_status);
- device_create_file(&new_client->dev, &dev_attr_in8_status);
- device_create_file(&new_client->dev, &dev_attr_in9_status);
- device_create_file(&new_client->dev, &dev_attr_in10_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
@@ -890,90 +908,92 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->tempnr) {
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_min);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
- device_create_file(&new_client->dev, &dev_attr_temp1_status);
- device_create_file(&new_client->dev, &dev_attr_temp2_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms_temp);
}
if (data->tempnr == 3) {
- device_create_file(&new_client->dev, &dev_attr_temp3_input);
- device_create_file(&new_client->dev, &dev_attr_temp3_min);
- device_create_file(&new_client->dev, &dev_attr_temp3_max);
- device_create_file(&new_client->dev, &dev_attr_temp3_crit);
- device_create_file(&new_client->dev, &dev_attr_temp3_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr);
}
if (data->innr == 14) {
- device_create_file(&new_client->dev, &dev_attr_temp4_input);
- device_create_file(&new_client->dev, &dev_attr_temp5_input);
- device_create_file(&new_client->dev, &dev_attr_temp6_input);
- device_create_file(&new_client->dev, &dev_attr_temp4_min);
- device_create_file(&new_client->dev, &dev_attr_temp5_min);
- device_create_file(&new_client->dev, &dev_attr_temp6_min);
- device_create_file(&new_client->dev, &dev_attr_temp4_max);
- device_create_file(&new_client->dev, &dev_attr_temp5_max);
- device_create_file(&new_client->dev, &dev_attr_temp6_max);
- device_create_file(&new_client->dev, &dev_attr_temp4_crit);
- device_create_file(&new_client->dev, &dev_attr_temp5_crit);
- device_create_file(&new_client->dev, &dev_attr_temp6_crit);
- device_create_file(&new_client->dev, &dev_attr_temp4_status);
- device_create_file(&new_client->dev, &dev_attr_temp5_status);
- device_create_file(&new_client->dev, &dev_attr_temp6_status);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr);
}
if (data->fannr) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) {
device_create_file(&new_client->dev,
- &dev_attr_fan1_input);
+ &sensor_dev_attr_fan1_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_min);
+ &sensor_dev_attr_fan1_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_div);
+ &sensor_dev_attr_fan1_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan1_status);
+ &sensor_dev_attr_fan1_status.dev_attr);
}
if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) {
device_create_file(&new_client->dev,
- &dev_attr_fan2_input);
+ &sensor_dev_attr_fan2_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_min);
+ &sensor_dev_attr_fan2_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_div);
+ &sensor_dev_attr_fan2_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan2_status);
+ &sensor_dev_attr_fan2_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
- device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
- device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
}
if (data->fannr == 3) {
if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
device_create_file(&new_client->dev,
- &dev_attr_fan3_input);
+ &sensor_dev_attr_fan3_input.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_min);
+ &sensor_dev_attr_fan3_min.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_div);
+ &sensor_dev_attr_fan3_div.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_fan3_status);
+ &sensor_dev_attr_fan3_status.dev_attr);
}
if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
- device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
}
return 0;
+ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
for (i = 0; i < 3; i++) {
if (data->address[i]) {
@@ -990,11 +1010,10 @@ static int pc87360_detach_client(struct i2c_client *client)
struct pc87360_data *data = i2c_get_clientdata(client);
int i;
- if ((i = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((i = i2c_detach_client(client)))
return i;
- }
for (i = 0; i < 3; i++) {
if (data->address[i]) {
@@ -1320,23 +1339,23 @@ static int __init pc87360_init(void)
/* Arbitrarily pick one of the addresses */
for (i = 0; i < 3; i++) {
if (extra_isa[i] != 0x0000) {
- normal_isa[0] = extra_isa[i];
+ address = extra_isa[i];
break;
}
}
- if (normal_isa[0] == 0x0000) {
+ if (address == 0x0000) {
printk(KERN_WARNING "pc87360: No active logical device, "
"module not inserted.\n");
return -ENODEV;
}
- return i2c_add_driver(&pc87360_driver);
+ return i2c_isa_add_driver(&pc87360_driver);
}
static void __exit pc87360_exit(void)
{
- i2c_del_driver(&pc87360_driver);
+ i2c_isa_del_driver(&pc87360_driver);
}
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 6bbfc8fb4f13..9c6cadec1087 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -55,7 +55,9 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <asm/io.h>
@@ -68,14 +70,10 @@ module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
-/* Addresses to scan.
+/* Device address
Note that we can't determine the ISA address until we have initialized
our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(sis5595);
+static unsigned short address;
/* Many SIS5595 constants specified below */
@@ -168,6 +166,7 @@ static inline u8 DIV_TO_REG(int val)
allocated. */
struct sis5595_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -190,8 +189,7 @@ struct sis5595_data {
static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter);
-static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detect(struct i2c_adapter *adapter);
static int sis5595_detach_client(struct i2c_client *client);
static int sis5595_read_value(struct i2c_client *client, u8 register);
@@ -202,9 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
static struct i2c_driver sis5595_driver = {
.owner = THIS_MODULE,
.name = "sis5595",
- .id = I2C_DRIVERID_SIS5595,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = sis5595_attach_adapter,
+ .attach_adapter = sis5595_detect,
.detach_client = sis5595_detach_client,
};
@@ -476,14 +472,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* This is called when the module is loaded */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, sis5595_detect);
-}
-
-int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+static int sis5595_detect(struct i2c_adapter *adapter)
{
int err = 0;
int i;
@@ -492,10 +481,6 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
char val;
u16 a;
- /* Make sure we are probing the ISA bus!! */
- if (!i2c_is_isa_adapter(adapter))
- goto exit;
-
if (force_addr)
address = force_addr & ~(SIS5595_EXTENT - 1);
/* Reserve the ISA region */
@@ -533,11 +518,10 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
goto exit_release;
}
- if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_release;
}
- memset(data, 0, sizeof(struct sis5595_data));
new_client = &data->client;
new_client->addr = address;
@@ -578,6 +562,12 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -608,7 +598,9 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
}
return 0;
-
+
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit_release:
@@ -619,18 +611,17 @@ exit:
static int sis5595_detach_client(struct i2c_client *client)
{
+ struct sis5595_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_is_isa_client(client))
- release_region(client->addr, SIS5595_EXTENT);
+ release_region(client->addr, SIS5595_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -745,7 +736,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
{
u16 val;
int *i;
- int addr = 0;
for (i = blacklist; *i != 0; i++) {
struct pci_dev *dev;
@@ -761,22 +751,14 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
pci_read_config_word(dev, SIS5595_BASE_REG, &val))
return -ENODEV;
- addr = val & ~(SIS5595_EXTENT - 1);
- if (addr == 0 && force_addr == 0) {
+ address = val & ~(SIS5595_EXTENT - 1);
+ if (address == 0 && force_addr == 0) {
dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
}
- if (force_addr)
- addr = force_addr; /* so detect will get called */
-
- if (!addr) {
- dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
- return -ENODEV;
- }
- normal_isa[0] = addr;
s_bridge = pci_dev_get(dev);
- if (i2c_add_driver(&sis5595_driver)) {
+ if (i2c_isa_add_driver(&sis5595_driver)) {
pci_dev_put(s_bridge);
s_bridge = NULL;
}
@@ -803,7 +785,7 @@ static void __exit sm_sis5595_exit(void)
{
pci_unregister_driver(&sis5595_pci_driver);
if (s_bridge != NULL) {
- i2c_del_driver(&sis5595_driver);
+ i2c_isa_del_driver(&sis5595_driver);
pci_dev_put(s_bridge);
s_bridge = NULL;
}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 251ac2659554..2a3e21b5b6b4 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -31,23 +31,14 @@
#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47b397 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .probe = normal_i2c, /* cheat */
- .ignore = normal_i2c, /* cheat */
- .forces = forces,
-};
+static unsigned short address;
/* Super-I/0 registers and commands */
@@ -100,6 +91,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
struct smsc47b397_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -215,64 +207,51 @@ sysfs_fan(4);
#define device_create_file_fan(client, num) \
device_create_file(&client->dev, &dev_attr_fan##num##_input)
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
-
-static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, smsc47b397_detect);
-}
-
static int smsc47b397_detach_client(struct i2c_client *client)
{
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, SMSC_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
+static int smsc47b397_detect(struct i2c_adapter *adapter);
+
static struct i2c_driver smsc47b397_driver = {
.owner = THIS_MODULE,
.name = "smsc47b397",
- .id = I2C_DRIVERID_SMSC47B397,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = smsc47b397_attach_adapter,
+ .attach_adapter = smsc47b397_detect,
.detach_client = smsc47b397_detach_client,
};
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int smsc47b397_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct smsc47b397_data *data;
int err = 0;
- if (!i2c_is_isa_adapter(adapter)) {
- return 0;
- }
-
- if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
- dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+ if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+ dev_err(&adapter->dev, "Region 0x%x already in use!\n",
+ address);
return -EBUSY;
}
- if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error_release;
}
- memset(data, 0x00, sizeof(struct smsc47b397_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
- new_client->addr = addr;
+ new_client->addr = address;
init_MUTEX(&data->lock);
new_client->adapter = adapter;
new_client->driver = &smsc47b397_driver;
@@ -285,6 +264,12 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
if ((err = i2c_attach_client(new_client)))
goto error_free;
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
device_create_file_temp(new_client, 1);
device_create_file_temp(new_client, 2);
device_create_file_temp(new_client, 3);
@@ -297,21 +282,23 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
- kfree(new_client);
+ kfree(data);
error_release:
- release_region(addr, SMSC_EXTENT);
+ release_region(address, SMSC_EXTENT);
return err;
}
-static int __init smsc47b397_find(unsigned int *addr)
+static int __init smsc47b397_find(unsigned short *addr)
{
u8 id, rev;
superio_enter();
id = superio_inb(SUPERIO_REG_DEVID);
- if (id != 0x6f) {
+ if ((id != 0x6f) && (id != 0x81)) {
superio_exit();
return -ENODEV;
}
@@ -322,8 +309,9 @@ static int __init smsc47b397_find(unsigned int *addr)
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
| superio_inb(SUPERIO_REG_BASE_LSB);
- printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
- "(base address 0x%04x, revision %u)\n", *addr, rev);
+ printk(KERN_INFO "smsc47b397: found SMSC %s "
+ "(base address 0x%04x, revision %u)\n",
+ id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
superio_exit();
return 0;
@@ -333,15 +321,15 @@ static int __init smsc47b397_init(void)
{
int ret;
- if ((ret = smsc47b397_find(normal_isa)))
+ if ((ret = smsc47b397_find(&address)))
return ret;
- return i2c_add_driver(&smsc47b397_driver);
+ return i2c_isa_add_driver(&smsc47b397_driver);
}
static void __exit smsc47b397_exit(void)
{
- i2c_del_driver(&smsc47b397_driver);
+ i2c_isa_del_driver(&smsc47b397_driver);
}
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 897117a7213f..5905c1af88f2 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -2,8 +2,8 @@
smsc47m1.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
- Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
- Super-I/O chips.
+ Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
+ LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -30,21 +30,14 @@
#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47m1 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .forces = forces,
-};
+static unsigned short address;
/* Super-I/0 registers and commands */
@@ -108,6 +101,7 @@ superio_exit(void)
struct smsc47m1_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -121,9 +115,7 @@ struct smsc47m1_data {
};
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
-static int smsc47m1_find(int *address);
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detect(struct i2c_adapter *adapter);
static int smsc47m1_detach_client(struct i2c_client *client);
static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
@@ -136,9 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static struct i2c_driver smsc47m1_driver = {
.owner = THIS_MODULE,
.name = "smsc47m1",
- .id = I2C_DRIVERID_SMSC47M1,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = smsc47m1_attach_adapter,
+ .attach_adapter = smsc47m1_detect,
.detach_client = smsc47m1_detach_client,
};
@@ -354,14 +344,7 @@ fan_present(2);
static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, smsc47m1_detect);
-}
-
-static int smsc47m1_find(int *address)
+static int __init smsc47m1_find(unsigned short *addr)
{
u8 val;
@@ -373,6 +356,8 @@ static int smsc47m1_find(int *address)
* 0x5F) and LPC47B27x (device id 0x51) have fan control.
* The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
* can do much more besides (device id 0x60).
+ * The LPC47M997 is undocumented, but seems to be compatible with
+ * the LPC47M192, and has the same device id.
*/
if (val == 0x51)
printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
@@ -381,17 +366,18 @@ static int smsc47m1_find(int *address)
else if (val == 0x5F)
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
else if (val == 0x60)
- printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
+ printk(KERN_INFO "smsc47m1: Found SMSC "
+ "LPC47M15x/LPC47M192/LPC47M997\n");
else {
superio_exit();
return -ENODEV;
}
superio_select();
- *address = (superio_inb(SUPERIO_REG_BASE) << 8)
- | superio_inb(SUPERIO_REG_BASE + 1);
+ *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+ | superio_inb(SUPERIO_REG_BASE + 1);
val = superio_inb(SUPERIO_REG_ACT);
- if (*address == 0 || (val & 0x01) == 0) {
+ if (*addr == 0 || (val & 0x01) == 0) {
printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
superio_exit();
return -ENODEV;
@@ -401,27 +387,22 @@ static int smsc47m1_find(int *address)
return 0;
}
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+static int smsc47m1_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct smsc47m1_data *data;
int err = 0;
int fan1, fan2, pwm1, pwm2;
- if (!i2c_is_isa_adapter(adapter)) {
- return 0;
- }
-
if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
}
- if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error_release;
}
- memset(data, 0x00, sizeof(struct smsc47m1_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -461,6 +442,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
function. */
smsc47m1_update_device(&new_client->dev, 1);
+ /* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto error_detach;
+ }
+
if (fan1) {
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -494,8 +482,10 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+error_detach:
+ i2c_detach_client(new_client);
error_free:
- kfree(new_client);
+ kfree(data);
error_release:
release_region(address, SMSC_EXTENT);
return err;
@@ -503,16 +493,16 @@ error_release:
static int smsc47m1_detach_client(struct i2c_client *client)
{
+ struct smsc47m1_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, SMSC_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -573,16 +563,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static int __init sm_smsc47m1_init(void)
{
- if (smsc47m1_find(normal_isa)) {
+ if (smsc47m1_find(&address)) {
return -ENODEV;
}
- return i2c_add_driver(&smsc47m1_driver);
+ return i2c_isa_add_driver(&smsc47m1_driver);
}
static void __exit sm_smsc47m1_exit(void)
{
- i2c_del_driver(&smsc47m1_driver);
+ i2c_isa_del_driver(&smsc47m1_driver);
}
MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 164d47948390..6f696f897176 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -35,26 +35,24 @@
#include <linux/pci.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <asm/io.h>
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static unsigned short force_addr = 0;
+static unsigned short force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
-/* Addresses to scan.
+/* Device address
Note that we can't determine the ISA address until we have initialized
our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(via686a);
+static unsigned short address;
/*
The Via 686a southbridge has a LM78-like chip integrated on the same IC.
@@ -200,7 +198,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
but the function is very linear in the useful range (0-80 deg C), so
we'll just use linear interpolation for 10-bit readings.) So, tempLUT
is the temp at via register values 0-255: */
-static const long tempLUT[] =
+static const s16 tempLUT[] =
{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@@ -272,7 +270,7 @@ static inline u8 TEMP_TO_REG(long val)
}
/* for 8-bit temperature hyst and over registers */
-#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
+#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
/* for 10-bit temperature readings */
static inline long TEMP_FROM_REG10(u16 val)
@@ -297,6 +295,7 @@ static inline long TEMP_FROM_REG10(u16 val)
via686a client is allocated. */
struct via686a_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -315,8 +314,7 @@ struct via686a_data {
static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
-static int via686a_attach_adapter(struct i2c_adapter *adapter);
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
+static int via686a_detect(struct i2c_adapter *adapter);
static int via686a_detach_client(struct i2c_client *client);
static inline int via686a_read_value(struct i2c_client *client, u8 reg)
@@ -576,22 +574,13 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static struct i2c_driver via686a_driver = {
.owner = THIS_MODULE,
.name = "via686a",
- .id = I2C_DRIVERID_VIA686A,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = via686a_attach_adapter,
+ .attach_adapter = via686a_detect,
.detach_client = via686a_detach_client,
};
/* This is called when the module is loaded */
-static int via686a_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, via686a_detect);
-}
-
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
+static int via686a_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct via686a_data *data;
@@ -599,18 +588,9 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
const char client_name[] = "via686a";
u16 val;
- /* Make sure we are probing the ISA bus!! */
- if (!i2c_is_isa_adapter(adapter)) {
- dev_err(&adapter->dev,
- "via686a_detect called for an I2C bus adapter?!?\n");
- return 0;
- }
-
/* 8231 requires multiple of 256, we enforce that on 686 as well */
- if (force_addr)
- address = force_addr & 0xFF00;
-
if (force_addr) {
+ address = force_addr & 0xFF00;
dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
address);
if (PCIBIOS_SUCCESSFUL !=
@@ -621,11 +601,17 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
return -ENODEV;
if (!(val & 0x0001)) {
- dev_warn(&adapter->dev, "enabling sensors\n");
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
- val | 0x0001))
+ if (force_addr) {
+ dev_info(&adapter->dev, "enabling sensors\n");
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+ val | 0x0001))
+ return -ENODEV;
+ } else {
+ dev_warn(&adapter->dev, "sensors disabled - enable "
+ "with force_addr=0x%x\n", address);
return -ENODEV;
+ }
}
/* Reserve the ISA region */
@@ -635,11 +621,10 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
return -ENODEV;
}
- if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
err = -ENOMEM;
- goto ERROR0;
+ goto exit_release;
}
- memset(data, 0, sizeof(struct via686a_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -655,12 +640,18 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
- goto ERROR3;
+ goto exit_free;
/* Initialize the VIA686A chip */
via686a_init_client(new_client);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -695,30 +686,31 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
-ERROR3:
+exit_detach:
+ i2c_detach_client(new_client);
+exit_free:
kfree(data);
-ERROR0:
+exit_release:
release_region(address, VIA686A_EXTENT);
return err;
}
static int via686a_detach_client(struct i2c_client *client)
{
+ struct via686a_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, VIA686A_EXTENT);
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
-/* Called when we have found a new VIA686A. Set limits, etc. */
static void via686a_init_client(struct i2c_client *client)
{
u8 reg;
@@ -810,29 +802,20 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 val;
- int addr = 0;
if (PCIBIOS_SUCCESSFUL !=
pci_read_config_word(dev, VIA686A_BASE_REG, &val))
return -ENODEV;
- addr = val & ~(VIA686A_EXTENT - 1);
- if (addr == 0 && force_addr == 0) {
+ address = val & ~(VIA686A_EXTENT - 1);
+ if (address == 0 && force_addr == 0) {
dev_err(&dev->dev, "base address not set - upgrade BIOS "
"or use force_addr=0xaddr\n");
return -ENODEV;
}
- if (force_addr)
- addr = force_addr; /* so detect will get called */
-
- if (!addr) {
- dev_err(&dev->dev, "No Via 686A sensors found.\n");
- return -ENODEV;
- }
- normal_isa[0] = addr;
s_bridge = pci_dev_get(dev);
- if (i2c_add_driver(&via686a_driver)) {
+ if (i2c_isa_add_driver(&via686a_driver)) {
pci_dev_put(s_bridge);
s_bridge = NULL;
}
@@ -859,7 +842,7 @@ static void __exit sm_via686a_exit(void)
{
pci_unregister_driver(&via686a_pci_driver);
if (s_bridge != NULL) {
- i2c_del_driver(&via686a_driver);
+ i2c_isa_del_driver(&via686a_driver);
pci_dev_put(s_bridge);
s_bridge = NULL;
}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 8a40b6976e1a..eee22a57e929 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -9,6 +9,9 @@
Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
in testing and debugging this driver.
+ This driver also supports the W83627EHG, which is the lead-free
+ version of the W83627EHF.
+
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
@@ -37,17 +40,14 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
-/* Addresses to scan
- The actual ISA address is read from Super-I/O configuration space */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(w83627ehf);
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
/*
* Super-I/O constants and functions
@@ -105,7 +105,9 @@ superio_exit(void)
* ISA constants
*/
-#define REGION_LENGTH 8
+#define REGION_ALIGNMENT ~7
+#define REGION_OFFSET 5
+#define REGION_LENGTH 2
#define ADDR_REG_OFFSET 5
#define DATA_REG_OFFSET 6
@@ -174,6 +176,7 @@ temp1_to_reg(int temp)
struct w83627ehf_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
struct semaphore update_lock;
@@ -666,25 +669,22 @@ static void w83627ehf_init_client(struct i2c_client *client)
}
}
-static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+static int w83627ehf_detect(struct i2c_adapter *adapter)
{
struct i2c_client *client;
struct w83627ehf_data *data;
int i, err = 0;
- if (!i2c_is_isa_adapter(adapter))
- return 0;
-
- if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+ if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
+ w83627ehf_driver.name)) {
err = -EBUSY;
goto exit;
}
- if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit_release;
}
- memset(data, 0, sizeof(struct w83627ehf_data));
client = &data->client;
i2c_set_clientdata(client, data);
@@ -720,6 +720,12 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
data->has_fan |= (1 << 4);
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
device_create_file(&client->dev, &dev_attr_fan1_input);
device_create_file(&client->dev, &dev_attr_fan1_min);
device_create_file(&client->dev, &dev_attr_fan1_div);
@@ -753,32 +759,27 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+exit_detach:
+ i2c_detach_client(client);
exit_free:
kfree(data);
exit_release:
- release_region(address, REGION_LENGTH);
+ release_region(address + REGION_OFFSET, REGION_LENGTH);
exit:
return err;
}
-static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, w83627ehf_detect);
-}
-
static int w83627ehf_detach_client(struct i2c_client *client)
{
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- release_region(client->addr, REGION_LENGTH);
- kfree(i2c_get_clientdata(client));
+ release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
+ kfree(data);
return 0;
}
@@ -786,12 +787,11 @@ static int w83627ehf_detach_client(struct i2c_client *client)
static struct i2c_driver w83627ehf_driver = {
.owner = THIS_MODULE,
.name = "w83627ehf",
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = w83627ehf_attach_adapter,
+ .attach_adapter = w83627ehf_detect,
.detach_client = w83627ehf_detach_client,
};
-static int __init w83627ehf_find(int sioaddr, int *address)
+static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
{
u16 val;
@@ -809,8 +809,8 @@ static int __init w83627ehf_find(int sioaddr, int *address)
superio_select(W83627EHF_LD_HWM);
val = (superio_inb(SIO_REG_ADDR) << 8)
| superio_inb(SIO_REG_ADDR + 1);
- *address = val & ~(REGION_LENGTH - 1);
- if (*address == 0) {
+ *addr = val & REGION_ALIGNMENT;
+ if (*addr == 0) {
superio_exit();
return -ENODEV;
}
@@ -826,16 +826,16 @@ static int __init w83627ehf_find(int sioaddr, int *address)
static int __init sensors_w83627ehf_init(void)
{
- if (w83627ehf_find(0x2e, &normal_isa[0])
- && w83627ehf_find(0x4e, &normal_isa[0]))
+ if (w83627ehf_find(0x2e, &address)
+ && w83627ehf_find(0x4e, &address))
return -ENODEV;
- return i2c_add_driver(&w83627ehf_driver);
+ return i2c_isa_add_driver(&w83627ehf_driver);
}
static void __exit sensors_w83627ehf_exit(void)
{
- i2c_del_driver(&w83627ehf_driver);
+ i2c_isa_del_driver(&w83627ehf_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bd87a42e068a..70ef926c3bd8 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -42,8 +42,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
@@ -56,12 +58,15 @@ module_param(force_i2c, byte, 0);
MODULE_PARM_DESC(force_i2c,
"Initialize the i2c address of the sensors");
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
/* Insmod parameters */
-SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
static int init = 1;
module_param(init, bool, 0);
@@ -137,10 +142,14 @@ superio_exit(void)
#define WINB_BASE_REG 0x60
/* Constants specified below */
-/* Length of ISA address segment */
-#define WINB_EXTENT 8
+/* Alignment of the base address */
+#define WINB_ALIGNMENT ~7
+
+/* Offset & size of I/O region we are interested in */
+#define WINB_REGION_OFFSET 5
+#define WINB_REGION_SIZE 2
-/* Where are the ISA address/data registers relative to the base address */
+/* Where are the sensors address/data registers relative to the base address */
#define W83781D_ADDR_REG_OFFSET 5
#define W83781D_DATA_REG_OFFSET 6
@@ -192,7 +201,6 @@ superio_exit(void)
#define W83627HF_REG_PWM1 0x5A
#define W83627HF_REG_PWM2 0x5B
-#define W83627HF_REG_PWMCLK12 0x5C
#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */
#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */
@@ -277,6 +285,7 @@ static inline u8 DIV_TO_REG(long val)
dynamically allocated, at the same time when a new client is allocated. */
struct w83627hf_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -314,9 +323,7 @@ struct w83627hf_data {
};
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
-static int w83627hf_detect(struct i2c_adapter *adapter, int address,
- int kind);
+static int w83627hf_detect(struct i2c_adapter *adapter);
static int w83627hf_detach_client(struct i2c_client *client);
static int w83627hf_read_value(struct i2c_client *client, u16 register);
@@ -328,9 +335,7 @@ static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
.owner = THIS_MODULE,
.name = "w83627hf",
- .id = I2C_DRIVERID_W83627HF,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = w83627hf_attach_adapter,
+ .attach_adapter = w83627hf_detect,
.detach_client = w83627hf_detach_client,
};
@@ -959,16 +964,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
-/* This function is called when:
- * w83627hf_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and w83627hf_driver is still present) */
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
-{
- return i2c_detect(adapter, &addr_data, w83627hf_detect);
-}
-
-static int w83627hf_find(int sioaddr, int *address)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr)
{
u16 val;
@@ -988,36 +984,29 @@ static int w83627hf_find(int sioaddr, int *address)
superio_select(W83627HF_LD_HWM);
val = (superio_inb(WINB_BASE_REG) << 8) |
superio_inb(WINB_BASE_REG + 1);
- *address = val & ~(WINB_EXTENT - 1);
- if (*address == 0 && force_addr == 0) {
+ *addr = val & WINB_ALIGNMENT;
+ if (*addr == 0 && force_addr == 0) {
superio_exit();
return -ENODEV;
}
- if (force_addr)
- *address = force_addr; /* so detect will get called */
superio_exit();
return 0;
}
-int w83627hf_detect(struct i2c_adapter *adapter, int address,
- int kind)
+static int w83627hf_detect(struct i2c_adapter *adapter)
{
- int val;
+ int val, kind;
struct i2c_client *new_client;
struct w83627hf_data *data;
int err = 0;
const char *client_name = "";
- if (!i2c_is_isa_adapter(adapter)) {
- err = -ENODEV;
- goto ERROR0;
- }
-
if(force_addr)
- address = force_addr & ~(WINB_EXTENT - 1);
+ address = force_addr & WINB_ALIGNMENT;
- if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
+ if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
+ w83627hf_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -1056,11 +1045,10 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
client structure, even though we cannot fill it completely yet.
But it allows us to access w83627hf_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct w83627hf_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -1102,6 +1090,12 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+
device_create_file_in(new_client, 0);
if (kind != w83697hf)
device_create_file_in(new_client, 1);
@@ -1152,26 +1146,28 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
return 0;
+ ERROR3:
+ i2c_detach_client(new_client);
ERROR2:
kfree(data);
ERROR1:
- release_region(address, WINB_EXTENT);
+ release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
ERROR0:
return err;
}
static int w83627hf_detach_client(struct i2c_client *client)
{
+ struct w83627hf_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- release_region(client->addr, WINB_EXTENT);
- kfree(i2c_get_clientdata(client));
+ release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
+ kfree(data);
return 0;
}
@@ -1282,7 +1278,6 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
return 0;
}
-/* Called when we have found a new W83781D. It should set limits, etc. */
static void w83627hf_init_client(struct i2c_client *client)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
@@ -1290,7 +1285,15 @@ static void w83627hf_init_client(struct i2c_client *client)
int type = data->type;
u8 tmp;
- if(init) {
+ if (reset) {
+ /* Resetting the chip has been the default for a long time,
+ but repeatedly caused problems (fans going to full
+ speed...) so it is now optional. It might even go away if
+ nobody reports it as being useful, as I see very little
+ reason why this would be needed at all. */
+ dev_info(&client->dev, "If reset=1 solved a problem you were "
+ "having, please report!\n");
+
/* save this register */
i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
/* Reset all except Watchdog values and last conversion values
@@ -1327,7 +1330,7 @@ static void w83627hf_init_client(struct i2c_client *client)
data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
} else {
/* Convert VID to voltage based on default VRM */
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
}
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
@@ -1368,12 +1371,6 @@ static void w83627hf_init_client(struct i2c_client *client)
}
}
- if (type == w83627hf) {
- /* enable PWM2 control (can't hurt since PWM reg
- should have been reset to 0xff) */
- w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
- 0x19);
- }
/* enable comparator mode for temp2 and temp3 so
alarm indication will work correctly */
i = w83627hf_read_value(client, W83781D_REG_IRQ);
@@ -1485,20 +1482,17 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
static int __init sensors_w83627hf_init(void)
{
- int addr;
-
- if (w83627hf_find(0x2e, &addr)
- && w83627hf_find(0x4e, &addr)) {
+ if (w83627hf_find(0x2e, &address)
+ && w83627hf_find(0x4e, &address)) {
return -ENODEV;
}
- normal_isa[0] = addr;
- return i2c_add_driver(&w83627hf_driver);
+ return i2c_isa_add_driver(&w83627hf_driver);
}
static void __exit sensors_w83627hf_exit(void)
{
- i2c_del_driver(&w83627hf_driver);
+ i2c_isa_del_driver(&w83627hf_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 0bb131ce09eb..9265f32122fa 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -38,8 +38,10 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
#include <asm/io.h>
#include "lm75.h"
@@ -47,10 +49,10 @@
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
/* Insmod parameters */
-SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
@@ -218,6 +220,7 @@ DIV_TO_REG(long val, enum chips type)
allocated. */
struct w83781d_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore lock;
enum chips type;
@@ -255,6 +258,7 @@ struct w83781d_data {
};
static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_isa_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);
@@ -273,6 +277,14 @@ static struct i2c_driver w83781d_driver = {
.detach_client = w83781d_detach_client,
};
+static struct i2c_driver w83781d_isa_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83781d-isa",
+ .attach_adapter = w83781d_isa_attach_adapter,
+ .detach_client = w83781d_detach_client,
+};
+
+
/* following are the sysfs callback functions */
#define show_in_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
@@ -856,7 +868,13 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, w83781d_detect);
+ return i2c_probe(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+ return w83781d_detect(adapter, isa_address, -1);
}
/* Assumes that adapter is of I2C, not ISA variety.
@@ -871,12 +889,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
const char *client_name = "";
struct w83781d_data *data = i2c_get_clientdata(new_client);
- data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[0])) {
err = -ENOMEM;
goto ERROR_SC_0;
}
- memset(data->lm75[0], 0x00, sizeof (struct i2c_client));
id = i2c_adapter_id(adapter);
@@ -901,13 +918,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
}
if (kind != w83783s) {
-
- data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!(data->lm75[1])) {
err = -ENOMEM;
goto ERROR_SC_1;
}
- memset(data->lm75[1], 0x0, sizeof(struct i2c_client));
if (force_subclients[0] == id &&
force_subclients[1] == address) {
@@ -961,10 +976,10 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
ERROR_SC_3:
i2c_detach_client(data->lm75[0]);
ERROR_SC_2:
- if (NULL != data->lm75[1])
+ if (data->lm75[1])
kfree(data->lm75[1]);
ERROR_SC_1:
- if (NULL != data->lm75[0])
+ if (data->lm75[0])
kfree(data->lm75[0]);
ERROR_SC_0:
return err;
@@ -999,7 +1014,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa)
if (!request_region(address, W83781D_EXTENT,
- w83781d_driver.name)) {
+ w83781d_isa_driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
@@ -1046,18 +1061,17 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
client structure, even though we cannot fill it completely yet.
But it allows us to access w83781d_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
- memset(data, 0, sizeof(struct w83781d_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
init_MUTEX(&data->lock);
new_client->adapter = adapter;
- new_client->driver = &w83781d_driver;
+ new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. */
@@ -1189,6 +1203,12 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
data->pwmenable[i] = 1;
/* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR4;
+ }
+
device_create_file_in(new_client, 0);
if (kind != w83783s)
device_create_file_in(new_client, 1);
@@ -1241,6 +1261,15 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
+ERROR4:
+ 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]);
+ }
ERROR3:
i2c_detach_client(new_client);
ERROR2:
@@ -1255,24 +1284,26 @@ ERROR0:
static int
w83781d_detach_client(struct i2c_client *client)
{
+ struct w83781d_data *data = i2c_get_clientdata(client);
int err;
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
if (i2c_is_isa_client(client))
release_region(client->addr, W83781D_EXTENT);
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
- if (i2c_get_clientdata(client)==NULL) {
- /* subclients */
+ /* main client */
+ if (data)
+ kfree(data);
+
+ /* subclient */
+ else
kfree(client);
- } else {
- /* main client */
- kfree(i2c_get_clientdata(client));
- }
return 0;
}
@@ -1416,7 +1447,6 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
return 0;
}
-/* Called when we have found a new W83781D. It should set limits, etc. */
static void
w83781d_init_client(struct i2c_client *client)
{
@@ -1443,7 +1473,7 @@ w83781d_init_client(struct i2c_client *client)
w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
}
- data->vrm = i2c_which_vrm();
+ data->vrm = vid_which_vrm();
if ((type != w83781d) && (type != as99127f)) {
tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1613,12 +1643,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
static int __init
sensors_w83781d_init(void)
{
- return i2c_add_driver(&w83781d_driver);
+ int res;
+
+ res = i2c_add_driver(&w83781d_driver);
+ if (res)
+ return res;
+
+ res = i2c_isa_add_driver(&w83781d_isa_driver);
+ if (res) {
+ i2c_del_driver(&w83781d_driver);
+ return res;
+ }
+
+ return 0;
}
static void __exit
sensors_w83781d_exit(void)
{
+ i2c_isa_del_driver(&w83781d_isa_driver);
i2c_del_driver(&w83781d_driver);
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
new file mode 100644
index 000000000000..4be59dbb78c4
--- /dev/null
+++ b/drivers/hwmon/w83792d.c
@@ -0,0 +1,1646 @@
+/*
+ w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (C) 2004, 2005 Winbond Electronics Corp.
+ Chunhao Huang <DZShen@Winbond.com.tw>,
+ Rudolf Marek <r.marek@sh.cvut.cz>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Note:
+ 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver.
+ 2. This driver is only for Winbond W83792D C version device, there
+ are also some motherboards with B version W83792D device. The
+ calculation method to in6-in7(measured value, limits) is a little
+ different between C and B version. C or B version can be identified
+ by CR[0x49h].
+*/
+
+/*
+ Supports following chips:
+
+ Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ w83792d 9 7 7 3 0x7a 0x5ca3 yes no
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83792d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+ "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force chip initialization");
+
+/* The W83792D registers */
+static const u8 W83792D_REG_IN[9] = {
+ 0x20, /* Vcore A in DataSheet */
+ 0x21, /* Vcore B in DataSheet */
+ 0x22, /* VIN0 in DataSheet */
+ 0x23, /* VIN1 in DataSheet */
+ 0x24, /* VIN2 in DataSheet */
+ 0x25, /* VIN3 in DataSheet */
+ 0x26, /* 5VCC in DataSheet */
+ 0xB0, /* 5VSB in DataSheet */
+ 0xB1 /* VBAT in DataSheet */
+};
+#define W83792D_REG_LOW_BITS1 0x3E /* Low Bits I in DataSheet */
+#define W83792D_REG_LOW_BITS2 0x3F /* Low Bits II in DataSheet */
+static const u8 W83792D_REG_IN_MAX[9] = {
+ 0x2B, /* Vcore A High Limit in DataSheet */
+ 0x2D, /* Vcore B High Limit in DataSheet */
+ 0x2F, /* VIN0 High Limit in DataSheet */
+ 0x31, /* VIN1 High Limit in DataSheet */
+ 0x33, /* VIN2 High Limit in DataSheet */
+ 0x35, /* VIN3 High Limit in DataSheet */
+ 0x37, /* 5VCC High Limit in DataSheet */
+ 0xB4, /* 5VSB High Limit in DataSheet */
+ 0xB6 /* VBAT High Limit in DataSheet */
+};
+static const u8 W83792D_REG_IN_MIN[9] = {
+ 0x2C, /* Vcore A Low Limit in DataSheet */
+ 0x2E, /* Vcore B Low Limit in DataSheet */
+ 0x30, /* VIN0 Low Limit in DataSheet */
+ 0x32, /* VIN1 Low Limit in DataSheet */
+ 0x34, /* VIN2 Low Limit in DataSheet */
+ 0x36, /* VIN3 Low Limit in DataSheet */
+ 0x38, /* 5VCC Low Limit in DataSheet */
+ 0xB5, /* 5VSB Low Limit in DataSheet */
+ 0xB7 /* VBAT Low Limit in DataSheet */
+};
+static const u8 W83792D_REG_FAN[7] = {
+ 0x28, /* FAN 1 Count in DataSheet */
+ 0x29, /* FAN 2 Count in DataSheet */
+ 0x2A, /* FAN 3 Count in DataSheet */
+ 0xB8, /* FAN 4 Count in DataSheet */
+ 0xB9, /* FAN 5 Count in DataSheet */
+ 0xBA, /* FAN 6 Count in DataSheet */
+ 0xBE /* FAN 7 Count in DataSheet */
+};
+static const u8 W83792D_REG_FAN_MIN[7] = {
+ 0x3B, /* FAN 1 Count Low Limit in DataSheet */
+ 0x3C, /* FAN 2 Count Low Limit in DataSheet */
+ 0x3D, /* FAN 3 Count Low Limit in DataSheet */
+ 0xBB, /* FAN 4 Count Low Limit in DataSheet */
+ 0xBC, /* FAN 5 Count Low Limit in DataSheet */
+ 0xBD, /* FAN 6 Count Low Limit in DataSheet */
+ 0xBF /* FAN 7 Count Low Limit in DataSheet */
+};
+#define W83792D_REG_FAN_CFG 0x84 /* FAN Configuration in DataSheet */
+static const u8 W83792D_REG_FAN_DIV[4] = {
+ 0x47, /* contains FAN2 and FAN1 Divisor */
+ 0x5B, /* contains FAN4 and FAN3 Divisor */
+ 0x5C, /* contains FAN6 and FAN5 Divisor */
+ 0x9E /* contains FAN7 Divisor. */
+};
+static const u8 W83792D_REG_PWM[7] = {
+ 0x81, /* FAN 1 Duty Cycle, be used to control */
+ 0x83, /* FAN 2 Duty Cycle, be used to control */
+ 0x94, /* FAN 3 Duty Cycle, be used to control */
+ 0xA3, /* FAN 4 Duty Cycle, be used to control */
+ 0xA4, /* FAN 5 Duty Cycle, be used to control */
+ 0xA5, /* FAN 6 Duty Cycle, be used to control */
+ 0xA6 /* FAN 7 Duty Cycle, be used to control */
+};
+#define W83792D_REG_BANK 0x4E
+#define W83792D_REG_TEMP2_CONFIG 0xC2
+#define W83792D_REG_TEMP3_CONFIG 0xCA
+
+static const u8 W83792D_REG_TEMP1[3] = {
+ 0x27, /* TEMP 1 in DataSheet */
+ 0x39, /* TEMP 1 Over in DataSheet */
+ 0x3A, /* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83792D_REG_TEMP_ADD[2][6] = {
+ { 0xC0, /* TEMP 2 in DataSheet */
+ 0xC1, /* TEMP 2(0.5 deg) in DataSheet */
+ 0xC5, /* TEMP 2 Over High part in DataSheet */
+ 0xC6, /* TEMP 2 Over Low part in DataSheet */
+ 0xC3, /* TEMP 2 Thyst High part in DataSheet */
+ 0xC4 }, /* TEMP 2 Thyst Low part in DataSheet */
+ { 0xC8, /* TEMP 3 in DataSheet */
+ 0xC9, /* TEMP 3(0.5 deg) in DataSheet */
+ 0xCD, /* TEMP 3 Over High part in DataSheet */
+ 0xCE, /* TEMP 3 Over Low part in DataSheet */
+ 0xCB, /* TEMP 3 Thyst High part in DataSheet */
+ 0xCC } /* TEMP 3 Thyst Low part in DataSheet */
+};
+
+static const u8 W83792D_REG_THERMAL[3] = {
+ 0x85, /* SmartFanI: Fan1 target value */
+ 0x86, /* SmartFanI: Fan2 target value */
+ 0x96 /* SmartFanI: Fan3 target value */
+};
+
+static const u8 W83792D_REG_TOLERANCE[3] = {
+ 0x87, /* (bit3-0)SmartFan Fan1 tolerance */
+ 0x87, /* (bit7-4)SmartFan Fan2 tolerance */
+ 0x97 /* (bit3-0)SmartFan Fan3 tolerance */
+};
+
+static const u8 W83792D_REG_POINTS[3][4] = {
+ { 0x85, /* SmartFanII: Fan1 temp point 1 */
+ 0xE3, /* SmartFanII: Fan1 temp point 2 */
+ 0xE4, /* SmartFanII: Fan1 temp point 3 */
+ 0xE5 }, /* SmartFanII: Fan1 temp point 4 */
+ { 0x86, /* SmartFanII: Fan2 temp point 1 */
+ 0xE6, /* SmartFanII: Fan2 temp point 2 */
+ 0xE7, /* SmartFanII: Fan2 temp point 3 */
+ 0xE8 }, /* SmartFanII: Fan2 temp point 4 */
+ { 0x96, /* SmartFanII: Fan3 temp point 1 */
+ 0xE9, /* SmartFanII: Fan3 temp point 2 */
+ 0xEA, /* SmartFanII: Fan3 temp point 3 */
+ 0xEB } /* SmartFanII: Fan3 temp point 4 */
+};
+
+static const u8 W83792D_REG_LEVELS[3][4] = {
+ { 0x88, /* (bit3-0) SmartFanII: Fan1 Non-Stop */
+ 0x88, /* (bit7-4) SmartFanII: Fan1 Level 1 */
+ 0xE0, /* (bit7-4) SmartFanII: Fan1 Level 2 */
+ 0xE0 }, /* (bit3-0) SmartFanII: Fan1 Level 3 */
+ { 0x89, /* (bit3-0) SmartFanII: Fan2 Non-Stop */
+ 0x89, /* (bit7-4) SmartFanII: Fan2 Level 1 */
+ 0xE1, /* (bit7-4) SmartFanII: Fan2 Level 2 */
+ 0xE1 }, /* (bit3-0) SmartFanII: Fan2 Level 3 */
+ { 0x98, /* (bit3-0) SmartFanII: Fan3 Non-Stop */
+ 0x98, /* (bit7-4) SmartFanII: Fan3 Level 1 */
+ 0xE2, /* (bit7-4) SmartFanII: Fan3 Level 2 */
+ 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */
+};
+
+#define W83792D_REG_CONFIG 0x40
+#define W83792D_REG_VID_FANDIV 0x47
+#define W83792D_REG_CHIPID 0x49
+#define W83792D_REG_WCHIPID 0x58
+#define W83792D_REG_CHIPMAN 0x4F
+#define W83792D_REG_PIN 0x4B
+#define W83792D_REG_I2C_SUBADDR 0x4A
+
+#define W83792D_REG_ALARM1 0xA9 /* realtime status register1 */
+#define W83792D_REG_ALARM2 0xAA /* realtime status register2 */
+#define W83792D_REG_ALARM3 0xAB /* realtime status register3 */
+#define W83792D_REG_CHASSIS 0x42 /* Bit 5: Case Open status bit */
+#define W83792D_REG_CHASSIS_CLR 0x44 /* Bit 7: Case Open CLR_CHS/Reset bit */
+
+/* control in0/in1 's limit modifiability */
+#define W83792D_REG_VID_IN_B 0x17
+
+#define W83792D_REG_VBAT 0x5D
+#define W83792D_REG_I2C_ADDR 0x48
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ Fixing this is just not worth it. */
+#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
+ ((((nr)==6)||((nr)==7))?(val*6):(val*4)))
+#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
+ ((((nr)==6)||((nr)==7))?(val/6):(val/4)))
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 255;
+ rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+ return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \
+ ((val) == 255 ? 0 : \
+ 1350000 / ((val) * (div))))
+
+/* for temp1 */
+#define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+ : (val)) / 1000, 0, 0xff))
+#define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+/* for temp2 and temp3, because they need addtional resolution */
+#define TEMP_ADD_FROM_REG(val1, val2) \
+ ((((val1) & 0x80 ? (val1)-0x100 \
+ : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
+#define TEMP_ADD_TO_REG_HIGH(val) \
+ (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+ : (val)) / 1000, 0, 0xff))
+#define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00)
+
+#define PWM_FROM_REG(val) (val)
+#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
+#define DIV_FROM_REG(val) (1 << (val))
+
+static inline u8
+DIV_TO_REG(long val)
+{
+ int i;
+ val = SENSORS_LIMIT(val, 1, 128) >> 1;
+ for (i = 0; i < 6; i++) {
+ if (val == 0)
+ break;
+ val >>= 1;
+ }
+ return ((u8) i);
+}
+
+struct w83792d_data {
+ struct i2c_client client;
+ struct class_device *class_dev;
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ /* array of 2 pointers to subclients */
+ struct i2c_client *lm75[2];
+
+ u8 in[9]; /* Register value */
+ u8 in_max[9]; /* Register value */
+ u8 in_min[9]; /* Register value */
+ u8 low_bits[2]; /* Additional resolution to voltage in0-6 */
+ u8 fan[7]; /* Register value */
+ u8 fan_min[7]; /* Register value */
+ u8 temp1[3]; /* current, over, thyst */
+ u8 temp_add[2][6]; /* Register value */
+ u8 fan_div[7]; /* Register encoding, shifted right */
+ u8 pwm[7]; /* We only consider the first 3 set of pwm,
+ although 792 chip has 7 set of pwm. */
+ u8 pwmenable[3];
+ u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */
+ u32 alarms; /* realtime status register encoding,combined */
+ u8 chassis; /* Chassis status */
+ u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */
+ u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */
+ u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */
+ u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */
+ u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */
+};
+
+static int w83792d_attach_adapter(struct i2c_adapter *adapter);
+static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83792d_detach_client(struct i2c_client *client);
+
+static int w83792d_read_value(struct i2c_client *client, u8 register);
+static int w83792d_write_value(struct i2c_client *client, u8 register,
+ u8 value);
+static struct w83792d_data *w83792d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
+#endif
+
+static void w83792d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83792d_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83792d",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = w83792d_attach_adapter,
+ .detach_client = w83792d_detach_client,
+};
+
+static long in_count_from_reg(int nr, struct w83792d_data *data)
+{
+ u16 vol_count = data->in[nr];
+ u16 low_bits = 0;
+ vol_count = (vol_count << 2);
+ switch (nr)
+ {
+ case 0: /* vin0 */
+ low_bits = (data->low_bits[0]) & 0x03;
+ break;
+ case 1: /* vin1 */
+ low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
+ break;
+ case 2: /* vin2 */
+ low_bits = ((data->low_bits[0]) & 0x30) >> 4;
+ break;
+ case 3: /* vin3 */
+ low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
+ break;
+ case 4: /* vin4 */
+ low_bits = (data->low_bits[1]) & 0x03;
+ break;
+ case 5: /* vin5 */
+ low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
+ break;
+ case 6: /* vin6 */
+ low_bits = ((data->low_bits[1]) & 0x30) >> 4;
+ default:
+ break;
+ }
+ vol_count = vol_count | low_bits;
+ return vol_count;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
+}
+
+#define show_in_reg(reg) \
+static ssize_t show_##reg(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 w83792d_data *data = w83792d_update_device(dev); \
+ return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \
+}
+
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+ int nr = sensor_attr->index; \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83792d_data *data = i2c_get_clientdata(client); \
+ u32 val; \
+ \
+ val = simple_strtoul(buf, NULL, 10); \
+ data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
+ w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+ \
+ return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_reg(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \
+ NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, store_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, store_in_max, offset);
+
+sysfs_in_reg(0);
+sysfs_in_reg(1);
+sysfs_in_reg(2);
+sysfs_in_reg(3);
+sysfs_in_reg(4);
+sysfs_in_reg(5);
+sysfs_in_reg(6);
+sysfs_in_reg(7);
+sysfs_in_reg(8);
+
+#define device_create_file_in(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \
+} while (0)
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (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 - 1; \
+ struct w83792d_data *data = w83792d_update_device(dev); \
+ return sprintf(buf,"%d\n", \
+ FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
+ data->fan_min[nr]);
+
+ return count;
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+ determined in part by the fan divisor. This follows the principle of
+ least suprise; the user doesn't expect the fan minimum to change just
+ because the divisor changed. */
+static ssize_t
+store_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ unsigned long min;
+ /*u8 reg;*/
+ u8 fan_div_reg = 0;
+ u8 tmp_fan_div;
+
+ /* Save fan_min */
+ min = FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr]));
+
+ data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+ fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
+ fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8;
+ tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70)
+ : ((data->fan_div[nr]) & 0x07);
+ w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1],
+ fan_div_reg | tmp_fan_div);
+
+ /* Restore fan_min */
+ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+ w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+ return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+ offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, store_fan_div, offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, store_fan_min, offset);
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+sysfs_fan(5);
+sysfs_fan(6);
+sysfs_fan(7);
+
+#define device_create_file_fan(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature1, includes measured value and limits */
+
+static ssize_t show_temp1(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 w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ s32 val;
+
+ val = simple_strtol(buf, NULL, 10);
+
+ data->temp1[nr] = TEMP1_TO_REG(val);
+ w83792d_write_value(client, W83792D_REG_TEMP1[nr],
+ data->temp1[nr]);
+
+ return count;
+}
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1,
+ store_temp1, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1,
+ store_temp1, 2);
+
+#define device_create_file_temp1(client) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature2-3, includes measured value and limits */
+
+static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf,"%ld\n",
+ (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index],
+ data->temp_add[nr][index+1]));
+}
+
+static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ s32 val;
+
+ val = simple_strtol(buf, NULL, 10);
+
+ data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
+ data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
+ w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index],
+ data->temp_add[nr][index]);
+ w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1],
+ data->temp_add[nr][index+1]);
+
+ return count;
+}
+
+#define sysfs_temp23(name,idx) \
+static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \
+ idx, 0); \
+static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \
+ show_temp23, store_temp23, idx, 2); \
+static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp23, store_temp23, idx, 4);
+
+sysfs_temp23(temp2,0)
+sysfs_temp23(temp3,1)
+
+#define device_create_file_temp_add(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \
+device_create_file(&client->dev, \
+&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \
+} while (0)
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->alarms);
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+
+
+
+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 w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1]));
+}
+
+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 - 1;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ long pwm_enable_tmp = 1;
+
+ switch (data->pwmenable[nr]) {
+ case 0:
+ pwm_enable_tmp = 1; /* manual mode */
+ break;
+ case 1:
+ pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */
+ break;
+ case 2:
+ pwm_enable_tmp = 2; /* Smart Fan II */
+ break;
+ }
+
+ return sprintf(buf, "%ld\n", pwm_enable_tmp);
+}
+
+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);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->pwm[nr] = PWM_TO_REG(val);
+ w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+
+ return count;
+}
+
+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);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
+
+ val = simple_strtoul(buf, NULL, 10);
+ switch (val) {
+ case 1:
+ data->pwmenable[nr] = 0; /* manual mode */
+ break;
+ case 2:
+ data->pwmenable[nr] = 2; /* Smart Fan II */
+ break;
+ case 3:
+ data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */
+ break;
+ default:
+ return -EINVAL;
+ }
+ cfg1_tmp = data->pwmenable[0];
+ cfg2_tmp = (data->pwmenable[1]) << 2;
+ cfg3_tmp = (data->pwmenable[2]) << 4;
+ cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
+ fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
+ w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
+
+ return count;
+}
+
+#define sysfs_pwm(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm, store_pwm, offset); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+ show_pwmenable, store_pwmenable, offset); \
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwm(3);
+
+
+#define device_create_file_pwm(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \
+} while (0)
+
+#define device_create_file_pwmenable(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_pwm_mode(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 w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_mode[nr-1]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 pwm_mode_mask = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
+ pwm_mode_mask = w83792d_read_value(client,
+ W83792D_REG_PWM[nr]) & 0x7f;
+ w83792d_write_value(client, W83792D_REG_PWM[nr],
+ ((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
+
+ return count;
+}
+
+#define sysfs_pwm_mode(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \
+ show_pwm_mode, store_pwm_mode, offset);
+
+sysfs_pwm_mode(1);
+sysfs_pwm_mode(2);
+sysfs_pwm_mode(3);
+
+#define device_create_file_pwm_mode(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_regs_chassis(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->chassis);
+}
+
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+
+#define device_create_file_chassis(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis); \
+} while (0)
+
+
+static ssize_t
+show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n", data->chassis_clear);
+}
+
+static ssize_t
+store_chassis_clear(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 temp1 = 0, temp2 = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
+ temp1 = ((data->chassis_clear) << 7) & 0x80;
+ temp2 = w83792d_read_value(client,
+ W83792D_REG_CHASSIS_CLR) & 0x7f;
+ w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
+
+ return count;
+}
+
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+ show_chassis_clear, store_chassis_clear);
+
+#define device_create_file_chassis_clear(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis_clear); \
+} while (0)
+
+
+
+/* For Smart Fan I / Thermal Cruise */
+static ssize_t
+show_thermal_cruise(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 w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]);
+}
+
+static ssize_t
+store_thermal_cruise(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 target_tmp=0, target_mask=0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ target_tmp = val;
+ target_tmp = target_tmp & 0x7f;
+ target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
+ data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
+ w83792d_write_value(client, W83792D_REG_THERMAL[nr],
+ (data->thermal_cruise[nr]) | target_mask);
+
+ return count;
+}
+
+#define sysfs_thermal_cruise(offset) \
+static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \
+ show_thermal_cruise, store_thermal_cruise, offset);
+
+sysfs_thermal_cruise(1);
+sysfs_thermal_cruise(2);
+sysfs_thermal_cruise(3);
+
+#define device_create_file_thermal_cruise(client, offset) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_thermal_cruise##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan I/Thermal Cruise and Smart Fan II */
+static ssize_t
+show_tolerance(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 w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]);
+}
+
+static ssize_t
+store_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);
+ int nr = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 tol_tmp, tol_mask;
+
+ val = simple_strtoul(buf, NULL, 10);
+ tol_mask = w83792d_read_value(client,
+ W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
+ tol_tmp = SENSORS_LIMIT(val, 0, 15);
+ tol_tmp &= 0x0f;
+ data->tolerance[nr] = tol_tmp;
+ if (nr == 1) {
+ tol_tmp <<= 4;
+ }
+ w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
+ tol_mask | tol_tmp);
+
+ return count;
+}
+
+#define sysfs_tolerance(offset) \
+static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \
+ show_tolerance, store_tolerance, offset);
+
+sysfs_tolerance(1);
+sysfs_tolerance(2);
+sysfs_tolerance(3);
+
+#define device_create_file_tolerance(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan II */
+static ssize_t
+show_sf2_point(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]);
+}
+
+static ssize_t
+store_sf2_point(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr - 1;
+ int index = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 mask_tmp = 0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
+ mask_tmp = w83792d_read_value(client,
+ W83792D_REG_POINTS[index][nr]) & 0x80;
+ w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
+ mask_tmp|data->sf2_points[index][nr]);
+
+ return count;
+}
+
+#define sysfs_sf2_point(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \
+ show_sf2_point, store_sf2_point, offset, index);
+
+sysfs_sf2_point(1, 1); /* Fan1 */
+sysfs_sf2_point(2, 1); /* Fan1 */
+sysfs_sf2_point(3, 1); /* Fan1 */
+sysfs_sf2_point(4, 1); /* Fan1 */
+sysfs_sf2_point(1, 2); /* Fan2 */
+sysfs_sf2_point(2, 2); /* Fan2 */
+sysfs_sf2_point(3, 2); /* Fan2 */
+sysfs_sf2_point(4, 2); /* Fan2 */
+sysfs_sf2_point(1, 3); /* Fan3 */
+sysfs_sf2_point(2, 3); /* Fan3 */
+sysfs_sf2_point(3, 3); /* Fan3 */
+sysfs_sf2_point(4, 3); /* Fan3 */
+
+#define device_create_file_sf2_point(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_sf2_level(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83792d_data *data = w83792d_update_device(dev);
+ return sprintf(buf, "%d\n",
+ (((data->sf2_levels[index-1][nr]) * 100) / 15));
+}
+
+static ssize_t
+store_sf2_level(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index - 1;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ u32 val;
+ u8 mask_tmp=0, level_tmp=0;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
+ mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
+ & ((nr==3) ? 0xf0 : 0x0f);
+ if (nr==3) {
+ level_tmp = data->sf2_levels[index][nr];
+ } else {
+ level_tmp = data->sf2_levels[index][nr] << 4;
+ }
+ w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+
+ return count;
+}
+
+#define sysfs_sf2_level(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \
+ show_sf2_level, store_sf2_level, offset, index);
+
+sysfs_sf2_level(1, 1); /* Fan1 */
+sysfs_sf2_level(2, 1); /* Fan1 */
+sysfs_sf2_level(3, 1); /* Fan1 */
+sysfs_sf2_level(1, 2); /* Fan2 */
+sysfs_sf2_level(2, 2); /* Fan2 */
+sysfs_sf2_level(3, 2); /* Fan2 */
+sysfs_sf2_level(1, 3); /* Fan3 */
+sysfs_sf2_level(2, 3); /* Fan3 */
+sysfs_sf2_level(3, 3); /* Fan3 */
+
+#define device_create_file_sf2_level(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+/* This function is called when:
+ * w83792d_driver is inserted (when this module is loaded), for each
+ available adapter
+ * when a new adapter is inserted (and w83792d_driver is still present) */
+static int
+w83792d_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, w83792d_detect);
+}
+
+
+static int
+w83792d_create_subclient(struct i2c_adapter *adapter,
+ struct i2c_client *new_client, int addr,
+ struct i2c_client **sub_cli)
+{
+ int err;
+ struct i2c_client *sub_client;
+
+ (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!(sub_client)) {
+ return -ENOMEM;
+ }
+ sub_client->addr = 0x48 + addr;
+ i2c_set_clientdata(sub_client, NULL);
+ sub_client->adapter = adapter;
+ sub_client->driver = &w83792d_driver;
+ sub_client->flags = 0;
+ strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE);
+ if ((err = i2c_attach_client(sub_client))) {
+ dev_err(&new_client->dev, "subclient registration "
+ "at address 0x%x failed\n", sub_client->addr);
+ kfree(sub_client);
+ return err;
+ }
+ return 0;
+}
+
+
+static int
+w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
+ struct i2c_client *new_client)
+{
+ int i, id, err;
+ u8 val;
+ struct w83792d_data *data = i2c_get_clientdata(new_client);
+
+ id = i2c_adapter_id(adapter);
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48 ||
+ force_subclients[i] > 0x4f) {
+ dev_err(&new_client->dev, "invalid subclient "
+ "address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ err = -ENODEV;
+ goto ERROR_SC_0;
+ }
+ }
+ w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) << 4));
+ }
+
+ val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
+ if (!(val & 0x08)) {
+ err = w83792d_create_subclient(adapter, new_client, val & 0x7,
+ &data->lm75[0]);
+ if (err < 0)
+ goto ERROR_SC_0;
+ }
+ if (!(val & 0x80)) {
+ if ((data->lm75[0] != NULL) &&
+ ((val & 0x7) == ((val >> 4) & 0x7))) {
+ dev_err(&new_client->dev, "duplicate addresses 0x%x, "
+ "use force_subclient\n", data->lm75[0]->addr);
+ err = -ENODEV;
+ goto ERROR_SC_1;
+ }
+ err = w83792d_create_subclient(adapter, new_client,
+ (val >> 4) & 0x7, &data->lm75[1]);
+ if (err < 0)
+ goto ERROR_SC_1;
+ }
+
+ return 0;
+
+/* Undo inits in case of errors */
+
+ERROR_SC_1:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ERROR_SC_0:
+ return err;
+}
+
+
+static int
+w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int i = 0, val1 = 0, val2;
+ struct i2c_client *new_client;
+ struct w83792d_data *data;
+ int err = 0;
+ const char *client_name = "";
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ goto ERROR0;
+ }
+
+ /* 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 w83792d_{read,write}_value. */
+
+ if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ init_MUTEX(&data->lock);
+ new_client->adapter = adapter;
+ new_client->driver = &w83792d_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ /* The w83792d 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 (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) {
+ dev_warn(&new_client->dev, "Detection failed at step "
+ "3\n");
+ goto ERROR1;
+ }
+ val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
+ val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+ /* Check for Winbond ID if in bank 0 */
+ if (!(val1 & 0x07)) { /* is Bank0 */
+ if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
+ ((val1 & 0x80) && (val2 != 0x5c))) {
+ goto ERROR1;
+ }
+ }
+ /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
+ should match */
+ if (w83792d_read_value(new_client,
+ W83792D_REG_I2C_ADDR) != address) {
+ dev_warn(&new_client->dev, "Detection failed "
+ "at step 5\n");
+ goto ERROR1;
+ }
+ }
+
+ /* 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 */
+ w83792d_write_value(new_client,
+ W83792D_REG_BANK,
+ (w83792d_read_value(new_client,
+ W83792D_REG_BANK) & 0x78) | 0x80);
+
+ /* Determine the chip type. */
+ if (kind <= 0) {
+ /* get vendor ID */
+ val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+ if (val2 != 0x5c) { /* the vendor is NOT Winbond */
+ goto ERROR1;
+ }
+ val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
+ if (val1 == 0x7a && address >= 0x2c) {
+ kind = w83792d;
+ } else {
+ if (kind == 0)
+ dev_warn(&new_client->dev,
+ "w83792d: Ignoring 'force' parameter for"
+ " unknown chip at adapter %d, address"
+ " 0x%02x\n", i2c_adapter_id(adapter),
+ address);
+ goto ERROR1;
+ }
+ }
+
+ if (kind == w83792d) {
+ client_name = "w83792d";
+ } else {
+ dev_err(&new_client->dev, "w83792d: Internal error: unknown"
+ " kind (%d)?!?", kind);
+ goto ERROR1;
+ }
+
+ /* 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->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR1;
+
+ if ((err = w83792d_detect_subclients(adapter, address,
+ kind, new_client)))
+ goto ERROR2;
+
+ /* Initialize the chip */
+ w83792d_init_client(new_client);
+
+ /* A few vars need to be filled upon startup */
+ for (i = 1; i <= 7; i++) {
+ data->fan_min[i - 1] = w83792d_read_value(new_client,
+ W83792D_REG_FAN_MIN[i]);
+ }
+
+ /* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto ERROR3;
+ }
+ device_create_file_in(new_client, 0);
+ device_create_file_in(new_client, 1);
+ device_create_file_in(new_client, 2);
+ device_create_file_in(new_client, 3);
+ device_create_file_in(new_client, 4);
+ device_create_file_in(new_client, 5);
+ device_create_file_in(new_client, 6);
+ device_create_file_in(new_client, 7);
+ device_create_file_in(new_client, 8);
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ device_create_file_fan(new_client, 3);
+ device_create_file_fan(new_client, 4);
+ device_create_file_fan(new_client, 5);
+ device_create_file_fan(new_client, 6);
+ device_create_file_fan(new_client, 7);
+
+ device_create_file_temp1(new_client); /* Temp1 */
+ device_create_file_temp_add(new_client, 2); /* Temp2 */
+ device_create_file_temp_add(new_client, 3); /* Temp3 */
+
+ device_create_file_alarms(new_client);
+
+ device_create_file_pwm(new_client, 1);
+ device_create_file_pwm(new_client, 2);
+ device_create_file_pwm(new_client, 3);
+
+ device_create_file_pwmenable(new_client, 1);
+ device_create_file_pwmenable(new_client, 2);
+ device_create_file_pwmenable(new_client, 3);
+
+ device_create_file_pwm_mode(new_client, 1);
+ device_create_file_pwm_mode(new_client, 2);
+ device_create_file_pwm_mode(new_client, 3);
+
+ device_create_file_chassis(new_client);
+ device_create_file_chassis_clear(new_client);
+
+ device_create_file_thermal_cruise(new_client, 1);
+ device_create_file_thermal_cruise(new_client, 2);
+ device_create_file_thermal_cruise(new_client, 3);
+
+ device_create_file_tolerance(new_client, 1);
+ device_create_file_tolerance(new_client, 2);
+ device_create_file_tolerance(new_client, 3);
+
+ device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */
+ device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */
+ device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */
+ device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */
+
+ device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */
+ device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */
+ device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */
+ device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */
+ device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */
+
+ return 0;
+
+ERROR3:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ if (data->lm75[1] != NULL) {
+ i2c_detach_client(data->lm75[1]);
+ kfree(data->lm75[1]);
+ }
+ERROR2:
+ i2c_detach_client(new_client);
+ERROR1:
+ kfree(data);
+ERROR0:
+ return err;
+}
+
+static int
+w83792d_detach_client(struct i2c_client *client)
+{
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ int err;
+
+ /* main client */
+ if (data)
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ /* main client */
+ if (data)
+ kfree(data);
+ /* subclient */
+ else
+ kfree(client);
+
+ return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+ bank switches. ISA access must always be locked explicitly!
+ We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
+ would slow down the W83792D access and should not be necessary.
+ There are some ugly typecasts here, but the good news is - they should
+ nowhere else be necessary! */
+static int
+w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+ int res=0;
+ res = i2c_smbus_read_byte_data(client, reg);
+
+ return res;
+}
+
+static int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ i2c_smbus_write_byte_data(client, reg, value);
+ return 0;
+}
+
+static void
+w83792d_init_client(struct i2c_client *client)
+{
+ u8 temp2_cfg, temp3_cfg, vid_in_b;
+
+ if (init) {
+ w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
+ }
+ /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
+ W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
+ vin0/vin1 can be modified by user;
+ W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
+ vin0/vin1 auto-updated, can NOT be modified by user. */
+ vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
+ w83792d_write_value(client, W83792D_REG_VID_IN_B,
+ vid_in_b & 0xbf);
+
+ temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG);
+ temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG);
+ w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG,
+ temp2_cfg & 0xe6);
+ w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG,
+ temp3_cfg & 0xe6);
+
+ /* Start monitoring */
+ w83792d_write_value(client, W83792D_REG_CONFIG,
+ (w83792d_read_value(client,
+ W83792D_REG_CONFIG) & 0xf7)
+ | 0x01);
+}
+
+static struct w83792d_data *w83792d_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83792d_data *data = i2c_get_clientdata(client);
+ int i, j;
+ u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
+
+ down(&data->update_lock);
+
+ if (time_after
+ (jiffies - data->last_updated, (unsigned long) (HZ * 3))
+ || time_before(jiffies, data->last_updated) || !data->valid) {
+ dev_dbg(dev, "Starting device update\n");
+
+ /* Update the voltages measured value and limits */
+ for (i = 0; i < 9; i++) {
+ data->in[i] = w83792d_read_value(client,
+ W83792D_REG_IN[i]);
+ data->in_max[i] = w83792d_read_value(client,
+ W83792D_REG_IN_MAX[i]);
+ data->in_min[i] = w83792d_read_value(client,
+ W83792D_REG_IN_MIN[i]);
+ }
+ data->low_bits[0] = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS1);
+ data->low_bits[1] = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS2);
+ for (i = 0; i < 7; i++) {
+ /* Update the Fan measured value and limits */
+ data->fan[i] = w83792d_read_value(client,
+ W83792D_REG_FAN[i]);
+ data->fan_min[i] = w83792d_read_value(client,
+ W83792D_REG_FAN_MIN[i]);
+ /* Update the PWM/DC Value and PWM/DC flag */
+ pwm_array_tmp[i] = w83792d_read_value(client,
+ W83792D_REG_PWM[i]);
+ data->pwm[i] = pwm_array_tmp[i] & 0x0f;
+ data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+ }
+
+ reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
+ data->pwmenable[0] = reg_tmp & 0x03;
+ data->pwmenable[1] = (reg_tmp>>2) & 0x03;
+ data->pwmenable[2] = (reg_tmp>>4) & 0x03;
+
+ for (i = 0; i < 3; i++) {
+ data->temp1[i] = w83792d_read_value(client,
+ W83792D_REG_TEMP1[i]);
+ }
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 6; j++) {
+ data->temp_add[i][j] = w83792d_read_value(
+ client,W83792D_REG_TEMP_ADD[i][j]);
+ }
+ }
+
+ /* Update the Fan Divisor */
+ for (i = 0; i < 4; i++) {
+ reg_array_tmp[i] = w83792d_read_value(client,
+ W83792D_REG_FAN_DIV[i]);
+ }
+ data->fan_div[0] = reg_array_tmp[0] & 0x07;
+ data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
+ data->fan_div[2] = reg_array_tmp[1] & 0x07;
+ data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
+ data->fan_div[4] = reg_array_tmp[2] & 0x07;
+ data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
+ data->fan_div[6] = reg_array_tmp[3] & 0x07;
+
+ /* Update the realtime status */
+ data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
+ (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
+ (w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
+
+ /* Update CaseOpen status and it's CLR_CHS. */
+ data->chassis = (w83792d_read_value(client,
+ W83792D_REG_CHASSIS) >> 5) & 0x01;
+ data->chassis_clear = (w83792d_read_value(client,
+ W83792D_REG_CHASSIS_CLR) >> 7) & 0x01;
+
+ /* Update Thermal Cruise/Smart Fan I target value */
+ for (i = 0; i < 3; i++) {
+ data->thermal_cruise[i] =
+ w83792d_read_value(client,
+ W83792D_REG_THERMAL[i]) & 0x7f;
+ }
+
+ /* Update Smart Fan I/II tolerance */
+ reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]);
+ data->tolerance[0] = reg_tmp & 0x0f;
+ data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+ data->tolerance[2] = w83792d_read_value(client,
+ W83792D_REG_TOLERANCE[2]) & 0x0f;
+
+ /* Update Smart Fan II temperature points */
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 4; j++) {
+ data->sf2_points[i][j] = w83792d_read_value(
+ client,W83792D_REG_POINTS[i][j]) & 0x7f;
+ }
+ }
+
+ /* Update Smart Fan II duty cycle levels */
+ for (i = 0; i < 3; i++) {
+ reg_tmp = w83792d_read_value(client,
+ W83792D_REG_LEVELS[i][0]);
+ data->sf2_levels[i][0] = reg_tmp & 0x0f;
+ data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
+ reg_tmp = w83792d_read_value(client,
+ W83792D_REG_LEVELS[i][2]);
+ data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
+ data->sf2_levels[i][3] = reg_tmp & 0x0f;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+#ifdef DEBUG
+ w83792d_print_debug(data, dev);
+#endif
+
+ return data;
+}
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
+{
+ int i=0, j=0;
+ dev_dbg(dev, "==========The following is the debug message...========\n");
+ dev_dbg(dev, "9 set of Voltages: =====>\n");
+ for (i=0; i<9; i++) {
+ dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]);
+ dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
+ dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
+ }
+ dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
+ dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+ dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
+ for (i=0; i<7; i++) {
+ dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
+ dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
+ dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]);
+ dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]);
+ }
+ dev_dbg(dev, "3 set of Temperatures: =====>\n");
+ for (i=0; i<3; i++) {
+ dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]);
+ }
+
+ for (i=0; i<2; i++) {
+ for (j=0; j<6; j++) {
+ dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j,
+ data->temp_add[i][j]);
+ }
+ }
+
+ for (i=0; i<7; i++) {
+ dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
+ }
+ dev_dbg(dev, "==========End of the debug message...==================\n");
+ dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init
+sensors_w83792d_init(void)
+{
+ return i2c_add_driver(&w83792d_driver);
+}
+
+static void __exit
+sensors_w83792d_exit(void)
+{
+ i2c_del_driver(&w83792d_driver);
+}
+
+MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>");
+MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83792d_init);
+module_exit(sensors_w83792d_exit);
+
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 4469d52aba4c..f495b6378668 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -36,7 +36,9 @@
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
/* How many retries on register read error */
#define MAX_RETRIES 5
@@ -47,13 +49,12 @@
*/
static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
-SENSORS_INSMOD_1(w83l785ts);
+I2C_CLIENT_INSMOD_1(w83l785ts);
/*
* The W83L785TS-S registers
@@ -73,7 +74,7 @@ SENSORS_INSMOD_1(w83l785ts);
* The W83L785TS-S uses signed 8-bit values.
*/
-#define TEMP_FROM_REG(val) ((val & 0x80 ? val-0x100 : val) * 1000)
+#define TEMP_FROM_REG(val) ((val) * 1000)
/*
* Functions declaration
@@ -105,32 +106,30 @@ static struct i2c_driver w83l785ts_driver = {
struct w83l785ts_data {
struct i2c_client client;
+ struct class_device *class_dev;
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* registers values */
- u8 temp, temp_over;
+ s8 temp[2]; /* 0: input
+ 1: critical limit */
};
/*
* Sysfs stuff
*/
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct w83l785ts_data *data = w83l785ts_update_device(dev);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83l785ts_data *data = w83l785ts_update_device(dev);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
-}
-
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
-static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
/*
* Real code
@@ -140,7 +139,7 @@ static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
- return i2c_detect(adapter, &addr_data, w83l785ts_detect);
+ return i2c_probe(adapter, &addr_data, w83l785ts_detect);
}
/*
@@ -157,12 +156,10 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
- if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct w83l785ts_data));
-
/* The common I2C client data is placed right before the
* W83L785TS-specific data. */
@@ -227,7 +224,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
init_MUTEX(&data->update_lock);
/* Default values in case the first read fails (unlikely). */
- data->temp_over = data->temp = 0;
+ data->temp[1] = data->temp[0] = 0;
/* Tell the I2C layer a new client has arrived. */
if ((err = i2c_attach_client(new_client)))
@@ -239,11 +236,21 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ data->class_dev = hwmon_device_register(&new_client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
return 0;
+exit_detach:
+ i2c_detach_client(new_client);
exit_free:
kfree(data);
exit:
@@ -252,15 +259,15 @@ exit:
static int w83l785ts_detach_client(struct i2c_client *client)
{
+ struct w83l785ts_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client)))
return err;
- }
- kfree(i2c_get_clientdata(client));
+ kfree(data);
return 0;
}
@@ -296,10 +303,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
dev_dbg(&client->dev, "Updating w83l785ts data.\n");
- data->temp = w83l785ts_read_value(client,
- W83L785TS_REG_TEMP, data->temp);
- data->temp_over = w83l785ts_read_value(client,
- W83L785TS_REG_TEMP_OVER, data->temp_over);
+ data->temp[0] = w83l785ts_read_value(client,
+ W83L785TS_REG_TEMP, data->temp[0]);
+ data->temp[1] = w83l785ts_read_value(client,
+ W83L785TS_REG_TEMP_OVER, data->temp[1]);
data->last_updated = jiffies;
data->valid = 1;
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index cd170395a8c7..71c5a854ac5d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -4,12 +4,8 @@
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
-obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
obj-y += busses/ chips/ algos/
-i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
-
-
ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index fb5b732238ed..df05df1a0ef6 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -519,8 +519,6 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_bit_algo = {
- .name = "Bit-shift algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = bit_xfer,
.functionality = bit_func,
};
@@ -541,8 +539,6 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
-
- adap->id |= i2c_bit_algo.id;
adap->algo = &i2c_bit_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index e6cae39f47aa..2db7bfc85225 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -713,8 +713,6 @@ static u32 iic_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm iic_algo = {
- .name = "ITE IIC algorithm",
- .id = I2C_ALGO_IIC,
.master_xfer = iic_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = iic_func,
@@ -738,8 +736,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
adap->name));
/* register new adapter to i2c module... */
-
- adap->id |= iic_algo.id;
adap->algo = &iic_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index cc3a952401f2..82946acab4c7 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -34,7 +34,7 @@
#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
-static int i2c_debug=0;
+static int i2c_debug;
#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
#define pca_inw(adap, reg) adap->read_byte(adap, reg)
@@ -187,12 +187,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
int numbytes = 0;
int state;
int ret;
+ int timeout = 100;
- state = pca_status(adap);
- if ( state != 0xF8 ) {
- dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
- /* FIXME: what to do. Force stop ? */
- return -EREMOTEIO;
+ while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+ msleep(10);
+ }
+ if (state != 0xf8) {
+ dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
+ return -EIO;
}
DEB1("{{{ XFER %d messages\n", num);
@@ -354,8 +356,6 @@ static int pca_init(struct i2c_algo_pca_data *adap)
}
static struct i2c_algorithm pca_algo = {
- .name = "PCA9564 algorithm",
- .id = I2C_ALGO_PCA,
.master_xfer = pca_xfer,
.functionality = pca_func,
};
@@ -369,8 +369,6 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
int rval;
/* register new adapter to i2c module... */
-
- adap->id |= pca_algo.id;
adap->algo = &pca_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 8d087dac32af..6e498df1f717 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -459,8 +459,6 @@ static u32 pcf_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm pcf_algo = {
- .name = "PCF8584 algorithm",
- .id = I2C_ALGO_PCF,
.master_xfer = pcf_xfer,
.functionality = pcf_func,
};
@@ -476,8 +474,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
-
- adap->id |= pcf_algo.id;
adap->algo = &pcf_algo;
adap->timeout = 100; /* default values, should */
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index 422721b241e5..932c4fa86c73 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -149,7 +149,7 @@ static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
err = i2c_write(adap, p->buf, p->len);
}
- return err;
+ return (err < 0) ? err : i;
}
static u32 sgi_func(struct i2c_adapter *adap)
@@ -158,8 +158,6 @@ static u32 sgi_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm sgi_algo = {
- .name = "SGI algorithm",
- .id = I2C_ALGO_SGI,
.master_xfer = sgi_xfer,
.functionality = sgi_func,
};
@@ -169,7 +167,6 @@ static struct i2c_algorithm sgi_algo = {
*/
int i2c_sgi_add_bus(struct i2c_adapter *adap)
{
- adap->id |= sgi_algo.id;
adap->algo = &sgi_algo;
return i2c_add_adapter(adap);
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index f2785499237b..938848ae162d 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -42,7 +42,7 @@
/* module parameters:
*/
-static int bit_scan=0; /* have a look at what's hanging 'round */
+static int bit_scan; /* have a look at what's hanging 'round */
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
@@ -135,8 +135,6 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_sibyte_algo = {
- .name = "SiByte algorithm",
- .id = I2C_ALGO_SIBYTE,
.smbus_xfer = smbus_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = bit_func,
@@ -151,8 +149,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
/* register new adapter to i2c module... */
-
- i2c_adap->id |= i2c_sibyte_algo.id;
i2c_adap->algo = &i2c_sibyte_algo;
/* Set the frequency to 100 kHz */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 916ba5e40a96..4010fe92e72b 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -135,15 +135,32 @@ config I2C_I810
help
If you say yes to this option, support will be included for the Intel
810/815 family of mainboard I2C interfaces. Specifically, the
- following versions of the chipset is supported:
+ following versions of the chipset are supported:
i810AA
i810AB
i810E
i815
+ i845G
This driver can also be built as a module. If so, the module
will be called i2c-i810.
+config I2C_PXA
+ tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
+ depends on I2C && EXPERIMENTAL && ARCH_PXA
+ help
+ If you have devices in the PXA I2C bus, say yes to this option.
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pxa.
+
+config I2C_PXA_SLAVE
+ bool "Intel PXA2XX I2C Slave comms support"
+ depends on I2C_PXA
+ help
+ Support I2C slave mode communications on the PXA I2C bus. This
+ is necessary for systems where the PXA may be a target on the
+ I2C bus.
+
config I2C_PIIX4
tristate "Intel PIIX4"
depends on I2C && PCI
@@ -182,14 +199,8 @@ config I2C_IOP3XX
will be called i2c-iop3xx.
config I2C_ISA
- tristate "ISA Bus support"
+ tristate
depends on I2C
- help
- If you say yes to this option, support will be included for i2c
- interfaces that are on the ISA bus.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-isa.
config I2C_ITE
tristate "ITE I2C Adapter"
@@ -235,6 +246,18 @@ config I2C_KEYWEST
This support is also available as a module. If so, the module
will be called i2c-keywest.
+config I2C_PMAC_SMU
+ tristate "Powermac SMU I2C interface"
+ depends on I2C && PMAC_SMU
+ help
+ This supports the use of the I2C interface in the SMU
+ chip on recent Apple machines like the iMac G5. It is used
+ among others by the thermal control driver for those machines.
+ Say Y if you have such a machine.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-pmac-smu.
+
config I2C_MPC
tristate "MPC107/824x/85xx/52xx"
depends on I2C && PPC32
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 42d6d814da72..f1df00f66c6c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_ITE) += i2c-ite.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o
+obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
+obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f634a0780cf0..ba90f5140af6 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -134,7 +134,7 @@
/* -> Read = 1 */
#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */
-
+static struct pci_driver ali1535_driver;
static unsigned short ali1535_smba;
static DECLARE_MUTEX(i2c_ali1535_sem);
@@ -162,7 +162,8 @@ static int ali1535_setup(struct pci_dev *dev)
goto exit;
}
- if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) {
+ if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
+ ali1535_driver.name)) {
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
ali1535_smba);
goto exit;
@@ -472,8 +473,6 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-i2c SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali1535_access,
.functionality = ali1535_func,
};
@@ -482,7 +481,6 @@ static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali1535_ids[] = {
@@ -515,6 +513,7 @@ static void __devexit ali1535_remove(struct pci_dev *dev)
}
static struct pci_driver ali1535_driver = {
+ .owner = THIS_MODULE,
.name = "ali1535_smbus",
.id_table = ali1535_ids,
.probe = ali1535_probe,
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index fdd881aee618..f1a62d892425 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -60,6 +60,7 @@
#define HST_CNTL2_SIZEMASK 0x38
+static struct pci_driver ali1563_pci_driver;
static unsigned short ali1563_smba;
static int ali1563_transaction(struct i2c_adapter * a, int size)
@@ -350,7 +351,8 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
goto Err;
}
- if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) {
+ if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+ ali1563_pci_driver.name)) {
dev_warn(&dev->dev,"Could not allocate I/O space");
goto Err;
}
@@ -366,8 +368,6 @@ static void ali1563_shutdown(struct pci_dev *dev)
}
static struct i2c_algorithm ali1563_algorithm = {
- .name = "Non-i2c SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali1563_access,
.functionality = ali1563_func,
};
@@ -408,7 +408,8 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
static struct pci_driver ali1563_pci_driver = {
- .name = "ali1563_i2c",
+ .owner = THIS_MODULE,
+ .name = "ali1563_smbus",
.id_table = ali1563_id_table,
.probe = ali1563_probe,
.remove = __devexit_p(ali1563_remove),
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 0f781a1a3323..400b08ed4299 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -125,12 +125,13 @@
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the i2c controller");
-static unsigned short ali15x3_smba = 0;
+static struct pci_driver ali15x3_driver;
+static unsigned short ali15x3_smba;
static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
{
@@ -166,7 +167,8 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
if(force_addr)
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
- if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
+ if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
+ ali15x3_driver.name)) {
dev_err(&ALI15X3_dev->dev,
"ALI15X3_smb region 0x%x already in use!\n",
ali15x3_smba);
@@ -462,8 +464,6 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = ali15x3_access,
.functionality = ali15x3_func,
};
@@ -472,7 +472,6 @@ static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali15x3_ids[] = {
@@ -505,6 +504,7 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
}
static struct pci_driver ali15x3_driver = {
+ .owner = THIS_MODULE,
.name = "ali15x3_smbus",
.id_table = ali15x3_ids,
.probe = ali15x3_probe,
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 4e553e8c5cba..f51ab652300a 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void)
init_MUTEX(&amd756_lock);
/* Define the 5 virtual adapters and algorithms structures */
- if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter),
+ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR1;
}
- if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm),
+ if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR2;
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6347ebc6fb53..de035d137c3f 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -85,8 +85,8 @@
#define AMD756_PROCESS_CALL 0x04
#define AMD756_BLOCK_DATA 0x05
-
-static unsigned short amd756_ioport = 0;
+static struct pci_driver amd756_driver;
+static unsigned short amd756_ioport;
/*
SMBUS event = I/O 28-29 bit 11
@@ -295,8 +295,6 @@ static u32 amd756_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = amd756_access,
.functionality = amd756_func,
};
@@ -305,7 +303,6 @@ struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
@@ -367,7 +364,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
amd756_ioport += SMB_ADDR_OFFSET;
}
- if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
+ if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
amd756_ioport);
return -ENODEV;
@@ -404,6 +401,7 @@ static void __devexit amd756_remove(struct pci_dev *dev)
}
static struct pci_driver amd756_driver = {
+ .owner = THIS_MODULE,
.name = "amd756_smbus",
.id_table = amd756_ids,
.probe = amd756_probe,
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index d6644481d2a0..f3b79a68dbec 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -30,6 +30,8 @@ struct amd_smbus {
int size;
};
+static struct pci_driver amd8111_driver;
+
/*
* AMD PCI control registers definitions.
*/
@@ -242,7 +244,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- protocol |= pec;
len = min_t(u8, data->block[0], 31);
amd_ec_write(smbus, AMD_SMB_CMD, command);
amd_ec_write(smbus, AMD_SMB_BCNT, len);
@@ -252,13 +253,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
read_write = I2C_SMBUS_READ;
break;
- case I2C_SMBUS_WORD_DATA_PEC:
- case I2C_SMBUS_BLOCK_DATA_PEC:
- case I2C_SMBUS_PROC_CALL_PEC:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
- return -1;
-
default:
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1;
@@ -323,8 +317,6 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus 2.0 adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = amd8111_access,
.functionality = amd8111_func,
};
@@ -345,16 +337,15 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
return -ENODEV;
- smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL);
+ smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
if (!smbus)
return -ENOMEM;
- memset(smbus, 0, sizeof(struct amd_smbus));
smbus->dev = dev;
smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0);
- if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0"))
+ if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
goto out_kfree;
smbus->adapter.owner = THIS_MODULE;
@@ -393,6 +384,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
}
static struct pci_driver amd8111_driver = {
+ .owner = THIS_MODULE,
.name = "amd8111_smbus2",
.id_table = amd8111_ids,
.probe = amd8111_probe,
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index a7ff112e49bf..d06edce03bf4 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -283,8 +283,6 @@ au1550_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm au1550_algo = {
- .name = "Au1550 algorithm",
- .id = I2C_ALGO_AU1550,
.master_xfer = au1550_xfer,
.functionality = au1550_func,
};
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 6930b660e508..59f8308c2356 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -22,7 +22,7 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
+/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
for Alpha Processor Inc. UP-2000(+) boards */
#include <linux/kernel.h>
@@ -46,12 +46,14 @@
#define DEFAULT_BASE 0x330
static int base;
+static u8 __iomem *base_iomem;
+
static int irq;
static int clock = 0x1c;
static int own = 0x55;
static int mmapped;
-/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
+/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
this module in real supports only one device, due to missing arguments
in some functions, called from the algo-pcf module. Sometimes it's
need to be rewriten - but for now just remove this for simpler reading */
@@ -60,40 +62,33 @@ static wait_queue_head_t pcf_wait;
static int pcf_pending;
static spinlock_t lock;
+static struct i2c_adapter pcf_isa_ops;
+
/* ----- local functions ---------------------------------------------- */
static void pcf_isa_setbyte(void *data, int ctl, int val)
{
- int address = ctl ? (base + 1) : base;
+ u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
/* enable irq if any specified for serial operation */
if (ctl && irq && (val & I2C_PCF_ESO)) {
val |= I2C_PCF_ENI;
}
- pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255);
-
- switch (mmapped) {
- case 0: /* regular I/O */
- outb(val, address);
- break;
- case 2: /* double mapped I/O needed for UP2000 board,
- I don't know why this... */
- writeb(val, (void *)address);
- /* fall */
- case 1: /* memory mapped I/O */
- writeb(val, (void *)address);
- break;
- }
+ pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
+ iowrite8(val, address);
+#ifdef __alpha__
+ /* API UP2000 needs some hardware fudging to make the write stick */
+ iowrite8(val, address);
+#endif
}
static int pcf_isa_getbyte(void *data, int ctl)
{
- int address = ctl ? (base + 1) : base;
- int val = mmapped ? readb((void *)address) : inb(address);
-
- pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
+ u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
+ int val = ioread8(address);
+ pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
return (val);
}
@@ -149,16 +144,40 @@ static int pcf_isa_init(void)
{
spin_lock_init(&lock);
if (!mmapped) {
- if (!request_region(base, 2, "i2c (isa bus adapter)")) {
- printk(KERN_ERR
- "i2c-elektor: requested I/O region (0x%X:2) "
- "is in use.\n", base);
+ if (!request_region(base, 2, pcf_isa_ops.name)) {
+ printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
+ "in use\n", pcf_isa_ops.name, base);
+ return -ENODEV;
+ }
+ base_iomem = ioport_map(base, 2);
+ if (!base_iomem) {
+ printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
+ pcf_isa_ops.name, base);
+ release_region(base, 2);
+ return -ENODEV;
+ }
+ } else {
+ if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
+ printk(KERN_ERR "%s: requested memory region (%#x:2) "
+ "is in use\n", pcf_isa_ops.name, base);
+ return -ENODEV;
+ }
+ base_iomem = ioremap(base, 2);
+ if (base_iomem == NULL) {
+ printk(KERN_ERR "%s: remap of memory region %#x "
+ "failed\n", pcf_isa_ops.name, base);
+ release_mem_region(base, 2);
return -ENODEV;
}
}
+ pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
+ base_iomem);
+
if (irq > 0) {
- if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) {
- printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq);
+ if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
+ NULL) < 0) {
+ printk(KERN_ERR "%s: Request irq%d failed\n",
+ pcf_isa_ops.name, irq);
irq = 0;
} else
enable_irq(irq);
@@ -186,47 +205,49 @@ static struct i2c_adapter pcf_isa_ops = {
.class = I2C_CLASS_HWMON,
.id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
- .name = "PCF8584 ISA adapter",
+ .name = "i2c-elektor",
};
-static int __init i2c_pcfisa_init(void)
+static int __init i2c_pcfisa_init(void)
{
#ifdef __alpha__
- /* check to see we have memory mapped PCF8584 connected to the
+ /* check to see we have memory mapped PCF8584 connected to the
Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
if (base == 0) {
struct pci_dev *cy693_dev;
-
- cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
+
+ cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
PCI_DEVICE_ID_CONTAQ_82C693, NULL);
if (cy693_dev) {
- char config;
+ unsigned char config;
/* yeap, we've found cypress, let's check config */
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
-
- pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config);
+
+ pr_debug("%s: found cy82c693, config "
+ "register 0x47 = 0x%02x\n",
+ pcf_isa_ops.name, config);
/* UP2000 board has this register set to 0xe1,
- but the most significant bit as seems can be
+ but the most significant bit as seems can be
reset during the proper initialisation
- sequence if guys from API decides to do that
- (so, we can even enable Tsunami Pchip
- window for the upper 1 Gb) */
+ sequence if guys from API decides to do that
+ (so, we can even enable Tsunami Pchip
+ window for the upper 1 Gb) */
/* so just check for ROMCS at 0xe0000,
- ROMCS enabled for writes
+ ROMCS enabled for writes
and external XD Bus buffer in use. */
if ((config & 0x7f) == 0x61) {
/* seems to be UP2000 like board */
base = 0xe0000;
- /* I don't know why we need to
- write twice */
- mmapped = 2;
- /* UP2000 drives ISA with
+ mmapped = 1;
+ /* UP2000 drives ISA with
8.25 MHz (PCI/4) clock
(this can be read from cypress) */
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
- printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n");
+ pr_info("%s: found API UP2000 like "
+ "board, will probe PCF8584 "
+ "later\n", pcf_isa_ops.name);
}
}
pci_dev_put(cy693_dev);
@@ -236,12 +257,11 @@ static int __init i2c_pcfisa_init(void)
/* sanity checks for mmapped I/O */
if (mmapped && base < 0xc8000) {
- printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
+ printk(KERN_ERR "%s: incorrect base address (%#x) specified "
+ "for mmapped I/O\n", pcf_isa_ops.name, base);
return -ENODEV;
}
- printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n");
-
if (base == 0) {
base = DEFAULT_BASE;
}
@@ -251,8 +271,8 @@ static int __init i2c_pcfisa_init(void)
return -ENODEV;
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
goto fail;
-
- printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base);
+
+ dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
return 0;
@@ -262,8 +282,13 @@ static int __init i2c_pcfisa_init(void)
free_irq(irq, NULL);
}
- if (!mmapped)
- release_region(base , 2);
+ if (!mmapped) {
+ ioport_unmap(base_iomem);
+ release_region(base, 2);
+ } else {
+ iounmap(base_iomem);
+ release_mem_region(base, 2);
+ }
return -ENODEV;
}
@@ -276,8 +301,13 @@ static void i2c_pcfisa_exit(void)
free_irq(irq, NULL);
}
- if (!mmapped)
- release_region(base , 2);
+ if (!mmapped) {
+ ioport_unmap(base_iomem);
+ release_region(base, 2);
+ } else {
+ iounmap(base_iomem);
+ release_mem_region(base, 2);
+ }
}
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index e0cb3b0f92fa..1b5354e24bf5 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -155,6 +155,7 @@ static void __devexit hydra_remove(struct pci_dev *dev)
static struct pci_driver hydra_driver = {
+ .owner = THIS_MODULE,
.name = "hydra_smbus",
.id_table = hydra_ids,
.probe = hydra_probe,
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1ab41313ce51..4f63195069da 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -52,10 +52,6 @@
#include <linux/i2c.h>
#include <asm/io.h>
-#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
-#define HAVE_PEC
-#endif
-
/* I801 SMBus address offsets */
#define SMBHSTSTS (0 + i801_smba)
#define SMBHSTCNT (2 + i801_smba)
@@ -106,10 +102,11 @@ MODULE_PARM_DESC(force_addr,
"EXTREMELY DANGEROUS!");
static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data,
- char read_write, int command);
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+ int command, int hwpec);
static unsigned short i801_smba;
+static struct pci_driver i801_driver;
static struct pci_dev *I801_dev;
static int isich4;
@@ -143,7 +140,7 @@ static int i801_setup(struct pci_dev *dev)
}
}
- if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
+ if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
i801_smba);
error_return = -EBUSY;
@@ -252,7 +249,7 @@ static int i801_transaction(void)
/* All-inclusive block transaction function */
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
- int command)
+ int command, int hwpec)
{
int i, len;
int smbcmd;
@@ -391,8 +388,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
goto END;
}
-#ifdef HAVE_PEC
- if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+ if (hwpec) {
/* wait for INTR bit as advised by Intel */
timeout = 0;
do {
@@ -406,7 +402,6 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
}
outb_p(temp, SMBHSTSTS);
}
-#endif
result = 0;
END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -421,14 +416,13 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data)
{
- int hwpec = 0;
+ int hwpec;
int block = 0;
int ret, xact = 0;
-#ifdef HAVE_PEC
- if(isich4)
- hwpec = (flags & I2C_CLIENT_PEC) != 0;
-#endif
+ hwpec = isich4 && (flags & I2C_CLIENT_PEC)
+ && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA;
switch (size) {
case I2C_SMBUS_QUICK:
@@ -463,11 +457,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
-#ifdef HAVE_PEC
- case I2C_SMBUS_BLOCK_DATA_PEC:
- if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
- size = I2C_SMBUS_BLOCK_DATA_PEC;
-#endif
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD);
outb_p(command, SMBHSTCMD);
@@ -479,27 +468,18 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1;
}
-#ifdef HAVE_PEC
- if(isich4 && hwpec) {
- if(size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- outb_p(1, SMBAUXCTL); /* enable HW PEC */
- }
-#endif
+ if (hwpec)
+ outb_p(1, SMBAUXCTL); /* enable hardware PEC */
+
if(block)
- ret = i801_block_transaction(data, read_write, size);
+ ret = i801_block_transaction(data, read_write, size, hwpec);
else {
outb_p(xact | ENABLE_INT9, SMBHSTCNT);
ret = i801_transaction();
}
-#ifdef HAVE_PEC
- if(isich4 && hwpec) {
- if(size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- outb_p(0, SMBAUXCTL);
- }
-#endif
+ if (hwpec)
+ outb_p(0, SMBAUXCTL); /* disable hardware PEC */
if(block)
return ret;
@@ -526,17 +506,10 @@ static u32 i801_func(struct i2c_adapter *adapter)
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
-#ifdef HAVE_PEC
- | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
- I2C_FUNC_SMBUS_HWPEC_CALC
- : 0)
-#endif
- ;
+ | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = i801_access,
.functionality = i801_func,
};
@@ -545,7 +518,6 @@ static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id i801_ids[] = {
@@ -588,6 +560,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
}
static struct pci_driver i801_driver = {
+ .owner = THIS_MODULE,
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index 0ff7016e0629..52bc30593bd7 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -32,6 +32,7 @@
i810AB 7123
i810E 7125
i815 1132
+ i845G 2562
*/
#include <linux/kernel.h>
@@ -232,6 +233,7 @@ static void __devexit i810_remove(struct pci_dev *dev)
}
static struct pci_driver i810_driver = {
+ .owner = THIS_MODULE,
.name = "i810_smbus",
.id_table = i810_ids,
.probe = i810_probe,
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 93ca36dc777e..1a587253d716 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -627,8 +627,6 @@ static u32 iic_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm iic_algo = {
- .name = "IBM IIC algorithm",
- .id = I2C_ALGO_OCP,
.master_xfer = iic_xfer,
.functionality = iic_func
};
@@ -674,13 +672,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
- if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
+ if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
ocp->def->index);
return -ENOMEM;
}
- memset(dev, 0, sizeof(*dev));
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
@@ -727,7 +724,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
adap = &dev->adap;
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
- adap->id = I2C_HW_OCP | iic_algo.id;
+ adap->id = I2C_HW_OCP;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 6b682e903f09..cfae4ad00fae 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -11,7 +11,7 @@
*
* Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
*
- * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
* Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
*
* Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005:
@@ -35,7 +35,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <asm/io.h>
@@ -43,7 +43,7 @@
#include "i2c-iop3xx.h"
/* global unit counter */
-static int i2c_id = 0;
+static int i2c_id;
static inline unsigned char
iic_cook_addr(struct i2c_msg *msg)
@@ -184,7 +184,7 @@ iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
do {
interrupted = wait_event_interruptible_timeout (
iop3xx_adap->waitq,
- (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
+ (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
1 * HZ;
);
if ((rc = iop3xx_i2c_error(sr)) < 0) {
@@ -399,8 +399,6 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
}
static struct i2c_algorithm iop3xx_i2c_algo = {
- .name = "IOP3xx I2C algorithm",
- .id = I2C_ALGO_IOP3XX,
.master_xfer = iop3xx_i2c_master_xfer,
.algo_control = iop3xx_i2c_algo_control,
.functionality = iop3xx_i2c_func,
@@ -442,19 +440,17 @@ iop3xx_i2c_probe(struct device *dev)
struct i2c_adapter *new_adapter;
struct i2c_algo_iop3xx_data *adapter_data;
- new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
if (!new_adapter) {
ret = -ENOMEM;
goto out;
}
- memset((void*)new_adapter, 0, sizeof(*new_adapter));
- adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
+ adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
if (!adapter_data) {
ret = -ENOMEM;
goto free_adapter;
}
- memset((void*)adapter_data, 0, sizeof(*adapter_data));
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -476,9 +472,10 @@ iop3xx_i2c_probe(struct device *dev)
goto release_region;
}
- res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
pdev->name, adapter_data);
- if (res) {
+
+ if (ret) {
ret = -EIO;
goto unmap;
}
@@ -527,6 +524,7 @@ out:
static struct device_driver iop3xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IOP3xx-I2C",
.bus = &platform_bus_type,
.probe = iop3xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 00e7f7157b75..03672c9ca409 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -1,6 +1,8 @@
/*
- i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
+ i2c-isa.c - an i2c-core-like thing for ISA hardware monitoring chips
+ Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+
+ Based on the i2c-isa pseudo-adapter from the lm_sensors project
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
This program is free software; you can redistribute it and/or modify
@@ -18,30 +20,37 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
- on first sight very useful; almost no functionality is preserved.
- Except that it makes writing drivers for chips which can be on both
- the SMBus and the ISA bus very much easier. See lm78.c for an example
- of this. */
+/* This implements an i2c-core-like thing for ISA hardware monitoring
+ chips. Such chips are linked to the i2c subsystem for historical
+ reasons (because the early ISA hardware monitoring chips such as the
+ LM78 had both an I2C and an ISA interface). They used to be
+ registered with the main i2c-core, but as a first step in the
+ direction of a clean separation between I2C and ISA chip drivers,
+ we now have this separate core for ISA ones. It is significantly
+ more simple than the real one, of course, because we don't have to
+ handle multiple busses: there is only one (fake) ISA adapter.
+ It is worth noting that we still rely on i2c-core for some things
+ at the moment - but hopefully this won't last. */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/i2c.h>
+#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
static u32 isa_func(struct i2c_adapter *adapter);
/* This is the actual algorithm we define */
static struct i2c_algorithm isa_algorithm = {
- .name = "ISA bus algorithm",
- .id = I2C_ALGO_ISA,
.functionality = isa_func,
};
/* There can only be one... */
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
+ .id = I2C_HW_ISA,
.class = I2C_CLASS_HWMON,
.algo = &isa_algorithm,
.name = "ISA main adapter",
@@ -53,17 +62,147 @@ static u32 isa_func(struct i2c_adapter *adapter)
return 0;
}
+
+/* Copied from i2c-core */
+static ssize_t show_adapter_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
+ return sprintf(buf, "%s\n", adap->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+
+static int i2c_isa_device_probe(struct device *dev)
+{
+ return -ENODEV;
+}
+
+static int i2c_isa_device_remove(struct device *dev)
+{
+ return 0;
+}
+
+
+/* We implement an interface which resembles i2c_{add,del}_driver,
+ but for i2c-isa drivers. We don't have to remember and handle lists
+ of drivers and adapters so this is much more simple, of course. */
+
+int i2c_isa_add_driver(struct i2c_driver *driver)
+{
+ int res;
+
+ /* Add the driver to the list of i2c drivers in the driver core */
+ driver->driver.name = driver->name;
+ driver->driver.owner = driver->owner;
+ driver->driver.bus = &i2c_bus_type;
+ driver->driver.probe = i2c_isa_device_probe;
+ driver->driver.remove = i2c_isa_device_remove;
+ res = driver_register(&driver->driver);
+ if (res)
+ return res;
+ dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
+
+ /* Now look for clients */
+ driver->attach_adapter(&isa_adapter);
+
+ return 0;
+}
+
+int i2c_isa_del_driver(struct i2c_driver *driver)
+{
+ struct list_head *item, *_n;
+ struct i2c_client *client;
+ int res;
+
+ /* Detach all clients belonging to this one driver */
+ list_for_each_safe(item, _n, &isa_adapter.clients) {
+ client = list_entry(item, struct i2c_client, list);
+ if (client->driver != driver)
+ continue;
+ dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
+ client->name, client->addr);
+ if ((res = driver->detach_client(client))) {
+ dev_err(&isa_adapter.dev, "Failed, driver "
+ "%s not unregistered!\n",
+ driver->name);
+ return res;
+ }
+ }
+
+ /* Get the driver off the core list */
+ driver_unregister(&driver->driver);
+ dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
+
+ return 0;
+}
+
+
static int __init i2c_isa_init(void)
{
- return i2c_add_adapter(&isa_adapter);
+ init_MUTEX(&isa_adapter.clist_lock);
+ INIT_LIST_HEAD(&isa_adapter.clients);
+
+ isa_adapter.nr = ANY_I2C_ISA_BUS;
+ isa_adapter.dev.parent = &platform_bus;
+ sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
+ isa_adapter.dev.driver = &i2c_adapter_driver;
+ isa_adapter.dev.release = &i2c_adapter_dev_release;
+ device_register(&isa_adapter.dev);
+ device_create_file(&isa_adapter.dev, &dev_attr_name);
+
+ /* Add this adapter to the i2c_adapter class */
+ memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
+ isa_adapter.class_dev.dev = &isa_adapter.dev;
+ isa_adapter.class_dev.class = &i2c_adapter_class;
+ strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
+ BUS_ID_SIZE);
+ class_device_register(&isa_adapter.class_dev);
+
+ dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
+
+ return 0;
}
static void __exit i2c_isa_exit(void)
{
- i2c_del_adapter(&isa_adapter);
+#ifdef DEBUG
+ struct list_head *item, *_n;
+ struct i2c_client *client = NULL;
+#endif
+
+ /* There should be no more active client */
+#ifdef DEBUG
+ dev_dbg(&isa_adapter.dev, "Looking for clients\n");
+ list_for_each_safe(item, _n, &isa_adapter.clients) {
+ client = list_entry(item, struct i2c_client, list);
+ dev_err(&isa_adapter.dev, "Driver %s still has an active "
+ "ISA client at 0x%x\n", client->driver->name,
+ client->addr);
+ }
+ if (client != NULL)
+ return;
+#endif
+
+ /* Clean up the sysfs representation */
+ dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
+ init_completion(&isa_adapter.dev_released);
+ init_completion(&isa_adapter.class_dev_released);
+ class_device_unregister(&isa_adapter.class_dev);
+ device_remove_file(&isa_adapter.dev, &dev_attr_name);
+ device_unregister(&isa_adapter.dev);
+
+ /* Wait for sysfs to drop all references */
+ dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
+ wait_for_completion(&isa_adapter.dev_released);
+ wait_for_completion(&isa_adapter.class_dev_released);
+
+ dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
}
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+EXPORT_SYMBOL(i2c_isa_add_driver);
+EXPORT_SYMBOL(i2c_isa_del_driver);
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("ISA bus access through i2c");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 1956af382cd8..64552a376f2d 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -28,7 +28,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
@@ -36,6 +36,8 @@
#include <asm/hardware.h> /* Pick up IXP2000-specific bits */
#include <asm/arch/gpio.h>
+static struct device_driver ixp2000_i2c_driver;
+
static inline int ixp2000_scl_pin(void *data)
{
return ((struct ixp2000_i2c_pins*)data)->scl_pin;
@@ -104,11 +106,10 @@ static int ixp2000_i2c_probe(struct device *dev)
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp2000_i2c_data *drv_data =
- kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
+ kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;
- memzero(drv_data, sizeof(*drv_data));
drv_data->gpio_pins = gpio;
drv_data->algo_data.data = gpio;
@@ -121,6 +122,8 @@ static int ixp2000_i2c_probe(struct device *dev)
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP2000,
+ strlcpy(drv_data->adapter.name, ixp2000_i2c_driver.name,
+ I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data,
drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -142,6 +145,7 @@ static int ixp2000_i2c_probe(struct device *dev)
}
static struct device_driver ixp2000_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP2000-I2C",
.bus = &platform_bus_type,
.probe = ixp2000_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index f6f5ca31fdba..cc652c350814 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -28,13 +28,15 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
+static struct device_driver ixp4xx_i2c_driver;
+
static inline int ixp4xx_scl_pin(void *data)
{
return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
@@ -105,12 +107,11 @@ static int ixp4xx_i2c_probe(struct device *dev)
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp4xx_i2c_data *drv_data =
- kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
+ kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
if(!drv_data)
return -ENOMEM;
- memzero(drv_data, sizeof(struct ixp4xx_i2c_data));
drv_data->gpio_pins = gpio;
/*
@@ -129,6 +130,8 @@ static int ixp4xx_i2c_probe(struct device *dev)
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP4XX;
+ strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name,
+ I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data;
drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -151,6 +154,7 @@ static int ixp4xx_i2c_probe(struct device *dev)
}
static struct device_driver ixp4xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP4XX-I2C",
.bus = &platform_bus_type,
.probe = ixp4xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 94ae808314f7..d61f748278fc 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -87,12 +87,9 @@ static const char *__kw_state_names[] = {
};
#endif /* DEBUG */
-static int probe;
-
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
MODULE_LICENSE("GPL");
-module_param(probe, bool, 0);
#ifdef POLLED_MODE
/* Don't schedule, the g5 fan controller is too
@@ -498,8 +495,6 @@ keywest_func(struct i2c_adapter * adapter)
/* For now, we only handle combined mode (smbus) */
static struct i2c_algorithm keywest_algorithm = {
- .name = "Keywest i2c",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = keywest_smbus_xfer,
.master_xfer = keywest_xfer,
.functionality = keywest_func,
@@ -540,13 +535,12 @@ create_iface(struct device_node *np, struct device *dev)
tsize = sizeof(struct keywest_iface) +
(sizeof(struct keywest_chan) + 4) * nchan;
- iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL);
+ iface = kzalloc(tsize, GFP_KERNEL);
if (iface == NULL) {
printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");
pmac_low_i2c_unlock(np);
return -ENOMEM;
}
- memset(iface, 0, tsize);
spin_lock_init(&iface->lock);
init_completion(&iface->complete);
iface->node = of_node_get(np);
@@ -616,12 +610,10 @@ create_iface(struct device_node *np, struct device *dev)
for (i=0; i<nchan; i++) {
struct keywest_chan* chan = &iface->channels[i];
- u8 addr;
sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
chan->iface = iface;
chan->chan_no = i;
- chan->adapter.id = I2C_ALGO_SMBUS;
chan->adapter.algo = &keywest_algorithm;
chan->adapter.algo_data = NULL;
chan->adapter.client_register = NULL;
@@ -635,15 +627,6 @@ create_iface(struct device_node *np, struct device *dev)
chan->adapter.name);
i2c_set_adapdata(&chan->adapter, NULL);
}
- if (probe) {
- printk("Probe: ");
- for (addr = 0x00; addr <= 0x7f; addr++) {
- if (i2c_smbus_xfer(&chan->adapter,addr,
- 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- printk("%02x ", addr);
- }
- printk("\n");
- }
}
printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
@@ -732,6 +715,7 @@ static struct of_device_id i2c_keywest_match[] =
static struct macio_driver i2c_keywest_macio_driver =
{
+ .owner = THIS_MODULE,
.name = "i2c-keywest",
.match_table = i2c_keywest_match,
.probe = create_iface_macio,
@@ -740,6 +724,7 @@ static struct macio_driver i2c_keywest_macio_driver =
static struct of_platform_driver i2c_keywest_of_platform_driver =
{
+ .owner = THIS_MODULE,
.name = "i2c-keywest",
.match_table = i2c_keywest_match,
.probe = create_iface_of_platform,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 9ad3e9262e8a..65b939a059e9 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -19,6 +19,8 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
#include <linux/fsl_devices.h>
#include <linux/i2c.h>
@@ -272,8 +274,6 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
}
static struct i2c_algorithm mpc_algo = {
- .name = "MPC algorithm",
- .id = I2C_ALGO_MPC107,
.master_xfer = mpc_xfer,
.functionality = mpc_functionality,
};
@@ -281,7 +281,7 @@ static struct i2c_algorithm mpc_algo = {
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.name = "MPC adapter",
- .id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
+ .id = I2C_HW_MPC107,
.algo = &mpc_algo,
.class = I2C_CLASS_HWMON,
.timeout = 1,
@@ -298,10 +298,9 @@ static int fsl_i2c_probe(struct device *device)
pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
- if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+ if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
return -ENOMEM;
}
- memset(i2c, 0, sizeof(*i2c));
i2c->irq = platform_get_irq(pdev, 0);
i2c->flags = pdata->device_flags;
@@ -363,6 +362,7 @@ static int fsl_i2c_remove(struct device *device)
/* Structure for a device driver */
static struct device_driver fsl_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "fsl-i2c",
.bus = &platform_bus_type,
.probe = fsl_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5b852782d2f5..6b48027b2ee3 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -17,6 +17,8 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mv643xx.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
/* Register defines */
@@ -423,18 +425,16 @@ static int
mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
- int i, rc = 0;
+ int i, rc;
for (i=0; i<num; i++)
- if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
- break;
+ if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0)
+ return rc;
- return rc;
+ return num;
}
static struct i2c_algorithm mv64xxx_i2c_algo = {
- .name = MV64XXX_I2C_CTLR_NAME " algorithm",
- .id = I2C_ALGO_MV64XXX,
.master_xfer = mv64xxx_i2c_xfer,
.functionality = mv64xxx_i2c_functionality,
};
@@ -502,13 +502,10 @@ mv64xxx_i2c_probe(struct device *dev)
if ((pd->id != 0) || !pdata)
return -ENODEV;
- drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
-
+ drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;
- memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
-
if (mv64xxx_i2c_map_regs(pd, drv_data)) {
rc = -ENODEV;
goto exit_kfree;
@@ -523,7 +520,7 @@ mv64xxx_i2c_probe(struct device *dev)
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
- drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
+ drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON;
@@ -572,6 +569,7 @@ mv64xxx_i2c_remove(struct device *dev)
}
static struct device_driver mv64xxx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = MV64XXX_I2C_CTLR_NAME,
.bus = &platform_bus_type,
.probe = mv64xxx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 74eb89aa9350..fd26036e68a3 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -97,11 +97,7 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define NVIDIA_SMB_PRTCL_PEC 0x80
-
-/* Other settings */
-#define MAX_TIMEOUT 256
-
-
+static struct pci_driver nforce2_driver;
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
@@ -110,8 +106,6 @@ static u32 nforce2_func(struct i2c_adapter *adapter);
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = nforce2_access,
.functionality = nforce2_func,
};
@@ -120,7 +114,6 @@ static struct i2c_adapter nforce2_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
/* Return -1 on error. See smbus.h for more information */
@@ -131,7 +124,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec, temp;
unsigned char len = 0; /* to keep the compiler quiet */
- int timeout = 0;
int i;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
@@ -191,36 +183,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
- /*
- outb_p(command, NVIDIA_SMB_CMD);
- outb_p(data->word, NVIDIA_SMB_DATA);
- outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
- protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec;
- read_write = I2C_SMBUS_READ;
- break;
- */
case I2C_SMBUS_BLOCK_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
return -1;
- /*
- protocol |= pec;
- len = min_t(u8, data->block[0], 31);
- outb_p(command, NVIDIA_SMB_CMD);
- outb_p(len, NVIDIA_SMB_BCNT);
- for (i = 0; i < len; i++)
- outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i);
- protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec;
- read_write = I2C_SMBUS_READ;
- break;
- */
-
- case I2C_SMBUS_WORD_DATA_PEC:
- case I2C_SMBUS_BLOCK_DATA_PEC:
- case I2C_SMBUS_PROC_CALL_PEC:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- dev_err(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
- return -1;
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
@@ -232,12 +198,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
temp = inb_p(NVIDIA_SMB_STS);
-#if 0
- do {
- i2c_do_pause(1);
- temp = inb_p(NVIDIA_SMB_STS);
- } while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
-#endif
if (~temp & NVIDIA_SMB_STS_DONE) {
udelay(500);
temp = inb_p(NVIDIA_SMB_STS);
@@ -247,9 +207,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
temp = inb_p(NVIDIA_SMB_STS);
}
- if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE)
- || (temp & NVIDIA_SMB_STS_STATUS))
+ if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
+ dev_dbg(&adap->dev, "SMBus Timeout! (0x%02x)\n", temp);
return -1;
+ }
if (read_write == I2C_SMBUS_WRITE)
return 0;
@@ -317,7 +278,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg,
smbus->base = iobase & 0xfffc;
smbus->size = 8;
- if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) {
+ if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
smbus->base, smbus->base+smbus->size-1, name);
return -1;
@@ -345,10 +306,8 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
int res1, res2;
/* we support 2 SMBus adapters */
- if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
- GFP_KERNEL)))
+ if (!(smbuses = kzalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL)))
return -ENOMEM;
- memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
pci_set_drvdata(dev, smbuses);
/* SMBus adapter 1 */
@@ -388,6 +347,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
}
static struct pci_driver nforce2_driver = {
+ .owner = THIS_MODULE,
.name = "nForce2_smbus",
.id_table = nforce2_ids,
.probe = nforce2_probe,
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 71a2502fe069..2854d858fc9b 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -155,12 +155,11 @@ static void i2c_parport_attach (struct parport *port)
{
struct i2c_par *adapter;
- adapter = kmalloc(sizeof(struct i2c_par), GFP_KERNEL);
+ adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
if (adapter == NULL) {
- printk(KERN_ERR "i2c-parport: Failed to kmalloc\n");
+ printk(KERN_ERR "i2c-parport: Failed to kzalloc\n");
return;
}
- memset(adapter, 0x00, sizeof(struct i2c_par));
pr_debug("i2c-parport: attaching to %s\n", port->name);
adapter->pdev = parport_register_device(port, "i2c-parport",
@@ -232,7 +231,7 @@ static void i2c_parport_detach (struct parport *port)
}
}
-static struct parport_driver i2c_driver = {
+static struct parport_driver i2c_parport_driver = {
.name = "i2c-parport",
.attach = i2c_parport_attach,
.detach = i2c_parport_detach,
@@ -250,12 +249,12 @@ static int __init i2c_parport_init(void)
type = 0;
}
- return parport_register_driver(&i2c_driver);
+ return parport_register_driver(&i2c_parport_driver);
}
static void __exit i2c_parport_exit(void)
{
- parport_unregister_driver(&i2c_driver);
+ parport_unregister_driver(&i2c_parport_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d34ee381ce1..7d63eec423fe 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -90,13 +90,13 @@ struct sd {
/* If force is set to anything different from 0, we forcibly enable the
PIIX4. DANGEROUS! */
-static int force = 0;
+static int force;
module_param (force, int, 0);
MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
/* If force_addr is set to anything different from 0, we forcibly enable
the PIIX4 at the given address. VERY DANGEROUS! */
-static int force_addr = 0;
+static int force_addr;
module_param (force_addr, int, 0);
MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. "
@@ -104,14 +104,15 @@ MODULE_PARM_DESC(force_addr,
/* If fix_hstcfg is set to anything different from 0, we reset one of the
registers to be a valid value. */
-static int fix_hstcfg = 0;
+static int fix_hstcfg;
module_param (fix_hstcfg, int, 0);
MODULE_PARM_DESC(fix_hstcfg,
"Fix config register. Needed on some boards (Force CPCI735).");
static int piix4_transaction(void);
-static unsigned short piix4_smba = 0;
+static unsigned short piix4_smba;
+static struct pci_driver piix4_driver;
static struct i2c_adapter piix4_adapter;
static struct dmi_system_id __devinitdata piix4_dmi_table[] = {
@@ -157,7 +158,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
}
}
- if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
+ if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
piix4_smba);
return -ENODEV;
@@ -399,8 +400,6 @@ static u32 piix4_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = piix4_access,
.functionality = piix4_func,
};
@@ -409,7 +408,6 @@ static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id piix4_ids[] = {
@@ -464,6 +462,7 @@ static void __devexit piix4_remove(struct pci_dev *dev)
}
static struct pci_driver piix4_driver = {
+ .owner = THIS_MODULE,
.name = "piix4_smbus",
.id_table = piix4_ids,
.probe = piix4_probe,
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
new file mode 100644
index 000000000000..bfefe7f7a53d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pmac-smu.c
@@ -0,0 +1,315 @@
+/*
+ i2c Support for Apple SMU Controller
+
+ Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
+ <benh@kernel.crashing.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/smu.h>
+
+static int probe;
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("I2C driver for Apple's SMU");
+MODULE_LICENSE("GPL");
+module_param(probe, bool, 0);
+
+
+/* Physical interface */
+struct smu_iface
+{
+ struct i2c_adapter adapter;
+ struct completion complete;
+ u32 busid;
+};
+
+static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc)
+{
+ struct smu_iface *iface = misc;
+ complete(&iface->complete);
+}
+
+/*
+ * SMBUS-type transfer entrypoint
+ */
+static s32 smu_smbus_xfer( struct i2c_adapter* adap,
+ u16 addr,
+ unsigned short flags,
+ char read_write,
+ u8 command,
+ int size,
+ union i2c_smbus_data* data)
+{
+ struct smu_iface *iface = i2c_get_adapdata(adap);
+ struct smu_i2c_cmd cmd;
+ int rc = 0;
+ int read = (read_write == I2C_SMBUS_READ);
+
+ cmd.info.bus = iface->busid;
+ cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00);
+
+ /* Prepare datas & select mode */
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
+ cmd.info.datalen = 0;
+ break;
+ case I2C_SMBUS_BYTE:
+ cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
+ cmd.info.datalen = 1;
+ if (!read)
+ cmd.info.data[0] = data->byte;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+ cmd.info.datalen = 1;
+ cmd.info.sublen = 1;
+ cmd.info.subaddr[0] = command;
+ cmd.info.subaddr[1] = 0;
+ cmd.info.subaddr[2] = 0;
+ if (!read)
+ cmd.info.data[0] = data->byte;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+ cmd.info.datalen = 2;
+ cmd.info.sublen = 1;
+ cmd.info.subaddr[0] = command;
+ cmd.info.subaddr[1] = 0;
+ cmd.info.subaddr[2] = 0;
+ if (!read) {
+ cmd.info.data[0] = data->byte & 0xff;
+ cmd.info.data[1] = (data->byte >> 8) & 0xff;
+ }
+ break;
+ /* Note that these are broken vs. the expected smbus API where
+ * on reads, the lenght is actually returned from the function,
+ * but I think the current API makes no sense and I don't want
+ * any driver that I haven't verified for correctness to go
+ * anywhere near a pmac i2c bus anyway ...
+ */
+ case I2C_SMBUS_BLOCK_DATA:
+ cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+ cmd.info.datalen = data->block[0] + 1;
+ if (cmd.info.datalen > 6)
+ return -EINVAL;
+ if (!read)
+ memcpy(cmd.info.data, data->block, cmd.info.datalen);
+ cmd.info.sublen = 1;
+ cmd.info.subaddr[0] = command;
+ cmd.info.subaddr[1] = 0;
+ cmd.info.subaddr[2] = 0;
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
+ cmd.info.datalen = data->block[0];
+ if (cmd.info.datalen > 7)
+ return -EINVAL;
+ if (!read)
+ memcpy(cmd.info.data, &data->block[1],
+ cmd.info.datalen);
+ cmd.info.sublen = 1;
+ cmd.info.subaddr[0] = command;
+ cmd.info.subaddr[1] = 0;
+ cmd.info.subaddr[2] = 0;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Turn a standardsub read into a combined mode access */
+ if (read_write == I2C_SMBUS_READ &&
+ cmd.info.type == SMU_I2C_TRANSFER_STDSUB)
+ cmd.info.type = SMU_I2C_TRANSFER_COMBINED;
+
+ /* Finish filling command and submit it */
+ cmd.done = smu_i2c_done;
+ cmd.misc = iface;
+ rc = smu_queue_i2c(&cmd);
+ if (rc < 0)
+ return rc;
+ wait_for_completion(&iface->complete);
+ rc = cmd.status;
+
+ if (!read || rc < 0)
+ return rc;
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ data->byte = cmd.info.data[0];
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ data->word = ((u16)cmd.info.data[1]) << 8;
+ data->word |= cmd.info.data[0];
+ break;
+ /* Note that these are broken vs. the expected smbus API where
+ * on reads, the lenght is actually returned from the function,
+ * but I think the current API makes no sense and I don't want
+ * any driver that I haven't verified for correctness to go
+ * anywhere near a pmac i2c bus anyway ...
+ */
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ memcpy(&data->block[0], cmd.info.data, cmd.info.datalen);
+ break;
+ }
+
+ return rc;
+}
+
+static u32
+smu_smbus_func(struct i2c_adapter * adapter)
+{
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+/* For now, we only handle combined mode (smbus) */
+static struct i2c_algorithm smu_algorithm = {
+ .smbus_xfer = smu_smbus_xfer,
+ .functionality = smu_smbus_func,
+};
+
+static int create_iface(struct device_node *np, struct device *dev)
+{
+ struct smu_iface* iface;
+ u32 *reg, busid;
+ int rc;
+
+ reg = (u32 *)get_property(np, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n");
+ return -ENXIO;
+ }
+ busid = *reg;
+
+ iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL);
+ if (iface == NULL) {
+ printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
+ return -ENOMEM;
+ }
+ init_completion(&iface->complete);
+ iface->busid = busid;
+
+ dev_set_drvdata(dev, iface);
+
+ sprintf(iface->adapter.name, "smu-i2c-%02x", busid);
+ iface->adapter.algo = &smu_algorithm;
+ iface->adapter.algo_data = NULL;
+ iface->adapter.client_register = NULL;
+ iface->adapter.client_unregister = NULL;
+ i2c_set_adapdata(&iface->adapter, iface);
+ iface->adapter.dev.parent = dev;
+
+ rc = i2c_add_adapter(&iface->adapter);
+ if (rc) {
+ printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration "
+ "failed\n", iface->adapter.name);
+ i2c_set_adapdata(&iface->adapter, NULL);
+ }
+
+ if (probe) {
+ unsigned char addr;
+ printk("Probe: ");
+ for (addr = 0x00; addr <= 0x7f; addr++) {
+ if (i2c_smbus_xfer(&iface->adapter,addr,
+ 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
+ printk("%02x ", addr);
+ }
+ printk("\n");
+ }
+
+ printk(KERN_INFO "SMU i2c bus %x registered\n", busid);
+
+ return 0;
+}
+
+static int dispose_iface(struct device *dev)
+{
+ struct smu_iface *iface = dev_get_drvdata(dev);
+ int rc;
+
+ rc = i2c_del_adapter(&iface->adapter);
+ i2c_set_adapdata(&iface->adapter, NULL);
+ /* We aren't that prepared to deal with this... */
+ if (rc)
+ printk("i2c-pmac-smu.c: Failed to remove bus %s !\n",
+ iface->adapter.name);
+ dev_set_drvdata(dev, NULL);
+ kfree(iface);
+
+ return 0;
+}
+
+
+static int create_iface_of_platform(struct of_device* dev,
+ const struct of_device_id *match)
+{
+ return create_iface(dev->node, &dev->dev);
+}
+
+
+static int dispose_iface_of_platform(struct of_device* dev)
+{
+ return dispose_iface(&dev->dev);
+}
+
+
+static struct of_device_id i2c_smu_match[] =
+{
+ {
+ .compatible = "smu-i2c",
+ },
+ {},
+};
+static struct of_platform_driver i2c_smu_of_platform_driver =
+{
+ .name = "i2c-smu",
+ .match_table = i2c_smu_match,
+ .probe = create_iface_of_platform,
+ .remove = dispose_iface_of_platform
+};
+
+
+static int __init i2c_pmac_smu_init(void)
+{
+ of_register_driver(&i2c_smu_of_platform_driver);
+ return 0;
+}
+
+
+static void __exit i2c_pmac_smu_cleanup(void)
+{
+ of_unregister_driver(&i2c_smu_of_platform_driver);
+}
+
+module_init(i2c_pmac_smu_init);
+module_exit(i2c_pmac_smu_cleanup);
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 83fd16d61ce5..42cb1d8ca659 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -83,11 +83,6 @@ struct s_i2c_chip {
/*
* i2c configuration
*/
-#ifndef I2C_HW_B_S3VIA
-#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
-#endif
-
-/* delays */
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
@@ -241,14 +236,12 @@ static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_devic
struct s_i2c_chip *chip;
struct s_i2c_bus *bus;
- pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
+ pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
if (chip == NULL) {
return -ENOMEM;
}
- memset(chip, 0, sizeof(struct s_i2c_chip));
-
base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
len = dev->resource[0].end - base + 1;
chip->mmio = ioremap_nocache(base, len);
@@ -308,6 +301,7 @@ static struct pci_device_id prosavage_pci_tbl[] = {
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
static struct pci_driver prosavage_driver = {
+ .owner = THIS_MODULE,
.name = "prosavage_smbus",
.id_table = prosavage_pci_tbl,
.probe = prosavage_probe,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
new file mode 100644
index 000000000000..67ccbea24ba4
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -0,0 +1,1027 @@
+/*
+ * i2c_adap_pxa.c
+ *
+ * I2C adapter for the PXA I2C bus access.
+ *
+ * Copyright (C) 2002 Intrinsyc Software Inc.
+ * Copyright (C) 2004-2005 Deep Blue Solutions 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.
+ *
+ * History:
+ * Apr 2002: Initial version [CS]
+ * Jun 2002: Properly seperated algo/adap [FB]
+ * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
+ * Sep 2004: Major rework to ensure efficient bus handling [RMK]
+ * Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood]
+ * Feb 2005: Rework slave mode handling [RMK]
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-pxa.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/pxa-regs.h>
+
+struct pxa_i2c {
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ struct i2c_msg *msg;
+ unsigned int msg_num;
+ unsigned int msg_idx;
+ unsigned int msg_ptr;
+ unsigned int slave_addr;
+
+ struct i2c_adapter adap;
+#ifdef CONFIG_I2C_PXA_SLAVE
+ struct i2c_slave_client *slave;
+#endif
+
+ unsigned int irqlogidx;
+ u32 isrlog[32];
+ u32 icrlog[32];
+};
+
+/*
+ * I2C Slave mode address
+ */
+#define I2C_PXA_SLAVE_ADDR 0x1
+
+#ifdef DEBUG
+
+struct bits {
+ u32 mask;
+ const char *set;
+ const char *unset;
+};
+#define BIT(m, s, u) { .mask = m, .set = s, .unset = u }
+
+static inline void
+decode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
+{
+ printk("%s %08x: ", prefix, val);
+ while (num--) {
+ const char *str = val & bits->mask ? bits->set : bits->unset;
+ if (str)
+ printk("%s ", str);
+ bits++;
+ }
+}
+
+static const struct bits isr_bits[] = {
+ BIT(ISR_RWM, "RX", "TX"),
+ BIT(ISR_ACKNAK, "NAK", "ACK"),
+ BIT(ISR_UB, "Bsy", "Rdy"),
+ BIT(ISR_IBB, "BusBsy", "BusRdy"),
+ BIT(ISR_SSD, "SlaveStop", NULL),
+ BIT(ISR_ALD, "ALD", NULL),
+ BIT(ISR_ITE, "TxEmpty", NULL),
+ BIT(ISR_IRF, "RxFull", NULL),
+ BIT(ISR_GCAD, "GenCall", NULL),
+ BIT(ISR_SAD, "SlaveAddr", NULL),
+ BIT(ISR_BED, "BusErr", NULL),
+};
+
+static void decode_ISR(unsigned int val)
+{
+ decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val);
+ printk("\n");
+}
+
+static const struct bits icr_bits[] = {
+ BIT(ICR_START, "START", NULL),
+ BIT(ICR_STOP, "STOP", NULL),
+ BIT(ICR_ACKNAK, "ACKNAK", NULL),
+ BIT(ICR_TB, "TB", NULL),
+ BIT(ICR_MA, "MA", NULL),
+ BIT(ICR_SCLE, "SCLE", "scle"),
+ BIT(ICR_IUE, "IUE", "iue"),
+ BIT(ICR_GCD, "GCD", NULL),
+ BIT(ICR_ITEIE, "ITEIE", NULL),
+ BIT(ICR_IRFIE, "IRFIE", NULL),
+ BIT(ICR_BEIE, "BEIE", NULL),
+ BIT(ICR_SSDIE, "SSDIE", NULL),
+ BIT(ICR_ALDIE, "ALDIE", NULL),
+ BIT(ICR_SADIE, "SADIE", NULL),
+ BIT(ICR_UR, "UR", "ur"),
+};
+
+static void decode_ICR(unsigned int val)
+{
+ decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val);
+ printk("\n");
+}
+
+static unsigned int i2c_debug = DEBUG;
+
+static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
+{
+ dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
+}
+
+#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
+#else
+#define i2c_debug 0
+
+#define show_state(i2c) do { } while (0)
+#define decode_ISR(val) do { } while (0)
+#define decode_ICR(val) do { } while (0)
+#endif
+
+#define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0)
+
+static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
+
+static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
+{
+ unsigned int i;
+ printk("i2c: error: %s\n", why);
+ printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
+ i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
+ printk("i2c: ICR: %08x ISR: %08x\n"
+ "i2c: log: ", ICR, ISR);
+ for (i = 0; i < i2c->irqlogidx; i++)
+ printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
+ printk("\n");
+}
+
+static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
+{
+ return !(ICR & ICR_SCLE);
+}
+
+static void i2c_pxa_abort(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ/4;
+
+ if (i2c_pxa_is_slavemode(i2c)) {
+ dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__);
+ return;
+ }
+
+ while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) {
+ unsigned long icr = ICR;
+
+ icr &= ~ICR_START;
+ icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
+
+ ICR = icr;
+
+ show_state(i2c);
+
+ msleep(1);
+ }
+
+ ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+}
+
+static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
+{
+ int timeout = DEF_TIMEOUT;
+
+ while (timeout-- && ISR & (ISR_IBB | ISR_UB)) {
+ if ((ISR & ISR_SAD) != 0)
+ timeout += 4;
+
+ msleep(2);
+ show_state(i2c);
+ }
+
+ if (timeout <= 0)
+ show_state(i2c);
+
+ return timeout <= 0 ? I2C_RETRY : 0;
+}
+
+static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ*4;
+
+ while (time_before(jiffies, timeout)) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, (long)jiffies, ISR, ICR, IBMR);
+
+ if (ISR & ISR_SAD) {
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
+ goto out;
+ }
+
+ /* wait for unit and bus being not busy, and we also do a
+ * quick check of the i2c lines themselves to ensure they've
+ * gone high...
+ */
+ if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) {
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
+ return 1;
+ }
+
+ msleep(1);
+ }
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
+ out:
+ return 0;
+}
+
+static int i2c_pxa_set_master(struct pxa_i2c *i2c)
+{
+ if (i2c_debug)
+ dev_dbg(&i2c->adap.dev, "setting to bus master\n");
+
+ if ((ISR & (ISR_UB | ISR_IBB)) != 0) {
+ dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
+ if (!i2c_pxa_wait_master(i2c)) {
+ dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
+ return I2C_RETRY;
+ }
+ }
+
+ ICR |= ICR_SCLE;
+ return 0;
+}
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
+{
+ unsigned long timeout = jiffies + HZ*1;
+
+ /* wait for stop */
+
+ show_state(i2c);
+
+ while (time_before(jiffies, timeout)) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, (long)jiffies, ISR, ICR, IBMR);
+
+ if ((ISR & (ISR_UB|ISR_IBB|ISR_SAD)) == ISR_SAD ||
+ (ICR & ICR_SCLE) == 0) {
+ if (i2c_debug > 1)
+ dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
+ return 1;
+ }
+
+ msleep(1);
+ }
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__);
+ return 0;
+}
+
+/*
+ * clear the hold on the bus, and take of anything else
+ * that has been configured
+ */
+static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
+{
+ show_state(i2c);
+
+ if (errcode < 0) {
+ udelay(100); /* simple delay */
+ } else {
+ /* we need to wait for the stop condition to end */
+
+ /* if we where in stop, then clear... */
+ if (ICR & ICR_STOP) {
+ udelay(100);
+ ICR &= ~ICR_STOP;
+ }
+
+ if (!i2c_pxa_wait_slave(i2c)) {
+ dev_err(&i2c->adap.dev, "%s: wait timedout\n",
+ __func__);
+ return;
+ }
+ }
+
+ ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA);
+ ICR &= ~ICR_SCLE;
+
+ if (i2c_debug) {
+ dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR);
+ decode_ICR(ICR);
+ }
+}
+#else
+#define i2c_pxa_set_slave(i2c, err) do { } while (0)
+#endif
+
+static void i2c_pxa_reset(struct pxa_i2c *i2c)
+{
+ pr_debug("Resetting I2C Controller Unit\n");
+
+ /* abort any transfer currently under way */
+ i2c_pxa_abort(i2c);
+
+ /* reset according to 9.8 */
+ ICR = ICR_UR;
+ ISR = I2C_ISR_INIT;
+ ICR &= ~ICR_UR;
+
+ ISAR = i2c->slave_addr;
+
+ /* set control register values */
+ ICR = I2C_ICR_INIT;
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ dev_info(&i2c->adap.dev, "Enabling slave mode\n");
+ ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE;
+#endif
+
+ i2c_pxa_set_slave(i2c, 0);
+
+ /* enable unit */
+ ICR |= ICR_IUE;
+ udelay(100);
+}
+
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+/*
+ * I2C EEPROM emulation.
+ */
+static struct i2c_eeprom_emu eeprom = {
+ .size = I2C_EEPROM_EMU_SIZE,
+ .watch = LIST_HEAD_INIT(eeprom.watch),
+};
+
+struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void)
+{
+ return &eeprom;
+}
+
+int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data,
+ unsigned int addr, unsigned int size,
+ struct i2c_eeprom_emu_watcher *watcher)
+{
+ struct i2c_eeprom_emu_watch *watch;
+ unsigned long flags;
+
+ if (addr + size > emu->size)
+ return -EINVAL;
+
+ watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL);
+ if (watch) {
+ watch->start = addr;
+ watch->end = addr + size - 1;
+ watch->ops = watcher;
+ watch->data = data;
+
+ local_irq_save(flags);
+ list_add(&watch->node, &emu->watch);
+ local_irq_restore(flags);
+ }
+
+ return watch ? 0 : -ENOMEM;
+}
+
+void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data,
+ struct i2c_eeprom_emu_watcher *watcher)
+{
+ struct i2c_eeprom_emu_watch *watch, *n;
+ unsigned long flags;
+
+ list_for_each_entry_safe(watch, n, &emu->watch, node) {
+ if (watch->ops == watcher && watch->data == data) {
+ local_irq_save(flags);
+ list_del(&watch->node);
+ local_irq_restore(flags);
+ kfree(watch);
+ }
+ }
+}
+
+static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+
+ eedbg(3, "i2c_eeprom_emu_event: %d\n", event);
+
+ switch (event) {
+ case I2C_SLAVE_EVENT_START_WRITE:
+ emu->seen_start = 1;
+ eedbg(2, "i2c_eeprom: write initiated\n");
+ break;
+
+ case I2C_SLAVE_EVENT_START_READ:
+ emu->seen_start = 0;
+ eedbg(2, "i2c_eeprom: read initiated\n");
+ break;
+
+ case I2C_SLAVE_EVENT_STOP:
+ emu->seen_start = 0;
+ eedbg(2, "i2c_eeprom: received stop\n");
+ break;
+
+ default:
+ eedbg(0, "i2c_eeprom: unhandled event\n");
+ break;
+ }
+}
+
+static int i2c_eeprom_emu_read(void *ptr)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+ int ret;
+
+ ret = emu->bytes[emu->ptr];
+ emu->ptr = (emu->ptr + 1) % emu->size;
+
+ return ret;
+}
+
+static void i2c_eeprom_emu_write(void *ptr, unsigned int val)
+{
+ struct i2c_eeprom_emu *emu = ptr;
+ struct i2c_eeprom_emu_watch *watch;
+
+ if (emu->seen_start != 0) {
+ eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val);
+ emu->ptr = val;
+ emu->seen_start = 0;
+ return;
+ }
+
+ emu->bytes[emu->ptr] = val;
+
+ eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n",
+ emu->ptr, val);
+
+ list_for_each_entry(watch, &emu->watch, node) {
+ if (!watch->ops || !watch->ops->write)
+ continue;
+ if (watch->start <= emu->ptr && watch->end >= emu->ptr)
+ watch->ops->write(watch->data, emu->ptr, val);
+ }
+
+ emu->ptr = (emu->ptr + 1) % emu->size;
+}
+
+struct i2c_slave_client eeprom_client = {
+ .data = &eeprom,
+ .event = i2c_eeprom_emu_event,
+ .read = i2c_eeprom_emu_read,
+ .write = i2c_eeprom_emu_write
+};
+
+/*
+ * PXA I2C Slave mode
+ */
+
+static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ if (isr & ISR_BED) {
+ /* what should we do here? */
+ } else {
+ int ret = i2c->slave->read(i2c->slave->data);
+
+ IDBR = ret;
+ ICR |= ICR_TB; /* allow next byte */
+ }
+}
+
+static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ unsigned int byte = IDBR;
+
+ if (i2c->slave != NULL)
+ i2c->slave->write(i2c->slave->data, byte);
+
+ ICR |= ICR_TB;
+}
+
+static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
+{
+ int timeout;
+
+ if (i2c_debug > 0)
+ dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n",
+ (isr & ISR_RWM) ? 'r' : 't');
+
+ if (i2c->slave != NULL)
+ i2c->slave->event(i2c->slave->data,
+ (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE);
+
+ /*
+ * slave could interrupt in the middle of us generating a
+ * start condition... if this happens, we'd better back off
+ * and stop holding the poor thing up
+ */
+ ICR &= ~(ICR_START|ICR_STOP);
+ ICR |= ICR_TB;
+
+ timeout = 0x10000;
+
+ while (1) {
+ if ((IBMR & 2) == 2)
+ break;
+
+ timeout--;
+
+ if (timeout <= 0) {
+ dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
+ break;
+ }
+ }
+
+ ICR &= ~ICR_SCLE;
+}
+
+static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
+{
+ if (i2c_debug > 2)
+ dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n");
+
+ if (i2c->slave != NULL)
+ i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP);
+
+ if (i2c_debug > 2)
+ dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n");
+
+ /*
+ * If we have a master-mode message waiting,
+ * kick it off now that the slave has completed.
+ */
+ if (i2c->msg)
+ i2c_pxa_master_complete(i2c, I2C_RETRY);
+}
+#else
+static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ if (isr & ISR_BED) {
+ /* what should we do here? */
+ } else {
+ IDBR = 0;
+ ICR |= ICR_TB;
+ }
+}
+
+static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ ICR |= ICR_TB | ICR_ACKNAK;
+}
+
+static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
+{
+ int timeout;
+
+ /*
+ * slave could interrupt in the middle of us generating a
+ * start condition... if this happens, we'd better back off
+ * and stop holding the poor thing up
+ */
+ ICR &= ~(ICR_START|ICR_STOP);
+ ICR |= ICR_TB | ICR_ACKNAK;
+
+ timeout = 0x10000;
+
+ while (1) {
+ if ((IBMR & 2) == 2)
+ break;
+
+ timeout--;
+
+ if (timeout <= 0) {
+ dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n");
+ break;
+ }
+ }
+
+ ICR &= ~ICR_SCLE;
+}
+
+static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
+{
+ if (i2c->msg)
+ i2c_pxa_master_complete(i2c, I2C_RETRY);
+}
+#endif
+
+/*
+ * PXA I2C Master mode
+ */
+
+static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg)
+{
+ unsigned int addr = (msg->addr & 0x7f) << 1;
+
+ if (msg->flags & I2C_M_RD)
+ addr |= 1;
+
+ return addr;
+}
+
+static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
+{
+ u32 icr;
+
+ /*
+ * Step 1: target slave address into IDBR
+ */
+ IDBR = i2c_pxa_addr_byte(i2c->msg);
+
+ /*
+ * Step 2: initiate the write.
+ */
+ icr = ICR & ~(ICR_STOP | ICR_ALDIE);
+ ICR = icr | ICR_START | ICR_TB;
+}
+
+/*
+ * We are protected by the adapter bus semaphore.
+ */
+static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
+{
+ long timeout;
+ int ret;
+
+ /*
+ * Wait for the bus to become free.
+ */
+ ret = i2c_pxa_wait_bus_not_busy(i2c);
+ if (ret) {
+ dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n");
+ goto out;
+ }
+
+ /*
+ * Set master mode.
+ */
+ ret = i2c_pxa_set_master(i2c);
+ if (ret) {
+ dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret);
+ goto out;
+ }
+
+ spin_lock_irq(&i2c->lock);
+
+ i2c->msg = msg;
+ i2c->msg_num = num;
+ i2c->msg_idx = 0;
+ i2c->msg_ptr = 0;
+ i2c->irqlogidx = 0;
+
+ i2c_pxa_start_message(i2c);
+
+ spin_unlock_irq(&i2c->lock);
+
+ /*
+ * The rest of the processing occurs in the interrupt handler.
+ */
+ timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
+
+ /*
+ * We place the return code in i2c->msg_idx.
+ */
+ ret = i2c->msg_idx;
+
+ if (timeout == 0)
+ i2c_pxa_scream_blue_murder(i2c, "timeout");
+
+ out:
+ return ret;
+}
+
+/*
+ * i2c_pxa_master_complete - complete the message and wake up.
+ */
+static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
+{
+ i2c->msg_ptr = 0;
+ i2c->msg = NULL;
+ i2c->msg_idx ++;
+ i2c->msg_num = 0;
+ if (ret)
+ i2c->msg_idx = ret;
+ wake_up(&i2c->wait);
+}
+
+static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
+{
+ u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+
+ again:
+ /*
+ * If ISR_ALD is set, we lost arbitration.
+ */
+ if (isr & ISR_ALD) {
+ /*
+ * Do we need to do anything here? The PXA docs
+ * are vague about what happens.
+ */
+ i2c_pxa_scream_blue_murder(i2c, "ALD set");
+
+ /*
+ * We ignore this error. We seem to see spurious ALDs
+ * for seemingly no reason. If we handle them as I think
+ * they should, we end up causing an I2C error, which
+ * is painful for some systems.
+ */
+ return; /* ignore */
+ }
+
+ if (isr & ISR_BED) {
+ int ret = BUS_ERROR;
+
+ /*
+ * I2C bus error - either the device NAK'd us, or
+ * something more serious happened. If we were NAK'd
+ * on the initial address phase, we can retry.
+ */
+ if (isr & ISR_ACKNAK) {
+ if (i2c->msg_ptr == 0 && i2c->msg_idx == 0)
+ ret = I2C_RETRY;
+ else
+ ret = XFER_NAKED;
+ }
+ i2c_pxa_master_complete(i2c, ret);
+ } else if (isr & ISR_RWM) {
+ /*
+ * Read mode. We have just sent the address byte, and
+ * now we must initiate the transfer.
+ */
+ if (i2c->msg_ptr == i2c->msg->len - 1 &&
+ i2c->msg_idx == i2c->msg_num - 1)
+ icr |= ICR_STOP | ICR_ACKNAK;
+
+ icr |= ICR_ALDIE | ICR_TB;
+ } else if (i2c->msg_ptr < i2c->msg->len) {
+ /*
+ * Write mode. Write the next data byte.
+ */
+ IDBR = i2c->msg->buf[i2c->msg_ptr++];
+
+ icr |= ICR_ALDIE | ICR_TB;
+
+ /*
+ * If this is the last byte of the last message, send
+ * a STOP.
+ */
+ if (i2c->msg_ptr == i2c->msg->len &&
+ i2c->msg_idx == i2c->msg_num - 1)
+ icr |= ICR_STOP;
+ } else if (i2c->msg_idx < i2c->msg_num - 1) {
+ /*
+ * Next segment of the message.
+ */
+ i2c->msg_ptr = 0;
+ i2c->msg_idx ++;
+ i2c->msg++;
+
+ /*
+ * If we aren't doing a repeated start and address,
+ * go back and try to send the next byte. Note that
+ * we do not support switching the R/W direction here.
+ */
+ if (i2c->msg->flags & I2C_M_NOSTART)
+ goto again;
+
+ /*
+ * Write the next address.
+ */
+ IDBR = i2c_pxa_addr_byte(i2c->msg);
+
+ /*
+ * And trigger a repeated start, and send the byte.
+ */
+ icr &= ~ICR_ALDIE;
+ icr |= ICR_START | ICR_TB;
+ } else {
+ if (i2c->msg->len == 0) {
+ /*
+ * Device probes have a message length of zero
+ * and need the bus to be reset before it can
+ * be used again.
+ */
+ i2c_pxa_reset(i2c);
+ }
+ i2c_pxa_master_complete(i2c, 0);
+ }
+
+ i2c->icrlog[i2c->irqlogidx-1] = icr;
+
+ ICR = icr;
+ show_state(i2c);
+}
+
+static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
+{
+ u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+
+ /*
+ * Read the byte.
+ */
+ i2c->msg->buf[i2c->msg_ptr++] = IDBR;
+
+ if (i2c->msg_ptr < i2c->msg->len) {
+ /*
+ * If this is the last byte of the last
+ * message, send a STOP.
+ */
+ if (i2c->msg_ptr == i2c->msg->len - 1)
+ icr |= ICR_STOP | ICR_ACKNAK;
+
+ icr |= ICR_ALDIE | ICR_TB;
+ } else {
+ i2c_pxa_master_complete(i2c, 0);
+ }
+
+ i2c->icrlog[i2c->irqlogidx-1] = icr;
+
+ ICR = icr;
+}
+
+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pxa_i2c *i2c = dev_id;
+ u32 isr = ISR;
+
+ if (i2c_debug > 2 && 0) {
+ dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
+ __func__, isr, ICR, IBMR);
+ decode_ISR(isr);
+ }
+
+ if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
+ i2c->isrlog[i2c->irqlogidx++] = isr;
+
+ show_state(i2c);
+
+ /*
+ * Always clear all pending IRQs.
+ */
+ ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED);
+
+ if (isr & ISR_SAD)
+ i2c_pxa_slave_start(i2c, isr);
+ if (isr & ISR_SSD)
+ i2c_pxa_slave_stop(i2c);
+
+ if (i2c_pxa_is_slavemode(i2c)) {
+ if (isr & ISR_ITE)
+ i2c_pxa_slave_txempty(i2c, isr);
+ if (isr & ISR_IRF)
+ i2c_pxa_slave_rxfull(i2c, isr);
+ } else if (i2c->msg) {
+ if (isr & ISR_ITE)
+ i2c_pxa_irq_txempty(i2c, isr);
+ if (isr & ISR_IRF)
+ i2c_pxa_irq_rxfull(i2c, isr);
+ } else {
+ i2c_pxa_scream_blue_murder(i2c, "spurious irq");
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+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;
+
+ for (i = adap->retries; i >= 0; i--) {
+ ret = i2c_pxa_do_xfer(i2c, msgs, num);
+ if (ret != I2C_RETRY)
+ goto out;
+
+ if (i2c_debug)
+ dev_dbg(&adap->dev, "Retrying transmission\n");
+ udelay(100);
+ }
+ i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
+ ret = -EREMOTEIO;
+ out:
+ i2c_pxa_set_slave(i2c, ret);
+ return ret;
+}
+
+static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm i2c_pxa_algorithm = {
+ .master_xfer = i2c_pxa_xfer,
+ .functionality = i2c_pxa_functionality,
+};
+
+static struct pxa_i2c i2c_pxa = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
+ .adap = {
+ .owner = THIS_MODULE,
+ .algo = &i2c_pxa_algorithm,
+ .name = "pxa2xx-i2c",
+ .retries = 5,
+ },
+};
+
+static int i2c_pxa_probe(struct device *dev)
+{
+ struct pxa_i2c *i2c = &i2c_pxa;
+ struct i2c_pxa_platform_data *plat = dev->platform_data;
+ int ret;
+
+#ifdef CONFIG_PXA27x
+ pxa_gpio_mode(GPIO117_I2CSCL_MD);
+ pxa_gpio_mode(GPIO118_I2CSDA_MD);
+ udelay(100);
+#endif
+
+ i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ i2c->slave = &eeprom_client;
+ if (plat) {
+ i2c->slave_addr = plat->slave_addr;
+ if (plat->slave)
+ i2c->slave = plat->slave;
+ }
+#endif
+
+ pxa_set_cken(CKEN14_I2C, 1);
+ ret = request_irq(IRQ_I2C, i2c_pxa_handler, SA_INTERRUPT,
+ "pxa2xx-i2c", i2c);
+ if (ret)
+ goto out;
+
+ i2c_pxa_reset(i2c);
+
+ i2c->adap.algo_data = i2c;
+ i2c->adap.dev.parent = dev;
+
+ ret = i2c_add_adapter(&i2c->adap);
+ if (ret < 0) {
+ printk(KERN_INFO "I2C: Failed to add bus\n");
+ goto err_irq;
+ }
+
+ dev_set_drvdata(dev, i2c);
+
+#ifdef CONFIG_I2C_PXA_SLAVE
+ printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n",
+ i2c->adap.dev.bus_id, i2c->slave_addr);
+#else
+ printk(KERN_INFO "I2C: %s: PXA I2C adapter\n",
+ i2c->adap.dev.bus_id);
+#endif
+ return 0;
+
+ err_irq:
+ free_irq(IRQ_I2C, i2c);
+ out:
+ return ret;
+}
+
+static int i2c_pxa_remove(struct device *dev)
+{
+ struct pxa_i2c *i2c = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ i2c_del_adapter(&i2c->adap);
+ free_irq(IRQ_I2C, i2c);
+ pxa_set_cken(CKEN14_I2C, 0);
+
+ return 0;
+}
+
+static struct device_driver i2c_pxa_driver = {
+ .name = "pxa2xx-i2c",
+ .bus = &platform_bus_type,
+ .probe = i2c_pxa_probe,
+ .remove = i2c_pxa_remove,
+};
+
+static int __init i2c_adap_pxa_init(void)
+{
+ return driver_register(&i2c_pxa_driver);
+}
+
+static void i2c_adap_pxa_exit(void)
+{
+ return driver_unregister(&i2c_pxa_driver);
+}
+
+module_init(i2c_adap_pxa_init);
+module_exit(i2c_adap_pxa_exit);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index a3b38257cc3d..1b582262e677 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -33,7 +33,7 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -568,7 +568,6 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
/* i2c bus registration info */
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
- .name = "S3C2410-I2C-Algorithm",
.master_xfer = s3c24xx_i2c_xfer,
.functionality = s3c24xx_i2c_func,
};
@@ -880,14 +879,12 @@ static int s3c24xx_i2c_remove(struct device *dev)
}
#ifdef CONFIG_PM
-static int s3c24xx_i2c_resume(struct device *dev, u32 level)
+static int s3c24xx_i2c_resume(struct device *dev)
{
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
-
- if (i2c != NULL && level == RESUME_ENABLE) {
- dev_dbg(dev, "resume: level %d\n", level);
+
+ if (i2c != NULL)
s3c24xx_i2c_init(i2c);
- }
return 0;
}
@@ -899,6 +896,7 @@ static int s3c24xx_i2c_resume(struct device *dev, u32 level)
/* device driver for platform bus bits */
static struct device_driver s3c2410_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2410-i2c",
.bus = &platform_bus_type,
.probe = s3c24xx_i2c_probe,
@@ -907,6 +905,7 @@ static struct device_driver s3c2410_i2c_driver = {
};
static struct device_driver s3c2440_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2440-i2c",
.bus = &platform_bus_type,
.probe = s3c24xx_i2c_probe,
@@ -919,8 +918,11 @@ static int __init i2c_adap_s3c_init(void)
int ret;
ret = driver_register(&s3c2410_i2c_driver);
- if (ret == 0)
- ret = driver_register(&s3c2440_i2c_driver);
+ if (ret == 0) {
+ ret = driver_register(&s3c2440_i2c_driver);
+ if (ret)
+ driver_unregister(&s3c2410_i2c_driver);
+ }
return ret;
}
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 0c8518298e4d..aebe87ba4033 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -179,6 +179,7 @@ static void __devexit savage4_remove(struct pci_dev *dev)
}
static struct pci_driver savage4_driver = {
+ .owner = THIS_MODULE,
.name = "savage4_smbus",
.id_table = savage4_ids,
.probe = savage4_probe,
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 1c99536b673b..fa503ed9f86d 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -23,8 +23,8 @@
#include <asm/sibyte/sb1250_smbus.h>
static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
- { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
- { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+ { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
+ { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
};
static struct i2c_adapter sibyte_board_adapter[2] = {
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index bbd5e4e52f09..3ad27c3ba15b 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -123,11 +123,12 @@ static int blacklist[] = {
/* If force_addr is set to anything different from 0, we forcibly enable
the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
-static unsigned short sis5595_base = 0;
+static struct pci_driver sis5595_driver;
+static unsigned short sis5595_base;
static u8 sis5595_read(u8 reg)
{
@@ -172,7 +173,8 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev)
/* NB: We grab just the two SMBus registers here, but this may still
* interfere with ACPI :-( */
- if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) {
+ if (!request_region(sis5595_base + SMB_INDEX, 2,
+ sis5595_driver.name)) {
dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
return -ENODEV;
@@ -357,8 +359,6 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis5595_access,
.functionality = sis5595_func,
};
@@ -366,7 +366,6 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
@@ -399,6 +398,7 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
}
static struct pci_driver sis5595_driver = {
+ .owner = THIS_MODULE,
.name = "sis5595_smbus",
.id_table = sis5595_ids,
.probe = sis5595_probe,
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index f58455e7689e..7f49e5fd3ff0 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -92,6 +92,8 @@
#define SIS630_PCALL 0x04
#define SIS630_BLOCK_DATA 0x05
+static struct pci_driver sis630_driver;
+
/* insmod parameters */
static int high_clock;
static int force;
@@ -101,7 +103,7 @@ module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
/* acpi base address */
-static unsigned short acpi_base = 0;
+static unsigned short acpi_base;
/* supported chips */
static int supported[] = {
@@ -432,7 +434,8 @@ static int sis630_setup(struct pci_dev *sis630_dev)
dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
/* Everything is happy, let's grab the memory and set things up. */
- if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
+ if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
+ sis630_driver.name)) {
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
goto exit;
@@ -448,8 +451,6 @@ exit:
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis630_access,
.functionality = sis630_func,
};
@@ -457,7 +458,6 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
@@ -496,6 +496,7 @@ static void __devexit sis630_remove(struct pci_dev *dev)
static struct pci_driver sis630_driver = {
+ .owner = THIS_MODULE,
.name = "sis630_smbus",
.id_table = sis630_ids,
.probe = sis630_probe,
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 6484792e23a1..6a134c091324 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -82,8 +82,9 @@
#define SIS96x_PROC_CALL 0x04
#define SIS96x_BLOCK_DATA 0x05
+static struct pci_driver sis96x_driver;
static struct i2c_adapter sis96x_adapter;
-static u16 sis96x_smbus_base = 0;
+static u16 sis96x_smbus_base;
static inline u8 sis96x_read(u8 reg)
{
@@ -249,8 +250,6 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = sis96x_access,
.functionality = sis96x_func,
};
@@ -259,7 +258,6 @@ static struct i2c_adapter sis96x_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id sis96x_ids[] = {
@@ -296,7 +294,8 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
sis96x_smbus_base);
/* Everything is happy, let's grab the memory and set things up. */
- if (!request_region(sis96x_smbus_base, SMB_IOSIZE, "sis96x-smbus")) {
+ if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
+ sis96x_driver.name)) {
dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x "
"already in use!\n", sis96x_smbus_base,
sis96x_smbus_base + SMB_IOSIZE - 1);
@@ -330,6 +329,7 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
}
static struct pci_driver sis96x_driver = {
+ .owner = THIS_MODULE,
.name = "sis96x_smbus",
.id_table = sis96x_ids,
.probe = sis96x_probe,
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 00d94e886955..73f481e93a36 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -109,8 +109,6 @@ static u32 stub_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.functionality = stub_func,
.smbus_xfer = stub_xfer,
};
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 040b8abeabba..544a38e64394 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -43,9 +43,9 @@
/* io-region reservation */
#define IOSPACE 0x06
-#define IOTEXT "via-i2c"
-static u16 pm_io_base = 0;
+static struct pci_driver vt586b_driver;
+static u16 pm_io_base;
/*
It does not appear from the datasheet that the GPIO pins are
@@ -130,7 +130,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
pci_read_config_word(dev, base, &pm_io_base);
pm_io_base &= (0xff << 8);
- if (!request_region(I2C_DIR, IOSPACE, IOTEXT)) {
+ if (!request_region(I2C_DIR, IOSPACE, vt586b_driver.name)) {
dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE);
return -ENODEV;
}
@@ -159,6 +159,7 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
static struct pci_driver vt586b_driver = {
+ .owner = THIS_MODULE,
.name = "vt586b_smbus",
.id_table = vt586b_ids,
.probe = vt586b_probe,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 6b5008005c6f..c9366b504833 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -1,9 +1,10 @@
/*
i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
- Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
+ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Copyright (C) 2005 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
@@ -21,15 +22,19 @@
*/
/*
- Supports Via devices:
- 82C596A/B (0x3050)
- 82C596B (0x3051)
- 82C686A/B
- 8231
- 8233
- 8233A (0x3147 and 0x3177)
- 8235
- 8237
+ Supports the following VIA south bridges:
+
+ Chip name PCI ID REV I2C block
+ VT82C596A 0x3050 no
+ VT82C596B 0x3051 no
+ VT82C686A 0x3057 0x30 no
+ VT82C686B 0x3057 0x40 yes
+ VT8231 0x8235 no?
+ VT8233 0x3074 yes
+ VT8233A 0x3147 yes?
+ VT8235 0x3177 yes
+ VT8237R 0x3227 yes
+
Note: we assume there can only be one device, with one SMBus interface.
*/
@@ -38,7 +43,6 @@
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
@@ -46,48 +50,37 @@
static struct pci_dev *vt596_pdev;
-#define SMBBA1 0x90
-#define SMBBA2 0x80
-#define SMBBA3 0xD0
+#define SMBBA1 0x90
+#define SMBBA2 0x80
+#define SMBBA3 0xD0
/* SMBus address offsets */
static unsigned short vt596_smba;
#define SMBHSTSTS (vt596_smba + 0)
-#define SMBHSLVSTS (vt596_smba + 1)
#define SMBHSTCNT (vt596_smba + 2)
#define SMBHSTCMD (vt596_smba + 3)
#define SMBHSTADD (vt596_smba + 4)
#define SMBHSTDAT0 (vt596_smba + 5)
#define SMBHSTDAT1 (vt596_smba + 6)
#define SMBBLKDAT (vt596_smba + 7)
-#define SMBSLVCNT (vt596_smba + 8)
-#define SMBSHDWCMD (vt596_smba + 9)
-#define SMBSLVEVT (vt596_smba + 0xA)
-#define SMBSLVDAT (vt596_smba + 0xC)
/* PCI Address Constants */
/* SMBus data in configuration space can be found in two places,
- We try to select the better one*/
-
-static unsigned short smb_cf_hstcfg = 0xD2;
+ We try to select the better one */
-#define SMBHSTCFG (smb_cf_hstcfg)
-#define SMBSLVC (smb_cf_hstcfg + 1)
-#define SMBSHDW1 (smb_cf_hstcfg + 2)
-#define SMBSHDW2 (smb_cf_hstcfg + 3)
-#define SMBREV (smb_cf_hstcfg + 4)
+static unsigned short SMBHSTCFG = 0xD2;
/* Other settings */
#define MAX_TIMEOUT 500
-#define ENABLE_INT9 0
/* VT82C596 constants */
-#define VT596_QUICK 0x00
-#define VT596_BYTE 0x04
-#define VT596_BYTE_DATA 0x08
-#define VT596_WORD_DATA 0x0C
-#define VT596_BLOCK_DATA 0x14
+#define VT596_QUICK 0x00
+#define VT596_BYTE 0x04
+#define VT596_BYTE_DATA 0x08
+#define VT596_WORD_DATA 0x0C
+#define VT596_BLOCK_DATA 0x14
+#define VT596_I2C_BLOCK_DATA 0x34
/* If force is set to anything different from 0, we forcibly enable the
@@ -105,40 +98,65 @@ MODULE_PARM_DESC(force_addr,
"EXTREMELY DANGEROUS!");
+static struct pci_driver vt596_driver;
static struct i2c_adapter vt596_adapter;
-/* Another internally used function */
-static int vt596_transaction(void)
+#define FEATURE_I2CBLOCK (1<<0)
+static unsigned int vt596_features;
+
+#ifdef DEBUG
+static void vt596_dump_regs(const char *msg, u8 size)
+{
+ dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
+ "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+ inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+ inb_p(SMBHSTDAT1));
+
+ if (size == VT596_BLOCK_DATA
+ || size == VT596_I2C_BLOCK_DATA) {
+ int i;
+
+ dev_dbg(&vt596_adapter.dev, "BLK=");
+ for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
+ printk("%02x,", inb_p(SMBBLKDAT));
+ printk("\n");
+ dev_dbg(&vt596_adapter.dev, " ");
+ for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
+ printk("%02x,", inb_p(SMBBLKDAT));
+ printk("%02x\n", inb_p(SMBBLKDAT));
+ }
+}
+#else
+static inline void vt596_dump_regs(const char *msg, u8 size) { }
+#endif
+
+/* Return -1 on error, 0 on success */
+static int vt596_transaction(u8 size)
{
int temp;
int result = 0;
int timeout = 0;
- dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
- inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
- inb_p(SMBHSTDAT1));
+ vt596_dump_regs("Transaction (pre)", size);
/* Make sure the SMBus host is ready to start transmitting */
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
- "Resetting...\n", temp);
-
+ "Resetting... ", temp);
+
outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
- dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
-
+ printk("Failed! (0x%02x)\n", temp);
return -1;
} else {
- dev_dbg(&vt596_adapter.dev, "Successfull!\n");
+ printk("Successful!\n");
}
}
- /* start the transaction by setting bit 6 */
- outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+ /* Start the transaction by setting bit 6 */
+ outb_p(0x40 | (size & 0x3C), SMBHSTCNT);
- /* We will always wait for a fraction of a second!
- I don't know if VIA needs this, Intel did */
+ /* We will always wait for a fraction of a second */
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
@@ -147,77 +165,61 @@ static int vt596_transaction(void)
/* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n");
+ dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
}
if (temp & 0x10) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n");
+ dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
+ inb_p(SMBHSTCNT) & 0x3C);
}
if (temp & 0x08) {
result = -1;
- dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be "
- "locked until next hard\nreset. (sorry!)\n");
- /* Clock stops and slave is stuck in mid-transmission */
+ dev_err(&vt596_adapter.dev, "SMBus collision!\n");
}
if (temp & 0x04) {
result = -1;
- dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
+ /* Quick commands are used to probe for chips, so
+ errors are expected, and we don't want to frighten the
+ user. */
+ if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
+ dev_err(&vt596_adapter.dev, "Transaction error!\n");
}
- if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ /* Resetting status register */
+ if (temp & 0x1F)
outb_p(temp, SMBHSTSTS);
- if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
- dev_warn(&vt596_adapter.dev, "Failed reset at end "
- "of transaction (%02x)\n", temp);
- }
- }
- dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
- inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
- inb_p(SMBHSTDAT1));
-
+ vt596_dump_regs("Transaction (post)", size);
+
return result;
}
-/* Return -1 on error. */
+/* Return -1 on error, 0 on success */
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write, u8 command,
- int size, union i2c_smbus_data *data)
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
{
- int i, len;
+ int i;
switch (size) {
- case I2C_SMBUS_PROC_CALL:
- dev_info(&vt596_adapter.dev,
- "I2C_SMBUS_PROC_CALL not supported!\n");
- return -1;
case I2C_SMBUS_QUICK:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
size = VT596_QUICK;
break;
case I2C_SMBUS_BYTE:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMBHSTCMD);
size = VT596_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE)
outb_p(data->byte, SMBHSTDAT0);
size = VT596_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
outb_p(data->word & 0xff, SMBHSTDAT0);
@@ -225,28 +227,33 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
}
size = VT596_WORD_DATA;
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (!(vt596_features & FEATURE_I2CBLOCK))
+ goto exit_unsupported;
+ if (read_write == I2C_SMBUS_READ)
+ outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+ /* Fall through */
case I2C_SMBUS_BLOCK_DATA:
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- SMBHSTADD);
outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) {
- len = data->block[0];
- if (len < 0)
- len = 0;
+ u8 len = data->block[0];
if (len > I2C_SMBUS_BLOCK_MAX)
len = I2C_SMBUS_BLOCK_MAX;
outb_p(len, SMBHSTDAT0);
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
outb_p(data->block[i], SMBBLKDAT);
}
- size = VT596_BLOCK_DATA;
+ size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
+ VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
break;
+ default:
+ goto exit_unsupported;
}
- outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+ outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
- if (vt596_transaction()) /* Error in transaction */
+ if (vt596_transaction(size)) /* Error in transaction */
return -1;
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
@@ -254,40 +261,42 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
switch (size) {
case VT596_BYTE:
- /* Where is the result put? I assume here it is in
- * SMBHSTDAT0 but it might just as well be in the
- * SMBHSTCMD. No clue in the docs
- */
- data->byte = inb_p(SMBHSTDAT0);
- break;
case VT596_BYTE_DATA:
data->byte = inb_p(SMBHSTDAT0);
break;
case VT596_WORD_DATA:
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
break;
+ case VT596_I2C_BLOCK_DATA:
case VT596_BLOCK_DATA:
data->block[0] = inb_p(SMBHSTDAT0);
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
data->block[0] = I2C_SMBUS_BLOCK_MAX;
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
break;
}
return 0;
+
+exit_unsupported:
+ dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
+ size);
+ return -1;
}
static u32 vt596_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ 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;
+
+ if (vt596_features & FEATURE_I2CBLOCK)
+ func |= I2C_FUNC_SMBUS_I2C_BLOCK;
+ return func;
}
static struct i2c_algorithm smbus_algorithm = {
- .name = "Non-I2C SMBus adapter",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = vt596_access,
.functionality = vt596_func,
};
@@ -296,7 +305,6 @@ static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static int __devinit vt596_probe(struct pci_dev *pdev,
@@ -304,7 +312,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
{
unsigned char temp;
int error = -ENODEV;
-
+
/* Determine the address of the SMBus areas */
if (force_addr) {
vt596_smba = force_addr & 0xfff0;
@@ -313,12 +321,12 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
}
if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
- !(vt596_smba & 0x1)) {
+ !(vt596_smba & 0x0001)) {
/* try 2nd address and config reg. for 596 */
if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
!pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
- (vt596_smba & 0x1)) {
- smb_cf_hstcfg = 0x84;
+ (vt596_smba & 0x0001)) {
+ SMBHSTCFG = 0x84;
} else {
/* no matches at all */
dev_err(&pdev->dev, "Cannot configure "
@@ -335,10 +343,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
return -ENODEV;
}
- found:
- if (!request_region(vt596_smba, 8, "viapro-smbus")) {
+found:
+ if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
- vt596_smba);
+ vt596_smba);
return -ENODEV;
}
@@ -350,16 +358,16 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
pci_write_config_word(pdev, id->driver_data, vt596_smba);
pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
- "address 0x%04x!\n", vt596_smba);
- } else if ((temp & 1) == 0) {
+ "address 0x%04x!\n", vt596_smba);
+ } else if (!(temp & 0x01)) {
if (force) {
- /* NOTE: This assumes I/O space and other allocations
- * WERE done by the Bios! Don't complain if your
- * hardware does weird things after enabling this.
- * :') Check for Bios updates before resorting to
+ /* NOTE: This assumes I/O space and other allocations
+ * WERE done by the Bios! Don't complain if your
+ * hardware does weird things after enabling this.
+ * :') Check for Bios updates before resorting to
* this.
*/
- pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
+ pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
dev_info(&pdev->dev, "Enabling SMBus device\n");
} else {
dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
@@ -369,22 +377,28 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
}
}
- if ((temp & 0x0E) == 8)
- dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n");
- else if ((temp & 0x0E) == 0)
- dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n");
- else
- dev_dbg(&pdev->dev, "Illegal Interrupt configuration "
- "(or code out of date)!\n");
-
- pci_read_config_byte(pdev, SMBREV, &temp);
- dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_VIA_8237:
+ case PCI_DEVICE_ID_VIA_8235:
+ case PCI_DEVICE_ID_VIA_8233A:
+ case PCI_DEVICE_ID_VIA_8233_0:
+ vt596_features |= FEATURE_I2CBLOCK;
+ break;
+ case PCI_DEVICE_ID_VIA_82C686_4:
+ /* The VT82C686B (rev 0x40) does support I2C block
+ transactions, but the VT82C686A (rev 0x30) doesn't */
+ if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
+ && temp >= 0x40)
+ vt596_features |= FEATURE_I2CBLOCK;
+ break;
+ }
+
vt596_adapter.dev.parent = &pdev->dev;
snprintf(vt596_adapter.name, I2C_NAME_SIZE,
- "SMBus Via Pro adapter at %04x", vt596_smba);
-
+ "SMBus Via Pro adapter at %04x", vt596_smba);
+
vt596_pdev = pci_dev_get(pdev);
if (i2c_add_adapter(&vt596_adapter)) {
pci_dev_put(vt596_pdev);
@@ -397,7 +411,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
*/
return -ENODEV;
- release_region:
+release_region:
release_region(vt596_smba, 8);
return error;
}
@@ -422,9 +436,10 @@ static struct pci_device_id vt596_ids[] = {
{ 0, }
};
-MODULE_DEVICE_TABLE (pci, vt596_ids);
+MODULE_DEVICE_TABLE(pci, vt596_ids);
static struct pci_driver vt596_driver = {
+ .owner = THIS_MODULE,
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index b675773b0cc1..650c3ebde84c 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -225,6 +225,7 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
}
static struct pci_driver voodoo3_driver = {
+ .owner = THIS_MODULE,
.name = "voodoo3_smbus",
.id_table = voodoo3_ids,
.probe = voodoo3_probe,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index a18bdd9aa7ba..d3478e084522 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -395,8 +395,6 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
/* For now, we only handle combined mode (smbus) */
static struct i2c_algorithm scx200_acb_algorithm = {
- .name = "NatSemi SCx200 ACCESS.bus",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = scx200_acb_smbus_xfer,
.functionality = scx200_acb_func,
};
@@ -444,19 +442,18 @@ static int __init scx200_acb_create(int base, int index)
int rc = 0;
char description[64];
- iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+ iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface) {
printk(KERN_ERR NAME ": can't allocate memory\n");
rc = -ENOMEM;
goto errout;
}
- memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
- adapter->id = I2C_ALGO_SMBUS;
+ adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON;
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 43f70dbfc03f..f9fae28f5612 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -2,17 +2,12 @@
# Miscellaneous I2C chip drivers configuration
#
-config I2C_SENSOR
- tristate
- default n
-
menu "Miscellaneous I2C Chip support"
depends on I2C
config SENSORS_DS1337
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1337 and DS1339 real-time clock chips.
@@ -23,7 +18,6 @@ config SENSORS_DS1337
config SENSORS_DS1374
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
DS1374 real-time clock chips.
@@ -34,7 +28,6 @@ config SENSORS_DS1374
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get read-only access to the EEPROM data
available on modern memory DIMMs and Sony Vaio laptops. Such
@@ -46,7 +39,6 @@ config SENSORS_EEPROM
config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Philips PCF8574 and
PCF8574A chips.
@@ -67,7 +59,6 @@ config SENSORS_PCA9539
config SENSORS_PCF8591
tristate "Philips PCF8591"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for Philips PCF8591 chips.
@@ -77,7 +68,6 @@ config SENSORS_PCF8591
config SENSORS_RTC8564
tristate "Epson 8564 RTC chip"
depends on I2C && EXPERIMENTAL
- select I2C_SENSOR
help
If you say yes here you get support for the Epson 8564 RTC chip.
@@ -136,4 +126,13 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
+config RTC_X1205_I2C
+ tristate "Xicor X1205 RTC chip"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Xicor X1205 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called x1205.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index a876dd42b860..46178b57b1f1 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 82cf959989fd..01b037007410 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -17,7 +17,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
#include <linux/string.h>
#include <linux/rtc.h> /* get the user-level API */
#include <linux/bcd.h>
@@ -39,9 +38,8 @@
* Functions declaration
*/
static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-SENSORS_INSMOD_1(ds1337);
+I2C_CLIENT_INSMOD_1(ds1337);
static int ds1337_attach_adapter(struct i2c_adapter *adapter);
static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
@@ -227,7 +225,7 @@ int ds1337_do_command(int bus, int cmd, void *arg)
static int ds1337_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, ds1337_detect);
+ return i2c_probe(adapter, &addr_data, ds1337_detect);
}
/*
@@ -245,11 +243,10 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
I2C_FUNC_I2C))
goto exit;
- if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct ds1337_data));
INIT_LIST_HEAD(&data->list);
/* The common I2C client data is placed right before the
@@ -354,11 +351,8 @@ static int ds1337_detach_client(struct i2c_client *client)
int err;
struct ds1337_data *data = i2c_get_clientdata(client);
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
list_del(&data->list);
kfree(data);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index a445736d8838..da488b735abf 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -53,7 +53,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
static ulong ds1374_read_rtc(void)
@@ -166,9 +165,10 @@ static void ds1374_set_tlet(ulong arg)
"can't confirm time set from rtc chip\n");
}
-ulong new_time;
+static ulong new_time;
-DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
+ (ulong) & new_time);
int ds1374_set_rtc_time(ulong nowtime)
{
@@ -194,13 +194,11 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
int rc;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
- client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
client->driver = &ds1374_driver;
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index a2da31b0dd7b..4baf573fa04f 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -33,15 +33,13 @@
#include <linux/sched.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(eeprom);
+I2C_CLIENT_INSMOD_1(eeprom);
/* Size of EEPROM in bytes */
@@ -90,8 +88,8 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_I2C_BLOCK_MAX)
- if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_I2C_BLOCK_MAX)
+ for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
+ if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
goto exit;
} else {
if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -153,21 +151,16 @@ static struct bin_attribute eeprom_attr = {
static int eeprom_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, eeprom_detect);
+ return i2c_probe(adapter, &addr_data, eeprom_detect);
}
-/* This function is called by i2c_detect */
-int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct eeprom_data *data;
int err = 0;
- /* prevent 24RF08 corruption */
- if (kind < 0)
- i2c_smbus_xfer(adapter, address, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL);
-
/* There are three ways we can read the EEPROM data:
(1) I2C block reads (faster, but unsupported by most adapters)
(2) Consecutive byte reads (100% overhead)
@@ -178,11 +171,10 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
| I2C_FUNC_SMBUS_BYTE))
goto exit;
- if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct eeprom_data));
new_client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE);
@@ -231,10 +223,8 @@ static int eeprom_detach_client(struct i2c_client *client)
int err;
err = i2c_detach_client(client);
- if (err) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ if (err)
return err;
- }
kfree(i2c_get_clientdata(client));
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 354a26295672..9dbb72fffbe2 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -27,7 +27,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb.h>
@@ -888,6 +888,7 @@ static int otg_remove(struct device *dev)
}
struct device_driver omap_otg_driver = {
+ .owner = THIS_MODULE,
.name = "omap_otg",
.bus = &platform_bus_type,
.probe = otg_probe,
@@ -1489,7 +1490,7 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
if (the_transceiver)
return 0;
- isp = kcalloc(1, sizeof *isp, GFP_KERNEL);
+ isp = kzalloc(sizeof *isp, GFP_KERNEL);
if (!isp)
return 0;
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 778d7e12859d..3df309ae44a6 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -42,7 +42,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
ulong
@@ -145,7 +144,7 @@ m41t00_set_tlet(ulong arg)
return;
}
-ulong new_time;
+static ulong new_time;
DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
@@ -175,13 +174,11 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
int rc;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
- client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
client->driver = &m41t00_driver;
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 0230375f72e5..b376a006883c 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -5,97 +5,60 @@
Based on i2c/chips/eeprom.c
- The MAX6875 has two EEPROM sections: config and user.
- At reset, the config EEPROM is read into the registers.
+ The MAX6875 has a bank of registers and two banks of EEPROM.
+ Address ranges are defined as follows:
+ * 0x0000 - 0x0046 = configuration registers
+ * 0x8000 - 0x8046 = configuration EEPROM
+ * 0x8100 - 0x82FF = user EEPROM
- This driver make 3 binary files available in sysfs:
- reg_config - direct access to the registers
- eeprom_config - acesses configuration eeprom space
- eeprom_user - free for application use
+ This driver makes the user EEPROM available for read.
- In our application, we put device serial & model numbers in user eeprom.
+ The registers & config EEPROM should be accessed via i2c-dev.
- Notes:
- 1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
- be overwritten, so the driver explicitly prevents that.
- 2) It's a good idea to keep the config (0x45) locked in config EEPROM.
- You can temporarily enable config writes by changing register 0x45.
+ The MAX6875 ignores the lowest address bit, so each chip responds to
+ two addresses - 0x50/0x51 and 0x52/0x53.
+
+ Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
+ address, so this driver is destructive if loaded for the wrong EEPROM chip.
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 of the License.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <asm/semaphore.h>
-/* Addresses to scan */
-/* No address scanned by default, as this could corrupt standard EEPROMS. */
+/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
/* Insmod parameters */
-SENSORS_INSMOD_1(max6875);
-
-/* this param will prevent 'accidental' writes to the eeprom */
-static int allow_write = 0;
-module_param(allow_write, int, 0);
-MODULE_PARM_DESC(allow_write,
- "Enable write access:\n"
- "*0: Read only\n"
- " 1: Read/Write access");
+I2C_CLIENT_INSMOD_1(max6875);
/* The MAX6875 can only read/write 16 bytes at a time */
#define SLICE_SIZE 16
#define SLICE_BITS 4
-/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
-#define CONFIG_EEPROM_BASE 0x8000
-#define CONFIG_EEPROM_SIZE 0x0046
-#define CONFIG_EEPROM_SLICES 5
-
/* USER EEPROM is at addresses 0x8100 - 0x82FF */
#define USER_EEPROM_BASE 0x8100
#define USER_EEPROM_SIZE 0x0200
#define USER_EEPROM_SLICES 32
/* MAX6875 commands */
-#define MAX6875_CMD_BLOCK_WRITE 0x83
-#define MAX6875_CMD_BLOCK_READ 0x84
-#define MAX6875_CMD_REBOOT 0x88
-
-enum max6875_area_type {
- max6875_register_config=0,
- max6875_eeprom_config,
- max6875_eeprom_user,
- max6857_max
-};
-
-struct eeprom_block {
- enum max6875_area_type type;
- u8 slices;
- u32 size;
- u32 valid;
- u32 base;
- unsigned long *updated;
- u8 *data;
-};
+#define MAX6875_CMD_BLK_READ 0x84
/* Each client has this additional data */
struct max6875_data {
struct i2c_client client;
struct semaphore update_lock;
- struct eeprom_block blocks[max6857_max];
- /* the above structs point into the arrays below */
- u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
- unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+
+ u32 valid;
+ u8 data[USER_EEPROM_SIZE];
+ unsigned long last_updated[USER_EEPROM_SLICES];
};
static int max6875_attach_adapter(struct i2c_adapter *adapter);
@@ -111,337 +74,158 @@ static struct i2c_driver max6875_driver = {
.detach_client = max6875_detach_client,
};
-static int max6875_update_slice(struct i2c_client *client,
- struct eeprom_block *blk,
- int slice)
+static void max6875_update_slice(struct i2c_client *client, int slice)
{
struct max6875_data *data = i2c_get_clientdata(client);
- int i, j, addr, count;
- u8 rdbuf[SLICE_SIZE];
- int retval = 0;
+ int i, j, addr;
+ u8 *buf;
- if (slice >= blk->slices)
- return -1;
+ if (slice >= USER_EEPROM_SLICES)
+ return;
down(&data->update_lock);
- if (!(blk->valid & (1 << slice)) ||
- (jiffies - blk->updated[slice] > 300 * HZ) ||
- (jiffies < blk->updated[slice])) {
- dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
- slice, blk->base);
+ buf = &data->data[slice << SLICE_BITS];
- addr = blk->base + (slice << SLICE_BITS);
- count = blk->size - (slice << SLICE_BITS);
- if (count > SLICE_SIZE) {
- count = SLICE_SIZE;
- }
+ if (!(data->valid & (1 << slice)) ||
+ time_after(jiffies, data->last_updated[slice])) {
- /* Preset the read address */
- if (addr < 0x100) {
- /* select the register */
- if (i2c_smbus_write_byte(client, addr & 0xFF)) {
- dev_dbg(&client->dev, "max6875 register select has failed!\n");
- retval = -1;
- goto exit;
- }
- } else {
- /* select the eeprom */
- if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
- dev_dbg(&client->dev, "max6875 address set has failed!\n");
- retval = -1;
- goto exit;
- }
+ dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
+
+ data->valid &= ~(1 << slice);
+
+ addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
+
+ /* select the eeprom address */
+ if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+ dev_err(&client->dev, "address set failed\n");
+ goto exit_up;
}
- if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
- rdbuf) != SLICE_SIZE)
- {
- retval = -1;
- goto exit;
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ if (i2c_smbus_read_i2c_block_data(client,
+ MAX6875_CMD_BLK_READ,
+ buf) != SLICE_SIZE) {
+ goto exit_up;
}
-
- memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
} else {
- for (i = 0; i < count; i++) {
+ for (i = 0; i < SLICE_SIZE; i++) {
j = i2c_smbus_read_byte(client);
- if (j < 0)
- {
- retval = -1;
- goto exit;
+ if (j < 0) {
+ goto exit_up;
}
- blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+ buf[i] = j;
}
}
- blk->updated[slice] = jiffies;
- blk->valid |= (1 << slice);
+ data->last_updated[slice] = jiffies;
+ data->valid |= (1 << slice);
}
- exit:
+exit_up:
up(&data->update_lock);
- return retval;
-}
-
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
- enum max6875_area_type area_type)
-{
- struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
- struct max6875_data *data = i2c_get_clientdata(client);
- struct eeprom_block *blk;
- int slice;
-
- blk = &data->blocks[area_type];
-
- if (off > blk->size)
- return 0;
- if (off + count > blk->size)
- count = blk->size - off;
-
- /* Only refresh slices which contain requested bytes */
- for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
- max6875_update_slice(client, blk, slice);
-
- memcpy(buf, &blk->data[off], count);
-
- return count;
-}
-
-static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_read(kobj, buf, off, count, max6875_register_config);
}
-
-static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
- enum max6875_area_type area_type)
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
{
- struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
- struct eeprom_block *blk;
- int slice, addr, retval;
- ssize_t sent = 0;
-
- blk = &data->blocks[area_type];
+ int slice, max_slice;
- if (off > blk->size)
+ if (off > USER_EEPROM_SIZE)
return 0;
- if ((off + count) > blk->size)
- count = blk->size - off;
- if (down_interruptible(&data->update_lock))
- return -EAGAIN;
+ if (off + count > USER_EEPROM_SIZE)
+ count = USER_EEPROM_SIZE - off;
- /* writing to a register is done with i2c_smbus_write_byte_data() */
- if (blk->type == max6875_register_config) {
- for (sent = 0; sent < count; sent++) {
- addr = off + sent;
- if (addr == 0x44)
- continue;
+ /* refresh slices which contain requested bytes */
+ max_slice = (off + count - 1) >> SLICE_BITS;
+ for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
+ max6875_update_slice(client, slice);
- retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
- }
- } else {
- int cmd, val;
-
- /* We are writing to EEPROM */
- for (sent = 0; sent < count; sent++) {
- addr = blk->base + off + sent;
- cmd = addr >> 8;
- val = (addr & 0xff) | (buf[sent] << 8); // reversed
-
- if (addr == 0x8044)
- continue;
+ memcpy(buf, &data->data[off], count);
- retval = i2c_smbus_write_word_data(client, cmd, val);
-
- if (retval) {
- goto error_exit;
- }
-
- /* A write takes up to 11 ms */
- msleep(11);
- }
- }
-
- /* Invalidate the scratch buffer */
- for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
- blk->valid &= ~(1 << slice);
-
- error_exit:
- up(&data->update_lock);
-
- return sent;
-}
-
-static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- return max6875_write(kobj, buf, off, count, max6875_register_config);
+ return count;
}
static struct bin_attribute user_eeprom_attr = {
.attr = {
- .name = "eeprom_user",
- .mode = S_IRUGO | S_IWUSR | S_IWGRP,
- .owner = THIS_MODULE,
- },
- .size = USER_EEPROM_SIZE,
- .read = max6875_user_read,
- .write = max6875_user_write,
-};
-
-static struct bin_attribute config_eeprom_attr = {
- .attr = {
- .name = "eeprom_config",
- .mode = S_IRUGO | S_IWUSR,
+ .name = "eeprom",
+ .mode = S_IRUGO,
.owner = THIS_MODULE,
},
- .size = CONFIG_EEPROM_SIZE,
- .read = max6875_config_read,
- .write = max6875_config_write,
-};
-
-static struct bin_attribute config_register_attr = {
- .attr = {
- .name = "reg_config",
- .mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
- },
- .size = CONFIG_EEPROM_SIZE,
- .read = max6875_cfgreg_read,
- .write = max6875_cfgreg_write,
+ .size = USER_EEPROM_SIZE,
+ .read = max6875_read,
};
static int max6875_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, max6875_detect);
+ return i2c_probe(adapter, &addr_data, max6875_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
{
- struct i2c_client *new_client;
+ struct i2c_client *real_client;
+ struct i2c_client *fake_client;
struct max6875_data *data;
int err = 0;
- /* Prevent 24RF08 corruption (in case of user error) */
- if (kind < 0)
- i2c_smbus_xfer(adapter, address, 0, 0, 0,
- I2C_SMBUS_QUICK, NULL);
-
- /* There are three ways we can read the EEPROM data:
- (1) I2C block reads (faster, but unsupported by most adapters)
- (2) Consecutive byte reads (100% overhead)
- (3) Regular byte data reads (200% overhead)
- The third method is not implemented by this driver because all
- known adapters support at least the second. */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
- goto exit;
-
- /* 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 eeprom_{read,write}_value. */
- if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BYTE))
+ return 0;
+
+ /* Only check even addresses */
+ if (address & 1)
+ return 0;
+
+ if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ /* A fake client is created on the odd address */
+ if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
err = -ENOMEM;
- goto exit;
+ goto exit_kfree1;
}
- memset(data, 0, sizeof(struct max6875_data));
-
- new_client = &data->client;
- i2c_set_clientdata(new_client, data);
- new_client->addr = address;
- new_client->adapter = adapter;
- new_client->driver = &max6875_driver;
- new_client->flags = 0;
-
- /* Setup the user section */
- data->blocks[max6875_eeprom_user].type = max6875_eeprom_user;
- data->blocks[max6875_eeprom_user].slices = USER_EEPROM_SLICES;
- data->blocks[max6875_eeprom_user].size = USER_EEPROM_SIZE;
- data->blocks[max6875_eeprom_user].base = USER_EEPROM_BASE;
- data->blocks[max6875_eeprom_user].data = data->data;
- data->blocks[max6875_eeprom_user].updated = data->last_updated;
-
- /* Setup the config section */
- data->blocks[max6875_eeprom_config].type = max6875_eeprom_config;
- data->blocks[max6875_eeprom_config].slices = CONFIG_EEPROM_SLICES;
- data->blocks[max6875_eeprom_config].size = CONFIG_EEPROM_SIZE;
- data->blocks[max6875_eeprom_config].base = CONFIG_EEPROM_BASE;
- data->blocks[max6875_eeprom_config].data = &data->data[USER_EEPROM_SIZE];
- data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
-
- /* Setup the register section */
- data->blocks[max6875_register_config].type = max6875_register_config;
- data->blocks[max6875_register_config].slices = CONFIG_EEPROM_SLICES;
- data->blocks[max6875_register_config].size = CONFIG_EEPROM_SIZE;
- data->blocks[max6875_register_config].base = 0;
- data->blocks[max6875_register_config].data = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
- data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
-
- /* Init the data */
- memset(data->data, 0xff, sizeof(data->data));
-
- /* Fill in the remaining client fields */
- strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+
+ /* Init real i2c_client */
+ real_client = &data->client;
+ i2c_set_clientdata(real_client, data);
+ real_client->addr = address;
+ real_client->adapter = adapter;
+ real_client->driver = &max6875_driver;
+ real_client->flags = 0;
+ strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
init_MUTEX(&data->update_lock);
- /* Verify that the chip is really what we think it is */
- if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
- (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
- goto exit_kfree;
-
- /* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
- if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
- (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
- (data->blocks[max6875_register_config].data[0x41] != 0) ||
- (data->blocks[max6875_register_config].data[0x42] != 0) ||
- (data->blocks[max6875_eeprom_config].data[0x40] !=
- data->blocks[max6875_register_config].data[0x40]))
- goto exit_kfree;
-
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(new_client)))
- goto exit_kfree;
-
- /* create the sysfs eeprom files with the correct permissions */
- if (allow_write == 0) {
- user_eeprom_attr.attr.mode &= ~S_IWUGO;
- user_eeprom_attr.write = NULL;
- config_eeprom_attr.attr.mode &= ~S_IWUGO;
- config_eeprom_attr.write = NULL;
- config_register_attr.attr.mode &= ~S_IWUGO;
- config_register_attr.write = NULL;
- }
- sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
- sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
- sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+ /* Init fake client data */
+ /* set the client data to the i2c_client so that it will get freed */
+ i2c_set_clientdata(fake_client, fake_client);
+ fake_client->addr = address | 1;
+ fake_client->adapter = adapter;
+ fake_client->driver = &max6875_driver;
+ fake_client->flags = 0;
+ strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
+
+ /* Prevent 24RF08 corruption (in case of user error) */
+ i2c_smbus_write_quick(real_client, 0);
+
+ if ((err = i2c_attach_client(real_client)) != 0)
+ goto exit_kfree2;
+
+ if ((err = i2c_attach_client(fake_client)) != 0)
+ goto exit_detach;
+
+ sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
return 0;
-exit_kfree:
+exit_detach:
+ i2c_detach_client(real_client);
+exit_kfree2:
+ kfree(fake_client);
+exit_kfree1:
kfree(data);
-exit:
return err;
}
@@ -450,13 +234,9 @@ static int max6875_detach_client(struct i2c_client *client)
int err;
err = i2c_detach_client(client);
- if (err) {
- dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ if (err)
return err;
- }
-
kfree(i2c_get_clientdata(client));
-
return 0;
}
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 9f3ad45daae2..59a930346229 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -13,14 +13,12 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
/* Insmod parameters */
-SENSORS_INSMOD_1(pca9539);
+I2C_CLIENT_INSMOD_1(pca9539);
enum pca9539_cmd
{
@@ -109,10 +107,10 @@ static struct attribute_group pca9539_defattr_group = {
static int pca9539_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pca9539_detect);
+ return i2c_probe(adapter, &addr_data, pca9539_detect);
}
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
@@ -124,11 +122,10 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pca9539_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -164,10 +161,8 @@ static int pca9539_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index cfcf64654080..c323c2de236c 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -39,16 +39,14 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_2(pcf8574, pcf8574a);
+I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
/* Initial values */
#define PCF8574_INIT 255 /* All outputs on (input mode) */
@@ -113,11 +111,11 @@ static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pcf8574_detect);
+ return i2c_probe(adapter, &addr_data, pcf8574_detect);
}
-/* This function is called by i2c_detect */
-int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct pcf8574_data *data;
@@ -129,11 +127,10 @@ int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pcf8574_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -186,11 +183,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index db812ade8564..ce420a67560b 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -24,15 +24,13 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_1(pcf8591);
+I2C_CLIENT_INSMOD_1(pcf8591);
static int input_mode;
module_param(input_mode, int, 0);
@@ -164,11 +162,11 @@ static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
*/
static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
{
- return i2c_detect(adapter, &addr_data, pcf8591_detect);
+ return i2c_probe(adapter, &addr_data, pcf8591_detect);
}
-/* This function is called by i2c_detect */
-int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct pcf8591_data *data;
@@ -180,11 +178,10 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
- if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- memset(data, 0, sizeof(struct pcf8591_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
@@ -241,11 +238,8 @@ static int pcf8591_detach_client(struct i2c_client *client)
{
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
kfree(i2c_get_clientdata(client));
return 0;
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 588fc2261a91..916cdc1af23c 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -67,7 +67,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
- .force = ignore,
};
static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
@@ -149,17 +148,16 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
{addr, I2C_M_RD, 2, data}
};
- d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
+ d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
if (!d) {
ret = -ENOMEM;
goto done;
}
- memset(d, 0, sizeof(struct rtc8564_data));
new_client = &d->client;
strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
i2c_set_clientdata(new_client, d);
- new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
+ new_client->flags = I2C_CLIENT_ALLOW_USE;
new_client->addr = addr;
new_client->adapter = adap;
new_client->driver = &rtc8564_driver;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280e9638c0f8..280dd7a45db6 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -500,11 +500,10 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
return 0;
}
- tps = kmalloc(sizeof *tps, GFP_KERNEL);
+ tps = kzalloc(sizeof *tps, GFP_KERNEL);
if (!tps)
return 0;
- memset(tps, 0, sizeof *tps);
init_MUTEX(&tps->lock);
INIT_WORK(&tps->work, tps65010_work, tps);
tps->irq = -1;
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
new file mode 100644
index 000000000000..7da366cdc18c
--- /dev/null
+++ b/drivers/i2c/chips/x1205.c
@@ -0,0 +1,698 @@
+/*
+ * x1205.c - An i2c driver for the Xicor X1205 RTC
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
+ *
+ * please send all reports to:
+ * kas11 at tampabay dot rr dot com
+ * a dot zummo at towertech dot it
+ *
+ * based on the other drivers in this same directory.
+ *
+ * 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/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/list.h>
+
+#include <linux/x1205.h>
+
+#define DRV_VERSION "0.9.9"
+
+/* Addresses to scan: none. This chip is located at
+ * 0x6f and uses a two bytes register addressing.
+ * Two bytes need to be written to read a single register,
+ * while most other chips just require one and take the second
+ * one as the data to be written. To prevent corrupting
+ * unknown chips, the user must explicitely set the probe parameter.
+ */
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+I2C_CLIENT_MODULE_PARM(hctosys,
+ "Set the system time from the hardware clock upon initialization");
+
+/* offsets into CCR area */
+
+#define CCR_SEC 0
+#define CCR_MIN 1
+#define CCR_HOUR 2
+#define CCR_MDAY 3
+#define CCR_MONTH 4
+#define CCR_YEAR 5
+#define CCR_WDAY 6
+#define CCR_Y2K 7
+
+#define X1205_REG_SR 0x3F /* status register */
+#define X1205_REG_Y2K 0x37
+#define X1205_REG_DW 0x36
+#define X1205_REG_YR 0x35
+#define X1205_REG_MO 0x34
+#define X1205_REG_DT 0x33
+#define X1205_REG_HR 0x32
+#define X1205_REG_MN 0x31
+#define X1205_REG_SC 0x30
+#define X1205_REG_DTR 0x13
+#define X1205_REG_ATR 0x12
+#define X1205_REG_INT 0x11
+#define X1205_REG_0 0x10
+#define X1205_REG_Y2K1 0x0F
+#define X1205_REG_DWA1 0x0E
+#define X1205_REG_YRA1 0x0D
+#define X1205_REG_MOA1 0x0C
+#define X1205_REG_DTA1 0x0B
+#define X1205_REG_HRA1 0x0A
+#define X1205_REG_MNA1 0x09
+#define X1205_REG_SCA1 0x08
+#define X1205_REG_Y2K0 0x07
+#define X1205_REG_DWA0 0x06
+#define X1205_REG_YRA0 0x05
+#define X1205_REG_MOA0 0x04
+#define X1205_REG_DTA0 0x03
+#define X1205_REG_HRA0 0x02
+#define X1205_REG_MNA0 0x01
+#define X1205_REG_SCA0 0x00
+
+#define X1205_CCR_BASE 0x30 /* Base address of CCR */
+#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
+
+#define X1205_SR_RTCF 0x01 /* Clock failure */
+#define X1205_SR_WEL 0x02 /* Write Enable Latch */
+#define X1205_SR_RWEL 0x04 /* Register Write Enable */
+
+#define X1205_DTR_DTR0 0x01
+#define X1205_DTR_DTR1 0x02
+#define X1205_DTR_DTR2 0x04
+
+#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
+
+/* Prototypes */
+static int x1205_attach(struct i2c_adapter *adapter);
+static int x1205_detach(struct i2c_client *client);
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+
+static struct i2c_driver x1205_driver = {
+ .owner = THIS_MODULE,
+ .name = "x1205",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = &x1205_attach,
+ .detach_client = &x1205_detach,
+};
+
+struct x1205_data {
+ struct i2c_client client;
+ struct list_head list;
+ unsigned int epoch;
+};
+
+static const unsigned char days_in_mo[] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static LIST_HEAD(x1205_clients);
+
+/* Workaround until the I2C subsytem will allow to send
+ * commands to a specific client. This function will send the command
+ * to the first client.
+ */
+int x1205_do_command(unsigned int cmd, void *arg)
+{
+ struct list_head *walk;
+ struct list_head *tmp;
+ struct x1205_data *data;
+
+ list_for_each_safe(walk, tmp, &x1205_clients) {
+ data = list_entry(walk, struct x1205_data, list);
+ return x1205_command(&data->client, cmd, arg);
+ }
+
+ return -ENODEV;
+}
+
+#define is_leap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+/* make sure the rtc_time values are in bounds */
+static int x1205_validate_tm(struct rtc_time *tm)
+{
+ int year = tm->tm_year + 1900;
+
+ if ((tm->tm_year < 70) || (tm->tm_year > 255))
+ return -EINVAL;
+
+ if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
+ return -EINVAL;
+
+ if (tm->tm_mday > days_in_mo[tm->tm_mon]
+ + ((tm->tm_mon == 1) && is_leap(year)))
+ return -EINVAL;
+
+ if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * In the routines that deal directly with the x1205 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+ u8 reg_base)
+{
+ unsigned char dt_addr[2] = { 0, reg_base };
+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+ unsigned char buf[8], sr;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &sr }, /* read status */
+ { client->addr, 0, 2, dt_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 8, buf }, /* read date */
+ };
+
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ /* read status register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ /* check for battery failure */
+ if (sr & X1205_SR_RTCF) {
+ dev_warn(&client->dev,
+ "Clock had a power failure, you must set the date.\n");
+ return -EINVAL;
+ }
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
+ tm->tm_min = BCD2BIN(buf[CCR_MIN]);
+ tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
+ data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
+ tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
+ tm->tm_wday = buf[CCR_WDAY];
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+ int datetoo, u8 reg_base)
+{
+ int i, err, xfer;
+
+ unsigned char buf[8];
+
+ static const unsigned char wel[3] = { 0, X1205_REG_SR,
+ X1205_SR_WEL };
+
+ static const unsigned char rwel[3] = { 0, X1205_REG_SR,
+ X1205_SR_WEL | X1205_SR_RWEL };
+
+ static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
+
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ /* check if all values in the tm struct are correct */
+ if ((err = x1205_validate_tm(tm)) < 0)
+ return err;
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+ buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+
+ /* set hour and 24hr bit */
+ buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+
+ /* should we also set the date? */
+ if (datetoo) {
+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+
+ /* month, 0 - 11 */
+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+
+ /* year, since 1900 */
+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
+ buf[CCR_WDAY] = tm->tm_wday & 0x07;
+ buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
+ }
+
+ /* this sequence is required to unlock the chip */
+ xfer = i2c_master_send(client, wel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ xfer = i2c_master_send(client, rwel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ /* write register's data */
+ for (i = 0; i < (datetoo ? 8 : 3); i++) {
+ unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
+
+ xfer = i2c_master_send(client, rdata, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev,
+ "%s: xfer=%d addr=%02x, data=%02x\n",
+ __FUNCTION__,
+ xfer, rdata[1], rdata[2]);
+ return -EIO;
+ }
+ };
+
+ /* disable further writes */
+ xfer = i2c_master_send(client, diswe, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int x1205_get_dtrim(struct i2c_client *client, int *trim)
+{
+ unsigned char dtr;
+ static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, dtr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
+ };
+
+ /* read dtr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
+
+ *trim = 0;
+
+ if (dtr & X1205_DTR_DTR0)
+ *trim += 20;
+
+ if (dtr & X1205_DTR_DTR1)
+ *trim += 10;
+
+ if (dtr & X1205_DTR_DTR2)
+ *trim = -*trim;
+
+ return 0;
+}
+
+static int x1205_get_atrim(struct i2c_client *client, int *trim)
+{
+ s8 atr;
+ static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, atr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, &atr }, /* read atr */
+ };
+
+ /* read atr register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
+
+ /* atr is a two's complement value on 6 bits,
+ * perform sign extension. The formula is
+ * Catr = (atr * 0.25pF) + 11.00pF.
+ */
+ if (atr & 0x20)
+ atr |= 0xC0;
+
+ dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
+
+ *trim = (atr * 250) + 11000;
+
+ dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
+
+ return 0;
+}
+
+static int x1205_hctosys(struct i2c_client *client)
+{
+ int err;
+
+ struct rtc_time tm;
+ struct timespec tv;
+
+ err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
+
+ if (err) {
+ dev_err(&client->dev,
+ "Unable to set the system clock\n");
+ return err;
+ }
+
+ /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+ * whether it stores the most close value or the value with partial
+ * seconds truncated. However, it is important that we use it to store
+ * the truncated value. This is because otherwise it is necessary,
+ * in an rtc sync function, to read both xtime.tv_sec and
+ * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
+ * of >32bits is not possible. So storing the most close value would
+ * slow down the sync API. So here we have the truncated value and
+ * the best guess is to add 0.5s.
+ */
+
+ tv.tv_nsec = NSEC_PER_SEC >> 1;
+
+ /* WARNING: this is not the C library 'mktime' call, it is a built in
+ * inline function from include/linux/time.h. It expects (requires)
+ * the month to be in the range 1-12
+ */
+
+ tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+
+ do_settimeofday(&tv);
+
+ dev_info(&client->dev,
+ "setting the system clock to %d-%d-%d %d:%d:%d\n",
+ tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour, tm.tm_min,
+ tm.tm_sec);
+
+ return 0;
+}
+
+struct x1205_limit
+{
+ unsigned char reg;
+ unsigned char mask;
+ unsigned char min;
+ unsigned char max;
+};
+
+static int x1205_validate_client(struct i2c_client *client)
+{
+ int i, xfer;
+
+ /* Probe array. We will read the register at the specified
+ * address and check if the given bits are zero.
+ */
+ static const unsigned char probe_zero_pattern[] = {
+ /* register, mask */
+ X1205_REG_SR, 0x18,
+ X1205_REG_DTR, 0xF8,
+ X1205_REG_ATR, 0xC0,
+ X1205_REG_INT, 0x18,
+ X1205_REG_0, 0xFF,
+ };
+
+ static const struct x1205_limit probe_limits_pattern[] = {
+ /* register, mask, min, max */
+ { X1205_REG_Y2K, 0xFF, 19, 20 },
+ { X1205_REG_DW, 0xFF, 0, 6 },
+ { X1205_REG_YR, 0xFF, 0, 99 },
+ { X1205_REG_MO, 0xFF, 0, 12 },
+ { X1205_REG_DT, 0xFF, 0, 31 },
+ { X1205_REG_HR, 0x7F, 0, 23 },
+ { X1205_REG_MN, 0xFF, 0, 59 },
+ { X1205_REG_SC, 0xFF, 0, 59 },
+ { X1205_REG_Y2K1, 0xFF, 19, 20 },
+ { X1205_REG_Y2K0, 0xFF, 19, 20 },
+ };
+
+ /* check that registers have bits a 0 where expected */
+ for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
+ unsigned char buf;
+
+ unsigned char addr[2] = { 0, probe_zero_pattern[i] };
+
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 2, addr },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+ if (xfer != 2) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register %x\n",
+ __FUNCTION__, addr[1]);
+
+ return -EIO;
+ }
+
+ if ((buf & probe_zero_pattern[i+1]) != 0) {
+ dev_err(&client->adapter->dev,
+ "%s: register=%02x, zero pattern=%d, value=%x\n",
+ __FUNCTION__, addr[1], i, buf);
+
+ return -ENODEV;
+ }
+ }
+
+ /* check limits (only registers with bcd values) */
+ for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
+ unsigned char reg, value;
+
+ unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
+
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 2, addr },
+ { client->addr, I2C_M_RD, 1, &reg },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+
+ if (xfer != 2) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register %x\n",
+ __FUNCTION__, addr[1]);
+
+ return -EIO;
+ }
+
+ value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+
+ if (value > probe_limits_pattern[i].max ||
+ value < probe_limits_pattern[i].min) {
+ dev_dbg(&client->adapter->dev,
+ "%s: register=%x, lim pattern=%d, value=%d\n",
+ __FUNCTION__, addr[1], i, value);
+
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int x1205_attach(struct i2c_adapter *adapter)
+{
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ return i2c_probe(adapter, &addr_data, x1205_probe);
+}
+
+int x1205_direct_attach(int adapter_id,
+ struct i2c_client_address_data *address_data)
+{
+ int err;
+ struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
+
+ if (adapter) {
+ err = i2c_probe(adapter,
+ address_data, x1205_probe);
+
+ i2c_put_adapter(adapter);
+
+ return err;
+ }
+
+ return -ENODEV;
+}
+
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct x1205_data *data;
+
+ int err = 0;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* Initialize our structures */
+ data->epoch = 2000;
+
+ client = &data->client;
+ client->addr = address;
+ client->driver = &x1205_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, "x1205", I2C_NAME_SIZE);
+
+ i2c_set_clientdata(client, data);
+
+ /* Verify the chip is really an X1205 */
+ if (kind < 0) {
+ if (x1205_validate_client(client) < 0) {
+ err = -ENODEV;
+ goto exit_kfree;
+ }
+ }
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ list_add(&data->list, &x1205_clients);
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ /* If requested, set the system time */
+ if (hctosys)
+ x1205_hctosys(client);
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+
+exit:
+ return err;
+}
+
+static int x1205_detach(struct i2c_client *client)
+{
+ int err;
+ struct x1205_data *data = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ list_del(&data->list);
+
+ kfree(data);
+
+ return 0;
+}
+
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+ void *param)
+{
+ if (param == NULL)
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+
+ switch (cmd) {
+ case X1205_CMD_GETDATETIME:
+ return x1205_get_datetime(client, param, X1205_CCR_BASE);
+
+ case X1205_CMD_SETTIME:
+ return x1205_set_datetime(client, param, 0,
+ X1205_CCR_BASE);
+
+ case X1205_CMD_SETDATETIME:
+ return x1205_set_datetime(client, param, 1,
+ X1205_CCR_BASE);
+
+ case X1205_CMD_GETALARM:
+ return x1205_get_datetime(client, param, X1205_ALM0_BASE);
+
+ case X1205_CMD_SETALARM:
+ return x1205_set_datetime(client, param, 1,
+ X1205_ALM0_BASE);
+
+ case X1205_CMD_GETDTRIM:
+ return x1205_get_dtrim(client, param);
+
+ case X1205_CMD_GETATRIM:
+ return x1205_get_atrim(client, param);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __init x1205_init(void)
+{
+ return i2c_add_driver(&x1205_driver);
+}
+
+static void __exit x1205_exit(void)
+{
+ i2c_del_driver(&x1205_driver);
+}
+
+MODULE_AUTHOR(
+ "Karen Spearel <kas11@tampabay.rr.com>, "
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Xicor X1205 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+EXPORT_SYMBOL_GPL(x1205_do_command);
+EXPORT_SYMBOL_GPL(x1205_direct_attach);
+
+module_init(x1205_init);
+module_exit(x1205_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 4a9ead277596..82ea1b7ec914 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -19,7 +19,8 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
- SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
+ SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
+ Jean Delvare <khali@linux-fr.org> */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -29,6 +30,7 @@
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/seq_file.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
@@ -48,7 +50,7 @@ static int i2c_bus_suspend(struct device * dev, pm_message_t state)
int rc = 0;
if (dev->driver && dev->driver->suspend)
- rc = dev->driver->suspend(dev,state,0);
+ rc = dev->driver->suspend(dev, state);
return rc;
}
@@ -57,11 +59,11 @@ static int i2c_bus_resume(struct device * dev)
int rc = 0;
if (dev->driver && dev->driver->resume)
- rc = dev->driver->resume(dev,0);
+ rc = dev->driver->resume(dev);
return rc;
}
-static struct bus_type i2c_bus_type = {
+struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.suspend = i2c_bus_suspend,
@@ -78,13 +80,14 @@ static int i2c_device_remove(struct device *dev)
return 0;
}
-static void i2c_adapter_dev_release(struct device *dev)
+void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
complete(&adap->dev_released);
}
-static struct device_driver i2c_adapter_driver = {
+struct device_driver i2c_adapter_driver = {
+ .owner = THIS_MODULE,
.name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
@@ -97,7 +100,8 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
complete(&adap->class_dev_released);
}
-static struct class i2c_adapter_class = {
+struct class i2c_adapter_class = {
+ .owner = THIS_MODULE,
.name = "i2c-adapter",
.release = &i2c_adapter_class_dev_release,
};
@@ -188,6 +192,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
class_device_register(&adap->class_dev);
+ dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
+
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
@@ -196,8 +202,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
driver->attach_adapter(adap);
}
- dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-
out_unlock:
up(&core_lists);
return res;
@@ -220,8 +224,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
break;
}
if (adap_from_list != adap) {
- pr_debug("I2C: Attempting to delete an unregistered "
- "adapter\n");
+ pr_debug("i2c-core: attempting to delete unregistered "
+ "adapter [%s]\n", adap->name);
res = -EINVAL;
goto out_unlock;
}
@@ -230,9 +234,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
driver = list_entry(item, struct i2c_driver, list);
if (driver->detach_adapter)
if ((res = driver->detach_adapter(adap))) {
- dev_warn(&adap->dev, "can't detach adapter "
- "while detaching driver %s: driver "
- "not detached!\n", driver->name);
+ dev_err(&adap->dev, "detach_adapter failed "
+ "for driver [%s]\n", driver->name);
goto out_unlock;
}
}
@@ -247,9 +250,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
* must be deleted, as this would cause invalid states.
*/
if ((res=client->driver->detach_client(client))) {
- dev_err(&adap->dev, "adapter not "
- "unregistered, because client at "
- "address %02x can't be detached. ",
+ dev_err(&adap->dev, "detach_client failed for client "
+ "[%s] at address 0x%02x\n", client->name,
client->addr);
goto out_unlock;
}
@@ -270,7 +272,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* free dynamically allocated bus id */
idr_remove(&i2c_adapter_idr, adap->nr);
- dev_dbg(&adap->dev, "adapter unregistered\n");
+ dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
out_unlock:
up(&core_lists);
@@ -293,6 +295,7 @@ int i2c_add_driver(struct i2c_driver *driver)
down(&core_lists);
/* add the driver to the list of i2c drivers in the driver core */
+ driver->driver.owner = driver->owner;
driver->driver.name = driver->name;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_device_probe;
@@ -303,7 +306,7 @@ int i2c_add_driver(struct i2c_driver *driver)
goto out_unlock;
list_add_tail(&driver->list,&drivers);
- pr_debug("i2c-core: driver %s registered.\n", driver->name);
+ pr_debug("i2c-core: driver [%s] registered\n", driver->name);
/* now look for instances of driver on our adapters */
if (driver->flags & I2C_DF_NOTIFY) {
@@ -331,21 +334,17 @@ int i2c_del_driver(struct i2c_driver *driver)
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
- */
- pr_debug("i2c-core: unregister_driver - looking for clients.\n");
- /* removing clients does not depend on the notify flag, else
+ *
+ * Removing clients does not depend on the notify flag, else
* invalid operation might (will!) result, when using stale client
* pointers.
*/
list_for_each(item1,&adapters) {
adap = list_entry(item1, struct i2c_adapter, list);
- dev_dbg(&adap->dev, "examining adapter\n");
if (driver->detach_adapter) {
if ((res = driver->detach_adapter(adap))) {
- dev_warn(&adap->dev, "while unregistering "
- "dummy driver %s, adapter could "
- "not be detached properly; driver "
- "not unloaded!",driver->name);
+ dev_err(&adap->dev, "detach_adapter failed "
+ "for driver [%s]\n", driver->name);
goto out_unlock;
}
} else {
@@ -353,16 +352,13 @@ int i2c_del_driver(struct i2c_driver *driver)
client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver)
continue;
- pr_debug("i2c-core.o: detaching client %s:\n", client->name);
+ dev_dbg(&adap->dev, "detaching client [%s] "
+ "at 0x%02x\n", client->name,
+ client->addr);
if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "while "
- "unregistering driver "
- "`%s', the client at "
- "address %02x of "
- "adapter could not "
- "be detached; driver "
- "not unloaded!",
- driver->name,
+ dev_err(&adap->dev, "detach_client "
+ "failed for client [%s] at "
+ "0x%02x\n", client->name,
client->addr);
goto out_unlock;
}
@@ -372,7 +368,7 @@ int i2c_del_driver(struct i2c_driver *driver)
driver_unregister(&driver->driver);
list_del(&driver->list);
- pr_debug("i2c-core: driver unregistered: %s\n", driver->name);
+ pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
out_unlock:
up(&core_lists);
@@ -417,15 +413,12 @@ int i2c_attach_client(struct i2c_client *client)
if (adapter->client_register) {
if (adapter->client_register(client)) {
- dev_warn(&adapter->dev, "warning: client_register "
- "seems to have failed for client %02x\n",
- client->addr);
+ dev_dbg(&adapter->dev, "client_register "
+ "failed for client [%s] at 0x%02x\n",
+ client->name, client->addr);
}
}
- dev_dbg(&adapter->dev, "client [%s] registered to adapter\n",
- client->name);
-
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -436,7 +429,8 @@ int i2c_attach_client(struct i2c_client *client)
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
"%d-%04x", i2c_adapter_id(adapter), client->addr);
- pr_debug("registering %s\n", client->dev.bus_id);
+ dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+ client->name, client->dev.bus_id);
device_register(&client->dev);
device_create_file(&client->dev, &dev_attr_client_name);
@@ -449,8 +443,12 @@ int i2c_detach_client(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
int res = 0;
- if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
+ if ((client->flags & I2C_CLIENT_ALLOW_USE)
+ && (client->usage_count > 0)) {
+ dev_warn(&client->dev, "Client [%s] still busy, "
+ "can't detach\n", client->name);
return -EBUSY;
+ }
if (adapter->client_unregister) {
res = adapter->client_unregister(client);
@@ -669,98 +667,135 @@ int i2c_control(struct i2c_client *client,
* Will not work for 10-bit addresses!
* ----------------------------------------------------
*/
+static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+ int (*found_proc) (struct i2c_adapter *, int, int))
+{
+ int err;
+
+ /* Make sure the address is valid */
+ if (addr < 0x03 || addr > 0x77) {
+ dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
+ addr);
+ return -EINVAL;
+ }
+
+ /* Skip if already in use */
+ if (i2c_check_addr(adapter, addr))
+ return 0;
+
+ /* Make sure there is something at this address, unless forced */
+ if (kind < 0) {
+ if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+ I2C_SMBUS_QUICK, NULL) < 0)
+ return 0;
+
+ /* prevent 24RF08 corruption */
+ if ((addr & ~0x0f) == 0x50)
+ i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+ I2C_SMBUS_QUICK, NULL);
+ }
+
+ /* Finally call the custom detection function */
+ err = found_proc(adapter, addr, kind);
+
+ /* -ENODEV can be returned if there is a chip at the given address
+ but it isn't supported by this chip driver. We catch it here as
+ this isn't an error. */
+ return (err == -ENODEV) ? 0 : err;
+}
+
int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
int (*found_proc) (struct i2c_adapter *, int, int))
{
- int addr,i,found,err;
+ int i, err;
int adap_id = i2c_adapter_id(adapter);
- /* Forget it if we can't probe using SMBUS_QUICK */
- if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
- return -1;
-
- for (addr = 0x00; addr <= 0x7f; addr++) {
-
- /* Skip if already in use */
- if (i2c_check_addr(adapter,addr))
- continue;
-
- /* If it is in one of the force entries, we don't do any detection
- at all */
- found = 0;
-
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
- if (((adap_id == address_data->force[i]) ||
- (address_data->force[i] == ANY_I2C_BUS)) &&
- (addr == address_data->force[i+1])) {
- dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n",
- adap_id, addr);
- if ((err = found_proc(adapter,addr,0)))
- return err;
- found = 1;
+ /* Force entries are done first, and are not affected by ignore
+ entries */
+ if (address_data->forces) {
+ unsigned short **forces = address_data->forces;
+ int kind;
+
+ for (kind = 0; forces[kind]; kind++) {
+ for (i = 0; forces[kind][i] != I2C_CLIENT_END;
+ i += 2) {
+ if (forces[kind][i] == adap_id
+ || forces[kind][i] == ANY_I2C_BUS) {
+ dev_dbg(&adapter->dev, "found force "
+ "parameter for adapter %d, "
+ "addr 0x%02x, kind %d\n",
+ adap_id, forces[kind][i + 1],
+ kind);
+ err = i2c_probe_address(adapter,
+ forces[kind][i + 1],
+ kind, found_proc);
+ if (err)
+ return err;
+ }
}
}
- if (found)
- continue;
+ }
- /* If this address is in one of the ignores, we can forget about
- it right now */
- for (i = 0;
- !found && (address_data->ignore[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == ANY_I2C_BUS))) &&
- (addr == address_data->ignore[i+1])) {
- dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
- "addr %04x\n", adap_id ,addr);
- found = 1;
- }
- }
- if (found)
- continue;
+ /* Stop here if we can't use SMBUS_QUICK */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+ if (address_data->probe[0] == I2C_CLIENT_END
+ && address_data->normal_i2c[0] == I2C_CLIENT_END)
+ return 0;
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- for (i = 0;
- !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
- i += 1) {
- if (addr == address_data->normal_i2c[i]) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
- "addr %02x\n", adap_id, addr);
- }
+ dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+ "can't probe for chips\n");
+ return -1;
+ }
+
+ /* Probe entries are done second, and are not affected by ignore
+ entries either */
+ for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
+ if (address_data->probe[i] == adap_id
+ || address_data->probe[i] == ANY_I2C_BUS) {
+ dev_dbg(&adapter->dev, "found probe parameter for "
+ "adapter %d, addr 0x%02x\n", adap_id,
+ address_data->probe[i + 1]);
+ err = i2c_probe_address(adapter,
+ address_data->probe[i + 1],
+ -1, found_proc);
+ if (err)
+ return err;
}
+ }
- for (i = 0;
- !found && (address_data->probe[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->probe[i]) ||
- ((address_data->probe[i] == ANY_I2C_BUS))) &&
- (addr == address_data->probe[i+1])) {
- found = 1;
- dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
- "addr %04x\n", adap_id,addr);
+ /* Normal entries are done last, unless shadowed by an ignore entry */
+ for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
+ int j, ignore;
+
+ ignore = 0;
+ for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
+ j += 2) {
+ if ((address_data->ignore[j] == adap_id ||
+ address_data->ignore[j] == ANY_I2C_BUS)
+ && address_data->ignore[j + 1]
+ == address_data->normal_i2c[i]) {
+ dev_dbg(&adapter->dev, "found ignore "
+ "parameter for adapter %d, "
+ "addr 0x%02x\n", adap_id,
+ address_data->ignore[j + 1]);
}
+ ignore = 1;
+ break;
}
- if (!found)
+ if (ignore)
continue;
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- if ((err = found_proc(adapter,addr,-1)))
- return err;
+ dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
+ "addr 0x%02x\n", adap_id,
+ address_data->normal_i2c[i]);
+ err = i2c_probe_address(adapter, address_data->normal_i2c[i],
+ -1, found_proc);
+ if (err)
+ return err;
}
- return 0;
-}
-/*
- * return id number for a specific adapter
- */
-int i2c_adapter_id(struct i2c_adapter *adap)
-{
- return adap->nr;
+ return 0;
}
struct i2c_adapter* i2c_get_adapter(int id)
@@ -797,101 +832,44 @@ crc8(u16 data)
return (u8)(data >> 8);
}
-/* CRC over count bytes in the first array plus the bytes in the rest
- array if it is non-null. rest[0] is the (length of rest) - 1
- and is included. */
-static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
{
int i;
for(i = 0; i < count; i++)
- crc = crc8((crc ^ first[i]) << 8);
- if(rest != NULL)
- for(i = 0; i <= rest[0]; i++)
- crc = crc8((crc ^ rest[i]) << 8);
+ crc = crc8((crc ^ p[i]) << 8);
return crc;
}
-static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+/* Assume a 7-bit address, which is reasonable for SMBus */
+static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
{
- return i2c_smbus_partial_pec(0, count, first, rest);
+ /* The address will be sent first */
+ u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+ pec = i2c_smbus_pec(pec, &addr, 1);
+
+ /* The data buffer follows */
+ return i2c_smbus_pec(pec, msg->buf, msg->len);
}
-/* Returns new "size" (transaction type)
- Note that we convert byte to byte_data and byte_data to word_data
- rather than invent new xxx_PEC transactions. */
-static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
- union i2c_smbus_data *data)
+/* Used for write only transactions */
+static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
{
- u8 buf[3];
-
- buf[0] = addr << 1;
- buf[1] = command;
- switch(size) {
- case I2C_SMBUS_BYTE:
- data->byte = i2c_smbus_pec(2, buf, NULL);
- size = I2C_SMBUS_BYTE_DATA;
- break;
- case I2C_SMBUS_BYTE_DATA:
- buf[2] = data->byte;
- data->word = buf[2] ||
- (i2c_smbus_pec(3, buf, NULL) << 8);
- size = I2C_SMBUS_WORD_DATA;
- break;
- case I2C_SMBUS_WORD_DATA:
- /* unsupported */
- break;
- case I2C_SMBUS_BLOCK_DATA:
- data->block[data->block[0] + 1] =
- i2c_smbus_pec(2, buf, data->block);
- size = I2C_SMBUS_BLOCK_DATA_PEC;
- break;
- }
- return size;
+ msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
+ msg->len++;
}
-static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
- union i2c_smbus_data *data)
+/* Return <0 on CRC error
+ If there was a write before this read (most cases) we need to take the
+ partial CRC from the write part into account.
+ Note that this function does modify the message (we need to decrease the
+ message length to hide the CRC byte from the caller). */
+static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
{
- u8 buf[3], rpec, cpec;
+ u8 rpec = msg->buf[--msg->len];
+ cpec = i2c_smbus_msg_pec(cpec, msg);
- buf[1] = command;
- switch(size) {
- case I2C_SMBUS_BYTE_DATA:
- buf[0] = (addr << 1) | 1;
- cpec = i2c_smbus_pec(2, buf, NULL);
- rpec = data->byte;
- break;
- case I2C_SMBUS_WORD_DATA:
- buf[0] = (addr << 1) | 1;
- buf[2] = data->word & 0xff;
- cpec = i2c_smbus_pec(3, buf, NULL);
- rpec = data->word >> 8;
- break;
- case I2C_SMBUS_WORD_DATA_PEC:
- /* unsupported */
- cpec = rpec = 0;
- break;
- case I2C_SMBUS_PROC_CALL_PEC:
- /* unsupported */
- cpec = rpec = 0;
- break;
- case I2C_SMBUS_BLOCK_DATA_PEC:
- buf[0] = (addr << 1);
- buf[2] = (addr << 1) | 1;
- cpec = i2c_smbus_pec(3, buf, data->block);
- rpec = data->block[data->block[0] + 1];
- break;
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
- buf[0] = (addr << 1) | 1;
- rpec = i2c_smbus_partial_pec(partial, 1,
- buf, data->block);
- cpec = data->block[data->block[0] + 1];
- break;
- default:
- cpec = rpec = 0;
- break;
- }
if (rpec != cpec) {
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec);
@@ -918,9 +896,8 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{
- union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
}
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
@@ -1003,13 +980,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
need to use only one message; when reading, we need two. We initialize
most things with sane defaults, to keep the code below somewhat
simpler. */
- unsigned char msgbuf0[34];
- unsigned char msgbuf1[34];
+ unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+ unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ?2:1;
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
int i;
+ u8 partial_pec = 0;
msgbuf0[0] = command;
switch(size) {
@@ -1052,7 +1030,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case I2C_SMBUS_BLOCK_DATA:
- case I2C_SMBUS_BLOCK_DATA_PEC:
if (read_write == I2C_SMBUS_READ) {
dev_err(&adapter->dev, "Block read not supported "
"under I2C emulation!\n");
@@ -1065,23 +1042,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
data->block[0]);
return -1;
}
- if(size == I2C_SMBUS_BLOCK_DATA_PEC)
- (msg[0].len)++;
- for (i = 1; i <= msg[0].len; i++)
+ for (i = 1; i < msg[0].len; i++)
msgbuf0[i] = data->block[i-1];
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
dev_dbg(&adapter->dev, "Block process call not supported "
"under I2C emulation!\n");
return -1;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
- msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
+ msg[1].len = I2C_SMBUS_BLOCK_MAX;
} else {
msg[0].len = data->block[0] + 1;
- if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
+ if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
"invalid block write size (%d)\n",
data->block[0]);
@@ -1097,9 +1071,30 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
return -1;
}
+ i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA);
+ if (i) {
+ /* Compute PEC if first message is a write */
+ if (!(msg[0].flags & I2C_M_RD)) {
+ if (num == 1) /* Write only */
+ i2c_smbus_add_pec(&msg[0]);
+ else /* Write followed by read */
+ partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
+ }
+ /* Ask for PEC if last message is a read */
+ if (msg[num-1].flags & I2C_M_RD)
+ msg[num-1].len++;
+ }
+
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
+ /* Check PEC if last message is a read */
+ if (i && (msg[num-1].flags & I2C_M_RD)) {
+ if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
+ return -1;
+ }
+
if (read_write == I2C_SMBUS_READ)
switch(size) {
case I2C_SMBUS_BYTE:
@@ -1114,8 +1109,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* fixed at 32 for now */
- data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
- for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
data->block[i+1] = msgbuf1[i];
break;
}
@@ -1128,28 +1123,8 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
union i2c_smbus_data * data)
{
s32 res;
- int swpec = 0;
- u8 partial = 0;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
- if((flags & I2C_CLIENT_PEC) &&
- !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
- swpec = 1;
- if(read_write == I2C_SMBUS_READ &&
- size == I2C_SMBUS_BLOCK_DATA)
- size = I2C_SMBUS_BLOCK_DATA_PEC;
- else if(size == I2C_SMBUS_PROC_CALL)
- size = I2C_SMBUS_PROC_CALL_PEC;
- else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
- i2c_smbus_add_pec(addr, command,
- I2C_SMBUS_BLOCK_DATA, data);
- partial = data->block[data->block[0] + 1];
- size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
- } else if(read_write == I2C_SMBUS_WRITE &&
- size != I2C_SMBUS_QUICK &&
- size != I2C_SMBUS_I2C_BLOCK_DATA)
- size = i2c_smbus_add_pec(addr, command, size, data);
- }
if (adapter->algo->smbus_xfer) {
down(&adapter->bus_lock);
@@ -1160,17 +1135,16 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data);
- if(res >= 0 && swpec &&
- size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
- (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
- size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
- if(i2c_smbus_check_pec(addr, command, size, partial, data))
- return -1;
- }
return res;
}
+/* Next four are needed by i2c-isa */
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
+EXPORT_SYMBOL_GPL(i2c_adapter_driver);
+EXPORT_SYMBOL_GPL(i2c_adapter_class);
+EXPORT_SYMBOL_GPL(i2c_bus_type);
+
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
EXPORT_SYMBOL(i2c_add_driver);
@@ -1186,7 +1160,6 @@ EXPORT_SYMBOL(i2c_master_send);
EXPORT_SYMBOL(i2c_master_recv);
EXPORT_SYMBOL(i2c_control);
EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_adapter_id);
EXPORT_SYMBOL(i2c_get_adapter);
EXPORT_SYMBOL(i2c_put_adapter);
EXPORT_SYMBOL(i2c_probe);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index bc5d557e5dd9..8af0bd1424d2 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -26,18 +26,15 @@
/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-/* The devfs code is contributed by Philipp Matthias Hahn
- <pmhahn@titan.lahn.de> */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
static struct i2c_client i2cdev_client_template;
@@ -80,10 +77,9 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
- i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL);
+ i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev)
return ERR_PTR(-ENOMEM);
- memset(i2c_dev, 0x00, sizeof(*i2c_dev));
spin_lock(&i2c_dev_array_lock);
if (i2c_dev_array[adap->nr]) {
@@ -177,8 +173,8 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
int i,datasize,res;
unsigned long funcs;
- dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
- iminor(inode),cmd, arg);
+ dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
+ cmd, arg);
switch ( cmd ) {
case I2C_SLAVE:
@@ -432,9 +428,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
if (IS_ERR(i2c_dev))
return PTR_ERR(i2c_dev);
- devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
- dev_dbg(&adap->dev, "Registered as minor %d\n", i2c_dev->minor);
+ pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+ adap->name, i2c_dev->minor);
/* register this i2c device with the driver core */
i2c_dev->adap = adap;
@@ -465,13 +460,12 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
return -ENODEV;
init_completion(&i2c_dev->released);
- devfs_remove("i2c/%d", i2c_dev->minor);
return_i2c_dev(i2c_dev);
class_device_unregister(&i2c_dev->class_dev);
wait_for_completion(&i2c_dev->released);
kfree(i2c_dev);
- dev_dbg(&adap->dev, "Adapter unregistered\n");
+ pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
return 0;
}
@@ -521,8 +515,6 @@ static int __init i2c_dev_init(void)
if (res)
goto out_unreg_class;
- devfs_mk_dir("i2c");
-
return 0;
out_unreg_class:
@@ -538,7 +530,6 @@ static void __exit i2c_dev_exit(void)
{
i2c_del_driver(&i2cdev_driver);
class_unregister(&i2c_dev_class);
- devfs_remove("i2c");
unregister_chrdev(I2C_MAJOR,"i2c");
}
diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
deleted file mode 100644
index f99a8161a9f1..000000000000
--- a/drivers/i2c/i2c-sensor-detect.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
- Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
- Mark D. Studebaker <mdsxyz123@yahoo.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/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
-static unsigned short empty[] = {I2C_CLIENT_END};
-static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
-
-/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
-int i2c_detect(struct i2c_adapter *adapter,
- struct i2c_address_data *address_data,
- int (*found_proc) (struct i2c_adapter *, int, int))
-{
- int addr, i, found, j, err;
- struct i2c_force_data *this_force;
- int is_isa = i2c_is_isa_adapter(adapter);
- int adapter_id =
- is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
- unsigned short *normal_i2c;
- unsigned int *normal_isa;
- unsigned short *probe;
- unsigned short *ignore;
-
- /* Forget it if we can't probe using SMBUS_QUICK */
- if ((!is_isa) &&
- !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
- return -1;
-
- /* Use default "empty" list if the adapter doesn't specify any */
- normal_i2c = probe = ignore = empty;
- normal_isa = empty_isa;
- if (address_data->normal_i2c)
- normal_i2c = address_data->normal_i2c;
- if (address_data->normal_isa)
- normal_isa = address_data->normal_isa;
- if (address_data->probe)
- probe = address_data->probe;
- if (address_data->ignore)
- ignore = address_data->ignore;
-
- for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
- if (!is_isa && i2c_check_addr(adapter, addr))
- continue;
-
- /* If it is in one of the force entries, we don't do any
- detection at all */
- found = 0;
- for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
- for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
- if ( ((adapter_id == this_force->force[j]) ||
- ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
- (addr == this_force->force[j + 1]) ) {
- dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
- if ((err = found_proc(adapter, addr, this_force->kind)))
- return err;
- found = 1;
- }
- }
- }
- if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about it
- right now */
- for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) {
- if ( ((adapter_id == ignore[i]) ||
- ((ignore[i] == ANY_I2C_BUS) &&
- !is_isa)) &&
- (addr == ignore[i + 1])) {
- dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- if (is_isa) {
- for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
- if (addr == normal_isa[i]) {
- dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- } else {
- for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) {
- if (addr == normal_i2c[i]) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr);
- }
- }
- }
-
- for (i = 0;
- !found && (probe[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adapter_id == probe[i]) ||
- ((probe[i] == ANY_I2C_BUS) && !is_isa))
- && (addr == probe[i + 1])) {
- dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (is_isa ||
- (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
- if ((err = found_proc(adapter, addr, -1)))
- return err;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
- "Rudolf Marek <r.marek@sh.cvut.cz>");
-
-MODULE_DESCRIPTION("i2c-sensor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
deleted file mode 100644
index 922e22f054bb..000000000000
--- a/drivers/i2c/i2c-sensor-vid.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- i2c-sensor-vid.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
-
- Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-struct vrm_model {
- u8 vendor;
- u8 eff_family;
- u8 eff_model;
- int vrm_type;
-};
-
-#define ANY 0xFF
-
-#ifdef CONFIG_X86
-
-static struct vrm_model vrm_models[] = {
- {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
- {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
- {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */
- {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
- {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
- {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
- {X86_VENDOR_INTEL, 0xF, ANY, 90}, /* P4 before Prescott */
- {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
- {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
- };
-
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
-{
- int i = 0;
-
- while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
- if (vrm_models[i].vendor==vendor)
- if ((vrm_models[i].eff_family==eff_family)&& \
- ((vrm_models[i].eff_model==eff_model)|| \
- (vrm_models[i].eff_model==ANY)))
- return vrm_models[i].vrm_type;
- i++;
- }
-
- return 0;
-}
-
-int i2c_which_vrm(void)
-{
- struct cpuinfo_x86 *c = cpu_data;
- u32 eax;
- u8 eff_family, eff_model;
- int vrm_ret;
-
- if (c->x86 < 6) return 0; /* any CPU with familly lower than 6
- dont have VID and/or CPUID */
- eax = cpuid_eax(1);
- eff_family = ((eax & 0x00000F00)>>8);
- eff_model = ((eax & 0x000000F0)>>4);
- if (eff_family == 0xF) { /* use extended model & family */
- eff_family += ((eax & 0x00F00000)>>20);
- eff_model += ((eax & 0x000F0000)>>16)<<4;
- }
- vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
- if (vrm_ret == 0)
- printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
- " x86 CPU\n");
- return vrm_ret;
-}
-
-/* and now for something completely different for Non-x86 world*/
-#else
-int i2c_which_vrm(void)
-{
- printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
- return 0;
-}
-#endif
-
-EXPORT_SYMBOL(i2c_which_vrm);
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5f33df47aa74..a737886e39d1 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -764,6 +764,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
config BLK_DEV_IDEDMA_PMAC
bool "PowerMac IDE DMA support"
depends on BLK_DEV_IDE_PMAC
+ select BLK_DEV_IDEDMA_PCI
help
This option allows the driver for the built-in IDE controller on
Power Macintoshes and PowerBooks to use DMA (direct memory access)
@@ -777,6 +778,35 @@ config BLK_DEV_IDE_PMAC_BLINK
This option enables the use of the sleep LED as a hard drive
activity LED.
+config BLK_DEV_IDE_AU1XXX
+ bool "IDE for AMD Alchemy Au1200"
+ depends on SOC_AU1200
+choice
+ prompt "IDE Mode for AMD Alchemy Au1200"
+ default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+
+config BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ bool "PIO+DbDMA IDE for AMD Alchemy Au1200"
+
+config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ bool "MDMA2+DbDMA IDE for AMD Alchemy Au1200"
+ depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+endchoice
+
+config BLK_DEV_IDE_AU1XXX_BURSTABLE_ON
+ bool "Enable burstable Mode on DbDMA"
+ default false
+ depends BLK_DEV_IDE_AU1XXX
+ help
+ This option enable the burstable Flag on DbDMA controller
+ (cf. "AMD Alchemy 'Au1200' Processor Data Book - PRELIMINARY").
+
+config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+ int "Maximum transfer size (KB) per request (up to 128)"
+ default "128"
+ depends BLK_DEV_IDE_AU1XXX
+
config IDE_ARM
def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
@@ -1012,7 +1042,7 @@ config BLK_DEV_UMC8672
endif
config BLK_DEV_IDEDMA
- def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS
+ def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
config IDEDMA_IVB
bool "IGNORE word93 Validation BITS"
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 74af7e074868..8b9d85526596 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2211,13 +2211,12 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (toc == NULL) {
/* Try to allocate space. */
- toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
- GFP_KERNEL);
- info->toc = toc;
+ toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
if (toc == NULL) {
printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
return -ENOMEM;
}
+ info->toc = toc;
}
/* Check to see if the existing data is still valid.
@@ -2240,7 +2239,8 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
/* First read just the header, so we know how long the TOC is. */
stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
sizeof(struct atapi_toc_header), sense);
- if (stat) return stat;
+ if (stat)
+ return stat;
#if ! STANDARD_ATAPI
if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
@@ -2324,7 +2324,8 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
/* Read the multisession information. */
stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
sizeof(ms_tmp), sense);
- if (stat) return stat;
+ if (stat)
+ return stat;
toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
} else {
@@ -2460,7 +2461,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
struct packet_command *cgc)
{
struct request req;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
if (cgc->timeout <= 0)
cgc->timeout = ATAPI_WAIT_PC;
@@ -2537,7 +2538,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, void *arg)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct cdrom_info *info = drive->driver_data;
int stat;
@@ -2548,7 +2549,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
*/
case CDROMPLAYTRKIND: {
unsigned long lba_start, lba_end;
- struct cdrom_ti *ti = (struct cdrom_ti *)arg;
+ struct cdrom_ti *ti = arg;
struct atapi_toc_entry *first_toc, *last_toc;
stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
@@ -2571,12 +2572,13 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
}
case CDROMREADTOCHDR: {
- struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
+ struct cdrom_tochdr *tochdr = arg;
struct atapi_toc *toc;
/* Make sure our saved TOC is valid. */
stat = cdrom_read_toc(drive, NULL);
- if (stat) return stat;
+ if (stat)
+ return stat;
toc = info->toc;
tochdr->cdth_trk0 = toc->hdr.first_track;
@@ -2586,11 +2588,12 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
}
case CDROMREADTOCENTRY: {
- struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
+ struct cdrom_tocentry *tocentry = arg;
struct atapi_toc_entry *toce;
stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
- if (stat) return stat;
+ if (stat)
+ return stat;
tocentry->cdte_ctrl = toce->control;
tocentry->cdte_adr = toce->adr;
@@ -2613,7 +2616,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct request_sense sense;
struct request req;
int ret;
@@ -2636,12 +2639,13 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
static
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct request_sense sense;
if (position) {
int stat = cdrom_lockdoor(drive, 0, &sense);
- if (stat) return stat;
+ if (stat)
+ return stat;
}
return cdrom_eject(drive, !position, &sense);
@@ -2650,7 +2654,7 @@ int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
return cdrom_lockdoor(drive, lock, NULL);
}
@@ -2700,7 +2704,7 @@ void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page
static
int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct request_sense sense;
struct atapi_capabilities_page cap;
int stat;
@@ -2723,7 +2727,7 @@ int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
static
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct media_event_desc med;
struct request_sense sense;
int stat;
@@ -2769,7 +2773,7 @@ int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
{
struct atapi_toc *toc;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
struct cdrom_info *info = drive->driver_data;
struct request_sense sense;
int ret;
@@ -2791,7 +2795,7 @@ int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
{
int stat;
char mcnbuf[24];
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
/* get MCN */
if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
@@ -2815,7 +2819,7 @@ static
int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
int slot_nr)
{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ ide_drive_t *drive = cdi->handle;
int retval;
if (slot_nr == CDSL_CURRENT) {
@@ -2886,7 +2890,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
devinfo->mask = 0;
devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
devinfo->capacity = nslots;
- devinfo->handle = (void *) drive;
+ devinfo->handle = drive;
strcpy(devinfo->name, drive->name);
/* set capability mask to match the probe. */
@@ -2942,7 +2946,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
* registered with the Uniform layer yet, it can't do this.
* Same goes for cdi->ops.
*/
- cdi->handle = (ide_drive_t *) drive;
+ cdi->handle = drive;
cdi->ops = &ide_cdrom_dops;
if (ide_cdrom_get_capabilities(drive, &cap))
@@ -3254,6 +3258,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
return 0;
}
+#ifdef CONFIG_PROC_FS
static
sector_t ide_cdrom_capacity (ide_drive_t *drive)
{
@@ -3264,6 +3269,7 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
return capacity * sectors_per_frame;
}
+#endif
static int ide_cd_remove(struct device *dev)
{
@@ -3309,7 +3315,7 @@ static int ide_cd_probe(struct device *);
static int proc_idecd_read_capacity
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- ide_drive_t*drive = (ide_drive_t *)data;
+ ide_drive_t *drive = data;
int len;
len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
@@ -3449,7 +3455,7 @@ static int ide_cd_probe(struct device *dev)
printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
+ info = kmalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
goto failed;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f9c1acb4ed6a..234f5de3e929 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -754,7 +754,7 @@ static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
idedisk_prepare_flush(q, rq);
- ret = blk_execute_rq(q, disk, rq);
+ ret = blk_execute_rq(q, disk, rq, 0);
/*
* if we failed and caller wants error offset, get it
@@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev)
goto failed;
g = alloc_disk_node(1 << PARTN_BITS,
- pcibus_to_node(drive->hwif->pci_dev->bus));
+ hwif_to_node(drive->hwif));
if (!g)
goto out_free_idkp;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 9eab6426148e..29c22fc278c6 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -317,7 +317,7 @@ typedef struct ide_floppy_obj {
unsigned long flags;
} idefloppy_floppy_t;
-#define IDEFLOPPY_TICKS_DELAY 3 /* default delay for ZIP 100 */
+#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
/*
* Floppy flag bits values.
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 248e3cc8b352..5275cbb1afe9 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -150,7 +150,7 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
switch (rq->pm->pm_step) {
case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
- if (rq->pm->pm_state == 4)
+ if (rq->pm->pm_state == PM_EVENT_FREEZE)
rq->pm->pm_step = ide_pm_state_completed;
else
rq->pm->pm_step = idedisk_pm_standby;
@@ -560,7 +560,7 @@ ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
EXPORT_SYMBOL_GPL(__ide_abort);
/**
- * ide_abort - abort pending IDE operatins
+ * ide_abort - abort pending IDE operations
* @drive: drive the error occurred on
* @msg: message to report
*
@@ -623,7 +623,7 @@ static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
* @drive: drive the completion interrupt occurred on
*
* drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- * We do any necessary daya reading and then wait for the drive to
+ * We do any necessary data reading and then wait for the drive to
* go non busy. At that point we may read the error data and complete
* the request
*/
@@ -773,7 +773,7 @@ EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
/**
* execute_drive_command - issue special drive command
- * @drive: the drive to issue th command on
+ * @drive: the drive to issue the command on
* @rq: the request structure holding the command
*
* execute_drive_cmd() issues a special drive command, usually
@@ -1101,6 +1101,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
ide_hwif_t *hwif;
struct request *rq;
ide_startstop_t startstop;
+ int loops = 0;
/* for atari only: POSSIBLY BROKEN HERE(?) */
ide_get_lock(ide_intr, hwgroup);
@@ -1153,6 +1154,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
/* no more work for this hwgroup (for now) */
return;
}
+ again:
hwif = HWIF(drive);
if (hwgroup->hwif->sharing_irq &&
hwif != hwgroup->hwif &&
@@ -1192,8 +1194,14 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* though. I hope that doesn't happen too much, hopefully not
* unless the subdriver triggers such a thing in its own PM
* state machine.
+ *
+ * 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->flags & REQ_PREEMPT)) {
+ drive = drive->next ? drive->next : hwgroup->drive;
+ if (loops++ < 4 && !blk_queue_plugged(drive->queue))
+ goto again;
/* We clear busy, there should be no pending ATA command at this point. */
hwgroup->busy = 0;
break;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b443b04a4c5a..0b0aa4f51628 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -601,44 +601,15 @@ EXPORT_SYMBOL(ide_wait_stat);
*/
u8 eighty_ninty_three (ide_drive_t *drive)
{
-#if 0
- if (!HWIF(drive)->udma_four)
+ if(HWIF(drive)->udma_four == 0)
+ return 0;
+ if (!(drive->id->hw_config & 0x6000))
return 0;
-
- if (drive->id->major_rev_num) {
- int hssbd = 0;
- int i;
- /*
- * Determine highest Supported SPEC
- */
- for (i=1; i<=15; i++)
- if (drive->id->major_rev_num & (1<<i))
- hssbd++;
-
- switch (hssbd) {
- case 7:
- case 6:
- case 5:
- /* ATA-4 and older do not support above Ultra 33 */
- default:
- return 0;
- }
- }
-
- return ((u8) (
-#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-
-#else
-
- return ((u8) ((HWIF(drive)->udma_four) &&
#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
+ if(!(drive->id->hw_config & 0x4000))
+ return 0;
#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-#endif
+ return 1;
}
EXPORT_SYMBOL(eighty_ninty_three);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 7df85af75371..c1128ae5cd2f 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -978,8 +978,7 @@ static int ide_init_queue(ide_drive_t *drive)
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &ide_lock,
- pcibus_to_node(drive->hwif->pci_dev->bus));
+ q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
if (!q)
return 1;
@@ -1048,6 +1047,8 @@ static int init_irq (ide_hwif_t *hwif)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
+ BUG_ON(hwif == NULL);
+
down(&ide_cfg_sem);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
@@ -1097,7 +1098,7 @@ static int init_irq (ide_hwif_t *hwif)
spin_unlock_irq(&ide_lock);
} else {
hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
- pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus));
+ hwif_to_node(hwif->drives[0].hwif));
if (!hwgroup)
goto out_up;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 4063d2c34e3d..84665e2ba3c8 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -64,6 +64,7 @@ static int proc_ide_read_imodel
case ide_cy82c693: name = "cy82c693"; break;
case ide_4drives: name = "4drives"; break;
case ide_pmac: name = "mac-io"; break;
+ case ide_au1xxx: name = "au1xxx"; break;
default: name = "(unknown)"; break;
}
len = sprintf(page, "%s\n", name);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 5a3dc46008e6..47f2b832555f 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1013,6 +1013,8 @@ typedef struct ide_tape_obj {
static DECLARE_MUTEX(idetape_ref_sem);
+static struct class *idetape_sysfs_class;
+
#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
#define ide_tape_g(disk) \
@@ -2903,8 +2905,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
(tape->ascq == 1 || tape->ascq == 8)))
return -EIO;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 10);
+ msleep(100);
}
return -EIO;
}
@@ -4705,6 +4706,10 @@ static void ide_tape_release(struct kref *kref)
drive->dsc_overlap = 0;
drive->driver_data = NULL;
+ class_device_destroy(idetape_sysfs_class,
+ MKDEV(IDETAPE_MAJOR, tape->minor));
+ class_device_destroy(idetape_sysfs_class,
+ MKDEV(IDETAPE_MAJOR, tape->minor + 128));
devfs_remove("%s/mt", drive->devfs_name);
devfs_remove("%s/mtn", drive->devfs_name);
devfs_unregister_tape(g->number);
@@ -4879,6 +4884,11 @@ static int ide_tape_probe(struct device *dev)
idetape_setup(drive, tape, minor);
+ class_device_create(idetape_sysfs_class, NULL,
+ MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
+ class_device_create(idetape_sysfs_class, NULL,
+ MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
+
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO,
"%s/mt", drive->devfs_name);
@@ -4904,6 +4914,7 @@ MODULE_LICENSE("GPL");
static void __exit idetape_exit (void)
{
driver_unregister(&idetape_driver.gen_driver);
+ class_destroy(idetape_sysfs_class);
unregister_chrdev(IDETAPE_MAJOR, "ht");
}
@@ -4912,11 +4923,33 @@ static void __exit idetape_exit (void)
*/
static int idetape_init (void)
{
+ int error = 1;
+ idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
+ if (IS_ERR(idetape_sysfs_class)) {
+ idetape_sysfs_class = NULL;
+ printk(KERN_ERR "Unable to create sysfs class for ide tapes\n");
+ error = -EBUSY;
+ goto out;
+ }
+
if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
- return -EBUSY;
+ error = -EBUSY;
+ goto out_free_class;
}
- return driver_register(&idetape_driver.gen_driver);
+
+ error = driver_register(&idetape_driver.gen_driver);
+ if (error)
+ goto out_free_driver;
+
+ return 0;
+
+out_free_driver:
+ driver_unregister(&idetape_driver.gen_driver);
+out_free_class:
+ class_destroy(idetape_sysfs_class);
+out:
+ return error;
}
module_init(idetape_init);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d04f62ab5de1..ace8edad6e96 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
}
rq.special = args;
+ args->rq = &rq;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c1196ce15b4d..2fcfac6e967a 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -27,6 +27,7 @@
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
+#include <linux/kernel.h>
#include <linux/hdreg.h>
#define XFER_PIO_5 0x0d
@@ -96,11 +97,9 @@ static struct ide_timing ide_timing[] = {
#define IDE_TIMING_UDMA 0x80
#define IDE_TIMING_ALL 0xff
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#define MAX(a,b) ((a)>(b)?(a):(b))
-#define FIT(v,min,max) MAX(MIN(v,max),min)
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
+#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
+#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
#define XFER_UDMA_133 0x48
@@ -188,14 +187,14 @@ static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int
static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
{
- if (what & IDE_TIMING_SETUP ) m->setup = MAX(a->setup, b->setup);
- if (what & IDE_TIMING_ACT8B ) m->act8b = MAX(a->act8b, b->act8b);
- if (what & IDE_TIMING_REC8B ) m->rec8b = MAX(a->rec8b, b->rec8b);
- if (what & IDE_TIMING_CYC8B ) m->cyc8b = MAX(a->cyc8b, b->cyc8b);
- if (what & IDE_TIMING_ACTIVE ) m->active = MAX(a->active, b->active);
- if (what & IDE_TIMING_RECOVER) m->recover = MAX(a->recover, b->recover);
- if (what & IDE_TIMING_CYCLE ) m->cycle = MAX(a->cycle, b->cycle);
- if (what & IDE_TIMING_UDMA ) m->udma = MAX(a->udma, b->udma);
+ if (what & IDE_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
+ if (what & IDE_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
+ if (what & IDE_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
+ if (what & IDE_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
+ if (what & IDE_TIMING_ACTIVE ) m->active = max(a->active, b->active);
+ if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & IDE_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
+ if (what & IDE_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
static struct ide_timing* ide_timing_find_mode(short speed)
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index dae1bd5b8c3e..73ca8f73917d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1229,7 +1229,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state)
rq.special = &args;
rq.pm = &rqpm;
rqpm.pm_step = ide_pm_state_start_suspend;
- rqpm.pm_state = state;
+ rqpm.pm_state = state.event;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -1248,7 +1248,7 @@ static int generic_ide_resume(struct device *dev)
rq.special = &args;
rq.pm = &rqpm;
rqpm.pm_step = ide_pm_state_start_resume;
- rqpm.pm_state = 0;
+ rqpm.pm_state = PM_EVENT_ON;
return ide_do_drive_cmd(drive, &rq, ide_head_wait);
}
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index f1d1ec4e9677..a35a58bef1a4 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -43,6 +43,7 @@
#include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/major.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -340,8 +341,7 @@ static void ide_config(dev_link_t *link)
break;
}
}
- __set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
}
if (hd < 0) {
@@ -454,9 +454,12 @@ int ide_event(event_t event, int priority,
static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4),
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
+ PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */
PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
@@ -474,13 +477,14 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b),
- PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79),
+ PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+ PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
PCMCIA_DEVICE_NULL,
};
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
new file mode 100644
index 000000000000..2b6327c576b9
--- /dev/null
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -0,0 +1,1250 @@
+/*
+ * linux/drivers/ide/mips/au1xxx-ide.c version 01.30.00 Aug. 02 2005
+ *
+ * BRIEF MODULE DESCRIPTION
+ * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
+ *
+ * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * 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.
+ *
+ * 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.
+ *
+ * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
+ * Interface and Linux Device Driver" Application Note.
+ */
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+#include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/sysdev.h>
+
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#if CONFIG_PM
+#include <asm/mach-au1x00/au1xxx_pm.h>
+#endif
+
+#include <asm/mach-au1x00/au1xxx_ide.h>
+
+#define DRV_NAME "au1200-ide"
+#define DRV_VERSION "1.0"
+#define DRV_AUTHOR "AMD PCS / Pete Popov <ppopov@embeddedalley.com>"
+#define DRV_DESC "Au1200 IDE"
+
+static _auide_hwif auide_hwif;
+static spinlock_t ide_tune_drive_spin_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t ide_tune_chipset_spin_lock = SPIN_LOCK_UNLOCKED;
+static int dbdma_init_done = 0;
+
+/*
+ * local I/O functions
+ */
+u8 auide_inb(unsigned long port)
+{
+ return (au_readb(port));
+}
+
+u16 auide_inw(unsigned long port)
+{
+ return (au_readw(port));
+}
+
+u32 auide_inl(unsigned long port)
+{
+ return (au_readl(port));
+}
+
+void auide_insw(unsigned long port, void *addr, u32 count)
+{
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+
+ _auide_hwif *ahwif = &auide_hwif;
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+
+ if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1,
+ DDMA_FLAGS_NOIE)) {
+ printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+ return;
+ }
+ ctp = *((chan_tab_t **)ahwif->rx_chan);
+ dp = ctp->cur_ptr;
+ while (dp->dscr_cmd0 & DSCR_CMD0_V)
+ ;
+ ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+#else
+ while (count--)
+ {
+ *(u16 *)addr = au_readw(port);
+ addr +=2 ;
+ }
+#endif
+}
+
+void auide_insl(unsigned long port, void *addr, u32 count)
+{
+ while (count--)
+ {
+ *(u32 *)addr = au_readl(port);
+ /* NOTE: For IDE interfaces over PCMCIA,
+ * 32-bit access does not work
+ */
+ addr += 4;
+ }
+}
+
+void auide_outb(u8 addr, unsigned long port)
+{
+ return (au_writeb(addr, port));
+}
+
+void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port)
+{
+ return (au_writeb(addr, port));
+}
+
+void auide_outw(u16 addr, unsigned long port)
+{
+ return (au_writew(addr, port));
+}
+
+void auide_outl(u32 addr, unsigned long port)
+{
+ return (au_writel(addr, port));
+}
+
+void auide_outsw(unsigned long port, void *addr, u32 count)
+{
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+ _auide_hwif *ahwif = &auide_hwif;
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+
+ if(!put_source_flags(ahwif->tx_chan, (void*)addr,
+ count << 1, DDMA_FLAGS_NOIE)) {
+ printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+ return;
+ }
+ ctp = *((chan_tab_t **)ahwif->tx_chan);
+ dp = ctp->cur_ptr;
+ while (dp->dscr_cmd0 & DSCR_CMD0_V)
+ ;
+ ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+#else
+ while (count--)
+ {
+ au_writew(*(u16 *)addr, port);
+ addr += 2;
+ }
+#endif
+}
+
+void auide_outsl(unsigned long port, void *addr, u32 count)
+{
+ while (count--)
+ {
+ au_writel(*(u32 *)addr, port);
+ /* NOTE: For IDE interfaces over PCMCIA,
+ * 32-bit access does not work
+ */
+ addr += 4;
+ }
+}
+
+static void auide_tune_drive(ide_drive_t *drive, byte pio)
+{
+ int mem_sttime;
+ int mem_stcfg;
+ unsigned long flags;
+ u8 speed;
+
+ /* get the best pio mode for the drive */
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+
+ printk("%s: setting Au1XXX IDE to PIO mode%d\n",
+ drive->name, pio);
+
+ spin_lock_irqsave(&ide_tune_drive_spin_lock, flags);
+
+ mem_sttime = 0;
+ mem_stcfg = au_readl(MEM_STCFG2);
+
+ /* set pio mode! */
+ switch(pio) {
+ case 0:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_PIO0_TWCS
+ | SBC_IDE_PIO0_TCSH
+ | SBC_IDE_PIO0_TCSOFF
+ | SBC_IDE_PIO0_TWP
+ | SBC_IDE_PIO0_TCSW
+ | SBC_IDE_PIO0_TPM
+ | SBC_IDE_PIO0_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg |= TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS;
+
+ au_writel(mem_sttime,MEM_STTIME2);
+ au_writel(mem_stcfg,MEM_STCFG2);
+ break;
+
+ case 1:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_PIO1_TWCS
+ | SBC_IDE_PIO1_TCSH
+ | SBC_IDE_PIO1_TCSOFF
+ | SBC_IDE_PIO1_TWP
+ | SBC_IDE_PIO1_TCSW
+ | SBC_IDE_PIO1_TPM
+ | SBC_IDE_PIO1_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg |= TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS;
+ break;
+
+ case 2:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_PIO2_TWCS
+ | SBC_IDE_PIO2_TCSH
+ | SBC_IDE_PIO2_TCSOFF
+ | SBC_IDE_PIO2_TWP
+ | SBC_IDE_PIO2_TCSW
+ | SBC_IDE_PIO2_TPM
+ | SBC_IDE_PIO2_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg &= ~TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS;
+ break;
+
+ case 3:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_PIO3_TWCS
+ | SBC_IDE_PIO3_TCSH
+ | SBC_IDE_PIO3_TCSOFF
+ | SBC_IDE_PIO3_TWP
+ | SBC_IDE_PIO3_TCSW
+ | SBC_IDE_PIO3_TPM
+ | SBC_IDE_PIO3_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg |= TS_MASK;
+ mem_stcfg &= ~TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS;
+
+ break;
+
+ case 4:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_PIO4_TWCS
+ | SBC_IDE_PIO4_TCSH
+ | SBC_IDE_PIO4_TCSOFF
+ | SBC_IDE_PIO4_TWP
+ | SBC_IDE_PIO4_TCSW
+ | SBC_IDE_PIO4_TPM
+ | SBC_IDE_PIO4_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg &= ~TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS;
+ break;
+ }
+
+ au_writel(mem_sttime,MEM_STTIME2);
+ au_writel(mem_stcfg,MEM_STCFG2);
+
+ spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags);
+
+ speed = pio + XFER_PIO_0;
+ ide_config_drive_speed(drive, speed);
+}
+
+static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
+{
+ u8 mode = 0;
+ int mem_sttime;
+ int mem_stcfg;
+ unsigned long flags;
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ struct hd_driveid *id = drive->id;
+
+ /*
+ * Now see what the current drive is capable of,
+ * selecting UDMA only if the mate said it was ok.
+ */
+ if (id && (id->capability & 1) && drive->autodma &&
+ !__ide_dma_bad_drive(drive)) {
+ if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
+ if (id->dma_mword & 4)
+ mode = XFER_MW_DMA_2;
+ else if (id->dma_mword & 2)
+ mode = XFER_MW_DMA_1;
+ else if (id->dma_mword & 1)
+ mode = XFER_MW_DMA_0;
+ }
+ }
+#endif
+
+ spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags);
+
+ mem_sttime = 0;
+ mem_stcfg = au_readl(MEM_STCFG2);
+
+ switch(speed) {
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ auide_tune_drive(drive, (speed - XFER_PIO_0));
+ break;
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ case XFER_MW_DMA_2:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_MDMA2_TWCS
+ | SBC_IDE_MDMA2_TCSH
+ | SBC_IDE_MDMA2_TCSOFF
+ | SBC_IDE_MDMA2_TWP
+ | SBC_IDE_MDMA2_TCSW
+ | SBC_IDE_MDMA2_TPM
+ | SBC_IDE_MDMA2_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg &= ~TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
+
+ mode = XFER_MW_DMA_2;
+ break;
+ case XFER_MW_DMA_1:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_MDMA1_TWCS
+ | SBC_IDE_MDMA1_TCSH
+ | SBC_IDE_MDMA1_TCSOFF
+ | SBC_IDE_MDMA1_TWP
+ | SBC_IDE_MDMA1_TCSW
+ | SBC_IDE_MDMA1_TPM
+ | SBC_IDE_MDMA1_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg &= ~TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
+
+ mode = XFER_MW_DMA_1;
+ break;
+ case XFER_MW_DMA_0:
+ /* set timing parameters for RCS2# */
+ mem_sttime = SBC_IDE_MDMA0_TWCS
+ | SBC_IDE_MDMA0_TCSH
+ | SBC_IDE_MDMA0_TCSOFF
+ | SBC_IDE_MDMA0_TWP
+ | SBC_IDE_MDMA0_TCSW
+ | SBC_IDE_MDMA0_TPM
+ | SBC_IDE_MDMA0_TA;
+ /* set configuration for RCS2# */
+ mem_stcfg |= TS_MASK;
+ mem_stcfg &= ~TCSOE_MASK;
+ mem_stcfg &= ~TOECS_MASK;
+ mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
+
+ mode = XFER_MW_DMA_0;
+ break;
+#endif
+ default:
+ return 1;
+ }
+
+ /*
+ * Tell the drive to switch to the new mode; abort on failure.
+ */
+ if (!mode || ide_config_drive_speed(drive, mode))
+ {
+ return 1; /* failure */
+ }
+
+
+ au_writel(mem_sttime,MEM_STTIME2);
+ au_writel(mem_stcfg,MEM_STCFG2);
+
+ spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags);
+
+ return 0;
+}
+
+/*
+ * Multi-Word DMA + DbDMA functions
+ */
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+
+static int in_drive_list(struct hd_driveid *id,
+ const struct drive_list_entry *drive_table)
+{
+ for ( ; drive_table->id_model ; drive_table++){
+ if ((!strcmp(drive_table->id_model, id->model)) &&
+ ((strstr(drive_table->id_firmware, id->fw_rev)) ||
+ (!strcmp(drive_table->id_firmware, "ALL")))
+ )
+ return 1;
+ }
+ return 0;
+}
+
+static int auide_build_sglist(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+ struct scatterlist *sg = hwif->sg_table;
+
+ ide_map_sg(drive, rq);
+
+ if (rq_data_dir(rq) == READ)
+ hwif->sg_dma_direction = DMA_FROM_DEVICE;
+ else
+ hwif->sg_dma_direction = DMA_TO_DEVICE;
+
+ return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,
+ hwif->sg_dma_direction);
+}
+
+static int auide_build_dmatable(ide_drive_t *drive)
+{
+ int i, iswrite, count = 0;
+ ide_hwif_t *hwif = HWIF(drive);
+
+ struct request *rq = HWGROUP(drive)->rq;
+
+ _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+ struct scatterlist *sg;
+
+ iswrite = (rq_data_dir(rq) == WRITE);
+ /* Save for interrupt context */
+ ahwif->drive = drive;
+
+ /* Build sglist */
+ hwif->sg_nents = i = auide_build_sglist(drive, rq);
+
+ if (!i)
+ return 0;
+
+ /* fill the descriptors */
+ sg = hwif->sg_table;
+ while (i && sg_dma_len(sg)) {
+ u32 cur_addr;
+ u32 cur_len;
+
+ cur_addr = sg_dma_address(sg);
+ cur_len = sg_dma_len(sg);
+
+ while (cur_len) {
+ u32 flags = DDMA_FLAGS_NOIE;
+ unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
+
+ if (++count >= PRD_ENTRIES) {
+ printk(KERN_WARNING "%s: DMA table too small\n",
+ drive->name);
+ goto use_pio_instead;
+ }
+
+ /* Lets enable intr for the last descriptor only */
+ if (1==i)
+ flags = DDMA_FLAGS_IE;
+ else
+ flags = DDMA_FLAGS_NOIE;
+
+ if (iswrite) {
+ if(!put_source_flags(ahwif->tx_chan,
+ (void*)(page_address(sg->page)
+ + sg->offset),
+ tc, flags)) {
+ printk(KERN_ERR "%s failed %d\n",
+ __FUNCTION__, __LINE__);
+ }
+ } else
+ {
+ if(!put_dest_flags(ahwif->rx_chan,
+ (void*)(page_address(sg->page)
+ + sg->offset),
+ tc, flags)) {
+ printk(KERN_ERR "%s failed %d\n",
+ __FUNCTION__, __LINE__);
+ }
+ }
+
+ cur_addr += tc;
+ cur_len -= tc;
+ }
+ sg++;
+ i--;
+ }
+
+ if (count)
+ return 1;
+
+use_pio_instead:
+ dma_unmap_sg(ahwif->dev,
+ hwif->sg_table,
+ hwif->sg_nents,
+ hwif->sg_dma_direction);
+
+ return 0; /* revert to PIO for this request */
+}
+
+static int auide_dma_end(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+
+ if (hwif->sg_nents) {
+ dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
+ hwif->sg_dma_direction);
+ hwif->sg_nents = 0;
+ }
+
+ return 0;
+}
+
+static void auide_dma_start(ide_drive_t *drive )
+{
+// printk("%s\n", __FUNCTION__);
+}
+
+ide_startstop_t auide_dma_intr(ide_drive_t *drive)
+{
+ //printk("%s\n", __FUNCTION__);
+
+ u8 stat = 0, dma_stat = 0;
+
+ dma_stat = HWIF(drive)->ide_dma_end(drive);
+ stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */
+ if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+ if (!dma_stat) {
+ struct request *rq = HWGROUP(drive)->rq;
+
+ ide_end_request(drive, 1, rq->nr_sectors);
+ return ide_stopped;
+ }
+ printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
+ drive->name, dma_stat);
+ }
+ return ide_error(drive, "dma_intr", stat);
+}
+
+static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+ //printk("%s\n", __FUNCTION__);
+
+ /* issue cmd to drive */
+ ide_execute_command(drive, command, &auide_dma_intr,
+ (2*WAIT_CMD), NULL);
+}
+
+static int auide_dma_setup(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+
+ if (drive->media != ide_disk)
+ return 1;
+
+ if (!auide_build_dmatable(drive))
+ /* try PIO instead of DMA */
+ return 1;
+
+ drive->waiting_for_dma = 1;
+
+ return 0;
+}
+
+static int auide_dma_check(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ if( !dbdma_init_done ){
+ auide_hwif.white_list = in_drive_list(drive->id,
+ dma_white_list);
+ auide_hwif.black_list = in_drive_list(drive->id,
+ dma_black_list);
+ auide_hwif.drive = drive;
+ auide_ddma_init(&auide_hwif);
+ dbdma_init_done = 1;
+ }
+#endif
+
+ /* Is the drive in our DMA black list? */
+ if ( auide_hwif.black_list ) {
+ drive->using_dma = 0;
+ printk("%s found in dma_blacklist[]! Disabling DMA.\n",
+ drive->id->model);
+ }
+ else
+ drive->using_dma = 1;
+
+ return HWIF(drive)->ide_dma_host_on(drive);
+}
+
+static int auide_dma_test_irq(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+
+ if (!drive->waiting_for_dma)
+ 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
+ */
+ drive->waiting_for_dma++;
+ if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
+ printk(KERN_WARNING "%s: timeout waiting for ddma to \
+ complete\n", drive->name);
+ return 1;
+ }
+ udelay(10);
+ return 0;
+}
+
+static int auide_dma_host_on(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+ return 0;
+}
+
+static int auide_dma_on(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+ drive->using_dma = 1;
+ return auide_dma_host_on(drive);
+}
+
+
+static int auide_dma_host_off(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+ return 0;
+}
+
+static int auide_dma_off_quietly(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+ drive->using_dma = 0;
+ return auide_dma_host_off(drive);
+}
+
+static int auide_dma_lostirq(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+
+ printk(KERN_ERR "%s: IRQ lost\n", drive->name);
+ return 0;
+}
+
+static void auide_ddma_tx_callback(int irq, void *param, struct pt_regs *regs)
+{
+// printk("%s\n", __FUNCTION__);
+
+ _auide_hwif *ahwif = (_auide_hwif*)param;
+ ahwif->drive->waiting_for_dma = 0;
+ return;
+}
+
+static void auide_ddma_rx_callback(int irq, void *param, struct pt_regs *regs)
+{
+// printk("%s\n", __FUNCTION__);
+
+ _auide_hwif *ahwif = (_auide_hwif*)param;
+ ahwif->drive->waiting_for_dma = 0;
+ return;
+}
+
+static int auide_dma_timeout(ide_drive_t *drive)
+{
+// printk("%s\n", __FUNCTION__);
+
+ printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
+
+ if (HWIF(drive)->ide_dma_test_irq(drive))
+ return 0;
+
+ return HWIF(drive)->ide_dma_end(drive);
+}
+#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+
+
+static int auide_ddma_init( _auide_hwif *auide )
+{
+// printk("%s\n", __FUNCTION__);
+
+ dbdev_tab_t source_dev_tab;
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+ dbdev_tab_t target_dev_tab;
+ ide_hwif_t *hwif = auide->hwif;
+ char warning_output [2][80];
+ int i;
+#endif
+
+ /* Add our custom device to DDMA device table */
+ /* Create our new device entries in the table */
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+ source_dev_tab.dev_id = AU1XXX_ATA_DDMA_REQ;
+
+ if( auide->white_list || auide->black_list ){
+ source_dev_tab.dev_tsize = 8;
+ source_dev_tab.dev_devwidth = 32;
+ source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
+ source_dev_tab.dev_intlevel = 0;
+ source_dev_tab.dev_intpolarity = 0;
+
+ /* init device table for target - static bus controller - */
+ target_dev_tab.dev_id = DSCR_CMD0_ALWAYS;
+ target_dev_tab.dev_tsize = 8;
+ target_dev_tab.dev_devwidth = 32;
+ target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
+ target_dev_tab.dev_intlevel = 0;
+ target_dev_tab.dev_intpolarity = 0;
+ target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE;
+ }
+ else{
+ source_dev_tab.dev_tsize = 1;
+ source_dev_tab.dev_devwidth = 16;
+ source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
+ source_dev_tab.dev_intlevel = 0;
+ source_dev_tab.dev_intpolarity = 0;
+
+ /* init device table for target - static bus controller - */
+ target_dev_tab.dev_id = DSCR_CMD0_ALWAYS;
+ target_dev_tab.dev_tsize = 1;
+ target_dev_tab.dev_devwidth = 16;
+ target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
+ target_dev_tab.dev_intlevel = 0;
+ target_dev_tab.dev_intpolarity = 0;
+ target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE;
+
+ sprintf(&warning_output[0][0],
+ "%s is not on ide driver white list.",
+ auide_hwif.drive->id->model);
+ for ( i=strlen(&warning_output[0][0]) ; i<76; i++ ){
+ sprintf(&warning_output[0][i]," ");
+ }
+
+ sprintf(&warning_output[1][0],
+ "To add %s please read 'Documentation/mips/AU1xxx_IDE.README'.",
+ auide_hwif.drive->id->model);
+ for ( i=strlen(&warning_output[1][0]) ; i<76; i++ ){
+ sprintf(&warning_output[1][i]," ");
+ }
+
+ printk("\n****************************************");
+ printk("****************************************\n");
+ printk("* %s *\n",&warning_output[0][0]);
+ printk("* Switch to safe MWDMA Mode! ");
+ printk(" *\n");
+ printk("* %s *\n",&warning_output[1][0]);
+ printk("****************************************");
+ printk("****************************************\n\n");
+ }
+#else
+ source_dev_tab.dev_id = DSCR_CMD0_ALWAYS;
+ source_dev_tab.dev_tsize = 8;
+ source_dev_tab.dev_devwidth = 32;
+ source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR;
+ source_dev_tab.dev_intlevel = 0;
+ source_dev_tab.dev_intpolarity = 0;
+#endif
+
+#if CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON
+ /* set flags for tx channel */
+ source_dev_tab.dev_flags = DEV_FLAGS_OUT
+ | DEV_FLAGS_SYNC
+ | DEV_FLAGS_BURSTABLE;
+ auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+ /* set flags for rx channel */
+ source_dev_tab.dev_flags = DEV_FLAGS_IN
+ | DEV_FLAGS_SYNC
+ | DEV_FLAGS_BURSTABLE;
+ auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+#else
+ /* set flags for tx channel */
+ source_dev_tab.dev_flags = DEV_FLAGS_OUT | DEV_FLAGS_SYNC;
+ auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+ /* set flags for rx channel */
+ source_dev_tab.dev_flags = DEV_FLAGS_IN | DEV_FLAGS_SYNC;
+ auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+
+ auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab);
+
+ /* Get a channel for TX */
+ auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id,
+ auide->tx_dev_id,
+ auide_ddma_tx_callback,
+ (void*)auide);
+ /* Get a channel for RX */
+ auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+ auide->target_dev_id,
+ auide_ddma_rx_callback,
+ (void*)auide);
+#else /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */
+ /*
+ * Note: if call back is not enabled, update ctp->cur_ptr manually
+ */
+ auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
+ auide->tx_dev_id,
+ NULL,
+ (void*)auide);
+ auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+ DSCR_CMD0_ALWAYS,
+ NULL,
+ (void*)auide);
+#endif
+ auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
+ NUM_DESCRIPTORS);
+ auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
+ NUM_DESCRIPTORS);
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+ hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
+ PRD_ENTRIES * PRD_BYTES, /* 1 Page */
+ &hwif->dmatable_dma, GFP_KERNEL);
+
+ auide->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
+ GFP_KERNEL|GFP_DMA);
+ if (auide->sg_table == NULL) {
+ return -ENOMEM;
+ }
+#endif
+ au1xxx_dbdma_start( auide->tx_chan );
+ au1xxx_dbdma_start( auide->rx_chan );
+ return 0;
+}
+
+static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+{
+ int i;
+#define ide_ioreg_t unsigned long
+ ide_ioreg_t *ata_regs = hw->io_ports;
+
+ /* fixme */
+ for (i = 0; i < IDE_CONTROL_OFFSET; i++) {
+ *ata_regs++ = (ide_ioreg_t) ahwif->regbase
+ + (ide_ioreg_t)(i << AU1XXX_ATA_REG_OFFSET);
+ }
+
+ /* set the Alternative Status register */
+ *ata_regs = (ide_ioreg_t) ahwif->regbase
+ + (ide_ioreg_t)(14 << AU1XXX_ATA_REG_OFFSET);
+}
+
+static int au_ide_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ _auide_hwif *ahwif = &auide_hwif;
+ ide_hwif_t *hwif;
+ struct resource *res;
+ int ret = 0;
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+ char *mode = "MWDMA2";
+#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+ char *mode = "PIO+DDMA(offload)";
+#endif
+
+ memset(&auide_hwif, 0, sizeof(_auide_hwif));
+ auide_hwif.dev = 0;
+
+ ahwif->dev = dev;
+ ahwif->irq = platform_get_irq(pdev, 0);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res == NULL) {
+ pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (!request_mem_region (res->start, res->end-res->start, pdev->name)) {
+ pr_debug("%s: request_mem_region failed\n", DRV_NAME);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ahwif->regbase = (u32)ioremap(res->start, res->end-res->start);
+ if (ahwif->regbase == 0) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ hwif = &ide_hwifs[pdev->id];
+ hw_regs_t *hw = &hwif->hw;
+ hwif->irq = hw->irq = ahwif->irq;
+ hwif->chipset = ide_au1xxx;
+
+ auide_setup_ports(hw, ahwif);
+ memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+ hwif->rqsize = CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ;
+ hwif->rqsize = ((hwif->rqsize > AU1XXX_ATA_RQSIZE)
+ || (hwif->rqsize < 32)) ? AU1XXX_ATA_RQSIZE : hwif->rqsize;
+#else /* if kernel config is not set */
+ hwif->rqsize = AU1XXX_ATA_RQSIZE;
+#endif
+
+ hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */
+ hwif->swdma_mask = 0x07;
+#else
+ hwif->mwdma_mask = 0x0;
+ hwif->swdma_mask = 0x0;
+#endif
+ //hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+ hwif->noprobe = 0;
+ hwif->drives[0].unmask = 1;
+ hwif->drives[1].unmask = 1;
+
+ /* hold should be on in all cases */
+ hwif->hold = 1;
+ hwif->mmio = 2;
+
+ /* set up local I/O function entry points */
+ hwif->INB = auide_inb;
+ hwif->INW = auide_inw;
+ hwif->INL = auide_inl;
+ hwif->INSW = auide_insw;
+ hwif->INSL = auide_insl;
+ hwif->OUTB = auide_outb;
+ hwif->OUTBSYNC = auide_outbsync;
+ hwif->OUTW = auide_outw;
+ hwif->OUTL = auide_outl;
+ hwif->OUTSW = auide_outsw;
+ hwif->OUTSL = auide_outsl;
+
+ hwif->tuneproc = &auide_tune_drive;
+ hwif->speedproc = &auide_tune_chipset;
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ hwif->ide_dma_off_quietly = &auide_dma_off_quietly;
+ hwif->ide_dma_timeout = &auide_dma_timeout;
+
+ hwif->ide_dma_check = &auide_dma_check;
+ hwif->dma_exec_cmd = &auide_dma_exec_cmd;
+ hwif->dma_start = &auide_dma_start;
+ hwif->ide_dma_end = &auide_dma_end;
+ hwif->dma_setup = &auide_dma_setup;
+ hwif->ide_dma_test_irq = &auide_dma_test_irq;
+ hwif->ide_dma_host_off = &auide_dma_host_off;
+ hwif->ide_dma_host_on = &auide_dma_host_on;
+ hwif->ide_dma_lostirq = &auide_dma_lostirq;
+ hwif->ide_dma_on = &auide_dma_on;
+
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[1].autodma = hwif->autodma;
+ hwif->atapi_dma = 1;
+ hwif->drives[0].using_dma = 1;
+ hwif->drives[1].using_dma = 1;
+#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+ hwif->autodma = 0;
+ hwif->channel = 0;
+ hwif->hold = 1;
+ hwif->select_data = 0; /* no chipset-specific code */
+ hwif->config_data = 0; /* no chipset-specific code */
+
+ hwif->drives[0].autodma = 0;
+ hwif->drives[0].drive_data = 0; /* no drive data */
+ hwif->drives[0].using_dma = 0;
+ hwif->drives[0].waiting_for_dma = 0;
+ hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */
+ /* secondary hdd not supported */
+ hwif->drives[1].autodma = 0;
+
+ hwif->drives[1].drive_data = 0;
+ hwif->drives[1].using_dma = 0;
+ hwif->drives[1].waiting_for_dma = 0;
+ hwif->drives[1].autotune = 2; /* 1=autotune, 2=noautotune, 0=default */
+#endif
+ hwif->drives[0].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+ hwif->drives[1].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+
+ /*Register Driver with PM Framework*/
+#ifdef CONFIG_PM
+ auide_hwif.pm.lock = SPIN_LOCK_UNLOCKED;
+ auide_hwif.pm.stopped = 0;
+
+ auide_hwif.pm.dev = new_au1xxx_power_device( "ide",
+ &au1200ide_pm_callback,
+ NULL);
+ if ( auide_hwif.pm.dev == NULL )
+ printk(KERN_INFO "Unable to create a power management \
+ device entry for the au1200-IDE.\n");
+ else
+ printk(KERN_INFO "Power management device entry for the \
+ au1200-IDE loaded.\n");
+#endif
+
+ auide_hwif.hwif = hwif;
+ hwif->hwif_data = &auide_hwif;
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ auide_ddma_init(&auide_hwif);
+ dbdma_init_done = 1;
+#endif
+
+ probe_hwif_init(hwif);
+ dev_set_drvdata(dev, hwif);
+
+ printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
+
+out:
+ return ret;
+}
+
+static int au_ide_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res;
+ ide_hwif_t *hwif = dev_get_drvdata(dev);
+ _auide_hwif *ahwif = &auide_hwif;
+
+ ide_unregister(hwif - ide_hwifs);
+
+ iounmap((void *)ahwif->regbase);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start);
+
+ return 0;
+}
+
+static struct device_driver au1200_ide_driver = {
+ .name = "au1200-ide",
+ .bus = &platform_bus_type,
+ .probe = au_ide_probe,
+ .remove = au_ide_remove,
+};
+
+static int __init au_ide_init(void)
+{
+ return driver_register(&au1200_ide_driver);
+}
+
+static void __init au_ide_exit(void)
+{
+ driver_unregister(&au1200_ide_driver);
+}
+
+#ifdef CONFIG_PM
+int au1200ide_pm_callback( au1xxx_power_dev_t *dev,\
+ au1xxx_request_t request, void *data) {
+
+ unsigned int d, err = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(auide_hwif.pm.lock, flags);
+
+ switch (request){
+ case AU1XXX_PM_SLEEP:
+ err = au1xxxide_pm_sleep(dev);
+ break;
+ case AU1XXX_PM_WAKEUP:
+ d = *((unsigned int*)data);
+ if ( d > 0 && d <= 99) {
+ err = au1xxxide_pm_standby(dev);
+ }
+ else {
+ err = au1xxxide_pm_resume(dev);
+ }
+ break;
+ case AU1XXX_PM_GETSTATUS:
+ err = au1xxxide_pm_getstatus(dev);
+ break;
+ case AU1XXX_PM_ACCESS:
+ err = au1xxxide_pm_access(dev);
+ break;
+ case AU1XXX_PM_IDLE:
+ err = au1xxxide_pm_idle(dev);
+ break;
+ case AU1XXX_PM_CLEANUP:
+ err = au1xxxide_pm_cleanup(dev);
+ break;
+ default:
+ err = -1;
+ break;
+ }
+
+ spin_unlock_irqrestore(auide_hwif.pm.lock, flags);
+
+ return err;
+}
+
+static int au1xxxide_pm_standby( au1xxx_power_dev_t *dev ) {
+ return 0;
+}
+
+static int au1xxxide_pm_sleep( au1xxx_power_dev_t *dev ) {
+
+ int retval;
+ ide_hwif_t *hwif = auide_hwif.hwif;
+ struct request rq;
+ struct request_pm_state rqpm;
+ ide_task_t args;
+
+ if(auide_hwif.pm.stopped)
+ return -1;
+
+ /*
+ * wait until hard disc is ready
+ */
+ if ( wait_for_ready(&hwif->drives[0], 35000) ) {
+ printk("Wait for drive sleep timeout!\n");
+ retval = -1;
+ }
+
+ /*
+ * sequenz to tell the high level ide driver that pm is resuming
+ */
+ memset(&rq, 0, sizeof(rq));
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq.flags = REQ_PM_SUSPEND;
+ rq.special = &args;
+ rq.pm = &rqpm;
+ rqpm.pm_step = ide_pm_state_start_suspend;
+ rqpm.pm_state = PMSG_SUSPEND;
+
+ retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_wait);
+
+ if (wait_for_ready (&hwif->drives[0], 35000)) {
+ printk("Wait for drive sleep timeout!\n");
+ retval = -1;
+ }
+
+ /*
+ * stop dbdma channels
+ */
+ au1xxx_dbdma_reset(auide_hwif.tx_chan);
+ au1xxx_dbdma_reset(auide_hwif.rx_chan);
+
+ auide_hwif.pm.stopped = 1;
+
+ return retval;
+}
+
+static int au1xxxide_pm_resume( au1xxx_power_dev_t *dev ) {
+
+ int retval;
+ ide_hwif_t *hwif = auide_hwif.hwif;
+ struct request rq;
+ struct request_pm_state rqpm;
+ ide_task_t args;
+
+ if(!auide_hwif.pm.stopped)
+ return -1;
+
+ /*
+ * start dbdma channels
+ */
+ au1xxx_dbdma_start(auide_hwif.tx_chan);
+ au1xxx_dbdma_start(auide_hwif.rx_chan);
+
+ /*
+ * wait until hard disc is ready
+ */
+ if (wait_for_ready ( &hwif->drives[0], 35000)) {
+ printk("Wait for drive wake up timeout!\n");
+ retval = -1;
+ }
+
+ /*
+ * sequenz to tell the high level ide driver that pm is resuming
+ */
+ memset(&rq, 0, sizeof(rq));
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq.flags = REQ_PM_RESUME;
+ rq.special = &args;
+ rq.pm = &rqpm;
+ rqpm.pm_step = ide_pm_state_start_resume;
+ rqpm.pm_state = PMSG_ON;
+
+ retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_head_wait);
+
+ /*
+ * wait for hard disc
+ */
+ if ( wait_for_ready(&hwif->drives[0], 35000) ) {
+ printk("Wait for drive wake up timeout!\n");
+ retval = -1;
+ }
+
+ auide_hwif.pm.stopped = 0;
+
+ return retval;
+}
+
+static int au1xxxide_pm_getstatus( au1xxx_power_dev_t *dev ) {
+ return dev->cur_state;
+}
+
+static int au1xxxide_pm_access( au1xxx_power_dev_t *dev ) {
+ if (dev->cur_state != AWAKE_STATE)
+ return 0;
+ else
+ return -1;
+}
+
+static int au1xxxide_pm_idle( au1xxx_power_dev_t *dev ) {
+ return 0;
+}
+
+static int au1xxxide_pm_cleanup( au1xxx_power_dev_t *dev ) {
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AU1200 IDE driver");
+
+module_init(au_ide_init);
+module_exit(au_ide_exit);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3de9ab897e42..3d9c7afc8695 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -608,7 +608,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
#ifdef __i386__
if (dev->resource[PCI_ROM_RESOURCE].start) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
#endif
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index da46577380f3..6e3ab0c38c4d 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -173,6 +173,12 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
+ },{ /* 14 */
+ .name = "Revolution",
+ .init_hwif = init_hwif_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = OFF_BOARD,
}
};
@@ -231,6 +237,7 @@ static struct pci_device_id generic_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
+ { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
/* Must come last. If you add entries adjust this table appropriately and the init_one code */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
{ 0, },
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index bbde46279984..be334da7a754 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -173,7 +173,7 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
if (cmd & PCI_COMMAND_MEMORY) {
if (pci_resource_start(dev, PCI_ROM_RESOURCE)) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n",
dev->resource[PCI_ROM_RESOURCE].start);
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 7b64db10d1b0..127619a109ed 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1334,9 +1334,13 @@ static int __devinit init_hpt366(struct pci_dev *dev)
static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{
int ret = 0;
- /* FIXME: Not portable */
+
+ /*
+ * FIXME: Not portable. Also, why do we enable the ROM in the first place?
+ * We don't seem to be using it.
+ */
if (dev->resource[PCI_ROM_RESOURCE].start)
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 10592cec6c43..24e21b2838c1 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -350,9 +350,9 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
{
ide_hwif_t *hwif = NULL;
- printk("SC1200: suspend(%u)\n", state);
+ printk("SC1200: suspend(%u)\n", state.event);
- if (state == 0) {
+ if (state.event == PM_EVENT_ON) {
// we only save state when going from full power to less
//
@@ -386,8 +386,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
/* You don't need to iterate over disks -- sysfs should have done that for you already */
pci_disable_device(dev);
- pci_set_power_state(dev,state);
- dev->current_state = state;
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ dev->current_state = state.event;
return 0;
}
@@ -396,8 +396,8 @@ static int sc1200_resume (struct pci_dev *dev)
ide_hwif_t *hwif = NULL;
printk("SC1200: resume\n");
- pci_set_power_state(dev,0); // bring chip back from sleep state
- dev->current_state = 0;
+ pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state
+ dev->current_state = PM_EVENT_ON;
pci_enable_device(dev);
//
// loop over all interfaces that are part of this pci device:
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index c6f5fa4b4ca6..ff2e217a8c84 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -21,6 +21,9 @@
*
* CSB6: `Champion South Bridge' IDE Interface (optional: third channel)
*
+ * HT1000: AKA BCM5785 - Hypertransport Southbridge for Opteron systems. IDE
+ * controller same as the CSB6. Single channel ATA100 only.
+ *
* Documentation:
* Available under NDA only. Errata info very hard to get.
*
@@ -71,6 +74,8 @@ static u8 svwks_ratemask (ide_drive_t *drive)
if (!svwks_revision)
pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
+ if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
+ return 2;
if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
u32 reg = 0;
if (isa_dev)
@@ -109,6 +114,7 @@ static u8 svwks_csb_check (struct pci_dev *dev)
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+ case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
return 1;
default:
break;
@@ -438,6 +444,13 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
pci_write_config_byte(dev, 0x5A, btr);
}
+ /* Setup HT1000 SouthBridge Controller - Single Channel Only */
+ else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) {
+ pci_read_config_byte(dev, 0x5A, &btr);
+ btr &= ~0x40;
+ btr |= 0x3;
+ pci_write_config_byte(dev, 0x5A, btr);
+ }
return (dev->irq) ? dev->irq : 0;
}
@@ -629,6 +642,15 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
.channels = 1, /* 2 */
.autodma = AUTODMA,
.bootable = ON_BOARD,
+ },{ /* 4 */
+ .name = "SvrWks HT1000",
+ .init_setup = init_setup_svwks,
+ .init_chipset = init_chipset_svwks,
+ .init_hwif = init_hwif_svwks,
+ .init_dma = init_dma_svwks,
+ .channels = 1, /* 2 */
+ .autodma = AUTODMA,
+ .bootable = ON_BOARD,
}
};
@@ -653,6 +675,7 @@ static struct pci_device_id svwks_pci_tbl[] = {
{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index be0fcc8f4b15..d8c3d8ebad30 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -81,7 +81,7 @@ typedef struct pmac_ide_hwif {
} pmac_ide_hwif_t;
-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS] __pmacdata;
+static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
static int pmac_ide_count;
enum {
@@ -242,7 +242,7 @@ struct mdma_timings_t {
int cycleTime;
};
-struct mdma_timings_t mdma_timings_33[] __pmacdata =
+struct mdma_timings_t mdma_timings_33[] =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
@@ -255,7 +255,7 @@ struct mdma_timings_t mdma_timings_33[] __pmacdata =
{ 0, 0, 0 }
};
-struct mdma_timings_t mdma_timings_33k[] __pmacdata =
+struct mdma_timings_t mdma_timings_33k[] =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
@@ -268,7 +268,7 @@ struct mdma_timings_t mdma_timings_33k[] __pmacdata =
{ 0, 0, 0 }
};
-struct mdma_timings_t mdma_timings_66[] __pmacdata =
+struct mdma_timings_t mdma_timings_66[] =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
@@ -286,7 +286,7 @@ struct {
int addrSetup; /* ??? */
int rdy2pause;
int wrDataSetup;
-} kl66_udma_timings[] __pmacdata =
+} kl66_udma_timings[] =
{
{ 0, 180, 120 }, /* Mode 0 */
{ 0, 150, 90 }, /* 1 */
@@ -301,7 +301,7 @@ struct kauai_timing {
u32 timing_reg;
};
-static struct kauai_timing kauai_pio_timings[] __pmacdata =
+static struct kauai_timing kauai_pio_timings[] =
{
{ 930 , 0x08000fff },
{ 600 , 0x08000a92 },
@@ -316,7 +316,7 @@ static struct kauai_timing kauai_pio_timings[] __pmacdata =
{ 120 , 0x04000148 }
};
-static struct kauai_timing kauai_mdma_timings[] __pmacdata =
+static struct kauai_timing kauai_mdma_timings[] =
{
{ 1260 , 0x00fff000 },
{ 480 , 0x00618000 },
@@ -330,7 +330,7 @@ static struct kauai_timing kauai_mdma_timings[] __pmacdata =
{ 0 , 0 },
};
-static struct kauai_timing kauai_udma_timings[] __pmacdata =
+static struct kauai_timing kauai_udma_timings[] =
{
{ 120 , 0x000070c0 },
{ 90 , 0x00005d80 },
@@ -341,7 +341,7 @@ static struct kauai_timing kauai_udma_timings[] __pmacdata =
{ 0 , 0 },
};
-static struct kauai_timing shasta_pio_timings[] __pmacdata =
+static struct kauai_timing shasta_pio_timings[] =
{
{ 930 , 0x08000fff },
{ 600 , 0x0A000c97 },
@@ -356,7 +356,7 @@ static struct kauai_timing shasta_pio_timings[] __pmacdata =
{ 120 , 0x0400010a }
};
-static struct kauai_timing shasta_mdma_timings[] __pmacdata =
+static struct kauai_timing shasta_mdma_timings[] =
{
{ 1260 , 0x00fff000 },
{ 480 , 0x00820800 },
@@ -370,7 +370,7 @@ static struct kauai_timing shasta_mdma_timings[] __pmacdata =
{ 0 , 0 },
};
-static struct kauai_timing shasta_udma133_timings[] __pmacdata =
+static struct kauai_timing shasta_udma133_timings[] =
{
{ 120 , 0x00035901, },
{ 90 , 0x000348b1, },
@@ -522,7 +522,7 @@ pmu_hd_blink_init(void)
* N.B. this can't be an initfunc, because the media-bay task can
* call ide_[un]register at any time.
*/
-void __pmac
+void
pmac_ide_init_hwif_ports(hw_regs_t *hw,
unsigned long data_port, unsigned long ctrl_port,
int *irq)
@@ -559,7 +559,7 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
* timing register when selecting that unit. This version is for
* ASICs with a single timing register
*/
-static void __pmac
+static void
pmac_ide_selectproc(ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -579,7 +579,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
* timing register when selecting that unit. This version is for
* ASICs with a dual timing register (Kauai)
*/
-static void __pmac
+static void
pmac_ide_kauai_selectproc(ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -600,7 +600,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
/*
* Force an update of controller timing values for a given drive
*/
-static void __pmac
+static void
pmac_ide_do_update_timings(ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -633,7 +633,7 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
* to sort that out sooner or later and see if I can finally get the
* common version to work properly in all cases
*/
-static int __pmac
+static int
pmac_ide_do_setfeature(ide_drive_t *drive, u8 command)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -710,7 +710,7 @@ out:
/*
* Old tuning functions (called on hdparm -p), sets up drive PIO timings
*/
-static void __pmac
+static void
pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
{
ide_pio_data_t d;
@@ -801,7 +801,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
/*
* Calculate KeyLargo ATA/66 UDMA timings
*/
-static int __pmac
+static int
set_timings_udma_ata4(u32 *timings, u8 speed)
{
unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
@@ -829,7 +829,7 @@ set_timings_udma_ata4(u32 *timings, u8 speed)
/*
* Calculate Kauai ATA/100 UDMA timings
*/
-static int __pmac
+static int
set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
{
struct ide_timing *t = ide_timing_find_mode(speed);
@@ -849,7 +849,7 @@ set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
/*
* Calculate Shasta ATA/133 UDMA timings
*/
-static int __pmac
+static int
set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
{
struct ide_timing *t = ide_timing_find_mode(speed);
@@ -869,7 +869,7 @@ set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
/*
* Calculate MDMA timings for all cells
*/
-static int __pmac
+static int
set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
u8 speed, int drive_cycle_time)
{
@@ -1014,7 +1014,7 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
* our dedicated function is more precise as it uses the drive provided
* cycle time value. We should probably fix this one to deal with that too...
*/
-static int __pmac
+static int
pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
{
int unit = (drive->select.b.unit & 0x01);
@@ -1092,7 +1092,7 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
* Blast some well known "safe" values to the timing registers at init or
* wakeup from sleep time, before we do real calculation
*/
-static void __pmac
+static void
sanitize_timings(pmac_ide_hwif_t *pmif)
{
unsigned int value, value2 = 0;
@@ -1123,13 +1123,13 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
pmif->timings[2] = pmif->timings[3] = value2;
}
-unsigned long __pmac
+unsigned long
pmac_ide_get_base(int index)
{
return pmac_ide[index].regbase;
}
-int __pmac
+int
pmac_ide_check_base(unsigned long base)
{
int ix;
@@ -1140,7 +1140,7 @@ pmac_ide_check_base(unsigned long base)
return -1;
}
-int __pmac
+int
pmac_ide_get_irq(unsigned long base)
{
int ix;
@@ -1151,7 +1151,7 @@ pmac_ide_get_irq(unsigned long base)
return 0;
}
-static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
dev_t __init
pmac_find_ide_boot(char *bootdevice, int n)
@@ -1504,12 +1504,12 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
}
static int
-pmac_ide_macio_suspend(struct macio_dev *mdev, u32 state)
+pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t state)
{
ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
int rc = 0;
- if (state != mdev->ofdev.dev.power.power_state && state >= 2) {
+ if (state.event != mdev->ofdev.dev.power.power_state.event && state.event >= PM_EVENT_SUSPEND) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = state;
@@ -1524,10 +1524,10 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
int rc = 0;
- if (mdev->ofdev.dev.power.power_state != 0) {
+ if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
rc = pmac_ide_do_resume(hwif);
if (rc == 0)
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state = PMSG_ON;
}
return rc;
@@ -1608,12 +1608,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
}
static int
-pmac_ide_pci_suspend(struct pci_dev *pdev, u32 state)
+pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
int rc = 0;
- if (state != pdev->dev.power.power_state && state >= 2) {
+ if (state.event != pdev->dev.power.power_state.event && state.event >= 2) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
pdev->dev.power.power_state = state;
@@ -1628,10 +1628,10 @@ pmac_ide_pci_resume(struct pci_dev *pdev)
ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
int rc = 0;
- if (pdev->dev.power.power_state != 0) {
+ if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
rc = pmac_ide_do_resume(hwif);
if (rc == 0)
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
}
return rc;
@@ -1664,7 +1664,7 @@ static struct macio_driver pmac_ide_macio_driver =
};
static struct pci_device_id pmac_ide_pci_match[] = {
- { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA,
@@ -1701,7 +1701,7 @@ pmac_ide_probe(void)
* pmac_ide_build_dmatable builds the DBDMA command list
* for a transfer and sets the DBDMA channel to point to it.
*/
-static int __pmac
+static int
pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
{
struct dbdma_cmd *table;
@@ -1785,7 +1785,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
}
/* Teardown mappings after DMA has completed. */
-static void __pmac
+static void
pmac_ide_destroy_dmatable (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
@@ -1802,7 +1802,7 @@ pmac_ide_destroy_dmatable (ide_drive_t *drive)
/*
* Pick up best MDMA timing for the drive and apply it
*/
-static int __pmac
+static int
pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -1859,7 +1859,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode)
/*
* Pick up best UDMA timing for the drive and apply it
*/
-static int __pmac
+static int
pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -1915,7 +1915,7 @@ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
* Check what is the best DMA timing setting for the drive and
* call appropriate functions to apply it.
*/
-static int __pmac
+static int
pmac_ide_dma_check(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -1967,7 +1967,7 @@ pmac_ide_dma_check(ide_drive_t *drive)
* 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
*/
-static int __pmac
+static int
pmac_ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -1997,7 +1997,7 @@ pmac_ide_dma_setup(ide_drive_t *drive)
return 0;
}
-static void __pmac
+static void
pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
{
/* issue cmd to drive */
@@ -2008,7 +2008,7 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
* Kick the DMA controller into life after the DMA command has been issued
* to the drive.
*/
-static void __pmac
+static void
pmac_ide_dma_start(ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2024,7 +2024,7 @@ pmac_ide_dma_start(ide_drive_t *drive)
/*
* After a DMA transfer, make sure the controller is stopped
*/
-static int __pmac
+static int
pmac_ide_dma_end (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2052,7 +2052,7 @@ pmac_ide_dma_end (ide_drive_t *drive)
* that's not implemented yet), on the other hand, we don't have shared interrupts
* so it's not really a problem
*/
-static int __pmac
+static int
pmac_ide_dma_test_irq (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2108,19 +2108,19 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
return 1;
}
-static int __pmac
+static int
pmac_ide_dma_host_off (ide_drive_t *drive)
{
return 0;
}
-static int __pmac
+static int
pmac_ide_dma_host_on (ide_drive_t *drive)
{
return 0;
}
-static int __pmac
+static int
pmac_ide_dma_lostirq (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 77da827b2898..18ed7765417c 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -229,6 +229,7 @@ second_chance_to_dma:
case PCI_DEVICE_ID_AMD_VIPER_7409:
case PCI_DEVICE_ID_CMD_643:
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+ case PCI_DEVICE_ID_REVOLUTION:
simplex_stat = hwif->INB(dma_base + 2);
hwif->OUTB((simplex_stat&0x60),(dma_base + 2));
simplex_stat = hwif->INB(dma_base + 2);
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 84ae027b021a..e8e28569a668 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -1297,4 +1297,3 @@ static void __exit amdtp_exit_module (void)
module_init(amdtp_init_module);
module_exit(amdtp_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16);
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index e6734263a1d3..28c5f4b726e2 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -37,7 +37,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 4538b0235ca3..cbbbe14b8849 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_device_create(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id);
devfs_mk_dir("ieee1394/dv/host%d", id);
@@ -2660,4 +2660,3 @@ static int __init dv1394_init_module(void)
module_init(dv1394_init_module);
module_exit(dv1394_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index cd53c174ced1..c9e92d85c893 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -89,7 +89,7 @@
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
- "$Rev: 1264 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1312 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
@@ -221,9 +221,7 @@ static int ether1394_open (struct net_device *dev)
if (priv->bc_state == ETHER1394_BC_ERROR) {
/* we'll try again */
priv->iso = hpsb_iso_recv_init(priv->host,
- ETHER1394_GASP_BUFFERS * 2 *
- (1 << (priv->host->csr.max_rec +
- 1)),
+ ETHER1394_ISO_BUF_SIZE,
ETHER1394_GASP_BUFFERS,
priv->broadcast_channel,
HPSB_ISO_DMA_PACKET_PER_BUFFER,
@@ -635,8 +633,8 @@ static void ether1394_add_host (struct hpsb_host *host)
* be checked when the eth device is opened. */
priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
- priv->iso = hpsb_iso_recv_init(host, (ETHER1394_GASP_BUFFERS * 2 *
- (1 << (host->csr.max_rec + 1))),
+ priv->iso = hpsb_iso_recv_init(host,
+ ETHER1394_ISO_BUF_SIZE,
ETHER1394_GASP_BUFFERS,
priv->broadcast_channel,
HPSB_ISO_DMA_PACKET_PER_BUFFER,
@@ -1632,7 +1630,7 @@ static void ether1394_complete_cb(void *__ptask)
/* Transmit a packet (called by kernel) */
static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
{
- int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+ gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct eth1394hdr *eth;
struct eth1394_priv *priv = netdev_priv(dev);
int proto;
@@ -1770,7 +1768,7 @@ fail:
static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
strcpy (info->driver, driver_name);
- strcpy (info->version, "$Rev: 1264 $");
+ strcpy (info->version, "$Rev: 1312 $");
/* FIXME XXX provide sane businfo */
strcpy (info->bus_info, "ieee1394");
}
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
index ed8f1c4b7fd8..a77213cfc483 100644
--- a/drivers/ieee1394/eth1394.h
+++ b/drivers/ieee1394/eth1394.h
@@ -44,6 +44,12 @@
#define ETHER1394_GASP_BUFFERS 16
+/* rawiso buffer size - due to a limitation in rawiso, we must limit each
+ * GASP buffer to be less than PAGE_SIZE. */
+#define ETHER1394_ISO_BUF_SIZE ETHER1394_GASP_BUFFERS * \
+ min((unsigned int)PAGE_SIZE, \
+ 2 * (1U << (priv->host->csr.max_rec + 1)))
+
/* Node set == 64 */
#define NODE_SET (ALL_NODES + 1)
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index c502c6e9c440..aeeaeb670d03 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/timer.h>
+#include <linux/jiffies.h>
#include "csr1212.h"
#include "ieee1394.h"
@@ -217,7 +218,7 @@ int hpsb_update_config_rom_image(struct hpsb_host *host)
/* IEEE 1394a-2000 prohibits using the same generation number
* twice in a 60 second period. */
- if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
+ if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
/* Wait 60 seconds from the last time this generation number was
* used. */
reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index 739e76840d51..38f42112dff0 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -135,17 +135,17 @@ enum isoctl_cmd {
enum reset_types {
/* 166 microsecond reset -- only type of reset available on
- non-1394a capable IEEE 1394 controllers */
+ non-1394a capable controllers */
LONG_RESET,
/* Short (arbitrated) reset -- only available on 1394a capable
- IEEE 1394 capable controllers */
+ controllers */
SHORT_RESET,
- /* Variants, that set force_root before issueing the bus reset */
+ /* Variants that set force_root before issueing the bus reset */
LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
- /* Variants, that clear force_root before issueing the bus reset */
+ /* Variants that clear force_root before issueing the bus reset */
LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT
};
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index b248d89de8b4..32a1e016c85e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -70,7 +70,7 @@ const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S32
struct class *hpsb_protocol_class;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-static void dump_packet(const char *text, quadlet_t *data, int size)
+static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
{
int i;
@@ -78,12 +78,15 @@ static void dump_packet(const char *text, quadlet_t *data, int size)
size = (size > 4 ? 4 : size);
printk(KERN_DEBUG "ieee1394: %s", text);
+ if (speed > -1 && speed < 6)
+ printk(" at %s", hpsb_speedto_str[speed]);
+ printk(":");
for (i = 0; i < size; i++)
printk(" %08x", data[i]);
printk("\n");
}
#else
-#define dump_packet(x,y,z)
+#define dump_packet(a,b,c,d)
#endif
static void abort_requests(struct hpsb_host *host);
@@ -544,8 +547,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (packet->data_size)
memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
- dump_packet("send packet local:", packet->header,
- packet->header_size);
+ dump_packet("send packet local", packet->header, packet->header_size, -1);
hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
hpsb_packet_received(host, data, size, 0);
@@ -561,21 +563,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
+ NODEID_TO_NODE(packet->node_id)];
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- switch (packet->speed_code) {
- case 2:
- dump_packet("send packet 400:", packet->header,
- packet->header_size);
- break;
- case 1:
- dump_packet("send packet 200:", packet->header,
- packet->header_size);
- break;
- default:
- dump_packet("send packet 100:", packet->header,
- packet->header_size);
- }
-#endif
+ dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
return host->driver->transmit_packet(host, packet);
}
@@ -636,7 +624,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
if (packet == NULL) {
HPSB_DEBUG("unsolicited response packet received - no tlabel match");
- dump_packet("contents:", data, 16);
+ dump_packet("contents", data, 16, -1);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
return;
}
@@ -677,11 +665,11 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
if (!tcode_match) {
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
HPSB_INFO("unsolicited response packet received - tcode mismatch");
- dump_packet("contents:", data, 16);
+ dump_packet("contents", data, 16, -1);
return;
}
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &host->pending_packet_queue);
if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
@@ -914,7 +902,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
return;
}
- dump_packet("received packet:", data, size);
+ dump_packet("received packet", data, size, -1);
tcode = (data[0] >> 4) & 0xf;
@@ -989,7 +977,7 @@ void abort_timedouts(unsigned long __opaque)
packet = (struct hpsb_packet *)skb->data;
if (time_before(packet->sendtime + expire, jiffies)) {
- __skb_unlink(skb, skb->list);
+ __skb_unlink(skb, &host->pending_packet_queue);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
queue_packet_complete(packet);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index bebcc47ab06c..7fff5a1d2ea4 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -64,10 +64,10 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
int i, ret = 0;
- for (i = 0; i < 3; i++) {
+ for (i = 1; ; i++) {
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
buffer, length);
- if (!ret)
+ if (!ret || i == 3)
break;
if (msleep_interruptible(334))
@@ -1068,6 +1068,8 @@ static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
struct unit_directory *ud;
int i = 0;
int length = 0;
+ /* ieee1394:venNmoNspNverN */
+ char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
if (!cdev)
return -ENODEV;
@@ -1094,6 +1096,12 @@ do { \
PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);
PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);
PUT_ENVP("VERSION=%06x", ud->version);
+ snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
+ ud->vendor_id,
+ ud->model_id,
+ ud->specifier_id,
+ ud->version);
+ PUT_ENVP("MODALIAS=%s", buf);
#undef PUT_ENVP
@@ -1284,7 +1292,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->device.driver &&
(!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
+ ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
device_release_driver(&ud->device);
}
up_write(&ne->device.bus->subsys.rwsem);
@@ -1307,7 +1315,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
continue;
if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device, 0);
+ ud->device.driver->resume(&ud->device);
}
up_read(&ne->device.bus->subsys.rwsem);
@@ -1430,9 +1438,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
if (host->busmgr_id == 0xffff && host->node_count > 1)
{
u16 root_node = host->node_count - 1;
- struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS);
- if (ne && ne->busopt.cmc)
+ /* get cycle master capability flag from root node */
+ if (host->is_cycmst ||
+ (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host),
+ (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)),
+ &bc, sizeof(quadlet_t)) &&
+ be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT))
hpsb_send_phy_config(host, root_node, -1);
else {
HPSB_DEBUG("The root node is not cycle master capable; "
@@ -1549,24 +1561,19 @@ static int nodemgr_host_thread(void *__hi)
}
}
- if (!nodemgr_check_irm_capability(host, reset_cycles)) {
+ if (!nodemgr_check_irm_capability(host, reset_cycles) ||
+ !nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
up(&nodemgr_serialize);
continue;
}
+ reset_cycles = 0;
/* Scan our nodes to get the bus options and create node
* entries. This does not do the sysfs stuff, since that
* would trigger hotplug callbacks and such, which is a
* bad idea at this point. */
nodemgr_node_scan(hi, generation);
- if (!nodemgr_do_irm_duties(host, reset_cycles)) {
- reset_cycles++;
- up(&nodemgr_serialize);
- continue;
- }
-
- reset_cycles = 0;
/* This actually does the full probe, with sysfs
* registration. */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index b12a970cc9a3..4cf9b8f3e336 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
static char version[] __devinitdata =
- "$Rev: 1299 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1313 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
@@ -478,7 +478,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
int num_ports, i;
spin_lock_init(&ohci->phy_reg_lock);
- spin_lock_init(&ohci->event_lock);
/* Put some defaults to these undefined bus options */
buf = reg_read(ohci, OHCI1394_BusOptions);
@@ -1085,7 +1084,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
if (printk_ratelimit())
- PRINT(KERN_ERR, "IR legacy activated");
+ DBGMSG("IR legacy activated");
}
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
@@ -2284,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
{
struct ohci1394_iso_tasklet *t;
unsigned long mask;
+ unsigned long flags;
- spin_lock(&ohci->iso_tasklet_list_lock);
+ spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
mask = 1 << t->context;
@@ -2296,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
tasklet_schedule(&t->tasklet);
}
- spin_unlock(&ohci->iso_tasklet_list_lock);
-
+ spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
}
static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
@@ -3402,7 +3401,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
/* We hopefully don't have to pre-allocate IT DMA like we did
* for IR DMA above. Allocate it on-demand and mark inactive. */
ohci->it_legacy_context.ohci = NULL;
+ spin_lock_init(&ohci->event_lock);
+ /*
+ * interrupts are disabled, all right, but... due to SA_SHIRQ we
+ * might get called anyway. We'll see no event, of course, but
+ * we need to get to that "no event", so enough should be initialized
+ * by that point.
+ */
if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
OHCI1394_DRIVER_NAME, ohci))
FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq);
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 36074e6eeebb..6b1ab875333b 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1464,26 +1464,6 @@ static int __devinit add_card(struct pci_dev *dev,
{ 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
};
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- union i2c_smbus_data data;
-
- if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
- PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
- else
- {
- u16 addr;
- for (addr=0x00; addr < 0x100; addr++) {
- if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
- PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
- break;
- }
- else
- PRINT(KERN_DEBUG, lynx->id,"got serial eeprom data at %x: %x",addr, data.byte);
- }
- }
-#endif
-
/* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
do it more efficiently in one transaction rather then using several reads */
if (i2c_transfer(i2c_ad, msg, 2) < 0) {
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index b4fa14793fe5..24411e666b21 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,7 +98,7 @@ static struct hpsb_address_ops arm_ops = {
static void queue_complete_cb(struct pending_request *req);
-static struct pending_request *__alloc_pending_request(unsigned int __nocast flags)
+static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
@@ -412,6 +412,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
static ssize_t raw1394_read(struct file *file, char __user * buffer,
size_t count, loff_t * offset_is_ignored)
{
+ unsigned long flags;
struct file_info *fi = (struct file_info *)file->private_data;
struct list_head *lh;
struct pending_request *req;
@@ -435,10 +436,10 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer,
}
}
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
lh = fi->req_complete.next;
list_del(lh);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
req = list_entry(lh, struct pending_request, list);
@@ -486,6 +487,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
static int state_initialized(struct file_info *fi, struct pending_request *req)
{
+ unsigned long flags;
struct host_info *hi;
struct raw1394_khost_list *khl;
@@ -499,7 +501,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
switch (req->req.type) {
case RAW1394_REQ_LIST_CARDS:
- spin_lock_irq(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, flags);
khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
SLAB_ATOMIC);
@@ -513,7 +515,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
khl++;
}
}
- spin_unlock_irq(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, flags);
if (khl != NULL) {
req->req.error = RAW1394_ERROR_NONE;
@@ -528,7 +530,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
break;
case RAW1394_REQ_SET_CARD:
- spin_lock_irq(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, flags);
if (req->req.misc < host_count) {
list_for_each_entry(hi, &host_info_list, list) {
if (!req->req.misc--)
@@ -550,7 +552,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
} else {
req->req.error = RAW1394_ERROR_INVALID_ARG;
}
- spin_unlock_irq(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, flags);
req->req.length = 0;
break;
@@ -569,7 +571,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
{
int channel = req->req.misc;
- spin_lock_irq(&host_info_lock);
if ((channel > 63) || (channel < -64)) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
} else if (channel >= 0) {
@@ -601,7 +602,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
- spin_unlock_irq(&host_info_lock);
}
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -627,6 +627,7 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
static int handle_async_request(struct file_info *fi,
struct pending_request *req, int node)
{
+ unsigned long flags;
struct hpsb_packet *packet = NULL;
u64 addr = req->req.address & 0xffffffffffffULL;
@@ -761,9 +762,9 @@ static int handle_async_request(struct file_info *fi,
hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req);
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
packet->generation = req->req.generation;
@@ -779,6 +780,7 @@ static int handle_async_request(struct file_info *fi,
static int handle_iso_send(struct file_info *fi, struct pending_request *req,
int channel)
{
+ unsigned long flags;
struct hpsb_packet *packet;
packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
@@ -804,9 +806,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
(void (*)(void *))queue_complete_req,
req);
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
@@ -821,6 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
static int handle_async_send(struct file_info *fi, struct pending_request *req)
{
+ unsigned long flags;
struct hpsb_packet *packet;
int header_length = req->req.misc & 0xffff;
int expect_response = req->req.misc >> 16;
@@ -867,9 +870,9 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req);
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
@@ -885,6 +888,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
u64 addr, size_t length, u16 flags)
{
+ unsigned long irqflags;
struct pending_request *req;
struct host_info *hi;
struct file_info *fi = NULL;
@@ -899,7 +903,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
"addr: %4.4x %8.8x length: %Zu", nodeid,
(u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
length);
- spin_lock(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -924,7 +928,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
if (!found) {
printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
" -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR);
} else {
DBGMSG("arm_read addr_entry FOUND");
@@ -954,7 +958,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) {
DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
}
@@ -974,7 +978,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
if (!(req->data)) {
free_pending_request(req);
DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
}
@@ -1031,13 +1035,14 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
sizeof(struct arm_request));
queue_complete_req(req);
}
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode);
}
static int arm_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t * data, u64 addr, size_t length, u16 flags)
{
+ unsigned long irqflags;
struct pending_request *req;
struct host_info *hi;
struct file_info *fi = NULL;
@@ -1052,7 +1057,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
"addr: %4.4x %8.8x length: %Zu", nodeid,
(u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
length);
- spin_lock(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -1077,7 +1082,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
if (!found) {
printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
" -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR);
} else {
DBGMSG("arm_write addr_entry FOUND");
@@ -1106,7 +1111,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) {
DBGMSG("arm_write -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request my be retried */
}
@@ -1118,7 +1123,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
if (!(req->data)) {
free_pending_request(req);
DBGMSG("arm_write -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
}
@@ -1165,7 +1170,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
sizeof(struct arm_request));
queue_complete_req(req);
}
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode);
}
@@ -1173,6 +1178,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
u16 flags)
{
+ unsigned long irqflags;
struct pending_request *req;
struct host_info *hi;
struct file_info *fi = NULL;
@@ -1198,7 +1204,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
(u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
be32_to_cpu(data), be32_to_cpu(arg));
}
- spin_lock(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -1224,7 +1230,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
if (!found) {
printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
" -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR);
} else {
DBGMSG("arm_lock addr_entry FOUND");
@@ -1307,7 +1313,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) {
DBGMSG("arm_lock -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
}
@@ -1316,7 +1322,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
if (!(req->data)) {
free_pending_request(req);
DBGMSG("arm_lock -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
}
@@ -1382,7 +1388,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
sizeof(struct arm_response) + 2 * sizeof(*store));
queue_complete_req(req);
}
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode);
}
@@ -1390,6 +1396,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags)
{
+ unsigned long irqflags;
struct pending_request *req;
struct host_info *hi;
struct file_info *fi = NULL;
@@ -1422,7 +1429,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
(u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
(u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
}
- spin_lock(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search addressentry in file_info's for host */
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -1449,7 +1456,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
printk(KERN_ERR
"raw1394: arm_lock64 FAILED addr_entry not found"
" -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR);
} else {
DBGMSG("arm_lock64 addr_entry FOUND");
@@ -1533,7 +1540,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
DBGMSG("arm_lock64 -> entering notification-section");
req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) {
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
DBGMSG("arm_lock64 -> rcode_conflict_error");
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
@@ -1542,7 +1549,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
req->data = kmalloc(size, SLAB_ATOMIC);
if (!(req->data)) {
free_pending_request(req);
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
DBGMSG("arm_lock64 -> rcode_conflict_error");
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */
@@ -1609,7 +1616,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
sizeof(struct arm_response) + 2 * sizeof(*store));
queue_complete_req(req);
}
- spin_unlock(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode);
}
@@ -1980,6 +1987,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
struct hpsb_packet *packet = NULL;
int retval = 0;
quadlet_t data;
+ unsigned long flags;
data = be32_to_cpu((u32) req->req.sendb);
DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
@@ -1990,9 +1998,9 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->packet = packet;
hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req);
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
packet->generation = req->req.generation;
retval = hpsb_send_packet(packet);
DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
@@ -2659,14 +2667,15 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
struct file_info *fi = file->private_data;
unsigned int mask = POLLOUT | POLLWRNORM;
+ unsigned long flags;
poll_wait(file, &fi->poll_wait_complete, pt);
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
if (!list_empty(&fi->req_complete)) {
mask |= POLLIN | POLLRDNORM;
}
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
return mask;
}
@@ -2710,6 +2719,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
struct arm_addr *arm_addr = NULL;
int another_host;
int csr_mod = 0;
+ unsigned long flags;
if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi);
@@ -2720,13 +2730,11 @@ static int raw1394_release(struct inode *inode, struct file *file)
}
}
- spin_lock_irq(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, flags);
fi->listen_channels = 0;
- spin_unlock_irq(&host_info_lock);
fail = 0;
/* set address-entries invalid */
- spin_lock_irq(&host_info_lock);
while (!list_empty(&fi->addr_list)) {
another_host = 0;
@@ -2777,14 +2785,14 @@ static int raw1394_release(struct inode *inode, struct file *file)
vfree(addr->addr_space_buffer);
kfree(addr);
} /* while */
- spin_unlock_irq(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, flags);
if (fail > 0) {
printk(KERN_ERR "raw1394: during addr_list-release "
"error(s) occurred \n");
}
while (!done) {
- spin_lock_irq(&fi->reqlists_lock);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
while (!list_empty(&fi->req_complete)) {
lh = fi->req_complete.next;
@@ -2798,7 +2806,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (list_empty(&fi->req_pending))
done = 1;
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
if (!done)
down_interruptible(&fi->complete_sem);
@@ -2828,9 +2836,9 @@ static int raw1394_release(struct inode *inode, struct file *file)
fi->host->id);
if (fi->state == connected) {
- spin_lock_irq(&host_info_lock);
+ spin_lock_irqsave(&host_info_lock, flags);
list_del(&fi->list);
- spin_unlock_irq(&host_info_lock);
+ spin_unlock_irqrestore(&host_info_lock, flags);
put_device(&fi->host->device);
}
@@ -2904,7 +2912,7 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
+ if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
@@ -2958,4 +2966,3 @@ static void __exit cleanup_raw1394(void)
module_init(init_raw1394);
module_exit(cleanup_raw1394);
MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 627af507643a..12cec7c4a342 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -97,16 +97,18 @@ static char version[] __devinitdata =
*/
static int max_speed = IEEE1394_SPEED_MAX;
module_param(max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)");
+MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)");
/*
* Set serialize_io to 1 if you'd like only one scsi command sent
* down to us at a time (debugging). This might be necessary for very
* badly behaved sbp2 devices.
+ *
+ * TODO: Make this configurable per device.
*/
-static int serialize_io;
+static int serialize_io = 1;
module_param(serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)");
+MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)");
/*
* Bump up max_sectors if you'd like to support very large sized
@@ -596,6 +598,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
}
+/*
+ * Is scsi_id valid? Is the 1394 node still present?
+ */
+static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id)
+{
+ return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
+}
+
/*********************************************
@@ -631,11 +641,23 @@ static int sbp2_remove(struct device *dev)
{
struct unit_directory *ud;
struct scsi_id_instance_data *scsi_id;
+ struct scsi_device *sdev;
SBP2_DEBUG("sbp2_remove");
ud = container_of(dev, struct unit_directory, device);
scsi_id = ud->device.driver_data;
+ if (!scsi_id)
+ return 0;
+
+ /* Trigger shutdown functions in scsi's highlevel. */
+ if (scsi_id->scsi_host)
+ scsi_unblock_requests(scsi_id->scsi_host);
+ sdev = scsi_id->sdev;
+ if (sdev) {
+ scsi_id->sdev = NULL;
+ scsi_remove_device(sdev);
+ }
sbp2_logout_device(scsi_id);
sbp2_remove_device(scsi_id);
@@ -790,7 +812,7 @@ static void sbp2_host_reset(struct hpsb_host *host)
static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- struct scsi_device *sdev;
+ int error;
SBP2_DEBUG("sbp2_start_device");
@@ -939,10 +961,10 @@ alloc_fail:
sbp2_max_speed_and_size(scsi_id);
/* Add this device to the scsi layer now */
- sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
- if (IS_ERR(sdev)) {
+ error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
+ if (error) {
SBP2_ERR("scsi_add_device failed");
- return PTR_ERR(sdev);
+ return error;
}
return 0;
@@ -2473,37 +2495,26 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct sbp2scsi_host_info *hi;
+ int result = DID_NO_CONNECT << 16;
SBP2_DEBUG("sbp2scsi_queuecommand");
- /*
- * If scsi_id is null, it means there is no device in this slot,
- * so we should return selection timeout.
- */
- if (!scsi_id) {
- SCpnt->result = DID_NO_CONNECT << 16;
- done (SCpnt);
- return 0;
- }
+ if (!sbp2util_node_is_available(scsi_id))
+ goto done;
hi = scsi_id->hi;
if (!hi) {
SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
- SCpnt->result = DID_NO_CONNECT << 16;
- done (SCpnt);
- return(0);
+ goto done;
}
/*
* Until we handle multiple luns, just return selection time-out
* to any IO directed at non-zero LUNs
*/
- if (SCpnt->device->lun) {
- SCpnt->result = DID_NO_CONNECT << 16;
- done (SCpnt);
- return(0);
- }
+ if (SCpnt->device->lun)
+ goto done;
/*
* Check for request sense command, and handle it here
@@ -2514,7 +2525,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
- return(0);
+ return 0;
}
/*
@@ -2522,9 +2533,8 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
if (!hpsb_node_entry_valid(scsi_id->ne)) {
SBP2_ERR("Bus reset in progress - rejecting command");
- SCpnt->result = DID_BUS_BUSY << 16;
- done (SCpnt);
- return(0);
+ result = DID_BUS_BUSY << 16;
+ goto done;
}
/*
@@ -2535,8 +2545,12 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
SCpnt, done);
}
+ return 0;
- return(0);
+done:
+ SCpnt->result = result;
+ done(SCpnt);
+ return 0;
}
/*
@@ -2683,14 +2697,27 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
}
-static int sbp2scsi_slave_configure (struct scsi_device *sdev)
+static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
{
- blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+ ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
+ return 0;
+}
+
+static int sbp2scsi_slave_configure(struct scsi_device *sdev)
+{
+ blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
return 0;
}
+static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
+{
+ ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
+ return;
+}
+
+
/*
* Called by scsi stack when something has really gone wrong. Usually
* called when a command has timed-out for some reason.
@@ -2705,7 +2732,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
SBP2_ERR("aborting sbp2 command");
scsi_print_command(SCpnt);
- if (scsi_id) {
+ if (sbp2util_node_is_available(scsi_id)) {
/*
* Right now, just return any matching command structures
@@ -2742,31 +2769,24 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
/*
* Called by scsi stack when something has really gone wrong.
*/
-static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+ unsigned long flags;
SBP2_ERR("reset requested");
- if (scsi_id) {
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+
+ if (sbp2util_node_is_available(scsi_id)) {
SBP2_ERR("Generating sbp2 fetch agent reset");
sbp2_agent_reset(scsi_id, 0);
}
- return(SUCCESS);
-}
-
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
- rc = __sbp2scsi_reset(SCpnt);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
- return rc;
+ return SUCCESS;
}
static const char *sbp2scsi_info (struct Scsi_Host *host)
@@ -2817,7 +2837,9 @@ static struct scsi_host_template scsi_driver_template = {
.eh_device_reset_handler = sbp2scsi_reset,
.eh_bus_reset_handler = sbp2scsi_reset,
.eh_host_reset_handler = sbp2scsi_reset,
+ .slave_alloc = sbp2scsi_slave_alloc,
.slave_configure = sbp2scsi_slave_configure,
+ .slave_destroy = sbp2scsi_slave_destroy,
.this_id = -1,
.sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
@@ -2837,7 +2859,8 @@ static int sbp2_module_init(void)
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
- SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
+ SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
+ SBP2_INFO("Try serialize_io=0 for better performance");
scsi_driver_template.can_queue = 1;
scsi_driver_template.cmd_per_lun = 1;
}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 06759b36afea..23911da50154 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -883,7 +883,7 @@ static int __video1394_ioctl(struct file *file,
v.channel);
}
- if (copy_to_user((void *)arg, &v, sizeof(v))) {
+ if (copy_to_user(argp, &v, sizeof(v))) {
/* FIXME : free allocated dma resources */
return -EFAULT;
}
@@ -1370,7 +1370,7 @@ 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;
- class_device_create(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
@@ -1571,4 +1571,3 @@ static int __init video1394_init_module (void)
module_init(video1394_init_module);
module_exit(video1394_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16);
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 79c8e2dd9c33..bdf0891a92dd 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -1,24 +1,38 @@
menu "InfiniBand support"
config INFINIBAND
+ depends on PCI || BROKEN
tristate "InfiniBand support"
---help---
Core support for InfiniBand (IB). Make sure to also select
any protocols you wish to use as well as drivers for your
InfiniBand hardware.
-config INFINIBAND_USER_VERBS
- tristate "InfiniBand userspace verbs support"
+config INFINIBAND_USER_MAD
+ tristate "InfiniBand userspace MAD support"
depends on INFINIBAND
---help---
- Userspace InfiniBand verbs support. This is the kernel side
- of userspace verbs, which allows userspace processes to
- directly access InfiniBand hardware for fast-path
- operations. You will also need libibverbs and a hardware
- driver library from <http://www.openib.org>.
+ Userspace InfiniBand Management Datagram (MAD) support. This
+ is the kernel side of the userspace MAD support, which allows
+ userspace processes to send and receive MADs. You will also
+ need libibumad from <http://www.openib.org>.
+
+config INFINIBAND_USER_ACCESS
+ tristate "InfiniBand userspace access (verbs and CM)"
+ depends on INFINIBAND
+ ---help---
+ Userspace InfiniBand access support. This enables the
+ kernel side of userspace verbs and the userspace
+ communication manager (CM). This allows userspace processes
+ to set up connections and directly access InfiniBand
+ hardware for fast-path operations. You will also need
+ libibverbs, libibcm and a hardware driver library from
+ <http://www.openib.org>.
source "drivers/infiniband/hw/mthca/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig"
+source "drivers/infiniband/ulp/srp/Kconfig"
+
endmenu
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index d256cf798218..a43fb34cca94 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_INFINIBAND) += core/
obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
+obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 10be36731ed7..ec3353f24b27 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -1,8 +1,7 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
- ib_cm.o ib_umad.o ib_ucm.o
-obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
+ ib_cm.o
+obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
+obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
device.o fmr_pool.o cache.o
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 729f0b0d983a..7545775d38ef 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -36,58 +37,41 @@
* $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
*/
-#include <linux/dma-mapping.h>
-
-#include <asm/bug.h>
+#include "agent.h"
+#include "smi.h"
-#include <ib_smi.h>
+#define SPFX "ib_agent: "
-#include "smi.h"
-#include "agent_priv.h"
-#include "mad_priv.h"
-#include "agent.h"
+struct ib_agent_port_private {
+ struct list_head port_list;
+ struct ib_mad_agent *agent[2];
+};
-spinlock_t ib_agent_port_list_lock;
+static DEFINE_SPINLOCK(ib_agent_port_list_lock);
static LIST_HEAD(ib_agent_port_list);
-/*
- * Caller must hold ib_agent_port_list_lock
- */
-static inline struct ib_agent_port_private *
-__ib_get_agent_port(struct ib_device *device, int port_num,
- struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+__ib_get_agent_port(struct ib_device *device, int port_num)
{
struct ib_agent_port_private *entry;
- BUG_ON(!(!!device ^ !!mad_agent)); /* Exactly one MUST be (!NULL) */
-
- if (device) {
- list_for_each_entry(entry, &ib_agent_port_list, port_list) {
- if (entry->smp_agent->device == device &&
- entry->port_num == port_num)
- return entry;
- }
- } else {
- list_for_each_entry(entry, &ib_agent_port_list, port_list) {
- if ((entry->smp_agent == mad_agent) ||
- (entry->perf_mgmt_agent == mad_agent))
- return entry;
- }
+ list_for_each_entry(entry, &ib_agent_port_list, port_list) {
+ if (entry->agent[0]->device == device &&
+ entry->agent[0]->port_num == port_num)
+ return entry;
}
return NULL;
}
-static inline struct ib_agent_port_private *
-ib_get_agent_port(struct ib_device *device, int port_num,
- struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+ib_get_agent_port(struct ib_device *device, int port_num)
{
struct ib_agent_port_private *entry;
unsigned long flags;
spin_lock_irqsave(&ib_agent_port_list_lock, flags);
- entry = __ib_get_agent_port(device, port_num, mad_agent);
+ entry = __ib_get_agent_port(device, port_num);
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
-
return entry;
}
@@ -99,226 +83,102 @@ int smi_check_local_dr_smp(struct ib_smp *smp,
if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
return 1;
- port_priv = ib_get_agent_port(device, port_num, NULL);
+
+ port_priv = ib_get_agent_port(device, port_num);
if (!port_priv) {
printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d "
- "not open\n",
- device->name, port_num);
+ "not open\n", device->name, port_num);
return 1;
}
- return smi_check_local_smp(port_priv->smp_agent, smp);
+ return smi_check_local_smp(port_priv->agent[0], smp);
}
-static int agent_mad_send(struct ib_mad_agent *mad_agent,
- struct ib_agent_port_private *port_priv,
- struct ib_mad_private *mad_priv,
- struct ib_grh *grh,
- struct ib_wc *wc)
+int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+ struct ib_wc *wc, struct ib_device *device,
+ int port_num, int qpn)
{
- struct ib_agent_send_wr *agent_send_wr;
- struct ib_sge gather_list;
- struct ib_send_wr send_wr;
- struct ib_send_wr *bad_send_wr;
- struct ib_ah_attr ah_attr;
- unsigned long flags;
- int ret = 1;
-
- agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);
- if (!agent_send_wr)
- goto out;
- agent_send_wr->mad = mad_priv;
-
- gather_list.addr = dma_map_single(mad_agent->device->dma_device,
- &mad_priv->mad,
- sizeof(mad_priv->mad),
- DMA_TO_DEVICE);
- gather_list.length = sizeof(mad_priv->mad);
- gather_list.lkey = mad_agent->mr->lkey;
-
- send_wr.next = NULL;
- send_wr.opcode = IB_WR_SEND;
- send_wr.sg_list = &gather_list;
- send_wr.num_sge = 1;
- send_wr.wr.ud.remote_qpn = wc->src_qp; /* DQPN */
- send_wr.wr.ud.timeout_ms = 0;
- send_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+ struct ib_agent_port_private *port_priv;
+ struct ib_mad_agent *agent;
+ struct ib_mad_send_buf *send_buf;
+ struct ib_ah *ah;
+ int ret;
- ah_attr.dlid = wc->slid;
- ah_attr.port_num = mad_agent->port_num;
- ah_attr.src_path_bits = wc->dlid_path_bits;
- ah_attr.sl = wc->sl;
- ah_attr.static_rate = 0;
- ah_attr.ah_flags = 0; /* No GRH */
- if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
- if (wc->wc_flags & IB_WC_GRH) {
- ah_attr.ah_flags = IB_AH_GRH;
- /* Should sgid be looked up ? */
- ah_attr.grh.sgid_index = 0;
- ah_attr.grh.hop_limit = grh->hop_limit;
- ah_attr.grh.flow_label = be32_to_cpu(
- grh->version_tclass_flow) & 0xfffff;
- ah_attr.grh.traffic_class = (be32_to_cpu(
- grh->version_tclass_flow) >> 20) & 0xff;
- memcpy(ah_attr.grh.dgid.raw,
- grh->sgid.raw,
- sizeof(ah_attr.grh.dgid));
- }
+ port_priv = ib_get_agent_port(device, port_num);
+ if (!port_priv) {
+ printk(KERN_ERR SPFX "Unable to find port agent\n");
+ return -ENODEV;
}
- agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);
- if (IS_ERR(agent_send_wr->ah)) {
- printk(KERN_ERR SPFX "No memory for address handle\n");
- kfree(agent_send_wr);
- goto out;
+ agent = port_priv->agent[qpn];
+ ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
+ if (IS_ERR(ah)) {
+ ret = PTR_ERR(ah);
+ printk(KERN_ERR SPFX "ib_create_ah_from_wc error:%d\n", ret);
+ return ret;
}
- send_wr.wr.ud.ah = agent_send_wr->ah;
- if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
- send_wr.wr.ud.pkey_index = wc->pkey_index;
- send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;
- } else { /* for SMPs */
- send_wr.wr.ud.pkey_index = 0;
- send_wr.wr.ud.remote_qkey = 0;
+ send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
+ IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
+ GFP_KERNEL);
+ if (IS_ERR(send_buf)) {
+ ret = PTR_ERR(send_buf);
+ printk(KERN_ERR SPFX "ib_create_send_mad error:%d\n", ret);
+ goto err1;
}
- send_wr.wr.ud.mad_hdr = &mad_priv->mad.mad.mad_hdr;
- send_wr.wr_id = (unsigned long)agent_send_wr;
- pci_unmap_addr_set(agent_send_wr, mapping, gather_list.addr);
-
- /* Send */
- spin_lock_irqsave(&port_priv->send_list_lock, flags);
- if (ib_post_send_mad(mad_agent, &send_wr, &bad_send_wr)) {
- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
- dma_unmap_single(mad_agent->device->dma_device,
- pci_unmap_addr(agent_send_wr, mapping),
- sizeof(mad_priv->mad),
- DMA_TO_DEVICE);
- ib_destroy_ah(agent_send_wr->ah);
- kfree(agent_send_wr);
- } else {
- list_add_tail(&agent_send_wr->send_list,
- &port_priv->send_posted_list);
- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
- ret = 0;
+ memcpy(send_buf->mad, mad, sizeof *mad);
+ send_buf->ah = ah;
+ if ((ret = ib_post_send_mad(send_buf, NULL))) {
+ printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
+ goto err2;
}
-
-out:
+ return 0;
+err2:
+ ib_free_send_mad(send_buf);
+err1:
+ ib_destroy_ah(ah);
return ret;
}
-int agent_send(struct ib_mad_private *mad,
- struct ib_grh *grh,
- struct ib_wc *wc,
- struct ib_device *device,
- int port_num)
-{
- struct ib_agent_port_private *port_priv;
- struct ib_mad_agent *mad_agent;
-
- port_priv = ib_get_agent_port(device, port_num, NULL);
- if (!port_priv) {
- printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",
- device->name, port_num);
- return 1;
- }
-
- /* Get mad agent based on mgmt_class in MAD */
- switch (mad->mad.mad.mad_hdr.mgmt_class) {
- case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
- case IB_MGMT_CLASS_SUBN_LID_ROUTED:
- mad_agent = port_priv->smp_agent;
- break;
- case IB_MGMT_CLASS_PERF_MGMT:
- mad_agent = port_priv->perf_mgmt_agent;
- break;
- default:
- return 1;
- }
-
- return agent_mad_send(mad_agent, port_priv, mad, grh, wc);
-}
-
static void agent_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc)
{
- struct ib_agent_port_private *port_priv;
- struct ib_agent_send_wr *agent_send_wr;
- unsigned long flags;
-
- /* Find matching MAD agent */
- port_priv = ib_get_agent_port(NULL, 0, mad_agent);
- if (!port_priv) {
- printk(KERN_ERR SPFX "agent_send_handler: no matching MAD "
- "agent %p\n", mad_agent);
- return;
- }
-
- agent_send_wr = (struct ib_agent_send_wr *)(unsigned long)mad_send_wc->wr_id;
- spin_lock_irqsave(&port_priv->send_list_lock, flags);
- /* Remove completed send from posted send MAD list */
- list_del(&agent_send_wr->send_list);
- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-
- dma_unmap_single(mad_agent->device->dma_device,
- pci_unmap_addr(agent_send_wr, mapping),
- sizeof(agent_send_wr->mad->mad),
- DMA_TO_DEVICE);
-
- ib_destroy_ah(agent_send_wr->ah);
-
- /* Release allocated memory */
- kmem_cache_free(ib_mad_cache, agent_send_wr->mad);
- kfree(agent_send_wr);
+ ib_destroy_ah(mad_send_wc->send_buf->ah);
+ ib_free_send_mad(mad_send_wc->send_buf);
}
int ib_agent_port_open(struct ib_device *device, int port_num)
{
- int ret;
struct ib_agent_port_private *port_priv;
unsigned long flags;
-
- /* First, check if port already open for SMI */
- port_priv = ib_get_agent_port(device, port_num, NULL);
- if (port_priv) {
- printk(KERN_DEBUG SPFX "%s port %d already open\n",
- device->name, port_num);
- return 0;
- }
+ int ret;
/* Create new device info */
- port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);
+ port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
if (!port_priv) {
printk(KERN_ERR SPFX "No memory for ib_agent_port_private\n");
ret = -ENOMEM;
goto error1;
}
- memset(port_priv, 0, sizeof *port_priv);
- port_priv->port_num = port_num;
- spin_lock_init(&port_priv->send_list_lock);
- INIT_LIST_HEAD(&port_priv->send_posted_list);
-
- /* Obtain send only MAD agent for SM class (SMI QP) */
- port_priv->smp_agent = ib_register_mad_agent(device, port_num,
- IB_QPT_SMI,
- NULL, 0,
+ /* Obtain send only MAD agent for SMI QP */
+ port_priv->agent[0] = ib_register_mad_agent(device, port_num,
+ IB_QPT_SMI, NULL, 0,
&agent_send_handler,
- NULL, NULL);
-
- if (IS_ERR(port_priv->smp_agent)) {
- ret = PTR_ERR(port_priv->smp_agent);
+ NULL, NULL);
+ if (IS_ERR(port_priv->agent[0])) {
+ ret = PTR_ERR(port_priv->agent[0]);
goto error2;
}
- /* Obtain send only MAD agent for PerfMgmt class (GSI QP) */
- port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
- IB_QPT_GSI,
- NULL, 0,
- &agent_send_handler,
- NULL, NULL);
- if (IS_ERR(port_priv->perf_mgmt_agent)) {
- ret = PTR_ERR(port_priv->perf_mgmt_agent);
+ /* Obtain send only MAD agent for GSI QP */
+ port_priv->agent[1] = ib_register_mad_agent(device, port_num,
+ IB_QPT_GSI, NULL, 0,
+ &agent_send_handler,
+ NULL, NULL);
+ if (IS_ERR(port_priv->agent[1])) {
+ ret = PTR_ERR(port_priv->agent[1]);
goto error3;
}
@@ -329,7 +189,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
return 0;
error3:
- ib_unregister_mad_agent(port_priv->smp_agent);
+ ib_unregister_mad_agent(port_priv->agent[0]);
error2:
kfree(port_priv);
error1:
@@ -342,7 +202,7 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
unsigned long flags;
spin_lock_irqsave(&ib_agent_port_list_lock, flags);
- port_priv = __ib_get_agent_port(device, port_num, NULL);
+ port_priv = __ib_get_agent_port(device, port_num);
if (port_priv == NULL) {
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
printk(KERN_ERR SPFX "Port %d not found\n", port_num);
@@ -351,9 +211,8 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
list_del(&port_priv->port_list);
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
- ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
- ib_unregister_mad_agent(port_priv->smp_agent);
+ ib_unregister_mad_agent(port_priv->agent[1]);
+ ib_unregister_mad_agent(port_priv->agent[0]);
kfree(port_priv);
-
return 0;
}
diff --git a/drivers/infiniband/core/agent.h b/drivers/infiniband/core/agent.h
index d9426842254a..86d72fab37b0 100644
--- a/drivers/infiniband/core/agent.h
+++ b/drivers/infiniband/core/agent.h
@@ -39,17 +39,15 @@
#ifndef __AGENT_H_
#define __AGENT_H_
-extern spinlock_t ib_agent_port_list_lock;
+#include <linux/err.h>
+#include <rdma/ib_mad.h>
-extern int ib_agent_port_open(struct ib_device *device,
- int port_num);
+extern int ib_agent_port_open(struct ib_device *device, int port_num);
extern int ib_agent_port_close(struct ib_device *device, int port_num);
-extern int agent_send(struct ib_mad_private *mad,
- struct ib_grh *grh,
- struct ib_wc *wc,
- struct ib_device *device,
- int port_num);
+extern int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+ struct ib_wc *wc, struct ib_device *device,
+ int port_num, int qpn);
#endif /* __AGENT_H_ */
diff --git a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
deleted file mode 100644
index 17435af1e914..000000000000
--- a/drivers/infiniband/core/agent_priv.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $
- */
-
-#ifndef __IB_AGENT_PRIV_H__
-#define __IB_AGENT_PRIV_H__
-
-#include <linux/pci.h>
-
-#define SPFX "ib_agent: "
-
-struct ib_agent_send_wr {
- struct list_head send_list;
- struct ib_ah *ah;
- struct ib_mad_private *mad;
- DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
-struct ib_agent_port_private {
- struct list_head port_list;
- struct list_head send_posted_list;
- spinlock_t send_list_lock;
- int port_num;
- struct ib_mad_agent *smp_agent; /* SM class */
- struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
-};
-
-#endif /* __IB_AGENT_PRIV_H__ */
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 3042360c97e1..c57a3871184c 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -1,5 +1,8 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, 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
@@ -32,12 +35,12 @@
* $Id: cache.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
+#include <linux/sched.h> /* INIT_WORK, schedule_work(), flush_scheduled_work() */
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "core_priv.h"
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 403ed125d8f4..02110e00d145 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -43,8 +43,8 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <ib_cache.h>
-#include <ib_cm.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
#include "cm_msgs.h"
MODULE_AUTHOR("Sean Hefty");
@@ -83,7 +83,7 @@ struct cm_port {
struct cm_device {
struct list_head list;
struct ib_device *device;
- u64 ca_guid;
+ __be64 ca_guid;
struct cm_port port[0];
};
@@ -100,8 +100,8 @@ struct cm_work {
struct list_head list;
struct cm_port *port;
struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */
- u32 local_id; /* Established / timewait */
- u32 remote_id;
+ __be32 local_id; /* Established / timewait */
+ __be32 remote_id;
struct ib_cm_event cm_event;
struct ib_sa_path_rec path[0];
};
@@ -110,8 +110,8 @@ struct cm_timewait_info {
struct cm_work work; /* Must be first. */
struct rb_node remote_qp_node;
struct rb_node remote_id_node;
- u64 remote_ca_guid;
- u32 remote_qpn;
+ __be64 remote_ca_guid;
+ __be32 remote_qpn;
u8 inserted_remote_qp;
u8 inserted_remote_id;
};
@@ -132,11 +132,12 @@ struct cm_id_private {
struct cm_av alt_av;
void *private_data;
- u64 tid;
- u32 local_qpn;
- u32 remote_qpn;
- u32 sq_psn;
- u32 rq_psn;
+ __be64 tid;
+ __be32 local_qpn;
+ __be32 remote_qpn;
+ enum ib_qp_type qp_type;
+ __be32 sq_psn;
+ __be32 rq_psn;
int timeout_ms;
enum ib_mtu path_mtu;
u8 private_data_len;
@@ -173,9 +174,9 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
if (IS_ERR(ah))
return PTR_ERR(ah);
- m = ib_create_send_mad(mad_agent, 1, cm_id_priv->av.pkey_index,
- ah, 0, sizeof(struct ib_mad_hdr),
- sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+ m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
+ cm_id_priv->av.pkey_index,
+ 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_ATOMIC);
if (IS_ERR(m)) {
ib_destroy_ah(ah);
@@ -183,7 +184,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
}
/* Timeout set by caller if response is expected. */
- m->send_wr.wr.ud.retries = cm_id_priv->max_cm_retries;
+ m->ah = ah;
+ m->retries = cm_id_priv->max_cm_retries;
atomic_inc(&cm_id_priv->refcount);
m->context[0] = cm_id_priv;
@@ -204,20 +206,20 @@ static int cm_alloc_response_msg(struct cm_port *port,
return PTR_ERR(ah);
m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
- ah, 0, sizeof(struct ib_mad_hdr),
- sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+ 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_ATOMIC);
if (IS_ERR(m)) {
ib_destroy_ah(ah);
return PTR_ERR(m);
}
+ m->ah = ah;
*msg = m;
return 0;
}
static void cm_free_msg(struct ib_mad_send_buf *msg)
{
- ib_destroy_ah(msg->send_wr.wr.ud.ah);
+ ib_destroy_ah(msg->ah);
if (msg->context[0])
cm_deref_id(msg->context[0]);
ib_free_send_mad(msg);
@@ -253,7 +255,7 @@ static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
u16 dlid, u8 sl, u16 src_path_bits)
{
memset(ah_attr, 0, sizeof ah_attr);
- ah_attr->dlid = be16_to_cpu(dlid);
+ ah_attr->dlid = dlid;
ah_attr->sl = sl;
ah_attr->src_path_bits = src_path_bits;
ah_attr->port_num = port_num;
@@ -264,7 +266,7 @@ static void cm_init_av_for_response(struct cm_port *port,
{
av->port = port;
av->pkey_index = wc->pkey_index;
- cm_set_ah_attr(&av->ah_attr, port->port_num, cpu_to_be16(wc->slid),
+ cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
wc->sl, wc->dlid_path_bits);
}
@@ -295,8 +297,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
return ret;
av->port = port;
- cm_set_ah_attr(&av->ah_attr, av->port->port_num, path->dlid,
- path->sl, path->slid & 0x7F);
+ cm_set_ah_attr(&av->ah_attr, av->port->port_num,
+ be16_to_cpu(path->dlid), path->sl,
+ be16_to_cpu(path->slid) & 0x7F);
av->packet_life_time = path->packet_life_time;
return 0;
}
@@ -309,26 +312,26 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
do {
spin_lock_irqsave(&cm.lock, flags);
ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
- (int *) &cm_id_priv->id.local_id);
+ (__force int *) &cm_id_priv->id.local_id);
spin_unlock_irqrestore(&cm.lock, flags);
} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
return ret;
}
-static void cm_free_id(u32 local_id)
+static void cm_free_id(__be32 local_id)
{
unsigned long flags;
spin_lock_irqsave(&cm.lock, flags);
- idr_remove(&cm.local_id_table, (int) local_id);
+ idr_remove(&cm.local_id_table, (__force int) local_id);
spin_unlock_irqrestore(&cm.lock, flags);
}
-static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
{
struct cm_id_private *cm_id_priv;
- cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
+ cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id);
if (cm_id_priv) {
if (cm_id_priv->id.remote_id == remote_id)
atomic_inc(&cm_id_priv->refcount);
@@ -339,7 +342,7 @@ static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
return cm_id_priv;
}
-static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
+static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
{
struct cm_id_private *cm_id_priv;
unsigned long flags;
@@ -356,17 +359,23 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
struct rb_node **link = &cm.listen_service_table.rb_node;
struct rb_node *parent = NULL;
struct cm_id_private *cur_cm_id_priv;
- u64 service_id = cm_id_priv->id.service_id;
- u64 service_mask = cm_id_priv->id.service_mask;
+ __be64 service_id = cm_id_priv->id.service_id;
+ __be64 service_mask = cm_id_priv->id.service_mask;
while (*link) {
parent = *link;
cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
service_node);
if ((cur_cm_id_priv->id.service_mask & service_id) ==
- (service_mask & cur_cm_id_priv->id.service_id))
- return cm_id_priv;
- if (service_id < cur_cm_id_priv->id.service_id)
+ (service_mask & cur_cm_id_priv->id.service_id) &&
+ (cm_id_priv->id.device == cur_cm_id_priv->id.device))
+ return cur_cm_id_priv;
+
+ if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
+ link = &(*link)->rb_left;
+ else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
+ link = &(*link)->rb_right;
+ else if (service_id < cur_cm_id_priv->id.service_id)
link = &(*link)->rb_left;
else
link = &(*link)->rb_right;
@@ -376,7 +385,8 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
return NULL;
}
-static struct cm_id_private * cm_find_listen(u64 service_id)
+static struct cm_id_private * cm_find_listen(struct ib_device *device,
+ __be64 service_id)
{
struct rb_node *node = cm.listen_service_table.rb_node;
struct cm_id_private *cm_id_priv;
@@ -384,9 +394,15 @@ static struct cm_id_private * cm_find_listen(u64 service_id)
while (node) {
cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
if ((cm_id_priv->id.service_mask & service_id) ==
- (cm_id_priv->id.service_mask & cm_id_priv->id.service_id))
+ cm_id_priv->id.service_id &&
+ (cm_id_priv->id.device == device))
return cm_id_priv;
- if (service_id < cm_id_priv->id.service_id)
+
+ if (device < cm_id_priv->id.device)
+ node = node->rb_left;
+ else if (device > cm_id_priv->id.device)
+ node = node->rb_right;
+ else if (service_id < cm_id_priv->id.service_id)
node = node->rb_left;
else
node = node->rb_right;
@@ -400,8 +416,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
struct rb_node **link = &cm.remote_id_table.rb_node;
struct rb_node *parent = NULL;
struct cm_timewait_info *cur_timewait_info;
- u64 remote_ca_guid = timewait_info->remote_ca_guid;
- u32 remote_id = timewait_info->work.remote_id;
+ __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+ __be32 remote_id = timewait_info->work.remote_id;
while (*link) {
parent = *link;
@@ -424,8 +440,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
return NULL;
}
-static struct cm_timewait_info * cm_find_remote_id(u64 remote_ca_guid,
- u32 remote_id)
+static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
+ __be32 remote_id)
{
struct rb_node *node = cm.remote_id_table.rb_node;
struct cm_timewait_info *timewait_info;
@@ -453,8 +469,8 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
struct rb_node **link = &cm.remote_qp_table.rb_node;
struct rb_node *parent = NULL;
struct cm_timewait_info *cur_timewait_info;
- u64 remote_ca_guid = timewait_info->remote_ca_guid;
- u32 remote_qpn = timewait_info->remote_qpn;
+ __be64 remote_ca_guid = timewait_info->remote_ca_guid;
+ __be32 remote_qpn = timewait_info->remote_qpn;
while (*link) {
parent = *link;
@@ -484,7 +500,7 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
struct rb_node *parent = NULL;
struct cm_id_private *cur_cm_id_priv;
union ib_gid *port_gid = &cm_id_priv->av.dgid;
- u32 remote_id = cm_id_priv->id.remote_id;
+ __be32 remote_id = cm_id_priv->id.remote_id;
while (*link) {
parent = *link;
@@ -521,20 +537,22 @@ static void cm_reject_sidr_req(struct cm_id_private *cm_id_priv,
ib_send_cm_sidr_rep(&cm_id_priv->id, &param);
}
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
+ ib_cm_handler cm_handler,
void *context)
{
struct cm_id_private *cm_id_priv;
int ret;
- cm_id_priv = kmalloc(sizeof *cm_id_priv, GFP_KERNEL);
+ cm_id_priv = kzalloc(sizeof *cm_id_priv, GFP_KERNEL);
if (!cm_id_priv)
return ERR_PTR(-ENOMEM);
- memset(cm_id_priv, 0, sizeof *cm_id_priv);
cm_id_priv->id.state = IB_CM_IDLE;
+ cm_id_priv->id.device = device;
cm_id_priv->id.cm_handler = cm_handler;
cm_id_priv->id.context = context;
+ cm_id_priv->id.remote_cm_qpn = 1;
ret = cm_alloc_id(cm_id_priv);
if (ret)
goto error;
@@ -598,14 +616,13 @@ static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
spin_unlock_irqrestore(&cm.lock, flags);
}
-static struct cm_timewait_info * cm_create_timewait_info(u32 local_id)
+static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
{
struct cm_timewait_info *timewait_info;
- timewait_info = kmalloc(sizeof *timewait_info, GFP_KERNEL);
+ timewait_info = kzalloc(sizeof *timewait_info, GFP_KERNEL);
if (!timewait_info)
return ERR_PTR(-ENOMEM);
- memset(timewait_info, 0, sizeof *timewait_info);
timewait_info->work.local_id = local_id;
INIT_WORK(&timewait_info->work.work, cm_work_handler,
@@ -659,8 +676,7 @@ retest:
break;
case IB_CM_SIDR_REQ_SENT:
cm_id->state = IB_CM_IDLE;
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
break;
case IB_CM_SIDR_REQ_RCVD:
@@ -671,8 +687,7 @@ retest:
case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
/* Fall through */
case IB_CM_REQ_RCVD:
case IB_CM_MRA_REQ_SENT:
@@ -689,8 +704,7 @@ retest:
ib_send_cm_dreq(cm_id, NULL, 0);
goto retest;
case IB_CM_DREQ_SENT:
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
cm_enter_timewait(cm_id_priv);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
break;
@@ -715,14 +729,15 @@ retest:
EXPORT_SYMBOL(ib_destroy_cm_id);
int ib_cm_listen(struct ib_cm_id *cm_id,
- u64 service_id,
- u64 service_mask)
+ __be64 service_id,
+ __be64 service_mask)
{
struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
unsigned long flags;
int ret = 0;
- service_mask = service_mask ? service_mask : ~0ULL;
+ service_mask = service_mask ? service_mask :
+ __constant_cpu_to_be64(~0ULL);
service_id &= service_mask;
if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID &&
(service_id != IB_CM_ASSIGN_SERVICE_ID))
@@ -735,8 +750,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
spin_lock_irqsave(&cm.lock, flags);
if (service_id == IB_CM_ASSIGN_SERVICE_ID) {
- cm_id->service_id = __cpu_to_be64(cm.listen_service_id++);
- cm_id->service_mask = ~0ULL;
+ cm_id->service_id = cpu_to_be64(cm.listen_service_id++);
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
} else {
cm_id->service_id = service_id;
cm_id->service_mask = service_mask;
@@ -752,18 +767,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_listen);
-static u64 cm_form_tid(struct cm_id_private *cm_id_priv,
- enum cm_msg_sequence msg_seq)
+static __be64 cm_form_tid(struct cm_id_private *cm_id_priv,
+ enum cm_msg_sequence msg_seq)
{
u64 hi_tid, low_tid;
hi_tid = ((u64) cm_id_priv->av.port->mad_agent->hi_tid) << 32;
- low_tid = (u64) (cm_id_priv->id.local_id | (msg_seq << 30));
+ low_tid = (u64) ((__force u32)cm_id_priv->id.local_id |
+ (msg_seq << 30));
return cpu_to_be64(hi_tid | low_tid);
}
static void cm_format_mad_hdr(struct ib_mad_hdr *hdr,
- enum cm_msg_attr_id attr_id, u64 tid)
+ __be16 attr_id, __be64 tid)
{
hdr->base_version = IB_MGMT_BASE_VERSION;
hdr->mgmt_class = IB_MGMT_CLASS_CM;
@@ -862,7 +878,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
struct ib_cm_req_param *param)
{
struct cm_id_private *cm_id_priv;
- struct ib_send_wr *bad_send_wr;
struct cm_req_msg *req_msg;
unsigned long flags;
int ret;
@@ -896,7 +911,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
goto error1;
}
cm_id->service_id = param->service_id;
- cm_id->service_mask = ~0ULL;
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
cm_id_priv->timeout_ms = cm_convert_to_ms(
param->primary_path->packet_life_time) * 2 +
cm_convert_to_ms(
@@ -906,6 +921,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_id_priv->responder_resources = param->responder_resources;
cm_id_priv->retry_count = param->retry_count;
cm_id_priv->path_mtu = param->primary_path->mtu;
+ cm_id_priv->qp_type = param->qp_type;
ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
if (ret)
@@ -914,7 +930,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
cm_format_req(req_msg, cm_id_priv, param);
cm_id_priv->tid = req_msg->hdr.tid;
- cm_id_priv->msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+ cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;
cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;
cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
@@ -923,8 +939,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_req_get_primary_local_ack_timeout(req_msg);
spin_lock_irqsave(&cm_id_priv->lock, flags);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &cm_id_priv->msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(cm_id_priv->msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
goto error2;
@@ -947,7 +962,6 @@ static int cm_issue_rej(struct cm_port *port,
void *ari, u8 ari_length)
{
struct ib_mad_send_buf *msg = NULL;
- struct ib_send_wr *bad_send_wr;
struct cm_rej_msg *rej_msg, *rcv_msg;
int ret;
@@ -963,22 +977,22 @@ static int cm_issue_rej(struct cm_port *port,
rej_msg->remote_comm_id = rcv_msg->local_comm_id;
rej_msg->local_comm_id = rcv_msg->remote_comm_id;
cm_rej_set_msg_rejected(rej_msg, msg_rejected);
- rej_msg->reason = reason;
+ rej_msg->reason = cpu_to_be16(reason);
if (ari && ari_length) {
cm_rej_set_reject_info_len(rej_msg, ari_length);
memcpy(rej_msg->ari, ari, ari_length);
}
- ret = ib_post_send_mad(port->mad_agent, &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
cm_free_msg(msg);
return ret;
}
-static inline int cm_is_active_peer(u64 local_ca_guid, u64 remote_ca_guid,
- u32 local_qpn, u32 remote_qpn)
+static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
+ __be32 local_qpn, __be32 remote_qpn)
{
return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||
((local_ca_guid == remote_ca_guid) &&
@@ -1042,7 +1056,6 @@ static void cm_format_req_event(struct cm_work *work,
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
param = &work->cm_event.param.req_rcvd;
param->listen_id = listen_id;
- param->device = cm_id_priv->av.port->mad_agent->device;
param->port = cm_id_priv->av.port->port_num;
param->primary_path = &work->path[0];
if (req_msg->alt_local_lid)
@@ -1137,7 +1150,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
break;
}
- rej_msg->reason = reason;
+ rej_msg->reason = cpu_to_be16(reason);
if (ari && ari_length) {
cm_rej_set_reject_info_len(rej_msg, ari_length);
memcpy(rej_msg->ari, ari, ari_length);
@@ -1151,7 +1164,6 @@ static void cm_dup_req_handler(struct cm_work *work,
struct cm_id_private *cm_id_priv)
{
struct ib_mad_send_buf *msg = NULL;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1180,8 +1192,7 @@ static void cm_dup_req_handler(struct cm_work *work,
}
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
- &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
goto free;
return;
@@ -1221,7 +1232,8 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
}
/* Find matching listen request. */
- listen_cm_id_priv = cm_find_listen(req_msg->service_id);
+ listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
+ req_msg->service_id);
if (!listen_cm_id_priv) {
spin_unlock_irqrestore(&cm.lock, flags);
cm_issue_rej(work->port, work->mad_recv_wc,
@@ -1249,7 +1261,7 @@ static int cm_req_handler(struct cm_work *work)
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id = ib_create_cm_id(NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
@@ -1276,7 +1288,7 @@ static int cm_req_handler(struct cm_work *work)
cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
cm_id_priv->id.context = listen_cm_id_priv->id.context;
cm_id_priv->id.service_id = req_msg->service_id;
- cm_id_priv->id.service_mask = ~0ULL;
+ cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
@@ -1300,6 +1312,7 @@ static int cm_req_handler(struct cm_work *work)
cm_req_get_primary_local_ack_timeout(req_msg);
cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
+ cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);
cm_process_work(cm_id_priv, work);
@@ -1310,6 +1323,7 @@ error3: atomic_dec(&cm_id_priv->refcount);
cm_deref_id(listen_cm_id_priv);
cm_cleanup_timewait(cm_id_priv->timewait_info);
error2: kfree(cm_id_priv->timewait_info);
+ cm_id_priv->timewait_info = NULL;
error1: ib_destroy_cm_id(&cm_id_priv->id);
return ret;
}
@@ -1343,7 +1357,6 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
struct cm_rep_msg *rep_msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1365,11 +1378,10 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
rep_msg = (struct cm_rep_msg *) msg->mad;
cm_format_rep(rep_msg, cm_id_priv, param);
- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+ msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -1407,7 +1419,6 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
void *data;
int ret;
@@ -1434,8 +1445,7 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_id,
cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -1480,7 +1490,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv;
struct cm_rep_msg *rep_msg;
struct ib_mad_send_buf *msg = NULL;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1508,8 +1517,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
goto unlock;
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
- &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
goto free;
goto deref;
@@ -1577,8 +1585,7 @@ static int cm_rep_handler(struct cm_work *work)
/* todo: handle peer_to_peer */
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1612,8 +1619,7 @@ static int cm_establish_handler(struct cm_work *work)
goto out;
}
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1652,8 +1658,7 @@ static int cm_rtu_handler(struct cm_work *work)
}
cm_id_priv->id.state = IB_CM_ESTABLISHED;
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1690,7 +1695,6 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1712,11 +1716,10 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
private_data, private_data_len);
- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+ msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
cm_enter_timewait(cm_id_priv);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -1750,7 +1753,6 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
void *data;
int ret;
@@ -1780,8 +1782,7 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id,
cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
- &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -1798,7 +1799,6 @@ static int cm_dreq_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv;
struct cm_dreq_msg *dreq_msg;
struct ib_mad_send_buf *msg = NULL;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1817,8 +1817,7 @@ static int cm_dreq_handler(struct cm_work *work)
switch (cm_id_priv->id.state) {
case IB_CM_REP_SENT:
case IB_CM_DREQ_SENT:
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
break;
case IB_CM_ESTABLISHED:
case IB_CM_MRA_REP_RCVD:
@@ -1832,8 +1831,7 @@ static int cm_dreq_handler(struct cm_work *work)
cm_id_priv->private_data_len);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr))
+ if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
goto deref;
default:
@@ -1880,8 +1878,7 @@ static int cm_drep_handler(struct cm_work *work)
}
cm_enter_timewait(cm_id_priv);
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1906,7 +1903,6 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -1950,8 +1946,7 @@ int ib_send_cm_rej(struct ib_cm_id *cm_id,
if (ret)
goto out;
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
cm_free_msg(msg);
@@ -1969,7 +1964,7 @@ static void cm_format_rej_event(struct cm_work *work)
param = &work->cm_event.param.rej_rcvd;
param->ari = rej_msg->ari;
param->ari_length = cm_rej_get_reject_info_len(rej_msg);
- param->reason = rej_msg->reason;
+ param->reason = __be16_to_cpu(rej_msg->reason);
work->cm_event.private_data = &rej_msg->private_data;
}
@@ -1978,20 +1973,20 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
struct cm_timewait_info *timewait_info;
struct cm_id_private *cm_id_priv;
unsigned long flags;
- u32 remote_id;
+ __be32 remote_id;
remote_id = rej_msg->local_comm_id;
- if (rej_msg->reason == IB_CM_REJ_TIMEOUT) {
+ if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
spin_lock_irqsave(&cm.lock, flags);
- timewait_info = cm_find_remote_id( *((u64 *) rej_msg->ari),
+ timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
remote_id);
if (!timewait_info) {
spin_unlock_irqrestore(&cm.lock, flags);
return NULL;
}
cm_id_priv = idr_find(&cm.local_id_table,
- (int) timewait_info->work.local_id);
+ (__force int) timewait_info->work.local_id);
if (cm_id_priv) {
if (cm_id_priv->id.remote_id == remote_id)
atomic_inc(&cm_id_priv->refcount);
@@ -2027,19 +2022,17 @@ static int cm_rej_handler(struct cm_work *work)
case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
/* fall through */
case IB_CM_REQ_RCVD:
case IB_CM_MRA_REQ_SENT:
- if (rej_msg->reason == IB_CM_REJ_STALE_CONN)
+ if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)
cm_enter_timewait(cm_id_priv);
else
cm_reset_to_idle(cm_id_priv);
break;
case IB_CM_DREQ_SENT:
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
/* fall through */
case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT:
@@ -2074,7 +2067,6 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
void *data;
unsigned long flags;
int ret;
@@ -2098,8 +2090,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_REQ, service_timeout,
private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
goto error2;
cm_id->state = IB_CM_MRA_REQ_SENT;
@@ -2112,8 +2103,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_REP, service_timeout,
private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
goto error2;
cm_id->state = IB_CM_MRA_REP_SENT;
@@ -2126,8 +2116,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id,
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
CM_MSG_RESPONSE_OTHER, service_timeout,
private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret)
goto error2;
cm_id->lap_state = IB_CM_MRA_LAP_SENT;
@@ -2189,14 +2178,14 @@ static int cm_mra_handler(struct cm_work *work)
case IB_CM_REQ_SENT:
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
ib_modify_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg, timeout))
+ cm_id_priv->msg, timeout))
goto out;
cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
break;
case IB_CM_REP_SENT:
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
ib_modify_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg, timeout))
+ cm_id_priv->msg, timeout))
goto out;
cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
break;
@@ -2204,7 +2193,7 @@ static int cm_mra_handler(struct cm_work *work)
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
ib_modify_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg, timeout))
+ cm_id_priv->msg, timeout))
goto out;
cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
break;
@@ -2267,7 +2256,6 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -2288,11 +2276,10 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,
alternate_path, private_data, private_data_len);
- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+ msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -2336,7 +2323,6 @@ static int cm_lap_handler(struct cm_work *work)
struct cm_lap_msg *lap_msg;
struct ib_cm_lap_event_param *param;
struct ib_mad_send_buf *msg = NULL;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -2370,8 +2356,7 @@ static int cm_lap_handler(struct cm_work *work)
cm_id_priv->private_data_len);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr))
+ if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
goto deref;
default:
@@ -2427,7 +2412,6 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -2450,8 +2434,7 @@ int ib_send_cm_apr(struct ib_cm_id *cm_id,
cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,
info, info_length, private_data, private_data_len);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -2490,8 +2473,7 @@ static int cm_apr_handler(struct cm_work *work)
goto out;
}
cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
cm_id_priv->msg = NULL;
ret = atomic_inc_and_test(&cm_id_priv->work_count);
@@ -2553,7 +2535,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
sidr_req_msg->request_id = cm_id_priv->id.local_id;
- sidr_req_msg->pkey = param->pkey;
+ sidr_req_msg->pkey = cpu_to_be16(param->pkey);
sidr_req_msg->service_id = param->service_id;
if (param->private_data && param->private_data_len)
@@ -2566,7 +2548,6 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -2580,7 +2561,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
goto out;
cm_id->service_id = param->service_id;
- cm_id->service_mask = ~0ULL;
+ cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
cm_id_priv->timeout_ms = param->timeout_ms;
cm_id_priv->max_cm_retries = param->max_cm_retries;
ret = cm_alloc_msg(cm_id_priv, &msg);
@@ -2589,13 +2570,12 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,
param);
- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+ msg->timeout_ms = cm_id_priv->timeout_ms;
msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;
spin_lock_irqsave(&cm_id_priv->lock, flags);
if (cm_id->state == IB_CM_IDLE)
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
else
ret = -EINVAL;
@@ -2621,9 +2601,8 @@ static void cm_format_sidr_req_event(struct cm_work *work,
sidr_req_msg = (struct cm_sidr_req_msg *)
work->mad_recv_wc->recv_buf.mad;
param = &work->cm_event.param.sidr_req_rcvd;
- param->pkey = sidr_req_msg->pkey;
+ param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
param->listen_id = listen_id;
- param->device = work->port->mad_agent->device;
param->port = work->port->port_num;
work->cm_event.private_data = &sidr_req_msg->private_data;
}
@@ -2636,7 +2615,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
struct ib_wc *wc;
unsigned long flags;
- cm_id = ib_create_cm_id(NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -2645,7 +2624,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
sidr_req_msg = (struct cm_sidr_req_msg *)
work->mad_recv_wc->recv_buf.mad;
wc = work->mad_recv_wc->wc;
- cm_id_priv->av.dgid.global.subnet_prefix = wc->slid;
+ cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
cm_id_priv->av.dgid.global.interface_id = 0;
cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
&cm_id_priv->av);
@@ -2660,7 +2639,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
spin_unlock_irqrestore(&cm.lock, flags);
goto out; /* Duplicate message. */
}
- cur_cm_id_priv = cm_find_listen(sidr_req_msg->service_id);
+ cur_cm_id_priv = cm_find_listen(cm_id->device,
+ sidr_req_msg->service_id);
if (!cur_cm_id_priv) {
rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
spin_unlock_irqrestore(&cm.lock, flags);
@@ -2673,7 +2653,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
cm_id_priv->id.context = cur_cm_id_priv->id.context;
cm_id_priv->id.service_id = sidr_req_msg->service_id;
- cm_id_priv->id.service_mask = ~0ULL;
+ cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
cm_process_work(cm_id_priv, work);
@@ -2709,7 +2689,6 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
{
struct cm_id_private *cm_id_priv;
struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
unsigned long flags;
int ret;
@@ -2731,8 +2710,7 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
param);
- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
- &msg->send_wr, &bad_send_wr);
+ ret = ib_post_send_mad(msg, NULL);
if (ret) {
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_free_msg(msg);
@@ -2785,8 +2763,7 @@ static int cm_sidr_rep_handler(struct cm_work *work)
goto out;
}
cm_id_priv->id.state = IB_CM_IDLE;
- ib_cancel_mad(cm_id_priv->av.port->mad_agent,
- (unsigned long) cm_id_priv->msg);
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
cm_format_sidr_rep_event(work);
@@ -2854,9 +2831,7 @@ discard:
static void cm_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc)
{
- struct ib_mad_send_buf *msg;
-
- msg = (struct ib_mad_send_buf *)(unsigned long)mad_send_wc->wr_id;
+ struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
switch (mad_send_wc->status) {
case IB_WC_SUCCESS:
@@ -3058,10 +3033,10 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
case IB_CM_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX | IB_QP_PORT;
- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+ qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
+ IB_ACCESS_REMOTE_WRITE;
if (cm_id_priv->responder_resources)
- qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_WRITE |
- IB_ACCESS_REMOTE_READ;
+ qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ;
qp_attr->pkey_index = cm_id_priv->av.pkey_index;
qp_attr->port_num = cm_id_priv->av.port->port_num;
ret = 0;
@@ -3091,14 +3066,18 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
case IB_CM_MRA_REP_RCVD:
case IB_CM_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
- IB_QP_DEST_QPN | IB_QP_RQ_PSN |
- IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER;
+ IB_QP_DEST_QPN | IB_QP_RQ_PSN;
qp_attr->ah_attr = cm_id_priv->av.ah_attr;
qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
- qp_attr->max_dest_rd_atomic = cm_id_priv->responder_resources;
- qp_attr->min_rnr_timer = 0;
+ if (cm_id_priv->qp_type == IB_QPT_RC) {
+ *qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
+ IB_QP_MIN_RNR_TIMER;
+ qp_attr->max_dest_rd_atomic =
+ cm_id_priv->responder_resources;
+ qp_attr->min_rnr_timer = 0;
+ }
if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_ALT_PATH;
qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
@@ -3127,14 +3106,17 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
case IB_CM_ESTABLISHED:
- *qp_attr_mask = IB_QP_STATE | IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
- IB_QP_RNR_RETRY | IB_QP_SQ_PSN |
- IB_QP_MAX_QP_RD_ATOMIC;
- qp_attr->timeout = cm_id_priv->local_ack_timeout;
- qp_attr->retry_cnt = cm_id_priv->retry_count;
- qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+ *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
- qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+ if (cm_id_priv->qp_type == IB_QPT_RC) {
+ *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_MAX_QP_RD_ATOMIC;
+ qp_attr->timeout = cm_id_priv->local_ack_timeout;
+ qp_attr->retry_cnt = cm_id_priv->retry_count;
+ qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+ qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+ }
if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
qp_attr->path_mig_state = IB_MIG_REARM;
@@ -3175,10 +3157,10 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
-static u64 cm_get_ca_guid(struct ib_device *device)
+static __be64 cm_get_ca_guid(struct ib_device *device)
{
struct ib_device_attr *device_attr;
- u64 guid;
+ __be64 guid;
int ret;
device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
@@ -3317,6 +3299,7 @@ static void __exit ib_cm_cleanup(void)
flush_workqueue(cm.wq);
destroy_workqueue(cm.wq);
ib_unregister_client(&cm_client);
+ idr_destroy(&cm.local_id_table);
}
module_init(ib_cm_init);
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 15a309a77b2b..4d3aee90c249 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -34,7 +34,7 @@
#if !defined(CM_MSGS_H)
#define CM_MSGS_H
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
/*
* Parameters to routines below should be in network-byte order, and values
@@ -43,19 +43,17 @@
#define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */
-enum cm_msg_attr_id {
- CM_REQ_ATTR_ID = __constant_htons(0x0010),
- CM_MRA_ATTR_ID = __constant_htons(0x0011),
- CM_REJ_ATTR_ID = __constant_htons(0x0012),
- CM_REP_ATTR_ID = __constant_htons(0x0013),
- CM_RTU_ATTR_ID = __constant_htons(0x0014),
- CM_DREQ_ATTR_ID = __constant_htons(0x0015),
- CM_DREP_ATTR_ID = __constant_htons(0x0016),
- CM_SIDR_REQ_ATTR_ID = __constant_htons(0x0017),
- CM_SIDR_REP_ATTR_ID = __constant_htons(0x0018),
- CM_LAP_ATTR_ID = __constant_htons(0x0019),
- CM_APR_ATTR_ID = __constant_htons(0x001A)
-};
+#define CM_REQ_ATTR_ID __constant_htons(0x0010)
+#define CM_MRA_ATTR_ID __constant_htons(0x0011)
+#define CM_REJ_ATTR_ID __constant_htons(0x0012)
+#define CM_REP_ATTR_ID __constant_htons(0x0013)
+#define CM_RTU_ATTR_ID __constant_htons(0x0014)
+#define CM_DREQ_ATTR_ID __constant_htons(0x0015)
+#define CM_DREP_ATTR_ID __constant_htons(0x0016)
+#define CM_SIDR_REQ_ATTR_ID __constant_htons(0x0017)
+#define CM_SIDR_REP_ATTR_ID __constant_htons(0x0018)
+#define CM_LAP_ATTR_ID __constant_htons(0x0019)
+#define CM_APR_ATTR_ID __constant_htons(0x001A)
enum cm_msg_sequence {
CM_MSG_SEQUENCE_REQ,
@@ -67,35 +65,35 @@ enum cm_msg_sequence {
struct cm_req_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 rsvd4;
- u64 service_id;
- u64 local_ca_guid;
- u32 rsvd24;
- u32 local_qkey;
+ __be32 local_comm_id;
+ __be32 rsvd4;
+ __be64 service_id;
+ __be64 local_ca_guid;
+ __be32 rsvd24;
+ __be32 local_qkey;
/* local QPN:24, responder resources:8 */
- u32 offset32;
+ __be32 offset32;
/* local EECN:24, initiator depth:8 */
- u32 offset36;
+ __be32 offset36;
/*
* remote EECN:24, remote CM response timeout:5,
* transport service type:2, end-to-end flow control:1
*/
- u32 offset40;
+ __be32 offset40;
/* starting PSN:24, local CM response timeout:5, retry count:3 */
- u32 offset44;
- u16 pkey;
+ __be32 offset44;
+ __be16 pkey;
/* path MTU:4, RDC exists:1, RNR retry count:3. */
u8 offset50;
/* max CM Retries:4, SRQ:1, rsvd:3 */
u8 offset51;
- u16 primary_local_lid;
- u16 primary_remote_lid;
+ __be16 primary_local_lid;
+ __be16 primary_remote_lid;
union ib_gid primary_local_gid;
union ib_gid primary_remote_gid;
/* flow label:20, rsvd:6, packet rate:6 */
- u32 primary_offset88;
+ __be32 primary_offset88;
u8 primary_traffic_class;
u8 primary_hop_limit;
/* SL:4, subnet local:1, rsvd:3 */
@@ -103,12 +101,12 @@ struct cm_req_msg {
/* local ACK timeout:5, rsvd:3 */
u8 primary_offset95;
- u16 alt_local_lid;
- u16 alt_remote_lid;
+ __be16 alt_local_lid;
+ __be16 alt_remote_lid;
union ib_gid alt_local_gid;
union ib_gid alt_remote_gid;
/* flow label:20, rsvd:6, packet rate:6 */
- u32 alt_offset132;
+ __be32 alt_offset132;
u8 alt_traffic_class;
u8 alt_hop_limit;
/* SL:4, subnet local:1, rsvd:3 */
@@ -120,12 +118,12 @@ struct cm_req_msg {
} __attribute__ ((packed));
-static inline u32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
{
return cpu_to_be32(be32_to_cpu(req_msg->offset32) >> 8);
}
-static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, u32 qpn)
+static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, __be32 qpn)
{
req_msg->offset32 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(req_msg->offset32) &
@@ -188,6 +186,7 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
req_msg->offset40 = cpu_to_be32((be32_to_cpu(
req_msg->offset40) &
0xFFFFFFF9) | 0x2);
+ break;
default:
req_msg->offset40 = cpu_to_be32(be32_to_cpu(
req_msg->offset40) &
@@ -208,13 +207,13 @@ static inline void cm_req_set_flow_ctrl(struct cm_req_msg *req_msg,
0xFFFFFFFE));
}
-static inline u32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
{
return cpu_to_be32(be32_to_cpu(req_msg->offset44) >> 8);
}
static inline void cm_req_set_starting_psn(struct cm_req_msg *req_msg,
- u32 starting_psn)
+ __be32 starting_psn)
{
req_msg->offset44 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
(be32_to_cpu(req_msg->offset44) & 0x000000FF));
@@ -288,13 +287,13 @@ static inline void cm_req_set_srq(struct cm_req_msg *req_msg, u8 srq)
((srq & 0x1) << 3));
}
-static inline u32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
{
- return cpu_to_be32((be32_to_cpu(req_msg->primary_offset88) >> 12));
+ return cpu_to_be32(be32_to_cpu(req_msg->primary_offset88) >> 12);
}
static inline void cm_req_set_primary_flow_label(struct cm_req_msg *req_msg,
- u32 flow_label)
+ __be32 flow_label)
{
req_msg->primary_offset88 = cpu_to_be32(
(be32_to_cpu(req_msg->primary_offset88) &
@@ -350,13 +349,13 @@ static inline void cm_req_set_primary_local_ack_timeout(struct cm_req_msg *req_m
(local_ack_timeout << 3));
}
-static inline u32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
+static inline __be32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
{
- return cpu_to_be32((be32_to_cpu(req_msg->alt_offset132) >> 12));
+ return cpu_to_be32(be32_to_cpu(req_msg->alt_offset132) >> 12);
}
static inline void cm_req_set_alt_flow_label(struct cm_req_msg *req_msg,
- u32 flow_label)
+ __be32 flow_label)
{
req_msg->alt_offset132 = cpu_to_be32(
(be32_to_cpu(req_msg->alt_offset132) &
@@ -422,8 +421,8 @@ enum cm_msg_response {
struct cm_mra_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* message MRAed:2, rsvd:6 */
u8 offset8;
/* service timeout:5, rsvd:3 */
@@ -458,13 +457,13 @@ static inline void cm_mra_set_service_timeout(struct cm_mra_msg *mra_msg,
struct cm_rej_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* message REJected:2, rsvd:6 */
u8 offset8;
/* reject info length:7, rsvd:1. */
u8 offset9;
- u16 reason;
+ __be16 reason;
u8 ari[IB_CM_REJ_ARI_LENGTH];
u8 private_data[IB_CM_REJ_PRIVATE_DATA_SIZE];
@@ -495,45 +494,45 @@ static inline void cm_rej_set_reject_info_len(struct cm_rej_msg *rej_msg,
struct cm_rep_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
- u32 local_qkey;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
+ __be32 local_qkey;
/* local QPN:24, rsvd:8 */
- u32 offset12;
+ __be32 offset12;
/* local EECN:24, rsvd:8 */
- u32 offset16;
+ __be32 offset16;
/* starting PSN:24 rsvd:8 */
- u32 offset20;
+ __be32 offset20;
u8 resp_resources;
u8 initiator_depth;
/* target ACK delay:5, failover accepted:2, end-to-end flow control:1 */
u8 offset26;
/* RNR retry count:3, SRQ:1, rsvd:5 */
u8 offset27;
- u64 local_ca_guid;
+ __be64 local_ca_guid;
u8 private_data[IB_CM_REP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset12) >> 8);
}
-static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, u32 qpn)
+static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
{
rep_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
}
-static inline u32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
+static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
}
static inline void cm_rep_set_starting_psn(struct cm_rep_msg *rep_msg,
- u32 starting_psn)
+ __be32 starting_psn)
{
rep_msg->offset20 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
(be32_to_cpu(rep_msg->offset20) & 0x000000FF));
@@ -600,8 +599,8 @@ static inline void cm_rep_set_srq(struct cm_rep_msg *rep_msg, u8 srq)
struct cm_rtu_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 private_data[IB_CM_RTU_PRIVATE_DATA_SIZE];
@@ -610,21 +609,21 @@ struct cm_rtu_msg {
struct cm_dreq_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
/* remote QPN/EECN:24, rsvd:8 */
- u32 offset8;
+ __be32 offset8;
u8 private_data[IB_CM_DREQ_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
+static inline __be32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
{
return cpu_to_be32(be32_to_cpu(dreq_msg->offset8) >> 8);
}
-static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
+static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, __be32 qpn)
{
dreq_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(dreq_msg->offset8) & 0x000000FF));
@@ -633,8 +632,8 @@ static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
struct cm_drep_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 private_data[IB_CM_DREP_PRIVATE_DATA_SIZE];
@@ -643,37 +642,37 @@ struct cm_drep_msg {
struct cm_lap_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
- u32 rsvd8;
+ __be32 rsvd8;
/* remote QPN/EECN:24, remote CM response timeout:5, rsvd:3 */
- u32 offset12;
- u32 rsvd16;
+ __be32 offset12;
+ __be32 rsvd16;
- u16 alt_local_lid;
- u16 alt_remote_lid;
+ __be16 alt_local_lid;
+ __be16 alt_remote_lid;
union ib_gid alt_local_gid;
union ib_gid alt_remote_gid;
/* flow label:20, rsvd:4, traffic class:8 */
- u32 offset56;
+ __be32 offset56;
u8 alt_hop_limit;
/* rsvd:2, packet rate:6 */
- uint8_t offset61;
+ u8 offset61;
/* SL:4, subnet local:1, rsvd:3 */
- uint8_t offset62;
+ u8 offset62;
/* local ACK timeout:5, rsvd:3 */
- uint8_t offset63;
+ u8 offset63;
u8 private_data[IB_CM_LAP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
{
return cpu_to_be32(be32_to_cpu(lap_msg->offset12) >> 8);
}
-static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, u32 qpn)
+static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, __be32 qpn)
{
lap_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(lap_msg->offset12) &
@@ -693,17 +692,17 @@ static inline void cm_lap_set_remote_resp_timeout(struct cm_lap_msg *lap_msg,
0xFFFFFF07));
}
-static inline u32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
+static inline __be32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
{
- return be32_to_cpu(lap_msg->offset56) >> 12;
+ return cpu_to_be32(be32_to_cpu(lap_msg->offset56) >> 12);
}
static inline void cm_lap_set_flow_label(struct cm_lap_msg *lap_msg,
- u32 flow_label)
+ __be32 flow_label)
{
- lap_msg->offset56 = cpu_to_be32((flow_label << 12) |
- (be32_to_cpu(lap_msg->offset56) &
- 0x00000FFF));
+ lap_msg->offset56 = cpu_to_be32(
+ (be32_to_cpu(lap_msg->offset56) & 0x00000FFF) |
+ (be32_to_cpu(flow_label) << 12));
}
static inline u8 cm_lap_get_traffic_class(struct cm_lap_msg *lap_msg)
@@ -766,8 +765,8 @@ static inline void cm_lap_set_local_ack_timeout(struct cm_lap_msg *lap_msg,
struct cm_apr_msg {
struct ib_mad_hdr hdr;
- u32 local_comm_id;
- u32 remote_comm_id;
+ __be32 local_comm_id;
+ __be32 remote_comm_id;
u8 info_length;
u8 ap_status;
@@ -779,10 +778,10 @@ struct cm_apr_msg {
struct cm_sidr_req_msg {
struct ib_mad_hdr hdr;
- u32 request_id;
- u16 pkey;
- u16 rsvd;
- u64 service_id;
+ __be32 request_id;
+ __be16 pkey;
+ __be16 rsvd;
+ __be64 service_id;
u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
@@ -790,26 +789,26 @@ struct cm_sidr_req_msg {
struct cm_sidr_rep_msg {
struct ib_mad_hdr hdr;
- u32 request_id;
+ __be32 request_id;
u8 status;
u8 info_length;
- u16 rsvd;
+ __be16 rsvd;
/* QPN:24, rsvd:8 */
- u32 offset8;
- u64 service_id;
- u32 qkey;
+ __be32 offset8;
+ __be64 service_id;
+ __be32 qkey;
u8 info[IB_CM_SIDR_REP_INFO_LENGTH];
u8 private_data[IB_CM_SIDR_REP_PRIVATE_DATA_SIZE];
} __attribute__ ((packed));
-static inline u32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
+static inline __be32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
{
return cpu_to_be32(be32_to_cpu(sidr_rep_msg->offset8) >> 8);
}
static inline void cm_sidr_rep_set_qpn(struct cm_sidr_rep_msg *sidr_rep_msg,
- u32 qpn)
+ __be32 qpn)
{
sidr_rep_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
(be32_to_cpu(sidr_rep_msg->offset8) &
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 797049626ff6..7ad47a4b166b 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -38,7 +38,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
int ib_device_register_sysfs(struct ib_device *device);
void ib_device_unregister_sysfs(struct ib_device *device);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 9197e92d708a..e169e798354b 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -160,17 +161,9 @@ static int alloc_name(char *name)
*/
struct ib_device *ib_alloc_device(size_t size)
{
- void *dev;
-
BUG_ON(size < sizeof (struct ib_device));
- dev = kmalloc(size, GFP_KERNEL);
- if (!dev)
- return NULL;
-
- memset(dev, 0, size);
-
- return dev;
+ return kzalloc(size, GFP_KERNEL);
}
EXPORT_SYMBOL(ib_alloc_device);
@@ -513,6 +506,12 @@ int ib_query_port(struct ib_device *device,
u8 port_num,
struct ib_port_attr *port_attr)
{
+ if (device->node_type == IB_NODE_SWITCH) {
+ if (port_num)
+ return -EINVAL;
+ } else if (port_num < 1 || port_num > device->phys_port_cnt)
+ return -EINVAL;
+
return device->query_port(device, port_num, port_attr);
}
EXPORT_SYMBOL(ib_query_port);
@@ -582,6 +581,12 @@ int ib_modify_port(struct ib_device *device,
u8 port_num, int port_modify_mask,
struct ib_port_modify *port_modify)
{
+ if (device->node_type == IB_NODE_SWITCH) {
+ if (port_num)
+ return -EINVAL;
+ } else if (port_num < 1 || port_num > device->phys_port_cnt)
+ return -EINVAL;
+
return device->modify_port(device, port_num, port_modify_mask,
port_modify);
}
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 7763b31abba7..d34a6f1c4f4c 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -39,7 +39,7 @@
#include <linux/jhash.h>
#include <linux/kthread.h>
-#include <ib_fmr_pool.h>
+#include <rdma/ib_fmr_pool.h>
#include "core_priv.h"
@@ -334,6 +334,7 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
{
struct ib_pool_fmr *fmr;
struct ib_pool_fmr *tmp;
+ LIST_HEAD(fmr_list);
int i;
kthread_stop(pool->thread);
@@ -341,6 +342,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
i = 0;
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+ if (fmr->remap_count) {
+ INIT_LIST_HEAD(&fmr_list);
+ list_add_tail(&fmr->fmr->list, &fmr_list);
+ ib_unmap_fmr(&fmr_list);
+ }
ib_dealloc_fmr(fmr->fmr);
list_del(&fmr->list);
kfree(fmr);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b97e210ce9c8..3d8175e5f054 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -255,12 +255,11 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
}
/* Allocate structures */
- mad_agent_priv = kmalloc(sizeof *mad_agent_priv, GFP_KERNEL);
+ mad_agent_priv = kzalloc(sizeof *mad_agent_priv, GFP_KERNEL);
if (!mad_agent_priv) {
ret = ERR_PTR(-ENOMEM);
goto error1;
}
- memset(mad_agent_priv, 0, sizeof *mad_agent_priv);
mad_agent_priv->agent.mr = ib_get_dma_mr(port_priv->qp_info[qpn].qp->pd,
IB_ACCESS_LOCAL_WRITE);
@@ -448,14 +447,13 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
goto error1;
}
/* Allocate structures */
- mad_snoop_priv = kmalloc(sizeof *mad_snoop_priv, GFP_KERNEL);
+ mad_snoop_priv = kzalloc(sizeof *mad_snoop_priv, GFP_KERNEL);
if (!mad_snoop_priv) {
ret = ERR_PTR(-ENOMEM);
goto error1;
}
/* Now, fill in the various structures */
- memset(mad_snoop_priv, 0, sizeof *mad_snoop_priv);
mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];
mad_snoop_priv->agent.device = device;
mad_snoop_priv->agent.recv_handler = recv_handler;
@@ -579,7 +577,7 @@ static void dequeue_mad(struct ib_mad_list_head *mad_list)
}
static void snoop_send(struct ib_mad_qp_info *qp_info,
- struct ib_send_wr *send_wr,
+ struct ib_mad_send_buf *send_buf,
struct ib_mad_send_wc *mad_send_wc,
int mad_snoop_flags)
{
@@ -597,7 +595,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
atomic_inc(&mad_snoop_priv->refcount);
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
- send_wr, mad_send_wc);
+ send_buf, mad_send_wc);
if (atomic_dec_and_test(&mad_snoop_priv->refcount))
wake_up(&mad_snoop_priv->wait);
spin_lock_irqsave(&qp_info->snoop_lock, flags);
@@ -654,10 +652,10 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
* Return < 0 if error
*/
static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
- struct ib_smp *smp,
- struct ib_send_wr *send_wr)
+ struct ib_mad_send_wr_private *mad_send_wr)
{
int ret;
+ struct ib_smp *smp = mad_send_wr->send_buf.mad;
unsigned long flags;
struct ib_mad_local_private *local;
struct ib_mad_private *mad_priv;
@@ -666,6 +664,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_device *device = mad_agent_priv->agent.device;
u8 port_num = mad_agent_priv->agent.port_num;
struct ib_wc mad_wc;
+ struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
ret = -EINVAL;
@@ -693,7 +692,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
goto out;
}
- build_smp_wc(send_wr->wr_id, smp->dr_slid, send_wr->wr.ud.pkey_index,
+ build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
+ send_wr->wr.ud.pkey_index,
send_wr->wr.ud.port_num, &mad_wc);
/* No GRH for DR SMP */
@@ -744,13 +744,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
goto out;
}
- local->send_wr = *send_wr;
- local->send_wr.sg_list = local->sg_list;
- memcpy(local->sg_list, send_wr->sg_list,
- sizeof *send_wr->sg_list * send_wr->num_sge);
- local->send_wr.next = NULL;
- local->tid = send_wr->wr.ud.mad_hdr->tid;
- local->wr_id = send_wr->wr_id;
+ local->mad_send_wr = mad_send_wr;
/* Reference MAD agent until send side of local completion handled */
atomic_inc(&mad_agent_priv->refcount);
/* Queue local completion to local list */
@@ -780,17 +774,17 @@ static int get_buf_length(int hdr_len, int data_len)
struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
u32 remote_qpn, u16 pkey_index,
- struct ib_ah *ah, int rmpp_active,
+ int rmpp_active,
int hdr_len, int data_len,
- unsigned int __nocast gfp_mask)
+ gfp_t gfp_mask)
{
struct ib_mad_agent_private *mad_agent_priv;
- struct ib_mad_send_buf *send_buf;
+ struct ib_mad_send_wr_private *mad_send_wr;
int buf_size;
void *buf;
- mad_agent_priv = container_of(mad_agent,
- struct ib_mad_agent_private, agent);
+ mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
+ agent);
buf_size = get_buf_length(hdr_len, data_len);
if ((!mad_agent->rmpp_version &&
@@ -798,45 +792,39 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
(!rmpp_active && buf_size > sizeof(struct ib_mad)))
return ERR_PTR(-EINVAL);
- buf = kmalloc(sizeof *send_buf + buf_size, gfp_mask);
+ buf = kzalloc(sizeof *mad_send_wr + buf_size, gfp_mask);
if (!buf)
return ERR_PTR(-ENOMEM);
- memset(buf, 0, sizeof *send_buf + buf_size);
-
- send_buf = buf + buf_size;
- send_buf->mad = buf;
-
- send_buf->sge.addr = dma_map_single(mad_agent->device->dma_device,
- buf, buf_size, DMA_TO_DEVICE);
- pci_unmap_addr_set(send_buf, mapping, send_buf->sge.addr);
- send_buf->sge.length = buf_size;
- send_buf->sge.lkey = mad_agent->mr->lkey;
-
- send_buf->send_wr.wr_id = (unsigned long) send_buf;
- send_buf->send_wr.sg_list = &send_buf->sge;
- send_buf->send_wr.num_sge = 1;
- send_buf->send_wr.opcode = IB_WR_SEND;
- send_buf->send_wr.send_flags = IB_SEND_SIGNALED;
- send_buf->send_wr.wr.ud.ah = ah;
- send_buf->send_wr.wr.ud.mad_hdr = &send_buf->mad->mad_hdr;
- send_buf->send_wr.wr.ud.remote_qpn = remote_qpn;
- send_buf->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
- send_buf->send_wr.wr.ud.pkey_index = pkey_index;
+
+ mad_send_wr = buf + buf_size;
+ mad_send_wr->send_buf.mad = buf;
+
+ mad_send_wr->mad_agent_priv = mad_agent_priv;
+ mad_send_wr->sg_list[0].length = buf_size;
+ mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;
+
+ mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
+ mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
+ mad_send_wr->send_wr.num_sge = 1;
+ mad_send_wr->send_wr.opcode = IB_WR_SEND;
+ mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
+ mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
+ mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
+ mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
if (rmpp_active) {
- struct ib_rmpp_mad *rmpp_mad;
- rmpp_mad = (struct ib_rmpp_mad *)send_buf->mad;
+ struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad;
rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -
- offsetof(struct ib_rmpp_mad, data) + data_len);
+ IB_MGMT_RMPP_HDR + data_len);
rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;
rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,
IB_MGMT_RMPP_FLAG_ACTIVE);
}
- send_buf->mad_agent = mad_agent;
+ mad_send_wr->send_buf.mad_agent = mad_agent;
atomic_inc(&mad_agent_priv->refcount);
- return send_buf;
+ return &mad_send_wr->send_buf;
}
EXPORT_SYMBOL(ib_create_send_mad);
@@ -846,10 +834,6 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
mad_agent_priv = container_of(send_buf->mad_agent,
struct ib_mad_agent_private, agent);
-
- dma_unmap_single(send_buf->mad_agent->device->dma_device,
- pci_unmap_addr(send_buf, mapping),
- send_buf->sge.length, DMA_TO_DEVICE);
kfree(send_buf->mad);
if (atomic_dec_and_test(&mad_agent_priv->refcount))
@@ -860,8 +844,10 @@ EXPORT_SYMBOL(ib_free_send_mad);
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
{
struct ib_mad_qp_info *qp_info;
- struct ib_send_wr *bad_send_wr;
struct list_head *list;
+ struct ib_send_wr *bad_send_wr;
+ struct ib_mad_agent *mad_agent;
+ struct ib_sge *sge;
unsigned long flags;
int ret;
@@ -870,10 +856,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
+ mad_agent = mad_send_wr->send_buf.mad_agent;
+ sge = mad_send_wr->sg_list;
+ sge->addr = dma_map_single(mad_agent->device->dma_device,
+ mad_send_wr->send_buf.mad, sge->length,
+ DMA_TO_DEVICE);
+ pci_unmap_addr_set(mad_send_wr, mapping, sge->addr);
+
spin_lock_irqsave(&qp_info->send_queue.lock, flags);
if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
- ret = ib_post_send(mad_send_wr->mad_agent_priv->agent.qp,
- &mad_send_wr->send_wr, &bad_send_wr);
+ ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
+ &bad_send_wr);
list = &qp_info->send_queue.list;
} else {
ret = 0;
@@ -885,6 +878,11 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
list_add_tail(&mad_send_wr->mad_list.list, list);
}
spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
+ if (ret)
+ dma_unmap_single(mad_agent->device->dma_device,
+ pci_unmap_addr(mad_send_wr, mapping),
+ sge->length, DMA_TO_DEVICE);
+
return ret;
}
@@ -892,45 +890,28 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
* ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
* with the registered client
*/
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
- struct ib_send_wr *send_wr,
- struct ib_send_wr **bad_send_wr)
+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+ struct ib_mad_send_buf **bad_send_buf)
{
- int ret = -EINVAL;
struct ib_mad_agent_private *mad_agent_priv;
-
- /* Validate supplied parameters */
- if (!bad_send_wr)
- goto error1;
-
- if (!mad_agent || !send_wr)
- goto error2;
-
- if (!mad_agent->send_handler)
- goto error2;
-
- mad_agent_priv = container_of(mad_agent,
- struct ib_mad_agent_private,
- agent);
+ struct ib_mad_send_buf *next_send_buf;
+ struct ib_mad_send_wr_private *mad_send_wr;
+ unsigned long flags;
+ int ret = -EINVAL;
/* Walk list of send WRs and post each on send list */
- while (send_wr) {
- unsigned long flags;
- struct ib_send_wr *next_send_wr;
- struct ib_mad_send_wr_private *mad_send_wr;
- struct ib_smp *smp;
-
- /* Validate more parameters */
- if (send_wr->num_sge > IB_MAD_SEND_REQ_MAX_SG)
- goto error2;
-
- if (send_wr->wr.ud.timeout_ms && !mad_agent->recv_handler)
- goto error2;
+ for (; send_buf; send_buf = next_send_buf) {
- if (!send_wr->wr.ud.mad_hdr) {
- printk(KERN_ERR PFX "MAD header must be supplied "
- "in WR %p\n", send_wr);
- goto error2;
+ mad_send_wr = container_of(send_buf,
+ struct ib_mad_send_wr_private,
+ send_buf);
+ mad_agent_priv = mad_send_wr->mad_agent_priv;
+
+ if (!send_buf->mad_agent->send_handler ||
+ (send_buf->timeout_ms &&
+ !send_buf->mad_agent->recv_handler)) {
+ ret = -EINVAL;
+ goto error;
}
/*
@@ -938,40 +919,24 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
* current one completes, and the user modifies the work
* request associated with the completion
*/
- next_send_wr = (struct ib_send_wr *)send_wr->next;
+ next_send_buf = send_buf->next;
+ mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
- smp = (struct ib_smp *)send_wr->wr.ud.mad_hdr;
- if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
- ret = handle_outgoing_dr_smp(mad_agent_priv, smp,
- send_wr);
+ if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
+ IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+ ret = handle_outgoing_dr_smp(mad_agent_priv,
+ mad_send_wr);
if (ret < 0) /* error */
- goto error2;
+ goto error;
else if (ret == 1) /* locally consumed */
- goto next;
+ continue;
}
- /* Allocate MAD send WR tracking structure */
- mad_send_wr = kmalloc(sizeof *mad_send_wr, GFP_ATOMIC);
- if (!mad_send_wr) {
- printk(KERN_ERR PFX "No memory for "
- "ib_mad_send_wr_private\n");
- ret = -ENOMEM;
- goto error2;
- }
- memset(mad_send_wr, 0, sizeof *mad_send_wr);
-
- mad_send_wr->send_wr = *send_wr;
- mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
- memcpy(mad_send_wr->sg_list, send_wr->sg_list,
- sizeof *send_wr->sg_list * send_wr->num_sge);
- mad_send_wr->wr_id = send_wr->wr_id;
- mad_send_wr->tid = send_wr->wr.ud.mad_hdr->tid;
- mad_send_wr->mad_agent_priv = mad_agent_priv;
+ mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
/* Timeout will be updated after send completes */
- mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr.
- ud.timeout_ms);
- mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
- /* One reference for each work request to QP + response */
+ mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
+ mad_send_wr->retries = send_buf->retries;
+ /* Reference for work request to QP + response */
mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
mad_send_wr->status = IB_WC_SUCCESS;
@@ -994,16 +959,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
list_del(&mad_send_wr->agent_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
atomic_dec(&mad_agent_priv->refcount);
- goto error2;
+ goto error;
}
-next:
- send_wr = next_send_wr;
}
return 0;
-
-error2:
- *bad_send_wr = send_wr;
-error1:
+error:
+ if (bad_send_buf)
+ *bad_send_buf = send_buf;
return ret;
}
EXPORT_SYMBOL(ib_post_send_mad);
@@ -1074,14 +1036,12 @@ static int method_in_use(struct ib_mad_mgmt_method_table **method,
static int allocate_method_table(struct ib_mad_mgmt_method_table **method)
{
/* Allocate management method table */
- *method = kmalloc(sizeof **method, GFP_ATOMIC);
+ *method = kzalloc(sizeof **method, GFP_ATOMIC);
if (!*method) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_mgmt_method_table\n");
return -ENOMEM;
}
- /* Clear management method table */
- memset(*method, 0, sizeof **method);
return 0;
}
@@ -1172,15 +1132,14 @@ static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
class = &port_priv->version[mad_reg_req->mgmt_class_version].class;
if (!*class) {
/* Allocate management class table for "new" class version */
- *class = kmalloc(sizeof **class, GFP_ATOMIC);
+ *class = kzalloc(sizeof **class, GFP_ATOMIC);
if (!*class) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_mgmt_class_table\n");
ret = -ENOMEM;
goto error1;
}
- /* Clear management class table */
- memset(*class, 0, sizeof(**class));
+
/* Allocate method table for this management class */
method = &(*class)->method_table[mgmt_class];
if ((ret = allocate_method_table(method)))
@@ -1244,25 +1203,24 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,
mad_reg_req->mgmt_class_version].vendor;
if (!*vendor_table) {
/* Allocate mgmt vendor class table for "new" class version */
- vendor = kmalloc(sizeof *vendor, GFP_ATOMIC);
+ vendor = kzalloc(sizeof *vendor, GFP_ATOMIC);
if (!vendor) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_mgmt_vendor_class_table\n");
goto error1;
}
- /* Clear management vendor class table */
- memset(vendor, 0, sizeof(*vendor));
+
*vendor_table = vendor;
}
if (!(*vendor_table)->vendor_class[vclass]) {
/* Allocate table for this management vendor class */
- vendor_class = kmalloc(sizeof *vendor_class, GFP_ATOMIC);
+ vendor_class = kzalloc(sizeof *vendor_class, GFP_ATOMIC);
if (!vendor_class) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_mgmt_vendor_class\n");
goto error2;
}
- memset(vendor_class, 0, sizeof(*vendor_class));
+
(*vendor_table)->vendor_class[vclass] = vendor_class;
}
for (i = 0; i < MAX_MGMT_OUI; i++) {
@@ -1446,8 +1404,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
* of MAD.
*/
hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32;
- list_for_each_entry(entry, &port_priv->agent_list,
- agent_list) {
+ list_for_each_entry(entry, &port_priv->agent_list, agent_list) {
if (entry->agent.hi_tid == hi_tid) {
mad_agent = entry;
break;
@@ -1554,7 +1511,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
}
struct ib_mad_send_wr_private*
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
{
struct ib_mad_send_wr_private *mad_send_wr;
@@ -1570,8 +1527,7 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
*/
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) {
- if (is_data_mad(mad_agent_priv,
- mad_send_wr->send_wr.wr.ud.mad_hdr) &&
+ if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
mad_send_wr->tid == tid && mad_send_wr->timeout) {
/* Verify request has not been canceled */
return (mad_send_wr->status == IB_WC_SUCCESS) ?
@@ -1597,7 +1553,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_send_wr_private *mad_send_wr;
struct ib_mad_send_wc mad_send_wc;
unsigned long flags;
- u64 tid;
+ __be64 tid;
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
@@ -1627,14 +1583,14 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
/* Defined behavior is to complete response before request */
- mad_recv_wc->wc->wr_id = mad_send_wr->wr_id;
+ mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
mad_recv_wc);
atomic_dec(&mad_agent_priv->refcount);
mad_send_wc.status = IB_WC_SUCCESS;
mad_send_wc.vendor_err = 0;
- mad_send_wc.wr_id = mad_send_wr->wr_id;
+ mad_send_wc.send_buf = &mad_send_wr->send_buf;
ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
} else {
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
@@ -1727,11 +1683,11 @@ local:
if (ret & IB_MAD_RESULT_CONSUMED)
goto out;
if (ret & IB_MAD_RESULT_REPLY) {
- /* Send response */
- if (!agent_send(response, &recv->grh, wc,
- port_priv->device,
- port_priv->port_num))
- response = NULL;
+ agent_send_response(&response->mad.mad,
+ &recv->grh, wc,
+ port_priv->device,
+ port_priv->port_num,
+ qp_info->qp->qp_num);
goto out;
}
}
@@ -1865,15 +1821,15 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
if (mad_send_wr->status != IB_WC_SUCCESS )
mad_send_wc->status = mad_send_wr->status;
- if (ret != IB_RMPP_RESULT_INTERNAL)
+ if (ret == IB_RMPP_RESULT_INTERNAL)
+ ib_rmpp_send_handler(mad_send_wc);
+ else
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
mad_send_wc);
/* Release reference on agent taken when sending */
if (atomic_dec_and_test(&mad_agent_priv->refcount))
wake_up(&mad_agent_priv->wait);
-
- kfree(mad_send_wr);
return;
done:
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
@@ -1887,6 +1843,7 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
struct ib_mad_qp_info *qp_info;
struct ib_mad_queue *send_queue;
struct ib_send_wr *bad_send_wr;
+ struct ib_mad_send_wc mad_send_wc;
unsigned long flags;
int ret;
@@ -1897,6 +1854,9 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
qp_info = send_queue->qp_info;
retry:
+ dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
+ pci_unmap_addr(mad_send_wr, mapping),
+ mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
queued_send_wr = NULL;
spin_lock_irqsave(&send_queue->lock, flags);
list_del(&mad_list->list);
@@ -1913,17 +1873,17 @@ retry:
}
spin_unlock_irqrestore(&send_queue->lock, flags);
- /* Restore client wr_id in WC and complete send */
- wc->wr_id = mad_send_wr->wr_id;
+ mad_send_wc.send_buf = &mad_send_wr->send_buf;
+ mad_send_wc.status = wc->status;
+ mad_send_wc.vendor_err = wc->vendor_err;
if (atomic_read(&qp_info->snoop_count))
- snoop_send(qp_info, &mad_send_wr->send_wr,
- (struct ib_mad_send_wc *)wc,
+ snoop_send(qp_info, &mad_send_wr->send_buf, &mad_send_wc,
IB_MAD_SNOOP_SEND_COMPLETIONS);
- ib_mad_complete_send_wr(mad_send_wr, (struct ib_mad_send_wc *)wc);
+ ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
if (queued_send_wr) {
ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
- &bad_send_wr);
+ &bad_send_wr);
if (ret) {
printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
mad_send_wr = queued_send_wr;
@@ -2065,38 +2025,37 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
&cancel_list, agent_list) {
- mad_send_wc.wr_id = mad_send_wr->wr_id;
+ mad_send_wc.send_buf = &mad_send_wr->send_buf;
+ list_del(&mad_send_wr->agent_list);
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc);
-
- list_del(&mad_send_wr->agent_list);
- kfree(mad_send_wr);
atomic_dec(&mad_agent_priv->refcount);
}
}
static struct ib_mad_send_wr_private*
-find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv, u64 wr_id)
+find_send_wr(struct ib_mad_agent_private *mad_agent_priv,
+ struct ib_mad_send_buf *send_buf)
{
struct ib_mad_send_wr_private *mad_send_wr;
list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
agent_list) {
- if (mad_send_wr->wr_id == wr_id)
+ if (&mad_send_wr->send_buf == send_buf)
return mad_send_wr;
}
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) {
- if (is_data_mad(mad_agent_priv,
- mad_send_wr->send_wr.wr.ud.mad_hdr) &&
- mad_send_wr->wr_id == wr_id)
+ if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
+ &mad_send_wr->send_buf == send_buf)
return mad_send_wr;
}
return NULL;
}
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
+int ib_modify_mad(struct ib_mad_agent *mad_agent,
+ struct ib_mad_send_buf *send_buf, u32 timeout_ms)
{
struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_wr_private *mad_send_wr;
@@ -2106,7 +2065,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
agent);
spin_lock_irqsave(&mad_agent_priv->lock, flags);
- mad_send_wr = find_send_by_wr_id(mad_agent_priv, wr_id);
+ mad_send_wr = find_send_wr(mad_agent_priv, send_buf);
if (!mad_send_wr || mad_send_wr->status != IB_WC_SUCCESS) {
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
return -EINVAL;
@@ -2118,7 +2077,7 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
}
- mad_send_wr->send_wr.wr.ud.timeout_ms = timeout_ms;
+ mad_send_wr->send_buf.timeout_ms = timeout_ms;
if (active)
mad_send_wr->timeout = msecs_to_jiffies(timeout_ms);
else
@@ -2129,9 +2088,10 @@ int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
}
EXPORT_SYMBOL(ib_modify_mad);
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id)
+void ib_cancel_mad(struct ib_mad_agent *mad_agent,
+ struct ib_mad_send_buf *send_buf)
{
- ib_modify_mad(mad_agent, wr_id, 0);
+ ib_modify_mad(mad_agent, send_buf, 0);
}
EXPORT_SYMBOL(ib_cancel_mad);
@@ -2165,9 +2125,9 @@ static void local_completions(void *data)
* Defined behavior is to complete response
* before request
*/
- build_smp_wc(local->wr_id, IB_LID_PERMISSIVE,
- 0 /* pkey index */,
- recv_mad_agent->agent.port_num, &wc);
+ build_smp_wc((unsigned long) local->mad_send_wr,
+ be16_to_cpu(IB_LID_PERMISSIVE),
+ 0, recv_mad_agent->agent.port_num, &wc);
local->mad_priv->header.recv_wc.wc = &wc;
local->mad_priv->header.recv_wc.mad_len =
@@ -2194,11 +2154,11 @@ local_send_completion:
/* Complete send */
mad_send_wc.status = IB_WC_SUCCESS;
mad_send_wc.vendor_err = 0;
- mad_send_wc.wr_id = local->wr_id;
+ mad_send_wc.send_buf = &local->mad_send_wr->send_buf;
if (atomic_read(&mad_agent_priv->qp_info->snoop_count))
- snoop_send(mad_agent_priv->qp_info, &local->send_wr,
- &mad_send_wc,
- IB_MAD_SNOOP_SEND_COMPLETIONS);
+ snoop_send(mad_agent_priv->qp_info,
+ &local->mad_send_wr->send_buf,
+ &mad_send_wc, IB_MAD_SNOOP_SEND_COMPLETIONS);
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc);
@@ -2219,8 +2179,7 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
if (!mad_send_wr->retries--)
return -ETIMEDOUT;
- mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr.
- wr.ud.timeout_ms);
+ mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
ret = ib_retry_rmpp(mad_send_wr);
@@ -2283,18 +2242,17 @@ static void timeout_sends(void *data)
mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
else
mad_send_wc.status = mad_send_wr->status;
- mad_send_wc.wr_id = mad_send_wr->wr_id;
+ mad_send_wc.send_buf = &mad_send_wr->send_buf;
mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
&mad_send_wc);
- kfree(mad_send_wr);
atomic_dec(&mad_agent_priv->refcount);
spin_lock_irqsave(&mad_agent_priv->lock, flags);
}
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
}
-static void ib_mad_thread_completion_handler(struct ib_cq *cq)
+static void ib_mad_thread_completion_handler(struct ib_cq *cq, void *arg)
{
struct ib_mad_port_private *port_priv = cq->cq_context;
@@ -2559,12 +2517,12 @@ static int ib_mad_port_open(struct ib_device *device,
char name[sizeof "ib_mad123"];
/* Create new device info */
- port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);
+ port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
if (!port_priv) {
printk(KERN_ERR PFX "No memory for ib_mad_port_private\n");
return -ENOMEM;
}
- memset(port_priv, 0, sizeof *port_priv);
+
port_priv->device = device;
port_priv->port_num = port_num;
spin_lock_init(&port_priv->reg_lock);
@@ -2574,8 +2532,7 @@ static int ib_mad_port_open(struct ib_device *device,
cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
port_priv->cq = ib_create_cq(port_priv->device,
- (ib_comp_handler)
- ib_mad_thread_completion_handler,
+ ib_mad_thread_completion_handler,
NULL, port_priv, cq_size);
if (IS_ERR(port_priv->cq)) {
printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
@@ -2682,40 +2639,47 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
static void ib_mad_init_device(struct ib_device *device)
{
- int num_ports, cur_port, i;
+ int start, end, i;
if (device->node_type == IB_NODE_SWITCH) {
- num_ports = 1;
- cur_port = 0;
+ start = 0;
+ end = 0;
} else {
- num_ports = device->phys_port_cnt;
- cur_port = 1;
+ start = 1;
+ end = device->phys_port_cnt;
}
- for (i = 0; i < num_ports; i++, cur_port++) {
- if (ib_mad_port_open(device, cur_port)) {
+
+ for (i = start; i <= end; i++) {
+ if (ib_mad_port_open(device, i)) {
printk(KERN_ERR PFX "Couldn't open %s port %d\n",
- device->name, cur_port);
- goto error_device_open;
+ device->name, i);
+ goto error;
}
- if (ib_agent_port_open(device, cur_port)) {
+ if (ib_agent_port_open(device, i)) {
printk(KERN_ERR PFX "Couldn't open %s port %d "
"for agents\n",
- device->name, cur_port);
- goto error_device_open;
+ device->name, i);
+ goto error_agent;
}
}
return;
-error_device_open:
- while (i > 0) {
- cur_port--;
- if (ib_agent_port_close(device, cur_port))
+error_agent:
+ if (ib_mad_port_close(device, i))
+ printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+ device->name, i);
+
+error:
+ i--;
+
+ while (i >= start) {
+ if (ib_agent_port_close(device, i))
printk(KERN_ERR PFX "Couldn't close %s port %d "
"for agents\n",
- device->name, cur_port);
- if (ib_mad_port_close(device, cur_port))
+ device->name, i);
+ if (ib_mad_port_close(device, i))
printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, cur_port);
+ device->name, i);
i--;
}
}
@@ -2753,7 +2717,6 @@ static int __init ib_mad_init_module(void)
int ret;
spin_lock_init(&ib_mad_port_list_lock);
- spin_lock_init(&ib_agent_port_list_lock);
ib_mad_cache = kmem_cache_create("ib_mad",
sizeof(struct ib_mad_private),
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 568da10b05ab..570f78682af3 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -40,8 +40,8 @@
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
#define PFX "ib_mad: "
@@ -118,10 +118,11 @@ struct ib_mad_send_wr_private {
struct ib_mad_list_head mad_list;
struct list_head agent_list;
struct ib_mad_agent_private *mad_agent_priv;
+ struct ib_mad_send_buf send_buf;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
struct ib_send_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
- u64 wr_id; /* client WR ID */
- u64 tid;
+ __be64 tid;
unsigned long timeout;
int retries;
int retry;
@@ -141,10 +142,7 @@ struct ib_mad_local_private {
struct list_head completion_list;
struct ib_mad_private *mad_priv;
struct ib_mad_agent_private *recv_mad_agent;
- struct ib_send_wr send_wr;
- struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
- u64 wr_id; /* client WR ID */
- u64 tid;
+ struct ib_mad_send_wr_private *mad_send_wr;
};
struct ib_mad_mgmt_method_table {
@@ -210,7 +208,7 @@ extern kmem_cache_t *ib_mad_cache;
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
struct ib_mad_send_wr_private *
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid);
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid);
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc);
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index 8f1eb80e421f..3249e1d8c07b 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -61,7 +61,7 @@ struct mad_rmpp_recv {
int seg_num;
int newwin;
- u64 tid;
+ __be64 tid;
u32 src_qp;
u16 slid;
u8 mgmt_class;
@@ -100,6 +100,119 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
}
}
+static int data_offset(u8 mgmt_class)
+{
+ if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
+ return IB_MGMT_SA_HDR;
+ else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+ (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
+ return IB_MGMT_VENDOR_HDR;
+ else
+ return IB_MGMT_RMPP_HDR;
+}
+
+static void format_ack(struct ib_rmpp_mad *ack,
+ struct ib_rmpp_mad *data,
+ struct mad_rmpp_recv *rmpp_recv)
+{
+ unsigned long flags;
+
+ memcpy(&ack->mad_hdr, &data->mad_hdr,
+ data_offset(data->mad_hdr.mgmt_class));
+
+ ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+ ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
+ ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+
+ spin_lock_irqsave(&rmpp_recv->lock, flags);
+ rmpp_recv->last_ack = rmpp_recv->seg_num;
+ ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
+ ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
+ spin_unlock_irqrestore(&rmpp_recv->lock, flags);
+}
+
+static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
+ struct ib_mad_recv_wc *recv_wc)
+{
+ struct ib_mad_send_buf *msg;
+ int ret;
+
+ msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
+ recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR,
+ IB_MGMT_RMPP_DATA, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad,
+ rmpp_recv);
+ msg->ah = rmpp_recv->ah;
+ ret = ib_post_send_mad(msg, NULL);
+ if (ret)
+ ib_free_send_mad(msg);
+}
+
+static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
+ struct ib_mad_recv_wc *recv_wc)
+{
+ struct ib_mad_send_buf *msg;
+ struct ib_ah *ah;
+
+ ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
+ recv_wc->recv_buf.grh, agent->port_num);
+ if (IS_ERR(ah))
+ return (void *) ah;
+
+ msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
+ recv_wc->wc->pkey_index, 1,
+ IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA,
+ GFP_KERNEL);
+ if (IS_ERR(msg))
+ ib_destroy_ah(ah);
+ else
+ msg->ah = ah;
+
+ return msg;
+}
+
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc)
+{
+ struct ib_rmpp_mad *rmpp_mad = mad_send_wc->send_buf->mad;
+
+ if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_ACK)
+ ib_destroy_ah(mad_send_wc->send_buf->ah);
+ ib_free_send_mad(mad_send_wc->send_buf);
+}
+
+static void nack_recv(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *recv_wc, u8 rmpp_status)
+{
+ struct ib_mad_send_buf *msg;
+ struct ib_rmpp_mad *rmpp_mad;
+ int ret;
+
+ msg = alloc_response_msg(&agent->agent, recv_wc);
+ if (IS_ERR(msg))
+ return;
+
+ rmpp_mad = msg->mad;
+ memcpy(rmpp_mad, recv_wc->recv_buf.mad,
+ data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
+
+ rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
+ rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION;
+ rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ABORT;
+ ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
+ rmpp_mad->rmpp_hdr.rmpp_status = rmpp_status;
+ rmpp_mad->rmpp_hdr.seg_num = 0;
+ rmpp_mad->rmpp_hdr.paylen_newwin = 0;
+
+ ret = ib_post_send_mad(msg, NULL);
+ if (ret) {
+ ib_destroy_ah(msg->ah);
+ ib_free_send_mad(msg);
+ }
+}
+
static void recv_timeout_handler(void *data)
{
struct mad_rmpp_recv *rmpp_recv = data;
@@ -115,8 +228,8 @@ static void recv_timeout_handler(void *data)
list_del(&rmpp_recv->list);
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
- /* TODO: send abort. */
rmpp_wc = rmpp_recv->rmpp_wc;
+ nack_recv(rmpp_recv->agent, rmpp_wc, IB_MGMT_RMPP_STATUS_T2L);
destroy_rmpp_recv(rmpp_recv);
ib_free_recv_mad(rmpp_wc);
}
@@ -230,60 +343,6 @@ insert_rmpp_recv(struct ib_mad_agent_private *agent,
return cur_rmpp_recv;
}
-static int data_offset(u8 mgmt_class)
-{
- if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
- return offsetof(struct ib_sa_mad, data);
- else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
- (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
- return offsetof(struct ib_vendor_mad, data);
- else
- return offsetof(struct ib_rmpp_mad, data);
-}
-
-static void format_ack(struct ib_rmpp_mad *ack,
- struct ib_rmpp_mad *data,
- struct mad_rmpp_recv *rmpp_recv)
-{
- unsigned long flags;
-
- memcpy(&ack->mad_hdr, &data->mad_hdr,
- data_offset(data->mad_hdr.mgmt_class));
-
- ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
- ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
- ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
-
- spin_lock_irqsave(&rmpp_recv->lock, flags);
- rmpp_recv->last_ack = rmpp_recv->seg_num;
- ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
- ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
- spin_unlock_irqrestore(&rmpp_recv->lock, flags);
-}
-
-static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
- struct ib_mad_recv_wc *recv_wc)
-{
- struct ib_mad_send_buf *msg;
- struct ib_send_wr *bad_send_wr;
- int hdr_len, ret;
-
- hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
- msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
- recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
- hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
- GFP_KERNEL);
- if (!msg)
- return;
-
- format_ack((struct ib_rmpp_mad *) msg->mad,
- (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
- ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
- &bad_send_wr);
- if (ret)
- ib_free_send_mad(msg);
-}
-
static inline int get_last_flag(struct ib_mad_recv_buf *seg)
{
struct ib_rmpp_mad *rmpp_mad;
@@ -351,8 +410,8 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv)
hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class);
data_size = sizeof(struct ib_rmpp_mad) - hdr_size;
- pad = data_size - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
- if (pad > data_size || pad < 0)
+ pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
+ if (pad > IB_MGMT_RMPP_DATA || pad < 0)
pad = 0;
return hdr_size + rmpp_recv->seg_num * data_size - pad;
@@ -522,17 +581,17 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
{
struct ib_rmpp_mad *rmpp_mad;
int timeout;
+ u32 paylen;
- rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+ rmpp_mad = mad_send_wr->send_buf.mad;
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num);
if (mad_send_wr->seg_num == 1) {
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST;
- rmpp_mad->rmpp_hdr.paylen_newwin =
- cpu_to_be32(mad_send_wr->total_seg *
- (sizeof(struct ib_rmpp_mad) -
- offsetof(struct ib_rmpp_mad, data)));
+ paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA -
+ mad_send_wr->pad;
+ rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
} else {
mad_send_wr->send_wr.num_sge = 2;
@@ -541,24 +600,51 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
mad_send_wr->data_offset;
mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
+ rmpp_mad->rmpp_hdr.paylen_newwin = 0;
}
if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST;
- rmpp_mad->rmpp_hdr.paylen_newwin =
- cpu_to_be32(sizeof(struct ib_rmpp_mad) -
- offsetof(struct ib_rmpp_mad, data) -
- mad_send_wr->pad);
+ paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad;
+ rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen);
}
/* 2 seconds for an ACK until we can find the packet lifetime */
- timeout = mad_send_wr->send_wr.wr.ud.timeout_ms;
+ timeout = mad_send_wr->send_buf.timeout_ms;
if (!timeout || timeout > 2000)
mad_send_wr->timeout = msecs_to_jiffies(2000);
mad_send_wr->seg_num++;
return ib_send_mad(mad_send_wr);
}
+static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
+ u8 rmpp_status)
+{
+ struct ib_mad_send_wr_private *mad_send_wr;
+ struct ib_mad_send_wc wc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&agent->lock, flags);
+ mad_send_wr = ib_find_send_mad(agent, tid);
+ if (!mad_send_wr)
+ goto out; /* Unmatched send */
+
+ if ((mad_send_wr->last_ack == mad_send_wr->total_seg) ||
+ (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
+ goto out; /* Send is already done */
+
+ ib_mark_mad_done(mad_send_wr);
+ spin_unlock_irqrestore(&agent->lock, flags);
+
+ wc.status = IB_WC_REM_ABORT_ERR;
+ wc.vendor_err = rmpp_status;
+ wc.send_buf = &mad_send_wr->send_buf;
+ ib_mad_complete_send_wr(mad_send_wr, &wc);
+ return;
+out:
+ spin_unlock_irqrestore(&agent->lock, flags);
+}
+
static void process_rmpp_ack(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
{
@@ -568,11 +654,21 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
int seg_num, newwin, ret;
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
- if (rmpp_mad->rmpp_hdr.rmpp_status)
+ if (rmpp_mad->rmpp_hdr.rmpp_status) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
return;
+ }
seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
+ if (newwin < seg_num) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_W2S);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
+ return;
+ }
spin_lock_irqsave(&agent->lock, flags);
mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
@@ -583,20 +679,25 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
(!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
goto out; /* Send is already done */
- if (seg_num > mad_send_wr->total_seg)
- goto out; /* Bad ACK */
+ if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) {
+ spin_unlock_irqrestore(&agent->lock, flags);
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_S2B);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
+ return;
+ }
if (newwin < mad_send_wr->newwin || seg_num < mad_send_wr->last_ack)
goto out; /* Old ACK */
if (seg_num > mad_send_wr->last_ack) {
mad_send_wr->last_ack = seg_num;
- mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
+ mad_send_wr->retries = mad_send_wr->send_buf.retries;
}
mad_send_wr->newwin = newwin;
if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
/* If no response is expected, the ACK completes the send */
- if (!mad_send_wr->send_wr.wr.ud.timeout_ms) {
+ if (!mad_send_wr->send_buf.timeout_ms) {
struct ib_mad_send_wc wc;
ib_mark_mad_done(mad_send_wr);
@@ -604,13 +705,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
wc.status = IB_WC_SUCCESS;
wc.vendor_err = 0;
- wc.wr_id = mad_send_wr->wr_id;
+ wc.send_buf = &mad_send_wr->send_buf;
ib_mad_complete_send_wr(mad_send_wr, &wc);
return;
}
if (mad_send_wr->refcount == 1)
- ib_reset_mad_timeout(mad_send_wr, mad_send_wr->
- send_wr.wr.ud.timeout_ms);
+ ib_reset_mad_timeout(mad_send_wr,
+ mad_send_wr->send_buf.timeout_ms);
} else if (mad_send_wr->refcount == 1 &&
mad_send_wr->seg_num < mad_send_wr->newwin &&
mad_send_wr->seg_num <= mad_send_wr->total_seg) {
@@ -628,6 +729,72 @@ out:
spin_unlock_irqrestore(&agent->lock, flags);
}
+static struct ib_mad_recv_wc *
+process_rmpp_data(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_hdr *rmpp_hdr;
+ u8 rmpp_status;
+
+ rmpp_hdr = &((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr;
+
+ if (rmpp_hdr->rmpp_status) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_STATUS;
+ goto bad;
+ }
+
+ if (rmpp_hdr->seg_num == __constant_htonl(1)) {
+ if (!(ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST)) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+ goto bad;
+ }
+ return start_rmpp(agent, mad_recv_wc);
+ } else {
+ if (ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST) {
+ rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
+ goto bad;
+ }
+ return continue_rmpp(agent, mad_recv_wc);
+ }
+bad:
+ nack_recv(agent, mad_recv_wc, rmpp_status);
+ ib_free_recv_mad(mad_recv_wc);
+ return NULL;
+}
+
+static void process_rmpp_stop(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_mad *rmpp_mad;
+
+ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+ if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ } else
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ rmpp_mad->rmpp_hdr.rmpp_status);
+}
+
+static void process_rmpp_abort(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ struct ib_rmpp_mad *rmpp_mad;
+
+ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+ if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN ||
+ rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ } else
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ rmpp_mad->rmpp_hdr.rmpp_status);
+}
+
struct ib_mad_recv_wc *
ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
@@ -638,23 +805,29 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
if (!(rmpp_mad->rmpp_hdr.rmpp_rtime_flags & IB_MGMT_RMPP_FLAG_ACTIVE))
return mad_recv_wc;
- if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION)
+ if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_UNV);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
goto out;
+ }
switch (rmpp_mad->rmpp_hdr.rmpp_type) {
case IB_MGMT_RMPP_TYPE_DATA:
- if (rmpp_mad->rmpp_hdr.seg_num == __constant_htonl(1))
- return start_rmpp(agent, mad_recv_wc);
- else
- return continue_rmpp(agent, mad_recv_wc);
+ return process_rmpp_data(agent, mad_recv_wc);
case IB_MGMT_RMPP_TYPE_ACK:
process_rmpp_ack(agent, mad_recv_wc);
break;
case IB_MGMT_RMPP_TYPE_STOP:
+ process_rmpp_stop(agent, mad_recv_wc);
+ break;
case IB_MGMT_RMPP_TYPE_ABORT:
- /* TODO: process_rmpp_nack(agent, mad_recv_wc); */
+ process_rmpp_abort(agent, mad_recv_wc);
break;
default:
+ abort_send(agent, rmpp_mad->mad_hdr.tid,
+ IB_MGMT_RMPP_STATUS_BADT);
+ nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
break;
}
out:
@@ -667,7 +840,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
struct ib_rmpp_mad *rmpp_mad;
int i, total_len, ret;
- rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+ rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED;
@@ -688,7 +861,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
(sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
- mad_send_wr->pad = total_len - offsetof(struct ib_rmpp_mad, data) -
+ mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR -
be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
/* We need to wait for the final ACK even if there isn't a response */
@@ -703,20 +876,15 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc)
{
struct ib_rmpp_mad *rmpp_mad;
- struct ib_mad_send_buf *msg;
int ret;
- rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+ rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
- if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
- msg = (struct ib_mad_send_buf *) (unsigned long)
- mad_send_wc->wr_id;
- ib_free_send_mad(msg);
+ if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */
- }
if (mad_send_wc->status != IB_WC_SUCCESS ||
mad_send_wr->status != IB_WC_SUCCESS)
@@ -727,7 +895,7 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
mad_send_wr->timeout =
- msecs_to_jiffies(mad_send_wr->send_wr.wr.ud.timeout_ms);
+ msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
return IB_RMPP_RESULT_PROCESSED; /* Send done */
}
@@ -748,7 +916,7 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr)
struct ib_rmpp_mad *rmpp_mad;
int ret;
- rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+ rmpp_mad = mad_send_wr->send_buf.mad;
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE))
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
diff --git a/drivers/infiniband/core/mad_rmpp.h b/drivers/infiniband/core/mad_rmpp.h
index c4924dfb8e75..f0616fd22494 100644
--- a/drivers/infiniband/core/mad_rmpp.h
+++ b/drivers/infiniband/core/mad_rmpp.h
@@ -51,6 +51,8 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc);
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc);
+
void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent);
int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr);
diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c
index eb5ff54c10d7..35df5010e723 100644
--- a/drivers/infiniband/core/packer.c
+++ b/drivers/infiniband/core/packer.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -32,7 +33,7 @@
* $Id: packer.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
static u64 value_read(int offset, int size, void *structure)
{
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 795184931c83..acda7d63d6fe 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, 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
@@ -43,9 +43,10 @@
#include <linux/dma-mapping.h>
#include <linux/kref.h>
#include <linux/idr.h>
+#include <linux/workqueue.h>
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -73,11 +74,10 @@ struct ib_sa_device {
struct ib_sa_query {
void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
void (*release)(struct ib_sa_query *);
- struct ib_sa_port *port;
- struct ib_sa_mad *mad;
- struct ib_sa_sm_ah *sm_ah;
- DECLARE_PCI_UNMAP_ADDR(mapping)
- int id;
+ struct ib_sa_port *port;
+ struct ib_mad_send_buf *mad_buf;
+ struct ib_sa_sm_ah *sm_ah;
+ int id;
};
struct ib_sa_service_query {
@@ -113,32 +113,6 @@ static DEFINE_IDR(query_idr);
static spinlock_t tid_lock;
static u32 tid;
-enum {
- IB_SA_ATTR_CLASS_PORTINFO = 0x01,
- IB_SA_ATTR_NOTICE = 0x02,
- IB_SA_ATTR_INFORM_INFO = 0x03,
- IB_SA_ATTR_NODE_REC = 0x11,
- IB_SA_ATTR_PORT_INFO_REC = 0x12,
- IB_SA_ATTR_SL2VL_REC = 0x13,
- IB_SA_ATTR_SWITCH_REC = 0x14,
- IB_SA_ATTR_LINEAR_FDB_REC = 0x15,
- IB_SA_ATTR_RANDOM_FDB_REC = 0x16,
- IB_SA_ATTR_MCAST_FDB_REC = 0x17,
- IB_SA_ATTR_SM_INFO_REC = 0x18,
- IB_SA_ATTR_LINK_REC = 0x20,
- IB_SA_ATTR_GUID_INFO_REC = 0x30,
- IB_SA_ATTR_SERVICE_REC = 0x31,
- IB_SA_ATTR_PARTITION_REC = 0x33,
- IB_SA_ATTR_RANGE_REC = 0x34,
- IB_SA_ATTR_PATH_REC = 0x35,
- IB_SA_ATTR_VL_ARB_REC = 0x36,
- IB_SA_ATTR_MC_GROUP_REC = 0x37,
- IB_SA_ATTR_MC_MEMBER_REC = 0x38,
- IB_SA_ATTR_TRACE_REC = 0x39,
- IB_SA_ATTR_MULTI_PATH_REC = 0x3a,
- IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b
-};
-
#define PATH_REC_FIELD(field) \
.struct_offset_bytes = offsetof(struct ib_sa_path_rec, field), \
.struct_size_bytes = sizeof ((struct ib_sa_path_rec *) 0)->field, \
@@ -431,8 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
event->event == IB_EVENT_LID_CHANGE ||
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_SM_CHANGE) {
- struct ib_sa_device *sa_dev =
- ib_get_client_data(event->device, &sa_client);
+ struct ib_sa_device *sa_dev;
+ sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
schedule_work(&sa_dev->port[event->element.port_num -
sa_dev->start_port].update_task);
@@ -452,6 +426,7 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
{
unsigned long flags;
struct ib_mad_agent *agent;
+ struct ib_mad_send_buf *mad_buf;
spin_lock_irqsave(&idr_lock, flags);
if (idr_find(&query_idr, id) != query) {
@@ -459,9 +434,10 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
return;
}
agent = query->port->agent;
+ mad_buf = query->mad_buf;
spin_unlock_irqrestore(&idr_lock, flags);
- ib_cancel_mad(agent, id);
+ ib_cancel_mad(agent, mad_buf);
}
EXPORT_SYMBOL(ib_sa_cancel_query);
@@ -483,71 +459,46 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
static int send_mad(struct ib_sa_query *query, int timeout_ms)
{
- struct ib_sa_port *port = query->port;
unsigned long flags;
- int ret;
- struct ib_sge gather_list;
- struct ib_send_wr *bad_wr, wr = {
- .opcode = IB_WR_SEND,
- .sg_list = &gather_list,
- .num_sge = 1,
- .send_flags = IB_SEND_SIGNALED,
- .wr = {
- .ud = {
- .mad_hdr = &query->mad->mad_hdr,
- .remote_qpn = 1,
- .remote_qkey = IB_QP1_QKEY,
- .timeout_ms = timeout_ms,
- }
- }
- };
+ int ret, id;
retry:
if (!idr_pre_get(&query_idr, GFP_ATOMIC))
return -ENOMEM;
spin_lock_irqsave(&idr_lock, flags);
- ret = idr_get_new(&query_idr, query, &query->id);
+ ret = idr_get_new(&query_idr, query, &id);
spin_unlock_irqrestore(&idr_lock, flags);
if (ret == -EAGAIN)
goto retry;
if (ret)
return ret;
- wr.wr_id = query->id;
+ query->mad_buf->timeout_ms = timeout_ms;
+ query->mad_buf->context[0] = query;
+ query->id = id;
- spin_lock_irqsave(&port->ah_lock, flags);
- kref_get(&port->sm_ah->ref);
- query->sm_ah = port->sm_ah;
- wr.wr.ud.ah = port->sm_ah->ah;
- spin_unlock_irqrestore(&port->ah_lock, flags);
+ spin_lock_irqsave(&query->port->ah_lock, flags);
+ kref_get(&query->port->sm_ah->ref);
+ query->sm_ah = query->port->sm_ah;
+ spin_unlock_irqrestore(&query->port->ah_lock, flags);
- gather_list.addr = dma_map_single(port->agent->device->dma_device,
- query->mad,
- sizeof (struct ib_sa_mad),
- DMA_TO_DEVICE);
- gather_list.length = sizeof (struct ib_sa_mad);
- gather_list.lkey = port->agent->mr->lkey;
- pci_unmap_addr_set(query, mapping, gather_list.addr);
+ query->mad_buf->ah = query->sm_ah->ah;
- ret = ib_post_send_mad(port->agent, &wr, &bad_wr);
+ ret = ib_post_send_mad(query->mad_buf, NULL);
if (ret) {
- dma_unmap_single(port->agent->device->dma_device,
- pci_unmap_addr(query, mapping),
- sizeof (struct ib_sa_mad),
- DMA_TO_DEVICE);
- kref_put(&query->sm_ah->ref, free_sm_ah);
spin_lock_irqsave(&idr_lock, flags);
- idr_remove(&query_idr, query->id);
+ idr_remove(&query_idr, id);
spin_unlock_irqrestore(&idr_lock, flags);
+
+ kref_put(&query->sm_ah->ref, free_sm_ah);
}
/*
* It's not safe to dereference query any more, because the
* send may already have completed and freed the query in
- * another context. So use wr.wr_id, which has a copy of the
- * query's id.
+ * another context.
*/
- return ret ? ret : wr.wr_id;
+ return ret ? ret : id;
}
static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
@@ -569,7 +520,6 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
{
- kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
}
@@ -600,7 +550,7 @@ static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
struct ib_sa_path_rec *rec,
ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
+ int timeout_ms, gfp_t gfp_mask,
void (*callback)(int status,
struct ib_sa_path_rec *resp,
void *context),
@@ -609,44 +559,59 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
{
struct ib_sa_path_query *query;
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
- struct ib_sa_port *port = &sa_dev->port[port_num - sa_dev->start_port];
- struct ib_mad_agent *agent = port->agent;
+ struct ib_sa_port *port;
+ struct ib_mad_agent *agent;
+ struct ib_sa_mad *mad;
int ret;
+ if (!sa_dev)
+ return -ENODEV;
+
+ port = &sa_dev->port[port_num - sa_dev->start_port];
+ agent = port->agent;
+
query = kmalloc(sizeof *query, gfp_mask);
if (!query)
return -ENOMEM;
- query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
- if (!query->sa_query.mad) {
- kfree(query);
- return -ENOMEM;
+
+ query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+ 0, IB_MGMT_SA_HDR,
+ IB_MGMT_SA_DATA, gfp_mask);
+ if (!query->sa_query.mad_buf) {
+ ret = -ENOMEM;
+ goto err1;
}
query->callback = callback;
query->context = context;
- init_mad(query->sa_query.mad, agent);
+ mad = query->sa_query.mad_buf->mad;
+ init_mad(mad, agent);
- query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
- query->sa_query.release = ib_sa_path_rec_release;
- query->sa_query.port = port;
- query->sa_query.mad->mad_hdr.method = IB_MGMT_METHOD_GET;
- query->sa_query.mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);
- query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+ query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
+ query->sa_query.release = ib_sa_path_rec_release;
+ query->sa_query.port = port;
+ mad->mad_hdr.method = IB_MGMT_METHOD_GET;
+ mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);
+ mad->sa_hdr.comp_mask = comp_mask;
- ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
- rec, query->sa_query.mad->data);
+ ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
*sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms);
- if (ret < 0) {
- *sa_query = NULL;
- kfree(query->sa_query.mad);
- kfree(query);
- }
+ if (ret < 0)
+ goto err2;
return ret;
+
+err2:
+ *sa_query = NULL;
+ ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+ kfree(query);
+ return ret;
}
EXPORT_SYMBOL(ib_sa_path_rec_get);
@@ -669,7 +634,6 @@ static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
{
- kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
}
@@ -702,7 +666,7 @@ static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
struct ib_sa_service_rec *rec,
ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
+ int timeout_ms, gfp_t gfp_mask,
void (*callback)(int status,
struct ib_sa_service_rec *resp,
void *context),
@@ -711,10 +675,17 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
{
struct ib_sa_service_query *query;
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
- struct ib_sa_port *port = &sa_dev->port[port_num - sa_dev->start_port];
- struct ib_mad_agent *agent = port->agent;
+ struct ib_sa_port *port;
+ struct ib_mad_agent *agent;
+ struct ib_sa_mad *mad;
int ret;
+ if (!sa_dev)
+ return -ENODEV;
+
+ port = &sa_dev->port[port_num - sa_dev->start_port];
+ agent = port->agent;
+
if (method != IB_MGMT_METHOD_GET &&
method != IB_MGMT_METHOD_SET &&
method != IB_SA_METHOD_DELETE)
@@ -723,37 +694,45 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
query = kmalloc(sizeof *query, gfp_mask);
if (!query)
return -ENOMEM;
- query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
- if (!query->sa_query.mad) {
- kfree(query);
- return -ENOMEM;
+
+ query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+ 0, IB_MGMT_SA_HDR,
+ IB_MGMT_SA_DATA, gfp_mask);
+ if (!query->sa_query.mad_buf) {
+ ret = -ENOMEM;
+ goto err1;
}
query->callback = callback;
query->context = context;
- init_mad(query->sa_query.mad, agent);
+ mad = query->sa_query.mad_buf->mad;
+ init_mad(mad, agent);
- query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
- query->sa_query.release = ib_sa_service_rec_release;
- query->sa_query.port = port;
- query->sa_query.mad->mad_hdr.method = method;
- query->sa_query.mad->mad_hdr.attr_id =
- cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
- query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+ query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
+ query->sa_query.release = ib_sa_service_rec_release;
+ query->sa_query.port = port;
+ mad->mad_hdr.method = method;
+ mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
+ mad->sa_hdr.comp_mask = comp_mask;
ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
- rec, query->sa_query.mad->data);
+ rec, mad->data);
*sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms);
- if (ret < 0) {
- *sa_query = NULL;
- kfree(query->sa_query.mad);
- kfree(query);
- }
+ if (ret < 0)
+ goto err2;
+
+ return ret;
+
+err2:
+ *sa_query = NULL;
+ ib_free_send_mad(query->sa_query.mad_buf);
+err1:
+ kfree(query);
return ret;
}
EXPORT_SYMBOL(ib_sa_service_rec_query);
@@ -777,7 +756,6 @@ static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
{
- kfree(sa_query->mad);
kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
}
@@ -785,7 +763,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
u8 method,
struct ib_sa_mcmember_rec *rec,
ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
+ int timeout_ms, gfp_t gfp_mask,
void (*callback)(int status,
struct ib_sa_mcmember_rec *resp,
void *context),
@@ -794,60 +772,69 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
{
struct ib_sa_mcmember_query *query;
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
- struct ib_sa_port *port = &sa_dev->port[port_num - sa_dev->start_port];
- struct ib_mad_agent *agent = port->agent;
+ struct ib_sa_port *port;
+ struct ib_mad_agent *agent;
+ struct ib_sa_mad *mad;
int ret;
+ if (!sa_dev)
+ return -ENODEV;
+
+ port = &sa_dev->port[port_num - sa_dev->start_port];
+ agent = port->agent;
+
query = kmalloc(sizeof *query, gfp_mask);
if (!query)
return -ENOMEM;
- query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
- if (!query->sa_query.mad) {
- kfree(query);
- return -ENOMEM;
+
+ query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+ 0, IB_MGMT_SA_HDR,
+ IB_MGMT_SA_DATA, gfp_mask);
+ if (!query->sa_query.mad_buf) {
+ ret = -ENOMEM;
+ goto err1;
}
query->callback = callback;
query->context = context;
- init_mad(query->sa_query.mad, agent);
+ mad = query->sa_query.mad_buf->mad;
+ init_mad(mad, agent);
- query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
- query->sa_query.release = ib_sa_mcmember_rec_release;
- query->sa_query.port = port;
- query->sa_query.mad->mad_hdr.method = method;
- query->sa_query.mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
- query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+ query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
+ query->sa_query.release = ib_sa_mcmember_rec_release;
+ query->sa_query.port = port;
+ mad->mad_hdr.method = method;
+ mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
+ mad->sa_hdr.comp_mask = comp_mask;
ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
- rec, query->sa_query.mad->data);
+ rec, mad->data);
*sa_query = &query->sa_query;
ret = send_mad(&query->sa_query, timeout_ms);
- if (ret < 0) {
- *sa_query = NULL;
- kfree(query->sa_query.mad);
- kfree(query);
- }
+ if (ret < 0)
+ goto err2;
return ret;
+
+err2:
+ *sa_query = NULL;
+ ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+ kfree(query);
+ return ret;
}
EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc)
{
- struct ib_sa_query *query;
+ struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
unsigned long flags;
- spin_lock_irqsave(&idr_lock, flags);
- query = idr_find(&query_idr, mad_send_wc->wr_id);
- spin_unlock_irqrestore(&idr_lock, flags);
-
- if (!query)
- return;
-
if (query->callback)
switch (mad_send_wc->status) {
case IB_WC_SUCCESS:
@@ -864,30 +851,25 @@ static void send_handler(struct ib_mad_agent *agent,
break;
}
- dma_unmap_single(agent->device->dma_device,
- pci_unmap_addr(query, mapping),
- sizeof (struct ib_sa_mad),
- DMA_TO_DEVICE);
- kref_put(&query->sm_ah->ref, free_sm_ah);
-
- query->release(query);
-
spin_lock_irqsave(&idr_lock, flags);
- idr_remove(&query_idr, mad_send_wc->wr_id);
+ idr_remove(&query_idr, query->id);
spin_unlock_irqrestore(&idr_lock, flags);
+
+ ib_free_send_mad(mad_send_wc->send_buf);
+ kref_put(&query->sm_ah->ref, free_sm_ah);
+ query->release(query);
}
static void recv_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_recv_wc *mad_recv_wc)
{
struct ib_sa_query *query;
- unsigned long flags;
+ struct ib_mad_send_buf *mad_buf;
- spin_lock_irqsave(&idr_lock, flags);
- query = idr_find(&query_idr, mad_recv_wc->wc->wr_id);
- spin_unlock_irqrestore(&idr_lock, flags);
+ mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
+ query = mad_buf->context[0];
- if (query && query->callback) {
+ if (query->callback) {
if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
query->callback(query,
mad_recv_wc->recv_buf.mad->mad_hdr.status ?
@@ -1001,6 +983,7 @@ static int __init ib_sa_init(void)
static void __exit ib_sa_cleanup(void)
{
ib_unregister_client(&sa_client);
+ idr_destroy(&query_idr);
}
module_init(ib_sa_init);
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index b4b284324a33..35852e794e26 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -36,7 +37,7 @@
* $Id: smi.c 1389 2004-12-27 22:56:47Z roland $
*/
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
#include "smi.h"
/*
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
index db25503a0736..2b3c40198f81 100644
--- a/drivers/infiniband/core/smi.h
+++ b/drivers/infiniband/core/smi.h
@@ -39,6 +39,8 @@
#ifndef __SMI_H_
#define __SMI_H_
+#include <rdma/ib_smi.h>
+
int smi_handle_dr_smp_recv(struct ib_smp *smp,
u8 node_type,
int port_num,
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 90d51b179abe..b8120650e711 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -34,7 +36,7 @@
#include "core_priv.h"
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
struct ib_port {
struct kobject kobj;
@@ -63,6 +65,11 @@ struct port_table_attribute {
int index;
};
+static inline int ibdev_is_alive(const struct ib_device *dev)
+{
+ return dev->reg_state == IB_DEV_REGISTERED;
+}
+
static ssize_t port_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -72,6 +79,8 @@ static ssize_t port_attr_show(struct kobject *kobj,
if (!port_attr->show)
return -EIO;
+ if (!ibdev_is_alive(p->ibdev))
+ return -ENODEV;
return port_attr->show(p, port_attr, buf);
}
@@ -253,14 +262,14 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) gid.raw)[0]),
- be16_to_cpu(((u16 *) gid.raw)[1]),
- be16_to_cpu(((u16 *) gid.raw)[2]),
- be16_to_cpu(((u16 *) gid.raw)[3]),
- be16_to_cpu(((u16 *) gid.raw)[4]),
- be16_to_cpu(((u16 *) gid.raw)[5]),
- be16_to_cpu(((u16 *) gid.raw)[6]),
- be16_to_cpu(((u16 *) gid.raw)[7]));
+ be16_to_cpu(((__be16 *) gid.raw)[0]),
+ be16_to_cpu(((__be16 *) gid.raw)[1]),
+ be16_to_cpu(((__be16 *) gid.raw)[2]),
+ be16_to_cpu(((__be16 *) gid.raw)[3]),
+ be16_to_cpu(((__be16 *) gid.raw)[4]),
+ be16_to_cpu(((__be16 *) gid.raw)[5]),
+ be16_to_cpu(((__be16 *) gid.raw)[6]),
+ be16_to_cpu(((__be16 *) gid.raw)[7]));
}
static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
@@ -298,14 +307,13 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
if (!p->ibdev->process_mad)
return sprintf(buf, "N/A (no PMA)\n");
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
if (!in_mad || !out_mad) {
ret = -ENOMEM;
goto out;
}
- memset(in_mad, 0, sizeof *in_mad);
in_mad->mad_hdr.base_version = 1;
in_mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_PERF_MGMT;
in_mad->mad_hdr.class_version = 1;
@@ -332,11 +340,11 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
break;
case 16:
ret = sprintf(buf, "%u\n",
- be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8)));
+ be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
break;
case 32:
ret = sprintf(buf, "%u\n",
- be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8)));
+ be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
break;
default:
ret = 0;
@@ -461,7 +469,7 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
return NULL;
for (i = 0; i < len; i++) {
- element = kcalloc(1, sizeof(struct port_table_attribute),
+ element = kzalloc(sizeof(struct port_table_attribute),
GFP_KERNEL);
if (!element)
goto err;
@@ -499,10 +507,9 @@ static int add_port(struct ib_device *device, int port_num)
if (ret)
return ret;
- p = kmalloc(sizeof *p, GFP_KERNEL);
+ p = kzalloc(sizeof *p, GFP_KERNEL);
if (!p)
return -ENOMEM;
- memset(p, 0, sizeof *p);
p->ibdev = device;
p->port_num = port_num;
@@ -579,6 +586,9 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf)
{
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
+ if (!ibdev_is_alive(dev))
+ return -ENODEV;
+
switch (dev->node_type) {
case IB_NODE_CA: return sprintf(buf, "%d: CA\n", dev->node_type);
case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
@@ -593,15 +603,18 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
struct ib_device_attr attr;
ssize_t ret;
+ if (!ibdev_is_alive(dev))
+ return -ENODEV;
+
ret = ib_query_device(dev, &attr);
if (ret)
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]),
- be16_to_cpu(((u16 *) &attr.sys_image_guid)[3]));
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
}
static ssize_t show_node_guid(struct class_device *cdev, char *buf)
@@ -610,15 +623,18 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
struct ib_device_attr attr;
ssize_t ret;
+ if (!ibdev_is_alive(dev))
+ return -ENODEV;
+
ret = ib_query_device(dev, &attr);
if (ret)
return ret;
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
- be16_to_cpu(((u16 *) &attr.node_guid)[0]),
- be16_to_cpu(((u16 *) &attr.node_guid)[1]),
- be16_to_cpu(((u16 *) &attr.node_guid)[2]),
- be16_to_cpu(((u16 *) &attr.node_guid)[3]));
+ be16_to_cpu(((__be16 *) &attr.node_guid)[0]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[1]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[2]),
+ be16_to_cpu(((__be16 *) &attr.node_guid)[3]));
}
static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 61d07c732f49..6e15787d1de1 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation. 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
@@ -40,47 +41,94 @@
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/cdev.h>
+#include <linux/idr.h>
#include <asm/uaccess.h>
-#include "ucm.h"
+#include <rdma/ib_cm.h>
+#include <rdma/ib_user_cm.h>
MODULE_AUTHOR("Libor Michalek");
MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
MODULE_LICENSE("Dual BSD/GPL");
-static int ucm_debug_level;
+struct ib_ucm_device {
+ int devnum;
+ struct cdev dev;
+ struct class_device class_dev;
+ struct ib_device *ib_dev;
+};
+
+struct ib_ucm_file {
+ struct semaphore mutex;
+ struct file *filp;
+ struct ib_ucm_device *device;
+
+ struct list_head ctxs;
+ struct list_head events;
+ wait_queue_head_t poll_wait;
+};
+
+struct ib_ucm_context {
+ int id;
+ wait_queue_head_t wait;
+ atomic_t ref;
+ int events_reported;
+
+ struct ib_ucm_file *file;
+ struct ib_cm_id *cm_id;
+ __u64 uid;
+
+ struct list_head events; /* list of pending events. */
+ struct list_head file_list; /* member in file ctx list */
+};
+
+struct ib_ucm_event {
+ struct ib_ucm_context *ctx;
+ struct list_head file_list; /* member in file event list */
+ struct list_head ctx_list; /* member in ctx event list */
-module_param_named(debug_level, ucm_debug_level, int, 0644);
-MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+ struct ib_cm_id *cm_id;
+ struct ib_ucm_event_resp resp;
+ void *data;
+ void *info;
+ int data_len;
+ int info_len;
+};
enum {
IB_UCM_MAJOR = 231,
- IB_UCM_MINOR = 255
+ IB_UCM_BASE_MINOR = 224,
+ IB_UCM_MAX_DEVICES = 32
};
-#define IB_UCM_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_MINOR)
+#define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
-#define PFX "UCM: "
+static void ib_ucm_add_one(struct ib_device *device);
+static void ib_ucm_remove_one(struct ib_device *device);
-#define ucm_dbg(format, arg...) \
- do { \
- if (ucm_debug_level > 0) \
- printk(KERN_DEBUG PFX format, ## arg); \
- } while (0)
+static struct ib_client ucm_client = {
+ .name = "ucm",
+ .add = ib_ucm_add_one,
+ .remove = ib_ucm_remove_one
+};
-static struct semaphore ctx_id_mutex;
-static struct idr ctx_id_table;
-static int ctx_id_rover = 0;
+static DECLARE_MUTEX(ctx_id_mutex);
+static DEFINE_IDR(ctx_id_table);
+static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
-static struct ib_ucm_context *ib_ucm_ctx_get(int id)
+static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
{
struct ib_ucm_context *ctx;
down(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, id);
- if (ctx)
- ctx->ref++;
+ if (!ctx)
+ ctx = ERR_PTR(-ENOENT);
+ else if (ctx->file != file)
+ ctx = ERR_PTR(-EINVAL);
+ else
+ atomic_inc(&ctx->ref);
up(&ctx_id_mutex);
return ctx;
@@ -88,21 +136,20 @@ static struct ib_ucm_context *ib_ucm_ctx_get(int id)
static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
{
- struct ib_ucm_event *uevent;
-
- down(&ctx_id_mutex);
-
- ctx->ref--;
- if (!ctx->ref)
- idr_remove(&ctx_id_table, ctx->id);
+ if (atomic_dec_and_test(&ctx->ref))
+ wake_up(&ctx->wait);
+}
- up(&ctx_id_mutex);
+static inline int ib_ucm_new_cm_id(int event)
+{
+ return event == IB_CM_REQ_RECEIVED || event == IB_CM_SIDR_REQ_RECEIVED;
+}
- if (ctx->ref)
- return;
+static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
+{
+ struct ib_ucm_event *uevent;
down(&ctx->file->mutex);
-
list_del(&ctx->file_list);
while (!list_empty(&ctx->events)) {
@@ -112,18 +159,12 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
list_del(&uevent->ctx_list);
/* clear incoming connections. */
- if (uevent->cm_id)
+ if (ib_ucm_new_cm_id(uevent->resp.event))
ib_destroy_cm_id(uevent->cm_id);
kfree(uevent);
}
-
up(&ctx->file->mutex);
-
- ucm_dbg("Destroyed CM ID <%d>\n", ctx->id);
-
- ib_destroy_cm_id(ctx->cm_id);
- kfree(ctx);
}
static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -131,54 +172,44 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
struct ib_ucm_context *ctx;
int result;
- ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx)
return NULL;
- ctx->ref = 1; /* user reference */
+ atomic_set(&ctx->ref, 1);
+ init_waitqueue_head(&ctx->wait);
ctx->file = file;
-
INIT_LIST_HEAD(&ctx->events);
- init_MUTEX(&ctx->mutex);
- list_add_tail(&ctx->file_list, &file->ctxs);
-
- ctx_id_rover = (ctx_id_rover + 1) & INT_MAX;
-retry:
- result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
- if (!result)
- goto error;
+ do {
+ result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
+ if (!result)
+ goto error;
- down(&ctx_id_mutex);
- result = idr_get_new_above(&ctx_id_table, ctx, ctx_id_rover, &ctx->id);
- up(&ctx_id_mutex);
+ down(&ctx_id_mutex);
+ result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
+ up(&ctx_id_mutex);
+ } while (result == -EAGAIN);
- if (result == -EAGAIN)
- goto retry;
if (result)
goto error;
- ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
-
+ list_add_tail(&ctx->file_list, &file->ctxs);
return ctx;
+
error:
- list_del(&ctx->file_list);
kfree(ctx);
-
return NULL;
}
-/*
- * Event portion of the API, handle CM events
- * and allow event polling.
- */
+
static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
struct ib_sa_path_rec *kpath)
{
if (!kpath || !upath)
return;
- memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid));
- memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid));
+ memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
+ memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
upath->dlid = kpath->dlid;
upath->slid = kpath->slid;
@@ -204,8 +235,6 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
struct ib_cm_req_event_param *kreq)
{
- ureq->listen_id = (long)kreq->listen_id->context;
-
ureq->remote_ca_guid = kreq->remote_ca_guid;
ureq->remote_qkey = kreq->remote_qkey;
ureq->remote_qpn = kreq->remote_qpn;
@@ -219,6 +248,7 @@ static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
ureq->retry_count = kreq->retry_count;
ureq->rnr_retry_count = kreq->rnr_retry_count;
ureq->srq = kreq->srq;
+ ureq->port = kreq->port;
ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
@@ -240,37 +270,6 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
urep->srq = krep->srq;
}
-static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej,
- struct ib_cm_rej_event_param *krej)
-{
- urej->reason = krej->reason;
-}
-
-static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra,
- struct ib_cm_mra_event_param *kmra)
-{
- umra->timeout = kmra->service_timeout;
-}
-
-static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap,
- struct ib_cm_lap_event_param *klap)
-{
- ib_ucm_event_path_get(&ulap->path, klap->alternate_path);
-}
-
-static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr,
- struct ib_cm_apr_event_param *kapr)
-{
- uapr->status = kapr->ap_status;
-}
-
-static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq,
- struct ib_cm_sidr_req_event_param *kreq)
-{
- ureq->listen_id = (long)kreq->listen_id->context;
- ureq->pkey = kreq->pkey;
-}
-
static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
struct ib_cm_sidr_rep_event_param *krep)
{
@@ -283,15 +282,13 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
struct ib_ucm_event *uvt)
{
void *info = NULL;
- int result;
switch (evt->event) {
case IB_CM_REQ_RECEIVED:
ib_ucm_event_req_get(&uvt->resp.u.req_resp,
&evt->param.req_rcvd);
uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE;
- uvt->resp.present |= (evt->param.req_rcvd.primary_path ?
- IB_UCM_PRES_PRIMARY : 0);
+ uvt->resp.present = IB_UCM_PRES_PRIMARY;
uvt->resp.present |= (evt->param.req_rcvd.alternate_path ?
IB_UCM_PRES_ALTERNATE : 0);
break;
@@ -299,57 +296,48 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
ib_ucm_event_rep_get(&uvt->resp.u.rep_resp,
&evt->param.rep_rcvd);
uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_RTU_RECEIVED:
uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_DREQ_RECEIVED:
uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_DREP_RECEIVED:
uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE;
uvt->resp.u.send_status = evt->param.send_status;
-
break;
case IB_CM_MRA_RECEIVED:
- ib_ucm_event_mra_get(&uvt->resp.u.mra_resp,
- &evt->param.mra_rcvd);
+ uvt->resp.u.mra_resp.timeout =
+ evt->param.mra_rcvd.service_timeout;
uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_REJ_RECEIVED:
- ib_ucm_event_rej_get(&uvt->resp.u.rej_resp,
- &evt->param.rej_rcvd);
+ uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason;
uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.rej_rcvd.ari_length;
info = evt->param.rej_rcvd.ari;
-
break;
case IB_CM_LAP_RECEIVED:
- ib_ucm_event_lap_get(&uvt->resp.u.lap_resp,
- &evt->param.lap_rcvd);
+ ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
+ evt->param.lap_rcvd.alternate_path);
uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
- uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ?
- IB_UCM_PRES_ALTERNATE : 0);
+ uvt->resp.present = IB_UCM_PRES_ALTERNATE;
break;
case IB_CM_APR_RECEIVED:
- ib_ucm_event_apr_get(&uvt->resp.u.apr_resp,
- &evt->param.apr_rcvd);
+ uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status;
uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.apr_rcvd.info_len;
info = evt->param.apr_rcvd.apr_info;
-
break;
case IB_CM_SIDR_REQ_RECEIVED:
- ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp,
- &evt->param.sidr_req_rcvd);
+ uvt->resp.u.sidr_req_resp.pkey =
+ evt->param.sidr_req_rcvd.pkey;
+ uvt->resp.u.sidr_req_resp.port =
+ evt->param.sidr_req_rcvd.port;
uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
-
break;
case IB_CM_SIDR_REP_RECEIVED:
ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp,
@@ -357,43 +345,35 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
uvt->info_len = evt->param.sidr_rep_rcvd.info_len;
info = evt->param.sidr_rep_rcvd.info;
-
break;
default:
uvt->resp.u.send_status = evt->param.send_status;
-
break;
}
- if (uvt->data_len && evt->private_data) {
-
+ if (uvt->data_len) {
uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
- if (!uvt->data) {
- result = -ENOMEM;
- goto error;
- }
+ if (!uvt->data)
+ goto err1;
memcpy(uvt->data, evt->private_data, uvt->data_len);
uvt->resp.present |= IB_UCM_PRES_DATA;
}
- if (uvt->info_len && info) {
-
+ if (uvt->info_len) {
uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
- if (!uvt->info) {
- result = -ENOMEM;
- goto error;
- }
+ if (!uvt->info)
+ goto err2;
memcpy(uvt->info, info, uvt->info_len);
uvt->resp.present |= IB_UCM_PRES_INFO;
}
-
return 0;
-error:
- kfree(uvt->info);
+
+err2:
kfree(uvt->data);
- return result;
+err1:
+ return -ENOMEM;
}
static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
@@ -402,64 +382,35 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
struct ib_ucm_event *uevent;
struct ib_ucm_context *ctx;
int result = 0;
- int id;
- /*
- * lookup correct context based on event type.
- */
- switch (event->event) {
- case IB_CM_REQ_RECEIVED:
- id = (long)event->param.req_rcvd.listen_id->context;
- break;
- case IB_CM_SIDR_REQ_RECEIVED:
- id = (long)event->param.sidr_req_rcvd.listen_id->context;
- break;
- default:
- id = (long)cm_id->context;
- break;
- }
-
- ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event);
-
- ctx = ib_ucm_ctx_get(id);
- if (!ctx)
- return -ENOENT;
-
- if (event->event == IB_CM_REQ_RECEIVED ||
- event->event == IB_CM_SIDR_REQ_RECEIVED)
- id = IB_UCM_CM_ID_INVALID;
- uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
- if (!uevent) {
- result = -ENOMEM;
- goto done;
- }
+ ctx = cm_id->context;
- memset(uevent, 0, sizeof(*uevent));
+ uevent = kzalloc(sizeof *uevent, GFP_KERNEL);
+ if (!uevent)
+ goto err1;
- uevent->resp.id = id;
+ uevent->ctx = ctx;
+ uevent->cm_id = cm_id;
+ uevent->resp.uid = ctx->uid;
+ uevent->resp.id = ctx->id;
uevent->resp.event = event->event;
result = ib_ucm_event_process(event, uevent);
if (result)
- goto done;
-
- uevent->ctx = ctx;
- uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED ||
- event->event == IB_CM_SIDR_REQ_RECEIVED ) ?
- cm_id : NULL);
+ goto err2;
down(&ctx->file->mutex);
-
list_add_tail(&uevent->file_list, &ctx->file->events);
list_add_tail(&uevent->ctx_list, &ctx->events);
-
wake_up_interruptible(&ctx->file->poll_wait);
-
up(&ctx->file->mutex);
-done:
- ctx->error = result;
- ib_ucm_ctx_put(ctx); /* func reference */
- return result;
+ return 0;
+
+err2:
+ kfree(uevent);
+err1:
+ /* Destroy new cm_id's */
+ return ib_ucm_new_cm_id(event->event);
}
static ssize_t ib_ucm_event(struct ib_ucm_file *file,
@@ -468,7 +419,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
{
struct ib_ucm_context *ctx;
struct ib_ucm_event_get cmd;
- struct ib_ucm_event *uevent = NULL;
+ struct ib_ucm_event *uevent;
int result = 0;
DEFINE_WAIT(wait);
@@ -477,11 +428,8 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- /*
- * wait
- */
- down(&file->mutex);
+ down(&file->mutex);
while (list_empty(&file->events)) {
if (file->filp->f_flags & O_NONBLOCK) {
@@ -508,22 +456,18 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
uevent = list_entry(file->events.next, struct ib_ucm_event, file_list);
- if (!uevent->cm_id)
- goto user;
+ if (ib_ucm_new_cm_id(uevent->resp.event)) {
+ ctx = ib_ucm_ctx_alloc(file);
+ if (!ctx) {
+ result = -ENOMEM;
+ goto done;
+ }
- ctx = ib_ucm_ctx_alloc(file);
- if (!ctx) {
- result = -ENOMEM;
- goto done;
+ ctx->cm_id = uevent->cm_id;
+ ctx->cm_id->context = ctx;
+ uevent->resp.id = ctx->id;
}
- ctx->cm_id = uevent->cm_id;
- ctx->cm_id->cm_handler = ib_ucm_event_handler;
- ctx->cm_id->context = (void *)(unsigned long)ctx->id;
-
- uevent->resp.id = ctx->id;
-
-user:
if (copy_to_user((void __user *)(unsigned long)cmd.response,
&uevent->resp, sizeof(uevent->resp))) {
result = -EFAULT;
@@ -531,12 +475,10 @@ user:
}
if (uevent->data) {
-
if (cmd.data_len < uevent->data_len) {
result = -ENOMEM;
goto done;
}
-
if (copy_to_user((void __user *)(unsigned long)cmd.data,
uevent->data, uevent->data_len)) {
result = -EFAULT;
@@ -545,12 +487,10 @@ user:
}
if (uevent->info) {
-
if (cmd.info_len < uevent->info_len) {
result = -ENOMEM;
goto done;
}
-
if (copy_to_user((void __user *)(unsigned long)cmd.info,
uevent->info, uevent->info_len)) {
result = -EFAULT;
@@ -560,6 +500,7 @@ user:
list_del(&uevent->file_list);
list_del(&uevent->ctx_list);
+ uevent->ctx->events_reported++;
kfree(uevent->data);
kfree(uevent->info);
@@ -569,7 +510,6 @@ done:
return result;
}
-
static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
const char __user *inbuf,
int in_len, int out_len)
@@ -585,30 +525,35 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
+ down(&file->mutex);
ctx = ib_ucm_ctx_alloc(file);
+ up(&file->mutex);
if (!ctx)
return -ENOMEM;
- ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler,
- (void *)(unsigned long)ctx->id);
- if (!ctx->cm_id) {
- result = -ENOMEM;
- goto err_cm;
+ ctx->uid = cmd.uid;
+ ctx->cm_id = ib_create_cm_id(file->device->ib_dev,
+ ib_ucm_event_handler, ctx);
+ if (IS_ERR(ctx->cm_id)) {
+ result = PTR_ERR(ctx->cm_id);
+ goto err1;
}
resp.id = ctx->id;
if (copy_to_user((void __user *)(unsigned long)cmd.response,
&resp, sizeof(resp))) {
result = -EFAULT;
- goto err_ret;
+ goto err2;
}
-
return 0;
-err_ret:
- ib_destroy_cm_id(ctx->cm_id);
-err_cm:
- ib_ucm_ctx_put(ctx); /* user reference */
+err2:
+ ib_destroy_cm_id(ctx->cm_id);
+err1:
+ down(&ctx_id_mutex);
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
+ kfree(ctx);
return result;
}
@@ -617,19 +562,44 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
int in_len, int out_len)
{
struct ib_ucm_destroy_id cmd;
+ struct ib_ucm_destroy_id_resp resp;
struct ib_ucm_context *ctx;
+ int result = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
+ down(&ctx_id_mutex);
+ ctx = idr_find(&ctx_id_table, cmd.id);
if (!ctx)
- return -ENOENT;
+ ctx = ERR_PTR(-ENOENT);
+ else if (ctx->file != file)
+ ctx = ERR_PTR(-EINVAL);
+ else
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
- ib_ucm_ctx_put(ctx); /* user reference */
- ib_ucm_ctx_put(ctx); /* func reference */
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- return 0;
+ atomic_dec(&ctx->ref);
+ wait_event(ctx->wait, !atomic_read(&ctx->ref));
+
+ /* No new events will be generated after destroying the cm_id. */
+ ib_destroy_cm_id(ctx->cm_id);
+ /* Cleanup events not yet reported to the user. */
+ ib_ucm_cleanup_events(ctx);
+
+ resp.events_reported = ctx->events_reported;
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ result = -EFAULT;
+
+ kfree(ctx);
+ return result;
}
static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
@@ -647,15 +617,9 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
-
- down(&ctx->file->mutex);
- if (ctx->file != file) {
- result = -EINVAL;
- goto done;
- }
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
resp.service_id = ctx->cm_id->service_id;
resp.service_mask = ctx->cm_id->service_mask;
@@ -666,9 +630,99 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
&resp, sizeof(resp)))
result = -EFAULT;
-done:
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ ib_ucm_ctx_put(ctx);
+ return result;
+}
+
+static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
+ struct ib_ah_attr *src_attr)
+{
+ memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
+ sizeof src_attr->grh.dgid);
+ dest_attr->grh_flow_label = src_attr->grh.flow_label;
+ dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
+ dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
+ dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
+
+ dest_attr->dlid = src_attr->dlid;
+ dest_attr->sl = src_attr->sl;
+ dest_attr->src_path_bits = src_attr->src_path_bits;
+ dest_attr->static_rate = src_attr->static_rate;
+ dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
+ dest_attr->port_num = src_attr->port_num;
+}
+
+static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
+ struct ib_qp_attr *src_attr)
+{
+ dest_attr->cur_qp_state = src_attr->cur_qp_state;
+ dest_attr->path_mtu = src_attr->path_mtu;
+ dest_attr->path_mig_state = src_attr->path_mig_state;
+ dest_attr->qkey = src_attr->qkey;
+ dest_attr->rq_psn = src_attr->rq_psn;
+ dest_attr->sq_psn = src_attr->sq_psn;
+ dest_attr->dest_qp_num = src_attr->dest_qp_num;
+ dest_attr->qp_access_flags = src_attr->qp_access_flags;
+
+ dest_attr->max_send_wr = src_attr->cap.max_send_wr;
+ dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
+ dest_attr->max_send_sge = src_attr->cap.max_send_sge;
+ dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
+ dest_attr->max_inline_data = src_attr->cap.max_inline_data;
+
+ ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
+ ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
+
+ dest_attr->pkey_index = src_attr->pkey_index;
+ dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
+ dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
+ dest_attr->sq_draining = src_attr->sq_draining;
+ dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
+ dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
+ dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
+ dest_attr->port_num = src_attr->port_num;
+ dest_attr->timeout = src_attr->timeout;
+ dest_attr->retry_cnt = src_attr->retry_cnt;
+ dest_attr->rnr_retry = src_attr->rnr_retry;
+ dest_attr->alt_port_num = src_attr->alt_port_num;
+ dest_attr->alt_timeout = src_attr->alt_timeout;
+}
+
+static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct ib_ucm_init_qp_attr_resp resp;
+ struct ib_ucm_init_qp_attr cmd;
+ struct ib_ucm_context *ctx;
+ struct ib_qp_attr qp_attr;
+ int result = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ resp.qp_attr_mask = 0;
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_state = cmd.qp_state;
+ result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
+ if (result)
+ goto out;
+
+ ib_ucm_copy_qp_attr(&resp, &qp_attr);
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ result = -EFAULT;
+
+out:
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -683,19 +737,12 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_cm_listen(ctx->cm_id, cmd.service_id,
- cmd.service_mask);
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -710,18 +757,12 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx)
- return -ENOENT;
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_cm_establish(ctx->cm_id);
-
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
+ result = ib_cm_establish(ctx->cm_id);
+ ib_ucm_ctx_put(ctx);
return result;
}
@@ -768,8 +809,8 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
return -EFAULT;
}
- memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid));
- memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid));
+ memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
+ memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
sa_path->dlid = ucm_path.dlid;
sa_path->slid = ucm_path.slid;
@@ -839,25 +880,17 @@ static ssize_t ib_ucm_send_req(struct ib_ucm_file *file,
param.max_cm_retries = cmd.max_cm_retries;
param.srq = cmd.srq;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_req(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.primary_path);
kfree(param.alternate_path);
-
return result;
}
@@ -890,23 +923,15 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
param.rnr_retry_count = cmd.rnr_retry_count;
param.srq = cmd.srq;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ ctx->uid = cmd.uid;
result = ib_send_cm_rep(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(param.private_data);
-
return result;
}
@@ -928,23 +953,14 @@ static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file,
if (result)
return result;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = func(ctx->cm_id, private_data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(private_data);
-
return result;
}
@@ -995,26 +1011,17 @@ static ssize_t ib_ucm_send_info(struct ib_ucm_file *file,
if (result)
goto done;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = func(ctx->cm_id, cmd.status,
- info, cmd.info_len,
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ result = func(ctx->cm_id, cmd.status, info, cmd.info_len,
data, cmd.data_len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(data);
kfree(info);
-
return result;
}
@@ -1048,24 +1055,14 @@ static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file,
if (result)
return result;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
+ result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
- result = ib_send_cm_mra(ctx->cm_id, cmd.timeout,
- data, cmd.len);
-
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
-done:
kfree(data);
-
return result;
}
@@ -1090,24 +1087,16 @@ static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file,
if (result)
goto done;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(data);
kfree(path);
-
return result;
}
@@ -1140,24 +1129,16 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
param.max_cm_retries = cmd.max_cm_retries;
param.pkey = cmd.pkey;
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
-
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_sidr_req(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.path);
-
return result;
}
@@ -1184,30 +1165,22 @@ static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file,
if (result)
goto done;
- param.qp_num = cmd.qpn;
- param.qkey = cmd.qkey;
- param.status = cmd.status;
- param.info_length = cmd.info_len;
- param.private_data_len = cmd.data_len;
-
- ctx = ib_ucm_ctx_get(cmd.id);
- if (!ctx) {
- result = -ENOENT;
- goto done;
- }
+ param.qp_num = cmd.qpn;
+ param.qkey = cmd.qkey;
+ param.status = cmd.status;
+ param.info_length = cmd.info_len;
+ param.private_data_len = cmd.data_len;
- down(&ctx->file->mutex);
- if (ctx->file != file)
- result = -EINVAL;
- else
+ ctx = ib_ucm_ctx_get(file, cmd.id);
+ if (!IS_ERR(ctx)) {
result = ib_send_cm_sidr_rep(ctx->cm_id, &param);
+ ib_ucm_ctx_put(ctx);
+ } else
+ result = PTR_ERR(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* func reference */
done:
kfree(param.private_data);
kfree(param.info);
-
return result;
}
@@ -1231,6 +1204,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
[IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req,
[IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep,
[IB_USER_CM_CMD_EVENT] = ib_ucm_event,
+ [IB_USER_CM_CMD_INIT_QP_ATTR] = ib_ucm_init_qp_attr,
};
static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
@@ -1246,9 +1220,6 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
- ucm_dbg("Write. cmd <%d> in <%d> out <%d> len <%Zu>\n",
- hdr.cmd, hdr.in, hdr.out, len);
-
if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
return -EINVAL;
@@ -1293,8 +1264,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
filp->private_data = file;
file->filp = filp;
-
- ucm_dbg("Created struct\n");
+ file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev);
return 0;
}
@@ -1305,26 +1275,37 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
struct ib_ucm_context *ctx;
down(&file->mutex);
-
while (!list_empty(&file->ctxs)) {
-
ctx = list_entry(file->ctxs.next,
struct ib_ucm_context, file_list);
+ up(&file->mutex);
+
+ down(&ctx_id_mutex);
+ idr_remove(&ctx_id_table, ctx->id);
+ up(&ctx_id_mutex);
+
+ ib_destroy_cm_id(ctx->cm_id);
+ ib_ucm_cleanup_events(ctx);
+ kfree(ctx);
- up(&ctx->file->mutex);
- ib_ucm_ctx_put(ctx); /* user reference */
down(&file->mutex);
}
-
up(&file->mutex);
-
kfree(file);
-
- ucm_dbg("Deleted struct\n");
return 0;
}
-static struct file_operations ib_ucm_fops = {
+static void ib_ucm_release_class_dev(struct class_device *class_dev)
+{
+ struct ib_ucm_device *dev;
+
+ dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+ cdev_del(&dev->dev);
+ clear_bit(dev->devnum, dev_map);
+ kfree(dev);
+}
+
+static struct file_operations ucm_fops = {
.owner = THIS_MODULE,
.open = ib_ucm_open,
.release = ib_ucm_close,
@@ -1332,55 +1313,141 @@ static struct file_operations ib_ucm_fops = {
.poll = ib_ucm_poll,
};
+static struct class ucm_class = {
+ .name = "infiniband_cm",
+ .release = ib_ucm_release_class_dev
+};
-static struct class *ib_ucm_class;
-static struct cdev ib_ucm_cdev;
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+ struct ib_ucm_device *dev;
+
+ dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+ return print_dev_t(buf, dev->dev.dev);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-static int __init ib_ucm_init(void)
+static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
- int result;
+ struct ib_ucm_device *dev;
+
+ dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+ return sprintf(buf, "%s\n", dev->ib_dev->name);
+}
+static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
- result = register_chrdev_region(IB_UCM_DEV, 1, "infiniband_cm");
- if (result) {
- ucm_dbg("Error <%d> registering dev\n", result);
- goto err_chr;
- }
+static void ib_ucm_add_one(struct ib_device *device)
+{
+ struct ib_ucm_device *ucm_dev;
+
+ if (!device->alloc_ucontext)
+ return;
+
+ ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL);
+ if (!ucm_dev)
+ return;
+
+ ucm_dev->ib_dev = device;
+
+ ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
+ if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES)
+ goto err;
+
+ set_bit(ucm_dev->devnum, dev_map);
- cdev_init(&ib_ucm_cdev, &ib_ucm_fops);
+ cdev_init(&ucm_dev->dev, &ucm_fops);
+ ucm_dev->dev.owner = THIS_MODULE;
+ kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum);
+ if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+ goto err;
- result = cdev_add(&ib_ucm_cdev, IB_UCM_DEV, 1);
- if (result) {
- ucm_dbg("Error <%d> adding cdev\n", result);
+ ucm_dev->class_dev.class = &ucm_class;
+ ucm_dev->class_dev.dev = device->dma_device;
+ snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
+ ucm_dev->devnum);
+ if (class_device_register(&ucm_dev->class_dev))
goto err_cdev;
- }
- ib_ucm_class = class_create(THIS_MODULE, "infiniband_cm");
- if (IS_ERR(ib_ucm_class)) {
- result = PTR_ERR(ib_ucm_class);
- ucm_dbg("Error <%d> creating class\n", result);
+ if (class_device_create_file(&ucm_dev->class_dev,
+ &class_device_attr_dev))
+ goto err_class;
+ if (class_device_create_file(&ucm_dev->class_dev,
+ &class_device_attr_ibdev))
goto err_class;
+
+ ib_set_client_data(device, &ucm_client, ucm_dev);
+ return;
+
+err_class:
+ class_device_unregister(&ucm_dev->class_dev);
+err_cdev:
+ cdev_del(&ucm_dev->dev);
+ clear_bit(ucm_dev->devnum, dev_map);
+err:
+ kfree(ucm_dev);
+ return;
+}
+
+static void ib_ucm_remove_one(struct ib_device *device)
+{
+ struct ib_ucm_device *ucm_dev = ib_get_client_data(device, &ucm_client);
+
+ if (!ucm_dev)
+ return;
+
+ class_device_unregister(&ucm_dev->class_dev);
+}
+
+static ssize_t show_abi_version(struct class *class, char *buf)
+{
+ return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);
+}
+static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+
+static int __init ib_ucm_init(void)
+{
+ int ret;
+
+ ret = register_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES,
+ "infiniband_cm");
+ if (ret) {
+ printk(KERN_ERR "ucm: couldn't register device number\n");
+ goto err;
}
- class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm");
+ ret = class_register(&ucm_class);
+ if (ret) {
+ printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
+ goto err_chrdev;
+ }
- idr_init(&ctx_id_table);
- init_MUTEX(&ctx_id_mutex);
+ ret = class_create_file(&ucm_class, &class_attr_abi_version);
+ if (ret) {
+ printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
+ goto err_class;
+ }
+ ret = ib_register_client(&ucm_client);
+ if (ret) {
+ printk(KERN_ERR "ucm: couldn't register client\n");
+ goto err_class;
+ }
return 0;
+
err_class:
- cdev_del(&ib_ucm_cdev);
-err_cdev:
- unregister_chrdev_region(IB_UCM_DEV, 1);
-err_chr:
- return result;
+ class_unregister(&ucm_class);
+err_chrdev:
+ unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+err:
+ return ret;
}
static void __exit ib_ucm_cleanup(void)
{
- class_device_destroy(ib_ucm_class, IB_UCM_DEV);
- class_destroy(ib_ucm_class);
- cdev_del(&ib_ucm_cdev);
- unregister_chrdev_region(IB_UCM_DEV, 1);
+ ib_unregister_client(&ucm_client);
+ class_unregister(&ucm_class);
+ unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+ idr_destroy(&ctx_id_table);
}
module_init(ib_ucm_init);
diff --git a/drivers/infiniband/core/ucm.h b/drivers/infiniband/core/ucm.h
deleted file mode 100644
index 6d36606151b2..000000000000
--- a/drivers/infiniband/core/ucm.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ucm.h 2208 2005-04-22 23:24:31Z libor $
- */
-
-#ifndef UCM_H
-#define UCM_H
-
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/idr.h>
-
-#include <ib_cm.h>
-#include <ib_user_cm.h>
-
-#define IB_UCM_CM_ID_INVALID 0xffffffff
-
-struct ib_ucm_file {
- struct semaphore mutex;
- struct file *filp;
- /*
- * list of pending events
- */
- struct list_head ctxs; /* list of active connections */
- struct list_head events; /* list of pending events */
- wait_queue_head_t poll_wait;
-};
-
-struct ib_ucm_context {
- int id;
- int ref;
- int error;
-
- struct ib_ucm_file *file;
- struct ib_cm_id *cm_id;
- struct semaphore mutex;
-
- struct list_head events; /* list of pending events. */
- struct list_head file_list; /* member in file ctx list */
-};
-
-struct ib_ucm_event {
- struct ib_ucm_context *ctx;
- struct list_head file_list; /* member in file event list */
- struct list_head ctx_list; /* member in ctx event list */
-
- struct ib_ucm_event_resp resp;
- void *data;
- void *info;
- int data_len;
- int info_len;
- /*
- * new connection identifiers needs to be saved until
- * userspace can get a handle on them.
- */
- struct ib_cm_id *cm_id;
-};
-
-#endif /* UCM_H */
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index dc4eb1db5e96..527b23450ab3 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, 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
@@ -34,7 +35,7 @@
#include <linux/errno.h>
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
#define STRUCT_FIELD(header, field) \
.struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \
@@ -194,6 +195,7 @@ void ib_ud_header_init(int payload_bytes,
struct ib_ud_header *header)
{
int header_len;
+ u16 packet_length;
memset(header, 0, sizeof *header);
@@ -208,7 +210,7 @@ void ib_ud_header_init(int payload_bytes,
header->lrh.link_version = 0;
header->lrh.link_next_header =
grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
- header->lrh.packet_length = (IB_LRH_BYTES +
+ packet_length = (IB_LRH_BYTES +
IB_BTH_BYTES +
IB_DETH_BYTES +
payload_bytes +
@@ -217,8 +219,7 @@ void ib_ud_header_init(int payload_bytes,
header->grh_present = grh_present;
if (grh_present) {
- header->lrh.packet_length += IB_GRH_BYTES / 4;
-
+ packet_length += IB_GRH_BYTES / 4;
header->grh.ip_version = 6;
header->grh.payload_length =
cpu_to_be16((IB_BTH_BYTES +
@@ -229,7 +230,7 @@ void ib_ud_header_init(int payload_bytes,
header->grh.next_header = 0x1b;
}
- cpu_to_be16s(&header->lrh.packet_length);
+ header->lrh.packet_length = cpu_to_be16(packet_length);
if (header->immediate_present)
header->bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 2e38792df533..aed5ca23fb22 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -49,8 +49,8 @@
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <ib_mad.h>
-#include <ib_user_mad.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_mad.h>
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
@@ -64,18 +64,42 @@ enum {
IB_UMAD_MINOR_BASE = 0
};
+/*
+ * Our lifetime rules for these structs are the following: each time a
+ * device special file is opened, we look up the corresponding struct
+ * ib_umad_port by minor in the umad_port[] table while holding the
+ * port_lock. If this lookup succeeds, we take a reference on the
+ * ib_umad_port's struct ib_umad_device while still holding the
+ * port_lock; if the lookup fails, we fail the open(). We drop these
+ * references in the corresponding close().
+ *
+ * In addition to references coming from open character devices, there
+ * is one more reference to each ib_umad_device representing the
+ * module's reference taken when allocating the ib_umad_device in
+ * ib_umad_add_one().
+ *
+ * When destroying an ib_umad_device, we clear all of its
+ * ib_umad_ports from umad_port[] while holding port_lock before
+ * dropping the module's reference to the ib_umad_device. This is
+ * always safe because any open() calls will either succeed and obtain
+ * a reference before we clear the umad_port[] entries, or fail after
+ * we clear the umad_port[] entries.
+ */
+
struct ib_umad_port {
- int devnum;
- struct cdev dev;
- struct class_device class_dev;
+ struct cdev *dev;
+ struct class_device *class_dev;
- int sm_devnum;
- struct cdev sm_dev;
- struct class_device sm_class_dev;
+ struct cdev *sm_dev;
+ struct class_device *sm_class_dev;
struct semaphore sm_sem;
+ struct rw_semaphore mutex;
+ struct list_head file_list;
+
struct ib_device *ib_dev;
struct ib_umad_device *umad_dev;
+ int dev_num;
u8 port_num;
};
@@ -87,37 +111,47 @@ struct ib_umad_device {
struct ib_umad_file {
struct ib_umad_port *port;
- spinlock_t recv_lock;
struct list_head recv_list;
+ struct list_head port_list;
+ spinlock_t recv_lock;
wait_queue_head_t recv_wait;
- struct rw_semaphore agent_mutex;
struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
struct ib_mr *mr[IB_UMAD_MAX_AGENTS];
};
struct ib_umad_packet {
- struct ib_ah *ah;
struct ib_mad_send_buf *msg;
struct list_head list;
int length;
- DECLARE_PCI_UNMAP_ADDR(mapping)
struct ib_user_mad mad;
};
+static struct class *umad_class;
+
static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
-static spinlock_t map_lock;
+
+static DEFINE_SPINLOCK(port_lock);
+static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
static void ib_umad_add_one(struct ib_device *device);
static void ib_umad_remove_one(struct ib_device *device);
+static void ib_umad_release_dev(struct kref *ref)
+{
+ struct ib_umad_device *dev =
+ container_of(ref, struct ib_umad_device, ref);
+
+ kfree(dev);
+}
+
static int queue_packet(struct ib_umad_file *file,
struct ib_mad_agent *agent,
struct ib_umad_packet *packet)
{
int ret = 1;
- down_read(&file->agent_mutex);
+ down_read(&file->port->mutex);
for (packet->mad.hdr.id = 0;
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
packet->mad.hdr.id++)
@@ -130,7 +164,7 @@ static int queue_packet(struct ib_umad_file *file,
break;
}
- up_read(&file->agent_mutex);
+ up_read(&file->port->mutex);
return ret;
}
@@ -139,22 +173,19 @@ static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *send_wc)
{
struct ib_umad_file *file = agent->context;
- struct ib_umad_packet *timeout, *packet =
- (void *) (unsigned long) send_wc->wr_id;
+ struct ib_umad_packet *timeout;
+ struct ib_umad_packet *packet = send_wc->send_buf->context[0];
- ib_destroy_ah(packet->msg->send_wr.wr.ud.ah);
+ ib_destroy_ah(packet->msg->ah);
ib_free_send_mad(packet->msg);
if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
- timeout = kmalloc(sizeof *timeout + sizeof (struct ib_mad_hdr),
- GFP_KERNEL);
+ timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL);
if (!timeout)
goto out;
- memset(timeout, 0, sizeof *timeout + sizeof (struct ib_mad_hdr));
-
- timeout->length = sizeof (struct ib_mad_hdr);
- timeout->mad.hdr.id = packet->mad.hdr.id;
+ timeout->length = IB_MGMT_MAD_HDR;
+ timeout->mad.hdr.id = packet->mad.hdr.id;
timeout->mad.hdr.status = ETIMEDOUT;
memcpy(timeout->mad.data, packet->mad.data,
sizeof (struct ib_mad_hdr));
@@ -177,11 +208,10 @@ static void recv_handler(struct ib_mad_agent *agent,
goto out;
length = mad_recv_wc->mad_len;
- packet = kmalloc(sizeof *packet + length, GFP_KERNEL);
+ packet = kzalloc(sizeof *packet + length, GFP_KERNEL);
if (!packet)
goto out;
- memset(packet, 0, sizeof *packet + length);
packet->length = length;
ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);
@@ -247,7 +277,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
else
ret = -ENOSPC;
} else if (copy_to_user(buf, &packet->mad,
- packet->length + sizeof (struct ib_user_mad)))
+ packet->length + sizeof (struct ib_user_mad)))
ret = -EFAULT;
else
ret = packet->length + sizeof (struct ib_user_mad);
@@ -268,26 +298,23 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
struct ib_umad_packet *packet;
struct ib_mad_agent *agent;
struct ib_ah_attr ah_attr;
- struct ib_send_wr *bad_wr;
+ struct ib_ah *ah;
struct ib_rmpp_mad *rmpp_mad;
u8 method;
- u64 *tid;
- int ret, length, hdr_len, data_len, rmpp_hdr_size;
+ __be64 *tid;
+ int ret, length, hdr_len, copy_offset;
int rmpp_active = 0;
if (count < sizeof (struct ib_user_mad))
return -EINVAL;
length = count - sizeof (struct ib_user_mad);
- packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +
- sizeof(struct ib_rmpp_hdr), GFP_KERNEL);
+ packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);
if (!packet)
return -ENOMEM;
if (copy_from_user(&packet->mad, buf,
- sizeof (struct ib_user_mad) +
- sizeof(struct ib_mad_hdr) +
- sizeof(struct ib_rmpp_hdr))) {
+ sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) {
ret = -EFAULT;
goto err;
}
@@ -298,9 +325,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
goto err;
}
- packet->length = length;
-
- down_read(&file->agent_mutex);
+ down_read(&file->port->mutex);
agent = file->agent[packet->mad.hdr.id];
if (!agent) {
@@ -316,14 +341,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
if (packet->mad.hdr.grh_present) {
ah_attr.ah_flags = IB_AH_GRH;
memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
- ah_attr.grh.flow_label = packet->mad.hdr.flow_label;
+ ah_attr.grh.flow_label = be32_to_cpu(packet->mad.hdr.flow_label);
ah_attr.grh.hop_limit = packet->mad.hdr.hop_limit;
ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;
}
- packet->ah = ib_create_ah(agent->qp->pd, &ah_attr);
- if (IS_ERR(packet->ah)) {
- ret = PTR_ERR(packet->ah);
+ ah = ib_create_ah(agent->qp->pd, &ah_attr);
+ if (IS_ERR(ah)) {
+ ret = PTR_ERR(ah);
goto err_up;
}
@@ -334,66 +359,47 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
ret = -EINVAL;
goto err_ah;
}
- /* Validate that management class can support RMPP */
+
+ /* Validate that the management class can support RMPP */
if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
- hdr_len = offsetof(struct ib_sa_mad, data);
- data_len = length;
+ hdr_len = IB_MGMT_SA_HDR;
} else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
(rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {
- hdr_len = offsetof(struct ib_vendor_mad, data);
- data_len = length - hdr_len;
+ hdr_len = IB_MGMT_VENDOR_HDR;
} else {
ret = -EINVAL;
goto err_ah;
}
rmpp_active = 1;
+ copy_offset = IB_MGMT_RMPP_HDR;
} else {
- if (length > sizeof(struct ib_mad)) {
- ret = -EINVAL;
- goto err_ah;
- }
- hdr_len = offsetof(struct ib_mad, data);
- data_len = length - hdr_len;
+ hdr_len = IB_MGMT_MAD_HDR;
+ copy_offset = IB_MGMT_MAD_HDR;
}
packet->msg = ib_create_send_mad(agent,
be32_to_cpu(packet->mad.hdr.qpn),
- 0, packet->ah, rmpp_active,
- hdr_len, data_len,
+ 0, rmpp_active,
+ hdr_len, length - hdr_len,
GFP_KERNEL);
if (IS_ERR(packet->msg)) {
ret = PTR_ERR(packet->msg);
goto err_ah;
}
- packet->msg->send_wr.wr.ud.timeout_ms = packet->mad.hdr.timeout_ms;
- packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries;
+ packet->msg->ah = ah;
+ packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
+ packet->msg->retries = packet->mad.hdr.retries;
+ packet->msg->context[0] = packet;
- /* Override send WR WRID initialized in ib_create_send_mad */
- packet->msg->send_wr.wr_id = (unsigned long) packet;
-
- if (!rmpp_active) {
- /* Copy message from user into send buffer */
- if (copy_from_user(packet->msg->mad,
- buf + sizeof(struct ib_user_mad), length)) {
- ret = -EFAULT;
- goto err_msg;
- }
- } else {
- rmpp_hdr_size = sizeof(struct ib_mad_hdr) +
- sizeof(struct ib_rmpp_hdr);
-
- /* Only copy MAD headers (RMPP header in place) */
- memcpy(packet->msg->mad, packet->mad.data,
- sizeof(struct ib_mad_hdr));
-
- /* Now, copy rest of message from user into send buffer */
- if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,
- buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,
- length - rmpp_hdr_size)) {
- ret = -EFAULT;
- goto err_msg;
- }
+ /* Copy MAD headers (RMPP header in place) */
+ memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR);
+ /* Now, copy rest of message from user into send buffer */
+ if (copy_from_user(packet->msg->mad + copy_offset,
+ buf + sizeof (struct ib_user_mad) + copy_offset,
+ length - copy_offset)) {
+ ret = -EFAULT;
+ goto err_msg;
}
/*
@@ -402,32 +408,32 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
* transaction ID matches the agent being used to send the
* MAD.
*/
- method = packet->msg->mad->mad_hdr.method;
+ method = ((struct ib_mad_hdr *) packet->msg->mad)->method;
if (!(method & IB_MGMT_METHOD_RESP) &&
method != IB_MGMT_METHOD_TRAP_REPRESS &&
method != IB_MGMT_METHOD_SEND) {
- tid = &packet->msg->mad->mad_hdr.tid;
+ tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;
*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
(be64_to_cpup(tid) & 0xffffffff));
}
- ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr);
+ ret = ib_post_send_mad(packet->msg, NULL);
if (ret)
goto err_msg;
- up_read(&file->agent_mutex);
+ up_read(&file->port->mutex);
- return sizeof (struct ib_user_mad_hdr) + packet->length;
+ return count;
err_msg:
ib_free_send_mad(packet->msg);
err_ah:
- ib_destroy_ah(packet->ah);
+ ib_destroy_ah(ah);
err_up:
- up_read(&file->agent_mutex);
+ up_read(&file->port->mutex);
err:
kfree(packet);
@@ -457,7 +463,12 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
int agent_id;
int ret;
- down_write(&file->agent_mutex);
+ down_write(&file->port->mutex);
+
+ if (!file->port->ib_dev) {
+ ret = -EPIPE;
+ goto out;
+ }
if (copy_from_user(&ureq, (void __user *) arg, sizeof ureq)) {
ret = -EFAULT;
@@ -519,7 +530,7 @@ err:
ib_unregister_mad_agent(agent);
out:
- up_write(&file->agent_mutex);
+ up_write(&file->port->mutex);
return ret;
}
@@ -528,7 +539,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
u32 id;
int ret = 0;
- down_write(&file->agent_mutex);
+ down_write(&file->port->mutex);
if (get_user(id, (u32 __user *) arg)) {
ret = -EFAULT;
@@ -545,7 +556,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
file->agent[id] = NULL;
out:
- up_write(&file->agent_mutex);
+ up_write(&file->port->mutex);
return ret;
}
@@ -564,33 +575,55 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
static int ib_umad_open(struct inode *inode, struct file *filp)
{
- struct ib_umad_port *port =
- container_of(inode->i_cdev, struct ib_umad_port, dev);
+ struct ib_umad_port *port;
struct ib_umad_file *file;
+ int ret = 0;
- file = kmalloc(sizeof *file, GFP_KERNEL);
- if (!file)
- return -ENOMEM;
+ spin_lock(&port_lock);
+ port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
+ if (port)
+ kref_get(&port->umad_dev->ref);
+ spin_unlock(&port_lock);
+
+ if (!port)
+ return -ENXIO;
- memset(file, 0, sizeof *file);
+ down_write(&port->mutex);
+
+ if (!port->ib_dev) {
+ ret = -ENXIO;
+ goto out;
+ }
+
+ file = kzalloc(sizeof *file, GFP_KERNEL);
+ if (!file) {
+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+ ret = -ENOMEM;
+ goto out;
+ }
spin_lock_init(&file->recv_lock);
- init_rwsem(&file->agent_mutex);
INIT_LIST_HEAD(&file->recv_list);
init_waitqueue_head(&file->recv_wait);
file->port = port;
filp->private_data = file;
- return 0;
+ list_add_tail(&file->port_list, &port->file_list);
+
+out:
+ up_write(&port->mutex);
+ return ret;
}
static int ib_umad_close(struct inode *inode, struct file *filp)
{
struct ib_umad_file *file = filp->private_data;
+ struct ib_umad_device *dev = file->port->umad_dev;
struct ib_umad_packet *packet, *tmp;
int i;
+ down_write(&file->port->mutex);
for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
if (file->agent[i]) {
ib_dereg_mr(file->mr[i]);
@@ -600,8 +633,13 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
list_for_each_entry_safe(packet, tmp, &file->recv_list, list)
kfree(packet);
+ list_del(&file->port_list);
+ up_write(&file->port->mutex);
+
kfree(file);
+ kref_put(&dev->ref, ib_umad_release_dev);
+
return 0;
}
@@ -618,30 +656,46 @@ static struct file_operations umad_fops = {
static int ib_umad_sm_open(struct inode *inode, struct file *filp)
{
- struct ib_umad_port *port =
- container_of(inode->i_cdev, struct ib_umad_port, sm_dev);
+ struct ib_umad_port *port;
struct ib_port_modify props = {
.set_port_cap_mask = IB_PORT_SM
};
int ret;
+ spin_lock(&port_lock);
+ port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
+ if (port)
+ kref_get(&port->umad_dev->ref);
+ spin_unlock(&port_lock);
+
+ if (!port)
+ return -ENXIO;
+
if (filp->f_flags & O_NONBLOCK) {
- if (down_trylock(&port->sm_sem))
- return -EAGAIN;
+ if (down_trylock(&port->sm_sem)) {
+ ret = -EAGAIN;
+ goto fail;
+ }
} else {
- if (down_interruptible(&port->sm_sem))
- return -ERESTARTSYS;
+ if (down_interruptible(&port->sm_sem)) {
+ ret = -ERESTARTSYS;
+ goto fail;
+ }
}
ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
if (ret) {
up(&port->sm_sem);
- return ret;
+ goto fail;
}
filp->private_data = port;
return 0;
+
+fail:
+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+ return ret;
}
static int ib_umad_sm_close(struct inode *inode, struct file *filp)
@@ -650,11 +704,17 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
struct ib_port_modify props = {
.clr_port_cap_mask = IB_PORT_SM
};
- int ret;
+ int ret = 0;
+
+ down_write(&port->mutex);
+ if (port->ib_dev)
+ ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
+ up_write(&port->mutex);
- ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
up(&port->sm_sem);
+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+
return ret;
}
@@ -670,21 +730,13 @@ static struct ib_client umad_client = {
.remove = ib_umad_remove_one
};
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct ib_umad_port *port = class_get_devdata(class_dev);
-
- if (class_dev == &port->class_dev)
- return print_dev_t(buf, port->dev.dev);
- else
- return print_dev_t(buf, port->sm_dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
struct ib_umad_port *port = class_get_devdata(class_dev);
+ if (!port)
+ return -ENODEV;
+
return sprintf(buf, "%s\n", port->ib_dev->name);
}
static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -693,38 +745,13 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
{
struct ib_umad_port *port = class_get_devdata(class_dev);
+ if (!port)
+ return -ENODEV;
+
return sprintf(buf, "%d\n", port->port_num);
}
static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
-static void ib_umad_release_dev(struct kref *ref)
-{
- struct ib_umad_device *dev =
- container_of(ref, struct ib_umad_device, ref);
-
- kfree(dev);
-}
-
-static void ib_umad_release_port(struct class_device *class_dev)
-{
- struct ib_umad_port *port = class_get_devdata(class_dev);
-
- if (class_dev == &port->class_dev) {
- cdev_del(&port->dev);
- clear_bit(port->devnum, dev_map);
- } else {
- cdev_del(&port->sm_dev);
- clear_bit(port->sm_devnum, dev_map);
- }
-
- kref_put(&port->umad_dev->ref, ib_umad_release_dev);
-}
-
-static struct class umad_class = {
- .name = "infiniband_mad",
- .release = ib_umad_release_port
-};
-
static ssize_t show_abi_version(struct class *class, char *buf)
{
return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
@@ -734,91 +761,122 @@ static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
static int ib_umad_init_port(struct ib_device *device, int port_num,
struct ib_umad_port *port)
{
- spin_lock(&map_lock);
- port->devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
- if (port->devnum >= IB_UMAD_MAX_PORTS) {
- spin_unlock(&map_lock);
+ spin_lock(&port_lock);
+ port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
+ if (port->dev_num >= IB_UMAD_MAX_PORTS) {
+ spin_unlock(&port_lock);
return -1;
}
- port->sm_devnum = find_next_zero_bit(dev_map, IB_UMAD_MAX_PORTS * 2, IB_UMAD_MAX_PORTS);
- if (port->sm_devnum >= IB_UMAD_MAX_PORTS * 2) {
- spin_unlock(&map_lock);
- return -1;
- }
- set_bit(port->devnum, dev_map);
- set_bit(port->sm_devnum, dev_map);
- spin_unlock(&map_lock);
+ set_bit(port->dev_num, dev_map);
+ spin_unlock(&port_lock);
port->ib_dev = device;
port->port_num = port_num;
init_MUTEX(&port->sm_sem);
+ init_rwsem(&port->mutex);
+ INIT_LIST_HEAD(&port->file_list);
- cdev_init(&port->dev, &umad_fops);
- port->dev.owner = THIS_MODULE;
- kobject_set_name(&port->dev.kobj, "umad%d", port->devnum);
- if (cdev_add(&port->dev, base_dev + port->devnum, 1))
+ port->dev = cdev_alloc();
+ if (!port->dev)
return -1;
-
- port->class_dev.class = &umad_class;
- port->class_dev.dev = device->dma_device;
-
- snprintf(port->class_dev.class_id, BUS_ID_SIZE, "umad%d", port->devnum);
-
- if (class_device_register(&port->class_dev))
+ port->dev->owner = THIS_MODULE;
+ port->dev->ops = &umad_fops;
+ kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
+ if (cdev_add(port->dev, base_dev + port->dev_num, 1))
goto err_cdev;
- class_set_devdata(&port->class_dev, port);
- kref_get(&port->umad_dev->ref);
+ port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,
+ device->dma_device,
+ "umad%d", port->dev_num);
+ if (IS_ERR(port->class_dev))
+ goto err_cdev;
- if (class_device_create_file(&port->class_dev, &class_device_attr_dev))
- goto err_class;
- if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev))
+ if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
goto err_class;
- if (class_device_create_file(&port->class_dev, &class_device_attr_port))
+ if (class_device_create_file(port->class_dev, &class_device_attr_port))
goto err_class;
- cdev_init(&port->sm_dev, &umad_sm_fops);
- port->sm_dev.owner = THIS_MODULE;
- kobject_set_name(&port->dev.kobj, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
- if (cdev_add(&port->sm_dev, base_dev + port->sm_devnum, 1))
- return -1;
-
- port->sm_class_dev.class = &umad_class;
- port->sm_class_dev.dev = device->dma_device;
-
- snprintf(port->sm_class_dev.class_id, BUS_ID_SIZE, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
+ port->sm_dev = cdev_alloc();
+ if (!port->sm_dev)
+ goto err_class;
+ port->sm_dev->owner = THIS_MODULE;
+ port->sm_dev->ops = &umad_sm_fops;
+ kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);
+ if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+ goto err_sm_cdev;
- if (class_device_register(&port->sm_class_dev))
+ port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,
+ device->dma_device,
+ "issm%d", port->dev_num);
+ if (IS_ERR(port->sm_class_dev))
goto err_sm_cdev;
- class_set_devdata(&port->sm_class_dev, port);
- kref_get(&port->umad_dev->ref);
+ class_set_devdata(port->class_dev, port);
+ class_set_devdata(port->sm_class_dev, port);
- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_dev))
- goto err_sm_class;
- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_ibdev))
+ if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
goto err_sm_class;
- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port))
+ if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
goto err_sm_class;
+ spin_lock(&port_lock);
+ umad_port[port->dev_num] = port;
+ spin_unlock(&port_lock);
+
return 0;
err_sm_class:
- class_device_unregister(&port->sm_class_dev);
+ class_device_destroy(umad_class, port->sm_dev->dev);
err_sm_cdev:
- cdev_del(&port->sm_dev);
+ cdev_del(port->sm_dev);
err_class:
- class_device_unregister(&port->class_dev);
+ class_device_destroy(umad_class, port->dev->dev);
err_cdev:
- cdev_del(&port->dev);
- clear_bit(port->devnum, dev_map);
+ cdev_del(port->dev);
+ clear_bit(port->dev_num, dev_map);
return -1;
}
+static void ib_umad_kill_port(struct ib_umad_port *port)
+{
+ struct ib_umad_file *file;
+ int id;
+
+ class_set_devdata(port->class_dev, NULL);
+ class_set_devdata(port->sm_class_dev, NULL);
+
+ class_device_destroy(umad_class, port->dev->dev);
+ class_device_destroy(umad_class, port->sm_dev->dev);
+
+ cdev_del(port->dev);
+ cdev_del(port->sm_dev);
+
+ spin_lock(&port_lock);
+ umad_port[port->dev_num] = NULL;
+ spin_unlock(&port_lock);
+
+ down_write(&port->mutex);
+
+ port->ib_dev = NULL;
+
+ list_for_each_entry(file, &port->file_list, port_list)
+ for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) {
+ if (!file->agent[id])
+ continue;
+ ib_dereg_mr(file->mr[id]);
+ ib_unregister_mad_agent(file->agent[id]);
+ file->agent[id] = NULL;
+ }
+
+ up_write(&port->mutex);
+
+ clear_bit(port->dev_num, dev_map);
+}
+
static void ib_umad_add_one(struct ib_device *device)
{
struct ib_umad_device *umad_dev;
@@ -831,15 +889,12 @@ static void ib_umad_add_one(struct ib_device *device)
e = device->phys_port_cnt;
}
- umad_dev = kmalloc(sizeof *umad_dev +
+ umad_dev = kzalloc(sizeof *umad_dev +
(e - s + 1) * sizeof (struct ib_umad_port),
GFP_KERNEL);
if (!umad_dev)
return;
- memset(umad_dev, 0, sizeof *umad_dev +
- (e - s + 1) * sizeof (struct ib_umad_port));
-
kref_init(&umad_dev->ref);
umad_dev->start_port = s;
@@ -857,10 +912,8 @@ static void ib_umad_add_one(struct ib_device *device)
return;
err:
- while (--i >= s) {
- class_device_unregister(&umad_dev->port[i - s].class_dev);
- class_device_unregister(&umad_dev->port[i - s].sm_class_dev);
- }
+ while (--i >= s)
+ ib_umad_kill_port(&umad_dev->port[i]);
kref_put(&umad_dev->ref, ib_umad_release_dev);
}
@@ -873,10 +926,8 @@ static void ib_umad_remove_one(struct ib_device *device)
if (!umad_dev)
return;
- for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) {
- class_device_unregister(&umad_dev->port[i].class_dev);
- class_device_unregister(&umad_dev->port[i].sm_class_dev);
- }
+ for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)
+ ib_umad_kill_port(&umad_dev->port[i]);
kref_put(&umad_dev->ref, ib_umad_release_dev);
}
@@ -885,8 +936,6 @@ static int __init ib_umad_init(void)
{
int ret;
- spin_lock_init(&map_lock);
-
ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
"infiniband_mad");
if (ret) {
@@ -894,13 +943,14 @@ static int __init ib_umad_init(void)
goto out;
}
- ret = class_register(&umad_class);
- if (ret) {
+ umad_class = class_create(THIS_MODULE, "infiniband_mad");
+ if (IS_ERR(umad_class)) {
+ ret = PTR_ERR(umad_class);
printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
goto out_chrdev;
}
- ret = class_create_file(&umad_class, &class_attr_abi_version);
+ ret = class_create_file(umad_class, &class_attr_abi_version);
if (ret) {
printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
goto out_class;
@@ -915,7 +965,7 @@ static int __init ib_umad_init(void)
return 0;
out_class:
- class_unregister(&umad_class);
+ class_destroy(umad_class);
out_chrdev:
unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
@@ -927,7 +977,7 @@ out:
static void __exit ib_umad_cleanup(void)
{
ib_unregister_client(&umad_client);
- class_unregister(&umad_class);
+ class_destroy(umad_class);
unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 7696022f9a4e..ecb830127865 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -1,6 +1,9 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -36,29 +39,47 @@
#ifndef UVERBS_H
#define UVERBS_H
-/* Include device.h and fs.h until cdev.h is self-sufficient */
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
#include <linux/kref.h>
#include <linux/idr.h>
-#include <ib_verbs.h>
-#include <ib_user_verbs.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
+/*
+ * Our lifetime rules for these structs are the following:
+ *
+ * struct ib_uverbs_device: One reference is held by the module and
+ * released in ib_uverbs_remove_one(). Another reference is taken by
+ * ib_uverbs_open() each time the character special file is opened,
+ * and released in ib_uverbs_release_file() when the file is released.
+ *
+ * struct ib_uverbs_file: One reference is held by the VFS and
+ * released when the file is closed. Another reference is taken when
+ * an asynchronous event queue file is created and released when the
+ * event file is closed.
+ *
+ * struct ib_uverbs_event_file: One reference is held by the VFS and
+ * released when the file is closed. For asynchronous event files,
+ * another reference is held by the corresponding main context file
+ * and released when that file is closed. For completion event files,
+ * a reference is taken when a CQ is created that uses the file, and
+ * released when the CQ is destroyed.
+ */
struct ib_uverbs_device {
+ struct kref ref;
int devnum;
- struct cdev dev;
- struct class_device class_dev;
+ struct cdev *dev;
+ struct class_device *class_dev;
struct ib_device *ib_dev;
- int num_comp;
+ int num_comp_vectors;
};
struct ib_uverbs_event_file {
struct kref ref;
+ struct file *file;
struct ib_uverbs_file *uverbs_file;
spinlock_t lock;
- int fd;
int is_async;
wait_queue_head_t poll_wait;
struct fasync_struct *async_queue;
@@ -67,27 +88,36 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file {
struct kref ref;
+ struct semaphore mutex;
struct ib_uverbs_device *device;
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
- struct ib_uverbs_event_file async_file;
- struct ib_uverbs_event_file comp_file[1];
+ struct ib_uverbs_event_file *async_file;
};
-struct ib_uverbs_async_event {
- struct ib_uverbs_async_event_desc desc;
+struct ib_uverbs_event {
+ union {
+ struct ib_uverbs_async_event_desc async;
+ struct ib_uverbs_comp_event_desc comp;
+ } desc;
struct list_head list;
+ struct list_head obj_list;
+ u32 *counter;
};
-struct ib_uverbs_comp_event {
- struct ib_uverbs_comp_event_desc desc;
- struct list_head list;
+struct ib_uevent_object {
+ struct ib_uobject uobject;
+ struct list_head event_list;
+ u32 events_reported;
};
-struct ib_uobject_mr {
- struct ib_uobject uobj;
- struct page *page_list;
- struct scatterlist *sg_list;
+struct ib_ucq_object {
+ struct ib_uobject uobject;
+ struct ib_uverbs_file *uverbs_file;
+ struct list_head comp_list;
+ struct list_head async_list;
+ u32 comp_events_reported;
+ u32 async_events_reported;
};
extern struct semaphore ib_uverbs_idr_mutex;
@@ -97,10 +127,25 @@ extern struct idr ib_uverbs_mw_idr;
extern struct idr ib_uverbs_ah_idr;
extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr;
+extern struct idr ib_uverbs_srq_idr;
+
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ int is_async, int *fd);
+void ib_uverbs_release_event_file(struct kref *ref);
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+ struct ib_uverbs_event_file *ev_file,
+ struct ib_ucq_object *uobj);
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+ struct ib_uevent_object *uobj);
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+ struct ib_event *event);
int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
void *addr, size_t size, int write);
@@ -112,22 +157,30 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem);
const char __user *buf, int in_len, \
int out_len)
-IB_UVERBS_DECLARE_CMD(query_params);
IB_UVERBS_DECLARE_CMD(get_context);
IB_UVERBS_DECLARE_CMD(query_device);
IB_UVERBS_DECLARE_CMD(query_port);
-IB_UVERBS_DECLARE_CMD(query_gid);
-IB_UVERBS_DECLARE_CMD(query_pkey);
IB_UVERBS_DECLARE_CMD(alloc_pd);
IB_UVERBS_DECLARE_CMD(dealloc_pd);
IB_UVERBS_DECLARE_CMD(reg_mr);
IB_UVERBS_DECLARE_CMD(dereg_mr);
+IB_UVERBS_DECLARE_CMD(create_comp_channel);
IB_UVERBS_DECLARE_CMD(create_cq);
+IB_UVERBS_DECLARE_CMD(poll_cq);
+IB_UVERBS_DECLARE_CMD(req_notify_cq);
IB_UVERBS_DECLARE_CMD(destroy_cq);
IB_UVERBS_DECLARE_CMD(create_qp);
IB_UVERBS_DECLARE_CMD(modify_qp);
IB_UVERBS_DECLARE_CMD(destroy_qp);
+IB_UVERBS_DECLARE_CMD(post_send);
+IB_UVERBS_DECLARE_CMD(post_recv);
+IB_UVERBS_DECLARE_CMD(post_srq_recv);
+IB_UVERBS_DECLARE_CMD(create_ah);
+IB_UVERBS_DECLARE_CMD(destroy_ah);
IB_UVERBS_DECLARE_CMD(attach_mcast);
IB_UVERBS_DECLARE_CMD(detach_mcast);
+IB_UVERBS_DECLARE_CMD(create_srq);
+IB_UVERBS_DECLARE_CMD(modify_srq);
+IB_UVERBS_DECLARE_CMD(destroy_srq);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5f2bbcda4c73..63a74151c60b 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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,6 +34,9 @@
* $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
*/
+#include <linux/file.h>
+#include <linux/fs.h>
+
#include <asm/uaccess.h>
#include "uverbs.h"
@@ -45,29 +49,6 @@
(udata)->outlen = (olen); \
} while (0)
-ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file,
- const char __user *buf,
- int in_len, int out_len)
-{
- struct ib_uverbs_query_params cmd;
- struct ib_uverbs_query_params_resp resp;
-
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- memset(&resp, 0, sizeof resp);
-
- resp.num_cq_events = file->device->num_comp;
-
- if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp))
- return -EFAULT;
-
- return in_len;
-}
-
ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
const char __user *buf,
int in_len, int out_len)
@@ -76,8 +57,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
struct ib_uverbs_get_context_resp resp;
struct ib_udata udata;
struct ib_device *ibdev = file->device->ib_dev;
- int i;
- int ret = in_len;
+ struct ib_ucontext *ucontext;
+ struct file *filp;
+ int ret;
if (out_len < sizeof resp)
return -ENOSPC;
@@ -85,45 +67,72 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ down(&file->mutex);
+
+ if (file->ucontext) {
+ ret = -EINVAL;
+ goto err;
+ }
+
INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
- file->ucontext = ibdev->alloc_ucontext(ibdev, &udata);
- if (IS_ERR(file->ucontext)) {
- ret = PTR_ERR(file->ucontext);
- file->ucontext = NULL;
- return ret;
- }
+ ucontext = ibdev->alloc_ucontext(ibdev, &udata);
+ if (IS_ERR(ucontext))
+ return PTR_ERR(file->ucontext);
- file->ucontext->device = ibdev;
- INIT_LIST_HEAD(&file->ucontext->pd_list);
- INIT_LIST_HEAD(&file->ucontext->mr_list);
- INIT_LIST_HEAD(&file->ucontext->mw_list);
- INIT_LIST_HEAD(&file->ucontext->cq_list);
- INIT_LIST_HEAD(&file->ucontext->qp_list);
- INIT_LIST_HEAD(&file->ucontext->srq_list);
- INIT_LIST_HEAD(&file->ucontext->ah_list);
- spin_lock_init(&file->ucontext->lock);
-
- resp.async_fd = file->async_file.fd;
- for (i = 0; i < file->device->num_comp; ++i)
- if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
- i * sizeof (__u32),
- &file->comp_file[i].fd, sizeof (__u32)))
- goto err;
+ ucontext->device = ibdev;
+ INIT_LIST_HEAD(&ucontext->pd_list);
+ INIT_LIST_HEAD(&ucontext->mr_list);
+ INIT_LIST_HEAD(&ucontext->mw_list);
+ INIT_LIST_HEAD(&ucontext->cq_list);
+ INIT_LIST_HEAD(&ucontext->qp_list);
+ INIT_LIST_HEAD(&ucontext->srq_list);
+ INIT_LIST_HEAD(&ucontext->ah_list);
+
+ resp.num_comp_vectors = file->device->num_comp_vectors;
+
+ filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
+ if (IS_ERR(filp)) {
+ ret = PTR_ERR(filp);
+ goto err_free;
+ }
if (copy_to_user((void __user *) (unsigned long) cmd.response,
- &resp, sizeof resp))
- goto err;
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_file;
+ }
+
+ file->async_file = filp->private_data;
+
+ INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,
+ ib_uverbs_event_handler);
+ ret = ib_register_event_handler(&file->event_handler);
+ if (ret)
+ goto err_file;
+
+ kref_get(&file->async_file->ref);
+ kref_get(&file->ref);
+ file->ucontext = ucontext;
+
+ fd_install(resp.async_fd, filp);
+
+ up(&file->mutex);
return in_len;
-err:
- ibdev->dealloc_ucontext(file->ucontext);
- file->ucontext = NULL;
+err_file:
+ put_unused_fd(resp.async_fd);
+ fput(filp);
+
+err_free:
+ ibdev->dealloc_ucontext(ucontext);
- return -EFAULT;
+err:
+ up(&file->mutex);
+ return ret;
}
ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
@@ -243,62 +252,6 @@ ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
return in_len;
}
-ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file,
- const char __user *buf,
- int in_len, int out_len)
-{
- struct ib_uverbs_query_gid cmd;
- struct ib_uverbs_query_gid_resp resp;
- int ret;
-
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- memset(&resp, 0, sizeof resp);
-
- ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index,
- (union ib_gid *) resp.gid);
- if (ret)
- return ret;
-
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
- &resp, sizeof resp))
- return -EFAULT;
-
- return in_len;
-}
-
-ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file,
- const char __user *buf,
- int in_len, int out_len)
-{
- struct ib_uverbs_query_pkey cmd;
- struct ib_uverbs_query_pkey_resp resp;
- int ret;
-
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- memset(&resp, 0, sizeof resp);
-
- ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index,
- &resp.pkey);
- if (ret)
- return ret;
-
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
- &resp, sizeof resp))
- return -EFAULT;
-
- return in_len;
-}
-
ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
const char __user *buf,
int in_len, int out_len)
@@ -337,24 +290,20 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
pd->uobject = uobj;
atomic_set(&pd->usecnt, 0);
+ down(&ib_uverbs_idr_mutex);
+
retry:
if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
ret = -ENOMEM;
- goto err_pd;
+ goto err_up;
}
- down(&ib_uverbs_idr_mutex);
ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
- up(&ib_uverbs_idr_mutex);
if (ret == -EAGAIN)
goto retry;
if (ret)
- goto err_pd;
-
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->pd_list);
- spin_unlock_irq(&file->ucontext->lock);
+ goto err_up;
memset(&resp, 0, sizeof resp);
resp.pd_handle = uobj->id;
@@ -362,21 +311,22 @@ retry:
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
ret = -EFAULT;
- goto err_list;
+ goto err_idr;
}
- return in_len;
+ down(&file->mutex);
+ list_add_tail(&uobj->list, &file->ucontext->pd_list);
+ up(&file->mutex);
-err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&ib_uverbs_idr_mutex);
- down(&ib_uverbs_idr_mutex);
+ return in_len;
+
+err_idr:
idr_remove(&ib_uverbs_pd_idr, uobj->id);
- up(&ib_uverbs_idr_mutex);
-err_pd:
+err_up:
+ up(&ib_uverbs_idr_mutex);
ib_dealloc_pd(pd);
err:
@@ -410,9 +360,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
kfree(uobj);
@@ -447,6 +397,14 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
return -EINVAL;
+ /*
+ * Local write permission is required if remote write or
+ * remote atomic permission is also requested.
+ */
+ if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
+ !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
+ return -EINVAL;
+
obj = kmalloc(sizeof *obj, GFP_KERNEL);
if (!obj)
return -ENOMEM;
@@ -512,24 +470,22 @@ retry:
resp.mr_handle = obj->uobject.id;
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
- spin_unlock_irq(&file->ucontext->lock);
-
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
ret = -EFAULT;
- goto err_list;
+ goto err_idr;
}
+ down(&file->mutex);
+ list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
+ up(&file->mutex);
+
up(&ib_uverbs_idr_mutex);
return in_len;
-err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&obj->uobject.list);
- spin_unlock_irq(&file->ucontext->lock);
+err_idr:
+ idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
err_unreg:
ib_dereg_mr(mr);
@@ -570,9 +526,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&memobj->uobject.list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj);
@@ -583,6 +539,35 @@ out:
return ret ? ret : in_len;
}
+ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_comp_channel cmd;
+ struct ib_uverbs_create_comp_channel_resp resp;
+ struct file *filp;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
+ if (IS_ERR(filp))
+ return PTR_ERR(filp);
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ put_unused_fd(resp.fd);
+ fput(filp);
+ return -EFAULT;
+ }
+
+ fd_install(resp.fd, filp);
+ return in_len;
+}
+
ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -590,7 +575,8 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_create_cq_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event_file *ev_file = NULL;
struct ib_cq *cq;
int ret;
@@ -604,15 +590,23 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
- if (cmd.event_handler >= file->device->num_comp)
+ if (cmd.comp_vector >= file->device->num_comp_vectors)
return -EINVAL;
+ if (cmd.comp_channel >= 0)
+ ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
+
uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
if (!uobj)
return -ENOMEM;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->uverbs_file = file;
+ uobj->comp_events_reported = 0;
+ uobj->async_events_reported = 0;
+ INIT_LIST_HEAD(&uobj->comp_list);
+ INIT_LIST_HEAD(&uobj->async_list);
cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
file->ucontext, &udata);
@@ -622,53 +616,50 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
}
cq->device = file->device->ib_dev;
- cq->uobject = uobj;
+ cq->uobject = &uobj->uobject;
cq->comp_handler = ib_uverbs_comp_handler;
cq->event_handler = ib_uverbs_cq_event_handler;
- cq->cq_context = file;
+ cq->cq_context = ev_file;
atomic_set(&cq->usecnt, 0);
+ down(&ib_uverbs_idr_mutex);
+
retry:
if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
ret = -ENOMEM;
- goto err_cq;
+ goto err_up;
}
- down(&ib_uverbs_idr_mutex);
- ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id);
- up(&ib_uverbs_idr_mutex);
+ ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
if (ret == -EAGAIN)
goto retry;
if (ret)
- goto err_cq;
-
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->cq_list);
- spin_unlock_irq(&file->ucontext->lock);
+ goto err_up;
memset(&resp, 0, sizeof resp);
- resp.cq_handle = uobj->id;
+ resp.cq_handle = uobj->uobject.id;
resp.cqe = cq->cqe;
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
ret = -EFAULT;
- goto err_list;
+ goto err_idr;
}
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+ up(&file->mutex);
+
+ up(&ib_uverbs_idr_mutex);
+
return in_len;
-err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+err_idr:
+ idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
- down(&ib_uverbs_idr_mutex);
- idr_remove(&ib_uverbs_cq_idr, uobj->id);
+err_up:
up(&ib_uverbs_idr_mutex);
-
-err_cq:
ib_destroy_cq(cq);
err:
@@ -676,25 +667,119 @@ err:
return ret;
}
+ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_poll_cq cmd;
+ struct ib_uverbs_poll_cq_resp *resp;
+ struct ib_cq *cq;
+ struct ib_wc *wc;
+ int ret = 0;
+ int i;
+ int rsize;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
+ if (!wc)
+ return -ENOMEM;
+
+ rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
+ resp = kmalloc(rsize, GFP_KERNEL);
+ if (!resp) {
+ ret = -ENOMEM;
+ goto out_wc;
+ }
+
+ down(&ib_uverbs_idr_mutex);
+ cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+ if (!cq || cq->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ resp->count = ib_poll_cq(cq, cmd.ne, wc);
+
+ for (i = 0; i < resp->count; i++) {
+ resp->wc[i].wr_id = wc[i].wr_id;
+ resp->wc[i].status = wc[i].status;
+ resp->wc[i].opcode = wc[i].opcode;
+ resp->wc[i].vendor_err = wc[i].vendor_err;
+ resp->wc[i].byte_len = wc[i].byte_len;
+ resp->wc[i].imm_data = wc[i].imm_data;
+ resp->wc[i].qp_num = wc[i].qp_num;
+ resp->wc[i].src_qp = wc[i].src_qp;
+ resp->wc[i].wc_flags = wc[i].wc_flags;
+ resp->wc[i].pkey_index = wc[i].pkey_index;
+ resp->wc[i].slid = wc[i].slid;
+ resp->wc[i].sl = wc[i].sl;
+ resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
+ resp->wc[i].port_num = wc[i].port_num;
+ }
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+ kfree(resp);
+
+out_wc:
+ kfree(wc);
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_req_notify_cq cmd;
+ struct ib_cq *cq;
+ int ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+ cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+ if (cq && cq->uobject->context == file->ucontext) {
+ ib_req_notify_cq(cq, cmd.solicited_only ?
+ IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+ ret = in_len;
+ }
+ up(&ib_uverbs_idr_mutex);
+
+ return ret;
+}
+
ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_cq cmd;
- struct ib_cq *cq;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_cq cmd;
+ struct ib_uverbs_destroy_cq_resp resp;
+ struct ib_cq *cq;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event_file *ev_file;
+ u64 user_handle;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext)
goto out;
- uobj = cq->uobject;
+ user_handle = cq->uobject->user_handle;
+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
+ ev_file = cq->cq_context;
ret = ib_destroy_cq(cq);
if (ret)
@@ -702,12 +787,21 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ ib_uverbs_release_ucq(file, ev_file, uobj);
+
+ resp.comp_events_reported = uobj->comp_events_reported;
+ resp.async_events_reported = uobj->async_events_reported;
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);
@@ -721,9 +815,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
struct ib_uverbs_create_qp cmd;
struct ib_uverbs_create_qp_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_uevent_object *uobj;
struct ib_pd *pd;
struct ib_cq *scq, *rcq;
+ struct ib_srq *srq;
struct ib_qp *qp;
struct ib_qp_init_attr attr;
int ret;
@@ -747,10 +842,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
+ srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
if (!pd || pd->uobject->context != file->ucontext ||
!scq || scq->uobject->context != file->ucontext ||
- !rcq || rcq->uobject->context != file->ucontext) {
+ !rcq || rcq->uobject->context != file->ucontext ||
+ (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
ret = -EINVAL;
goto err_up;
}
@@ -759,7 +856,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.qp_context = file;
attr.send_cq = scq;
attr.recv_cq = rcq;
- attr.srq = NULL;
+ attr.srq = srq;
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
attr.qp_type = cmd.qp_type;
@@ -769,8 +866,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.cap.max_recv_sge = cmd.max_recv_sge;
attr.cap.max_inline_data = cmd.max_inline_data;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
qp = pd->device->create_qp(pd, &attr, &udata);
if (IS_ERR(qp)) {
@@ -783,7 +882,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
qp->send_cq = attr.send_cq;
qp->recv_cq = attr.recv_cq;
qp->srq = attr.srq;
- qp->uobject = uobj;
+ qp->uobject = &uobj->uobject;
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
@@ -802,33 +901,31 @@ retry:
goto err_destroy;
}
- ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
if (ret == -EAGAIN)
goto retry;
if (ret)
goto err_destroy;
- resp.qp_handle = uobj->id;
-
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->qp_list);
- spin_unlock_irq(&file->ucontext->lock);
+ resp.qp_handle = uobj->uobject.id;
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
ret = -EFAULT;
- goto err_list;
+ goto err_idr;
}
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
+ up(&file->mutex);
+
up(&ib_uverbs_idr_mutex);
return in_len;
-err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+err_idr:
+ idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);
err_destroy:
ib_destroy_qp(qp);
@@ -927,21 +1024,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_qp cmd;
- struct ib_qp *qp;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_qp cmd;
+ struct ib_uverbs_destroy_qp_resp resp;
+ struct ib_qp *qp;
+ struct ib_uevent_object *uobj;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
goto out;
- uobj = qp->uobject;
+ uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
ret = ib_destroy_qp(qp);
if (ret)
@@ -949,9 +1049,479 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ ib_uverbs_release_uevent(file, uobj);
+
+ resp.events_reported = uobj->events_reported;
+
+ kfree(uobj);
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_post_send cmd;
+ struct ib_uverbs_post_send_resp resp;
+ struct ib_uverbs_send_wr *user_wr;
+ struct ib_send_wr *wr = NULL, *last, *next, *bad_wr;
+ struct ib_qp *qp;
+ int i, sg_ind;
+ ssize_t ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
+ cmd.sge_count * sizeof (struct ib_uverbs_sge))
+ return -EINVAL;
+
+ if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
+ return -EINVAL;
+
+ user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
+ if (!user_wr)
+ return -ENOMEM;
+
+ down(&ib_uverbs_idr_mutex);
+
+ qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+ if (!qp || qp->uobject->context != file->ucontext)
+ goto out;
+
+ sg_ind = 0;
+ last = NULL;
+ for (i = 0; i < cmd.wr_count; ++i) {
+ if (copy_from_user(user_wr,
+ buf + sizeof cmd + i * cmd.wqe_size,
+ cmd.wqe_size)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (user_wr->num_sge + sg_ind > cmd.sge_count) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+ user_wr->num_sge * sizeof (struct ib_sge),
+ GFP_KERNEL);
+ if (!next) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!last)
+ wr = next;
+ else
+ last->next = next;
+ last = next;
+
+ next->next = NULL;
+ next->wr_id = user_wr->wr_id;
+ next->num_sge = user_wr->num_sge;
+ next->opcode = user_wr->opcode;
+ next->send_flags = user_wr->send_flags;
+ next->imm_data = user_wr->imm_data;
+
+ if (qp->qp_type == IB_QPT_UD) {
+ next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
+ user_wr->wr.ud.ah);
+ if (!next->wr.ud.ah) {
+ ret = -EINVAL;
+ goto out;
+ }
+ next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn;
+ next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
+ } else {
+ switch (next->opcode) {
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ case IB_WR_RDMA_READ:
+ next->wr.rdma.remote_addr =
+ user_wr->wr.rdma.remote_addr;
+ next->wr.rdma.rkey =
+ user_wr->wr.rdma.rkey;
+ break;
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ next->wr.atomic.remote_addr =
+ user_wr->wr.atomic.remote_addr;
+ next->wr.atomic.compare_add =
+ user_wr->wr.atomic.compare_add;
+ next->wr.atomic.swap = user_wr->wr.atomic.swap;
+ next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (next->num_sge) {
+ next->sg_list = (void *) next +
+ ALIGN(sizeof *next, sizeof (struct ib_sge));
+ if (copy_from_user(next->sg_list,
+ buf + sizeof cmd +
+ cmd.wr_count * cmd.wqe_size +
+ sg_ind * sizeof (struct ib_sge),
+ next->num_sge * sizeof (struct ib_sge))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ sg_ind += next->num_sge;
+ } else
+ next->sg_list = NULL;
+ }
+
+ resp.bad_wr = 0;
+ ret = qp->device->post_send(qp, wr, &bad_wr);
+ if (ret)
+ for (next = wr; next; next = next->next) {
+ ++resp.bad_wr;
+ if (next == bad_wr)
+ break;
+ }
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ while (wr) {
+ next = wr->next;
+ kfree(wr);
+ wr = next;
+ }
+
+ kfree(user_wr);
+
+ return ret ? ret : in_len;
+}
+
+static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
+ int in_len,
+ u32 wr_count,
+ u32 sge_count,
+ u32 wqe_size)
+{
+ struct ib_uverbs_recv_wr *user_wr;
+ struct ib_recv_wr *wr = NULL, *last, *next;
+ int sg_ind;
+ int i;
+ int ret;
+
+ if (in_len < wqe_size * wr_count +
+ sge_count * sizeof (struct ib_uverbs_sge))
+ return ERR_PTR(-EINVAL);
+
+ if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
+ return ERR_PTR(-EINVAL);
+
+ user_wr = kmalloc(wqe_size, GFP_KERNEL);
+ if (!user_wr)
+ return ERR_PTR(-ENOMEM);
+
+ sg_ind = 0;
+ last = NULL;
+ for (i = 0; i < wr_count; ++i) {
+ if (copy_from_user(user_wr, buf + i * wqe_size,
+ wqe_size)) {
+ ret = -EFAULT;
+ goto err;
+ }
+
+ if (user_wr->num_sge + sg_ind > sge_count) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+ user_wr->num_sge * sizeof (struct ib_sge),
+ GFP_KERNEL);
+ if (!next) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (!last)
+ wr = next;
+ else
+ last->next = next;
+ last = next;
+
+ next->next = NULL;
+ next->wr_id = user_wr->wr_id;
+ next->num_sge = user_wr->num_sge;
+
+ if (next->num_sge) {
+ next->sg_list = (void *) next +
+ ALIGN(sizeof *next, sizeof (struct ib_sge));
+ if (copy_from_user(next->sg_list,
+ buf + wr_count * wqe_size +
+ sg_ind * sizeof (struct ib_sge),
+ next->num_sge * sizeof (struct ib_sge))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ sg_ind += next->num_sge;
+ } else
+ next->sg_list = NULL;
+ }
+
+ kfree(user_wr);
+ return wr;
+
+err:
+ kfree(user_wr);
+
+ while (wr) {
+ next = wr->next;
+ kfree(wr);
+ wr = next;
+ }
+
+ return ERR_PTR(ret);
+}
+
+ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_post_recv cmd;
+ struct ib_uverbs_post_recv_resp resp;
+ struct ib_recv_wr *wr, *next, *bad_wr;
+ struct ib_qp *qp;
+ ssize_t ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+ in_len - sizeof cmd, cmd.wr_count,
+ cmd.sge_count, cmd.wqe_size);
+ if (IS_ERR(wr))
+ return PTR_ERR(wr);
+
+ down(&ib_uverbs_idr_mutex);
+
+ qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+ if (!qp || qp->uobject->context != file->ucontext)
+ goto out;
+
+ resp.bad_wr = 0;
+ ret = qp->device->post_recv(qp, wr, &bad_wr);
+ if (ret)
+ for (next = wr; next; next = next->next) {
+ ++resp.bad_wr;
+ if (next == bad_wr)
+ break;
+ }
+
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ while (wr) {
+ next = wr->next;
+ kfree(wr);
+ wr = next;
+ }
+
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_post_srq_recv cmd;
+ struct ib_uverbs_post_srq_recv_resp resp;
+ struct ib_recv_wr *wr, *next, *bad_wr;
+ struct ib_srq *srq;
+ ssize_t ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+ in_len - sizeof cmd, cmd.wr_count,
+ cmd.sge_count, cmd.wqe_size);
+ if (IS_ERR(wr))
+ return PTR_ERR(wr);
+
+ down(&ib_uverbs_idr_mutex);
+
+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+ if (!srq || srq->uobject->context != file->ucontext)
+ goto out;
+
+ resp.bad_wr = 0;
+ ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
+ if (ret)
+ for (next = wr; next; next = next->next) {
+ ++resp.bad_wr;
+ if (next == bad_wr)
+ break;
+ }
+
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ while (wr) {
+ next = wr->next;
+ kfree(wr);
+ wr = next;
+ }
+
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_ah cmd;
+ struct ib_uverbs_create_ah_resp resp;
+ struct ib_uobject *uobj;
+ struct ib_pd *pd;
+ struct ib_ah *ah;
+ struct ib_ah_attr attr;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+ if (!uobj)
+ return -ENOMEM;
+
+ down(&ib_uverbs_idr_mutex);
+
+ pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+ if (!pd || pd->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto err_up;
+ }
+
+ uobj->user_handle = cmd.user_handle;
+ uobj->context = file->ucontext;
+
+ attr.dlid = cmd.attr.dlid;
+ attr.sl = cmd.attr.sl;
+ attr.src_path_bits = cmd.attr.src_path_bits;
+ attr.static_rate = cmd.attr.static_rate;
+ attr.port_num = cmd.attr.port_num;
+ attr.grh.flow_label = cmd.attr.grh.flow_label;
+ attr.grh.sgid_index = cmd.attr.grh.sgid_index;
+ attr.grh.hop_limit = cmd.attr.grh.hop_limit;
+ attr.grh.traffic_class = cmd.attr.grh.traffic_class;
+ memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
+
+ ah = ib_create_ah(pd, &attr);
+ if (IS_ERR(ah)) {
+ ret = PTR_ERR(ah);
+ goto err_up;
+ }
+
+ ah->uobject = uobj;
+
+retry:
+ if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto err_destroy;
+ }
+
+ ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);
+
+ if (ret == -EAGAIN)
+ goto retry;
+ if (ret)
+ goto err_destroy;
+
+ resp.ah_handle = uobj->id;
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_idr;
+ }
+
+ down(&file->mutex);
+ list_add_tail(&uobj->list, &file->ucontext->ah_list);
+ up(&file->mutex);
+
+ up(&ib_uverbs_idr_mutex);
+
+ return in_len;
+
+err_idr:
+ idr_remove(&ib_uverbs_ah_idr, uobj->id);
+
+err_destroy:
+ ib_destroy_ah(ah);
+
+err_up:
+ up(&ib_uverbs_idr_mutex);
+
+ kfree(uobj);
+ return ret;
+}
+
+ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len, int out_len)
+{
+ struct ib_uverbs_destroy_ah cmd;
+ struct ib_ah *ah;
+ struct ib_uobject *uobj;
+ int ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+
+ ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
+ if (!ah || ah->uobject->context != file->ucontext)
+ goto out;
+
+ uobj = ah->uobject;
+
+ ret = ib_destroy_ah(ah);
+ if (ret)
+ goto out;
+
+ idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
+
+ down(&file->mutex);
list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
kfree(uobj);
@@ -1004,3 +1574,189 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
return ret ? ret : in_len;
}
+
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_srq cmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ struct ib_uevent_object *uobj;
+ struct ib_pd *pd;
+ struct ib_srq *srq;
+ struct ib_srq_init_attr attr;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+ if (!uobj)
+ return -ENOMEM;
+
+ down(&ib_uverbs_idr_mutex);
+
+ pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+
+ if (!pd || pd->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto err_up;
+ }
+
+ attr.event_handler = ib_uverbs_srq_event_handler;
+ attr.srq_context = file;
+ attr.attr.max_wr = cmd.max_wr;
+ attr.attr.max_sge = cmd.max_sge;
+ attr.attr.srq_limit = cmd.srq_limit;
+
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
+
+ srq = pd->device->create_srq(pd, &attr, &udata);
+ if (IS_ERR(srq)) {
+ ret = PTR_ERR(srq);
+ goto err_up;
+ }
+
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->uobject = &uobj->uobject;
+ srq->event_handler = attr.event_handler;
+ srq->srq_context = attr.srq_context;
+ atomic_inc(&pd->usecnt);
+ atomic_set(&srq->usecnt, 0);
+
+ memset(&resp, 0, sizeof resp);
+
+retry:
+ if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto err_destroy;
+ }
+
+ ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
+
+ if (ret == -EAGAIN)
+ goto retry;
+ if (ret)
+ goto err_destroy;
+
+ resp.srq_handle = uobj->uobject.id;
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_idr;
+ }
+
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+ up(&file->mutex);
+
+ up(&ib_uverbs_idr_mutex);
+
+ return in_len;
+
+err_idr:
+ idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
+
+err_destroy:
+ ib_destroy_srq(srq);
+
+err_up:
+ up(&ib_uverbs_idr_mutex);
+
+ kfree(uobj);
+ return ret;
+}
+
+ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_modify_srq cmd;
+ struct ib_srq *srq;
+ struct ib_srq_attr attr;
+ int ret;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+
+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+ if (!srq || srq->uobject->context != file->ucontext) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ attr.max_wr = cmd.max_wr;
+ attr.max_sge = cmd.max_sge;
+ attr.srq_limit = cmd.srq_limit;
+
+ ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_destroy_srq cmd;
+ struct ib_uverbs_destroy_srq_resp resp;
+ struct ib_srq *srq;
+ struct ib_uevent_object *uobj;
+ int ret = -EINVAL;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ down(&ib_uverbs_idr_mutex);
+
+ memset(&resp, 0, sizeof resp);
+
+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+ if (!srq || srq->uobject->context != file->ucontext)
+ goto out;
+
+ uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
+
+ ret = ib_destroy_srq(srq);
+ if (ret)
+ goto out;
+
+ idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ ib_uverbs_release_uevent(file, uobj);
+
+ resp.events_reported = uobj->events_reported;
+
+ kfree(uobj);
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
+out:
+ up(&ib_uverbs_idr_mutex);
+
+ return ret ? ret : in_len;
+}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index eb99e693dec2..de6581d7cb8d 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -1,6 +1,9 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -41,6 +44,7 @@
#include <linux/poll.h>
#include <linux/file.h>
#include <linux/mount.h>
+#include <linux/cdev.h>
#include <asm/uaccess.h>
@@ -60,6 +64,8 @@ enum {
#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
+static struct class *uverbs_class;
+
DECLARE_MUTEX(ib_uverbs_idr_mutex);
DEFINE_IDR(ib_uverbs_pd_idr);
DEFINE_IDR(ib_uverbs_mr_idr);
@@ -67,30 +73,40 @@ DEFINE_IDR(ib_uverbs_mw_idr);
DEFINE_IDR(ib_uverbs_ah_idr);
DEFINE_IDR(ib_uverbs_cq_idr);
DEFINE_IDR(ib_uverbs_qp_idr);
+DEFINE_IDR(ib_uverbs_srq_idr);
static spinlock_t map_lock;
+static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len) = {
- [IB_USER_VERBS_CMD_QUERY_PARAMS] = ib_uverbs_query_params,
- [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
- [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
- [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
- [IB_USER_VERBS_CMD_QUERY_GID] = ib_uverbs_query_gid,
- [IB_USER_VERBS_CMD_QUERY_PKEY] = ib_uverbs_query_pkey,
- [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
- [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
- [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
- [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
- [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
- [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
- [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
- [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
- [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
- [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
- [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
+ [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
+ [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,
+ [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,
+ [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
+ [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
+ [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
+ [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
+ [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
+ [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
+ [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,
+ [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,
+ [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,
+ [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,
+ [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,
+ [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
+ [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,
+ [IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,
+ [IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,
+ [IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,
+ [IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,
+ [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
+ [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
+ [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
+ [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
+ [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
};
static struct vfsmount *uverbs_event_mnt;
@@ -98,7 +114,54 @@ static struct vfsmount *uverbs_event_mnt;
static void ib_uverbs_add_one(struct ib_device *device);
static void ib_uverbs_remove_one(struct ib_device *device);
-static int ib_dealloc_ucontext(struct ib_ucontext *context)
+static void ib_uverbs_release_dev(struct kref *ref)
+{
+ struct ib_uverbs_device *dev =
+ container_of(ref, struct ib_uverbs_device, ref);
+
+ kfree(dev);
+}
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+ struct ib_uverbs_event_file *ev_file,
+ struct ib_ucq_object *uobj)
+{
+ struct ib_uverbs_event *evt, *tmp;
+
+ if (ev_file) {
+ spin_lock_irq(&ev_file->lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&ev_file->lock);
+
+ kref_put(&ev_file->ref, ib_uverbs_release_event_file);
+ }
+
+ spin_lock_irq(&file->async_file->lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file->lock);
+}
+
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+ struct ib_uevent_object *uobj)
+{
+ struct ib_uverbs_event *evt, *tmp;
+
+ spin_lock_irq(&file->async_file->lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file->lock);
+}
+
+static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
+ struct ib_ucontext *context)
{
struct ib_uobject *uobj, *tmp;
@@ -107,36 +170,60 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
down(&ib_uverbs_idr_mutex);
- /* XXX Free AHs */
+ list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
+ struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
+ idr_remove(&ib_uverbs_ah_idr, uobj->id);
+ ib_destroy_ah(ah);
+ list_del(&uobj->list);
+ kfree(uobj);
+ }
list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+ struct ib_uevent_object *uevent =
+ container_of(uobj, struct ib_uevent_object, uobject);
idr_remove(&ib_uverbs_qp_idr, uobj->id);
ib_destroy_qp(qp);
list_del(&uobj->list);
- kfree(uobj);
+ ib_uverbs_release_uevent(file, uevent);
+ kfree(uevent);
}
list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+ struct ib_uverbs_event_file *ev_file = cq->cq_context;
+ struct ib_ucq_object *ucq =
+ container_of(uobj, struct ib_ucq_object, uobject);
idr_remove(&ib_uverbs_cq_idr, uobj->id);
ib_destroy_cq(cq);
list_del(&uobj->list);
- kfree(uobj);
+ ib_uverbs_release_ucq(file, ev_file, ucq);
+ kfree(ucq);
+ }
+
+ list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+ struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+ struct ib_uevent_object *uevent =
+ container_of(uobj, struct ib_uevent_object, uobject);
+ idr_remove(&ib_uverbs_srq_idr, uobj->id);
+ ib_destroy_srq(srq);
+ list_del(&uobj->list);
+ ib_uverbs_release_uevent(file, uevent);
+ kfree(uevent);
}
- /* XXX Free SRQs */
/* XXX Free MWs */
list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id);
+ struct ib_device *mrdev = mr->device;
struct ib_umem_object *memobj;
idr_remove(&ib_uverbs_mr_idr, uobj->id);
ib_dereg_mr(mr);
memobj = container_of(uobj, struct ib_umem_object, uobject);
- ib_umem_release_on_close(mr->device, &memobj->umem);
+ ib_umem_release_on_close(mrdev, &memobj->umem);
list_del(&uobj->list);
kfree(memobj);
@@ -161,6 +248,8 @@ static void ib_uverbs_release_file(struct kref *ref)
container_of(ref, struct ib_uverbs_file, ref);
module_put(file->device->ib_dev->owner);
+ kref_put(&file->device->ref, ib_uverbs_release_dev);
+
kfree(file);
}
@@ -168,46 +257,42 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
{
struct ib_uverbs_event_file *file = filp->private_data;
- void *event;
+ struct ib_uverbs_event *event;
int eventsz;
int ret = 0;
spin_lock_irq(&file->lock);
- while (list_empty(&file->event_list) && file->fd >= 0) {
+ while (list_empty(&file->event_list)) {
spin_unlock_irq(&file->lock);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(file->poll_wait,
- !list_empty(&file->event_list) ||
- file->fd < 0))
+ !list_empty(&file->event_list)))
return -ERESTARTSYS;
spin_lock_irq(&file->lock);
}
- if (file->fd < 0) {
- spin_unlock_irq(&file->lock);
- return -ENODEV;
- }
+ event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
- if (file->is_async) {
- event = list_entry(file->event_list.next,
- struct ib_uverbs_async_event, list);
+ if (file->is_async)
eventsz = sizeof (struct ib_uverbs_async_event_desc);
- } else {
- event = list_entry(file->event_list.next,
- struct ib_uverbs_comp_event, list);
+ else
eventsz = sizeof (struct ib_uverbs_comp_event_desc);
- }
if (eventsz > count) {
ret = -EINVAL;
event = NULL;
- } else
+ } else {
list_del(file->event_list.next);
+ if (event->counter) {
+ ++(*event->counter);
+ list_del(&event->obj_list);
+ }
+ }
spin_unlock_irq(&file->lock);
@@ -232,29 +317,19 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
poll_wait(filp, &file->poll_wait, wait);
spin_lock_irq(&file->lock);
- if (file->fd < 0)
- pollflags = POLLERR;
- else if (!list_empty(&file->event_list))
+ if (!list_empty(&file->event_list))
pollflags = POLLIN | POLLRDNORM;
spin_unlock_irq(&file->lock);
return pollflags;
}
-static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
+void ib_uverbs_release_event_file(struct kref *ref)
{
- struct list_head *entry, *tmp;
+ struct ib_uverbs_event_file *file =
+ container_of(ref, struct ib_uverbs_event_file, ref);
- spin_lock_irq(&file->lock);
- if (file->fd != -1) {
- file->fd = -1;
- list_for_each_safe(entry, tmp, &file->event_list)
- if (file->is_async)
- kfree(list_entry(entry, struct ib_uverbs_async_event, list));
- else
- kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
- }
- spin_unlock_irq(&file->lock);
+ kfree(file);
}
static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
@@ -267,21 +342,30 @@ static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
{
struct ib_uverbs_event_file *file = filp->private_data;
+ struct ib_uverbs_event *entry, *tmp;
+
+ spin_lock_irq(&file->lock);
+ file->file = NULL;
+ list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
+ if (entry->counter)
+ list_del(&entry->obj_list);
+ kfree(entry);
+ }
+ spin_unlock_irq(&file->lock);
- ib_uverbs_event_release(file);
ib_uverbs_event_fasync(-1, filp, 0);
- kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+
+ if (file->is_async) {
+ ib_unregister_event_handler(&file->uverbs_file->event_handler);
+ kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+ }
+ kref_put(&file->ref, ib_uverbs_release_event_file);
return 0;
}
static struct file_operations uverbs_event_fops = {
- /*
- * No .owner field since we artificially create event files,
- * so there is no increment to the module reference count in
- * the open path. All event files come from a uverbs command
- * file, which already takes a module reference, so this is OK.
- */
+ .owner = THIS_MODULE,
.read = ib_uverbs_event_read,
.poll = ib_uverbs_event_poll,
.release = ib_uverbs_event_close,
@@ -290,100 +374,201 @@ static struct file_operations uverbs_event_fops = {
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
{
- struct ib_uverbs_file *file = cq_context;
- struct ib_uverbs_comp_event *entry;
- unsigned long flags;
+ struct ib_uverbs_event_file *file = cq_context;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event *entry;
+ unsigned long flags;
+
+ if (!file)
+ return;
+
+ spin_lock_irqsave(&file->lock, flags);
+ if (!file->file) {
+ spin_unlock_irqrestore(&file->lock, flags);
+ return;
+ }
entry = kmalloc(sizeof *entry, GFP_ATOMIC);
- if (!entry)
+ if (!entry) {
+ spin_unlock_irqrestore(&file->lock, flags);
return;
+ }
+
+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
- entry->desc.cq_handle = cq->uobject->user_handle;
+ entry->desc.comp.cq_handle = cq->uobject->user_handle;
+ entry->counter = &uobj->comp_events_reported;
- spin_lock_irqsave(&file->comp_file[0].lock, flags);
- list_add_tail(&entry->list, &file->comp_file[0].event_list);
- spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
+ list_add_tail(&entry->list, &file->event_list);
+ list_add_tail(&entry->obj_list, &uobj->comp_list);
+ spin_unlock_irqrestore(&file->lock, flags);
- wake_up_interruptible(&file->comp_file[0].poll_wait);
- kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN);
+ wake_up_interruptible(&file->poll_wait);
+ kill_fasync(&file->async_queue, SIGIO, POLL_IN);
}
static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
- __u64 element, __u64 event)
+ __u64 element, __u64 event,
+ struct list_head *obj_list,
+ u32 *counter)
{
- struct ib_uverbs_async_event *entry;
+ struct ib_uverbs_event *entry;
unsigned long flags;
+ spin_lock_irqsave(&file->async_file->lock, flags);
+ if (!file->async_file->file) {
+ spin_unlock_irqrestore(&file->async_file->lock, flags);
+ return;
+ }
+
entry = kmalloc(sizeof *entry, GFP_ATOMIC);
- if (!entry)
+ if (!entry) {
+ spin_unlock_irqrestore(&file->async_file->lock, flags);
return;
+ }
- entry->desc.element = element;
- entry->desc.event_type = event;
+ entry->desc.async.element = element;
+ entry->desc.async.event_type = event;
+ entry->counter = counter;
- spin_lock_irqsave(&file->async_file.lock, flags);
- list_add_tail(&entry->list, &file->async_file.event_list);
- spin_unlock_irqrestore(&file->async_file.lock, flags);
+ list_add_tail(&entry->list, &file->async_file->event_list);
+ if (obj_list)
+ list_add_tail(&entry->obj_list, obj_list);
+ spin_unlock_irqrestore(&file->async_file->lock, flags);
- wake_up_interruptible(&file->async_file.poll_wait);
- kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN);
+ wake_up_interruptible(&file->async_file->poll_wait);
+ kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
}
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
{
- ib_uverbs_async_handler(context_ptr,
- event->element.cq->uobject->user_handle,
- event->event);
+ struct ib_ucq_object *uobj = container_of(event->element.cq->uobject,
+ struct ib_ucq_object, uobject);
+
+ ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle,
+ event->event, &uobj->async_list,
+ &uobj->async_events_reported);
+
}
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
{
- ib_uverbs_async_handler(context_ptr,
- event->element.qp->uobject->user_handle,
- event->event);
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.qp->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
+}
+
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
+{
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.srq->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
}
-static void ib_uverbs_event_handler(struct ib_event_handler *handler,
- struct ib_event *event)
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+ struct ib_event *event)
{
struct ib_uverbs_file *file =
container_of(handler, struct ib_uverbs_file, event_handler);
- ib_uverbs_async_handler(file, event->element.port_num, event->event);
+ ib_uverbs_async_handler(file, event->element.port_num, event->event,
+ NULL, NULL);
}
-static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
- struct ib_uverbs_file *uverbs_file)
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ int is_async, int *fd)
{
+ struct ib_uverbs_event_file *ev_file;
struct file *filp;
+ int ret;
- spin_lock_init(&file->lock);
- INIT_LIST_HEAD(&file->event_list);
- init_waitqueue_head(&file->poll_wait);
- file->uverbs_file = uverbs_file;
- file->async_queue = NULL;
-
- file->fd = get_unused_fd();
- if (file->fd < 0)
- return file->fd;
+ ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
+ if (!ev_file)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&ev_file->ref);
+ spin_lock_init(&ev_file->lock);
+ INIT_LIST_HEAD(&ev_file->event_list);
+ init_waitqueue_head(&ev_file->poll_wait);
+ ev_file->uverbs_file = uverbs_file;
+ ev_file->async_queue = NULL;
+ ev_file->is_async = is_async;
+
+ *fd = get_unused_fd();
+ if (*fd < 0) {
+ ret = *fd;
+ goto err;
+ }
filp = get_empty_filp();
if (!filp) {
- put_unused_fd(file->fd);
- return -ENFILE;
+ ret = -ENFILE;
+ goto err_fd;
}
- filp->f_op = &uverbs_event_fops;
+ ev_file->file = filp;
+
+ /*
+ * fops_get() can't fail here, because we're coming from a
+ * system call on a uverbs file, which will already have a
+ * module reference.
+ */
+ filp->f_op = fops_get(&uverbs_event_fops);
filp->f_vfsmnt = mntget(uverbs_event_mnt);
filp->f_dentry = dget(uverbs_event_mnt->mnt_root);
filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
filp->f_flags = O_RDONLY;
filp->f_mode = FMODE_READ;
- filp->private_data = file;
+ filp->private_data = ev_file;
- fd_install(file->fd, filp);
+ return filp;
- return 0;
+err_fd:
+ put_unused_fd(*fd);
+
+err:
+ kfree(ev_file);
+ return ERR_PTR(ret);
+}
+
+/*
+ * Look up a completion event file by FD. If lookup is successful,
+ * takes a ref to the event file struct that it returns; if
+ * unsuccessful, returns NULL.
+ */
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
+{
+ struct ib_uverbs_event_file *ev_file = NULL;
+ struct file *filp;
+
+ filp = fget(fd);
+ if (!filp)
+ return NULL;
+
+ if (filp->f_op != &uverbs_event_fops)
+ goto out;
+
+ ev_file = filp->private_data;
+ if (ev_file->is_async) {
+ ev_file = NULL;
+ goto out;
+ }
+
+ kref_get(&ev_file->ref);
+
+out:
+ fput(filp);
+ return ev_file;
}
static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
@@ -401,11 +586,13 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count)
return -EINVAL;
- if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table))
+ if (hdr.command < 0 ||
+ hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+ !uverbs_cmd_table[hdr.command] ||
+ !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
return -EINVAL;
- if (!file->ucontext &&
- hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&
+ if (!file->ucontext &&
hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
return -EINVAL;
@@ -425,60 +612,45 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
static int ib_uverbs_open(struct inode *inode, struct file *filp)
{
- struct ib_uverbs_device *dev =
- container_of(inode->i_cdev, struct ib_uverbs_device, dev);
+ struct ib_uverbs_device *dev;
struct ib_uverbs_file *file;
- int i = 0;
int ret;
- if (!try_module_get(dev->ib_dev->owner))
- return -ENODEV;
-
- file = kmalloc(sizeof *file +
- (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
- GFP_KERNEL);
- if (!file)
- return -ENOMEM;
-
- file->device = dev;
- kref_init(&file->ref);
+ spin_lock(&map_lock);
+ dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
+ if (dev)
+ kref_get(&dev->ref);
+ spin_unlock(&map_lock);
- file->ucontext = NULL;
+ if (!dev)
+ return -ENXIO;
- ret = ib_uverbs_event_init(&file->async_file, file);
- if (ret)
+ if (!try_module_get(dev->ib_dev->owner)) {
+ ret = -ENODEV;
goto err;
+ }
- file->async_file.is_async = 1;
-
- kref_get(&file->ref);
-
- for (i = 0; i < dev->num_comp; ++i) {
- ret = ib_uverbs_event_init(&file->comp_file[i], file);
- if (ret)
- goto err_async;
- kref_get(&file->ref);
- file->comp_file[i].is_async = 0;
+ file = kmalloc(sizeof *file, GFP_KERNEL);
+ if (!file) {
+ ret = -ENOMEM;
+ goto err_module;
}
+ file->device = dev;
+ file->ucontext = NULL;
+ file->async_file = NULL;
+ kref_init(&file->ref);
+ init_MUTEX(&file->mutex);
filp->private_data = file;
- INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,
- ib_uverbs_event_handler);
- if (ib_register_event_handler(&file->event_handler))
- goto err_async;
-
return 0;
-err_async:
- while (i--)
- ib_uverbs_event_release(&file->comp_file[i]);
-
- ib_uverbs_event_release(&file->async_file);
+err_module:
+ module_put(dev->ib_dev->owner);
err:
- kref_put(&file->ref, ib_uverbs_release_file);
+ kref_put(&dev->ref, ib_uverbs_release_dev);
return ret;
}
@@ -486,14 +658,11 @@ err:
static int ib_uverbs_close(struct inode *inode, struct file *filp)
{
struct ib_uverbs_file *file = filp->private_data;
- int i;
- ib_unregister_event_handler(&file->event_handler);
- ib_uverbs_event_release(&file->async_file);
- ib_dealloc_ucontext(file->ucontext);
+ ib_uverbs_cleanup_ucontext(file, file->ucontext);
- for (i = 0; i < file->device->num_comp; ++i)
- ib_uverbs_event_release(&file->comp_file[i]);
+ if (file->async_file)
+ kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
kref_put(&file->ref, ib_uverbs_release_file);
@@ -523,27 +692,25 @@ static struct ib_client uverbs_client = {
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
{
- struct ib_uverbs_device *dev =
- container_of(class_dev, struct ib_uverbs_device, class_dev);
+ struct ib_uverbs_device *dev = class_get_devdata(class_dev);
+
+ if (!dev)
+ return -ENODEV;
return sprintf(buf, "%s\n", dev->ib_dev->name);
}
static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
-static void ib_uverbs_release_class_dev(struct class_device *class_dev)
+static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
{
- struct ib_uverbs_device *dev =
- container_of(class_dev, struct ib_uverbs_device, class_dev);
+ struct ib_uverbs_device *dev = class_get_devdata(class_dev);
- cdev_del(&dev->dev);
- clear_bit(dev->devnum, dev_map);
- kfree(dev);
-}
+ if (!dev)
+ return -ENODEV;
-static struct class uverbs_class = {
- .name = "infiniband_verbs",
- .release = ib_uverbs_release_class_dev
-};
+ return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+}
+static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
static ssize_t show_abi_version(struct class *class, char *buf)
{
@@ -558,11 +725,11 @@ static void ib_uverbs_add_one(struct ib_device *device)
if (!device->alloc_ucontext)
return;
- uverbs_dev = kmalloc(sizeof *uverbs_dev, GFP_KERNEL);
+ uverbs_dev = kzalloc(sizeof *uverbs_dev, GFP_KERNEL);
if (!uverbs_dev)
return;
- memset(uverbs_dev, 0, sizeof *uverbs_dev);
+ kref_init(&uverbs_dev->ref);
spin_lock(&map_lock);
uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -573,41 +740,49 @@ static void ib_uverbs_add_one(struct ib_device *device)
set_bit(uverbs_dev->devnum, dev_map);
spin_unlock(&map_lock);
- uverbs_dev->ib_dev = device;
- uverbs_dev->num_comp = 1;
+ uverbs_dev->ib_dev = device;
+ uverbs_dev->num_comp_vectors = 1;
- if (device->mmap)
- cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops);
- else
- cdev_init(&uverbs_dev->dev, &uverbs_fops);
- uverbs_dev->dev.owner = THIS_MODULE;
- kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);
- if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+ uverbs_dev->dev = cdev_alloc();
+ if (!uverbs_dev->dev)
goto err;
+ uverbs_dev->dev->owner = THIS_MODULE;
+ uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+ kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
+ if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+ goto err_cdev;
- uverbs_dev->class_dev.class = &uverbs_class;
- uverbs_dev->class_dev.dev = device->dma_device;
- uverbs_dev->class_dev.devt = uverbs_dev->dev.dev;
- snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum);
- if (class_device_register(&uverbs_dev->class_dev))
+ uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
+ uverbs_dev->dev->dev,
+ device->dma_device,
+ "uverbs%d", uverbs_dev->devnum);
+ if (IS_ERR(uverbs_dev->class_dev))
goto err_cdev;
- if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
+ class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
+
+ if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
goto err_class;
+ if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
+ goto err_class;
+
+ spin_lock(&map_lock);
+ dev_table[uverbs_dev->devnum] = uverbs_dev;
+ spin_unlock(&map_lock);
ib_set_client_data(device, &uverbs_client, uverbs_dev);
return;
err_class:
- class_device_unregister(&uverbs_dev->class_dev);
+ class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
err_cdev:
- cdev_del(&uverbs_dev->dev);
+ cdev_del(uverbs_dev->dev);
clear_bit(uverbs_dev->devnum, dev_map);
err:
- kfree(uverbs_dev);
+ kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
return;
}
@@ -618,7 +793,16 @@ static void ib_uverbs_remove_one(struct ib_device *device)
if (!uverbs_dev)
return;
- class_device_unregister(&uverbs_dev->class_dev);
+ class_set_devdata(uverbs_dev->class_dev, NULL);
+ class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
+ cdev_del(uverbs_dev->dev);
+
+ spin_lock(&map_lock);
+ dev_table[uverbs_dev->devnum] = NULL;
+ spin_unlock(&map_lock);
+
+ clear_bit(uverbs_dev->devnum, dev_map);
+ kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
}
static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
@@ -648,13 +832,14 @@ static int __init ib_uverbs_init(void)
goto out;
}
- ret = class_register(&uverbs_class);
- if (ret) {
+ uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
+ if (IS_ERR(uverbs_class)) {
+ ret = PTR_ERR(uverbs_class);
printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
goto out_chrdev;
}
- ret = class_create_file(&uverbs_class, &class_attr_abi_version);
+ ret = class_create_file(uverbs_class, &class_attr_abi_version);
if (ret) {
printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
goto out_class;
@@ -688,7 +873,7 @@ out_fs:
unregister_filesystem(&uverbs_event_fs);
out_class:
- class_unregister(&uverbs_class);
+ class_destroy(uverbs_class);
out_chrdev:
unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
@@ -702,8 +887,15 @@ static void __exit ib_uverbs_cleanup(void)
ib_unregister_client(&uverbs_client);
mntput(uverbs_event_mnt);
unregister_filesystem(&uverbs_event_fs);
- class_unregister(&uverbs_class);
+ class_destroy(uverbs_class);
unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+ idr_destroy(&ib_uverbs_pd_idr);
+ idr_destroy(&ib_uverbs_mr_idr);
+ idr_destroy(&ib_uverbs_mw_idr);
+ idr_destroy(&ib_uverbs_ah_idr);
+ idr_destroy(&ib_uverbs_cq_idr);
+ idr_destroy(&ib_uverbs_qp_idr);
+ idr_destroy(&ib_uverbs_srq_idr);
}
module_init(ib_uverbs_init);
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
index ed550f6595bd..36a32c315668 100644
--- a/drivers/infiniband/core/uverbs_mem.c
+++ b/drivers/infiniband/core/uverbs_mem.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 506fdf1f2a26..72d3ef786db5 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -4,6 +4,7 @@
* Copyright (c) 2004 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -40,8 +41,8 @@
#include <linux/errno.h>
#include <linux/err.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
/* Protection domains */
@@ -153,6 +154,66 @@ int ib_destroy_ah(struct ib_ah *ah)
}
EXPORT_SYMBOL(ib_destroy_ah);
+/* Shared receive queues */
+
+struct ib_srq *ib_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *srq_init_attr)
+{
+ struct ib_srq *srq;
+
+ if (!pd->device->create_srq)
+ return ERR_PTR(-ENOSYS);
+
+ srq = pd->device->create_srq(pd, srq_init_attr, NULL);
+
+ if (!IS_ERR(srq)) {
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->uobject = NULL;
+ srq->event_handler = srq_init_attr->event_handler;
+ srq->srq_context = srq_init_attr->srq_context;
+ atomic_inc(&pd->usecnt);
+ atomic_set(&srq->usecnt, 0);
+ }
+
+ return srq;
+}
+EXPORT_SYMBOL(ib_create_srq);
+
+int ib_modify_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask)
+{
+ return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);
+}
+EXPORT_SYMBOL(ib_modify_srq);
+
+int ib_query_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr)
+{
+ return srq->device->query_srq ?
+ srq->device->query_srq(srq, srq_attr) : -ENOSYS;
+}
+EXPORT_SYMBOL(ib_query_srq);
+
+int ib_destroy_srq(struct ib_srq *srq)
+{
+ struct ib_pd *pd;
+ int ret;
+
+ if (atomic_read(&srq->usecnt))
+ return -EBUSY;
+
+ pd = srq->pd;
+
+ ret = srq->device->destroy_srq(srq);
+ if (!ret)
+ atomic_dec(&pd->usecnt);
+
+ return ret;
+}
+EXPORT_SYMBOL(ib_destroy_srq);
+
/* Queue pairs */
struct ib_qp *ib_create_qp(struct ib_pd *pd,
@@ -462,16 +523,22 @@ EXPORT_SYMBOL(ib_dealloc_fmr);
int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
{
- return qp->device->attach_mcast ?
- qp->device->attach_mcast(qp, gid, lid) :
- -ENOSYS;
+ if (!qp->device->attach_mcast)
+ return -ENOSYS;
+ if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+ return -EINVAL;
+
+ return qp->device->attach_mcast(qp, gid, lid);
}
EXPORT_SYMBOL(ib_attach_mcast);
int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
{
- return qp->device->detach_mcast ?
- qp->device->detach_mcast(qp, gid, lid) :
- -ENOSYS;
+ if (!qp->device->detach_mcast)
+ return -ENOSYS;
+ if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+ return -EINVAL;
+
+ return qp->device->detach_mcast(qp, gid, lid);
}
EXPORT_SYMBOL(ib_detach_mcast);
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index 5dcbd43073e2..47ec5a7cba0b 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
EXTRA_CFLAGS += -DDEBUG
endif
@@ -9,4 +7,5 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
- mthca_provider.o mthca_memfree.o mthca_uar.o
+ mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o \
+ mthca_catas.o
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index b1db48dd91d6..9ba3211cef7c 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -177,3 +177,119 @@ void mthca_array_cleanup(struct mthca_array *array, int nent)
kfree(array->page_list);
}
+
+/*
+ * Handling for queue buffers -- we allocate a bunch of memory and
+ * register it in a memory region at HCA virtual address 0. If the
+ * requested size is > max_direct, we split the allocation into
+ * multiple pages, so we don't require too much contiguous memory.
+ */
+
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+ union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+ int hca_write, struct mthca_mr *mr)
+{
+ int err = -ENOMEM;
+ int npages, shift;
+ u64 *dma_list = NULL;
+ dma_addr_t t;
+ int i;
+
+ if (size <= max_direct) {
+ *is_direct = 1;
+ npages = 1;
+ shift = get_order(size) + PAGE_SHIFT;
+
+ buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev,
+ size, &t, GFP_KERNEL);
+ if (!buf->direct.buf)
+ return -ENOMEM;
+
+ pci_unmap_addr_set(&buf->direct, mapping, t);
+
+ memset(buf->direct.buf, 0, size);
+
+ while (t & ((1 << shift) - 1)) {
+ --shift;
+ npages *= 2;
+ }
+
+ dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ if (!dma_list)
+ goto err_free;
+
+ for (i = 0; i < npages; ++i)
+ dma_list[i] = t + i * (1 << shift);
+ } else {
+ *is_direct = 0;
+ npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ shift = PAGE_SHIFT;
+
+ dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ if (!dma_list)
+ return -ENOMEM;
+
+ buf->page_list = kmalloc(npages * sizeof *buf->page_list,
+ GFP_KERNEL);
+ if (!buf->page_list)
+ goto err_out;
+
+ for (i = 0; i < npages; ++i)
+ buf->page_list[i].buf = NULL;
+
+ for (i = 0; i < npages; ++i) {
+ buf->page_list[i].buf =
+ dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
+ &t, GFP_KERNEL);
+ if (!buf->page_list[i].buf)
+ goto err_free;
+
+ dma_list[i] = t;
+ pci_unmap_addr_set(&buf->page_list[i], mapping, t);
+
+ memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+ }
+ }
+
+ err = mthca_mr_alloc_phys(dev, pd->pd_num,
+ dma_list, shift, npages,
+ 0, size,
+ MTHCA_MPT_FLAG_LOCAL_READ |
+ (hca_write ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0),
+ mr);
+ if (err)
+ goto err_free;
+
+ kfree(dma_list);
+
+ return 0;
+
+err_free:
+ mthca_buf_free(dev, size, buf, *is_direct, NULL);
+
+err_out:
+ kfree(dma_list);
+
+ return err;
+}
+
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+ int is_direct, struct mthca_mr *mr)
+{
+ int i;
+
+ if (mr)
+ mthca_free_mr(dev, mr);
+
+ if (is_direct)
+ dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
+ pci_unmap_addr(&buf->direct, mapping));
+ else {
+ for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ buf->page_list[i].buf,
+ pci_unmap_addr(&buf->page_list[i],
+ mapping));
+ kfree(buf->page_list);
+ }
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index d58dcbe66488..22fdc446f25c 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -34,23 +34,25 @@
*/
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
#include "mthca_dev.h"
struct mthca_av {
- u32 port_pd;
- u8 reserved1;
- u8 g_slid;
- u16 dlid;
- u8 reserved2;
- u8 gid_index;
- u8 msg_sr;
- u8 hop_limit;
- u32 sl_tclass_flowlabel;
- u32 dgid[4];
+ __be32 port_pd;
+ u8 reserved1;
+ u8 g_slid;
+ __be16 dlid;
+ u8 reserved2;
+ u8 gid_index;
+ u8 msg_sr;
+ u8 hop_limit;
+ __be32 sl_tclass_flowlabel;
+ __be32 dgid[4];
};
int mthca_create_ah(struct mthca_dev *dev,
@@ -128,7 +130,7 @@ on_hca_fail:
av, (unsigned long) ah->avdma);
for (j = 0; j < 8; ++j)
printk(KERN_DEBUG " [%2x] %08x\n",
- j * 4, be32_to_cpu(((u32 *) av)[j]));
+ j * 4, be32_to_cpu(((__be32 *) av)[j]));
}
if (ah->type == MTHCA_AH_ON_HCA) {
@@ -169,7 +171,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
header->lrh.destination_lid = ah->av->dlid;
- header->lrh.source_lid = ah->av->g_slid & 0x7f;
+ header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f);
if (ah->av->g_slid & 0x80) {
header->grh_present = 1;
header->grh.traffic_class =
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
new file mode 100644
index 000000000000..7ac52af43b99
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, 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.
+ *
+ * - 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.
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "mthca_dev.h"
+
+enum {
+ MTHCA_CATAS_POLL_INTERVAL = 5 * HZ,
+
+ MTHCA_CATAS_TYPE_INTERNAL = 0,
+ MTHCA_CATAS_TYPE_UPLINK = 3,
+ MTHCA_CATAS_TYPE_DDR = 4,
+ MTHCA_CATAS_TYPE_PARITY = 5,
+};
+
+static DEFINE_SPINLOCK(catas_lock);
+
+static void handle_catas(struct mthca_dev *dev)
+{
+ struct ib_event event;
+ const char *type;
+ int i;
+
+ event.device = &dev->ib_dev;
+ event.event = IB_EVENT_DEVICE_FATAL;
+ event.element.port_num = 0;
+
+ ib_dispatch_event(&event);
+
+ switch (swab32(readl(dev->catas_err.map)) >> 24) {
+ case MTHCA_CATAS_TYPE_INTERNAL:
+ type = "internal error";
+ break;
+ case MTHCA_CATAS_TYPE_UPLINK:
+ type = "uplink bus error";
+ break;
+ case MTHCA_CATAS_TYPE_DDR:
+ type = "DDR data error";
+ break;
+ case MTHCA_CATAS_TYPE_PARITY:
+ type = "internal parity error";
+ break;
+ default:
+ type = "unknown error";
+ break;
+ }
+
+ mthca_err(dev, "Catastrophic error detected: %s\n", type);
+ for (i = 0; i < dev->catas_err.size; ++i)
+ mthca_err(dev, " buf[%02x]: %08x\n",
+ i, swab32(readl(dev->catas_err.map + i)));
+}
+
+static void poll_catas(unsigned long dev_ptr)
+{
+ struct mthca_dev *dev = (struct mthca_dev *) dev_ptr;
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < dev->catas_err.size; ++i)
+ if (readl(dev->catas_err.map + i)) {
+ handle_catas(dev);
+ return;
+ }
+
+ spin_lock_irqsave(&catas_lock, flags);
+ if (dev->catas_err.stop)
+ mod_timer(&dev->catas_err.timer,
+ jiffies + MTHCA_CATAS_POLL_INTERVAL);
+ spin_unlock_irqrestore(&catas_lock, flags);
+
+ return;
+}
+
+void mthca_start_catas_poll(struct mthca_dev *dev)
+{
+ unsigned long addr;
+
+ init_timer(&dev->catas_err.timer);
+ dev->catas_err.stop = 0;
+ dev->catas_err.map = NULL;
+
+ addr = pci_resource_start(dev->pdev, 0) +
+ ((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;
+ }
+
+ dev->catas_err.timer.data = (unsigned long) dev;
+ dev->catas_err.timer.function = poll_catas;
+ dev->catas_err.timer.expires = jiffies + MTHCA_CATAS_POLL_INTERVAL;
+ add_timer(&dev->catas_err.timer);
+}
+
+void mthca_stop_catas_poll(struct mthca_dev *dev)
+{
+ spin_lock_irq(&catas_lock);
+ dev->catas_err.stop = 1;
+ spin_unlock_irq(&catas_lock);
+
+ del_timer_sync(&dev->catas_err.timer);
+
+ 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);
+ }
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 1557a522d831..49f211d55df7 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems. 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
@@ -36,7 +38,7 @@
#include <linux/pci.h>
#include <linux/errno.h>
#include <asm/io.h>
-#include <ib_mad.h>
+#include <rdma/ib_mad.h>
#include "mthca_dev.h"
#include "mthca_config_reg.h"
@@ -108,6 +110,7 @@ enum {
CMD_SW2HW_SRQ = 0x35,
CMD_HW2SW_SRQ = 0x36,
CMD_QUERY_SRQ = 0x37,
+ CMD_ARM_SRQ = 0x40,
/* QP/EE commands */
CMD_RST2INIT_QPEE = 0x19,
@@ -219,20 +222,20 @@ static int mthca_cmd_post(struct mthca_dev *dev,
* (and some architectures such as ia64 implement memcpy_toio
* in terms of writeb).
*/
- __raw_writel(cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
- __raw_writel(cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
- __raw_writel(cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
- __raw_writel(cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
- __raw_writel(cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
- __raw_writel(cpu_to_be32(token << 16), dev->hcr + 5 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
+ __raw_writel((__force u32) cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
+ __raw_writel((__force u32) cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
+ __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
+ __raw_writel((__force u32) cpu_to_be32(token << 16), dev->hcr + 5 * 4);
/* __raw_writel may not order writes. */
wmb();
- __raw_writel(cpu_to_be32((1 << HCR_GO_BIT) |
- (event ? (1 << HCA_E_BIT) : 0) |
- (op_modifier << HCR_OPMOD_SHIFT) |
- op), dev->hcr + 6 * 4);
+ __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
+ (event ? (1 << HCA_E_BIT) : 0) |
+ (op_modifier << HCR_OPMOD_SHIFT) |
+ op), dev->hcr + 6 * 4);
out:
up(&dev->cmd.hcr_sem);
@@ -273,12 +276,14 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
goto out;
}
- if (out_is_imm) {
- memcpy_fromio(out_param, dev->hcr + HCR_OUT_PARAM_OFFSET, sizeof (u64));
- be64_to_cpus(out_param);
- }
+ if (out_is_imm)
+ *out_param =
+ (u64) be32_to_cpu((__force __be32)
+ __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
+ (u64) be32_to_cpu((__force __be32)
+ __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
- *status = be32_to_cpu(__raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+ *status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
out:
up(&dev->cmd.poll_sem);
@@ -520,7 +525,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
}
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask)
+ gfp_t gfp_mask)
{
struct mthca_mailbox *mailbox;
@@ -601,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
err = -EINVAL;
goto out;
}
- for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) {
+ for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) {
if (virt != -1) {
pages[nent * 2] = cpu_to_be64(virt);
virt += 1 << lg;
@@ -612,7 +617,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
ts += 1 << (lg - 10);
++tc;
- if (nent == MTHCA_MAILBOX_SIZE / 16) {
+ if (++nent == MTHCA_MAILBOX_SIZE / 16) {
err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
CMD_TIME_CLASS_B, status);
if (err || *status)
@@ -702,9 +707,13 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
dev->cmd.max_cmds = 1 << lg;
+ MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
+ MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
mthca_dbg(dev, "FW version %012llx, max commands %d\n",
(unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
+ mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",
+ (unsigned long long) dev->catas_err.addr, dev->catas_err.size);
if (mthca_is_memfree(dev)) {
MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET);
@@ -929,9 +938,9 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
goto out;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
- dev_lim->max_srq_sz = 1 << field;
+ dev_lim->max_srq_sz = (1 << field) - 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
- dev_lim->max_qp_sz = 1 << field;
+ dev_lim->max_qp_sz = (1 << field) - 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);
dev_lim->reserved_qps = 1 << (field & 0xf);
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);
@@ -1029,6 +1038,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
+ mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
+ dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
@@ -1039,6 +1050,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
dev_lim->max_pds, dev_lim->reserved_mgms);
+ mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
+ dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
@@ -1082,6 +1095,34 @@ out:
return err;
}
+static void get_board_id(void *vsd, char *board_id)
+{
+ int i;
+
+#define VSD_OFFSET_SIG1 0x00
+#define VSD_OFFSET_SIG2 0xde
+#define VSD_OFFSET_MLX_BOARD_ID 0xd0
+#define VSD_OFFSET_TS_BOARD_ID 0x20
+
+#define VSD_SIGNATURE_TOPSPIN 0x5ad
+
+ memset(board_id, 0, MTHCA_BOARD_ID_LEN);
+
+ if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
+ be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
+ strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
+ } else {
+ /*
+ * The board ID is a string but the firmware byte
+ * swaps each 4-byte word before passing it back to
+ * us. Therefore we need to swab it before printing.
+ */
+ for (i = 0; i < 4; ++i)
+ ((u32 *) board_id)[i] =
+ swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
+ }
+}
+
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
struct mthca_adapter *adapter, u8 *status)
{
@@ -1094,6 +1135,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04
#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
+#define QUERY_ADAPTER_VSD_OFFSET 0x20
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
@@ -1111,6 +1153,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
+ get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
+ adapter->board_id);
+
out:
mthca_free_mailbox(dev, mailbox);
return err;
@@ -1121,7 +1166,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
u8 *status)
{
struct mthca_mailbox *mailbox;
- u32 *inbox;
+ __be32 *inbox;
int err;
#define INIT_HCA_IN_SIZE 0x200
@@ -1247,10 +1292,8 @@ int mthca_INIT_IB(struct mthca_dev *dev,
#define INIT_IB_FLAG_SIG (1 << 18)
#define INIT_IB_FLAG_NG (1 << 17)
#define INIT_IB_FLAG_G0 (1 << 16)
-#define INIT_IB_FLAG_1X (1 << 8)
-#define INIT_IB_FLAG_4X (1 << 9)
-#define INIT_IB_FLAG_12X (1 << 11)
#define INIT_IB_VL_SHIFT 4
+#define INIT_IB_PORT_WIDTH_SHIFT 8
#define INIT_IB_MTU_SHIFT 12
#define INIT_IB_MAX_GID_OFFSET 0x06
#define INIT_IB_MAX_PKEY_OFFSET 0x0a
@@ -1266,12 +1309,11 @@ int mthca_INIT_IB(struct mthca_dev *dev,
memset(inbox, 0, INIT_IB_IN_SIZE);
flags = 0;
- flags |= param->enable_1x ? INIT_IB_FLAG_1X : 0;
- flags |= param->enable_4x ? INIT_IB_FLAG_4X : 0;
flags |= param->set_guid0 ? INIT_IB_FLAG_G0 : 0;
flags |= param->set_node_guid ? INIT_IB_FLAG_NG : 0;
flags |= param->set_si_guid ? INIT_IB_FLAG_SIG : 0;
flags |= param->vl_cap << INIT_IB_VL_SHIFT;
+ flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT;
flags |= param->mtu_cap << INIT_IB_MTU_SHIFT;
MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET);
@@ -1342,7 +1384,7 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st
int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
{
struct mthca_mailbox *mailbox;
- u64 *inbox;
+ __be64 *inbox;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -1468,6 +1510,27 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
CMD_TIME_CLASS_A, status);
}
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status)
+{
+ return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
+ CMD_TIME_CLASS_A, status);
+}
+
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status)
+{
+ return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
+ CMD_HW2SW_SRQ,
+ CMD_TIME_CLASS_A, status);
+}
+
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+{
+ return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
+ CMD_TIME_CLASS_B, status);
+}
+
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
u8 *status)
@@ -1513,7 +1576,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
if (i % 8 == 0)
printk(" [%02x] ", i * 4);
printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
@@ -1533,7 +1596,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
if (i % 8 == 0)
printk("[%02x] ", i * 4);
printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index ed517f175dd6..18175bec84c2 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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 +36,7 @@
#ifndef MTHCA_CMD_H
#define MTHCA_CMD_H
-#include <ib_verbs.h>
+#include <rdma/ib_verbs.h>
#define MTHCA_MAILBOX_SIZE 4096
@@ -183,10 +184,11 @@ struct mthca_dev_lim {
};
struct mthca_adapter {
- u32 vendor_id;
- u32 device_id;
- u32 revision_id;
- u8 inta_pin;
+ u32 vendor_id;
+ u32 device_id;
+ u32 revision_id;
+ char board_id[MTHCA_BOARD_ID_LEN];
+ u8 inta_pin;
};
struct mthca_init_hca_param {
@@ -218,8 +220,7 @@ struct mthca_init_hca_param {
};
struct mthca_init_ib_param {
- int enable_1x;
- int enable_4x;
+ int port_width;
int vl_cap;
int mtu_cap;
u16 gid_cap;
@@ -247,7 +248,7 @@ void mthca_cmd_event(struct mthca_dev *dev, u16 token,
u8 status, u64 out_param);
struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask);
+ gfp_t gfp_mask);
void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
@@ -297,6 +298,11 @@ int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
int cq_num, u8 *status);
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
int cq_num, u8 *status);
+int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status);
+int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+ int srq_num, u8 *status);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
u8 *status);
diff --git a/drivers/infiniband/hw/mthca/mthca_config_reg.h b/drivers/infiniband/hw/mthca/mthca_config_reg.h
index b4bfbbfe2c3d..afa56bfaab2e 100644
--- a/drivers/infiniband/hw/mthca/mthca_config_reg.h
+++ b/drivers/infiniband/hw/mthca/mthca_config_reg.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 5687c3014522..f98e23555826 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -37,7 +39,7 @@
#include <linux/init.h>
#include <linux/hardirq.h>
-#include <ib_pack.h>
+#include <rdma/ib_pack.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -55,21 +57,21 @@ enum {
* Must be packed because start is 64 bits but only aligned to 32 bits.
*/
struct mthca_cq_context {
- u32 flags;
- u64 start;
- u32 logsize_usrpage;
- u32 error_eqn; /* Tavor only */
- u32 comp_eqn;
- u32 pd;
- u32 lkey;
- u32 last_notified_index;
- u32 solicit_producer_index;
- u32 consumer_index;
- u32 producer_index;
- u32 cqn;
- u32 ci_db; /* Arbel only */
- u32 state_db; /* Arbel only */
- u32 reserved;
+ __be32 flags;
+ __be64 start;
+ __be32 logsize_usrpage;
+ __be32 error_eqn; /* Tavor only */
+ __be32 comp_eqn;
+ __be32 pd;
+ __be32 lkey;
+ __be32 last_notified_index;
+ __be32 solicit_producer_index;
+ __be32 consumer_index;
+ __be32 producer_index;
+ __be32 cqn;
+ __be32 ci_db; /* Arbel only */
+ __be32 state_db; /* Arbel only */
+ u32 reserved;
} __attribute__((packed));
#define MTHCA_CQ_STATUS_OK ( 0 << 28)
@@ -108,31 +110,31 @@ enum {
};
struct mthca_cqe {
- u32 my_qpn;
- u32 my_ee;
- u32 rqpn;
- u16 sl_g_mlpath;
- u16 rlid;
- u32 imm_etype_pkey_eec;
- u32 byte_cnt;
- u32 wqe;
- u8 opcode;
- u8 is_send;
- u8 reserved;
- u8 owner;
+ __be32 my_qpn;
+ __be32 my_ee;
+ __be32 rqpn;
+ __be16 sl_g_mlpath;
+ __be16 rlid;
+ __be32 imm_etype_pkey_eec;
+ __be32 byte_cnt;
+ __be32 wqe;
+ u8 opcode;
+ u8 is_send;
+ u8 reserved;
+ u8 owner;
};
struct mthca_err_cqe {
- u32 my_qpn;
- u32 reserved1[3];
- u8 syndrome;
- u8 reserved2;
- u16 db_cnt;
- u32 reserved3;
- u32 wqe;
- u8 opcode;
- u8 reserved4[2];
- u8 owner;
+ __be32 my_qpn;
+ u32 reserved1[3];
+ u8 syndrome;
+ u8 reserved2;
+ __be16 db_cnt;
+ u32 reserved3;
+ __be32 wqe;
+ u8 opcode;
+ u8 reserved4[2];
+ u8 owner;
};
#define MTHCA_CQ_ENTRY_OWNER_SW (0 << 7)
@@ -191,7 +193,7 @@ static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
int incr)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
if (mthca_is_memfree(dev)) {
*cq->set_ci_db = cpu_to_be32(cq->cons_index);
@@ -206,7 +208,7 @@ static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
}
}
-void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
+void mthca_cq_completion(struct mthca_dev *dev, u32 cqn)
{
struct mthca_cq *cq;
@@ -222,7 +224,37 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
}
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
+void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
+ enum ib_event_type event_type)
+{
+ struct mthca_cq *cq;
+ struct ib_event event;
+
+ spin_lock(&dev->cq_table.lock);
+
+ cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
+
+ if (cq)
+ atomic_inc(&cq->refcount);
+ spin_unlock(&dev->cq_table.lock);
+
+ if (!cq) {
+ mthca_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+ return;
+ }
+
+ event.device = &dev->ib_dev;
+ event.event = event_type;
+ event.element.cq = &cq->ibcq;
+ if (cq->ibcq.event_handler)
+ cq->ibcq.event_handler(&event, cq->ibcq.cq_context);
+
+ if (atomic_dec_and_test(&cq->refcount))
+ wake_up(&cq->wait);
+}
+
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+ struct mthca_srq *srq)
{
struct mthca_cq *cq;
struct mthca_cqe *cqe;
@@ -263,8 +295,11 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
*/
while (prod_index > cq->cons_index) {
cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe);
- if (cqe->my_qpn == cpu_to_be32(qpn))
+ if (cqe->my_qpn == cpu_to_be32(qpn)) {
+ if (srq)
+ mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
++nfreed;
+ }
else if (nfreed)
memcpy(get_cqe(cq, (prod_index - 1 + nfreed) &
cq->ibcq.cqe),
@@ -291,7 +326,7 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
{
int err;
int dbd;
- u32 new_wqe;
+ __be32 new_wqe;
if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
mthca_dbg(dev, "local QP operation err "
@@ -365,6 +400,13 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
break;
}
+ /*
+ * Mem-free HCAs always generate one CQE per WQE, even in the
+ * error case, so we don't have to check the doorbell count, etc.
+ */
+ if (mthca_is_memfree(dev))
+ return 0;
+
err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
if (err)
return err;
@@ -373,12 +415,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
* If we're at the end of the WQE chain, or we've used up our
* doorbell count, free the CQE. Otherwise just update it for
* the next poll operation.
- *
- * This does not apply to mem-free HCAs: they don't use the
- * doorbell count field, and so we should always free the CQE.
*/
- if (mthca_is_memfree(dev) ||
- !(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
+ if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
return 0;
cqe->db_cnt = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd);
@@ -450,23 +488,27 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
>> wq->wqe_shift);
entry->wr_id = (*cur_qp)->wrid[wqe_index +
(*cur_qp)->rq.max];
+ } else if ((*cur_qp)->ibqp.srq) {
+ struct mthca_srq *srq = to_msrq((*cur_qp)->ibqp.srq);
+ u32 wqe = be32_to_cpu(cqe->wqe);
+ wq = NULL;
+ wqe_index = wqe >> srq->wqe_shift;
+ entry->wr_id = srq->wrid[wqe_index];
+ mthca_free_srq_wqe(srq, wqe);
} else {
wq = &(*cur_qp)->rq;
wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
entry->wr_id = (*cur_qp)->wrid[wqe_index];
}
- if (wq->last_comp < wqe_index)
- wq->tail += wqe_index - wq->last_comp;
- else
- wq->tail += wqe_index + wq->max - wq->last_comp;
-
- wq->last_comp = wqe_index;
+ if (wq) {
+ if (wq->last_comp < wqe_index)
+ wq->tail += wqe_index - wq->last_comp;
+ else
+ wq->tail += wqe_index + wq->max - wq->last_comp;
- if (0)
- mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
- is_send ? "Send" : "Receive",
- (*cur_qp)->qpn, wqe_index, wq->max);
+ wq->last_comp = wqe_index;
+ }
if (is_error) {
err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
@@ -584,13 +626,13 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
MTHCA_TAVOR_CQ_DB_REQ_NOT) |
to_mcq(cq)->cqn);
- doorbell[1] = 0xffffffff;
+ doorbell[1] = (__force __be32) 0xffffffff;
mthca_write64(doorbell,
to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
@@ -602,9 +644,9 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
{
struct mthca_cq *cq = to_mcq(ibcq);
- u32 doorbell[2];
+ __be32 doorbell[2];
u32 sn;
- u32 ci;
+ __be32 ci;
sn = cq->arm_sn & 3;
ci = cpu_to_be32(cq->cons_index);
@@ -637,113 +679,8 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
{
- int i;
- int size;
-
- if (cq->is_direct)
- dma_free_coherent(&dev->pdev->dev,
- (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
- cq->queue.direct.buf,
- pci_unmap_addr(&cq->queue.direct,
- mapping));
- else {
- size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
- for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
- if (cq->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- cq->queue.page_list[i].buf,
- pci_unmap_addr(&cq->queue.page_list[i],
- mapping));
-
- kfree(cq->queue.page_list);
- }
-}
-
-static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
- struct mthca_cq *cq)
-{
- int err = -ENOMEM;
- int npages, shift;
- u64 *dma_list = NULL;
- dma_addr_t t;
- int i;
-
- if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
- cq->is_direct = 1;
- npages = 1;
- shift = get_order(size) + PAGE_SHIFT;
-
- cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev,
- size, &t, GFP_KERNEL);
- if (!cq->queue.direct.buf)
- return -ENOMEM;
-
- pci_unmap_addr_set(&cq->queue.direct, mapping, t);
-
- memset(cq->queue.direct.buf, 0, size);
-
- while (t & ((1 << shift) - 1)) {
- --shift;
- npages *= 2;
- }
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_free;
-
- for (i = 0; i < npages; ++i)
- dma_list[i] = t + i * (1 << shift);
- } else {
- cq->is_direct = 0;
- npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
- shift = PAGE_SHIFT;
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- return -ENOMEM;
-
- cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
- GFP_KERNEL);
- if (!cq->queue.page_list)
- goto err_out;
-
- for (i = 0; i < npages; ++i)
- cq->queue.page_list[i].buf = NULL;
-
- for (i = 0; i < npages; ++i) {
- cq->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
- if (!cq->queue.page_list[i].buf)
- goto err_free;
-
- dma_list[i] = t;
- pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
-
- memset(cq->queue.page_list[i].buf, 0, PAGE_SIZE);
- }
- }
-
- err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
- dma_list, shift, npages,
- 0, size,
- MTHCA_MPT_FLAG_LOCAL_WRITE |
- MTHCA_MPT_FLAG_LOCAL_READ,
- &cq->mr);
- if (err)
- goto err_free;
-
- kfree(dma_list);
-
- return 0;
-
-err_free:
- mthca_free_cq_buf(dev, cq);
-
-err_out:
- kfree(dma_list);
-
- return err;
+ mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+ &cq->queue, cq->is_direct, &cq->mr);
}
int mthca_init_cq(struct mthca_dev *dev, int nent,
@@ -795,7 +732,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context = mailbox->buf;
if (cq->is_kernel) {
- err = mthca_alloc_cq_buf(dev, size, cq);
+ err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE,
+ &cq->queue, &cq->is_direct,
+ &dev->driver_pd, 1, &cq->mr);
if (err)
goto err_out_mailbox;
@@ -811,7 +750,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context->flags = cpu_to_be32(MTHCA_CQ_STATUS_OK |
MTHCA_CQ_STATE_DISARMED |
MTHCA_CQ_FLAG_TR);
- cq_context->start = cpu_to_be64(0);
cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
if (ctx)
cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
@@ -857,10 +795,8 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
return 0;
err_out_free_mr:
- if (cq->is_kernel) {
- mthca_free_mr(dev, &cq->mr);
+ if (cq->is_kernel)
mthca_free_cq_buf(dev, cq);
- }
err_out_mailbox:
mthca_free_mailbox(dev, mailbox);
@@ -904,7 +840,7 @@ void mthca_free_cq(struct mthca_dev *dev,
mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
if (0) {
- u32 *ctx = mailbox->buf;
+ __be32 *ctx = mailbox->buf;
int j;
printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
@@ -928,7 +864,6 @@ void mthca_free_cq(struct mthca_dev *dev,
wait_event(cq->wait, !atomic_read(&cq->refcount));
if (cq->is_kernel) {
- mthca_free_mr(dev, &cq->mr);
mthca_free_cq_buf(dev, cq);
if (mthca_is_memfree(dev)) {
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 5ecdd2eeeb0f..e7e5d3b4f004 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -67,6 +69,10 @@ enum {
};
enum {
+ MTHCA_BOARD_ID_LEN = 64
+};
+
+enum {
MTHCA_EQ_CONTEXT_SIZE = 0x40,
MTHCA_CQ_CONTEXT_SIZE = 0x40,
MTHCA_QP_CONTEXT_SIZE = 0x200,
@@ -77,6 +83,8 @@ enum {
/* Arbel FW gives us these, but we need them for Tavor */
MTHCA_MPT_ENTRY_SIZE = 0x40,
MTHCA_MTT_SEG_SIZE = 0x40,
+
+ MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
};
enum {
@@ -122,12 +130,16 @@ struct mthca_limits {
int num_uars;
int max_sg;
int num_qps;
+ int max_wqes;
+ int max_qp_init_rdma;
int reserved_qps;
int num_srqs;
+ int max_srq_wqes;
int reserved_srqs;
int num_eecs;
int reserved_eecs;
int num_cqs;
+ int max_cqes;
int reserved_cqs;
int num_eqs;
int reserved_eqs;
@@ -142,6 +154,8 @@ struct mthca_limits {
int reserved_mcgs;
int num_pds;
int reserved_pds;
+ u32 flags;
+ u8 port_width_cap;
};
struct mthca_alloc {
@@ -211,6 +225,13 @@ struct mthca_cq_table {
struct mthca_icm_table *table;
};
+struct mthca_srq_table {
+ struct mthca_alloc alloc;
+ spinlock_t lock;
+ struct mthca_array srq;
+ struct mthca_icm_table *table;
+};
+
struct mthca_qp_table {
struct mthca_alloc alloc;
u32 rdb_base;
@@ -237,6 +258,14 @@ struct mthca_mcg_table {
struct mthca_icm_table *table;
};
+struct mthca_catas_err {
+ u64 addr;
+ u32 __iomem *map;
+ unsigned long stop;
+ u32 size;
+ struct timer_list timer;
+};
+
struct mthca_dev {
struct ib_device ib_dev;
struct pci_dev *pdev;
@@ -246,6 +275,7 @@ struct mthca_dev {
unsigned long device_cap_flags;
u32 rev_id;
+ char board_id[MTHCA_BOARD_ID_LEN];
/* firmware info */
u64 fw_ver;
@@ -291,10 +321,13 @@ struct mthca_dev {
struct mthca_mr_table mr_table;
struct mthca_eq_table eq_table;
struct mthca_cq_table cq_table;
+ struct mthca_srq_table srq_table;
struct mthca_qp_table qp_table;
struct mthca_av_table av_table;
struct mthca_mcg_table mcg_table;
+ struct mthca_catas_err catas_err;
+
struct mthca_uar driver_uar;
struct mthca_db_table *db_tab;
struct mthca_pd driver_pd;
@@ -331,14 +364,13 @@ extern void __buggy_use_of_MTHCA_PUT(void);
#define MTHCA_PUT(dest, source, offset) \
do { \
- __typeof__(source) *__p = \
- (__typeof__(source) *) ((char *) (dest) + (offset)); \
+ void *__d = ((char *) (dest) + (offset)); \
switch (sizeof(source)) { \
- case 1: *__p = (source); break; \
- case 2: *__p = cpu_to_be16(source); break; \
- case 4: *__p = cpu_to_be32(source); break; \
- case 8: *__p = cpu_to_be64(source); break; \
- default: __buggy_use_of_MTHCA_PUT(); \
+ case 1: *(u8 *) __d = (source); break; \
+ case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
+ case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
+ case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
+ default: __buggy_use_of_MTHCA_PUT(); \
} \
} while (0)
@@ -354,12 +386,18 @@ int mthca_array_set(struct mthca_array *array, int index, void *value);
void mthca_array_clear(struct mthca_array *array, int index);
int mthca_array_init(struct mthca_array *array, int nent);
void mthca_array_cleanup(struct mthca_array *array, int nent);
+int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
+ union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
+ int hca_write, struct mthca_mr *mr);
+void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
+ int is_direct, struct mthca_mr *mr);
int mthca_init_uar_table(struct mthca_dev *dev);
int mthca_init_pd_table(struct mthca_dev *dev);
int mthca_init_mr_table(struct mthca_dev *dev);
int mthca_init_eq_table(struct mthca_dev *dev);
int mthca_init_cq_table(struct mthca_dev *dev);
+int mthca_init_srq_table(struct mthca_dev *dev);
int mthca_init_qp_table(struct mthca_dev *dev);
int mthca_init_av_table(struct mthca_dev *dev);
int mthca_init_mcg_table(struct mthca_dev *dev);
@@ -369,6 +407,7 @@ void mthca_cleanup_pd_table(struct mthca_dev *dev);
void mthca_cleanup_mr_table(struct mthca_dev *dev);
void mthca_cleanup_eq_table(struct mthca_dev *dev);
void mthca_cleanup_cq_table(struct mthca_dev *dev);
+void mthca_cleanup_srq_table(struct mthca_dev *dev);
void mthca_cleanup_qp_table(struct mthca_dev *dev);
void mthca_cleanup_av_table(struct mthca_dev *dev);
void mthca_cleanup_mcg_table(struct mthca_dev *dev);
@@ -376,6 +415,9 @@ void mthca_cleanup_mcg_table(struct mthca_dev *dev);
int mthca_register_device(struct mthca_dev *dev);
void mthca_unregister_device(struct mthca_dev *dev);
+void mthca_start_catas_poll(struct mthca_dev *dev);
+void mthca_stop_catas_poll(struct mthca_dev *dev);
+
int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
@@ -418,8 +460,24 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
struct mthca_cq *cq);
void mthca_free_cq(struct mthca_dev *dev,
struct mthca_cq *cq);
-void mthca_cq_event(struct mthca_dev *dev, u32 cqn);
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn);
+void mthca_cq_completion(struct mthca_dev *dev, u32 cqn);
+void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
+ enum ib_event_type event_type);
+void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+ struct mthca_srq *srq);
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct ib_srq_attr *attr, struct mthca_srq *srq);
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask);
+void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
+ enum ib_event_type event_type);
+void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
+int mthca_tavor_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+int mthca_arbel_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
enum ib_event_type event_type);
@@ -433,7 +491,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
struct ib_recv_wr **bad_wr);
int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
- int index, int *dbd, u32 *new_wqe);
+ int index, int *dbd, __be32 *new_wqe);
int mthca_alloc_qp(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
diff --git a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h
index 535fad7710fb..dd9a44d170c9 100644
--- a/drivers/infiniband/hw/mthca/mthca_doorbell.h
+++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -57,13 +58,13 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writeq((__force u64) val, dest);
}
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
__raw_writeq(*(u64 *) val, dest);
}
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
{
*(u64 *) db = *(u64 *) val;
}
@@ -86,18 +87,18 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
__raw_writel(((__force u32 *) &val)[1], dest + 4);
}
-static inline void mthca_write64(u32 val[2], void __iomem *dest,
+static inline void mthca_write64(__be32 val[2], void __iomem *dest,
spinlock_t *doorbell_lock)
{
unsigned long flags;
spin_lock_irqsave(doorbell_lock, flags);
- __raw_writel(val[0], dest);
- __raw_writel(val[1], dest + 4);
+ __raw_writel((__force u32) val[0], dest);
+ __raw_writel((__force u32) val[1], dest + 4);
spin_unlock_irqrestore(doorbell_lock, flags);
}
-static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
{
db[0] = val[0];
wmb();
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index cbcf2b4722e4..34d68e5a72d8 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -51,18 +52,18 @@ enum {
* Must be packed because start is 64 bits but only aligned to 32 bits.
*/
struct mthca_eq_context {
- u32 flags;
- u64 start;
- u32 logsize_usrpage;
- u32 tavor_pd; /* reserved for Arbel */
- u8 reserved1[3];
- u8 intr;
- u32 arbel_pd; /* lost_count for Tavor */
- u32 lkey;
- u32 reserved2[2];
- u32 consumer_index;
- u32 producer_index;
- u32 reserved3[4];
+ __be32 flags;
+ __be64 start;
+ __be32 logsize_usrpage;
+ __be32 tavor_pd; /* reserved for Arbel */
+ u8 reserved1[3];
+ u8 intr;
+ __be32 arbel_pd; /* lost_count for Tavor */
+ __be32 lkey;
+ u32 reserved2[2];
+ __be32 consumer_index;
+ __be32 producer_index;
+ u32 reserved3[4];
} __attribute__((packed));
#define MTHCA_EQ_STATUS_OK ( 0 << 28)
@@ -82,7 +83,8 @@ enum {
MTHCA_EVENT_TYPE_PATH_MIG = 0x01,
MTHCA_EVENT_TYPE_COMM_EST = 0x02,
MTHCA_EVENT_TYPE_SQ_DRAINED = 0x03,
- MTHCA_EVENT_TYPE_SRQ_LAST_WQE = 0x13,
+ MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE = 0x13,
+ MTHCA_EVENT_TYPE_SRQ_LIMIT = 0x14,
MTHCA_EVENT_TYPE_CQ_ERROR = 0x04,
MTHCA_EVENT_TYPE_WQ_CATAS_ERROR = 0x05,
MTHCA_EVENT_TYPE_EEC_CATAS_ERROR = 0x06,
@@ -109,8 +111,9 @@ enum {
(1ULL << MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR) | \
(1ULL << MTHCA_EVENT_TYPE_PORT_CHANGE) | \
(1ULL << MTHCA_EVENT_TYPE_ECC_DETECT))
-#define MTHCA_SRQ_EVENT_MASK (1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR) | \
- (1ULL << MTHCA_EVENT_TYPE_SRQ_LAST_WQE)
+#define MTHCA_SRQ_EVENT_MASK ((1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR) | \
+ (1ULL << MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE) | \
+ (1ULL << MTHCA_EVENT_TYPE_SRQ_LIMIT))
#define MTHCA_CMD_EVENT_MASK (1ULL << MTHCA_EVENT_TYPE_CMD)
#define MTHCA_EQ_DB_INC_CI (1 << 24)
@@ -127,28 +130,31 @@ struct mthca_eqe {
union {
u32 raw[6];
struct {
- u32 cqn;
+ __be32 cqn;
} __attribute__((packed)) comp;
struct {
- u16 reserved1;
- u16 token;
- u32 reserved2;
- u8 reserved3[3];
- u8 status;
- u64 out_param;
+ u16 reserved1;
+ __be16 token;
+ u32 reserved2;
+ u8 reserved3[3];
+ u8 status;
+ __be64 out_param;
} __attribute__((packed)) cmd;
struct {
- u32 qpn;
+ __be32 qpn;
} __attribute__((packed)) qp;
struct {
- u32 cqn;
- u32 reserved1;
- u8 reserved2[3];
- u8 syndrome;
+ __be32 srqn;
+ } __attribute__((packed)) srq;
+ struct {
+ __be32 cqn;
+ u32 reserved1;
+ u8 reserved2[3];
+ u8 syndrome;
} __attribute__((packed)) cq_err;
struct {
- u32 reserved1[2];
- u32 port;
+ u32 reserved1[2];
+ __be32 port;
} __attribute__((packed)) port_change;
} event;
u8 reserved3[3];
@@ -167,7 +173,7 @@ static inline u64 async_mask(struct mthca_dev *dev)
static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
@@ -190,8 +196,8 @@ static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u
{
/* See comment in tavor_set_eq_ci() above. */
wmb();
- __raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
- eq->eqn * 8);
+ __raw_writel((__force u32) cpu_to_be32(ci),
+ dev->eq_regs.arbel.eq_set_ci_base + eq->eqn * 8);
/* We still want ordering, just not swabbing, so add a barrier */
mb();
}
@@ -206,7 +212,7 @@ static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
{
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_REQ_NOT | eqn);
doorbell[1] = 0;
@@ -224,7 +230,7 @@ static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
{
if (!mthca_is_memfree(dev)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
doorbell[1] = cpu_to_be32(cqn);
@@ -286,7 +292,7 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
case MTHCA_EVENT_TYPE_COMP:
disarm_cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff;
disarm_cq(dev, eq->eqn, disarm_cqn);
- mthca_cq_event(dev, disarm_cqn);
+ mthca_cq_completion(dev, disarm_cqn);
break;
case MTHCA_EVENT_TYPE_PATH_MIG:
@@ -304,6 +310,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
IB_EVENT_SQ_DRAINED);
break;
+ case MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE:
+ mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
+ IB_EVENT_QP_LAST_WQE_REACHED);
+ break;
+
+ case MTHCA_EVENT_TYPE_SRQ_LIMIT:
+ mthca_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff,
+ IB_EVENT_SRQ_LIMIT_REACHED);
+ break;
+
case MTHCA_EVENT_TYPE_WQ_CATAS_ERROR:
mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
IB_EVENT_QP_FATAL);
@@ -348,6 +364,8 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
eqe->event.cq_err.syndrome == 1 ?
"overrun" : "access violation",
be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff);
+ mthca_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn),
+ IB_EVENT_CQ_ERR);
break;
case MTHCA_EVENT_TYPE_EQ_OVERFLOW:
@@ -395,20 +413,21 @@ static irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr, struct pt_regs
writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
ecr = readl(dev->eq_regs.tavor.ecr_base + 4);
- if (ecr) {
- writel(ecr, dev->eq_regs.tavor.ecr_base +
- MTHCA_ECR_CLR_BASE - MTHCA_ECR_BASE + 4);
+ if (!ecr)
+ return IRQ_NONE;
+
+ writel(ecr, dev->eq_regs.tavor.ecr_base +
+ MTHCA_ECR_CLR_BASE - MTHCA_ECR_BASE + 4);
- for (i = 0; i < MTHCA_NUM_EQ; ++i)
- if (ecr & dev->eq_table.eq[i].eqn_mask &&
- mthca_eq_int(dev, &dev->eq_table.eq[i])) {
+ for (i = 0; i < MTHCA_NUM_EQ; ++i)
+ if (ecr & dev->eq_table.eq[i].eqn_mask) {
+ if (mthca_eq_int(dev, &dev->eq_table.eq[i]))
tavor_set_eq_ci(dev, &dev->eq_table.eq[i],
dev->eq_table.eq[i].cons_index);
- tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
- }
- }
+ tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
+ }
- return IRQ_RETVAL(ecr);
+ return IRQ_HANDLED;
}
static irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr,
@@ -475,12 +494,8 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
int i;
u8 status;
- /* Make sure EQ size is aligned to a power of 2 size. */
- for (i = 1; i < nent; i <<= 1)
- ; /* nothing */
- nent = i;
-
- eq->dev = dev;
+ eq->dev = dev;
+ eq->nent = roundup_pow_of_two(max(nent, 2));
eq->page_list = kmalloc(npages * sizeof *eq->page_list,
GFP_KERNEL);
@@ -511,7 +526,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
memset(eq->page_list[i].buf, 0, PAGE_SIZE);
}
- for (i = 0; i < nent; ++i)
+ for (i = 0; i < eq->nent; ++i)
set_eqe_hw(get_eqe(eq, i));
eq->eqn = mthca_alloc(&dev->eq_table.alloc);
@@ -527,8 +542,6 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
if (err)
goto err_out_free_eq;
- eq->nent = nent;
-
memset(eq_context, 0, sizeof *eq_context);
eq_context->flags = cpu_to_be32(MTHCA_EQ_STATUS_OK |
MTHCA_EQ_OWNER_HW |
@@ -537,7 +550,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
if (mthca_is_memfree(dev))
eq_context->flags |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL);
- eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+ eq_context->logsize_usrpage = cpu_to_be32((ffs(eq->nent) - 1) << 24);
if (mthca_is_memfree(dev)) {
eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num);
} else {
@@ -568,7 +581,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
dev->eq_table.arm_mask |= eq->eqn_mask;
mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
- eq->eqn, nent);
+ eq->eqn, eq->nent);
return err;
@@ -841,7 +854,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
dev->eq_table.clr_mask =
swab32(1 << (dev->eq_table.inta_pin & 31));
dev->eq_table.clr_int = dev->clr_base +
- (dev->eq_table.inta_pin < 31 ? 4 : 0);
+ (dev->eq_table.inta_pin < 32 ? 4 : 0);
}
dev->eq_table.arm_mask = 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 7df223642015..1229c604c6e0 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -32,9 +34,12 @@
* $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_verbs.h>
-#include <ib_mad.h>
-#include <ib_smi.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -44,11 +49,6 @@ enum {
MTHCA_VENDOR_CLASS2 = 0xa
};
-struct mthca_trap_mad {
- struct ib_mad *mad;
- DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
static void update_sm_ah(struct mthca_dev *dev,
u8 port_num, u16 lid, u8 sl)
{
@@ -114,49 +114,14 @@ static void forward_trap(struct mthca_dev *dev,
struct ib_mad *mad)
{
int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
- struct mthca_trap_mad *tmad;
- struct ib_sge gather_list;
- struct ib_send_wr *bad_wr, wr = {
- .opcode = IB_WR_SEND,
- .sg_list = &gather_list,
- .num_sge = 1,
- .send_flags = IB_SEND_SIGNALED,
- .wr = {
- .ud = {
- .remote_qpn = qpn,
- .remote_qkey = qpn ? IB_QP1_QKEY : 0,
- .timeout_ms = 0
- }
- }
- };
+ struct ib_mad_send_buf *send_buf;
struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn];
int ret;
unsigned long flags;
if (agent) {
- tmad = kmalloc(sizeof *tmad, GFP_KERNEL);
- if (!tmad)
- return;
-
- tmad->mad = kmalloc(sizeof *tmad->mad, GFP_KERNEL);
- if (!tmad->mad) {
- kfree(tmad);
- return;
- }
-
- memcpy(tmad->mad, mad, sizeof *mad);
-
- wr.wr.ud.mad_hdr = &tmad->mad->mad_hdr;
- wr.wr_id = (unsigned long) tmad;
-
- gather_list.addr = dma_map_single(agent->device->dma_device,
- tmad->mad,
- sizeof *tmad->mad,
- DMA_TO_DEVICE);
- gather_list.length = sizeof *tmad->mad;
- gather_list.lkey = to_mpd(agent->qp->pd)->ntmr.ibmr.lkey;
- pci_unmap_addr_set(tmad, mapping, gather_list.addr);
-
+ send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
+ IB_MGMT_MAD_DATA, GFP_ATOMIC);
/*
* We rely here on the fact that MLX QPs don't use the
* address handle after the send is posted (this is
@@ -164,21 +129,15 @@ static void forward_trap(struct mthca_dev *dev,
* it's OK for our devices).
*/
spin_lock_irqsave(&dev->sm_lock, flags);
- wr.wr.ud.ah = dev->sm_ah[port_num - 1];
- if (wr.wr.ud.ah)
- ret = ib_post_send_mad(agent, &wr, &bad_wr);
+ memcpy(send_buf->mad, mad, sizeof *mad);
+ if ((send_buf->ah = dev->sm_ah[port_num - 1]))
+ ret = ib_post_send_mad(send_buf, NULL);
else
ret = -EINVAL;
spin_unlock_irqrestore(&dev->sm_lock, flags);
- if (ret) {
- dma_unmap_single(agent->device->dma_device,
- pci_unmap_addr(tmad, mapping),
- sizeof *tmad->mad,
- DMA_TO_DEVICE);
- kfree(tmad->mad);
- kfree(tmad);
- }
+ if (ret)
+ ib_free_send_mad(send_buf);
}
}
@@ -192,7 +151,7 @@ int mthca_process_mad(struct ib_device *ibdev,
{
int err;
u8 status;
- u16 slid = in_wc ? in_wc->slid : IB_LID_PERMISSIVE;
+ u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
/* Forward locally generated traps to the SM */
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&
@@ -265,15 +224,7 @@ int mthca_process_mad(struct ib_device *ibdev,
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc)
{
- struct mthca_trap_mad *tmad =
- (void *) (unsigned long) mad_send_wc->wr_id;
-
- dma_unmap_single(agent->device->dma_device,
- pci_unmap_addr(tmad, mapping),
- sizeof *tmad->mad,
- DMA_TO_DEVICE);
- kfree(tmad->mad);
- kfree(tmad);
+ ib_free_send_mad(mad_send_wc->send_buf);
}
int mthca_create_agents(struct mthca_dev *dev)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 2ef916859e17..45c6328e780c 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -34,7 +35,6 @@
*/
#include <linux/config.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -162,15 +162,26 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.pkey_table_len = dev_lim->max_pkeys;
mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
mdev->limits.max_sg = dev_lim->max_sg;
+ mdev->limits.max_wqes = dev_lim->max_qp_sz;
+ mdev->limits.max_qp_init_rdma = dev_lim->max_requester_per_qp;
mdev->limits.reserved_qps = dev_lim->reserved_qps;
+ mdev->limits.max_srq_wqes = dev_lim->max_srq_sz;
mdev->limits.reserved_srqs = dev_lim->reserved_srqs;
mdev->limits.reserved_eecs = dev_lim->reserved_eecs;
+ /*
+ * Subtract 1 from the limit because we need to allocate a
+ * spare CQE so the HCA HW can tell the difference between an
+ * empty CQ and a full CQ.
+ */
+ mdev->limits.max_cqes = dev_lim->max_cq_sz - 1;
mdev->limits.reserved_cqs = dev_lim->reserved_cqs;
mdev->limits.reserved_eqs = dev_lim->reserved_eqs;
mdev->limits.reserved_mtts = dev_lim->reserved_mtts;
mdev->limits.reserved_mrws = dev_lim->reserved_mrws;
mdev->limits.reserved_uars = dev_lim->reserved_uars;
mdev->limits.reserved_pds = dev_lim->reserved_pds;
+ mdev->limits.port_width_cap = dev_lim->max_port_width;
+ mdev->limits.flags = dev_lim->flags;
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
May be doable since hardware supports it for SRQ.
@@ -212,7 +223,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- struct mthca_adapter adapter;
err = mthca_SYS_EN(mdev, &status);
if (err) {
@@ -253,6 +263,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.uarc_size = 0;
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ profile.num_srq = dev_lim.max_srqs;
err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
if (err < 0)
@@ -270,26 +282,8 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable;
}
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
- if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_close;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
- goto err_close;
- }
-
- mdev->eq_table.inta_pin = adapter.inta_pin;
- mdev->rev_id = adapter.revision_id;
-
return 0;
-err_close:
- mthca_CLOSE_HCA(mdev, 0, &status);
-
err_disable:
mthca_SYS_DIS(mdev, &status);
@@ -442,15 +436,29 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
- dev_lim->cqc_entry_sz,
- mdev->limits.num_cqs,
- mdev->limits.reserved_cqs, 0);
+ dev_lim->cqc_entry_sz,
+ mdev->limits.num_cqs,
+ mdev->limits.reserved_cqs, 0);
if (!mdev->cq_table.table) {
mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
err = -ENOMEM;
goto err_unmap_rdb;
}
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ) {
+ mdev->srq_table.table =
+ mthca_alloc_icm_table(mdev, init_hca->srqc_base,
+ dev_lim->srq_entry_sz,
+ mdev->limits.num_srqs,
+ mdev->limits.reserved_srqs, 0);
+ if (!mdev->srq_table.table) {
+ mthca_err(mdev, "Failed to map SRQ context memory, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_unmap_cq;
+ }
+ }
+
/*
* It's not strictly required, but for simplicity just map the
* whole multicast group table now. The table isn't very big
@@ -466,11 +474,15 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
if (!mdev->mcg_table.table) {
mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
err = -ENOMEM;
- goto err_unmap_cq;
+ goto err_unmap_srq;
}
return 0;
+err_unmap_srq:
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ mthca_free_icm_table(mdev, mdev->srq_table.table);
+
err_unmap_cq:
mthca_free_icm_table(mdev, mdev->cq_table.table);
@@ -501,12 +513,30 @@ err_free_aux:
return err;
}
+static void mthca_free_icms(struct mthca_dev *mdev)
+{
+ u8 status;
+
+ mthca_free_icm_table(mdev, mdev->mcg_table.table);
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ mthca_free_icm_table(mdev, mdev->srq_table.table);
+ mthca_free_icm_table(mdev, mdev->cq_table.table);
+ mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
+ mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
+ mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
+ mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
+ mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
+ mthca_unmap_eq_icm(mdev);
+
+ mthca_UNMAP_ICM_AUX(mdev, &status);
+ mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+}
+
static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
{
struct mthca_dev_lim dev_lim;
struct mthca_profile profile;
struct mthca_init_hca_param init_hca;
- struct mthca_adapter adapter;
u64 icm_size;
u8 status;
int err;
@@ -551,6 +581,8 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.num_udav = 0;
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ profile.num_srq = dev_lim.max_srqs;
icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
if ((int) icm_size < 0) {
@@ -574,34 +606,10 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev)
goto err_free_icm;
}
- err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
- if (err) {
- mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
- goto err_free_icm;
- }
- if (status) {
- mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
- "aborting.\n", status);
- err = -EINVAL;
- goto err_free_icm;
- }
-
- mdev->eq_table.inta_pin = adapter.inta_pin;
- mdev->rev_id = adapter.revision_id;
-
return 0;
err_free_icm:
- mthca_free_icm_table(mdev, mdev->cq_table.table);
- mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
- mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
- mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
- mthca_unmap_eq_icm(mdev);
-
- mthca_UNMAP_ICM_AUX(mdev, &status);
- mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
+ mthca_free_icms(mdev);
err_stop_fw:
mthca_UNMAP_FA(mdev, &status);
@@ -614,12 +622,59 @@ err_disable:
return err;
}
+static void mthca_close_hca(struct mthca_dev *mdev)
+{
+ u8 status;
+
+ mthca_CLOSE_HCA(mdev, 0, &status);
+
+ if (mthca_is_memfree(mdev)) {
+ mthca_free_icms(mdev);
+
+ mthca_UNMAP_FA(mdev, &status);
+ mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
+
+ if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
+ mthca_DISABLE_LAM(mdev, &status);
+ } else
+ mthca_SYS_DIS(mdev, &status);
+}
+
static int __devinit mthca_init_hca(struct mthca_dev *mdev)
{
+ u8 status;
+ int err;
+ struct mthca_adapter adapter;
+
if (mthca_is_memfree(mdev))
- return mthca_init_arbel(mdev);
+ err = mthca_init_arbel(mdev);
else
- return mthca_init_tavor(mdev);
+ err = mthca_init_tavor(mdev);
+
+ if (err)
+ return err;
+
+ err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+ if (err) {
+ mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
+ goto err_close;
+ }
+ if (status) {
+ mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
+ "aborting.\n", status);
+ err = -EINVAL;
+ goto err_close;
+ }
+
+ mdev->eq_table.inta_pin = adapter.inta_pin;
+ mdev->rev_id = adapter.revision_id;
+ memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
+
+ return 0;
+
+err_close:
+ mthca_close_hca(mdev);
+ return err;
}
static int __devinit mthca_setup_hca(struct mthca_dev *dev)
@@ -709,11 +764,18 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
goto err_cmd_poll;
}
+ err = mthca_init_srq_table(dev);
+ if (err) {
+ mthca_err(dev, "Failed to initialize "
+ "shared receive queue table, aborting.\n");
+ goto err_cq_table_free;
+ }
+
err = mthca_init_qp_table(dev);
if (err) {
mthca_err(dev, "Failed to initialize "
"queue pair table, aborting.\n");
- goto err_cq_table_free;
+ goto err_srq_table_free;
}
err = mthca_init_av_table(dev);
@@ -738,6 +800,9 @@ err_av_table_free:
err_qp_table_free:
mthca_cleanup_qp_table(dev);
+err_srq_table_free:
+ mthca_cleanup_srq_table(dev);
+
err_cq_table_free:
mthca_cleanup_cq_table(dev);
@@ -844,33 +909,6 @@ static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev)
return 0;
}
-static void mthca_close_hca(struct mthca_dev *mdev)
-{
- u8 status;
-
- mthca_CLOSE_HCA(mdev, 0, &status);
-
- if (mthca_is_memfree(mdev)) {
- mthca_free_icm_table(mdev, mdev->cq_table.table);
- mthca_free_icm_table(mdev, mdev->qp_table.rdb_table);
- mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
- mthca_free_icm_table(mdev, mdev->qp_table.qp_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);
- mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
- mthca_unmap_eq_icm(mdev);
-
- mthca_UNMAP_ICM_AUX(mdev, &status);
- mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);
-
- mthca_UNMAP_FA(mdev, &status);
- mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);
-
- if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
- mthca_DISABLE_LAM(mdev, &status);
- } else
- mthca_SYS_DIS(mdev, &status);
-}
-
/* Types of supported HCA */
enum {
TAVOR, /* MT23108 */
@@ -887,9 +925,9 @@ static struct {
int is_memfree;
int is_pcie;
} mthca_hca_table[] = {
- [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 2), .is_memfree = 0, .is_pcie = 0 },
- [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 6, 2), .is_memfree = 0, .is_pcie = 1 },
- [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 0, 1), .is_memfree = 1, .is_pcie = 1 },
+ [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 },
+ [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 },
+ [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 },
[SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 }
};
@@ -906,12 +944,12 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
++mthca_version_printed;
}
- printk(KERN_INFO PFX "Initializing %s (%s)\n",
- pci_pretty_name(pdev), pci_name(pdev));
+ printk(KERN_INFO PFX "Initializing %s\n",
+ pci_name(pdev));
if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) {
- printk(KERN_ERR PFX "%s (%s) has invalid driver data %lx\n",
- pci_pretty_name(pdev), pci_name(pdev), id->driver_data);
+ printk(KERN_ERR PFX "%s has invalid driver data %lx\n",
+ pci_name(pdev), id->driver_data);
return -ENODEV;
}
@@ -1019,7 +1057,7 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
goto err_cmd;
if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) {
- mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n",
+ mthca_warn(mdev, "HCA FW version %d.%d.%d is old (%d.%d.%d is current).\n",
(int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff,
(int) (mdev->fw_ver & 0xffff),
(int) (mthca_hca_table[id->driver_data].latest_fw >> 32),
@@ -1051,6 +1089,7 @@ err_cleanup:
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
mthca_cleanup_qp_table(mdev);
+ mthca_cleanup_srq_table(mdev);
mthca_cleanup_cq_table(mdev);
mthca_cmd_use_polling(mdev);
mthca_cleanup_eq_table(mdev);
@@ -1100,6 +1139,7 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev)
mthca_cleanup_mcg_table(mdev);
mthca_cleanup_av_table(mdev);
mthca_cleanup_qp_table(mdev);
+ mthca_cleanup_srq_table(mdev);
mthca_cleanup_cq_table(mdev);
mthca_cmd_use_polling(mdev);
mthca_cleanup_eq_table(mdev);
@@ -1156,6 +1196,7 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table);
static struct pci_driver mthca_driver = {
.name = DRV_NAME,
+ .owner = THIS_MODULE,
.id_table = mthca_pci_table,
.probe = mthca_init_one,
.remove = __devexit_p(mthca_remove_one)
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 5be7d949dbf6..2fc449da418d 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -33,19 +33,17 @@
*/
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
-enum {
- MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
-};
-
struct mthca_mgm {
- u32 next_gid_index;
- u32 reserved[3];
- u8 gid[16];
- u32 qp[MTHCA_QP_PER_MGM];
+ __be32 next_gid_index;
+ u32 reserved[3];
+ u8 gid[16];
+ __be32 qp[MTHCA_QP_PER_MGM];
};
static const u8 zero_gid[16]; /* automatically initialized to 0 */
@@ -94,10 +92,14 @@ static int find_mgm(struct mthca_dev *dev,
if (0)
mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
"%04x:%04x:%04x:%04x is %04x\n",
- be16_to_cpu(((u16 *) gid)[0]), be16_to_cpu(((u16 *) gid)[1]),
- be16_to_cpu(((u16 *) gid)[2]), be16_to_cpu(((u16 *) gid)[3]),
- be16_to_cpu(((u16 *) gid)[4]), be16_to_cpu(((u16 *) gid)[5]),
- be16_to_cpu(((u16 *) gid)[6]), be16_to_cpu(((u16 *) gid)[7]),
+ be16_to_cpu(((__be16 *) gid)[0]),
+ be16_to_cpu(((__be16 *) gid)[1]),
+ be16_to_cpu(((__be16 *) gid)[2]),
+ be16_to_cpu(((__be16 *) gid)[3]),
+ be16_to_cpu(((__be16 *) gid)[4]),
+ be16_to_cpu(((__be16 *) gid)[5]),
+ be16_to_cpu(((__be16 *) gid)[6]),
+ be16_to_cpu(((__be16 *) gid)[7]),
*hash);
*index = *hash;
@@ -185,7 +187,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
}
for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
- if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
+ if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) {
+ mthca_dbg(dev, "QP %06x already a member of MGM\n",
+ ibqp->qp_num);
+ err = 0;
+ goto out;
+ } else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
break;
}
@@ -258,14 +265,14 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (index == -1) {
mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"not found\n",
- be16_to_cpu(((u16 *) gid->raw)[0]),
- be16_to_cpu(((u16 *) gid->raw)[1]),
- be16_to_cpu(((u16 *) gid->raw)[2]),
- be16_to_cpu(((u16 *) gid->raw)[3]),
- be16_to_cpu(((u16 *) gid->raw)[4]),
- be16_to_cpu(((u16 *) gid->raw)[5]),
- be16_to_cpu(((u16 *) gid->raw)[6]),
- be16_to_cpu(((u16 *) gid->raw)[7]));
+ be16_to_cpu(((__be16 *) gid->raw)[0]),
+ be16_to_cpu(((__be16 *) gid->raw)[1]),
+ be16_to_cpu(((__be16 *) gid->raw)[2]),
+ be16_to_cpu(((__be16 *) gid->raw)[3]),
+ be16_to_cpu(((__be16 *) gid->raw)[4]),
+ be16_to_cpu(((__be16 *) gid->raw)[5]),
+ be16_to_cpu(((__be16 *) gid->raw)[6]),
+ be16_to_cpu(((__be16 *) gid->raw)[7]));
err = -EINVAL;
goto out;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 2a8646150355..d72fe95cba08 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -81,7 +82,7 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
}
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- unsigned int gfp_mask)
+ gfp_t gfp_mask)
{
struct mthca_icm *icm;
struct mthca_icm_chunk *chunk = NULL;
@@ -285,10 +286,11 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
{
struct mthca_icm_table *table;
int num_icm;
+ unsigned chunk_size;
int i;
u8 status;
- num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE;
+ num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
if (!table)
@@ -305,7 +307,11 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
table->icm[i] = NULL;
for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
- table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
+ chunk_size = MTHCA_TABLE_CHUNK_SIZE;
+ if ((i + 1) * MTHCA_TABLE_CHUNK_SIZE > nobj * obj_size)
+ chunk_size = nobj * obj_size - i * MTHCA_TABLE_CHUNK_SIZE;
+
+ table->icm[i] = mthca_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
__GFP_NOWARN);
if (!table->icm[i])
@@ -481,7 +487,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
}
}
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+ u32 qn, __be32 **db)
{
int group;
int start, end, dir;
@@ -523,12 +530,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
goto found;
}
+ for (i = start; i != end; i += dir)
+ if (!dev->db_tab->page[i].db_rec) {
+ page = dev->db_tab->page + i;
+ goto alloc;
+ }
+
if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
ret = -ENOMEM;
goto out;
}
+ if (group == 0)
+ ++dev->db_tab->max_group1;
+ else
+ --dev->db_tab->min_group2;
+
page = dev->db_tab->page + end;
+
+alloc:
page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
&page->mapping, GFP_KERNEL);
if (!page->db_rec) {
@@ -548,10 +568,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
}
bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
- if (group == 0)
- ++dev->db_tab->max_group1;
- else
- --dev->db_tab->min_group2;
found:
j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
@@ -564,7 +580,7 @@ found:
page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
- *db = (u32 *) &page->db_rec[j];
+ *db = (__be32 *) &page->db_rec[j];
out:
up(&dev->db_tab->mutex);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 4761d844cb5f..4fdca26eea85 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -76,7 +77,7 @@ struct mthca_icm_iter {
struct mthca_dev;
struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
- unsigned int gfp_mask);
+ gfp_t gfp_mask);
void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
@@ -137,7 +138,7 @@ enum {
struct mthca_db_page {
DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE);
- u64 *db_rec;
+ __be64 *db_rec;
dma_addr_t mapping;
};
@@ -172,7 +173,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
int mthca_init_db_tab(struct mthca_dev *dev);
void mthca_cleanup_db_tab(struct mthca_dev *dev);
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+ u32 qn, __be32 **db);
void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
#endif /* MTHCA_MEMFREE_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index cbe50feaf680..e995e2aa016d 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -50,18 +51,18 @@ struct mthca_mtt {
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
*/
struct mthca_mpt_entry {
- u32 flags;
- u32 page_size;
- u32 key;
- u32 pd;
- u64 start;
- u64 length;
- u32 lkey;
- u32 window_count;
- u32 window_count_limit;
- u64 mtt_seg;
- u32 mtt_sz; /* Arbel only */
- u32 reserved[2];
+ __be32 flags;
+ __be32 page_size;
+ __be32 key;
+ __be32 pd;
+ __be64 start;
+ __be64 length;
+ __be32 lkey;
+ __be32 window_count;
+ __be32 window_count_limit;
+ __be64 mtt_seg;
+ __be32 mtt_sz; /* Arbel only */
+ u32 reserved[2];
} __attribute__((packed));
#define MTHCA_MPT_FLAG_SW_OWNS (0xfUL << 28)
@@ -139,13 +140,11 @@ static int __devinit mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
buddy->max_order = max_order;
spin_lock_init(&buddy->lock);
- buddy->bits = kmalloc((buddy->max_order + 1) * sizeof (long *),
+ buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
if (!buddy->bits)
goto err_out;
- memset(buddy->bits, 0, (buddy->max_order + 1) * sizeof (long *));
-
for (i = 0; i <= buddy->max_order; ++i) {
s = BITS_TO_LONGS(1 << (buddy->max_order - i));
buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
@@ -247,7 +246,7 @@ int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
int start_index, u64 *buffer_list, int list_len)
{
struct mthca_mailbox *mailbox;
- u64 *mtt_entry;
+ __be64 *mtt_entry;
int err = 0;
u8 status;
int i;
@@ -389,7 +388,7 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
if (i % 4 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+ printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
if ((i + 1) % 4 == 0)
printk("\n");
}
@@ -458,7 +457,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
{
mthca_table_put(dev, dev->mr_table.mpt_table,
- arbel_key_to_hw_index(lkey));
+ key_to_hw_index(dev, lkey));
mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey));
}
@@ -562,7 +561,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
if (i % 4 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+ printk(" %08x", be32_to_cpu(((__be32 *) mpt_entry)[i]));
if ((i + 1) % 4 == 0)
printk("\n");
}
@@ -669,7 +668,7 @@ int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size));
mpt_entry.start = cpu_to_be64(iova);
- writel(mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
+ __raw_writel((__force u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key);
memcpy_toio(&fmr->mem.tavor.mpt->start, &mpt_entry.start,
offsetof(struct mthca_mpt_entry, window_count) -
offsetof(struct mthca_mpt_entry, start));
diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c
index c2c899844e98..3dbf06a6e6f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_pd.c
+++ b/drivers/infiniband/hw/mthca/mthca_pd.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 4fedc32d5871..08a909371b0a 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -34,6 +35,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "mthca_profile.h"
@@ -79,12 +82,10 @@ u64 mthca_make_profile(struct mthca_dev *dev,
struct mthca_resource tmp;
int i, j;
- profile = kmalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
+ profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
if (!profile)
return -ENOMEM;
- memset(profile, 0, MTHCA_RES_NUM * sizeof *profile);
-
profile[MTHCA_RES_QP].size = dev_lim->qpc_entry_sz;
profile[MTHCA_RES_EEC].size = dev_lim->eec_entry_sz;
profile[MTHCA_RES_SRQ].size = dev_lim->srq_entry_sz;
@@ -101,6 +102,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
profile[MTHCA_RES_UARC].size = request->uarc_size;
profile[MTHCA_RES_QP].num = request->num_qp;
+ profile[MTHCA_RES_SRQ].num = request->num_srq;
profile[MTHCA_RES_EQP].num = request->num_qp;
profile[MTHCA_RES_RDB].num = request->num_qp * request->rdb_per_qp;
profile[MTHCA_RES_CQ].num = request->num_cq;
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.h b/drivers/infiniband/hw/mthca/mthca_profile.h
index 17aef3357661..94641808f97f 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.h
+++ b/drivers/infiniband/hw/mthca/mthca_profile.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -41,6 +42,7 @@
struct mthca_profile {
int num_qp;
int rdb_per_qp;
+ int num_srq;
int num_cq;
int num_mcg;
int num_mpt;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 81919a7b4935..6b0166668269 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -2,6 +2,8 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -34,7 +36,8 @@
* $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $
*/
-#include <ib_smi.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
#include <linux/mm.h>
#include "mthca_dev.h"
@@ -79,24 +82,35 @@ static int mthca_query_device(struct ib_device *ibdev,
}
props->device_cap_flags = mdev->device_cap_flags;
- props->vendor_id = be32_to_cpup((u32 *) (out_mad->data + 36)) &
+ props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
- props->vendor_part_id = be16_to_cpup((u16 *) (out_mad->data + 30));
- props->hw_ver = be16_to_cpup((u16 *) (out_mad->data + 32));
+ props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30));
+ props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32));
memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
memcpy(&props->node_guid, out_mad->data + 12, 8);
props->max_mr_size = ~0ull;
props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps;
- props->max_qp_wr = 0xffff;
+ props->max_qp_wr = mdev->limits.max_wqes;
props->max_sge = mdev->limits.max_sg;
props->max_cq = mdev->limits.num_cqs - mdev->limits.reserved_cqs;
- props->max_cqe = 0xffff;
+ props->max_cqe = mdev->limits.max_cqes;
props->max_mr = mdev->limits.num_mpts - mdev->limits.reserved_mrws;
props->max_pd = mdev->limits.num_pds - mdev->limits.reserved_pds;
props->max_qp_rd_atom = 1 << mdev->qp_table.rdb_shift;
- props->max_qp_init_rd_atom = 1 << mdev->qp_table.rdb_shift;
+ props->max_qp_init_rd_atom = mdev->limits.max_qp_init_rdma;
+ props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
+ props->max_srq = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
+ props->max_srq_wr = mdev->limits.max_srq_wqes;
+ props->max_srq_sge = mdev->limits.max_sg;
props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay;
+ props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ?
+ IB_ATOMIC_HCA : IB_ATOMIC_NONE;
+ props->max_pkeys = mdev->limits.pkey_table_len;
+ props->max_mcast_grp = mdev->limits.num_mgms + mdev->limits.num_amgms;
+ props->max_mcast_qp_attach = MTHCA_QP_PER_MGM;
+ props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
+ props->max_mcast_grp;
err = 0;
out:
@@ -118,6 +132,8 @@ static int mthca_query_port(struct ib_device *ibdev,
if (!in_mad || !out_mad)
goto out;
+ memset(props, 0, sizeof *props);
+
memset(in_mad, 0, sizeof *in_mad);
in_mad->base_version = 1;
in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
@@ -136,18 +152,23 @@ static int mthca_query_port(struct ib_device *ibdev,
goto out;
}
- props->lid = be16_to_cpup((u16 *) (out_mad->data + 16));
+ props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
- props->sm_lid = be16_to_cpup((u16 *) (out_mad->data + 18));
+ props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
props->sm_sl = out_mad->data[36] & 0xf;
props->state = out_mad->data[32] & 0xf;
props->phys_state = out_mad->data[33] >> 4;
- props->port_cap_flags = be32_to_cpup((u32 *) (out_mad->data + 20));
+ props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20));
props->gid_tbl_len = to_mdev(ibdev)->limits.gid_table_len;
+ props->max_msg_sz = 0x80000000;
props->pkey_tbl_len = to_mdev(ibdev)->limits.pkey_table_len;
- props->qkey_viol_cntr = be16_to_cpup((u16 *) (out_mad->data + 48));
+ props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
+ props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
props->active_width = out_mad->data[31] & 0xf;
props->active_speed = out_mad->data[35] >> 4;
+ props->max_mtu = out_mad->data[41] & 0xf;
+ props->active_mtu = out_mad->data[36] >> 4;
+ props->subnet_timeout = out_mad->data[51] & 0x1f;
out:
kfree(in_mad);
@@ -221,7 +242,7 @@ static int mthca_query_pkey(struct ib_device *ibdev,
goto out;
}
- *pkey = be16_to_cpu(((u16 *) out_mad->data)[index % 32]);
+ *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
out:
kfree(in_mad);
@@ -420,6 +441,77 @@ static int mthca_ah_destroy(struct ib_ah *ah)
return 0;
}
+static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct mthca_create_srq ucmd;
+ struct mthca_ucontext *context = NULL;
+ struct mthca_srq *srq;
+ int err;
+
+ srq = kmalloc(sizeof *srq, GFP_KERNEL);
+ if (!srq)
+ return ERR_PTR(-ENOMEM);
+
+ if (pd->uobject) {
+ context = to_mucontext(pd->uobject->context);
+
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+ return ERR_PTR(-EFAULT);
+
+ err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+ context->db_tab, ucmd.db_index,
+ ucmd.db_page);
+
+ if (err)
+ goto err_free;
+
+ srq->mr.ibmr.lkey = ucmd.lkey;
+ srq->db_index = ucmd.db_index;
+ }
+
+ err = mthca_alloc_srq(to_mdev(pd->device), to_mpd(pd),
+ &init_attr->attr, srq);
+
+ if (err && pd->uobject)
+ mthca_unmap_user_db(to_mdev(pd->device), &context->uar,
+ context->db_tab, ucmd.db_index);
+
+ if (err)
+ goto err_free;
+
+ if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof (__u32))) {
+ mthca_free_srq(to_mdev(pd->device), srq);
+ err = -EFAULT;
+ goto err_free;
+ }
+
+ return &srq->ibsrq;
+
+err_free:
+ kfree(srq);
+
+ return ERR_PTR(err);
+}
+
+static int mthca_destroy_srq(struct ib_srq *srq)
+{
+ struct mthca_ucontext *context;
+
+ if (srq->uobject) {
+ context = to_mucontext(srq->uobject->context);
+
+ mthca_unmap_user_db(to_mdev(srq->device), &context->uar,
+ context->db_tab, to_msrq(srq)->db_index);
+ }
+
+ mthca_free_srq(to_mdev(srq->device), to_msrq(srq));
+ kfree(srq);
+
+ return 0;
+}
+
static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata)
@@ -558,6 +650,9 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
int nent;
int err;
+ if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes)
+ return ERR_PTR(-EINVAL);
+
if (context) {
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
return ERR_PTR(-EFAULT);
@@ -933,7 +1028,7 @@ static ssize_t show_rev(struct class_device *cdev, char *buf)
static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
{
struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
- return sprintf(buf, "%x.%x.%x\n", (int) (dev->fw_ver >> 32),
+ return sprintf(buf, "%d.%d.%d\n", (int) (dev->fw_ver >> 32),
(int) (dev->fw_ver >> 16) & 0xffff,
(int) dev->fw_ver & 0xffff);
}
@@ -956,14 +1051,22 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
}
}
+static ssize_t show_board(struct class_device *cdev, char *buf)
+{
+ struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
+ return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
+}
+
static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct class_device_attribute *mthca_class_attributes[] = {
&class_device_attr_hw_rev,
&class_device_attr_fw_ver,
- &class_device_attr_hca_type
+ &class_device_attr_hca_type,
+ &class_device_attr_board_id
};
int mthca_register_device(struct mthca_dev *dev)
@@ -974,6 +1077,26 @@ int mthca_register_device(struct mthca_dev *dev)
strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
dev->ib_dev.owner = THIS_MODULE;
+ dev->ib_dev.uverbs_abi_ver = MTHCA_UVERBS_ABI_VERSION;
+ dev->ib_dev.uverbs_cmd_mask =
+ (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
+ (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_REG_MR) |
+ (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
+ (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
+ (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
dev->ib_dev.node_type = IB_NODE_CA;
dev->ib_dev.phys_port_cnt = dev->limits.num_ports;
dev->ib_dev.dma_device = &dev->pdev->dev;
@@ -990,6 +1113,18 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.dealloc_pd = mthca_dealloc_pd;
dev->ib_dev.create_ah = mthca_ah_create;
dev->ib_dev.destroy_ah = mthca_ah_destroy;
+
+ if (dev->mthca_flags & MTHCA_FLAG_SRQ) {
+ dev->ib_dev.create_srq = mthca_create_srq;
+ dev->ib_dev.modify_srq = mthca_modify_srq;
+ dev->ib_dev.destroy_srq = mthca_destroy_srq;
+
+ if (mthca_is_memfree(dev))
+ dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;
+ else
+ dev->ib_dev.post_srq_recv = mthca_tavor_post_srq_recv;
+ }
+
dev->ib_dev.create_qp = mthca_create_qp;
dev->ib_dev.modify_qp = mthca_modify_qp;
dev->ib_dev.destroy_qp = mthca_destroy_qp;
@@ -1040,10 +1175,13 @@ int mthca_register_device(struct mthca_dev *dev)
}
}
+ mthca_start_catas_poll(dev);
+
return 0;
}
void mthca_unregister_device(struct mthca_dev *dev)
{
+ mthca_stop_catas_poll(dev);
ib_unregister_device(&dev->ib_dev);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 1d032791cc8b..bcd4b01a339c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -36,8 +37,8 @@
#ifndef MTHCA_PROVIDER_H
#define MTHCA_PROVIDER_H
-#include <ib_verbs.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
#define MTHCA_MPT_FLAG_ATOMIC (1 << 14)
#define MTHCA_MPT_FLAG_REMOTE_WRITE (1 << 13)
@@ -50,6 +51,11 @@ struct mthca_buf_list {
DECLARE_PCI_UNMAP_ADDR(mapping)
};
+union mthca_buf {
+ struct mthca_buf_list direct;
+ struct mthca_buf_list *page_list;
+};
+
struct mthca_uar {
unsigned long pfn;
int index;
@@ -181,19 +187,39 @@ struct mthca_cq {
/* Next fields are Arbel only */
int set_ci_db_index;
- u32 *set_ci_db;
+ __be32 *set_ci_db;
int arm_db_index;
- u32 *arm_db;
+ __be32 *arm_db;
int arm_sn;
- union {
- struct mthca_buf_list direct;
- struct mthca_buf_list *page_list;
- } queue;
+ union mthca_buf queue;
struct mthca_mr mr;
wait_queue_head_t wait;
};
+struct mthca_srq {
+ struct ib_srq ibsrq;
+ spinlock_t lock;
+ atomic_t refcount;
+ int srqn;
+ int max;
+ int max_gs;
+ int wqe_shift;
+ int first_free;
+ int last_free;
+ u16 counter; /* Arbel only */
+ int db_index; /* Arbel only */
+ __be32 *db; /* Arbel only */
+ void *last;
+
+ int is_direct;
+ u64 *wrid;
+ union mthca_buf queue;
+ struct mthca_mr mr;
+
+ wait_queue_head_t wait;
+};
+
struct mthca_wq {
spinlock_t lock;
int max;
@@ -206,7 +232,7 @@ struct mthca_wq {
int wqe_shift;
int db_index; /* Arbel only */
- u32 *db;
+ __be32 *db;
};
struct mthca_qp {
@@ -227,10 +253,7 @@ struct mthca_qp {
int send_wqe_offset;
u64 *wrid;
- union {
- struct mthca_buf_list direct;
- struct mthca_buf_list *page_list;
- } queue;
+ union mthca_buf queue;
wait_queue_head_t wait;
};
@@ -277,6 +300,11 @@ static inline struct mthca_cq *to_mcq(struct ib_cq *ibcq)
return container_of(ibcq, struct mthca_cq, ibcq);
}
+static inline struct mthca_srq *to_msrq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct mthca_srq, ibsrq);
+}
+
static inline struct mthca_qp *to_mqp(struct ib_qp *ibqp)
{
return container_of(ibqp, struct mthca_qp, ibqp);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index f7126b14d5ae..8852ea477c21 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -34,14 +36,17 @@
*/
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
-#include <ib_verbs.h>
-#include <ib_cache.h>
-#include <ib_pack.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_pack.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
#include "mthca_memfree.h"
+#include "mthca_wqe.h"
enum {
MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
@@ -95,62 +100,62 @@ enum {
};
struct mthca_qp_path {
- u32 port_pkey;
- u8 rnr_retry;
- u8 g_mylmc;
- u16 rlid;
- u8 ackto;
- u8 mgid_index;
- u8 static_rate;
- u8 hop_limit;
- u32 sl_tclass_flowlabel;
- u8 rgid[16];
+ __be32 port_pkey;
+ u8 rnr_retry;
+ u8 g_mylmc;
+ __be16 rlid;
+ u8 ackto;
+ u8 mgid_index;
+ u8 static_rate;
+ u8 hop_limit;
+ __be32 sl_tclass_flowlabel;
+ u8 rgid[16];
} __attribute__((packed));
struct mthca_qp_context {
- u32 flags;
- u32 tavor_sched_queue; /* Reserved on Arbel */
- u8 mtu_msgmax;
- u8 rq_size_stride; /* Reserved on Tavor */
- u8 sq_size_stride; /* Reserved on Tavor */
- u8 rlkey_arbel_sched_queue; /* Reserved on Tavor */
- u32 usr_page;
- u32 local_qpn;
- u32 remote_qpn;
- u32 reserved1[2];
+ __be32 flags;
+ __be32 tavor_sched_queue; /* Reserved on Arbel */
+ u8 mtu_msgmax;
+ u8 rq_size_stride; /* Reserved on Tavor */
+ u8 sq_size_stride; /* Reserved on Tavor */
+ u8 rlkey_arbel_sched_queue; /* Reserved on Tavor */
+ __be32 usr_page;
+ __be32 local_qpn;
+ __be32 remote_qpn;
+ u32 reserved1[2];
struct mthca_qp_path pri_path;
struct mthca_qp_path alt_path;
- u32 rdd;
- u32 pd;
- u32 wqe_base;
- u32 wqe_lkey;
- u32 params1;
- u32 reserved2;
- u32 next_send_psn;
- u32 cqn_snd;
- u32 snd_wqe_base_l; /* Next send WQE on Tavor */
- u32 snd_db_index; /* (debugging only entries) */
- u32 last_acked_psn;
- u32 ssn;
- u32 params2;
- u32 rnr_nextrecvpsn;
- u32 ra_buff_indx;
- u32 cqn_rcv;
- u32 rcv_wqe_base_l; /* Next recv WQE on Tavor */
- u32 rcv_db_index; /* (debugging only entries) */
- u32 qkey;
- u32 srqn;
- u32 rmsn;
- u16 rq_wqe_counter; /* reserved on Tavor */
- u16 sq_wqe_counter; /* reserved on Tavor */
- u32 reserved3[18];
+ __be32 rdd;
+ __be32 pd;
+ __be32 wqe_base;
+ __be32 wqe_lkey;
+ __be32 params1;
+ __be32 reserved2;
+ __be32 next_send_psn;
+ __be32 cqn_snd;
+ __be32 snd_wqe_base_l; /* Next send WQE on Tavor */
+ __be32 snd_db_index; /* (debugging only entries) */
+ __be32 last_acked_psn;
+ __be32 ssn;
+ __be32 params2;
+ __be32 rnr_nextrecvpsn;
+ __be32 ra_buff_indx;
+ __be32 cqn_rcv;
+ __be32 rcv_wqe_base_l; /* Next recv WQE on Tavor */
+ __be32 rcv_db_index; /* (debugging only entries) */
+ __be32 qkey;
+ __be32 srqn;
+ __be32 rmsn;
+ __be16 rq_wqe_counter; /* reserved on Tavor */
+ __be16 sq_wqe_counter; /* reserved on Tavor */
+ u32 reserved3[18];
} __attribute__((packed));
struct mthca_qp_param {
- u32 opt_param_mask;
- u32 reserved1;
+ __be32 opt_param_mask;
+ u32 reserved1;
struct mthca_qp_context context;
- u32 reserved2[62];
+ u32 reserved2[62];
} __attribute__((packed));
enum {
@@ -173,80 +178,6 @@ enum {
MTHCA_QP_OPTPAR_SCHED_QUEUE = 1 << 16
};
-enum {
- MTHCA_NEXT_DBD = 1 << 7,
- MTHCA_NEXT_FENCE = 1 << 6,
- MTHCA_NEXT_CQ_UPDATE = 1 << 3,
- MTHCA_NEXT_EVENT_GEN = 1 << 2,
- MTHCA_NEXT_SOLICIT = 1 << 1,
-
- MTHCA_MLX_VL15 = 1 << 17,
- MTHCA_MLX_SLR = 1 << 16
-};
-
-enum {
- MTHCA_INVAL_LKEY = 0x100
-};
-
-struct mthca_next_seg {
- u32 nda_op; /* [31:6] next WQE [4:0] next opcode */
- u32 ee_nds; /* [31:8] next EE [7] DBD [6] F [5:0] next WQE size */
- u32 flags; /* [3] CQ [2] Event [1] Solicit */
- u32 imm; /* immediate data */
-};
-
-struct mthca_tavor_ud_seg {
- u32 reserved1;
- u32 lkey;
- u64 av_addr;
- u32 reserved2[4];
- u32 dqpn;
- u32 qkey;
- u32 reserved3[2];
-};
-
-struct mthca_arbel_ud_seg {
- u32 av[8];
- u32 dqpn;
- u32 qkey;
- u32 reserved[2];
-};
-
-struct mthca_bind_seg {
- u32 flags; /* [31] Atomic [30] rem write [29] rem read */
- u32 reserved;
- u32 new_rkey;
- u32 lkey;
- u64 addr;
- u64 length;
-};
-
-struct mthca_raddr_seg {
- u64 raddr;
- u32 rkey;
- u32 reserved;
-};
-
-struct mthca_atomic_seg {
- u64 swap_add;
- u64 compare;
-};
-
-struct mthca_data_seg {
- u32 byte_count;
- u32 lkey;
- u64 addr;
-};
-
-struct mthca_mlx_seg {
- u32 nda_op;
- u32 nds;
- u32 flags; /* [17] VL15 [16] SLR [14:12] static rate
- [11:8] SL [3] C [2] E */
- u16 rlid;
- u16 vcrc;
-};
-
static const u8 mthca_opcode[] = {
[IB_WR_SEND] = MTHCA_OPCODE_SEND,
[IB_WR_SEND_WITH_IMM] = MTHCA_OPCODE_SEND_IMM,
@@ -291,6 +222,15 @@ static void *get_send_wqe(struct mthca_qp *qp, int n)
(PAGE_SIZE - 1));
}
+static void mthca_wq_init(struct mthca_wq *wq)
+{
+ spin_lock_init(&wq->lock);
+ wq->next_ind = 0;
+ wq->last_comp = wq->max - 1;
+ wq->head = 0;
+ wq->tail = 0;
+}
+
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
enum ib_event_type event_type)
{
@@ -400,8 +340,7 @@ static const struct {
[UC] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
- IB_QP_RQ_PSN |
- IB_QP_MAX_DEST_RD_ATOMIC),
+ IB_QP_RQ_PSN),
[RC] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
@@ -430,8 +369,7 @@ static const struct {
.trans = MTHCA_TRANS_RTR2RTS,
.req_param = {
[UD] = IB_QP_SQ_PSN,
- [UC] = (IB_QP_SQ_PSN |
- IB_QP_MAX_QP_RD_ATOMIC),
+ [UC] = IB_QP_SQ_PSN,
[RC] = (IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
@@ -508,8 +446,6 @@ static const struct {
[UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[UC] = (IB_QP_AV |
- IB_QP_MAX_QP_RD_ATOMIC |
- IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
@@ -540,7 +476,7 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = (IB_QP_CUR_STATE),
+ [UC] = IB_QP_CUR_STATE,
[RC] = (IB_QP_CUR_STATE |
IB_QP_MIN_RNR_TIMER),
[MLX] = (IB_QP_CUR_STATE |
@@ -573,12 +509,11 @@ static void init_port(struct mthca_dev *dev, int port)
memset(&param, 0, sizeof param);
- param.enable_1x = 1;
- param.enable_4x = 1;
- param.vl_cap = dev->limits.vl_cap;
- param.mtu_cap = dev->limits.mtu_cap;
- param.gid_cap = dev->limits.gid_table_len;
- param.pkey_cap = dev->limits.pkey_table_len;
+ param.port_width = dev->limits.port_width_cap;
+ param.vl_cap = dev->limits.vl_cap;
+ param.mtu_cap = dev->limits.mtu_cap;
+ param.gid_cap = dev->limits.gid_table_len;
+ param.pkey_cap = dev->limits.pkey_table_len;
err = mthca_INIT_IB(dev, &param, port, &status);
if (err)
@@ -649,6 +584,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
+ if ((attr_mask & IB_QP_PKEY_INDEX) &&
+ attr->pkey_index >= dev->limits.pkey_table_len) {
+ mthca_dbg(dev, "PKey index (%u) too large. max is %d\n",
+ attr->pkey_index,dev->limits.pkey_table_len-1);
+ return -EINVAL;
+ }
+
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -684,10 +626,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
if (mthca_is_memfree(dev)) {
- qp_context->rq_size_stride =
- ((ffs(qp->rq.max) - 1) << 3) | (qp->rq.wqe_shift - 4);
- qp_context->sq_size_stride =
- ((ffs(qp->sq.max) - 1) << 3) | (qp->sq.wqe_shift - 4);
+ if (qp->rq.max)
+ qp_context->rq_size_stride = long_log2(qp->rq.max) << 3;
+ qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
+
+ if (qp->sq.max)
+ qp_context->sq_size_stride = long_log2(qp->sq.max) << 3;
+ qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
}
/* leave arbel_sched_queue as 0 */
@@ -746,7 +691,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_TIMEOUT) {
- qp_context->pri_path.ackto = attr->timeout;
+ qp_context->pri_path.ackto = attr->timeout << 3;
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT);
}
@@ -856,6 +801,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+ if (ibqp->srq)
+ qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RIC);
+
if (attr_mask & IB_QP_MIN_RNR_TIMER) {
qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
@@ -878,6 +826,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
}
+ if (ibqp->srq)
+ qp_context->srqn = cpu_to_be32(1 << 24 |
+ to_msrq(ibqp->srq)->srqn);
+
err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans,
qp->qpn, 0, mailbox, 0, &status);
if (status) {
@@ -895,8 +847,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
store_attrs(to_msqp(qp), attr, attr_mask);
/*
- * If we are moving QP0 to RTR, bring the IB link up; if we
- * are moving QP0 to RESET or ERROR, bring the link back down.
+ * If we moved QP0 to RTR, bring the IB link up; if we moved
+ * QP0 to RESET or ERROR, bring the link back down.
*/
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR &&
@@ -910,6 +862,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
}
+ /*
+ * If we moved a kernel QP to RESET, clean up all old CQ
+ * entries and reinitialize the QP.
+ */
+ if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+ if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+
+ mthca_wq_init(&qp->sq);
+ mthca_wq_init(&qp->rq);
+
+ if (mthca_is_memfree(dev)) {
+ *qp->sq.db = 0;
+ *qp->rq.db = 0;
+ }
+ }
+
return err;
}
@@ -925,10 +897,6 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
struct mthca_qp *qp)
{
int size;
- int i;
- int npages, shift;
- dma_addr_t t;
- u64 *dma_list = NULL;
int err = -ENOMEM;
size = sizeof (struct mthca_next_seg) +
@@ -978,116 +946,24 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
if (!qp->wrid)
goto err_out;
- if (size <= MTHCA_MAX_DIRECT_QP_SIZE) {
- qp->is_direct = 1;
- npages = 1;
- shift = get_order(size) + PAGE_SHIFT;
-
- if (0)
- mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n",
- size, shift);
-
- qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size,
- &t, GFP_KERNEL);
- if (!qp->queue.direct.buf)
- goto err_out;
-
- pci_unmap_addr_set(&qp->queue.direct, mapping, t);
-
- memset(qp->queue.direct.buf, 0, size);
-
- while (t & ((1 << shift) - 1)) {
- --shift;
- npages *= 2;
- }
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_out_free;
-
- for (i = 0; i < npages; ++i)
- dma_list[i] = t + i * (1 << shift);
- } else {
- qp->is_direct = 0;
- npages = size / PAGE_SIZE;
- shift = PAGE_SHIFT;
-
- if (0)
- mthca_dbg(dev, "Creating indirect QP with %d pages\n", npages);
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_out;
-
- qp->queue.page_list = kmalloc(npages *
- sizeof *qp->queue.page_list,
- GFP_KERNEL);
- if (!qp->queue.page_list)
- goto err_out;
-
- for (i = 0; i < npages; ++i) {
- qp->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
- if (!qp->queue.page_list[i].buf)
- goto err_out_free;
-
- memset(qp->queue.page_list[i].buf, 0, PAGE_SIZE);
-
- pci_unmap_addr_set(&qp->queue.page_list[i], mapping, t);
- dma_list[i] = t;
- }
- }
-
- err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
- npages, 0, size,
- MTHCA_MPT_FLAG_LOCAL_READ,
- &qp->mr);
+ err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_QP_SIZE,
+ &qp->queue, &qp->is_direct, pd, 0, &qp->mr);
if (err)
- goto err_out_free;
+ goto err_out;
- kfree(dma_list);
return 0;
- err_out_free:
- if (qp->is_direct) {
- dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
- pci_unmap_addr(&qp->queue.direct, mapping));
- } else
- for (i = 0; i < npages; ++i) {
- if (qp->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- qp->queue.page_list[i].buf,
- pci_unmap_addr(&qp->queue.page_list[i],
- mapping));
-
- }
-
- err_out:
+err_out:
kfree(qp->wrid);
- kfree(dma_list);
return err;
}
static void mthca_free_wqe_buf(struct mthca_dev *dev,
struct mthca_qp *qp)
{
- int i;
- int size = PAGE_ALIGN(qp->send_wqe_offset +
- (qp->sq.max << qp->sq.wqe_shift));
-
- if (qp->is_direct) {
- dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
- pci_unmap_addr(&qp->queue.direct, mapping));
- } else {
- for (i = 0; i < size / PAGE_SIZE; ++i) {
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- qp->queue.page_list[i].buf,
- pci_unmap_addr(&qp->queue.page_list[i],
- mapping));
- }
- }
-
+ mthca_buf_free(dev, PAGE_ALIGN(qp->send_wqe_offset +
+ (qp->sq.max << qp->sq.wqe_shift)),
+ &qp->queue, qp->is_direct, &qp->mr);
kfree(qp->wrid);
}
@@ -1161,16 +1037,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
}
}
-static void mthca_wq_init(struct mthca_wq* wq)
-{
- spin_lock_init(&wq->lock);
- wq->next_ind = 0;
- wq->last_comp = wq->max - 1;
- wq->head = 0;
- wq->tail = 0;
- wq->last = NULL;
-}
-
static int mthca_alloc_qp_common(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
@@ -1182,6 +1048,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
int i;
atomic_set(&qp->refcount, 1);
+ init_waitqueue_head(&qp->wait);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
qp->resp_depth = 0;
@@ -1240,6 +1107,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
}
}
+ qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
+ qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1);
+
return 0;
}
@@ -1247,8 +1117,10 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
struct mthca_qp *qp)
{
/* Sanity check QP size before proceeding */
- if (cap->max_send_wr > 65536 || cap->max_recv_wr > 65536 ||
- cap->max_send_sge > 64 || cap->max_recv_sge > 64)
+ if (cap->max_send_wr > dev->limits.max_wqes ||
+ cap->max_recv_wr > dev->limits.max_wqes ||
+ cap->max_send_sge > dev->limits.max_sg ||
+ cap->max_recv_sge > dev->limits.max_sg)
return -EINVAL;
if (mthca_is_memfree(dev)) {
@@ -1428,11 +1300,12 @@ void mthca_free_qp(struct mthca_dev *dev,
* unref the mem-free tables and free the QPN in our table.
*/
if (!qp->ibqp.uobject) {
- mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn);
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
- mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn);
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+ qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
- mthca_free_mr(dev, &qp->mr);
mthca_free_memfree(dev, qp);
mthca_free_wqe_buf(dev, qp);
}
@@ -1457,6 +1330,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
{
int header_size;
int err;
+ u16 pkey;
ib_ud_header_init(256, /* assume a MAD */
sqp->ud_header.grh_present,
@@ -1467,8 +1341,8 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
return err;
mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MTHCA_MLX_VL15 : 0) |
- (sqp->ud_header.lrh.destination_lid == 0xffff ?
- MTHCA_MLX_SLR : 0) |
+ (sqp->ud_header.lrh.destination_lid ==
+ IB_LID_PERMISSIVE ? MTHCA_MLX_SLR : 0) |
(sqp->ud_header.lrh.service_level << 8));
mlx->rlid = sqp->ud_header.lrh.destination_lid;
mlx->vcrc = 0;
@@ -1488,18 +1362,16 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
}
sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0;
- if (sqp->ud_header.lrh.destination_lid == 0xffff)
- sqp->ud_header.lrh.source_lid = 0xffff;
+ if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
+ sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
if (!sqp->qp.ibqp.qp_num)
ib_get_cached_pkey(&dev->ib_dev, sqp->port,
- sqp->pkey_index,
- &sqp->ud_header.bth.pkey);
+ sqp->pkey_index, &pkey);
else
ib_get_cached_pkey(&dev->ib_dev, sqp->port,
- wr->wr.ud.pkey_index,
- &sqp->ud_header.bth.pkey);
- cpu_to_be16s(&sqp->ud_header.bth.pkey);
+ wr->wr.ud.pkey_index, &pkey);
+ sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
@@ -1720,15 +1592,13 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- if (prev_wqe) {
- ((struct mthca_next_seg *) prev_wqe)->nda_op =
- cpu_to_be32(((ind << qp->sq.wqe_shift) +
- qp->send_wqe_offset) |
- mthca_opcode[wr->opcode]);
- wmb();
- ((struct mthca_next_seg *) prev_wqe)->ee_nds =
- cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
- }
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32(((ind << qp->sq.wqe_shift) +
+ qp->send_wqe_offset) |
+ mthca_opcode[wr->opcode]);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
if (!size0) {
size0 = size;
@@ -1742,7 +1612,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
qp->send_wqe_offset) | f0 | op0);
@@ -1825,13 +1695,11 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
qp->wrid[ind] = wr->wr_id;
- if (likely(prev_wqe)) {
- ((struct mthca_next_seg *) prev_wqe)->nda_op =
- cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
- wmb();
- ((struct mthca_next_seg *) prev_wqe)->ee_nds =
- cpu_to_be32(MTHCA_NEXT_DBD | size);
- }
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32(MTHCA_NEXT_DBD | size);
if (!size0)
size0 = size;
@@ -1843,7 +1711,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
@@ -2042,15 +1910,13 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- if (likely(prev_wqe)) {
- ((struct mthca_next_seg *) prev_wqe)->nda_op =
- cpu_to_be32(((ind << qp->sq.wqe_shift) +
- qp->send_wqe_offset) |
- mthca_opcode[wr->opcode]);
- wmb();
- ((struct mthca_next_seg *) prev_wqe)->ee_nds =
- cpu_to_be32(MTHCA_NEXT_DBD | size);
- }
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32(((ind << qp->sq.wqe_shift) +
+ qp->send_wqe_offset) |
+ mthca_opcode[wr->opcode]);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32(MTHCA_NEXT_DBD | size);
if (!size0) {
size0 = size;
@@ -2064,7 +1930,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
out:
if (likely(nreq)) {
- u32 doorbell[2];
+ __be32 doorbell[2];
doorbell[0] = cpu_to_be32((nreq << 24) |
((qp->sq.head & 0xffff) << 8) |
@@ -2174,19 +2040,25 @@ out:
}
int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
- int index, int *dbd, u32 *new_wqe)
+ int index, int *dbd, __be32 *new_wqe)
{
struct mthca_next_seg *next;
+ /*
+ * For SRQs, all WQEs generate a CQE, so we're always at the
+ * end of the doorbell chain.
+ */
+ if (qp->ibqp.srq) {
+ *new_wqe = 0;
+ return 0;
+ }
+
if (is_send)
next = get_send_wqe(qp, index);
else
next = get_recv_wqe(qp, index);
- if (mthca_is_memfree(dev))
- *dbd = 1;
- else
- *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
+ *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
if (next->ee_nds & cpu_to_be32(0x3f))
*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
(next->ee_nds & cpu_to_be32(0x3f));
@@ -2258,5 +2130,6 @@ void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev)
for (i = 0; i < 2; ++i)
mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+ mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
mthca_alloc_cleanup(&dev->qp_table.alloc);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 8ea801271a41..df5e494a9d38 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -37,6 +37,7 @@
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/slab.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
@@ -71,8 +72,8 @@ int mthca_reset(struct mthca_dev *mdev)
bridge)) != NULL) {
if (bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
bridge->subordinate == mdev->pdev->bus) {
- mthca_dbg(mdev, "Found bridge: %s (%s)\n",
- pci_pretty_name(bridge), pci_name(bridge));
+ mthca_dbg(mdev, "Found bridge: %s\n",
+ pci_name(bridge));
break;
}
}
@@ -83,8 +84,8 @@ int mthca_reset(struct mthca_dev *mdev)
* assume we're in no-bridge mode and hope for
* the best.
*/
- mthca_warn(mdev, "No bridge found for %s (%s)\n",
- pci_pretty_name(mdev->pdev), pci_name(mdev->pdev));
+ mthca_warn(mdev, "No bridge found for %s\n",
+ pci_name(mdev->pdev));
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
new file mode 100644
index 000000000000..292f55be8cbd
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, 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.
+ *
+ * - 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.
+ *
+ * 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.
+ *
+ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#include "mthca_dev.h"
+#include "mthca_cmd.h"
+#include "mthca_memfree.h"
+#include "mthca_wqe.h"
+
+enum {
+ MTHCA_MAX_DIRECT_SRQ_SIZE = 4 * PAGE_SIZE
+};
+
+struct mthca_tavor_srq_context {
+ __be64 wqe_base_ds; /* low 6 bits is descriptor size */
+ __be32 state_pd;
+ __be32 lkey;
+ __be32 uar;
+ __be32 wqe_cnt;
+ u32 reserved[2];
+};
+
+struct mthca_arbel_srq_context {
+ __be32 state_logsize_srqn;
+ __be32 lkey;
+ __be32 db_index;
+ __be32 logstride_usrpage;
+ __be64 wqe_base;
+ __be32 eq_pd;
+ __be16 limit_watermark;
+ __be16 wqe_cnt;
+ u16 reserved1;
+ __be16 wqe_counter;
+ u32 reserved2[3];
+};
+
+static void *get_wqe(struct mthca_srq *srq, int n)
+{
+ if (srq->is_direct)
+ return srq->queue.direct.buf + (n << srq->wqe_shift);
+ else
+ return srq->queue.page_list[(n << srq->wqe_shift) >> PAGE_SHIFT].buf +
+ ((n << srq->wqe_shift) & (PAGE_SIZE - 1));
+}
+
+/*
+ * Return a pointer to the location within a WQE that we're using as a
+ * link when the WQE is in the free list. We use the imm field
+ * because in the Tavor case, posting a WQE may overwrite the next
+ * segment of the previous WQE, but a receive WQE will never touch the
+ * imm field. This avoids corrupting our free list if the previous
+ * WQE has already completed and been put on the free list when we
+ * post the next WQE.
+ */
+static inline int *wqe_to_link(void *wqe)
+{
+ return (int *) (wqe + offsetof(struct mthca_next_seg, imm));
+}
+
+static void mthca_tavor_init_srq_context(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_srq *srq,
+ struct mthca_tavor_srq_context *context)
+{
+ memset(context, 0, sizeof *context);
+
+ context->wqe_base_ds = cpu_to_be64(1 << (srq->wqe_shift - 4));
+ context->state_pd = cpu_to_be32(pd->pd_num);
+ context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
+
+ if (pd->ibpd.uobject)
+ context->uar =
+ cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+ else
+ context->uar = cpu_to_be32(dev->driver_uar.index);
+}
+
+static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_srq *srq,
+ struct mthca_arbel_srq_context *context)
+{
+ int logsize;
+
+ memset(context, 0, sizeof *context);
+
+ logsize = long_log2(srq->max) + srq->wqe_shift;
+ context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
+ context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
+ context->db_index = cpu_to_be32(srq->db_index);
+ context->logstride_usrpage = cpu_to_be32((srq->wqe_shift - 4) << 29);
+ if (pd->ibpd.uobject)
+ context->logstride_usrpage |=
+ cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index);
+ else
+ context->logstride_usrpage |= cpu_to_be32(dev->driver_uar.index);
+ context->eq_pd = cpu_to_be32(MTHCA_EQ_ASYNC << 24 | pd->pd_num);
+}
+
+static void mthca_free_srq_buf(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+ mthca_buf_free(dev, srq->max << srq->wqe_shift, &srq->queue,
+ srq->is_direct, &srq->mr);
+ kfree(srq->wrid);
+}
+
+static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct mthca_srq *srq)
+{
+ struct mthca_data_seg *scatter;
+ void *wqe;
+ int err;
+ int i;
+
+ if (pd->ibpd.uobject)
+ return 0;
+
+ srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL);
+ if (!srq->wrid)
+ return -ENOMEM;
+
+ err = mthca_buf_alloc(dev, srq->max << srq->wqe_shift,
+ MTHCA_MAX_DIRECT_SRQ_SIZE,
+ &srq->queue, &srq->is_direct, pd, 1, &srq->mr);
+ if (err) {
+ kfree(srq->wrid);
+ return err;
+ }
+
+ /*
+ * Now initialize the SRQ buffer so that all of the WQEs are
+ * linked into the list of free WQEs. In addition, set the
+ * scatter list L_Keys to the sentry value of 0x100.
+ */
+ for (i = 0; i < srq->max; ++i) {
+ wqe = get_wqe(srq, i);
+
+ *wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
+
+ for (scatter = wqe + sizeof (struct mthca_next_seg);
+ (void *) scatter < wqe + (1 << srq->wqe_shift);
+ ++scatter)
+ scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ }
+
+ srq->last = get_wqe(srq, srq->max - 1);
+
+ return 0;
+}
+
+int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
+ struct ib_srq_attr *attr, struct mthca_srq *srq)
+{
+ struct mthca_mailbox *mailbox;
+ u8 status;
+ int ds;
+ int err;
+
+ /* Sanity check SRQ size before proceeding */
+ if (attr->max_wr > dev->limits.max_srq_wqes ||
+ attr->max_sge > dev->limits.max_sg)
+ return -EINVAL;
+
+ srq->max = attr->max_wr;
+ srq->max_gs = attr->max_sge;
+ srq->counter = 0;
+
+ if (mthca_is_memfree(dev))
+ srq->max = roundup_pow_of_two(srq->max + 1);
+
+ ds = min(64UL,
+ roundup_pow_of_two(sizeof (struct mthca_next_seg) +
+ srq->max_gs * sizeof (struct mthca_data_seg)));
+ srq->wqe_shift = long_log2(ds);
+
+ srq->srqn = mthca_alloc(&dev->srq_table.alloc);
+ if (srq->srqn == -1)
+ return -ENOMEM;
+
+ if (mthca_is_memfree(dev)) {
+ err = mthca_table_get(dev, dev->srq_table.table, srq->srqn);
+ if (err)
+ goto err_out;
+
+ if (!pd->ibpd.uobject) {
+ srq->db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SRQ,
+ srq->srqn, &srq->db);
+ if (srq->db_index < 0) {
+ err = -ENOMEM;
+ goto err_out_icm;
+ }
+ }
+ }
+
+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+ if (IS_ERR(mailbox)) {
+ err = PTR_ERR(mailbox);
+ goto err_out_db;
+ }
+
+ err = mthca_alloc_srq_buf(dev, pd, srq);
+ if (err)
+ goto err_out_mailbox;
+
+ spin_lock_init(&srq->lock);
+ atomic_set(&srq->refcount, 1);
+ init_waitqueue_head(&srq->wait);
+
+ if (mthca_is_memfree(dev))
+ mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
+ else
+ mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
+
+ err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+
+ if (err) {
+ mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
+ goto err_out_free_buf;
+ }
+ if (status) {
+ mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
+ status);
+ err = -EINVAL;
+ goto err_out_free_buf;
+ }
+
+ spin_lock_irq(&dev->srq_table.lock);
+ if (mthca_array_set(&dev->srq_table.srq,
+ srq->srqn & (dev->limits.num_srqs - 1),
+ srq)) {
+ spin_unlock_irq(&dev->srq_table.lock);
+ goto err_out_free_srq;
+ }
+ spin_unlock_irq(&dev->srq_table.lock);
+
+ mthca_free_mailbox(dev, mailbox);
+
+ srq->first_free = 0;
+ srq->last_free = srq->max - 1;
+
+ return 0;
+
+err_out_free_srq:
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ if (err)
+ mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+ else if (status)
+ mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+err_out_free_buf:
+ if (!pd->ibpd.uobject)
+ mthca_free_srq_buf(dev, srq);
+
+err_out_mailbox:
+ mthca_free_mailbox(dev, mailbox);
+
+err_out_db:
+ if (!pd->ibpd.uobject && mthca_is_memfree(dev))
+ mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+
+err_out_icm:
+ mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+
+err_out:
+ mthca_free(&dev->srq_table.alloc, srq->srqn);
+
+ return err;
+}
+
+void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+ struct mthca_mailbox *mailbox;
+ int err;
+ u8 status;
+
+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+ if (IS_ERR(mailbox)) {
+ mthca_warn(dev, "No memory for mailbox to free SRQ.\n");
+ return;
+ }
+
+ err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+ if (err)
+ mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
+ else if (status)
+ mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
+
+ spin_lock_irq(&dev->srq_table.lock);
+ mthca_array_clear(&dev->srq_table.srq,
+ srq->srqn & (dev->limits.num_srqs - 1));
+ spin_unlock_irq(&dev->srq_table.lock);
+
+ atomic_dec(&srq->refcount);
+ wait_event(srq->wait, !atomic_read(&srq->refcount));
+
+ if (!srq->ibsrq.uobject) {
+ mthca_free_srq_buf(dev, srq);
+ if (mthca_is_memfree(dev))
+ mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);
+ }
+
+ mthca_table_put(dev, dev->srq_table.table, srq->srqn);
+ mthca_free(&dev->srq_table.alloc, srq->srqn);
+ mthca_free_mailbox(dev, mailbox);
+}
+
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask)
+{
+ struct mthca_dev *dev = to_mdev(ibsrq->device);
+ struct mthca_srq *srq = to_msrq(ibsrq);
+ int ret;
+ u8 status;
+
+ /* We don't support resizing SRQs (yet?) */
+ if (attr_mask & IB_SRQ_MAX_WR)
+ return -EINVAL;
+
+ if (attr_mask & IB_SRQ_LIMIT) {
+ ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+ if (ret)
+ return ret;
+ if (status)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
+ enum ib_event_type event_type)
+{
+ struct mthca_srq *srq;
+ struct ib_event event;
+
+ spin_lock(&dev->srq_table.lock);
+ srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
+ if (srq)
+ atomic_inc(&srq->refcount);
+ spin_unlock(&dev->srq_table.lock);
+
+ if (!srq) {
+ mthca_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
+ return;
+ }
+
+ if (!srq->ibsrq.event_handler)
+ goto out;
+
+ event.device = &dev->ib_dev;
+ event.event = event_type;
+ event.element.srq = &srq->ibsrq;
+ srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
+
+out:
+ if (atomic_dec_and_test(&srq->refcount))
+ wake_up(&srq->wait);
+}
+
+/*
+ * This function must be called with IRQs disabled.
+ */
+void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr)
+{
+ int ind;
+
+ ind = wqe_addr >> srq->wqe_shift;
+
+ spin_lock(&srq->lock);
+
+ if (likely(srq->first_free >= 0))
+ *wqe_to_link(get_wqe(srq, srq->last_free)) = ind;
+ else
+ srq->first_free = ind;
+
+ *wqe_to_link(get_wqe(srq, ind)) = -1;
+ srq->last_free = ind;
+
+ spin_unlock(&srq->lock);
+}
+
+int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibsrq->device);
+ struct mthca_srq *srq = to_msrq(ibsrq);
+ unsigned long flags;
+ int err = 0;
+ int first_ind;
+ int ind;
+ int next_ind;
+ int nreq;
+ int i;
+ void *wqe;
+ void *prev_wqe;
+
+ spin_lock_irqsave(&srq->lock, flags);
+
+ first_ind = srq->first_free;
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ ind = srq->first_free;
+
+ if (ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+
+ wqe = get_wqe(srq, ind);
+ next_ind = *wqe_to_link(wqe);
+
+ if (next_ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+
+ prev_wqe = srq->last;
+ srq->last = wqe;
+
+ ((struct mthca_next_seg *) wqe)->nda_op = 0;
+ ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ /* flags field will always remain 0 */
+
+ wqe += sizeof (struct mthca_next_seg);
+
+ if (unlikely(wr->num_sge > srq->max_gs)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ srq->last = prev_wqe;
+ break;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ }
+
+ if (i < srq->max_gs) {
+ ((struct mthca_data_seg *) wqe)->byte_count = 0;
+ ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ ((struct mthca_data_seg *) wqe)->addr = 0;
+ }
+
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32((ind << srq->wqe_shift) | 1);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32(MTHCA_NEXT_DBD);
+
+ srq->wrid[ind] = wr->wr_id;
+ srq->first_free = next_ind;
+ }
+
+ if (likely(nreq)) {
+ __be32 doorbell[2];
+
+ doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+ doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq);
+
+ /*
+ * Make sure that descriptors are written before
+ * doorbell is rung.
+ */
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ }
+
+ spin_unlock_irqrestore(&srq->lock, flags);
+ return err;
+}
+
+int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibsrq->device);
+ struct mthca_srq *srq = to_msrq(ibsrq);
+ unsigned long flags;
+ int err = 0;
+ int ind;
+ int next_ind;
+ int nreq;
+ int i;
+ void *wqe;
+
+ spin_lock_irqsave(&srq->lock, flags);
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ ind = srq->first_free;
+
+ if (ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+
+ wqe = get_wqe(srq, ind);
+ next_ind = *wqe_to_link(wqe);
+
+ if (next_ind < 0) {
+ mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ break;
+ }
+
+ ((struct mthca_next_seg *) wqe)->nda_op =
+ cpu_to_be32((next_ind << srq->wqe_shift) | 1);
+ ((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ /* flags field will always remain 0 */
+
+ wqe += sizeof (struct mthca_next_seg);
+
+ if (unlikely(wr->num_sge > srq->max_gs)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ break;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ }
+
+ if (i < srq->max_gs) {
+ ((struct mthca_data_seg *) wqe)->byte_count = 0;
+ ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(MTHCA_INVAL_LKEY);
+ ((struct mthca_data_seg *) wqe)->addr = 0;
+ }
+
+ srq->wrid[ind] = wr->wr_id;
+ srq->first_free = next_ind;
+ }
+
+ if (likely(nreq)) {
+ srq->counter += nreq;
+
+ /*
+ * Make sure that descriptors are written before
+ * we write doorbell record.
+ */
+ wmb();
+ *srq->db = cpu_to_be32(srq->counter);
+ }
+
+ spin_unlock_irqrestore(&srq->lock, flags);
+ return err;
+}
+
+int __devinit mthca_init_srq_table(struct mthca_dev *dev)
+{
+ int err;
+
+ if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+ return 0;
+
+ spin_lock_init(&dev->srq_table.lock);
+
+ err = mthca_alloc_init(&dev->srq_table.alloc,
+ dev->limits.num_srqs,
+ dev->limits.num_srqs - 1,
+ dev->limits.reserved_srqs);
+ if (err)
+ return err;
+
+ err = mthca_array_init(&dev->srq_table.srq,
+ dev->limits.num_srqs);
+ if (err)
+ mthca_alloc_cleanup(&dev->srq_table.alloc);
+
+ return err;
+}
+
+void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev)
+{
+ if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
+ return;
+
+ mthca_array_cleanup(&dev->srq_table.srq, dev->limits.num_srqs);
+ mthca_alloc_cleanup(&dev->srq_table.alloc);
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_uar.c b/drivers/infiniband/hw/mthca/mthca_uar.c
index 1c8791ded6ff..8e9219842be4 100644
--- a/drivers/infiniband/hw/mthca/mthca_uar.c
+++ b/drivers/infiniband/hw/mthca/mthca_uar.c
@@ -32,6 +32,8 @@
* $Id$
*/
+#include <asm/page.h> /* PAGE_SHIFT */
+
#include "mthca_dev.h"
#include "mthca_memfree.h"
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h b/drivers/infiniband/hw/mthca/mthca_user.h
index 3024c1b4547d..bb015c6494c4 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -38,6 +38,12 @@
#include <linux/types.h>
/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define MTHCA_UVERBS_ABI_VERSION 1
+
+/*
* Make sure that all structs defined in this file remain laid out so
* that they pack the same way on 32-bit and 64-bit architectures (to
* avoid incompatibility between 32-bit userspace and 64-bit kernels).
@@ -69,6 +75,17 @@ struct mthca_create_cq_resp {
__u32 reserved;
};
+struct mthca_create_srq {
+ __u32 lkey;
+ __u32 db_index;
+ __u64 db_page;
+};
+
+struct mthca_create_srq_resp {
+ __u32 srqn;
+ __u32 reserved;
+};
+
struct mthca_create_qp {
__u32 lkey;
__u32 reserved;
diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
new file mode 100644
index 000000000000..1f4c0ff28f79
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, 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.
+ *
+ * - 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.
+ *
+ * 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.
+ *
+ * $Id: mthca_wqe.h 3047 2005-08-10 03:59:35Z roland $
+ */
+
+#ifndef MTHCA_WQE_H
+#define MTHCA_WQE_H
+
+#include <linux/types.h>
+
+enum {
+ MTHCA_NEXT_DBD = 1 << 7,
+ MTHCA_NEXT_FENCE = 1 << 6,
+ MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+ MTHCA_NEXT_EVENT_GEN = 1 << 2,
+ MTHCA_NEXT_SOLICIT = 1 << 1,
+
+ MTHCA_MLX_VL15 = 1 << 17,
+ MTHCA_MLX_SLR = 1 << 16
+};
+
+enum {
+ MTHCA_INVAL_LKEY = 0x100
+};
+
+struct mthca_next_seg {
+ __be32 nda_op; /* [31:6] next WQE [4:0] next opcode */
+ __be32 ee_nds; /* [31:8] next EE [7] DBD [6] F [5:0] next WQE size */
+ __be32 flags; /* [3] CQ [2] Event [1] Solicit */
+ __be32 imm; /* immediate data */
+};
+
+struct mthca_tavor_ud_seg {
+ u32 reserved1;
+ __be32 lkey;
+ __be64 av_addr;
+ u32 reserved2[4];
+ __be32 dqpn;
+ __be32 qkey;
+ u32 reserved3[2];
+};
+
+struct mthca_arbel_ud_seg {
+ __be32 av[8];
+ __be32 dqpn;
+ __be32 qkey;
+ u32 reserved[2];
+};
+
+struct mthca_bind_seg {
+ __be32 flags; /* [31] Atomic [30] rem write [29] rem read */
+ u32 reserved;
+ __be32 new_rkey;
+ __be32 lkey;
+ __be64 addr;
+ __be64 length;
+};
+
+struct mthca_raddr_seg {
+ __be64 raddr;
+ __be32 rkey;
+ u32 reserved;
+};
+
+struct mthca_atomic_seg {
+ __be64 swap_add;
+ __be64 compare;
+};
+
+struct mthca_data_seg {
+ __be32 byte_count;
+ __be32 lkey;
+ __be64 addr;
+};
+
+struct mthca_mlx_seg {
+ __be32 nda_op;
+ __be32 nds;
+ __be32 flags; /* [17] VL15 [16] SLR [14:12] static rate
+ [11:8] SL [3] C [2] E */
+ __be16 rlid;
+ __be16 vcrc;
+};
+
+#endif /* MTHCA_WQE_H */
diff --git a/drivers/infiniband/include/ib_cache.h b/drivers/infiniband/include/ib_cache.h
deleted file mode 100644
index 44ef6bb9b9df..000000000000
--- a/drivers/infiniband/include/ib_cache.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_cache.h 1349 2004-12-16 21:09:43Z roland $
- */
-
-#ifndef _IB_CACHE_H
-#define _IB_CACHE_H
-
-#include <ib_verbs.h>
-
-/**
- * ib_get_cached_gid - Returns a cached GID table entry
- * @device: The device to query.
- * @port_num: The port number of the device to query.
- * @index: The index into the cached GID table to query.
- * @gid: The GID value found at the specified index.
- *
- * ib_get_cached_gid() fetches the specified GID table entry stored in
- * the local software cache.
- */
-int ib_get_cached_gid(struct ib_device *device,
- u8 port_num,
- int index,
- union ib_gid *gid);
-
-/**
- * ib_find_cached_gid - Returns the port number and GID table index where
- * a specified GID value occurs.
- * @device: The device to query.
- * @gid: The GID value to search for.
- * @port_num: The port number of the device where the GID value was found.
- * @index: The index into the cached GID table where the GID was found. This
- * parameter may be NULL.
- *
- * ib_find_cached_gid() searches for the specified GID value in
- * the local software cache.
- */
-int ib_find_cached_gid(struct ib_device *device,
- union ib_gid *gid,
- u8 *port_num,
- u16 *index);
-
-/**
- * ib_get_cached_pkey - Returns a cached PKey table entry
- * @device: The device to query.
- * @port_num: The port number of the device to query.
- * @index: The index into the cached PKey table to query.
- * @pkey: The PKey value found at the specified index.
- *
- * ib_get_cached_pkey() fetches the specified PKey table entry stored in
- * the local software cache.
- */
-int ib_get_cached_pkey(struct ib_device *device_handle,
- u8 port_num,
- int index,
- u16 *pkey);
-
-/**
- * ib_find_cached_pkey - Returns the PKey table index where a specified
- * PKey value occurs.
- * @device: The device to query.
- * @port_num: The port number of the device to search for the PKey.
- * @pkey: The PKey value to search for.
- * @index: The index into the cached PKey table where the PKey was found.
- *
- * ib_find_cached_pkey() searches the specified PKey table in
- * the local software cache.
- */
-int ib_find_cached_pkey(struct ib_device *device,
- u8 port_num,
- u16 pkey,
- u16 *index);
-
-#endif /* _IB_CACHE_H */
diff --git a/drivers/infiniband/include/ib_cm.h b/drivers/infiniband/include/ib_cm.h
deleted file mode 100644
index e5d74a730a70..000000000000
--- a/drivers/infiniband/include/ib_cm.h
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_cm.h 2730 2005-06-28 16:43:03Z sean.hefty $
- */
-#if !defined(IB_CM_H)
-#define IB_CM_H
-
-#include <ib_mad.h>
-#include <ib_sa.h>
-
-enum ib_cm_state {
- IB_CM_IDLE,
- IB_CM_LISTEN,
- IB_CM_REQ_SENT,
- IB_CM_REQ_RCVD,
- IB_CM_MRA_REQ_SENT,
- IB_CM_MRA_REQ_RCVD,
- IB_CM_REP_SENT,
- IB_CM_REP_RCVD,
- IB_CM_MRA_REP_SENT,
- IB_CM_MRA_REP_RCVD,
- IB_CM_ESTABLISHED,
- IB_CM_DREQ_SENT,
- IB_CM_DREQ_RCVD,
- IB_CM_TIMEWAIT,
- IB_CM_SIDR_REQ_SENT,
- IB_CM_SIDR_REQ_RCVD
-};
-
-enum ib_cm_lap_state {
- IB_CM_LAP_IDLE,
- IB_CM_LAP_SENT,
- IB_CM_LAP_RCVD,
- IB_CM_MRA_LAP_SENT,
- IB_CM_MRA_LAP_RCVD,
-};
-
-enum ib_cm_event_type {
- IB_CM_REQ_ERROR,
- IB_CM_REQ_RECEIVED,
- IB_CM_REP_ERROR,
- IB_CM_REP_RECEIVED,
- IB_CM_RTU_RECEIVED,
- IB_CM_USER_ESTABLISHED,
- IB_CM_DREQ_ERROR,
- IB_CM_DREQ_RECEIVED,
- IB_CM_DREP_RECEIVED,
- IB_CM_TIMEWAIT_EXIT,
- IB_CM_MRA_RECEIVED,
- IB_CM_REJ_RECEIVED,
- IB_CM_LAP_ERROR,
- IB_CM_LAP_RECEIVED,
- IB_CM_APR_RECEIVED,
- IB_CM_SIDR_REQ_ERROR,
- IB_CM_SIDR_REQ_RECEIVED,
- IB_CM_SIDR_REP_RECEIVED
-};
-
-enum ib_cm_data_size {
- IB_CM_REQ_PRIVATE_DATA_SIZE = 92,
- IB_CM_MRA_PRIVATE_DATA_SIZE = 222,
- IB_CM_REJ_PRIVATE_DATA_SIZE = 148,
- IB_CM_REP_PRIVATE_DATA_SIZE = 196,
- IB_CM_RTU_PRIVATE_DATA_SIZE = 224,
- IB_CM_DREQ_PRIVATE_DATA_SIZE = 220,
- IB_CM_DREP_PRIVATE_DATA_SIZE = 224,
- IB_CM_REJ_ARI_LENGTH = 72,
- IB_CM_LAP_PRIVATE_DATA_SIZE = 168,
- IB_CM_APR_PRIVATE_DATA_SIZE = 148,
- IB_CM_APR_INFO_LENGTH = 72,
- IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
- IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
- IB_CM_SIDR_REP_INFO_LENGTH = 72
-};
-
-struct ib_cm_id;
-
-struct ib_cm_req_event_param {
- struct ib_cm_id *listen_id;
- struct ib_device *device;
- u8 port;
-
- struct ib_sa_path_rec *primary_path;
- struct ib_sa_path_rec *alternate_path;
-
- u64 remote_ca_guid;
- u32 remote_qkey;
- u32 remote_qpn;
- enum ib_qp_type qp_type;
-
- u32 starting_psn;
- u8 responder_resources;
- u8 initiator_depth;
- unsigned int local_cm_response_timeout:5;
- unsigned int flow_control:1;
- unsigned int remote_cm_response_timeout:5;
- unsigned int retry_count:3;
- unsigned int rnr_retry_count:3;
- unsigned int srq:1;
-};
-
-struct ib_cm_rep_event_param {
- u64 remote_ca_guid;
- u32 remote_qkey;
- u32 remote_qpn;
- u32 starting_psn;
- u8 responder_resources;
- u8 initiator_depth;
- unsigned int target_ack_delay:5;
- unsigned int failover_accepted:2;
- unsigned int flow_control:1;
- unsigned int rnr_retry_count:3;
- unsigned int srq:1;
-};
-
-enum ib_cm_rej_reason {
- IB_CM_REJ_NO_QP = __constant_htons(1),
- IB_CM_REJ_NO_EEC = __constant_htons(2),
- IB_CM_REJ_NO_RESOURCES = __constant_htons(3),
- IB_CM_REJ_TIMEOUT = __constant_htons(4),
- IB_CM_REJ_UNSUPPORTED = __constant_htons(5),
- IB_CM_REJ_INVALID_COMM_ID = __constant_htons(6),
- IB_CM_REJ_INVALID_COMM_INSTANCE = __constant_htons(7),
- IB_CM_REJ_INVALID_SERVICE_ID = __constant_htons(8),
- IB_CM_REJ_INVALID_TRANSPORT_TYPE = __constant_htons(9),
- IB_CM_REJ_STALE_CONN = __constant_htons(10),
- IB_CM_REJ_RDC_NOT_EXIST = __constant_htons(11),
- IB_CM_REJ_INVALID_GID = __constant_htons(12),
- IB_CM_REJ_INVALID_LID = __constant_htons(13),
- IB_CM_REJ_INVALID_SL = __constant_htons(14),
- IB_CM_REJ_INVALID_TRAFFIC_CLASS = __constant_htons(15),
- IB_CM_REJ_INVALID_HOP_LIMIT = __constant_htons(16),
- IB_CM_REJ_INVALID_PACKET_RATE = __constant_htons(17),
- IB_CM_REJ_INVALID_ALT_GID = __constant_htons(18),
- IB_CM_REJ_INVALID_ALT_LID = __constant_htons(19),
- IB_CM_REJ_INVALID_ALT_SL = __constant_htons(20),
- IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21),
- IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22),
- IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23),
- IB_CM_REJ_PORT_REDIRECT = __constant_htons(24),
- IB_CM_REJ_INVALID_MTU = __constant_htons(26),
- IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27),
- IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28),
- IB_CM_REJ_INVALID_RNR_RETRY = __constant_htons(29),
- IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID = __constant_htons(30),
- IB_CM_REJ_INVALID_CLASS_VERSION = __constant_htons(31),
- IB_CM_REJ_INVALID_FLOW_LABEL = __constant_htons(32),
- IB_CM_REJ_INVALID_ALT_FLOW_LABEL = __constant_htons(33)
-};
-
-struct ib_cm_rej_event_param {
- enum ib_cm_rej_reason reason;
- void *ari;
- u8 ari_length;
-};
-
-struct ib_cm_mra_event_param {
- u8 service_timeout;
-};
-
-struct ib_cm_lap_event_param {
- struct ib_sa_path_rec *alternate_path;
-};
-
-enum ib_cm_apr_status {
- IB_CM_APR_SUCCESS,
- IB_CM_APR_INVALID_COMM_ID,
- IB_CM_APR_UNSUPPORTED,
- IB_CM_APR_REJECT,
- IB_CM_APR_REDIRECT,
- IB_CM_APR_IS_CURRENT,
- IB_CM_APR_INVALID_QPN_EECN,
- IB_CM_APR_INVALID_LID,
- IB_CM_APR_INVALID_GID,
- IB_CM_APR_INVALID_FLOW_LABEL,
- IB_CM_APR_INVALID_TCLASS,
- IB_CM_APR_INVALID_HOP_LIMIT,
- IB_CM_APR_INVALID_PACKET_RATE,
- IB_CM_APR_INVALID_SL
-};
-
-struct ib_cm_apr_event_param {
- enum ib_cm_apr_status ap_status;
- void *apr_info;
- u8 info_len;
-};
-
-struct ib_cm_sidr_req_event_param {
- struct ib_cm_id *listen_id;
- struct ib_device *device;
- u8 port;
-
- u16 pkey;
-};
-
-enum ib_cm_sidr_status {
- IB_SIDR_SUCCESS,
- IB_SIDR_UNSUPPORTED,
- IB_SIDR_REJECT,
- IB_SIDR_NO_QP,
- IB_SIDR_REDIRECT,
- IB_SIDR_UNSUPPORTED_VERSION
-};
-
-struct ib_cm_sidr_rep_event_param {
- enum ib_cm_sidr_status status;
- u32 qkey;
- u32 qpn;
- void *info;
- u8 info_len;
-
-};
-
-struct ib_cm_event {
- enum ib_cm_event_type event;
- union {
- struct ib_cm_req_event_param req_rcvd;
- struct ib_cm_rep_event_param rep_rcvd;
- /* No data for RTU received events. */
- struct ib_cm_rej_event_param rej_rcvd;
- struct ib_cm_mra_event_param mra_rcvd;
- struct ib_cm_lap_event_param lap_rcvd;
- struct ib_cm_apr_event_param apr_rcvd;
- /* No data for DREQ/DREP received events. */
- struct ib_cm_sidr_req_event_param sidr_req_rcvd;
- struct ib_cm_sidr_rep_event_param sidr_rep_rcvd;
- enum ib_wc_status send_status;
- } param;
-
- void *private_data;
-};
-
-/**
- * ib_cm_handler - User-defined callback to process communication events.
- * @cm_id: Communication identifier associated with the reported event.
- * @event: Information about the communication event.
- *
- * IB_CM_REQ_RECEIVED and IB_CM_SIDR_REQ_RECEIVED communication events
- * generated as a result of listen requests result in the allocation of a
- * new @cm_id. The new @cm_id is returned to the user through this callback.
- * Clients are responsible for destroying the new @cm_id. For peer-to-peer
- * IB_CM_REQ_RECEIVED and all other events, the returned @cm_id corresponds
- * to a user's existing communication identifier.
- *
- * Users may not call ib_destroy_cm_id while in the context of this callback;
- * however, returning a non-zero value instructs the communication manager to
- * destroy the @cm_id after the callback completes.
- */
-typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
- struct ib_cm_event *event);
-
-struct ib_cm_id {
- ib_cm_handler cm_handler;
- void *context;
- u64 service_id;
- u64 service_mask;
- enum ib_cm_state state; /* internal CM/debug use */
- enum ib_cm_lap_state lap_state; /* internal CM/debug use */
- u32 local_id;
- u32 remote_id;
-};
-
-/**
- * ib_create_cm_id - Allocate a communication identifier.
- * @cm_handler: Callback invoked to notify the user of CM events.
- * @context: User specified context associated with the communication
- * identifier.
- *
- * Communication identifiers are used to track connection states, service
- * ID resolution requests, and listen requests.
- */
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
- void *context);
-
-/**
- * ib_destroy_cm_id - Destroy a connection identifier.
- * @cm_id: Connection identifier to destroy.
- *
- * This call blocks until the connection identifier is destroyed.
- */
-void ib_destroy_cm_id(struct ib_cm_id *cm_id);
-
-#define IB_SERVICE_ID_AGN_MASK __constant_cpu_to_be64(0xFF00000000000000ULL)
-#define IB_CM_ASSIGN_SERVICE_ID __constant_cpu_to_be64(0x0200000000000000ULL)
-
-/**
- * ib_cm_listen - Initiates listening on the specified service ID for
- * connection and service ID resolution requests.
- * @cm_id: Connection identifier associated with the listen request.
- * @service_id: Service identifier matched against incoming connection
- * and service ID resolution requests. The service ID should be specified
- * network-byte order. If set to IB_CM_ASSIGN_SERVICE_ID, the CM will
- * assign a service ID to the caller.
- * @service_mask: Mask applied to service ID used to listen across a
- * range of service IDs. If set to 0, the service ID is matched
- * exactly. This parameter is ignored if %service_id is set to
- * IB_CM_ASSIGN_SERVICE_ID.
- */
-int ib_cm_listen(struct ib_cm_id *cm_id,
- u64 service_id,
- u64 service_mask);
-
-struct ib_cm_req_param {
- struct ib_sa_path_rec *primary_path;
- struct ib_sa_path_rec *alternate_path;
- u64 service_id;
- u32 qp_num;
- enum ib_qp_type qp_type;
- u32 starting_psn;
- const void *private_data;
- u8 private_data_len;
- u8 peer_to_peer;
- u8 responder_resources;
- u8 initiator_depth;
- u8 remote_cm_response_timeout;
- u8 flow_control;
- u8 local_cm_response_timeout;
- u8 retry_count;
- u8 rnr_retry_count;
- u8 max_cm_retries;
- u8 srq;
-};
-
-/**
- * ib_send_cm_req - Sends a connection request to the remote node.
- * @cm_id: Connection identifier that will be associated with the
- * connection request.
- * @param: Connection request information needed to establish the
- * connection.
- */
-int ib_send_cm_req(struct ib_cm_id *cm_id,
- struct ib_cm_req_param *param);
-
-struct ib_cm_rep_param {
- u32 qp_num;
- u32 starting_psn;
- const void *private_data;
- u8 private_data_len;
- u8 responder_resources;
- u8 initiator_depth;
- u8 target_ack_delay;
- u8 failover_accepted;
- u8 flow_control;
- u8 rnr_retry_count;
- u8 srq;
-};
-
-/**
- * ib_send_cm_rep - Sends a connection reply in response to a connection
- * request.
- * @cm_id: Connection identifier that will be associated with the
- * connection request.
- * @param: Connection reply information needed to establish the
- * connection.
- */
-int ib_send_cm_rep(struct ib_cm_id *cm_id,
- struct ib_cm_rep_param *param);
-
-/**
- * ib_send_cm_rtu - Sends a connection ready to use message in response
- * to a connection reply message.
- * @cm_id: Connection identifier associated with the connection request.
- * @private_data: Optional user-defined private data sent with the
- * ready to use message.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_rtu(struct ib_cm_id *cm_id,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_send_cm_dreq - Sends a disconnection request for an existing
- * connection.
- * @cm_id: Connection identifier associated with the connection being
- * released.
- * @private_data: Optional user-defined private data sent with the
- * disconnection request message.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_dreq(struct ib_cm_id *cm_id,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_send_cm_drep - Sends a disconnection reply to a disconnection request.
- * @cm_id: Connection identifier associated with the connection being
- * released.
- * @private_data: Optional user-defined private data sent with the
- * disconnection reply message.
- * @private_data_len: Size of the private data buffer, in bytes.
- *
- * If the cm_id is in the correct state, the CM will transition the connection
- * to the timewait state, even if an error occurs sending the DREP message.
- */
-int ib_send_cm_drep(struct ib_cm_id *cm_id,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_cm_establish - Forces a connection state to established.
- * @cm_id: Connection identifier to transition to established.
- *
- * This routine should be invoked by users who receive messages on a
- * connected QP before an RTU has been received.
- */
-int ib_cm_establish(struct ib_cm_id *cm_id);
-
-/**
- * ib_send_cm_rej - Sends a connection rejection message to the
- * remote node.
- * @cm_id: Connection identifier associated with the connection being
- * rejected.
- * @reason: Reason for the connection request rejection.
- * @ari: Optional additional rejection information.
- * @ari_length: Size of the additional rejection information, in bytes.
- * @private_data: Optional user-defined private data sent with the
- * rejection message.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_rej(struct ib_cm_id *cm_id,
- enum ib_cm_rej_reason reason,
- void *ari,
- u8 ari_length,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_send_cm_mra - Sends a message receipt acknowledgement to a connection
- * message.
- * @cm_id: Connection identifier associated with the connection message.
- * @service_timeout: The maximum time required for the sender to reply to
- * to the connection message.
- * @private_data: Optional user-defined private data sent with the
- * message receipt acknowledgement.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_mra(struct ib_cm_id *cm_id,
- u8 service_timeout,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_send_cm_lap - Sends a load alternate path request.
- * @cm_id: Connection identifier associated with the load alternate path
- * message.
- * @alternate_path: A path record that identifies the alternate path to
- * load.
- * @private_data: Optional user-defined private data sent with the
- * load alternate path message.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_lap(struct ib_cm_id *cm_id,
- struct ib_sa_path_rec *alternate_path,
- const void *private_data,
- u8 private_data_len);
-
-/**
- * ib_cm_init_qp_attr - Initializes the QP attributes for use in transitioning
- * to a specified QP state.
- * @cm_id: Communication identifier associated with the QP attributes to
- * initialize.
- * @qp_attr: On input, specifies the desired QP state. On output, the
- * mandatory and desired optional attributes will be set in order to
- * modify the QP to the specified state.
- * @qp_attr_mask: The QP attribute mask that may be used to transition the
- * QP to the specified state.
- *
- * Users must set the @qp_attr->qp_state to the desired QP state. This call
- * will set all required attributes for the given transition, along with
- * known optional attributes. Users may override the attributes returned from
- * this call before calling ib_modify_qp.
- */
-int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
- struct ib_qp_attr *qp_attr,
- int *qp_attr_mask);
-
-/**
- * ib_send_cm_apr - Sends an alternate path response message in response to
- * a load alternate path request.
- * @cm_id: Connection identifier associated with the alternate path response.
- * @status: Reply status sent with the alternate path response.
- * @info: Optional additional information sent with the alternate path
- * response.
- * @info_length: Size of the additional information, in bytes.
- * @private_data: Optional user-defined private data sent with the
- * alternate path response message.
- * @private_data_len: Size of the private data buffer, in bytes.
- */
-int ib_send_cm_apr(struct ib_cm_id *cm_id,
- enum ib_cm_apr_status status,
- void *info,
- u8 info_length,
- const void *private_data,
- u8 private_data_len);
-
-struct ib_cm_sidr_req_param {
- struct ib_sa_path_rec *path;
- u64 service_id;
- int timeout_ms;
- const void *private_data;
- u8 private_data_len;
- u8 max_cm_retries;
- u16 pkey;
-};
-
-/**
- * ib_send_cm_sidr_req - Sends a service ID resolution request to the
- * remote node.
- * @cm_id: Communication identifier that will be associated with the
- * service ID resolution request.
- * @param: Service ID resolution request information.
- */
-int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
- struct ib_cm_sidr_req_param *param);
-
-struct ib_cm_sidr_rep_param {
- u32 qp_num;
- u32 qkey;
- enum ib_cm_sidr_status status;
- const void *info;
- u8 info_length;
- const void *private_data;
- u8 private_data_len;
-};
-
-/**
- * ib_send_cm_sidr_rep - Sends a service ID resolution request to the
- * remote node.
- * @cm_id: Communication identifier associated with the received service ID
- * resolution request.
- * @param: Service ID resolution reply information.
- */
-int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
- struct ib_cm_sidr_rep_param *param);
-
-#endif /* IB_CM_H */
diff --git a/drivers/infiniband/include/ib_fmr_pool.h b/drivers/infiniband/include/ib_fmr_pool.h
deleted file mode 100644
index 6c9e24d6e144..000000000000
--- a/drivers/infiniband/include/ib_fmr_pool.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_fmr_pool.h 2730 2005-06-28 16:43:03Z sean.hefty $
- */
-
-#if !defined(IB_FMR_POOL_H)
-#define IB_FMR_POOL_H
-
-#include <ib_verbs.h>
-
-struct ib_fmr_pool;
-
-/**
- * struct ib_fmr_pool_param - Parameters for creating FMR pool
- * @max_pages_per_fmr:Maximum number of pages per map request.
- * @access:Access flags for FMRs in pool.
- * @pool_size:Number of FMRs to allocate for pool.
- * @dirty_watermark:Flush is triggered when @dirty_watermark dirty
- * FMRs are present.
- * @flush_function:Callback called when unmapped FMRs are flushed and
- * more FMRs are possibly available for mapping
- * @flush_arg:Context passed to user's flush function.
- * @cache:If set, FMRs may be reused after unmapping for identical map
- * requests.
- */
-struct ib_fmr_pool_param {
- int max_pages_per_fmr;
- enum ib_access_flags access;
- int pool_size;
- int dirty_watermark;
- void (*flush_function)(struct ib_fmr_pool *pool,
- void * arg);
- void *flush_arg;
- unsigned cache:1;
-};
-
-struct ib_pool_fmr {
- struct ib_fmr *fmr;
- struct ib_fmr_pool *pool;
- struct list_head list;
- struct hlist_node cache_node;
- int ref_count;
- int remap_count;
- u64 io_virtual_address;
- int page_list_len;
- u64 page_list[0];
-};
-
-struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
- struct ib_fmr_pool_param *params);
-
-void ib_destroy_fmr_pool(struct ib_fmr_pool *pool);
-
-int ib_flush_fmr_pool(struct ib_fmr_pool *pool);
-
-struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle,
- u64 *page_list,
- int list_len,
- u64 *io_virtual_address);
-
-int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr);
-
-#endif /* IB_FMR_POOL_H */
diff --git a/drivers/infiniband/include/ib_mad.h b/drivers/infiniband/include/ib_mad.h
deleted file mode 100644
index 491b6f25b3b8..000000000000
--- a/drivers/infiniband/include/ib_mad.h
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_mad.h 2775 2005-07-02 13:42:12Z halr $
- */
-
-#if !defined( IB_MAD_H )
-#define IB_MAD_H
-
-#include <linux/pci.h>
-
-#include <ib_verbs.h>
-
-/* Management base version */
-#define IB_MGMT_BASE_VERSION 1
-
-/* Management classes */
-#define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01
-#define IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 0x81
-#define IB_MGMT_CLASS_SUBN_ADM 0x03
-#define IB_MGMT_CLASS_PERF_MGMT 0x04
-#define IB_MGMT_CLASS_BM 0x05
-#define IB_MGMT_CLASS_DEVICE_MGMT 0x06
-#define IB_MGMT_CLASS_CM 0x07
-#define IB_MGMT_CLASS_SNMP 0x08
-#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
-#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F
-
-#define IB_OPENIB_OUI (0x001405)
-
-/* Management methods */
-#define IB_MGMT_METHOD_GET 0x01
-#define IB_MGMT_METHOD_SET 0x02
-#define IB_MGMT_METHOD_GET_RESP 0x81
-#define IB_MGMT_METHOD_SEND 0x03
-#define IB_MGMT_METHOD_TRAP 0x05
-#define IB_MGMT_METHOD_REPORT 0x06
-#define IB_MGMT_METHOD_REPORT_RESP 0x86
-#define IB_MGMT_METHOD_TRAP_REPRESS 0x07
-
-#define IB_MGMT_METHOD_RESP 0x80
-
-#define IB_MGMT_MAX_METHODS 128
-
-/* RMPP information */
-#define IB_MGMT_RMPP_VERSION 1
-
-#define IB_MGMT_RMPP_TYPE_DATA 1
-#define IB_MGMT_RMPP_TYPE_ACK 2
-#define IB_MGMT_RMPP_TYPE_STOP 3
-#define IB_MGMT_RMPP_TYPE_ABORT 4
-
-#define IB_MGMT_RMPP_FLAG_ACTIVE 1
-#define IB_MGMT_RMPP_FLAG_FIRST (1<<1)
-#define IB_MGMT_RMPP_FLAG_LAST (1<<2)
-
-#define IB_MGMT_RMPP_NO_RESPTIME 0x1F
-
-#define IB_MGMT_RMPP_STATUS_SUCCESS 0
-#define IB_MGMT_RMPP_STATUS_RESX 1
-#define IB_MGMT_RMPP_STATUS_T2L 118
-#define IB_MGMT_RMPP_STATUS_BAD_LEN 119
-#define IB_MGMT_RMPP_STATUS_BAD_SEG 120
-#define IB_MGMT_RMPP_STATUS_BADT 121
-#define IB_MGMT_RMPP_STATUS_W2S 122
-#define IB_MGMT_RMPP_STATUS_S2B 123
-#define IB_MGMT_RMPP_STATUS_BAD_STATUS 124
-#define IB_MGMT_RMPP_STATUS_UNV 125
-#define IB_MGMT_RMPP_STATUS_TMR 126
-#define IB_MGMT_RMPP_STATUS_UNSPEC 127
-
-#define IB_QP0 0
-#define IB_QP1 __constant_htonl(1)
-#define IB_QP1_QKEY 0x80010000
-#define IB_QP_SET_QKEY 0x80000000
-
-struct ib_mad_hdr {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- u16 status;
- u16 class_specific;
- u64 tid;
- u16 attr_id;
- u16 resv;
- u32 attr_mod;
-};
-
-struct ib_rmpp_hdr {
- u8 rmpp_version;
- u8 rmpp_type;
- u8 rmpp_rtime_flags;
- u8 rmpp_status;
- u32 seg_num;
- u32 paylen_newwin;
-};
-
-typedef u64 __bitwise ib_sa_comp_mask;
-
-#define IB_SA_COMP_MASK(n) ((__force ib_sa_comp_mask) cpu_to_be64(1ull << n))
-
-/*
- * ib_sa_hdr and ib_sa_mad structures must be packed because they have
- * 64-bit fields that are only 32-bit aligned. 64-bit architectures will
- * lay them out wrong otherwise. (And unfortunately they are sent on
- * the wire so we can't change the layout)
- */
-struct ib_sa_hdr {
- u64 sm_key;
- u16 attr_offset;
- u16 reserved;
- ib_sa_comp_mask comp_mask;
-} __attribute__ ((packed));
-
-struct ib_mad {
- struct ib_mad_hdr mad_hdr;
- u8 data[232];
-};
-
-struct ib_rmpp_mad {
- struct ib_mad_hdr mad_hdr;
- struct ib_rmpp_hdr rmpp_hdr;
- u8 data[220];
-};
-
-struct ib_sa_mad {
- struct ib_mad_hdr mad_hdr;
- struct ib_rmpp_hdr rmpp_hdr;
- struct ib_sa_hdr sa_hdr;
- u8 data[200];
-} __attribute__ ((packed));
-
-struct ib_vendor_mad {
- struct ib_mad_hdr mad_hdr;
- struct ib_rmpp_hdr rmpp_hdr;
- u8 reserved;
- u8 oui[3];
- u8 data[216];
-};
-
-/**
- * ib_mad_send_buf - MAD data buffer and work request for sends.
- * @mad: References an allocated MAD data buffer. The size of the data
- * buffer is specified in the @send_wr.length field.
- * @mapping: DMA mapping information.
- * @mad_agent: MAD agent that allocated the buffer.
- * @context: User-controlled context fields.
- * @send_wr: An initialized work request structure used when sending the MAD.
- * The wr_id field of the work request is initialized to reference this
- * data structure.
- * @sge: A scatter-gather list referenced by the work request.
- *
- * Users are responsible for initializing the MAD buffer itself, with the
- * exception of specifying the payload length field in any RMPP MAD.
- */
-struct ib_mad_send_buf {
- struct ib_mad *mad;
- DECLARE_PCI_UNMAP_ADDR(mapping)
- struct ib_mad_agent *mad_agent;
- void *context[2];
- struct ib_send_wr send_wr;
- struct ib_sge sge;
-};
-
-/**
- * ib_get_rmpp_resptime - Returns the RMPP response time.
- * @rmpp_hdr: An RMPP header.
- */
-static inline u8 ib_get_rmpp_resptime(struct ib_rmpp_hdr *rmpp_hdr)
-{
- return rmpp_hdr->rmpp_rtime_flags >> 3;
-}
-
-/**
- * ib_get_rmpp_flags - Returns the RMPP flags.
- * @rmpp_hdr: An RMPP header.
- */
-static inline u8 ib_get_rmpp_flags(struct ib_rmpp_hdr *rmpp_hdr)
-{
- return rmpp_hdr->rmpp_rtime_flags & 0x7;
-}
-
-/**
- * ib_set_rmpp_resptime - Sets the response time in an RMPP header.
- * @rmpp_hdr: An RMPP header.
- * @rtime: The response time to set.
- */
-static inline void ib_set_rmpp_resptime(struct ib_rmpp_hdr *rmpp_hdr, u8 rtime)
-{
- rmpp_hdr->rmpp_rtime_flags = ib_get_rmpp_flags(rmpp_hdr) | (rtime << 3);
-}
-
-/**
- * ib_set_rmpp_flags - Sets the flags in an RMPP header.
- * @rmpp_hdr: An RMPP header.
- * @flags: The flags to set.
- */
-static inline void ib_set_rmpp_flags(struct ib_rmpp_hdr *rmpp_hdr, u8 flags)
-{
- rmpp_hdr->rmpp_rtime_flags = (rmpp_hdr->rmpp_rtime_flags & 0xF1) |
- (flags & 0x7);
-}
-
-struct ib_mad_agent;
-struct ib_mad_send_wc;
-struct ib_mad_recv_wc;
-
-/**
- * ib_mad_send_handler - callback handler for a sent MAD.
- * @mad_agent: MAD agent that sent the MAD.
- * @mad_send_wc: Send work completion information on the sent MAD.
- */
-typedef void (*ib_mad_send_handler)(struct ib_mad_agent *mad_agent,
- struct ib_mad_send_wc *mad_send_wc);
-
-/**
- * ib_mad_snoop_handler - Callback handler for snooping sent MADs.
- * @mad_agent: MAD agent that snooped the MAD.
- * @send_wr: Work request information on the sent MAD.
- * @mad_send_wc: Work completion information on the sent MAD. Valid
- * only for snooping that occurs on a send completion.
- *
- * Clients snooping MADs should not modify data referenced by the @send_wr
- * or @mad_send_wc.
- */
-typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent,
- struct ib_send_wr *send_wr,
- struct ib_mad_send_wc *mad_send_wc);
-
-/**
- * ib_mad_recv_handler - callback handler for a received MAD.
- * @mad_agent: MAD agent requesting the received MAD.
- * @mad_recv_wc: Received work completion information on the received MAD.
- *
- * MADs received in response to a send request operation will be handed to
- * the user after the send operation completes. All data buffers given
- * to registered agents through this routine are owned by the receiving
- * client, except for snooping agents. Clients snooping MADs should not
- * modify the data referenced by @mad_recv_wc.
- */
-typedef void (*ib_mad_recv_handler)(struct ib_mad_agent *mad_agent,
- struct ib_mad_recv_wc *mad_recv_wc);
-
-/**
- * ib_mad_agent - Used to track MAD registration with the access layer.
- * @device: Reference to device registration is on.
- * @qp: Reference to QP used for sending and receiving MADs.
- * @mr: Memory region for system memory usable for DMA.
- * @recv_handler: Callback handler for a received MAD.
- * @send_handler: Callback handler for a sent MAD.
- * @snoop_handler: Callback handler for snooped sent MADs.
- * @context: User-specified context associated with this registration.
- * @hi_tid: Access layer assigned transaction ID for this client.
- * Unsolicited MADs sent by this client will have the upper 32-bits
- * of their TID set to this value.
- * @port_num: Port number on which QP is registered
- * @rmpp_version: If set, indicates the RMPP version used by this agent.
- */
-struct ib_mad_agent {
- struct ib_device *device;
- struct ib_qp *qp;
- struct ib_mr *mr;
- ib_mad_recv_handler recv_handler;
- ib_mad_send_handler send_handler;
- ib_mad_snoop_handler snoop_handler;
- void *context;
- u32 hi_tid;
- u8 port_num;
- u8 rmpp_version;
-};
-
-/**
- * ib_mad_send_wc - MAD send completion information.
- * @wr_id: Work request identifier associated with the send MAD request.
- * @status: Completion status.
- * @vendor_err: Optional vendor error information returned with a failed
- * request.
- */
-struct ib_mad_send_wc {
- u64 wr_id;
- enum ib_wc_status status;
- u32 vendor_err;
-};
-
-/**
- * ib_mad_recv_buf - received MAD buffer information.
- * @list: Reference to next data buffer for a received RMPP MAD.
- * @grh: References a data buffer containing the global route header.
- * The data refereced by this buffer is only valid if the GRH is
- * valid.
- * @mad: References the start of the received MAD.
- */
-struct ib_mad_recv_buf {
- struct list_head list;
- struct ib_grh *grh;
- struct ib_mad *mad;
-};
-
-/**
- * ib_mad_recv_wc - received MAD information.
- * @wc: Completion information for the received data.
- * @recv_buf: Specifies the location of the received data buffer(s).
- * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
- * @mad_len: The length of the received MAD, without duplicated headers.
- *
- * For received response, the wr_id field of the wc is set to the wr_id
- * for the corresponding send request.
- */
-struct ib_mad_recv_wc {
- struct ib_wc *wc;
- struct ib_mad_recv_buf recv_buf;
- struct list_head rmpp_list;
- int mad_len;
-};
-
-/**
- * ib_mad_reg_req - MAD registration request
- * @mgmt_class: Indicates which management class of MADs should be receive
- * by the caller. This field is only required if the user wishes to
- * receive unsolicited MADs, otherwise it should be 0.
- * @mgmt_class_version: Indicates which version of MADs for the given
- * management class to receive.
- * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
- * in the range from 0x30 to 0x4f. Otherwise not used.
- * @method_mask: The caller will receive unsolicited MADs for any method
- * where @method_mask = 1.
- */
-struct ib_mad_reg_req {
- u8 mgmt_class;
- u8 mgmt_class_version;
- u8 oui[3];
- DECLARE_BITMAP(method_mask, IB_MGMT_MAX_METHODS);
-};
-
-/**
- * ib_register_mad_agent - Register to send/receive MADs.
- * @device: The device to register with.
- * @port_num: The port on the specified device to use.
- * @qp_type: Specifies which QP to access. Must be either
- * IB_QPT_SMI or IB_QPT_GSI.
- * @mad_reg_req: Specifies which unsolicited MADs should be received
- * by the caller. This parameter may be NULL if the caller only
- * wishes to receive solicited responses.
- * @rmpp_version: If set, indicates that the client will send
- * and receive MADs that contain the RMPP header for the given version.
- * If set to 0, indicates that RMPP is not used by this client.
- * @send_handler: The completion callback routine invoked after a send
- * request has completed.
- * @recv_handler: The completion callback routine invoked for a received
- * MAD.
- * @context: User specified context associated with the registration.
- */
-struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
- u8 port_num,
- enum ib_qp_type qp_type,
- struct ib_mad_reg_req *mad_reg_req,
- u8 rmpp_version,
- ib_mad_send_handler send_handler,
- ib_mad_recv_handler recv_handler,
- void *context);
-
-enum ib_mad_snoop_flags {
- /*IB_MAD_SNOOP_POSTED_SENDS = 1,*/
- /*IB_MAD_SNOOP_RMPP_SENDS = (1<<1),*/
- IB_MAD_SNOOP_SEND_COMPLETIONS = (1<<2),
- /*IB_MAD_SNOOP_RMPP_SEND_COMPLETIONS = (1<<3),*/
- IB_MAD_SNOOP_RECVS = (1<<4)
- /*IB_MAD_SNOOP_RMPP_RECVS = (1<<5),*/
- /*IB_MAD_SNOOP_REDIRECTED_QPS = (1<<6)*/
-};
-
-/**
- * ib_register_mad_snoop - Register to snoop sent and received MADs.
- * @device: The device to register with.
- * @port_num: The port on the specified device to use.
- * @qp_type: Specifies which QP traffic to snoop. Must be either
- * IB_QPT_SMI or IB_QPT_GSI.
- * @mad_snoop_flags: Specifies information where snooping occurs.
- * @send_handler: The callback routine invoked for a snooped send.
- * @recv_handler: The callback routine invoked for a snooped receive.
- * @context: User specified context associated with the registration.
- */
-struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
- u8 port_num,
- enum ib_qp_type qp_type,
- int mad_snoop_flags,
- ib_mad_snoop_handler snoop_handler,
- ib_mad_recv_handler recv_handler,
- void *context);
-
-/**
- * ib_unregister_mad_agent - Unregisters a client from using MAD services.
- * @mad_agent: Corresponding MAD registration request to deregister.
- *
- * After invoking this routine, MAD services are no longer usable by the
- * client on the associated QP.
- */
-int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
-
-/**
- * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
- * with the registered client.
- * @mad_agent: Specifies the associated registration to post the send to.
- * @send_wr: Specifies the information needed to send the MAD(s).
- * @bad_send_wr: Specifies the MAD on which an error was encountered.
- *
- * Sent MADs are not guaranteed to complete in the order that they were posted.
- *
- * If the MAD requires RMPP, the data buffer should contain a single copy
- * of the common MAD, RMPP, and class specific headers, followed by the class
- * defined data. If the class defined data would not divide evenly into
- * RMPP segments, then space must be allocated at the end of the referenced
- * buffer for any required padding. To indicate the amount of class defined
- * data being transferred, the paylen_newwin field in the RMPP header should
- * be set to the size of the class specific header plus the amount of class
- * defined data being transferred. The paylen_newwin field should be
- * specified in network-byte order.
- */
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
- struct ib_send_wr *send_wr,
- struct ib_send_wr **bad_send_wr);
-
-/**
- * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer.
- * @mad_recv_wc: Work completion information for a received MAD.
- * @buf: User-provided data buffer to receive the coalesced buffers. The
- * referenced buffer should be at least the size of the mad_len specified
- * by @mad_recv_wc.
- *
- * This call copies a chain of received MAD segments into a single data buffer,
- * removing duplicated headers.
- */
-void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf);
-
-/**
- * ib_free_recv_mad - Returns data buffers used to receive a MAD.
- * @mad_recv_wc: Work completion information for a received MAD.
- *
- * Clients receiving MADs through their ib_mad_recv_handler must call this
- * routine to return the work completion buffers to the access layer.
- */
-void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc);
-
-/**
- * ib_cancel_mad - Cancels an outstanding send MAD operation.
- * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to cancel.
- *
- * MADs will be returned to the user through the corresponding
- * ib_mad_send_handler.
- */
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id);
-
-/**
- * ib_modify_mad - Modifies an outstanding send MAD operation.
- * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to modify.
- * @timeout_ms: New timeout value for sent MAD.
- *
- * This call will reset the timeout value for a sent MAD to the specified
- * value.
- */
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms);
-
-/**
- * ib_redirect_mad_qp - Registers a QP for MAD services.
- * @qp: Reference to a QP that requires MAD services.
- * @rmpp_version: If set, indicates that the client will send
- * and receive MADs that contain the RMPP header for the given version.
- * If set to 0, indicates that RMPP is not used by this client.
- * @send_handler: The completion callback routine invoked after a send
- * request has completed.
- * @recv_handler: The completion callback routine invoked for a received
- * MAD.
- * @context: User specified context associated with the registration.
- *
- * Use of this call allows clients to use MAD services, such as RMPP,
- * on user-owned QPs. After calling this routine, users may send
- * MADs on the specified QP by calling ib_mad_post_send.
- */
-struct ib_mad_agent *ib_redirect_mad_qp(struct ib_qp *qp,
- u8 rmpp_version,
- ib_mad_send_handler send_handler,
- ib_mad_recv_handler recv_handler,
- void *context);
-
-/**
- * ib_process_mad_wc - Processes a work completion associated with a
- * MAD sent or received on a redirected QP.
- * @mad_agent: Specifies the registered MAD service using the redirected QP.
- * @wc: References a work completion associated with a sent or received
- * MAD segment.
- *
- * This routine is used to complete or continue processing on a MAD request.
- * If the work completion is associated with a send operation, calling
- * this routine is required to continue an RMPP transfer or to wait for a
- * corresponding response, if it is a request. If the work completion is
- * associated with a receive operation, calling this routine is required to
- * process an inbound or outbound RMPP transfer, or to match a response MAD
- * with its corresponding request.
- */
-int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
- struct ib_wc *wc);
-
-/**
- * ib_create_send_mad - Allocate and initialize a data buffer and work request
- * for sending a MAD.
- * @mad_agent: Specifies the registered MAD service to associate with the MAD.
- * @remote_qpn: Specifies the QPN of the receiving node.
- * @pkey_index: Specifies which PKey the MAD will be sent using. This field
- * is valid only if the remote_qpn is QP 1.
- * @ah: References the address handle used to transfer to the remote node.
- * @rmpp_active: Indicates if the send will enable RMPP.
- * @hdr_len: Indicates the size of the data header of the MAD. This length
- * should include the common MAD header, RMPP header, plus any class
- * specific header.
- * @data_len: Indicates the size of any user-transferred data. The call will
- * automatically adjust the allocated buffer size to account for any
- * additional padding that may be necessary.
- * @gfp_mask: GFP mask used for the memory allocation.
- *
- * This is a helper routine that may be used to allocate a MAD. Users are
- * not required to allocate outbound MADs using this call. The returned
- * MAD send buffer will reference a data buffer usable for sending a MAD, along
- * with an initialized work request structure. Users may modify the returned
- * MAD data buffer or work request before posting the send.
- *
- * The returned data buffer will be cleared. Users are responsible for
- * initializing the common MAD and any class specific headers. If @rmpp_active
- * is set, the RMPP header will be initialized for sending.
- */
-struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
- u32 remote_qpn, u16 pkey_index,
- struct ib_ah *ah, int rmpp_active,
- int hdr_len, int data_len,
- unsigned int __nocast gfp_mask);
-
-/**
- * ib_free_send_mad - Returns data buffers used to send a MAD.
- * @send_buf: Previously allocated send data buffer.
- */
-void ib_free_send_mad(struct ib_mad_send_buf *send_buf);
-
-#endif /* IB_MAD_H */
diff --git a/drivers/infiniband/include/ib_pack.h b/drivers/infiniband/include/ib_pack.h
deleted file mode 100644
index fe480f3e8654..000000000000
--- a/drivers/infiniband/include/ib_pack.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Corporation. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_pack.h 1349 2004-12-16 21:09:43Z roland $
- */
-
-#ifndef IB_PACK_H
-#define IB_PACK_H
-
-#include <ib_verbs.h>
-
-enum {
- IB_LRH_BYTES = 8,
- IB_GRH_BYTES = 40,
- IB_BTH_BYTES = 12,
- IB_DETH_BYTES = 8
-};
-
-struct ib_field {
- size_t struct_offset_bytes;
- size_t struct_size_bytes;
- int offset_words;
- int offset_bits;
- int size_bits;
- char *field_name;
-};
-
-#define RESERVED \
- .field_name = "reserved"
-
-/*
- * This macro cleans up the definitions of constants for BTH opcodes.
- * It is used to define constants such as IB_OPCODE_UD_SEND_ONLY,
- * which becomes IB_OPCODE_UD + IB_OPCODE_SEND_ONLY, and this gives
- * the correct value.
- *
- * In short, user code should use the constants defined using the
- * macro rather than worrying about adding together other constants.
-*/
-#define IB_OPCODE(transport, op) \
- IB_OPCODE_ ## transport ## _ ## op = \
- IB_OPCODE_ ## transport + IB_OPCODE_ ## op
-
-enum {
- /* transport types -- just used to define real constants */
- IB_OPCODE_RC = 0x00,
- IB_OPCODE_UC = 0x20,
- IB_OPCODE_RD = 0x40,
- IB_OPCODE_UD = 0x60,
-
- /* operations -- just used to define real constants */
- IB_OPCODE_SEND_FIRST = 0x00,
- IB_OPCODE_SEND_MIDDLE = 0x01,
- IB_OPCODE_SEND_LAST = 0x02,
- IB_OPCODE_SEND_LAST_WITH_IMMEDIATE = 0x03,
- IB_OPCODE_SEND_ONLY = 0x04,
- IB_OPCODE_SEND_ONLY_WITH_IMMEDIATE = 0x05,
- IB_OPCODE_RDMA_WRITE_FIRST = 0x06,
- IB_OPCODE_RDMA_WRITE_MIDDLE = 0x07,
- IB_OPCODE_RDMA_WRITE_LAST = 0x08,
- IB_OPCODE_RDMA_WRITE_LAST_WITH_IMMEDIATE = 0x09,
- IB_OPCODE_RDMA_WRITE_ONLY = 0x0a,
- IB_OPCODE_RDMA_WRITE_ONLY_WITH_IMMEDIATE = 0x0b,
- IB_OPCODE_RDMA_READ_REQUEST = 0x0c,
- IB_OPCODE_RDMA_READ_RESPONSE_FIRST = 0x0d,
- IB_OPCODE_RDMA_READ_RESPONSE_MIDDLE = 0x0e,
- IB_OPCODE_RDMA_READ_RESPONSE_LAST = 0x0f,
- IB_OPCODE_RDMA_READ_RESPONSE_ONLY = 0x10,
- IB_OPCODE_ACKNOWLEDGE = 0x11,
- IB_OPCODE_ATOMIC_ACKNOWLEDGE = 0x12,
- IB_OPCODE_COMPARE_SWAP = 0x13,
- IB_OPCODE_FETCH_ADD = 0x14,
-
- /* real constants follow -- see comment about above IB_OPCODE()
- macro for more details */
-
- /* RC */
- IB_OPCODE(RC, SEND_FIRST),
- IB_OPCODE(RC, SEND_MIDDLE),
- IB_OPCODE(RC, SEND_LAST),
- IB_OPCODE(RC, SEND_LAST_WITH_IMMEDIATE),
- IB_OPCODE(RC, SEND_ONLY),
- IB_OPCODE(RC, SEND_ONLY_WITH_IMMEDIATE),
- IB_OPCODE(RC, RDMA_WRITE_FIRST),
- IB_OPCODE(RC, RDMA_WRITE_MIDDLE),
- IB_OPCODE(RC, RDMA_WRITE_LAST),
- IB_OPCODE(RC, RDMA_WRITE_LAST_WITH_IMMEDIATE),
- IB_OPCODE(RC, RDMA_WRITE_ONLY),
- IB_OPCODE(RC, RDMA_WRITE_ONLY_WITH_IMMEDIATE),
- IB_OPCODE(RC, RDMA_READ_REQUEST),
- IB_OPCODE(RC, RDMA_READ_RESPONSE_FIRST),
- IB_OPCODE(RC, RDMA_READ_RESPONSE_MIDDLE),
- IB_OPCODE(RC, RDMA_READ_RESPONSE_LAST),
- IB_OPCODE(RC, RDMA_READ_RESPONSE_ONLY),
- IB_OPCODE(RC, ACKNOWLEDGE),
- IB_OPCODE(RC, ATOMIC_ACKNOWLEDGE),
- IB_OPCODE(RC, COMPARE_SWAP),
- IB_OPCODE(RC, FETCH_ADD),
-
- /* UC */
- IB_OPCODE(UC, SEND_FIRST),
- IB_OPCODE(UC, SEND_MIDDLE),
- IB_OPCODE(UC, SEND_LAST),
- IB_OPCODE(UC, SEND_LAST_WITH_IMMEDIATE),
- IB_OPCODE(UC, SEND_ONLY),
- IB_OPCODE(UC, SEND_ONLY_WITH_IMMEDIATE),
- IB_OPCODE(UC, RDMA_WRITE_FIRST),
- IB_OPCODE(UC, RDMA_WRITE_MIDDLE),
- IB_OPCODE(UC, RDMA_WRITE_LAST),
- IB_OPCODE(UC, RDMA_WRITE_LAST_WITH_IMMEDIATE),
- IB_OPCODE(UC, RDMA_WRITE_ONLY),
- IB_OPCODE(UC, RDMA_WRITE_ONLY_WITH_IMMEDIATE),
-
- /* RD */
- IB_OPCODE(RD, SEND_FIRST),
- IB_OPCODE(RD, SEND_MIDDLE),
- IB_OPCODE(RD, SEND_LAST),
- IB_OPCODE(RD, SEND_LAST_WITH_IMMEDIATE),
- IB_OPCODE(RD, SEND_ONLY),
- IB_OPCODE(RD, SEND_ONLY_WITH_IMMEDIATE),
- IB_OPCODE(RD, RDMA_WRITE_FIRST),
- IB_OPCODE(RD, RDMA_WRITE_MIDDLE),
- IB_OPCODE(RD, RDMA_WRITE_LAST),
- IB_OPCODE(RD, RDMA_WRITE_LAST_WITH_IMMEDIATE),
- IB_OPCODE(RD, RDMA_WRITE_ONLY),
- IB_OPCODE(RD, RDMA_WRITE_ONLY_WITH_IMMEDIATE),
- IB_OPCODE(RD, RDMA_READ_REQUEST),
- IB_OPCODE(RD, RDMA_READ_RESPONSE_FIRST),
- IB_OPCODE(RD, RDMA_READ_RESPONSE_MIDDLE),
- IB_OPCODE(RD, RDMA_READ_RESPONSE_LAST),
- IB_OPCODE(RD, RDMA_READ_RESPONSE_ONLY),
- IB_OPCODE(RD, ACKNOWLEDGE),
- IB_OPCODE(RD, ATOMIC_ACKNOWLEDGE),
- IB_OPCODE(RD, COMPARE_SWAP),
- IB_OPCODE(RD, FETCH_ADD),
-
- /* UD */
- IB_OPCODE(UD, SEND_ONLY),
- IB_OPCODE(UD, SEND_ONLY_WITH_IMMEDIATE)
-};
-
-enum {
- IB_LNH_RAW = 0,
- IB_LNH_IP = 1,
- IB_LNH_IBA_LOCAL = 2,
- IB_LNH_IBA_GLOBAL = 3
-};
-
-struct ib_unpacked_lrh {
- u8 virtual_lane;
- u8 link_version;
- u8 service_level;
- u8 link_next_header;
- __be16 destination_lid;
- __be16 packet_length;
- __be16 source_lid;
-};
-
-struct ib_unpacked_grh {
- u8 ip_version;
- u8 traffic_class;
- __be32 flow_label;
- __be16 payload_length;
- u8 next_header;
- u8 hop_limit;
- union ib_gid source_gid;
- union ib_gid destination_gid;
-};
-
-struct ib_unpacked_bth {
- u8 opcode;
- u8 solicited_event;
- u8 mig_req;
- u8 pad_count;
- u8 transport_header_version;
- __be16 pkey;
- __be32 destination_qpn;
- u8 ack_req;
- __be32 psn;
-};
-
-struct ib_unpacked_deth {
- __be32 qkey;
- __be32 source_qpn;
-};
-
-struct ib_ud_header {
- struct ib_unpacked_lrh lrh;
- int grh_present;
- struct ib_unpacked_grh grh;
- struct ib_unpacked_bth bth;
- struct ib_unpacked_deth deth;
- int immediate_present;
- __be32 immediate_data;
-};
-
-void ib_pack(const struct ib_field *desc,
- int desc_len,
- void *structure,
- void *buf);
-
-void ib_unpack(const struct ib_field *desc,
- int desc_len,
- void *buf,
- void *structure);
-
-void ib_ud_header_init(int payload_bytes,
- int grh_present,
- struct ib_ud_header *header);
-
-int ib_ud_header_pack(struct ib_ud_header *header,
- void *buf);
-
-int ib_ud_header_unpack(void *buf,
- struct ib_ud_header *header);
-
-#endif /* IB_PACK_H */
diff --git a/drivers/infiniband/include/ib_sa.h b/drivers/infiniband/include/ib_sa.h
deleted file mode 100644
index 6d999f7b5d93..000000000000
--- a/drivers/infiniband/include/ib_sa.h
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_sa.h 2811 2005-07-06 18:11:43Z halr $
- */
-
-#ifndef IB_SA_H
-#define IB_SA_H
-
-#include <linux/compiler.h>
-
-#include <ib_verbs.h>
-#include <ib_mad.h>
-
-enum {
- IB_SA_CLASS_VERSION = 2, /* IB spec version 1.1/1.2 */
-
- IB_SA_METHOD_GET_TABLE = 0x12,
- IB_SA_METHOD_GET_TABLE_RESP = 0x92,
- IB_SA_METHOD_DELETE = 0x15
-};
-
-enum ib_sa_selector {
- IB_SA_GTE = 0,
- IB_SA_LTE = 1,
- IB_SA_EQ = 2,
- /*
- * The meaning of "best" depends on the attribute: for
- * example, for MTU best will return the largest available
- * MTU, while for packet life time, best will return the
- * smallest available life time.
- */
- IB_SA_BEST = 3
-};
-
-enum ib_sa_rate {
- IB_SA_RATE_2_5_GBPS = 2,
- IB_SA_RATE_5_GBPS = 5,
- IB_SA_RATE_10_GBPS = 3,
- IB_SA_RATE_20_GBPS = 6,
- IB_SA_RATE_30_GBPS = 4,
- IB_SA_RATE_40_GBPS = 7,
- IB_SA_RATE_60_GBPS = 8,
- IB_SA_RATE_80_GBPS = 9,
- IB_SA_RATE_120_GBPS = 10
-};
-
-static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
-{
- switch (rate) {
- case IB_SA_RATE_2_5_GBPS: return 1;
- case IB_SA_RATE_5_GBPS: return 2;
- case IB_SA_RATE_10_GBPS: return 4;
- case IB_SA_RATE_20_GBPS: return 8;
- case IB_SA_RATE_30_GBPS: return 12;
- case IB_SA_RATE_40_GBPS: return 16;
- case IB_SA_RATE_60_GBPS: return 24;
- case IB_SA_RATE_80_GBPS: return 32;
- case IB_SA_RATE_120_GBPS: return 48;
- default: return -1;
- }
-}
-
-/*
- * Structures for SA records are named "struct ib_sa_xxx_rec." No
- * attempt is made to pack structures to match the physical layout of
- * SA records in SA MADs; all packing and unpacking is handled by the
- * SA query code.
- *
- * For a record with structure ib_sa_xxx_rec, the naming convention
- * for the component mask value for field yyy is IB_SA_XXX_REC_YYY (we
- * never use different abbreviations or otherwise change the spelling
- * of xxx/yyy between ib_sa_xxx_rec.yyy and IB_SA_XXX_REC_YYY).
- *
- * Reserved rows are indicated with comments to help maintainability.
- */
-
-/* reserved: 0 */
-/* reserved: 1 */
-#define IB_SA_PATH_REC_DGID IB_SA_COMP_MASK( 2)
-#define IB_SA_PATH_REC_SGID IB_SA_COMP_MASK( 3)
-#define IB_SA_PATH_REC_DLID IB_SA_COMP_MASK( 4)
-#define IB_SA_PATH_REC_SLID IB_SA_COMP_MASK( 5)
-#define IB_SA_PATH_REC_RAW_TRAFFIC IB_SA_COMP_MASK( 6)
-/* reserved: 7 */
-#define IB_SA_PATH_REC_FLOW_LABEL IB_SA_COMP_MASK( 8)
-#define IB_SA_PATH_REC_HOP_LIMIT IB_SA_COMP_MASK( 9)
-#define IB_SA_PATH_REC_TRAFFIC_CLASS IB_SA_COMP_MASK(10)
-#define IB_SA_PATH_REC_REVERSIBLE IB_SA_COMP_MASK(11)
-#define IB_SA_PATH_REC_NUMB_PATH IB_SA_COMP_MASK(12)
-#define IB_SA_PATH_REC_PKEY IB_SA_COMP_MASK(13)
-/* reserved: 14 */
-#define IB_SA_PATH_REC_SL IB_SA_COMP_MASK(15)
-#define IB_SA_PATH_REC_MTU_SELECTOR IB_SA_COMP_MASK(16)
-#define IB_SA_PATH_REC_MTU IB_SA_COMP_MASK(17)
-#define IB_SA_PATH_REC_RATE_SELECTOR IB_SA_COMP_MASK(18)
-#define IB_SA_PATH_REC_RATE IB_SA_COMP_MASK(19)
-#define IB_SA_PATH_REC_PACKET_LIFE_TIME_SELECTOR IB_SA_COMP_MASK(20)
-#define IB_SA_PATH_REC_PACKET_LIFE_TIME IB_SA_COMP_MASK(21)
-#define IB_SA_PATH_REC_PREFERENCE IB_SA_COMP_MASK(22)
-
-struct ib_sa_path_rec {
- /* reserved */
- /* reserved */
- union ib_gid dgid;
- union ib_gid sgid;
- u16 dlid;
- u16 slid;
- int raw_traffic;
- /* reserved */
- u32 flow_label;
- u8 hop_limit;
- u8 traffic_class;
- int reversible;
- u8 numb_path;
- u16 pkey;
- /* reserved */
- u8 sl;
- u8 mtu_selector;
- u8 mtu;
- u8 rate_selector;
- u8 rate;
- u8 packet_life_time_selector;
- u8 packet_life_time;
- u8 preference;
-};
-
-#define IB_SA_MCMEMBER_REC_MGID IB_SA_COMP_MASK( 0)
-#define IB_SA_MCMEMBER_REC_PORT_GID IB_SA_COMP_MASK( 1)
-#define IB_SA_MCMEMBER_REC_QKEY IB_SA_COMP_MASK( 2)
-#define IB_SA_MCMEMBER_REC_MLID IB_SA_COMP_MASK( 3)
-#define IB_SA_MCMEMBER_REC_MTU_SELECTOR IB_SA_COMP_MASK( 4)
-#define IB_SA_MCMEMBER_REC_MTU IB_SA_COMP_MASK( 5)
-#define IB_SA_MCMEMBER_REC_TRAFFIC_CLASS IB_SA_COMP_MASK( 6)
-#define IB_SA_MCMEMBER_REC_PKEY IB_SA_COMP_MASK( 7)
-#define IB_SA_MCMEMBER_REC_RATE_SELECTOR IB_SA_COMP_MASK( 8)
-#define IB_SA_MCMEMBER_REC_RATE IB_SA_COMP_MASK( 9)
-#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR IB_SA_COMP_MASK(10)
-#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME IB_SA_COMP_MASK(11)
-#define IB_SA_MCMEMBER_REC_SL IB_SA_COMP_MASK(12)
-#define IB_SA_MCMEMBER_REC_FLOW_LABEL IB_SA_COMP_MASK(13)
-#define IB_SA_MCMEMBER_REC_HOP_LIMIT IB_SA_COMP_MASK(14)
-#define IB_SA_MCMEMBER_REC_SCOPE IB_SA_COMP_MASK(15)
-#define IB_SA_MCMEMBER_REC_JOIN_STATE IB_SA_COMP_MASK(16)
-#define IB_SA_MCMEMBER_REC_PROXY_JOIN IB_SA_COMP_MASK(17)
-
-struct ib_sa_mcmember_rec {
- union ib_gid mgid;
- union ib_gid port_gid;
- u32 qkey;
- u16 mlid;
- u8 mtu_selector;
- u8 mtu;
- u8 traffic_class;
- u16 pkey;
- u8 rate_selector;
- u8 rate;
- u8 packet_life_time_selector;
- u8 packet_life_time;
- u8 sl;
- u32 flow_label;
- u8 hop_limit;
- u8 scope;
- u8 join_state;
- int proxy_join;
-};
-
-/* Service Record Component Mask Sec 15.2.5.14 Ver 1.1 */
-#define IB_SA_SERVICE_REC_SERVICE_ID IB_SA_COMP_MASK( 0)
-#define IB_SA_SERVICE_REC_SERVICE_GID IB_SA_COMP_MASK( 1)
-#define IB_SA_SERVICE_REC_SERVICE_PKEY IB_SA_COMP_MASK( 2)
-/* reserved: 3 */
-#define IB_SA_SERVICE_REC_SERVICE_LEASE IB_SA_COMP_MASK( 4)
-#define IB_SA_SERVICE_REC_SERVICE_KEY IB_SA_COMP_MASK( 5)
-#define IB_SA_SERVICE_REC_SERVICE_NAME IB_SA_COMP_MASK( 6)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_0 IB_SA_COMP_MASK( 7)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_1 IB_SA_COMP_MASK( 8)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_2 IB_SA_COMP_MASK( 9)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_3 IB_SA_COMP_MASK(10)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_4 IB_SA_COMP_MASK(11)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_5 IB_SA_COMP_MASK(12)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_6 IB_SA_COMP_MASK(13)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_7 IB_SA_COMP_MASK(14)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_8 IB_SA_COMP_MASK(15)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_9 IB_SA_COMP_MASK(16)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_10 IB_SA_COMP_MASK(17)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_11 IB_SA_COMP_MASK(18)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_12 IB_SA_COMP_MASK(19)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_13 IB_SA_COMP_MASK(20)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_14 IB_SA_COMP_MASK(21)
-#define IB_SA_SERVICE_REC_SERVICE_DATA8_15 IB_SA_COMP_MASK(22)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_0 IB_SA_COMP_MASK(23)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_1 IB_SA_COMP_MASK(24)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_2 IB_SA_COMP_MASK(25)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_3 IB_SA_COMP_MASK(26)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_4 IB_SA_COMP_MASK(27)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_5 IB_SA_COMP_MASK(28)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_6 IB_SA_COMP_MASK(29)
-#define IB_SA_SERVICE_REC_SERVICE_DATA16_7 IB_SA_COMP_MASK(30)
-#define IB_SA_SERVICE_REC_SERVICE_DATA32_0 IB_SA_COMP_MASK(31)
-#define IB_SA_SERVICE_REC_SERVICE_DATA32_1 IB_SA_COMP_MASK(32)
-#define IB_SA_SERVICE_REC_SERVICE_DATA32_2 IB_SA_COMP_MASK(33)
-#define IB_SA_SERVICE_REC_SERVICE_DATA32_3 IB_SA_COMP_MASK(34)
-#define IB_SA_SERVICE_REC_SERVICE_DATA64_0 IB_SA_COMP_MASK(35)
-#define IB_SA_SERVICE_REC_SERVICE_DATA64_1 IB_SA_COMP_MASK(36)
-
-#define IB_DEFAULT_SERVICE_LEASE 0xFFFFFFFF
-
-struct ib_sa_service_rec {
- u64 id;
- union ib_gid gid;
- u16 pkey;
- /* reserved */
- u32 lease;
- u8 key[16];
- u8 name[64];
- u8 data8[16];
- u16 data16[8];
- u32 data32[4];
- u64 data64[2];
-};
-
-struct ib_sa_query;
-
-void ib_sa_cancel_query(int id, struct ib_sa_query *query);
-
-int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
- struct ib_sa_path_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
- void (*callback)(int status,
- struct ib_sa_path_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query);
-
-int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
- u8 method,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query);
-
-int ib_sa_service_rec_query(struct ib_device *device, u8 port_num,
- u8 method,
- struct ib_sa_service_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
- void (*callback)(int status,
- struct ib_sa_service_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **sa_query);
-
-/**
- * ib_sa_mcmember_rec_set - Start an MCMember set query
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
- *
- * Send an MCMember Set query to the SA (eg to join a multicast
- * group). The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query. The resp parameter of
- * the callback is only valid if status is 0.
- *
- * If the return value of ib_sa_mcmember_rec_set() is negative, it is
- * an error code. Otherwise it is a query ID that can be used to
- * cancel the query.
- */
-static inline int
-ib_sa_mcmember_rec_set(struct ib_device *device, u8 port_num,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query)
-{
- return ib_sa_mcmember_rec_query(device, port_num,
- IB_MGMT_METHOD_SET,
- rec, comp_mask,
- timeout_ms, gfp_mask, callback,
- context, query);
-}
-
-/**
- * ib_sa_mcmember_rec_delete - Start an MCMember delete query
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
- *
- * Send an MCMember Delete query to the SA (eg to leave a multicast
- * group). The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query. The resp parameter of
- * the callback is only valid if status is 0.
- *
- * If the return value of ib_sa_mcmember_rec_delete() is negative, it
- * is an error code. Otherwise it is a query ID that can be used to
- * cancel the query.
- */
-static inline int
-ib_sa_mcmember_rec_delete(struct ib_device *device, u8 port_num,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, unsigned int __nocast gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query)
-{
- return ib_sa_mcmember_rec_query(device, port_num,
- IB_SA_METHOD_DELETE,
- rec, comp_mask,
- timeout_ms, gfp_mask, callback,
- context, query);
-}
-
-
-#endif /* IB_SA_H */
diff --git a/drivers/infiniband/include/ib_smi.h b/drivers/infiniband/include/ib_smi.h
deleted file mode 100644
index ca8216514963..000000000000
--- a/drivers/infiniband/include/ib_smi.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_smi.h 1389 2004-12-27 22:56:47Z roland $
- */
-
-#if !defined( IB_SMI_H )
-#define IB_SMI_H
-
-#include <ib_mad.h>
-
-#define IB_LID_PERMISSIVE 0xFFFF
-
-#define IB_SMP_DATA_SIZE 64
-#define IB_SMP_MAX_PATH_HOPS 64
-
-struct ib_smp {
- u8 base_version;
- u8 mgmt_class;
- u8 class_version;
- u8 method;
- u16 status;
- u8 hop_ptr;
- u8 hop_cnt;
- u64 tid;
- u16 attr_id;
- u16 resv;
- u32 attr_mod;
- u64 mkey;
- u16 dr_slid;
- u16 dr_dlid;
- u8 reserved[28];
- u8 data[IB_SMP_DATA_SIZE];
- u8 initial_path[IB_SMP_MAX_PATH_HOPS];
- u8 return_path[IB_SMP_MAX_PATH_HOPS];
-} __attribute__ ((packed));
-
-#define IB_SMP_DIRECTION __constant_htons(0x8000)
-
-/* Subnet management attributes */
-#define IB_SMP_ATTR_NOTICE __constant_htons(0x0002)
-#define IB_SMP_ATTR_NODE_DESC __constant_htons(0x0010)
-#define IB_SMP_ATTR_NODE_INFO __constant_htons(0x0011)
-#define IB_SMP_ATTR_SWITCH_INFO __constant_htons(0x0012)
-#define IB_SMP_ATTR_GUID_INFO __constant_htons(0x0014)
-#define IB_SMP_ATTR_PORT_INFO __constant_htons(0x0015)
-#define IB_SMP_ATTR_PKEY_TABLE __constant_htons(0x0016)
-#define IB_SMP_ATTR_SL_TO_VL_TABLE __constant_htons(0x0017)
-#define IB_SMP_ATTR_VL_ARB_TABLE __constant_htons(0x0018)
-#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE __constant_htons(0x0019)
-#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE __constant_htons(0x001A)
-#define IB_SMP_ATTR_MCAST_FORWARD_TABLE __constant_htons(0x001B)
-#define IB_SMP_ATTR_SM_INFO __constant_htons(0x0020)
-#define IB_SMP_ATTR_VENDOR_DIAG __constant_htons(0x0030)
-#define IB_SMP_ATTR_LED_INFO __constant_htons(0x0031)
-#define IB_SMP_ATTR_VENDOR_MASK __constant_htons(0xFF00)
-
-static inline u8
-ib_get_smp_direction(struct ib_smp *smp)
-{
- return ((smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION);
-}
-
-#endif /* IB_SMI_H */
diff --git a/drivers/infiniband/include/ib_user_cm.h b/drivers/infiniband/include/ib_user_cm.h
deleted file mode 100644
index 500b1af6ff77..000000000000
--- a/drivers/infiniband/include/ib_user_cm.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_user_cm.h 2576 2005-06-09 17:00:30Z libor $
- */
-
-#ifndef IB_USER_CM_H
-#define IB_USER_CM_H
-
-#include <linux/types.h>
-
-#define IB_USER_CM_ABI_VERSION 1
-
-enum {
- IB_USER_CM_CMD_CREATE_ID,
- IB_USER_CM_CMD_DESTROY_ID,
- IB_USER_CM_CMD_ATTR_ID,
-
- IB_USER_CM_CMD_LISTEN,
- IB_USER_CM_CMD_ESTABLISH,
-
- IB_USER_CM_CMD_SEND_REQ,
- IB_USER_CM_CMD_SEND_REP,
- IB_USER_CM_CMD_SEND_RTU,
- IB_USER_CM_CMD_SEND_DREQ,
- IB_USER_CM_CMD_SEND_DREP,
- IB_USER_CM_CMD_SEND_REJ,
- IB_USER_CM_CMD_SEND_MRA,
- IB_USER_CM_CMD_SEND_LAP,
- IB_USER_CM_CMD_SEND_APR,
- IB_USER_CM_CMD_SEND_SIDR_REQ,
- IB_USER_CM_CMD_SEND_SIDR_REP,
-
- IB_USER_CM_CMD_EVENT,
-};
-/*
- * command ABI structures.
- */
-struct ib_ucm_cmd_hdr {
- __u32 cmd;
- __u16 in;
- __u16 out;
-};
-
-struct ib_ucm_create_id {
- __u64 response;
-};
-
-struct ib_ucm_create_id_resp {
- __u32 id;
-};
-
-struct ib_ucm_destroy_id {
- __u32 id;
-};
-
-struct ib_ucm_attr_id {
- __u64 response;
- __u32 id;
-};
-
-struct ib_ucm_attr_id_resp {
- __u64 service_id;
- __u64 service_mask;
- __u32 local_id;
- __u32 remote_id;
-};
-
-struct ib_ucm_listen {
- __u64 service_id;
- __u64 service_mask;
- __u32 id;
-};
-
-struct ib_ucm_establish {
- __u32 id;
-};
-
-struct ib_ucm_private_data {
- __u64 data;
- __u32 id;
- __u8 len;
- __u8 reserved[3];
-};
-
-struct ib_ucm_path_rec {
- __u8 dgid[16];
- __u8 sgid[16];
- __u16 dlid;
- __u16 slid;
- __u32 raw_traffic;
- __u32 flow_label;
- __u32 reversible;
- __u32 mtu;
- __u16 pkey;
- __u8 hop_limit;
- __u8 traffic_class;
- __u8 numb_path;
- __u8 sl;
- __u8 mtu_selector;
- __u8 rate_selector;
- __u8 rate;
- __u8 packet_life_time_selector;
- __u8 packet_life_time;
- __u8 preference;
-};
-
-struct ib_ucm_req {
- __u32 id;
- __u32 qpn;
- __u32 qp_type;
- __u32 psn;
- __u64 sid;
- __u64 data;
- __u64 primary_path;
- __u64 alternate_path;
- __u8 len;
- __u8 peer_to_peer;
- __u8 responder_resources;
- __u8 initiator_depth;
- __u8 remote_cm_response_timeout;
- __u8 flow_control;
- __u8 local_cm_response_timeout;
- __u8 retry_count;
- __u8 rnr_retry_count;
- __u8 max_cm_retries;
- __u8 srq;
- __u8 reserved[1];
-};
-
-struct ib_ucm_rep {
- __u64 data;
- __u32 id;
- __u32 qpn;
- __u32 psn;
- __u8 len;
- __u8 responder_resources;
- __u8 initiator_depth;
- __u8 target_ack_delay;
- __u8 failover_accepted;
- __u8 flow_control;
- __u8 rnr_retry_count;
- __u8 srq;
-};
-
-struct ib_ucm_info {
- __u32 id;
- __u32 status;
- __u64 info;
- __u64 data;
- __u8 info_len;
- __u8 data_len;
- __u8 reserved[2];
-};
-
-struct ib_ucm_mra {
- __u64 data;
- __u32 id;
- __u8 len;
- __u8 timeout;
- __u8 reserved[2];
-};
-
-struct ib_ucm_lap {
- __u64 path;
- __u64 data;
- __u32 id;
- __u8 len;
- __u8 reserved[3];
-};
-
-struct ib_ucm_sidr_req {
- __u32 id;
- __u32 timeout;
- __u64 sid;
- __u64 data;
- __u64 path;
- __u16 pkey;
- __u8 len;
- __u8 max_cm_retries;
-};
-
-struct ib_ucm_sidr_rep {
- __u32 id;
- __u32 qpn;
- __u32 qkey;
- __u32 status;
- __u64 info;
- __u64 data;
- __u8 info_len;
- __u8 data_len;
- __u8 reserved[2];
-};
-/*
- * event notification ABI structures.
- */
-struct ib_ucm_event_get {
- __u64 response;
- __u64 data;
- __u64 info;
- __u8 data_len;
- __u8 info_len;
- __u8 reserved[2];
-};
-
-struct ib_ucm_req_event_resp {
- __u32 listen_id;
- /* device */
- /* port */
- struct ib_ucm_path_rec primary_path;
- struct ib_ucm_path_rec alternate_path;
- __u64 remote_ca_guid;
- __u32 remote_qkey;
- __u32 remote_qpn;
- __u32 qp_type;
- __u32 starting_psn;
- __u8 responder_resources;
- __u8 initiator_depth;
- __u8 local_cm_response_timeout;
- __u8 flow_control;
- __u8 remote_cm_response_timeout;
- __u8 retry_count;
- __u8 rnr_retry_count;
- __u8 srq;
-};
-
-struct ib_ucm_rep_event_resp {
- __u64 remote_ca_guid;
- __u32 remote_qkey;
- __u32 remote_qpn;
- __u32 starting_psn;
- __u8 responder_resources;
- __u8 initiator_depth;
- __u8 target_ack_delay;
- __u8 failover_accepted;
- __u8 flow_control;
- __u8 rnr_retry_count;
- __u8 srq;
- __u8 reserved[1];
-};
-
-struct ib_ucm_rej_event_resp {
- __u32 reason;
- /* ari in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_mra_event_resp {
- __u8 timeout;
- __u8 reserved[3];
-};
-
-struct ib_ucm_lap_event_resp {
- struct ib_ucm_path_rec path;
-};
-
-struct ib_ucm_apr_event_resp {
- __u32 status;
- /* apr info in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_sidr_req_event_resp {
- __u32 listen_id;
- /* device */
- /* port */
- __u16 pkey;
- __u8 reserved[2];
-};
-
-struct ib_ucm_sidr_rep_event_resp {
- __u32 status;
- __u32 qkey;
- __u32 qpn;
- /* info in ib_ucm_event_get info field. */
-};
-
-#define IB_UCM_PRES_DATA 0x01
-#define IB_UCM_PRES_INFO 0x02
-#define IB_UCM_PRES_PRIMARY 0x04
-#define IB_UCM_PRES_ALTERNATE 0x08
-
-struct ib_ucm_event_resp {
- __u32 id;
- __u32 event;
- __u32 present;
- union {
- struct ib_ucm_req_event_resp req_resp;
- struct ib_ucm_rep_event_resp rep_resp;
- struct ib_ucm_rej_event_resp rej_resp;
- struct ib_ucm_mra_event_resp mra_resp;
- struct ib_ucm_lap_event_resp lap_resp;
- struct ib_ucm_apr_event_resp apr_resp;
-
- struct ib_ucm_sidr_req_event_resp sidr_req_resp;
- struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
-
- __u32 send_status;
- } u;
-};
-
-#endif /* IB_USER_CM_H */
diff --git a/drivers/infiniband/include/ib_user_mad.h b/drivers/infiniband/include/ib_user_mad.h
deleted file mode 100644
index a9a56b50aacc..000000000000
--- a/drivers/infiniband/include/ib_user_mad.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_user_mad.h 2814 2005-07-06 19:14:09Z halr $
- */
-
-#ifndef IB_USER_MAD_H
-#define IB_USER_MAD_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_MAD_ABI_VERSION 5
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- */
-
-/**
- * ib_user_mad_hdr - MAD packet header
- * @id - ID of agent MAD received with/to be sent with
- * @status - 0 on successful receive, ETIMEDOUT if no response
- * received (transaction ID in data[] will be set to TID of original
- * request) (ignored on send)
- * @timeout_ms - Milliseconds to wait for response (unset on receive)
- * @retries - Number of automatic retries to attempt
- * @qpn - Remote QP number received from/to be sent to
- * @qkey - Remote Q_Key to be sent with (unset on receive)
- * @lid - Remote lid received from/to be sent to
- * @sl - Service level received with/to be sent with
- * @path_bits - Local path bits received with/to be sent with
- * @grh_present - If set, GRH was received/should be sent
- * @gid_index - Local GID index to send with (unset on receive)
- * @hop_limit - Hop limit in GRH
- * @traffic_class - Traffic class in GRH
- * @gid - Remote GID in GRH
- * @flow_label - Flow label in GRH
- *
- * All multi-byte quantities are stored in network (big endian) byte order.
- */
-struct ib_user_mad_hdr {
- __u32 id;
- __u32 status;
- __u32 timeout_ms;
- __u32 retries;
- __u32 length;
- __u32 qpn;
- __u32 qkey;
- __u16 lid;
- __u8 sl;
- __u8 path_bits;
- __u8 grh_present;
- __u8 gid_index;
- __u8 hop_limit;
- __u8 traffic_class;
- __u8 gid[16];
- __u32 flow_label;
-};
-
-/**
- * ib_user_mad - MAD packet
- * @hdr - MAD packet header
- * @data - Contents of MAD
- *
- */
-struct ib_user_mad {
- struct ib_user_mad_hdr hdr;
- __u8 data[0];
-};
-
-/**
- * ib_user_mad_reg_req - MAD registration request
- * @id - Set by the kernel; used to identify agent in future requests.
- * @qpn - Queue pair number; must be 0 or 1.
- * @method_mask - The caller will receive unsolicited MADs for any method
- * where @method_mask = 1.
- * @mgmt_class - Indicates which management class of MADs should be receive
- * by the caller. This field is only required if the user wishes to
- * receive unsolicited MADs, otherwise it should be 0.
- * @mgmt_class_version - Indicates which version of MADs for the given
- * management class to receive.
- * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
- * in the range from 0x30 to 0x4f. Otherwise not used.
- * @rmpp_version: If set, indicates the RMPP version used.
- *
- */
-struct ib_user_mad_reg_req {
- __u32 id;
- __u32 method_mask[4];
- __u8 qpn;
- __u8 mgmt_class;
- __u8 mgmt_class_version;
- __u8 oui[3];
- __u8 rmpp_version;
-};
-
-#define IB_IOCTL_MAGIC 0x1b
-
-#define IB_USER_MAD_REGISTER_AGENT _IOWR(IB_IOCTL_MAGIC, 1, \
- struct ib_user_mad_reg_req)
-
-#define IB_USER_MAD_UNREGISTER_AGENT _IOW(IB_IOCTL_MAGIC, 2, __u32)
-
-#endif /* IB_USER_MAD_H */
diff --git a/drivers/infiniband/include/ib_user_verbs.h b/drivers/infiniband/include/ib_user_verbs.h
deleted file mode 100644
index 7c613706af72..000000000000
--- a/drivers/infiniband/include/ib_user_verbs.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Cisco Systems. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_user_verbs.h 2708 2005-06-24 17:27:21Z roland $
- */
-
-#ifndef IB_USER_VERBS_H
-#define IB_USER_VERBS_H
-
-#include <linux/types.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_VERBS_ABI_VERSION 1
-
-enum {
- IB_USER_VERBS_CMD_QUERY_PARAMS,
- IB_USER_VERBS_CMD_GET_CONTEXT,
- IB_USER_VERBS_CMD_QUERY_DEVICE,
- IB_USER_VERBS_CMD_QUERY_PORT,
- IB_USER_VERBS_CMD_QUERY_GID,
- IB_USER_VERBS_CMD_QUERY_PKEY,
- IB_USER_VERBS_CMD_ALLOC_PD,
- IB_USER_VERBS_CMD_DEALLOC_PD,
- IB_USER_VERBS_CMD_CREATE_AH,
- IB_USER_VERBS_CMD_MODIFY_AH,
- IB_USER_VERBS_CMD_QUERY_AH,
- IB_USER_VERBS_CMD_DESTROY_AH,
- IB_USER_VERBS_CMD_REG_MR,
- IB_USER_VERBS_CMD_REG_SMR,
- IB_USER_VERBS_CMD_REREG_MR,
- IB_USER_VERBS_CMD_QUERY_MR,
- IB_USER_VERBS_CMD_DEREG_MR,
- IB_USER_VERBS_CMD_ALLOC_MW,
- IB_USER_VERBS_CMD_BIND_MW,
- IB_USER_VERBS_CMD_DEALLOC_MW,
- IB_USER_VERBS_CMD_CREATE_CQ,
- IB_USER_VERBS_CMD_RESIZE_CQ,
- IB_USER_VERBS_CMD_DESTROY_CQ,
- IB_USER_VERBS_CMD_POLL_CQ,
- IB_USER_VERBS_CMD_PEEK_CQ,
- IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
- IB_USER_VERBS_CMD_CREATE_QP,
- IB_USER_VERBS_CMD_QUERY_QP,
- IB_USER_VERBS_CMD_MODIFY_QP,
- IB_USER_VERBS_CMD_DESTROY_QP,
- IB_USER_VERBS_CMD_POST_SEND,
- IB_USER_VERBS_CMD_POST_RECV,
- IB_USER_VERBS_CMD_ATTACH_MCAST,
- IB_USER_VERBS_CMD_DETACH_MCAST
-};
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- * In particular do not use pointer types -- pass pointers in __u64
- * instead.
- */
-
-struct ib_uverbs_async_event_desc {
- __u64 element;
- __u32 event_type; /* enum ib_event_type */
- __u32 reserved;
-};
-
-struct ib_uverbs_comp_event_desc {
- __u64 cq_handle;
-};
-
-/*
- * All commands from userspace should start with a __u32 command field
- * followed by __u16 in_words and out_words fields (which give the
- * length of the command block and response buffer if any in 32-bit
- * words). The kernel driver will read these fields first and read
- * the rest of the command struct based on these value.
- */
-
-struct ib_uverbs_cmd_hdr {
- __u32 command;
- __u16 in_words;
- __u16 out_words;
-};
-
-/*
- * No driver_data for "query params" command, since this is intended
- * to be a core function with no possible device dependence.
- */
-struct ib_uverbs_query_params {
- __u64 response;
-};
-
-struct ib_uverbs_query_params_resp {
- __u32 num_cq_events;
-};
-
-struct ib_uverbs_get_context {
- __u64 response;
- __u64 cq_fd_tab;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_get_context_resp {
- __u32 async_fd;
- __u32 reserved;
-};
-
-struct ib_uverbs_query_device {
- __u64 response;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_device_resp {
- __u64 fw_ver;
- __u64 node_guid;
- __u64 sys_image_guid;
- __u64 max_mr_size;
- __u64 page_size_cap;
- __u32 vendor_id;
- __u32 vendor_part_id;
- __u32 hw_ver;
- __u32 max_qp;
- __u32 max_qp_wr;
- __u32 device_cap_flags;
- __u32 max_sge;
- __u32 max_sge_rd;
- __u32 max_cq;
- __u32 max_cqe;
- __u32 max_mr;
- __u32 max_pd;
- __u32 max_qp_rd_atom;
- __u32 max_ee_rd_atom;
- __u32 max_res_rd_atom;
- __u32 max_qp_init_rd_atom;
- __u32 max_ee_init_rd_atom;
- __u32 atomic_cap;
- __u32 max_ee;
- __u32 max_rdd;
- __u32 max_mw;
- __u32 max_raw_ipv6_qp;
- __u32 max_raw_ethy_qp;
- __u32 max_mcast_grp;
- __u32 max_mcast_qp_attach;
- __u32 max_total_mcast_qp_attach;
- __u32 max_ah;
- __u32 max_fmr;
- __u32 max_map_per_fmr;
- __u32 max_srq;
- __u32 max_srq_wr;
- __u32 max_srq_sge;
- __u16 max_pkeys;
- __u8 local_ca_ack_delay;
- __u8 phys_port_cnt;
- __u8 reserved[4];
-};
-
-struct ib_uverbs_query_port {
- __u64 response;
- __u8 port_num;
- __u8 reserved[7];
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_port_resp {
- __u32 port_cap_flags;
- __u32 max_msg_sz;
- __u32 bad_pkey_cntr;
- __u32 qkey_viol_cntr;
- __u32 gid_tbl_len;
- __u16 pkey_tbl_len;
- __u16 lid;
- __u16 sm_lid;
- __u8 state;
- __u8 max_mtu;
- __u8 active_mtu;
- __u8 lmc;
- __u8 max_vl_num;
- __u8 sm_sl;
- __u8 subnet_timeout;
- __u8 init_type_reply;
- __u8 active_width;
- __u8 active_speed;
- __u8 phys_state;
- __u8 reserved[3];
-};
-
-struct ib_uverbs_query_gid {
- __u64 response;
- __u8 port_num;
- __u8 index;
- __u8 reserved[6];
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_gid_resp {
- __u8 gid[16];
-};
-
-struct ib_uverbs_query_pkey {
- __u64 response;
- __u8 port_num;
- __u8 index;
- __u8 reserved[6];
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_query_pkey_resp {
- __u16 pkey;
- __u16 reserved;
-};
-
-struct ib_uverbs_alloc_pd {
- __u64 response;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_alloc_pd_resp {
- __u32 pd_handle;
-};
-
-struct ib_uverbs_dealloc_pd {
- __u32 pd_handle;
-};
-
-struct ib_uverbs_reg_mr {
- __u64 response;
- __u64 start;
- __u64 length;
- __u64 hca_va;
- __u32 pd_handle;
- __u32 access_flags;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_reg_mr_resp {
- __u32 mr_handle;
- __u32 lkey;
- __u32 rkey;
-};
-
-struct ib_uverbs_dereg_mr {
- __u32 mr_handle;
-};
-
-struct ib_uverbs_create_cq {
- __u64 response;
- __u64 user_handle;
- __u32 cqe;
- __u32 event_handler;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_cq_resp {
- __u32 cq_handle;
- __u32 cqe;
-};
-
-struct ib_uverbs_destroy_cq {
- __u32 cq_handle;
-};
-
-struct ib_uverbs_create_qp {
- __u64 response;
- __u64 user_handle;
- __u32 pd_handle;
- __u32 send_cq_handle;
- __u32 recv_cq_handle;
- __u32 srq_handle;
- __u32 max_send_wr;
- __u32 max_recv_wr;
- __u32 max_send_sge;
- __u32 max_recv_sge;
- __u32 max_inline_data;
- __u8 sq_sig_all;
- __u8 qp_type;
- __u8 is_srq;
- __u8 reserved;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_create_qp_resp {
- __u32 qp_handle;
- __u32 qpn;
-};
-
-/*
- * This struct needs to remain a multiple of 8 bytes to keep the
- * alignment of the modify QP parameters.
- */
-struct ib_uverbs_qp_dest {
- __u8 dgid[16];
- __u32 flow_label;
- __u16 dlid;
- __u16 reserved;
- __u8 sgid_index;
- __u8 hop_limit;
- __u8 traffic_class;
- __u8 sl;
- __u8 src_path_bits;
- __u8 static_rate;
- __u8 is_global;
- __u8 port_num;
-};
-
-struct ib_uverbs_modify_qp {
- struct ib_uverbs_qp_dest dest;
- struct ib_uverbs_qp_dest alt_dest;
- __u32 qp_handle;
- __u32 attr_mask;
- __u32 qkey;
- __u32 rq_psn;
- __u32 sq_psn;
- __u32 dest_qp_num;
- __u32 qp_access_flags;
- __u16 pkey_index;
- __u16 alt_pkey_index;
- __u8 qp_state;
- __u8 cur_qp_state;
- __u8 path_mtu;
- __u8 path_mig_state;
- __u8 en_sqd_async_notify;
- __u8 max_rd_atomic;
- __u8 max_dest_rd_atomic;
- __u8 min_rnr_timer;
- __u8 port_num;
- __u8 timeout;
- __u8 retry_cnt;
- __u8 rnr_retry;
- __u8 alt_port_num;
- __u8 alt_timeout;
- __u8 reserved[2];
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_modify_qp_resp {
-};
-
-struct ib_uverbs_destroy_qp {
- __u32 qp_handle;
-};
-
-struct ib_uverbs_attach_mcast {
- __u8 gid[16];
- __u32 qp_handle;
- __u16 mlid;
- __u16 reserved;
- __u64 driver_data[0];
-};
-
-struct ib_uverbs_detach_mcast {
- __u8 gid[16];
- __u32 qp_handle;
- __u16 mlid;
- __u16 reserved;
- __u64 driver_data[0];
-};
-
-#endif /* IB_USER_VERBS_H */
diff --git a/drivers/infiniband/include/ib_verbs.h b/drivers/infiniband/include/ib_verbs.h
deleted file mode 100644
index 5d24edaa66e6..000000000000
--- a/drivers/infiniband/include/ib_verbs.h
+++ /dev/null
@@ -1,1365 +0,0 @@
-/*
- * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
- * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
- * Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
- * Copyright (c) 2005 Cisco Systems. 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
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, 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.
- *
- * - 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.
- *
- * 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.
- *
- * $Id: ib_verbs.h 1349 2004-12-16 21:09:43Z roland $
- */
-
-#if !defined(IB_VERBS_H)
-#define IB_VERBS_H
-
-#include <linux/types.h>
-#include <linux/device.h>
-
-#include <asm/atomic.h>
-#include <asm/scatterlist.h>
-#include <asm/uaccess.h>
-
-union ib_gid {
- u8 raw[16];
- struct {
- u64 subnet_prefix;
- u64 interface_id;
- } global;
-};
-
-enum ib_node_type {
- IB_NODE_CA = 1,
- IB_NODE_SWITCH,
- IB_NODE_ROUTER
-};
-
-enum ib_device_cap_flags {
- IB_DEVICE_RESIZE_MAX_WR = 1,
- IB_DEVICE_BAD_PKEY_CNTR = (1<<1),
- IB_DEVICE_BAD_QKEY_CNTR = (1<<2),
- IB_DEVICE_RAW_MULTI = (1<<3),
- IB_DEVICE_AUTO_PATH_MIG = (1<<4),
- IB_DEVICE_CHANGE_PHY_PORT = (1<<5),
- IB_DEVICE_UD_AV_PORT_ENFORCE = (1<<6),
- IB_DEVICE_CURR_QP_STATE_MOD = (1<<7),
- IB_DEVICE_SHUTDOWN_PORT = (1<<8),
- IB_DEVICE_INIT_TYPE = (1<<9),
- IB_DEVICE_PORT_ACTIVE_EVENT = (1<<10),
- IB_DEVICE_SYS_IMAGE_GUID = (1<<11),
- IB_DEVICE_RC_RNR_NAK_GEN = (1<<12),
- IB_DEVICE_SRQ_RESIZE = (1<<13),
- IB_DEVICE_N_NOTIFY_CQ = (1<<14),
-};
-
-enum ib_atomic_cap {
- IB_ATOMIC_NONE,
- IB_ATOMIC_HCA,
- IB_ATOMIC_GLOB
-};
-
-struct ib_device_attr {
- u64 fw_ver;
- u64 node_guid;
- u64 sys_image_guid;
- u64 max_mr_size;
- u64 page_size_cap;
- u32 vendor_id;
- u32 vendor_part_id;
- u32 hw_ver;
- int max_qp;
- int max_qp_wr;
- int device_cap_flags;
- int max_sge;
- int max_sge_rd;
- int max_cq;
- int max_cqe;
- int max_mr;
- int max_pd;
- int max_qp_rd_atom;
- int max_ee_rd_atom;
- int max_res_rd_atom;
- int max_qp_init_rd_atom;
- int max_ee_init_rd_atom;
- enum ib_atomic_cap atomic_cap;
- int max_ee;
- int max_rdd;
- int max_mw;
- int max_raw_ipv6_qp;
- int max_raw_ethy_qp;
- int max_mcast_grp;
- int max_mcast_qp_attach;
- int max_total_mcast_qp_attach;
- int max_ah;
- int max_fmr;
- int max_map_per_fmr;
- int max_srq;
- int max_srq_wr;
- int max_srq_sge;
- u16 max_pkeys;
- u8 local_ca_ack_delay;
-};
-
-enum ib_mtu {
- IB_MTU_256 = 1,
- IB_MTU_512 = 2,
- IB_MTU_1024 = 3,
- IB_MTU_2048 = 4,
- IB_MTU_4096 = 5
-};
-
-static inline int ib_mtu_enum_to_int(enum ib_mtu mtu)
-{
- switch (mtu) {
- case IB_MTU_256: return 256;
- case IB_MTU_512: return 512;
- case IB_MTU_1024: return 1024;
- case IB_MTU_2048: return 2048;
- case IB_MTU_4096: return 4096;
- default: return -1;
- }
-}
-
-enum ib_port_state {
- IB_PORT_NOP = 0,
- IB_PORT_DOWN = 1,
- IB_PORT_INIT = 2,
- IB_PORT_ARMED = 3,
- IB_PORT_ACTIVE = 4,
- IB_PORT_ACTIVE_DEFER = 5
-};
-
-enum ib_port_cap_flags {
- IB_PORT_SM = 1 << 1,
- IB_PORT_NOTICE_SUP = 1 << 2,
- IB_PORT_TRAP_SUP = 1 << 3,
- IB_PORT_OPT_IPD_SUP = 1 << 4,
- IB_PORT_AUTO_MIGR_SUP = 1 << 5,
- IB_PORT_SL_MAP_SUP = 1 << 6,
- IB_PORT_MKEY_NVRAM = 1 << 7,
- IB_PORT_PKEY_NVRAM = 1 << 8,
- IB_PORT_LED_INFO_SUP = 1 << 9,
- IB_PORT_SM_DISABLED = 1 << 10,
- IB_PORT_SYS_IMAGE_GUID_SUP = 1 << 11,
- IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP = 1 << 12,
- IB_PORT_CM_SUP = 1 << 16,
- IB_PORT_SNMP_TUNNEL_SUP = 1 << 17,
- IB_PORT_REINIT_SUP = 1 << 18,
- IB_PORT_DEVICE_MGMT_SUP = 1 << 19,
- IB_PORT_VENDOR_CLASS_SUP = 1 << 20,
- IB_PORT_DR_NOTICE_SUP = 1 << 21,
- IB_PORT_CAP_MASK_NOTICE_SUP = 1 << 22,
- IB_PORT_BOOT_MGMT_SUP = 1 << 23,
- IB_PORT_LINK_LATENCY_SUP = 1 << 24,
- IB_PORT_CLIENT_REG_SUP = 1 << 25
-};
-
-enum ib_port_width {
- IB_WIDTH_1X = 1,
- IB_WIDTH_4X = 2,
- IB_WIDTH_8X = 4,
- IB_WIDTH_12X = 8
-};
-
-static inline int ib_width_enum_to_int(enum ib_port_width width)
-{
- switch (width) {
- case IB_WIDTH_1X: return 1;
- case IB_WIDTH_4X: return 4;
- case IB_WIDTH_8X: return 8;
- case IB_WIDTH_12X: return 12;
- default: return -1;
- }
-}
-
-struct ib_port_attr {
- enum ib_port_state state;
- enum ib_mtu max_mtu;
- enum ib_mtu active_mtu;
- int gid_tbl_len;
- u32 port_cap_flags;
- u32 max_msg_sz;
- u32 bad_pkey_cntr;
- u32 qkey_viol_cntr;
- u16 pkey_tbl_len;
- u16 lid;
- u16 sm_lid;
- u8 lmc;
- u8 max_vl_num;
- u8 sm_sl;
- u8 subnet_timeout;
- u8 init_type_reply;
- u8 active_width;
- u8 active_speed;
- u8 phys_state;
-};
-
-enum ib_device_modify_flags {
- IB_DEVICE_MODIFY_SYS_IMAGE_GUID = 1
-};
-
-struct ib_device_modify {
- u64 sys_image_guid;
-};
-
-enum ib_port_modify_flags {
- IB_PORT_SHUTDOWN = 1,
- IB_PORT_INIT_TYPE = (1<<2),
- IB_PORT_RESET_QKEY_CNTR = (1<<3)
-};
-
-struct ib_port_modify {
- u32 set_port_cap_mask;
- u32 clr_port_cap_mask;
- u8 init_type;
-};
-
-enum ib_event_type {
- IB_EVENT_CQ_ERR,
- IB_EVENT_QP_FATAL,
- IB_EVENT_QP_REQ_ERR,
- IB_EVENT_QP_ACCESS_ERR,
- IB_EVENT_COMM_EST,
- IB_EVENT_SQ_DRAINED,
- IB_EVENT_PATH_MIG,
- IB_EVENT_PATH_MIG_ERR,
- IB_EVENT_DEVICE_FATAL,
- IB_EVENT_PORT_ACTIVE,
- IB_EVENT_PORT_ERR,
- IB_EVENT_LID_CHANGE,
- IB_EVENT_PKEY_CHANGE,
- IB_EVENT_SM_CHANGE
-};
-
-struct ib_event {
- struct ib_device *device;
- union {
- struct ib_cq *cq;
- struct ib_qp *qp;
- u8 port_num;
- } element;
- enum ib_event_type event;
-};
-
-struct ib_event_handler {
- struct ib_device *device;
- void (*handler)(struct ib_event_handler *, struct ib_event *);
- struct list_head list;
-};
-
-#define INIT_IB_EVENT_HANDLER(_ptr, _device, _handler) \
- do { \
- (_ptr)->device = _device; \
- (_ptr)->handler = _handler; \
- INIT_LIST_HEAD(&(_ptr)->list); \
- } while (0)
-
-struct ib_global_route {
- union ib_gid dgid;
- u32 flow_label;
- u8 sgid_index;
- u8 hop_limit;
- u8 traffic_class;
-};
-
-struct ib_grh {
- u32 version_tclass_flow;
- u16 paylen;
- u8 next_hdr;
- u8 hop_limit;
- union ib_gid sgid;
- union ib_gid dgid;
-};
-
-enum {
- IB_MULTICAST_QPN = 0xffffff
-};
-
-enum ib_ah_flags {
- IB_AH_GRH = 1
-};
-
-struct ib_ah_attr {
- struct ib_global_route grh;
- u16 dlid;
- u8 sl;
- u8 src_path_bits;
- u8 static_rate;
- u8 ah_flags;
- u8 port_num;
-};
-
-enum ib_wc_status {
- IB_WC_SUCCESS,
- IB_WC_LOC_LEN_ERR,
- IB_WC_LOC_QP_OP_ERR,
- IB_WC_LOC_EEC_OP_ERR,
- IB_WC_LOC_PROT_ERR,
- IB_WC_WR_FLUSH_ERR,
- IB_WC_MW_BIND_ERR,
- IB_WC_BAD_RESP_ERR,
- IB_WC_LOC_ACCESS_ERR,
- IB_WC_REM_INV_REQ_ERR,
- IB_WC_REM_ACCESS_ERR,
- IB_WC_REM_OP_ERR,
- IB_WC_RETRY_EXC_ERR,
- IB_WC_RNR_RETRY_EXC_ERR,
- IB_WC_LOC_RDD_VIOL_ERR,
- IB_WC_REM_INV_RD_REQ_ERR,
- IB_WC_REM_ABORT_ERR,
- IB_WC_INV_EECN_ERR,
- IB_WC_INV_EEC_STATE_ERR,
- IB_WC_FATAL_ERR,
- IB_WC_RESP_TIMEOUT_ERR,
- IB_WC_GENERAL_ERR
-};
-
-enum ib_wc_opcode {
- IB_WC_SEND,
- IB_WC_RDMA_WRITE,
- IB_WC_RDMA_READ,
- IB_WC_COMP_SWAP,
- IB_WC_FETCH_ADD,
- IB_WC_BIND_MW,
-/*
- * Set value of IB_WC_RECV so consumers can test if a completion is a
- * receive by testing (opcode & IB_WC_RECV).
- */
- IB_WC_RECV = 1 << 7,
- IB_WC_RECV_RDMA_WITH_IMM
-};
-
-enum ib_wc_flags {
- IB_WC_GRH = 1,
- IB_WC_WITH_IMM = (1<<1)
-};
-
-struct ib_wc {
- u64 wr_id;
- enum ib_wc_status status;
- enum ib_wc_opcode opcode;
- u32 vendor_err;
- u32 byte_len;
- __be32 imm_data;
- u32 qp_num;
- u32 src_qp;
- int wc_flags;
- u16 pkey_index;
- u16 slid;
- u8 sl;
- u8 dlid_path_bits;
- u8 port_num; /* valid only for DR SMPs on switches */
-};
-
-enum ib_cq_notify {
- IB_CQ_SOLICITED,
- IB_CQ_NEXT_COMP
-};
-
-struct ib_qp_cap {
- u32 max_send_wr;
- u32 max_recv_wr;
- u32 max_send_sge;
- u32 max_recv_sge;
- u32 max_inline_data;
-};
-
-enum ib_sig_type {
- IB_SIGNAL_ALL_WR,
- IB_SIGNAL_REQ_WR
-};
-
-enum ib_qp_type {
- /*
- * IB_QPT_SMI and IB_QPT_GSI have to be the first two entries
- * here (and in that order) since the MAD layer uses them as
- * indices into a 2-entry table.
- */
- IB_QPT_SMI,
- IB_QPT_GSI,
-
- IB_QPT_RC,
- IB_QPT_UC,
- IB_QPT_UD,
- IB_QPT_RAW_IPV6,
- IB_QPT_RAW_ETY
-};
-
-struct ib_qp_init_attr {
- void (*event_handler)(struct ib_event *, void *);
- void *qp_context;
- struct ib_cq *send_cq;
- struct ib_cq *recv_cq;
- struct ib_srq *srq;
- struct ib_qp_cap cap;
- enum ib_sig_type sq_sig_type;
- enum ib_qp_type qp_type;
- u8 port_num; /* special QP types only */
-};
-
-enum ib_rnr_timeout {
- IB_RNR_TIMER_655_36 = 0,
- IB_RNR_TIMER_000_01 = 1,
- IB_RNR_TIMER_000_02 = 2,
- IB_RNR_TIMER_000_03 = 3,
- IB_RNR_TIMER_000_04 = 4,
- IB_RNR_TIMER_000_06 = 5,
- IB_RNR_TIMER_000_08 = 6,
- IB_RNR_TIMER_000_12 = 7,
- IB_RNR_TIMER_000_16 = 8,
- IB_RNR_TIMER_000_24 = 9,
- IB_RNR_TIMER_000_32 = 10,
- IB_RNR_TIMER_000_48 = 11,
- IB_RNR_TIMER_000_64 = 12,
- IB_RNR_TIMER_000_96 = 13,
- IB_RNR_TIMER_001_28 = 14,
- IB_RNR_TIMER_001_92 = 15,
- IB_RNR_TIMER_002_56 = 16,
- IB_RNR_TIMER_003_84 = 17,
- IB_RNR_TIMER_005_12 = 18,
- IB_RNR_TIMER_007_68 = 19,
- IB_RNR_TIMER_010_24 = 20,
- IB_RNR_TIMER_015_36 = 21,
- IB_RNR_TIMER_020_48 = 22,
- IB_RNR_TIMER_030_72 = 23,
- IB_RNR_TIMER_040_96 = 24,
- IB_RNR_TIMER_061_44 = 25,
- IB_RNR_TIMER_081_92 = 26,
- IB_RNR_TIMER_122_88 = 27,
- IB_RNR_TIMER_163_84 = 28,
- IB_RNR_TIMER_245_76 = 29,
- IB_RNR_TIMER_327_68 = 30,
- IB_RNR_TIMER_491_52 = 31
-};
-
-enum ib_qp_attr_mask {
- IB_QP_STATE = 1,
- IB_QP_CUR_STATE = (1<<1),
- IB_QP_EN_SQD_ASYNC_NOTIFY = (1<<2),
- IB_QP_ACCESS_FLAGS = (1<<3),
- IB_QP_PKEY_INDEX = (1<<4),
- IB_QP_PORT = (1<<5),
- IB_QP_QKEY = (1<<6),
- IB_QP_AV = (1<<7),
- IB_QP_PATH_MTU = (1<<8),
- IB_QP_TIMEOUT = (1<<9),
- IB_QP_RETRY_CNT = (1<<10),
- IB_QP_RNR_RETRY = (1<<11),
- IB_QP_RQ_PSN = (1<<12),
- IB_QP_MAX_QP_RD_ATOMIC = (1<<13),
- IB_QP_ALT_PATH = (1<<14),
- IB_QP_MIN_RNR_TIMER = (1<<15),
- IB_QP_SQ_PSN = (1<<16),
- IB_QP_MAX_DEST_RD_ATOMIC = (1<<17),
- IB_QP_PATH_MIG_STATE = (1<<18),
- IB_QP_CAP = (1<<19),
- IB_QP_DEST_QPN = (1<<20)
-};
-
-enum ib_qp_state {
- IB_QPS_RESET,
- IB_QPS_INIT,
- IB_QPS_RTR,
- IB_QPS_RTS,
- IB_QPS_SQD,
- IB_QPS_SQE,
- IB_QPS_ERR
-};
-
-enum ib_mig_state {
- IB_MIG_MIGRATED,
- IB_MIG_REARM,
- IB_MIG_ARMED
-};
-
-struct ib_qp_attr {
- enum ib_qp_state qp_state;
- enum ib_qp_state cur_qp_state;
- enum ib_mtu path_mtu;
- enum ib_mig_state path_mig_state;
- u32 qkey;
- u32 rq_psn;
- u32 sq_psn;
- u32 dest_qp_num;
- int qp_access_flags;
- struct ib_qp_cap cap;
- struct ib_ah_attr ah_attr;
- struct ib_ah_attr alt_ah_attr;
- u16 pkey_index;
- u16 alt_pkey_index;
- u8 en_sqd_async_notify;
- u8 sq_draining;
- u8 max_rd_atomic;
- u8 max_dest_rd_atomic;
- u8 min_rnr_timer;
- u8 port_num;
- u8 timeout;
- u8 retry_cnt;
- u8 rnr_retry;
- u8 alt_port_num;
- u8 alt_timeout;
-};
-
-enum ib_wr_opcode {
- IB_WR_RDMA_WRITE,
- IB_WR_RDMA_WRITE_WITH_IMM,
- IB_WR_SEND,
- IB_WR_SEND_WITH_IMM,
- IB_WR_RDMA_READ,
- IB_WR_ATOMIC_CMP_AND_SWP,
- IB_WR_ATOMIC_FETCH_AND_ADD
-};
-
-enum ib_send_flags {
- IB_SEND_FENCE = 1,
- IB_SEND_SIGNALED = (1<<1),
- IB_SEND_SOLICITED = (1<<2),
- IB_SEND_INLINE = (1<<3)
-};
-
-struct ib_sge {
- u64 addr;
- u32 length;
- u32 lkey;
-};
-
-struct ib_send_wr {
- struct ib_send_wr *next;
- u64 wr_id;
- struct ib_sge *sg_list;
- int num_sge;
- enum ib_wr_opcode opcode;
- int send_flags;
- __be32 imm_data;
- union {
- struct {
- u64 remote_addr;
- u32 rkey;
- } rdma;
- struct {
- u64 remote_addr;
- u64 compare_add;
- u64 swap;
- u32 rkey;
- } atomic;
- struct {
- struct ib_ah *ah;
- struct ib_mad_hdr *mad_hdr;
- u32 remote_qpn;
- u32 remote_qkey;
- int timeout_ms; /* valid for MADs only */
- int retries; /* valid for MADs only */
- u16 pkey_index; /* valid for GSI only */
- u8 port_num; /* valid for DR SMPs on switch only */
- } ud;
- } wr;
-};
-
-struct ib_recv_wr {
- struct ib_recv_wr *next;
- u64 wr_id;
- struct ib_sge *sg_list;
- int num_sge;
-};
-
-enum ib_access_flags {
- IB_ACCESS_LOCAL_WRITE = 1,
- IB_ACCESS_REMOTE_WRITE = (1<<1),
- IB_ACCESS_REMOTE_READ = (1<<2),
- IB_ACCESS_REMOTE_ATOMIC = (1<<3),
- IB_ACCESS_MW_BIND = (1<<4)
-};
-
-struct ib_phys_buf {
- u64 addr;
- u64 size;
-};
-
-struct ib_mr_attr {
- struct ib_pd *pd;
- u64 device_virt_addr;
- u64 size;
- int mr_access_flags;
- u32 lkey;
- u32 rkey;
-};
-
-enum ib_mr_rereg_flags {
- IB_MR_REREG_TRANS = 1,
- IB_MR_REREG_PD = (1<<1),
- IB_MR_REREG_ACCESS = (1<<2)
-};
-
-struct ib_mw_bind {
- struct ib_mr *mr;
- u64 wr_id;
- u64 addr;
- u32 length;
- int send_flags;
- int mw_access_flags;
-};
-
-struct ib_fmr_attr {
- int max_pages;
- int max_maps;
- u8 page_size;
-};
-
-struct ib_ucontext {
- struct ib_device *device;
- struct list_head pd_list;
- struct list_head mr_list;
- struct list_head mw_list;
- struct list_head cq_list;
- struct list_head qp_list;
- struct list_head srq_list;
- struct list_head ah_list;
- spinlock_t lock;
-};
-
-struct ib_uobject {
- u64 user_handle; /* handle given to us by userspace */
- struct ib_ucontext *context; /* associated user context */
- struct list_head list; /* link to context's list */
- u32 id; /* index into kernel idr */
-};
-
-struct ib_umem {
- unsigned long user_base;
- unsigned long virt_base;
- size_t length;
- int offset;
- int page_size;
- int writable;
- struct list_head chunk_list;
-};
-
-struct ib_umem_chunk {
- struct list_head list;
- int nents;
- int nmap;
- struct scatterlist page_list[0];
-};
-
-struct ib_udata {
- void __user *inbuf;
- void __user *outbuf;
- size_t inlen;
- size_t outlen;
-};
-
-#define IB_UMEM_MAX_PAGE_CHUNK \
- ((PAGE_SIZE - offsetof(struct ib_umem_chunk, page_list)) / \
- ((void *) &((struct ib_umem_chunk *) 0)->page_list[1] - \
- (void *) &((struct ib_umem_chunk *) 0)->page_list[0]))
-
-struct ib_umem_object {
- struct ib_uobject uobject;
- struct ib_umem umem;
-};
-
-struct ib_pd {
- struct ib_device *device;
- struct ib_uobject *uobject;
- atomic_t usecnt; /* count all resources */
-};
-
-struct ib_ah {
- struct ib_device *device;
- struct ib_pd *pd;
- struct ib_uobject *uobject;
-};
-
-typedef void (*ib_comp_handler)(struct ib_cq *cq, void *cq_context);
-
-struct ib_cq {
- struct ib_device *device;
- struct ib_uobject *uobject;
- ib_comp_handler comp_handler;
- void (*event_handler)(struct ib_event *, void *);
- void * cq_context;
- int cqe;
- atomic_t usecnt; /* count number of work queues */
-};
-
-struct ib_srq {
- struct ib_device *device;
- struct ib_uobject *uobject;
- struct ib_pd *pd;
- void *srq_context;
- atomic_t usecnt;
-};
-
-struct ib_qp {
- struct ib_device *device;
- struct ib_pd *pd;
- struct ib_cq *send_cq;
- struct ib_cq *recv_cq;
- struct ib_srq *srq;
- struct ib_uobject *uobject;
- void (*event_handler)(struct ib_event *, void *);
- void *qp_context;
- u32 qp_num;
- enum ib_qp_type qp_type;
-};
-
-struct ib_mr {
- struct ib_device *device;
- struct ib_pd *pd;
- struct ib_uobject *uobject;
- u32 lkey;
- u32 rkey;
- atomic_t usecnt; /* count number of MWs */
-};
-
-struct ib_mw {
- struct ib_device *device;
- struct ib_pd *pd;
- struct ib_uobject *uobject;
- u32 rkey;
-};
-
-struct ib_fmr {
- struct ib_device *device;
- struct ib_pd *pd;
- struct list_head list;
- u32 lkey;
- u32 rkey;
-};
-
-struct ib_mad;
-struct ib_grh;
-
-enum ib_process_mad_flags {
- IB_MAD_IGNORE_MKEY = 1,
- IB_MAD_IGNORE_BKEY = 2,
- IB_MAD_IGNORE_ALL = IB_MAD_IGNORE_MKEY | IB_MAD_IGNORE_BKEY
-};
-
-enum ib_mad_result {
- IB_MAD_RESULT_FAILURE = 0, /* (!SUCCESS is the important flag) */
- IB_MAD_RESULT_SUCCESS = 1 << 0, /* MAD was successfully processed */
- IB_MAD_RESULT_REPLY = 1 << 1, /* Reply packet needs to be sent */
- IB_MAD_RESULT_CONSUMED = 1 << 2 /* Packet consumed: stop processing */
-};
-
-#define IB_DEVICE_NAME_MAX 64
-
-struct ib_cache {
- rwlock_t lock;
- struct ib_event_handler event_handler;
- struct ib_pkey_cache **pkey_cache;
- struct ib_gid_cache **gid_cache;
-};
-
-struct ib_device {
- struct device *dma_device;
-
- char name[IB_DEVICE_NAME_MAX];
-
- struct list_head event_handler_list;
- spinlock_t event_handler_lock;
-
- struct list_head core_list;
- struct list_head client_data_list;
- spinlock_t client_data_lock;
-
- struct ib_cache cache;
-
- u32 flags;
-
- int (*query_device)(struct ib_device *device,
- struct ib_device_attr *device_attr);
- int (*query_port)(struct ib_device *device,
- u8 port_num,
- struct ib_port_attr *port_attr);
- int (*query_gid)(struct ib_device *device,
- u8 port_num, int index,
- union ib_gid *gid);
- int (*query_pkey)(struct ib_device *device,
- u8 port_num, u16 index, u16 *pkey);
- int (*modify_device)(struct ib_device *device,
- int device_modify_mask,
- struct ib_device_modify *device_modify);
- int (*modify_port)(struct ib_device *device,
- u8 port_num, int port_modify_mask,
- struct ib_port_modify *port_modify);
- struct ib_ucontext * (*alloc_ucontext)(struct ib_device *device,
- struct ib_udata *udata);
- int (*dealloc_ucontext)(struct ib_ucontext *context);
- int (*mmap)(struct ib_ucontext *context,
- struct vm_area_struct *vma);
- struct ib_pd * (*alloc_pd)(struct ib_device *device,
- struct ib_ucontext *context,
- struct ib_udata *udata);
- int (*dealloc_pd)(struct ib_pd *pd);
- struct ib_ah * (*create_ah)(struct ib_pd *pd,
- struct ib_ah_attr *ah_attr);
- int (*modify_ah)(struct ib_ah *ah,
- struct ib_ah_attr *ah_attr);
- int (*query_ah)(struct ib_ah *ah,
- struct ib_ah_attr *ah_attr);
- int (*destroy_ah)(struct ib_ah *ah);
- struct ib_qp * (*create_qp)(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr,
- struct ib_udata *udata);
- int (*modify_qp)(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr,
- int qp_attr_mask);
- int (*query_qp)(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr,
- int qp_attr_mask,
- struct ib_qp_init_attr *qp_init_attr);
- int (*destroy_qp)(struct ib_qp *qp);
- int (*post_send)(struct ib_qp *qp,
- struct ib_send_wr *send_wr,
- struct ib_send_wr **bad_send_wr);
- int (*post_recv)(struct ib_qp *qp,
- struct ib_recv_wr *recv_wr,
- struct ib_recv_wr **bad_recv_wr);
- struct ib_cq * (*create_cq)(struct ib_device *device, int cqe,
- struct ib_ucontext *context,
- struct ib_udata *udata);
- int (*destroy_cq)(struct ib_cq *cq);
- int (*resize_cq)(struct ib_cq *cq, int *cqe);
- int (*poll_cq)(struct ib_cq *cq, int num_entries,
- struct ib_wc *wc);
- int (*peek_cq)(struct ib_cq *cq, int wc_cnt);
- int (*req_notify_cq)(struct ib_cq *cq,
- enum ib_cq_notify cq_notify);
- int (*req_ncomp_notif)(struct ib_cq *cq,
- int wc_cnt);
- struct ib_mr * (*get_dma_mr)(struct ib_pd *pd,
- int mr_access_flags);
- struct ib_mr * (*reg_phys_mr)(struct ib_pd *pd,
- struct ib_phys_buf *phys_buf_array,
- int num_phys_buf,
- int mr_access_flags,
- u64 *iova_start);
- struct ib_mr * (*reg_user_mr)(struct ib_pd *pd,
- struct ib_umem *region,
- int mr_access_flags,
- struct ib_udata *udata);
- int (*query_mr)(struct ib_mr *mr,
- struct ib_mr_attr *mr_attr);
- int (*dereg_mr)(struct ib_mr *mr);
- int (*rereg_phys_mr)(struct ib_mr *mr,
- int mr_rereg_mask,
- struct ib_pd *pd,
- struct ib_phys_buf *phys_buf_array,
- int num_phys_buf,
- int mr_access_flags,
- u64 *iova_start);
- struct ib_mw * (*alloc_mw)(struct ib_pd *pd);
- int (*bind_mw)(struct ib_qp *qp,
- struct ib_mw *mw,
- struct ib_mw_bind *mw_bind);
- int (*dealloc_mw)(struct ib_mw *mw);
- struct ib_fmr * (*alloc_fmr)(struct ib_pd *pd,
- int mr_access_flags,
- struct ib_fmr_attr *fmr_attr);
- int (*map_phys_fmr)(struct ib_fmr *fmr,
- u64 *page_list, int list_len,
- u64 iova);
- int (*unmap_fmr)(struct list_head *fmr_list);
- int (*dealloc_fmr)(struct ib_fmr *fmr);
- int (*attach_mcast)(struct ib_qp *qp,
- union ib_gid *gid,
- u16 lid);
- int (*detach_mcast)(struct ib_qp *qp,
- union ib_gid *gid,
- u16 lid);
- int (*process_mad)(struct ib_device *device,
- int process_mad_flags,
- u8 port_num,
- struct ib_wc *in_wc,
- struct ib_grh *in_grh,
- struct ib_mad *in_mad,
- struct ib_mad *out_mad);
-
- struct module *owner;
- struct class_device class_dev;
- struct kobject ports_parent;
- struct list_head port_list;
-
- enum {
- IB_DEV_UNINITIALIZED,
- IB_DEV_REGISTERED,
- IB_DEV_UNREGISTERED
- } reg_state;
-
- u8 node_type;
- u8 phys_port_cnt;
-};
-
-struct ib_client {
- char *name;
- void (*add) (struct ib_device *);
- void (*remove)(struct ib_device *);
-
- struct list_head list;
-};
-
-struct ib_device *ib_alloc_device(size_t size);
-void ib_dealloc_device(struct ib_device *device);
-
-int ib_register_device (struct ib_device *device);
-void ib_unregister_device(struct ib_device *device);
-
-int ib_register_client (struct ib_client *client);
-void ib_unregister_client(struct ib_client *client);
-
-void *ib_get_client_data(struct ib_device *device, struct ib_client *client);
-void ib_set_client_data(struct ib_device *device, struct ib_client *client,
- void *data);
-
-static inline int ib_copy_from_udata(void *dest, struct ib_udata *udata, size_t len)
-{
- return copy_from_user(dest, udata->inbuf, len) ? -EFAULT : 0;
-}
-
-static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len)
-{
- return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0;
-}
-
-int ib_register_event_handler (struct ib_event_handler *event_handler);
-int ib_unregister_event_handler(struct ib_event_handler *event_handler);
-void ib_dispatch_event(struct ib_event *event);
-
-int ib_query_device(struct ib_device *device,
- struct ib_device_attr *device_attr);
-
-int ib_query_port(struct ib_device *device,
- u8 port_num, struct ib_port_attr *port_attr);
-
-int ib_query_gid(struct ib_device *device,
- u8 port_num, int index, union ib_gid *gid);
-
-int ib_query_pkey(struct ib_device *device,
- u8 port_num, u16 index, u16 *pkey);
-
-int ib_modify_device(struct ib_device *device,
- int device_modify_mask,
- struct ib_device_modify *device_modify);
-
-int ib_modify_port(struct ib_device *device,
- u8 port_num, int port_modify_mask,
- struct ib_port_modify *port_modify);
-
-/**
- * ib_alloc_pd - Allocates an unused protection domain.
- * @device: The device on which to allocate the protection domain.
- *
- * A protection domain object provides an association between QPs, shared
- * receive queues, address handles, memory regions, and memory windows.
- */
-struct ib_pd *ib_alloc_pd(struct ib_device *device);
-
-/**
- * ib_dealloc_pd - Deallocates a protection domain.
- * @pd: The protection domain to deallocate.
- */
-int ib_dealloc_pd(struct ib_pd *pd);
-
-/**
- * ib_create_ah - Creates an address handle for the given address vector.
- * @pd: The protection domain associated with the address handle.
- * @ah_attr: The attributes of the address vector.
- *
- * The address handle is used to reference a local or global destination
- * in all UD QP post sends.
- */
-struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
-
-/**
- * ib_create_ah_from_wc - Creates an address handle associated with the
- * sender of the specified work completion.
- * @pd: The protection domain associated with the address handle.
- * @wc: Work completion information associated with a received message.
- * @grh: References the received global route header. This parameter is
- * ignored unless the work completion indicates that the GRH is valid.
- * @port_num: The outbound port number to associate with the address.
- *
- * The address handle is used to reference a local or global destination
- * in all UD QP post sends.
- */
-struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
- struct ib_grh *grh, u8 port_num);
-
-/**
- * ib_modify_ah - Modifies the address vector associated with an address
- * handle.
- * @ah: The address handle to modify.
- * @ah_attr: The new address vector attributes to associate with the
- * address handle.
- */
-int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
-
-/**
- * ib_query_ah - Queries the address vector associated with an address
- * handle.
- * @ah: The address handle to query.
- * @ah_attr: The address vector attributes associated with the address
- * handle.
- */
-int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
-
-/**
- * ib_destroy_ah - Destroys an address handle.
- * @ah: The address handle to destroy.
- */
-int ib_destroy_ah(struct ib_ah *ah);
-
-/**
- * ib_create_qp - Creates a QP associated with the specified protection
- * domain.
- * @pd: The protection domain associated with the QP.
- * @qp_init_attr: A list of initial attributes required to create the QP.
- */
-struct ib_qp *ib_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *qp_init_attr);
-
-/**
- * ib_modify_qp - Modifies the attributes for the specified QP and then
- * transitions the QP to the given state.
- * @qp: The QP to modify.
- * @qp_attr: On input, specifies the QP attributes to modify. On output,
- * the current values of selected QP attributes are returned.
- * @qp_attr_mask: A bit-mask used to specify which attributes of the QP
- * are being modified.
- */
-int ib_modify_qp(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr,
- int qp_attr_mask);
-
-/**
- * ib_query_qp - Returns the attribute list and current values for the
- * specified QP.
- * @qp: The QP to query.
- * @qp_attr: The attributes of the specified QP.
- * @qp_attr_mask: A bit-mask used to select specific attributes to query.
- * @qp_init_attr: Additional attributes of the selected QP.
- *
- * The qp_attr_mask may be used to limit the query to gathering only the
- * selected attributes.
- */
-int ib_query_qp(struct ib_qp *qp,
- struct ib_qp_attr *qp_attr,
- int qp_attr_mask,
- struct ib_qp_init_attr *qp_init_attr);
-
-/**
- * ib_destroy_qp - Destroys the specified QP.
- * @qp: The QP to destroy.
- */
-int ib_destroy_qp(struct ib_qp *qp);
-
-/**
- * ib_post_send - Posts a list of work requests to the send queue of
- * the specified QP.
- * @qp: The QP to post the work request on.
- * @send_wr: A list of work requests to post on the send queue.
- * @bad_send_wr: On an immediate failure, this parameter will reference
- * the work request that failed to be posted on the QP.
- */
-static inline int ib_post_send(struct ib_qp *qp,
- struct ib_send_wr *send_wr,
- struct ib_send_wr **bad_send_wr)
-{
- return qp->device->post_send(qp, send_wr, bad_send_wr);
-}
-
-/**
- * ib_post_recv - Posts a list of work requests to the receive queue of
- * the specified QP.
- * @qp: The QP to post the work request on.
- * @recv_wr: A list of work requests to post on the receive queue.
- * @bad_recv_wr: On an immediate failure, this parameter will reference
- * the work request that failed to be posted on the QP.
- */
-static inline int ib_post_recv(struct ib_qp *qp,
- struct ib_recv_wr *recv_wr,
- struct ib_recv_wr **bad_recv_wr)
-{
- return qp->device->post_recv(qp, recv_wr, bad_recv_wr);
-}
-
-/**
- * ib_create_cq - Creates a CQ on the specified device.
- * @device: The device on which to create the CQ.
- * @comp_handler: A user-specified callback that is invoked when a
- * completion event occurs on the CQ.
- * @event_handler: A user-specified callback that is invoked when an
- * asynchronous event not associated with a completion occurs on the CQ.
- * @cq_context: Context associated with the CQ returned to the user via
- * the associated completion and event handlers.
- * @cqe: The minimum size of the CQ.
- *
- * Users can examine the cq structure to determine the actual CQ size.
- */
-struct ib_cq *ib_create_cq(struct ib_device *device,
- ib_comp_handler comp_handler,
- void (*event_handler)(struct ib_event *, void *),
- void *cq_context, int cqe);
-
-/**
- * ib_resize_cq - Modifies the capacity of the CQ.
- * @cq: The CQ to resize.
- * @cqe: The minimum size of the CQ.
- *
- * Users can examine the cq structure to determine the actual CQ size.
- */
-int ib_resize_cq(struct ib_cq *cq, int cqe);
-
-/**
- * ib_destroy_cq - Destroys the specified CQ.
- * @cq: The CQ to destroy.
- */
-int ib_destroy_cq(struct ib_cq *cq);
-
-/**
- * ib_poll_cq - poll a CQ for completion(s)
- * @cq:the CQ being polled
- * @num_entries:maximum number of completions to return
- * @wc:array of at least @num_entries &struct ib_wc where completions
- * will be returned
- *
- * Poll a CQ for (possibly multiple) completions. If the return value
- * is < 0, an error occurred. If the return value is >= 0, it is the
- * number of completions returned. If the return value is
- * non-negative and < num_entries, then the CQ was emptied.
- */
-static inline int ib_poll_cq(struct ib_cq *cq, int num_entries,
- struct ib_wc *wc)
-{
- return cq->device->poll_cq(cq, num_entries, wc);
-}
-
-/**
- * ib_peek_cq - Returns the number of unreaped completions currently
- * on the specified CQ.
- * @cq: The CQ to peek.
- * @wc_cnt: A minimum number of unreaped completions to check for.
- *
- * If the number of unreaped completions is greater than or equal to wc_cnt,
- * this function returns wc_cnt, otherwise, it returns the actual number of
- * unreaped completions.
- */
-int ib_peek_cq(struct ib_cq *cq, int wc_cnt);
-
-/**
- * ib_req_notify_cq - Request completion notification on a CQ.
- * @cq: The CQ to generate an event for.
- * @cq_notify: If set to %IB_CQ_SOLICITED, completion notification will
- * occur on the next solicited event. If set to %IB_CQ_NEXT_COMP,
- * notification will occur on the next completion.
- */
-static inline int ib_req_notify_cq(struct ib_cq *cq,
- enum ib_cq_notify cq_notify)
-{
- return cq->device->req_notify_cq(cq, cq_notify);
-}
-
-/**
- * ib_req_ncomp_notif - Request completion notification when there are
- * at least the specified number of unreaped completions on the CQ.
- * @cq: The CQ to generate an event for.
- * @wc_cnt: The number of unreaped completions that should be on the
- * CQ before an event is generated.
- */
-static inline int ib_req_ncomp_notif(struct ib_cq *cq, int wc_cnt)
-{
- return cq->device->req_ncomp_notif ?
- cq->device->req_ncomp_notif(cq, wc_cnt) :
- -ENOSYS;
-}
-
-/**
- * ib_get_dma_mr - Returns a memory region for system memory that is
- * usable for DMA.
- * @pd: The protection domain associated with the memory region.
- * @mr_access_flags: Specifies the memory access rights.
- */
-struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags);
-
-/**
- * ib_reg_phys_mr - Prepares a virtually addressed memory region for use
- * by an HCA.
- * @pd: The protection domain associated assigned to the registered region.
- * @phys_buf_array: Specifies a list of physical buffers to use in the
- * memory region.
- * @num_phys_buf: Specifies the size of the phys_buf_array.
- * @mr_access_flags: Specifies the memory access rights.
- * @iova_start: The offset of the region's starting I/O virtual address.
- */
-struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
- struct ib_phys_buf *phys_buf_array,
- int num_phys_buf,
- int mr_access_flags,
- u64 *iova_start);
-
-/**
- * ib_rereg_phys_mr - Modifies the attributes of an existing memory region.
- * Conceptually, this call performs the functions deregister memory region
- * followed by register physical memory region. Where possible,
- * resources are reused instead of deallocated and reallocated.
- * @mr: The memory region to modify.
- * @mr_rereg_mask: A bit-mask used to indicate which of the following
- * properties of the memory region are being modified.
- * @pd: If %IB_MR_REREG_PD is set in mr_rereg_mask, this field specifies
- * the new protection domain to associated with the memory region,
- * otherwise, this parameter is ignored.
- * @phys_buf_array: If %IB_MR_REREG_TRANS is set in mr_rereg_mask, this
- * field specifies a list of physical buffers to use in the new
- * translation, otherwise, this parameter is ignored.
- * @num_phys_buf: If %IB_MR_REREG_TRANS is set in mr_rereg_mask, this
- * field specifies the size of the phys_buf_array, otherwise, this
- * parameter is ignored.
- * @mr_access_flags: If %IB_MR_REREG_ACCESS is set in mr_rereg_mask, this
- * field specifies the new memory access rights, otherwise, this
- * parameter is ignored.
- * @iova_start: The offset of the region's starting I/O virtual address.
- */
-int ib_rereg_phys_mr(struct ib_mr *mr,
- int mr_rereg_mask,
- struct ib_pd *pd,
- struct ib_phys_buf *phys_buf_array,
- int num_phys_buf,
- int mr_access_flags,
- u64 *iova_start);
-
-/**
- * ib_query_mr - Retrieves information about a specific memory region.
- * @mr: The memory region to retrieve information about.
- * @mr_attr: The attributes of the specified memory region.
- */
-int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr);
-
-/**
- * ib_dereg_mr - Deregisters a memory region and removes it from the
- * HCA translation table.
- * @mr: The memory region to deregister.
- */
-int ib_dereg_mr(struct ib_mr *mr);
-
-/**
- * ib_alloc_mw - Allocates a memory window.
- * @pd: The protection domain associated with the memory window.
- */
-struct ib_mw *ib_alloc_mw(struct ib_pd *pd);
-
-/**
- * ib_bind_mw - Posts a work request to the send queue of the specified
- * QP, which binds the memory window to the given address range and
- * remote access attributes.
- * @qp: QP to post the bind work request on.
- * @mw: The memory window to bind.
- * @mw_bind: Specifies information about the memory window, including
- * its address range, remote access rights, and associated memory region.
- */
-static inline int ib_bind_mw(struct ib_qp *qp,
- struct ib_mw *mw,
- struct ib_mw_bind *mw_bind)
-{
- /* XXX reference counting in corresponding MR? */
- return mw->device->bind_mw ?
- mw->device->bind_mw(qp, mw, mw_bind) :
- -ENOSYS;
-}
-
-/**
- * ib_dealloc_mw - Deallocates a memory window.
- * @mw: The memory window to deallocate.
- */
-int ib_dealloc_mw(struct ib_mw *mw);
-
-/**
- * ib_alloc_fmr - Allocates a unmapped fast memory region.
- * @pd: The protection domain associated with the unmapped region.
- * @mr_access_flags: Specifies the memory access rights.
- * @fmr_attr: Attributes of the unmapped region.
- *
- * A fast memory region must be mapped before it can be used as part of
- * a work request.
- */
-struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd,
- int mr_access_flags,
- struct ib_fmr_attr *fmr_attr);
-
-/**
- * ib_map_phys_fmr - Maps a list of physical pages to a fast memory region.
- * @fmr: The fast memory region to associate with the pages.
- * @page_list: An array of physical pages to map to the fast memory region.
- * @list_len: The number of pages in page_list.
- * @iova: The I/O virtual address to use with the mapped region.
- */
-static inline int ib_map_phys_fmr(struct ib_fmr *fmr,
- u64 *page_list, int list_len,
- u64 iova)
-{
- return fmr->device->map_phys_fmr(fmr, page_list, list_len, iova);
-}
-
-/**
- * ib_unmap_fmr - Removes the mapping from a list of fast memory regions.
- * @fmr_list: A linked list of fast memory regions to unmap.
- */
-int ib_unmap_fmr(struct list_head *fmr_list);
-
-/**
- * ib_dealloc_fmr - Deallocates a fast memory region.
- * @fmr: The fast memory region to deallocate.
- */
-int ib_dealloc_fmr(struct ib_fmr *fmr);
-
-/**
- * ib_attach_mcast - Attaches the specified QP to a multicast group.
- * @qp: QP to attach to the multicast group. The QP must be type
- * IB_QPT_UD.
- * @gid: Multicast group GID.
- * @lid: Multicast group LID in host byte order.
- *
- * In order to send and receive multicast packets, subnet
- * administration must have created the multicast group and configured
- * the fabric appropriately. The port associated with the specified
- * QP must also be a member of the multicast group.
- */
-int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
-
-/**
- * ib_detach_mcast - Detaches the specified QP from a multicast group.
- * @qp: QP to detach from the multicast group.
- * @gid: Multicast group GID.
- * @lid: Multicast group LID in host byte order.
- */
-int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
-
-#endif /* IB_VERBS_H */
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
index 394bc08abc6f..8935e74ae3f8 100644
--- a/drivers/infiniband/ulp/ipoib/Makefile
+++ b/drivers/infiniband/ulp/ipoib/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -Idrivers/infiniband/include
-
obj-$(CONFIG_INFINIBAND_IPOIB) += ib_ipoib.o
ib_ipoib-y := ipoib_main.o \
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 04c98f54e9c4..0095acc0fbbe 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -49,9 +51,9 @@
#include <asm/atomic.h>
#include <asm/semaphore.h>
-#include <ib_verbs.h>
-#include <ib_pack.h>
-#include <ib_sa.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_sa.h>
/* constants */
@@ -88,8 +90,8 @@ enum {
/* structs */
struct ipoib_header {
- u16 proto;
- u16 reserved;
+ __be16 proto;
+ u16 reserved;
};
struct ipoib_pseudoheader {
@@ -98,7 +100,12 @@ struct ipoib_pseudoheader {
struct ipoib_mcast;
-struct ipoib_buf {
+struct ipoib_rx_buf {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+};
+
+struct ipoib_tx_buf {
struct sk_buff *skb;
DECLARE_PCI_UNMAP_ADDR(mapping)
};
@@ -148,14 +155,14 @@ struct ipoib_dev_priv {
unsigned int admin_mtu;
unsigned int mcast_mtu;
- struct ipoib_buf *rx_ring;
+ struct ipoib_rx_buf *rx_ring;
- spinlock_t tx_lock;
- struct ipoib_buf *tx_ring;
- unsigned tx_head;
- unsigned tx_tail;
- struct ib_sge tx_sge;
- struct ib_send_wr tx_wr;
+ spinlock_t tx_lock;
+ struct ipoib_tx_buf *tx_ring;
+ unsigned tx_head;
+ unsigned tx_tail;
+ struct ib_sge tx_sge;
+ struct ib_send_wr tx_wr;
struct ib_wc ibwc[IPOIB_NUM_WC];
@@ -228,6 +235,7 @@ static inline void ipoib_put_ah(struct ipoib_ah *ah)
kref_put(&ah->ref, ipoib_free_ah);
}
+int ipoib_open(struct net_device *dev);
int ipoib_add_pkey_attr(struct net_device *dev);
void ipoib_send(struct net_device *dev, struct sk_buff *skb,
@@ -255,11 +263,12 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
void ipoib_mcast_restart_task(void *dev_ptr);
int ipoib_mcast_start_thread(struct net_device *dev);
-int ipoib_mcast_stop_thread(struct net_device *dev);
+int ipoib_mcast_stop_thread(struct net_device *dev, int flush);
void ipoib_mcast_dev_down(struct net_device *dev);
void ipoib_mcast_dev_flush(struct net_device *dev);
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev);
void ipoib_mcast_iter_free(struct ipoib_mcast_iter *iter);
int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter);
@@ -269,13 +278,14 @@ void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,
unsigned int *queuelen,
unsigned int *complete,
unsigned int *send_only);
+#endif
int ipoib_mcast_attach(struct net_device *dev, u16 mlid,
union ib_gid *mgid);
int ipoib_mcast_detach(struct net_device *dev, u16 mlid,
union ib_gid *mgid);
-int ipoib_qp_create(struct net_device *dev);
+int ipoib_init_qp(struct net_device *dev);
int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca);
void ipoib_transport_dev_cleanup(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index a84e5fe0f193..38b150f775e7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -97,7 +97,7 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
for (n = 0, i = 0; i < sizeof mgid / 2; ++i) {
n += sprintf(gid_buf + n, "%x",
- be16_to_cpu(((u16 *)mgid.raw)[i]));
+ be16_to_cpu(((__be16 *) mgid.raw)[i]));
if (i < sizeof mgid / 2 - 1)
gid_buf[n++] = ':';
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index eee82363167d..54ef2fea530f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -1,5 +1,8 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2004, 2005 Voltaire, 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 +38,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "ipoib.h"
@@ -92,57 +95,65 @@ void ipoib_free_ah(struct kref *kref)
}
}
-static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv,
- unsigned int wr_id,
- dma_addr_t addr)
+static int ipoib_ib_post_receive(struct net_device *dev, int id)
{
- struct ib_sge list = {
- .addr = addr,
- .length = IPOIB_BUF_SIZE,
- .lkey = priv->mr->lkey,
- };
- struct ib_recv_wr param = {
- .wr_id = wr_id | IPOIB_OP_RECV,
- .sg_list = &list,
- .num_sge = 1,
- };
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_sge list;
+ struct ib_recv_wr param;
struct ib_recv_wr *bad_wr;
+ int ret;
+
+ list.addr = priv->rx_ring[id].mapping;
+ list.length = IPOIB_BUF_SIZE;
+ list.lkey = priv->mr->lkey;
+
+ param.next = NULL;
+ param.wr_id = id | IPOIB_OP_RECV;
+ param.sg_list = &list;
+ param.num_sge = 1;
+
+ ret = ib_post_recv(priv->qp, &param, &bad_wr);
+ if (unlikely(ret)) {
+ ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
+ dma_unmap_single(priv->ca->dma_device,
+ priv->rx_ring[id].mapping,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ dev_kfree_skb_any(priv->rx_ring[id].skb);
+ priv->rx_ring[id].skb = NULL;
+ }
- return ib_post_recv(priv->qp, &param, &bad_wr);
+ return ret;
}
-static int ipoib_ib_post_receive(struct net_device *dev, int id)
+static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct sk_buff *skb;
dma_addr_t addr;
- int ret;
skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
- if (!skb) {
- ipoib_warn(priv, "failed to allocate receive buffer\n");
-
- priv->rx_ring[id].skb = NULL;
+ if (!skb)
return -ENOMEM;
- }
- skb_reserve(skb, 4); /* 16 byte align IP header */
- priv->rx_ring[id].skb = skb;
+
+ /*
+ * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
+ * header. So we need 4 more bytes to get to 48 and align the
+ * IP header to a multiple of 16.
+ */
+ skb_reserve(skb, 4);
+
addr = dma_map_single(priv->ca->dma_device,
skb->data, IPOIB_BUF_SIZE,
DMA_FROM_DEVICE);
- pci_unmap_addr_set(&priv->rx_ring[id], mapping, addr);
-
- ret = ipoib_ib_receive(priv, id, addr);
- if (ret) {
- ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n",
- id, ret);
- dma_unmap_single(priv->ca->dma_device, addr,
- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(addr))) {
dev_kfree_skb_any(skb);
- priv->rx_ring[id].skb = NULL;
+ return -EIO;
}
- return ret;
+ priv->rx_ring[id].skb = skb;
+ priv->rx_ring[id].mapping = addr;
+
+ return 0;
}
static int ipoib_ib_post_receives(struct net_device *dev)
@@ -151,6 +162,10 @@ static int ipoib_ib_post_receives(struct net_device *dev)
int i;
for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+ if (ipoib_alloc_rx_skb(dev, i)) {
+ ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+ return -ENOMEM;
+ }
if (ipoib_ib_post_receive(dev, i)) {
ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i);
return -EIO;
@@ -173,28 +188,36 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
wr_id &= ~IPOIB_OP_RECV;
if (wr_id < IPOIB_RX_RING_SIZE) {
- struct sk_buff *skb = priv->rx_ring[wr_id].skb;
+ struct sk_buff *skb = priv->rx_ring[wr_id].skb;
+ dma_addr_t addr = priv->rx_ring[wr_id].mapping;
- priv->rx_ring[wr_id].skb = NULL;
-
- dma_unmap_single(priv->ca->dma_device,
- pci_unmap_addr(&priv->rx_ring[wr_id],
- mapping),
- IPOIB_BUF_SIZE,
- DMA_FROM_DEVICE);
-
- if (wc->status != IB_WC_SUCCESS) {
+ if (unlikely(wc->status != IB_WC_SUCCESS)) {
if (wc->status != IB_WC_WR_FLUSH_ERR)
ipoib_warn(priv, "failed recv event "
"(status=%d, wrid=%d vend_err %x)\n",
wc->status, wr_id, wc->vendor_err);
+ dma_unmap_single(priv->ca->dma_device, addr,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
+ priv->rx_ring[wr_id].skb = NULL;
return;
}
+ /*
+ * If we can't allocate a new RX buffer, dump
+ * this packet and reuse the old buffer.
+ */
+ if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) {
+ ++priv->stats.rx_dropped;
+ goto repost;
+ }
+
ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
wc->byte_len, wc->slid);
+ dma_unmap_single(priv->ca->dma_device, addr,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+
skb_put(skb, wc->byte_len);
skb_pull(skb, IB_GRH_BYTES);
@@ -217,8 +240,8 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
dev_kfree_skb_any(skb);
}
- /* repost receive */
- if (ipoib_ib_post_receive(dev, wr_id))
+ repost:
+ if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
ipoib_warn(priv, "ipoib_ib_post_receive failed "
"for buf %d\n", wr_id);
} else
@@ -226,7 +249,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
wr_id);
} else {
- struct ipoib_buf *tx_req;
+ struct ipoib_tx_buf *tx_req;
unsigned long flags;
if (wr_id >= IPOIB_TX_RING_SIZE) {
@@ -299,7 +322,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
struct ipoib_ah *address, u32 qpn)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_buf *tx_req;
+ struct ipoib_tx_buf *tx_req;
dma_addr_t addr;
if (skb->len > dev->mtu + INFINIBAND_ALEN) {
@@ -384,9 +407,9 @@ int ipoib_ib_dev_open(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
- ret = ipoib_qp_create(dev);
+ ret = ipoib_init_qp(dev);
if (ret) {
- ipoib_warn(priv, "ipoib_qp_create returned %d\n", ret);
+ ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
return -1;
}
@@ -429,7 +452,7 @@ int ipoib_ib_dev_down(struct net_device *dev)
flush_workqueue(ipoib_workqueue);
}
- ipoib_mcast_stop_thread(dev);
+ ipoib_mcast_stop_thread(dev, 1);
/*
* Flush the multicast groups first so we stop any multicast joins. The
@@ -463,15 +486,16 @@ int ipoib_ib_dev_stop(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_attr qp_attr;
- int attr_mask;
unsigned long begin;
- struct ipoib_buf *tx_req;
+ struct ipoib_tx_buf *tx_req;
int i;
- /* Kill the existing QP and allocate a new one */
+ /*
+ * Move our QP to the error state and then reinitialize in
+ * when all work requests have completed or have been flushed.
+ */
qp_attr.qp_state = IB_QPS_ERR;
- attr_mask = IB_QP_STATE;
- if (ib_modify_qp(priv->qp, &qp_attr, attr_mask))
+ if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
ipoib_warn(priv, "Failed to modify QP to ERROR state\n");
/* Wait for all sends and receives to complete */
@@ -518,8 +542,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
timeout:
qp_attr.qp_state = IB_QPS_RESET;
- attr_mask = IB_QP_STATE;
- if (ib_modify_qp(priv->qp, &qp_attr, attr_mask))
+ if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
ipoib_warn(priv, "Failed to modify QP to RESET state\n");
/* Wait for all AHs to be reaped */
@@ -596,7 +619,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
ipoib_dbg(priv, "cleaning up ib_dev\n");
- ipoib_mcast_stop_thread(dev);
+ ipoib_mcast_stop_thread(dev, 1);
/* Delete the broadcast address and the local address */
ipoib_mcast_dev_down(dev);
@@ -613,7 +636,6 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
* Bug #2507. This implementation will probably be removed when the P_Key
* change async notification is available.
*/
-int ipoib_open(struct net_device *dev);
static void ipoib_pkey_dev_check_presence(struct net_device *dev)
{
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 6f60abbaebd5..ce0296273e76 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -34,7 +36,6 @@
#include "ipoib.h"
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -355,18 +356,15 @@ static struct ipoib_path *path_rec_create(struct net_device *dev,
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
- path = kmalloc(sizeof *path, GFP_ATOMIC);
+ path = kzalloc(sizeof *path, GFP_ATOMIC);
if (!path)
return NULL;
- path->dev = dev;
- path->pathrec.dlid = 0;
- path->ah = NULL;
+ path->dev = dev;
skb_queue_head_init(&path->queue);
INIT_LIST_HEAD(&path->neigh_list);
- path->query = NULL;
init_completion(&path->done);
memcpy(path->pathrec.dgid.raw, gid->raw, sizeof (union ib_gid));
@@ -473,7 +471,7 @@ err:
spin_unlock(&priv->lock);
}
-static void path_lookup(struct sk_buff *skb, struct net_device *dev)
+static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
@@ -550,11 +548,8 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct ipoib_neigh *neigh;
unsigned long flags;
- local_irq_save(flags);
- if (!spin_trylock(&priv->tx_lock)) {
- local_irq_restore(flags);
+ if (!spin_trylock_irqsave(&priv->tx_lock, flags))
return NETDEV_TX_LOCKED;
- }
/*
* Check if our queue is stopped. Since we have the LLTX bit
@@ -568,7 +563,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->dst && skb->dst->neighbour) {
if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
- path_lookup(skb, dev);
+ ipoib_path_lookup(skb, dev);
goto out;
}
@@ -600,14 +595,15 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
} else {
- /* unicast GID -- should be ARP reply */
+ /* unicast GID -- should be ARP or RARP reply */
- if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) {
+ if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
+ (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x "
IPOIB_GID_FMT "\n",
skb->dst ? "neigh" : "dst",
- be16_to_cpup((u16 *) skb->data),
- be32_to_cpup((u32 *) phdr->hwaddr),
+ be16_to_cpup((__be16 *) skb->data),
+ be32_to_cpup((__be32 *) phdr->hwaddr),
IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4)));
dev_kfree_skb_any(skb);
++priv->stats.tx_dropped;
@@ -635,8 +631,11 @@ static void ipoib_timeout(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- ipoib_warn(priv, "transmit timeout: latency %ld\n",
- jiffies - dev->trans_start);
+ ipoib_warn(priv, "transmit timeout: latency %d msecs\n",
+ jiffies_to_msecs(jiffies - dev->trans_start));
+ ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n",
+ netif_queue_stopped(dev),
+ priv->tx_head, priv->tx_tail);
/* XXX reset QP, etc. */
}
@@ -670,7 +669,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- schedule_work(&priv->restart_task);
+ queue_work(ipoib_workqueue, &priv->restart_task);
}
static void ipoib_neigh_destructor(struct neighbour *n)
@@ -727,25 +726,21 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
/* Allocate RX/TX "rings" to hold queued skbs */
- priv->rx_ring = kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf),
+ priv->rx_ring = kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
GFP_KERNEL);
if (!priv->rx_ring) {
printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
ca->name, IPOIB_RX_RING_SIZE);
goto out;
}
- memset(priv->rx_ring, 0,
- IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf));
- priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf),
+ priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
GFP_KERNEL);
if (!priv->tx_ring) {
printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
ca->name, IPOIB_TX_RING_SIZE);
goto out_rx_ring_cleanup;
}
- memset(priv->tx_ring, 0,
- IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf));
/* priv->tx_head & tx_tail are already 0 */
@@ -779,15 +774,11 @@ void ipoib_dev_cleanup(struct net_device *dev)
ipoib_ib_dev_cleanup(dev);
- if (priv->rx_ring) {
- kfree(priv->rx_ring);
- priv->rx_ring = NULL;
- }
+ kfree(priv->rx_ring);
+ kfree(priv->tx_ring);
- if (priv->tx_ring) {
- kfree(priv->tx_ring);
- priv->tx_ring = NULL;
- }
+ priv->rx_ring = NULL;
+ priv->tx_ring = NULL;
}
static void ipoib_setup(struct net_device *dev)
@@ -806,10 +797,6 @@ static void ipoib_setup(struct net_device *dev)
dev->watchdog_timeo = HZ;
- dev->rebuild_header = NULL;
- dev->set_mac_address = NULL;
- dev->header_cache_update = NULL;
-
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
/*
@@ -885,6 +872,12 @@ static ssize_t create_child(struct class_device *cdev,
if (pkey < 0 || pkey > 0xffff)
return -EINVAL;
+ /*
+ * Set the full membership bit, so that we join the right
+ * broadcast group, etc.
+ */
+ pkey |= 0x8000;
+
ret = ipoib_vlan_add(container_of(cdev, struct net_device, class_dev),
pkey);
@@ -937,6 +930,12 @@ static struct net_device *ipoib_add_port(const char *format,
goto alloc_mem_failed;
}
+ /*
+ * Set the full membership bit, so that we join the right
+ * broadcast group, etc.
+ */
+ priv->pkey |= 0x8000;
+
priv->dev->broadcast[8] = priv->pkey >> 8;
priv->dev->broadcast[9] = priv->pkey & 0xff;
@@ -995,6 +994,7 @@ debug_failed:
register_failed:
ib_unregister_event_handler(&priv->event_handler);
+ flush_scheduled_work();
event_failed:
ipoib_dev_cleanup(priv->dev);
@@ -1047,11 +1047,14 @@ static void ipoib_remove_one(struct ib_device *device)
list_for_each_entry_safe(priv, tmp, dev_list, list) {
ib_unregister_event_handler(&priv->event_handler);
+ flush_scheduled_work();
unregister_netdev(priv->dev);
ipoib_dev_cleanup(priv->dev);
free_netdev(priv->dev);
}
+
+ kfree(dev_list);
}
static int __init ipoib_init_module(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 70208c3d21e2..3ecf78a9493a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2004 Voltaire, 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
@@ -133,17 +135,15 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
{
struct ipoib_mcast *mcast;
- mcast = kmalloc(sizeof (*mcast), can_sleep ? GFP_KERNEL : GFP_ATOMIC);
+ mcast = kzalloc(sizeof *mcast, can_sleep ? GFP_KERNEL : GFP_ATOMIC);
if (!mcast)
return NULL;
- memset(mcast, 0, sizeof (*mcast));
-
init_completion(&mcast->done);
mcast->dev = dev;
mcast->created = jiffies;
- mcast->backoff = HZ;
+ mcast->backoff = 1;
mcast->logcount = 0;
INIT_LIST_HEAD(&mcast->list);
@@ -357,7 +357,7 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec,
IB_SA_MCMEMBER_REC_MGID |
@@ -394,7 +394,7 @@ static void ipoib_mcast_join_complete(int status,
IPOIB_GID_ARG(mcast->mcmember.mgid), status);
if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
- mcast->backoff = HZ;
+ mcast->backoff = 1;
down(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -457,7 +457,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
comp_mask =
IB_SA_MCMEMBER_REC_MGID |
@@ -494,7 +494,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task,
- mcast->backoff);
+ mcast->backoff * HZ);
up(&mcast_mutex);
} else
mcast->query_id = ret;
@@ -596,7 +596,7 @@ int ipoib_mcast_start_thread(struct net_device *dev)
return 0;
}
-int ipoib_mcast_stop_thread(struct net_device *dev)
+int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_mcast *mcast;
@@ -608,7 +608,8 @@ int ipoib_mcast_stop_thread(struct net_device *dev)
cancel_delayed_work(&priv->mcast_task);
up(&mcast_mutex);
- flush_workqueue(ipoib_workqueue);
+ if (flush)
+ flush_workqueue(ipoib_workqueue);
if (priv->broadcast && priv->broadcast->query) {
ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
@@ -646,7 +647,7 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
rec.mgid = mcast->mcmember.mgid;
rec.port_gid = priv->local_gid;
- rec.pkey = be16_to_cpu(priv->pkey);
+ rec.pkey = cpu_to_be16(priv->pkey);
/* Remove ourselves from the multicast group */
ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
@@ -830,7 +831,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
ipoib_dbg_mcast(priv, "restarting multicast task\n");
- ipoib_mcast_stop_thread(dev);
+ ipoib_mcast_stop_thread(dev, 0);
spin_lock_irqsave(&priv->lock, flags);
@@ -916,6 +917,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
ipoib_mcast_start_thread(dev);
}
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+
struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev)
{
struct ipoib_mcast_iter *iter;
@@ -988,3 +991,5 @@ void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,
*complete = iter->complete;
*send_only = iter->send_only;
}
+
+#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 4933edf062c2..e829e10400e3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. 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
@@ -32,7 +33,7 @@
* $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <ib_cache.h>
+#include <rdma/ib_cache.h>
#include "ipoib.h"
@@ -40,7 +41,6 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_attr *qp_attr;
- int attr_mask;
int ret;
u16 pkey_index;
@@ -58,8 +58,7 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
/* set correct QKey for QP */
qp_attr->qkey = priv->qkey;
- attr_mask = IB_QP_QKEY;
- ret = ib_modify_qp(priv->qp, qp_attr, attr_mask);
+ ret = ib_modify_qp(priv->qp, qp_attr, IB_QP_QKEY);
if (ret) {
ipoib_warn(priv, "failed to modify QP, ret = %d\n", ret);
goto out;
@@ -91,7 +90,7 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
return ret;
}
-int ipoib_qp_create(struct net_device *dev)
+int ipoib_init_qp(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
@@ -148,10 +147,11 @@ int ipoib_qp_create(struct net_device *dev)
return 0;
out_fail:
- ib_destroy_qp(priv->qp);
- priv->qp = NULL;
+ qp_attr.qp_state = IB_QPS_RESET;
+ if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
+ ipoib_warn(priv, "Failed to modify QP to RESET state\n");
- return -EINVAL;
+ return ret;
}
int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 94b8ea812fef..332d730e60c2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -32,7 +32,6 @@
* $Id: ipoib_vlan.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/infiniband/ulp/srp/Kbuild b/drivers/infiniband/ulp/srp/Kbuild
new file mode 100644
index 000000000000..a16c73c667cb
--- /dev/null
+++ b/drivers/infiniband/ulp/srp/Kbuild
@@ -0,0 +1 @@
+obj-$(CONFIG_INFINIBAND_SRP) += ib_srp.o
diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig
new file mode 100644
index 000000000000..8fe3be4e9910
--- /dev/null
+++ b/drivers/infiniband/ulp/srp/Kconfig
@@ -0,0 +1,11 @@
+config INFINIBAND_SRP
+ tristate "InfiniBand SCSI RDMA Protocol"
+ depends on INFINIBAND && SCSI
+ ---help---
+ Support for the SCSI RDMA Protocol over InfiniBand. This
+ allows you to access storage devices that speak SRP over
+ InfiniBand.
+
+ The SRP protocol is defined by the INCITS T10 technical
+ committee. See <http://www.t10.org/>.
+
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
new file mode 100644
index 000000000000..2687e34aa5bc
--- /dev/null
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -0,0 +1,1700 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, 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.
+ *
+ * - 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.
+ *
+ * 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.
+ *
+ * $Id: ib_srp.c 3932 2005-11-01 17:19:29Z roland $
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/parser.h>
+#include <linux/random.h>
+
+#include <asm/atomic.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/srp.h>
+
+#include <rdma/ib_cache.h>
+
+#include "ib_srp.h"
+
+#define DRV_NAME "ib_srp"
+#define PFX DRV_NAME ": "
+#define DRV_VERSION "0.2"
+#define DRV_RELDATE "November 1, 2005"
+
+MODULE_AUTHOR("Roland Dreier");
+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator "
+ "v" DRV_VERSION " (" DRV_RELDATE ")");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static int topspin_workarounds = 1;
+
+module_param(topspin_workarounds, int, 0444);
+MODULE_PARM_DESC(topspin_workarounds,
+ "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
+
+static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
+
+static void srp_add_one(struct ib_device *device);
+static void srp_remove_one(struct ib_device *device);
+static void srp_completion(struct ib_cq *cq, void *target_ptr);
+static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
+
+static struct ib_client srp_client = {
+ .name = "srp",
+ .add = srp_add_one,
+ .remove = srp_remove_one
+};
+
+static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
+{
+ return (struct srp_target_port *) host->hostdata;
+}
+
+static const char *srp_target_info(struct Scsi_Host *host)
+{
+ return host_to_target(host)->target_name;
+}
+
+static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
+ gfp_t gfp_mask,
+ enum dma_data_direction direction)
+{
+ struct srp_iu *iu;
+
+ iu = kmalloc(sizeof *iu, gfp_mask);
+ if (!iu)
+ goto out;
+
+ iu->buf = kzalloc(size, gfp_mask);
+ if (!iu->buf)
+ goto out_free_iu;
+
+ iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction);
+ if (dma_mapping_error(iu->dma))
+ goto out_free_buf;
+
+ iu->size = size;
+ iu->direction = direction;
+
+ return iu;
+
+out_free_buf:
+ kfree(iu->buf);
+out_free_iu:
+ kfree(iu);
+out:
+ return NULL;
+}
+
+static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
+{
+ if (!iu)
+ return;
+
+ dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction);
+ kfree(iu->buf);
+ kfree(iu);
+}
+
+static void srp_qp_event(struct ib_event *event, void *context)
+{
+ printk(KERN_ERR PFX "QP event %d\n", event->event);
+}
+
+static int srp_init_qp(struct srp_target_port *target,
+ struct ib_qp *qp)
+{
+ struct ib_qp_attr *attr;
+ int ret;
+
+ attr = kmalloc(sizeof *attr, GFP_KERNEL);
+ if (!attr)
+ return -ENOMEM;
+
+ ret = ib_find_cached_pkey(target->srp_host->dev,
+ target->srp_host->port,
+ be16_to_cpu(target->path.pkey),
+ &attr->pkey_index);
+ if (ret)
+ goto out;
+
+ attr->qp_state = IB_QPS_INIT;
+ attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE);
+ attr->port_num = target->srp_host->port;
+
+ ret = ib_modify_qp(qp, attr,
+ IB_QP_STATE |
+ IB_QP_PKEY_INDEX |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PORT);
+
+out:
+ kfree(attr);
+ return ret;
+}
+
+static int srp_create_target_ib(struct srp_target_port *target)
+{
+ struct ib_qp_init_attr *init_attr;
+ int ret;
+
+ init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
+ if (!init_attr)
+ return -ENOMEM;
+
+ target->cq = ib_create_cq(target->srp_host->dev, srp_completion,
+ NULL, target, SRP_CQ_SIZE);
+ if (IS_ERR(target->cq)) {
+ ret = PTR_ERR(target->cq);
+ goto out;
+ }
+
+ ib_req_notify_cq(target->cq, IB_CQ_NEXT_COMP);
+
+ init_attr->event_handler = srp_qp_event;
+ init_attr->cap.max_send_wr = SRP_SQ_SIZE;
+ init_attr->cap.max_recv_wr = SRP_RQ_SIZE;
+ init_attr->cap.max_recv_sge = 1;
+ init_attr->cap.max_send_sge = 1;
+ init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
+ init_attr->qp_type = IB_QPT_RC;
+ init_attr->send_cq = target->cq;
+ init_attr->recv_cq = target->cq;
+
+ target->qp = ib_create_qp(target->srp_host->pd, init_attr);
+ if (IS_ERR(target->qp)) {
+ ret = PTR_ERR(target->qp);
+ ib_destroy_cq(target->cq);
+ goto out;
+ }
+
+ ret = srp_init_qp(target, target->qp);
+ if (ret) {
+ ib_destroy_qp(target->qp);
+ ib_destroy_cq(target->cq);
+ goto out;
+ }
+
+out:
+ kfree(init_attr);
+ return ret;
+}
+
+static void srp_free_target_ib(struct srp_target_port *target)
+{
+ int i;
+
+ ib_destroy_qp(target->qp);
+ ib_destroy_cq(target->cq);
+
+ for (i = 0; i < SRP_RQ_SIZE; ++i)
+ srp_free_iu(target->srp_host, target->rx_ring[i]);
+ for (i = 0; i < SRP_SQ_SIZE + 1; ++i)
+ srp_free_iu(target->srp_host, target->tx_ring[i]);
+}
+
+static void srp_path_rec_completion(int status,
+ struct ib_sa_path_rec *pathrec,
+ void *target_ptr)
+{
+ struct srp_target_port *target = target_ptr;
+
+ target->status = status;
+ if (status)
+ printk(KERN_ERR PFX "Got failed path rec status %d\n", status);
+ else
+ target->path = *pathrec;
+ complete(&target->done);
+}
+
+static int srp_lookup_path(struct srp_target_port *target)
+{
+ target->path.numb_path = 1;
+
+ init_completion(&target->done);
+
+ target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev,
+ target->srp_host->port,
+ &target->path,
+ IB_SA_PATH_REC_DGID |
+ IB_SA_PATH_REC_SGID |
+ IB_SA_PATH_REC_NUMB_PATH |
+ IB_SA_PATH_REC_PKEY,
+ SRP_PATH_REC_TIMEOUT_MS,
+ GFP_KERNEL,
+ srp_path_rec_completion,
+ target, &target->path_query);
+ if (target->path_query_id < 0)
+ return target->path_query_id;
+
+ wait_for_completion(&target->done);
+
+ if (target->status < 0)
+ printk(KERN_WARNING PFX "Path record query failed\n");
+
+ return target->status;
+}
+
+static int srp_send_req(struct srp_target_port *target)
+{
+ struct {
+ struct ib_cm_req_param param;
+ struct srp_login_req priv;
+ } *req = NULL;
+ int status;
+
+ req = kzalloc(sizeof *req, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->param.primary_path = &target->path;
+ req->param.alternate_path = NULL;
+ req->param.service_id = target->service_id;
+ req->param.qp_num = target->qp->qp_num;
+ req->param.qp_type = target->qp->qp_type;
+ req->param.private_data = &req->priv;
+ req->param.private_data_len = sizeof req->priv;
+ req->param.flow_control = 1;
+
+ get_random_bytes(&req->param.starting_psn, 4);
+ req->param.starting_psn &= 0xffffff;
+
+ /*
+ * Pick some arbitrary defaults here; we could make these
+ * module parameters if anyone cared about setting them.
+ */
+ req->param.responder_resources = 4;
+ req->param.remote_cm_response_timeout = 20;
+ req->param.local_cm_response_timeout = 20;
+ req->param.retry_count = 7;
+ req->param.rnr_retry_count = 7;
+ req->param.max_cm_retries = 15;
+
+ req->priv.opcode = SRP_LOGIN_REQ;
+ req->priv.tag = 0;
+ req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+ req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
+ SRP_BUF_FORMAT_INDIRECT);
+ memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16);
+ /*
+ * Topspin/Cisco SRP targets will reject our login unless we
+ * zero out the first 8 bytes of our initiator port ID. The
+ * second 8 bytes must be our local node GUID, but we always
+ * use that anyway.
+ */
+ if (topspin_workarounds && !memcmp(&target->ioc_guid, topspin_oui, 3)) {
+ printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround "
+ "activated for target GUID %016llx\n",
+ (unsigned long long) be64_to_cpu(target->ioc_guid));
+ memset(req->priv.initiator_port_id, 0, 8);
+ }
+ memcpy(req->priv.target_port_id, &target->id_ext, 8);
+ memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
+
+ status = ib_send_cm_req(target->cm_id, &req->param);
+
+ kfree(req);
+
+ return status;
+}
+
+static void srp_disconnect_target(struct srp_target_port *target)
+{
+ /* XXX should send SRP_I_LOGOUT request */
+
+ init_completion(&target->done);
+ ib_send_cm_dreq(target->cm_id, NULL, 0);
+ wait_for_completion(&target->done);
+}
+
+static void srp_remove_work(void *target_ptr)
+{
+ struct srp_target_port *target = target_ptr;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+ if (target->state != SRP_TARGET_DEAD) {
+ spin_unlock_irq(target->scsi_host->host_lock);
+ scsi_host_put(target->scsi_host);
+ return;
+ }
+ target->state = SRP_TARGET_REMOVED;
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ down(&target->srp_host->target_mutex);
+ list_del(&target->list);
+ up(&target->srp_host->target_mutex);
+
+ scsi_remove_host(target->scsi_host);
+ ib_destroy_cm_id(target->cm_id);
+ srp_free_target_ib(target);
+ scsi_host_put(target->scsi_host);
+ /* And another put to really free the target port... */
+ scsi_host_put(target->scsi_host);
+}
+
+static int srp_connect_target(struct srp_target_port *target)
+{
+ int ret;
+
+ ret = srp_lookup_path(target);
+ if (ret)
+ return ret;
+
+ while (1) {
+ init_completion(&target->done);
+ ret = srp_send_req(target);
+ if (ret)
+ return ret;
+ wait_for_completion(&target->done);
+
+ /*
+ * The CM event handling code will set status to
+ * SRP_PORT_REDIRECT if we get a port redirect REJ
+ * back, or SRP_DLID_REDIRECT if we get a lid/qp
+ * redirect REJ back.
+ */
+ switch (target->status) {
+ case 0:
+ return 0;
+
+ case SRP_PORT_REDIRECT:
+ ret = srp_lookup_path(target);
+ if (ret)
+ return ret;
+ break;
+
+ case SRP_DLID_REDIRECT:
+ break;
+
+ default:
+ return target->status;
+ }
+ }
+}
+
+static int srp_reconnect_target(struct srp_target_port *target)
+{
+ struct ib_cm_id *new_cm_id;
+ struct ib_qp_attr qp_attr;
+ struct srp_request *req;
+ struct ib_wc wc;
+ int ret;
+ int i;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+ if (target->state != SRP_TARGET_LIVE) {
+ spin_unlock_irq(target->scsi_host->host_lock);
+ return -EAGAIN;
+ }
+ target->state = SRP_TARGET_CONNECTING;
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ srp_disconnect_target(target);
+ /*
+ * Now get a new local CM ID so that we avoid confusing the
+ * target in case things are really fouled up.
+ */
+ new_cm_id = ib_create_cm_id(target->srp_host->dev,
+ srp_cm_handler, target);
+ if (IS_ERR(new_cm_id)) {
+ ret = PTR_ERR(new_cm_id);
+ goto err;
+ }
+ ib_destroy_cm_id(target->cm_id);
+ target->cm_id = new_cm_id;
+
+ qp_attr.qp_state = IB_QPS_RESET;
+ ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
+ if (ret)
+ goto err;
+
+ ret = srp_init_qp(target, target->qp);
+ if (ret)
+ goto err;
+
+ while (ib_poll_cq(target->cq, 1, &wc) > 0)
+ ; /* nothing */
+
+ list_for_each_entry(req, &target->req_queue, list) {
+ req->scmnd->result = DID_RESET << 16;
+ req->scmnd->scsi_done(req->scmnd);
+ }
+
+ target->rx_head = 0;
+ target->tx_head = 0;
+ target->tx_tail = 0;
+ target->req_head = 0;
+ for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
+ target->req_ring[i].next = i + 1;
+ target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+ INIT_LIST_HEAD(&target->req_queue);
+
+ ret = srp_connect_target(target);
+ if (ret)
+ goto err;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+ if (target->state == SRP_TARGET_CONNECTING) {
+ ret = 0;
+ target->state = SRP_TARGET_LIVE;
+ } else
+ ret = -EAGAIN;
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ return ret;
+
+err:
+ printk(KERN_ERR PFX "reconnect failed (%d), removing target port.\n", ret);
+
+ /*
+ * We couldn't reconnect, so kill our target port off.
+ * However, we have to defer the real removal because we might
+ * be in the context of the SCSI error handler now, which
+ * would deadlock if we call scsi_remove_host().
+ */
+ spin_lock_irq(target->scsi_host->host_lock);
+ if (target->state == SRP_TARGET_CONNECTING) {
+ target->state = SRP_TARGET_DEAD;
+ INIT_WORK(&target->work, srp_remove_work, target);
+ schedule_work(&target->work);
+ }
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ return ret;
+}
+
+static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+ struct srp_request *req)
+{
+ struct srp_cmd *cmd = req->cmd->buf;
+ int len;
+ u8 fmt;
+
+ if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
+ return sizeof (struct srp_cmd);
+
+ if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
+ scmnd->sc_data_direction != DMA_TO_DEVICE) {
+ printk(KERN_WARNING PFX "Unhandled data direction %d\n",
+ scmnd->sc_data_direction);
+ return -EINVAL;
+ }
+
+ if (scmnd->use_sg) {
+ struct scatterlist *scat = scmnd->request_buffer;
+ int n;
+ int i;
+
+ n = dma_map_sg(target->srp_host->dev->dma_device,
+ scat, scmnd->use_sg, scmnd->sc_data_direction);
+
+ if (n == 1) {
+ struct srp_direct_buf *buf = (void *) cmd->add_data;
+
+ fmt = SRP_DATA_DESC_DIRECT;
+
+ buf->va = cpu_to_be64(sg_dma_address(scat));
+ buf->key = cpu_to_be32(target->srp_host->mr->rkey);
+ buf->len = cpu_to_be32(sg_dma_len(scat));
+
+ len = sizeof (struct srp_cmd) +
+ sizeof (struct srp_direct_buf);
+ } else {
+ struct srp_indirect_buf *buf = (void *) cmd->add_data;
+ u32 datalen = 0;
+
+ fmt = SRP_DATA_DESC_INDIRECT;
+
+ if (scmnd->sc_data_direction == DMA_TO_DEVICE)
+ cmd->data_out_desc_cnt = n;
+ else
+ cmd->data_in_desc_cnt = n;
+
+ buf->table_desc.va = cpu_to_be64(req->cmd->dma +
+ sizeof *cmd +
+ sizeof *buf);
+ buf->table_desc.key =
+ cpu_to_be32(target->srp_host->mr->rkey);
+ buf->table_desc.len =
+ cpu_to_be32(n * sizeof (struct srp_direct_buf));
+
+ for (i = 0; i < n; ++i) {
+ buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i]));
+ buf->desc_list[i].key =
+ cpu_to_be32(target->srp_host->mr->rkey);
+ buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
+
+ datalen += sg_dma_len(&scat[i]);
+ }
+
+ buf->len = cpu_to_be32(datalen);
+
+ len = sizeof (struct srp_cmd) +
+ sizeof (struct srp_indirect_buf) +
+ n * sizeof (struct srp_direct_buf);
+ }
+ } else {
+ struct srp_direct_buf *buf = (void *) cmd->add_data;
+ dma_addr_t dma;
+
+ dma = dma_map_single(target->srp_host->dev->dma_device,
+ scmnd->request_buffer, scmnd->request_bufflen,
+ scmnd->sc_data_direction);
+ if (dma_mapping_error(dma)) {
+ printk(KERN_WARNING PFX "unable to map %p/%d (dir %d)\n",
+ scmnd->request_buffer, (int) scmnd->request_bufflen,
+ scmnd->sc_data_direction);
+ return -EINVAL;
+ }
+
+ pci_unmap_addr_set(req, direct_mapping, dma);
+
+ buf->va = cpu_to_be64(dma);
+ buf->key = cpu_to_be32(target->srp_host->mr->rkey);
+ buf->len = cpu_to_be32(scmnd->request_bufflen);
+
+ fmt = SRP_DATA_DESC_DIRECT;
+
+ len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
+ }
+
+ if (scmnd->sc_data_direction == DMA_TO_DEVICE)
+ cmd->buf_fmt = fmt << 4;
+ else
+ cmd->buf_fmt = fmt;
+
+
+ return len;
+}
+
+static void srp_unmap_data(struct scsi_cmnd *scmnd,
+ struct srp_target_port *target,
+ struct srp_request *req)
+{
+ if (!scmnd->request_buffer ||
+ (scmnd->sc_data_direction != DMA_TO_DEVICE &&
+ scmnd->sc_data_direction != DMA_FROM_DEVICE))
+ return;
+
+ if (scmnd->use_sg)
+ dma_unmap_sg(target->srp_host->dev->dma_device,
+ (struct scatterlist *) scmnd->request_buffer,
+ scmnd->use_sg, scmnd->sc_data_direction);
+ else
+ dma_unmap_single(target->srp_host->dev->dma_device,
+ pci_unmap_addr(req, direct_mapping),
+ scmnd->request_bufflen,
+ scmnd->sc_data_direction);
+}
+
+static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
+{
+ struct srp_request *req;
+ struct scsi_cmnd *scmnd;
+ unsigned long flags;
+ s32 delta;
+
+ delta = (s32) be32_to_cpu(rsp->req_lim_delta);
+
+ spin_lock_irqsave(target->scsi_host->host_lock, flags);
+
+ target->req_lim += delta;
+
+ req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT];
+
+ if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
+ if (be32_to_cpu(rsp->resp_data_len) < 4)
+ req->tsk_status = -1;
+ else
+ req->tsk_status = rsp->data[3];
+ complete(&req->done);
+ } else {
+ scmnd = req->scmnd;
+ if (!scmnd)
+ printk(KERN_ERR "Null scmnd for RSP w/tag %016llx\n",
+ (unsigned long long) rsp->tag);
+ scmnd->result = rsp->status;
+
+ if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
+ memcpy(scmnd->sense_buffer, rsp->data +
+ be32_to_cpu(rsp->resp_data_len),
+ min_t(int, be32_to_cpu(rsp->sense_data_len),
+ SCSI_SENSE_BUFFERSIZE));
+ }
+
+ if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
+ scmnd->resid = be32_to_cpu(rsp->data_out_res_cnt);
+ else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
+ scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
+
+ srp_unmap_data(scmnd, target, req);
+
+ if (!req->tsk_mgmt) {
+ req->scmnd = NULL;
+ scmnd->host_scribble = (void *) -1L;
+ scmnd->scsi_done(scmnd);
+
+ list_del(&req->list);
+ req->next = target->req_head;
+ target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+ } else
+ req->cmd_done = 1;
+ }
+
+ spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+}
+
+static void srp_reconnect_work(void *target_ptr)
+{
+ struct srp_target_port *target = target_ptr;
+
+ srp_reconnect_target(target);
+}
+
+static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+{
+ struct srp_iu *iu;
+ u8 opcode;
+
+ iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
+
+ dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
+ target->max_ti_iu_len, DMA_FROM_DEVICE);
+
+ opcode = *(u8 *) iu->buf;
+
+ if (0) {
+ int i;
+
+ printk(KERN_ERR PFX "recv completion, opcode 0x%02x\n", opcode);
+
+ for (i = 0; i < wc->byte_len; ++i) {
+ if (i % 8 == 0)
+ printk(KERN_ERR " [%02x] ", i);
+ printk(" %02x", ((u8 *) iu->buf)[i]);
+ if ((i + 1) % 8 == 0)
+ printk("\n");
+ }
+
+ if (wc->byte_len % 8)
+ printk("\n");
+ }
+
+ switch (opcode) {
+ case SRP_RSP:
+ srp_process_rsp(target, iu->buf);
+ break;
+
+ case SRP_T_LOGOUT:
+ /* XXX Handle target logout */
+ printk(KERN_WARNING PFX "Got target logout request\n");
+ break;
+
+ default:
+ printk(KERN_WARNING PFX "Unhandled SRP opcode 0x%02x\n", opcode);
+ break;
+ }
+
+ dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
+ target->max_ti_iu_len, DMA_FROM_DEVICE);
+}
+
+static void srp_completion(struct ib_cq *cq, void *target_ptr)
+{
+ struct srp_target_port *target = target_ptr;
+ struct ib_wc wc;
+ unsigned long flags;
+
+ ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+ while (ib_poll_cq(cq, 1, &wc) > 0) {
+ if (wc.status) {
+ printk(KERN_ERR PFX "failed %s status %d\n",
+ wc.wr_id & SRP_OP_RECV ? "receive" : "send",
+ wc.status);
+ spin_lock_irqsave(target->scsi_host->host_lock, flags);
+ if (target->state == SRP_TARGET_LIVE)
+ schedule_work(&target->work);
+ spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+ break;
+ }
+
+ if (wc.wr_id & SRP_OP_RECV)
+ srp_handle_recv(target, &wc);
+ else
+ ++target->tx_tail;
+ }
+}
+
+static int __srp_post_recv(struct srp_target_port *target)
+{
+ struct srp_iu *iu;
+ struct ib_sge list;
+ struct ib_recv_wr wr, *bad_wr;
+ unsigned int next;
+ int ret;
+
+ next = target->rx_head & (SRP_RQ_SIZE - 1);
+ wr.wr_id = next | SRP_OP_RECV;
+ iu = target->rx_ring[next];
+
+ list.addr = iu->dma;
+ list.length = iu->size;
+ list.lkey = target->srp_host->mr->lkey;
+
+ wr.next = NULL;
+ wr.sg_list = &list;
+ wr.num_sge = 1;
+
+ ret = ib_post_recv(target->qp, &wr, &bad_wr);
+ if (!ret)
+ ++target->rx_head;
+
+ return ret;
+}
+
+static int srp_post_recv(struct srp_target_port *target)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(target->scsi_host->host_lock, flags);
+ ret = __srp_post_recv(target);
+ spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+
+ return ret;
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.
+ */
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target)
+{
+ if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
+ return NULL;
+
+ return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.
+ */
+static int __srp_post_send(struct srp_target_port *target,
+ struct srp_iu *iu, int len)
+{
+ struct ib_sge list;
+ struct ib_send_wr wr, *bad_wr;
+ int ret = 0;
+
+ if (target->req_lim < 1) {
+ printk(KERN_ERR PFX "Target has req_lim %d\n", target->req_lim);
+ return -EAGAIN;
+ }
+
+ list.addr = iu->dma;
+ list.length = len;
+ list.lkey = target->srp_host->mr->lkey;
+
+ wr.next = NULL;
+ wr.wr_id = target->tx_head & SRP_SQ_SIZE;
+ wr.sg_list = &list;
+ wr.num_sge = 1;
+ wr.opcode = IB_WR_SEND;
+ wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = ib_post_send(target->qp, &wr, &bad_wr);
+
+ if (!ret) {
+ ++target->tx_head;
+ --target->req_lim;
+ }
+
+ return ret;
+}
+
+static int srp_queuecommand(struct scsi_cmnd *scmnd,
+ void (*done)(struct scsi_cmnd *))
+{
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_request *req;
+ struct srp_iu *iu;
+ struct srp_cmd *cmd;
+ long req_index;
+ int len;
+
+ if (target->state == SRP_TARGET_CONNECTING)
+ goto err;
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED) {
+ scmnd->result = DID_BAD_TARGET << 16;
+ done(scmnd);
+ return 0;
+ }
+
+ iu = __srp_get_tx_iu(target);
+ if (!iu)
+ goto err;
+
+ dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
+ SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+
+ req_index = target->req_head;
+
+ scmnd->scsi_done = done;
+ scmnd->result = 0;
+ scmnd->host_scribble = (void *) req_index;
+
+ cmd = iu->buf;
+ memset(cmd, 0, sizeof *cmd);
+
+ cmd->opcode = SRP_CMD;
+ cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
+ cmd->tag = req_index;
+ memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
+
+ req = &target->req_ring[req_index];
+
+ req->scmnd = scmnd;
+ req->cmd = iu;
+ req->cmd_done = 0;
+ req->tsk_mgmt = NULL;
+
+ len = srp_map_data(scmnd, target, req);
+ if (len < 0) {
+ printk(KERN_ERR PFX "Failed to map data\n");
+ goto err;
+ }
+
+ if (__srp_post_recv(target)) {
+ printk(KERN_ERR PFX "Recv failed\n");
+ goto err_unmap;
+ }
+
+ dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
+ SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+
+ if (__srp_post_send(target, iu, len)) {
+ printk(KERN_ERR PFX "Send failed\n");
+ goto err_unmap;
+ }
+
+ target->req_head = req->next;
+ list_add_tail(&req->list, &target->req_queue);
+
+ return 0;
+
+err_unmap:
+ srp_unmap_data(scmnd, target, req);
+
+err:
+ return SCSI_MLQUEUE_HOST_BUSY;
+}
+
+static int srp_alloc_iu_bufs(struct srp_target_port *target)
+{
+ int i;
+
+ for (i = 0; i < SRP_RQ_SIZE; ++i) {
+ target->rx_ring[i] = srp_alloc_iu(target->srp_host,
+ target->max_ti_iu_len,
+ GFP_KERNEL, DMA_FROM_DEVICE);
+ if (!target->rx_ring[i])
+ goto err;
+ }
+
+ for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+ target->tx_ring[i] = srp_alloc_iu(target->srp_host,
+ SRP_MAX_IU_LEN,
+ GFP_KERNEL, DMA_TO_DEVICE);
+ if (!target->tx_ring[i])
+ goto err;
+ }
+
+ return 0;
+
+err:
+ for (i = 0; i < SRP_RQ_SIZE; ++i) {
+ srp_free_iu(target->srp_host, target->rx_ring[i]);
+ target->rx_ring[i] = NULL;
+ }
+
+ for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+ srp_free_iu(target->srp_host, target->tx_ring[i]);
+ target->tx_ring[i] = NULL;
+ }
+
+ return -ENOMEM;
+}
+
+static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
+ struct ib_cm_event *event,
+ struct srp_target_port *target)
+{
+ struct ib_class_port_info *cpi;
+ int opcode;
+
+ switch (event->param.rej_rcvd.reason) {
+ case IB_CM_REJ_PORT_CM_REDIRECT:
+ cpi = event->param.rej_rcvd.ari;
+ target->path.dlid = cpi->redirect_lid;
+ target->path.pkey = cpi->redirect_pkey;
+ cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
+ memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);
+
+ target->status = target->path.dlid ?
+ SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
+ break;
+
+ case IB_CM_REJ_PORT_REDIRECT:
+ if (topspin_workarounds &&
+ !memcmp(&target->ioc_guid, topspin_oui, 3)) {
+ /*
+ * Topspin/Cisco SRP gateways incorrectly send
+ * reject reason code 25 when they mean 24
+ * (port redirect).
+ */
+ memcpy(target->path.dgid.raw,
+ event->param.rej_rcvd.ari, 16);
+
+ printk(KERN_DEBUG PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
+ (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
+ (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
+
+ target->status = SRP_PORT_REDIRECT;
+ } else {
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
+ target->status = -ECONNRESET;
+ }
+ break;
+
+ case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
+ target->status = -ECONNRESET;
+ break;
+
+ case IB_CM_REJ_CONSUMER_DEFINED:
+ opcode = *(u8 *) event->private_data;
+ if (opcode == SRP_LOGIN_REJ) {
+ struct srp_login_rej *rej = event->private_data;
+ u32 reason = be32_to_cpu(rej->reason);
+
+ if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
+ printk(KERN_WARNING PFX
+ "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
+ else
+ printk(KERN_WARNING PFX
+ "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
+ } else
+ printk(KERN_WARNING " REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
+ " opcode 0x%02x\n", opcode);
+ target->status = -ECONNRESET;
+ break;
+
+ default:
+ printk(KERN_WARNING " REJ reason 0x%x\n",
+ event->param.rej_rcvd.reason);
+ target->status = -ECONNRESET;
+ }
+}
+
+static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+{
+ struct srp_target_port *target = cm_id->context;
+ struct ib_qp_attr *qp_attr = NULL;
+ int attr_mask = 0;
+ int comp = 0;
+ int opcode = 0;
+
+ switch (event->event) {
+ case IB_CM_REQ_ERROR:
+ printk(KERN_DEBUG PFX "Sending CM REQ failed\n");
+ comp = 1;
+ target->status = -ECONNRESET;
+ break;
+
+ case IB_CM_REP_RECEIVED:
+ comp = 1;
+ opcode = *(u8 *) event->private_data;
+
+ if (opcode == SRP_LOGIN_RSP) {
+ struct srp_login_rsp *rsp = event->private_data;
+
+ target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
+ target->req_lim = be32_to_cpu(rsp->req_lim_delta);
+
+ target->scsi_host->can_queue = min(target->req_lim,
+ target->scsi_host->can_queue);
+ } else {
+ printk(KERN_WARNING PFX "Unhandled RSP opcode %#x\n", opcode);
+ target->status = -ECONNRESET;
+ break;
+ }
+
+ target->status = srp_alloc_iu_bufs(target);
+ if (target->status)
+ break;
+
+ qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
+ if (!qp_attr) {
+ target->status = -ENOMEM;
+ break;
+ }
+
+ qp_attr->qp_state = IB_QPS_RTR;
+ target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
+ if (target->status)
+ break;
+
+ target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);
+ if (target->status)
+ break;
+
+ target->status = srp_post_recv(target);
+ if (target->status)
+ break;
+
+ qp_attr->qp_state = IB_QPS_RTS;
+ target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
+ if (target->status)
+ break;
+
+ target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);
+ if (target->status)
+ break;
+
+ target->status = ib_send_cm_rtu(cm_id, NULL, 0);
+ if (target->status)
+ break;
+
+ break;
+
+ case IB_CM_REJ_RECEIVED:
+ printk(KERN_DEBUG PFX "REJ received\n");
+ comp = 1;
+
+ srp_cm_rej_handler(cm_id, event, target);
+ break;
+
+ case IB_CM_MRA_RECEIVED:
+ printk(KERN_ERR PFX "MRA received\n");
+ break;
+
+ case IB_CM_DREP_RECEIVED:
+ break;
+
+ case IB_CM_TIMEWAIT_EXIT:
+ printk(KERN_ERR PFX "connection closed\n");
+
+ comp = 1;
+ target->status = 0;
+ break;
+
+ default:
+ printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event);
+ break;
+ }
+
+ if (comp)
+ complete(&target->done);
+
+ kfree(qp_attr);
+
+ return 0;
+}
+
+static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
+{
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_request *req;
+ struct srp_iu *iu;
+ struct srp_tsk_mgmt *tsk_mgmt;
+ int req_index;
+ int ret = FAILED;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+
+ if (scmnd->host_scribble == (void *) -1L)
+ goto out;
+
+ req_index = (long) scmnd->host_scribble;
+ printk(KERN_ERR "Abort for req_index %d\n", req_index);
+
+ req = &target->req_ring[req_index];
+ init_completion(&req->done);
+
+ iu = __srp_get_tx_iu(target);
+ if (!iu)
+ goto out;
+
+ tsk_mgmt = iu->buf;
+ memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
+
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
+ tsk_mgmt->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
+ tsk_mgmt->tag = req_index | SRP_TAG_TSK_MGMT;
+ tsk_mgmt->tsk_mgmt_func = func;
+ tsk_mgmt->task_tag = req_index;
+
+ if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
+ goto out;
+
+ req->tsk_mgmt = iu;
+
+ spin_unlock_irq(target->scsi_host->host_lock);
+ if (!wait_for_completion_timeout(&req->done,
+ msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
+ return FAILED;
+ spin_lock_irq(target->scsi_host->host_lock);
+
+ if (req->cmd_done) {
+ list_del(&req->list);
+ req->next = target->req_head;
+ target->req_head = req_index;
+
+ scmnd->scsi_done(scmnd);
+ } else if (!req->tsk_status) {
+ scmnd->result = DID_ABORT << 16;
+ ret = SUCCESS;
+ }
+
+out:
+ spin_unlock_irq(target->scsi_host->host_lock);
+ return ret;
+}
+
+static int srp_abort(struct scsi_cmnd *scmnd)
+{
+ printk(KERN_ERR "SRP abort called\n");
+
+ return srp_send_tsk_mgmt(scmnd, SRP_TSK_ABORT_TASK);
+}
+
+static int srp_reset_device(struct scsi_cmnd *scmnd)
+{
+ printk(KERN_ERR "SRP reset_device called\n");
+
+ return srp_send_tsk_mgmt(scmnd, SRP_TSK_LUN_RESET);
+}
+
+static int srp_reset_host(struct scsi_cmnd *scmnd)
+{
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ int ret = FAILED;
+
+ printk(KERN_ERR PFX "SRP reset_host called\n");
+
+ if (!srp_reconnect_target(target))
+ ret = SUCCESS;
+
+ return ret;
+}
+
+static struct scsi_host_template srp_template = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .info = srp_target_info,
+ .queuecommand = srp_queuecommand,
+ .eh_abort_handler = srp_abort,
+ .eh_device_reset_handler = srp_reset_device,
+ .eh_host_reset_handler = srp_reset_host,
+ .can_queue = SRP_SQ_SIZE,
+ .this_id = -1,
+ .sg_tablesize = SRP_MAX_INDIRECT,
+ .cmd_per_lun = SRP_SQ_SIZE,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+{
+ sprintf(target->target_name, "SRP.T10:%016llX",
+ (unsigned long long) be64_to_cpu(target->id_ext));
+
+ if (scsi_add_host(target->scsi_host, host->dev->dma_device))
+ return -ENODEV;
+
+ down(&host->target_mutex);
+ list_add_tail(&target->list, &host->target_list);
+ up(&host->target_mutex);
+
+ target->state = SRP_TARGET_LIVE;
+
+ /* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */
+ scsi_scan_target(&target->scsi_host->shost_gendev,
+ 0, target->scsi_id, ~0, 0);
+
+ return 0;
+}
+
+static void srp_release_class_dev(struct class_device *class_dev)
+{
+ struct srp_host *host =
+ container_of(class_dev, struct srp_host, class_dev);
+
+ complete(&host->released);
+}
+
+static struct class srp_class = {
+ .name = "infiniband_srp",
+ .release = srp_release_class_dev
+};
+
+/*
+ * Target ports are added by writing
+ *
+ * id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
+ * pkey=<P_Key>,service_id=<service ID>
+ *
+ * to the add_target sysfs attribute.
+ */
+enum {
+ SRP_OPT_ERR = 0,
+ SRP_OPT_ID_EXT = 1 << 0,
+ SRP_OPT_IOC_GUID = 1 << 1,
+ SRP_OPT_DGID = 1 << 2,
+ SRP_OPT_PKEY = 1 << 3,
+ SRP_OPT_SERVICE_ID = 1 << 4,
+ SRP_OPT_MAX_SECT = 1 << 5,
+ SRP_OPT_ALL = (SRP_OPT_ID_EXT |
+ SRP_OPT_IOC_GUID |
+ SRP_OPT_DGID |
+ SRP_OPT_PKEY |
+ SRP_OPT_SERVICE_ID),
+};
+
+static 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" },
+ { SRP_OPT_PKEY, "pkey=%x" },
+ { SRP_OPT_SERVICE_ID, "service_id=%s" },
+ { SRP_OPT_MAX_SECT, "max_sect=%d" },
+ { SRP_OPT_ERR, NULL }
+};
+
+static int srp_parse_options(const char *buf, struct srp_target_port *target)
+{
+ char *options, *sep_opt;
+ char *p;
+ char dgid[3];
+ substring_t args[MAX_OPT_ARGS];
+ int opt_mask = 0;
+ int token;
+ int ret = -EINVAL;
+ int i;
+
+ options = kstrdup(buf, GFP_KERNEL);
+ if (!options)
+ return -ENOMEM;
+
+ sep_opt = options;
+ while ((p = strsep(&sep_opt, ",")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, srp_opt_tokens, args);
+ opt_mask |= token;
+
+ switch (token) {
+ case SRP_OPT_ID_EXT:
+ p = match_strdup(args);
+ target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
+ kfree(p);
+ break;
+
+ case SRP_OPT_IOC_GUID:
+ p = match_strdup(args);
+ target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16));
+ kfree(p);
+ break;
+
+ case SRP_OPT_DGID:
+ p = match_strdup(args);
+ if (strlen(p) != 32) {
+ printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
+ goto out;
+ }
+
+ for (i = 0; i < 16; ++i) {
+ strlcpy(dgid, p + i * 2, 3);
+ target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);
+ }
+ break;
+
+ case SRP_OPT_PKEY:
+ if (match_hex(args, &token)) {
+ printk(KERN_WARNING PFX "bad P_Key parameter '%s'\n", p);
+ goto out;
+ }
+ target->path.pkey = cpu_to_be16(token);
+ break;
+
+ case SRP_OPT_SERVICE_ID:
+ p = match_strdup(args);
+ target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
+ kfree(p);
+ break;
+
+ case SRP_OPT_MAX_SECT:
+ if (match_int(args, &token)) {
+ printk(KERN_WARNING PFX "bad max sect parameter '%s'\n", p);
+ goto out;
+ }
+ target->scsi_host->max_sectors = token;
+ break;
+
+ default:
+ printk(KERN_WARNING PFX "unknown parameter or missing value "
+ "'%s' in target creation request\n", p);
+ goto out;
+ }
+ }
+
+ if ((opt_mask & SRP_OPT_ALL) == SRP_OPT_ALL)
+ ret = 0;
+ else
+ for (i = 0; i < ARRAY_SIZE(srp_opt_tokens); ++i)
+ if ((srp_opt_tokens[i].token & SRP_OPT_ALL) &&
+ !(srp_opt_tokens[i].token & opt_mask))
+ printk(KERN_WARNING PFX "target creation request is "
+ "missing parameter '%s'\n",
+ srp_opt_tokens[i].pattern);
+
+out:
+ kfree(options);
+ return ret;
+}
+
+static ssize_t srp_create_target(struct class_device *class_dev,
+ const char *buf, size_t count)
+{
+ struct srp_host *host =
+ container_of(class_dev, struct srp_host, class_dev);
+ struct Scsi_Host *target_host;
+ struct srp_target_port *target;
+ int ret;
+ int i;
+
+ target_host = scsi_host_alloc(&srp_template,
+ sizeof (struct srp_target_port));
+ if (!target_host)
+ return -ENOMEM;
+
+ target = host_to_target(target_host);
+ memset(target, 0, sizeof *target);
+
+ target->scsi_host = target_host;
+ target->srp_host = host;
+
+ INIT_WORK(&target->work, srp_reconnect_work, target);
+
+ for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
+ target->req_ring[i].next = i + 1;
+ target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+ INIT_LIST_HEAD(&target->req_queue);
+
+ ret = srp_parse_options(buf, target);
+ if (ret)
+ goto err;
+
+ ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid);
+
+ printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
+ "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ (unsigned long long) be64_to_cpu(target->id_ext),
+ (unsigned long long) be64_to_cpu(target->ioc_guid),
+ be16_to_cpu(target->path.pkey),
+ (unsigned long long) be64_to_cpu(target->service_id),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[0]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[2]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[4]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[6]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[8]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[10]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[12]),
+ (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[14]));
+
+ ret = srp_create_target_ib(target);
+ if (ret)
+ goto err;
+
+ target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target);
+ if (IS_ERR(target->cm_id)) {
+ ret = PTR_ERR(target->cm_id);
+ goto err_free;
+ }
+
+ ret = srp_connect_target(target);
+ if (ret) {
+ printk(KERN_ERR PFX "Connection failed\n");
+ goto err_cm_id;
+ }
+
+ ret = srp_add_target(host, target);
+ if (ret)
+ goto err_disconnect;
+
+ return count;
+
+err_disconnect:
+ srp_disconnect_target(target);
+
+err_cm_id:
+ ib_destroy_cm_id(target->cm_id);
+
+err_free:
+ srp_free_target_ib(target);
+
+err:
+ scsi_host_put(target_host);
+
+ return ret;
+}
+
+static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
+
+static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
+{
+ struct srp_host *host =
+ container_of(class_dev, struct srp_host, class_dev);
+
+ return sprintf(buf, "%s\n", host->dev->name);
+}
+
+static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+static ssize_t show_port(struct class_device *class_dev, char *buf)
+{
+ struct srp_host *host =
+ container_of(class_dev, struct srp_host, class_dev);
+
+ return sprintf(buf, "%d\n", host->port);
+}
+
+static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
+
+static struct srp_host *srp_add_port(struct ib_device *device,
+ __be64 node_guid, u8 port)
+{
+ struct srp_host *host;
+
+ host = kzalloc(sizeof *host, GFP_KERNEL);
+ if (!host)
+ return NULL;
+
+ INIT_LIST_HEAD(&host->target_list);
+ init_MUTEX(&host->target_mutex);
+ init_completion(&host->released);
+ host->dev = device;
+ host->port = port;
+
+ host->initiator_port_id[7] = port;
+ memcpy(host->initiator_port_id + 8, &node_guid, 8);
+
+ host->pd = ib_alloc_pd(device);
+ if (IS_ERR(host->pd))
+ goto err_free;
+
+ host->mr = ib_get_dma_mr(host->pd,
+ IB_ACCESS_LOCAL_WRITE |
+ IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE);
+ if (IS_ERR(host->mr))
+ goto err_pd;
+
+ host->class_dev.class = &srp_class;
+ host->class_dev.dev = device->dma_device;
+ snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
+ device->name, port);
+
+ if (class_device_register(&host->class_dev))
+ goto err_mr;
+ if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
+ goto err_class;
+ if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
+ goto err_class;
+ if (class_device_create_file(&host->class_dev, &class_device_attr_port))
+ goto err_class;
+
+ return host;
+
+err_class:
+ class_device_unregister(&host->class_dev);
+
+err_mr:
+ ib_dereg_mr(host->mr);
+
+err_pd:
+ ib_dealloc_pd(host->pd);
+
+err_free:
+ kfree(host);
+
+ return NULL;
+}
+
+static void srp_add_one(struct ib_device *device)
+{
+ struct list_head *dev_list;
+ struct srp_host *host;
+ struct ib_device_attr *dev_attr;
+ int s, e, p;
+
+ dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
+ if (!dev_attr)
+ return;
+
+ if (ib_query_device(device, dev_attr)) {
+ printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n",
+ device->name);
+ goto out;
+ }
+
+ dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
+ if (!dev_list)
+ goto out;
+
+ INIT_LIST_HEAD(dev_list);
+
+ if (device->node_type == IB_NODE_SWITCH) {
+ s = 0;
+ e = 0;
+ } else {
+ s = 1;
+ e = device->phys_port_cnt;
+ }
+
+ for (p = s; p <= e; ++p) {
+ host = srp_add_port(device, dev_attr->node_guid, p);
+ if (host)
+ list_add_tail(&host->list, dev_list);
+ }
+
+ ib_set_client_data(device, &srp_client, dev_list);
+
+out:
+ kfree(dev_attr);
+}
+
+static void srp_remove_one(struct ib_device *device)
+{
+ struct list_head *dev_list;
+ struct srp_host *host, *tmp_host;
+ LIST_HEAD(target_list);
+ struct srp_target_port *target, *tmp_target;
+ unsigned long flags;
+
+ dev_list = ib_get_client_data(device, &srp_client);
+
+ list_for_each_entry_safe(host, tmp_host, dev_list, list) {
+ class_device_unregister(&host->class_dev);
+ /*
+ * Wait for the sysfs entry to go away, so that no new
+ * target ports can be created.
+ */
+ wait_for_completion(&host->released);
+
+ /*
+ * Mark all target ports as removed, so we stop queueing
+ * commands and don't try to reconnect.
+ */
+ down(&host->target_mutex);
+ list_for_each_entry_safe(target, tmp_target,
+ &host->target_list, list) {
+ spin_lock_irqsave(target->scsi_host->host_lock, flags);
+ if (target->state != SRP_TARGET_REMOVED)
+ target->state = SRP_TARGET_REMOVED;
+ spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+ }
+ up(&host->target_mutex);
+
+ /*
+ * Wait for any reconnection tasks that may have
+ * started before we marked our target ports as
+ * removed, and any target port removal tasks.
+ */
+ flush_scheduled_work();
+
+ list_for_each_entry_safe(target, tmp_target,
+ &host->target_list, list) {
+ scsi_remove_host(target->scsi_host);
+ srp_disconnect_target(target);
+ ib_destroy_cm_id(target->cm_id);
+ srp_free_target_ib(target);
+ scsi_host_put(target->scsi_host);
+ }
+
+ ib_dereg_mr(host->mr);
+ ib_dealloc_pd(host->pd);
+ kfree(host);
+ }
+
+ kfree(dev_list);
+}
+
+static int __init srp_init_module(void)
+{
+ int ret;
+
+ ret = class_register(&srp_class);
+ if (ret) {
+ printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
+ return ret;
+ }
+
+ ret = ib_register_client(&srp_client);
+ if (ret) {
+ printk(KERN_ERR PFX "couldn't register IB client\n");
+ class_unregister(&srp_class);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit srp_cleanup_module(void)
+{
+ ib_unregister_client(&srp_client);
+ class_unregister(&srp_class);
+}
+
+module_init(srp_init_module);
+module_exit(srp_cleanup_module);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
new file mode 100644
index 000000000000..4fec28a71367
--- /dev/null
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, 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.
+ *
+ * - 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.
+ *
+ * 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.
+ *
+ * $Id: ib_srp.h 3932 2005-11-01 17:19:29Z roland $
+ */
+
+#ifndef IB_SRP_H
+#define IB_SRP_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include <asm/semaphore.h>
+
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_cm.h>
+
+enum {
+ SRP_PATH_REC_TIMEOUT_MS = 1000,
+ SRP_ABORT_TIMEOUT_MS = 5000,
+
+ SRP_PORT_REDIRECT = 1,
+ SRP_DLID_REDIRECT = 2,
+
+ SRP_MAX_IU_LEN = 256,
+
+ SRP_RQ_SHIFT = 6,
+ SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT,
+ SRP_SQ_SIZE = SRP_RQ_SIZE - 1,
+ SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE,
+
+ SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1)
+};
+
+#define SRP_OP_RECV (1 << 31)
+#define SRP_MAX_INDIRECT ((SRP_MAX_IU_LEN - \
+ sizeof (struct srp_cmd) - \
+ sizeof (struct srp_indirect_buf)) / 16)
+
+enum srp_target_state {
+ SRP_TARGET_LIVE,
+ SRP_TARGET_CONNECTING,
+ SRP_TARGET_DEAD,
+ SRP_TARGET_REMOVED
+};
+
+struct srp_host {
+ u8 initiator_port_id[16];
+ struct ib_device *dev;
+ u8 port;
+ struct ib_pd *pd;
+ struct ib_mr *mr;
+ struct class_device class_dev;
+ struct list_head target_list;
+ struct semaphore target_mutex;
+ struct completion released;
+ struct list_head list;
+};
+
+struct srp_request {
+ struct list_head list;
+ struct scsi_cmnd *scmnd;
+ struct srp_iu *cmd;
+ struct srp_iu *tsk_mgmt;
+ DECLARE_PCI_UNMAP_ADDR(direct_mapping)
+ struct completion done;
+ short next;
+ u8 cmd_done;
+ u8 tsk_status;
+};
+
+struct srp_target_port {
+ __be64 id_ext;
+ __be64 ioc_guid;
+ __be64 service_id;
+ struct srp_host *srp_host;
+ struct Scsi_Host *scsi_host;
+ char target_name[32];
+ unsigned int scsi_id;
+
+ struct ib_sa_path_rec path;
+ struct ib_sa_query *path_query;
+ int path_query_id;
+
+ struct ib_cm_id *cm_id;
+ struct ib_cq *cq;
+ struct ib_qp *qp;
+
+ int max_ti_iu_len;
+ s32 req_lim;
+
+ unsigned rx_head;
+ struct srp_iu *rx_ring[SRP_RQ_SIZE];
+
+ unsigned tx_head;
+ unsigned tx_tail;
+ struct srp_iu *tx_ring[SRP_SQ_SIZE + 1];
+
+ int req_head;
+ struct list_head req_queue;
+ struct srp_request req_ring[SRP_SQ_SIZE];
+
+ struct work_struct work;
+
+ struct list_head list;
+ struct completion done;
+ int status;
+ enum srp_target_state state;
+};
+
+struct srp_iu {
+ dma_addr_t dma;
+ void *buf;
+ size_t size;
+ enum dma_data_direction direction;
+};
+
+#endif /* IB_SRP_H */
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 20e3a165989f..9f2352bd8348 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -20,7 +20,6 @@
#include <linux/major.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/compat.h>
struct evdev {
@@ -160,6 +159,8 @@ struct input_event_compat {
# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
#elif defined(CONFIG_ARCH_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
+#elif defined(CONFIG_MIPS)
+# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
@@ -320,7 +321,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
if (get_user(v, ip + 1)) return -EFAULT;
if (v < 0 || v > KEY_MAX) return -EINVAL;
- if (v >> (dev->keycodesize * 8)) return -EINVAL;
+ if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
u = SET_INPUT_KEYCODE(dev, t, v);
clear_bit(u, dev->keybit);
set_bit(v, dev->keybit);
@@ -391,6 +392,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; len = SW_MAX; break;
default: return -EINVAL;
}
len = NBITS(len) * sizeof(long);
@@ -419,6 +421,13 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
}
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
+ int len;
+ len = NBITS(SW_MAX) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
+ }
+
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
int len;
if (!dev->name) return -ENOENT;
@@ -499,7 +508,7 @@ do { \
int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
for (i = 0; i < len / sizeof(compat_long_t); i++) \
- if (copy_to_user((compat_long_t*) p + i, \
+ if (copy_to_user((compat_long_t __user *) p + i, \
(compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
sizeof(compat_long_t))) \
return -EFAULT; \
@@ -556,6 +565,7 @@ static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned lon
case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; max = SW_MAX; break;
default: return -EINVAL;
}
bit_to_user(bits, max);
@@ -570,6 +580,9 @@ static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned lon
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
bit_to_user(dev->snd, SND_MAX);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
+ bit_to_user(dev->sw, SW_MAX);
+
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
int len;
if (!dev->name) return -ENOENT;
@@ -652,6 +665,7 @@ static struct file_operations evdev_fops = {
static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct evdev *evdev;
+ struct class_device *cdev;
int minor;
for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
@@ -677,11 +691,13 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
evdev_table[minor] = evdev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
- dev->dev, "event%d", minor);
+ dev->cdev.dev, evdev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ evdev->name);
return &evdev->handle;
}
@@ -691,9 +707,9 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev *evdev = handle->private;
struct evdev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
- devfs_remove("input/event%d", evdev->minor);
evdev->exist = 0;
if (evdev->open) {
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index a0118038330a..462f8d300aae 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -75,7 +75,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
if (!request_region(ioport, iolen, "emu10k1-gp"))
return -EBUSY;
- emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
port = gameport_allocate_port();
if (!emu || !port) {
printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 57615bc63906..47e93daa0fa7 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -83,7 +83,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
struct fm801_gp *gp;
struct gameport *port;
- gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+ gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL);
port = gameport_allocate_port();
if (!gp || !port) {
printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index ab09cf4093e3..0506934244f0 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/sched.h> /* HZ */
/*#include <asm/io.h>*/
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 1ab5f2dc8a2a..d2e55dc956ba 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -142,7 +142,7 @@ static int ns558_isa_probe(int io)
return -EBUSY;
}
- ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
port = gameport_allocate_port();
if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed.\n");
@@ -215,7 +215,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
if (!request_region(ioport, iolen, "ns558-pnp"))
return -EBUSY;
- ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL);
port = gameport_allocate_port();
if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed\n");
@@ -275,9 +275,9 @@ static int __init ns558_init(void)
static void __exit ns558_exit(void)
{
- struct ns558 *ns558;
+ struct ns558 *ns558, *safe;
- list_for_each_entry(ns558, &ns558_list, node) {
+ list_for_each_entry_safe(ns558, safe, &ns558_list, node) {
gameport_unregister_port(ns558->gameport);
release_region(ns558->io & ~(ns558->size - 1), ns558->size);
kfree(ns558);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a275211c8e1e..1a1654caedd5 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -22,12 +22,12 @@
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(input_allocate_device);
EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process);
EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL(input_class);
+EXPORT_SYMBOL_GPL(input_class);
#define INPUT_DEVICES 256
@@ -89,6 +89,15 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
break;
+ case EV_SW:
+
+ if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value)
+ return;
+
+ change_bit(code, dev->sw);
+
+ break;
+
case EV_ABS:
if (code > ABS_MAX || !test_bit(code, dev->absbit))
@@ -299,6 +308,7 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
MATCH_BIT(ledbit, LED_MAX);
MATCH_BIT(sndbit, SND_MAX);
MATCH_BIT(ffbit, FF_MAX);
+ MATCH_BIT(swbit, SW_MAX);
return id;
}
@@ -306,123 +316,21 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
return NULL;
}
-
-/*
- * Input hotplugging interface - loading event handlers based on
- * device bitfields.
- */
-
-#ifdef CONFIG_HOTPLUG
-
-/*
- * Input hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when input devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
- * or other modules, configure the device, and more. Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- */
-
-#define SPRINTF_BIT_A(bit, name, max) \
- do { \
- envp[i++] = scratch; \
- scratch += sprintf(scratch, name); \
- for (j = NBITS(max) - 1; j >= 0; j--) \
- if (dev->bit[j]) break; \
- for (; j >= 0; j--) \
- scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
- scratch++; \
- } while (0)
-
-#define SPRINTF_BIT_A2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_A(bit, name, max); \
- } while (0)
-
-static void input_call_hotplug(char *verb, struct input_dev *dev)
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
{
- char *argv[3], **envp, *buf, *scratch;
- int i = 0, j, value;
-
- if (!hotplug_path[0]) {
- printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
- return;
- }
- if (in_interrupt()) {
- printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
- return;
- }
- if (!current->fs->root) {
- printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
- return;
- }
- if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
- if (!(buf = kmalloc(1024, GFP_KERNEL))) {
- kfree (envp);
- printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
- return;
- }
-
- argv[0] = hotplug_path;
- argv[1] = "input";
- argv[2] = NULL;
-
- envp[i++] = "HOME=/";
- envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
- scratch = buf;
-
- envp[i++] = scratch;
- scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
-
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
-
- if (dev->name) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
- }
-
- if (dev->phys) {
- envp[i++] = scratch;
- scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
- }
-
- SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
-
- envp[i++] = NULL;
-
-#ifdef INPUT_DEBUG
- printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
- argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
-#endif
-
- value = call_usermodehelper(argv [0], argv, envp, 0);
+ int i;
+ int len = 0;
- kfree(buf);
- kfree(envp);
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
-#ifdef INPUT_DEBUG
- if (value != 0)
- printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
-#endif
+ for (; i >= 0; i--)
+ len += snprintf(buf + len, max(buf_size - len, 0),
+ "%lx%s", bitmap[i], i > 0 ? " " : "");
+ return len;
}
-#endif
-
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir;
@@ -444,37 +352,39 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
return 0;
}
-#define SPRINTF_BIT_B(bit, name, max) \
- do { \
- len += sprintf(buf + len, "B: %s", name); \
- for (i = NBITS(max) - 1; i >= 0; i--) \
- if (dev->bit[i]) break; \
- for (; i >= 0; i--) \
- len += sprintf(buf + len, "%lx ", dev->bit[i]); \
- len += sprintf(buf + len, "\n"); \
+#define SPRINTF_BIT(ev, bm) \
+ do { \
+ len += sprintf(buf + len, "B: %s=", #ev); \
+ len += input_print_bitmap(buf + len, INT_MAX, \
+ dev->bm##bit, ev##_MAX); \
+ len += sprintf(buf + len, "\n"); \
} while (0)
-#define SPRINTF_BIT_B2(bit, name, max, ev) \
- do { \
- if (test_bit(ev, dev->evbit)) \
- SPRINTF_BIT_B(bit, name, max); \
+#define TEST_AND_SPRINTF_BIT(ev, bm) \
+ do { \
+ if (test_bit(EV_##ev, dev->evbit)) \
+ SPRINTF_BIT(ev, bm); \
} while (0)
static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
{
struct input_dev *dev;
struct input_handle *handle;
+ const char *path;
off_t at = 0;
- int i, len, cnt = 0;
+ int len, cnt = 0;
list_for_each_entry(dev, &input_dev_list, node) {
+ path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL;
+
len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
len += sprintf(buf + len, "H: Handlers=");
list_for_each_entry(handle, &dev->h_list, d_node)
@@ -482,14 +392,15 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
len += sprintf(buf + len, "\n");
- SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
- SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
- SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
- SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
- SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
- SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
- SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
- SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
+ SPRINTF_BIT(EV, ev);
+ TEST_AND_SPRINTF_BIT(KEY, key);
+ TEST_AND_SPRINTF_BIT(REL, rel);
+ TEST_AND_SPRINTF_BIT(ABS, abs);
+ TEST_AND_SPRINTF_BIT(MSC, msc);
+ TEST_AND_SPRINTF_BIT(LED, led);
+ TEST_AND_SPRINTF_BIT(SND, snd);
+ TEST_AND_SPRINTF_BIT(FF, ff);
+ TEST_AND_SPRINTF_BIT(SW, sw);
len += sprintf(buf + len, "\n");
@@ -504,6 +415,8 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int
if (cnt >= count)
break;
}
+
+ kfree(path);
}
if (&dev->node == &input_dev_list)
@@ -594,6 +507,240 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { }
#endif
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int retval; \
+ \
+ retval = down_interruptible(&input_dev->sem); \
+ if (retval) \
+ return retval; \
+ \
+ retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \
+ \
+ up(&input_dev->sem); \
+ \
+ return retval; \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+
+INPUT_DEV_STRING_ATTR_SHOW(name);
+INPUT_DEV_STRING_ATTR_SHOW(phys);
+INPUT_DEV_STRING_ATTR_SHOW(uniq);
+
+static struct attribute *input_dev_attrs[] = {
+ &class_device_attr_name.attr,
+ &class_device_attr_phys.attr,
+ &class_device_attr_uniq.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_group = {
+ .attrs = input_dev_attrs,
+};
+
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return sprintf(buf, "%04x\n", input_dev->id.name); \
+} \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+
+INPUT_DEV_ID_ATTR(bustype);
+INPUT_DEV_ID_ATTR(vendor);
+INPUT_DEV_ID_ATTR(product);
+INPUT_DEV_ID_ATTR(version);
+
+static struct attribute *input_dev_id_attrs[] = {
+ &class_device_attr_bustype.attr,
+ &class_device_attr_vendor.attr,
+ &class_device_attr_product.attr,
+ &class_device_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_id_attr_group = {
+ .name = "id",
+ .attrs = input_dev_id_attrs,
+};
+
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+} \
+static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+
+INPUT_DEV_CAP_ATTR(EV, ev);
+INPUT_DEV_CAP_ATTR(KEY, key);
+INPUT_DEV_CAP_ATTR(REL, rel);
+INPUT_DEV_CAP_ATTR(ABS, abs);
+INPUT_DEV_CAP_ATTR(MSC, msc);
+INPUT_DEV_CAP_ATTR(LED, led);
+INPUT_DEV_CAP_ATTR(SND, snd);
+INPUT_DEV_CAP_ATTR(FF, ff);
+INPUT_DEV_CAP_ATTR(SW, sw);
+
+static struct attribute *input_dev_caps_attrs[] = {
+ &class_device_attr_ev.attr,
+ &class_device_attr_key.attr,
+ &class_device_attr_rel.attr,
+ &class_device_attr_abs.attr,
+ &class_device_attr_msc.attr,
+ &class_device_attr_led.attr,
+ &class_device_attr_snd.attr,
+ &class_device_attr_ff.attr,
+ &class_device_attr_sw.attr,
+ NULL
+};
+
+static struct attribute_group input_dev_caps_attr_group = {
+ .name = "capabilities",
+ .attrs = input_dev_caps_attrs,
+};
+
+static void input_dev_release(struct class_device *class_dev)
+{
+ struct input_dev *dev = to_input_dev(class_dev);
+
+ kfree(dev);
+ module_put(THIS_MODULE);
+}
+
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ const char *name, unsigned long *bitmap, int max)
+{
+ if (*cur_index >= num_envp - 1)
+ return -ENOMEM;
+
+ envp[*cur_index] = buffer + *cur_len;
+
+ *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ *cur_len += input_print_bitmap(buffer + *cur_len,
+ max(buffer_size - *cur_len, 0),
+ bitmap, max) + 1;
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ (*cur_index)++;
+ return 0;
+}
+
+#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
+ do { \
+ int err = add_hotplug_env_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ fmt, val); \
+ if (err) \
+ return err; \
+ } while (0)
+
+#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
+ do { \
+ int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ name, bm, max); \
+ if (err) \
+ return err; \
+ } while (0)
+
+static int input_dev_hotplug(struct class_device *cdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct input_dev *dev = to_input_dev(cdev);
+ int i = 0;
+ int len = 0;
+
+ INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
+ dev->id.bustype, dev->id.vendor,
+ dev->id.product, dev->id.version);
+ if (dev->name)
+ INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
+ if (dev->phys)
+ INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
+ if (dev->phys)
+ INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
+
+ INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
+ if (test_bit(EV_KEY, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
+ if (test_bit(EV_REL, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
+ if (test_bit(EV_ABS, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
+ if (test_bit(EV_MSC, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
+ if (test_bit(EV_LED, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
+ if (test_bit(EV_SND, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
+ if (test_bit(EV_FF, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
+ if (test_bit(EV_SW, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+struct class input_class = {
+ .name = "input",
+ .release = input_dev_release,
+ .hotplug = input_dev_hotplug,
+};
+
+struct input_dev *input_allocate_device(void)
+{
+ struct input_dev *dev;
+
+ dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
+ if (dev) {
+ dev->dynalloc = 1;
+ dev->cdev.class = &input_class;
+ class_device_initialize(&dev->cdev);
+ INIT_LIST_HEAD(&dev->h_list);
+ INIT_LIST_HEAD(&dev->node);
+ }
+
+ return dev;
+}
+
+static void input_register_classdevice(struct input_dev *dev)
+{
+ static atomic_t input_no = ATOMIC_INIT(0);
+ const char *path;
+
+ __module_get(THIS_MODULE);
+
+ dev->dev = dev->cdev.dev;
+
+ snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+ path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
+ printk(KERN_INFO "input: %s as %s/%s\n",
+ dev->name ? dev->name : "Unspecified device",
+ path ? path : "", dev->cdev.class_id);
+ kfree(path);
+
+ class_device_add(&dev->cdev);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_group);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+}
+
void input_register_device(struct input_dev *dev)
{
struct input_handle *handle;
@@ -620,15 +767,15 @@ void input_register_device(struct input_dev *dev)
INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
+ if (dev->dynalloc)
+ input_register_classdevice(dev);
+
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("add", dev);
-#endif
input_wakeup_procfs_readers();
}
@@ -648,12 +795,14 @@ void input_unregister_device(struct input_dev *dev)
handle->handler->disconnect(handle);
}
-#ifdef CONFIG_HOTPLUG
- input_call_hotplug("remove", dev);
-#endif
-
list_del_init(&dev->node);
+ if (dev->dynalloc) {
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ class_device_unregister(&dev->cdev);
+ }
+
input_wakeup_procfs_readers();
}
@@ -736,16 +885,14 @@ static struct file_operations input_fops = {
.open = input_open_file,
};
-struct class *input_class;
-
static int __init input_init(void)
{
int err;
- input_class = class_create(THIS_MODULE, "input");
- if (IS_ERR(input_class)) {
- printk(KERN_ERR "input: unable to register input class\n");
- return PTR_ERR(input_class);
+ err = class_register(&input_class);
+ if (err) {
+ printk(KERN_ERR "input: unable to register input_dev class\n");
+ return err;
}
err = input_proc_init();
@@ -758,24 +905,18 @@ static int __init input_init(void)
goto fail2;
}
- err = devfs_mk_dir("input");
- if (err)
- goto fail3;
-
return 0;
- fail3: unregister_chrdev(INPUT_MAJOR, "input");
fail2: input_proc_exit();
- fail1: class_destroy(input_class);
+ fail1: class_unregister(&input_class);
return err;
}
static void __exit input_exit(void)
{
input_proc_exit();
- devfs_remove("input");
unregister_chrdev(INPUT_MAJOR, "input");
- class_destroy(input_class);
+ class_unregister(&input_class);
}
subsys_initcall(input_init);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index e0938d1d3ad7..20e2972b9204 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -26,7 +26,6 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces");
@@ -449,6 +448,7 @@ static struct file_operations joydev_fops = {
static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct joydev *joydev;
+ struct class_device *cdev;
int i, j, t, minor;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
@@ -514,11 +514,13 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev_table[minor] = joydev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
- dev->dev, "js%d", minor);
+ dev->cdev.dev, joydev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ joydev->name);
return &joydev->handle;
}
@@ -528,8 +530,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev *joydev = handle->private;
struct joydev_list *list;
- class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
- devfs_remove("input/js%d", joydev->minor);
+ sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+ class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0;
if (joydev->open) {
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index bf34f75b9467..4571ea3a4b92 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver"
@@ -269,7 +270,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
int i;
int err;
- if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+ if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL)))
return -ENOMEM;
a3d->gameport = gameport;
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 265962956c63..704bf70f1db7 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -34,6 +34,7 @@
#include <linux/input.h>
#include <linux/gameport.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Logitech ADI joystick family driver"
@@ -54,7 +55,7 @@ MODULE_LICENSE("GPL");
#define ADI_MIN_LENGTH 8
#define ADI_MIN_LEN_LENGTH 10
#define ADI_MIN_ID_LENGTH 66
-#define ADI_MAX_NAME_LENGTH 48
+#define ADI_MAX_NAME_LENGTH 64
#define ADI_MAX_CNAME_LENGTH 16
#define ADI_MAX_PHYS_LENGTH 64
@@ -106,7 +107,7 @@ static struct {
*/
struct adi {
- struct input_dev dev;
+ struct input_dev *dev;
int length;
int ret;
int idx;
@@ -215,7 +216,7 @@ static inline int adi_get_bits(struct adi *adi, int count)
static int adi_decode(struct adi *adi)
{
- struct input_dev *dev = &adi->dev;
+ struct input_dev *dev = adi->dev;
char *abs = adi->abs;
short *key = adi->key;
int i, t;
@@ -318,7 +319,8 @@ static void adi_init_digital(struct gameport *gameport)
for (i = 0; seq[i]; i++) {
gameport_trigger(gameport);
- if (seq[i] > 0) msleep(seq[i]);
+ if (seq[i] > 0)
+ msleep(seq[i]);
if (seq[i] < 0) {
mdelay(-seq[i]);
udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
@@ -397,42 +399,46 @@ static void adi_id_decode(struct adi *adi, struct adi_port *port)
}
}
-static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
+static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
{
- int i, t;
+ struct input_dev *input_dev;
char buf[ADI_MAX_NAME_LENGTH];
+ int i, t;
- if (!adi->length) return;
-
- init_input_dev(&adi->dev);
+ adi->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
- snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
+ snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname);
snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
adi->abs = adi_abs[t];
adi->key = adi_key[t];
- adi->dev.open = adi_open;
- adi->dev.close = adi_close;
+ input_dev->name = adi->name;
+ input_dev->phys = adi->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
+ input_dev->id.product = adi->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &port->gameport->dev;
+ input_dev->private = port;
- adi->dev.name = adi->name;
- adi->dev.phys = adi->phys;
- adi->dev.id.bustype = BUS_GAMEPORT;
- adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
- adi->dev.id.product = adi->id;
- adi->dev.id.version = 0x0100;
+ input_dev->open = adi_open;
+ input_dev->close = adi_close;
- adi->dev.private = port;
- adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
- set_bit(adi->abs[i], adi->dev.absbit);
+ set_bit(adi->abs[i], input_dev->absbit);
for (i = 0; i < adi->buttons; i++)
- set_bit(adi->key[i], adi->dev.keybit);
+ set_bit(adi->key[i], input_dev->keybit);
+
+ return 0;
}
static void adi_init_center(struct adi *adi)
@@ -445,17 +451,17 @@ static void adi_init_center(struct adi *adi)
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
t = adi->abs[i];
- x = adi->dev.abs[t];
+ x = adi->dev->abs[t];
if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
x = i < adi->axes10 ? 512 : 128;
if (i < adi->axes10)
- input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+ input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16);
else if (i < adi->axes10 + adi->axes8)
- input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+ input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16);
else
- input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
+ input_set_abs_params(adi->dev, t, -1, 1, 0, 0);
}
}
@@ -469,7 +475,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
int i;
int err;
- if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+ port = kzalloc(sizeof(struct adi_port), GFP_KERNEL);
+ if (!port)
return -ENOMEM;
port->gameport = gameport;
@@ -477,10 +484,8 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_drvdata(gameport, port);
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
- if (err) {
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail1;
adi_init_digital(gameport);
adi_read_packet(port);
@@ -490,13 +495,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++) {
adi_id_decode(port->adi + i, port);
- adi_init_input(port->adi + i, port, i);
+
+ if (!port->adi[i].length)
+ continue;
+
+ err = adi_init_input(port->adi + i, port, i);
+ if (err)
+ goto fail2;
}
if (!port->adi[0].length && !port->adi[1].length) {
- gameport_close(gameport);
- kfree(port);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail2;
}
gameport_set_poll_handler(gameport, adi_poll);
@@ -511,12 +521,18 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0) {
adi_init_center(port->adi + i);
- input_register_device(&port->adi[i].dev);
- printk(KERN_INFO "input: %s [%s] on %s\n",
- port->adi[i].name, port->adi[i].cname, gameport->phys);
+ input_register_device(port->adi[i].dev);
}
return 0;
+
+ fail2: for (i = 0; i < 2; i++)
+ if (port->adi[i].dev)
+ input_free_device(port->adi[i].dev);
+ gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(port);
+ return err;
}
static void adi_disconnect(struct gameport *gameport)
@@ -526,7 +542,7 @@ static void adi_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0)
- input_unregister_device(&port->adi[i].dev);
+ input_unregister_device(port->adi[i].dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(port);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index e996183c5b06..8558a99f6635 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -53,11 +53,9 @@ __obsolete_setup("amijoy=");
static int amijoy_used;
static DECLARE_MUTEX(amijoy_sem);
-static struct input_dev amijoy_dev[2];
+static struct input_dev *amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
-static char *amijoy_name = "Amiga joystick";
-
static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
int i, data = 0, button = 0;
@@ -70,15 +68,15 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
}
- input_regs(amijoy_dev + i, fp);
+ input_regs(amijoy_dev[i], fp);
- input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
+ input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
- input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
+ input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
data = ~(data ^ (data << 1));
- input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
+ input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
- input_sync(amijoy_dev + i);
+ input_sync(amijoy_dev[i]);
}
return IRQ_HANDLED;
}
@@ -114,39 +112,52 @@ static void amijoy_close(struct input_dev *dev)
static int __init amijoy_init(void)
{
int i, j;
+ int err;
- for (i = 0; i < 2; i++)
- if (amijoy[i]) {
- if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
- "amijoy [Denise]")) {
- if (i == 1 && amijoy[0]) {
- input_unregister_device(amijoy_dev);
- release_mem_region(CUSTOM_PHYSADDR+10, 2);
- }
- return -EBUSY;
- }
+ for (i = 0; i < 2; i++) {
+ if (!amijoy[i])
+ continue;
- amijoy_dev[i].open = amijoy_open;
- amijoy_dev[i].close = amijoy_close;
- amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- for (j = 0; j < 2; j++) {
- amijoy_dev[i].absmin[ABS_X + j] = -1;
- amijoy_dev[i].absmax[ABS_X + j] = 1;
- }
+ amijoy_dev[i] = input_allocate_device();
+ if (!amijoy_dev[i]) {
+ err = -ENOMEM;
+ goto fail;
+ }
- amijoy_dev[i].name = amijoy_name;
- amijoy_dev[i].phys = amijoy_phys[i];
- amijoy_dev[i].id.bustype = BUS_AMIGA;
- amijoy_dev[i].id.vendor = 0x0001;
- amijoy_dev[i].id.product = 0x0003;
- amijoy_dev[i].id.version = 0x0100;
+ if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
+ input_free_device(amijoy_dev[i]);
+ err = -EBUSY;
+ goto fail;
+ }
- input_register_device(amijoy_dev + i);
- printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
+ amijoy_dev[i]->name = "Amiga joystick";
+ amijoy_dev[i]->phys = amijoy_phys[i];
+ amijoy_dev[i]->id.bustype = BUS_AMIGA;
+ amijoy_dev[i]->id.vendor = 0x0001;
+ amijoy_dev[i]->id.product = 0x0003;
+ amijoy_dev[i]->id.version = 0x0100;
+
+ amijoy_dev[i]->open = amijoy_open;
+ amijoy_dev[i]->close = amijoy_close;
+
+ amijoy_dev[i]->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ amijoy_dev[i]->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ amijoy_dev[i]->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ for (j = 0; j < 2; j++) {
+ amijoy_dev[i]->absmin[ABS_X + j] = -1;
+ amijoy_dev[i]->absmax[ABS_X + j] = 1;
}
+
+ input_register_device(amijoy_dev[i]);
+ }
return 0;
+
+ fail: while (--i >= 0)
+ if (amijoy[i]) {
+ input_unregister_device(amijoy_dev[i]);
+ release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
+ }
+ return err;
}
static void __exit amijoy_exit(void)
@@ -155,8 +166,8 @@ static void __exit amijoy_exit(void)
for (i = 0; i < 2; i++)
if (amijoy[i]) {
- input_unregister_device(amijoy_dev + i);
- release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
+ input_unregister_device(amijoy_dev[i]);
+ release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
}
}
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index c3a5739030c3..3121961e3e7c 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/gameport.h>
+#include <linux/jiffies.h>
#include <asm/timex.h>
#define DRIVER_DESC "Analog joystick and gamepad driver"
@@ -111,7 +112,7 @@ static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN
static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
struct analog {
- struct input_dev dev;
+ struct input_dev *dev;
int mask;
short *buttons;
char name[ANALOG_MAX_NAME_LENGTH];
@@ -182,7 +183,7 @@ static unsigned long analog_faketime = 0;
static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
{
- struct input_dev *dev = &analog->dev;
+ struct input_dev *dev = analog->dev;
int i, j;
if (analog->mask & ANALOG_HAT_FCS)
@@ -428,27 +429,30 @@ static void analog_name(struct analog *analog)
* analog_init_device()
*/
-static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
+static int analog_init_device(struct analog_port *port, struct analog *analog, int index)
{
+ struct input_dev *input_dev;
int i, j, t, v, w, x, y, z;
analog_name(analog);
sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
- init_input_dev(&analog->dev);
+ analog->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
- analog->dev.name = analog->name;
- analog->dev.phys = analog->phys;
- analog->dev.id.bustype = BUS_GAMEPORT;
- analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
- analog->dev.id.product = analog->mask >> 4;
- analog->dev.id.version = 0x0100;
+ input_dev->name = analog->name;
+ input_dev->phys = analog->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
+ input_dev->id.product = analog->mask >> 4;
+ input_dev->id.version = 0x0100;
- analog->dev.open = analog_open;
- analog->dev.close = analog_close;
- analog->dev.private = port;
- analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->open = analog_open;
+ input_dev->close = analog_close;
+ input_dev->private = port;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = j = 0; i < 4; i++)
if (analog->mask & (1 << i)) {
@@ -461,8 +465,6 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
v = (x >> 3);
w = (x >> 3);
- set_bit(t, analog->dev.absbit);
-
if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
x = y;
@@ -472,11 +474,7 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
w = (x >> 4);
}
- analog->dev.absmax[t] = (x << 1) - v;
- analog->dev.absmin[t] = v;
- analog->dev.absfuzz[t] = port->fuzz;
- analog->dev.absflat[t] = w;
-
+ input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);
j++;
}
@@ -484,41 +482,30 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
if (analog->mask & analog_exts[i])
for (x = 0; x < 2; x++) {
t = analog_hats[j++];
- set_bit(t, analog->dev.absbit);
- analog->dev.absmax[t] = 1;
- analog->dev.absmin[t] = -1;
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
}
for (i = j = 0; i < 4; i++)
if (analog->mask & (0x10 << i))
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_BTNS_CHF)
for (i = 0; i < 2; i++)
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
if (analog->mask & ANALOG_HBTN_CHF)
for (i = 0; i < 4; i++)
- set_bit(analog->buttons[j++], analog->dev.keybit);
+ set_bit(analog->buttons[j++], input_dev->keybit);
for (i = 0; i < 4; i++)
if (analog->mask & (ANALOG_BTN_TL << i))
- set_bit(analog_pads[i], analog->dev.keybit);
+ set_bit(analog_pads[i], input_dev->keybit);
analog_decode(analog, port->axes, port->initial, port->buttons);
- input_register_device(&analog->dev);
+ input_register_device(analog->dev);
- printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
-
- if (port->cooked)
- printk(" [ADC port]\n");
- else
- printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
- port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
- port->speed > 10000 ? "M" : "k",
- port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
- : (port->loop * 1000000) / port->speed);
+ return 0;
}
/*
@@ -655,41 +642,45 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
int i;
int err;
- if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+ if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
return - ENOMEM;
err = analog_init_port(gameport, drv, port);
- if (err) {
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail1;
err = analog_init_masks(port);
- if (err) {
- gameport_close(gameport);
- gameport_set_drvdata(gameport, NULL);
- kfree(port);
- return err;
- }
+ if (err)
+ goto fail2;
gameport_set_poll_handler(gameport, analog_poll);
gameport_set_poll_interval(gameport, 10);
for (i = 0; i < 2; i++)
- if (port->analog[i].mask)
- analog_init_device(port, port->analog + i, i);
+ if (port->analog[i].mask) {
+ err = analog_init_device(port, port->analog + i, i);
+ if (err)
+ goto fail3;
+ }
return 0;
+
+ fail3: while (--i >= 0)
+ input_unregister_device(port->analog[i].dev);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(port);
+ return err;
}
static void analog_disconnect(struct gameport *gameport)
{
- int i;
struct analog_port *port = gameport_get_drvdata(gameport);
+ int i;
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
- input_unregister_device(&port->analog[i].dev);
+ input_unregister_device(port->analog[i].dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index a6002205328f..1909f7ef340c 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver"
@@ -44,13 +45,11 @@ MODULE_LICENSE("GPL");
#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
#define COBRA_LENGTH 36
-static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
-
static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
struct cobra {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct input_dev *dev[2];
int reads;
int bads;
unsigned char exists;
@@ -128,7 +127,7 @@ static void cobra_poll(struct gameport *gameport)
for (i = 0; i < 2; i++)
if (cobra->exists & r & (1 << i)) {
- dev = cobra->dev + i;
+ dev = cobra->dev[i];
input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
@@ -159,11 +158,13 @@ static void cobra_close(struct input_dev *dev)
static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct cobra *cobra;
+ struct input_dev *input_dev;
unsigned int data[2];
int i, j;
int err;
- if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+ cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
+ if (!cobra)
return -ENOMEM;
cobra->gameport = gameport;
@@ -191,38 +192,46 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, cobra_poll);
gameport_set_poll_interval(gameport, 20);
- for (i = 0; i < 2; i++)
- if ((cobra->exists >> i) & 1) {
-
- sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+ for (i = 0; i < 2; i++) {
+ if (~(cobra->exists >> i) & 1)
+ continue;
- cobra->dev[i].private = cobra;
- cobra->dev[i].open = cobra_open;
- cobra->dev[i].close = cobra_close;
+ cobra->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- cobra->dev[i].name = cobra_name;
- cobra->dev[i].phys = cobra->phys[i];
- cobra->dev[i].id.bustype = BUS_GAMEPORT;
- cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
- cobra->dev[i].id.product = 0x0008;
- cobra->dev[i].id.version = 0x0100;
+ sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
- cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->name = "Creative Labs Blaster GamePad Cobra";
+ input_dev->phys = cobra->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
+ input_dev->id.product = 0x0008;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = cobra;
- input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
- input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
+ input_dev->open = cobra_open;
+ input_dev->close = cobra_close;
- for (j = 0; cobra_btn[j]; j++)
- set_bit(cobra_btn[j], cobra->dev[i].keybit);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
+ for (j = 0; cobra_btn[j]; j++)
+ set_bit(cobra_btn[j], input_dev->keybit);
- input_register_device(&cobra->dev[i]);
- printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
- }
+ input_register_device(cobra->dev[i]);
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: for (i = 0; i < 2; i++)
+ if (cobra->dev[i])
+ input_unregister_device(cobra->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(cobra);
return err;
}
@@ -234,7 +243,7 @@ static void cobra_disconnect(struct gameport *gameport)
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1)
- input_unregister_device(cobra->dev + i);
+ input_unregister_device(cobra->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(cobra);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index fbd3eed07f90..499344c72756 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -43,25 +43,28 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
MODULE_LICENSE("GPL");
-static int db9[] __initdata = { -1, 0 };
-static int db9_nargs __initdata = 0;
-module_param_array_named(dev, db9, int, &db9_nargs, 0);
-MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
+struct db9_config {
+ int args[2];
+ int nargs;
+};
-static int db9_2[] __initdata = { -1, 0 };
-static int db9_nargs_2 __initdata = 0;
-module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
-MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
+#define DB9_MAX_PORTS 3
+static struct db9_config db9[DB9_MAX_PORTS] __initdata;
-static int db9_3[] __initdata = { -1, 0 };
-static int db9_nargs_3 __initdata = 0;
-module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
+module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
+MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
+module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
+MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
+module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
__obsolete_setup("db9=");
__obsolete_setup("db9_2=");
__obsolete_setup("db9_3=");
+#define DB9_ARG_PARPORT 0
+#define DB9_ARG_MODE 1
+
#define DB9_MULTI_STICK 0x01
#define DB9_MULTI2_STICK 0x02
#define DB9_GENESIS_PAD 0x03
@@ -87,40 +90,53 @@ __obsolete_setup("db9_3=");
#define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08
-#define DB9_MAX_DEVICES 2
-
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
+#define DB9_MAX_DEVICES 2
+
+struct db9_mode_data {
+ const char *name;
+ const short *buttons;
+ int n_buttons;
+ int n_pads;
+ int n_axis;
+ int bidirectional;
+ int reverse;
+};
+
struct db9 {
- struct input_dev dev[DB9_MAX_DEVICES];
+ struct input_dev *dev[DB9_MAX_DEVICES];
struct timer_list timer;
struct pardevice *pd;
int mode;
int used;
struct semaphore sem;
- char phys[2][32];
+ char phys[DB9_MAX_DEVICES][32];
};
static struct db9 *db9_base[3];
-static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
-static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
-static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
-
-static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
-static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
- db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
- db9_cd32_btn, db9_cd32_btn };
-static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
- NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
- "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
-
-static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
-static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
+static const short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
+static const short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
+static const short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
-static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
+
+static const struct db9_mode_data db9_modes[] = {
+ { NULL, NULL, 0, 0, 0, 0, 0 },
+ { "Multisystem joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
+ { "Multisystem joystick (2 fire)", db9_multi_btn, 2, 1, 2, 1, 1 },
+ { "Genesis pad", db9_genesis_btn, 4, 1, 2, 1, 1 },
+ { NULL, NULL, 0, 0, 0, 0, 0 },
+ { "Genesis 5 pad", db9_genesis_btn, 6, 1, 2, 1, 1 },
+ { "Genesis 6 pad", db9_genesis_btn, 8, 1, 2, 1, 1 },
+ { "Saturn pad", db9_cd32_btn, 9, 6, 7, 0, 1 },
+ { "Multisystem (0.8.0.2) joystick", db9_multi_btn, 1, 1, 2, 1, 1 },
+ { "Multisystem (0.8.0.2-dual) joystick", db9_multi_btn, 1, 2, 2, 1, 1 },
+ { "Amiga CD-32 pad", db9_cd32_btn, 7, 1, 2, 1, 1 },
+ { "Saturn dpp", db9_cd32_btn, 9, 6, 7, 0, 0 },
+ { "Saturn dpp dual", db9_cd32_btn, 9, 12, 7, 0, 0 },
+};
/*
* Saturn controllers
@@ -342,7 +358,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
default:
return -1;
}
- max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
+ max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
for (tmp = 0, i = 0; i < n; i++) {
id = db9_saturn_read_packet(port, data, type + i, 1);
tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
@@ -354,17 +370,18 @@ static void db9_timer(unsigned long private)
{
struct db9 *db9 = (void *) private;
struct parport *port = db9->pd->port;
- struct input_dev *dev = db9->dev;
+ struct input_dev *dev = db9->dev[0];
+ struct input_dev *dev2 = db9->dev[1];
int data, i;
- switch(db9->mode) {
+ switch (db9->mode) {
case DB9_MULTI_0802_2:
data = parport_read_data(port) >> 3;
- input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
- input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
- input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
+ input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+ input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
+ input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
case DB9_MULTI_0802:
@@ -405,7 +422,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -414,7 +431,7 @@ static void db9_timer(unsigned long private)
case DB9_GENESIS5_PAD:
parport_write_control(port, DB9_NOSELECT);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -422,7 +439,7 @@ static void db9_timer(unsigned long private)
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
@@ -434,7 +451,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NOSELECT); /* 1 */
udelay(DB9_GENESIS6_DELAY);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -443,7 +460,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -477,7 +494,7 @@ static void db9_timer(unsigned long private)
case DB9_CD32_PAD:
- data=parport_read_data(port);
+ data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
@@ -489,7 +506,7 @@ static void db9_timer(unsigned long private)
parport_write_control(port, 0x02);
parport_write_control(port, 0x0a);
input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
- }
+ }
parport_write_control(port, 0x00);
break;
@@ -513,7 +530,7 @@ static int db9_open(struct input_dev *dev)
if (!db9->used++) {
parport_claim(db9->pd);
parport_write_data(port, 0xff);
- if (db9_reverse[db9->mode]) {
+ if (db9_modes[db9->mode].reverse) {
parport_data_reverse(port);
parport_write_control(port, DB9_NORMAL);
}
@@ -539,117 +556,160 @@ static void db9_close(struct input_dev *dev)
up(&db9->sem);
}
-static struct db9 __init *db9_probe(int *config, int nargs)
+static struct db9 __init *db9_probe(int parport, int mode)
{
struct db9 *db9;
+ const struct db9_mode_data *db9_mode;
struct parport *pp;
+ struct pardevice *pd;
+ struct input_dev *input_dev;
int i, j;
+ int err;
- if (config[0] < 0)
- return NULL;
-
- if (nargs < 2) {
- printk(KERN_ERR "db9.c: Device type must be specified.\n");
- return NULL;
+ if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
+ printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
+ err = -EINVAL;
+ goto err_out;
}
- if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
- printk(KERN_ERR "db9.c: bad config\n");
- return NULL;
- }
+ db9_mode = &db9_modes[mode];
- pp = parport_find_number(config[0]);
+ pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "db9.c: no such parport\n");
- return NULL;
+ err = -ENODEV;
+ goto err_out;
}
- if (db9_bidirectional[config[1]]) {
- if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
- printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
- parport_put_port(pp);
- return NULL;
- }
+ if (db9_mode[mode].bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
+ printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+ err = -EINVAL;
+ goto err_put_pp;
+ }
+
+ pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
+ printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
+ err = -EBUSY;
+ goto err_put_pp;
}
- if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
+ if (!db9) {
+ printk(KERN_ERR "db9.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
}
init_MUTEX(&db9->sem);
- db9->mode = config[1];
+ db9->pd = pd;
+ db9->mode = mode;
init_timer(&db9->timer);
db9->timer.data = (long) db9;
db9->timer.function = db9_timer;
- db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
- parport_put_port(pp);
-
- if (!db9->pd) {
- printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
- kfree(db9);
- return NULL;
- }
+ for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {
- for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
+ db9->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "db9.c: Not enough memory for input device\n");
+ err = -ENOMEM;
+ goto err_free_devs;
+ }
sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
- db9->dev[i].private = db9;
- db9->dev[i].open = db9_open;
- db9->dev[i].close = db9_close;
-
- db9->dev[i].name = db9_name[db9->mode];
- db9->dev[i].phys = db9->phys[i];
- db9->dev[i].id.bustype = BUS_PARPORT;
- db9->dev[i].id.vendor = 0x0002;
- db9->dev[i].id.product = config[1];
- db9->dev[i].id.version = 0x0100;
-
- db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; j < db9_buttons[db9->mode]; j++)
- set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
- for (j = 0; j < db9_num_axis[db9->mode]; j++) {
- set_bit(db9_abs[j], db9->dev[i].absbit);
- if (j < 2) {
- db9->dev[i].absmin[db9_abs[j]] = -1;
- db9->dev[i].absmax[db9_abs[j]] = 1;
- } else {
- db9->dev[i].absmin[db9_abs[j]] = 1;
- db9->dev[i].absmax[db9_abs[j]] = 255;
- db9->dev[i].absflat[db9_abs[j]] = 0;
- }
+ input_dev->name = db9_mode->name;
+ input_dev->phys = db9->phys[i];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0002;
+ input_dev->id.product = mode;
+ input_dev->id.version = 0x0100;
+ input_dev->private = db9;
+
+ input_dev->open = db9_open;
+ input_dev->close = db9_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ for (j = 0; j < db9_mode->n_buttons; j++)
+ set_bit(db9_mode->buttons[j], input_dev->keybit);
+ for (j = 0; j < db9_mode->n_axis; j++) {
+ if (j < 2)
+ input_set_abs_params(input_dev, db9_abs[j], -1, 1, 0, 0);
+ else
+ input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
}
- input_register_device(db9->dev + i);
- printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
+
+ input_register_device(input_dev);
}
+ parport_put_port(pp);
return db9;
+
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(db9->dev[i]);
+ kfree(db9);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
+
+static void __exit db9_remove(struct db9 *db9)
+{
+ int i;
+
+ for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
+ input_unregister_device(db9->dev[i]);
+ parport_unregister_device(db9->pd);
+ kfree(db9);
}
static int __init db9_init(void)
{
- db9_base[0] = db9_probe(db9, db9_nargs);
- db9_base[1] = db9_probe(db9_2, db9_nargs_2);
- db9_base[2] = db9_probe(db9_3, db9_nargs_3);
+ int i;
+ int have_dev = 0;
+ int err = 0;
+
+ for (i = 0; i < DB9_MAX_PORTS; i++) {
+ if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
+ continue;
+
+ if (db9[i].nargs < 2) {
+ printk(KERN_ERR "db9.c: Device type must be specified.\n");
+ err = -EINVAL;
+ break;
+ }
+
+ db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
+ db9[i].args[DB9_ARG_MODE]);
+ if (IS_ERR(db9_base[i])) {
+ err = PTR_ERR(db9_base[i]);
+ break;
+ }
+
+ have_dev = 1;
+ }
- if (db9_base[0] || db9_base[1] || db9_base[2])
- return 0;
+ if (err) {
+ while (--i >= 0)
+ db9_remove(db9_base[i]);
+ return err;
+ }
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit db9_exit(void)
{
- int i, j;
+ int i;
- for (i = 0; i < 3; i++)
- if (db9_base[i]) {
- for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
- input_unregister_device(db9_base[i]->dev + j);
- parport_unregister_device(db9_base[i]->pd);
- }
+ for (i = 0; i < DB9_MAX_PORTS; i++)
+ if (db9_base[i])
+ db9_remove(db9_base[i]);
}
module_init(db9_init);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 95bbdd302aad..7df2d82f2c83 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL");
-static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs __initdata = 0;
-module_param_array_named(map, gc, int, &gc_nargs, 0);
-MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+#define GC_MAX_PORTS 3
+#define GC_MAX_DEVICES 5
-static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_2 __initdata = 0;
-module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
-MODULE_PARM_DESC(map2, "Describers second set of devices");
+struct gc_config {
+ int args[GC_MAX_DEVICES + 1];
+ int nargs;
+};
+
+static struct gc_config gc[GC_MAX_PORTS] __initdata;
-static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_3 __initdata = 0;
-module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
-MODULE_PARM_DESC(map3, "Describers third set of devices");
+module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
+MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("gc=");
__obsolete_setup("gc_2=");
@@ -77,12 +79,12 @@ __obsolete_setup("gc_3=");
struct gc {
struct pardevice *pd;
- struct input_dev dev[5];
+ struct input_dev *dev[GC_MAX_DEVICES];
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
struct semaphore sem;
- char phys[5][32];
+ char phys[GC_MAX_DEVICES][32];
};
static struct gc *gc_base[3];
@@ -330,7 +332,6 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
static void gc_timer(unsigned long private)
{
struct gc *gc = (void *) private;
- struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
@@ -357,16 +358,16 @@ static void gc_timer(unsigned long private)
if (data[31 - j] & s) axes[1] |= 1 << j;
}
- input_report_abs(dev + i, ABS_X, axes[0]);
- input_report_abs(dev + i, ABS_Y, -axes[1]);
+ input_report_abs(gc->dev[i], ABS_X, axes[0]);
+ input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
- input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
- input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+ input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++)
- input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+ input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
}
@@ -384,19 +385,19 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
- input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
- input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
+ input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
+ input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
}
if (s & gc->pads[GC_NES])
for (j = 0; j < 4; j++)
- input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+ input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
if (s & gc->pads[GC_SNES])
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+ input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
@@ -413,15 +414,15 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
- input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3]));
- input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1]));
- input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
+ input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3]));
+ input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1]));
+ input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
}
if (s & gc->pads[GC_MULTI2])
- input_report_key(dev + i, BTN_THUMB, s & data[5]);
+ input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
}
}
@@ -438,44 +439,44 @@ static void gc_timer(unsigned long private)
case GC_PSX_RUMBLE:
- input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
- input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
+ input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
+ input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
case GC_PSX_NEGCON:
case GC_PSX_ANALOG:
- if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
- input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+ input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
for (j = 0; j < 4; j++)
- input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
+ input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
- input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
- input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+ input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+ input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
}
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+ input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
- input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
- input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+ input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
+ input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
break;
case GC_PSX_NORMAL:
- if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+ if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
- input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+ input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
- input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
- input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+ input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+ input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
- input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+ input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
@@ -483,12 +484,12 @@ static void gc_timer(unsigned long private)
}
for (j = 0; j < 8; j++)
- input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+ input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
- input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
- input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+ input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
+ input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
- input_sync(dev + i);
+ input_sync(gc->dev[i]);
break;
@@ -533,177 +534,212 @@ static void gc_close(struct input_dev *dev)
up(&gc->sem);
}
-static struct gc __init *gc_probe(int *config, int nargs)
+static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
- struct gc *gc;
- struct parport *pp;
- int i, j;
+ struct input_dev *input_dev;
+ int i;
- if (config[0] < 0)
- return NULL;
+ if (!pad_type)
+ return 0;
- if (nargs < 2) {
- printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
- return NULL;
+ if (pad_type < 1 || pad_type > GC_MAX) {
+ printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
+ return -EINVAL;
}
- pp = parport_find_number(config[0]);
-
- if (!pp) {
- printk(KERN_ERR "gamecon.c: no such parport\n");
- return NULL;
+ gc->dev[idx] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
+ return -ENOMEM;
}
- if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ input_dev->name = gc_names[pad_type];
+ input_dev->phys = gc->phys[idx];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = pad_type;
+ input_dev->id.version = 0x0100;
+ input_dev->private = gc;
+
+ input_dev->open = gc_open;
+ input_dev->close = gc_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+ for (i = 0; i < 2; i++)
+ input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+
+ gc->pads[0] |= gc_status_bit[idx];
+ gc->pads[pad_type] |= gc_status_bit[idx];
+
+ switch (pad_type) {
+
+ case GC_N64:
+ for (i = 0; i < 10; i++)
+ set_bit(gc_n64_btn[i], input_dev->keybit);
+
+ for (i = 0; i < 2; i++) {
+ input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
+ input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
+ }
+
+ break;
+
+ case GC_SNES:
+ for (i = 4; i < 8; i++)
+ set_bit(gc_snes_btn[i], input_dev->keybit);
+ case GC_NES:
+ for (i = 0; i < 4; i++)
+ set_bit(gc_snes_btn[i], input_dev->keybit);
+ break;
+
+ case GC_MULTI2:
+ set_bit(BTN_THUMB, input_dev->keybit);
+ case GC_MULTI:
+ set_bit(BTN_TRIGGER, input_dev->keybit);
+ break;
+
+ case GC_PSX:
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
+ for (i = 0; i < 12; i++)
+ set_bit(gc_psx_btn[i], input_dev->keybit);
+
+ break;
+
+ case GC_DDR:
+ for (i = 0; i < 4; i++)
+ set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
+ for (i = 0; i < 12; i++)
+ set_bit(gc_psx_btn[i], input_dev->keybit);
+
+ break;
}
- init_MUTEX(&gc->sem);
+ return 0;
+}
- gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
+{
+ struct gc *gc;
+ struct parport *pp;
+ struct pardevice *pd;
+ int i;
+ int err;
- parport_put_port(pp);
+ pp = parport_find_number(parport);
+ if (!pp) {
+ printk(KERN_ERR "gamecon.c: no such parport\n");
+ err = -EINVAL;
+ goto err_out;
+ }
- if (!gc->pd) {
+ pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
- kfree(gc);
- return NULL;
+ err = -EBUSY;
+ goto err_put_pp;
}
- parport_claim(gc->pd);
+ gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
+ if (!gc) {
+ printk(KERN_ERR "gamecon.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
+ }
+ init_MUTEX(&gc->sem);
+ gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
- for (i = 0; i < nargs - 1; i++) {
-
- if (!config[i + 1])
+ for (i = 0; i < n_pads; i++) {
+ if (!pads[i])
continue;
- if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
- printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
- continue;
- }
-
- gc->dev[i].private = gc;
- gc->dev[i].open = gc_open;
- gc->dev[i].close = gc_close;
+ sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+ err = gc_setup_pad(gc, i, pads[i]);
+ if (err)
+ goto err_free_devs;
- gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_register_device(gc->dev[i]);
+ }
- for (j = 0; j < 2; j++) {
- set_bit(ABS_X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_X + j] = -1;
- gc->dev[i].absmax[ABS_X + j] = 1;
- }
+ if (!gc->pads[0]) {
+ printk(KERN_ERR "gamecon.c: No valid devices specified\n");
+ err = -EINVAL;
+ goto err_free_gc;
+ }
- gc->pads[0] |= gc_status_bit[i];
- gc->pads[config[i + 1]] |= gc_status_bit[i];
+ parport_put_port(pp);
+ return gc;
- switch(config[i + 1]) {
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(gc->dev[i]);
+ err_free_gc:
+ kfree(gc);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
- case GC_N64:
- for (j = 0; j < 10; j++)
- set_bit(gc_n64_btn[j], gc->dev[i].keybit);
-
- for (j = 0; j < 2; j++) {
- set_bit(ABS_X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_X + j] = -127;
- gc->dev[i].absmax[ABS_X + j] = 126;
- gc->dev[i].absflat[ABS_X + j] = 2;
- set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
- gc->dev[i].absmin[ABS_HAT0X + j] = -1;
- gc->dev[i].absmax[ABS_HAT0X + j] = 1;
- }
+static void __exit gc_remove(struct gc *gc)
+{
+ int i;
- break;
+ for (i = 0; i < GC_MAX_DEVICES; i++)
+ if (gc->dev[i])
+ input_unregister_device(gc->dev[i]);
+ parport_unregister_device(gc->pd);
+ kfree(gc);
+}
- case GC_SNES:
- for (j = 4; j < 8; j++)
- set_bit(gc_snes_btn[j], gc->dev[i].keybit);
- case GC_NES:
- for (j = 0; j < 4; j++)
- set_bit(gc_snes_btn[j], gc->dev[i].keybit);
- break;
-
- case GC_MULTI2:
- set_bit(BTN_THUMB, gc->dev[i].keybit);
- case GC_MULTI:
- set_bit(BTN_TRIGGER, gc->dev[i].keybit);
- break;
-
- case GC_PSX:
- case GC_DDR:
- if(config[i + 1] == GC_DDR) {
- for (j = 0; j < 4; j++)
- set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
- } else {
- for (j = 0; j < 6; j++) {
- set_bit(gc_psx_abs[j], gc->dev[i].absbit);
- gc->dev[i].absmin[gc_psx_abs[j]] = 4;
- gc->dev[i].absmax[gc_psx_abs[j]] = 252;
- gc->dev[i].absflat[gc_psx_abs[j]] = 2;
- }
- }
+static int __init gc_init(void)
+{
+ int i;
+ int have_dev = 0;
+ int err = 0;
- for (j = 0; j < 12; j++)
- set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+ for (i = 0; i < GC_MAX_PORTS; i++) {
+ if (gc[i].nargs == 0 || gc[i].args[0] < 0)
+ continue;
- break;
+ if (gc[i].nargs < 2) {
+ printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
+ err = -EINVAL;
+ break;
}
- sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+ gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
+ if (IS_ERR(gc_base[i])) {
+ err = PTR_ERR(gc_base[i]);
+ break;
+ }
- gc->dev[i].name = gc_names[config[i + 1]];
- gc->dev[i].phys = gc->phys[i];
- gc->dev[i].id.bustype = BUS_PARPORT;
- gc->dev[i].id.vendor = 0x0001;
- gc->dev[i].id.product = config[i + 1];
- gc->dev[i].id.version = 0x0100;
+ have_dev = 1;
}
- parport_release(gc->pd);
-
- if (!gc->pads[0]) {
- parport_unregister_device(gc->pd);
- kfree(gc);
- return NULL;
+ if (err) {
+ while (--i >= 0)
+ gc_remove(gc_base[i]);
+ return err;
}
- for (i = 0; i < 5; i++)
- if (gc->pads[0] & gc_status_bit[i]) {
- input_register_device(gc->dev + i);
- printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
- }
-
- return gc;
-}
-
-static int __init gc_init(void)
-{
- gc_base[0] = gc_probe(gc, gc_nargs);
- gc_base[1] = gc_probe(gc_2, gc_nargs_2);
- gc_base[2] = gc_probe(gc_3, gc_nargs_3);
-
- if (gc_base[0] || gc_base[1] || gc_base[2])
- return 0;
-
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit gc_exit(void)
{
- int i, j;
-
- for (i = 0; i < 3; i++)
- if (gc_base[i]) {
- for (j = 0; j < 5; j++)
- if (gc_base[i]->pads[0] & gc_status_bit[j])
- input_unregister_device(gc_base[i]->dev + j);
- parport_unregister_device(gc_base[i]->pd);
- }
+ int i;
+
+ for (i = 0; i < GC_MAX_PORTS; i++)
+ if (gc_base[i])
+ gc_remove(gc_base[i]);
}
module_init(gc_init);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 7d969420066c..8a3ad455eb38 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/gameport.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Genius Flight 2000 joystick driver"
@@ -81,7 +82,7 @@ static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
struct gf2k {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int reads;
int bads;
unsigned char id;
@@ -175,7 +176,7 @@ static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
{
- struct input_dev *dev = &gf2k->dev;
+ struct input_dev *dev = gf2k->dev;
int i, t;
for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
@@ -239,13 +240,19 @@ static void gf2k_close(struct input_dev *dev)
static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct gf2k *gf2k;
+ struct input_dev *input_dev;
unsigned char data[GF2K_LENGTH];
int i, err;
- if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
- return -ENOMEM;
+ gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!gf2k || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
gf2k->gameport = gameport;
+ gf2k->dev = input_dev;
gameport_set_drvdata(gameport, gf2k);
@@ -295,53 +302,52 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
gf2k->length = gf2k_lens[gf2k->id];
- init_input_dev(&gf2k->dev);
-
- gf2k->dev.private = gf2k;
- gf2k->dev.open = gf2k_open;
- gf2k->dev.close = gf2k_close;
- gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->name = gf2k_names[gf2k->id];
+ input_dev->phys = gf2k->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
+ input_dev->id.product = gf2k->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = gf2k;
- gf2k->dev.name = gf2k_names[gf2k->id];
- gf2k->dev.phys = gf2k->phys;
- gf2k->dev.id.bustype = BUS_GAMEPORT;
- gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
- gf2k->dev.id.product = gf2k->id;
- gf2k->dev.id.version = 0x0100;
+ input_dev->open = gf2k_open;
+ input_dev->close = gf2k_close;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < gf2k_axes[gf2k->id]; i++)
- set_bit(gf2k_abs[i], gf2k->dev.absbit);
+ set_bit(gf2k_abs[i], input_dev->absbit);
for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
- set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
- gf2k->dev.absmin[ABS_HAT0X + i] = -1;
- gf2k->dev.absmax[ABS_HAT0X + i] = 1;
+ set_bit(ABS_HAT0X + i, input_dev->absbit);
+ input_dev->absmin[ABS_HAT0X + i] = -1;
+ input_dev->absmax[ABS_HAT0X + i] = 1;
}
for (i = 0; i < gf2k_joys[gf2k->id]; i++)
- set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
+ set_bit(gf2k_btn_joy[i], input_dev->keybit);
for (i = 0; i < gf2k_pads[gf2k->id]; i++)
- set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
+ set_bit(gf2k_btn_pad[i], input_dev->keybit);
gf2k_read_packet(gameport, gf2k->length, data);
gf2k_read(gf2k, data);
for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
- gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
- gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
- gf2k->dev.absmin[gf2k_abs[i]] = 32;
- gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
- gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
+ input_dev->absmax[gf2k_abs[i]] = (i < 2) ? input_dev->abs[gf2k_abs[i]] * 2 - 32 :
+ input_dev->abs[gf2k_abs[0]] + input_dev->abs[gf2k_abs[1]] - 32;
+ input_dev->absmin[gf2k_abs[i]] = 32;
+ input_dev->absfuzz[gf2k_abs[i]] = 8;
+ input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
}
- input_register_device(&gf2k->dev);
- printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
+ input_register_device(gf2k->dev);
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(gf2k);
return err;
}
@@ -350,7 +356,7 @@ static void gf2k_disconnect(struct gameport *gameport)
{
struct gf2k *gf2k = gameport_get_drvdata(gameport);
- input_unregister_device(&gf2k->dev);
+ input_unregister_device(gf2k->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(gf2k);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index d1500d2562d6..a936e7aedb10 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
@@ -55,7 +56,7 @@ MODULE_LICENSE("GPL");
struct grip {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct input_dev *dev[2];
unsigned char mode[2];
int reads;
int bads;
@@ -190,7 +191,7 @@ static void grip_poll(struct gameport *gameport)
for (i = 0; i < 2; i++) {
- dev = grip->dev + i;
+ dev = grip->dev[i];
grip->reads++;
switch (grip->mode[i]) {
@@ -297,11 +298,12 @@ static void grip_close(struct input_dev *dev)
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
+ struct input_dev *input_dev;
unsigned int data[GRIP_LENGTH_XT];
int i, j, t;
int err;
- if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+ if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
return -ENOMEM;
grip->gameport = gameport;
@@ -339,48 +341,56 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, grip_poll);
gameport_set_poll_interval(gameport, 20);
- for (i = 0; i < 2; i++)
- if (grip->mode[i]) {
+ for (i = 0; i < 2; i++) {
+ if (!grip->mode[i])
+ continue;
- sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+ grip->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- grip->dev[i].private = grip;
+ sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
- grip->dev[i].open = grip_open;
- grip->dev[i].close = grip_close;
+ input_dev->name = grip_name[grip->mode[i]];
+ input_dev->phys = grip->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+ input_dev->id.product = grip->mode[i];
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = grip;
- grip->dev[i].name = grip_name[grip->mode[i]];
- grip->dev[i].phys = grip->phys[i];
- grip->dev[i].id.bustype = BUS_GAMEPORT;
- grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
- grip->dev[i].id.product = grip->mode[i];
- grip->dev[i].id.version = 0x0100;
+ input_dev->open = grip_open;
+ input_dev->close = grip_close;
- grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
+ for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
- if (j < grip_cen[grip->mode[i]])
- input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
- else if (j < grip_anx[grip->mode[i]])
- input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
- else
- input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
- }
+ if (j < grip_cen[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 14, 52, 1, 2);
+ else if (j < grip_anx[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 3, 57, 1, 0);
+ else
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ }
- for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
- if (t > 0)
- set_bit(t, grip->dev[i].keybit);
+ for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
+ if (t > 0)
+ set_bit(t, input_dev->keybit);
- printk(KERN_INFO "input: %s on %s\n",
- grip_name[grip->mode[i]], gameport->phys);
- input_register_device(grip->dev + i);
- }
+ input_register_device(grip->dev[i]);
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: for (i = 0; i < 2; i++)
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(grip);
return err;
}
@@ -391,8 +401,8 @@ static void grip_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < 2; i++)
- if (grip->mode[i])
- input_unregister_device(grip->dev + i);
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(grip);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 0da7bd133ccf..51a912222e85 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Gravis Grip Multiport driver"
@@ -32,23 +33,37 @@ MODULE_LICENSE("GPL");
#define dbg(format, arg...) do {} while (0)
#endif
+#define GRIP_MAX_PORTS 4
/*
* Grip multiport state
*/
+struct grip_port {
+ struct input_dev *dev;
+ int mode;
+ int registered;
+
+ /* individual gamepad states */
+ int buttons;
+ int xaxes;
+ int yaxes;
+ int dirty; /* has the state been updated? */
+};
+
struct grip_mp {
struct gameport *gameport;
- struct input_dev dev[4];
- int mode[4];
- int registered[4];
+ struct grip_port *port[GRIP_MAX_PORTS];
+// struct input_dev *dev[4];
+// int mode[4];
+// int registered[4];
int reads;
int bads;
/* individual gamepad states */
- int buttons[4];
- int xaxes[4];
- int yaxes[4];
- int dirty[4]; /* has the state been updated? */
+// int buttons[4];
+// int xaxes[4];
+// int yaxes[4];
+// int dirty[4]; /* has the state been updated? */
};
/*
@@ -85,16 +100,16 @@ struct grip_mp {
#define GRIP_MODE_GP 2
#define GRIP_MODE_C64 3
-static int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
-static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
+static const int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
+static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
-static int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
-static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
-static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
-static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
+static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
+static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
-static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
+static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
static const int init_seq[] = {
1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
@@ -104,9 +119,9 @@ static const int init_seq[] = {
/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
-static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
+static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
-static void register_slot(int i, struct grip_mp *grip);
+static int register_slot(int i, struct grip_mp *grip);
/*
* Returns whether an odd or even number of bits are on in pkt.
@@ -353,9 +368,10 @@ static int dig_mode_start(struct gameport *gameport, u32 *packet)
static int get_and_decode_packet(struct grip_mp *grip, int flags)
{
+ struct grip_port *port;
u32 packet;
int joytype = 0;
- int slot = 0;
+ int slot;
/* Get a packet and check for validity */
@@ -377,6 +393,8 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if ((slot < 0) || (slot > 3))
return flags;
+ port = grip->port[slot];
+
/*
* Handle "reset" packets, which occur at startup, and when gamepads
* are removed or plugged in. May contain configuration of a new gamepad.
@@ -385,14 +403,14 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
joytype = (packet >> 16) & 0x1f;
if (!joytype) {
- if (grip->registered[slot]) {
+ if (port->registered) {
printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
- grip_name[grip->mode[slot]], slot);
- input_unregister_device(grip->dev + slot);
- grip->registered[slot] = 0;
+ grip_name[port->mode], slot);
+ input_unregister_device(port->dev);
+ port->registered = 0;
}
dbg("Reset: grip multiport slot %d\n", slot);
- grip->mode[slot] = GRIP_MODE_RESET;
+ port->mode = GRIP_MODE_RESET;
flags |= IO_SLOT_CHANGE;
return flags;
}
@@ -402,17 +420,17 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if (joytype == 0x1f) {
int dir = (packet >> 8) & 0xf; /* eight way directional value */
- grip->buttons[slot] = (~packet) & 0xff;
- grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
- grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
- grip->dirty[slot] = 1;
+ port->buttons = (~packet) & 0xff;
+ port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
+ port->xaxes = (axis_map[dir] & 3) - 1;
+ port->dirty = 1;
- if (grip->mode[slot] == GRIP_MODE_RESET)
+ if (port->mode == GRIP_MODE_RESET)
flags |= IO_SLOT_CHANGE;
- grip->mode[slot] = GRIP_MODE_GP;
+ port->mode = GRIP_MODE_GP;
- if (!grip->registered[slot]) {
+ if (!port->registered) {
dbg("New Grip pad in multiport slot %d.\n", slot);
register_slot(slot, grip);
}
@@ -445,9 +463,9 @@ static int slots_valid(struct grip_mp *grip)
return 0;
for (slot = 0; slot < 4; slot++) {
- if (grip->mode[slot] == GRIP_MODE_RESET)
+ if (grip->port[slot]->mode == GRIP_MODE_RESET)
invalid = 1;
- if (grip->mode[slot] != GRIP_MODE_NONE)
+ if (grip->port[slot]->mode != GRIP_MODE_NONE)
active = 1;
}
@@ -484,7 +502,7 @@ static int multiport_init(struct grip_mp *grip)
/* Get packets, store multiport state, and check state's validity */
for (tries = 0; tries < 4096; tries++) {
- if ( slots_valid(grip) ) {
+ if (slots_valid(grip)) {
initialized = 1;
break;
}
@@ -499,24 +517,24 @@ static int multiport_init(struct grip_mp *grip)
static void report_slot(struct grip_mp *grip, int slot)
{
- struct input_dev *dev = &(grip->dev[slot]);
- int i, buttons = grip->buttons[slot];
+ struct grip_port *port = grip->port[slot];
+ int i;
/* Store button states with linux input driver */
for (i = 0; i < 8; i++)
- input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
+ input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
/* Store axis states with linux driver */
- input_report_abs(dev, ABS_X, grip->xaxes[slot]);
- input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
+ input_report_abs(port->dev, ABS_X, port->xaxes);
+ input_report_abs(port->dev, ABS_Y, port->yaxes);
/* Tell the receiver of the events to process them */
- input_sync(dev);
+ input_sync(port->dev);
- grip->dirty[slot] = 0;
+ port->dirty = 0;
}
/*
@@ -540,7 +558,7 @@ static void grip_poll(struct gameport *gameport)
}
for (i = 0; i < 4; i++)
- if (grip->dirty[i])
+ if (grip->port[i]->dirty)
report_slot(grip, i);
}
@@ -571,35 +589,43 @@ static void grip_close(struct input_dev *dev)
* Tell the linux input layer about a newly plugged-in gamepad.
*/
-static void register_slot(int slot, struct grip_mp *grip)
+static int register_slot(int slot, struct grip_mp *grip)
{
+ struct grip_port *port = grip->port[slot];
+ struct input_dev *input_dev;
int j, t;
- grip->dev[slot].private = grip;
- grip->dev[slot].open = grip_open;
- grip->dev[slot].close = grip_close;
- grip->dev[slot].name = grip_name[grip->mode[slot]];
- grip->dev[slot].id.bustype = BUS_GAMEPORT;
- grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
- grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
- grip->dev[slot].id.version = 0x0100;
- grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ port->dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = grip_name[port->mode];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+ input_dev->id.product = 0x0100 + port->mode;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &grip->gameport->dev;
+ input_dev->private = grip;
+
+ input_dev->open = grip_open;
+ input_dev->close = grip_close;
- for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
- input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
+ for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+
+ for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
if (t > 0)
- set_bit(t, grip->dev[slot].keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(grip->dev + slot);
- grip->registered[slot] = 1;
+ input_register_device(port->dev);
+ port->registered = 1;
- if (grip->dirty[slot]) /* report initial state, if any */
+ if (port->dirty) /* report initial state, if any */
report_slot(grip, slot);
- printk(KERN_INFO "grip_mp: added %s, slot %d\n",
- grip_name[grip->mode[slot]], slot);
+ return 0;
}
static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
@@ -607,7 +633,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
struct grip_mp *grip;
int err;
- if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+ if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
return -ENOMEM;
grip->gameport = gameport;
@@ -626,7 +652,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
goto fail2;
}
- if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+ if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
/* nothing plugged in */
err = -ENODEV;
goto fail2;
@@ -646,8 +672,8 @@ static void grip_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < 4; i++)
- if (grip->registered[i])
- input_unregister_device(grip->dev + i);
+ if (grip->port[i]->registered)
+ input_unregister_device(grip->port[i]->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(grip);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index f93da7bc082d..6e2c721c26ba 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Guillemot Digital joystick driver"
@@ -67,7 +68,7 @@ struct guillemot_type {
struct guillemot {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int bads;
int reads;
struct guillemot_type *type;
@@ -123,7 +124,7 @@ static int guillemot_read_packet(struct gameport *gameport, u8 *data)
static void guillemot_poll(struct gameport *gameport)
{
struct guillemot *guillemot = gameport_get_drvdata(gameport);
- struct input_dev *dev = &guillemot->dev;
+ struct input_dev *dev = guillemot->dev;
u8 data[GUILLEMOT_MAX_LENGTH];
int i;
@@ -179,14 +180,20 @@ static void guillemot_close(struct input_dev *dev)
static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct guillemot *guillemot;
+ struct input_dev *input_dev;
u8 data[GUILLEMOT_MAX_LENGTH];
int i, t;
int err;
- if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
- return -ENOMEM;
+ guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!guillemot || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
guillemot->gameport = gameport;
+ guillemot->dev = input_dev;
gameport_set_drvdata(gameport, guillemot);
@@ -216,41 +223,40 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
gameport_set_poll_interval(gameport, 20);
sprintf(guillemot->phys, "%s/input0", gameport->phys);
-
guillemot->type = guillemot_type + i;
- guillemot->dev.private = guillemot;
- guillemot->dev.open = guillemot_open;
- guillemot->dev.close = guillemot_close;
+ input_dev->name = guillemot_type[i].name;
+ input_dev->phys = guillemot->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
+ input_dev->id.product = guillemot_type[i].id;
+ input_dev->id.version = (int)data[14] << 8 | data[15];
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = guillemot;
- guillemot->dev.name = guillemot_type[i].name;
- guillemot->dev.phys = guillemot->phys;
- guillemot->dev.id.bustype = BUS_GAMEPORT;
- guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
- guillemot->dev.id.product = guillemot_type[i].id;
- guillemot->dev.id.version = (int)data[14] << 8 | data[15];
+ input_dev->open = guillemot_open;
+ input_dev->close = guillemot_close;
- guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
- input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
if (guillemot->type->hat) {
- input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
- input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
}
for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
- set_bit(t, guillemot->dev.keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(&guillemot->dev);
- printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
- guillemot->type->name, data[14], data[15], gameport->phys);
+ input_register_device(guillemot->dev);
return 0;
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(guillemot);
return err;
}
@@ -260,7 +266,7 @@ static void guillemot_disconnect(struct gameport *gameport)
struct guillemot *guillemot = gameport_get_drvdata(gameport);
printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
- input_unregister_device(&guillemot->dev);
+ input_unregister_device(guillemot->dev);
gameport_close(gameport);
kfree(guillemot);
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index e31b7b93fde2..64b9c31c47fc 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -144,7 +144,7 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
int is_update;
/* Check this effect type is supported by this device */
- if (!test_bit(effect->type, iforce->dev.ffbit))
+ if (!test_bit(effect->type, iforce->dev->ffbit))
return -EINVAL;
/*
@@ -152,30 +152,31 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
*/
if (effect->id == -1) {
- for (id=0; id < FF_EFFECTS_MAX; ++id)
- if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
+ for (id = 0; id < FF_EFFECTS_MAX; ++id)
+ if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags))
+ break;
- if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
+ if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max)
return -ENOMEM;
effect->id = id;
iforce->core_effects[id].owner = current->pid;
- iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
+ iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED); /* Only IS_USED bit must be set */
is_update = FALSE;
}
else {
/* We want to update an effect */
- if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
+ if (!CHECK_OWNERSHIP(effect->id, iforce))
+ return -EACCES;
/* Parameter type cannot be updated */
if (effect->type != iforce->core_effects[effect->id].effect.type)
return -EINVAL;
/* Check the effect is not already being updated */
- if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
+ if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags))
return -EAGAIN;
- }
is_update = TRUE;
}
@@ -339,15 +340,19 @@ void iforce_delete_device(struct iforce *iforce)
int iforce_init_device(struct iforce *iforce)
{
+ struct input_dev *input_dev;
unsigned char c[] = "CEOV";
int i;
+ input_dev = input_allocate_device();
+ if (input_dev)
+ return -ENOMEM;
+
init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock);
init_MUTEX(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data;
-
- iforce->dev.ff_effects_max = 10;
+ iforce->dev = input_dev;
/*
* Input device fields.
@@ -356,26 +361,27 @@ int iforce_init_device(struct iforce *iforce)
switch (iforce->bus) {
#ifdef CONFIG_JOYSTICK_IFORCE_USB
case IFORCE_USB:
- iforce->dev.id.bustype = BUS_USB;
- iforce->dev.dev = &iforce->usbdev->dev;
+ input_dev->id.bustype = BUS_USB;
+ input_dev->cdev.dev = &iforce->usbdev->dev;
break;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
case IFORCE_232:
- iforce->dev.id.bustype = BUS_RS232;
- iforce->dev.dev = &iforce->serio->dev;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->cdev.dev = &iforce->serio->dev;
break;
#endif
}
- iforce->dev.private = iforce;
- iforce->dev.name = "Unknown I-Force device";
- iforce->dev.open = iforce_open;
- iforce->dev.close = iforce_release;
- iforce->dev.flush = iforce_flush;
- iforce->dev.event = iforce_input_event;
- iforce->dev.upload_effect = iforce_upload_effect;
- iforce->dev.erase_effect = iforce_erase_effect;
+ input_dev->private = iforce;
+ input_dev->name = "Unknown I-Force device";
+ input_dev->open = iforce_open;
+ input_dev->close = iforce_release;
+ input_dev->flush = iforce_flush;
+ input_dev->event = iforce_input_event;
+ input_dev->upload_effect = iforce_upload_effect;
+ input_dev->erase_effect = iforce_erase_effect;
+ input_dev->ff_effects_max = 10;
/*
* On-device memory allocation.
@@ -399,7 +405,8 @@ int iforce_init_device(struct iforce *iforce)
if (i == 20) { /* 5 seconds */
printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
- return -1;
+ input_free_device(input_dev);
+ return -ENODEV;
}
/*
@@ -407,12 +414,12 @@ int iforce_init_device(struct iforce *iforce)
*/
if (!iforce_get_id_packet(iforce, "M"))
- iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
+ input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
if (!iforce_get_id_packet(iforce, "P"))
- iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1];
+ input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
@@ -422,15 +429,15 @@ int iforce_init_device(struct iforce *iforce)
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
if (!iforce_get_id_packet(iforce, "N"))
- iforce->dev.ff_effects_max = iforce->edata[1];
+ iforce->dev->ff_effects_max = iforce->edata[1];
else
printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
/* Check if the device can store more effects than the driver can really handle */
- if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
+ if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) {
printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
- iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
- iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
+ iforce->dev->ff_effects_max, FF_EFFECTS_MAX);
+ iforce->dev->ff_effects_max = FF_EFFECTS_MAX;
}
/*
@@ -453,29 +460,28 @@ int iforce_init_device(struct iforce *iforce)
*/
for (i = 0; iforce_device[i].idvendor; i++)
- if (iforce_device[i].idvendor == iforce->dev.id.vendor &&
- iforce_device[i].idproduct == iforce->dev.id.product)
+ if (iforce_device[i].idvendor == input_dev->id.vendor &&
+ iforce_device[i].idproduct == input_dev->id.product)
break;
iforce->type = iforce_device + i;
- iforce->dev.name = iforce->type->name;
+ input_dev->name = iforce->type->name;
/*
* Set input device bitfields and ranges.
*/
- iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
for (i = 0; iforce->type->btn[i] >= 0; i++) {
signed short t = iforce->type->btn[i];
- set_bit(t, iforce->dev.keybit);
+ set_bit(t, input_dev->keybit);
}
- set_bit(BTN_DEAD, iforce->dev.keybit);
+ set_bit(BTN_DEAD, input_dev->keybit);
for (i = 0; iforce->type->abs[i] >= 0; i++) {
signed short t = iforce->type->abs[i];
- set_bit(t, iforce->dev.absbit);
switch (t) {
@@ -483,52 +489,42 @@ int iforce_init_device(struct iforce *iforce)
case ABS_Y:
case ABS_WHEEL:
- iforce->dev.absmax[t] = 1920;
- iforce->dev.absmin[t] = -1920;
- iforce->dev.absflat[t] = 128;
- iforce->dev.absfuzz[t] = 16;
-
- set_bit(t, iforce->dev.ffbit);
+ input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
+ set_bit(t, input_dev->ffbit);
break;
case ABS_THROTTLE:
case ABS_GAS:
case ABS_BRAKE:
- iforce->dev.absmax[t] = 255;
- iforce->dev.absmin[t] = 0;
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
break;
case ABS_RUDDER:
- iforce->dev.absmax[t] = 127;
- iforce->dev.absmin[t] = -128;
+ input_set_abs_params(input_dev, t, -128, 127, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y:
case ABS_HAT1X:
case ABS_HAT1Y:
- iforce->dev.absmax[t] = 1;
- iforce->dev.absmin[t] = -1;
+
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
break;
}
}
for (i = 0; iforce->type->ff[i] >= 0; i++)
- set_bit(iforce->type->ff[i], iforce->dev.ffbit);
+ set_bit(iforce->type->ff[i], input_dev->ffbit);
/*
* Register input device.
*/
- input_register_device(&iforce->dev);
-
- printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
+ input_register_device(iforce->dev);
- printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
- iforce->dev.name, iforce->dev.ff_effects_max,
- iforce->device_memory.end);
+ printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
return 0;
}
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 58728ebaaf80..4a2629243e19 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -139,7 +139,8 @@ printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
{
int i;
- for (i=0; i<iforce->dev.ff_effects_max; ++i) {
+
+ for (i = 0; i < iforce->dev->ff_effects_max; ++i) {
if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
(iforce->core_effects[i].mod1_chunk.start == addr ||
iforce->core_effects[i].mod2_chunk.start == addr)) {
@@ -153,7 +154,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
{
- struct input_dev *dev = &iforce->dev;
+ struct input_dev *dev = iforce->dev;
int i;
static int being_used = 0;
@@ -249,9 +250,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
int iforce_get_id_packet(struct iforce *iforce, char *packet)
{
- DECLARE_WAITQUEUE(wait, current);
- int timeout = HZ; /* 1 second */
-
switch (iforce->bus) {
case IFORCE_USB:
@@ -260,22 +258,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->cr.bRequest = packet[0];
iforce->ctrl->dev = iforce->usbdev;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&iforce->wait, &wait);
-
- if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
+ if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
return -1;
- }
- while (timeout && iforce->ctrl->status == -EINPROGRESS)
- timeout = schedule_timeout(timeout);
+ wait_event_interruptible_timeout(iforce->wait,
+ iforce->ctrl->status != -EINPROGRESS, HZ);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
-
- if (!timeout) {
+ if (iforce->ctrl->status != -EINPROGRESS) {
usb_unlink_urb(iforce->ctrl);
return -1;
}
@@ -290,16 +279,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
iforce->expect_packet = FF_CMD_QUERY;
iforce_send_packet(iforce, FF_CMD_QUERY, packet);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&iforce->wait, &wait);
-
- while (timeout && iforce->expect_packet)
- timeout = schedule_timeout(timeout);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&iforce->wait, &wait);
+ wait_event_interruptible_timeout(iforce->wait,
+ !iforce->expect_packet, HZ);
- if (!timeout) {
+ if (iforce->expect_packet) {
iforce->expect_packet = 0;
return -1;
}
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 11f51905cba7..64a78c515484 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -131,11 +131,10 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
struct iforce *iforce;
int err;
- if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
+ iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
+ if (!iforce)
return -ENOMEM;
- memset(iforce, 0, sizeof(struct iforce));
-
iforce->bus = IFORCE_232;
iforce->serio = serio;
@@ -148,7 +147,8 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
return err;
}
- if (iforce_init_device(iforce)) {
+ err = iforce_init_device(iforce);
+ if (err) {
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(iforce);
@@ -162,7 +162,7 @@ static void iforce_serio_disconnect(struct serio *serio)
{
struct iforce *iforce = serio_get_drvdata(serio);
- input_unregister_device(&iforce->dev);
+ input_unregister_device(iforce->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(iforce);
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 6369a24684fe..64b4a3080985 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -95,6 +95,7 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
+ wake_up(&iforce->wait);
iforce_process_packet(iforce,
(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
@@ -134,28 +135,24 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce;
+ int err = -ENOMEM;
interface = intf->cur_altsetting;
epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc;
- if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
+ if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
goto fail;
- memset(iforce, 0, sizeof(struct iforce));
-
- if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
- if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
- if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
- }
iforce->bus = IFORCE_USB;
iforce->usbdev = dev;
@@ -173,7 +170,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
(void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
- if (iforce_init_device(iforce)) goto fail;
+ err = iforce_init_device(iforce);
+ if (err)
+ goto fail;
usb_set_intfdata(intf, iforce);
return 0;
@@ -186,7 +185,7 @@ fail:
kfree(iforce);
}
- return -ENODEV;
+ return err;
}
/* Called by iforce_delete() */
@@ -210,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (iforce) {
iforce->usbdev = NULL;
- input_unregister_device(&iforce->dev);
+ input_unregister_device(iforce->dev);
if (!open) {
iforce_delete_device(iforce);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index bce247bc300b..146f406b8f8a 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -117,7 +117,7 @@ struct iforce_device {
};
struct iforce {
- struct input_dev dev; /* Input device interface */
+ struct input_dev *dev; /* Input device interface */
struct iforce_device *type;
int bus;
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index 9d3f8c38cb09..c4ed01758226 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "InterAct digital joystick driver"
@@ -54,7 +55,7 @@ MODULE_LICENSE("GPL");
struct interact {
struct gameport *gameport;
- struct input_dev dev;
+ struct input_dev *dev;
int bads;
int reads;
unsigned char type;
@@ -130,7 +131,7 @@ static int interact_read_packet(struct gameport *gameport, int length, u32 *data
static void interact_poll(struct gameport *gameport)
{
struct interact *interact = gameport_get_drvdata(gameport);
- struct input_dev *dev = &interact->dev;
+ struct input_dev *dev = interact->dev;
u32 data[3];
int i;
@@ -208,14 +209,20 @@ static void interact_close(struct input_dev *dev)
static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct interact *interact;
+ struct input_dev *input_dev;
__u32 data[3];
int i, t;
int err;
- if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
- return -ENOMEM;
+ interact = kzalloc(sizeof(struct interact), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!interact || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
interact->gameport = gameport;
+ interact->dev = input_dev;
gameport_set_drvdata(gameport, interact);
@@ -249,41 +256,40 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
interact->type = i;
interact->length = interact_type[i].length;
- interact->dev.private = interact;
- interact->dev.open = interact_open;
- interact->dev.close = interact_close;
+ input_dev->name = interact_type[i].name;
+ input_dev->phys = interact->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
+ input_dev->id.product = interact_type[i].id;
+ input_dev->id.version = 0x0100;
+ input_dev->private = interact;
- interact->dev.name = interact_type[i].name;
- interact->dev.phys = interact->phys;
- interact->dev.id.bustype = BUS_GAMEPORT;
- interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
- interact->dev.id.product = interact_type[i].id;
- interact->dev.id.version = 0x0100;
+ input_dev->open = interact_open;
+ input_dev->close = interact_close;
- interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
- set_bit(t, interact->dev.absbit);
+ set_bit(t, input_dev->absbit);
if (i < interact_type[interact->type].b8) {
- interact->dev.absmin[t] = 0;
- interact->dev.absmax[t] = 255;
+ input_dev->absmin[t] = 0;
+ input_dev->absmax[t] = 255;
} else {
- interact->dev.absmin[t] = -1;
- interact->dev.absmax[t] = 1;
+ input_dev->absmin[t] = -1;
+ input_dev->absmax[t] = 1;
}
}
for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
- set_bit(t, interact->dev.keybit);
+ set_bit(t, input_dev->keybit);
- input_register_device(&interact->dev);
- printk(KERN_INFO "input: %s on %s\n",
- interact_type[interact->type].name, gameport->phys);
+ input_register_device(interact->dev);
return 0;
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
+ input_free_device(input_dev);
kfree(interact);
return err;
}
@@ -292,7 +298,7 @@ static void interact_disconnect(struct gameport *gameport)
{
struct interact *interact = gameport_get_drvdata(gameport);
- input_unregister_device(&interact->dev);
+ input_unregister_device(interact->dev);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(interact);
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 4234ccaf9146..88ec5a918f2e 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -34,6 +34,7 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/slab.h>
#define DRIVER_DESC "Gameport data dumper module"
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 1ba503627242..ca3cc2319d6a 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -49,14 +49,13 @@ MODULE_LICENSE("GPL");
static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
/*
* Per-Magellan data.
*/
struct magellan {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[MAGELLAN_MAX_LENGTH];
char phys[32];
@@ -85,7 +84,7 @@ static int magellan_crunch_nibbles(unsigned char *data, int count)
static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
{
- struct input_dev *dev = &magellan->dev;
+ struct input_dev *dev = magellan->dev;
unsigned char *data = magellan->data;
int i, t;
@@ -138,9 +137,9 @@ static void magellan_disconnect(struct serio *serio)
{
struct magellan* magellan = serio_get_drvdata(serio);
- input_unregister_device(&magellan->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(magellan->dev);
kfree(magellan);
}
@@ -153,52 +152,48 @@ static void magellan_disconnect(struct serio *serio)
static int magellan_connect(struct serio *serio, struct serio_driver *drv)
{
struct magellan *magellan;
- int i, t;
- int err;
-
- if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
- return -ENOMEM;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i;
- memset(magellan, 0, sizeof(struct magellan));
+ magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!magellan || !input_dev)
+ goto fail;
- magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ magellan->dev = input_dev;
+ sprintf(magellan->phys, "%s/input0", serio->phys);
- for (i = 0; i < 9; i++)
- set_bit(magellan_buttons[i], magellan->dev.keybit);
+ input_dev->name = "LogiCad3D Magellan / SpaceMouse";
+ input_dev->phys = magellan->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_MAGELLAN;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = magellan;
- for (i = 0; i < 6; i++) {
- t = magellan_axes[i];
- set_bit(t, magellan->dev.absbit);
- magellan->dev.absmin[t] = -360;
- magellan->dev.absmax[t] = 360;
- }
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- sprintf(magellan->phys, "%s/input0", serio->phys);
+ for (i = 0; i < 9; i++)
+ set_bit(magellan_buttons[i], input_dev->keybit);
- init_input_dev(&magellan->dev);
- magellan->dev.private = magellan;
- magellan->dev.name = magellan_name;
- magellan->dev.phys = magellan->phys;
- magellan->dev.id.bustype = BUS_RS232;
- magellan->dev.id.vendor = SERIO_MAGELLAN;
- magellan->dev.id.product = 0x0001;
- magellan->dev.id.version = 0x0100;
- magellan->dev.dev = &serio->dev;
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, magellan_axes[i], -360, 360, 0, 0);
serio_set_drvdata(serio, magellan);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(magellan);
- return err;
- }
-
- input_register_device(&magellan->dev);
-
- printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(magellan->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(magellan);
+ return err;
}
/*
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 47144a7ed9e7..78dd163cd702 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/gameport.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "Microsoft SideWinder joystick family driver"
@@ -113,7 +114,7 @@ static struct {
struct sw {
struct gameport *gameport;
- struct input_dev dev[4];
+ struct input_dev *dev[4];
char name[64];
char phys[4][32];
int length;
@@ -301,7 +302,7 @@ static int sw_check(__u64 t)
static int sw_parse(unsigned char *buf, struct sw *sw)
{
int hat, i, j;
- struct input_dev *dev = sw->dev;
+ struct input_dev *dev;
switch (sw->type) {
@@ -310,6 +311,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
return -1;
+ dev = sw->dev[0];
+
input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));
@@ -335,13 +338,13 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (sw_parity(GB(i*15,15)))
return -1;
- input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
- input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
+ input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
+ input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
for (j = 0; j < 10; j++)
- input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
+ input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
- input_sync(dev + i);
+ input_sync(sw->dev[i]);
}
return 0;
@@ -352,6 +355,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 9,10));
input_report_abs(dev, ABS_Y, GB(19,10));
input_report_abs(dev, ABS_RZ, GB(36, 6));
@@ -372,6 +376,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_X, GB( 0,10));
input_report_abs(dev, ABS_Y, GB(16,10));
input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
@@ -396,6 +401,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
if (!sw_parity(GB(0,33)))
return -1;
+ dev = sw->dev[0];
input_report_abs(dev, ABS_RX, GB( 0,10));
input_report_abs(dev, ABS_RUDDER, GB(10, 6));
input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
@@ -581,6 +587,7 @@ static int sw_guess_mode(unsigned char *buf, int len)
static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct sw *sw;
+ struct input_dev *input_dev;
int i, j, k, l;
int err;
unsigned char *buf = NULL; /* [SW_LENGTH] */
@@ -590,7 +597,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
comment[0] = 0;
- sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
+ sw = kzalloc(sizeof(struct sw), GFP_KERNEL);
buf = kmalloc(SW_LENGTH, GFP_KERNEL);
idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
if (!sw || !buf || !idbuf) {
@@ -729,42 +736,50 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
- sw->dev[i].private = sw;
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- sw->dev[i].open = sw_open;
- sw->dev[i].close = sw_close;
+ input_dev->name = sw->name;
+ input_dev->phys = sw->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
+ input_dev->id.product = sw->type;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = sw;
- sw->dev[i].name = sw->name;
- sw->dev[i].phys = sw->phys[i];
- sw->dev[i].id.bustype = BUS_GAMEPORT;
- sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
- sw->dev[i].id.product = sw->type;
- sw->dev[i].id.version = 0x0100;
+ input_dev->open = sw_open;
+ input_dev->close = sw_close;
- sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
code = sw_abs[sw->type][j];
- set_bit(code, sw->dev[i].absbit);
- sw->dev[i].absmax[code] = (1 << bits) - 1;
- sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
- sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
+ set_bit(code, input_dev->absbit);
+ input_dev->absmax[code] = (1 << bits) - 1;
+ input_dev->absmin[code] = (bits == 1) ? -1 : 0;
+ input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
if (code != ABS_THROTTLE)
- sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
+ input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
}
for (j = 0; (code = sw_btn[sw->type][j]); j++)
- set_bit(code, sw->dev[i].keybit);
+ set_bit(code, input_dev->keybit);
+
+ dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
- input_register_device(sw->dev + i);
- printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
- sw->name, comment, gameport->phys, m, l, k);
+ input_register_device(sw->dev[i]);
}
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0)
+ input_unregister_device(sw->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(sw);
kfree(buf);
kfree(idbuf);
@@ -777,7 +792,7 @@ static void sw_disconnect(struct gameport *gameport)
int i;
for (i = 0; i < sw->number; i++)
- input_unregister_device(sw->dev + i);
+ input_unregister_device(sw->dev[i]);
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(sw);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index a436f2220856..d6f8db8ec3fd 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -70,8 +70,7 @@ static char *spaceball_names[] = {
*/
struct spaceball {
- struct input_dev dev;
- struct serio *serio;
+ struct input_dev *dev;
int idx;
int escape;
unsigned char data[SPACEBALL_MAX_LENGTH];
@@ -85,7 +84,7 @@ struct spaceball {
static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
{
- struct input_dev *dev = &spaceball->dev;
+ struct input_dev *dev = spaceball->dev;
unsigned char *data = spaceball->data;
int i;
@@ -193,9 +192,9 @@ static void spaceball_disconnect(struct serio *serio)
{
struct spaceball* spaceball = serio_get_drvdata(serio);
- input_unregister_device(&spaceball->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(spaceball->dev);
kfree(spaceball);
}
@@ -208,69 +207,62 @@ static void spaceball_disconnect(struct serio *serio)
static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceball *spaceball;
- int i, t, id;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i, id;
if ((id = serio->id.id) > SPACEBALL_MAX_ID)
return -ENODEV;
- if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
- return - ENOMEM;
+ spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!spaceball || !input_dev)
+ goto fail;
- memset(spaceball, 0, sizeof(struct spaceball));
+ spaceball->dev = input_dev;
+ sprintf(spaceball->phys, "%s/input0", serio->phys);
+
+ input_dev->name = spaceball_names[id];
+ input_dev->phys = spaceball->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SPACEBALL;
+ input_dev->id.product = id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = spaceball;
- spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
switch (id) {
case SPACEBALL_4000FLX:
case SPACEBALL_4000FLX_L:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
- spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9);
+ input_dev->keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
default:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
| BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
case SPACEBALL_3003C:
- spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
+ input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
}
- for (i = 0; i < 6; i++) {
- t = spaceball_axes[i];
- set_bit(t, spaceball->dev.absbit);
- spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
- spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
- spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
- spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
+ for (i = 0; i < 3; i++) {
+ input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40);
+ input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8);
}
- spaceball->serio = serio;
- spaceball->dev.private = spaceball;
-
- sprintf(spaceball->phys, "%s/input0", serio->phys);
-
- init_input_dev(&spaceball->dev);
- spaceball->dev.name = spaceball_names[id];
- spaceball->dev.phys = spaceball->phys;
- spaceball->dev.id.bustype = BUS_RS232;
- spaceball->dev.id.vendor = SERIO_SPACEBALL;
- spaceball->dev.id.product = id;
- spaceball->dev.id.version = 0x0100;
- spaceball->dev.dev = &serio->dev;
-
serio_set_drvdata(serio, spaceball);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(spaceball);
- return err;
- }
-
- input_register_device(&spaceball->dev);
-
- printk(KERN_INFO "input: %s on serio%s\n",
- spaceball_names[id], serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(spaceball->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(spaceball);
+ return err;
}
/*
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 01fd2e4791ae..7c123a01c58e 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -52,15 +52,13 @@ MODULE_LICENSE("GPL");
static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
/*
* Per-Orb data.
*/
struct spaceorb {
- struct input_dev dev;
- struct serio *serio;
+ struct input_dev *dev;
int idx;
unsigned char data[SPACEORB_MAX_LENGTH];
char phys[32];
@@ -78,7 +76,7 @@ static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive
static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
{
- struct input_dev *dev = &spaceorb->dev;
+ struct input_dev *dev = spaceorb->dev;
unsigned char *data = spaceorb->data;
unsigned char c = 0;
int axes[6];
@@ -95,8 +93,8 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'R': /* Reset packet */
spaceorb->data[spaceorb->idx - 1] = 0;
for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
- printk(KERN_INFO "input: %s [%s] on %s\n",
- spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
+ printk(KERN_INFO "input: %s [%s] is %s\n",
+ dev->name, spaceorb->data + i, spaceorb->phys);
break;
case 'D': /* Ball + button data */
@@ -123,7 +121,7 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
case 'E': /* Error packet */
if (spaceorb->idx != 4) return;
- printk(KERN_ERR "joy-spaceorb: Device error. [ ");
+ printk(KERN_ERR "spaceorb: Device error. [ ");
for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
printk("]\n");
break;
@@ -154,9 +152,9 @@ static void spaceorb_disconnect(struct serio *serio)
{
struct spaceorb* spaceorb = serio_get_drvdata(serio);
- input_unregister_device(&spaceorb->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(spaceorb->dev);
kfree(spaceorb);
}
@@ -169,52 +167,48 @@ static void spaceorb_disconnect(struct serio *serio)
static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceorb *spaceorb;
- int i, t;
- int err;
-
- if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(spaceorb, 0, sizeof(struct spaceorb));
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+ int i;
- spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!spaceorb || !input_dev)
+ goto fail;
- for (i = 0; i < 6; i++)
- set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
+ spaceorb->dev = input_dev;
+ sprintf(spaceorb->phys, "%s/input0", serio->phys);
- for (i = 0; i < 6; i++) {
- t = spaceorb_axes[i];
- set_bit(t, spaceorb->dev.absbit);
- spaceorb->dev.absmin[t] = -508;
- spaceorb->dev.absmax[t] = 508;
- }
+ input_dev->name = "SpaceTec SpaceOrb 360 / Avenger";
+ input_dev->phys = spaceorb->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SPACEORB;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = spaceorb;
- spaceorb->serio = serio;
- spaceorb->dev.private = spaceorb;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- sprintf(spaceorb->phys, "%s/input0", serio->phys);
+ for (i = 0; i < 6; i++)
+ set_bit(spaceorb_buttons[i], input_dev->keybit);
- init_input_dev(&spaceorb->dev);
- spaceorb->dev.name = spaceorb_name;
- spaceorb->dev.phys = spaceorb->phys;
- spaceorb->dev.id.bustype = BUS_RS232;
- spaceorb->dev.id.vendor = SERIO_SPACEORB;
- spaceorb->dev.id.product = 0x0001;
- spaceorb->dev.id.version = 0x0100;
- spaceorb->dev.dev = &serio->dev;
+ for (i = 0; i < 6; i++)
+ input_set_abs_params(input_dev, spaceorb_axes[i], -508, 508, 0, 0);
serio_set_drvdata(serio, spaceorb);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(spaceorb);
- return err;
- }
-
- input_register_device(&spaceorb->dev);
+ if (err)
+ goto fail;
+ input_register_device(spaceorb->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(spaceorb);
+ return err;
}
/*
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 6f6e6753d590..0a9ed1d30636 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
#define STINGER_MAX_LENGTH 8
-static char *stinger_name = "Gravis Stinger";
-
/*
* Per-Stinger data.
*/
struct stinger {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[STINGER_MAX_LENGTH];
char phys[32];
@@ -68,7 +66,7 @@ struct stinger {
static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
{
- struct input_dev *dev = &stinger->dev;
+ struct input_dev *dev = stinger->dev;
unsigned char *data = stinger->data;
if (!stinger->idx) return;
@@ -126,9 +124,9 @@ static void stinger_disconnect(struct serio *serio)
{
struct stinger *stinger = serio_get_drvdata(serio);
- input_unregister_device(&stinger->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(stinger->dev);
kfree(stinger);
}
@@ -141,53 +139,46 @@ static void stinger_disconnect(struct serio *serio)
static int stinger_connect(struct serio *serio, struct serio_driver *drv)
{
struct stinger *stinger;
- int i;
- int err;
-
- if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(stinger, 0, sizeof(struct stinger));
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
- BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
- BIT(BTN_START) | BIT(BTN_SELECT);
- stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!stinger || !input_dev)
+ goto fail;
+ stinger->dev = input_dev;
sprintf(stinger->phys, "%s/serio0", serio->phys);
- init_input_dev(&stinger->dev);
- stinger->dev.name = stinger_name;
- stinger->dev.phys = stinger->phys;
- stinger->dev.id.bustype = BUS_RS232;
- stinger->dev.id.vendor = SERIO_STINGER;
- stinger->dev.id.product = 0x0001;
- stinger->dev.id.version = 0x0100;
- stinger->dev.dev = &serio->dev;
-
- for (i = 0; i < 2; i++) {
- stinger->dev.absmax[ABS_X+i] = 64;
- stinger->dev.absmin[ABS_X+i] = -64;
- stinger->dev.absflat[ABS_X+i] = 4;
- }
-
- stinger->dev.private = stinger;
+ input_dev->name = "Gravis Stinger";
+ input_dev->phys = stinger->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_STINGER;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = stinger;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
+ BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) |
+ BIT(BTN_START) | BIT(BTN_SELECT);
+ input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 4);
+ input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 4);
serio_set_drvdata(serio, stinger);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(stinger);
- return err;
- }
-
- input_register_device(&stinger->dev);
-
- printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(stinger->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(stinger);
+ return err;
}
/*
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 9eb9954cac6e..60e2aac7d06e 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
#define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
@@ -63,37 +64,70 @@ MODULE_LICENSE("GPL");
#define TMDC_ABS_HAT 4
#define TMDC_BTN 16
-static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
-static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
+static const unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
+static const unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
-static signed char tmdc_abs[TMDC_ABS] =
+static const signed char tmdc_abs[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
-static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
+static const signed char tmdc_abs_hat[TMDC_ABS_HAT] =
{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static signed char tmdc_abs_at[TMDC_ABS] =
+static const signed char tmdc_abs_at[TMDC_ABS] =
{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
-static signed char tmdc_abs_fm[TMDC_ABS] =
+static const signed char tmdc_abs_fm[TMDC_ABS] =
{ ABS_RX, ABS_RY, ABS_X, ABS_Y };
-static short tmdc_btn_pad[TMDC_BTN] =
+static const short tmdc_btn_pad[TMDC_BTN] =
{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
-static short tmdc_btn_joy[TMDC_BTN] =
+static const short tmdc_btn_joy[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
-static short tmdc_btn_fm[TMDC_BTN] =
+static const short tmdc_btn_fm[TMDC_BTN] =
{ BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
-static short tmdc_btn_at[TMDC_BTN] =
+static const short tmdc_btn_at[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
BTN_BASE3, BTN_BASE2, BTN_BASE };
-static struct {
+static const struct {
int x;
int y;
} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
+static const struct tmdc_model {
+ unsigned char id;
+ const char *name;
+ char abs;
+ char hats;
+ char btnc[4];
+ char btno[4];
+ const signed char *axes;
+ const short *buttons;
+} tmdc_models[] = {
+ { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
+ { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+ { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
+ { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
+ { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+ { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }
+};
+
+
+struct tmdc_port {
+ struct input_dev *dev;
+ char name[64];
+ char phys[32];
+ int mode;
+ const signed char *abs;
+ const short *btn;
+ unsigned char absc;
+ unsigned char btnc[4];
+ unsigned char btno[4];
+};
+
struct tmdc {
struct gameport *gameport;
- struct input_dev dev[2];
+ struct tmdc_port *port[2];
+#if 0
+ struct input_dev *dev[2];
char name[2][64];
char phys[2][32];
int mode[2];
@@ -102,6 +136,7 @@ struct tmdc {
unsigned char absc[2];
unsigned char btnc[2][4];
unsigned char btno[2][4];
+#endif
int reads;
int bads;
unsigned char exists;
@@ -156,6 +191,50 @@ static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMD
return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
}
+static int tmdc_parse_packet(struct tmdc_port *port, unsigned char *data)
+{
+ int i, k, l;
+
+ if (data[TMDC_BYTE_ID] != port->mode)
+ return -1;
+
+ for (i = 0; i < port->absc; i++) {
+ if (port->abs[i] < 0)
+ return 0;
+
+ input_report_abs(port->dev, port->abs[i], data[tmdc_byte_a[i]]);
+ }
+
+ switch (port->mode) {
+
+ case TMDC_MODE_M3DI:
+
+ i = tmdc_byte_d[0];
+ input_report_abs(port->dev, ABS_HAT0X, ((data[i] >> 3) & 1) - ((data[i] >> 1) & 1));
+ input_report_abs(port->dev, ABS_HAT0Y, ((data[i] >> 2) & 1) - ( data[i] & 1));
+ break;
+
+ case TMDC_MODE_AT:
+
+ i = tmdc_byte_a[3];
+ input_report_abs(port->dev, ABS_HAT0X, tmdc_hat_to_axis[(data[i] - 141) / 25].x);
+ input_report_abs(port->dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[i] - 141) / 25].y);
+ break;
+
+ }
+
+ for (k = l = 0; k < 4; k++) {
+ for (i = 0; i < port->btnc[k]; i++)
+ input_report_key(port->dev, port->btn[i + l],
+ ((data[tmdc_byte_d[k]] >> (i + port->btno[k])) & 1));
+ l += port->btnc[k];
+ }
+
+ input_sync(port->dev);
+
+ return 0;
+}
+
/*
* tmdc_poll() reads and analyzes ThrustMaster joystick data.
*/
@@ -164,57 +243,21 @@ static void tmdc_poll(struct gameport *gameport)
{
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc = gameport_get_drvdata(gameport);
- struct input_dev *dev;
unsigned char r, bad = 0;
- int i, j, k, l;
+ int i;
tmdc->reads++;
if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
bad = 1;
- else
-
- for (j = 0; j < 2; j++)
- if (r & (1 << j) & tmdc->exists) {
-
- if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
- bad = 1;
- continue;
- }
-
- dev = tmdc->dev + j;
-
- for (i = 0; i < tmdc->absc[j]; i++) {
- if (tmdc->abs[j][i] < 0) continue;
- input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
- }
-
- switch (tmdc->mode[j]) {
+ else {
+ for (i = 0; i < 2; i++) {
+ if (r & (1 << i) & tmdc->exists) {
- case TMDC_MODE_M3DI:
-
- i = tmdc_byte_d[0];
- input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
- input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
- break;
-
- case TMDC_MODE_AT:
-
- i = tmdc_byte_a[3];
- input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
- input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
- break;
-
- }
-
- for (k = l = 0; k < 4; k++) {
- for (i = 0; i < tmdc->btnc[j][k]; i++)
- input_report_key(dev, tmdc->btn[j][i + l],
- ((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
- l += tmdc->btnc[j][k];
+ if (tmdc_parse_packet(tmdc->port[i], data[i]))
+ bad = 1;
}
-
- input_sync(dev);
+ }
}
tmdc->bads += bad;
@@ -235,34 +278,92 @@ static void tmdc_close(struct input_dev *dev)
gameport_stop_polling(tmdc->gameport);
}
+static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
+{
+ const struct tmdc_model *model;
+ struct tmdc_port *port;
+ struct input_dev *input_dev;
+ int i, j, b = 0;
+
+ tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!port || !input_dev) {
+ kfree(port);
+ input_free_device(input_dev);
+ return -ENOMEM;
+ }
+
+ port->mode = data[TMDC_BYTE_ID];
+
+ for (model = tmdc_models; model->id && model->id != port->mode; model++)
+ /* empty */;
+
+ port->abs = model->axes;
+ port->btn = model->buttons;
+
+ if (!model->id) {
+ port->absc = data[TMDC_BYTE_DEF] >> 4;
+ for (i = 0; i < 4; i++)
+ port->btnc[i] = i < (data[TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
+ } else {
+ port->absc = model->abs;
+ for (i = 0; i < 4; i++)
+ port->btnc[i] = model->btnc[i];
+ }
+
+ for (i = 0; i < 4; i++)
+ port->btno[i] = model->btno[i];
+
+ snprintf(port->name, sizeof(port->name), model->name,
+ port->absc, (data[TMDC_BYTE_DEF] & 0xf) << 3, port->mode);
+ snprintf(port->phys, sizeof(port->phys), "%s/input%d", tmdc->gameport->phys, i);
+
+ port->dev = input_dev;
+
+ input_dev->name = port->name;
+ input_dev->phys = port->phys;
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
+ input_dev->id.product = model->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &tmdc->gameport->dev;
+ input_dev->private = tmdc;
+
+ input_dev->open = tmdc_open;
+ input_dev->close = tmdc_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+ for (i = 0; i < port->absc && i < TMDC_ABS; i++)
+ if (port->abs[i] >= 0)
+ input_set_abs_params(input_dev, port->abs[i], 8, 248, 2, 4);
+
+ for (i = 0; i < model->hats && i < TMDC_ABS_HAT; i++)
+ input_set_abs_params(input_dev, tmdc_abs_hat[i], -1, 1, 0, 0);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < port->btnc[i] && j < TMDC_BTN; j++)
+ set_bit(port->btn[j + b], input_dev->keybit);
+ b += port->btnc[i];
+ }
+
+ input_register_device(port->dev);
+
+ return 0;
+}
+
/*
* tmdc_probe() probes for ThrustMaster type joysticks.
*/
static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{
- static struct models {
- unsigned char id;
- char *name;
- char abs;
- char hats;
- char btnc[4];
- char btno[4];
- signed char *axes;
- short *buttons;
- } models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
- { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
- { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
- { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
- { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
- { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
-
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc;
- int i, j, k, l, m;
+ int i;
int err;
- if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+ if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
return -ENOMEM;
tmdc->gameport = gameport;
@@ -281,68 +382,25 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
gameport_set_poll_handler(gameport, tmdc_poll);
gameport_set_poll_interval(gameport, 20);
- for (j = 0; j < 2; j++)
- if (tmdc->exists & (1 << j)) {
+ for (i = 0; i < 2; i++) {
+ if (tmdc->exists & (1 << i)) {
- tmdc->mode[j] = data[j][TMDC_BYTE_ID];
-
- for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
-
- tmdc->abs[j] = models[m].axes;
- tmdc->btn[j] = models[m].buttons;
-
- if (!models[m].id) {
- models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
- for (k = 0; k < 4; k++)
- models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
- }
-
- tmdc->absc[j] = models[m].abs;
- for (k = 0; k < 4; k++) {
- tmdc->btnc[j][k] = models[m].btnc[k];
- tmdc->btno[j][k] = models[m].btno[k];
- }
-
- sprintf(tmdc->name[j], models[m].name, models[m].abs,
- (data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
-
- sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
-
- tmdc->dev[j].private = tmdc;
- tmdc->dev[j].open = tmdc_open;
- tmdc->dev[j].close = tmdc_close;
-
- tmdc->dev[j].name = tmdc->name[j];
- tmdc->dev[j].phys = tmdc->phys[j];
- tmdc->dev[j].id.bustype = BUS_GAMEPORT;
- tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
- tmdc->dev[j].id.product = models[m].id;
- tmdc->dev[j].id.version = 0x0100;
-
- tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
- for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
- if (tmdc->abs[j][i] >= 0)
- input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
-
- for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
- input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
-
-
- for (k = l = 0; k < 4; k++) {
- for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
- set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
- l += models[m].btnc[k];
- }
-
- input_register_device(tmdc->dev + j);
- printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
+ err = tmdc_setup_port(tmdc, i, data[i]);
+ if (err)
+ goto fail3;
}
+ }
return 0;
-fail2: gameport_close(gameport);
-fail1: gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0) {
+ if (tmdc->port[i]) {
+ input_unregister_device(tmdc->port[i]->dev);
+ kfree(tmdc->port[i]);
+ }
+ }
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
return err;
}
@@ -352,9 +410,12 @@ static void tmdc_disconnect(struct gameport *gameport)
struct tmdc *tmdc = gameport_get_drvdata(gameport);
int i;
- for (i = 0; i < 2; i++)
- if (tmdc->exists & (1 << i))
- input_unregister_device(tmdc->dev + i);
+ for (i = 0; i < 2; i++) {
+ if (tmdc->port[i]) {
+ input_unregister_device(tmdc->port[i]->dev);
+ kfree(tmdc->port[i]);
+ }
+ }
gameport_close(gameport);
gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 28100d461cb7..7e9764937d06 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -42,19 +42,21 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
MODULE_LICENSE("GPL");
-static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs __initdata = 0;
-module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
-MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
+#define TGFX_MAX_PORTS 3
+#define TGFX_MAX_DEVICES 7
-static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_2 __initdata = 0;
-module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
-MODULE_PARM_DESC(map2, "Describes second set of devices");
+struct tgfx_config {
+ int args[TGFX_MAX_DEVICES + 1];
+ int nargs;
+};
+
+static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
-static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_3 __initdata = 0;
-module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
+module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
+module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("tgfx=");
@@ -75,17 +77,17 @@ __obsolete_setup("tgfx_3=");
#define TGFX_TOP2 0x08
static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
-static char *tgfx_name = "TurboGraFX Multisystem joystick";
static struct tgfx {
struct pardevice *pd;
struct timer_list timer;
- struct input_dev dev[7];
- char phys[7][32];
+ struct input_dev *dev[TGFX_MAX_DEVICES];
+ char name[TGFX_MAX_DEVICES][64];
+ char phys[TGFX_MAX_DEVICES][32];
int sticks;
int used;
struct semaphore sem;
-} *tgfx_base[3];
+} *tgfx_base[TGFX_MAX_PORTS];
/*
* tgfx_timer() reads and analyzes TurboGraFX joystick data.
@@ -100,7 +102,7 @@ static void tgfx_timer(unsigned long private)
for (i = 0; i < 7; i++)
if (tgfx->sticks & (1 << i)) {
- dev = tgfx->dev + i;
+ dev = tgfx->dev[i];
parport_write_data(tgfx->pd->port, ~(1 << i));
data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
@@ -153,118 +155,165 @@ static void tgfx_close(struct input_dev *dev)
up(&tgfx->sem);
}
+
+
/*
* tgfx_probe() probes for tg gamepads.
*/
-static struct tgfx __init *tgfx_probe(int *config, int nargs)
+static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
{
struct tgfx *tgfx;
+ struct input_dev *input_dev;
struct parport *pp;
+ struct pardevice *pd;
int i, j;
+ int err;
- if (config[0] < 0)
- return NULL;
-
- if (nargs < 2) {
- printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
- return NULL;
- }
-
- pp = parport_find_number(config[0]);
-
+ pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "turbografx.c: no such parport\n");
- return NULL;
+ err = -EINVAL;
+ goto err_out;
}
- if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
- parport_put_port(pp);
- return NULL;
+ pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+ if (!pd) {
+ printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
+ err = -EBUSY;
+ goto err_put_pp;
}
- init_MUTEX(&tgfx->sem);
-
- tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
- parport_put_port(pp);
-
- if (!tgfx->pd) {
- printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
- kfree(tgfx);
- return NULL;
+ tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
+ if (!tgfx) {
+ printk(KERN_ERR "turbografx.c: Not enough memory\n");
+ err = -ENOMEM;
+ goto err_unreg_pardev;
}
+ init_MUTEX(&tgfx->sem);
+ tgfx->pd = pd;
init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer;
- tgfx->sticks = 0;
+ for (i = 0; i < n_devs; i++) {
+ if (n_buttons[i] < 1)
+ continue;
- for (i = 0; i < nargs - 1; i++)
- if (config[i+1] > 0 && config[i+1] < 6) {
-
- tgfx->sticks |= (1 << i);
+ if (n_buttons[i] > 6) {
+ printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
+ err = -EINVAL;
+ goto err_free_devs;
+ }
- tgfx->dev[i].private = tgfx;
- tgfx->dev[i].open = tgfx_open;
- tgfx->dev[i].close = tgfx_close;
+ tgfx->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
+ err = -ENOMEM;
+ goto err_free_devs;
+ }
- sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
+ tgfx->sticks |= (1 << i);
+ snprintf(tgfx->name[i], sizeof(tgfx->name[i]),
+ "TurboGraFX %d-button Multisystem joystick", n_buttons[i]);
+ snprintf(tgfx->phys[i], sizeof(tgfx->phys[i]),
+ "%s/input%d", tgfx->pd->port->name, i);
- tgfx->dev[i].name = tgfx_name;
- tgfx->dev[i].phys = tgfx->phys[i];
- tgfx->dev[i].id.bustype = BUS_PARPORT;
- tgfx->dev[i].id.vendor = 0x0003;
- tgfx->dev[i].id.product = config[i+1];
- tgfx->dev[i].id.version = 0x0100;
+ input_dev->name = tgfx->name[i];
+ input_dev->phys = tgfx->phys[i];
+ input_dev->id.bustype = BUS_PARPORT;
+ input_dev->id.vendor = 0x0003;
+ input_dev->id.product = n_buttons[i];
+ input_dev->id.version = 0x0100;
- tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ input_dev->private = tgfx;
+ input_dev->open = tgfx_open;
+ input_dev->close = tgfx_close;
- for (j = 0; j < config[i+1]; j++)
- set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
- tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
- tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
+ for (j = 0; j < n_buttons[i]; j++)
+ set_bit(tgfx_buttons[j], input_dev->keybit);
- input_register_device(tgfx->dev + i);
- printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
- config[i+1], tgfx->pd->port->name);
- }
+ input_register_device(tgfx->dev[i]);
+ }
if (!tgfx->sticks) {
- parport_unregister_device(tgfx->pd);
- kfree(tgfx);
- return NULL;
+ printk(KERN_ERR "turbografx.c: No valid devices specified\n");
+ err = -EINVAL;
+ goto err_free_tgfx;
}
return tgfx;
+
+ err_free_devs:
+ while (--i >= 0)
+ input_unregister_device(tgfx->dev[i]);
+ err_free_tgfx:
+ kfree(tgfx);
+ err_unreg_pardev:
+ parport_unregister_device(pd);
+ err_put_pp:
+ parport_put_port(pp);
+ err_out:
+ return ERR_PTR(err);
+}
+
+static void __exit tgfx_remove(struct tgfx *tgfx)
+{
+ int i;
+
+ for (i = 0; i < TGFX_MAX_DEVICES; i++)
+ if (tgfx->dev[i])
+ input_unregister_device(tgfx->dev[i]);
+ parport_unregister_device(tgfx->pd);
+ kfree(tgfx);
}
static int __init tgfx_init(void)
{
- tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
- tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
- tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
+ int i;
+ int have_dev = 0;
+ int err = 0;
+
+ for (i = 0; i < TGFX_MAX_PORTS; i++) {
+ if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
+ continue;
+
+ if (tgfx[i].nargs < 2) {
+ printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
+ err = -EINVAL;
+ break;
+ }
+
+ tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1);
+ if (IS_ERR(tgfx_base[i])) {
+ err = PTR_ERR(tgfx_base[i]);
+ break;
+ }
+
+ have_dev = 1;
+ }
- if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
- return 0;
+ if (err) {
+ while (--i >= 0)
+ tgfx_remove(tgfx_base[i]);
+ return err;
+ }
- return -ENODEV;
+ return have_dev ? 0 : -ENODEV;
}
static void __exit tgfx_exit(void)
{
- int i, j;
+ int i;
- for (i = 0; i < 3; i++)
- if (tgfx_base[i]) {
- for (j = 0; j < 7; j++)
- if (tgfx_base[i]->sticks & (1 << j))
- input_unregister_device(tgfx_base[i]->dev + j);
- parport_unregister_device(tgfx_base[i]->pd);
- }
+ for (i = 0; i < TGFX_MAX_PORTS; i++)
+ if (tgfx_base[i])
+ tgfx_remove(tgfx_base[i]);
}
module_init(tgfx_init);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 0379bc166525..cd3a1e742a30 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -69,8 +69,6 @@ MODULE_LICENSE("GPL");
#define TWIDJOY_MAX_LENGTH 5
-static char *twidjoy_name = "Handykey Twiddler";
-
static struct twidjoy_button_spec {
int bitshift;
int bitmask;
@@ -95,7 +93,7 @@ twidjoy_buttons[] = {
*/
struct twidjoy {
- struct input_dev dev;
+ struct input_dev *dev;
int idx;
unsigned char data[TWIDJOY_MAX_LENGTH];
char phys[32];
@@ -108,37 +106,33 @@ struct twidjoy {
static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
{
- if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
- struct input_dev *dev = &twidjoy->dev;
- unsigned char *data = twidjoy->data;
- struct twidjoy_button_spec *bp;
- int button_bits, abs_x, abs_y;
-
- button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
+ struct input_dev *dev = twidjoy->dev;
+ unsigned char *data = twidjoy->data;
+ struct twidjoy_button_spec *bp;
+ int button_bits, abs_x, abs_y;
- input_regs(dev, regs);
+ button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
- for (bp = twidjoy_buttons; bp->bitmask; bp++) {
- int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
- int i;
+ input_regs(dev, regs);
- for (i = 0; i < bp->bitmask; i++)
- input_report_key(dev, bp->buttons[i], i+1 == value);
- }
+ for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+ int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
+ int i;
- abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
- if (data[4] & 0x08) abs_x -= 256;
+ for (i = 0; i < bp->bitmask; i++)
+ input_report_key(dev, bp->buttons[i], i+1 == value);
+ }
- abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
- if (data[3] & 0x02) abs_y -= 256;
+ abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
+ if (data[4] & 0x08) abs_x -= 256;
- input_report_abs(dev, ABS_X, -abs_x);
- input_report_abs(dev, ABS_Y, +abs_y);
+ abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
+ if (data[3] & 0x02) abs_y -= 256;
- input_sync(dev);
- }
+ input_report_abs(dev, ABS_X, -abs_x);
+ input_report_abs(dev, ABS_Y, +abs_y);
- return;
+ input_sync(dev);
}
/*
@@ -179,9 +173,9 @@ static void twidjoy_disconnect(struct serio *serio)
{
struct twidjoy *twidjoy = serio_get_drvdata(serio);
- input_unregister_device(&twidjoy->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(twidjoy->dev);
kfree(twidjoy);
}
@@ -195,59 +189,49 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
{
struct twidjoy_button_spec *bp;
struct twidjoy *twidjoy;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
- return -ENOMEM;
- memset(twidjoy, 0, sizeof(struct twidjoy));
+ twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!twidjoy || !input_dev)
+ goto fail;
+ twidjoy->dev = input_dev;
sprintf(twidjoy->phys, "%s/input0", serio->phys);
- init_input_dev(&twidjoy->dev);
- twidjoy->dev.name = twidjoy_name;
- twidjoy->dev.phys = twidjoy->phys;
- twidjoy->dev.id.bustype = BUS_RS232;
- twidjoy->dev.id.vendor = SERIO_TWIDJOY;
- twidjoy->dev.id.product = 0x0001;
- twidjoy->dev.id.version = 0x0100;
- twidjoy->dev.dev = &serio->dev;
-
- twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
- for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+ input_dev->name = "Handykey Twiddler";
+ input_dev->phys = twidjoy->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_TWIDJOY;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = twidjoy;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
+ input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
+
+ for (bp = twidjoy_buttons; bp->bitmask; bp++)
for (i = 0; i < bp->bitmask; i++)
- set_bit(bp->buttons[i], twidjoy->dev.keybit);
- }
-
- twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
- for (i = 0; i < 2; i++) {
- twidjoy->dev.absmax[ABS_X+i] = 50;
- twidjoy->dev.absmin[ABS_X+i] = -50;
-
- /* TODO: arndt 20010708: Are these values appropriate? */
- twidjoy->dev.absfuzz[ABS_X+i] = 4;
- twidjoy->dev.absflat[ABS_X+i] = 4;
- }
-
- twidjoy->dev.private = twidjoy;
+ set_bit(bp->buttons[i], input_dev->keybit);
serio_set_drvdata(serio, twidjoy);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(twidjoy);
- return err;
- }
-
- input_register_device(&twidjoy->dev);
-
- printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(twidjoy->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(twidjoy);
+ return err;
}
/*
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 6976a219504c..99a642d2a1fe 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -47,14 +47,13 @@ MODULE_LICENSE("GPL");
#define WARRIOR_MAX_LENGTH 16
static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
-static char *warrior_name = "Logitech WingMan Warrior";
/*
* Per-Warrior data.
*/
struct warrior {
- struct input_dev dev;
+ struct input_dev *dev;
int idx, len;
unsigned char data[WARRIOR_MAX_LENGTH];
char phys[32];
@@ -67,7 +66,7 @@ struct warrior {
static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
{
- struct input_dev *dev = &warrior->dev;
+ struct input_dev *dev = warrior->dev;
unsigned char *data = warrior->data;
if (!warrior->idx) return;
@@ -131,9 +130,9 @@ static void warrior_disconnect(struct serio *serio)
{
struct warrior *warrior = serio_get_drvdata(serio);
- input_unregister_device(&warrior->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(warrior->dev);
kfree(warrior);
}
@@ -146,60 +145,48 @@ static void warrior_disconnect(struct serio *serio)
static int warrior_connect(struct serio *serio, struct serio_driver *drv)
{
struct warrior *warrior;
- int i;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(warrior, 0, sizeof(struct warrior));
-
- warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
- warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
- warrior->dev.relbit[0] = BIT(REL_DIAL);
- warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+ warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!warrior || !input_dev)
+ goto fail;
+ warrior->dev = input_dev;
sprintf(warrior->phys, "%s/input0", serio->phys);
- init_input_dev(&warrior->dev);
- warrior->dev.name = warrior_name;
- warrior->dev.phys = warrior->phys;
- warrior->dev.id.bustype = BUS_RS232;
- warrior->dev.id.vendor = SERIO_WARRIOR;
- warrior->dev.id.product = 0x0001;
- warrior->dev.id.version = 0x0100;
- warrior->dev.dev = &serio->dev;
-
- for (i = 0; i < 2; i++) {
- warrior->dev.absmax[ABS_X+i] = -64;
- warrior->dev.absmin[ABS_X+i] = 64;
- warrior->dev.absflat[ABS_X+i] = 8;
- }
-
- warrior->dev.absmax[ABS_THROTTLE] = -112;
- warrior->dev.absmin[ABS_THROTTLE] = 112;
-
- for (i = 0; i < 2; i++) {
- warrior->dev.absmax[ABS_HAT0X+i] = -1;
- warrior->dev.absmin[ABS_HAT0X+i] = 1;
- }
-
- warrior->dev.private = warrior;
+ input_dev->name = "Logitech WingMan Warrior";
+ input_dev->phys = warrior->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_WARRIOR;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = warrior;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
+ input_dev->relbit[0] = BIT(REL_DIAL);
+ input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
+ input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
+ input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
serio_set_drvdata(serio, warrior);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(warrior);
- return err;
- }
-
- input_register_device(&warrior->dev);
-
- printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(warrior->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(warrior);
+ return err;
}
/*
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index e55dee390775..4a917748fd9f 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -13,11 +13,11 @@ menuconfig INPUT_KEYBOARD
if INPUT_KEYBOARD
config KEYBOARD_ATKBD
- tristate "AT keyboard" if !PC
+ tristate "AT keyboard" if !X86_PC
default y
select SERIO
select SERIO_LIBPS2
- select SERIO_I8042 if PC
+ select SERIO_I8042 if X86_PC
select SERIO_GSCPS2 if GSC
help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
@@ -93,7 +93,7 @@ config KEYBOARD_LKKBD
config KEYBOARD_LOCOMO
tristate "LoCoMo Keyboard Support"
- depends on SHARP_LOCOMO
+ depends on SHARP_LOCOMO && INPUT_KEYBOARD
help
Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
@@ -132,6 +132,17 @@ config KEYBOARD_CORGI
To compile this driver as a module, choose M here: the
module will be called corgikbd.
+config KEYBOARD_SPITZ
+ tristate "Spitz keyboard"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+ SL-C3000 and Sl-C3100 series of PDAs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called spitzkbd.
+
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b02eeceea3c3..9ce0b87f2fac 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 4e8e8ea214ab..4c8fb1f8631f 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -155,10 +155,7 @@ static const char *amikbd_messages[8] = {
[7] = KERN_WARNING "amikbd: keyboard interrupt\n"
};
-static struct input_dev amikbd_dev;
-
-static char *amikbd_name = "Amiga keyboard";
-static char *amikbd_phys = "amikbd/input0";
+static struct input_dev *amikbd_dev;
static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
@@ -176,16 +173,16 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
scancode = amikbd_keycode[scancode];
- input_regs(&amikbd_dev, fp);
+ input_regs(amikbd_dev, fp);
if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
- input_report_key(&amikbd_dev, scancode, 1);
- input_report_key(&amikbd_dev, scancode, 0);
- input_sync(&amikbd_dev);
+ input_report_key(amikbd_dev, scancode, 1);
+ input_report_key(amikbd_dev, scancode, 0);
} else {
- input_report_key(&amikbd_dev, scancode, down);
- input_sync(&amikbd_dev);
+ input_report_key(amikbd_dev, scancode, down);
}
+
+ input_sync(amikbd_dev);
} else /* scancodes >= 0x78 are error codes */
printk(amikbd_messages[scancode - 0x78]);
@@ -202,39 +199,41 @@ static int __init amikbd_init(void)
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY;
- init_input_dev(&amikbd_dev);
-
- amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- amikbd_dev.keycode = amikbd_keycode;
- amikbd_dev.keycodesize = sizeof(unsigned char);
- amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
+ amikbd_dev = input_allocate_device();
+ if (!amikbd_dev) {
+ printk(KERN_ERR "amikbd: not enough memory for input device\n");
+ release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+ return -ENOMEM;
+ }
+
+ amikbd_dev->name = "Amiga Keyboard";
+ amikbd_dev->phys = "amikbd/input0";
+ amikbd_dev->id.bustype = BUS_AMIGA;
+ amikbd_dev->id.vendor = 0x0001;
+ amikbd_dev->id.product = 0x0001;
+ amikbd_dev->id.version = 0x0100;
+
+ amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ amikbd_dev->keycode = amikbd_keycode;
+ amikbd_dev->keycodesize = sizeof(unsigned char);
+ amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
for (i = 0; i < 0x78; i++)
if (amikbd_keycode[i])
- set_bit(amikbd_keycode[i], amikbd_dev.keybit);
+ set_bit(amikbd_keycode[i], amikbd_dev->keybit);
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
- amikbd_dev.name = amikbd_name;
- amikbd_dev.phys = amikbd_phys;
- amikbd_dev.id.bustype = BUS_AMIGA;
- amikbd_dev.id.vendor = 0x0001;
- amikbd_dev.id.product = 0x0001;
- amikbd_dev.id.version = 0x0100;
-
- input_register_device(&amikbd_dev);
-
- printk(KERN_INFO "input: %s\n", amikbd_name);
-
+ input_register_device(amikbd_dev);
return 0;
}
static void __exit amikbd_exit(void)
{
- input_unregister_device(&amikbd_dev);
free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
- release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
+ input_unregister_device(amikbd_dev);
+ release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
}
module_init(amikbd_init);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4d4985b59abf..820c7fd9a604 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -185,12 +185,12 @@ static struct {
struct atkbd {
- struct ps2dev ps2dev;
+ struct ps2dev ps2dev;
+ struct input_dev *dev;
/* Written only during init */
char name[64];
char phys[32];
- struct input_dev dev;
unsigned short id;
unsigned char keycode[512];
@@ -208,6 +208,7 @@ struct atkbd {
unsigned char resend;
unsigned char release;
unsigned char bat_xl;
+ unsigned char err_xl;
unsigned int last;
unsigned long time;
};
@@ -289,22 +290,25 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (!atkbd->enabled)
goto out;
- input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+ input_event(atkbd->dev, EV_MSC, MSC_RAW, code);
if (atkbd->translated) {
if (atkbd->emul ||
!(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
- code == ATKBD_RET_ERR ||
+ (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
(code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
atkbd->release = code >> 7;
code &= 0x7f;
}
- if (!atkbd->emul &&
- (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
+ if (!atkbd->emul) {
+ if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
atkbd->bat_xl = !atkbd->release;
+ if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
+ atkbd->err_xl = !atkbd->release;
+ }
}
switch (code) {
@@ -322,10 +326,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->release = 1;
goto out;
case ATKBD_RET_HANGUEL:
- atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3);
+ atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
goto out;
case ATKBD_RET_HANJA:
- atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
+ atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
goto out;
case ATKBD_RET_ERR:
printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
@@ -341,7 +345,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
}
if (atkbd->keycode[code] != ATKBD_KEY_NULL)
- input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
+ input_event(atkbd->dev, EV_MSC, MSC_SCAN, code);
switch (atkbd->keycode[code]) {
case ATKBD_KEY_NULL:
@@ -361,7 +365,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
"to make it known.\n",
code & 0x80 ? "e0" : "", code & 0x7f);
}
- input_sync(&atkbd->dev);
+ input_sync(atkbd->dev);
break;
case ATKBD_SCR_1:
scroll = 1 - atkbd->release * 2;
@@ -386,7 +390,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
default:
value = atkbd->release ? 0 :
- (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
+ (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key)));
switch (value) { /* Workaround Toshiba laptop multiple keypress */
case 0:
@@ -394,7 +398,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
case 1:
atkbd->last = code;
- atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
+ atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;
break;
case 2:
if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@@ -402,16 +406,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
}
- atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
+ atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);
}
if (atkbd->scroll) {
- input_regs(&atkbd->dev, regs);
+ input_regs(atkbd->dev, regs);
if (click != -1)
- input_report_key(&atkbd->dev, BTN_MIDDLE, click);
- input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
- input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
- input_sync(&atkbd->dev);
+ input_report_key(atkbd->dev, BTN_MIDDLE, click);
+ input_report_rel(atkbd->dev, REL_WHEEL, scroll);
+ input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);
+ input_sync(atkbd->dev);
}
atkbd->release = 0;
@@ -459,7 +463,6 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
return 0;
-
case EV_REP:
if (atkbd->softrepeat) return 0;
@@ -689,7 +692,7 @@ static void atkbd_disconnect(struct serio *serio)
device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
device_remove_file(&serio->dev, &atkbd_attr_softraw);
- input_unregister_device(&atkbd->dev);
+ input_unregister_device(atkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(atkbd);
@@ -697,7 +700,7 @@ static void atkbd_disconnect(struct serio *serio)
/*
- * atkbd_set_device_attrs() initializes keyboard's keycode table
+ * atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -733,53 +736,58 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
static void atkbd_set_device_attrs(struct atkbd *atkbd)
{
+ struct input_dev *input_dev = atkbd->dev;
int i;
- memset(&atkbd->dev, 0, sizeof(struct input_dev));
+ if (atkbd->extra)
+ sprintf(atkbd->name, "AT Set 2 Extra keyboard");
+ else
+ sprintf(atkbd->name, "AT %s Set %d keyboard",
+ atkbd->translated ? "Translated" : "Raw", atkbd->set);
- init_input_dev(&atkbd->dev);
+ sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);
- atkbd->dev.name = atkbd->name;
- atkbd->dev.phys = atkbd->phys;
- atkbd->dev.id.bustype = BUS_I8042;
- atkbd->dev.id.vendor = 0x0001;
- atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
- atkbd->dev.id.version = atkbd->id;
- atkbd->dev.event = atkbd_event;
- atkbd->dev.private = atkbd;
- atkbd->dev.dev = &atkbd->ps2dev.serio->dev;
+ input_dev->name = atkbd->name;
+ input_dev->phys = atkbd->phys;
+ input_dev->id.bustype = BUS_I8042;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
+ input_dev->id.version = atkbd->id;
+ input_dev->event = atkbd_event;
+ input_dev->private = atkbd;
+ input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
- atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
if (atkbd->write) {
- atkbd->dev.evbit[0] |= BIT(EV_LED);
- atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ input_dev->evbit[0] |= BIT(EV_LED);
+ input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
}
if (atkbd->extra)
- atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
+ input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
if (!atkbd->softrepeat) {
- atkbd->dev.rep[REP_DELAY] = 250;
- atkbd->dev.rep[REP_PERIOD] = 33;
+ input_dev->rep[REP_DELAY] = 250;
+ input_dev->rep[REP_PERIOD] = 33;
}
- atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
+ input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
if (atkbd->scroll) {
- atkbd->dev.evbit[0] |= BIT(EV_REL);
- atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
- set_bit(BTN_MIDDLE, atkbd->dev.keybit);
+ input_dev->evbit[0] |= BIT(EV_REL);
+ input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
+ set_bit(BTN_MIDDLE, input_dev->keybit);
}
- atkbd->dev.keycode = atkbd->keycode;
- atkbd->dev.keycodesize = sizeof(unsigned char);
- atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
+ input_dev->keycode = atkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
for (i = 0; i < 512; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
- set_bit(atkbd->keycode[i], atkbd->dev.keybit);
+ set_bit(atkbd->keycode[i], input_dev->keybit);
}
/*
@@ -792,13 +800,15 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct atkbd *atkbd;
- int err;
-
- if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
- return - ENOMEM;
+ struct input_dev *dev;
+ int err = -ENOMEM;
- memset(atkbd, 0, sizeof(struct atkbd));
+ atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
+ dev = input_allocate_device();
+ if (!atkbd || !dev)
+ goto fail;
+ atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
switch (serio->id.type) {
@@ -824,19 +834,15 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, atkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(atkbd);
- return err;
- }
+ if (err)
+ goto fail;
if (atkbd->write) {
if (atkbd_probe(atkbd)) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(atkbd);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -847,19 +853,9 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->id = 0xab00;
}
- if (atkbd->extra)
- sprintf(atkbd->name, "AT Set 2 Extra keyboard");
- else
- sprintf(atkbd->name, "AT %s Set %d keyboard",
- atkbd->translated ? "Translated" : "Raw", atkbd->set);
-
- sprintf(atkbd->phys, "%s/input0", serio->phys);
-
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
-
device_create_file(&serio->dev, &atkbd_attr_extra);
device_create_file(&serio->dev, &atkbd_attr_scroll);
device_create_file(&serio->dev, &atkbd_attr_set);
@@ -868,9 +864,14 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_enable(atkbd);
- printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
+ input_register_device(atkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(dev);
+ kfree(atkbd);
+ return err;
}
/*
@@ -892,9 +893,9 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd);
if (atkbd->write) {
- param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
- | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
+ param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
if (atkbd_probe(atkbd))
return -1;
@@ -1004,6 +1005,7 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1015,12 +1017,19 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
return -EINVAL;
if (atkbd->extra != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ /*
+ * Since device's properties will change we need to
+ * unregister old device. But allocate new one first
+ * to make sure we have it.
+ */
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd_activate(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1032,6 +1041,7 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1040,12 +1050,14 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
return -EINVAL;
if (atkbd->scroll != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->scroll = value;
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1057,6 +1069,7 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1068,13 +1081,15 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
return -EINVAL;
if (atkbd->set != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
@@ -1086,6 +1101,7 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1097,15 +1113,16 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
return -EINVAL;
if (atkbd->softrepeat != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->softrepeat = value;
if (atkbd->softrepeat)
atkbd->softraw = 1;
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
-
return count;
}
@@ -1117,6 +1134,7 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{
+ struct input_dev *new_dev;
unsigned long value;
char *rest;
@@ -1125,11 +1143,13 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
return -EINVAL;
if (atkbd->softraw != value) {
- /* unregister device as it's properties will change */
- input_unregister_device(&atkbd->dev);
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+ input_unregister_device(atkbd->dev);
+ atkbd->dev = new_dev;
atkbd->softraw = value;
atkbd_set_device_attrs(atkbd);
- input_register_device(&atkbd->dev);
+ input_register_device(atkbd->dev);
}
return count;
}
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index a8551711e8d6..d00d14bb637a 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -12,10 +12,11 @@
*/
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/irq.h>
@@ -32,7 +33,6 @@
/* zero code, 124 scancodes + 3 hinge combinations */
#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
#define SCAN_INTERVAL (HZ/10)
-#define CORGIKBD_PRESSED 1
#define HINGE_SCAN_INTERVAL (HZ/4)
@@ -70,28 +70,15 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
struct corgikbd {
unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
- struct input_dev input;
- char phys[32];
+ struct input_dev *input;
- unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
spinlock_t lock;
-
struct timer_list timer;
struct timer_list htimer;
-};
-static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
-{
- if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
- corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
- input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
- if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
- input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
- } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
- corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
- input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
- }
-}
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
#define KB_DISCHARGE_DELAY 10
#define KB_ACTIVATE_DELAY 10
@@ -105,36 +92,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c
*/
static inline void corgikbd_discharge_all(void)
{
- // STROBE All HiZ
+ /* STROBE All HiZ */
GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
}
static inline void corgikbd_activate_all(void)
{
- // STROBE ALL -> High
+ /* STROBE ALL -> High */
GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
udelay(KB_DISCHARGE_DELAY);
- // Clear any interrupts we may have triggered when altering the GPIO lines
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
}
static inline void corgikbd_activate_col(int col)
{
- // STROBE col -> High, not col -> HiZ
+ /* STROBE col -> High, not col -> HiZ */
GPSR2 = CORGI_GPIO_STROBE_BIT(col);
GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
}
static inline void corgikbd_reset_col(int col)
{
- // STROBE col -> Low
+ /* STROBE col -> Low */
GPCR2 = CORGI_GPIO_STROBE_BIT(col);
- // STROBE col -> out, not col -> HiZ
+ /* STROBE col -> out, not col -> HiZ */
GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
}
@@ -149,14 +136,17 @@ static inline void corgikbd_reset_col(int col)
/* Scan the hardware keyboard and push any changes up through the input layer */
static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
{
- unsigned int row, col, rowd, scancode;
+ unsigned int row, col, rowd;
unsigned long flags;
unsigned int num_pressed;
+ if (corgikbd_data->suspended)
+ return;
+
spin_lock_irqsave(&corgikbd_data->lock, flags);
if (regs)
- input_regs(&corgikbd_data->input, regs);
+ input_regs(corgikbd_data->input, regs);
num_pressed = 0;
for (col = 0; col < KB_COLS; col++) {
@@ -173,17 +163,28 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
rowd = GET_ROWS_STATUS(col);
for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
scancode = SCANCODE(row, col);
- handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
- if (rowd & KB_ROWMASK(row))
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
+
+ if (pressed)
num_pressed++;
+
+ if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
+ && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
+ input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+ corgikbd_data->suspend_jiffies=jiffies;
+ }
}
corgikbd_reset_col(col);
}
corgikbd_activate_all();
- input_sync(&corgikbd_data->input);
+ input_sync(corgikbd_data->input);
/* if any keys are pressed, enable the timer */
if (num_pressed)
@@ -221,8 +222,11 @@ static void corgikbd_timer_callback(unsigned long data)
* The hinge switches generate no interrupt so they need to be
* monitored by a timer.
*
- * When we detect changes, we debounce it and then pass the three
- * positions the system can take as keypresses to the input system.
+ * We debounce the switches and pass them to the input system.
+ *
+ * gprr == 0x00 - Keyboard with Landscape Screen
+ * 0x08 - No Keyboard with Portrait Screen
+ * 0x0c - Keyboard and Screen Closed
*/
#define HINGE_STABLE_COUNT 2
@@ -235,7 +239,7 @@ static void corgikbd_hinge_timer(unsigned long data)
unsigned long gprr;
unsigned long flags;
- gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+ gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
if (gprr != sharpsl_hinge_state) {
hinge_count = 0;
sharpsl_hinge_state = gprr;
@@ -244,10 +248,9 @@ static void corgikbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&corgikbd_data->lock, flags);
- handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
- handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
- handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
- input_sync(&corgikbd_data->input);
+ input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+ input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+ input_sync(corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags);
}
@@ -255,19 +258,48 @@ static void corgikbd_hinge_timer(unsigned long data)
mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
}
+#ifdef CONFIG_PM
+static int corgikbd_suspend(struct device *dev, pm_message_t state)
+{
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+ corgikbd->suspended = 1;
+
+ return 0;
+}
+
+static int corgikbd_resume(struct device *dev)
+{
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ corgikbd->suspend_jiffies=jiffies;
+ corgikbd->suspended = 0;
+
+ return 0;
+}
+#else
+#define corgikbd_suspend NULL
+#define corgikbd_resume NULL
+#endif
+
static int __init corgikbd_probe(struct device *dev)
{
- int i;
struct corgikbd *corgikbd;
+ struct input_dev *input_dev;
+ int i;
- corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
- if (!corgikbd)
+ corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!corgikbd || !input_dev) {
+ kfree(corgikbd);
+ input_free_device(input_dev);
return -ENOMEM;
+ }
- dev_set_drvdata(dev,corgikbd);
- strcpy(corgikbd->phys, "corgikbd/input0");
+ dev_set_drvdata(dev, corgikbd);
- spin_lock_init(corgikbd->lock);
+ corgikbd->input = input_dev;
+ spin_lock_init(&corgikbd->lock);
/* Init Keyboard rescan timer */
init_timer(&corgikbd->timer);
@@ -279,26 +311,32 @@ static int __init corgikbd_probe(struct device *dev)
corgikbd->htimer.function = corgikbd_hinge_timer;
corgikbd->htimer.data = (unsigned long) corgikbd;
- init_input_dev(&corgikbd->input);
- corgikbd->input.private = corgikbd;
- corgikbd->input.name = "Corgi Keyboard";
- corgikbd->input.dev = dev;
- corgikbd->input.phys = corgikbd->phys;
- corgikbd->input.id.bustype = BUS_HOST;
- corgikbd->input.id.vendor = 0x0001;
- corgikbd->input.id.product = 0x0001;
- corgikbd->input.id.version = 0x0100;
- corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
- corgikbd->input.keycode = corgikbd->keycode;
- corgikbd->input.keycodesize = sizeof(unsigned char);
- corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
+ corgikbd->suspend_jiffies=jiffies;
memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
+
+ input_dev->name = "Corgi Keyboard";
+ input_dev->phys = "corgikbd/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = dev;
+ input_dev->private = corgikbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->keycode = corgikbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
- set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
- clear_bit(0, corgikbd->input.keybit);
+ set_bit(corgikbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ set_bit(SW_0, input_dev->swbit);
+ set_bit(SW_1, input_dev->swbit);
+
+ input_register_device(corgikbd->input);
- input_register_device(&corgikbd->input);
mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@@ -315,8 +353,6 @@ static int __init corgikbd_probe(struct device *dev)
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
- printk(KERN_INFO "input: Corgi Keyboard Registered\n");
-
return 0;
}
@@ -331,7 +367,7 @@ static int corgikbd_remove(struct device *dev)
del_timer_sync(&corgikbd->htimer);
del_timer_sync(&corgikbd->timer);
- input_unregister_device(&corgikbd->input);
+ input_unregister_device(corgikbd->input);
kfree(corgikbd);
@@ -343,6 +379,8 @@ static struct device_driver corgikbd_driver = {
.bus = &platform_bus_type,
.probe = corgikbd_probe,
.remove = corgikbd_remove,
+ .suspend = corgikbd_suspend,
+ .resume = corgikbd_resume,
};
static int __devinit corgikbd_init(void)
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index ef78bffed5e7..0a90962c38e7 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -204,7 +204,7 @@ static irqreturn_t hil_kbd_interrupt(struct serio *serio,
hil_packet packet;
int idx;
- kbd = (struct hil_kbd *)serio->private;
+ kbd = serio_get_drvdata(serio);
if (kbd == NULL) {
BUG();
return IRQ_HANDLED;
@@ -234,7 +234,7 @@ static void hil_kbd_disconnect(struct serio *serio)
{
struct hil_kbd *kbd;
- kbd = (struct hil_kbd *)serio->private;
+ kbd = serio_get_drvdata(serio);
if (kbd == NULL) {
BUG();
return;
@@ -245,20 +245,20 @@ static void hil_kbd_disconnect(struct serio *serio)
kfree(kbd);
}
-static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct hil_kbd *kbd;
uint8_t did, *idd;
int i;
- if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
- if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+ kbd = kmalloc(sizeof(*kbd), GFP_KERNEL);
+ if (!kbd)
+ return -ENOMEM;
memset(kbd, 0, sizeof(struct hil_kbd));
if (serio_open(serio, drv)) goto bail0;
- serio->private = kbd;
+ serio_set_drvdata(serio, kbd);
kbd->serio = serio;
kbd->dev.private = kbd;
@@ -342,19 +342,31 @@ static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
down(&(kbd->sem));
up(&(kbd->sem));
- return;
+ return 0;
bail1:
serio_close(serio);
bail0:
kfree(kbd);
+ serio_set_drvdata(serio, NULL);
+ return -EIO;
}
+static struct serio_device_id hil_kbd_ids[] = {
+ {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
struct serio_driver hil_kbd_serio_drv = {
.driver = {
.name = "hil_kbd",
},
.description = "HP HIL keyboard driver",
+ .id_table = hil_kbd_ids,
.connect = hil_kbd_connect,
.disconnect = hil_kbd_disconnect,
.interrupt = hil_kbd_interrupt
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index eecb77db0847..e95bc052e32a 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -22,7 +22,7 @@
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/init.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/hil.h>
#include <linux/spinlock.h>
@@ -278,11 +278,11 @@ static int __init
hil_init_chip(struct parisc_device *dev)
{
if (!dev->irq) {
- printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+ printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start);
return -ENODEV;
}
- hil_base = dev->hpa;
+ hil_base = dev->hpa.start;
hil_irq = dev->irq;
hil_dev.dev_id = dev;
@@ -299,7 +299,7 @@ static struct parisc_device_id hil_tbl[] = {
MODULE_DEVICE_TABLE(parisc, hil_tbl);
static struct parisc_driver hil_driver = {
- .name = "HIL",
+ .name = "hil",
.id_table = hil_tbl,
.probe = hil_init_chip,
};
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 098963c7cdd6..9481132532d0 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -102,7 +102,7 @@ static int ctrlclick_volume = 100; /* % */
module_param (ctrlclick_volume, int, 0);
MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
-static int lk201_compose_is_alt = 0;
+static int lk201_compose_is_alt;
module_param (lk201_compose_is_alt, int, 0);
MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
"will act as an Alt key");
@@ -274,7 +274,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
};
#define CHECK_LED(LED, BITS) do { \
- if (test_bit (LED, lk->dev.led)) \
+ if (test_bit (LED, lk->dev->led)) \
leds_on |= BITS; \
else \
leds_off |= BITS; \
@@ -287,7 +287,7 @@ struct lkkbd {
lk_keycode_t keycode[LK_NUM_KEYCODES];
int ignore_bytes;
unsigned char id[LK_NUM_IGNORE_BYTES];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
struct work_struct tq;
char name[64];
@@ -423,8 +423,7 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
DBG (KERN_INFO "Got byte 0x%02x\n", data);
if (lk->ignore_bytes > 0) {
- DBG (KERN_INFO "Ignoring a byte on %s\n",
- lk->name);
+ DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name);
lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
if (lk->ignore_bytes == 0)
@@ -435,11 +434,11 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
switch (data) {
case LK_ALL_KEYS_UP:
- input_regs (&lk->dev, regs);
+ input_regs (lk->dev, regs);
for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
if (lk->keycode[i] != KEY_RESERVED)
- input_report_key (&lk->dev, lk->keycode[i], 0);
- input_sync (&lk->dev);
+ input_report_key (lk->dev, lk->keycode[i], 0);
+ input_sync (lk->dev);
break;
case LK_METRONOME:
DBG (KERN_INFO "Got LK_METRONOME and don't "
@@ -482,12 +481,12 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
default:
if (lk->keycode[data] != KEY_RESERVED) {
- input_regs (&lk->dev, regs);
- if (!test_bit (lk->keycode[data], lk->dev.key))
- input_report_key (&lk->dev, lk->keycode[data], 1);
+ input_regs (lk->dev, regs);
+ if (!test_bit (lk->keycode[data], lk->dev->key))
+ input_report_key (lk->dev, lk->keycode[data], 1);
else
- input_report_key (&lk->dev, lk->keycode[data], 0);
- input_sync (&lk->dev);
+ input_report_key (lk->dev, lk->keycode[data], 0);
+ input_sync (lk->dev);
} else
printk (KERN_WARNING "%s: Unknown key with "
"scancode 0x%02x on %s.\n",
@@ -605,7 +604,7 @@ lkkbd_reinit (void *data)
lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
/* Enable/disable keyclick (and possibly set volume) */
- if (test_bit (SND_CLICK, lk->dev.snd)) {
+ if (test_bit (SND_CLICK, lk->dev->snd)) {
lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -616,7 +615,7 @@ lkkbd_reinit (void *data)
}
/* Sound the bell if needed */
- if (test_bit (SND_BELL, lk->dev.snd))
+ if (test_bit (SND_BELL, lk->dev->snd))
lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
}
@@ -627,71 +626,70 @@ static int
lkkbd_connect (struct serio *serio, struct serio_driver *drv)
{
struct lkkbd *lk;
+ struct input_dev *input_dev;
int i;
int err;
- if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset (lk, 0, sizeof (struct lkkbd));
-
- init_input_dev (&lk->dev);
- set_bit (EV_KEY, lk->dev.evbit);
- set_bit (EV_LED, lk->dev.evbit);
- set_bit (EV_SND, lk->dev.evbit);
- set_bit (EV_REP, lk->dev.evbit);
- set_bit (LED_CAPSL, lk->dev.ledbit);
- set_bit (LED_SLEEP, lk->dev.ledbit);
- set_bit (LED_COMPOSE, lk->dev.ledbit);
- set_bit (LED_SCROLLL, lk->dev.ledbit);
- set_bit (SND_BELL, lk->dev.sndbit);
- set_bit (SND_CLICK, lk->dev.sndbit);
+ lk = kzalloc (sizeof (struct lkkbd), GFP_KERNEL);
+ input_dev = input_allocate_device ();
+ if (!lk || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
lk->serio = serio;
-
+ lk->dev = input_dev;
INIT_WORK (&lk->tq, lkkbd_reinit, lk);
-
lk->bell_volume = bell_volume;
lk->keyclick_volume = keyclick_volume;
lk->ctrlclick_volume = ctrlclick_volume;
+ memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
- lk->dev.keycode = lk->keycode;
- lk->dev.keycodesize = sizeof (lk_keycode_t);
- lk->dev.keycodemax = LK_NUM_KEYCODES;
-
- lk->dev.event = lkkbd_event;
- lk->dev.private = lk;
+ strlcpy (lk->name, "DEC LK keyboard", sizeof(lk->name));
+ snprintf (lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
+
+ input_dev->name = lk->name;
+ input_dev->phys = lk->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_LKKBD;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->event = lkkbd_event;
+ input_dev->private = lk;
+
+ set_bit (EV_KEY, input_dev->evbit);
+ set_bit (EV_LED, input_dev->evbit);
+ set_bit (EV_SND, input_dev->evbit);
+ set_bit (EV_REP, input_dev->evbit);
+ set_bit (LED_CAPSL, input_dev->ledbit);
+ set_bit (LED_SLEEP, input_dev->ledbit);
+ set_bit (LED_COMPOSE, input_dev->ledbit);
+ set_bit (LED_SCROLLL, input_dev->ledbit);
+ set_bit (SND_BELL, input_dev->sndbit);
+ set_bit (SND_CLICK, input_dev->sndbit);
+
+ input_dev->keycode = lk->keycode;
+ input_dev->keycodesize = sizeof (lk_keycode_t);
+ input_dev->keycodemax = LK_NUM_KEYCODES;
+ for (i = 0; i < LK_NUM_KEYCODES; i++)
+ set_bit (lk->keycode[i], input_dev->keybit);
serio_set_drvdata (serio, lk);
err = serio_open (serio, drv);
- if (err) {
- serio_set_drvdata (serio, NULL);
- kfree (lk);
- return err;
- }
+ if (err)
+ goto fail;
- sprintf (lk->name, "DEC LK keyboard");
- sprintf (lk->phys, "%s/input0", serio->phys);
-
- memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
- for (i = 0; i < LK_NUM_KEYCODES; i++)
- set_bit (lk->keycode[i], lk->dev.keybit);
-
- lk->dev.name = lk->name;
- lk->dev.phys = lk->phys;
- lk->dev.id.bustype = BUS_RS232;
- lk->dev.id.vendor = SERIO_LKKBD;
- lk->dev.id.product = 0;
- lk->dev.id.version = 0x0100;
- lk->dev.dev = &serio->dev;
-
- input_register_device (&lk->dev);
-
- printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
+ input_register_device (lk->dev);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
return 0;
+
+ fail: serio_set_drvdata (serio, NULL);
+ input_free_device (input_dev);
+ kfree (lk);
+ return err;
}
/*
@@ -702,9 +700,11 @@ lkkbd_disconnect (struct serio *serio)
{
struct lkkbd *lk = serio_get_drvdata (serio);
- input_unregister_device (&lk->dev);
+ input_get_device (lk->dev);
+ input_unregister_device (lk->dev);
serio_close (serio);
serio_set_drvdata (serio, NULL);
+ input_put_device (lk->dev);
kfree (lk);
}
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index eecbde294f1f..cc6aaf9e85be 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -37,7 +37,7 @@ static unsigned char dc_kbd_keycode[256] = {
struct dc_kbd {
- struct input_dev dev;
+ struct input_dev *dev;
unsigned char new[8];
unsigned char old[8];
};
@@ -46,30 +46,24 @@ struct dc_kbd {
static void dc_scan_kbd(struct dc_kbd *kbd)
{
int i;
- struct input_dev *dev = &kbd->dev;
+ struct input_dev *dev = kbd->dev;
- for(i=0; i<8; i++)
- input_report_key(dev,
- dc_kbd_keycode[i+224],
- (kbd->new[0]>>i)&1);
+ for (i = 0; i < 8; i++)
+ input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
- for(i=2; i<8; i++) {
+ for (i = 2; i < 8; i++) {
- if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
- if(dc_kbd_keycode[kbd->old[i]])
- input_report_key(dev,
- dc_kbd_keycode[kbd->old[i]],
- 0);
+ if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
+ if (dc_kbd_keycode[kbd->old[i]])
+ input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
else
printk("Unknown key (scancode %#x) released.",
kbd->old[i]);
}
- if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
+ if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
if(dc_kbd_keycode[kbd->new[i]])
- input_report_key(dev,
- dc_kbd_keycode[kbd->new[i]],
- 1);
+ input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
else
printk("Unknown key (scancode %#x) pressed.",
kbd->new[i]);
@@ -89,43 +83,39 @@ static void dc_kbd_callback(struct mapleq *mq)
unsigned long *buf = mq->recvbuf;
if (buf[1] == mapledev->function) {
- memcpy(kbd->new, buf+2, 8);
+ memcpy(kbd->new, buf + 2, 8);
dc_scan_kbd(kbd);
}
}
static int dc_kbd_connect(struct maple_device *dev)
{
- int i;
- unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_kbd *kbd;
+ struct input_dev *input_dev;
+ unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
+ int i;
- if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
- return -1;
- memset(kbd, 0, sizeof(struct dc_kbd));
-
- dev->private_data = kbd;
-
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-
- init_input_dev(&kbd->dev);
-
- for (i=0; i<255; i++)
- set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
-
- clear_bit(0, kbd->dev.keybit);
+ dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbd || !input_dev) {
+ kfree(kbd);
+ input_free_device(input_dev);
+ return -ENOMEM;
+ }
- kbd->dev.private = kbd;
+ kbd->dev = input_dev;
- kbd->dev.name = dev->product_name;
- kbd->dev.id.bustype = BUS_MAPLE;
+ input_dev->name = dev->product_name;
+ input_dev->id.bustype = BUS_MAPLE;
+ input_dev->private = kbd;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ for (i = 0; i < 255; i++)
+ set_bit(dc_kbd_keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- input_register_device(&kbd->dev);
+ input_register_device(kbd->dev);
maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
-
- printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
-
return 0;
}
@@ -134,7 +124,7 @@ static void dc_kbd_disconnect(struct maple_device *dev)
{
struct dc_kbd *kbd = dev->private_data;
- input_unregister_device(&kbd->dev);
+ input_unregister_device(kbd->dev);
kfree(kbd);
}
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 2e8ce1613eec..d10983c521e6 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -57,11 +57,9 @@ static unsigned char nkbd_keycode[128] = {
KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
};
-static char *nkbd_name = "Newton Keyboard";
-
struct nkbd {
unsigned char keycode[128];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
char phys[32];
};
@@ -73,13 +71,13 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
/* invalid scan codes are probably the init sequence, so we ignore them */
if (nkbd->keycode[data & NKBD_KEY]) {
- input_regs(&nkbd->dev, regs);
- input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
- input_sync(&nkbd->dev);
+ input_regs(nkbd->dev, regs);
+ input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
+ input_sync(nkbd->dev);
}
else if (data == 0xe7) /* end of init sequence */
- printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+ printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
return IRQ_HANDLED;
}
@@ -87,62 +85,59 @@ static irqreturn_t nkbd_interrupt(struct serio *serio,
static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct nkbd *nkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(nkbd, 0, sizeof(struct nkbd));
- nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!nkbd || !input_dev)
+ goto fail;
nkbd->serio = serio;
+ nkbd->dev = input_dev;
+ sprintf(nkbd->phys, "%s/input0", serio->phys);
+ memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
- init_input_dev(&nkbd->dev);
- nkbd->dev.keycode = nkbd->keycode;
- nkbd->dev.keycodesize = sizeof(unsigned char);
- nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
- nkbd->dev.private = nkbd;
+ input_dev->name = "Newton Keyboard";
+ input_dev->phys = nkbd->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_NEWTON;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = nkbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->keycode = nkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
+ for (i = 0; i < 128; i++)
+ set_bit(nkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
serio_set_drvdata(serio, nkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(nkbd);
- return err;
- }
-
- memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
- for (i = 0; i < 128; i++)
- set_bit(nkbd->keycode[i], nkbd->dev.keybit);
- clear_bit(0, nkbd->dev.keybit);
-
- sprintf(nkbd->phys, "%s/input0", serio->phys);
-
- nkbd->dev.name = nkbd_name;
- nkbd->dev.phys = nkbd->phys;
- nkbd->dev.id.bustype = BUS_RS232;
- nkbd->dev.id.vendor = SERIO_NEWTON;
- nkbd->dev.id.product = 0x0001;
- nkbd->dev.id.version = 0x0100;
- nkbd->dev.dev = &serio->dev;
-
- input_register_device(&nkbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(nkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(nkbd);
+ return err;
}
static void nkbd_disconnect(struct serio *serio)
{
struct nkbd *nkbd = serio_get_drvdata(serio);
- input_unregister_device(&nkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(nkbd->dev);
kfree(nkbd);
}
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
new file mode 100644
index 000000000000..0fa38a559cdf
--- /dev/null
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -0,0 +1,487 @@
+/*
+ * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on corgikbd.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.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/spitz.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define KB_ROWS 7
+#define KB_COLS 11
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) (((r)<<4) + (c) + 1)
+#define NR_SCANCODES ((KB_ROWS<<4) + 1)
+
+#define HINGE_SCAN_INTERVAL (150) /* ms */
+
+#define SPITZ_KEY_CALENDER KEY_F1
+#define SPITZ_KEY_ADDRESS KEY_F2
+#define SPITZ_KEY_FN KEY_F3
+#define SPITZ_KEY_CANCEL KEY_F4
+#define SPITZ_KEY_EXOK KEY_F5
+#define SPITZ_KEY_EXCANCEL KEY_F6
+#define SPITZ_KEY_EXJOGDOWN KEY_F7
+#define SPITZ_KEY_EXJOGUP KEY_F8
+#define SPITZ_KEY_JAP1 KEY_LEFTALT
+#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL
+#define SPITZ_KEY_SYNC KEY_F9
+#define SPITZ_KEY_MAIL KEY_F10
+#define SPITZ_KEY_OK KEY_F11
+#define SPITZ_KEY_MENU KEY_F12
+
+static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
+ 0, /* 0 */
+ KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */
+ 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
+ KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
+ SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
+ SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
+ SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */
+ KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */
+};
+
+static int spitz_strobes[] = {
+ SPITZ_GPIO_KEY_STROBE0,
+ SPITZ_GPIO_KEY_STROBE1,
+ SPITZ_GPIO_KEY_STROBE2,
+ SPITZ_GPIO_KEY_STROBE3,
+ SPITZ_GPIO_KEY_STROBE4,
+ SPITZ_GPIO_KEY_STROBE5,
+ SPITZ_GPIO_KEY_STROBE6,
+ SPITZ_GPIO_KEY_STROBE7,
+ SPITZ_GPIO_KEY_STROBE8,
+ SPITZ_GPIO_KEY_STROBE9,
+ SPITZ_GPIO_KEY_STROBE10,
+};
+
+static int spitz_senses[] = {
+ SPITZ_GPIO_KEY_SENSE0,
+ SPITZ_GPIO_KEY_SENSE1,
+ SPITZ_GPIO_KEY_SENSE2,
+ SPITZ_GPIO_KEY_SENSE3,
+ SPITZ_GPIO_KEY_SENSE4,
+ SPITZ_GPIO_KEY_SENSE5,
+ SPITZ_GPIO_KEY_SENSE6,
+};
+
+struct spitzkbd {
+ unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
+ struct input_dev *input;
+ char phys[32];
+
+ spinlock_t lock;
+ struct timer_list timer;
+ struct timer_list htimer;
+
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+#define KB_DISCHARGE_DELAY 10
+#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.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void spitzkbd_discharge_all(void)
+{
+ /* STROBE All HiZ */
+ GPCR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPCR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPCR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPCR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+}
+
+static inline void spitzkbd_activate_all(void)
+{
+ /* STROBE ALL -> High */
+ GPSR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT;
+ GPSR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT;
+ GPSR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT;
+ GPSR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT;
+
+ udelay(KB_DISCHARGE_DELAY);
+
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
+ GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
+ GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
+ GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
+ GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
+}
+
+static inline void spitzkbd_activate_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPSR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline void spitzkbd_reset_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPCR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline int spitzkbd_get_row_status(int col)
+{
+ return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
+ | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
+ | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
+}
+
+/*
+ * The spitz keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd;
+ unsigned long flags;
+ unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
+
+ if (spitzkbd_data->suspended)
+ return;
+
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ input_regs(spitzkbd_data->input, regs);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+ /*
+ * Discharge the output driver capacitatance
+ * in the keyboard matrix. (Yes it is significant..)
+ */
+
+ spitzkbd_discharge_all();
+ udelay(KB_DISCHARGE_DELAY);
+
+ spitzkbd_activate_col(col);
+ udelay(KB_ACTIVATE_DELAY);
+
+ rowd = spitzkbd_get_row_status(col);
+ for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
+ scancode = SCANCODE(row, col);
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+
+ if (pressed)
+ num_pressed++;
+ }
+ spitzkbd_reset_col(col);
+ }
+
+ spitzkbd_activate_all();
+
+ input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+ input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+
+ if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
+ input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+ spitzkbd_data->suspend_jiffies = jiffies;
+ }
+
+ input_sync(spitzkbd_data->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+}
+
+/*
+ * spitz keyboard interrupt handler.
+ */
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->timer)) {
+ /** wait chattering delay **/
+ udelay(20);
+ spitzkbd_scankeyboard(spitzkbd_data, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * spitz timer checking for released keys
+ */
+static void spitzkbd_timer_callback(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+
+ spitzkbd_scankeyboard(spitzkbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate an interrupt.
+ * We debounce the switches and pass them to the input system.
+ */
+
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->htimer))
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ return IRQ_HANDLED;
+}
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void spitzkbd_hinge_timer(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ unsigned long state;
+ unsigned long flags;
+
+ state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+ if (state != sharpsl_hinge_state) {
+ hinge_count = 0;
+ sharpsl_hinge_state = state;
+ } else if (hinge_count < HINGE_STABLE_COUNT) {
+ hinge_count++;
+ }
+
+ if (hinge_count >= HINGE_STABLE_COUNT) {
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+ input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_sync(spitzkbd_data->input);
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+ } else {
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+ }
+}
+
+#ifdef CONFIG_PM
+static int spitzkbd_suspend(struct device *dev, pm_message_t state)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ spitzkbd->suspended = 1;
+
+ /* Set Strobe lines as inputs - *except* strobe line 0 leave this
+ enabled so we can detect a power button press for resume */
+ for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+
+ return 0;
+}
+
+static int spitzkbd_resume(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ spitzkbd->suspend_jiffies = jiffies;
+ spitzkbd->suspended = 0;
+
+ return 0;
+}
+#else
+#define spitzkbd_suspend NULL
+#define spitzkbd_resume NULL
+#endif
+
+static int __init spitzkbd_probe(struct device *dev)
+{
+ struct spitzkbd *spitzkbd;
+ struct input_dev *input_dev;
+ int i;
+
+ spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
+ if (!spitzkbd)
+ return -ENOMEM;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(spitzkbd);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, spitzkbd);
+ strcpy(spitzkbd->phys, "spitzkbd/input0");
+
+ spin_lock_init(&spitzkbd->lock);
+
+ /* Init Keyboard rescan timer */
+ init_timer(&spitzkbd->timer);
+ spitzkbd->timer.function = spitzkbd_timer_callback;
+ spitzkbd->timer.data = (unsigned long) spitzkbd;
+
+ /* Init Hinge Timer */
+ init_timer(&spitzkbd->htimer);
+ spitzkbd->htimer.function = spitzkbd_hinge_timer;
+ spitzkbd->htimer.data = (unsigned long) spitzkbd;
+
+ spitzkbd->suspend_jiffies = jiffies;
+
+ spitzkbd->input = input_dev;
+
+ input_dev->private = spitzkbd;
+ input_dev->name = "Spitz Keyboard";
+ input_dev->phys = spitzkbd->phys;
+ input_dev->cdev.dev = dev;
+
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ input_dev->keycode = spitzkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+
+ memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
+ for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
+ set_bit(spitzkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ set_bit(SW_0, input_dev->swbit);
+ set_bit(SW_1, input_dev->swbit);
+
+ input_register_device(input_dev);
+
+ mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
+ pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
+ if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
+ SA_INTERRUPT, "Spitzkbd Sense", spitzkbd))
+ printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
+ else
+ set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING);
+ }
+
+ /* Set Strobe lines as outputs - set high */
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
+
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd);
+
+ set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE);
+
+ printk(KERN_INFO "input: Spitz Keyboard Registered\n");
+
+ return 0;
+}
+
+static int spitzkbd_remove(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
+ free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
+
+ free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+
+ del_timer_sync(&spitzkbd->htimer);
+ del_timer_sync(&spitzkbd->timer);
+
+ input_unregister_device(spitzkbd->input);
+
+ kfree(spitzkbd);
+
+ return 0;
+}
+
+static struct device_driver spitzkbd_driver = {
+ .name = "spitz-keyboard",
+ .bus = &platform_bus_type,
+ .probe = spitzkbd_probe,
+ .remove = spitzkbd_remove,
+ .suspend = spitzkbd_suspend,
+ .resume = spitzkbd_resume,
+};
+
+static int __devinit spitzkbd_init(void)
+{
+ return driver_register(&spitzkbd_driver);
+}
+
+static void __exit spitzkbd_exit(void)
+{
+ driver_unregister(&spitzkbd_driver);
+}
+
+module_init(spitzkbd_init);
+module_exit(spitzkbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Spitz Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 596964ceb96d..b15b6d8d4f83 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static unsigned char sunkbd_keycode[128] = {
- 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64, 0,
+ 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
@@ -76,13 +76,14 @@ static unsigned char sunkbd_keycode[128] = {
struct sunkbd {
unsigned char keycode[128];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
struct work_struct tq;
wait_queue_head_t wait;
char name[64];
char phys[32];
char type;
+ unsigned char enabled;
volatile s8 reset;
volatile s8 layout;
};
@@ -124,10 +125,13 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
break;
default:
+ if (!sunkbd->enabled)
+ break;
+
if (sunkbd->keycode[data & SUNKBD_KEY]) {
- input_regs(&sunkbd->dev, regs);
- input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
- input_sync(&sunkbd->dev);
+ input_regs(sunkbd->dev, regs);
+ input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
+ input_sync(sunkbd->dev);
} else {
printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
@@ -184,7 +188,7 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
sunkbd->reset = -2;
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
- if (sunkbd->reset <0)
+ if (sunkbd->reset < 0)
return -1;
sunkbd->type = sunkbd->reset;
@@ -213,10 +217,17 @@ static void sunkbd_reinit(void *data)
sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
sunkbd->serio->write(sunkbd->serio,
- (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
- (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
- sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
- sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
+ (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
+ (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led));
+ sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
+ sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
+}
+
+static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
+{
+ serio_pause_rx(sunkbd->serio);
+ sunkbd->enabled = 1;
+ serio_continue_rx(sunkbd->serio);
}
/*
@@ -226,70 +237,64 @@ static void sunkbd_reinit(void *data)
static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct sunkbd *sunkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
- return -ENOMEM;
- memset(sunkbd, 0, sizeof(struct sunkbd));
-
- init_input_dev(&sunkbd->dev);
- init_waitqueue_head(&sunkbd->wait);
-
- sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
- sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
- sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+ sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!sunkbd || !input_dev)
+ goto fail;
sunkbd->serio = serio;
-
+ sunkbd->dev = input_dev;
+ init_waitqueue_head(&sunkbd->wait);
INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
-
- sunkbd->dev.keycode = sunkbd->keycode;
- sunkbd->dev.keycodesize = sizeof(unsigned char);
- sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
-
- sunkbd->dev.event = sunkbd_event;
- sunkbd->dev.private = sunkbd;
+ snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
serio_set_drvdata(serio, sunkbd);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(sunkbd);
- return err;
- }
+ if (err)
+ goto fail;
if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(sunkbd);
- return -ENODEV;
+ goto fail;
}
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
-
memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
- for (i = 0; i < 128; i++)
- set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
- clear_bit(0, sunkbd->dev.keybit);
-
- sprintf(sunkbd->phys, "%s/input0", serio->phys);
-
- sunkbd->dev.name = sunkbd->name;
- sunkbd->dev.phys = sunkbd->phys;
- sunkbd->dev.id.bustype = BUS_RS232;
- sunkbd->dev.id.vendor = SERIO_SUNKBD;
- sunkbd->dev.id.product = sunkbd->type;
- sunkbd->dev.id.version = 0x0100;
- sunkbd->dev.dev = &serio->dev;
- input_register_device(&sunkbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
+ input_dev->name = sunkbd->name;
+ input_dev->phys = sunkbd->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_SUNKBD;
+ input_dev->id.product = sunkbd->type;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = sunkbd;
+ input_dev->event = sunkbd_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
+ input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+
+ input_dev->keycode = sunkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
+ for (i = 0; i < 128; i++)
+ set_bit(sunkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+ sunkbd_enable(sunkbd, 1);
+ input_register_device(sunkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(sunkbd);
+ return err;
}
/*
@@ -299,7 +304,9 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
static void sunkbd_disconnect(struct serio *serio)
{
struct sunkbd *sunkbd = serio_get_drvdata(serio);
- input_unregister_device(&sunkbd->dev);
+
+ sunkbd_enable(sunkbd, 0);
+ input_unregister_device(sunkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(sunkbd);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 19eaec7789d1..4135e3e16c51 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -56,11 +56,9 @@ static unsigned char xtkbd_keycode[256] = {
106
};
-static char *xtkbd_name = "XT Keyboard";
-
struct xtkbd {
unsigned char keycode[256];
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
char phys[32];
};
@@ -77,9 +75,9 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
default:
if (xtkbd->keycode[data & XTKBD_KEY]) {
- input_regs(&xtkbd->dev, regs);
- input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
- input_sync(&xtkbd->dev);
+ input_regs(xtkbd->dev, regs);
+ input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
+ input_sync(xtkbd->dev);
} else {
printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
@@ -91,62 +89,60 @@ static irqreturn_t xtkbd_interrupt(struct serio *serio,
static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct xtkbd *xtkbd;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
int i;
- int err;
-
- if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(xtkbd, 0, sizeof(struct xtkbd));
- xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!xtkbd || !input_dev)
+ goto fail;
xtkbd->serio = serio;
+ xtkbd->dev = input_dev;
+ sprintf(xtkbd->phys, "%s/input0", serio->phys);
+ memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
- init_input_dev(&xtkbd->dev);
- xtkbd->dev.keycode = xtkbd->keycode;
- xtkbd->dev.keycodesize = sizeof(unsigned char);
- xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
- xtkbd->dev.private = xtkbd;
-
- serio_set_drvdata(serio, xtkbd);
+ input_dev->name = "XT Keyboard";
+ input_dev->phys = xtkbd->phys;
+ input_dev->id.bustype = BUS_XTKBD;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = xtkbd;
- err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(xtkbd);
- return err;
- }
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->keycode = xtkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
- memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
for (i = 0; i < 255; i++)
- set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
- clear_bit(0, xtkbd->dev.keybit);
-
- sprintf(xtkbd->phys, "%s/input0", serio->phys);
-
- xtkbd->dev.name = xtkbd_name;
- xtkbd->dev.phys = xtkbd->phys;
- xtkbd->dev.id.bustype = BUS_XTKBD;
- xtkbd->dev.id.vendor = 0x0001;
- xtkbd->dev.id.product = 0x0001;
- xtkbd->dev.id.version = 0x0100;
- xtkbd->dev.dev = &serio->dev;
+ set_bit(xtkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- input_register_device(&xtkbd->dev);
+ serio_set_drvdata(serio, xtkbd);
- printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail;
+ input_register_device(xtkbd->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(xtkbd);
+ return err;
}
static void xtkbd_disconnect(struct serio *serio)
{
struct xtkbd *xtkbd = serio_get_drvdata(serio);
- input_unregister_device(&xtkbd->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(xtkbd->dev);
kfree(xtkbd);
}
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index bb934e6d9636..b3eaac1b35b6 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -14,7 +14,7 @@ if INPUT_MISC
config INPUT_PCSPKR
tristate "PC Speaker support"
- depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
+ depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
help
Say Y here if you want the standard PC Speaker to be used for
bells and whistles.
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 64abdd98d482..04489ad7702a 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -24,9 +24,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL");
-static char m68kspkr_name[] = "m68k beeper";
-static char m68kspkr_phys[] = "m68k/generic";
-static struct input_dev m68kspkr_dev;
+static struct input_dev *m68kspkr_dev;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -51,32 +49,34 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
static int __init m68kspkr_init(void)
{
- if (!mach_beep){
- printk("%s: no lowlevel beep support\n", m68kspkr_name);
- return -1;
+ if (!mach_beep) {
+ printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
+ return -ENODEV;
}
- m68kspkr_dev.evbit[0] = BIT(EV_SND);
- m68kspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- m68kspkr_dev.event = m68kspkr_event;
+ m68kspkr_dev = input_allocate_device();
+ if (!m68kspkr_dev)
+ return -ENOMEM;
- m68kspkr_dev.name = m68kspkr_name;
- m68kspkr_dev.phys = m68kspkr_phys;
- m68kspkr_dev.id.bustype = BUS_HOST;
- m68kspkr_dev.id.vendor = 0x001f;
- m68kspkr_dev.id.product = 0x0001;
- m68kspkr_dev.id.version = 0x0100;
+ m68kspkr_dev->name = "m68k beeper";
+ m68kspkr_dev->phys = "m68k/generic";
+ m68kspkr_dev->id.bustype = BUS_HOST;
+ m68kspkr_dev->id.vendor = 0x001f;
+ m68kspkr_dev->id.product = 0x0001;
+ m68kspkr_dev->id.version = 0x0100;
- input_register_device(&m68kspkr_dev);
+ m68kspkr_dev->evbit[0] = BIT(EV_SND);
+ m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ m68kspkr_dev->event = m68kspkr_event;
- printk(KERN_INFO "input: %s\n", m68kspkr_name);
+ input_register_device(m68kspkr_dev);
return 0;
}
static void __exit m68kspkr_exit(void)
{
- input_unregister_device(&m68kspkr_dev);
+ input_unregister_device(m68kspkr_dev);
}
module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 3013194f462b..68ac97f101b0 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -23,9 +23,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
-static char pcspkr_name[] = "PC Speaker";
-static char pcspkr_phys[] = "isa0061/input0";
-static struct input_dev pcspkr_dev;
+static struct input_dev *pcspkr_dev;
static DEFINE_SPINLOCK(i8253_beep_lock);
@@ -68,27 +66,29 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
static int __init pcspkr_init(void)
{
- pcspkr_dev.evbit[0] = BIT(EV_SND);
- pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- pcspkr_dev.event = pcspkr_event;
+ pcspkr_dev = input_allocate_device();
+ if (!pcspkr_dev)
+ return -ENOMEM;
- pcspkr_dev.name = pcspkr_name;
- pcspkr_dev.phys = pcspkr_phys;
- pcspkr_dev.id.bustype = BUS_ISA;
- pcspkr_dev.id.vendor = 0x001f;
- pcspkr_dev.id.product = 0x0001;
- pcspkr_dev.id.version = 0x0100;
+ pcspkr_dev->name = "PC Speaker";
+ pcspkr_dev->phys = "isa0061/input0";
+ pcspkr_dev->id.bustype = BUS_ISA;
+ pcspkr_dev->id.vendor = 0x001f;
+ pcspkr_dev->id.product = 0x0001;
+ pcspkr_dev->id.version = 0x0100;
- input_register_device(&pcspkr_dev);
+ pcspkr_dev->evbit[0] = BIT(EV_SND);
+ pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ pcspkr_dev->event = pcspkr_event;
- printk(KERN_INFO "input: %s\n", pcspkr_name);
+ input_register_device(pcspkr_dev);
return 0;
}
static void __exit pcspkr_exit(void)
{
- input_unregister_device(&pcspkr_dev);
+ input_unregister_device(pcspkr_dev);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
}
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index cdc3fb3d5f46..29d97b12be7a 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -17,28 +17,24 @@
#endif
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
-MODULE_DESCRIPTION("PC Speaker beeper driver");
+MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL");
static unsigned long beep_iobase;
-
-static char *sparcspkr_isa_name = "Sparc ISA Speaker";
-static char *sparcspkr_ebus_name = "Sparc EBUS Speaker";
-static char *sparcspkr_phys = "sparc/input0";
-static struct input_dev sparcspkr_dev;
+static struct input_dev *sparcspkr_dev;
DEFINE_SPINLOCK(beep_lock);
static void __init init_sparcspkr_struct(void)
{
- sparcspkr_dev.evbit[0] = BIT(EV_SND);
- sparcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-
- sparcspkr_dev.phys = sparcspkr_phys;
- sparcspkr_dev.id.bustype = BUS_ISA;
- sparcspkr_dev.id.vendor = 0x001f;
- sparcspkr_dev.id.product = 0x0001;
- sparcspkr_dev.id.version = 0x0100;
+ sparcspkr_dev->evbit[0] = BIT(EV_SND);
+ sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+
+ sparcspkr_dev->phys = "sparc/input0";
+ sparcspkr_dev->id.bustype = BUS_ISA;
+ sparcspkr_dev->id.vendor = 0x001f;
+ sparcspkr_dev->id.product = 0x0001;
+ sparcspkr_dev->id.version = 0x0100;
}
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -84,14 +80,15 @@ static int __init init_ebus_beep(struct linux_ebus_device *edev)
{
beep_iobase = edev->resource[0].start;
- init_sparcspkr_struct();
+ sparcspkr_dev = input_allocate_device();
+ if (!sparcspkr_dev)
+ return -ENOMEM;
- sparcspkr_dev.name = sparcspkr_ebus_name;
- sparcspkr_dev.event = ebus_spkr_event;
+ sparcspkr_dev->name = "Sparc EBUS Speaker";
+ sparcspkr_dev->event = ebus_spkr_event;
- input_register_device(&sparcspkr_dev);
+ input_register_device(sparcspkr_dev);
- printk(KERN_INFO "input: %s\n", sparcspkr_ebus_name);
return 0;
}
@@ -137,15 +134,17 @@ static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
{
beep_iobase = isa_dev->resource.start;
+ sparcspkr_dev = input_allocate_device();
+ if (!sparcspkr_dev)
+ return -ENOMEM;
+
init_sparcspkr_struct();
- sparcspkr_dev.name = sparcspkr_isa_name;
- sparcspkr_dev.event = isa_spkr_event;
- sparcspkr_dev.id.bustype = BUS_ISA;
+ sparcspkr_dev->name = "Sparc ISA Speaker";
+ sparcspkr_dev->event = isa_spkr_event;
- input_register_device(&sparcspkr_dev);
+ input_register_device(sparcspkr_dev);
- printk(KERN_INFO "input: %s\n", sparcspkr_isa_name);
return 0;
}
#endif
@@ -182,7 +181,7 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void)
{
- input_unregister_device(&sparcspkr_dev);
+ input_unregister_device(sparcspkr_dev);
}
module_init(sparcspkr_init);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index d5c5b32045af..4015a91f4b6e 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -90,11 +90,11 @@ static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct
static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request)
{
- complete(&request->done);
-
/* Mark slot as available */
udev->requests[request->id] = NULL;
wake_up_interruptible(&udev->requests_waitq);
+
+ complete(&request->done);
}
static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 537154dd7a87..574b18a523af 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -17,7 +17,7 @@ config MOUSE_PS2
default y
select SERIO
select SERIO_LIBPS2
- select SERIO_I8042 if PC
+ select SERIO_I8042 if X86_PC
select SERIO_GSCPS2 if GSC
---help---
Say Y here if you have a PS/2 mouse connected to your system. This
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c4909b49337d..82b330bbf068 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
+psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0d68e5e0182a..4acc7fd4cd0f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -79,8 +79,8 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
{
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = &psmouse->dev;
- struct input_dev *dev2 = &priv->dev2;
+ struct input_dev *dev = psmouse->dev;
+ struct input_dev *dev2 = priv->dev2;
int x, y, z, ges, fin, left, right, middle;
int back = 0, forward = 0;
@@ -170,7 +170,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
if (priv->i->flags & ALPS_WHEEL)
- input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
+ input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, forward);
@@ -379,20 +379,24 @@ static int alps_reconnect(struct psmouse *psmouse)
static void alps_disconnect(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
+
psmouse_reset(psmouse);
- input_unregister_device(&priv->dev2);
+ input_unregister_device(priv->dev2);
kfree(priv);
}
int alps_init(struct psmouse *psmouse)
{
struct alps_data *priv;
+ struct input_dev *dev1 = psmouse->dev, *dev2;
int version;
- psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
- if (!priv)
+ psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+ dev2 = input_allocate_device();
+ if (!priv || !dev2)
goto init_fail;
- memset(priv, 0, sizeof(struct alps_data));
+
+ priv->dev2 = dev2;
if (!(priv->i = alps_get_model(psmouse, &version)))
goto init_fail;
@@ -411,41 +415,39 @@ int alps_init(struct psmouse *psmouse)
if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
goto init_fail;
- psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
- psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
+ dev1->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+ dev1->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+ dev1->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
- input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
+ dev1->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+ input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->i->flags & ALPS_WHEEL) {
- psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
- psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+ dev1->evbit[LONG(EV_REL)] |= BIT(EV_REL);
+ dev1->relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
}
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
- psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+ dev1->keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+ dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
}
sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
- priv->dev2.phys = priv->phys;
- priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
- priv->dev2.id.bustype = BUS_I8042;
- priv->dev2.id.vendor = 0x0002;
- priv->dev2.id.product = PSMOUSE_ALPS;
- priv->dev2.id.version = 0x0000;
-
- priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
- priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ dev2->phys = priv->phys;
+ dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
+ dev2->id.bustype = BUS_I8042;
+ dev2->id.vendor = 0x0002;
+ dev2->id.product = PSMOUSE_ALPS;
+ dev2->id.version = 0x0000;
- input_register_device(&priv->dev2);
+ dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
+ dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
+ input_register_device(priv->dev2);
psmouse->protocol_handler = alps_process_byte;
psmouse->disconnect = alps_disconnect;
@@ -455,6 +457,7 @@ int alps_init(struct psmouse *psmouse)
return 0;
init_fail:
+ input_free_device(dev2);
kfree(priv);
return -1;
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index aba103dd65b7..e428f8d5d12e 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -22,7 +22,7 @@ struct alps_model_info {
};
struct alps_data {
- struct input_dev dev2; /* Relative device */
+ struct input_dev *dev2; /* Relative device */
char name[32]; /* Name */
char phys[32]; /* Phys */
struct alps_model_info *i; /* Info */
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index e994849efb8f..d13d4c8fe3c5 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -34,10 +34,7 @@ MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
static int amimouse_lastx, amimouse_lasty;
-static struct input_dev amimouse_dev;
-
-static char *amimouse_name = "Amiga mouse";
-static char *amimouse_phys = "amimouse/input0";
+static struct input_dev *amimouse_dev;
static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
@@ -62,16 +59,16 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
potgor = custom.potgor;
- input_regs(&amimouse_dev, fp);
+ input_regs(amimouse_dev, fp);
- input_report_rel(&amimouse_dev, REL_X, dx);
- input_report_rel(&amimouse_dev, REL_Y, dy);
+ input_report_rel(amimouse_dev, REL_X, dx);
+ input_report_rel(amimouse_dev, REL_Y, dy);
- input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
- input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
- input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400);
+ input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
+ input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
+ input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400);
- input_sync(&amimouse_dev);
+ input_sync(amimouse_dev);
return IRQ_HANDLED;
}
@@ -103,28 +100,30 @@ static int __init amimouse_init(void)
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
- amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- amimouse_dev.open = amimouse_open;
- amimouse_dev.close = amimouse_close;
+ if (!(amimouse_dev = input_allocate_device()))
+ return -ENOMEM;
+
+ amimouse_dev->name = "Amiga mouse";
+ amimouse_dev->phys = "amimouse/input0";
+ amimouse_dev->id.bustype = BUS_AMIGA;
+ amimouse_dev->id.vendor = 0x0001;
+ amimouse_dev->id.product = 0x0002;
+ amimouse_dev->id.version = 0x0100;
- amimouse_dev.name = amimouse_name;
- amimouse_dev.phys = amimouse_phys;
- amimouse_dev.id.bustype = BUS_AMIGA;
- amimouse_dev.id.vendor = 0x0001;
- amimouse_dev.id.product = 0x0002;
- amimouse_dev.id.version = 0x0100;
+ amimouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ amimouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ amimouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ amimouse_dev->open = amimouse_open;
+ amimouse_dev->close = amimouse_close;
- input_register_device(&amimouse_dev);
+ input_register_device(amimouse_dev);
- printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
return 0;
}
static void __exit amimouse_exit(void)
{
- input_unregister_device(&amimouse_dev);
+ input_unregister_device(amimouse_dev);
}
module_init(amimouse_init);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bc22849c6c79..c2bf2ed07dc6 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -196,7 +196,7 @@ static irqreturn_t hil_ptr_interrupt(struct serio *serio,
hil_packet packet;
int idx;
- ptr = (struct hil_ptr *)serio->private;
+ ptr = serio_get_drvdata(serio);
if (ptr == NULL) {
BUG();
return IRQ_HANDLED;
@@ -227,7 +227,7 @@ static void hil_ptr_disconnect(struct serio *serio)
{
struct hil_ptr *ptr;
- ptr = (struct hil_ptr *)serio->private;
+ ptr = serio_get_drvdata(serio);
if (ptr == NULL) {
BUG();
return;
@@ -238,21 +238,19 @@ static void hil_ptr_disconnect(struct serio *serio)
kfree(ptr);
}
-static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
{
struct hil_ptr *ptr;
char *txt;
unsigned int i, naxsets, btntype;
uint8_t did, *idd;
- if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
- if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+ if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM;
memset(ptr, 0, sizeof(struct hil_ptr));
if (serio_open(serio, driver)) goto bail0;
- serio->private = ptr;
+ serio_set_drvdata(serio, ptr);
ptr->serio = serio;
ptr->dev.private = ptr;
@@ -380,23 +378,34 @@ static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
did);
- return;
+ return 0;
bail1:
serio_close(serio);
bail0:
kfree(ptr);
- return;
+ serio_set_drvdata(serio, NULL);
+ return -ENODEV;
}
+static struct serio_device_id hil_ptr_ids[] = {
+ {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
static struct serio_driver hil_ptr_serio_driver = {
.driver = {
.name = "hil_ptr",
},
.description = "HP HIL mouse/tablet driver",
- .connect = hil_ptr_connect,
- .disconnect = hil_ptr_disconnect,
- .interrupt = hil_ptr_interrupt
+ .id_table = hil_ptr_ids,
+ .connect = hil_ptr_connect,
+ .disconnect = hil_ptr_disconnect,
+ .interrupt = hil_ptr_interrupt
};
static int __init hil_ptr_init(void)
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 1f62c0134010..afc66f56df43 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -87,40 +87,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq=");
-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int inport_open(struct input_dev *dev)
-{
- if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
- return -EBUSY;
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
- return 0;
-}
-
-static void inport_close(struct input_dev *dev)
-{
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- free_irq(inport_irq, NULL);
-}
-
-static struct input_dev inport_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .open = inport_open,
- .close = inport_close,
- .name = INPORT_NAME,
- .phys = "isa023c/input0",
- .id = {
- .bustype = BUS_ISA,
- .vendor = INPORT_VENDOR,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *inport_dev;
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -129,31 +96,48 @@ static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_regs(&inport_dev, regs);
+ input_regs(inport_dev, regs);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
- input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
+ input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
- input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
+ input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
- input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
- input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
- input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
+ input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
+ input_report_key(inport_dev, BTN_LEFT, buttons & 2);
+ input_report_key(inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_sync(&inport_dev);
+ input_sync(inport_dev);
return IRQ_HANDLED;
}
+static int inport_open(struct input_dev *dev)
+{
+ if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
+ return -EBUSY;
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+
+ return 0;
+}
+
+static void inport_close(struct input_dev *dev)
+{
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
+ free_irq(inport_irq, NULL);
+}
+
static int __init inport_init(void)
{
- unsigned char a,b,c;
+ unsigned char a, b, c;
if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -163,26 +147,44 @@ static int __init inport_init(void)
a = inb(INPORT_SIGNATURE_PORT);
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
- if (( a == b ) || ( a != c )) {
+ if (a == b || a != c) {
release_region(INPORT_BASE, INPORT_EXTENT);
printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
return -ENODEV;
}
+ if (!(inport_dev = input_allocate_device())) {
+ printk(KERN_ERR "inport.c: Not enough memory for input device\n");
+ release_region(INPORT_BASE, INPORT_EXTENT);
+ return -ENOMEM;
+ }
+
+ inport_dev->name = INPORT_NAME;
+ inport_dev->phys = "isa023c/input0";
+ inport_dev->id.bustype = BUS_ISA;
+ inport_dev->id.vendor = INPORT_VENDOR;
+ inport_dev->id.product = 0x0001;
+ inport_dev->id.version = 0x0100;
+
+ inport_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ inport_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ inport_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+ inport_dev->open = inport_open;
+ inport_dev->close = inport_close;
+
outb(INPORT_RESET, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_register_device(&inport_dev);
-
- printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n", INPORT_BASE, inport_irq);
+ input_register_device(inport_dev);
return 0;
}
static void __exit inport_exit(void)
{
- input_unregister_device(&inport_dev);
+ input_unregister_device(inport_dev);
release_region(INPORT_BASE, INPORT_EXTENT);
}
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index bd9df9b28325..55991424ac91 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -34,7 +34,7 @@ static struct dmi_system_id lifebook_dmi_table[] = {
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
if (psmouse->pktcnt != 3)
return PSMOUSE_GOOD_DATA;
@@ -113,15 +113,17 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
int lifebook_init(struct psmouse *psmouse)
{
+ struct input_dev *input_dev = psmouse->dev;
+
if (lifebook_absolute_mode(psmouse))
return -1;
- psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
+ input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
psmouse->protocol_handler = lifebook_process_byte;
psmouse->set_resolution = lifebook_set_resolution;
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 8b5243167227..9c7ce38806d7 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -77,39 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("logibm_irq=");
-static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int logibm_open(struct input_dev *dev)
-{
- if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
- printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
- return -EBUSY;
- }
- outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
- return 0;
-}
-
-static void logibm_close(struct input_dev *dev)
-{
- outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- free_irq(logibm_irq, NULL);
-}
-
-static struct input_dev logibm_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .open = logibm_open,
- .close = logibm_close,
- .name = "Logitech bus mouse",
- .phys = "isa023c/input0",
- .id = {
- .bustype = BUS_ISA,
- .vendor = 0x0003,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *logibm_dev;
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -127,18 +95,34 @@ static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dy |= (buttons & 0xf) << 4;
buttons = ~buttons >> 5;
- input_regs(&logibm_dev, regs);
- input_report_rel(&logibm_dev, REL_X, dx);
- input_report_rel(&logibm_dev, REL_Y, dy);
- input_report_key(&logibm_dev, BTN_RIGHT, buttons & 1);
- input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 2);
- input_report_key(&logibm_dev, BTN_LEFT, buttons & 4);
- input_sync(&logibm_dev);
+ input_regs(logibm_dev, regs);
+ input_report_rel(logibm_dev, REL_X, dx);
+ input_report_rel(logibm_dev, REL_Y, dy);
+ input_report_key(logibm_dev, BTN_RIGHT, buttons & 1);
+ input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2);
+ input_report_key(logibm_dev, BTN_LEFT, buttons & 4);
+ input_sync(logibm_dev);
outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
return IRQ_HANDLED;
}
+static int logibm_open(struct input_dev *dev)
+{
+ if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
+ printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
+ return -EBUSY;
+ }
+ outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
+ return 0;
+}
+
+static void logibm_close(struct input_dev *dev)
+{
+ outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
+ free_irq(logibm_irq, NULL);
+}
+
static int __init logibm_init(void)
{
if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
@@ -159,16 +143,34 @@ static int __init logibm_init(void)
outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- input_register_device(&logibm_dev);
+ if (!(logibm_dev = input_allocate_device())) {
+ printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
+ release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+ return -ENOMEM;
+ }
+
+ logibm_dev->name = "Logitech bus mouse";
+ logibm_dev->phys = "isa023c/input0";
+ logibm_dev->id.bustype = BUS_ISA;
+ logibm_dev->id.vendor = 0x0003;
+ logibm_dev->id.product = 0x0001;
+ logibm_dev->id.version = 0x0100;
+
+ logibm_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ logibm_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ logibm_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+ logibm_dev->open = logibm_open;
+ logibm_dev->close = logibm_close;
- printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
+ input_register_device(logibm_dev);
return 0;
}
static void __exit logibm_exit(void)
{
- input_unregister_device(&logibm_dev);
+ input_unregister_device(logibm_dev);
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
}
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 48d2b20d2642..0f69ff46c1ae 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -40,7 +40,7 @@ struct ps2pp_info {
static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
if (psmouse->pktcnt < 3)
@@ -150,12 +150,12 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
}
-static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf)
+static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
{
return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
}
-static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char
return count;
}
-PSMOUSE_DEFINE_ATTR(smartscroll);
+PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
+ ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
/*
* Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -194,7 +195,7 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
static void ps2pp_disconnect(struct psmouse *psmouse)
{
- device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+ device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
}
static struct ps2pp_info *get_model_info(unsigned char model)
@@ -222,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
@@ -255,25 +257,27 @@ static struct ps2pp_info *get_model_info(unsigned char model)
static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info,
int using_ps2pp)
{
+ struct input_dev *input_dev = psmouse->dev;
+
if (model_info->features & PS2PP_SIDE_BTN)
- set_bit(BTN_SIDE, psmouse->dev.keybit);
+ set_bit(BTN_SIDE, input_dev->keybit);
if (model_info->features & PS2PP_EXTRA_BTN)
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_EXTRA, input_dev->keybit);
if (model_info->features & PS2PP_TASK_BTN)
- set_bit(BTN_TASK, psmouse->dev.keybit);
+ set_bit(BTN_TASK, input_dev->keybit);
if (model_info->features & PS2PP_NAV_BTN) {
- set_bit(BTN_FORWARD, psmouse->dev.keybit);
- set_bit(BTN_BACK, psmouse->dev.keybit);
+ set_bit(BTN_FORWARD, input_dev->keybit);
+ set_bit(BTN_BACK, input_dev->keybit);
}
if (model_info->features & PS2PP_WHEEL)
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(REL_WHEEL, input_dev->relbit);
if (model_info->features & PS2PP_HWHEEL)
- set_bit(REL_HWHEEL, psmouse->dev.relbit);
+ set_bit(REL_HWHEEL, input_dev->relbit);
switch (model_info->kind) {
case PS2PP_KIND_WHEEL:
@@ -379,12 +383,13 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
- device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+ device_create_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_smartscroll.dattr);
}
}
if (buttons < 3)
- clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
+ clear_bit(BTN_MIDDLE, psmouse->dev->keybit);
if (model_info)
ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
index e90c60cbbf05..b5b34fe4fee8 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -41,13 +41,12 @@ static int dc_mouse_connect(struct maple_device *dev)
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct input_dev *input_dev;
- if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
- return -1;
+ dev->private_data = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
dev->private_data = input_dev;
- memset(input_dev, 0, sizeof(struct dc_mouse));
- init_input_dev(input_dev);
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
@@ -59,8 +58,6 @@ static int dc_mouse_connect(struct maple_device *dev)
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
- printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
-
return 0;
}
@@ -70,7 +67,6 @@ static void dc_mouse_disconnect(struct maple_device *dev)
struct input_dev *input_dev = dev->private_data;
input_unregister_device(input_dev);
- kfree(input_dev);
}
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 93393d5c0078..d284ea712151 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -53,13 +53,10 @@ MODULE_LICENSE("GPL");
static int pc110pad_irq = 10;
static int pc110pad_io = 0x15e0;
-static struct input_dev pc110pad_dev;
+static struct input_dev *pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
-static char *pc110pad_name = "IBM PC110 TouchPad";
-static char *pc110pad_phys = "isa15e0/input0";
-
static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
int value = inb_p(pc110pad_io);
@@ -74,14 +71,14 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
if (pc110pad_count < 3)
return IRQ_HANDLED;
- input_regs(&pc110pad_dev, regs);
- input_report_key(&pc110pad_dev, BTN_TOUCH,
+ input_regs(pc110pad_dev, regs);
+ input_report_key(pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01);
- input_report_abs(&pc110pad_dev, ABS_X,
+ input_report_abs(pc110pad_dev, ABS_X,
pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
- input_report_abs(&pc110pad_dev, ABS_Y,
+ input_report_abs(pc110pad_dev, ABS_Y,
pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
- input_sync(&pc110pad_dev);
+ input_sync(pc110pad_dev);
pc110pad_count = 0;
return IRQ_HANDLED;
@@ -94,9 +91,9 @@ static void pc110pad_close(struct input_dev *dev)
static int pc110pad_open(struct input_dev *dev)
{
- pc110pad_interrupt(0,NULL,NULL);
- pc110pad_interrupt(0,NULL,NULL);
- pc110pad_interrupt(0,NULL,NULL);
+ pc110pad_interrupt(0, NULL, NULL);
+ pc110pad_interrupt(0, NULL, NULL);
+ pc110pad_interrupt(0, NULL, NULL);
outb(PC110PAD_ON, pc110pad_io + 2);
pc110pad_count = 0;
@@ -127,45 +124,46 @@ static int __init pc110pad_init(void)
outb(PC110PAD_OFF, pc110pad_io + 2);
- if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL))
- {
+ if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
release_region(pc110pad_io, 4);
printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
return -EBUSY;
}
- pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ if (!(pc110pad_dev = input_allocate_device())) {
+ free_irq(pc110pad_irq, NULL);
+ release_region(pc110pad_io, 4);
+ printk(KERN_ERR "pc110pad: Not enough memory.\n");
+ return -ENOMEM;
+ }
- pc110pad_dev.absmax[ABS_X] = 0x1ff;
- pc110pad_dev.absmax[ABS_Y] = 0x0ff;
+ pc110pad_dev->name = "IBM PC110 TouchPad";
+ pc110pad_dev->phys = "isa15e0/input0";
+ pc110pad_dev->id.bustype = BUS_ISA;
+ pc110pad_dev->id.vendor = 0x0003;
+ pc110pad_dev->id.product = 0x0001;
+ pc110pad_dev->id.version = 0x0100;
- pc110pad_dev.open = pc110pad_open;
- pc110pad_dev.close = pc110pad_close;
+ pc110pad_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ pc110pad_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ pc110pad_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- pc110pad_dev.name = pc110pad_name;
- pc110pad_dev.phys = pc110pad_phys;
- pc110pad_dev.id.bustype = BUS_ISA;
- pc110pad_dev.id.vendor = 0x0003;
- pc110pad_dev.id.product = 0x0001;
- pc110pad_dev.id.version = 0x0100;
+ pc110pad_dev->absmax[ABS_X] = 0x1ff;
+ pc110pad_dev->absmax[ABS_Y] = 0x0ff;
- input_register_device(&pc110pad_dev);
+ pc110pad_dev->open = pc110pad_open;
+ pc110pad_dev->close = pc110pad_close;
- printk(KERN_INFO "input: %s at %#x irq %d\n",
- pc110pad_name, pc110pad_io, pc110pad_irq);
+ input_register_device(pc110pad_dev);
return 0;
}
static void __exit pc110pad_exit(void)
{
- input_unregister_device(&pc110pad_dev);
-
outb(PC110PAD_OFF, pc110pad_io + 2);
-
free_irq(pc110pad_irq, NULL);
+ input_unregister_device(pc110pad_dev);
release_region(pc110pad_io, 4);
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 2bb2fe78bdca..6ee9999a2eaa 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -25,6 +25,7 @@
#include "logips2pp.h"
#include "alps.h"
#include "lifebook.h"
+#include "trackpoint.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -57,10 +58,30 @@ static unsigned int psmouse_resetafter;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
-PSMOUSE_DEFINE_ATTR(protocol);
-PSMOUSE_DEFINE_ATTR(rate);
-PSMOUSE_DEFINE_ATTR(resolution);
-PSMOUSE_DEFINE_ATTR(resetafter);
+PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
+ NULL,
+ psmouse_attr_show_protocol, psmouse_attr_set_protocol);
+PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, rate),
+ psmouse_show_int_attr, psmouse_attr_set_rate);
+PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resolution),
+ psmouse_show_int_attr, psmouse_attr_set_resolution);
+PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resetafter),
+ psmouse_show_int_attr, psmouse_set_int_attr);
+
+static struct attribute *psmouse_attributes[] = {
+ &psmouse_attr_protocol.dattr.attr,
+ &psmouse_attr_rate.dattr.attr,
+ &psmouse_attr_resolution.dattr.attr,
+ &psmouse_attr_resetafter.dattr.attr,
+ NULL
+};
+
+static struct attribute_group psmouse_attribute_group = {
+ .attrs = psmouse_attributes,
+};
__obsolete_setup("psmouse_noext");
__obsolete_setup("psmouse_resolution=");
@@ -93,7 +114,7 @@ struct psmouse_protocol {
static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
if (psmouse->pktcnt < psmouse->pktsize)
@@ -312,12 +333,11 @@ static int genius_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
- set_bit(BTN_SIDE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
psmouse->vendor = "Genius";
- psmouse->name = "Wheel Mouse";
psmouse->pktsize = 4;
}
@@ -344,8 +364,8 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
+ set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Wheel Mouse";
@@ -377,10 +397,10 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_MIDDLE, psmouse->dev.keybit);
- set_bit(REL_WHEEL, psmouse->dev.relbit);
- set_bit(BTN_SIDE, psmouse->dev.keybit);
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+ set_bit(REL_WHEEL, psmouse->dev->relbit);
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Explorer Mouse";
@@ -412,7 +432,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties)
return -1;
if (set_properties) {
- set_bit(BTN_EXTRA, psmouse->dev.keybit);
+ set_bit(BTN_EXTRA, psmouse->dev->keybit);
psmouse->vendor = "Kensington";
psmouse->name = "ThinkingMouse";
@@ -520,6 +540,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_IMPS;
/*
+ * Try to initialize the IBM TrackPoint
+ */
+ if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TRACKPOINT;
+
+/*
* Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3.
*/
@@ -600,6 +626,12 @@ static struct psmouse_protocol psmouse_protocols[] = {
.init = lifebook_init,
},
{
+ .type = PSMOUSE_TRACKPOINT,
+ .name = "TPPS/2",
+ .alias = "trackpoint",
+ .detect = trackpoint_detect,
+ },
+ {
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
@@ -787,10 +819,7 @@ static void psmouse_disconnect(struct serio *serio)
psmouse = serio_get_drvdata(serio);
- device_remove_file(&serio->dev, &psmouse_attr_protocol);
- device_remove_file(&serio->dev, &psmouse_attr_rate);
- device_remove_file(&serio->dev, &psmouse_attr_resolution);
- device_remove_file(&serio->dev, &psmouse_attr_resetafter);
+ sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
down(&psmouse_sem);
@@ -809,9 +838,9 @@ static void psmouse_disconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(&psmouse->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(psmouse->dev);
kfree(psmouse);
if (parent)
@@ -822,16 +851,14 @@ static void psmouse_disconnect(struct serio *serio)
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
{
- memset(&psmouse->dev, 0, sizeof(struct input_dev));
-
- init_input_dev(&psmouse->dev);
+ struct input_dev *input_dev = psmouse->dev;
- psmouse->dev.private = psmouse;
- psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
+ input_dev->private = psmouse;
+ input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
- psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
@@ -853,12 +880,12 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
- psmouse->dev.name = psmouse->devname;
- psmouse->dev.phys = psmouse->phys;
- psmouse->dev.id.bustype = BUS_I8042;
- psmouse->dev.id.vendor = 0x0002;
- psmouse->dev.id.product = psmouse->type;
- psmouse->dev.id.version = psmouse->model;
+ input_dev->name = psmouse->devname;
+ input_dev->phys = psmouse->phys;
+ input_dev->id.bustype = BUS_I8042;
+ input_dev->id.vendor = 0x0002;
+ input_dev->id.product = psmouse->type;
+ input_dev->id.version = psmouse->model;
return 0;
}
@@ -870,7 +897,8 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct psmouse *psmouse, *parent = NULL;
- int retval;
+ struct input_dev *input_dev;
+ int retval = -ENOMEM;
down(&psmouse_sem);
@@ -883,12 +911,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
- retval = -ENOMEM;
+ psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!psmouse || !input_dev)
goto out;
- }
ps2_init(&psmouse->ps2dev, serio);
+ psmouse->dev = input_dev;
sprintf(psmouse->phys, "%s/input0", serio->phys);
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -896,16 +925,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, psmouse);
retval = serio_open(serio, drv);
- if (retval) {
- serio_set_drvdata(serio, NULL);
- kfree(psmouse);
+ if (retval)
goto out;
- }
if (psmouse_probe(psmouse) < 0) {
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(psmouse);
retval = -ENODEV;
goto out;
}
@@ -917,26 +941,27 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_switch_protocol(psmouse, NULL);
- input_register_device(&psmouse->dev);
- printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
-
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
psmouse_initialize(psmouse);
+ input_register_device(psmouse->dev);
+
if (parent && parent->pt_activate)
parent->pt_activate(parent);
- device_create_file(&serio->dev, &psmouse_attr_protocol);
- device_create_file(&serio->dev, &psmouse_attr_rate);
- device_create_file(&serio->dev, &psmouse_attr_resolution);
- device_create_file(&serio->dev, &psmouse_attr_resetafter);
+ sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
psmouse_activate(psmouse);
retval = 0;
out:
+ if (retval) {
+ serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(psmouse);
+ }
+
/* If this is a pass-through port the parent needs to be re-activated */
if (parent)
psmouse_activate(parent);
@@ -1027,10 +1052,12 @@ static struct serio_driver psmouse_drv = {
.cleanup = psmouse_cleanup,
};
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
- ssize_t (*handler)(struct psmouse *, char *))
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
struct serio *serio = to_serio_port(dev);
+ struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+ struct psmouse *psmouse;
int retval;
retval = serio_pin_driver(serio);
@@ -1042,19 +1069,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
goto out;
}
- retval = handler(serio_get_drvdata(serio), buf);
+ psmouse = serio_get_drvdata(serio);
+
+ retval = attr->show(psmouse, attr->data, buf);
out:
serio_unpin_driver(serio);
return retval;
}
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
- ssize_t (*handler)(struct psmouse *, const char *, size_t))
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
- struct psmouse *psmouse = serio_get_drvdata(serio);
- struct psmouse *parent = NULL;
+ struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+ struct psmouse *psmouse, *parent = NULL;
int retval;
retval = serio_pin_driver(serio);
@@ -1070,6 +1099,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
if (retval)
goto out_unpin;
+ psmouse = serio_get_drvdata(serio);
+
if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV;
goto out_up;
@@ -1082,7 +1113,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
psmouse_deactivate(psmouse);
- retval = handler(psmouse, buf, count);
+ retval = attr->set(psmouse, attr->data, buf, count);
if (retval != -ENODEV)
psmouse_activate(psmouse);
@@ -1097,15 +1128,38 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
return retval;
}
-static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
+static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
+{
+ unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+
+ return sprintf(buf, "%lu\n", *field);
+}
+
+static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
+{
+ unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+ unsigned long value;
+ char *rest;
+
+ value = simple_strtoul(buf, &rest, 10);
+ if (*rest)
+ return -EINVAL;
+
+ *field = value;
+
+ return count;
+}
+
+static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
{
return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
}
-static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
struct serio *serio = psmouse->ps2dev.serio;
struct psmouse *parent = NULL;
+ struct input_dev *new_dev;
struct psmouse_protocol *proto;
int retry = 0;
@@ -1115,9 +1169,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
if (psmouse->type == proto->type)
return count;
+ if (!(new_dev = input_allocate_device()))
+ return -ENOMEM;
+
while (serio->child) {
if (++retry > 3) {
printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
+ input_free_device(new_dev);
return -EIO;
}
@@ -1127,11 +1185,15 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
serio_pin_driver_uninterruptible(serio);
down(&psmouse_sem);
- if (serio->drv != &psmouse_drv)
+ if (serio->drv != &psmouse_drv) {
+ input_free_device(new_dev);
return -ENODEV;
+ }
- if (psmouse->type == proto->type)
+ if (psmouse->type == proto->type) {
+ input_free_device(new_dev);
return count; /* switched by other thread */
+ }
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1144,8 +1206,9 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
psmouse->disconnect(psmouse);
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(&psmouse->dev);
+ input_unregister_device(psmouse->dev);
+ psmouse->dev = new_dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
if (psmouse_switch_protocol(psmouse, proto) < 0) {
@@ -1157,8 +1220,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- input_register_device(&psmouse->dev);
- printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
+ input_register_device(psmouse->dev);
if (parent && parent->pt_activate)
parent->pt_activate(parent);
@@ -1166,12 +1228,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
return count;
}
-static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->rate);
-}
-
-static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -1184,12 +1241,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s
return count;
}
-static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->resolution);
-}
-
-static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
{
unsigned long value;
char *rest;
@@ -1202,23 +1254,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *
return count;
}
-static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%d\n", psmouse->resetafter);
-}
-
-static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
-{
- unsigned long value;
- char *rest;
-
- value = simple_strtoul(buf, &rest, 10);
- if (*rest)
- return -EINVAL;
-
- psmouse->resetafter = value;
- return count;
-}
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
{
@@ -1234,7 +1269,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
*((unsigned int *)kp->arg) = proto->type;
- return 0; \
+ return 0;
}
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 86691cf43433..7c4192bd1279 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -36,7 +36,7 @@ typedef enum {
struct psmouse {
void *private;
- struct input_dev dev;
+ struct input_dev *dev;
struct ps2dev ps2dev;
char *vendor;
char *name;
@@ -78,6 +78,7 @@ enum psmouse_type {
PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS,
PSMOUSE_LIFEBOOK,
+ PSMOUSE_TRACKPOINT,
PSMOUSE_AUTO /* This one should always be last */
};
@@ -85,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
- ssize_t (*handler)(struct psmouse *, char *));
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
- ssize_t (*handler)(struct psmouse *, const char *, size_t));
-
-#define PSMOUSE_DEFINE_ATTR(_name) \
-static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \
-static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
-static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \
-{ \
- return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \
-} \
-static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
-{ \
- return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
-} \
-static struct device_attribute psmouse_attr_##_name = \
- __ATTR(_name, S_IWUSR | S_IRUGO, \
- psmouse_do_show_##_name, psmouse_do_set_##_name);
+
+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);
+};
+#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
+
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
+ char *buf);
+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) \
+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 = { \
+ .dattr = { \
+ .attr = { \
+ .name = __stringify(_name), \
+ .mode = _mode, \
+ .owner = THIS_MODULE, \
+ }, \
+ .show = psmouse_attr_show_helper, \
+ .store = psmouse_attr_set_helper, \
+ }, \
+ .data = _data, \
+ .show = _show, \
+ .set = _set, \
+}
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 8fe1212b8fd7..09b6ffdb7582 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -34,20 +34,7 @@ MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
MODULE_LICENSE("GPL");
static short rpcmouse_lastx, rpcmouse_lasty;
-
-static struct input_dev rpcmouse_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
- .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
- .relbit = { BIT(REL_X) | BIT(REL_Y) },
- .name = "Acorn RiscPC Mouse",
- .phys = "rpcmouse/input0",
- .id = {
- .bustype = BUS_HOST,
- .vendor = 0x0005,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
+static struct input_dev *rpcmouse_dev;
static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -78,29 +65,41 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+
static int __init rpcmouse_init(void)
{
- init_input_dev(&rpcmouse_dev);
+ if (!(rpcmouse_dev = input_allocate_device()))
+ return -ENOMEM;
+
+ rpcmouse_dev->name = "Acorn RiscPC Mouse";
+ rpcmouse_dev->phys = "rpcmouse/input0";
+ rpcmouse_dev->id.bustype = BUS_HOST;
+ rpcmouse_dev->id.vendor = 0x0005;
+ rpcmouse_dev->id.product = 0x0001;
+ rpcmouse_dev->id.version = 0x0100;
+
+ rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ rpcmouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
- if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) {
+ if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", rpcmouse_dev)) {
printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
- return -1;
+ input_free_device(rpcmouse_dev);
+ return -EBUSY;
}
- input_register_device(&rpcmouse_dev);
-
- printk(KERN_INFO "input: Acorn RiscPC mouse\n");
+ input_register_device(rpcmouse_dev);
return 0;
}
static void __exit rpcmouse_exit(void)
{
- input_unregister_device(&rpcmouse_dev);
- free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev);
+ free_irq(IRQ_VSYNCPULSE, rpcmouse_dev);
+ input_unregister_device(rpcmouse_dev);
}
module_init(rpcmouse_init);
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index d12b93ae3900..4bf584364d28 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -48,7 +48,7 @@ static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse"
"Logitech MZ++ Mouse"};
struct sermouse {
- struct input_dev dev;
+ struct input_dev *dev;
signed char buf[8];
unsigned char count;
unsigned char type;
@@ -64,7 +64,7 @@ struct sermouse {
static void sermouse_process_msc(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
{
- struct input_dev *dev = &sermouse->dev;
+ struct input_dev *dev = sermouse->dev;
signed char *buf = sermouse->buf;
input_regs(dev, regs);
@@ -107,7 +107,7 @@ static void sermouse_process_msc(struct sermouse *sermouse, signed char data, st
static void sermouse_process_ms(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
{
- struct input_dev *dev = &sermouse->dev;
+ struct input_dev *dev = sermouse->dev;
signed char *buf = sermouse->buf;
if (data & 0x40) sermouse->count = 0;
@@ -230,9 +230,9 @@ static void sermouse_disconnect(struct serio *serio)
{
struct sermouse *sermouse = serio_get_drvdata(serio);
- input_unregister_device(&sermouse->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_unregister_device(sermouse->dev);
kfree(sermouse);
}
@@ -244,56 +244,52 @@ static void sermouse_disconnect(struct serio *serio)
static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct sermouse *sermouse;
- unsigned char c;
- int err;
+ struct input_dev *input_dev;
+ unsigned char c = serio->id.extra;
+ int err = -ENOMEM;
- if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
- return -ENODEV;
-
- if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(sermouse, 0, sizeof(struct sermouse));
-
- init_input_dev(&sermouse->dev);
- sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
- sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- sermouse->dev.private = sermouse;
-
- sermouse->type = serio->id.proto;
- c = serio->id.extra;
-
- if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
- if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
- if (c & 0x04) set_bit(BTN_EXTRA, sermouse->dev.keybit);
- if (c & 0x10) set_bit(REL_WHEEL, sermouse->dev.relbit);
- if (c & 0x20) set_bit(REL_HWHEEL, sermouse->dev.relbit);
+ sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!sermouse || !input_dev)
+ goto fail;
+ sermouse->dev = input_dev;
sprintf(sermouse->phys, "%s/input0", serio->phys);
+ sermouse->type = serio->id.proto;
- sermouse->dev.name = sermouse_protocols[sermouse->type];
- sermouse->dev.phys = sermouse->phys;
- sermouse->dev.id.bustype = BUS_RS232;
- sermouse->dev.id.vendor = sermouse->type;
- sermouse->dev.id.product = c;
- sermouse->dev.id.version = 0x0100;
- sermouse->dev.dev = &serio->dev;
+ input_dev->name = sermouse_protocols[sermouse->type];
+ input_dev->phys = sermouse->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = sermouse->type;
+ input_dev->id.product = c;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->private = sermouse;
+
+ if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
+ if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
+ if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
+ if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
+ if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
serio_set_drvdata(serio, sermouse);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(sermouse);
- return err;
- }
-
- input_register_device(&sermouse->dev);
+ if (err)
+ goto fail;
- printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
+ input_register_device(sermouse->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(sermouse);
+ return err;
}
static struct serio_device_id sermouse_serio_ids[] = {
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 029309422409..97cdfd6acaca 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -342,7 +342,7 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
*/
static void synaptics_process_packet(struct psmouse *psmouse)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
struct synaptics_data *priv = psmouse->private;
struct synaptics_hw_state hw;
int num_fingers;
@@ -473,7 +473,7 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
- struct input_dev *dev = &psmouse->dev;
+ struct input_dev *dev = psmouse->dev;
struct synaptics_data *priv = psmouse->private;
input_regs(dev, regs);
@@ -645,7 +645,7 @@ int synaptics_init(struct psmouse *psmouse)
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id, priv->capabilities, priv->ext_cap);
- set_input_params(&psmouse->dev, priv);
+ set_input_params(psmouse->dev, priv);
psmouse->protocol_handler = synaptics_process_byte;
psmouse->set_rate = synaptics_set_rate;
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
new file mode 100644
index 000000000000..b4898d8a68e2
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.c
@@ -0,0 +1,304 @@
+/*
+ * Stephen Evanchik <evanchsa@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.
+ *
+ * Trademarks are the property of their respective owners.
+ */
+
+#include <linux/delay.h>
+#include <linux/serio.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/libps2.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "psmouse.h"
+#include "trackpoint.h"
+
+/*
+ * Device IO: read, write and toggle bit
+ */
+static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results)
+{
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val)
+{
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask)
+{
+ /* Bad things will happen if the loc param isn't in this range */
+ if (loc < 0x20 || loc >= 0x2F)
+ return -1;
+
+ if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+ ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Trackpoint-specific attributes
+ */
+struct trackpoint_attr_data {
+ size_t field_offset;
+ unsigned char command;
+ unsigned char mask;
+};
+
+static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ struct trackpoint_attr_data *attr = data;
+ unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+
+ return sprintf(buf, "%u\n", *field);
+}
+
+static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ 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)
+ return -EINVAL;
+
+ *field = value;
+ trackpoint_write(&psmouse->ps2dev, attr->command, value);
+
+ return count;
+}
+
+#define TRACKPOINT_INT_ATTR(_name, _command) \
+ static struct trackpoint_attr_data trackpoint_attr_##_name = { \
+ .field_offset = offsetof(struct trackpoint_data, _name), \
+ .command = _command, \
+ }; \
+ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
+ &trackpoint_attr_##_name, \
+ trackpoint_show_int_attr, trackpoint_set_int_attr)
+
+static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ 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)
+ return -EINVAL;
+
+ if (*field != value) {
+ *field = value;
+ trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
+ }
+
+ return count;
+}
+
+
+#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \
+ static struct trackpoint_attr_data trackpoint_attr_##_name = { \
+ .field_offset = offsetof(struct trackpoint_data, _name), \
+ .command = _command, \
+ .mask = _mask, \
+ }; \
+ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \
+ &trackpoint_attr_##_name, \
+ trackpoint_show_int_attr, trackpoint_set_bit_attr)
+
+TRACKPOINT_INT_ATTR(sensitivity, TP_SENS);
+TRACKPOINT_INT_ATTR(speed, TP_SPEED);
+TRACKPOINT_INT_ATTR(inertia, TP_INERTIA);
+TRACKPOINT_INT_ATTR(reach, TP_REACH);
+TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS);
+TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG);
+TRACKPOINT_INT_ATTR(thresh, TP_THRESH);
+TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
+TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
+TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
+
+TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+static struct attribute *trackpoint_attrs[] = {
+ &psmouse_attr_sensitivity.dattr.attr,
+ &psmouse_attr_speed.dattr.attr,
+ &psmouse_attr_inertia.dattr.attr,
+ &psmouse_attr_reach.dattr.attr,
+ &psmouse_attr_draghys.dattr.attr,
+ &psmouse_attr_mindrag.dattr.attr,
+ &psmouse_attr_thresh.dattr.attr,
+ &psmouse_attr_upthresh.dattr.attr,
+ &psmouse_attr_ztime.dattr.attr,
+ &psmouse_attr_jenks.dattr.attr,
+ &psmouse_attr_press_to_select.dattr.attr,
+ &psmouse_attr_skipback.dattr.attr,
+ &psmouse_attr_ext_dev.dattr.attr,
+ NULL
+};
+
+static struct attribute_group trackpoint_attr_group = {
+ .attrs = trackpoint_attrs,
+};
+
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+ kfree(psmouse->private);
+ psmouse->private = NULL;
+}
+
+static int trackpoint_sync(struct psmouse *psmouse)
+{
+ unsigned char toggle;
+ struct trackpoint_data *tp = psmouse->private;
+
+ if (!tp)
+ return -1;
+
+ /* Disable features that may make device unusable with this driver */
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
+ if (toggle & TP_MASK_TWOHAND)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
+ if (toggle & TP_MASK_SOURCE_TAG)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
+ if (toggle & TP_MASK_MB)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
+
+ /* Push the config to the device */
+ trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity);
+ trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
+ trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
+
+ trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
+ trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
+ trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
+
+ trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
+ trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh);
+
+ trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime);
+ trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
+ if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
+ if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+
+ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
+ if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev)
+ trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+ return 0;
+}
+
+static void trackpoint_defaults(struct trackpoint_data *tp)
+{
+ tp->press_to_select = TP_DEF_PTSON;
+ tp->sensitivity = TP_DEF_SENS;
+ tp->speed = TP_DEF_SPEED;
+ tp->reach = TP_DEF_REACH;
+
+ tp->draghys = TP_DEF_DRAGHYS;
+ tp->mindrag = TP_DEF_MINDRAG;
+
+ tp->thresh = TP_DEF_THRESH;
+ tp->upthresh = TP_DEF_UP_THRESH;
+
+ tp->ztime = TP_DEF_Z_TIME;
+ tp->jenks = TP_DEF_JENKS_CURV;
+
+ tp->inertia = TP_DEF_INERTIA;
+ tp->skipback = TP_DEF_SKIPBACK;
+ tp->ext_dev = TP_DEF_EXT_DEV;
+}
+
+int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+ struct trackpoint_data *priv;
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char firmware_id;
+ unsigned char button_info;
+ unsigned char param[2];
+
+ param[0] = param[1] = 0;
+
+ if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+ return -1;
+
+ if (param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ if (!set_properties)
+ return 0;
+
+ firmware_id = param[1];
+
+ if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
+ printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
+ button_info = 0;
+ }
+
+ psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
+ if (!priv)
+ return -1;
+
+ psmouse->vendor = "IBM";
+ psmouse->name = "TrackPoint";
+
+ psmouse->reconnect = trackpoint_sync;
+ psmouse->disconnect = trackpoint_disconnect;
+
+ trackpoint_defaults(priv);
+ trackpoint_sync(psmouse);
+
+ sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+
+ printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
+ firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
+
+ return 0;
+}
+
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
new file mode 100644
index 000000000000..9857d8b6ad66
--- /dev/null
+++ b/drivers/input/mouse/trackpoint.h
@@ -0,0 +1,147 @@
+/*
+ * IBM TrackPoint PS/2 mouse driver
+ *
+ * Stephen Evanchik <evanchsa@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.
+ */
+
+#ifndef _TRACKPOINT_H
+#define _TRACKPOINT_H
+
+/*
+ * These constants are from the TrackPoint System
+ * Engineering documentation Version 4 from IBM Watson
+ * research:
+ * http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
+
+#define TP_COMMAND 0xE2 /* Commands start with this */
+
+#define TP_READ_ID 0xE1 /* Sent for device identification */
+#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */
+ /* by the firmware ID */
+
+
+/*
+ * Commands
+ */
+#define TP_RECALIB 0x51 /* Recalibrate */
+#define TP_POWER_DOWN 0x44 /* Can only be undone through HW reset */
+#define TP_EXT_DEV 0x21 /* Determines if external device is connected (RO) */
+#define TP_EXT_BTN 0x4B /* Read extended button status */
+#define TP_POR 0x7F /* Execute Power on Reset */
+#define TP_POR_RESULTS 0x25 /* Read Power on Self test results */
+#define TP_DISABLE_EXT 0x40 /* Disable external pointing device */
+#define TP_ENABLE_EXT 0x41 /* Enable external pointing device */
+
+/*
+ * Mode manipulation
+ */
+#define TP_SET_SOFT_TRANS 0x4E /* Set mode */
+#define TP_CANCEL_SOFT_TRANS 0xB9 /* Cancel mode */
+#define TP_SET_HARD_TRANS 0x45 /* Mode can only be set */
+
+
+/*
+ * Register oriented commands/properties
+ */
+#define TP_WRITE_MEM 0x81
+#define TP_READ_MEM 0x80 /* Not used in this implementation */
+
+/*
+* RAM Locations for properties
+ */
+#define TP_SENS 0x4A /* Sensitivity */
+#define TP_MB 0x4C /* Read Middle Button Status (RO) */
+#define TP_INERTIA 0x4D /* Negative Inertia */
+#define TP_SPEED 0x60 /* Speed of TP Cursor */
+#define TP_REACH 0x57 /* Backup for Z-axis press */
+#define TP_DRAGHYS 0x58 /* Drag Hysteresis */
+ /* (how hard it is to drag */
+ /* with Z-axis pressed) */
+
+#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
+ /* to trigger dragging */
+
+#define TP_THRESH 0x5C /* Minimum value for a Z-axis press */
+#define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */
+#define TP_Z_TIME 0x5E /* How sharp of a press */
+#define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */
+
+/*
+ * Toggling Flag bits
+ */
+#define TP_TOGGLE 0x47 /* Toggle command */
+
+#define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */
+#define TP_MASK_MB 0x01
+#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */
+#define TP_MASK_EXT_DEV 0x02
+#define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */
+#define TP_MASK_DRIFT 0x80
+#define TP_TOGGLE_BURST 0x28 /* Burst Mode */
+#define TP_MASK_BURST 0x80
+#define TP_TOGGLE_PTSON 0x2C /* Press to Select */
+#define TP_MASK_PTSON 0x01
+#define TP_TOGGLE_HARD_TRANS 0x2C /* Alternate method to set Hard Transparency */
+#define TP_MASK_HARD_TRANS 0x80
+#define TP_TOGGLE_TWOHAND 0x2D /* Two handed */
+#define TP_MASK_TWOHAND 0x01
+#define TP_TOGGLE_STICKY_TWO 0x2D /* Sticky two handed */
+#define TP_MASK_STICKY_TWO 0x04
+#define TP_TOGGLE_SKIPBACK 0x2D /* Suppress movement after drag release */
+#define TP_MASK_SKIPBACK 0x08
+#define TP_TOGGLE_SOURCE_TAG 0x20 /* Bit 3 of the first packet will be set to
+ to the origin of the packet (external or TP) */
+#define TP_MASK_SOURCE_TAG 0x80
+#define TP_TOGGLE_EXT_TAG 0x22 /* Bit 3 of the first packet coming from the
+ external device will be forced to 1 */
+#define TP_MASK_EXT_TAG 0x04
+
+
+/* Power on Self Test Results */
+#define TP_POR_SUCCESS 0x3B
+
+/*
+ * Default power on values
+ */
+#define TP_DEF_SENS 0x80
+#define TP_DEF_INERTIA 0x06
+#define TP_DEF_SPEED 0x61
+#define TP_DEF_REACH 0x0A
+
+#define TP_DEF_DRAGHYS 0xFF
+#define TP_DEF_MINDRAG 0x14
+
+#define TP_DEF_THRESH 0x08
+#define TP_DEF_UP_THRESH 0xFF
+#define TP_DEF_Z_TIME 0x26
+#define TP_DEF_JENKS_CURV 0x87
+
+/* Toggles */
+#define TP_DEF_MB 0x00
+#define TP_DEF_PTSON 0x00
+#define TP_DEF_SKIPBACK 0x00
+#define TP_DEF_EXT_DEV 0x01
+
+#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
+
+struct trackpoint_data
+{
+ unsigned char sensitivity, speed, inertia, reach;
+ unsigned char draghys, mindrag;
+ unsigned char thresh, upthresh;
+ unsigned char ztime, jenks;
+
+ unsigned char press_to_select;
+ unsigned char skipback;
+
+ unsigned char ext_dev;
+};
+
+extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+
+#endif /* _TRACKPOINT_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index f024be9b44d2..36e9442a16b2 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -112,7 +112,7 @@ MODULE_LICENSE ("GPL");
struct vsxxxaa {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
unsigned char buf[BUFLEN];
@@ -211,7 +211,7 @@ vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t le
static void
vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right;
int dx, dy;
@@ -269,7 +269,7 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
static void
vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right, touch;
int x, y;
@@ -323,7 +323,7 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
static void
vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
{
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
unsigned char *buf = mouse->buf;
int left, middle, right;
unsigned char error;
@@ -483,9 +483,9 @@ vsxxxaa_disconnect (struct serio *serio)
{
struct vsxxxaa *mouse = serio_get_drvdata (serio);
- input_unregister_device (&mouse->dev);
serio_close (serio);
serio_set_drvdata (serio, NULL);
+ input_unregister_device (mouse->dev);
kfree (mouse);
}
@@ -493,61 +493,57 @@ static int
vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
{
struct vsxxxaa *mouse;
- int err;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
- return -ENOMEM;
-
- memset (mouse, 0, sizeof (struct vsxxxaa));
-
- init_input_dev (&mouse->dev);
- set_bit (EV_KEY, mouse->dev.evbit); /* We have buttons */
- set_bit (EV_REL, mouse->dev.evbit);
- set_bit (EV_ABS, mouse->dev.evbit);
- set_bit (BTN_LEFT, mouse->dev.keybit); /* We have 3 buttons */
- set_bit (BTN_MIDDLE, mouse->dev.keybit);
- set_bit (BTN_RIGHT, mouse->dev.keybit);
- set_bit (BTN_TOUCH, mouse->dev.keybit); /* ...and Tablet */
- set_bit (REL_X, mouse->dev.relbit);
- set_bit (REL_Y, mouse->dev.relbit);
- set_bit (ABS_X, mouse->dev.absbit);
- set_bit (ABS_Y, mouse->dev.absbit);
-
- mouse->dev.absmin[ABS_X] = 0;
- mouse->dev.absmax[ABS_X] = 1023;
- mouse->dev.absmin[ABS_Y] = 0;
- mouse->dev.absmax[ABS_Y] = 1023;
-
- mouse->dev.private = mouse;
+ mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
+ input_dev = input_allocate_device ();
+ if (!mouse || !input_dev)
+ goto fail;
+ mouse->dev = input_dev;
+ mouse->serio = serio;
sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
sprintf (mouse->phys, "%s/input0", serio->phys);
- mouse->dev.name = mouse->name;
- mouse->dev.phys = mouse->phys;
- mouse->dev.id.bustype = BUS_RS232;
- mouse->dev.dev = &serio->dev;
- mouse->serio = serio;
+
+ input_dev->name = mouse->name;
+ input_dev->phys = mouse->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = mouse;
+
+ set_bit (EV_KEY, input_dev->evbit); /* We have buttons */
+ set_bit (EV_REL, input_dev->evbit);
+ set_bit (EV_ABS, input_dev->evbit);
+ set_bit (BTN_LEFT, input_dev->keybit); /* We have 3 buttons */
+ set_bit (BTN_MIDDLE, input_dev->keybit);
+ set_bit (BTN_RIGHT, input_dev->keybit);
+ set_bit (BTN_TOUCH, input_dev->keybit); /* ...and Tablet */
+ set_bit (REL_X, input_dev->relbit);
+ set_bit (REL_Y, input_dev->relbit);
+ input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0);
serio_set_drvdata (serio, mouse);
err = serio_open (serio, drv);
- if (err) {
- serio_set_drvdata (serio, NULL);
- kfree (mouse);
- return err;
- }
+ if (err)
+ goto fail;
/*
* Request selftest. Standard packet format and differential
* mode will be requested after the device ID'ed successfully.
*/
- mouse->serio->write (mouse->serio, 'T'); /* Test */
-
- input_register_device (&mouse->dev);
+ serio->write (serio, 'T'); /* Test */
- printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+ input_register_device (input_dev);
return 0;
+
+ fail: serio_set_drvdata (serio, NULL);
+ input_free_device (input_dev);
+ kfree (mouse);
+ return err;
}
static struct serio_device_id vsxxaa_serio_ids[] = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index c6194a9dd174..2d0af44ac4b9 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -9,7 +9,7 @@
* the Free Software Foundation.
*/
-#define MOUSEDEV_MINOR_BASE 32
+#define MOUSEDEV_MINOR_BASE 32
#define MOUSEDEV_MINORS 32
#define MOUSEDEV_MIX 31
@@ -24,7 +24,6 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
#include <linux/miscdevice.h>
#endif
@@ -621,6 +620,7 @@ static struct file_operations mousedev_fops = {
static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
{
struct mousedev *mousedev;
+ struct class_device *cdev;
int minor = 0;
for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
@@ -649,11 +649,13 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
mousedev_table[minor] = mousedev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
- dev->dev, "mouse%d", minor);
+ dev->cdev.dev, mousedev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ mousedev->name);
return &mousedev->handle;
}
@@ -663,9 +665,9 @@ static void mousedev_disconnect(struct input_handle *handle)
struct mousedev *mousedev = handle->private;
struct mousedev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
- devfs_remove("input/mouse%d", mousedev->minor);
mousedev->exist = 0;
if (mousedev->open) {
@@ -738,9 +740,7 @@ static int __init mousedev_init(void)
mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
- class_device_create(input_class,
+ class_device_create(&input_class, NULL,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -759,8 +759,7 @@ static void __exit mousedev_exit(void)
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
- devfs_remove("input/mice");
- class_device_destroy(input_class,
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
}
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index dd0f5bd90241..4da6c86b5d76 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -37,6 +37,7 @@
#include <linux/serio.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 897e4c12b642..a7b0de0f92b2 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -211,9 +211,6 @@ static void gscps2_reset(struct gscps2port *ps2port)
writeb(0xff, addr+GSC_RESET);
gscps2_flush(ps2port);
spin_unlock_irqrestore(&ps2port->lock, flags);
-
- /* enable it */
- gscps2_enable(ps2port, ENABLE);
}
static LIST_HEAD(ps2port_list);
@@ -307,6 +304,9 @@ static int gscps2_open(struct serio *port)
gscps2_reset(ps2port);
+ /* enable it */
+ gscps2_enable(ps2port, ENABLE);
+
gscps2_interrupt(0, NULL, NULL);
return 0;
@@ -331,7 +331,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
{
struct gscps2port *ps2port;
struct serio *serio;
- unsigned long hpa = dev->hpa;
+ unsigned long hpa = dev->hpa.start;
int ret;
if (!dev->irq)
@@ -370,8 +370,6 @@ static int __init gscps2_probe(struct parisc_device *dev)
serio->port_data = ps2port;
serio->dev.parent = &dev->dev;
- list_add_tail(&ps2port->node, &ps2port_list);
-
ret = -EBUSY;
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
goto fail_miserably;
@@ -396,15 +394,16 @@ static int __init gscps2_probe(struct parisc_device *dev)
serio_register_port(ps2port->port);
+ list_add_tail(&ps2port->node, &ps2port_list);
+
return 0;
fail:
free_irq(dev->irq, ps2port);
fail_miserably:
- list_del(&ps2port->node);
iounmap(ps2port->addr);
- release_mem_region(dev->hpa, GSC_STATUS + 4);
+ release_mem_region(dev->hpa.start, GSC_STATUS + 4);
fail_nomem:
kfree(ps2port);
@@ -444,7 +443,7 @@ static struct parisc_device_id gscps2_device_tbl[] = {
};
static struct parisc_driver parisc_ps2_driver = {
- .name = "GSC PS2",
+ .name = "gsc_ps2",
.id_table = gscps2_device_tbl,
.probe = gscps2_probe,
.remove = gscps2_remove,
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index c243cb6fdfc4..5704204964a3 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -801,7 +801,8 @@ static int hil_mlc_serio_open(struct serio *serio) {
struct hil_mlc_serio_map *map;
struct hil_mlc *mlc;
- if (serio->private != NULL) return -EBUSY;
+ if (serio_get_drvdata(serio) != NULL)
+ return -EBUSY;
map = serio->port_data;
if (map == NULL) {
@@ -832,11 +833,18 @@ static void hil_mlc_serio_close(struct serio *serio) {
return;
}
- serio->private = NULL;
+ serio_set_drvdata(serio, NULL);
serio->drv = NULL;
/* TODO wake up interruptable */
}
+static struct serio_device_id hil_mlc_serio_id = {
+ .type = SERIO_HIL_MLC,
+ .proto = SERIO_HIL,
+ .extra = SERIO_ANY,
+ .id = SERIO_ANY,
+};
+
int hil_mlc_register(hil_mlc *mlc) {
int i;
unsigned long flags;
@@ -867,7 +875,7 @@ int hil_mlc_register(hil_mlc *mlc) {
mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
mlc->serio[i] = mlc_serio;
memset(mlc_serio, 0, sizeof(*mlc_serio));
- mlc_serio->type = SERIO_HIL | SERIO_HIL_MLC;
+ mlc_serio->id = hil_mlc_serio_id;
mlc_serio->write = hil_mlc_serio_write;
mlc_serio->open = hil_mlc_serio_open;
mlc_serio->close = hil_mlc_serio_close;
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 7629452dd64b..a10348bb25e9 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -764,7 +764,7 @@ MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
static int __init hp_sdc_init_hppa(struct parisc_device *d);
static struct parisc_driver hp_sdc_driver = {
- .name = "HP SDC",
+ .name = "hp_sdc",
.id_table = hp_sdc_tbl,
.probe = hp_sdc_init_hppa,
};
@@ -875,9 +875,9 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d)
hp_sdc.dev = d;
hp_sdc.irq = d->irq;
hp_sdc.nmi = d->aux_irq;
- hp_sdc.base_io = d->hpa;
- hp_sdc.data_io = d->hpa + 0x800;
- hp_sdc.status_io = d->hpa + 0x801;
+ hp_sdc.base_io = d->hpa.start;
+ hp_sdc.data_io = d->hpa.start + 0x800;
+ hp_sdc.status_io = d->hpa.start + 0x801;
return hp_sdc_init();
}
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index e3c44ffae674..1c9426fd5205 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -40,6 +40,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <asm/semaphore.h>
#define PREFIX "HP SDC MLC: "
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index c9e633d21d90..9a9221644250 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -69,16 +69,16 @@ static inline int i8042_platform_init(void)
*/
#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
- return -1;
+ return -EBUSY;
#endif
i8042_reset = 1;
#if defined(CONFIG_PPC64)
if (check_legacy_ioport(I8042_DATA_REG))
- return -1;
+ return -EBUSY;
if (!request_region(I8042_DATA_REG, 16, "i8042"))
- return -1;
+ return -EBUSY;
#endif
return 0;
}
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index 863b9c95fbb8..ee1ad27d6ed0 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -58,7 +58,7 @@ static inline int i8042_platform_init(void)
#if 0
/* XXX sgi_kh is a virtual address */
if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
- return 1;
+ return -EBUSY;
#endif
i8042_reset = 1;
diff --git a/drivers/input/serio/i8042-jazzio.h b/drivers/input/serio/i8042-jazzio.h
index 5c20ab131488..13fd7108eb28 100644
--- a/drivers/input/serio/i8042-jazzio.h
+++ b/drivers/input/serio/i8042-jazzio.h
@@ -53,7 +53,7 @@ static inline int i8042_platform_init(void)
#if 0
/* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
- return 1;
+ return -EBUSY;
#endif
return 0;
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index da2a19812485..ed9446f6d7e3 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -48,10 +48,10 @@ static inline void i8042_write_command(int val)
#define OBP_PS2MS_NAME1 "kdmouse"
#define OBP_PS2MS_NAME2 "mouse"
-static int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
{
#ifndef CONFIG_PCI
- return -1;
+ return -ENODEV;
#else
char prop[128];
int len;
@@ -59,14 +59,14 @@ static int i8042_platform_init(void)
len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
if (len < 0) {
printk("i8042: Cannot get name property of root OBP node.\n");
- return -1;
+ return -ENODEV;
}
if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
/* Hardcoded values for MrCoffee. */
i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
kbd_iobase = ioremap(0x71300060, 8);
if (!kbd_iobase)
- return -1;
+ return -ENODEV;
} else {
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
@@ -78,7 +78,7 @@ static int i8042_platform_init(void)
goto edev_found;
}
}
- return -1;
+ return -ENODEV;
edev_found:
for_each_edevchild(edev, child) {
@@ -96,7 +96,7 @@ static int i8042_platform_init(void)
i8042_aux_irq == -1) {
printk("i8042: Error, 8042 device lacks both kbd and "
"mouse nodes.\n");
- return -1;
+ return -ENODEV;
}
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 03877c84e6ff..273bb3b08cfa 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -138,6 +138,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ .ident = "Fujitsu-Siemens Lifebook E4010",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
+ },
+ },
+ {
.ident = "Toshiba P10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -256,9 +263,10 @@ static void i8042_pnp_exit(void)
}
}
-static int i8042_pnp_init(void)
+static int __init i8042_pnp_init(void)
{
- int result_kbd, result_aux;
+ int result_kbd = 0, result_aux = 0;
+ char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
if (i8042_nopnp) {
printk(KERN_INFO "i8042: PNP detection disabled\n");
@@ -267,6 +275,7 @@ static int i8042_pnp_init(void)
if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
i8042_pnp_kbd_registered = 1;
+
if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
i8042_pnp_aux_registered = 1;
@@ -280,6 +289,27 @@ static int i8042_pnp_init(void)
#endif
}
+ if (result_kbd > 0)
+ snprintf(kbd_irq_str, sizeof(kbd_irq_str),
+ "%d", i8042_pnp_kbd_irq);
+ if (result_aux > 0)
+ snprintf(aux_irq_str, sizeof(aux_irq_str),
+ "%d", i8042_pnp_aux_irq);
+
+ printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
+ i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
+ i8042_pnp_aux_name,
+ i8042_pnp_data_reg, i8042_pnp_command_reg,
+ kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+ aux_irq_str);
+
+#if defined(__ia64__)
+ if (result_kbd <= 0)
+ i8042_nokbd = 1;
+ if (result_aux <= 0)
+ i8042_noaux = 1;
+#endif
+
if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
@@ -294,53 +324,47 @@ static int i8042_pnp_init(void)
i8042_pnp_command_reg = i8042_command_reg;
}
- if (!i8042_pnp_kbd_irq) {
- printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+ if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq);
i8042_pnp_kbd_irq = i8042_kbd_irq;
}
- if (!i8042_pnp_aux_irq) {
- printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+ if (!i8042_noaux && !i8042_pnp_aux_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq);
i8042_pnp_aux_irq = i8042_aux_irq;
}
-#if defined(__ia64__)
- if (result_aux <= 0)
- i8042_noaux = 1;
-#endif
-
i8042_data_reg = i8042_pnp_data_reg;
i8042_command_reg = i8042_pnp_command_reg;
i8042_kbd_irq = i8042_pnp_kbd_irq;
i8042_aux_irq = i8042_pnp_aux_irq;
- printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
- i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
- i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
- (result_aux > 0) ? "," : "", i8042_aux_irq);
-
return 0;
}
+#else
+static inline int i8042_pnp_init(void) { return 0; }
+static inline void i8042_pnp_exit(void) { }
#endif
-static inline int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
{
+ int retval;
+
/*
* On ix86 platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on ix86 boxes.
*
* if (!request_region(I8042_DATA_REG, 16, "i8042"))
- * return -1;
+ * return -EBUSY;
*/
i8042_kbd_irq = I8042_MAP_IRQ(1);
i8042_aux_irq = I8042_MAP_IRQ(12);
-#ifdef CONFIG_PNP
- if (i8042_pnp_init())
- return -1;
-#endif
+ retval = i8042_pnp_init();
+ if (retval)
+ return retval;
#if defined(__ia64__)
i8042_reset = 1;
@@ -354,14 +378,12 @@ static inline int i8042_platform_init(void)
i8042_nomux = 1;
#endif
- return 0;
+ return retval;
}
static inline void i8042_platform_exit(void)
{
-#ifdef CONFIG_PNP
i8042_pnp_exit();
-#endif
}
#endif /* _I8042_X86IA64IO_H */
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 708a1d3beab9..01e186422021 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -20,6 +20,7 @@
#include <linux/serio.h>
#include <linux/err.h>
#include <linux/rcupdate.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
@@ -27,6 +28,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
MODULE_LICENSE("GPL");
+static unsigned int i8042_nokbd;
+module_param_named(nokbd, i8042_nokbd, bool, 0);
+MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port.");
+
static unsigned int i8042_noaux;
module_param_named(noaux, i8042_noaux, bool, 0);
MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
@@ -338,10 +343,10 @@ static int i8042_open(struct serio *serio)
return 0;
-activate_fail:
+ activate_fail:
free_irq(port->irq, i8042_request_irq_cookie);
-irq_fail:
+ irq_fail:
serio_unregister_port_delayed(serio);
return -1;
@@ -485,7 +490,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
serio_interrupt(port->serio, data, dfl, regs);
ret = 1;
-out:
+ out:
return IRQ_RETVAL(ret);
}
@@ -552,7 +557,7 @@ static int i8042_enable_mux_ports(void)
* Enable all muxed ports.
*/
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
i8042_command(&param, I8042_CMD_MUX_PFX + i);
i8042_command(&param, I8042_CMD_AUX_ENABLE);
}
@@ -682,7 +687,7 @@ static int __init i8042_port_register(struct i8042_port *port)
kfree(port->serio);
port->serio = NULL;
i8042_ctr |= port->disable;
- return -1;
+ return -EIO;
}
printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
@@ -907,12 +912,10 @@ static long i8042_panic_blink(long count)
* Here we try to restore the original BIOS settings
*/
-static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
+static int i8042_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_DISABLE) {
- del_timer_sync(&i8042_timer);
- i8042_controller_reset();
- }
+ del_timer_sync(&i8042_timer);
+ i8042_controller_reset();
return 0;
}
@@ -922,13 +925,10 @@ static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
* Here we try to reset everything back to a state in which suspended
*/
-static int i8042_resume(struct device *dev, u32 level)
+static int i8042_resume(struct device *dev)
{
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
if (i8042_ctl_test())
return -1;
@@ -977,85 +977,88 @@ static struct device_driver i8042_driver = {
.shutdown = i8042_shutdown,
};
-static void __init i8042_create_kbd_port(void)
+static int __init i8042_create_kbd_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
- serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
- strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
-
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+ serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
+ strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
-static void __init i8042_create_aux_port(void)
+static int __init i8042_create_aux_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->write = i8042_aux_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
- strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
-
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = SERIO_8042;
+ serio->write = i8042_aux_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
+ strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
-static void __init i8042_create_mux_port(int index)
+static int __init i8042_create_mux_port(int index)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->write = i8042_aux_write;
- serio->open = i8042_open;
- serio->close = i8042_close;
- serio->start = i8042_start;
- serio->stop = i8042_stop;
- serio->port_data = port;
- serio->dev.parent = &i8042_platform_device->dev;
- snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
- snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
-
- *port = i8042_ports[I8042_AUX_PORT_NO];
- port->exists = 0;
- snprintf(port->name, sizeof(port->name), "AUX%d", index);
- port->mux = index;
- port->serio = serio;
- i8042_port_register(port);
- }
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ serio->id.type = SERIO_8042;
+ serio->write = i8042_aux_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
+ serio->dev.parent = &i8042_platform_device->dev;
+ snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
+ snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
+
+ *port = i8042_ports[I8042_AUX_PORT_NO];
+ port->exists = 0;
+ snprintf(port->name, sizeof(port->name), "AUX%d", index);
+ port->mux = index;
+ port->serio = serio;
+
+ return i8042_port_register(port);
}
static int __init i8042_init(void)
{
- int i;
+ int i, have_ports = 0;
int err;
dbg_init();
@@ -1063,43 +1066,73 @@ static int __init i8042_init(void)
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
- if (i8042_platform_init())
- return -EBUSY;
+ err = i8042_platform_init();
+ if (err)
+ return err;
i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
if (i8042_controller_init()) {
- i8042_platform_exit();
- return -ENODEV;
+ err = -ENODEV;
+ goto err_platform_exit;
}
err = driver_register(&i8042_driver);
- if (err) {
- i8042_platform_exit();
- return err;
- }
+ if (err)
+ goto err_controller_cleanup;
i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
if (IS_ERR(i8042_platform_device)) {
- driver_unregister(&i8042_driver);
- i8042_platform_exit();
- return PTR_ERR(i8042_platform_device);
+ err = PTR_ERR(i8042_platform_device);
+ goto err_unregister_driver;
}
if (!i8042_noaux && !i8042_check_aux()) {
- if (!i8042_nomux && !i8042_check_mux())
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
- i8042_create_mux_port(i);
- else
- i8042_create_aux_port();
+ if (!i8042_nomux && !i8042_check_mux()) {
+ for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
+ err = i8042_create_mux_port(i);
+ if (err)
+ goto err_unregister_ports;
+ }
+ } else {
+ err = i8042_create_aux_port();
+ if (err)
+ goto err_unregister_ports;
+ }
+ have_ports = 1;
+ }
+
+ if (!i8042_nokbd) {
+ err = i8042_create_kbd_port();
+ if (err)
+ goto err_unregister_ports;
+ have_ports = 1;
}
- i8042_create_kbd_port();
+ if (!have_ports) {
+ err = -ENODEV;
+ goto err_unregister_device;
+ }
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return 0;
+
+ err_unregister_ports:
+ for (i = 0; i < I8042_NUM_PORTS; i++)
+ if (i8042_ports[i].serio)
+ serio_unregister_port(i8042_ports[i].serio);
+ err_unregister_device:
+ platform_device_unregister(i8042_platform_device);
+ err_unregister_driver:
+ driver_unregister(&i8042_driver);
+ err_controller_cleanup:
+ i8042_controller_cleanup();
+ err_platform_exit:
+ i8042_platform_exit();
+
+ return err;
}
static void __exit i8042_exit(void)
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 9880fc145d90..d857f7081adb 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -14,7 +14,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/err.h>
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index 46093c507988..b44d255596c2 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -37,6 +37,7 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/bitops.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 106f5eefd89a..52c49258f8a4 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/err.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/hardware.h>
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 79ca38469159..1bd88fca0542 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -87,7 +87,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL);
+ serport = kzalloc(sizeof(struct serport), GFP_KERNEL);
if (!serport)
return -ENOMEM;
@@ -165,7 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
return -EBUSY;
- serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
+ serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0489af5a80c9..21d55ed4b88a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -24,17 +24,17 @@ config TOUCHSCREEN_BITSY
module will be called h3600_ts_input.
config TOUCHSCREEN_CORGI
- tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the driver for the touchscreen on the
- Sharp SL-C7xx series of PDAs.
+ Sharp SL-C7xx and SL-Cxx00 series of PDAs.
If unsure, say N.
To compile this driver as a module, choose M here: the
- module will be called ads7846_ts.
+ module will be called corgi_ts.
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 3f8b61cfbc37..15e88eeae8d6 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -1,5 +1,5 @@
/*
- * Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models
*
* Copyright (c) 2004-2005 Richard Purdie
*
@@ -11,7 +11,7 @@
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
@@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <asm/irq.h>
-#include <asm/arch/corgi.h>
+#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -41,24 +41,25 @@ struct ts_event {
};
struct corgi_ts {
- char phys[32];
- struct input_dev input;
+ struct input_dev *input;
struct timer_list timer;
struct ts_event tc;
int pendown;
int power_mode;
+ int irq_gpio;
+ struct corgits_machinfo *machinfo;
};
-#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
-
-#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#ifdef CONFIG_PXA25x
#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
-#define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-#define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
-
-#define WAIT_HS_400_VGA 7013U // 17.615us
-#define WAIT_HS_400_QVGA 16622U // 41.750us
-
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
+#endif
+#ifdef CONFIG_PXA27x
+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x))
+#endif
/* ADS7846 Touch Screen Controller bit definitions */
#define ADSCTRL_PD0 (1u << 0) /* PD0 */
@@ -69,43 +70,31 @@ struct corgi_ts {
#define ADSCTRL_STS (1u << 7) /* Start Bit */
/* External Functions */
-extern int w100fb_get_xres(void);
-extern int w100fb_get_blanking(void);
-extern int w100fb_get_fastsysclk(void);
extern unsigned int get_clk_frequency_khz(int info);
-static unsigned long calc_waittime(void)
+static unsigned long calc_waittime(struct corgi_ts *corgi_ts)
{
- int w100fb_xres = w100fb_get_xres();
- unsigned int waittime = 0;
-
- if (w100fb_xres == 480 || w100fb_xres == 640) {
- waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
+ unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len();
- if (w100fb_get_fastsysclk() == 100)
- waittime = waittime * 75 / 100;
-
- if (w100fb_xres == 640)
- waittime *= 3;
-
- return waittime;
- }
-
- return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
+ if (hsync_len)
+ return get_clk_frequency_khz(0)*1000/hsync_len;
+ else
+ return 0;
}
-static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend,
+ unsigned int address, unsigned long wait_time)
{
+ unsigned long timer1 = 0, timer2, pmnc = 0;
int pos = 0;
- unsigned long timer1 = 0, timer2;
- int dosleep;
- dosleep = !w100fb_get_blanking();
+ if (wait_time && doSend) {
+ PMNC_GET(pmnc);
+ if (!(pmnc & 0x01))
+ PMNC_SET(0x01);
- if (dosleep && doSend) {
- CCNT_ON();
/* polling HSync */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get CCNT */
CCNT(timer1);
}
@@ -119,12 +108,12 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
corgi_ssp_ads7846_put(cmd);
corgi_ssp_ads7846_get();
- if (dosleep) {
+ if (wait_time) {
/* Wait after HSync */
CCNT(timer2);
if (timer2-timer1 > wait_time) {
- /* timeout */
- SyncHS();
+ /* too slow - timeout, try again */
+ corgi_ts->machinfo->wait_hsync();
/* get OSCR */
CCNT(timer1);
/* Wait after HSync */
@@ -134,8 +123,8 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
CCNT(timer2);
}
corgi_ssp_ads7846_put(cmd);
- if (dosleep)
- CCNT_OFF();
+ if (wait_time && !(pmnc & 0x01))
+ PMNC_SET(pmnc);
}
return pos;
}
@@ -148,23 +137,23 @@ static int read_xydata(struct corgi_ts *corgi_ts)
/* critical section */
local_irq_save(flags);
corgi_ssp_ads7846_lock();
- wait_time=calc_waittime();
+ wait_time = calc_waittime(corgi_ts);
/* Y-axis */
- sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time);
/* Y-axis */
- sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time);
/* X-axis */
- y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+ y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time);
/* Z1 */
- x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+ x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time);
/* Z2 */
- z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
- z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+ z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time);
+ z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time);
/* Power-Down Enable */
corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -192,21 +181,19 @@ static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
return;
- if (regs)
- input_regs(&corgi_ts->input, regs);
-
- input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
- input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
- input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
- input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
- input_sync(&corgi_ts->input);
+ input_regs(corgi_ts->input, regs);
+ input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x);
+ input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y);
+ input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
+ input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
+ input_sync(corgi_ts->input);
}
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
{
- if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+ if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
/* Disable Interrupt */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
if (read_xydata(corgi_ts)) {
corgi_ts->pendown = 1;
new_data(corgi_ts, regs);
@@ -225,7 +212,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->pendown = 0;
}
}
@@ -244,34 +231,32 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
#ifdef CONFIG_PM
-static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+static int corgits_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN) {
- struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
-
- if (corgi_ts->pendown) {
- del_timer_sync(&corgi_ts->timer);
- corgi_ts->tc.pressure = 0;
- new_data(corgi_ts, NULL);
- corgi_ts->pendown = 0;
- }
- corgi_ts->power_mode = PWR_MODE_SUSPEND;
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ if (corgi_ts->pendown) {
+ del_timer_sync(&corgi_ts->timer);
+ corgi_ts->tc.pressure = 0;
+ new_data(corgi_ts, NULL);
+ corgi_ts->pendown = 0;
}
+ corgi_ts->power_mode = PWR_MODE_SUSPEND;
+
+ corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+
return 0;
}
-static int corgits_resume(struct device *dev, uint32_t level)
+static int corgits_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+ corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ /* Enable Falling Edge */
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
- corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
- /* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
- corgi_ts->power_mode = PWR_MODE_ACTIVE;
- }
return 0;
}
#else
@@ -282,34 +267,47 @@ static int corgits_resume(struct device *dev, uint32_t level)
static int __init corgits_probe(struct device *dev)
{
struct corgi_ts *corgi_ts;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
- return -ENOMEM;
+ corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!corgi_ts || !input_dev)
+ goto fail;
dev_set_drvdata(dev, corgi_ts);
- memset(corgi_ts, 0, sizeof(struct corgi_ts));
+ corgi_ts->machinfo = dev->platform_data;
+ corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
- init_input_dev(&corgi_ts->input);
- corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
- input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
- input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+ if (corgi_ts->irq_gpio < 0) {
+ err = -ENODEV;
+ goto fail;
+ }
+
+ corgi_ts->input = input_dev;
+
+ init_timer(&corgi_ts->timer);
+ corgi_ts->timer.data = (unsigned long) corgi_ts;
+ corgi_ts->timer.function = corgi_ts_timer;
- strcpy(corgi_ts->phys, "corgits/input0");
+ input_dev->name = "Corgi Touchscreen";
+ input_dev->phys = "corgits/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = dev;
+ input_dev->private = corgi_ts;
- corgi_ts->input.private = corgi_ts;
- corgi_ts->input.name = "Corgi Touchscreen";
- corgi_ts->input.dev = dev;
- corgi_ts->input.phys = corgi_ts->phys;
- corgi_ts->input.id.bustype = BUS_HOST;
- corgi_ts->input.id.vendor = 0x0001;
- corgi_ts->input.id.product = 0x0002;
- corgi_ts->input.id.version = 0x0100;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
- pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
- pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+ pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
/* Initiaize ADS7846 Difference Reference mode */
corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -321,34 +319,34 @@ static int __init corgits_probe(struct device *dev)
corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
mdelay(5);
- init_timer(&corgi_ts->timer);
- corgi_ts->timer.data = (unsigned long) corgi_ts;
- corgi_ts->timer.function = corgi_ts_timer;
+ if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+ err = -EBUSY;
+ goto fail;
+ }
- input_register_device(&corgi_ts->input);
- corgi_ts->power_mode = PWR_MODE_ACTIVE;
+ input_register_device(corgi_ts->input);
- if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
- input_unregister_device(&corgi_ts->input);
- kfree(corgi_ts);
- return -EBUSY;
- }
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
-
- printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(corgi_ts);
+ return err;
+
}
static int corgits_remove(struct device *dev)
{
struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+ free_irq(corgi_ts->irq_gpio, NULL);
del_timer_sync(&corgi_ts->timer);
- input_unregister_device(&corgi_ts->input);
+ corgi_ts->machinfo->put_hsync();
+ input_unregister_device(corgi_ts->input);
kfree(corgi_ts);
return 0;
}
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 3cdc9cab688d..c86a2eb310fd 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -36,14 +36,12 @@ MODULE_LICENSE("GPL");
#define ELO_MAX_LENGTH 10
-static char *elo_name = "Elo Serial TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct elo {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int id;
int idx;
@@ -54,7 +52,7 @@ struct elo {
static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->csum += elo->data[elo->idx] = data;
@@ -80,7 +78,7 @@ static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_r
input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
- input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
+ input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]);
input_sync(dev);
}
elo->idx = 0;
@@ -91,7 +89,7 @@ static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_r
static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->data[elo->idx] = data;
@@ -129,7 +127,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re
case 5:
if ((data & 0xf0) == 0) {
input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
- input_report_key(dev, BTN_TOUCH, elo->data[5]);
+ input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
}
input_sync(dev);
elo->idx = 0;
@@ -139,7 +137,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re
static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
{
- struct input_dev *dev = &elo->dev;
+ struct input_dev *dev = elo->dev;
elo->data[elo->idx] = data;
@@ -191,7 +189,7 @@ static void elo_disconnect(struct serio *serio)
{
struct elo* elo = serio_get_drvdata(serio);
- input_unregister_device(&elo->dev);
+ input_unregister_device(elo->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(elo);
@@ -206,67 +204,68 @@ static void elo_disconnect(struct serio *serio)
static int elo_connect(struct serio *serio, struct serio_driver *drv)
{
struct elo *elo;
+ struct input_dev *input_dev;
int err;
- if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
- return -ENOMEM;
+ elo = kzalloc(sizeof(struct elo), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!elo || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
- memset(elo, 0, sizeof(struct elo));
+ elo->serio = serio;
+ elo->id = serio->id.id;
+ elo->dev = input_dev;
+ snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
- init_input_dev(&elo->dev);
- elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_dev->private = elo;
+ input_dev->name = "Elo Serial TouchScreen";
+ input_dev->phys = elo->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_ELO;
+ input_dev->id.product = elo->id;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
- elo->id = serio->id.id;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
switch (elo->id) {
case 0: /* 10-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
break;
case 1: /* 6-byte protocol */
- input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
case 2: /* 4-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
break;
case 3: /* 3-byte protocol */
- input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
- input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
break;
}
- elo->serio = serio;
-
- sprintf(elo->phys, "%s/input0", serio->phys);
-
- elo->dev.private = elo;
- elo->dev.name = elo_name;
- elo->dev.phys = elo->phys;
- elo->dev.id.bustype = BUS_RS232;
- elo->dev.id.vendor = SERIO_ELO;
- elo->dev.id.product = elo->id;
- elo->dev.id.version = 0x0100;
-
serio_set_drvdata(serio, elo);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(elo);
- return err;
- }
-
- input_register_device(&elo->dev);
-
- printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(elo->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(elo);
+ return err;
}
/*
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 53a27e43dd23..466da190ceec 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
#define GUNZE_MAX_LENGTH 10
-static char *gunze_name = "Gunze AHL-51S TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct gunze {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int idx;
unsigned char data[GUNZE_MAX_LENGTH];
@@ -64,7 +62,7 @@ struct gunze {
static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
{
- struct input_dev *dev = &gunze->dev;
+ struct input_dev *dev = gunze->dev;
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
@@ -100,11 +98,13 @@ static irqreturn_t gunze_interrupt(struct serio *serio,
static void gunze_disconnect(struct serio *serio)
{
- struct gunze* gunze = serio_get_drvdata(serio);
+ struct gunze *gunze = serio_get_drvdata(serio);
- input_unregister_device(&gunze->dev);
+ input_get_device(gunze->dev);
+ input_unregister_device(gunze->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(gunze->dev);
kfree(gunze);
}
@@ -117,45 +117,45 @@ static void gunze_disconnect(struct serio *serio)
static int gunze_connect(struct serio *serio, struct serio_driver *drv)
{
struct gunze *gunze;
+ struct input_dev *input_dev;
int err;
- if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(gunze, 0, sizeof(struct gunze));
-
- init_input_dev(&gunze->dev);
- gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
- input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
+ gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!gunze || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
gunze->serio = serio;
-
+ gunze->dev = input_dev;
sprintf(gunze->phys, "%s/input0", serio->phys);
- gunze->dev.private = gunze;
- gunze->dev.name = gunze_name;
- gunze->dev.phys = gunze->phys;
- gunze->dev.id.bustype = BUS_RS232;
- gunze->dev.id.vendor = SERIO_GUNZE;
- gunze->dev.id.product = 0x0051;
- gunze->dev.id.version = 0x0100;
+ input_dev->private = gunze;
+ input_dev->name = "Gunze AHL-51S TouchScreen";
+ input_dev->phys = gunze->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_GUNZE;
+ input_dev->id.product = 0x0051;
+ input_dev->id.version = 0x0100;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
serio_set_drvdata(serio, gunze);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(gunze);
- return err;
- }
-
- input_register_device(&gunze->dev);
-
- printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
+ if (err)
+ goto fail;
+ input_register_device(gunze->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(gunze);
+ return err;
}
/*
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index bcfa1e36f957..a18d56bdafd9 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -39,7 +39,6 @@
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/pm.h>
/* SA1100 serial defines */
#include <asm/arch/hardware.h>
@@ -93,16 +92,12 @@ MODULE_LICENSE("GPL");
#define H3600_SCANCODE_LEFT 8 /* 8 -> left */
#define H3600_SCANCODE_DOWN 9 /* 9 -> down */
-static char *h3600_name = "H3600 TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct h3600_dev {
- struct input_dev dev;
- struct pm_dev *pm_dev;
+ struct input_dev *dev;
struct serio *serio;
- struct pm_dev *pm_dev;
unsigned char event; /* event ID from packet */
unsigned char chksum;
unsigned char len;
@@ -163,33 +158,6 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
return 0;
}
-static int suspended = 0;
-static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
- void *data)
-{
- struct input_dev *dev = (struct input_dev *) data;
-
- switch (req) {
- case PM_SUSPEND: /* enter D1-D3 */
- suspended = 1;
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_BLANK:
- if (!suspended)
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_RESUME: /* enter D0 */
- /* same as unblank */
- case PM_UNBLANK:
- if (suspended) {
- //initSerial();
- suspended = 0;
- }
- h3600_flite_power(dev, FLITE_PWR_ON);
- break;
- }
- return 0;
-}
#endif
/*
@@ -199,7 +167,7 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
*/
static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
{
- struct input_dev *dev = &ts->dev;
+ struct input_dev *dev = ts->dev;
static int touched = 0;
int key, down = 0;
@@ -295,6 +263,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
static int h3600ts_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value)
{
+#if 0
struct h3600_dev *ts = dev->private;
switch (type) {
@@ -304,6 +273,8 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type,
}
}
return -1;
+#endif
+ return 0;
}
/*
@@ -380,14 +351,48 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
{
struct h3600_dev *ts;
+ struct input_dev *input_dev;
int err;
- if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
- return -ENOMEM;
+ ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ts || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
- memset(ts, 0, sizeof(struct h3600_dev));
+ ts->serio = serio;
+ ts->dev = input_dev;
+ sprintf(ts->phys, "%s/input0", serio->phys);
- init_input_dev(&ts->dev);
+ input_dev->name = "H3600 TouchScreen";
+ input_dev->phys = ts->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_H3600;
+ input_dev->id.product = 0x0666; /* FIXME !!! We can ask the hardware */
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &serio->dev;
+ input_dev->private = ts;
+
+ input_dev->event = h3600ts_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
+ input_dev->ledbit[0] = BIT(LED_SLEEP);
+ input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0);
+
+ set_bit(KEY_RECORD, input_dev->keybit);
+ set_bit(KEY_Q, input_dev->keybit);
+ set_bit(KEY_PROG1, input_dev->keybit);
+ set_bit(KEY_PROG2, input_dev->keybit);
+ set_bit(KEY_PROG3, input_dev->keybit);
+ set_bit(KEY_UP, input_dev->keybit);
+ set_bit(KEY_RIGHT, input_dev->keybit);
+ set_bit(KEY_LEFT, input_dev->keybit);
+ set_bit(KEY_DOWN, input_dev->keybit);
+ set_bit(KEY_ENTER, input_dev->keybit);
+ set_bit(KEY_SUSPEND, input_dev->keybit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
/* Device specific stuff */
set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
@@ -397,73 +402,35 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto fail2;
}
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_suspend", &ts->dev)) {
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
- kfree(ts);
- return -EBUSY;
+ err = -EBUSY;
+ goto fail3;
}
- /* Now we have things going we setup our input device */
- ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
- ts->dev.ledbit[0] = BIT(LED_SLEEP);
- input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0);
- input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0);
-
- set_bit(KEY_RECORD, ts->dev.keybit);
- set_bit(KEY_Q, ts->dev.keybit);
- set_bit(KEY_PROG1, ts->dev.keybit);
- set_bit(KEY_PROG2, ts->dev.keybit);
- set_bit(KEY_PROG3, ts->dev.keybit);
- set_bit(KEY_UP, ts->dev.keybit);
- set_bit(KEY_RIGHT, ts->dev.keybit);
- set_bit(KEY_LEFT, ts->dev.keybit);
- set_bit(KEY_DOWN, ts->dev.keybit);
- set_bit(KEY_ENTER, ts->dev.keybit);
- ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
-
- ts->serio = serio;
-
- sprintf(ts->phys, "%s/input0", serio->phys);
-
- ts->dev.event = h3600ts_event;
- ts->dev.private = ts;
- ts->dev.name = h3600_name;
- ts->dev.phys = ts->phys;
- ts->dev.id.bustype = BUS_RS232;
- ts->dev.id.vendor = SERIO_H3600;
- ts->dev.id.product = 0x0666; /* FIXME !!! We can ask the hardware */
- ts->dev.id.version = 0x0100;
-
serio_set_drvdata(serio, ts);
err = serio_open(serio, drv);
- if (err) {
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
- free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
- serio_set_drvdata(serio, NULL);
- kfree(ts);
+ if (err)
return err;
- }
//h3600_flite_control(1, 25); /* default brightness */
-#ifdef CONFIG_PM
- ts->pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT,
- h3600ts_pm_callback);
- printk("registered pm callback\n");
-#endif
- input_register_device(&ts->dev);
-
- printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
+ input_register_device(ts->dev);
return 0;
+
+fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
+fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
+fail1: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(ts);
+ return err;
}
/*
@@ -476,9 +443,11 @@ static void h3600ts_disconnect(struct serio *serio)
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
- input_unregister_device(&ts->dev);
+ input_get_device(ts->dev);
+ input_unregister_device(ts->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(ts->dev);
kfree(ts);
}
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 7e1404441eca..957dd5a1b15e 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -21,10 +21,8 @@
static void do_softint(void *data);
-static struct input_dev hp680_ts_dev;
+static struct input_dev *hp680_ts_dev;
static DECLARE_WORK(work, do_softint, 0);
-static char *hp680_ts_name = "HP Jornada touchscreen";
-static char *hp680_ts_phys = "input0";
static void do_softint(void *data)
{
@@ -58,14 +56,14 @@ static void do_softint(void *data)
}
if (touched) {
- input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
- input_report_abs(&hp680_ts_dev, ABS_X, absx);
- input_report_abs(&hp680_ts_dev, ABS_Y, absy);
+ input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
+ input_report_abs(hp680_ts_dev, ABS_X, absx);
+ input_report_abs(hp680_ts_dev, ABS_Y, absy);
} else {
- input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
+ input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
}
- input_sync(&hp680_ts_dev);
+ input_sync(hp680_ts_dev);
enable_irq(HP680_TS_IRQ);
}
@@ -92,27 +90,29 @@ static int __init hp680_ts_init(void)
scpcr |= SCPCR_TS_ENABLE;
ctrl_outw(scpcr, SCPCR);
- memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
- init_input_dev(&hp680_ts_dev);
+ hp680_ts_dev = input_allocate_device();
+ if (!hp680_ts_dev)
+ return -ENOMEM;
- hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
- hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
- hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
- hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
- hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+ hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN;
+ hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
+ hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX;
+ hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
- hp680_ts_dev.name = hp680_ts_name;
- hp680_ts_dev.phys = hp680_ts_phys;
- input_register_device(&hp680_ts_dev);
+ hp680_ts_dev->name = "HP Jornada touchscreen";
+ hp680_ts_dev->phys = "hp680_ts/input0";
- if (request_irq
- (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
- printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
+ input_register_device(hp680_ts_dev);
+
+ if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
+ SA_INTERRUPT, MODNAME, 0) < 0) {
+ printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
HP680_TS_IRQ);
- input_unregister_device(&hp680_ts_dev);
+ input_unregister_device(hp680_ts_dev);
return -EBUSY;
}
@@ -124,7 +124,7 @@ static void __exit hp680_ts_exit(void)
free_irq(HP680_TS_IRQ, 0);
cancel_delayed_work(&work);
flush_scheduled_work();
- input_unregister_device(&hp680_ts_dev);
+ input_unregister_device(hp680_ts_dev);
}
module_init(hp680_ts_init);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index afaaebe5225b..4844d250a5eb 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -77,7 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
#define MK712_READ_ONE_POINT 0x20
#define MK712_POWERUP 0x40
-static struct input_dev mk712_dev;
+static struct input_dev *mk712_dev;
static DEFINE_SPINLOCK(mk712_lock);
static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -88,7 +88,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static unsigned short last_y;
spin_lock(&mk712_lock);
- input_regs(&mk712_dev, regs);
+ input_regs(mk712_dev, regs);
status = inb(mk712_io + MK712_STATUS);
@@ -100,7 +100,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (~status & MK712_STATUS_TOUCH)
{
debounce = 1;
- input_report_key(&mk712_dev, BTN_TOUCH, 0);
+ input_report_key(mk712_dev, BTN_TOUCH, 0);
goto end;
}
@@ -110,15 +110,15 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
goto end;
}
- input_report_key(&mk712_dev, BTN_TOUCH, 1);
- input_report_abs(&mk712_dev, ABS_X, last_x);
- input_report_abs(&mk712_dev, ABS_Y, last_y);
+ input_report_key(mk712_dev, BTN_TOUCH, 1);
+ input_report_abs(mk712_dev, ABS_X, last_x);
+ input_report_abs(mk712_dev, ABS_Y, last_y);
end:
last_x = inw(mk712_io + MK712_X) & 0x0fff;
last_y = inw(mk712_io + MK712_Y) & 0x0fff;
- input_sync(&mk712_dev);
+ input_sync(mk712_dev);
spin_unlock(&mk712_lock);
return IRQ_HANDLED;
}
@@ -154,30 +154,11 @@ static void mk712_close(struct input_dev *dev)
spin_unlock_irqrestore(&mk712_lock, flags);
}
-static struct input_dev mk712_dev = {
- .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
- .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
- .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
- .open = mk712_open,
- .close = mk712_close,
- .name = "ICS MicroClock MK712 TouchScreen",
- .phys = "isa0260/input0",
- .absmin = { [ABS_X] = 0, [ABS_Y] = 0 },
- .absmax = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
- .absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
- .id = {
- .bustype = BUS_ISA,
- .vendor = 0x0005,
- .product = 0x0001,
- .version = 0x0100,
- },
-};
-
int __init mk712_init(void)
{
+ int err;
- if(!request_region(mk712_io, 8, "mk712"))
- {
+ if (!request_region(mk712_io, 8, "mk712")) {
printk(KERN_WARNING "mk712: unable to get IO region\n");
return -ENODEV;
}
@@ -188,28 +169,49 @@ int __init mk712_init(void)
(inw(mk712_io + MK712_Y) & 0xf000) ||
(inw(mk712_io + MK712_STATUS) & 0xf333)) {
printk(KERN_WARNING "mk712: device not present\n");
- release_region(mk712_io, 8);
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}
- if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
- {
- printk(KERN_WARNING "mk712: unable to get IRQ\n");
- release_region(mk712_io, 8);
- return -EBUSY;
+ if (!(mk712_dev = input_allocate_device())) {
+ printk(KERN_ERR "mk712: not enough memory\n");
+ err = -ENOMEM;
+ goto fail;
}
- input_register_device(&mk712_dev);
+ mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
+ mk712_dev->phys = "isa0260/input0";
+ mk712_dev->id.bustype = BUS_ISA;
+ mk712_dev->id.vendor = 0x0005;
+ mk712_dev->id.product = 0x0001;
+ mk712_dev->id.version = 0x0100;
+
+ mk712_dev->open = mk712_open;
+ mk712_dev->close = mk712_close;
- printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
+ mk712_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ mk712_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
+ input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
+ if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
+ printk(KERN_WARNING "mk712: unable to get IRQ\n");
+ err = -EBUSY;
+ goto fail;
+ }
+
+ input_register_device(mk712_dev);
return 0;
+
+ fail: input_free_device(mk712_dev);
+ release_region(mk712_io, 8);
+ return err;
}
static void __exit mk712_exit(void)
{
- input_unregister_device(&mk712_dev);
- free_irq(mk712_irq, &mk712_dev);
+ input_unregister_device(mk712_dev);
+ free_irq(mk712_irq, mk712_dev);
release_region(mk712_io, 8);
}
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index aa8ee7842179..1d0d37eeef6e 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -51,14 +51,12 @@ MODULE_LICENSE("GPL");
#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
-static char *mtouch_name = "MicroTouch Serial TouchScreen";
-
/*
* Per-touchscreen data.
*/
struct mtouch {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
int idx;
unsigned char data[MTOUCH_MAX_LENGTH];
@@ -67,7 +65,7 @@ struct mtouch {
static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
{
- struct input_dev *dev = &mtouch->dev;
+ struct input_dev *dev = mtouch->dev;
if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
input_regs(dev, regs);
@@ -116,9 +114,11 @@ static void mtouch_disconnect(struct serio *serio)
{
struct mtouch* mtouch = serio_get_drvdata(serio);
- input_unregister_device(&mtouch->dev);
+ input_get_device(mtouch->dev);
+ input_unregister_device(mtouch->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(mtouch->dev);
kfree(mtouch);
}
@@ -131,46 +131,46 @@ static void mtouch_disconnect(struct serio *serio)
static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
{
struct mtouch *mtouch;
+ struct input_dev *input_dev;
int err;
- if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(mtouch, 0, sizeof(*mtouch));
-
- init_input_dev(&mtouch->dev);
- mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
- input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
+ mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mtouch || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
+ }
mtouch->serio = serio;
-
+ mtouch->dev = input_dev;
sprintf(mtouch->phys, "%s/input0", serio->phys);
- mtouch->dev.private = mtouch;
- mtouch->dev.name = mtouch_name;
- mtouch->dev.phys = mtouch->phys;
- mtouch->dev.id.bustype = BUS_RS232;
- mtouch->dev.id.vendor = SERIO_MICROTOUCH;
- mtouch->dev.id.product = 0;
- mtouch->dev.id.version = 0x0100;
+ input_dev->private = mtouch;
+ input_dev->name = "MicroTouch Serial TouchScreen";
+ input_dev->phys = mtouch->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_MICROTOUCH;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0100;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
+ input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
serio_set_drvdata(serio, mtouch);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(mtouch);
- return err;
- }
-
- input_register_device(&mtouch->dev);
+ if (err)
+ goto fail;
- printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
+ input_register_device(mtouch->dev);
return 0;
+
+ fail: serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(mtouch);
+ return err;
}
/*
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 50c63a155156..ca1547929d62 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -53,7 +53,6 @@
#include <linux/random.h>
#include <linux/time.h>
#include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
#ifndef CONFIG_INPUT_TSDEV_SCREEN_X
#define CONFIG_INPUT_TSDEV_SCREEN_X 240
@@ -369,6 +368,7 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
struct input_device_id *id)
{
struct tsdev *tsdev;
+ struct class_device *cdev;
int minor, delta;
for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
@@ -410,13 +410,13 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
tsdev_table[minor] = tsdev;
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
- devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
- S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
- class_device_create(input_class,
+ cdev = class_device_create(&input_class, &dev->cdev,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
- dev->dev, "ts%d", minor);
+ dev->cdev.dev, tsdev->name);
+
+ /* temporary symlink to keep userspace happy */
+ sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+ tsdev->name);
return &tsdev->handle;
}
@@ -426,10 +426,9 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev *tsdev = handle->private;
struct tsdev_list *list;
- class_device_destroy(input_class,
+ sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+ class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
- devfs_remove("input/ts%d", tsdev->minor);
- devfs_remove("input/tsraw%d", tsdev->minor);
tsdev->exist = 0;
if (tsdev->open) {
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index afa46681f983..6ae6eb322111 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -606,7 +606,7 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
(m->msg.data_b3_req.blocknr == blocknr)) {
/* found corresponding DATA_B3_REQ */
- skb_unlink(tmp);
+ skb_unlink(tmp, &card->ackq);
chan->queued -= m->msg.data_b3_req.datalen;
if (m->msg.data_b3_req.flags)
ret = m->msg.data_b3_req.datalen;
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 04fb606b5ddd..11ae0fddea04 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1505,7 +1505,7 @@ static int __init capi_init(void)
return PTR_ERR(capi_class);
}
- class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+ class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
"isdn/capi20");
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index f8570fd9d2ab..7b564c0dd996 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ctype.h>
+#include <linux/sched.h> /* current */
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
MODULE_AUTHOR("Carsten Paeth");
@@ -191,8 +192,10 @@ static int __init capifs_init(void)
err = register_filesystem(&capifs_fs_type);
if (!err) {
capifs_mnt = kern_mount(&capifs_fs_type);
- if (IS_ERR(capifs_mnt))
+ if (IS_ERR(capifs_mnt)) {
err = PTR_ERR(capifs_mnt);
+ unregister_filesystem(&capifs_fs_type);
+ }
}
if (!err)
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index e1f0d87de0eb..0b0ea26023e5 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -287,12 +287,12 @@ divert_dev_init(void)
init_waitqueue_head(&rd_queue);
#ifdef CONFIG_PROC_FS
- isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+ isdn_proc_entry = proc_mkdir("net/isdn", NULL);
if (!isdn_proc_entry)
return (-1);
isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
if (!isdn_divert_entry) {
- remove_proc_entry("isdn", proc_net);
+ remove_proc_entry("net/isdn", NULL);
return (-1);
}
isdn_divert_entry->proc_fops = &isdn_fops;
@@ -312,7 +312,7 @@ divert_dev_deinit(void)
#ifdef CONFIG_PROC_FS
remove_proc_entry("divert", isdn_proc_entry);
- remove_proc_entry("isdn", proc_net);
+ remove_proc_entry("net/isdn", NULL);
#endif /* CONFIG_PROC_FS */
return (0);
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index 7fdf8ae5be52..27204f4b111a 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -30,8 +30,6 @@ static char *DRIVERNAME =
static char *DRIVERLNAME = "divadidd";
char *DRIVERRELEASE_DIDD = "2.0";
-static char *main_proc_dir = "eicon";
-
MODULE_DESCRIPTION("DIDD table driver for diva drivers");
MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
@@ -89,7 +87,7 @@ proc_read(char *page, char **start, off_t off, int count, int *eof,
static int DIVA_INIT_FUNCTION create_proc(void)
{
- proc_net_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net);
+ proc_net_eicon = proc_mkdir("net/eicon", NULL);
if (proc_net_eicon) {
if ((proc_didd =
@@ -105,7 +103,7 @@ static int DIVA_INIT_FUNCTION create_proc(void)
static void DIVA_EXIT_FUNCTION remove_proc(void)
{
remove_proc_entry(DRIVERLNAME, proc_net_eicon);
- remove_proc_entry(main_proc_dir, proc_net);
+ remove_proc_entry("net/eicon", NULL);
}
static int DIVA_INIT_FUNCTION divadidd_init(void)
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
index b6435589d459..c12efa6f8429 100644
--- a/drivers/isdn/hardware/eicon/divasproc.c
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -381,7 +381,7 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a)
char tmp[16];
sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
- if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_eicon)))
+ if (!(de = proc_mkdir(tmp, proc_net_eicon)))
return (0);
a->proc_adapter_dir = (void *) de;
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 6c7b8bffc6fd..801c98f30e5c 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -134,6 +134,7 @@ config HISAX_AVM_A1
config HISAX_FRITZPCI
bool "AVM PnP/PCI (Fritz!PnP/PCI)"
+ depends on BROKEN || !PPC64
help
This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
See <file:Documentation/isdn/README.HiSax> on how to configure it.
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 7333377ab31d..e3866b0a97fd 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1063,7 +1063,7 @@ tx_b_frame(struct hfc4s8s_btype *bch)
Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
}
ack_len += skb->truesize;
- bch->tx_skb = 0;
+ bch->tx_skb = NULL;
bch->tx_cnt = 0;
dev_kfree_skb(skb);
} else
@@ -1659,10 +1659,10 @@ hfc4s8s_remove(struct pci_dev *pdev)
}
static struct pci_driver hfc4s8s_driver = {
- name:"hfc4s8s_l1",
- probe:hfc4s8s_probe,
- remove:__devexit_p(hfc4s8s_remove),
- id_table:hfc4s8s_ids,
+ .name = "hfc4s8s_l1",
+ .probe = hfc4s8s_probe,
+ .remove = __devexit_p(hfc4s8s_remove),
+ .id_table = hfc4s8s_ids,
};
/**********************/
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8337b0f26cc4..4866fc32d8d9 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] =
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
+ {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"},
{0, 0, NULL, NULL},
};
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 17cf7663c582..26c545fa223b 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -10,7 +10,6 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -1242,6 +1241,8 @@ struct IsdnCardState {
#ifdef CONFIG_HISAX_ENTERNOW_PCI
#define CARD_FN_ENTERNOW_PCI 1
+#else
+#define CARD_FN_ENTERNOW_PCI 0
#endif
#define TEI_PER_CARD 1
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index c6b5bf7d2aca..dc334aab433e 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -611,7 +611,7 @@ static int sedlbauer_event(event_t event, int priority,
} /* sedlbauer_event */
static struct pcmcia_device_id sedlbauer_ids[] = {
- PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c),
+ PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index 0fda5c89429b..9ffaae7c657a 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter);
#define __debug_variable st5481_debug
#include "hisax_debug.h"
-#ifdef CONFIG_HISAX_DEBUG
-
extern int st5481_debug;
+#ifdef CONFIG_HISAX_DEBUG
+
#define DBG_ISO_PACKET(level,urb) \
if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 2fcd093921d8..657817a591fe 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs)
test_and_clear_bit(buf_nr, &b_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (b_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
- }
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(4,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ if (b_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
+ }
+ break;
}
}
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 071b1d31999f..941f7022ada1 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs)
test_and_clear_bit(buf_nr, &d_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (d_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
- }
- return;
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ break;
+ default:
+ WARN("urb status %d",urb->status);
+ if (d_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
+ }
+ break;
}
+ return; // Give up
}
FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
@@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter)
adapter->l1m.fsm = &l1fsm;
adapter->l1m.state = ST_L1_F3;
- adapter->l1m.debug = 1;
+ adapter->l1m.debug = st5481_debug & 0x100;
adapter->l1m.userdata = adapter;
adapter->l1m.printdebug = l1m_debug;
FsmInitTimer(&adapter->l1m, &adapter->timer);
adapter->d_out.fsm.fsm = &dout_fsm;
adapter->d_out.fsm.state = ST_DOUT_NONE;
- adapter->d_out.fsm.debug = 1;
+ adapter->d_out.fsm.debug = st5481_debug & 0x100;
adapter->d_out.fsm.userdata = adapter;
adapter->d_out.fsm.printdebug = dout_debug;
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 7aa810d5d333..2cf5d1a6df6c 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */
module_param(number_of_leds, int, 0);
#ifdef CONFIG_HISAX_DEBUG
-static int debug = 0x1;
+static int debug = 0;
module_param(debug, int, 0);
-int st5481_debug;
#endif
+int st5481_debug;
static LIST_HEAD(adapter_list);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ab62223297a5..89fbeb58485d 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs)
struct ctrl_msg *ctrl_msg;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
@@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs)
int status;
switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- DBG(1, "urb shutting down with status: %d", urb->status);
- return;
- default:
- WARN("nonzero urb status received: %d", urb->status);
- goto exit;
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ DBG(2, "urb shutting down with status: %d", urb->status);
+ return;
+ default:
+ WARN("nonzero urb status received: %d", urb->status);
+ goto exit;
}
- DBG_PACKET(1, data, INT_PKT_SIZE);
+ DBG_PACKET(2, data, INT_PKT_SIZE);
if (urb->actual_length == 0) {
goto exit;
@@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
struct urb *urb;
u8 *buf;
- DBG(1,"");
+ DBG(2,"");
if ((status = usb_reset_configuration (dev)) < 0) {
WARN("reset_configuration failed,status=%d",status);
@@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter)
DBG(1,"");
// Stop and free Control and Interrupt URBs
- usb_unlink_urb(ctrl->urb);
+ usb_kill_urb(ctrl->urb);
if (ctrl->urb->transfer_buffer)
kfree(ctrl->urb->transfer_buffer);
usb_free_urb(ctrl->urb);
+ ctrl->urb = NULL;
- usb_unlink_urb(intr->urb);
+ usb_kill_urb(intr->urb);
if (intr->urb->transfer_buffer)
kfree(intr->urb->transfer_buffer);
usb_free_urb(intr->urb);
+ ctrl->urb = NULL;
}
/*
@@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev,
spin_lock_init(&urb->lock);
urb->dev=dev;
urb->pipe=pipe;
+ urb->interval = 1;
urb->transfer_buffer=buf;
urb->number_of_packets = num_packets;
urb->transfer_buffer_length=num_packets*packet_size;
@@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
if (urb[j]) {
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
+ urb[j]->transfer_buffer = NULL;
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
return retval;
@@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2])
int j;
for (j = 0; j < 2; j++) {
- usb_unlink_urb(urb[j]);
+ usb_kill_urb(urb[j]);
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
@@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
int len, count, status;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 5da507e532fc..639582f61f41 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -394,7 +394,7 @@ hysdn_procconf_init(void)
hysdn_card *card;
uchar conf_name[20];
- hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+ hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
if (!hysdn_proc_entry) {
printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
return (-1);
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index baf4bcad9bf9..0afe442db3b0 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -283,23 +283,19 @@ static void bsd_free (void *state)
/*
* Release the dictionary
*/
- if (db->dict) {
- vfree (db->dict);
- db->dict = NULL;
- }
+ vfree(db->dict);
+ db->dict = NULL;
/*
* Release the string buffer
*/
- if (db->lens) {
- vfree (db->lens);
- db->lens = NULL;
- }
+ vfree(db->lens);
+ db->lens = NULL;
/*
* Finally release the structure itself.
*/
- kfree (db);
+ kfree(db);
}
}
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index eebcb0b97f0e..8a7d54a5c97d 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1953,7 +1953,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
kfree(d->rcvcount);
if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
- if (!adding) kfree(d->rcverr);
+ if (!adding)
+ kfree(d->rcverr);
return -1;
}
memset((char *) d->rcvcount, 0, sizeof(int) * m);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index f30e8e63ae0d..96c115e13389 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1786,7 +1786,6 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
lp->stats.rx_bytes += skb->len;
}
skb->dev = ndev;
- skb->input_dev = ndev;
skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data;
#ifdef ISDN_DEBUG_NET_DUMP
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 260a323a96d3..d97a9be5469c 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1177,7 +1177,6 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
mlp->huptimer = 0;
#endif /* CONFIG_IPPP_FILTER */
skb->dev = dev;
- skb->input_dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
index f47f2b9846d8..38619e8cd823 100644
--- a/drivers/isdn/i4l/isdn_v110.c
+++ b/drivers/isdn/i4l/isdn_v110.c
@@ -516,11 +516,11 @@ buffer_full:
}
int
-isdn_v110_stat_callback(int idx, isdn_ctrl * c)
+isdn_v110_stat_callback(int idx, isdn_ctrl *c)
{
isdn_v110_stream *v = NULL;
int i;
- int ret;
+ int ret = 0;
if (idx < 0)
return 0;
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index e0d1b01cc74c..386df71eee74 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1650,7 +1650,7 @@ static void __exit icn_exit(void)
{
isdn_ctrl cmd;
icn_card *card = cards;
- icn_card *last;
+ icn_card *last, *tmpcard;
int i;
unsigned long flags;
@@ -1670,8 +1670,9 @@ static void __exit icn_exit(void)
for (i = 0; i < ICN_BCH; i++)
icn_free_queue(card, i);
}
- card = card->next;
+ tmpcard = card->next;
spin_unlock_irqrestore(&card->lock, flags);
+ card = tmpcard;
}
card = cards;
cards = NULL;
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 40b0df04ed9f..1ebed041672d 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -87,7 +87,7 @@ static int __init sc_init(void)
*/
for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
if(!request_region(io[b] + i * 0x400, 1, "sc test")) {
- pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400);
+ pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
io[b] = 0;
break;
} else
@@ -181,7 +181,7 @@ static int __init sc_init(void)
for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) {
pr_debug("Checking RAM address 0x%x...\n", i);
if(request_region(i, SRAM_PAGESIZE, "sc test")) {
- pr_debug(" check_region succeeded\n");
+ pr_debug(" request_region succeeded\n");
model = identify_board(i, io[b]);
release_region(i, SRAM_PAGESIZE);
if (model >= 0) {
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 65ab64c43b3e..bc3e096d84f7 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -103,7 +103,7 @@ config PMAC_MEDIABAY
# on non-powerbook machines (but only on PMU based ones AFAIK)
config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
- depends on ADB_PMU
+ depends on ADB_PMU && (BROKEN || !PPC64)
help
Say Y here to build in code to manage the LCD backlight on a
Macintosh PowerBook. With this code, the backlight will be turned
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index c0dc1e3fa58b..d2ead1776c16 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -905,5 +905,5 @@ adbdev_init(void)
adb_dev_class = class_create(THIS_MODULE, "adb");
if (IS_ERR(adb_dev_class))
return;
- class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+ class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
}
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index db654e8bd67e..8f02c155fdc0 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -206,7 +206,7 @@ u8 adb_to_linux_keycodes[128] = {
};
struct adbhid {
- struct input_dev input;
+ struct input_dev *input;
int id;
int default_id;
int original_handler_id;
@@ -291,10 +291,10 @@ adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
switch (keycode) {
case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
- input_regs(&ahid->input, regs);
- input_report_key(&ahid->input, KEY_CAPSLOCK, 1);
- input_report_key(&ahid->input, KEY_CAPSLOCK, 0);
- input_sync(&ahid->input);
+ input_regs(ahid->input, regs);
+ input_report_key(ahid->input, KEY_CAPSLOCK, 1);
+ input_report_key(ahid->input, KEY_CAPSLOCK, 0);
+ input_sync(ahid->input);
return;
#ifdef CONFIG_PPC_PMAC
case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
@@ -347,10 +347,10 @@ adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
}
if (adbhid[id]->keycode[keycode]) {
- input_regs(&adbhid[id]->input, regs);
- input_report_key(&adbhid[id]->input,
+ input_regs(adbhid[id]->input, regs);
+ input_report_key(adbhid[id]->input,
adbhid[id]->keycode[keycode], !up_flag);
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
} else
printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
up_flag ? "released" : "pressed");
@@ -441,20 +441,20 @@ adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopo
break;
}
- input_regs(&adbhid[id]->input, regs);
+ input_regs(adbhid[id]->input, regs);
- input_report_key(&adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1));
- input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
- input_report_key(&adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1));
+ input_report_key(adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1));
- input_report_rel(&adbhid[id]->input, REL_X,
+ input_report_rel(adbhid[id]->input, REL_X,
((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ));
- input_report_rel(&adbhid[id]->input, REL_Y,
+ input_report_rel(adbhid[id]->input, REL_Y,
((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 ));
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
}
static void
@@ -467,7 +467,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
return;
}
- input_regs(&adbhid[id]->input, regs);
+ input_regs(adbhid[id]->input, regs);
switch (adbhid[id]->original_handler_id) {
default:
@@ -477,19 +477,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
switch (data[1] & 0x0f) {
case 0x0: /* microphone */
- input_report_key(&adbhid[id]->input, KEY_SOUND, down);
+ input_report_key(adbhid[id]->input, KEY_SOUND, down);
break;
case 0x1: /* mute */
- input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+ input_report_key(adbhid[id]->input, KEY_MUTE, down);
break;
case 0x2: /* volume decrease */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
break;
case 0x3: /* volume increase */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
break;
default:
@@ -513,19 +513,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
switch (data[1] & 0x0f) {
case 0x8: /* mute */
- input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+ input_report_key(adbhid[id]->input, KEY_MUTE, down);
break;
case 0x7: /* volume decrease */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
break;
case 0x6: /* volume increase */
- input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+ input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
break;
case 0xb: /* eject */
- input_report_key(&adbhid[id]->input, KEY_EJECTCD, down);
+ input_report_key(adbhid[id]->input, KEY_EJECTCD, down);
break;
case 0xa: /* brightness decrease */
@@ -539,7 +539,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
}
}
#endif /* CONFIG_PMAC_BACKLIGHT */
- input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
break;
case 0x9: /* brightness increase */
@@ -553,19 +553,19 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
}
}
#endif /* CONFIG_PMAC_BACKLIGHT */
- input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);
+ input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
break;
case 0xc: /* videomode switch */
- input_report_key(&adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
+ input_report_key(adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
break;
case 0xd: /* keyboard illumination toggle */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
break;
case 0xe: /* keyboard illumination decrease */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMDOWN, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMDOWN, down);
break;
case 0xf:
@@ -573,7 +573,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0x8f:
case 0x0f:
/* keyboard illumination increase */
- input_report_key(&adbhid[id]->input, KEY_KBDILLUMUP, down);
+ input_report_key(adbhid[id]->input, KEY_KBDILLUMUP, down);
break;
case 0x7f:
@@ -596,7 +596,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
break;
}
- input_sync(&adbhid[id]->input);
+ input_sync(adbhid[id]->input);
}
static struct adb_request led_request;
@@ -683,7 +683,7 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
int i;
for (i = 1; i < 16; i++) {
if (adbhid[i])
- del_timer_sync(&adbhid[i]->input.timer);
+ del_timer_sync(&adbhid[i]->input->timer);
}
}
@@ -699,153 +699,164 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
return NOTIFY_DONE;
}
-static void
+static int
adbhid_input_register(int id, int default_id, int original_handler_id,
int current_handler_id, int mouse_kind)
{
+ struct adbhid *hid;
+ struct input_dev *input_dev;
+ int err;
int i;
if (adbhid[id]) {
printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);
- return;
+ return -EEXIST;
}
- if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL)))
- return;
-
- memset(adbhid[id], 0, sizeof(struct adbhid));
- sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
+ adbhid[id] = hid = kzalloc(sizeof(struct adbhid), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!hid || !input_dev) {
+ err = -ENOMEM;
+ goto fail;
- init_input_dev(&adbhid[id]->input);
+ }
- adbhid[id]->id = default_id;
- adbhid[id]->original_handler_id = original_handler_id;
- adbhid[id]->current_handler_id = current_handler_id;
- adbhid[id]->mouse_kind = mouse_kind;
- adbhid[id]->flags = 0;
- adbhid[id]->input.private = adbhid[id];
- adbhid[id]->input.name = adbhid[id]->name;
- adbhid[id]->input.phys = adbhid[id]->phys;
- adbhid[id]->input.id.bustype = BUS_ADB;
- adbhid[id]->input.id.vendor = 0x0001;
- adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id;
- adbhid[id]->input.id.version = 0x0100;
+ sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
+
+ hid->input = input_dev;
+ hid->id = default_id;
+ hid->original_handler_id = original_handler_id;
+ hid->current_handler_id = current_handler_id;
+ hid->mouse_kind = mouse_kind;
+ hid->flags = 0;
+ input_dev->private = hid;
+ input_dev->name = hid->name;
+ input_dev->phys = hid->phys;
+ input_dev->id.bustype = BUS_ADB;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = (id << 12) | (default_id << 8) | original_handler_id;
+ input_dev->id.version = 0x0100;
switch (default_id) {
case ADB_KEYBOARD:
- if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {
- kfree(adbhid[id]);
- return;
+ hid->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL);
+ if (!hid->keycode) {
+ err = -ENOMEM;
+ goto fail;
}
- sprintf(adbhid[id]->name, "ADB keyboard");
+ sprintf(hid->name, "ADB keyboard");
- memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
+ memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
printk(KERN_INFO "Detected ADB keyboard, type ");
switch (original_handler_id) {
default:
printk("<unknown>.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN;
+ input_dev->id.version = ADB_KEYBOARD_UNKNOWN;
break;
case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
case 0xC0: case 0xC3: case 0xC6:
printk("ANSI.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI;
+ input_dev->id.version = ADB_KEYBOARD_ANSI;
break;
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
case 0xC4: case 0xC7:
printk("ISO, swapping keys.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_ISO;
- i = adbhid[id]->keycode[10];
- adbhid[id]->keycode[10] = adbhid[id]->keycode[50];
- adbhid[id]->keycode[50] = i;
+ input_dev->id.version = ADB_KEYBOARD_ISO;
+ i = hid->keycode[10];
+ hid->keycode[10] = hid->keycode[50];
+ hid->keycode[50] = i;
break;
case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
printk("JIS.\n");
- adbhid[id]->input.id.version = ADB_KEYBOARD_JIS;
+ input_dev->id.version = ADB_KEYBOARD_JIS;
break;
}
for (i = 0; i < 128; i++)
- if (adbhid[id]->keycode[i])
- set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit);
-
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
- adbhid[id]->input.event = adbhid_kbd_event;
- adbhid[id]->input.keycodemax = 127;
- adbhid[id]->input.keycodesize = 1;
+ if (hid->keycode[i])
+ set_bit(hid->keycode[i], input_dev->keybit);
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+ input_dev->event = adbhid_kbd_event;
+ input_dev->keycodemax = 127;
+ input_dev->keycodesize = 1;
break;
case ADB_MOUSE:
- sprintf(adbhid[id]->name, "ADB mouse");
+ sprintf(hid->name, "ADB mouse");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
break;
case ADB_MISC:
switch (original_handler_id) {
case 0x02: /* Adjustable keyboard button device */
- sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- set_bit(KEY_SOUND, adbhid[id]->input.keybit);
- set_bit(KEY_MUTE, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
+ sprintf(hid->name, "ADB adjustable keyboard buttons");
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ set_bit(KEY_SOUND, input_dev->keybit);
+ set_bit(KEY_MUTE, input_dev->keybit);
+ set_bit(KEY_VOLUMEUP, input_dev->keybit);
+ set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
break;
case 0x1f: /* Powerbook button device */
- sprintf(adbhid[id]->name, "ADB Powerbook buttons");
- adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- set_bit(KEY_MUTE, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
- set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit);
- set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_EJECTCD, adbhid[id]->input.keybit);
- set_bit(KEY_SWITCHVIDEOMODE, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMTOGGLE, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMDOWN, adbhid[id]->input.keybit);
- set_bit(KEY_KBDILLUMUP, adbhid[id]->input.keybit);
+ sprintf(hid->name, "ADB Powerbook buttons");
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ set_bit(KEY_MUTE, input_dev->keybit);
+ set_bit(KEY_VOLUMEUP, input_dev->keybit);
+ set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSUP, input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSDOWN, input_dev->keybit);
+ set_bit(KEY_EJECTCD, input_dev->keybit);
+ set_bit(KEY_SWITCHVIDEOMODE, input_dev->keybit);
+ set_bit(KEY_KBDILLUMTOGGLE, input_dev->keybit);
+ set_bit(KEY_KBDILLUMDOWN, input_dev->keybit);
+ set_bit(KEY_KBDILLUMUP, input_dev->keybit);
break;
}
- if (adbhid[id]->name[0])
+ if (hid->name[0])
break;
/* else fall through */
default:
printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");
- kfree(adbhid[id]);
- return;
+ err = -ENODEV;
+ goto fail;
}
- adbhid[id]->input.keycode = adbhid[id]->keycode;
-
- input_register_device(&adbhid[id]->input);
+ input_dev->keycode = hid->keycode;
- printk(KERN_INFO "input: %s on %s\n",
- adbhid[id]->name, adbhid[id]->phys);
+ input_register_device(input_dev);
if (default_id == ADB_KEYBOARD) {
/* HACK WARNING!! This should go away as soon there is an utility
* to control that for event devices.
*/
- adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */
- adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */
+ input_dev->rep[REP_DELAY] = 500; /* input layer default: 250 */
+ input_dev->rep[REP_PERIOD] = 66; /* input layer default: 33 */
}
+
+ return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(hid);
+ adbhid[id] = NULL;
+ return err;
}
static void adbhid_input_unregister(int id)
{
- input_unregister_device(&adbhid[id]->input);
+ input_unregister_device(adbhid[id]->input);
if (adbhid[id]->keycode)
kfree(adbhid[id]->keycode);
kfree(adbhid[id]);
@@ -858,7 +869,7 @@ adbhid_input_reregister(int id, int default_id, int org_handler_id,
int cur_handler_id, int mk)
{
if (adbhid[id]) {
- if (adbhid[id]->input.id.product !=
+ if (adbhid[id]->input->id.product !=
((id << 12)|(default_id << 8)|org_handler_id)) {
adbhid_input_unregister(id);
adbhid_input_register(id, default_id, org_handler_id,
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 5e0811dc6536..2b8a6e821d44 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -27,7 +27,7 @@ static volatile unsigned char __iomem *anslcd_ptr;
#undef DEBUG
-static void __pmac
+static void
anslcd_write_byte_ctrl ( unsigned char c )
{
#ifdef DEBUG
@@ -43,14 +43,14 @@ anslcd_write_byte_ctrl ( unsigned char c )
}
}
-static void __pmac
+static void
anslcd_write_byte_data ( unsigned char c )
{
out_8(anslcd_ptr + ANSLCD_DATA_IX, c);
udelay(anslcd_short_delay);
}
-static ssize_t __pmac
+static ssize_t
anslcd_write( struct file * file, const char __user * buf,
size_t count, loff_t *ppos )
{
@@ -73,7 +73,7 @@ anslcd_write( struct file * file, const char __user * buf,
return p - buf;
}
-static int __pmac
+static int
anslcd_ioctl( struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg )
{
@@ -115,7 +115,7 @@ anslcd_ioctl( struct inode * inode, struct file * file,
}
}
-static int __pmac
+static int
anslcd_open( struct inode * inode, struct file * file )
{
return 0;
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index 19d3e05d6825..e5a2bbf99399 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -430,8 +430,8 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
-1: Unknown
8) min = minutes; sec = seconds */
- unsigned short ac_line_status = 0xff;
- unsigned short battery_status = 0xff;
+ unsigned short ac_line_status;
+ unsigned short battery_status = 0;
unsigned short battery_flag = 0xff;
int percentage = -1;
int time_units = -1;
@@ -446,6 +446,7 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0);
for (i=0; i<pmu_battery_count; i++) {
if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
+ battery_status++;
if (percentage < 0)
percentage = 0;
if (charge < 0)
@@ -461,6 +462,9 @@ static int apm_emu_get_info(char *buf, char **start, off_t fpos, int length)
charging++;
}
}
+ if (0 == battery_status)
+ ac_line_status = 1;
+ battery_status = 0xff;
if (real_count) {
if (amperage < 0) {
if (btype == PMU_BATT_TYPE_SMART)
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 5ad3a5a9eb7f..a66636116f0b 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
-static struct input_dev emumousebtn;
-static void emumousebtn_input_register(void);
+static struct input_dev *emumousebtn;
+static int emumousebtn_input_register(void);
static int mouse_emulate_buttons = 0;
static int mouse_button2_keycode = KEY_RIGHTCTRL; /* right control key */
static int mouse_button3_keycode = KEY_RIGHTALT; /* right option key */
@@ -90,10 +90,10 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
&& (keycode == mouse_button2_keycode
|| keycode == mouse_button3_keycode)) {
if (mouse_emulate_buttons == 1) {
- input_report_key(&emumousebtn,
+ input_report_key(emumousebtn,
keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
down);
- input_sync(&emumousebtn);
+ input_sync(emumousebtn);
return 1;
}
mouse_last_keycode = down ? keycode : 0;
@@ -105,30 +105,34 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
-static void emumousebtn_input_register(void)
+static int emumousebtn_input_register(void)
{
- emumousebtn.name = "Macintosh mouse button emulation";
+ emumousebtn = input_allocate_device();
+ if (!emumousebtn)
+ return -ENOMEM;
- init_input_dev(&emumousebtn);
+ emumousebtn->name = "Macintosh mouse button emulation";
+ emumousebtn->id.bustype = BUS_ADB;
+ emumousebtn->id.vendor = 0x0001;
+ emumousebtn->id.product = 0x0001;
+ emumousebtn->id.version = 0x0100;
- emumousebtn.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- emumousebtn.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- emumousebtn.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ emumousebtn->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- emumousebtn.id.bustype = BUS_ADB;
- emumousebtn.id.vendor = 0x0001;
- emumousebtn.id.product = 0x0001;
- emumousebtn.id.version = 0x0100;
+ input_register_device(emumousebtn);
- input_register_device(&emumousebtn);
-
- printk(KERN_INFO "input: Macintosh mouse button emulation\n");
+ return 0;
}
int __init mac_hid_init(void)
{
+ int err;
- emumousebtn_input_register();
+ err = emumousebtn_input_register();
+ if (err)
+ return err;
#if defined(CONFIG_SYSCTL)
mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 1ee003346923..c34c96d18907 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -17,6 +17,8 @@
#include <linux/pci_ids.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/slab.h>
+
#include <asm/machdep.h>
#include <asm/macio.h>
#include <asm/pmac_feature.h>
diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c
index 97d22bb4516a..7f7d4eaca870 100644
--- a/drivers/macintosh/macio_sysfs.c
+++ b/drivers/macintosh/macio_sysfs.c
@@ -39,6 +39,31 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf)
return length;
}
+static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct of_device *of;
+ char *compat;
+ int cplen;
+ int length;
+
+ of = &to_macio_device (dev)->ofdev;
+ compat = (char *) get_property (of->node, "compatible", &cplen);
+ if (!compat) compat = "", cplen = 1;
+ length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type);
+ buf += length;
+ while (cplen > 0) {
+ int l;
+ length += sprintf (buf, "C%s", compat);
+ buf += length;
+ l = strlen (compat) + 1;
+ compat += l;
+ cplen -= l;
+ }
+
+ return length;
+}
+
macio_config_of_attr (name, "%s\n");
macio_config_of_attr (type, "%s\n");
@@ -46,5 +71,6 @@ struct device_attribute macio_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(type),
__ATTR_RO(compatible),
+ __ATTR_RO(modalias),
__ATTR_NULL
};
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 7c16c25fc5d4..b856bb67169c 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -167,19 +167,19 @@ enum {
* Functions for polling content of media bay
*/
-static u8 __pmac
+static u8
ohare_mb_content(struct media_bay_info *bay)
{
return (MB_IN32(bay, OHARE_MBCR) >> 12) & 7;
}
-static u8 __pmac
+static u8
heathrow_mb_content(struct media_bay_info *bay)
{
return (MB_IN32(bay, HEATHROW_MBCR) >> 12) & 7;
}
-static u8 __pmac
+static u8
keylargo_mb_content(struct media_bay_info *bay)
{
int new_gpio;
@@ -205,7 +205,7 @@ keylargo_mb_content(struct media_bay_info *bay)
* into reset state as well
*/
-static void __pmac
+static void
ohare_mb_power(struct media_bay_info* bay, int on_off)
{
if (on_off) {
@@ -224,7 +224,7 @@ ohare_mb_power(struct media_bay_info* bay, int on_off)
MB_BIC(bay, OHARE_MBCR, 0x00000F00);
}
-static void __pmac
+static void
heathrow_mb_power(struct media_bay_info* bay, int on_off)
{
if (on_off) {
@@ -243,7 +243,7 @@ heathrow_mb_power(struct media_bay_info* bay, int on_off)
MB_BIC(bay, HEATHROW_MBCR, 0x00000F00);
}
-static void __pmac
+static void
keylargo_mb_power(struct media_bay_info* bay, int on_off)
{
if (on_off) {
@@ -267,7 +267,7 @@ keylargo_mb_power(struct media_bay_info* bay, int on_off)
* enable the related busses
*/
-static int __pmac
+static int
ohare_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
{
switch(device_id) {
@@ -287,7 +287,7 @@ ohare_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
return -ENODEV;
}
-static int __pmac
+static int
heathrow_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
{
switch(device_id) {
@@ -307,7 +307,7 @@ heathrow_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
return -ENODEV;
}
-static int __pmac
+static int
keylargo_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
{
switch(device_id) {
@@ -330,43 +330,43 @@ keylargo_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
* Functions for tweaking resets
*/
-static void __pmac
+static void
ohare_mb_un_reset(struct media_bay_info* bay)
{
MB_BIS(bay, OHARE_FCR, OH_BAY_RESET_N);
}
-static void __pmac keylargo_mb_init(struct media_bay_info *bay)
+static void keylargo_mb_init(struct media_bay_info *bay)
{
MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE);
}
-static void __pmac heathrow_mb_un_reset(struct media_bay_info* bay)
+static void heathrow_mb_un_reset(struct media_bay_info* bay)
{
MB_BIS(bay, HEATHROW_FCR, HRW_BAY_RESET_N);
}
-static void __pmac keylargo_mb_un_reset(struct media_bay_info* bay)
+static void keylargo_mb_un_reset(struct media_bay_info* bay)
{
MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET);
}
-static void __pmac ohare_mb_un_reset_ide(struct media_bay_info* bay)
+static void ohare_mb_un_reset_ide(struct media_bay_info* bay)
{
MB_BIS(bay, OHARE_FCR, OH_IDE1_RESET_N);
}
-static void __pmac heathrow_mb_un_reset_ide(struct media_bay_info* bay)
+static void heathrow_mb_un_reset_ide(struct media_bay_info* bay)
{
MB_BIS(bay, HEATHROW_FCR, HRW_IDE1_RESET_N);
}
-static void __pmac keylargo_mb_un_reset_ide(struct media_bay_info* bay)
+static void keylargo_mb_un_reset_ide(struct media_bay_info* bay)
{
MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N);
}
-static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff)
+static inline void set_mb_power(struct media_bay_info* bay, int onoff)
{
/* Power up up and assert the bay reset line */
if (onoff) {
@@ -382,7 +382,7 @@ static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff)
bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
}
-static void __pmac poll_media_bay(struct media_bay_info* bay)
+static void poll_media_bay(struct media_bay_info* bay)
{
int id = bay->ops->content(bay);
@@ -415,7 +415,7 @@ static void __pmac poll_media_bay(struct media_bay_info* bay)
}
}
-int __pmac check_media_bay(struct device_node *which_bay, int what)
+int check_media_bay(struct device_node *which_bay, int what)
{
#ifdef CONFIG_BLK_DEV_IDE
int i;
@@ -432,7 +432,7 @@ int __pmac check_media_bay(struct device_node *which_bay, int what)
}
EXPORT_SYMBOL(check_media_bay);
-int __pmac check_media_bay_by_base(unsigned long base, int what)
+int check_media_bay_by_base(unsigned long base, int what)
{
#ifdef CONFIG_BLK_DEV_IDE
int i;
@@ -449,7 +449,7 @@ int __pmac check_media_bay_by_base(unsigned long base, int what)
return -ENODEV;
}
-int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
int irq, int index)
{
#ifdef CONFIG_BLK_DEV_IDE
@@ -489,7 +489,7 @@ int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long
return -ENODEV;
}
-static void __pmac media_bay_step(int i)
+static void media_bay_step(int i)
{
struct media_bay_info* bay = &media_bays[i];
@@ -619,7 +619,7 @@ static void __pmac media_bay_step(int i)
* with the IDE driver. It needs to be a thread because
* ide_register can't be called from interrupt context.
*/
-static int __pmac media_bay_task(void *x)
+static int media_bay_task(void *x)
{
int i;
@@ -704,11 +704,11 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
}
-static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
+static int media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
{
struct media_bay_info *bay = macio_get_drvdata(mdev);
- if (state != mdev->ofdev.dev.power.power_state && state == PM_SUSPEND_MEM) {
+ if (state.event != mdev->ofdev.dev.power.power_state.event && state.event == PM_EVENT_SUSPEND) {
down(&bay->lock);
bay->sleeping = 1;
set_mb_power(bay, 0);
@@ -719,12 +719,12 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
return 0;
}
-static int __pmac media_bay_resume(struct macio_dev *mdev)
+static int media_bay_resume(struct macio_dev *mdev)
{
struct media_bay_info *bay = macio_get_drvdata(mdev);
- if (mdev->ofdev.dev.power.power_state != 0) {
- mdev->ofdev.dev.power.power_state = 0;
+ if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
+ mdev->ofdev.dev.power.power_state = PMSG_ON;
/* We re-enable the bay using it's previous content
only if it did not change. Note those bozo timings,
@@ -760,7 +760,7 @@ static int __pmac media_bay_resume(struct macio_dev *mdev)
/* Definitions of "ops" structures.
*/
-static struct mb_ops ohare_mb_ops __pmacdata = {
+static struct mb_ops ohare_mb_ops = {
.name = "Ohare",
.content = ohare_mb_content,
.power = ohare_mb_power,
@@ -769,7 +769,7 @@ static struct mb_ops ohare_mb_ops __pmacdata = {
.un_reset_ide = ohare_mb_un_reset_ide,
};
-static struct mb_ops heathrow_mb_ops __pmacdata = {
+static struct mb_ops heathrow_mb_ops = {
.name = "Heathrow",
.content = heathrow_mb_content,
.power = heathrow_mb_power,
@@ -778,7 +778,7 @@ static struct mb_ops heathrow_mb_ops __pmacdata = {
.un_reset_ide = heathrow_mb_un_reset_ide,
};
-static struct mb_ops keylargo_mb_ops __pmacdata = {
+static struct mb_ops keylargo_mb_ops = {
.name = "KeyLargo",
.init = keylargo_mb_init,
.content = keylargo_mb_content,
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index fb535737d17d..34f3c7e2d832 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -8,21 +8,15 @@
*/
/*
- * For now, this driver includes:
- * - RTC get & set
- * - reboot & shutdown commands
- * all synchronous with IRQ disabled (ugh)
- *
* TODO:
- * rework in a way the PMU driver works, that is asynchronous
- * with a queue of commands. I'll do that as soon as I have an
- * SMU based machine at hand. Some more cleanup is needed too,
- * like maybe fitting it into a platform device, etc...
- * Also check what's up with cache coherency, and if we really
- * can't do better than flushing the cache, maybe build a table
- * of command len/reply len like the PMU driver to only flush
- * what is actually necessary.
- * --BenH.
+ * - maybe add timeout to commands ?
+ * - blocking version of time functions
+ * - polling version of i2c commands (including timer that works with
+ * interrutps off)
+ * - maybe avoid some data copies with i2c by directly using the smu cmd
+ * buffer and a lower level internal interface
+ * - understand SMU -> CPU events and implement reception of them via
+ * the userland interface
*/
#include <linux/config.h>
@@ -36,6 +30,11 @@
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/sysdev.h>
+#include <linux/poll.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -45,8 +44,13 @@
#include <asm/smu.h>
#include <asm/sections.h>
#include <asm/abs_addr.h>
+#include <asm/uaccess.h>
+#include <asm/of_device.h>
+
+#define VERSION "0.6"
+#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
-#define DEBUG_SMU 1
+#undef DEBUG_SMU
#ifdef DEBUG_SMU
#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
@@ -57,20 +61,30 @@
/*
* This is the command buffer passed to the SMU hardware
*/
+#define SMU_MAX_DATA 254
+
struct smu_cmd_buf {
u8 cmd;
u8 length;
- u8 data[0x0FFE];
+ u8 data[SMU_MAX_DATA];
};
struct smu_device {
spinlock_t lock;
struct device_node *of_node;
- int db_ack; /* doorbell ack GPIO */
- int db_req; /* doorbell req GPIO */
+ struct of_device *of_dev;
+ int doorbell; /* doorbell gpio */
u32 __iomem *db_buf; /* doorbell buffer */
+ int db_irq;
+ int msg;
+ int msg_irq;
struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
u32 cmd_buf_abs; /* command buffer absolute */
+ struct list_head cmd_list;
+ struct smu_cmd *cmd_cur; /* pending command */
+ struct list_head cmd_i2c_list;
+ struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */
+ struct timer_list i2c_timer;
};
/*
@@ -79,113 +93,245 @@ struct smu_device {
*/
static struct smu_device *smu;
+
/*
- * SMU low level communication stuff
+ * SMU driver low level stuff
*/
-static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack)
-{
- rmb();
- return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0;
-}
-static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf)
+static void smu_start_cmd(void)
{
- return (~cmd_buf->cmd) & 0xff;
-}
+ unsigned long faddr, fend;
+ struct smu_cmd *cmd;
-static void smu_send_cmd(struct smu_device *dev)
-{
- /* SMU command buf is currently cacheable, we need a physical
- * address. This isn't exactly a DMA mapping here, I suspect
+ if (list_empty(&smu->cmd_list))
+ return;
+
+ /* Fetch first command in queue */
+ cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link);
+ smu->cmd_cur = cmd;
+ list_del(&cmd->link);
+
+ DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd,
+ cmd->data_len);
+ DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n",
+ ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1],
+ ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]);
+
+ /* Fill the SMU command buffer */
+ smu->cmd_buf->cmd = cmd->cmd;
+ smu->cmd_buf->length = cmd->data_len;
+ memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len);
+
+ /* Flush command and data to RAM */
+ faddr = (unsigned long)smu->cmd_buf;
+ fend = faddr + smu->cmd_buf->length + 2;
+ flush_inval_dcache_range(faddr, fend);
+
+ /* This isn't exactly a DMA mapping here, I suspect
* the SMU is actually communicating with us via i2c to the
* northbridge or the CPU to access RAM.
*/
- writel(dev->cmd_buf_abs, dev->db_buf);
+ writel(smu->cmd_buf_abs, smu->db_buf);
/* Ring the SMU doorbell */
- pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4);
- pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4);
+ pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4);
}
-static int smu_cmd_done(struct smu_device *dev)
+
+static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
{
- unsigned long wait = 0;
- int gpio;
+ unsigned long flags;
+ struct smu_cmd *cmd;
+ void (*done)(struct smu_cmd *cmd, void *misc) = NULL;
+ void *misc = NULL;
+ u8 gpio;
+ int rc = 0;
- /* Check the SMU doorbell */
- do {
- gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO,
- NULL, dev->db_ack);
- if ((gpio & 7) == 7)
- return 0;
- udelay(100);
- } while(++wait < 10000);
+ /* SMU completed the command, well, we hope, let's make sure
+ * of it
+ */
+ spin_lock_irqsave(&smu->lock, flags);
- printk(KERN_ERR "SMU timeout !\n");
- return -ENXIO;
+ gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
+ if ((gpio & 7) != 7) {
+ spin_unlock_irqrestore(&smu->lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ cmd = smu->cmd_cur;
+ smu->cmd_cur = NULL;
+ if (cmd == NULL)
+ goto bail;
+
+ if (rc == 0) {
+ unsigned long faddr;
+ int reply_len;
+ u8 ack;
+
+ /* CPU might have brought back the cache line, so we need
+ * to flush again before peeking at the SMU response. We
+ * flush the entire buffer for now as we haven't read the
+ * reply lenght (it's only 2 cache lines anyway)
+ */
+ faddr = (unsigned long)smu->cmd_buf;
+ flush_inval_dcache_range(faddr, faddr + 256);
+
+ /* Now check ack */
+ ack = (~cmd->cmd) & 0xff;
+ if (ack != smu->cmd_buf->cmd) {
+ DPRINTK("SMU: incorrect ack, want %x got %x\n",
+ ack, smu->cmd_buf->cmd);
+ rc = -EIO;
+ }
+ reply_len = rc == 0 ? smu->cmd_buf->length : 0;
+ DPRINTK("SMU: reply len: %d\n", reply_len);
+ if (reply_len > cmd->reply_len) {
+ printk(KERN_WARNING "SMU: reply buffer too small,"
+ "got %d bytes for a %d bytes buffer\n",
+ reply_len, cmd->reply_len);
+ reply_len = cmd->reply_len;
+ }
+ cmd->reply_len = reply_len;
+ if (cmd->reply_buf && reply_len)
+ memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len);
+ }
+
+ /* Now complete the command. Write status last in order as we lost
+ * ownership of the command structure as soon as it's no longer -1
+ */
+ done = cmd->done;
+ misc = cmd->misc;
+ mb();
+ cmd->status = rc;
+ bail:
+ /* Start next command if any */
+ smu_start_cmd();
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ /* Call command completion handler if any */
+ if (done)
+ done(cmd, misc);
+
+ /* It's an edge interrupt, nothing to do */
+ return IRQ_HANDLED;
}
-static int smu_do_cmd(struct smu_device *dev)
+
+static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
{
- int rc;
- u8 cmd_ack;
+ /* I don't quite know what to do with this one, we seem to never
+ * receive it, so I suspect we have to arm it someway in the SMU
+ * to start getting events that way.
+ */
- DPRINTK("SMU do_cmd %02x len=%d %02x\n",
- dev->cmd_buf->cmd, dev->cmd_buf->length,
- dev->cmd_buf->data[0]);
+ printk(KERN_INFO "SMU: message interrupt !\n");
- cmd_ack = smu_save_ack_cmd(dev->cmd_buf);
+ /* It's an edge interrupt, nothing to do */
+ return IRQ_HANDLED;
+}
- /* Clear cmd_buf cache lines */
- flush_inval_dcache_range((unsigned long)dev->cmd_buf,
- ((unsigned long)dev->cmd_buf) +
- sizeof(struct smu_cmd_buf));
- smu_send_cmd(dev);
- rc = smu_cmd_done(dev);
- if (rc == 0)
- rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1;
- DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n",
- dev->cmd_buf->cmd, dev->cmd_buf->length,
- dev->cmd_buf->data[0], rc, cmd_ack);
+/*
+ * Queued command management.
+ *
+ */
+
+int smu_queue_cmd(struct smu_cmd *cmd)
+{
+ unsigned long flags;
- return rc;
+ if (smu == NULL)
+ return -ENODEV;
+ if (cmd->data_len > SMU_MAX_DATA ||
+ cmd->reply_len > SMU_MAX_DATA)
+ return -EINVAL;
+
+ cmd->status = 1;
+ spin_lock_irqsave(&smu->lock, flags);
+ list_add_tail(&cmd->link, &smu->cmd_list);
+ if (smu->cmd_cur == NULL)
+ smu_start_cmd();
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ return 0;
}
+EXPORT_SYMBOL(smu_queue_cmd);
-/* RTC low level commands */
-static inline int bcd2hex (int n)
+
+int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
+ unsigned int data_len,
+ void (*done)(struct smu_cmd *cmd, void *misc),
+ void *misc, ...)
{
- return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
+ struct smu_cmd *cmd = &scmd->cmd;
+ va_list list;
+ int i;
+
+ if (data_len > sizeof(scmd->buffer))
+ return -EINVAL;
+
+ memset(scmd, 0, sizeof(*scmd));
+ cmd->cmd = command;
+ cmd->data_len = data_len;
+ cmd->data_buf = scmd->buffer;
+ cmd->reply_len = sizeof(scmd->buffer);
+ cmd->reply_buf = scmd->buffer;
+ cmd->done = done;
+ cmd->misc = misc;
+
+ va_start(list, misc);
+ for (i = 0; i < data_len; ++i)
+ scmd->buffer[i] = (u8)va_arg(list, int);
+ va_end(list);
+
+ return smu_queue_cmd(cmd);
}
+EXPORT_SYMBOL(smu_queue_simple);
-static inline int hex2bcd (int n)
+
+void smu_poll(void)
{
- return ((n / 10) << 4) + (n % 10);
+ u8 gpio;
+
+ if (smu == NULL)
+ return;
+
+ gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
+ if ((gpio & 7) == 7)
+ smu_db_intr(smu->db_irq, smu, NULL);
}
+EXPORT_SYMBOL(smu_poll);
-#if 0
-static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+
+void smu_done_complete(struct smu_cmd *cmd, void *misc)
{
- cmd_buf->cmd = 0x8e;
- cmd_buf->length = 8;
- cmd_buf->data[0] = 0x00;
- memset(cmd_buf->data + 1, 0, 7);
+ struct completion *comp = misc;
+
+ complete(comp);
}
+EXPORT_SYMBOL(smu_done_complete);
+
-static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+void smu_spinwait_cmd(struct smu_cmd *cmd)
{
- cmd_buf->cmd = 0x8e;
- cmd_buf->length = 1;
- cmd_buf->data[0] = 0x01;
+ while(cmd->status == 1)
+ smu_poll();
}
+EXPORT_SYMBOL(smu_spinwait_cmd);
+
-static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+/* RTC low level commands */
+static inline int bcd2hex (int n)
{
- cmd_buf->cmd = 0x8e;
- cmd_buf->length = 1;
- cmd_buf->data[0] = 0x02;
+ return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
}
-#endif
+
+
+static inline int hex2bcd (int n)
+{
+ return ((n / 10) << 4) + (n % 10);
+}
+
static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
struct rtc_time *time)
@@ -202,100 +348,96 @@ static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
}
-static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf)
-{
- cmd_buf->cmd = 0x8e;
- cmd_buf->length = 1;
- cmd_buf->data[0] = 0x81;
-}
-static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf,
- struct rtc_time *time)
+int smu_get_rtc_time(struct rtc_time *time, int spinwait)
{
- time->tm_sec = bcd2hex(cmd_buf->data[0]);
- time->tm_min = bcd2hex(cmd_buf->data[1]);
- time->tm_hour = bcd2hex(cmd_buf->data[2]);
- time->tm_wday = bcd2hex(cmd_buf->data[3]);
- time->tm_mday = bcd2hex(cmd_buf->data[4]);
- time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1;
- time->tm_year = bcd2hex(cmd_buf->data[6]) + 100;
-}
-
-int smu_get_rtc_time(struct rtc_time *time)
-{
- unsigned long flags;
+ struct smu_simple_cmd cmd;
int rc;
if (smu == NULL)
return -ENODEV;
memset(time, 0, sizeof(struct rtc_time));
- spin_lock_irqsave(&smu->lock, flags);
- smu_fill_get_rtc_cmd(smu->cmd_buf);
- rc = smu_do_cmd(smu);
- if (rc == 0)
- smu_parse_get_rtc_reply(smu->cmd_buf, time);
- spin_unlock_irqrestore(&smu->lock, flags);
+ rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL,
+ SMU_CMD_RTC_GET_DATETIME);
+ if (rc)
+ return rc;
+ smu_spinwait_simple(&cmd);
- return rc;
+ time->tm_sec = bcd2hex(cmd.buffer[0]);
+ time->tm_min = bcd2hex(cmd.buffer[1]);
+ time->tm_hour = bcd2hex(cmd.buffer[2]);
+ time->tm_wday = bcd2hex(cmd.buffer[3]);
+ time->tm_mday = bcd2hex(cmd.buffer[4]);
+ time->tm_mon = bcd2hex(cmd.buffer[5]) - 1;
+ time->tm_year = bcd2hex(cmd.buffer[6]) + 100;
+
+ return 0;
}
-int smu_set_rtc_time(struct rtc_time *time)
+
+int smu_set_rtc_time(struct rtc_time *time, int spinwait)
{
- unsigned long flags;
+ struct smu_simple_cmd cmd;
int rc;
if (smu == NULL)
return -ENODEV;
- spin_lock_irqsave(&smu->lock, flags);
- smu_fill_set_rtc_cmd(smu->cmd_buf, time);
- rc = smu_do_cmd(smu);
- spin_unlock_irqrestore(&smu->lock, flags);
+ rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL,
+ SMU_CMD_RTC_SET_DATETIME,
+ hex2bcd(time->tm_sec),
+ hex2bcd(time->tm_min),
+ hex2bcd(time->tm_hour),
+ time->tm_wday,
+ hex2bcd(time->tm_mday),
+ hex2bcd(time->tm_mon) + 1,
+ hex2bcd(time->tm_year - 100));
+ if (rc)
+ return rc;
+ smu_spinwait_simple(&cmd);
- return rc;
+ return 0;
}
+
void smu_shutdown(void)
{
- const unsigned char *command = "SHUTDOWN";
- unsigned long flags;
+ struct smu_simple_cmd cmd;
if (smu == NULL)
return;
- spin_lock_irqsave(&smu->lock, flags);
- smu->cmd_buf->cmd = 0xaa;
- smu->cmd_buf->length = strlen(command);
- strcpy(smu->cmd_buf->data, command);
- smu_do_cmd(smu);
+ if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL,
+ 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0))
+ return;
+ smu_spinwait_simple(&cmd);
for (;;)
;
- spin_unlock_irqrestore(&smu->lock, flags);
}
+
void smu_restart(void)
{
- const unsigned char *command = "RESTART";
- unsigned long flags;
+ struct smu_simple_cmd cmd;
if (smu == NULL)
return;
- spin_lock_irqsave(&smu->lock, flags);
- smu->cmd_buf->cmd = 0xaa;
- smu->cmd_buf->length = strlen(command);
- strcpy(smu->cmd_buf->data, command);
- smu_do_cmd(smu);
+ if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL,
+ 'R', 'E', 'S', 'T', 'A', 'R', 'T', 0))
+ return;
+ smu_spinwait_simple(&cmd);
for (;;)
;
- spin_unlock_irqrestore(&smu->lock, flags);
}
+
int smu_present(void)
{
return smu != NULL;
}
+EXPORT_SYMBOL(smu_present);
int smu_init (void)
@@ -307,6 +449,8 @@ int smu_init (void)
if (np == NULL)
return -ENODEV;
+ printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR);
+
if (smu_cmdbuf_abs == 0) {
printk(KERN_ERR "SMU: Command buffer not allocated !\n");
return -EINVAL;
@@ -318,7 +462,13 @@ int smu_init (void)
memset(smu, 0, sizeof(*smu));
spin_lock_init(&smu->lock);
+ INIT_LIST_HEAD(&smu->cmd_list);
+ INIT_LIST_HEAD(&smu->cmd_i2c_list);
smu->of_node = np;
+ smu->db_irq = NO_IRQ;
+ smu->msg_irq = NO_IRQ;
+ init_timer(&smu->i2c_timer);
+
/* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
* 32 bits value safely
*/
@@ -331,8 +481,8 @@ int smu_init (void)
goto fail;
}
data = (u32 *)get_property(np, "reg", NULL);
- of_node_put(np);
if (data == NULL) {
+ of_node_put(np);
printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
goto fail;
}
@@ -341,8 +491,31 @@ int smu_init (void)
* and ack. GPIOs are at 0x50, best would be to find that out
* in the device-tree though.
*/
- smu->db_req = 0x50 + *data;
- smu->db_ack = 0x50 + *data;
+ smu->doorbell = *data;
+ if (smu->doorbell < 0x50)
+ smu->doorbell += 0x50;
+ if (np->n_intrs > 0)
+ smu->db_irq = np->intrs[0].line;
+
+ of_node_put(np);
+
+ /* Now look for the smu-interrupt GPIO */
+ do {
+ np = of_find_node_by_name(NULL, "smu-interrupt");
+ if (np == NULL)
+ break;
+ data = (u32 *)get_property(np, "reg", NULL);
+ if (data == NULL) {
+ of_node_put(np);
+ break;
+ }
+ smu->msg = *data;
+ if (smu->msg < 0x50)
+ smu->msg += 0x50;
+ if (np->n_intrs > 0)
+ smu->msg_irq = np->intrs[0].line;
+ of_node_put(np);
+ } while(0);
/* Doorbell buffer is currently hard-coded, I didn't find a proper
* device-tree entry giving the address. Best would probably to use
@@ -362,3 +535,584 @@ int smu_init (void)
return -ENXIO;
}
+
+
+static int smu_late_init(void)
+{
+ if (!smu)
+ return 0;
+
+ /*
+ * Try to request the interrupts
+ */
+
+ if (smu->db_irq != NO_IRQ) {
+ if (request_irq(smu->db_irq, smu_db_intr,
+ SA_SHIRQ, "SMU doorbell", smu) < 0) {
+ printk(KERN_WARNING "SMU: can't "
+ "request interrupt %d\n",
+ smu->db_irq);
+ smu->db_irq = NO_IRQ;
+ }
+ }
+
+ if (smu->msg_irq != NO_IRQ) {
+ if (request_irq(smu->msg_irq, smu_msg_intr,
+ SA_SHIRQ, "SMU message", smu) < 0) {
+ printk(KERN_WARNING "SMU: can't "
+ "request interrupt %d\n",
+ smu->msg_irq);
+ smu->msg_irq = NO_IRQ;
+ }
+ }
+
+ return 0;
+}
+arch_initcall(smu_late_init);
+
+/*
+ * sysfs visibility
+ */
+
+static void smu_expose_childs(void *unused)
+{
+ struct device_node *np;
+
+ for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) {
+ if (device_is_compatible(np, "smu-i2c")) {
+ char name[32];
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+ if (reg == NULL)
+ continue;
+ sprintf(name, "smu-i2c-%02x", *reg);
+ of_platform_device_create(np, name, &smu->of_dev->dev);
+ }
+ }
+
+}
+
+static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
+
+static int smu_platform_probe(struct of_device* dev,
+ const struct of_device_id *match)
+{
+ if (!smu)
+ return -ENODEV;
+ smu->of_dev = dev;
+
+ /*
+ * Ok, we are matched, now expose all i2c busses. We have to defer
+ * that unfortunately or it would deadlock inside the device model
+ */
+ schedule_work(&smu_expose_childs_work);
+
+ return 0;
+}
+
+static struct of_device_id smu_platform_match[] =
+{
+ {
+ .type = "smu",
+ },
+ {},
+};
+
+static struct of_platform_driver smu_of_platform_driver =
+{
+ .name = "smu",
+ .match_table = smu_platform_match,
+ .probe = smu_platform_probe,
+};
+
+static int __init smu_init_sysfs(void)
+{
+ int rc;
+
+ /*
+ * Due to sysfs bogosity, a sysdev is not a real device, so
+ * we should in fact create both if we want sysdev semantics
+ * for power management.
+ * For now, we don't power manage machines with an SMU chip,
+ * I'm a bit too far from figuring out how that works with those
+ * new chipsets, but that will come back and bite us
+ */
+ rc = of_register_driver(&smu_of_platform_driver);
+ return 0;
+}
+
+device_initcall(smu_init_sysfs);
+
+struct of_device *smu_get_ofdev(void)
+{
+ if (!smu)
+ return NULL;
+ return smu->of_dev;
+}
+
+EXPORT_SYMBOL_GPL(smu_get_ofdev);
+
+/*
+ * i2c interface
+ */
+
+static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
+{
+ void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done;
+ void *misc = cmd->misc;
+ unsigned long flags;
+
+ /* Check for read case */
+ if (!fail && cmd->read) {
+ if (cmd->pdata[0] < 1)
+ fail = 1;
+ else
+ memcpy(cmd->info.data, &cmd->pdata[1],
+ cmd->info.datalen);
+ }
+
+ DPRINTK("SMU: completing, success: %d\n", !fail);
+
+ /* Update status and mark no pending i2c command with lock
+ * held so nobody comes in while we dequeue an eventual
+ * pending next i2c command
+ */
+ spin_lock_irqsave(&smu->lock, flags);
+ smu->cmd_i2c_cur = NULL;
+ wmb();
+ cmd->status = fail ? -EIO : 0;
+
+ /* Is there another i2c command waiting ? */
+ if (!list_empty(&smu->cmd_i2c_list)) {
+ struct smu_i2c_cmd *newcmd;
+
+ /* Fetch it, new current, remove from list */
+ newcmd = list_entry(smu->cmd_i2c_list.next,
+ struct smu_i2c_cmd, link);
+ smu->cmd_i2c_cur = newcmd;
+ list_del(&cmd->link);
+
+ /* Queue with low level smu */
+ list_add_tail(&cmd->scmd.link, &smu->cmd_list);
+ if (smu->cmd_cur == NULL)
+ smu_start_cmd();
+ }
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ /* Call command completion handler if any */
+ if (done)
+ done(cmd, misc);
+
+}
+
+
+static void smu_i2c_retry(unsigned long data)
+{
+ struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data;
+
+ DPRINTK("SMU: i2c failure, requeuing...\n");
+
+ /* requeue command simply by resetting reply_len */
+ cmd->pdata[0] = 0xff;
+ cmd->scmd.reply_len = 0x10;
+ smu_queue_cmd(&cmd->scmd);
+}
+
+
+static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
+{
+ struct smu_i2c_cmd *cmd = misc;
+ int fail = 0;
+
+ DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n",
+ cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len);
+
+ /* Check for possible status */
+ if (scmd->status < 0)
+ fail = 1;
+ else if (cmd->read) {
+ if (cmd->stage == 0)
+ fail = cmd->pdata[0] != 0;
+ else
+ fail = cmd->pdata[0] >= 0x80;
+ } else {
+ fail = cmd->pdata[0] != 0;
+ }
+
+ /* Handle failures by requeuing command, after 5ms interval
+ */
+ if (fail && --cmd->retries > 0) {
+ DPRINTK("SMU: i2c failure, starting timer...\n");
+ smu->i2c_timer.function = smu_i2c_retry;
+ smu->i2c_timer.data = (unsigned long)cmd;
+ smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5);
+ add_timer(&smu->i2c_timer);
+ return;
+ }
+
+ /* If failure or stage 1, command is complete */
+ if (fail || cmd->stage != 0) {
+ smu_i2c_complete_command(cmd, fail);
+ return;
+ }
+
+ DPRINTK("SMU: going to stage 1\n");
+
+ /* Ok, initial command complete, now poll status */
+ scmd->reply_buf = cmd->pdata;
+ scmd->reply_len = 0x10;
+ scmd->data_buf = cmd->pdata;
+ scmd->data_len = 1;
+ cmd->pdata[0] = 0;
+ cmd->stage = 1;
+ cmd->retries = 20;
+ smu_queue_cmd(scmd);
+}
+
+
+int smu_queue_i2c(struct smu_i2c_cmd *cmd)
+{
+ unsigned long flags;
+
+ if (smu == NULL)
+ return -ENODEV;
+
+ /* Fill most fields of scmd */
+ cmd->scmd.cmd = SMU_CMD_I2C_COMMAND;
+ cmd->scmd.done = smu_i2c_low_completion;
+ cmd->scmd.misc = cmd;
+ cmd->scmd.reply_buf = cmd->pdata;
+ cmd->scmd.reply_len = 0x10;
+ cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
+ cmd->scmd.status = 1;
+ cmd->stage = 0;
+ cmd->pdata[0] = 0xff;
+ cmd->retries = 20;
+ cmd->status = 1;
+
+ /* Check transfer type, sanitize some "info" fields
+ * based on transfer type and do more checking
+ */
+ cmd->info.caddr = cmd->info.devaddr;
+ cmd->read = cmd->info.devaddr & 0x01;
+ switch(cmd->info.type) {
+ case SMU_I2C_TRANSFER_SIMPLE:
+ memset(&cmd->info.sublen, 0, 4);
+ break;
+ case SMU_I2C_TRANSFER_COMBINED:
+ cmd->info.devaddr &= 0xfe;
+ case SMU_I2C_TRANSFER_STDSUB:
+ if (cmd->info.sublen > 3)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Finish setting up command based on transfer direction
+ */
+ if (cmd->read) {
+ if (cmd->info.datalen > SMU_I2C_READ_MAX)
+ return -EINVAL;
+ memset(cmd->info.data, 0xff, cmd->info.datalen);
+ cmd->scmd.data_len = 9;
+ } else {
+ if (cmd->info.datalen > SMU_I2C_WRITE_MAX)
+ return -EINVAL;
+ cmd->scmd.data_len = 9 + cmd->info.datalen;
+ }
+
+ DPRINTK("SMU: i2c enqueuing command\n");
+ DPRINTK("SMU: %s, len=%d bus=%x addr=%x sub0=%x type=%x\n",
+ cmd->read ? "read" : "write", cmd->info.datalen,
+ cmd->info.bus, cmd->info.caddr,
+ cmd->info.subaddr[0], cmd->info.type);
+
+
+ /* Enqueue command in i2c list, and if empty, enqueue also in
+ * main command list
+ */
+ spin_lock_irqsave(&smu->lock, flags);
+ if (smu->cmd_i2c_cur == NULL) {
+ smu->cmd_i2c_cur = cmd;
+ list_add_tail(&cmd->scmd.link, &smu->cmd_list);
+ if (smu->cmd_cur == NULL)
+ smu_start_cmd();
+ } else
+ list_add_tail(&cmd->link, &smu->cmd_i2c_list);
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ return 0;
+}
+
+
+
+/*
+ * Userland driver interface
+ */
+
+
+static LIST_HEAD(smu_clist);
+static DEFINE_SPINLOCK(smu_clist_lock);
+
+enum smu_file_mode {
+ smu_file_commands,
+ smu_file_events,
+ smu_file_closing
+};
+
+struct smu_private
+{
+ struct list_head list;
+ enum smu_file_mode mode;
+ int busy;
+ struct smu_cmd cmd;
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ u8 buffer[SMU_MAX_DATA];
+};
+
+
+static int smu_open(struct inode *inode, struct file *file)
+{
+ struct smu_private *pp;
+ unsigned long flags;
+
+ pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL);
+ if (pp == 0)
+ return -ENOMEM;
+ memset(pp, 0, sizeof(struct smu_private));
+ spin_lock_init(&pp->lock);
+ pp->mode = smu_file_commands;
+ init_waitqueue_head(&pp->wait);
+
+ spin_lock_irqsave(&smu_clist_lock, flags);
+ list_add(&pp->list, &smu_clist);
+ spin_unlock_irqrestore(&smu_clist_lock, flags);
+ file->private_data = pp;
+
+ return 0;
+}
+
+
+static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc)
+{
+ struct smu_private *pp = misc;
+
+ wake_up_all(&pp->wait);
+}
+
+
+static ssize_t smu_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct smu_private *pp = file->private_data;
+ unsigned long flags;
+ struct smu_user_cmd_hdr hdr;
+ int rc = 0;
+
+ if (pp->busy)
+ return -EBUSY;
+ else if (copy_from_user(&hdr, buf, sizeof(hdr)))
+ return -EFAULT;
+ else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) {
+ pp->mode = smu_file_events;
+ return 0;
+ } else if (hdr.cmdtype != SMU_CMDTYPE_SMU)
+ return -EINVAL;
+ else if (pp->mode != smu_file_commands)
+ return -EBADFD;
+ else if (hdr.data_len > SMU_MAX_DATA)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pp->lock, flags);
+ if (pp->busy) {
+ spin_unlock_irqrestore(&pp->lock, flags);
+ return -EBUSY;
+ }
+ pp->busy = 1;
+ pp->cmd.status = 1;
+ spin_unlock_irqrestore(&pp->lock, flags);
+
+ if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) {
+ pp->busy = 0;
+ return -EFAULT;
+ }
+
+ pp->cmd.cmd = hdr.cmd;
+ pp->cmd.data_len = hdr.data_len;
+ pp->cmd.reply_len = SMU_MAX_DATA;
+ pp->cmd.data_buf = pp->buffer;
+ pp->cmd.reply_buf = pp->buffer;
+ pp->cmd.done = smu_user_cmd_done;
+ pp->cmd.misc = pp;
+ rc = smu_queue_cmd(&pp->cmd);
+ if (rc < 0)
+ return rc;
+ return count;
+}
+
+
+static ssize_t smu_read_command(struct file *file, struct smu_private *pp,
+ char __user *buf, size_t count)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct smu_user_reply_hdr hdr;
+ unsigned long flags;
+ int size, rc = 0;
+
+ if (!pp->busy)
+ return 0;
+ if (count < sizeof(struct smu_user_reply_hdr))
+ return -EOVERFLOW;
+ spin_lock_irqsave(&pp->lock, flags);
+ if (pp->cmd.status == 1) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ add_wait_queue(&pp->wait, &wait);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ rc = 0;
+ if (pp->cmd.status != 1)
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ spin_unlock_irqrestore(&pp->lock, flags);
+ schedule();
+ spin_lock_irqsave(&pp->lock, flags);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&pp->wait, &wait);
+ }
+ spin_unlock_irqrestore(&pp->lock, flags);
+ if (rc)
+ return rc;
+ if (pp->cmd.status != 0)
+ pp->cmd.reply_len = 0;
+ size = sizeof(hdr) + pp->cmd.reply_len;
+ if (count < size)
+ size = count;
+ rc = size;
+ hdr.status = pp->cmd.status;
+ hdr.reply_len = pp->cmd.reply_len;
+ if (copy_to_user(buf, &hdr, sizeof(hdr)))
+ return -EFAULT;
+ size -= sizeof(hdr);
+ if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size))
+ return -EFAULT;
+ pp->busy = 0;
+
+ return rc;
+}
+
+
+static ssize_t smu_read_events(struct file *file, struct smu_private *pp,
+ char __user *buf, size_t count)
+{
+ /* Not implemented */
+ msleep_interruptible(1000);
+ return 0;
+}
+
+
+static ssize_t smu_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct smu_private *pp = file->private_data;
+
+ if (pp->mode == smu_file_commands)
+ return smu_read_command(file, pp, buf, count);
+ if (pp->mode == smu_file_events)
+ return smu_read_events(file, pp, buf, count);
+
+ return -EBADFD;
+}
+
+static unsigned int smu_fpoll(struct file *file, poll_table *wait)
+{
+ struct smu_private *pp = file->private_data;
+ unsigned int mask = 0;
+ unsigned long flags;
+
+ if (pp == 0)
+ return 0;
+
+ if (pp->mode == smu_file_commands) {
+ poll_wait(file, &pp->wait, wait);
+
+ spin_lock_irqsave(&pp->lock, flags);
+ if (pp->busy && pp->cmd.status != 1)
+ mask |= POLLIN;
+ spin_unlock_irqrestore(&pp->lock, flags);
+ } if (pp->mode == smu_file_events) {
+ /* Not yet implemented */
+ }
+ return mask;
+}
+
+static int smu_release(struct inode *inode, struct file *file)
+{
+ struct smu_private *pp = file->private_data;
+ unsigned long flags;
+ unsigned int busy;
+
+ if (pp == 0)
+ return 0;
+
+ file->private_data = NULL;
+
+ /* Mark file as closing to avoid races with new request */
+ spin_lock_irqsave(&pp->lock, flags);
+ pp->mode = smu_file_closing;
+ busy = pp->busy;
+
+ /* Wait for any pending request to complete */
+ if (busy && pp->cmd.status == 1) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&pp->wait, &wait);
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (pp->cmd.status != 1)
+ break;
+ spin_lock_irqsave(&pp->lock, flags);
+ schedule();
+ spin_unlock_irqrestore(&pp->lock, flags);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&pp->wait, &wait);
+ }
+ spin_unlock_irqrestore(&pp->lock, flags);
+
+ spin_lock_irqsave(&smu_clist_lock, flags);
+ list_del(&pp->list);
+ spin_unlock_irqrestore(&smu_clist_lock, flags);
+ kfree(pp);
+
+ return 0;
+}
+
+
+static struct file_operations smu_device_fops = {
+ .llseek = no_llseek,
+ .read = smu_read,
+ .write = smu_write,
+ .poll = smu_fpoll,
+ .open = smu_open,
+ .release = smu_release,
+};
+
+static struct miscdevice pmu_device = {
+ MISC_DYNAMIC_MINOR, "smu", &smu_device_fops
+};
+
+static int smu_device_init(void)
+{
+ if (!smu)
+ return -ENODEV;
+ if (misc_register(&pmu_device) < 0)
+ printk(KERN_ERR "via-pmu: cannot register misc device.\n");
+ return 0;
+}
+device_initcall(smu_device_init);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index c9ca1118e449..f38696622eb4 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -599,7 +599,7 @@ thermostat_init(void)
sensor_location[2] = "?";
}
- of_dev = of_platform_device_create(np, "temperatures");
+ of_dev = of_platform_device_create(np, "temperatures", NULL);
if (of_dev == NULL) {
printk(KERN_ERR "Can't register temperatures device !\n");
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 703e31973314..cc507ceef153 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -2051,7 +2051,7 @@ static int __init therm_pm72_init(void)
return -ENODEV;
}
}
- of_dev = of_platform_device_create(np, "temperature");
+ of_dev = of_platform_device_create(np, "temperature", NULL);
if (of_dev == NULL) {
printk(KERN_ERR "Can't register FCU platform device !\n");
return -ENODEV;
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index cbb72eb0426d..6aaa1df1a64e 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -504,7 +504,7 @@ g4fan_init( void )
}
if( !(np=of_find_node_by_name(NULL, "fan")) )
return -ENODEV;
- x.of_dev = of_platform_device_create( np, "temperature" );
+ x.of_dev = of_platform_device_create(np, "temperature", NULL);
of_node_put( np );
if( !x.of_dev ) {
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 417deb5de108..d843a6c9c6df 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -37,7 +37,6 @@ static DEFINE_SPINLOCK(cuda_lock);
#ifdef CONFIG_MAC
#define CUDA_IRQ IRQ_MAC_ADB
-#define __openfirmware
#define eieio()
#else
#define CUDA_IRQ vias->intrs[0].line
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4a0a0ad2d03c..9bc6cc6e3845 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -155,10 +155,10 @@ static spinlock_t pmu_lock;
static u8 pmu_intr_mask;
static int pmu_version;
static int drop_interrupts;
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
static int option_lid_wakeup = 1;
static int sleep_in_progress;
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
static unsigned long async_req_locks;
static unsigned int pmu_irq_stats[11];
@@ -244,7 +244,7 @@ int pmu_wink(struct adb_request *req);
* - the number of response bytes which the PMU will return, or
* -1 if it will send a length byte.
*/
-static const s8 pmu_data_len[256][2] __openfirmwaredata = {
+static const s8 pmu_data_len[256][2] = {
/* 0 1 2 3 4 5 6 7 */
/*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
/*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
@@ -295,7 +295,7 @@ static struct backlight_controller pmu_backlight_controller = {
};
#endif /* CONFIG_PMAC_BACKLIGHT */
-int __openfirmware
+int
find_via_pmu(void)
{
if (via != 0)
@@ -374,7 +374,7 @@ find_via_pmu(void)
}
#ifdef CONFIG_ADB
-static int __openfirmware
+static int
pmu_probe(void)
{
return vias == NULL? -ENODEV: 0;
@@ -405,7 +405,7 @@ static int __init via_pmu_start(void)
bright_req_2.complete = 1;
batt_req.complete = 1;
-#ifdef CONFIG_PPC32
+#if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE)
if (pmu_kind == PMU_KEYLARGO_BASED)
openpic_set_irq_priority(vias->intrs[0].line,
OPENPIC_PRIORITY_DEFAULT + 1);
@@ -520,7 +520,7 @@ static int __init via_pmu_dev_init(void)
device_initcall(via_pmu_dev_init);
-static int __openfirmware
+static int
init_pmu(void)
{
int timeout;
@@ -588,17 +588,6 @@ pmu_get_model(void)
return pmu_kind;
}
-#ifndef CONFIG_PPC64
-static inline void wakeup_decrementer(void)
-{
- set_dec(tb_ticks_per_jiffy);
- /* No currently-supported powerbook has a 601,
- * so use get_tbl, not native
- */
- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
-}
-#endif
-
static void pmu_set_server_mode(int server_mode)
{
struct adb_request req;
@@ -625,7 +614,7 @@ static void pmu_set_server_mode(int server_mode)
/* This new version of the code for 2400/3400/3500 powerbooks
* is inspired from the implementation in gkrellm-pmu
*/
-static void __pmac
+static void
done_battery_state_ohare(struct adb_request* req)
{
/* format:
@@ -713,7 +702,7 @@ done_battery_state_ohare(struct adb_request* req)
clear_bit(0, &async_req_locks);
}
-static void __pmac
+static void
done_battery_state_smart(struct adb_request* req)
{
/* format:
@@ -791,7 +780,7 @@ done_battery_state_smart(struct adb_request* req)
clear_bit(0, &async_req_locks);
}
-static void __pmac
+static void
query_battery_state(void)
{
if (test_and_set_bit(0, &async_req_locks))
@@ -804,7 +793,7 @@ query_battery_state(void)
2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);
}
-static int __pmac
+static int
proc_get_info(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -819,7 +808,7 @@ proc_get_info(char *page, char **start, off_t off,
return p - page;
}
-static int __pmac
+static int
proc_get_irqstats(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -846,7 +835,7 @@ proc_get_irqstats(char *page, char **start, off_t off,
return p - page;
}
-static int __pmac
+static int
proc_get_batt(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -870,13 +859,13 @@ proc_get_batt(char *page, char **start, off_t off,
return p - page;
}
-static int __pmac
+static int
proc_read_options(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
char *p = page;
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
if (pmu_kind == PMU_KEYLARGO_BASED &&
pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
@@ -887,7 +876,7 @@ proc_read_options(char *page, char **start, off_t off,
return p - page;
}
-static int __pmac
+static int
proc_write_options(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
@@ -917,7 +906,7 @@ proc_write_options(struct file *file, const char __user *buffer,
*(val++) = 0;
while(*val == ' ')
val++;
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
if (pmu_kind == PMU_KEYLARGO_BASED &&
pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
if (!strcmp(label, "lid_wakeup"))
@@ -934,7 +923,7 @@ proc_write_options(struct file *file, const char __user *buffer,
#ifdef CONFIG_ADB
/* Send an ADB command */
-static int __pmac
+static int
pmu_send_request(struct adb_request *req, int sync)
{
int i, ret;
@@ -1014,7 +1003,7 @@ pmu_send_request(struct adb_request *req, int sync)
}
/* Enable/disable autopolling */
-static int __pmac
+static int
pmu_adb_autopoll(int devs)
{
struct adb_request req;
@@ -1037,7 +1026,7 @@ pmu_adb_autopoll(int devs)
}
/* Reset the ADB bus */
-static int __pmac
+static int
pmu_adb_reset_bus(void)
{
struct adb_request req;
@@ -1072,7 +1061,7 @@ pmu_adb_reset_bus(void)
#endif /* CONFIG_ADB */
/* Construct and send a pmu request */
-int __openfirmware
+int
pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
int nbytes, ...)
{
@@ -1098,7 +1087,7 @@ pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
return pmu_queue_request(req);
}
-int __pmac
+int
pmu_queue_request(struct adb_request *req)
{
unsigned long flags;
@@ -1190,7 +1179,7 @@ pmu_done(struct adb_request *req)
(*done)(req);
}
-static void __pmac
+static void
pmu_start(void)
{
struct adb_request *req;
@@ -1214,7 +1203,7 @@ pmu_start(void)
send_byte(req->data[0]);
}
-void __openfirmware
+void
pmu_poll(void)
{
if (!via)
@@ -1224,7 +1213,7 @@ pmu_poll(void)
via_pmu_interrupt(0, NULL, NULL);
}
-void __openfirmware
+void
pmu_poll_adb(void)
{
if (!via)
@@ -1239,7 +1228,7 @@ pmu_poll_adb(void)
|| req_awaiting_reply));
}
-void __openfirmware
+void
pmu_wait_complete(struct adb_request *req)
{
if (!via)
@@ -1253,7 +1242,7 @@ pmu_wait_complete(struct adb_request *req)
* This is done to avoid spurrious shutdowns when we know we'll have
* interrupts switched off for a long time
*/
-void __openfirmware
+void
pmu_suspend(void)
{
unsigned long flags;
@@ -1293,7 +1282,7 @@ pmu_suspend(void)
} while (1);
}
-void __openfirmware
+void
pmu_resume(void)
{
unsigned long flags;
@@ -1323,7 +1312,7 @@ pmu_resume(void)
}
/* Interrupt data could be the result data from an ADB cmd */
-static void __pmac
+static void
pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
{
unsigned char ints, pirq;
@@ -1435,7 +1424,7 @@ next:
goto next;
}
-static struct adb_request* __pmac
+static struct adb_request*
pmu_sr_intr(struct pt_regs *regs)
{
struct adb_request *req;
@@ -1541,7 +1530,7 @@ pmu_sr_intr(struct pt_regs *regs)
return NULL;
}
-static irqreturn_t __pmac
+static irqreturn_t
via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
{
unsigned long flags;
@@ -1629,7 +1618,7 @@ no_free_slot:
return IRQ_RETVAL(handled);
}
-void __pmac
+void
pmu_unlock(void)
{
unsigned long flags;
@@ -1642,7 +1631,7 @@ pmu_unlock(void)
}
-static irqreturn_t __pmac
+static irqreturn_t
gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
{
unsigned long flags;
@@ -1663,12 +1652,12 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
}
#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight_to_bright[] __pmacdata = {
+static int backlight_to_bright[] = {
0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
};
-static int __openfirmware
+static int
pmu_set_backlight_enable(int on, int level, void* data)
{
struct adb_request req;
@@ -1688,7 +1677,7 @@ pmu_set_backlight_enable(int on, int level, void* data)
return 0;
}
-static void __openfirmware
+static void
pmu_bright_complete(struct adb_request *req)
{
if (req == &bright_req_1)
@@ -1697,7 +1686,7 @@ pmu_bright_complete(struct adb_request *req)
clear_bit(2, &async_req_locks);
}
-static int __openfirmware
+static int
pmu_set_backlight_level(int level, void* data)
{
if (vias == NULL)
@@ -1717,7 +1706,7 @@ pmu_set_backlight_level(int level, void* data)
}
#endif /* CONFIG_PMAC_BACKLIGHT */
-void __pmac
+void
pmu_enable_irled(int on)
{
struct adb_request req;
@@ -1732,7 +1721,7 @@ pmu_enable_irled(int on)
pmu_wait_complete(&req);
}
-void __pmac
+void
pmu_restart(void)
{
struct adb_request req;
@@ -1757,7 +1746,7 @@ pmu_restart(void)
;
}
-void __pmac
+void
pmu_shutdown(void)
{
struct adb_request req;
@@ -2074,9 +2063,12 @@ pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
n->list.next = NULL;
return 0;
}
+#endif /* CONFIG_PM */
+
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
/* Sleep is broadcast last-to-first */
-static int __pmac
+static int
broadcast_sleep(int when, int fallback)
{
int ret = PBOOK_SLEEP_OK;
@@ -2101,7 +2093,7 @@ broadcast_sleep(int when, int fallback)
}
/* Wake is broadcast first-to-last */
-static int __pmac
+static int
broadcast_wake(void)
{
int ret = PBOOK_SLEEP_OK;
@@ -2132,7 +2124,7 @@ static struct pci_save {
} *pbook_pci_saves;
static int pbook_npci_saves;
-static void __pmac
+static void
pbook_alloc_pci_save(void)
{
int npci;
@@ -2149,7 +2141,7 @@ pbook_alloc_pci_save(void)
pbook_npci_saves = npci;
}
-static void __pmac
+static void
pbook_free_pci_save(void)
{
if (pbook_pci_saves == NULL)
@@ -2159,7 +2151,7 @@ pbook_free_pci_save(void)
pbook_npci_saves = 0;
}
-static void __pmac
+static void
pbook_pci_save(void)
{
struct pci_save *ps = pbook_pci_saves;
@@ -2190,7 +2182,7 @@ pbook_pci_save(void)
* during boot, it will be in the pci dev list. If it's disabled at this point
* (and it will probably be), then you can't access it's config space.
*/
-static void __pmac
+static void
pbook_pci_restore(void)
{
u16 cmd;
@@ -2238,7 +2230,7 @@ pbook_pci_restore(void)
#ifdef DEBUG_SLEEP
/* N.B. This doesn't work on the 3400 */
-void __pmac
+void
pmu_blink(int n)
{
struct adb_request req;
@@ -2277,9 +2269,9 @@ pmu_blink(int n)
* Put the powerbook to sleep.
*/
-static u32 save_via[8] __pmacdata;
+static u32 save_via[8];
-static void __pmac
+static void
save_via_state(void)
{
save_via[0] = in_8(&via[ANH]);
@@ -2291,7 +2283,7 @@ save_via_state(void)
save_via[6] = in_8(&via[T1CL]);
save_via[7] = in_8(&via[T1CH]);
}
-static void __pmac
+static void
restore_via_state(void)
{
out_8(&via[ANH], save_via[0]);
@@ -2307,7 +2299,7 @@ restore_via_state(void)
out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
}
-static int __pmac
+static int
pmac_suspend_devices(void)
{
int ret;
@@ -2397,7 +2389,7 @@ pmac_suspend_devices(void)
return 0;
}
-static int __pmac
+static int
pmac_wakeup_devices(void)
{
mdelay(100);
@@ -2436,7 +2428,7 @@ pmac_wakeup_devices(void)
#define GRACKLE_NAP (1<<4)
#define GRACKLE_SLEEP (1<<3)
-int __pmac
+int
powerbook_sleep_grackle(void)
{
unsigned long save_l2cr;
@@ -2520,7 +2512,7 @@ powerbook_sleep_grackle(void)
return 0;
}
-static int __pmac
+static int
powerbook_sleep_Core99(void)
{
unsigned long save_l2cr;
@@ -2620,7 +2612,7 @@ powerbook_sleep_Core99(void)
#define PB3400_MEM_CTRL 0xf8000000
#define PB3400_MEM_CTRL_SLEEP 0x70
-static int __pmac
+static int
powerbook_sleep_3400(void)
{
int ret, i, x;
@@ -2698,7 +2690,7 @@ powerbook_sleep_3400(void)
return 0;
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
/*
* Support for /dev/pmu device
@@ -2720,9 +2712,9 @@ struct pmu_private {
};
static LIST_HEAD(all_pmu_pvt);
-static DEFINE_SPINLOCK(all_pvt_lock __pmacdata);
+static DEFINE_SPINLOCK(all_pvt_lock);
-static void __pmac
+static void
pmu_pass_intr(unsigned char *data, int len)
{
struct pmu_private *pp;
@@ -2751,7 +2743,7 @@ pmu_pass_intr(unsigned char *data, int len)
spin_unlock_irqrestore(&all_pvt_lock, flags);
}
-static int __pmac
+static int
pmu_open(struct inode *inode, struct file *file)
{
struct pmu_private *pp;
@@ -2773,7 +2765,7 @@ pmu_open(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t __pmac
+static ssize_t
pmu_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -2825,14 +2817,14 @@ pmu_read(struct file *file, char __user *buf,
return ret;
}
-static ssize_t __pmac
+static ssize_t
pmu_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return 0;
}
-static unsigned int __pmac
+static unsigned int
pmu_fpoll(struct file *filp, poll_table *wait)
{
struct pmu_private *pp = filp->private_data;
@@ -2849,7 +2841,7 @@ pmu_fpoll(struct file *filp, poll_table *wait)
return mask;
}
-static int __pmac
+static int
pmu_release(struct inode *inode, struct file *file)
{
struct pmu_private *pp = file->private_data;
@@ -2874,8 +2866,7 @@ pmu_release(struct inode *inode, struct file *file)
return 0;
}
-/* Note: removed __openfirmware here since it causes link errors */
-static int __pmac
+static int
pmu_ioctl(struct inode * inode, struct file *filp,
u_int cmd, u_long arg)
{
@@ -2883,7 +2874,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
int error = -EINVAL;
switch (cmd) {
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
case PMU_IOC_SLEEP:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -2911,7 +2902,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
return put_user(0, argp);
else
return put_user(1, argp);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
#ifdef CONFIG_PMAC_BACKLIGHT
/* Backlight should have its own device or go via
@@ -2957,7 +2948,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
return error;
}
-static struct file_operations pmu_device_fops __pmacdata = {
+static struct file_operations pmu_device_fops = {
.read = pmu_read,
.write = pmu_write,
.poll = pmu_fpoll,
@@ -2966,7 +2957,7 @@ static struct file_operations pmu_device_fops __pmacdata = {
.release = pmu_release,
};
-static struct miscdevice pmu_device __pmacdata = {
+static struct miscdevice pmu_device = {
PMU_MINOR, "pmu", &pmu_device_fops
};
@@ -2982,7 +2973,7 @@ device_initcall(pmu_device_init);
#ifdef DEBUG_SLEEP
-static inline void __pmac
+static inline void
polled_handshake(volatile unsigned char __iomem *via)
{
via[B] &= ~TREQ; eieio();
@@ -2993,7 +2984,7 @@ polled_handshake(volatile unsigned char __iomem *via)
;
}
-static inline void __pmac
+static inline void
polled_send_byte(volatile unsigned char __iomem *via, int x)
{
via[ACR] |= SR_OUT | SR_EXT; eieio();
@@ -3001,7 +2992,7 @@ polled_send_byte(volatile unsigned char __iomem *via, int x)
polled_handshake(via);
}
-static inline int __pmac
+static inline int
polled_recv_byte(volatile unsigned char __iomem *via)
{
int x;
@@ -3013,7 +3004,7 @@ polled_recv_byte(volatile unsigned char __iomem *via)
return x;
}
-int __pmac
+int
pmu_polled_request(struct adb_request *req)
{
unsigned long flags;
@@ -3059,13 +3050,13 @@ pmu_polled_request(struct adb_request *req)
* to do suspend-to-disk.
*/
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
static int pmu_sys_suspended = 0;
static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
{
- if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+ if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended)
return 0;
/* Suspend PMU event interrupts */
@@ -3094,7 +3085,7 @@ static int pmu_sys_resume(struct sys_device *sysdev)
return 0;
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
static struct sysdev_class pmu_sysclass = {
set_kset_name("pmu"),
@@ -3106,10 +3097,10 @@ static struct sys_device device_pmu = {
};
static struct sysdev_driver driver_pmu = {
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
.suspend = &pmu_sys_suspend,
.resume = &pmu_sys_resume,
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
};
static int __init init_pmu_sysfs(void)
@@ -3147,12 +3138,12 @@ EXPORT_SYMBOL(pmu_i2c_combined_read);
EXPORT_SYMBOL(pmu_i2c_stdsub_write);
EXPORT_SYMBOL(pmu_i2c_simple_read);
EXPORT_SYMBOL(pmu_i2c_simple_write);
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
EXPORT_SYMBOL(pmu_register_sleep_notifier);
EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
EXPORT_SYMBOL(pmu_enable_irled);
EXPORT_SYMBOL(pmu_battery_count);
EXPORT_SYMBOL(pmu_batteries);
EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM && CONFIG_PPC32 */
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 820dc52e30bc..6f80d76ac17c 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -835,7 +835,7 @@ static struct pci_save {
} *pbook_pci_saves;
static int n_pbook_pci_saves;
-static inline void __openfirmware
+static inline void
pbook_pci_save(void)
{
int npci;
@@ -863,7 +863,7 @@ pbook_pci_save(void)
}
}
-static inline void __openfirmware
+static inline void
pbook_pci_restore(void)
{
u16 cmd;
@@ -902,7 +902,7 @@ pbook_pci_restore(void)
#define IRQ_ENABLE ((unsigned int *)0xf3000024)
#define MEM_CTRL ((unsigned int *)0xf8000070)
-int __openfirmware powerbook_sleep(void)
+int powerbook_sleep(void)
{
int ret, i, x;
static int save_backlight;
@@ -1001,25 +1001,24 @@ int __openfirmware powerbook_sleep(void)
/*
* Support for /dev/pmu device
*/
-static int __openfirmware pmu_open(struct inode *inode, struct file *file)
+static int pmu_open(struct inode *inode, struct file *file)
{
return 0;
}
-static ssize_t __openfirmware pmu_read(struct file *file, char *buf,
+static ssize_t pmu_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
return 0;
}
-static ssize_t __openfirmware pmu_write(struct file *file, const char *buf,
+static ssize_t pmu_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
return 0;
}
-/* Note: removed __openfirmware here since it causes link errors */
-static int /*__openfirmware*/ pmu_ioctl(struct inode * inode, struct file *filp,
+static int pmu_ioctl(struct inode * inode, struct file *filp,
u_int cmd, u_long arg)
{
int error;
diff --git a/drivers/mca/mca-device.c b/drivers/mca/mca-device.c
index 76d430aa243f..e7adf89fae41 100644
--- a/drivers/mca/mca-device.c
+++ b/drivers/mca/mca-device.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mca.h>
+#include <linux/string.h>
/**
* mca_device_read_stored_pos - read POS register from stored data
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 70bca955e0de..01654fcabc52 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -91,7 +91,7 @@ int bitmap_active(struct bitmap *bitmap)
#define WRITE_POOL_SIZE 256
/* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+static void *write_pool_alloc(gfp_t gfp_flags, void *data)
{
return kmalloc(sizeof(struct page_list), gfp_flags);
}
@@ -270,19 +270,20 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
if (!page)
return ERR_PTR(-ENOMEM);
- do {
- ITERATE_RDEV(mddev, rdev, tmp)
- if (rdev->in_sync && !rdev->faulty)
- goto found;
- return ERR_PTR(-EIO);
- found:
+ ITERATE_RDEV(mddev, rdev, tmp) {
+ if (! rdev->in_sync || rdev->faulty)
+ continue;
+
target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
- } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+ if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+ page->index = index;
+ return page;
+ }
+ }
+ return ERR_PTR(-EIO);
- page->index = index;
- return page;
}
static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
@@ -437,6 +438,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
printk(KERN_DEBUG " daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
printk(KERN_DEBUG " sync size: %llu KB\n",
(unsigned long long)le64_to_cpu(sb->sync_size)/2);
+ printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
kunmap(bitmap->sb_page);
}
@@ -445,7 +447,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
{
char *reason = NULL;
bitmap_super_t *sb;
- unsigned long chunksize, daemon_sleep;
+ unsigned long chunksize, daemon_sleep, write_behind;
unsigned long bytes_read;
unsigned long long events;
int err = -EINVAL;
@@ -474,6 +476,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
chunksize = le32_to_cpu(sb->chunksize);
daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+ write_behind = le32_to_cpu(sb->write_behind);
/* verify that the bitmap-specific fields are valid */
if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -485,7 +488,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
else if ((1 << ffz(~chunksize)) != chunksize)
reason = "bitmap chunksize not a power of 2";
else if (daemon_sleep < 1 || daemon_sleep > 15)
- reason = "daemon sleep period out of range";
+ reason = "daemon sleep period out of range (1-15s)";
+ else if (write_behind > COUNTER_MAX)
+ reason = "write-behind limit out of range (0 - 16383)";
if (reason) {
printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
bmname(bitmap), reason);
@@ -518,8 +523,12 @@ success:
/* assign fields using values from superblock */
bitmap->chunksize = chunksize;
bitmap->daemon_sleep = daemon_sleep;
+ bitmap->daemon_lastrun = jiffies;
+ bitmap->max_write_behind = write_behind;
bitmap->flags |= sb->state;
bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+ if (sb->state & BITMAP_STALE)
+ bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
kunmap(bitmap->sb_page);
@@ -617,7 +626,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
page_cache_release(sb_page);
}
-static void bitmap_stop_daemons(struct bitmap *bitmap);
+static void bitmap_stop_daemon(struct bitmap *bitmap);
/* dequeue the next item in a page list -- don't call from irq context */
static struct page_list *dequeue_page(struct bitmap *bitmap)
@@ -659,7 +668,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
bitmap->file = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags);
- bitmap_stop_daemons(bitmap);
+ bitmap_stop_daemon(bitmap);
drain_write_queues(bitmap);
@@ -818,8 +827,7 @@ int bitmap_unplug(struct bitmap *bitmap)
return 0;
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
- unsigned long sectors, int in_sync);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file
@@ -827,8 +835,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
* if there's no bitmap file, or if the bitmap file had been
* previously kicked from the array, we mark all the bits as
* 1's in order to cause a full resync.
+ *
+ * We ignore all bits for sectors that end earlier than 'start'.
+ * This is used when reading an out-of-date bitmap...
*/
-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
{
unsigned long i, chunks, index, oldindex, bit;
struct page *page = NULL, *oldpage = NULL;
@@ -915,7 +926,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
* whole page and write it out
*/
memset(page_address(page) + offset, 0xff,
- PAGE_SIZE - offset);
+ PAGE_SIZE - offset);
ret = write_page(bitmap, page, 1);
if (ret) {
kunmap(page);
@@ -929,9 +940,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
}
if (test_bit(bit, page_address(page))) {
/* if the disk bit is set, set the memory bit */
- bitmap_set_memory_bits(bitmap,
- i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
+ ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
+ );
bit_cnt++;
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
}
@@ -1143,6 +1156,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
err = -EINTR;
goto out;
}
+ if (bitmap == NULL)
+ /* about to be stopped. */
+ return;
PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
/* wait on bitmap page writebacks */
@@ -1172,21 +1188,12 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
}
}
-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
void (*func)(mddev_t *), char *name)
{
mdk_thread_t *daemon;
- unsigned long flags;
char namebuf[32];
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = NULL;
-
- if (!bitmap->file) /* no need for daemon if there's no backing file */
- goto out_unlock;
-
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
#ifdef INJECT_FATAL_FAULT_2
daemon = NULL;
#else
@@ -1196,47 +1203,32 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
if (!daemon) {
printk(KERN_ERR "%s: failed to start bitmap daemon\n",
bmname(bitmap));
- return -ECHILD;
+ return ERR_PTR(-ECHILD);
}
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = daemon;
-
md_wakeup_thread(daemon); /* start it running */
PRINTK("%s: %s daemon (pid %d) started...\n",
bmname(bitmap), name, daemon->tsk->pid);
-out_unlock:
- spin_unlock_irqrestore(&bitmap->lock, flags);
- return 0;
-}
-static int bitmap_start_daemons(struct bitmap *bitmap)
-{
- int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
- bitmap_writeback_daemon, "bitmap_wb");
- return err;
+ return daemon;
}
-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+static void bitmap_stop_daemon(struct bitmap *bitmap)
{
- mdk_thread_t *daemon;
- unsigned long flags;
-
- spin_lock_irqsave(&bitmap->lock, flags);
- daemon = *ptr;
- *ptr = NULL;
- spin_unlock_irqrestore(&bitmap->lock, flags);
- if (daemon)
- md_unregister_thread(daemon); /* destroy the thread */
-}
+ /* the daemon can't stop itself... it'll just exit instead... */
+ if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+ current->pid != bitmap->writeback_daemon->tsk->pid) {
+ mdk_thread_t *daemon;
+ unsigned long flags;
-static void bitmap_stop_daemons(struct bitmap *bitmap)
-{
- /* the daemons can't stop themselves... they'll just exit instead... */
- if (bitmap->writeback_daemon &&
- current->pid != bitmap->writeback_daemon->tsk->pid)
- bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+ spin_lock_irqsave(&bitmap->lock, flags);
+ daemon = bitmap->writeback_daemon;
+ bitmap->writeback_daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (daemon && ! IS_ERR(daemon))
+ md_unregister_thread(daemon); /* destroy the thread */
+ }
}
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1276,9 +1268,16 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
}
}
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
{
if (!bitmap) return 0;
+
+ if (behind) {
+ atomic_inc(&bitmap->behind_writes);
+ PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
+ atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ }
+
while (sectors) {
int blocks;
bitmap_counter_t *bmc;
@@ -1313,9 +1312,15 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
}
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
- int success)
+ int success, int behind)
{
if (!bitmap) return;
+ if (behind) {
+ atomic_dec(&bitmap->behind_writes);
+ PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
+ atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ }
+
while (sectors) {
int blocks;
unsigned long flags;
@@ -1426,51 +1431,66 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
- unsigned long sectors, int in_sync)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
{
/* For each chunk covered by any of these sectors, set the
- * counter to 1 and set resync_needed unless in_sync. They should all
+ * counter to 1 and set resync_needed. They should all
* be 0 at this point
*/
- while (sectors) {
- int secs;
- bitmap_counter_t *bmc;
- spin_lock_irq(&bitmap->lock);
- bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
- if (!bmc) {
- spin_unlock_irq(&bitmap->lock);
- return;
- }
- if (! *bmc) {
- struct page *page;
- *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
- bitmap_count_page(bitmap, offset, 1);
- page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
- }
+
+ int secs;
+ bitmap_counter_t *bmc;
+ spin_lock_irq(&bitmap->lock);
+ bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+ if (!bmc) {
spin_unlock_irq(&bitmap->lock);
- if (sectors > secs)
- sectors -= secs;
- else
- sectors = 0;
+ return;
+ }
+ if (! *bmc) {
+ struct page *page;
+ *bmc = 1 | (needed?NEEDED_MASK:0);
+ bitmap_count_page(bitmap, offset, 1);
+ page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
+ spin_unlock_irq(&bitmap->lock);
+
+}
+
+/*
+ * flush out any pending updates
+ */
+void bitmap_flush(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+ int sleep;
+
+ if (!bitmap) /* there was no bitmap */
+ return;
+
+ /* run the daemon_work three time to ensure everything is flushed
+ * that can be
+ */
+ sleep = bitmap->daemon_sleep;
+ bitmap->daemon_sleep = 0;
+ bitmap_daemon_work(bitmap);
+ bitmap_daemon_work(bitmap);
+ bitmap_daemon_work(bitmap);
+ bitmap->daemon_sleep = sleep;
+ bitmap_update_sb(bitmap);
}
/*
* free memory that was allocated
*/
-void bitmap_destroy(mddev_t *mddev)
+static void bitmap_free(struct bitmap *bitmap)
{
unsigned long k, pages;
struct bitmap_page *bp;
- struct bitmap *bitmap = mddev->bitmap;
if (!bitmap) /* there was no bitmap */
return;
- mddev->bitmap = NULL; /* disconnect from the md device */
-
/* release the bitmap file and kill the daemon */
bitmap_file_put(bitmap);
@@ -1488,6 +1508,17 @@ void bitmap_destroy(mddev_t *mddev)
kfree(bp);
kfree(bitmap);
}
+void bitmap_destroy(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+
+ if (!bitmap) /* there was no bitmap */
+ return;
+
+ mddev->bitmap = NULL; /* disconnect from the md device */
+
+ bitmap_free(bitmap);
+}
/*
* initialize the bitmap structure
@@ -1501,6 +1532,7 @@ int bitmap_create(mddev_t *mddev)
unsigned long pages;
struct file *file = mddev->bitmap_file;
int err;
+ sector_t start;
BUG_ON(sizeof(bitmap_super_t) != 256);
@@ -1517,15 +1549,15 @@ int bitmap_create(mddev_t *mddev)
spin_lock_init(&bitmap->lock);
bitmap->mddev = mddev;
- mddev->bitmap = bitmap;
spin_lock_init(&bitmap->write_lock);
INIT_LIST_HEAD(&bitmap->complete_pages);
init_waitqueue_head(&bitmap->write_wait);
bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
write_pool_free, NULL);
+ err = -ENOMEM;
if (!bitmap->write_pool)
- return -ENOMEM;
+ goto error;
bitmap->file = file;
bitmap->offset = mddev->bitmap_offset;
@@ -1533,7 +1565,7 @@ int bitmap_create(mddev_t *mddev)
/* read superblock from bitmap file (this sets bitmap->chunksize) */
err = bitmap_read_sb(bitmap);
if (err)
- return err;
+ goto error;
bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
sizeof(bitmap->chunksize));
@@ -1557,26 +1589,44 @@ int bitmap_create(mddev_t *mddev)
#else
bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
#endif
+ err = -ENOMEM;
if (!bitmap->bp)
- return -ENOMEM;
+ goto error;
memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
bitmap->flags |= BITMAP_ACTIVE;
/* now that we have some pages available, initialize the in-memory
* bitmap from the on-disk bitmap */
- err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+ start = 0;
+ if (mddev->degraded == 0
+ || bitmap->events_cleared == mddev->events)
+ /* no need to keep dirty bits to optimise a re-add of a missing device */
+ start = mddev->recovery_cp;
+ err = bitmap_init_from_disk(bitmap, start);
+
if (err)
- return err;
+ goto error;
printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
pages, bmname(bitmap));
- /* kick off the bitmap daemons */
- err = bitmap_start_daemons(bitmap);
- if (err)
- return err;
+ mddev->bitmap = bitmap;
+
+ if (file)
+ /* kick off the bitmap writeback daemon */
+ bitmap->writeback_daemon =
+ bitmap_start_daemon(bitmap,
+ bitmap_writeback_daemon,
+ "bitmap_wb");
+
+ if (IS_ERR(bitmap->writeback_daemon))
+ return PTR_ERR(bitmap->writeback_daemon);
return bitmap_update_sb(bitmap);
+
+ error:
+ bitmap_free(bitmap);
+ return err;
}
/* the bitmap API -- for raid personalities */
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index d0a4bab220e5..cf6631056683 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -15,7 +15,7 @@
#include <linux/crypto.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/page.h>
#include "dm.h"
@@ -96,7 +96,7 @@ static kmem_cache_t *_crypt_io_pool;
/*
* Mempool alloc and free functions for the page
*/
-static void *mempool_alloc_page(unsigned int __nocast gfp_mask, void *data)
+static void *mempool_alloc_page(gfp_t gfp_mask, void *data)
{
return alloc_page(gfp_mask);
}
@@ -144,7 +144,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
}
/* Hash the cipher key with the given hash algorithm */
- hash_tfm = crypto_alloc_tfm(opts, 0);
+ hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP);
if (hash_tfm == NULL) {
ti->error = PFX "Error initializing ESSIV hash";
return -EINVAL;
@@ -164,15 +164,14 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
return -ENOMEM;
}
- sg.page = virt_to_page(cc->key);
- sg.offset = offset_in_page(cc->key);
- sg.length = cc->key_size;
+ sg_set_buf(&sg, cc->key, cc->key_size);
crypto_digest_digest(hash_tfm, &sg, 1, salt);
crypto_free_tfm(hash_tfm);
/* Setup the essiv_tfm with the given salt */
essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm),
- CRYPTO_TFM_MODE_ECB);
+ CRYPTO_TFM_MODE_ECB |
+ CRYPTO_TFM_REQ_MAY_SLEEP);
if (essiv_tfm == NULL) {
ti->error = PFX "Error allocating crypto tfm for ESSIV";
kfree(salt);
@@ -206,14 +205,12 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc)
static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
{
- struct scatterlist sg = { NULL, };
+ struct scatterlist sg;
memset(iv, 0, cc->iv_size);
*(u64 *)iv = cpu_to_le64(sector);
- sg.page = virt_to_page(iv);
- sg.offset = offset_in_page(iv);
- sg.length = cc->iv_size;
+ sg_set_buf(&sg, iv, cc->iv_size);
crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private,
&sg, &sg, cc->iv_size);
@@ -330,7 +327,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
{
struct bio *bio;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+ gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
unsigned int i;
/*
@@ -587,7 +584,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad1;
}
- tfm = crypto_alloc_tfm(cipher, crypto_flags);
+ tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP);
if (!tfm) {
ti->error = PFX "Error allocating crypto tfm";
goto bad1;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 17212b4201a1..cc07bbebbb16 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -568,12 +568,9 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
bad:
dm_io_put(sectors_to_pages(chunk_size));
- if (ps) {
- if (ps->area)
- free_area(ps);
-
- kfree(ps);
- }
+ if (ps && ps->area)
+ free_area(ps);
+ kfree(ps);
return r;
}
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 45754bb6a799..4809b209fbb1 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -32,7 +32,7 @@ struct io {
static unsigned _num_ios;
static mempool_t *_io_pool;
-static void *alloc_io(unsigned int __nocast gfp_mask, void *pool_data)
+static void *alloc_io(gfp_t gfp_mask, void *pool_data)
{
return kmalloc(sizeof(struct io), gfp_mask);
}
@@ -239,6 +239,11 @@ static void vm_dp_init(struct dpages *dp, void *data)
dp->context_ptr = data;
}
+static void dm_bio_destructor(struct bio *bio)
+{
+ bio_free(bio, _bios);
+}
+
/*-----------------------------------------------------------------
* IO routines that accept a list of pages.
*---------------------------------------------------------------*/
@@ -263,6 +268,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
bio->bi_bdev = where->bdev;
bio->bi_end_io = endio;
bio->bi_private = io;
+ bio->bi_destructor = dm_bio_destructor;
bio_set_region(bio, region);
/*
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 200a0688f717..54ec737195e0 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi
static void __hash_remove(struct hash_cell *hc)
{
+ struct dm_table *table;
+
/* remove from the dev hash */
list_del(&hc->uuid_list);
list_del(&hc->name_list);
unregister_with_devfs(hc);
dm_set_mdptr(hc->md, NULL);
+
+ table = dm_get_table(hc->md);
+ if (table) {
+ dm_table_event(table);
+ dm_table_put(table);
+ }
+
dm_put(hc->md);
if (hc->new_map)
dm_table_put(hc->new_map);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 785806bdb248..f9b7b32d5d5c 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
/*
* If we run out of usable paths, should we queue I/O or error it?
*/
-static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path)
+static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
+ unsigned save_old_value)
{
unsigned long flags;
spin_lock_irqsave(&m->lock, flags);
- m->saved_queue_if_no_path = m->queue_if_no_path;
+ if (save_old_value)
+ m->saved_queue_if_no_path = m->queue_if_no_path;
+ else
+ m->saved_queue_if_no_path = queue_if_no_path;
m->queue_if_no_path = queue_if_no_path;
if (!m->queue_if_no_path && m->queue_size)
queue_work(kmultipathd, &m->process_queued_ios);
@@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m,
return 0;
if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
- return queue_if_no_path(m, 1);
+ return queue_if_no_path(m, 1, 0);
else {
ti->error = "Unrecognised multipath feature request";
return -EINVAL;
@@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti)
{
struct multipath *m = (struct multipath *) ti->private;
- queue_if_no_path(m, 0);
+ queue_if_no_path(m, 0, 1);
}
/*
@@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
if (argc == 1) {
if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
- return queue_if_no_path(m, 1);
+ return queue_if_no_path(m, 1, 0);
else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
- return queue_if_no_path(m, 0);
+ return queue_if_no_path(m, 0, 0);
}
if (argc != 2)
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 12031c9d3f1e..2375709a392c 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -122,7 +122,7 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
/* FIXME move this */
static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
-static void *region_alloc(unsigned int __nocast gfp_mask, void *pool_data)
+static void *region_alloc(gfp_t gfp_mask, void *pool_data)
{
return kmalloc(sizeof(struct region), gfp_mask);
}
@@ -375,16 +375,18 @@ static void rh_inc(struct region_hash *rh, region_t region)
read_lock(&rh->hash_lock);
reg = __rh_find(rh, region);
+
+ atomic_inc(&reg->pending);
+
+ spin_lock_irq(&rh->region_lock);
if (reg->state == RH_CLEAN) {
rh->log->type->mark_region(rh->log, reg->key);
- spin_lock_irq(&rh->region_lock);
reg->state = RH_DIRTY;
list_del_init(&reg->list); /* take off the clean list */
- spin_unlock_irq(&rh->region_lock);
}
+ spin_unlock_irq(&rh->region_lock);
- atomic_inc(&reg->pending);
read_unlock(&rh->hash_lock);
}
@@ -408,6 +410,10 @@ static void rh_dec(struct region_hash *rh, region_t region)
if (atomic_dec_and_test(&reg->pending)) {
spin_lock_irqsave(&rh->region_lock, flags);
+ if (atomic_read(&reg->pending)) { /* check race */
+ spin_unlock_irqrestore(&rh->region_lock, flags);
+ return;
+ }
if (reg->state == RH_RECOVERING) {
list_add_tail(&reg->list, &rh->quiesced_regions);
} else {
@@ -1230,7 +1236,7 @@ static int __init dm_mirror_init(void)
if (r)
return r;
- _kmirrord_wq = create_workqueue("kmirrord");
+ _kmirrord_wq = create_singlethread_workqueue("kmirrord");
if (!_kmirrord_wq) {
DMERR("couldn't start kmirrord");
dm_dirty_log_exit();
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d487d9deb98e..930b9fc27953 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -399,6 +399,11 @@ struct clone_info {
unsigned short idx;
};
+static void dm_bio_destructor(struct bio *bio)
+{
+ bio_free(bio, dm_set);
+}
+
/*
* Creates a little bio that is just does part of a bvec.
*/
@@ -410,6 +415,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
struct bio_vec *bv = bio->bi_io_vec + idx;
clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set);
+ clone->bi_destructor = dm_bio_destructor;
*clone->bi_io_vec = *bv;
clone->bi_sector = sector;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 8d740013d74d..946efef3a8f5 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -38,7 +38,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
/*
* sector_div(a,b) returns the remainer and sets a to a/b
*/
- (void)sector_div(block, conf->smallest->size);
+ block >>= conf->preshift;
+ (void)sector_div(block, conf->hash_spacing);
hash = conf->hash_table[block];
while ((sector>>1) >= (hash->size + hash->offset))
@@ -47,7 +48,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
}
/**
- * linear_mergeable_bvec -- tell bio layer if a two requests can be merged
+ * linear_mergeable_bvec -- tell bio layer if two requests can be merged
* @q: request queue
* @bio: the buffer head that's been built up so far
* @biovec: the request that could be merged to it.
@@ -116,7 +117,7 @@ static int linear_run (mddev_t *mddev)
dev_info_t **table;
mdk_rdev_t *rdev;
int i, nb_zone, cnt;
- sector_t start;
+ sector_t min_spacing;
sector_t curr_offset;
struct list_head *tmp;
@@ -127,11 +128,6 @@ static int linear_run (mddev_t *mddev)
memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
mddev->private = conf;
- /*
- * Find the smallest device.
- */
-
- conf->smallest = NULL;
cnt = 0;
mddev->array_size = 0;
@@ -159,8 +155,6 @@ static int linear_run (mddev_t *mddev)
disk->size = rdev->size;
mddev->array_size += rdev->size;
- if (!conf->smallest || (disk->size < conf->smallest->size))
- conf->smallest = disk;
cnt++;
}
if (cnt != mddev->raid_disks) {
@@ -168,6 +162,36 @@ static int linear_run (mddev_t *mddev)
goto out;
}
+ min_spacing = mddev->array_size;
+ sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+
+ /* min_spacing 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
+ * the actual spacing
+ */
+ conf->hash_spacing = mddev->array_size;
+ for (i=0; i < cnt-1 ; i++) {
+ sector_t sz = 0;
+ int j;
+ for (j=i; i<cnt-1 && sz < min_spacing ; j++)
+ sz += conf->disks[j].size;
+ if (sz >= min_spacing && sz < conf->hash_spacing)
+ conf->hash_spacing = sz;
+ }
+
+ /* hash_spacing may be too large for sector_div to work with,
+ * so we might need to pre-shift
+ */
+ conf->preshift = 0;
+ if (sizeof(sector_t) > sizeof(u32)) {
+ sector_t space = conf->hash_spacing;
+ while (space > (sector_t)(~(u32)0)) {
+ space >>= 1;
+ conf->preshift++;
+ }
+ }
/*
* This code was restructured to work around a gcc-2.95.3 internal
* compiler error. Alter it with care.
@@ -177,39 +201,52 @@ static int linear_run (mddev_t *mddev)
unsigned round;
unsigned long base;
- sz = mddev->array_size;
- base = conf->smallest->size;
+ sz = mddev->array_size >> conf->preshift;
+ sz += 1; /* force round-up */
+ base = conf->hash_spacing >> conf->preshift;
round = sector_div(sz, base);
- nb_zone = conf->nr_zones = sz + (round ? 1 : 0);
+ nb_zone = sz + (round ? 1 : 0);
}
-
- conf->hash_table = kmalloc (sizeof (dev_info_t*) * nb_zone,
+ BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
+
+ conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
GFP_KERNEL);
if (!conf->hash_table)
goto out;
/*
* Here we generate the linear hash table
+ * First calculate the device offsets.
*/
+ conf->disks[0].offset = 0;
+ for (i=1; i<mddev->raid_disks; i++)
+ conf->disks[i].offset =
+ conf->disks[i-1].offset +
+ conf->disks[i-1].size;
+
table = conf->hash_table;
- start = 0;
curr_offset = 0;
- for (i = 0; i < cnt; i++) {
- dev_info_t *disk = conf->disks + i;
+ i = 0;
+ for (curr_offset = 0;
+ curr_offset < mddev->array_size;
+ curr_offset += conf->hash_spacing) {
- disk->offset = curr_offset;
- curr_offset += disk->size;
+ while (i < mddev->raid_disks-1 &&
+ curr_offset >= conf->disks[i+1].offset)
+ i++;
+
+ *table ++ = conf->disks + i;
+ }
- /* 'curr_offset' is the end of this disk
- * 'start' is the start of table
+ if (conf->preshift) {
+ conf->hash_spacing >>= conf->preshift;
+ /* round hash_spacing up so that when we divide by it,
+ * we err on the side of "too-low", which is safest.
*/
- while (start < curr_offset) {
- *table++ = disk;
- start += conf->smallest->size;
- }
+ conf->hash_spacing++;
}
- if (table-conf->hash_table != nb_zone)
- BUG();
+
+ BUG_ON(table - conf->hash_table > nb_zone);
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->unplug_fn = linear_unplug;
@@ -234,18 +271,19 @@ static int linear_stop (mddev_t *mddev)
static int linear_make_request (request_queue_t *q, struct bio *bio)
{
+ const int rw = bio_data_dir(bio);
mddev_t *mddev = q->queuedata;
dev_info_t *tmp_dev;
sector_t block;
- if (bio_data_dir(bio)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
}
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+
tmp_dev = which_dev(mddev, bio->bi_sector);
block = bio->bi_sector >> 1;
@@ -294,7 +332,7 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
sector_t s = 0;
seq_printf(seq, " ");
- for (j = 0; j < conf->nr_zones; j++)
+ for (j = 0; j < mddev->raid_disks; j++)
{
char b[BDEVNAME_SIZE];
s += conf->smallest_size;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6580e0fa4a47..9ecf51ee596f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/config.h>
+#include <linux/kthread.h>
#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/raid/bitmap.h>
@@ -73,7 +74,7 @@ static DEFINE_SPINLOCK(pers_lock);
* Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit'
* is 1000 KB/sec, so the extra system load does not show up that much.
* Increase it if you want to have more _guaranteed_ speed. Note that
- * the RAID driver will use the maximum available bandwith if the IO
+ * the RAID driver will use the maximum available bandwidth if the IO
* subsystem is idle. There is also an 'absolute maximum' reconstruction
* speed limit - in case reconstruction slows down your system despite
* idle IO detection.
@@ -256,8 +257,7 @@ static inline void mddev_unlock(mddev_t * mddev)
{
up(&mddev->reconfig_sem);
- if (mddev->thread)
- md_wakeup_thread(mddev->thread);
+ md_wakeup_thread(mddev->thread);
}
mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
@@ -394,7 +394,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
return ret;
}
-static int read_disk_sb(mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev, int size)
{
char b[BDEVNAME_SIZE];
if (!rdev->sb_page) {
@@ -405,7 +405,7 @@ static int read_disk_sb(mdk_rdev_t * rdev)
return 0;
- if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
+ if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
goto fail;
rdev->sb_loaded = 1;
return 0;
@@ -532,7 +532,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ ret = read_disk_sb(rdev, MD_SB_BYTES);
if (ret) return ret;
ret = -EINVAL;
@@ -565,6 +565,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
rdev->preferred_minor = sb->md_minor;
rdev->data_offset = 0;
+ rdev->sb_size = MD_SB_BYTES;
if (sb->level == LEVEL_MULTIPATH)
rdev->desc_nr = -1;
@@ -623,6 +624,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->raid_disks = sb->raid_disks;
mddev->size = sb->size;
mddev->events = md_event(sb);
+ mddev->bitmap_offset = 0;
+ mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
if (sb->state & (1<<MD_SB_CLEAN))
mddev->recovery_cp = MaxSector;
@@ -643,12 +646,12 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1) {
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps only support for raid1\n");
return -EINVAL;
}
- mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+ mddev->bitmap_offset = mddev->default_bitmap_offset;
}
} else if (mddev->pers == NULL) {
@@ -669,6 +672,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (mddev->level != LEVEL_MULTIPATH) {
rdev->faulty = 0;
+ rdev->flags = 0;
desc = sb->disks + rdev->desc_nr;
if (desc->state & (1<<MD_DISK_FAULTY))
@@ -678,6 +682,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 1;
rdev->raid_disk = desc->raid_disk;
}
+ if (desc->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
} else /* MULTIPATH are always insync */
rdev->in_sync = 1;
return 0;
@@ -706,6 +712,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
int i;
int active=0, working=0,failed=0,spare=0,nr_disks=0;
+ rdev->sb_size = MD_SB_BYTES;
+
sb = (mdp_super_t*)page_address(rdev->sb_page);
memset(sb, 0, sizeof(*sb));
@@ -776,6 +784,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
spare++;
working++;
}
+ if (test_bit(WriteMostly, &rdev2->flags))
+ d->state |= (1<<MD_DISK_WRITEMOSTLY);
}
/* now set the "removed" and "faulty" bits on any missing devices */
@@ -831,6 +841,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
int ret;
sector_t sb_offset;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+ int bmask;
/*
* Calculate the position of the superblock.
@@ -859,7 +870,10 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
}
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ /* superblock is rarely larger than 1K, but it can be larger,
+ * and it is safe to read 4k, so we do that
+ */
+ ret = read_disk_sb(rdev, 4096);
if (ret) return ret;
@@ -869,7 +883,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
sb->major_version != cpu_to_le32(1) ||
le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
- sb->feature_map != 0)
+ (le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
return -EINVAL;
if (calc_sb_1_csum(sb) != sb->sb_csum) {
@@ -885,6 +899,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
+ rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
+ bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+ if (rdev->sb_size & bmask)
+ rdev-> sb_size = (rdev->sb_size | bmask)+1;
+
if (refdev == 0)
return 1;
else {
@@ -938,13 +957,16 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events);
+ mddev->bitmap_offset = 0;
+ mddev->default_bitmap_offset = 0;
+ mddev->default_bitmap_offset = 1024;
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
memcpy(mddev->uuid, sb->set_uuid, 16);
mddev->max_disks = (4096-256)/2;
- if ((le32_to_cpu(sb->feature_map) & 1) &&
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
mddev->bitmap_file == NULL ) {
if (mddev->level != 1) {
printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
@@ -985,6 +1007,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->raid_disk = role;
break;
}
+ rdev->flags = 0;
+ if (sb->devflags & WriteMostly1)
+ set_bit(WriteMostly, &rdev->flags);
} else /* MULTIPATH are always insync */
rdev->in_sync = 1;
@@ -1016,7 +1041,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
if (mddev->bitmap && mddev->bitmap_file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
- sb->feature_map = cpu_to_le32(1);
+ sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
max_dev = 0;
@@ -1362,7 +1387,7 @@ repeat:
dprintk("%s ", bdevname(rdev->bdev,b));
if (!rdev->faulty) {
md_super_write(mddev,rdev,
- rdev->sb_offset<<1, MD_SB_BYTES,
+ rdev->sb_offset<<1, rdev->sb_size,
rdev->sb_page);
dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
bdevname(rdev->bdev,b),
@@ -1688,6 +1713,7 @@ static int do_md_run(mddev_t * mddev)
mddev->pers = pers[pnum];
spin_unlock(&pers_lock);
+ mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
/* before we start the array running, initialise the bitmap */
@@ -1712,6 +1738,7 @@ static int do_md_run(mddev_t * mddev)
mddev->in_sync = 1;
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_wakeup_thread(mddev->thread);
if (mddev->sb_dirty)
md_update_sb(mddev);
@@ -1798,6 +1825,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
goto out;
mddev->ro = 1;
} else {
+ bitmap_flush(mddev);
+ wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
if (mddev->ro)
set_disk_ro(disk, 0);
blk_queue_make_request(mddev->queue, md_fail_request);
@@ -1822,6 +1851,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
fput(mddev->bitmap_file);
mddev->bitmap_file = NULL;
}
+ mddev->bitmap_offset = 0;
/*
* Free resources if final stop
@@ -2067,6 +2097,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
info.state = 0;
if (mddev->in_sync)
info.state = (1<<MD_SB_CLEAN);
+ if (mddev->bitmap && mddev->bitmap_offset)
+ info.state = (1<<MD_SB_BITMAP_PRESENT);
info.active_disks = active;
info.working_disks = working;
info.failed_disks = failed;
@@ -2081,7 +2113,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
return 0;
}
-static int get_bitmap_file(mddev_t * mddev, void * arg)
+static int get_bitmap_file(mddev_t * mddev, void __user * arg)
{
mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
char *ptr, *buf = NULL;
@@ -2140,6 +2172,8 @@ static int get_disk_info(mddev_t * mddev, void __user * arg)
info.state |= (1<<MD_DISK_ACTIVE);
info.state |= (1<<MD_DISK_SYNC);
}
+ if (test_bit(WriteMostly, &rdev->flags))
+ info.state |= (1<<MD_DISK_WRITEMOSTLY);
} else {
info.major = info.minor = 0;
info.raid_disk = -1;
@@ -2204,8 +2238,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
mdname(mddev));
return -EINVAL;
}
- rdev = md_import_device(dev, mddev->major_version,
- mddev->minor_version);
+ if (mddev->persistent)
+ rdev = md_import_device(dev, mddev->major_version,
+ mddev->minor_version);
+ else
+ rdev = md_import_device(dev, -1, -1);
if (IS_ERR(rdev)) {
printk(KERN_WARNING
"md: md_import_device returned %ld\n",
@@ -2225,14 +2262,16 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
rdev->saved_raid_disk = rdev->raid_disk;
rdev->in_sync = 0; /* just to be sure */
+ if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
+
rdev->raid_disk = -1;
err = bind_rdev_to_array(rdev, mddev);
if (err)
export_rdev(rdev);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- if (mddev->thread)
- md_wakeup_thread(mddev->thread);
+ md_wakeup_thread(mddev->thread);
return err;
}
@@ -2266,6 +2305,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
else
rdev->in_sync = 0;
+ if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+ set_bit(WriteMostly, &rdev->flags);
+
err = bind_rdev_to_array(rdev, mddev);
if (err) {
export_rdev(rdev);
@@ -2425,25 +2467,51 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
{
int err;
- if (mddev->pers)
- return -EBUSY;
+ if (mddev->pers) {
+ if (!mddev->pers->quiesce)
+ return -EBUSY;
+ if (mddev->recovery || mddev->sync_thread)
+ return -EBUSY;
+ /* we should be able to change the bitmap.. */
+ }
- mddev->bitmap_file = fget(fd);
- if (mddev->bitmap_file == NULL) {
- printk(KERN_ERR "%s: error: failed to get bitmap file\n",
- mdname(mddev));
- return -EBADF;
- }
+ if (fd >= 0) {
+ if (mddev->bitmap)
+ return -EEXIST; /* cannot add when bitmap is present */
+ mddev->bitmap_file = fget(fd);
- err = deny_bitmap_write_access(mddev->bitmap_file);
- if (err) {
- printk(KERN_ERR "%s: error: bitmap file is already in use\n",
- mdname(mddev));
- fput(mddev->bitmap_file);
- mddev->bitmap_file = NULL;
- } else
+ if (mddev->bitmap_file == NULL) {
+ printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+ mdname(mddev));
+ return -EBADF;
+ }
+
+ err = deny_bitmap_write_access(mddev->bitmap_file);
+ if (err) {
+ printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+ mdname(mddev));
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ return err;
+ }
mddev->bitmap_offset = 0; /* file overrides offset */
+ } else if (mddev->bitmap == NULL)
+ return -ENOENT; /* cannot remove what isn't there */
+ err = 0;
+ if (mddev->pers) {
+ mddev->pers->quiesce(mddev, 1);
+ if (fd >= 0)
+ err = bitmap_create(mddev);
+ if (fd < 0 || err)
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ } else if (fd < 0) {
+ if (mddev->bitmap_file)
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ }
+
return err;
}
@@ -2523,6 +2591,11 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
{
int rv = 0;
int cnt = 0;
+ int state = 0;
+
+ /* calculate expected state,ignoring low bits */
+ if (mddev->bitmap && mddev->bitmap_offset)
+ state |= (1 << MD_SB_BITMAP_PRESENT);
if (mddev->major_version != info->major_version ||
mddev->minor_version != info->minor_version ||
@@ -2531,12 +2604,16 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
mddev->level != info->level ||
/* mddev->layout != info->layout || */
!mddev->persistent != info->not_persistent||
- mddev->chunk_size != info->chunk_size )
+ mddev->chunk_size != info->chunk_size ||
+ /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
+ ((state^info->state) & 0xfffffe00)
+ )
return -EINVAL;
/* Check there is only one change */
if (mddev->size != info->size) cnt++;
if (mddev->raid_disks != info->raid_disks) cnt++;
if (mddev->layout != info->layout) cnt++;
+ if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
if (cnt == 0) return 0;
if (cnt > 1) return -EINVAL;
@@ -2615,6 +2692,35 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
}
}
}
+ if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (mddev->recovery || mddev->sync_thread)
+ return -EBUSY;
+ if (info->state & (1<<MD_SB_BITMAP_PRESENT)) {
+ /* add the bitmap */
+ if (mddev->bitmap)
+ return -EEXIST;
+ if (mddev->default_bitmap_offset == 0)
+ return -EINVAL;
+ mddev->bitmap_offset = mddev->default_bitmap_offset;
+ mddev->pers->quiesce(mddev, 1);
+ rv = bitmap_create(mddev);
+ if (rv)
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ } else {
+ /* remove the bitmap */
+ if (!mddev->bitmap)
+ return -ENOENT;
+ if (mddev->bitmap->file)
+ return -EINVAL;
+ mddev->pers->quiesce(mddev, 1);
+ bitmap_destroy(mddev);
+ mddev->pers->quiesce(mddev, 0);
+ mddev->bitmap_offset = 0;
+ }
+ }
md_update_sb(mddev);
return rv;
}
@@ -2776,7 +2882,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case GET_BITMAP_FILE:
- err = get_bitmap_file(mddev, (void *)arg);
+ err = get_bitmap_file(mddev, argp);
goto done_unlock;
case GET_DISK_INFO:
@@ -2945,18 +3051,6 @@ static int md_thread(void * arg)
{
mdk_thread_t *thread = arg;
- lock_kernel();
-
- /*
- * Detach thread
- */
-
- daemonize(thread->name, mdname(thread->mddev));
-
- current->exit_signal = SIGCHLD;
- allow_signal(SIGKILL);
- thread->tsk = current;
-
/*
* md_thread is a 'system-thread', it's priority should be very
* high. We avoid resource deadlocks individually in each
@@ -2968,14 +3062,15 @@ static int md_thread(void * arg)
* bdflush, otherwise bdflush will deadlock if there are too
* many dirty RAID5 blocks.
*/
- unlock_kernel();
+ allow_signal(SIGKILL);
complete(thread->event);
- while (thread->run) {
+ while (!kthread_should_stop()) {
void (*run)(mddev_t *);
wait_event_interruptible_timeout(thread->wqueue,
- test_bit(THREAD_WAKEUP, &thread->flags),
+ test_bit(THREAD_WAKEUP, &thread->flags)
+ || kthread_should_stop(),
thread->timeout);
try_to_freeze();
@@ -2984,11 +3079,8 @@ static int md_thread(void * arg)
run = thread->run;
if (run)
run(thread->mddev);
-
- if (signal_pending(current))
- flush_signals(current);
}
- complete(thread->event);
+
return 0;
}
@@ -3005,11 +3097,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
const char *name)
{
mdk_thread_t *thread;
- int ret;
struct completion event;
- thread = (mdk_thread_t *) kmalloc
- (sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
@@ -3022,8 +3112,8 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
thread->mddev = mddev;
thread->name = name;
thread->timeout = MAX_SCHEDULE_TIMEOUT;
- ret = kernel_thread(md_thread, thread, 0);
- if (ret < 0) {
+ thread->tsk = kthread_run(md_thread, thread, name, mdname(thread->mddev));
+ if (IS_ERR(thread->tsk)) {
kfree(thread);
return NULL;
}
@@ -3033,21 +3123,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
void md_unregister_thread(mdk_thread_t *thread)
{
- struct completion event;
-
- init_completion(&event);
-
- thread->event = &event;
-
- /* As soon as ->run is set to NULL, the task could disappear,
- * so we need to hold tasklist_lock until we have sent the signal
- */
dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
- read_lock(&tasklist_lock);
- thread->run = NULL;
- send_sig(SIGKILL, thread->tsk, 1);
- read_unlock(&tasklist_lock);
- wait_for_completion(&event);
+
+ kthread_stop(thread->tsk);
kfree(thread);
}
@@ -3254,10 +3332,13 @@ static int md_seq_show(struct seq_file *seq, void *v)
char b[BDEVNAME_SIZE];
seq_printf(seq, " %s[%d]",
bdevname(rdev->bdev,b), rdev->desc_nr);
+ if (test_bit(WriteMostly, &rdev->flags))
+ seq_printf(seq, "(W)");
if (rdev->faulty) {
seq_printf(seq, "(F)");
continue;
- }
+ } else if (rdev->raid_disk < 0)
+ seq_printf(seq, "(S)"); /* spare */
size += rdev->size;
}
@@ -3269,6 +3350,15 @@ static int md_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n %llu blocks",
(unsigned long long)size);
}
+ if (mddev->persistent) {
+ if (mddev->major_version != 0 ||
+ mddev->minor_version != 90) {
+ seq_printf(seq," super %d.%d",
+ mddev->major_version,
+ mddev->minor_version);
+ }
+ } else
+ seq_printf(seq, " super non-persistent");
if (mddev->pers) {
mddev->pers->status (seq, mddev);
@@ -3376,8 +3466,8 @@ static int is_mddev_idle(mddev_t *mddev)
idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
- curr_events = disk_stat_read(disk, read_sectors) +
- disk_stat_read(disk, write_sectors) -
+ curr_events = disk_stat_read(disk, sectors[0]) +
+ disk_stat_read(disk, sectors[1]) -
atomic_read(&disk->sync_io);
/* Allow some slack between valud of curr_events and last_events,
* as there are some uninteresting races.
@@ -3411,7 +3501,6 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
*/
void md_write_start(mddev_t *mddev, struct bio *bi)
{
- DEFINE_WAIT(w);
if (bio_data_dir(bi) != WRITE)
return;
@@ -3479,12 +3568,13 @@ static void md_do_sync(mddev_t *mddev)
mddev->curr_resync = 2;
try_again:
- if (signal_pending(current)) {
+ if (signal_pending(current) ||
+ kthread_should_stop()) {
flush_signals(current);
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
goto skip;
}
ITERATE_MDDEV(mddev2,tmp) {
- printk(".");
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync &&
@@ -3501,8 +3591,9 @@ static void md_do_sync(mddev_t *mddev)
*/
continue;
prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE);
- if (!signal_pending(current)
- && mddev2->curr_resync >= mddev->curr_resync) {
+ if (!signal_pending(current) &&
+ !kthread_should_stop() &&
+ mddev2->curr_resync >= mddev->curr_resync) {
printk(KERN_INFO "md: delaying resync of %s"
" until %s has finished resync (they"
" share one or more physical units)\n",
@@ -3529,7 +3620,7 @@ static void md_do_sync(mddev_t *mddev)
printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
" %d KB/sec/disc.\n", sysctl_speed_limit_min);
- printk(KERN_INFO "md: using maximum available idle IO bandwith "
+ printk(KERN_INFO "md: using maximum available idle IO bandwidth "
"(but not more than %d KB/sec) for reconstruction.\n",
sysctl_speed_limit_max);
@@ -3608,7 +3699,7 @@ static void md_do_sync(mddev_t *mddev)
}
- if (signal_pending(current)) {
+ if (signal_pending(current) || kthread_should_stop()) {
/*
* got a signal, exit.
*/
@@ -4007,3 +4098,5 @@ EXPORT_SYMBOL(md_wakeup_thread);
EXPORT_SYMBOL(md_print_devices);
EXPORT_SYMBOL(md_check_recovery);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("md");
+MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 2d2ca7fa0265..c06f4474192b 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -38,7 +38,7 @@
static mdk_personality_t multipath_personality;
-static void *mp_pool_alloc(unsigned int __nocast gfp_flags, void *data)
+static void *mp_pool_alloc(gfp_t gfp_flags, void *data)
{
struct multipath_bh *mpb;
mpb = kmalloc(sizeof(*mpb), gfp_flags);
@@ -168,19 +168,20 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
multipath_conf_t *conf = mddev_to_conf(mddev);
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
+ const int rw = bio_data_dir(bio);
+
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
mp_bh->master_bio = bio;
mp_bh->mddev = mddev;
- if (bio_data_dir(bio)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
- }
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
mp_bh->path = multipath_map(conf);
if (mp_bh->path < 0) {
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 2120710172c5..fece3277c2a5 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -403,15 +403,16 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
mdk_rdev_t *tmp_dev;
unsigned long chunk;
sector_t block, rsect;
+ const int rw = bio_data_dir(bio);
- if (bio_data_dir(bio)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
}
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
+
chunk_size = mddev->chunk_size >> 10;
chunk_sects = mddev->chunk_size >> 9;
chunksize_bits = ffz(~chunk_size);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d3a64a04a6d8..e16f473bcf46 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -52,7 +52,7 @@ static mdk_personality_t raid1_personality;
static void unplug_slaves(mddev_t *mddev);
-static void * r1bio_pool_alloc(unsigned int __nocast gfp_flags, void *data)
+static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
{
struct pool_info *pi = data;
r1bio_t *r1_bio;
@@ -79,7 +79,7 @@ static void r1bio_pool_free(void *r1_bio, void *data)
#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
#define RESYNC_WINDOW (2048*1024)
-static void * r1buf_pool_alloc(unsigned int __nocast gfp_flags, void *data)
+static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
{
struct pool_info *pi = data;
struct page *page;
@@ -222,8 +222,17 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
{
struct bio *bio = r1_bio->master_bio;
- bio_endio(bio, bio->bi_size,
- test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+ /* if nobody has done the final endio yet, do it now */
+ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+ PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
+ (bio_data_dir(bio) == WRITE) ? "write" : "read",
+ (unsigned long long) bio->bi_sector,
+ (unsigned long long) bio->bi_sector +
+ (bio->bi_size >> 9) - 1);
+
+ bio_endio(bio, bio->bi_size,
+ test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+ }
free_r1bio(r1_bio);
}
@@ -292,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
- int mirror;
+ int mirror, behind;
conf_t *conf = mddev_to_conf(r1_bio->mddev);
if (bio->bi_size)
@@ -323,16 +332,46 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
update_head_pos(mirror, r1_bio);
+ behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
+ if (behind) {
+ if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+ atomic_dec(&r1_bio->behind_remaining);
+
+ /* In behind mode, we ACK the master bio once the I/O has safely
+ * reached all non-writemostly disks. Setting the Returned bit
+ * ensures that this gets done only once -- we don't ever want to
+ * return -EIO here, instead we'll wait */
+
+ if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+ test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+ /* Maybe we can return now */
+ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+ struct bio *mbio = r1_bio->master_bio;
+ PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+ (unsigned long long) mbio->bi_sector,
+ (unsigned long long) mbio->bi_sector +
+ (mbio->bi_size >> 9) - 1);
+ bio_endio(mbio, mbio->bi_size, 0);
+ }
+ }
+ }
/*
*
* Let's see if all mirrored write operations have finished
* already.
*/
if (atomic_dec_and_test(&r1_bio->remaining)) {
+ if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+ /* free extra copy of the data pages */
+ int i = bio->bi_vcnt;
+ while (i--)
+ __free_page(bio->bi_io_vec[i].bv_page);
+ }
/* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
r1_bio->sectors,
- !test_bit(R1BIO_Degraded, &r1_bio->state));
+ !test_bit(R1BIO_Degraded, &r1_bio->state),
+ behind);
md_write_end(r1_bio->mddev);
raid_end_bio_io(r1_bio);
}
@@ -360,13 +399,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
{
const unsigned long this_sector = r1_bio->sector;
int new_disk = conf->last_used, disk = new_disk;
+ int wonly_disk = -1;
const int sectors = r1_bio->sectors;
sector_t new_distance, current_distance;
- mdk_rdev_t *new_rdev, *rdev;
+ mdk_rdev_t *rdev;
rcu_read_lock();
/*
- * Check if it if we can balance. We can balance on the whole
+ * Check if we can balance. We can balance on the whole
* device if no resync is going on, or below the resync window.
* We take the first readable disk when above the resync window.
*/
@@ -376,11 +416,16 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* Choose the first operation device, for consistancy */
new_disk = 0;
- while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
- !new_rdev->in_sync) {
- new_disk++;
- if (new_disk == conf->raid_disks) {
- new_disk = -1;
+ for (rdev = conf->mirrors[new_disk].rdev;
+ !rdev || !rdev->in_sync
+ || test_bit(WriteMostly, &rdev->flags);
+ rdev = conf->mirrors[++new_disk].rdev) {
+
+ if (rdev && rdev->in_sync)
+ wonly_disk = new_disk;
+
+ if (new_disk == conf->raid_disks - 1) {
+ new_disk = wonly_disk;
break;
}
}
@@ -389,16 +434,26 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */
- while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
- !new_rdev->in_sync) {
+ for (rdev = conf->mirrors[new_disk].rdev;
+ !rdev || !rdev->in_sync ||
+ test_bit(WriteMostly, &rdev->flags);
+ rdev = conf->mirrors[new_disk].rdev) {
+
+ if (rdev && rdev->in_sync)
+ wonly_disk = new_disk;
+
if (new_disk <= 0)
new_disk = conf->raid_disks;
new_disk--;
if (new_disk == disk) {
- new_disk = -1;
- goto rb_out;
+ new_disk = wonly_disk;
+ break;
}
}
+
+ if (new_disk < 0)
+ goto rb_out;
+
disk = new_disk;
/* now disk == new_disk == starting point for search */
@@ -419,37 +474,41 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
disk = conf->raid_disks;
disk--;
- if ((rdev=conf->mirrors[disk].rdev) == NULL ||
- !rdev->in_sync)
+ rdev = conf->mirrors[disk].rdev;
+
+ if (!rdev ||
+ !rdev->in_sync ||
+ test_bit(WriteMostly, &rdev->flags))
continue;
if (!atomic_read(&rdev->nr_pending)) {
new_disk = disk;
- new_rdev = rdev;
break;
}
new_distance = abs(this_sector - conf->mirrors[disk].head_position);
if (new_distance < current_distance) {
current_distance = new_distance;
new_disk = disk;
- new_rdev = rdev;
}
} while (disk != conf->last_used);
-rb_out:
+ rb_out:
if (new_disk >= 0) {
- conf->next_seq_sect = this_sector + sectors;
- conf->last_used = new_disk;
- atomic_inc(&new_rdev->nr_pending);
- if (!new_rdev->in_sync) {
+ rdev = conf->mirrors[new_disk].rdev;
+ if (!rdev)
+ goto retry;
+ atomic_inc(&rdev->nr_pending);
+ if (!rdev->in_sync) {
/* cannot risk returning a device that failed
* before we inc'ed nr_pending
*/
- atomic_dec(&new_rdev->nr_pending);
+ atomic_dec(&rdev->nr_pending);
goto retry;
}
+ conf->next_seq_sect = this_sector + sectors;
+ conf->last_used = new_disk;
}
rcu_read_unlock();
@@ -542,6 +601,39 @@ static void device_barrier(conf_t *conf, sector_t sect)
spin_unlock_irq(&conf->resync_lock);
}
+/* duplicate the data pages for behind I/O */
+static struct page **alloc_behind_pages(struct bio *bio)
+{
+ int i;
+ struct bio_vec *bvec;
+ struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
+ GFP_NOIO);
+ if (unlikely(!pages))
+ goto do_sync_io;
+
+ memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
+
+ bio_for_each_segment(bvec, bio, i) {
+ pages[i] = alloc_page(GFP_NOIO);
+ if (unlikely(!pages[i]))
+ goto do_sync_io;
+ memcpy(kmap(pages[i]) + bvec->bv_offset,
+ kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
+ kunmap(pages[i]);
+ kunmap(bvec->bv_page);
+ }
+
+ return pages;
+
+do_sync_io:
+ if (pages)
+ for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
+ __free_page(pages[i]);
+ kfree(pages);
+ PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+ return NULL;
+}
+
static int make_request(request_queue_t *q, struct bio * bio)
{
mddev_t *mddev = q->queuedata;
@@ -554,7 +646,13 @@ static int make_request(request_queue_t *q, struct bio * bio)
struct bitmap *bitmap = mddev->bitmap;
unsigned long flags;
struct bio_list bl;
+ struct page **behind_pages = NULL;
+ const int rw = bio_data_dir(bio);
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
/*
* Register the new request and wait if the reconstruction
@@ -568,13 +666,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
conf->nr_pending++;
spin_unlock_irq(&conf->resync_lock);
- if (bio_data_dir(bio)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
- }
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
/*
* make_request() can abort the operation when READA is being
@@ -589,9 +682,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1_bio->mddev = mddev;
r1_bio->sector = bio->bi_sector;
- r1_bio->state = 0;
-
- if (bio_data_dir(bio) == READ) {
+ if (rw == READ) {
/*
* read balancing logic:
*/
@@ -651,13 +742,22 @@ static int make_request(request_queue_t *q, struct bio * bio)
}
rcu_read_unlock();
+ BUG_ON(targets == 0); /* we never fail the last device */
+
if (targets < conf->raid_disks) {
/* array is degraded, we will not clear the bitmap
* on I/O completion (see raid1_end_write_request) */
set_bit(R1BIO_Degraded, &r1_bio->state);
}
+ /* do behind I/O ? */
+ if (bitmap &&
+ atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind &&
+ (behind_pages = alloc_behind_pages(bio)) != NULL)
+ set_bit(R1BIO_BehindIO, &r1_bio->state);
+
atomic_set(&r1_bio->remaining, 0);
+ atomic_set(&r1_bio->behind_remaining, 0);
bio_list_init(&bl);
for (i = 0; i < disks; i++) {
@@ -674,12 +774,31 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_rw = WRITE;
mbio->bi_private = r1_bio;
+ if (behind_pages) {
+ struct bio_vec *bvec;
+ int j;
+
+ /* Yes, I really want the '__' version so that
+ * we clear any unused pointer in the io_vec, rather
+ * than leave them unchanged. This is important
+ * because when we come to free the pages, we won't
+ * know the originial bi_idx, so we just free
+ * them all
+ */
+ __bio_for_each_segment(bvec, mbio, j, 0)
+ bvec->bv_page = behind_pages[j];
+ if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags))
+ atomic_inc(&r1_bio->behind_remaining);
+ }
+
atomic_inc(&r1_bio->remaining);
bio_list_add(&bl, mbio);
}
+ kfree(behind_pages); /* the behind pages are attached to the bios now */
- bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+ bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
+ test_bit(R1BIO_BehindIO, &r1_bio->state));
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_merge(&conf->pending_bio_list, &bl);
bio_list_init(&bl);
@@ -893,7 +1012,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
if (!uptodate) {
md_error(r1_bio->mddev,
conf->mirrors[r1_bio->read_disk].rdev);
- set_bit(R1BIO_Degraded, &r1_bio->state);
} else
set_bit(R1BIO_Uptodate, &r1_bio->state);
rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
@@ -918,10 +1036,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
mirror = i;
break;
}
- if (!uptodate) {
+ if (!uptodate)
md_error(mddev, conf->mirrors[mirror].rdev);
- set_bit(R1BIO_Degraded, &r1_bio->state);
- }
+
update_head_pos(mirror, r1_bio);
if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -1107,8 +1224,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t max_sector, nr_sectors;
int disk;
int i;
+ int wonly;
int write_targets = 0;
int sync_blocks;
+ int still_degraded = 0;
if (!conf->r1buf_pool)
{
@@ -1137,7 +1256,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
- if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) &&
+ /* before building a request, check if we can skip these blocks..
+ * This call the bitmap_start_sync doesn't actually record anything
+ */
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync) {
/* We can skip this block, and probably several more */
*skipped = 1;
@@ -1158,14 +1280,21 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*/
disk = conf->last_used;
/* make sure disk is operational */
-
+ wonly = disk;
while (conf->mirrors[disk].rdev == NULL ||
- !conf->mirrors[disk].rdev->in_sync) {
+ !conf->mirrors[disk].rdev->in_sync ||
+ test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
+ ) {
+ if (conf->mirrors[disk].rdev &&
+ conf->mirrors[disk].rdev->in_sync)
+ wonly = disk;
if (disk <= 0)
disk = conf->raid_disks;
disk--;
- if (disk == conf->last_used)
+ if (disk == conf->last_used) {
+ disk = wonly;
break;
+ }
}
conf->last_used = disk;
atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
@@ -1203,24 +1332,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (i == disk) {
bio->bi_rw = READ;
bio->bi_end_io = end_sync_read;
- } else if (conf->mirrors[i].rdev &&
- !conf->mirrors[i].rdev->faulty &&
- (!conf->mirrors[i].rdev->in_sync ||
- sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
+ } else if (conf->mirrors[i].rdev == NULL ||
+ conf->mirrors[i].rdev->faulty) {
+ still_degraded = 1;
+ continue;
+ } else if (!conf->mirrors[i].rdev->in_sync ||
+ sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
bio->bi_rw = WRITE;
bio->bi_end_io = end_sync_write;
write_targets ++;
} else
+ /* no need to read or write here */
continue;
bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
bio->bi_private = r1_bio;
}
- if (write_targets + 1 < conf->raid_disks)
- /* array degraded, can't clear bitmap */
- set_bit(R1BIO_Degraded, &r1_bio->state);
-
if (write_targets == 0) {
/* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished
@@ -1243,7 +1371,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
break;
if (sync_blocks == 0) {
if (!bitmap_start_sync(mddev->bitmap, sector_nr,
- &sync_blocks, mddev->degraded) &&
+ &sync_blocks, still_degraded) &&
!conf->fullsync)
break;
if (sync_blocks < (PAGE_SIZE>>9))
@@ -1438,6 +1566,17 @@ out:
static int stop(mddev_t *mddev)
{
conf_t *conf = mddev_to_conf(mddev);
+ struct bitmap *bitmap = mddev->bitmap;
+ int behind_wait = 0;
+
+ /* wait for behind writes to complete */
+ while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+ behind_wait++;
+ printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ); /* wait a second */
+ /* need to kick something here to make sure I/O goes? */
+ }
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
@@ -1560,6 +1699,35 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
return 0;
}
+static void raid1_quiesce(mddev_t *mddev, int state)
+{
+ conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1:
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+ conf->resync_lock, raid1_unplug(mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+ break;
+ case 0:
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ spin_unlock_irq(&conf->resync_lock);
+ wake_up(&conf->wait_resume);
+ wake_up(&conf->wait_idle);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
+
static mdk_personality_t raid1_personality =
{
@@ -1576,6 +1744,7 @@ static mdk_personality_t raid1_personality =
.sync_request = sync_request,
.resize = raid1_resize,
.reshape = raid1_reshape,
+ .quiesce = raid1_quiesce,
};
static int __init raid_init(void)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 62ebb1bc72be..bbe40e9cf923 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -47,7 +47,7 @@
static void unplug_slaves(mddev_t *mddev);
-static void * r10bio_pool_alloc(unsigned int __nocast gfp_flags, void *data)
+static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
{
conf_t *conf = data;
r10bio_t *r10_bio;
@@ -81,7 +81,7 @@ static void r10bio_pool_free(void *r10_bio, void *data)
* one for write (we recover only one drive per r10buf)
*
*/
-static void * r10buf_pool_alloc(unsigned int __nocast gfp_flags, void *data)
+static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
{
conf_t *conf = data;
struct page *page;
@@ -538,7 +538,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
}
- current_distance = abs(this_sector - conf->mirrors[disk].head_position);
+ current_distance = abs(r10_bio->devs[slot].addr -
+ conf->mirrors[disk].head_position);
/* Find the disk whose head is closest */
@@ -667,6 +668,12 @@ static int make_request(request_queue_t *q, struct bio * bio)
struct bio *read_bio;
int i;
int chunk_sects = conf->chunk_mask + 1;
+ const int rw = bio_data_dir(bio);
+
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
/* If this request crosses a chunk boundary, we need to
* split it. This will only happen for 1 PAGE (or less) requests.
@@ -712,13 +719,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
conf->nr_pending++;
spin_unlock_irq(&conf->resync_lock);
- if (bio_data_dir(bio)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
- }
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
@@ -728,7 +730,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r10_bio->mddev = mddev;
r10_bio->sector = bio->bi_sector;
- if (bio_data_dir(bio) == READ) {
+ if (rw == READ) {
/*
* read balancing logic:
*/
@@ -900,6 +902,27 @@ static void close_sync(conf_t *conf)
conf->r10buf_pool = NULL;
}
+/* check if there are enough drives for
+ * every block to appear on atleast one
+ */
+static int enough(conf_t *conf)
+{
+ int first = 0;
+
+ do {
+ int n = conf->copies;
+ int cnt = 0;
+ while (n--) {
+ if (conf->mirrors[first].rdev)
+ cnt++;
+ first = (first+1) % conf->raid_disks;
+ }
+ if (cnt == 0)
+ return 0;
+ } while (first != 0);
+ return 1;
+}
+
static int raid10_spare_active(mddev_t *mddev)
{
int i;
@@ -938,6 +961,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
* very different from resync
*/
return 0;
+ if (!enough(conf))
+ return 0;
for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -1445,7 +1470,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
}
}
if (j == conf->copies) {
- BUG();
+ /* Cannot recover, so abort the recovery */
+ put_buf(r10_bio);
+ r10_bio = rb2;
+ if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery))
+ printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n",
+ mdname(mddev));
+ break;
}
}
if (biolist == NULL) {
@@ -1678,9 +1709,10 @@ static int run(mddev_t *mddev)
init_waitqueue_head(&conf->wait_idle);
init_waitqueue_head(&conf->wait_resume);
- if (!conf->working_disks) {
- printk(KERN_ERR "raid10: no operational mirrors for %s\n",
- mdname(mddev));
+ /* need to check that every block has at least one working mirror */
+ if (!enough(conf)) {
+ printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
+ mdname(mddev));
goto out_free_conf;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 43f231a467d5..6497295ebfb9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -24,6 +24,8 @@
#include <linux/bitops.h>
#include <asm/atomic.h>
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -79,8 +81,13 @@ static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -244,6 +251,9 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -803,6 +813,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
{
struct bio **bip;
raid5_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -811,9 +822,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -836,6 +849,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -958,12 +978,13 @@ static void handle_stripe(struct stripe_head *sh)
* need to be failed
*/
if (failed > 1 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -981,6 +1002,7 @@ static void handle_stripe(struct stripe_head *sh)
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1009,8 +1031,11 @@ static void handle_stripe(struct stripe_head *sh)
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 1 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1038,6 +1063,7 @@ static void handle_stripe(struct stripe_head *sh)
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
struct bio *wbi, *wbi2;
+ int bitmap_end = 0;
PRINTK("Return write for disc %d\n", i);
spin_lock_irq(&conf->device_lock);
wbi = dev->written;
@@ -1051,7 +1077,13 @@ static void handle_stripe(struct stripe_head *sh)
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1175,7 +1207,8 @@ static void handle_stripe(struct stripe_head *sh)
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && (rcw == 0 ||rmw == 0)) {
+ if (locked == 0 && (rcw == 0 ||rmw == 0) &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
PRINTK("Computing parity...\n");
compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
/* now every locked buffer is ready to be written */
@@ -1231,6 +1264,7 @@ static void handle_stripe(struct stripe_head *sh)
dev = &sh->dev[failed_num];
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantwrite, &dev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
locked++;
set_bit(STRIPE_INSYNC, &sh->state);
set_bit(R5_Syncio, &dev->flags);
@@ -1298,6 +1332,8 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1322,6 +1358,20 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
}
}
+static inline void activate_bit_delay(raid5_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -1354,8 +1404,10 @@ static void raid5_unplug_device(request_queue_t *q)
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid5_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1410,16 +1462,17 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t new_sector;
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ const int rw = bio_data_dir(bi);
+
+ if (unlikely(bio_barrier(bi))) {
+ bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
md_write_start(mddev, bi);
- if (bio_data_dir(bi)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bi));
- }
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
last_sector = bi->bi_sector + (bi->bi_size>>9);
@@ -1488,10 +1541,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks-1;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there is 1 or more failed drives and we are trying
@@ -1503,6 +1566,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1520,6 +1590,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1553,6 +1624,13 @@ static void raid5d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1586,7 +1664,7 @@ static void raid5d (mddev_t *mddev)
PRINTK("--- raid5d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid5_conf_t *conf;
int raid_disk, memory;
@@ -1616,6 +1694,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1727,6 +1806,9 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
/* Ok, everything is just fine now */
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
@@ -1907,6 +1989,8 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -1936,6 +2020,35 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+static void raid5_quiesce(mddev_t *mddev, int state)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid5_personality=
{
.name = "raid5",
@@ -1950,6 +2063,7 @@ static mdk_personality_t raid5_personality=
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+ .quiesce = raid5_quiesce,
};
static int __init raid5_init (void)
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h
index f80ee6350edf..31cbee71365f 100644
--- a/drivers/md/raid6.h
+++ b/drivers/md/raid6.h
@@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE];
#define __init
#define __exit
#define __attribute_const__ __attribute__((const))
+#define noinline __attribute__((noinline))
#define preempt_enable()
#define preempt_disable()
+#define cpu_has_feature(x) 1
+#define enable_kernel_altivec()
+#define disable_kernel_altivec()
#endif /* __KERNEL__ */
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index acf386fc4b4f..51c63c0cf1c9 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -19,6 +19,7 @@
#include "raid6.h"
#ifndef __KERNEL__
#include <sys/mman.h>
+#include <stdio.h>
#endif
struct raid6_calls raid6_call;
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index 1de8f030eee0..b9afd35b8812 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -27,16 +27,20 @@
#ifdef CONFIG_ALTIVEC
#include <altivec.h>
-#include <asm/system.h>
-#include <asm/cputable.h>
+#ifdef __KERNEL__
+# include <asm/system.h>
+# include <asm/cputable.h>
+#endif
/*
- * This is the C data type to use
+ * This is the C data type to use. We use a vector of
+ * signed char so vec_cmpgt() will generate the right
+ * instruction.
*/
-typedef vector unsigned char unative_t;
+typedef vector signed char unative_t;
-#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
+#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
#define NSIZE sizeof(unative_t)
/*
@@ -108,7 +112,11 @@ int raid6_have_altivec(void);
int raid6_have_altivec(void)
{
/* This assumes either all CPUs have Altivec or none does */
+# ifdef __KERNEL__
return cpu_has_feature(CPU_FTR_ALTIVEC);
+# else
+ return 1;
+# endif
}
#endif
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 495dee1d1e83..6437a95ffc1c 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -29,6 +29,8 @@
#include <asm/atomic.h>
#include "raid6.h"
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -98,8 +100,13 @@ static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -262,6 +269,9 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -906,6 +916,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
{
struct bio **bip;
raid6_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -914,9 +925,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -939,6 +952,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -1066,12 +1086,13 @@ static void handle_stripe(struct stripe_head *sh)
* need to be failed
*/
if (failed > 2 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -1089,6 +1110,7 @@ static void handle_stripe(struct stripe_head *sh)
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1117,8 +1139,11 @@ static void handle_stripe(struct stripe_head *sh)
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 2 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1155,6 +1180,7 @@ static void handle_stripe(struct stripe_head *sh)
if (!test_bit(R5_LOCKED, &dev->flags) &&
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
+ int bitmap_end = 0;
struct bio *wbi, *wbi2;
PRINTK("Return write for stripe %llu disc %d\n",
(unsigned long long)sh->sector, i);
@@ -1170,7 +1196,13 @@ static void handle_stripe(struct stripe_head *sh)
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1285,7 +1317,8 @@ static void handle_stripe(struct stripe_head *sh)
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && rcw == 0) {
+ if (locked == 0 && rcw == 0 &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
if ( must_compute > 0 ) {
/* We have failed blocks and need to compute them */
switch ( failed ) {
@@ -1388,6 +1421,7 @@ static void handle_stripe(struct stripe_head *sh)
bdev = &sh->dev[failed_num[1]];
locked += !test_bit(R5_LOCKED, &bdev->flags);
set_bit(R5_LOCKED, &bdev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
set_bit(R5_Wantwrite, &bdev->flags);
set_bit(STRIPE_INSYNC, &sh->state);
@@ -1457,6 +1491,8 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1481,6 +1517,20 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
}
}
+static inline void activate_bit_delay(raid6_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
@@ -1513,8 +1563,10 @@ static void raid6_unplug_device(request_queue_t *q)
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid6_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1569,16 +1621,17 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t new_sector;
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ const int rw = bio_data_dir(bi);
+
+ if (unlikely(bio_barrier(bi))) {
+ bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
md_write_start(mddev, bi);
- if (bio_data_dir(bi)==WRITE) {
- disk_stat_inc(mddev->gendisk, writes);
- disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
- } else {
- disk_stat_inc(mddev->gendisk, reads);
- disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bi));
- }
+ disk_stat_inc(mddev->gendisk, ios[rw]);
+ disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
last_sector = bi->bi_sector + (bi->bi_size>>9);
@@ -1625,7 +1678,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
if (--bi->bi_phys_segments == 0) {
int bytes = bi->bi_size;
- if ( bio_data_dir(bi) == WRITE )
+ if (rw == WRITE )
md_write_end(mddev);
bi->bi_size = 0;
bi->bi_end_io(bi, bytes, 0);
@@ -1647,10 +1700,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks - 2;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there are 2 or more failed drives and we are trying
@@ -1662,6 +1725,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1679,6 +1749,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1712,6 +1783,13 @@ static void raid6d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1745,7 +1823,7 @@ static void raid6d (mddev_t *mddev)
PRINTK("--- raid6d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid6_conf_t *conf;
int raid_disk, memory;
@@ -1775,6 +1853,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1894,6 +1973,9 @@ static int run (mddev_t *mddev)
/* Ok, everything is just fine now */
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid6_unplug_device;
mddev->queue->issue_flush_fn = raid6_issue_flush;
return 0;
@@ -2071,6 +2153,8 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -2100,6 +2184,35 @@ static int raid6_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+static void raid6_quiesce(mddev_t *mddev, int state)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid6_personality=
{
.name = "raid6",
@@ -2114,6 +2227,7 @@ static mdk_personality_t raid6_personality=
.spare_active = raid6_spare_active,
.sync_request = sync_request,
.resize = raid6_resize,
+ .quiesce = raid6_quiesce,
};
static int __init raid6_init (void)
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile
index 557806728609..78e0396adf2a 100644
--- a/drivers/md/raid6test/Makefile
+++ b/drivers/md/raid6test/Makefile
@@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired
CFLAGS = -I.. -g $(OPTFLAGS)
LD = ld
PERL = perl
+AR = ar
+RANLIB = ranlib
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
@@ -18,18 +20,33 @@ PERL = perl
%.uc: ../%.uc
cp -f $< $@
-all: raid6.o raid6test
+all: raid6.a raid6test
-raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
+raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
raid6int32.o \
raid6mmx.o raid6sse1.o raid6sse2.o \
+ raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \
raid6recov.o raid6algos.o \
raid6tables.o
- $(LD) -r -o $@ $^
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
-raid6test: raid6.o test.c
+raid6test: test.c raid6.a
$(CC) $(CFLAGS) -o raid6test $^
+raid6altivec1.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+
+raid6altivec2.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+
+raid6altivec4.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+
+raid6altivec8.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+
raid6int1.c: raid6int.uc ../unroll.pl
$(PERL) ../unroll.pl 1 < raid6int.uc > $@
@@ -52,7 +69,7 @@ raid6tables.c: mktables
./mktables > raid6tables.c
clean:
- rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test
+ rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test
spotless: clean
rm -f *~
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 772d6112fb3b..c578a529e7a8 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -2,4 +2,7 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := video/ radio/ dvb/ common/
+obj-y := common/
+obj-$(CONFIG_VIDEO_DEV) += video/
+obj-$(CONFIG_VIDEO_DEV) += radio/
+obj-$(CONFIG_DVB) += dvb/
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index ab7a1fba4427..31fccb4f05d6 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-common.c,v 1.11 2005/07/07 14:44:43 mchehab Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -23,6 +22,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/string.h>
#include <media/ir-common.h>
/* -------------------------------------------------------------------------- */
@@ -253,7 +253,6 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
if (ir_codes)
memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
- init_input_dev(dev);
dev->keycode = ir->ir_codes;
dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
dev->keycodemax = IR_KEYTAB_SIZE;
@@ -335,6 +334,72 @@ int ir_dump_samples(u32 *samples, int count)
return 0;
}
+/* decode raw samples, pulse distance coding used by NEC remotes */
+int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
+{
+ int i,last,bit,len;
+ u32 curBit;
+ u32 value;
+
+ /* find start burst */
+ for (i = len = 0; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (bit) {
+ len++;
+ } else {
+ if (len >= 29)
+ break;
+ len = 0;
+ }
+ }
+
+ /* start burst to short */
+ if (len < 29)
+ return 0xffffffff;
+
+ /* find start silence */
+ for (len = 0; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (bit) {
+ break;
+ } else {
+ len++;
+ }
+ }
+
+ /* silence to short */
+ if (len < 7)
+ return 0xffffffff;
+
+ /* go decoding */
+ len = 0;
+ last = 1;
+ value = 0; curBit = 1;
+ for (; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (last) {
+ if(bit) {
+ continue;
+ } else {
+ len = 1;
+ }
+ } else {
+ if (bit) {
+ if (len > (low + high) /2)
+ value |= curBit;
+ curBit <<= 1;
+ if (curBit == 1)
+ break;
+ } else {
+ len++;
+ }
+ }
+ last = bit;
+ }
+
+ return value;
+}
+
/* decode raw samples, biphase coding, used by rc5 for example */
int ir_decode_biphase(u32 *samples, int count, int low, int high)
{
@@ -383,6 +448,7 @@ EXPORT_SYMBOL_GPL(ir_input_keydown);
EXPORT_SYMBOL_GPL(ir_extract_bits);
EXPORT_SYMBOL_GPL(ir_dump_samples);
EXPORT_SYMBOL_GPL(ir_decode_biphase);
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
/*
* Local variables:
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index cd5828b5e9e3..206cc2f61f26 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -168,10 +168,8 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
return;
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
pt->cpu = NULL;
- if (NULL != pt->slist) {
- kfree(pt->slist);
- pt->slist = NULL;
- }
+ kfree(pt->slist);
+ pt->slist = NULL;
}
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index c04fd11526e0..37888989ea2e 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -1,5 +1,4 @@
#include <media/saa7146_vv.h>
-#include <linux/version.h>
#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 781f23f0cbcc..fec6beab8c28 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -1,4 +1,3 @@
-#include <linux/version.h>
#include <media/saa7146_vv.h>
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
@@ -387,8 +386,6 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in
/* exported algorithm data */
static struct i2c_algorithm saa7146_algo = {
- .name = "saa7146 i2c algorithm",
- .id = I2C_ALGO_SAA7146,
.master_xfer = saa7146_i2c_xfer,
.functionality = saa7146_i2c_func,
};
@@ -404,15 +401,12 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- i2c_adapter->data = dev;
-#else
BUG_ON(!i2c_adapter->class);
i2c_set_adapdata(i2c_adapter,dev);
-#endif
+ i2c_adapter->dev.parent = &dev->pci->dev;
i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL;
- i2c_adapter->id = I2C_ALGO_SAA7146;
+ i2c_adapter->id = I2C_HW_SAA7146;
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
i2c_adapter->retries = SAA7146_I2C_RETRIES;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 0410cc96a48e..47e28b0ee951 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -164,12 +164,11 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
return 0;
}
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- struct flexcop_device *fc = fe->dvb->priv;
div = params->frequency / 125;
@@ -180,7 +179,7 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_fronten
if (params->frequency < 1500000) buf[3] |= 0x10;
- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -335,8 +334,103 @@ static struct mt312_config skystar23_samsung_tbdu18132_config = {
.pll_set = skystar23_samsung_tbdu18132_pll_set,
};
+
+static u8 alps_tdee4_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0xf8,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
+
static struct stv0297_config alps_tdee4_stv0297_config = {
.demod_address = 0x1c,
+ .inittab = alps_tdee4_stv0297_inittab,
// .invert = 1,
// .pll_set = alps_tdee4_stv0297_pll_set,
};
@@ -370,7 +464,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
} else
/* try the cable dvb (stv0297) */
- if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
+ if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_CABLE;
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
} else
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index be4266d4ae91..56495cb6cd02 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -172,8 +172,6 @@ static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm flexcop_algo = {
- .name = "FlexCop I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = flexcop_master_xfer,
.functionality = flexcop_i2c_func,
};
@@ -192,7 +190,6 @@ int flexcop_i2c_init(struct flexcop_device *fc)
fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
fc->i2c_adap.algo = &flexcop_algo;
fc->i2c_adap.algo_data = NULL;
- fc->i2c_adap.id = I2C_ALGO_BIT;
if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
return ret;
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index b12545f093f8..1e85d16491b0 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -1,5 +1,5 @@
config DVB_BT8XX
- tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards"
+ tristate "BT8xx based PCI cards"
depends on DVB_CORE && PCI && VIDEO_BT848
select DVB_MT352
select DVB_SP887X
@@ -8,8 +8,8 @@ config DVB_BT8XX
select DVB_OR51211
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
- the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
- pcHDTV HD2000 cards.
+ the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
+ the pcHDTV HD2000 cards, and certain AVerMedia cards.
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 3c5a8e273c4a..f29571450038 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -1,7 +1,7 @@
/*
* bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
*
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
*
* large parts based on the bttv driver
* Copyright (C) 1996,97,98 Ralph Metzler (rjkm@metzlerbros.de)
@@ -219,7 +219,7 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
controlreg &= ~0x1f;
controlreg |= 0x1b;
- btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START);
+ btwrite(bt->risc_dma, BT878_ARISC_START);
/* original int mask had :
* 6 2 8 4 0
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index 837623f7fcdf..a73baf00ca39 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -1,7 +1,7 @@
/*
bt878.h - Bt878 audio module (register offsets)
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.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
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 07a0b0a968a6..34a837a1abf4 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1,5 +1,4 @@
/*
-
Frontend/Card driver for TwinHan DST Frontend
Copyright (C) 2003 Jamie Honan
Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
@@ -19,7 +18,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -28,31 +26,45 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <asm/div64.h>
-
#include "dvb_frontend.h"
#include "dst_priv.h"
#include "dst_common.h"
-
static unsigned int verbose = 1;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
-
static unsigned int dst_addons;
module_param(dst_addons, int, 0644);
MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
-#define dprintk if (debug) printk
-
-#define HAS_LOCK 1
-#define ATTEMPT_TUNE 2
-#define HAS_POWER 4
-
-static void dst_packsize(struct dst_state* state, int psize)
+#define HAS_LOCK 1
+#define ATTEMPT_TUNE 2
+#define HAS_POWER 4
+
+#define DST_ERROR 0
+#define DST_NOTICE 1
+#define DST_INFO 2
+#define DST_DEBUG 3
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_ERROR) && (x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_INFO) && (x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ##arg); \
+ } \
+} while(0)
+
+
+static void dst_packsize(struct dst_state *state, int psize)
{
union dst_gpio_packet bits;
@@ -60,7 +72,7 @@ static void dst_packsize(struct dst_state* state, int psize)
bt878_device_control(state->bt, DST_IG_TS, &bits);
}
-int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay)
+int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay)
{
union dst_gpio_packet enb;
union dst_gpio_packet bits;
@@ -68,63 +80,55 @@ int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int
enb.enb.mask = mask;
enb.enb.enable = enbb;
- if (verbose > 4)
- dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", __FUNCTION__, mask, enbb, outhigh);
+ dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
- dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", __FUNCTION__, err, mask, enbb);
+ dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
return -EREMOTEIO;
}
udelay(1000);
/* because complete disabling means no output, no need to do output packet */
if (enbb == 0)
return 0;
-
if (delay)
msleep(10);
-
bits.outp.mask = enbb;
bits.outp.highvals = outhigh;
-
if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
- dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
+ dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
return -EREMOTEIO;
}
+
return 0;
}
EXPORT_SYMBOL(dst_gpio_outb);
-int dst_gpio_inb(struct dst_state *state, u8 * result)
+int dst_gpio_inb(struct dst_state *state, u8 *result)
{
union dst_gpio_packet rd_packet;
int err;
*result = 0;
-
if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
- dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
return -EREMOTEIO;
}
-
*result = (u8) rd_packet.rd.value;
+
return 0;
}
EXPORT_SYMBOL(dst_gpio_inb);
int rdc_reset_state(struct dst_state *state)
{
- if (verbose > 1)
- dprintk("%s: Resetting state machine\n", __FUNCTION__);
-
+ dprintk(verbose, DST_INFO, 1, "Resetting state machine");
if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
-
msleep(10);
-
if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
msleep(10);
return -1;
}
@@ -135,16 +139,14 @@ EXPORT_SYMBOL(rdc_reset_state);
int rdc_8820_reset(struct dst_state *state)
{
- if (verbose > 1)
- dprintk("%s: Resetting DST\n", __FUNCTION__);
-
+ dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
udelay(1000);
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
@@ -155,10 +157,11 @@ EXPORT_SYMBOL(rdc_8820_reset);
int dst_pio_enable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
udelay(1000);
+
return 0;
}
EXPORT_SYMBOL(dst_pio_enable);
@@ -166,7 +169,7 @@ EXPORT_SYMBOL(dst_pio_enable);
int dst_pio_disable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
- dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -183,19 +186,16 @@ int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
for (i = 0; i < 200; i++) {
if (dst_gpio_inb(state, &reply) < 0) {
- dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
return -1;
}
-
if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
- if (verbose > 4)
- dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
+ dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
return 1;
}
msleep(10);
}
- if (verbose > 1)
- dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+ dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
return 0;
}
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(dst_wait_dst_ready);
int dst_error_recovery(struct dst_state *state)
{
- dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
+ dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
dst_pio_disable(state);
msleep(10);
dst_pio_enable(state);
@@ -215,7 +215,7 @@ EXPORT_SYMBOL(dst_error_recovery);
int dst_error_bailout(struct dst_state *state)
{
- dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
rdc_8820_reset(state);
dst_pio_disable(state);
msleep(10);
@@ -224,17 +224,15 @@ int dst_error_bailout(struct dst_state *state)
}
EXPORT_SYMBOL(dst_error_bailout);
-
-int dst_comm_init(struct dst_state* state)
+int dst_comm_init(struct dst_state *state)
{
- if (verbose > 1)
- dprintk ("%s: Initializing DST..\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Initializing DST.");
if ((dst_pio_enable(state)) < 0) {
- dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
return -1;
}
if ((rdc_reset_state(state)) < 0) {
- dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -246,36 +244,33 @@ int dst_comm_init(struct dst_state* state)
}
EXPORT_SYMBOL(dst_comm_init);
-
int write_dst(struct dst_state *state, u8 *data, u8 len)
{
struct i2c_msg msg = {
- .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = data,
+ .len = len
};
int err;
- int cnt;
- if (debug && (verbose > 4)) {
- u8 i;
- if (verbose > 4) {
- dprintk("%s writing [ ", __FUNCTION__);
- for (i = 0; i < len; i++)
- dprintk("%02x ", data[i]);
- dprintk("]\n");
- }
- }
+ u8 cnt, i;
+
+ dprintk(verbose, DST_NOTICE, 0, "writing [ ");
+ for (i = 0; i < len; i++)
+ dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
+ dprintk(verbose, DST_NOTICE, 0, "]\n");
+
for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
- dprintk("%s: _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+ dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
dst_error_recovery(state);
continue;
} else
break;
}
-
if (cnt >= 2) {
- if (verbose > 1)
- printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
dst_error_bailout(state);
return -1;
@@ -285,36 +280,37 @@ int write_dst(struct dst_state *state, u8 *data, u8 len)
}
EXPORT_SYMBOL(write_dst);
-int read_dst(struct dst_state *state, u8 * ret, u8 len)
+int read_dst(struct dst_state *state, u8 *ret, u8 len)
{
- struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = ret,
+ .len = len
+ };
+
int err;
int cnt;
for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-
- dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
+ dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
dst_error_recovery(state);
-
continue;
} else
break;
}
if (cnt >= 2) {
- if (verbose > 1)
- printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
dst_error_bailout(state);
return -1;
}
- if (debug && (verbose > 4)) {
- dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
- for (err = 1; err < len; err++)
- dprintk(" 0x%x", ret[err]);
- if (err > 1)
- dprintk("\n");
- }
+ dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
+ for (err = 1; err < len; err++)
+ dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
+ if (err > 1)
+ dprintk(verbose, DST_DEBUG, 0, "\n");
return 0;
}
@@ -323,19 +319,16 @@ EXPORT_SYMBOL(read_dst);
static int dst_set_polarization(struct dst_state *state)
{
switch (state->voltage) {
- case SEC_VOLTAGE_13: // vertical
- printk("%s: Polarization=[Vertical]\n", __FUNCTION__);
- state->tx_tuna[8] &= ~0x40; //1
- break;
-
- case SEC_VOLTAGE_18: // horizontal
- printk("%s: Polarization=[Horizontal]\n", __FUNCTION__);
- state->tx_tuna[8] |= 0x40; // 0
- break;
-
- case SEC_VOLTAGE_OFF:
-
- break;
+ case SEC_VOLTAGE_13: /* Vertical */
+ dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
+ state->tx_tuna[8] &= ~0x40;
+ break;
+ case SEC_VOLTAGE_18: /* Horizontal */
+ dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
+ state->tx_tuna[8] |= 0x40;
+ break;
+ case SEC_VOLTAGE_OFF:
+ break;
}
return 0;
@@ -344,14 +337,12 @@ static int dst_set_polarization(struct dst_state *state)
static int dst_set_freq(struct dst_state *state, u32 freq)
{
state->frequency = freq;
- if (debug > 4)
- dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
+ dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
if (state->dst_type == DST_TYPE_IS_SAT) {
freq = freq / 1000;
if (freq < 950 || freq > 2150)
return -EINVAL;
-
state->tx_tuna[2] = (freq >> 8);
state->tx_tuna[3] = (u8) freq;
state->tx_tuna[4] = 0x01;
@@ -360,27 +351,25 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
if (freq < 1531)
state->tx_tuna[8] |= 0x04;
}
-
} else if (state->dst_type == DST_TYPE_IS_TERR) {
freq = freq / 1000;
if (freq < 137000 || freq > 858000)
return -EINVAL;
-
state->tx_tuna[2] = (freq >> 16) & 0xff;
state->tx_tuna[3] = (freq >> 8) & 0xff;
state->tx_tuna[4] = (u8) freq;
-
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ freq = freq / 1000;
state->tx_tuna[2] = (freq >> 16) & 0xff;
state->tx_tuna[3] = (freq >> 8) & 0xff;
state->tx_tuna[4] = (u8) freq;
-
} else
return -EINVAL;
+
return 0;
}
-static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
+static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
{
state->bandwidth = bandwidth;
@@ -388,103 +377,95 @@ static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
return 0;
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x06;
- else {
- state->tx_tuna[6] = 0x06;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- case BANDWIDTH_7_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x07;
- else {
- state->tx_tuna[6] = 0x07;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- case BANDWIDTH_8_MHZ:
- if (state->dst_hw_cap & DST_TYPE_HAS_CA)
- state->tx_tuna[7] = 0x08;
- else {
- state->tx_tuna[6] = 0x08;
- state->tx_tuna[7] = 0x00;
- }
- break;
-
- default:
- return -EINVAL;
+ case BANDWIDTH_6_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x06;
+ else {
+ state->tx_tuna[6] = 0x06;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ case BANDWIDTH_7_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x07;
+ else {
+ state->tx_tuna[6] = 0x07;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ case BANDWIDTH_8_MHZ:
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+ state->tx_tuna[7] = 0x08;
+ else {
+ state->tx_tuna[6] = 0x08;
+ state->tx_tuna[7] = 0x00;
+ }
+ break;
+ default:
+ return -EINVAL;
}
+
return 0;
}
-static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion)
+static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
{
state->inversion = inversion;
switch (inversion) {
- case INVERSION_OFF: // Inversion = Normal
- state->tx_tuna[8] &= ~0x80;
- break;
-
- case INVERSION_ON:
- state->tx_tuna[8] |= 0x80;
- break;
- default:
- return -EINVAL;
+ case INVERSION_OFF: /* Inversion = Normal */
+ state->tx_tuna[8] &= ~0x80;
+ break;
+ case INVERSION_ON:
+ state->tx_tuna[8] |= 0x80;
+ break;
+ default:
+ return -EINVAL;
}
+
return 0;
}
-static int dst_set_fec(struct dst_state* state, fe_code_rate_t fec)
+static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
{
state->fec = fec;
return 0;
}
-static fe_code_rate_t dst_get_fec(struct dst_state* state)
+static fe_code_rate_t dst_get_fec(struct dst_state *state)
{
return state->fec;
}
-static int dst_set_symbolrate(struct dst_state* state, u32 srate)
+static int dst_set_symbolrate(struct dst_state *state, u32 srate)
{
- u8 *val;
u32 symcalc;
u64 sval;
state->symbol_rate = srate;
-
if (state->dst_type == DST_TYPE_IS_TERR) {
return 0;
}
- if (debug > 4)
- dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
+ dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
srate /= 1000;
- val = &state->tx_tuna[0];
-
if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
sval = srate;
sval <<= 20;
do_div(sval, 88000);
symcalc = (u32) sval;
-
- if (debug > 4)
- dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
-
- val[5] = (u8) (symcalc >> 12);
- val[6] = (u8) (symcalc >> 4);
- val[7] = (u8) (symcalc << 4);
+ dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+ state->tx_tuna[5] = (u8) (symcalc >> 12);
+ state->tx_tuna[6] = (u8) (symcalc >> 4);
+ state->tx_tuna[7] = (u8) (symcalc << 4);
} else {
- val[5] = (u8) (srate >> 16) & 0x7f;
- val[6] = (u8) (srate >> 8);
- val[7] = (u8) srate;
+ state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+ state->tx_tuna[6] = (u8) (srate >> 8);
+ state->tx_tuna[7] = (u8) srate;
+ }
+ state->tx_tuna[8] &= ~0x20;
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+ if (srate > 8000)
+ state->tx_tuna[8] |= 0x20;
}
- val[8] &= ~0x20;
- if (srate > 8000)
- val[8] |= 0x20;
return 0;
}
@@ -496,32 +477,27 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
state->modulation = modulation;
switch (modulation) {
- case QAM_16:
- state->tx_tuna[8] = 0x10;
- break;
-
- case QAM_32:
- state->tx_tuna[8] = 0x20;
- break;
-
- case QAM_64:
- state->tx_tuna[8] = 0x40;
- break;
-
- case QAM_128:
- state->tx_tuna[8] = 0x80;
- break;
-
- case QAM_256:
- state->tx_tuna[8] = 0x00;
- break;
-
- case QPSK:
- case QAM_AUTO:
- case VSB_8:
- case VSB_16:
- default:
- return -EINVAL;
+ case QAM_16:
+ state->tx_tuna[8] = 0x10;
+ break;
+ case QAM_32:
+ state->tx_tuna[8] = 0x20;
+ break;
+ case QAM_64:
+ state->tx_tuna[8] = 0x40;
+ break;
+ case QAM_128:
+ state->tx_tuna[8] = 0x80;
+ break;
+ case QAM_256:
+ state->tx_tuna[8] = 0x00;
+ break;
+ case QPSK:
+ case QAM_AUTO:
+ case VSB_8:
+ case VSB_16:
+ default:
+ return -EINVAL;
}
@@ -534,7 +510,7 @@ static fe_modulation_t dst_get_modulation(struct dst_state *state)
}
-u8 dst_check_sum(u8 * buf, u32 len)
+u8 dst_check_sum(u8 *buf, u32 len)
{
u32 i;
u8 val = 0;
@@ -549,26 +525,24 @@ EXPORT_SYMBOL(dst_check_sum);
static void dst_type_flags_print(u32 type_flags)
{
- printk("DST type flags :");
+ dprintk(verbose, DST_ERROR, 0, "DST type flags :");
if (type_flags & DST_TYPE_HAS_NEWTUNE)
- printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
if (type_flags & DST_TYPE_HAS_TS204)
- printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
if (type_flags & DST_TYPE_HAS_SYMDIV)
- printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
if (type_flags & DST_TYPE_HAS_FW_1)
- printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
if (type_flags & DST_TYPE_HAS_FW_2)
- printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
if (type_flags & DST_TYPE_HAS_FW_3)
- printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
-// if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
-
- printk("\n");
+ dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+ dprintk(verbose, DST_ERROR, 0, "\n");
}
-static int dst_type_print (u8 type)
+static int dst_type_print(u8 type)
{
char *otype;
switch (type) {
@@ -585,10 +559,10 @@ static int dst_type_print (u8 type)
break;
default:
- printk("%s: invalid dst type %d\n", __FUNCTION__, type);
+ dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
return -EINVAL;
}
- printk("DST type : %s\n", otype);
+ dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
return 0;
}
@@ -700,7 +674,7 @@ struct dst_types dst_tlist[] = {
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
- | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ | DST_TYPE_HAS_FW_2,
.dst_feature = DST_TYPE_HAS_CA
},
@@ -708,7 +682,7 @@ struct dst_types dst_tlist[] = {
.device_id = "DCTNEW",
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
- .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
+ .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
.dst_feature = 0
},
@@ -716,7 +690,7 @@ struct dst_types dst_tlist[] = {
.device_id = "DTT-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
.dst_feature = 0
},
@@ -756,6 +730,71 @@ struct dst_types dst_tlist[] = {
};
+static int dst_get_mac(struct dst_state *state)
+{
+ u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_mac[7] = dst_check_sum(get_mac, 7);
+ if (dst_command(state, get_mac, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->mac_address, '\0', 8);
+ memcpy(&state->mac_address, &state->rxbuffer, 6);
+ dprintk(verbose, DST_ERROR, 1, "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]",
+ state->mac_address[0], state->mac_address[1], state->mac_address[2],
+ state->mac_address[4], state->mac_address[5], state->mac_address[6]);
+
+ return 0;
+}
+
+static int dst_fw_ver(struct dst_state *state)
+{
+ u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_ver[7] = dst_check_sum(get_ver, 7);
+ if (dst_command(state, get_ver, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->fw_version, '\0', 8);
+ memcpy(&state->fw_version, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
+ state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
+ state->fw_version[1],
+ state->fw_version[5], state->fw_version[6],
+ state->fw_version[4], state->fw_version[3], state->fw_version[2]);
+
+ return 0;
+}
+
+static int dst_card_type(struct dst_state *state)
+{
+ u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_type[7] = dst_check_sum(get_type, 7);
+ if (dst_command(state, get_type, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->card_info, '\0', 8);
+ memcpy(&state->card_info, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+
+ return 0;
+}
+
+static int dst_get_vendor(struct dst_state *state)
+{
+ u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ get_vendor[7] = dst_check_sum(get_vendor, 7);
+ if (dst_command(state, get_vendor, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+ return -1;
+ }
+ memset(&state->vendor, '\0', 8);
+ memcpy(&state->vendor, &state->rxbuffer, 8);
+ dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
+
+ return 0;
+}
static int dst_get_device_id(struct dst_state *state)
{
@@ -772,53 +811,45 @@ static int dst_get_device_id(struct dst_state *state)
if (write_dst(state, device_type, FIXED_COMM))
return -1; /* Write failed */
-
if ((dst_pio_disable(state)) < 0)
return -1;
-
if (read_dst(state, &reply, GET_ACK))
return -1; /* Read failure */
-
if (reply != ACK) {
- dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", __FUNCTION__, reply);
+ dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
return -1; /* Unack'd write */
}
-
if (!dst_wait_dst_ready(state, DEVICE_INIT))
return -1; /* DST not ready yet */
-
if (read_dst(state, state->rxbuffer, FIXED_COMM))
return -1;
dst_pio_disable(state);
-
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
- dprintk("%s: Checksum failure! \n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Checksum failure!");
return -1; /* Checksum failure */
}
-
state->rxbuffer[7] = '\0';
- for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, p_dst_type++) {
+ for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
use_type_flags = p_dst_type->type_flags;
use_dst_type = p_dst_type->dst_type;
/* Card capabilities */
state->dst_hw_cap = p_dst_type->dst_feature;
- printk ("%s: Recognise [%s]\n", __FUNCTION__, p_dst_type->device_id);
+ dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
break;
}
}
if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
- printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, &state->rxbuffer[0], &state->rxbuffer[1]);
- printk("%s: please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
+ dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
use_dst_type = DST_TYPE_IS_SAT;
use_type_flags = DST_TYPE_HAS_SYMDIV;
}
-
dst_type_print(use_dst_type);
state->type_flags = use_type_flags;
state->dst_type = use_dst_type;
@@ -834,7 +865,7 @@ static int dst_get_device_id(struct dst_state *state)
static int dst_probe(struct dst_state *state)
{
if ((rdc_8820_reset(state)) < 0) {
- dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
return -1;
}
if (dst_addons & DST_TYPE_HAS_CA)
@@ -843,80 +874,87 @@ static int dst_probe(struct dst_state *state)
msleep(100);
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
return -1;
}
msleep(100);
if (dst_get_device_id(state) < 0) {
- dprintk("%s: unknown device.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "unknown device.");
return -1;
}
+ if (dst_get_mac(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
+ return 0;
+ }
+ if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
+ if (dst_fw_ver(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
+ return 0;
+ }
+ if (dst_card_type(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
+ return 0;
+ }
+ if (dst_get_vendor(state) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
+ return 0;
+ }
+ }
return 0;
}
-int dst_command(struct dst_state* state, u8 * data, u8 len)
+int dst_command(struct dst_state *state, u8 *data, u8 len)
{
u8 reply;
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Communication Initialization Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
return -1;
}
-
if (write_dst(state, data, len)) {
- if (verbose > 1)
- dprintk("%s: Tring to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
return -1;
}
return -1;
}
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
return -1;
}
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
-
if (read_dst(state, &reply, GET_ACK)) {
- if (verbose > 1)
- dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
return -1;
}
return -1;
}
-
if (reply != ACK) {
- dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+ dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
return -1;
}
if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
return 0;
-
-// udelay(3000);
if (state->type_flags & DST_TYPE_HAS_FW_1)
udelay(3000);
else
udelay(2000);
-
if (!dst_wait_dst_ready(state, NO_DELAY))
return -1;
-
if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
- if (verbose > 1)
- dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
if ((dst_error_recovery(state)) < 0) {
- dprintk("%s: Recovery failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "Recovery failed.");
return -1;
}
return -1;
}
-
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
- dprintk("%s: checksum failure\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure");
return -1;
}
@@ -924,11 +962,11 @@ int dst_command(struct dst_state* state, u8 * data, u8 len)
}
EXPORT_SYMBOL(dst_command);
-static int dst_get_signal(struct dst_state* state)
+static int dst_get_signal(struct dst_state *state)
{
int retval;
u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
- dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+ //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
state->decode_lock = state->decode_strength = state->decode_snr = 0;
return 0;
@@ -955,13 +993,12 @@ static int dst_get_signal(struct dst_state* state)
return 0;
}
-static int dst_tone_power_cmd(struct dst_state* state)
+static int dst_tone_power_cmd(struct dst_state *state)
{
u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
if (state->dst_type == DST_TYPE_IS_TERR)
return 0;
-
paket[4] = state->tx_tuna[4];
paket[2] = state->tx_tuna[2];
paket[3] = state->tx_tuna[3];
@@ -971,61 +1008,53 @@ static int dst_tone_power_cmd(struct dst_state* state)
return 0;
}
-static int dst_get_tuna(struct dst_state* state)
+static int dst_get_tuna(struct dst_state *state)
{
int retval;
if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
return 0;
-
state->diseq_flags &= ~(HAS_LOCK);
if (!dst_wait_dst_ready(state, NO_DELAY))
return 0;
-
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+ if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
/* how to get variable length reply ???? */
retval = read_dst(state, state->rx_tuna, 10);
- } else {
+ else
retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
- }
-
if (retval < 0) {
- dprintk("%s: read not successful\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "read not successful");
return 0;
}
-
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
- dprintk("%s: checksum failure?\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
return 0;
}
} else {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
- dprintk("%s: checksum failure?\n", __FUNCTION__);
+ dprintk(verbose, DST_INFO, 1, "checksum failure? ");
return 0;
}
}
if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
return 0;
state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
-
state->decode_lock = 1;
state->diseq_flags |= HAS_LOCK;
return 1;
}
-static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-static int dst_write_tuna(struct dvb_frontend* fe)
+static int dst_write_tuna(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
int retval;
u8 reply;
- if (debug > 4)
- dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
-
+ dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
state->decode_freq = 0;
state->decode_lock = state->decode_strength = state->decode_snr = 0;
if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1035,35 +1064,31 @@ static int dst_write_tuna(struct dvb_frontend* fe)
state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
if ((dst_comm_init(state)) < 0) {
- dprintk("%s: DST Communication initialization failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
return -1;
}
-
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
retval = write_dst(state, &state->tx_tuna[0], 10);
-
} else {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
}
if (retval < 0) {
dst_pio_disable(state);
- dprintk("%s: write not successful\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "write not successful");
return retval;
}
-
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
return -1;
}
-
if ((read_dst(state, &reply, GET_ACK) < 0)) {
- dprintk("%s: read verify not successful.\n", __FUNCTION__);
+ dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
return -1;
}
if (reply != ACK) {
- dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+ dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
return 0;
}
state->diseq_flags |= ATTEMPT_TUNE;
@@ -1085,14 +1110,13 @@ static int dst_write_tuna(struct dvb_frontend* fe)
* Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
*/
-static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
-
if (cmd->msg_len == 0 || cmd->msg_len > 4)
return -EINVAL;
memcpy(&paket[3], cmd->msg, cmd->msg_len);
@@ -1101,65 +1125,61 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd*
return 0;
}
-static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
int need_cmd;
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
state->voltage = voltage;
-
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
need_cmd = 0;
- switch (voltage) {
- case SEC_VOLTAGE_13:
- case SEC_VOLTAGE_18:
- if ((state->diseq_flags & HAS_POWER) == 0)
- need_cmd = 1;
- state->diseq_flags |= HAS_POWER;
- state->tx_tuna[4] = 0x01;
- break;
- case SEC_VOLTAGE_OFF:
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ case SEC_VOLTAGE_18:
+ if ((state->diseq_flags & HAS_POWER) == 0)
need_cmd = 1;
- state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
- state->tx_tuna[4] = 0x00;
- break;
-
- default:
- return -EINVAL;
+ state->diseq_flags |= HAS_POWER;
+ state->tx_tuna[4] = 0x01;
+ break;
+ case SEC_VOLTAGE_OFF:
+ need_cmd = 1;
+ state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+ state->tx_tuna[4] = 0x00;
+ break;
+ default:
+ return -EINVAL;
}
+
if (need_cmd)
dst_tone_power_cmd(state);
return 0;
}
-static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
state->tone = tone;
-
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
switch (tone) {
- case SEC_TONE_OFF:
- if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
- state->tx_tuna[2] = 0x00;
- else
- state->tx_tuna[2] = 0xff;
-
- break;
-
- case SEC_TONE_ON:
- state->tx_tuna[2] = 0x02;
- break;
+ case SEC_TONE_OFF:
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+ state->tx_tuna[2] = 0x00;
+ else
+ state->tx_tuna[2] = 0xff;
+ break;
- default:
- return -EINVAL;
+ case SEC_TONE_ON:
+ state->tx_tuna[2] = 0x02;
+ break;
+ default:
+ return -EINVAL;
}
dst_tone_power_cmd(state);
@@ -1172,16 +1192,14 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
-
state->minicmd = minicmd;
-
switch (minicmd) {
- case SEC_MINI_A:
- state->tx_tuna[3] = 0x02;
- break;
- case SEC_MINI_B:
- state->tx_tuna[3] = 0xff;
- break;
+ case SEC_MINI_A:
+ state->tx_tuna[3] = 0x02;
+ break;
+ case SEC_MINI_B:
+ state->tx_tuna[3] = 0xff;
+ break;
}
dst_tone_power_cmd(state);
@@ -1189,42 +1207,37 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
}
-static int dst_init(struct dvb_frontend* fe)
+static int dst_init(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
- static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
- static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
- static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
- static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-// state->inversion = INVERSION_ON;
+ struct dst_state *state = fe->demodulator_priv;
+
+ static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
+ static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
+ static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+
state->inversion = INVERSION_OFF;
state->voltage = SEC_VOLTAGE_13;
state->tone = SEC_TONE_OFF;
- state->symbol_rate = 29473000;
- state->fec = FEC_AUTO;
state->diseq_flags = 0;
state->k22 = 0x02;
state->bandwidth = BANDWIDTH_7_MHZ;
state->cur_jiff = jiffies;
- if (state->dst_type == DST_TYPE_IS_SAT) {
- state->frequency = 950000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna));
- } else if (state->dst_type == DST_TYPE_IS_TERR) {
- state->frequency = 137000000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna));
- } else if (state->dst_type == DST_TYPE_IS_CABLE) {
- state->frequency = 51000000;
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna));
- }
+ if (state->dst_type == DST_TYPE_IS_SAT)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+ else if (state->dst_type == DST_TYPE_IS_TERR)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+ else if (state->dst_type == DST_TYPE_IS_CABLE)
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
return 0;
}
-static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
*status = 0;
if (state->diseq_flags & HAS_LOCK) {
@@ -1236,9 +1249,9 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_get_signal(state);
*strength = state->decode_strength;
@@ -1246,9 +1259,9 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
return 0;
}
-static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
+static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_get_signal(state);
*snr = state->decode_snr;
@@ -1256,28 +1269,24 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
-static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
dst_set_freq(state, p->frequency);
- if (verbose > 4)
- dprintk("Set Frequency=[%d]\n", p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
-// dst_set_inversion(state, p->inversion);
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
-
dst_set_fec(state, p->u.qpsk.fec_inner);
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
dst_set_polarization(state);
- if (verbose > 4)
- dprintk("Set Symbolrate=[%d]\n", p->u.qpsk.symbol_rate);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
- } else if (state->dst_type == DST_TYPE_IS_TERR) {
+ } else if (state->dst_type == DST_TYPE_IS_TERR)
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
- } else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ else if (state->dst_type == DST_TYPE_IS_CABLE) {
dst_set_fec(state, p->u.qam.fec_inner);
dst_set_symbolrate(state, p->u.qam.symbol_rate);
dst_set_modulation(state, p->u.qam.modulation);
@@ -1287,16 +1296,14 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
return 0;
}
-static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
p->frequency = state->decode_freq;
-// p->inversion = state->inversion;
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
p->inversion = state->inversion;
-
p->u.qpsk.symbol_rate = state->symbol_rate;
p->u.qpsk.fec_inner = dst_get_fec(state);
} else if (state->dst_type == DST_TYPE_IS_TERR) {
@@ -1304,16 +1311,15 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
p->u.qam.symbol_rate = state->symbol_rate;
p->u.qam.fec_inner = dst_get_fec(state);
-// p->u.qam.modulation = QAM_AUTO;
p->u.qam.modulation = dst_get_modulation(state);
}
return 0;
}
-static void dst_release(struct dvb_frontend* fe)
+static void dst_release(struct dvb_frontend *fe)
{
- struct dst_state* state = fe->demodulator_priv;
+ struct dst_state *state = fe->demodulator_priv;
kfree(state);
}
@@ -1321,9 +1327,8 @@ static struct dvb_frontend_ops dst_dvbt_ops;
static struct dvb_frontend_ops dst_dvbs_ops;
static struct dvb_frontend_ops dst_dvbc_ops;
-struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
+struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
{
-
/* check if the ASIC is there */
if (dst_probe(state) < 0) {
if (state)
@@ -1336,17 +1341,14 @@ struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
case DST_TYPE_IS_TERR:
memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
break;
-
case DST_TYPE_IS_CABLE:
memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
break;
-
case DST_TYPE_IS_SAT:
memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
break;
-
default:
- printk("%s: unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n", __FUNCTION__);
+ dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
if (state)
kfree(state);
@@ -1374,12 +1376,9 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
@@ -1401,16 +1400,12 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
-
.diseqc_send_burst = dst_send_burst,
.diseqc_send_master_cmd = dst_set_diseqc,
.set_voltage = dst_set_voltage,
@@ -1432,18 +1427,14 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
},
.release = dst_release,
-
.init = dst_init,
-
.set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
-
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
};
-
MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
MODULE_AUTHOR("Jamie Honan, Manu Abraham");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index bfaacd5fc20f..6776a592045f 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -18,30 +18,42 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
-
#include <linux/dvb/ca.h>
#include "dvbdev.h"
#include "dvb_frontend.h"
-
#include "dst_ca.h"
#include "dst_common.h"
+#define DST_CA_ERROR 0
+#define DST_CA_NOTICE 1
+#define DST_CA_INFO 2
+#define DST_CA_DEBUG 3
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_CA_ERROR) && (x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_INFO) && (x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
+ else if ((x > DST_CA_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ## arg); \
+ } \
+} while(0)
+
+
static unsigned int verbose = 5;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
-
-#define dprintk if (debug) printk
-
/* Need some more work */
static int ca_set_slot_descr(void)
{
@@ -61,27 +73,20 @@ static int put_checksum(u8 *check_string, int length)
{
u8 i = 0, checksum = 0;
- if (verbose > 3) {
- dprintk("%s: ========================= Checksum calculation ===========================\n", __FUNCTION__);
- dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ========================= Checksum calculation ===========================");
+ dprintk(verbose, DST_CA_DEBUG, 1, " String Length=[0x%02x]", length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " String=[");
- dprintk("%s: String=[", __FUNCTION__);
- }
while (i < length) {
- if (verbose > 3)
- dprintk(" %02x", check_string[i]);
+ dprintk(verbose, DST_CA_DEBUG, 0, " %02x", check_string[i]);
checksum += check_string[i];
i++;
}
- if (verbose > 3) {
- dprintk(" ]\n");
- dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
- }
+ dprintk(verbose, DST_CA_DEBUG, 0, " ]\n");
+ dprintk(verbose, DST_CA_DEBUG, 1, "Sum=[%02x]\n", checksum);
check_string[length] = ~checksum + 1;
- if (verbose > 3) {
- dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, check_string[length]);
- dprintk("%s: ==========================================================================\n", __FUNCTION__);
- }
+ dprintk(verbose, DST_CA_DEBUG, 1, " Checksum=[%02x]", check_string[length]);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ==========================================================================");
return 0;
}
@@ -94,30 +99,26 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8
msleep(65);
if (write_dst(state, data, len)) {
- dprintk("%s: Write not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
-
if ((dst_pio_disable(state)) < 0) {
- dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
return -1;
}
-
if (read_dst(state, &reply, GET_ACK) < 0) {
- dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
-
if (read) {
if (! dst_wait_dst_ready(state, LONG_DELAY)) {
- dprintk("%s: 8820 not ready\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
return -1;
}
-
if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
- dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
dst_error_recovery(state);
return -1;
}
@@ -133,8 +134,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
while (dst_ca_comm_err < RETRIES) {
dst_comm_init(state);
- if (verbose > 2)
- dprintk("%s: Put Command\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
if (dst_ci_command(state, data, ca_string, len, read)) { // If error
dst_error_recovery(state);
dst_ca_comm_err++; // work required here.
@@ -153,18 +153,15 @@ static int ca_get_app_info(struct dst_state *state)
put_checksum(&command[0], command[0]);
if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1) {
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
-
- dprintk("%s: ================================ CI Module Application Info ======================================\n", __FUNCTION__);
- dprintk("%s: Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]\n",
- __FUNCTION__, state->messages[7], (state->messages[8] << 8) | state->messages[9],
- (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
- dprintk("%s: ==================================================================================================\n", __FUNCTION__);
- }
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+ dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+ dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+ state->messages[7], (state->messages[8] << 8) | state->messages[9],
+ (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+ dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
return 0;
}
@@ -177,31 +174,26 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
put_checksum(&slot_command[0], slot_command[0]);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1)
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
/* Will implement the rest soon */
- if (verbose > 1) {
- dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
- dprintk("===================================\n");
- for (i = 0; i < 8; i++)
- dprintk(" %d", slot_cap[i]);
- dprintk("\n");
- }
+ dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
+ dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
+ dprintk(verbose, DST_CA_INFO, 0, "\n");
p_ca_caps->slot_num = 1;
p_ca_caps->slot_type = 1;
p_ca_caps->descr_num = slot_cap[7];
p_ca_caps->descr_type = 1;
-
- if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) {
+ if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps)))
return -EFAULT;
- }
return 0;
}
@@ -222,46 +214,37 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s
put_checksum(&slot_command[0], 7);
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
- dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
return -1;
}
- if (verbose > 1)
- dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
/* Will implement the rest soon */
- if (verbose > 1) {
- dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
- dprintk("===================================\n");
- for (i = 0; i < 8; i++)
- dprintk(" %d", slot_info[i]);
- dprintk("\n");
- }
+ dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
+ dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
+ dprintk(verbose, DST_CA_INFO, 0, "\n");
if (slot_info[4] & 0x80) {
p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
p_ca_slot_info->num = 1;
p_ca_slot_info->type = CA_CI;
- }
- else if (slot_info[4] & 0x40) {
+ } else if (slot_info[4] & 0x40) {
p_ca_slot_info->flags = CA_CI_MODULE_READY;
p_ca_slot_info->num = 1;
p_ca_slot_info->type = CA_CI;
- }
- else {
+ } else
p_ca_slot_info->flags = 0;
- }
- if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) {
+ if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
return -EFAULT;
- }
return 0;
}
-
-
static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
{
u8 i = 0;
@@ -270,24 +253,21 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
return -EFAULT;
-
if (p_ca_message->msg) {
- if (verbose > 3)
- dprintk("Message = [%02x %02x %02x]\n", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
for (i = 0; i < 3; i++) {
command = command | p_ca_message->msg[i];
if (i < 2)
command = command << 8;
}
- if (verbose > 3)
- dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
switch (command) {
- case CA_APP_INFO:
- memcpy(p_ca_message->msg, state->messages, 128);
- if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
- return -EFAULT;
+ case CA_APP_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
break;
}
}
@@ -298,10 +278,13 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
{
if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
- hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
- hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
- }
- else {
+ hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
+ hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
+ } else {
+ if (length > 247) {
+ dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
+ return -1;
+ }
hw_buffer->msg[0] = (length & 0xff) + 7;
hw_buffer->msg[1] = 0x40;
hw_buffer->msg[2] = 0x03;
@@ -309,6 +292,11 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
hw_buffer->msg[4] = 0x03;
hw_buffer->msg[5] = length & 0xff;
hw_buffer->msg[6] = 0x00;
+ /*
+ * Need to compute length for EN50221 section 8.3.2, for the time being
+ * assuming 8.3.2 is not applicable
+ */
+ memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
}
return 0;
}
@@ -317,13 +305,12 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
{
if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
- dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
- dprintk("%s: Resetting DST.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
+ dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
rdc_reset_state(state);
return -1;
}
- if (verbose > 2)
- dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
return 0;
}
@@ -334,130 +321,47 @@ u32 asn_1_decode(u8 *asn_1_array)
u32 length = 0;
length_field = asn_1_array[0];
- dprintk("%s: Length field=[%02x]\n", __FUNCTION__, length_field);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
if (length_field < 0x80) {
length = length_field & 0x7f;
- dprintk("%s: Length=[%02x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
} else {
word_count = length_field & 0x7f;
for (count = 0; count < word_count; count++) {
length = (length | asn_1_array[count + 1]) << 8;
- dprintk("%s: Length=[%04x]\n", __FUNCTION__, length);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
}
}
return length;
}
-static int init_buffer(u8 *buffer, u32 length)
-{
- u32 i;
- for (i = 0; i < length; i++)
- buffer[i] = 0;
-
- return 0;
-}
-
static int debug_string(u8 *msg, u32 length, u32 offset)
{
u32 i;
- dprintk(" String=[ ");
+ dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
for (i = offset; i < length; i++)
- dprintk("%02x ", msg[i]);
- dprintk("]\n");
-
- return 0;
-}
-
-static int copy_string(u8 *destination, u8 *source, u32 dest_offset, u32 source_offset, u32 length)
-{
- u32 i;
- dprintk("%s: Copying [", __FUNCTION__);
- for (i = 0; i < length; i++) {
- destination[i + dest_offset] = source[i + source_offset];
- dprintk(" %02x", source[i + source_offset]);
- }
- dprintk("]\n");
-
- return i;
-}
-
-static int modify_4_bits(u8 *message, u32 pos)
-{
- message[pos] &= 0x0f;
+ dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
+ dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
return 0;
}
-
-
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
{
- u32 length = 0, count = 0;
- u8 asn_1_words, program_header_length;
- u16 program_info_length = 0, es_info_length = 0;
- u32 hw_offset = 0, buf_offset = 0, i;
- u8 dst_tag_length;
+ u32 length = 0;
+ u8 tag_length = 8;
length = asn_1_decode(&p_ca_message->msg[3]);
- dprintk("%s: CA Message length=[%d]\n", __FUNCTION__, length);
- dprintk("%s: ASN.1 ", __FUNCTION__);
- debug_string(&p_ca_message->msg[4], length, 0); // length does not include tag and length
+ dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
+ debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */
- init_buffer(hw_buffer->msg, length);
+ memset(hw_buffer->msg, '\0', length);
handle_dst_tag(state, p_ca_message, hw_buffer, length);
+ put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
- hw_offset = 7;
- asn_1_words = 1; // just a hack to test, should compute this one
- buf_offset = 3;
- program_header_length = 6;
- dst_tag_length = 7;
-
-// debug_twinhan_ca_params(state, p_ca_message, hw_buffer, reply, query, length, hw_offset, buf_offset);
-// dprintk("%s: Program Header(BUF)", __FUNCTION__);
-// debug_string(&p_ca_message->msg[4], program_header_length, 0);
-// dprintk("%s: Copying Program header\n", __FUNCTION__);
- copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + asn_1_words), program_header_length);
- buf_offset += program_header_length, hw_offset += program_header_length;
- modify_4_bits(hw_buffer->msg, (hw_offset - 2));
- if (state->type_flags & DST_TYPE_HAS_INC_COUNT) { // workaround
- dprintk("%s: Probably an ASIC bug !!!\n", __FUNCTION__);
- debug_string(hw_buffer->msg, (hw_offset + program_header_length), 0);
- hw_buffer->msg[hw_offset - 1] += 1;
- }
-
-// dprintk("%s: Program Header(HW), Count=[%d]", __FUNCTION__, count);
-// debug_string(hw_buffer->msg, hw_offset, 0);
-
- program_info_length = ((program_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
- dprintk("%s: Program info length=[%02x]\n", __FUNCTION__, program_info_length);
- if (program_info_length) {
- count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + 1), (program_info_length + 1) ); // copy next elem, not current
- buf_offset += count, hw_offset += count;
-// dprintk("%s: Program level ", __FUNCTION__);
-// debug_string(hw_buffer->msg, hw_offset, 0);
- }
-
- buf_offset += 1;// hw_offset += 1;
- for (i = buf_offset; i < length; i++) {
-// dprintk("%s: Stream Header ", __FUNCTION__);
- count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, buf_offset, 5);
- modify_4_bits(hw_buffer->msg, (hw_offset + 3));
-
- hw_offset += 5, buf_offset += 5, i += 4;
-// debug_string(hw_buffer->msg, hw_offset, (hw_offset - 5));
- es_info_length = ((es_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
- dprintk("%s: ES info length=[%02x]\n", __FUNCTION__, es_info_length);
- if (es_info_length) {
- // copy descriptors @ STREAM level
- dprintk("%s: Descriptors @ STREAM level...!!! \n", __FUNCTION__);
- }
-
- }
- hw_buffer->msg[length + dst_tag_length] = dst_check_sum(hw_buffer->msg, (length + dst_tag_length));
-// dprintk("%s: Total length=[%d], Checksum=[%02x]\n", __FUNCTION__, (length + dst_tag_length), hw_buffer->msg[length + dst_tag_length]);
- debug_string(hw_buffer->msg, (length + dst_tag_length + 1), 0); // dst tags also
- write_to_8820(state, hw_buffer, (length + dst_tag_length + 1), reply); // checksum
+ debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */
+ write_to_8820(state, hw_buffer, (length + tag_length), reply);
return 0;
}
@@ -471,26 +375,24 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message
/* Do test board */
/* Not there yet but soon */
-
/* CA PMT Reply capable */
if (ca_pmt_reply_test) {
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
- dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
return -1;
}
/* Process CA PMT Reply */
/* will implement soon */
- dprintk("%s: Not there yet\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
}
/* CA PMT Reply not capable */
if (!ca_pmt_reply_test) {
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
- dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
return -1;
}
- if (verbose > 3)
- dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
/* put a dummy message */
}
@@ -506,11 +408,10 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
struct ca_msg *hw_buffer;
if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
- if (verbose > 3)
- dprintk("%s\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " ");
if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
return -EFAULT;
@@ -525,51 +426,35 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (i < 2)
command = command << 8;
}
- if (verbose > 3)
- dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
switch (command) {
- case CA_PMT:
- if (verbose > 3)
-// dprintk("Command = SEND_CA_PMT\n");
- dprintk("Command = SEND_CA_PMT\n");
-// if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
- if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
- dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_PMT Success !\n", __FUNCTION__);
-// retval = dummy_set_pmt(state, p_ca_message, hw_buffer, 0, 0);
-
- break;
-
- case CA_PMT_REPLY:
- if (verbose > 3)
- dprintk("Command = CA_PMT_REPLY\n");
- /* Have to handle the 2 basic types of cards here */
- if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
- dprintk("%s: -->CA_PMT_REPLY Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_PMT_REPLY Success !\n", __FUNCTION__);
-
- /* Certain boards do behave different ? */
-// retval = ca_set_pmt(state, p_ca_message, hw_buffer, 1, 1);
-
- case CA_APP_INFO_ENQUIRY: // only for debugging
- if (verbose > 3)
- dprintk("%s: Getting Cam Application information\n", __FUNCTION__);
-
- if ((ca_get_app_info(state)) < 0) {
- dprintk("%s: -->CA_APP_INFO_ENQUIRY Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 3)
- dprintk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
-
- break;
+ case CA_PMT:
+ dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
+ break;
+ case CA_PMT_REPLY:
+ dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
+ /* Have to handle the 2 basic types of cards here */
+ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
+ break;
+ case CA_APP_INFO_ENQUIRY: // only for debugging
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
+
+ if ((ca_get_app_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
+ break;
}
}
return 0;
@@ -584,121 +469,88 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct ca_msg *p_ca_message;
if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
- dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
-
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */
switch (cmd) {
- case CA_SEND_MSG:
- if (verbose > 1)
- dprintk("%s: Sending message\n", __FUNCTION__);
- if ((ca_send_message(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_SEND_MSG Failed !\n", __FUNCTION__);
- return -1;
- }
-
- break;
-
- case CA_GET_MSG:
- if (verbose > 1)
- dprintk("%s: Getting message\n", __FUNCTION__);
- if ((ca_get_message(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_GET_MSG Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_MSG Success !\n", __FUNCTION__);
-
- break;
-
- case CA_RESET:
- if (verbose > 1)
- dprintk("%s: Resetting DST\n", __FUNCTION__);
- dst_error_bailout(state);
- msleep(4000);
-
- break;
-
- case CA_GET_SLOT_INFO:
- if (verbose > 1)
- dprintk("%s: Getting Slot info\n", __FUNCTION__);
- if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
- dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", __FUNCTION__);
-
- break;
-
- case CA_GET_CAP:
- if (verbose > 1)
- dprintk("%s: Getting Slot capabilities\n", __FUNCTION__);
- if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
- dprintk("%s: -->CA_GET_CAP Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_CAP Success !\n", __FUNCTION__);
-
- break;
-
- case CA_GET_DESCR_INFO:
- if (verbose > 1)
- dprintk("%s: Getting descrambler description\n", __FUNCTION__);
- if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
- dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", __FUNCTION__);
-
- break;
-
- case CA_SET_DESCR:
- if (verbose > 1)
- dprintk("%s: Setting descrambler\n", __FUNCTION__);
- if ((ca_set_slot_descr()) < 0) {
- dprintk("%s: -->CA_SET_DESCR Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_SET_DESCR Success !\n", __FUNCTION__);
-
- break;
-
- case CA_SET_PID:
- if (verbose > 1)
- dprintk("%s: Setting PID\n", __FUNCTION__);
- if ((ca_set_pid()) < 0) {
- dprintk("%s: -->CA_SET_PID Failed !\n", __FUNCTION__);
- return -1;
- }
- if (verbose > 1)
- dprintk("%s: -->CA_SET_PID Success !\n", __FUNCTION__);
-
- default:
- return -EOPNOTSUPP;
- };
+ case CA_SEND_MSG:
+ dprintk(verbose, DST_CA_INFO, 1, " Sending message");
+ if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
+ return -1;
+ }
+ break;
+ case CA_GET_MSG:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting message");
+ if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
+ break;
+ case CA_RESET:
+ dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
+ dst_error_bailout(state);
+ msleep(4000);
+ break;
+ case CA_GET_SLOT_INFO:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
+ if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
+ break;
+ case CA_GET_CAP:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
+ if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
+ break;
+ case CA_GET_DESCR_INFO:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
+ if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
+ break;
+ case CA_SET_DESCR:
+ dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
+ if ((ca_set_slot_descr()) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
+ break;
+ case CA_SET_PID:
+ dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
+ if ((ca_set_pid()) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
+ default:
+ return -EOPNOTSUPP;
+ };
return 0;
}
static int dst_ca_open(struct inode *inode, struct file *file)
{
- if (verbose > 4)
- dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
try_module_get(THIS_MODULE);
return 0;
@@ -706,27 +558,24 @@ static int dst_ca_open(struct inode *inode, struct file *file)
static int dst_ca_release(struct inode *inode, struct file *file)
{
- if (verbose > 4)
- dprintk("%s:Device closed.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
module_put(THIS_MODULE);
return 0;
}
-static int dst_ca_read(struct file *file, char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
int bytes_read = 0;
- if (verbose > 4)
- dprintk("%s:Device read.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
return bytes_read;
}
-static int dst_ca_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
{
- if (verbose > 4)
- dprintk("%s:Device write.\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
return 0;
}
@@ -751,8 +600,7 @@ static struct dvb_device dvbdev_ca = {
int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
{
struct dvb_device *dvbdev;
- if (verbose > 4)
- dprintk("%s:registering DST-CA device\n", __FUNCTION__);
+ dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
return 0;
}
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index ef532a6aceaa..3281a6ca3685 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -61,7 +61,6 @@
#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
#define DST_TYPE_HAS_SESSION 128
-
#define RDC_8820_PIO_0_DISABLE 0
#define RDC_8820_PIO_0_ENABLE 1
#define RDC_8820_INT 2
@@ -114,6 +113,10 @@ struct dst_state {
fe_sec_mini_cmd_t minicmd;
fe_modulation_t modulation;
u8 messages[256];
+ u8 mac_address[8];
+ u8 fw_version[8];
+ u8 card_info[8];
+ u8 vendor[8];
};
struct dst_types {
@@ -124,15 +127,12 @@ struct dst_types {
u32 dst_feature;
};
-
-
struct dst_config
{
/* the ASIC i2c address */
u8 demod_address;
};
-
int rdc_reset_state(struct dst_state *state);
int rdc_8820_reset(struct dst_state *state);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 6f857c6091f3..c5c7672cd538 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -32,9 +32,7 @@
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
-
#include "dvb-bt8xx.h"
-
#include "bt878.h"
static int debug;
@@ -43,9 +41,11 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk( args... ) \
- do { \
+ do \
if (debug) printk(KERN_DEBUG args); \
- } while (0)
+ while (0)
+
+#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
static void dvb_bt8xx_task(unsigned long data)
{
@@ -119,14 +119,12 @@ static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci
unsigned int card_nr;
/* Hmm, n squared. Hope n is small */
- for (card_nr = 0; card_nr < bt878_num; card_nr++) {
+ for (card_nr = 0; card_nr < bt878_num; card_nr++)
if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
return &bt878[card_nr];
- }
return NULL;
}
-
static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
@@ -154,16 +152,21 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
unsigned char bs = 0;
unsigned char cp = 0;
- #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 542000000) cp = 0xb4;
- else if (params->frequency < 771000000) cp = 0xbc;
- else cp = 0xf4;
+ if (params->frequency < 542000000)
+ cp = 0xb4;
+ else if (params->frequency < 771000000)
+ cp = 0xbc;
+ else
+ cp = 0xf4;
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x08;
+ if (params->frequency == 0)
+ bs = 0x03;
+ else if (params->frequency < 443250000)
+ bs = 0x02;
+ else
+ bs = 0x08;
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
@@ -175,7 +178,6 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
}
static struct mt352_config thomson_dtt7579_config = {
-
.demod_address = 0x0f,
.demod_init = thomson_dtt7579_demod_init,
.pll_set = thomson_dtt7579_pll_set,
@@ -183,25 +185,26 @@ static struct mt352_config thomson_dtt7579_config = {
static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
- u32 freq = params->frequency;
-
- int i, a, n, pump;
- u32 band, pll;
+ u32 freq = params->frequency;
+ int i, a, n, pump;
+ u32 band, pll;
- u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
- 1576000,1718000,1856000,2036000,2150000};
- u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
- 0x00102000,0x00104000,0x00108000,0x00110000,
- 0x00120000,0x00140000};
+ u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
+ 1576000,1718000,1856000,2036000,2150000};
+ u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
+ 0x00102000,0x00104000,0x00108000,0x00110000,
+ 0x00120000,0x00140000};
-#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
+ #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
/* This is really the bit driving the tuner chip cx24108 */
- if(freq<950000) freq=950000; /* kHz */
- if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
+ if (freq<950000)
+ freq = 950000; /* kHz */
+ else if (freq>2150000)
+ freq = 2150000; /* satellite IF is 950..2150MHz */
/* decide which VCO to use for the input frequency */
for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
@@ -228,25 +231,22 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
cx24110_pll_write(fe,0x500c0000);
cx24110_pll_write(fe,0x83f1f800);
cx24110_pll_write(fe,pll);
-/* writereg(client,0x56,0x7f);*/
+ //writereg(client,0x56,0x7f);
return 0;
}
static int pinnsat_pll_init(struct dvb_frontend* fe)
{
- return 0;
+ return 0;
}
-
static struct cx24110_config pctvsat_config = {
-
.demod_address = 0x55,
.pll_init = pinnsat_pll_init,
.pll_set = cx24108_pll_set,
};
-
static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -258,15 +258,23 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
div = (36000000 + params->frequency + 83333) / 166666;
cfg = 0x88;
- if (params->frequency < 175000000) cpump = 2;
- else if (params->frequency < 390000000) cpump = 1;
- else if (params->frequency < 470000000) cpump = 2;
- else if (params->frequency < 750000000) cpump = 2;
- else cpump = 3;
+ if (params->frequency < 175000000)
+ cpump = 2;
+ else if (params->frequency < 390000000)
+ cpump = 1;
+ else if (params->frequency < 470000000)
+ cpump = 2;
+ else if (params->frequency < 750000000)
+ cpump = 2;
+ else
+ cpump = 3;
- if (params->frequency < 175000000) band_select = 0x0e;
- else if (params->frequency < 470000000) band_select = 0x05;
- else band_select = 0x03;
+ if (params->frequency < 175000000)
+ band_select = 0x0e;
+ else if (params->frequency < 470000000)
+ band_select = 0x05;
+ else
+ band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
@@ -285,14 +293,11 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
}
static struct sp887x_config microtune_mt7202dtf_config = {
-
.demod_address = 0x70,
.pll_set = microtune_mt7202dtf_pll_set,
.request_firmware = microtune_mt7202dtf_request_firmware,
};
-
-
static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
@@ -303,7 +308,6 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
udelay(2000);
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
@@ -323,28 +327,45 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
unsigned char bs = 0;
unsigned char cp = 0;
- #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 150000000) cp = 0xB4;
- else if (params->frequency < 173000000) cp = 0xBC;
- else if (params->frequency < 250000000) cp = 0xB4;
- else if (params->frequency < 400000000) cp = 0xBC;
- else if (params->frequency < 420000000) cp = 0xF4;
- else if (params->frequency < 470000000) cp = 0xFC;
- else if (params->frequency < 600000000) cp = 0xBC;
- else if (params->frequency < 730000000) cp = 0xF4;
- else cp = 0xFC;
-
- if (params->frequency < 150000000) bs = 0x01;
- else if (params->frequency < 173000000) bs = 0x01;
- else if (params->frequency < 250000000) bs = 0x02;
- else if (params->frequency < 400000000) bs = 0x02;
- else if (params->frequency < 420000000) bs = 0x02;
- else if (params->frequency < 470000000) bs = 0x02;
- else if (params->frequency < 600000000) bs = 0x08;
- else if (params->frequency < 730000000) bs = 0x08;
- else bs = 0x08;
+ if (params->frequency < 150000000)
+ cp = 0xB4;
+ else if (params->frequency < 173000000)
+ cp = 0xBC;
+ else if (params->frequency < 250000000)
+ cp = 0xB4;
+ else if (params->frequency < 400000000)
+ cp = 0xBC;
+ else if (params->frequency < 420000000)
+ cp = 0xF4;
+ else if (params->frequency < 470000000)
+ cp = 0xFC;
+ else if (params->frequency < 600000000)
+ cp = 0xBC;
+ else if (params->frequency < 730000000)
+ cp = 0xF4;
+ else
+ cp = 0xFC;
+
+ if (params->frequency < 150000000)
+ bs = 0x01;
+ else if (params->frequency < 173000000)
+ bs = 0x01;
+ else if (params->frequency < 250000000)
+ bs = 0x02;
+ else if (params->frequency < 400000000)
+ bs = 0x02;
+ else if (params->frequency < 420000000)
+ bs = 0x02;
+ else if (params->frequency < 470000000)
+ bs = 0x02;
+ else if (params->frequency < 600000000)
+ bs = 0x08;
+ else if (params->frequency < 730000000)
+ bs = 0x08;
+ else
+ bs = 0x08;
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
@@ -356,19 +377,15 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
}
static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
-
.demod_address = 0x0f,
.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
};
-
static struct dst_config dst_config = {
-
.demod_address = 0x55,
};
-
static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
{
struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
@@ -398,10 +415,8 @@ static void or51211_reset(struct dvb_frontend * fe)
*/
/* reset & PRM1,2&4 are outputs */
int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
- if (ret != 0) {
- printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR "
- "(%i)\n", ret);
- }
+ if (ret != 0)
+ printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000); /* Reset */
msleep(20);
/* Now set for normal operation */
@@ -417,7 +432,6 @@ static void or51211_sleep(struct dvb_frontend * fe)
}
static struct or51211_config or51211_config = {
-
.demod_address = 0x15,
.request_firmware = or51211_request_firmware,
.setmode = or51211_setmode,
@@ -425,7 +439,6 @@ static struct or51211_config or51211_config = {
.sleep = or51211_sleep,
};
-
static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -454,12 +467,84 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
}
static struct nxt6000_config vp3021_alps_tded4_config = {
-
.demod_address = 0x0a,
.clock_inversion = 1,
.pll_set = vp3021_alps_tded4_pll_set,
};
+static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
+{
+ static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
+ static u8 mt352_reset [] = { 0x50, 0x80 };
+ static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };
+ static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ udelay(2000);
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+ mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
+ mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+ return 0;
+}
+
+static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+{
+ u32 div;
+ struct dvb_ofdm_parameters *op = &params->u.ofdm;
+
+ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+ pllbuf[0] = 0xc2;
+ pllbuf[1] = (div >> 8) & 0x7F;
+ pllbuf[2] = div & 0xFF;
+ pllbuf[3] = 0x85;
+
+ dprintk("frequency %u, div %u\n", params->frequency, div);
+
+ if (params->frequency < 470000000)
+ pllbuf[4] = 0x02;
+ else if (params->frequency > 823000000)
+ pllbuf[4] = 0x88;
+ else
+ pllbuf[4] = 0x08;
+
+ if (op->bandwidth == 8)
+ pllbuf[4] |= 0x04;
+
+ return 0;
+}
+
+static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
+{
+ /*
+ * Reset the frontend, must be called before trying
+ * to initialise the MT352 or mt352_attach
+ * will fail.
+ *
+ * Presumably not required for the NXT6000 frontend.
+ *
+ */
+
+ int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
+ if (ret != 0)
+ printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
+
+ /* Pulse the reset line */
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low */
+ msleep(100);
+
+ bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+}
+
+static struct mt352_config digitv_alps_tded4_config = {
+ .demod_address = 0x0a,
+ .demod_init = digitv_alps_tded4_demod_init,
+ .pll_set = digitv_alps_tded4_pll_set,
+};
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
{
@@ -473,7 +558,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
- break;
}
break;
#endif
@@ -483,17 +567,28 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
#else
case BTTV_NEBULA_DIGITV:
#endif
+ /*
+ * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
+ * this would be a cleaner solution than trying each frontend in turn.
+ */
+
+ /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
if (card->fe != NULL) {
+ dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
break;
}
+
+ /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
+ digitv_alps_tded4_reset(card);
+ card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+
+ if (card->fe != NULL)
+ dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
break;
case BTTV_AVDVBT_761:
card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_AVDVBT_771:
@@ -501,7 +596,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
- break;
}
break;
@@ -522,54 +616,41 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
/* Attach other DST peripherals if any */
/* Conditional Access device */
- if (state->dst_hw_cap & DST_TYPE_HAS_CA) {
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA)
ret = dst_ca_attach(state, &card->dvb_adapter);
- }
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_PINNACLESAT:
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
case BTTV_PC_HDTV:
card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
- if (card->fe != NULL) {
- break;
- }
break;
}
- if (card->fe == NULL) {
+ if (card->fe == NULL)
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,
card->bt->dev->subsystem_device);
- } else {
+ else
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
printk("dvb-bt8xx: Frontend registration failed!\n");
if (card->fe->ops->release)
card->fe->ops->release(card->fe);
card->fe = NULL;
}
- }
}
static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
- THIS_MODULE)) < 0) {
+ if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
-
}
card->dvb_adapter.priv = card;
@@ -664,8 +745,7 @@ static int dvb_bt8xx_probe(struct device *dev)
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
card->i2c_adapter = &sub->core->i2c_adap;
- switch(sub->core->type)
- {
+ switch(sub->core->type) {
case BTTV_PINNACLESAT:
card->gpio_mode = 0x0400c060;
/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
@@ -751,7 +831,6 @@ static int dvb_bt8xx_probe(struct device *dev)
kfree(card);
return -EFAULT;
-
}
init_MUTEX(&card->bt->gpio_lock);
@@ -779,7 +858,8 @@ static int dvb_bt8xx_remove(struct device *dev)
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
- if (card->fe) dvb_unregister_frontend(card->fe);
+ if (card->fe)
+ dvb_unregister_frontend(card->fe);
dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 2923b3b0dd3c..9ec8e5bd6c1f 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -2,7 +2,7 @@
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
* Copyright (C) 1999-2001 Ralph Metzler & Marcus Metzler for convergence integrated media GmbH
* Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
*
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 226714085f58..7cf4c4a888ec 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
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 "100"
+ 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
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 7d8b3cad350b..a1607e7d6d6b 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -25,7 +25,6 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/pci.h>
@@ -36,7 +35,6 @@
#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)
@@ -49,7 +47,7 @@
#define STREAM_URB_COUNT (32)
#define STREAM_BUF_SIZE (512) /* bytes */
#define ENABLE_RC (1)
- #define RC_QUERY_INTERVAL (100) /* milliseconds */
+ #define RC_QUERY_INTERVAL (50) /* milliseconds */
#define QUERY_INTERVAL (333) /* milliseconds */
#endif
@@ -139,9 +137,12 @@ struct cinergyt2 {
struct urb *stream_urb [STREAM_URB_COUNT];
#ifdef ENABLE_RC
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char phys[64];
struct work_struct rc_query_work;
int rc_input_event;
+ u32 rc_last_code;
+ unsigned long last_event_jiffies;
#endif
};
@@ -156,7 +157,7 @@ struct cinergyt2_rc_event {
uint32_t value;
} __attribute__((packed));
-static const uint32_t rc_keys [] = {
+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,
@@ -683,60 +684,129 @@ static struct dvb_device cinergyt2_fe_template = {
};
#ifdef ENABLE_RC
+
static void cinergyt2_query_rc (void *data)
{
- struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
- char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS };
+ struct cinergyt2 *cinergyt2 = data;
+ char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
struct cinergyt2_rc_event rc_events[12];
- int n, len;
+ int n, len, i;
if (down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
- (char *) rc_events, sizeof(rc_events));
-
- for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
- int i;
+ (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);
+ cinergyt2->rc_input_event = KEY_MAX;
+ }
+ cinergyt2->rc_last_code = ~0;
+ }
+ goto out;
+ }
+ cinergyt2->last_event_jiffies = jiffies;
-/* dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/
+ 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 == ~0)
- {
- /**
- * keyrepeat bit. If we would handle this properly
- * we would need to emit down events as long the
- * keyrepeat goes, a up event if no further
- * repeat bits occur. Would need a timer to implement
- * and no other driver does this, so we simply
- * emit the last key up/down sequence again.
- */
+ rc_events[n].value == ~0) {
+ /* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
- for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); 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];
+ 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) {
- input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
- input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
- input_sync(&cinergyt2->rc_input_dev);
+ if (rc_events[n].value == cinergyt2->rc_last_code &&
+ cinergyt2->rc_last_code != ~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);
+ cinergyt2->rc_last_code = rc_events[n].value;
}
}
+out:
schedule_delayed_work(&cinergyt2->rc_query_work,
msecs_to_jiffies(RC_QUERY_INTERVAL));
up(&cinergyt2->sem);
}
-#endif
+
+static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
+{
+ struct input_dev *input_dev;
+ int i;
+
+ cinergyt2->rc_input_dev = 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 = ~0;
+ INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
+
+ input_dev->name = DRIVER_NAME " remote control";
+ input_dev->phys = cinergyt2->phys;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ for (i = 0; ARRAY_SIZE(rc_keys); i += 3)
+ set_bit(rc_keys[i + 2], input_dev->keybit);
+ input_dev->keycodesize = 0;
+ input_dev->keycodemax = 0;
+
+ input_register_device(cinergyt2->rc_input_dev);
+ schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
+}
+
+static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
+{
+ cancel_delayed_work(&cinergyt2->rc_query_work);
+ flush_scheduled_work();
+ input_unregister_device(cinergyt2->rc_input_dev);
+}
+
+static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
+{
+ cancel_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 (void *data)
{
@@ -772,7 +842,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
const struct usb_device_id *id)
{
struct cinergyt2 *cinergyt2;
- int i, err;
+ int err;
if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
dprintk(1, "out of memory?!?\n");
@@ -827,31 +897,17 @@ static int cinergyt2_probe (struct usb_interface *intf,
&cinergyt2_fe_template, cinergyt2,
DVB_DEVICE_FRONTEND);
-#ifdef ENABLE_RC
- init_input_dev(&cinergyt2->rc_input_dev);
-
- cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
- cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
- cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
- cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
-
- for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3)
- set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit);
-
- input_register_device(&cinergyt2->rc_input_dev);
-
- cinergyt2->rc_input_event = KEY_MAX;
+ err = cinergyt2_register_rc(cinergyt2);
+ if (err)
+ goto bailout;
- INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
return 0;
bailout:
dvb_dmxdev_release(&cinergyt2->dmxdev);
dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_adapter (&cinergyt2->adapter);
- cinergyt2_free_stream_urbs (cinergyt2);
+ dvb_unregister_adapter(&cinergyt2->adapter);
+ cinergyt2_free_stream_urbs(cinergyt2);
kfree(cinergyt2);
return -ENOMEM;
}
@@ -863,11 +919,7 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
if (down_interruptible(&cinergyt2->sem))
return;
-#ifdef ENABLE_RC
- cancel_delayed_work(&cinergyt2->rc_query_work);
- flush_scheduled_work();
- input_unregister_device(&cinergyt2->rc_input_dev);
-#endif
+ cinergyt2_unregister_rc(cinergyt2);
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
dvb_net_release(&cinergyt2->dvbnet);
@@ -888,11 +940,10 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
- if (state > 0) { /* state 0 seems to mean DEVICE_PM_ON */
+ if (state.event > PM_EVENT_ON) {
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-#ifdef ENABLE_RC
- cancel_delayed_work(&cinergyt2->rc_query_work);
-#endif
+
+ cinergyt2_suspend_rc(cinergyt2);
cancel_delayed_work(&cinergyt2->query_work);
if (cinergyt2->streaming)
cinergyt2_stop_stream_xfer(cinergyt2);
@@ -920,9 +971,8 @@ static int cinergyt2_resume (struct usb_interface *intf)
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
-#ifdef ENABLE_RC
- schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
+ cinergyt2_resume_rc(cinergyt2);
+
up(&cinergyt2->sem);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fb55eaa5c8e7..9719a3b30f78 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -30,6 +30,7 @@
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/time.h>
+#include <linux/dvb/dmx.h>
/*--------------------------------------------------------------------------*/
/* Common definitions */
@@ -124,9 +125,7 @@ struct dmx_ts_feed {
u16 pid,
int type,
enum dmx_ts_pes pes_type,
- size_t callback_length,
size_t circular_buffer_size,
- int descramble,
struct timespec timeout);
int (*start_filtering) (struct dmx_ts_feed* feed);
int (*stop_filtering) (struct dmx_ts_feed* feed);
@@ -159,7 +158,6 @@ struct dmx_section_feed {
int (*set) (struct dmx_section_feed* feed,
u16 pid,
size_t circular_buffer_size,
- int descramble,
int check_crc);
int (*allocate_filter) (struct dmx_section_feed* feed,
struct dmx_section_filter** filter);
@@ -207,7 +205,6 @@ struct dmx_frontend {
struct list_head connectivity_list; /* List of front-ends that can
be connected to a particular
demux */
- void* priv; /* Pointer to private data of the API client */
enum dmx_frontend_source source;
};
@@ -225,8 +222,6 @@ struct dmx_frontend {
#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
#define DMX_CRC_CHECKING 16
#define DMX_TS_DESCRAMBLING 32
-#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64
-#define DMX_MAC_ADDRESS_DESCRAMBLING 128
/*
* Demux resource type identifier.
@@ -244,9 +239,7 @@ struct dmx_frontend {
struct dmx_demux {
u32 capabilities; /* Bitfield of capability flags */
struct dmx_frontend* frontend; /* Front-end connected to the demux */
- struct list_head reg_list; /* List of registered demuxes */
void* priv; /* Pointer to private data of the API client */
- int users; /* Number of users */
int (*open) (struct dmx_demux* demux);
int (*close) (struct dmx_demux* demux);
int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
@@ -260,17 +253,6 @@ struct dmx_demux {
dmx_section_cb callback);
int (*release_section_feed) (struct dmx_demux* demux,
struct dmx_section_feed* feed);
- int (*descramble_mac_address) (struct dmx_demux* demux,
- u8* buffer1,
- size_t buffer1_length,
- u8* buffer2,
- size_t buffer2_length,
- u16 pid);
- int (*descramble_section_payload) (struct dmx_demux* demux,
- u8* buffer1,
- size_t buffer1_length,
- u8* buffer2, size_t buffer2_length,
- u16 pid);
int (*add_frontend) (struct dmx_demux* demux,
struct dmx_frontend* frontend);
int (*remove_frontend) (struct dmx_demux* demux,
@@ -282,20 +264,12 @@ struct dmx_demux {
int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
+ int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
+
+ int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
+
int (*get_stc) (struct dmx_demux* demux, unsigned int num,
u64 *stc, unsigned int *base);
};
-/*--------------------------------------------------------------------------*/
-/* Demux directory */
-/*--------------------------------------------------------------------------*/
-
-/*
- * DMX_DIR_ENTRY(): Casts elements in the list of registered
- * demuxes from the generic type struct list_head* to the type struct dmx_demux
- *.
- */
-
-#define DMX_DIR_ENTRY(list) list_entry(list, struct dmx_demux, reg_list)
-
#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 68050cd527cb..8028c3a5e287 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -571,7 +571,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
return ret;
}
- ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0,
+ ret=(*secfeed)->set(*secfeed, para->pid, 32768,
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
if (ret<0) {
@@ -654,7 +654,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
(*tsfeed)->priv = (void *) filter;
ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
- 188, 32768, 0, timeout);
+ 32768, timeout);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed);
@@ -929,6 +929,22 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg);
break;
+ case DMX_GET_CAPS:
+ if (!dmxdev->demux->get_caps) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
+ break;
+
+ case DMX_SET_SOURCE:
+ if (!dmxdev->demux->set_source) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = dmxdev->demux->set_source(dmxdev->demux, parg);
+ break;
+
case DMX_GET_STC:
if (!dmxdev->demux->get_stc) {
ret=-EINVAL;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 0eb9aa711fb0..2aa767f9bd7d 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -36,6 +36,7 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/rwsem.h>
+#include <linux/sched.h>
#include "dvb_ca_en50221.h"
#include "dvb_ringbuffer.h"
@@ -47,7 +48,7 @@ MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
#define dprintk if (dvb_ca_en50221_debug) printk
-#define INIT_TIMEOUT_SECS 5
+#define INIT_TIMEOUT_SECS 10
#define HOST_LINK_BUF_SIZE 0x200
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index ac9889d22288..dc476dda2b71 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -38,82 +38,52 @@
*/
// #define DVB_DEMUX_SECTION_LOSS_LOG
-
-static LIST_HEAD(dmx_muxs);
-
-
-static int dmx_register_demux(struct dmx_demux *demux)
-{
- demux->users = 0;
- list_add(&demux->reg_list, &dmx_muxs);
- return 0;
-}
-
-static int dmx_unregister_demux(struct dmx_demux* demux)
-{
- struct list_head *pos, *n, *head=&dmx_muxs;
-
- list_for_each_safe (pos, n, head) {
- if (DMX_DIR_ENTRY(pos) == demux) {
- if (demux->users>0)
- return -EINVAL;
- list_del(pos);
- return 0;
- }
- }
-
- return -ENODEV;
-}
-
-
/******************************************************************************
* static inlined helper functions
******************************************************************************/
-
static inline u16 section_length(const u8 *buf)
{
- return 3+((buf[1]&0x0f)<<8)+buf[2];
+ return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
}
-
static inline u16 ts_pid(const u8 *buf)
{
- return ((buf[1]&0x1f)<<8)+buf[2];
+ return ((buf[1] & 0x1f) << 8) + buf[2];
}
-
static inline u8 payload(const u8 *tsp)
{
- if (!(tsp[3] & 0x10)) // no payload?
+ if (!(tsp[3] & 0x10)) // no payload?
return 0;
- if (tsp[3] & 0x20) { // adaptation field?
- if (tsp[4] > 183) // corrupted data?
+
+ if (tsp[3] & 0x20) { // adaptation field?
+ if (tsp[4] > 183) // corrupted data?
return 0;
else
- return 184-1-tsp[4];
+ return 184 - 1 - tsp[4];
}
+
return 184;
}
-
-static u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len)
+static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len)
{
- return (f->feed.sec.crc_val = crc32_be (f->feed.sec.crc_val, src, len));
+ return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len));
}
-
-static void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_t len)
+static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s,
+ size_t len)
{
- memcpy (d, s, len);
+ memcpy(d, s, len);
}
-
/******************************************************************************
* Software filter functions
******************************************************************************/
-static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf)
+static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
int count = payload(buf);
int p;
@@ -123,32 +93,31 @@ static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u
if (count == 0)
return -1;
- p = 188-count;
+ p = 188 - count;
/*
- cc=buf[3]&0x0f;
- ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
- dvbdmxfeed->cc=cc;
+ cc = buf[3] & 0x0f;
+ ccok = ((feed->cc + 1) & 0x0f) == cc;
+ feed->cc = cc;
if (!ccok)
printk("missed packet!\n");
*/
- if (buf[1] & 0x40) // PUSI ?
+ if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa;
feed->peslen += count;
- return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+ return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
}
-
-static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
- struct dvb_demux_filter *f)
+static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
+ struct dvb_demux_filter *f)
{
u8 neq = 0;
int i;
- for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
if (f->maskandmode[i] & xor)
@@ -160,12 +129,11 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
if (f->doneq && !neq)
return 0;
- return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
- NULL, 0, &f->filter, DMX_OK);
+ return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
+ NULL, 0, &f->filter, DMX_OK);
}
-
-static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
+static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct dvb_demux_filter *f = feed->filter;
@@ -195,26 +163,24 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
return 0;
}
-
static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
{
struct dmx_section_feed *sec = &feed->feed.sec;
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- if(sec->secbufp < sec->tsfeedp)
- {
+ if (sec->secbufp < sec->tsfeedp) {
int i, n = sec->tsfeedp - sec->secbufp;
- /* section padding is done with 0xff bytes entirely.
- ** due to speed reasons, we won't check all of them
- ** but just first and last
- */
- if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff)
- {
+ /*
+ * Section padding is done with 0xff bytes entirely.
+ * Due to speed reasons, we won't check all of them
+ * but just first and last.
+ */
+ if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
printk("dvb_demux.c section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
printk("dvb_demux.c pad data:");
- for(i = 0; i < n; i++)
+ for (i = 0; i < n; i++)
printk(" %02x", sec->secbuf[i]);
printk("\n");
}
@@ -226,82 +192,81 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
}
/*
-** Losless Section Demux 1.4.1 by Emard
-** Valsecchi Patrick:
-** - middle of section A (no PUSI)
-** - end of section A and start of section B
-** (with PUSI pointing to the start of the second section)
-**
-** In this case, without feed->pusi_seen you'll receive a garbage section
-** consisting of the end of section A. Basically because tsfeedp
-** is incemented and the use=0 condition is not raised
-** when the second packet arrives.
-**
-** Fix:
-** when demux is started, let feed->pusi_seen = 0 to
-** prevent initial feeding of garbage from the end of
-** previous section. When you for the first time see PUSI=1
-** then set feed->pusi_seen = 1
-*/
-static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+ * Losless Section Demux 1.4.1 by Emard
+ * Valsecchi Patrick:
+ * - middle of section A (no PUSI)
+ * - end of section A and start of section B
+ * (with PUSI pointing to the start of the second section)
+ *
+ * In this case, without feed->pusi_seen you'll receive a garbage section
+ * consisting of the end of section A. Basically because tsfeedp
+ * is incemented and the use=0 condition is not raised
+ * when the second packet arrives.
+ *
+ * Fix:
+ * when demux is started, let feed->pusi_seen = 0 to
+ * prevent initial feeding of garbage from the end of
+ * previous section. When you for the first time see PUSI=1
+ * then set feed->pusi_seen = 1
+ */
+static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
+ const u8 *buf, u8 len)
{
struct dvb_demux *demux = feed->demux;
struct dmx_section_feed *sec = &feed->feed.sec;
u16 limit, seclen, n;
- if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
+ if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0;
- if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE)
- {
+ if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
printk("dvb_demux.c section buffer full loss: %d/%d\n",
- sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE);
+ sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
+ DMX_MAX_SECFEED_SIZE);
#endif
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
}
- if(len <= 0)
+ if (len <= 0)
return 0;
demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
sec->tsfeedp += len;
- /* -----------------------------------------------------
- ** Dump all the sections we can find in the data (Emard)
- */
-
+ /*
+ * Dump all the sections we can find in the data (Emard)
+ */
limit = sec->tsfeedp;
- if(limit > DMX_MAX_SECFEED_SIZE)
- return -1; /* internal error should never happen */
+ if (limit > DMX_MAX_SECFEED_SIZE)
+ return -1; /* internal error should never happen */
/* to be sure always set secbuf */
sec->secbuf = sec->secbuf_base + sec->secbufp;
- for(n = 0; sec->secbufp + 2 < limit; n++)
- {
+ for (n = 0; sec->secbufp + 2 < limit; n++) {
seclen = section_length(sec->secbuf);
- if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
- || seclen + sec->secbufp > limit)
+ if (seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
+ || seclen + sec->secbufp > limit)
return 0;
sec->seclen = seclen;
sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */
- if(feed->pusi_seen)
+ if (feed->pusi_seen)
dvb_dmx_swfilter_section_feed(feed);
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
else
printk("dvb_demux.c pusi not seen, discarding section data\n");
#endif
- sec->secbufp += seclen; /* secbufp and secbuf moving together is */
- sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
+ sec->secbufp += seclen; /* secbufp and secbuf moving together is */
+ sec->secbuf += seclen; /* redundant but saves pointer arithmetic */
}
return 0;
}
-
-static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
+static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
u8 p, count;
int ccok, dc_i = 0;
@@ -309,10 +274,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
count = payload(buf);
- if (count == 0) /* count == 0 if no payload or out of range */
+ if (count == 0) /* count == 0 if no payload or out of range */
return -1;
- p = 188 - count; /* payload start */
+ p = 188 - count; /* payload start */
cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc;
@@ -326,52 +291,53 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
if (!ccok || dc_i) {
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- printk("dvb_demux.c discontinuity detected %d bytes lost\n", count);
- /* those bytes under sume circumstances will again be reported
- ** in the following dvb_dmx_swfilter_section_new
- */
+ printk("dvb_demux.c discontinuity detected %d bytes lost\n",
+ count);
+ /*
+ * those bytes under sume circumstances will again be reported
+ * in the following dvb_dmx_swfilter_section_new
+ */
#endif
- /* Discontinuity detected. Reset pusi_seen = 0 to
- ** stop feeding of suspicious data until next PUSI=1 arrives
- */
+ /*
+ * Discontinuity detected. Reset pusi_seen = 0 to
+ * stop feeding of suspicious data until next PUSI=1 arrives
+ */
feed->pusi_seen = 0;
dvb_dmx_swfilter_section_new(feed);
- return 0;
}
if (buf[1] & 0x40) {
- // PUSI=1 (is set), section boundary is here
+ /* PUSI=1 (is set), section boundary is here */
if (count > 1 && buf[p] < count) {
- const u8 *before = buf+p+1;
+ const u8 *before = &buf[p + 1];
u8 before_len = buf[p];
- const u8 *after = before+before_len;
- u8 after_len = count-1-before_len;
+ const u8 *after = &before[before_len];
+ u8 after_len = count - 1 - before_len;
- dvb_dmx_swfilter_section_copy_dump(feed, before, before_len);
+ dvb_dmx_swfilter_section_copy_dump(feed, before,
+ before_len);
/* before start of new section, set pusi_seen = 1 */
feed->pusi_seen = 1;
dvb_dmx_swfilter_section_new(feed);
- dvb_dmx_swfilter_section_copy_dump(feed, after, after_len);
+ dvb_dmx_swfilter_section_copy_dump(feed, after,
+ after_len);
}
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- else
- if (count > 0)
- printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+ else if (count > 0)
+ printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
#endif
} else {
- // PUSI=0 (is not set), no section boundary
- const u8 *entire = buf+p;
- u8 entire_len = count;
-
- dvb_dmx_swfilter_section_copy_dump(feed, entire, entire_len);
+ /* PUSI=0 (is not set), no section boundary */
+ dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
}
+
return 0;
}
-
-static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf)
+static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
+ const u8 *buf)
{
- switch(feed->type) {
+ switch (feed->type) {
case DMX_TYPE_TS:
if (!feed->feed.ts.is_filtering)
break;
@@ -379,7 +345,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
- feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+ DMX_OK);
}
if (feed->ts_type & TS_DECODER)
if (feed->demux->write_to_decoder)
@@ -390,7 +357,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
if (!feed->feed.sec.is_filtering)
break;
if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
- feed->feed.sec.seclen = feed->feed.sec.secbufp=0;
+ feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
break;
default:
@@ -406,7 +373,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
{
struct dvb_demux_feed *feed;
- struct list_head *pos, *head=&demux->feed_list;
+ struct list_head *pos, *head = &demux->feed_list;
u16 pid = ts_pid(buf);
int dvr_done = 0;
@@ -432,21 +399,21 @@ 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)
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
+ size_t count)
{
spin_lock(&demux->lock);
while (count--) {
- if(buf[0] == 0x47) {
- dvb_dmx_swfilter_packet(demux, buf);
- }
+ if (buf[0] == 0x47)
+ dvb_dmx_swfilter_packet(demux, buf);
buf += 188;
}
spin_unlock(&demux->lock);
}
-EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
@@ -454,8 +421,10 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
spin_lock(&demux->lock);
- if ((i = demux->tsbufp)) {
- if (count < (j=188-i)) {
+ if (demux->tsbufp) {
+ i = demux->tsbufp;
+ j = 188 - i;
+ if (count < j) {
memcpy(&demux->tsbuf[i], buf, count);
demux->tsbufp += count;
goto bailout;
@@ -469,13 +438,13 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
while (p < count) {
if (buf[p] == 0x47) {
- if (count-p >= 188) {
- dvb_dmx_swfilter_packet(demux, buf+p);
+ if (count - p >= 188) {
+ dvb_dmx_swfilter_packet(demux, &buf[p]);
p += 188;
} else {
- i = count-p;
- memcpy(demux->tsbuf, buf+p, i);
- demux->tsbufp=i;
+ i = count - p;
+ memcpy(demux->tsbuf, &buf[p], i);
+ demux->tsbufp = i;
goto bailout;
}
} else
@@ -485,24 +454,29 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
bailout:
spin_unlock(&demux->lock);
}
+
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- int p = 0,i, j;
+ int p = 0, i, j;
u8 tmppack[188];
+
spin_lock(&demux->lock);
- if ((i = demux->tsbufp)) {
- if (count < (j=204-i)) {
+ if (demux->tsbufp) {
+ i = demux->tsbufp;
+ j = 204 - i;
+ if (count < j) {
memcpy(&demux->tsbuf[i], buf, count);
demux->tsbufp += count;
goto bailout;
}
memcpy(&demux->tsbuf[i], buf, j);
- if ((demux->tsbuf[0] == 0x47)|(demux->tsbuf[0]==0xB8)) {
+ if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
memcpy(tmppack, demux->tsbuf, 188);
- if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+ if (tmppack[0] == 0xB8)
+ tmppack[0] = 0x47;
dvb_dmx_swfilter_packet(demux, tmppack);
}
demux->tsbufp = 0;
@@ -510,16 +484,17 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
while (p < count) {
- if ((buf[p] == 0x47)|(buf[p] == 0xB8)) {
- if (count-p >= 204) {
- memcpy(tmppack, buf+p, 188);
- if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+ if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+ if (count - p >= 204) {
+ memcpy(tmppack, &buf[p], 188);
+ if (tmppack[0] == 0xB8)
+ tmppack[0] = 0x47;
dvb_dmx_swfilter_packet(demux, tmppack);
p += 204;
} else {
- i = count-p;
- memcpy(demux->tsbuf, buf+p, i);
- demux->tsbufp=i;
+ i = count - p;
+ memcpy(demux->tsbuf, &buf[p], i);
+ demux->tsbufp = i;
goto bailout;
}
} else {
@@ -530,14 +505,14 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
bailout:
spin_unlock(&demux->lock);
}
-EXPORT_SYMBOL(dvb_dmx_swfilter_204);
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
-static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
+static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
{
int i;
- for (i=0; i<demux->filternum; i++)
+ for (i = 0; i < demux->filternum; i++)
if (demux->filter[i].state == DMX_STATE_FREE)
break;
@@ -549,11 +524,11 @@ static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
return &demux->filter[i];
}
-static struct dvb_demux_feed * dvb_dmx_feed_alloc(struct dvb_demux *demux)
+static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux)
{
int i;
- for (i=0; i<demux->feednum; i++)
+ for (i = 0; i < demux->feednum; i++)
if (demux->feed[i].state == DMX_STATE_FREE)
break;
@@ -581,7 +556,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __FUNCTION__, feed->type, feed->state, feed->pid);
goto out;
}
@@ -595,7 +570,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __FUNCTION__, feed->type, feed->state, feed->pid);
goto out;
}
@@ -604,18 +579,17 @@ out:
spin_unlock_irq(&feed->demux->lock);
}
-static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
- enum dmx_ts_pes pes_type, size_t callback_length,
- size_t circular_buffer_size, int descramble,
- struct timespec timeout)
+static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
+ enum dmx_ts_pes pes_type,
+ size_t circular_buffer_size, struct timespec timeout)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
if (pid > DMX_MAX_PID)
return -EINVAL;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (ts_type & TS_DECODER) {
@@ -638,20 +612,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
feed->pid = pid;
feed->buffer_size = circular_buffer_size;
- feed->descramble = descramble;
feed->timeout = timeout;
- feed->cb_length = callback_length;
feed->ts_type = ts_type;
feed->pes_type = pes_type;
- if (feed->descramble) {
- up(&demux->mutex);
- return -ENOSYS;
- }
-
if (feed->buffer_size) {
#ifdef NOBUFS
- feed->buffer=NULL;
+ feed->buffer = NULL;
#else
feed->buffer = vmalloc(feed->buffer_size);
if (!feed->buffer) {
@@ -667,14 +634,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
return 0;
}
-
-static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
+static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
int ret;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
@@ -701,13 +667,13 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
return 0;
}
-static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
+static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
struct dvb_demux *demux = feed->demux;
int ret;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state < DMX_STATE_GO) {
@@ -731,13 +697,14 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
return ret;
}
-static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed,
- dmx_ts_cb callback)
+static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
+ struct dmx_ts_feed **ts_feed,
+ dmx_ts_cb callback)
{
- struct dvb_demux *demux = (struct dvb_demux *) dmx;
+ struct dvb_demux *demux = (struct dvb_demux *)dmx;
struct dvb_demux_feed *feed;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (!(feed = dvb_dmx_feed_alloc(demux))) {
@@ -760,7 +727,6 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
(*ts_feed)->set = dmx_ts_feed_set;
-
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
feed->state = DMX_STATE_FREE;
up(&demux->mutex);
@@ -776,22 +742,22 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
return 0;
}
-static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_feed)
+static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
+ struct dmx_ts_feed *ts_feed)
{
- struct dvb_demux *demux = (struct dvb_demux *) dmx;
- struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+ struct dvb_demux *demux = (struct dvb_demux *)dmx;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
- if (down_interruptible (&demux->mutex))
+ if (down_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (feed->state == DMX_STATE_FREE) {
up(&demux->mutex);
return -EINVAL;
}
-
#ifndef NOBUFS
vfree(feed->buffer);
- feed->buffer=0;
+ feed->buffer = NULL;
#endif
feed->state = DMX_STATE_FREE;
@@ -808,19 +774,18 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
return 0;
}
-
/******************************************************************************
* dmx_section_feed API calls
******************************************************************************/
-static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
- struct dmx_section_filter** filter)
+static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
+ struct dmx_section_filter **filter)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
struct dvb_demux_filter *dvbdmxfilter;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
@@ -844,36 +809,29 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
return 0;
}
-
-static int dmx_section_feed_set(struct dmx_section_feed* feed,
- u16 pid, size_t circular_buffer_size,
- int descramble, int check_crc)
+static int dmx_section_feed_set(struct dmx_section_feed *feed,
+ u16 pid, size_t circular_buffer_size,
+ int check_crc)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
if (pid > 0x1fff)
return -EINVAL;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
dvb_demux_feed_add(dvbdmxfeed);
dvbdmxfeed->pid = pid;
dvbdmxfeed->buffer_size = circular_buffer_size;
- dvbdmxfeed->descramble = descramble;
- if (dvbdmxfeed->descramble) {
- up(&dvbdmx->mutex);
- return -ENOSYS;
- }
-
dvbdmxfeed->feed.sec.check_crc = check_crc;
#ifdef NOBUFS
dvbdmxfeed->buffer = NULL;
#else
- dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
+ dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
if (!dvbdmxfeed->buffer) {
up(&dvbdmx->mutex);
return -ENOMEM;
@@ -885,7 +843,6 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
return 0;
}
-
static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
{
int i;
@@ -893,12 +850,12 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
struct dmx_section_filter *sf;
u8 mask, mode, doneq;
- if (!(f=dvbdmxfeed->filter))
+ if (!(f = dvbdmxfeed->filter))
return;
do {
sf = &f->filter;
doneq = 0;
- for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
mode = sf->filter_mode[i];
mask = sf->filter_mask[i];
f->maskandmode[i] = mask & mode;
@@ -908,14 +865,13 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
} while ((f = f->next));
}
-
static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (feed->is_filtering) {
@@ -954,14 +910,13 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
return 0;
}
-
-static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
+static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (!dvbdmx->stop_feed) {
@@ -980,15 +935,14 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
return ret;
}
-
static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
- struct dmx_section_filter* filter)
+ struct dmx_section_filter *filter)
{
- struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *) filter, *f;
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (dvbdmxfilter->feed != dvbdmxfeed) {
@@ -1005,7 +959,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
if (f == dvbdmxfilter) {
dvbdmxfeed->filter = dvbdmxfilter->next;
} else {
- while(f->next != dvbdmxfilter)
+ while (f->next != dvbdmxfilter)
f = f->next;
f->next = f->next->next;
}
@@ -1020,10 +974,10 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback)
{
- struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
struct dvb_demux_feed *dvbdmxfeed;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
@@ -1041,7 +995,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
dvbdmxfeed->filter = NULL;
dvbdmxfeed->buffer = NULL;
- (*feed)=&dvbdmxfeed->feed.sec;
+ (*feed) = &dvbdmxfeed->feed.sec;
(*feed)->is_filtering = 0;
(*feed)->parent = demux;
(*feed)->priv = NULL;
@@ -1059,21 +1013,21 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
static int dvbdmx_release_section_feed(struct dmx_demux *demux,
struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
- if (down_interruptible (&dvbdmx->mutex))
+ if (down_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
- if (dvbdmxfeed->state==DMX_STATE_FREE) {
+ if (dvbdmxfeed->state == DMX_STATE_FREE) {
up(&dvbdmx->mutex);
return -EINVAL;
}
#ifndef NOBUFS
vfree(dvbdmxfeed->buffer);
- dvbdmxfeed->buffer=0;
+ dvbdmxfeed->buffer = NULL;
#endif
- dvbdmxfeed->state=DMX_STATE_FREE;
+ dvbdmxfeed->state = DMX_STATE_FREE;
dvb_demux_feed_del(dvbdmxfeed);
@@ -1083,14 +1037,13 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
return 0;
}
-
/******************************************************************************
* dvb_demux kernel data API calls
******************************************************************************/
static int dvbdmx_open(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
return -EUSERS;
@@ -1099,10 +1052,9 @@ static int dvbdmx_open(struct dmx_demux *demux)
return 0;
}
-
static int dvbdmx_close(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (dvbdemux->users == 0)
return -ENODEV;
@@ -1112,15 +1064,14 @@ static int dvbdmx_close(struct dmx_demux *demux)
return 0;
}
-
static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
return -EINVAL;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
dvb_dmx_swfilter(dvbdemux, buf, count);
up(&dvbdemux->mutex);
@@ -1130,10 +1081,10 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
return count;
}
-
-static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_add_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
struct list_head *head = &dvbdemux->frontend_list;
list_add(&(frontend->connectivity_list), head);
@@ -1141,13 +1092,13 @@ static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *fro
return 0;
}
-
-static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_remove_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
- list_for_each_safe (pos, n, head) {
+ list_for_each_safe(pos, n, head) {
if (DMX_FE_ENTRY(pos) == frontend) {
list_del(pos);
return 0;
@@ -1157,25 +1108,25 @@ static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *
return -ENODEV;
}
-
-static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux)
+static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (list_empty(&dvbdemux->frontend_list))
return NULL;
+
return &dvbdemux->frontend_list;
}
-
-static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_connect_frontend(struct dmx_demux *demux,
+ struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (demux->frontend)
return -EINVAL;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
demux->frontend = frontend;
@@ -1183,12 +1134,11 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend
return 0;
}
-
static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- if (down_interruptible (&dvbdemux->mutex))
+ if (down_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
demux->frontend = NULL;
@@ -1196,44 +1146,42 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
return 0;
}
-
-static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
+static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
{
- struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
+ memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
return 0;
}
-
int dvb_dmx_init(struct dvb_demux *dvbdemux)
{
- int i, err;
+ int i;
struct dmx_demux *dmx = &dvbdemux->dmx;
dvbdemux->users = 0;
- dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
+ dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
if (!dvbdemux->filter)
return -ENOMEM;
- dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
+ dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
if (!dvbdemux->feed) {
vfree(dvbdemux->filter);
return -ENOMEM;
}
- for (i=0; i<dvbdemux->filternum; i++) {
+ for (i = 0; i < dvbdemux->filternum; i++) {
dvbdemux->filter[i].state = DMX_STATE_FREE;
dvbdemux->filter[i].index = i;
}
- for (i=0; i<dvbdemux->feednum; i++) {
+ for (i = 0; i < dvbdemux->feednum; i++) {
dvbdemux->feed[i].state = DMX_STATE_FREE;
dvbdemux->feed[i].index = i;
}
- dvbdemux->frontend_list.next=
- dvbdemux->frontend_list.prev=
- &dvbdemux->frontend_list;
- for (i=0; i<DMX_TS_PES_OTHER; i++) {
+
+ INIT_LIST_HEAD(&dvbdemux->frontend_list);
+
+ for (i = 0; i < DMX_TS_PES_OTHER; i++) {
dvbdemux->pesfilter[i] = NULL;
dvbdemux->pids[i] = 0xffff;
}
@@ -1247,12 +1195,11 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
if (!dvbdemux->check_crc32)
dvbdemux->check_crc32 = dvb_dmx_crc32;
- if (!dvbdemux->memcopy)
- dvbdemux->memcopy = dvb_dmx_memcopy;
+ if (!dvbdemux->memcopy)
+ dvbdemux->memcopy = dvb_dmx_memcopy;
dmx->frontend = NULL;
- dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list;
- dmx->priv = (void *) dvbdemux;
+ dmx->priv = dvbdemux;
dmx->open = dvbdmx_open;
dmx->close = dvbdmx_close;
dmx->write = dvbdmx_write;
@@ -1261,9 +1208,6 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
dmx->release_section_feed = dvbdmx_release_section_feed;
- dmx->descramble_mac_address = NULL;
- dmx->descramble_section_payload = NULL;
-
dmx->add_frontend = dvbdmx_add_frontend;
dmx->remove_frontend = dvbdmx_remove_frontend;
dmx->get_frontends = dvbdmx_get_frontends;
@@ -1274,21 +1218,15 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
sema_init(&dvbdemux->mutex, 1);
spin_lock_init(&dvbdemux->lock);
- if ((err = dmx_register_demux(dmx)) < 0)
- return err;
-
return 0;
}
-EXPORT_SYMBOL(dvb_dmx_init);
+EXPORT_SYMBOL(dvb_dmx_init);
-int dvb_dmx_release(struct dvb_demux *dvbdemux)
+void dvb_dmx_release(struct dvb_demux *dvbdemux)
{
- struct dmx_demux *dmx = &dvbdemux->dmx;
-
- dmx_unregister_demux(dmx);
vfree(dvbdemux->filter);
vfree(dvbdemux->feed);
- return 0;
}
+
EXPORT_SYMBOL(dvb_dmx_release);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index c09beb391622..0cc888339d52 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -20,7 +20,6 @@
*
*/
-
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
@@ -44,103 +43,98 @@
#define DVB_DEMUX_MASK_MAX 18
struct dvb_demux_filter {
- struct dmx_section_filter filter;
- u8 maskandmode [DMX_MAX_FILTER_SIZE];
- u8 maskandnotmode [DMX_MAX_FILTER_SIZE];
+ struct dmx_section_filter filter;
+ u8 maskandmode[DMX_MAX_FILTER_SIZE];
+ u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
int doneq;
- struct dvb_demux_filter *next;
- struct dvb_demux_feed *feed;
- int index;
- int state;
- int type;
- int pesto;
-
- u16 handle;
- u16 hw_handle;
- struct timer_list timer;
- int ts_state;
-};
+ struct dvb_demux_filter *next;
+ struct dvb_demux_feed *feed;
+ int index;
+ int state;
+ int type;
+ u16 hw_handle;
+ struct timer_list timer;
+};
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
struct dvb_demux_feed {
- union {
- struct dmx_ts_feed ts;
- struct dmx_section_feed sec;
+ union {
+ struct dmx_ts_feed ts;
+ struct dmx_section_feed sec;
} feed;
- union {
- dmx_ts_cb ts;
- dmx_section_cb sec;
+ union {
+ dmx_ts_cb ts;
+ dmx_section_cb sec;
} cb;
- struct dvb_demux *demux;
+ struct dvb_demux *demux;
void *priv;
- int type;
- int state;
- u16 pid;
- u8 *buffer;
- int buffer_size;
- int descramble;
+ int type;
+ int state;
+ u16 pid;
+ u8 *buffer;
+ int buffer_size;
- struct timespec timeout;
- struct dvb_demux_filter *filter;
- int cb_length;
+ struct timespec timeout;
+ struct dvb_demux_filter *filter;
- int ts_type;
- enum dmx_ts_pes pes_type;
+ int ts_type;
+ enum dmx_ts_pes pes_type;
- int cc;
- int pusi_seen; /* prevents feeding of garbage from previous section */
+ int cc;
+ int pusi_seen; /* prevents feeding of garbage from previous section */
- u16 peslen;
+ u16 peslen;
struct list_head list_head;
- int index; /* a unique index for each feed (can be used as hardware pid filter index) */
+ unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
};
struct dvb_demux {
- struct dmx_demux dmx;
- void *priv;
- int filternum;
- int feednum;
- int (*start_feed) (struct dvb_demux_feed *feed);
- int (*stop_feed) (struct dvb_demux_feed *feed);
- int (*write_to_decoder) (struct dvb_demux_feed *feed,
+ struct dmx_demux dmx;
+ void *priv;
+ int filternum;
+ int feednum;
+ int (*start_feed)(struct dvb_demux_feed *feed);
+ int (*stop_feed)(struct dvb_demux_feed *feed);
+ int (*write_to_decoder)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
- u32 (*check_crc32) (struct dvb_demux_feed *feed,
+ u32 (*check_crc32)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
- void (*memcopy) (struct dvb_demux_feed *feed, u8 *dst,
+ void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
- int users;
+ int users;
#define MAX_DVB_DEMUX_USERS 10
- struct dvb_demux_filter *filter;
- struct dvb_demux_feed *feed;
+ struct dvb_demux_filter *filter;
+ struct dvb_demux_feed *feed;
- struct list_head frontend_list;
+ struct list_head frontend_list;
- struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
- u16 pids[DMX_TS_PES_OTHER];
- int playing;
- int recording;
+ struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
+ u16 pids[DMX_TS_PES_OTHER];
+ int playing;
+ int recording;
#define DMX_MAX_PID 0x2000
struct list_head feed_list;
- u8 tsbuf[204];
- int tsbufp;
+ u8 tsbuf[204];
+ int tsbufp;
struct semaphore mutex;
spinlock_t lock;
};
-
int dvb_dmx_init(struct dvb_demux *dvbdemux);
-int dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
+void dvb_dmx_release(struct dvb_demux *dvbdemux);
+void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
+ size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count);
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
+ size_t count);
#endif /* _DVB_DEMUX_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 6a968c346a36..87935490bfb2 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -62,7 +62,6 @@
#include <linux/uio.h>
#include <asm/uaccess.h>
#include <linux/crc32.h>
-#include <linux/version.h>
#include "dvb_demux.h"
#include "dvb_net.h"
@@ -171,11 +170,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
skb->mac.raw=skb->data;
skb_pull(skb,dev->hard_header_len);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
- eth = skb->mac.ethernet;
-#else
eth = eth_hdr(skb);
-#endif
if (*eth->h_dest & 1) {
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -908,7 +903,7 @@ static int dvb_net_feed_start(struct net_device *dev)
return ret;
}
- ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+ ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
if (ret<0) {
printk("%s: could not set section feed\n", dev->name);
@@ -960,9 +955,7 @@ static int dvb_net_feed_start(struct net_device *dev)
priv->tsfeed->priv = (void *)dev;
ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
TS_PACKET, DMX_TS_PES_OTHER,
- 188 * 100, /* nr. of bytes delivered per callback */
32768, /* circular buffer size */
- 0, /* descramble */
timeout);
if (ret < 0) {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 4b7adca3e286..477b4fa56430 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -235,7 +235,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
S_IFCHR | S_IRUSR | S_IWUSR,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
- class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 612e5b087b1c..54e2b29076b1 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -93,13 +93,30 @@ config DVB_USB_DIGITV
Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
config DVB_USB_VP7045
- tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+ tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
depends on DVB_USB
help
Say Y here to support the
+
TwinhanDTV Alpha (stick) (VP-7045),
- TwinhanDTV MagicBox II (VP-7046) and
- DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+ TwinhanDTV MagicBox II (VP-7046),
+ DigitalNow TinyUSB 2 DVB-t,
+ DigitalRise USB 2.0 Ter (Beetle) and
+ TYPHOON DVB-T USB DRIVE
+
+ DVB-T USB2.0 receivers.
+
+config DVB_USB_VP702X
+ tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the
+
+ TwinhanDTV StarBox,
+ DigitalRise USB Starbox and
+ TYPHOON DVB-S USB 2.0 BOX
+
+ DVB-S USB2.0 receivers.
config DVB_USB_NOVA_T_USB2
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 746d87ed6f32..2dc9aad9681e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -4,6 +4,9 @@ obj-$(CONFIG_DVB_USB) += dvb-usb.o
dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
+obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
+
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index f2fcc2f1f846..e55322ef76b3 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -90,7 +90,7 @@ static struct dvb_usb_properties a800_properties;
static int a800_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index c3e1b661aae6..3fe383f4bb4c 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -48,35 +48,26 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
return 0;
}
-/* I2C */
-static void cxusb_set_i2c_path(struct dvb_usb_device *d, enum cxusb_i2c_pathes path)
+/* GPIO */
+static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
{
struct cxusb_state *st = d->priv;
u8 o[2],i;
- if (path == st->cur_i2c_path)
+ if (st->gpio_write_state[GPIO_TUNER] == onoff)
return;
- o[0] = IOCTL_SET_I2C_PATH;
- switch (path) {
- case PATH_CX22702:
- o[1] = 0;
- break;
- case PATH_TUNER_OTHER:
- o[1] = 1;
- break;
- default:
- err("unkown i2c path");
- return;
- }
- cxusb_ctrl_msg(d,CMD_IOCTL,o,2,&i,1);
+ o[0] = GPIO_TUNER;
+ o[1] = onoff;
+ cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
if (i != 0x01)
- deb_info("i2c_path setting failed.\n");
+ deb_info("gpio_write failed.\n");
- st->cur_i2c_path = path;
+ st->gpio_write_state[GPIO_TUNER] = onoff;
}
+/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -92,10 +83,10 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
switch (msg[i].addr) {
case 0x63:
- cxusb_set_i2c_path(d,PATH_CX22702);
+ cxusb_gpio_tuner(d,0);
break;
default:
- cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
+ cxusb_gpio_tuner(d,1);
break;
}
@@ -141,24 +132,26 @@ static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm cxusb_i2c_algo = {
- .name = "Conexant USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = cxusb_i2c_xfer,
.functionality = cxusb_i2c_func,
};
static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
{
- return 0;
+ u8 b = 0;
+ if (onoff)
+ return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
+ else
+ return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
}
static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
if (onoff)
- cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
+ cxusb_ctrl_msg(d,CMD_STREAMING_ON, buf, 2, NULL, 0);
else
- cxusb_ctrl_msg(d,0x37, NULL, 0, NULL, 0);
+ cxusb_ctrl_msg(d,CMD_STREAMING_OFF, NULL, 0, NULL, 0);
return 0;
}
@@ -184,22 +177,11 @@ static int cxusb_tuner_attach(struct dvb_usb_device *d)
static int cxusb_frontend_attach(struct dvb_usb_device *d)
{
- u8 buf[2] = { 0x03, 0x00 };
- u8 b = 0;
-
- if (usb_set_interface(d->udev,0,0) < 0)
- err("set interface to alts=0 failed");
-
- cxusb_ctrl_msg(d,0xde,&b,0,NULL,0);
- cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
- cxusb_ctrl_msg(d,CMD_POWER_OFF, NULL, 0, &b, 1);
-
+ u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
err("set interface failed");
- cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
- cxusb_set_i2c_path(d,PATH_CX22702);
- cxusb_ctrl_msg(d,CMD_POWER_ON, NULL, 0, &b, 1);
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
return 0;
@@ -213,7 +195,7 @@ static struct dvb_usb_properties cxusb_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL);
}
static struct usb_device_id cxusb_table [] = {
@@ -239,14 +221,12 @@ static struct dvb_usb_properties cxusb_properties = {
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
- .type = DVB_USB_ISOC,
+ .type = DVB_USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
- .isoc = {
- .framesperurb = 32,
- .framesize = 940,
- .interval = 5,
+ .bulk = {
+ .buffersize = 8192,
}
}
},
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 1d79016e3195..135c2a81f581 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -1,30 +1,31 @@
#ifndef _DVB_USB_CXUSB_H_
#define _DVB_USB_CXUSB_H_
-#define DVB_USB_LOG_PREFIX "digitv"
+#define DVB_USB_LOG_PREFIX "cxusb"
#include "dvb-usb.h"
extern int dvb_usb_cxusb_debug;
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
/* usb commands - some of it are guesses, don't have a reference yet */
-#define CMD_I2C_WRITE 0x08
-#define CMD_I2C_READ 0x09
+#define CMD_I2C_WRITE 0x08
+#define CMD_I2C_READ 0x09
-#define CMD_IOCTL 0x0e
-#define IOCTL_SET_I2C_PATH 0x02
+#define CMD_GPIO_READ 0x0d
+#define CMD_GPIO_WRITE 0x0e
+#define GPIO_TUNER 0x02
-#define CMD_POWER_OFF 0x50
-#define CMD_POWER_ON 0x51
+#define CMD_POWER_OFF 0xdc
+#define CMD_POWER_ON 0xde
-enum cxusb_i2c_pathes {
- PATH_UNDEF = 0x00,
- PATH_CX22702 = 0x01,
- PATH_TUNER_OTHER = 0x02,
-};
+#define CMD_STREAMING_ON 0x36
+#define CMD_STREAMING_OFF 0x37
+
+#define CMD_ANALOG 0x50
+#define CMD_DIGITAL 0x51
struct cxusb_state {
- enum cxusb_i2c_pathes cur_i2c_path;
+ u8 gpio_write_state[3];
};
#endif
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 63b626f70c81..00b946419b40 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -70,13 +70,22 @@ EXPORT_SYMBOL(dibusb_power_ctrl);
int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
- u8 b[2];
- b[0] = DIBUSB_REQ_SET_IOCTL;
- b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+ u8 b[3] = { 0 };
+ int ret;
+
+ if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0)
+ return ret;
- dvb_usb_generic_write(d,b,3);
+ if (onoff) {
+ b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
+ b[1] = 0x00;
+ if ((ret = dvb_usb_generic_write(d,b,2)) < 0)
+ return ret;
+ }
- return dibusb_streaming_ctrl(d,onoff);
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+ return dvb_usb_generic_write(d,b,3);
}
EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
@@ -147,8 +156,6 @@ static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
}
struct i2c_algorithm dibusb_i2c_algo = {
- .name = "DiBcom USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = dibusb_i2c_xfer,
.functionality = dibusb_i2c_func,
};
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 828b5182e16c..0058505634a0 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -86,9 +86,9 @@ static struct dvb_usb_properties dibusb2_0b_properties;
static int dibusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
- dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
- dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0)
return 0;
return -EINVAL;
@@ -126,10 +126,12 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
+/* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) },
+
// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
-/* 27 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+/* 28 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
{ } /* Terminating entry */
};
@@ -262,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
},
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
- { &dibusb_dib3000mb_table[27], NULL },
+ { &dibusb_dib3000mb_table[28], NULL },
{ NULL },
},
#endif
@@ -306,12 +308,16 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
}
},
- .num_device_descs = 1,
+ .num_device_descs = 2,
.devices = {
- { "KWorld/ADSTech Instant DVB-T USB 2.0",
+ { "KWorld/ADSTech Instant DVB-T USB2.0",
{ &dibusb_dib3000mb_table[23], NULL },
{ &dibusb_dib3000mb_table[24], NULL },
},
+ { "KWorld Xpert DVB-T USB2.0",
+ { &dibusb_dib3000mb_table[27], NULL },
+ { NULL }
+ },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index e9dac430f37d..6a0912eab396 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -20,7 +20,7 @@ static struct dvb_usb_properties dibusb_mc_properties;
static int dibusb_mc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 9a676afc1d6e..74545f82eff1 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -77,8 +77,6 @@ static u32 digitv_i2c_func(struct i2c_adapter *adapter)
}
static struct i2c_algorithm digitv_i2c_algo = {
- .name = "Nebula DigiTV USB I2C algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = digitv_i2c_xfer,
.functionality = digitv_i2c_func,
};
@@ -113,31 +111,28 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
}
static struct mt352_config digitv_mt352_config = {
- .demod_address = 0x0, /* ignored by the digitv anyway */
.demod_init = digitv_mt352_demod_init,
.pll_set = dvb_usb_pll_set,
};
-static struct nxt6000_config digitv_nxt6000_config = {
- .demod_address = 0x0, /* ignored by the digitv anyway */
- .clock_inversion = 0x0,
+static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+ u8 b[5];
+ dvb_usb_pll_set(fe,fep,b);
+ return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
+}
- .pll_init = NULL,
- .pll_set = NULL,
+static struct nxt6000_config digitv_nxt6000_config = {
+ .clock_inversion = 1,
+ .pll_set = digitv_nxt6000_pll_set,
};
static int digitv_frontend_attach(struct dvb_usb_device *d)
{
- if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL)
+ if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
+ (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
return 0;
- if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
-
- warn("nxt6000 support is not done yet, in fact you are one of the first "
- "person who wants to use this device in Linux. Please report to "
- "linux-dvb@linuxtv.org");
-
- return 0;
- }
return -EIO;
}
@@ -175,7 +170,18 @@ static struct dvb_usb_properties digitv_properties;
static int digitv_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+ struct dvb_usb_device *d;
+ int ret;
+ if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+ u8 b[4] = { 0 };
+
+ b[0] = 1;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+
+ b[0] = 0;
+ digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ }
+ return ret;
}
static struct usb_device_id digitv_table [] = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index b032523b07bc..0a94ec22aeb8 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -18,6 +18,7 @@ struct dtt200u_fe_state {
struct dvb_frontend_parameters fep;
struct dvb_frontend frontend;
+ struct dvb_frontend_ops ops;
};
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,8 +164,9 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
deb_info("attaching frontend dtt200u\n");
state->d = d;
+ memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
- state->frontend.ops = &dtt200u_fe_ops;
+ state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
goto success;
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 47dba6e45968..b595476332cd 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -98,20 +98,19 @@ static struct dvb_usb_properties wt220u_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE) == 0 ||
- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
return 0;
return -ENODEV;
}
static struct usb_device_id dtt200u_usb_table [] = {
-// { USB_DEVICE(0x04b4,0x8613) },
- { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
- { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
- { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) },
- { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) },
- { 0 },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) },
+ { 0 },
};
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -152,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { 0 },
+ { NULL },
}
};
@@ -189,11 +188,11 @@ static struct dvb_usb_properties wt220u_properties = {
.num_device_descs = 1,
.devices = {
- { .name = "WideView WT-220U PenType Receiver (and clones)",
+ { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
@@ -201,9 +200,9 @@ static struct dvb_usb_properties wt220u_properties = {
static struct usb_driver dtt200u_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dtt200u",
- .probe = dtt200u_usb_probe,
+ .probe = dtt200u_usb_probe,
.disconnect = dvb_usb_device_exit,
- .id_table = dtt200u_usb_table,
+ .id_table = dtt200u_usb_table,
};
/* module stuff */
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 3491ff40885c..6fa92100248b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -23,12 +23,12 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
*/
if (newfeedcount == 0) {
deb_ts("stop feeding\n");
+ dvb_usb_urb_kill(d);
if (d->props.streaming_ctrl != NULL)
if ((ret = d->props.streaming_ctrl(d,0)))
err("error while stopping stream.");
- dvb_usb_urb_kill(d);
}
d->feedcount = newfeedcount;
@@ -44,6 +44,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
* for reception.
*/
if (d->feedcount == onoff && d->feedcount > 0) {
+ deb_ts("submitting all URBs\n");
+ dvb_usb_urb_submit(d);
deb_ts("controlling pid parser\n");
if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
@@ -59,7 +61,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
return -ENODEV;
}
- dvb_usb_urb_submit(d);
}
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 9f0a8d90d146..da970947dfc7 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -27,7 +27,6 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
#endif
d->i2c_adap.algo = d->props.i2c_algo;
d->i2c_adap.algo_data = NULL;
- d->i2c_adap.id = I2C_ALGO_BIT;
i2c_set_adapdata(&d->i2c_adap, d);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 794d513a8480..0818996bf150 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -24,8 +24,10 @@
#define USB_VID_HANFTEK 0x15f4
#define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025
+#define USB_VID_KWORLD 0xeb2a
#define USB_VID_KYE 0x0458
#define USB_VID_MEDION 0x1660
+#define USB_VID_PINNACLE 0x2304
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
@@ -52,12 +54,14 @@
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
+#define USB_PID_TWINHAN_VP7020_COLD 0x3203
+#define USB_PID_TWINHAN_VP7020_WARM 0x3204
#define USB_PID_TWINHAN_VP7045_COLD 0x3205
#define USB_PID_TWINHAN_VP7045_WARM 0x3206
-#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
-#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
+#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
@@ -85,5 +89,7 @@
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
+#define USB_PID_PCTV_200E 0x020e
+#define USB_PID_PCTV_400E 0x020f
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index 65f0c095abc9..a902059812a2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -128,7 +128,9 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
/*
* USB
*/
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
+
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
+ *props, struct module *owner,struct dvb_usb_device **du)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_device *d = NULL;
@@ -170,6 +172,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *p
usb_set_intfdata(intf, d);
+ if (du != NULL)
+ *du = d;
+
ret = dvb_usb_init(d);
}
@@ -196,19 +201,6 @@ void dvb_usb_device_exit(struct usb_interface *intf)
}
EXPORT_SYMBOL(dvb_usb_device_exit);
-/* module stuff */
-static int __init dvb_usb_module_init(void)
-{
- return 0;
-}
-
-static void __exit dvb_usb_module_exit(void)
-{
-}
-
-module_init (dvb_usb_module_init);
-module_exit (dvb_usb_module_exit);
-
MODULE_VERSION("0.3");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index fc7800f1743e..e5c6d9835e06 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -39,9 +39,9 @@ static void dvb_usb_read_remote_control(void *data)
d->last_event = event;
case REMOTE_KEY_REPEAT:
deb_rc("key repeated\n");
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 1);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(d->rc_input_dev);
break;
default:
break;
@@ -53,8 +53,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("NO KEY PRESSED\n");
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
deb_rc("releasing event %d\n",d->last_event);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(d->rc_input_dev);
}
d->last_state = REMOTE_NO_KEY_PRESSED;
d->last_event = 0;
@@ -63,8 +63,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("KEY PRESSED\n");
deb_rc("pressing event %d\n",event);
- input_event(&d->rc_input_dev, EV_KEY, event, 1);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_sync(d->rc_input_dev);
d->last_event = event;
d->last_state = REMOTE_KEY_PRESSED;
@@ -73,8 +73,8 @@ static void dvb_usb_read_remote_control(void *data)
deb_rc("KEY_REPEAT\n");
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
deb_rc("repeating event %d\n",d->last_event);
- input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
- input_sync(&d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
+ input_sync(d->rc_input_dev);
d->last_state = REMOTE_KEY_REPEAT;
}
default:
@@ -89,24 +89,30 @@ schedule:
int dvb_usb_remote_init(struct dvb_usb_device *d)
{
int i;
+
if (d->props.rc_key_map == NULL ||
d->props.rc_query == NULL ||
dvb_usb_disable_rc_polling)
return 0;
- /* Initialise the remote-control structures.*/
- init_input_dev(&d->rc_input_dev);
+ usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+ strlcpy(d->rc_phys, "/ir0", sizeof(d->rc_phys));
+
+ d->rc_input_dev = input_allocate_device();
+ if (!d->rc_input_dev)
+ return -ENOMEM;
- d->rc_input_dev.evbit[0] = BIT(EV_KEY);
- d->rc_input_dev.keycodesize = sizeof(unsigned char);
- d->rc_input_dev.keycodemax = KEY_MAX;
- d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
+ d->rc_input_dev->evbit[0] = BIT(EV_KEY);
+ d->rc_input_dev->keycodesize = sizeof(unsigned char);
+ d->rc_input_dev->keycodemax = KEY_MAX;
+ d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
+ d->rc_input_dev->phys = d->rc_phys;
/* set the bits for the keys */
- deb_rc("key map size: %d\n",d->props.rc_key_map_size);
+ deb_rc("key map size: %d\n", d->props.rc_key_map_size);
for (i = 0; i < d->props.rc_key_map_size; i++) {
deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
- set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
+ set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
}
/* Start the remote-control polling. */
@@ -114,14 +120,14 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
d->props.rc_interval = 100; /* default */
/* setting these two values to non-zero, we have to manage key repeats */
- d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
- d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150;
+ d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+ d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
- input_register_device(&d->rc_input_dev);
+ input_register_device(d->rc_input_dev);
INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
- info("schedule remote query interval to %d msecs.",d->props.rc_interval);
+ info("schedule remote query interval to %d msecs.", d->props.rc_interval);
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
d->state |= DVB_USB_STATE_REMOTE;
@@ -134,7 +140,7 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
if (d->state & DVB_USB_STATE_REMOTE) {
cancel_delayed_work(&d->rc_query_work);
flush_scheduled_work();
- input_unregister_device(&d->rc_input_dev);
+ input_unregister_device(d->rc_input_dev);
}
d->state &= ~DVB_USB_STATE_REMOTE;
return 0;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index a80567caf508..b4a1a98006c7 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -127,7 +127,7 @@ struct dvb_usb_device;
* helper functions.
*
* @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
- * Currently only BULK is implemented
+ * (BULK or ISOC)
*
* @num_device_descs: number of struct dvb_usb_device_description in @devices
* @devices: array of struct dvb_usb_device_description compatibles with these
@@ -300,7 +300,8 @@ struct dvb_usb_device {
int (*fe_init) (struct dvb_frontend *);
/* remote control */
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char rc_phys[64];
struct work_struct rc_query_work;
u32 last_event;
int last_state;
@@ -310,7 +311,7 @@ struct dvb_usb_device {
void *priv;
};
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *, struct dvb_usb_device **);
extern void dvb_usb_device_exit(struct usb_interface *);
/* the generic read/write method for device control */
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 258a92bfbcc7..1841a66427bf 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -144,7 +144,7 @@ static struct dvb_usb_properties nova_t_properties;
static int nova_t_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
}
/* do not change the order of the ID table */
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 2112ac3cf5e2..6fd67657c269 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -77,7 +77,7 @@ static struct dvb_usb_properties umt_properties;
static int umt_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
+ if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
return 0;
return -EINVAL;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
new file mode 100644
index 000000000000..f20d8dbd0be8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -0,0 +1,339 @@
+/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
+ * DVB-S receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ * Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * This file can be removed soon, after the DST-driver is rewritten to provice
+ * the frontend-controlling separately.
+ *
+ * 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
+ *
+ */
+#include "vp702x.h"
+
+struct vp702x_fe_state {
+ struct dvb_frontend fe;
+ struct dvb_usb_device *d;
+
+ fe_sec_voltage_t voltage;
+ fe_sec_tone_mode_t tone_mode;
+
+ u8 lnb_buf[8];
+
+ u8 lock;
+ u8 sig;
+ u8 snr;
+
+ unsigned long next_status_check;
+ unsigned long status_check_interval;
+};
+
+static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
+{
+ u8 buf[10];
+ if (time_after(jiffies,st->next_status_check)) {
+ vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
+
+ st->lock = buf[4];
+ vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
+ vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
+
+ st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+ }
+ return 0;
+}
+
+static u8 vp702x_chksum(u8 *buf,int f, int count)
+{
+ u8 s = 0;
+ int i;
+ for (i = f; i < f+count; i++)
+ s += buf[i];
+ return ~s+1;
+}
+
+static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ deb_fe("%s\n",__FUNCTION__);
+
+ if (st->lock == 0)
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+ else
+ *status = 0;
+
+ deb_fe("real state: %x\n",*status);
+ *status = 0x1f;
+
+ if (*status & FE_HAS_LOCK)
+ st->status_check_interval = 1000;
+ else
+ st->status_check_interval = 250;
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ *ber = 0;
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+ *unc = 0;
+ return 0;
+}
+
+static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+
+ *strength = (st->sig << 8) | st->sig;
+ return 0;
+}
+
+static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ u8 _snr;
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+
+ _snr = (st->snr & 0x1f) * 0xff / 0x1f;
+ *snr = (_snr << 8) | _snr;
+ return 0;
+}
+
+static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ tune->min_delay_ms = 2000;
+ return 0;
+}
+
+static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u32 freq = fep->frequency/1000;
+ /*CalFrequency*/
+/* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
+ u64 sr;
+ u8 cmd[8] = { 0 },ibuf[10];
+
+ cmd[0] = (freq >> 8) & 0x7f;
+ cmd[1] = freq & 0xff;
+ cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
+
+ sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
+ do_div(sr,88000);
+ cmd[3] = (sr >> 12) & 0xff;
+ cmd[4] = (sr >> 4) & 0xff;
+ cmd[5] = (sr << 4) & 0xf0;
+
+ deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
+ fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
+
+/* if (fep->inversion == INVERSION_ON)
+ cmd[6] |= 0x80; */
+
+ if (st->voltage == SEC_VOLTAGE_18)
+ cmd[6] |= 0x40;
+
+/* if (fep->u.qpsk.symbol_rate > 8000000)
+ cmd[6] |= 0x20;
+
+ if (fep->frequency < 1531000)
+ cmd[6] |= 0x04;
+
+ if (st->tone_mode == SEC_TONE_ON)
+ cmd[6] |= 0x01;*/
+
+ cmd[7] = vp702x_chksum(cmd,0,7);
+
+ st->status_check_interval = 250;
+ st->next_status_check = jiffies;
+
+ vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+ msleep(30);
+ vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("tuning failed.\n");
+ else
+ deb_fe("tuning succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ return 0;
+}
+
+static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *m)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 cmd[8],ibuf[10];
+ memset(cmd,0,8);
+
+ deb_fe("%s\n",__FUNCTION__);
+
+ if (m->msg_len > 4)
+ return -EINVAL;
+
+ cmd[1] = SET_DISEQC_CMD;
+ cmd[2] = m->msg_len;
+ memcpy(&cmd[3], m->msg, m->msg_len);
+ cmd[7] = vp702x_chksum(cmd,0,7);
+
+ vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("diseqc cmd failed.\n");
+ else
+ deb_fe("diseqc cmd succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+ deb_fe("%s\n",__FUNCTION__);
+ return 0;
+}
+
+static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+ deb_fe("%s\n",__FUNCTION__);
+
+ st->tone_mode = tone;
+
+ if (tone == SEC_TONE_ON)
+ st->lnb_buf[2] = 0x02;
+ else
+ st->lnb_buf[2] = 0x00;
+
+ st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+ vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("set_tone cmd failed.\n");
+ else
+ deb_fe("set_tone cmd succeeded.\n");
+
+ return 0;
+}
+
+static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+ voltage)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+ deb_fe("%s\n",__FUNCTION__);
+
+ st->voltage = voltage;
+
+ if (voltage != SEC_VOLTAGE_OFF)
+ st->lnb_buf[4] = 0x01;
+ else
+ st->lnb_buf[4] = 0x00;
+
+ st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+ vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+ if (ibuf[2] == 0 && ibuf[3] == 0)
+ deb_fe("set_voltage cmd failed.\n");
+ else
+ deb_fe("set_voltage cmd succeeded.\n");
+
+ return 0;
+}
+
+static void vp702x_fe_release(struct dvb_frontend* fe)
+{
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ kfree(st);
+}
+
+static struct dvb_frontend_ops vp702x_fe_ops;
+
+struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
+{
+ struct vp702x_fe_state *s = kmalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+ memset(s,0,sizeof(struct vp702x_fe_state));
+
+ s->d = d;
+ s->fe.ops = &vp702x_fe_ops;
+ s->fe.demodulator_priv = s;
+
+ s->lnb_buf[1] = SET_LNB_POWER;
+ s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
+
+ goto success;
+error:
+ return NULL;
+success:
+ return &s->fe;
+}
+
+
+static struct dvb_frontend_ops vp702x_fe_ops = {
+ .info = {
+ .name = "Twinhan DST-like frontend (VP7021/VP7020) 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 = vp702x_fe_release,
+
+ .init = NULL,
+ .sleep = NULL,
+
+ .set_frontend = vp702x_fe_set_frontend,
+ .get_frontend = vp702x_fe_get_frontend,
+ .get_tune_settings = vp702x_fe_get_tune_settings,
+
+ .read_status = vp702x_fe_read_status,
+ .read_ber = vp702x_fe_read_ber,
+ .read_signal_strength = vp702x_fe_read_signal_strength,
+ .read_snr = vp702x_fe_read_snr,
+ .read_ucblocks = vp702x_fe_read_unc_blocks,
+
+ .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
+ .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
+ .set_tone = vp702x_fe_set_tone,
+ .set_voltage = vp702x_fe_set_voltage,
+};
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
new file mode 100644
index 000000000000..de13c04e8e64
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -0,0 +1,290 @@
+/* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S
+ * receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ * Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "vp702x.h"
+
+/* debug */
+int dvb_usb_vp702x_debug;
+module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+struct vp702x_state {
+ u8 pid_table[17]; /* [16] controls the pid_table state */
+};
+
+/* check for mutex FIXME */
+int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ int ret = 0,try = 0;
+
+ while (ret >= 0 && ret != blen && try < 3) {
+ ret = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value,index,b,blen,
+ 2000);
+ deb_info("reading number %d (ret: %d)\n",try,ret);
+ try++;
+ }
+
+ if (ret < 0 || ret != blen) {
+ warn("usb in operation failed.");
+ ret = -EIO;
+ } else
+ ret = 0;
+
+ deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ return ret;
+}
+
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ if (usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ value,index,b,blen,
+ 2000) != blen) {
+ warn("usb out operation failed.");
+ return -EIO;
+ } else
+ return 0;
+}
+
+int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+ int ret;
+
+ if ((ret = down_interruptible(&d->usb_sem)))
+ return ret;
+
+ if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0)
+ goto unlock;
+ msleep(msec);
+ ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
+
+unlock:
+ up(&d->usb_sem);
+
+ return ret;
+}
+
+int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+ u8 bout[olen+2];
+ u8 bin[ilen+1];
+ int ret = 0;
+
+ bout[0] = 0x00;
+ bout[1] = cmd;
+ memcpy(&bout[2],o,olen);
+
+ ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
+
+ if (ret == 0)
+ memcpy(i,&bin[1],ilen);
+
+ return ret;
+}
+
+static int vp702x_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+ struct vp702x_state *st = d->priv;
+ u8 buf[9];
+
+ if (onoff) {
+ st->pid_table[16] |= 1 << index;
+ st->pid_table[index*2] = (pid >> 8) & 0xff;
+ st->pid_table[index*2+1] = pid & 0xff;
+ } else {
+ st->pid_table[16] &= ~(1 << index);
+ st->pid_table[index*2] = st->pid_table[index*2+1] = 0;
+ }
+
+ return vp702x_usb_inout_cmd(d,SET_PID_FILTER,st->pid_table,17,buf,9,10);
+}
+
+static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0);
+
+ vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+ return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+}
+
+/* keys for the enclosed remote control */
+static struct dvb_usb_rc_key vp702x_rc_keys[] = {
+ { 0x00, 0x01, KEY_1 },
+ { 0x00, 0x02, KEY_2 },
+};
+
+/* remote control stuff (does not work with my box) */
+static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[10];
+ int i;
+
+/* remove the following return to enabled remote querying */
+ return 0;
+
+ vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
+
+ deb_rc("remote query key: %x %d\n",key[1],key[1]);
+
+ if (key[1] == 0x44) {
+ *state = REMOTE_NO_KEY_PRESSED;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++)
+ if (vp702x_rc_keys[i].custom == key[1]) {
+ *state = REMOTE_KEY_PRESSED;
+ *event = vp702x_rc_keys[i].event;
+ break;
+ }
+ return 0;
+}
+
+static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
+{
+ u8 macb[9];
+ if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10))
+ return -EIO;
+ memcpy(mac,&macb[3],6);
+ return 0;
+}
+
+static int vp702x_frontend_attach(struct dvb_usb_device *d)
+{
+ u8 buf[9] = { 0 };
+
+ if (vp702x_usb_inout_cmd(d, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10))
+ return -EIO;
+
+ buf[8] = '\0';
+ info("system string: %s",&buf[1]);
+
+ d->fe = vp702x_fe_attach(d);
+ return 0;
+}
+
+static struct dvb_usb_properties vp702x_properties;
+
+static int vp702x_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ usb_clear_halt(udev,usb_sndctrlpipe(udev,0));
+ usb_clear_halt(udev,usb_rcvctrlpipe(udev,0));
+
+ return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id vp702x_usb_table [] = {
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
+
+static struct dvb_usb_properties vp702x_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+ .pid_filter_count = 8, /* !!! */
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-vp702x-01.fw",
+
+ .pid_filter = vp702x_pid_filter,
+ .power_ctrl = vp702x_power_ctrl,
+ .frontend_attach = vp702x_frontend_attach,
+ .read_mac_address = vp702x_read_mac_addr,
+
+ .rc_key_map = vp702x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(vp702x_rc_keys),
+ .rc_interval = 400,
+ .rc_query = vp702x_rc_query,
+
+ .size_of_priv = sizeof(struct vp702x_state),
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
+ .cold_ids = { &vp702x_usb_table[0], NULL },
+ .warm_ids = { &vp702x_usb_table[1], NULL },
+ },
+ { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
+ .cold_ids = { &vp702x_usb_table[2], NULL },
+ .warm_ids = { &vp702x_usb_table[3], NULL },
+ },
+ { 0 },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vp702x_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "dvb-usb-vp702x",
+ .probe = vp702x_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = vp702x_usb_table,
+};
+
+/* module stuff */
+static int __init vp702x_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&vp702x_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit vp702x_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&vp702x_usb_driver);
+}
+
+module_init(vp702x_usb_module_init);
+module_exit(vp702x_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
new file mode 100644
index 000000000000..4a3e8c7eca2b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -0,0 +1,109 @@
+#ifndef _DVB_USB_VP7021_H_
+#define _DVB_USB_VP7021_H_
+
+#define DVB_USB_LOG_PREFIX "vp702x"
+#include "dvb-usb.h"
+
+extern int dvb_usb_vp702x_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_vp702x_debug,0x04,args)
+#define deb_fe(args...) dprintk(dvb_usb_vp702x_debug,0x08,args)
+
+/* commands are read and written with USB control messages */
+
+/* consecutive read/write operation */
+#define REQUEST_OUT 0xB2
+#define REQUEST_IN 0xB3
+
+/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
+ * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
+ * the returning buffer looks as follows
+ * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
+
+#define GET_TUNER_STATUS 0x05
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
+
+#define GET_SYSTEM_STRING 0x06
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
+
+#define SET_DISEQC_CMD 0x08
+/* additional out buffer:
+ * 0 1 2 3 4
+ * len X1 X2 X3 X4
+ * additional in buffer:
+ * 0 1 2
+ * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+
+#define SET_LNB_POWER 0x09
+/* additional out buffer:
+ * 0 1 2
+ * 0x00 0xff 1 = on, 0 = off
+ * additional in buffer:
+ * 0 1 2
+ * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
+
+#define GET_MAC_ADDRESS 0x0A
+/* #define GET_MAC_ADDRESS 0x0B */
+/* additional in buffer:
+ * 0 1 2 3 4 5 6 7 8
+ * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
+
+#define SET_PID_FILTER 0x11
+/* additional in buffer:
+ * 0 1 ... 14 15 16
+ * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
+
+/* request: 0xB2; i: 0; v: 0;
+ * b[0] != 0 -> tune and lock a channel
+ * 0 1 2 3 4 5 6 7
+ * freq0 freq1 divstep srate0 srate1 srate2 flag chksum
+ */
+
+
+/* one direction requests */
+#define READ_REMOTE_REQ 0xB4
+/* IN i: 0; v: 0; b[0] == request, b[1] == key */
+
+#define READ_PID_NUMBER_REQ 0xB5
+/* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
+
+#define WRITE_EEPROM_REQ 0xB6
+/* OUT i: offset; v: value to write; no extra buffer */
+
+#define READ_EEPROM_REQ 0xB7
+/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
+
+#define READ_STATUS 0xB8
+/* IN i: 0; v: 0; bufferlen 10 */
+
+#define READ_TUNER_REG_REQ 0xB9
+/* IN i: 0; v: register; b[0] = value */
+
+#define READ_FX2_REG_REQ 0xBA
+/* IN i: offset; v: 0; b[0] = value */
+
+#define WRITE_FX2_REG_REQ 0xBB
+/* OUT i: offset; v: value to write; 1 byte extra buffer */
+
+#define SET_TUNER_POWER_REQ 0xBC
+/* IN i: 0 = power off, 1 = power on */
+
+#define WRITE_TUNER_REG_REQ 0xBD
+/* IN i: register, v: value to write, no extra buffer */
+
+#define RESET_TUNER 0xBE
+/* IN i: 0, v: 0, no extra buffer */
+
+extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
+
+extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 9ac95f54f9fc..75765e3a569c 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -164,7 +164,6 @@ static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int off
return 0;
}
-
static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{
return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
@@ -199,7 +198,7 @@ static struct dvb_usb_properties vp7045_properties;
static int vp7045_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
+ return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
}
static struct usb_device_id vp7045_usb_table [] = {
@@ -248,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { 0 },
+ { NULL },
}
};
@@ -256,9 +255,9 @@ static struct dvb_usb_properties vp7045_properties = {
static struct usb_driver vp7045_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_vp7045",
- .probe = vp7045_usb_probe,
+ .probe = vp7045_usb_probe,
.disconnect = dvb_usb_device_exit,
- .id_table = vp7045_usb_table,
+ .id_table = vp7045_usb_table,
};
/* module stuff */
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index e83256d0fd14..a50a41f6f79d 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -188,7 +188,7 @@ config DVB_BCM3510
support this frontend.
config DVB_LGDT330X
- tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)"
+ tristate "LG Electronics LGDT3302/LGDT3303 based"
depends on DVB_CORE
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index f5fdc5c3e605..f6d4ee78bdd4 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -36,6 +36,9 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "bcm3510.h"
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 8222b88cb486..d4b97989e3ed 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -1,7 +1,7 @@
/*
cx24110 - Single Chip Satellite Channel Receiver driver module
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
work
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
@@ -387,8 +387,9 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- int rv, bit, i;
+ int rv, bit;
struct cx24110_state *state = fe->demodulator_priv;
+ unsigned long timeout;
if (burst == SEC_MINI_A)
bit = 0x00;
@@ -398,12 +399,14 @@ static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
return -EINVAL;
rv = cx24110_readreg(state, 0x77);
- cx24110_writereg(state, 0x77, rv|0x04);
+ if (!(rv & 0x04))
+ cx24110_writereg(state, 0x77, rv | 0x04);
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
- for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
- ; /* wait for LNB ready */
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
+ ; /* wait for LNB ready */
return 0;
}
@@ -413,17 +416,22 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
{
int i, rv;
struct cx24110_state *state = fe->demodulator_priv;
+ unsigned long timeout;
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
rv = cx24110_readreg(state, 0x77);
- cx24110_writereg(state, 0x77, rv|0x04);
+ if (rv & 0x04) {
+ cx24110_writereg(state, 0x77, rv & ~0x04);
+ msleep(30); /* reportedly fixes switching problems */
+ }
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
- for (i=500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40);)
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
; /* wait for LNB ready */
return 0;
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
index 6b663f4744e0..b63ecf26421a 100644
--- a/drivers/media/dvb/frontends/cx24110.h
+++ b/drivers/media/dvb/frontends/cx24110.h
@@ -1,7 +1,7 @@
/*
cx24110 - Single Chip Satellite Channel Receiver driver module
- Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+ Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
work
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index cd434b7cf9db..6b0553608610 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -23,11 +23,12 @@
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/version.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 "dib3000-common.h"
#include "dib3000mb_priv.h"
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index cd33705a4320..c024fad17337 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -22,11 +22,12 @@
*/
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/version.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 "dib3000-common.h"
#include "dib3000mc_priv.h"
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 5264310c070e..536c35d969b7 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -225,6 +225,22 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
};
EXPORT_SYMBOL(dvb_pll_tua6034);
+/* Infineon TUA6034
+ * used in LG Innotek TDVS-H062F
+ */
+struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
+ .name = "LG/Infineon TUA6034",
+ .min = 54000000,
+ .max = 863000000,
+ .count = 3,
+ .entries = {
+ { 160000000, 44000000, 62500, 0xce, 0x01 },
+ { 455000000, 44000000, 62500, 0xce, 0x02 },
+ { 999999999, 44000000, 62500, 0xce, 0x04 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+
/* Philips FMD1216ME
* used in Medion Hybrid PCMCIA card and USB Box
*/
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index cb794759d89e..205b2d1a8852 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -31,6 +31,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
extern struct dvb_pll_desc dvb_pll_env57h1xd5;
extern struct dvb_pll_desc dvb_pll_tua6034;
+extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
extern struct dvb_pll_desc dvb_pll_tda665x;
extern struct dvb_pll_desc dvb_pll_fmd1216me;
extern struct dvb_pll_desc dvb_pll_tded4;
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index cff93b9d8ab2..794be520d590 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -22,6 +22,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "dvb_dummy_fe.h"
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index e94dee50eecd..8dde72bd1046 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -1,11 +1,8 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
- * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com>
- * Copyright (C) 2005
- *
* 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
@@ -25,11 +22,13 @@
/*
* NOTES ABOUT THIS DRIVER
*
- * This driver supports DViCO FusionHDTV Gold under Linux.
+ * This Linux driver supports:
+ * DViCO FusionHDTV 3 Gold-Q
+ * DViCO FusionHDTV 3 Gold-T
+ * DViCO FusionHDTV 5 Gold
*
* TODO:
- * BER and signal strength always return 0.
- * Include support for LGDT3303
+ * signal strength always returns 0.
*
*/
@@ -38,10 +37,11 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "lgdt330x_priv.h"
#include "lgdt330x.h"
@@ -70,55 +70,37 @@ struct lgdt330x_state
u32 current_frequency;
};
-static int i2c_writebytes (struct lgdt330x_state* state,
- u8 addr, /* demod_address or pll_address */
- u8 *buf, /* data bytes to send */
- int len /* number of bytes to send */ )
+static int i2c_write_demod_bytes (struct lgdt330x_state* state,
+ u8 *buf, /* data bytes to send */
+ int len /* number of bytes to send */ )
{
- u8 tmp[] = { buf[0], buf[1] };
struct i2c_msg msg =
- { .addr = addr, .flags = 0, .buf = tmp, .len = 2 };
- int err;
+ { .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2 };
int i;
+ int err;
- for (i=1; i<len; i++) {
- tmp[1] = buf[i];
+ for (i=0; i<len-1; i+=2){
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
+ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
- tmp[0]++;
+ msg.buf += 2;
}
return 0;
}
-#if 0
-static int i2c_readbytes (struct lgdt330x_state* state,
- u8 addr, /* demod_address or pll_address */
- u8 *buf, /* holds data bytes read */
- int len /* number of bytes to read */ )
-{
- struct i2c_msg msg =
- { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
- int err;
-
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
- return -EREMOTEIO;
- }
- return 0;
-}
-#endif
-
/*
* This routine writes the register (reg) to the demod bus
* then reads the data returned for (len) bytes.
*/
-static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
+static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
enum I2C_REG reg, u8* buf, int len)
{
u8 wr [] = { reg };
@@ -139,7 +121,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
}
/* Software reset */
-int lgdt330x_SwReset(struct lgdt330x_state* state)
+static int lgdt3302_SwReset(struct lgdt330x_state* state)
{
u8 ret;
u8 reset[] = {
@@ -148,23 +130,50 @@ int lgdt330x_SwReset(struct lgdt330x_state* state)
* bits 5-0 are 1 to mask interrupts */
};
- ret = i2c_writebytes(state,
- state->config->demod_address,
- reset, sizeof(reset));
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
if (ret == 0) {
- /* spec says reset takes 100 ns why wait */
- /* mdelay(100); */ /* keep low for 100mS */
- reset[1] = 0x7f; /* force reset high (inactive)
- * and unmask interrupts */
- ret = i2c_writebytes(state,
- state->config->demod_address,
- reset, sizeof(reset));
+
+ /* force reset high (inactive) and unmask interrupts */
+ reset[1] = 0x7f;
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
+ }
+ return ret;
+}
+
+static int lgdt3303_SwReset(struct lgdt330x_state* state)
+{
+ u8 ret;
+ u8 reset[] = {
+ 0x02,
+ 0x00 /* bit 0 is active low software reset */
+ };
+
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
+ if (ret == 0) {
+
+ /* force reset high (inactive) */
+ reset[1] = 0x01;
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
}
- /* Spec does not indicate a need for this either */
- /*mdelay(5); */ /* wait 5 msec before doing more */
return ret;
}
+static int lgdt330x_SwReset(struct lgdt330x_state* state)
+{
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ return lgdt3302_SwReset(state);
+ case LGDT3303:
+ return lgdt3303_SwReset(state);
+ default:
+ return -ENODEV;
+ }
+}
+
static int lgdt330x_init(struct dvb_frontend* fe)
{
/* Hardware reset is done using gpio[0] of cx23880x chip.
@@ -173,22 +182,98 @@ static int lgdt330x_init(struct dvb_frontend* fe)
* Maybe there needs to be a callable function in cx88-core or
* the caller of this function needs to do it. */
- dprintk("%s entered\n", __FUNCTION__);
- return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv);
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize each different chip
+ */
+ static u8 lgdt3302_init_data[] = {
+ /* Use 50MHz parameter values from spec sheet since xtal is 50 */
+ /* Change the value of NCOCTFV[25:0] of carrier
+ recovery center frequency register */
+ VSB_CARRIER_FREQ0, 0x00,
+ VSB_CARRIER_FREQ1, 0x87,
+ VSB_CARRIER_FREQ2, 0x8e,
+ VSB_CARRIER_FREQ3, 0x01,
+ /* Change the TPCLK pin polarity
+ data is valid on falling clock */
+ DEMUX_CONTROL, 0xfb,
+ /* Change the value of IFBW[11:0] of
+ AGC IF/RF loop filter bandwidth register */
+ AGC_RF_BANDWIDTH0, 0x40,
+ AGC_RF_BANDWIDTH1, 0x93,
+ AGC_RF_BANDWIDTH2, 0x00,
+ /* Change the value of bit 6, 'nINAGCBY' and
+ 'NSSEL[1:0] of ACG function control register 2 */
+ AGC_FUNC_CTRL2, 0xc6,
+ /* Change the value of bit 6 'RFFIX'
+ of AGC function control register 3 */
+ AGC_FUNC_CTRL3, 0x40,
+ /* Set the value of 'INLVTHD' register 0x2a/0x2c
+ to 0x7fe */
+ AGC_DELAY0, 0x07,
+ AGC_DELAY2, 0xfe,
+ /* Change the value of IAGCBW[15:8]
+ of inner AGC loop filter bandwith */
+ AGC_LOOP_BANDWIDTH0, 0x08,
+ AGC_LOOP_BANDWIDTH1, 0x9a
+ };
+
+ static u8 lgdt3303_init_data[] = {
+ 0x4c, 0x14
+ };
+
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ char *chip_name;
+ int err;
+
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ chip_name = "LGDT3302";
+ err = i2c_write_demod_bytes(state, lgdt3302_init_data,
+ sizeof(lgdt3302_init_data));
+ break;
+ case LGDT3303:
+ chip_name = "LGDT3303";
+ err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+ sizeof(lgdt3303_init_data));
+ break;
+ default:
+ chip_name = "undefined";
+ printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
+ dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+ if (err < 0)
+ return err;
+ return lgdt330x_SwReset(state);
}
static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
{
- *ber = 0; /* Dummy out for now */
+ *ber = 0; /* Not supplied by the demod chips */
return 0;
}
static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ int err;
u8 buf[2];
- i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+ buf, sizeof(buf));
+ break;
+ case LGDT3303:
+ err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
+ buf, sizeof(buf));
+ break;
+ default:
+ printk(KERN_WARNING
+ "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
*ucblocks = (buf[0] << 8) | buf[1];
return 0;
@@ -197,125 +282,116 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int lgdt330x_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
- struct lgdt330x_state* state =
- (struct lgdt330x_state*) fe->demodulator_priv;
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize 8VSB for lgdt3303 chip 50 MHz IF
+ */
+ static u8 lgdt3303_8vsb_44_data[] = {
+ 0x04, 0x00,
+ 0x0d, 0x40,
+ 0x0e, 0x87,
+ 0x0f, 0x8e,
+ 0x10, 0x01,
+ 0x47, 0x8b };
+
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize QAM for lgdt3303 chip
+ */
+ static u8 lgdt3303_qam_data[] = {
+ 0x04, 0x00,
+ 0x0d, 0x00,
+ 0x0e, 0x00,
+ 0x0f, 0x00,
+ 0x10, 0x00,
+ 0x51, 0x63,
+ 0x47, 0x66,
+ 0x48, 0x66,
+ 0x4d, 0x1a,
+ 0x49, 0x08,
+ 0x4a, 0x9b };
+
+ struct lgdt330x_state* state = fe->demodulator_priv;
- /* Use 50MHz parameter values from spec sheet since xtal is 50 */
static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
- static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
- static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
- static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
- static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
- static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe };
- static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
+ int err;
/* Change only if we are actually changing the modulation */
if (state->current_modulation != param->u.vsb.modulation) {
switch(param->u.vsb.modulation) {
case VSB_8:
dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
- /* Select VSB mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x07;
+ /* Select VSB mode */
+ top_ctrl_cfg[1] = 0x03;
/* Select ANT connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 1);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
+ sizeof(lgdt3303_8vsb_44_data));
+ }
break;
case QAM_64:
dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
- /* Select QAM_64 mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x04;
+ /* Select QAM_64 mode */
+ top_ctrl_cfg[1] = 0x00;
/* Select CABLE connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 0);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+ sizeof(lgdt3303_qam_data));
+ }
break;
case QAM_256:
dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
- /* Select QAM_256 mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x05;
+ /* Select QAM_256 mode */
+ top_ctrl_cfg[1] = 0x01;
/* Select CABLE connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 0);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+ sizeof(lgdt3303_qam_data));
+ }
break;
default:
printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
return -1;
}
- /* Initializations common to all modes */
+ /*
+ * select serial or parallel MPEG harware interface
+ * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
+ * Parallel: 0x00
+ */
+ top_ctrl_cfg[1] |= state->config->serial_mpeg;
/* Select the requested mode */
- i2c_writebytes(state, state->config->demod_address,
- top_ctrl_cfg, sizeof(top_ctrl_cfg));
-
- /* Change the value of IFBW[11:0]
- of AGC IF/RF loop filter bandwidth register */
- i2c_writebytes(state, state->config->demod_address,
- agc_rf_cfg, sizeof(agc_rf_cfg));
-
- /* Change the value of bit 6, 'nINAGCBY' and
- 'NSSEL[1:0] of ACG function control register 2 */
- /* Change the value of bit 6 'RFFIX'
- of AGC function control register 3 */
- i2c_writebytes(state, state->config->demod_address,
- agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
-
- /* Change the TPCLK pin polarity
- data is valid on falling clock */
- i2c_writebytes(state, state->config->demod_address,
- demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
-
- /* Change the value of NCOCTFV[25:0] of carrier
- recovery center frequency register */
- i2c_writebytes(state, state->config->demod_address,
- vsb_freq_cfg, sizeof(vsb_freq_cfg));
-
- /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */
- i2c_writebytes(state, state->config->demod_address,
- agc_delay_cfg, sizeof(agc_delay_cfg));
-
- /* Change the value of IAGCBW[15:8]
- of inner AGC loop filter bandwith */
- i2c_writebytes(state, state->config->demod_address,
- agc_loop_cfg, sizeof(agc_loop_cfg));
-
- state->config->set_ts_params(fe, 0);
+ i2c_write_demod_bytes(state, top_ctrl_cfg,
+ sizeof(top_ctrl_cfg));
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
state->current_modulation = param->u.vsb.modulation;
}
- /* Change only if we are actually changing the channel */
- if (state->current_frequency != param->frequency) {
- u8 buf[5];
- struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 };
- int err;
+ /* Tune to the specified frequency */
+ if (state->config->pll_set)
+ state->config->pll_set(fe, param);
- state->config->pll_set(fe, param, buf);
- msg.addr = buf[0];
+ /* Keep track of the new frequency */
+ state->current_frequency = param->frequency;
- dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n", __FUNCTION__,
- buf[0],buf[1],buf[2],buf[3],buf[4]);
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-#if 0
- /* Check the status of the tuner pll */
- i2c_readbytes(state, buf[0], &buf[1], 1);
- dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]);
-#endif
- /* Update current frequency */
- state->current_frequency = param->frequency;
- }
lgdt330x_SwReset(state);
return 0;
}
@@ -328,21 +404,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe,
return 0;
}
-static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ struct lgdt330x_state* state = fe->demodulator_priv;
u8 buf[3];
*status = 0; /* Reset status result */
- /*
- * You must set the Mask bits to 1 in the IRQ_MASK in order
- * to see that status bit in the IRQ_STATUS register.
- * This is done in SwReset();
- */
-
/* AGC status register */
- i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
+ i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
if ((buf[0] & 0x0c) == 0x8){
/* Test signal does not exist flag */
@@ -353,16 +423,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
+ /*
+ * You must set the Mask bits to 1 in the IRQ_MASK in order
+ * to see that status bit in the IRQ_STATUS register.
+ * This is done in SwReset();
+ */
/* signal status */
- i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
+ i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
-#if 0
- /* Alternative method to check for a signal */
- /* using the SNR good/bad interrupts. */
- if ((buf[2] & 0x30) == 0x10)
- *status |= FE_HAS_SIGNAL;
-#endif
/* sync status */
if ((buf[2] & 0x03) == 0x01) {
@@ -376,7 +445,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
/* Carrier Recovery Lock Status Register */
- i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
switch (state->current_modulation) {
case QAM_256:
@@ -396,13 +465,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
+static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ int err;
+ u8 buf[3];
+
+ *status = 0; /* Reset status result */
+
+ /* lgdt3303 AGC status register */
+ err = i2c_read_demod_bytes(state, 0x58, buf, 1);
+ if (err < 0)
+ return err;
+
+ dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+ if ((buf[0] & 0x21) == 0x01){
+ /* Test input signal does not exist flag */
+ /* as well as the AGC lock flag. */
+ *status |= FE_HAS_SIGNAL;
+ } else {
+ /* Without a signal all other status bits are meaningless */
+ return 0;
+ }
+
+ /* Carrier Recovery Lock Status Register */
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+ /* Need to undestand why there are 3 lock levels here */
+ if ((buf[0] & 0x07) == 0x07)
+ *status |= FE_HAS_CARRIER;
+ else
+ break;
+ i2c_read_demod_bytes(state, 0x8a, buf, 1);
+ if ((buf[0] & 0x04) == 0x04)
+ *status |= FE_HAS_SYNC;
+ if ((buf[0] & 0x01) == 0x01)
+ *status |= FE_HAS_LOCK;
+ if ((buf[0] & 0x08) == 0x08)
+ *status |= FE_HAS_VITERBI;
+ break;
+ case VSB_8:
+ if ((buf[0] & 0x80) == 0x80)
+ *status |= FE_HAS_CARRIER;
+ else
+ break;
+ i2c_read_demod_bytes(state, 0x38, buf, 1);
+ if ((buf[0] & 0x02) == 0x00)
+ *status |= FE_HAS_SYNC;
+ if ((buf[0] & 0x01) == 0x01) {
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_VITERBI;
+ }
+ break;
+ default:
+ printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+ }
+ return 0;
+}
+
static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
/* not directly available. */
+ *strength = 0;
return 0;
}
-static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
+static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
{
#ifdef SNR_IN_DB
/*
@@ -451,7 +582,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
- 90833, 114351, 143960, 181235, 228161, 0x040000
+ 90833, 114351, 143960, 181235, 228161, 0x080000
};
static u8 buf[5];/* read data buffer */
@@ -459,8 +590,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
static u32 snr_db; /* index into SNR_EQ[] */
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
- /* read both equalizer and pase tracker noise data */
- i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+ /* read both equalizer and phase tracker noise data */
+ i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
if (state->current_modulation == VSB_8) {
/* Equalizer Mean-Square Error Register for VSB */
@@ -496,19 +627,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
/* read both equalizer and pase tracker noise data */
- i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+ i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
if (state->current_modulation == VSB_8) {
- /* Equalizer Mean-Square Error Register for VSB */
- noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
- } else {
- /* Phase Tracker Mean-Square Error Register for QAM */
+ /* Phase Tracker Mean-Square Error Register for VSB */
noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+ } else {
+
+ /* Carrier Recovery Mean-Square Error for QAM */
+ i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ noise = ((buf[0] & 3) << 8) | buf[1];
}
/* Small values for noise mean signal is better so invert noise */
- /* Noise is 19 bit value so discard 3 LSB*/
- *snr = ~noise>>3;
+ *snr = ~noise;
#endif
dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
@@ -516,6 +648,32 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
+static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ /* Return the raw noise value */
+ static u8 buf[5];/* read data buffer */
+ static u32 noise; /* noise value */
+ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+
+ if (state->current_modulation == VSB_8) {
+
+ /* Phase Tracker Mean-Square Error Register for VSB */
+ noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
+ } else {
+
+ /* Carrier Recovery Mean-Square Error for QAM */
+ i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ noise = (buf[0] << 8) | buf[1];
+ }
+
+ /* Small values for noise mean signal is better so invert noise */
+ *snr = ~noise;
+
+ dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+
+ return 0;
+}
+
static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
{
/* I have no idea about this - it may not be needed */
@@ -531,7 +689,8 @@ static void lgdt330x_release(struct dvb_frontend* fe)
kfree(state);
}
-static struct dvb_frontend_ops lgdt330x_ops;
+static struct dvb_frontend_ops lgdt3302_ops;
+static struct dvb_frontend_ops lgdt3303_ops;
struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c)
@@ -548,9 +707,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops));
+ switch (config->demod_chip) {
+ case LGDT3302:
+ memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+ break;
+ case LGDT3303:
+ memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+ break;
+ default:
+ goto error;
+ }
+
/* Verify communication with demod chip */
- if (i2c_selectreadbytes(state, 2, buf, 1))
+ if (i2c_read_demod_bytes(state, 2, buf, 1))
goto error;
state->current_frequency = -1;
@@ -568,9 +737,33 @@ error:
return NULL;
}
-static struct dvb_frontend_ops lgdt330x_ops = {
+static struct dvb_frontend_ops lgdt3302_ops = {
+ .info = {
+ .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
+ .type = FE_ATSC,
+ .frequency_min= 54000000,
+ .frequency_max= 858000000,
+ .frequency_stepsize= 62500,
+ /* Symbol rate is for all VSB modes need to check QAM */
+ .symbol_rate_min = 10762000,
+ .symbol_rate_max = 10762000,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+ .init = lgdt330x_init,
+ .set_frontend = lgdt330x_set_parameters,
+ .get_frontend = lgdt330x_get_frontend,
+ .get_tune_settings = lgdt330x_get_tune_settings,
+ .read_status = lgdt3302_read_status,
+ .read_ber = lgdt330x_read_ber,
+ .read_signal_strength = lgdt330x_read_signal_strength,
+ .read_snr = lgdt3302_read_snr,
+ .read_ucblocks = lgdt330x_read_ucblocks,
+ .release = lgdt330x_release,
+};
+
+static struct dvb_frontend_ops lgdt3303_ops = {
.info = {
- .name= "LG Electronics lgdt330x VSB/QAM Frontend",
+ .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
.type = FE_ATSC,
.frequency_min= 54000000,
.frequency_max= 858000000,
@@ -584,15 +777,15 @@ static struct dvb_frontend_ops lgdt330x_ops = {
.set_frontend = lgdt330x_set_parameters,
.get_frontend = lgdt330x_get_frontend,
.get_tune_settings = lgdt330x_get_tune_settings,
- .read_status = lgdt330x_read_status,
+ .read_status = lgdt3303_read_status,
.read_ber = lgdt330x_read_ber,
.read_signal_strength = lgdt330x_read_signal_strength,
- .read_snr = lgdt330x_read_snr,
+ .read_snr = lgdt3303_read_snr,
.read_ucblocks = lgdt330x_read_ucblocks,
.release = lgdt330x_release,
};
-MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
MODULE_AUTHOR("Wilson Michaels");
MODULE_LICENSE("GPL");
@@ -601,6 +794,5 @@ EXPORT_SYMBOL(lgdt330x_attach);
/*
* Local variables:
* c-basic-offset: 8
- * compile-command: "make DVB=1"
* End:
*/
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
index 04986f8e7565..e209ba1e47c5 100644
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ b/drivers/media/dvb/frontends/lgdt330x.h
@@ -1,5 +1,5 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
@@ -24,14 +24,26 @@
#include <linux/dvb/frontend.h>
+typedef enum lg_chip_t {
+ UNDEFINED,
+ LGDT3302,
+ LGDT3303
+}lg_chip_type;
+
struct lgdt330x_config
{
/* The demodulator's i2c address */
u8 demod_address;
+ /* LG demodulator chip LGDT3302 or LGDT3303 */
+ lg_chip_type demod_chip;
+
+ /* MPEG hardware interface - 0:parallel 1:serial */
+ int serial_mpeg;
+
/* PLL interface */
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address);
+ int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h
index 4143ce8f1a95..59b7c5b9012d 100644
--- a/drivers/media/dvb/frontends/lgdt330x_priv.h
+++ b/drivers/media/dvb/frontends/lgdt330x_priv.h
@@ -1,5 +1,5 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
@@ -57,8 +57,10 @@ enum I2C_REG {
PH_ERR1= 0x4a,
PH_ERR2= 0x4b,
DEMUX_CONTROL= 0x66,
- PACKET_ERR_COUNTER1= 0x6a,
- PACKET_ERR_COUNTER2= 0x6b,
+ LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
+ LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+ LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
+ LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
};
#endif /* _LGDT330X_PRIV_ */
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index e455aecd76b2..e38454901dd1 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -29,6 +29,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "mt312_priv.h"
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index d32dc4de9e7f..f0c610f2c2df 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -35,6 +35,8 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "mt352_priv.h"
@@ -462,9 +464,11 @@ static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct mt352_state* state = fe->demodulator_priv;
- u16 signal = ((mt352_read_register(state, AGC_GAIN_1) << 8) & 0x0f) |
- (mt352_read_register(state, AGC_GAIN_0));
+ /* align the 12 bit AGC gain with the most significant bits */
+ u16 signal = ((mt352_read_register(state, AGC_GAIN_1) & 0x0f) << 12) |
+ (mt352_read_register(state, AGC_GAIN_0) << 4);
+ /* inverse of gain is signal strength */
*strength = ~signal;
return 0;
}
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 35a1d60f1927..30786b1911bd 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -32,6 +32,8 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "nxt2002.h"
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index 966de9853d18..88a57b791112 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -482,6 +482,7 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
return result;
+ msleep(500);
return 0;
}
@@ -525,6 +526,12 @@ static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
return 0;
}
+static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 500;
+ return 0;
+}
+
static struct dvb_frontend_ops nxt6000_ops;
struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -578,6 +585,8 @@ static struct dvb_frontend_ops nxt6000_ops = {
.init = nxt6000_init,
+ .get_tune_settings = nxt6000_fe_get_tune_settings,
+
.set_frontend = nxt6000_set_frontend,
.read_status = nxt6000_read_status,
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index cc0a77c790f1..817b044c7fd1 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -36,6 +36,8 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include "dvb_frontend.h"
@@ -370,22 +372,19 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
or51132_setmode(fe);
}
- /* Change only if we are actually changing the channel */
- if (state->current_frequency != param->frequency) {
- dvb_pll_configure(state->config->pll_desc, buf,
- param->frequency, 0);
- dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
- if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
- printk(KERN_WARNING "or51132: set_parameters error "
- "writing to tuner\n");
-
- /* Set to current mode */
- or51132_setmode(fe);
+ dvb_pll_configure(state->config->pll_desc, buf,
+ param->frequency, 0);
+ dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
+ "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
+ if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
+ printk(KERN_WARNING "or51132: set_parameters error "
+ "writing to tuner\n");
- /* Update current frequency */
- state->current_frequency = param->frequency;
- }
+ /* Set to current mode */
+ or51132_setmode(fe);
+
+ /* Update current frequency */
+ state->current_frequency = param->frequency;
return 0;
}
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index ad56a9958404..8a9db23dd1b7 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -34,6 +34,8 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 4f396ac8de77..f265418e3261 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
#include "dvb_frontend.h"
#include "s5h1420.h"
@@ -48,7 +50,8 @@ struct s5h1420_state {
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings);
static int debug = 0;
@@ -91,7 +94,8 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
switch(voltage) {
case SEC_VOLTAGE_13:
- s5h1420_writereg(state, 0x3c, (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
+ s5h1420_writereg(state, 0x3c,
+ (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
break;
case SEC_VOLTAGE_18:
@@ -112,18 +116,21 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
switch(tone) {
case SEC_TONE_ON:
- s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
+ s5h1420_writereg(state, 0x3b,
+ (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
break;
case SEC_TONE_OFF:
- s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+ s5h1420_writereg(state, 0x3b,
+ (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
break;
}
return 0;
}
-static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd* cmd)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -131,6 +138,9 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
unsigned long timeout;
int result = 0;
+ if (cmd->msg_len > 8)
+ return -EINVAL;
+
/* setup for DISEQC */
val = s5h1420_readreg(state, 0x3b);
s5h1420_writereg(state, 0x3b, 0x02);
@@ -138,16 +148,17 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
/* write the DISEQC command bytes */
for(i=0; i< cmd->msg_len; i++) {
- s5h1420_writereg(state, 0x3c + i, cmd->msg[i]);
+ s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
}
/* kick off transmission */
- s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | ((cmd->msg_len-1) << 4) | 0x08);
+ s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
+ ((cmd->msg_len-1) << 4) | 0x08);
/* wait for transmission to complete */
timeout = jiffies + ((100*HZ) / 1000);
while(time_before(jiffies, timeout)) {
- if (s5h1420_readreg(state, 0x3b) & 0x08)
+ if (!(s5h1420_readreg(state, 0x3b) & 0x08))
break;
msleep(5);
@@ -161,7 +172,8 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
return result;
}
-static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply)
+static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
+ struct dvb_diseqc_slave_reply* reply)
{
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
@@ -205,7 +217,7 @@ static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_
/* extract data */
for(i=0; i< length; i++) {
- reply->msg[i] = s5h1420_readreg(state, 0x3c + i);
+ reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
}
exit:
@@ -236,7 +248,7 @@ static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicm
s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
/* wait for transmission to complete */
- timeout = jiffies + ((20*HZ) / 1000);
+ timeout = jiffies + ((100*HZ) / 1000);
while(time_before(jiffies, timeout)) {
if (!(s5h1420_readreg(state, 0x3b) & 0x08))
break;
@@ -259,9 +271,9 @@ static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
val = s5h1420_readreg(state, 0x14);
if (val & 0x02)
- status |= FE_HAS_SIGNAL; // FIXME: not sure if this is right
+ status |= FE_HAS_SIGNAL;
if (val & 0x01)
- status |= FE_HAS_CARRIER; // FIXME: not sure if this is right
+ status |= FE_HAS_CARRIER;
val = s5h1420_readreg(state, 0x36);
if (val & 0x01)
status |= FE_HAS_VITERBI;
@@ -284,8 +296,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* determine lock state */
*status = s5h1420_get_status_bits(state);
- /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion,
- wait a bit and check again */
+ /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+ the inversion, wait a bit and check again */
if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
val = s5h1420_readreg(state, 0x32);
if ((val & 0x07) == 0x03) {
@@ -330,6 +342,10 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
tmp = (tmp * 2 * 7) / 8;
break;
}
+ if (tmp == 0) {
+ printk("s5h1420: avoided division by 0\n");
+ tmp = 1;
+ }
tmp = state->fclk / tmp;
/* set the MPEG_CLK_INTL for the calculated data rate */
@@ -368,16 +384,21 @@ static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
s5h1420_writereg(state, 0x46, 0x1d);
mdelay(25);
- return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ *ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ return 0;
}
static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct s5h1420_state* state = fe->demodulator_priv;
- u8 val = 0xff - s5h1420_readreg(state, 0x15);
+ u8 val = s5h1420_readreg(state, 0x15);
- return (int) ((val << 8) | val);
+ *strength = (u16) ((val << 8) | val);
+
+ return 0;
}
static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
@@ -386,7 +407,10 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
s5h1420_writereg(state, 0x46, 0x1f);
mdelay(25);
- return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ *ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+ return 0;
}
static void s5h1420_reset(struct s5h1420_state* state)
@@ -396,11 +420,12 @@ static void s5h1420_reset(struct s5h1420_state* state)
udelay(10);
}
-static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
{
u64 val;
- val = (p->u.qpsk.symbol_rate / 1000) * (1<<24);
+ val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
if (p->u.qpsk.symbol_rate <= 21000000) {
val *= 2;
}
@@ -415,7 +440,7 @@ static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_fronte
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
{
- u64 val;
+ u64 val = 0;
int sampling = 2;
if (s5h1420_readreg(state, 0x05) & 0x2)
@@ -427,10 +452,10 @@ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
val |= s5h1420_readreg(state, 0x13);
s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
- val *= (state->fclk / 1000);
+ val *= (state->fclk / 1000ULL);
do_div(val, ((1<<24) * sampling));
- return (u32) (val * 1000);
+ return (u32) (val * 1000ULL);
}
static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
@@ -463,46 +488,55 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
* divide fclk by 1000000 to get the correct value. */
- val = - ((val * (state->fclk/1000000)) / (1<<24));
+ val = (((-val) * (state->fclk/1000000)) / (1<<24));
return val;
}
-static void s5h1420_setfec(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
{
+ u8 inversion = 0;
+
+ if (p->inversion == INVERSION_OFF) {
+ inversion = state->config->invert ? 0x08 : 0;
+ } else if (p->inversion == INVERSION_ON) {
+ inversion = state->config->invert ? 0 : 0x08;
+ }
+
if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
- s5h1420_writereg(state, 0x31, 0x00);
s5h1420_writereg(state, 0x30, 0x3f);
+ s5h1420_writereg(state, 0x31, 0x00 | inversion);
} else {
switch(p->u.qpsk.fec_inner) {
case FEC_1_2:
- s5h1420_writereg(state, 0x31, 0x10);
s5h1420_writereg(state, 0x30, 0x01);
+ s5h1420_writereg(state, 0x31, 0x10 | inversion);
break;
case FEC_2_3:
- s5h1420_writereg(state, 0x31, 0x11);
s5h1420_writereg(state, 0x30, 0x02);
+ s5h1420_writereg(state, 0x31, 0x11 | inversion);
break;
case FEC_3_4:
- s5h1420_writereg(state, 0x31, 0x12);
s5h1420_writereg(state, 0x30, 0x04);
- break;
+ s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ break;
case FEC_5_6:
- s5h1420_writereg(state, 0x31, 0x13);
s5h1420_writereg(state, 0x30, 0x08);
+ s5h1420_writereg(state, 0x31, 0x13 | inversion);
break;
case FEC_6_7:
- s5h1420_writereg(state, 0x31, 0x14);
s5h1420_writereg(state, 0x30, 0x10);
+ s5h1420_writereg(state, 0x31, 0x14 | inversion);
break;
case FEC_7_8:
- s5h1420_writereg(state, 0x31, 0x15);
s5h1420_writereg(state, 0x30, 0x20);
+ s5h1420_writereg(state, 0x31, 0x15 | inversion);
break;
default:
@@ -536,22 +570,6 @@ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
return FEC_NONE;
}
-static void s5h1420_setinversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
-{
- if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
- s5h1420_writereg(state, 0x31, 0x00);
- s5h1420_writereg(state, 0x30, 0x3f);
- } else {
- u8 tmp = s5h1420_readreg(state, 0x31) & 0xf7;
- tmp |= 0x10;
-
- if (p->inversion == INVERSION_ON)
- tmp |= 0x80;
-
- s5h1420_writereg(state, 0x31, tmp);
- }
-}
-
static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
{
if (s5h1420_readreg(state, 0x32) & 0x08)
@@ -560,35 +578,35 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
return INVERSION_OFF;
}
-static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
{
struct s5h1420_state* state = fe->demodulator_priv;
- u32 frequency_delta;
+ int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
+ u32 tmp;
/* check if we should do a fast-tune */
memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
s5h1420_get_tune_settings(fe, &fesettings);
frequency_delta = p->frequency - state->tunedfreq;
- if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) &&
+ if ((frequency_delta > -fesettings.max_drift) &&
+ (frequency_delta < fesettings.max_drift) &&
(frequency_delta != 0) &&
(state->fec_inner == p->u.qpsk.fec_inner) &&
(state->symbol_rate == p->u.qpsk.symbol_rate)) {
- s5h1420_setfreqoffset(state, frequency_delta);
+ if (state->config->pll_set) {
+ s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+ state->config->pll_set(fe, p, &tmp);
+ s5h1420_setfreqoffset(state, p->frequency - tmp);
+ }
return 0;
}
/* first of all, software reset */
s5h1420_reset(state);
- /* set tuner PLL */
- if (state->config->pll_set) {
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- state->config->pll_set(fe, p, &state->tunedfreq);
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
- }
-
/* set s5h1420 fclk PLL according to desired symbol rate */
if (p->u.qpsk.symbol_rate > 28000000) {
state->fclk = 88000000;
@@ -609,8 +627,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* set misc registers */
s5h1420_writereg(state, 0x02, 0x00);
+ s5h1420_writereg(state, 0x06, 0x00);
s5h1420_writereg(state, 0x07, 0xb0);
- s5h1420_writereg(state, 0x0a, 0x67);
+ s5h1420_writereg(state, 0x0a, 0xe7);
s5h1420_writereg(state, 0x0b, 0x78);
s5h1420_writereg(state, 0x0c, 0x48);
s5h1420_writereg(state, 0x0d, 0x6b);
@@ -626,21 +645,26 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* start QPSK */
s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
- /* set the frequency offset to adjust for PLL inaccuracy */
- s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq);
+ /* set tuner PLL */
+ if (state->config->pll_set) {
+ s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+ state->config->pll_set(fe, p, &tmp);
+ s5h1420_setfreqoffset(state, 0);
+ }
/* set the reset of the parameters */
s5h1420_setsymbolrate(state, p);
- s5h1420_setinversion(state, p);
- s5h1420_setfec(state, p);
+ s5h1420_setfec_inversion(state, p);
state->fec_inner = p->u.qpsk.fec_inner;
state->symbol_rate = p->u.qpsk.symbol_rate;
state->postlocked = 0;
+ state->tunedfreq = p->frequency;
return 0;
}
-static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
{
struct s5h1420_state* state = fe->demodulator_priv;
@@ -652,7 +676,8 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
{
if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
fesettings->min_delay_ms = 50;
@@ -717,7 +742,8 @@ static void s5h1420_release(struct dvb_frontend* fe)
static struct dvb_frontend_ops s5h1420_ops;
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c)
+struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ struct i2c_adapter* i2c)
{
struct s5h1420_state* state = NULL;
u8 identity;
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index b687fc77ceb3..872028ddf2a2 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -30,6 +30,9 @@ struct s5h1420_config
/* the demodulator's i2c address */
u8 demod_address;
+ /* does the inversion require inversion? */
+ u8 invert:1;
+
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 764a95a2e212..1c6b2e9264bc 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -32,6 +32,8 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "sp8870.h"
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index d868a6927a16..73384e75625e 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -14,6 +14,8 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "sp887x.h"
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 928aca052afe..6122ba754bc5 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
#include "dvb_frontend.h"
#include "stv0297.h"
@@ -35,7 +37,6 @@ struct stv0297_state {
struct dvb_frontend frontend;
unsigned long base_freq;
- u8 pwm;
};
#if 1
@@ -46,94 +47,6 @@ struct stv0297_state {
#define STV0297_CLOCK_KHZ 28900
-static u8 init_tab[] = {
- 0x00, 0x09,
- 0x01, 0x69,
- 0x03, 0x00,
- 0x04, 0x00,
- 0x07, 0x00,
- 0x08, 0x00,
- 0x20, 0x00,
- 0x21, 0x40,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x24, 0x40,
- 0x25, 0x88,
- 0x30, 0xff,
- 0x31, 0x00,
- 0x32, 0xff,
- 0x33, 0x00,
- 0x34, 0x50,
- 0x35, 0x7f,
- 0x36, 0x00,
- 0x37, 0x20,
- 0x38, 0x00,
- 0x40, 0x1c,
- 0x41, 0xff,
- 0x42, 0x29,
- 0x43, 0x00,
- 0x44, 0xff,
- 0x45, 0x00,
- 0x46, 0x00,
- 0x49, 0x04,
- 0x4a, 0xff,
- 0x4b, 0x7f,
- 0x52, 0x30,
- 0x55, 0xae,
- 0x56, 0x47,
- 0x57, 0xe1,
- 0x58, 0x3a,
- 0x5a, 0x1e,
- 0x5b, 0x34,
- 0x60, 0x00,
- 0x63, 0x00,
- 0x64, 0x00,
- 0x65, 0x00,
- 0x66, 0x00,
- 0x67, 0x00,
- 0x68, 0x00,
- 0x69, 0x00,
- 0x6a, 0x02,
- 0x6b, 0x00,
- 0x70, 0xff,
- 0x71, 0x00,
- 0x72, 0x00,
- 0x73, 0x00,
- 0x74, 0x0c,
- 0x80, 0x00,
- 0x81, 0x00,
- 0x82, 0x00,
- 0x83, 0x00,
- 0x84, 0x04,
- 0x85, 0x80,
- 0x86, 0x24,
- 0x87, 0x78,
- 0x88, 0x00,
- 0x89, 0x00,
- 0x90, 0x01,
- 0x91, 0x01,
- 0xa0, 0x00,
- 0xa1, 0x00,
- 0xa2, 0x00,
- 0xb0, 0x91,
- 0xb1, 0x0b,
- 0xc0, 0x53,
- 0xc1, 0x70,
- 0xc2, 0x12,
- 0xd0, 0x00,
- 0xd1, 0x00,
- 0xd2, 0x00,
- 0xd3, 0x00,
- 0xd4, 0x00,
- 0xd5, 0x00,
- 0xde, 0x00,
- 0xdf, 0x00,
- 0x61, 0x49,
- 0x62, 0x0b,
- 0x53, 0x08,
- 0x59, 0x08,
-};
-
static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
{
@@ -378,34 +291,9 @@ static int stv0297_init(struct dvb_frontend *fe)
struct stv0297_state *state = fe->demodulator_priv;
int i;
- /* soft reset */
- stv0297_writereg_mask(state, 0x80, 1, 1);
- stv0297_writereg_mask(state, 0x80, 1, 0);
-
- /* reset deinterleaver */
- stv0297_writereg_mask(state, 0x81, 1, 1);
- stv0297_writereg_mask(state, 0x81, 1, 0);
-
/* load init table */
- for (i = 0; i < sizeof(init_tab); i += 2) {
- stv0297_writereg(state, init_tab[i], init_tab[i + 1]);
- }
-
- /* set a dummy symbol rate */
- stv0297_set_symbolrate(state, 6900);
-
- /* invert AGC1 polarity */
- stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
-
- /* setup bit error counting */
- stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
-
- /* min + max PWM */
- stv0297_writereg(state, 0x4a, 0x00);
- stv0297_writereg(state, 0x4b, state->pwm);
+ for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+ stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
msleep(200);
if (state->config->pll_init)
@@ -606,7 +494,13 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
stv0297_set_inversion(state, inversion);
/* kick off lock */
- stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+ /* Disable corner detection for higher QAMs */
+ if (p->u.qam.modulation == QAM_128 ||
+ p->u.qam.modulation == QAM_256)
+ stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
+ else
+ stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+
stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
@@ -732,7 +626,7 @@ static void stv0297_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops stv0297_ops;
struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
- struct i2c_adapter *i2c, int pwm)
+ struct i2c_adapter *i2c)
{
struct stv0297_state *state = NULL;
@@ -746,7 +640,6 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
state->i2c = i2c;
memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
state->base_freq = 0;
- state->pwm = pwm;
/* check if the demod is there */
if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
index 3be535989302..9e53f019db71 100644
--- a/drivers/media/dvb/frontends/stv0297.h
+++ b/drivers/media/dvb/frontends/stv0297.h
@@ -29,6 +29,12 @@ struct stv0297_config
/* the demodulator's i2c address */
u8 demod_address;
+ /* inittab - array of pairs of values.
+ * First of each pair is the register, second is the value.
+ * List should be terminated with an 0xff, 0xff pair.
+ */
+ u8* inittab;
+
/* does the "inversion" need inverted? */
u8 invert:1;
@@ -38,7 +44,7 @@ struct stv0297_config
};
extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
- struct i2c_adapter* i2c, int pwm);
+ struct i2c_adapter* i2c);
extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
#endif // STV0297_H
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index cfa3928bb487..889d9257215d 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -48,6 +48,7 @@
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
@@ -63,12 +64,8 @@ struct stv0299_state {
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...) \
@@ -481,7 +478,7 @@ static int stv0299_init (struct dvb_frontend* fe)
if (state->config->pll_init) {
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_init(fe);
+ state->config->pll_init(fe, state->i2c);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
}
@@ -520,7 +517,8 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_BER) return 0;
+ stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10);
+ msleep(100);
*ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
@@ -559,8 +557,9 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
- else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30);
+ msleep(100);
+ *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
}
@@ -603,7 +602,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
} else {
/* A "normal" tune is requested */
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, p);
+ state->config->pll_set(fe, state->i2c, p);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
stv0299_writeregI(state, 0x32, 0x80);
@@ -615,7 +614,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
}
} else {
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, p);
+ state->config->pll_set(fe, state->i2c, p);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
stv0299_set_FEC (state, p->u.qpsk.fec_inner);
@@ -709,7 +708,6 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
state->tuner_frequency = 0;
state->symbol_rate = 0;
state->fec_inner = 0;
- state->errmode = STATUS_BER;
/* check if the demod is there */
stv0299_writeregI(state, 0x02, 0x34); /* standby off */
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 79457a80a11f..d0c4484861e1 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -92,8 +92,8 @@ struct stv0299_config
int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
/* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
+ int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 87d5f4d8790f..eaf130e666d8 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2)
- printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n",
- state->frontend.dvb->num, __FUNCTION__, ret);
+ printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
+ __FUNCTION__, ret);
return b1[0];
}
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index ab0c032472cc..3529c618f828 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -32,6 +32,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
#include "dvb_frontend.h"
#include "tda1004x.h"
@@ -1046,8 +1050,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
tmp = tda1004x_read_byte(state, TDA1004X_SNR);
if (tmp < 0)
return -EIO;
- if (tmp)
- tmp = 255 - tmp;
+ tmp = 255 - tmp;
*snr = ((tmp << 8) | tmp);
dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 168e013d23bd..c05cf1861051 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -30,6 +30,7 @@
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "tda8083.h"
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
index 88e125079ca1..d1cabb6a0a13 100644
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ b/drivers/media/dvb/frontends/tda80xx.c
@@ -30,6 +30,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <asm/irq.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 70fb44b391a7..c6d276618e86 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -194,19 +194,18 @@ static int ves1820_init(struct dvb_frontend* fe)
{
struct ves1820_state* state = fe->demodulator_priv;
int i;
- int val;
ves1820_writereg(state, 0, 0);
- for (i = 0; i < 53; i++) {
- val = ves1820_inittab[i];
- if ((i == 2) && (state->config->selagc)) val |= 0x08;
- ves1820_writereg(state, i, val);
- }
+ for (i = 0; i < sizeof(ves1820_inittab); i++)
+ ves1820_writereg(state, i, ves1820_inittab[i]);
+ if (state->config->selagc)
+ ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
ves1820_writereg(state, 0x34, state->pwm);
- if (state->config->pll_init) state->config->pll_init(fe);
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
return 0;
}
@@ -234,7 +233,7 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
ves1820_writereg(state, 0x09, reg0x09[real_qam]);
ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
-
+ ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
return 0;
}
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 706e0bcb5ede..85b437bbddcd 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -633,7 +633,6 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
i2c_set_adapdata(&pluto->i2c_adap, pluto);
strcpy(pluto->i2c_adap.name, DRIVER_NAME);
pluto->i2c_adap.owner = THIS_MODULE;
- pluto->i2c_adap.id = I2C_ALGO_BIT;
pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
pluto->i2c_adap.dev.parent = &pdev->dev;
pluto->i2c_adap.algo_data = &pluto->i2c_bit;
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index bf3c011d2cfb..d8bf65877897 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -102,6 +102,9 @@ config DVB_BUDGET_AV
select VIDEO_DEV
select VIDEO_SAA7146_VV
select DVB_STV0299
+ select DVB_TDA1004X
+ select DVB_TDA10021
+ select FW_LOADER
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index e4c6e87f6c5d..22b203f8ff27 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -168,7 +168,9 @@ static void init_av7110_av(struct av7110 *av7110)
if (ret < 0)
printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
if (rgb_on &&
- (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
+ ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
+ (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
+ (av7110->dev->pci->subsystem_device == 0x0000)) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
//saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
}
@@ -177,9 +179,6 @@ static void init_av7110_av(struct av7110 *av7110)
ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
if (ret < 0)
printk("dvb-ttpci:cannot set volume :%d\n",ret);
- ret = av7110_setup_irc_config(av7110, 0);
- if (ret < 0)
- printk("dvb-ttpci:cannot setup irc config :%d\n",ret);
}
static void recover_arm(struct av7110 *av7110)
@@ -265,60 +264,6 @@ static int arm_thread(void *data)
}
-/**
- * Hack! we save the last av7110 ptr. This should be ok, since
- * you rarely will use more then one IR control.
- *
- * If we want to support multiple controls we would have to do much more...
- */
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
- int ret = 0;
- static struct av7110 *last;
-
- dprintk(4, "%p\n", av7110);
-
- if (!av7110)
- av7110 = last;
- else
- last = av7110;
-
- if (av7110) {
- ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
- av7110->ir_config = ir_config;
- }
- return ret;
-}
-
-static void (*irc_handler)(u32);
-
-void av7110_register_irc_handler(void (*func)(u32))
-{
- dprintk(4, "registering %p\n", func);
- irc_handler = func;
-}
-
-void av7110_unregister_irc_handler(void (*func)(u32))
-{
- dprintk(4, "unregistering %p\n", func);
- irc_handler = NULL;
-}
-
-static void run_handlers(unsigned long ircom)
-{
- if (irc_handler != NULL)
- (*irc_handler)((u32) ircom);
-}
-
-static DECLARE_TASKLET(irtask, run_handlers, 0);
-
-static void IR_handle(struct av7110 *av7110, u32 ircom)
-{
- dprintk(4, "ircommand = %08x\n", ircom);
- irtask.data = (unsigned long) ircom;
- tasklet_schedule(&irtask);
-}
-
/****************************************************************************
* IRQ handling
****************************************************************************/
@@ -711,8 +656,9 @@ static void gpioirq(unsigned long data)
return;
case DATA_IRCOMMAND:
- IR_handle(av7110,
- swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
+ if (av7110->ir_handler)
+ av7110->ir_handler(av7110,
+ swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
break;
@@ -1668,9 +1614,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
u8 data[4];
u32 div;
@@ -1687,7 +1632,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ ret = i2c_transfer(i2c, &msg, 1);
if (ret != 1)
return -EIO;
return 0;
@@ -1751,9 +1696,8 @@ static u8 alps_bsbe1_inittab[] = {
0xff, 0xff
};
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
int ret;
u8 data[4];
u32 div;
@@ -1768,7 +1712,7 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
- ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ ret = i2c_transfer(i2c, &msg, 1);
return (ret != 1) ? -EIO : 0;
}
@@ -1936,6 +1880,98 @@ static struct sp8870_config alps_tdlb7_config = {
};
+static u8 nexusca_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0x7b,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
@@ -1984,6 +2020,7 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
static struct stv0297_config nexusca_stv0297_config = {
.demod_address = 0x1C,
+ .inittab = nexusca_stv0297_inittab,
.invert = 1,
.pll_set = nexusca_stv0297_pll_set,
};
@@ -2261,7 +2298,7 @@ static int frontend_init(struct av7110 *av7110)
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
- av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b);
+ av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
if (av7110->fe) {
/* set TDA9819 into DVB mode */
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
@@ -2692,7 +2729,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
goto err_av7110_exit_v4l_12;
#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
- av7110_ir_init();
+ av7110_ir_init(av7110);
#endif
printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
av7110_num++;
@@ -2734,6 +2771,9 @@ static int av7110_detach(struct saa7146_dev* saa)
struct av7110 *av7110 = saa->ext_priv;
dprintk(4, "%p\n", av7110);
+#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);
@@ -2830,7 +2870,7 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = x_name, \
.ext = &av7110_extension }
-MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X");
+MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
@@ -2842,16 +2882,16 @@ MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
static struct pci_device_id pci_tbl[] = {
- MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
- MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000),
- MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
- MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
- MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
- MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
- MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
- MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
- MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
- MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
+ MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
+ MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
+ MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
+ MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
+ MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
+ MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
+ MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
+ MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
+ MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
+ MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
@@ -2889,9 +2929,6 @@ static int __init av7110_init(void)
static void __exit av7110_exit(void)
{
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
- av7110_ir_exit();
-#endif
saa7146_unregister_extension(&av7110_extension);
}
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 508b7739c609..cce00ef293e9 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -228,7 +228,10 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
- u32 ir_config;
+ u32 ir_config;
+ u32 ir_command;
+ void (*ir_handler)(struct av7110 *av7110, u32 ircom);
+ struct tasklet_struct ir_tasklet;
/* firmware stuff */
unsigned char *bin_fw;
@@ -257,12 +260,10 @@ struct av7110 {
extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid);
-extern void av7110_register_irc_handler(void (*func)(u32));
-extern void av7110_unregister_irc_handler(void (*func)(u32));
extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
-extern int av7110_ir_init (void);
-extern void av7110_ir_exit (void);
+extern int av7110_ir_init(struct av7110 *av7110);
+extern void av7110_ir_exit(struct av7110 *av7110);
/* msp3400 i2c subaddresses */
#define MSP_WR_DEM 0x10
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 1220826696c5..7442f56a72ec 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -41,6 +41,8 @@
#include "av7110.h"
#include "av7110_hw.h"
+#define _NOHANDSHAKE
+
/****************************************************************************
* DEBI functions
****************************************************************************/
@@ -364,7 +366,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
msleep(1);
}
- wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
#ifndef _NOHANDSHAKE
start = jiffies;
@@ -437,7 +440,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
- wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
+ if (FW_VERSION(av7110->arm_app) <= 0x261f)
+ wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
#ifdef COM_DEBUG
start = jiffies;
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 665cdb8a3f71..f5e59fc924af 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -7,15 +7,15 @@
#include <asm/bitops.h>
#include "av7110.h"
+#include "av7110_hw.h"
-#define UP_TIMEOUT (HZ/4)
+#define UP_TIMEOUT (HZ*7/25)
/* enable ir debugging by or'ing debug with 16 */
-static int ir_initialized;
-static struct input_dev input_dev;
-
-static u32 ir_config;
+static int av_cnt;
+static struct av7110 *av_list[4];
+static struct input_dev *input_dev;
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
@@ -43,18 +43,21 @@ static u16 key_map [256] = {
static void av7110_emit_keyup(unsigned long data)
{
- if (!data || !test_bit(data, input_dev.key))
+ if (!data || !test_bit(data, input_dev->key))
return;
- input_event(&input_dev, EV_KEY, data, !!0);
+ input_event(input_dev, EV_KEY, data, !!0);
}
static struct timer_list keyup_timer = { .function = av7110_emit_keyup };
-static void av7110_emit_key(u32 ircom)
+static void av7110_emit_key(unsigned long parm)
{
+ struct av7110 *av7110 = (struct av7110 *) parm;
+ u32 ir_config = av7110->ir_config;
+ u32 ircom = av7110->ir_command;
u8 data;
u8 addr;
static u16 old_toggle = 0;
@@ -62,19 +65,33 @@ static void av7110_emit_key(u32 ircom)
u16 keycode;
/* extract device address and data */
- if (ir_config & 0x0001) {
- /* TODO RCMM: ? bits device address, 8 bits data */
+ switch (ir_config & 0x0003) {
+ case 0: /* RC5: 5 bits device address, 6 bits data */
+ data = ircom & 0x3f;
+ addr = (ircom >> 6) & 0x1f;
+ break;
+
+ case 1: /* RCMM: 8(?) bits device address, 8(?) bits data */
data = ircom & 0xff;
addr = (ircom >> 8) & 0xff;
- } else {
- /* RC5: 5 bits device address, 6 bits data */
+ break;
+
+ case 2: /* extended RC5: 5 bits device address, 7 bits data */
data = ircom & 0x3f;
addr = (ircom >> 6) & 0x1f;
+ /* invert 7th data bit for backward compatibility with RC5 keymaps */
+ if (!(ircom & 0x1000))
+ data |= 0x40;
+ break;
+
+ default:
+ printk("invalid ir_config %x\n", ir_config);
+ return;
}
keycode = key_map[data];
- dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
+ dprintk(16, "code %08x -> addr %i data 0x%02x -> keycode %i\n",
ircom, addr, data, keycode);
/* check device address (if selected) */
@@ -87,21 +104,21 @@ static void av7110_emit_key(u32 ircom)
return;
}
- if (ir_config & 0x0001)
+ if ((ir_config & 0x0003) == 1)
new_toggle = 0; /* RCMM */
else
- new_toggle = (ircom & 0x800); /* RC5 */
+ new_toggle = (ircom & 0x800); /* RC5, extended RC5 */
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
- input_event(&input_dev, EV_KEY, keyup_timer.data, !!0);
- input_event(&input_dev, EV_KEY, keycode, !0);
+ input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
+ input_event(input_dev, EV_KEY, keycode, !0);
} else
- input_event(&input_dev, EV_KEY, keycode, 2);
+ input_event(input_dev, EV_KEY, keycode, 2);
} else
- input_event(&input_dev, EV_KEY, keycode, !0);
+ input_event(input_dev, EV_KEY, keycode, !0);
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@@ -115,13 +132,13 @@ static void input_register_keys(void)
{
int i;
- memset(input_dev.keybit, 0, sizeof(input_dev.keybit));
+ memset(input_dev->keybit, 0, sizeof(input_dev->keybit));
- for (i = 0; i < sizeof(key_map) / sizeof(key_map[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(key_map); i++) {
if (key_map[i] > KEY_MAX)
key_map[i] = 0;
else if (key_map[i] > KEY_RESERVED)
- set_bit(key_map[i], input_dev.keybit);
+ set_bit(key_map[i], input_dev->keybit);
}
}
@@ -137,6 +154,8 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
{
char *page;
int size = 4 + 256 * sizeof(u16);
+ u32 ir_config;
+ int i;
if (count < size)
return -EINVAL;
@@ -153,60 +172,100 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
memcpy(&ir_config, page, 4);
memcpy(&key_map, page + 4, 256 * sizeof(u16));
vfree(page);
- av7110_setup_irc_config(NULL, ir_config);
+ if (FW_VERSION(av_list[0]->arm_app) >= 0x2620 && !(ir_config & 0x0001))
+ ir_config |= 0x0002; /* enable extended RC5 */
+ for (i = 0; i < av_cnt; i++)
+ av7110_setup_irc_config(av_list[i], ir_config);
input_register_keys();
return count;
}
-int __init av7110_ir_init(void)
+int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
{
- static struct proc_dir_entry *e;
+ int ret = 0;
- if (ir_initialized)
- return 0;
+ dprintk(4, "%p\n", av7110);
+ if (av7110) {
+ ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+ av7110->ir_config = ir_config;
+ }
+ return ret;
+}
- init_timer(&keyup_timer);
- keyup_timer.data = 0;
- input_dev.name = "DVB on-card IR receiver";
+static void ir_handler(struct av7110 *av7110, u32 ircom)
+{
+ dprintk(4, "ircommand = %08x\n", ircom);
+ av7110->ir_command = ircom;
+ tasklet_schedule(&av7110->ir_tasklet);
+}
- /**
- * enable keys
- */
- set_bit(EV_KEY, input_dev.evbit);
- set_bit(EV_REP, input_dev.evbit);
- input_register_keys();
+int __init av7110_ir_init(struct av7110 *av7110)
+{
+ static struct proc_dir_entry *e;
+
+ if (av_cnt >= sizeof av_list/sizeof av_list[0])
+ return -ENOSPC;
+
+ av7110_setup_irc_config(av7110, 0x0001);
+ av_list[av_cnt++] = av7110;
- input_register_device(&input_dev);
- input_dev.timer.function = input_repeat_key;
+ if (av_cnt == 1) {
+ init_timer(&keyup_timer);
+ keyup_timer.data = 0;
- av7110_setup_irc_config(NULL, 0x0001);
- av7110_register_irc_handler(av7110_emit_key);
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
- e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
- if (e) {
- e->write_proc = av7110_ir_write_proc;
- e->size = 4 + 256 * sizeof(u16);
+ input_dev->name = "DVB on-card IR receiver";
+
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_REP, input_dev->evbit);
+ input_register_keys();
+ input_register_device(input_dev);
+ input_dev->timer.function = input_repeat_key;
+
+ e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+ if (e) {
+ e->write_proc = av7110_ir_write_proc;
+ e->size = 4 + 256 * sizeof(u16);
+ }
}
- ir_initialized = 1;
+ tasklet_init(&av7110->ir_tasklet, av7110_emit_key, (unsigned long) av7110);
+ av7110->ir_handler = ir_handler;
+
return 0;
}
-void __exit av7110_ir_exit(void)
+void __exit av7110_ir_exit(struct av7110 *av7110)
{
- if (ir_initialized == 0)
+ int i;
+
+ if (av_cnt == 0)
return;
- del_timer_sync(&keyup_timer);
- remove_proc_entry("av7110_ir", NULL);
- av7110_unregister_irc_handler(av7110_emit_key);
- input_unregister_device(&input_dev);
- ir_initialized = 0;
+
+ av7110->ir_handler = NULL;
+ tasklet_kill(&av7110->ir_tasklet);
+ for (i = 0; i < av_cnt; i++)
+ if (av_list[i] == av7110) {
+ av_list[i] = av_list[av_cnt-1];
+ av_list[av_cnt-1] = NULL;
+ break;
+ }
+
+ if (av_cnt == 1) {
+ del_timer_sync(&keyup_timer);
+ remove_proc_entry("av7110_ir", NULL);
+ input_unregister_device(input_dev);
+ }
+
+ av_cnt--;
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
//MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index e65fc36e2ce8..6af74f78b3e5 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -70,7 +70,7 @@ static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
return 0;
}
-static struct v4l2_input inputs[2] = {
+static struct v4l2_input inputs[4] = {
{
.index = 0,
.name = "DVB",
@@ -87,6 +87,22 @@ static struct v4l2_input inputs[2] = {
.tuner = 0,
.std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
.status = 0,
+ }, {
+ .index = 2,
+ .name = "Video",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
+ }, {
+ .index = 3,
+ .name = "Y/C",
+ .type = V4L2_INPUT_TYPE_CAMERA,
+ .audioset = 0,
+ .tuner = 0,
+ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+ .status = 0,
}
};
@@ -212,24 +228,44 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
}
if (0 != av7110->current_input) {
+ dprintk(1, "switching to analog TV:\n");
adswitch = 1;
source = SAA7146_HPS_SOURCE_PORT_B;
sync = SAA7146_HPS_SYNC_PORT_B;
memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
- dprintk(1, "switching to analog TV\n");
- msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
- msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
- msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
- msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
- msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
- msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
- if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
- if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
- dprintk(1, "setting band in demodulator failed.\n");
- } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ switch (av7110->current_input) {
+ case 1:
+ dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+ msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
+ msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
+ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
+ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
+ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
+
+ if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+ if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
+ dprintk(1, "setting band in demodulator failed.\n");
+ } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ }
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 2:
+ dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ case 3:
+ dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+ if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
+ dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+ break;
+ default:
+ dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
}
} else {
adswitch = 0;
@@ -300,7 +336,6 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
// FIXME: standard / stereo detection is still broken
msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
-
msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
stereo = (s8)(stereo_det >> 8);
@@ -310,7 +345,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
t->audmode = V4L2_TUNER_MODE_STEREO;
}
else if (stereo < -0x10) {
- /* bilingual*/
+ /* bilingual */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
}
@@ -344,7 +379,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
fm_matrix = 0x3000; // mono
src = 0x0010;
break;
- default: /* case V4L2_TUNER_MODE_MONO: {*/
+ default: /* case V4L2_TUNER_MODE_MONO: */
dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
fm_matrix = 0x3000; // mono
src = 0x0030;
@@ -406,7 +441,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
if (av7110->analog_tuner_flags) {
- if (i->index < 0 || i->index >= 2)
+ if (i->index < 0 || i->index >= 4)
return -EINVAL;
} else {
if (i->index != 0)
@@ -433,10 +468,9 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
if (!av7110->analog_tuner_flags)
return 0;
- if (input < 0 || input >= 2)
+ if (input < 0 || input >= 4)
return -EINVAL;
- /* FIXME: switch inputs here */
av7110->current_input = input;
return av7110_dvb_c_switch(fh);
}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9746d2bb916f..7692cd23f839 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int timeout = 50; // 5 seconds (4.4.6 Ready)
+ int timeout = 500; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@@ -217,7 +217,6 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
return -ETIMEDOUT;
}
@@ -276,7 +275,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
printk(KERN_INFO "budget-av: cam ejected\n");
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
budget_av->slot_status = 0;
}
}
@@ -453,9 +451,9 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
}
static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
struct dvb_frontend_parameters *params)
{
- struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -481,7 +479,7 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -745,6 +743,7 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBT_KNC1_PLUS:
// Enable / PowerON Frontend
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index a1267054bc01..51c30ba68140 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -40,6 +40,7 @@
#include "dvb_ca_en50221.h"
#include "stv0299.h"
+#include "stv0297.h"
#include "tda1004x.h"
#define DEBIADDR_IR 0x1234
@@ -63,7 +64,7 @@
struct budget_ci {
struct budget budget;
- struct input_dev input_dev;
+ struct input_dev *input_dev;
struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
@@ -144,7 +145,7 @@ static void msp430_ir_debounce(unsigned long data)
static void msp430_ir_interrupt(unsigned long data)
{
struct budget_ci *budget_ci = (struct budget_ci *) data;
- struct input_dev *dev = &budget_ci->input_dev;
+ struct input_dev *dev = budget_ci->input_dev;
unsigned int code =
ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
@@ -180,25 +181,27 @@ static void msp430_ir_interrupt(unsigned long data)
static int msp430_ir_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
+ struct input_dev *input_dev;
int i;
- memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
+ budget_ci->input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
- budget_ci->input_dev.name = budget_ci->ir_dev_name;
- set_bit(EV_KEY, budget_ci->input_dev.evbit);
+ input_dev->name = budget_ci->ir_dev_name;
- for (i = 0; i < sizeof(key_map) / sizeof(*key_map); i++)
+ set_bit(EV_KEY, input_dev->evbit);
+ for (i = 0; i < ARRAY_SIZE(key_map); i++)
if (key_map[i])
- set_bit(key_map[i], budget_ci->input_dev.keybit);
+ set_bit(key_map[i], input_dev->keybit);
- input_register_device(&budget_ci->input_dev);
+ input_register_device(budget_ci->input_dev);
- budget_ci->input_dev.timer.function = msp430_ir_debounce;
+ input_dev->timer.function = msp430_ir_debounce;
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
-
saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
return 0;
@@ -207,7 +210,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
static void msp430_ir_deinit(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
- struct input_dev *dev = &budget_ci->input_dev;
+ struct input_dev *dev = budget_ci->input_dev;
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
@@ -548,9 +551,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -567,7 +569,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_param
if (params->frequency > 1530000)
buf[3] = 0xc0;
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -669,9 +671,9 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
}
static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
struct dvb_frontend_parameters *params)
{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -697,7 +699,7 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -848,6 +850,180 @@ static struct tda1004x_config philips_tdm1316l_config = {
.request_firmware = philips_tdm1316l_request_firmware,
};
+static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+ u8 tuner_buf[5];
+ struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
+ .flags = 0,
+ .buf = tuner_buf,
+ .len = sizeof(tuner_buf) };
+ int tuner_frequency = 0;
+ u8 band, cp, filter;
+
+ // determine charge pump
+ tuner_frequency = params->frequency + 36125000;
+ if (tuner_frequency < 87000000)
+ return -EINVAL;
+ else if (tuner_frequency < 130000000) {
+ cp = 3;
+ band = 1;
+ } else if (tuner_frequency < 160000000) {
+ cp = 5;
+ band = 1;
+ } else if (tuner_frequency < 200000000) {
+ cp = 6;
+ band = 1;
+ } else if (tuner_frequency < 290000000) {
+ cp = 3;
+ band = 2;
+ } else if (tuner_frequency < 420000000) {
+ cp = 5;
+ band = 2;
+ } else if (tuner_frequency < 480000000) {
+ cp = 6;
+ band = 2;
+ } else if (tuner_frequency < 620000000) {
+ cp = 3;
+ band = 4;
+ } else if (tuner_frequency < 830000000) {
+ cp = 5;
+ band = 4;
+ } else if (tuner_frequency < 895000000) {
+ cp = 7;
+ band = 4;
+ } else
+ return -EINVAL;
+
+ // assume PLL filter should always be 8MHz for the moment.
+ filter = 1;
+
+ // calculate divisor
+ tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+
+ // setup tuner buffer
+ tuner_buf[0] = tuner_frequency >> 8;
+ tuner_buf[1] = tuner_frequency & 0xff;
+ tuner_buf[2] = 0xc8;
+ tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ tuner_buf[4] = 0x80;
+
+ stv0297_enable_plli2c(fe);
+ if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ msleep(50);
+
+ stv0297_enable_plli2c(fe);
+ if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ msleep(1);
+
+ return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x20,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x00,
+ 0x4b, 0x7b,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x10,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x04,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x38,
+ 0x62, 0x0a,
+ 0x53, 0x13,
+ 0x59, 0x08,
+ 0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+ .demod_address = 0x1c,
+ .inittab = dvbc_philips_tdm1316l_inittab,
+ .invert = 0,
+ .pll_set = dvbc_philips_tdm1316l_pll_set,
+};
+
+
static void frontend_init(struct budget_ci *budget_ci)
@@ -869,6 +1045,15 @@ static void frontend_init(struct budget_ci *budget_ci)
}
break;
+ case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
+ budget_ci->tuner_pll_address = 0x61;
+ budget_ci->budget.dvb_frontend =
+ stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+ if (budget_ci->budget.dvb_frontend) {
+ break;
+ }
+ break;
+
case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
budget_ci->tuner_pll_address = 0x63;
budget_ci->budget.dvb_frontend =
@@ -878,7 +1063,7 @@ static void frontend_init(struct budget_ci *budget_ci)
}
break;
- case 0x1012: // Hauppauge/TT Nova-T CI budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+ case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
budget_ci->tuner_pll_address = 0x60;
budget_ci->budget.dvb_frontend =
tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
@@ -966,10 +1151,12 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
+ MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
{
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 8142e26b47f5..b1f21ef0e3b3 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -353,9 +353,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -370,7 +369,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 9961917e8a7f..43d6c8268642 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -332,9 +332,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
{
- struct budget* budget = (struct budget*) fe->dvb->priv;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -349,7 +348,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
return 0;
}
@@ -481,6 +480,7 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
static struct s5h1420_config s5h1420_config = {
.demod_address = 0x53,
+ .invert = 1,
.pll_set = s5h1420_pll_set,
};
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index aa43b5fcb8e7..d200ab0ad9e7 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/errno.h>
+#include <linux/jiffies.h>
#include <asm/semaphore.h>
#include "dvb_frontend.h"
@@ -570,7 +571,8 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
const u8 * data, int len);
#endif
-static int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid;
+static int numpkt = 0, numts, numstuff, numsec, numinvalid;
+static unsigned long lastj;
static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
int len)
@@ -779,7 +781,7 @@ static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
u8 *data;
int len;
numpkt++;
- if ((jiffies - lastj) >= HZ) {
+ if (time_after_eq(jiffies, lastj + HZ)) {
#if DEBUG > 2
printk
("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
@@ -1299,7 +1301,7 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
return 0;
}
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
@@ -1322,7 +1324,7 @@ static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
if (ttusb->revision == TTUSB_REV_2_2)
buf[3] |= 0x20;
- if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1472,8 +1474,6 @@ static void frontend_init(struct ttusb* ttusb)
static struct i2c_algorithm ttusb_dec_algo = {
- .name = "ttusb dec i2c algorithm",
- .id = I2C_ALGO_BIT,
.master_xfer = master_xfer,
.functionality = functionality,
};
@@ -1525,7 +1525,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
#endif
ttusb->i2c_adap.algo = &ttusb_dec_algo;
ttusb->i2c_adap.algo_data = NULL;
- ttusb->i2c_adap.id = I2C_ALGO_BIT;
result = i2c_add_adapter(&ttusb->i2c_adap);
if (result) {
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 45c9a9a08e4d..832d179f26fa 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -28,7 +28,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
-#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
@@ -153,7 +152,8 @@ struct ttusb_dec {
struct list_head filter_info_list;
spinlock_t filter_info_list_lock;
- struct input_dev rc_input_dev;
+ struct input_dev *rc_input_dev;
+ char rc_phys[64];
int active; /* Loaded successfully */
};
@@ -236,9 +236,9 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
* this should/could be added later ...
* for now lets report each signal as a key down and up*/
dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
- input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1);
- input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0);
- input_sync(&dec->rc_input_dev);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+ input_sync(dec->rc_input_dev);
}
exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1182,29 +1182,38 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
-static void ttusb_init_rc( struct ttusb_dec *dec)
+static int ttusb_init_rc(struct ttusb_dec *dec)
{
+ struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
int i;
- init_input_dev(&dec->rc_input_dev);
+ usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
+ strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
- dec->rc_input_dev.name = "ttusb_dec remote control";
- dec->rc_input_dev.evbit[0] = BIT(EV_KEY);
- dec->rc_input_dev.keycodesize = sizeof(u16);
- dec->rc_input_dev.keycodemax = 0x1a;
- dec->rc_input_dev.keycode = rc_keys;
+ dec->rc_input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "ttusb_dec remote control";
+ input_dev->phys = dec->rc_phys;
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->keycodesize = sizeof(u16);
+ input_dev->keycodemax = 0x1a;
+ input_dev->keycode = rc_keys;
- for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
- set_bit(rc_keys[i], dec->rc_input_dev.keybit);
+ for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
+ set_bit(rc_keys[i], input_dev->keybit);
- input_register_device(&dec->rc_input_dev);
+ input_register_device(input_dev);
- if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) {
+ if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
- }
+
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+
+ return 0;
}
static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
@@ -1514,7 +1523,7 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
* As the irq is submitted after the interface is changed,
* this is the best method i figured out.
* Any others?*/
- if(dec->interface == TTUSB_DEC_INTERFACE_IN)
+ if (dec->interface == TTUSB_DEC_INTERFACE_IN)
usb_kill_urb(dec->irq_urb);
usb_free_urb(dec->irq_urb);
@@ -1522,7 +1531,10 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
dec->irq_buffer, dec->irq_dma_handle);
- input_unregister_device(&dec->rc_input_dev);
+ if (dec->rc_input_dev) {
+ input_unregister_device(dec->rc_input_dev);
+ dec->rc_input_dev = NULL;
+ }
}
@@ -1660,7 +1672,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
- if(enable_rc)
+ if (enable_rc)
ttusb_init_rc(dec);
return 0;
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index df79d5e0aaed..e09214082e01 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
+#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
#include <linux/delay.h>
#include <asm/uaccess.h>
#include "miropcm20-rds-core.h"
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 8b4ad70dd1b2..877c770558e9 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 013c835ed910..5319a9c9a979 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,7 +26,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 53d399b6652b..9b0406318f2d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
@@ -543,7 +543,7 @@ static int cadet_probe(void)
for(i=0;i<8;i++) {
io=iovals[i];
- if(request_region(io,2, "cadet-probe")>=0) {
+ if (request_region(io, 2, "cadet-probe")) {
cadet_setfreq(1410);
if(cadet_getfreq()==1410) {
release_region(io, 2);
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 202bfe6819b8..6418f03b9ce4 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -17,7 +17,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index c00245d4d249..b2256d675b44 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -10,7 +10,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 3a464a09221f..6f03ce4dd7b0 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h> /* __setup */
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/isapnp.h>
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0732efda6a98..71971e9bb342 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -14,7 +14,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 248d67fde037..b03573c6840e 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -25,7 +25,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index d7da901ebe90..f304f3c14763 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -31,7 +31,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/proc_fs.h> /* radio card status report */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 342f92df4aba..4c6d6fb49034 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -28,7 +28,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay, msleep */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index ac81e5e01a9a..bbb989df4cf0 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -22,12 +22,21 @@ config VIDEO_BT848
the Miro, Hauppauge and STB boards. Please read the material in
<file:Documentation/video4linux/bttv/> for more information.
- If you say Y or M here, you need to say Y or M to "I2C support" and
- "I2C bit-banging interfaces" in the device drivers section.
-
To compile this driver as a module, choose M here: the
module will be called bttv.
+config VIDEO_SAA6588
+ tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
+ depends on VIDEO_DEV && I2C && VIDEO_BT848
+
+ help
+ Support for Radio Data System (RDS) decoder. This allows seeing
+ radio station identification transmitted using this standard.
+ Currentlly, it works only with bt8x8 chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa6588.
+
config VIDEO_PMS
tristate "Mediavision Pro Movie Studio Video For Linux"
depends on VIDEO_DEV && ISA
@@ -253,7 +262,7 @@ config VIDEO_SAA7134_DVB
depends on VIDEO_SAA7134 && DVB_CORE
select VIDEO_BUF_DVB
select DVB_MT352
- select DVB_CX22702
+ select DVB_TDA1004X
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
@@ -356,7 +365,7 @@ config VIDEO_M32R_AR
config VIDEO_M32R_AR_M64278
tristate "Use Colour AR module M64278(VGA)"
- depends on VIDEO_M32R_AR
+ depends on VIDEO_M32R_AR && PLAT_M32700UT
---help---
Say Y here to use the Renesas M64278E-800 camera module,
which supports VGA(640x480 pixcels) size of images.
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 810e7aac0a53..046b82de9285 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -5,6 +5,7 @@
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
+rds-objs := saa6588.o
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
+obj-$(CONFIG_VIDEO_SAA6588) += rds.o
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
@@ -29,7 +31,7 @@ obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
obj-$(CONFIG_VIDEO_PMS) += pms.o
obj-$(CONFIG_VIDEO_PLANB) += planb.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o saa7191.o indycam.o
obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 48989eda2400..1ca2b67aedfb 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -391,7 +390,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7170;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index f898b6586374..173bca1e0295 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -39,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -441,7 +440,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7175;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 8733588f6db3..3ee0afca76a7 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -507,7 +506,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_bt819;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index a070417e65e6..76c1b63ebdf2 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -188,7 +188,7 @@ static int bt832_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, bt832_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, bt832_attach);
#endif
return 0;
@@ -241,7 +241,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("bt832"),
+ .name = "bt832",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index a5d529ccf3ad..8eb871d0e85b 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -295,7 +294,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_bt856;
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index 7f2d515d2873..a48de3c0e3f0 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -1,5 +1,4 @@
/*
- $Id: btcx-risc.c,v 1.6 2005/02/21 13:57:59 kraxel Exp $
btcx-risc.c
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h
index 41f60395a520..503e6c6d7b69 100644
--- a/drivers/media/video/btcx-risc.h
+++ b/drivers/media/video/btcx-risc.h
@@ -1,5 +1,4 @@
/*
- * $Id: btcx-risc.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
*/
struct btcx_riscmem {
unsigned int size;
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 6c52fd0bb7df..0881a17d5226 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-cards.c,v 1.54 2005/07/19 18:26:46 mkrufky Exp $
bttv-cards.c
@@ -95,7 +94,7 @@ static int __devinit pvr_boot(struct bttv *btv);
static unsigned int triton1=0;
static unsigned int vsfx=0;
static unsigned int latency = UNSET;
-static unsigned int no_overlay=-1;
+int no_overlay=-1;
static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
@@ -169,10 +168,10 @@ static struct CARD {
{ 0xd01810fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" },
{ 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
- // some cards ship with byteswapped IDs ...
+ /* some cards ship with byteswapped IDs ... */
{ 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
{ 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
- // this seems to happen as well ...
+ /* this seems to happen as well ... */
{ 0xff1211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
@@ -200,12 +199,12 @@ static struct CARD {
{ 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV Radio+" },
{ 0x1127153b, BTTV_TERRATV, "Terratec TV+ (V1.05)" },
- // clashes with FlyVideo
- //{ 0x18521852, BTTV_TERRATV, "Terratec TV+ (V1.10)" },
+ /* clashes with FlyVideo
+ *{ 0x18521852, BTTV_TERRATV, "Terratec TV+ (V1.10)" }, */
{ 0x1134153b, BTTV_TERRATVALUE, "Terratec TValue (LR102)" },
- { 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, // LR102
- { 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" }, // ??
- { 0xff3b153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, // ??
+ { 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */
+ { 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" }, /* ?? */
+ { 0xff3b153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */
{ 0x400015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
@@ -287,10 +286,12 @@ static struct CARD {
{ 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
{ 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
- // likely broken, vendor id doesn't match the other magic views ...
- //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+ { 0x15409511, BTTV_ACORP_Y878F, "Acorp Y878F" },
- // DVB cards (using pci function .1 for mpeg data xfer)
+ /* likely broken, vendor id doesn't match the other magic views ...
+ * { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+
+ /* DVB cards (using pci function .1 for mpeg data xfer) */
{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
{ 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" },
@@ -298,7 +299,8 @@ static struct CARD {
{ 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB" },
{ 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
- { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DVICO FusionHDTV DVB-T Lite" },
+ { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
+ { 0xd50018ac, BTTV_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0, -1, NULL }
};
@@ -316,6 +318,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1, 0},
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MIRO PCTV",
.video_inputs = 4,
@@ -327,6 +330,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 2, 0, 0, 0, 10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Hauppauge (bt848)",
.video_inputs = 4,
@@ -338,6 +342,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "STB, Gateway P/N 6000699 (bt848)",
.video_inputs = 3,
@@ -350,6 +355,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -365,6 +371,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Diamond DTV2000",
.video_inputs = 4,
@@ -376,6 +383,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 0, 1, 3},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "AVerMedia TVPhone",
.video_inputs = 3,
@@ -388,6 +396,7 @@ struct tvcard bttv_tvcards[] = {
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = avermedia_tvphone_audio,
.has_remote = 1,
},{
@@ -401,6 +410,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0 },
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x08 ---------------------------------- */
@@ -415,6 +425,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "IMS/IXmicro TurboTV",
.video_inputs = 3,
@@ -427,6 +438,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Hauppauge (bt878)",
.video_inputs = 4,
@@ -439,6 +451,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MIRO PCTV pro",
.video_inputs = 3,
@@ -450,6 +463,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20001,0x10001, 0, 0,10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x0c ---------------------------------- */
@@ -463,6 +477,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 13, 14, 11, 7, 0, 0},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "AVerMedia TVCapture 98",
.video_inputs = 3,
@@ -476,6 +491,7 @@ struct tvcard bttv_tvcards[] = {
.msp34xx_alt = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = avermedia_tv_stereo_audio,
},{
.name = "Aimslab Video Highway Xtreme (VHX)",
@@ -489,6 +505,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Zoltrix TV-Max",
.video_inputs = 3,
@@ -500,6 +517,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0 , 0, 1 , 0, 10},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x10 ---------------------------------- */
@@ -510,7 +528,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x01fe00,
.muxsel = { 2, 3, 1, 1},
- // 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru>
+ /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
.audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -526,6 +544,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = winview_audio,
.has_radio = 1,
},{
@@ -539,6 +558,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {1, 0, 0, 0, 0},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
.video_inputs = 4,
@@ -550,6 +570,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.no_msp34xx = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x14 ---------------------------------- */
@@ -560,10 +581,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = {2, 3, 1, 1},
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
.video_inputs = 4,
- .audio_inputs = 2, // tuner, line in
+ .audio_inputs = 2, /* tuner, line in */
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
@@ -571,6 +593,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Askey CPH050/ Phoebe Tv Master + FM",
.video_inputs = 3,
@@ -583,6 +606,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
.video_inputs = 3,
@@ -591,11 +615,12 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 7,
.muxsel = { 2, 3, -1 },
- .digital_mode = DIGITAL_MODE_CAMERA,
+ .digital_mode = DIGITAL_MODE_CAMERA,
.audiomux = { 0, 0, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSBB5_PAL_I,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x18 ---------------------------------- */
@@ -610,6 +635,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
},{
.name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
@@ -622,6 +648,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000},
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
},{
.name = "Hauppauge WinCam newer (bt878)",
@@ -634,6 +661,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
.video_inputs = 4,
@@ -645,6 +673,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_SECAM,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x1c ---------------------------------- */
@@ -658,37 +687,38 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
/* GPIO wiring:
- External 20 pin connector (for Active Radio Upgrade board)
- gpio00: i2c-sda
- gpio01: i2c-scl
- gpio02: om5610-data
- gpio03: om5610-clk
- gpio04: om5610-wre
- gpio05: om5610-stereo
- gpio06: rds6588-davn
- gpio07: Pin 7 n.c.
- gpio08: nIOW
- gpio09+10: nIOR, nSEL ?? (bt878)
- gpio09: nIOR (bt848)
- gpio10: nSEL (bt848)
- Sound Routing:
- gpio16: u2-A0 (1st 4052bt)
- gpio17: u2-A1
- gpio18: u2-nEN
- gpio19: u4-A0 (2nd 4052)
- gpio20: u4-A1
- u4-nEN - GND
- Btspy:
- 00000 : Cdrom (internal audio input)
+ External 20 pin connector (for Active Radio Upgrade board)
+ gpio00: i2c-sda
+ gpio01: i2c-scl
+ gpio02: om5610-data
+ gpio03: om5610-clk
+ gpio04: om5610-wre
+ gpio05: om5610-stereo
+ gpio06: rds6588-davn
+ gpio07: Pin 7 n.c.
+ gpio08: nIOW
+ gpio09+10: nIOR, nSEL ?? (bt878)
+ gpio09: nIOR (bt848)
+ gpio10: nSEL (bt848)
+ Sound Routing:
+ gpio16: u2-A0 (1st 4052bt)
+ gpio17: u2-A1
+ gpio18: u2-nEN
+ gpio19: u4-A0 (2nd 4052)
+ gpio20: u4-A1
+ u4-nEN - GND
+ Btspy:
+ 00000 : Cdrom (internal audio input)
10000 : ext. Video audio input
20000 : TV Mono
a0000 : TV Mono/2
- 1a0000 : TV Stereo
+ 1a0000 : TV Stereo
30000 : Radio
40000 : Mute
- */
+*/
},{
/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
@@ -702,6 +732,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.muxsel_hook = PXC200_muxsel,
},{
@@ -710,11 +741,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .gpiomask = 0x1800, //0x8dfe00
+ .gpiomask = 0x1800, /* 0x8dfe00 */
.muxsel = { 2, 3, 1, 1},
.audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Formac iProTV, Formac ProTV I (bt848)",
.video_inputs = 4,
@@ -726,6 +758,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 1, 0, 0, 0, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x20 ---------------------------------- */
@@ -739,6 +772,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TerraTValue Version Bt878",
.video_inputs = 3,
@@ -751,31 +785,33 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Leadtek WinFast 2000/ WinFast 2000 XP",
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1, 0}, // TV, CVid, SVid, CVid over SVid connector
+ .muxsel = { 2, 3, 1, 1, 0}, /* TV, CVid, SVid, CVid over SVid connector */
/* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
.gpiomask = 0xb33000,
.audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 },
/* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
gpio23 -- hef4052:nEnable (0x800000)
gpio12 -- hef4052:A1
- gpio13 -- hef4052:A0
- 0x0000: external audio
- 0x1000: FM
- 0x2000: TV
- 0x3000: n.c.
- Note: There exists another variant "Winfast 2000" with tv stereo !?
- Note: eeprom only contains FF and pci subsystem id 107d:6606
- */
+ gpio13 -- hef4052:A0
+ 0x0000: external audio
+ 0x1000: FM
+ 0x2000: TV
+ 0x3000: n.c.
+ Note: There exists another variant "Winfast 2000" with tv stereo !?
+ Note: eeprom only contains FF and pci subsystem id 107d:6606
+ */
.needs_tvaudio = 0,
.pll = PLL_28,
.has_radio = 1,
- .tuner_type = 5, // default for now, gpio reads BFFF06 for Pal bg+dk
+ .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+ .tuner_addr = ADDR_UNSET,
.audio_hook = winfast2000_audio,
.has_remote = 1,
},{
@@ -789,6 +825,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x24 ---------------------------------- */
@@ -802,6 +839,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
.name = "Prolink PixelView PlayTV pro",
@@ -815,6 +853,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Askey CPH06X TView99",
.video_inputs = 4,
@@ -827,6 +866,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
},{
.name = "Pinnacle PCTV Studio/Rave",
@@ -840,6 +880,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x28 ---------------------------------- */
@@ -854,6 +895,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -868,6 +910,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
.audio_hook = avermedia_tvphone_audio,
},{
@@ -883,6 +926,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Little OnAir TV",
.video_inputs = 3,
@@ -894,6 +938,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
.no_msp34xx = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x2c ---------------------------------- */
@@ -908,6 +953,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_NONE,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "MATRIX-Vision MV-Delta 2",
.video_inputs = 5,
@@ -920,6 +966,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Zoltrix Genie TV/FM",
.video_inputs = 3,
@@ -932,6 +979,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 21,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TV/Radio+",
.video_inputs = 3,
@@ -945,6 +993,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_35,
.tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
@@ -960,6 +1009,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "IODATA GV-BCTV3/PCI",
.video_inputs = 3,
@@ -972,6 +1022,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
},{
.name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
@@ -986,6 +1037,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
/* GPIO wiring: (different from Rev.4C !)
GPIO17: U4.A0 (first hef4052bt)
@@ -994,8 +1046,8 @@ struct tvcard bttv_tvcards[] = {
GPIO21: U4.nEN
GPIO22: BT832 Reset Line
GPIO23: A5,A0, U5,nEN
- Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
- */
+ Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
+ */
},{
.name = "Eagle Wireless Capricorn2 (bt878A)",
.video_inputs = 4,
@@ -1007,6 +1059,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 1, 2, 3, 4},
.pll = PLL_28,
.tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x34 ---------------------------------- */
@@ -1020,20 +1073,21 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1},
.audiomux = { 1, 0xd0001, 0, 0, 10},
/* sound path (5 sources):
- MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
+ MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
0= ext. Audio IN
1= from MUX2
2= Mono TV sound from Tuner
3= not connected
- MUX2 (mask 0x30000):
+ MUX2 (mask 0x30000):
0,2,3= from MSP34xx
1= FM stereo Radio from Tuner */
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Claas Langbehn <claas@bigfoot.com>,
- Sven Grothklags <sven@upb.de> */
+ Sven Grothklags <sven@upb.de> */
.name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
.video_inputs = 4,
.audio_inputs = 3,
@@ -1045,10 +1099,11 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
/* Tim Röstermundt <rosterm@uni-muenster.de>
- in de.comp.os.unix.linux.hardware:
+ in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
options tuner type=5 */
@@ -1060,15 +1115,16 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x18e0,
.muxsel = { 2, 3, 1, 1},
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
- /* For cards with tda9820/tda9821:
- 0x0000: Tuner normal stereo
- 0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
- 0x0880: Tuner A2 stereo */
+ /* For cards with tda9820/tda9821:
+ 0x0000: Tuner normal stereo
+ 0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
+ 0x0880: Tuner A2 stereo */
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
- old Easy TV BT848 version (model CPH031) */
+ old Easy TV BT848 version (model CPH031) */
.name = "Askey CPH031/ BESTBUY Easy TV",
.video_inputs = 4,
.audio_inputs = 1,
@@ -1080,6 +1136,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x38 ---------------------------------- */
@@ -1094,10 +1151,11 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
},{
/* This is the ultimate cheapo capture card
- * just a BT848A on a small PCB!
- * Steve Hosgood <steve@equiinet.com> */
+ * just a BT848A on a small PCB!
+ * Steve Hosgood <steve@equiinet.com> */
.name = "GrandTec 'Grand Video Capture' (Bt848)",
.video_inputs = 2,
.audio_inputs = 0,
@@ -1110,19 +1168,21 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_35,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- /* Daniel Herrington <daniel.herrington@home.com> */
- .name = "Askey CPH060/ Phoebe TV Master Only (No FM)",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0xe00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = TUNER_TEMIC_4036FY5_NTSC,
+ /* Daniel Herrington <daniel.herrington@home.com> */
+ .name = "Askey CPH060/ Phoebe TV Master Only (No FM)",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0xe00,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = TUNER_TEMIC_4036FY5_NTSC,
+ .tuner_addr = ADDR_UNSET,
},{
/* Matti Mottus <mottus@physic.ut.ee> */
.name = "Askey CPH03x TV Capturer",
@@ -1130,11 +1190,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .gpiomask = 0x03000F,
+ .gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 0},
- .audiomux = { 2,0,0,0,1 },
+ .audiomux = { 2,0,0,0,1 },
.pll = PLL_28,
.tuner_type = 0,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x3c ---------------------------------- */
@@ -1149,7 +1210,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 2, 0, 0, 1, 8},
.pll = PLL_35,
.tuner_type = TUNER_TEMIC_PAL,
-
+ .tuner_addr = ADDR_UNSET,
},{
/* Adrian Cox <adrian@humboldt.co.uk */
.name = "AG Electronics GMV1",
@@ -1164,10 +1225,11 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
- new Easy TV BT878 version (model CPH061)
- special thanks to Informatica Mieres for providing the card */
+ new Easy TV BT878 version (model CPH061)
+ special thanks to Informatica Mieres for providing the card */
.name = "Askey CPH061/ BESTBUY Easy TV (bt878)",
.video_inputs = 3,
.audio_inputs = 2,
@@ -1179,6 +1241,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* Lukas Gebauer <geby@volny.cz> */
.name = "ATI TV-Wonder",
@@ -1191,6 +1254,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe},
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x40 ---------------------------------- */
@@ -1206,6 +1270,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
+ .tuner_addr = ADDR_UNSET,
},{
/* DeeJay <deejay@westel900.net (2000S) */
.name = "Lifeview FlyVideo 2000S LR90",
@@ -1216,7 +1281,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x18e0,
.muxsel = { 2, 3, 0, 1},
/* Radio changed from 1e80 to 0x800 to make
- FlyVideo2000S in .hu happy (gm)*/
+ FlyVideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 },
.audio_hook = fv2000s_audio,
@@ -1225,6 +1290,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "Terratec TValueRadio",
.video_inputs = 3,
@@ -1237,6 +1303,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 1,
},{
/* TANAKA Kei <peg00625@nifty.com> */
@@ -1251,25 +1318,27 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
},{
/* ---- card 0x44 ---------------------------------- */
- .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
- // try "insmod msp3400 simple=0" if you have
- // sound problems with this card.
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = -1,
- .gpiomask = 0x4f8a00,
- // 0x100000: 1=MSP enabled (0=disable again)
- // 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC)
- .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
- // tvtuner, radio, external,internal, mute, stereo
- /* tuner, Composit, SVid, Composit-on-Svid-adapter*/
- .muxsel = { 2, 3 ,0 ,1},
- .tuner_type = TUNER_MT2032,
+ .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+ /* try "insmod msp3400 simple=0" if you have
+ * sound problems with this card. */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = -1,
+ .gpiomask = 0x4f8a00,
+ /* 0x100000: 1=MSP enabled (0=disable again)
+ * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+ .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
+ /* tvtuner, radio, external,internal, mute, stereo
+ * tuner, Composit, SVid, Composit-on-Svid-adapter */
+ .muxsel = { 2, 3 ,0 ,1},
+ .tuner_type = TUNER_MT2032,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
@@ -1279,22 +1348,24 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.muxsel = { 2 },
.gpiomask = 0
},{
- /* Tomasz Pyra <hellfire@sedez.iq.pl> */
- .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
- .video_inputs = 3,
- .audio_inputs = 4,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0, 11, 7, 13, 0}, // TV and Radio with same GPIO !
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = 25,
+ /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+ .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
+ .video_inputs = 3,
+ .audio_inputs = 4,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 15,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = 25,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
/* GPIO wiring:
GPIO0: U4.A0 (hef4052bt)
@@ -1302,16 +1373,18 @@ struct tvcard bttv_tvcards[] = {
GPIO2: U4.A1 (second hef4052bt)
GPIO3: U4.nEN, U5.A0, A5.nEN
GPIO8-15: vrd866b ?
- */
+ */
},{
.name = "Lifeview FlyVideo 98EZ (capture only) LR51",
.video_inputs = 4,
.audio_inputs = 0,
.tuner = -1,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
+ .muxsel = { 2, 3, 1, 1}, /* AV1, AV2, SVHS, CVid adapter on SVHS */
.pll = PLL_28,
.no_msp34xx = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x48 ---------------------------------- */
@@ -1329,8 +1402,9 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.pll = PLL_28,
.tuner_type = 5,
- .audio_hook = pvbt878p9b_audio, // Note: not all cards have stereo
- .has_radio = 1, // Note: not all cards have radio
+ .tuner_addr = ADDR_UNSET,
+ .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */
+ .has_radio = 1, /* Note: not all cards have radio */
.has_remote = 1,
/* GPIO wiring:
GPIO0: A0 hef4052
@@ -1338,7 +1412,7 @@ struct tvcard bttv_tvcards[] = {
GPIO3: nEN hef4052
GPIO8-15: vrd866b
GPIO20,22,23: R30,R29,R28
- */
+ */
},{
/* Clay Kunz <ckunz@mail.arc.nasa.gov> */
/* you must jumper JP5 for the card to work */
@@ -1352,6 +1426,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Miguel Freitas <miguel@cetuc.puc-rio.br> */
.name = "RemoteVision MX (RV605)",
@@ -1362,71 +1437,78 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x00,
.gpiomask2 = 0x07ff,
.muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
- 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
+ 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.muxsel_hook = rv605_muxsel,
},{
- .name = "Powercolor MTV878/ MTV878R/ MTV878F",
- .video_inputs = 3,
- .audio_inputs = 2,
+ .name = "Powercolor MTV878/ MTV878R/ MTV878F",
+ .video_inputs = 3,
+ .audio_inputs = 2,
.tuner = 0,
- .svhs = 2,
- .gpiomask = 0x1C800F, // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
- .muxsel = { 2, 1, 1, },
- .audiomux = { 0, 1, 2, 2, 4 },
- .needs_tvaudio = 0,
- .tuner_type = TUNER_PHILIPS_PAL,
+ .svhs = 2,
+ .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
+ .muxsel = { 2, 1, 1, },
+ .audiomux = { 0, 1, 2, 2, 4 },
+ .needs_tvaudio = 0,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
.has_radio = 1,
},{
/* ---- card 0x4c ---------------------------------- */
- /* Masaki Suzuki <masaki@btree.org> */
- .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x140007,
- .muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4, 0 },
- .tuner_type = TUNER_PHILIPS_NTSC,
- .audio_hook = windvr_audio,
-},{
- .name = "GrandTec Multi Capture Card (Bt878)",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .gpiomask = 0,
- .muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = -1,
-},{
- .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
- .video_inputs = 4,
- .audio_inputs = 3,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 7,
- .muxsel = { 2, 3, 1, 1 }, // Tuner, SVid, SVHS, SVid to SVHS connector
- .audiomux = { 0 ,0 ,4, 4,4,4},// Yes, this tuner uses the same audio output for TV and FM radio!
- // This card lacks external Audio In, so we mute it on Ext. & Int.
- // The PCB can take a sbx1637/sbx1673, wiring unknown.
- // This card lacks PCI subsystem ID, sigh.
- // audiomux=1: lower volume, 2+3: mute
- // btwincap uses 0x80000/0x80003
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = 5, // Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
- // radio signal strength indicators work fine.
- .has_radio = 1,
+ /* Masaki Suzuki <masaki@btree.org> */
+ .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x140007,
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4, 0 },
+ .tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
+ .audio_hook = windvr_audio,
+},{
+ .name = "GrandTec Multi Capture Card (Bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+},{
+ .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
+ .video_inputs = 4,
+ .audio_inputs = 3,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */
+ .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio!
+ * This card lacks external Audio In, so we mute it on Ext. & Int.
+ * The PCB can take a sbx1637/sbx1673, wiring unknown.
+ * This card lacks PCI subsystem ID, sigh.
+ * audiomux=1: lower volume, 2+3: mute
+ * btwincap uses 0x80000/0x80003
+ */
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
+ /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
+ radio signal strength indicators work fine. */
+ .has_radio = 1,
/* GPIO Info:
GPIO0,1: HEF4052 A0,A1
GPIO2: HEF4052 nENABLE
@@ -1437,25 +1519,27 @@ struct tvcard bttv_tvcards[] = {
GPIO22,23: ??
?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
},{
- /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
- .name = "DSP Design TCVIDEO",
- .video_inputs = 4,
- .svhs = -1,
- .muxsel = { 2, 3, 1, 0},
- .pll = PLL_28,
- .tuner_type = -1,
+ /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
+ .name = "DSP Design TCVIDEO",
+ .video_inputs = 4,
+ .svhs = -1,
+ .muxsel = { 2, 3, 1, 0},
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- /* ---- card 0x50 ---------------------------------- */
+ /* ---- card 0x50 ---------------------------------- */
.name = "Hauppauge WinTV PVR",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 0, 1, 1},
- .needs_tvaudio = 1,
- .pll = PLL_28,
- .tuner_type = -1,
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 0, 1, 1},
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.gpiomask = 7,
.audiomux = {7},
@@ -1471,6 +1555,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = gvbctv5pci_audio,
.has_radio = 1,
},{
@@ -1482,9 +1567,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 3, 2, 0, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
.video_inputs = 3,
@@ -1494,9 +1580,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x54 ---------------------------------- */
@@ -1508,9 +1595,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 3, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */
.video_inputs = 1,
@@ -1520,9 +1608,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 0 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */
.video_inputs = 2,
@@ -1532,9 +1621,10 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 0, 1 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */
.video_inputs = 1,
@@ -1543,10 +1633,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.muxsel = { 0 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x58 ---------------------------------- */
@@ -1557,10 +1648,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 0, 1 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */
.video_inputs = 2,
@@ -1569,10 +1661,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
.name = "Osprey 500", /* 500 */
.video_inputs = 2,
@@ -1582,19 +1675,21 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3 },
.pll = PLL_28,
.tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
- .name = "Osprey 540", /* 540 */
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = -1,
- .pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
+ .name = "Osprey 540", /* 540 */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = -1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
},{
/* ---- card 0x5C ---------------------------------- */
@@ -1605,10 +1700,11 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
- .tuner_type = -1,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */
},{
/* M G Berberich <berberic@forwiss.uni-passau.de> */
.name = "IDS Eagle",
@@ -1616,6 +1712,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
.gpiomask = 0,
.muxsel = { 0, 1, 2, 3 },
@@ -1630,6 +1727,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -1641,38 +1739,40 @@ struct tvcard bttv_tvcards[] = {
.no_gpioirq = 1,
.has_dvb = 1,
},{
- .name = "Formac ProTV II (bt878)",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 3,
- .gpiomask = 2,
- // TV, Comp1, Composite over SVID con, SVID
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 2, 0, 0, 0 },
- .pll = PLL_28,
+ .name = "Formac ProTV II (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 3,
+ .gpiomask = 2,
+ /* TV, Comp1, Composite over SVID con, SVID */
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 2, 2, 0, 0, 0 },
+ .pll = PLL_28,
.has_radio = 1,
- .tuner_type = TUNER_PHILIPS_PAL,
- /* sound routing:
- GPIO=0x00,0x01,0x03: mute (?)
- 0x02: both TV and radio (tuner: FM1216/I)
- The card has onboard audio connectors labeled "cdrom" and "board",
- not soldered here, though unknown wiring.
- Card lacks: external audio in, pci subsystem id.
- */
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
+/* sound routing:
+ GPIO=0x00,0x01,0x03: mute (?)
+ 0x02: both TV and radio (tuner: FM1216/I)
+ The card has onboard audio connectors labeled "cdrom" and "board",
+ not soldered here, though unknown wiring.
+ Card lacks: external audio in, pci subsystem id.
+*/
},{
/* ---- card 0x60 ---------------------------------- */
.name = "MachTV",
- .video_inputs = 3,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = -1,
- .gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
- .needs_tvaudio = 1,
- .tuner_type = 5,
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = -1,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0, 1, 2, 3, 4},
+ .needs_tvaudio = 1,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
.pll = 1,
},{
.name = "Euresys Picolo",
@@ -1686,6 +1786,8 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.muxsel = { 2, 0, 1},
.pll = PLL_28,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* Luc Van Hoeylandt <luc@e-magic.be> */
.name = "ProVideo PV150", /* 0x4f */
@@ -1699,7 +1801,8 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
},{
/* Hiroshi Takekawa <sian@big.or.jp> */
/* This card lacks subsystem ID */
@@ -1716,78 +1819,85 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 2,
+ .tuner_addr = ADDR_UNSET,
.audio_hook = adtvk503_audio,
},{
/* ---- card 0x64 ---------------------------------- */
- .name = "Hercules Smart TV Stereo",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 1 },
- .needs_tvaudio = 1,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = 5,
+ .name = "Hercules Smart TV Stereo",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x00,
+ .muxsel = { 2, 3, 1, 1 },
+ .needs_tvaudio = 1,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 5,
+ .tuner_addr = ADDR_UNSET,
/* Notes:
- - card lacks subsystem ID
- - stereo variant w/ daughter board with tda9874a @0xb0
- - Audio Routing:
+ - card lacks subsystem ID
+ - stereo variant w/ daughter board with tda9874a @0xb0
+ - Audio Routing:
always from tda9874 independent of GPIO (?)
external line in: unknown
- - Other chips: em78p156elp @ 0x96 (probably IR remote control)
- hef4053 (instead 4052) for unknown function
+ - Other chips: em78p156elp @ 0x96 (probably IR remote control)
+ hef4053 (instead 4052) for unknown function
*/
},{
- .name = "Pace TV & Radio Card",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 1}, // Tuner, CVid, SVid, CVid over SVid connector
- .gpiomask = 0,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = 1,
- .has_radio = 1,
- .pll = PLL_28,
- /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
- only internal line out: (4pin header) RGGL
- Radio must be decoded by msp3410d (not routed through)*/
- // .digital_mode = DIGITAL_MODE_CAMERA, // todo!
-},{
- /* Chris Willing <chris@vislab.usyd.edu.au> */
- .name = "IVC-200",
- .video_inputs = 1,
- .audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
- .svhs = -1,
- .gpiomask = 0xdf,
- .muxsel = { 2 },
- .pll = PLL_28,
+ .name = "Pace TV & Radio Card",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */
+ .gpiomask = 0,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = 1,
+ .tuner_addr = ADDR_UNSET,
+ .has_radio = 1,
+ .pll = PLL_28,
+ /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+ only internal line out: (4pin header) RGGL
+ Radio must be decoded by msp3410d (not routed through)*/
+ /*
+ .digital_mode = DIGITAL_MODE_CAMERA, todo!
+ */
+},{
+ /* Chris Willing <chris@vislab.usyd.edu.au> */
+ .name = "IVC-200",
+ .video_inputs = 1,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .svhs = -1,
+ .gpiomask = 0xdf,
+ .muxsel = { 2 },
+ .pll = PLL_28,
},{
.name = "Grand X-Guard / Trust 814PCI",
.video_inputs = 16,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
.tuner_type = 4,
- .gpiomask2 = 0xff,
+ .tuner_addr = ADDR_UNSET,
+ .gpiomask2 = 0xff,
.muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 },
.muxsel_hook = xguard_muxsel,
.no_msp34xx = 1,
.no_tda9875 = 1,
- .no_tda7432 = 1,
+ .no_tda7432 = 1,
.pll = PLL_28,
},{
/* ---- card 0x68 ---------------------------------- */
.name = "Nebula Electronics DigiTV",
.video_inputs = 1,
- .tuner = -1,
+ .tuner = -1,
.svhs = -1,
.muxsel = { 2, 3, 1, 0},
.no_msp34xx = 1,
@@ -1795,22 +1905,24 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
.no_gpioirq = 1,
},{
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
.name = "ProVideo PV143",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .gpiomask = 0,
- .muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
- .needs_tvaudio = 0,
- .no_msp34xx = 1,
- .pll = PLL_28,
- .tuner_type = -1,
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* M.Klahr@phytec.de */
.name = "PHYTEC VD-009-X1 MiniDIN (bt878)",
@@ -1824,6 +1936,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "PHYTEC VD-009-X1 Combi (bt878)",
.video_inputs = 4,
@@ -1836,6 +1949,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* ---- card 0x6c ---------------------------------- */
@@ -1846,13 +1960,14 @@ struct tvcard bttv_tvcards[] = {
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
- via the upper nibble of muxsel. here: used for
- xternal video-mux */
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
.name = "PHYTEC VD-009 Combi (bt878)",
.video_inputs = 10,
@@ -1861,23 +1976,25 @@ struct tvcard bttv_tvcards[] = {
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
- via the upper nibble of muxsel. here: used for
- xternal video-mux */
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
- .name = "IVC-100",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
- .svhs = -1,
- .gpiomask = 0xdf,
- .muxsel = { 2, 3, 1, 0 },
- .pll = PLL_28,
+ .name = "IVC-100",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .svhs = -1,
+ .gpiomask = 0xdf,
+ .muxsel = { 2, 3, 1, 0 },
+ .pll = PLL_28,
},{
/* IVC-120G - Alan Garfield <alan@fromorbit.com> */
.name = "IVC-120G",
@@ -1885,6 +2002,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0, /* card has no audio */
.tuner = -1, /* card has no tuner */
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1, /* card has no svhs */
.needs_tvaudio = 0,
.no_msp34xx = 1,
@@ -1892,7 +2010,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.gpiomask = 0x00,
.muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
.muxsel_hook = ivc120_muxsel,
.pll = PLL_28,
},{
@@ -1905,6 +2023,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1, 0},
.tuner_type = TUNER_PHILIPS_ATSC,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
},{
.name = "Twinhan DST + clones",
@@ -1912,19 +2031,21 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.no_tda7432 = 1,
.tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
.no_video = 1,
.has_dvb = 1,
},{
- .name = "Winfast VC100",
+ .name = "Winfast VC100",
.video_inputs = 3,
.audio_inputs = 0,
.svhs = 1,
- .tuner = -1, // no tuner
- .muxsel = { 3, 1, 1, 3}, // Vid In, SVid In, Vid over SVid in connector
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = TUNER_ABSENT,
+ .tuner = -1,
+ .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_28,
},{
.name = "Teppro TEV-560/InterVision IV-560",
@@ -1937,44 +2058,49 @@ struct tvcard bttv_tvcards[] = {
.audiomux = { 1, 1, 1, 1, 0},
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.pll = PLL_35,
},{
/* ---- card 0x74 ---------------------------------- */
- .name = "SIMUS GVC1100",
- .video_inputs = 4,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .tuner_type = -1,
- .pll = PLL_28,
- .muxsel = { 2, 2, 2, 2},
- .gpiomask = 0x3F,
+ .name = "SIMUS GVC1100",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .muxsel = { 2, 2, 2, 2},
+ .gpiomask = 0x3F,
.muxsel_hook = gvc1100_muxsel,
},{
- /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
- .name = "NGS NGSTV+",
- .video_inputs = 3,
- .tuner = 0,
- .svhs = 2,
- .gpiomask = 0x008007,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0, 0, 0, 0, 0x000003, 0},
- .pll = PLL_28,
- .tuner_type = TUNER_PHILIPS_PAL,
- .has_remote = 1,
-},{
- /* http://linuxmedialabs.com */
- .name = "LMLBT4",
- .video_inputs = 4, /* IN1,IN2,IN3,IN4 */
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .muxsel = { 2, 3, 1, 0 },
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .needs_tvaudio = 0,
+ /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
+ .name = "NGS NGSTV+",
+ .video_inputs = 3,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x008007,
+ .muxsel = {2, 3, 0, 0},
+ .audiomux = {0, 0, 0, 0, 0x000003, 0},
+ .pll = PLL_28,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
+ .has_remote = 1,
+},{
+ /* http://linuxmedialabs.com */
+ .name = "LMLBT4",
+ .video_inputs = 4, /* IN1,IN2,IN3,IN4 */
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .muxsel = { 2, 3, 1, 0 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .needs_tvaudio = 0,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Helmroos Harri <harri.helmroos@pp.inet.fi> */
.name = "Tekram M205 PRO",
@@ -1982,6 +2108,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.svhs = 2,
.needs_tvaudio = 0,
.gpiomask = 0x68,
@@ -2004,6 +2131,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1,
.has_radio = 1,
},{
@@ -2026,6 +2154,8 @@ struct tvcard bttv_tvcards[] = {
.pll = PLL_28,
.needs_tvaudio = 0,
.muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Spirit TV Tuner from http://spiritmodems.com.au */
/* Stafford Goodsell <surge@goliath.homeunix.org> */
@@ -2038,23 +2168,25 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 1, 1 },
.audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00},
.tuner_type = TUNER_TEMIC_PAL,
+ .tuner_addr = ADDR_UNSET,
.no_msp34xx = 1,
.no_tda9875 = 1,
},{
/* Wolfram Joost <wojo@frokaschwei.de> */
- .name = "AVerMedia AVerTV DVB-T 771",
- .video_inputs = 2,
- .svhs = 1,
- .tuner = -1,
- .tuner_type = TUNER_ABSENT,
- .muxsel = { 3 , 3 },
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .pll = PLL_28,
- .has_dvb = 1,
- .no_gpioirq = 1,
- .has_remote = 1,
+ .name = "AVerMedia AVerTV DVB-T 771",
+ .video_inputs = 2,
+ .svhs = 1,
+ .tuner = -1,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = ADDR_UNSET,
+ .muxsel = { 3 , 3 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .pll = PLL_28,
+ .has_dvb = 1,
+ .no_gpioirq = 1,
+ .has_remote = 1,
},{
/* ---- card 0x7c ---------------------------------- */
/* Matt Jesson <dvb@jesson.eclipse.co.uk> */
@@ -2069,6 +2201,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.has_dvb = 1,
.no_gpioirq = 1,
.has_remote = 1,
@@ -2081,12 +2214,13 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0x0,
.muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3 },
+ 3, 3, 3, 3, 3, 3, 3, 3 },
.muxsel_hook = sigmaSQ_muxsel,
.audiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* andre.schwarz@matrix-vision.de */
.name = "MATRIX Vision Sigma-SLC",
@@ -2101,6 +2235,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* BTTV_APAC_VIEWCOMP */
/* Attila Kondoros <attila.kondoros@chello.hu> */
@@ -2116,13 +2251,14 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
+ .tuner_addr = ADDR_UNSET,
.has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */
.has_radio = 1, /* not every card has radio */
},{
/* ---- card 0x80 ---------------------------------- */
/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
- .name = "DVICO FusionHDTV DVB-T Lite",
+ .name = "DViCO FusionHDTV DVB-T Lite",
.tuner = -1,
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -2131,6 +2267,7 @@ struct tvcard bttv_tvcards[] = {
.no_video = 1,
.has_dvb = 1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
},{
/* Steven <photon38@pchome.com.tw> */
.name = "V-Gear MyVCD",
@@ -2144,62 +2281,65 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
+ .tuner_addr = ADDR_UNSET,
.has_radio = 0,
- // .has_remote = 1,
},{
/* Rick C <cryptdragoon@gmail.com> */
- .name = "Super TV Tuner",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 0},
- .tuner_type = TUNER_PHILIPS_NTSC,
- .gpiomask = 0x008007,
- .audiomux = { 0, 0x000001,0,0, 0},
- .needs_tvaudio = 1,
- .has_radio = 1,
-},{
- /* Chris Fanning <video4linux@haydon.net> */
- .name = "Tibet Systems 'Progress DVR' CS16",
- .video_inputs = 16,
- .audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
- .pll = PLL_28,
- .no_msp34xx = 1,
- .no_tda9875 = 1,
- .no_tda7432 = 1,
- .tuner_type = -1,
- .muxsel_hook = tibetCS16_muxsel,
+ .name = "Super TV Tuner",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0},
+ .tuner_type = TUNER_PHILIPS_NTSC,
+ .tuner_addr = ADDR_UNSET,
+ .gpiomask = 0x008007,
+ .audiomux = { 0, 0x000001,0,0, 0},
+ .needs_tvaudio = 1,
+ .has_radio = 1,
+},{
+ /* Chris Fanning <video4linux@haydon.net> */
+ .name = "Tibet Systems 'Progress DVR' CS16",
+ .video_inputs = 16,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ .pll = PLL_28,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .muxsel_hook = tibetCS16_muxsel,
},
{
/* Bill Brack <wbrack@mmm.com.hk> */
/*
- * Note that, because of the card's wiring, the "master"
- * BT878A chip (i.e. the one which controls the analog switch
- * and must use this card type) is the 2nd one detected. The
- * other 3 chips should use card type 0x85, whose description
- * follows this one. There is a EEPROM on the card (which is
- * connected to the I2C of one of those other chips), but is
- * not currently handled. There is also a facility for a
- * "monitor", which is also not currently implemented.
- */
- .name = "Kodicom 4400R (master)",
+ * Note that, because of the card's wiring, the "master"
+ * BT878A chip (i.e. the one which controls the analog switch
+ * and must use this card type) is the 2nd one detected. The
+ * other 3 chips should use card type 0x85, whose description
+ * follows this one. There is a EEPROM on the card (which is
+ * connected to the I2C of one of those other chips), but is
+ * not currently handled. There is also a facility for a
+ * "monitor", which is also not currently implemented.
+ */
+ .name = "Kodicom 4400R (master)",
.video_inputs = 16,
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
/* GPIO bits 0-9 used for analog switch:
- * 00 - 03: camera selector
- * 04 - 06: channel (controller) selector
- * 07: data (1->on, 0->off)
- * 08: strobe
- * 09: reset
- * bit 16 is input from sync separator for the channel
- */
+ * 00 - 03: camera selector
+ * 04 - 06: channel (controller) selector
+ * 07: data (1->on, 0->off)
+ * 08: strobe
+ * 09: reset
+ * bit 16 is input from sync separator for the channel
+ */
.gpiomask = 0x0003ff,
.no_gpioirq = 1,
.muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
@@ -2212,15 +2352,16 @@ struct tvcard bttv_tvcards[] = {
{
/* Bill Brack <wbrack@mmm.com.hk> */
/* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
- * one which controls the analog switch, and must use the card type)
- * is the 2nd one detected. The other 3 chips should use this card
- * type
- */
+ * one which controls the analog switch, and must use the card type)
+ * is the 2nd one detected. The other 3 chips should use this card
+ * type
+ */
.name = "Kodicom 4400R (slave)",
.video_inputs = 16,
.audio_inputs = 0,
.tuner = -1,
.tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
.svhs = -1,
.gpiomask = 0x010000,
.no_gpioirq = 1,
@@ -2232,18 +2373,51 @@ struct tvcard bttv_tvcards[] = {
.muxsel_hook = kodicom4400r_muxsel,
},
{
- /* ---- card 0x85---------------------------------- */
- /* Michael Henson <mhenson@clarityvi.com> */
- /* Adlink RTV24 with special unlock codes */
- .name = "Adlink RTV24",
- .video_inputs = 4,
- .audio_inputs = 1,
- .tuner = 0,
- .svhs = 2,
- .muxsel = { 2, 3, 1, 0},
- .tuner_type = -1,
- .pll = PLL_28,
-
+ /* ---- card 0x86---------------------------------- */
+ /* Michael Henson <mhenson@clarityvi.com> */
+ /* Adlink RTV24 with special unlock codes */
+ .name = "Adlink RTV24",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0},
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .pll = PLL_28,
+},
+{
+ /* ---- card 0x87---------------------------------- */
+ /* Michael Krufky <mkrufky@m1k.net> */
+ .name = "DViCO FusionHDTV 5 Lite",
+ .tuner = 0,
+ .tuner_type = TUNER_LG_TDVS_H062F,
+ .tuner_addr = ADDR_UNSET,
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1 },
+ .gpiomask = 0x00e00007,
+ .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 },
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+},{
+ /* ---- card 0x88---------------------------------- */
+ /* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */
+ .name = "Acorp Y878F",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x01fe00,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = TUNER_YMEC_TVF66T5_B_DFF,
+ .tuner_addr = 0xc1 >>1,
+ .has_radio = 1,
}};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2355,32 +2529,32 @@ static void flyvideo_gpio(struct bttv *btv)
int tuner=-1,ttype;
gpio_inout(0xffffff, 0);
- udelay(8); // without this we would see the 0x1800 mask
+ udelay(8); /* without this we would see the 0x1800 mask */
gpio = gpio_read();
/* FIXME: must restore OUR_EN ??? */
- // all cards provide GPIO info, some have an additional eeprom
- // LR50: GPIO coding can be found lower right CP1 .. CP9
- // CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
- // GPIO14-12: n.c.
- // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-
- // lowest 3 bytes are remote control codes (no handshake needed)
- // xxxFFF: No remote control chip soldered
- // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
- // Note: Some bits are Audio_Mask !
+ /* all cards provide GPIO info, some have an additional eeprom
+ * LR50: GPIO coding can be found lower right CP1 .. CP9
+ * CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
+ * GPIO14-12: n.c.
+ * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
+ * lowest 3 bytes are remote control codes (no handshake needed)
+ * xxxFFF: No remote control chip soldered
+ * 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
+ case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
break;
- case 0x2: tuner=39;// LG NTSC (newer TAPC series) TAPC-H701P
+ case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
break;
- case 0x4: tuner=5; // Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216
+ case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
break;
- case 0x6: tuner=37; // LG PAL (newer TAPC series) TAPC-G702P
+ case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
break;
- case 0xC: tuner=3; // Philips SECAM(+PAL) FQ1216ME or FI1216MF
+ case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
@@ -2388,15 +2562,16 @@ static void flyvideo_gpio(struct bttv *btv)
has_remote = gpio & 0x800000;
has_radio = gpio & 0x400000;
- // unknown 0x200000;
- // unknown2 0x100000;
- is_capture_only = !(gpio & 0x008000); //GPIO15
+ /* unknown 0x200000;
+ * unknown2 0x100000; */
+ is_capture_only = !(gpio & 0x008000); /* GPIO15 */
has_tda9820_tda9821 = !(gpio & 0x004000);
- is_lr90 = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only)
- // gpio & 0x001000 // output bit for audio routing
+ is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
+ /*
+ * gpio & 0x001000 output bit for audio routing */
if(is_capture_only)
- tuner=4; // No tuner present
+ tuner=4; /* 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);
@@ -2404,15 +2579,15 @@ static void flyvideo_gpio(struct bttv *btv)
btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
is_capture_only?"yes":"no ");
- if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through
+ if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */
btv->tuner_type = tuner;
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
+ /* 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_hook = lt9415_audio;
- //todo: if(has_tda9874) btv->audio_hook = fv2000s_audio;
+ /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */
}
static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1,
@@ -2633,6 +2808,8 @@ void __devinit bttv_init_card1(struct bttv *btv)
void __devinit bttv_init_card2(struct bttv *btv)
{
int tda9887;
+ int addr=ADDR_UNSET;
+
btv->tuner_type = -1;
if (BTTV_UNKNOWN == btv->c.type) {
@@ -2773,9 +2950,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->pll.pll_current = -1;
/* tuner configuration (from card list / autodetect / insmod option) */
- if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
+ if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+ addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+ if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
if(UNSET == btv->tuner_type)
- btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
+ btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
if (UNSET != tuner[btv->c.nr])
btv->tuner_type = tuner[btv->c.nr];
printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type);
@@ -2787,7 +2967,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = btv->tuner_type;
- tun_setup.addr = ADDR_UNSET;
+ tun_setup.addr = addr;
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
}
@@ -2880,7 +3060,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&tv, eeprom_data);
+ tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
}
@@ -2902,7 +3082,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
btv->mbox_csel = 1 << 10;
freq=88000/62.5;
- tea5757_write(btv, 5 * freq + 0x358); // write 0x1ed8
+ tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
if (0x1ed8 == tea5757_read(btv)) {
printk("bttv%d: Terratec Active Radio Upgrade found.\n",
btv->c.nr);
@@ -3073,7 +3253,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
case 0x0060:
case 0x0070:
btv->c.type = BTTV_OSPREY2x0;
- //enable output on select control lines
+ /* enable output on select control lines */
gpio_inout(0xffffff,0x000303);
break;
default:
@@ -3105,7 +3285,7 @@ static int tuner_1_table[] = {
TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
- TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
+ TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
static void __devinit avermedia_eeprom(struct bttv *btv)
@@ -3126,7 +3306,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
if (tuner_make == 4)
if(tuner_format == 0x09)
- tuner = TUNER_LG_NTSC_NEW_TAPC; // TAPC-G702P
+ tuner = 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]);
@@ -3143,7 +3323,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
- // fix up our card entry
+ /* fix up our card entry */
if(norm==VIDEO_MODE_NTSC) {
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x957fff;
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x957fff;
@@ -3154,7 +3334,7 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm)
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x947fff;
dprintk("bttv_tda9880_setnorm to PAL\n");
}
- // set GPIO according
+ /* set GPIO according */
gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].audiomux[btv->audio]);
}
@@ -3447,7 +3627,7 @@ static int tea5757_read(struct bttv *btv)
udelay(10);
timeout= jiffies + HZ;
- // wait for DATA line to go low; error if it doesn't
+ /* wait for DATA line to go low; error if it doesn't */
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
schedule();
if (bus_in(btv,btv->mbox_data)) {
@@ -3574,8 +3754,8 @@ gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set)
con = 0x300;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x200;
-// if (v->mode & VIDEO_SOUND_MONO)
-// con = 0x100;
+/* if (v->mode & VIDEO_SOUND_MONO)
+ * con = 0x100; */
gpio_bits(0x300, con);
} else {
v->mode = VIDEO_SOUND_STEREO |
@@ -3718,7 +3898,7 @@ lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
}
}
-// TDA9821 on TerraTV+ Bt848, Bt878
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
static void
terratv_audio(struct bttv *btv, struct video_audio *v, int set)
{
@@ -3818,7 +3998,7 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
- val = 0x1080; //-dk-???: 0x0880, 0x0080, 0x1800 ...
+ val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
}
if (val != 0xffff) {
gpio_bits(0x1800, val);
@@ -3869,10 +4049,10 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0xffffff;
- //btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN);
+ /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
if (set) {
- //btor(***, BT848_GPIO_OUT_EN);
+ /* btor(***, BT848_GPIO_OUT_EN); */
if (v->mode & VIDEO_SOUND_LANG1)
con = 0x00000000;
if (v->mode & VIDEO_SOUND_LANG2)
@@ -4079,14 +4259,14 @@ static void kodicom4400r_init(struct bttv *btv)
master[btv->c.nr+2] = btv;
}
-// The Grandtec X-Guard framegrabber card uses two Dual 4-channel
-// video multiplexers to provide up to 16 video inputs. These
-// multiplexers are controlled by the lower 8 GPIO pins of the
-// bt878. The multiplexers probably Pericom PI5V331Q or similar.
-
-// xxx0 is pin xxx of multiplexer U5,
-// yyy1 is pin yyy of multiplexer U2
+/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+ * video multiplexers to provide up to 16 video inputs. These
+ * multiplexers are controlled by the lower 8 GPIO pins of the
+ * bt878. The multiplexers probably Pericom PI5V331Q or similar.
+ * xxx0 is pin xxx of multiplexer U5,
+ * yyy1 is pin yyy of multiplexer U2
+ */
#define ENA0 0x01
#define ENB0 0x02
#define ENA1 0x04
@@ -4157,14 +4337,14 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
static void ivc120_muxsel(struct bttv *btv, unsigned int input)
{
- // Simple maths
+ /* Simple maths */
int key = input % 4;
int matrix = input / 4;
dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
btv->c.nr, input, matrix, key);
- // Handles the input selection on the TDA8540's
+ /* Handles the input selection on the TDA8540's */
bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
((matrix == 3) ? (key | key << 2) : 0x00), 1);
bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
@@ -4174,17 +4354,17 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
((matrix == 2) ? (key | key << 2) : 0x00), 1);
- // Handles the output enables on the TDA8540's
+ /* Handles the output enables on the TDA8540's */
bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
- ((matrix == 3) ? 0x03 : 0x00), 1); // 13 - 16
+ ((matrix == 3) ? 0x03 : 0x00), 1); /* 13 - 16 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
- ((matrix == 0) ? 0x03 : 0x00), 1); // 1-4
+ ((matrix == 0) ? 0x03 : 0x00), 1); /* 1-4 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
- ((matrix == 1) ? 0x03 : 0x00), 1); // 5-8
+ ((matrix == 1) ? 0x03 : 0x00), 1); /* 5-8 */
bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
- ((matrix == 2) ? 0x03 : 0x00), 1); // 9-12
+ ((matrix == 2) ? 0x03 : 0x00), 1); /* 9-12 */
- // Selects MUX0 for input on the 878
+ /* Selects MUX0 for input on the 878 */
btaor((0)<<5, ~(3<<5), BT848_IFORM);
}
@@ -4296,9 +4476,11 @@ void __devinit bttv_check_chipset(void)
printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
if (pcipci_fail) {
printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
- if (UNSET == no_overlay) {
- printk(KERN_WARNING "bttv: going to disable overlay.\n");
+ if (!no_overlay) {
+ printk(KERN_WARNING "bttv: overlay will be disabled.\n");
no_overlay = 1;
+ } else {
+ printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n");
}
}
if (UNSET != latency)
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 67f331eeeb19..c062a017491e 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-driver.c,v 1.45 2005/07/20 19:43:24 mkrufky Exp $
bttv - Bt848 frame grabber driver
@@ -42,6 +41,9 @@
#include "bttvp.h"
+#include "rds.h"
+
+
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
@@ -80,6 +82,7 @@ static unsigned int irq_iswitch = 0;
static unsigned int uv_ratio = 50;
static unsigned int full_luma_range = 0;
static unsigned int coring = 0;
+extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
@@ -760,21 +763,21 @@ static void set_pll(struct bttv *btv)
/* no PLL needed */
if (btv->pll.pll_current == 0)
return;
- vprintk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
- btv->c.nr,btv->pll.pll_ifreq);
+ bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
+ btv->c.nr,btv->pll.pll_ifreq);
btwrite(0x00,BT848_TGCTRL);
btwrite(0x00,BT848_PLL_XCI);
btv->pll.pll_current = 0;
return;
}
- vprintk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
- btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+ bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
+ btv->pll.pll_ifreq, btv->pll.pll_ofreq);
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
for (i=0; i<10; i++) {
/* Let other people run while the PLL stabilizes */
- vprintk(".");
+ bttv_printk(".");
msleep(10);
if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -782,12 +785,12 @@ static void set_pll(struct bttv *btv)
} else {
btwrite(0x08,BT848_TGCTRL);
btv->pll.pll_current = btv->pll.pll_ofreq;
- vprintk(" ok\n");
+ bttv_printk(" ok\n");
return;
}
}
btv->pll.pll_current = -1;
- vprintk("failed\n");
+ bttv_printk("failed\n");
return;
}
@@ -2151,6 +2154,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (no_overlay > 0) {
+ printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ return -EINVAL;
+ }
return setup_window(fh, btv, &f->fmt.win, 1);
case V4L2_BUF_TYPE_VBI_CAPTURE:
retval = bttv_switch_type(fh,f->type);
@@ -2224,9 +2231,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
/* others */
cap->type = VID_TYPE_CAPTURE|
VID_TYPE_TUNER|
- VID_TYPE_OVERLAY|
VID_TYPE_CLIPPING|
VID_TYPE_SCALES;
+ if (no_overlay <= 0)
+ cap->type |= VID_TYPE_OVERLAY;
+
cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
cap->minwidth = 48;
@@ -2302,6 +2311,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
struct video_window *win = arg;
struct v4l2_window w2;
+ if (no_overlay > 0) {
+ printk ("VIDIOCSWIN: no_overlay\n");
+ return -EINVAL;
+ }
+
w2.field = V4L2_FIELD_ANY;
w2.w.left = win->x;
w2.w.top = win->y;
@@ -2577,10 +2591,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
cap->version = BTTV_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
+ if (no_overlay <= 0)
+ cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
if (bttv_tvcards[btv->c.type].tuner != UNSET &&
bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
@@ -3076,7 +3092,7 @@ static struct file_operations bttv_fops =
static struct video_device bttv_video_template =
{
.name = "UNSET",
- .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
+ .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.hardware = VID_HARDWARE_BT848,
.fops = &bttv_fops,
@@ -3114,15 +3130,12 @@ static int radio_open(struct inode *inode, struct file *file)
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
down(&btv->lock);
- if (btv->radio_user) {
- up(&btv->lock);
- return -EBUSY;
- }
+
btv->radio_user++;
+
file->private_data = btv;
- i2c_vidiocschan(btv);
- bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
+ bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
audio_mux(btv,AUDIO_RADIO);
up(&btv->lock);
@@ -3131,9 +3144,13 @@ static int radio_open(struct inode *inode, struct file *file)
static int radio_release(struct inode *inode, struct file *file)
{
- struct bttv *btv = file->private_data;
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
btv->radio_user--;
+
+ bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+
return 0;
}
@@ -3189,13 +3206,42 @@ static int radio_ioctl(struct inode *inode, struct file *file,
return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
}
+static ssize_t radio_read(struct file *file, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
+ cmd.block_count = count/3;
+ cmd.buffer = data;
+ cmd.instance = file;
+ cmd.result = -ENODEV;
+
+ bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
+
+ return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+ struct bttv *btv = file->private_data;
+ struct rds_command cmd;
+ cmd.instance = file;
+ cmd.event_list = wait;
+ cmd.result = -ENODEV;
+ bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
+
+ return cmd.result;
+}
+
static struct file_operations radio_fops =
{
.owner = THIS_MODULE,
.open = radio_open,
+ .read = radio_read,
.release = radio_release,
.ioctl = radio_ioctl,
.llseek = no_llseek,
+ .poll = radio_poll,
};
static struct video_device radio_template =
@@ -3756,6 +3802,12 @@ static void bttv_unregister_video(struct bttv *btv)
/* register video4linux devices */
static int __devinit bttv_register_video(struct bttv *btv)
{
+ if (no_overlay <= 0) {
+ bttv_video_template.type |= VID_TYPE_OVERLAY;
+ } else {
+ printk("bttv: Overlay support disabled.\n");
+ }
+
/* video */
btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
if (NULL == btv->video_dev)
@@ -4027,7 +4079,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
struct bttv_buffer_set idle;
unsigned long flags;
- dprintk("bttv%d: suspend %d\n", btv->c.nr, state);
+ dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4060,15 +4112,29 @@ static int bttv_resume(struct pci_dev *pci_dev)
{
struct bttv *btv = pci_get_drvdata(pci_dev);
unsigned long flags;
+ int err;
dprintk("bttv%d: resume\n", btv->c.nr);
/* restore pci state */
if (btv->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+ btv->c.nr);
+ return err;
+ }
btv->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err=pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ pci_disable_device(pci_dev);
+ printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+ btv->c.nr);
+ btv->state.disabled = 1;
+ return err;
+ }
+
pci_restore_state(pci_dev);
/* restore bt878 state */
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index 77320cdf205f..6b280c03e398 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-gpio.c,v 1.7 2005/02/16 12:14:10 kraxel Exp $
bttv-gpio.c -- gpio sub drivers
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 234a85563769..e684df37eb0e 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-i2c.c,v 1.25 2005/07/05 17:37:35 nsh Exp $
bttv-i2c.c -- all the i2c code is here
@@ -109,7 +108,7 @@ static struct i2c_adapter bttv_i2c_adap_sw_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("bt848"),
+ .name = "bt848",
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
@@ -270,8 +269,6 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int
}
static struct i2c_algorithm bttv_algo = {
- .name = "bt878",
- .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.master_xfer = bttv_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
@@ -282,8 +279,8 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("bt878"),
- .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
+ .name = "bt878",
+ .id = I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
.client_register = attach_inform,
};
@@ -298,7 +295,7 @@ static int attach_inform(struct i2c_client *client)
if (bttv_debug)
printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
btv->c.nr,client->driver->name,client->addr,
- i2c_clientname(client));
+ client->name);
if (!client->driver->command)
return 0;
@@ -326,7 +323,7 @@ void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
}
static struct i2c_client bttv_i2c_client_template = {
- I2C_DEVNAME("bttv internal"),
+ .name = "bttv internal",
};
@@ -383,6 +380,7 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
}
static char *i2c_devs[128] = {
+ [ 0x1c >> 1 ] = "lgdt330x",
[ 0x30 >> 1 ] = "IR (hauppauge)",
[ 0x80 >> 1 ] = "msp34xx",
[ 0x86 >> 1 ] = "tda9887",
diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c
index f7b5543a96a1..e8aada772b89 100644
--- a/drivers/media/video/bttv-if.c
+++ b/drivers/media/video/bttv-if.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-if.c,v 1.4 2004/11/17 18:47:47 kraxel Exp $
bttv-if.c -- old gpio interface to other kernel modules
don't use in new code, will go away in 2.7
diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
index 9ed21fd190c6..a5ed99b89445 100644
--- a/drivers/media/video/bttv-risc.c
+++ b/drivers/media/video/bttv-risc.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-risc.c,v 1.10 2004/11/19 18:07:12 kraxel Exp $
bttv-risc.c -- interfaces to other kernel modules
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
index 06f3e62b3e8d..f4f58c60f152 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bttv-vbi.c
@@ -1,5 +1,4 @@
/*
- $Id: bttv-vbi.c,v 1.9 2005/01/13 17:22:33 kraxel Exp $
bttv - Bt848 frame grabber driver
vbi interface
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index f2af9e1454f0..d254e90e3bb9 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,4 @@
/*
- * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $
*
* bttv - Bt848 frame grabber driver
*
@@ -218,6 +217,8 @@ struct tvcard
#define PLL_35 2
unsigned int tuner_type;
+ unsigned int tuner_addr;
+
unsigned int has_radio;
void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index aab094bc243d..e0e7c7a84bc5 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -1,5 +1,4 @@
/*
- $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $
bttv - Bt848 frame grabber driver
@@ -222,7 +221,7 @@ extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
extern int init_bttv_i2c(struct bttv *btv);
extern int fini_bttv_i2c(struct bttv *btv);
-#define vprintk if (bttv_verbose) printk
+#define bttv_printk if (bttv_verbose) printk
#define dprintk if (bttv_debug >= 1) printk
#define d2printk if (bttv_debug >= 2) printk
@@ -241,7 +240,7 @@ struct bttv_pll_info {
/* for gpio-connected remote control */
struct bttv_input {
- struct input_dev dev;
+ struct input_dev *dev;
struct ir_input_state ir;
char name[32];
char phys[32];
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 8c08b7f1ad23..b7ec9bf45085 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -1397,7 +1397,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam)
static void proc_cpia_create(void)
{
- cpia_proc_root = create_proc_entry("cpia", S_IFDIR, NULL);
+ cpia_proc_root = proc_mkdir("cpia", NULL);
if (cpia_proc_root)
cpia_proc_root->owner = THIS_MODULE;
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index cdda423386c5..9774e94d1e7d 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -445,10 +445,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
ucpia->sbuf[1].urb = NULL;
}
- if (ucpia->sbuf[1].data) {
- kfree(ucpia->sbuf[1].data);
- ucpia->sbuf[1].data = NULL;
- }
+ kfree(ucpia->sbuf[1].data);
+ ucpia->sbuf[1].data = NULL;
if (ucpia->sbuf[0].urb) {
usb_kill_urb(ucpia->sbuf[0].urb);
@@ -456,10 +454,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
ucpia->sbuf[0].urb = NULL;
}
- if (ucpia->sbuf[0].data) {
- kfree(ucpia->sbuf[0].data);
- ucpia->sbuf[0].data = NULL;
- }
+ kfree(ucpia->sbuf[0].data);
+ ucpia->sbuf[0].data = NULL;
}
static int cpia_usb_close(void *privdata)
@@ -623,20 +619,14 @@ static void cpia_disconnect(struct usb_interface *intf)
ucpia->curbuff = ucpia->workbuff = NULL;
- if (ucpia->buffers[2]) {
- vfree(ucpia->buffers[2]);
- ucpia->buffers[2] = NULL;
- }
+ vfree(ucpia->buffers[2]);
+ ucpia->buffers[2] = NULL;
- if (ucpia->buffers[1]) {
- vfree(ucpia->buffers[1]);
- ucpia->buffers[1] = NULL;
- }
+ vfree(ucpia->buffers[1]);
+ ucpia->buffers[1] = NULL;
- if (ucpia->buffers[0]) {
- vfree(ucpia->buffers[0]);
- ucpia->buffers[0] = NULL;
- }
+ vfree(ucpia->buffers[0]);
+ ucpia->buffers[0] = NULL;
cam->lowlevel_data = NULL;
kfree(ucpia);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 4f39688f780a..0c0c59e94774 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -62,7 +61,6 @@ static LIST_HEAD(cx8802_devlist);
#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
/* Firmware API commands */
-/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
#define IVTV_API_STD_TIMEOUT 500
#define BLACKBIRD_API_PING 0x80
@@ -696,7 +694,6 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
/* assign stream type */
blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
- /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
/* assign output port */
blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
@@ -824,7 +821,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
+ /* initialize the video input */
+ blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0);
msleep(1);
@@ -833,11 +831,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
msleep(1);
- /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
+ /* start capturing to the host interface */
+ /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */
blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE
- ); /* start capturing to the host interface */
+ );
msleep(10);
blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
@@ -851,8 +850,8 @@ static int bb_buf_setup(struct videobuf_queue *q,
{
struct cx8802_fh *fh = q->priv_data;
- fh->dev->ts_packet_size = 512;
- fh->dev->ts_packet_count = 100;
+ fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
+ fh->dev->ts_packet_count = 32; /* was: 100 */
*size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
if (0 == *count)
@@ -900,12 +899,36 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
{
struct cx8802_fh *fh = file->private_data;
struct cx8802_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
if (debug > 1)
- cx88_print_ioctl(dev->core->name,cmd);
+ cx88_print_ioctl(core->name,cmd);
switch (cmd) {
+ /* --- capabilities ------------------------------------------ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap,0,sizeof(*cap));
+ strcpy(cap->driver, "cx88_blackbird");
+ strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+ sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+ cap->version = CX88_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
+ 0;
+ if (UNSET != core->tuner_type)
+ cap->capabilities |= V4L2_CAP_TUNER;
+
+ return 0;
+ }
+
/* --- capture ioctls ---------------------------------------- */
case VIDIOC_ENUM_FMT:
{
@@ -935,7 +958,11 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage = 188 * 4 * 1024; /* 1024 * 512 */ /* FIXME: BUFFER_SIZE */;
+ f->fmt.pix.colorspace = 0;
+ return 0;
}
/* --- streaming capture ------------------------------------- */
@@ -959,15 +986,25 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
return videobuf_streamoff(&fh->mpegq);
default:
- return -EINVAL;
+ return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
}
return 0;
}
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
+static unsigned int mpeg_translate_ioctl(unsigned int cmd)
+{
+ return cmd;
+}
+
static int mpeg_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+ cmd = cx88_ioctl_translator( cmd );
+ return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
}
static int mpeg_open(struct inode *inode, struct file *file)
@@ -1135,7 +1172,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
dev->pci = pci_dev;
dev->core = core;
dev->width = 720;
- dev->height = 480;
+ dev->height = 576;
err = cx8802_init_common(dev);
if (0 != err)
@@ -1148,6 +1185,9 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
list_add_tail(&dev->devlist,&cx8802_devlist);
blackbird_register_video(dev);
+
+ /* initial device configuration: needed ? */
+
return 0;
fail_free:
@@ -1202,6 +1242,8 @@ static int blackbird_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
+ cx88_ioctl_hook = mpeg_do_ioctl;
+ cx88_ioctl_translator = mpeg_translate_ioctl;
return pci_register_driver(&blackbird_pci_driver);
}
@@ -1213,6 +1255,9 @@ static void blackbird_fini(void)
module_init(blackbird_init);
module_exit(blackbird_fini);
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index ebf02a7f81e8..4da91d535a5b 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -499,9 +498,6 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
- },{
- .type = CX88_VMUX_SVIDEO,
- .vmux = 2,
}},
.dvb = 1,
},
@@ -614,12 +610,12 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0xed12, // internal decoder
+ .gpio0 = 0xed12, /* internal decoder */
.gpio2 = 0x00ff,
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
- .gpio0 = 0xff01, // mono from tuner chip
+ .gpio0 = 0xff01, /* mono from tuner chip */
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -715,19 +711,18 @@ struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0f0d,
+ .gpio0 = 0x97ed,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x97e9,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x97e9,
}},
.dvb = 1,
},
@@ -765,20 +760,21 @@ struct cx88_board cx88_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0f0d,
+ .gpio0 = 0x87fd,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x87f9,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0x0f00,
+ .gpio0 = 0x87f9,
}},
+ .dvb = 1,
},
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -949,7 +945,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&tv, eeprom_data);
+ tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
core->tuner_type = tv.tuner_type;
core->has_radio = tv.has_radio;
}
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 5e868f5cd0c0..dc5c5c1f3461 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-core.c,v 1.33 2005/07/07 14:17:47 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
@@ -876,7 +875,7 @@ static int set_tvaudio(struct cx88_core *core)
cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
cx88_set_tvaudio(core);
- // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
+ /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
@@ -1087,10 +1086,17 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
core->pci_irqmask = 0x00fc00;
+ init_MUTEX(&core->lock);
core->nr = cx88_devcount++;
sprintf(core->name,"cx88[%d]",core->nr);
if (0 != get_ressources(core,pci)) {
+ printk(KERN_ERR "CORE %s No more PCI ressources for "
+ "subsystem: %04x:%04x, board: %s\n",
+ core->name,pci->subsystem_vendor,
+ pci->subsystem_device,
+ cx88_boards[core->board].name);
+
cx88_devcount--;
goto fail_free;
}
@@ -1114,11 +1120,11 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
core->board = CX88_BOARD_UNKNOWN;
cx88_card_list(core,pci);
}
- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
- core->name,pci->subsystem_vendor,
- pci->subsystem_device,cx88_boards[core->board].name,
- core->board, card[core->nr] == core->board ?
- "insmod option" : "autodetected");
+ printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ core->name,pci->subsystem_vendor,
+ pci->subsystem_device,cx88_boards[core->board].name,
+ core->board, card[core->nr] == core->board ?
+ "insmod option" : "autodetected");
core->tuner_type = tuner[core->nr];
core->radio_type = radio[core->nr];
@@ -1202,4 +1208,5 @@ EXPORT_SYMBOL(cx88_core_put);
* 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/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index ef0e9a85c359..4334744652de 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
@@ -29,7 +28,7 @@
#include <linux/kthread.h>
#include <linux/file.h>
#include <linux/suspend.h>
-#include <linux/config.h>
+
#include "cx88.h"
#include "dvb-pll.h"
@@ -208,14 +207,41 @@ static struct or51132_config pchdtv_hd3000 = {
#ifdef HAVE_LGDT330X
static int lgdt330x_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
- u8* pllbuf)
+ struct dvb_frontend_parameters* params)
{
+ /* FIXME make this routine use the tuner-simple code.
+ * It could probably be shared with a number of ATSC
+ * frontends. Many share the same tuner with analog TV. */
+
struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
+ u8 buf[4];
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
+ int err;
- pllbuf[0] = dev->core->pll_addr;
- dvb_pll_configure(dev->core->pll_desc, &pllbuf[1],
- params->frequency, 0);
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
+ dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
+ dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+ if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "cx88-dvb: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+ if (core->tuner_type == TUNER_LG_TDVS_H062F) {
+ /* Set the Auxiliary Byte. */
+ buf[2] &= ~0x20;
+ buf[2] |= 0x18;
+ buf[3] = 0x50;
+ i2c_transfer(&core->i2c_adap, &msg, 1);
+ }
return 0;
}
@@ -244,6 +270,16 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
static struct lgdt330x_config fusionhdtv_3_gold = {
.demod_address = 0x0e,
+ .demod_chip = LGDT3302,
+ .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
+ .pll_set = lgdt330x_pll_set,
+ .set_ts_params = lgdt330x_set_ts_param,
+};
+
+static struct lgdt330x_config fusionhdtv_5_gold = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
.pll_set = lgdt330x_pll_set,
.set_ts_params = lgdt330x_set_ts_param,
};
@@ -332,6 +368,22 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
}
break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+ dev->ts_gen_cntrl = 0x08;
+ {
+ /* Do a hardware reset of chip before using it. */
+ struct cx88_core *core = dev->core;
+
+ cx_clear(MO_GP0_IO, 1);
+ mdelay(100);
+ cx_set(MO_GP0_IO, 1);
+ mdelay(200);
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
+ dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
+ &dev->core->i2c_adap);
+ }
+ break;
#endif
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
@@ -348,10 +400,8 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
}
- /* Copy the board name into the DVB structure */
- strlcpy(dev->dvb.frontend->ops->info.name,
- cx88_boards[dev->core->board].name,
- sizeof(dev->dvb.frontend->ops->info.name));
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
/* register everything */
return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index a628a55299c6..761cebd40dbd 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,4 @@
/*
- $Id: cx88-i2c.c,v 1.30 2005/07/25 05:10:13 mkrufky Exp $
cx88-i2c.c -- all the i2c code is here
@@ -95,7 +94,7 @@ static int attach_inform(struct i2c_client *client)
struct cx88_core *core = i2c_get_adapdata(client->adapter);
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name,client->addr,i2c_clientname(client));
+ client->driver->name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -128,7 +127,7 @@ static int detach_inform(struct i2c_client *client)
{
struct cx88_core *core = i2c_get_adapdata(client->adapter);
- dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client));
+ dprintk(1, "i2c detach [client=%s]\n", client->name);
return 0;
}
@@ -152,7 +151,7 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
/* ----------------------------------------------------------------------- */
static struct i2c_adapter cx8800_i2c_adap_template = {
- I2C_DEVNAME("cx2388x"),
+ .name = "cx2388x",
.owner = THIS_MODULE,
.id = I2C_HW_B_CX2388x,
.client_register = attach_inform,
@@ -160,7 +159,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = {
};
static struct i2c_client cx8800_i2c_client_template = {
- I2C_DEVNAME("cx88xx internal"),
+ .name = "cx88xx internal",
};
static char *i2c_devs[128] = {
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 214887798192..c27fe4c36f69 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-input.c,v 1.15 2005/07/07 13:58:38 mchehab Exp $
*
* Device driver for GPIO attached remote control interfaces
* on Conexant 2388x based TV/DVB cards.
@@ -212,9 +211,56 @@ static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
+/* Cinergy 1400 DVB-T */
+static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
+ [0x01] = KEY_POWER,
+ [0x02] = KEY_1,
+ [0x03] = KEY_2,
+ [0x04] = KEY_3,
+ [0x05] = KEY_4,
+ [0x06] = KEY_5,
+ [0x07] = KEY_6,
+ [0x08] = KEY_7,
+ [0x09] = KEY_8,
+ [0x0a] = KEY_9,
+ [0x0c] = KEY_0,
+
+ [0x0b] = KEY_VIDEO,
+ [0x0d] = KEY_REFRESH,
+ [0x0e] = KEY_SELECT,
+ [0x0f] = KEY_EPG,
+ [0x10] = KEY_UP,
+ [0x11] = KEY_LEFT,
+ [0x12] = KEY_OK,
+ [0x13] = KEY_RIGHT,
+ [0x14] = KEY_DOWN,
+ [0x15] = KEY_TEXT,
+ [0x16] = KEY_INFO,
+
+ [0x17] = KEY_RED,
+ [0x18] = KEY_GREEN,
+ [0x19] = KEY_YELLOW,
+ [0x1a] = KEY_BLUE,
+
+ [0x1b] = KEY_CHANNELUP,
+ [0x1c] = KEY_VOLUMEUP,
+ [0x1d] = KEY_MUTE,
+ [0x1e] = KEY_VOLUMEDOWN,
+ [0x1f] = KEY_CHANNELDOWN,
+
+ [0x40] = KEY_PAUSE,
+ [0x4c] = KEY_PLAY,
+ [0x58] = KEY_RECORD,
+ [0x54] = KEY_PREVIOUS,
+ [0x48] = KEY_STOP,
+ [0x5c] = KEY_NEXT,
+};
+
+/* ---------------------------------------------------------------------- */
+
struct cx88_IR {
struct cx88_core *core;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
char name[32];
char phys[32];
@@ -241,7 +287,7 @@ module_param(ir_debug, int, 0644); /* debug level [IR] */
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define ir_dprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
+ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
/* ---------------------------------------------------------------------- */
@@ -269,23 +315,23 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown) {
- ir_input_keydown(&ir->input, &ir->ir, data, data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup)) {
- ir_input_keydown(&ir->input, &ir->ir, data, data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else {
/* can't distinguish keydown/up :-/ */
- ir_input_keydown(&ir->input, &ir->ir, data, data);
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
+ ir_input_nokey(ir->input, &ir->ir);
}
}
@@ -311,13 +357,19 @@ static void cx88_ir_work(void *data)
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
struct cx88_IR *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
- ir = kmalloc(sizeof(*ir), GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir, 0, sizeof(*ir));
+ }
+
+ ir->input = input_dev;
/* detect & configure */
switch (core->board) {
@@ -329,6 +381,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keyup = 0x60;
ir->polling = 50; /* ms */
break;
+ case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ ir_codes = ir_codes_cinergy_1400;
+ ir_type = IR_TYPE_PD;
+ ir->sampling = 1;
+ break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
ir_codes = ir_codes_hauppauge_new;
@@ -374,6 +431,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
if (NULL == ir_codes) {
kfree(ir);
+ input_free_device(input_dev);
return -ENODEV;
}
@@ -382,18 +440,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
cx88_boards[core->board].name);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
- ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
- ir->input.name = ir->name;
- ir->input.phys = ir->phys;
- ir->input.id.bustype = BUS_PCI;
- ir->input.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (pci->subsystem_vendor) {
- ir->input.id.vendor = pci->subsystem_vendor;
- ir->input.id.product = pci->subsystem_device;
+ input_dev->id.vendor = pci->subsystem_vendor;
+ input_dev->id.product = pci->subsystem_device;
} else {
- ir->input.id.vendor = pci->vendor;
- ir->input.id.product = pci->device;
+ input_dev->id.vendor = pci->vendor;
+ input_dev->id.product = pci->device;
}
+ input_dev->cdev.dev = &pci->dev;
/* record handles to ourself */
ir->core = core;
@@ -413,8 +472,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
}
/* all done */
- input_register_device(&ir->input);
- printk("%s: registered IR remote control\n", core->name);
+ input_register_device(ir->input);
return 0;
}
@@ -432,7 +490,7 @@ int cx88_ir_fini(struct cx88_core *core)
flush_scheduled_work();
}
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
kfree(ir);
/* done */
@@ -445,7 +503,7 @@ int cx88_ir_fini(struct cx88_core *core)
void cx88_ir_irq(struct cx88_core *core)
{
struct cx88_IR *ir = core->ir;
- u32 samples, rc5;
+ u32 samples, ircode;
int i;
if (NULL == ir)
@@ -463,7 +521,7 @@ void cx88_ir_irq(struct cx88_core *core)
if (!ir->scount) {
/* nothing to sample */
if (ir->ir.keypressed && time_after(jiffies, ir->release))
- ir_input_nokey(&ir->input, &ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
return;
}
@@ -477,13 +535,44 @@ void cx88_ir_irq(struct cx88_core *core)
/* decode it */
switch (core->board) {
+ case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
+
+ if (ircode == 0xffffffff) { /* decoding error */
+ ir_dprintk("pulse distance decoding error\n");
+ break;
+ }
+
+ ir_dprintk("pulse distance decoded: %x\n", ircode);
+
+ if (ircode == 0) { /* key still pressed */
+ ir_dprintk("pulse distance decoded repeat code\n");
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
+ }
+
+ if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+ ir_dprintk("pulse distance decoded wrong address\n");
+ break;
+ }
+
+ if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
+ ir_dprintk("pulse distance decoded wrong check sum\n");
+ break;
+ }
+
+ ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);
+
+ ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
- rc5 = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
- ir_dprintk("biphase decoded: %x\n", rc5);
- if ((rc5 & 0xfffff000) != 0x3000)
+ ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+ ir_dprintk("biphase decoded: %x\n", ircode);
+ if ((ircode & 0xfffff000) != 0x3000)
break;
- ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
+ ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode);
ir->release = jiffies + msecs_to_jiffies(120);
break;
}
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index fe2767c0ff94..ee2300e1ae0b 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-mpeg.c,v 1.31 2005/07/07 14:17:47 mchehab Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
@@ -73,11 +72,15 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
udelay(100);
cx_write(MO_PINMUX_IO, 0x00);
cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
- if ((core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q) ||
- (core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T)) {
+ switch (core->board) {
+ case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+ case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
cx_write(TS_SOP_STAT, 1<<13);
- } else {
+ break;
+ default:
cx_write(TS_SOP_STAT, 0x00);
+ break;
}
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
udelay(100);
@@ -86,12 +89,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
if (cx88_boards[core->board].blackbird) {
cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
- // cx_write(TS_F2_CMD_STAT_MM, 0x2900106); /* F2_CMD_STAT_MM defaults + master + memory space */
cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
udelay(100);
cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
- //cx_write(TS_HW_SOP_CNTRL, 0x2F0BC0); /* mpeg start byte ts: 0x2F0BC0 ? */
cx_write(TS_VALERR_CNTRL, 0x2000);
cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
@@ -106,7 +107,6 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
dprintk( 0, "setting the interrupt mask\n" );
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
cx_set(MO_TS_INTMSK, 0x1f0011);
- //cx_write(MO_TS_INTMSK, 0x0f0011);
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
@@ -206,7 +206,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(0,"[%p/%d] %s - first active\n",
buf, buf->vb.i, __FUNCTION__);
- //udelay(100);
} else {
dprintk( 1, "queue is not empty - append to active\n" );
@@ -217,7 +216,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __FUNCTION__);
- //udelay(100);
}
}
@@ -387,7 +385,6 @@ int cx8802_init_common(struct cx8802_dev *dev)
dev->pci_lat,pci_resource_start(dev->pci,0));
/* initialize driver struct */
- init_MUTEX(&dev->lock);
spin_lock_init(&dev->slock);
/* init dma queue */
@@ -458,14 +455,28 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
int cx8802_resume_common(struct pci_dev *pci_dev)
{
- struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
+ int err;
if (dev->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ dev->core->name);
+ return err;
+ }
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err=pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ dev->core->name);
+ pci_disable_device(pci_dev);
+ dev->state.disabled = 1;
+
+ return err;
+ }
pci_restore_state(pci_dev);
/* FIXME: re-initialize hardware */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index 37f82662d265..0a3a62fc9bbb 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -1,5 +1,4 @@
/*
- $Id: cx88-reg.h,v 1.8 2005/07/07 13:58:38 mchehab Exp $
cx88x-hw.h - CX2388x register offsets
@@ -40,6 +39,29 @@
#define CX88X_EN_TBFX 0x02
#define CX88X_EN_VSFX 0x04
+/* ---------------------------------------------------------------------- */
+/* PCI controller registers */
+
+/* Command and Status Register */
+#define F0_CMD_STAT_MM 0x2f0004
+#define F1_CMD_STAT_MM 0x2f0104
+#define F2_CMD_STAT_MM 0x2f0204
+#define F3_CMD_STAT_MM 0x2f0304
+#define F4_CMD_STAT_MM 0x2f0404
+
+/* Device Control #1 */
+#define F0_DEV_CNTRL1_MM 0x2f0040
+#define F1_DEV_CNTRL1_MM 0x2f0140
+#define F2_DEV_CNTRL1_MM 0x2f0240
+#define F3_DEV_CNTRL1_MM 0x2f0340
+#define F4_DEV_CNTRL1_MM 0x2f0440
+
+/* Device Control #1 */
+#define F0_BAR0_MM 0x2f0010
+#define F1_BAR0_MM 0x2f0110
+#define F2_BAR0_MM 0x2f0210
+#define F3_BAR0_MM 0x2f0310
+#define F4_BAR0_MM 0x2f0410
/* ---------------------------------------------------------------------- */
/* DMA Controller registers */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 91207f10bae7..2765acee0285 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,4 @@
/*
- $Id: cx88-tvaudio.c,v 1.37 2005/07/07 13:58:38 mchehab Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
@@ -121,25 +120,19 @@ static void set_audio_registers(struct cx88_core *core,
}
static void set_audio_start(struct cx88_core *core,
- u32 mode, u32 ctl)
+ u32 mode)
{
// mute
cx_write(AUD_VOL_CTL, (1 << 6));
- // increase level of input by 12dB
-// cx_write(AUD_AFE_12DB_EN, 0x0001);
- cx_write(AUD_AFE_12DB_EN, 0x0000);
-
// start programming
cx_write(AUD_CTL, 0x0000);
cx_write(AUD_INIT, mode);
cx_write(AUD_INIT_LD, 0x0001);
cx_write(AUD_SOFT_RESET, 0x0001);
-
- cx_write(AUD_CTL, ctl);
}
-static void set_audio_finish(struct cx88_core *core)
+static void set_audio_finish(struct cx88_core *core, u32 ctl)
{
u32 volume;
@@ -154,25 +147,25 @@ static void set_audio_finish(struct cx88_core *core)
cx_write(AUD_I2SOUTPUTCNTL, 1);
cx_write(AUD_I2SCNTL, 0);
//cx_write(AUD_APB_IN_RATE_ADJ, 0);
+ } else {
+ ctl |= EN_DAC_ENABLE;
+ cx_write(AUD_CTL, ctl);
}
- // finish programming
+ /* finish programming */
cx_write(AUD_SOFT_RESET, 0x0000);
- // start audio processing
- cx_set(AUD_CTL, EN_DAC_ENABLE);
-
- // unmute
+ /* unmute */
volume = cx_sread(SHADOW_AUD_VOL_CTL);
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
}
/* ----------------------------------------------------------- */
-static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
+static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u32 mode)
{
static const struct rlist btsc[] = {
- /* from dscaler */
+ { AUD_AFE_12DB_EN, 0x00000001 },
{ AUD_OUT1_SEL, 0x00000013 },
{ AUD_OUT1_SHIFT, 0x00000000 },
{ AUD_POLY0_DDS_CONSTANT, 0x0012010c },
@@ -206,9 +199,10 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
{ AUD_RDSI_SHIFT, 0x00000000 },
{ AUD_RDSQ_SHIFT, 0x00000000 },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
- { /* end of list */ },
+ { /* end of list */ },
};
static const struct rlist btsc_sap[] = {
+ { AUD_AFE_12DB_EN, 0x00000001 },
{ AUD_DBX_IN_GAIN, 0x00007200 },
{ AUD_DBX_WBE_GAIN, 0x00006200 },
{ AUD_DBX_SE_GAIN, 0x00006200 },
@@ -259,371 +253,400 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
{ AUD_RDSI_SHIFT, 0x00000000 },
{ AUD_RDSQ_SHIFT, 0x00000000 },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
- { /* end of list */ },
+ { /* end of list */ },
};
- // dscaler: exactly taken from driver,
- // dscaler: don't know why to set EN_FMRADIO_EN_RDS
+ mode |= EN_FMRADIO_EN_RDS;
+
if (sap) {
dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0001,
- EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
+ set_audio_start(core, SEL_SAP);
set_audio_registers(core, btsc_sap);
+ set_audio_finish(core, mode);
} else {
dprintk("%s (status: known-good)\n",__FUNCTION__);
- set_audio_start(core, 0x0001,
- EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
+ set_audio_start(core, SEL_BTSC);
set_audio_registers(core, btsc);
+ set_audio_finish(core, mode);
}
- set_audio_finish(core);
}
static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
{
- /* This is probably weird..
- * Let's operate and find out. */
-
- static const struct rlist nicam_l_mono[] = {
- { AUD_ERRLOGPERIOD_R, 0x00000064 },
- { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
- { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
-
- { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
- { AUD_QAM_MODE, 0x00 },
- { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x4a },
-
- { AUD_DEEMPHGAIN_R, 0x6680 },
- { AUD_DEEMPHNUMER1_R, 0x353DE },
- { AUD_DEEMPHNUMER2_R, 0x1B1 },
- { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
- { AUD_DEEMPHDENOM2_R, 0x0 },
- { AUD_FM_MODE_ENABLE, 0x7 },
- { AUD_POLYPH80SCALEFAC, 0x3 },
- { AUD_AFE_12DB_EN, 0x1 },
- { AAGC_GAIN, 0x0 },
- { AAGC_HYST, 0x18 },
- { AAGC_DEF, 0x20 },
- { AUD_DN0_FREQ, 0x0 },
- { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
- { AUD_DCOC_0_SRC, 0x21 },
- { AUD_IIR1_0_SEL, 0x0 },
- { AUD_IIR1_0_SHIFT, 0x7 },
- { AUD_IIR1_1_SEL, 0x2 },
- { AUD_IIR1_1_SHIFT, 0x0 },
- { AUD_DCOC_1_SRC, 0x3 },
- { AUD_DCOC1_SHIFT, 0x0 },
- { AUD_DCOC_PASS_IN, 0x0 },
- { AUD_IIR1_2_SEL, 0x23 },
- { AUD_IIR1_2_SHIFT, 0x0 },
- { AUD_IIR1_3_SEL, 0x4 },
- { AUD_IIR1_3_SHIFT, 0x7 },
- { AUD_IIR1_4_SEL, 0x5 },
- { AUD_IIR1_4_SHIFT, 0x7 },
- { AUD_IIR3_0_SEL, 0x7 },
- { AUD_IIR3_0_SHIFT, 0x0 },
- { AUD_DEEMPH0_SRC_SEL, 0x11 },
- { AUD_DEEMPH0_SHIFT, 0x0 },
- { AUD_DEEMPH0_G0, 0x7000 },
- { AUD_DEEMPH0_A0, 0x0 },
- { AUD_DEEMPH0_B0, 0x0 },
- { AUD_DEEMPH0_A1, 0x0 },
- { AUD_DEEMPH0_B1, 0x0 },
- { AUD_DEEMPH1_SRC_SEL, 0x11 },
- { AUD_DEEMPH1_SHIFT, 0x0 },
- { AUD_DEEMPH1_G0, 0x7000 },
- { AUD_DEEMPH1_A0, 0x0 },
- { AUD_DEEMPH1_B0, 0x0 },
- { AUD_DEEMPH1_A1, 0x0 },
- { AUD_DEEMPH1_B1, 0x0 },
- { AUD_OUT0_SEL, 0x3F },
- { AUD_OUT1_SEL, 0x3F },
- { AUD_DMD_RA_DDS, 0x0F5C285 },
- { AUD_PLL_INT, 0x1E },
- { AUD_PLL_DDS, 0x0 },
- { AUD_PLL_FRAC, 0x0E542 },
-
- // setup QAM registers
- { AUD_RATE_ADJ1, 0x00000100 },
- { AUD_RATE_ADJ2, 0x00000200 },
- { AUD_RATE_ADJ3, 0x00000300 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00000500 },
- { AUD_RATE_THRES_DMD, 0x000000C0 },
- { /* end of list */ },
- };
-
- static const struct rlist nicam_l[] = {
- // setup QAM registers
- { AUD_RATE_ADJ1, 0x00000060 },
- { AUD_RATE_ADJ2, 0x000000F9 },
- { AUD_RATE_ADJ3, 0x000001CC },
- { AUD_RATE_ADJ4, 0x000002B3 },
- { AUD_RATE_ADJ5, 0x00000726 },
- { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_ERRLOGPERIOD_R, 0x00000064 },
- { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
- { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
- { AUD_POLYPH80SCALEFAC, 0x00000003 },
- { AUD_DMD_RA_DDS, 0x00C00000 },
- { AUD_PLL_INT, 0x0000001E },
- { AUD_PLL_DDS, 0x00000000 },
- { AUD_PLL_FRAC, 0x0000E542 },
- { AUD_START_TIMER, 0x00000000 },
- { AUD_DEEMPHNUMER1_R, 0x000353DE },
- { AUD_DEEMPHNUMER2_R, 0x000001B1 },
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_PHACC_FREQ_8MSB, 0x34 },
- { AUD_PHACC_FREQ_8LSB, 0x4C },
- { AUD_DEEMPHGAIN_R, 0x00006680 },
- { AUD_RATE_THRES_DMD, 0x000000C0 },
- { /* end of list */ },
- } ;
- dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
- if (!stereo) {
- /* AM mono sound */
- set_audio_start(core, 0x0004,
- 0x100c /* FIXME again */);
- set_audio_registers(core, nicam_l_mono);
- } else {
- set_audio_start(core, 0x0010,
- 0x1924 /* FIXME again */);
- set_audio_registers(core, nicam_l);
- }
- set_audio_finish(core);
+ /* This is probably weird..
+ * Let's operate and find out. */
+
+ static const struct rlist nicam_l_mono[] = {
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+
+ { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
+ { AUD_QAM_MODE, 0x00 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x4a },
+
+ { AUD_DEEMPHGAIN_R, 0x6680 },
+ { AUD_DEEMPHNUMER1_R, 0x353DE },
+ { AUD_DEEMPHNUMER2_R, 0x1B1 },
+ { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x0 },
+ { AUD_FM_MODE_ENABLE, 0x7 },
+ { AUD_POLYPH80SCALEFAC, 0x3 },
+ { AUD_AFE_12DB_EN, 0x1 },
+ { AAGC_GAIN, 0x0 },
+ { AAGC_HYST, 0x18 },
+ { AAGC_DEF, 0x20 },
+ { AUD_DN0_FREQ, 0x0 },
+ { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
+ { AUD_DCOC_0_SRC, 0x21 },
+ { AUD_IIR1_0_SEL, 0x0 },
+ { AUD_IIR1_0_SHIFT, 0x7 },
+ { AUD_IIR1_1_SEL, 0x2 },
+ { AUD_IIR1_1_SHIFT, 0x0 },
+ { AUD_DCOC_1_SRC, 0x3 },
+ { AUD_DCOC1_SHIFT, 0x0 },
+ { AUD_DCOC_PASS_IN, 0x0 },
+ { AUD_IIR1_2_SEL, 0x23 },
+ { AUD_IIR1_2_SHIFT, 0x0 },
+ { AUD_IIR1_3_SEL, 0x4 },
+ { AUD_IIR1_3_SHIFT, 0x7 },
+ { AUD_IIR1_4_SEL, 0x5 },
+ { AUD_IIR1_4_SHIFT, 0x7 },
+ { AUD_IIR3_0_SEL, 0x7 },
+ { AUD_IIR3_0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_SRC_SEL, 0x11 },
+ { AUD_DEEMPH0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_G0, 0x7000 },
+ { AUD_DEEMPH0_A0, 0x0 },
+ { AUD_DEEMPH0_B0, 0x0 },
+ { AUD_DEEMPH0_A1, 0x0 },
+ { AUD_DEEMPH0_B1, 0x0 },
+ { AUD_DEEMPH1_SRC_SEL, 0x11 },
+ { AUD_DEEMPH1_SHIFT, 0x0 },
+ { AUD_DEEMPH1_G0, 0x7000 },
+ { AUD_DEEMPH1_A0, 0x0 },
+ { AUD_DEEMPH1_B0, 0x0 },
+ { AUD_DEEMPH1_A1, 0x0 },
+ { AUD_DEEMPH1_B1, 0x0 },
+ { AUD_OUT0_SEL, 0x3F },
+ { AUD_OUT1_SEL, 0x3F },
+ { AUD_DMD_RA_DDS, 0x0F5C285 },
+ { AUD_PLL_INT, 0x1E },
+ { AUD_PLL_DDS, 0x0 },
+ { AUD_PLL_FRAC, 0x0E542 },
+
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000100 },
+ { AUD_RATE_ADJ2, 0x00000200 },
+ { AUD_RATE_ADJ3, 0x00000300 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00000500 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ };
+ static const struct rlist nicam_l[] = {
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000060 },
+ { AUD_RATE_ADJ2, 0x000000F9 },
+ { AUD_RATE_ADJ3, 0x000001CC },
+ { AUD_RATE_ADJ4, 0x000002B3 },
+ { AUD_RATE_ADJ5, 0x00000726 },
+ { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_DMD_RA_DDS, 0x00C00000 },
+ { AUD_PLL_INT, 0x0000001E },
+ { AUD_PLL_DDS, 0x00000000 },
+ { AUD_PLL_FRAC, 0x0000E542 },
+ { AUD_START_TIMER, 0x00000000 },
+ { AUD_DEEMPHNUMER1_R, 0x000353DE },
+ { AUD_DEEMPHNUMER2_R, 0x000001B1 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x34 },
+ { AUD_PHACC_FREQ_8LSB, 0x4C },
+ { AUD_DEEMPHGAIN_R, 0x00006680 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ } ;
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* AM Mono */
+ set_audio_start(core, SEL_A2);
+ set_audio_registers(core, nicam_l_mono);
+ set_audio_finish(core, EN_A2_FORCE_MONO1);
+ } else {
+ /* Nicam Stereo */
+ set_audio_start(core, SEL_NICAM);
+ set_audio_registers(core, nicam_l);
+ set_audio_finish(core, 0x1924); /* FIXME */
+ }
}
static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
{
static const struct rlist pal_i_fm_mono[] = {
- {AUD_ERRLOGPERIOD_R, 0x00000064},
- {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
- {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
- {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
- {AUD_PDF_DDS_CNST_BYTE2, 0x06},
- {AUD_PDF_DDS_CNST_BYTE1, 0x82},
- {AUD_PDF_DDS_CNST_BYTE0, 0x12},
- {AUD_QAM_MODE, 0x05},
- {AUD_PHACC_FREQ_8MSB, 0x3a},
- {AUD_PHACC_FREQ_8LSB, 0x93},
- {AUD_DMD_RA_DDS, 0x002a4f2f},
- {AUD_PLL_INT, 0x0000001e},
- {AUD_PLL_DDS, 0x00000004},
- {AUD_PLL_FRAC, 0x0000e542},
- {AUD_RATE_ADJ1, 0x00000100},
- {AUD_RATE_ADJ2, 0x00000200},
- {AUD_RATE_ADJ3, 0x00000300},
- {AUD_RATE_ADJ4, 0x00000400},
- {AUD_RATE_ADJ5, 0x00000500},
- {AUD_THR_FR, 0x00000000},
- {AUD_PILOT_BQD_1_K0, 0x0000755b},
- {AUD_PILOT_BQD_1_K1, 0x00551340},
- {AUD_PILOT_BQD_1_K2, 0x006d30be},
- {AUD_PILOT_BQD_1_K3, 0xffd394af},
- {AUD_PILOT_BQD_1_K4, 0x00400000},
- {AUD_PILOT_BQD_2_K0, 0x00040000},
- {AUD_PILOT_BQD_2_K1, 0x002a4841},
- {AUD_PILOT_BQD_2_K2, 0x00400000},
- {AUD_PILOT_BQD_2_K3, 0x00000000},
- {AUD_PILOT_BQD_2_K4, 0x00000000},
- {AUD_MODE_CHG_TIMER, 0x00000060},
- {AUD_AFE_12DB_EN, 0x00000001},
- {AAGC_HYST, 0x0000000a},
- {AUD_CORDIC_SHIFT_0, 0x00000007},
- {AUD_CORDIC_SHIFT_1, 0x00000007},
- {AUD_C1_UP_THR, 0x00007000},
- {AUD_C1_LO_THR, 0x00005400},
- {AUD_C2_UP_THR, 0x00005400},
- {AUD_C2_LO_THR, 0x00003000},
- {AUD_DCOC_0_SRC, 0x0000001a},
- {AUD_DCOC0_SHIFT, 0x00000000},
- {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
- {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
- {AUD_DCOC_PASS_IN, 0x00000003},
- {AUD_IIR3_0_SEL, 0x00000021},
- {AUD_DN2_AFC, 0x00000002},
- {AUD_DCOC_1_SRC, 0x0000001b},
- {AUD_DCOC1_SHIFT, 0x00000000},
- {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
- {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
- {AUD_IIR3_1_SEL, 0x00000023},
- {AUD_DN0_FREQ, 0x000035a3},
- {AUD_DN2_FREQ, 0x000029c7},
- {AUD_CRDC0_SRC_SEL, 0x00000511},
- {AUD_IIR1_0_SEL, 0x00000001},
- {AUD_IIR1_1_SEL, 0x00000000},
- {AUD_IIR3_2_SEL, 0x00000003},
- {AUD_IIR3_2_SHIFT, 0x00000000},
- {AUD_IIR3_0_SEL, 0x00000002},
- {AUD_IIR2_0_SEL, 0x00000021},
- {AUD_IIR2_0_SHIFT, 0x00000002},
- {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
- {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
- {AUD_POLYPH80SCALEFAC, 0x00000001},
- {AUD_START_TIMER, 0x00000000},
- { /* end of list */ },
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x3a},
+ {AUD_PHACC_FREQ_8LSB, 0x93},
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000004},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000060},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AAGC_HYST, 0x0000000a},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_DN0_FREQ, 0x000035a3},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_CRDC0_SRC_SEL, 0x00000511},
+ {AUD_IIR1_0_SEL, 0x00000001},
+ {AUD_IIR1_1_SEL, 0x00000000},
+ {AUD_IIR3_2_SEL, 0x00000003},
+ {AUD_IIR3_2_SHIFT, 0x00000000},
+ {AUD_IIR3_0_SEL, 0x00000002},
+ {AUD_IIR2_0_SEL, 0x00000021},
+ {AUD_IIR2_0_SHIFT, 0x00000002},
+ {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+ {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
};
static const struct rlist pal_i_nicam[] = {
- { AUD_RATE_ADJ1, 0x00000010 },
- { AUD_RATE_ADJ2, 0x00000040 },
- { AUD_RATE_ADJ3, 0x00000100 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00001000 },
- // { AUD_DMD_RA_DDS, 0x00c0d5ce },
- { AUD_DEEMPHGAIN_R, 0x000023c2 },
- { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
- { AUD_DEEMPHNUMER2_R, 0x0003023e },
- { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_DEEMPHDENOM2_R, 0x00000000 },
- { AUD_ERRLOGPERIOD_R, 0x00000fff },
- { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
- { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
- { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
- { AUD_POLYPH80SCALEFAC, 0x00000003 },
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x93 },
- { /* end of list */ },
- };
-
- dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
- if (!stereo) {
- // FM mono
- set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ { AUD_RATE_ADJ1, 0x00000010 },
+ { AUD_RATE_ADJ2, 0x00000040 },
+ { AUD_RATE_ADJ3, 0x00000100 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00001000 },
+ // { AUD_DMD_RA_DDS, 0x00c0d5ce },
+ { AUD_DEEMPHGAIN_R, 0x000023c2 },
+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
+ { AUD_DEEMPHNUMER2_R, 0x0003023e },
+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000fff },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x93 },
+ { /* end of list */ },
+ };
+
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* FM Mono */
+ set_audio_start(core, SEL_A2);
set_audio_registers(core, pal_i_fm_mono);
- } else {
- // Nicam Stereo
- set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ set_audio_finish(core, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ } else {
+ /* Nicam Stereo */
+ set_audio_start(core, SEL_NICAM);
set_audio_registers(core, pal_i_nicam);
- }
- set_audio_finish(core);
+ set_audio_finish(core, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ }
}
-static void set_audio_standard_A2(struct cx88_core *core)
+static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
{
- /* from dscaler cvs */
static const struct rlist a2_common[] = {
- { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
- { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
- { AUD_QAM_MODE, 0x05 },
- { AUD_PHACC_FREQ_8MSB, 0x34 },
- { AUD_PHACC_FREQ_8LSB, 0x4c },
-
- { AUD_RATE_ADJ1, 0x00001000 },
- { AUD_RATE_ADJ2, 0x00002000 },
- { AUD_RATE_ADJ3, 0x00003000 },
- { AUD_RATE_ADJ4, 0x00004000 },
- { AUD_RATE_ADJ5, 0x00005000 },
- { AUD_THR_FR, 0x00000000 },
- { AAGC_HYST, 0x0000001a },
- { AUD_PILOT_BQD_1_K0, 0x0000755b },
- { AUD_PILOT_BQD_1_K1, 0x00551340 },
- { AUD_PILOT_BQD_1_K2, 0x006d30be },
- { AUD_PILOT_BQD_1_K3, 0xffd394af },
- { AUD_PILOT_BQD_1_K4, 0x00400000 },
- { AUD_PILOT_BQD_2_K0, 0x00040000 },
- { AUD_PILOT_BQD_2_K1, 0x002a4841 },
- { AUD_PILOT_BQD_2_K2, 0x00400000 },
- { AUD_PILOT_BQD_2_K3, 0x00000000 },
- { AUD_PILOT_BQD_2_K4, 0x00000000 },
- { AUD_MODE_CHG_TIMER, 0x00000040 },
- { AUD_START_TIMER, 0x00000200 },
- { AUD_AFE_12DB_EN, 0x00000000 },
- { AUD_CORDIC_SHIFT_0, 0x00000007 },
- { AUD_CORDIC_SHIFT_1, 0x00000007 },
- { AUD_DEEMPH0_G0, 0x00000380 },
- { AUD_DEEMPH1_G0, 0x00000380 },
- { AUD_DCOC_0_SRC, 0x0000001a },
- { AUD_DCOC0_SHIFT, 0x00000000 },
- { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000003 },
- { AUD_IIR3_0_SEL, 0x00000021 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DCOC_1_SRC, 0x0000001b },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_RDSI_SEL, 0x00000017 },
- { AUD_RDSI_SHIFT, 0x00000000 },
- { AUD_RDSQ_SEL, 0x00000017 },
- { AUD_RDSQ_SHIFT, 0x00000000 },
- { AUD_POLYPH80SCALEFAC, 0x00000001 },
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x34},
+ {AUD_PHACC_FREQ_8LSB, 0x4c},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AAGC_HYST, 0x0000001a},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000040},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_DEEMPH0_G0, 0x00000380},
+ {AUD_DEEMPH1_G0, 0x00000380},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_RDSI_SEL, 0x00000017},
+ {AUD_RDSI_SHIFT, 0x00000000},
+ {AUD_RDSQ_SEL, 0x00000017},
+ {AUD_RDSQ_SHIFT, 0x00000000},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000000},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
+ };
+ static const struct rlist a2_bg[] = {
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
{ /* end of list */ },
};
- static const struct rlist a2_table1[] = {
- // PAL-BG
- { AUD_DMD_RA_DDS, 0x002a73bd },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C1_LO_THR, 0x00005400 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
+ static const struct rlist a2_dk[] = {
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DN0_FREQ, 0x00003a1c},
+ {AUD_DN2_FREQ, 0x0000d2e0},
{ /* end of list */ },
};
- static const struct rlist a2_table2[] = {
- // PAL-DK
- { AUD_DMD_RA_DDS, 0x002a73bd },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C1_LO_THR, 0x00005400 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
- { AUD_DN0_FREQ, 0x00003a1c },
- { AUD_DN2_FREQ, 0x0000d2e0 },
+/* unknown, probably NTSC-M */
+ static const struct rlist a2_m[] = {
+ {AUD_DMD_RA_DDS, 0x002a0425},
+ {AUD_C1_UP_THR, 0x00003c00},
+ {AUD_C1_LO_THR, 0x00003000},
+ {AUD_C2_UP_THR, 0x00006000},
+ {AUD_C2_LO_THR, 0x00003c00},
+ {AUD_DEEMPH0_A0, 0x00007a80},
+ {AUD_DEEMPH1_A0, 0x00007a80},
+ {AUD_DEEMPH0_G0, 0x00001200},
+ {AUD_DEEMPH1_G0, 0x00001200},
+ {AUD_DN0_FREQ, 0x0000283b},
+ {AUD_DN1_FREQ, 0x00003418},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_POLY0_DDS_CONSTANT, 0x000a7540},
{ /* end of list */ },
};
- static const struct rlist a2_table3[] = {
- // unknown, probably NTSC-M
- { AUD_DMD_RA_DDS, 0x002a2873 },
- { AUD_C1_UP_THR, 0x00003c00 },
- { AUD_C1_LO_THR, 0x00003000 },
- { AUD_C2_UP_THR, 0x00006000 },
- { AUD_C2_LO_THR, 0x00003c00 },
- { AUD_DN0_FREQ, 0x00002836 },
- { AUD_DN1_FREQ, 0x00003418 },
- { AUD_DN2_FREQ, 0x000029c7 },
- { AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
+
+ static const struct rlist a2_deemph50[] = {
+ {AUD_DEEMPH0_G0, 0x00000380},
+ {AUD_DEEMPH1_G0, 0x00000380},
+ {AUD_DEEMPHGAIN_R, 0x000011e1},
+ {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+ {AUD_DEEMPHNUMER2_R, 0x0003023c},
+ { /* end of list */ },
+ };
+
+ static const struct rlist a2_deemph75[] = {
+ {AUD_DEEMPH0_G0, 0x00000480},
+ {AUD_DEEMPH1_G0, 0x00000480},
+ {AUD_DEEMPHGAIN_R, 0x00009000},
+ {AUD_DEEMPHNUMER1_R, 0x000353de},
+ {AUD_DEEMPHNUMER2_R, 0x000001b1},
{ /* end of list */ },
};
- set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
+ set_audio_start(core, SEL_A2);
set_audio_registers(core, a2_common);
switch (core->tvaudio) {
case WW_A2_BG:
dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
- set_audio_registers(core, a2_table1);
+ set_audio_registers(core, a2_bg);
+ set_audio_registers(core, a2_deemph50);
break;
case WW_A2_DK:
dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
- set_audio_registers(core, a2_table2);
+ set_audio_registers(core, a2_dk);
+ set_audio_registers(core, a2_deemph50);
break;
case WW_A2_M:
dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
- set_audio_registers(core, a2_table3);
+ set_audio_registers(core, a2_m);
+ set_audio_registers(core, a2_deemph75);
break;
};
- set_audio_finish(core);
+
+ mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
+ set_audio_finish(core, mode);
}
static void set_audio_standard_EIAJ(struct cx88_core *core)
@@ -635,9 +658,9 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
};
dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0002, EN_EIAJ_AUTO_STEREO);
+ set_audio_start(core, SEL_EIAJ);
set_audio_registers(core, eiaj);
- set_audio_finish(core);
+ set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
}
static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
@@ -683,7 +706,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
};
dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
+ set_audio_start(core, SEL_FMRADIO);
switch (deemph)
{
@@ -700,7 +723,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
break;
}
- set_audio_finish(core);
+ set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
}
/* ----------------------------------------------------------- */
@@ -709,7 +732,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
{
switch (core->tvaudio) {
case WW_BTSC:
- set_audio_standard_BTSC(core,0);
+ set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
break;
case WW_NICAM_BGDKL:
set_audio_standard_NICAM_L(core,0);
@@ -720,7 +743,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
- set_audio_standard_A2(core);
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
break;
case WW_EIAJ:
set_audio_standard_EIAJ(core);
@@ -734,7 +757,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_NONE:
default:
printk("%s/0: unknown tv audio mode [%d]\n",
- core->name, core->tvaudio);
+ core->name, core->tvaudio);
break;
}
return;
@@ -769,6 +792,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
aud_ctl_names[cx_read(AUD_CTL) & 63]);
core->astat = reg;
+/* TODO
+ Reading from AUD_STATUS is not enough
+ for auto-detecting sap/dual-fm/nicam.
+ Add some code here later.
+*/
+
+# if 0
t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
t->rxsubchans = V4L2_TUNER_SUB_MONO;
@@ -779,7 +809,7 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
t->capability = V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_SAP;
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
- if (1 == pilot) {
+ if (1 == pilot) {
/* SAP */
t->rxsubchans |= V4L2_TUNER_SUB_SAP;
}
@@ -787,13 +817,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
- if (1 == pilot) {
+ if (1 == pilot) {
/* stereo */
t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
if (0 == mode)
t->audmode = V4L2_TUNER_MODE_STEREO;
}
- if (2 == pilot) {
+ if (2 == pilot) {
/* dual language -- FIXME */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
@@ -805,16 +835,17 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
break;
- case WW_SYSTEM_L_AM:
- if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
- t->audmode = V4L2_TUNER_MODE_STEREO;
+ case WW_SYSTEM_L_AM:
+ if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
- break ;
+ break ;
default:
/* nothing */
break;
}
+# endif
return;
}
@@ -835,16 +866,16 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
case WW_BTSC:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
- ctl = EN_BTSC_FORCE_MONO;
- mask = 0x3f;
+ set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
break;
- case V4L2_TUNER_MODE_SAP:
- ctl = EN_BTSC_FORCE_SAP;
- mask = 0x3f;
+ case V4L2_TUNER_MODE_LANG1:
+ set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
break;
case V4L2_TUNER_MODE_STEREO:
- ctl = EN_BTSC_AUTO_STEREO;
- mask = 0x3f;
+ set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
break;
}
break;
@@ -854,16 +885,13 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
- ctl = EN_A2_FORCE_MONO1;
- mask = 0x3f;
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
break;
case V4L2_TUNER_MODE_LANG2:
- ctl = EN_A2_AUTO_MONO2;
- mask = 0x3f;
+ set_audio_standard_A2(core, EN_A2_FORCE_MONO2);
break;
case V4L2_TUNER_MODE_STEREO:
- ctl = EN_A2_AUTO_STEREO | EN_DMTRX_SUMR;
- mask = 0x8bf;
+ set_audio_standard_A2(core, EN_A2_FORCE_STEREO);
break;
}
break;
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 320d57888bbd..9bc6c8995581 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 5f58c103198a..3dbc074fb515 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,4 @@
/*
- * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -66,7 +65,7 @@ module_param(vid_limit,int,0644);
MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
#define dprintk(level,fmt, arg...) if (video_debug >= level) \
- printk(KERN_DEBUG "%s/0: " fmt, dev->core->name , ## arg)
+ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
/* ------------------------------------------------------------------ */
@@ -326,22 +325,23 @@ static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
{
+ struct cx88_core *core = dev->core;
if (fh->resources & bit)
/* have it already allocated */
return 1;
/* is it free? */
- down(&dev->lock);
+ down(&core->lock);
if (dev->resources & bit) {
/* no, someone else uses it */
- up(&dev->lock);
+ up(&core->lock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
dev->resources |= bit;
dprintk(1,"res: get %d\n",bit);
- up(&dev->lock);
+ up(&core->lock);
return 1;
}
@@ -360,27 +360,29 @@ int res_locked(struct cx8800_dev *dev, unsigned int bit)
static
void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
{
+ struct cx88_core *core = dev->core;
if ((fh->resources & bits) != bits)
BUG();
- down(&dev->lock);
+ down(&core->lock);
fh->resources &= ~bits;
dev->resources &= ~bits;
dprintk(1,"res: put %d\n",bits);
- up(&dev->lock);
+ up(&core->lock);
}
/* ------------------------------------------------------------------ */
-static int video_mux(struct cx8800_dev *dev, unsigned int input)
+/* static int video_mux(struct cx8800_dev *dev, unsigned int input) */
+static int video_mux(struct cx88_core *core, unsigned int input)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
input, INPUT(input)->vmux,
INPUT(input)->gpio0,INPUT(input)->gpio1,
INPUT(input)->gpio2,INPUT(input)->gpio3);
- dev->core->input = input;
+ core->input = input;
cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14);
cx_write(MO_GP3_IO, INPUT(input)->gpio3);
cx_write(MO_GP0_IO, INPUT(input)->gpio0);
@@ -413,9 +415,9 @@ static int start_video_dma(struct cx8800_dev *dev,
struct cx88_core *core = dev->core;
/* setup fifo + format */
- cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH21],
+ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- cx88_set_scale(dev->core, buf->vb.width, buf->vb.height, buf->vb.field);
+ cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
/* reset counter */
@@ -424,6 +426,14 @@ static int start_video_dma(struct cx8800_dev *dev,
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
+
+ /* Enables corresponding bits at PCI_INT_STAT:
+ bits 0 to 4: video, audio, transport stream, VIP, Host
+ bit 7: timer
+ bits 8 and 9: DMA complete for: SRC, DST
+ bits 10 and 11: BERR signal asserted for RISC: RD, WR
+ bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+ */
cx_set(MO_VID_INTMSK, 0x0f0011);
/* enable capture */
@@ -431,7 +441,7 @@ static int start_video_dma(struct cx8800_dev *dev,
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
- cx_set(MO_VID_DMACNTRL, 0x11);
+ cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
return 0;
}
@@ -455,6 +465,7 @@ static int stop_video_dma(struct cx8800_dev *dev)
static int restart_video_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
{
+ struct cx88_core *core = dev->core;
struct cx88_buffer *buf, *prev;
struct list_head *item;
@@ -524,12 +535,13 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
{
struct cx8800_fh *fh = q->priv_data;
struct cx8800_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
int rc, init_buffer = 0;
BUG_ON(NULL == fh->fmt);
- if (fh->width < 48 || fh->width > norm_maxw(dev->core->tvnorm) ||
- fh->height < 32 || fh->height > norm_maxh(dev->core->tvnorm))
+ if (fh->width < 48 || fh->width > norm_maxw(core->tvnorm) ||
+ fh->height < 32 || fh->height > norm_maxh(core->tvnorm))
return -EINVAL;
buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
@@ -609,6 +621,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
struct cx88_buffer *prev;
struct cx8800_fh *fh = vq->priv_data;
struct cx8800_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
/* add jump to stopper */
@@ -701,6 +714,7 @@ static int video_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct cx8800_dev *h,*dev = NULL;
+ struct cx88_core *core;
struct cx8800_fh *fh;
struct list_head *list;
enum v4l2_buf_type type = 0;
@@ -725,6 +739,8 @@ static int video_open(struct inode *inode, struct file *file)
if (NULL == dev)
return -ENODEV;
+ core = dev->core;
+
dprintk(1,"open minor=%d radio=%d type=%s\n",
minor,radio,v4l2_type_names[type]);
@@ -755,17 +771,16 @@ static int video_open(struct inode *inode, struct file *file)
fh);
if (fh->radio) {
- struct cx88_core *core = dev->core;
int board = core->board;
dprintk(1,"video_open: setting radio device\n");
cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
- dev->core->tvaudio = WW_FM;
+ core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
- cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
+ cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
}
return 0;
@@ -857,6 +872,9 @@ static int video_release(struct inode *inode, struct file *file)
videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
+
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
return 0;
}
@@ -870,9 +888,10 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */
-static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
u32 value;
int i;
@@ -898,9 +917,10 @@ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return 0;
}
-static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
{
- struct cx88_core *core = dev->core;
+ /* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
u32 v_sat_value;
u32 value;
@@ -913,9 +933,9 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return -EINVAL;
if (ctl->value < c->v.minimum)
- return -ERANGE;
+ ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum)
- return -ERANGE;
+ ctl->value = c->v.maximum;
switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE:
value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
@@ -946,7 +966,8 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
return 0;
}
-static void init_controls(struct cx8800_dev *dev)
+/* static void init_controls(struct cx8800_dev *dev) */
+static void init_controls(struct cx88_core *core)
{
static struct v4l2_control mute = {
.id = V4L2_CID_AUDIO_MUTE,
@@ -969,11 +990,11 @@ static void init_controls(struct cx8800_dev *dev)
.value = 0x80,
};
- set_control(dev,&mute);
- set_control(dev,&volume);
- set_control(dev,&hue);
- set_control(dev,&contrast);
- set_control(dev,&brightness);
+ set_control(core,&mute);
+ set_control(core,&volume);
+ set_control(core,&hue);
+ set_control(core,&contrast);
+ set_control(core,&brightness);
}
/* ------------------------------------------------------------------ */
@@ -1004,6 +1025,8 @@ static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
struct v4l2_format *f)
{
+ struct cx88_core *core = dev->core;
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
@@ -1016,8 +1039,8 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
return -EINVAL;
field = f->fmt.pix.field;
- maxw = norm_maxw(dev->core->tvnorm);
- maxh = norm_maxh(dev->core->tvnorm);
+ maxw = norm_maxw(core->tvnorm);
+ maxh = norm_maxh(core->tvnorm);
if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2)
@@ -1101,12 +1124,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (video_debug > 1)
cx88_print_ioctl(core->name,cmd);
switch (cmd) {
+
+ /* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "cx8800");
+ strcpy(cap->driver, "cx8800");
strlcpy(cap->card, cx88_boards[core->board].name,
sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
@@ -1116,12 +1141,128 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
+ /* --- capture ioctls ---------------------------------------- */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ enum v4l2_buf_type type;
+ unsigned int index;
+
+ index = f->index;
+ type = f->type;
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (index >= ARRAY_SIZE(formats))
+ return -EINVAL;
+ memset(f,0,sizeof(*f));
+ f->index = index;
+ f->type = type;
+ strlcpy(f->description,formats[index].name,sizeof(f->description));
+ f->pixelformat = formats[index].fourcc;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_g_fmt(dev,fh,f);
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_s_fmt(dev,fh,f);
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+ return cx8800_try_fmt(dev,fh,f);
+ }
+
+ /* --- streaming capture ------------------------------------- */
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf *mbuf = arg;
+ struct videobuf_queue *q;
+ struct v4l2_requestbuffers req;
+ unsigned int i;
+
+ q = get_queue(fh);
+ memset(&req,0,sizeof(req));
+ req.type = q->type;
+ req.count = 8;
+ req.memory = V4L2_MEMORY_MMAP;
+ err = videobuf_reqbufs(q,&req);
+ if (err < 0)
+ return err;
+ memset(mbuf,0,sizeof(*mbuf));
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
+ }
+ return 0;
+ }
+ case VIDIOC_REQBUFS:
+ return videobuf_reqbufs(get_queue(fh), arg);
+
+ case VIDIOC_QUERYBUF:
+ return videobuf_querybuf(get_queue(fh), arg);
+
+ case VIDIOC_QBUF:
+ return videobuf_qbuf(get_queue(fh), arg);
+
+ case VIDIOC_DQBUF:
+ return videobuf_dqbuf(get_queue(fh), arg,
+ file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_STREAMON:
+ {
+ int res = get_ressource(fh);
+
+ if (!res_get(dev,fh,res))
+ return -EBUSY;
+ return videobuf_streamon(get_queue(fh));
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ int res = get_ressource(fh);
+
+ err = videobuf_streamoff(get_queue(fh));
+ if (err < 0)
+ return err;
+ res_free(dev,fh,res);
+ return 0;
+ }
+
+ default:
+ return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
+ }
+ return 0;
+}
+
+int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+ struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+{
+ int err;
+
+ if (video_debug > 1)
+ cx88_print_ioctl(core->name,cmd);
+ printk( KERN_INFO "CORE IOCTL: 0x%x\n", cmd );
+ cx88_print_ioctl(core->name,cmd);
+ dprintk( 1, "CORE IOCTL: 0x%x\n", cmd );
+
+ switch (cmd) {
/* ---------- tv norms ---------- */
case VIDIOC_ENUMSTD:
{
@@ -1156,9 +1297,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (i == ARRAY_SIZE(tvnorms))
return -EINVAL;
- down(&dev->lock);
- cx88_set_tvnorm(dev->core,&tvnorms[i]);
- up(&dev->lock);
+ down(&core->lock);
+ cx88_set_tvnorm(core,&tvnorms[i]);
+ up(&core->lock);
return 0;
}
@@ -1199,7 +1340,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{
unsigned int *i = arg;
- *i = dev->core->input;
+ *i = core->input;
return 0;
}
case VIDIOC_S_INPUT:
@@ -1208,55 +1349,15 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (*i >= 4)
return -EINVAL;
- down(&dev->lock);
+ down(&core->lock);
cx88_newstation(core);
- video_mux(dev,*i);
- up(&dev->lock);
+ video_mux(core,*i);
+ up(&core->lock);
return 0;
}
- /* --- capture ioctls ---------------------------------------- */
- case VIDIOC_ENUM_FMT:
- {
- struct v4l2_fmtdesc *f = arg;
- enum v4l2_buf_type type;
- unsigned int index;
-
- index = f->index;
- type = f->type;
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (index >= ARRAY_SIZE(formats))
- return -EINVAL;
- memset(f,0,sizeof(*f));
- f->index = index;
- f->type = type;
- strlcpy(f->description,formats[index].name,sizeof(f->description));
- f->pixelformat = formats[index].fourcc;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- case VIDIOC_G_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_g_fmt(dev,fh,f);
- }
- case VIDIOC_S_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_s_fmt(dev,fh,f);
- }
- case VIDIOC_TRY_FMT:
- {
- struct v4l2_format *f = arg;
- return cx8800_try_fmt(dev,fh,f);
- }
-
/* --- controls ---------------------------------------------- */
case VIDIOC_QUERYCTRL:
{
@@ -1277,9 +1378,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
case VIDIOC_G_CTRL:
- return get_control(dev,arg);
+ return get_control(core,arg);
case VIDIOC_S_CTRL:
- return set_control(dev,arg);
+ return set_control(core,arg);
/* --- tuner ioctls ------------------------------------------ */
case VIDIOC_G_TUNER:
@@ -1323,10 +1424,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (UNSET == core->tuner_type)
return -EINVAL;
- f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
- f->frequency = dev->freq;
+ /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+ f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ f->frequency = core->freq;
- cx88_call_i2c_clients(dev->core,VIDIOC_G_FREQUENCY,f);
+ cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
return 0;
}
@@ -1338,83 +1440,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (f->tuner != 0)
return -EINVAL;
- if (0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)
+ if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
return -EINVAL;
- if (1 == fh->radio && f->type != V4L2_TUNER_RADIO)
+ if (1 == radio && f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- down(&dev->lock);
- dev->freq = f->frequency;
+ down(&core->lock);
+ core->freq = f->frequency;
cx88_newstation(core);
- cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
+ cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
/* When changing channels it is required to reset TVAUDIO */
msleep (10);
cx88_set_tvaudio(core);
- up(&dev->lock);
- return 0;
- }
-
- /* --- streaming capture ------------------------------------- */
- case VIDIOCGMBUF:
- {
- struct video_mbuf *mbuf = arg;
- struct videobuf_queue *q;
- struct v4l2_requestbuffers req;
- unsigned int i;
-
- q = get_queue(fh);
- memset(&req,0,sizeof(req));
- req.type = q->type;
- req.count = 8;
- req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(q,&req);
- if (err < 0)
- return err;
- memset(mbuf,0,sizeof(*mbuf));
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return 0;
- }
- case VIDIOC_REQBUFS:
- return videobuf_reqbufs(get_queue(fh), arg);
-
- case VIDIOC_QUERYBUF:
- return videobuf_querybuf(get_queue(fh), arg);
-
- case VIDIOC_QBUF:
- return videobuf_qbuf(get_queue(fh), arg);
-
- case VIDIOC_DQBUF:
- return videobuf_dqbuf(get_queue(fh), arg,
- file->f_flags & O_NONBLOCK);
-
- case VIDIOC_STREAMON:
- {
- int res = get_ressource(fh);
-
- if (!res_get(dev,fh,res))
- return -EBUSY;
- return videobuf_streamon(get_queue(fh));
- }
- case VIDIOC_STREAMOFF:
- {
- int res = get_ressource(fh);
-
- err = videobuf_streamoff(get_queue(fh));
- if (err < 0)
- return err;
- res_free(dev,fh,res);
+ up(&core->lock);
return 0;
}
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
- video_do_ioctl);
+ driver_ioctl);
}
return 0;
}
@@ -1461,7 +1506,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
memset(t,0,sizeof(*t));
strcpy(t->name, "Radio");
- cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t);
+ cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
return 0;
}
case VIDIOC_ENUMINPUT:
@@ -1501,8 +1546,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
if (v->tuner) /* Only tuner 0 */
return -EINVAL;
- cx88_call_i2c_clients(dev->core,VIDIOCSTUNER,v);
- return 0;
+ cx88_call_i2c_clients(core,VIDIOCSTUNER,v);
+ return 0;
}
case VIDIOC_S_TUNER:
{
@@ -1511,7 +1556,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
if (0 != t->index)
return -EINVAL;
- cx88_call_i2c_clients(dev->core,VIDIOC_S_TUNER,t);
+ cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
return 0;
}
@@ -1569,7 +1614,7 @@ static void cx8800_vid_timeout(unsigned long data)
struct cx88_buffer *buf;
unsigned long flags;
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
@@ -1614,14 +1659,14 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
}
/* risc1 y */
if (status & 0x01) {
spin_lock(&dev->slock);
count = cx_read(MO_VIDY_GPCNT);
- cx88_wakeup(dev->core, &dev->vidq, count);
+ cx88_wakeup(core, &dev->vidq, count);
spin_unlock(&dev->slock);
}
@@ -1629,7 +1674,7 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
if (status & 0x08) {
spin_lock(&dev->slock);
count = cx_read(MO_VBI_GPCNT);
- cx88_wakeup(dev->core, &dev->vbiq, count);
+ cx88_wakeup(core, &dev->vbiq, count);
spin_unlock(&dev->slock);
}
@@ -1798,7 +1843,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
}
/* initialize driver struct */
- init_MUTEX(&dev->lock);
spin_lock_init(&dev->slock);
core->tvnorm = tvnorms;
@@ -1835,6 +1879,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
request_module("tuner");
if (core->tda9887_conf)
request_module("tda9887");
+
/* register v4l devices */
dev->video_dev = cx88_vdev_init(core,dev->pci,
&cx8800_video_template,"video");
@@ -1878,11 +1923,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
pci_set_drvdata(pci_dev,dev);
/* initial device configuration */
- down(&dev->lock);
- init_controls(dev);
- cx88_set_tvnorm(dev->core,tvnorms);
- video_mux(dev,0);
- up(&dev->lock);
+ down(&core->lock);
+ init_controls(core);
+ cx88_set_tvnorm(core,tvnorms);
+ video_mux(core,0);
+ up(&core->lock);
/* start tvaudio thread */
if (core->tuner_type != TUNER_ABSENT)
@@ -1902,14 +1947,15 @@ fail_free:
static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx88_core *core = dev->core;
/* stop thread */
- if (dev->core->kthread) {
- kthread_stop(dev->core->kthread);
- dev->core->kthread = NULL;
+ if (core->kthread) {
+ kthread_stop(core->kthread);
+ core->kthread = NULL;
}
- cx88_shutdown(dev->core); /* FIXME */
+ cx88_shutdown(core); /* FIXME */
pci_disable_device(pci_dev);
/* unregister stuff */
@@ -1921,7 +1967,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
/* free memory */
btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
list_del(&dev->devlist);
- cx88_core_put(dev->core,dev->pci);
+ cx88_core_put(core,dev->pci);
kfree(dev);
}
@@ -1945,7 +1991,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
spin_unlock(&dev->slock);
/* FIXME -- shutdown device */
- cx88_shutdown(dev->core);
+ cx88_shutdown(core);
pci_save_state(pci_dev);
if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
@@ -1959,16 +2005,32 @@ static int cx8800_resume(struct pci_dev *pci_dev)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
+ int err;
if (dev->state.disabled) {
- pci_enable_device(pci_dev);
+ err=pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ core->name);
+ return err;
+ }
+
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, PCI_D0);
+ err= pci_set_power_state(pci_dev, PCI_D0);
+ if (err) {
+ printk(KERN_ERR "%s: can't enable device\n",
+ core->name);
+
+ pci_disable_device(pci_dev);
+ dev->state.disabled = 1;
+
+ return err;
+ }
pci_restore_state(pci_dev);
/* FIXME: re-initialize hardware */
- cx88_reset(dev->core);
+ cx88_reset(core);
/* restart video+vbi capture */
spin_lock(&dev->slock);
@@ -2030,6 +2092,8 @@ static void cx8800_fini(void)
module_init(cx8800_init);
module_exit(cx8800_fini);
+EXPORT_SYMBOL(cx88_do_ioctl);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index da65dc92787c..f48dd4353568 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,4 @@
/*
- * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -35,7 +34,7 @@
#include "btcx-risc.h"
#include "cx88-reg.h"
-#include <linux/utsname.h>
+#include <linux/version.h>
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
#ifndef TRUE
@@ -48,6 +47,9 @@
#define CX88_MAXBOARDS 8
+/* Max number of inputs by card */
+#define MAX_CX88_INPUT 8
+
/* ----------------------------------------------------------- */
/* defines and enums */
@@ -199,7 +201,7 @@ struct cx88_board {
unsigned char tuner_addr;
unsigned char radio_addr;
int tda9887_conf;
- struct cx88_input input[8];
+ struct cx88_input input[MAX_CX88_INPUT];
struct cx88_input radio;
int blackbird:1;
int dvb:1;
@@ -288,6 +290,11 @@ struct cx88_core {
/* IR remote control state */
struct cx88_IR *ir;
+
+ struct semaphore lock;
+
+ /* various v4l controls */
+ u32 freq;
};
struct cx8800_dev;
@@ -323,8 +330,7 @@ struct cx8800_suspend_state {
struct cx8800_dev {
struct cx88_core *core;
struct list_head devlist;
- struct semaphore lock;
- spinlock_t slock;
+ spinlock_t slock;
/* various device info */
unsigned int resources;
@@ -342,7 +348,6 @@ struct cx8800_dev {
struct cx88_dmaqueue vbiq;
/* various v4l controls */
- u32 freq;
/* other global state info */
struct cx8800_suspend_state state;
@@ -350,14 +355,8 @@ struct cx8800_dev {
/* ----------------------------------------------------------- */
/* function 1: audio/alsa stuff */
+/* =============> moved to cx88-alsa.c <====================== */
-struct cx8801_dev {
- struct cx88_core *core;
-
- /* pci i/o */
- struct pci_dev *pci;
- unsigned char pci_rev,pci_lat;
-};
/* ----------------------------------------------------------- */
/* function 2: mpeg stuff */
@@ -373,8 +372,7 @@ struct cx8802_suspend_state {
struct cx8802_dev {
struct cx88_core *core;
- struct semaphore lock;
- spinlock_t slock;
+ spinlock_t slock;
/* pci i/o */
struct pci_dev *pci;
@@ -553,8 +551,21 @@ void cx8802_fini_common(struct cx8802_dev *dev);
int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
int cx8802_resume_common(struct pci_dev *pci_dev);
+/* ----------------------------------------------------------- */
+/* cx88-video.c */
+extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+ struct cx88_core *core, unsigned int cmd,
+ void *arg, v4l2_kioctl driver_ioctl);
+
+/* ----------------------------------------------------------- */
+/* cx88-blackbird.c */
+extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
/*
* 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/indycam.c b/drivers/media/video/indycam.c
new file mode 100644
index 000000000000..26dd06ec89a2
--- /dev/null
+++ b/drivers/media/video/indycam.c
@@ -0,0 +1,410 @@
+/*
+ * indycam.c - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <linux/videodev.h>
+/* IndyCam decodes stream of photons into digital image representation ;-) */
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "indycam.h"
+
+//#define INDYCAM_DEBUG
+
+#define INDYCAM_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("SGI IndyCam driver");
+MODULE_VERSION(INDYCAM_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#ifdef INDYCAM_DEBUG
+#define dprintk(x...) printk("IndyCam: " x);
+#define indycam_regdump(client) indycam_regdump_debug(client)
+#else
+#define dprintk(x...)
+#define indycam_regdump(client)
+#endif
+
+struct indycam {
+ struct i2c_client *client;
+ int version;
+};
+
+static struct i2c_driver i2c_driver_indycam;
+
+static const unsigned char initseq[] = {
+ INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
+ INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */
+ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */
+ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */
+ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */
+ INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */
+ INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */
+ INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
+};
+
+/* IndyCam register handling */
+
+static int indycam_read_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char *value)
+{
+ int ret;
+
+ if (reg == INDYCAM_RESET) {
+ dprintk("indycam_read_reg(): "
+ "skipping write-only register %d\n", reg);
+ *value = 0;
+ return 0;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
+ "register = 0x%02x\n", reg);
+ return ret;
+ }
+
+ *value = (unsigned char)ret;
+
+ return 0;
+}
+
+static int indycam_write_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char value)
+{
+ int err;
+
+ if ((reg == INDYCAM_BRIGHTNESS)
+ || (reg == INDYCAM_VERSION)) {
+ dprintk("indycam_write_reg(): "
+ "skipping read-only register %d\n", reg);
+ return 0;
+ }
+
+ dprintk("Writing Reg %d = 0x%02x\n", reg, value);
+ err = i2c_smbus_write_byte_data(client, reg, value);
+ if (err) {
+ printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
+ "register = 0x%02x, value = 0x%02x\n", reg, value);
+ }
+ return err;
+}
+
+static int indycam_write_block(struct i2c_client *client, unsigned char reg,
+ unsigned char length, unsigned char *data)
+{
+ unsigned char i;
+ int err;
+
+ for (i = reg; i < length; i++) {
+ err = indycam_write_reg(client, reg + i, data[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+#ifdef INDYCAM_DEBUG
+static void indycam_regdump_debug(struct i2c_client *client)
+{
+ int i;
+ unsigned char val;
+
+ for (i = 0; i < 9; i++) {
+ indycam_read_reg(client, i, &val);
+ dprintk("Reg %d = 0x%02x\n", i, val);
+ }
+}
+#endif
+
+static int indycam_get_controls(struct i2c_client *client,
+ struct indycam_control *ctrl)
+{
+ unsigned char ctrl_reg;
+
+ indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+ ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA)
+ ? INDYCAM_VALUE_ENABLED
+ : INDYCAM_VALUE_DISABLED;
+ ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL)
+ ? INDYCAM_VALUE_ENABLED
+ : INDYCAM_VALUE_DISABLED;
+ indycam_read_reg(client, INDYCAM_SHUTTER,
+ (unsigned char *)&ctrl->shutter);
+ indycam_read_reg(client, INDYCAM_GAIN,
+ (unsigned char *)&ctrl->gain);
+ indycam_read_reg(client, INDYCAM_RED_BALANCE,
+ (unsigned char *)&ctrl->red_balance);
+ indycam_read_reg(client, INDYCAM_BLUE_BALANCE,
+ (unsigned char *)&ctrl->blue_balance);
+ indycam_read_reg(client, INDYCAM_RED_SATURATION,
+ (unsigned char *)&ctrl->red_saturation);
+ indycam_read_reg(client, INDYCAM_BLUE_SATURATION,
+ (unsigned char *)&ctrl->blue_saturation);
+ indycam_read_reg(client, INDYCAM_GAMMA,
+ (unsigned char *)&ctrl->gamma);
+
+ return 0;
+}
+
+static int indycam_set_controls(struct i2c_client *client,
+ struct indycam_control *ctrl)
+{
+ unsigned char ctrl_reg;
+
+ indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg);
+ if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) {
+ if (ctrl->agc)
+ ctrl_reg |= INDYCAM_CONTROL_AGCENA;
+ else
+ ctrl_reg &= ~INDYCAM_CONTROL_AGCENA;
+ }
+ if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) {
+ if (ctrl->awb)
+ ctrl_reg |= INDYCAM_CONTROL_AWBCTL;
+ else
+ ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL;
+ }
+ indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg);
+
+ if (ctrl->shutter >= 0)
+ indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter);
+ if (ctrl->gain >= 0)
+ indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain);
+ if (ctrl->red_balance >= 0)
+ indycam_write_reg(client, INDYCAM_RED_BALANCE,
+ ctrl->red_balance);
+ if (ctrl->blue_balance >= 0)
+ indycam_write_reg(client, INDYCAM_BLUE_BALANCE,
+ ctrl->blue_balance);
+ if (ctrl->red_saturation >= 0)
+ indycam_write_reg(client, INDYCAM_RED_SATURATION,
+ ctrl->red_saturation);
+ if (ctrl->blue_saturation >= 0)
+ indycam_write_reg(client, INDYCAM_BLUE_SATURATION,
+ ctrl->blue_saturation);
+ if (ctrl->gamma >= 0)
+ indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma);
+
+ return 0;
+}
+
+/* I2C-interface */
+
+static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ int err = 0;
+ struct indycam *camera;
+ struct i2c_client *client;
+
+ printk(KERN_INFO "SGI IndyCam driver version %s\n",
+ INDYCAM_MODULE_VERSION);
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+ camera = kmalloc(sizeof(struct indycam), GFP_KERNEL);
+ if (!camera) {
+ err = -ENOMEM;
+ goto out_free_client;
+ }
+
+ memset(client, 0, sizeof(struct i2c_client));
+ memset(camera, 0, sizeof(struct indycam));
+
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &i2c_driver_indycam;
+ client->flags = 0;
+ strcpy(client->name, "IndyCam client");
+ i2c_set_clientdata(client, camera);
+
+ camera->client = client;
+
+ err = i2c_attach_client(client);
+ if (err)
+ goto out_free_camera;
+
+ camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION);
+ if (camera->version != CAMERA_VERSION_INDY &&
+ camera->version != CAMERA_VERSION_MOOSE) {
+ err = -ENODEV;
+ goto out_detach_client;
+ }
+ printk(KERN_INFO "IndyCam v%d.%d detected\n",
+ INDYCAM_VERSION_MAJOR(camera->version),
+ INDYCAM_VERSION_MINOR(camera->version));
+
+ indycam_regdump(client);
+
+ // initialize
+ err = indycam_write_block(client, 0, sizeof(initseq),
+ (unsigned char *)&initseq);
+ if (err) {
+ printk(KERN_ERR "IndyCam initalization failed\n");
+ err = -EIO;
+ goto out_detach_client;
+ }
+
+ indycam_regdump(client);
+
+ // white balance
+ err = indycam_write_reg(client, INDYCAM_CONTROL,
+ INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
+ if (err) {
+ printk(KERN_ERR "IndyCam white balance "
+ "initialization failed\n");
+ err = -EIO;
+ goto out_detach_client;
+ }
+
+ indycam_regdump(client);
+
+ printk(KERN_INFO "IndyCam initialized\n");
+
+ return 0;
+
+out_detach_client:
+ i2c_detach_client(client);
+out_free_camera:
+ kfree(camera);
+out_free_client:
+ kfree(client);
+ return err;
+}
+
+static int indycam_probe(struct i2c_adapter *adap)
+{
+ /* Indy specific crap */
+ if (adap->id == I2C_HW_SGI_VINO)
+ return indycam_attach(adap, INDYCAM_ADDR, 0);
+ /* Feel free to add probe here :-) */
+ return -ENODEV;
+}
+
+static int indycam_detach(struct i2c_client *client)
+{
+ struct indycam *camera = i2c_get_clientdata(client);
+
+ i2c_detach_client(client);
+ kfree(camera);
+ kfree(client);
+ return 0;
+}
+
+static int indycam_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ // struct indycam *camera = i2c_get_clientdata(client);
+
+ /* The old video_decoder interface just isn't enough,
+ * so we'll use some custom commands. */
+ switch (cmd) {
+ case DECODER_GET_CAPABILITIES: {
+ struct video_decoder_capability *cap = arg;
+
+ cap->flags = VIDEO_DECODER_NTSC;
+ cap->inputs = 1;
+ cap->outputs = 1;
+ break;
+ }
+ case DECODER_GET_STATUS: {
+ int *iarg = arg;
+
+ *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
+ DECODER_STATUS_COLOR;
+ break;
+ }
+ case DECODER_SET_NORM: {
+ int *iarg = arg;
+
+ switch (*iarg) {
+ case VIDEO_MODE_NTSC:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_INPUT: {
+ int *iarg = arg;
+
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_SET_OUTPUT: {
+ int *iarg = arg;
+
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_ENABLE_OUTPUT: {
+ /* Always enabled */
+ break;
+ }
+ case DECODER_SET_PICTURE: {
+ // struct video_picture *pic = arg;
+ /* TODO: convert values for indycam_set_controls() */
+ break;
+ }
+ case DECODER_INDYCAM_GET_CONTROLS: {
+ struct indycam_control *ctrl = arg;
+ indycam_get_controls(client, ctrl);
+ }
+ case DECODER_INDYCAM_SET_CONTROLS: {
+ struct indycam_control *ctrl = arg;
+ indycam_set_controls(client, ctrl);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver i2c_driver_indycam = {
+ .owner = THIS_MODULE,
+ .name = "indycam",
+ .id = I2C_DRIVERID_INDYCAM,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = indycam_probe,
+ .detach_client = indycam_detach,
+ .command = indycam_command,
+};
+
+static int __init indycam_init(void)
+{
+ return i2c_add_driver(&i2c_driver_indycam);
+}
+
+static void __exit indycam_exit(void)
+{
+ i2c_del_driver(&i2c_driver_indycam);
+}
+
+module_init(indycam_init);
+module_exit(indycam_exit);
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h
new file mode 100644
index 000000000000..d9ddb6b79a03
--- /dev/null
+++ b/drivers/media/video/indycam.h
@@ -0,0 +1,112 @@
+/*
+ * indycam.h - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _INDYCAM_H_
+#define _INDYCAM_H_
+
+/* I2C address for the Guinness Camera */
+#define INDYCAM_ADDR 0x56
+
+/* Camera version */
+#define CAMERA_VERSION_INDY 0x10 /* v1.0 */
+#define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */
+#define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4)
+#define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f)
+
+/* Register bus addresses */
+#define INDYCAM_CONTROL 0x00
+#define INDYCAM_SHUTTER 0x01
+#define INDYCAM_GAIN 0x02
+#define INDYCAM_BRIGHTNESS 0x03 /* read-only */
+#define INDYCAM_RED_BALANCE 0x04
+#define INDYCAM_BLUE_BALANCE 0x05
+#define INDYCAM_RED_SATURATION 0x06
+#define INDYCAM_BLUE_SATURATION 0x07
+#define INDYCAM_GAMMA 0x08
+#define INDYCAM_VERSION 0x0e /* read-only */
+#define INDYCAM_RESET 0x0f /* write-only */
+
+#define INDYCAM_LED 0x46
+#define INDYCAM_ORIENTATION 0x47
+#define INDYCAM_BUTTON 0x48
+
+/* Field definitions of registers */
+#define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */
+#define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */
+ /* 2-3 are reserved */
+#define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */
+
+#define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */
+#define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */
+#define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */
+#define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */
+#define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */
+#define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */
+#define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */
+#define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */
+#define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */
+
+#define INDYCAM_LED_ACTIVE 0x10
+#define INDYCAM_LED_INACTIVE 0x30
+#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40
+#define INDYCAM_BUTTON_RELEASED 0x10
+
+#define INDYCAM_SHUTTER_MIN 0x00
+#define INDYCAM_SHUTTER_MAX 0xff
+#define INDYCAM_GAIN_MIN 0x00
+#define INDYCAM_GAIN_MAX 0xff
+#define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */
+#define INDYCAM_RED_BALANCE_MAX 0xff
+#define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */
+#define INDYCAM_BLUE_BALANCE_MAX 0xff
+#define INDYCAM_RED_SATURATION_MIN 0x00
+#define INDYCAM_RED_SATURATION_MAX 0xff
+#define INDYCAM_BLUE_SATURATION_MIN 0x00
+#define INDYCAM_BLUE_SATURATION_MAX 0xff
+#define INDYCAM_GAMMA_MIN 0x00
+#define INDYCAM_GAMMA_MAX 0xff
+
+/* Driver interface definitions */
+
+#define INDYCAM_VALUE_ENABLED 1
+#define INDYCAM_VALUE_DISABLED 0
+#define INDYCAM_VALUE_UNCHANGED -1
+
+/* When setting controls, a value of -1 leaves the control unchanged. */
+struct indycam_control {
+ int agc; /* boolean */
+ int awb; /* boolean */
+ int shutter;
+ int gain;
+ int red_balance;
+ int blue_balance;
+ int red_saturation;
+ int blue_saturation;
+ int gamma;
+};
+
+#define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control)
+#define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control)
+
+/* Default values for controls */
+
+#define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED
+#define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED
+
+#define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60
+#define INDYCAM_GAIN_DEFAULT 0x80
+#define INDYCAM_RED_BALANCE_DEFAULT 0x18
+#define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4
+#define INDYCAM_RED_SATURATION_DEFAULT 0x80
+#define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0
+#define INDYCAM_GAMMA_DEFAULT 0x80
+
+#endif
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index a565823330aa..234151e48edc 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
*
* Copyright (c) 2003 Gerd Knorr
* Copyright (c) 2003 Pavel Machek
@@ -159,7 +158,7 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
struct IR {
struct bttv_sub_device *sub;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
char name[32];
char phys[32];
@@ -218,23 +217,23 @@ static void ir_handle_key(struct IR *ir)
if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown) {
- ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup)) {
- ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
}
} else {
/* can't disturgissh keydown/up :-/ */
- ir_input_keydown(&ir->input,&ir->ir,data,data);
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_keydown(ir->input, &ir->ir, data, data);
+ ir_input_nokey(ir->input, &ir->ir);
}
}
@@ -269,13 +268,17 @@ static int ir_probe(struct device *dev)
{
struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
struct IR *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
- ir = kmalloc(sizeof(*ir),GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
/* detect & configure */
switch (sub->core->type) {
@@ -329,6 +332,7 @@ static int ir_probe(struct device *dev)
}
if (NULL == ir_codes) {
kfree(ir);
+ input_free_device(input_dev);
return -ENODEV;
}
@@ -342,18 +346,19 @@ static int ir_probe(struct device *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(sub->core->pci));
- ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
- ir->input.name = ir->name;
- ir->input.phys = ir->phys;
- ir->input.id.bustype = BUS_PCI;
- ir->input.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (sub->core->pci->subsystem_vendor) {
- ir->input.id.vendor = sub->core->pci->subsystem_vendor;
- ir->input.id.product = sub->core->pci->subsystem_device;
+ input_dev->id.vendor = sub->core->pci->subsystem_vendor;
+ input_dev->id.product = sub->core->pci->subsystem_device;
} else {
- ir->input.id.vendor = sub->core->pci->vendor;
- ir->input.id.product = sub->core->pci->device;
+ input_dev->id.vendor = sub->core->pci->vendor;
+ input_dev->id.product = sub->core->pci->device;
}
+ input_dev->cdev.dev = &sub->core->pci->dev;
if (ir->polling) {
INIT_WORK(&ir->work, ir_work, ir);
@@ -364,9 +369,8 @@ static int ir_probe(struct device *dev)
}
/* all done */
- dev_set_drvdata(dev,ir);
- input_register_device(&ir->input);
- printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys);
+ dev_set_drvdata(dev, ir);
+ input_register_device(ir->input);
return 0;
}
@@ -380,7 +384,7 @@ static int ir_remove(struct device *dev)
flush_scheduled_work();
}
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
kfree(ir);
return 0;
}
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 9fc5055e001c..9703d3d351f9 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -1,5 +1,4 @@
/*
- * $Id: ir-kbd-i2c.c,v 1.11 2005/07/07 16:42:11 mchehab Exp $
*
* keyboard input driver for i2c IR remote controls
*
@@ -122,10 +121,9 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
};
-struct IR;
struct IR {
struct i2c_client c;
- struct input_dev input;
+ struct input_dev *input;
struct ir_input_state ir;
struct work_struct work;
@@ -272,9 +270,9 @@ static void ir_key_poll(struct IR *ir)
}
if (0 == rc) {
- ir_input_nokey(&ir->input,&ir->ir);
+ ir_input_nokey(ir->input, &ir->ir);
} else {
- ir_input_keydown(&ir->input,&ir->ir, ir_key, ir_raw);
+ ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
}
}
@@ -308,7 +306,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("unset"),
+ .name = "unset",
.driver = &driver
};
@@ -319,11 +317,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
char *name;
int ir_type;
struct IR *ir;
+ struct input_dev *input_dev;
- if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL)))
+ ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
+
ir->c = client_template;
+ ir->input = input_dev;
i2c_set_clientdata(&ir->c, ir);
ir->c.adapter = adap;
@@ -376,13 +381,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir->c.dev.bus_id);
/* init + register input device */
- ir_input_init(&ir->input,&ir->ir,ir_type,ir_codes);
- ir->input.id.bustype = BUS_I2C;
- ir->input.name = ir->c.name;
- ir->input.phys = ir->phys;
- input_register_device(&ir->input);
- printk(DEVNAME ": %s detected at %s [%s]\n",
- ir->input.name,ir->input.phys,adap->name);
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->name = ir->c.name;
+ input_dev->phys = ir->phys;
+
+ input_register_device(ir->input);
/* start polling via eventd */
INIT_WORK(&ir->work, ir_work, ir);
@@ -403,7 +407,7 @@ static int ir_detach(struct i2c_client *client)
flush_scheduled_work();
/* unregister devices */
- input_unregister_device(&ir->input);
+ input_unregister_device(ir->input);
i2c_detach_client(&ir->c);
/* free memory */
@@ -429,10 +433,10 @@ static int ir_probe(struct i2c_adapter *adap)
struct i2c_client c; char buf; int i,rc;
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
+ case I2C_HW_B_BT848:
probe = probe_bttv;
break;
- case I2C_ALGO_SAA7134:
+ case I2C_HW_SAA7134:
probe = probe_saa7134;
break;
}
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index fe194012bccf..3f2a882bc20a 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
#include "meye.h"
#include <linux/meye.h>
@@ -121,7 +122,7 @@ static int ptable_alloc(void)
memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
/* give only 32 bit DMA addresses */
- if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff))
+ if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK))
return -1;
meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 62f1b8ddb98b..262890cb20a7 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -124,10 +124,14 @@ module_param(standard, int, 0644);
module_param(amsound, int, 0644);
module_param(dolby, int, 0644);
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Simple, 2=Simpler");
MODULE_PARM_DESC(once, "No continuous stereo monitoring");
MODULE_PARM_DESC(debug, "Enable debug messages");
+MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo");
MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
+MODULE_PARM_DESC(dolby, "Activates Dolby processsing");
+
MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
MODULE_AUTHOR("Gerd Knorr");
@@ -1416,8 +1420,8 @@ static int msp_detach(struct i2c_client *client);
static int msp_probe(struct i2c_adapter *adap);
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
-static int msp_suspend(struct device * dev, u32 state, u32 level);
-static int msp_resume(struct device * dev, u32 level);
+static int msp_suspend(struct device * dev, pm_message_t state);
+static int msp_resume(struct device * dev);
static void msp_wake_thread(struct i2c_client *client);
@@ -1437,7 +1441,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
@@ -1452,7 +1456,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
if (-1 == msp3400c_reset(&client_template)) {
- dprintk("msp3400: no chip found\n");
+ dprintk("msp34xx: no chip found\n");
return -1;
}
@@ -1478,7 +1482,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
if (-1 == msp3400c_reset(c)) {
kfree(msp);
kfree(c);
- dprintk("msp3400: no chip found\n");
+ dprintk("msp34xx: no chip found\n");
return -1;
}
@@ -1488,7 +1492,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
kfree(msp);
kfree(c);
- printk("msp3400: error while reading chip version\n");
+ dprintk("msp34xx: error while reading chip version\n");
return -1;
}
@@ -1509,7 +1513,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
}
/* hello world :-) */
- printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c));
+ printk(KERN_INFO "msp34xx: init: chip=%s", c->name);
if (HAVE_NICAM(msp))
printk(" +nicam");
if (HAVE_SIMPLE(msp))
@@ -1817,7 +1821,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int msp_suspend(struct device * dev, u32 state, u32 level)
+static int msp_suspend(struct device * dev, pm_message_t state)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
@@ -1826,7 +1830,7 @@ static int msp_suspend(struct device * dev, u32 state, u32 level)
return 0;
}
-static int msp_resume(struct device * dev, u32 level)
+static int msp_resume(struct device * dev)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index 023f33056a4f..2d9ff40f0b09 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -1,5 +1,4 @@
/*
- * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
*/
#ifndef MSP3400_H
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 2fb7c2d1787a..972aa5e0aeef 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -1,5 +1,4 @@
/*
- * $Id: mt20xx.c,v 1.5 2005/06/16 08:29:49 nsh Exp $
*
* i2c tv tuner chip device driver
* controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -494,6 +493,7 @@ int microtune_init(struct i2c_client *c)
memset(buf,0,sizeof(buf));
t->tv_freq = NULL;
t->radio_freq = NULL;
+ t->standby = NULL;
name = "unknown";
i2c_master_send(c,buf,1);
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
index 3433619ad93f..b3f4d266cede 100644
--- a/drivers/media/video/ovcamchip/ov6x20.c
+++ b/drivers/media/video/ovcamchip/ov6x20.c
@@ -164,10 +164,10 @@ static int ov6x20_init(struct i2c_client *c)
DDEBUG(4, &c->dev, "entered");
switch (c->adapter->id) {
- case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511:
+ case I2C_HW_SMBUS_OV511:
rc = ov_write_regvals(c, regvals_init_6x20_511);
break;
- case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518:
+ case I2C_HW_SMBUS_OV518:
rc = ov_write_regvals(c, regvals_init_6x20_518);
break;
default:
@@ -338,7 +338,7 @@ static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
/******** Palette-specific regs ********/
/* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
if (win->format == VIDEO_PALETTE_GREY)
ov_write_mask(c, 0x13, 0x00, 0x20);
else
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
index 44a842379b45..6eab458ab792 100644
--- a/drivers/media/video/ovcamchip/ov6x30.c
+++ b/drivers/media/video/ovcamchip/ov6x30.c
@@ -301,7 +301,7 @@ static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
/******** Palette-specific regs ********/
if (win->format == VIDEO_PALETTE_GREY) {
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
/* Do nothing - we're already in 8-bit mode */
} else {
ov_write_mask(c, 0x13, 0x20, 0x20);
@@ -313,7 +313,7 @@ static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
* Therefore, the OV6630 needs to be in 8-bit multiplexed
* output mode */
- if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+ if (c->adapter->id == I2C_HW_SMBUS_OV518) {
/* Do nothing - we want to stay in 8-bit mode */
/* Warning: Messing with reg 0x13 breaks OV518 color */
} else {
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 54dd5612d3b8..2de34ebf0673 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -296,10 +296,10 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
* attach to adapters that are known to contain OV camera chips. */
switch (adap->id) {
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OVFX2):
- case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF):
+ case I2C_HW_SMBUS_OV511:
+ case I2C_HW_SMBUS_OV518:
+ case I2C_HW_SMBUS_OVFX2:
+ case I2C_HW_SMBUS_W9968CF:
PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
break;
default:
@@ -314,7 +314,7 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
}
memcpy(c, &client_template, sizeof *c);
c->adapter = adap;
- strcpy(i2c_clientname(c), "OV????");
+ strcpy(c->name, "OV????");
ov = kmalloc(sizeof *ov, GFP_KERNEL);
if (!ov) {
@@ -328,7 +328,7 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
if (rc < 0)
goto error;
- strcpy(i2c_clientname(c), chip_names[ov->subtype]);
+ strcpy(c->name, chip_names[ov->subtype]);
PDEBUG(1, "Camera chip detection complete");
@@ -421,7 +421,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.driver = &driver,
};
diff --git a/drivers/media/video/rds.h b/drivers/media/video/rds.h
new file mode 100644
index 000000000000..0d30eb744e61
--- /dev/null
+++ b/drivers/media/video/rds.h
@@ -0,0 +1,48 @@
+/*
+
+ Types and defines needed for RDS. This is included by
+ saa6588.c and every driver (e.g. bttv-driver.c) that wants
+ to use the saa6588 module.
+
+ Instead of having a seperate rds.h, I'd prefer to include
+ this stuff in one of the already existing files like tuner.h
+
+ (c) 2005 by Hans J. Koch
+
+ 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 _RDS_H
+#define _RDS_H
+
+struct rds_command {
+ unsigned int block_count;
+ int result;
+ unsigned char __user *buffer;
+ struct file *instance;
+ poll_table *event_list;
+};
+
+#define RDS_CMD_OPEN _IOW('R',1,int)
+#define RDS_CMD_CLOSE _IOW('R',2,int)
+#define RDS_CMD_READ _IOR('R',3,int)
+#define RDS_CMD_POLL _IOR('R',4,int)
+
+#endif
+
+
+
+
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
new file mode 100644
index 000000000000..72b70eb5da1d
--- /dev/null
+++ b/drivers/media/video/saa6588.c
@@ -0,0 +1,534 @@
+/*
+ Driver for SAA6588 RDS decoder
+
+ (c) 2005 Hans J. Koch
+
+ 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/kernel.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include <media/id.h>
+
+#include "rds.h"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {
+ 0x20 >> 1,
+ 0x22 >> 1,
+ I2C_CLIENT_END,
+};
+
+I2C_CLIENT_INSMOD;
+
+/* insmod options */
+static unsigned int debug = 0;
+static unsigned int xtal = 0;
+static unsigned int rbds = 0;
+static unsigned int plvl = 0;
+static unsigned int bufblocks = 100;
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "enable debug messages");
+MODULE_PARM(xtal, "i");
+MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
+MODULE_PARM(rbds, "i");
+MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
+MODULE_PARM(plvl, "i");
+MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
+MODULE_PARM(bufblocks, "i");
+MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
+
+MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
+MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>");
+
+MODULE_LICENSE("GPL");
+
+/* ---------------------------------------------------------------------- */
+
+#define UNSET (-1U)
+#define PREFIX "saa6588: "
+#define dprintk if (debug) printk
+
+struct saa6588 {
+ struct i2c_client client;
+ struct work_struct work;
+ struct timer_list timer;
+ spinlock_t lock;
+ unsigned char *buffer;
+ unsigned int buf_size;
+ unsigned int rd_index;
+ unsigned int wr_index;
+ unsigned int block_count;
+ unsigned char last_blocknum;
+ wait_queue_head_t read_queue;
+ int data_available_for_read;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * SAA6588 defines
+ */
+
+/* Initialization and mode control byte (0w) */
+
+/* bit 0+1 (DAC0/DAC1) */
+#define cModeStandard 0x00
+#define cModeFastPI 0x01
+#define cModeReducedRequest 0x02
+#define cModeInvalid 0x03
+
+/* bit 2 (RBDS) */
+#define cProcessingModeRDS 0x00
+#define cProcessingModeRBDS 0x04
+
+/* bit 3+4 (SYM0/SYM1) */
+#define cErrCorrectionNone 0x00
+#define cErrCorrection2Bits 0x08
+#define cErrCorrection5Bits 0x10
+#define cErrCorrectionNoneRBDS 0x18
+
+/* bit 5 (NWSY) */
+#define cSyncNormal 0x00
+#define cSyncRestart 0x20
+
+/* bit 6 (TSQD) */
+#define cSigQualityDetectOFF 0x00
+#define cSigQualityDetectON 0x40
+
+/* bit 7 (SQCM) */
+#define cSigQualityTriggered 0x00
+#define cSigQualityContinous 0x80
+
+/* Pause level and flywheel control byte (1w) */
+
+/* bits 0..5 (FEB0..FEB5) */
+#define cFlywheelMaxBlocksMask 0x3F
+#define cFlywheelDefault 0x20
+
+/* bits 6+7 (PL0/PL1) */
+#define cPauseLevel_11mV 0x00
+#define cPauseLevel_17mV 0x40
+#define cPauseLevel_27mV 0x80
+#define cPauseLevel_43mV 0xC0
+
+/* Pause time/oscillator frequency/quality detector control byte (1w) */
+
+/* bits 0..4 (SQS0..SQS4) */
+#define cQualityDetectSensMask 0x1F
+#define cQualityDetectDefault 0x0F
+
+/* bit 5 (SOSC) */
+#define cSelectOscFreqOFF 0x00
+#define cSelectOscFreqON 0x20
+
+/* bit 6+7 (PTF0/PTF1) */
+#define cOscFreq_4332kHz 0x00
+#define cOscFreq_8664kHz 0x40
+#define cOscFreq_12996kHz 0x80
+#define cOscFreq_17328kHz 0xC0
+
+/* ---------------------------------------------------------------------- */
+
+static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
+{
+ int i;
+
+ if (s->rd_index == s->wr_index) {
+ if (debug > 2)
+ dprintk(PREFIX "Read: buffer empty.\n");
+ return 0;
+ }
+
+ if (debug > 2) {
+ dprintk(PREFIX "Read: ");
+ for (i = s->rd_index; i < s->rd_index + 3; i++)
+ dprintk("0x%02x ", s->buffer[i]);
+ }
+
+ if (copy_to_user(user_buf, &s->buffer[s->rd_index], 3))
+ return -EFAULT;
+
+ s->rd_index += 3;
+ if (s->rd_index >= s->buf_size)
+ s->rd_index = 0;
+ s->block_count--;
+
+ if (debug > 2)
+ dprintk("%d blocks total.\n", s->block_count);
+
+ return 1;
+}
+
+static void read_from_buf(struct saa6588 *s, struct rds_command *a)
+{
+ unsigned long flags;
+
+ unsigned char __user *buf_ptr = a->buffer;
+ unsigned int i;
+ unsigned int rd_blocks;
+
+ a->result = 0;
+ if (!a->buffer)
+ return;
+
+ while (!s->data_available_for_read) {
+ int ret = wait_event_interruptible(s->read_queue,
+ s->data_available_for_read);
+ if (ret == -ERESTARTSYS) {
+ a->result = -EINTR;
+ return;
+ }
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+ rd_blocks = a->block_count;
+ if (rd_blocks > s->block_count)
+ rd_blocks = s->block_count;
+
+ if (!rd_blocks)
+ return;
+
+ for (i = 0; i < rd_blocks; i++) {
+ if (block_to_user_buf(s, buf_ptr)) {
+ buf_ptr += 3;
+ a->result++;
+ } else
+ break;
+ }
+ a->result *= 3;
+ s->data_available_for_read = (s->block_count > 0);
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf)
+{
+ unsigned int i;
+
+ if (debug > 3)
+ dprintk(PREFIX "New block: ");
+
+ for (i = 0; i < 3; ++i) {
+ if (debug > 3)
+ dprintk("0x%02x ", blockbuf[i]);
+ s->buffer[s->wr_index] = blockbuf[i];
+ s->wr_index++;
+ }
+
+ if (s->wr_index >= s->buf_size)
+ s->wr_index = 0;
+
+ if (s->wr_index == s->rd_index) {
+ s->rd_index++;
+ if (s->rd_index >= s->buf_size)
+ s->rd_index = 0;
+ } else
+ s->block_count++;
+
+ if (debug > 3)
+ dprintk("%d blocks total.\n", s->block_count);
+}
+
+static void saa6588_i2c_poll(struct saa6588 *s)
+{
+ unsigned long flags;
+ unsigned char tmpbuf[6];
+ unsigned char blocknum;
+ unsigned char tmp;
+
+ /* Although we only need 3 bytes, we have to read at least 6.
+ SAA6588 returns garbage otherwise */
+ if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) {
+ if (debug > 1)
+ dprintk(PREFIX "read error!\n");
+ return;
+ }
+
+ blocknum = tmpbuf[0] >> 5;
+ if (blocknum == s->last_blocknum) {
+ if (debug > 3)
+ dprintk("Saw block %d again.\n", blocknum);
+ return;
+ }
+
+ s->last_blocknum = blocknum;
+
+ /*
+ Byte order according to v4l2 specification:
+
+ Byte 0: Least Significant Byte of RDS Block
+ Byte 1: Most Significant Byte of RDS Block
+ Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error
+ occurred during reception of this block.
+ Bit 6: Corrected bit. Indicates that an error was
+ corrected for this data block.
+ Bits 5-3: Received Offset. Indicates the offset received
+ by the sync system.
+ Bits 2-0: Offset Name. Indicates the offset applied to this data.
+
+ SAA6588 byte order is Status-MSB-LSB, so we have to swap the
+ first and the last of the 3 bytes block.
+ */
+
+ tmp = tmpbuf[2];
+ tmpbuf[2] = tmpbuf[0];
+ tmpbuf[0] = tmp;
+
+ tmp = blocknum;
+ tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */
+ if ((tmpbuf[2] & 0x03) == 0x03)
+ tmp |= 0x80; /* uncorrectable error */
+ else if ((tmpbuf[2] & 0x03) != 0x00)
+ tmp |= 0x40; /* corrected error */
+ tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */
+
+ spin_lock_irqsave(&s->lock, flags);
+ block_to_buf(s, tmpbuf);
+ spin_unlock_irqrestore(&s->lock, flags);
+ s->data_available_for_read = 1;
+ wake_up_interruptible(&s->read_queue);
+}
+
+static void saa6588_timer(unsigned long data)
+{
+ struct saa6588 *s = (struct saa6588 *)data;
+
+ schedule_work(&s->work);
+}
+
+static void saa6588_work(void *data)
+{
+ struct saa6588 *s = (struct saa6588 *)data;
+
+ saa6588_i2c_poll(s);
+ mod_timer(&s->timer, jiffies + HZ / 50); /* 20 msec */
+}
+
+static int saa6588_configure(struct saa6588 *s)
+{
+ unsigned char buf[3];
+ int rc;
+
+ buf[0] = cSyncRestart;
+ if (rbds)
+ buf[0] |= cProcessingModeRBDS;
+
+ buf[1] = cFlywheelDefault;
+ switch (plvl) {
+ case 0:
+ buf[1] |= cPauseLevel_11mV;
+ break;
+ case 1:
+ buf[1] |= cPauseLevel_17mV;
+ break;
+ case 2:
+ buf[1] |= cPauseLevel_27mV;
+ break;
+ case 3:
+ buf[1] |= cPauseLevel_43mV;
+ break;
+ default: /* nothing */
+ break;
+ }
+
+ buf[2] = cQualityDetectDefault | cSelectOscFreqON;
+
+ switch (xtal) {
+ case 0:
+ buf[2] |= cOscFreq_4332kHz;
+ break;
+ case 1:
+ buf[2] |= cOscFreq_8664kHz;
+ break;
+ case 2:
+ buf[2] |= cOscFreq_12996kHz;
+ break;
+ case 3:
+ buf[2] |= cOscFreq_17328kHz;
+ break;
+ default: /* nothing */
+ break;
+ }
+
+ dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",
+ buf[0], buf[1], buf[2]);
+
+ if (3 != (rc = i2c_master_send(&s->client, buf, 3)))
+ printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct saa6588 *s;
+ client_template.adapter = adap;
+ client_template.addr = addr;
+
+ printk(PREFIX "chip found @ 0x%x\n", addr << 1);
+
+ if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL)))
+ return -ENOMEM;
+
+ s->buf_size = bufblocks * 3;
+
+ if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) {
+ kfree(s);
+ return -ENOMEM;
+ }
+ s->client = client_template;
+ s->block_count = 0;
+ s->wr_index = 0;
+ s->rd_index = 0;
+ s->last_blocknum = 0xff;
+ init_waitqueue_head(&s->read_queue);
+ s->data_available_for_read = 0;
+ i2c_set_clientdata(&s->client, s);
+ i2c_attach_client(&s->client);
+
+ saa6588_configure(s);
+
+ /* start polling via eventd */
+ INIT_WORK(&s->work, saa6588_work, s);
+ init_timer(&s->timer);
+ s->timer.function = saa6588_timer;
+ s->timer.data = (unsigned long)s;
+ schedule_work(&s->work);
+
+ return 0;
+}
+
+static int saa6588_probe(struct i2c_adapter *adap)
+{
+#ifdef I2C_CLASS_TV_ANALOG
+ if (adap->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, saa6588_attach);
+#else
+ switch (adap->id) {
+ case I2C_ALGO_BIT | I2C_HW_B_BT848:
+ case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+ case I2C_ALGO_SAA7134:
+ return i2c_probe(adap, &addr_data, saa6588_attach);
+ break;
+ }
+#endif
+ return 0;
+}
+
+static int saa6588_detach(struct i2c_client *client)
+{
+ struct saa6588 *s = i2c_get_clientdata(client);
+
+ del_timer_sync(&s->timer);
+ flush_scheduled_work();
+
+ i2c_detach_client(client);
+ kfree(s->buffer);
+ kfree(s);
+ return 0;
+}
+
+static int saa6588_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ struct saa6588 *s = i2c_get_clientdata(client);
+ struct rds_command *a = (struct rds_command *)arg;
+
+ switch (cmd) {
+ /* --- open() for /dev/radio --- */
+ case RDS_CMD_OPEN:
+ a->result = 0; /* return error if chip doesn't work ??? */
+ break;
+ /* --- close() for /dev/radio --- */
+ case RDS_CMD_CLOSE:
+ s->data_available_for_read = 1;
+ wake_up_interruptible(&s->read_queue);
+ a->result = 0;
+ break;
+ /* --- read() for /dev/radio --- */
+ case RDS_CMD_READ:
+ read_from_buf(s, a);
+ break;
+ /* --- poll() for /dev/radio --- */
+ case RDS_CMD_POLL:
+ a->result = 0;
+ if (s->data_available_for_read) {
+ a->result |= POLLIN | POLLRDNORM;
+ }
+ poll_wait(a->instance, &s->read_queue, a->event_list);
+ break;
+
+ default:
+ /* nothing */
+ break;
+ }
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver driver = {
+ .owner = THIS_MODULE,
+ .name = "i2c saa6588 driver",
+ .id = -1, /* FIXME */
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = saa6588_probe,
+ .detach_client = saa6588_detach,
+ .command = saa6588_command,
+};
+
+static struct i2c_client client_template = {
+ .name = "saa6588",
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
+};
+
+static int __init saa6588_init_module(void)
+{
+ return i2c_add_driver(&driver);
+}
+
+static void __exit saa6588_cleanup_module(void)
+{
+ i2c_del_driver(&driver);
+}
+
+module_init(saa6588_init_module);
+module_exit(saa6588_cleanup_module);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 22d055d8a695..e116bdbed310 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -470,7 +470,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7110;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fcd897382fcf..fe8a5e453969 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -42,7 +42,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -489,7 +488,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7111;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 2ba997f5ef1d..d9f50e2f7b92 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -45,7 +45,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -827,7 +826,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7114;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 79d05ea1b69b..382911c6ef22 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -598,7 +598,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("saa6752hs"),
+ .name = "saa6752hs",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 88b71a20b602..acc7a4335e23 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-cards.c,v 1.80 2005/07/07 01:49:30 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* card-specific stuff.
@@ -1373,7 +1372,7 @@ struct saa7134_board saa7134_boards[] = {
.inputs = {{
.name = name_comp1,
.vmux = 1,
- .amux = LINE2,
+ .amux = LINE1,
},{
.name = name_tv,
.vmux = 3,
@@ -1382,7 +1381,7 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE2,
+ .amux = LINE1,
}},
.radio = {
.name = name_radio,
@@ -2001,6 +2000,115 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000,
},
},
+ [SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
+ .name = "FlyTV mini Asus Digimatrix",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_LG_NTSC_TALN_MINI,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio, /* radio unconfirmed */
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_KWORLD_TERMINATOR] = {
+ /* Kworld V-Stream Studio TV Terminator */
+ /* "James Webb <jrwebb@qwest.net> */
+ .name = "V-Stream Studio TV Terminator",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 1 << 21,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x0000000,
+ .tv = 1,
+ },{
+ .name = name_comp1, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ .gpio = 0x0000000,
+ },{
+ .name = name_svideo, /* S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ .gpio = 0x0000000,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_YUAN_TUN900] = {
+ /* FIXME:
+ * S-Video and composite sources untested.
+ * Radio not working.
+ * Remote control not yet implemented.
+ * From : codemaster@webgeeks.be */
+ .name = "Yuan TUN-900 (saa7135)",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr= ADDR_UNSET,
+ .radio_addr= ADDR_UNSET,
+ .gpiomask = 0x00010003,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x01,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ .gpio = 0x02,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE2,
+ .gpio = 0x02,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x00010003,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x01,
+ },
+ },
};
@@ -2272,12 +2380,6 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
- .subvendor = 0x1131,
- .subdevice = 0,
- .driver_data = SAA7134_BOARD_SABRENT_SBTTVFM,
- },{
- .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x1461, /* Avermedia Technologies Inc */
.subdevice = 0x9715,
@@ -2346,6 +2448,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x4e42,
.subdevice = 0x0502,
.driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1043,
+ .subdevice = 0x0210, /* mini pci NTSC version */
+ .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1043,
+ .subdevice = 0x0210, /* mini pci PAL/SECAM version */
+ .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX,
},{
/* --- boards without eeprom + subsystem ID --- */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 1dbe61755e9f..e5e36f3c6250 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-core.c,v 1.39 2005/07/05 17:37:35 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* driver core
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 8be6a90358c8..639ae51a052d 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-dvb.c,v 1.23 2005/07/24 22:12:47 mkrufky Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
@@ -29,7 +28,6 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/suspend.h>
-#include <linux/config.h>
#include "saa7134-reg.h"
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index c85348d0239f..77b627eb6483 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 1203b93a572c..711aa8e85fac 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* i2c interface support
@@ -334,7 +333,7 @@ static int attach_inform(struct i2c_client *client)
struct tuner_setup tun_setup;
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name,client->addr,i2c_clientname(client));
+ client->driver->name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -370,8 +369,6 @@ static int attach_inform(struct i2c_client *client)
}
static struct i2c_algorithm saa7134_algo = {
- .name = "saa7134",
- .id = I2C_ALGO_SAA7134,
.master_xfer = saa7134_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
@@ -382,14 +379,14 @@ static struct i2c_adapter saa7134_adap_template = {
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
- I2C_DEVNAME("saa7134"),
- .id = I2C_ALGO_SAA7134,
+ .name = "saa7134",
+ .id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
.client_register = attach_inform,
};
static struct i2c_client saa7134_client_template = {
- I2C_DEVNAME("saa7134 internal"),
+ .name = "saa7134 internal",
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 213740122fe6..242cb235cf92 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-input.c,v 1.21 2005/06/22 23:37:34 nsh Exp $
*
* handle saa7134 IR remotes via linux kernel input layer.
*
@@ -426,9 +425,9 @@ static int build_key(struct saa7134_dev *dev)
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- ir_input_keydown(&ir->dev,&ir->ir,data,data);
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->dev,&ir->ir);
+ ir_input_nokey(ir->dev, &ir->ir);
}
return 0;
}
@@ -457,6 +456,7 @@ static void saa7134_input_timer(unsigned long data)
int saa7134_input_init1(struct saa7134_dev *dev)
{
struct saa7134_ir *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
u32 mask_keycode = 0;
u32 mask_keydown = 0;
@@ -536,10 +536,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
return -ENODEV;
}
- ir = kmalloc(sizeof(*ir),GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
/* init hardware-specific stuff */
ir->mask_keycode = mask_keycode;
@@ -553,18 +556,19 @@ int saa7134_input_init1(struct saa7134_dev *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(dev->pci));
- ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
- ir->dev.name = ir->name;
- ir->dev.phys = ir->phys;
- ir->dev.id.bustype = BUS_PCI;
- ir->dev.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (dev->pci->subsystem_vendor) {
- ir->dev.id.vendor = dev->pci->subsystem_vendor;
- ir->dev.id.product = dev->pci->subsystem_device;
+ input_dev->id.vendor = dev->pci->subsystem_vendor;
+ input_dev->id.product = dev->pci->subsystem_device;
} else {
- ir->dev.id.vendor = dev->pci->vendor;
- ir->dev.id.product = dev->pci->device;
+ input_dev->id.vendor = dev->pci->vendor;
+ input_dev->id.product = dev->pci->device;
}
+ input_dev->cdev.dev = &dev->pci->dev;
/* all done */
dev->remote = ir;
@@ -576,8 +580,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
add_timer(&ir->timer);
}
- input_register_device(&dev->remote->dev);
- printk("%s: registered input device for IR\n",dev->name);
+ input_register_device(ir->dev);
return 0;
}
@@ -586,9 +589,9 @@ void saa7134_input_fini(struct saa7134_dev *dev)
if (NULL == dev->remote)
return;
- input_unregister_device(&dev->remote->dev);
if (dev->remote->polling)
del_timer_sync(&dev->remote->timer);
+ input_unregister_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index b5bede95dbf5..c20630c82f1c 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-oss.c,v 1.17 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* oss dsp interface
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
index 87734f22af7d..ae0c7a165390 100644
--- a/drivers/media/video/saa7134/saa7134-reg.h
+++ b/drivers/media/video/saa7134/saa7134-reg.h
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-reg.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
*
* philips saa7134 registers
*/
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 4dd9f1b23928..463885601ab4 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-ts.c,v 1.15 2005/06/14 22:48:18 hhackmann Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index eeafa5a71d2b..badf2f9e3072 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-tvaudio.c,v 1.30 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* tv audio decoder (fm stereo, nicam, ...)
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 29e51cad2aaf..f4aee0af80e1 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index a4c2f751d097..35e5e85f669a 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134-video.c,v 1.36 2005/06/28 23:41:47 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -1368,29 +1367,7 @@ static int video_release(struct inode *inode, struct file *file)
saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
- if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
- u8 data[2];
- int ret;
- struct i2c_msg msg = {.addr=I2C_ADDR_TDA8290, .flags=0, .buf=data, .len = 2};
- data[0] = 0x21;
- data[1] = 0xc0;
- ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
- if (ret != 1)
- printk(KERN_ERR "TDA8290 access failure\n");
- msg.addr = I2C_ADDR_TDA8275;
- data[0] = 0x30;
- data[1] = 0xd0;
- ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
- if (ret != 1)
- printk(KERN_ERR "TDA8275 access failure\n");
- msg.addr = I2C_ADDR_TDA8290;
- data[0] = 0x21;
- data[1] = 0x80;
- i2c_transfer(&dev->i2c_adap, &msg, 1);
- data[0] = 0x00;
- data[1] = 0x02;
- i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
+ saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
/* free stuff */
videobuf_mmap_free(&fh->cap);
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 2af0cb2a731b..860b89530e2a 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,4 @@
/*
- * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $
*
* v4l2 device driver for philips saa7134 based TV cards
*
@@ -185,6 +184,9 @@ struct saa7134_format {
#define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63
+#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
+#define SAA7134_BOARD_KWORLD_TERMINATOR 65
+#define SAA7134_BOARD_YUAN_TUN900 66
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -349,7 +351,7 @@ struct saa7134_oss {
/* IR input */
struct saa7134_ir {
- struct input_dev dev;
+ struct input_dev *dev;
struct ir_input_state ir;
char name[32];
char phys[32];
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 108e7a4a0273..132aa7943c16 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -39,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/videodev.h>
@@ -387,7 +386,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7185;
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
new file mode 100644
index 000000000000..3ddbb62312be
--- /dev/null
+++ b/drivers/media/video/saa7191.c
@@ -0,0 +1,510 @@
+/*
+ * saa7191.c - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <linux/videodev.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION "0.0.3"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+struct saa7191 {
+ struct i2c_client *client;
+
+ /* the register values are stored here as the actual
+ * I2C-registers are write-only */
+ unsigned char reg[25];
+
+ unsigned char norm;
+ unsigned char input;
+};
+
+static struct i2c_driver i2c_driver_saa7191;
+
+static const unsigned char initseq[] = {
+ 0, /* Subaddress */
+ 0x50, /* SAA7191_REG_IDEL */
+ 0x30, /* SAA7191_REG_HSYB */
+ 0x00, /* SAA7191_REG_HSYS */
+ 0xe8, /* SAA7191_REG_HCLB */
+ 0xb6, /* SAA7191_REG_HCLS */
+ 0xf4, /* SAA7191_REG_HPHI */
+ 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */
+ 0x00, /* SAA7191_REG_HUEC */
+ 0xf8, /* SAA7191_REG_CKTQ */
+ 0xf8, /* SAA7191_REG_CKTS */
+ 0x90, /* SAA7191_REG_PLSE */
+ 0x90, /* SAA7191_REG_SESE */
+ 0x00, /* SAA7191_REG_GAIN */
+ 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */
+ 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */
+ 0x99, /* SAA7191_REG_CTL3 - automatic field detection */
+ 0x00, /* SAA7191_REG_CTL4 */
+ 0x2c, /* SAA7191_REG_CHCV */
+ 0x00, /* unused */
+ 0x00, /* unused */
+ 0x34, /* SAA7191_REG_HS6B */
+ 0x0a, /* SAA7191_REG_HS6S */
+ 0xf4, /* SAA7191_REG_HC6B */
+ 0xce, /* SAA7191_REG_HC6S */
+ 0xf4, /* SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static unsigned char saa7191_read_reg(struct i2c_client *client,
+ unsigned char reg)
+{
+ return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
+}
+
+static int saa7191_read_status(struct i2c_client *client,
+ unsigned char *value)
+{
+ int ret;
+
+ ret = i2c_master_recv(client, value, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int saa7191_write_reg(struct i2c_client *client, unsigned char reg,
+ unsigned char value)
+{
+
+ ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* the first byte of data must be the first subaddress number (register) */
+static int saa7191_write_block(struct i2c_client *client,
+ unsigned char length, unsigned char *data)
+{
+ int i;
+ int ret;
+
+ struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
+ for (i = 0; i < (length - 1); i++) {
+ decoder->reg[data[0] + i] = data[i + 1];
+ }
+
+ ret = i2c_master_send(client, data, length);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+ "write failed");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_set_input(struct i2c_client *client, int input)
+{
+ unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
+ unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
+ int err;
+
+ switch (input) {
+ case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+ | SAA7191_IOCK_GPSW2);
+ /* Chrominance trap active */
+ luma &= ~SAA7191_LUMA_BYPS;
+ break;
+ case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+ iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+ /* Chrominance trap bypassed */
+ luma |= SAA7191_LUMA_BYPS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
+ if (err)
+ return -EIO;
+
+ return 0;
+}
+
+static int saa7191_set_norm(struct i2c_client *client, int norm)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+ unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+ unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
+ unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
+ int err;
+
+ switch(norm) {
+ case SAA7191_NORM_AUTO: {
+ unsigned char status;
+
+ // does status depend on current norm ?
+ if (saa7191_read_status(client, &status))
+ return -EIO;
+
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~SAA7191_CTL3_FSEL;
+ ctl3 |= SAA7191_CTL3_AUFD;
+ chcv = (status & SAA7191_STATUS_FIDT)
+ ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL;
+ break;
+ }
+ case SAA7191_NORM_PAL:
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ break;
+ case SAA7191_NORM_NTSC:
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~SAA7191_CTL3_AUFD;
+ ctl3 |= SAA7191_CTL3_FSEL;
+ chcv = SAA7191_CHCV_NTSC;
+ break;
+ case SAA7191_NORM_SECAM:
+ stdc |= SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
+ if (err)
+ return -EIO;
+
+ decoder->norm = norm;
+
+ return 0;
+}
+
+static int saa7191_get_controls(struct i2c_client *client,
+ struct saa7191_control *ctrl)
+{
+ unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC);
+ unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
+
+ if (hue < 0x80) {
+ hue += 0x80;
+ } else {
+ hue -= 0x80;
+ }
+ ctrl->hue = hue;
+
+ ctrl->vtrc = (stdc & SAA7191_STDC_VTRC)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+ return 0;
+}
+
+static int saa7191_set_controls(struct i2c_client *client,
+ struct saa7191_control *ctrl)
+{
+ int err;
+
+ if (ctrl->hue >= 0) {
+ unsigned char hue = ctrl->hue & 0xff;
+ if (hue < 0x80) {
+ hue += 0x80;
+ } else {
+ hue -= 0x80;
+ }
+ err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue);
+ if (err)
+ return -EIO;
+ }
+ if (ctrl->vtrc >= 0) {
+ unsigned char stdc =
+ saa7191_read_reg(client, SAA7191_REG_STDC);
+
+ if (ctrl->vtrc) {
+ stdc |= SAA7191_STDC_VTRC;
+ } else {
+ stdc &= ~SAA7191_STDC_VTRC;
+ }
+
+ err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+ if (err)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* I2C-interface */
+
+static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ int err = 0;
+ struct saa7191 *decoder;
+ struct i2c_client *client;
+
+ printk(KERN_INFO "Philips SAA7191 driver version %s\n",
+ SAA7191_MODULE_VERSION);
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+ decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+ if (!decoder) {
+ err = -ENOMEM;
+ goto out_free_client;
+ }
+
+ memset(client, 0, sizeof(struct i2c_client));
+ memset(decoder, 0, sizeof(struct saa7191));
+
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &i2c_driver_saa7191;
+ client->flags = 0;
+ strcpy(client->name, "saa7191 client");
+ i2c_set_clientdata(client, decoder);
+
+ decoder->client = client;
+
+ err = i2c_attach_client(client);
+ if (err)
+ goto out_free_decoder;
+
+ decoder->input = SAA7191_INPUT_COMPOSITE;
+ decoder->norm = SAA7191_NORM_AUTO;
+
+ err = saa7191_write_block(client, sizeof(initseq),
+ (unsigned char *)initseq);
+ if (err) {
+ printk(KERN_ERR "SAA7191 initialization failed\n");
+ goto out_detach_client;
+ }
+
+ printk(KERN_INFO "SAA7191 initialized\n");
+
+ return 0;
+
+out_detach_client:
+ i2c_detach_client(client);
+out_free_decoder:
+ kfree(decoder);
+out_free_client:
+ kfree(client);
+ return err;
+}
+
+static int saa7191_probe(struct i2c_adapter *adap)
+{
+ /* Always connected to VINO */
+ if (adap->id == I2C_HW_SGI_VINO)
+ return saa7191_attach(adap, SAA7191_ADDR, 0);
+ /* Feel free to add probe here :-) */
+ return -ENODEV;
+}
+
+static int saa7191_detach(struct i2c_client *client)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+
+ i2c_detach_client(client);
+ kfree(decoder);
+ kfree(client);
+ return 0;
+}
+
+static int saa7191_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ struct saa7191 *decoder = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case DECODER_GET_CAPABILITIES: {
+ struct video_decoder_capability *cap = arg;
+
+ cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
+ VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
+ cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1;
+ cap->outputs = 1;
+ break;
+ }
+ case DECODER_GET_STATUS: {
+ int *iarg = arg;
+ unsigned char status;
+ int res = 0;
+
+ if (saa7191_read_status(client, &status)) {
+ return -EIO;
+ }
+ if ((status & SAA7191_STATUS_HLCK) == 0)
+ res |= DECODER_STATUS_GOOD;
+ if (status & SAA7191_STATUS_CODE)
+ res |= DECODER_STATUS_COLOR;
+ switch (decoder->norm) {
+ case SAA7191_NORM_NTSC:
+ res |= DECODER_STATUS_NTSC;
+ break;
+ case SAA7191_NORM_PAL:
+ res |= DECODER_STATUS_PAL;
+ break;
+ case SAA7191_NORM_SECAM:
+ res |= DECODER_STATUS_SECAM;
+ break;
+ case SAA7191_NORM_AUTO:
+ default:
+ if (status & SAA7191_STATUS_FIDT)
+ res |= DECODER_STATUS_NTSC;
+ else
+ res |= DECODER_STATUS_PAL;
+ break;
+ }
+ *iarg = res;
+ break;
+ }
+ case DECODER_SET_NORM: {
+ int *iarg = arg;
+
+ switch (*iarg) {
+ case VIDEO_MODE_AUTO:
+ return saa7191_set_norm(client, SAA7191_NORM_AUTO);
+ case VIDEO_MODE_PAL:
+ return saa7191_set_norm(client, SAA7191_NORM_PAL);
+ case VIDEO_MODE_NTSC:
+ return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+ case VIDEO_MODE_SECAM:
+ return saa7191_set_norm(client, SAA7191_NORM_SECAM);
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_INPUT: {
+ int *iarg = arg;
+
+ switch (client->adapter->id) {
+ case I2C_HW_SGI_VINO:
+ return saa7191_set_input(client, *iarg);
+ default:
+ if (*iarg != 0)
+ return -EINVAL;
+ }
+ break;
+ }
+ case DECODER_SET_OUTPUT: {
+ int *iarg = arg;
+
+ /* not much choice of outputs */
+ if (*iarg != 0)
+ return -EINVAL;
+ break;
+ }
+ case DECODER_ENABLE_OUTPUT: {
+ /* Always enabled */
+ break;
+ }
+ case DECODER_SET_PICTURE: {
+ struct video_picture *pic = arg;
+ unsigned val;
+ int err;
+
+ val = (pic->hue >> 8) - 0x80;
+ err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
+ if (err)
+ return -EIO;
+ break;
+ }
+ case DECODER_SAA7191_GET_STATUS: {
+ struct saa7191_status *status = arg;
+ unsigned char status_reg;
+
+ if (saa7191_read_status(client, &status_reg))
+ return -EIO;
+ status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+ status->ntsc = (status_reg & SAA7191_STATUS_FIDT)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+ status->color = (status_reg & SAA7191_STATUS_CODE)
+ ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
+
+ status->input = decoder->input;
+ status->norm = decoder->norm;
+ }
+ case DECODER_SAA7191_SET_NORM: {
+ int *norm = arg;
+ return saa7191_set_norm(client, *norm);
+ }
+ case DECODER_SAA7191_GET_CONTROLS: {
+ struct saa7191_control *ctrl = arg;
+ return saa7191_get_controls(client, ctrl);
+ }
+ case DECODER_SAA7191_SET_CONTROLS: {
+ struct saa7191_control *ctrl = arg;
+ return saa7191_set_controls(client, ctrl);
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver i2c_driver_saa7191 = {
+ .owner = THIS_MODULE,
+ .name = "saa7191",
+ .id = I2C_DRIVERID_SAA7191,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = saa7191_probe,
+ .detach_client = saa7191_detach,
+ .command = saa7191_command
+};
+
+static int saa7191_init(void)
+{
+ return i2c_add_driver(&i2c_driver_saa7191);
+}
+
+static void saa7191_exit(void)
+{
+ i2c_del_driver(&i2c_driver_saa7191);
+}
+
+module_init(saa7191_init);
+module_exit(saa7191_exit);
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h
new file mode 100644
index 000000000000..272045031435
--- /dev/null
+++ b/drivers/media/video/saa7191.h
@@ -0,0 +1,139 @@
+/*
+ * saa7191.h - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR 0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL 0x00
+#define SAA7191_REG_HSYB 0x01
+#define SAA7191_REG_HSYS 0x02
+#define SAA7191_REG_HCLB 0x03
+#define SAA7191_REG_HCLS 0x04
+#define SAA7191_REG_HPHI 0x05
+#define SAA7191_REG_LUMA 0x06
+#define SAA7191_REG_HUEC 0x07
+#define SAA7191_REG_CKTQ 0x08
+#define SAA7191_REG_CKTS 0x09
+#define SAA7191_REG_PLSE 0x0a
+#define SAA7191_REG_SESE 0x0b
+#define SAA7191_REG_GAIN 0x0c
+#define SAA7191_REG_STDC 0x0d
+#define SAA7191_REG_IOCK 0x0e
+#define SAA7191_REG_CTL3 0x0f
+#define SAA7191_REG_CTL4 0x10
+#define SAA7191_REG_CHCV 0x11
+#define SAA7191_REG_HS6B 0x14
+#define SAA7191_REG_HS6S 0x15
+#define SAA7191_REG_HC6B 0x16
+#define SAA7191_REG_HC6S 0x17
+#define SAA7191_REG_HP6I 0x18
+#define SAA7191_REG_STATUS 0xff /* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE 0x01 /* color detected flag */
+#define SAA7191_STATUS_FIDT 0x20 /* format type NTSC/PAL */
+#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked/locked */
+#define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+#define SAA7191_LUMA_BYPS 0x80
+
+/* Chroma Gain Control Settings Register definitions */
+/* 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO 0x80
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC 0x80
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS 0x01
+/* the bit fields above must be or'd with this value */
+#define SAA7191_STDC_VALUE 0x0c
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL 0x80
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS 0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2 0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1 0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD 0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL 0x40
+/* the bit fields above must be or'd with this value */
+#define SAA7191_CTL3_VALUE 0x19
+
+/* Chrominance Gain Control Register definitions
+ * (nominal value for UV CCIR level) */
+#define SAA7191_CHCV_NTSC 0x2c
+#define SAA7191_CHCV_PAL 0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE 0
+#define SAA7191_INPUT_SVIDEO 1
+
+#define SAA7191_NORM_AUTO 0
+#define SAA7191_NORM_PAL 1
+#define SAA7191_NORM_NTSC 2
+#define SAA7191_NORM_SECAM 3
+
+#define SAA7191_VALUE_ENABLED 1
+#define SAA7191_VALUE_DISABLED 0
+#define SAA7191_VALUE_UNCHANGED -1
+
+struct saa7191_status {
+ /* 0=no signal, 1=signal active*/
+ int signal;
+ /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+ int ntsc;
+ /* 0=no color detected, 1=color detected */
+ int color;
+
+ /* current SAA7191_INPUT_ */
+ int input;
+ /* current SAA7191_NORM_ */
+ int norm;
+};
+
+#define SAA7191_HUE_MIN 0x00
+#define SAA7191_HUE_MAX 0xff
+#define SAA7191_HUE_DEFAULT 0x80
+
+#define SAA7191_VTRC_MIN 0x00
+#define SAA7191_VTRC_MAX 0x01
+#define SAA7191_VTRC_DEFAULT 0x00
+
+struct saa7191_control {
+ int hue;
+ int vtrc;
+};
+
+#define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status)
+#define DECODER_SAA7191_SET_NORM _IOW('d', 196, int)
+#define DECODER_SAA7191_GET_CONTROLS _IOR('d', 197, struct saa7191_control)
+#define DECODER_SAA7191_SET_CONTROLS _IOW('d', 198, struct saa7191_control)
+
+#endif
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index b57743571087..d4497dbae05c 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2184,30 +2184,18 @@ static void release_saa(void)
vfree(saa->vidbuf);
vfree(saa->audbuf);
vfree(saa->osdbuf);
- if (saa->dmavid2)
- kfree((void *) saa->dmavid2);
+ kfree(saa->dmavid2);
saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
saa->dmavid2 = NULL;
- if (saa->dmadebi)
- kfree((void *) saa->dmadebi);
- if (saa->dmavid1)
- kfree((void *) saa->dmavid1);
- if (saa->dmavid2)
- kfree((void *) saa->dmavid2);
- if (saa->dmavid3)
- kfree((void *) saa->dmavid3);
- if (saa->dmaa1in)
- kfree((void *) saa->dmaa1in);
- if (saa->dmaa1out)
- kfree((void *) saa->dmaa1out);
- if (saa->dmaa2in)
- kfree((void *) saa->dmaa2in);
- if (saa->dmaa2out)
- kfree((void *) saa->dmaa2out);
- if (saa->dmaRPS1)
- kfree((void *) saa->dmaRPS1);
- if (saa->dmaRPS2)
- kfree((void *) saa->dmaRPS2);
+ kfree(saa->dmadebi);
+ kfree(saa->dmavid1);
+ kfree(saa->dmavid3);
+ kfree(saa->dmaa1in);
+ kfree(saa->dmaa1out);
+ kfree(saa->dmaa2in);
+ kfree(saa->dmaa2out);
+ kfree(saa->dmaRPS1);
+ kfree(saa->dmaRPS2);
free_irq(saa->irq, saa);
if (saa->saa7146_mem)
iounmap(saa->saa7146_mem);
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 7cb1fb3e66f9..255b6088ebf9 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -328,7 +328,7 @@ static int tda7432_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda7432_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, tda7432_attach);
#endif
return 0;
@@ -513,7 +513,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda7432"),
+ .name = "tda7432",
.driver = &driver,
};
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index a8b6a8df5109..c65f0c7680a2 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -1,5 +1,4 @@
/*
- * $Id: tda8290.c,v 1.15 2005/07/08 20:21:33 mchehab Exp $
*
* i2c tv tuner chip device driver
* controls the philips tda8290+75 tuner chip combo.
@@ -9,6 +8,9 @@
#include <linux/delay.h>
#include <media/tuner.h>
+#define I2C_ADDR_TDA8290 0x4b
+#define I2C_ADDR_TDA8275 0x61
+
/* ---------------------------------------------------------------------- */
struct freq_entry {
@@ -75,10 +77,12 @@ static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00,
static unsigned char i2c_set_VS[2] = { 0x30, 0x6F };
static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B };
static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 };
+static unsigned char i2c_tda8290_standby[2] = { 0x00, 0x02 };
static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 };
static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 };
static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 };
static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF };
+static unsigned char i2c_cb1_D0[2] = { 0x30, 0xD0 };
static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 };
static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 };
static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 };
@@ -117,6 +121,13 @@ static struct i2c_msg i2c_msg_epilog[] = {
{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on },
};
+static struct i2c_msg i2c_msg_standby[] = {
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D0), i2c_cb1_D0 },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_standby), i2c_tda8290_standby },
+};
+
static int tda8290_tune(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -205,6 +216,11 @@ static int has_signal(struct i2c_client *c)
return (afc & 0x80)? 65535:0;
}
+static void standby(struct i2c_client *c)
+{
+ i2c_transfer(c->adapter, i2c_msg_standby, ARRAY_SIZE(i2c_msg_standby));
+}
+
int tda8290_init(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -214,6 +230,7 @@ int tda8290_init(struct i2c_client *c)
t->tv_freq = set_tv_freq;
t->radio_freq = set_radio_freq;
t->has_signal = has_signal;
+ t->standby = standby;
i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge));
i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init));
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index c29bdfc3244e..1794686612c6 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -205,7 +205,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ 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;
}
@@ -231,7 +231,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tda9840"),
+ .name = "tda9840",
.driver = &driver,
};
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 566e1a5ca135..7e3dcdb262b0 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -262,7 +262,7 @@ static int tda9875_probe(struct i2c_adapter *adap)
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9875_attach);
#else
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->id == I2C_HW_B_BT848)
return i2c_probe(adap, &addr_data, tda9875_attach);
#endif
return 0;
@@ -384,7 +384,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda9875"),
+ .name = "tda9875",
.driver = &driver,
};
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 108c3ad7d622..94053f149ddf 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -23,6 +23,7 @@
TDA9887 (world), TDA9885 (USA)
Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
- KNC One TV-Station RDS (saa7134)
+ - Hauppauge PVR-150/500 (possibly more)
*/
@@ -49,7 +50,7 @@ MODULE_LICENSE("GPL");
struct tda9887 {
struct i2c_client client;
v4l2_std_id std;
- unsigned int radio;
+ enum tuner_mode mode;
unsigned int config;
unsigned int pinnacle_id;
unsigned int using_v4l2;
@@ -196,7 +197,7 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
+ cDeemphasis75 ),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_45_75 ),
@@ -364,7 +365,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
struct tvnorm *norm = NULL;
int i;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
if (t->radio_mode == V4L2_TUNER_MODE_MONO)
norm = &radio_mono;
else
@@ -378,7 +379,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
}
}
if (NULL == norm) {
- dprintk(PREFIX "Oops: no tvnorm entry found\n");
+ dprintk(PREFIX "Unsupported tvnorm entry - audio muted\n");
return -1;
}
@@ -519,6 +520,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n");
t->std = V4L2_STD_PAL_DK;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ printk(PREFIX "pal= argument not recognised\n");
+ break;
}
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -535,6 +542,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n");
t->std = V4L2_STD_SECAM_L;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ printk(PREFIX "secam= argument not recognised\n");
+ break;
}
}
return 0;
@@ -569,6 +582,10 @@ static int tda9887_configure(struct tda9887 *t)
tda9887_set_config(t,buf);
tda9887_set_insmod(t,buf);
+ if (t->mode == T_STANDBY) {
+ buf[1] |= cForcedMuteAudioON;
+ }
+
dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
buf[1],buf[2],buf[3]);
@@ -618,9 +635,9 @@ static int tda9887_probe(struct i2c_adapter *adap)
return i2c_probe(adap, &addr_data, tda9887_attach);
#else
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
+ case I2C_HW_SAA7134:
return i2c_probe(adap, &addr_data, tda9887_attach);
break;
}
@@ -653,10 +670,17 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* --- configuration --- */
case AUDC_SET_RADIO:
- t->radio = 1;
+ {
+ t->mode = T_RADIO;
tda9887_configure(t);
break;
-
+ }
+ case TUNER_SET_STANDBY:
+ {
+ t->mode = T_STANDBY;
+ tda9887_configure(t);
+ break;
+ }
case AUDC_CONFIG_PINNACLE:
{
int *i = arg;
@@ -689,7 +713,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct video_channel *vc = arg;
CHECK_V4L2;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tda9887_fixup_std(t);
@@ -701,7 +725,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
v4l2_std_id *id = arg;
SWITCH_V4L2;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
t->std = *id;
tda9887_fixup_std(t);
tda9887_configure(t);
@@ -713,14 +737,14 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
SWITCH_V4L2;
if (V4L2_TUNER_ANALOG_TV == f->type) {
- if (t->radio == 0)
+ if (t->mode == T_ANALOG_TV)
return 0;
- t->radio = 0;
+ t->mode = T_ANALOG_TV;
}
if (V4L2_TUNER_RADIO == f->type) {
- if (t->radio == 1)
+ if (t->mode == T_RADIO)
return 0;
- t->radio = 1;
+ t->mode = T_RADIO;
}
tda9887_configure(t);
break;
@@ -735,7 +759,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
};
struct v4l2_tuner* tuner = arg;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
__u8 reg = 0;
tuner->afc=0;
if (1 == i2c_master_recv(&t->client,&reg,1))
@@ -747,7 +771,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner* tuner = arg;
- if (t->radio) {
+ if (t->mode == T_RADIO) {
t->radio_mode = tuner->audmode;
tda9887_configure (t);
}
@@ -760,13 +784,13 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tda9887_suspend(struct device * dev, u32 state, u32 level)
+static int tda9887_suspend(struct device * dev, pm_message_t state)
{
dprintk("tda9887: suspend\n");
return 0;
}
-static int tda9887_resume(struct device * dev, u32 level)
+static int tda9887_resume(struct device * dev)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
struct tda9887 *t = i2c_get_clientdata(c);
@@ -793,7 +817,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("tda9887"),
+ .name = "tda9887",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index cebcc1fa68d1..38bf50943798 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -2,7 +2,6 @@
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
* I2C address is allways 0xC0.
*
- * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $
*
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
* This code is placed under the terms of the GNU General Public License
@@ -205,11 +204,6 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
buffer[4] = 0;
- if (t->mode == T_STANDBY) {
- tuner_dbg("TEA5767 set to standby mode\n");
- buffer[3] |= TEA5767_STDBY;
- }
-
if (t->audmode == V4L2_TUNER_MODE_MONO) {
tuner_dbg("TEA5767 set to mono\n");
buffer[2] |= TEA5767_MONO;
@@ -290,13 +284,31 @@ static int tea5767_stereo(struct i2c_client *c)
return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0);
}
+static void tea5767_standby(struct i2c_client *c)
+{
+ unsigned char buffer[5];
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned div, rc;
+
+ div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
+ buffer[0] = (div >> 8) & 0x3f;
+ buffer[1] = div & 0xff;
+ buffer[2] = TEA5767_PORT1_HIGH;
+ buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
+ TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
+ buffer[4] = 0;
+
+ if (5 != (rc = i2c_master_send(c, buffer, 5)))
+ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+}
+
int tea5767_autodetection(struct i2c_client *c)
{
unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int rc;
struct tuner *t = i2c_get_clientdata(c);
- if (7 != (rc = i2c_master_recv(c, buffer, 7))) {
+ if ((rc = i2c_master_recv(c, buffer, 7))< 5) {
tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
return EINVAL;
}
@@ -313,15 +325,10 @@ int tea5767_autodetection(struct i2c_client *c)
* bit 0 : internally set to 0
* Byte 5: bit 7:0 : == 0
*/
- if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
+ if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
return EINVAL;
}
- /* It seems that tea5767 returns 0xff after the 5th byte */
- if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
- tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
- return EINVAL;
- }
/* It seems that tea5767 returns 0xff after the 5th byte */
if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
@@ -337,14 +344,14 @@ int tea5767_tuner_init(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
- tuner_info("type set to %d (%s)\n", t->type,
- "Philips TEA5767HN FM Radio");
+ tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
strlcpy(c->name, "tea5767", sizeof(c->name));
t->tv_freq = set_tv_freq;
t->radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
+ t->standby = tea5767_standby;
return (0);
}
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index b44db8a7b94d..ee3688348b66 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -86,7 +86,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ 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;
}
@@ -200,7 +200,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tea6415c"),
+ .name = "tea6415c",
.driver = &driver,
};
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 48d4db7d507b..17975c19da5e 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -135,7 +135,7 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
static int attach(struct i2c_adapter *adapter)
{
/* let's see whether this is a know adapter we can attach to */
- if (adapter->id != I2C_ALGO_SAA7146) {
+ 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;
}
@@ -177,7 +177,7 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template = {
- I2C_DEVNAME("tea6420"),
+ .name = "tea6420",
.driver = &driver,
};
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 7d825e510ffd..79203595b9c1 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -41,7 +41,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
/* ---------------------------------------------------------------------- */
@@ -166,7 +165,7 @@ static int
tuner_probe(struct i2c_adapter *adap)
{
this_adap = 0;
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_LP))
+ if (adap->id == I2C_HW_B_LP)
return i2c_probe(adap, &addr_data, tuner_attach);
return 0;
}
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f0a579827a24..ad85bef1c3d5 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,4 @@
/*
- * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -182,6 +181,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
i2c_master_send(c, buffer, 4);
default_tuner_init(c);
break;
+ case TUNER_LG_TDVS_H062F:
+ /* Set the Auxiliary Byte. */
+ buffer[2] &= ~0x20;
+ buffer[2] |= 0x18;
+ buffer[3] = 0x20;
+ i2c_master_send(c, buffer, 4);
+ default_tuner_init(c);
+ break;
default:
default_tuner_init(c);
break;
@@ -208,31 +215,31 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
{
struct tuner *t = i2c_get_clientdata(c);
- if (tun_setup->addr == ADDR_UNSET) {
- if (t->mode_mask & tun_setup->mode_mask)
+ if ((tun_setup->addr == ADDR_UNSET &&
+ (t->mode_mask & tun_setup->mode_mask)) ||
+ tun_setup->addr == c->addr) {
set_type(c, tun_setup->type, tun_setup->mode_mask);
- } else if (tun_setup->addr == c->addr) {
- set_type(c, tun_setup->type, tun_setup->mode_mask);
}
}
static inline int check_mode(struct tuner *t, char *cmd)
{
- if (1 << t->mode & t->mode_mask) {
- switch (t->mode) {
- case V4L2_TUNER_RADIO:
- tuner_dbg("Cmd %s accepted for radio\n", cmd);
- break;
- case V4L2_TUNER_ANALOG_TV:
- tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
- break;
- case V4L2_TUNER_DIGITAL_TV:
- tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
- break;
- }
- return 0;
+ if ((1 << t->mode & t->mode_mask) == 0) {
+ return EINVAL;
+ }
+
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO:
+ tuner_dbg("Cmd %s accepted for radio\n", cmd);
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
+ break;
+ case V4L2_TUNER_DIGITAL_TV:
+ tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
+ break;
}
- return EINVAL;
+ return 0;
}
static char pal[] = "-";
@@ -274,6 +281,12 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg ("insmod fixup: PAL => PAL-N\n");
t->std = V4L2_STD_PAL_N;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_warn ("pal= argument not recognised\n");
+ break;
}
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -290,6 +303,12 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
t->std = V4L2_STD_SECAM_L;
break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_warn ("secam= argument not recognised\n");
+ break;
}
}
@@ -406,20 +425,18 @@ static int tuner_detach(struct i2c_client *client)
static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
{
- if (mode != t->mode) {
-
- t->mode = mode;
- if (check_mode(t, cmd) == EINVAL) {
- t->mode = T_STANDBY;
- if (V4L2_TUNER_RADIO == mode) {
- set_tv_freq(client, 400 * 16);
- } else {
- set_radio_freq(client, 87.5 * 16000);
- }
- return EINVAL;
- }
- }
- return 0;
+ if (mode == t->mode)
+ return 0;
+
+ t->mode = mode;
+
+ if (check_mode(t, cmd) == EINVAL) {
+ t->mode = T_STANDBY;
+ if (t->standby)
+ t->standby (client);
+ return EINVAL;
+ }
+ return 0;
}
#define switch_v4l2() if (!t->using_v4l2) \
@@ -453,6 +470,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
case AUDC_SET_RADIO:
set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
break;
+ case TUNER_SET_STANDBY:
+ {
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
+ break;
+ }
case AUDC_CONFIG_PINNACLE:
if (check_mode(t, "AUDC_CONFIG_PINNACLE") == EINVAL)
return 0;
@@ -672,7 +697,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tuner_suspend(struct device *dev, u32 state, u32 level)
+static int tuner_suspend(struct device *dev, pm_message_t state)
{
struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
@@ -682,7 +707,7 @@ static int tuner_suspend(struct device *dev, u32 state, u32 level)
return 0;
}
-static int tuner_resume(struct device *dev, u32 level)
+static int tuner_resume(struct device *dev)
{
struct i2c_client *c = container_of (dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata (c);
@@ -709,7 +734,7 @@ static struct i2c_driver driver = {
},
};
static struct i2c_client client_template = {
- I2C_DEVNAME("(tuner unset)"),
+ .name = "(tuner unset)",
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index de0c93aeb75d..8edd73abe1d8 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,4 @@
/*
- * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -102,6 +101,7 @@ struct tunertype
* "no float in kernel" rule.
*/
static struct tunertype tuners[] = {
+ /* 0-9 */
{ "Temic PAL (4002 FH5)", TEMIC, PAL,
16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
{ "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I,
@@ -110,7 +110,6 @@ static struct tunertype tuners[] = {
16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
{ "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM,
16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
-
{ "NoTuner", NoTuner, NOTUNER,
0,0,0x00,0x00,0x00,0x00,0x00},
{ "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL,
@@ -119,34 +118,34 @@ static struct tunertype tuners[] = {
16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
-
{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
{ "Alps HSBH1", TEMIC, NTSC,
16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
- { "Alps TSBE1",TEMIC,PAL,
+
+ /* 10-19 */
+ { "Alps TSBE1", TEMIC, PAL,
16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
{ "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
-
{ "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
{ "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
- { "Alps TSCH6",Alps,NTSC,
+ { "Alps TSCH6", Alps, NTSC,
16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
-
- { "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
+ { "Temic PAL_DK (4016 FY5)", TEMIC, PAL,
16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
- { "Philips NTSC_M (MK2)",Philips,NTSC,
+ { "Philips NTSC_M (MK2)", Philips, NTSC,
16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+ /* 20-29 */
{ "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic NTSC (4039 FR5)", TEMIC, NTSC,
@@ -155,7 +154,6 @@ static struct tunertype tuners[] = {
16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
{ "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-
{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
@@ -164,25 +162,24 @@ static struct tunertype tuners[] = {
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
-
{ "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+
+ /* 30-39 */
{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
-
- { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
+ { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
16*169,16*464,0xA0,0x90,0x30,0x8e,623},
- { "MT20xx universal", Microtune,PAL|NTSC,
+ { "MT20xx universal", Microtune, PAL|NTSC,
/* see mt20xx.c for details */ },
{ "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
{ "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
-
{ "Temic NTSC (4136 FY5)", TEMIC, NTSC,
16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
{ "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
@@ -192,42 +189,41 @@ static struct tunertype tuners[] = {
{ "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
+ /* 40-49 */
{ "HITACHI V7-J180AT", HITACHI, NTSC,
16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
- { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
+ { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC,
16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-
{ "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
- { "Microtune 4049 FM5",Microtune,PAL,
+ { "Microtune 4049 FM5", Microtune, PAL,
16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
{ "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
-
{ "Tenna TNF 8831 BGFF)", Philips, PAL,
16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
{ "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
+
+ /* 50-59 */
{ "TCL 2002N", TCL, NTSC,
16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
{ "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
-
{ "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC,
16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
{ "Philips FQ1286", Philips, NTSC,
- 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested
- { "tda8290+75", Philips,PAL|NTSC,
+ 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, /* UHF band untested */
+ { "tda8290+75", Philips, PAL|NTSC,
/* see tda8290.c for details */ },
{ "LG PAL (TAPE series)", LGINNOTEK, PAL,
16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
-
{ "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
{ "Philips FQ1236A MK4", Philips, NTSC,
@@ -237,6 +233,7 @@ static struct tunertype tuners[] = {
{ "Ymec TVision TVF-5533MF", Philips, NTSC,
16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
+ /* 60-66 */
{ "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
{ "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL,
@@ -245,12 +242,12 @@ static struct tunertype tuners[] = {
/* see tea5767.c for details */},
{ "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
-
- { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC,
+ { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC,
16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732},
-
{ "Ymec TVF66T5-B/DFF", Philips, PAL,
16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623},
+ { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC,
+ 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 },
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -471,6 +468,10 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
case TUNER_LG_PAL_FM:
buffer[3] = 0xa5;
break;
+ case TUNER_MICROTUNE_4049FM5:
+ div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
+ buffer[3] = 0xa4;
+ break;
default:
buffer[3] = 0xa4;
break;
@@ -497,6 +498,7 @@ int default_tuner_init(struct i2c_client *c)
t->radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
t->is_stereo = tuner_stereo;
+ t->standby = NULL;
return 0;
}
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index f42a1efa8fcf..1c31ef52f863 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -46,7 +46,17 @@ MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
MODULE_LICENSE("GPL");
#define UNSET (-1U)
-#define dprintk if (debug) printk
+
+#define tvaudio_info(fmt, arg...) do {\
+ printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_dbg(fmt, arg...) do {\
+ if (debug) \
+ printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+ chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
/* ---------------------------------------------------------------------- */
/* our structs */
@@ -162,24 +172,24 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
unsigned char buffer[2];
if (-1 == subaddr) {
- dprintk("%s: chip_write: 0x%x\n",
- i2c_clientname(&chip->c), val);
+ tvaudio_dbg("%s: chip_write: 0x%x\n",
+ chip->c.name, val);
chip->shadow.bytes[1] = val;
buffer[0] = val;
if (1 != i2c_master_send(&chip->c,buffer,1)) {
- printk(KERN_WARNING "%s: I/O error (write 0x%x)\n",
- i2c_clientname(&chip->c), val);
+ tvaudio_warn("%s: I/O error (write 0x%x)\n",
+ chip->c.name, val);
return -1;
}
} else {
- dprintk("%s: chip_write: reg%d=0x%x\n",
- i2c_clientname(&chip->c), subaddr, val);
+ tvaudio_dbg("%s: chip_write: reg%d=0x%x\n",
+ chip->c.name, subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
buffer[0] = subaddr;
buffer[1] = val;
if (2 != i2c_master_send(&chip->c,buffer,2)) {
- printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n",
- i2c_clientname(&chip->c), subaddr, val);
+ tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n",
+ chip->c.name, subaddr, val);
return -1;
}
}
@@ -203,31 +213,30 @@ static int chip_read(struct CHIPSTATE *chip)
unsigned char buffer;
if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
- printk(KERN_WARNING "%s: I/O error (read)\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: I/O error (read)\n",
+ chip->c.name);
return -1;
}
- dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer);
+ tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name,buffer);
return buffer;
}
static int chip_read2(struct CHIPSTATE *chip, int subaddr)
{
- unsigned char write[1];
- unsigned char read[1];
- struct i2c_msg msgs[2] = {
- { chip->c.addr, 0, 1, write },
- { chip->c.addr, I2C_M_RD, 1, read }
- };
- write[0] = subaddr;
+ unsigned char write[1];
+ unsigned char read[1];
+ struct i2c_msg msgs[2] = {
+ { chip->c.addr, 0, 1, write },
+ { chip->c.addr, I2C_M_RD, 1, read }
+ };
+ write[0] = subaddr;
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
- printk(KERN_WARNING "%s: I/O error (read2)\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: I/O error (read2)\n", chip->c.name);
return -1;
}
- dprintk("%s: chip_read2: reg%d=0x%x\n",
- i2c_clientname(&chip->c),subaddr,read[0]);
+ tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n",
+ chip->c.name,subaddr,read[0]);
return read[0];
}
@@ -239,17 +248,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
return 0;
/* update our shadow register set; print bytes if (debug > 0) */
- dprintk("%s: chip_cmd(%s): reg=%d, data:",
- i2c_clientname(&chip->c),name,cmd->bytes[0]);
+ tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:",
+ chip->c.name,name,cmd->bytes[0]);
for (i = 1; i < cmd->count; i++) {
- dprintk(" 0x%x",cmd->bytes[i]);
+ if (debug)
+ printk(" 0x%x",cmd->bytes[i]);
chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
}
- dprintk("\n");
+ if (debug)
+ printk("\n");
/* send data to the chip */
if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
- printk(KERN_WARNING "%s: I/O error (%s)\n", i2c_clientname(&chip->c), name);
+ tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name);
return -1;
}
return 0;
@@ -264,19 +275,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
static void chip_thread_wake(unsigned long data)
{
- struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+ struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
wake_up_interruptible(&chip->wq);
}
static int chip_thread(void *data)
{
DECLARE_WAITQUEUE(wait, current);
- struct CHIPSTATE *chip = data;
+ struct CHIPSTATE *chip = data;
struct CHIPDESC *desc = chiplist + chip->type;
- daemonize("%s",i2c_clientname(&chip->c));
+ daemonize("%s", chip->c.name);
allow_signal(SIGTERM);
- dprintk("%s: thread started\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread started\n", chip->c.name);
for (;;) {
add_wait_queue(&chip->wq, &wait);
@@ -288,7 +299,7 @@ static int chip_thread(void *data)
try_to_freeze();
if (chip->done || signal_pending(current))
break;
- dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread wakeup\n", chip->c.name);
/* don't do anything for radio or if mode != auto */
if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
@@ -301,8 +312,8 @@ static int chip_thread(void *data)
mod_timer(&chip->wt, jiffies+2*HZ);
}
- dprintk("%s: thread exiting\n", i2c_clientname(&chip->c));
- complete_and_exit(&chip->texit, 0);
+ tvaudio_dbg("%s: thread exiting\n", chip->c.name);
+ complete_and_exit(&chip->texit, 0);
return 0;
}
@@ -312,9 +323,9 @@ static void generic_checkmode(struct CHIPSTATE *chip)
int mode = desc->getmode(chip);
if (mode == chip->prevmode)
- return;
+ return;
- dprintk("%s: thread checkmode\n", i2c_clientname(&chip->c));
+ tvaudio_dbg("%s: thread checkmode\n", chip->c.name);
chip->prevmode = mode;
if (mode & VIDEO_SOUND_STEREO)
@@ -361,8 +372,8 @@ static int tda9840_getmode(struct CHIPSTATE *chip)
if (val & TDA9840_ST_STEREO)
mode |= VIDEO_SOUND_STEREO;
- dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
- val, mode);
+ tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+ val, mode);
return mode;
}
@@ -657,8 +668,8 @@ static int tda9873_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_STEREO;
if (val & TDA9873_DUAL)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
- dprintk ("tda9873_getmode(): raw chip read: %d, return: %d\n",
- val, mode);
+ tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n",
+ val, mode);
return mode;
}
@@ -668,12 +679,12 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
/* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) {
- dprintk("tda9873_setmode(): external input\n");
+ tvaudio_dbg("tda9873_setmode(): external input\n");
return;
}
- dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
- dprintk("tda9873_setmode(): sw_data = %d\n", sw_data);
+ tvaudio_dbg("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+ tvaudio_dbg("tda9873_setmode(): sw_data = %d\n", sw_data);
switch (mode) {
case VIDEO_SOUND_MONO:
@@ -694,7 +705,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
}
chip_write(chip, TDA9873_SW, sw_data);
- dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n",
+ tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n",
mode, sw_data);
}
@@ -831,9 +842,9 @@ static int tda9874a_setup(struct CHIPSTATE *chip)
} else { /* dic == 0x07 */
chip_write(chip, TDA9874A_AMCONR, 0xfb);
chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
- chip_write(chip, TDA9874A_AOSR, 0x00); // or 0x10
+ chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
}
- dprintk("tda9874a_setup(): %s [0x%02X].\n",
+ tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n",
tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
return 1;
}
@@ -876,7 +887,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
- dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+ tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
dsr, nsr, necr, mode);
return mode;
}
@@ -922,7 +933,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_AOSR, aosr);
chip_write(chip, TDA9874A_MDACOSR, mdacosr);
- dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+ tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
mode, aosr, mdacosr);
} else { /* dic == 0x07 */
@@ -957,7 +968,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_FMMR, fmmr);
chip_write(chip, TDA9874A_AOSR, aosr);
- dprintk("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+ tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
mode, fmmr, aosr);
}
}
@@ -971,10 +982,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
return 0;
- dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+ tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
if((dic == 0x11)||(dic == 0x07)) {
- printk("tvaudio: found tda9874%s.\n", (dic == 0x11) ? "a":"h");
+ tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h");
tda9874a_dic = dic; /* remember device id. */
return 1;
}
@@ -1098,7 +1109,7 @@ static int tda8425_initialize(struct CHIPSTATE *chip)
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF,
/* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2};
- if (chip->c.adapter->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) {
+ if (chip->c.adapter->id == I2C_HW_B_RIVA) {
memcpy (desc->inputmap, inputmap, sizeof (inputmap));
}
return 0;
@@ -1149,7 +1160,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for TA8874Z */
-// write 1st byte
+/* write 1st byte */
#define TA8874Z_LED_STE 0x80
#define TA8874Z_LED_BIL 0x40
#define TA8874Z_LED_EXT 0x20
@@ -1159,21 +1170,22 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
#define TA8874Z_MODE_SUB 0x02
#define TA8874Z_MODE_MAIN 0x01
-// write 2nd byte
-//#define TA8874Z_TI 0x80 // test mode
+/* write 2nd byte */
+/*#define TA8874Z_TI 0x80 */ /* test mode */
#define TA8874Z_SEPARATION 0x3f
#define TA8874Z_SEPARATION_DEFAULT 0x10
-// read
+/* read */
#define TA8874Z_B1 0x80
#define TA8874Z_B0 0x40
#define TA8874Z_CHAG_FLAG 0x20
-// B1 B0
-// mono L H
-// stereo L L
-// BIL H L
-
+/*
+ * B1 B0
+ * mono L H
+ * stereo L L
+ * BIL H L
+ */
static int ta8874z_getmode(struct CHIPSTATE *chip)
{
int val, mode;
@@ -1185,7 +1197,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip)
}else if (!(val & TA8874Z_B0)){
mode |= VIDEO_SOUND_STEREO;
}
- //dprintk ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode);
+ /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
return mode;
}
@@ -1198,7 +1210,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
{
int update = 1;
audiocmd *t = NULL;
- dprintk("ta8874z_setmode(): mode: 0x%02x\n", mode);
+ tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode);
switch(mode){
case VIDEO_SOUND_MONO:
@@ -1238,11 +1250,11 @@ static int tda9850 = 1;
static int tda9855 = 1;
static int tda9873 = 1;
static int tda9874a = 1;
-static int tea6300 = 0; // address clash with msp34xx
-static int tea6320 = 0; // address clash with msp34xx
+static int tea6300 = 0; /* address clash with msp34xx */
+static int tea6320 = 0; /* address clash with msp34xx */
static int tea6420 = 1;
static int pic16c54 = 1;
-static int ta8874z = 0; // address clash with tda9840
+static int ta8874z = 0; /* address clash with tda9840 */
module_param(tda8425, int, 0444);
module_param(tda9840, int, 0444);
@@ -1444,7 +1456,7 @@ static struct CHIPDESC chiplist[] = {
{
.name = "ta8874z",
.id = -1,
- //.id = I2C_DRIVERID_TA8874Z,
+ /*.id = I2C_DRIVERID_TA8874Z, */
.checkit = ta8874z_checkit,
.insmodopt = &ta8874z,
.addr_lo = I2C_TDA9840 >> 1,
@@ -1479,7 +1491,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(&chip->c, chip);
/* find description for the chip */
- dprintk("tvaudio: chip found @ i2c-addr=0x%x\n", addr<<1);
+ tvaudio_dbg("chip found @ 0x%x\n", addr<<1);
for (desc = chiplist; desc->name != NULL; desc++) {
if (0 == *(desc->insmodopt))
continue;
@@ -1491,17 +1503,19 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
break;
}
if (desc->name == NULL) {
- dprintk("tvaudio: no matching chip description found\n");
+ tvaudio_dbg("no matching chip description found\n");
return -EIO;
}
- printk("tvaudio: found %s @ 0x%x\n", desc->name, addr<<1);
- dprintk("tvaudio: matches:%s%s%s.\n",
- (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
- (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
- (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
+ tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
+ if (desc->flags) {
+ tvaudio_dbg("matches:%s%s%s.\n",
+ (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
+ (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
+ (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
+ }
/* fill required data structures */
- strcpy(i2c_clientname(&chip->c),desc->name);
+ strcpy(chip->c.name,desc->name);
chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
@@ -1537,8 +1551,8 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
init_completion(&chip->texit);
chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
if (chip->tpid < 0)
- printk(KERN_WARNING "%s: kernel_thread() failed\n",
- i2c_clientname(&chip->c));
+ tvaudio_warn("%s: kernel_thread() failed\n",
+ chip->c.name);
wake_up_interruptible(&chip->wq);
}
return 0;
@@ -1548,16 +1562,16 @@ static int chip_probe(struct i2c_adapter *adap)
{
/* don't attach on saa7146 based cards,
because dedicated drivers are used */
- if ((adap->id & I2C_ALGO_SAA7146))
+ if ((adap->id == I2C_HW_SAA7146))
return 0;
#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, chip_attach);
#else
switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
+ case I2C_HW_SAA7134:
return i2c_probe(adap, &addr_data, chip_attach);
}
#endif
@@ -1587,11 +1601,11 @@ static int chip_detach(struct i2c_client *client)
static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
- __u16 *sarg = arg;
+ __u16 *sarg = arg;
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
- dprintk("%s: chip_command 0x%x\n",i2c_clientname(&chip->c),cmd);
+ tvaudio_dbg("%s: chip_command 0x%x\n",chip->c.name,cmd);
switch (cmd) {
case AUDC_SET_INPUT:
@@ -1604,7 +1618,6 @@ static int chip_command(struct i2c_client *client,
break;
case AUDC_SET_RADIO:
- dprintk(KERN_DEBUG "tvaudio: AUDC_SET_RADIO\n");
chip->norm = VIDEO_MODE_RADIO;
chip->watch_stereo = 0;
/* del_timer(&chip->wt); */
@@ -1612,7 +1625,7 @@ static int chip_command(struct i2c_client *client,
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
+ kernel pointer here... */
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
@@ -1646,9 +1659,9 @@ static int chip_command(struct i2c_client *client,
if (desc->flags & CHIP_HAS_VOLUME) {
chip->left = (min(65536 - va->balance,32768) *
- va->volume) / 32768;
+ va->volume) / 32768;
chip->right = (min(va->balance,(__u16)32768) *
- va->volume) / 32768;
+ va->volume) / 32768;
chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
}
@@ -1670,17 +1683,16 @@ static int chip_command(struct i2c_client *client,
{
struct video_channel *vc = arg;
- dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n");
chip->norm = vc->norm;
break;
}
case VIDIOCSFREQ:
{
- chip->mode = 0; /* automatic */
+ chip->mode = 0; /* automatic */
if (desc->checkmode) {
desc->setmode(chip,VIDEO_SOUND_MONO);
- if (chip->prevmode != VIDEO_SOUND_MONO)
- chip->prevmode = -1; /* reset previous mode */
+ if (chip->prevmode != VIDEO_SOUND_MONO)
+ chip->prevmode = -1; /* reset previous mode */
mod_timer(&chip->wt, jiffies+2*HZ);
/* the thread will call checkmode() later */
}
@@ -1692,29 +1704,32 @@ static int chip_command(struct i2c_client *client,
static struct i2c_driver driver = {
.owner = THIS_MODULE,
- .name = "generic i2c audio driver",
- .id = I2C_DRIVERID_TVAUDIO,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = chip_probe,
- .detach_client = chip_detach,
- .command = chip_command,
+ .name = "generic i2c audio driver",
+ .id = I2C_DRIVERID_TVAUDIO,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = chip_probe,
+ .detach_client = chip_detach,
+ .command = chip_command,
};
static struct i2c_client client_template =
{
- I2C_DEVNAME("(unset)"),
+ .name = "(unset)",
.flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
+ .driver = &driver,
};
static int __init audiochip_init_module(void)
{
struct CHIPDESC *desc;
- printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
- printk(KERN_INFO "tvaudio: known chips: ");
- for (desc = chiplist; desc->name != NULL; desc++)
- printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);
- printk("\n");
+
+ if (debug) {
+ printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
+ printk(KERN_INFO "tvaudio: known chips: ");
+ for (desc = chiplist; desc->name != NULL; desc++)
+ printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name);
+ printk("\n");
+ }
return i2c_add_driver(&driver);
}
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 127ec38ebd60..5344d5592199 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -47,18 +47,21 @@ MODULE_LICENSE("GPL");
static int debug = 0;
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-2)");
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
-#define dprintk(num, args...) \
- do { \
- if (debug >= num) \
- printk(KERN_INFO "tveeprom: " args); \
- } while (0)
+#define tveeprom_info(fmt, arg...) do {\
+ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_dbg(fmt, arg...) do {\
+ if (debug) \
+ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+ c->adapter->nr, c->addr , ##arg); } while (0)
-#define TVEEPROM_KERN_ERR(args...) printk(KERN_ERR "tveeprom: " args);
-#define TVEEPROM_KERN_INFO(args...) printk(KERN_INFO "tveeprom: " args);
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
@@ -70,14 +73,14 @@ static struct HAUPPAUGE_TUNER_FMT
}
hauppauge_tuner_fmt[] =
{
- { 0x00000000, "unknown1" },
- { 0x00000000, "unknown2" },
- { 0x00000007, "PAL(B/G)" },
- { 0x00001000, "NTSC(M)" },
- { 0x00000010, "PAL(I)" },
- { 0x00400000, "SECAM(L/L´)" },
- { 0x00000e00, "PAL(D/K)" },
- { 0x03000000, "ATSC Digital" },
+ { 0x00000000, " unknown1" },
+ { 0x00000000, " unknown2" },
+ { 0x00000007, " PAL(B/G)" },
+ { 0x00001000, " NTSC(M)" },
+ { 0x00000010, " PAL(I)" },
+ { 0x00400000, " SECAM(L/L')" },
+ { 0x00000e00, " PAL(D/K)" },
+ { 0x03000000, " ATSC Digital" },
};
/* This is the full list of possible tuners. Many thanks to Hauppauge for
@@ -152,13 +155,13 @@ hauppauge_tuner[] =
{ TUNER_MICROTUNE_4049FM5, "Microtune 4049 FM5"},
{ TUNER_ABSENT, "LG TPI8NSR11F"},
{ TUNER_ABSENT, "Microtune 4049 FM5 Alt I2C"},
- { TUNER_ABSENT, "Philips FQ1216ME MK3"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216ME MK3"},
{ TUNER_ABSENT, "Philips FI1236 MK3"},
{ TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216 ME MK3"},
- { TUNER_ABSENT, "Philips FM1236 MK3"},
+ { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK3"},
{ TUNER_ABSENT, "Philips FM1216MP MK3"},
/* 60-69 */
- { TUNER_ABSENT, "LG S001D MK3"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "LG S001D MK3"},
{ TUNER_ABSENT, "LG M001D MK3"},
{ TUNER_ABSENT, "LG S701D MK3"},
{ TUNER_ABSENT, "LG M701D MK3"},
@@ -167,7 +170,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Temic 4106FH5"},
{ TUNER_ABSENT, "Philips FQ1216LMP MK3"},
{ TUNER_LG_NTSC_TAPE, "LG TAPE H001F MK3"},
- { TUNER_ABSENT, "LG TAPE H701F MK3"},
+ { TUNER_LG_NTSC_TAPE, "LG TAPE H701F MK3"},
/* 70-79 */
{ TUNER_ABSENT, "LG TALN H200T"},
{ TUNER_ABSENT, "LG TALN H250T"},
@@ -183,8 +186,8 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Philips FQ1216LME MK3"},
{ TUNER_ABSENT, "LG TAPC G701D"},
{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
- { TUNER_ABSENT, "TCL 2002MB 3"},
- { TUNER_ABSENT, "TCL 2002MI 3"},
+ { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
+ { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
{ TUNER_TCL_2002N, "TCL 2002N 6A"},
{ TUNER_ABSENT, "Philips FQ1236 MK3"},
{ TUNER_ABSENT, "Samsung TCPN 2121P30A"},
@@ -199,17 +202,51 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Philips FQ1236 MK5"},
{ TUNER_ABSENT, "Unspecified"},
{ TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"},
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_TCL_2002N, "TCL 2002N 5H"},
+ /* 100-103 */
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_TEA5767, "Philips TEA5767HN FM Radio"},
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"},
};
-static char *sndtype[] = {
- "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C", "MSP3410D",
- "MSP3415", "MSP3430", "MSP3438", "CS5331", "MSP3435", "MSP3440",
- "MSP3445", "MSP3411", "MSP3416", "MSP3425",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *audioIC[] = {
+ /* 0-4 */
+ "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C",
+ /* 5-9 */
+ "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331",
+ /* 10-14 */
+ "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416",
+ /* 15-19 */
+ "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716",
+ /* 20-24 */
+ "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408",
+ /* 25-29 */
+ "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d",
+ /* 30-34 */
+ "CX880", "CX881", "CX883", "CX882", "CX25840",
+ /* 35-38 */
+ "CX25841", "CX25842", "CX25843", "CX23418",
+};
- "Type 0x10","Type 0x11","Type 0x12","Type 0x13",
- "Type 0x14","Type 0x15","Type 0x16","Type 0x17",
- "Type 0x18","MSP4418","Type 0x1a","MSP4448",
- "Type 0x1c","Type 0x1d","Type 0x1e","Type 0x1f",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *decoderIC[] = {
+ /* 0-4 */
+ "None", "BT815", "BT817", "BT819", "BT815A",
+ /* 5-9 */
+ "BT817A", "BT819A", "BT827", "BT829", "BT848",
+ /* 10-14 */
+ "BT848A", "BT849A", "BT829A", "BT827A", "BT878",
+ /* 15-19 */
+ "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
+ /* 20-24 */
+ "CX880", "CX881", "CX883", "SAA7111", "SAA7113",
+ /* 25-29 */
+ "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
+ /* 30-31 */
+ "CX25843", "CX23418",
};
static int hasRadioTuner(int tunerType)
@@ -250,7 +287,8 @@ static int hasRadioTuner(int tunerType)
return 0;
}
-void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data)
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
+ unsigned char *eeprom_data)
{
/* ----------------------------------------------
** The hauppauge eeprom format is tagged
@@ -260,10 +298,11 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
**
** In our (ivtv) case we're interested in the following:
- ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
- ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
- ** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM)
- ** audio proc: tag [02].01 or [05].00 (lower nibble indexes lut?)
+ ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
+ ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
+ ** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM)
+ ** audio proc: tag [02].01 or [05].00 (mask with 0x7f)
+ ** decoder proc: tag [09].01)
** Fun info:
** model: tag [00].07-08 or [06].00-01
@@ -273,20 +312,24 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** # of inputs/outputs ???
*/
- int i, j, len, done, beenhere, tag, tuner = 0, t_format = 0;
- char *t_name = NULL, *t_fmt_name = NULL;
+ int i, j, len, done, beenhere, tag;
- dprintk(1, "%s\n",__FUNCTION__);
- tvee->revision = done = len = beenhere = 0;
- for (i = 0; !done && i < 256; i += len) {
- dprintk(2, "processing pos = %02x (%02x, %02x)\n",
- i, eeprom_data[i], eeprom_data[i + 1]);
+ int tuner1 = 0, t_format1 = 0;
+ char *t_name1 = NULL;
+ const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
+ int tuner2 = 0, t_format2 = 0;
+ char *t_name2 = NULL;
+ const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
+
+ memset(tvee, 0, sizeof(*tvee));
+ done = len = beenhere = 0;
+ for (i = 0; !done && i < 256; i += len) {
if (eeprom_data[i] == 0x84) {
len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
- i+=3;
+ i += 3;
} else if ((eeprom_data[i] & 0xf0) == 0x70) {
- if ((eeprom_data[i] & 0x08)) {
+ if (eeprom_data[i] & 0x08) {
/* verify checksum! */
done = 1;
break;
@@ -294,24 +337,30 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
len = eeprom_data[i] & 0x07;
++i;
} else {
- TVEEPROM_KERN_ERR("Encountered bad packet header [%02x]. "
+ tveeprom_warn("Encountered bad packet header [%02x]. "
"Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]);
return;
}
- dprintk(1, "%3d [%02x] ", len, eeprom_data[i]);
- for(j = 1; j < len; j++) {
- dprintk(1, "%02x ", eeprom_data[i + j]);
- }
- dprintk(1, "\n");
+ if (debug) {
+ tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1);
+ for(j = 1; j < len; j++) {
+ printk(" %02x", eeprom_data[i + j]);
+ }
+ printk("\n");
+ }
/* process by tag */
tag = eeprom_data[i];
switch (tag) {
case 0x00:
- tuner = eeprom_data[i+6];
- t_format = eeprom_data[i+5];
+ /* tag: 'Comprehensive' */
+ tuner1 = eeprom_data[i+6];
+ t_format1 = eeprom_data[i+5];
tvee->has_radio = eeprom_data[i+len-1];
+ /* old style tag, don't know how to detect
+ IR presence, mark as unknown. */
+ tvee->has_ir = 2;
tvee->model =
eeprom_data[i+8] +
(eeprom_data[i+9] << 8);
@@ -319,25 +368,43 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
(eeprom_data[i+11] << 8) +
(eeprom_data[i+12] << 16);
break;
+
case 0x01:
+ /* tag: 'SerialID' */
tvee->serial_number =
eeprom_data[i+6] +
(eeprom_data[i+7] << 8) +
(eeprom_data[i+8] << 16);
break;
+
case 0x02:
- tvee->audio_processor = eeprom_data[i+2] & 0x0f;
+ /* tag 'AudioInfo'
+ Note mask with 0x7F, high bit used on some older models
+ to indicate 4052 mux was removed in favor of using MSP
+ inputs directly. */
+ tvee->audio_processor = eeprom_data[i+2] & 0x7f;
break;
+
+ /* case 0x03: tag 'EEInfo' */
+
case 0x04:
+ /* tag 'SerialID2' */
tvee->serial_number =
eeprom_data[i+5] +
(eeprom_data[i+6] << 8) +
(eeprom_data[i+7] << 16);
break;
+
case 0x05:
- tvee->audio_processor = eeprom_data[i+1] & 0x0f;
+ /* tag 'Audio2'
+ Note mask with 0x7F, high bit used on some older models
+ to indicate 4052 mux was removed in favor of using MSP
+ inputs directly. */
+ tvee->audio_processor = eeprom_data[i+1] & 0x7f;
break;
+
case 0x06:
+ /* tag 'ModelRev' */
tvee->model =
eeprom_data[i+1] +
(eeprom_data[i+2] << 8);
@@ -345,27 +412,66 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
(eeprom_data[i+6] << 8) +
(eeprom_data[i+7] << 16);
break;
+
+ case 0x07:
+ /* tag 'Details': according to Hauppauge not interesting
+ on any PCI-era or later boards. */
+ break;
+
+ /* there is no tag 0x08 defined */
+
+ case 0x09:
+ /* tag 'Video' */
+ tvee->decoder_processor = eeprom_data[i + 1];
+ break;
+
case 0x0a:
- if(beenhere == 0) {
- tuner = eeprom_data[i+2];
- t_format = eeprom_data[i+1];
+ /* tag 'Tuner' */
+ if (beenhere == 0) {
+ tuner1 = eeprom_data[i+2];
+ t_format1 = eeprom_data[i+1];
beenhere = 1;
- break;
} else {
- break;
- }
+ /* a second (radio) tuner may be present */
+ tuner2 = eeprom_data[i+2];
+ t_format2 = eeprom_data[i+1];
+ if (t_format2 == 0) { /* not a TV tuner? */
+ tvee->has_radio = 1; /* must be radio */
+ }
+ }
+ break;
+
+ case 0x0b:
+ /* tag 'Inputs': according to Hauppauge this is specific
+ to each driver family, so no good assumptions can be
+ made. */
+ break;
+
+ /* case 0x0c: tag 'Balun' */
+ /* case 0x0d: tag 'Teletext' */
+
case 0x0e:
+ /* tag: 'Radio' */
tvee->has_radio = eeprom_data[i+1];
break;
+
+ case 0x0f:
+ /* tag 'IRInfo' */
+ tvee->has_ir = eeprom_data[i+1];
+ break;
+
+ /* case 0x10: tag 'VBIInfo' */
+ /* case 0x11: tag 'QCInfo' */
+ /* case 0x12: tag 'InfoBits' */
+
default:
- dprintk(1, "Not sure what to do with tag [%02x]\n", tag);
+ tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag);
/* dump the rest of the packet? */
}
-
}
if (!done) {
- TVEEPROM_KERN_ERR("Ran out of data!\n");
+ tveeprom_warn("Ran out of data!\n");
return;
}
@@ -377,47 +483,72 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
tvee->rev_str[4] = 0;
}
- if (hasRadioTuner(tuner) && !tvee->has_radio) {
- TVEEPROM_KERN_INFO("The eeprom says no radio is present, but the tuner type\n");
- TVEEPROM_KERN_INFO("indicates otherwise. I will assume that radio is present.\n");
+ if (hasRadioTuner(tuner1) && !tvee->has_radio) {
+ tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
+ tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
tvee->has_radio = 1;
}
- if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
- tvee->tuner_type = hauppauge_tuner[tuner].id;
- t_name = hauppauge_tuner[tuner].name;
+ if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+ tvee->tuner_type = hauppauge_tuner[tuner1].id;
+ t_name1 = hauppauge_tuner[tuner1].name;
} else {
- t_name = "<unknown>";
+ t_name1 = "unknown";
+ }
+
+ if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+ tvee->tuner2_type = hauppauge_tuner[tuner2].id;
+ t_name2 = hauppauge_tuner[tuner2].name;
+ } else {
+ t_name2 = "unknown";
}
tvee->tuner_formats = 0;
- t_fmt_name = "<none>";
- for (i = 0; i < 8; i++) {
- if (t_format & (1<<i)) {
+ tvee->tuner2_formats = 0;
+ for (i = j = 0; i < 8; i++) {
+ if (t_format1 & (1 << i)) {
tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
- /* yuck */
- t_fmt_name = hauppauge_tuner_fmt[i].name;
+ t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
}
+ if (t_format2 & (1 << i)) {
+ tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
+ t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
+ }
}
-
- TVEEPROM_KERN_INFO("Hauppauge: model = %d, rev = %s, serial# = %d\n",
- tvee->model,
- tvee->rev_str,
- tvee->serial_number);
- TVEEPROM_KERN_INFO("tuner = %s (idx = %d, type = %d)\n",
- t_name,
- tuner,
- tvee->tuner_type);
- TVEEPROM_KERN_INFO("tuner fmt = %s (eeprom = 0x%02x, v4l2 = 0x%08x)\n",
- t_fmt_name,
- t_format,
- tvee->tuner_formats);
-
- TVEEPROM_KERN_INFO("audio_processor = %s (type = %d)\n",
- STRM(sndtype,tvee->audio_processor),
+ tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
+ tvee->model, tvee->rev_str, tvee->serial_number);
+ tveeprom_info("tuner model is %s (idx %d, type %d)\n",
+ t_name1, tuner1, tvee->tuner_type);
+ tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+ t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3],
+ t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7],
+ t_format1);
+ if (tuner2) {
+ tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
+ t_name2, tuner2, tvee->tuner2_type);
+ }
+ if (t_format2) {
+ tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+ t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3],
+ t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7],
+ t_format2);
+ }
+ tveeprom_info("audio processor is %s (idx %d)\n",
+ STRM(audioIC, tvee->audio_processor),
tvee->audio_processor);
-
+ if (tvee->decoder_processor) {
+ tveeprom_info("decoder processor is %s (idx %d)\n",
+ STRM(decoderIC, tvee->decoder_processor),
+ tvee->decoder_processor);
+ }
+ if (tvee->has_ir == 2)
+ tveeprom_info("has %sradio\n",
+ tvee->has_radio ? "" : "no ");
+ else
+ tveeprom_info("has %sradio, has %sIR remote\n",
+ tvee->has_radio ? "" : "no ",
+ tvee->has_ir ? "" : "no ");
}
EXPORT_SYMBOL(tveeprom_hauppauge_analog);
@@ -429,40 +560,31 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
unsigned char buf;
int err;
- dprintk(1, "%s\n",__FUNCTION__);
buf = 0;
- if (1 != (err = i2c_master_send(c,&buf,1))) {
- printk(KERN_INFO "tveeprom(%s): Huh, no eeprom present (err=%d)?\n",
- c->name,err);
+ if (1 != (err = i2c_master_send(c, &buf, 1))) {
+ tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
return -1;
}
- if (len != (err = i2c_master_recv(c,eedata,len))) {
- printk(KERN_WARNING "tveeprom(%s): i2c eeprom read error (err=%d)\n",
- c->name,err);
+ if (len != (err = i2c_master_recv(c, eedata, len))) {
+ tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
return -1;
}
+ if (debug) {
+ int i;
+
+ tveeprom_info("full 256-byte eeprom dump:\n");
+ for (i = 0; i < len; i++) {
+ if (0 == (i % 16))
+ tveeprom_info("%02x:", i);
+ printk(" %02x", eedata[i]);
+ if (15 == (i % 16))
+ printk("\n");
+ }
+ }
return 0;
}
EXPORT_SYMBOL(tveeprom_read);
-#if 0
-int tveeprom_dump(unsigned char *eedata, int len)
-{
- int i;
-
- dprintk(1, "%s\n",__FUNCTION__);
- for (i = 0; i < len; i++) {
- if (0 == (i % 16))
- printk(KERN_INFO "tveeprom: %02x:",i);
- printk(" %02x",eedata[i]);
- if (15 == (i % 16))
- printk("\n");
- }
- return 0;
-}
-EXPORT_SYMBOL(tveeprom_dump);
-#endif /* 0 */
-
/* ----------------------------------------------------------------------- */
/* needed for ivtv.sf.net at the moment. Should go away in the long */
/* run, just call the exported tveeprom_* directly, there is no point in */
@@ -495,12 +617,13 @@ tveeprom_command(struct i2c_client *client,
buf = kmalloc(256,GFP_KERNEL);
memset(buf,0,256);
tveeprom_read(client,buf,256);
- tveeprom_hauppauge_analog(&eeprom,buf);
+ tveeprom_hauppauge_analog(client, &eeprom,buf);
kfree(buf);
eeprom_props[0] = eeprom.tuner_type;
eeprom_props[1] = eeprom.tuner_formats;
eeprom_props[2] = eeprom.model;
eeprom_props[3] = eeprom.revision;
+ eeprom_props[4] = eeprom.has_radio;
break;
default:
return -EINVAL;
@@ -515,8 +638,6 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
{
struct i2c_client *client;
- dprintk(1,"%s: id 0x%x @ 0x%x\n",__FUNCTION__,
- adapter->id, address << 1);
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (NULL == client)
return -ENOMEM;
@@ -533,8 +654,7 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
static int
tveeprom_attach_adapter (struct i2c_adapter *adapter)
{
- dprintk(1,"%s: id 0x%x\n",__FUNCTION__,adapter->id);
- if (adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adapter->id != I2C_HW_B_BT848)
return 0;
return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
}
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 51b99cdbf29e..d86e08ebddfc 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -1,5 +1,4 @@
/*
- * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
*/
#include <linux/module.h>
@@ -91,7 +90,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
strlcpy(info.id, "tv card", sizeof(info.id));
- strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+ strlcpy(info.name, client->name, sizeof(info.name));
info.modify_counter = 42 /* FIXME */;
if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
@@ -100,7 +99,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
strlcpy(info.id, "tv card", sizeof(info.id));
- strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+ strlcpy(info.name, client->name, sizeof(info.name));
if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -276,9 +275,9 @@ static int tvmixer_clients(struct i2c_client *client)
#else
/* TV card ??? */
switch (client->adapter->id) {
- case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+ case I2C_HW_SMBUS_VOODOO3:
+ case I2C_HW_B_BT848:
+ case I2C_HW_B_RIVA:
/* ok, have a look ... */
break;
default:
@@ -295,7 +294,7 @@ static int tvmixer_clients(struct i2c_client *client)
devices[i].dev = NULL;
devices[i].minor = -1;
printk("tvmixer: %s unregistered (#1)\n",
- i2c_clientname(client));
+ client->name);
return 0;
}
}
@@ -354,7 +353,7 @@ static void __exit tvmixer_cleanup_module(void)
if (devices[i].minor != -1) {
unregister_sound_mixer(devices[i].minor);
printk("tvmixer: %s unregistered (#2)\n",
- i2c_clientname(devices[i].dev));
+ devices[i].dev->name);
}
}
}
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 70ecbdb80277..59bb71381a1b 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1,5 +1,4 @@
/*
- * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
*
* Video for Linux Two
* Backward Compatibility Layer
@@ -604,9 +603,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
break;
}
-#if 0 /* FIXME */
- pict->depth = fmt2->fmt.pix.depth;
-#endif
pict->palette = pixelformat_to_palette(
fmt2->fmt.pix.pixelformat);
break;
@@ -707,13 +703,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
}
case VIDIOCSTUNER: /* select a tuner input */
{
-#if 0 /* FIXME */
- err = drv(inode, file, VIDIOC_S_INPUT, &i);
- if (err < 0)
- dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
-#else
err = 0;
-#endif
break;
}
case VIDIOCGFREQ: /* get frequency */
@@ -852,12 +842,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
err = 0;
break;
}
-#if 0
- case VIDIOCGMBUF:
- /* v4l2 drivers must implement that themself. The
- mmap() differences can't be translated fully
- transparent, thus there is no point to try that */
-#endif
case VIDIOCMCAPTURE: /* capture a frame */
{
struct video_mmap *mm = arg;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b5e0cf3448f4..597b8db35a13 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -84,20 +84,6 @@ MODULE_LICENSE("GPL");
* Video Standard Operations (contributed by Michael Schimek)
*/
-#if 0 /* seems to have no users */
-/* This is the recommended method to deal with the framerate fields. More
- sophisticated drivers will access the fields directly. */
-unsigned int
-v4l2_video_std_fps(struct v4l2_standard *vs)
-{
- if (vs->frameperiod.numerator > 0)
- return (((vs->frameperiod.denominator << 8) /
- vs->frameperiod.numerator) +
- (1 << 7)) / (1 << 8);
- return 0;
-}
-EXPORT_SYMBOL(v4l2_video_std_fps);
-#endif
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
@@ -213,10 +199,6 @@ char *v4l2_ioctl_names[256] = {
[_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
[_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
[_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
-#if 0
- [_IOC_NR(VIDIOC_G_COMP)] = "VIDIOC_G_COMP",
- [_IOC_NR(VIDIOC_S_COMP)] = "VIDIOC_S_COMP",
-#endif
[_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
[_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
[_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index 15f5bb486963..55f129e964eb 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -1,5 +1,4 @@
/*
- * $Id: video-buf-dvb.c,v 1.7 2004/12/09 12:51:35 kraxel Exp $
*
* some helper function for simple DVB cards which simply DMA the
* complete transport stream and let the computer sort everything else
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 5afdc7852610..574b8e36f3c6 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -1,5 +1,4 @@
/*
- * $Id: video-buf.c,v 1.18 2005/02/24 13:32:30 kraxel Exp $
*
* generic helper functions for video4linux capture buffers, to handle
* memory management and PCI DMA. Right now bttv + saa7134 use it.
@@ -268,10 +267,10 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
kfree(dma->pages);
dma->pages = NULL;
}
- if (dma->vmalloc) {
- vfree(dma->vmalloc);
- dma->vmalloc = NULL;
- }
+
+ vfree(dma->vmalloc);
+ dma->vmalloc = NULL;
+
if (dma->bus_addr) {
dma->bus_addr = 0;
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 76e8681d65c6..ed4394e854ab 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -1,80 +1,607 @@
/*
- * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys.
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
*
* This file is subject to the terms and conditions of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * Based on the previous version of the driver for 2.4 kernels by:
* Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
*/
-#include <linux/module.h>
+/*
+ * TODO:
+ * - remove "hacks" from memory allocation code and implement nopage()
+ * - check decimation, calculating and reporting image size when
+ * using decimation
+ * - check vino_acquire_input(), vino_set_input() and channel
+ * ownership handling
+ * - report VINO error-interrupts via ioctls ?
+ * - implement picture controls (all implemented?)
+ * - use macros for boolean values (?)
+ * - implement user mode buffers and overlay (?)
+ */
+
#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/wrapper.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
+#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.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 <asm/addrspace.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/pgtable.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+
#include <asm/paccess.h>
#include <asm/io.h>
#include <asm/sgi/ip22.h>
-#include <asm/sgi/hpc3.h>
#include <asm/sgi/mc.h>
#include "vino.h"
+#include "saa7191.h"
+#include "indycam.h"
+
+/* Uncomment the following line to get lots and lots of (mostly useless)
+ * debug info.
+ * Note that the debug output also slows down the driver significantly */
+// #define VINO_DEBUG
+
+#define VINO_MODULE_VERSION "0.0.3"
+#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3)
+
+MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
+MODULE_VERSION(VINO_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
-/* debugging? */
-#if 1
-#define DEBUG(x...) printk(x);
+#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags))
+#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags))
+
+#ifdef VINO_DEBUG
+#define dprintk(x...) printk("VINO: " x);
#else
-#define DEBUG(x...)
+#define dprintk(x...)
#endif
+#define VINO_NO_CHANNEL 0
+#define VINO_CHANNEL_A 1
+#define VINO_CHANNEL_B 2
+
+#define VINO_PAL_WIDTH 768
+#define VINO_PAL_HEIGHT 576
+#define VINO_NTSC_WIDTH 640
+#define VINO_NTSC_HEIGHT 480
+
+#define VINO_MIN_WIDTH 32
+#define VINO_MIN_HEIGHT 32
+
+#define VINO_CLIPPING_START_ODD_D1 1
+#define VINO_CLIPPING_START_ODD_PAL 1
+#define VINO_CLIPPING_START_ODD_NTSC 1
+
+#define VINO_CLIPPING_START_EVEN_D1 2
+#define VINO_CLIPPING_START_EVEN_PAL 2
+#define VINO_CLIPPING_START_EVEN_NTSC 2
+
+#define VINO_INPUT_CHANNEL_COUNT 3
+
+#define VINO_INPUT_NONE -1
+#define VINO_INPUT_COMPOSITE 0
+#define VINO_INPUT_SVIDEO 1
+#define VINO_INPUT_D1 2
+
+#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
+
+#define VINO_FIFO_THRESHOLD_DEFAULT 512
+
+/*#define VINO_FRAMEBUFFER_SIZE (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \
+ + 2 * PAGE_SIZE)*/
+#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
+ * VINO_PAL_HEIGHT * 4 \
+ + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
+
+#define VINO_FRAMEBUFFER_MAX_COUNT 8
+
+#define VINO_FRAMEBUFFER_UNUSED 0
+#define VINO_FRAMEBUFFER_IN_USE 1
+#define VINO_FRAMEBUFFER_READY 2
+
+#define VINO_QUEUE_ERROR -1
+#define VINO_QUEUE_MAGIC 0x20050125
+
+#define VINO_MEMORY_NONE 0
+#define VINO_MEMORY_MMAP 1
+#define VINO_MEMORY_USERPTR 2
+
+#define VINO_DUMMY_DESC_COUNT 4
+#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
+
+/* the number is the index for vino_data_formats */
+#define VINO_DATA_FMT_NONE -1
+#define VINO_DATA_FMT_GREY 0
+#define VINO_DATA_FMT_RGB332 1
+#define VINO_DATA_FMT_RGB32 2
+#define VINO_DATA_FMT_YUV 3
+//#define VINO_DATA_FMT_RGB24 4
+
+#define VINO_DATA_FMT_COUNT 4
+
+#define VINO_DATA_NORM_NONE -1
+#define VINO_DATA_NORM_NTSC 0
+#define VINO_DATA_NORM_PAL 1
+#define VINO_DATA_NORM_SECAM 2
+#define VINO_DATA_NORM_D1 3
+/* The following is a special entry that can be used to
+ * autodetect the norm. */
+#define VINO_DATA_NORM_AUTO 0xff
+
+#define VINO_DATA_NORM_COUNT 4
-/* VINO ASIC registers */
-struct sgi_vino *vino;
+/* Internal data structure definitions */
-static const char *vinostr = "VINO IndyCam/TV";
-static int threshold_a = 512;
-static int threshold_b = 512;
+struct vino_input {
+ char *name;
+ v4l2_std_id std;
+};
+
+struct vino_clipping {
+ unsigned int left, right, top, bottom;
+};
+
+struct vino_data_format {
+ /* the description */
+ char *description;
+ /* bytes per pixel */
+ unsigned int bpp;
+ /* V4L2 fourcc code */
+ __u32 pixelformat;
+ /* V4L2 colorspace (duh!) */
+ enum v4l2_colorspace colorspace;
+};
+
+struct vino_data_norm {
+ char *description;
+ unsigned int width, height;
+ struct vino_clipping odd;
+ struct vino_clipping even;
+
+ v4l2_std_id std;
+ unsigned int fps_min, fps_max;
+ __u32 framelines;
+};
+
+struct vino_descriptor_table {
+ /* the number of PAGE_SIZE sized pages in the buffer */
+ unsigned int page_count;
+ /* virtual (kmalloc'd) pointers to the actual data
+ * (in PAGE_SIZE chunks, used with mmap streaming) */
+ unsigned long *virtual;
+
+ /* cpu address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ unsigned long *dma_cpu;
+ /* dma address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ dma_addr_t dma;
+};
+
+struct vino_framebuffer {
+ /* identifier nubmer */
+ unsigned int id;
+ /* the length of the whole buffer */
+ unsigned int size;
+ /* the length of actual data in buffer */
+ unsigned int data_size;
+ /* the data format */
+ unsigned int data_format;
+ /* the state of buffer data */
+ unsigned int state;
+ /* is the buffer mapped in user space? */
+ unsigned int map_count;
+ /* memory offset for mmap() */
+ unsigned int offset;
+ /* frame counter */
+ unsigned int frame_counter;
+ /* timestamp (written when image capture finishes) */
+ struct timeval timestamp;
+
+ struct vino_descriptor_table desc_table;
+
+ spinlock_t state_lock;
+};
-struct vino_device {
- struct video_device vdev;
-#define VINO_CHAN_A 1
-#define VINO_CHAN_B 2
- int chan;
+struct vino_framebuffer_fifo {
+ unsigned int length;
+
+ unsigned int used;
+ unsigned int head;
+ unsigned int tail;
+
+ unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT];
+};
+
+struct vino_framebuffer_queue {
+ unsigned int magic;
+
+ /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
+ unsigned int type;
+ unsigned int length;
+
+ /* data field of in and out contain index numbers for buffer */
+ struct vino_framebuffer_fifo in;
+ struct vino_framebuffer_fifo out;
+
+ struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT];
+
+ spinlock_t queue_lock;
+ struct semaphore queue_sem;
+ wait_queue_head_t frame_wait_queue;
+};
+
+struct vino_channel_settings {
+ unsigned int channel;
+
+ int input;
+ unsigned int data_format;
+ unsigned int data_norm;
+ struct vino_clipping clipping;
+ unsigned int decimation;
+ unsigned int line_size;
+ unsigned int alpha;
+ unsigned int fps;
+ unsigned int framert_reg;
+
+ unsigned int fifo_threshold;
+
+ struct vino_framebuffer_queue fb_queue;
+
+ /* number of the current field */
+ unsigned int field;
+
+ /* read in progress */
+ int reading;
+ /* streaming is active */
+ int streaming;
+ /* the driver is currently processing the queue */
+ int capturing;
+
+ struct semaphore sem;
+ spinlock_t capture_lock;
+
+ unsigned int users;
+
+ /* V4L support */
+ struct video_device *v4l_device;
};
struct vino_client {
+ /* the channel which owns this client:
+ * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+ unsigned int owner;
struct i2c_client *driver;
- int owner;
};
-struct vino_video {
- struct vino_device chA;
- struct vino_device chB;
+struct vino_settings {
+ struct vino_channel_settings a;
+ struct vino_channel_settings b;
struct vino_client decoder;
struct vino_client camera;
- struct semaphore input_lock;
+ /* a lock for vino register access */
+ spinlock_t vino_lock;
+ /* a lock for channel input changes */
+ spinlock_t input_lock;
- /* Loaded into VINO descriptors to clear End Of Descriptors table
- * interupt condition */
unsigned long dummy_page;
- unsigned int dummy_buf[4] __attribute__((aligned(8)));
+ struct vino_descriptor_table dummy_desc_table;
};
-static struct vino_video *Vino;
+/* Module parameters */
+
+/*
+ * Using vino_pixel_conversion the ARGB32-format pixels supplied
+ * by the VINO chip can be converted to more common formats
+ * like RGBA32 (or probably RGB24 in the future). This way we
+ * can give out data that can be specified correctly with
+ * the V4L2-definitions.
+ *
+ * The pixel format is specified as RGBA32 when no conversion
+ * is used.
+ *
+ * Note that this only affects the 32-bit bit depth.
+ *
+ * Use non-zero value to enable conversion.
+ */
+static int vino_pixel_conversion = 0;
+module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+MODULE_PARM_DESC(pixelconv,
+ "enable pixel conversion (non-zero value enables)");
+
+/* Internal data structures */
+
+static struct sgi_vino *vino;
+
+static struct vino_settings *vino_drvdata;
+
+static const char *vino_driver_name = "vino";
+static const char *vino_driver_description = "SGI VINO";
+static const char *vino_bus_name = "GIO64 bus";
+static const char *vino_v4l_device_name_a = "SGI VINO Channel A";
+static const char *vino_v4l_device_name_b = "SGI VINO Channel B";
+
+static const struct vino_input vino_inputs[] = {
+ {
+ .name = "Composite",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ },{
+ .name = "S-Video",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ },{
+ .name = "D1 (IndyCam)",
+ .std = V4L2_STD_NTSC,
+ }
+};
+
+static const struct vino_data_format vino_data_formats[] = {
+ {
+ .description = "8-bit greyscale",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_GREY,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ },{
+ .description = "8-bit dithered RGB 3-3-2",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_RGB332,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },{
+ .description = "32-bit RGB",
+ .bpp = 4,
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },{
+ .description = "YUV 4:2:2",
+ .bpp = 4,
+ .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ }/*,{
+ .description = "24-bit RGB",
+ .bpp = 3,
+ .pixelformat = V4L2_PIX_FMT_RGB24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }*/
+};
+
+static const struct vino_data_norm vino_data_norms[] = {
+ {
+ .description = "NTSC",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ },{
+ .description = "PAL",
+ .std = V4L2_STD_PAL,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ },{
+ .description = "SECAM",
+ .std = V4L2_STD_SECAM,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ },{
+ .description = "NTSC (D1 input)",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ }
+};
+
+#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
+
+struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic Gain Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AGC_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic White Balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AWB_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = INDYCAM_GAIN_MIN,
+ .maximum = INDYCAM_GAIN_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAIN_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Saturation",
+ .minimum = INDYCAM_RED_SATURATION_MIN,
+ .maximum = INDYCAM_RED_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_SATURATION_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE + 1,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Saturation",
+ .minimum = INDYCAM_BLUE_SATURATION_MIN,
+ .maximum = INDYCAM_BLUE_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = INDYCAM_RED_BALANCE_MIN,
+ .maximum = INDYCAM_RED_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_BALANCE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = INDYCAM_BLUE_BALANCE_MIN,
+ .maximum = INDYCAM_BLUE_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Shutter Control",
+ .minimum = INDYCAM_SHUTTER_MIN,
+ .maximum = INDYCAM_SHUTTER_MAX,
+ .step = 1,
+ .default_value = INDYCAM_SHUTTER_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_GAMMA,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gamma",
+ .minimum = INDYCAM_GAMMA_MIN,
+ .maximum = INDYCAM_GAMMA_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAMMA_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ }
+};
+
+#define VINO_SAA7191_V4L2_CONTROL_COUNT 2
+
+struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = SAA7191_HUE_MIN,
+ .maximum = SAA7191_HUE_MAX,
+ .step = 1,
+ .default_value = SAA7191_HUE_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ },{
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "VTR Time Constant",
+ .minimum = SAA7191_VTRC_MIN,
+ .maximum = SAA7191_VTRC_MAX,
+ .step = 1,
+ .default_value = SAA7191_VTRC_DEFAULT,
+ .flags = 0,
+ .reserved = { 0, 0 },
+ }
+};
+
+/* VINO I2C bus functions */
unsigned i2c_vino_getctrl(void *data)
{
@@ -112,49 +639,49 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data =
*/
static int i2c_vino_client_reg(struct i2c_client *client)
{
- int res = 0;
+ int ret = 0;
- down(&Vino->input_lock);
+ spin_lock(&vino_drvdata->input_lock);
switch (client->driver->id) {
case I2C_DRIVERID_SAA7191:
- if (Vino->decoder.driver)
- res = -EBUSY;
+ if (vino_drvdata->decoder.driver)
+ ret = -EBUSY;
else
- Vino->decoder.driver = client;
+ vino_drvdata->decoder.driver = client;
break;
case I2C_DRIVERID_INDYCAM:
- if (Vino->camera.driver)
- res = -EBUSY;
+ if (vino_drvdata->camera.driver)
+ ret = -EBUSY;
else
- Vino->camera.driver = client;
+ vino_drvdata->camera.driver = client;
break;
default:
- res = -ENODEV;
+ ret = -ENODEV;
}
- up(&Vino->input_lock);
+ spin_unlock(&vino_drvdata->input_lock);
- return res;
+ return ret;
}
static int i2c_vino_client_unreg(struct i2c_client *client)
{
- int res = 0;
+ int ret = 0;
- down(&Vino->input_lock);
- if (client == Vino->decoder.driver) {
- if (Vino->decoder.owner)
- res = -EBUSY;
+ spin_lock(&vino_drvdata->input_lock);
+ if (client == vino_drvdata->decoder.driver) {
+ if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
+ ret = -EBUSY;
else
- Vino->decoder.driver = NULL;
- } else if (client == Vino->camera.driver) {
- if (Vino->camera.owner)
- res = -EBUSY;
+ vino_drvdata->decoder.driver = NULL;
+ } else if (client == vino_drvdata->camera.driver) {
+ if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
+ ret = -EBUSY;
else
- Vino->camera.driver = NULL;
+ vino_drvdata->camera.driver = NULL;
}
- up(&Vino->input_lock);
+ spin_unlock(&vino_drvdata->input_lock);
- return res;
+ return ret;
}
static struct i2c_adapter vino_i2c_adapter =
@@ -176,172 +703,3591 @@ static int vino_i2c_del_bus(void)
return i2c_sgi_del_bus(&vino_i2c_adapter);
}
+static int i2c_camera_command(unsigned int cmd, void *arg)
+{
+ return vino_drvdata->camera.driver->
+ driver->command(vino_drvdata->camera.driver,
+ cmd, arg);
+}
+
+static int i2c_decoder_command(unsigned int cmd, void *arg)
+{
+ return vino_drvdata->decoder.driver->
+ driver->command(vino_drvdata->decoder.driver,
+ cmd, arg);
+}
+
+/* VINO framebuffer/DMA descriptor management */
+
+static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
+ unsigned int count)
+{
+ unsigned int i;
+
+ dprintk("vino_free_buffer_with_count(): count = %d\n", count);
+
+ for (i = 0; i < count; i++) {
+ mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i]));
+ dma_unmap_single(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ free_page(fb->desc_table.virtual[i]);
+ }
+
+ dma_free_coherent(NULL,
+ VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
+ sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
+ fb->desc_table.dma);
+ kfree(fb->desc_table.virtual);
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+}
+
+static void vino_free_buffer(struct vino_framebuffer *fb)
+{
+ vino_free_buffer_with_count(fb, fb->desc_table.page_count);
+}
+
+static int vino_allocate_buffer(struct vino_framebuffer *fb,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_allocate_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE) + 4) & ~3;
+
+ dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual = (unsigned long *)
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+ fb->data_format = VINO_DATA_FMT_NONE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+
+#if 0
+/* user buffers not fully implemented yet */
+static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
+ void *user,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_prepare_user_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE)) & ~3;
+
+ dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual = (unsigned long *)
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ mem_map_reserve(virt_to_page(fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+#endif
+
+static void vino_sync_buffer(struct vino_framebuffer *fb)
+{
+ int i;
+
+ dprintk("vino_sync_buffer():\n");
+
+ for (i = 0; i < fb->desc_table.page_count; i++)
+ dma_sync_single(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+}
+
+/* Framebuffer fifo functions (need to be locked externally) */
+
+static void vino_fifo_init(struct vino_framebuffer_fifo *f,
+ unsigned int length)
+{
+ f->length = 0;
+ f->used = 0;
+ f->head = 0;
+ f->tail = 0;
+
+ if (length > VINO_FRAMEBUFFER_MAX_COUNT)
+ length = VINO_FRAMEBUFFER_MAX_COUNT;
+
+ f->length = length;
+}
+
+/* returns true/false */
+static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+ unsigned int i;
+ for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
+ if (f->data[i] == id)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* returns true/false */
+static int vino_fifo_full(struct vino_framebuffer_fifo *f)
+{
+ return (f->used == f->length);
+}
+
+static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
+{
+ return f->used;
+}
-static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
{
+ if (id >= f->length) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (vino_fifo_has_id(f, id)) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (f->used < f->length) {
+ f->data[f->tail] = id;
+ f->tail = (f->tail + 1) % f->length;
+ f->used++;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
}
-static int vino_open(struct video_device *dev, int flags)
+static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
return 0;
}
-static void vino_close(struct video_device *dev)
+static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ f->head = (f->head + 1) % f->length;
+ f->used--;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
}
-static int vino_mmap(struct video_device *dev, const char *adr,
- unsigned long size)
+/* Framebuffer queue functions */
+
+/* execute with queue_lock locked */
+static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
+ unsigned int length)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ unsigned int i;
- return -EINVAL;
+ q->length = 0;
+ memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
+ memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
+ for (i = 0; i < length; i++) {
+ dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
+ i);
+ vino_free_buffer(q->buffer[i]);
+ kfree(q->buffer[i]);
+ }
+
+ q->type = VINO_MEMORY_NONE;
+ q->magic = 0;
}
-static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static void vino_queue_free(struct vino_framebuffer_queue *q)
{
- struct vino_device *videv = (struct vino_device *)dev;
+ dprintk("vino_queue_free():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC)
+ return;
+ if (q->type != VINO_MEMORY_MMAP)
+ return;
+
+ down(&q->queue_sem);
+
+ vino_queue_free_with_count(q, q->length);
+
+ up(&q->queue_sem);
+}
+
+static int vino_queue_init(struct vino_framebuffer_queue *q,
+ unsigned int *length)
+{
+ unsigned int i;
+ int ret = 0;
+
+ dprintk("vino_queue_init(): length = %d\n", *length);
+
+ if (q->magic == VINO_QUEUE_MAGIC) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (q->type != VINO_MEMORY_NONE) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (*length < 1)
+ return -EINVAL;
+
+ down(&q->queue_sem);
+
+ if (*length > VINO_FRAMEBUFFER_MAX_COUNT)
+ *length = VINO_FRAMEBUFFER_MAX_COUNT;
+
+ q->length = 0;
+
+ for (i = 0; i < *length; i++) {
+ dprintk("vino_queue_init(): allocating buffer %d\n", i);
+ q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
+ GFP_KERNEL);
+ if (!q->buffer[i]) {
+ dprintk("vino_queue_init(): kmalloc() failed\n");
+ ret = -ENOMEM;
+ break;
+ }
+
+ ret = vino_allocate_buffer(q->buffer[i],
+ VINO_FRAMEBUFFER_SIZE);
+ if (ret) {
+ kfree(q->buffer[i]);
+ dprintk("vino_queue_init(): "
+ "vino_allocate_buffer() failed\n");
+ break;
+ }
+
+ q->buffer[i]->id = i;
+ if (i > 0) {
+ q->buffer[i]->offset = q->buffer[i - 1]->offset +
+ q->buffer[i - 1]->size;
+ } else {
+ q->buffer[i]->offset = 0;
+ }
+
+ spin_lock_init(&q->buffer[i]->state_lock);
+
+ dprintk("vino_queue_init(): buffer = %d, offset = %d, "
+ "size = %d\n", i, q->buffer[i]->offset,
+ q->buffer[i]->size);
+ }
+
+ if (ret) {
+ vino_queue_free_with_count(q, i);
+ *length = 0;
+ } else {
+ q->length = *length;
+ vino_fifo_init(&q->in, q->length);
+ vino_fifo_init(&q->out, q->length);
+ q->type = VINO_MEMORY_MMAP;
+ q->magic = VINO_QUEUE_MAGIC;
+ }
+
+ up(&q->queue_sem);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_add(struct
+ vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned int total;
+ unsigned long flags;
+
+ dprintk("vino_queue_add(): id = %d\n", id);
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ /* not needed?: if (vino_fifo_full(&q->out)) {
+ goto out;
+ }*/
+ /* check that outgoing queue isn't already full
+ * (or that it won't become full) */
+ total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+ if (total >= q->length)
+ goto out;
+
+ if (vino_fifo_enqueue(&q->in, id))
+ goto out;
+
+ ret = q->buffer[id];
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_transfer(struct
+ vino_framebuffer_queue *q)
+{
+ struct vino_framebuffer *ret = NULL;
+ struct vino_framebuffer *fb;
+ int id;
+ unsigned long flags;
+
+ dprintk("vino_queue_transfer():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ // now this actually removes an entry from the incoming queue
+ if (vino_fifo_dequeue(&q->in, &id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_transfer(): id = %d\n", id);
+ fb = q->buffer[id];
+
+ // we have already checked that the outgoing queue is not full, but...
+ if (vino_fifo_enqueue(&q->out, id)) {
+ printk(KERN_ERR "vino_queue_transfer(): "
+ "outgoing queue is full, this shouldn't happen!\n");
+ goto out;
+ }
+
+ ret = fb;
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->in, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->out, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->in);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_total(struct vino_framebuffer_queue *q,
+ unsigned int *total)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_peek(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_peek(&q->in, id)) {
+ goto out;
+ }
+
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_remove(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+ dprintk("vino_queue_remove():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_dequeue(&q->out, id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_remove(): id = %d\n", *id);
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct
+vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ ret = q->buffer[id];
+ out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
+{
+ unsigned int length = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return length;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ length = q->length;
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return length;
+}
+
+static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
+{
+ unsigned int i;
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ for (i = 0; i < q->length; i++) {
+ if (q->buffer[i]->map_count > 0) {
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* VINO functions */
+
+/* execute with input_lock locked */
+static void vino_update_line_size(struct vino_channel_settings *vcs)
+{
+ unsigned int w = vcs->clipping.right - vcs->clipping.left;
+ unsigned int d = vcs->decimation;
+ unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
+ unsigned int lsize;
+
+ dprintk("update_line_size(): before: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+ /* line size must be multiple of 8 bytes */
+ lsize = (bpp * (w / d)) & ~7;
+ w = (lsize / bpp) * d;
+
+ vcs->clipping.right = vcs->clipping.left + w;
+ vcs->line_size = lsize;
+ dprintk("update_line_size(): after: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_clipping(struct vino_channel_settings *vcs,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ unsigned int maxwidth, maxheight;
+ unsigned int d;
+
+ maxwidth = vino_data_norms[vcs->data_norm].width;
+ maxheight = vino_data_norms[vcs->data_norm].height;
+ d = vcs->decimation;
+
+ y &= ~1; /* odd/even fields */
+
+ if (x > maxwidth) {
+ x = 0;
+ }
+ if (y > maxheight) {
+ y = 0;
+ }
+
+ if (((w / d) < VINO_MIN_WIDTH)
+ || ((h / d) < VINO_MIN_HEIGHT)) {
+ w = VINO_MIN_WIDTH * d;
+ h = VINO_MIN_HEIGHT * d;
+ }
+
+ if ((x + w) > maxwidth) {
+ w = maxwidth - x;
+ if ((w / d) < VINO_MIN_WIDTH)
+ x = maxwidth - VINO_MIN_WIDTH * d;
+ }
+ if ((y + h) > maxheight) {
+ h = maxheight - y;
+ if ((h / d) < VINO_MIN_HEIGHT)
+ y = maxheight - VINO_MIN_HEIGHT * d;
+ }
+
+ vcs->clipping.left = x;
+ vcs->clipping.top = y;
+ vcs->clipping.right = x + w;
+ vcs->clipping.bottom = y + h;
+
+ vino_update_line_size(vcs);
+
+ dprintk("clipping %d, %d, %d, %d / %d - %d\n",
+ vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
+ vcs->clipping.bottom, vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_clipping(struct vino_channel_settings *vcs)
+{
+ vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
+ vino_data_norms[vcs->data_norm].height);
+}
+
+/* execute with input_lock locked */
+static void vino_set_scaling(struct vino_channel_settings *vcs,
+ unsigned int w, unsigned int h)
+{
+ unsigned int x, y, curw, curh, d;
+
+ x = vcs->clipping.left;
+ y = vcs->clipping.top;
+ curw = vcs->clipping.right - vcs->clipping.left;
+ curh = vcs->clipping.bottom - vcs->clipping.top;
+
+ d = max(curw / w, curh / h);
+
+ dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
+ w, h, curw, curh, d);
+
+ if (d < 1) {
+ d = 1;
+ }
+ if (d > 8) {
+ d = 8;
+ }
+
+ vcs->decimation = d;
+ vino_set_clipping(vcs, x, y, w * d, h * d);
+
+ dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
+ vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
+ vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_reset_scaling(struct vino_channel_settings *vcs)
+{
+ vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
+ vcs->clipping.bottom - vcs->clipping.top);
+}
+
+/* execute with input_lock locked */
+static void vino_set_framerate(struct vino_channel_settings *vcs,
+ unsigned int fps)
+{
+ unsigned int mask;
+
+ switch (vcs->data_norm) {
+ case VINO_DATA_NORM_NTSC:
+ case VINO_DATA_NORM_D1:
+ fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 6:
+ mask = 0x003;
+ break;
+ case 12:
+ mask = 0x0c3;
+ break;
+ case 18:
+ mask = 0x333;
+ break;
+ case 24:
+ mask = 0x3ff;
+ break;
+ case 30:
+ mask = 0xfff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask);
+ break;
+ case VINO_DATA_NORM_PAL:
+ case VINO_DATA_NORM_SECAM:
+ fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 5:
+ mask = 0x003;
+ break;
+ case 10:
+ mask = 0x0c3;
+ break;
+ case 15:
+ mask = 0x333;
+ break;
+ case 20:
+ mask = 0x0ff;
+ break;
+ case 25:
+ mask = 0x3ff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
+ break;
+ }
+
+ vcs->fps = fps;
+}
+
+/* execute with input_lock locked */
+static void vino_set_default_framerate(struct vino_channel_settings *vcs)
+{
+ vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
+}
+
+/*
+ * Prepare VINO for DMA transfer...
+ * (execute only with vino_lock and input_lock locked)
+ */
+static int vino_dma_setup(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ u32 ctrl, intr;
+ struct sgi_vino_channel *ch;
+ const struct vino_data_norm *norm;
+
+ dprintk("vino_dma_setup():\n");
+
+ vcs->field = 0;
+ fb->frame_counter = 0;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+ norm = &vino_data_norms[vcs->data_norm];
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ /* VINO line size register is set 8 bytes less than actual */
+ ch->line_size = vcs->line_size - 8;
+
+ /* let VINO know where to transfer data */
+ ch->start_desc_tbl = fb->desc_table.dma;
+ ch->next_4_desc = fb->desc_table.dma;
+
+ /* give vino time to fetch the first four descriptors, 5 usec
+ * should be more than enough time */
+ udelay(VINO_DESC_FETCH_DELAY);
+
+ /* set the alpha register */
+ ch->alpha = vcs->alpha;
+
+ /* set clipping registers */
+ ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.top / 2) |
+ VINO_CLIP_X(vcs->clipping.left);
+ ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_X(vcs->clipping.right);
+ /* FIXME: end-of-field bug workaround
+ VINO_CLIP_X(VINO_PAL_WIDTH);
+ */
+
+ /* set the size of actual content in the buffer (DECIMATION !) */
+ fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation) *
+ ((vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation) *
+ vino_data_formats[vcs->data_format].bpp;
+
+ ch->frame_rate = vcs->framert_reg;
+
+ ctrl = vino->control;
+ intr = vino->intr_status;
+
+ if (vcs->channel == VINO_CHANNEL_A) {
+ /* All interrupt conditions for this channel was cleared
+ * so clear the interrupt status register and enable
+ * interrupts */
+ intr &= ~VINO_INTSTAT_A;
+ ctrl |= VINO_CTRL_A_INT;
+
+ /* enable synchronization */
+ ctrl |= VINO_CTRL_A_SYNC_ENBL;
+
+ /* enable frame assembly */
+ ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
+
+ /* set decimation used */
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_A_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_A_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_A_DEC_SCALE_SHIFT;
+ }
+
+ /* select input interface */
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_A_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_A_SELECT;
+
+ /* palette */
+ ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
+ VINO_CTRL_A_DITHER);
+ } else {
+ intr &= ~VINO_INTSTAT_B;
+ ctrl |= VINO_CTRL_B_INT;
+
+ ctrl |= VINO_CTRL_B_SYNC_ENBL;
+ ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
+
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_B_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_B_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_B_DEC_SCALE_SHIFT;
+
+ }
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_B_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_B_SELECT;
+
+ ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
+ VINO_CTRL_B_DITHER);
+ }
+
+ /* set palette */
+ fb->data_format = vcs->data_format;
+
+ switch (vcs->data_format) {
+ case VINO_DATA_FMT_GREY:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
+ break;
+ case VINO_DATA_FMT_RGB32:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
+ break;
+ case VINO_DATA_FMT_YUV:
+ /* nothing needs to be done */
+ break;
+ case VINO_DATA_FMT_RGB332:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
+ VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
+ break;
+ }
+
+ vino->intr_status = intr;
+ vino->control = ctrl;
+
+ return 0;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_start(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ dprintk("vino_dma_start():\n");
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
+ vino->control = ctrl;
+}
+
+/* (execute only with vino_lock locked) */
+static void vino_dma_stop(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+ ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
+ vino->control = ctrl;
+ dprintk("vino_dma_stop():\n");
+}
+
+/*
+ * Load dummy page to descriptor registers. This prevents generating of
+ * spurious interrupts. (execute only with vino_lock locked)
+ */
+static void vino_clear_interrupt(struct vino_channel_settings *vcs)
+{
+ struct sgi_vino_channel *ch;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
+ ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
+
+ udelay(VINO_DESC_FETCH_DELAY);
+ dprintk("channel %c clear interrupt condition\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
+}
+
+static int vino_capture(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags, flags2;
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ err = -EBUSY;
+ fb->state = VINO_FRAMEBUFFER_IN_USE;
+
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
+
+ vino_dma_setup(vcs, fb);
+ vino_dma_start(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ return err;
+}
+
+static
+struct vino_framebuffer *vino_capture_enqueue(struct
+ vino_channel_settings *vcs,
+ unsigned int index)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ dprintk("vino_capture_enqueue():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ fb = vino_queue_add(&vcs->fb_queue, index);
+ if (fb == NULL) {
+ dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
+ "queue full?\n");
+ goto out;
+ }
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return fb;
+}
+
+static int vino_capture_next(struct vino_channel_settings *vcs, int start)
+{
+ struct vino_framebuffer *fb;
+ unsigned int incoming, id;
+ int err = 0;
+ unsigned long flags, flags2;
+
+ dprintk("vino_capture_next():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ if (start) {
+ /* start capture only if capture isn't in progress already */
+ if (vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+
+ } else {
+ /* capture next frame:
+ * stop capture if capturing is not set */
+ if (!vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+ }
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_capture_next(): vino_queue_get_incoming() "
+ "failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+ if (incoming == 0) {
+ dprintk("vino_capture_next(): no buffers available\n");
+ goto out;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &id);
+ if (fb == NULL) {
+ dprintk("vino_capture_next(): vino_queue_peek() failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ spin_lock_irqsave(&fb->state_lock, flags2);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ spin_unlock_irqrestore(&fb->state_lock, flags2);
+
+ if (start) {
+ vcs->capturing = 1;
+ }
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ err = vino_capture(vcs, fb);
+
+ return err;
+
+out:
+ vcs->capturing = 0;
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return err;
+}
+
+static int vino_is_capturing(struct vino_channel_settings *vcs)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ ret = vcs->capturing;
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return ret;
+}
+
+/* waits until a frame is captured */
+static int vino_wait_for_frame(struct vino_channel_settings *vcs)
+{
+ wait_queue_t wait;
+ int err = 0;
+
+ dprintk("vino_wait_for_frame():\n");
+
+ init_waitqueue_entry(&wait, current);
+ /* add ourselves into wait queue */
+ add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+ /* and set current state */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* to ensure that schedule_timeout will return immediately
+ * if VINO interrupt was triggred meanwhile */
+ schedule_timeout(HZ / 10);
+
+ if (signal_pending(current))
+ err = -EINTR;
+
+ remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+ dprintk("vino_wait_for_frame(): waiting for frame %s\n",
+ err ? "failed" : "ok");
+
+ return err;
+}
+
+/* the function assumes that PAGE_SIZE % 4 == 0 */
+static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
+ unsigned char *pageptr;
+ unsigned int page, i;
+ unsigned char a;
+
+ for (page = 0; page < fb->desc_table.page_count; page++) {
+ pageptr = (unsigned char *)fb->desc_table.virtual[page];
+
+ for (i = 0; i < PAGE_SIZE; i += 4) {
+ a = pageptr[0];
+ pageptr[0] = pageptr[3];
+ pageptr[1] = pageptr[2];
+ pageptr[2] = pageptr[1];
+ pageptr[3] = a;
+ pageptr += 4;
+ }
+ }
+}
+
+/* checks if the buffer is in correct state and syncs data */
+static int vino_check_buffer(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags;
+
+ dprintk("vino_check_buffer():\n");
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ switch (fb->state) {
+ case VINO_FRAMEBUFFER_IN_USE:
+ err = -EIO;
+ break;
+ case VINO_FRAMEBUFFER_READY:
+ vino_sync_buffer(fb);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (!err) {
+ if (vino_pixel_conversion
+ && (fb->data_format == VINO_DATA_FMT_RGB32)) {
+ vino_convert_to_rgba(fb);
+ }
+ } else if (err && (err != -EINVAL)) {
+ dprintk("vino_check_buffer(): buffer not ready\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+ }
+
+ return err;
+}
+
+/* forcefully terminates capture */
+static void vino_capture_stop(struct vino_channel_settings *vcs)
+{
+ unsigned int incoming = 0, outgoing = 0, id;
+ unsigned long flags, flags2;
+
+ dprintk("vino_capture_stop():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ /* unset capturing to stop queue processing */
+ vcs->capturing = 0;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
+
+ /* remove all items from the queue */
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ while (incoming > 0) {
+ vino_queue_transfer(&vcs->fb_queue);
+
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ }
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ while (outgoing > 0) {
+ vino_queue_remove(&vcs->fb_queue, &id);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+}
+
+static int vino_capture_failed(struct vino_channel_settings *vcs)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+ unsigned int i;
+ int ret;
+
+ dprintk("vino_capture_failed():\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
+ if (ret == VINO_QUEUE_ERROR) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+ if (i == 0) {
+ /* no buffers to process */
+ return 0;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &i);
+ if (fb == NULL) {
+ dprintk("vino_queue_peek() failed\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ vino_queue_transfer(&vcs->fb_queue);
+ vino_queue_remove(&vcs->fb_queue, &i);
+ /* we should actually discard the newest frame,
+ * but who cares ... */
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ return 0;
+}
+
+static void vino_frame_done(struct vino_channel_settings *vcs,
+ unsigned int fc)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ fb = vino_queue_transfer(&vcs->fb_queue);
+ if (!fb) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ fb->frame_counter = fc;
+ do_gettimeofday(&fb->timestamp);
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ fb->state = VINO_FRAMEBUFFER_READY;
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ wake_up(&vcs->fb_queue.frame_wait_queue);
+
+ vino_capture_next(vcs, 0);
+}
+
+static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 intr;
+ unsigned int fc_a, fc_b;
+ int done_a = 0;
+ int done_b = 0;
+
+ spin_lock(&vino_drvdata->vino_lock);
+
+ intr = vino->intr_status;
+ fc_a = vino->a.field_counter / 2;
+ fc_b = vino->b.field_counter / 2;
+
+ // TODO: handle error-interrupts in some special way ?
+
+ if (intr & VINO_INTSTAT_A) {
+ if (intr & VINO_INTSTAT_A_EOF) {
+ vino_drvdata->a.field++;
+ if (vino_drvdata->a.field > 1) {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ vino_drvdata->a.field = 0;
+ done_a = 1;
+ }
+ dprintk("intr: channel A end-of-field interrupt: "
+ "%04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ done_a = 1;
+ dprintk("channel A error interrupt: %04x\n", intr);
+ }
+ }
+ if (intr & VINO_INTSTAT_B) {
+ if (intr & VINO_INTSTAT_B_EOF) {
+ vino_drvdata->b.field++;
+ if (vino_drvdata->b.field > 1) {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ vino_drvdata->b.field = 0;
+ done_b = 1;
+ }
+ dprintk("intr: channel B end-of-field interrupt: "
+ "%04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ done_b = 1;
+ dprintk("channel B error interrupt: %04x\n", intr);
+ }
+ }
+
+ /* always remember to clear interrupt status */
+ vino->intr_status = ~intr;
+
+ spin_unlock(&vino_drvdata->vino_lock);
+
+ if (done_a) {
+ vino_frame_done(&vino_drvdata->a, fc_a);
+ dprintk("channel A frame done, interrupt: %d\n", intr);
+ }
+ if (done_b) {
+ vino_frame_done(&vino_drvdata->b, fc_b);
+ dprintk("channel B frame done, interrupt: %d\n", intr);
+ }
- return -EINVAL;
+ return IRQ_HANDLED;
}
-static const struct video_device vino_device = {
+/* VINO video input management */
+
+static int vino_get_saa7191_input(int input)
+{
+ switch (input) {
+ case VINO_INPUT_COMPOSITE:
+ return SAA7191_INPUT_COMPOSITE;
+ case VINO_INPUT_SVIDEO:
+ return SAA7191_INPUT_SVIDEO;
+ default:
+ printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
+ "invalid input!\n");
+ return -1;
+ }
+}
+
+static int vino_get_saa7191_norm(int norm)
+{
+ switch (norm) {
+ case VINO_DATA_NORM_AUTO:
+ return SAA7191_NORM_AUTO;
+ case VINO_DATA_NORM_PAL:
+ return SAA7191_NORM_PAL;
+ case VINO_DATA_NORM_NTSC:
+ return SAA7191_NORM_NTSC;
+ case VINO_DATA_NORM_SECAM:
+ return SAA7191_NORM_SECAM;
+ default:
+ printk(KERN_ERR "VINO: vino_get_saa7191_norm(): "
+ "invalid norm!\n");
+ return -1;
+ }
+}
+
+/* execute with input_lock locked */
+static int vino_is_input_owner(struct vino_channel_settings *vcs)
+{
+ switch(vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ return (vino_drvdata->decoder.owner == vcs->channel);
+ case VINO_INPUT_D1:
+ return (vino_drvdata->camera.owner == vcs->channel);
+ default:
+ return 0;
+ }
+}
+
+static int vino_acquire_input(struct vino_channel_settings *vcs)
+{
+ int ret = 0;
+
+ dprintk("vino_acquire_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* First try D1 and then SAA7191 */
+ if (vino_drvdata->camera.driver
+ && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
+ if (i2c_use_client(vino_drvdata->camera.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vino_drvdata->camera.owner = vcs->channel;
+ vcs->input = VINO_INPUT_D1;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ } else if (vino_drvdata->decoder.driver
+ && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
+ int saa7191_input;
+ int saa7191_norm;
+
+ if (i2c_use_client(vino_drvdata->decoder.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vino_drvdata->decoder.owner = vcs->channel;
+ vcs->input = VINO_INPUT_COMPOSITE;
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+
+ saa7191_input = vino_get_saa7191_input(vcs->input);
+ i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+
+ saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+ } else {
+ vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.input : vino_drvdata->a.input;
+ vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
+ }
+
+ if (vcs->input == VINO_INPUT_NONE) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (vino_is_input_owner(vcs)) {
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+ }
+
+ dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static int vino_set_input(struct vino_channel_settings *vcs, int input)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+ int ret = 0;
+
+ dprintk("vino_set_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (vcs->input == input)
+ goto out;
+
+ switch(input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ if (!vino_drvdata->decoder.driver) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
+ if (i2c_use_client(vino_drvdata->decoder.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ vino_drvdata->decoder.owner = vcs->channel;
+ }
+
+ if (vino_drvdata->decoder.owner == vcs->channel) {
+ int saa7191_input;
+ int saa7191_norm;
+
+ vcs->input = input;
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+
+ saa7191_input = vino_get_saa7191_input(vcs->input);
+ i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input);
+ saa7191_norm = vino_get_saa7191_norm(vcs->data_norm);
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM,
+ &saa7191_norm);
+ } else {
+ if (vcs2->input != input) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ vcs->input = input;
+ vcs->data_norm = vcs2->data_norm;
+ }
+
+ if (vino_drvdata->camera.owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->
+ camera.driver);
+ vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ }
+ }
+ break;
+ case VINO_INPUT_D1:
+ if (!vino_drvdata->camera.driver) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
+ if (i2c_use_client(vino_drvdata->camera.driver)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ vino_drvdata->camera.owner = vcs->channel;
+ }
+
+ if (vino_drvdata->decoder.owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->
+ decoder.driver);
+ vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ }
+ }
+
+ vcs->input = input;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+
+ dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static void vino_release_input(struct vino_channel_settings *vcs)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+
+ dprintk("vino_release_input():\n");
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* Release ownership of the channel
+ * and if the other channel takes input from
+ * the same source, transfer the ownership */
+ if (vino_drvdata->camera.owner == vcs->channel) {
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->camera.driver);
+ vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+ }
+ } else if (vino_drvdata->decoder.owner == vcs->channel) {
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder.owner = vcs2->channel;
+ } else {
+ i2c_release_client(vino_drvdata->decoder.driver);
+ vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+ }
+ }
+ vcs->input = VINO_INPUT_NONE;
+
+ spin_unlock(&vino_drvdata->input_lock);
+}
+
+/* execute with input_lock locked */
+static int vino_set_data_norm(struct vino_channel_settings *vcs,
+ unsigned int data_norm)
+{
+ int saa7191_norm;
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ /* only one "norm" supported */
+ if (data_norm != VINO_DATA_NORM_D1)
+ return -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+
+ saa7191_norm = vino_get_saa7191_norm(data_norm);
+
+ i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm);
+ vcs->data_norm = data_norm;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* V4L2 helper functions */
+
+static int vino_find_data_format(__u32 pixelformat)
+{
+ int i;
+
+ for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
+ if (vino_data_formats[i].pixelformat == pixelformat)
+ return i;
+ }
+
+ return VINO_DATA_FMT_NONE;
+}
+
+static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index)
+{
+ int data_norm = VINO_DATA_NORM_NONE;
+
+ spin_lock(&vino_drvdata->input_lock);
+ switch(vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ if (index == 0) {
+ data_norm = VINO_DATA_NORM_PAL;
+ } else if (index == 1) {
+ data_norm = VINO_DATA_NORM_NTSC;
+ } else if (index == 2) {
+ data_norm = VINO_DATA_NORM_SECAM;
+ }
+ break;
+ case VINO_INPUT_D1:
+ if (index == 0) {
+ data_norm = VINO_DATA_NORM_D1;
+ }
+ break;
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return data_norm;
+}
+
+static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
+{
+ int input = VINO_INPUT_NONE;
+
+ spin_lock(&vino_drvdata->input_lock);
+ if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ case 2:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ } else if (vino_drvdata->decoder.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ }
+ } else if (vino_drvdata->camera.driver) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return input;
+}
+
+/* execute with input_lock locked */
+static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
+{
+ __u32 index = 0;
+ // FIXME: detect when no inputs available
+
+ if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ case VINO_INPUT_D1:
+ index = 2;
+ break;
+ }
+ } else if (vino_drvdata->decoder.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ }
+ } else if (vino_drvdata->camera.driver) {
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ index = 0;
+ break;
+ }
+ }
+
+ return index;
+}
+
+/* V4L2 ioctls */
+
+static void vino_v4l2_querycap(struct v4l2_capability *cap)
+{
+ memset(cap, 0, sizeof(struct v4l2_capability));
+
+ strcpy(cap->driver, vino_driver_name);
+ strcpy(cap->card, vino_driver_description);
+ strcpy(cap->bus_info, vino_bus_name);
+ cap->version = VINO_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING;
+ // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+}
+
+static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ __u32 index = i->index;
+ int input;
+ dprintk("requested index = %d\n", index);
+
+ input = vino_enum_input(vcs, index);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ memset(i, 0, sizeof(struct v4l2_input));
+
+ i->index = index;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = vino_inputs[input].std;
+ strcpy(i->name, vino_inputs[input].name);
+
+ if ((input == VINO_INPUT_COMPOSITE)
+ || (input == VINO_INPUT_SVIDEO)) {
+ struct saa7191_status status;
+ i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
+ i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL;
+ i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ __u32 index;
+ int input;
+
+ spin_lock(&vino_drvdata->input_lock);
+ input = vcs->input;
+ index = vino_find_input_index(vcs);
+ spin_unlock(&vino_drvdata->input_lock);
+
+ dprintk("input = %d\n", input);
+
+ if (input == VINO_INPUT_NONE) {
+ return -EINVAL;
+ }
+
+ memset(i, 0, sizeof(struct v4l2_input));
+
+ i->index = index;
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = vino_inputs[input].std;
+ strcpy(i->name, vino_inputs[input].name);
+
+ return 0;
+}
+
+static int vino_v4l2_s_input(struct vino_channel_settings *vcs,
+ struct v4l2_input *i)
+{
+ int input;
+ dprintk("requested input = %d\n", i->index);
+
+ input = vino_enum_input(vcs, i->index);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ return vino_set_input(vcs, input);
+}
+
+static int vino_v4l2_enumstd(struct vino_channel_settings *vcs,
+ struct v4l2_standard *s)
+{
+ int index = s->index;
+ int data_norm = vino_enum_data_norm(vcs, index);
+ dprintk("standard index = %d\n", index);
+
+ if (data_norm == VINO_DATA_NORM_NONE)
+ return -EINVAL;
+
+ dprintk("standard name = %s\n",
+ vino_data_norms[data_norm].description);
+
+ memset(s, 0, sizeof(struct v4l2_standard));
+ s->index = index;
+
+ s->id = vino_data_norms[data_norm].std;
+ s->frameperiod.numerator = 1;
+ s->frameperiod.denominator =
+ vino_data_norms[data_norm].fps_max;
+ s->framelines =
+ vino_data_norms[data_norm].framelines;
+ strcpy(s->name,
+ vino_data_norms[data_norm].description);
+
+ return 0;
+}
+
+static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
+ v4l2_std_id *std)
+{
+ spin_lock(&vino_drvdata->input_lock);
+ dprintk("current standard = %d\n", vcs->data_norm);
+ *std = vino_data_norms[vcs->data_norm].std;
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return 0;
+}
+
+static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
+ v4l2_std_id *std)
+{
+ int ret = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ /* check if the standard is valid for the current input */
+ if (vino_is_input_owner(vcs)
+ && (vino_inputs[vcs->input].std & (*std))) {
+ dprintk("standard accepted\n");
+
+ /* change the video norm for SAA7191
+ * and accept NTSC for D1 (do nothing) */
+
+ if (vcs->input == VINO_INPUT_D1)
+ goto out;
+
+ if ((*std) & V4L2_STD_PAL) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_PAL);
+ vcs->data_norm = VINO_DATA_NORM_PAL;
+ } else if ((*std) & V4L2_STD_NTSC) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC);
+ vcs->data_norm = VINO_DATA_NORM_NTSC;
+ } else if ((*std) & V4L2_STD_SECAM) {
+ vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM);
+ vcs->data_norm = VINO_DATA_NORM_SECAM;
+ } else {
+ ret = -EINVAL;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+out:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return ret;
+}
+
+static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_fmtdesc *fd)
+{
+ enum v4l2_buf_type type = fd->type;
+ int index = fd->index;
+ dprintk("format index = %d\n", index);
+
+ switch (fd->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if ((fd->index < 0) ||
+ (fd->index >= VINO_DATA_FMT_COUNT))
+ return -EINVAL;
+ dprintk("format name = %s\n",
+ vino_data_formats[index].description);
+
+ memset(fd, 0, sizeof(struct v4l2_fmtdesc));
+ fd->index = index;
+ fd->type = type;
+ fd->pixelformat = vino_data_formats[index].pixelformat;
+ strcpy(fd->description, vino_data_formats[index].description);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ struct vino_channel_settings tempvcs;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+
+ dprintk("requested: w = %d, h = %d\n",
+ pf->width, pf->height);
+
+ spin_lock(&vino_drvdata->input_lock);
+ memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+ spin_unlock(&vino_drvdata->input_lock);
+
+ tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+ if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+ tempvcs.data_format = VINO_DATA_FMT_RGB32;
+ pf->pixelformat =
+ vino_data_formats[tempvcs.data_format].
+ pixelformat;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[tempvcs.data_format].description);
+
+ pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+ tempvcs.decimation;
+ pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = tempvcs.line_size;
+ pf->sizeimage = tempvcs.line_size *
+ (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+ pf->colorspace =
+ vino_data_formats[tempvcs.data_format].colorspace;
+
+ pf->priv = 0;
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ spin_lock(&vino_drvdata->input_lock);
+
+ pf->width = (vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation;
+ pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].pixelformat;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ pf->priv = 0;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs,
+ struct v4l2_format *f)
+{
+ int data_format;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+
+ data_format = vino_find_data_format(pf->pixelformat);
+ if (data_format == VINO_DATA_FMT_NONE) {
+ vcs->data_format = VINO_DATA_FMT_RGB32;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].
+ pixelformat;
+ } else {
+ vcs->data_format = data_format;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(vcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[vcs->data_format].description);
+
+ pf->width = vcs->clipping.right - vcs->clipping.left;
+ pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ pf->priv = 0;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
+ struct v4l2_cropcap *ccap)
+{
+ const struct vino_data_norm *norm;
+
+ switch (ccap->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+ norm = &vino_data_norms[vcs->data_norm];
+ spin_unlock(&vino_drvdata->input_lock);
+
+ ccap->bounds.left = 0;
+ ccap->bounds.top = 0;
+ ccap->bounds.width = norm->width;
+ ccap->bounds.height = norm->height;
+ memcpy(&ccap->defrect, &ccap->bounds,
+ sizeof(struct v4l2_rect));
+
+ ccap->pixelaspect.numerator = 1;
+ ccap->pixelaspect.denominator = 1;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
+ struct v4l2_crop *c)
+{
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+
+ c->c.left = vcs->clipping.left;
+ c->c.top = vcs->clipping.top;
+ c->c.width = vcs->clipping.right - vcs->clipping.left;
+ c->c.height = vcs->clipping.bottom - vcs->clipping.top;
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
+ struct v4l2_crop *c)
+{
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock(&vino_drvdata->input_lock);
+
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+ vino_set_clipping(vcs, c->c.left, c->c.top,
+ c->c.width, c->c.height);
+
+ spin_unlock(&vino_drvdata->input_lock);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
+ struct v4l2_streamparm *sp)
+{
+ switch (sp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+ memset(cp, 0, sizeof(struct v4l2_captureparm));
+
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+
+ spin_lock(&vino_drvdata->input_lock);
+ cp->timeperframe.denominator = vcs->fps;
+ spin_unlock(&vino_drvdata->input_lock);
+
+ // TODO: cp->readbuffers = xxx;
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
+ struct v4l2_streamparm *sp)
+{
+ switch (sp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+
+ spin_lock(&vino_drvdata->input_lock);
+ if (!vino_is_input_owner(vcs)) {
+ spin_unlock(&vino_drvdata->input_lock);
+ return -EINVAL;
+ }
+
+ if ((cp->timeperframe.numerator == 0) ||
+ (cp->timeperframe.denominator == 0)) {
+ /* reset framerate */
+ vino_set_default_framerate(vcs);
+ } else {
+ vino_set_framerate(vcs, cp->timeperframe.denominator /
+ cp->timeperframe.numerator);
+ }
+ spin_unlock(&vino_drvdata->input_lock);
+
+ // TODO: set buffers according to cp->readbuffers
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs,
+ struct v4l2_requestbuffers *rb)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (rb->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ // TODO: check queue type
+ if (rb->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ if (vino_is_capturing(vcs)) {
+ dprintk("busy, capturing\n");
+ return -EBUSY;
+ }
+
+ dprintk("count = %d\n", rb->count);
+ if (rb->count > 0) {
+ if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+ dprintk("busy, buffers still mapped\n");
+ return -EBUSY;
+ } else {
+ vino_queue_free(&vcs->fb_queue);
+ vino_queue_init(&vcs->fb_queue, &rb->count);
+ }
+ } else {
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb,
+ struct v4l2_buffer *b)
+{
+ if (vino_queue_outgoing_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_QUEUED;
+ b->flags |= V4L2_BUF_FLAG_DONE;
+ } else if (vino_queue_incoming_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_DONE;
+ b->flags |= V4L2_BUF_FLAG_QUEUED;
+ } else {
+ b->flags &= ~(V4L2_BUF_FLAG_DONE |
+ V4L2_BUF_FLAG_QUEUED);
+ }
+
+ b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
+
+ if (fb->map_count > 0)
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+ b->index = fb->id;
+ b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
+ V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
+ b->m.offset = fb->offset;
+ b->bytesused = fb->data_size;
+ b->length = fb->size;
+ b->field = V4L2_FIELD_INTERLACED;
+ b->sequence = fb->frame_counter;
+ memcpy(&b->timestamp, &fb->timestamp,
+ sizeof(struct timeval));
+ // b->input ?
+
+ dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
+ fb->id, fb->size, fb->data_size, fb->offset);
+}
+
+static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+
+ // TODO: check queue type
+ if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+ dprintk("invalid index = %d\n",
+ b->index);
+ return -EINVAL;
+ }
+
+ fb = vino_queue_get_buffer(&vcs->fb_queue,
+ b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_get_buffer() failed");
+ return -EINVAL;
+ }
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+ int ret;
+
+ // TODO: check queue type
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ fb = vino_capture_enqueue(vcs, b->index);
+ if (fb == NULL)
+ return -EINVAL;
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+
+ if (vcs->streaming) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret)
+ return ret;
+ }
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
+ struct v4l2_buffer *b,
+ unsigned int nonblocking)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ switch (b->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct vino_framebuffer *fb;
+ unsigned int incoming, outgoing;
+ int err;
+
+ // TODO: check queue type
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EIO;
+ }
+ err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+ if (err) {
+ dprintk("vino_queue_get_outgoing() failed\n");
+ return -EIO;
+ }
+
+ dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+ if (outgoing == 0) {
+ if (incoming == 0) {
+ dprintk("no incoming or outgoing buffers\n");
+ return -EINVAL;
+ }
+ if (nonblocking) {
+ dprintk("non-blocking I/O was selected and "
+ "there are no buffers to dequeue\n");
+ return -EAGAIN;
+ }
+
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ /* interrupted */
+ vino_capture_failed(vcs);
+ return -EIO;
+ }
+ }
+ }
+
+ fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_remove() failed\n");
+ return -EINVAL;
+ }
+
+ err = vino_check_buffer(vcs, fb);
+ if (err)
+ return -EIO;
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+ break;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
+{
+ unsigned int incoming;
+ int ret;
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (vcs->streaming)
+ return 0;
+
+ // TODO: check queue type
+
+ if (vino_queue_get_length(&vcs->fb_queue) < 1) {
+ dprintk("no buffers allocated\n");
+ return -EINVAL;
+ }
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (ret) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+
+ vcs->streaming = 1;
+
+ if (incoming > 0) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret) {
+ vcs->streaming = 0;
+
+ dprintk("couldn't start capture\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
+{
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (!vcs->streaming)
+ return 0;
+
+ vino_capture_stop(vcs);
+ vcs->streaming = 0;
+
+ return 0;
+}
+
+static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
+ struct v4l2_queryctrl *queryctrl)
+{
+ int i;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_indycam_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_saa7191_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ found:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
+ struct v4l2_control *control)
+{
+ struct indycam_control indycam_ctrl;
+ struct saa7191_control saa7191_ctrl;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS,
+ &indycam_ctrl);
+
+ switch(control->id) {
+ case V4L2_CID_AUTOGAIN:
+ control->value = indycam_ctrl.agc;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ control->value = indycam_ctrl.awb;
+ break;
+ case V4L2_CID_GAIN:
+ control->value = indycam_ctrl.gain;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ control->value = indycam_ctrl.red_saturation;
+ break;
+ case V4L2_CID_PRIVATE_BASE + 1:
+ control->value = indycam_ctrl.blue_saturation;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ control->value = indycam_ctrl.red_balance;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ control->value = indycam_ctrl.blue_balance;
+ break;
+ case V4L2_CID_EXPOSURE:
+ control->value = indycam_ctrl.shutter;
+ break;
+ case V4L2_CID_GAMMA:
+ control->value = indycam_ctrl.gamma;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS,
+ &saa7191_ctrl);
+
+ switch(control->id) {
+ case V4L2_CID_HUE:
+ control->value = saa7191_ctrl.hue;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ control->value = saa7191_ctrl.vtrc;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
+ struct v4l2_control *control)
+{
+ struct indycam_control indycam_ctrl;
+ struct saa7191_control saa7191_ctrl;
+ int i;
+ int err = 0;
+
+ spin_lock(&vino_drvdata->input_lock);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id ==
+ control->id) {
+ if ((control->value >=
+ vino_indycam_v4l2_controls[i].minimum)
+ && (control->value <=
+ vino_indycam_v4l2_controls[i].
+ maximum)) {
+ goto ok1;
+ } else {
+ err = -ERANGE;
+ goto error;
+ }
+ }
+ }
+ err = -EINVAL;
+ goto error;
+
+ok1:
+ indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED;
+ indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED;
+
+ switch(control->id) {
+ case V4L2_CID_AUTOGAIN:
+ indycam_ctrl.agc = control->value;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ indycam_ctrl.awb = control->value;
+ break;
+ case V4L2_CID_GAIN:
+ indycam_ctrl.gain = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ indycam_ctrl.red_saturation = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE + 1:
+ indycam_ctrl.blue_saturation = control->value;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ indycam_ctrl.red_balance = control->value;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ indycam_ctrl.blue_balance = control->value;
+ break;
+ case V4L2_CID_EXPOSURE:
+ indycam_ctrl.shutter = control->value;
+ break;
+ case V4L2_CID_GAMMA:
+ indycam_ctrl.gamma = control->value;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err)
+ i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS,
+ &indycam_ctrl);
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id ==
+ control->id) {
+ if ((control->value >=
+ vino_saa7191_v4l2_controls[i].minimum)
+ && (control->value <=
+ vino_saa7191_v4l2_controls[i].
+ maximum)) {
+ goto ok2;
+ } else {
+ err = -ERANGE;
+ goto error;
+ }
+ }
+ }
+ err = -EINVAL;
+ goto error;
+
+ok2:
+ saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED;
+ saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED;
+
+ switch(control->id) {
+ case V4L2_CID_HUE:
+ saa7191_ctrl.hue = control->value;
+ break;
+ case V4L2_CID_PRIVATE_BASE:
+ saa7191_ctrl.vtrc = control->value;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err)
+ i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS,
+ &saa7191_ctrl);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+error:
+ spin_unlock(&vino_drvdata->input_lock);
+
+ return err;
+}
+
+/* File operations */
+
+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);
+ int ret = 0;
+ dprintk("open(): channel = %c\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
+
+ down(&vcs->sem);
+
+ if (vcs->users) {
+ dprintk("open(): driver busy\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = vino_acquire_input(vcs);
+ if (ret) {
+ dprintk("open(): vino_acquire_input() failed\n");
+ goto out;
+ }
+
+ vcs->users++;
+
+ out:
+ up(&vcs->sem);
+
+ dprintk("open(): %s!\n", ret ? "failed" : "complete");
+
+ return ret;
+}
+
+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);
+ dprintk("close():\n");
+
+ down(&vcs->sem);
+
+ vcs->users--;
+
+ if (!vcs->users) {
+ vino_release_input(vcs);
+
+ /* stop DMA and free buffers */
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+
+ up(&vcs->sem);
+
+ return 0;
+}
+
+static void vino_vm_open(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count++;
+ dprintk("vino_vm_open(): count = %d\n", fb->map_count);
+}
+
+static void vino_vm_close(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count--;
+ dprintk("vino_vm_close(): count = %d\n", fb->map_count);
+}
+
+static struct vm_operations_struct vino_vm_ops = {
+ .open = vino_vm_open,
+ .close = vino_vm_close,
+};
+
+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);
+
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ struct vino_framebuffer *fb = NULL;
+ unsigned int i, length;
+ int ret = 0;
+
+ dprintk("mmap():\n");
+
+ // TODO: reject mmap if already mapped
+
+ if (down_interruptible(&vcs->sem))
+ return -EINTR;
+
+ if (vcs->reading) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ // TODO: check queue type
+
+ if (!(vma->vm_flags & VM_WRITE)) {
+ dprintk("mmap(): app bug: PROT_WRITE please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!(vma->vm_flags & VM_SHARED)) {
+ dprintk("mmap(): app bug: MAP_SHARED please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* find the correct buffer using offset */
+ length = vino_queue_get_length(&vcs->fb_queue);
+ if (length == 0) {
+ dprintk("mmap(): queue not initialized\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < length; i++) {
+ fb = vino_queue_get_buffer(&vcs->fb_queue, i);
+ if (fb == NULL) {
+ dprintk("mmap(): vino_queue_get_buffer() failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fb->offset == offset)
+ goto found;
+ }
+
+ dprintk("mmap(): invalid offset = %lu\n", offset);
+ ret = -EINVAL;
+ goto out;
+
+found:
+ dprintk("mmap(): buffer = %d\n", i);
+
+ if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
+ dprintk("mmap(): failed: size = %lu > %lu\n",
+ size, fb->desc_table.page_count * PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < fb->desc_table.page_count; i++) {
+ unsigned long pfn =
+ virt_to_phys((void *)fb->desc_table.virtual[i]) >>
+ PAGE_SHIFT;
+
+ if (size < PAGE_SIZE)
+ break;
+
+ // protection was: PAGE_READONLY
+ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+ vma->vm_page_prot)) {
+ dprintk("mmap(): remap_pfn_range() failed\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ start += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ fb->map_count = 1;
+
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_flags &= ~VM_IO;
+ vma->vm_private_data = fb;
+ vma->vm_file = file;
+ vma->vm_ops = &vino_vm_ops;
+
+out:
+ up(&vcs->sem);
+
+ return ret;
+}
+
+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);
+ unsigned int outgoing;
+ unsigned int ret = 0;
+
+ // lock mutex (?)
+ // TODO: this has to be corrected for different read modes
+
+ dprintk("poll():\n");
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+ if (outgoing > 0)
+ goto over;
+
+ poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+
+over:
+ dprintk("poll(): data %savailable\n",
+ (outgoing > 0) ? "" : "not ");
+ if (outgoing > 0) {
+ ret = POLLIN | POLLRDNORM;
+ }
+
+error:
+
+ return ret;
+}
+
+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);
+
+ switch (_IOC_TYPE(cmd)) {
+ case 'v':
+ dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd);
+ break;
+ case 'V':
+ dprintk("ioctl(): V4L2 %s (0x%08x)\n",
+ v4l2_ioctl_names[_IOC_NR(cmd)], cmd);
+ break;
+ default:
+ dprintk("ioctl(): unsupported command 0x%08x\n", cmd);
+ }
+
+ switch (cmd) {
+ /* TODO: V4L1 interface (use compatibility layer?) */
+ /* V4L2 interface */
+ case VIDIOC_QUERYCAP: {
+ vino_v4l2_querycap(arg);
+ break;
+ }
+ case VIDIOC_ENUMINPUT: {
+ return vino_v4l2_enuminput(vcs, arg);
+ }
+ case VIDIOC_G_INPUT: {
+ return vino_v4l2_g_input(vcs, arg);
+ }
+ case VIDIOC_S_INPUT: {
+ return vino_v4l2_s_input(vcs, arg);
+ }
+ case VIDIOC_ENUMSTD: {
+ return vino_v4l2_enumstd(vcs, arg);
+ }
+ case VIDIOC_G_STD: {
+ return vino_v4l2_g_std(vcs, arg);
+ }
+ case VIDIOC_S_STD: {
+ return vino_v4l2_s_std(vcs, arg);
+ }
+ case VIDIOC_ENUM_FMT: {
+ return vino_v4l2_enum_fmt(vcs, arg);
+ }
+ case VIDIOC_TRY_FMT: {
+ return vino_v4l2_try_fmt(vcs, arg);
+ }
+ case VIDIOC_G_FMT: {
+ return vino_v4l2_g_fmt(vcs, arg);
+ }
+ case VIDIOC_S_FMT: {
+ return vino_v4l2_s_fmt(vcs, arg);
+ }
+ case VIDIOC_CROPCAP: {
+ return vino_v4l2_cropcap(vcs, arg);
+ }
+ case VIDIOC_G_CROP: {
+ return vino_v4l2_g_crop(vcs, arg);
+ }
+ case VIDIOC_S_CROP: {
+ return vino_v4l2_s_crop(vcs, arg);
+ }
+ case VIDIOC_G_PARM: {
+ return vino_v4l2_g_parm(vcs, arg);
+ }
+ case VIDIOC_S_PARM: {
+ return vino_v4l2_s_parm(vcs, arg);
+ }
+ case VIDIOC_REQBUFS: {
+ return vino_v4l2_reqbufs(vcs, arg);
+ }
+ case VIDIOC_QUERYBUF: {
+ return vino_v4l2_querybuf(vcs, arg);
+ }
+ case VIDIOC_QBUF: {
+ return vino_v4l2_qbuf(vcs, arg);
+ }
+ case VIDIOC_DQBUF: {
+ return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK);
+ }
+ case VIDIOC_STREAMON: {
+ return vino_v4l2_streamon(vcs);
+ }
+ case VIDIOC_STREAMOFF: {
+ return vino_v4l2_streamoff(vcs);
+ }
+ case VIDIOC_QUERYCTRL: {
+ return vino_v4l2_queryctrl(vcs, arg);
+ }
+ case VIDIOC_G_CTRL: {
+ return vino_v4l2_g_ctrl(vcs, arg);
+ }
+ case VIDIOC_S_CTRL: {
+ return vino_v4l2_s_ctrl(vcs, arg);
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+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);
+ int ret;
+
+ if (down_interruptible(&vcs->sem))
+ return -EINTR;
+
+ ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl);
+
+ up(&vcs->sem);
+
+ return ret;
+}
+
+/* Initialization and cleanup */
+
+// __initdata
+static int vino_init_stage = 0;
+
+static struct file_operations vino_fops = {
.owner = THIS_MODULE,
- .type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE,
- .hardware = VID_HARDWARE_VINO,
- .name = "VINO",
.open = vino_open,
- .close = vino_close,
+ .release = vino_close,
.ioctl = vino_ioctl,
.mmap = vino_mmap,
+ .poll = vino_poll,
+ .llseek = no_llseek,
};
-static int __init vino_init(void)
+static struct video_device v4l_device_template = {
+ .name = "NOT SET",
+ //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
+ // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
+ .hardware = VID_HARDWARE_VINO,
+ .fops = &vino_fops,
+ .minor = -1,
+};
+
+static void vino_module_cleanup(int stage)
+{
+ switch(stage) {
+ case 10:
+ video_unregister_device(vino_drvdata->b.v4l_device);
+ vino_drvdata->b.v4l_device = NULL;
+ case 9:
+ video_unregister_device(vino_drvdata->a.v4l_device);
+ vino_drvdata->a.v4l_device = NULL;
+ case 8:
+ vino_i2c_del_bus();
+ case 7:
+ free_irq(SGI_VINO_IRQ, NULL);
+ case 6:
+ if (vino_drvdata->b.v4l_device) {
+ video_device_release(vino_drvdata->b.v4l_device);
+ vino_drvdata->b.v4l_device = NULL;
+ }
+ case 5:
+ if (vino_drvdata->a.v4l_device) {
+ video_device_release(vino_drvdata->a.v4l_device);
+ vino_drvdata->a.v4l_device = NULL;
+ }
+ case 4:
+ /* all entries in dma_cpu dummy table have the same address */
+ dma_unmap_single(NULL,
+ vino_drvdata->dummy_desc_table.dma_cpu[0],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
+ * sizeof(dma_addr_t),
+ (void *)vino_drvdata->
+ dummy_desc_table.dma_cpu,
+ vino_drvdata->dummy_desc_table.dma);
+ case 3:
+ free_page(vino_drvdata->dummy_page);
+ case 2:
+ kfree(vino_drvdata);
+ case 1:
+ iounmap(vino);
+ case 0:
+ break;
+ default:
+ dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
+ stage);
+ }
+}
+
+static int vino_probe(void)
{
- unsigned long rev;
- int i, ret = 0;
+ unsigned long rev_id;
- /* VINO is Indy specific beast */
- if (ip22_is_fullhouse())
+ if (ip22_is_fullhouse()) {
+ printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
return -ENODEV;
+ }
- /*
- * VINO is in the EISA address space, so the sysid register will tell
- * us if the EISA_PRESENT pin on MC has been pulled low.
- *
- * If EISA_PRESENT is not set we definitely don't have a VINO equiped
- * system.
- */
if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
- printk(KERN_ERR "VINO not found\n");
+ printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
return -ENODEV;
}
vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
- if (!vino)
+ if (!vino) {
+ printk(KERN_ERR "VINO: ioremap() failed\n");
return -EIO;
+ }
+ vino_init_stage++;
- /* Okay, once we know that VINO is present we'll read its revision
- * safe way. One never knows... */
- if (get_dbe(rev, &(vino->rev_id))) {
- printk(KERN_ERR "VINO: failed to read revision register\n");
- ret = -ENODEV;
- goto out_unmap;
+ if (get_dbe(rev_id, &(vino->rev_id))) {
+ printk(KERN_ERR "Failed to read VINO revision register\n");
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
}
- if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) {
- printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev);
- ret = -ENODEV;
- goto out_unmap;
+
+ if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
+ printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
+ rev_id);
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
}
- printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev));
- Vino = (struct vino_video *)
- kmalloc(sizeof(struct vino_video), GFP_KERNEL);
- if (!Vino) {
- ret = -ENOMEM;
- goto out_unmap;
+ printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n",
+ VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id));
+
+ return 0;
+}
+
+static int vino_init(void)
+{
+ dma_addr_t dma_dummy_address;
+ int i;
+
+ vino_drvdata = (struct vino_settings *)
+ kmalloc(sizeof(struct vino_settings), GFP_KERNEL);
+ if (!vino_drvdata) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
}
+ memset(vino_drvdata, 0, sizeof(struct vino_settings));
+ vino_init_stage++;
- Vino->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!Vino->dummy_page) {
- ret = -ENOMEM;
- goto out_free_vino;
+ /* create a dummy dma descriptor */
+ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_page) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
}
- for (i = 0; i < 4; i++)
- Vino->dummy_buf[i] = PHYSADDR(Vino->dummy_page);
+ vino_init_stage++;
+
+ // TODO: use page_count in dummy_desc_table
+
+ vino_drvdata->dummy_desc_table.dma_cpu =
+ dma_alloc_coherent(NULL,
+ VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
+ &vino_drvdata->dummy_desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_desc_table.dma_cpu) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ dma_dummy_address = dma_map_single(NULL,
+ (void *)vino_drvdata->dummy_page,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
+ vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
+ }
+
+ /* initialize VINO */
vino->control = 0;
- /* prevent VINO from throwing spurious interrupts */
- vino->a.next_4_desc = PHYSADDR(Vino->dummy_buf);
- vino->b.next_4_desc = PHYSADDR(Vino->dummy_buf);
- udelay(5);
+ vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ udelay(VINO_DESC_FETCH_DELAY);
+
vino->intr_status = 0;
- /* set threshold level */
- vino->a.fifo_thres = threshold_a;
- vino->b.fifo_thres = threshold_b;
- init_MUTEX(&Vino->input_lock);
+ vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+ vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+
+ return 0;
+}
+
+static int vino_init_channel_settings(struct vino_channel_settings *vcs,
+ unsigned int channel, const char *name)
+{
+ vcs->channel = channel;
+ vcs->input = VINO_INPUT_NONE;
+ vcs->alpha = 0;
+ vcs->users = 0;
+ vcs->data_format = VINO_DATA_FMT_GREY;
+ vcs->data_norm = VINO_DATA_NORM_NTSC;
+ vcs->decimation = 1;
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+
+ vcs->capturing = 0;
+
+ init_MUTEX(&vcs->sem);
+ spin_lock_init(&vcs->capture_lock);
+
+ init_MUTEX(&vcs->fb_queue.queue_sem);
+ spin_lock_init(&vcs->fb_queue.queue_lock);
+ init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
+
+ vcs->v4l_device = video_device_alloc();
+ if (!vcs->v4l_device) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ memcpy(vcs->v4l_device, &v4l_device_template,
+ sizeof(struct video_device));
+ strcpy(vcs->v4l_device->name, name);
+ vcs->v4l_device->release = video_device_release;
+
+ video_set_drvdata(vcs->v4l_device, vcs);
+
+ return 0;
+}
+
+static int __init vino_module_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "SGI VINO driver version %s\n",
+ VINO_MODULE_VERSION);
+
+ ret = vino_probe();
+ if (ret)
+ return ret;
+
+ ret = vino_init();
+ if (ret)
+ return ret;
+
+ /* initialize data structures */
- if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) {
- printk(KERN_ERR "VINO: irq%02d registration failed\n",
+ spin_lock_init(&vino_drvdata->vino_lock);
+ spin_lock_init(&vino_drvdata->input_lock);
+
+ ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
+ vino_v4l_device_name_a);
+ if (ret)
+ return ret;
+
+ ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
+ vino_v4l_device_name_b);
+ if (ret)
+ return ret;
+
+ /* initialize hardware and register V4L devices */
+
+ ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
+ vino_driver_description, NULL);
+ if (ret) {
+ printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
SGI_VINO_IRQ);
- ret = -EAGAIN;
- goto out_free_page;
+ vino_module_cleanup(vino_init_stage);
+ return -EAGAIN;
}
+ vino_init_stage++;
ret = vino_i2c_add_bus();
if (ret) {
- printk(KERN_ERR "VINO: I2C bus registration failed\n");
- goto out_free_irq;
+ printk(KERN_ERR "VINO I2C bus registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return ret;
}
+ vino_init_stage++;
- if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) {
- printk("%s, chnl %d: device registration failed.\n",
- Vino->chA.vdev.name, Vino->chA.chan);
- ret = -EINVAL;
- goto out_i2c_del_bus;
+ ret = video_register_device(vino_drvdata->a.v4l_device,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel A Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
}
- if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) {
- printk("%s, chnl %d: device registration failed.\n",
- Vino->chB.vdev.name, Vino->chB.chan);
- ret = -EINVAL;
- goto out_unregister_vdev;
+ vino_init_stage++;
+
+ ret = video_register_device(vino_drvdata->b.v4l_device,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel B Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
}
+ vino_init_stage++;
- return 0;
+#if defined(CONFIG_KMOD) && defined(MODULE)
+ request_module("saa7191");
+ request_module("indycam");
+#endif
-out_unregister_vdev:
- video_unregister_device(&Vino->chA.vdev);
-out_i2c_del_bus:
- vino_i2c_del_bus();
-out_free_irq:
- free_irq(SGI_VINO_IRQ, NULL);
-out_free_page:
- free_page(Vino->dummy_page);
-out_free_vino:
- kfree(Vino);
-out_unmap:
- iounmap(vino);
+ dprintk("init complete!\n");
- return ret;
+ return 0;
}
-static void __exit vino_exit(void)
+static void __exit vino_module_exit(void)
{
- video_unregister_device(&Vino->chA.vdev);
- video_unregister_device(&Vino->chB.vdev);
- vino_i2c_del_bus();
- free_irq(SGI_VINO_IRQ, NULL);
- free_page(Vino->dummy_page);
- kfree(Vino);
- iounmap(vino);
+ dprintk("exiting, stage = %d ...\n", vino_init_stage);
+ vino_module_cleanup(vino_init_stage);
+ dprintk("cleanup complete, exit!\n");
}
-module_init(vino_init);
-module_exit(vino_exit);
-
-MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)");
-MODULE_LICENSE("GPL");
+module_init(vino_module_init);
+module_exit(vino_module_exit);
diff --git a/drivers/media/video/vino.h b/drivers/media/video/vino.h
index d2fce472f35a..de2d615ae7c9 100644
--- a/drivers/media/video/vino.h
+++ b/drivers/media/video/vino.h
@@ -1,13 +1,19 @@
/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
* Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
* Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
*/
-#ifndef VINO_H
-#define VINO_H
+#ifndef _VINO_H_
+#define _VINO_H_
#define VINO_BASE 0x00080000 /* Vino is in the EISA address space,
* but it is not an EISA bus card */
+#define VINO_PAGE_SIZE 4096
struct sgi_vino_channel {
u32 _pad_alpha;
@@ -21,8 +27,9 @@ struct sgi_vino_channel {
u32 _pad_clip_end;
volatile u32 clip_end;
+#define VINO_FRAMERT_FULL 0xfff
#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */
-#define VINO_FRAMERT_RT(x) (((x) & 0x1fff) << 1) /* bits 1:12 */
+#define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */
u32 _pad_frame_rate;
volatile u32 frame_rate;
@@ -67,18 +74,18 @@ struct sgi_vino {
volatile u32 rev_id;
#define VINO_CTRL_LITTLE_ENDIAN (1<<0)
-#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */
-#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */
-#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */
-#define VINO_CTRL_A_INT (VINO_CTRL_A_FIELD_TRANS_INT | \
- VINO_CTRL_A_FIFO_OF_INT | \
- VINO_CTRL_A_END_DESC_TBL_INT)
-#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */
-#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */
-#define VINO_CTRL_B_END_DESC_TBL_INT (1<<6) /* End of desc table int */
-#define VINO_CTRL_B_INT (VINO_CTRL_B_FIELD_TRANS_INT | \
- VINO_CTRL_B_FIFO_OF_INT | \
- VINO_CTRL_B_END_DESC_TBL_INT)
+#define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */
+#define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */
+#define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */
+#define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \
+ VINO_CTRL_A_FIFO_INT | \
+ VINO_CTRL_A_EOD_INT)
+#define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */
+#define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */
+#define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */
+#define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \
+ VINO_CTRL_B_FIFO_INT | \
+ VINO_CTRL_B_EOD_INT)
#define VINO_CTRL_A_DMA_ENBL (1<<7)
#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8)
#define VINO_CTRL_A_SYNC_ENBL (1<<9)
@@ -104,18 +111,18 @@ struct sgi_vino {
u32 _pad_control;
volatile u32 control;
-#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */
-#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */
-#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */
-#define VINO_INTSTAT_A (VINO_INTSTAT_A_FIELD_TRANS | \
- VINO_INTSTAT_A_FIFO_OF | \
- VINO_INTSTAT_A_END_DESC_TBL)
-#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */
-#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */
-#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */
-#define VINO_INTSTAT_B (VINO_INTSTAT_B_FIELD_TRANS | \
- VINO_INTSTAT_B_FIFO_OF | \
- VINO_INTSTAT_B_END_DESC_TBL)
+#define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */
+#define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */
+#define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */
+#define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \
+ VINO_INTSTAT_A_FIFO | \
+ VINO_INTSTAT_A_EOD)
+#define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */
+#define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */
+#define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */
+#define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \
+ VINO_INTSTAT_B_FIFO | \
+ VINO_INTSTAT_B_EOD)
u32 _pad_intr_status;
volatile u32 intr_status;
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 5dbd9f6bf353..137b58f2c666 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -203,7 +203,7 @@ static const unsigned short init_ntsc[] = {
0x8c, 640, /* Horizontal length */
0x8d, 640, /* Number of pixels */
0x8f, 0xc00, /* Disable window 2 */
- 0xf0, 0x173, /* 13.5 MHz transport, Forced
+ 0xf0, 0x73, /* 13.5 MHz transport, Forced
* mode, latch windows */
0xf2, 0x13, /* NTSC M, composite input */
0xe7, 0x1e1, /* Enable vertical standard
@@ -212,38 +212,36 @@ static const unsigned short init_ntsc[] = {
static const unsigned short init_pal[] = {
0x88, 23, /* Window 1 vertical begin */
- 0x89, 288 + 16, /* Vertical lines in (16 lines
+ 0x89, 288, /* Vertical lines in (16 lines
* skipped by the VFE) */
- 0x8a, 288 + 16, /* Vertical lines out (16 lines
+ 0x8a, 288, /* Vertical lines out (16 lines
* skipped by the VFE) */
0x8b, 16, /* Horizontal begin */
0x8c, 768, /* Horizontal length */
0x8d, 784, /* Number of pixels
* Must be >= Horizontal begin + Horizontal length */
0x8f, 0xc00, /* Disable window 2 */
- 0xf0, 0x177, /* 13.5 MHz transport, Forced
+ 0xf0, 0x77, /* 13.5 MHz transport, Forced
* mode, latch windows */
0xf2, 0x3d1, /* PAL B,G,H,I, composite input */
- 0xe7, 0x261, /* PAL/SECAM set to 288 + 16 lines
- * change to 0x241 for 288 lines */
+ 0xe7, 0x241, /* PAL/SECAM set to 288 lines */
};
static const unsigned short init_secam[] = {
- 0x88, 23 - 16, /* Window 1 vertical begin */
- 0x89, 288 + 16, /* Vertical lines in (16 lines
+ 0x88, 23, /* Window 1 vertical begin */
+ 0x89, 288, /* Vertical lines in (16 lines
* skipped by the VFE) */
- 0x8a, 288 + 16, /* Vertical lines out (16 lines
+ 0x8a, 288, /* Vertical lines out (16 lines
* skipped by the VFE) */
0x8b, 16, /* Horizontal begin */
0x8c, 768, /* Horizontal length */
0x8d, 784, /* Number of pixels
* Must be >= Horizontal begin + Horizontal length */
0x8f, 0xc00, /* Disable window 2 */
- 0xf0, 0x177, /* 13.5 MHz transport, Forced
+ 0xf0, 0x77, /* 13.5 MHz transport, Forced
* mode, latch windows */
0xf2, 0x3d5, /* SECAM, composite input */
- 0xe7, 0x261, /* PAL/SECAM set to 288 + 16 lines
- * change to 0x241 for 288 lines */
+ 0xe7, 0x241, /* PAL/SECAM set to 288 lines */
};
static const unsigned char init_common[] = {
@@ -410,6 +408,12 @@ vpx3220_command (struct i2c_client *client,
case DECODER_SET_NORM:
{
int *iarg = arg, data;
+ int temp_input;
+
+ /* Here we back up the input selection because it gets
+ overwritten when we fill the registers with the
+ choosen video norm */
+ temp_input = vpx3220_fp_read(client, 0xf2);
dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
I2C_NAME(client), *iarg);
@@ -449,6 +453,10 @@ vpx3220_command (struct i2c_client *client,
}
decoder->norm = *iarg;
+
+ /* And here we set the backed up video input again */
+ vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
+ udelay(10);
}
break;
@@ -576,7 +584,6 @@ static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
.ignore = &ignore,
- .force = &ignore,
};
static struct i2c_driver vpx3220_i2c_driver;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 25743085b2d5..eed2acea1779 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -737,7 +737,7 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
};
static struct i2c_adapter zoran_i2c_adapter_template = {
- I2C_DEVNAME("zr36057"),
+ .name = "zr36057",
.id = I2C_HW_B_ZR36067,
.algo = NULL,
.client_register = zoran_i2c_client_register,
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index ba838a42ec80..53adeb70f2ca 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -650,7 +650,7 @@ jpg_fbuffer_free (struct file *file)
off += PAGE_SIZE)
ClearPageReserved(MAP_NR
(mem + off));
- kfree((void *) mem);
+ kfree(mem);
fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
}
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index c33533155cc7..07286816d7df 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -820,11 +820,9 @@ void zoran_close(struct video_device* dev)
msleep(100); /* Wait 1/10th of a second */
/* free the allocated framebuffer */
- if (ztv->fbuffer)
- bfree( ztv->fbuffer, ZORAN_MAX_FBUFSIZE );
+ bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
ztv->fbuffer = 0;
- if (ztv->overinfo.overlay)
- kfree( ztv->overinfo.overlay );
+ kfree(ztv->overinfo.overlay);
ztv->overinfo.overlay = 0;
}
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 33f209a39cb6..1883d22cffeb 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -35,6 +35,23 @@ config FUSION_FC
LSIFC929X
LSIFC929XL
+config FUSION_SAS
+ tristate "Fusion MPT ScsiHost drivers for SAS"
+ depends on PCI && SCSI
+ select FUSION
+ select SCSI_SAS_ATTRS
+ ---help---
+ SCSI HOST support for a SAS host adapters.
+
+ List of supported controllers:
+
+ LSISAS1064
+ LSISAS1066
+ LSISAS1068
+ LSISAS1064E
+ LSISAS1066E
+ LSISAS1068E
+
config FUSION_MAX_SGE
int "Maximum number of scatter gather entries (16 - 128)"
depends on FUSION
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 1d2f9db813c1..8a2e2657f4c2 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -34,5 +34,6 @@
obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o
obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o
+obj-$(CONFIG_FUSION_SAS) += mptbase.o mptscsih.o mptsas.o
obj-$(CONFIG_FUSION_CTL) += mptctl.o
obj-$(CONFIG_FUSION_LAN) += mptlan.o
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 9f98334e5076..b61e3d175070 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.07
+ * mpi.h Version: 01.05.08
*
* Version History
* ---------------
@@ -71,6 +71,9 @@
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
+ * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Added EEDP IOCStatus codes.
* --------------------------------------------------------------------------
*/
@@ -101,7 +104,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x09)
+#define MPI_HEADER_VERSION_UNIT (0x0A)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -292,10 +295,13 @@
#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D)
#define MPI_FUNCTION_DIAG_RELEASE (0x1E)
+#define MPI_FUNCTION_SCSI_IO_32 (0x1F)
+
#define MPI_FUNCTION_LAN_SEND (0x20)
#define MPI_FUNCTION_LAN_RECEIVE (0x21)
#define MPI_FUNCTION_LAN_RESET (0x22)
+#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED (0x23)
#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24)
#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25)
@@ -681,6 +687,15 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
/****************************************************************************/
+/* For use by SCSI Initiator and SCSI Target end-to-end data protection */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
+#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
+#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
+
+
+/****************************************************************************/
/* SCSI Target values */
/****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 15b12b06799d..d8339896f734 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.08
+ * mpi_cnfg.h Version: 01.05.09
*
* Version History
* ---------------
@@ -232,6 +232,23 @@
* New physical mapping mode in SAS IO Unit Page 2.
* Added CONFIG_PAGE_SAS_ENCLOSURE_0.
* Added Slot and Enclosure fields to SAS Device Page 0.
+ * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1.
+ * Added more RAID type defines to IOC Page 2.
+ * Added Port Enable Delay settings to BIOS Page 1.
+ * Added Bad Block Table Full define to RAID Volume Page 0.
+ * Added Previous State defines to RAID Physical Disk
+ * Page 0.
+ * Added Max Sata Targets define for DiscoveryStatus field
+ * of SAS IO Unit Page 0.
+ * Added Device Self Test to Control Flags of SAS IO Unit
+ * Page 1.
+ * Added Direct Attach Starting Slot Number define for SAS
+ * IO Unit Page 2.
+ * Added new fields in SAS Device Page 2 for enclosure
+ * mapping.
+ * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ * Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
* --------------------------------------------------------------------------
*/
@@ -477,6 +494,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626)
#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642)
#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -769,9 +787,13 @@ typedef struct _CONFIG_PAGE_IOC_1
} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
IOCPage1_t, MPI_POINTER pIOCPage1_t;
-#define MPI_IOCPAGE1_PAGEVERSION (0x02)
+#define MPI_IOCPAGE1_PAGEVERSION (0x03)
/* defines for the Flags field */
+#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000)
+#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000)
+#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000)
+#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000)
#define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010)
#define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001)
@@ -795,6 +817,11 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL
#define MPI_RAID_VOL_TYPE_IS (0x00)
#define MPI_RAID_VOL_TYPE_IME (0x01)
#define MPI_RAID_VOL_TYPE_IM (0x02)
+#define MPI_RAID_VOL_TYPE_RAID_5 (0x03)
+#define MPI_RAID_VOL_TYPE_RAID_6 (0x04)
+#define MPI_RAID_VOL_TYPE_RAID_10 (0x05)
+#define MPI_RAID_VOL_TYPE_RAID_50 (0x06)
+#define MPI_RAID_VOL_TYPE_UNKNOWN (0xFF)
/* IOC Page 2 Volume Flags values */
@@ -820,13 +847,17 @@ typedef struct _CONFIG_PAGE_IOC_2
} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
IOCPage2_t, MPI_POINTER pIOCPage2_t;
-#define MPI_IOCPAGE2_PAGEVERSION (0x02)
+#define MPI_IOCPAGE2_PAGEVERSION (0x03)
/* IOC Page 2 Capabilities flags */
#define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT (0x00000001)
#define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT (0x00000002)
#define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT (0x00000004)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT (0x00000008)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT (0x00000010)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT (0x00000020)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT (0x00000040)
#define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000)
#define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000)
#define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000)
@@ -945,7 +976,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
-#define MPI_BIOSPAGE1_PAGEVERSION (0x01)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x02)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -954,6 +985,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1167,6 +1200,7 @@ typedef struct _CONFIG_PAGE_BIOS_2
#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03)
#define MPI_BIOSPAGE2_FORM_FC_WWN (0x04)
#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05)
+#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
/****************************************************************************
@@ -1957,11 +1991,11 @@ typedef struct _RAID_VOL0_STATUS
RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t;
/* RAID Volume Page 0 VolumeStatus defines */
-
#define MPI_RAIDVOL0_STATUS_FLAG_ENABLED (0x01)
#define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED (0x02)
#define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x04)
#define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x08)
+#define MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x10)
#define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00)
#define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01)
@@ -2025,7 +2059,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
-#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x04)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x05)
/* values for RAID Volume Page 0 InactiveStatus field */
#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
@@ -2104,6 +2138,8 @@ typedef struct _RAID_PHYS_DISK0_STATUS
#define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01)
#define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02)
#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04)
+#define MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00)
+#define MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x08)
#define MPI_PHYSDISK0_STATUS_ONLINE (0x00)
#define MPI_PHYSDISK0_STATUS_MISSING (0x01)
@@ -2132,7 +2168,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0
} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t;
-#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x01)
+#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x02)
typedef struct _RAID_PHYS_DISK1_PATH
@@ -2263,7 +2299,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
-#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x02)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x03)
/* values for SAS IO Unit Page 0 PortFlags */
#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08)
@@ -2299,6 +2335,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
#define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400)
#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
+#define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS (0x00001000)
typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
@@ -2336,6 +2373,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04)
/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
@@ -2345,9 +2383,8 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x10)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02)
-#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
@@ -2390,7 +2427,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
-#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x03)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2406,6 +2443,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
+#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
@@ -2584,11 +2622,19 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U64 PhysicalIdentifier; /* 08h */
- U32 Reserved1; /* 10h */
+ U32 EnclosureMapping; /* 10h */
} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2,
SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t;
-#define MPI_SASDEVICE2_PAGEVERSION (0x00)
+#define MPI_SASDEVICE2_PAGEVERSION (0x01)
+
+/* defines for SAS Device Page 2 EnclosureMapping field */
+#define MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT (0x0000000F)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_MISSING_COUNT (0)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS (0x000007F0)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS (4)
+#define MPI_SASDEVICE2_ENC_MAP_MASK_START_INDEX (0x001FF800)
+#define MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX (11)
/****************************************************************************
@@ -2598,7 +2644,8 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2
typedef struct _CONFIG_PAGE_SAS_PHY_0
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U16 OwnerDevHandle; /* 08h */
+ U16 Reserved1; /* 0Ah */
U64 SASAddress; /* 0Ch */
U16 AttachedDevHandle; /* 14h */
U8 AttachedPhyIdentifier; /* 16h */
@@ -2607,12 +2654,12 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
U8 ProgrammedLinkRate; /* 20h */
U8 HwLinkRate; /* 21h */
U8 ChangeCount; /* 22h */
- U8 Reserved3; /* 23h */
+ U8 Flags; /* 23h */
U32 PhyInfo; /* 24h */
} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
-#define MPI_SASPHY0_PAGEVERSION (0x00)
+#define MPI_SASPHY0_PAGEVERSION (0x01)
/* values for SAS PHY Page 0 ProgrammedLinkRate field */
#define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK (0xF0)
@@ -2632,6 +2679,9 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
#define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5 (0x08)
#define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0 (0x09)
+/* values for SAS PHY Page 0 Flags field */
+#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
+
/* values for SAS PHY Page 0 PhyInfo field */
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000)
@@ -2690,7 +2740,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0,
SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t;
-#define MPI_SASENCLOSURE0_PAGEVERSION (0x00)
+#define MPI_SASENCLOSURE0_PAGEVERSION (0x01)
/* values for SAS Enclosure Page 0 Flags field */
#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020)
@@ -2702,6 +2752,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
/****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index c9edbee41edf..1a30ef16adb4 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,17 +6,17 @@
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.09
+ Header Set Release Version: 01.05.10
Header Set Release Date: 03-11-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.07 01.05.06
- mpi_ioc.h 01.05.08 01.05.07
- mpi_cnfg.h 01.05.08 01.05.07
- mpi_init.h 01.05.04 01.05.03
- mpi_targ.h 01.05.04 01.05.03
+ mpi.h 01.05.08 01.05.07
+ mpi_ioc.h 01.05.09 01.05.08
+ mpi_cnfg.h 01.05.09 01.05.08
+ mpi_init.h 01.05.05 01.05.04
+ mpi_targ.h 01.05.05 01.05.04
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02
@@ -24,7 +24,7 @@
mpi_inb.h 01.05.01 01.05.01
mpi_sas.h 01.05.01 01.05.01
mpi_type.h 01.05.01 01.05.01
- mpi_history.txt 01.05.09 01.05.08
+ mpi_history.txt 01.05.09 01.05.09
* Date Version Description
@@ -88,6 +88,9 @@ mpi.h
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
+ * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Added EEDP IOCStatus codes.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -159,6 +162,8 @@ mpi_ioc.h
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
+ * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
+ * Added Max SATA Targets to SAS Discovery Error event.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -380,6 +385,23 @@ mpi_cnfg.h
* New physical mapping mode in SAS IO Unit Page 2.
* Added CONFIG_PAGE_SAS_ENCLOSURE_0.
* Added Slot and Enclosure fields to SAS Device Page 0.
+ * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1.
+ * Added more RAID type defines to IOC Page 2.
+ * Added Port Enable Delay settings to BIOS Page 1.
+ * Added Bad Block Table Full define to RAID Volume Page 0.
+ * Added Previous State defines to RAID Physical Disk
+ * Page 0.
+ * Added Max Sata Targets define for DiscoveryStatus field
+ * of SAS IO Unit Page 0.
+ * Added Device Self Test to Control Flags of SAS IO Unit
+ * Page 1.
+ * Added Direct Attach Starting Slot Number define for SAS
+ * IO Unit Page 2.
+ * Added new fields in SAS Device Page 2 for enclosure
+ * mapping.
+ * Added OwnerDevHandle and Flags field to SAS PHY Page 0.
+ * Added IOC GPIO Flags define to SAS Enclosure Page 0.
+ * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
* --------------------------------------------------------------------------
mpi_init.h
@@ -418,6 +440,8 @@ mpi_init.h
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
+ * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
+ * Added four new defines for SEP SlotStatus.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -461,6 +485,7 @@ mpi_targ.h
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
+ * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
* --------------------------------------------------------------------------
mpi_fc.h
@@ -571,20 +596,20 @@ mpi_type.h
mpi_history.txt Parts list history
-Filename 01.05.09
----------- --------
-mpi.h 01.05.07
-mpi_ioc.h 01.05.08
-mpi_cnfg.h 01.05.08
-mpi_init.h 01.05.04
-mpi_targ.h 01.05.04
-mpi_fc.h 01.05.01
-mpi_lan.h 01.05.01
-mpi_raid.h 01.05.02
-mpi_tool.h 01.05.03
-mpi_inb.h 01.05.01
-mpi_sas.h 01.05.01
-mpi_type.h 01.05.01
+Filename 01.05.10 01.05.09
+---------- -------- --------
+mpi.h 01.05.08 01.05.07
+mpi_ioc.h 01.05.09 01.05.08
+mpi_cnfg.h 01.05.09 01.05.08
+mpi_init.h 01.05.05 01.05.04
+mpi_targ.h 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01
+mpi_sas.h 01.05.01 01.05.01
+mpi_type.h 01.05.01 01.05.01
Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index aca035801a86..d5af75afbd94 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.04
+ * mpi_init.h Version: 01.05.05
*
* Version History
* ---------------
@@ -48,6 +48,8 @@
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
+ * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
+ * Added four new defines for SEP SlotStatus.
* --------------------------------------------------------------------------
*/
@@ -203,6 +205,197 @@ typedef struct _MSG_SCSI_IO_REPLY
/****************************************************************************/
+/* SCSI IO 32 messages and associated structures */
+/****************************************************************************/
+
+typedef struct
+{
+ U8 CDB[20]; /* 00h */
+ U32 PrimaryReferenceTag; /* 14h */
+ U16 PrimaryApplicationTag; /* 18h */
+ U16 PrimaryApplicationTagMask; /* 1Ah */
+ U32 TransferLength; /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP32, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP32,
+ MpiScsiIo32CdbEedp32_t, MPI_POINTER pMpiScsiIo32CdbEedp32_t;
+
+typedef struct
+{
+ U8 CDB[16]; /* 00h */
+ U32 DataLength; /* 10h */
+ U32 PrimaryReferenceTag; /* 14h */
+ U16 PrimaryApplicationTag; /* 18h */
+ U16 PrimaryApplicationTagMask; /* 1Ah */
+ U32 TransferLength; /* 1Ch */
+} MPI_SCSI_IO32_CDB_EEDP16, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP16,
+ MpiScsiIo32CdbEedp16_t, MPI_POINTER pMpiScsiIo32CdbEedp16_t;
+
+typedef union
+{
+ U8 CDB32[32];
+ MPI_SCSI_IO32_CDB_EEDP32 EEDP32;
+ MPI_SCSI_IO32_CDB_EEDP16 EEDP16;
+ SGE_SIMPLE_UNION SGE;
+} MPI_SCSI_IO32_CDB_UNION, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_UNION,
+ MpiScsiIo32Cdb_t, MPI_POINTER pMpiScsiIo32Cdb_t;
+
+typedef struct
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U16 Reserved1; /* 02h */
+ U32 Reserved2; /* 04h */
+} MPI_SCSI_IO32_BUS_TARGET_ID_FORM, MPI_POINTER PTR_MPI_SCSI_IO32_BUS_TARGET_ID_FORM,
+ MpiScsiIo32BusTargetIdForm_t, MPI_POINTER pMpiScsiIo32BusTargetIdForm_t;
+
+typedef union
+{
+ MPI_SCSI_IO32_BUS_TARGET_ID_FORM SCSIID;
+ U64 WWID;
+} MPI_SCSI_IO32_ADDRESS, MPI_POINTER PTR_MPI_SCSI_IO32_ADDRESS,
+ MpiScsiIo32Address_t, MPI_POINTER pMpiScsiIo32Address_t;
+
+typedef struct _MSG_SCSI_IO32_REQUEST
+{
+ U8 Port; /* 00h */
+ U8 Reserved1; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U8 CDBLength; /* 04h */
+ U8 SenseBufferLength; /* 05h */
+ U8 Flags; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 LUN[8]; /* 0Ch */
+ U32 Control; /* 14h */
+ MPI_SCSI_IO32_CDB_UNION CDB; /* 18h */
+ U32 DataLength; /* 38h */
+ U32 BidirectionalDataLength; /* 3Ch */
+ U32 SecondaryReferenceTag; /* 40h */
+ U16 SecondaryApplicationTag; /* 44h */
+ U16 Reserved2; /* 46h */
+ U16 EEDPFlags; /* 48h */
+ U16 ApplicationTagTranslationMask; /* 4Ah */
+ U32 EEDPBlockSize; /* 4Ch */
+ MPI_SCSI_IO32_ADDRESS DeviceAddress; /* 50h */
+ U8 SGLOffset0; /* 58h */
+ U8 SGLOffset1; /* 59h */
+ U8 SGLOffset2; /* 5Ah */
+ U8 SGLOffset3; /* 5Bh */
+ U32 Reserved3; /* 5Ch */
+ U32 Reserved4; /* 60h */
+ U32 SenseBufferLowAddr; /* 64h */
+ SGE_IO_UNION SGL; /* 68h */
+} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
+ SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
+
+/* SCSI IO 32 MsgFlags bits */
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01)
+
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
+#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_IOC (0x02)
+
+#define MPI_SCSIIO32_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
+#define MPI_SCSIIO32_MSGFLGS_SGL_OFFSETS_CHAINS (0x08)
+#define MPI_SCSIIO32_MSGFLGS_MULTICAST (0x10)
+#define MPI_SCSIIO32_MSGFLGS_BIDIRECTIONAL (0x20)
+#define MPI_SCSIIO32_MSGFLGS_LARGE_CDB (0x40)
+
+/* SCSI IO 32 Flags bits */
+#define MPI_SCSIIO32_FLAGS_FORM_MASK (0x03)
+#define MPI_SCSIIO32_FLAGS_FORM_SCSIID (0x00)
+#define MPI_SCSIIO32_FLAGS_FORM_WWID (0x01)
+
+/* SCSI IO 32 LUN fields */
+#define MPI_SCSIIO32_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI_SCSIIO32_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI_SCSIIO32_LUN_LEVEL_1_WORD (0xFF00)
+#define MPI_SCSIIO32_LUN_LEVEL_1_DWORD (0x0000FF00)
+
+/* SCSI IO 32 Control bits */
+#define MPI_SCSIIO32_CONTROL_DATADIRECTION_MASK (0x03000000)
+#define MPI_SCSIIO32_CONTROL_NODATATRANSFER (0x00000000)
+#define MPI_SCSIIO32_CONTROL_WRITE (0x01000000)
+#define MPI_SCSIIO32_CONTROL_READ (0x02000000)
+#define MPI_SCSIIO32_CONTROL_BIDIRECTIONAL (0x03000000)
+
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_MASK (0xFC000000)
+#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_SHIFT (26)
+
+#define MPI_SCSIIO32_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
+#define MPI_SCSIIO32_CONTROL_SIMPLEQ (0x00000000)
+#define MPI_SCSIIO32_CONTROL_HEADOFQ (0x00000100)
+#define MPI_SCSIIO32_CONTROL_ORDEREDQ (0x00000200)
+#define MPI_SCSIIO32_CONTROL_ACAQ (0x00000400)
+#define MPI_SCSIIO32_CONTROL_UNTAGGED (0x00000500)
+#define MPI_SCSIIO32_CONTROL_NO_DISCONNECT (0x00000700)
+
+#define MPI_SCSIIO32_CONTROL_TASKMANAGE_MASK (0x00FF0000)
+#define MPI_SCSIIO32_CONTROL_OBSOLETE (0x00800000)
+#define MPI_SCSIIO32_CONTROL_CLEAR_ACA_RSV (0x00400000)
+#define MPI_SCSIIO32_CONTROL_TARGET_RESET (0x00200000)
+#define MPI_SCSIIO32_CONTROL_LUN_RESET_RSV (0x00100000)
+#define MPI_SCSIIO32_CONTROL_RESERVED (0x00080000)
+#define MPI_SCSIIO32_CONTROL_CLR_TASK_SET_RSV (0x00040000)
+#define MPI_SCSIIO32_CONTROL_ABORT_TASK_SET (0x00020000)
+#define MPI_SCSIIO32_CONTROL_RESERVED2 (0x00010000)
+
+/* SCSI IO 32 EEDPFlags */
+#define MPI_SCSIIO32_EEDPFLAGS_MASK_OP (0x0007)
+#define MPI_SCSIIO32_EEDPFLAGS_NOOP_OP (0x0000)
+#define MPI_SCSIIO32_EEDPFLAGS_CHK_OP (0x0001)
+#define MPI_SCSIIO32_EEDPFLAGS_STRIP_OP (0x0002)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP (0x0003)
+#define MPI_SCSIIO32_EEDPFLAGS_INSERT_OP (0x0004)
+#define MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP (0x0006)
+#define MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP (0x0007)
+
+#define MPI_SCSIIO32_EEDPFLAGS_PASS_REF_TAG (0x0008)
+#define MPI_SCSIIO32_EEDPFLAGS_8_9THS_MODE (0x0010)
+
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_MASK (0x0700)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD (0x0100)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG (0x0200)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG (0x0400)
+#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_SHIFT (8)
+
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
+#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
+
+
+/* SCSIIO32 IO reply structure */
+typedef struct _MSG_SCSIIO32_IO_REPLY
+{
+ U8 Port; /* 00h */
+ U8 Reserved1; /* 01h */
+ U8 MsgLength; /* 02h */
+ U8 Function; /* 03h */
+ U8 CDBLength; /* 04h */
+ U8 SenseBufferLength; /* 05h */
+ U8 Flags; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 SCSIStatus; /* 0Ch */
+ U8 SCSIState; /* 0Dh */
+ U16 IOCStatus; /* 0Eh */
+ U32 IOCLogInfo; /* 10h */
+ U32 TransferCount; /* 14h */
+ U32 SenseCount; /* 18h */
+ U32 ResponseInfo; /* 1Ch */
+ U16 TaskTag; /* 20h */
+ U16 Reserved2; /* 22h */
+ U32 BidirectionalTransferCount; /* 24h */
+} MSG_SCSIIO32_IO_REPLY, MPI_POINTER PTR_MSG_SCSIIO32_IO_REPLY,
+ SCSIIO32Reply_t, MPI_POINTER pSCSIIO32Reply_t;
+
+
+/****************************************************************************/
/* SCSI Task Management messages */
/****************************************************************************/
@@ -310,10 +503,14 @@ typedef struct _MSG_SEP_REQUEST
#define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
#define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
#define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_CONSISTENCY_CHECK (0x00001000)
+#define MPI_SEP_REQ_SLOTSTATUS_DISABLE (0x00002000)
+#define MPI_SEP_REQ_SLOTSTATUS_REQ_RESERVED_DEVICE (0x00004000)
#define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
#define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT (0x00080000)
#define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE (0x00400000)
+#define MPI_SEP_REQ_SLOTSTATUS_ACTIVE (0x00800000)
#define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000)
#define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000)
#define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF (0x10000000)
@@ -352,11 +549,15 @@ typedef struct _MSG_SEP_REPLY
#define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
#define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
#define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI_SEP_REPLY_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000)
+#define MPI_SEP_REPLY_SLOTSTATUS_DISABLE (0x00002000)
+#define MPI_SEP_REPLY_SLOTSTATUS_RESERVED_DEVICE (0x00004000)
#define MPI_SEP_REPLY_SLOTSTATUS_REPORT (0x00010000)
#define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
#define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY (0x00080000)
#define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE (0x00400000)
+#define MPI_SEP_REPLY_SLOTSTATUS_ACTIVE (0x00800000)
#define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED (0x01000000)
#define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED (0x02000000)
#define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index f91eb4efe8cc..93b70e2b4266 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.08
+ * mpi_ioc.h Version: 01.05.09
*
* Version History
* ---------------
@@ -81,6 +81,8 @@
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
+ * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
+ * Added Max SATA Targets to SAS Discovery Error event.
* --------------------------------------------------------------------------
*/
@@ -261,7 +263,11 @@ typedef struct _MSG_IOC_FACTS_REPLY
#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
-
+#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040)
+#define MPI_IOCFACTS_CAPABILITY_BIDIRECTIONAL (0x00000080)
+#define MPI_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
+#define MPI_IOCFACTS_CAPABILITY_SCSIIO32 (0x00000200)
+#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16 (0x00000400)
/*****************************************************************************
@@ -677,6 +683,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200)
#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800)
+#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000)
/*****************************************************************************
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
index 623901fd82be..3f462859ceea 100644
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -6,7 +6,7 @@
* Title: MPI Target mode messages and structures
* Creation Date: June 22, 2000
*
- * mpi_targ.h Version: 01.05.04
+ * mpi_targ.h Version: 01.05.05
*
* Version History
* ---------------
@@ -53,6 +53,7 @@
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
+ * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines.
* --------------------------------------------------------------------------
*/
@@ -371,6 +372,77 @@ typedef struct _MSG_TARGET_ERROR_REPLY
/****************************************************************************/
+/* Target Assist Extended Request */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_ASSIST_EXT_REQUEST
+{
+ U8 StatusCode; /* 00h */
+ U8 TargetAssistFlags; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 QueueTag; /* 04h */
+ U8 Reserved1; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U32 ReplyWord; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 RelativeOffset; /* 18h */
+ U32 Reserved2; /* 1Ch */
+ U32 Reserved3; /* 20h */
+ U32 PrimaryReferenceTag; /* 24h */
+ U16 PrimaryApplicationTag; /* 28h */
+ U16 PrimaryApplicationTagMask; /* 2Ah */
+ U32 Reserved4; /* 2Ch */
+ U32 DataLength; /* 30h */
+ U32 BidirectionalDataLength; /* 34h */
+ U32 SecondaryReferenceTag; /* 38h */
+ U16 SecondaryApplicationTag; /* 3Ch */
+ U16 Reserved5; /* 3Eh */
+ U16 EEDPFlags; /* 40h */
+ U16 ApplicationTagTranslationMask; /* 42h */
+ U32 EEDPBlockSize; /* 44h */
+ U8 SGLOffset0; /* 48h */
+ U8 SGLOffset1; /* 49h */
+ U8 SGLOffset2; /* 4Ah */
+ U8 SGLOffset3; /* 4Bh */
+ U32 Reserved6; /* 4Ch */
+ SGE_IO_UNION SGL[1]; /* 50h */
+} MSG_TARGET_ASSIST_EXT_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_EXT_REQUEST,
+ TargetAssistExtRequest_t, MPI_POINTER pTargetAssistExtRequest_t;
+
+/* see the defines after MSG_TARGET_ASSIST_REQUEST for TargetAssistFlags */
+
+/* defines for the MsgFlags field */
+#define TARGET_ASSIST_EXT_MSGFLAGS_BIDIRECTIONAL (0x20)
+#define TARGET_ASSIST_EXT_MSGFLAGS_MULTICAST (0x10)
+#define TARGET_ASSIST_EXT_MSGFLAGS_SGL_OFFSET_CHAINS (0x08)
+
+/* defines for the EEDPFlags field */
+#define TARGET_ASSIST_EXT_EEDP_MASK_OP (0x0007)
+#define TARGET_ASSIST_EXT_EEDP_NOOP_OP (0x0000)
+#define TARGET_ASSIST_EXT_EEDP_CHK_OP (0x0001)
+#define TARGET_ASSIST_EXT_EEDP_STRIP_OP (0x0002)
+#define TARGET_ASSIST_EXT_EEDP_CHKRM_OP (0x0003)
+#define TARGET_ASSIST_EXT_EEDP_INSERT_OP (0x0004)
+#define TARGET_ASSIST_EXT_EEDP_REPLACE_OP (0x0006)
+#define TARGET_ASSIST_EXT_EEDP_CHKREGEN_OP (0x0007)
+
+#define TARGET_ASSIST_EXT_EEDP_PASS_REF_TAG (0x0008)
+
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_MASK (0x0700)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_GUARD (0x0100)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_APPTAG (0x0200)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_REFTAG (0x0400)
+#define TARGET_ASSIST_EXT_EEDP_T10_CHK_SHIFT (8)
+
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_APPTAG (0x1000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_APPTAG (0x2000)
+#define TARGET_ASSIST_EXT_EEDP_INC_SEC_REFTAG (0x4000)
+#define TARGET_ASSIST_EXT_EEDP_INC_PRI_REFTAG (0x8000)
+
+
+/****************************************************************************/
/* Target Status Send Request */
/****************************************************************************/
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ffbe6f4720e1..790a2932ded9 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -135,13 +135,12 @@ static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
-//static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
-static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag);
+static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
@@ -152,6 +151,7 @@ static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int GetLanConfigPages(MPT_ADAPTER *ioc);
static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
static int GetIoUnitPage2(MPT_ADAPTER *ioc);
+int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
@@ -159,6 +159,8 @@ static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
static void mpt_timer_expired(unsigned long data);
static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
+static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
+static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
#ifdef CONFIG_PROC_FS
static int procmpt_summary_read(char *buf, char **start, off_t offset,
@@ -175,6 +177,7 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *
static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
+static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
/* module entry point */
static int __init fusion_init (void);
@@ -206,6 +209,144 @@ pci_enable_io_access(struct pci_dev *pdev)
pci_write_config_word(pdev, PCI_COMMAND, command_reg);
}
+/*
+ * Process turbo (context) reply...
+ */
+static void
+mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+ MPT_FRAME_HDR *mf = NULL;
+ MPT_FRAME_HDR *mr = NULL;
+ int req_idx = 0;
+ int cb_idx;
+
+ dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
+ ioc->name, pa));
+
+ switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
+ case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
+ req_idx = pa & 0x0000FFFF;
+ cb_idx = (pa & 0x00FF0000) >> 16;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+ break;
+ case MPI_CONTEXT_REPLY_TYPE_LAN:
+ cb_idx = mpt_lan_index;
+ /*
+ * Blind set of mf to NULL here was fatal
+ * after lan_reply says "freeme"
+ * Fix sort of combined with an optimization here;
+ * added explicit check for case where lan_reply
+ * was just returning 1 and doing nothing else.
+ * For this case skip the callback, but set up
+ * proper mf value first here:-)
+ */
+ if ((pa & 0x58000000) == 0x58000000) {
+ req_idx = pa & 0x0000FFFF;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+ mpt_free_msg_frame(ioc, mf);
+ mb();
+ return;
+ break;
+ }
+ mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+ break;
+ case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
+ cb_idx = mpt_stm_index;
+ mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
+ break;
+ default:
+ cb_idx = 0;
+ BUG();
+ }
+
+ /* Check for (valid) IO callback! */
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+ MptCallbacks[cb_idx] == NULL) {
+ printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+ __FUNCTION__, ioc->name, cb_idx);
+ goto out;
+ }
+
+ if (MptCallbacks[cb_idx](ioc, mf, mr))
+ mpt_free_msg_frame(ioc, mf);
+ out:
+ mb();
+}
+
+static void
+mpt_reply(MPT_ADAPTER *ioc, u32 pa)
+{
+ MPT_FRAME_HDR *mf;
+ MPT_FRAME_HDR *mr;
+ int req_idx;
+ int cb_idx;
+ int freeme;
+
+ u32 reply_dma_low;
+ u16 ioc_stat;
+
+ /* non-TURBO reply! Hmmm, something may be up...
+ * Newest turbo reply mechanism; get address
+ * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
+ */
+
+ /* Map DMA address of reply header to cpu address.
+ * pa is 32 bits - but the dma address may be 32 or 64 bits
+ * get offset based only only the low addresses
+ */
+
+ reply_dma_low = (pa <<= 1);
+ mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
+ (reply_dma_low - ioc->reply_frames_low_dma));
+
+ req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
+ cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
+ mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
+
+ dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
+ ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
+ DBG_DUMP_REPLY_FRAME(mr)
+
+ /* Check/log IOC log info
+ */
+ ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
+ if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+ u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+ if (ioc->bus_type == FC)
+ mpt_fc_log_info(ioc, log_info);
+ else if (ioc->bus_type == SCSI)
+ mpt_sp_log_info(ioc, log_info);
+ else if (ioc->bus_type == SAS)
+ mpt_sas_log_info(ioc, log_info);
+ }
+ if (ioc_stat & MPI_IOCSTATUS_MASK) {
+ if (ioc->bus_type == SCSI &&
+ cb_idx != mpt_stm_index &&
+ cb_idx != mpt_lan_index)
+ mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
+ }
+
+
+ /* Check for (valid) IO callback! */
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
+ MptCallbacks[cb_idx] == NULL) {
+ printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
+ __FUNCTION__, ioc->name, cb_idx);
+ freeme = 0;
+ goto out;
+ }
+
+ freeme = MptCallbacks[cb_idx](ioc, mf, mr);
+
+ out:
+ /* Flush (non-TURBO) reply with a WRITE! */
+ CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+
+ if (freeme)
+ mpt_free_msg_frame(ioc, mf);
+ mb();
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
@@ -218,8 +359,7 @@ pci_enable_io_access(struct pci_dev *pdev)
* (also referred to as a IO Controller or IOC).
* This routine must clear the interrupt from the adapter and does
* so by reading the reply FIFO. Multiple replies may be processed
- * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR
- * which is currently set to 32 in mptbase.h.
+ * per single call to this routine.
*
* This routine handles register-level access of the adapter but
* dispatches (calls) a protocol-specific callback routine to handle
@@ -228,164 +368,21 @@ pci_enable_io_access(struct pci_dev *pdev)
static irqreturn_t
mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
{
- MPT_ADAPTER *ioc;
- MPT_FRAME_HDR *mf;
- MPT_FRAME_HDR *mr;
- u32 pa;
- int req_idx;
- int cb_idx;
- int type;
- int freeme;
-
- ioc = (MPT_ADAPTER *)bus_id;
+ MPT_ADAPTER *ioc = bus_id;
+ u32 pa;
/*
* Drain the reply FIFO!
- *
- * NOTES: I've seen up to 10 replies processed in this loop, so far...
- * Update: I've seen up to 9182 replies processed in this loop! ??
- * Update: Limit ourselves to processing max of N replies
- * (bottom of loop).
*/
while (1) {
-
- if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)
+ pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
+ if (pa == 0xFFFFFFFF)
return IRQ_HANDLED;
-
- cb_idx = 0;
- freeme = 0;
-
- /*
- * Check for non-TURBO reply!
- */
- if (pa & MPI_ADDRESS_REPLY_A_BIT) {
- u32 reply_dma_low;
- u16 ioc_stat;
-
- /* non-TURBO reply! Hmmm, something may be up...
- * Newest turbo reply mechanism; get address
- * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
- */
-
- /* Map DMA address of reply header to cpu address.
- * pa is 32 bits - but the dma address may be 32 or 64 bits
- * get offset based only only the low addresses
- */
- reply_dma_low = (pa = (pa << 1));
- mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
- (reply_dma_low - ioc->reply_frames_low_dma));
-
- req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
- cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
-
- dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
- ioc->name, mr, req_idx));
- DBG_DUMP_REPLY_FRAME(mr)
-
- /* Check/log IOC log info
- */
- ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
- if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
- u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
- if (ioc->bus_type == FC)
- mpt_fc_log_info(ioc, log_info);
- else if (ioc->bus_type == SCSI)
- mpt_sp_log_info(ioc, log_info);
- }
- if (ioc_stat & MPI_IOCSTATUS_MASK) {
- if (ioc->bus_type == SCSI)
- mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
- }
- } else {
- /*
- * Process turbo (context) reply...
- */
- dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
- type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
- if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
- cb_idx = mpt_stm_index;
- mf = NULL;
- mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
- } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
- cb_idx = mpt_lan_index;
- /* Blind set of mf to NULL here was fatal
- * after lan_reply says "freeme"
- * Fix sort of combined with an optimization here;
- * added explicit check for case where lan_reply
- * was just returning 1 and doing nothing else.
- * For this case skip the callback, but set up
- * proper mf value first here:-)
- */
- if ((pa & 0x58000000) == 0x58000000) {
- req_idx = pa & 0x0000FFFF;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
- freeme = 1;
- /*
- * IMPORTANT! Invalidate the callback!
- */
- cb_idx = 0;
- } else {
- mf = NULL;
- }
- mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
- } else {
- req_idx = pa & 0x0000FFFF;
- cb_idx = (pa & 0x00FF0000) >> 16;
- mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
- mr = NULL;
- }
- pa = 0; /* No reply flush! */
- }
-
-#ifdef MPT_DEBUG_IRQ
- if (ioc->bus_type == SCSI) {
- /* Verify mf, mr are reasonable.
- */
- if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))
- || (mf < ioc->req_frames)) ) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth))
- || (mr < ioc->reply_frames)) ) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) {
- printk(MYIOC_s_WARN_FMT
- "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx);
- cb_idx = 0;
- pa = 0;
- freeme = 0;
- }
- }
-#endif
-
- /* Check for (valid) IO callback! */
- if (cb_idx) {
- /* Do the callback! */
- freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);
- }
-
- if (pa) {
- /* Flush (non-TURBO) reply with a WRITE! */
- CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
- }
-
- if (freeme) {
- /* Put Request back on FreeQ! */
- mpt_free_msg_frame(ioc, mf);
- }
-
- mb();
- } /* drain reply FIFO */
+ else if (pa & MPI_ADDRESS_REPLY_A_BIT)
+ mpt_reply(ioc, pa);
+ else
+ mpt_turbo_reply(ioc, pa);
+ }
return IRQ_HANDLED;
}
@@ -399,7 +396,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
* @mf: Pointer to original MPT request frame
* @reply: Pointer to MPT reply frame (NULL if TurboReply)
*
- * Returns 1 indicating original alloc'd request frame ptr
+ * Returns 1 indicating original alloc'd request frame ptr
* should be freed, or 0 if it shouldn't.
*/
static int
@@ -408,28 +405,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
int freereq = 1;
u8 func;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
-
- if ((mf == NULL) ||
- (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
- printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n",
- ioc->name, (void *)mf);
- return 1;
- }
-
- if (reply == NULL) {
- dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n",
- ioc->name));
- return 1;
- }
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
+#if defined(MPT_DEBUG_MSG_FRAME)
if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
DBG_DUMP_REQUEST_FRAME_HDR(mf)
}
+#endif
func = reply->u.hdr.Function;
- dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
+ dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
ioc->name, func));
if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
@@ -448,8 +434,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
* Hmmm... It seems that EventNotificationReply is an exception
* to the rule of one reply per request.
*/
- if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
+ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
freereq = 0;
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
+ ioc->name, pEvReply));
+ } else {
+ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
+ ioc->name, pEvReply));
+ }
#ifdef CONFIG_PROC_FS
// LogEvent(ioc, pEvReply);
@@ -491,10 +483,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
pCfg->status = status;
if (status == MPI_IOCSTATUS_SUCCESS) {
- pCfg->hdr->PageVersion = pReply->Header.PageVersion;
- pCfg->hdr->PageLength = pReply->Header.PageLength;
- pCfg->hdr->PageNumber = pReply->Header.PageNumber;
- pCfg->hdr->PageType = pReply->Header.PageType;
+ if ((pReply->Header.PageType &
+ MPI_CONFIG_PAGETYPE_MASK) ==
+ MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pCfg->cfghdr.ehdr->ExtPageLength =
+ le16_to_cpu(pReply->ExtPageLength);
+ pCfg->cfghdr.ehdr->ExtPageType =
+ pReply->ExtPageType;
+ }
+ pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+
+ /* If this is a regular header, save PageLength. */
+ /* LMP Do this better so not using a reserved field! */
+ pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+ pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+ pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
}
}
@@ -504,6 +507,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
pCfg->wait_done = 1;
wake_up(&mpt_waitq);
}
+ } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
+ /* we should be always getting a reply frame */
+ memcpy(ioc->persist_reply_frame, reply,
+ min(MPT_DEFAULT_FRAME_SIZE,
+ 4*reply->u.reply.MsgLength));
+ del_timer(&ioc->persist_timer);
+ ioc->persist_wait_done = 1;
+ wake_up(&mpt_waitq);
} else {
printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
ioc->name, func);
@@ -705,7 +716,7 @@ mpt_device_driver_deregister(int cb_idx)
if (dd_cbfunc->remove)
dd_cbfunc->remove(ioc->pcidev);
}
-
+
MptDeviceDriverHandlers[cb_idx] = NULL;
}
@@ -745,6 +756,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
u.frame.linkage.list);
list_del(&mf->u.frame.linkage.list);
+ mf->u.frame.linkage.arg1 = 0;
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
@@ -818,7 +830,7 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
}
#endif
- mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
+ mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
}
@@ -840,6 +852,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
/* Put Request back on FreeQ! */
spin_lock_irqsave(&ioc->FreeQlock, flags);
+ mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
#ifdef MFCNT
ioc->mfcnt--;
@@ -920,7 +933,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
/* Make sure there are no doorbells */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
+
CHIPREG_WRITE32(&ioc->chip->Doorbell,
((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
@@ -935,14 +948,14 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
return -5;
dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
- ioc->name, ii));
+ ioc->name, ii));
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
return -2;
}
-
+
/* Send request via doorbell handshake */
req_as_bytes = (u8 *) req;
for (ii = 0; ii < reqBytes/4; ii++) {
@@ -966,12 +979,123 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req,
/* Make sure there are no doorbells */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
+
return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
+ * mpt_host_page_access_control - provides mechanism for the host
+ * driver to control the IOC's Host Page Buffer access.
+ * @ioc: Pointer to MPT adapter structure
+ * @access_control_value: define bits below
+ *
+ * Access Control Value - bits[15:12]
+ * 0h Reserved
+ * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
+ * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
+ * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+
+static int
+mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
+{
+ int r = 0;
+
+ /* return if in use */
+ if (CHIPREG_READ32(&ioc->chip->Doorbell)
+ & MPI_DOORBELL_ACTIVE)
+ return -1;
+
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+ CHIPREG_WRITE32(&ioc->chip->Doorbell,
+ ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
+ <<MPI_DOORBELL_FUNCTION_SHIFT) |
+ (access_control_value<<12)));
+
+ /* Wait for IOC to clear Doorbell Status bit */
+ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
+ return -2;
+ }else
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_host_page_alloc - allocate system memory for the fw
+ * If we already allocated memory in past, then resend the same pointer.
+ * ioc@: Pointer to pointer to IOC adapter
+ * ioc_init@: Pointer to ioc init config page
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
+{
+ char *psge;
+ int flags_length;
+ u32 host_page_buffer_sz=0;
+
+ if(!ioc->HostPageBuffer) {
+
+ host_page_buffer_sz =
+ le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
+
+ if(!host_page_buffer_sz)
+ return 0; /* fw doesn't need any host buffers */
+
+ /* spin till we get enough memory */
+ while(host_page_buffer_sz > 0) {
+
+ if((ioc->HostPageBuffer = pci_alloc_consistent(
+ ioc->pcidev,
+ host_page_buffer_sz,
+ &ioc->HostPageBuffer_dma)) != NULL) {
+
+ dinitprintk((MYIOC_s_INFO_FMT
+ "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
+ ioc->name,
+ ioc->HostPageBuffer,
+ ioc->HostPageBuffer_dma,
+ host_page_buffer_sz));
+ ioc->alloc_total += host_page_buffer_sz;
+ ioc->HostPageBuffer_sz = host_page_buffer_sz;
+ break;
+ }
+
+ host_page_buffer_sz -= (4*1024);
+ }
+ }
+
+ if(!ioc->HostPageBuffer) {
+ printk(MYIOC_s_ERR_FMT
+ "Failed to alloc memory for host_page_buffer!\n",
+ ioc->name);
+ return -999;
+ }
+
+ psge = (char *)&ioc_init->HostPageBufferSGE;
+ flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+ MPI_SGE_FLAGS_32_BIT_ADDRESSING |
+ MPI_SGE_FLAGS_HOST_TO_IOC |
+ MPI_SGE_FLAGS_END_OF_BUFFER;
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
+ }
+ flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
+ flags_length |= ioc->HostPageBuffer_sz;
+ mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+ ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
+
+return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
* mpt_verify_adapter - Given a unique IOC identifier, set pointer to
* the associated MPT adapter structure.
* @iocid: IOC unique identifier (integer)
@@ -988,9 +1112,9 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
if (ioc->id == iocid) {
*iocpp =ioc;
return iocid;
- }
+ }
}
-
+
*iocpp = NULL;
return -1;
}
@@ -1032,9 +1156,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_enable_device(pdev))
return r;
-
+
dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
-
+
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
@@ -1059,7 +1183,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
-
+
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
@@ -1079,7 +1203,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
/* Initilize SCSI Config Data structure
*/
- memset(&ioc->spi_data, 0, sizeof(ScsiCfgData));
+ memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
/* Initialize the running configQ head.
*/
@@ -1088,7 +1212,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
ioc->id = mpt_ids++;
-
+
mem_phys = msize = 0;
port = psize = 0;
for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
@@ -1143,7 +1267,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->prod_name = "LSIFC909";
ioc->bus_type = FC;
}
- if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
ioc->prod_name = "LSIFC929";
ioc->bus_type = FC;
}
@@ -1208,6 +1332,33 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->prod_name = "LSI53C1035";
ioc->bus_type = SCSI;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
+ ioc->prod_name = "LSISAS1064";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
+ ioc->prod_name = "LSISAS1066";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
+ ioc->prod_name = "LSISAS1068";
+ ioc->bus_type = SAS;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
+ ioc->prod_name = "LSISAS1064E";
+ ioc->bus_type = SAS;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
+ ioc->prod_name = "LSISAS1066E";
+ ioc->bus_type = SAS;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
+ ioc->prod_name = "LSISAS1068E";
+ ioc->bus_type = SAS;
+ }
if (ioc->errata_flag_1064)
pci_disable_io_access(pdev);
@@ -1322,7 +1473,7 @@ mpt_detach(struct pci_dev *pdev)
remove_proc_entry(pname, NULL);
sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
remove_proc_entry(pname, NULL);
-
+
/* call per device driver remove entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
@@ -1330,7 +1481,7 @@ mpt_detach(struct pci_dev *pdev)
MptDeviceDriverHandlers[ii]->remove(pdev);
}
}
-
+
/* Disable interrupts! */
CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
@@ -1403,7 +1554,7 @@ mpt_resume(struct pci_dev *pdev)
u32 device_state = pdev->current_state;
int recovery_state;
int ii;
-
+
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -1534,7 +1685,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
break;
}
-
+
if (ii == 5) {
dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1542,7 +1693,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
MptDisplayIocCapabilities(ioc);
}
-
+
if (alt_ioc_ready) {
if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
@@ -1599,8 +1750,23 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
*/
if (ret == 0) {
rc = mpt_do_upload(ioc, sleepFlag);
- if (rc != 0)
+ if (rc == 0) {
+ if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+ /*
+ * Maintain only one pointer to FW memory
+ * so there will not be two attempt to
+ * downloadboot onboard dual function
+ * chips (mpt_adapter_disable,
+ * mpt_diag_reset)
+ */
+ ioc->cached_fw = NULL;
+ ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
+ ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+ }
+ } else {
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
+ ret = -5;
+ }
}
}
}
@@ -1613,7 +1779,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (reset_alt_ioc_active && ioc->alt_ioc) {
/* (re)Enable alt-IOC! (reply interrupt) */
- dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
+ dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
ioc->alt_ioc->active = 1;
@@ -1635,7 +1801,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* and we try GetLanConfigPages again...
*/
if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
- if (ioc->bus_type == FC) {
+ if (ioc->bus_type == SAS) {
+
+ /* clear persistency table */
+ if(ioc->facts.IOCExceptions &
+ MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
+ ret = mptbase_sas_persist_operation(ioc,
+ MPI_SAS_OP_CLEAR_NOT_PRESENT);
+ if(ret != 0)
+ return -1;
+ }
+
+ /* Find IM volumes
+ */
+ mpt_findImVolumes(ioc);
+
+ } else if (ioc->bus_type == FC) {
/*
* Pre-fetch FC port WWN and stuff...
* (FCPortPage0_t stuff)
@@ -1670,7 +1851,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* Find IM volumes
*/
- if (ioc->facts.MsgVersion >= 0x0102)
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
mpt_findImVolumes(ioc);
/* Check, and possibly reset, the coalescing value
@@ -1700,7 +1881,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
}
if (alt_ioc_ready && MptResetHandlers[ii]) {
- dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
+ drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
handlers++;
@@ -1733,8 +1914,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
" searching for devfn match on %x or %x\n",
- ioc->name, pci_name(pdev), pdev->devfn,
- func-1, func+1));
+ ioc->name, pci_name(pdev), pdev->bus->number,
+ pdev->devfn, func-1, func+1));
peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
if (!peer) {
@@ -1778,7 +1959,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
if (ioc->cached_fw != NULL) {
ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
- if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
+ if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", ret);
}
@@ -1826,9 +2007,9 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
}
kfree(ioc->spi_data.nvram);
- kfree(ioc->spi_data.pIocPg3);
+ kfree(ioc->raid_data.pIocPg3);
ioc->spi_data.nvram = NULL;
- ioc->spi_data.pIocPg3 = NULL;
+ ioc->raid_data.pIocPg3 = NULL;
if (ioc->spi_data.pIocPg4 != NULL) {
sz = ioc->spi_data.IocPg4Sz;
@@ -1847,6 +2028,23 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
kfree(ioc->ChainToChain);
ioc->ChainToChain = NULL;
+
+ if (ioc->HostPageBuffer != NULL) {
+ if((ret = mpt_host_page_access_control(ioc,
+ MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
+ printk(KERN_ERR MYNAM
+ ": %s: host page buffers free failed (%d)!\n",
+ __FUNCTION__, ret);
+ }
+ dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
+ ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+ pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
+ ioc->HostPageBuffer,
+ ioc->HostPageBuffer_dma);
+ ioc->HostPageBuffer = NULL;
+ ioc->HostPageBuffer_sz = 0;
+ ioc->alloc_total -= ioc->HostPageBuffer_sz;
+ }
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1861,36 +2059,39 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
static void
mpt_adapter_dispose(MPT_ADAPTER *ioc)
{
- if (ioc != NULL) {
- int sz_first, sz_last;
+ int sz_first, sz_last;
- sz_first = ioc->alloc_total;
+ if (ioc == NULL)
+ return;
- mpt_adapter_disable(ioc);
+ sz_first = ioc->alloc_total;
- if (ioc->pci_irq != -1) {
- free_irq(ioc->pci_irq, ioc);
- ioc->pci_irq = -1;
- }
+ mpt_adapter_disable(ioc);
- if (ioc->memmap != NULL)
- iounmap(ioc->memmap);
+ if (ioc->pci_irq != -1) {
+ free_irq(ioc->pci_irq, ioc);
+ ioc->pci_irq = -1;
+ }
+
+ if (ioc->memmap != NULL) {
+ iounmap(ioc->memmap);
+ ioc->memmap = NULL;
+ }
#if defined(CONFIG_MTRR) && 0
- if (ioc->mtrr_reg > 0) {
- mtrr_del(ioc->mtrr_reg, 0, 0);
- dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
- }
+ if (ioc->mtrr_reg > 0) {
+ mtrr_del(ioc->mtrr_reg, 0, 0);
+ dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
+ }
#endif
- /* Zap the adapter lookup ptr! */
- list_del(&ioc->list);
+ /* Zap the adapter lookup ptr! */
+ list_del(&ioc->list);
- sz_last = ioc->alloc_total;
- dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
- ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
- kfree(ioc);
- }
+ sz_last = ioc->alloc_total;
+ dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
+ ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+ kfree(ioc);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1977,7 +2178,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
}
/* Is it already READY? */
- if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
+ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
return 0;
/*
@@ -1995,7 +2196,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Hmmm... Did it get left operational?
*/
if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
- dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+ dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
ioc->name));
/* Check WhoInit.
@@ -2004,8 +2205,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Else, fall through to KickStart case
*/
whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
- dprintk((KERN_WARNING MYNAM
- ": whoinit 0x%x\n statefault %d force %d\n",
+ dinitprintk((KERN_INFO MYNAM
+ ": whoinit 0x%x statefault %d force %d\n",
whoinit, statefault, force));
if (whoinit == MPI_WHOINIT_PCI_PEER)
return -4;
@@ -2026,7 +2227,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
* Loop here waiting for IOC to come READY.
*/
ii = 0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
+ cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
@@ -2140,8 +2341,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
get_facts.Function = MPI_FUNCTION_IOC_FACTS;
/* Assert: All other get_facts fields are zero! */
- dinitprintk((MYIOC_s_INFO_FMT
- "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
+ dinitprintk((MYIOC_s_INFO_FMT
+ "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
ioc->name, req_sz, reply_sz));
/* No non-zero fields in the get_facts request are greater than
@@ -2174,7 +2375,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
- status = facts->IOCStatus & MPI_IOCSTATUS_MASK;
+ status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
/* CHECKME! IOCStatus, IOCLogInfo */
facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
@@ -2204,6 +2405,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
le32_to_cpu(facts->CurrentSenseBufferHighAddr);
facts->CurReplyFrameSize =
le16_to_cpu(facts->CurReplyFrameSize);
+ facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
/*
* Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
@@ -2221,7 +2423,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
if ( sz & 0x02 )
sz += 2;
facts->FWImageSize = sz;
-
+
if (!facts->RequestFrameSize) {
/* Something is wrong! */
printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2240,7 +2442,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
ioc->NBShiftFactor = shiftFactor;
dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
ioc->name, vv, shiftFactor, r));
-
+
if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
/*
* Set values for this IOC's request & reply frame sizes,
@@ -2261,7 +2463,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
return r;
}
} else {
- printk(MYIOC_s_ERR_FMT
+ printk(MYIOC_s_ERR_FMT
"Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
RequestFrameSize)/sizeof(u32)));
@@ -2375,13 +2577,25 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
ioc->name, ioc->upload_fw, ioc->facts.Flags));
- if (ioc->bus_type == FC)
+ if(ioc->bus_type == SAS)
+ ioc_init.MaxDevices = ioc->facts.MaxDevices;
+ else if(ioc->bus_type == FC)
ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
else
ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
-
ioc_init.MaxBuses = MPT_MAX_BUS;
-
+ dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
+ ioc->name, ioc->facts.MsgVersion));
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+ // set MsgVersion and HeaderVersion host driver was built with
+ ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
+ ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
+
+ if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
+ ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
+ } else if(mpt_host_page_alloc(ioc, &ioc_init))
+ return -99;
+ }
ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
if (sizeof(dma_addr_t) == sizeof(u64)) {
@@ -2395,17 +2609,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
ioc_init.HostMfaHighAddr = cpu_to_le32(0);
ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
}
-
+
ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
+ ioc->facts.MaxDevices = ioc_init.MaxDevices;
+ ioc->facts.MaxBuses = ioc_init.MaxBuses;
dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
ioc->name, &ioc_init));
r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
- if (r != 0)
+ if (r != 0) {
+ printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
return r;
+ }
/* No need to byte swap the multibyte fields in the reply
* since we don't even look at it's contents.
@@ -2413,9 +2631,11 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
ioc->name, &ioc_init));
-
- if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
+
+ if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
+ printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
return r;
+ }
/* YIKES! SUPER IMPORTANT!!!
* Poll IocState until _OPERATIONAL while IOC is doing
@@ -2440,7 +2660,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
state = mpt_GetIocState(ioc, 1);
count++;
}
- dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
+ dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
ioc->name, count));
return r;
@@ -2462,7 +2682,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
{
PortEnable_t port_enable;
MPIDefaultReply_t reply_buf;
- int ii;
+ int rc;
int req_sz;
int reply_sz;
@@ -2484,22 +2704,15 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
/* RAID FW may take a long time to enable
*/
- if (ioc->bus_type == FC) {
- ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
- reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag);
- } else {
- ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+ if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+ > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
+ } else {
+ rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
+ reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
}
-
- if (ii != 0)
- return ii;
-
- /* We do not even look at the reply, so we need not
- * swap the multi-byte fields.
- */
-
- return 0;
+ return rc;
}
/*
@@ -2529,7 +2742,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
int sz;
sz = ioc->facts.FWImageSize;
- dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
pci_free_consistent(ioc->pcidev, sz,
ioc->cached_fw, ioc->cached_fw_dma);
@@ -2573,9 +2786,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
mpt_alloc_fw_memory(ioc, sz);
- dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
+ dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-
+
if (ioc->cached_fw == NULL) {
/* Major Failure.
*/
@@ -2605,14 +2818,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
- dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
+ dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
prequest, sgeoffset));
DBG_DUMP_FW_REQUEST_FRAME(prequest)
ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
- dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
+ dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
cmdStatus = -EFAULT;
if (ii == 0) {
@@ -2627,10 +2840,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
cmdStatus = 0;
}
}
- dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+ dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
ioc->name, cmdStatus));
-
+
if (cmdStatus) {
ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
@@ -2656,9 +2869,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
* <0 for fw upload failure.
*/
static int
-mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
+mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
{
- MpiFwHeader_t *pFwHeader;
MpiExtImageHeader_t *pExtImage;
u32 fwSize;
u32 diag0val;
@@ -2669,18 +2881,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
u32 load_addr;
u32 ioc_state=0;
- ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
- ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
-
- if ( ioc->facts.FWImageSize == 0 )
- return -1;
-
- if (ioc->cached_fw == NULL)
- return -2;
-
- /* prevent a second downloadboot and memory free with alt_ioc */
- if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
- ioc->alt_ioc->cached_fw = NULL;
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
+ ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
@@ -2708,16 +2910,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
ioc->name, count));
break;
}
- /* wait 1 sec */
+ /* wait .1 sec */
if (sleepFlag == CAN_SLEEP) {
- msleep_interruptible (1000);
+ msleep_interruptible (100);
} else {
- mdelay (1000);
+ mdelay (100);
}
}
if ( count == 30 ) {
- ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n",
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
+ "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
ioc->name, diag0val));
return -3;
}
@@ -2732,7 +2935,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* Set the DiagRwEn and Disable ARM bits */
CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
- pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
fwSize = (pFwHeader->ImageSize + 3)/4;
ptrFw = (u32 *) pFwHeader;
@@ -2761,8 +2963,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
fwSize = (pExtImage->ImageSize + 3) >> 2;
ptrFw = (u32 *)pExtImage;
- ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
- ioc->name, fwSize*4, ptrFw, load_addr));
+ ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
+ ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
while (fwSize--) {
@@ -2782,19 +2984,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* Clear the internal flash bad bit - autoincrementing register,
* so must do two writes.
*/
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
- diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
- diagRwData |= 0x4000000;
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
- CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+ if (ioc->bus_type == SCSI) {
+ /*
+ * 1030 and 1035 H/W errata, workaround to access
+ * the ClearFlashBadSignatureBit
+ */
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+ diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
+ diagRwData |= 0x40000000;
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
+ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+
+ } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
+ MPI_DIAG_CLEAR_FLASH_BAD_SIG);
+
+ /* wait 1 msec */
+ if (sleepFlag == CAN_SLEEP) {
+ msleep_interruptible (1);
+ } else {
+ mdelay (1);
+ }
+ }
if (ioc->errata_flag_1064)
pci_disable_io_access(ioc->pcidev);
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
- ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
+ ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
+ "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
ioc->name, diag0val));
- diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
+ diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
ioc->name, diag0val));
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
@@ -2802,10 +3023,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* Write 0xFF to reset the sequencer */
CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+ if (ioc->bus_type == SAS) {
+ ioc_state = mpt_GetIocState(ioc, 0);
+ if ( (GetIocFacts(ioc, sleepFlag,
+ MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
+ ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
+ ioc->name, ioc_state));
+ return -EFAULT;
+ }
+ }
+
for (count=0; count<HZ*20; count++) {
if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
ioc->name, count, ioc_state));
+ if (ioc->bus_type == SAS) {
+ return 0;
+ }
if ((SendIocInit(ioc, sleepFlag)) != 0) {
ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
ioc->name));
@@ -2845,9 +3079,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
* 0 else
*
* Returns:
- * 1 - hard reset, READY
- * 0 - no reset due to History bit, READY
- * -1 - no reset due to History bit but not READY
+ * 1 - hard reset, READY
+ * 0 - no reset due to History bit, READY
+ * -1 - no reset due to History bit but not READY
* OR reset but failed to come READY
* -2 - no reset, could not enter DIAG mode
* -3 - reset but bad FW bit
@@ -2990,7 +3224,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
*
*/
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
- mdelay (1);
+ mdelay(1);
/*
* Now hit the reset bit in the Diagnostic register
@@ -3039,12 +3273,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- ssleep(1);
+ msleep_interruptible (1000);
} else {
mdelay (1000);
}
}
- if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) {
+ if ((count = mpt_downloadboot(ioc,
+ (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", count);
}
@@ -3170,7 +3405,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
u32 state;
int cntdn, count;
- drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+ drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
ioc->name, reset_type));
CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
@@ -3374,6 +3609,9 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->reply_frames = (MPT_FRAME_HDR *) mem;
ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
+ dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
alloc_dma += reply_sz;
mem += reply_sz;
@@ -3382,7 +3620,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->req_frames = (MPT_FRAME_HDR *) mem;
ioc->req_frames_dma = alloc_dma;
- dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
+ dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
ioc->name, mem, (void *)(ulong)alloc_dma));
ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
@@ -3408,7 +3646,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
ioc->ChainBuffer = mem;
ioc->ChainBufferDMA = alloc_dma;
- dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
+ dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
/* Initialize the free chain Q.
@@ -3513,7 +3751,7 @@ out_fail:
*/
static int
mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
- int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
+ int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
{
MPIDefaultReply_t *mptReply;
int failcnt = 0;
@@ -3588,7 +3826,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
*/
if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
failcnt++;
-
+
dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
@@ -3624,7 +3862,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
int count = 0;
u32 intstat=0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+ cntdn = 1000 * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
@@ -3674,7 +3912,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
int count = 0;
u32 intstat=0;
- cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
+ cntdn = 1000 * howlong;
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
@@ -3747,7 +3985,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
}
dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
- ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
+ ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
/*
@@ -3819,7 +4057,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -3863,7 +4101,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -3930,7 +4168,7 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -3988,6 +4226,85 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
+ * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sas_address: 64bit SAS Address for operation.
+ * @target_id: specified target for operation
+ * @bus: specified bus for operation
+ * @persist_opcode: see below
+ *
+ * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
+ * devices not currently present.
+ * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
+ *
+ * NOTE: Don't use not this function during interrupt time.
+ *
+ * Returns: 0 for success, non-zero error
+ */
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int
+mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
+{
+ SasIoUnitControlRequest_t *sasIoUnitCntrReq;
+ SasIoUnitControlReply_t *sasIoUnitCntrReply;
+ MPT_FRAME_HDR *mf = NULL;
+ MPIHeader_t *mpi_hdr;
+
+
+ /* insure garbage is not sent to fw */
+ switch(persist_opcode) {
+
+ case MPI_SAS_OP_CLEAR_NOT_PRESENT:
+ case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
+
+ /* Get a MF for this command.
+ */
+ if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
+ printk("%s: no msg frames!\n",__FUNCTION__);
+ return -1;
+ }
+
+ mpi_hdr = (MPIHeader_t *) mf;
+ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
+ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
+ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
+ sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
+ sasIoUnitCntrReq->Operation = persist_opcode;
+
+ init_timer(&ioc->persist_timer);
+ ioc->persist_timer.data = (unsigned long) ioc;
+ ioc->persist_timer.function = mpt_timer_expired;
+ ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
+ ioc->persist_wait_done=0;
+ add_timer(&ioc->persist_timer);
+ mpt_put_msg_frame(mpt_base_index, ioc, mf);
+ wait_event(mpt_waitq, ioc->persist_wait_done);
+
+ sasIoUnitCntrReply =
+ (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+ if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
+ printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+ __FUNCTION__,
+ sasIoUnitCntrReply->IOCStatus,
+ sasIoUnitCntrReply->IOCLogInfo);
+ return -1;
+ }
+
+ printk("%s: success\n",__FUNCTION__);
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
* GetIoUnitPage2 - Retrieve BIOS version and boot order information.
* @ioc: Pointer to MPT_ADAPTER structure
*
@@ -4012,7 +4329,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc)
hdr.PageLength = 0;
hdr.PageNumber = 2;
hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
@@ -4102,7 +4419,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 0;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4122,6 +4439,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
ioc->spi_data.minSyncFactor = MPT_ASYNC;
ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
rc = 1;
+ ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
/* Save the Port Page 0 data
*/
@@ -4131,7 +4450,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
- dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+ ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
ioc->name, pPP0->Capabilities));
}
ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
@@ -4140,6 +4459,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
ioc->spi_data.minSyncFactor = (u8) (data >> 8);
+ ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
} else {
ioc->spi_data.maxSyncOffset = 0;
ioc->spi_data.minSyncFactor = MPT_ASYNC;
@@ -4152,8 +4473,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
- if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+ if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
ioc->spi_data.minSyncFactor = MPT_ULTRA;
+ ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
+ ioc->name, ioc->spi_data.minSyncFactor));
+ }
}
}
if (pbuf) {
@@ -4168,7 +4492,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4236,7 +4560,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = portnum;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4245,8 +4569,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp1version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp1length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
header.PageVersion = 0;
header.PageLength = 0;
@@ -4255,8 +4579,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
if (mpt_config(ioc, &cfg) != 0)
return -EFAULT;
- ioc->spi_data.sdp0version = cfg.hdr->PageVersion;
- ioc->spi_data.sdp0length = cfg.hdr->PageLength;
+ ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
+ ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
@@ -4298,7 +4622,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 2;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4320,10 +4644,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
if (mpt_config(ioc, &cfg) != 0)
goto done_and_free;
- if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
+ if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
mem = kmalloc(iocpage2sz, GFP_ATOMIC);
if (mem) {
- ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
+ ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
} else {
goto done_and_free;
}
@@ -4340,7 +4664,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
/* At least 1 RAID Volume
*/
pIocRv = pIoc2->RaidVolume;
- ioc->spi_data.isRaid = 0;
+ ioc->raid_data.isRaid = 0;
for (jj = 0; jj < nVols; jj++, pIocRv++) {
vid = pIocRv->VolumeID;
vbus = pIocRv->VolumeBus;
@@ -4349,7 +4673,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
/* find the match
*/
if (vbus == 0) {
- ioc->spi_data.isRaid |= (1 << vid);
+ ioc->raid_data.isRaid |= (1 << vid);
} else {
/* Error! Always bus 0
*/
@@ -4384,8 +4708,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
/* Free the old page
*/
- kfree(ioc->spi_data.pIocPg3);
- ioc->spi_data.pIocPg3 = NULL;
+ kfree(ioc->raid_data.pIocPg3);
+ ioc->raid_data.pIocPg3 = NULL;
/* There is at least one physical disk.
* Read and save IOC Page 3
@@ -4394,7 +4718,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 3;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4422,7 +4746,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
mem = kmalloc(iocpage3sz, GFP_ATOMIC);
if (mem) {
memcpy(mem, (u8 *)pIoc3, iocpage3sz);
- ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem;
+ ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
}
}
@@ -4446,7 +4770,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 4;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4498,7 +4822,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
header.PageLength = 0;
header.PageNumber = 1;
header.PageType = MPI_CONFIG_PAGETYPE_IOC;
- cfg.hdr = &header;
+ cfg.cfghdr.hdr = &header;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -4580,13 +4904,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
if (evnp == NULL) {
- dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
+ devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
ioc->name));
return 0;
}
memset(evnp, 0, sizeof(*evnp));
- dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch));
+ devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
evnp->ChainOffset = 0;
@@ -4610,8 +4934,10 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
EventAck_t *pAck;
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
- printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n",
- ioc->name);
+ printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
+ "request frame for Event=%x EventContext=%x EventData=%x!\n",
+ ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
+ le32_to_cpu(evnp->Data[0]));
return -1;
}
memset(pAck, 0, sizeof(*pAck));
@@ -4647,10 +4973,11 @@ int
mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
{
Config_t *pReq;
+ ConfigExtendedPageHeader_t *pExtHdr = NULL;
MPT_FRAME_HDR *mf;
unsigned long flags;
int ii, rc;
- u32 flagsLength;
+ int flagsLength;
int in_isr;
/* Prevent calling wait_event() (below), if caller happens
@@ -4675,16 +5002,30 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Reserved = 0;
pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_CONFIG;
+
+ /* Assume page type is not extended and clear "reserved" fields. */
pReq->ExtPageLength = 0;
pReq->ExtPageType = 0;
pReq->MsgFlags = 0;
+
for (ii=0; ii < 8; ii++)
pReq->Reserved2[ii] = 0;
- pReq->Header.PageVersion = pCfg->hdr->PageVersion;
- pReq->Header.PageLength = pCfg->hdr->PageLength;
- pReq->Header.PageNumber = pCfg->hdr->PageNumber;
- pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+ pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
+ pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
+ pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
+ pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
+
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
+ pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
+ pReq->ExtPageType = pExtHdr->ExtPageType;
+ pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+
+ /* Page Length must be treated as a reserved field for the extended header. */
+ pReq->Header.PageLength = 0;
+ }
+
pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
/* Add a SGE to the config request.
@@ -4694,12 +5035,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
else
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
- flagsLength |= pCfg->hdr->PageLength * 4;
+ if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+ flagsLength |= pExtHdr->ExtPageLength * 4;
- mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
+ }
+ else {
+ flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
+
+ dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
+ ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+ }
- dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
- ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+ mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
/* Append pCfg pointer to end of mf
*/
@@ -4789,8 +5138,8 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Reserved3 = 0;
pReq->NumAddressBytes = 0x01;
pReq->Reserved4 = 0;
- pReq->DataLength = 0x04;
- pdev = (struct pci_dev *) ioc->pcidev;
+ pReq->DataLength = cpu_to_le16(0x04);
+ pdev = ioc->pcidev;
if (pdev->devfn & 1)
pReq->DeviceAddr = 0xB2;
else
@@ -5321,8 +5670,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *
-EventDescriptionStr(u8 event, u32 evData0)
+static void
+EventDescriptionStr(u8 event, u32 evData0, char *evStr)
{
char *ds;
@@ -5375,8 +5724,95 @@ EventDescriptionStr(u8 event, u32 evData0)
ds = "Events(OFF) Change";
break;
case MPI_EVENT_INTEGRATED_RAID:
- ds = "Integrated Raid";
+ {
+ u8 ReasonCode = (u8)(evData0 >> 16);
+ switch (ReasonCode) {
+ case MPI_EVENT_RAID_RC_VOLUME_CREATED :
+ ds = "Integrated Raid: Volume Created";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_DELETED :
+ ds = "Integrated Raid: Volume Deleted";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
+ ds = "Integrated Raid: Volume Settings Changed";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
+ ds = "Integrated Raid: Volume Status Changed";
+ break;
+ case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
+ ds = "Integrated Raid: Volume Physdisk Changed";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
+ ds = "Integrated Raid: Physdisk Created";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
+ ds = "Integrated Raid: Physdisk Deleted";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
+ ds = "Integrated Raid: Physdisk Settings Changed";
+ break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
+ ds = "Integrated Raid: Physdisk Status Changed";
+ break;
+ case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
+ ds = "Integrated Raid: Domain Validation Needed";
+ break;
+ case MPI_EVENT_RAID_RC_SMART_DATA :
+ ds = "Integrated Raid; Smart Data";
+ break;
+ case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
+ ds = "Integrated Raid: Replace Action Started";
+ break;
+ default:
+ ds = "Integrated Raid";
+ break;
+ }
+ break;
+ }
+ case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
+ ds = "SCSI Device Status Change";
+ break;
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ {
+ u8 ReasonCode = (u8)(evData0 >> 16);
+ switch (ReasonCode) {
+ case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+ ds = "SAS Device Status Change: Added";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+ ds = "SAS Device Status Change: Deleted";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+ ds = "SAS Device Status Change: SMART Data";
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
+ ds = "SAS Device Status Change: No Persistancy Added";
+ break;
+ default:
+ ds = "SAS Device Status Change: Unknown";
+ break;
+ }
+ break;
+ }
+ case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
+ ds = "Bus Timer Expired";
+ break;
+ case MPI_EVENT_QUEUE_FULL:
+ ds = "Queue Full";
break;
+ case MPI_EVENT_SAS_SES:
+ ds = "SAS SES Event";
+ break;
+ case MPI_EVENT_PERSISTENT_TABLE_FULL:
+ ds = "Persistent Table Full";
+ break;
+ case MPI_EVENT_SAS_PHY_LINK_STATUS:
+ ds = "SAS PHY Link Status";
+ break;
+ case MPI_EVENT_SAS_DISCOVERY_ERROR:
+ ds = "SAS Discovery Error";
+ break;
+
/*
* MPT base "custom" events may be added here...
*/
@@ -5384,7 +5820,7 @@ EventDescriptionStr(u8 event, u32 evData0)
ds = "Unknown";
break;
}
- return ds;
+ strcpy(evStr,ds);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5406,7 +5842,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
int ii;
int r = 0;
int handlers = 0;
- char *evStr;
+ char evStr[100];
u8 event;
/*
@@ -5419,7 +5855,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
evData0 = le32_to_cpu(pEventReply->Data[0]);
}
- evStr = EventDescriptionStr(event, evData0);
+ EventDescriptionStr(event, evData0, evStr);
devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
ioc->name,
evStr,
@@ -5436,20 +5872,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* Do general / base driver event processing
*/
switch(event) {
- case MPI_EVENT_NONE: /* 00 */
- case MPI_EVENT_LOG_DATA: /* 01 */
- case MPI_EVENT_STATE_CHANGE: /* 02 */
- case MPI_EVENT_UNIT_ATTENTION: /* 03 */
- case MPI_EVENT_IOC_BUS_RESET: /* 04 */
- case MPI_EVENT_EXT_BUS_RESET: /* 05 */
- case MPI_EVENT_RESCAN: /* 06 */
- case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
- case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
- case MPI_EVENT_LOGOUT: /* 09 */
- case MPI_EVENT_INTEGRATED_RAID: /* 0B */
- case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */
- default:
- break;
case MPI_EVENT_EVENT_CHANGE: /* 0A */
if (evDataLen) {
u8 evState = evData0 & 0xFF;
@@ -5462,6 +5884,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
}
}
break;
+ default:
+ break;
}
/*
@@ -5504,6 +5928,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* If needed, send (a single) EventAck.
*/
if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
+ devtprintk((MYIOC_s_WARN_FMT
+ "EventAck required\n",ioc->name));
if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
ioc->name, ii));
@@ -5584,7 +6010,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
case 0x00080000:
desc = "Outbound DMA Overrun";
break;
-
+
case 0x00090000:
desc = "Task Management";
break;
@@ -5600,12 +6026,117 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
case 0x000C0000:
desc = "Untagged Table Size";
break;
-
+
}
printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
}
+/* strings for sas loginfo */
+ static char *originator_str[] = {
+ "IOP", /* 00h */
+ "PL", /* 01h */
+ "IR" /* 02h */
+ };
+ static char *iop_code_str[] = {
+ NULL, /* 00h */
+ "Invalid SAS Address", /* 01h */
+ NULL, /* 02h */
+ "Invalid Page", /* 03h */
+ NULL, /* 04h */
+ "Task Terminated" /* 05h */
+ };
+ static char *pl_code_str[] = {
+ NULL, /* 00h */
+ "Open Failure", /* 01h */
+ "Invalid Scatter Gather List", /* 02h */
+ "Wrong Relative Offset or Frame Length", /* 03h */
+ "Frame Transfer Error", /* 04h */
+ "Transmit Frame Connected Low", /* 05h */
+ "SATA Non-NCQ RW Error Bit Set", /* 06h */
+ "SATA Read Log Receive Data Error", /* 07h */
+ "SATA NCQ Fail All Commands After Error", /* 08h */
+ "SATA Error in Receive Set Device Bit FIS", /* 09h */
+ "Receive Frame Invalid Message", /* 0Ah */
+ "Receive Context Message Valid Error", /* 0Bh */
+ "Receive Frame Current Frame Error", /* 0Ch */
+ "SATA Link Down", /* 0Dh */
+ "Discovery SATA Init W IOS", /* 0Eh */
+ "Config Invalid Page", /* 0Fh */
+ "Discovery SATA Init Timeout", /* 10h */
+ "Reset", /* 11h */
+ "Abort", /* 12h */
+ "IO Not Yet Executed", /* 13h */
+ "IO Executed", /* 14h */
+ NULL, /* 15h */
+ NULL, /* 16h */
+ NULL, /* 17h */
+ NULL, /* 18h */
+ NULL, /* 19h */
+ NULL, /* 1Ah */
+ NULL, /* 1Bh */
+ NULL, /* 1Ch */
+ NULL, /* 1Dh */
+ NULL, /* 1Eh */
+ NULL, /* 1Fh */
+ "Enclosure Management" /* 20h */
+ };
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mpt_sas_log_info - Log information returned from SAS IOC.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @log_info: U32 LogInfo reply word from the IOC
+ *
+ * Refer to lsi/mpi_log_sas.h.
+ */
+static void
+mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
+{
+union loginfo_type {
+ u32 loginfo;
+ struct {
+ u32 subcode:16;
+ u32 code:8;
+ u32 originator:4;
+ u32 bus_type:4;
+ }dw;
+};
+ union loginfo_type sas_loginfo;
+ char *code_desc = NULL;
+
+ sas_loginfo.loginfo = log_info;
+ if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
+ (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
+ return;
+ if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
+ (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
+ code_desc = iop_code_str[sas_loginfo.dw.code];
+ }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
+ (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
+ code_desc = pl_code_str[sas_loginfo.dw.code];
+ }
+
+ if (code_desc != NULL)
+ printk(MYIOC_s_INFO_FMT
+ "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+ " SubCode(0x%04x)\n",
+ ioc->name,
+ log_info,
+ originator_str[sas_loginfo.dw.originator],
+ code_desc,
+ sas_loginfo.dw.subcode);
+ else
+ printk(MYIOC_s_INFO_FMT
+ "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
+ " SubCode(0x%04x)\n",
+ ioc->name,
+ log_info,
+ originator_str[sas_loginfo.dw.originator],
+ sas_loginfo.dw.code,
+ sas_loginfo.dw.subcode);
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
@@ -5692,7 +6223,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
break;
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
- /* This error is checked in scsi_io_done(). Skip.
+ /* This error is checked in scsi_io_done(). Skip.
desc = "SCSI Data Underrun";
*/
break;
@@ -5767,6 +6298,7 @@ EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
+EXPORT_SYMBOL(mptbase_sas_persist_operation);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 848fb236b175..75105277e22f 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -65,6 +65,7 @@
#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */
#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */
#include "lsi/mpi_tool.h" /* Tools support */
+#include "lsi/mpi_sas.h" /* SAS support */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -76,8 +77,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.02"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02"
+#define MPT_LINUX_VERSION_COMMON "3.03.03"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.03"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -423,7 +424,7 @@ typedef struct _MPT_IOCTL {
/*
* Event Structure and define
*/
-#define MPTCTL_EVENT_LOG_SIZE (0x0000000A)
+#define MPTCTL_EVENT_LOG_SIZE (0x000000032)
typedef struct _mpt_ioctl_events {
u32 event; /* Specified by define above */
u32 eventContext; /* Index or counter */
@@ -451,16 +452,13 @@ typedef struct _mpt_ioctl_events {
#define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */
/* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */
-typedef struct _ScsiCfgData {
+typedef struct _SpiCfgData {
u32 PortFlags;
int *nvram; /* table of device NVRAM values */
- IOCPage2_t *pIocPg2; /* table of Raid Volumes */
- IOCPage3_t *pIocPg3; /* table of physical disks */
IOCPage4_t *pIocPg4; /* SEP devices addressing */
dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */
int IocPg4Sz; /* IOCPage4 size */
u8 dvStatus[MPT_MAX_SCSI_DEVICES];
- int isRaid; /* bit field, 1 if RAID */
u8 minSyncFactor; /* 0xFF if async */
u8 maxSyncOffset; /* 0 if async */
u8 maxBusWidth; /* 0 if narrow, 1 if wide */
@@ -472,10 +470,28 @@ typedef struct _ScsiCfgData {
u8 dvScheduled; /* 1 if scheduled */
u8 forceDv; /* 1 to force DV scheduling */
u8 noQas; /* Disable QAS for this adapter */
- u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */
+ u8 Saf_Te; /* 1 to force all Processors as
+ * SAF-TE if Inquiry data length
+ * is too short to check for SAF-TE
+ */
u8 mpt_dv; /* command line option: enhanced=1, basic=0 */
+ u8 bus_reset; /* 1 to allow bus reset */
u8 rsvd[1];
-} ScsiCfgData;
+}SpiCfgData;
+
+typedef struct _SasCfgData {
+ u8 ptClear; /* 1 to automatically clear the
+ * persistent table.
+ * 0 to disable
+ * automatic clearing.
+ */
+}SasCfgData;
+
+typedef struct _RaidCfgData {
+ IOCPage2_t *pIocPg2; /* table of Raid Volumes */
+ IOCPage3_t *pIocPg3; /* table of physical disks */
+ int isRaid; /* bit field, 1 if RAID */
+}RaidCfgData;
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -530,11 +546,16 @@ typedef struct _MPT_ADAPTER
u8 *sense_buf_pool;
dma_addr_t sense_buf_pool_dma;
u32 sense_buf_low_dma;
+ u8 *HostPageBuffer; /* SAS - host page buffer support */
+ u32 HostPageBuffer_sz;
+ dma_addr_t HostPageBuffer_dma;
int mtrr_reg;
struct pci_dev *pcidev; /* struct pci_dev pointer */
u8 __iomem *memmap; /* mmap address */
struct Scsi_Host *sh; /* Scsi Host pointer */
- ScsiCfgData spi_data; /* Scsi config. data */
+ SpiCfgData spi_data; /* Scsi config. data */
+ RaidCfgData raid_data; /* Raid config. data */
+ SasCfgData sas_data; /* Sas config. data */
MPT_IOCTL *ioctl; /* ioctl data pointer */
struct proc_dir_entry *ioc_dentry;
struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */
@@ -554,31 +575,35 @@ typedef struct _MPT_ADAPTER
#else
u32 mfcnt;
#endif
- u32 NB_for_64_byte_frame;
+ u32 NB_for_64_byte_frame;
u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
IOCFactsReply_t facts;
PortFactsReply_t pfacts[2];
FCPortPage0_t fc_port_page0[2];
+ struct timer_list persist_timer; /* persist table timer */
+ int persist_wait_done; /* persist completion flag */
+ u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
LANPage0_t lan_cnfg_page0;
LANPage1_t lan_cnfg_page1;
- /*
+ /*
* Description: errata_flag_1064
* If a PCIX read occurs within 1 or 2 cycles after the chip receives
* a split completion for a read data, an internal address pointer incorrectly
* increments by 32 bytes
*/
- int errata_flag_1064;
+ int errata_flag_1064;
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
- u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
+ u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
u8 pad1[4];
int DoneCtx;
int TaskCtx;
int InternalCtx;
- struct list_head list;
+ struct list_head list;
struct net_device *netdev;
+ struct list_head sas_topology;
} MPT_ADAPTER;
/*
@@ -915,7 +940,10 @@ struct scsi_cmnd;
typedef struct _x_config_parms {
struct list_head linkage; /* linked list */
struct timer_list timer; /* timer function for this request */
- ConfigPageHeader_t *hdr;
+ union {
+ ConfigExtendedPageHeader_t *ehdr;
+ ConfigPageHeader_t *hdr;
+ } cfghdr;
dma_addr_t physAddr;
int wait_done; /* wait for this request */
u32 pageAddr; /* properly formatted */
@@ -961,6 +989,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
/*
* Public data decl's...
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 05ea5944c487..cb2d59d5f5af 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -242,7 +242,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
/* Set the command status to GOOD if IOC Status is GOOD
* OR if SCSI I/O cmd and data underrun or recovered error.
*/
- iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+ iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocStatus == MPI_IOCSTATUS_SUCCESS)
ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
@@ -1326,7 +1326,7 @@ mptctl_gettargetinfo (unsigned long arg)
*/
if (hd && hd->Targets) {
mpt_findImVolumes(ioc);
- pIoc2 = ioc->spi_data.pIocPg2;
+ pIoc2 = ioc->raid_data.pIocPg2;
for ( id = 0; id <= max_id; ) {
if ( pIoc2 && pIoc2->NumActiveVolumes ) {
if ( id == pIoc2->RaidVolume[0].VolumeID ) {
@@ -1348,7 +1348,7 @@ mptctl_gettargetinfo (unsigned long arg)
--maxWordsLeft;
goto next_id;
} else {
- pIoc3 = ioc->spi_data.pIocPg3;
+ pIoc3 = ioc->raid_data.pIocPg3;
for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
goto next_id;
@@ -2324,7 +2324,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
hdr.PageLength = 0;
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.pageAddr = 0;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
@@ -2333,7 +2333,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
strncpy(karg.serial_number, " ", 24);
if (mpt_config(ioc, &cfg) == 0) {
- if (cfg.hdr->PageLength > 0) {
+ if (cfg.cfghdr.hdr->PageLength > 0) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -2479,7 +2479,7 @@ mptctl_hp_targetinfo(unsigned long arg)
hdr.PageNumber = 0;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
cfg.timeout = 0;
@@ -2527,15 +2527,15 @@ mptctl_hp_targetinfo(unsigned long arg)
hdr.PageNumber = 3;
hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &hdr;
+ cfg.cfghdr.hdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
cfg.timeout = 0;
cfg.physAddr = -1;
- if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+ if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) {
/* Issue the second config page request */
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
- data_sz = (int) cfg.hdr->PageLength * 4;
+ data_sz = (int) cfg.cfghdr.hdr->PageLength * 4;
pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
ioc->pcidev, data_sz, &page_dma);
if (pg3_alloc) {
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 13771abea13f..a628be9bbbad 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -189,7 +189,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
- return -ENODEV;
+ return 0;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 52794be5a95c..ed3c891e388f 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -312,7 +312,12 @@ static int
mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
struct net_device *dev = ioc->netdev;
- struct mpt_lan_priv *priv = netdev_priv(dev);
+ struct mpt_lan_priv *priv;
+
+ if (dev == NULL)
+ return(1);
+ else
+ priv = netdev_priv(dev);
dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
new file mode 100644
index 000000000000..7de19a84dc74
--- /dev/null
+++ b/drivers/message/fusion/mptsas.c
@@ -0,0 +1,1239 @@
+/*
+ * linux/drivers/message/fusion/mptsas.c
+ * For use with LSI Logic PCI chip/adapter(s)
+ * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ * Copyright (c) 1999-2005 LSI Logic Corporation
+ * (mailto:mpt_linux_developer@lsil.com)
+ * Copyright (c) 2005 Dell
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ 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 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.
+
+ NO WARRANTY
+ THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ solely responsible for determining the appropriateness of using and
+ distributing the Program and assumes all risks associated with its
+ exercise of rights under this Agreement, including but not limited to
+ the risks and costs of program errors, damage to or loss of data,
+ programs or equipment, and unavailability or interruption of operations.
+
+ DISCLAIMER OF LIABILITY
+ NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ 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/errno.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_sas.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+
+#define my_NAME "Fusion MPT SAS Host driver"
+#define my_VERSION MPT_LINUX_VERSION_COMMON
+#define MYNAM "mptsas"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+static int mpt_pq_filter;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter,
+ "Enable peripheral qualifier filter: enable=1 "
+ "(default=0)");
+
+static int mpt_pt_clear;
+module_param(mpt_pt_clear, int, 0);
+MODULE_PARM_DESC(mpt_pt_clear,
+ "Clear persistency table: enable=1 "
+ "(default=MPTSCSIH_PT_CLEAR=0)");
+
+static int mptsasDoneCtx = -1;
+static int mptsasTaskCtx = -1;
+static int mptsasInternalCtx = -1; /* Used only for internal commands */
+
+
+/*
+ * SAS topology structures
+ *
+ * The MPT Fusion firmware interface spreads information about the
+ * SAS topology over many manufacture pages, thus we need some data
+ * structure to collect it and process it for the SAS transport class.
+ */
+
+struct mptsas_devinfo {
+ u16 handle; /* unique id to address this device */
+ u8 phy_id; /* phy number of parent device */
+ u8 port_id; /* sas physical port this device
+ is assoc'd with */
+ u8 target; /* logical target id of this device */
+ u8 bus; /* logical bus number of this device */
+ u64 sas_address; /* WWN of this device,
+ SATA is assigned by HBA,expander */
+ u32 device_info; /* bitfield detailed info about this device */
+};
+
+struct mptsas_phyinfo {
+ u8 phy_id; /* phy index */
+ u8 port_id; /* port number this phy is part of */
+ u8 negotiated_link_rate; /* nego'd link rate for this phy */
+ u8 hw_link_rate; /* hardware max/min phys link rate */
+ u8 programmed_link_rate; /* programmed max/min phy link rate */
+ struct mptsas_devinfo identify; /* point to phy device info */
+ struct mptsas_devinfo attached; /* point to attached device info */
+ struct sas_rphy *rphy;
+};
+
+struct mptsas_portinfo {
+ struct list_head list;
+ u16 handle; /* unique id to address this */
+ u8 num_phys; /* number of phys */
+ struct mptsas_phyinfo *phy_info;
+};
+
+/*
+ * This is pretty ugly. We will be able to seriously clean it up
+ * once the DV code in mptscsih goes away and we can properly
+ * implement ->target_alloc.
+ */
+static int
+mptsas_slave_alloc(struct scsi_device *device)
+{
+ struct Scsi_Host *host = device->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ VirtDevice *vdev;
+ uint target = device->id;
+ int i;
+
+ if ((vdev = hd->Targets[target]) != NULL)
+ goto out;
+
+ vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ if (!vdev) {
+ printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+ hd->ioc->name, sizeof(VirtDevice));
+ return -ENOMEM;
+ }
+
+ memset(vdev, 0, sizeof(VirtDevice));
+ vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
+ vdev->ioc_id = hd->ioc->id;
+
+ rphy = dev_to_rphy(device->sdev_target->dev.parent);
+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+ for (i = 0; i < p->num_phys; i++) {
+ if (p->phy_info[i].attached.sas_address ==
+ rphy->identify.sas_address) {
+ vdev->target_id =
+ p->phy_info[i].attached.target;
+ vdev->bus_id = p->phy_info[i].attached.bus;
+ hd->Targets[device->id] = vdev;
+ goto out;
+ }
+ }
+ }
+
+ printk("No matching SAS device found!!\n");
+ kfree(vdev);
+ return -ENODEV;
+
+ out:
+ vdev->num_luns++;
+ device->hostdata = vdev;
+ return 0;
+}
+
+static struct scsi_host_template mptsas_driver_template = {
+ .proc_name = "mptsas",
+ .proc_info = mptscsih_proc_info,
+ .name = "MPT SPI Host",
+ .info = mptscsih_info,
+ .queuecommand = mptscsih_qcmd,
+ .slave_alloc = mptsas_slave_alloc,
+ .slave_configure = mptscsih_slave_configure,
+ .slave_destroy = mptscsih_slave_destroy,
+ .change_queue_depth = mptscsih_change_queue_depth,
+ .eh_abort_handler = mptscsih_abort,
+ .eh_device_reset_handler = mptscsih_dev_reset,
+ .eh_bus_reset_handler = mptscsih_bus_reset,
+ .eh_host_reset_handler = mptscsih_host_reset,
+ .bios_param = mptscsih_bios_param,
+ .can_queue = MPT_FC_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = MPT_SCSI_SG_DEPTH,
+ .max_sectors = 8192,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+};
+
+static struct sas_function_template mptsas_transport_functions = {
+};
+
+static struct scsi_transport_template *mptsas_transport_template;
+
+#ifdef SASDEBUG
+static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
+{
+ printk("---- IO UNIT PAGE 0 ------------\n");
+ printk("Handle=0x%X\n",
+ le16_to_cpu(phy_data->AttachedDeviceHandle));
+ printk("Controller Handle=0x%X\n",
+ le16_to_cpu(phy_data->ControllerDevHandle));
+ printk("Port=0x%X\n", phy_data->Port);
+ printk("Port Flags=0x%X\n", phy_data->PortFlags);
+ printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
+ printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
+ printk("Controller PHY Device Info=0x%X\n",
+ le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
+ printk("DiscoveryStatus=0x%X\n",
+ le32_to_cpu(phy_data->DiscoveryStatus));
+ printk("\n");
+}
+
+static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
+{
+ __le64 sas_address;
+
+ memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
+
+ printk("---- SAS PHY PAGE 0 ------------\n");
+ printk("Attached Device Handle=0x%X\n",
+ le16_to_cpu(pg0->AttachedDevHandle));
+ printk("SAS Address=0x%llX\n",
+ (unsigned long long)le64_to_cpu(sas_address));
+ printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
+ printk("Attached Device Info=0x%X\n",
+ le32_to_cpu(pg0->AttachedDeviceInfo));
+ printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
+ printk("Change Count=0x%X\n", pg0->ChangeCount);
+ printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
+ printk("\n");
+}
+
+static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
+{
+ __le64 sas_address;
+
+ memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
+
+ printk("---- SAS DEVICE PAGE 0 ---------\n");
+ printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
+ printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
+ printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
+ printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
+ printk("Target ID=0x%X\n", pg0->TargetID);
+ printk("Bus=0x%X\n", pg0->Bus);
+ printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
+ printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
+ printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
+ printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
+ printk("Physical Port=0x%X\n", pg0->PhysicalPort);
+ printk("\n");
+}
+
+static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
+{
+ printk("---- SAS EXPANDER PAGE 1 ------------\n");
+
+ printk("Physical Port=0x%X\n", pg1->PhysicalPort);
+ printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
+ printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
+ printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
+ printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
+ printk("Owner Device Handle=0x%X\n",
+ le16_to_cpu(pg1->OwnerDevHandle));
+ printk("Attached Device Handle=0x%X\n",
+ le16_to_cpu(pg1->AttachedDevHandle));
+}
+#else
+#define mptsas_print_phy_data(phy_data) do { } while (0)
+#define mptsas_print_phy_pg0(pg0) do { } while (0)
+#define mptsas_print_device_pg0(pg0) do { } while (0)
+#define mptsas_print_expander_pg1(pg1) do { } while (0)
+#endif
+
+static int
+mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+{
+ ConfigExtendedPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ SasIOUnitPage0_t *buffer;
+ dma_addr_t dma_handle;
+ int error, i;
+
+ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+ hdr.ExtPageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.Reserved1 = 0;
+ hdr.Reserved2 = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+
+ cfg.cfghdr.ehdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.pageAddr = 0;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0; /* read */
+ cfg.timeout = 10;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out;
+ if (!hdr.ExtPageLength) {
+ error = -ENXIO;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ &dma_handle);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out_free_consistent;
+
+ port_info->num_phys = buffer->NumPhys;
+ port_info->phy_info = kcalloc(port_info->num_phys,
+ sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+ if (!port_info->phy_info) {
+ error = -ENOMEM;
+ goto out_free_consistent;
+ }
+
+ for (i = 0; i < port_info->num_phys; i++) {
+ mptsas_print_phy_data(&buffer->PhyData[i]);
+ port_info->phy_info[i].phy_id = i;
+ port_info->phy_info[i].port_id =
+ buffer->PhyData[i].Port;
+ port_info->phy_info[i].negotiated_link_rate =
+ buffer->PhyData[i].NegotiatedLinkRate;
+ }
+
+ out_free_consistent:
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ buffer, dma_handle);
+ out:
+ return error;
+}
+
+static int
+mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
+ u32 form, u32 form_specific)
+{
+ ConfigExtendedPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ SasPhyPage0_t *buffer;
+ dma_addr_t dma_handle;
+ int error;
+
+ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
+ hdr.ExtPageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.Reserved1 = 0;
+ hdr.Reserved2 = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
+
+ cfg.cfghdr.ehdr = &hdr;
+ cfg.dir = 0; /* read */
+ cfg.timeout = 10;
+
+ /* Get Phy Pg 0 for each Phy. */
+ cfg.physAddr = -1;
+ cfg.pageAddr = form + form_specific;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out;
+
+ if (!hdr.ExtPageLength) {
+ error = -ENXIO;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ &dma_handle);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out_free_consistent;
+
+ mptsas_print_phy_pg0(buffer);
+
+ phy_info->hw_link_rate = buffer->HwLinkRate;
+ phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
+ phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
+ phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
+
+ out_free_consistent:
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ buffer, dma_handle);
+ out:
+ return error;
+}
+
+static int
+mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
+ u32 form, u32 form_specific)
+{
+ ConfigExtendedPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ SasDevicePage0_t *buffer;
+ dma_addr_t dma_handle;
+ __le64 sas_address;
+ int error;
+
+ hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
+ hdr.ExtPageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.Reserved1 = 0;
+ hdr.Reserved2 = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+
+ cfg.cfghdr.ehdr = &hdr;
+ cfg.pageAddr = form + form_specific;
+ cfg.physAddr = -1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0; /* read */
+ cfg.timeout = 10;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out;
+ if (!hdr.ExtPageLength) {
+ error = -ENXIO;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ &dma_handle);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out_free_consistent;
+
+ mptsas_print_device_pg0(buffer);
+
+ device_info->handle = le16_to_cpu(buffer->DevHandle);
+ device_info->phy_id = buffer->PhyNum;
+ device_info->port_id = buffer->PhysicalPort;
+ device_info->target = buffer->TargetID;
+ device_info->bus = buffer->Bus;
+ memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
+ device_info->sas_address = le64_to_cpu(sas_address);
+ device_info->device_info =
+ le32_to_cpu(buffer->DeviceInfo);
+
+ out_free_consistent:
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ buffer, dma_handle);
+ out:
+ return error;
+}
+
+static int
+mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
+ u32 form, u32 form_specific)
+{
+ ConfigExtendedPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ SasExpanderPage0_t *buffer;
+ dma_addr_t dma_handle;
+ int error;
+
+ hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
+ hdr.ExtPageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.Reserved1 = 0;
+ hdr.Reserved2 = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+
+ cfg.cfghdr.ehdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.pageAddr = form + form_specific;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0; /* read */
+ cfg.timeout = 10;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out;
+
+ if (!hdr.ExtPageLength) {
+ error = -ENXIO;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ &dma_handle);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out_free_consistent;
+
+ /* save config data */
+ port_info->num_phys = buffer->NumPhys;
+ port_info->handle = le16_to_cpu(buffer->DevHandle);
+ port_info->phy_info = kcalloc(port_info->num_phys,
+ sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+ if (!port_info->phy_info) {
+ error = -ENOMEM;
+ goto out_free_consistent;
+ }
+
+ out_free_consistent:
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ buffer, dma_handle);
+ out:
+ return error;
+}
+
+static int
+mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
+ u32 form, u32 form_specific)
+{
+ ConfigExtendedPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ SasExpanderPage1_t *buffer;
+ dma_addr_t dma_handle;
+ int error;
+
+ hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
+ hdr.ExtPageLength = 0;
+ hdr.PageNumber = 1;
+ hdr.Reserved1 = 0;
+ hdr.Reserved2 = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+
+ cfg.cfghdr.ehdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.pageAddr = form + form_specific;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0; /* read */
+ cfg.timeout = 10;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out;
+
+ if (!hdr.ExtPageLength) {
+ error = -ENXIO;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ &dma_handle);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ error = mpt_config(ioc, &cfg);
+ if (error)
+ goto out_free_consistent;
+
+
+ mptsas_print_expander_pg1(buffer);
+
+ /* save config data */
+ phy_info->phy_id = buffer->PhyIdentifier;
+ phy_info->port_id = buffer->PhysicalPort;
+ phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
+ phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
+ phy_info->hw_link_rate = buffer->HwLinkRate;
+ phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
+ phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
+
+
+ out_free_consistent:
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+ buffer, dma_handle);
+ out:
+ return error;
+}
+
+static void
+mptsas_parse_device_info(struct sas_identify *identify,
+ struct mptsas_devinfo *device_info)
+{
+ u16 protocols;
+
+ identify->sas_address = device_info->sas_address;
+ identify->phy_identifier = device_info->phy_id;
+
+ /*
+ * Fill in Phy Initiator Port Protocol.
+ * Bits 6:3, more than one bit can be set, fall through cases.
+ */
+ protocols = device_info->device_info & 0x78;
+ identify->initiator_port_protocols = 0;
+ if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
+ if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
+ if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
+ if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
+
+ /*
+ * Fill in Phy Target Port Protocol.
+ * Bits 10:7, more than one bit can be set, fall through cases.
+ */
+ protocols = device_info->device_info & 0x780;
+ identify->target_port_protocols = 0;
+ if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_SSP;
+ if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_STP;
+ if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_SMP;
+ if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ identify->target_port_protocols |= SAS_PROTOCOL_SATA;
+
+ /*
+ * Fill in Attached device type.
+ */
+ switch (device_info->device_info &
+ MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+ case MPI_SAS_DEVICE_INFO_NO_DEVICE:
+ identify->device_type = SAS_PHY_UNUSED;
+ break;
+ case MPI_SAS_DEVICE_INFO_END_DEVICE:
+ identify->device_type = SAS_END_DEVICE;
+ break;
+ case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
+ identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
+ break;
+ case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+ identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
+ break;
+ }
+}
+
+static int mptsas_probe_one_phy(struct device *dev,
+ struct mptsas_phyinfo *phy_info, int index)
+{
+ struct sas_phy *port;
+ int error;
+
+ port = sas_phy_alloc(dev, index);
+ if (!port)
+ return -ENOMEM;
+
+ port->port_identifier = phy_info->port_id;
+ mptsas_parse_device_info(&port->identify, &phy_info->identify);
+
+ /*
+ * Set Negotiated link rate.
+ */
+ switch (phy_info->negotiated_link_rate) {
+ case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
+ port->negotiated_linkrate = SAS_PHY_DISABLED;
+ break;
+ case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
+ port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+ break;
+ case MPI_SAS_IOUNIT0_RATE_1_5:
+ port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI_SAS_IOUNIT0_RATE_3_0:
+ port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
+ case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
+ default:
+ port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+ break;
+ }
+
+ /*
+ * Set Max hardware link rate.
+ */
+ switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+ case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
+ port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+ port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Set Max programmed link rate.
+ */
+ switch (phy_info->programmed_link_rate &
+ MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
+ port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
+ port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Set Min hardware link rate.
+ */
+ switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
+ case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
+ port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+ port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Set Min programmed link rate.
+ */
+ switch (phy_info->programmed_link_rate &
+ MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
+ port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
+ port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ default:
+ break;
+ }
+
+ error = sas_phy_add(port);
+ if (error) {
+ sas_phy_free(port);
+ return error;
+ }
+
+ if (phy_info->attached.handle) {
+ struct sas_rphy *rphy;
+
+ rphy = sas_rphy_alloc(port);
+ if (!rphy)
+ return 0; /* non-fatal: an rphy can be added later */
+
+ mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+ error = sas_rphy_add(rphy);
+ if (error) {
+ sas_rphy_free(rphy);
+ return error;
+ }
+
+ phy_info->rphy = rphy;
+ }
+
+ return 0;
+}
+
+static int
+mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
+{
+ struct mptsas_portinfo *port_info;
+ u32 handle = 0xFFFF;
+ int error = -ENOMEM, i;
+
+ port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ if (!port_info)
+ goto out;
+ memset(port_info, 0, sizeof(*port_info));
+
+ error = mptsas_sas_io_unit_pg0(ioc, port_info);
+ if (error)
+ goto out_free_port_info;
+
+ list_add_tail(&port_info->list, &ioc->sas_topology);
+
+ for (i = 0; i < port_info->num_phys; i++) {
+ mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
+ (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
+ MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
+
+ mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
+ (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
+ port_info->phy_info[i].identify.phy_id =
+ port_info->phy_info[i].phy_id;
+ handle = port_info->phy_info[i].identify.handle;
+
+ if (port_info->phy_info[i].attached.handle) {
+ mptsas_sas_device_pg0(ioc,
+ &port_info->phy_info[i].attached,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ port_info->phy_info[i].attached.handle);
+ }
+
+ mptsas_probe_one_phy(&ioc->sh->shost_gendev,
+ &port_info->phy_info[i], *index);
+ (*index)++;
+ }
+
+ return 0;
+
+ out_free_port_info:
+ kfree(port_info);
+ out:
+ return error;
+}
+
+static int
+mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
+{
+ struct mptsas_portinfo *port_info, *p;
+ int error = -ENOMEM, i, j;
+
+ port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ if (!port_info)
+ goto out;
+ memset(port_info, 0, sizeof(*port_info));
+
+ error = mptsas_sas_expander_pg0(ioc, port_info,
+ (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+ MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
+ if (error)
+ goto out_free_port_info;
+
+ *handle = port_info->handle;
+
+ list_add_tail(&port_info->list, &ioc->sas_topology);
+ for (i = 0; i < port_info->num_phys; i++) {
+ struct device *parent;
+
+ mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
+ (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
+ MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
+
+ if (port_info->phy_info[i].identify.handle) {
+ mptsas_sas_device_pg0(ioc,
+ &port_info->phy_info[i].identify,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ port_info->phy_info[i].identify.handle);
+ port_info->phy_info[i].identify.phy_id =
+ port_info->phy_info[i].phy_id;
+ }
+
+ if (port_info->phy_info[i].attached.handle) {
+ mptsas_sas_device_pg0(ioc,
+ &port_info->phy_info[i].attached,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ port_info->phy_info[i].attached.handle);
+ }
+
+ /*
+ * If we find a parent port handle this expander is
+ * attached to another expander, else it hangs of the
+ * HBA phys.
+ */
+ parent = &ioc->sh->shost_gendev;
+ list_for_each_entry(p, &ioc->sas_topology, list) {
+ for (j = 0; j < p->num_phys; j++) {
+ if (port_info->phy_info[i].identify.handle ==
+ p->phy_info[j].attached.handle)
+ parent = &p->phy_info[j].rphy->dev;
+ }
+ }
+
+ mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index);
+ (*index)++;
+ }
+
+ return 0;
+
+ out_free_port_info:
+ kfree(port_info);
+ out:
+ return error;
+}
+
+static void
+mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
+{
+ u32 handle = 0xFFFF;
+ int index = 0;
+
+ mptsas_probe_hba_phys(ioc, &index);
+ while (!mptsas_probe_expander_phys(ioc, &handle, &index))
+ ;
+}
+
+static int
+mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct Scsi_Host *sh;
+ MPT_SCSI_HOST *hd;
+ MPT_ADAPTER *ioc;
+ unsigned long flags;
+ int sz, ii;
+ int numSGE = 0;
+ int scale;
+ int ioc_cap;
+ u8 *mem;
+ int error=0;
+ int r;
+
+ r = mpt_attach(pdev,id);
+ if (r)
+ return r;
+
+ ioc = pci_get_drvdata(pdev);
+ ioc->DoneCtx = mptsasDoneCtx;
+ ioc->TaskCtx = mptsasTaskCtx;
+ ioc->InternalCtx = mptsasInternalCtx;
+
+ /* Added sanity check on readiness of the MPT adapter.
+ */
+ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping because it's not operational!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ if (!ioc->active) {
+ printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ /* Sanity check - ensure at least 1 port is INITIATOR capable
+ */
+ ioc_cap = 0;
+ for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
+ if (ioc->pfacts[ii].ProtocolFlags &
+ MPI_PORTFACTS_PROTOCOL_INITIATOR)
+ ioc_cap++;
+ }
+
+ if (!ioc_cap) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping ioc=%p because SCSI Initiator mode "
+ "is NOT enabled!\n", ioc->name, ioc);
+ return 0;
+ }
+
+ sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
+ if (!sh) {
+ printk(MYIOC_s_WARN_FMT
+ "Unable to register controller with SCSI subsystem\n",
+ ioc->name);
+ return -1;
+ }
+
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+ /* Attach the SCSI Host to the IOC structure
+ */
+ ioc->sh = sh;
+
+ sh->io_port = 0;
+ sh->n_io_port = 0;
+ sh->irq = 0;
+
+ /* set 16 byte cdb's */
+ sh->max_cmd_len = 16;
+
+ sh->max_id = ioc->pfacts->MaxDevices + 1;
+
+ sh->transportt = mptsas_transport_template;
+
+ sh->max_lun = MPT_LAST_LUN + 1;
+ sh->max_channel = 0;
+ sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+ /* Required entry.
+ */
+ sh->unique_id = ioc->id;
+
+ INIT_LIST_HEAD(&ioc->sas_topology);
+
+ /* Verify that we won't exceed the maximum
+ * number of chain buffers
+ * We can optimize: ZZ = req_sz/sizeof(SGE)
+ * For 32bit SGE's:
+ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+ * + (req_sz - 64)/sizeof(SGE)
+ * A slightly different algorithm is required for
+ * 64bit SGEs.
+ */
+ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ numSGE = (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ } else {
+ numSGE = 1 + (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ }
+
+ if (numSGE < sh->sg_tablesize) {
+ /* Reset this value */
+ dprintk((MYIOC_s_INFO_FMT
+ "Resetting sg_tablesize to %d from %d\n",
+ ioc->name, numSGE, sh->sg_tablesize));
+ sh->sg_tablesize = numSGE;
+ }
+
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+ hd = (MPT_SCSI_HOST *) sh->hostdata;
+ hd->ioc = ioc;
+
+ /* SCSI needs scsi_cmnd lookup table!
+ * (with size equal to req_depth*PtrSz!)
+ */
+ sz = ioc->req_depth * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptsas_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ ioc->name, hd->ScsiLookup, sz));
+
+ /* Allocate memory for the device structures.
+ * A non-Null pointer at an offset
+ * indicates a device exists.
+ * max_id = 1 + maximum id (hosts.h)
+ */
+ sz = sh->max_id * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptsas_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->Targets = (VirtDevice **) mem;
+
+ dprintk((KERN_INFO
+ " Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+ /* Clear the TM flags
+ */
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ hd->resetPending = 0;
+ hd->abortSCpnt = NULL;
+
+ /* Clear the pointer used to store
+ * single-threaded commands, i.e., those
+ * issued during a bus scan, dv and
+ * configuration pages.
+ */
+ hd->cmdPtr = NULL;
+
+ /* Initialize this SCSI Hosts' timers
+ * To use, set the timer expires field
+ * and add_timer
+ */
+ init_timer(&hd->timer);
+ hd->timer.data = (unsigned long) hd;
+ hd->timer.function = mptscsih_timer_expired;
+
+ hd->mpt_pq_filter = mpt_pq_filter;
+ ioc->sas_data.ptClear = mpt_pt_clear;
+
+ if (ioc->sas_data.ptClear==1) {
+ mptbase_sas_persist_operation(
+ ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
+ }
+
+ ddvprintk((MYIOC_s_INFO_FMT
+ "mpt_pq_filter %x mpt_pq_filter %x\n",
+ ioc->name,
+ mpt_pq_filter,
+ mpt_pq_filter));
+
+ init_waitqueue_head(&hd->scandv_waitq);
+ hd->scandv_wait_done = 0;
+ hd->last_queue_full = 0;
+
+ error = scsi_add_host(sh, &ioc->pcidev->dev);
+ if (error) {
+ dprintk((KERN_ERR MYNAM
+ "scsi_add_host failed\n"));
+ goto mptsas_probe_failed;
+ }
+
+ mptsas_scan_sas_topology(ioc);
+
+ return 0;
+
+mptsas_probe_failed:
+
+ mptscsih_remove(pdev);
+ return error;
+}
+
+static void __devexit mptsas_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptsas_portinfo *p, *n;
+
+ sas_remove_host(ioc->sh);
+
+ list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
+
+ mptscsih_remove(pdev);
+}
+
+static struct pci_device_id mptsas_pci_table[] = {
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
+
+
+static struct pci_driver mptsas_driver = {
+ .name = "mptsas",
+ .id_table = mptsas_pci_table,
+ .probe = mptsas_probe,
+ .remove = __devexit_p(mptsas_remove),
+ .shutdown = mptscsih_shutdown,
+#ifdef CONFIG_PM
+ .suspend = mptscsih_suspend,
+ .resume = mptscsih_resume,
+#endif
+};
+
+static int __init
+mptsas_init(void)
+{
+ show_mptmod_ver(my_NAME, my_VERSION);
+
+ mptsas_transport_template =
+ sas_attach_transport(&mptsas_transport_functions);
+ if (!mptsas_transport_template)
+ return -ENODEV;
+
+ mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
+ mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+ mptsasInternalCtx =
+ mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
+
+ if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
+ if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+ dprintk((KERN_INFO MYNAM
+ ": Registered for IOC reset notifications\n"));
+ }
+
+ return pci_register_driver(&mptsas_driver);
+}
+
+static void __exit
+mptsas_exit(void)
+{
+ pci_unregister_driver(&mptsas_driver);
+ sas_release_transport(mptsas_transport_template);
+
+ mpt_reset_deregister(mptsasDoneCtx);
+ mpt_event_deregister(mptsasDoneCtx);
+
+ mpt_deregister(mptsasInternalCtx);
+ mpt_deregister(mptsasTaskCtx);
+ mpt_deregister(mptsasDoneCtx);
+}
+
+module_init(mptsas_init);
+module_exit(mptsas_exit);
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b9d4f78725b4..5cb07eb224d7 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -62,6 +62,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -93,8 +94,9 @@ typedef struct _BIG_SENSE_BUF {
#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
+#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
@@ -159,6 +161,8 @@ int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
+static struct work_struct mptscsih_persistTask;
+
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static void mptscsih_domainValidation(void *hd);
@@ -167,6 +171,7 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
+static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
#endif
void mptscsih_remove(struct pci_dev *);
@@ -281,12 +286,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
chain_idx = offset / ioc->req_sz;
rc = SUCCESS;
- dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
- ioc->name, *retIndex, chainBuf));
+ dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
+ ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
} else {
rc = FAILED;
chain_idx = MPT_HOST_NO_CHAIN;
- dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+ dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
ioc->name));
}
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -432,7 +437,7 @@ nextSGEset:
*/
pReq->ChainOffset = 0;
RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
- dsgprintk((MYIOC_s_ERR_FMT
+ dsgprintk((MYIOC_s_INFO_FMT
"Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
ioc->RequestNB[req_idx] = RequestNB;
}
@@ -491,11 +496,12 @@ nextSGEset:
/* NOTE: psge points to the beginning of the chain element
* in current buffer. Get a chain buffer.
*/
- dsgprintk((MYIOC_s_INFO_FMT
- "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
- ioc->name, pReq->CDB[0], SCpnt));
- if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
+ if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
+ dfailprintk((MYIOC_s_INFO_FMT
+ "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
+ ioc->name, pReq->CDB[0], SCpnt));
return FAILED;
+ }
/* Update the tracking arrays.
* If chainSge == NULL, update ReqToChain, else ChainToChain
@@ -577,14 +583,20 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1;
}
- dmfprintk((MYIOC_s_INFO_FMT
- "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
- ioc->name, mf, mr, sc, req_idx));
-
sc->result = DID_OK << 16; /* Set default reply as OK */
pScsiReq = (SCSIIORequest_t *) mf;
pScsiReply = (SCSIIOReply_t *) mr;
+ if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
+ dmfprintk((MYIOC_s_INFO_FMT
+ "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
+ ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
+ }else{
+ dmfprintk((MYIOC_s_INFO_FMT
+ "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
+ ioc->name, mf, mr, sc, req_idx));
+ }
+
if (pScsiReply == NULL) {
/* special context reply handling */
;
@@ -599,11 +611,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
sc->resid = sc->request_bufflen - xfer_cnt;
+ /*
+ * if we get a data underrun indication, yet no data was
+ * transferred and the SCSI status indicates that the
+ * command was never started, change the data underrun
+ * to success
+ */
+ if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
+ (scsi_status == MPI_SCSI_STATUS_BUSY ||
+ scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
+ scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
+ status = MPI_IOCSTATUS_SUCCESS;
+ }
+
dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
"resid=%d bufflen=%d xfer_cnt=%d\n",
ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
- status, scsi_state, scsi_status, sc->resid,
+ status, scsi_state, scsi_status, sc->resid,
sc->request_bufflen, xfer_cnt));
if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
@@ -612,8 +637,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
/*
* Look for + dump FCP ResponseInfo[]!
*/
- if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
- printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
+ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
+ pScsiReply->ResponseInfo) {
+ printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+ "FCP_ResponseInfo=%08xh\n",
+ ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
le32_to_cpu(pScsiReply->ResponseInfo));
}
@@ -654,21 +682,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
break;
case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
- if ( xfer_cnt >= sc->underflow ) {
- /* Sufficient data transfer occurred */
+ sc->resid = sc->request_bufflen - xfer_cnt;
+ if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
+ sc->result=DID_SOFT_ERROR << 16;
+ else /* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status;
- } else if ( xfer_cnt == 0 ) {
- /* A CRC Error causes this condition; retry */
- sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
- (CHECK_CONDITION << 1);
- sc->sense_buffer[0] = 0x70;
- sc->sense_buffer[2] = NO_SENSE;
- sc->sense_buffer[12] = 0;
- sc->sense_buffer[13] = 0;
- } else {
- sc->result = DID_SOFT_ERROR << 16;
- }
- dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+ dreplyprintk((KERN_NOTICE
+ "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
break;
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
@@ -683,7 +703,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
;
} else {
if (xfer_cnt < sc->underflow) {
- sc->result = DID_SOFT_ERROR << 16;
+ if (scsi_status == SAM_STAT_BUSY)
+ sc->result = SAM_STAT_BUSY;
+ else
+ sc->result = DID_SOFT_ERROR << 16;
}
if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
/* What to do?
@@ -708,8 +731,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
- scsi_status = pScsiReply->SCSIStatus;
- sc->result = (DID_OK << 16) | scsi_status;
+ if (scsi_status == MPI_SCSI_STATUS_BUSY)
+ sc->result = (DID_BUS_BUSY << 16) | scsi_status;
+ else
+ sc->result = (DID_OK << 16) | scsi_status;
if (scsi_state == 0) {
;
} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -796,7 +821,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1;
}
-
/*
* mptscsih_flush_running_cmds - For each command found, search
* Scsi_Host instance taskQ and reply to OS.
@@ -882,12 +906,13 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
SCSIIORequest_t *mf = NULL;
int ii;
int max = hd->ioc->req_depth;
+ struct scsi_cmnd *sc;
dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
target, lun, max));
for (ii=0; ii < max; ii++) {
- if (hd->ScsiLookup[ii] != NULL) {
+ if ((sc = hd->ScsiLookup[ii]) != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
@@ -902,9 +927,22 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd->ioc, ii);
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+ if (sc->use_sg) {
+ pci_unmap_sg(hd->ioc->pcidev,
+ (struct scatterlist *) sc->request_buffer,
+ sc->use_sg,
+ sc->sc_data_direction);
+ } else if (sc->request_bufflen) {
+ pci_unmap_single(hd->ioc->pcidev,
+ sc->SCp.dma_handle,
+ sc->request_bufflen,
+ sc->sc_data_direction);
+ }
+ sc->host_scribble = NULL;
+ sc->result = DID_NO_CONNECT << 16;
+ sc->scsi_done(sc);
}
}
-
return;
}
@@ -959,8 +997,10 @@ mptscsih_remove(struct pci_dev *pdev)
unsigned long flags;
int sz1;
- if(!host)
+ if(!host) {
+ mpt_detach(pdev);
return;
+ }
scsi_remove_host(host);
@@ -1017,7 +1057,7 @@ mptscsih_remove(struct pci_dev *pdev)
scsi_host_put(host);
mpt_detach(pdev);
-
+
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1072,7 +1112,7 @@ mptscsih_resume(struct pci_dev *pdev)
MPT_SCSI_HOST *hd;
mpt_resume(pdev);
-
+
if(!host)
return 0;
@@ -1214,8 +1254,8 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off
int size = 0;
if (func) {
- /*
- * write is not supported
+ /*
+ * write is not supported
*/
} else {
if (start)
@@ -1248,8 +1288,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
SCSIIORequest_t *pScsiReq;
- VirtDevice *pTarget;
- int target;
+ VirtDevice *pTarget = SCpnt->device->hostdata;
int lun;
u32 datalen;
u32 scsictl;
@@ -1259,12 +1298,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
int ii;
hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
- target = SCpnt->device->id;
lun = SCpnt->device->lun;
SCpnt->scsi_done = done;
- pTarget = hd->Targets[target];
-
dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
@@ -1307,7 +1343,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Default to untagged. Once a target structure has been allocated,
* use the Inquiry data to determine if device supports tagged.
*/
- if ( pTarget
+ if (pTarget
&& (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
@@ -1317,8 +1353,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Use the above information to set up the message frame
*/
- pScsiReq->TargetID = (u8) target;
- pScsiReq->Bus = (u8) SCpnt->device->channel;
+ pScsiReq->TargetID = (u8) pTarget->target_id;
+ pScsiReq->Bus = pTarget->bus_id;
pScsiReq->ChainOffset = 0;
pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
pScsiReq->CDBLength = SCpnt->cmd_len;
@@ -1370,7 +1406,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
if (hd->ioc->bus_type == SCSI) {
- int dvStatus = hd->ioc->spi_data.dvStatus[target];
+ int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
int issueCmd = 1;
if (dvStatus || hd->ioc->spi_data.forceDv) {
@@ -1418,6 +1454,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
return 0;
fail:
+ hd->ScsiLookup[my_idx] = NULL;
mptscsih_freeChainBuffers(hd->ioc, my_idx);
mpt_free_msg_frame(hd->ioc, mf);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1535,17 +1572,17 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
*/
if (mptscsih_tm_pending_wait(hd) == FAILED) {
if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
- dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
@@ -1631,8 +1668,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
hd->ioc->name));
- //return FAILED;
- return -999;
+ return FAILED;
}
dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
hd->ioc->name, mf));
@@ -1661,9 +1697,8 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->TaskMsgContext = ctx2abort;
- dtmprintk((MYIOC_s_INFO_FMT
- "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
- hd->ioc->name, ctx2abort, type));
+ dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+ hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
@@ -1707,24 +1742,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
MPT_FRAME_HDR *mf;
u32 ctx2abort;
int scpnt_idx;
+ int retval;
/* If we can't locate our host adapter structure, return FAILED status.
*/
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
SCpnt->result = DID_RESET << 16;
SCpnt->scsi_done(SCpnt);
- dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+ dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
"Can't locate host! (sc=%p)\n",
SCpnt));
return FAILED;
}
ioc = hd->ioc;
- if (hd->resetPending)
+ if (hd->resetPending) {
return FAILED;
-
- printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
- hd->ioc->name, SCpnt);
+ }
if (hd->timeouts < -1)
hd->timeouts++;
@@ -1732,16 +1766,20 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
/* Find this command
*/
if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
- /* Cmd not found in ScsiLookup.
+ /* Cmd not found in ScsiLookup.
* Do OS callback.
*/
SCpnt->result = DID_RESET << 16;
- dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
+ dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
"Command not in the active list! (sc=%p)\n",
hd->ioc->name, SCpnt));
return SUCCESS;
}
+ printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
+ hd->ioc->name, SCpnt);
+ scsi_print_command(SCpnt);
+
/* Most important! Set TaskMsgContext to SCpnt's MsgContext!
* (the IO to be ABORT'd)
*
@@ -1754,38 +1792,22 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
hd->abortSCpnt = SCpnt;
- if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+ retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
- ctx2abort, 2 /* 2 second timeout */)
- < 0) {
+ ctx2abort, 2 /* 2 second timeout */);
- /* The TM request failed and the subsequent FW-reload failed!
- * Fatal error case.
- */
- printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
- hd->ioc->name, SCpnt);
+ printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
+ hd->ioc->name,
+ ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
- /* We must clear our pending flag before clearing our state.
- */
+ if (retval == 0)
+ return SUCCESS;
+
+ if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
-
- /* Unmap the DMA buffers, if any. */
- if (SCpnt->use_sg) {
- pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
- SCpnt->use_sg, SCpnt->sc_data_direction);
- } else if (SCpnt->request_bufflen) {
- pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
- SCpnt->request_bufflen, SCpnt->sc_data_direction);
- }
- hd->ScsiLookup[scpnt_idx] = NULL;
- SCpnt->result = DID_RESET << 16;
- SCpnt->scsi_done(SCpnt); /* Issue the command callback */
- mptscsih_freeChainBuffers(ioc, scpnt_idx);
- mpt_free_msg_frame(ioc, mf);
- return FAILED;
}
- return SUCCESS;
+ return FAILED;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1801,11 +1823,12 @@ int
mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
+ int retval;
/* If we can't locate our host adapter structure, return FAILED status.
*/
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
- dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
+ dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
"Can't locate host! (sc=%p)\n",
SCpnt));
return FAILED;
@@ -1814,24 +1837,26 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
if (hd->resetPending)
return FAILED;
- printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
+ printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
+ scsi_print_command(SCpnt);
- if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+ retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
SCpnt->device->channel, SCpnt->device->id,
- 0, 0, 5 /* 5 second timeout */)
- < 0){
- /* The TM request failed and the subsequent FW-reload failed!
- * Fatal error case.
- */
- printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
- hd->ioc->name, SCpnt);
+ 0, 0, 5 /* 5 second timeout */);
+
+ printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
+ hd->ioc->name,
+ ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+ if (retval == 0)
+ return SUCCESS;
+
+ if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
- return FAILED;
}
-
- return SUCCESS;
+ return FAILED;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1847,41 +1872,39 @@ int
mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
- spinlock_t *host_lock = SCpnt->device->host->host_lock;
+ int retval;
/* If we can't locate our host adapter structure, return FAILED status.
*/
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
- dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
+ dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
"Can't locate host! (sc=%p)\n",
SCpnt ) );
return FAILED;
}
- printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
+ printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
+ scsi_print_command(SCpnt);
if (hd->timeouts < -1)
hd->timeouts++;
- /* We are now ready to execute the task management request. */
- if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
- < 0){
+ retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+ SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */);
- /* The TM request failed and the subsequent FW-reload failed!
- * Fatal error case.
- */
- printk(MYIOC_s_WARN_FMT
- "Error processing TaskMgmt request (sc=%p)\n",
- hd->ioc->name, SCpnt);
+ printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
+ hd->ioc->name,
+ ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+ if (retval == 0)
+ return SUCCESS;
+
+ if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
- spin_lock_irq(host_lock);
- return FAILED;
}
-
- return SUCCESS;
+ return FAILED;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1902,13 +1925,13 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
/* If we can't locate the host to reset, then we failed. */
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
- dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+ dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
"Can't locate host! (sc=%p)\n",
SCpnt ) );
return FAILED;
}
- printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
+ printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
/* If our attempts to reset the host failed, then return a failed
@@ -1924,7 +1947,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
hd->tmState = TM_STATE_NONE;
}
- dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
+ dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
"Status = %s\n",
(status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
@@ -1951,8 +1974,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
if (hd->tmState == TM_STATE_NONE) {
hd->tmState = TM_STATE_IN_PROGRESS;
hd->tmPending = 1;
- status = SUCCESS;
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ status = SUCCESS;
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -1980,7 +2003,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
if(hd->tmPending == 0) {
status = SUCCESS;
- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -2163,7 +2186,7 @@ mptscsih_slave_alloc(struct scsi_device *device)
vdev->raidVolume = 0;
hd->Targets[device->id] = vdev;
if (hd->ioc->bus_type == SCSI) {
- if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
+ if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
vdev->raidVolume = 1;
ddvtprintk((KERN_INFO
"RAID Volume @ id %d\n", device->id));
@@ -2174,22 +2197,7 @@ mptscsih_slave_alloc(struct scsi_device *device)
out:
vdev->num_luns++;
- return 0;
-}
-
-static int
-mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
-{
- int i;
-
- if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
- return 0;
-
- for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) {
- if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID)
- return 1;
- }
-
+ device->hostdata = vdev;
return 0;
}
@@ -2220,7 +2228,7 @@ mptscsih_slave_destroy(struct scsi_device *device)
hd->Targets[target] = NULL;
if (hd->ioc->bus_type == SCSI) {
- if (mptscsih_is_raid_volume(hd, target)) {
+ if (mptscsih_is_phys_disk(hd->ioc, target)) {
hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
} else {
hd->ioc->spi_data.dvStatus[target] =
@@ -2318,10 +2326,10 @@ mptscsih_slave_configure(struct scsi_device *device)
if (pTarget == NULL) {
/* Driver doesn't know about this device.
* Kernel may generate a "Dummy Lun 0" which
- * may become a real Lun if a
+ * may become a real Lun if a
* "scsi add-single-device" command is executed
- * while the driver is active (hot-plug a
- * device). LSI Raid controllers need
+ * while the driver is active (hot-plug a
+ * device). LSI Raid controllers need
* queue_depth set to DEV_HIGH for this reason.
*/
scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
@@ -2433,6 +2441,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
MPT_SCSI_HOST *hd;
unsigned long flags;
+ int ii;
dtmprintk((KERN_WARNING MYNAM
": IOC %s_reset routed to SCSI host driver!\n",
@@ -2490,11 +2499,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* ScsiLookup initialization
*/
- {
- int ii;
- for (ii=0; ii < hd->ioc->req_depth; ii++)
- hd->ScsiLookup[ii] = NULL;
- }
+ for (ii=0; ii < hd->ioc->req_depth; ii++)
+ hd->ScsiLookup[ii] = NULL;
/* 2. Chain Buffer initialization
*/
@@ -2543,6 +2549,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* work queue thread to clear the persitency table */
+static void
+mptscsih_sas_persist_clear_table(void * arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+
+ mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int
mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
@@ -2552,18 +2568,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
ioc->name, event));
+ if (ioc->sh == NULL ||
+ ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+ return 1;
+
switch (event) {
case MPI_EVENT_UNIT_ATTENTION: /* 03 */
/* FIXME! */
break;
case MPI_EVENT_IOC_BUS_RESET: /* 04 */
case MPI_EVENT_EXT_BUS_RESET: /* 05 */
- hd = NULL;
- if (ioc->sh) {
- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
- if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
- hd->soft_resets++;
- }
+ if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
+ hd->soft_resets++;
break;
case MPI_EVENT_LOGOUT: /* 09 */
/* FIXME! */
@@ -2582,69 +2598,24 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
break;
case MPI_EVENT_INTEGRATED_RAID: /* 0B */
+ {
+ pMpiEventDataRaid_t pRaidEventData =
+ (pMpiEventDataRaid_t) pEvReply->Data;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
- /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
- * if DV disabled. Need to check for target mode.
- */
- hd = NULL;
- if (ioc->sh)
- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
-
- if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
- ScsiCfgData *pSpi;
- Ioc3PhysDisk_t *pPDisk;
- int numPDisk;
- u8 reason;
- u8 physDiskNum;
-
- reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
- if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
- /* New or replaced disk.
- * Set DV flag and schedule DV.
- */
- pSpi = &ioc->spi_data;
- physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
- ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
- if (pSpi->pIocPg3) {
- pPDisk = pSpi->pIocPg3->PhysDisk;
- numPDisk =pSpi->pIocPg3->NumPhysDisks;
-
- while (numPDisk) {
- if (physDiskNum == pPDisk->PhysDiskNum) {
- pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
- pSpi->forceDv = MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
- break;
- }
- pPDisk++;
- numPDisk--;
- }
-
- if (numPDisk == 0) {
- /* The physical disk that needs DV was not found
- * in the stored IOC Page 3. The driver must reload
- * this page. DV routine will set the NEED_DV flag for
- * all phys disks that have DV_NOT_DONE set.
- */
- pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
- ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
- }
- }
- }
- }
+ /* Domain Validation Needed */
+ if (ioc->bus_type == SCSI &&
+ pRaidEventData->ReasonCode ==
+ MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
+ mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
#endif
+ break;
+ }
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
- printk("Raid Event RF: ");
- {
- u32 *m = (u32 *)pEvReply;
- int ii;
- int n = (int)pEvReply->MsgLength;
- for (ii=6; ii < n; ii++)
- printk(" %08x", le32_to_cpu(m[ii]));
- printk("\n");
- }
-#endif
+ /* Persistent table is full. */
+ case MPI_EVENT_PERSISTENT_TABLE_FULL:
+ INIT_WORK(&mptscsih_persistTask,
+ mptscsih_sas_persist_clear_table,(void *)ioc);
+ schedule_work(&mptscsih_persistTask);
break;
case MPI_EVENT_NONE: /* 00 */
@@ -2681,7 +2652,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
{
int indexed_lun, lun_index;
VirtDevice *vdev;
- ScsiCfgData *pSpi;
+ SpiCfgData *pSpi;
char data_56;
dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
@@ -2691,7 +2662,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
* If the peripheral qualifier filter is enabled then if the target reports a 0x1
* (i.e. The targer is capable of supporting the specified peripheral device type
* on this logical unit; however, the physical device is not currently connected
- * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
+ * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
* capable of supporting a physical device on this logical unit). This is to work
* around a bug in th emid-layer in some distributions in which the mid-layer will
* continue to try to communicate to the LUN and evntually create a dummy LUN.
@@ -2788,7 +2759,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
static void
mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
{
- ScsiCfgData *pspi_data = &hd->ioc->spi_data;
+ SpiCfgData *pspi_data = &hd->ioc->spi_data;
int id = (int) target->target_id;
int nvram;
VirtDevice *vdev;
@@ -2967,11 +2938,13 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
static void
mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
{
+ MPT_ADAPTER *ioc = hd->ioc;
u8 cmd;
- ScsiCfgData *pSpi;
+ SpiCfgData *pSpi;
- ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
- pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
+ ddvtprintk((MYIOC_s_NOTE_FMT
+ " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
+ hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
return;
@@ -2979,12 +2952,12 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
cmd = pReq->CDB[0];
if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
- pSpi = &hd->ioc->spi_data;
- if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
+ pSpi = &ioc->spi_data;
+ if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
/* Set NEED_DV for all hidden disks
*/
- Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
- int numPDisk = pSpi->pIocPg3->NumPhysDisks;
+ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
while (numPDisk) {
pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
@@ -2998,6 +2971,50 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
}
}
+/* mptscsih_raid_set_dv_flags()
+ *
+ * New or replaced disk. Set DV flag and schedule DV.
+ */
+static void
+mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
+{
+ MPT_ADAPTER *ioc = hd->ioc;
+ SpiCfgData *pSpi = &ioc->spi_data;
+ Ioc3PhysDisk_t *pPDisk;
+ int numPDisk;
+
+ if (hd->negoNvram != 0)
+ return;
+
+ ddvtprintk(("DV requested for phys disk id %d\n", id));
+ if (ioc->raid_data.pIocPg3) {
+ pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+ while (numPDisk) {
+ if (id == pPDisk->PhysDiskNum) {
+ pSpi->dvStatus[pPDisk->PhysDiskID] =
+ (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
+ pSpi->forceDv = MPT_SCSICFG_NEED_DV;
+ ddvtprintk(("NEED_DV set for phys disk id %d\n",
+ pPDisk->PhysDiskID));
+ break;
+ }
+ pPDisk++;
+ numPDisk--;
+ }
+
+ if (numPDisk == 0) {
+ /* The physical disk that needs DV was not found
+ * in the stored IOC Page 3. The driver must reload
+ * this page. DV routine will set the NEED_DV flag for
+ * all phys disks that have DV_NOT_DONE set.
+ */
+ pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+ ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
+ }
+ }
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* If no Target, bus reset on 1st I/O. Set the flag to
@@ -3085,7 +3102,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
MPT_ADAPTER *ioc = hd->ioc;
Config_t *pReq;
SCSIDevicePage1_t *pData;
- VirtDevice *pTarget;
+ VirtDevice *pTarget=NULL;
MPT_FRAME_HDR *mf;
dma_addr_t dataDma;
u16 req_idx;
@@ -3184,7 +3201,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
#endif
if (flags & MPT_SCSICFG_BLK_NEGO)
- negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
+ negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
mptscsih_setDevicePage1Flags(width, factor, offset,
&requested, &configuration, negoFlags);
@@ -3194,8 +3211,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
/* Get a MF for this command.
*/
if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
- dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
- ioc->name));
+ dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
+ ioc->name));
return -EAGAIN;
}
@@ -3289,7 +3306,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
/* Get a MF for this command.
*/
if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
- dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+ dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
ioc->name));
return -EAGAIN;
}
@@ -3447,7 +3464,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
* some type of error occurred.
*/
MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
- if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
+ if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
completionCode = MPT_SCANDV_GOOD;
else
completionCode = MPT_SCANDV_SOME_ERROR;
@@ -3955,7 +3972,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
header1.PageLength = ioc->spi_data.sdp1length;
header1.PageNumber = 1;
header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -3996,16 +4013,16 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
"offset=0 negoFlags=%x request=%x config=%x\n",
id, flags, requested, configuration));
- pcfg1Data->RequestedParameters = le32_to_cpu(requested);
+ pcfg1Data->RequestedParameters = cpu_to_le32(requested);
pcfg1Data->Reserved = 0;
- pcfg1Data->Configuration = le32_to_cpu(configuration);
+ pcfg1Data->Configuration = cpu_to_le32(configuration);
cfg.pageAddr = (bus<<8) | id;
mpt_config(hd->ioc, &cfg);
}
/* If target Ptr NULL or if this target is NOT a disk, skip.
*/
- if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
+ if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){
for (lun=0; lun <= MPT_LAST_LUN; lun++) {
/* If LUN present, issue the command
*/
@@ -4100,9 +4117,9 @@ mptscsih_domainValidation(void *arg)
if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
mpt_read_ioc_pg_3(ioc);
- if (ioc->spi_data.pIocPg3) {
- Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+ if (ioc->raid_data.pIocPg3) {
+ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
while (numPDisk) {
if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
@@ -4141,7 +4158,7 @@ mptscsih_domainValidation(void *arg)
isPhysDisk = mptscsih_is_phys_disk(ioc, id);
if (isPhysDisk) {
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- if (hd->ioc->spi_data.isRaid & (1 << ii)) {
+ if (hd->ioc->raid_data.isRaid & (1 << ii)) {
hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
}
}
@@ -4160,7 +4177,7 @@ mptscsih_domainValidation(void *arg)
if (isPhysDisk) {
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- if (hd->ioc->spi_data.isRaid & (1 << ii)) {
+ if (hd->ioc->raid_data.isRaid & (1 << ii)) {
hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
}
}
@@ -4182,21 +4199,21 @@ mptscsih_domainValidation(void *arg)
/* Search IOC page 3 to determine if this is hidden physical disk
*/
-static int
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int
mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
{
- if (ioc->spi_data.pIocPg3) {
- Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+ int i;
- while (numPDisk) {
- if (pPDisk->PhysDiskID == id) {
- return 1;
- }
- pPDisk++;
- numPDisk--;
- }
+ if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+ return 0;
+
+ for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+ if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+ return 1;
}
+
return 0;
}
@@ -4353,7 +4370,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
/* Prep cfg structure
*/
cfg.pageAddr = (bus<<8) | id;
- cfg.hdr = NULL;
+ cfg.cfghdr.hdr = NULL;
/* Prep SDP0 header
*/
@@ -4399,10 +4416,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
cfg1_dma_addr = dvbuf_dma + sz;
- /* Skip this ID? Set cfg.hdr to force config page write
+ /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
*/
{
- ScsiCfgData *pspi_data = &hd->ioc->spi_data;
+ SpiCfgData *pspi_data = &hd->ioc->spi_data;
if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
/* Set the factor from nvram */
nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
@@ -4417,7 +4434,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
dv.cmd = MPT_SET_MAX;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
/* Save the final negotiated settings to
* SCSI device page 1.
@@ -4432,11 +4449,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
/* Finish iocmd inititialization - hidden or visible disk? */
- if (ioc->spi_data.pIocPg3) {
+ if (ioc->raid_data.pIocPg3) {
/* Search IOC page 3 for matching id
*/
- Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
+ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
while (numPDisk) {
if (pPDisk->PhysDiskID == id) {
@@ -4460,7 +4477,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
/* RAID Volume ID's may double for a physical device. If RAID but
* not a physical ID as well, skip DV.
*/
- if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
+ if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
goto target_done;
@@ -4483,7 +4500,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
dv.cmd = MPT_SET_MIN;
mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -4596,8 +4613,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
if ((pbuf1[56] & 0x02) == 0) {
pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
- "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
+ ddvprintk((MYIOC_s_NOTE_FMT
+ "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
ioc->name, id, pbuf1[56]));
}
}
@@ -4637,7 +4654,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
u32 sdp0_info;
u32 sdp0_nego;
- cfg.hdr = &header0;
+ cfg.cfghdr.hdr = &header0;
cfg.physAddr = cfg0_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.dir = 0;
@@ -4673,7 +4690,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
if (!firstPass)
doFallback = 1;
} else {
- ddvprintk((MYIOC_s_NOTE_FMT
+ ddvprintk((MYIOC_s_NOTE_FMT
"DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
mptscsih_initTarget(hd,
@@ -4689,8 +4706,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
} else if (rc == MPT_SCANDV_ISSUE_SENSE)
doFallback = 1; /* set fallback flag */
- else if ((rc == MPT_SCANDV_DID_RESET) ||
- (rc == MPT_SCANDV_SENSE) ||
+ else if ((rc == MPT_SCANDV_DID_RESET) ||
+ (rc == MPT_SCANDV_SENSE) ||
(rc == MPT_SCANDV_FALLBACK))
doFallback = 1; /* set fallback flag */
else
@@ -4722,7 +4739,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
* 4) release
* 5) update nego parms to target struct
*/
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -4809,6 +4826,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
notDone = 0;
if (iocmd.flags & MPT_ICFLAG_ECHO) {
bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
+ if (pbuf1[0] & 0x01)
+ iocmd.flags |= MPT_ICFLAG_EBOS;
} else {
bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
}
@@ -4905,6 +4924,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
+ if (iocmd.flags & MPT_ICFLAG_EBOS)
+ goto skip_Reserve;
+
repeat = 5;
while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
iocmd.cmd = RESERVE;
@@ -4948,6 +4970,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
}
+skip_Reserve:
mptscsih_fillbuf(pbuf1, sz, patt, 1);
iocmd.cmd = WRITE_BUFFER;
iocmd.data_dma = buf1_dma;
@@ -5121,12 +5144,12 @@ target_done:
/* Set if cfg1_dma_addr contents is valid
*/
- if ((cfg.hdr != NULL) && (retcode == 0)){
+ if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
/* If disk, not U320, disable QAS
*/
if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
+ ddvprintk((MYIOC_s_NOTE_FMT
"noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
}
@@ -5137,7 +5160,7 @@ target_done:
* skip save of the final negotiated settings to
* SCSI device page 1.
*
- cfg.hdr = &header1;
+ cfg.cfghdr.hdr = &header1;
cfg.physAddr = cfg1_dma_addr;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
@@ -5192,11 +5215,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
* If not an LVD bus, the adapter minSyncFactor has been
* already throttled back.
*/
+ negoFlags = hd->ioc->spi_data.noQas;
if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
width = pTarget->maxWidth;
offset = pTarget->maxOffset;
factor = pTarget->minSyncFactor;
- negoFlags = pTarget->negoFlags;
+ negoFlags |= pTarget->negoFlags;
} else {
if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
data = hd->ioc->spi_data.nvram[id];
@@ -5217,7 +5241,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
}
/* Set the negotiation flags */
- negoFlags = hd->ioc->spi_data.noQas;
if (!width)
negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
@@ -5248,7 +5271,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
/* Update tmax values with those from Device Page 0.*/
pPage0 = (SCSIDevicePage0_t *) pPage;
if (pPage0) {
- val = cpu_to_le32(pPage0->NegotiatedParameters);
+ val = le32_to_cpu(pPage0->NegotiatedParameters);
dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
@@ -5276,12 +5299,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
dv->now.offset, &val, &configuration, dv->now.flags);
dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
- ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
+ ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
break;
@@ -5301,9 +5324,9 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
offset, &val, &configuration, negoFlags);
dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
id, width, factor, offset, negoFlags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
id, width, factor, offset, val, configuration, negoFlags));
@@ -5377,12 +5400,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
if (pPage1) {
mptscsih_setDevicePage1Flags (width, factor, offset, &val,
&configuration, dv->now.flags);
- dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
+ dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
id, width, offset, factor, dv->now.flags, val, configuration));
- pPage1->RequestedParameters = le32_to_cpu(val);
+ pPage1->RequestedParameters = cpu_to_le32(val);
pPage1->Reserved = 0;
- pPage1->Configuration = le32_to_cpu(configuration);
+ pPage1->Configuration = cpu_to_le32(configuration);
}
ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 51c0255ac16e..971fda4b8b57 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/message/fusion/mptscsi.h
+ * linux/drivers/message/fusion/mptscsih.h
* High performance SCSI / Fibre Channel SCSI Host device driver.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
@@ -53,8 +53,8 @@
* SCSI Public stuff...
*/
-#define MPT_SCSI_CMD_PER_DEV_HIGH 31
-#define MPT_SCSI_CMD_PER_DEV_LOW 7
+#define MPT_SCSI_CMD_PER_DEV_HIGH 64
+#define MPT_SCSI_CMD_PER_DEV_LOW 32
#define MPT_SCSI_CMD_PER_LUN 7
@@ -77,6 +77,7 @@
#define MPTSCSIH_MAX_WIDTH 1
#define MPTSCSIH_MIN_SYNC 0x08
#define MPTSCSIH_SAF_TE 0
+#define MPTSCSIH_PT_CLEAR 0
#endif
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index dfa8806b1e13..5c0e307d1d5d 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -162,15 +162,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u8 *mem;
int error=0;
int r;
-
+
if ((r = mpt_attach(pdev,id)) != 0)
return r;
-
+
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptspiDoneCtx;
ioc->TaskCtx = mptspiTaskCtx;
ioc->InternalCtx = mptspiInternalCtx;
-
+
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
@@ -199,7 +199,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
- return -ENODEV;
+ return 0;
}
sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 06e8eb19a05c..43a942a29c2e 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -53,6 +53,9 @@ config I2O_CONFIG
To compile this support as a module, choose M here: the
module will be called i2o_config.
+ Note: If you want to use the new API you have to download the
+ i2o_config patch from http://i2o.shadowconnect.com/
+
config I2O_CONFIG_OLD_IOCTL
bool "Enable ioctls (OBSOLETE)"
depends on I2O_CONFIG
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index fe2e7afc9eae..10432f665201 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -30,503 +30,9 @@
static struct i2o_driver i2o_config_driver;
-/* Special file operations for sysfs */
-struct fops_attribute {
- struct bin_attribute bin;
- struct file_operations fops;
-};
-
-/**
- * sysfs_read_dummy
- */
-static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
- size_t count)
-{
- return 0;
-};
-
-/**
- * sysfs_write_dummy
- */
-static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
- size_t count)
-{
- return 0;
-};
-
-/**
- * sysfs_create_fops_file - Creates attribute with special file operations
- * @kobj: kobject which should contains the attribute
- * @attr: attributes which should be used to create file
- *
- * First creates attribute @attr in kobject @kobj. If it is the first time
- * this function is called, merge old fops from sysfs with new one and
- * write it back. Afterwords the new fops will be set for the created
- * attribute.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int sysfs_create_fops_file(struct kobject *kobj,
- struct fops_attribute *attr)
-{
- struct file_operations tmp, *fops;
- struct dentry *d;
- struct qstr qstr;
- int rc;
-
- fops = &attr->fops;
-
- if (fops->read)
- attr->bin.read = sysfs_read_dummy;
-
- if (fops->write)
- attr->bin.write = sysfs_write_dummy;
-
- if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
- return rc;
-
- qstr.name = attr->bin.attr.name;
- qstr.len = strlen(qstr.name);
- qstr.hash = full_name_hash(qstr.name, qstr.len);
-
- if ((d = lookup_hash(&qstr, kobj->dentry))) {
- if (!fops->owner) {
- memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
- if (fops->read)
- tmp.read = fops->read;
- if (fops->write)
- tmp.write = fops->write;
- memcpy(fops, &tmp, sizeof(tmp));
- }
-
- d->d_inode->i_fop = fops;
- } else
- sysfs_remove_bin_file(kobj, &attr->bin);
-
- return -ENOENT;
-};
-
-/**
- * sysfs_remove_fops_file - Remove attribute with special file operations
- * @kobj: kobject which contains the attribute
- * @attr: attributes which are used to create file
- *
- * Only wrapper arround sysfs_remove_bin_file()
- *
- * Returns 0 on success or negative error code on failure.
- */
-static inline int sysfs_remove_fops_file(struct kobject *kobj,
- struct fops_attribute *attr)
-{
- return sysfs_remove_bin_file(kobj, &attr->bin);
-};
-
-/**
- * i2o_config_read_hrt - Returns the HRT of the controller
- * @kob: kernel object handle
- * @buf: buffer into which the HRT should be copied
- * @off: file offset
- * @count: number of bytes to read
- *
- * Put @count bytes starting at @off into @buf from the HRT of the I2O
- * controller corresponding to @kobj.
- *
- * Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
- loff_t offset, size_t count)
-{
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- i2o_hrt *hrt = c->hrt.virt;
-
- u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
-
- if (offset > size)
- return 0;
-
- if (offset + count > size)
- count = size - offset;
-
- memcpy(buf, (u8 *) hrt + offset, count);
-
- return count;
-};
-
-/**
- * i2o_config_read_lct - Returns the LCT of the controller
- * @kob: kernel object handle
- * @buf: buffer into which the LCT should be copied
- * @off: file offset
- * @count: number of bytes to read
- *
- * Put @count bytes starting at @off into @buf from the LCT of the I2O
- * controller corresponding to @kobj.
- *
- * Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
- loff_t offset, size_t count)
-{
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 size = c->lct->table_size * 4;
-
- if (offset > size)
- return 0;
-
- if (offset + count > size)
- count = size - offset;
-
- memcpy(buf, (u8 *) c->lct + offset, count);
-
- return count;
-};
-
-#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
-static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
- return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
-};\
-\
-static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
- return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
-}; \
-\
-static struct fops_attribute i2o_config_attr_##_name = { \
- .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
- .owner = THIS_MODULE }, \
- .size = 0, }, \
- .fops = { .write = i2o_config_##_name##_write, \
- .read = i2o_config_##_name##_read} \
-};
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/**
- * i2o_config_dpt_reagion - Converts type and id to flash region
- * @swtype: type of software module reading
- * @swid: id of software which should be read
- *
- * Converts type and id from I2O spec to the matching region for DPT /
- * Adaptec controllers.
- *
- * Returns region which match type and id or -1 on error.
- */
-static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
-{
- switch (swtype) {
- case I2O_SOFTWARE_MODULE_IRTOS:
- /*
- * content: operation firmware
- * region size:
- * 0xbc000 for 2554, 3754, 2564, 3757
- * 0x170000 for 2865
- * 0x17c000 for 3966
- */
- if (!swid)
- return 0;
-
- break;
-
- case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
- /*
- * content: BIOS and SMOR
- * BIOS size: first 0x8000 bytes
- * region size:
- * 0x40000 for 2554, 3754, 2564, 3757
- * 0x80000 for 2865, 3966
- */
- if (!swid)
- return 1;
-
- break;
-
- case I2O_SOFTWARE_MODULE_IOP_CONFIG:
- switch (swid) {
- case 0:
- /*
- * content: NVRAM defaults
- * region size: 0x2000 bytes
- */
- return 2;
- case 1:
- /*
- * content: serial number
- * region size: 0x2000 bytes
- */
- return 3;
- }
- break;
- }
-
- return -1;
-};
-
-#endif
-
-/**
- * i2o_config_sw_read - Read a software module from controller
- * @file: file pointer
- * @buf: buffer into which the data should be copied
- * @count: number of bytes to read
- * @off: file offset
- * @swtype: type of software module reading
- * @swid: id of software which should be read
- *
- * Transfers @count bytes at offset @offset from IOP into buffer using
- * type @swtype and id @swid as described in I2O spec.
- *
- * Returns number of bytes copied into buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
- size_t count, loff_t * offset, u8 swtype,
- u32 swid)
-{
- struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
- struct kobject *kobj = sd->s_element;
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 m, function = I2O_CMD_SW_UPLOAD;
- struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
- int rc, status;
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
-
- mptr = &msg->body[3];
-
- if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
- i2o_msg_nop(c, m);
- return rc;
- }
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- mptr = &msg->body[4];
- function = I2O_CMD_PRIVATE;
-
- writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
- writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
- &msg->body[0]);
- writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
- writel(*offset, &msg->body[2]);
- writel(count, &msg->body[3]);
- } else
-#endif
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
- writel(0xD0000000 | count, mptr++);
- writel(buffer.phys, mptr);
-
- writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (!c->adaptec)
-#endif
- {
- writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(swid, &msg->body[2]);
- }
-
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
- if (status == I2O_POST_WAIT_OK) {
- if (!(rc = copy_to_user(buf, buffer.virt, count))) {
- rc = count;
- *offset += count;
- }
- } else
- rc = -EIO;
-
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- return rc;
-};
-
-/**
- * i2o_config_sw_write - Write a software module to controller
- * @file: file pointer
- * @buf: buffer into which the data should be copied
- * @count: number of bytes to read
- * @off: file offset
- * @swtype: type of software module writing
- * @swid: id of software which should be written
- *
- * Transfers @count bytes at offset @offset from buffer to IOP using
- * type @swtype and id @swid as described in I2O spec.
- *
- * Returns number of bytes copied from buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
- size_t count, loff_t * offset, u8 swtype,
- u32 swid)
-{
- struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
- struct kobject *kobj = sd->s_element;
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 m, function = I2O_CMD_SW_DOWNLOAD;
- struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
- int rc, status;
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
-
- mptr = &msg->body[3];
-
- if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
- goto nop_msg;
-
- if ((rc = copy_from_user(buffer.virt, buf, count)))
- goto free_buffer;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- mptr = &msg->body[4];
- function = I2O_CMD_PRIVATE;
-
- writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
- writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
- &msg->body[0]);
- writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
- writel(*offset, &msg->body[2]);
- writel(count, &msg->body[3]);
- } else
-#endif
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
- writel(0xD4000000 | count, mptr++);
- writel(buffer.phys, mptr);
-
- writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (!c->adaptec)
-#endif
- {
- writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(swid, &msg->body[2]);
- }
-
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- if (status != I2O_POST_WAIT_OK)
- return -EIO;
-
- *offset += count;
-
- return count;
-
- free_buffer:
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- nop_msg:
- i2o_msg_nop(c, m);
-
- return rc;
-};
-
-/* attribute for HRT in sysfs */
-static struct bin_attribute i2o_config_hrt_attr = {
- .attr = {
- .name = "hrt",
- .mode = S_IRUGO,
- .owner = THIS_MODULE},
- .size = 0,
- .read = i2o_config_read_hrt
-};
-
-/* attribute for LCT in sysfs */
-static struct bin_attribute i2o_config_lct_attr = {
- .attr = {
- .name = "lct",
- .mode = S_IRUGO,
- .owner = THIS_MODULE},
- .size = 0,
- .read = i2o_config_read_lct
-};
-
-/* IRTOS firmware access */
-I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/*
- * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
- * controllers
- */
-I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
-I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
-I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
-
-#endif
-
-/**
- * i2o_config_notify_controller_add - Notify of added controller
- * @c: the controller which was added
- *
- * If a I2O controller is added, we catch the notification to add sysfs
- * entries.
- */
-static void i2o_config_notify_controller_add(struct i2o_controller *c)
-{
- struct kobject *kobj = &c->exec->device.kobj;
-
- sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
- sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
-
- sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
- sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
- sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
- }
-#endif
-};
-
-/**
- * i2o_config_notify_controller_remove - Notify of removed controller
- * @c: the controller which was removed
- *
- * If a I2O controller is removed, we catch the notification to remove the
- * sysfs entries.
- */
-static void i2o_config_notify_controller_remove(struct i2o_controller *c)
-{
- struct kobject *kobj = &c->exec->device.kobj;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
- sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
- sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
- }
-#endif
- sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
-
- sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
- sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
-};
-
/* Config OSM driver struct */
static struct i2o_driver i2o_config_driver = {
.name = OSM_NAME,
- .notify_controller_add = i2o_config_notify_controller_add,
- .notify_controller_remove = i2o_config_notify_controller_remove
};
#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
@@ -550,8 +56,11 @@ static int __init i2o_config_init(void)
return -EBUSY;
}
#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
- if (i2o_config_old_init())
+ if (i2o_config_old_init()) {
+ osm_err("old config handler initialization failed\n");
i2o_driver_unregister(&i2o_config_driver);
+ return -EBUSY;
+ }
#endif
return 0;
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index c5bcfd70f711..9eefedb16211 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -36,9 +36,6 @@ extern void __exit i2o_pci_exit(void);
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
-extern int i2o_device_init(void);
-extern void i2o_device_exit(void);
-
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
extern void i2o_iop_free(struct i2o_controller *);
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 018ca887ca85..40d4ea898dbc 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -90,7 +90,7 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg)
};
if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
- printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.",
+ printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
req_status);
else
printk(KERN_DEBUG "TRANSPORT_%s.\n",
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 21f16ba3ac38..8eb50cdb8ae1 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -16,6 +16,8 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "core.h"
/**
@@ -45,10 +47,10 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
writel(type, &msg->body[0]);
return i2o_msg_post_wait(dev->iop, m, 60);
-};
+}
/**
- * i2o_device_claim - claim a device for use by an OSM
+ * i2o_device_claim - claim a device for use by an OSM
* @dev: I2O device to claim
* @drv: I2O driver which wants to claim the device
*
@@ -73,7 +75,7 @@ int i2o_device_claim(struct i2o_device *dev)
up(&dev->lock);
return rc;
-};
+}
/**
* i2o_device_claim_release - release a device that the OSM is using
@@ -119,7 +121,8 @@ int i2o_device_claim_release(struct i2o_device *dev)
up(&dev->lock);
return rc;
-};
+}
+
/**
* i2o_device_release - release the memory for a I2O device
@@ -135,39 +138,47 @@ static void i2o_device_release(struct device *dev)
pr_debug("i2o: device %s released\n", dev->bus_id);
kfree(i2o_dev);
-};
+}
+
/**
- * i2o_device_class_release - Remove I2O device attributes
- * @cd: I2O class device which is added to the I2O device class
+ * i2o_device_class_show_class_id - Displays class id of I2O device
+ * @cd: class device of which the class id should be displayed
+ * @buf: buffer into which the class id should be printed
*
- * Removes attributes from the I2O device again. Also search each device
- * on the controller for I2O devices which refert to this device as parent
- * or user and remove this links also.
+ * Returns the number of bytes which are printed into the buffer.
*/
-static void i2o_device_class_release(struct class_device *cd)
+static ssize_t i2o_device_show_class_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct i2o_device *i2o_dev, *tmp;
- struct i2o_controller *c;
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
- i2o_dev = to_i2o_device(cd->dev);
- c = i2o_dev->iop;
+ sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
+ return strlen(buf) + 1;
+}
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
+/**
+ * i2o_device_class_show_tid - Displays TID of I2O device
+ * @cd: class device of which the TID should be displayed
+ * @buf: buffer into which the class id should be printed
+ *
+ * Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_show_tid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- }
-};
+ sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
+ return strlen(buf) + 1;
+}
-/* I2O device class */
-static struct class i2o_device_class = {
- .name = "i2o_device",
- .release = i2o_device_class_release
+struct device_attribute i2o_device_attrs[] = {
+ __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
+ __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
+ __ATTR_NULL
};
/**
@@ -193,11 +204,69 @@ static struct i2o_device *i2o_device_alloc(void)
dev->device.bus = &i2o_bus_type;
dev->device.release = &i2o_device_release;
- dev->classdev.class = &i2o_device_class;
- dev->classdev.dev = &dev->device;
return dev;
-};
+}
+
+/**
+ * i2o_setup_sysfs_links - Adds attributes to the I2O device
+ * @cd: I2O class device which is added to the I2O device class
+ *
+ * This function get called when a I2O device is added to the class. It
+ * creates the attributes for each device and creates user/parent symlink
+ * if necessary.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
+{
+ struct i2o_controller *c = i2o_dev->iop;
+ struct i2o_device *tmp;
+
+ /* create user entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+ if (tmp && tmp != i2o_dev)
+ sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "user");
+
+ /* create user entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
+ tmp != i2o_dev)
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
+
+ /* create parent entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+ if (tmp && tmp != i2o_dev)
+ sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "parent");
+
+ /* create parent entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
+ tmp != i2o_dev)
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+}
+
+static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
+{
+ struct i2o_controller *c = i2o_dev->iop;
+ struct i2o_device *tmp;
+
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ }
+}
+
+
/**
* i2o_device_add - allocate a new I2O device and add it to the IOP
@@ -222,28 +291,25 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
}
dev->lct_data = *entry;
+ dev->iop = c;
snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
dev->lct_data.tid);
- snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit,
- dev->lct_data.tid);
-
- dev->iop = c;
dev->device.parent = &c->device;
device_register(&dev->device);
list_add_tail(&dev->list, &c->devices);
- class_device_register(&dev->classdev);
+ i2o_setup_sysfs_links(dev);
i2o_driver_notify_device_add_all(dev);
pr_debug("i2o: device %s added\n", dev->device.bus_id);
return dev;
-};
+}
/**
* i2o_device_remove - remove an I2O device from the I2O core
@@ -256,10 +322,10 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
void i2o_device_remove(struct i2o_device *i2o_dev)
{
i2o_driver_notify_device_remove_all(i2o_dev);
- class_device_unregister(&i2o_dev->classdev);
+ i2o_remove_sysfs_links(i2o_dev);
list_del(&i2o_dev->list);
device_unregister(&i2o_dev->device);
-};
+}
/**
* i2o_device_parse_lct - Parse a previously fetched LCT and create devices
@@ -337,99 +403,8 @@ int i2o_device_parse_lct(struct i2o_controller *c)
up(&c->lct_lock);
return 0;
-};
-
-/**
- * i2o_device_class_show_class_id - Displays class id of I2O device
- * @cd: class device of which the class id should be displayed
- * @buf: buffer into which the class id should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
- char *buf)
-{
- struct i2o_device *dev = to_i2o_device(cd->dev);
-
- sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
- return strlen(buf) + 1;
-};
-
-/**
- * i2o_device_class_show_tid - Displays TID of I2O device
- * @cd: class device of which the TID should be displayed
- * @buf: buffer into which the class id should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
-{
- struct i2o_device *dev = to_i2o_device(cd->dev);
-
- sprintf(buf, "0x%03x\n", dev->lct_data.tid);
- return strlen(buf) + 1;
-};
-
-/* I2O device class attributes */
-static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id,
- NULL);
-static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL);
-
-/**
- * i2o_device_class_add - Adds attributes to the I2O device
- * @cd: I2O class device which is added to the I2O device class
- *
- * This function get called when a I2O device is added to the class. It
- * creates the attributes for each device and creates user/parent symlink
- * if necessary.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_device_class_add(struct class_device *cd)
-{
- struct i2o_device *i2o_dev, *tmp;
- struct i2o_controller *c;
-
- i2o_dev = to_i2o_device(cd->dev);
- c = i2o_dev->iop;
-
- class_device_create_file(cd, &class_device_attr_class_id);
- class_device_create_file(cd, &class_device_attr_tid);
-
- /* create user entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "user");
-
- /* create user entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
-
- /* create parent entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "parent");
-
- /* create parent entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
-
- return 0;
-};
+}
-/* I2O device class interface */
-static struct class_interface i2o_device_class_interface = {
- .class = &i2o_device_class,
- .add = i2o_device_class_add
-};
/*
* Run time support routines
@@ -553,11 +528,11 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
}
/*
- * if oper == I2O_PARAMS_TABLE_GET, get from all rows
- * if fieldcount == -1 return all fields
+ * if oper == I2O_PARAMS_TABLE_GET, get from all rows
+ * if fieldcount == -1 return all fields
* ibuf and ibuflen are unused (use NULL, 0)
- * else return specific fields
- * ibuf contains fieldindexes
+ * else return specific fields
+ * ibuf contains fieldindexes
*
* if oper == I2O_PARAMS_LIST_GET, get from specific rows
* if fieldcount == -1 return all fields
@@ -602,35 +577,6 @@ int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
return size;
}
-/**
- * i2o_device_init - Initialize I2O devices
- *
- * Registers the I2O device class.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_device_init(void)
-{
- int rc;
-
- rc = class_register(&i2o_device_class);
- if (rc)
- return rc;
-
- return class_interface_register(&i2o_device_class_interface);
-};
-
-/**
- * i2o_device_exit - I2O devices exit function
- *
- * Unregisters the I2O device class.
- */
-void i2o_device_exit(void)
-{
- class_interface_register(&i2o_device_class_interface);
- class_unregister(&i2o_device_class);
-};
-
EXPORT_SYMBOL(i2o_device_claim);
EXPORT_SYMBOL(i2o_device_claim_release);
EXPORT_SYMBOL(i2o_parm_field_get);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 739bfdef0c6d..0fb9c4e2ad4c 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -17,6 +17,9 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/i2o.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "core.h"
#define OSM_NAME "i2o"
@@ -58,9 +61,12 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
};
/* I2O bus type */
+extern struct device_attribute i2o_device_attrs[];
+
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
+ .dev_attrs = i2o_device_attrs,
};
/**
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index bda2c62648ba..b675b4ebbebd 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -30,6 +30,10 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/param.h> /* HZ */
#include "core.h"
#define OSM_NAME "exec-osm"
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 42f8b810d6e5..61b837de4b6a 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include "core.h"
#define OSM_NAME "i2o"
@@ -833,6 +834,7 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
+ class_device_unregister(c->classdev);
device_del(&c->device);
/* Ask the IOP to switch to RESET state */
@@ -1077,9 +1079,7 @@ static void i2o_iop_release(struct device *dev)
};
/* I2O controller class */
-static struct class i2o_controller_class = {
- .name = "i2o_controller",
-};
+static struct class *i2o_controller_class;
/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
@@ -1110,14 +1110,10 @@ struct i2o_controller *i2o_iop_alloc(void)
sprintf(c->name, "iop%d", c->unit);
device_initialize(&c->device);
- class_device_initialize(&c->classdev);
c->device.release = &i2o_iop_release;
- c->classdev.class = &i2o_controller_class;
- c->classdev.dev = &c->device;
snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
- snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
#if BITS_PER_LONG == 64
spin_lock_init(&c->context_list_lock);
@@ -1146,7 +1142,9 @@ int i2o_iop_add(struct i2o_controller *c)
goto iop_reset;
}
- if ((rc = class_device_add(&c->classdev))) {
+ c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
+ &c->device, "iop%d", c->unit);
+ if (IS_ERR(c->classdev)) {
osm_err("%s: could not add controller class\n", c->name);
goto device_del;
}
@@ -1184,7 +1182,7 @@ int i2o_iop_add(struct i2o_controller *c)
return 0;
class_del:
- class_device_del(&c->classdev);
+ class_device_unregister(c->classdev);
device_del:
device_del(&c->device);
@@ -1246,13 +1244,10 @@ static int __init i2o_iop_init(void)
printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
- rc = i2o_device_init();
- if (rc)
- goto exit;
-
- if ((rc = class_register(&i2o_controller_class))) {
+ i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
+ if (IS_ERR(i2o_controller_class)) {
osm_err("can't register class i2o_controller\n");
- goto device_exit;
+ goto exit;
}
if ((rc = i2o_driver_init()))
@@ -1273,10 +1268,7 @@ static int __init i2o_iop_init(void)
i2o_driver_exit();
class_exit:
- class_unregister(&i2o_controller_class);
-
- device_exit:
- i2o_device_exit();
+ class_destroy(i2o_controller_class);
exit:
return rc;
@@ -1292,8 +1284,7 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit();
i2o_exec_exit();
i2o_driver_exit();
- class_unregister(&i2o_controller_class);
- i2o_device_exit();
+ class_destroy(i2o_controller_class);
};
module_init(i2o_iop_init);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 7a60fd7be8ad..66c03e882570 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -32,6 +32,8 @@
#include <linux/i2o.h>
#include "core.h"
+#define OSM_DESCRIPTION "I2O-subsystem"
+
/* PCI device id table for all I2O controllers */
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
@@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c)
if (c->base.virt)
iounmap(c->base.virt);
+
+ pci_release_regions(c->pdev);
}
/**
@@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
struct device *dev = &pdev->dev;
int i;
+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+ printk(KERN_ERR "%s: device already claimed\n", c->name);
+ return -ENODEV;
+ }
+
for (i = 0; i < 6; i++) {
/* Skip I/O spaces */
if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
if (!c->base.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
+ i2o_pci_free(c);
return -ENOMEM;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
new file mode 100644
index 000000000000..550f29744812
--- /dev/null
+++ b/drivers/mfd/Kconfig
@@ -0,0 +1,25 @@
+#
+# Multifunction miscellaneous devices
+#
+
+menu "Multimedia Capabilities Port drivers"
+
+config MCP
+ tristate
+
+# Interface drivers
+config MCP_SA11X0
+ tristate "Support SA11x0 MCP interface"
+ depends on ARCH_SA1100
+ select MCP
+
+# Chip drivers
+config MCP_UCB1200
+ tristate "Support for UCB1200 / UCB1300"
+ depends on MCP
+
+config MCP_UCB1200_TS
+ tristate "Touchscreen interface support"
+ depends on MCP_UCB1200 && INPUT
+
+endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
new file mode 100644
index 000000000000..adb29b5368a8
--- /dev/null
+++ b/drivers/mfd/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for multifunction miscellaneous devices
+#
+
+obj-$(CONFIG_MCP) += mcp-core.o
+obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
+obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
+
+ifeq ($(CONFIG_SA1100_ASSABET),y)
+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
+endif
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
new file mode 100644
index 000000000000..c75d713c01e4
--- /dev/null
+++ b/drivers/mfd/mcp-core.c
@@ -0,0 +1,255 @@
+/*
+ * linux/drivers/mfd/mcp-core.c
+ *
+ * Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * Generic MCP (Multimedia Communications Port) layer. All MCP locking
+ * is solely held within this file.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/system.h>
+
+#include "mcp.h"
+
+#define to_mcp(d) container_of(d, struct mcp, attached_device)
+#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
+
+static int mcp_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int mcp_bus_probe(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ return drv->probe(mcp);
+}
+
+static int mcp_bus_remove(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ drv->remove(mcp);
+ return 0;
+}
+
+static int mcp_bus_suspend(struct device *dev, pm_message_t state)
+{
+ struct mcp *mcp = to_mcp(dev);
+ int ret = 0;
+
+ if (dev->driver) {
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ ret = drv->suspend(mcp, state);
+ }
+ return ret;
+}
+
+static int mcp_bus_resume(struct device *dev)
+{
+ struct mcp *mcp = to_mcp(dev);
+ int ret = 0;
+
+ if (dev->driver) {
+ struct mcp_driver *drv = to_mcp_driver(dev->driver);
+
+ ret = drv->resume(mcp);
+ }
+ return ret;
+}
+
+static struct bus_type mcp_bus_type = {
+ .name = "mcp",
+ .match = mcp_bus_match,
+ .suspend = mcp_bus_suspend,
+ .resume = mcp_bus_resume,
+};
+
+/**
+ * mcp_set_telecom_divisor - set the telecom divisor
+ * @mcp: MCP interface structure
+ * @div: SIB clock divisor
+ *
+ * Set the telecom divisor on the MCP interface. The resulting
+ * sample rate is SIBCLOCK/div.
+ */
+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
+{
+ spin_lock_irq(&mcp->lock);
+ mcp->ops->set_telecom_divisor(mcp, div);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_telecom_divisor);
+
+/**
+ * mcp_set_audio_divisor - set the audio divisor
+ * @mcp: MCP interface structure
+ * @div: SIB clock divisor
+ *
+ * Set the audio divisor on the MCP interface.
+ */
+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
+{
+ spin_lock_irq(&mcp->lock);
+ mcp->ops->set_audio_divisor(mcp, div);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_set_audio_divisor);
+
+/**
+ * mcp_reg_write - write a device register
+ * @mcp: MCP interface structure
+ * @reg: 4-bit register index
+ * @val: 16-bit data value
+ *
+ * Write a device register. The MCP interface must be enabled
+ * to prevent this function hanging.
+ */
+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ mcp->ops->reg_write(mcp, reg, val);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_reg_write);
+
+/**
+ * mcp_reg_read - read a device register
+ * @mcp: MCP interface structure
+ * @reg: 4-bit register index
+ *
+ * Read a device register and return its value. The MCP interface
+ * must be enabled to prevent this function hanging.
+ */
+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ val = mcp->ops->reg_read(mcp, reg);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL(mcp_reg_read);
+
+/**
+ * mcp_enable - enable the MCP interface
+ * @mcp: MCP interface to enable
+ *
+ * Enable the MCP interface. Each call to mcp_enable will need
+ * a corresponding call to mcp_disable to disable the interface.
+ */
+void mcp_enable(struct mcp *mcp)
+{
+ spin_lock_irq(&mcp->lock);
+ if (mcp->use_count++ == 0)
+ mcp->ops->enable(mcp);
+ spin_unlock_irq(&mcp->lock);
+}
+EXPORT_SYMBOL(mcp_enable);
+
+/**
+ * mcp_disable - disable the MCP interface
+ * @mcp: MCP interface to disable
+ *
+ * Disable the MCP interface. The MCP interface will only be
+ * disabled once the number of calls to mcp_enable matches the
+ * number of calls to mcp_disable.
+ */
+void mcp_disable(struct mcp *mcp)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
+ if (--mcp->use_count == 0)
+ mcp->ops->disable(mcp);
+ spin_unlock_irqrestore(&mcp->lock, flags);
+}
+EXPORT_SYMBOL(mcp_disable);
+
+static void mcp_release(struct device *dev)
+{
+ struct mcp *mcp = container_of(dev, struct mcp, attached_device);
+
+ kfree(mcp);
+}
+
+struct mcp *mcp_host_alloc(struct device *parent, size_t size)
+{
+ struct mcp *mcp;
+
+ mcp = kmalloc(sizeof(struct mcp) + size, GFP_KERNEL);
+ if (mcp) {
+ memset(mcp, 0, sizeof(struct mcp) + size);
+ spin_lock_init(&mcp->lock);
+ mcp->attached_device.parent = parent;
+ mcp->attached_device.bus = &mcp_bus_type;
+ mcp->attached_device.dma_mask = parent->dma_mask;
+ mcp->attached_device.release = mcp_release;
+ }
+ return mcp;
+}
+EXPORT_SYMBOL(mcp_host_alloc);
+
+int mcp_host_register(struct mcp *mcp)
+{
+ strcpy(mcp->attached_device.bus_id, "mcp0");
+ return device_register(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_register);
+
+void mcp_host_unregister(struct mcp *mcp)
+{
+ device_unregister(&mcp->attached_device);
+}
+EXPORT_SYMBOL(mcp_host_unregister);
+
+int mcp_driver_register(struct mcp_driver *mcpdrv)
+{
+ mcpdrv->drv.bus = &mcp_bus_type;
+ mcpdrv->drv.probe = mcp_bus_probe;
+ mcpdrv->drv.remove = mcp_bus_remove;
+ return driver_register(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_register);
+
+void mcp_driver_unregister(struct mcp_driver *mcpdrv)
+{
+ driver_unregister(&mcpdrv->drv);
+}
+EXPORT_SYMBOL(mcp_driver_unregister);
+
+static int __init mcp_init(void)
+{
+ return bus_register(&mcp_bus_type);
+}
+
+static void __exit mcp_exit(void)
+{
+ bus_unregister(&mcp_bus_type);
+}
+
+module_init(mcp_init);
+module_exit(mcp_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Core multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
new file mode 100644
index 000000000000..7daa0ed7331c
--- /dev/null
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -0,0 +1,273 @@
+/*
+ * linux/drivers/mfd/mcp-sa11x0.c
+ *
+ * Copyright (C) 2001-2005 Russell King
+ *
+ * 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.
+ *
+ * SA11x0 MCP (Multimedia Communications Port) driver.
+ *
+ * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+#include <asm/arch/mcp.h>
+
+#include <asm/arch/assabet.h>
+
+#include "mcp.h"
+
+struct mcp_sa11x0 {
+ u32 mccr0;
+ u32 mccr1;
+};
+
+#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
+
+static void
+mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
+{
+ unsigned int mccr0;
+
+ divisor /= 32;
+
+ mccr0 = Ser4MCCR0 & ~0x00007f00;
+ mccr0 |= divisor << 8;
+ Ser4MCCR0 = mccr0;
+}
+
+static void
+mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
+{
+ unsigned int mccr0;
+
+ divisor /= 32;
+
+ mccr0 = Ser4MCCR0 & ~0x0000007f;
+ mccr0 |= divisor;
+ Ser4MCCR0 = mccr0;
+}
+
+/*
+ * Write data to the device. The bit should be set after 3 subframe
+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static void
+mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+{
+ int ret = -ETIME;
+ int i;
+
+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+
+ for (i = 0; i < 2; i++) {
+ udelay(mcp->rw_timeout);
+ if (Ser4MCSR & MCSR_CWC) {
+ ret = 0;
+ break;
+ }
+ }
+
+ if (ret < 0)
+ printk(KERN_WARNING "mcp: write timed out\n");
+}
+
+/*
+ * Read data from the device. The bit should be set after 3 subframe
+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
+ * We really should try doing something more productive while we
+ * wait.
+ */
+static unsigned int
+mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
+{
+ int ret = -ETIME;
+ int i;
+
+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
+
+ for (i = 0; i < 2; i++) {
+ udelay(mcp->rw_timeout);
+ if (Ser4MCSR & MCSR_CRC) {
+ ret = Ser4MCDR2 & 0xffff;
+ break;
+ }
+ }
+
+ if (ret < 0)
+ printk(KERN_WARNING "mcp: read timed out\n");
+
+ return ret;
+}
+
+static void mcp_sa11x0_enable(struct mcp *mcp)
+{
+ Ser4MCSR = -1;
+ Ser4MCCR0 |= MCCR0_MCE;
+}
+
+static void mcp_sa11x0_disable(struct mcp *mcp)
+{
+ Ser4MCCR0 &= ~MCCR0_MCE;
+}
+
+/*
+ * Our methods.
+ */
+static struct mcp_ops mcp_sa11x0 = {
+ .set_telecom_divisor = mcp_sa11x0_set_telecom_divisor,
+ .set_audio_divisor = mcp_sa11x0_set_audio_divisor,
+ .reg_write = mcp_sa11x0_write,
+ .reg_read = mcp_sa11x0_read,
+ .enable = mcp_sa11x0_enable,
+ .disable = mcp_sa11x0_disable,
+};
+
+static int mcp_sa11x0_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mcp_plat_data *data = pdev->dev.platform_data;
+ struct mcp *mcp;
+ int ret;
+
+ if (!data)
+ return -ENODEV;
+
+ if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
+ return -EBUSY;
+
+ mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
+ if (!mcp) {
+ ret = -ENOMEM;
+ goto release;
+ }
+
+ mcp->owner = THIS_MODULE;
+ mcp->ops = &mcp_sa11x0;
+ mcp->sclk_rate = data->sclk_rate;
+ mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
+ mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
+ mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
+ mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
+
+ dev_set_drvdata(dev, mcp);
+
+ if (machine_is_assabet()) {
+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+ }
+
+ /*
+ * Setup the PPC unit correctly.
+ */
+ PPDR &= ~PPC_RXD4;
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PSDR |= PPC_RXD4;
+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
+ /*
+ * Initialise device. Note that we initially
+ * set the sampling rate to minimum.
+ */
+ Ser4MCSR = -1;
+ Ser4MCCR1 = data->mccr1;
+ Ser4MCCR0 = data->mccr0 | 0x7f7f;
+
+ /*
+ * Calculate the read/write timeout (us) from the bit clock
+ * rate. This is the period for 3 64-bit frames. Always
+ * round this time up.
+ */
+ mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
+ mcp->sclk_rate;
+
+ ret = mcp_host_register(mcp);
+ if (ret == 0)
+ goto out;
+
+ release:
+ release_mem_region(0x80060000, 0x60);
+ dev_set_drvdata(dev, NULL);
+
+ out:
+ return ret;
+}
+
+static int mcp_sa11x0_remove(struct device *dev)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+ mcp_host_unregister(mcp);
+ release_mem_region(0x80060000, 0x60);
+
+ return 0;
+}
+
+static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ priv(mcp)->mccr0 = Ser4MCCR0;
+ priv(mcp)->mccr1 = Ser4MCCR1;
+ Ser4MCCR0 &= ~MCCR0_MCE;
+
+ return 0;
+}
+
+static int mcp_sa11x0_resume(struct device *dev)
+{
+ struct mcp *mcp = dev_get_drvdata(dev);
+
+ Ser4MCCR1 = priv(mcp)->mccr1;
+ Ser4MCCR0 = priv(mcp)->mccr0;
+
+ return 0;
+}
+
+/*
+ * The driver for the SA11x0 MCP port.
+ */
+static struct device_driver mcp_sa11x0_driver = {
+ .name = "sa11x0-mcp",
+ .bus = &platform_bus_type,
+ .probe = mcp_sa11x0_probe,
+ .remove = mcp_sa11x0_remove,
+ .suspend = mcp_sa11x0_suspend,
+ .resume = mcp_sa11x0_resume,
+};
+
+/*
+ * This needs re-working
+ */
+static int __init mcp_sa11x0_init(void)
+{
+ return driver_register(&mcp_sa11x0_driver);
+}
+
+static void __exit mcp_sa11x0_exit(void)
+{
+ driver_unregister(&mcp_sa11x0_driver);
+}
+
+module_init(mcp_sa11x0_init);
+module_exit(mcp_sa11x0_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mcp.h b/drivers/mfd/mcp.h
new file mode 100644
index 000000000000..c093a93b8808
--- /dev/null
+++ b/drivers/mfd/mcp.h
@@ -0,0 +1,66 @@
+/*
+ * linux/drivers/mfd/mcp.h
+ *
+ * Copyright (C) 2001 Russell King, 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.
+ */
+#ifndef MCP_H
+#define MCP_H
+
+struct mcp_ops;
+
+struct mcp {
+ struct module *owner;
+ struct mcp_ops *ops;
+ spinlock_t lock;
+ int use_count;
+ unsigned int sclk_rate;
+ unsigned int rw_timeout;
+ dma_device_t dma_audio_rd;
+ dma_device_t dma_audio_wr;
+ dma_device_t dma_telco_rd;
+ dma_device_t dma_telco_wr;
+ struct device attached_device;
+};
+
+struct mcp_ops {
+ void (*set_telecom_divisor)(struct mcp *, unsigned int);
+ void (*set_audio_divisor)(struct mcp *, unsigned int);
+ void (*reg_write)(struct mcp *, unsigned int, unsigned int);
+ unsigned int (*reg_read)(struct mcp *, unsigned int);
+ void (*enable)(struct mcp *);
+ void (*disable)(struct mcp *);
+};
+
+void mcp_set_telecom_divisor(struct mcp *, unsigned int);
+void mcp_set_audio_divisor(struct mcp *, unsigned int);
+void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
+unsigned int mcp_reg_read(struct mcp *, unsigned int);
+void mcp_enable(struct mcp *);
+void mcp_disable(struct mcp *);
+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
+
+struct mcp *mcp_host_alloc(struct device *, size_t);
+int mcp_host_register(struct mcp *);
+void mcp_host_unregister(struct mcp *);
+
+struct mcp_driver {
+ struct device_driver drv;
+ int (*probe)(struct mcp *);
+ void (*remove)(struct mcp *);
+ int (*suspend)(struct mcp *, pm_message_t);
+ int (*resume)(struct mcp *);
+};
+
+int mcp_driver_register(struct mcp_driver *);
+void mcp_driver_unregister(struct mcp_driver *);
+
+#define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device)
+#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
+
+#define mcp_priv(mcp) ((void *)((mcp)+1))
+
+#endif
diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c
new file mode 100644
index 000000000000..e325fa71f38b
--- /dev/null
+++ b/drivers/mfd/ucb1x00-assabet.c
@@ -0,0 +1,73 @@
+/*
+ * linux/drivers/mfd/ucb1x00-assabet.c
+ *
+ * Copyright (C) 2001-2003 Russell King, 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.
+ *
+ * We handle the machine-specific bits of the UCB1x00 driver here.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+
+#include "ucb1x00.h"
+
+#define UCB1X00_ATTR(name,input)\
+static ssize_t name##_show(struct class_device *dev, char *buf) \
+{ \
+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); \
+ int val; \
+ ucb1x00_adc_enable(ucb); \
+ val = ucb1x00_adc_read(ucb, input, UCB_NOSYNC); \
+ ucb1x00_adc_disable(ucb); \
+ return sprintf(buf, "%d\n", val); \
+} \
+static CLASS_DEVICE_ATTR(name,0444,name##_show,NULL)
+
+UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1);
+UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0);
+UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
+
+static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
+{
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+ class_device_create_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+ return 0;
+}
+
+static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
+{
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+ class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+}
+
+static struct ucb1x00_driver ucb1x00_assabet_driver = {
+ .add = ucb1x00_assabet_add,
+ .remove = ucb1x00_assabet_remove,
+};
+
+static int __init ucb1x00_assabet_init(void)
+{
+ return ucb1x00_register_driver(&ucb1x00_assabet_driver);
+}
+
+static void __exit ucb1x00_assabet_exit(void)
+{
+ ucb1x00_unregister_driver(&ucb1x00_assabet_driver);
+}
+
+module_init(ucb1x00_assabet_init);
+module_exit(ucb1x00_assabet_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
new file mode 100644
index 000000000000..e335d54c4659
--- /dev/null
+++ b/drivers/mfd/ucb1x00-core.c
@@ -0,0 +1,663 @@
+/*
+ * linux/drivers/mfd/ucb1x00-core.c
+ *
+ * Copyright (C) 2001 Russell King, 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.
+ *
+ * The UCB1x00 core driver provides basic services for handling IO,
+ * the ADC, interrupts, and accessing registers. It is designed
+ * such that everything goes through this layer, thereby providing
+ * a consistent locking methodology, as well as allowing the drivers
+ * to be used on other non-MCP-enabled hardware platforms.
+ *
+ * Note that all locks are private to this file. Nothing else may
+ * touch them.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include "ucb1x00.h"
+
+static DECLARE_MUTEX(ucb1x00_sem);
+static LIST_HEAD(ucb1x00_drivers);
+static LIST_HEAD(ucb1x00_devices);
+
+/**
+ * ucb1x00_io_set_dir - set IO direction
+ * @ucb: UCB1x00 structure describing chip
+ * @in: bitfield of IO pins to be set as inputs
+ * @out: bitfield of IO pins to be set as outputs
+ *
+ * Set the IO direction of the ten general purpose IO pins on
+ * the UCB1x00 chip. The @in bitfield has priority over the
+ * @out bitfield, in that if you specify a pin as both input
+ * and output, it will end up as an input.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ucb->io_lock, flags);
+ ucb->io_dir |= out;
+ ucb->io_dir &= ~in;
+
+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+ spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ * ucb1x00_io_write - set or clear IO outputs
+ * @ucb: UCB1x00 structure describing chip
+ * @set: bitfield of IO pins to set to logic '1'
+ * @clear: bitfield of IO pins to set to logic '0'
+ *
+ * Set the IO output state of the specified IO pins. The value
+ * is retained if the pins are subsequently configured as inputs.
+ * The @clear bitfield has priority over the @set bitfield -
+ * outputs will be cleared.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ucb->io_lock, flags);
+ ucb->io_out |= set;
+ ucb->io_out &= ~clear;
+
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+ spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ * ucb1x00_io_read - read the current state of the IO pins
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Return a bitfield describing the logic state of the ten
+ * general purpose IO pins.
+ *
+ * ucb1x00_enable must have been called to enable the comms
+ * before using this function.
+ *
+ * This function does not take any semaphores or spinlocks.
+ */
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
+{
+ return ucb1x00_reg_read(ucb, UCB_IO_DATA);
+}
+
+/*
+ * UCB1300 data sheet says we must:
+ * 1. enable ADC => 5us (including reference startup time)
+ * 2. select input => 51*tsibclk => 4.3us
+ * 3. start conversion => 102*tsibclk => 8.5us
+ * (tsibclk = 1/11981000)
+ * Period between SIB 128-bit frames = 10.7us
+ */
+
+/**
+ * ucb1x00_adc_enable - enable the ADC converter
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
+ * Any code wishing to use the ADC converter must call this
+ * function prior to using it.
+ *
+ * This function takes the ADC semaphore to prevent two or more
+ * concurrent uses, and therefore may sleep. As a result, it
+ * can only be called from process context, not interrupt
+ * context.
+ *
+ * You should release the ADC as soon as possible using
+ * ucb1x00_adc_disable.
+ */
+void ucb1x00_adc_enable(struct ucb1x00 *ucb)
+{
+ down(&ucb->adc_sem);
+
+ ucb->adc_cr |= UCB_ADC_ENA;
+
+ ucb1x00_enable(ucb);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+}
+
+/**
+ * ucb1x00_adc_read - read the specified ADC channel
+ * @ucb: UCB1x00 structure describing chip
+ * @adc_channel: ADC channel mask
+ * @sync: wait for syncronisation pulse.
+ *
+ * Start an ADC conversion and wait for the result. Note that
+ * synchronised ADC conversions (via the ADCSYNC pin) must wait
+ * until the trigger is asserted and the conversion is finished.
+ *
+ * This function currently spins waiting for the conversion to
+ * complete (2 frames max without sync).
+ *
+ * If called for a synchronised ADC conversion, it may sleep
+ * with the ADC semaphore held.
+ */
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
+{
+ unsigned int val;
+
+ if (sync)
+ adc_channel |= UCB_ADC_SYNC_ENA;
+
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
+
+ for (;;) {
+ val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
+ if (val & UCB_ADC_DAT_VAL)
+ break;
+ /* yield to other processes */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ return UCB_ADC_DAT(val);
+}
+
+/**
+ * ucb1x00_adc_disable - disable the ADC converter
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Disable the ADC converter and release the ADC semaphore.
+ */
+void ucb1x00_adc_disable(struct ucb1x00 *ucb)
+{
+ ucb->adc_cr &= ~UCB_ADC_ENA;
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+ ucb1x00_disable(ucb);
+
+ up(&ucb->adc_sem);
+}
+
+/*
+ * UCB1x00 Interrupt handling.
+ *
+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
+ * Since we need to read an internal register, we must re-enable
+ * SIBCLK to talk to the chip. We leave the clock running until
+ * we have finished processing all interrupts from the chip.
+ */
+static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+ struct ucb1x00 *ucb = devid;
+ struct ucb1x00_irq *irq;
+ unsigned int isr, i;
+
+ ucb1x00_enable(ucb);
+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
+ if (isr & 1 && irq->fn)
+ irq->fn(i, irq->devid);
+ ucb1x00_disable(ucb);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ucb1x00_hook_irq - hook a UCB1x00 interrupt
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @fn: function to call when interrupt is triggered
+ * @devid: device id to pass to interrupt handler
+ *
+ * Hook the specified interrupt. You can only register one handler
+ * for each interrupt source. The interrupt source is not enabled
+ * by this function; use ucb1x00_enable_irq instead.
+ *
+ * Interrupt handlers will be called with other interrupts enabled.
+ *
+ * Returns zero on success, or one of the following errors:
+ * -EINVAL if the interrupt index is invalid
+ * -EBUSY if the interrupt has already been hooked
+ */
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
+{
+ struct ucb1x00_irq *irq;
+ int ret = -EINVAL;
+
+ if (idx < 16) {
+ irq = ucb->irq_handler + idx;
+ ret = -EBUSY;
+
+ spin_lock_irq(&ucb->lock);
+ if (irq->fn == NULL) {
+ irq->devid = devid;
+ irq->fn = fn;
+ ret = 0;
+ }
+ spin_unlock_irq(&ucb->lock);
+ }
+ return ret;
+}
+
+/**
+ * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @edges: interrupt edges to enable
+ *
+ * Enable the specified interrupt to trigger on %UCB_RISING,
+ * %UCB_FALLING or both edges. The interrupt should have been
+ * hooked by ucb1x00_hook_irq.
+ */
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+ unsigned long flags;
+
+ if (idx < 16) {
+ spin_lock_irqsave(&ucb->lock, flags);
+
+ ucb1x00_enable(ucb);
+ if (edges & UCB_RISING) {
+ ucb->irq_ris_enbl |= 1 << idx;
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ }
+ if (edges & UCB_FALLING) {
+ ucb->irq_fal_enbl |= 1 << idx;
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ }
+ ucb1x00_disable(ucb);
+ spin_unlock_irqrestore(&ucb->lock, flags);
+ }
+}
+
+/**
+ * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
+ * @ucb: UCB1x00 structure describing chip
+ * @edges: interrupt edges to disable
+ *
+ * Disable the specified interrupt triggering on the specified
+ * (%UCB_RISING, %UCB_FALLING or both) edges.
+ */
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+ unsigned long flags;
+
+ if (idx < 16) {
+ spin_lock_irqsave(&ucb->lock, flags);
+
+ ucb1x00_enable(ucb);
+ if (edges & UCB_RISING) {
+ ucb->irq_ris_enbl &= ~(1 << idx);
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ }
+ if (edges & UCB_FALLING) {
+ ucb->irq_fal_enbl &= ~(1 << idx);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ }
+ ucb1x00_disable(ucb);
+ spin_unlock_irqrestore(&ucb->lock, flags);
+ }
+}
+
+/**
+ * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
+ * @ucb: UCB1x00 structure describing chip
+ * @idx: interrupt index
+ * @devid: device id.
+ *
+ * Disable the interrupt source and remove the handler. devid must
+ * match the devid passed when hooking the interrupt.
+ *
+ * Returns zero on success, or one of the following errors:
+ * -EINVAL if the interrupt index is invalid
+ * -ENOENT if devid does not match
+ */
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
+{
+ struct ucb1x00_irq *irq;
+ int ret;
+
+ if (idx >= 16)
+ goto bad;
+
+ irq = ucb->irq_handler + idx;
+ ret = -ENOENT;
+
+ spin_lock_irq(&ucb->lock);
+ if (irq->devid == devid) {
+ ucb->irq_ris_enbl &= ~(1 << idx);
+ ucb->irq_fal_enbl &= ~(1 << idx);
+
+ ucb1x00_enable(ucb);
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+ ucb1x00_disable(ucb);
+
+ irq->fn = NULL;
+ irq->devid = NULL;
+ ret = 0;
+ }
+ spin_unlock_irq(&ucb->lock);
+ return ret;
+
+bad:
+ printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx);
+ return -EINVAL;
+}
+
+static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
+{
+ struct ucb1x00_dev *dev;
+ int ret = -ENOMEM;
+
+ dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL);
+ if (dev) {
+ dev->ucb = ucb;
+ dev->drv = drv;
+
+ ret = drv->add(dev);
+
+ if (ret == 0) {
+ list_add(&dev->dev_node, &ucb->devs);
+ list_add(&dev->drv_node, &drv->devs);
+ } else {
+ kfree(dev);
+ }
+ }
+ return ret;
+}
+
+static void ucb1x00_remove_dev(struct ucb1x00_dev *dev)
+{
+ dev->drv->remove(dev);
+ list_del(&dev->dev_node);
+ list_del(&dev->drv_node);
+ kfree(dev);
+}
+
+/*
+ * Try to probe our interrupt, rather than relying on lots of
+ * hard-coded machine dependencies. For reference, the expected
+ * IRQ mappings are:
+ *
+ * Machine Default IRQ
+ * adsbitsy IRQ_GPCIN4
+ * cerf IRQ_GPIO_UCB1200_IRQ
+ * flexanet IRQ_GPIO_GUI
+ * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
+ * graphicsclient ADS_EXT_IRQ(8)
+ * graphicsmaster ADS_EXT_IRQ(8)
+ * lart LART_IRQ_UCB1200
+ * omnimeter IRQ_GPIO23
+ * pfs168 IRQ_GPIO_UCB1300_IRQ
+ * simpad IRQ_GPIO_UCB1300_IRQ
+ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
+ * yopy IRQ_GPIO_UCB1200_IRQ
+ */
+static int ucb1x00_detect_irq(struct ucb1x00 *ucb)
+{
+ unsigned long mask;
+
+ mask = probe_irq_on();
+ if (!mask)
+ return NO_IRQ;
+
+ /*
+ * Enable the ADC interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /*
+ * Cause an ADC interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+
+ /*
+ * Wait for the conversion to complete.
+ */
+ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
+ ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
+
+ /*
+ * Disable and clear interrupt.
+ */
+ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
+ ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /*
+ * Read triggered interrupt.
+ */
+ return probe_irq_off(mask);
+}
+
+static void ucb1x00_release(struct class_device *dev)
+{
+ struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);
+ kfree(ucb);
+}
+
+static struct class ucb1x00_class = {
+ .name = "ucb1x00",
+ .release = ucb1x00_release,
+};
+
+static int ucb1x00_probe(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb;
+ struct ucb1x00_driver *drv;
+ unsigned int id;
+ int ret = -ENODEV;
+
+ mcp_enable(mcp);
+ id = mcp_reg_read(mcp, UCB_ID);
+
+ if (id != UCB_ID_1200 && id != UCB_ID_1300) {
+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
+ goto err_disable;
+ }
+
+ ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
+ ret = -ENOMEM;
+ if (!ucb)
+ goto err_disable;
+
+ memset(ucb, 0, sizeof(struct ucb1x00));
+
+ ucb->cdev.class = &ucb1x00_class;
+ ucb->cdev.dev = &mcp->attached_device;
+ strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id));
+
+ spin_lock_init(&ucb->lock);
+ spin_lock_init(&ucb->io_lock);
+ sema_init(&ucb->adc_sem, 1);
+
+ ucb->id = id;
+ ucb->mcp = mcp;
+ ucb->irq = ucb1x00_detect_irq(ucb);
+ if (ucb->irq == NO_IRQ) {
+ printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb);
+ if (ret) {
+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+ ucb->irq, ret);
+ goto err_free;
+ }
+
+ set_irq_type(ucb->irq, IRQT_RISING);
+ mcp_set_drvdata(mcp, ucb);
+
+ ret = class_device_register(&ucb->cdev);
+ if (ret)
+ goto err_irq;
+
+ INIT_LIST_HEAD(&ucb->devs);
+ down(&ucb1x00_sem);
+ list_add(&ucb->node, &ucb1x00_devices);
+ list_for_each_entry(drv, &ucb1x00_drivers, node) {
+ ucb1x00_add_dev(ucb, drv);
+ }
+ up(&ucb1x00_sem);
+ goto out;
+
+ err_irq:
+ free_irq(ucb->irq, ucb);
+ err_free:
+ kfree(ucb);
+ err_disable:
+ mcp_disable(mcp);
+ out:
+ return ret;
+}
+
+static void ucb1x00_remove(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct list_head *l, *n;
+
+ down(&ucb1x00_sem);
+ list_del(&ucb->node);
+ list_for_each_safe(l, n, &ucb->devs) {
+ struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node);
+ ucb1x00_remove_dev(dev);
+ }
+ up(&ucb1x00_sem);
+
+ free_irq(ucb->irq, ucb);
+ class_device_unregister(&ucb->cdev);
+}
+
+int ucb1x00_register_driver(struct ucb1x00_driver *drv)
+{
+ struct ucb1x00 *ucb;
+
+ INIT_LIST_HEAD(&drv->devs);
+ down(&ucb1x00_sem);
+ list_add(&drv->node, &ucb1x00_drivers);
+ list_for_each_entry(ucb, &ucb1x00_devices, node) {
+ ucb1x00_add_dev(ucb, drv);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
+{
+ struct list_head *n, *l;
+
+ down(&ucb1x00_sem);
+ list_del(&drv->node);
+ list_for_each_safe(l, n, &drv->devs) {
+ struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node);
+ ucb1x00_remove_dev(dev);
+ }
+ up(&ucb1x00_sem);
+}
+
+static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct ucb1x00_dev *dev;
+
+ down(&ucb1x00_sem);
+ list_for_each_entry(dev, &ucb->devs, dev_node) {
+ if (dev->drv->suspend)
+ dev->drv->suspend(dev, state);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+static int ucb1x00_resume(struct mcp *mcp)
+{
+ struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+ struct ucb1x00_dev *dev;
+
+ down(&ucb1x00_sem);
+ list_for_each_entry(dev, &ucb->devs, dev_node) {
+ if (dev->drv->resume)
+ dev->drv->resume(dev);
+ }
+ up(&ucb1x00_sem);
+ return 0;
+}
+
+static struct mcp_driver ucb1x00_driver = {
+ .drv = {
+ .name = "ucb1x00",
+ },
+ .probe = ucb1x00_probe,
+ .remove = ucb1x00_remove,
+ .suspend = ucb1x00_suspend,
+ .resume = ucb1x00_resume,
+};
+
+static int __init ucb1x00_init(void)
+{
+ int ret = class_register(&ucb1x00_class);
+ if (ret == 0) {
+ ret = mcp_driver_register(&ucb1x00_driver);
+ if (ret)
+ class_unregister(&ucb1x00_class);
+ }
+ return ret;
+}
+
+static void __exit ucb1x00_exit(void)
+{
+ mcp_driver_unregister(&ucb1x00_driver);
+ class_unregister(&ucb1x00_class);
+}
+
+module_init(ucb1x00_init);
+module_exit(ucb1x00_exit);
+
+EXPORT_SYMBOL(ucb1x00_io_set_dir);
+EXPORT_SYMBOL(ucb1x00_io_write);
+EXPORT_SYMBOL(ucb1x00_io_read);
+
+EXPORT_SYMBOL(ucb1x00_adc_enable);
+EXPORT_SYMBOL(ucb1x00_adc_read);
+EXPORT_SYMBOL(ucb1x00_adc_disable);
+
+EXPORT_SYMBOL(ucb1x00_hook_irq);
+EXPORT_SYMBOL(ucb1x00_free_irq);
+EXPORT_SYMBOL(ucb1x00_enable_irq);
+EXPORT_SYMBOL(ucb1x00_disable_irq);
+
+EXPORT_SYMBOL(ucb1x00_register_driver);
+EXPORT_SYMBOL(ucb1x00_unregister_driver);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
new file mode 100644
index 000000000000..a984c0efabf0
--- /dev/null
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -0,0 +1,436 @@
+/*
+ * Touchscreen driver for UCB1x00-based touchscreens
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ * Copyright (C) 2005 Pavel Machek
+ *
+ * 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.
+ *
+ * 21-Jan-2002 <jco@ict.es> :
+ *
+ * Added support for synchronous A/D mode. This mode is useful to
+ * avoid noise induced in the touchpanel by the LCD, provided that
+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
+ * It is important to note that the signal connected to the ADCSYNC
+ * pin should provide pulses even when the LCD is blanked, otherwise
+ * a pen touch needed to unblank the LCD will never be read.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/semaphore.h>
+#include <asm/arch/collie.h>
+#include <asm/mach-types.h>
+
+#include "ucb1x00.h"
+
+
+struct ucb1x00_ts {
+ struct input_dev *idev;
+ struct ucb1x00 *ucb;
+
+ wait_queue_head_t irq_wait;
+ struct task_struct *rtask;
+ u16 x_res;
+ u16 y_res;
+
+ unsigned int restart:1;
+ unsigned int adcsync:1;
+};
+
+static int adcsync;
+
+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
+{
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+ input_sync(ts->idev);
+}
+
+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
+{
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+/*
+ * Switch to interrupt mode.
+ */
+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, 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);
+}
+
+/*
+ * Switch to pressure mode, and read pressure. We don't need to wait
+ * here, since both plates are being driven.
+ */
+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
+{
+ if (machine_is_collie()) {
+ ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
+ } else {
+ ucb1x00_reg_write(ts->ucb, 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);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+ }
+}
+
+/*
+ * Switch to X position mode and measure Y plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
+{
+ if (machine_is_collie())
+ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
+ else {
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ }
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+}
+
+/*
+ * Switch to Y position mode and measure X plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
+{
+ if (machine_is_collie())
+ ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
+ else {
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ }
+
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
+}
+
+/*
+ * Switch to X plate resistance mode. Set MX to ground, PX to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+/*
+ * Switch to Y plate resistance mode. Set MY to ground, PY to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
+{
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
+{
+ unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+ if (machine_is_collie())
+ return (!(val & (UCB_TS_CR_TSPX_LOW)));
+ else
+ return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
+}
+
+/*
+ * This is a RT kernel thread that handles the ADC accesses
+ * (mainly so we can use semaphores in the UCB1200 core code
+ * to serialise accesses to the ADC).
+ */
+static int ucb1x00_thread(void *_ts)
+{
+ struct ucb1x00_ts *ts = _ts;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ int valid;
+
+ /*
+ * We could run as a real-time thread. However, thus far
+ * this doesn't seem to be necessary.
+ */
+// tsk->policy = SCHED_FIFO;
+// tsk->rt_priority = 1;
+
+ valid = 0;
+
+ add_wait_queue(&ts->irq_wait, &wait);
+ while (!kthread_should_stop()) {
+ unsigned int x, y, p;
+ signed long timeout;
+
+ ts->restart = 0;
+
+ ucb1x00_adc_enable(ts->ucb);
+
+ x = ucb1x00_ts_read_xpos(ts);
+ y = ucb1x00_ts_read_ypos(ts);
+ p = ucb1x00_ts_read_pressure(ts);
+
+ /*
+ * Switch back to interrupt mode.
+ */
+ ucb1x00_ts_mode_int(ts);
+ ucb1x00_adc_disable(ts->ucb);
+
+ msleep(10);
+
+ ucb1x00_enable(ts->ucb);
+
+
+ if (ucb1x00_ts_pen_down(ts)) {
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
+ ucb1x00_disable(ts->ucb);
+
+ /*
+ * If we spat out a valid sample set last time,
+ * spit out a "pen off" sample here.
+ */
+ if (valid) {
+ ucb1x00_ts_event_release(ts);
+ valid = 0;
+ }
+
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ } else {
+ ucb1x00_disable(ts->ucb);
+
+ /*
+ * Filtering is policy. Policy belongs in user
+ * space. We therefore leave it to user space
+ * to do any filtering they please.
+ */
+ if (!ts->restart) {
+ ucb1x00_ts_evt_add(ts, p, x, y);
+ valid = 1;
+ }
+
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ timeout = HZ / 100;
+ }
+
+ try_to_freeze();
+
+ schedule_timeout(timeout);
+ }
+
+ remove_wait_queue(&ts->irq_wait, &wait);
+
+ ts->rtask = NULL;
+ return 0;
+}
+
+/*
+ * We only detect touch screen _touches_ with this interrupt
+ * handler, and even then we just schedule our task.
+ */
+static void ucb1x00_ts_irq(int idx, void *id)
+{
+ struct ucb1x00_ts *ts = id;
+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+ wake_up(&ts->irq_wait);
+}
+
+static int ucb1x00_ts_open(struct input_dev *idev)
+{
+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+ int ret = 0;
+
+ BUG_ON(ts->rtask);
+
+ init_waitqueue_head(&ts->irq_wait);
+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
+ if (ret < 0)
+ goto out;
+
+ /*
+ * If we do this at all, we should allow the user to
+ * measure and read the X and Y resistance at any time.
+ */
+ ucb1x00_adc_enable(ts->ucb);
+ ts->x_res = ucb1x00_ts_read_xres(ts);
+ ts->y_res = ucb1x00_ts_read_yres(ts);
+ ucb1x00_adc_disable(ts->ucb);
+
+ ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
+ if (!IS_ERR(ts->rtask)) {
+ ret = 0;
+ } else {
+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+ ts->rtask = NULL;
+ ret = -EFAULT;
+ }
+
+ out:
+ return ret;
+}
+
+/*
+ * Release touchscreen resources. Disable IRQs.
+ */
+static void ucb1x00_ts_close(struct input_dev *idev)
+{
+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+
+ if (ts->rtask)
+ kthread_stop(ts->rtask);
+
+ ucb1x00_enable(ts->ucb);
+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
+ ucb1x00_disable(ts->ucb);
+}
+
+#ifdef CONFIG_PM
+static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts = dev->priv;
+
+ if (ts->rtask != NULL) {
+ /*
+ * Restart the TS thread to ensure the
+ * TS interrupt mode is set up again
+ * after sleep.
+ */
+ ts->restart = 1;
+ wake_up(&ts->irq_wait);
+ }
+ return 0;
+}
+#else
+#define ucb1x00_ts_resume NULL
+#endif
+
+
+/*
+ * Initialisation.
+ */
+static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts;
+
+ ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->idev = input_allocate_device();
+ if (!ts->idev) {
+ kfree(ts);
+ return -ENOMEM;
+ }
+
+ ts->ucb = dev->ucb;
+ ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
+
+ ts->idev->name = "Touchscreen panel";
+ ts->idev->id.product = ts->ucb->id;
+ ts->idev->open = ucb1x00_ts_open;
+ ts->idev->close = ucb1x00_ts_close;
+
+ __set_bit(EV_ABS, ts->idev->evbit);
+ __set_bit(ABS_X, ts->idev->absbit);
+ __set_bit(ABS_Y, ts->idev->absbit);
+ __set_bit(ABS_PRESSURE, ts->idev->absbit);
+
+ input_register_device(ts->idev);
+
+ dev->priv = ts;
+
+ return 0;
+}
+
+static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
+{
+ struct ucb1x00_ts *ts = dev->priv;
+
+ input_unregister_device(ts->idev);
+ kfree(ts);
+}
+
+static struct ucb1x00_driver ucb1x00_ts_driver = {
+ .add = ucb1x00_ts_add,
+ .remove = ucb1x00_ts_remove,
+ .resume = ucb1x00_ts_resume,
+};
+
+static int __init ucb1x00_ts_init(void)
+{
+ return ucb1x00_register_driver(&ucb1x00_ts_driver);
+}
+
+static void __exit ucb1x00_ts_exit(void)
+{
+ ucb1x00_unregister_driver(&ucb1x00_ts_driver);
+}
+
+module_param(adcsync, int, 0444);
+module_init(ucb1x00_ts_init);
+module_exit(ucb1x00_ts_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
new file mode 100644
index 000000000000..9c9a647d8b7b
--- /dev/null
+++ b/drivers/mfd/ucb1x00.h
@@ -0,0 +1,254 @@
+/*
+ * linux/drivers/mfd/ucb1x00.h
+ *
+ * Copyright (C) 2001 Russell King, 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.
+ */
+#ifndef UCB1200_H
+#define UCB1200_H
+
+#define UCB_IO_DATA 0x00
+#define UCB_IO_DIR 0x01
+
+#define UCB_IO_0 (1 << 0)
+#define UCB_IO_1 (1 << 1)
+#define UCB_IO_2 (1 << 2)
+#define UCB_IO_3 (1 << 3)
+#define UCB_IO_4 (1 << 4)
+#define UCB_IO_5 (1 << 5)
+#define UCB_IO_6 (1 << 6)
+#define UCB_IO_7 (1 << 7)
+#define UCB_IO_8 (1 << 8)
+#define UCB_IO_9 (1 << 9)
+
+#define UCB_IE_RIS 0x02
+#define UCB_IE_FAL 0x03
+#define UCB_IE_STATUS 0x04
+#define UCB_IE_CLEAR 0x04
+#define UCB_IE_ADC (1 << 11)
+#define UCB_IE_TSPX (1 << 12)
+#define UCB_IE_TSMX (1 << 13)
+#define UCB_IE_TCLIP (1 << 14)
+#define UCB_IE_ACLIP (1 << 15)
+
+#define UCB_IRQ_TSPX 12
+
+#define UCB_TC_A 0x05
+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
+
+#define UCB_TC_B 0x06
+#define UCB_TC_B_VOICE_ENA (1 << 3)
+#define UCB_TC_B_CLIP (1 << 4)
+#define UCB_TC_B_ATT (1 << 6)
+#define UCB_TC_B_SIDE_ENA (1 << 11)
+#define UCB_TC_B_MUTE (1 << 13)
+#define UCB_TC_B_IN_ENA (1 << 14)
+#define UCB_TC_B_OUT_ENA (1 << 15)
+
+#define UCB_AC_A 0x07
+#define UCB_AC_B 0x08
+#define UCB_AC_B_LOOP (1 << 8)
+#define UCB_AC_B_MUTE (1 << 13)
+#define UCB_AC_B_IN_ENA (1 << 14)
+#define UCB_AC_B_OUT_ENA (1 << 15)
+
+#define UCB_TS_CR 0x09
+#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 0x0a
+#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 0x0b
+#define UCB_ADC_DAT_VAL (1 << 15)
+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
+
+#define UCB_ID 0x0c
+#define UCB_ID_1200 0x1004
+#define UCB_ID_1300 0x1005
+
+#define UCB_MODE 0x0d
+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
+#define UCB_MODE_AUD_OFF_CAN (1 << 13)
+
+#include "mcp.h"
+
+struct ucb1x00_irq {
+ void *devid;
+ void (*fn)(int, void *);
+};
+
+struct ucb1x00 {
+ spinlock_t lock;
+ struct mcp *mcp;
+ unsigned int irq;
+ struct semaphore adc_sem;
+ spinlock_t io_lock;
+ u16 id;
+ u16 io_dir;
+ u16 io_out;
+ u16 adc_cr;
+ u16 irq_fal_enbl;
+ u16 irq_ris_enbl;
+ struct ucb1x00_irq irq_handler[16];
+ struct class_device cdev;
+ struct list_head node;
+ struct list_head devs;
+};
+
+struct ucb1x00_driver;
+
+struct ucb1x00_dev {
+ struct list_head dev_node;
+ struct list_head drv_node;
+ struct ucb1x00 *ucb;
+ struct ucb1x00_driver *drv;
+ void *priv;
+};
+
+struct ucb1x00_driver {
+ struct list_head node;
+ struct list_head devs;
+ int (*add)(struct ucb1x00_dev *dev);
+ void (*remove)(struct ucb1x00_dev *dev);
+ int (*suspend)(struct ucb1x00_dev *dev, pm_message_t state);
+ int (*resume)(struct ucb1x00_dev *dev);
+};
+
+#define classdev_to_ucb1x00(cd) container_of(cd, struct ucb1x00, cdev)
+
+int ucb1x00_register_driver(struct ucb1x00_driver *);
+void ucb1x00_unregister_driver(struct ucb1x00_driver *);
+
+/**
+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Return the SIB clock rate in Hz.
+ */
+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
+{
+ return mcp_get_sclk_rate(ucb->mcp);
+}
+
+/**
+ * ucb1x00_enable - enable the UCB1x00 SIB clock
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Enable the SIB clock. This can be called multiple times.
+ */
+static inline void ucb1x00_enable(struct ucb1x00 *ucb)
+{
+ mcp_enable(ucb->mcp);
+}
+
+/**
+ * ucb1x00_disable - disable the UCB1x00 SIB clock
+ * @ucb: UCB1x00 structure describing chip
+ *
+ * Disable the SIB clock. The SIB clock will only be disabled
+ * when the number of ucb1x00_enable calls match the number of
+ * ucb1x00_disable calls.
+ */
+static inline void ucb1x00_disable(struct ucb1x00 *ucb)
+{
+ mcp_disable(ucb->mcp);
+}
+
+/**
+ * ucb1x00_reg_write - write a UCB1x00 register
+ * @ucb: UCB1x00 structure describing chip
+ * @reg: UCB1x00 4-bit register index to write
+ * @val: UCB1x00 16-bit value to write
+ *
+ * Write the UCB1x00 register @reg with value @val. The SIB
+ * clock must be running for this function to return.
+ */
+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
+{
+ mcp_reg_write(ucb->mcp, reg, val);
+}
+
+/**
+ * ucb1x00_reg_read - read a UCB1x00 register
+ * @ucb: UCB1x00 structure describing chip
+ * @reg: UCB1x00 4-bit register index to write
+ *
+ * Read the UCB1x00 register @reg and return its value. The SIB
+ * clock must be running for this function to return.
+ */
+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
+{
+ return mcp_reg_read(ucb->mcp, reg);
+}
+/**
+ * ucb1x00_set_audio_divisor -
+ * @ucb: UCB1x00 structure describing chip
+ * @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+ mcp_set_audio_divisor(ucb->mcp, div);
+}
+
+/**
+ * ucb1x00_set_telecom_divisor -
+ * @ucb: UCB1x00 structure describing chip
+ * @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+ mcp_set_telecom_divisor(ucb->mcp, div);
+}
+
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
+
+#define UCB_NOSYNC (0)
+#define UCB_SYNC (1)
+
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
+void ucb1x00_adc_enable(struct ucb1x00 *ucb);
+void ucb1x00_adc_disable(struct ucb1x00 *ucb);
+
+/*
+ * Which edges of the IRQ do you want to control today?
+ */
+#define UCB_RISING (1 << 0)
+#define UCB_FALLING (1 << 1)
+
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
+
+#endif
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 7501fab349e4..9c4dd682ac74 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -21,7 +21,7 @@
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <linux/hdpu_features.h>
@@ -192,22 +192,37 @@ static int hdpu_cpustate_probe(struct device *ddev)
{
struct platform_device *pdev = to_platform_device(ddev);
struct resource *res;
+ struct proc_dir_entry *proc_de;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cpustate.set_addr = (unsigned long *)res->start;
cpustate.clr_addr = (unsigned long *)res->end - 1;
- misc_register(&cpustate_dev);
- create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc, NULL);
+ ret = misc_register(&cpustate_dev);
+ if (ret) {
+ printk(KERN_WARNING "sky_cpustate: Unable to register misc "
+ "device.\n");
+ cpustate.set_addr = NULL;
+ cpustate.clr_addr = NULL;
+ return ret;
+ }
+
+ proc_de = create_proc_read_entry("sky_cpustate", 0, 0,
+ cpustate_read_proc, NULL);
+ if (proc_de == NULL)
+ printk(KERN_WARNING "sky_cpustate: Unable to create proc "
+ "dir entry\n");
printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
return 0;
}
+
static int hdpu_cpustate_remove(struct device *ddev)
{
- cpustate.set_addr = 0;
- cpustate.clr_addr = 0;
+ cpustate.set_addr = NULL;
+ cpustate.clr_addr = NULL;
remove_proc_entry("sky_cpustate", NULL);
misc_deregister(&cpustate_dev);
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index c203b27269ea..165f3405df27 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -21,7 +21,7 @@
#include <linux/hdpu_features.h>
#include <linux/pci.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
static int hdpu_nexus_probe(struct device *ddev);
static int hdpu_nexus_remove(struct device *ddev);
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 914804512dba..7e98434cfa37 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -25,15 +25,15 @@
#include <linux/termios.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
-#include <linux/serial.h>
#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
#include "ibmasm.h"
#include "lowlevel.h"
void ibmasm_register_uart(struct service_processor *sp)
{
- struct serial_struct serial;
+ struct uart_port uport;
void __iomem *iomem_base;
iomem_base = sp->base_address + SCOUT_COM_B_BASE;
@@ -47,14 +47,14 @@ void ibmasm_register_uart(struct service_processor *sp)
return;
}
- memset(&serial, 0, sizeof(serial));
- serial.irq = sp->irq;
- serial.baud_base = 3686400 / 16;
- serial.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
- serial.io_type = UPIO_MEM;
- serial.iomem_base = iomem_base;
+ memset(&uport, 0, sizeof(struct uart_port));
+ uport.irq = sp->irq;
+ uport.uartclk = 3686400;
+ uport.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
+ uport.iotype = UPIO_MEM;
+ uport.membase = iomem_base;
- sp->serial_line = register_serial(&serial);
+ sp->serial_line = serial8250_register_port(&uport);
if (sp->serial_line < 0) {
dev_err(sp->dev, "Failed to register serial port\n");
return;
@@ -68,5 +68,5 @@ void ibmasm_unregister_uart(struct service_processor *sp)
return;
disable_uart_interrupts(sp->base_address);
- unregister_serial(sp->serial_line);
+ serial8250_unregister_port(sp->serial_line);
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4991bbd054f3..c483a863b116 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -60,4 +60,13 @@ config MMC_WBSD
If unsure, say N.
+config MMC_AU1X
+ tristate "Alchemy AU1XX0 MMC Card Interface support"
+ depends on SOC_AU1X00 && MMC
+ help
+ This selects the AMD Alchemy(R) Multimedia card interface.
+ iIf you have a Alchemy platform with a MMC slot, say Y or M here.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 89510c2086c7..e351e71146e9 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -18,5 +18,6 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
obj-$(CONFIG_MMC_PXA) += pxamci.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
+obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
new file mode 100644
index 000000000000..aaf04638054e
--- /dev/null
+++ b/drivers/mmc/au1xmmc.c
@@ -0,0 +1,1026 @@
+/*
+ * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver
+ *
+ * Copyright (c) 2005, Advanced Micro Devices, Inc.
+ *
+ * Developed with help from the 2.4.30 MMC AU1XXX controller including
+ * the following copyright notices:
+ * Copyright (c) 2003-2004 Embedded Edge, LLC.
+ * Portions Copyright (C) 2002 Embedix, Inc
+ * Copyright 2002 Hewlett-Packard Company
+
+ * 2.6 version of this driver inspired by:
+ * (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman,
+ * All Rights Reserved.
+ * (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King,
+ * 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.
+ */
+
+/* Why is a timer used to detect insert events?
+ *
+ * From the AU1100 MMC application guide:
+ * If the Au1100-based design is intended to support both MultiMediaCards
+ * and 1- or 4-data bit SecureDigital cards, then the solution is to
+ * connect a weak (560KOhm) pull-up resistor to connector pin 1.
+ * In doing so, a MMC card never enters SPI-mode communications,
+ * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective
+ * (the low to high transition will not occur).
+ *
+ * So we use the timer to check the status manually.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/scatterlist.h>
+
+#include <au1xxx.h>
+#include "au1xmmc.h"
+
+#define DRIVER_NAME "au1xxx-mmc"
+
+/* Set this to enable special debugging macros */
+/* #define MMC_DEBUG */
+
+#ifdef MMC_DEBUG
+#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#else
+#define DEBUG(fmt, idx, args...)
+#endif
+
+const struct {
+ u32 iobase;
+ u32 tx_devid, rx_devid;
+ u16 bcsrpwr;
+ u16 bcsrstatus;
+ u16 wpstatus;
+} au1xmmc_card_table[] = {
+ { SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
+ BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
+#ifndef CONFIG_MIPS_DB1200
+ { SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
+ BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
+#endif
+};
+
+#define AU1XMMC_CONTROLLER_COUNT \
+ (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+
+/* This array stores pointers for the hosts (used by the IRQ handler) */
+struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
+static int dma = 1;
+
+#ifdef MODULE
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
+#endif
+
+static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
+{
+ u32 val = au_readl(HOST_CONFIG(host));
+ val |= mask;
+ au_writel(val, HOST_CONFIG(host));
+ au_sync();
+}
+
+static inline void FLUSH_FIFO(struct au1xmmc_host *host)
+{
+ u32 val = au_readl(HOST_CONFIG2(host));
+
+ au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+ au_sync_delay(1);
+
+ /* SEND_STOP will turn off clock control - this re-enables it */
+ val &= ~SD_CONFIG2_DF;
+
+ au_writel(val, HOST_CONFIG2(host));
+ au_sync();
+}
+
+static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
+{
+ u32 val = au_readl(HOST_CONFIG(host));
+ val &= ~mask;
+ au_writel(val, HOST_CONFIG(host));
+ au_sync();
+}
+
+static inline void SEND_STOP(struct au1xmmc_host *host)
+{
+
+ /* We know the value of CONFIG2, so avoid a read we don't need */
+ u32 mask = SD_CONFIG2_EN;
+
+ WARN_ON(host->status != HOST_S_DATA);
+ host->status = HOST_S_STOP;
+
+ au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host));
+ au_sync();
+
+ /* Send the stop commmand */
+ au_writel(STOP_CMD, HOST_CMD(host));
+}
+
+static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
+{
+
+ u32 val = au1xmmc_card_table[host->id].bcsrpwr;
+
+ bcsr->board &= ~val;
+ if (state) bcsr->board |= val;
+
+ au_sync_delay(1);
+}
+
+static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+{
+ return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
+ ? 1 : 0;
+}
+
+static inline int au1xmmc_card_readonly(struct au1xmmc_host *host)
+{
+ return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
+ ? 1 : 0;
+}
+
+static void au1xmmc_finish_request(struct au1xmmc_host *host)
+{
+
+ struct mmc_request *mrq = host->mrq;
+
+ host->mrq = NULL;
+ host->flags &= HOST_F_ACTIVE;
+
+ host->dma.len = 0;
+ host->dma.dir = 0;
+
+ host->pio.index = 0;
+ host->pio.offset = 0;
+ host->pio.len = 0;
+
+ host->status = HOST_S_IDLE;
+
+ bcsr->disk_leds |= (1 << 8);
+
+ mmc_request_done(host->mmc, mrq);
+}
+
+static void au1xmmc_tasklet_finish(unsigned long param)
+{
+ struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+ au1xmmc_finish_request(host);
+}
+
+static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
+ struct mmc_command *cmd)
+{
+
+ u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
+
+ switch(cmd->flags) {
+ case MMC_RSP_R1:
+ mmccmd |= SD_CMD_RT_1;
+ break;
+ case MMC_RSP_R1B:
+ mmccmd |= SD_CMD_RT_1B;
+ break;
+ case MMC_RSP_R2:
+ mmccmd |= SD_CMD_RT_2;
+ break;
+ case MMC_RSP_R3:
+ mmccmd |= SD_CMD_RT_3;
+ break;
+ }
+
+ switch(cmd->opcode) {
+ case MMC_READ_SINGLE_BLOCK:
+ case SD_APP_SEND_SCR:
+ mmccmd |= SD_CMD_CT_2;
+ break;
+ case MMC_READ_MULTIPLE_BLOCK:
+ mmccmd |= SD_CMD_CT_4;
+ break;
+ case MMC_WRITE_BLOCK:
+ mmccmd |= SD_CMD_CT_1;
+ break;
+
+ case MMC_WRITE_MULTIPLE_BLOCK:
+ mmccmd |= SD_CMD_CT_3;
+ break;
+ case MMC_STOP_TRANSMISSION:
+ mmccmd |= SD_CMD_CT_7;
+ break;
+ }
+
+ au_writel(cmd->arg, HOST_CMDARG(host));
+ au_sync();
+
+ if (wait)
+ IRQ_OFF(host, SD_CONFIG_CR);
+
+ au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+ au_sync();
+
+ /* Wait for the command to go on the line */
+
+ while(1) {
+ if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO))
+ break;
+ }
+
+ /* Wait for the command to come back */
+
+ if (wait) {
+ u32 status = au_readl(HOST_STATUS(host));
+
+ while(!(status & SD_STATUS_CR))
+ status = au_readl(HOST_STATUS(host));
+
+ /* Clear the CR status */
+ au_writel(SD_STATUS_CR, HOST_STATUS(host));
+
+ IRQ_ON(host, SD_CONFIG_CR);
+ }
+
+ return MMC_ERR_NONE;
+}
+
+static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
+{
+
+ struct mmc_request *mrq = host->mrq;
+ struct mmc_data *data;
+ u32 crc;
+
+ WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP);
+
+ if (host->mrq == NULL)
+ return;
+
+ data = mrq->cmd->data;
+
+ if (status == 0)
+ status = au_readl(HOST_STATUS(host));
+
+ /* The transaction is really over when the SD_STATUS_DB bit is clear */
+
+ while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
+ status = au_readl(HOST_STATUS(host));
+
+ data->error = MMC_ERR_NONE;
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
+
+ /* Process any errors */
+
+ crc = (status & (SD_STATUS_WC | SD_STATUS_RC));
+ if (host->flags & HOST_F_XMIT)
+ crc |= ((status & 0x07) == 0x02) ? 0 : 1;
+
+ if (crc)
+ data->error = MMC_ERR_BADCRC;
+
+ /* Clear the CRC bits */
+ au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+
+ data->bytes_xfered = 0;
+
+ if (data->error == MMC_ERR_NONE) {
+ if (host->flags & HOST_F_DMA) {
+ u32 chan = DMA_CHANNEL(host);
+
+ chan_tab_t *c = *((chan_tab_t **) chan);
+ au1x_dma_chan_t *cp = c->chan_ptr;
+ data->bytes_xfered = cp->ddma_bytecnt;
+ }
+ else
+ data->bytes_xfered =
+ (data->blocks * (1 << data->blksz_bits)) -
+ host->pio.len;
+ }
+
+ au1xmmc_finish_request(host);
+}
+
+static void au1xmmc_tasklet_data(unsigned long param)
+{
+ struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+
+ u32 status = au_readl(HOST_STATUS(host));
+ au1xmmc_data_complete(host, status);
+}
+
+#define AU1XMMC_MAX_TRANSFER 8
+
+static void au1xmmc_send_pio(struct au1xmmc_host *host)
+{
+
+ struct mmc_data *data = 0;
+ int sg_len, max, count = 0;
+ unsigned char *sg_ptr;
+ u32 status = 0;
+ struct scatterlist *sg;
+
+ data = host->mrq->data;
+
+ if (!(host->flags & HOST_F_XMIT))
+ return;
+
+ /* This is the pointer to the data buffer */
+ sg = &data->sg[host->pio.index];
+ sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+ /* This is the space left inside the buffer */
+ sg_len = data->sg[host->pio.index].length - host->pio.offset;
+
+ /* Check to if we need less then the size of the sg_buffer */
+
+ max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
+ if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER;
+
+ for(count = 0; count < max; count++ ) {
+ unsigned char val;
+
+ status = au_readl(HOST_STATUS(host));
+
+ if (!(status & SD_STATUS_TH))
+ break;
+
+ val = *sg_ptr++;
+
+ au_writel((unsigned long) val, HOST_TXPORT(host));
+ au_sync();
+ }
+
+ host->pio.len -= count;
+ host->pio.offset += count;
+
+ if (count == sg_len) {
+ host->pio.index++;
+ host->pio.offset = 0;
+ }
+
+ if (host->pio.len == 0) {
+ IRQ_OFF(host, SD_CONFIG_TH);
+
+ if (host->flags & HOST_F_STOP)
+ SEND_STOP(host);
+
+ tasklet_schedule(&host->data_task);
+ }
+}
+
+static void au1xmmc_receive_pio(struct au1xmmc_host *host)
+{
+
+ struct mmc_data *data = 0;
+ int sg_len = 0, max = 0, count = 0;
+ unsigned char *sg_ptr = 0;
+ u32 status = 0;
+ struct scatterlist *sg;
+
+ data = host->mrq->data;
+
+ if (!(host->flags & HOST_F_RECV))
+ return;
+
+ max = host->pio.len;
+
+ if (host->pio.index < host->dma.len) {
+ sg = &data->sg[host->pio.index];
+ sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+ /* This is the space left inside the buffer */
+ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
+
+ /* Check to if we need less then the size of the sg_buffer */
+ if (sg_len < max) max = sg_len;
+ }
+
+ if (max > AU1XMMC_MAX_TRANSFER)
+ max = AU1XMMC_MAX_TRANSFER;
+
+ for(count = 0; count < max; count++ ) {
+ u32 val;
+ status = au_readl(HOST_STATUS(host));
+
+ if (!(status & SD_STATUS_NE))
+ break;
+
+ if (status & SD_STATUS_RC) {
+ DEBUG("RX CRC Error [%d + %d].\n", host->id,
+ host->pio.len, count);
+ break;
+ }
+
+ if (status & SD_STATUS_RO) {
+ DEBUG("RX Overrun [%d + %d]\n", host->id,
+ host->pio.len, count);
+ break;
+ }
+ else if (status & SD_STATUS_RU) {
+ DEBUG("RX Underrun [%d + %d]\n", host->id,
+ host->pio.len, count);
+ break;
+ }
+
+ val = au_readl(HOST_RXPORT(host));
+
+ if (sg_ptr)
+ *sg_ptr++ = (unsigned char) (val & 0xFF);
+ }
+
+ host->pio.len -= count;
+ host->pio.offset += count;
+
+ if (sg_len && count == sg_len) {
+ host->pio.index++;
+ host->pio.offset = 0;
+ }
+
+ if (host->pio.len == 0) {
+ //IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);
+ IRQ_OFF(host, SD_CONFIG_NE);
+
+ if (host->flags & HOST_F_STOP)
+ SEND_STOP(host);
+
+ tasklet_schedule(&host->data_task);
+ }
+}
+
+/* static void au1xmmc_cmd_complete
+ This is called when a command has been completed - grab the response
+ and check for errors. Then start the data transfer if it is indicated.
+*/
+
+static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
+{
+
+ struct mmc_request *mrq = host->mrq;
+ struct mmc_command *cmd;
+ int trans;
+
+ if (!host->mrq)
+ return;
+
+ cmd = mrq->cmd;
+ cmd->error = MMC_ERR_NONE;
+
+ if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {
+
+ /* Techincally, we should be getting all 48 bits of the response
+ * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,
+ * our data ends up being shifted 8 bits to the right. In this case,
+ * that means that the OSR data starts at bit 31, so we can just
+ * read RESP0 and return that
+ */
+
+ cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+ }
+ else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
+ u32 r[4];
+ int i;
+
+ r[0] = au_readl(host->iobase + SD_RESP3);
+ r[1] = au_readl(host->iobase + SD_RESP2);
+ r[2] = au_readl(host->iobase + SD_RESP1);
+ r[3] = au_readl(host->iobase + SD_RESP0);
+
+ /* The CRC is omitted from the response, so really we only got
+ * 120 bytes, but the engine expects 128 bits, so we have to shift
+ * things up
+ */
+
+ for(i = 0; i < 4; i++) {
+ cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+ if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+ }
+ }
+
+ /* Figure out errors */
+
+ if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))
+ cmd->error = MMC_ERR_BADCRC;
+
+ trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);
+
+ if (!trans || cmd->error != MMC_ERR_NONE) {
+
+ IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);
+ tasklet_schedule(&host->finish_task);
+ return;
+ }
+
+ host->status = HOST_S_DATA;
+
+ if (host->flags & HOST_F_DMA) {
+ u32 channel = DMA_CHANNEL(host);
+
+ /* Start the DMA as soon as the buffer gets something in it */
+
+ if (host->flags & HOST_F_RECV) {
+ u32 mask = SD_STATUS_DB | SD_STATUS_NE;
+
+ while((status & mask) != mask)
+ status = au_readl(HOST_STATUS(host));
+ }
+
+ au1xxx_dbdma_start(channel);
+ }
+}
+
+static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
+{
+
+ unsigned int pbus = get_au1x00_speed();
+ unsigned int divisor;
+ u32 config;
+
+ /* From databook:
+ divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
+ */
+
+ pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
+ pbus /= 2;
+
+ divisor = ((pbus / rate) / 2) - 1;
+
+ config = au_readl(HOST_CONFIG(host));
+
+ config &= ~(SD_CONFIG_DIV);
+ config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
+
+ au_writel(config, HOST_CONFIG(host));
+ au_sync();
+}
+
+static int
+au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
+{
+
+ int datalen = data->blocks * (1 << data->blksz_bits);
+
+ if (dma != 0)
+ host->flags |= HOST_F_DMA;
+
+ if (data->flags & MMC_DATA_READ)
+ host->flags |= HOST_F_RECV;
+ else
+ host->flags |= HOST_F_XMIT;
+
+ if (host->mrq->stop)
+ host->flags |= HOST_F_STOP;
+
+ host->dma.dir = DMA_BIDIRECTIONAL;
+
+ host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma.dir);
+
+ if (host->dma.len == 0)
+ return MMC_ERR_TIMEOUT;
+
+ au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
+
+ if (host->flags & HOST_F_DMA) {
+ int i;
+ u32 channel = DMA_CHANNEL(host);
+
+ au1xxx_dbdma_stop(channel);
+
+ for(i = 0; i < host->dma.len; i++) {
+ u32 ret = 0, flags = DDMA_FLAGS_NOIE;
+ struct scatterlist *sg = &data->sg[i];
+ int sg_len = sg->length;
+
+ int len = (datalen > sg_len) ? sg_len : datalen;
+
+ if (i == host->dma.len - 1)
+ flags = DDMA_FLAGS_IE;
+
+ if (host->flags & HOST_F_XMIT){
+ ret = au1xxx_dbdma_put_source_flags(channel,
+ (void *) (page_address(sg->page) +
+ sg->offset),
+ len, flags);
+ }
+ else {
+ ret = au1xxx_dbdma_put_dest_flags(channel,
+ (void *) (page_address(sg->page) +
+ sg->offset),
+ len, flags);
+ }
+
+ if (!ret)
+ goto dataerr;
+
+ datalen -= len;
+ }
+ }
+ else {
+ host->pio.index = 0;
+ host->pio.offset = 0;
+ host->pio.len = datalen;
+
+ if (host->flags & HOST_F_XMIT)
+ IRQ_ON(host, SD_CONFIG_TH);
+ else
+ IRQ_ON(host, SD_CONFIG_NE);
+ //IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);
+ }
+
+ return MMC_ERR_NONE;
+
+ dataerr:
+ dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
+ return MMC_ERR_TIMEOUT;
+}
+
+/* static void au1xmmc_request
+ This actually starts a command or data transaction
+*/
+
+static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
+{
+
+ struct au1xmmc_host *host = mmc_priv(mmc);
+ int ret = MMC_ERR_NONE;
+
+ WARN_ON(irqs_disabled());
+ WARN_ON(host->status != HOST_S_IDLE);
+
+ host->mrq = mrq;
+ host->status = HOST_S_CMD;
+
+ bcsr->disk_leds &= ~(1 << 8);
+
+ if (mrq->data) {
+ FLUSH_FIFO(host);
+ ret = au1xmmc_prepare_data(host, mrq->data);
+ }
+
+ if (ret == MMC_ERR_NONE)
+ ret = au1xmmc_send_command(host, 0, mrq->cmd);
+
+ if (ret != MMC_ERR_NONE) {
+ mrq->cmd->error = ret;
+ au1xmmc_finish_request(host);
+ }
+}
+
+static void au1xmmc_reset_controller(struct au1xmmc_host *host)
+{
+
+ /* Apply the clock */
+ au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+ au_sync_delay(1);
+
+ au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+ au_sync_delay(5);
+
+ au_writel(~0, HOST_STATUS(host));
+ au_sync();
+
+ au_writel(0, HOST_BLKSIZE(host));
+ au_writel(0x001fffff, HOST_TIMEOUT(host));
+ au_sync();
+
+ au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+ au_sync();
+
+ au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+ au_sync_delay(1);
+
+ au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+ au_sync();
+
+ /* Configure interrupts */
+ au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+ au_sync();
+}
+
+
+static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+{
+ struct au1xmmc_host *host = mmc_priv(mmc);
+
+ DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
+ host->id, ios->power_mode, ios->clock, ios->vdd,
+ ios->bus_mode);
+
+ if (ios->power_mode == MMC_POWER_OFF)
+ au1xmmc_set_power(host, 0);
+ else if (ios->power_mode == MMC_POWER_ON) {
+ au1xmmc_set_power(host, 1);
+ }
+
+ if (ios->clock && ios->clock != host->clock) {
+ au1xmmc_set_clock(host, ios->clock);
+ host->clock = ios->clock;
+ }
+}
+
+static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
+ u32 status;
+
+ /* Avoid spurious interrupts */
+
+ if (!host->mrq)
+ return;
+
+ if (host->flags & HOST_F_STOP)
+ SEND_STOP(host);
+
+ tasklet_schedule(&host->data_task);
+}
+
+#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
+#define STATUS_DATA_IN (SD_STATUS_NE)
+#define STATUS_DATA_OUT (SD_STATUS_TH)
+
+static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ u32 status;
+ int i, ret = 0;
+
+ disable_irq(AU1100_SD_IRQ);
+
+ for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+ struct au1xmmc_host * host = au1xmmc_hosts[i];
+ u32 handled = 1;
+
+ status = au_readl(HOST_STATUS(host));
+
+ if (host->mrq && (status & STATUS_TIMEOUT)) {
+ if (status & SD_STATUS_RAT)
+ host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+
+ else if (status & SD_STATUS_DT)
+ host->mrq->data->error = MMC_ERR_TIMEOUT;
+
+ /* In PIO mode, interrupts might still be enabled */
+ IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
+
+ //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
+ tasklet_schedule(&host->finish_task);
+ }
+#if 0
+ else if (status & SD_STATUS_DD) {
+
+ /* Sometimes we get a DD before a NE in PIO mode */
+
+ if (!(host->flags & HOST_F_DMA) &&
+ (status & SD_STATUS_NE))
+ au1xmmc_receive_pio(host);
+ else {
+ au1xmmc_data_complete(host, status);
+ //tasklet_schedule(&host->data_task);
+ }
+ }
+#endif
+ else if (status & (SD_STATUS_CR)) {
+ if (host->status == HOST_S_CMD)
+ au1xmmc_cmd_complete(host,status);
+ }
+ else if (!(host->flags & HOST_F_DMA)) {
+ if ((host->flags & HOST_F_XMIT) &&
+ (status & STATUS_DATA_OUT))
+ au1xmmc_send_pio(host);
+ else if ((host->flags & HOST_F_RECV) &&
+ (status & STATUS_DATA_IN))
+ au1xmmc_receive_pio(host);
+ }
+ else if (status & 0x203FBC70) {
+ DEBUG("Unhandled status %8.8x\n", host->id, status);
+ handled = 0;
+ }
+
+ au_writel(status, HOST_STATUS(host));
+ au_sync();
+
+ ret |= handled;
+ }
+
+ enable_irq(AU1100_SD_IRQ);
+ return ret;
+}
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+ struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+
+ int card = au1xmmc_card_inserted(host);
+ int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+
+ if (card != controller) {
+ host->flags &= ~HOST_F_ACTIVE;
+ if (card) host->flags |= HOST_F_ACTIVE;
+ mmc_detect_change(host->mmc, 0);
+ }
+
+ if (host->mrq != NULL) {
+ u32 status = au_readl(HOST_STATUS(host));
+ DEBUG("PENDING - %8.8x\n", host->id, status);
+ }
+
+ mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
+}
+
+static dbdev_tab_t au1xmmc_mem_dbdev =
+{
+ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
+};
+
+static void au1xmmc_init_dma(struct au1xmmc_host *host)
+{
+
+ u32 rxchan, txchan;
+
+ int txid = au1xmmc_card_table[host->id].tx_devid;
+ int rxid = au1xmmc_card_table[host->id].rx_devid;
+
+ /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+ of 8 bits. And since devices are shared, we need to create
+ our own to avoid freaking out other devices
+ */
+
+ int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+
+ txchan = au1xxx_dbdma_chan_alloc(memid, txid,
+ au1xmmc_dma_callback, (void *) host);
+
+ rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
+ au1xmmc_dma_callback, (void *) host);
+
+ au1xxx_dbdma_set_devwidth(txchan, 8);
+ au1xxx_dbdma_set_devwidth(rxchan, 8);
+
+ au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
+ au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
+
+ host->tx_chan = txchan;
+ host->rx_chan = rxchan;
+}
+
+struct mmc_host_ops au1xmmc_ops = {
+ .request = au1xmmc_request,
+ .set_ios = au1xmmc_set_ios,
+};
+
+static int au1xmmc_probe(struct device *dev)
+{
+
+ int i, ret = 0;
+
+ /* THe interrupt is shared among all controllers */
+ ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, SA_INTERRUPT, "MMC", 0);
+
+ if (ret) {
+ printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
+ AU1100_SD_IRQ, ret);
+ return -ENXIO;
+ }
+
+ disable_irq(AU1100_SD_IRQ);
+
+ for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+ struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev);
+ struct au1xmmc_host *host = 0;
+
+ if (!mmc) {
+ printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
+ au1xmmc_hosts[i] = 0;
+ continue;
+ }
+
+ mmc->ops = &au1xmmc_ops;
+
+ mmc->f_min = 450000;
+ mmc->f_max = 24000000;
+
+ mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+ mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+
+ mmc->ocr_avail = AU1XMMC_OCR;
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+
+ host->id = i;
+ host->iobase = au1xmmc_card_table[host->id].iobase;
+ host->clock = 0;
+ host->power_mode = MMC_POWER_OFF;
+
+ host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
+ host->status = HOST_S_IDLE;
+
+ init_timer(&host->timer);
+
+ host->timer.function = au1xmmc_poll_event;
+ host->timer.data = (unsigned long) host;
+ host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+
+ tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+ (unsigned long) host);
+
+ tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+ (unsigned long) host);
+
+ spin_lock_init(&host->lock);
+
+ if (dma != 0)
+ au1xmmc_init_dma(host);
+
+ au1xmmc_reset_controller(host);
+
+ mmc_add_host(mmc);
+ au1xmmc_hosts[i] = host;
+
+ add_timer(&host->timer);
+
+ printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
+ host->id, host->iobase, dma ? "dma" : "pio");
+ }
+
+ enable_irq(AU1100_SD_IRQ);
+
+ return 0;
+}
+
+static int au1xmmc_remove(struct device *dev)
+{
+
+ int i;
+
+ disable_irq(AU1100_SD_IRQ);
+
+ for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+ struct au1xmmc_host *host = au1xmmc_hosts[i];
+ if (!host) continue;
+
+ tasklet_kill(&host->data_task);
+ tasklet_kill(&host->finish_task);
+
+ del_timer_sync(&host->timer);
+ au1xmmc_set_power(host, 0);
+
+ mmc_remove_host(host->mmc);
+
+ au1xxx_dbdma_chan_free(host->tx_chan);
+ au1xxx_dbdma_chan_free(host->rx_chan);
+
+ au_writel(0x0, HOST_ENABLE(host));
+ au_sync();
+ }
+
+ free_irq(AU1100_SD_IRQ, 0);
+ return 0;
+}
+
+static struct device_driver au1xmmc_driver = {
+ .name = DRIVER_NAME,
+ .bus = &platform_bus_type,
+ .probe = au1xmmc_probe,
+ .remove = au1xmmc_remove,
+ .suspend = NULL,
+ .resume = NULL
+};
+
+static int __init au1xmmc_init(void)
+{
+ return driver_register(&au1xmmc_driver);
+}
+
+static void __exit au1xmmc_exit(void)
+{
+ driver_unregister(&au1xmmc_driver);
+}
+
+module_init(au1xmmc_init);
+module_exit(au1xmmc_exit);
+
+#ifdef MODULE
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
+MODULE_LICENSE("GPL");
+#endif
+
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/au1xmmc.h
new file mode 100644
index 000000000000..341cbdf0baca
--- /dev/null
+++ b/drivers/mmc/au1xmmc.h
@@ -0,0 +1,96 @@
+#ifndef _AU1XMMC_H_
+#define _AU1XMMC_H_
+
+/* Hardware definitions */
+
+#define AU1XMMC_DESCRIPTOR_COUNT 1
+#define AU1XMMC_DESCRIPTOR_SIZE 2048
+
+#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \
+ MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \
+ MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
+
+/* Easy access macros */
+
+#define HOST_STATUS(h) ((h)->iobase + SD_STATUS)
+#define HOST_CONFIG(h) ((h)->iobase + SD_CONFIG)
+#define HOST_ENABLE(h) ((h)->iobase + SD_ENABLE)
+#define HOST_TXPORT(h) ((h)->iobase + SD_TXPORT)
+#define HOST_RXPORT(h) ((h)->iobase + SD_RXPORT)
+#define HOST_CMDARG(h) ((h)->iobase + SD_CMDARG)
+#define HOST_BLKSIZE(h) ((h)->iobase + SD_BLKSIZE)
+#define HOST_CMD(h) ((h)->iobase + SD_CMD)
+#define HOST_CONFIG2(h) ((h)->iobase + SD_CONFIG2)
+#define HOST_TIMEOUT(h) ((h)->iobase + SD_TIMEOUT)
+#define HOST_DEBUG(h) ((h)->iobase + SD_DEBUG)
+
+#define DMA_CHANNEL(h) \
+ ( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
+
+/* This gives us a hard value for the stop command that we can write directly
+ * to the command register
+ */
+
+#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)
+
+/* This is the set of interrupts that we configure by default */
+
+#if 0
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \
+ SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+#endif
+
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \
+ SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+/* The poll event (looking for insert/remove events runs twice a second */
+#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
+
+struct au1xmmc_host {
+ struct mmc_host *mmc;
+ struct mmc_request *mrq;
+
+ u32 id;
+
+ u32 flags;
+ u32 iobase;
+ u32 clock;
+ u32 bus_width;
+ u32 power_mode;
+
+ int status;
+
+ struct {
+ int len;
+ int dir;
+ } dma;
+
+ struct {
+ int index;
+ int offset;
+ int len;
+ } pio;
+
+ u32 tx_chan;
+ u32 rx_chan;
+
+ struct timer_list timer;
+ struct tasklet_struct finish_task;
+ struct tasklet_struct data_task;
+
+ spinlock_t lock;
+};
+
+/* Status flags used by the host structure */
+
+#define HOST_F_XMIT 0x0001
+#define HOST_F_RECV 0x0002
+#define HOST_F_DMA 0x0010
+#define HOST_F_ACTIVE 0x0100
+#define HOST_F_STOP 0x1000
+
+#define HOST_S_IDLE 0x0001
+#define HOST_S_CMD 0x0002
+#define HOST_S_DATA 0x0003
+#define HOST_S_STOP 0x0004
+
+#endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index eeb9f6668e69..ceae379a4d4c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2,6 +2,8 @@
* linux/drivers/mmc/mmc.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ * SD support Copyright (C) 2005 Pierre Ossman, 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
@@ -16,6 +18,8 @@
#include <linux/delay.h>
#include <linux/pagemap.h>
#include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -172,7 +176,81 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
EXPORT_SYMBOL(mmc_wait_for_cmd);
+/**
+ * mmc_wait_for_app_cmd - start an application command and wait for
+ completion
+ * @host: MMC host to start command
+ * @rca: RCA to send MMC_APP_CMD to
+ * @cmd: MMC command to start
+ * @retries: maximum number of retries
+ *
+ * Sends a MMC_APP_CMD, checks the card response, sends the command
+ * in the parameter and waits for it to complete. Return any error
+ * that occurred while the command was executing. Do not attempt to
+ * parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+ struct mmc_command *cmd, int retries)
+{
+ struct mmc_request mrq;
+ struct mmc_command appcmd;
+
+ int i, err;
+
+ BUG_ON(host->card_busy == NULL);
+ BUG_ON(retries < 0);
+
+ err = MMC_ERR_INVALID;
+
+ /*
+ * We have to resend MMC_APP_CMD for each attempt so
+ * we cannot use the retries field in mmc_command.
+ */
+ for (i = 0;i <= retries;i++) {
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ appcmd.opcode = MMC_APP_CMD;
+ appcmd.arg = rca << 16;
+ appcmd.flags = MMC_RSP_R1;
+ appcmd.retries = 0;
+ memset(appcmd.resp, 0, sizeof(appcmd.resp));
+ appcmd.data = NULL;
+
+ mrq.cmd = &appcmd;
+ appcmd.data = NULL;
+
+ mmc_wait_for_req(host, &mrq);
+
+ if (appcmd.error) {
+ err = appcmd.error;
+ continue;
+ }
+
+ /* Check that card supported application commands */
+ if (!(appcmd.resp[0] & R1_APP_CMD))
+ return MMC_ERR_FAILED;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ memset(cmd->resp, 0, sizeof(cmd->resp));
+ cmd->retries = 0;
+
+ mrq.cmd = cmd;
+ cmd->data = NULL;
+
+ mmc_wait_for_req(host, &mrq);
+
+ err = cmd->error;
+ if (cmd->error == MMC_ERR_NONE)
+ break;
+ }
+ return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
/**
* __mmc_claim_host - exclusively claim a host
@@ -206,16 +284,10 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);
- if (card != (void *)-1 && host->card_selected != card) {
- struct mmc_command cmd;
-
- host->card_selected = card;
-
- cmd.opcode = MMC_SELECT_CARD;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
-
- err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (card != (void *)-1) {
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE)
+ return err;
}
return err;
@@ -245,6 +317,63 @@ void mmc_release_host(struct mmc_host *host)
EXPORT_SYMBOL(mmc_release_host);
+static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+ struct mmc_command cmd;
+
+ BUG_ON(host->card_busy == NULL);
+
+ if (host->card_selected == card)
+ return MMC_ERR_NONE;
+
+ host->card_selected = card;
+
+ cmd.opcode = MMC_SELECT_CARD;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ /*
+ * Default bus width is 1 bit.
+ */
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+ /*
+ * We can only change the bus width of the selected
+ * card so therefore we have to put the handling
+ * here.
+ */
+ if (host->caps & MMC_CAP_4_BIT_DATA) {
+ /*
+ * The card is in 1 bit mode by default so
+ * we only need to change if it supports the
+ * wider version.
+ */
+ if (mmc_card_sd(card) &&
+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ struct mmc_command cmd;
+ cmd.opcode = SD_APP_SET_BUS_WIDTH;
+ cmd.arg = SD_BUS_WIDTH_4;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
+ CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ return err;
+
+ host->ios.bus_width = MMC_BUS_WIDTH_4;
+ }
+ }
+
+ host->ops->set_ios(host, &host->ios);
+
+ return MMC_ERR_NONE;
+}
+
/*
* Ensure that no card is selected.
*/
@@ -322,48 +451,69 @@ static void mmc_decode_cid(struct mmc_card *card)
memset(&card->cid, 0, sizeof(struct mmc_cid));
- /*
- * The selection of the format here is guesswork based upon
- * information people have sent to date.
- */
- switch (card->csd.mmca_vsn) {
- case 0: /* MMC v1.? */
- case 1: /* MMC v1.4 */
- card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
- card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
- card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
- card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
- card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
- card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
- card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
- card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
- card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
- card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
- card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
- card->cid.month = UNSTUFF_BITS(resp, 12, 4);
- card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
- break;
-
- case 2: /* MMC v2.x ? */
- case 3: /* MMC v3.x ? */
- card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
- card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
- card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
- card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
- card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
- card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
- card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
- card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
- card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
- card->cid.month = UNSTUFF_BITS(resp, 12, 4);
- card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
- break;
-
- default:
- printk("%s: card has unknown MMCA version %d\n",
- card->host->host_name, card->csd.mmca_vsn);
- mmc_card_set_bad(card);
- break;
+ if (mmc_card_sd(card)) {
+ /*
+ * SD doesn't currently have a version field so we will
+ * have to assume we can parse this.
+ */
+ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
+ card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4);
+ card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4);
+ card->cid.serial = UNSTUFF_BITS(resp, 24, 32);
+ card->cid.year = UNSTUFF_BITS(resp, 12, 8);
+ card->cid.month = UNSTUFF_BITS(resp, 8, 4);
+
+ card->cid.year += 2000; /* SD cards year offset */
+ } else {
+ /*
+ * The selection of the format here is based upon published
+ * specs from sandisk and from what people have reported.
+ */
+ switch (card->csd.mmca_vsn) {
+ case 0: /* MMC v1.0 - v1.2 */
+ case 1: /* MMC v1.4 */
+ card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
+ card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
+ card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
+ card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
+ card->cid.month = UNSTUFF_BITS(resp, 12, 4);
+ card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
+ break;
+
+ case 2: /* MMC v2.0 - v2.2 */
+ case 3: /* MMC v3.1 - v3.3 */
+ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
+ card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
+ card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
+ card->cid.month = UNSTUFF_BITS(resp, 12, 4);
+ card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
+ break;
+
+ default:
+ printk("%s: card has unknown MMCA version %d\n",
+ mmc_hostname(card->host), card->csd.mmca_vsn);
+ mmc_card_set_bad(card);
+ break;
+ }
}
}
@@ -376,34 +526,86 @@ static void mmc_decode_csd(struct mmc_card *card)
unsigned int e, m, csd_struct;
u32 *resp = card->raw_csd;
- /*
- * We only understand CSD structure v1.1 and v2.
- * v2 has extra information in bits 15, 11 and 10.
- */
- csd_struct = UNSTUFF_BITS(resp, 126, 2);
- if (csd_struct != 1 && csd_struct != 2) {
- printk("%s: unrecognised CSD structure version %d\n",
- card->host->host_name, csd_struct);
- mmc_card_set_bad(card);
- return;
+ if (mmc_card_sd(card)) {
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+ if (csd_struct != 0) {
+ printk("%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
+
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+
+ e = UNSTUFF_BITS(resp, 47, 3);
+ m = UNSTUFF_BITS(resp, 62, 12);
+ csd->capacity = (1 + m) << (e + 2);
+
+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ } else {
+ /*
+ * We only understand CSD structure v1.1 and v1.2.
+ * v1.2 has extra information in bits 15, 11 and 10.
+ */
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+ if (csd_struct != 1 && csd_struct != 2) {
+ printk("%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
+
+ csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+
+ e = UNSTUFF_BITS(resp, 47, 3);
+ m = UNSTUFF_BITS(resp, 62, 12);
+ csd->capacity = (1 + m) << (e + 2);
+
+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
}
+}
- csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
- m = UNSTUFF_BITS(resp, 115, 4);
- e = UNSTUFF_BITS(resp, 112, 3);
- csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
- csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static void mmc_decode_scr(struct mmc_card *card)
+{
+ struct sd_scr *scr = &card->scr;
+ unsigned int scr_struct;
+ u32 resp[4];
+
+ BUG_ON(!mmc_card_sd(card));
- m = UNSTUFF_BITS(resp, 99, 4);
- e = UNSTUFF_BITS(resp, 96, 3);
- csd->max_dtr = tran_exp[e] * tran_mant[m];
- csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+ resp[3] = card->raw_scr[1];
+ resp[2] = card->raw_scr[0];
- e = UNSTUFF_BITS(resp, 47, 3);
- m = UNSTUFF_BITS(resp, 62, 12);
- csd->capacity = (1 + m) << (e + 2);
+ scr_struct = UNSTUFF_BITS(resp, 60, 4);
+ if (scr_struct != 0) {
+ printk("%s: unrecognised SCR structure version %d\n",
+ mmc_hostname(card->host), scr_struct);
+ mmc_card_set_bad(card);
+ return;
+ }
- csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+ scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
}
/*
@@ -457,6 +659,11 @@ static void mmc_idle_cards(struct mmc_host *host)
{
struct mmc_command cmd;
+ host->ios.chip_select = MMC_CS_HIGH;
+ host->ops->set_ios(host, &host->ios);
+
+ mmc_delay(1);
+
cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0;
cmd.flags = MMC_RSP_NONE;
@@ -464,6 +671,11 @@ static void mmc_idle_cards(struct mmc_host *host)
mmc_wait_for_cmd(host, &cmd, 0);
mmc_delay(1);
+
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ops->set_ios(host, &host->ios);
+
+ mmc_delay(1);
}
/*
@@ -475,7 +687,9 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.vdd = bit;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_UP;
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ops->set_ios(host, &host->ios);
mmc_delay(1);
@@ -492,7 +706,9 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.clock = 0;
host->ios.vdd = 0;
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_OFF;
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ops->set_ios(host, &host->ios);
}
@@ -524,6 +740,34 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err;
}
+static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+ struct mmc_command cmd;
+ int i, err = 0;
+
+ cmd.opcode = SD_APP_OP_COND;
+ cmd.arg = ocr;
+ cmd.flags = MMC_RSP_R3;
+
+ for (i = 100; i; i--) {
+ err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ break;
+
+ if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+ break;
+
+ err = MMC_ERR_TIMEOUT;
+
+ mmc_delay(10);
+ }
+
+ if (rocr)
+ *rocr = cmd.resp[0];
+
+ return err;
+}
+
/*
* Discover cards by requesting their CID. If this command
* times out, it is not an error; there are no further cards
@@ -551,7 +795,7 @@ static void mmc_discover_cards(struct mmc_host *host)
}
if (err != MMC_ERR_NONE) {
printk(KERN_ERR "%s: error requesting CID: %d\n",
- host->host_name, err);
+ mmc_hostname(host), err);
break;
}
@@ -567,13 +811,38 @@ static void mmc_discover_cards(struct mmc_host *host)
card->state &= ~MMC_STATE_DEAD;
- cmd.opcode = MMC_SET_RELATIVE_ADDR;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1;
+ if (host->mode == MMC_MODE_SD) {
+ mmc_card_set_sd(card);
- err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
- if (err != MMC_ERR_NONE)
- mmc_card_set_dead(card);
+ cmd.opcode = SD_SEND_RELATIVE_ADDR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ mmc_card_set_dead(card);
+ else {
+ card->rca = cmd.resp[0] >> 16;
+
+ if (!host->ops->get_ro) {
+ printk(KERN_WARNING "%s: host does not "
+ "support reading read-only "
+ "switch. assuming write-enable.\n",
+ mmc_hostname(host));
+ } else {
+ if (host->ops->get_ro(host))
+ mmc_card_set_readonly(card);
+ }
+ }
+ } else {
+ cmd.opcode = MMC_SET_RELATIVE_ADDR;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ mmc_card_set_dead(card);
+ }
}
}
@@ -605,6 +874,79 @@ static void mmc_read_csds(struct mmc_host *host)
}
}
+static void mmc_read_scrs(struct mmc_host *host)
+{
+ int err;
+ struct mmc_card *card;
+
+ struct mmc_request mrq;
+ struct mmc_command cmd;
+ struct mmc_data data;
+
+ struct scatterlist sg;
+
+ list_for_each_entry(card, &host->cards, node) {
+ if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+ continue;
+ if (!mmc_card_sd(card))
+ continue;
+
+ err = mmc_select_card(host, card);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = MMC_APP_CMD;
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1;
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+
+ cmd.opcode = SD_APP_SEND_SCR;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1;
+
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ data.timeout_ns = card->csd.tacc_ns * 10;
+ data.timeout_clks = card->csd.tacc_clks * 10;
+ data.blksz_bits = 3;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ memset(&mrq, 0, sizeof(struct mmc_request));
+
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+ sg_init_one(&sg, (u8*)card->raw_scr, 8);
+
+ err = mmc_wait_for_req(host, &mrq);
+ if (err != MMC_ERR_NONE) {
+ mmc_card_set_dead(card);
+ continue;
+ }
+
+ card->raw_scr[0] = ntohl(card->raw_scr[0]);
+ card->raw_scr[1] = ntohl(card->raw_scr[1]);
+
+ mmc_decode_scr(card);
+ }
+
+ mmc_deselect_cards(host);
+}
+
static unsigned int mmc_calculate_clock(struct mmc_host *host)
{
struct mmc_card *card;
@@ -657,12 +999,24 @@ static void mmc_setup(struct mmc_host *host)
int err;
u32 ocr;
+ host->mode = MMC_MODE_SD;
+
mmc_power_up(host);
mmc_idle_cards(host);
- err = mmc_send_op_cond(host, 0, &ocr);
- if (err != MMC_ERR_NONE)
- return;
+ err = mmc_send_app_op_cond(host, 0, &ocr);
+
+ /*
+ * If we fail to detect any SD cards then try
+ * searching for MMC cards.
+ */
+ if (err != MMC_ERR_NONE) {
+ host->mode = MMC_MODE_MMC;
+
+ err = mmc_send_op_cond(host, 0, &ocr);
+ if (err != MMC_ERR_NONE)
+ return;
+ }
host->ocr = mmc_select_voltage(host, ocr);
@@ -702,7 +1056,10 @@ static void mmc_setup(struct mmc_host *host)
* all get the idea that they should be ready for CMD2.
* (My SanDisk card seems to need this.)
*/
- mmc_send_op_cond(host, host->ocr, NULL);
+ if (host->mode == MMC_MODE_SD)
+ mmc_send_app_op_cond(host, host->ocr, NULL);
+ else
+ mmc_send_op_cond(host, host->ocr, NULL);
mmc_discover_cards(host);
@@ -713,19 +1070,26 @@ static void mmc_setup(struct mmc_host *host)
host->ops->set_ios(host, &host->ios);
mmc_read_csds(host);
+
+ if (host->mode == MMC_MODE_SD)
+ mmc_read_scrs(host);
}
/**
* mmc_detect_change - process change of state on a MMC socket
* @host: host which changed state.
+ * @delay: optional delay to wait before detection (jiffies)
*
* All we know is that card(s) have been inserted or removed
* from the socket(s). We don't know which socket or cards.
*/
-void mmc_detect_change(struct mmc_host *host)
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
- schedule_work(&host->detect);
+ if (delay)
+ schedule_delayed_work(&host->detect, delay);
+ else
+ schedule_work(&host->detect);
}
EXPORT_SYMBOL(mmc_detect_change);
@@ -796,17 +1160,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
struct mmc_host *host;
- host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ host = mmc_alloc_host_sysfs(extra, dev);
if (host) {
- memset(host, 0, sizeof(struct mmc_host) + extra);
-
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_LIST_HEAD(&host->cards);
INIT_WORK(&host->detect, mmc_rescan, host);
- host->dev = dev;
-
/*
* By default, hosts do not support SGIO or large requests.
* They have to set these according to their abilities.
@@ -828,15 +1188,15 @@ EXPORT_SYMBOL(mmc_alloc_host);
*/
int mmc_add_host(struct mmc_host *host)
{
- static unsigned int host_num;
-
- snprintf(host->host_name, sizeof(host->host_name),
- "mmc%d", host_num++);
+ int ret;
- mmc_power_off(host);
- mmc_detect_change(host);
+ ret = mmc_add_host_sysfs(host);
+ if (ret == 0) {
+ mmc_power_off(host);
+ mmc_detect_change(host, 0);
+ }
- return 0;
+ return ret;
}
EXPORT_SYMBOL(mmc_add_host);
@@ -859,6 +1219,7 @@ void mmc_remove_host(struct mmc_host *host)
}
mmc_power_off(host);
+ mmc_remove_host_sysfs(host);
}
EXPORT_SYMBOL(mmc_remove_host);
@@ -872,7 +1233,7 @@ EXPORT_SYMBOL(mmc_remove_host);
void mmc_free_host(struct mmc_host *host)
{
flush_scheduled_work();
- kfree(host);
+ mmc_free_host_sysfs(host);
}
EXPORT_SYMBOL(mmc_free_host);
@@ -902,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
*/
int mmc_resume_host(struct mmc_host *host)
{
- mmc_detect_change(host);
+ mmc_detect_change(host, 0);
return 0;
}
diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h
index b498dffe0b11..97bae00292fa 100644
--- a/drivers/mmc/mmc.h
+++ b/drivers/mmc/mmc.h
@@ -13,4 +13,9 @@
void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
int mmc_register_card(struct mmc_card *card);
void mmc_remove_card(struct mmc_card *card);
+
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
+int mmc_add_host_sysfs(struct mmc_host *host);
+void mmc_remove_host_sysfs(struct mmc_host *host);
+void mmc_free_host_sysfs(struct mmc_host *host);
#endif
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index d4eee99c2bf6..9b629856c735 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -85,6 +85,12 @@ static void mmc_blk_put(struct mmc_blk_data *md)
up(&open_lock);
}
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+ return mmc_card_readonly(card) ||
+ !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
static int mmc_blk_open(struct inode *inode, struct file *filp)
{
struct mmc_blk_data *md;
@@ -95,6 +101,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
if (md->usage == 2)
check_disk_change(inode->i_bdev);
ret = 0;
+
+ if ((filp->f_mode & FMODE_WRITE) &&
+ mmc_blk_readonly(md->queue.card))
+ ret = -EROFS;
}
return ret;
@@ -403,9 +413,10 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- printk(KERN_INFO "%s: %s %s %dKiB\n",
+ printk(KERN_INFO "%s: %s %s %dKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- (card->csd.capacity << card->csd.read_blkbits) / 1024);
+ (card->csd.capacity << card->csd.read_blkbits) / 1024,
+ mmc_blk_readonly(card)?"(ro)":"");
mmc_set_drvdata(card, md);
add_disk(md->disk);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 5556cd3b5559..3f4a66ca9555 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/idr.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -20,6 +21,7 @@
#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
#define MMC_ATTR(name, fmt, args...) \
static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
@@ -32,6 +34,7 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
card->raw_cid[2], card->raw_cid[3]);
MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
@@ -55,6 +58,8 @@ static struct device_attribute mmc_dev_attrs[] = {
__ATTR_NULL
};
+static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
+
static void mmc_release_card(struct device *dev)
{
@@ -205,10 +210,20 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
*/
int mmc_register_card(struct mmc_card *card)
{
- snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
- "%s:%04x", card->host->host_name, card->rca);
+ int ret;
- return device_add(&card->dev);
+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+ "%s:%04x", mmc_hostname(card->host), card->rca);
+
+ ret = device_add(&card->dev);
+ if (ret == 0) {
+ if (mmc_card_sd(card)) {
+ ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
+ if (ret)
+ device_del(&card->dev);
+ }
+ }
+ return ret;
}
/*
@@ -217,20 +232,108 @@ int mmc_register_card(struct mmc_card *card)
*/
void mmc_remove_card(struct mmc_card *card)
{
- if (mmc_card_present(card))
+ if (mmc_card_present(card)) {
+ if (mmc_card_sd(card))
+ device_remove_file(&card->dev, &mmc_dev_attr_scr);
+
device_del(&card->dev);
+ }
put_device(&card->dev);
}
+static void mmc_host_classdev_release(struct class_device *dev)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ kfree(host);
+}
+
+static struct class mmc_host_class = {
+ .name = "mmc_host",
+ .release = mmc_host_classdev_release,
+};
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/*
+ * Internal function. Allocate a new MMC host.
+ */
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
+{
+ struct mmc_host *host;
+
+ host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ if (host) {
+ memset(host, 0, sizeof(struct mmc_host) + extra);
+
+ host->dev = dev;
+ host->class_dev.dev = host->dev;
+ host->class_dev.class = &mmc_host_class;
+ class_device_initialize(&host->class_dev);
+ }
+
+ return host;
+}
+
+/*
+ * Internal function. Register a new MMC host with the MMC class.
+ */
+int mmc_add_host_sysfs(struct mmc_host *host)
+{
+ int err;
+
+ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&mmc_host_lock);
+ err = idr_get_new(&mmc_host_idr, host, &host->index);
+ spin_unlock(&mmc_host_lock);
+ if (err)
+ return err;
+
+ snprintf(host->class_dev.class_id, BUS_ID_SIZE,
+ "mmc%d", host->index);
+
+ return class_device_add(&host->class_dev);
+}
+
+/*
+ * Internal function. Unregister a MMC host with the MMC class.
+ */
+void mmc_remove_host_sysfs(struct mmc_host *host)
+{
+ class_device_del(&host->class_dev);
+
+ spin_lock(&mmc_host_lock);
+ idr_remove(&mmc_host_idr, host->index);
+ spin_unlock(&mmc_host_lock);
+}
+
+/*
+ * Internal function. Free a MMC host.
+ */
+void mmc_free_host_sysfs(struct mmc_host *host)
+{
+ class_device_put(&host->class_dev);
+}
+
+
static int __init mmc_init(void)
{
- return bus_register(&mmc_bus_type);
+ int ret = bus_register(&mmc_bus_type);
+ if (ret == 0) {
+ ret = class_register(&mmc_host_class);
+ if (ret)
+ bus_unregister(&mmc_bus_type);
+ }
+ return ret;
}
static void __exit mmc_exit(void)
{
+ class_unregister(&mmc_host_class);
bus_unregister(&mmc_bus_type);
}
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 7a42966d755b..1e6bdba26756 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -24,6 +24,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/scatterlist.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#include <asm/mach/mmc.h>
@@ -34,7 +35,7 @@
#ifdef CONFIG_MMC_DEBUG
#define DBG(host,fmt,args...) \
- pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args)
+ pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
#else
#define DBG(host,fmt,args...) do { } while (0)
#endif
@@ -442,7 +443,7 @@ static void mmci_check_status(unsigned long data)
status = host->plat->status(mmc_dev(host->mmc));
if (status ^ host->oldstat)
- mmc_detect_change(host->mmc);
+ mmc_detect_change(host->mmc, 0);
host->oldstat = status;
mod_timer(&host->timer, jiffies + HZ);
@@ -541,7 +542,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
mmc_add_host(mmc);
printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n",
- mmc->host_name, amba_rev(dev), amba_config(dev),
+ mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
dev->res.start, dev->irq[0], dev->irq[1]);
init_timer(&host->timer);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index b78beb1b0159..f31e247b2cbe 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -20,7 +20,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
@@ -29,7 +29,6 @@
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/scatterlist.h>
#include <asm/sizes.h>
@@ -362,6 +361,16 @@ static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
pxamci_start_cmd(host, mrq->cmd, cmdat);
}
+static int pxamci_get_ro(struct mmc_host *mmc)
+{
+ struct pxamci_host *host = mmc_priv(mmc);
+
+ if (host->pdata && host->pdata->get_ro)
+ return host->pdata->get_ro(mmc->dev);
+ /* Host doesn't support read only detection so assume writeable */
+ return 0;
+}
+
static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct pxamci_host *host = mmc_priv(mmc);
@@ -401,6 +410,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static struct mmc_host_ops pxamci_ops = {
.request = pxamci_request,
+ .get_ro = pxamci_get_ro,
.set_ios = pxamci_set_ios,
};
@@ -412,7 +422,9 @@ static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs)
static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs)
{
- mmc_detect_change(devid);
+ struct pxamci_host *host = mmc_priv(devid);
+
+ mmc_detect_change(devid, host->pdata->detect_delay);
return IRQ_HANDLED;
}
@@ -558,23 +570,23 @@ static int pxamci_remove(struct device *dev)
}
#ifdef CONFIG_PM
-static int pxamci_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxamci_suspend(struct device *dev, pm_message_t state)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
int ret = 0;
- if (mmc && level == SUSPEND_DISABLE)
+ if (mmc)
ret = mmc_suspend_host(mmc, state);
return ret;
}
-static int pxamci_resume(struct device *dev, u32 level)
+static int pxamci_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
int ret = 0;
- if (mmc && level == RESUME_ENABLE)
+ if (mmc)
ret = mmc_resume_host(mmc);
return ret;
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 8b487ed1069c..942668e93a74 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -26,7 +26,7 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -42,7 +42,7 @@
#include "wbsd.h"
#define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.2"
+#define DRIVER_VERSION "1.4"
#ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \
@@ -93,7 +93,7 @@ static int dma = 2;
static inline void wbsd_unlock_config(struct wbsd_host* host)
{
BUG_ON(host->config == 0);
-
+
outb(host->unlock_code, host->config);
outb(host->unlock_code, host->config);
}
@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
static inline void wbsd_lock_config(struct wbsd_host* host)
{
BUG_ON(host->config == 0);
-
+
outb(LOCK_CODE, host->config);
}
static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
{
BUG_ON(host->config == 0);
-
+
outb(reg, host->config);
outb(value, host->config + 1);
}
@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
{
BUG_ON(host->config == 0);
-
+
outb(reg, host->config);
return inb(host->config + 1);
}
@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
static void wbsd_init_device(struct wbsd_host* host)
{
u8 setup, ier;
-
+
/*
* Reset chip (SD/MMC part) and fifo.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
/*
* Set DAT3 to input
*/
setup &= ~WBSD_DAT3_H;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
host->flags &= ~WBSD_FIGNORE_DETECT;
-
+
/*
* Read back default clock.
*/
@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
* Power down port.
*/
outb(WBSD_POWER_N, host->base + WBSD_CSR);
-
+
/*
* Set maximum timeout.
*/
wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
-
+
/*
* Test for card presence
*/
@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
host->flags |= WBSD_FCARD_PRESENT;
else
host->flags &= ~WBSD_FCARD_PRESENT;
-
+
/*
* Enable interesting interrupts.
*/
@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
static void wbsd_reset(struct wbsd_host* host)
{
u8 setup;
-
+
printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
-
+
/*
* Soft reset of chip (SD/MMC part).
*/
@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
{
unsigned long dmaflags;
-
+
DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-
+
if (host->dma >= 0)
{
/*
@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
}
-
+
host->mrq = NULL;
/*
@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
host->offset = 0;
host->remain = host->cur_sg->length;
}
-
+
return host->num_sg;
}
@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg;
char* dmabuf = host->dma_buffer;
char* sgbuf;
-
+
size = host->size;
-
+
sg = data->sg;
len = data->sg_len;
-
+
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
memcpy(dmabuf, sgbuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length;
-
+
if (size < sg[i].length)
size = 0;
else
size -= sg[i].length;
-
+
if (size == 0)
break;
}
-
+
/*
* Check that we didn't get a request to transfer
* more data than can fit into the SG list.
*/
-
+
BUG_ON(size != 0);
-
+
host->size -= size;
}
@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
struct scatterlist* sg;
char* dmabuf = host->dma_buffer;
char* sgbuf;
-
+
size = host->size;
-
+
sg = data->sg;
len = data->sg_len;
-
+
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
memcpy(sgbuf, dmabuf, sg[i].length);
kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
dmabuf += sg[i].length;
-
+
if (size < sg[i].length)
size = 0;
else
size -= sg[i].length;
-
+
if (size == 0)
break;
}
-
+
/*
* Check that we didn't get a request to transfer
* more data than can fit into the SG list.
*/
-
+
BUG_ON(size != 0);
-
+
host->size -= size;
}
/*
* Command handling
*/
-
+
static inline void wbsd_get_short_reply(struct wbsd_host* host,
struct mmc_command* cmd)
{
@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID;
return;
}
-
+
cmd->resp[0] =
wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
cmd->resp[0] |=
@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
struct mmc_command* cmd)
{
int i;
-
+
/*
* Correct response type?
*/
@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
cmd->error = MMC_ERR_INVALID;
return;
}
-
+
for (i = 0;i < 4;i++)
{
cmd->resp[i] =
@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
{
int i;
u8 status, isr;
-
+
DBGF("Sending cmd (%x)\n", cmd->opcode);
/*
@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* transfer.
*/
host->isr = 0;
-
+
/*
* Send the command (CRC calculated by host).
*/
outb(cmd->opcode, host->base + WBSD_CMDR);
for (i = 3;i >= 0;i--)
outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
-
+
cmd->error = MMC_ERR_NONE;
-
+
/*
* Wait for the request to complete.
*/
@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Read back status.
*/
isr = host->isr;
-
+
/* Card removed? */
if (isr & WBSD_INT_CARD)
cmd->error = MMC_ERR_TIMEOUT;
@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data;
char* buffer;
int i, fsr, fifo;
-
+
/*
* Handle excessive data.
*/
if (data->bytes_xfered == host->size)
return;
-
+
buffer = wbsd_kmap_sg(host) + host->offset;
/*
@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
- */
+ */
if (fsr & WBSD_FIFO_FULL)
fifo = 16;
else if (fsr & WBSD_FIFO_FUTHRE)
fifo = 8;
else
fifo = 1;
-
+
for (i = 0;i < fifo;i++)
{
*buffer = inb(host->base + WBSD_DFR);
@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
host->remain--;
data->bytes_xfered++;
-
+
/*
* Transfer done?
*/
if (data->bytes_xfered == host->size)
{
- wbsd_kunmap_sg(host);
+ wbsd_kunmap_sg(host);
return;
}
-
+
/*
* End of scatter list entry?
*/
if (host->remain == 0)
{
wbsd_kunmap_sg(host);
-
+
/*
* Get next entry. Check if last.
*/
@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON(1);
-
+
host->size = data->bytes_xfered;
-
+
return;
}
-
+
buffer = wbsd_kmap_sg(host);
}
}
}
-
+
wbsd_kunmap_sg(host);
/*
@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
struct mmc_data* data = host->mrq->cmd->data;
char* buffer;
int i, fsr, fifo;
-
+
/*
* Check that we aren't being called after the
* entire buffer has been transfered.
@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
- */
+ */
if (fsr & WBSD_FIFO_EMPTY)
fifo = 0;
else if (fsr & WBSD_FIFO_EMTHRE)
@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
buffer++;
host->offset++;
host->remain--;
-
+
data->bytes_xfered++;
-
+
/*
* Transfer done?
*/
@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
if (host->remain == 0)
{
wbsd_kunmap_sg(host);
-
+
/*
* Get next entry. Check if last.
*/
@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON(1);
-
+
host->size = data->bytes_xfered;
-
+
return;
}
-
+
buffer = wbsd_kmap_sg(host);
}
}
}
-
+
wbsd_kunmap_sg(host);
-
+
/*
* The controller stops sending interrupts for
* 'FIFO empty' under certain conditions. So we
@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
1 << data->blksz_bits, data->blocks, data->flags);
DBGF("tsac %d ms nsac %d clk\n",
data->timeout_ns / 1000000, data->timeout_clks);
-
+
/*
* Calculate size.
*/
@@ -708,23 +708,40 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
wbsd_write_index(host, WBSD_IDX_TAAC, 127);
else
wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
-
+
if (data->timeout_clks > 255)
wbsd_write_index(host, WBSD_IDX_NSAC, 255);
else
wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
-
+
/*
* Inform the chip of how large blocks will be
* sent. It needs this to determine when to
* calculate CRC.
*
* Space for CRC must be included in the size.
+ * Two bytes are needed for each data line.
*/
- blksize = (1 << data->blksz_bits) + 2;
-
- wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
- wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+ if (host->bus_width == MMC_BUS_WIDTH_1)
+ {
+ blksize = (1 << data->blksz_bits) + 2;
+
+ wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
+ wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+ }
+ else if (host->bus_width == MMC_BUS_WIDTH_4)
+ {
+ blksize = (1 << data->blksz_bits) + 2 * 4;
+
+ wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
+ | WBSD_DATA_WIDTH);
+ wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
+ }
+ else
+ {
+ data->error = MMC_ERR_INVALID;
+ return;
+ }
/*
* Clear the FIFO. This is needed even for DMA
@@ -734,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
setup |= WBSD_FIFO_RESET;
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
/*
* DMA transfer?
*/
if (host->dma >= 0)
- {
+ {
/*
* The buffer for DMA is only 64 kB.
*/
@@ -749,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data->error = MMC_ERR_INVALID;
return;
}
-
+
/*
* Transfer data from the SG list to
* the DMA buffer.
*/
if (data->flags & MMC_DATA_WRITE)
wbsd_sg_to_dma(host, data);
-
+
/*
* Initialise the ISA DMA controller.
- */
+ */
dmaflags = claim_dma_lock();
disable_dma(host->dma);
clear_dma_ff(host->dma);
@@ -785,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* output to a minimum.
*/
host->firsterr = 1;
-
+
/*
* Initialise the SG list.
*/
wbsd_init_sg(host, data);
-
+
/*
* Turn off DMA.
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
+
/*
* Set up FIFO threshold levels (and fill
* buffer if doing a write).
@@ -811,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
WBSD_FIFOEN_EMPTY | 8);
wbsd_fill_fifo(host);
}
- }
-
+ }
+
data->error = MMC_ERR_NONE;
}
@@ -821,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
unsigned long dmaflags;
int count;
u8 status;
-
+
WARN_ON(host->mrq == NULL);
/*
@@ -838,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
status = wbsd_read_index(host, WBSD_IDX_STATUS);
} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
-
+
/*
* DMA transfer?
*/
@@ -848,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Disable DMA on the host.
*/
wbsd_write_index(host, WBSD_IDX_DMA, 0);
-
+
/*
* Turn of ISA DMA controller.
*/
@@ -857,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
clear_dma_ff(host->dma);
count = get_dma_residue(host->dma);
release_dma_lock(dmaflags);
-
+
/*
* Any leftover data?
*/
@@ -865,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
"transfer. %d bytes left.\n", count);
-
+
data->error = MMC_ERR_FAILED;
}
else
@@ -876,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
*/
if (data->flags & MMC_DATA_READ)
wbsd_dma_to_sg(host, data);
-
+
data->bytes_xfered = host->size;
}
}
-
+
DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-
+
wbsd_request_end(host, host->mrq);
}
@@ -907,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
cmd = mrq->cmd;
host->mrq = mrq;
-
+
/*
* If there is no card in the slot then
* timeout immediatly.
@@ -924,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
if (cmd->data)
{
wbsd_prepare_data(host, cmd->data);
-
+
if (cmd->data->error != MMC_ERR_NONE)
goto done;
}
-
+
wbsd_send_command(host, cmd);
/*
* If this is a data transfer the request
* will be finished after the data has
* transfered.
- */
+ */
if (cmd->data && (cmd->error == MMC_ERR_NONE))
{
/*
@@ -948,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
return;
}
-
+
done:
wbsd_request_end(host, mrq);
@@ -959,9 +976,10 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{
struct wbsd_host* host = mmc_priv(mmc);
u8 clk, setup, pwr;
-
- DBGF("clock %uHz busmode %u powermode %u Vdd %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+ DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+ ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
+ ios->vdd, ios->bus_width);
spin_lock_bh(&host->lock);
@@ -971,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
*/
if (ios->power_mode == MMC_POWER_OFF)
wbsd_init_device(host);
-
+
if (ios->clock >= 24000000)
clk = WBSD_CLK_24M;
else if (ios->clock >= 16000000)
@@ -1003,30 +1021,66 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
/*
* MMC cards need to have pin 1 high during init.
- * Init time corresponds rather nicely with the bus mode.
* It wreaks havoc with the card detection though so
- * that needs to be disabed.
+ * that needs to be disabled.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
- if ((ios->power_mode == MMC_POWER_ON) &&
- (ios->bus_mode == MMC_BUSMODE_OPENDRAIN))
+ if (ios->chip_select == MMC_CS_HIGH)
{
+ BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
setup |= WBSD_DAT3_H;
host->flags |= WBSD_FIGNORE_DETECT;
}
else
{
- setup &= ~WBSD_DAT3_H;
- host->flags &= ~WBSD_FIGNORE_DETECT;
+ if (setup & WBSD_DAT3_H)
+ {
+ setup &= ~WBSD_DAT3_H;
+
+ /*
+ * We cannot resume card detection immediatly
+ * because of capacitance and delays in the chip.
+ */
+ mod_timer(&host->ignore_timer, jiffies + HZ/100);
+ }
}
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
+
+ /*
+ * Store bus width for later. Will be used when
+ * setting up the data transfer.
+ */
+ host->bus_width = ios->bus_width;
+
+ spin_unlock_bh(&host->lock);
+}
+
+static int wbsd_get_ro(struct mmc_host* mmc)
+{
+ struct wbsd_host* host = mmc_priv(mmc);
+ u8 csr;
+
+ spin_lock_bh(&host->lock);
+
+ csr = inb(host->base + WBSD_CSR);
+ csr |= WBSD_MSLED;
+ outb(csr, host->base + WBSD_CSR);
+
+ mdelay(1);
+
+ csr = inb(host->base + WBSD_CSR);
+ csr &= ~WBSD_MSLED;
+ outb(csr, host->base + WBSD_CSR);
+
spin_unlock_bh(&host->lock);
+
+ return csr & WBSD_WRPT;
}
static struct mmc_host_ops wbsd_ops = {
.request = wbsd_request,
.set_ios = wbsd_set_ios,
+ .get_ro = wbsd_get_ro,
};
/*****************************************************************************\
@@ -1036,17 +1090,28 @@ static struct mmc_host_ops wbsd_ops = {
\*****************************************************************************/
/*
- * Helper function for card detection
+ * Helper function to reset detection ignore
*/
-static void wbsd_detect_card(unsigned long data)
+
+static void wbsd_reset_ignore(unsigned long data)
{
struct wbsd_host *host = (struct wbsd_host*)data;
-
+
BUG_ON(host == NULL);
-
- DBG("Executing card detection\n");
-
- mmc_detect_change(host->mmc);
+
+ DBG("Resetting card detection ignore\n");
+
+ spin_lock_bh(&host->lock);
+
+ host->flags &= ~WBSD_FIGNORE_DETECT;
+
+ /*
+ * Card status might have changed during the
+ * blackout.
+ */
+ tasklet_schedule(&host->card_tasklet);
+
+ spin_unlock_bh(&host->lock);
}
/*
@@ -1066,7 +1131,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
WARN_ON(!host->mrq->cmd->data);
if (!host->mrq->cmd->data)
return NULL;
-
+
return host->mrq->cmd->data;
}
@@ -1074,68 +1139,67 @@ static void wbsd_tasklet_card(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr;
-
+ int delay = -1;
+
spin_lock(&host->lock);
-
+
if (host->flags & WBSD_FIGNORE_DETECT)
{
spin_unlock(&host->lock);
return;
}
-
+
csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff);
-
+
if (csr & WBSD_CARDPRESENT)
{
if (!(host->flags & WBSD_FCARD_PRESENT))
{
DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT;
-
- /*
- * Delay card detection to allow electrical connections
- * to stabilise.
- */
- mod_timer(&host->timer, jiffies + HZ/2);
+
+ delay = 500;
}
-
- spin_unlock(&host->lock);
}
else if (host->flags & WBSD_FCARD_PRESENT)
{
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
-
+
if (host->mrq)
{
printk(KERN_ERR DRIVER_NAME
": Card removed during transfer!\n");
wbsd_reset(host);
-
+
host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet);
}
-
- /*
- * Unlock first since we might get a call back.
- */
- spin_unlock(&host->lock);
- mmc_detect_change(host->mmc);
+ delay = 0;
}
+
+ /*
+ * Unlock first since we might get a call back.
+ */
+
+ spin_unlock(&host->lock);
+
+ if (delay != -1)
+ mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
}
static void wbsd_tasklet_fifo(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
@@ -1154,7 +1218,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
tasklet_schedule(&host->finish_tasklet);
}
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1162,23 +1226,23 @@ static void wbsd_tasklet_crc(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC;
-
+
tasklet_schedule(&host->finish_tasklet);
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1186,23 +1250,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("Timeout\n");
data->error = MMC_ERR_TIMEOUT;
-
+
tasklet_schedule(&host->finish_tasklet);
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1210,20 +1274,20 @@ static void wbsd_tasklet_finish(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
-
+
WARN_ON(!host->mrq);
if (!host->mrq)
goto end;
-
+
data = wbsd_get_data(host);
if (!data)
goto end;
wbsd_finish_data(host, data);
-
-end:
+
+end:
spin_unlock(&host->lock);
}
@@ -1231,7 +1295,7 @@ static void wbsd_tasklet_block(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
struct mmc_data* data;
-
+
spin_lock(&host->lock);
if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
@@ -1240,15 +1304,15 @@ static void wbsd_tasklet_block(unsigned long param)
data = wbsd_get_data(host);
if (!data)
goto end;
-
+
DBGF("CRC error\n");
data->error = MMC_ERR_BADCRC;
-
+
tasklet_schedule(&host->finish_tasklet);
}
-end:
+end:
spin_unlock(&host->lock);
}
@@ -1260,7 +1324,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct wbsd_host* host = dev_id;
int isr;
-
+
isr = inb(host->base + WBSD_ISR);
/*
@@ -1268,7 +1332,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
*/
if (isr == 0xff || isr == 0x00)
return IRQ_NONE;
-
+
host->isr |= isr;
/*
@@ -1286,7 +1350,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
tasklet_hi_schedule(&host->block_tasklet);
if (isr & WBSD_INT_TC)
tasklet_schedule(&host->finish_tasklet);
-
+
return IRQ_HANDLED;
}
@@ -1304,14 +1368,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
{
struct mmc_host* mmc;
struct wbsd_host* host;
-
+
/*
* Allocate MMC structure.
*/
mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
if (!mmc)
return -ENOMEM;
-
+
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -1324,37 +1388,38 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc->f_min = 375000;
mmc->f_max = 24000000;
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
-
+ mmc->caps = MMC_CAP_4_BIT_DATA;
+
spin_lock_init(&host->lock);
-
+
/*
- * Set up detection timer
+ * Set up timers
*/
- init_timer(&host->timer);
- host->timer.data = (unsigned long)host;
- host->timer.function = wbsd_detect_card;
-
+ init_timer(&host->ignore_timer);
+ host->ignore_timer.data = (unsigned long)host;
+ host->ignore_timer.function = wbsd_reset_ignore;
+
/*
* Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512.
*/
mmc->max_hw_segs = 128;
mmc->max_phys_segs = 128;
-
+
/*
* Maximum number of sectors in one transfer. Also limited by 64kB
* buffer.
*/
mmc->max_sectors = 128;
-
+
/*
* Maximum segment size. Could be one segment with the maximum number
* of segments.
*/
mmc->max_seg_size = mmc->max_sectors * 512;
-
+
dev_set_drvdata(dev, mmc);
-
+
return 0;
}
@@ -1362,18 +1427,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
{
struct mmc_host* mmc;
struct wbsd_host* host;
-
+
mmc = dev_get_drvdata(dev);
if (!mmc)
return;
-
+
host = mmc_priv(mmc);
BUG_ON(host == NULL);
-
- del_timer_sync(&host->timer);
-
+
+ del_timer_sync(&host->ignore_timer);
+
mmc_free_host(mmc);
-
+
dev_set_drvdata(dev, NULL);
}
@@ -1385,7 +1450,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
int i, j, k;
int id;
-
+
/*
* Iterate through all ports, all codes to
* find hardware that is in our known list.
@@ -1394,44 +1459,47 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
if (!request_region(config_ports[i], 2, DRIVER_NAME))
continue;
-
+
for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
{
id = 0xFFFF;
-
- outb(unlock_codes[j], config_ports[i]);
- outb(unlock_codes[j], config_ports[i]);
-
+
+ host->config = config_ports[i];
+ host->unlock_code = unlock_codes[j];
+
+ wbsd_unlock_config(host);
+
outb(WBSD_CONF_ID_HI, config_ports[i]);
id = inb(config_ports[i] + 1) << 8;
outb(WBSD_CONF_ID_LO, config_ports[i]);
id |= inb(config_ports[i] + 1);
-
+
+ wbsd_lock_config(host);
+
for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
{
if (id == valid_ids[k])
- {
+ {
host->chip_id = id;
- host->config = config_ports[i];
- host->unlock_code = unlock_codes[i];
-
+
return 0;
}
}
-
+
if (id != 0xFFFF)
{
DBG("Unknown hardware (id %x) found at %x\n",
id, config_ports[i]);
}
-
- outb(LOCK_CODE, config_ports[i]);
}
-
+
release_region(config_ports[i], 2);
}
-
+
+ host->config = 0;
+ host->unlock_code = 0;
+
return -ENODEV;
}
@@ -1443,12 +1511,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
{
if (io & 0x7)
return -EINVAL;
-
+
if (!request_region(base, 8, DRIVER_NAME))
return -EIO;
-
+
host->base = io;
-
+
return 0;
}
@@ -1456,12 +1524,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
{
if (host->base)
release_region(host->base, 8);
-
+
host->base = 0;
if (host->config)
release_region(host->config, 2);
-
+
host->config = 0;
}
@@ -1473,10 +1541,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
{
if (dma < 0)
return;
-
+
if (request_dma(dma, DRIVER_NAME))
goto err;
-
+
/*
* We need to allocate a special buffer in
* order for ISA to be able to DMA to it.
@@ -1491,7 +1559,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
*/
host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-
+
/*
* ISA DMA must be aligned on a 64k basis.
*/
@@ -1504,19 +1572,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
goto kfree;
host->dma = dma;
-
+
return;
-
+
kfree:
/*
* If we've gotten here then there is some kind of alignment bug
*/
BUG_ON(1);
-
+
dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL;
-
+
kfree(host->dma_buffer);
host->dma_buffer = NULL;
@@ -1537,7 +1605,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
kfree(host->dma_buffer);
if (host->dma >= 0)
free_dma(host->dma);
-
+
host->dma = -1;
host->dma_buffer = NULL;
host->dma_addr = (dma_addr_t)NULL;
@@ -1550,7 +1618,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
{
int ret;
-
+
/*
* Allocate interrupt.
*/
@@ -1558,7 +1626,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
if (ret)
return ret;
-
+
host->irq = irq;
/*
@@ -1570,7 +1638,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
-
+
return 0;
}
@@ -1580,9 +1648,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
return;
free_irq(host->irq, host);
-
+
host->irq = 0;
-
+
tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->fifo_tasklet);
tasklet_kill(&host->crc_tasklet);
@@ -1599,7 +1667,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
int base, int irq, int dma)
{
int ret;
-
+
/*
* Allocate I/O ports.
*/
@@ -1618,7 +1686,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Allocate DMA.
*/
wbsd_request_dma(host, dma);
-
+
return 0;
}
@@ -1637,11 +1705,13 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host)
* Configure the resources the chip should use.
*/
-static void __devinit wbsd_chip_config(struct wbsd_host* host)
+static void wbsd_chip_config(struct wbsd_host* host)
{
+ wbsd_unlock_config(host);
+
/*
* Reset the chip.
- */
+ */
wbsd_write_config(host, WBSD_CONF_SWRST, 1);
wbsd_write_config(host, WBSD_CONF_SWRST, 0);
@@ -1649,53 +1719,59 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
* Select SD/MMC function.
*/
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
+
/*
* Set up card detection.
*/
wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
-
+
/*
* Configure chip
*/
wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-
+
wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
-
+
if (host->dma >= 0)
wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
-
+
/*
* Enable and power up chip.
*/
wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+
+ wbsd_lock_config(host);
}
/*
* Check that configured resources are correct.
*/
-
-static int __devinit wbsd_chip_validate(struct wbsd_host* host)
+
+static int wbsd_chip_validate(struct wbsd_host* host)
{
int base, irq, dma;
-
+
+ wbsd_unlock_config(host);
+
/*
* Select SD/MMC function.
*/
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-
+
/*
* Read configuration.
*/
base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
-
+
irq = wbsd_read_config(host, WBSD_CONF_IRQ);
-
+
dma = wbsd_read_config(host, WBSD_CONF_DRQ);
-
+
+ wbsd_lock_config(host);
+
/*
* Validate against given configuration.
*/
@@ -1705,10 +1781,24 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
return 0;
if ((dma != host->dma) && (host->dma != -1))
return 0;
-
+
return 1;
}
+/*
+ * Powers down the SD function
+ */
+
+static void wbsd_chip_poweroff(struct wbsd_host* host)
+{
+ wbsd_unlock_config(host);
+
+ wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+ wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+
+ wbsd_lock_config(host);
+}
+
/*****************************************************************************\
* *
* Devices setup and shutdown *
@@ -1721,14 +1811,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
struct wbsd_host* host = NULL;
struct mmc_host* mmc = NULL;
int ret;
-
+
ret = wbsd_alloc_mmc(dev);
if (ret)
return ret;
-
+
mmc = dev_get_drvdata(dev);
host = mmc_priv(mmc);
-
+
/*
* Scan for hardware.
*/
@@ -1747,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return ret;
}
}
-
+
/*
* Request resources.
*/
@@ -1758,7 +1848,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
wbsd_free_mmc(dev);
return ret;
}
-
+
/*
* See if chip needs to be configured.
*/
@@ -1775,14 +1865,18 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
}
else
wbsd_chip_config(host);
-
+
/*
* Power Management stuff. No idea how this works.
* Not tested.
*/
#ifdef CONFIG_PM
if (host->config)
+ {
+ wbsd_unlock_config(host);
wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+ wbsd_lock_config(host);
+ }
#endif
/*
* Allow device to initialise itself properly.
@@ -1793,10 +1887,10 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Reset the chip into a known state.
*/
wbsd_init_device(host);
-
+
mmc_add_host(mmc);
- printk(KERN_INFO "%s: W83L51xD", mmc->host_name);
+ printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
if (host->chip_id != 0)
printk(" id %x", (int)host->chip_id);
printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
@@ -1815,27 +1909,22 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
{
struct mmc_host* mmc = dev_get_drvdata(dev);
struct wbsd_host* host;
-
+
if (!mmc)
return;
host = mmc_priv(mmc);
-
+
mmc_remove_host(mmc);
+ /*
+ * Power down the SD/MMC function.
+ */
if (!pnp)
- {
- /*
- * Power down the SD/MMC function.
- */
- wbsd_unlock_config(host);
- wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
- wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
- wbsd_lock_config(host);
- }
-
+ wbsd_chip_poweroff(host);
+
wbsd_release_resources(host);
-
+
wbsd_free_mmc(dev);
}
@@ -1865,7 +1954,7 @@ static int __devinit
wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
{
int io, irq, dma;
-
+
/*
* Get resources from PnP layer.
*/
@@ -1875,9 +1964,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
dma = pnp_dma(pnpdev, 0);
else
dma = -1;
-
+
DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
-
+
return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
}
@@ -1893,23 +1982,59 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
*/
#ifdef CONFIG_PM
-static int wbsd_suspend(struct device *dev, pm_message_t state, u32 level)
+
+static int wbsd_suspend(struct device *dev, pm_message_t state)
{
- DBGF("Not yet supported\n");
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct wbsd_host *host;
+ int ret;
+
+ if (!mmc)
+ return 0;
+
+ DBG("Suspending...\n");
+
+ ret = mmc_suspend_host(mmc, state);
+ if (!ret)
+ return ret;
+
+ host = mmc_priv(mmc);
+
+ wbsd_chip_poweroff(host);
return 0;
}
-static int wbsd_resume(struct device *dev, u32 level)
+static int wbsd_resume(struct device *dev)
{
- DBGF("Not yet supported\n");
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct wbsd_host *host;
- return 0;
+ if (!mmc)
+ return 0;
+
+ DBG("Resuming...\n");
+
+ host = mmc_priv(mmc);
+
+ wbsd_chip_config(host);
+
+ /*
+ * Allow device to initialise itself properly.
+ */
+ mdelay(5);
+
+ wbsd_init_device(host);
+
+ return mmc_resume_host(mmc);
}
-#else
+
+#else /* CONFIG_PM */
+
#define wbsd_suspend NULL
#define wbsd_resume NULL
-#endif
+
+#endif /* CONFIG_PM */
static struct platform_device *wbsd_device;
@@ -1918,7 +2043,7 @@ static struct device_driver wbsd_driver = {
.bus = &platform_bus_type,
.probe = wbsd_probe,
.remove = wbsd_remove,
-
+
.suspend = wbsd_suspend,
.resume = wbsd_resume,
};
@@ -1941,7 +2066,7 @@ static struct pnp_driver wbsd_pnp_driver = {
static int __init wbsd_drv_init(void)
{
int result;
-
+
printk(KERN_INFO DRIVER_NAME
": Winbond W83L51xD SD/MMC card interface driver, "
DRIVER_VERSION "\n");
@@ -1956,8 +2081,8 @@ static int __init wbsd_drv_init(void)
return result;
}
-#endif /* CONFIG_PNP */
-
+#endif /* CONFIG_PNP */
+
if (nopnp)
{
result = driver_register(&wbsd_driver);
@@ -1979,13 +2104,13 @@ static void __exit wbsd_drv_exit(void)
if (!nopnp)
pnp_unregister_driver(&wbsd_pnp_driver);
-
-#endif /* CONFIG_PNP */
+
+#endif /* CONFIG_PNP */
if (nopnp)
{
platform_device_unregister(wbsd_device);
-
+
driver_unregister(&wbsd_driver);
}
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 661a9f6a6e6f..249baa701cb0 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -106,6 +106,8 @@
#define WBSD_CLK_16M 0x02
#define WBSD_CLK_24M 0x03
+#define WBSD_DATA_WIDTH 0x01
+
#define WBSD_DAT3_H 0x08
#define WBSD_FIFO_RESET 0x04
#define WBSD_SOFT_RESET 0x02
@@ -137,49 +139,50 @@
struct wbsd_host
{
struct mmc_host* mmc; /* MMC structure */
-
+
spinlock_t lock; /* Mutex */
int flags; /* Driver states */
#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */
#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */
-
+
struct mmc_request* mrq; /* Current request */
-
+
u8 isr; /* Accumulated ISR */
-
+
struct scatterlist* cur_sg; /* Current SG entry */
unsigned int num_sg; /* Number of entries left */
void* mapped_sg; /* vaddr of mapped sg */
-
+
unsigned int offset; /* Offset into current entry */
unsigned int remain; /* Data left in curren entry */
int size; /* Total size of transfer */
-
+
char* dma_buffer; /* ISA DMA buffer */
dma_addr_t dma_addr; /* Physical address for same */
int firsterr; /* See fifo functions */
-
+
u8 clk; /* Current clock speed */
-
+ unsigned char bus_width; /* Current bus width */
+
int config; /* Config port */
u8 unlock_code; /* Code to unlock config */
int chip_id; /* ID of controller */
-
+
int base; /* I/O port base */
int irq; /* Interrupt */
int dma; /* DMA channel */
-
+
struct tasklet_struct card_tasklet; /* Tasklet structures */
struct tasklet_struct fifo_tasklet;
struct tasklet_struct crc_tasklet;
struct tasklet_struct timeout_tasklet;
struct tasklet_struct finish_tasklet;
struct tasklet_struct block_tasklet;
-
- struct timer_list timer; /* Card detection timer */
+
+ struct timer_list ignore_timer; /* Ignore detection timer */
};
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index 62d235a9a4e2..4f6778f3ee3e 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/mtd/jedec.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
index 9a087c1fb0b7..24f670b5a4f3 100644
--- a/drivers/mtd/devices/docecc.c
+++ b/drivers/mtd/devices/docecc.c
@@ -40,7 +40,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/doc2000.h>
-#define DEBUG 0
+#define DEBUG_ECC 0
/* need to undef it (from asm/termbits.h) */
#undef B0
@@ -249,7 +249,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
lambda[j] ^= Alpha_to[modnn(u + tmp)];
}
}
-#if DEBUG >= 1
+#if DEBUG_ECC >= 1
/* Test code that verifies the erasure locator polynomial just constructed
Needed only for decoder debugging. */
@@ -276,7 +276,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
count = -1;
goto finish;
}
-#if DEBUG >= 2
+#if DEBUG_ECC >= 2
printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
for (i = 0; i < count; i++)
printf("%d ", loc[i]);
@@ -409,7 +409,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
}
if (den == 0) {
-#if DEBUG >= 1
+#if DEBUG_ECC >= 1
printf("\n ERROR: denominator = 0\n");
#endif
/* Convert to dual- basis */
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index dfd335e4a2a8..df987a53ed9c 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -44,6 +44,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <linux/mtd/mtd.h>
#ifdef HAVE_PARTITIONS
#include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index bb713fed2f37..1443117fd8f4 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -91,8 +91,7 @@ static void __exit cleanup_mtdram(void)
{
if (mtd_info) {
del_mtd_device(mtd_info);
- if (mtd_info->priv)
- vfree(mtd_info->priv);
+ vfree(mtd_info->priv);
kfree(mtd_info);
}
}
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index a423a382095a..765c0179c8df 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -22,6 +22,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args)
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index d9ab60b36fd4..d32c1b3a8ce3 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1017,27 +1017,16 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
void ftl_freepart(partition_t *part)
{
- if (part->VirtualBlockMap) {
vfree(part->VirtualBlockMap);
part->VirtualBlockMap = NULL;
- }
- if (part->VirtualPageMap) {
kfree(part->VirtualPageMap);
part->VirtualPageMap = NULL;
- }
- if (part->EUNInfo) {
kfree(part->EUNInfo);
part->EUNInfo = NULL;
- }
- if (part->XferInfo) {
kfree(part->XferInfo);
part->XferInfo = NULL;
- }
- if (part->bam_cache) {
kfree(part->bam_cache);
part->bam_cache = NULL;
- }
-
} /* ftl_freepart */
static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index 0c45464e3f7b..bfe994e59265 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -33,13 +33,13 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
-
+#include <linux/slab.h>
+#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <asm/arch/map.h>
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index da8584a662f4..c68b31dc7e6d 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -20,6 +20,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 938c41f2f056..e5b74169fde6 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index 0bc79c93a584..f99519692cb7 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -30,12 +30,15 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/string.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
+#include <asm/io.h>
+
/*
** The DIL/NetPC keeps its BIOS in two distinct flash blocks.
** Destroying any of these blocks transforms the DNPC into
diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c
index ab6dbe2b8cce..1df6188926b3 100644
--- a/drivers/mtd/maps/epxa10db-flash.c
+++ b/drivers/mtd/maps/epxa10db-flash.c
@@ -27,12 +27,15 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/slab.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
+#include <asm/io.h>
#include <asm/hardware.h>
+
#ifdef CONFIG_EPXA10DB
#define BOARD_NAME "EPXA10DB"
#else
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
index 068bb6a54520..00f7bbe5479e 100644
--- a/drivers/mtd/maps/fortunet.c
+++ b/drivers/mtd/maps/fortunet.c
@@ -7,11 +7,14 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/string.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+
#define MAX_NUM_REGIONS 4
#define MAX_NUM_PARTITIONS 8
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index e39a98a0171c..d14a0185b8f4 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -32,7 +32,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 3e94b616743d..00b9f67580f1 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -22,15 +22,17 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
#include <asm/io.h>
#include <asm/hardware.h>
-#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <linux/reboot.h>
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 5afe660aa2c4..733a9297a562 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -20,13 +20,16 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
+
#include <asm/io.h>
-#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <linux/reboot.h>
@@ -254,6 +257,6 @@ module_init(ixp4xx_flash_init);
module_exit(ixp4xx_flash_exit);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
+MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
MODULE_AUTHOR("Deepak Saxena");
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
index 1298de475c9a..2337e0c46750 100644
--- a/drivers/mtd/maps/lubbock-flash.c
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -15,10 +15,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
+
#include <linux/dma-mapping.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
+
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c
index 87e93fa60588..da0f8a692628 100644
--- a/drivers/mtd/maps/mainstone-flash.c
+++ b/drivers/mtd/maps/mainstone-flash.c
@@ -16,9 +16,12 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
+
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
index 496109071cb1..da36e8dddd17 100644
--- a/drivers/mtd/maps/omap-toto-flash.c
+++ b/drivers/mtd/maps/omap-toto-flash.c
@@ -12,9 +12,9 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 8cc71409a328..7f370bb794fe 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -30,19 +30,20 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/slab.h>
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
-#include <asm/mach-types.h>
#include <asm/mach/flash.h>
#include <asm/arch/tc.h>
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 18dbd3af1eaa..d9c64e99ee32 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 118b04544cad..104576b5be34 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -30,6 +30,8 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 52385705da09..c8d0da19d897 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
@@ -21,7 +21,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
-#include <asm/mach-types.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/mach/flash.h>
@@ -130,20 +130,21 @@ struct sa_subdev_info {
char name[16];
struct map_info map;
struct mtd_info *mtd;
- struct flash_platform_data *data;
+ struct flash_platform_data *plat;
};
struct sa_info {
struct mtd_partition *parts;
struct mtd_info *mtd;
int num_subdev;
+ unsigned int nr_parts;
struct sa_subdev_info subdev[0];
};
static void sa1100_set_vpp(struct map_info *map, int on)
{
struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
- subdev->data->set_vpp(on);
+ subdev->plat->set_vpp(on);
}
static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
@@ -187,7 +188,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
goto out;
}
- if (subdev->data->set_vpp)
+ if (subdev->plat->set_vpp)
subdev->map.set_vpp = sa1100_set_vpp;
subdev->map.phys = phys;
@@ -204,7 +205,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
* Now let's probe for the actual flash. Do it here since
* specific machine settings might have been set above.
*/
- subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
+ subdev->mtd = do_map_probe(subdev->plat->map_name, &subdev->map);
if (subdev->mtd == NULL) {
ret = -ENXIO;
goto err;
@@ -223,13 +224,17 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
return ret;
}
-static void sa1100_destroy(struct sa_info *info)
+static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *plat)
{
int i;
if (info->mtd) {
- del_mtd_partitions(info->mtd);
-
+ if (info->nr_parts == 0)
+ del_mtd_device(info->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+ else
+ del_mtd_partitions(info->mtd);
+#endif
#ifdef CONFIG_MTD_CONCAT
if (info->mtd != info->subdev[0].mtd)
mtd_concat_destroy(info->mtd);
@@ -242,10 +247,13 @@ static void sa1100_destroy(struct sa_info *info)
for (i = info->num_subdev - 1; i >= 0; i--)
sa1100_destroy_subdev(&info->subdev[i]);
kfree(info);
+
+ if (plat->exit)
+ plat->exit();
}
static struct sa_info *__init
-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
+sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
{
struct sa_info *info;
int nr, size, i, ret = 0;
@@ -275,6 +283,12 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
memset(info, 0, size);
+ if (plat->init) {
+ ret = plat->init();
+ if (ret)
+ goto err;
+ }
+
/*
* Claim and then map the memory regions.
*/
@@ -287,8 +301,8 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
break;
subdev->map.name = subdev->name;
- sprintf(subdev->name, "sa1100-%d", i);
- subdev->data = flash;
+ sprintf(subdev->name, "%s-%d", plat->name, i);
+ subdev->plat = plat;
ret = sa1100_probe_subdev(subdev, res);
if (ret)
@@ -309,7 +323,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
* otherwise fail. Either way, it'll be called "sa1100".
*/
if (info->num_subdev == 1) {
- strcpy(info->subdev[0].name, "sa1100");
+ strcpy(info->subdev[0].name, plat->name);
info->mtd = info->subdev[0].mtd;
ret = 0;
} else if (info->num_subdev > 1) {
@@ -322,7 +336,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
cdev[i] = info->subdev[i].mtd;
info->mtd = mtd_concat_create(cdev, info->num_subdev,
- "sa1100");
+ plat->name);
if (info->mtd == NULL)
ret = -ENXIO;
#else
@@ -336,7 +350,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
return info;
err:
- sa1100_destroy(info);
+ sa1100_destroy(info, plat);
out:
return ERR_PTR(ret);
}
@@ -346,16 +360,16 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static int __init sa1100_mtd_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct flash_platform_data *flash = pdev->dev.platform_data;
+ struct flash_platform_data *plat = pdev->dev.platform_data;
struct mtd_partition *parts;
const char *part_type = NULL;
struct sa_info *info;
int err, nr_parts = 0;
- if (!flash)
+ if (!plat)
return -ENODEV;
- info = sa1100_setup_mtd(pdev, flash);
+ info = sa1100_setup_mtd(pdev, plat);
if (IS_ERR(info)) {
err = PTR_ERR(info);
goto out;
@@ -372,8 +386,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
} else
#endif
{
- parts = flash->parts;
- nr_parts = flash->nr_parts;
+ parts = plat->parts;
+ nr_parts = plat->nr_parts;
part_type = "static";
}
@@ -387,6 +401,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
add_mtd_partitions(info->mtd, parts, nr_parts);
}
+ info->nr_parts = nr_parts;
+
dev_set_drvdata(dev, info);
err = 0;
@@ -397,33 +413,44 @@ static int __init sa1100_mtd_probe(struct device *dev)
static int __exit sa1100_mtd_remove(struct device *dev)
{
struct sa_info *info = dev_get_drvdata(dev);
+ struct flash_platform_data *plat = dev->platform_data;
+
dev_set_drvdata(dev, NULL);
- sa1100_destroy(info);
+ sa1100_destroy(info, plat);
+
return 0;
}
#ifdef CONFIG_PM
-static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100_mtd_suspend(struct device *dev, pm_message_t state)
{
struct sa_info *info = dev_get_drvdata(dev);
int ret = 0;
- if (info && level == SUSPEND_SAVE_STATE)
+ if (info)
ret = info->mtd->suspend(info->mtd);
return ret;
}
-static int sa1100_mtd_resume(struct device *dev, u32 level)
+static int sa1100_mtd_resume(struct device *dev)
{
struct sa_info *info = dev_get_drvdata(dev);
- if (info && level == RESUME_RESTORE_STATE)
+ if (info)
info->mtd->resume(info->mtd);
return 0;
}
+
+static void sa1100_mtd_shutdown(struct device *dev)
+{
+ struct sa_info *info = dev_get_drvdata(dev);
+ if (info && info->mtd->suspend(info->mtd) == 0)
+ info->mtd->resume(info->mtd);
+}
#else
#define sa1100_mtd_suspend NULL
#define sa1100_mtd_resume NULL
+#define sa1100_mtd_shutdown NULL
#endif
static struct device_driver sa1100_mtd_driver = {
@@ -433,6 +460,7 @@ static struct device_driver sa1100_mtd_driver = {
.remove = __exit_p(sa1100_mtd_remove),
.suspend = sa1100_mtd_suspend,
.resume = sa1100_mtd_resume,
+ .shutdown = sa1100_mtd_shutdown,
};
static int __init sa1100_mtd_init(void)
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index d15da6fd84c1..b7f093fbf9b0 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -82,7 +82,7 @@ int __init init_sharpsl(void)
} else if (machine_is_tosa()) {
sharpsl_partitions[0].size=0x006a0000;
sharpsl_partitions[0].offset=0x00160000;
- } else if (machine_is_spitz()) {
+ } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) {
sharpsl_partitions[0].size=0x006b0000;
sharpsl_partitions[0].offset=0x00140000;
} else {
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 995e9991cb8d..4e28b977f224 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -27,12 +27,14 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+
#define FLASH_ADDR 0x40000000
#define FLASH_SIZE 0x00800000
#define FLASH_BANK_MAX 4
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 811d92e5f5b1..cc372136e852 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -25,9 +25,6 @@
/****************************************************************************/
-
-/****************************************************************************/
-
struct map_info uclinux_ram_map = {
.name = "RAM",
};
@@ -60,14 +57,15 @@ int __init uclinux_mtd_init(void)
struct mtd_info *mtd;
struct map_info *mapp;
extern char _ebss;
+ unsigned long addr = (unsigned long) &_ebss;
mapp = &uclinux_ram_map;
- mapp->phys = (unsigned long) &_ebss;
- mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
+ mapp->phys = addr;
+ mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
mapp->bankwidth = 4;
printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
- (int) mapp->map_priv_2, (int) mapp->size);
+ (int) mapp->phys, (int) mapp->size);
mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
@@ -95,7 +93,6 @@ int __init uclinux_mtd_init(void)
printk("uclinux[mtd]: set %s to be root filesystem\n",
uclinux_romfs[0].name);
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
- put_mtd_device(mtd);
return(0);
}
@@ -109,7 +106,7 @@ void __exit uclinux_mtd_cleanup(void)
map_destroy(uclinux_ram_mtdinfo);
uclinux_ram_mtdinfo = NULL;
}
- if (uclinux_ram_map.map_priv_1) {
+ if (uclinux_ram_map.virt) {
iounmap((void *) uclinux_ram_map.virt);
uclinux_ram_map.virt = 0;
}
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index b7c32c242bc7..400dd9c89883 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/sched.h> /* TASK_* */
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 4b3c6263e7fc..8c0d94b72b63 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/sched.h> /* TASK_* */
#include <asm/uaccess.h>
#include <linux/device.h>
@@ -24,10 +25,10 @@ static void mtd_notify_add(struct mtd_info* mtd)
if (!mtd)
return;
- class_device_create(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
NULL, "mtd%d", mtd->index);
- class_device_create(mtd_class,
+ class_device_create(mtd_class, NULL,
MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
NULL, "mtd%dro", mtd->index);
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 8f66d093c80d..f3e65af33a9c 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -14,7 +14,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-
+#include <linux/sched.h> /* TASK_* */
#include <linux/mtd/mtd.h>
#include <linux/mtd/concat.h>
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index eee5115658c8..04e54318bc6a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -526,6 +526,7 @@ static void nand_wait_ready(struct mtd_info *mtd)
do {
if (this->dev_ready(mtd))
return;
+ touch_softlockup_watchdog();
} while (time_before(jiffies, timeo));
}
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 891e3a1b9110..2df5e47d1f5c 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -48,9 +48,10 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -58,7 +59,6 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/mach-types.h>
#include <asm/hardware/clock.h>
#include <asm/arch/regs-nand.h>
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 9853b87bb756..88b5b5b40b43 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -221,10 +221,16 @@ sharpsl_nand_init(void)
sharpsl_partition_info[1].size=25 * 1024 * 1024;
} else if (machine_is_husky()) {
sharpsl_partition_info[1].size=53 * 1024 * 1024;
- }
+ } else if (machine_is_spitz()) {
+ sharpsl_partition_info[1].size=5 * 1024 * 1024;
+ } else if (machine_is_akita()) {
+ sharpsl_partition_info[1].size=58 * 1024 * 1024;
+ } else if (machine_is_borzoi()) {
+ sharpsl_partition_info[1].size=32 * 1024 * 1024;
+ }
}
- if (machine_is_husky()) {
+ if (machine_is_husky() || machine_is_borzoi()) {
/* Need to use small eraseblock size for backward compatibility */
sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 07746b95fd83..455ba915ede7 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -973,6 +973,11 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
netif_device_detach(dev);
vortex_down(dev, 1);
}
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+ free_irq(dev->irq, dev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
return 0;
}
@@ -980,8 +985,19 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
static int vortex_resume (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ struct vortex_private *vp = netdev_priv(dev);
- if (dev && dev->priv) {
+ if (dev && vp) {
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ if (request_irq(dev->irq, vp->full_bus_master_rx ?
+ &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
+ printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+ pci_disable_device(pdev);
+ return -EBUSY;
+ }
if (netif_running(dev)) {
vortex_up(dev);
netif_device_attach(dev);
@@ -1873,6 +1889,7 @@ vortex_timer(unsigned long data)
{
spin_lock_bh(&vp->lock);
mii_status = mdio_read(dev, vp->phys[0], 1);
+ mii_status = mdio_read(dev, vp->phys[0], 1);
ok = 1;
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 7b293f01c9ed..f822cd3025ff 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -353,8 +353,6 @@ struct cp_private {
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
- struct cp_dma_stats *nic_stats;
- dma_addr_t nic_stats_dma;
unsigned rx_tail ____cacheline_aligned;
struct cp_desc *rx_ring;
@@ -1029,8 +1027,7 @@ static void cp_reset_hw (struct cp_private *cp)
if (!(cpr8(Cmd) & CmdReset))
return;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
}
printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1143,10 +1140,6 @@ static int cp_alloc_rings (struct cp_private *cp)
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
- mem += (CP_RING_BYTES - CP_STATS_SIZE);
- cp->nic_stats = mem;
- cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
-
return cp_init_rings(cp);
}
@@ -1187,7 +1180,6 @@ static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
- cp->nic_stats = NULL;
}
static int cp_open (struct net_device *dev)
@@ -1516,13 +1508,17 @@ static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = netdev_priv(dev);
+ struct cp_dma_stats *nic_stats;
+ dma_addr_t dma;
int i;
- memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+ nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
+ if (!nic_stats)
+ return;
/* begin NIC statistics dump */
- cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
- cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
+ cpw32(StatsAddr + 4, (u64)dma >> 32);
+ cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
cpr32(StatsAddr);
for (i = 0; i < 1000; i++) {
@@ -1532,24 +1528,27 @@ static void cp_get_ethtool_stats (struct net_device *dev,
}
cpw32(StatsAddr, 0);
cpw32(StatsAddr + 4, 0);
+ cpr32(StatsAddr);
i = 0;
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
if (i != CP_NUM_STATS)
BUG();
+
+ pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
static struct ethtool_ops cp_ethtool_ops = {
@@ -1575,6 +1574,7 @@ static struct ethtool_ops cp_ethtool_ops = {
.set_wol = cp_set_wol,
.get_strings = cp_get_strings,
.get_ethtool_stats = cp_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1773,6 +1773,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->open = cp_open;
dev->stop = cp_close;
@@ -1897,6 +1898,7 @@ static int cp_resume (struct pci_dev *pdev)
{
struct net_device *dev;
struct cp_private *cp;
+ unsigned long flags;
dev = pci_get_drvdata (pdev);
cp = netdev_priv(dev);
@@ -1910,6 +1912,12 @@ static int cp_resume (struct pci_dev *pdev)
cp_init_hw (cp);
netif_start_queue (dev);
+
+ spin_lock_irqsave (&cp->lock, flags);
+
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+
+ spin_unlock_irqrestore (&cp->lock, flags);
return 0;
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 4c2cf7bbd252..30bee11c48bd 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -552,7 +552,8 @@ const static struct {
{ "RTL-8100B/8139D",
HW_REVID(1, 1, 1, 0, 1, 0, 1),
- HasLWake,
+ HasHltClk /* XXX undocumented? */
+ | HasLWake,
},
{ "RTL-8101",
@@ -970,6 +971,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *) (dev->dev_addr))[i] =
le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* The Rtl8139-specific entries in the device structure. */
dev->open = rtl8139_open;
@@ -2465,6 +2467,7 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
.get_strings = rtl8139_get_strings,
.get_stats_count = rtl8139_get_stats_count,
.get_ethtool_stats = rtl8139_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 6d76f3a99b17..f87027420081 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -1094,7 +1094,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
- if (inb_p(e8390_base) & E8390_TRANS)
+ if (inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
{
printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
dev->name);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8a835eb58808..57edae4790e8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -131,6 +131,8 @@ config NET_SB1000
source "drivers/net/arcnet/Kconfig"
+source "drivers/net/phy/Kconfig"
+
#
# Ethernet
#
@@ -395,7 +397,7 @@ config SUN3LANCE
If you're not building a kernel for a Sun 3, say N.
config SUN3_82586
- tristate "Sun3 on-board Intel 82586 support"
+ bool "Sun3 on-board Intel 82586 support"
depends on NET_ETHERNET && SUN3
help
This driver enables support for the on-board Intel 82586 based
@@ -445,7 +447,7 @@ config NET_SB1250_MAC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && PCI && SGI_IP27
+ depends on NET_ETHERNET && PCI && SGI_IP27 && BROKEN
select CRC32
select MII
help
@@ -473,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
the moment only acceleration of IPv4 is supported. This option
enables offloading for checksums on transmit. If unsure, say Y.
+config MIPS_SIM_NET
+ tristate "MIPS simulator Network device (EXPERIMENTAL)"
+ depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
+ help
+ The MIPSNET device is a simple Ethernet network device which is
+ emulated by the MIPS Simulator.
+ If you are not using a MIPSsim or are unsure, say N.
+
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
depends on NET_ETHERNET && SGI_IP32=y
@@ -546,6 +556,14 @@ config SUNGEM
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
<http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
+config CASSINI
+ tristate "Sun Cassini support"
+ depends on NET_ETHERNET && PCI
+ select CRC32
+ help
+ Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+
config NET_VENDOR_3COM
bool "3COM cards"
depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
@@ -1145,38 +1163,74 @@ config IBMVETH
be called ibmveth.
config IBM_EMAC
- tristate "IBM PPC4xx EMAC driver support"
+ tristate "PowerPC 4xx on-chip Ethernet support"
depends on 4xx
- select CRC32
- ---help---
- This driver supports the IBM PPC4xx EMAC family of on-chip
- Ethernet controllers.
-
-config IBM_EMAC_ERRMSG
- bool "Verbose error messages"
- depends on IBM_EMAC
+ help
+ This driver supports the PowerPC 4xx EMAC family of on-chip
+ Ethernet controllers.
config IBM_EMAC_RXB
int "Number of receive buffers"
depends on IBM_EMAC
- default "128" if IBM_EMAC4
- default "64"
+ default "128"
config IBM_EMAC_TXB
int "Number of transmit buffers"
depends on IBM_EMAC
- default "128" if IBM_EMAC4
- default "8"
+ default "64"
+
+config IBM_EMAC_POLL_WEIGHT
+ int "MAL NAPI polling weight"
+ depends on IBM_EMAC
+ default "32"
-config IBM_EMAC_FGAP
- int "Frame gap"
+config IBM_EMAC_RX_COPY_THRESHOLD
+ int "RX skb copy threshold (bytes)"
depends on IBM_EMAC
- default "8"
+ default "256"
-config IBM_EMAC_SKBRES
- int "Skb reserve amount"
+config IBM_EMAC_RX_SKB_HEADROOM
+ int "Additional RX skb headroom (bytes)"
depends on IBM_EMAC
default "0"
+ help
+ Additional receive skb headroom. Note, that driver
+ will always reserve at least 2 bytes to make IP header
+ aligned, so usualy there is no need to add any additional
+ headroom.
+
+ If unsure, set to 0.
+
+config IBM_EMAC_PHY_RX_CLK_FIX
+ bool "PHY Rx clock workaround"
+ depends on IBM_EMAC && (405EP || 440GX || 440EP)
+ help
+ Enable this if EMAC attached to a PHY which doesn't generate
+ RX clock if there is no link, if this is the case, you will
+ see "TX disable timeout" or "RX disable timeout" in the system
+ log.
+
+ If unsure, say N.
+
+config IBM_EMAC_DEBUG
+ bool "Debugging"
+ depends on IBM_EMAC
+ default n
+
+config IBM_EMAC_ZMII
+ bool
+ depends on IBM_EMAC && (NP405H || NP405L || 44x)
+ default y
+
+config IBM_EMAC_RGMII
+ bool
+ depends on IBM_EMAC && 440GX
+ default y
+
+config IBM_EMAC_TAH
+ bool
+ depends on IBM_EMAC && 440GX
+ default y
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
@@ -1645,7 +1699,7 @@ config LAN_SAA9730
config NET_POCKET
bool "Pocket and portable adapters"
- depends on NET_ETHERNET && ISA
+ depends on NET_ETHERNET && PARPORT
---help---
Cute little network (Ethernet) devices which attach to the parallel
port ("pocket adapters"), commonly used with laptops. If you have
@@ -1669,7 +1723,7 @@ config NET_POCKET
config ATP
tristate "AT-LAN-TEC/RealTek pocket adapter support"
- depends on NET_POCKET && ISA && X86
+ depends on NET_POCKET && PARPORT && X86
select CRC32
---help---
This is a network (Ethernet) device which attaches to your parallel
@@ -1684,7 +1738,7 @@ config ATP
config DE600
tristate "D-Link DE600 pocket adapter support"
- depends on NET_POCKET && ISA
+ depends on NET_POCKET && PARPORT
---help---
This is a network (Ethernet) device which attaches to your parallel
port. Read <file:Documentation/networking/DLINK.txt> as well as the
@@ -1699,7 +1753,7 @@ config DE600
config DE620
tristate "D-Link DE620 pocket adapter support"
- depends on NET_POCKET && ISA
+ depends on NET_POCKET && PARPORT
---help---
This is a network (Ethernet) device which attaches to your parallel
port. Read <file:Documentation/networking/DLINK.txt> as well as the
@@ -1736,11 +1790,18 @@ config 68360_ENET
the Motorola 68360 processor.
config FEC
- bool "FEC ethernet controller (of ColdFire 5272)"
- depends on M5272 || M5282
+ bool "FEC ethernet controller (of ColdFire CPUs)"
+ depends on M523x || M527x || M5272 || M528x
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
- controller on the Motorola ColdFire 5272 processor.
+ controller on some Motorola ColdFire processors.
+
+config FEC2
+ bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+ depends on FEC
+ help
+ Say Y here if you want to use the second built-in 10/100 Fast
+ ethernet controller on some Motorola ColdFire processors.
config NE_H8300
tristate "NE2000 compatible support for H8/300"
@@ -1750,6 +1811,7 @@ config NE_H8300
controller on the Renesas H8/300 processor.
source "drivers/net/fec_8xx/Kconfig"
+source "drivers/net/fs_enet/Kconfig"
endmenu
@@ -1921,6 +1983,20 @@ config R8169_VLAN
If in doubt, say Y.
+config SIS190
+ tristate "SiS190/SiS191 gigabit ethernet support"
+ depends on PCI
+ select CRC32
+ select MII
+ ---help---
+ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+ appear in lan on motherboard designs which are based on SiS 965
+ and SiS 966 south bridge.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sis190. This is recommended.
+
config SKGE
tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
@@ -1928,7 +2004,7 @@ config SKGE
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
- driver with better performance and more complete ethtool support.
+ with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
@@ -2042,9 +2118,17 @@ config BNX2
To compile this driver as a module, choose M here: the module
will be called bnx2. This is recommended.
+config SPIDER_NET
+ tristate "Spider Gigabit Ethernet driver"
+ depends on PCI && PPC_BPA
+ help
+ This driver supports the Gigabit Ethernet chips present on the
+ Cell Processor-Based Blades from IBM.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
+ select PHYLIB
help
This driver supports the Gigabit TSEC on the MPC85xx
family of chips, and the FEC on the 8540
@@ -2091,6 +2175,25 @@ endmenu
menu "Ethernet (10000 Mbit)"
depends on !UML
+config CHELSIO_T1
+ tristate "Chelsio 10Gb Ethernet support"
+ depends on PCI
+ help
+ This driver supports Chelsio N110 and N210 models 10Gb Ethernet
+ cards. More information about adapter features and performance
+ tuning is in <file:Documentation/networking/cxgb.txt>.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.htm>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called cxgb.
+
config IXGB
tristate "Intel(R) PRO/10GbE support"
depends on PCI
@@ -2135,8 +2238,8 @@ config S2IO
depends on PCI
---help---
This driver supports the 10Gbe XFrame NIC of S2IO.
- For help regarding driver compilation, installation and
- tuning please look into ~/drivers/net/s2io/README.txt.
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/s2io.txt>.
config S2IO_NAPI
bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
@@ -2186,6 +2289,20 @@ config ISERIES_VETH
tristate "iSeries Virtual Ethernet driver support"
depends on PPC_ISERIES
+config RIONET
+ tristate "RapidIO Ethernet over messaging driver support"
+ depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+ int "Number of outbound queue entries"
+ depends on RIONET
+ default "128"
+
+config RIONET_RX_SIZE
+ int "Number of inbound queue entries"
+ depends on RIONET
+ default "128"
+
config FDDI
bool "FDDI driver support"
depends on (PCI || EISA)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 63c6d1e6d4d9..7c313cb341b8 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,10 +9,11 @@ endif
obj-$(CONFIG_E1000) += e1000/
obj-$(CONFIG_IBM_EMAC) += ibm_emac/
obj-$(CONFIG_IXGB) += ixgb/
+obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
#
# link order important here
@@ -27,6 +28,7 @@ obj-$(CONFIG_SUNQE) += sunqe.o
obj-$(CONFIG_SUNBMAC) += sunbmac.o
obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
+obj-$(CONFIG_CASSINI) += cassini.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_BMAC) += bmac.o
@@ -42,6 +44,7 @@ obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_E100) += e100.o
obj-$(CONFIG_TLAN) += tlan.o
obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SIS190) += sis190.o
obj-$(CONFIG_SIS900) += sis900.o
obj-$(CONFIG_YELLOWFIN) += yellowfin.o
obj-$(CONFIG_ACENIC) += acenic.o
@@ -52,6 +55,8 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BNX2) += bnx2.o
+spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SK98LIN) += sk98lin/
@@ -59,12 +64,14 @@ obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
#
# end link order section
#
obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_PHYLIB) += phy/
obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o
@@ -160,6 +167,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
@@ -195,3 +203,6 @@ obj-$(CONFIG_IRDA) += irda/
obj-$(CONFIG_ETRAX_ETHERNET) += cris/
obj-$(CONFIG_NETCONSOLE) += netconsole.o
+
+obj-$(CONFIG_FS_ENET) += fs_enet/
+
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 3707df6b0cfa..60304f7e7e5b 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -87,7 +87,6 @@ extern struct net_device *mvme147lance_probe(int unit);
extern struct net_device *tc515_probe(int unit);
extern struct net_device *lance_probe(int unit);
extern struct net_device *mace_probe(int unit);
-extern struct net_device *macsonic_probe(int unit);
extern struct net_device *mac8390_probe(int unit);
extern struct net_device *mac89x0_probe(int unit);
extern struct net_device *mc32_probe(int unit);
@@ -284,9 +283,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
#ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */
{mace_probe, 0},
#endif
-#ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */
- {macsonic_probe, 0},
-#endif
#ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */
{mac8390_probe, 0},
#endif
@@ -318,17 +314,9 @@ static void __init ethif_probe2(int unit)
#ifdef CONFIG_TR
/* Token-ring device probe */
extern int ibmtr_probe_card(struct net_device *);
-extern struct net_device *sk_isa_probe(int unit);
-extern struct net_device *proteon_probe(int unit);
extern struct net_device *smctr_probe(int unit);
static struct devprobe2 tr_probes2[] __initdata = {
-#ifdef CONFIG_SKISA
- {sk_isa_probe, 0},
-#endif
-#ifdef CONFIG_PROTEON
- {proteon_probe, 0},
-#endif
#ifdef CONFIG_SMCTR
{smctr_probe, 0},
#endif
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 91791ba37769..8a0af5453e21 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -275,7 +275,7 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev)
return 0;
out2:
if (ei_status.reg0)
- iounmap((void *)dev->mem_start);
+ iounmap(ei_status.mem);
out1:
free_irq(dev->irq, dev);
out:
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index dbecc6bf7851..b8953de5664a 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -871,10 +871,8 @@ static void ace_init_cleanup(struct net_device *dev)
if (ap->info)
pci_free_consistent(ap->pdev, sizeof(struct ace_info),
ap->info, ap->info_dma);
- if (ap->skb)
- kfree(ap->skb);
- if (ap->trace_buf)
- kfree(ap->trace_buf);
+ kfree(ap->skb);
+ kfree(ap->trace_buf);
if (dev->irq)
free_irq(dev->irq, dev);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index d9ba8be72af8..d9ba8be72af8 100755..100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index cfe3a4298822..cfe3a4298822 100755..100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 4f9f69e22c1b..12ef52c193a3 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -597,7 +597,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
struct ArcProto *proto;
int txbuf;
unsigned long flags;
- int freeskb = 0;
+ int freeskb, retval;
BUGMSG(D_DURING,
"transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
@@ -615,7 +615,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
dev_kfree_skb(skb);
- return 0; /* don't try again */
+ return NETDEV_TX_OK; /* don't try again */
}
/* We're busy transmitting a packet... */
@@ -623,8 +623,11 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
AINTMASK(0);
-
- txbuf = get_arcbuf(dev);
+ if(lp->next_tx == -1)
+ txbuf = get_arcbuf(dev);
+ else {
+ txbuf = -1;
+ }
if (txbuf != -1) {
if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
!proto->ack_tx) {
@@ -638,6 +641,8 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
lp->outgoing.skb = skb;
lp->outgoing.pkt = pkt;
+ freeskb = 0;
+
if (proto->continue_tx &&
proto->continue_tx(dev, txbuf)) {
BUGMSG(D_NORMAL,
@@ -645,10 +650,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
"(proto='%c')\n", proto->suffix);
}
}
-
+ retval = NETDEV_TX_OK;
+ dev->trans_start = jiffies;
lp->next_tx = txbuf;
} else {
- freeskb = 1;
+ retval = NETDEV_TX_BUSY;
+ freeskb = 0;
}
BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());
@@ -664,7 +671,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (freeskb) {
dev_kfree_skb(skb);
}
- return 0; /* no need to try again */
+ return retval; /* no need to try again */
}
@@ -690,7 +697,6 @@ static int go_tx(struct net_device *dev)
/* start sending */
ACOMMAND(TXcmd | (lp->cur_tx << 3));
- dev->trans_start = jiffies;
lp->stats.tx_packets++;
lp->lasttrans_dest = lp->lastload_dest;
lp->lastload_dest = 0;
@@ -917,6 +923,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
status);
+ /* MYRECON bit is at bit 7 of diagstatus */
+ if(diagstatus & 0x80)
+ BUGMSG(D_RECON,"Put out that recon myself\n");
/* is the RECON info empty or old? */
if (!lp->first_recon || !lp->last_recon ||
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 52c77cbe8c62..1f0302735416 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -160,7 +160,7 @@ static int __init com90io_probe(struct net_device *dev)
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
- BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n",
+ BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
@@ -242,7 +242,7 @@ static int __init com90io_found(struct net_device *dev)
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
- /* Reserve the I/O region - guaranteed to work by check_region */
+ /* Reserve the I/O region */
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 9b659e3c8d67..877891a29aaa 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -15,25 +15,22 @@
*/
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/bitops.h>
+#include <linux/platform_device.h>
-#include <asm/system.h>
-#include <asm/irq.h>
+#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/dma.h>
+#include <asm/system.h>
#define TX_BUFFERS 15
#define RX_BUFFERS 25
@@ -85,7 +82,7 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg)
u_short v;
__asm__(
"str%?h %1, [%2] @ NAT_RAP\n\t"
- "str%?h %0, [%2, #8] @ NET_IDP\n\t"
+ "ldr%?h %0, [%2, #8] @ NET_IDP\n\t"
: "=r" (v)
: "r" (reg), "r" (ISAIO_BASE + 0x0464));
return v;
@@ -283,12 +280,15 @@ static void am79c961_timer(unsigned long data)
lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
carrier = netif_carrier_ok(dev);
- if (lnkstat && !carrier)
+ if (lnkstat && !carrier) {
netif_carrier_on(dev);
- else if (!lnkstat && carrier)
+ printk("%s: link up\n", dev->name);
+ } else if (!lnkstat && carrier) {
netif_carrier_off(dev);
+ printk("%s: link down\n", dev->name);
+ }
- mod_timer(&priv->timer, jiffies + 5*HZ);
+ mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
}
/*
@@ -668,17 +668,25 @@ static void __init am79c961_banner(void)
printk(KERN_INFO "%s", version);
}
-static int __init am79c961_init(void)
+static int __init am79c961_probe(struct device *_dev)
{
+ struct platform_device *pdev = to_platform_device(_dev);
+ struct resource *res;
struct net_device *dev;
struct dev_priv *priv;
int i, ret;
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -ENODEV;
+
dev = alloc_etherdev(sizeof(struct dev_priv));
ret = -ENOMEM;
if (!dev)
goto out;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
priv = netdev_priv(dev);
/*
@@ -686,8 +694,8 @@ static int __init am79c961_init(void)
* The PNP initialisation should have been
* done by the ether bootp loader.
*/
- dev->base_addr = 0x220;
- dev->irq = IRQ_EBSA110_ETHERNET;
+ dev->base_addr = res->start;
+ dev->irq = platform_get_irq(pdev, 0);
ret = -ENODEV;
if (!request_region(dev->base_addr, 0x18, dev->name))
@@ -708,14 +716,10 @@ static int __init am79c961_init(void)
inb(dev->base_addr + 4) != 0x2b)
goto release;
- am79c961_banner();
- printk(KERN_INFO "%s: ether address ", dev->name);
-
- /* Retrive and print the ethernet address. */
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
- printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
- }
+
+ am79c961_banner();
spin_lock_init(&priv->chip_lock);
init_timer(&priv->timer);
@@ -736,8 +740,15 @@ static int __init am79c961_init(void)
#endif
ret = register_netdev(dev);
- if (ret == 0)
+ if (ret == 0) {
+ printk(KERN_INFO "%s: ether address ", dev->name);
+
+ /* Retrive and print the ethernet address. */
+ for (i = 0; i < 6; i++)
+ printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
+
return 0;
+ }
release:
release_region(dev->base_addr, 0x18);
@@ -747,4 +758,15 @@ out:
return ret;
}
+static struct device_driver am79c961_driver = {
+ .name = "am79c961",
+ .bus = &platform_bus_type,
+ .probe = am79c961_probe,
+};
+
+static int __init am79c961_init(void)
+{
+ return driver_register(&am79c961_driver);
+}
+
__initcall(am79c961_init);
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h
index 1e9b05050cbe..6a49ac7f6d46 100644
--- a/drivers/net/arm/am79c961a.h
+++ b/drivers/net/arm/am79c961a.h
@@ -143,6 +143,4 @@ struct dev_priv {
struct timer_list timer;
};
-extern int am79c961_probe (struct net_device *dev);
-
#endif
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index 1798ce7262c9..0095384ff454 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -155,7 +155,7 @@ static int bionet_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
static void bionet_tick(unsigned long);
-static struct timer_list bionet_timer = TIMER_INITIALIZER(bionet_tick, 0, 0);
+static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 81c362c8cb97..8b997809f9de 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -165,7 +165,7 @@ static void pamsnet_tick(unsigned long);
static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
-static struct timer_list pamsnet_timer = TIMER_INITIALIZER(pamsnet_tick, 0, 0);
+static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index ad011214c7f2..e01b6a78ec63 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -235,7 +235,7 @@ struct lance_private {
#define MEM lp->mem
#define DREG IO->data
#define AREG IO->addr
-#define REGA(a) ( AREG = (a), DREG )
+#define REGA(a) (*( AREG = (a), &DREG ))
/* Definitions for packet buffer access: */
#define PKT_BUF_SZ 1544
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c82b9cd1c924..332e9953c55c 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -151,13 +151,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
SUPPORTED_Autoneg
-static char *phy_link[] =
-{ "unknown",
- "10Base2", "10BaseT",
- "AUI",
- "100BaseT", "100BaseTX", "100BaseFX"
-};
-
int bcm_5201_init(struct net_device *dev, int phy_addr)
{
s16 data;
@@ -785,6 +778,7 @@ static struct mii_chip_info {
{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+ {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
@@ -1045,7 +1039,7 @@ found:
#endif
if (aup->mii->chip_info == NULL) {
- printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+ printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
dev->name);
return -1;
}
@@ -1546,6 +1540,9 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
printk(KERN_ERR "%s: out of memory\n", dev->name);
goto err_out;
}
+ aup->mii->next = NULL;
+ aup->mii->chip_info = NULL;
+ aup->mii->status = 0;
aup->mii->mii_control_reg = 0;
aup->mii->mii_data_reg = 0;
@@ -1609,8 +1606,7 @@ err_out:
/* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.*/
reset_mac(dev);
- if (aup->mii)
- kfree(aup->mii);
+ kfree(aup->mii);
for (i = 0; i < NUM_RX_DMA; i++) {
if (aup->rx_db_inuse[i])
ReleaseDB(aup, aup->rx_db_inuse[i]);
@@ -1809,8 +1805,7 @@ static void __exit au1000_cleanup_module(void)
if (dev) {
aup = (struct au1000_private *) dev->priv;
unregister_netdev(dev);
- if (aup->mii)
- kfree(aup->mii);
+ kfree(aup->mii);
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/b44.c b/drivers/net/b44.c
index 94939f570f78..0ee3e27969c6 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/version.h>
+#include <linux/dma-mapping.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -106,6 +107,29 @@ static int b44_poll(struct net_device *dev, int *budget);
static void b44_poll_controller(struct net_device *dev);
#endif
+static int dma_desc_align_mask;
+static int dma_desc_sync_size;
+
+static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
+ dma_addr_t dma_base,
+ unsigned long offset,
+ enum dma_data_direction dir)
+{
+ dma_sync_single_range_for_device(&pdev->dev, dma_base,
+ offset & dma_desc_align_mask,
+ dma_desc_sync_size, dir);
+}
+
+static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
+ dma_addr_t dma_base,
+ unsigned long offset,
+ enum dma_data_direction dir)
+{
+ dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
+ offset & dma_desc_align_mask,
+ dma_desc_sync_size, dir);
+}
+
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
{
return readl(bp->regs + reg);
@@ -668,6 +692,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dp->ctrl = cpu_to_le32(ctrl);
dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+ dest_idx * sizeof(dp),
+ DMA_BIDIRECTIONAL);
+
return RX_PKT_BUF_SZ;
}
@@ -692,6 +721,11 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
pci_unmap_addr_set(dest_map, mapping,
pci_unmap_addr(src_map, mapping));
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
+ src_idx * sizeof(src_desc),
+ DMA_BIDIRECTIONAL);
+
ctrl = src_desc->ctrl;
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -700,8 +734,14 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dest_desc->ctrl = ctrl;
dest_desc->addr = src_desc->addr;
+
src_map->skb = NULL;
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+ dest_idx * sizeof(dest_desc),
+ DMA_BIDIRECTIONAL);
+
pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
@@ -959,6 +999,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
+ if (bp->flags & B44_FLAG_TX_RING_HACK)
+ b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
+ entry * sizeof(bp->tx_ring[0]),
+ DMA_TO_DEVICE);
+
entry = NEXT_TX(entry);
bp->tx_prod = entry;
@@ -1064,6 +1109,16 @@ static void b44_init_rings(struct b44 *bp)
memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
+ if (bp->flags & B44_FLAG_RX_RING_HACK)
+ dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES,
+ PCI_DMA_BIDIRECTIONAL);
+
+ if (bp->flags & B44_FLAG_TX_RING_HACK)
+ dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES,
+ PCI_DMA_TODEVICE);
+
for (i = 0; i < bp->rx_pending; i++) {
if (b44_alloc_rx_skb(bp, -1, i) < 0)
break;
@@ -1076,23 +1131,33 @@ static void b44_init_rings(struct b44 *bp)
*/
static void b44_free_consistent(struct b44 *bp)
{
- if (bp->rx_buffers) {
- kfree(bp->rx_buffers);
- bp->rx_buffers = NULL;
- }
- if (bp->tx_buffers) {
- kfree(bp->tx_buffers);
- bp->tx_buffers = NULL;
- }
+ kfree(bp->rx_buffers);
+ bp->rx_buffers = NULL;
+ kfree(bp->tx_buffers);
+ bp->tx_buffers = NULL;
if (bp->rx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma);
+ if (bp->flags & B44_FLAG_RX_RING_HACK) {
+ dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
+ kfree(bp->rx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
+ bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
- pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma);
+ if (bp->flags & B44_FLAG_TX_RING_HACK) {
+ dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
+ kfree(bp->tx_ring);
+ } else
+ pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
+ bp->flags &= ~B44_FLAG_TX_RING_HACK;
}
}
@@ -1118,12 +1183,56 @@ static int b44_alloc_consistent(struct b44 *bp)
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
- if (!bp->rx_ring)
- goto out_err;
+ if (!bp->rx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+
+ if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(rx_ring, 0, size);
+ rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
+
+ if (rx_ring_dma + size > B44_DMA_MASK) {
+ kfree(rx_ring);
+ goto out_err;
+ }
+
+ bp->rx_ring = rx_ring;
+ bp->rx_ring_dma = rx_ring_dma;
+ bp->flags |= B44_FLAG_RX_RING_HACK;
+ }
bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
- if (!bp->tx_ring)
- goto out_err;
+ if (!bp->tx_ring) {
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *tx_ring;
+ dma_addr_t tx_ring_dma;
+
+ if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+ goto out_err;
+
+ memset(tx_ring, 0, size);
+ tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
+
+ if (tx_ring_dma + size > B44_DMA_MASK) {
+ kfree(tx_ring);
+ goto out_err;
+ }
+
+ bp->tx_ring = tx_ring;
+ bp->tx_ring_dma = tx_ring_dma;
+ bp->flags |= B44_FLAG_TX_RING_HACK;
+ }
return 0;
@@ -1507,14 +1616,14 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->advertising = 0;
if (bp->flags & B44_FLAG_ADV_10HALF)
- cmd->advertising |= ADVERTISE_10HALF;
+ cmd->advertising |= ADVERTISED_10baseT_Half;
if (bp->flags & B44_FLAG_ADV_10FULL)
- cmd->advertising |= ADVERTISE_10FULL;
+ cmd->advertising |= ADVERTISED_10baseT_Full;
if (bp->flags & B44_FLAG_ADV_100HALF)
- cmd->advertising |= ADVERTISE_100HALF;
+ cmd->advertising |= ADVERTISED_100baseT_Half;
if (bp->flags & B44_FLAG_ADV_100FULL)
- cmd->advertising |= ADVERTISE_100FULL;
- cmd->advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ cmd->advertising |= ADVERTISED_100baseT_Full;
+ cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ?
SPEED_100 : SPEED_10;
cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
@@ -1676,6 +1785,7 @@ static struct ethtool_ops b44_ethtool_ops = {
.set_pauseparam = b44_set_pauseparam,
.get_msglevel = b44_get_msglevel,
.set_msglevel = b44_set_msglevel,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1718,6 +1828,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->dev->dev_addr[3] = eeprom[80];
bp->dev->dev_addr[4] = eeprom[83];
bp->dev->dev_addr[5] = eeprom[82];
+ memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
bp->phy_addr = eeprom[90] & 0x1f;
@@ -1930,6 +2041,8 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
b44_free_rings(bp);
spin_unlock_irq(&bp->lock);
+
+ free_irq(dev->irq, dev);
pci_disable_device(pdev);
return 0;
}
@@ -1946,6 +2059,9 @@ static int b44_resume(struct pci_dev *pdev)
if (!netif_running(dev))
return 0;
+ if (request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev))
+ printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
+
spin_lock_irq(&bp->lock);
b44_init_rings(bp);
@@ -1971,6 +2087,12 @@ static struct pci_driver b44_driver = {
static int __init b44_init(void)
{
+ unsigned int dma_desc_align_size = dma_get_cache_alignment();
+
+ /* Setup paramaters for syncing RX/TX DMA descriptors */
+ dma_desc_align_mask = ~(dma_desc_align_size - 1);
+ dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+
return pci_module_init(&b44_driver);
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 11c40a2e71c7..593cb0ad4100 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -400,6 +400,8 @@ struct b44 {
#define B44_FLAG_ADV_100HALF 0x04000000
#define B44_FLAG_ADV_100FULL 0x08000000
#define B44_FLAG_INTERNAL_PHY 0x10000000
+#define B44_FLAG_RX_RING_HACK 0x20000000
+#define B44_FLAG_TX_RING_HACK 0x40000000
u32 rx_offset;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 8dc657fc8afb..bbca8ae8018c 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -218,7 +218,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
static inline
-volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
+unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
{
return in_le16((void __iomem *)dev->base_addr + reg_offset);
}
@@ -1658,6 +1658,7 @@ static struct of_device_id bmac_match[] =
},
{},
};
+MODULE_DEVICE_TABLE (of, bmac_match);
static struct macio_driver bmac_driver =
{
@@ -1689,10 +1690,8 @@ static void __exit bmac_exit(void)
{
macio_unregister_driver(&bmac_driver);
- if (bmac_emergency_rxbuf != NULL) {
- kfree(bmac_emergency_rxbuf);
- bmac_emergency_rxbuf = NULL;
- }
+ kfree(bmac_emergency_rxbuf);
+ bmac_emergency_rxbuf = NULL;
}
MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8acc655ec1e8..11d252318221 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -14,8 +14,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.2.19"
-#define DRV_MODULE_RELDATE "May 23, 2005"
+#define DRV_MODULE_VERSION "1.2.21"
+#define DRV_MODULE_RELDATE "September 7, 2005"
#define RUN_AT(x) (jiffies + (x))
@@ -52,7 +52,6 @@ static struct {
{ "HP NC370i Multifunction Gigabit Server Adapter" },
{ "Broadcom NetXtreme II BCM5706 1000Base-SX" },
{ "HP NC370F Multifunction Gigabit Server Adapter" },
- { 0 },
};
static struct pci_device_id bnx2_pci_tbl[] = {
@@ -108,6 +107,15 @@ static struct flash_spec flash_table[] =
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
+static inline u32 bnx2_tx_avail(struct bnx2 *bp)
+{
+ u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+
+ if (diff > MAX_TX_DESC_CNT)
+ diff = (diff & MAX_TX_DESC_CNT) - 1;
+ return (bp->tx_ring_size - diff);
+}
+
static u32
bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
{
@@ -306,20 +314,16 @@ bnx2_free_mem(struct bnx2 *bp)
bp->tx_desc_ring, bp->tx_desc_mapping);
bp->tx_desc_ring = NULL;
}
- if (bp->tx_buf_ring) {
- kfree(bp->tx_buf_ring);
- bp->tx_buf_ring = NULL;
- }
+ kfree(bp->tx_buf_ring);
+ bp->tx_buf_ring = NULL;
if (bp->rx_desc_ring) {
pci_free_consistent(bp->pdev,
sizeof(struct rx_bd) * RX_DESC_CNT,
bp->rx_desc_ring, bp->rx_desc_mapping);
bp->rx_desc_ring = NULL;
}
- if (bp->rx_buf_ring) {
- kfree(bp->rx_buf_ring);
- bp->rx_buf_ring = NULL;
- }
+ kfree(bp->rx_buf_ring);
+ bp->rx_buf_ring = NULL;
}
static int
@@ -807,7 +811,19 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
BMCR_ANENABLE);
- bp->serdes_an_pending = SERDES_AN_TIMEOUT / bp->timer_interval;
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ /* Speed up link-up time when the link partner
+ * does not autonegotiate which is very common
+ * in blade servers. Some blade servers use
+ * IPMI for kerboard input and it's important
+ * to minimize link disruptions. Autoneg. involves
+ * exchanging base pages plus 3 next pages and
+ * normally completes in about 120 msec.
+ */
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+ }
}
return 0;
@@ -1327,22 +1343,17 @@ bnx2_tx_int(struct bnx2 *bp)
}
}
- atomic_add(tx_free_bd, &bp->tx_avail_bd);
+ bp->tx_cons = sw_cons;
if (unlikely(netif_queue_stopped(bp->dev))) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->tx_lock, flags);
+ spin_lock(&bp->tx_lock);
if ((netif_queue_stopped(bp->dev)) &&
- (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)) {
+ (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
netif_wake_queue(bp->dev);
}
- spin_unlock_irqrestore(&bp->tx_lock, flags);
+ spin_unlock(&bp->tx_lock);
}
-
- bp->tx_cons = sw_cons;
-
}
static inline void
@@ -1518,20 +1529,18 @@ bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
struct net_device *dev = dev_instance;
struct bnx2 *bp = dev->priv;
+ prefetch(bp->status_blk);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
/* Return here if interrupt is disabled. */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- return IRQ_RETVAL(1);
- }
+ if (unlikely(atomic_read(&bp->intr_sem) != 0))
+ return IRQ_HANDLED;
- if (netif_rx_schedule_prep(dev)) {
- __netif_rx_schedule(dev);
- }
+ netif_rx_schedule(dev);
- return IRQ_RETVAL(1);
+ return IRQ_HANDLED;
}
static irqreturn_t
@@ -1546,25 +1555,22 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
* When using MSI, the MSI message will always complete after
* the status block write.
*/
- if ((bp->status_blk->status_idx == bp->last_status_idx) ||
+ if ((bp->status_blk->status_idx == bp->last_status_idx) &&
(REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
- return IRQ_RETVAL(0);
+ return IRQ_NONE;
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
/* Return here if interrupt is shared and is disabled. */
- if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
- return IRQ_RETVAL(1);
- }
+ if (unlikely(atomic_read(&bp->intr_sem) != 0))
+ return IRQ_HANDLED;
- if (netif_rx_schedule_prep(dev)) {
- __netif_rx_schedule(dev);
- }
+ netif_rx_schedule(dev);
- return IRQ_RETVAL(1);
+ return IRQ_HANDLED;
}
static int
@@ -1581,11 +1587,9 @@ bnx2_poll(struct net_device *dev, int *budget)
(bp->status_blk->status_attn_bits_ack &
STATUS_ATTN_BITS_LINK_STATE)) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock(&bp->phy_lock);
bnx2_phy_int(bp);
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock(&bp->phy_lock);
}
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) {
@@ -1628,9 +1632,8 @@ bnx2_set_rx_mode(struct net_device *dev)
struct bnx2 *bp = dev->priv;
u32 rx_mode, sort_mode;
int i;
- unsigned long flags;
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock_bh(&bp->phy_lock);
rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
@@ -1691,7 +1694,7 @@ bnx2_set_rx_mode(struct net_device *dev)
REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock_bh(&bp->phy_lock);
}
static void
@@ -1998,14 +2001,14 @@ bnx2_init_cpus(struct bnx2 *bp)
}
static int
-bnx2_set_power_state(struct bnx2 *bp, int state)
+bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
{
u16 pmcsr;
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
switch (state) {
- case 0: {
+ case PCI_D0: {
u32 val;
pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
@@ -2026,7 +2029,7 @@ bnx2_set_power_state(struct bnx2 *bp, int state)
REG_WR(bp, BNX2_RPM_CONFIG, val);
break;
}
- case 3: {
+ case PCI_D3hot: {
int i;
u32 val, wol_msg;
@@ -2960,7 +2963,6 @@ bnx2_init_tx_ring(struct bnx2 *bp)
bp->tx_prod = 0;
bp->tx_cons = 0;
bp->tx_prod_bseq = 0;
- atomic_set(&bp->tx_avail_bd, bp->tx_ring_size);
val = BNX2_L2CTX_TYPE_TYPE_L2;
val |= BNX2_L2CTX_TYPE_SIZE_L2;
@@ -3507,11 +3509,11 @@ bnx2_test_registers(struct bnx2 *bp)
rw_mask = reg_tbl[i].rw_mask;
ro_mask = reg_tbl[i].ro_mask;
- save_val = readl((u8 *) bp->regview + offset);
+ save_val = readl(bp->regview + offset);
- writel(0, (u8 *) bp->regview + offset);
+ writel(0, bp->regview + offset);
- val = readl((u8 *) bp->regview + offset);
+ val = readl(bp->regview + offset);
if ((val & rw_mask) != 0) {
goto reg_test_err;
}
@@ -3520,9 +3522,9 @@ bnx2_test_registers(struct bnx2 *bp)
goto reg_test_err;
}
- writel(0xffffffff, (u8 *) bp->regview + offset);
+ writel(0xffffffff, bp->regview + offset);
- val = readl((u8 *) bp->regview + offset);
+ val = readl(bp->regview + offset);
if ((val & rw_mask) != rw_mask) {
goto reg_test_err;
}
@@ -3531,11 +3533,11 @@ bnx2_test_registers(struct bnx2 *bp)
goto reg_test_err;
}
- writel(save_val, (u8 *) bp->regview + offset);
+ writel(save_val, bp->regview + offset);
continue;
reg_test_err:
- writel(save_val, (u8 *) bp->regview + offset);
+ writel(save_val, bp->regview + offset);
ret = -ENODEV;
break;
}
@@ -3752,10 +3754,10 @@ bnx2_test_link(struct bnx2 *bp)
{
u32 bmsr;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_read_phy(bp, MII_BMSR, &bmsr);
bnx2_read_phy(bp, MII_BMSR, &bmsr);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
if (bmsr & BMSR_LSTATUS) {
return 0;
@@ -3801,6 +3803,9 @@ bnx2_timer(unsigned long data)
struct bnx2 *bp = (struct bnx2 *) data;
u32 msg;
+ if (!netif_running(bp->dev))
+ return;
+
if (atomic_read(&bp->intr_sem) != 0)
goto bnx2_restart_timer;
@@ -3809,15 +3814,16 @@ bnx2_timer(unsigned long data)
if ((bp->phy_flags & PHY_SERDES_FLAG) &&
(CHIP_NUM(bp) == CHIP_NUM_5706)) {
- unsigned long flags;
- spin_lock_irqsave(&bp->phy_lock, flags);
+ spin_lock(&bp->phy_lock);
if (bp->serdes_an_pending) {
bp->serdes_an_pending--;
}
else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
u32 bmcr;
+ bp->current_interval = bp->timer_interval;
+
bnx2_read_phy(bp, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) {
@@ -3860,14 +3866,14 @@ bnx2_timer(unsigned long data)
}
}
+ else
+ bp->current_interval = bp->timer_interval;
- spin_unlock_irqrestore(&bp->phy_lock, flags);
+ spin_unlock(&bp->phy_lock);
}
bnx2_restart_timer:
- bp->timer.expires = RUN_AT(bp->timer_interval);
-
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
/* Called with rtnl_lock */
@@ -3877,7 +3883,7 @@ bnx2_open(struct net_device *dev)
struct bnx2 *bp = dev->priv;
int rc;
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
bnx2_disable_int(bp);
rc = bnx2_alloc_mem(bp);
@@ -3920,12 +3926,7 @@ bnx2_open(struct net_device *dev)
return rc;
}
- init_timer(&bp->timer);
-
- bp->timer.expires = RUN_AT(bp->timer_interval);
- bp->timer.data = (unsigned long) bp;
- bp->timer.function = bnx2_timer;
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
atomic_set(&bp->intr_sem, 0);
@@ -3976,12 +3977,17 @@ bnx2_reset_task(void *data)
{
struct bnx2 *bp = data;
+ if (!netif_running(bp->dev))
+ return;
+
+ bp->in_reset_task = 1;
bnx2_netif_stop(bp);
bnx2_init_nic(bp);
atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp);
+ bp->in_reset_task = 0;
}
static void
@@ -4041,9 +4047,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
u16 prod, ring_prod;
int i;
- if (unlikely(atomic_read(&bp->tx_avail_bd) <
- (skb_shinfo(skb)->nr_frags + 1))) {
-
+ if (unlikely(bnx2_tx_avail(bp) < (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
dev->name);
@@ -4140,8 +4144,6 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
prod = NEXT_TX_BD(prod);
bp->tx_prod_bseq += skb->len;
- atomic_sub(last_frag + 1, &bp->tx_avail_bd);
-
REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
@@ -4150,17 +4152,13 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
bp->tx_prod = prod;
dev->trans_start = jiffies;
- if (unlikely(atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS)) {
- unsigned long flags;
-
- spin_lock_irqsave(&bp->tx_lock, flags);
- if (atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS) {
- netif_stop_queue(dev);
-
- if (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)
- netif_wake_queue(dev);
- }
- spin_unlock_irqrestore(&bp->tx_lock, flags);
+ if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
+ spin_lock(&bp->tx_lock);
+ netif_stop_queue(dev);
+
+ if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+ netif_wake_queue(dev);
+ spin_unlock(&bp->tx_lock);
}
return NETDEV_TX_OK;
@@ -4173,7 +4171,13 @@ bnx2_close(struct net_device *dev)
struct bnx2 *bp = dev->priv;
u32 reset_code;
- flush_scheduled_work();
+ /* Calling flush_scheduled_work() may deadlock because
+ * linkwatch_event() may be on the workqueue and it will try to get
+ * the rtnl_lock which we are holding.
+ */
+ while (bp->in_reset_task)
+ msleep(1);
+
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
if (bp->wol)
@@ -4190,7 +4194,7 @@ bnx2_close(struct net_device *dev)
bnx2_free_mem(bp);
bp->link_up = 0;
netif_carrier_off(bp->dev);
- bnx2_set_power_state(bp, 3);
+ bnx2_set_power_state(bp, PCI_D3hot);
return 0;
}
@@ -4390,11 +4394,11 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
bp->req_line_speed = req_line_speed;
bp->req_duplex = req_duplex;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_setup_phy(bp);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4464,19 +4468,20 @@ bnx2_nway_reset(struct net_device *dev)
return -EINVAL;
}
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
/* Force a link down visible on the other side */
if (bp->phy_flags & PHY_SERDES_FLAG) {
bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
msleep(20);
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
if (CHIP_NUM(bp) == CHIP_NUM_5706) {
- bp->serdes_an_pending = SERDES_AN_TIMEOUT /
- bp->timer_interval;
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
}
}
@@ -4484,7 +4489,7 @@ bnx2_nway_reset(struct net_device *dev)
bmcr &= ~BMCR_LOOPBACK;
bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4670,11 +4675,11 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
bp->autoneg &= ~AUTONEG_FLOW_CTRL;
}
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
bnx2_setup_phy(bp);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4698,7 +4703,7 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
#define BNX2_NUM_STATS 45
-struct {
+static struct {
char string[ETH_GSTRING_LEN];
} bnx2_stats_str_arr[BNX2_NUM_STATS] = {
{ "rx_bytes" },
@@ -4750,7 +4755,7 @@ struct {
#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
-unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
+static unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
STATS_OFFSET32(stat_IfHCInOctets_hi),
STATS_OFFSET32(stat_IfHCInBadOctets_hi),
STATS_OFFSET32(stat_IfHCOutOctets_hi),
@@ -4801,7 +4806,7 @@ unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
* skipped because of errata.
*/
-u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
+static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
8,0,8,8,8,8,8,8,8,8,
4,0,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
@@ -4811,7 +4816,7 @@ u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
#define BNX2_NUM_TESTS 6
-struct {
+static struct {
char string[ETH_GSTRING_LEN];
} bnx2_tests_str_arr[BNX2_NUM_TESTS] = {
{ "register_test (offline)" },
@@ -4910,7 +4915,7 @@ bnx2_get_ethtool_stats(struct net_device *dev,
struct bnx2 *bp = dev->priv;
int i;
u32 *hw_stats = (u32 *) bp->stats_blk;
- u8 *stats_len_arr = 0;
+ u8 *stats_len_arr = NULL;
if (hw_stats == NULL) {
memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS);
@@ -5006,13 +5011,14 @@ static struct ethtool_ops bnx2_ethtool_ops = {
.phys_id = bnx2_phys_id,
.get_stats_count = bnx2_get_stats_count,
.get_ethtool_stats = bnx2_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/* Called with rtnl_lock */
static int
bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
+ struct mii_ioctl_data *data = if_mii(ifr);
struct bnx2 *bp = dev->priv;
int err;
@@ -5024,9 +5030,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: {
u32 mii_regval;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
data->val_out = mii_regval;
@@ -5037,9 +5043,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- spin_lock_irq(&bp->phy_lock);
+ spin_lock_bh(&bp->phy_lock);
err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
- spin_unlock_irq(&bp->phy_lock);
+ spin_unlock_bh(&bp->phy_lock);
return err;
@@ -5057,6 +5063,9 @@ bnx2_change_mac_addr(struct net_device *dev, void *p)
struct sockaddr *addr = p;
struct bnx2 *bp = dev->priv;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if (netif_running(dev))
bnx2_set_mac_addr(bp);
@@ -5192,7 +5201,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
@@ -5305,6 +5314,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->stats_ticks = 1000000 & 0xffff00;
bp->timer_interval = HZ;
+ bp->current_interval = HZ;
/* Disable WOL support if we are running on a SERDES chip. */
if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
@@ -5328,6 +5338,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->req_line_speed = 0;
if (bp->phy_flags & PHY_SERDES_FLAG) {
bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+ reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE +
+ BNX2_PORT_HW_CFG_CONFIG);
+ reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+ if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+ bp->autoneg = 0;
+ bp->req_line_speed = bp->line_speed = SPEED_1000;
+ bp->req_duplex = DUPLEX_FULL;
+ }
}
else {
bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
@@ -5335,11 +5354,17 @@ 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.data = (unsigned long) bp;
+ bp->timer.function = bnx2_timer;
+
return 0;
err_out_unmap:
if (bp->regview) {
iounmap(bp->regview);
+ bp->regview = NULL;
}
err_out_release:
@@ -5414,6 +5439,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
memcpy(dev->dev_addr, bp->mac_addr, 6);
+ memcpy(dev->perm_addr, bp->mac_addr, 6);
bp->name = board_info[ent->driver_data].name,
printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
"IRQ %d, ",
@@ -5454,6 +5480,8 @@ bnx2_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = dev->priv;
+ flush_scheduled_work();
+
unregister_netdev(dev);
if (bp->regview)
@@ -5466,7 +5494,7 @@ bnx2_remove_one(struct pci_dev *pdev)
}
static int
-bnx2_suspend(struct pci_dev *pdev, u32 state)
+bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = dev->priv;
@@ -5484,7 +5512,7 @@ bnx2_suspend(struct pci_dev *pdev, u32 state)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
bnx2_reset_chip(bp, reset_code);
bnx2_free_skbs(bp);
- bnx2_set_power_state(bp, state);
+ bnx2_set_power_state(bp, pci_choose_state(pdev, state));
return 0;
}
@@ -5497,7 +5525,7 @@ bnx2_resume(struct pci_dev *pdev)
if (!netif_running(dev))
return 0;
- bnx2_set_power_state(bp, 0);
+ bnx2_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
bnx2_init_nic(bp);
bnx2_netif_start(bp);
@@ -5505,12 +5533,12 @@ bnx2_resume(struct pci_dev *pdev)
}
static struct pci_driver bnx2_pci_driver = {
- name: DRV_MODULE_NAME,
- id_table: bnx2_pci_tbl,
- probe: bnx2_init_one,
- remove: __devexit_p(bnx2_remove_one),
- suspend: bnx2_suspend,
- resume: bnx2_resume,
+ .name = DRV_MODULE_NAME,
+ .id_table = bnx2_pci_tbl,
+ .probe = bnx2_init_one,
+ .remove = __devexit_p(bnx2_remove_one),
+ .suspend = bnx2_suspend,
+ .resume = bnx2_resume,
};
static int __init bnx2_init(void)
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 8214a2853d0d..62857b6a6ee4 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -50,6 +50,7 @@
#endif
#include <linux/workqueue.h>
#include <linux/crc32.h>
+#include <linux/prefetch.h>
/* Hardware data structures and register definitions automatically
* generated from RTL code. Do not modify.
@@ -3841,12 +3842,12 @@ struct bnx2 {
struct status_block *status_blk;
u32 last_status_idx;
- atomic_t tx_avail_bd;
struct tx_bd *tx_desc_ring;
struct sw_bd *tx_buf_ring;
u32 tx_prod_bseq;
u16 tx_prod;
u16 tx_cons;
+ int tx_ring_size;
#ifdef BCM_VLAN
struct vlan_group *vlgrp;
@@ -3872,8 +3873,10 @@ struct bnx2 {
char *name;
int timer_interval;
+ int current_interval;
struct timer_list timer;
struct work_struct reset_task;
+ int in_reset_task;
/* Used to synchronize phy accesses. */
spinlock_t phy_lock;
@@ -3927,7 +3930,6 @@ struct bnx2 {
u16 fw_wr_seq;
u16 fw_drv_pulse_wr_seq;
- int tx_ring_size;
dma_addr_t tx_desc_mapping;
@@ -3985,7 +3987,7 @@ struct bnx2 {
#define PHY_LOOPBACK 2
u8 serdes_an_pending;
-#define SERDES_AN_TIMEOUT (2 * HZ)
+#define SERDES_AN_TIMEOUT (HZ / 3)
u8 mac_addr[8];
@@ -4171,6 +4173,9 @@ struct fw_info {
#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a2e8dda5afac..d2f34d5a8083 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2419,22 +2419,19 @@ out:
return 0;
}
-int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev)
{
struct bonding *bond = dev->priv;
struct slave *slave = NULL;
int ret = NET_RX_DROP;
- if (!(dev->flags & IFF_MASTER)) {
+ if (!(dev->flags & IFF_MASTER))
goto out;
- }
read_lock(&bond->lock);
- slave = bond_get_slave_by_dev((struct bonding *)dev->priv,
- skb->real_dev);
- if (slave == NULL) {
+ slave = bond_get_slave_by_dev((struct bonding *)dev->priv, orig_dev);
+ if (!slave)
goto out_unlock;
- }
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index f46823894187..673a30af5660 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -295,6 +295,6 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype);
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 5ce606d9dc03..f8fce3961197 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -354,15 +354,14 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
_unlock_rx_hashtbl(bond);
}
-static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype)
+static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
{
struct bonding *bond = bond_dev->priv;
struct arp_pkt *arp = (struct arp_pkt *)skb->data;
int res = NET_RX_DROP;
- if (!(bond_dev->flags & IFF_MASTER)) {
+ if (!(bond_dev->flags & IFF_MASTER))
goto out;
- }
if (!arp) {
dprintk("Packet has no ARP data\n");
@@ -1106,18 +1105,13 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
}
}
- if (found) {
- /* a slave was found that is using the mac address
- * of the new slave
- */
- printk(KERN_ERR DRV_NAME
- ": Error: the hw address of slave %s is not "
- "unique - cannot enslave it!",
- slave->dev->name);
- return -EINVAL;
- }
+ if (!found)
+ return 0;
- return 0;
+ /* Try setting slave mac to bond address and fall-through
+ to code handling that situation below... */
+ alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
+ bond->alb_info.rlb_enabled);
}
/* The slave's address is equal to the address of the bond.
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2c930da90a85..8032126fd589 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -487,6 +487,8 @@
* * Added xmit_hash_policy_layer34()
* - Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4.
* Set version to 2.6.3.
+ * 2005/09/26 - Jay Vosburgh <fubar@us.ibm.com>
+ * - Removed backwards compatibility for old ifenslaves. Version 2.6.4.
*/
//#define BONDING_DEBUG 1
@@ -595,14 +597,7 @@ static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
static int lacp_fast = 0;
-static int app_abi_ver = 0;
-static int orig_app_abi_ver = -1; /* This is used to save the first ABI version
- * we receive from the application. Once set,
- * it won't be changed, and the module will
- * refuse to enslave/release interfaces if the
- * command comes from an application using
- * another ABI version.
- */
+
struct bond_parm_tbl {
char *modename;
int mode;
@@ -1294,12 +1289,13 @@ static void bond_mc_list_destroy(struct bonding *bond)
/*
* Copy all the Multicast addresses from src to the bonding device dst
*/
-static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, int gpf_flag)
+static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond,
+ gfp_t gfp_flag)
{
struct dev_mc_list *dmi, *new_dmi;
for (dmi = mc_list; dmi; dmi = dmi->next) {
- new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag);
+ new_dmi = kmalloc(sizeof(struct dev_mc_list), gfp_flag);
if (!new_dmi) {
/* FIXME: Potential memory leak !!! */
@@ -1604,6 +1600,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_
return 0;
}
+#define BOND_INTERSECT_FEATURES \
+ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+
+/*
+ * Compute the features available to the bonding device by
+ * intersection of all of the slave devices' BOND_INTERSECT_FEATURES.
+ * Call this after attaching or detaching a slave to update the
+ * bond's features.
+ */
+static int bond_compute_features(struct bonding *bond)
+{
+ int i;
+ struct slave *slave;
+ struct net_device *bond_dev = bond->dev;
+ int features = bond->bond_features;
+
+ bond_for_each_slave(bond, slave, i) {
+ struct net_device * slave_dev = slave->dev;
+ if (i == 0) {
+ features |= BOND_INTERSECT_FEATURES;
+ }
+ features &=
+ ~(~slave_dev->features & BOND_INTERSECT_FEATURES);
+ }
+
+ /* turn off NETIF_F_SG if we need a csum and h/w can't do it */
+ if ((features & NETIF_F_SG) &&
+ !(features & (NETIF_F_IP_CSUM |
+ NETIF_F_NO_CSUM |
+ NETIF_F_HW_CSUM))) {
+ features &= ~NETIF_F_SG;
+ }
+
+ bond_dev->features = features;
+
+ return 0;
+}
+
/* enslave device <slave> to bond device <master> */
static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
@@ -1615,7 +1649,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
int old_features = bond_dev->features;
int res = 0;
- if (slave_dev->do_ioctl == NULL) {
+ if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
+ slave_dev->do_ioctl == NULL) {
printk(KERN_WARNING DRV_NAME
": Warning : no link monitoring support for %s\n",
slave_dev->name);
@@ -1663,51 +1698,29 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
}
}
- if (app_abi_ver >= 1) {
- /* The application is using an ABI, which requires the
- * slave interface to be closed.
- */
- if ((slave_dev->flags & IFF_UP)) {
- printk(KERN_ERR DRV_NAME
- ": Error: %s is up\n",
- slave_dev->name);
- res = -EPERM;
- goto err_undo_flags;
- }
-
- if (slave_dev->set_mac_address == NULL) {
- printk(KERN_ERR DRV_NAME
- ": Error: The slave device you specified does "
- "not support setting the MAC address.\n");
- printk(KERN_ERR
- "Your kernel likely does not support slave "
- "devices.\n");
+ /*
+ * Old ifenslave binaries are no longer supported. These can
+ * be identified with moderate accurary by the state of the slave:
+ * the current ifenslave will set the interface down prior to
+ * enslaving it; the old ifenslave will not.
+ */
+ if ((slave_dev->flags & IFF_UP)) {
+ printk(KERN_ERR DRV_NAME ": %s is up. "
+ "This may be due to an out of date ifenslave.\n",
+ slave_dev->name);
+ res = -EPERM;
+ goto err_undo_flags;
+ }
- res = -EOPNOTSUPP;
- goto err_undo_flags;
- }
- } else {
- /* The application is not using an ABI, which requires the
- * slave interface to be open.
- */
- if (!(slave_dev->flags & IFF_UP)) {
- printk(KERN_ERR DRV_NAME
- ": Error: %s is not running\n",
- slave_dev->name);
- res = -EINVAL;
- goto err_undo_flags;
- }
+ if (slave_dev->set_mac_address == NULL) {
+ printk(KERN_ERR DRV_NAME
+ ": Error: The slave device you specified does "
+ "not support setting the MAC address.\n");
+ printk(KERN_ERR
+ "Your kernel likely does not support slave devices.\n");
- if ((bond->params.mode == BOND_MODE_8023AD) ||
- (bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
- printk(KERN_ERR DRV_NAME
- ": Error: to use %s mode, you must upgrade "
- "ifenslave.\n",
- bond_mode_name(bond->params.mode));
- res = -EOPNOTSUPP;
- goto err_undo_flags;
- }
+ res = -EOPNOTSUPP;
+ goto err_undo_flags;
}
new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
@@ -1723,41 +1736,36 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
*/
new_slave->original_flags = slave_dev->flags;
- if (app_abi_ver >= 1) {
- /* save slave's original ("permanent") mac address for
- * modes that needs it, and for restoring it upon release,
- * and then set it to the master's address
- */
- memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
+ /*
+ * Save slave's original ("permanent") mac address for modes
+ * that need it, and for restoring it upon release, and then
+ * set it to the master's address
+ */
+ memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
- /* set slave to master's mac address
- * The application already set the master's
- * mac address to that of the first slave
- */
- memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
- addr.sa_family = slave_dev->type;
- res = dev_set_mac_address(slave_dev, &addr);
- if (res) {
- dprintk("Error %d calling set_mac_address\n", res);
- goto err_free;
- }
+ /*
+ * Set slave to master's mac address. The application already
+ * set the master's mac address to that of the first slave
+ */
+ memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
+ addr.sa_family = slave_dev->type;
+ res = dev_set_mac_address(slave_dev, &addr);
+ if (res) {
+ dprintk("Error %d calling set_mac_address\n", res);
+ goto err_free;
+ }
- /* open the slave since the application closed it */
- res = dev_open(slave_dev);
- if (res) {
- dprintk("Openning slave %s failed\n", slave_dev->name);
- goto err_restore_mac;
- }
+ /* open the slave since the application closed it */
+ res = dev_open(slave_dev);
+ if (res) {
+ dprintk("Openning slave %s failed\n", slave_dev->name);
+ goto err_restore_mac;
}
res = netdev_set_master(slave_dev, bond_dev);
if (res) {
dprintk("Error %d calling netdev_set_master\n", res);
- if (app_abi_ver < 1) {
- goto err_free;
- } else {
- goto err_close;
- }
+ goto err_close;
}
new_slave->dev = slave_dev;
@@ -1811,6 +1819,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
new_slave->delay = 0;
new_slave->link_failure_count = 0;
+ bond_compute_features(bond);
+
if (bond->params.miimon && !bond->params.use_carrier) {
link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@@ -1956,39 +1966,6 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
write_unlock_bh(&bond->lock);
- if (app_abi_ver < 1) {
- /*
- * !!! This is to support old versions of ifenslave.
- * We can remove this in 2.5 because our ifenslave takes
- * care of this for us.
- * We check to see if the master has a mac address yet.
- * If not, we'll give it the mac address of our slave device.
- */
- int ndx = 0;
-
- for (ndx = 0; ndx < bond_dev->addr_len; ndx++) {
- dprintk("Checking ndx=%d of bond_dev->dev_addr\n",
- ndx);
- if (bond_dev->dev_addr[ndx] != 0) {
- dprintk("Found non-zero byte at ndx=%d\n",
- ndx);
- break;
- }
- }
-
- if (ndx == bond_dev->addr_len) {
- /*
- * We got all the way through the address and it was
- * all 0's.
- */
- dprintk("%s doesn't have a MAC address yet. \n",
- bond_dev->name);
- dprintk("Going to give assign it from %s.\n",
- slave_dev->name);
- bond_sethwaddr(bond_dev, slave_dev);
- }
- }
-
printk(KERN_INFO DRV_NAME
": %s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
@@ -2015,7 +1992,7 @@ err_free:
err_undo_flags:
bond_dev->features = old_features;
-
+
return res;
}
@@ -2100,6 +2077,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* release the slave from its bond */
bond_detach_slave(bond, slave);
+ bond_compute_features(bond);
+
if (bond->primary_slave == slave) {
bond->primary_slave = NULL;
}
@@ -2184,12 +2163,10 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* close slave before restoring its mac address */
dev_close(slave_dev);
- if (app_abi_ver >= 1) {
- /* restore original ("permanent") mac address */
- memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
- addr.sa_family = slave_dev->type;
- dev_set_mac_address(slave_dev, &addr);
- }
+ /* restore original ("permanent") mac address */
+ memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+ addr.sa_family = slave_dev->type;
+ dev_set_mac_address(slave_dev, &addr);
/* restore the original state of the
* IFF_NOARP flag that might have been
@@ -2243,6 +2220,8 @@ static int bond_release_all(struct net_device *bond_dev)
bond_alb_deinit_slave(bond, slave);
}
+ bond_compute_features(bond);
+
/* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from
* within a lock.
@@ -2275,12 +2254,10 @@ static int bond_release_all(struct net_device *bond_dev)
/* close slave before restoring its mac address */
dev_close(slave_dev);
- if (app_abi_ver >= 1) {
- /* restore original ("permanent") mac address*/
- memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
- addr.sa_family = slave_dev->type;
- dev_set_mac_address(slave_dev, &addr);
- }
+ /* restore original ("permanent") mac address*/
+ memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
+ addr.sa_family = slave_dev->type;
+ dev_set_mac_address(slave_dev, &addr);
/* restore the original state of the IFF_NOARP flag that might have
* been set by bond_set_slave_inactive_flags()
@@ -2378,57 +2355,6 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
return res;
}
-static int bond_ethtool_ioctl(struct net_device *bond_dev, struct ifreq *ifr)
-{
- struct ethtool_drvinfo info;
- void __user *addr = ifr->ifr_data;
- uint32_t cmd;
-
- if (get_user(cmd, (uint32_t __user *)addr)) {
- return -EFAULT;
- }
-
- switch (cmd) {
- case ETHTOOL_GDRVINFO:
- if (copy_from_user(&info, addr, sizeof(info))) {
- return -EFAULT;
- }
-
- if (strcmp(info.driver, "ifenslave") == 0) {
- int new_abi_ver;
- char *endptr;
-
- new_abi_ver = simple_strtoul(info.fw_version,
- &endptr, 0);
- if (*endptr) {
- printk(KERN_ERR DRV_NAME
- ": Error: got invalid ABI "
- "version from application\n");
-
- return -EINVAL;
- }
-
- if (orig_app_abi_ver == -1) {
- orig_app_abi_ver = new_abi_ver;
- }
-
- app_abi_ver = new_abi_ver;
- }
-
- strncpy(info.driver, DRV_NAME, 32);
- strncpy(info.version, DRV_VERSION, 32);
- snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
-
- if (copy_to_user(addr, &info, sizeof(info))) {
- return -EFAULT;
- }
-
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
{
struct bonding *bond = bond_dev->priv;
@@ -2731,7 +2657,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev)
return 0;
rcu_read_lock();
- idev = __in_dev_get(dev);
+ idev = __in_dev_get_rcu(dev);
if (!idev)
goto out;
@@ -2835,6 +2761,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
* This target is not on a VLAN
*/
if (rt->u.dst.dev == bond->dev) {
+ ip_rt_put(rt);
dprintk("basa: rtdev == bond->dev: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
@@ -2854,6 +2781,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
}
if (vlan_id) {
+ ip_rt_put(rt);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
vlan->vlan_ip, vlan_id);
continue;
@@ -2865,6 +2793,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
bond->dev->name, NIPQUAD(fl.fl4_dst),
rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
}
+ ip_rt_put(rt);
}
}
@@ -3394,16 +3323,11 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave
seq_printf(seq, "Link Failure Count: %d\n",
slave->link_failure_count);
- if (app_abi_ver >= 1) {
- seq_printf(seq,
- "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
- slave->perm_hwaddr[0],
- slave->perm_hwaddr[1],
- slave->perm_hwaddr[2],
- slave->perm_hwaddr[3],
- slave->perm_hwaddr[4],
- slave->perm_hwaddr[5]);
- }
+ seq_printf(seq,
+ "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ slave->perm_hwaddr[0], slave->perm_hwaddr[1],
+ slave->perm_hwaddr[2], slave->perm_hwaddr[3],
+ slave->perm_hwaddr[4], slave->perm_hwaddr[5]);
if (bond->params.mode == BOND_MODE_8023AD) {
const struct aggregator *agg
@@ -3588,6 +3512,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
{
struct net_device *bond_dev = slave_dev->master;
+ struct bonding *bond = bond_dev->priv;
switch (event) {
case NETDEV_UNREGISTER:
@@ -3626,6 +3551,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* TODO: handle changing the primary's name
*/
break;
+ case NETDEV_FEAT_CHANGE:
+ bond_compute_features(bond);
+ break;
default:
break;
}
@@ -3958,15 +3886,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
struct ifslave k_sinfo;
struct ifslave __user *u_sinfo = NULL;
struct mii_ioctl_data *mii = NULL;
- int prev_abi_ver = orig_app_abi_ver;
int res = 0;
dprintk("bond_ioctl: master=%s, cmd=%d\n",
bond_dev->name, cmd);
switch (cmd) {
- case SIOCETHTOOL:
- return bond_ethtool_ioctl(bond_dev, ifr);
case SIOCGMIIPHY:
mii = if_mii(ifr);
if (!mii) {
@@ -4038,21 +3963,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
return -EPERM;
}
- if (orig_app_abi_ver == -1) {
- /* no orig_app_abi_ver was provided yet, so we'll use the
- * current one from now on, even if it's 0
- */
- orig_app_abi_ver = app_abi_ver;
-
- } else if (orig_app_abi_ver != app_abi_ver) {
- printk(KERN_ERR DRV_NAME
- ": Error: already using ifenslave ABI version %d; to "
- "upgrade ifenslave to version %d, you must first "
- "reload bonding.\n",
- orig_app_abi_ver, app_abi_ver);
- return -EINVAL;
- }
-
slave_dev = dev_get_by_name(ifr->ifr_slave);
dprintk("slave_dev=%p: \n", slave_dev);
@@ -4085,14 +3995,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
dev_put(slave_dev);
}
- if (res < 0) {
- /* The ioctl failed, so there's no point in changing the
- * orig_app_abi_ver. We'll restore it's value just in case
- * we've changed it earlier in this function.
- */
- orig_app_abi_ver = prev_abi_ver;
- }
-
return res;
}
@@ -4339,6 +4241,43 @@ out:
return 0;
}
+static void bond_activebackup_xmit_copy(struct sk_buff *skb,
+ struct bonding *bond,
+ struct slave *slave)
+{
+ struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
+ struct ethhdr *eth_data;
+ u8 *hwaddr;
+ int res;
+
+ if (!skb2) {
+ printk(KERN_ERR DRV_NAME ": Error: "
+ "bond_activebackup_xmit_copy(): skb_copy() failed\n");
+ return;
+ }
+
+ skb2->mac.raw = (unsigned char *)skb2->data;
+ eth_data = eth_hdr(skb2);
+
+ /* Pick an appropriate source MAC address
+ * -- use slave's perm MAC addr, unless used by bond
+ * -- otherwise, borrow active slave's perm MAC addr
+ * since that will not be used
+ */
+ hwaddr = slave->perm_hwaddr;
+ if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
+ hwaddr = bond->curr_active_slave->perm_hwaddr;
+
+ /* Set source MAC address appropriately */
+ memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
+
+ res = bond_dev_queue_xmit(bond, skb2, slave->dev);
+ if (res)
+ dev_kfree_skb(skb2);
+
+ return;
+}
+
/*
* in active-backup mode, we know that bond->curr_active_slave is always valid if
* the bond has a usable interface.
@@ -4355,10 +4294,26 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
goto out;
}
- if (bond->curr_active_slave) { /* one usable interface */
- res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+ if (!bond->curr_active_slave)
+ goto out;
+
+ /* Xmit IGMP frames on all slaves to ensure rapid fail-over
+ for multicast traffic on snooping switches */
+ if (skb->protocol == __constant_htons(ETH_P_IP) &&
+ skb->nh.iph->protocol == IPPROTO_IGMP) {
+ struct slave *slave, *active_slave;
+ int i;
+
+ active_slave = bond->curr_active_slave;
+ bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
+ active_slave->prev)
+ if (IS_UP(slave->dev) &&
+ (slave->link == BOND_LINK_UP))
+ bond_activebackup_xmit_copy(skb, bond, slave);
}
+ res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+
out:
if (res) {
/* no suitable interface, frame not sent */
@@ -4526,6 +4481,20 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
}
}
+static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strncpy(drvinfo->driver, DRV_NAME, 32);
+ strncpy(drvinfo->version, DRV_VERSION, 32);
+ snprintf(drvinfo->fw_version, 32, "%d", BOND_ABI_VERSION);
+}
+
+static struct ethtool_ops bond_ethtool_ops = {
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .get_drvinfo = bond_ethtool_get_drvinfo,
+};
+
/*
* Does not allocate but creates a /proc entry.
* Allowed to fail.
@@ -4555,6 +4524,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
bond_dev->stop = bond_close;
bond_dev->get_stats = bond_get_stats;
bond_dev->do_ioctl = bond_do_ioctl;
+ bond_dev->ethtool_ops = &bond_ethtool_ops;
bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address;
@@ -4591,6 +4561,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
+ bond->bond_features = bond_dev->features;
+
#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
#endif
@@ -4980,6 +4952,14 @@ static int __init bonding_init(void)
return 0;
out_err:
+ /*
+ * rtnl_unlock() will run netdev_run_todo(), putting the
+ * thus-far-registered bonding devices into a state which
+ * unregigister_netdevice() will accept
+ */
+ rtnl_unlock();
+ rtnl_lock();
+
/* free and unregister all bonds that were successfully added */
bond_free_all();
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index d27f377b3eeb..bbf9da8af624 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -40,8 +40,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "2.6.3"
-#define DRV_RELDATE "June 8, 2005"
+#define DRV_VERSION "2.6.4"
+#define DRV_RELDATE "September 26, 2005"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -211,6 +211,9 @@ struct bonding {
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
+ /* the features the bonding device supports, independently
+ * of any slaves */
+ int bond_features;
};
/**
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 3d88ad622bdb..fb4098ed469e 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -323,33 +323,27 @@ static void bsd_reset (void *state)
*/
static void bsd_free (void *state)
- {
- struct bsd_db *db = (struct bsd_db *) state;
+{
+ struct bsd_db *db = state;
- if (db)
- {
+ if (!db)
+ return;
+
/*
* Release the dictionary
*/
- if (db->dict)
- {
- vfree (db->dict);
- db->dict = NULL;
- }
+ vfree(db->dict);
+ db->dict = NULL;
/*
* Release the string buffer
*/
- if (db->lens)
- {
- vfree (db->lens);
- db->lens = NULL;
- }
+ vfree(db->lens);
+ db->lens = NULL;
/*
* Finally release the structure itself.
*/
- kfree (db);
- }
- }
+ kfree(db);
+}
/*
* Allocate space for a (de) compressor.
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
new file mode 100644
index 000000000000..50f43dbf31ae
--- /dev/null
+++ b/drivers/net/cassini.c
@@ -0,0 +1,5237 @@
+/* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
+ *
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2003 Adrian Sun (asun@darksunrising.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.
+ *
+ * This driver uses the sungem driver (c) David Miller
+ * (davem@redhat.com) as its basis.
+ *
+ * The cassini chip has a number of features that distinguish it from
+ * the gem chip:
+ * 4 transmit descriptor rings that are used for either QoS (VLAN) or
+ * load balancing (non-VLAN mode)
+ * batching of multiple packets
+ * multiple CPU dispatching
+ * page-based RX descriptor engine with separate completion rings
+ * Gigabit support (GMII and PCS interface)
+ * MIF link up/down detection works
+ *
+ * RX is handled by page sized buffers that are attached as fragments to
+ * the skb. here's what's done:
+ * -- driver allocates pages at a time and keeps reference counts
+ * on them.
+ * -- the upper protocol layers assume that the header is in the skb
+ * itself. as a result, cassini will copy a small amount (64 bytes)
+ * to make them happy.
+ * -- driver appends the rest of the data pages as frags to skbuffs
+ * and increments the reference count
+ * -- on page reclamation, the driver swaps the page with a spare page.
+ * if that page is still in use, it frees its reference to that page,
+ * and allocates a new page for use. otherwise, it just recycles the
+ * the page.
+ *
+ * NOTE: cassini can parse the header. however, it's not worth it
+ * as long as the network stack requires a header copy.
+ *
+ * TX has 4 queues. currently these queues are used in a round-robin
+ * fashion for load balancing. They can also be used for QoS. for that
+ * to work, however, QoS information needs to be exposed down to the driver
+ * level so that subqueues get targetted to particular transmit rings.
+ * alternatively, the queues can be configured via use of the all-purpose
+ * ioctl.
+ *
+ * RX DATA: the rx completion ring has all the info, but the rx desc
+ * ring has all of the data. RX can conceivably come in under multiple
+ * interrupts, but the INT# assignment needs to be set up properly by
+ * the BIOS and conveyed to the driver. PCI BIOSes don't know how to do
+ * that. also, the two descriptor rings are designed to distinguish between
+ * encrypted and non-encrypted packets, but we use them for buffering
+ * instead.
+ *
+ * by default, the selective clear mask is set up to process rx packets.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
+#include <linux/mii.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <net/checksum.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define cas_page_map(x) kmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
+#define cas_page_unmap(x) kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
+#define CAS_NCPUS num_online_cpus()
+
+#if defined(CONFIG_CASSINI_NAPI) && defined(HAVE_NETDEV_POLL)
+#define USE_NAPI
+#define cas_skb_release(x) netif_receive_skb(x)
+#else
+#define cas_skb_release(x) netif_rx(x)
+#endif
+
+/* select which firmware to use */
+#define USE_HP_WORKAROUND
+#define HP_WORKAROUND_DEFAULT /* select which firmware to use as default */
+#define CAS_HP_ALT_FIRMWARE cas_prog_null /* alternate firmware */
+
+#include "cassini.h"
+
+#define USE_TX_COMPWB /* use completion writeback registers */
+#define USE_CSMA_CD_PROTO /* standard CSMA/CD */
+#define USE_RX_BLANK /* hw interrupt mitigation */
+#undef USE_ENTROPY_DEV /* don't test for entropy device */
+
+/* NOTE: these aren't useable unless PCI interrupts can be assigned.
+ * also, we need to make cp->lock finer-grained.
+ */
+#undef USE_PCI_INTB
+#undef USE_PCI_INTC
+#undef USE_PCI_INTD
+#undef USE_QOS
+
+#undef USE_VPD_DEBUG /* debug vpd information if defined */
+
+/* rx processing options */
+#define USE_PAGE_ORDER /* specify to allocate large rx pages */
+#define RX_DONT_BATCH 0 /* if 1, don't batch flows */
+#define RX_COPY_ALWAYS 0 /* if 0, use frags */
+#define RX_COPY_MIN 64 /* copy a little to make upper layers happy */
+#undef RX_COUNT_BUFFERS /* define to calculate RX buffer stats */
+
+#define DRV_MODULE_NAME "cassini"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.4"
+#define DRV_MODULE_RELDATE "1 July 2004"
+
+#define CAS_DEF_MSG_ENABLE \
+ (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)
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define CAS_TX_TIMEOUT (HZ)
+#define CAS_LINK_TIMEOUT (22*HZ/10)
+#define CAS_LINK_FAST_TIMEOUT (1)
+
+/* timeout values for state changing. these specify the number
+ * of 10us delays to be used before giving up.
+ */
+#define STOP_TRIES_PHY 1000
+#define STOP_TRIES 5000
+
+/* specify a minimum frame size to deal with some fifo issues
+ * max mtu == 2 * page size - ethernet header - 64 - swivel =
+ * 2 * page_size - 0x50
+ */
+#define CAS_MIN_FRAME 97
+#define CAS_1000MB_MIN_FRAME 255
+#define CAS_MIN_MTU 60
+#define CAS_MAX_MTU min(((cp->page_size << 1) - 0x50), 9000)
+
+#if 1
+/*
+ * Eliminate these and use separate atomic counters for each, to
+ * avoid a race condition.
+ */
+#else
+#define CAS_RESET_MTU 1
+#define CAS_RESET_ALL 2
+#define CAS_RESET_SPARE 3
+#endif
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
+MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(cassini_debug, "i");
+MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
+MODULE_PARM(link_mode, "i");
+MODULE_PARM_DESC(link_mode, "default link mode");
+
+/*
+ * Work around for a PCS bug in which the link goes down due to the chip
+ * being confused and never showing a link status of "up."
+ */
+#define DEFAULT_LINKDOWN_TIMEOUT 5
+/*
+ * Value in seconds, for user input.
+ */
+static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT;
+MODULE_PARM(linkdown_timeout, "i");
+MODULE_PARM_DESC(linkdown_timeout,
+"min reset interval in sec. for PCS linkdown issue; disabled if not positive");
+
+/*
+ * value in 'ticks' (units used by jiffies). Set when we init the
+ * module because 'HZ' in actually a function call on some flavors of
+ * Linux. This will default to DEFAULT_LINKDOWN_TIMEOUT * HZ.
+ */
+static int link_transition_timeout;
+
+
+static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
+static int link_mode;
+
+static u16 link_modes[] __devinitdata = {
+ BMCR_ANENABLE, /* 0 : autoneg */
+ 0, /* 1 : 10bt half duplex */
+ BMCR_SPEED100, /* 2 : 100bt half duplex */
+ BMCR_FULLDPLX, /* 3 : 10bt full duplex */
+ BMCR_SPEED100|BMCR_FULLDPLX, /* 4 : 100bt full duplex */
+ CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */
+};
+
+static struct pci_device_id cas_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cas_pci_tbl);
+
+static void cas_set_link_modes(struct cas *cp);
+
+static inline void cas_lock_tx(struct cas *cp)
+{
+ int i;
+
+ for (i = 0; i < N_TX_RINGS; i++)
+ spin_lock(&cp->tx_lock[i]);
+}
+
+static inline void cas_lock_all(struct cas *cp)
+{
+ spin_lock_irq(&cp->lock);
+ cas_lock_tx(cp);
+}
+
+/* WTZ: QA was finding deadlock problems with the previous
+ * versions after long test runs with multiple cards per machine.
+ * See if replacing cas_lock_all with safer versions helps. The
+ * symptoms QA is reporting match those we'd expect if interrupts
+ * aren't being properly restored, and we fixed a previous deadlock
+ * with similar symptoms by using save/restore versions in other
+ * places.
+ */
+#define cas_lock_all_save(cp, flags) \
+do { \
+ struct cas *xxxcp = (cp); \
+ spin_lock_irqsave(&xxxcp->lock, flags); \
+ cas_lock_tx(xxxcp); \
+} while (0)
+
+static inline void cas_unlock_tx(struct cas *cp)
+{
+ int i;
+
+ for (i = N_TX_RINGS; i > 0; i--)
+ spin_unlock(&cp->tx_lock[i - 1]);
+}
+
+static inline void cas_unlock_all(struct cas *cp)
+{
+ cas_unlock_tx(cp);
+ spin_unlock_irq(&cp->lock);
+}
+
+#define cas_unlock_all_restore(cp, flags) \
+do { \
+ struct cas *xxxcp = (cp); \
+ cas_unlock_tx(xxxcp); \
+ spin_unlock_irqrestore(&xxxcp->lock, flags); \
+} while (0)
+
+static void cas_disable_irq(struct cas *cp, const int ring)
+{
+ /* Make sure we won't get any more interrupts */
+ if (ring == 0) {
+ writel(0xFFFFFFFF, cp->regs + REG_INTR_MASK);
+ return;
+ }
+
+ /* disable completion interrupts and selectively mask */
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ switch (ring) {
+#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+#ifdef USE_PCI_INTB
+ case 1:
+#endif
+#ifdef USE_PCI_INTC
+ case 2:
+#endif
+#ifdef USE_PCI_INTD
+ case 3:
+#endif
+ writel(INTRN_MASK_CLEAR_ALL | INTRN_MASK_RX_EN,
+ cp->regs + REG_PLUS_INTRN_MASK(ring));
+ break;
+#endif
+ default:
+ writel(INTRN_MASK_CLEAR_ALL, cp->regs +
+ REG_PLUS_INTRN_MASK(ring));
+ break;
+ }
+ }
+}
+
+static inline void cas_mask_intr(struct cas *cp)
+{
+ int i;
+
+ for (i = 0; i < N_RX_COMP_RINGS; i++)
+ cas_disable_irq(cp, i);
+}
+
+static void cas_enable_irq(struct cas *cp, const int ring)
+{
+ if (ring == 0) { /* all but TX_DONE */
+ writel(INTR_TX_DONE, cp->regs + REG_INTR_MASK);
+ return;
+ }
+
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ switch (ring) {
+#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+#ifdef USE_PCI_INTB
+ case 1:
+#endif
+#ifdef USE_PCI_INTC
+ case 2:
+#endif
+#ifdef USE_PCI_INTD
+ case 3:
+#endif
+ writel(INTRN_MASK_RX_EN, cp->regs +
+ REG_PLUS_INTRN_MASK(ring));
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+static inline void cas_unmask_intr(struct cas *cp)
+{
+ int i;
+
+ for (i = 0; i < N_RX_COMP_RINGS; i++)
+ cas_enable_irq(cp, i);
+}
+
+static inline void cas_entropy_gather(struct cas *cp)
+{
+#ifdef USE_ENTROPY_DEV
+ if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
+ return;
+
+ batch_entropy_store(readl(cp->regs + REG_ENTROPY_IV),
+ readl(cp->regs + REG_ENTROPY_IV),
+ sizeof(uint64_t)*8);
+#endif
+}
+
+static inline void cas_entropy_reset(struct cas *cp)
+{
+#ifdef USE_ENTROPY_DEV
+ if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
+ return;
+
+ writel(BIM_LOCAL_DEV_PAD | BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_EXT,
+ cp->regs + REG_BIM_LOCAL_DEV_EN);
+ writeb(ENTROPY_RESET_STC_MODE, cp->regs + REG_ENTROPY_RESET);
+ writeb(0x55, cp->regs + REG_ENTROPY_RAND_REG);
+
+ /* if we read back 0x0, we don't have an entropy device */
+ if (readb(cp->regs + REG_ENTROPY_RAND_REG) == 0)
+ cp->cas_flags &= ~CAS_FLAG_ENTROPY_DEV;
+#endif
+}
+
+/* access to the phy. the following assumes that we've initialized the MIF to
+ * be in frame rather than bit-bang mode
+ */
+static u16 cas_phy_read(struct cas *cp, int reg)
+{
+ u32 cmd;
+ int limit = STOP_TRIES_PHY;
+
+ cmd = MIF_FRAME_ST | MIF_FRAME_OP_READ;
+ cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
+ cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
+ cmd |= MIF_FRAME_TURN_AROUND_MSB;
+ writel(cmd, cp->regs + REG_MIF_FRAME);
+
+ /* poll for completion */
+ while (limit-- > 0) {
+ udelay(10);
+ cmd = readl(cp->regs + REG_MIF_FRAME);
+ if (cmd & MIF_FRAME_TURN_AROUND_LSB)
+ return (cmd & MIF_FRAME_DATA_MASK);
+ }
+ return 0xFFFF; /* -1 */
+}
+
+static int cas_phy_write(struct cas *cp, int reg, u16 val)
+{
+ int limit = STOP_TRIES_PHY;
+ u32 cmd;
+
+ cmd = MIF_FRAME_ST | MIF_FRAME_OP_WRITE;
+ cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
+ cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
+ cmd |= MIF_FRAME_TURN_AROUND_MSB;
+ cmd |= val & MIF_FRAME_DATA_MASK;
+ writel(cmd, cp->regs + REG_MIF_FRAME);
+
+ /* poll for completion */
+ while (limit-- > 0) {
+ udelay(10);
+ cmd = readl(cp->regs + REG_MIF_FRAME);
+ if (cmd & MIF_FRAME_TURN_AROUND_LSB)
+ return 0;
+ }
+ return -1;
+}
+
+static void cas_phy_powerup(struct cas *cp)
+{
+ u16 ctl = cas_phy_read(cp, MII_BMCR);
+
+ if ((ctl & BMCR_PDOWN) == 0)
+ return;
+ ctl &= ~BMCR_PDOWN;
+ cas_phy_write(cp, MII_BMCR, ctl);
+}
+
+static void cas_phy_powerdown(struct cas *cp)
+{
+ u16 ctl = cas_phy_read(cp, MII_BMCR);
+
+ if (ctl & BMCR_PDOWN)
+ return;
+ ctl |= BMCR_PDOWN;
+ cas_phy_write(cp, MII_BMCR, ctl);
+}
+
+/* cp->lock held. note: the last put_page will free the buffer */
+static int cas_page_free(struct cas *cp, cas_page_t *page)
+{
+ pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size,
+ PCI_DMA_FROMDEVICE);
+ __free_pages(page->buffer, cp->page_order);
+ kfree(page);
+ return 0;
+}
+
+#ifdef RX_COUNT_BUFFERS
+#define RX_USED_ADD(x, y) ((x)->used += (y))
+#define RX_USED_SET(x, y) ((x)->used = (y))
+#else
+#define RX_USED_ADD(x, y)
+#define RX_USED_SET(x, y)
+#endif
+
+/* local page allocation routines for the receive buffers. jumbo pages
+ * require at least 8K contiguous and 8K aligned buffers.
+ */
+static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
+{
+ cas_page_t *page;
+
+ page = kmalloc(sizeof(cas_page_t), flags);
+ if (!page)
+ return NULL;
+
+ INIT_LIST_HEAD(&page->list);
+ RX_USED_SET(page, 0);
+ page->buffer = alloc_pages(flags, cp->page_order);
+ if (!page->buffer)
+ goto page_err;
+ page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
+ cp->page_size, PCI_DMA_FROMDEVICE);
+ return page;
+
+page_err:
+ kfree(page);
+ return NULL;
+}
+
+/* initialize spare pool of rx buffers, but allocate during the open */
+static void cas_spare_init(struct cas *cp)
+{
+ spin_lock(&cp->rx_inuse_lock);
+ INIT_LIST_HEAD(&cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+
+ spin_lock(&cp->rx_spare_lock);
+ INIT_LIST_HEAD(&cp->rx_spare_list);
+ cp->rx_spares_needed = RX_SPARE_COUNT;
+ spin_unlock(&cp->rx_spare_lock);
+}
+
+/* used on close. free all the spare buffers. */
+static void cas_spare_free(struct cas *cp)
+{
+ struct list_head list, *elem, *tmp;
+
+ /* free spare buffers */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_spare_lock);
+ list_splice(&cp->rx_spare_list, &list);
+ INIT_LIST_HEAD(&cp->rx_spare_list);
+ spin_unlock(&cp->rx_spare_lock);
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_free(cp, list_entry(elem, cas_page_t, list));
+ }
+
+ INIT_LIST_HEAD(&list);
+#if 1
+ /*
+ * Looks like Adrian had protected this with a different
+ * lock than used everywhere else to manipulate this list.
+ */
+ spin_lock(&cp->rx_inuse_lock);
+ list_splice(&cp->rx_inuse_list, &list);
+ INIT_LIST_HEAD(&cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+#else
+ spin_lock(&cp->rx_spare_lock);
+ list_splice(&cp->rx_inuse_list, &list);
+ INIT_LIST_HEAD(&cp->rx_inuse_list);
+ spin_unlock(&cp->rx_spare_lock);
+#endif
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_free(cp, list_entry(elem, cas_page_t, list));
+ }
+}
+
+/* replenish spares if needed */
+static void cas_spare_recover(struct cas *cp, const gfp_t flags)
+{
+ struct list_head list, *elem, *tmp;
+ int needed, i;
+
+ /* check inuse list. if we don't need any more free buffers,
+ * just free it
+ */
+
+ /* make a local copy of the list */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_inuse_lock);
+ list_splice(&cp->rx_inuse_list, &list);
+ INIT_LIST_HEAD(&cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_t *page = list_entry(elem, cas_page_t, list);
+
+ if (page_count(page->buffer) > 1)
+ continue;
+
+ list_del(elem);
+ spin_lock(&cp->rx_spare_lock);
+ if (cp->rx_spares_needed > 0) {
+ list_add(elem, &cp->rx_spare_list);
+ cp->rx_spares_needed--;
+ spin_unlock(&cp->rx_spare_lock);
+ } else {
+ spin_unlock(&cp->rx_spare_lock);
+ cas_page_free(cp, page);
+ }
+ }
+
+ /* put any inuse buffers back on the list */
+ if (!list_empty(&list)) {
+ spin_lock(&cp->rx_inuse_lock);
+ list_splice(&list, &cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+ }
+
+ spin_lock(&cp->rx_spare_lock);
+ needed = cp->rx_spares_needed;
+ spin_unlock(&cp->rx_spare_lock);
+ if (!needed)
+ return;
+
+ /* we still need spares, so try to allocate some */
+ INIT_LIST_HEAD(&list);
+ i = 0;
+ while (i < needed) {
+ cas_page_t *spare = cas_page_alloc(cp, flags);
+ if (!spare)
+ break;
+ list_add(&spare->list, &list);
+ i++;
+ }
+
+ spin_lock(&cp->rx_spare_lock);
+ list_splice(&list, &cp->rx_spare_list);
+ cp->rx_spares_needed -= i;
+ spin_unlock(&cp->rx_spare_lock);
+}
+
+/* pull a page from the list. */
+static cas_page_t *cas_page_dequeue(struct cas *cp)
+{
+ struct list_head *entry;
+ int recover;
+
+ spin_lock(&cp->rx_spare_lock);
+ if (list_empty(&cp->rx_spare_list)) {
+ /* try to do a quick recovery */
+ spin_unlock(&cp->rx_spare_lock);
+ cas_spare_recover(cp, GFP_ATOMIC);
+ spin_lock(&cp->rx_spare_lock);
+ if (list_empty(&cp->rx_spare_list)) {
+ if (netif_msg_rx_err(cp))
+ printk(KERN_ERR "%s: no spare buffers "
+ "available.\n", cp->dev->name);
+ spin_unlock(&cp->rx_spare_lock);
+ return NULL;
+ }
+ }
+
+ entry = cp->rx_spare_list.next;
+ list_del(entry);
+ recover = ++cp->rx_spares_needed;
+ spin_unlock(&cp->rx_spare_lock);
+
+ /* trigger the timer to do the recovery */
+ if ((recover & (RX_SPARE_RECOVER_VAL - 1)) == 0) {
+#if 1
+ atomic_inc(&cp->reset_task_pending);
+ atomic_inc(&cp->reset_task_pending_spare);
+ schedule_work(&cp->reset_task);
+#else
+ atomic_set(&cp->reset_task_pending, CAS_RESET_SPARE);
+ schedule_work(&cp->reset_task);
+#endif
+ }
+ return list_entry(entry, cas_page_t, list);
+}
+
+
+static void cas_mif_poll(struct cas *cp, const int enable)
+{
+ u32 cfg;
+
+ cfg = readl(cp->regs + REG_MIF_CFG);
+ cfg &= (MIF_CFG_MDIO_0 | MIF_CFG_MDIO_1);
+
+ if (cp->phy_type & CAS_PHY_MII_MDIO1)
+ cfg |= MIF_CFG_PHY_SELECT;
+
+ /* poll and interrupt on link status change. */
+ if (enable) {
+ cfg |= MIF_CFG_POLL_EN;
+ cfg |= CAS_BASE(MIF_CFG_POLL_REG, MII_BMSR);
+ cfg |= CAS_BASE(MIF_CFG_POLL_PHY, cp->phy_addr);
+ }
+ writel((enable) ? ~(BMSR_LSTATUS | BMSR_ANEGCOMPLETE) : 0xFFFF,
+ cp->regs + REG_MIF_MASK);
+ writel(cfg, cp->regs + REG_MIF_CFG);
+}
+
+/* Must be invoked under cp->lock */
+static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep)
+{
+ u16 ctl;
+#if 1
+ int lcntl;
+ int changed = 0;
+ int oldstate = cp->lstate;
+ int link_was_not_down = !(oldstate == link_down);
+#endif
+ /* Setup link parameters */
+ if (!ep)
+ goto start_aneg;
+ lcntl = cp->link_cntl;
+ if (ep->autoneg == AUTONEG_ENABLE)
+ cp->link_cntl = BMCR_ANENABLE;
+ else {
+ cp->link_cntl = 0;
+ if (ep->speed == SPEED_100)
+ cp->link_cntl |= BMCR_SPEED100;
+ else if (ep->speed == SPEED_1000)
+ cp->link_cntl |= CAS_BMCR_SPEED1000;
+ if (ep->duplex == DUPLEX_FULL)
+ cp->link_cntl |= BMCR_FULLDPLX;
+ }
+#if 1
+ changed = (lcntl != cp->link_cntl);
+#endif
+start_aneg:
+ if (cp->lstate == link_up) {
+ printk(KERN_INFO "%s: PCS link down.\n",
+ cp->dev->name);
+ } else {
+ if (changed) {
+ printk(KERN_INFO "%s: link configuration changed\n",
+ cp->dev->name);
+ }
+ }
+ cp->lstate = link_down;
+ cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+ if (!cp->hw_running)
+ return;
+#if 1
+ /*
+ * WTZ: If the old state was link_up, we turn off the carrier
+ * to replicate everything we do elsewhere on a link-down
+ * event when we were already in a link-up state..
+ */
+ if (oldstate == link_up)
+ netif_carrier_off(cp->dev);
+ if (changed && link_was_not_down) {
+ /*
+ * WTZ: This branch will simply schedule a full reset after
+ * we explicitly changed link modes in an ioctl. See if this
+ * fixes the link-problems we were having for forced mode.
+ */
+ atomic_inc(&cp->reset_task_pending);
+ atomic_inc(&cp->reset_task_pending_all);
+ schedule_work(&cp->reset_task);
+ cp->timer_ticks = 0;
+ mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+ return;
+ }
+#endif
+ if (cp->phy_type & CAS_PHY_SERDES) {
+ u32 val = readl(cp->regs + REG_PCS_MII_CTRL);
+
+ if (cp->link_cntl & BMCR_ANENABLE) {
+ val |= (PCS_MII_RESTART_AUTONEG | PCS_MII_AUTONEG_EN);
+ cp->lstate = link_aneg;
+ } else {
+ if (cp->link_cntl & BMCR_FULLDPLX)
+ val |= PCS_MII_CTRL_DUPLEX;
+ val &= ~PCS_MII_AUTONEG_EN;
+ cp->lstate = link_force_ok;
+ }
+ cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+ writel(val, cp->regs + REG_PCS_MII_CTRL);
+
+ } else {
+ cas_mif_poll(cp, 0);
+ ctl = cas_phy_read(cp, MII_BMCR);
+ ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
+ CAS_BMCR_SPEED1000 | BMCR_ANENABLE);
+ ctl |= cp->link_cntl;
+ if (ctl & BMCR_ANENABLE) {
+ ctl |= BMCR_ANRESTART;
+ cp->lstate = link_aneg;
+ } else {
+ cp->lstate = link_force_ok;
+ }
+ cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+ cas_phy_write(cp, MII_BMCR, ctl);
+ cas_mif_poll(cp, 1);
+ }
+
+ cp->timer_ticks = 0;
+ mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+}
+
+/* Must be invoked under cp->lock. */
+static int cas_reset_mii_phy(struct cas *cp)
+{
+ int limit = STOP_TRIES_PHY;
+ u16 val;
+
+ cas_phy_write(cp, MII_BMCR, BMCR_RESET);
+ udelay(100);
+ while (limit--) {
+ val = cas_phy_read(cp, MII_BMCR);
+ if ((val & BMCR_RESET) == 0)
+ break;
+ udelay(10);
+ }
+ return (limit <= 0);
+}
+
+static void cas_saturn_firmware_load(struct cas *cp)
+{
+ cas_saturn_patch_t *patch = cas_saturn_patch;
+
+ cas_phy_powerdown(cp);
+
+ /* expanded memory access mode */
+ cas_phy_write(cp, DP83065_MII_MEM, 0x0);
+
+ /* pointer configuration for new firmware */
+ cas_phy_write(cp, DP83065_MII_REGE, 0x8ff9);
+ cas_phy_write(cp, DP83065_MII_REGD, 0xbd);
+ cas_phy_write(cp, DP83065_MII_REGE, 0x8ffa);
+ cas_phy_write(cp, DP83065_MII_REGD, 0x82);
+ cas_phy_write(cp, DP83065_MII_REGE, 0x8ffb);
+ cas_phy_write(cp, DP83065_MII_REGD, 0x0);
+ cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc);
+ cas_phy_write(cp, DP83065_MII_REGD, 0x39);
+
+ /* 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++;
+ }
+
+ /* enable firmware */
+ cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
+ cas_phy_write(cp, DP83065_MII_REGD, 0x1);
+}
+
+
+/* phy initialization */
+static void cas_phy_init(struct cas *cp)
+{
+ u16 val;
+
+ /* if we're in MII/GMII mode, set up phy */
+ if (CAS_PHY_MII(cp->phy_type)) {
+ writel(PCS_DATAPATH_MODE_MII,
+ cp->regs + REG_PCS_DATAPATH_MODE);
+
+ cas_mif_poll(cp, 0);
+ cas_reset_mii_phy(cp); /* take out of isolate mode */
+
+ if (PHY_LUCENT_B0 == cp->phy_id) {
+ /* workaround link up/down issue with lucent */
+ cas_phy_write(cp, LUCENT_MII_REG, 0x8000);
+ cas_phy_write(cp, MII_BMCR, 0x00f1);
+ cas_phy_write(cp, LUCENT_MII_REG, 0x0);
+
+ } else if (PHY_BROADCOM_B0 == (cp->phy_id & 0xFFFFFFFC)) {
+ /* workarounds for broadcom phy */
+ cas_phy_write(cp, BROADCOM_MII_REG8, 0x0C20);
+ cas_phy_write(cp, BROADCOM_MII_REG7, 0x0012);
+ cas_phy_write(cp, BROADCOM_MII_REG5, 0x1804);
+ cas_phy_write(cp, BROADCOM_MII_REG7, 0x0013);
+ cas_phy_write(cp, BROADCOM_MII_REG5, 0x1204);
+ cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
+ cas_phy_write(cp, BROADCOM_MII_REG5, 0x0132);
+ cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
+ cas_phy_write(cp, BROADCOM_MII_REG5, 0x0232);
+ cas_phy_write(cp, BROADCOM_MII_REG7, 0x201F);
+ cas_phy_write(cp, BROADCOM_MII_REG5, 0x0A20);
+
+ } else if (PHY_BROADCOM_5411 == cp->phy_id) {
+ val = cas_phy_read(cp, BROADCOM_MII_REG4);
+ val = cas_phy_read(cp, BROADCOM_MII_REG4);
+ if (val & 0x0080) {
+ /* link workaround */
+ cas_phy_write(cp, BROADCOM_MII_REG4,
+ val & ~0x0080);
+ }
+
+ } else if (cp->cas_flags & CAS_FLAG_SATURN) {
+ writel((cp->phy_type & CAS_PHY_MII_MDIO0) ?
+ SATURN_PCFG_FSI : 0x0,
+ cp->regs + REG_SATURN_PCFG);
+
+ /* load firmware to address 10Mbps auto-negotiation
+ * issue. NOTE: this will need to be changed if the
+ * default firmware gets fixed.
+ */
+ if (PHY_NS_DP83065 == cp->phy_id) {
+ cas_saturn_firmware_load(cp);
+ }
+ cas_phy_powerup(cp);
+ }
+
+ /* advertise capabilities */
+ val = cas_phy_read(cp, MII_BMCR);
+ val &= ~BMCR_ANENABLE;
+ cas_phy_write(cp, MII_BMCR, val);
+ udelay(10);
+
+ cas_phy_write(cp, MII_ADVERTISE,
+ cas_phy_read(cp, MII_ADVERTISE) |
+ (ADVERTISE_10HALF | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_100FULL |
+ CAS_ADVERTISE_PAUSE |
+ CAS_ADVERTISE_ASYM_PAUSE));
+
+ if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+ /* make sure that we don't advertise half
+ * duplex to avoid a chip issue
+ */
+ val = cas_phy_read(cp, CAS_MII_1000_CTRL);
+ val &= ~CAS_ADVERTISE_1000HALF;
+ val |= CAS_ADVERTISE_1000FULL;
+ cas_phy_write(cp, CAS_MII_1000_CTRL, val);
+ }
+
+ } else {
+ /* reset pcs for serdes */
+ u32 val;
+ int limit;
+
+ writel(PCS_DATAPATH_MODE_SERDES,
+ cp->regs + REG_PCS_DATAPATH_MODE);
+
+ /* enable serdes pins on saturn */
+ if (cp->cas_flags & CAS_FLAG_SATURN)
+ writel(0, cp->regs + REG_SATURN_PCFG);
+
+ /* Reset PCS unit. */
+ val = readl(cp->regs + REG_PCS_MII_CTRL);
+ val |= PCS_MII_RESET;
+ writel(val, cp->regs + REG_PCS_MII_CTRL);
+
+ limit = STOP_TRIES;
+ while (limit-- > 0) {
+ udelay(10);
+ if ((readl(cp->regs + REG_PCS_MII_CTRL) &
+ PCS_MII_RESET) == 0)
+ break;
+ }
+ if (limit <= 0)
+ printk(KERN_WARNING "%s: PCS reset bit would not "
+ "clear [%08x].\n", cp->dev->name,
+ readl(cp->regs + REG_PCS_STATE_MACHINE));
+
+ /* Make sure PCS is disabled while changing advertisement
+ * configuration.
+ */
+ writel(0x0, cp->regs + REG_PCS_CFG);
+
+ /* Advertise all capabilities except half-duplex. */
+ val = readl(cp->regs + REG_PCS_MII_ADVERT);
+ val &= ~PCS_MII_ADVERT_HD;
+ val |= (PCS_MII_ADVERT_FD | PCS_MII_ADVERT_SYM_PAUSE |
+ PCS_MII_ADVERT_ASYM_PAUSE);
+ writel(val, cp->regs + REG_PCS_MII_ADVERT);
+
+ /* enable PCS */
+ writel(PCS_CFG_EN, cp->regs + REG_PCS_CFG);
+
+ /* pcs workaround: enable sync detect */
+ writel(PCS_SERDES_CTRL_SYNCD_EN,
+ cp->regs + REG_PCS_SERDES_CTRL);
+ }
+}
+
+
+static int cas_pcs_link_check(struct cas *cp)
+{
+ u32 stat, state_machine;
+ int retval = 0;
+
+ /* The link status bit latches on zero, so you must
+ * read it twice in such a case to see a transition
+ * to the link being up.
+ */
+ stat = readl(cp->regs + REG_PCS_MII_STATUS);
+ if ((stat & PCS_MII_STATUS_LINK_STATUS) == 0)
+ stat = readl(cp->regs + REG_PCS_MII_STATUS);
+
+ /* The remote-fault indication is only valid
+ * when autoneg has completed.
+ */
+ if ((stat & (PCS_MII_STATUS_AUTONEG_COMP |
+ PCS_MII_STATUS_REMOTE_FAULT)) ==
+ (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) {
+ if (netif_msg_link(cp))
+ printk(KERN_INFO "%s: PCS RemoteFault\n",
+ cp->dev->name);
+ }
+
+ /* work around link detection issue by querying the PCS state
+ * machine directly.
+ */
+ state_machine = readl(cp->regs + REG_PCS_STATE_MACHINE);
+ if ((state_machine & PCS_SM_LINK_STATE_MASK) != SM_LINK_STATE_UP) {
+ stat &= ~PCS_MII_STATUS_LINK_STATUS;
+ } else if (state_machine & PCS_SM_WORD_SYNC_STATE_MASK) {
+ stat |= PCS_MII_STATUS_LINK_STATUS;
+ }
+
+ if (stat & PCS_MII_STATUS_LINK_STATUS) {
+ if (cp->lstate != link_up) {
+ if (cp->opened) {
+ cp->lstate = link_up;
+ cp->link_transition = LINK_TRANSITION_LINK_UP;
+
+ cas_set_link_modes(cp);
+ netif_carrier_on(cp->dev);
+ }
+ }
+ } else if (cp->lstate == link_up) {
+ cp->lstate = link_down;
+ if (link_transition_timeout != 0 &&
+ cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
+ !cp->link_transition_jiffies_valid) {
+ /*
+ * force a reset, as a workaround for the
+ * link-failure problem. May want to move this to a
+ * point a bit earlier in the sequence. If we had
+ * generated a reset a short time ago, we'll wait for
+ * the link timer to check the status until a
+ * timer expires (link_transistion_jiffies_valid is
+ * true when the timer is running.) Instead of using
+ * a system timer, we just do a check whenever the
+ * link timer is running - this clears the flag after
+ * a suitable delay.
+ */
+ retval = 1;
+ cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
+ cp->link_transition_jiffies = jiffies;
+ cp->link_transition_jiffies_valid = 1;
+ } else {
+ cp->link_transition = LINK_TRANSITION_ON_FAILURE;
+ }
+ netif_carrier_off(cp->dev);
+ if (cp->opened && netif_msg_link(cp)) {
+ printk(KERN_INFO "%s: PCS link down.\n",
+ cp->dev->name);
+ }
+
+ /* Cassini only: if you force a mode, there can be
+ * sync problems on link down. to fix that, the following
+ * things need to be checked:
+ * 1) read serialink state register
+ * 2) read pcs status register to verify link down.
+ * 3) if link down and serial link == 0x03, then you need
+ * to global reset the chip.
+ */
+ if ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0) {
+ /* should check to see if we're in a forced mode */
+ stat = readl(cp->regs + REG_PCS_SERDES_STATE);
+ if (stat == 0x03)
+ return 1;
+ }
+ } else if (cp->lstate == link_down) {
+ if (link_transition_timeout != 0 &&
+ cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
+ !cp->link_transition_jiffies_valid) {
+ /* force a reset, as a workaround for the
+ * link-failure problem. May want to move
+ * this to a point a bit earlier in the
+ * sequence.
+ */
+ retval = 1;
+ cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
+ cp->link_transition_jiffies = jiffies;
+ cp->link_transition_jiffies_valid = 1;
+ } else {
+ cp->link_transition = LINK_TRANSITION_STILL_FAILED;
+ }
+ }
+
+ return retval;
+}
+
+static int cas_pcs_interrupt(struct net_device *dev,
+ struct cas *cp, u32 status)
+{
+ u32 stat = readl(cp->regs + REG_PCS_INTR_STATUS);
+
+ if ((stat & PCS_INTR_STATUS_LINK_CHANGE) == 0)
+ return 0;
+ return cas_pcs_link_check(cp);
+}
+
+static int cas_txmac_interrupt(struct net_device *dev,
+ struct cas *cp, u32 status)
+{
+ u32 txmac_stat = readl(cp->regs + REG_MAC_TX_STATUS);
+
+ if (!txmac_stat)
+ return 0;
+
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: txmac interrupt, txmac_stat: 0x%x\n",
+ cp->dev->name, txmac_stat);
+
+ /* Defer timer expiration is quite normal,
+ * don't even log the event.
+ */
+ if ((txmac_stat & MAC_TX_DEFER_TIMER) &&
+ !(txmac_stat & ~MAC_TX_DEFER_TIMER))
+ return 0;
+
+ spin_lock(&cp->stat_lock[0]);
+ if (txmac_stat & MAC_TX_UNDERRUN) {
+ printk(KERN_ERR "%s: TX MAC xmit underrun.\n",
+ dev->name);
+ cp->net_stats[0].tx_fifo_errors++;
+ }
+
+ if (txmac_stat & MAC_TX_MAX_PACKET_ERR) {
+ printk(KERN_ERR "%s: TX MAC max packet size error.\n",
+ dev->name);
+ cp->net_stats[0].tx_errors++;
+ }
+
+ /* The rest are all cases of one of the 16-bit TX
+ * counters expiring.
+ */
+ if (txmac_stat & MAC_TX_COLL_NORMAL)
+ cp->net_stats[0].collisions += 0x10000;
+
+ if (txmac_stat & MAC_TX_COLL_EXCESS) {
+ cp->net_stats[0].tx_aborted_errors += 0x10000;
+ cp->net_stats[0].collisions += 0x10000;
+ }
+
+ if (txmac_stat & MAC_TX_COLL_LATE) {
+ cp->net_stats[0].tx_aborted_errors += 0x10000;
+ cp->net_stats[0].collisions += 0x10000;
+ }
+ spin_unlock(&cp->stat_lock[0]);
+
+ /* We do not keep track of MAC_TX_COLL_FIRST and
+ * MAC_TX_PEAK_ATTEMPTS events.
+ */
+ return 0;
+}
+
+static void cas_load_firmware(struct cas *cp, cas_hp_inst_t *firmware)
+{
+ cas_hp_inst_t *inst;
+ u32 val;
+ int i;
+
+ i = 0;
+ while ((inst = firmware) && inst->note) {
+ writel(i, cp->regs + REG_HP_INSTR_RAM_ADDR);
+
+ val = CAS_BASE(HP_INSTR_RAM_HI_VAL, inst->val);
+ val |= CAS_BASE(HP_INSTR_RAM_HI_MASK, inst->mask);
+ writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_HI);
+
+ val = CAS_BASE(HP_INSTR_RAM_MID_OUTARG, inst->outarg >> 10);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_OUTOP, inst->outop);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_FNEXT, inst->fnext);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_FOFF, inst->foff);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_SNEXT, inst->snext);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_SOFF, inst->soff);
+ val |= CAS_BASE(HP_INSTR_RAM_MID_OP, inst->op);
+ writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_MID);
+
+ val = CAS_BASE(HP_INSTR_RAM_LOW_OUTMASK, inst->outmask);
+ val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTSHIFT, inst->outshift);
+ val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTEN, inst->outenab);
+ val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTARG, inst->outarg);
+ writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_LOW);
+ ++firmware;
+ ++i;
+ }
+}
+
+static void cas_init_rx_dma(struct cas *cp)
+{
+ u64 desc_dma = cp->block_dvma;
+ u32 val;
+ int i, size;
+
+ /* rx free descriptors */
+ val = CAS_BASE(RX_CFG_SWIVEL, RX_SWIVEL_OFF_VAL);
+ val |= CAS_BASE(RX_CFG_DESC_RING, RX_DESC_RINGN_INDEX(0));
+ val |= CAS_BASE(RX_CFG_COMP_RING, RX_COMP_RINGN_INDEX(0));
+ if ((N_RX_DESC_RINGS > 1) &&
+ (cp->cas_flags & CAS_FLAG_REG_PLUS)) /* do desc 2 */
+ val |= CAS_BASE(RX_CFG_DESC_RING1, RX_DESC_RINGN_INDEX(1));
+ writel(val, cp->regs + REG_RX_CFG);
+
+ val = (unsigned long) cp->init_rxds[0] -
+ (unsigned long) cp->init_block;
+ writel((desc_dma + val) >> 32, cp->regs + REG_RX_DB_HI);
+ writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_DB_LOW);
+ writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
+
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ /* rx desc 2 is for IPSEC packets. however,
+ * we don't it that for that purpose.
+ */
+ val = (unsigned long) cp->init_rxds[1] -
+ (unsigned long) cp->init_block;
+ writel((desc_dma + val) >> 32, cp->regs + REG_PLUS_RX_DB1_HI);
+ writel((desc_dma + val) & 0xffffffff, cp->regs +
+ REG_PLUS_RX_DB1_LOW);
+ writel(RX_DESC_RINGN_SIZE(1) - 4, cp->regs +
+ REG_PLUS_RX_KICK1);
+ }
+
+ /* rx completion registers */
+ val = (unsigned long) cp->init_rxcs[0] -
+ (unsigned long) cp->init_block;
+ writel((desc_dma + val) >> 32, cp->regs + REG_RX_CB_HI);
+ writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_CB_LOW);
+
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ /* rx comp 2-4 */
+ for (i = 1; i < MAX_RX_COMP_RINGS; i++) {
+ val = (unsigned long) cp->init_rxcs[i] -
+ (unsigned long) cp->init_block;
+ writel((desc_dma + val) >> 32, cp->regs +
+ REG_PLUS_RX_CBN_HI(i));
+ writel((desc_dma + val) & 0xffffffff, cp->regs +
+ REG_PLUS_RX_CBN_LOW(i));
+ }
+ }
+
+ /* read selective clear regs to prevent spurious interrupts
+ * on reset because complete == kick.
+ * selective clear set up to prevent interrupts on resets
+ */
+ readl(cp->regs + REG_INTR_STATUS_ALIAS);
+ writel(INTR_RX_DONE | INTR_RX_BUF_UNAVAIL, cp->regs + REG_ALIAS_CLEAR);
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ for (i = 1; i < N_RX_COMP_RINGS; i++)
+ readl(cp->regs + REG_PLUS_INTRN_STATUS_ALIAS(i));
+
+ /* 2 is different from 3 and 4 */
+ if (N_RX_COMP_RINGS > 1)
+ writel(INTR_RX_DONE_ALT | INTR_RX_BUF_UNAVAIL_1,
+ cp->regs + REG_PLUS_ALIASN_CLEAR(1));
+
+ for (i = 2; i < N_RX_COMP_RINGS; i++)
+ writel(INTR_RX_DONE_ALT,
+ cp->regs + REG_PLUS_ALIASN_CLEAR(i));
+ }
+
+ /* set up pause thresholds */
+ val = CAS_BASE(RX_PAUSE_THRESH_OFF,
+ cp->rx_pause_off / RX_PAUSE_THRESH_QUANTUM);
+ val |= CAS_BASE(RX_PAUSE_THRESH_ON,
+ cp->rx_pause_on / RX_PAUSE_THRESH_QUANTUM);
+ writel(val, cp->regs + REG_RX_PAUSE_THRESH);
+
+ /* zero out dma reassembly buffers */
+ for (i = 0; i < 64; i++) {
+ writel(i, cp->regs + REG_RX_TABLE_ADDR);
+ writel(0x0, cp->regs + REG_RX_TABLE_DATA_LOW);
+ writel(0x0, cp->regs + REG_RX_TABLE_DATA_MID);
+ writel(0x0, cp->regs + REG_RX_TABLE_DATA_HI);
+ }
+
+ /* make sure address register is 0 for normal operation */
+ writel(0x0, cp->regs + REG_RX_CTRL_FIFO_ADDR);
+ writel(0x0, cp->regs + REG_RX_IPP_FIFO_ADDR);
+
+ /* interrupt mitigation */
+#ifdef USE_RX_BLANK
+ val = CAS_BASE(RX_BLANK_INTR_TIME, RX_BLANK_INTR_TIME_VAL);
+ val |= CAS_BASE(RX_BLANK_INTR_PKT, RX_BLANK_INTR_PKT_VAL);
+ writel(val, cp->regs + REG_RX_BLANK);
+#else
+ writel(0x0, cp->regs + REG_RX_BLANK);
+#endif
+
+ /* interrupt generation as a function of low water marks for
+ * free desc and completion entries. these are used to trigger
+ * housekeeping for rx descs. we don't use the free interrupt
+ * as it's not very useful
+ */
+ /* val = CAS_BASE(RX_AE_THRESH_FREE, RX_AE_FREEN_VAL(0)); */
+ val = CAS_BASE(RX_AE_THRESH_COMP, RX_AE_COMP_VAL);
+ writel(val, cp->regs + REG_RX_AE_THRESH);
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ val = CAS_BASE(RX_AE1_THRESH_FREE, RX_AE_FREEN_VAL(1));
+ writel(val, cp->regs + REG_PLUS_RX_AE1_THRESH);
+ }
+
+ /* Random early detect registers. useful for congestion avoidance.
+ * this should be tunable.
+ */
+ writel(0x0, cp->regs + REG_RX_RED);
+
+ /* receive page sizes. default == 2K (0x800) */
+ val = 0;
+ if (cp->page_size == 0x1000)
+ val = 0x1;
+ else if (cp->page_size == 0x2000)
+ val = 0x2;
+ else if (cp->page_size == 0x4000)
+ val = 0x3;
+
+ /* round mtu + offset. constrain to page size. */
+ size = cp->dev->mtu + 64;
+ if (size > cp->page_size)
+ size = cp->page_size;
+
+ if (size <= 0x400)
+ i = 0x0;
+ else if (size <= 0x800)
+ i = 0x1;
+ else if (size <= 0x1000)
+ i = 0x2;
+ else
+ i = 0x3;
+
+ cp->mtu_stride = 1 << (i + 10);
+ val = CAS_BASE(RX_PAGE_SIZE, val);
+ val |= CAS_BASE(RX_PAGE_SIZE_MTU_STRIDE, i);
+ val |= CAS_BASE(RX_PAGE_SIZE_MTU_COUNT, cp->page_size >> (i + 10));
+ val |= CAS_BASE(RX_PAGE_SIZE_MTU_OFF, 0x1);
+ writel(val, cp->regs + REG_RX_PAGE_SIZE);
+
+ /* enable the header parser if desired */
+ if (CAS_HP_FIRMWARE == cas_prog_null)
+ return;
+
+ val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS);
+ val |= HP_CFG_PARSE_EN | HP_CFG_SYN_INC_MASK;
+ val |= CAS_BASE(HP_CFG_TCP_THRESH, HP_TCP_THRESH_VAL);
+ writel(val, cp->regs + REG_HP_CFG);
+}
+
+static inline void cas_rxc_init(struct cas_rx_comp *rxc)
+{
+ memset(rxc, 0, sizeof(*rxc));
+ rxc->word4 = cpu_to_le64(RX_COMP4_ZERO);
+}
+
+/* NOTE: we use the ENC RX DESC ring for spares. the rx_page[0,1]
+ * flipping is protected by the fact that the chip will not
+ * hand back the same page index while it's being processed.
+ */
+static inline cas_page_t *cas_page_spare(struct cas *cp, const int index)
+{
+ cas_page_t *page = cp->rx_pages[1][index];
+ cas_page_t *new;
+
+ if (page_count(page->buffer) == 1)
+ return page;
+
+ new = cas_page_dequeue(cp);
+ if (new) {
+ spin_lock(&cp->rx_inuse_lock);
+ list_add(&page->list, &cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+ }
+ return new;
+}
+
+/* this needs to be changed if we actually use the ENC RX DESC ring */
+static cas_page_t *cas_page_swap(struct cas *cp, const int ring,
+ const int index)
+{
+ cas_page_t **page0 = cp->rx_pages[0];
+ cas_page_t **page1 = cp->rx_pages[1];
+
+ /* swap if buffer is in use */
+ if (page_count(page0[index]->buffer) > 1) {
+ cas_page_t *new = cas_page_spare(cp, index);
+ if (new) {
+ page1[index] = page0[index];
+ page0[index] = new;
+ }
+ }
+ RX_USED_SET(page0[index], 0);
+ return page0[index];
+}
+
+static void cas_clean_rxds(struct cas *cp)
+{
+ /* only clean ring 0 as ring 1 is used for spare buffers */
+ struct cas_rx_desc *rxd = cp->init_rxds[0];
+ int i, size;
+
+ /* release all rx flows */
+ for (i = 0; i < N_RX_FLOWS; i++) {
+ struct sk_buff *skb;
+ while ((skb = __skb_dequeue(&cp->rx_flows[i]))) {
+ cas_skb_release(skb);
+ }
+ }
+
+ /* initialize descriptors */
+ size = RX_DESC_RINGN_SIZE(0);
+ for (i = 0; i < size; i++) {
+ cas_page_t *page = cas_page_swap(cp, 0, i);
+ rxd[i].buffer = cpu_to_le64(page->dma_addr);
+ rxd[i].index = cpu_to_le64(CAS_BASE(RX_INDEX_NUM, i) |
+ CAS_BASE(RX_INDEX_RING, 0));
+ }
+
+ cp->rx_old[0] = RX_DESC_RINGN_SIZE(0) - 4;
+ cp->rx_last[0] = 0;
+ cp->cas_flags &= ~CAS_FLAG_RXD_POST(0);
+}
+
+static void cas_clean_rxcs(struct cas *cp)
+{
+ int i, j;
+
+ /* take ownership of rx comp descriptors */
+ memset(cp->rx_cur, 0, sizeof(*cp->rx_cur)*N_RX_COMP_RINGS);
+ memset(cp->rx_new, 0, sizeof(*cp->rx_new)*N_RX_COMP_RINGS);
+ for (i = 0; i < N_RX_COMP_RINGS; i++) {
+ struct cas_rx_comp *rxc = cp->init_rxcs[i];
+ for (j = 0; j < RX_COMP_RINGN_SIZE(i); j++) {
+ cas_rxc_init(rxc + j);
+ }
+ }
+}
+
+#if 0
+/* When we get a RX fifo overflow, the RX unit is probably hung
+ * so we do the following.
+ *
+ * If any part of the reset goes wrong, we return 1 and that causes the
+ * whole chip to be reset.
+ */
+static int cas_rxmac_reset(struct cas *cp)
+{
+ struct net_device *dev = cp->dev;
+ int limit;
+ u32 val;
+
+ /* First, reset MAC RX. */
+ writel(cp->mac_rx_cfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+ for (limit = 0; limit < STOP_TRIES; limit++) {
+ if (!(readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN))
+ break;
+ udelay(10);
+ }
+ if (limit == STOP_TRIES) {
+ printk(KERN_ERR "%s: RX MAC will not disable, resetting whole "
+ "chip.\n", dev->name);
+ return 1;
+ }
+
+ /* Second, disable RX DMA. */
+ writel(0, cp->regs + REG_RX_CFG);
+ for (limit = 0; limit < STOP_TRIES; limit++) {
+ if (!(readl(cp->regs + REG_RX_CFG) & RX_CFG_DMA_EN))
+ break;
+ udelay(10);
+ }
+ if (limit == STOP_TRIES) {
+ printk(KERN_ERR "%s: RX DMA will not disable, resetting whole "
+ "chip.\n", dev->name);
+ return 1;
+ }
+
+ mdelay(5);
+
+ /* Execute RX reset command. */
+ writel(SW_RESET_RX, cp->regs + REG_SW_RESET);
+ for (limit = 0; limit < STOP_TRIES; limit++) {
+ if (!(readl(cp->regs + REG_SW_RESET) & SW_RESET_RX))
+ break;
+ udelay(10);
+ }
+ if (limit == STOP_TRIES) {
+ printk(KERN_ERR "%s: RX reset command will not execute, "
+ "resetting whole chip.\n", dev->name);
+ return 1;
+ }
+
+ /* reset driver rx state */
+ cas_clean_rxds(cp);
+ cas_clean_rxcs(cp);
+
+ /* Now, reprogram the rest of RX unit. */
+ cas_init_rx_dma(cp);
+
+ /* re-enable */
+ val = readl(cp->regs + REG_RX_CFG);
+ writel(val | RX_CFG_DMA_EN, cp->regs + REG_RX_CFG);
+ writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
+ val = readl(cp->regs + REG_MAC_RX_CFG);
+ writel(val | MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+ return 0;
+}
+#endif
+
+static int cas_rxmac_interrupt(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ u32 stat = readl(cp->regs + REG_MAC_RX_STATUS);
+
+ if (!stat)
+ return 0;
+
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: rxmac interrupt, stat: 0x%x\n",
+ cp->dev->name, stat);
+
+ /* these are all rollovers */
+ spin_lock(&cp->stat_lock[0]);
+ if (stat & MAC_RX_ALIGN_ERR)
+ cp->net_stats[0].rx_frame_errors += 0x10000;
+
+ if (stat & MAC_RX_CRC_ERR)
+ cp->net_stats[0].rx_crc_errors += 0x10000;
+
+ if (stat & MAC_RX_LEN_ERR)
+ cp->net_stats[0].rx_length_errors += 0x10000;
+
+ if (stat & MAC_RX_OVERFLOW) {
+ cp->net_stats[0].rx_over_errors++;
+ cp->net_stats[0].rx_fifo_errors++;
+ }
+
+ /* We do not track MAC_RX_FRAME_COUNT and MAC_RX_VIOL_ERR
+ * events.
+ */
+ spin_unlock(&cp->stat_lock[0]);
+ return 0;
+}
+
+static int cas_mac_interrupt(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ u32 stat = readl(cp->regs + REG_MAC_CTRL_STATUS);
+
+ if (!stat)
+ return 0;
+
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: mac interrupt, stat: 0x%x\n",
+ cp->dev->name, stat);
+
+ /* This interrupt is just for pause frame and pause
+ * tracking. It is useful for diagnostics and debug
+ * but probably by default we will mask these events.
+ */
+ if (stat & MAC_CTRL_PAUSE_STATE)
+ cp->pause_entered++;
+
+ if (stat & MAC_CTRL_PAUSE_RECEIVED)
+ cp->pause_last_time_recvd = (stat >> 16);
+
+ return 0;
+}
+
+
+/* Must be invoked under cp->lock. */
+static inline int cas_mdio_link_not_up(struct cas *cp)
+{
+ u16 val;
+
+ switch (cp->lstate) {
+ case link_force_ret:
+ if (netif_msg_link(cp))
+ printk(KERN_INFO "%s: Autoneg failed again, keeping"
+ " forced mode\n", cp->dev->name);
+ cas_phy_write(cp, MII_BMCR, cp->link_fcntl);
+ cp->timer_ticks = 5;
+ cp->lstate = link_force_ok;
+ cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+ break;
+
+ case link_aneg:
+ val = cas_phy_read(cp, MII_BMCR);
+
+ /* Try forced modes. we try things in the following order:
+ * 1000 full -> 100 full/half -> 10 half
+ */
+ val &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
+ val |= BMCR_FULLDPLX;
+ val |= (cp->cas_flags & CAS_FLAG_1000MB_CAP) ?
+ CAS_BMCR_SPEED1000 : BMCR_SPEED100;
+ cas_phy_write(cp, MII_BMCR, val);
+ cp->timer_ticks = 5;
+ cp->lstate = link_force_try;
+ cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+ break;
+
+ case link_force_try:
+ /* Downgrade from 1000 to 100 to 10 Mbps if necessary. */
+ val = cas_phy_read(cp, MII_BMCR);
+ cp->timer_ticks = 5;
+ if (val & CAS_BMCR_SPEED1000) { /* gigabit */
+ val &= ~CAS_BMCR_SPEED1000;
+ val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+ cas_phy_write(cp, MII_BMCR, val);
+ break;
+ }
+
+ if (val & BMCR_SPEED100) {
+ if (val & BMCR_FULLDPLX) /* fd failed */
+ val &= ~BMCR_FULLDPLX;
+ else { /* 100Mbps failed */
+ val &= ~BMCR_SPEED100;
+ }
+ cas_phy_write(cp, MII_BMCR, val);
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+/* must be invoked with cp->lock held */
+static int cas_mii_link_check(struct cas *cp, const u16 bmsr)
+{
+ int restart;
+
+ if (bmsr & BMSR_LSTATUS) {
+ /* Ok, here we got a link. If we had it due to a forced
+ * fallback, and we were configured for autoneg, we
+ * retry a short autoneg pass. If you know your hub is
+ * broken, use ethtool ;)
+ */
+ if ((cp->lstate == link_force_try) &&
+ (cp->link_cntl & BMCR_ANENABLE)) {
+ cp->lstate = link_force_ret;
+ cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+ cas_mif_poll(cp, 0);
+ cp->link_fcntl = cas_phy_read(cp, MII_BMCR);
+ cp->timer_ticks = 5;
+ if (cp->opened && netif_msg_link(cp))
+ printk(KERN_INFO "%s: Got link after fallback, retrying"
+ " autoneg once...\n", cp->dev->name);
+ cas_phy_write(cp, MII_BMCR,
+ cp->link_fcntl | BMCR_ANENABLE |
+ BMCR_ANRESTART);
+ cas_mif_poll(cp, 1);
+
+ } else if (cp->lstate != link_up) {
+ cp->lstate = link_up;
+ cp->link_transition = LINK_TRANSITION_LINK_UP;
+
+ if (cp->opened) {
+ cas_set_link_modes(cp);
+ netif_carrier_on(cp->dev);
+ }
+ }
+ return 0;
+ }
+
+ /* link not up. if the link was previously up, we restart the
+ * whole process
+ */
+ restart = 0;
+ if (cp->lstate == link_up) {
+ cp->lstate = link_down;
+ cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+
+ netif_carrier_off(cp->dev);
+ if (cp->opened && netif_msg_link(cp))
+ printk(KERN_INFO "%s: Link down\n",
+ cp->dev->name);
+ restart = 1;
+
+ } else if (++cp->timer_ticks > 10)
+ cas_mdio_link_not_up(cp);
+
+ return restart;
+}
+
+static int cas_mif_interrupt(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ u32 stat = readl(cp->regs + REG_MIF_STATUS);
+ u16 bmsr;
+
+ /* check for a link change */
+ if (CAS_VAL(MIF_STATUS_POLL_STATUS, stat) == 0)
+ return 0;
+
+ bmsr = CAS_VAL(MIF_STATUS_POLL_DATA, stat);
+ return cas_mii_link_check(cp, bmsr);
+}
+
+static int cas_pci_interrupt(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ u32 stat = readl(cp->regs + REG_PCI_ERR_STATUS);
+
+ if (!stat)
+ return 0;
+
+ printk(KERN_ERR "%s: PCI error [%04x:%04x] ", dev->name, stat,
+ readl(cp->regs + REG_BIM_DIAG));
+
+ /* cassini+ has this reserved */
+ if ((stat & PCI_ERR_BADACK) &&
+ ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0))
+ printk("<No ACK64# during ABS64 cycle> ");
+
+ if (stat & PCI_ERR_DTRTO)
+ printk("<Delayed transaction timeout> ");
+ if (stat & PCI_ERR_OTHER)
+ printk("<other> ");
+ if (stat & PCI_ERR_BIM_DMA_WRITE)
+ printk("<BIM DMA 0 write req> ");
+ if (stat & PCI_ERR_BIM_DMA_READ)
+ printk("<BIM DMA 0 read req> ");
+ printk("\n");
+
+ if (stat & PCI_ERR_OTHER) {
+ u16 cfg;
+
+ /* Interrogate PCI config space for the
+ * true cause.
+ */
+ pci_read_config_word(cp->pdev, PCI_STATUS, &cfg);
+ printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n",
+ dev->name, cfg);
+ if (cfg & PCI_STATUS_PARITY)
+ printk(KERN_ERR "%s: PCI parity error detected.\n",
+ dev->name);
+ if (cfg & PCI_STATUS_SIG_TARGET_ABORT)
+ printk(KERN_ERR "%s: PCI target abort.\n",
+ dev->name);
+ if (cfg & PCI_STATUS_REC_TARGET_ABORT)
+ printk(KERN_ERR "%s: PCI master acks target abort.\n",
+ dev->name);
+ if (cfg & PCI_STATUS_REC_MASTER_ABORT)
+ printk(KERN_ERR "%s: PCI master abort.\n", dev->name);
+ if (cfg & PCI_STATUS_SIG_SYSTEM_ERROR)
+ printk(KERN_ERR "%s: PCI system error SERR#.\n",
+ dev->name);
+ if (cfg & PCI_STATUS_DETECTED_PARITY)
+ printk(KERN_ERR "%s: PCI parity error.\n",
+ dev->name);
+
+ /* Write the error bits back to clear them. */
+ cfg &= (PCI_STATUS_PARITY |
+ PCI_STATUS_SIG_TARGET_ABORT |
+ PCI_STATUS_REC_TARGET_ABORT |
+ PCI_STATUS_REC_MASTER_ABORT |
+ PCI_STATUS_SIG_SYSTEM_ERROR |
+ PCI_STATUS_DETECTED_PARITY);
+ pci_write_config_word(cp->pdev, PCI_STATUS, cfg);
+ }
+
+ /* For all PCI errors, we should reset the chip. */
+ return 1;
+}
+
+/* All non-normal interrupt conditions get serviced here.
+ * Returns non-zero if we should just exit the interrupt
+ * handler right now (ie. if we reset the card which invalidates
+ * all of the other original irq status bits).
+ */
+static int cas_abnormal_irq(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ if (status & INTR_RX_TAG_ERROR) {
+ /* corrupt RX tag framing */
+ if (netif_msg_rx_err(cp))
+ printk(KERN_DEBUG "%s: corrupt rx tag framing\n",
+ cp->dev->name);
+ spin_lock(&cp->stat_lock[0]);
+ cp->net_stats[0].rx_errors++;
+ spin_unlock(&cp->stat_lock[0]);
+ goto do_reset;
+ }
+
+ if (status & INTR_RX_LEN_MISMATCH) {
+ /* length mismatch. */
+ if (netif_msg_rx_err(cp))
+ printk(KERN_DEBUG "%s: length mismatch for rx frame\n",
+ cp->dev->name);
+ spin_lock(&cp->stat_lock[0]);
+ cp->net_stats[0].rx_errors++;
+ spin_unlock(&cp->stat_lock[0]);
+ goto do_reset;
+ }
+
+ if (status & INTR_PCS_STATUS) {
+ if (cas_pcs_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+
+ if (status & INTR_TX_MAC_STATUS) {
+ if (cas_txmac_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+
+ if (status & INTR_RX_MAC_STATUS) {
+ if (cas_rxmac_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+
+ if (status & INTR_MAC_CTRL_STATUS) {
+ if (cas_mac_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+
+ if (status & INTR_MIF_STATUS) {
+ if (cas_mif_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+
+ if (status & INTR_PCI_ERROR_STATUS) {
+ if (cas_pci_interrupt(dev, cp, status))
+ goto do_reset;
+ }
+ return 0;
+
+do_reset:
+#if 1
+ atomic_inc(&cp->reset_task_pending);
+ atomic_inc(&cp->reset_task_pending_all);
+ printk(KERN_ERR "%s:reset called in cas_abnormal_irq [0x%x]\n",
+ dev->name, status);
+ schedule_work(&cp->reset_task);
+#else
+ atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+ printk(KERN_ERR "reset called in cas_abnormal_irq\n");
+ schedule_work(&cp->reset_task);
+#endif
+ return 1;
+}
+
+/* NOTE: CAS_TABORT returns 1 or 2 so that it can be used when
+ * determining whether to do a netif_stop/wakeup
+ */
+#define CAS_TABORT(x) (((x)->cas_flags & CAS_FLAG_TARGET_ABORT) ? 2 : 1)
+#define CAS_ROUND_PAGE(x) (((x) + PAGE_SIZE - 1) & PAGE_MASK)
+static inline int cas_calc_tabort(struct cas *cp, const unsigned long addr,
+ const int len)
+{
+ unsigned long off = addr + len;
+
+ if (CAS_TABORT(cp) == 1)
+ return 0;
+ if ((CAS_ROUND_PAGE(off) - off) > TX_TARGET_ABORT_LEN)
+ return 0;
+ return TX_TARGET_ABORT_LEN;
+}
+
+static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
+{
+ struct cas_tx_desc *txds;
+ struct sk_buff **skbs;
+ struct net_device *dev = cp->dev;
+ int entry, count;
+
+ spin_lock(&cp->tx_lock[ring]);
+ txds = cp->init_txds[ring];
+ skbs = cp->tx_skbs[ring];
+ entry = cp->tx_old[ring];
+
+ count = TX_BUFF_COUNT(ring, entry, limit);
+ while (entry != limit) {
+ struct sk_buff *skb = skbs[entry];
+ dma_addr_t daddr;
+ u32 dlen;
+ int frag;
+
+ if (!skb) {
+ /* this should never occur */
+ entry = TX_DESC_NEXT(ring, entry);
+ continue;
+ }
+
+ /* however, we might get only a partial skb release. */
+ count -= skb_shinfo(skb)->nr_frags +
+ + cp->tx_tiny_use[ring][entry].nbufs + 1;
+ if (count < 0)
+ break;
+
+ if (netif_msg_tx_done(cp))
+ printk(KERN_DEBUG "%s: tx[%d] done, slot %d\n",
+ cp->dev->name, ring, entry);
+
+ skbs[entry] = NULL;
+ cp->tx_tiny_use[ring][entry].nbufs = 0;
+
+ for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
+ struct cas_tx_desc *txd = txds + entry;
+
+ daddr = le64_to_cpu(txd->buffer);
+ dlen = CAS_VAL(TX_DESC_BUFLEN,
+ le64_to_cpu(txd->control));
+ pci_unmap_page(cp->pdev, daddr, dlen,
+ PCI_DMA_TODEVICE);
+ entry = TX_DESC_NEXT(ring, entry);
+
+ /* tiny buffer may follow */
+ if (cp->tx_tiny_use[ring][entry].used) {
+ cp->tx_tiny_use[ring][entry].used = 0;
+ entry = TX_DESC_NEXT(ring, entry);
+ }
+ }
+
+ spin_lock(&cp->stat_lock[ring]);
+ cp->net_stats[ring].tx_packets++;
+ cp->net_stats[ring].tx_bytes += skb->len;
+ spin_unlock(&cp->stat_lock[ring]);
+ dev_kfree_skb_irq(skb);
+ }
+ cp->tx_old[ring] = entry;
+
+ /* this is wrong for multiple tx rings. the net device needs
+ * multiple queues for this to do the right thing. we wait
+ * for 2*packets to be available when using tiny buffers
+ */
+ if (netif_queue_stopped(dev) &&
+ (TX_BUFFS_AVAIL(cp, ring) > CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1)))
+ netif_wake_queue(dev);
+ spin_unlock(&cp->tx_lock[ring]);
+}
+
+static void cas_tx(struct net_device *dev, struct cas *cp,
+ u32 status)
+{
+ int limit, ring;
+#ifdef USE_TX_COMPWB
+ u64 compwb = le64_to_cpu(cp->init_block->tx_compwb);
+#endif
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n",
+ cp->dev->name, status, compwb);
+ /* process all the rings */
+ for (ring = 0; ring < N_TX_RINGS; ring++) {
+#ifdef USE_TX_COMPWB
+ /* use the completion writeback registers */
+ limit = (CAS_VAL(TX_COMPWB_MSB, compwb) << 8) |
+ CAS_VAL(TX_COMPWB_LSB, compwb);
+ compwb = TX_COMPWB_NEXT(compwb);
+#else
+ limit = readl(cp->regs + REG_TX_COMPN(ring));
+#endif
+ if (cp->tx_old[ring] != limit)
+ cas_tx_ringN(cp, ring, limit);
+ }
+}
+
+
+static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
+ int entry, const u64 *words,
+ struct sk_buff **skbref)
+{
+ int dlen, hlen, len, i, alloclen;
+ int off, swivel = RX_SWIVEL_OFF_VAL;
+ struct cas_page *page;
+ struct sk_buff *skb;
+ void *addr, *crcaddr;
+ char *p;
+
+ hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]);
+ dlen = CAS_VAL(RX_COMP1_DATA_SIZE, words[0]);
+ len = hlen + dlen;
+
+ if (RX_COPY_ALWAYS || (words[2] & RX_COMP3_SMALL_PKT))
+ alloclen = len;
+ else
+ alloclen = max(hlen, RX_COPY_MIN);
+
+ skb = dev_alloc_skb(alloclen + swivel + cp->crc_size);
+ if (skb == NULL)
+ return -1;
+
+ *skbref = skb;
+ skb->dev = cp->dev;
+ skb_reserve(skb, swivel);
+
+ p = skb->data;
+ addr = crcaddr = NULL;
+ if (hlen) { /* always copy header pages */
+ i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
+ page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+ off = CAS_VAL(RX_COMP2_HDR_OFF, words[1]) * 0x100 +
+ swivel;
+
+ i = hlen;
+ if (!dlen) /* attach FCS */
+ i += cp->crc_size;
+ pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+ addr = cas_page_map(page->buffer);
+ memcpy(p, addr + off, i);
+ pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+ cas_page_unmap(addr);
+ RX_USED_ADD(page, 0x100);
+ p += hlen;
+ swivel = 0;
+ }
+
+
+ if (alloclen < (hlen + dlen)) {
+ skb_frag_t *frag = skb_shinfo(skb)->frags;
+
+ /* normal or jumbo packets. we use frags */
+ i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+ page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+ off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
+
+ hlen = min(cp->page_size - off, dlen);
+ if (hlen < 0) {
+ if (netif_msg_rx_err(cp)) {
+ printk(KERN_DEBUG "%s: rx page overflow: "
+ "%d\n", cp->dev->name, hlen);
+ }
+ dev_kfree_skb_irq(skb);
+ return -1;
+ }
+ i = hlen;
+ if (i == dlen) /* attach FCS */
+ i += cp->crc_size;
+ pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+
+ /* make sure we always copy a header */
+ swivel = 0;
+ if (p == (char *) skb->data) { /* not split */
+ addr = cas_page_map(page->buffer);
+ memcpy(p, addr + off, RX_COPY_MIN);
+ pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+ cas_page_unmap(addr);
+ off += RX_COPY_MIN;
+ swivel = RX_COPY_MIN;
+ RX_USED_ADD(page, cp->mtu_stride);
+ } else {
+ RX_USED_ADD(page, hlen);
+ }
+ skb_put(skb, alloclen);
+
+ skb_shinfo(skb)->nr_frags++;
+ skb->data_len += hlen - swivel;
+ skb->len += hlen - swivel;
+
+ get_page(page->buffer);
+ frag->page = page->buffer;
+ frag->page_offset = off;
+ frag->size = hlen - swivel;
+
+ /* any more data? */
+ if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
+ hlen = dlen;
+ off = 0;
+
+ i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+ page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+ pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr,
+ hlen + cp->crc_size,
+ PCI_DMA_FROMDEVICE);
+ pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
+ hlen + cp->crc_size,
+ PCI_DMA_FROMDEVICE);
+
+ skb_shinfo(skb)->nr_frags++;
+ skb->data_len += hlen;
+ skb->len += hlen;
+ frag++;
+
+ get_page(page->buffer);
+ frag->page = page->buffer;
+ frag->page_offset = 0;
+ frag->size = hlen;
+ RX_USED_ADD(page, hlen + cp->crc_size);
+ }
+
+ if (cp->crc_size) {
+ addr = cas_page_map(page->buffer);
+ crcaddr = addr + off + hlen;
+ }
+
+ } else {
+ /* copying packet */
+ if (!dlen)
+ goto end_copy_pkt;
+
+ i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+ page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+ off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
+ hlen = min(cp->page_size - off, dlen);
+ if (hlen < 0) {
+ if (netif_msg_rx_err(cp)) {
+ printk(KERN_DEBUG "%s: rx page overflow: "
+ "%d\n", cp->dev->name, hlen);
+ }
+ dev_kfree_skb_irq(skb);
+ return -1;
+ }
+ i = hlen;
+ if (i == dlen) /* attach FCS */
+ i += cp->crc_size;
+ pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+ addr = cas_page_map(page->buffer);
+ memcpy(p, addr + off, i);
+ pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+ PCI_DMA_FROMDEVICE);
+ cas_page_unmap(addr);
+ if (p == (char *) skb->data) /* not split */
+ RX_USED_ADD(page, cp->mtu_stride);
+ else
+ RX_USED_ADD(page, i);
+
+ /* any more data? */
+ if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
+ p += hlen;
+ i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+ page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+ pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr,
+ dlen + cp->crc_size,
+ PCI_DMA_FROMDEVICE);
+ addr = cas_page_map(page->buffer);
+ memcpy(p, addr, dlen + cp->crc_size);
+ pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
+ dlen + cp->crc_size,
+ PCI_DMA_FROMDEVICE);
+ cas_page_unmap(addr);
+ RX_USED_ADD(page, dlen + cp->crc_size);
+ }
+end_copy_pkt:
+ if (cp->crc_size) {
+ addr = NULL;
+ crcaddr = skb->data + alloclen;
+ }
+ skb_put(skb, alloclen);
+ }
+
+ i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]);
+ if (cp->crc_size) {
+ /* checksum includes FCS. strip it out. */
+ i = csum_fold(csum_partial(crcaddr, cp->crc_size, i));
+ if (addr)
+ cas_page_unmap(addr);
+ }
+ skb->csum = ntohs(i ^ 0xffff);
+ skb->ip_summed = CHECKSUM_HW;
+ skb->protocol = eth_type_trans(skb, cp->dev);
+ return len;
+}
+
+
+/* we can handle up to 64 rx flows at a time. we do the same thing
+ * as nonreassm except that we batch up the buffers.
+ * NOTE: we currently just treat each flow as a bunch of packets that
+ * we pass up. a better way would be to coalesce the packets
+ * into a jumbo packet. to do that, we need to do the following:
+ * 1) the first packet will have a clean split between header and
+ * data. save both.
+ * 2) each time the next flow packet comes in, extend the
+ * data length and merge the checksums.
+ * 3) on flow release, fix up the header.
+ * 4) make sure the higher layer doesn't care.
+ * because packets get coalesced, we shouldn't run into fragment count
+ * issues.
+ */
+static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words,
+ struct sk_buff *skb)
+{
+ int flowid = CAS_VAL(RX_COMP3_FLOWID, words[2]) & (N_RX_FLOWS - 1);
+ struct sk_buff_head *flow = &cp->rx_flows[flowid];
+
+ /* this is protected at a higher layer, so no need to
+ * do any additional locking here. stick the buffer
+ * at the end.
+ */
+ __skb_insert(skb, flow->prev, (struct sk_buff *) flow, flow);
+ if (words[0] & RX_COMP1_RELEASE_FLOW) {
+ while ((skb = __skb_dequeue(flow))) {
+ cas_skb_release(skb);
+ }
+ }
+}
+
+/* put rx descriptor back on ring. if a buffer is in use by a higher
+ * layer, this will need to put in a replacement.
+ */
+static void cas_post_page(struct cas *cp, const int ring, const int index)
+{
+ cas_page_t *new;
+ int entry;
+
+ entry = cp->rx_old[ring];
+
+ new = cas_page_swap(cp, ring, index);
+ cp->init_rxds[ring][entry].buffer = cpu_to_le64(new->dma_addr);
+ cp->init_rxds[ring][entry].index =
+ cpu_to_le64(CAS_BASE(RX_INDEX_NUM, index) |
+ CAS_BASE(RX_INDEX_RING, ring));
+
+ entry = RX_DESC_ENTRY(ring, entry + 1);
+ cp->rx_old[ring] = entry;
+
+ if (entry % 4)
+ return;
+
+ if (ring == 0)
+ writel(entry, cp->regs + REG_RX_KICK);
+ else if ((N_RX_DESC_RINGS > 1) &&
+ (cp->cas_flags & CAS_FLAG_REG_PLUS))
+ writel(entry, cp->regs + REG_PLUS_RX_KICK1);
+}
+
+
+/* only when things are bad */
+static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
+{
+ unsigned int entry, last, count, released;
+ int cluster;
+ cas_page_t **page = cp->rx_pages[ring];
+
+ entry = cp->rx_old[ring];
+
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: rxd[%d] interrupt, done: %d\n",
+ cp->dev->name, ring, entry);
+
+ cluster = -1;
+ count = entry & 0x3;
+ last = RX_DESC_ENTRY(ring, num ? entry + num - 4: entry - 4);
+ released = 0;
+ while (entry != last) {
+ /* make a new buffer if it's still in use */
+ if (page_count(page[entry]->buffer) > 1) {
+ cas_page_t *new = cas_page_dequeue(cp);
+ if (!new) {
+ /* let the timer know that we need to
+ * do this again
+ */
+ cp->cas_flags |= CAS_FLAG_RXD_POST(ring);
+ if (!timer_pending(&cp->link_timer))
+ mod_timer(&cp->link_timer, jiffies +
+ CAS_LINK_FAST_TIMEOUT);
+ cp->rx_old[ring] = entry;
+ cp->rx_last[ring] = num ? num - released : 0;
+ return -ENOMEM;
+ }
+ spin_lock(&cp->rx_inuse_lock);
+ list_add(&page[entry]->list, &cp->rx_inuse_list);
+ spin_unlock(&cp->rx_inuse_lock);
+ cp->init_rxds[ring][entry].buffer =
+ cpu_to_le64(new->dma_addr);
+ page[entry] = new;
+
+ }
+
+ if (++count == 4) {
+ cluster = entry;
+ count = 0;
+ }
+ released++;
+ entry = RX_DESC_ENTRY(ring, entry + 1);
+ }
+ cp->rx_old[ring] = entry;
+
+ if (cluster < 0)
+ return 0;
+
+ if (ring == 0)
+ writel(cluster, cp->regs + REG_RX_KICK);
+ else if ((N_RX_DESC_RINGS > 1) &&
+ (cp->cas_flags & CAS_FLAG_REG_PLUS))
+ writel(cluster, cp->regs + REG_PLUS_RX_KICK1);
+ return 0;
+}
+
+
+/* process a completion ring. packets are set up in three basic ways:
+ * small packets: should be copied header + data in single buffer.
+ * large packets: header and data in a single buffer.
+ * split packets: header in a separate buffer from data.
+ * data may be in multiple pages. data may be > 256
+ * bytes but in a single page.
+ *
+ * NOTE: RX page posting is done in this routine as well. while there's
+ * the capability of using multiple RX completion rings, it isn't
+ * really worthwhile due to the fact that the page posting will
+ * force serialization on the single descriptor ring.
+ */
+static int cas_rx_ringN(struct cas *cp, int ring, int budget)
+{
+ struct cas_rx_comp *rxcs = cp->init_rxcs[ring];
+ int entry, drops;
+ int npackets = 0;
+
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: rx[%d] interrupt, done: %d/%d\n",
+ cp->dev->name, ring,
+ readl(cp->regs + REG_RX_COMP_HEAD),
+ cp->rx_new[ring]);
+
+ entry = cp->rx_new[ring];
+ drops = 0;
+ while (1) {
+ struct cas_rx_comp *rxc = rxcs + entry;
+ struct sk_buff *skb;
+ int type, len;
+ u64 words[4];
+ int i, dring;
+
+ words[0] = le64_to_cpu(rxc->word1);
+ words[1] = le64_to_cpu(rxc->word2);
+ words[2] = le64_to_cpu(rxc->word3);
+ words[3] = le64_to_cpu(rxc->word4);
+
+ /* don't touch if still owned by hw */
+ type = CAS_VAL(RX_COMP1_TYPE, words[0]);
+ if (type == 0)
+ break;
+
+ /* hw hasn't cleared the zero bit yet */
+ if (words[3] & RX_COMP4_ZERO) {
+ break;
+ }
+
+ /* get info on the packet */
+ if (words[3] & (RX_COMP4_LEN_MISMATCH | RX_COMP4_BAD)) {
+ spin_lock(&cp->stat_lock[ring]);
+ cp->net_stats[ring].rx_errors++;
+ if (words[3] & RX_COMP4_LEN_MISMATCH)
+ cp->net_stats[ring].rx_length_errors++;
+ if (words[3] & RX_COMP4_BAD)
+ cp->net_stats[ring].rx_crc_errors++;
+ spin_unlock(&cp->stat_lock[ring]);
+
+ /* We'll just return it to Cassini. */
+ drop_it:
+ spin_lock(&cp->stat_lock[ring]);
+ ++cp->net_stats[ring].rx_dropped;
+ spin_unlock(&cp->stat_lock[ring]);
+ goto next;
+ }
+
+ len = cas_rx_process_pkt(cp, rxc, entry, words, &skb);
+ if (len < 0) {
+ ++drops;
+ goto drop_it;
+ }
+
+ /* see if it's a flow re-assembly or not. the driver
+ * itself handles release back up.
+ */
+ if (RX_DONT_BATCH || (type == 0x2)) {
+ /* non-reassm: these always get released */
+ cas_skb_release(skb);
+ } else {
+ cas_rx_flow_pkt(cp, words, skb);
+ }
+
+ spin_lock(&cp->stat_lock[ring]);
+ cp->net_stats[ring].rx_packets++;
+ cp->net_stats[ring].rx_bytes += len;
+ spin_unlock(&cp->stat_lock[ring]);
+ cp->dev->last_rx = jiffies;
+
+ next:
+ npackets++;
+
+ /* should it be released? */
+ if (words[0] & RX_COMP1_RELEASE_HDR) {
+ i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
+ dring = CAS_VAL(RX_INDEX_RING, i);
+ i = CAS_VAL(RX_INDEX_NUM, i);
+ cas_post_page(cp, dring, i);
+ }
+
+ if (words[0] & RX_COMP1_RELEASE_DATA) {
+ i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+ dring = CAS_VAL(RX_INDEX_RING, i);
+ i = CAS_VAL(RX_INDEX_NUM, i);
+ cas_post_page(cp, dring, i);
+ }
+
+ if (words[0] & RX_COMP1_RELEASE_NEXT) {
+ i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+ dring = CAS_VAL(RX_INDEX_RING, i);
+ i = CAS_VAL(RX_INDEX_NUM, i);
+ cas_post_page(cp, dring, i);
+ }
+
+ /* skip to the next entry */
+ entry = RX_COMP_ENTRY(ring, entry + 1 +
+ CAS_VAL(RX_COMP1_SKIP, words[0]));
+#ifdef USE_NAPI
+ if (budget && (npackets >= budget))
+ break;
+#endif
+ }
+ cp->rx_new[ring] = entry;
+
+ if (drops)
+ printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+ cp->dev->name);
+ return npackets;
+}
+
+
+/* put completion entries back on the ring */
+static void cas_post_rxcs_ringN(struct net_device *dev,
+ struct cas *cp, int ring)
+{
+ struct cas_rx_comp *rxc = cp->init_rxcs[ring];
+ int last, entry;
+
+ last = cp->rx_cur[ring];
+ entry = cp->rx_new[ring];
+ if (netif_msg_intr(cp))
+ printk(KERN_DEBUG "%s: rxc[%d] interrupt, done: %d/%d\n",
+ dev->name, ring, readl(cp->regs + REG_RX_COMP_HEAD),
+ entry);
+
+ /* zero and re-mark descriptors */
+ while (last != entry) {
+ cas_rxc_init(rxc + last);
+ last = RX_COMP_ENTRY(ring, last + 1);
+ }
+ cp->rx_cur[ring] = last;
+
+ if (ring == 0)
+ writel(last, cp->regs + REG_RX_COMP_TAIL);
+ else if (cp->cas_flags & CAS_FLAG_REG_PLUS)
+ writel(last, cp->regs + REG_PLUS_RX_COMPN_TAIL(ring));
+}
+
+
+
+/* cassini can use all four PCI interrupts for the completion ring.
+ * rings 3 and 4 are identical
+ */
+#if defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+static inline void cas_handle_irqN(struct net_device *dev,
+ struct cas *cp, const u32 status,
+ const int ring)
+{
+ if (status & (INTR_RX_COMP_FULL_ALT | INTR_RX_COMP_AF_ALT))
+ cas_post_rxcs_ringN(dev, cp, ring);
+}
+
+static irqreturn_t cas_interruptN(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+ int ring;
+ u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring));
+
+ /* check for shared irq */
+ if (status == 0)
+ return IRQ_NONE;
+
+ ring = (irq == cp->pci_irq_INTC) ? 2 : 3;
+ spin_lock_irqsave(&cp->lock, flags);
+ if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
+#ifdef USE_NAPI
+ cas_mask_intr(cp);
+ netif_rx_schedule(dev);
+#else
+ cas_rx_ringN(cp, ring, 0);
+#endif
+ status &= ~INTR_RX_DONE_ALT;
+ }
+
+ if (status)
+ cas_handle_irqN(dev, cp, status, ring);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ return IRQ_HANDLED;
+}
+#endif
+
+#ifdef USE_PCI_INTB
+/* everything but rx packets */
+static inline void cas_handle_irq1(struct cas *cp, const u32 status)
+{
+ if (status & INTR_RX_BUF_UNAVAIL_1) {
+ /* Frame arrived, no free RX buffers available.
+ * NOTE: we can get this on a link transition. */
+ cas_post_rxds_ringN(cp, 1, 0);
+ spin_lock(&cp->stat_lock[1]);
+ cp->net_stats[1].rx_dropped++;
+ spin_unlock(&cp->stat_lock[1]);
+ }
+
+ if (status & INTR_RX_BUF_AE_1)
+ cas_post_rxds_ringN(cp, 1, RX_DESC_RINGN_SIZE(1) -
+ RX_AE_FREEN_VAL(1));
+
+ if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
+ cas_post_rxcs_ringN(cp, 1);
+}
+
+/* ring 2 handles a few more events than 3 and 4 */
+static irqreturn_t cas_interrupt1(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+ u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
+
+ /* check for shared interrupt */
+ if (status == 0)
+ return IRQ_NONE;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
+#ifdef USE_NAPI
+ cas_mask_intr(cp);
+ netif_rx_schedule(dev);
+#else
+ cas_rx_ringN(cp, 1, 0);
+#endif
+ status &= ~INTR_RX_DONE_ALT;
+ }
+ if (status)
+ cas_handle_irq1(cp, status);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ return IRQ_HANDLED;
+}
+#endif
+
+static inline void cas_handle_irq(struct net_device *dev,
+ struct cas *cp, const u32 status)
+{
+ /* housekeeping interrupts */
+ if (status & INTR_ERROR_MASK)
+ cas_abnormal_irq(dev, cp, status);
+
+ if (status & INTR_RX_BUF_UNAVAIL) {
+ /* Frame arrived, no free RX buffers available.
+ * NOTE: we can get this on a link transition.
+ */
+ cas_post_rxds_ringN(cp, 0, 0);
+ spin_lock(&cp->stat_lock[0]);
+ cp->net_stats[0].rx_dropped++;
+ spin_unlock(&cp->stat_lock[0]);
+ } else if (status & INTR_RX_BUF_AE) {
+ cas_post_rxds_ringN(cp, 0, RX_DESC_RINGN_SIZE(0) -
+ RX_AE_FREEN_VAL(0));
+ }
+
+ if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
+ cas_post_rxcs_ringN(dev, cp, 0);
+}
+
+static irqreturn_t cas_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+ u32 status = readl(cp->regs + REG_INTR_STATUS);
+
+ if (status == 0)
+ return IRQ_NONE;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ if (status & (INTR_TX_ALL | INTR_TX_INTME)) {
+ cas_tx(dev, cp, status);
+ status &= ~(INTR_TX_ALL | INTR_TX_INTME);
+ }
+
+ if (status & INTR_RX_DONE) {
+#ifdef USE_NAPI
+ cas_mask_intr(cp);
+ netif_rx_schedule(dev);
+#else
+ cas_rx_ringN(cp, 0, 0);
+#endif
+ status &= ~INTR_RX_DONE;
+ }
+
+ if (status)
+ cas_handle_irq(dev, cp, status);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ return IRQ_HANDLED;
+}
+
+
+#ifdef USE_NAPI
+static int cas_poll(struct net_device *dev, int *budget)
+{
+ struct cas *cp = netdev_priv(dev);
+ int i, enable_intr, todo, credits;
+ u32 status = readl(cp->regs + REG_INTR_STATUS);
+ unsigned long flags;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_tx(dev, cp, status);
+ spin_unlock_irqrestore(&cp->lock, flags);
+
+ /* NAPI rx packets. we spread the credits across all of the
+ * rxc rings
+ */
+ todo = min(*budget, dev->quota);
+
+ /* to make sure we're fair with the work we loop through each
+ * ring N_RX_COMP_RING times with a request of
+ * todo / N_RX_COMP_RINGS
+ */
+ enable_intr = 1;
+ credits = 0;
+ for (i = 0; i < N_RX_COMP_RINGS; i++) {
+ int j;
+ for (j = 0; j < N_RX_COMP_RINGS; j++) {
+ credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS);
+ if (credits >= todo) {
+ enable_intr = 0;
+ goto rx_comp;
+ }
+ }
+ }
+
+rx_comp:
+ *budget -= credits;
+ dev->quota -= credits;
+
+ /* final rx completion */
+ spin_lock_irqsave(&cp->lock, flags);
+ if (status)
+ cas_handle_irq(dev, cp, status);
+
+#ifdef USE_PCI_INTB
+ if (N_RX_COMP_RINGS > 1) {
+ status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
+ if (status)
+ cas_handle_irq1(dev, cp, status);
+ }
+#endif
+
+#ifdef USE_PCI_INTC
+ if (N_RX_COMP_RINGS > 2) {
+ status = readl(cp->regs + REG_PLUS_INTRN_STATUS(2));
+ if (status)
+ cas_handle_irqN(dev, cp, status, 2);
+ }
+#endif
+
+#ifdef USE_PCI_INTD
+ if (N_RX_COMP_RINGS > 3) {
+ status = readl(cp->regs + REG_PLUS_INTRN_STATUS(3));
+ if (status)
+ cas_handle_irqN(dev, cp, status, 3);
+ }
+#endif
+ spin_unlock_irqrestore(&cp->lock, flags);
+ if (enable_intr) {
+ netif_rx_complete(dev);
+ cas_unmask_intr(cp);
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void cas_netpoll(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+
+ cas_disable_irq(cp, 0);
+ cas_interrupt(cp->pdev->irq, dev, NULL);
+ cas_enable_irq(cp, 0);
+
+#ifdef USE_PCI_INTB
+ if (N_RX_COMP_RINGS > 1) {
+ /* cas_interrupt1(); */
+ }
+#endif
+#ifdef USE_PCI_INTC
+ if (N_RX_COMP_RINGS > 2) {
+ /* cas_interruptN(); */
+ }
+#endif
+#ifdef USE_PCI_INTD
+ if (N_RX_COMP_RINGS > 3) {
+ /* cas_interruptN(); */
+ }
+#endif
+}
+#endif
+
+static void cas_tx_timeout(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+
+ printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+ if (!cp->hw_running) {
+ printk("%s: hrm.. hw not running!\n", dev->name);
+ return;
+ }
+
+ printk(KERN_ERR "%s: MIF_STATE[%08x]\n",
+ dev->name, readl(cp->regs + REG_MIF_STATE_MACHINE));
+
+ printk(KERN_ERR "%s: MAC_STATE[%08x]\n",
+ dev->name, readl(cp->regs + REG_MAC_STATE_MACHINE));
+
+ printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x] "
+ "FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n",
+ dev->name,
+ readl(cp->regs + REG_TX_CFG),
+ readl(cp->regs + REG_MAC_TX_STATUS),
+ readl(cp->regs + REG_MAC_TX_CFG),
+ readl(cp->regs + REG_TX_FIFO_PKT_CNT),
+ readl(cp->regs + REG_TX_FIFO_WRITE_PTR),
+ readl(cp->regs + REG_TX_FIFO_READ_PTR),
+ readl(cp->regs + REG_TX_SM_1),
+ readl(cp->regs + REG_TX_SM_2));
+
+ printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n",
+ dev->name,
+ readl(cp->regs + REG_RX_CFG),
+ readl(cp->regs + REG_MAC_RX_STATUS),
+ readl(cp->regs + REG_MAC_RX_CFG));
+
+ printk(KERN_ERR "%s: HP_STATE[%08x:%08x:%08x:%08x]\n",
+ dev->name,
+ readl(cp->regs + REG_HP_STATE_MACHINE),
+ readl(cp->regs + REG_HP_STATUS0),
+ readl(cp->regs + REG_HP_STATUS1),
+ readl(cp->regs + REG_HP_STATUS2));
+
+#if 1
+ atomic_inc(&cp->reset_task_pending);
+ atomic_inc(&cp->reset_task_pending_all);
+ schedule_work(&cp->reset_task);
+#else
+ atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+ schedule_work(&cp->reset_task);
+#endif
+}
+
+static inline int cas_intme(int ring, int entry)
+{
+ /* Algorithm: IRQ every 1/2 of descriptors. */
+ if (!(entry & ((TX_DESC_RINGN_SIZE(ring) >> 1) - 1)))
+ return 1;
+ return 0;
+}
+
+
+static void cas_write_txd(struct cas *cp, int ring, int entry,
+ dma_addr_t mapping, int len, u64 ctrl, int last)
+{
+ struct cas_tx_desc *txd = cp->init_txds[ring] + entry;
+
+ ctrl |= CAS_BASE(TX_DESC_BUFLEN, len);
+ if (cas_intme(ring, entry))
+ ctrl |= TX_DESC_INTME;
+ if (last)
+ ctrl |= TX_DESC_EOF;
+ txd->control = cpu_to_le64(ctrl);
+ txd->buffer = cpu_to_le64(mapping);
+}
+
+static inline void *tx_tiny_buf(struct cas *cp, const int ring,
+ const int entry)
+{
+ return cp->tx_tiny_bufs[ring] + TX_TINY_BUF_LEN*entry;
+}
+
+static inline dma_addr_t tx_tiny_map(struct cas *cp, const int ring,
+ const int entry, const int tentry)
+{
+ cp->tx_tiny_use[ring][tentry].nbufs++;
+ cp->tx_tiny_use[ring][entry].used = 1;
+ return cp->tx_tiny_dvma[ring] + TX_TINY_BUF_LEN*entry;
+}
+
+static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
+ struct sk_buff *skb)
+{
+ struct net_device *dev = cp->dev;
+ int entry, nr_frags, frag, tabort, tentry;
+ dma_addr_t mapping;
+ unsigned long flags;
+ u64 ctrl;
+ u32 len;
+
+ spin_lock_irqsave(&cp->tx_lock[ring], flags);
+
+ /* This is a hard error, log it. */
+ if (TX_BUFFS_AVAIL(cp, ring) <=
+ CAS_TABORT(cp)*(skb_shinfo(skb)->nr_frags + 1)) {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
+ printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+ "queue awake!\n", dev->name);
+ return 1;
+ }
+
+ ctrl = 0;
+ if (skb->ip_summed == CHECKSUM_HW) {
+ u64 csum_start_off, csum_stuff_off;
+
+ csum_start_off = (u64) (skb->h.raw - skb->data);
+ csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data);
+
+ ctrl = TX_DESC_CSUM_EN |
+ CAS_BASE(TX_DESC_CSUM_START, csum_start_off) |
+ CAS_BASE(TX_DESC_CSUM_STUFF, csum_stuff_off);
+ }
+
+ entry = cp->tx_new[ring];
+ cp->tx_skbs[ring][entry] = skb;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ len = skb_headlen(skb);
+ mapping = pci_map_page(cp->pdev, virt_to_page(skb->data),
+ offset_in_page(skb->data), len,
+ PCI_DMA_TODEVICE);
+
+ tentry = entry;
+ tabort = cas_calc_tabort(cp, (unsigned long) skb->data, len);
+ if (unlikely(tabort)) {
+ /* NOTE: len is always > tabort */
+ cas_write_txd(cp, ring, entry, mapping, len - tabort,
+ ctrl | TX_DESC_SOF, 0);
+ entry = TX_DESC_NEXT(ring, entry);
+
+ memcpy(tx_tiny_buf(cp, ring, entry), skb->data +
+ len - tabort, tabort);
+ mapping = tx_tiny_map(cp, ring, entry, tentry);
+ cas_write_txd(cp, ring, entry, mapping, tabort, ctrl,
+ (nr_frags == 0));
+ } else {
+ cas_write_txd(cp, ring, entry, mapping, len, ctrl |
+ TX_DESC_SOF, (nr_frags == 0));
+ }
+ entry = TX_DESC_NEXT(ring, entry);
+
+ for (frag = 0; frag < nr_frags; frag++) {
+ skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
+
+ len = fragp->size;
+ mapping = pci_map_page(cp->pdev, fragp->page,
+ fragp->page_offset, len,
+ PCI_DMA_TODEVICE);
+
+ tabort = cas_calc_tabort(cp, fragp->page_offset, len);
+ if (unlikely(tabort)) {
+ void *addr;
+
+ /* NOTE: len is always > tabort */
+ cas_write_txd(cp, ring, entry, mapping, len - tabort,
+ ctrl, 0);
+ entry = TX_DESC_NEXT(ring, entry);
+
+ addr = cas_page_map(fragp->page);
+ memcpy(tx_tiny_buf(cp, ring, entry),
+ addr + fragp->page_offset + len - tabort,
+ tabort);
+ cas_page_unmap(addr);
+ mapping = tx_tiny_map(cp, ring, entry, tentry);
+ len = tabort;
+ }
+
+ cas_write_txd(cp, ring, entry, mapping, len, ctrl,
+ (frag + 1 == nr_frags));
+ entry = TX_DESC_NEXT(ring, entry);
+ }
+
+ cp->tx_new[ring] = entry;
+ if (TX_BUFFS_AVAIL(cp, ring) <= CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1))
+ netif_stop_queue(dev);
+
+ if (netif_msg_tx_queued(cp))
+ printk(KERN_DEBUG "%s: tx[%d] queued, slot %d, skblen %d, "
+ "avail %d\n",
+ dev->name, ring, entry, skb->len,
+ TX_BUFFS_AVAIL(cp, ring));
+ writel(entry, cp->regs + REG_TX_KICKN(ring));
+ spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
+ return 0;
+}
+
+static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+
+ /* this is only used as a load-balancing hint, so it doesn't
+ * need to be SMP safe
+ */
+ static int ring;
+
+ skb = skb_padto(skb, cp->min_frame_size);
+ if (!skb)
+ return 0;
+
+ /* XXX: we need some higher-level QoS hooks to steer packets to
+ * individual queues.
+ */
+ if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb))
+ return 1;
+ dev->trans_start = jiffies;
+ return 0;
+}
+
+static void cas_init_tx_dma(struct cas *cp)
+{
+ u64 desc_dma = cp->block_dvma;
+ unsigned long off;
+ u32 val;
+ int i;
+
+ /* set up tx completion writeback registers. must be 8-byte aligned */
+#ifdef USE_TX_COMPWB
+ off = offsetof(struct cas_init_block, tx_compwb);
+ writel((desc_dma + off) >> 32, cp->regs + REG_TX_COMPWB_DB_HI);
+ writel((desc_dma + off) & 0xffffffff, cp->regs + REG_TX_COMPWB_DB_LOW);
+#endif
+
+ /* enable completion writebacks, enable paced mode,
+ * disable read pipe, and disable pre-interrupt compwbs
+ */
+ val = TX_CFG_COMPWB_Q1 | TX_CFG_COMPWB_Q2 |
+ TX_CFG_COMPWB_Q3 | TX_CFG_COMPWB_Q4 |
+ TX_CFG_DMA_RDPIPE_DIS | TX_CFG_PACED_MODE |
+ TX_CFG_INTR_COMPWB_DIS;
+
+ /* write out tx ring info and tx desc bases */
+ for (i = 0; i < MAX_TX_RINGS; i++) {
+ off = (unsigned long) cp->init_txds[i] -
+ (unsigned long) cp->init_block;
+
+ val |= CAS_TX_RINGN_BASE(i);
+ writel((desc_dma + off) >> 32, cp->regs + REG_TX_DBN_HI(i));
+ writel((desc_dma + off) & 0xffffffff, cp->regs +
+ REG_TX_DBN_LOW(i));
+ /* don't zero out the kick register here as the system
+ * will wedge
+ */
+ }
+ writel(val, cp->regs + REG_TX_CFG);
+
+ /* program max burst sizes. these numbers should be different
+ * if doing QoS.
+ */
+#ifdef USE_QOS
+ writel(0x800, cp->regs + REG_TX_MAXBURST_0);
+ writel(0x1600, cp->regs + REG_TX_MAXBURST_1);
+ writel(0x2400, cp->regs + REG_TX_MAXBURST_2);
+ writel(0x4800, cp->regs + REG_TX_MAXBURST_3);
+#else
+ writel(0x800, cp->regs + REG_TX_MAXBURST_0);
+ writel(0x800, cp->regs + REG_TX_MAXBURST_1);
+ writel(0x800, cp->regs + REG_TX_MAXBURST_2);
+ writel(0x800, cp->regs + REG_TX_MAXBURST_3);
+#endif
+}
+
+/* Must be invoked under cp->lock. */
+static inline void cas_init_dma(struct cas *cp)
+{
+ cas_init_tx_dma(cp);
+ cas_init_rx_dma(cp);
+}
+
+/* Must be invoked under cp->lock. */
+static u32 cas_setup_multicast(struct cas *cp)
+{
+ u32 rxcfg = 0;
+ int i;
+
+ if (cp->dev->flags & IFF_PROMISC) {
+ rxcfg |= MAC_RX_CFG_PROMISC_EN;
+
+ } else if (cp->dev->flags & IFF_ALLMULTI) {
+ for (i=0; i < 16; i++)
+ writel(0xFFFF, cp->regs + REG_MAC_HASH_TABLEN(i));
+ rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
+
+ } else {
+ u16 hash_table[16];
+ u32 crc;
+ struct dev_mc_list *dmi = cp->dev->mc_list;
+ int i;
+
+ /* use the alternate mac address registers for the
+ * first 15 multicast addresses
+ */
+ for (i = 1; i <= CAS_MC_EXACT_MATCH_SIZE; i++) {
+ if (!dmi) {
+ writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 0));
+ writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 1));
+ writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 2));
+ continue;
+ }
+ writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5],
+ cp->regs + REG_MAC_ADDRN(i*3 + 0));
+ writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3],
+ cp->regs + REG_MAC_ADDRN(i*3 + 1));
+ writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1],
+ cp->regs + REG_MAC_ADDRN(i*3 + 2));
+ dmi = dmi->next;
+ }
+
+ /* use hw hash table for the next series of
+ * multicast addresses
+ */
+ memset(hash_table, 0, sizeof(hash_table));
+ while (dmi) {
+ crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr);
+ crc >>= 24;
+ hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
+ dmi = dmi->next;
+ }
+ for (i=0; i < 16; i++)
+ writel(hash_table[i], cp->regs +
+ REG_MAC_HASH_TABLEN(i));
+ rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
+ }
+
+ return rxcfg;
+}
+
+/* must be invoked under cp->stat_lock[N_TX_RINGS] */
+static void cas_clear_mac_err(struct cas *cp)
+{
+ writel(0, cp->regs + REG_MAC_COLL_NORMAL);
+ writel(0, cp->regs + REG_MAC_COLL_FIRST);
+ writel(0, cp->regs + REG_MAC_COLL_EXCESS);
+ writel(0, cp->regs + REG_MAC_COLL_LATE);
+ writel(0, cp->regs + REG_MAC_TIMER_DEFER);
+ writel(0, cp->regs + REG_MAC_ATTEMPTS_PEAK);
+ writel(0, cp->regs + REG_MAC_RECV_FRAME);
+ writel(0, cp->regs + REG_MAC_LEN_ERR);
+ writel(0, cp->regs + REG_MAC_ALIGN_ERR);
+ writel(0, cp->regs + REG_MAC_FCS_ERR);
+ writel(0, cp->regs + REG_MAC_RX_CODE_ERR);
+}
+
+
+static void cas_mac_reset(struct cas *cp)
+{
+ int i;
+
+ /* do both TX and RX reset */
+ writel(0x1, cp->regs + REG_MAC_TX_RESET);
+ writel(0x1, cp->regs + REG_MAC_RX_RESET);
+
+ /* wait for TX */
+ i = STOP_TRIES;
+ while (i-- > 0) {
+ if (readl(cp->regs + REG_MAC_TX_RESET) == 0)
+ break;
+ udelay(10);
+ }
+
+ /* wait for RX */
+ i = STOP_TRIES;
+ while (i-- > 0) {
+ if (readl(cp->regs + REG_MAC_RX_RESET) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (readl(cp->regs + REG_MAC_TX_RESET) |
+ readl(cp->regs + REG_MAC_RX_RESET))
+ printk(KERN_ERR "%s: mac tx[%d]/rx[%d] reset failed [%08x]\n",
+ cp->dev->name, readl(cp->regs + REG_MAC_TX_RESET),
+ readl(cp->regs + REG_MAC_RX_RESET),
+ readl(cp->regs + REG_MAC_STATE_MACHINE));
+}
+
+
+/* Must be invoked under cp->lock. */
+static void cas_init_mac(struct cas *cp)
+{
+ unsigned char *e = &cp->dev->dev_addr[0];
+ int i;
+#ifdef CONFIG_CASSINI_MULTICAST_REG_WRITE
+ u32 rxcfg;
+#endif
+ cas_mac_reset(cp);
+
+ /* setup core arbitration weight register */
+ writel(CAWR_RR_DIS, cp->regs + REG_CAWR);
+
+ /* XXX Use pci_dma_burst_advice() */
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
+ /* set the infinite burst register for chips that don't have
+ * pci issues.
+ */
+ if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) == 0)
+ writel(INF_BURST_EN, cp->regs + REG_INF_BURST);
+#endif
+
+ writel(0x1BF0, cp->regs + REG_MAC_SEND_PAUSE);
+
+ writel(0x00, cp->regs + REG_MAC_IPG0);
+ writel(0x08, cp->regs + REG_MAC_IPG1);
+ writel(0x04, cp->regs + REG_MAC_IPG2);
+
+ /* change later for 802.3z */
+ writel(0x40, cp->regs + REG_MAC_SLOT_TIME);
+
+ /* min frame + FCS */
+ writel(ETH_ZLEN + 4, cp->regs + REG_MAC_FRAMESIZE_MIN);
+
+ /* Ethernet payload + header + FCS + optional VLAN tag. NOTE: we
+ * specify the maximum frame size to prevent RX tag errors on
+ * oversized frames.
+ */
+ writel(CAS_BASE(MAC_FRAMESIZE_MAX_BURST, 0x2000) |
+ CAS_BASE(MAC_FRAMESIZE_MAX_FRAME,
+ (CAS_MAX_MTU + ETH_HLEN + 4 + 4)),
+ cp->regs + REG_MAC_FRAMESIZE_MAX);
+
+ /* NOTE: crc_size is used as a surrogate for half-duplex.
+ * workaround saturn half-duplex issue by increasing preamble
+ * size to 65 bytes.
+ */
+ if ((cp->cas_flags & CAS_FLAG_SATURN) && cp->crc_size)
+ writel(0x41, cp->regs + REG_MAC_PA_SIZE);
+ else
+ writel(0x07, cp->regs + REG_MAC_PA_SIZE);
+ writel(0x04, cp->regs + REG_MAC_JAM_SIZE);
+ writel(0x10, cp->regs + REG_MAC_ATTEMPT_LIMIT);
+ writel(0x8808, cp->regs + REG_MAC_CTRL_TYPE);
+
+ writel((e[5] | (e[4] << 8)) & 0x3ff, cp->regs + REG_MAC_RANDOM_SEED);
+
+ writel(0, cp->regs + REG_MAC_ADDR_FILTER0);
+ writel(0, cp->regs + REG_MAC_ADDR_FILTER1);
+ writel(0, cp->regs + REG_MAC_ADDR_FILTER2);
+ writel(0, cp->regs + REG_MAC_ADDR_FILTER2_1_MASK);
+ writel(0, cp->regs + REG_MAC_ADDR_FILTER0_MASK);
+
+ /* setup mac address in perfect filter array */
+ for (i = 0; i < 45; i++)
+ writel(0x0, cp->regs + REG_MAC_ADDRN(i));
+
+ writel((e[4] << 8) | e[5], cp->regs + REG_MAC_ADDRN(0));
+ writel((e[2] << 8) | e[3], cp->regs + REG_MAC_ADDRN(1));
+ writel((e[0] << 8) | e[1], cp->regs + REG_MAC_ADDRN(2));
+
+ writel(0x0001, cp->regs + REG_MAC_ADDRN(42));
+ writel(0xc200, cp->regs + REG_MAC_ADDRN(43));
+ writel(0x0180, cp->regs + REG_MAC_ADDRN(44));
+
+#ifndef CONFIG_CASSINI_MULTICAST_REG_WRITE
+ cp->mac_rx_cfg = cas_setup_multicast(cp);
+#else
+ /* WTZ: Do what Adrian did in cas_set_multicast. Doing
+ * a writel does not seem to be necessary because Cassini
+ * seems to preserve the configuration when we do the reset.
+ * If the chip is in trouble, though, it is not clear if we
+ * can really count on this behavior. cas_set_multicast uses
+ * spin_lock_irqsave, but we are called only in cas_init_hw and
+ * cas_init_hw is protected by cas_lock_all, which calls
+ * spin_lock_irq (so it doesn't need to save the flags, and
+ * we should be OK for the writel, as that is the only
+ * difference).
+ */
+ cp->mac_rx_cfg = rxcfg = cas_setup_multicast(cp);
+ writel(rxcfg, cp->regs + REG_MAC_RX_CFG);
+#endif
+ spin_lock(&cp->stat_lock[N_TX_RINGS]);
+ cas_clear_mac_err(cp);
+ spin_unlock(&cp->stat_lock[N_TX_RINGS]);
+
+ /* Setup MAC interrupts. We want to get all of the interesting
+ * counter expiration events, but we do not want to hear about
+ * normal rx/tx as the DMA engine tells us that.
+ */
+ writel(MAC_TX_FRAME_XMIT, cp->regs + REG_MAC_TX_MASK);
+ writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
+
+ /* Don't enable even the PAUSE interrupts for now, we
+ * make no use of those events other than to record them.
+ */
+ writel(0xffffffff, cp->regs + REG_MAC_CTRL_MASK);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_init_pause_thresholds(struct cas *cp)
+{
+ /* Calculate pause thresholds. Setting the OFF threshold to the
+ * full RX fifo size effectively disables PAUSE generation
+ */
+ if (cp->rx_fifo_size <= (2 * 1024)) {
+ cp->rx_pause_off = cp->rx_pause_on = cp->rx_fifo_size;
+ } else {
+ int max_frame = (cp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63;
+ if (max_frame * 3 > cp->rx_fifo_size) {
+ cp->rx_pause_off = 7104;
+ cp->rx_pause_on = 960;
+ } else {
+ int off = (cp->rx_fifo_size - (max_frame * 2));
+ int on = off - max_frame;
+ cp->rx_pause_off = off;
+ cp->rx_pause_on = on;
+ }
+ }
+}
+
+static int cas_vpd_match(const void __iomem *p, const char *str)
+{
+ int len = strlen(str) + 1;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (readb(p + i) != str[i])
+ return 0;
+ }
+ return 1;
+}
+
+
+/* get the mac address by reading the vpd information in the rom.
+ * also get the phy type and determine if there's an entropy generator.
+ * NOTE: this is a bit convoluted for the following reasons:
+ * 1) vpd info has order-dependent mac addresses for multinic cards
+ * 2) the only way to determine the nic order is to use the slot
+ * number.
+ * 3) fiber cards don't have bridges, so their slot numbers don't
+ * mean anything.
+ * 4) we don't actually know we have a fiber card until after
+ * the mac addresses are parsed.
+ */
+static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr,
+ const int offset)
+{
+ void __iomem *p = cp->regs + REG_EXPANSION_ROM_RUN_START;
+ void __iomem *base, *kstart;
+ int i, len;
+ int found = 0;
+#define VPD_FOUND_MAC 0x01
+#define VPD_FOUND_PHY 0x02
+
+ int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */
+ int mac_off = 0;
+
+ /* give us access to the PROM */
+ writel(BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_PAD,
+ cp->regs + REG_BIM_LOCAL_DEV_EN);
+
+ /* check for an expansion rom */
+ if (readb(p) != 0x55 || readb(p + 1) != 0xaa)
+ goto use_random_mac_addr;
+
+ /* search for beginning of vpd */
+ base = NULL;
+ for (i = 2; i < EXPANSION_ROM_SIZE; i++) {
+ /* check for PCIR */
+ if ((readb(p + i + 0) == 0x50) &&
+ (readb(p + i + 1) == 0x43) &&
+ (readb(p + i + 2) == 0x49) &&
+ (readb(p + i + 3) == 0x52)) {
+ base = p + (readb(p + i + 8) |
+ (readb(p + i + 9) << 8));
+ break;
+ }
+ }
+
+ if (!base || (readb(base) != 0x82))
+ goto use_random_mac_addr;
+
+ i = (readb(base + 1) | (readb(base + 2) << 8)) + 3;
+ while (i < EXPANSION_ROM_SIZE) {
+ if (readb(base + i) != 0x90) /* no vpd found */
+ goto use_random_mac_addr;
+
+ /* found a vpd field */
+ len = readb(base + i + 1) | (readb(base + i + 2) << 8);
+
+ /* extract keywords */
+ kstart = base + i + 3;
+ p = kstart;
+ while ((p - kstart) < len) {
+ int klen = readb(p + 2);
+ int j;
+ char type;
+
+ p += 3;
+
+ /* look for the following things:
+ * -- correct length == 29
+ * 3 (type) + 2 (size) +
+ * 18 (strlen("local-mac-address") + 1) +
+ * 6 (mac addr)
+ * -- VPD Instance 'I'
+ * -- VPD Type Bytes 'B'
+ * -- VPD data length == 6
+ * -- property string == local-mac-address
+ *
+ * -- correct length == 24
+ * 3 (type) + 2 (size) +
+ * 12 (strlen("entropy-dev") + 1) +
+ * 7 (strlen("vms110") + 1)
+ * -- VPD Instance 'I'
+ * -- VPD Type String 'B'
+ * -- VPD data length == 7
+ * -- property string == entropy-dev
+ *
+ * -- correct length == 18
+ * 3 (type) + 2 (size) +
+ * 9 (strlen("phy-type") + 1) +
+ * 4 (strlen("pcs") + 1)
+ * -- VPD Instance 'I'
+ * -- VPD Type String 'S'
+ * -- VPD data length == 4
+ * -- property string == phy-type
+ *
+ * -- correct length == 23
+ * 3 (type) + 2 (size) +
+ * 14 (strlen("phy-interface") + 1) +
+ * 4 (strlen("pcs") + 1)
+ * -- VPD Instance 'I'
+ * -- VPD Type String 'S'
+ * -- VPD data length == 4
+ * -- property string == phy-interface
+ */
+ if (readb(p) != 'I')
+ goto next;
+
+ /* finally, check string and length */
+ type = readb(p + 3);
+ if (type == 'B') {
+ if ((klen == 29) && readb(p + 4) == 6 &&
+ cas_vpd_match(p + 5,
+ "local-mac-address")) {
+ if (mac_off++ > offset)
+ goto next;
+
+ /* set mac address */
+ for (j = 0; j < 6; j++)
+ dev_addr[j] =
+ readb(p + 23 + j);
+ goto found_mac;
+ }
+ }
+
+ if (type != 'S')
+ goto next;
+
+#ifdef USE_ENTROPY_DEV
+ if ((klen == 24) &&
+ cas_vpd_match(p + 5, "entropy-dev") &&
+ cas_vpd_match(p + 17, "vms110")) {
+ cp->cas_flags |= CAS_FLAG_ENTROPY_DEV;
+ goto next;
+ }
+#endif
+
+ if (found & VPD_FOUND_PHY)
+ goto next;
+
+ if ((klen == 18) && readb(p + 4) == 4 &&
+ cas_vpd_match(p + 5, "phy-type")) {
+ if (cas_vpd_match(p + 14, "pcs")) {
+ phy_type = CAS_PHY_SERDES;
+ goto found_phy;
+ }
+ }
+
+ if ((klen == 23) && readb(p + 4) == 4 &&
+ cas_vpd_match(p + 5, "phy-interface")) {
+ if (cas_vpd_match(p + 19, "pcs")) {
+ phy_type = CAS_PHY_SERDES;
+ goto found_phy;
+ }
+ }
+found_mac:
+ found |= VPD_FOUND_MAC;
+ goto next;
+
+found_phy:
+ found |= VPD_FOUND_PHY;
+
+next:
+ p += klen;
+ }
+ i += len + 3;
+ }
+
+use_random_mac_addr:
+ if (found & VPD_FOUND_MAC)
+ goto done;
+
+ /* Sun MAC prefix then 3 random bytes. */
+ printk(PFX "MAC address not found in ROM VPD\n");
+ dev_addr[0] = 0x08;
+ dev_addr[1] = 0x00;
+ dev_addr[2] = 0x20;
+ get_random_bytes(dev_addr + 3, 3);
+
+done:
+ writel(0, cp->regs + REG_BIM_LOCAL_DEV_EN);
+ return phy_type;
+}
+
+/* check pci invariants */
+static void cas_check_pci_invariants(struct cas *cp)
+{
+ struct pci_dev *pdev = cp->pdev;
+ u8 rev;
+
+ cp->cas_flags = 0;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+ (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
+ if (rev >= CAS_ID_REVPLUS)
+ cp->cas_flags |= CAS_FLAG_REG_PLUS;
+ if (rev < CAS_ID_REVPLUS02u)
+ cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
+
+ /* Original Cassini supports HW CSUM, but it's not
+ * enabled by default as it can trigger TX hangs.
+ */
+ if (rev < CAS_ID_REV2)
+ cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
+ } else {
+ /* Only sun has original cassini chips. */
+ cp->cas_flags |= CAS_FLAG_REG_PLUS;
+
+ /* We use a flag because the same phy might be externally
+ * connected.
+ */
+ if ((pdev->vendor == PCI_VENDOR_ID_NS) &&
+ (pdev->device == PCI_DEVICE_ID_NS_SATURN))
+ cp->cas_flags |= CAS_FLAG_SATURN;
+ }
+}
+
+
+static int cas_check_invariants(struct cas *cp)
+{
+ struct pci_dev *pdev = cp->pdev;
+ u32 cfg;
+ int i;
+
+ /* get page size for rx buffers. */
+ cp->page_order = 0;
+#ifdef USE_PAGE_ORDER
+ if (PAGE_SHIFT < CAS_JUMBO_PAGE_SHIFT) {
+ /* see if we can allocate larger pages */
+ struct page *page = alloc_pages(GFP_ATOMIC,
+ CAS_JUMBO_PAGE_SHIFT -
+ PAGE_SHIFT);
+ if (page) {
+ __free_pages(page, CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT);
+ cp->page_order = CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT;
+ } else {
+ printk(PFX "MTU limited to %d bytes\n", CAS_MAX_MTU);
+ }
+ }
+#endif
+ cp->page_size = (PAGE_SIZE << cp->page_order);
+
+ /* Fetch the FIFO configurations. */
+ cp->tx_fifo_size = readl(cp->regs + REG_TX_FIFO_SIZE) * 64;
+ cp->rx_fifo_size = RX_FIFO_SIZE;
+
+ /* finish phy determination. MDIO1 takes precedence over MDIO0 if
+ * they're both connected.
+ */
+ cp->phy_type = cas_get_vpd_info(cp, cp->dev->dev_addr,
+ PCI_SLOT(pdev->devfn));
+ if (cp->phy_type & CAS_PHY_SERDES) {
+ cp->cas_flags |= CAS_FLAG_1000MB_CAP;
+ return 0; /* no more checking needed */
+ }
+
+ /* MII */
+ cfg = readl(cp->regs + REG_MIF_CFG);
+ if (cfg & MIF_CFG_MDIO_1) {
+ cp->phy_type = CAS_PHY_MII_MDIO1;
+ } else if (cfg & MIF_CFG_MDIO_0) {
+ cp->phy_type = CAS_PHY_MII_MDIO0;
+ }
+
+ cas_mif_poll(cp, 0);
+ writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
+
+ for (i = 0; i < 32; i++) {
+ u32 phy_id;
+ int j;
+
+ for (j = 0; j < 3; j++) {
+ cp->phy_addr = i;
+ phy_id = cas_phy_read(cp, MII_PHYSID1) << 16;
+ phy_id |= cas_phy_read(cp, MII_PHYSID2);
+ if (phy_id && (phy_id != 0xFFFFFFFF)) {
+ cp->phy_id = phy_id;
+ goto done;
+ }
+ }
+ }
+ printk(KERN_ERR PFX "MII phy did not respond [%08x]\n",
+ readl(cp->regs + REG_MIF_STATE_MACHINE));
+ return -1;
+
+done:
+ /* see if we can do gigabit */
+ cfg = cas_phy_read(cp, MII_BMSR);
+ if ((cfg & CAS_BMSR_1000_EXTEND) &&
+ cas_phy_read(cp, CAS_MII_1000_EXTEND))
+ cp->cas_flags |= CAS_FLAG_1000MB_CAP;
+ return 0;
+}
+
+/* Must be invoked under cp->lock. */
+static inline void cas_start_dma(struct cas *cp)
+{
+ int i;
+ u32 val;
+ int txfailed = 0;
+
+ /* enable dma */
+ val = readl(cp->regs + REG_TX_CFG) | TX_CFG_DMA_EN;
+ writel(val, cp->regs + REG_TX_CFG);
+ val = readl(cp->regs + REG_RX_CFG) | RX_CFG_DMA_EN;
+ writel(val, cp->regs + REG_RX_CFG);
+
+ /* enable the mac */
+ val = readl(cp->regs + REG_MAC_TX_CFG) | MAC_TX_CFG_EN;
+ writel(val, cp->regs + REG_MAC_TX_CFG);
+ val = readl(cp->regs + REG_MAC_RX_CFG) | MAC_RX_CFG_EN;
+ writel(val, cp->regs + REG_MAC_RX_CFG);
+
+ i = STOP_TRIES;
+ while (i-- > 0) {
+ val = readl(cp->regs + REG_MAC_TX_CFG);
+ if ((val & MAC_TX_CFG_EN))
+ break;
+ udelay(10);
+ }
+ if (i < 0) txfailed = 1;
+ i = STOP_TRIES;
+ while (i-- > 0) {
+ val = readl(cp->regs + REG_MAC_RX_CFG);
+ if ((val & MAC_RX_CFG_EN)) {
+ if (txfailed) {
+ printk(KERN_ERR
+ "%s: enabling mac failed [tx:%08x:%08x].\n",
+ cp->dev->name,
+ readl(cp->regs + REG_MIF_STATE_MACHINE),
+ readl(cp->regs + REG_MAC_STATE_MACHINE));
+ }
+ goto enable_rx_done;
+ }
+ udelay(10);
+ }
+ printk(KERN_ERR "%s: enabling mac failed [%s:%08x:%08x].\n",
+ cp->dev->name,
+ (txfailed? "tx,rx":"rx"),
+ readl(cp->regs + REG_MIF_STATE_MACHINE),
+ readl(cp->regs + REG_MAC_STATE_MACHINE));
+
+enable_rx_done:
+ cas_unmask_intr(cp); /* enable interrupts */
+ writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
+ writel(0, cp->regs + REG_RX_COMP_TAIL);
+
+ if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+ if (N_RX_DESC_RINGS > 1)
+ writel(RX_DESC_RINGN_SIZE(1) - 4,
+ cp->regs + REG_PLUS_RX_KICK1);
+
+ for (i = 1; i < N_RX_COMP_RINGS; i++)
+ writel(0, cp->regs + REG_PLUS_RX_COMPN_TAIL(i));
+ }
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_read_pcs_link_mode(struct cas *cp, int *fd, int *spd,
+ int *pause)
+{
+ u32 val = readl(cp->regs + REG_PCS_MII_LPA);
+ *fd = (val & PCS_MII_LPA_FD) ? 1 : 0;
+ *pause = (val & PCS_MII_LPA_SYM_PAUSE) ? 0x01 : 0x00;
+ if (val & PCS_MII_LPA_ASYM_PAUSE)
+ *pause |= 0x10;
+ *spd = 1000;
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_read_mii_link_mode(struct cas *cp, int *fd, int *spd,
+ int *pause)
+{
+ u32 val;
+
+ *fd = 0;
+ *spd = 10;
+ *pause = 0;
+
+ /* use GMII registers */
+ val = cas_phy_read(cp, MII_LPA);
+ if (val & CAS_LPA_PAUSE)
+ *pause = 0x01;
+
+ if (val & CAS_LPA_ASYM_PAUSE)
+ *pause |= 0x10;
+
+ if (val & LPA_DUPLEX)
+ *fd = 1;
+ if (val & LPA_100)
+ *spd = 100;
+
+ if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+ val = cas_phy_read(cp, CAS_MII_1000_STATUS);
+ if (val & (CAS_LPA_1000FULL | CAS_LPA_1000HALF))
+ *spd = 1000;
+ if (val & CAS_LPA_1000FULL)
+ *fd = 1;
+ }
+}
+
+/* A link-up condition has occurred, initialize and enable the
+ * rest of the chip.
+ *
+ * Must be invoked under cp->lock.
+ */
+static void cas_set_link_modes(struct cas *cp)
+{
+ u32 val;
+ int full_duplex, speed, pause;
+
+ full_duplex = 0;
+ speed = 10;
+ pause = 0;
+
+ if (CAS_PHY_MII(cp->phy_type)) {
+ cas_mif_poll(cp, 0);
+ val = cas_phy_read(cp, MII_BMCR);
+ if (val & BMCR_ANENABLE) {
+ cas_read_mii_link_mode(cp, &full_duplex, &speed,
+ &pause);
+ } else {
+ if (val & BMCR_FULLDPLX)
+ full_duplex = 1;
+
+ if (val & BMCR_SPEED100)
+ speed = 100;
+ else if (val & CAS_BMCR_SPEED1000)
+ speed = (cp->cas_flags & CAS_FLAG_1000MB_CAP) ?
+ 1000 : 100;
+ }
+ cas_mif_poll(cp, 1);
+
+ } else {
+ val = readl(cp->regs + REG_PCS_MII_CTRL);
+ cas_read_pcs_link_mode(cp, &full_duplex, &speed, &pause);
+ if ((val & PCS_MII_AUTONEG_EN) == 0) {
+ if (val & PCS_MII_CTRL_DUPLEX)
+ full_duplex = 1;
+ }
+ }
+
+ if (netif_msg_link(cp))
+ printk(KERN_INFO "%s: Link up at %d Mbps, %s-duplex.\n",
+ cp->dev->name, speed, (full_duplex ? "full" : "half"));
+
+ val = MAC_XIF_TX_MII_OUTPUT_EN | MAC_XIF_LINK_LED;
+ if (CAS_PHY_MII(cp->phy_type)) {
+ val |= MAC_XIF_MII_BUFFER_OUTPUT_EN;
+ if (!full_duplex)
+ val |= MAC_XIF_DISABLE_ECHO;
+ }
+ if (full_duplex)
+ val |= MAC_XIF_FDPLX_LED;
+ if (speed == 1000)
+ val |= MAC_XIF_GMII_MODE;
+ writel(val, cp->regs + REG_MAC_XIF_CFG);
+
+ /* deal with carrier and collision detect. */
+ val = MAC_TX_CFG_IPG_EN;
+ if (full_duplex) {
+ val |= MAC_TX_CFG_IGNORE_CARRIER;
+ val |= MAC_TX_CFG_IGNORE_COLL;
+ } else {
+#ifndef USE_CSMA_CD_PROTO
+ val |= MAC_TX_CFG_NEVER_GIVE_UP_EN;
+ val |= MAC_TX_CFG_NEVER_GIVE_UP_LIM;
+#endif
+ }
+ /* val now set up for REG_MAC_TX_CFG */
+
+ /* If gigabit and half-duplex, enable carrier extension
+ * mode. increase slot time to 512 bytes as well.
+ * else, disable it and make sure slot time is 64 bytes.
+ * also activate checksum bug workaround
+ */
+ if ((speed == 1000) && !full_duplex) {
+ writel(val | MAC_TX_CFG_CARRIER_EXTEND,
+ cp->regs + REG_MAC_TX_CFG);
+
+ val = readl(cp->regs + REG_MAC_RX_CFG);
+ val &= ~MAC_RX_CFG_STRIP_FCS; /* checksum workaround */
+ writel(val | MAC_RX_CFG_CARRIER_EXTEND,
+ cp->regs + REG_MAC_RX_CFG);
+
+ writel(0x200, cp->regs + REG_MAC_SLOT_TIME);
+
+ cp->crc_size = 4;
+ /* minimum size gigabit frame at half duplex */
+ cp->min_frame_size = CAS_1000MB_MIN_FRAME;
+
+ } else {
+ writel(val, cp->regs + REG_MAC_TX_CFG);
+
+ /* checksum bug workaround. don't strip FCS when in
+ * half-duplex mode
+ */
+ val = readl(cp->regs + REG_MAC_RX_CFG);
+ if (full_duplex) {
+ val |= MAC_RX_CFG_STRIP_FCS;
+ cp->crc_size = 0;
+ cp->min_frame_size = CAS_MIN_MTU;
+ } else {
+ val &= ~MAC_RX_CFG_STRIP_FCS;
+ cp->crc_size = 4;
+ cp->min_frame_size = CAS_MIN_FRAME;
+ }
+ writel(val & ~MAC_RX_CFG_CARRIER_EXTEND,
+ cp->regs + REG_MAC_RX_CFG);
+ writel(0x40, cp->regs + REG_MAC_SLOT_TIME);
+ }
+
+ if (netif_msg_link(cp)) {
+ if (pause & 0x01) {
+ printk(KERN_INFO "%s: Pause is enabled "
+ "(rxfifo: %d off: %d on: %d)\n",
+ cp->dev->name,
+ cp->rx_fifo_size,
+ cp->rx_pause_off,
+ cp->rx_pause_on);
+ } else if (pause & 0x10) {
+ printk(KERN_INFO "%s: TX pause enabled\n",
+ cp->dev->name);
+ } else {
+ printk(KERN_INFO "%s: Pause is disabled\n",
+ cp->dev->name);
+ }
+ }
+
+ val = readl(cp->regs + REG_MAC_CTRL_CFG);
+ val &= ~(MAC_CTRL_CFG_SEND_PAUSE_EN | MAC_CTRL_CFG_RECV_PAUSE_EN);
+ if (pause) { /* symmetric or asymmetric pause */
+ val |= MAC_CTRL_CFG_SEND_PAUSE_EN;
+ if (pause & 0x01) { /* symmetric pause */
+ val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
+ }
+ }
+ writel(val, cp->regs + REG_MAC_CTRL_CFG);
+ cas_start_dma(cp);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_init_hw(struct cas *cp, int restart_link)
+{
+ if (restart_link)
+ cas_phy_init(cp);
+
+ cas_init_pause_thresholds(cp);
+ cas_init_mac(cp);
+ cas_init_dma(cp);
+
+ if (restart_link) {
+ /* Default aneg parameters */
+ cp->timer_ticks = 0;
+ cas_begin_auto_negotiation(cp, NULL);
+ } else if (cp->lstate == link_up) {
+ cas_set_link_modes(cp);
+ netif_carrier_on(cp->dev);
+ }
+}
+
+/* Must be invoked under cp->lock. on earlier cassini boards,
+ * SOFT_0 is tied to PCI reset. we use this to force a pci reset,
+ * let it settle out, and then restore pci state.
+ */
+static void cas_hard_reset(struct cas *cp)
+{
+ writel(BIM_LOCAL_DEV_SOFT_0, cp->regs + REG_BIM_LOCAL_DEV_EN);
+ udelay(20);
+ pci_restore_state(cp->pdev);
+}
+
+
+static void cas_global_reset(struct cas *cp, int blkflag)
+{
+ int limit;
+
+ /* issue a global reset. don't use RSTOUT. */
+ if (blkflag && !CAS_PHY_MII(cp->phy_type)) {
+ /* For PCS, when the blkflag is set, we should set the
+ * SW_REST_BLOCK_PCS_SLINK bit to prevent the results of
+ * the last autonegotiation from being cleared. We'll
+ * need some special handling if the chip is set into a
+ * loopback mode.
+ */
+ writel((SW_RESET_TX | SW_RESET_RX | SW_RESET_BLOCK_PCS_SLINK),
+ cp->regs + REG_SW_RESET);
+ } else {
+ writel(SW_RESET_TX | SW_RESET_RX, cp->regs + REG_SW_RESET);
+ }
+
+ /* need to wait at least 3ms before polling register */
+ mdelay(3);
+
+ limit = STOP_TRIES;
+ while (limit-- > 0) {
+ u32 val = readl(cp->regs + REG_SW_RESET);
+ if ((val & (SW_RESET_TX | SW_RESET_RX)) == 0)
+ goto done;
+ udelay(10);
+ }
+ printk(KERN_ERR "%s: sw reset failed.\n", cp->dev->name);
+
+done:
+ /* enable various BIM interrupts */
+ writel(BIM_CFG_DPAR_INTR_ENABLE | BIM_CFG_RMA_INTR_ENABLE |
+ BIM_CFG_RTA_INTR_ENABLE, cp->regs + REG_BIM_CFG);
+
+ /* clear out pci error status mask for handled errors.
+ * we don't deal with DMA counter overflows as they happen
+ * all the time.
+ */
+ writel(0xFFFFFFFFU & ~(PCI_ERR_BADACK | PCI_ERR_DTRTO |
+ PCI_ERR_OTHER | PCI_ERR_BIM_DMA_WRITE |
+ PCI_ERR_BIM_DMA_READ), cp->regs +
+ REG_PCI_ERR_STATUS_MASK);
+
+ /* set up for MII by default to address mac rx reset timeout
+ * issue
+ */
+ writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
+}
+
+static void cas_reset(struct cas *cp, int blkflag)
+{
+ u32 val;
+
+ cas_mask_intr(cp);
+ cas_global_reset(cp, blkflag);
+ cas_mac_reset(cp);
+ cas_entropy_reset(cp);
+
+ /* disable dma engines. */
+ val = readl(cp->regs + REG_TX_CFG);
+ val &= ~TX_CFG_DMA_EN;
+ writel(val, cp->regs + REG_TX_CFG);
+
+ val = readl(cp->regs + REG_RX_CFG);
+ val &= ~RX_CFG_DMA_EN;
+ writel(val, cp->regs + REG_RX_CFG);
+
+ /* program header parser */
+ if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) ||
+ (CAS_HP_ALT_FIRMWARE == cas_prog_null)) {
+ cas_load_firmware(cp, CAS_HP_FIRMWARE);
+ } else {
+ cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE);
+ }
+
+ /* clear out error registers */
+ spin_lock(&cp->stat_lock[N_TX_RINGS]);
+ cas_clear_mac_err(cp);
+ spin_unlock(&cp->stat_lock[N_TX_RINGS]);
+}
+
+/* Shut down the chip, must be called with pm_sem held. */
+static void cas_shutdown(struct cas *cp)
+{
+ unsigned long flags;
+
+ /* Make us not-running to avoid timers respawning */
+ cp->hw_running = 0;
+
+ del_timer_sync(&cp->link_timer);
+
+ /* Stop the reset task */
+#if 0
+ while (atomic_read(&cp->reset_task_pending_mtu) ||
+ atomic_read(&cp->reset_task_pending_spare) ||
+ atomic_read(&cp->reset_task_pending_all))
+ schedule();
+
+#else
+ while (atomic_read(&cp->reset_task_pending))
+ schedule();
+#endif
+ /* Actually stop the chip */
+ cas_lock_all_save(cp, flags);
+ cas_reset(cp, 0);
+ if (cp->cas_flags & CAS_FLAG_SATURN)
+ cas_phy_powerdown(cp);
+ cas_unlock_all_restore(cp, flags);
+}
+
+static int cas_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct cas *cp = netdev_priv(dev);
+
+ if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return 0;
+
+ /* let the reset task handle it */
+#if 1
+ atomic_inc(&cp->reset_task_pending);
+ if ((cp->phy_type & CAS_PHY_SERDES)) {
+ atomic_inc(&cp->reset_task_pending_all);
+ } else {
+ atomic_inc(&cp->reset_task_pending_mtu);
+ }
+ schedule_work(&cp->reset_task);
+#else
+ atomic_set(&cp->reset_task_pending, (cp->phy_type & CAS_PHY_SERDES) ?
+ CAS_RESET_ALL : CAS_RESET_MTU);
+ printk(KERN_ERR "reset called in cas_change_mtu\n");
+ schedule_work(&cp->reset_task);
+#endif
+
+ flush_scheduled_work();
+ return 0;
+}
+
+static void cas_clean_txd(struct cas *cp, int ring)
+{
+ struct cas_tx_desc *txd = cp->init_txds[ring];
+ struct sk_buff *skb, **skbs = cp->tx_skbs[ring];
+ u64 daddr, dlen;
+ int i, size;
+
+ size = TX_DESC_RINGN_SIZE(ring);
+ for (i = 0; i < size; i++) {
+ int frag;
+
+ if (skbs[i] == NULL)
+ continue;
+
+ skb = skbs[i];
+ skbs[i] = NULL;
+
+ for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
+ int ent = i & (size - 1);
+
+ /* first buffer is never a tiny buffer and so
+ * needs to be unmapped.
+ */
+ daddr = le64_to_cpu(txd[ent].buffer);
+ dlen = CAS_VAL(TX_DESC_BUFLEN,
+ le64_to_cpu(txd[ent].control));
+ pci_unmap_page(cp->pdev, daddr, dlen,
+ PCI_DMA_TODEVICE);
+
+ if (frag != skb_shinfo(skb)->nr_frags) {
+ i++;
+
+ /* next buffer might by a tiny buffer.
+ * skip past it.
+ */
+ ent = i & (size - 1);
+ if (cp->tx_tiny_use[ring][ent].used)
+ i++;
+ }
+ }
+ dev_kfree_skb_any(skb);
+ }
+
+ /* zero out tiny buf usage */
+ memset(cp->tx_tiny_use[ring], 0, size*sizeof(*cp->tx_tiny_use[ring]));
+}
+
+/* freed on close */
+static inline void cas_free_rx_desc(struct cas *cp, int ring)
+{
+ cas_page_t **page = cp->rx_pages[ring];
+ int i, size;
+
+ size = RX_DESC_RINGN_SIZE(ring);
+ for (i = 0; i < size; i++) {
+ if (page[i]) {
+ cas_page_free(cp, page[i]);
+ page[i] = NULL;
+ }
+ }
+}
+
+static void cas_free_rxds(struct cas *cp)
+{
+ int i;
+
+ for (i = 0; i < N_RX_DESC_RINGS; i++)
+ cas_free_rx_desc(cp, i);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_clean_rings(struct cas *cp)
+{
+ int i;
+
+ /* need to clean all tx rings */
+ memset(cp->tx_old, 0, sizeof(*cp->tx_old)*N_TX_RINGS);
+ memset(cp->tx_new, 0, sizeof(*cp->tx_new)*N_TX_RINGS);
+ for (i = 0; i < N_TX_RINGS; i++)
+ cas_clean_txd(cp, i);
+
+ /* zero out init block */
+ memset(cp->init_block, 0, sizeof(struct cas_init_block));
+ cas_clean_rxds(cp);
+ cas_clean_rxcs(cp);
+}
+
+/* allocated on open */
+static inline int cas_alloc_rx_desc(struct cas *cp, int ring)
+{
+ cas_page_t **page = cp->rx_pages[ring];
+ int size, i = 0;
+
+ size = RX_DESC_RINGN_SIZE(ring);
+ for (i = 0; i < size; i++) {
+ if ((page[i] = cas_page_alloc(cp, GFP_KERNEL)) == NULL)
+ return -1;
+ }
+ return 0;
+}
+
+static int cas_alloc_rxds(struct cas *cp)
+{
+ int i;
+
+ for (i = 0; i < N_RX_DESC_RINGS; i++) {
+ if (cas_alloc_rx_desc(cp, i) < 0) {
+ cas_free_rxds(cp);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void cas_reset_task(void *data)
+{
+ struct cas *cp = (struct cas *) data;
+#if 0
+ int pending = atomic_read(&cp->reset_task_pending);
+#else
+ int pending_all = atomic_read(&cp->reset_task_pending_all);
+ int pending_spare = atomic_read(&cp->reset_task_pending_spare);
+ int pending_mtu = atomic_read(&cp->reset_task_pending_mtu);
+
+ if (pending_all == 0 && pending_spare == 0 && pending_mtu == 0) {
+ /* We can have more tasks scheduled than actually
+ * needed.
+ */
+ atomic_dec(&cp->reset_task_pending);
+ return;
+ }
+#endif
+ /* The link went down, we reset the ring, but keep
+ * DMA stopped. Use this function for reset
+ * on error as well.
+ */
+ if (cp->hw_running) {
+ unsigned long flags;
+
+ /* Make sure we don't get interrupts or tx packets */
+ netif_device_detach(cp->dev);
+ cas_lock_all_save(cp, flags);
+
+ if (cp->opened) {
+ /* We call cas_spare_recover when we call cas_open.
+ * but we do not initialize the lists cas_spare_recover
+ * uses until cas_open is called.
+ */
+ cas_spare_recover(cp, GFP_ATOMIC);
+ }
+#if 1
+ /* test => only pending_spare set */
+ if (!pending_all && !pending_mtu)
+ goto done;
+#else
+ if (pending == CAS_RESET_SPARE)
+ goto done;
+#endif
+ /* when pending == CAS_RESET_ALL, the following
+ * call to cas_init_hw will restart auto negotiation.
+ * Setting the second argument of cas_reset to
+ * !(pending == CAS_RESET_ALL) will set this argument
+ * to 1 (avoiding reinitializing the PHY for the normal
+ * PCS case) when auto negotiation is not restarted.
+ */
+#if 1
+ cas_reset(cp, !(pending_all > 0));
+ if (cp->opened)
+ cas_clean_rings(cp);
+ cas_init_hw(cp, (pending_all > 0));
+#else
+ cas_reset(cp, !(pending == CAS_RESET_ALL));
+ if (cp->opened)
+ cas_clean_rings(cp);
+ cas_init_hw(cp, pending == CAS_RESET_ALL);
+#endif
+
+done:
+ cas_unlock_all_restore(cp, flags);
+ netif_device_attach(cp->dev);
+ }
+#if 1
+ atomic_sub(pending_all, &cp->reset_task_pending_all);
+ atomic_sub(pending_spare, &cp->reset_task_pending_spare);
+ atomic_sub(pending_mtu, &cp->reset_task_pending_mtu);
+ atomic_dec(&cp->reset_task_pending);
+#else
+ atomic_set(&cp->reset_task_pending, 0);
+#endif
+}
+
+static void cas_link_timer(unsigned long data)
+{
+ struct cas *cp = (struct cas *) data;
+ int mask, pending = 0, reset = 0;
+ unsigned long flags;
+
+ if (link_transition_timeout != 0 &&
+ cp->link_transition_jiffies_valid &&
+ ((jiffies - cp->link_transition_jiffies) >
+ (link_transition_timeout))) {
+ /* One-second counter so link-down workaround doesn't
+ * cause resets to occur so fast as to fool the switch
+ * into thinking the link is down.
+ */
+ cp->link_transition_jiffies_valid = 0;
+ }
+
+ if (!cp->hw_running)
+ return;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_lock_tx(cp);
+ cas_entropy_gather(cp);
+
+ /* If the link task is still pending, we just
+ * reschedule the link timer
+ */
+#if 1
+ if (atomic_read(&cp->reset_task_pending_all) ||
+ atomic_read(&cp->reset_task_pending_spare) ||
+ atomic_read(&cp->reset_task_pending_mtu))
+ goto done;
+#else
+ if (atomic_read(&cp->reset_task_pending))
+ goto done;
+#endif
+
+ /* check for rx cleaning */
+ if ((mask = (cp->cas_flags & CAS_FLAG_RXD_POST_MASK))) {
+ int i, rmask;
+
+ for (i = 0; i < MAX_RX_DESC_RINGS; i++) {
+ rmask = CAS_FLAG_RXD_POST(i);
+ if ((mask & rmask) == 0)
+ continue;
+
+ /* post_rxds will do a mod_timer */
+ if (cas_post_rxds_ringN(cp, i, cp->rx_last[i]) < 0) {
+ pending = 1;
+ continue;
+ }
+ cp->cas_flags &= ~rmask;
+ }
+ }
+
+ if (CAS_PHY_MII(cp->phy_type)) {
+ u16 bmsr;
+ cas_mif_poll(cp, 0);
+ bmsr = cas_phy_read(cp, MII_BMSR);
+ /* WTZ: Solaris driver reads this twice, but that
+ * may be due to the PCS case and the use of a
+ * common implementation. Read it twice here to be
+ * safe.
+ */
+ bmsr = cas_phy_read(cp, MII_BMSR);
+ cas_mif_poll(cp, 1);
+ readl(cp->regs + REG_MIF_STATUS); /* avoid dups */
+ reset = cas_mii_link_check(cp, bmsr);
+ } else {
+ reset = cas_pcs_link_check(cp);
+ }
+
+ if (reset)
+ goto done;
+
+ /* check for tx state machine confusion */
+ if ((readl(cp->regs + REG_MAC_TX_STATUS) & MAC_TX_FRAME_XMIT) == 0) {
+ u32 val = readl(cp->regs + REG_MAC_STATE_MACHINE);
+ u32 wptr, rptr;
+ int tlm = CAS_VAL(MAC_SM_TLM, val);
+
+ if (((tlm == 0x5) || (tlm == 0x3)) &&
+ (CAS_VAL(MAC_SM_ENCAP_SM, val) == 0)) {
+ if (netif_msg_tx_err(cp))
+ printk(KERN_DEBUG "%s: tx err: "
+ "MAC_STATE[%08x]\n",
+ cp->dev->name, val);
+ reset = 1;
+ goto done;
+ }
+
+ val = readl(cp->regs + REG_TX_FIFO_PKT_CNT);
+ wptr = readl(cp->regs + REG_TX_FIFO_WRITE_PTR);
+ rptr = readl(cp->regs + REG_TX_FIFO_READ_PTR);
+ if ((val == 0) && (wptr != rptr)) {
+ if (netif_msg_tx_err(cp))
+ printk(KERN_DEBUG "%s: tx err: "
+ "TX_FIFO[%08x:%08x:%08x]\n",
+ cp->dev->name, val, wptr, rptr);
+ reset = 1;
+ }
+
+ if (reset)
+ cas_hard_reset(cp);
+ }
+
+done:
+ if (reset) {
+#if 1
+ atomic_inc(&cp->reset_task_pending);
+ atomic_inc(&cp->reset_task_pending_all);
+ schedule_work(&cp->reset_task);
+#else
+ atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+ printk(KERN_ERR "reset called in cas_link_timer\n");
+ schedule_work(&cp->reset_task);
+#endif
+ }
+
+ if (!pending)
+ mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+ cas_unlock_tx(cp);
+ spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+/* tiny buffers are used to avoid target abort issues with
+ * older cassini's
+ */
+static void cas_tx_tiny_free(struct cas *cp)
+{
+ struct pci_dev *pdev = cp->pdev;
+ int i;
+
+ for (i = 0; i < N_TX_RINGS; i++) {
+ if (!cp->tx_tiny_bufs[i])
+ continue;
+
+ pci_free_consistent(pdev, TX_TINY_BUF_BLOCK,
+ cp->tx_tiny_bufs[i],
+ cp->tx_tiny_dvma[i]);
+ cp->tx_tiny_bufs[i] = NULL;
+ }
+}
+
+static int cas_tx_tiny_alloc(struct cas *cp)
+{
+ struct pci_dev *pdev = cp->pdev;
+ int i;
+
+ for (i = 0; i < N_TX_RINGS; i++) {
+ cp->tx_tiny_bufs[i] =
+ pci_alloc_consistent(pdev, TX_TINY_BUF_BLOCK,
+ &cp->tx_tiny_dvma[i]);
+ if (!cp->tx_tiny_bufs[i]) {
+ cas_tx_tiny_free(cp);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static int cas_open(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ int hw_was_up, err;
+ unsigned long flags;
+
+ down(&cp->pm_sem);
+
+ hw_was_up = cp->hw_running;
+
+ /* The power-management semaphore protects the hw_running
+ * etc. state so it is safe to do this bit without cp->lock
+ */
+ if (!cp->hw_running) {
+ /* Reset the chip */
+ cas_lock_all_save(cp, flags);
+ /* We set the second arg to cas_reset to zero
+ * because cas_init_hw below will have its second
+ * argument set to non-zero, which will force
+ * autonegotiation to start.
+ */
+ cas_reset(cp, 0);
+ cp->hw_running = 1;
+ cas_unlock_all_restore(cp, flags);
+ }
+
+ if (cas_tx_tiny_alloc(cp) < 0)
+ return -ENOMEM;
+
+ /* alloc rx descriptors */
+ err = -ENOMEM;
+ if (cas_alloc_rxds(cp) < 0)
+ goto err_tx_tiny;
+
+ /* allocate spares */
+ cas_spare_init(cp);
+ cas_spare_recover(cp, GFP_KERNEL);
+
+ /* We can now request the interrupt as we know it's masked
+ * on the controller. cassini+ has up to 4 interrupts
+ * that can be used, but you need to do explicit pci interrupt
+ * mapping to expose them
+ */
+ if (request_irq(cp->pdev->irq, cas_interrupt,
+ SA_SHIRQ, dev->name, (void *) dev)) {
+ printk(KERN_ERR "%s: failed to request irq !\n",
+ cp->dev->name);
+ err = -EAGAIN;
+ goto err_spare;
+ }
+
+ /* init hw */
+ cas_lock_all_save(cp, flags);
+ cas_clean_rings(cp);
+ cas_init_hw(cp, !hw_was_up);
+ cp->opened = 1;
+ cas_unlock_all_restore(cp, flags);
+
+ netif_start_queue(dev);
+ up(&cp->pm_sem);
+ return 0;
+
+err_spare:
+ cas_spare_free(cp);
+ cas_free_rxds(cp);
+err_tx_tiny:
+ cas_tx_tiny_free(cp);
+ up(&cp->pm_sem);
+ return err;
+}
+
+static int cas_close(struct net_device *dev)
+{
+ unsigned long flags;
+ struct cas *cp = netdev_priv(dev);
+
+ /* Make sure we don't get distracted by suspend/resume */
+ down(&cp->pm_sem);
+
+ netif_stop_queue(dev);
+
+ /* Stop traffic, mark us closed */
+ cas_lock_all_save(cp, flags);
+ cp->opened = 0;
+ cas_reset(cp, 0);
+ cas_phy_init(cp);
+ cas_begin_auto_negotiation(cp, NULL);
+ cas_clean_rings(cp);
+ cas_unlock_all_restore(cp, flags);
+
+ free_irq(cp->pdev->irq, (void *) dev);
+ cas_spare_free(cp);
+ cas_free_rxds(cp);
+ cas_tx_tiny_free(cp);
+ up(&cp->pm_sem);
+ return 0;
+}
+
+static struct {
+ const char name[ETH_GSTRING_LEN];
+} ethtool_cassini_statnames[] = {
+ {"collisions"},
+ {"rx_bytes"},
+ {"rx_crc_errors"},
+ {"rx_dropped"},
+ {"rx_errors"},
+ {"rx_fifo_errors"},
+ {"rx_frame_errors"},
+ {"rx_length_errors"},
+ {"rx_over_errors"},
+ {"rx_packets"},
+ {"tx_aborted_errors"},
+ {"tx_bytes"},
+ {"tx_dropped"},
+ {"tx_errors"},
+ {"tx_fifo_errors"},
+ {"tx_packets"}
+};
+#define CAS_NUM_STAT_KEYS (sizeof(ethtool_cassini_statnames)/ETH_GSTRING_LEN)
+
+static struct {
+ const int offsets; /* neg. values for 2nd arg to cas_read_phy */
+} ethtool_register_table[] = {
+ {-MII_BMSR},
+ {-MII_BMCR},
+ {REG_CAWR},
+ {REG_INF_BURST},
+ {REG_BIM_CFG},
+ {REG_RX_CFG},
+ {REG_HP_CFG},
+ {REG_MAC_TX_CFG},
+ {REG_MAC_RX_CFG},
+ {REG_MAC_CTRL_CFG},
+ {REG_MAC_XIF_CFG},
+ {REG_MIF_CFG},
+ {REG_PCS_CFG},
+ {REG_SATURN_PCFG},
+ {REG_PCS_MII_STATUS},
+ {REG_PCS_STATE_MACHINE},
+ {REG_MAC_COLL_EXCESS},
+ {REG_MAC_COLL_LATE}
+};
+#define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int))
+#define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN)
+
+static void cas_read_regs(struct cas *cp, u8 *ptr, int len)
+{
+ u8 *p;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ for (i = 0, p = ptr; i < len ; i ++, p += sizeof(u32)) {
+ u16 hval;
+ u32 val;
+ if (ethtool_register_table[i].offsets < 0) {
+ hval = cas_phy_read(cp,
+ -ethtool_register_table[i].offsets);
+ val = hval;
+ } else {
+ val= readl(cp->regs+ethtool_register_table[i].offsets);
+ }
+ memcpy(p, (u8 *)&val, sizeof(u32));
+ }
+ spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+static struct net_device_stats *cas_get_stats(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ struct net_device_stats *stats = cp->net_stats;
+ unsigned long flags;
+ int i;
+ unsigned long tmp;
+
+ /* we collate all of the stats into net_stats[N_TX_RING] */
+ if (!cp->hw_running)
+ return stats + N_TX_RINGS;
+
+ /* collect outstanding stats */
+ /* WTZ: the Cassini spec gives these as 16 bit counters but
+ * stored in 32-bit words. Added a mask of 0xffff to be safe,
+ * in case the chip somehow puts any garbage in the other bits.
+ * Also, counter usage didn't seem to mach what Adrian did
+ * in the parts of the code that set these quantities. Made
+ * that consistent.
+ */
+ spin_lock_irqsave(&cp->stat_lock[N_TX_RINGS], flags);
+ stats[N_TX_RINGS].rx_crc_errors +=
+ readl(cp->regs + REG_MAC_FCS_ERR) & 0xffff;
+ stats[N_TX_RINGS].rx_frame_errors +=
+ readl(cp->regs + REG_MAC_ALIGN_ERR) &0xffff;
+ stats[N_TX_RINGS].rx_length_errors +=
+ readl(cp->regs + REG_MAC_LEN_ERR) & 0xffff;
+#if 1
+ tmp = (readl(cp->regs + REG_MAC_COLL_EXCESS) & 0xffff) +
+ (readl(cp->regs + REG_MAC_COLL_LATE) & 0xffff);
+ stats[N_TX_RINGS].tx_aborted_errors += tmp;
+ stats[N_TX_RINGS].collisions +=
+ tmp + (readl(cp->regs + REG_MAC_COLL_NORMAL) & 0xffff);
+#else
+ stats[N_TX_RINGS].tx_aborted_errors +=
+ readl(cp->regs + REG_MAC_COLL_EXCESS);
+ stats[N_TX_RINGS].collisions += readl(cp->regs + REG_MAC_COLL_EXCESS) +
+ readl(cp->regs + REG_MAC_COLL_LATE);
+#endif
+ cas_clear_mac_err(cp);
+
+ /* saved bits that are unique to ring 0 */
+ spin_lock(&cp->stat_lock[0]);
+ stats[N_TX_RINGS].collisions += stats[0].collisions;
+ stats[N_TX_RINGS].rx_over_errors += stats[0].rx_over_errors;
+ stats[N_TX_RINGS].rx_frame_errors += stats[0].rx_frame_errors;
+ stats[N_TX_RINGS].rx_fifo_errors += stats[0].rx_fifo_errors;
+ stats[N_TX_RINGS].tx_aborted_errors += stats[0].tx_aborted_errors;
+ stats[N_TX_RINGS].tx_fifo_errors += stats[0].tx_fifo_errors;
+ spin_unlock(&cp->stat_lock[0]);
+
+ for (i = 0; i < N_TX_RINGS; i++) {
+ spin_lock(&cp->stat_lock[i]);
+ stats[N_TX_RINGS].rx_length_errors +=
+ stats[i].rx_length_errors;
+ stats[N_TX_RINGS].rx_crc_errors += stats[i].rx_crc_errors;
+ stats[N_TX_RINGS].rx_packets += stats[i].rx_packets;
+ stats[N_TX_RINGS].tx_packets += stats[i].tx_packets;
+ stats[N_TX_RINGS].rx_bytes += stats[i].rx_bytes;
+ stats[N_TX_RINGS].tx_bytes += stats[i].tx_bytes;
+ stats[N_TX_RINGS].rx_errors += stats[i].rx_errors;
+ stats[N_TX_RINGS].tx_errors += stats[i].tx_errors;
+ stats[N_TX_RINGS].rx_dropped += stats[i].rx_dropped;
+ stats[N_TX_RINGS].tx_dropped += stats[i].tx_dropped;
+ memset(stats + i, 0, sizeof(struct net_device_stats));
+ spin_unlock(&cp->stat_lock[i]);
+ }
+ spin_unlock_irqrestore(&cp->stat_lock[N_TX_RINGS], flags);
+ return stats + N_TX_RINGS;
+}
+
+
+static void cas_set_multicast(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ u32 rxcfg, rxcfg_new;
+ unsigned long flags;
+ int limit = STOP_TRIES;
+
+ if (!cp->hw_running)
+ return;
+
+ spin_lock_irqsave(&cp->lock, flags);
+ rxcfg = readl(cp->regs + REG_MAC_RX_CFG);
+
+ /* disable RX MAC and wait for completion */
+ writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+ while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN) {
+ if (!limit--)
+ break;
+ udelay(10);
+ }
+
+ /* disable hash filter and wait for completion */
+ limit = STOP_TRIES;
+ rxcfg &= ~(MAC_RX_CFG_PROMISC_EN | MAC_RX_CFG_HASH_FILTER_EN);
+ writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+ while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_HASH_FILTER_EN) {
+ if (!limit--)
+ break;
+ udelay(10);
+ }
+
+ /* program hash filters */
+ cp->mac_rx_cfg = rxcfg_new = cas_setup_multicast(cp);
+ rxcfg |= rxcfg_new;
+ writel(rxcfg, cp->regs + REG_MAC_RX_CFG);
+ spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct cas *cp = netdev_priv(dev);
+ strncpy(info->driver, DRV_MODULE_NAME, ETHTOOL_BUSINFO_LEN);
+ strncpy(info->version, DRV_MODULE_VERSION, ETHTOOL_BUSINFO_LEN);
+ info->fw_version[0] = '\0';
+ strncpy(info->bus_info, pci_name(cp->pdev), ETHTOOL_BUSINFO_LEN);
+ info->regdump_len = cp->casreg_len < CAS_MAX_REGS ?
+ cp->casreg_len : CAS_MAX_REGS;
+ info->n_stats = CAS_NUM_STAT_KEYS;
+}
+
+static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct cas *cp = netdev_priv(dev);
+ u16 bmcr;
+ int full_duplex, speed, pause;
+ unsigned long flags;
+ enum link_state linkstate = link_up;
+
+ cmd->advertising = 0;
+ cmd->supported = SUPPORTED_Autoneg;
+ if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+ cmd->supported |= SUPPORTED_1000baseT_Full;
+ cmd->advertising |= ADVERTISED_1000baseT_Full;
+ }
+
+ /* Record PHY settings if HW is on. */
+ spin_lock_irqsave(&cp->lock, flags);
+ bmcr = 0;
+ linkstate = cp->lstate;
+ if (CAS_PHY_MII(cp->phy_type)) {
+ cmd->port = PORT_MII;
+ cmd->transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ?
+ XCVR_INTERNAL : XCVR_EXTERNAL;
+ cmd->phy_address = cp->phy_addr;
+ cmd->advertising |= ADVERTISED_TP | ADVERTISED_MII |
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full;
+
+ cmd->supported |=
+ (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_TP | SUPPORTED_MII);
+
+ if (cp->hw_running) {
+ cas_mif_poll(cp, 0);
+ bmcr = cas_phy_read(cp, MII_BMCR);
+ cas_read_mii_link_mode(cp, &full_duplex,
+ &speed, &pause);
+ cas_mif_poll(cp, 1);
+ }
+
+ } else {
+ cmd->port = PORT_FIBRE;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->phy_address = 0;
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+
+ if (cp->hw_running) {
+ /* pcs uses the same bits as mii */
+ bmcr = readl(cp->regs + REG_PCS_MII_CTRL);
+ cas_read_pcs_link_mode(cp, &full_duplex,
+ &speed, &pause);
+ }
+ }
+ spin_unlock_irqrestore(&cp->lock, flags);
+
+ if (bmcr & BMCR_ANENABLE) {
+ cmd->advertising |= ADVERTISED_Autoneg;
+ cmd->autoneg = AUTONEG_ENABLE;
+ cmd->speed = ((speed == 10) ?
+ SPEED_10 :
+ ((speed == 1000) ?
+ SPEED_1000 : SPEED_100));
+ cmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+ } else {
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->speed =
+ (bmcr & CAS_BMCR_SPEED1000) ?
+ SPEED_1000 :
+ ((bmcr & BMCR_SPEED100) ? SPEED_100:
+ SPEED_10);
+ cmd->duplex =
+ (bmcr & BMCR_FULLDPLX) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ }
+ if (linkstate != link_up) {
+ /* Force these to "unknown" if the link is not up and
+ * autonogotiation in enabled. We can set the link
+ * speed to 0, but not cmd->duplex,
+ * because its legal values are 0 and 1. Ethtool will
+ * print the value reported in parentheses after the
+ * word "Unknown" for unrecognized values.
+ *
+ * If in forced mode, we report the speed and duplex
+ * settings that we configured.
+ */
+ if (cp->link_cntl & BMCR_ANENABLE) {
+ cmd->speed = 0;
+ cmd->duplex = 0xff;
+ } else {
+ cmd->speed = SPEED_10;
+ if (cp->link_cntl & BMCR_SPEED100) {
+ cmd->speed = SPEED_100;
+ } else if (cp->link_cntl & CAS_BMCR_SPEED1000) {
+ cmd->speed = SPEED_1000;
+ }
+ cmd->duplex = (cp->link_cntl & BMCR_FULLDPLX)?
+ DUPLEX_FULL : DUPLEX_HALF;
+ }
+ }
+ return 0;
+}
+
+static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+
+ /* Verify the settings we care about. */
+ if (cmd->autoneg != AUTONEG_ENABLE &&
+ cmd->autoneg != AUTONEG_DISABLE)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_DISABLE &&
+ ((cmd->speed != SPEED_1000 &&
+ cmd->speed != SPEED_100 &&
+ cmd->speed != SPEED_10) ||
+ (cmd->duplex != DUPLEX_HALF &&
+ cmd->duplex != DUPLEX_FULL)))
+ return -EINVAL;
+
+ /* Apply settings and restart link process. */
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_begin_auto_negotiation(cp, cmd);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ return 0;
+}
+
+static int cas_nway_reset(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+
+ if ((cp->link_cntl & BMCR_ANENABLE) == 0)
+ return -EINVAL;
+
+ /* Restart link process. */
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_begin_auto_negotiation(cp, NULL);
+ spin_unlock_irqrestore(&cp->lock, flags);
+
+ return 0;
+}
+
+static u32 cas_get_link(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ return cp->lstate == link_up;
+}
+
+static u32 cas_get_msglevel(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ return cp->msg_enable;
+}
+
+static void cas_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct cas *cp = netdev_priv(dev);
+ cp->msg_enable = value;
+}
+
+static int cas_get_regs_len(struct net_device *dev)
+{
+ struct cas *cp = netdev_priv(dev);
+ return cp->casreg_len < CAS_MAX_REGS ? cp->casreg_len: CAS_MAX_REGS;
+}
+
+static void cas_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ struct cas *cp = netdev_priv(dev);
+ regs->version = 0;
+ /* cas_read_regs handles locks (cp->lock). */
+ cas_read_regs(cp, p, regs->len / sizeof(u32));
+}
+
+static int cas_get_stats_count(struct net_device *dev)
+{
+ return CAS_NUM_STAT_KEYS;
+}
+
+static void cas_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ memcpy(data, &ethtool_cassini_statnames,
+ CAS_NUM_STAT_KEYS * ETH_GSTRING_LEN);
+}
+
+static void cas_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *estats, u64 *data)
+{
+ struct cas *cp = netdev_priv(dev);
+ struct net_device_stats *stats = cas_get_stats(cp->dev);
+ int i = 0;
+ data[i++] = stats->collisions;
+ data[i++] = stats->rx_bytes;
+ data[i++] = stats->rx_crc_errors;
+ data[i++] = stats->rx_dropped;
+ data[i++] = stats->rx_errors;
+ data[i++] = stats->rx_fifo_errors;
+ data[i++] = stats->rx_frame_errors;
+ data[i++] = stats->rx_length_errors;
+ data[i++] = stats->rx_over_errors;
+ data[i++] = stats->rx_packets;
+ data[i++] = stats->tx_aborted_errors;
+ data[i++] = stats->tx_bytes;
+ data[i++] = stats->tx_dropped;
+ data[i++] = stats->tx_errors;
+ data[i++] = stats->tx_fifo_errors;
+ data[i++] = stats->tx_packets;
+ BUG_ON(i != CAS_NUM_STAT_KEYS);
+}
+
+static struct ethtool_ops cas_ethtool_ops = {
+ .get_drvinfo = cas_get_drvinfo,
+ .get_settings = cas_get_settings,
+ .set_settings = cas_set_settings,
+ .nway_reset = cas_nway_reset,
+ .get_link = cas_get_link,
+ .get_msglevel = cas_get_msglevel,
+ .set_msglevel = cas_set_msglevel,
+ .get_regs_len = cas_get_regs_len,
+ .get_regs = cas_get_regs,
+ .get_stats_count = cas_get_stats_count,
+ .get_strings = cas_get_strings,
+ .get_ethtool_stats = cas_get_ethtool_stats,
+};
+
+static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct cas *cp = netdev_priv(dev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+ unsigned long flags;
+ int rc = -EOPNOTSUPP;
+
+ /* Hold the PM semaphore while doing ioctl's or we may collide
+ * with open/close and power management and oops.
+ */
+ down(&cp->pm_sem);
+ switch (cmd) {
+ case SIOCGMIIPHY: /* Get address of MII PHY in use. */
+ data->phy_id = cp->phy_addr;
+ /* Fallthrough... */
+
+ case SIOCGMIIREG: /* Read MII PHY register. */
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_mif_poll(cp, 0);
+ data->val_out = cas_phy_read(cp, data->reg_num & 0x1f);
+ cas_mif_poll(cp, 1);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ rc = 0;
+ break;
+
+ case SIOCSMIIREG: /* Write MII PHY register. */
+ if (!capable(CAP_NET_ADMIN)) {
+ rc = -EPERM;
+ break;
+ }
+ spin_lock_irqsave(&cp->lock, flags);
+ cas_mif_poll(cp, 0);
+ rc = cas_phy_write(cp, data->reg_num & 0x1f, data->val_in);
+ cas_mif_poll(cp, 1);
+ spin_unlock_irqrestore(&cp->lock, flags);
+ break;
+ default:
+ break;
+ };
+
+ up(&cp->pm_sem);
+ return rc;
+}
+
+static int __devinit cas_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int cas_version_printed = 0;
+ unsigned long casreg_base, casreg_len;
+ struct net_device *dev;
+ struct cas *cp;
+ int i, err, pci_using_dac;
+ u16 pci_cmd;
+ u8 orig_cacheline_size = 0, cas_cacheline_size = 0;
+
+ if (cas_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device, "
+ "aborting.\n");
+ return err;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find proper PCI device "
+ "base address, aborting.\n");
+ err = -ENODEV;
+ goto err_out_disable_pdev;
+ }
+
+ dev = alloc_etherdev(sizeof(*cp));
+ if (!dev) {
+ printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ err = -ENOMEM;
+ goto err_out_disable_pdev;
+ }
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ err = pci_request_regions(pdev, dev->name);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources, "
+ "aborting.\n");
+ goto err_out_free_netdev;
+ }
+ pci_set_master(pdev);
+
+ /* we must always turn on parity response or else parity
+ * doesn't get generated properly. disable SERR/PERR as well.
+ * in addition, we want to turn MWI on.
+ */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_SERR;
+ pci_cmd |= PCI_COMMAND_PARITY;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+ pci_set_mwi(pdev);
+ /*
+ * On some architectures, the default cache line size set
+ * by pci_set_mwi reduces perforamnce. We have to increase
+ * it for this case. To start, we'll print some configuration
+ * data.
+ */
+#if 1
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
+ &orig_cacheline_size);
+ if (orig_cacheline_size < CAS_PREF_CACHELINE_SIZE) {
+ cas_cacheline_size =
+ (CAS_PREF_CACHELINE_SIZE < SMP_CACHE_BYTES) ?
+ CAS_PREF_CACHELINE_SIZE : SMP_CACHE_BYTES;
+ if (pci_write_config_byte(pdev,
+ PCI_CACHE_LINE_SIZE,
+ cas_cacheline_size)) {
+ printk(KERN_ERR PFX "Could not set PCI cache "
+ "line size\n");
+ goto err_write_cacheline;
+ }
+ }
+#endif
+
+
+ /* Configure DMA attributes. */
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ pci_using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev,
+ DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "Unable to obtain 64-bit DMA "
+ "for consistent allocations\n");
+ goto err_out_free_res;
+ }
+
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "No usable DMA configuration, "
+ "aborting.\n");
+ goto err_out_free_res;
+ }
+ pci_using_dac = 0;
+ }
+
+ casreg_base = pci_resource_start(pdev, 0);
+ casreg_len = pci_resource_len(pdev, 0);
+
+ cp = netdev_priv(dev);
+ cp->pdev = pdev;
+#if 1
+ /* A value of 0 indicates we never explicitly set it */
+ cp->orig_cacheline_size = cas_cacheline_size ? orig_cacheline_size: 0;
+#endif
+ cp->dev = dev;
+ cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE :
+ cassini_debug;
+
+ cp->link_transition = LINK_TRANSITION_UNKNOWN;
+ cp->link_transition_jiffies_valid = 0;
+
+ spin_lock_init(&cp->lock);
+ spin_lock_init(&cp->rx_inuse_lock);
+ spin_lock_init(&cp->rx_spare_lock);
+ for (i = 0; i < N_TX_RINGS; i++) {
+ spin_lock_init(&cp->stat_lock[i]);
+ spin_lock_init(&cp->tx_lock[i]);
+ }
+ spin_lock_init(&cp->stat_lock[N_TX_RINGS]);
+ init_MUTEX(&cp->pm_sem);
+
+ init_timer(&cp->link_timer);
+ cp->link_timer.function = cas_link_timer;
+ cp->link_timer.data = (unsigned long) cp;
+
+#if 1
+ /* Just in case the implementation of atomic operations
+ * change so that an explicit initialization is necessary.
+ */
+ atomic_set(&cp->reset_task_pending, 0);
+ atomic_set(&cp->reset_task_pending_all, 0);
+ atomic_set(&cp->reset_task_pending_spare, 0);
+ atomic_set(&cp->reset_task_pending_mtu, 0);
+#endif
+ INIT_WORK(&cp->reset_task, cas_reset_task, cp);
+
+ /* Default link parameters */
+ if (link_mode >= 0 && link_mode <= 6)
+ cp->link_cntl = link_modes[link_mode];
+ else
+ cp->link_cntl = BMCR_ANENABLE;
+ cp->lstate = link_down;
+ cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+ netif_carrier_off(cp->dev);
+ cp->timer_ticks = 0;
+
+ /* give us access to cassini registers */
+ cp->regs = ioremap(casreg_base, casreg_len);
+ if (cp->regs == 0UL) {
+ printk(KERN_ERR PFX "Cannot map device registers, "
+ "aborting.\n");
+ goto err_out_free_res;
+ }
+ cp->casreg_len = casreg_len;
+
+ pci_save_state(pdev);
+ cas_check_pci_invariants(cp);
+ cas_hard_reset(cp);
+ cas_reset(cp, 0);
+ if (cas_check_invariants(cp))
+ goto err_out_iounmap;
+
+ cp->init_block = (struct cas_init_block *)
+ pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
+ &cp->block_dvma);
+ if (!cp->init_block) {
+ printk(KERN_ERR PFX "Cannot allocate init block, "
+ "aborting.\n");
+ goto err_out_iounmap;
+ }
+
+ for (i = 0; i < N_TX_RINGS; i++)
+ cp->init_txds[i] = cp->init_block->txds[i];
+
+ for (i = 0; i < N_RX_DESC_RINGS; i++)
+ cp->init_rxds[i] = cp->init_block->rxds[i];
+
+ for (i = 0; i < N_RX_COMP_RINGS; i++)
+ cp->init_rxcs[i] = cp->init_block->rxcs[i];
+
+ for (i = 0; i < N_RX_FLOWS; i++)
+ skb_queue_head_init(&cp->rx_flows[i]);
+
+ dev->open = cas_open;
+ dev->stop = cas_close;
+ dev->hard_start_xmit = cas_start_xmit;
+ dev->get_stats = cas_get_stats;
+ dev->set_multicast_list = cas_set_multicast;
+ dev->do_ioctl = cas_ioctl;
+ dev->ethtool_ops = &cas_ethtool_ops;
+ dev->tx_timeout = cas_tx_timeout;
+ dev->watchdog_timeo = CAS_TX_TIMEOUT;
+ dev->change_mtu = cas_change_mtu;
+#ifdef USE_NAPI
+ dev->poll = cas_poll;
+ dev->weight = 64;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = cas_netpoll;
+#endif
+ dev->irq = pdev->irq;
+ dev->dma = 0;
+
+ /* Cassini features. */
+ if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0)
+ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ if (register_netdev(dev)) {
+ printk(KERN_ERR PFX "Cannot register net device, "
+ "aborting.\n");
+ goto err_out_free_consistent;
+ }
+
+ i = readl(cp->regs + REG_BIM_CFG);
+ printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) "
+ "Ethernet[%d] ", dev->name,
+ (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "",
+ (i & BIM_CFG_32BIT) ? "32" : "64",
+ (i & BIM_CFG_66MHZ) ? "66" : "33",
+ (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq);
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? ' ' : ':');
+ printk("\n");
+
+ pci_set_drvdata(pdev, dev);
+ cp->hw_running = 1;
+ cas_entropy_reset(cp);
+ cas_phy_init(cp);
+ cas_begin_auto_negotiation(cp, NULL);
+ return 0;
+
+err_out_free_consistent:
+ pci_free_consistent(pdev, sizeof(struct cas_init_block),
+ cp->init_block, cp->block_dvma);
+
+err_out_iounmap:
+ down(&cp->pm_sem);
+ if (cp->hw_running)
+ cas_shutdown(cp);
+ up(&cp->pm_sem);
+
+ iounmap(cp->regs);
+
+
+err_out_free_res:
+ pci_release_regions(pdev);
+
+err_write_cacheline:
+ /* Try to restore it in case the error occured after we
+ * set it.
+ */
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, orig_cacheline_size);
+
+err_out_free_netdev:
+ free_netdev(dev);
+
+err_out_disable_pdev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return -ENODEV;
+}
+
+static void __devexit cas_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct cas *cp;
+ if (!dev)
+ return;
+
+ cp = netdev_priv(dev);
+ unregister_netdev(dev);
+
+ down(&cp->pm_sem);
+ flush_scheduled_work();
+ if (cp->hw_running)
+ cas_shutdown(cp);
+ up(&cp->pm_sem);
+
+#if 1
+ if (cp->orig_cacheline_size) {
+ /* Restore the cache line size if we had modified
+ * it.
+ */
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
+ cp->orig_cacheline_size);
+ }
+#endif
+ pci_free_consistent(pdev, sizeof(struct cas_init_block),
+ cp->init_block, cp->block_dvma);
+ iounmap(cp->regs);
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int cas_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct cas *cp = netdev_priv(dev);
+ unsigned long flags;
+
+ /* We hold the PM semaphore during entire driver
+ * sleep time
+ */
+ down(&cp->pm_sem);
+
+ /* If the driver is opened, we stop the DMA */
+ if (cp->opened) {
+ netif_device_detach(dev);
+
+ cas_lock_all_save(cp, flags);
+
+ /* We can set the second arg of cas_reset to 0
+ * because on resume, we'll call cas_init_hw with
+ * its second arg set so that autonegotiation is
+ * restarted.
+ */
+ cas_reset(cp, 0);
+ cas_clean_rings(cp);
+ cas_unlock_all_restore(cp, flags);
+ }
+
+ if (cp->hw_running)
+ cas_shutdown(cp);
+
+ return 0;
+}
+
+static int cas_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct cas *cp = netdev_priv(dev);
+
+ printk(KERN_INFO "%s: resuming\n", dev->name);
+
+ cas_hard_reset(cp);
+ if (cp->opened) {
+ unsigned long flags;
+ cas_lock_all_save(cp, flags);
+ cas_reset(cp, 0);
+ cp->hw_running = 1;
+ cas_clean_rings(cp);
+ cas_init_hw(cp, 1);
+ cas_unlock_all_restore(cp, flags);
+
+ netif_device_attach(dev);
+ }
+ up(&cp->pm_sem);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_driver cas_driver = {
+ .name = DRV_MODULE_NAME,
+ .id_table = cas_pci_tbl,
+ .probe = cas_init_one,
+ .remove = __devexit_p(cas_remove_one),
+#ifdef CONFIG_PM
+ .suspend = cas_suspend,
+ .resume = cas_resume
+#endif
+};
+
+static int __init cas_init(void)
+{
+ if (linkdown_timeout > 0)
+ link_transition_timeout = linkdown_timeout * HZ;
+ else
+ link_transition_timeout = 0;
+
+ return pci_module_init(&cas_driver);
+}
+
+static void __exit cas_cleanup(void)
+{
+ pci_unregister_driver(&cas_driver);
+}
+
+module_init(cas_init);
+module_exit(cas_cleanup);
diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
new file mode 100644
index 000000000000..88063ef16cf6
--- /dev/null
+++ b/drivers/net/cassini.h
@@ -0,0 +1,4425 @@
+/* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
+ * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
+ *
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (c) 2003 Adrian Sun (asun@darksunrising.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.
+ *
+ * vendor id: 0x108E (Sun Microsystems, Inc.)
+ * device id: 0xabba (Cassini)
+ * revision ids: 0x01 = Cassini
+ * 0x02 = Cassini rev 2
+ * 0x10 = Cassini+
+ * 0x11 = Cassini+ 0.2u
+ *
+ * vendor id: 0x100b (National Semiconductor)
+ * device id: 0x0035 (DP83065/Saturn)
+ * revision ids: 0x30 = Saturn B2
+ *
+ * rings are all offset from 0.
+ *
+ * there are two clock domains:
+ * PCI: 33/66MHz clock
+ * chip: 125MHz clock
+ */
+
+#ifndef _CASSINI_H
+#define _CASSINI_H
+
+/* cassini register map: 2M memory mapped in 32-bit memory space accessible as
+ * 32-bit words. there is no i/o port access. REG_ addresses are
+ * shared between cassini and cassini+. REG_PLUS_ addresses only
+ * appear in cassini+. REG_MINUS_ addresses only appear in cassini.
+ */
+#define CAS_ID_REV2 0x02
+#define CAS_ID_REVPLUS 0x10
+#define CAS_ID_REVPLUS02u 0x11
+#define CAS_ID_REVSATURNB2 0x30
+
+/** global resources **/
+
+/* this register sets the weights for the weighted round robin arbiter. e.g.,
+ * if rx weight == 1 and tx weight == 0, rx == 2x tx transfer credit
+ * for its next turn to access the pci bus.
+ * map: 0x0 = x1, 0x1 = x2, 0x2 = x4, 0x3 = x8
+ * DEFAULT: 0x0, SIZE: 5 bits
+ */
+#define REG_CAWR 0x0004 /* core arbitration weight */
+#define CAWR_RX_DMA_WEIGHT_SHIFT 0
+#define CAWR_RX_DMA_WEIGHT_MASK 0x03 /* [0:1] */
+#define CAWR_TX_DMA_WEIGHT_SHIFT 2
+#define CAWR_TX_DMA_WEIGHT_MASK 0x0C /* [3:2] */
+#define CAWR_RR_DIS 0x10 /* [4] */
+
+/* if enabled, BIM can send bursts across PCI bus > cacheline size. burst
+ * sizes determined by length of packet or descriptor transfer and the
+ * max length allowed by the target.
+ * DEFAULT: 0x0, SIZE: 1 bit
+ */
+#define REG_INF_BURST 0x0008 /* infinite burst enable reg */
+#define INF_BURST_EN 0x1 /* enable */
+
+/* top level interrupts [0-9] are auto-cleared to 0 when the status
+ * register is read. second level interrupts [13 - 18] are cleared at
+ * the source. tx completion register 3 is replicated in [19 - 31]
+ * DEFAULT: 0x00000000, SIZE: 29 bits
+ */
+#define REG_INTR_STATUS 0x000C /* interrupt status register */
+#define INTR_TX_INTME 0x00000001 /* frame w/ INT ME desc bit set
+ xferred from host queue to
+ TX FIFO */
+#define INTR_TX_ALL 0x00000002 /* all xmit frames xferred into
+ TX FIFO. i.e.,
+ TX Kick == TX complete. if
+ PACED_MODE set, then TX FIFO
+ also empty */
+#define INTR_TX_DONE 0x00000004 /* any frame xferred into tx
+ FIFO */
+#define INTR_TX_TAG_ERROR 0x00000008 /* TX FIFO tag framing
+ corrupted. FATAL ERROR */
+#define INTR_RX_DONE 0x00000010 /* at least 1 frame xferred
+ from RX FIFO to host mem.
+ RX completion reg updated.
+ may be delayed by recv
+ intr blanking. */
+#define INTR_RX_BUF_UNAVAIL 0x00000020 /* no more receive buffers.
+ RX Kick == RX complete */
+#define INTR_RX_TAG_ERROR 0x00000040 /* RX FIFO tag framing
+ corrupted. FATAL ERROR */
+#define INTR_RX_COMP_FULL 0x00000080 /* no more room in completion
+ ring to post descriptors.
+ RX complete head incr to
+ almost reach RX complete
+ tail */
+#define INTR_RX_BUF_AE 0x00000100 /* less than the
+ programmable threshold #
+ of free descr avail for
+ hw use */
+#define INTR_RX_COMP_AF 0x00000200 /* less than the
+ programmable threshold #
+ of descr spaces for hw
+ use in completion descr
+ ring */
+#define INTR_RX_LEN_MISMATCH 0x00000400 /* len field from MAC !=
+ len of non-reassembly pkt
+ from fifo during DMA or
+ header parser provides TCP
+ header and payload size >
+ MAC packet size.
+ FATAL ERROR */
+#define INTR_SUMMARY 0x00001000 /* summary interrupt bit. this
+ bit will be set if an interrupt
+ generated on the pci bus. useful
+ when driver is polling for
+ interrupts */
+#define INTR_PCS_STATUS 0x00002000 /* PCS interrupt status register */
+#define INTR_TX_MAC_STATUS 0x00004000 /* TX MAC status register has at
+ least 1 unmasked interrupt set */
+#define INTR_RX_MAC_STATUS 0x00008000 /* RX MAC status register has at
+ least 1 unmasked interrupt set */
+#define INTR_MAC_CTRL_STATUS 0x00010000 /* MAC control status register has
+ at least 1 unmasked interrupt
+ set */
+#define INTR_MIF_STATUS 0x00020000 /* MIF status register has at least
+ 1 unmasked interrupt set */
+#define INTR_PCI_ERROR_STATUS 0x00040000 /* PCI error status register in the
+ BIF has at least 1 unmasked
+ interrupt set */
+#define INTR_TX_COMP_3_MASK 0xFFF80000 /* mask for TX completion
+ 3 reg data */
+#define INTR_TX_COMP_3_SHIFT 19
+#define INTR_ERROR_MASK (INTR_MIF_STATUS | INTR_PCI_ERROR_STATUS | \
+ INTR_PCS_STATUS | INTR_RX_LEN_MISMATCH | \
+ INTR_TX_MAC_STATUS | INTR_RX_MAC_STATUS | \
+ INTR_TX_TAG_ERROR | INTR_RX_TAG_ERROR | \
+ INTR_MAC_CTRL_STATUS)
+
+/* determines which status events will cause an interrupt. layout same
+ * as REG_INTR_STATUS.
+ * DEFAULT: 0xFFFFFFFF, SIZE: 16 bits
+ */
+#define REG_INTR_MASK 0x0010 /* Interrupt mask */
+
+/* top level interrupt bits that are cleared during read of REG_INTR_STATUS_ALIAS.
+ * useful when driver is polling for interrupts. layout same as REG_INTR_MASK.
+ * DEFAULT: 0x00000000, SIZE: 12 bits
+ */
+#define REG_ALIAS_CLEAR 0x0014 /* alias clear mask
+ (used w/ status alias) */
+/* same as REG_INTR_STATUS except that only bits cleared are those selected by
+ * REG_ALIAS_CLEAR
+ * DEFAULT: 0x00000000, SIZE: 29 bits
+ */
+#define REG_INTR_STATUS_ALIAS 0x001C /* interrupt status alias
+ (selective clear) */
+
+/* DEFAULT: 0x0, SIZE: 3 bits */
+#define REG_PCI_ERR_STATUS 0x1000 /* PCI error status */
+#define PCI_ERR_BADACK 0x01 /* reserved in Cassini+.
+ set if no ACK64# during ABS64 cycle
+ in Cassini. */
+#define PCI_ERR_DTRTO 0x02 /* delayed xaction timeout. set if
+ no read retry after 2^15 clocks */
+#define PCI_ERR_OTHER 0x04 /* other PCI errors */
+#define PCI_ERR_BIM_DMA_WRITE 0x08 /* BIM received 0 count DMA write req.
+ unused in Cassini. */
+#define PCI_ERR_BIM_DMA_READ 0x10 /* BIM received 0 count DMA read req.
+ unused in Cassini. */
+#define PCI_ERR_BIM_DMA_TIMEOUT 0x20 /* BIM received 255 retries during
+ DMA. unused in cassini. */
+
+/* mask for PCI status events that will set PCI_ERR_STATUS. if cleared, event
+ * causes an interrupt to be generated.
+ * DEFAULT: 0x7, SIZE: 3 bits
+ */
+#define REG_PCI_ERR_STATUS_MASK 0x1004 /* PCI Error status mask */
+
+/* used to configure PCI related parameters that are not in PCI config space.
+ * DEFAULT: 0bxx000, SIZE: 5 bits
+ */
+#define REG_BIM_CFG 0x1008 /* BIM Configuration */
+#define BIM_CFG_RESERVED0 0x001 /* reserved */
+#define BIM_CFG_RESERVED1 0x002 /* reserved */
+#define BIM_CFG_64BIT_DISABLE 0x004 /* disable 64-bit mode */
+#define BIM_CFG_66MHZ 0x008 /* (ro) 1 = 66MHz, 0 = < 66MHz */
+#define BIM_CFG_32BIT 0x010 /* (ro) 1 = 32-bit slot, 0 = 64-bit */
+#define BIM_CFG_DPAR_INTR_ENABLE 0x020 /* detected parity err enable */
+#define BIM_CFG_RMA_INTR_ENABLE 0x040 /* master abort intr enable */
+#define BIM_CFG_RTA_INTR_ENABLE 0x080 /* target abort intr enable */
+#define BIM_CFG_RESERVED2 0x100 /* reserved */
+#define BIM_CFG_BIM_DISABLE 0x200 /* stop BIM DMA. use before global
+ reset. reserved in Cassini. */
+#define BIM_CFG_BIM_STATUS 0x400 /* (ro) 1 = BIM DMA suspended.
+ reserved in Cassini. */
+#define BIM_CFG_PERROR_BLOCK 0x800 /* block PERR# to pci bus. def: 0.
+ reserved in Cassini. */
+
+/* DEFAULT: 0x00000000, SIZE: 32 bits */
+#define REG_BIM_DIAG 0x100C /* BIM Diagnostic */
+#define BIM_DIAG_MSTR_SM_MASK 0x3FFFFF00 /* PCI master controller state
+ machine bits [21:0] */
+#define BIM_DIAG_BRST_SM_MASK 0x7F /* PCI burst controller state
+ machine bits [6:0] */
+
+/* writing to SW_RESET_TX and SW_RESET_RX will issue a global
+ * reset. poll until TX and RX read back as 0's for completion.
+ */
+#define REG_SW_RESET 0x1010 /* Software reset */
+#define SW_RESET_TX 0x00000001 /* reset TX DMA engine. poll until
+ cleared to 0. */
+#define SW_RESET_RX 0x00000002 /* reset RX DMA engine. poll until
+ cleared to 0. */
+#define SW_RESET_RSTOUT 0x00000004 /* force RSTOUT# pin active (low).
+ resets PHY and anything else
+ connected to RSTOUT#. RSTOUT#
+ is also activated by local PCI
+ reset when hot-swap is being
+ done. */
+#define SW_RESET_BLOCK_PCS_SLINK 0x00000008 /* if a global reset is done with
+ this bit set, PCS and SLINK
+ modules won't be reset.
+ i.e., link won't drop. */
+#define SW_RESET_BREQ_SM_MASK 0x00007F00 /* breq state machine [6:0] */
+#define SW_RESET_PCIARB_SM_MASK 0x00070000 /* pci arbitration state bits:
+ 0b000: ARB_IDLE1
+ 0b001: ARB_IDLE2
+ 0b010: ARB_WB_ACK
+ 0b011: ARB_WB_WAT
+ 0b100: ARB_RB_ACK
+ 0b101: ARB_RB_WAT
+ 0b110: ARB_RB_END
+ 0b111: ARB_WB_END */
+#define SW_RESET_RDPCI_SM_MASK 0x00300000 /* read pci state bits:
+ 0b00: RD_PCI_WAT
+ 0b01: RD_PCI_RDY
+ 0b11: RD_PCI_ACK */
+#define SW_RESET_RDARB_SM_MASK 0x00C00000 /* read arbitration state bits:
+ 0b00: AD_IDL_RX
+ 0b01: AD_ACK_RX
+ 0b10: AD_ACK_TX
+ 0b11: AD_IDL_TX */
+#define SW_RESET_WRPCI_SM_MASK 0x06000000 /* write pci state bits
+ 0b00: WR_PCI_WAT
+ 0b01: WR_PCI_RDY
+ 0b11: WR_PCI_ACK */
+#define SW_RESET_WRARB_SM_MASK 0x38000000 /* write arbitration state bits:
+ 0b000: ARB_IDLE1
+ 0b001: ARB_IDLE2
+ 0b010: ARB_TX_ACK
+ 0b011: ARB_TX_WAT
+ 0b100: ARB_RX_ACK
+ 0b110: ARB_RX_WAT */
+
+/* Cassini only. 64-bit register used to check PCI datapath. when read,
+ * value written has both lower and upper 32-bit halves rotated to the right
+ * one bit position. e.g., FFFFFFFF FFFFFFFF -> 7FFFFFFF 7FFFFFFF
+ */
+#define REG_MINUS_BIM_DATAPATH_TEST 0x1018 /* Cassini: BIM datapath test
+ Cassini+: reserved */
+
+/* output enables are provided for each device's chip select and for the rest
+ * of the outputs from cassini to its local bus devices. two sw programmable
+ * bits are connected to general purpus control/status bits.
+ * DEFAULT: 0x7
+ */
+#define REG_BIM_LOCAL_DEV_EN 0x1020 /* BIM local device
+ output EN. default: 0x7 */
+#define BIM_LOCAL_DEV_PAD 0x01 /* address bus, RW signal, and
+ OE signal output enable on the
+ local bus interface. these
+ are shared between both local
+ bus devices. tristate when 0. */
+#define BIM_LOCAL_DEV_PROM 0x02 /* PROM chip select */
+#define BIM_LOCAL_DEV_EXT 0x04 /* secondary local bus device chip
+ select output enable */
+#define BIM_LOCAL_DEV_SOFT_0 0x08 /* sw programmable ctrl bit 0 */
+#define BIM_LOCAL_DEV_SOFT_1 0x10 /* sw programmable ctrl bit 1 */
+#define BIM_LOCAL_DEV_HW_RESET 0x20 /* internal hw reset. Cassini+ only. */
+
+/* access 24 entry BIM read and write buffers. put address in REG_BIM_BUFFER_ADDR
+ * and read/write from/to it REG_BIM_BUFFER_DATA_LOW and _DATA_HI.
+ * _DATA_HI should be the last access of the sequence.
+ * DEFAULT: undefined
+ */
+#define REG_BIM_BUFFER_ADDR 0x1024 /* BIM buffer address. for
+ purposes. */
+#define BIM_BUFFER_ADDR_MASK 0x3F /* index (0 - 23) of buffer */
+#define BIM_BUFFER_WR_SELECT 0x40 /* write buffer access = 1
+ read buffer access = 0 */
+/* DEFAULT: undefined */
+#define REG_BIM_BUFFER_DATA_LOW 0x1028 /* BIM buffer data low */
+#define REG_BIM_BUFFER_DATA_HI 0x102C /* BIM buffer data high */
+
+/* set BIM_RAM_BIST_START to start built-in self test for BIM read buffer.
+ * bit auto-clears when done with status read from _SUMMARY and _PASS bits.
+ */
+#define REG_BIM_RAM_BIST 0x102C /* BIM RAM (read buffer) BIST
+ control/status */
+#define BIM_RAM_BIST_RD_START 0x01 /* start BIST for BIM read buffer */
+#define BIM_RAM_BIST_WR_START 0x02 /* start BIST for BIM write buffer.
+ Cassini only. reserved in
+ Cassini+. */
+#define BIM_RAM_BIST_RD_PASS 0x04 /* summary BIST pass status for read
+ buffer. */
+#define BIM_RAM_BIST_WR_PASS 0x08 /* summary BIST pass status for write
+ buffer. Cassini only. reserved
+ in Cassini+. */
+#define BIM_RAM_BIST_RD_LOW_PASS 0x10 /* read low bank passes BIST */
+#define BIM_RAM_BIST_RD_HI_PASS 0x20 /* read high bank passes BIST */
+#define BIM_RAM_BIST_WR_LOW_PASS 0x40 /* write low bank passes BIST.
+ Cassini only. reserved in
+ Cassini+. */
+#define BIM_RAM_BIST_WR_HI_PASS 0x80 /* write high bank passes BIST.
+ Cassini only. reserved in
+ Cassini+. */
+
+/* ASUN: i'm not sure what this does as it's not in the spec.
+ * DEFAULT: 0xFC
+ */
+#define REG_BIM_DIAG_MUX 0x1030 /* BIM diagnostic probe mux
+ select register */
+
+/* enable probe monitoring mode and select data appearing on the P_A* bus. bit
+ * values for _SEL_HI_MASK and _SEL_LOW_MASK:
+ * 0x0: internal probe[7:0] (pci arb state, wtc empty w, wtc full w, wtc empty w,
+ * wtc empty r, post pci)
+ * 0x1: internal probe[15:8] (pci wbuf comp, pci wpkt comp, pci rbuf comp,
+ * pci rpkt comp, txdma wr req, txdma wr ack,
+ * txdma wr rdy, txdma wr xfr done)
+ * 0x2: internal probe[23:16] (txdma rd req, txdma rd ack, txdma rd rdy, rxdma rd,
+ * rd arb state, rd pci state)
+ * 0x3: internal probe[31:24] (rxdma req, rxdma ack, rxdma rdy, wrarb state,
+ * wrpci state)
+ * 0x4: pci io probe[7:0] 0x5: pci io probe[15:8]
+ * 0x6: pci io probe[23:16] 0x7: pci io probe[31:24]
+ * 0x8: pci io probe[39:32] 0x9: pci io probe[47:40]
+ * 0xa: pci io probe[55:48] 0xb: pci io probe[63:56]
+ * the following are not available in Cassini:
+ * 0xc: rx probe[7:0] 0xd: tx probe[7:0]
+ * 0xe: hp probe[7:0] 0xf: mac probe[7:0]
+ */
+#define REG_PLUS_PROBE_MUX_SELECT 0x1034 /* Cassini+: PROBE MUX SELECT */
+#define PROBE_MUX_EN 0x80000000 /* allow probe signals to be
+ driven on local bus P_A[15:0]
+ for debugging */
+#define PROBE_MUX_SUB_MUX_MASK 0x0000FF00 /* select sub module probe signals:
+ 0x03 = mac[1:0]
+ 0x0C = rx[1:0]
+ 0x30 = tx[1:0]
+ 0xC0 = hp[1:0] */
+#define PROBE_MUX_SEL_HI_MASK 0x000000F0 /* select which module to appear
+ on P_A[15:8]. see above for
+ values. */
+#define PROBE_MUX_SEL_LOW_MASK 0x0000000F /* select which module to appear
+ on P_A[7:0]. see above for
+ values. */
+
+/* values mean the same thing as REG_INTR_MASK excep that it's for INTB.
+ DEFAULT: 0x1F */
+#define REG_PLUS_INTR_MASK_1 0x1038 /* Cassini+: interrupt mask
+ register 2 for INTB */
+#define REG_PLUS_INTRN_MASK(x) (REG_PLUS_INTR_MASK_1 + ((x) - 1)*16)
+/* bits correspond to both _MASK and _STATUS registers. _ALT corresponds to
+ * all of the alternate (2-4) INTR registers while _1 corresponds to only
+ * _MASK_1 and _STATUS_1 registers.
+ * DEFAULT: 0x7 for MASK registers, 0x0 for ALIAS_CLEAR registers
+ */
+#define INTR_RX_DONE_ALT 0x01
+#define INTR_RX_COMP_FULL_ALT 0x02
+#define INTR_RX_COMP_AF_ALT 0x04
+#define INTR_RX_BUF_UNAVAIL_1 0x08
+#define INTR_RX_BUF_AE_1 0x10 /* almost empty */
+#define INTRN_MASK_RX_EN 0x80
+#define INTRN_MASK_CLEAR_ALL (INTR_RX_DONE_ALT | \
+ INTR_RX_COMP_FULL_ALT | \
+ INTR_RX_COMP_AF_ALT | \
+ INTR_RX_BUF_UNAVAIL_1 | \
+ INTR_RX_BUF_AE_1)
+#define REG_PLUS_INTR_STATUS_1 0x103C /* Cassini+: interrupt status
+ register 2 for INTB. default: 0x1F */
+#define REG_PLUS_INTRN_STATUS(x) (REG_PLUS_INTR_STATUS_1 + ((x) - 1)*16)
+#define INTR_STATUS_ALT_INTX_EN 0x80 /* generate INTX when one of the
+ flags are set. enables desc ring. */
+
+#define REG_PLUS_ALIAS_CLEAR_1 0x1040 /* Cassini+: alias clear mask
+ register 2 for INTB */
+#define REG_PLUS_ALIASN_CLEAR(x) (REG_PLUS_ALIAS_CLEAR_1 + ((x) - 1)*16)
+
+#define REG_PLUS_INTR_STATUS_ALIAS_1 0x1044 /* Cassini+: interrupt status
+ register alias 2 for INTB */
+#define REG_PLUS_INTRN_STATUS_ALIAS(x) (REG_PLUS_INTR_STATUS_ALIAS_1 + ((x) - 1)*16)
+
+#define REG_SATURN_PCFG 0x106c /* pin configuration register for
+ integrated macphy */
+
+#define SATURN_PCFG_TLA 0x00000001 /* 1 = phy actled */
+#define SATURN_PCFG_FLA 0x00000002 /* 1 = phy link10led */
+#define SATURN_PCFG_CLA 0x00000004 /* 1 = phy link100led */
+#define SATURN_PCFG_LLA 0x00000008 /* 1 = phy link1000led */
+#define SATURN_PCFG_RLA 0x00000010 /* 1 = phy duplexled */
+#define SATURN_PCFG_PDS 0x00000020 /* phy debug mode.
+ 0 = normal */
+#define SATURN_PCFG_MTP 0x00000080 /* test point select */
+#define SATURN_PCFG_GMO 0x00000100 /* GMII observe. 1 =
+ GMII on SERDES pins for
+ monitoring. */
+#define SATURN_PCFG_FSI 0x00000200 /* 1 = freeze serdes/gmii. all
+ pins configed as outputs.
+ for power saving when using
+ internal phy. */
+#define SATURN_PCFG_LAD 0x00000800 /* 0 = mac core led ctrl
+ polarity from strapping
+ value.
+ 1 = mac core led ctrl
+ polarity active low. */
+
+
+/** transmit dma registers **/
+#define MAX_TX_RINGS_SHIFT 2
+#define MAX_TX_RINGS (1 << MAX_TX_RINGS_SHIFT)
+#define MAX_TX_RINGS_MASK (MAX_TX_RINGS - 1)
+
+/* TX configuration.
+ * descr ring sizes size = 32 * (1 << n), n < 9. e.g., 0x8 = 8k. default: 0x8
+ * DEFAULT: 0x3F000001
+ */
+#define REG_TX_CFG 0x2004 /* TX config */
+#define TX_CFG_DMA_EN 0x00000001 /* enable TX DMA. if cleared, DMA
+ will stop after xfer of current
+ buffer has been completed. */
+#define TX_CFG_FIFO_PIO_SEL 0x00000002 /* TX DMA FIFO can be
+ accessed w/ FIFO addr
+ and data registers.
+ TX DMA should be
+ disabled. */
+#define TX_CFG_DESC_RING0_MASK 0x0000003C /* # desc entries in
+ ring 1. */
+#define TX_CFG_DESC_RING0_SHIFT 2
+#define TX_CFG_DESC_RINGN_MASK(a) (TX_CFG_DESC_RING0_MASK << (a)*4)
+#define TX_CFG_DESC_RINGN_SHIFT(a) (TX_CFG_DESC_RING0_SHIFT + (a)*4)
+#define TX_CFG_PACED_MODE 0x00100000 /* TX_ALL only set after
+ TX FIFO becomes empty.
+ if 0, TX_ALL set
+ if descr queue empty. */
+#define TX_CFG_DMA_RDPIPE_DIS 0x01000000 /* always set to 1 */
+#define TX_CFG_COMPWB_Q1 0x02000000 /* completion writeback happens at
+ the end of every packet kicked
+ through Q1. */
+#define TX_CFG_COMPWB_Q2 0x04000000 /* completion writeback happens at
+ the end of every packet kicked
+ through Q2. */
+#define TX_CFG_COMPWB_Q3 0x08000000 /* completion writeback happens at
+ the end of every packet kicked
+ through Q3 */
+#define TX_CFG_COMPWB_Q4 0x10000000 /* completion writeback happens at
+ the end of every packet kicked
+ through Q4 */
+#define TX_CFG_INTR_COMPWB_DIS 0x20000000 /* disable pre-interrupt completion
+ writeback */
+#define TX_CFG_CTX_SEL_MASK 0xC0000000 /* selects tx test port
+ connection
+ 0b00: tx mac req,
+ tx mac retry req,
+ tx ack and tx tag.
+ 0b01: txdma rd req,
+ txdma rd ack,
+ txdma rd rdy,
+ txdma rd type0
+ 0b11: txdma wr req,
+ txdma wr ack,
+ txdma wr rdy,
+ txdma wr xfr done. */
+#define TX_CFG_CTX_SEL_SHIFT 30
+
+/* 11-bit counters that point to next location in FIFO to be loaded/retrieved.
+ * used for diagnostics only.
+ */
+#define REG_TX_FIFO_WRITE_PTR 0x2014 /* TX FIFO write pointer */
+#define REG_TX_FIFO_SHADOW_WRITE_PTR 0x2018 /* TX FIFO shadow write
+ pointer. temp hold reg.
+ diagnostics only. */
+#define REG_TX_FIFO_READ_PTR 0x201C /* TX FIFO read pointer */
+#define REG_TX_FIFO_SHADOW_READ_PTR 0x2020 /* TX FIFO shadow read
+ pointer */
+
+/* (ro) 11-bit up/down counter w/ # of frames currently in TX FIFO */
+#define REG_TX_FIFO_PKT_CNT 0x2024 /* TX FIFO packet counter */
+
+/* current state of all state machines in TX */
+#define REG_TX_SM_1 0x2028 /* TX state machine reg #1 */
+#define TX_SM_1_CHAIN_MASK 0x000003FF /* chaining state machine */
+#define TX_SM_1_CSUM_MASK 0x00000C00 /* checksum state machine */
+#define TX_SM_1_FIFO_LOAD_MASK 0x0003F000 /* FIFO load state machine.
+ = 0x01 when TX disabled. */
+#define TX_SM_1_FIFO_UNLOAD_MASK 0x003C0000 /* FIFO unload state machine */
+#define TX_SM_1_CACHE_MASK 0x03C00000 /* desc. prefetch cache controller
+ state machine */
+#define TX_SM_1_CBQ_ARB_MASK 0xF8000000 /* CBQ arbiter state machine */
+
+#define REG_TX_SM_2 0x202C /* TX state machine reg #2 */
+#define TX_SM_2_COMP_WB_MASK 0x07 /* completion writeback sm */
+#define TX_SM_2_SUB_LOAD_MASK 0x38 /* sub load state machine */
+#define TX_SM_2_KICK_MASK 0xC0 /* kick state machine */
+
+/* 64-bit pointer to the transmit data buffer. only the 50 LSB are incremented
+ * while the upper 23 bits are taken from the TX descriptor
+ */
+#define REG_TX_DATA_PTR_LOW 0x2030 /* TX data pointer low */
+#define REG_TX_DATA_PTR_HI 0x2034 /* TX data pointer high */
+
+/* 13 bit registers written by driver w/ descriptor value that follows
+ * last valid xmit descriptor. kick # and complete # values are used by
+ * the xmit dma engine to control tx descr fetching. if > 1 valid
+ * tx descr is available within the cache line being read, cassini will
+ * internally cache up to 4 of them. 0 on reset. _KICK = rw, _COMP = ro.
+ */
+#define REG_TX_KICK0 0x2038 /* TX kick reg #1 */
+#define REG_TX_KICKN(x) (REG_TX_KICK0 + (x)*4)
+#define REG_TX_COMP0 0x2048 /* TX completion reg #1 */
+#define REG_TX_COMPN(x) (REG_TX_COMP0 + (x)*4)
+
+/* values of TX_COMPLETE_1-4 are written. each completion register
+ * is 2bytes in size and contiguous. 8B allocation w/ 8B alignment.
+ * NOTE: completion reg values are only written back prior to TX_INTME and
+ * TX_ALL interrupts. at all other times, the most up-to-date index values
+ * should be obtained from the REG_TX_COMPLETE_# registers.
+ * here's the layout:
+ * offset from base addr completion # byte
+ * 0 TX_COMPLETE_1_MSB
+ * 1 TX_COMPLETE_1_LSB
+ * 2 TX_COMPLETE_2_MSB
+ * 3 TX_COMPLETE_2_LSB
+ * 4 TX_COMPLETE_3_MSB
+ * 5 TX_COMPLETE_3_LSB
+ * 6 TX_COMPLETE_4_MSB
+ * 7 TX_COMPLETE_4_LSB
+ */
+#define TX_COMPWB_SIZE 8
+#define REG_TX_COMPWB_DB_LOW 0x2058 /* TX completion write back
+ base low */
+#define REG_TX_COMPWB_DB_HI 0x205C /* TX completion write back
+ base high */
+#define TX_COMPWB_MSB_MASK 0x00000000000000FFULL
+#define TX_COMPWB_MSB_SHIFT 0
+#define TX_COMPWB_LSB_MASK 0x000000000000FF00ULL
+#define TX_COMPWB_LSB_SHIFT 8
+#define TX_COMPWB_NEXT(x) ((x) >> 16)
+
+/* 53 MSB used as base address. 11 LSB assumed to be 0. TX desc pointer must
+ * be 2KB-aligned. */
+#define REG_TX_DB0_LOW 0x2060 /* TX descriptor base low #1 */
+#define REG_TX_DB0_HI 0x2064 /* TX descriptor base hi #1 */
+#define REG_TX_DBN_LOW(x) (REG_TX_DB0_LOW + (x)*8)
+#define REG_TX_DBN_HI(x) (REG_TX_DB0_HI + (x)*8)
+
+/* 16-bit registers hold weights for the weighted round-robin of the
+ * four CBQ TX descr rings. weights correspond to # bytes xferred from
+ * host to TXFIFO in a round of WRR arbitration. can be set
+ * dynamically with new weights set upon completion of the current
+ * packet transfer from host memory to TXFIFO. a dummy write to any of
+ * these registers causes a queue1 pre-emption with all historical bw
+ * deficit data reset to 0 (useful when congestion requires a
+ * pre-emption/re-allocation of network bandwidth
+ */
+#define REG_TX_MAXBURST_0 0x2080 /* TX MaxBurst #1 */
+#define REG_TX_MAXBURST_1 0x2084 /* TX MaxBurst #2 */
+#define REG_TX_MAXBURST_2 0x2088 /* TX MaxBurst #3 */
+#define REG_TX_MAXBURST_3 0x208C /* TX MaxBurst #4 */
+
+/* diagnostics access to any TX FIFO location. every access is 65
+ * bits. _DATA_LOW = 32 LSB, _DATA_HI_T1/T0 = 32 MSB. _TAG = tag bit.
+ * writing _DATA_HI_T0 sets tag bit low, writing _DATA_HI_T1 sets tag
+ * bit high. TX_FIFO_PIO_SEL must be set for TX FIFO PIO access. if
+ * TX FIFO data integrity is desired, TX DMA should be
+ * disabled. _DATA_HI_Tx should be the last access of the sequence.
+ */
+#define REG_TX_FIFO_ADDR 0x2104 /* TX FIFO address */
+#define REG_TX_FIFO_TAG 0x2108 /* TX FIFO tag */
+#define REG_TX_FIFO_DATA_LOW 0x210C /* TX FIFO data low */
+#define REG_TX_FIFO_DATA_HI_T1 0x2110 /* TX FIFO data high t1 */
+#define REG_TX_FIFO_DATA_HI_T0 0x2114 /* TX FIFO data high t0 */
+#define REG_TX_FIFO_SIZE 0x2118 /* (ro) TX FIFO size = 0x090 = 9KB */
+
+/* 9-bit register controls BIST of TX FIFO. bit set indicates that the BIST
+ * passed for the specified memory
+ */
+#define REG_TX_RAMBIST 0x211C /* TX RAMBIST control/status */
+#define TX_RAMBIST_STATE 0x01C0 /* progress state of RAMBIST
+ controller state machine */
+#define TX_RAMBIST_RAM33A_PASS 0x0020 /* RAM33A passed */
+#define TX_RAMBIST_RAM32A_PASS 0x0010 /* RAM32A passed */
+#define TX_RAMBIST_RAM33B_PASS 0x0008 /* RAM33B passed */
+#define TX_RAMBIST_RAM32B_PASS 0x0004 /* RAM32B passed */
+#define TX_RAMBIST_SUMMARY 0x0002 /* all RAM passed */
+#define TX_RAMBIST_START 0x0001 /* write 1 to start BIST. self
+ clears on completion. */
+
+/** receive dma registers **/
+#define MAX_RX_DESC_RINGS 2
+#define MAX_RX_COMP_RINGS 4
+
+/* receive DMA channel configuration. default: 0x80910
+ * free ring size = (1 << n)*32 -> [32 - 8k]
+ * completion ring size = (1 << n)*128 -> [128 - 32k], n < 9
+ * DEFAULT: 0x80910
+ */
+#define REG_RX_CFG 0x4000 /* RX config */
+#define RX_CFG_DMA_EN 0x00000001 /* enable RX DMA. 0 stops
+ channel as soon as current
+ frame xfer has completed.
+ driver should disable MAC
+ for 200ms before disabling
+ RX */
+#define RX_CFG_DESC_RING_MASK 0x0000001E /* # desc entries in RX
+ free desc ring.
+ def: 0x8 = 8k */
+#define RX_CFG_DESC_RING_SHIFT 1
+#define RX_CFG_COMP_RING_MASK 0x000001E0 /* # desc entries in RX complete
+ ring. def: 0x8 = 32k */
+#define RX_CFG_COMP_RING_SHIFT 5
+#define RX_CFG_BATCH_DIS 0x00000200 /* disable receive desc
+ batching. def: 0x0 =
+ enabled */
+#define RX_CFG_SWIVEL_MASK 0x00001C00 /* byte offset of the 1st
+ data byte of the packet
+ w/in 8 byte boundares.
+ this swivels the data
+ DMA'ed to header
+ buffers, jumbo buffers
+ when header split is not
+ requested and MTU sized
+ buffers. def: 0x2 */
+#define RX_CFG_SWIVEL_SHIFT 10
+
+/* cassini+ only */
+#define RX_CFG_DESC_RING1_MASK 0x000F0000 /* # of desc entries in
+ RX free desc ring 2.
+ def: 0x8 = 8k */
+#define RX_CFG_DESC_RING1_SHIFT 16
+
+
+/* the page size register allows cassini chips to do the following with
+ * received data:
+ * [--------------------------------------------------------------] page
+ * [off][buf1][pad][off][buf2][pad][off][buf3][pad][off][buf4][pad]
+ * |--------------| = PAGE_SIZE_BUFFER_STRIDE
+ * page = PAGE_SIZE
+ * offset = PAGE_SIZE_MTU_OFF
+ * for the above example, MTU_BUFFER_COUNT = 4.
+ * NOTE: as is apparent, you need to ensure that the following holds:
+ * MTU_BUFFER_COUNT <= PAGE_SIZE/PAGE_SIZE_BUFFER_STRIDE
+ * DEFAULT: 0x48002002 (8k pages)
+ */
+#define REG_RX_PAGE_SIZE 0x4004 /* RX page size */
+#define RX_PAGE_SIZE_MASK 0x00000003 /* size of pages pointed to
+ by receive descriptors.
+ if jumbo buffers are
+ supported the page size
+ should not be < 8k.
+ 0b00 = 2k, 0b01 = 4k
+ 0b10 = 8k, 0b11 = 16k
+ DEFAULT: 8k */
+#define RX_PAGE_SIZE_SHIFT 0
+#define RX_PAGE_SIZE_MTU_COUNT_MASK 0x00007800 /* # of MTU buffers the hw
+ packs into a page.
+ DEFAULT: 4 */
+#define RX_PAGE_SIZE_MTU_COUNT_SHIFT 11
+#define RX_PAGE_SIZE_MTU_STRIDE_MASK 0x18000000 /* # of bytes that separate
+ each MTU buffer +
+ offset from each
+ other.
+ 0b00 = 1k, 0b01 = 2k
+ 0b10 = 4k, 0b11 = 8k
+ DEFAULT: 0x1 */
+#define RX_PAGE_SIZE_MTU_STRIDE_SHIFT 27
+#define RX_PAGE_SIZE_MTU_OFF_MASK 0xC0000000 /* offset in each page that
+ hw writes the MTU buffer
+ into.
+ 0b00 = 0,
+ 0b01 = 64 bytes
+ 0b10 = 96, 0b11 = 128
+ DEFAULT: 0x1 */
+#define RX_PAGE_SIZE_MTU_OFF_SHIFT 30
+
+/* 11-bit counter points to next location in RX FIFO to be loaded/read.
+ * shadow write pointers enable retries in case of early receive aborts.
+ * DEFAULT: 0x0. generated on 64-bit boundaries.
+ */
+#define REG_RX_FIFO_WRITE_PTR 0x4008 /* RX FIFO write pointer */
+#define REG_RX_FIFO_READ_PTR 0x400C /* RX FIFO read pointer */
+#define REG_RX_IPP_FIFO_SHADOW_WRITE_PTR 0x4010 /* RX IPP FIFO shadow write
+ pointer */
+#define REG_RX_IPP_FIFO_SHADOW_READ_PTR 0x4014 /* RX IPP FIFO shadow read
+ pointer */
+#define REG_RX_IPP_FIFO_READ_PTR 0x400C /* RX IPP FIFO read
+ pointer. (8-bit counter) */
+
+/* current state of RX DMA state engines + other info
+ * DEFAULT: 0x0
+ */
+#define REG_RX_DEBUG 0x401C /* RX debug */
+#define RX_DEBUG_LOAD_STATE_MASK 0x0000000F /* load state machine w/ MAC:
+ 0x0 = idle, 0x1 = load_bop
+ 0x2 = load 1, 0x3 = load 2
+ 0x4 = load 3, 0x5 = load 4
+ 0x6 = last detect
+ 0x7 = wait req
+ 0x8 = wait req statuss 1st
+ 0x9 = load st
+ 0xa = bubble mac
+ 0xb = error */
+#define RX_DEBUG_LM_STATE_MASK 0x00000070 /* load state machine w/ HP and
+ RX FIFO:
+ 0x0 = idle, 0x1 = hp xfr
+ 0x2 = wait hp ready
+ 0x3 = wait flow code
+ 0x4 = fifo xfer
+ 0x5 = make status
+ 0x6 = csum ready
+ 0x7 = error */
+#define RX_DEBUG_FC_STATE_MASK 0x000000180 /* flow control state machine
+ w/ MAC:
+ 0x0 = idle
+ 0x1 = wait xoff ack
+ 0x2 = wait xon
+ 0x3 = wait xon ack */
+#define RX_DEBUG_DATA_STATE_MASK 0x000001E00 /* unload data state machine
+ states:
+ 0x0 = idle data
+ 0x1 = header begin
+ 0x2 = xfer header
+ 0x3 = xfer header ld
+ 0x4 = mtu begin
+ 0x5 = xfer mtu
+ 0x6 = xfer mtu ld
+ 0x7 = jumbo begin
+ 0x8 = xfer jumbo
+ 0x9 = xfer jumbo ld
+ 0xa = reas begin
+ 0xb = xfer reas
+ 0xc = flush tag
+ 0xd = xfer reas ld
+ 0xe = error
+ 0xf = bubble idle */
+#define RX_DEBUG_DESC_STATE_MASK 0x0001E000 /* unload desc state machine
+ states:
+ 0x0 = idle desc
+ 0x1 = wait ack
+ 0x9 = wait ack 2
+ 0x2 = fetch desc 1
+ 0xa = fetch desc 2
+ 0x3 = load ptrs
+ 0x4 = wait dma
+ 0x5 = wait ack batch
+ 0x6 = post batch
+ 0x7 = xfr done */
+#define RX_DEBUG_INTR_READ_PTR_MASK 0x30000000 /* interrupt read ptr of the
+ interrupt queue */
+#define RX_DEBUG_INTR_WRITE_PTR_MASK 0xC0000000 /* interrupt write pointer
+ of the interrupt queue */
+
+/* flow control frames are emmitted using two PAUSE thresholds:
+ * XOFF PAUSE uses pause time value pre-programmed in the Send PAUSE MAC reg
+ * XON PAUSE uses a pause time of 0. granularity of threshold is 64bytes.
+ * PAUSE thresholds defined in terms of FIFO occupancy and may be translated
+ * into FIFO vacancy using RX_FIFO_SIZE. setting ON will trigger XON frames
+ * when FIFO reaches 0. OFF threshold should not be > size of RX FIFO. max
+ * value is is 0x6F.
+ * DEFAULT: 0x00078
+ */
+#define REG_RX_PAUSE_THRESH 0x4020 /* RX pause thresholds */
+#define RX_PAUSE_THRESH_QUANTUM 64
+#define RX_PAUSE_THRESH_OFF_MASK 0x000001FF /* XOFF PAUSE emitted when
+ RX FIFO occupancy >
+ value*64B */
+#define RX_PAUSE_THRESH_OFF_SHIFT 0
+#define RX_PAUSE_THRESH_ON_MASK 0x001FF000 /* XON PAUSE emitted after
+ emitting XOFF PAUSE when RX
+ FIFO occupancy falls below
+ this value*64B. must be
+ < XOFF threshold. if =
+ RX_FIFO_SIZE< XON frames are
+ never emitted. */
+#define RX_PAUSE_THRESH_ON_SHIFT 12
+
+/* 13-bit register used to control RX desc fetching and intr generation. if 4+
+ * valid RX descriptors are available, Cassini will read 4 at a time.
+ * writing N means that all desc up to *but* excluding N are available. N must
+ * be a multiple of 4 (N % 4 = 0). first desc should be cache-line aligned.
+ * DEFAULT: 0 on reset
+ */
+#define REG_RX_KICK 0x4024 /* RX kick reg */
+
+/* 8KB aligned 64-bit pointer to the base of the RX free/completion rings.
+ * lower 13 bits of the low register are hard-wired to 0.
+ */
+#define REG_RX_DB_LOW 0x4028 /* RX descriptor ring
+ base low */
+#define REG_RX_DB_HI 0x402C /* RX descriptor ring
+ base hi */
+#define REG_RX_CB_LOW 0x4030 /* RX completion ring
+ base low */
+#define REG_RX_CB_HI 0x4034 /* RX completion ring
+ base hi */
+/* 13-bit register indicate desc used by cassini for receive frames. used
+ * for diagnostic purposes.
+ * DEFAULT: 0 on reset
+ */
+#define REG_RX_COMP 0x4038 /* (ro) RX completion */
+
+/* HEAD and TAIL are used to control RX desc posting and interrupt
+ * generation. hw moves the head register to pass ownership to sw. sw
+ * moves the tail register to pass ownership back to hw. to give all
+ * entries to hw, set TAIL = HEAD. if HEAD and TAIL indicate that no
+ * more entries are available, DMA will pause and an interrupt will be
+ * generated to indicate no more entries are available. sw can use
+ * this interrupt to reduce the # of times it must update the
+ * completion tail register.
+ * DEFAULT: 0 on reset
+ */
+#define REG_RX_COMP_HEAD 0x403C /* RX completion head */
+#define REG_RX_COMP_TAIL 0x4040 /* RX completion tail */
+
+/* values used for receive interrupt blanking. loaded each time the ISR is read
+ * DEFAULT: 0x00000000
+ */
+#define REG_RX_BLANK 0x4044 /* RX blanking register
+ for ISR read */
+#define RX_BLANK_INTR_PKT_MASK 0x000001FF /* RX_DONE intr asserted if
+ this many sets of completion
+ writebacks (up to 2 packets)
+ occur since the last time
+ the ISR was read. 0 = no
+ packet blanking */
+#define RX_BLANK_INTR_PKT_SHIFT 0
+#define RX_BLANK_INTR_TIME_MASK 0x3FFFF000 /* RX_DONE interrupt asserted
+ if that many clocks were
+ counted since last time the
+ ISR was read.
+ each count is 512 core
+ clocks (125MHz). 0 = no
+ time blanking */
+#define RX_BLANK_INTR_TIME_SHIFT 12
+
+/* values used for interrupt generation based on threshold values of how
+ * many free desc and completion entries are available for hw use.
+ * DEFAULT: 0x00000000
+ */
+#define REG_RX_AE_THRESH 0x4048 /* RX almost empty
+ thresholds */
+#define RX_AE_THRESH_FREE_MASK 0x00001FFF /* RX_BUF_AE will be
+ generated if # desc
+ avail for hw use <=
+ # */
+#define RX_AE_THRESH_FREE_SHIFT 0
+#define RX_AE_THRESH_COMP_MASK 0x0FFFE000 /* RX_COMP_AE will be
+ generated if # of
+ completion entries
+ avail for hw use <=
+ # */
+#define RX_AE_THRESH_COMP_SHIFT 13
+
+/* probabilities for random early drop (RED) thresholds on a FIFO threshold
+ * basis. probability should increase when the FIFO level increases. control
+ * packets are never dropped and not counted in stats. probability programmed
+ * on a 12.5% granularity. e.g., 0x1 = 1/8 packets dropped.
+ * DEFAULT: 0x00000000
+ */
+#define REG_RX_RED 0x404C /* RX random early detect enable */
+#define RX_RED_4K_6K_FIFO_MASK 0x000000FF /* 4KB < FIFO thresh < 6KB */
+#define RX_RED_6K_8K_FIFO_MASK 0x0000FF00 /* 6KB < FIFO thresh < 8KB */
+#define RX_RED_8K_10K_FIFO_MASK 0x00FF0000 /* 8KB < FIFO thresh < 10KB */
+#define RX_RED_10K_12K_FIFO_MASK 0xFF000000 /* 10KB < FIFO thresh < 12KB */
+
+/* FIFO fullness levels for RX FIFO, RX control FIFO, and RX IPP FIFO.
+ * RX control FIFO = # of packets in RX FIFO.
+ * DEFAULT: 0x0
+ */
+#define REG_RX_FIFO_FULLNESS 0x4050 /* (ro) RX FIFO fullness */
+#define RX_FIFO_FULLNESS_RX_FIFO_MASK 0x3FF80000 /* level w/ 8B granularity */
+#define RX_FIFO_FULLNESS_IPP_FIFO_MASK 0x0007FF00 /* level w/ 8B granularity */
+#define RX_FIFO_FULLNESS_RX_PKT_MASK 0x000000FF /* # packets in RX FIFO */
+#define REG_RX_IPP_PACKET_COUNT 0x4054 /* RX IPP packet counter */
+#define REG_RX_WORK_DMA_PTR_LOW 0x4058 /* RX working DMA ptr low */
+#define REG_RX_WORK_DMA_PTR_HI 0x405C /* RX working DMA ptr
+ high */
+
+/* BIST testing ro RX FIFO, RX control FIFO, and RX IPP FIFO. only RX BIST
+ * START/COMPLETE is writeable. START will clear when the BIST has completed
+ * checking all 17 RAMS.
+ * DEFAULT: 0bxxxx xxxxx xxxx xxxx xxxx x000 0000 0000 00x0
+ */
+#define REG_RX_BIST 0x4060 /* (ro) RX BIST */
+#define RX_BIST_32A_PASS 0x80000000 /* RX FIFO 32A passed */
+#define RX_BIST_33A_PASS 0x40000000 /* RX FIFO 33A passed */
+#define RX_BIST_32B_PASS 0x20000000 /* RX FIFO 32B passed */
+#define RX_BIST_33B_PASS 0x10000000 /* RX FIFO 33B passed */
+#define RX_BIST_32C_PASS 0x08000000 /* RX FIFO 32C passed */
+#define RX_BIST_33C_PASS 0x04000000 /* RX FIFO 33C passed */
+#define RX_BIST_IPP_32A_PASS 0x02000000 /* RX IPP FIFO 33B passed */
+#define RX_BIST_IPP_33A_PASS 0x01000000 /* RX IPP FIFO 33A passed */
+#define RX_BIST_IPP_32B_PASS 0x00800000 /* RX IPP FIFO 32B passed */
+#define RX_BIST_IPP_33B_PASS 0x00400000 /* RX IPP FIFO 33B passed */
+#define RX_BIST_IPP_32C_PASS 0x00200000 /* RX IPP FIFO 32C passed */
+#define RX_BIST_IPP_33C_PASS 0x00100000 /* RX IPP FIFO 33C passed */
+#define RX_BIST_CTRL_32_PASS 0x00800000 /* RX CTRL FIFO 32 passed */
+#define RX_BIST_CTRL_33_PASS 0x00400000 /* RX CTRL FIFO 33 passed */
+#define RX_BIST_REAS_26A_PASS 0x00200000 /* RX Reas 26A passed */
+#define RX_BIST_REAS_26B_PASS 0x00100000 /* RX Reas 26B passed */
+#define RX_BIST_REAS_27_PASS 0x00080000 /* RX Reas 27 passed */
+#define RX_BIST_STATE_MASK 0x00078000 /* BIST state machine */
+#define RX_BIST_SUMMARY 0x00000002 /* when BIST complete,
+ summary pass bit
+ contains AND of BIST
+ results of all 16
+ RAMS */
+#define RX_BIST_START 0x00000001 /* write 1 to start
+ BIST. self clears
+ on completion. */
+
+/* next location in RX CTRL FIFO that will be loaded w/ data from RX IPP/read
+ * from to retrieve packet control info.
+ * DEFAULT: 0
+ */
+#define REG_RX_CTRL_FIFO_WRITE_PTR 0x4064 /* (ro) RX control FIFO
+ write ptr */
+#define REG_RX_CTRL_FIFO_READ_PTR 0x4068 /* (ro) RX control FIFO read
+ ptr */
+
+/* receive interrupt blanking. loaded each time interrupt alias register is
+ * read.
+ * DEFAULT: 0x0
+ */
+#define REG_RX_BLANK_ALIAS_READ 0x406C /* RX blanking register for
+ alias read */
+#define RX_BAR_INTR_PACKET_MASK 0x000001FF /* assert RX_DONE if #
+ completion writebacks
+ > # since last ISR
+ read. 0 = no
+ blanking. up to 2
+ packets per
+ completion wb. */
+#define RX_BAR_INTR_TIME_MASK 0x3FFFF000 /* assert RX_DONE if #
+ clocks > # since last
+ ISR read. each count
+ is 512 core clocks
+ (125MHz). 0 = no
+ blanking. */
+
+/* diagnostic access to RX FIFO. 32 LSB accessed via DATA_LOW. 32 MSB accessed
+ * via DATA_HI_T0 or DATA_HI_T1. TAG reads the tag bit. writing HI_T0
+ * will unset the tag bit while writing HI_T1 will set the tag bit. to reset
+ * to normal operation after diagnostics, write to address location 0x0.
+ * RX_DMA_EN bit must be set to 0x0 for RX FIFO PIO access. DATA_HI should
+ * be the last write access of a write sequence.
+ * DEFAULT: undefined
+ */
+#define REG_RX_FIFO_ADDR 0x4080 /* RX FIFO address */
+#define REG_RX_FIFO_TAG 0x4084 /* RX FIFO tag */
+#define REG_RX_FIFO_DATA_LOW 0x4088 /* RX FIFO data low */
+#define REG_RX_FIFO_DATA_HI_T0 0x408C /* RX FIFO data high T0 */
+#define REG_RX_FIFO_DATA_HI_T1 0x4090 /* RX FIFO data high T1 */
+
+/* diagnostic assess to RX CTRL FIFO. 8-bit FIFO_ADDR holds address of
+ * 81 bit control entry and 6 bit flow id. LOW and MID are both 32-bit
+ * accesses. HI is 7-bits with 6-bit flow id and 1 bit control
+ * word. RX_DMA_EN must be 0 for RX CTRL FIFO PIO access. DATA_HI
+ * should be last write access of the write sequence.
+ * DEFAULT: undefined
+ */
+#define REG_RX_CTRL_FIFO_ADDR 0x4094 /* RX Control FIFO and
+ Batching FIFO addr */
+#define REG_RX_CTRL_FIFO_DATA_LOW 0x4098 /* RX Control FIFO data
+ low */
+#define REG_RX_CTRL_FIFO_DATA_MID 0x409C /* RX Control FIFO data
+ mid */
+#define REG_RX_CTRL_FIFO_DATA_HI 0x4100 /* RX Control FIFO data
+ hi and flow id */
+#define RX_CTRL_FIFO_DATA_HI_CTRL 0x0001 /* upper bit of ctrl word */
+#define RX_CTRL_FIFO_DATA_HI_FLOW_MASK 0x007E /* flow id */
+
+/* diagnostic access to RX IPP FIFO. same semantics as RX_FIFO.
+ * DEFAULT: undefined
+ */
+#define REG_RX_IPP_FIFO_ADDR 0x4104 /* RX IPP FIFO address */
+#define REG_RX_IPP_FIFO_TAG 0x4108 /* RX IPP FIFO tag */
+#define REG_RX_IPP_FIFO_DATA_LOW 0x410C /* RX IPP FIFO data low */
+#define REG_RX_IPP_FIFO_DATA_HI_T0 0x4110 /* RX IPP FIFO data high
+ T0 */
+#define REG_RX_IPP_FIFO_DATA_HI_T1 0x4114 /* RX IPP FIFO data high
+ T1 */
+
+/* 64-bit pointer to receive data buffer in host memory used for headers and
+ * small packets. MSB in high register. loaded by DMA state machine and
+ * increments as DMA writes receive data. only 50 LSB are incremented. top
+ * 13 bits taken from RX descriptor.
+ * DEFAULT: undefined
+ */
+#define REG_RX_HEADER_PAGE_PTR_LOW 0x4118 /* (ro) RX header page ptr
+ low */
+#define REG_RX_HEADER_PAGE_PTR_HI 0x411C /* (ro) RX header page ptr
+ high */
+#define REG_RX_MTU_PAGE_PTR_LOW 0x4120 /* (ro) RX MTU page pointer
+ low */
+#define REG_RX_MTU_PAGE_PTR_HI 0x4124 /* (ro) RX MTU page pointer
+ high */
+
+/* PIO diagnostic access to RX reassembly DMA Table RAM. 6-bit register holds
+ * one of 64 79-bit locations in the RX Reassembly DMA table and the addr of
+ * one of the 64 byte locations in the Batching table. LOW holds 32 LSB.
+ * MID holds the next 32 LSB. HIGH holds the 15 MSB. RX_DMA_EN must be set
+ * to 0 for PIO access. DATA_HIGH should be last write of write sequence.
+ * layout:
+ * reassmbl ptr [78:15] | reassmbl index [14:1] | reassmbl entry valid [0]
+ * DEFAULT: undefined
+ */
+#define REG_RX_TABLE_ADDR 0x4128 /* RX reassembly DMA table
+ address */
+#define RX_TABLE_ADDR_MASK 0x0000003F /* address mask */
+
+#define REG_RX_TABLE_DATA_LOW 0x412C /* RX reassembly DMA table
+ data low */
+#define REG_RX_TABLE_DATA_MID 0x4130 /* RX reassembly DMA table
+ data mid */
+#define REG_RX_TABLE_DATA_HI 0x4134 /* RX reassembly DMA table
+ data high */
+
+/* cassini+ only */
+/* 8KB aligned 64-bit pointer to base of RX rings. lower 13 bits hardwired to
+ * 0. same semantics as primary desc/complete rings.
+ */
+#define REG_PLUS_RX_DB1_LOW 0x4200 /* RX descriptor ring
+ 2 base low */
+#define REG_PLUS_RX_DB1_HI 0x4204 /* RX descriptor ring
+ 2 base high */
+#define REG_PLUS_RX_CB1_LOW 0x4208 /* RX completion ring
+ 2 base low. 4 total */
+#define REG_PLUS_RX_CB1_HI 0x420C /* RX completion ring
+ 2 base high. 4 total */
+#define REG_PLUS_RX_CBN_LOW(x) (REG_PLUS_RX_CB1_LOW + 8*((x) - 1))
+#define REG_PLUS_RX_CBN_HI(x) (REG_PLUS_RX_CB1_HI + 8*((x) - 1))
+#define REG_PLUS_RX_KICK1 0x4220 /* RX Kick 2 register */
+#define REG_PLUS_RX_COMP1 0x4224 /* (ro) RX completion 2
+ reg */
+#define REG_PLUS_RX_COMP1_HEAD 0x4228 /* (ro) RX completion 2
+ head reg. 4 total. */
+#define REG_PLUS_RX_COMP1_TAIL 0x422C /* RX completion 2
+ tail reg. 4 total. */
+#define REG_PLUS_RX_COMPN_HEAD(x) (REG_PLUS_RX_COMP1_HEAD + 8*((x) - 1))
+#define REG_PLUS_RX_COMPN_TAIL(x) (REG_PLUS_RX_COMP1_TAIL + 8*((x) - 1))
+#define REG_PLUS_RX_AE1_THRESH 0x4240 /* RX almost empty 2
+ thresholds */
+#define RX_AE1_THRESH_FREE_MASK RX_AE_THRESH_FREE_MASK
+#define RX_AE1_THRESH_FREE_SHIFT RX_AE_THRESH_FREE_SHIFT
+
+/** header parser registers **/
+
+/* RX parser configuration register.
+ * DEFAULT: 0x1651004
+ */
+#define REG_HP_CFG 0x4140 /* header parser
+ configuration reg */
+#define HP_CFG_PARSE_EN 0x00000001 /* enab header parsing */
+#define HP_CFG_NUM_CPU_MASK 0x000000FC /* # processors
+ 0 = 64. 0x3f = 63 */
+#define HP_CFG_NUM_CPU_SHIFT 2
+#define HP_CFG_SYN_INC_MASK 0x00000100 /* SYN bit won't increment
+ TCP seq # by one when
+ stored in FDBM */
+#define HP_CFG_TCP_THRESH_MASK 0x000FFE00 /* # bytes of TCP data
+ needed to be considered
+ for reassembly */
+#define HP_CFG_TCP_THRESH_SHIFT 9
+
+/* access to RX Instruction RAM. 5-bit register/counter holds addr
+ * of 39 bit entry to be read/written. 32 LSB in _DATA_LOW. 7 MSB in _DATA_HI.
+ * RX_DMA_EN must be 0 for RX instr PIO access. DATA_HI should be last access
+ * of sequence.
+ * DEFAULT: undefined
+ */
+#define REG_HP_INSTR_RAM_ADDR 0x4144 /* HP instruction RAM
+ address */
+#define HP_INSTR_RAM_ADDR_MASK 0x01F /* 5-bit mask */
+#define REG_HP_INSTR_RAM_DATA_LOW 0x4148 /* HP instruction RAM
+ data low */
+#define HP_INSTR_RAM_LOW_OUTMASK_MASK 0x0000FFFF
+#define HP_INSTR_RAM_LOW_OUTMASK_SHIFT 0
+#define HP_INSTR_RAM_LOW_OUTSHIFT_MASK 0x000F0000
+#define HP_INSTR_RAM_LOW_OUTSHIFT_SHIFT 16
+#define HP_INSTR_RAM_LOW_OUTEN_MASK 0x00300000
+#define HP_INSTR_RAM_LOW_OUTEN_SHIFT 20
+#define HP_INSTR_RAM_LOW_OUTARG_MASK 0xFFC00000
+#define HP_INSTR_RAM_LOW_OUTARG_SHIFT 22
+#define REG_HP_INSTR_RAM_DATA_MID 0x414C /* HP instruction RAM
+ data mid */
+#define HP_INSTR_RAM_MID_OUTARG_MASK 0x00000003
+#define HP_INSTR_RAM_MID_OUTARG_SHIFT 0
+#define HP_INSTR_RAM_MID_OUTOP_MASK 0x0000003C
+#define HP_INSTR_RAM_MID_OUTOP_SHIFT 2
+#define HP_INSTR_RAM_MID_FNEXT_MASK 0x000007C0
+#define HP_INSTR_RAM_MID_FNEXT_SHIFT 6
+#define HP_INSTR_RAM_MID_FOFF_MASK 0x0003F800
+#define HP_INSTR_RAM_MID_FOFF_SHIFT 11
+#define HP_INSTR_RAM_MID_SNEXT_MASK 0x007C0000
+#define HP_INSTR_RAM_MID_SNEXT_SHIFT 18
+#define HP_INSTR_RAM_MID_SOFF_MASK 0x3F800000
+#define HP_INSTR_RAM_MID_SOFF_SHIFT 23
+#define HP_INSTR_RAM_MID_OP_MASK 0xC0000000
+#define HP_INSTR_RAM_MID_OP_SHIFT 30
+#define REG_HP_INSTR_RAM_DATA_HI 0x4150 /* HP instruction RAM
+ data high */
+#define HP_INSTR_RAM_HI_VAL_MASK 0x0000FFFF
+#define HP_INSTR_RAM_HI_VAL_SHIFT 0
+#define HP_INSTR_RAM_HI_MASK_MASK 0xFFFF0000
+#define HP_INSTR_RAM_HI_MASK_SHIFT 16
+
+/* PIO access into RX Header parser data RAM and flow database.
+ * 11-bit register. Data fills the LSB portion of bus if less than 32 bits.
+ * DATA_RAM: write RAM_FDB_DATA with index to access DATA_RAM.
+ * RAM bytes = 4*(x - 1) + [3:0]. e.g., 0 -> [3:0], 31 -> [123:120]
+ * FLOWDB: write DATA_RAM_FDB register and then read/write FDB1-12 to access
+ * flow database.
+ * RX_DMA_EN must be 0 for RX parser RAM PIO access. RX Parser RAM data reg
+ * should be the last write access of the write sequence.
+ * DEFAULT: undefined
+ */
+#define REG_HP_DATA_RAM_FDB_ADDR 0x4154 /* HP data and FDB
+ RAM address */
+#define HP_DATA_RAM_FDB_DATA_MASK 0x001F /* select 1 of 86 byte
+ locations in header
+ parser data ram to
+ read/write */
+#define HP_DATA_RAM_FDB_FDB_MASK 0x3F00 /* 1 of 64 353-bit locations
+ in the flow database */
+#define REG_HP_DATA_RAM_DATA 0x4158 /* HP data RAM data */
+
+/* HP flow database registers: 1 - 12, 0x415C - 0x4188, 4 8-bit bytes
+ * FLOW_DB(1) = IP_SA[127:96], FLOW_DB(2) = IP_SA[95:64]
+ * FLOW_DB(3) = IP_SA[63:32], FLOW_DB(4) = IP_SA[31:0]
+ * FLOW_DB(5) = IP_DA[127:96], FLOW_DB(6) = IP_DA[95:64]
+ * FLOW_DB(7) = IP_DA[63:32], FLOW_DB(8) = IP_DA[31:0]
+ * FLOW_DB(9) = {TCP_SP[15:0],TCP_DP[15:0]}
+ * FLOW_DB(10) = bit 0 has value for flow valid
+ * FLOW_DB(11) = TCP_SEQ[63:32], FLOW_DB(12) = TCP_SEQ[31:0]
+ */
+#define REG_HP_FLOW_DB0 0x415C /* HP flow database 1 reg */
+#define REG_HP_FLOW_DBN(x) (REG_HP_FLOW_DB0 + (x)*4)
+
+/* diagnostics for RX Header Parser block.
+ * ASUN: the header parser state machine register is used for diagnostics
+ * purposes. however, the spec doesn't have any details on it.
+ */
+#define REG_HP_STATE_MACHINE 0x418C /* (ro) HP state machine */
+#define REG_HP_STATUS0 0x4190 /* (ro) HP status 1 */
+#define HP_STATUS0_SAP_MASK 0xFFFF0000 /* SAP */
+#define HP_STATUS0_L3_OFF_MASK 0x0000FE00 /* L3 offset */
+#define HP_STATUS0_LB_CPUNUM_MASK 0x000001F8 /* load balancing CPU
+ number */
+#define HP_STATUS0_HRP_OPCODE_MASK 0x00000007 /* HRP opcode */
+
+#define REG_HP_STATUS1 0x4194 /* (ro) HP status 2 */
+#define HP_STATUS1_ACCUR2_MASK 0xE0000000 /* accu R2[6:4] */
+#define HP_STATUS1_FLOWID_MASK 0x1F800000 /* flow id */
+#define HP_STATUS1_TCP_OFF_MASK 0x007F0000 /* tcp payload offset */
+#define HP_STATUS1_TCP_SIZE_MASK 0x0000FFFF /* tcp payload size */
+
+#define REG_HP_STATUS2 0x4198 /* (ro) HP status 3 */
+#define HP_STATUS2_ACCUR2_MASK 0xF0000000 /* accu R2[3:0] */
+#define HP_STATUS2_CSUM_OFF_MASK 0x07F00000 /* checksum start
+ start offset */
+#define HP_STATUS2_ACCUR1_MASK 0x000FE000 /* accu R1 */
+#define HP_STATUS2_FORCE_DROP 0x00001000 /* force drop */
+#define HP_STATUS2_BWO_REASSM 0x00000800 /* batching w/o
+ reassembly */
+#define HP_STATUS2_JH_SPLIT_EN 0x00000400 /* jumbo header split
+ enable */
+#define HP_STATUS2_FORCE_TCP_NOCHECK 0x00000200 /* force tcp no payload
+ check */
+#define HP_STATUS2_DATA_MASK_ZERO 0x00000100 /* mask of data length
+ equal to zero */
+#define HP_STATUS2_FORCE_TCP_CHECK 0x00000080 /* force tcp payload
+ chk */
+#define HP_STATUS2_MASK_TCP_THRESH 0x00000040 /* mask of payload
+ threshold */
+#define HP_STATUS2_NO_ASSIST 0x00000020 /* no assist */
+#define HP_STATUS2_CTRL_PACKET_FLAG 0x00000010 /* control packet flag */
+#define HP_STATUS2_TCP_FLAG_CHECK 0x00000008 /* tcp flag check */
+#define HP_STATUS2_SYN_FLAG 0x00000004 /* syn flag */
+#define HP_STATUS2_TCP_CHECK 0x00000002 /* tcp payload chk */
+#define HP_STATUS2_TCP_NOCHECK 0x00000001 /* tcp no payload chk */
+
+/* BIST for header parser(HP) and flow database memories (FDBM). set _START
+ * to start BIST. controller clears _START on completion. _START can also
+ * be cleared to force termination of BIST. a bit set indicates that that
+ * memory passed its BIST.
+ */
+#define REG_HP_RAM_BIST 0x419C /* HP RAM BIST reg */
+#define HP_RAM_BIST_HP_DATA_PASS 0x80000000 /* HP data ram */
+#define HP_RAM_BIST_HP_INSTR0_PASS 0x40000000 /* HP instr ram 0 */
+#define HP_RAM_BIST_HP_INSTR1_PASS 0x20000000 /* HP instr ram 1 */
+#define HP_RAM_BIST_HP_INSTR2_PASS 0x10000000 /* HP instr ram 2 */
+#define HP_RAM_BIST_FDBM_AGE0_PASS 0x08000000 /* FDBM aging RAM0 */
+#define HP_RAM_BIST_FDBM_AGE1_PASS 0x04000000 /* FDBM aging RAM1 */
+#define HP_RAM_BIST_FDBM_FLOWID00_PASS 0x02000000 /* FDBM flowid RAM0
+ bank 0 */
+#define HP_RAM_BIST_FDBM_FLOWID10_PASS 0x01000000 /* FDBM flowid RAM1
+ bank 0 */
+#define HP_RAM_BIST_FDBM_FLOWID20_PASS 0x00800000 /* FDBM flowid RAM2
+ bank 0 */
+#define HP_RAM_BIST_FDBM_FLOWID30_PASS 0x00400000 /* FDBM flowid RAM3
+ bank 0 */
+#define HP_RAM_BIST_FDBM_FLOWID01_PASS 0x00200000 /* FDBM flowid RAM0
+ bank 1 */
+#define HP_RAM_BIST_FDBM_FLOWID11_PASS 0x00100000 /* FDBM flowid RAM1
+ bank 2 */
+#define HP_RAM_BIST_FDBM_FLOWID21_PASS 0x00080000 /* FDBM flowid RAM2
+ bank 1 */
+#define HP_RAM_BIST_FDBM_FLOWID31_PASS 0x00040000 /* FDBM flowid RAM3
+ bank 1 */
+#define HP_RAM_BIST_FDBM_TCPSEQ_PASS 0x00020000 /* FDBM tcp sequence
+ RAM */
+#define HP_RAM_BIST_SUMMARY 0x00000002 /* all BIST tests */
+#define HP_RAM_BIST_START 0x00000001 /* start/stop BIST */
+
+
+/** MAC registers. **/
+/* reset bits are set using a PIO write and self-cleared after the command
+ * execution has completed.
+ */
+#define REG_MAC_TX_RESET 0x6000 /* TX MAC software reset
+ command (default: 0x0) */
+#define REG_MAC_RX_RESET 0x6004 /* RX MAC software reset
+ command (default: 0x0) */
+/* execute a pause flow control frame transmission
+ DEFAULT: 0x0XXXX */
+#define REG_MAC_SEND_PAUSE 0x6008 /* send pause command reg */
+#define MAC_SEND_PAUSE_TIME_MASK 0x0000FFFF /* value of pause time
+ to be sent on network
+ in units of slot
+ times */
+#define MAC_SEND_PAUSE_SEND 0x00010000 /* send pause flow ctrl
+ frame on network */
+
+/* bit set indicates that event occurred. auto-cleared when status register
+ * is read and have corresponding mask bits in mask register. events will
+ * trigger an interrupt if the corresponding mask bit is 0.
+ * status register default: 0x00000000
+ * mask register default = 0xFFFFFFFF on reset
+ */
+#define REG_MAC_TX_STATUS 0x6010 /* TX MAC status reg */
+#define MAC_TX_FRAME_XMIT 0x0001 /* successful frame
+ transmision */
+#define MAC_TX_UNDERRUN 0x0002 /* terminated frame
+ transmission due to
+ data starvation in the
+ xmit data path */
+#define MAC_TX_MAX_PACKET_ERR 0x0004 /* frame exceeds max allowed
+ length passed to TX MAC
+ by the DMA engine */
+#define MAC_TX_COLL_NORMAL 0x0008 /* rollover of the normal
+ collision counter */
+#define MAC_TX_COLL_EXCESS 0x0010 /* rollover of the excessive
+ collision counter */
+#define MAC_TX_COLL_LATE 0x0020 /* rollover of the late
+ collision counter */
+#define MAC_TX_COLL_FIRST 0x0040 /* rollover of the first
+ collision counter */
+#define MAC_TX_DEFER_TIMER 0x0080 /* rollover of the defer
+ timer */
+#define MAC_TX_PEAK_ATTEMPTS 0x0100 /* rollover of the peak
+ attempts counter */
+
+#define REG_MAC_RX_STATUS 0x6014 /* RX MAC status reg */
+#define MAC_RX_FRAME_RECV 0x0001 /* successful receipt of
+ a frame */
+#define MAC_RX_OVERFLOW 0x0002 /* dropped frame due to
+ RX FIFO overflow */
+#define MAC_RX_FRAME_COUNT 0x0004 /* rollover of receive frame
+ counter */
+#define MAC_RX_ALIGN_ERR 0x0008 /* rollover of alignment
+ error counter */
+#define MAC_RX_CRC_ERR 0x0010 /* rollover of crc error
+ counter */
+#define MAC_RX_LEN_ERR 0x0020 /* rollover of length
+ error counter */
+#define MAC_RX_VIOL_ERR 0x0040 /* rollover of code
+ violation error */
+
+/* DEFAULT: 0xXXXX0000 on reset */
+#define REG_MAC_CTRL_STATUS 0x6018 /* MAC control status reg */
+#define MAC_CTRL_PAUSE_RECEIVED 0x00000001 /* successful
+ reception of a
+ pause control
+ frame */
+#define MAC_CTRL_PAUSE_STATE 0x00000002 /* MAC has made a
+ transition from
+ "not paused" to
+ "paused" */
+#define MAC_CTRL_NOPAUSE_STATE 0x00000004 /* MAC has made a
+ transition from
+ "paused" to "not
+ paused" */
+#define MAC_CTRL_PAUSE_TIME_MASK 0xFFFF0000 /* value of pause time
+ operand that was
+ received in the last
+ pause flow control
+ frame */
+
+/* layout identical to TX MAC[8:0] */
+#define REG_MAC_TX_MASK 0x6020 /* TX MAC mask reg */
+/* layout identical to RX MAC[6:0] */
+#define REG_MAC_RX_MASK 0x6024 /* RX MAC mask reg */
+/* layout identical to CTRL MAC[2:0] */
+#define REG_MAC_CTRL_MASK 0x6028 /* MAC control mask reg */
+
+/* to ensure proper operation, CFG_EN must be cleared to 0 and a delay
+ * imposed before writes to other bits in the TX_MAC_CFG register or any of
+ * the MAC parameters is performed. delay dependent upon time required to
+ * transmit a maximum size frame (= MAC_FRAMESIZE_MAX*8/Mbps). e.g.,
+ * the delay for a 1518-byte frame on a 100Mbps network is 125us.
+ * alternatively, just poll TX_CFG_EN until it reads back as 0.
+ * NOTE: on half-duplex 1Gbps, TX_CFG_CARRIER_EXTEND and
+ * RX_CFG_CARRIER_EXTEND should be set and the SLOT_TIME register should
+ * be 0x200 (slot time of 512 bytes)
+ */
+#define REG_MAC_TX_CFG 0x6030 /* TX MAC config reg */
+#define MAC_TX_CFG_EN 0x0001 /* enable TX MAC. 0 will
+ force TXMAC state
+ machine to remain in
+ idle state or to
+ transition to idle state
+ on completion of an
+ ongoing packet. */
+#define MAC_TX_CFG_IGNORE_CARRIER 0x0002 /* disable CSMA/CD deferral
+ process. set to 1 when
+ full duplex and 0 when
+ half duplex */
+#define MAC_TX_CFG_IGNORE_COLL 0x0004 /* disable CSMA/CD backoff
+ algorithm. set to 1 when
+ full duplex and 0 when
+ half duplex */
+#define MAC_TX_CFG_IPG_EN 0x0008 /* enable extension of the
+ Rx-to-TX IPG. after
+ receiving a frame, TX
+ MAC will reset its
+ deferral process to
+ carrier sense for the
+ amount of time = IPG0 +
+ IPG1 and commit to
+ transmission for time
+ specified in IPG2. when
+ 0 or when xmitting frames
+ back-to-pack (Tx-to-Tx
+ IPG), TX MAC ignores
+ IPG0 and will only use
+ IPG1 for deferral time.
+ IPG2 still used. */
+#define MAC_TX_CFG_NEVER_GIVE_UP_EN 0x0010 /* TX MAC will not easily
+ give up on frame
+ xmission. if backoff
+ algorithm reaches the
+ ATTEMPT_LIMIT, it will
+ clear attempts counter
+ and continue trying to
+ send the frame as
+ specified by
+ GIVE_UP_LIM. when 0,
+ TX MAC will execute
+ standard CSMA/CD prot. */
+#define MAC_TX_CFG_NEVER_GIVE_UP_LIM 0x0020 /* when set, TX MAC will
+ continue to try to xmit
+ until successful. when
+ 0, TX MAC will continue
+ to try xmitting until
+ successful or backoff
+ algorithm reaches
+ ATTEMPT_LIMIT*16 */
+#define MAC_TX_CFG_NO_BACKOFF 0x0040 /* modify CSMA/CD to disable
+ backoff algorithm. TX
+ MAC will not back off
+ after a xmission attempt
+ that resulted in a
+ collision. */
+#define MAC_TX_CFG_SLOW_DOWN 0x0080 /* modify CSMA/CD so that
+ deferral process is reset
+ in response to carrier
+ sense during the entire
+ duration of IPG. TX MAC
+ will only commit to frame
+ xmission after frame
+ xmission has actually
+ begun. */
+#define MAC_TX_CFG_NO_FCS 0x0100 /* TX MAC will not generate
+ CRC for all xmitted
+ packets. when clear, CRC
+ generation is dependent
+ upon NO_CRC bit in the
+ xmit control word from
+ TX DMA */
+#define MAC_TX_CFG_CARRIER_EXTEND 0x0200 /* enables xmit part of the
+ carrier extension
+ feature. this allows for
+ longer collision domains
+ by extending the carrier
+ and collision window
+ from the end of FCS until
+ the end of the slot time
+ if necessary. Required
+ for half-duplex at 1Gbps,
+ clear otherwise. */
+
+/* when CRC is not stripped, reassembly packets will not contain the CRC.
+ * these will be stripped by HRP because it reassembles layer 4 data, and the
+ * CRC is layer 2. however, non-reassembly packets will still contain the CRC
+ * when passed to the host. to ensure proper operation, need to wait 3.2ms
+ * after clearing RX_CFG_EN before writing to any other RX MAC registers
+ * or other MAC parameters. alternatively, poll RX_CFG_EN until it clears
+ * to 0. similary, HASH_FILTER_EN and ADDR_FILTER_EN have the same
+ * restrictions as CFG_EN.
+ */
+#define REG_MAC_RX_CFG 0x6034 /* RX MAC config reg */
+#define MAC_RX_CFG_EN 0x0001 /* enable RX MAC */
+#define MAC_RX_CFG_STRIP_PAD 0x0002 /* always program to 0.
+ feature not supported */
+#define MAC_RX_CFG_STRIP_FCS 0x0004 /* RX MAC will strip the
+ last 4 bytes of a
+ received frame. */
+#define MAC_RX_CFG_PROMISC_EN 0x0008 /* promiscuous mode */
+#define MAC_RX_CFG_PROMISC_GROUP_EN 0x0010 /* accept all valid
+ multicast frames (group
+ bit in DA field set) */
+#define MAC_RX_CFG_HASH_FILTER_EN 0x0020 /* use hash table to filter
+ multicast addresses */
+#define MAC_RX_CFG_ADDR_FILTER_EN 0x0040 /* cause RX MAC to use
+ address filtering regs
+ to filter both unicast
+ and multicast
+ addresses */
+#define MAC_RX_CFG_DISABLE_DISCARD 0x0080 /* pass errored frames to
+ RX DMA by setting BAD
+ bit but not Abort bit
+ in the status. CRC,
+ framing, and length errs
+ will not increment
+ error counters. frames
+ which don't match dest
+ addr will be passed up
+ w/ BAD bit set. */
+#define MAC_RX_CFG_CARRIER_EXTEND 0x0100 /* enable reception of
+ packet bursts generated
+ by carrier extension
+ with packet bursting
+ senders. only applies
+ to half-duplex 1Gbps */
+
+/* DEFAULT: 0x0 */
+#define REG_MAC_CTRL_CFG 0x6038 /* MAC control config reg */
+#define MAC_CTRL_CFG_SEND_PAUSE_EN 0x0001 /* respond to requests for
+ sending pause flow ctrl
+ frames */
+#define MAC_CTRL_CFG_RECV_PAUSE_EN 0x0002 /* respond to received
+ pause flow ctrl frames */
+#define MAC_CTRL_CFG_PASS_CTRL 0x0004 /* pass valid MAC ctrl
+ packets to RX DMA */
+
+/* to ensure proper operation, a global initialization sequence should be
+ * performed when a loopback config is entered or exited. if programmed after
+ * a hw or global sw reset, RX/TX MAC software reset and initialization
+ * should be done to ensure stable clocking.
+ * DEFAULT: 0x0
+ */
+#define REG_MAC_XIF_CFG 0x603C /* XIF config reg */
+#define MAC_XIF_TX_MII_OUTPUT_EN 0x0001 /* enable output drivers
+ on MII xmit bus */
+#define MAC_XIF_MII_INT_LOOPBACK 0x0002 /* loopback GMII xmit data
+ path to GMII recv data
+ path. phy mode register
+ clock selection must be
+ set to GMII mode and
+ GMII_MODE should be set
+ to 1. in loopback mode,
+ REFCLK will drive the
+ entire mac core. 0 for
+ normal operation. */
+#define MAC_XIF_DISABLE_ECHO 0x0004 /* disables receive data
+ path during packet
+ xmission. clear to 0
+ in any full duplex mode,
+ in any loopback mode,
+ or in half-duplex SERDES
+ or SLINK modes. set when
+ in half-duplex when
+ using external phy. */
+#define MAC_XIF_GMII_MODE 0x0008 /* MAC operates with GMII
+ clocks and datapath */
+#define MAC_XIF_MII_BUFFER_OUTPUT_EN 0x0010 /* MII_BUF_EN pin. enable
+ external tristate buffer
+ on the MII receive
+ bus. */
+#define MAC_XIF_LINK_LED 0x0020 /* LINKLED# active (low) */
+#define MAC_XIF_FDPLX_LED 0x0040 /* FDPLXLED# active (low) */
+
+#define REG_MAC_IPG0 0x6040 /* inter-packet gap0 reg.
+ recommended: 0x00 */
+#define REG_MAC_IPG1 0x6044 /* inter-packet gap1 reg
+ recommended: 0x08 */
+#define REG_MAC_IPG2 0x6048 /* inter-packet gap2 reg
+ recommended: 0x04 */
+#define REG_MAC_SLOT_TIME 0x604C /* slot time reg
+ recommended: 0x40 */
+#define REG_MAC_FRAMESIZE_MIN 0x6050 /* min frame size reg
+ recommended: 0x40 */
+
+/* FRAMESIZE_MAX holds both the max frame size as well as the max burst size.
+ * recommended value: 0x2000.05EE
+ */
+#define REG_MAC_FRAMESIZE_MAX 0x6054 /* max frame size reg */
+#define MAC_FRAMESIZE_MAX_BURST_MASK 0x3FFF0000 /* max burst size */
+#define MAC_FRAMESIZE_MAX_BURST_SHIFT 16
+#define MAC_FRAMESIZE_MAX_FRAME_MASK 0x00007FFF /* max frame size */
+#define MAC_FRAMESIZE_MAX_FRAME_SHIFT 0
+#define REG_MAC_PA_SIZE 0x6058 /* PA size reg. number of
+ preamble bytes that the
+ TX MAC will xmit at the
+ beginning of each frame
+ value should be 2 or
+ greater. recommended
+ value: 0x07 */
+#define REG_MAC_JAM_SIZE 0x605C /* jam size reg. duration
+ of jam in units of media
+ byte time. recommended
+ value: 0x04 */
+#define REG_MAC_ATTEMPT_LIMIT 0x6060 /* attempt limit reg. #
+ of attempts TX MAC will
+ make to xmit a frame
+ before it resets its
+ attempts counter. after
+ the limit has been
+ reached, TX MAC may or
+ may not drop the frame
+ dependent upon value
+ in TX_MAC_CFG.
+ recommended
+ value: 0x10 */
+#define REG_MAC_CTRL_TYPE 0x6064 /* MAC control type reg.
+ type field of a MAC
+ ctrl frame. recommended
+ value: 0x8808 */
+
+/* mac address registers: 0 - 44, 0x6080 - 0x6130, 4 8-bit bytes.
+ * register contains comparison
+ * 0 16 MSB of primary MAC addr [47:32] of DA field
+ * 1 16 middle bits "" [31:16] of DA field
+ * 2 16 LSB "" [15:0] of DA field
+ * 3*x 16MSB of alt MAC addr 1-15 [47:32] of DA field
+ * 4*x 16 middle bits "" [31:16]
+ * 5*x 16 LSB "" [15:0]
+ * 42 16 MSB of MAC CTRL addr [47:32] of DA.
+ * 43 16 middle bits "" [31:16]
+ * 44 16 LSB "" [15:0]
+ * MAC CTRL addr must be the reserved multicast addr for MAC CTRL frames.
+ * if there is a match, MAC will set the bit for alternative address
+ * filter pass [15]
+
+ * here is the map of registers given MAC address notation: a:b:c:d:e:f
+ * ab cd ef
+ * primary addr reg 2 reg 1 reg 0
+ * alt addr 1 reg 5 reg 4 reg 3
+ * alt addr x reg 5*x reg 4*x reg 3*x
+ * ctrl addr reg 44 reg 43 reg 42
+ */
+#define REG_MAC_ADDR0 0x6080 /* MAC address 0 reg */
+#define REG_MAC_ADDRN(x) (REG_MAC_ADDR0 + (x)*4)
+#define REG_MAC_ADDR_FILTER0 0x614C /* address filter 0 reg
+ [47:32] */
+#define REG_MAC_ADDR_FILTER1 0x6150 /* address filter 1 reg
+ [31:16] */
+#define REG_MAC_ADDR_FILTER2 0x6154 /* address filter 2 reg
+ [15:0] */
+#define REG_MAC_ADDR_FILTER2_1_MASK 0x6158 /* address filter 2 and 1
+ mask reg. 8-bit reg
+ contains nibble mask for
+ reg 2 and 1. */
+#define REG_MAC_ADDR_FILTER0_MASK 0x615C /* address filter 0 mask
+ reg */
+
+/* hash table registers: 0 - 15, 0x6160 - 0x619C, 4 8-bit bytes
+ * 16-bit registers contain bits of the hash table.
+ * reg x -> [16*(15 - x) + 15 : 16*(15 - x)].
+ * e.g., 15 -> [15:0], 0 -> [255:240]
+ */
+#define REG_MAC_HASH_TABLE0 0x6160 /* hash table 0 reg */
+#define REG_MAC_HASH_TABLEN(x) (REG_MAC_HASH_TABLE0 + (x)*4)
+
+/* statistics registers. these registers generate an interrupt on
+ * overflow. recommended initialization: 0x0000. most are 16-bits except
+ * for PEAK_ATTEMPTS register which is 8 bits.
+ */
+#define REG_MAC_COLL_NORMAL 0x61A0 /* normal collision
+ counter. */
+#define REG_MAC_COLL_FIRST 0x61A4 /* first attempt
+ successful collision
+ counter */
+#define REG_MAC_COLL_EXCESS 0x61A8 /* excessive collision
+ counter */
+#define REG_MAC_COLL_LATE 0x61AC /* late collision counter */
+#define REG_MAC_TIMER_DEFER 0x61B0 /* defer timer. time base
+ is the media byte
+ clock/256 */
+#define REG_MAC_ATTEMPTS_PEAK 0x61B4 /* peak attempts reg */
+#define REG_MAC_RECV_FRAME 0x61B8 /* receive frame counter */
+#define REG_MAC_LEN_ERR 0x61BC /* length error counter */
+#define REG_MAC_ALIGN_ERR 0x61C0 /* alignment error counter */
+#define REG_MAC_FCS_ERR 0x61C4 /* FCS error counter */
+#define REG_MAC_RX_CODE_ERR 0x61C8 /* RX code violation
+ error counter */
+
+/* misc registers */
+#define REG_MAC_RANDOM_SEED 0x61CC /* random number seed reg.
+ 10-bit register used as a
+ seed for the random number
+ generator for the CSMA/CD
+ backoff algorithm. only
+ programmed after power-on
+ reset and should be a
+ random value which has a
+ high likelihood of being
+ unique for each MAC
+ attached to a network
+ segment (e.g., 10 LSB of
+ MAC address) */
+
+/* ASUN: there's a PAUSE_TIMER (ro) described, but it's not in the address
+ * map
+ */
+
+/* 27-bit register has the current state for key state machines in the MAC */
+#define REG_MAC_STATE_MACHINE 0x61D0 /* (ro) state machine reg */
+#define MAC_SM_RLM_MASK 0x07800000
+#define MAC_SM_RLM_SHIFT 23
+#define MAC_SM_RX_FC_MASK 0x00700000
+#define MAC_SM_RX_FC_SHIFT 20
+#define MAC_SM_TLM_MASK 0x000F0000
+#define MAC_SM_TLM_SHIFT 16
+#define MAC_SM_ENCAP_SM_MASK 0x0000F000
+#define MAC_SM_ENCAP_SM_SHIFT 12
+#define MAC_SM_TX_REQ_MASK 0x00000C00
+#define MAC_SM_TX_REQ_SHIFT 10
+#define MAC_SM_TX_FC_MASK 0x000003C0
+#define MAC_SM_TX_FC_SHIFT 6
+#define MAC_SM_FIFO_WRITE_SEL_MASK 0x00000038
+#define MAC_SM_FIFO_WRITE_SEL_SHIFT 3
+#define MAC_SM_TX_FIFO_EMPTY_MASK 0x00000007
+#define MAC_SM_TX_FIFO_EMPTY_SHIFT 0
+
+/** MIF registers. the MIF can be programmed in either bit-bang or
+ * frame mode.
+ **/
+#define REG_MIF_BIT_BANG_CLOCK 0x6200 /* MIF bit-bang clock.
+ 1 -> 0 will generate a
+ rising edge. 0 -> 1 will
+ generate a falling edge. */
+#define REG_MIF_BIT_BANG_DATA 0x6204 /* MIF bit-bang data. 1-bit
+ register generates data */
+#define REG_MIF_BIT_BANG_OUTPUT_EN 0x6208 /* MIF bit-bang output
+ enable. enable when
+ xmitting data from MIF to
+ transceiver. */
+
+/* 32-bit register serves as an instruction register when the MIF is
+ * programmed in frame mode. load this register w/ a valid instruction
+ * (as per IEEE 802.3u MII spec). poll this register to check for instruction
+ * execution completion. during a read operation, this register will also
+ * contain the 16-bit data returned by the tranceiver. unless specified
+ * otherwise, fields are considered "don't care" when polling for
+ * completion.
+ */
+#define REG_MIF_FRAME 0x620C /* MIF frame/output reg */
+#define MIF_FRAME_START_MASK 0xC0000000 /* start of frame.
+ load w/ 01 when
+ issuing an instr */
+#define MIF_FRAME_ST 0x40000000 /* STart of frame */
+#define MIF_FRAME_OPCODE_MASK 0x30000000 /* opcode. 01 for a
+ write. 10 for a
+ read */
+#define MIF_FRAME_OP_READ 0x20000000 /* read OPcode */
+#define MIF_FRAME_OP_WRITE 0x10000000 /* write OPcode */
+#define MIF_FRAME_PHY_ADDR_MASK 0x0F800000 /* phy address. when
+ issuing an instr,
+ this field should be
+ loaded w/ the XCVR
+ addr */
+#define MIF_FRAME_PHY_ADDR_SHIFT 23
+#define MIF_FRAME_REG_ADDR_MASK 0x007C0000 /* register address.
+ when issuing an instr,
+ addr of register
+ to be read/written */
+#define MIF_FRAME_REG_ADDR_SHIFT 18
+#define MIF_FRAME_TURN_AROUND_MSB 0x00020000 /* turn around, MSB.
+ when issuing an instr,
+ set this bit to 1 */
+#define MIF_FRAME_TURN_AROUND_LSB 0x00010000 /* turn around, LSB.
+ when issuing an instr,
+ set this bit to 0.
+ when polling for
+ completion, 1 means
+ that instr execution
+ has been completed */
+#define MIF_FRAME_DATA_MASK 0x0000FFFF /* instruction payload
+ load with 16-bit data
+ to be written in
+ transceiver reg for a
+ write. doesn't matter
+ in a read. when
+ polling for
+ completion, field is
+ "don't care" for write
+ and 16-bit data
+ returned by the
+ transceiver for a
+ read (if valid bit
+ is set) */
+#define REG_MIF_CFG 0x6210 /* MIF config reg */
+#define MIF_CFG_PHY_SELECT 0x0001 /* 1 -> select MDIO_1
+ 0 -> select MDIO_0 */
+#define MIF_CFG_POLL_EN 0x0002 /* enable polling
+ mechanism. if set,
+ BB_MODE should be 0 */
+#define MIF_CFG_BB_MODE 0x0004 /* 1 -> bit-bang mode
+ 0 -> frame mode */
+#define MIF_CFG_POLL_REG_MASK 0x00F8 /* register address to be
+ used by polling mode.
+ only meaningful if POLL_EN
+ is set to 1 */
+#define MIF_CFG_POLL_REG_SHIFT 3
+#define MIF_CFG_MDIO_0 0x0100 /* (ro) dual purpose.
+ when MDIO_0 is idle,
+ 1 -> tranceiver is
+ connected to MDIO_0.
+ when MIF is communicating
+ w/ MDIO_0 in bit-bang
+ mode, this bit indicates
+ the incoming bit stream
+ during a read op */
+#define MIF_CFG_MDIO_1 0x0200 /* (ro) dual purpose.
+ when MDIO_1 is idle,
+ 1 -> transceiver is
+ connected to MDIO_1.
+ when MIF is communicating
+ w/ MDIO_1 in bit-bang
+ mode, this bit indicates
+ the incoming bit stream
+ during a read op */
+#define MIF_CFG_POLL_PHY_MASK 0x7C00 /* tranceiver address to
+ be polled */
+#define MIF_CFG_POLL_PHY_SHIFT 10
+
+/* 16-bit register used to determine which bits in the POLL_STATUS portion of
+ * the MIF_STATUS register will cause an interrupt. if a mask bit is 0,
+ * corresponding bit of the POLL_STATUS will generate a MIF interrupt when
+ * set. DEFAULT: 0xFFFF
+ */
+#define REG_MIF_MASK 0x6214 /* MIF mask reg */
+
+/* 32-bit register used when in poll mode. auto-cleared after being read */
+#define REG_MIF_STATUS 0x6218 /* MIF status reg */
+#define MIF_STATUS_POLL_DATA_MASK 0xFFFF0000 /* poll data contains
+ the "latest image"
+ update of the XCVR
+ reg being read */
+#define MIF_STATUS_POLL_DATA_SHIFT 16
+#define MIF_STATUS_POLL_STATUS_MASK 0x0000FFFF /* poll status indicates
+ which bits in the
+ POLL_DATA field have
+ changed since the
+ MIF_STATUS reg was
+ last read */
+#define MIF_STATUS_POLL_STATUS_SHIFT 0
+
+/* 7-bit register has current state for all state machines in the MIF */
+#define REG_MIF_STATE_MACHINE 0x621C /* MIF state machine reg */
+#define MIF_SM_CONTROL_MASK 0x07 /* control state machine
+ state */
+#define MIF_SM_EXECUTION_MASK 0x60 /* execution state machine
+ state */
+
+/** PCS/Serialink. the following registers are equivalent to the standard
+ * MII management registers except that they're directly mapped in
+ * Cassini's register space.
+ **/
+
+/* the auto-negotiation enable bit should be programmed the same at
+ * the link partner as in the local device to enable auto-negotiation to
+ * complete. when that bit is reprogrammed, auto-neg/manual config is
+ * restarted automatically.
+ * DEFAULT: 0x1040
+ */
+#define REG_PCS_MII_CTRL 0x9000 /* PCS MII control reg */
+#define PCS_MII_CTRL_1000_SEL 0x0040 /* reads 1. ignored on
+ writes */
+#define PCS_MII_CTRL_COLLISION_TEST 0x0080 /* COL signal at the PCS
+ to MAC interface is
+ activated regardless
+ of activity */
+#define PCS_MII_CTRL_DUPLEX 0x0100 /* forced 0x0. PCS
+ behaviour same for
+ half and full dplx */
+#define PCS_MII_RESTART_AUTONEG 0x0200 /* self clearing.
+ restart auto-
+ negotiation */
+#define PCS_MII_ISOLATE 0x0400 /* read as 0. ignored
+ on writes */
+#define PCS_MII_POWER_DOWN 0x0800 /* read as 0. ignored
+ on writes */
+#define PCS_MII_AUTONEG_EN 0x1000 /* default 1. PCS goes
+ through automatic
+ link config before it
+ can be used. when 0,
+ link can be used
+ w/out any link config
+ phase */
+#define PCS_MII_10_100_SEL 0x2000 /* read as 0. ignored on
+ writes */
+#define PCS_MII_RESET 0x8000 /* reset PCS. self-clears
+ when done */
+
+/* DEFAULT: 0x0108 */
+#define REG_PCS_MII_STATUS 0x9004 /* PCS MII status reg */
+#define PCS_MII_STATUS_EXTEND_CAP 0x0001 /* reads 0 */
+#define PCS_MII_STATUS_JABBER_DETECT 0x0002 /* reads 0 */
+#define PCS_MII_STATUS_LINK_STATUS 0x0004 /* 1 -> link up.
+ 0 -> link down. 0 is
+ latched so that 0 is
+ kept until read. read
+ 2x to determine if the
+ link has gone up again */
+#define PCS_MII_STATUS_AUTONEG_ABLE 0x0008 /* reads 1 (able to perform
+ auto-neg) */
+#define PCS_MII_STATUS_REMOTE_FAULT 0x0010 /* 1 -> remote fault detected
+ from received link code
+ word. only valid after
+ auto-neg completed */
+#define PCS_MII_STATUS_AUTONEG_COMP 0x0020 /* 1 -> auto-negotiation
+ completed
+ 0 -> auto-negotiation not
+ completed */
+#define PCS_MII_STATUS_EXTEND_STATUS 0x0100 /* reads as 1. used as an
+ indication that this is
+ a 1000 Base-X PHY. writes
+ to it are ignored */
+
+/* used during auto-negotiation.
+ * DEFAULT: 0x00E0
+ */
+#define REG_PCS_MII_ADVERT 0x9008 /* PCS MII advertisement
+ reg */
+#define PCS_MII_ADVERT_FD 0x0020 /* advertise full duplex
+ 1000 Base-X */
+#define PCS_MII_ADVERT_HD 0x0040 /* advertise half-duplex
+ 1000 Base-X */
+#define PCS_MII_ADVERT_SYM_PAUSE 0x0080 /* advertise PAUSE
+ symmetric capability */
+#define PCS_MII_ADVERT_ASYM_PAUSE 0x0100 /* advertises PAUSE
+ asymmetric capability */
+#define PCS_MII_ADVERT_RF_MASK 0x3000 /* remote fault. write bit13
+ to optionally indicate to
+ link partner that chip is
+ going off-line. bit12 will
+ get set when signal
+ detect == FAIL and will
+ remain set until
+ successful negotiation */
+#define PCS_MII_ADVERT_ACK 0x4000 /* (ro) */
+#define PCS_MII_ADVERT_NEXT_PAGE 0x8000 /* (ro) forced 0x0 */
+
+/* contents updated as a result of autonegotiation. layout and definitions
+ * identical to PCS_MII_ADVERT
+ */
+#define REG_PCS_MII_LPA 0x900C /* PCS MII link partner
+ ability reg */
+#define PCS_MII_LPA_FD PCS_MII_ADVERT_FD
+#define PCS_MII_LPA_HD PCS_MII_ADVERT_HD
+#define PCS_MII_LPA_SYM_PAUSE PCS_MII_ADVERT_SYM_PAUSE
+#define PCS_MII_LPA_ASYM_PAUSE PCS_MII_ADVERT_ASYM_PAUSE
+#define PCS_MII_LPA_RF_MASK PCS_MII_ADVERT_RF_MASK
+#define PCS_MII_LPA_ACK PCS_MII_ADVERT_ACK
+#define PCS_MII_LPA_NEXT_PAGE PCS_MII_ADVERT_NEXT_PAGE
+
+/* DEFAULT: 0x0 */
+#define REG_PCS_CFG 0x9010 /* PCS config reg */
+#define PCS_CFG_EN 0x01 /* enable PCS. must be
+ 0 when modifying
+ PCS_MII_ADVERT */
+#define PCS_CFG_SD_OVERRIDE 0x02 /* sets signal detect to
+ OK. bit is
+ non-resettable */
+#define PCS_CFG_SD_ACTIVE_LOW 0x04 /* changes interpretation
+ of optical signal to make
+ signal detect okay when
+ signal is low */
+#define PCS_CFG_JITTER_STUDY_MASK 0x18 /* used to make jitter
+ measurements. a single
+ code group is xmitted
+ regularly.
+ 0x0 = normal operation
+ 0x1 = high freq test
+ pattern, D21.5
+ 0x2 = low freq test
+ pattern, K28.7
+ 0x3 = reserved */
+#define PCS_CFG_10MS_TIMER_OVERRIDE 0x20 /* shortens 10-20ms auto-
+ negotiation timer to
+ a few cycles for test
+ purposes */
+
+/* used for diagnostic purposes. bits 20-22 autoclear on read */
+#define REG_PCS_STATE_MACHINE 0x9014 /* (ro) PCS state machine
+ and diagnostic reg */
+#define PCS_SM_TX_STATE_MASK 0x0000000F /* 0 and 1 indicate
+ xmission of idle.
+ otherwise, xmission of
+ a packet */
+#define PCS_SM_RX_STATE_MASK 0x000000F0 /* 0 indicates reception
+ of idle. otherwise,
+ reception of packet */
+#define PCS_SM_WORD_SYNC_STATE_MASK 0x00000700 /* 0 indicates loss of
+ sync */
+#define PCS_SM_SEQ_DETECT_STATE_MASK 0x00001800 /* cycling through 0-3
+ indicates reception of
+ Config codes. cycling
+ through 0-1 indicates
+ reception of idles */
+#define PCS_SM_LINK_STATE_MASK 0x0001E000
+#define SM_LINK_STATE_UP 0x00016000 /* link state is up */
+
+#define PCS_SM_LOSS_LINK_C 0x00100000 /* loss of link due to
+ recept of Config
+ codes */
+#define PCS_SM_LOSS_LINK_SYNC 0x00200000 /* loss of link due to
+ loss of sync */
+#define PCS_SM_LOSS_SIGNAL_DETECT 0x00400000 /* signal detect goes
+ from OK to FAIL. bit29
+ will also be set if
+ this is set */
+#define PCS_SM_NO_LINK_BREAKLINK 0x01000000 /* link not up due to
+ receipt of breaklink
+ C codes from partner.
+ C codes w/ 0 content
+ received triggering
+ start/restart of
+ autonegotiation.
+ should be sent for
+ no longer than 20ms */
+#define PCS_SM_NO_LINK_SERDES 0x02000000 /* serdes being
+ initialized. see serdes
+ state reg */
+#define PCS_SM_NO_LINK_C 0x04000000 /* C codes not stable or
+ not received */
+#define PCS_SM_NO_LINK_SYNC 0x08000000 /* word sync not
+ achieved */
+#define PCS_SM_NO_LINK_WAIT_C 0x10000000 /* waiting for C codes
+ w/ ack bit set */
+#define PCS_SM_NO_LINK_NO_IDLE 0x20000000 /* link partner continues
+ to send C codes
+ instead of idle
+ symbols or pkt data */
+
+/* this register indicates interrupt changes in specific PCS MII status bits.
+ * PCS_INT may be masked at the ISR level. only a single bit is implemented
+ * for link status change.
+ */
+#define REG_PCS_INTR_STATUS 0x9018 /* PCS interrupt status */
+#define PCS_INTR_STATUS_LINK_CHANGE 0x04 /* link status has changed
+ since last read */
+
+/* control which network interface is used. no more than one bit should
+ * be set.
+ * DEFAULT: none
+ */
+#define REG_PCS_DATAPATH_MODE 0x9050 /* datapath mode reg */
+#define PCS_DATAPATH_MODE_MII 0x00 /* PCS is not used and
+ MII/GMII is selected.
+ selection between MII and
+ GMII is controlled by
+ XIF_CFG */
+#define PCS_DATAPATH_MODE_SERDES 0x02 /* PCS is used via the
+ 10-bit interface */
+
+/* input to serdes chip or serialink block */
+#define REG_PCS_SERDES_CTRL 0x9054 /* serdes control reg */
+#define PCS_SERDES_CTRL_LOOPBACK 0x01 /* enable loopback on
+ serdes interface */
+#define PCS_SERDES_CTRL_SYNCD_EN 0x02 /* enable sync carrier
+ detection. should be
+ 0x0 for normal
+ operation */
+#define PCS_SERDES_CTRL_LOCKREF 0x04 /* frequency-lock RBC[0:1]
+ to REFCLK when set.
+ when clear, receiver
+ clock locks to incoming
+ serial data */
+
+/* multiplex test outputs into the PROM address (PA_3 through PA_0) pins.
+ * should be 0x0 for normal operations.
+ * 0b000 normal operation, PROM address[3:0] selected
+ * 0b001 rxdma req, rxdma ack, rxdma ready, rxdma read
+ * 0b010 rxmac req, rx ack, rx tag, rx clk shared
+ * 0b011 txmac req, tx ack, tx tag, tx retry req
+ * 0b100 tx tp3, tx tp2, tx tp1, tx tp0
+ * 0b101 R period RX, R period TX, R period HP, R period BIM
+ * DEFAULT: 0x0
+ */
+#define REG_PCS_SHARED_OUTPUT_SEL 0x9058 /* shared output select */
+#define PCS_SOS_PROM_ADDR_MASK 0x0007
+
+/* used for diagnostics. this register indicates progress of the SERDES
+ * boot up.
+ * 0b00 undergoing reset
+ * 0b01 waiting 500us while lockrefn is asserted
+ * 0b10 waiting for comma detect
+ * 0b11 receive data is synchronized
+ * DEFAULT: 0x0
+ */
+#define REG_PCS_SERDES_STATE 0x905C /* (ro) serdes state */
+#define PCS_SERDES_STATE_MASK 0x03
+
+/* used for diagnostics. indicates number of packets transmitted or received.
+ * counters rollover w/out generating an interrupt.
+ * DEFAULT: 0x0
+ */
+#define REG_PCS_PACKET_COUNT 0x9060 /* (ro) PCS packet counter */
+#define PCS_PACKET_COUNT_TX 0x000007FF /* pkts xmitted by PCS */
+#define PCS_PACKET_COUNT_RX 0x07FF0000 /* pkts recvd by PCS
+ whether they
+ encountered an error
+ or not */
+
+/** LocalBus Devices. the following provides run-time access to the
+ * Cassini's PROM
+ ***/
+#define REG_EXPANSION_ROM_RUN_START 0x100000 /* expansion rom run time
+ access */
+#define REG_EXPANSION_ROM_RUN_END 0x17FFFF
+
+#define REG_SECOND_LOCALBUS_START 0x180000 /* secondary local bus
+ device */
+#define REG_SECOND_LOCALBUS_END 0x1FFFFF
+
+/* entropy device */
+#define REG_ENTROPY_START REG_SECOND_LOCALBUS_START
+#define REG_ENTROPY_DATA (REG_ENTROPY_START + 0x00)
+#define REG_ENTROPY_STATUS (REG_ENTROPY_START + 0x04)
+#define ENTROPY_STATUS_DRDY 0x01
+#define ENTROPY_STATUS_BUSY 0x02
+#define ENTROPY_STATUS_CIPHER 0x04
+#define ENTROPY_STATUS_BYPASS_MASK 0x18
+#define REG_ENTROPY_MODE (REG_ENTROPY_START + 0x05)
+#define ENTROPY_MODE_KEY_MASK 0x07
+#define ENTROPY_MODE_ENCRYPT 0x40
+#define REG_ENTROPY_RAND_REG (REG_ENTROPY_START + 0x06)
+#define REG_ENTROPY_RESET (REG_ENTROPY_START + 0x07)
+#define ENTROPY_RESET_DES_IO 0x01
+#define ENTROPY_RESET_STC_MODE 0x02
+#define ENTROPY_RESET_KEY_CACHE 0x04
+#define ENTROPY_RESET_IV 0x08
+#define REG_ENTROPY_IV (REG_ENTROPY_START + 0x08)
+#define REG_ENTROPY_KEY0 (REG_ENTROPY_START + 0x10)
+#define REG_ENTROPY_KEYN(x) (REG_ENTROPY_KEY0 + 4*(x))
+
+/* phys of interest w/ their special mii registers */
+#define PHY_LUCENT_B0 0x00437421
+#define LUCENT_MII_REG 0x1F
+
+#define PHY_NS_DP83065 0x20005c78
+#define DP83065_MII_MEM 0x16
+#define DP83065_MII_REGD 0x1D
+#define DP83065_MII_REGE 0x1E
+
+#define PHY_BROADCOM_5411 0x00206071
+#define PHY_BROADCOM_B0 0x00206050
+#define BROADCOM_MII_REG4 0x14
+#define BROADCOM_MII_REG5 0x15
+#define BROADCOM_MII_REG7 0x17
+#define BROADCOM_MII_REG8 0x18
+
+#define CAS_MII_ANNPTR 0x07
+#define CAS_MII_ANNPRR 0x08
+#define CAS_MII_1000_CTRL 0x09
+#define CAS_MII_1000_STATUS 0x0A
+#define CAS_MII_1000_EXTEND 0x0F
+
+#define CAS_BMSR_1000_EXTEND 0x0100 /* supports 1000Base-T extended status */
+/*
+ * if autoneg is disabled, here's the table:
+ * BMCR_SPEED100 = 100Mbps
+ * BMCR_SPEED1000 = 1000Mbps
+ * ~(BMCR_SPEED100 | BMCR_SPEED1000) = 10Mbps
+ */
+#define CAS_BMCR_SPEED1000 0x0040 /* Select 1000Mbps */
+
+#define CAS_ADVERTISE_1000HALF 0x0100
+#define CAS_ADVERTISE_1000FULL 0x0200
+#define CAS_ADVERTISE_PAUSE 0x0400
+#define CAS_ADVERTISE_ASYM_PAUSE 0x0800
+
+/* regular lpa register */
+#define CAS_LPA_PAUSE CAS_ADVERTISE_PAUSE
+#define CAS_LPA_ASYM_PAUSE CAS_ADVERTISE_ASYM_PAUSE
+
+/* 1000_STATUS register */
+#define CAS_LPA_1000HALF 0x0400
+#define CAS_LPA_1000FULL 0x0800
+
+#define CAS_EXTEND_1000XFULL 0x8000
+#define CAS_EXTEND_1000XHALF 0x4000
+#define CAS_EXTEND_1000TFULL 0x2000
+#define CAS_EXTEND_1000THALF 0x1000
+
+/* cassini header parser firmware */
+typedef struct cas_hp_inst {
+ const char *note;
+
+ u16 mask, val;
+
+ u8 op;
+ u8 soff, snext; /* if match succeeds, new offset and match */
+ u8 foff, fnext; /* if match fails, new offset and match */
+ /* output info */
+ u8 outop; /* output opcode */
+
+ u16 outarg; /* output argument */
+ u8 outenab; /* output enable: 0 = not, 1 = if match
+ 2 = if !match, 3 = always */
+ u8 outshift; /* barrel shift right, 4 bits */
+ u16 outmask;
+} cas_hp_inst_t;
+
+/* comparison */
+#define OP_EQ 0 /* packet == value */
+#define OP_LT 1 /* packet < value */
+#define OP_GT 2 /* packet > value */
+#define OP_NP 3 /* new packet */
+
+/* output opcodes */
+#define CL_REG 0
+#define LD_FID 1
+#define LD_SEQ 2
+#define LD_CTL 3
+#define LD_SAP 4
+#define LD_R1 5
+#define LD_L3 6
+#define LD_SUM 7
+#define LD_HDR 8
+#define IM_FID 9
+#define IM_SEQ 10
+#define IM_SAP 11
+#define IM_R1 12
+#define IM_CTL 13
+#define LD_LEN 14
+#define ST_FLG 15
+
+/* match setp #s for IP4TCP4 */
+#define S1_PCKT 0
+#define S1_VLAN 1
+#define S1_CFI 2
+#define S1_8023 3
+#define S1_LLC 4
+#define S1_LLCc 5
+#define S1_IPV4 6
+#define S1_IPV4c 7
+#define S1_IPV4F 8
+#define S1_TCP44 9
+#define S1_IPV6 10
+#define S1_IPV6L 11
+#define S1_IPV6c 12
+#define S1_TCP64 13
+#define S1_TCPSQ 14
+#define S1_TCPFG 15
+#define S1_TCPHL 16
+#define S1_TCPHc 17
+#define S1_CLNP 18
+#define S1_CLNP2 19
+#define S1_DROP 20
+#define S2_HTTP 21
+#define S1_ESP4 22
+#define S1_AH4 23
+#define S1_ESP6 24
+#define S1_AH6 25
+
+#define CAS_PROG_IP46TCP4_PREAMBLE \
+{ "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, S1_PCKT, \
+ CL_REG, 0x3ff, 1, 0x0, 0x0000}, \
+{ "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023, \
+ IM_CTL, 0x00a, 3, 0x0, 0xffff}, \
+{ "CFI?", 0x1000, 0x1000, OP_EQ, 0, S1_DROP, 1, S1_8023, \
+ CL_REG, 0x000, 0, 0x0, 0x0000}, \
+{ "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4, \
+ CL_REG, 0x000, 0, 0x0, 0x0000}, \
+{ "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP, \
+ CL_REG, 0x000, 0, 0x0, 0x0000}, \
+{ "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP, \
+ CL_REG, 0x000, 0, 0x0, 0x0000}, \
+{ "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6, \
+ LD_SAP, 0x100, 3, 0x0, 0xffff}, \
+{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP, \
+ LD_SUM, 0x00a, 1, 0x0, 0x0000}, \
+{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP, \
+ LD_LEN, 0x03e, 1, 0x0, 0xffff}, \
+{ "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_CLNP, \
+ LD_FID, 0x182, 1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ \
+{ "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP, \
+ LD_SUM, 0x015, 1, 0x0, 0x0000}, \
+{ "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP, \
+ IM_R1, 0x128, 1, 0x0, 0xffff}, \
+{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP, \
+ LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ \
+{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP, \
+ LD_LEN, 0x03f, 1, 0x0, 0xffff}
+
+#ifdef USE_HP_IP46TCP4
+static cas_hp_inst_t cas_prog_ip46tcp4tab[] = {
+ CAS_PROG_IP46TCP4_PREAMBLE,
+ { "TCP seq", /* DADDR should point to dest port */
+ 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */
+ { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0,
+ S1_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0,
+ S1_TCPHc, LD_R1, 0x205, 3, 0xB, 0xf000},
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0,
+ S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff},
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x000, 0, 0x0, 0x0000},
+ { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x080, 3, 0x0, 0xffff},
+ { NULL },
+};
+#ifdef HP_IP46TCP4_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_ip46tcp4tab
+#endif
+#endif
+
+/*
+ * Alternate table load which excludes HTTP server traffic from reassembly.
+ * It is substantially similar to the basic table, with one extra state
+ * and a few extra compares. */
+#ifdef USE_HP_IP46TCP4NOHTTP
+static cas_hp_inst_t cas_prog_ip46tcp4nohttptab[] = {
+ CAS_PROG_IP46TCP4_PREAMBLE,
+ { "TCP seq", /* DADDR should point to dest port */
+ 0xFFFF, 0x0080, OP_EQ, 0, S2_HTTP, 0, S1_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff} , /* Load TCP seq # */
+ { "TCP control flags", 0xFFFF, 0x8080, OP_EQ, 0, S2_HTTP, 0,
+ S1_TCPHL, ST_FLG, 0x145, 2, 0x0, 0x002f, }, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc,
+ LD_R1, 0x205, 3, 0xB, 0xf000},
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ LD_HDR, 0x0ff, 3, 0x0, 0xffff},
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ CL_REG, 0x002, 3, 0x0, 0x0000},
+ { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x080, 3, 0x0, 0xffff},
+ { "No HTTP", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x044, 3, 0x0, 0xffff},
+ { NULL },
+};
+#ifdef HP_IP46TCP4NOHTTP_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_ip46tcp4nohttptab
+#endif
+#endif
+
+/* match step #s for IP4FRAG */
+#define S3_IPV6c 11
+#define S3_TCP64 12
+#define S3_TCPSQ 13
+#define S3_TCPFG 14
+#define S3_TCPHL 15
+#define S3_TCPHc 16
+#define S3_FRAG 17
+#define S3_FOFF 18
+#define S3_CLNP 19
+
+#ifdef USE_HP_IP4FRAG
+static cas_hp_inst_t cas_prog_ip4fragtab[] = {
+ { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, S1_PCKT,
+ CL_REG, 0x3ff, 1, 0x0, 0x0000},
+ { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023,
+ IM_CTL, 0x00a, 3, 0x0, 0xffff},
+ { "CFI?", 0x1000, 0x1000, OP_EQ, 0, S3_CLNP, 1, S1_8023,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S3_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLCc?",0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S3_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6,
+ LD_SAP, 0x100, 3, 0x0, 0xffff},
+ { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S3_CLNP,
+ LD_SUM, 0x00a, 1, 0x0, 0x0000},
+ { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S3_FRAG,
+ LD_LEN, 0x03e, 3, 0x0, 0xffff},
+ { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S3_TCPSQ, 0, S3_CLNP,
+ LD_FID, 0x182, 3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+ { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S3_IPV6c, 0, S3_CLNP,
+ LD_SUM, 0x015, 1, 0x0, 0x0000},
+ { "IPV6 cont?", 0xf000, 0x6000, OP_EQ, 3, S3_TCP64, 0, S3_CLNP,
+ LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
+ { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S3_TCPSQ, 0, S3_CLNP,
+ LD_LEN, 0x03f, 1, 0x0, 0xffff},
+ { "TCP seq", /* DADDR should point to dest port */
+ 0x0000, 0x0000, OP_EQ, 0, S3_TCPFG, 4, S3_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */
+ { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S3_TCPHL, 0,
+ S3_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S3_TCPHc, 0, S3_TCPHc,
+ LD_R1, 0x205, 3, 0xB, 0xf000},
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ LD_HDR, 0x0ff, 3, 0x0, 0xffff},
+ { "IP4 Fragment", 0x0000, 0x0000, OP_EQ, 0, S3_FOFF, 0, S3_FOFF,
+ LD_FID, 0x103, 3, 0x0, 0xffff}, /* FID IP4 src+dst */
+ { "IP4 frag offset", 0x0000, 0x0000, OP_EQ, 0, S3_FOFF, 0, S3_FOFF,
+ LD_SEQ, 0x040, 1, 0xD, 0xfff8},
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { NULL },
+};
+#ifdef HP_IP4FRAG_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_ip4fragtab
+#endif
+#endif
+
+/*
+ * Alternate table which does batching without reassembly
+ */
+#ifdef USE_HP_IP46TCP4BATCH
+static cas_hp_inst_t cas_prog_ip46tcp4batchtab[] = {
+ CAS_PROG_IP46TCP4_PREAMBLE,
+ { "TCP seq", /* DADDR should point to dest port */
+ 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 0, S1_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */
+ { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0,
+ S1_TCPHL, ST_FLG, 0x000, 3, 0x0, 0x0000}, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0,
+ S1_TCPHc, LD_R1, 0x205, 3, 0xB, 0xf000},
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0,
+ S1_PCKT, IM_CTL, 0x040, 3, 0x0, 0xffff}, /* set batch bit */
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0,
+ S1_PCKT, IM_CTL, 0x080, 3, 0x0, 0xffff},
+ { NULL },
+};
+#ifdef HP_IP46TCP4BATCH_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_ip46tcp4batchtab
+#endif
+#endif
+
+/* Workaround for Cassini rev2 descriptor corruption problem.
+ * Does batching without reassembly, and sets the SAP to a known
+ * data pattern for all packets.
+ */
+#ifdef USE_HP_WORKAROUND
+static cas_hp_inst_t cas_prog_workaroundtab[] = {
+ { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0,
+ S1_PCKT, CL_REG, 0x3ff, 1, 0x0, 0x0000} ,
+ { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023,
+ IM_CTL, 0x04a, 3, 0x0, 0xffff},
+ { "CFI?", 0x1000, 0x1000, OP_EQ, 0, S1_CLNP, 1, S1_8023,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6,
+ IM_SAP, 0x6AE, 3, 0x0, 0xffff},
+ { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP,
+ LD_SUM, 0x00a, 1, 0x0, 0x0000},
+ { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP,
+ LD_LEN, 0x03e, 1, 0x0, 0xffff},
+ { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_CLNP,
+ LD_FID, 0x182, 3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+ { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP,
+ LD_SUM, 0x015, 1, 0x0, 0x0000},
+ { "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP,
+ IM_R1, 0x128, 1, 0x0, 0xffff},
+ { "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP,
+ LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
+ { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP,
+ LD_LEN, 0x03f, 1, 0x0, 0xffff},
+ { "TCP seq", /* DADDR should point to dest port */
+ 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */
+ { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0,
+ S1_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc,
+ LD_R1, 0x205, 3, 0xB, 0xf000},
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0,
+ S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff},
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2,
+ IM_SAP, 0x6AE, 3, 0x0, 0xffff} ,
+ { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { NULL },
+};
+#ifdef HP_WORKAROUND_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_workaroundtab
+#endif
+#endif
+
+#ifdef USE_HP_ENCRYPT
+static cas_hp_inst_t cas_prog_encryptiontab[] = {
+ { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0,
+ S1_PCKT, CL_REG, 0x3ff, 1, 0x0, 0x0000},
+ { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023,
+ IM_CTL, 0x00a, 3, 0x0, 0xffff},
+#if 0
+//"CFI?", /* 02 FIND CFI and If FIND go to S1_DROP */
+//0x1000, 0x1000, OP_EQ, 0, S1_DROP, 1, S1_8023, CL_REG, 0x000, 0, 0x0, 0x00
+ 00,
+#endif
+ { "CFI?", /* FIND CFI and If FIND go to CleanUP1 (ignore and send to host) */
+ 0x1000, 0x1000, OP_EQ, 0, S1_CLNP, 1, S1_8023,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP,
+ CL_REG, 0x000, 0, 0x0, 0x0000},
+ { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6,
+ LD_SAP, 0x100, 3, 0x0, 0xffff},
+ { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP,
+ LD_SUM, 0x00a, 1, 0x0, 0x0000},
+ { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP,
+ LD_LEN, 0x03e, 1, 0x0, 0xffff},
+ { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_ESP4,
+ LD_FID, 0x182, 1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+ { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP,
+ LD_SUM, 0x015, 1, 0x0, 0x0000},
+ { "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP,
+ IM_R1, 0x128, 1, 0x0, 0xffff},
+ { "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP,
+ LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
+ { "TCP64?",
+#if 0
+//@@@0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_ESP6, LD_LEN, 0x03f, 1, 0x0, 0xffff,
+#endif
+ 0xff00, 0x0600, OP_EQ, 12, S1_TCPSQ, 0, S1_ESP6, LD_LEN,
+ 0x03f, 1, 0x0, 0xffff},
+ { "TCP seq", /* 14:DADDR should point to dest port */
+ 0xFFFF, 0x0080, OP_EQ, 0, S2_HTTP, 0, S1_TCPFG, LD_SEQ,
+ 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */
+ { "TCP control flags", 0xFFFF, 0x8080, OP_EQ, 0, S2_HTTP, 0,
+ S1_TCPHL, ST_FLG, 0x145, 2, 0x0, 0x002f}, /* Load TCP flags */
+ { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc,
+ LD_R1, 0x205, 3, 0xB, 0xf000} ,
+ { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0,
+ S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff},
+ { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2,
+ IM_CTL, 0x001, 3, 0x0, 0x0001},
+ { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ CL_REG, 0x002, 3, 0x0, 0x0000},
+ { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x080, 3, 0x0, 0xffff},
+ { "No HTTP", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT,
+ IM_CTL, 0x044, 3, 0x0, 0xffff},
+ { "IPV4 ESP encrypted?", /* S1_ESP4 */
+ 0x00ff, 0x0032, OP_EQ, 0, S1_CLNP2, 0, S1_AH4, IM_CTL,
+ 0x021, 1, 0x0, 0xffff},
+ { "IPV4 AH encrypted?", /* S1_AH4 */
+ 0x00ff, 0x0033, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
+ 0x021, 1, 0x0, 0xffff},
+ { "IPV6 ESP encrypted?", /* S1_ESP6 */
+#if 0
+//@@@0x00ff, 0x0032, OP_EQ, 0, S1_CLNP2, 0, S1_AH6, IM_CTL, 0x021, 1, 0x0, 0xffff,
+#endif
+ 0xff00, 0x3200, OP_EQ, 0, S1_CLNP2, 0, S1_AH6, IM_CTL,
+ 0x021, 1, 0x0, 0xffff},
+ { "IPV6 AH encrypted?", /* S1_AH6 */
+#if 0
+//@@@0x00ff, 0x0033, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL, 0x021, 1, 0x0, 0xffff,
+#endif
+ 0xff00, 0x3300, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
+ 0x021, 1, 0x0, 0xffff},
+ { NULL },
+};
+#ifdef HP_ENCRYPT_DEFAULT
+#define CAS_HP_FIRMWARE cas_prog_encryptiontab
+#endif
+#endif
+
+static cas_hp_inst_t cas_prog_null[] = { {NULL} };
+#ifdef HP_NULL_DEFAULT
+#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
+#define CAS_PHY_MII_MDIO0 0x02
+#define CAS_PHY_MII_MDIO1 0x04
+#define CAS_PHY_MII(x) ((x) & (CAS_PHY_MII_MDIO0 | CAS_PHY_MII_MDIO1))
+
+/* _RING_INDEX is the index for the ring sizes to be used. _RING_SIZE
+ * is the actual size. the default index for the various rings is
+ * 8. NOTE: there a bunch of alignment constraints for the rings. to
+ * deal with that, i just allocate rings to create the desired
+ * alignment. here are the constraints:
+ * RX DESC and COMP rings must be 8KB aligned
+ * TX DESC must be 2KB aligned.
+ * if you change the numbers, be cognizant of how the alignment will change
+ * in INIT_BLOCK as well.
+ */
+
+#define DESC_RING_I_TO_S(x) (32*(1 << (x)))
+#define COMP_RING_I_TO_S(x) (128*(1 << (x)))
+#define TX_DESC_RING_INDEX 4 /* 512 = 8k */
+#define RX_DESC_RING_INDEX 4 /* 512 = 8k */
+#define RX_COMP_RING_INDEX 4 /* 2048 = 64k: should be 4x rx ring size */
+
+#if (TX_DESC_RING_INDEX > 8) || (TX_DESC_RING_INDEX < 0)
+#error TX_DESC_RING_INDEX must be between 0 and 8
+#endif
+
+#if (RX_DESC_RING_INDEX > 8) || (RX_DESC_RING_INDEX < 0)
+#error RX_DESC_RING_INDEX must be between 0 and 8
+#endif
+
+#if (RX_COMP_RING_INDEX > 8) || (RX_COMP_RING_INDEX < 0)
+#error RX_COMP_RING_INDEX must be between 0 and 8
+#endif
+
+#define N_TX_RINGS MAX_TX_RINGS /* for QoS */
+#define N_TX_RINGS_MASK MAX_TX_RINGS_MASK
+#define N_RX_DESC_RINGS MAX_RX_DESC_RINGS /* 1 for ipsec */
+#define N_RX_COMP_RINGS 0x1 /* for mult. PCI interrupts */
+
+/* number of flows that can go through re-assembly */
+#define N_RX_FLOWS 64
+
+#define TX_DESC_RING_SIZE DESC_RING_I_TO_S(TX_DESC_RING_INDEX)
+#define RX_DESC_RING_SIZE DESC_RING_I_TO_S(RX_DESC_RING_INDEX)
+#define RX_COMP_RING_SIZE COMP_RING_I_TO_S(RX_COMP_RING_INDEX)
+#define TX_DESC_RINGN_INDEX(x) TX_DESC_RING_INDEX
+#define RX_DESC_RINGN_INDEX(x) RX_DESC_RING_INDEX
+#define RX_COMP_RINGN_INDEX(x) RX_COMP_RING_INDEX
+#define TX_DESC_RINGN_SIZE(x) TX_DESC_RING_SIZE
+#define RX_DESC_RINGN_SIZE(x) RX_DESC_RING_SIZE
+#define RX_COMP_RINGN_SIZE(x) RX_COMP_RING_SIZE
+
+/* convert values */
+#define CAS_BASE(x, y) (((y) << (x ## _SHIFT)) & (x ## _MASK))
+#define CAS_VAL(x, y) (((y) & (x ## _MASK)) >> (x ## _SHIFT))
+#define CAS_TX_RINGN_BASE(y) ((TX_DESC_RINGN_INDEX(y) << \
+ TX_CFG_DESC_RINGN_SHIFT(y)) & \
+ TX_CFG_DESC_RINGN_MASK(y))
+
+/* min is 2k, but we can't do jumbo frames unless it's at least 8k */
+#define CAS_MIN_PAGE_SHIFT 11 /* 2048 */
+#define CAS_JUMBO_PAGE_SHIFT 13 /* 8192 */
+#define CAS_MAX_PAGE_SHIFT 14 /* 16384 */
+
+#define TX_DESC_BUFLEN_MASK 0x0000000000003FFFULL /* buffer length in
+ bytes. 0 - 9256 */
+#define TX_DESC_BUFLEN_SHIFT 0
+#define TX_DESC_CSUM_START_MASK 0x00000000001F8000ULL /* checksum start. #
+ of bytes to be
+ skipped before
+ csum calc begins.
+ value must be
+ even */
+#define TX_DESC_CSUM_START_SHIFT 15
+#define TX_DESC_CSUM_STUFF_MASK 0x000000001FE00000ULL /* checksum stuff.
+ byte offset w/in
+ the pkt for the
+ 1st csum byte.
+ must be > 8 */
+#define TX_DESC_CSUM_STUFF_SHIFT 21
+#define TX_DESC_CSUM_EN 0x0000000020000000ULL /* enable checksum */
+#define TX_DESC_EOF 0x0000000040000000ULL /* end of frame */
+#define TX_DESC_SOF 0x0000000080000000ULL /* start of frame */
+#define TX_DESC_INTME 0x0000000100000000ULL /* interrupt me */
+#define TX_DESC_NO_CRC 0x0000000200000000ULL /* debugging only.
+ CRC will not be
+ inserted into
+ outgoing frame. */
+struct cas_tx_desc {
+ u64 control;
+ u64 buffer;
+};
+
+/* descriptor ring for free buffers contains page-sized buffers. the index
+ * value is not used by the hw in any way. it's just stored and returned in
+ * the completion ring.
+ */
+struct cas_rx_desc {
+ u64 index;
+ u64 buffer;
+};
+
+/* received packets are put on the completion ring. */
+/* word 1 */
+#define RX_COMP1_DATA_SIZE_MASK 0x0000000007FFE000ULL
+#define RX_COMP1_DATA_SIZE_SHIFT 13
+#define RX_COMP1_DATA_OFF_MASK 0x000001FFF8000000ULL
+#define RX_COMP1_DATA_OFF_SHIFT 27
+#define RX_COMP1_DATA_INDEX_MASK 0x007FFE0000000000ULL
+#define RX_COMP1_DATA_INDEX_SHIFT 41
+#define RX_COMP1_SKIP_MASK 0x0180000000000000ULL
+#define RX_COMP1_SKIP_SHIFT 55
+#define RX_COMP1_RELEASE_NEXT 0x0200000000000000ULL
+#define RX_COMP1_SPLIT_PKT 0x0400000000000000ULL
+#define RX_COMP1_RELEASE_FLOW 0x0800000000000000ULL
+#define RX_COMP1_RELEASE_DATA 0x1000000000000000ULL
+#define RX_COMP1_RELEASE_HDR 0x2000000000000000ULL
+#define RX_COMP1_TYPE_MASK 0xC000000000000000ULL
+#define RX_COMP1_TYPE_SHIFT 62
+
+/* word 2 */
+#define RX_COMP2_NEXT_INDEX_MASK 0x00000007FFE00000ULL
+#define RX_COMP2_NEXT_INDEX_SHIFT 21
+#define RX_COMP2_HDR_SIZE_MASK 0x00000FF800000000ULL
+#define RX_COMP2_HDR_SIZE_SHIFT 35
+#define RX_COMP2_HDR_OFF_MASK 0x0003F00000000000ULL
+#define RX_COMP2_HDR_OFF_SHIFT 44
+#define RX_COMP2_HDR_INDEX_MASK 0xFFFC000000000000ULL
+#define RX_COMP2_HDR_INDEX_SHIFT 50
+
+/* word 3 */
+#define RX_COMP3_SMALL_PKT 0x0000000000000001ULL
+#define RX_COMP3_JUMBO_PKT 0x0000000000000002ULL
+#define RX_COMP3_JUMBO_HDR_SPLIT_EN 0x0000000000000004ULL
+#define RX_COMP3_CSUM_START_MASK 0x000000000007F000ULL
+#define RX_COMP3_CSUM_START_SHIFT 12
+#define RX_COMP3_FLOWID_MASK 0x0000000001F80000ULL
+#define RX_COMP3_FLOWID_SHIFT 19
+#define RX_COMP3_OPCODE_MASK 0x000000000E000000ULL
+#define RX_COMP3_OPCODE_SHIFT 25
+#define RX_COMP3_FORCE_FLAG 0x0000000010000000ULL
+#define RX_COMP3_NO_ASSIST 0x0000000020000000ULL
+#define RX_COMP3_LOAD_BAL_MASK 0x000001F800000000ULL
+#define RX_COMP3_LOAD_BAL_SHIFT 35
+#define RX_PLUS_COMP3_ENC_PKT 0x0000020000000000ULL /* cas+ */
+#define RX_COMP3_L3_HEAD_OFF_MASK 0x0000FE0000000000ULL /* cas */
+#define RX_COMP3_L3_HEAD_OFF_SHIFT 41
+#define RX_PLUS_COMP_L3_HEAD_OFF_MASK 0x0000FC0000000000ULL /* cas+ */
+#define RX_PLUS_COMP_L3_HEAD_OFF_SHIFT 42
+#define RX_COMP3_SAP_MASK 0xFFFF000000000000ULL
+#define RX_COMP3_SAP_SHIFT 48
+
+/* word 4 */
+#define RX_COMP4_TCP_CSUM_MASK 0x000000000000FFFFULL
+#define RX_COMP4_TCP_CSUM_SHIFT 0
+#define RX_COMP4_PKT_LEN_MASK 0x000000003FFF0000ULL
+#define RX_COMP4_PKT_LEN_SHIFT 16
+#define RX_COMP4_PERFECT_MATCH_MASK 0x00000003C0000000ULL
+#define RX_COMP4_PERFECT_MATCH_SHIFT 30
+#define RX_COMP4_ZERO 0x0000080000000000ULL
+#define RX_COMP4_HASH_VAL_MASK 0x0FFFF00000000000ULL
+#define RX_COMP4_HASH_VAL_SHIFT 44
+#define RX_COMP4_HASH_PASS 0x1000000000000000ULL
+#define RX_COMP4_BAD 0x4000000000000000ULL
+#define RX_COMP4_LEN_MISMATCH 0x8000000000000000ULL
+
+/* we encode the following: ring/index/release. only 14 bits
+ * are usable.
+ * NOTE: the encoding is dependent upon RX_DESC_RING_SIZE and
+ * MAX_RX_DESC_RINGS. */
+#define RX_INDEX_NUM_MASK 0x0000000000000FFFULL
+#define RX_INDEX_NUM_SHIFT 0
+#define RX_INDEX_RING_MASK 0x0000000000001000ULL
+#define RX_INDEX_RING_SHIFT 12
+#define RX_INDEX_RELEASE 0x0000000000002000ULL
+
+struct cas_rx_comp {
+ u64 word1;
+ u64 word2;
+ u64 word3;
+ u64 word4;
+};
+
+enum link_state {
+ link_down = 0, /* No link, will retry */
+ link_aneg, /* Autoneg in progress */
+ link_force_try, /* Try Forced link speed */
+ link_force_ret, /* Forced mode worked, retrying autoneg */
+ link_force_ok, /* Stay in forced mode */
+ link_up /* Link is up */
+};
+
+typedef struct cas_page {
+ struct list_head list;
+ struct page *buffer;
+ dma_addr_t dma_addr;
+ int used;
+} cas_page_t;
+
+
+/* some alignment constraints:
+ * TX DESC, RX DESC, and RX COMP must each be 8K aligned.
+ * TX COMPWB must be 8-byte aligned.
+ * to accomplish this, here's what we do:
+ *
+ * INIT_BLOCK_RX_COMP = 64k (already aligned)
+ * INIT_BLOCK_RX_DESC = 8k
+ * INIT_BLOCK_TX = 8k
+ * INIT_BLOCK_RX1_DESC = 8k
+ * TX COMPWB
+ */
+#define INIT_BLOCK_TX (TX_DESC_RING_SIZE)
+#define INIT_BLOCK_RX_DESC (RX_DESC_RING_SIZE)
+#define INIT_BLOCK_RX_COMP (RX_COMP_RING_SIZE)
+
+struct cas_init_block {
+ struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP];
+ struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC];
+ struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX];
+ u64 tx_compwb;
+};
+
+/* tiny buffers to deal with target abort issue. we allocate a bit
+ * over so that we don't have target abort issues with these buffers
+ * as well.
+ */
+#define TX_TINY_BUF_LEN 0x100
+#define TX_TINY_BUF_BLOCK ((INIT_BLOCK_TX + 1)*TX_TINY_BUF_LEN)
+
+struct cas_tiny_count {
+ int nbufs;
+ int used;
+};
+
+struct cas {
+ spinlock_t lock; /* for most bits */
+ spinlock_t tx_lock[N_TX_RINGS]; /* tx bits */
+ spinlock_t stat_lock[N_TX_RINGS + 1]; /* for stat gathering */
+ spinlock_t rx_inuse_lock; /* rx inuse list */
+ spinlock_t rx_spare_lock; /* rx spare list */
+
+ void __iomem *regs;
+ int tx_new[N_TX_RINGS], tx_old[N_TX_RINGS];
+ int rx_old[N_RX_DESC_RINGS];
+ int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS];
+ int rx_last[N_RX_DESC_RINGS];
+
+ /* Set when chip is actually in operational state
+ * (ie. not power managed) */
+ int hw_running;
+ int opened;
+ struct semaphore pm_sem; /* open/close/suspend/resume */
+
+ struct cas_init_block *init_block;
+ struct cas_tx_desc *init_txds[MAX_TX_RINGS];
+ struct cas_rx_desc *init_rxds[MAX_RX_DESC_RINGS];
+ struct cas_rx_comp *init_rxcs[MAX_RX_COMP_RINGS];
+
+ /* we use sk_buffs for tx and pages for rx. the rx skbuffs
+ * are there for flow re-assembly. */
+ struct sk_buff *tx_skbs[N_TX_RINGS][TX_DESC_RING_SIZE];
+ struct sk_buff_head rx_flows[N_RX_FLOWS];
+ cas_page_t *rx_pages[N_RX_DESC_RINGS][RX_DESC_RING_SIZE];
+ struct list_head rx_spare_list, rx_inuse_list;
+ int rx_spares_needed;
+
+ /* for small packets when copying would be quicker than
+ mapping */
+ struct cas_tiny_count tx_tiny_use[N_TX_RINGS][TX_DESC_RING_SIZE];
+ u8 *tx_tiny_bufs[N_TX_RINGS];
+
+ u32 msg_enable;
+
+ /* N_TX_RINGS must be >= N_RX_DESC_RINGS */
+ struct net_device_stats net_stats[N_TX_RINGS + 1];
+
+ u32 pci_cfg[64 >> 2];
+ u8 pci_revision;
+
+ int phy_type;
+ int phy_addr;
+ u32 phy_id;
+#define CAS_FLAG_1000MB_CAP 0x00000001
+#define CAS_FLAG_REG_PLUS 0x00000002
+#define CAS_FLAG_TARGET_ABORT 0x00000004
+#define CAS_FLAG_SATURN 0x00000008
+#define CAS_FLAG_RXD_POST_MASK 0x000000F0
+#define CAS_FLAG_RXD_POST_SHIFT 4
+#define CAS_FLAG_RXD_POST(x) ((1 << (CAS_FLAG_RXD_POST_SHIFT + (x))) & \
+ CAS_FLAG_RXD_POST_MASK)
+#define CAS_FLAG_ENTROPY_DEV 0x00000100
+#define CAS_FLAG_NO_HW_CSUM 0x00000200
+ u32 cas_flags;
+ int packet_min; /* minimum packet size */
+ int tx_fifo_size;
+ int rx_fifo_size;
+ int rx_pause_off;
+ int rx_pause_on;
+ int crc_size; /* 4 if half-duplex */
+
+ int pci_irq_INTC;
+ int min_frame_size; /* for tx fifo workaround */
+
+ /* page size allocation */
+ int page_size;
+ int page_order;
+ int mtu_stride;
+
+ u32 mac_rx_cfg;
+
+ /* Autoneg & PHY control */
+ int link_cntl;
+ int link_fcntl;
+ enum link_state lstate;
+ struct timer_list link_timer;
+ int timer_ticks;
+ struct work_struct reset_task;
+#if 0
+ atomic_t reset_task_pending;
+#else
+ atomic_t reset_task_pending;
+ atomic_t reset_task_pending_mtu;
+ atomic_t reset_task_pending_spare;
+ atomic_t reset_task_pending_all;
+#endif
+
+#ifdef CONFIG_CASSINI_QGE_DEBUG
+ atomic_t interrupt_seen; /* 1 if any interrupts are getting through */
+#endif
+
+ /* Link-down problem workaround */
+#define LINK_TRANSITION_UNKNOWN 0
+#define LINK_TRANSITION_ON_FAILURE 1
+#define LINK_TRANSITION_STILL_FAILED 2
+#define LINK_TRANSITION_LINK_UP 3
+#define LINK_TRANSITION_LINK_CONFIG 4
+#define LINK_TRANSITION_LINK_DOWN 5
+#define LINK_TRANSITION_REQUESTED_RESET 6
+ int link_transition;
+ int link_transition_jiffies_valid;
+ unsigned long link_transition_jiffies;
+
+ /* Tuning */
+ u8 orig_cacheline_size; /* value when loaded */
+#define CAS_PREF_CACHELINE_SIZE 0x20 /* Minimum desired */
+
+ /* Diagnostic counters and state. */
+ int casreg_len; /* reg-space size for dumping */
+ u64 pause_entered;
+ u16 pause_last_time_recvd;
+
+ dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
+ struct pci_dev *pdev;
+ struct net_device *dev;
+};
+
+#define TX_DESC_NEXT(r, x) (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1))
+#define RX_DESC_ENTRY(r, x) ((x) & (RX_DESC_RINGN_SIZE(r) - 1))
+#define RX_COMP_ENTRY(r, x) ((x) & (RX_COMP_RINGN_SIZE(r) - 1))
+
+#define TX_BUFF_COUNT(r, x, y) ((x) <= (y) ? ((y) - (x)) : \
+ (TX_DESC_RINGN_SIZE(r) - (x) + (y)))
+
+#define TX_BUFFS_AVAIL(cp, i) ((cp)->tx_old[(i)] <= (cp)->tx_new[(i)] ? \
+ (cp)->tx_old[(i)] + (TX_DESC_RINGN_SIZE(i) - 1) - (cp)->tx_new[(i)] : \
+ (cp)->tx_old[(i)] - (cp)->tx_new[(i)] - 1)
+
+#define CAS_ALIGN(addr, align) \
+ (((unsigned long) (addr) + ((align) - 1UL)) & ~((align) - 1))
+
+#define RX_FIFO_SIZE 16384
+#define EXPANSION_ROM_SIZE 65536
+
+#define CAS_MC_EXACT_MATCH_SIZE 15
+#define CAS_MC_HASH_SIZE 256
+#define CAS_MC_HASH_MAX (CAS_MC_EXACT_MATCH_SIZE + \
+ CAS_MC_HASH_SIZE)
+
+#define TX_TARGET_ABORT_LEN 0x20
+#define RX_SWIVEL_OFF_VAL 0x2
+#define RX_AE_FREEN_VAL(x) (RX_DESC_RINGN_SIZE(x) >> 1)
+#define RX_AE_COMP_VAL (RX_COMP_RING_SIZE >> 1)
+#define RX_BLANK_INTR_PKT_VAL 0x05
+#define RX_BLANK_INTR_TIME_VAL 0x0F
+#define HP_TCP_THRESH_VAL 1530 /* reduce to enable reassembly */
+
+#define RX_SPARE_COUNT (RX_DESC_RING_SIZE >> 1)
+#define RX_SPARE_RECOVER_VAL (RX_SPARE_COUNT >> 2)
+
+#endif /* _CASSINI_H */
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
new file mode 100644
index 000000000000..91e927827c43
--- /dev/null
+++ b/drivers/net/chelsio/Makefile
@@ -0,0 +1,11 @@
+#
+# Chelsio 10Gb NIC driver for Linux.
+#
+
+obj-$(CONFIG_CHELSIO_T1) += cxgb.o
+
+EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS)
+
+
+cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
+
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
new file mode 100644
index 000000000000..bf3e7b6a7a18
--- /dev/null
+++ b/drivers/net/chelsio/common.h
@@ -0,0 +1,314 @@
+/*****************************************************************************
+ * *
+ * File: common.h *
+ * $Revision: 1.21 $ *
+ * $Date: 2005/06/22 00:43:25 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_COMMON_H_
+#define _CXGB_COMMON_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/pci_ids.h>
+
+#define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver"
+#define DRV_NAME "cxgb"
+#define DRV_VERSION "2.1.1"
+#define PFX DRV_NAME ": "
+
+#define CH_ERR(fmt, ...) printk(KERN_ERR PFX fmt, ## __VA_ARGS__)
+#define CH_WARN(fmt, ...) printk(KERN_WARNING PFX fmt, ## __VA_ARGS__)
+#define CH_ALERT(fmt, ...) printk(KERN_ALERT PFX fmt, ## __VA_ARGS__)
+
+#define CH_DEVICE(devid, ssid, idx) \
+ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
+
+#define SUPPORTED_PAUSE (1 << 13)
+#define SUPPORTED_LOOPBACK (1 << 15)
+
+#define ADVERTISED_PAUSE (1 << 13)
+#define ADVERTISED_ASYM_PAUSE (1 << 14)
+
+typedef struct adapter adapter_t;
+
+void t1_elmer0_ext_intr(adapter_t *adapter);
+void t1_link_changed(adapter_t *adapter, int port_id, int link_status,
+ int speed, int duplex, int fc);
+
+struct t1_rx_mode {
+ struct net_device *dev;
+ u32 idx;
+ struct dev_mc_list *list;
+};
+
+#define t1_rx_mode_promisc(rm) (rm->dev->flags & IFF_PROMISC)
+#define t1_rx_mode_allmulti(rm) (rm->dev->flags & IFF_ALLMULTI)
+#define t1_rx_mode_mc_cnt(rm) (rm->dev->mc_count)
+
+static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm)
+{
+ u8 *addr = NULL;
+
+ if (rm->idx++ < rm->dev->mc_count) {
+ addr = rm->list->dmi_addr;
+ rm->list = rm->list->next;
+ }
+ return addr;
+}
+
+#define MAX_NPORTS 4
+
+#define SPEED_INVALID 0xffff
+#define DUPLEX_INVALID 0xff
+
+enum {
+ CHBT_BOARD_N110,
+ CHBT_BOARD_N210
+};
+
+enum {
+ CHBT_TERM_T1,
+ CHBT_TERM_T2
+};
+
+enum {
+ CHBT_MAC_PM3393,
+};
+
+enum {
+ CHBT_PHY_88X2010,
+};
+
+enum {
+ PAUSE_RX = 1 << 0,
+ PAUSE_TX = 1 << 1,
+ PAUSE_AUTONEG = 1 << 2
+};
+
+/* Revisions of T1 chip */
+enum {
+ TERM_T1A = 0,
+ TERM_T1B = 1,
+ TERM_T2 = 3
+};
+
+struct sge_params {
+ unsigned int cmdQ_size[2];
+ unsigned int freelQ_size[2];
+ unsigned int large_buf_capacity;
+ unsigned int rx_coalesce_usecs;
+ unsigned int last_rx_coalesce_raw;
+ unsigned int default_rx_coalesce_usecs;
+ unsigned int sample_interval_usecs;
+ unsigned int coalesce_enable;
+ unsigned int polling;
+};
+
+struct chelsio_pci_params {
+ unsigned short speed;
+ unsigned char width;
+ unsigned char is_pcix;
+};
+
+struct adapter_params {
+ struct sge_params sge;
+ struct chelsio_pci_params pci;
+
+ const struct board_info *brd_info;
+
+ unsigned int nports; /* # of ethernet ports */
+ unsigned int stats_update_period;
+ unsigned short chip_revision;
+ unsigned char chip_version;
+};
+
+struct link_config {
+ unsigned int supported; /* link capabilities */
+ unsigned int advertising; /* advertised capabilities */
+ unsigned short requested_speed; /* speed user has requested */
+ unsigned short speed; /* actual link speed */
+ unsigned char requested_duplex; /* duplex user has requested */
+ unsigned char duplex; /* actual link duplex */
+ unsigned char requested_fc; /* flow control user has requested */
+ unsigned char fc; /* actual link flow control */
+ unsigned char autoneg; /* autonegotiating? */
+};
+
+struct cmac;
+struct cphy;
+
+struct port_info {
+ struct net_device *dev;
+ struct cmac *mac;
+ struct cphy *phy;
+ struct link_config link_config;
+ struct net_device_stats netstats;
+};
+
+struct sge;
+struct peespi;
+
+struct adapter {
+ u8 __iomem *regs;
+ struct pci_dev *pdev;
+ unsigned long registered_device_map;
+ unsigned long open_device_map;
+ unsigned long flags;
+
+ const char *name;
+ int msg_enable;
+ u32 mmio_len;
+
+ struct work_struct ext_intr_handler_task;
+ struct adapter_params params;
+
+ struct vlan_group *vlan_grp;
+
+ /* Terminator modules. */
+ struct sge *sge;
+ struct peespi *espi;
+
+ struct port_info port[MAX_NPORTS];
+ struct work_struct stats_update_task;
+ struct timer_list stats_update_timer;
+
+ struct semaphore mib_mutex;
+ spinlock_t tpi_lock;
+ spinlock_t work_lock;
+ /* guards async operations */
+ spinlock_t async_lock ____cacheline_aligned;
+ u32 slow_intr_mask;
+};
+
+enum { /* adapter flags */
+ FULL_INIT_DONE = 1 << 0,
+ TSO_CAPABLE = 1 << 2,
+ TCP_CSUM_CAPABLE = 1 << 3,
+ UDP_CSUM_CAPABLE = 1 << 4,
+ VLAN_ACCEL_CAPABLE = 1 << 5,
+ RX_CSUM_ENABLED = 1 << 6,
+};
+
+struct mdio_ops;
+struct gmac;
+struct gphy;
+
+struct board_info {
+ unsigned char board;
+ unsigned char port_number;
+ unsigned long caps;
+ unsigned char chip_term;
+ unsigned char chip_mac;
+ unsigned char chip_phy;
+ unsigned int clock_core;
+ unsigned int clock_mc3;
+ unsigned int clock_mc4;
+ unsigned int espi_nports;
+ unsigned int clock_cspi;
+ unsigned int clock_elmer0;
+ unsigned char mdio_mdien;
+ unsigned char mdio_mdiinv;
+ unsigned char mdio_mdc;
+ unsigned char mdio_phybaseaddr;
+ struct gmac *gmac;
+ struct gphy *gphy;
+ struct mdio_ops *mdio_ops;
+ const char *desc;
+};
+
+extern struct pci_device_id t1_pci_tbl[];
+
+static inline int adapter_matches_type(const adapter_t *adapter,
+ int version, int revision)
+{
+ return adapter->params.chip_version == version &&
+ adapter->params.chip_revision == revision;
+}
+
+#define t1_is_T1B(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1B)
+#define is_T2(adap) adapter_matches_type(adap, CHBT_TERM_T2, TERM_T2)
+
+/* Returns true if an adapter supports VLAN acceleration and TSO */
+static inline int vlan_tso_capable(const adapter_t *adapter)
+{
+ return !t1_is_T1B(adapter);
+}
+
+#define for_each_port(adapter, iter) \
+ for (iter = 0; iter < (adapter)->params.nports; ++iter)
+
+#define board_info(adapter) ((adapter)->params.brd_info)
+#define is_10G(adapter) (board_info(adapter)->caps & SUPPORTED_10000baseT_Full)
+
+static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
+{
+ return board_info(adap)->clock_core / 1000000;
+}
+
+extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
+extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
+
+extern void t1_interrupts_enable(adapter_t *adapter);
+extern void t1_interrupts_disable(adapter_t *adapter);
+extern void t1_interrupts_clear(adapter_t *adapter);
+extern int elmer0_ext_intr_handler(adapter_t *adapter);
+extern int t1_slow_intr_handler(adapter_t *adapter);
+
+extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
+extern const struct board_info *t1_get_board_info(unsigned int board_id);
+extern const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
+ unsigned short ssid);
+extern int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data);
+extern int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ struct adapter_params *p);
+extern int t1_init_hw_modules(adapter_t *adapter);
+extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
+extern void t1_free_sw_modules(adapter_t *adapter);
+extern void t1_fatal_err(adapter_t *adapter);
+
+extern void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable);
+extern void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable);
+extern void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable);
+
+#endif /* _CXGB_COMMON_H_ */
diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h
new file mode 100644
index 000000000000..3412342f7345
--- /dev/null
+++ b/drivers/net/chelsio/cphy.h
@@ -0,0 +1,148 @@
+/*****************************************************************************
+ * *
+ * File: cphy.h *
+ * $Revision: 1.7 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_CPHY_H_
+#define _CXGB_CPHY_H_
+
+#include "common.h"
+
+struct mdio_ops {
+ void (*init)(adapter_t *adapter, const struct board_info *bi);
+ int (*read)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *val);
+ int (*write)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val);
+};
+
+/* PHY interrupt types */
+enum {
+ cphy_cause_link_change = 0x1,
+ cphy_cause_error = 0x2
+};
+
+struct cphy;
+
+/* PHY operations */
+struct cphy_ops {
+ void (*destroy)(struct cphy *);
+ int (*reset)(struct cphy *, int wait);
+
+ int (*interrupt_enable)(struct cphy *);
+ int (*interrupt_disable)(struct cphy *);
+ int (*interrupt_clear)(struct cphy *);
+ int (*interrupt_handler)(struct cphy *);
+
+ int (*autoneg_enable)(struct cphy *);
+ int (*autoneg_disable)(struct cphy *);
+ int (*autoneg_restart)(struct cphy *);
+
+ int (*advertise)(struct cphy *phy, unsigned int advertise_map);
+ int (*set_loopback)(struct cphy *, int on);
+ int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
+ int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
+ int *duplex, int *fc);
+};
+
+/* A PHY instance */
+struct cphy {
+ int addr; /* PHY address */
+ adapter_t *adapter; /* associated adapter */
+ struct cphy_ops *ops; /* PHY operations */
+ int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *val);
+ int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val);
+ struct cphy_instance *instance;
+};
+
+/* Convenience MDIO read/write wrappers */
+static inline int mdio_read(struct cphy *cphy, int mmd, int reg,
+ unsigned int *valp)
+{
+ return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp);
+}
+
+static inline int mdio_write(struct cphy *cphy, int mmd, int reg,
+ unsigned int val)
+{
+ return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val);
+}
+
+static inline int simple_mdio_read(struct cphy *cphy, int reg,
+ unsigned int *valp)
+{
+ return mdio_read(cphy, 0, reg, valp);
+}
+
+static inline int simple_mdio_write(struct cphy *cphy, int reg,
+ unsigned int val)
+{
+ return mdio_write(cphy, 0, reg, val);
+}
+
+/* Convenience initializer */
+static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
+ int phy_addr, struct cphy_ops *phy_ops,
+ struct mdio_ops *mdio_ops)
+{
+ phy->adapter = adapter;
+ phy->addr = phy_addr;
+ phy->ops = phy_ops;
+ if (mdio_ops) {
+ phy->mdio_read = mdio_ops->read;
+ phy->mdio_write = mdio_ops->write;
+ }
+}
+
+/* Operations of the PHY-instance factory */
+struct gphy {
+ /* Construct a PHY instance with the given PHY address */
+ struct cphy *(*create)(adapter_t *adapter, int phy_addr,
+ struct mdio_ops *mdio_ops);
+
+ /*
+ * Reset the PHY chip. This resets the whole PHY chip, not individual
+ * ports.
+ */
+ int (*reset)(adapter_t *adapter);
+};
+
+extern struct gphy t1_mv88x201x_ops;
+extern struct gphy t1_dummy_phy_ops;
+
+#endif /* _CXGB_CPHY_H_ */
diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/chelsio/cpl5_cmd.h
new file mode 100644
index 000000000000..27925e487bcf
--- /dev/null
+++ b/drivers/net/chelsio/cpl5_cmd.h
@@ -0,0 +1,145 @@
+/*****************************************************************************
+ * *
+ * File: cpl5_cmd.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_CPL5_CMD_H_
+#define _CXGB_CPL5_CMD_H_
+
+#include <asm/byteorder.h>
+
+#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD)
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+
+enum CPL_opcode {
+ CPL_RX_PKT = 0xAD,
+ CPL_TX_PKT = 0xB2,
+ CPL_TX_PKT_LSO = 0xB6,
+};
+
+enum { /* TX_PKT_LSO ethernet types */
+ CPL_ETH_II,
+ CPL_ETH_II_VLAN,
+ CPL_ETH_802_3,
+ CPL_ETH_802_3_VLAN
+};
+
+struct cpl_rx_data {
+ u32 rsvd0;
+ u32 len;
+ u32 seq;
+ u16 urg;
+ u8 rsvd1;
+ u8 status;
+};
+
+/*
+ * We want this header's alignment to be no more stringent than 2-byte aligned.
+ * All fields are u8 or u16 except for the length. However that field is not
+ * used so we break it into 2 16-bit parts to easily meet our alignment needs.
+ */
+struct cpl_tx_pkt {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 ip_csum_dis:1;
+ u8 l4_csum_dis:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 l4_csum_dis:1;
+ u8 ip_csum_dis:1;
+ u8 iff:4;
+#endif
+ u16 vlan;
+ u16 len_hi;
+ u16 len_lo;
+};
+
+struct cpl_tx_pkt_lso {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 ip_csum_dis:1;
+ u8 l4_csum_dis:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 l4_csum_dis:1;
+ u8 ip_csum_dis:1;
+ u8 iff:4;
+#endif
+ u16 vlan;
+ u32 len;
+
+ u32 rsvd2;
+ u8 rsvd3;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 tcp_hdr_words:4;
+ u8 ip_hdr_words:4;
+#else
+ u8 ip_hdr_words:4;
+ u8 tcp_hdr_words:4;
+#endif
+ u16 eth_type_mss;
+};
+
+struct cpl_rx_pkt {
+ u8 opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 iff:4;
+ u8 csum_valid:1;
+ u8 bad_pkt:1;
+ u8 vlan_valid:1;
+ u8 rsvd:1;
+#else
+ u8 rsvd:1;
+ u8 vlan_valid:1;
+ u8 bad_pkt:1;
+ u8 csum_valid:1;
+ u8 iff:4;
+#endif
+ u16 csum;
+ u16 vlan;
+ u16 len;
+};
+
+#endif /* _CXGB_CPL5_CMD_H_ */
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
new file mode 100644
index 000000000000..349ebe783ed6
--- /dev/null
+++ b/drivers/net/chelsio/cxgb2.c
@@ -0,0 +1,1256 @@
+/*****************************************************************************
+ * *
+ * File: cxgb2.c *
+ * $Revision: 1.25 $ *
+ * $Date: 2005/06/22 00:43:25 $ *
+ * Description: *
+ * Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/mii.h>
+#include <linux/sockios.h>
+#include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
+#include <asm/uaccess.h>
+
+#include "cpl5_cmd.h"
+#include "regs.h"
+#include "gmac.h"
+#include "cphy.h"
+#include "sge.h"
+#include "espi.h"
+
+#ifdef work_struct
+#include <linux/tqueue.h>
+#define INIT_WORK INIT_TQUEUE
+#define schedule_work schedule_task
+#define flush_scheduled_work flush_scheduled_tasks
+
+static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
+{
+ mod_timer(&ap->stats_update_timer, jiffies + secs * HZ);
+}
+
+static inline void cancel_mac_stats_update(struct adapter *ap)
+{
+ del_timer_sync(&ap->stats_update_timer);
+ flush_scheduled_tasks();
+}
+
+/*
+ * Stats update timer for 2.4. It schedules a task to do the actual update as
+ * we need to access MAC statistics in process context.
+ */
+static void mac_stats_timer(unsigned long data)
+{
+ struct adapter *ap = (struct adapter *)data;
+
+ schedule_task(&ap->stats_update_task);
+}
+#else
+#include <linux/workqueue.h>
+
+static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
+{
+ schedule_delayed_work(&ap->stats_update_task, secs * HZ);
+}
+
+static inline void cancel_mac_stats_update(struct adapter *ap)
+{
+ cancel_delayed_work(&ap->stats_update_task);
+}
+#endif
+
+#define MAX_CMDQ_ENTRIES 16384
+#define MAX_CMDQ1_ENTRIES 1024
+#define MAX_RX_BUFFERS 16384
+#define MAX_RX_JUMBO_BUFFERS 16384
+#define MAX_TX_BUFFERS_HIGH 16384U
+#define MAX_TX_BUFFERS_LOW 1536U
+#define MIN_FL_ENTRIES 32
+
+#define PORT_MASK ((1 << MAX_NPORTS) - 1)
+
+#define DFLT_MSG_ENABLE (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)
+
+/*
+ * The EEPROM is actually bigger but only the first few bytes are used so we
+ * only report those.
+ */
+#define EEPROM_SIZE 32
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("Chelsio Communications");
+MODULE_LICENSE("GPL");
+
+static int dflt_msg_enable = DFLT_MSG_ENABLE;
+
+MODULE_PARM(dflt_msg_enable, "i");
+MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap");
+
+
+static const char pci_speed[][4] = {
+ "33", "66", "100", "133"
+};
+
+/*
+ * Setup MAC to receive the types of packets we want.
+ */
+static void t1_set_rxmode(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ struct t1_rx_mode rm;
+
+ rm.dev = dev;
+ rm.idx = 0;
+ rm.list = dev->mc_list;
+ mac->ops->set_rx_mode(mac, &rm);
+}
+
+static void link_report(struct port_info *p)
+{
+ if (!netif_carrier_ok(p->dev))
+ printk(KERN_INFO "%s: link down\n", p->dev->name);
+ else {
+ const char *s = "10Mbps";
+
+ switch (p->link_config.speed) {
+ case SPEED_10000: s = "10Gbps"; break;
+ case SPEED_1000: s = "1000Mbps"; break;
+ case SPEED_100: s = "100Mbps"; break;
+ }
+
+ printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
+ p->dev->name, s,
+ p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
+ }
+}
+
+void t1_link_changed(struct adapter *adapter, int port_id, int link_stat,
+ int speed, int duplex, int pause)
+{
+ struct port_info *p = &adapter->port[port_id];
+
+ if (link_stat != netif_carrier_ok(p->dev)) {
+ if (link_stat)
+ netif_carrier_on(p->dev);
+ else
+ netif_carrier_off(p->dev);
+ link_report(p);
+
+ }
+}
+
+static void link_start(struct port_info *p)
+{
+ struct cmac *mac = p->mac;
+
+ mac->ops->reset(mac);
+ if (mac->ops->macaddress_set)
+ mac->ops->macaddress_set(mac, p->dev->dev_addr);
+ t1_set_rxmode(p->dev);
+ t1_link_start(p->phy, mac, &p->link_config);
+ mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+}
+
+static void enable_hw_csum(struct adapter *adapter)
+{
+ if (adapter->flags & TSO_CAPABLE)
+ t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */
+ t1_tp_set_tcp_checksum_offload(adapter, 1);
+}
+
+/*
+ * Things to do upon first use of a card.
+ * This must run with the rtnl lock held.
+ */
+static int cxgb_up(struct adapter *adapter)
+{
+ int err = 0;
+
+ if (!(adapter->flags & FULL_INIT_DONE)) {
+ err = t1_init_hw_modules(adapter);
+ if (err)
+ goto out_err;
+
+ enable_hw_csum(adapter);
+ adapter->flags |= FULL_INIT_DONE;
+ }
+
+ t1_interrupts_clear(adapter);
+ if ((err = request_irq(adapter->pdev->irq,
+ t1_select_intr_handler(adapter), SA_SHIRQ,
+ adapter->name, adapter))) {
+ goto out_err;
+ }
+ t1_sge_start(adapter->sge);
+ t1_interrupts_enable(adapter);
+ out_err:
+ return err;
+}
+
+/*
+ * Release resources when all the ports have been stopped.
+ */
+static void cxgb_down(struct adapter *adapter)
+{
+ t1_sge_stop(adapter->sge);
+ t1_interrupts_disable(adapter);
+ free_irq(adapter->pdev->irq, adapter);
+}
+
+static int cxgb_open(struct net_device *dev)
+{
+ int err;
+ struct adapter *adapter = dev->priv;
+ int other_ports = adapter->open_device_map & PORT_MASK;
+
+ if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0)
+ return err;
+
+ __set_bit(dev->if_port, &adapter->open_device_map);
+ link_start(&adapter->port[dev->if_port]);
+ netif_start_queue(dev);
+ if (!other_ports && adapter->params.stats_update_period)
+ schedule_mac_stats_update(adapter,
+ adapter->params.stats_update_period);
+ return 0;
+}
+
+static int cxgb_close(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct cmac *mac = p->mac;
+
+ netif_stop_queue(dev);
+ mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
+ netif_carrier_off(dev);
+
+ clear_bit(dev->if_port, &adapter->open_device_map);
+ if (adapter->params.stats_update_period &&
+ !(adapter->open_device_map & PORT_MASK)) {
+ /* Stop statistics accumulation. */
+ smp_mb__after_clear_bit();
+ spin_lock(&adapter->work_lock); /* sync with update task */
+ spin_unlock(&adapter->work_lock);
+ cancel_mac_stats_update(adapter);
+ }
+
+ if (!adapter->open_device_map)
+ cxgb_down(adapter);
+ return 0;
+}
+
+static struct net_device_stats *t1_get_stats(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct net_device_stats *ns = &p->netstats;
+ const struct cmac_statistics *pstats;
+
+ /* Do a full update of the MAC stats */
+ pstats = p->mac->ops->statistics_update(p->mac,
+ MAC_STATS_UPDATE_FULL);
+
+ ns->tx_packets = pstats->TxUnicastFramesOK +
+ pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
+
+ ns->rx_packets = pstats->RxUnicastFramesOK +
+ pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
+
+ ns->tx_bytes = pstats->TxOctetsOK;
+ ns->rx_bytes = pstats->RxOctetsOK;
+
+ ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
+ pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
+ ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
+ pstats->RxFCSErrors + pstats->RxAlignErrors +
+ pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
+ pstats->RxSymbolErrors + pstats->RxRuntErrors;
+
+ ns->multicast = pstats->RxMulticastFramesOK;
+ ns->collisions = pstats->TxTotalCollisions;
+
+ /* detailed rx_errors */
+ ns->rx_length_errors = pstats->RxFrameTooLongErrors +
+ pstats->RxJabberErrors;
+ ns->rx_over_errors = 0;
+ ns->rx_crc_errors = pstats->RxFCSErrors;
+ ns->rx_frame_errors = pstats->RxAlignErrors;
+ ns->rx_fifo_errors = 0;
+ ns->rx_missed_errors = 0;
+
+ /* detailed tx_errors */
+ ns->tx_aborted_errors = pstats->TxFramesAbortedDueToXSCollisions;
+ ns->tx_carrier_errors = 0;
+ ns->tx_fifo_errors = pstats->TxUnderrun;
+ ns->tx_heartbeat_errors = 0;
+ ns->tx_window_errors = pstats->TxLateCollisions;
+ return ns;
+}
+
+static u32 get_msglevel(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+
+ return adapter->msg_enable;
+}
+
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+ struct adapter *adapter = dev->priv;
+
+ adapter->msg_enable = val;
+}
+
+static char stats_strings[][ETH_GSTRING_LEN] = {
+ "TxOctetsOK",
+ "TxOctetsBad",
+ "TxUnicastFramesOK",
+ "TxMulticastFramesOK",
+ "TxBroadcastFramesOK",
+ "TxPauseFrames",
+ "TxFramesWithDeferredXmissions",
+ "TxLateCollisions",
+ "TxTotalCollisions",
+ "TxFramesAbortedDueToXSCollisions",
+ "TxUnderrun",
+ "TxLengthErrors",
+ "TxInternalMACXmitError",
+ "TxFramesWithExcessiveDeferral",
+ "TxFCSErrors",
+
+ "RxOctetsOK",
+ "RxOctetsBad",
+ "RxUnicastFramesOK",
+ "RxMulticastFramesOK",
+ "RxBroadcastFramesOK",
+ "RxPauseFrames",
+ "RxFCSErrors",
+ "RxAlignErrors",
+ "RxSymbolErrors",
+ "RxDataErrors",
+ "RxSequenceErrors",
+ "RxRuntErrors",
+ "RxJabberErrors",
+ "RxInternalMACRcvError",
+ "RxInRangeLengthErrors",
+ "RxOutOfRangeLengthField",
+ "RxFrameTooLongErrors",
+
+ "TSO",
+ "VLANextractions",
+ "VLANinsertions",
+ "RxCsumGood",
+ "TxCsumOffload",
+ "RxDrops"
+
+ "respQ_empty",
+ "respQ_overflow",
+ "freelistQ_empty",
+ "pkt_too_big",
+ "pkt_mismatch",
+ "cmdQ_full0",
+ "cmdQ_full1",
+ "tx_ipfrags",
+ "tx_reg_pkts",
+ "tx_lso_pkts",
+ "tx_do_cksum",
+
+ "espi_DIP2ParityErr",
+ "espi_DIP4Err",
+ "espi_RxDrops",
+ "espi_TxDrops",
+ "espi_RxOvfl",
+ "espi_ParityErr"
+};
+
+#define T2_REGMAP_SIZE (3 * 1024)
+
+static int get_regs_len(struct net_device *dev)
+{
+ return T2_REGMAP_SIZE;
+}
+
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct adapter *adapter = dev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, pci_name(adapter->pdev));
+}
+
+static int get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(stats_strings);
+}
+
+static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ if (stringset == ETH_SS_STATS)
+ memcpy(data, stats_strings, sizeof(stats_strings));
+}
+
+static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
+ u64 *data)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ const struct cmac_statistics *s;
+ const struct sge_port_stats *ss;
+ const struct sge_intr_counts *t;
+
+ s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
+ ss = t1_sge_get_port_stats(adapter->sge, dev->if_port);
+ t = t1_sge_get_intr_counts(adapter->sge);
+
+ *data++ = s->TxOctetsOK;
+ *data++ = s->TxOctetsBad;
+ *data++ = s->TxUnicastFramesOK;
+ *data++ = s->TxMulticastFramesOK;
+ *data++ = s->TxBroadcastFramesOK;
+ *data++ = s->TxPauseFrames;
+ *data++ = s->TxFramesWithDeferredXmissions;
+ *data++ = s->TxLateCollisions;
+ *data++ = s->TxTotalCollisions;
+ *data++ = s->TxFramesAbortedDueToXSCollisions;
+ *data++ = s->TxUnderrun;
+ *data++ = s->TxLengthErrors;
+ *data++ = s->TxInternalMACXmitError;
+ *data++ = s->TxFramesWithExcessiveDeferral;
+ *data++ = s->TxFCSErrors;
+
+ *data++ = s->RxOctetsOK;
+ *data++ = s->RxOctetsBad;
+ *data++ = s->RxUnicastFramesOK;
+ *data++ = s->RxMulticastFramesOK;
+ *data++ = s->RxBroadcastFramesOK;
+ *data++ = s->RxPauseFrames;
+ *data++ = s->RxFCSErrors;
+ *data++ = s->RxAlignErrors;
+ *data++ = s->RxSymbolErrors;
+ *data++ = s->RxDataErrors;
+ *data++ = s->RxSequenceErrors;
+ *data++ = s->RxRuntErrors;
+ *data++ = s->RxJabberErrors;
+ *data++ = s->RxInternalMACRcvError;
+ *data++ = s->RxInRangeLengthErrors;
+ *data++ = s->RxOutOfRangeLengthField;
+ *data++ = s->RxFrameTooLongErrors;
+
+ *data++ = ss->tso;
+ *data++ = ss->vlan_xtract;
+ *data++ = ss->vlan_insert;
+ *data++ = ss->rx_cso_good;
+ *data++ = ss->tx_cso;
+ *data++ = ss->rx_drops;
+
+ *data++ = (u64)t->respQ_empty;
+ *data++ = (u64)t->respQ_overflow;
+ *data++ = (u64)t->freelistQ_empty;
+ *data++ = (u64)t->pkt_too_big;
+ *data++ = (u64)t->pkt_mismatch;
+ *data++ = (u64)t->cmdQ_full[0];
+ *data++ = (u64)t->cmdQ_full[1];
+ *data++ = (u64)t->tx_ipfrags;
+ *data++ = (u64)t->tx_reg_pkts;
+ *data++ = (u64)t->tx_lso_pkts;
+ *data++ = (u64)t->tx_do_cksum;
+}
+
+static inline void reg_block_dump(struct adapter *ap, void *buf,
+ unsigned int start, unsigned int end)
+{
+ u32 *p = buf + start;
+
+ for ( ; start <= end; start += sizeof(u32))
+ *p++ = readl(ap->regs + start);
+}
+
+static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *buf)
+{
+ struct adapter *ap = dev->priv;
+
+ /*
+ * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
+ */
+ regs->version = 2;
+
+ memset(buf, 0, T2_REGMAP_SIZE);
+ reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
+}
+
+static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+
+ cmd->supported = p->link_config.supported;
+ cmd->advertising = p->link_config.advertising;
+
+ if (netif_carrier_ok(dev)) {
+ cmd->speed = p->link_config.speed;
+ cmd->duplex = p->link_config.duplex;
+ } else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+
+ cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
+ cmd->phy_address = p->phy->addr;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = p->link_config.autoneg;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+ return 0;
+}
+
+static int speed_duplex_to_caps(int speed, int duplex)
+{
+ int cap = 0;
+
+ switch (speed) {
+ case SPEED_10:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_10baseT_Full;
+ else
+ cap = SUPPORTED_10baseT_Half;
+ break;
+ case SPEED_100:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_100baseT_Full;
+ else
+ cap = SUPPORTED_100baseT_Half;
+ break;
+ case SPEED_1000:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_1000baseT_Full;
+ else
+ cap = SUPPORTED_1000baseT_Half;
+ break;
+ case SPEED_10000:
+ if (duplex == DUPLEX_FULL)
+ cap = SUPPORTED_10000baseT_Full;
+ }
+ return cap;
+}
+
+#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
+ ADVERTISED_10000baseT_Full)
+
+static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct link_config *lc = &p->link_config;
+
+ if (!(lc->supported & SUPPORTED_Autoneg))
+ return -EOPNOTSUPP; /* can't change speed/duplex */
+
+ if (cmd->autoneg == AUTONEG_DISABLE) {
+ int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
+
+ if (!(lc->supported & cap) || cmd->speed == SPEED_1000)
+ return -EINVAL;
+ lc->requested_speed = cmd->speed;
+ lc->requested_duplex = cmd->duplex;
+ lc->advertising = 0;
+ } else {
+ cmd->advertising &= ADVERTISED_MASK;
+ if (cmd->advertising & (cmd->advertising - 1))
+ cmd->advertising = lc->supported;
+ cmd->advertising &= lc->supported;
+ if (!cmd->advertising)
+ return -EINVAL;
+ lc->requested_speed = SPEED_INVALID;
+ lc->requested_duplex = DUPLEX_INVALID;
+ lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
+ }
+ lc->autoneg = cmd->autoneg;
+ if (netif_running(dev))
+ t1_link_start(p->phy, p->mac, lc);
+ return 0;
+}
+
+static void get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+
+ epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
+ epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
+ epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
+}
+
+static int set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct adapter *adapter = dev->priv;
+ struct port_info *p = &adapter->port[dev->if_port];
+ struct link_config *lc = &p->link_config;
+
+ if (epause->autoneg == AUTONEG_DISABLE)
+ lc->requested_fc = 0;
+ else if (lc->supported & SUPPORTED_Autoneg)
+ lc->requested_fc = PAUSE_AUTONEG;
+ else
+ return -EINVAL;
+
+ if (epause->rx_pause)
+ lc->requested_fc |= PAUSE_RX;
+ if (epause->tx_pause)
+ lc->requested_fc |= PAUSE_TX;
+ if (lc->autoneg == AUTONEG_ENABLE) {
+ if (netif_running(dev))
+ t1_link_start(p->phy, p->mac, lc);
+ } else {
+ lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+ if (netif_running(dev))
+ p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
+ lc->fc);
+ }
+ return 0;
+}
+
+static u32 get_rx_csum(struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+
+ return (adapter->flags & RX_CSUM_ENABLED) != 0;
+}
+
+static int set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct adapter *adapter = dev->priv;
+
+ if (data)
+ adapter->flags |= RX_CSUM_ENABLED;
+ else
+ adapter->flags &= ~RX_CSUM_ENABLED;
+ return 0;
+}
+
+static int set_tso(struct net_device *dev, u32 value)
+{
+ struct adapter *adapter = dev->priv;
+
+ if (!(adapter->flags & TSO_CAPABLE))
+ return value ? -EOPNOTSUPP : 0;
+ return ethtool_op_set_tso(dev, value);
+}
+
+static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
+{
+ struct adapter *adapter = dev->priv;
+ int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ e->rx_max_pending = MAX_RX_BUFFERS;
+ e->rx_mini_max_pending = 0;
+ e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
+ e->tx_max_pending = MAX_CMDQ_ENTRIES;
+
+ e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
+ e->rx_mini_pending = 0;
+ e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
+ e->tx_pending = adapter->params.sge.cmdQ_size[0];
+}
+
+static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
+{
+ struct adapter *adapter = dev->priv;
+ int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
+ e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
+ e->tx_pending > MAX_CMDQ_ENTRIES ||
+ e->rx_pending < MIN_FL_ENTRIES ||
+ e->rx_jumbo_pending < MIN_FL_ENTRIES ||
+ e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
+ return -EINVAL;
+
+ if (adapter->flags & FULL_INIT_DONE)
+ return -EBUSY;
+
+ adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
+ adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
+ adapter->params.sge.cmdQ_size[0] = e->tx_pending;
+ adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
+ MAX_CMDQ1_ENTRIES : e->tx_pending;
+ return 0;
+}
+
+static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+{
+ struct adapter *adapter = dev->priv;
+
+ /*
+ * If RX coalescing is requested we use NAPI, otherwise interrupts.
+ * This choice can be made only when all ports and the TOE are off.
+ */
+ if (adapter->open_device_map == 0)
+ adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
+
+ if (adapter->params.sge.polling) {
+ adapter->params.sge.rx_coalesce_usecs = 0;
+ } else {
+ adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
+ }
+ adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
+ adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
+ t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
+ return 0;
+}
+
+static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
+{
+ struct adapter *adapter = dev->priv;
+
+ c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
+ c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
+ c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
+ return 0;
+}
+
+static int get_eeprom_len(struct net_device *dev)
+{
+ return EEPROM_SIZE;
+}
+
+#define EEPROM_MAGIC(ap) \
+ (PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
+
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
+ u8 *data)
+{
+ int i;
+ u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
+ struct adapter *adapter = dev->priv;
+
+ e->magic = EEPROM_MAGIC(adapter);
+ for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
+ t1_seeprom_read(adapter, i, (u32 *)&buf[i]);
+ memcpy(data, buf + e->offset, e->len);
+ return 0;
+}
+
+static struct ethtool_ops t1_ethtool_ops = {
+ .get_settings = get_settings,
+ .set_settings = set_settings,
+ .get_drvinfo = get_drvinfo,
+ .get_msglevel = get_msglevel,
+ .set_msglevel = set_msglevel,
+ .get_ringparam = get_sge_param,
+ .set_ringparam = set_sge_param,
+ .get_coalesce = get_coalesce,
+ .set_coalesce = set_coalesce,
+ .get_eeprom_len = get_eeprom_len,
+ .get_eeprom = get_eeprom,
+ .get_pauseparam = get_pauseparam,
+ .set_pauseparam = set_pauseparam,
+ .get_rx_csum = get_rx_csum,
+ .set_rx_csum = set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_link = ethtool_op_get_link,
+ .get_strings = get_strings,
+ .get_stats_count = get_stats_count,
+ .get_ethtool_stats = get_stats,
+ .get_regs_len = get_regs_len,
+ .get_regs = get_regs,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = set_tso,
+};
+
+static void cxgb_proc_cleanup(struct adapter *adapter,
+ struct proc_dir_entry *dir)
+{
+ const char *name;
+ name = adapter->name;
+ remove_proc_entry(name, dir);
+}
+//#define chtoe_setup_toedev(adapter) NULL
+#define update_mtu_tab(adapter)
+#define write_smt_entry(adapter, idx)
+
+static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct adapter *adapter = dev->priv;
+ struct mii_ioctl_data *data = if_mii(req);
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = adapter->port[dev->if_port].phy->addr;
+ /* FALLTHRU */
+ case SIOCGMIIREG: {
+ struct cphy *phy = adapter->port[dev->if_port].phy;
+ u32 val;
+
+ if (!phy->mdio_read)
+ return -EOPNOTSUPP;
+ phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
+ &val);
+ data->val_out = val;
+ break;
+ }
+ case SIOCSMIIREG: {
+ struct cphy *phy = adapter->port[dev->if_port].phy;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (!phy->mdio_write)
+ return -EOPNOTSUPP;
+ phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
+ data->val_in);
+ break;
+ }
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int t1_change_mtu(struct net_device *dev, int new_mtu)
+{
+ int ret;
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+
+ if (!mac->ops->set_mtu)
+ return -EOPNOTSUPP;
+ if (new_mtu < 68)
+ return -EINVAL;
+ if ((ret = mac->ops->set_mtu(mac, new_mtu)))
+ return ret;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static int t1_set_mac_addr(struct net_device *dev, void *p)
+{
+ struct adapter *adapter = dev->priv;
+ struct cmac *mac = adapter->port[dev->if_port].mac;
+ struct sockaddr *addr = p;
+
+ if (!mac->ops->macaddress_set)
+ return -EOPNOTSUPP;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ mac->ops->macaddress_set(mac, dev->dev_addr);
+ return 0;
+}
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+static void vlan_rx_register(struct net_device *dev,
+ struct vlan_group *grp)
+{
+ struct adapter *adapter = dev->priv;
+
+ spin_lock_irq(&adapter->async_lock);
+ adapter->vlan_grp = grp;
+ t1_set_vlan_accel(adapter, grp != NULL);
+ spin_unlock_irq(&adapter->async_lock);
+}
+
+static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct adapter *adapter = dev->priv;
+
+ spin_lock_irq(&adapter->async_lock);
+ if (adapter->vlan_grp)
+ adapter->vlan_grp->vlan_devices[vid] = NULL;
+ spin_unlock_irq(&adapter->async_lock);
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void t1_netpoll(struct net_device *dev)
+{
+ unsigned long flags;
+ struct adapter *adapter = dev->priv;
+
+ local_irq_save(flags);
+ t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter, NULL);
+ local_irq_restore(flags);
+}
+#endif
+
+/*
+ * Periodic accumulation of MAC statistics. This is used only if the MAC
+ * does not have any other way to prevent stats counter overflow.
+ */
+static void mac_stats_task(void *data)
+{
+ int i;
+ struct adapter *adapter = data;
+
+ for_each_port(adapter, i) {
+ struct port_info *p = &adapter->port[i];
+
+ if (netif_running(p->dev))
+ p->mac->ops->statistics_update(p->mac,
+ MAC_STATS_UPDATE_FAST);
+ }
+
+ /* Schedule the next statistics update if any port is active. */
+ spin_lock(&adapter->work_lock);
+ if (adapter->open_device_map & PORT_MASK)
+ schedule_mac_stats_update(adapter,
+ adapter->params.stats_update_period);
+ spin_unlock(&adapter->work_lock);
+}
+
+/*
+ * Processes elmer0 external interrupts in process context.
+ */
+static void ext_intr_task(void *data)
+{
+ struct adapter *adapter = data;
+
+ elmer0_ext_intr_handler(adapter);
+
+ /* Now reenable external interrupts */
+ spin_lock_irq(&adapter->async_lock);
+ adapter->slow_intr_mask |= F_PL_INTR_EXT;
+ writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
+ writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+ adapter->regs + A_PL_ENABLE);
+ spin_unlock_irq(&adapter->async_lock);
+}
+
+/*
+ * Interrupt-context handler for elmer0 external interrupts.
+ */
+void t1_elmer0_ext_intr(struct adapter *adapter)
+{
+ /*
+ * Schedule a task to handle external interrupts as we require
+ * a process context. We disable EXT interrupts in the interim
+ * and let the task reenable them when it's done.
+ */
+ adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
+ writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+ adapter->regs + A_PL_ENABLE);
+ schedule_work(&adapter->ext_intr_handler_task);
+}
+
+void t1_fatal_err(struct adapter *adapter)
+{
+ if (adapter->flags & FULL_INIT_DONE) {
+ t1_sge_stop(adapter->sge);
+ t1_interrupts_disable(adapter);
+ }
+ CH_ALERT("%s: encountered fatal error, operation suspended\n",
+ adapter->name);
+}
+
+static int __devinit init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int version_printed;
+
+ int i, err, pci_using_dac = 0;
+ unsigned long mmio_start, mmio_len;
+ const struct board_info *bi;
+ struct adapter *adapter = NULL;
+ struct port_info *pi;
+
+ if (!version_printed) {
+ printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
+ DRV_VERSION);
+ ++version_printed;
+ }
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ CH_ERR("%s: cannot find PCI device memory base address\n",
+ pci_name(pdev));
+ err = -ENODEV;
+ goto out_disable_pdev;
+ }
+
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ pci_using_dac = 1;
+
+ if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
+ CH_ERR("%s: unable to obtain 64-bit DMA for"
+ "consistent allocations\n", pci_name(pdev));
+ err = -ENODEV;
+ goto out_disable_pdev;
+ }
+
+ } else if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
+ CH_ERR("%s: no usable DMA configuration\n", pci_name(pdev));
+ goto out_disable_pdev;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ CH_ERR("%s: cannot obtain PCI resources\n", pci_name(pdev));
+ goto out_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ mmio_start = pci_resource_start(pdev, 0);
+ mmio_len = pci_resource_len(pdev, 0);
+ bi = t1_get_board_info(ent->driver_data);
+
+ for (i = 0; i < bi->port_number; ++i) {
+ struct net_device *netdev;
+
+ netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto out_free_dev;
+ }
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ if (!adapter) {
+ adapter = netdev->priv;
+ adapter->pdev = pdev;
+ adapter->port[0].dev = netdev; /* so we don't leak it */
+
+ adapter->regs = ioremap(mmio_start, mmio_len);
+ if (!adapter->regs) {
+ CH_ERR("%s: cannot map device registers\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto out_free_dev;
+ }
+
+ if (t1_get_board_rev(adapter, bi, &adapter->params)) {
+ err = -ENODEV; /* Can't handle this chip rev */
+ goto out_free_dev;
+ }
+
+ adapter->name = pci_name(pdev);
+ adapter->msg_enable = dflt_msg_enable;
+ adapter->mmio_len = mmio_len;
+
+ init_MUTEX(&adapter->mib_mutex);
+ spin_lock_init(&adapter->tpi_lock);
+ spin_lock_init(&adapter->work_lock);
+ spin_lock_init(&adapter->async_lock);
+
+ INIT_WORK(&adapter->ext_intr_handler_task,
+ ext_intr_task, adapter);
+ INIT_WORK(&adapter->stats_update_task, mac_stats_task,
+ adapter);
+#ifdef work_struct
+ init_timer(&adapter->stats_update_timer);
+ adapter->stats_update_timer.function = mac_stats_timer;
+ adapter->stats_update_timer.data =
+ (unsigned long)adapter;
+#endif
+
+ pci_set_drvdata(pdev, netdev);
+ }
+
+ pi = &adapter->port[i];
+ pi->dev = netdev;
+ netif_carrier_off(netdev);
+ netdev->irq = pdev->irq;
+ netdev->if_port = i;
+ netdev->mem_start = mmio_start;
+ netdev->mem_end = mmio_start + mmio_len - 1;
+ netdev->priv = adapter;
+ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_LLTX;
+
+ adapter->flags |= RX_CSUM_ENABLED | TCP_CSUM_CAPABLE;
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+ if (vlan_tso_capable(adapter)) {
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ adapter->flags |= VLAN_ACCEL_CAPABLE;
+ netdev->features |=
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->vlan_rx_register = vlan_rx_register;
+ netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
+#endif
+ adapter->flags |= TSO_CAPABLE;
+ netdev->features |= NETIF_F_TSO;
+ }
+
+ netdev->open = cxgb_open;
+ netdev->stop = cxgb_close;
+ netdev->hard_start_xmit = t1_start_xmit;
+ netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
+ sizeof(struct cpl_tx_pkt_lso) :
+ sizeof(struct cpl_tx_pkt);
+ netdev->get_stats = t1_get_stats;
+ netdev->set_multicast_list = t1_set_rxmode;
+ netdev->do_ioctl = t1_ioctl;
+ netdev->change_mtu = t1_change_mtu;
+ netdev->set_mac_address = t1_set_mac_addr;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = t1_netpoll;
+#endif
+ netdev->weight = 64;
+
+ SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
+ }
+
+ if (t1_init_sw_modules(adapter, bi) < 0) {
+ err = -ENODEV;
+ goto out_free_dev;
+ }
+
+ /*
+ * The card is now ready to go. If any errors occur during device
+ * registration we do not fail the whole card but rather proceed only
+ * with the ports we manage to register successfully. However we must
+ * register at least one net device.
+ */
+ for (i = 0; i < bi->port_number; ++i) {
+ err = register_netdev(adapter->port[i].dev);
+ if (err)
+ CH_WARN("%s: cannot register net device %s, skipping\n",
+ pci_name(pdev), adapter->port[i].dev->name);
+ else {
+ /*
+ * Change the name we use for messages to the name of
+ * the first successfully registered interface.
+ */
+ if (!adapter->registered_device_map)
+ adapter->name = adapter->port[i].dev->name;
+
+ __set_bit(i, &adapter->registered_device_map);
+ }
+ }
+ if (!adapter->registered_device_map) {
+ CH_ERR("%s: could not register any net devices\n",
+ pci_name(pdev));
+ goto out_release_adapter_res;
+ }
+
+ printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
+ bi->desc, adapter->params.chip_revision,
+ adapter->params.pci.is_pcix ? "PCIX" : "PCI",
+ adapter->params.pci.speed, adapter->params.pci.width);
+ return 0;
+
+ out_release_adapter_res:
+ t1_free_sw_modules(adapter);
+ out_free_dev:
+ if (adapter) {
+ if (adapter->regs) iounmap(adapter->regs);
+ for (i = bi->port_number - 1; i >= 0; --i)
+ if (adapter->port[i].dev) {
+ cxgb_proc_cleanup(adapter, proc_root_driver);
+ kfree(adapter->port[i].dev);
+ }
+ }
+ pci_release_regions(pdev);
+ out_disable_pdev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static inline void t1_sw_reset(struct pci_dev *pdev)
+{
+ pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
+ pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
+}
+
+static void __devexit remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (dev) {
+ int i;
+ struct adapter *adapter = dev->priv;
+
+ for_each_port(adapter, i)
+ if (test_bit(i, &adapter->registered_device_map))
+ unregister_netdev(adapter->port[i].dev);
+
+ t1_free_sw_modules(adapter);
+ iounmap(adapter->regs);
+ while (--i >= 0)
+ if (adapter->port[i].dev) {
+ cxgb_proc_cleanup(adapter, proc_root_driver);
+ kfree(adapter->port[i].dev);
+ }
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ t1_sw_reset(pdev);
+ }
+}
+
+static struct pci_driver driver = {
+ .name = DRV_NAME,
+ .id_table = t1_pci_tbl,
+ .probe = init_one,
+ .remove = __devexit_p(remove_one),
+};
+
+static int __init t1_init_module(void)
+{
+ return pci_module_init(&driver);
+}
+
+static void __exit t1_cleanup_module(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(t1_init_module);
+module_exit(t1_cleanup_module);
diff --git a/drivers/net/chelsio/elmer0.h b/drivers/net/chelsio/elmer0.h
new file mode 100644
index 000000000000..5590cb2dac19
--- /dev/null
+++ b/drivers/net/chelsio/elmer0.h
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ * *
+ * File: elmer0.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 22:49:43 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_ELMER0_H_
+#define _CXGB_ELMER0_H_
+
+/* ELMER0 registers */
+#define A_ELMER0_VERSION 0x100000
+#define A_ELMER0_PHY_CFG 0x100004
+#define A_ELMER0_INT_ENABLE 0x100008
+#define A_ELMER0_INT_CAUSE 0x10000c
+#define A_ELMER0_GPI_CFG 0x100010
+#define A_ELMER0_GPI_STAT 0x100014
+#define A_ELMER0_GPO 0x100018
+#define A_ELMER0_PORT0_MI1_CFG 0x400000
+
+#define S_MI1_MDI_ENABLE 0
+#define V_MI1_MDI_ENABLE(x) ((x) << S_MI1_MDI_ENABLE)
+#define F_MI1_MDI_ENABLE V_MI1_MDI_ENABLE(1U)
+
+#define S_MI1_MDI_INVERT 1
+#define V_MI1_MDI_INVERT(x) ((x) << S_MI1_MDI_INVERT)
+#define F_MI1_MDI_INVERT V_MI1_MDI_INVERT(1U)
+
+#define S_MI1_PREAMBLE_ENABLE 2
+#define V_MI1_PREAMBLE_ENABLE(x) ((x) << S_MI1_PREAMBLE_ENABLE)
+#define F_MI1_PREAMBLE_ENABLE V_MI1_PREAMBLE_ENABLE(1U)
+
+#define S_MI1_SOF 3
+#define M_MI1_SOF 0x3
+#define V_MI1_SOF(x) ((x) << S_MI1_SOF)
+#define G_MI1_SOF(x) (((x) >> S_MI1_SOF) & M_MI1_SOF)
+
+#define S_MI1_CLK_DIV 5
+#define M_MI1_CLK_DIV 0xff
+#define V_MI1_CLK_DIV(x) ((x) << S_MI1_CLK_DIV)
+#define G_MI1_CLK_DIV(x) (((x) >> S_MI1_CLK_DIV) & M_MI1_CLK_DIV)
+
+#define A_ELMER0_PORT0_MI1_ADDR 0x400004
+
+#define S_MI1_REG_ADDR 0
+#define M_MI1_REG_ADDR 0x1f
+#define V_MI1_REG_ADDR(x) ((x) << S_MI1_REG_ADDR)
+#define G_MI1_REG_ADDR(x) (((x) >> S_MI1_REG_ADDR) & M_MI1_REG_ADDR)
+
+#define S_MI1_PHY_ADDR 5
+#define M_MI1_PHY_ADDR 0x1f
+#define V_MI1_PHY_ADDR(x) ((x) << S_MI1_PHY_ADDR)
+#define G_MI1_PHY_ADDR(x) (((x) >> S_MI1_PHY_ADDR) & M_MI1_PHY_ADDR)
+
+#define A_ELMER0_PORT0_MI1_DATA 0x400008
+
+#define S_MI1_DATA 0
+#define M_MI1_DATA 0xffff
+#define V_MI1_DATA(x) ((x) << S_MI1_DATA)
+#define G_MI1_DATA(x) (((x) >> S_MI1_DATA) & M_MI1_DATA)
+
+#define A_ELMER0_PORT0_MI1_OP 0x40000c
+
+#define S_MI1_OP 0
+#define M_MI1_OP 0x3
+#define V_MI1_OP(x) ((x) << S_MI1_OP)
+#define G_MI1_OP(x) (((x) >> S_MI1_OP) & M_MI1_OP)
+
+#define S_MI1_ADDR_AUTOINC 2
+#define V_MI1_ADDR_AUTOINC(x) ((x) << S_MI1_ADDR_AUTOINC)
+#define F_MI1_ADDR_AUTOINC V_MI1_ADDR_AUTOINC(1U)
+
+#define S_MI1_OP_BUSY 31
+#define V_MI1_OP_BUSY(x) ((x) << S_MI1_OP_BUSY)
+#define F_MI1_OP_BUSY V_MI1_OP_BUSY(1U)
+
+#define A_ELMER0_PORT1_MI1_CFG 0x500000
+#define A_ELMER0_PORT1_MI1_ADDR 0x500004
+#define A_ELMER0_PORT1_MI1_DATA 0x500008
+#define A_ELMER0_PORT1_MI1_OP 0x50000c
+#define A_ELMER0_PORT2_MI1_CFG 0x600000
+#define A_ELMER0_PORT2_MI1_ADDR 0x600004
+#define A_ELMER0_PORT2_MI1_DATA 0x600008
+#define A_ELMER0_PORT2_MI1_OP 0x60000c
+#define A_ELMER0_PORT3_MI1_CFG 0x700000
+#define A_ELMER0_PORT3_MI1_ADDR 0x700004
+#define A_ELMER0_PORT3_MI1_DATA 0x700008
+#define A_ELMER0_PORT3_MI1_OP 0x70000c
+
+/* Simple bit definition for GPI and GP0 registers. */
+#define ELMER0_GP_BIT0 0x0001
+#define ELMER0_GP_BIT1 0x0002
+#define ELMER0_GP_BIT2 0x0004
+#define ELMER0_GP_BIT3 0x0008
+#define ELMER0_GP_BIT4 0x0010
+#define ELMER0_GP_BIT5 0x0020
+#define ELMER0_GP_BIT6 0x0040
+#define ELMER0_GP_BIT7 0x0080
+#define ELMER0_GP_BIT8 0x0100
+#define ELMER0_GP_BIT9 0x0200
+#define ELMER0_GP_BIT10 0x0400
+#define ELMER0_GP_BIT11 0x0800
+#define ELMER0_GP_BIT12 0x1000
+#define ELMER0_GP_BIT13 0x2000
+#define ELMER0_GP_BIT14 0x4000
+#define ELMER0_GP_BIT15 0x8000
+#define ELMER0_GP_BIT16 0x10000
+#define ELMER0_GP_BIT17 0x20000
+#define ELMER0_GP_BIT18 0x40000
+#define ELMER0_GP_BIT19 0x80000
+
+#define MI1_OP_DIRECT_WRITE 1
+#define MI1_OP_DIRECT_READ 2
+
+#define MI1_OP_INDIRECT_ADDRESS 0
+#define MI1_OP_INDIRECT_WRITE 1
+#define MI1_OP_INDIRECT_READ_INC 2
+#define MI1_OP_INDIRECT_READ 3
+
+#endif /* _CXGB_ELMER0_H_ */
diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c
new file mode 100644
index 000000000000..230642571c92
--- /dev/null
+++ b/drivers/net/chelsio/espi.c
@@ -0,0 +1,346 @@
+/*****************************************************************************
+ * *
+ * File: espi.c *
+ * $Revision: 1.14 $ *
+ * $Date: 2005/05/14 00:59:32 $ *
+ * Description: *
+ * Ethernet SPI functionality. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "regs.h"
+#include "espi.h"
+
+struct peespi {
+ adapter_t *adapter;
+ struct espi_intr_counts intr_cnt;
+ u32 misc_ctrl;
+ spinlock_t lock;
+};
+
+#define ESPI_INTR_MASK (F_DIP4ERR | F_RXDROP | F_TXDROP | F_RXOVERFLOW | \
+ F_RAMPARITYERR | F_DIP2PARITYERR)
+#define MON_MASK (V_MONITORED_PORT_NUM(3) | F_MONITORED_DIRECTION \
+ | F_MONITORED_INTERFACE)
+
+#define TRICN_CNFG 14
+#define TRICN_CMD_READ 0x11
+#define TRICN_CMD_WRITE 0x21
+#define TRICN_CMD_ATTEMPTS 10
+
+static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
+ int ch_addr, int reg_offset, u32 wr_data)
+{
+ int busy, attempts = TRICN_CMD_ATTEMPTS;
+
+ writel(V_WRITE_DATA(wr_data) |
+ V_REGISTER_OFFSET(reg_offset) |
+ V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
+ V_BUNDLE_ADDR(bundle_addr) |
+ V_SPI4_COMMAND(TRICN_CMD_WRITE),
+ adapter->regs + A_ESPI_CMD_ADDR);
+ writel(0, adapter->regs + A_ESPI_GOSTAT);
+
+ do {
+ busy = readl(adapter->regs + A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
+ } while (busy && --attempts);
+
+ if (busy)
+ CH_ERR("%s: TRICN write timed out\n", adapter->name);
+
+ return busy;
+}
+
+/* 1. Deassert rx_reset_core. */
+/* 2. Program TRICN_CNFG registers. */
+/* 3. Deassert rx_reset_link */
+static int tricn_init(adapter_t *adapter)
+{
+ int i = 0;
+ int sme = 1;
+ int stat = 0;
+ int timeout = 0;
+ int is_ready = 0;
+ int dynamic_deskew = 0;
+
+ if (dynamic_deskew)
+ sme = 0;
+
+
+ /* 1 */
+ timeout=1000;
+ do {
+ stat = readl(adapter->regs + A_ESPI_RX_RESET);
+ is_ready = (stat & 0x4);
+ timeout--;
+ udelay(5);
+ } while (!is_ready || (timeout==0));
+ writel(0x2, adapter->regs + A_ESPI_RX_RESET);
+ if (timeout==0)
+ {
+ CH_ERR("ESPI : ERROR : Timeout tricn_init() \n");
+ t1_fatal_err(adapter);
+ }
+
+ /* 2 */
+ if (sme) {
+ tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
+ tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
+ }
+ for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
+ for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
+ for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ for (i=4; i<= 4; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+ for (i=5; i<= 5; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
+ for (i=6; i<= 6; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+ for (i=7; i<= 7; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0x80);
+ for (i=8; i<= 8; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1);
+
+ /* 3 */
+ writel(0x3, adapter->regs + A_ESPI_RX_RESET);
+
+ return 0;
+}
+
+void t1_espi_intr_enable(struct peespi *espi)
+{
+ u32 enable, pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
+
+ /*
+ * Cannot enable ESPI interrupts on T1B because HW asserts the
+ * interrupt incorrectly, namely the driver gets ESPI interrupts
+ * but no data is actually dropped (can verify this reading the ESPI
+ * drop registers). Also, once the ESPI interrupt is asserted it
+ * cannot be cleared (HW bug).
+ */
+ enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
+ writel(enable, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr | F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
+}
+
+void t1_espi_intr_clear(struct peespi *espi)
+{
+ writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
+ writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
+}
+
+void t1_espi_intr_disable(struct peespi *espi)
+{
+ u32 pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
+
+ writel(0, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ writel(pl_intr & ~F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
+}
+
+int t1_espi_intr_handler(struct peespi *espi)
+{
+ u32 cnt;
+ u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
+
+ if (status & F_DIP4ERR)
+ espi->intr_cnt.DIP4_err++;
+ if (status & F_RXDROP)
+ espi->intr_cnt.rx_drops++;
+ if (status & F_TXDROP)
+ espi->intr_cnt.tx_drops++;
+ if (status & F_RXOVERFLOW)
+ espi->intr_cnt.rx_ovflw++;
+ if (status & F_RAMPARITYERR)
+ espi->intr_cnt.parity_err++;
+ if (status & F_DIP2PARITYERR) {
+ espi->intr_cnt.DIP2_parity_err++;
+
+ /*
+ * Must read the error count to clear the interrupt
+ * that it causes.
+ */
+ cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ }
+
+ /*
+ * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
+ * write the status as is.
+ */
+ if (status && t1_is_T1B(espi->adapter))
+ status = 1;
+ writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
+ return 0;
+}
+
+const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
+{
+ return &espi->intr_cnt;
+}
+
+static void espi_setup_for_pm3393(adapter_t *adapter)
+{
+ u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
+
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN1);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
+ writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(0x100, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
+ writel(wmark, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
+ writel(3, adapter->regs + A_ESPI_CALENDAR_LENGTH);
+ writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
+ writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
+}
+
+/* T2 Init part -- */
+/* 1. Set T_ESPI_MISCCTRL_ADDR */
+/* 2. Init ESPI registers. */
+/* 3. Init TriCN Hard Macro */
+int t1_espi_init(struct peespi *espi, int mac_type, int nports)
+{
+ u32 cnt;
+
+ u32 status_enable_extra = 0;
+ adapter_t *adapter = espi->adapter;
+ u32 status, burstval = 0x800100;
+
+ /* Disable ESPI training. MACs that can handle it enable it below. */
+ writel(0, adapter->regs + A_ESPI_TRAIN);
+
+ if (is_T2(adapter)) {
+ writel(V_OUT_OF_SYNC_COUNT(4) |
+ V_DIP2_PARITY_ERR_THRES(3) |
+ V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
+ if (nports == 4) {
+ /* T204: maxburst1 = 0x40, maxburst2 = 0x20 */
+ burstval = 0x200040;
+ }
+ }
+ writel(burstval, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
+
+ switch (mac_type) {
+ case CHBT_MAC_PM3393:
+ espi_setup_for_pm3393(adapter);
+ break;
+ default:
+ return -1;
+ }
+
+ /*
+ * Make sure any pending interrupts from the SPI are
+ * Cleared before enabling the interrupt.
+ */
+ writel(ESPI_INTR_MASK, espi->adapter->regs + A_ESPI_INTR_ENABLE);
+ status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
+ if (status & F_DIP2PARITYERR) {
+ cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
+ }
+
+ /*
+ * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we
+ * write the status as is.
+ */
+ if (status && t1_is_T1B(espi->adapter))
+ status = 1;
+ writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
+
+ writel(status_enable_extra | F_RXSTATUSENABLE,
+ adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
+
+ if (is_T2(adapter)) {
+ tricn_init(adapter);
+ /*
+ * Always position the control at the 1st port egress IN
+ * (sop,eop) counter to reduce PIOs for T/N210 workaround.
+ */
+ espi->misc_ctrl = (readl(adapter->regs + A_ESPI_MISC_CONTROL)
+ & ~MON_MASK) | (F_MONITORED_DIRECTION
+ | F_MONITORED_INTERFACE);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_lock_init(&espi->lock);
+ }
+
+ return 0;
+}
+
+void t1_espi_destroy(struct peespi *espi)
+{
+ kfree(espi);
+}
+
+struct peespi *t1_espi_create(adapter_t *adapter)
+{
+ struct peespi *espi = kmalloc(sizeof(*espi), GFP_KERNEL);
+
+ memset(espi, 0, sizeof(*espi));
+
+ if (espi)
+ espi->adapter = adapter;
+ return espi;
+}
+
+void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
+{
+ struct peespi *espi = adapter->espi;
+
+ if (!is_T2(adapter))
+ return;
+ spin_lock(&espi->lock);
+ espi->misc_ctrl = (val & ~MON_MASK) |
+ (espi->misc_ctrl & MON_MASK);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ spin_unlock(&espi->lock);
+}
+
+u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
+{
+ u32 sel;
+
+ struct peespi *espi = adapter->espi;
+
+ if (!is_T2(adapter))
+ return 0;
+ sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
+ if (!wait) {
+ if (!spin_trylock(&espi->lock))
+ return 0;
+ }
+ else
+ spin_lock(&espi->lock);
+ if ((sel != (espi->misc_ctrl & MON_MASK))) {
+ writel(((espi->misc_ctrl & ~MON_MASK) | sel),
+ adapter->regs + A_ESPI_MISC_CONTROL);
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
+ }
+ else
+ sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
+ spin_unlock(&espi->lock);
+ return sel;
+}
diff --git a/drivers/net/chelsio/espi.h b/drivers/net/chelsio/espi.h
new file mode 100644
index 000000000000..c90e37f8457c
--- /dev/null
+++ b/drivers/net/chelsio/espi.h
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * *
+ * File: espi.h *
+ * $Revision: 1.7 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_ESPI_H_
+#define _CXGB_ESPI_H_
+
+#include "common.h"
+
+struct espi_intr_counts {
+ unsigned int DIP4_err;
+ unsigned int rx_drops;
+ unsigned int tx_drops;
+ unsigned int rx_ovflw;
+ unsigned int parity_err;
+ unsigned int DIP2_parity_err;
+};
+
+struct peespi;
+
+struct peespi *t1_espi_create(adapter_t *adapter);
+void t1_espi_destroy(struct peespi *espi);
+int t1_espi_init(struct peespi *espi, int mac_type, int nports);
+
+void t1_espi_intr_enable(struct peespi *);
+void t1_espi_intr_clear(struct peespi *);
+void t1_espi_intr_disable(struct peespi *);
+int t1_espi_intr_handler(struct peespi *);
+const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi);
+
+void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val);
+u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait);
+
+#endif /* _CXGB_ESPI_H_ */
diff --git a/drivers/net/chelsio/gmac.h b/drivers/net/chelsio/gmac.h
new file mode 100644
index 000000000000..746b0eeea964
--- /dev/null
+++ b/drivers/net/chelsio/gmac.h
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * *
+ * File: gmac.h *
+ * $Revision: 1.6 $ *
+ * $Date: 2005/06/21 18:29:47 $ *
+ * Description: *
+ * Generic MAC functionality. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_GMAC_H_
+#define _CXGB_GMAC_H_
+
+#include "common.h"
+
+enum { MAC_STATS_UPDATE_FAST, MAC_STATS_UPDATE_FULL };
+enum { MAC_DIRECTION_RX = 1, MAC_DIRECTION_TX = 2 };
+
+struct cmac_statistics {
+ /* Transmit */
+ u64 TxOctetsOK;
+ u64 TxOctetsBad;
+ u64 TxUnicastFramesOK;
+ u64 TxMulticastFramesOK;
+ u64 TxBroadcastFramesOK;
+ u64 TxPauseFrames;
+ u64 TxFramesWithDeferredXmissions;
+ u64 TxLateCollisions;
+ u64 TxTotalCollisions;
+ u64 TxFramesAbortedDueToXSCollisions;
+ u64 TxUnderrun;
+ u64 TxLengthErrors;
+ u64 TxInternalMACXmitError;
+ u64 TxFramesWithExcessiveDeferral;
+ u64 TxFCSErrors;
+
+ /* Receive */
+ u64 RxOctetsOK;
+ u64 RxOctetsBad;
+ u64 RxUnicastFramesOK;
+ u64 RxMulticastFramesOK;
+ u64 RxBroadcastFramesOK;
+ u64 RxPauseFrames;
+ u64 RxFCSErrors;
+ u64 RxAlignErrors;
+ u64 RxSymbolErrors;
+ u64 RxDataErrors;
+ u64 RxSequenceErrors;
+ u64 RxRuntErrors;
+ u64 RxJabberErrors;
+ u64 RxInternalMACRcvError;
+ u64 RxInRangeLengthErrors;
+ u64 RxOutOfRangeLengthField;
+ u64 RxFrameTooLongErrors;
+};
+
+struct cmac_ops {
+ void (*destroy)(struct cmac *);
+ int (*reset)(struct cmac *);
+ int (*interrupt_enable)(struct cmac *);
+ int (*interrupt_disable)(struct cmac *);
+ int (*interrupt_clear)(struct cmac *);
+ int (*interrupt_handler)(struct cmac *);
+
+ int (*enable)(struct cmac *, int);
+ int (*disable)(struct cmac *, int);
+
+ int (*loopback_enable)(struct cmac *);
+ int (*loopback_disable)(struct cmac *);
+
+ int (*set_mtu)(struct cmac *, int mtu);
+ int (*set_rx_mode)(struct cmac *, struct t1_rx_mode *rm);
+
+ int (*set_speed_duplex_fc)(struct cmac *, int speed, int duplex, int fc);
+ int (*get_speed_duplex_fc)(struct cmac *, int *speed, int *duplex,
+ int *fc);
+
+ const struct cmac_statistics *(*statistics_update)(struct cmac *, int);
+
+ int (*macaddress_get)(struct cmac *, u8 mac_addr[6]);
+ int (*macaddress_set)(struct cmac *, u8 mac_addr[6]);
+};
+
+typedef struct _cmac_instance cmac_instance;
+
+struct cmac {
+ struct cmac_statistics stats;
+ adapter_t *adapter;
+ struct cmac_ops *ops;
+ cmac_instance *instance;
+};
+
+struct gmac {
+ unsigned int stats_update_period;
+ struct cmac *(*create)(adapter_t *adapter, int index);
+ int (*reset)(adapter_t *);
+};
+
+extern struct gmac t1_pm3393_ops;
+extern struct gmac t1_chelsio_mac_ops;
+extern struct gmac t1_vsc7321_ops;
+extern struct gmac t1_ixf1010_ops;
+extern struct gmac t1_dummy_mac_ops;
+
+#endif /* _CXGB_GMAC_H_ */
diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c
new file mode 100644
index 000000000000..db5034282782
--- /dev/null
+++ b/drivers/net/chelsio/mv88x201x.c
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ * *
+ * File: mv88x201x.c *
+ * $Revision: 1.12 $ *
+ * $Date: 2005/04/15 19:27:14 $ *
+ * Description: *
+ * Marvell PHY (mv88x201x) functionality. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "cphy.h"
+#include "elmer0.h"
+
+/*
+ * The 88x2010 Rev C. requires some link status registers * to be read
+ * twice in order to get the right values. Future * revisions will fix
+ * this problem and then this macro * can disappear.
+ */
+#define MV88x2010_LINK_STATUS_BUGS 1
+
+static int led_init(struct cphy *cphy)
+{
+ /* Setup the LED registers so we can turn on/off.
+ * Writing these bits maps control to another
+ * register. mmd(0x1) addr(0x7)
+ */
+ mdio_write(cphy, 0x3, 0x8304, 0xdddd);
+ return 0;
+}
+
+static int led_link(struct cphy *cphy, u32 do_enable)
+{
+ u32 led = 0;
+#define LINK_ENABLE_BIT 0x1
+
+ mdio_read(cphy, 0x1, 0x7, &led);
+
+ if (do_enable & LINK_ENABLE_BIT) {
+ led |= LINK_ENABLE_BIT;
+ mdio_write(cphy, 0x1, 0x7, led);
+ } else {
+ led &= ~LINK_ENABLE_BIT;
+ mdio_write(cphy, 0x1, 0x7, led);
+ }
+ return 0;
+}
+
+/* Port Reset */
+static int mv88x201x_reset(struct cphy *cphy, int wait)
+{
+ /* This can be done through registers. It is not required since
+ * a full chip reset is used.
+ */
+ return 0;
+}
+
+static int mv88x201x_interrupt_enable(struct cphy *cphy)
+{
+ u32 elmer;
+
+ /* Enable PHY LASI interrupts. */
+ mdio_write(cphy, 0x1, 0x9002, 0x1);
+
+ /* Enable Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_disable(struct cphy *cphy)
+{
+ u32 elmer;
+
+ /* Disable PHY LASI interrupts. */
+ mdio_write(cphy, 0x1, 0x9002, 0x0);
+
+ /* Disable Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_clear(struct cphy *cphy)
+{
+ u32 elmer;
+ u32 val;
+
+#ifdef MV88x2010_LINK_STATUS_BUGS
+ /* Required to read twice before clear takes affect. */
+ mdio_read(cphy, 0x1, 0x9003, &val);
+ mdio_read(cphy, 0x1, 0x9004, &val);
+ mdio_read(cphy, 0x1, 0x9005, &val);
+
+ /* Read this register after the others above it else
+ * the register doesn't clear correctly.
+ */
+ mdio_read(cphy, 0x1, 0x1, &val);
+#endif
+
+ /* Clear link status. */
+ mdio_read(cphy, 0x1, 0x1, &val);
+ /* Clear PHY LASI interrupts. */
+ mdio_read(cphy, 0x1, 0x9005, &val);
+
+#ifdef MV88x2010_LINK_STATUS_BUGS
+ /* Do it again. */
+ mdio_read(cphy, 0x1, 0x9003, &val);
+ mdio_read(cphy, 0x1, 0x9004, &val);
+#endif
+
+ /* Clear Marvell interrupts through Elmer0. */
+ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT6;
+ t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
+ return 0;
+}
+
+static int mv88x201x_interrupt_handler(struct cphy *cphy)
+{
+ /* Clear interrupts */
+ mv88x201x_interrupt_clear(cphy);
+
+ /* We have only enabled link change interrupts and so
+ * cphy_cause must be a link change interrupt.
+ */
+ return cphy_cause_link_change;
+}
+
+static int mv88x201x_set_loopback(struct cphy *cphy, int on)
+{
+ return 0;
+}
+
+static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
+ int *speed, int *duplex, int *fc)
+{
+ u32 val = 0;
+#define LINK_STATUS_BIT 0x4
+
+ if (link_ok) {
+ /* Read link status. */
+ mdio_read(cphy, 0x1, 0x1, &val);
+ val &= LINK_STATUS_BIT;
+ *link_ok = (val == LINK_STATUS_BIT);
+ /* Turn on/off Link LED */
+ led_link(cphy, *link_ok);
+ }
+ if (speed)
+ *speed = SPEED_10000;
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ if (fc)
+ *fc = PAUSE_RX | PAUSE_TX;
+ return 0;
+}
+
+static void mv88x201x_destroy(struct cphy *cphy)
+{
+ kfree(cphy);
+}
+
+static struct cphy_ops mv88x201x_ops = {
+ .destroy = mv88x201x_destroy,
+ .reset = mv88x201x_reset,
+ .interrupt_enable = mv88x201x_interrupt_enable,
+ .interrupt_disable = mv88x201x_interrupt_disable,
+ .interrupt_clear = mv88x201x_interrupt_clear,
+ .interrupt_handler = mv88x201x_interrupt_handler,
+ .get_link_status = mv88x201x_get_link_status,
+ .set_loopback = mv88x201x_set_loopback,
+};
+
+static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
+ struct mdio_ops *mdio_ops)
+{
+ u32 val;
+ struct cphy *cphy = kmalloc(sizeof(*cphy), GFP_KERNEL);
+
+ if (!cphy)
+ return NULL;
+ memset(cphy, 0, sizeof(*cphy));
+ cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
+
+ /* Commands the PHY to enable XFP's clock. */
+ mdio_read(cphy, 0x3, 0x8300, &val);
+ mdio_write(cphy, 0x3, 0x8300, val | 1);
+
+ /* Clear link status. Required because of a bug in the PHY. */
+ mdio_read(cphy, 0x1, 0x8, &val);
+ mdio_read(cphy, 0x3, 0x8, &val);
+
+ /* Allows for Link,Ack LED turn on/off */
+ led_init(cphy);
+ return cphy;
+}
+
+/* Chip Reset */
+static int mv88x201x_phy_reset(adapter_t *adapter)
+{
+ u32 val;
+
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~4;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ msleep(100);
+
+ t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
+ msleep(1000);
+
+ /* Now lets enable the Laser. Delay 100us */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val |= 0x8000;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+ udelay(100);
+ return 0;
+}
+
+struct gphy t1_mv88x201x_ops = {
+ mv88x201x_phy_create,
+ mv88x201x_phy_reset
+};
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c
new file mode 100644
index 000000000000..04a1404fc65e
--- /dev/null
+++ b/drivers/net/chelsio/pm3393.c
@@ -0,0 +1,826 @@
+/*****************************************************************************
+ * *
+ * File: pm3393.c *
+ * $Revision: 1.16 $ *
+ * $Date: 2005/05/14 00:59:32 $ *
+ * Description: *
+ * PMC/SIERRA (pm3393) MAC-PHY functionality. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "regs.h"
+#include "gmac.h"
+#include "elmer0.h"
+#include "suni1x10gexp_regs.h"
+
+/* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
+ */
+enum {
+ MMD_RESERVED,
+ MMD_PMAPMD,
+ MMD_WIS,
+ MMD_PCS,
+ MMD_PHY_XGXS, /* XGMII Extender Sublayer */
+ MMD_DTE_XGXS,
+};
+
+enum {
+ PHY_XGXS_CTRL_1,
+ PHY_XGXS_STATUS_1
+};
+
+#define OFFSET(REG_ADDR) (REG_ADDR << 2)
+
+/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
+#define MAX_FRAME_SIZE 9600
+
+#define IPG 12
+#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
+ SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
+ SUNI1x10GEXP_BITMSK_TXXG_PADEN)
+#define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
+ SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
+
+/* Update statistics every 15 minutes */
+#define STATS_TICK_SECS (15 * 60)
+
+enum { /* RMON registers */
+ RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
+ RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
+ RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
+ RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
+ RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
+ RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
+ RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
+ RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
+ RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
+ RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
+ RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
+ RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
+ RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
+
+ TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
+ TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
+ TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
+ TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
+ TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
+ TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
+ TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW
+};
+
+struct _cmac_instance {
+ u8 enabled;
+ u8 fc;
+ u8 mac_addr[6];
+};
+
+static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
+{
+ t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
+ return 0;
+}
+
+static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
+{
+ t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
+ return 0;
+}
+
+/* Port reset. */
+static int pm3393_reset(struct cmac *cmac)
+{
+ return 0;
+}
+
+/*
+ * Enable interrupts for the PM3393
+
+ 1. Enable PM3393 BLOCK interrupts.
+ 2. Enable PM3393 Master Interrupt bit(INTE)
+ 3. Enable ELMER's PM3393 bit.
+ 4. Enable Terminator external interrupt.
+*/
+static int pm3393_interrupt_enable(struct cmac *cmac)
+{
+ u32 pl_intr;
+
+ /* PM3393 - Enabling all hardware block interrupts.
+ */
+ pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
+
+ /* Don't interrupt on statistics overflow, we are polling */
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
+
+ /* PM3393 - Global interrupt enable
+ */
+ /* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
+ 0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
+
+ /* TERMINATOR - PL_INTERUPTS_EXT */
+ pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
+ pl_intr |= F_PL_INTR_EXT;
+ writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
+ return 0;
+}
+
+static int pm3393_interrupt_disable(struct cmac *cmac)
+{
+ u32 elmer;
+
+ /* PM3393 - Enabling HW interrupt blocks. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
+ pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
+
+ /* PM3393 - Global interrupt enable */
+ pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
+
+ /* ELMER - External chip interrupts. */
+ t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
+ elmer &= ~ELMER0_GP_BIT1;
+ t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
+
+ /* TERMINATOR - PL_INTERUPTS_EXT */
+ /* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
+ * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
+ */
+
+ return 0;
+}
+
+static int pm3393_interrupt_clear(struct cmac *cmac)
+{
+ u32 elmer;
+ u32 pl_intr;
+ u32 val32;
+
+ /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
+ * bit WCIMODE=0 for a clear-on-read.
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
+ &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
+ pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
+
+ /* PM3393 - Global interrupt status
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
+
+ /* ELMER - External chip interrupts.
+ */
+ t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
+ elmer |= ELMER0_GP_BIT1;
+ t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
+
+ /* TERMINATOR - PL_INTERUPTS_EXT
+ */
+ pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
+ pl_intr |= F_PL_INTR_EXT;
+ writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
+
+ return 0;
+}
+
+/* Interrupt handler */
+static int pm3393_interrupt_handler(struct cmac *cmac)
+{
+ u32 master_intr_status;
+/*
+ 1. Read master interrupt register.
+ 2. Read BLOCK's interrupt status registers.
+ 3. Handle BLOCK interrupts.
+*/
+ /* Read the master interrupt status register. */
+ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
+ &master_intr_status);
+
+ /* TBD XXX Lets just clear everything for now */
+ pm3393_interrupt_clear(cmac);
+
+ return 0;
+}
+
+static int pm3393_enable(struct cmac *cmac, int which)
+{
+ if (which & MAC_DIRECTION_RX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
+ (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
+
+ if (which & MAC_DIRECTION_TX) {
+ u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
+
+ if (cmac->instance->fc & PAUSE_RX)
+ val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
+ if (cmac->instance->fc & PAUSE_TX)
+ val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
+ }
+
+ cmac->instance->enabled |= which;
+ return 0;
+}
+
+static int pm3393_enable_port(struct cmac *cmac, int which)
+{
+ /* Clear port statistics */
+ pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
+ SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
+ udelay(2);
+ memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
+
+ pm3393_enable(cmac, which);
+
+ /*
+ * XXX This should be done by the PHY and preferrably not at all.
+ * The PHY doesn't give us link status indication on its own so have
+ * the link management code query it instead.
+ */
+ {
+ extern void link_changed(adapter_t *adapter, int port_id);
+
+ link_changed(cmac->adapter, 0);
+ }
+ return 0;
+}
+
+static int pm3393_disable(struct cmac *cmac, int which)
+{
+ if (which & MAC_DIRECTION_RX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
+ if (which & MAC_DIRECTION_TX)
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
+
+ /*
+ * The disable is graceful. Give the PM3393 time. Can't wait very
+ * long here, we may be holding locks.
+ */
+ udelay(20);
+
+ cmac->instance->enabled &= ~which;
+ return 0;
+}
+
+static int pm3393_loopback_enable(struct cmac *cmac)
+{
+ return 0;
+}
+
+static int pm3393_loopback_disable(struct cmac *cmac)
+{
+ return 0;
+}
+
+static int pm3393_set_mtu(struct cmac *cmac, int mtu)
+{
+ int enabled = cmac->instance->enabled;
+
+ /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
+ mtu += 14 + 4;
+ if (mtu > MAX_FRAME_SIZE)
+ return -EINVAL;
+
+ /* Disable Rx/Tx MAC before configuring it. */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
+
+ if (enabled)
+ pm3393_enable(cmac, enabled);
+ return 0;
+}
+
+static u32 calc_crc(u8 *b, int len)
+{
+ int i;
+ u32 crc = (u32)~0;
+
+ /* calculate crc one bit at a time */
+ while (len--) {
+ crc ^= *b++;
+ for (i = 0; i < 8; i++) {
+ if (crc & 0x1)
+ crc = (crc >> 1) ^ 0xedb88320;
+ else
+ crc = (crc >> 1);
+ }
+ }
+
+ /* reverse bits */
+ crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
+ crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
+ crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
+ /* swap bytes */
+ crc = (crc >> 16) | (crc << 16);
+ crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
+
+ return crc;
+}
+
+static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
+{
+ int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
+ u32 rx_mode;
+
+ /* Disable MAC RX before reconfiguring it */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX);
+
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
+ rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
+ SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
+ (u16)rx_mode);
+
+ if (t1_rx_mode_promisc(rm)) {
+ /* Promiscuous mode. */
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
+ }
+ if (t1_rx_mode_allmulti(rm)) {
+ /* Accept all multicast. */
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
+ } else if (t1_rx_mode_mc_cnt(rm)) {
+ /* Accept one or more multicast(s). */
+ u8 *addr;
+ int bit;
+ u16 mc_filter[4] = { 0, };
+
+ while ((addr = t1_get_next_mcaddr(rm))) {
+ bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */
+ mc_filter[bit >> 4] |= 1 << (bit & 0xf);
+ }
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
+ rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
+ }
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
+
+ if (enabled)
+ pm3393_enable(cmac, MAC_DIRECTION_RX);
+
+ return 0;
+}
+
+static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
+ int *duplex, int *fc)
+{
+ if (speed)
+ *speed = SPEED_10000;
+ if (duplex)
+ *duplex = DUPLEX_FULL;
+ if (fc)
+ *fc = cmac->instance->fc;
+ return 0;
+}
+
+static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
+ int fc)
+{
+ if (speed >= 0 && speed != SPEED_10000)
+ return -1;
+ if (duplex >= 0 && duplex != DUPLEX_FULL)
+ return -1;
+ if (fc & ~(PAUSE_TX | PAUSE_RX))
+ return -1;
+
+ if (fc != cmac->instance->fc) {
+ cmac->instance->fc = (u8) fc;
+ if (cmac->instance->enabled & MAC_DIRECTION_TX)
+ pm3393_enable(cmac, MAC_DIRECTION_TX);
+ }
+ return 0;
+}
+
+#define RMON_UPDATE(mac, name, stat_name) \
+ { \
+ t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
+ t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
+ t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
+ (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
+ (((u64)val1 & 0xffff) << 16) | \
+ (((u64)val2 & 0xff) << 32) | \
+ ((mac)->stats.stat_name & \
+ (~(u64)0 << 40)); \
+ if (ro & \
+ ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
+ (mac)->stats.stat_name += ((u64)1 << 40); \
+ }
+
+static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
+ int flag)
+{
+ u64 ro;
+ u32 val0, val1, val2, val3;
+
+ /* Snap the counters */
+ pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
+ SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
+
+ /* Counter rollover, clear on read */
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
+ pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
+ ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
+ (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
+
+ /* Rx stats */
+ RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
+ RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
+ RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
+ RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
+ RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
+ RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
+ RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
+ RxInternalMACRcvError);
+ RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
+ RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
+ RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
+ RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
+ RMON_UPDATE(mac, RxFragments, RxRuntErrors);
+ RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
+
+ /* Tx stats */
+ RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
+ RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
+ TxInternalMACXmitError);
+ RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
+ RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
+ RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
+ RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
+ RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
+
+ return &mac->stats;
+}
+
+static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
+{
+ memcpy(mac_addr, cmac->instance->mac_addr, 6);
+ return 0;
+}
+
+static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
+{
+ u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
+
+ /*
+ * MAC addr: 00:07:43:00:13:09
+ *
+ * ma[5] = 0x09
+ * ma[4] = 0x13
+ * ma[3] = 0x00
+ * ma[2] = 0x43
+ * ma[1] = 0x07
+ * ma[0] = 0x00
+ *
+ * The PM3393 requires byte swapping and reverse order entry
+ * when programming MAC addresses:
+ *
+ * low_bits[15:0] = ma[1]:ma[0]
+ * mid_bits[31:16] = ma[3]:ma[2]
+ * high_bits[47:32] = ma[5]:ma[4]
+ */
+
+ /* Store local copy */
+ memcpy(cmac->instance->mac_addr, ma, 6);
+
+ lo = ((u32) ma[1] << 8) | (u32) ma[0];
+ mid = ((u32) ma[3] << 8) | (u32) ma[2];
+ hi = ((u32) ma[5] << 8) | (u32) ma[4];
+
+ /* Disable Rx/Tx MAC before configuring it. */
+ if (enabled)
+ pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+
+ /* Set RXXG Station Address */
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
+
+ /* Set TXXG Station Address */
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
+
+ /* Setup Exact Match Filter 1 with our MAC address
+ *
+ * Must disable exact match filter before configuring it.
+ */
+ pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
+ val &= 0xff0f;
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
+
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
+
+ val |= 0x0090;
+ pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
+
+ if (enabled)
+ pm3393_enable(cmac, enabled);
+ return 0;
+}
+
+static void pm3393_destroy(struct cmac *cmac)
+{
+ kfree(cmac);
+}
+
+static struct cmac_ops pm3393_ops = {
+ .destroy = pm3393_destroy,
+ .reset = pm3393_reset,
+ .interrupt_enable = pm3393_interrupt_enable,
+ .interrupt_disable = pm3393_interrupt_disable,
+ .interrupt_clear = pm3393_interrupt_clear,
+ .interrupt_handler = pm3393_interrupt_handler,
+ .enable = pm3393_enable_port,
+ .disable = pm3393_disable,
+ .loopback_enable = pm3393_loopback_enable,
+ .loopback_disable = pm3393_loopback_disable,
+ .set_mtu = pm3393_set_mtu,
+ .set_rx_mode = pm3393_set_rx_mode,
+ .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
+ .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
+ .statistics_update = pm3393_update_statistics,
+ .macaddress_get = pm3393_macaddress_get,
+ .macaddress_set = pm3393_macaddress_set
+};
+
+static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
+{
+ struct cmac *cmac;
+
+ cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
+ if (!cmac)
+ return NULL;
+ memset(cmac, 0, sizeof(*cmac));
+
+ cmac->ops = &pm3393_ops;
+ cmac->instance = (cmac_instance *) (cmac + 1);
+ cmac->adapter = adapter;
+ cmac->instance->fc = PAUSE_TX | PAUSE_RX;
+
+ t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
+ t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
+ t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
+ t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001); /* PL4IO Enable */
+ t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
+ t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
+ t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202); /* PL4IO Calendar Repetitions */
+
+ t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080); /* EFLX Enable */
+ t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000); /* EFLX Channel Deprovision */
+ t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000); /* EFLX Low Limit */
+ t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040); /* EFLX High Limit */
+ t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc); /* EFLX Almost Full */
+ t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199); /* EFLX Almost Empty */
+ t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240); /* EFLX Cut Through Threshold */
+ t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000); /* EFLX Indirect Register Update */
+ t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001); /* EFLX Channel Provision */
+ t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff); /* EFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff); /* EFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff); /* EFLX enable overflow interrupt The other bit are undocumented */
+ t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff); /* EFLX Undocumented */
+
+ t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000); /* IFLX Configuration - enable */
+ t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000); /* IFLX Channel Deprovision */
+ t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000); /* IFLX Low Limit */
+ t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100); /* IFLX High Limit */
+ t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00); /* IFLX Almost Full Limit */
+ t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599); /* IFLX Almost Empty Limit */
+ t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000); /* IFLX Indirect Register Update */
+ t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001); /* IFLX Channel Provision */
+ t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff); /* IFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff); /* IFLX Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff); /* IFLX Enable overflow interrupt. The other bit are undocumented */
+
+ t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe); /* PL4MOS Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff); /* PL4MOS Undocumented */
+ t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008); /* PL4MOS Starving Burst Size */
+ t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008); /* PL4MOS Hungry Burst Size */
+ t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008); /* PL4MOS Transfer Size */
+ t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005); /* PL4MOS Disable */
+
+ t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103); /* PL4ODP Training Repeat and SOP rule */
+ t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000); /* PL4ODP MAX_T setting */
+
+ t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087); /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
+ t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f); /* PL4IDU Enable Dip4 check error interrupts */
+
+ t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32); /* # TXXG Config */
+ /* For T1 use timer based Mac flow control. */
+ t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
+ t1_tpi_write(adapter, OFFSET(0x2040), 0x059c); /* # RXXG Config */
+ t1_tpi_write(adapter, OFFSET(0x2049), 0x0001); /* # RXXG Cut Through */
+ t1_tpi_write(adapter, OFFSET(0x2070), 0x0000); /* # Disable promiscuous mode */
+
+ /* Setup Exact Match Filter 0 to allow broadcast packets.
+ */
+ t1_tpi_write(adapter, OFFSET(0x206e), 0x0000); /* # Disable Match Enable bit */
+ t1_tpi_write(adapter, OFFSET(0x204a), 0xffff); /* # low addr */
+ t1_tpi_write(adapter, OFFSET(0x204b), 0xffff); /* # mid addr */
+ t1_tpi_write(adapter, OFFSET(0x204c), 0xffff); /* # high addr */
+ t1_tpi_write(adapter, OFFSET(0x206e), 0x0009); /* # Enable Match Enable bit */
+
+ t1_tpi_write(adapter, OFFSET(0x0003), 0x0000); /* # NO SOP/ PAD_EN setup */
+ t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0); /* # RXEQB disabled */
+ t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f); /* # No Preemphasis */
+
+ return cmac;
+}
+
+static int pm3393_mac_reset(adapter_t * adapter)
+{
+ u32 val;
+ u32 x;
+ u32 is_pl4_reset_finished;
+ u32 is_pl4_outof_lock;
+ u32 is_xaui_mabc_pll_locked;
+ u32 successful_reset;
+ int i;
+
+ /* The following steps are required to properly reset
+ * the PM3393. This information is provided in the
+ * PM3393 datasheet (Issue 2: November 2002)
+ * section 13.1 -- Device Reset.
+ *
+ * The PM3393 has three types of components that are
+ * individually reset:
+ *
+ * DRESETB - Digital circuitry
+ * PL4_ARESETB - PL4 analog circuitry
+ * XAUI_ARESETB - XAUI bus analog circuitry
+ *
+ * Steps to reset PM3393 using RSTB pin:
+ *
+ * 1. Assert RSTB pin low ( write 0 )
+ * 2. Wait at least 1ms to initiate a complete initialization of device.
+ * 3. Wait until all external clocks and REFSEL are stable.
+ * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
+ * 5. De-assert RSTB ( write 1 )
+ * 6. Wait until internal timers to expires after ~14ms.
+ * - Allows analog clock synthesizer(PL4CSU) to stabilize to
+ * selected reference frequency before allowing the digital
+ * portion of the device to operate.
+ * 7. Wait at least 200us for XAUI interface to stabilize.
+ * 8. Verify the PM3393 came out of reset successfully.
+ * Set successful reset flag if everything worked else try again
+ * a few more times.
+ */
+
+ successful_reset = 0;
+ for (i = 0; i < 3 && !successful_reset; i++) {
+ /* 1 */
+ t1_tpi_read(adapter, A_ELMER0_GPO, &val);
+ val &= ~1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ /* 2 */
+ msleep(1);
+
+ /* 3 */
+ msleep(1);
+
+ /* 4 */
+ msleep(2 /*1 extra ms for safety */ );
+
+ /* 5 */
+ val |= 1;
+ t1_tpi_write(adapter, A_ELMER0_GPO, val);
+
+ /* 6 */
+ msleep(15 /*1 extra ms for safety */ );
+
+ /* 7 */
+ msleep(1);
+
+ /* 8 */
+
+ /* Has PL4 analog block come out of reset correctly? */
+ t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
+ is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
+
+ /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
+ * figure out why? */
+
+ /* Have all PL4 block clocks locked? */
+ x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
+ /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */ |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
+ SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
+ is_pl4_outof_lock = (val & x);
+
+ /* ??? If this fails, might be able to software reset the XAUI part
+ * and try to recover... thus saving us from doing another HW reset */
+ /* Has the XAUI MABC PLL circuitry stablized? */
+ is_xaui_mabc_pll_locked =
+ (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
+
+ successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
+ && is_xaui_mabc_pll_locked);
+ }
+ return successful_reset ? 0 : 1;
+}
+
+struct gmac t1_pm3393_ops = {
+ STATS_TICK_SECS,
+ pm3393_mac_create,
+ pm3393_mac_reset
+};
diff --git a/drivers/net/chelsio/regs.h b/drivers/net/chelsio/regs.h
new file mode 100644
index 000000000000..b90e11f40d1f
--- /dev/null
+++ b/drivers/net/chelsio/regs.h
@@ -0,0 +1,468 @@
+/*****************************************************************************
+ * *
+ * File: regs.h *
+ * $Revision: 1.8 $ *
+ * $Date: 2005/06/21 18:29:48 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_REGS_H_
+#define _CXGB_REGS_H_
+
+/* SGE registers */
+#define A_SG_CONTROL 0x0
+
+#define S_CMDQ0_ENABLE 0
+#define V_CMDQ0_ENABLE(x) ((x) << S_CMDQ0_ENABLE)
+#define F_CMDQ0_ENABLE V_CMDQ0_ENABLE(1U)
+
+#define S_CMDQ1_ENABLE 1
+#define V_CMDQ1_ENABLE(x) ((x) << S_CMDQ1_ENABLE)
+#define F_CMDQ1_ENABLE V_CMDQ1_ENABLE(1U)
+
+#define S_FL0_ENABLE 2
+#define V_FL0_ENABLE(x) ((x) << S_FL0_ENABLE)
+#define F_FL0_ENABLE V_FL0_ENABLE(1U)
+
+#define S_FL1_ENABLE 3
+#define V_FL1_ENABLE(x) ((x) << S_FL1_ENABLE)
+#define F_FL1_ENABLE V_FL1_ENABLE(1U)
+
+#define S_CPL_ENABLE 4
+#define V_CPL_ENABLE(x) ((x) << S_CPL_ENABLE)
+#define F_CPL_ENABLE V_CPL_ENABLE(1U)
+
+#define S_RESPONSE_QUEUE_ENABLE 5
+#define V_RESPONSE_QUEUE_ENABLE(x) ((x) << S_RESPONSE_QUEUE_ENABLE)
+#define F_RESPONSE_QUEUE_ENABLE V_RESPONSE_QUEUE_ENABLE(1U)
+
+#define S_CMDQ_PRIORITY 6
+#define M_CMDQ_PRIORITY 0x3
+#define V_CMDQ_PRIORITY(x) ((x) << S_CMDQ_PRIORITY)
+#define G_CMDQ_PRIORITY(x) (((x) >> S_CMDQ_PRIORITY) & M_CMDQ_PRIORITY)
+
+#define S_DISABLE_CMDQ1_GTS 9
+#define V_DISABLE_CMDQ1_GTS(x) ((x) << S_DISABLE_CMDQ1_GTS)
+#define F_DISABLE_CMDQ1_GTS V_DISABLE_CMDQ1_GTS(1U)
+
+#define S_DISABLE_FL0_GTS 10
+#define V_DISABLE_FL0_GTS(x) ((x) << S_DISABLE_FL0_GTS)
+#define F_DISABLE_FL0_GTS V_DISABLE_FL0_GTS(1U)
+
+#define S_DISABLE_FL1_GTS 11
+#define V_DISABLE_FL1_GTS(x) ((x) << S_DISABLE_FL1_GTS)
+#define F_DISABLE_FL1_GTS V_DISABLE_FL1_GTS(1U)
+
+#define S_ENABLE_BIG_ENDIAN 12
+#define V_ENABLE_BIG_ENDIAN(x) ((x) << S_ENABLE_BIG_ENDIAN)
+#define F_ENABLE_BIG_ENDIAN V_ENABLE_BIG_ENDIAN(1U)
+
+#define S_ISCSI_COALESCE 14
+#define V_ISCSI_COALESCE(x) ((x) << S_ISCSI_COALESCE)
+#define F_ISCSI_COALESCE V_ISCSI_COALESCE(1U)
+
+#define S_RX_PKT_OFFSET 15
+#define V_RX_PKT_OFFSET(x) ((x) << S_RX_PKT_OFFSET)
+
+#define S_VLAN_XTRACT 18
+#define V_VLAN_XTRACT(x) ((x) << S_VLAN_XTRACT)
+#define F_VLAN_XTRACT V_VLAN_XTRACT(1U)
+
+#define A_SG_DOORBELL 0x4
+#define A_SG_CMD0BASELWR 0x8
+#define A_SG_CMD0BASEUPR 0xc
+#define A_SG_CMD1BASELWR 0x10
+#define A_SG_CMD1BASEUPR 0x14
+#define A_SG_FL0BASELWR 0x18
+#define A_SG_FL0BASEUPR 0x1c
+#define A_SG_FL1BASELWR 0x20
+#define A_SG_FL1BASEUPR 0x24
+#define A_SG_CMD0SIZE 0x28
+#define A_SG_FL0SIZE 0x2c
+#define A_SG_RSPSIZE 0x30
+#define A_SG_RSPBASELWR 0x34
+#define A_SG_RSPBASEUPR 0x38
+#define A_SG_FLTHRESHOLD 0x3c
+#define A_SG_RSPQUEUECREDIT 0x40
+#define A_SG_SLEEPING 0x48
+#define A_SG_INTRTIMER 0x4c
+#define A_SG_CMD1SIZE 0xb0
+#define A_SG_FL1SIZE 0xb4
+#define A_SG_INT_ENABLE 0xb8
+
+#define S_RESPQ_EXHAUSTED 0
+#define V_RESPQ_EXHAUSTED(x) ((x) << S_RESPQ_EXHAUSTED)
+#define F_RESPQ_EXHAUSTED V_RESPQ_EXHAUSTED(1U)
+
+#define S_RESPQ_OVERFLOW 1
+#define V_RESPQ_OVERFLOW(x) ((x) << S_RESPQ_OVERFLOW)
+#define F_RESPQ_OVERFLOW V_RESPQ_OVERFLOW(1U)
+
+#define S_FL_EXHAUSTED 2
+#define V_FL_EXHAUSTED(x) ((x) << S_FL_EXHAUSTED)
+#define F_FL_EXHAUSTED V_FL_EXHAUSTED(1U)
+
+#define S_PACKET_TOO_BIG 3
+#define V_PACKET_TOO_BIG(x) ((x) << S_PACKET_TOO_BIG)
+#define F_PACKET_TOO_BIG V_PACKET_TOO_BIG(1U)
+
+#define S_PACKET_MISMATCH 4
+#define V_PACKET_MISMATCH(x) ((x) << S_PACKET_MISMATCH)
+#define F_PACKET_MISMATCH V_PACKET_MISMATCH(1U)
+
+#define A_SG_INT_CAUSE 0xbc
+#define A_SG_RESPACCUTIMER 0xc0
+
+/* MC3 registers */
+
+#define S_READY 1
+#define V_READY(x) ((x) << S_READY)
+#define F_READY V_READY(1U)
+
+/* MC4 registers */
+
+#define A_MC4_CFG 0x180
+#define S_MC4_SLOW 25
+#define V_MC4_SLOW(x) ((x) << S_MC4_SLOW)
+#define F_MC4_SLOW V_MC4_SLOW(1U)
+
+/* TPI registers */
+
+#define A_TPI_ADDR 0x280
+#define A_TPI_WR_DATA 0x284
+#define A_TPI_RD_DATA 0x288
+#define A_TPI_CSR 0x28c
+
+#define S_TPIWR 0
+#define V_TPIWR(x) ((x) << S_TPIWR)
+#define F_TPIWR V_TPIWR(1U)
+
+#define S_TPIRDY 1
+#define V_TPIRDY(x) ((x) << S_TPIRDY)
+#define F_TPIRDY V_TPIRDY(1U)
+
+#define A_TPI_PAR 0x29c
+
+#define S_TPIPAR 0
+#define M_TPIPAR 0x7f
+#define V_TPIPAR(x) ((x) << S_TPIPAR)
+#define G_TPIPAR(x) (((x) >> S_TPIPAR) & M_TPIPAR)
+
+/* TP registers */
+
+#define A_TP_IN_CONFIG 0x300
+
+#define S_TP_IN_CSPI_CPL 3
+#define V_TP_IN_CSPI_CPL(x) ((x) << S_TP_IN_CSPI_CPL)
+#define F_TP_IN_CSPI_CPL V_TP_IN_CSPI_CPL(1U)
+
+#define S_TP_IN_CSPI_CHECK_IP_CSUM 5
+#define V_TP_IN_CSPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_IP_CSUM)
+#define F_TP_IN_CSPI_CHECK_IP_CSUM V_TP_IN_CSPI_CHECK_IP_CSUM(1U)
+
+#define S_TP_IN_CSPI_CHECK_TCP_CSUM 6
+#define V_TP_IN_CSPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_TCP_CSUM)
+#define F_TP_IN_CSPI_CHECK_TCP_CSUM V_TP_IN_CSPI_CHECK_TCP_CSUM(1U)
+
+#define S_TP_IN_ESPI_ETHERNET 8
+#define V_TP_IN_ESPI_ETHERNET(x) ((x) << S_TP_IN_ESPI_ETHERNET)
+#define F_TP_IN_ESPI_ETHERNET V_TP_IN_ESPI_ETHERNET(1U)
+
+#define S_TP_IN_ESPI_CHECK_IP_CSUM 12
+#define V_TP_IN_ESPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_IP_CSUM)
+#define F_TP_IN_ESPI_CHECK_IP_CSUM V_TP_IN_ESPI_CHECK_IP_CSUM(1U)
+
+#define S_TP_IN_ESPI_CHECK_TCP_CSUM 13
+#define V_TP_IN_ESPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_TCP_CSUM)
+#define F_TP_IN_ESPI_CHECK_TCP_CSUM V_TP_IN_ESPI_CHECK_TCP_CSUM(1U)
+
+#define S_OFFLOAD_DISABLE 14
+#define V_OFFLOAD_DISABLE(x) ((x) << S_OFFLOAD_DISABLE)
+#define F_OFFLOAD_DISABLE V_OFFLOAD_DISABLE(1U)
+
+#define A_TP_OUT_CONFIG 0x304
+
+#define S_TP_OUT_CSPI_CPL 2
+#define V_TP_OUT_CSPI_CPL(x) ((x) << S_TP_OUT_CSPI_CPL)
+#define F_TP_OUT_CSPI_CPL V_TP_OUT_CSPI_CPL(1U)
+
+#define S_TP_OUT_ESPI_ETHERNET 6
+#define V_TP_OUT_ESPI_ETHERNET(x) ((x) << S_TP_OUT_ESPI_ETHERNET)
+#define F_TP_OUT_ESPI_ETHERNET V_TP_OUT_ESPI_ETHERNET(1U)
+
+#define S_TP_OUT_ESPI_GENERATE_IP_CSUM 10
+#define V_TP_OUT_ESPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_IP_CSUM)
+#define F_TP_OUT_ESPI_GENERATE_IP_CSUM V_TP_OUT_ESPI_GENERATE_IP_CSUM(1U)
+
+#define S_TP_OUT_ESPI_GENERATE_TCP_CSUM 11
+#define V_TP_OUT_ESPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_TCP_CSUM)
+#define F_TP_OUT_ESPI_GENERATE_TCP_CSUM V_TP_OUT_ESPI_GENERATE_TCP_CSUM(1U)
+
+#define A_TP_GLOBAL_CONFIG 0x308
+
+#define S_IP_TTL 0
+#define M_IP_TTL 0xff
+#define V_IP_TTL(x) ((x) << S_IP_TTL)
+
+#define S_TCP_CSUM 11
+#define V_TCP_CSUM(x) ((x) << S_TCP_CSUM)
+#define F_TCP_CSUM V_TCP_CSUM(1U)
+
+#define S_UDP_CSUM 12
+#define V_UDP_CSUM(x) ((x) << S_UDP_CSUM)
+#define F_UDP_CSUM V_UDP_CSUM(1U)
+
+#define S_IP_CSUM 13
+#define V_IP_CSUM(x) ((x) << S_IP_CSUM)
+#define F_IP_CSUM V_IP_CSUM(1U)
+
+#define S_PATH_MTU 15
+#define V_PATH_MTU(x) ((x) << S_PATH_MTU)
+#define F_PATH_MTU V_PATH_MTU(1U)
+
+#define S_5TUPLE_LOOKUP 17
+#define V_5TUPLE_LOOKUP(x) ((x) << S_5TUPLE_LOOKUP)
+
+#define S_SYN_COOKIE_PARAMETER 26
+#define V_SYN_COOKIE_PARAMETER(x) ((x) << S_SYN_COOKIE_PARAMETER)
+
+#define A_TP_PC_CONFIG 0x348
+#define S_DIS_TX_FILL_WIN_PUSH 12
+#define V_DIS_TX_FILL_WIN_PUSH(x) ((x) << S_DIS_TX_FILL_WIN_PUSH)
+#define F_DIS_TX_FILL_WIN_PUSH V_DIS_TX_FILL_WIN_PUSH(1U)
+
+#define S_TP_PC_REV 30
+#define M_TP_PC_REV 0x3
+#define G_TP_PC_REV(x) (((x) >> S_TP_PC_REV) & M_TP_PC_REV)
+#define A_TP_RESET 0x44c
+#define S_TP_RESET 0
+#define V_TP_RESET(x) ((x) << S_TP_RESET)
+#define F_TP_RESET V_TP_RESET(1U)
+
+#define A_TP_INT_ENABLE 0x470
+#define A_TP_INT_CAUSE 0x474
+#define A_TP_TX_DROP_CONFIG 0x4b8
+
+#define S_ENABLE_TX_DROP 31
+#define V_ENABLE_TX_DROP(x) ((x) << S_ENABLE_TX_DROP)
+#define F_ENABLE_TX_DROP V_ENABLE_TX_DROP(1U)
+
+#define S_ENABLE_TX_ERROR 30
+#define V_ENABLE_TX_ERROR(x) ((x) << S_ENABLE_TX_ERROR)
+#define F_ENABLE_TX_ERROR V_ENABLE_TX_ERROR(1U)
+
+#define S_DROP_TICKS_CNT 4
+#define V_DROP_TICKS_CNT(x) ((x) << S_DROP_TICKS_CNT)
+
+#define S_NUM_PKTS_DROPPED 0
+#define V_NUM_PKTS_DROPPED(x) ((x) << S_NUM_PKTS_DROPPED)
+
+/* CSPI registers */
+
+#define S_DIP4ERR 0
+#define V_DIP4ERR(x) ((x) << S_DIP4ERR)
+#define F_DIP4ERR V_DIP4ERR(1U)
+
+#define S_RXDROP 1
+#define V_RXDROP(x) ((x) << S_RXDROP)
+#define F_RXDROP V_RXDROP(1U)
+
+#define S_TXDROP 2
+#define V_TXDROP(x) ((x) << S_TXDROP)
+#define F_TXDROP V_TXDROP(1U)
+
+#define S_RXOVERFLOW 3
+#define V_RXOVERFLOW(x) ((x) << S_RXOVERFLOW)
+#define F_RXOVERFLOW V_RXOVERFLOW(1U)
+
+#define S_RAMPARITYERR 4
+#define V_RAMPARITYERR(x) ((x) << S_RAMPARITYERR)
+#define F_RAMPARITYERR V_RAMPARITYERR(1U)
+
+/* ESPI registers */
+
+#define A_ESPI_SCH_TOKEN0 0x880
+#define A_ESPI_SCH_TOKEN1 0x884
+#define A_ESPI_SCH_TOKEN2 0x888
+#define A_ESPI_SCH_TOKEN3 0x88c
+#define A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK 0x890
+#define A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK 0x894
+#define A_ESPI_CALENDAR_LENGTH 0x898
+#define A_PORT_CONFIG 0x89c
+
+#define S_RX_NPORTS 0
+#define V_RX_NPORTS(x) ((x) << S_RX_NPORTS)
+
+#define S_TX_NPORTS 8
+#define V_TX_NPORTS(x) ((x) << S_TX_NPORTS)
+
+#define A_ESPI_FIFO_STATUS_ENABLE 0x8a0
+
+#define S_RXSTATUSENABLE 0
+#define V_RXSTATUSENABLE(x) ((x) << S_RXSTATUSENABLE)
+#define F_RXSTATUSENABLE V_RXSTATUSENABLE(1U)
+
+#define S_INTEL1010MODE 4
+#define V_INTEL1010MODE(x) ((x) << S_INTEL1010MODE)
+#define F_INTEL1010MODE V_INTEL1010MODE(1U)
+
+#define A_ESPI_MAXBURST1_MAXBURST2 0x8a8
+#define A_ESPI_TRAIN 0x8ac
+#define A_ESPI_INTR_STATUS 0x8c8
+
+#define S_DIP2PARITYERR 5
+#define V_DIP2PARITYERR(x) ((x) << S_DIP2PARITYERR)
+#define F_DIP2PARITYERR V_DIP2PARITYERR(1U)
+
+#define A_ESPI_INTR_ENABLE 0x8cc
+#define A_RX_DROP_THRESHOLD 0x8d0
+#define A_ESPI_RX_RESET 0x8ec
+#define A_ESPI_MISC_CONTROL 0x8f0
+
+#define S_OUT_OF_SYNC_COUNT 0
+#define V_OUT_OF_SYNC_COUNT(x) ((x) << S_OUT_OF_SYNC_COUNT)
+
+#define S_DIP2_PARITY_ERR_THRES 5
+#define V_DIP2_PARITY_ERR_THRES(x) ((x) << S_DIP2_PARITY_ERR_THRES)
+
+#define S_DIP4_THRES 9
+#define V_DIP4_THRES(x) ((x) << S_DIP4_THRES)
+
+#define S_MONITORED_PORT_NUM 25
+#define V_MONITORED_PORT_NUM(x) ((x) << S_MONITORED_PORT_NUM)
+
+#define S_MONITORED_DIRECTION 27
+#define V_MONITORED_DIRECTION(x) ((x) << S_MONITORED_DIRECTION)
+#define F_MONITORED_DIRECTION V_MONITORED_DIRECTION(1U)
+
+#define S_MONITORED_INTERFACE 28
+#define V_MONITORED_INTERFACE(x) ((x) << S_MONITORED_INTERFACE)
+#define F_MONITORED_INTERFACE V_MONITORED_INTERFACE(1U)
+
+#define A_ESPI_DIP2_ERR_COUNT 0x8f4
+#define A_ESPI_CMD_ADDR 0x8f8
+
+#define S_WRITE_DATA 0
+#define V_WRITE_DATA(x) ((x) << S_WRITE_DATA)
+
+#define S_REGISTER_OFFSET 8
+#define V_REGISTER_OFFSET(x) ((x) << S_REGISTER_OFFSET)
+
+#define S_CHANNEL_ADDR 12
+#define V_CHANNEL_ADDR(x) ((x) << S_CHANNEL_ADDR)
+
+#define S_MODULE_ADDR 16
+#define V_MODULE_ADDR(x) ((x) << S_MODULE_ADDR)
+
+#define S_BUNDLE_ADDR 20
+#define V_BUNDLE_ADDR(x) ((x) << S_BUNDLE_ADDR)
+
+#define S_SPI4_COMMAND 24
+#define V_SPI4_COMMAND(x) ((x) << S_SPI4_COMMAND)
+
+#define A_ESPI_GOSTAT 0x8fc
+#define S_ESPI_CMD_BUSY 8
+#define V_ESPI_CMD_BUSY(x) ((x) << S_ESPI_CMD_BUSY)
+#define F_ESPI_CMD_BUSY V_ESPI_CMD_BUSY(1U)
+
+/* PL registers */
+
+#define A_PL_ENABLE 0xa00
+
+#define S_PL_INTR_SGE_ERR 0
+#define V_PL_INTR_SGE_ERR(x) ((x) << S_PL_INTR_SGE_ERR)
+#define F_PL_INTR_SGE_ERR V_PL_INTR_SGE_ERR(1U)
+
+#define S_PL_INTR_SGE_DATA 1
+#define V_PL_INTR_SGE_DATA(x) ((x) << S_PL_INTR_SGE_DATA)
+#define F_PL_INTR_SGE_DATA V_PL_INTR_SGE_DATA(1U)
+
+#define S_PL_INTR_TP 6
+#define V_PL_INTR_TP(x) ((x) << S_PL_INTR_TP)
+#define F_PL_INTR_TP V_PL_INTR_TP(1U)
+
+#define S_PL_INTR_ESPI 8
+#define V_PL_INTR_ESPI(x) ((x) << S_PL_INTR_ESPI)
+#define F_PL_INTR_ESPI V_PL_INTR_ESPI(1U)
+
+#define S_PL_INTR_PCIX 10
+#define V_PL_INTR_PCIX(x) ((x) << S_PL_INTR_PCIX)
+#define F_PL_INTR_PCIX V_PL_INTR_PCIX(1U)
+
+#define S_PL_INTR_EXT 11
+#define V_PL_INTR_EXT(x) ((x) << S_PL_INTR_EXT)
+#define F_PL_INTR_EXT V_PL_INTR_EXT(1U)
+
+#define A_PL_CAUSE 0xa04
+
+/* MC5 registers */
+
+#define A_MC5_CONFIG 0xc04
+
+#define S_TCAM_RESET 1
+#define V_TCAM_RESET(x) ((x) << S_TCAM_RESET)
+#define F_TCAM_RESET V_TCAM_RESET(1U)
+
+#define S_M_BUS_ENABLE 5
+#define V_M_BUS_ENABLE(x) ((x) << S_M_BUS_ENABLE)
+#define F_M_BUS_ENABLE V_M_BUS_ENABLE(1U)
+
+/* PCICFG registers */
+
+#define A_PCICFG_PM_CSR 0x44
+#define A_PCICFG_VPD_ADDR 0x4a
+
+#define S_VPD_OP_FLAG 15
+#define V_VPD_OP_FLAG(x) ((x) << S_VPD_OP_FLAG)
+#define F_VPD_OP_FLAG V_VPD_OP_FLAG(1U)
+
+#define A_PCICFG_VPD_DATA 0x4c
+
+#define A_PCICFG_INTR_ENABLE 0xf4
+#define A_PCICFG_INTR_CAUSE 0xf8
+
+#define A_PCICFG_MODE 0xfc
+
+#define S_PCI_MODE_64BIT 0
+#define V_PCI_MODE_64BIT(x) ((x) << S_PCI_MODE_64BIT)
+#define F_PCI_MODE_64BIT V_PCI_MODE_64BIT(1U)
+
+#define S_PCI_MODE_PCIX 5
+#define V_PCI_MODE_PCIX(x) ((x) << S_PCI_MODE_PCIX)
+#define F_PCI_MODE_PCIX V_PCI_MODE_PCIX(1U)
+
+#define S_PCI_MODE_CLK 6
+#define M_PCI_MODE_CLK 0x3
+#define G_PCI_MODE_CLK(x) (((x) >> S_PCI_MODE_CLK) & M_PCI_MODE_CLK)
+
+#endif /* _CXGB_REGS_H_ */
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
new file mode 100644
index 000000000000..53b41d99b00b
--- /dev/null
+++ b/drivers/net/chelsio/sge.c
@@ -0,0 +1,1684 @@
+/*****************************************************************************
+ * *
+ * File: sge.c *
+ * $Revision: 1.26 $ *
+ * $Date: 2005/06/21 18:29:48 $ *
+ * Description: *
+ * DMA engine. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+
+#include "cpl5_cmd.h"
+#include "sge.h"
+#include "regs.h"
+#include "espi.h"
+
+
+#ifdef NETIF_F_TSO
+#include <linux/tcp.h>
+#endif
+
+#define SGE_CMDQ_N 2
+#define SGE_FREELQ_N 2
+#define SGE_CMDQ0_E_N 1024
+#define SGE_CMDQ1_E_N 128
+#define SGE_FREEL_SIZE 4096
+#define SGE_JUMBO_FREEL_SIZE 512
+#define SGE_FREEL_REFILL_THRESH 16
+#define SGE_RESPQ_E_N 1024
+#define SGE_INTRTIMER_NRES 1000
+#define SGE_RX_COPY_THRES 256
+#define SGE_RX_SM_BUF_SIZE 1536
+
+# define SGE_RX_DROP_THRES 2
+
+#define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4)
+
+/*
+ * Period of the TX buffer reclaim timer. This timer does not need to run
+ * frequently as TX buffers are usually reclaimed by new TX packets.
+ */
+#define TX_RECLAIM_PERIOD (HZ / 4)
+
+#ifndef NET_IP_ALIGN
+# define NET_IP_ALIGN 2
+#endif
+
+#define M_CMD_LEN 0x7fffffff
+#define V_CMD_LEN(v) (v)
+#define G_CMD_LEN(v) ((v) & M_CMD_LEN)
+#define V_CMD_GEN1(v) ((v) << 31)
+#define V_CMD_GEN2(v) (v)
+#define F_CMD_DATAVALID (1 << 1)
+#define F_CMD_SOP (1 << 2)
+#define V_CMD_EOP(v) ((v) << 3)
+
+/*
+ * Command queue, receive buffer list, and response queue descriptors.
+ */
+#if defined(__BIG_ENDIAN_BITFIELD)
+struct cmdQ_e {
+ u32 addr_lo;
+ u32 len_gen;
+ u32 flags;
+ u32 addr_hi;
+};
+
+struct freelQ_e {
+ u32 addr_lo;
+ u32 len_gen;
+ u32 gen2;
+ u32 addr_hi;
+};
+
+struct respQ_e {
+ u32 Qsleeping : 4;
+ u32 Cmdq1CreditReturn : 5;
+ u32 Cmdq1DmaComplete : 5;
+ u32 Cmdq0CreditReturn : 5;
+ u32 Cmdq0DmaComplete : 5;
+ u32 FreelistQid : 2;
+ u32 CreditValid : 1;
+ u32 DataValid : 1;
+ u32 Offload : 1;
+ u32 Eop : 1;
+ u32 Sop : 1;
+ u32 GenerationBit : 1;
+ u32 BufferLength;
+};
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+struct cmdQ_e {
+ u32 len_gen;
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 flags;
+};
+
+struct freelQ_e {
+ u32 len_gen;
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 gen2;
+};
+
+struct respQ_e {
+ u32 BufferLength;
+ u32 GenerationBit : 1;
+ u32 Sop : 1;
+ u32 Eop : 1;
+ u32 Offload : 1;
+ u32 DataValid : 1;
+ u32 CreditValid : 1;
+ u32 FreelistQid : 2;
+ u32 Cmdq0DmaComplete : 5;
+ u32 Cmdq0CreditReturn : 5;
+ u32 Cmdq1DmaComplete : 5;
+ u32 Cmdq1CreditReturn : 5;
+ u32 Qsleeping : 4;
+} ;
+#endif
+
+/*
+ * SW Context Command and Freelist Queue Descriptors
+ */
+struct cmdQ_ce {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ DECLARE_PCI_UNMAP_LEN(dma_len);
+};
+
+struct freelQ_ce {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ DECLARE_PCI_UNMAP_LEN(dma_len);
+};
+
+/*
+ * SW command, freelist and response rings
+ */
+struct cmdQ {
+ unsigned long status; /* HW DMA fetch status */
+ unsigned int in_use; /* # of in-use command descriptors */
+ unsigned int size; /* # of descriptors */
+ unsigned int processed; /* total # of descs HW has processed */
+ unsigned int cleaned; /* total # of descs SW has reclaimed */
+ unsigned int stop_thres; /* SW TX queue suspend threshold */
+ u16 pidx; /* producer index (SW) */
+ u16 cidx; /* consumer index (HW) */
+ u8 genbit; /* current generation (=valid) bit */
+ u8 sop; /* is next entry start of packet? */
+ struct cmdQ_e *entries; /* HW command descriptor Q */
+ struct cmdQ_ce *centries; /* SW command context descriptor Q */
+ spinlock_t lock; /* Lock to protect cmdQ enqueuing */
+ dma_addr_t dma_addr; /* DMA addr HW command descriptor Q */
+};
+
+struct freelQ {
+ unsigned int credits; /* # of available RX buffers */
+ unsigned int size; /* free list capacity */
+ u16 pidx; /* producer index (SW) */
+ u16 cidx; /* consumer index (HW) */
+ u16 rx_buffer_size; /* Buffer size on this free list */
+ u16 dma_offset; /* DMA offset to align IP headers */
+ u16 recycleq_idx; /* skb recycle q to use */
+ u8 genbit; /* current generation (=valid) bit */
+ struct freelQ_e *entries; /* HW freelist descriptor Q */
+ struct freelQ_ce *centries; /* SW freelist context descriptor Q */
+ dma_addr_t dma_addr; /* DMA addr HW freelist descriptor Q */
+};
+
+struct respQ {
+ unsigned int credits; /* credits to be returned to SGE */
+ unsigned int size; /* # of response Q descriptors */
+ u16 cidx; /* consumer index (SW) */
+ u8 genbit; /* current generation(=valid) bit */
+ struct respQ_e *entries; /* HW response descriptor Q */
+ dma_addr_t dma_addr; /* DMA addr HW response descriptor Q */
+};
+
+/* Bit flags for cmdQ.status */
+enum {
+ CMDQ_STAT_RUNNING = 1, /* fetch engine is running */
+ CMDQ_STAT_LAST_PKT_DB = 2 /* last packet rung the doorbell */
+};
+
+/*
+ * Main SGE data structure
+ *
+ * Interrupts are handled by a single CPU and it is likely that on a MP system
+ * the application is migrated to another CPU. In that scenario, we try to
+ * seperate the RX(in irq context) and TX state in order to decrease memory
+ * contention.
+ */
+struct sge {
+ struct adapter *adapter; /* adapter backpointer */
+ struct net_device *netdev; /* netdevice backpointer */
+ struct freelQ freelQ[SGE_FREELQ_N]; /* buffer free lists */
+ struct respQ respQ; /* response Q */
+ unsigned long stopped_tx_queues; /* bitmap of suspended Tx queues */
+ unsigned int rx_pkt_pad; /* RX padding for L2 packets */
+ unsigned int jumbo_fl; /* jumbo freelist Q index */
+ unsigned int intrtimer_nres; /* no-resource interrupt timer */
+ unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */
+ struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
+ struct timer_list espibug_timer;
+ unsigned int espibug_timeout;
+ struct sk_buff *espibug_skb;
+ u32 sge_control; /* shadow value of sge control reg */
+ struct sge_intr_counts stats;
+ struct sge_port_stats port_stats[MAX_NPORTS];
+ struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
+};
+
+/*
+ * PIO to indicate that memory mapped Q contains valid descriptor(s).
+ */
+static inline void doorbell_pio(struct adapter *adapter, u32 val)
+{
+ wmb();
+ writel(val, adapter->regs + A_SG_DOORBELL);
+}
+
+/*
+ * Frees all RX buffers on the freelist Q. The caller must make sure that
+ * the SGE is turned off before calling this function.
+ */
+static void free_freelQ_buffers(struct pci_dev *pdev, struct freelQ *q)
+{
+ unsigned int cidx = q->cidx;
+
+ while (q->credits--) {
+ struct freelQ_ce *ce = &q->centries[cidx];
+
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(ce->skb);
+ ce->skb = NULL;
+ if (++cidx == q->size)
+ cidx = 0;
+ }
+}
+
+/*
+ * Free RX free list and response queue resources.
+ */
+static void free_rx_resources(struct sge *sge)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ if (sge->respQ.entries) {
+ size = sizeof(struct respQ_e) * sge->respQ.size;
+ pci_free_consistent(pdev, size, sge->respQ.entries,
+ sge->respQ.dma_addr);
+ }
+
+ for (i = 0; i < SGE_FREELQ_N; i++) {
+ struct freelQ *q = &sge->freelQ[i];
+
+ if (q->centries) {
+ free_freelQ_buffers(pdev, q);
+ kfree(q->centries);
+ }
+ if (q->entries) {
+ size = sizeof(struct freelQ_e) * q->size;
+ pci_free_consistent(pdev, size, q->entries,
+ q->dma_addr);
+ }
+ }
+}
+
+/*
+ * Allocates basic RX resources, consisting of memory mapped freelist Qs and a
+ * response queue.
+ */
+static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_FREELQ_N; i++) {
+ struct freelQ *q = &sge->freelQ[i];
+
+ q->genbit = 1;
+ q->size = p->freelQ_size[i];
+ q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN;
+ size = sizeof(struct freelQ_e) * q->size;
+ q->entries = (struct freelQ_e *)
+ pci_alloc_consistent(pdev, size, &q->dma_addr);
+ if (!q->entries)
+ goto err_no_mem;
+ memset(q->entries, 0, size);
+ size = sizeof(struct freelQ_ce) * q->size;
+ q->centries = kmalloc(size, GFP_KERNEL);
+ if (!q->centries)
+ goto err_no_mem;
+ memset(q->centries, 0, size);
+ }
+
+ /*
+ * Calculate the buffer sizes for the two free lists. FL0 accommodates
+ * regular sized Ethernet frames, FL1 is sized not to exceed 16K,
+ * including all the sk_buff overhead.
+ *
+ * Note: For T2 FL0 and FL1 are reversed.
+ */
+ sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE +
+ sizeof(struct cpl_rx_data) +
+ sge->freelQ[!sge->jumbo_fl].dma_offset;
+ sge->freelQ[sge->jumbo_fl].rx_buffer_size = (16 * 1024) -
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ /*
+ * Setup which skb recycle Q should be used when recycling buffers from
+ * each free list.
+ */
+ sge->freelQ[!sge->jumbo_fl].recycleq_idx = 0;
+ sge->freelQ[sge->jumbo_fl].recycleq_idx = 1;
+
+ sge->respQ.genbit = 1;
+ sge->respQ.size = SGE_RESPQ_E_N;
+ sge->respQ.credits = 0;
+ size = sizeof(struct respQ_e) * sge->respQ.size;
+ sge->respQ.entries = (struct respQ_e *)
+ pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr);
+ if (!sge->respQ.entries)
+ goto err_no_mem;
+ memset(sge->respQ.entries, 0, size);
+ return 0;
+
+err_no_mem:
+ free_rx_resources(sge);
+ return -ENOMEM;
+}
+
+/*
+ * Reclaims n TX descriptors and frees the buffers associated with them.
+ */
+static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n)
+{
+ struct cmdQ_ce *ce;
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int cidx = q->cidx;
+
+ q->in_use -= n;
+ ce = &q->centries[cidx];
+ while (n--) {
+ if (q->sop)
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ q->sop = 0;
+ if (ce->skb) {
+ dev_kfree_skb(ce->skb);
+ q->sop = 1;
+ }
+ ce++;
+ if (++cidx == q->size) {
+ cidx = 0;
+ ce = q->centries;
+ }
+ }
+ q->cidx = cidx;
+}
+
+/*
+ * Free TX resources.
+ *
+ * Assumes that SGE is stopped and all interrupts are disabled.
+ */
+static void free_tx_resources(struct sge *sge)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_CMDQ_N; i++) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ if (q->centries) {
+ if (q->in_use)
+ free_cmdQ_buffers(sge, q, q->in_use);
+ kfree(q->centries);
+ }
+ if (q->entries) {
+ size = sizeof(struct cmdQ_e) * q->size;
+ pci_free_consistent(pdev, size, q->entries,
+ q->dma_addr);
+ }
+ }
+}
+
+/*
+ * Allocates basic TX resources, consisting of memory mapped command Qs.
+ */
+static int alloc_tx_resources(struct sge *sge, struct sge_params *p)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ unsigned int size, i;
+
+ for (i = 0; i < SGE_CMDQ_N; i++) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ q->genbit = 1;
+ q->sop = 1;
+ q->size = p->cmdQ_size[i];
+ q->in_use = 0;
+ q->status = 0;
+ q->processed = q->cleaned = 0;
+ q->stop_thres = 0;
+ spin_lock_init(&q->lock);
+ size = sizeof(struct cmdQ_e) * q->size;
+ q->entries = (struct cmdQ_e *)
+ pci_alloc_consistent(pdev, size, &q->dma_addr);
+ if (!q->entries)
+ goto err_no_mem;
+ memset(q->entries, 0, size);
+ size = sizeof(struct cmdQ_ce) * q->size;
+ q->centries = kmalloc(size, GFP_KERNEL);
+ if (!q->centries)
+ goto err_no_mem;
+ memset(q->centries, 0, size);
+ }
+
+ /*
+ * CommandQ 0 handles Ethernet and TOE packets, while queue 1 is TOE
+ * only. For queue 0 set the stop threshold so we can handle one more
+ * packet from each port, plus reserve an additional 24 entries for
+ * Ethernet packets only. Queue 1 never suspends nor do we reserve
+ * space for Ethernet packets.
+ */
+ sge->cmdQ[0].stop_thres = sge->adapter->params.nports *
+ (MAX_SKB_FRAGS + 1);
+ return 0;
+
+err_no_mem:
+ free_tx_resources(sge);
+ return -ENOMEM;
+}
+
+static inline void setup_ring_params(struct adapter *adapter, u64 addr,
+ u32 size, int base_reg_lo,
+ int base_reg_hi, int size_reg)
+{
+ writel((u32)addr, adapter->regs + base_reg_lo);
+ writel(addr >> 32, adapter->regs + base_reg_hi);
+ writel(size, adapter->regs + size_reg);
+}
+
+/*
+ * Enable/disable VLAN acceleration.
+ */
+void t1_set_vlan_accel(struct adapter *adapter, int on_off)
+{
+ struct sge *sge = adapter->sge;
+
+ sge->sge_control &= ~F_VLAN_XTRACT;
+ if (on_off)
+ sge->sge_control |= F_VLAN_XTRACT;
+ if (adapter->open_device_map) {
+ writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
+ readl(adapter->regs + A_SG_CONTROL); /* flush */
+ }
+}
+
+/*
+ * Programs the various SGE registers. However, the engine is not yet enabled,
+ * but sge->sge_control is setup and ready to go.
+ */
+static void configure_sge(struct sge *sge, struct sge_params *p)
+{
+ struct adapter *ap = sge->adapter;
+
+ writel(0, ap->regs + A_SG_CONTROL);
+ setup_ring_params(ap, sge->cmdQ[0].dma_addr, sge->cmdQ[0].size,
+ A_SG_CMD0BASELWR, A_SG_CMD0BASEUPR, A_SG_CMD0SIZE);
+ setup_ring_params(ap, sge->cmdQ[1].dma_addr, sge->cmdQ[1].size,
+ A_SG_CMD1BASELWR, A_SG_CMD1BASEUPR, A_SG_CMD1SIZE);
+ setup_ring_params(ap, sge->freelQ[0].dma_addr,
+ sge->freelQ[0].size, A_SG_FL0BASELWR,
+ A_SG_FL0BASEUPR, A_SG_FL0SIZE);
+ setup_ring_params(ap, sge->freelQ[1].dma_addr,
+ sge->freelQ[1].size, A_SG_FL1BASELWR,
+ A_SG_FL1BASEUPR, A_SG_FL1SIZE);
+
+ /* The threshold comparison uses <. */
+ writel(SGE_RX_SM_BUF_SIZE + 1, ap->regs + A_SG_FLTHRESHOLD);
+
+ setup_ring_params(ap, sge->respQ.dma_addr, sge->respQ.size,
+ A_SG_RSPBASELWR, A_SG_RSPBASEUPR, A_SG_RSPSIZE);
+ writel((u32)sge->respQ.size - 1, ap->regs + A_SG_RSPQUEUECREDIT);
+
+ sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE |
+ F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE |
+ V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE |
+ F_DISABLE_FL0_GTS | F_DISABLE_FL1_GTS |
+ V_RX_PKT_OFFSET(sge->rx_pkt_pad);
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ sge->sge_control |= F_ENABLE_BIG_ENDIAN;
+#endif
+
+ /* Initialize no-resource timer */
+ sge->intrtimer_nres = SGE_INTRTIMER_NRES * core_ticks_per_usec(ap);
+
+ t1_sge_set_coalesce_params(sge, p);
+}
+
+/*
+ * Return the payload capacity of the jumbo free-list buffers.
+ */
+static inline unsigned int jumbo_payload_capacity(const struct sge *sge)
+{
+ return sge->freelQ[sge->jumbo_fl].rx_buffer_size -
+ sge->freelQ[sge->jumbo_fl].dma_offset -
+ sizeof(struct cpl_rx_data);
+}
+
+/*
+ * Frees all SGE related resources and the sge structure itself
+ */
+void t1_sge_destroy(struct sge *sge)
+{
+ if (sge->espibug_skb)
+ kfree_skb(sge->espibug_skb);
+
+ free_tx_resources(sge);
+ free_rx_resources(sge);
+ kfree(sge);
+}
+
+/*
+ * Allocates new RX buffers on the freelist Q (and tracks them on the freelist
+ * context Q) until the Q is full or alloc_skb fails.
+ *
+ * It is possible that the generation bits already match, indicating that the
+ * buffer is already valid and nothing needs to be done. This happens when we
+ * copied a received buffer into a new sk_buff during the interrupt processing.
+ *
+ * If the SGE doesn't automatically align packets properly (!sge->rx_pkt_pad),
+ * we specify a RX_OFFSET in order to make sure that the IP header is 4B
+ * aligned.
+ */
+static void refill_free_list(struct sge *sge, struct freelQ *q)
+{
+ struct pci_dev *pdev = sge->adapter->pdev;
+ struct freelQ_ce *ce = &q->centries[q->pidx];
+ struct freelQ_e *e = &q->entries[q->pidx];
+ unsigned int dma_len = q->rx_buffer_size - q->dma_offset;
+
+
+ while (q->credits < q->size) {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+
+ skb = alloc_skb(q->rx_buffer_size, GFP_ATOMIC);
+ if (!skb)
+ break;
+
+ skb_reserve(skb, q->dma_offset);
+ mapping = pci_map_single(pdev, skb->data, dma_len,
+ PCI_DMA_FROMDEVICE);
+ ce->skb = skb;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, dma_len);
+ e->addr_lo = (u32)mapping;
+ e->addr_hi = (u64)mapping >> 32;
+ e->len_gen = V_CMD_LEN(dma_len) | V_CMD_GEN1(q->genbit);
+ wmb();
+ e->gen2 = V_CMD_GEN2(q->genbit);
+
+ e++;
+ ce++;
+ if (++q->pidx == q->size) {
+ q->pidx = 0;
+ q->genbit ^= 1;
+ ce = q->centries;
+ e = q->entries;
+ }
+ q->credits++;
+ }
+
+}
+
+/*
+ * Calls refill_free_list for both free lists. If we cannot fill at least 1/4
+ * of both rings, we go into 'few interrupt mode' in order to give the system
+ * time to free up resources.
+ */
+static void freelQs_empty(struct sge *sge)
+{
+ struct adapter *adapter = sge->adapter;
+ u32 irq_reg = readl(adapter->regs + A_SG_INT_ENABLE);
+ u32 irqholdoff_reg;
+
+ refill_free_list(sge, &sge->freelQ[0]);
+ refill_free_list(sge, &sge->freelQ[1]);
+
+ if (sge->freelQ[0].credits > (sge->freelQ[0].size >> 2) &&
+ sge->freelQ[1].credits > (sge->freelQ[1].size >> 2)) {
+ irq_reg |= F_FL_EXHAUSTED;
+ irqholdoff_reg = sge->fixed_intrtimer;
+ } else {
+ /* Clear the F_FL_EXHAUSTED interrupts for now */
+ irq_reg &= ~F_FL_EXHAUSTED;
+ irqholdoff_reg = sge->intrtimer_nres;
+ }
+ writel(irqholdoff_reg, adapter->regs + A_SG_INTRTIMER);
+ writel(irq_reg, adapter->regs + A_SG_INT_ENABLE);
+
+ /* We reenable the Qs to force a freelist GTS interrupt later */
+ doorbell_pio(adapter, F_FL0_ENABLE | F_FL1_ENABLE);
+}
+
+#define SGE_PL_INTR_MASK (F_PL_INTR_SGE_ERR | F_PL_INTR_SGE_DATA)
+#define SGE_INT_FATAL (F_RESPQ_OVERFLOW | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
+#define SGE_INT_ENABLE (F_RESPQ_EXHAUSTED | F_RESPQ_OVERFLOW | \
+ F_FL_EXHAUSTED | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
+
+/*
+ * Disable SGE Interrupts
+ */
+void t1_sge_intr_disable(struct sge *sge)
+{
+ u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
+
+ writel(val & ~SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
+ writel(0, sge->adapter->regs + A_SG_INT_ENABLE);
+}
+
+/*
+ * Enable SGE interrupts.
+ */
+void t1_sge_intr_enable(struct sge *sge)
+{
+ u32 en = SGE_INT_ENABLE;
+ u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
+
+ if (sge->adapter->flags & TSO_CAPABLE)
+ en &= ~F_PACKET_TOO_BIG;
+ writel(en, sge->adapter->regs + A_SG_INT_ENABLE);
+ writel(val | SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
+}
+
+/*
+ * Clear SGE interrupts.
+ */
+void t1_sge_intr_clear(struct sge *sge)
+{
+ writel(SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_CAUSE);
+ writel(0xffffffff, sge->adapter->regs + A_SG_INT_CAUSE);
+}
+
+/*
+ * SGE 'Error' interrupt handler
+ */
+int t1_sge_intr_error_handler(struct sge *sge)
+{
+ struct adapter *adapter = sge->adapter;
+ u32 cause = readl(adapter->regs + A_SG_INT_CAUSE);
+
+ if (adapter->flags & TSO_CAPABLE)
+ cause &= ~F_PACKET_TOO_BIG;
+ if (cause & F_RESPQ_EXHAUSTED)
+ sge->stats.respQ_empty++;
+ if (cause & F_RESPQ_OVERFLOW) {
+ sge->stats.respQ_overflow++;
+ CH_ALERT("%s: SGE response queue overflow\n",
+ adapter->name);
+ }
+ if (cause & F_FL_EXHAUSTED) {
+ sge->stats.freelistQ_empty++;
+ freelQs_empty(sge);
+ }
+ if (cause & F_PACKET_TOO_BIG) {
+ sge->stats.pkt_too_big++;
+ CH_ALERT("%s: SGE max packet size exceeded\n",
+ adapter->name);
+ }
+ if (cause & F_PACKET_MISMATCH) {
+ sge->stats.pkt_mismatch++;
+ CH_ALERT("%s: SGE packet mismatch\n", adapter->name);
+ }
+ if (cause & SGE_INT_FATAL)
+ t1_fatal_err(adapter);
+
+ writel(cause, adapter->regs + A_SG_INT_CAUSE);
+ return 0;
+}
+
+const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge)
+{
+ return &sge->stats;
+}
+
+const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port)
+{
+ return &sge->port_stats[port];
+}
+
+/**
+ * recycle_fl_buf - recycle a free list buffer
+ * @fl: the free list
+ * @idx: index of buffer to recycle
+ *
+ * Recycles the specified buffer on the given free list by adding it at
+ * the next available slot on the list.
+ */
+static void recycle_fl_buf(struct freelQ *fl, int idx)
+{
+ struct freelQ_e *from = &fl->entries[idx];
+ struct freelQ_e *to = &fl->entries[fl->pidx];
+
+ fl->centries[fl->pidx] = fl->centries[idx];
+ to->addr_lo = from->addr_lo;
+ to->addr_hi = from->addr_hi;
+ to->len_gen = G_CMD_LEN(from->len_gen) | V_CMD_GEN1(fl->genbit);
+ wmb();
+ to->gen2 = V_CMD_GEN2(fl->genbit);
+ fl->credits++;
+
+ if (++fl->pidx == fl->size) {
+ fl->pidx = 0;
+ fl->genbit ^= 1;
+ }
+}
+
+/**
+ * get_packet - return the next ingress packet buffer
+ * @pdev: the PCI device that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the actual packet length, excluding any SGE padding
+ * @dma_pad: padding at beginning of buffer left by SGE DMA
+ * @skb_pad: padding to be used if the packet is copied
+ * @copy_thres: length threshold under which a packet should be copied
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list and complete setup of the
+ * sk_buff. If the packet is small we make a copy and recycle the
+ * original buffer, otherwise we use the original buffer itself. If a
+ * positive drop threshold is supplied packets are dropped and their
+ * buffers recycled if (a) the number of remaining buffers is under the
+ * threshold and the packet is too big to copy, or (b) the packet should
+ * be copied but there is no memory for the copy.
+ */
+static inline struct sk_buff *get_packet(struct pci_dev *pdev,
+ struct freelQ *fl, unsigned int len,
+ int dma_pad, int skb_pad,
+ unsigned int copy_thres,
+ unsigned int drop_thres)
+{
+ struct sk_buff *skb;
+ struct freelQ_ce *ce = &fl->centries[fl->cidx];
+
+ if (len < copy_thres) {
+ skb = alloc_skb(len + skb_pad, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ skb_reserve(skb, skb_pad);
+ skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, ce->skb->data + dma_pad, len);
+ pci_dma_sync_single_for_device(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ goto use_orig_buf;
+
+ recycle_fl_buf(fl, fl->cidx);
+ return skb;
+ }
+
+ if (fl->credits < drop_thres) {
+ recycle_fl_buf(fl, fl->cidx);
+ return NULL;
+ }
+
+use_orig_buf:
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
+ skb = ce->skb;
+ skb_reserve(skb, dma_pad);
+ skb_put(skb, len);
+ return skb;
+}
+
+/**
+ * unexpected_offload - handle an unexpected offload packet
+ * @adapter: the adapter
+ * @fl: the free list that received the packet
+ *
+ * Called when we receive an unexpected offload packet (e.g., the TOE
+ * function is disabled or the card is a NIC). Prints a message and
+ * recycles the buffer.
+ */
+static void unexpected_offload(struct adapter *adapter, struct freelQ *fl)
+{
+ struct freelQ_ce *ce = &fl->centries[fl->cidx];
+ struct sk_buff *skb = ce->skb;
+
+ pci_dma_sync_single_for_cpu(adapter->pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
+ CH_ERR("%s: unexpected offload packet, cmd %u\n",
+ adapter->name, *skb->data);
+ recycle_fl_buf(fl, fl->cidx);
+}
+
+/*
+ * Write the command descriptors to transmit the given skb starting at
+ * descriptor pidx with the given generation.
+ */
+static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
+ unsigned int pidx, unsigned int gen,
+ struct cmdQ *q)
+{
+ dma_addr_t mapping;
+ struct cmdQ_e *e, *e1;
+ struct cmdQ_ce *ce;
+ unsigned int i, flags, nfrags = skb_shinfo(skb)->nr_frags;
+
+ mapping = pci_map_single(adapter->pdev, skb->data,
+ skb->len - skb->data_len, PCI_DMA_TODEVICE);
+ ce = &q->centries[pidx];
+ ce->skb = NULL;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, skb->len - skb->data_len);
+
+ flags = F_CMD_DATAVALID | F_CMD_SOP | V_CMD_EOP(nfrags == 0) |
+ V_CMD_GEN2(gen);
+ e = &q->entries[pidx];
+ e->addr_lo = (u32)mapping;
+ e->addr_hi = (u64)mapping >> 32;
+ e->len_gen = V_CMD_LEN(skb->len - skb->data_len) | V_CMD_GEN1(gen);
+ for (e1 = e, i = 0; nfrags--; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ ce++;
+ e1++;
+ if (++pidx == q->size) {
+ pidx = 0;
+ gen ^= 1;
+ ce = q->centries;
+ e1 = q->entries;
+ }
+
+ mapping = pci_map_page(adapter->pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+ ce->skb = NULL;
+ pci_unmap_addr_set(ce, dma_addr, mapping);
+ pci_unmap_len_set(ce, dma_len, frag->size);
+
+ e1->addr_lo = (u32)mapping;
+ e1->addr_hi = (u64)mapping >> 32;
+ e1->len_gen = V_CMD_LEN(frag->size) | V_CMD_GEN1(gen);
+ e1->flags = F_CMD_DATAVALID | V_CMD_EOP(nfrags == 0) |
+ V_CMD_GEN2(gen);
+ }
+
+ ce->skb = skb;
+ wmb();
+ e->flags = flags;
+}
+
+/*
+ * Clean up completed Tx buffers.
+ */
+static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q)
+{
+ unsigned int reclaim = q->processed - q->cleaned;
+
+ if (reclaim) {
+ free_cmdQ_buffers(sge, q, reclaim);
+ q->cleaned += reclaim;
+ }
+}
+
+#ifndef SET_ETHTOOL_OPS
+# define __netif_rx_complete(dev) netif_rx_complete(dev)
+#endif
+
+/*
+ * We cannot use the standard netif_rx_schedule_prep() because we have multiple
+ * ports plus the TOE all multiplexing onto a single response queue, therefore
+ * accepting new responses cannot depend on the state of any particular port.
+ * So define our own equivalent that omits the netif_running() test.
+ */
+static inline int napi_schedule_prep(struct net_device *dev)
+{
+ return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+
+/**
+ * sge_rx - process an ingress ethernet packet
+ * @sge: the sge structure
+ * @fl: the free list that contains the packet buffer
+ * @len: the packet length
+ *
+ * Process an ingress ethernet pakcet and deliver it to the stack.
+ */
+static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
+{
+ struct sk_buff *skb;
+ struct cpl_rx_pkt *p;
+ struct adapter *adapter = sge->adapter;
+
+ sge->stats.ethernet_pkts++;
+ skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad,
+ sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES,
+ SGE_RX_DROP_THRES);
+ if (!skb) {
+ sge->port_stats[0].rx_drops++; /* charge only port 0 for now */
+ return 0;
+ }
+
+ p = (struct cpl_rx_pkt *)skb->data;
+ skb_pull(skb, sizeof(*p));
+ skb->dev = adapter->port[p->iff].dev;
+ skb->dev->last_rx = jiffies;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
+ skb->protocol == htons(ETH_P_IP) &&
+ (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
+ sge->port_stats[p->iff].rx_cso_good++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
+ sge->port_stats[p->iff].vlan_xtract++;
+ if (adapter->params.sge.polling)
+ vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
+ ntohs(p->vlan));
+ else
+ vlan_hwaccel_rx(skb, adapter->vlan_grp,
+ ntohs(p->vlan));
+ } else if (adapter->params.sge.polling)
+ netif_receive_skb(skb);
+ else
+ netif_rx(skb);
+ return 0;
+}
+
+/*
+ * Returns true if a command queue has enough available descriptors that
+ * we can resume Tx operation after temporarily disabling its packet queue.
+ */
+static inline int enough_free_Tx_descs(const struct cmdQ *q)
+{
+ unsigned int r = q->processed - q->cleaned;
+
+ return q->in_use - r < (q->size >> 1);
+}
+
+/*
+ * Called when sufficient space has become available in the SGE command queues
+ * after the Tx packet schedulers have been suspended to restart the Tx path.
+ */
+static void restart_tx_queues(struct sge *sge)
+{
+ struct adapter *adap = sge->adapter;
+
+ if (enough_free_Tx_descs(&sge->cmdQ[0])) {
+ int i;
+
+ for_each_port(adap, i) {
+ struct net_device *nd = adap->port[i].dev;
+
+ if (test_and_clear_bit(nd->if_port,
+ &sge->stopped_tx_queues) &&
+ netif_running(nd)) {
+ sge->stats.cmdQ_restarted[3]++;
+ netif_wake_queue(nd);
+ }
+ }
+ }
+}
+
+/*
+ * update_tx_info is called from the interrupt handler/NAPI to return cmdQ0
+ * information.
+ */
+static unsigned int update_tx_info(struct adapter *adapter,
+ unsigned int flags,
+ unsigned int pr0)
+{
+ struct sge *sge = adapter->sge;
+ struct cmdQ *cmdq = &sge->cmdQ[0];
+
+ cmdq->processed += pr0;
+
+ if (flags & F_CMDQ0_ENABLE) {
+ clear_bit(CMDQ_STAT_RUNNING, &cmdq->status);
+
+ if (cmdq->cleaned + cmdq->in_use != cmdq->processed &&
+ !test_and_set_bit(CMDQ_STAT_LAST_PKT_DB, &cmdq->status)) {
+ set_bit(CMDQ_STAT_RUNNING, &cmdq->status);
+ writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
+ }
+ flags &= ~F_CMDQ0_ENABLE;
+ }
+
+ if (unlikely(sge->stopped_tx_queues != 0))
+ restart_tx_queues(sge);
+
+ return flags;
+}
+
+/*
+ * Process SGE responses, up to the supplied budget. Returns the number of
+ * responses processed. A negative budget is effectively unlimited.
+ */
+static int process_responses(struct adapter *adapter, int budget)
+{
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &sge->respQ;
+ struct respQ_e *e = &q->entries[q->cidx];
+ int budget_left = budget;
+ unsigned int flags = 0;
+ unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
+
+
+ while (likely(budget_left && e->GenerationBit == q->genbit)) {
+ flags |= e->Qsleeping;
+
+ cmdq_processed[0] += e->Cmdq0CreditReturn;
+ cmdq_processed[1] += e->Cmdq1CreditReturn;
+
+ /* We batch updates to the TX side to avoid cacheline
+ * ping-pong of TX state information on MP where the sender
+ * might run on a different CPU than this function...
+ */
+ if (unlikely(flags & F_CMDQ0_ENABLE || cmdq_processed[0] > 64)) {
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ cmdq_processed[0] = 0;
+ }
+ if (unlikely(cmdq_processed[1] > 16)) {
+ sge->cmdQ[1].processed += cmdq_processed[1];
+ cmdq_processed[1] = 0;
+ }
+ if (likely(e->DataValid)) {
+ struct freelQ *fl = &sge->freelQ[e->FreelistQid];
+
+ if (unlikely(!e->Sop || !e->Eop))
+ BUG();
+ if (unlikely(e->Offload))
+ unexpected_offload(adapter, fl);
+ else
+ sge_rx(sge, fl, e->BufferLength);
+
+ /*
+ * Note: this depends on each packet consuming a
+ * single free-list buffer; cf. the BUG above.
+ */
+ if (++fl->cidx == fl->size)
+ fl->cidx = 0;
+ if (unlikely(--fl->credits <
+ fl->size - SGE_FREEL_REFILL_THRESH))
+ refill_free_list(sge, fl);
+ } else
+ sge->stats.pure_rsps++;
+
+ e++;
+ if (unlikely(++q->cidx == q->size)) {
+ q->cidx = 0;
+ q->genbit ^= 1;
+ e = q->entries;
+ }
+ prefetch(e);
+
+ if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
+ writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
+ q->credits = 0;
+ }
+ --budget_left;
+ }
+
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ sge->cmdQ[1].processed += cmdq_processed[1];
+
+ budget -= budget_left;
+ return budget;
+}
+
+/*
+ * A simpler version of process_responses() that handles only pure (i.e.,
+ * non data-carrying) responses. Such respones are too light-weight to justify
+ * calling a softirq when using NAPI, so we handle them specially in hard
+ * interrupt context. The function is called with a pointer to a response,
+ * which the caller must ensure is a valid pure response. Returns 1 if it
+ * encounters a valid data-carrying response, 0 otherwise.
+ */
+static int process_pure_responses(struct adapter *adapter, struct respQ_e *e)
+{
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &sge->respQ;
+ unsigned int flags = 0;
+ unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
+
+ do {
+ flags |= e->Qsleeping;
+
+ cmdq_processed[0] += e->Cmdq0CreditReturn;
+ cmdq_processed[1] += e->Cmdq1CreditReturn;
+
+ e++;
+ if (unlikely(++q->cidx == q->size)) {
+ q->cidx = 0;
+ q->genbit ^= 1;
+ e = q->entries;
+ }
+ prefetch(e);
+
+ if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
+ writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
+ q->credits = 0;
+ }
+ sge->stats.pure_rsps++;
+ } while (e->GenerationBit == q->genbit && !e->DataValid);
+
+ flags = update_tx_info(adapter, flags, cmdq_processed[0]);
+ sge->cmdQ[1].processed += cmdq_processed[1];
+
+ return e->GenerationBit == q->genbit;
+}
+
+/*
+ * Handler for new data events when using NAPI. This does not need any locking
+ * or protection from interrupts as data interrupts are off at this point and
+ * other adapter interrupts do not interfere.
+ */
+static int t1_poll(struct net_device *dev, int *budget)
+{
+ struct adapter *adapter = dev->priv;
+ int effective_budget = min(*budget, dev->quota);
+
+ int work_done = process_responses(adapter, effective_budget);
+ *budget -= work_done;
+ dev->quota -= work_done;
+
+ if (work_done >= effective_budget)
+ return 1;
+
+ __netif_rx_complete(dev);
+
+ /*
+ * Because we don't atomically flush the following write it is
+ * possible that in very rare cases it can reach the device in a way
+ * that races with a new response being written plus an error interrupt
+ * causing the NAPI interrupt handler below to return unhandled status
+ * to the OS. To protect against this would require flushing the write
+ * and doing both the write and the flush with interrupts off. Way too
+ * expensive and unjustifiable given the rarity of the race.
+ */
+ writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
+ return 0;
+}
+
+/*
+ * Returns true if the device is already scheduled for polling.
+ */
+static inline int napi_is_scheduled(struct net_device *dev)
+{
+ return test_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+/*
+ * NAPI version of the main interrupt handler.
+ */
+static irqreturn_t t1_interrupt_napi(int irq, void *data, struct pt_regs *regs)
+{
+ int handled;
+ struct adapter *adapter = data;
+ struct sge *sge = adapter->sge;
+ struct respQ *q = &adapter->sge->respQ;
+
+ /*
+ * Clear the SGE_DATA interrupt first thing. Normally the NAPI
+ * handler has control of the response queue and the interrupt handler
+ * can look at the queue reliably only once it knows NAPI is off.
+ * We can't wait that long to clear the SGE_DATA interrupt because we
+ * could race with t1_poll rearming the SGE interrupt, so we need to
+ * clear the interrupt speculatively and really early on.
+ */
+ writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+ spin_lock(&adapter->async_lock);
+ if (!napi_is_scheduled(sge->netdev)) {
+ struct respQ_e *e = &q->entries[q->cidx];
+
+ if (e->GenerationBit == q->genbit) {
+ if (e->DataValid ||
+ process_pure_responses(adapter, e)) {
+ if (likely(napi_schedule_prep(sge->netdev)))
+ __netif_rx_schedule(sge->netdev);
+ else
+ printk(KERN_CRIT
+ "NAPI schedule failure!\n");
+ } else
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ handled = 1;
+ goto unlock;
+ } else
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ } else
+ if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA)
+ printk(KERN_ERR "data interrupt while NAPI running\n");
+
+ handled = t1_slow_intr_handler(adapter);
+ if (!handled)
+ sge->stats.unhandled_irqs++;
+ unlock:
+ spin_unlock(&adapter->async_lock);
+ return IRQ_RETVAL(handled != 0);
+}
+
+/*
+ * Main interrupt handler, optimized assuming that we took a 'DATA'
+ * interrupt.
+ *
+ * 1. Clear the interrupt
+ * 2. Loop while we find valid descriptors and process them; accumulate
+ * information that can be processed after the loop
+ * 3. Tell the SGE at which index we stopped processing descriptors
+ * 4. Bookkeeping; free TX buffers, ring doorbell if there are any
+ * outstanding TX buffers waiting, replenish RX buffers, potentially
+ * reenable upper layers if they were turned off due to lack of TX
+ * resources which are available again.
+ * 5. If we took an interrupt, but no valid respQ descriptors was found we
+ * let the slow_intr_handler run and do error handling.
+ */
+static irqreturn_t t1_interrupt(int irq, void *cookie, struct pt_regs *regs)
+{
+ int work_done;
+ struct respQ_e *e;
+ struct adapter *adapter = cookie;
+ struct respQ *Q = &adapter->sge->respQ;
+
+ spin_lock(&adapter->async_lock);
+ e = &Q->entries[Q->cidx];
+ prefetch(e);
+
+ writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+ if (likely(e->GenerationBit == Q->genbit))
+ work_done = process_responses(adapter, -1);
+ else
+ work_done = t1_slow_intr_handler(adapter);
+
+ /*
+ * The unconditional clearing of the PL_CAUSE above may have raced
+ * with DMA completion and the corresponding generation of a response
+ * to cause us to miss the resulting data interrupt. The next write
+ * is also unconditional to recover the missed interrupt and render
+ * this race harmless.
+ */
+ writel(Q->cidx, adapter->regs + A_SG_SLEEPING);
+
+ if (!work_done)
+ adapter->sge->stats.unhandled_irqs++;
+ spin_unlock(&adapter->async_lock);
+ return IRQ_RETVAL(work_done != 0);
+}
+
+intr_handler_t t1_select_intr_handler(adapter_t *adapter)
+{
+ return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
+}
+
+/*
+ * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
+ *
+ * The code figures out how many entries the sk_buff will require in the
+ * cmdQ and updates the cmdQ data structure with the state once the enqueue
+ * has complete. Then, it doesn't access the global structure anymore, but
+ * uses the corresponding fields on the stack. In conjuction with a spinlock
+ * around that code, we can make the function reentrant without holding the
+ * lock when we actually enqueue (which might be expensive, especially on
+ * architectures with IO MMUs).
+ *
+ * This runs with softirqs disabled.
+ */
+unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
+ unsigned int qid, struct net_device *dev)
+{
+ struct sge *sge = adapter->sge;
+ struct cmdQ *q = &sge->cmdQ[qid];
+ unsigned int credits, pidx, genbit, count;
+
+ spin_lock(&q->lock);
+ reclaim_completed_tx(sge, q);
+
+ pidx = q->pidx;
+ credits = q->size - q->in_use;
+ count = 1 + skb_shinfo(skb)->nr_frags;
+
+ { /* Ethernet packet */
+ if (unlikely(credits < count)) {
+ netif_stop_queue(dev);
+ set_bit(dev->if_port, &sge->stopped_tx_queues);
+ sge->stats.cmdQ_full[3]++;
+ spin_unlock(&q->lock);
+ CH_ERR("%s: Tx ring full while queue awake!\n",
+ adapter->name);
+ return 1;
+ }
+ if (unlikely(credits - count < q->stop_thres)) {
+ sge->stats.cmdQ_full[3]++;
+ netif_stop_queue(dev);
+ set_bit(dev->if_port, &sge->stopped_tx_queues);
+ }
+ }
+ q->in_use += count;
+ genbit = q->genbit;
+ q->pidx += count;
+ if (q->pidx >= q->size) {
+ q->pidx -= q->size;
+ q->genbit ^= 1;
+ }
+ spin_unlock(&q->lock);
+
+ write_tx_descs(adapter, skb, pidx, genbit, q);
+
+ /*
+ * We always ring the doorbell for cmdQ1. For cmdQ0, we only ring
+ * the doorbell if the Q is asleep. There is a natural race, where
+ * the hardware is going to sleep just after we checked, however,
+ * then the interrupt handler will detect the outstanding TX packet
+ * and ring the doorbell for us.
+ */
+ if (qid)
+ doorbell_pio(adapter, F_CMDQ1_ENABLE);
+ else {
+ clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
+ set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
+ writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
+ }
+ }
+ return 0;
+}
+
+#define MK_ETH_TYPE_MSS(type, mss) (((mss) & 0x3FFF) | ((type) << 14))
+
+/*
+ * eth_hdr_len - return the length of an Ethernet header
+ * @data: pointer to the start of the Ethernet header
+ *
+ * Returns the length of an Ethernet header, including optional VLAN tag.
+ */
+static inline int eth_hdr_len(const void *data)
+{
+ const struct ethhdr *e = data;
+
+ return e->h_proto == htons(ETH_P_8021Q) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+/*
+ * Adds the CPL header to the sk_buff and passes it to t1_sge_tx.
+ */
+int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct adapter *adapter = dev->priv;
+ struct sge_port_stats *st = &adapter->sge->port_stats[dev->if_port];
+ struct sge *sge = adapter->sge;
+ struct cpl_tx_pkt *cpl;
+
+#ifdef NETIF_F_TSO
+ if (skb_shinfo(skb)->tso_size) {
+ int eth_type;
+ struct cpl_tx_pkt_lso *hdr;
+
+ st->tso++;
+
+ eth_type = skb->nh.raw - skb->data == ETH_HLEN ?
+ CPL_ETH_II : CPL_ETH_II_VLAN;
+
+ hdr = (struct cpl_tx_pkt_lso *)skb_push(skb, sizeof(*hdr));
+ hdr->opcode = CPL_TX_PKT_LSO;
+ hdr->ip_csum_dis = hdr->l4_csum_dis = 0;
+ hdr->ip_hdr_words = skb->nh.iph->ihl;
+ hdr->tcp_hdr_words = skb->h.th->doff;
+ hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
+ skb_shinfo(skb)->tso_size));
+ hdr->len = htonl(skb->len - sizeof(*hdr));
+ cpl = (struct cpl_tx_pkt *)hdr;
+ sge->stats.tx_lso_pkts++;
+ } else
+#endif
+ {
+ /*
+ * Packets shorter than ETH_HLEN can break the MAC, drop them
+ * early. Also, we may get oversized packets because some
+ * parts of the kernel don't handle our unusual hard_header_len
+ * right, drop those too.
+ */
+ if (unlikely(skb->len < ETH_HLEN ||
+ skb->len > dev->mtu + eth_hdr_len(skb->data))) {
+ dev_kfree_skb_any(skb);
+ return NET_XMIT_SUCCESS;
+ }
+
+ /*
+ * We are using a non-standard hard_header_len and some kernel
+ * components, such as pktgen, do not handle it right.
+ * Complain when this happens but try to fix things up.
+ */
+ if (unlikely(skb_headroom(skb) <
+ dev->hard_header_len - ETH_HLEN)) {
+ struct sk_buff *orig_skb = skb;
+
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: inadequate headroom in "
+ "Tx packet\n", dev->name);
+ skb = skb_realloc_headroom(skb, sizeof(*cpl));
+ dev_kfree_skb_any(orig_skb);
+ if (!skb)
+ return -ENOMEM;
+ }
+
+ if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
+ skb->ip_summed == CHECKSUM_HW &&
+ skb->nh.iph->protocol == IPPROTO_UDP)
+ if (unlikely(skb_checksum_help(skb, 0))) {
+ dev_kfree_skb_any(skb);
+ return -ENOMEM;
+ }
+
+ /* Hmmm, assuming to catch the gratious arp... and we'll use
+ * it to flush out stuck espi packets...
+ */
+ if (unlikely(!adapter->sge->espibug_skb)) {
+ if (skb->protocol == htons(ETH_P_ARP) &&
+ skb->nh.arph->ar_op == htons(ARPOP_REQUEST)) {
+ adapter->sge->espibug_skb = skb;
+ /* We want to re-use this skb later. We
+ * simply bump the reference count and it
+ * will not be freed...
+ */
+ skb = skb_get(skb);
+ }
+ }
+
+ cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl));
+ cpl->opcode = CPL_TX_PKT;
+ cpl->ip_csum_dis = 1; /* SW calculates IP csum */
+ cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_HW ? 0 : 1;
+ /* the length field isn't used so don't bother setting it */
+
+ st->tx_cso += (skb->ip_summed == CHECKSUM_HW);
+ sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_HW);
+ sge->stats.tx_reg_pkts++;
+ }
+ cpl->iff = dev->if_port;
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+ cpl->vlan_valid = 1;
+ cpl->vlan = htons(vlan_tx_tag_get(skb));
+ st->vlan_insert++;
+ } else
+#endif
+ cpl->vlan_valid = 0;
+
+ dev->trans_start = jiffies;
+ return t1_sge_tx(skb, adapter, 0, dev);
+}
+
+/*
+ * Callback for the Tx buffer reclaim timer. Runs with softirqs disabled.
+ */
+static void sge_tx_reclaim_cb(unsigned long data)
+{
+ int i;
+ struct sge *sge = (struct sge *)data;
+
+ for (i = 0; i < SGE_CMDQ_N; ++i) {
+ struct cmdQ *q = &sge->cmdQ[i];
+
+ if (!spin_trylock(&q->lock))
+ continue;
+
+ reclaim_completed_tx(sge, q);
+ if (i == 0 && q->in_use) /* flush pending credits */
+ writel(F_CMDQ0_ENABLE,
+ sge->adapter->regs + A_SG_DOORBELL);
+
+ spin_unlock(&q->lock);
+ }
+ mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+}
+
+/*
+ * Propagate changes of the SGE coalescing parameters to the HW.
+ */
+int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
+{
+ sge->netdev->poll = t1_poll;
+ sge->fixed_intrtimer = p->rx_coalesce_usecs *
+ core_ticks_per_usec(sge->adapter);
+ writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
+ return 0;
+}
+
+/*
+ * Allocates both RX and TX resources and configures the SGE. However,
+ * the hardware is not enabled yet.
+ */
+int t1_sge_configure(struct sge *sge, struct sge_params *p)
+{
+ if (alloc_rx_resources(sge, p))
+ return -ENOMEM;
+ if (alloc_tx_resources(sge, p)) {
+ free_rx_resources(sge);
+ return -ENOMEM;
+ }
+ configure_sge(sge, p);
+
+ /*
+ * Now that we have sized the free lists calculate the payload
+ * capacity of the large buffers. Other parts of the driver use
+ * this to set the max offload coalescing size so that RX packets
+ * do not overflow our large buffers.
+ */
+ p->large_buf_capacity = jumbo_payload_capacity(sge);
+ return 0;
+}
+
+/*
+ * Disables the DMA engine.
+ */
+void t1_sge_stop(struct sge *sge)
+{
+ writel(0, sge->adapter->regs + A_SG_CONTROL);
+ (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+ if (is_T2(sge->adapter))
+ del_timer_sync(&sge->espibug_timer);
+ del_timer_sync(&sge->tx_reclaim_timer);
+}
+
+/*
+ * Enables the DMA engine.
+ */
+void t1_sge_start(struct sge *sge)
+{
+ refill_free_list(sge, &sge->freelQ[0]);
+ refill_free_list(sge, &sge->freelQ[1]);
+
+ writel(sge->sge_control, sge->adapter->regs + A_SG_CONTROL);
+ doorbell_pio(sge->adapter, F_FL0_ENABLE | F_FL1_ENABLE);
+ (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
+
+ mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+
+ if (is_T2(sge->adapter))
+ mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
+}
+
+/*
+ * Callback for the T2 ESPI 'stuck packet feature' workaorund
+ */
+static void espibug_workaround(void *data)
+{
+ struct adapter *adapter = (struct adapter *)data;
+ struct sge *sge = adapter->sge;
+
+ if (netif_running(adapter->port[0].dev)) {
+ struct sk_buff *skb = sge->espibug_skb;
+
+ u32 seop = t1_espi_get_mon(adapter, 0x930, 0);
+
+ if ((seop & 0xfff0fff) == 0xfff && skb) {
+ if (!skb->cb[0]) {
+ u8 ch_mac_addr[ETH_ALEN] =
+ {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
+ memcpy(skb->data + sizeof(struct cpl_tx_pkt),
+ ch_mac_addr, ETH_ALEN);
+ memcpy(skb->data + skb->len - 10, ch_mac_addr,
+ ETH_ALEN);
+ skb->cb[0] = 0xff;
+ }
+
+ /* bump the reference count to avoid freeing of the
+ * skb once the DMA has completed.
+ */
+ skb = skb_get(skb);
+ t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
+ }
+ }
+ mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
+}
+
+/*
+ * Creates a t1_sge structure and returns suggested resource parameters.
+ */
+struct sge * __devinit t1_sge_create(struct adapter *adapter,
+ struct sge_params *p)
+{
+ struct sge *sge = kmalloc(sizeof(*sge), GFP_KERNEL);
+
+ if (!sge)
+ return NULL;
+ memset(sge, 0, sizeof(*sge));
+
+ sge->adapter = adapter;
+ sge->netdev = adapter->port[0].dev;
+ sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2;
+ sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
+
+ init_timer(&sge->tx_reclaim_timer);
+ sge->tx_reclaim_timer.data = (unsigned long)sge;
+ sge->tx_reclaim_timer.function = sge_tx_reclaim_cb;
+
+ if (is_T2(sge->adapter)) {
+ init_timer(&sge->espibug_timer);
+ sge->espibug_timer.function = (void *)&espibug_workaround;
+ sge->espibug_timer.data = (unsigned long)sge->adapter;
+ sge->espibug_timeout = 1;
+ }
+
+
+ p->cmdQ_size[0] = SGE_CMDQ0_E_N;
+ p->cmdQ_size[1] = SGE_CMDQ1_E_N;
+ p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE;
+ p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE;
+ p->rx_coalesce_usecs = 50;
+ p->coalesce_enable = 0;
+ p->sample_interval_usecs = 0;
+ p->polling = 0;
+
+ return sge;
+}
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
new file mode 100644
index 000000000000..434b25586851
--- /dev/null
+++ b/drivers/net/chelsio/sge.h
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ * *
+ * File: sge.h *
+ * $Revision: 1.11 $ *
+ * $Date: 2005/06/21 22:10:55 $ *
+ * Description: *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_SGE_H_
+#define _CXGB_SGE_H_
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <asm/byteorder.h>
+
+#ifndef IRQ_RETVAL
+#define IRQ_RETVAL(x)
+typedef void irqreturn_t;
+#endif
+
+typedef irqreturn_t (*intr_handler_t)(int, void *, struct pt_regs *);
+
+struct sge_intr_counts {
+ unsigned int respQ_empty; /* # times respQ empty */
+ unsigned int respQ_overflow; /* # respQ overflow (fatal) */
+ unsigned int freelistQ_empty; /* # times freelist empty */
+ unsigned int pkt_too_big; /* packet too large (fatal) */
+ unsigned int pkt_mismatch;
+ unsigned int cmdQ_full[3]; /* not HW IRQ, host cmdQ[] full */
+ unsigned int cmdQ_restarted[3];/* # of times cmdQ X was restarted */
+ unsigned int ethernet_pkts; /* # of Ethernet packets received */
+ unsigned int offload_pkts; /* # of offload packets received */
+ unsigned int offload_bundles; /* # of offload pkt bundles delivered */
+ unsigned int pure_rsps; /* # of non-payload responses */
+ unsigned int unhandled_irqs; /* # of unhandled interrupts */
+ unsigned int tx_ipfrags;
+ unsigned int tx_reg_pkts;
+ unsigned int tx_lso_pkts;
+ unsigned int tx_do_cksum;
+};
+
+struct sge_port_stats {
+ unsigned long rx_cso_good; /* # of successful RX csum offloads */
+ unsigned long tx_cso; /* # of TX checksum offloads */
+ unsigned long vlan_xtract; /* # of VLAN tag extractions */
+ unsigned long vlan_insert; /* # of VLAN tag extractions */
+ unsigned long tso; /* # of TSO requests */
+ unsigned long rx_drops; /* # of packets dropped due to no mem */
+};
+
+struct sk_buff;
+struct net_device;
+struct adapter;
+struct sge_params;
+struct sge;
+
+struct sge *t1_sge_create(struct adapter *, struct sge_params *);
+int t1_sge_configure(struct sge *, struct sge_params *);
+int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
+void t1_sge_destroy(struct sge *);
+intr_handler_t t1_select_intr_handler(adapter_t *adapter);
+unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
+ unsigned int qid, struct net_device *netdev);
+int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void t1_set_vlan_accel(struct adapter *adapter, int on_off);
+void t1_sge_start(struct sge *);
+void t1_sge_stop(struct sge *);
+int t1_sge_intr_error_handler(struct sge *);
+void t1_sge_intr_enable(struct sge *);
+void t1_sge_intr_disable(struct sge *);
+void t1_sge_intr_clear(struct sge *);
+const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge);
+const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port);
+
+#endif /* _CXGB_SGE_H_ */
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c
new file mode 100644
index 000000000000..1ebb5d149aef
--- /dev/null
+++ b/drivers/net/chelsio/subr.c
@@ -0,0 +1,812 @@
+/*****************************************************************************
+ * *
+ * File: subr.c *
+ * $Revision: 1.27 $ *
+ * $Date: 2005/06/22 01:08:36 $ *
+ * Description: *
+ * Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
+ * All rights reserved. *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: Dimitrios Michailidis <dm@chelsio.com> *
+ * Tina Yang <tainay@chelsio.com> *
+ * Felix Marti <felix@chelsio.com> *
+ * Scott Bardone <sbardone@chelsio.com> *
+ * Kurt Ottaway <kottaway@chelsio.com> *
+ * Frank DiMambro <frank@chelsio.com> *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#include "common.h"
+#include "elmer0.h"
+#include "regs.h"
+#include "gmac.h"
+#include "cphy.h"
+#include "sge.h"
+#include "espi.h"
+
+/**
+ * t1_wait_op_done - wait until an operation is completed
+ * @adapter: the adapter performing the operation
+ * @reg: the register to check for completion
+ * @mask: a single-bit field within @reg that indicates completion
+ * @polarity: the value of the field when the operation is completed
+ * @attempts: number of check iterations
+ * @delay: delay in usecs between iterations
+ *
+ * Wait until an operation is completed by checking a bit in a register
+ * up to @attempts times. Returns %0 if the operation completes and %1
+ * otherwise.
+ */
+static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
+ int attempts, int delay)
+{
+ while (1) {
+ u32 val = readl(adapter->regs + reg) & mask;
+
+ if (!!val == polarity)
+ return 0;
+ if (--attempts == 0)
+ return 1;
+ if (delay)
+ udelay(delay);
+ }
+}
+
+#define TPI_ATTEMPTS 50
+
+/*
+ * Write a register over the TPI interface (unlocked and locked versions).
+ */
+static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
+{
+ int tpi_busy;
+
+ writel(addr, adapter->regs + A_TPI_ADDR);
+ writel(value, adapter->regs + A_TPI_WR_DATA);
+ writel(F_TPIWR, adapter->regs + A_TPI_CSR);
+
+ tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
+ TPI_ATTEMPTS, 3);
+ if (tpi_busy)
+ CH_ALERT("%s: TPI write to 0x%x failed\n",
+ adapter->name, addr);
+ return tpi_busy;
+}
+
+int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
+{
+ int ret;
+
+ spin_lock(&(adapter)->tpi_lock);
+ ret = __t1_tpi_write(adapter, addr, value);
+ spin_unlock(&(adapter)->tpi_lock);
+ return ret;
+}
+
+/*
+ * Read a register over the TPI interface (unlocked and locked versions).
+ */
+static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
+{
+ int tpi_busy;
+
+ writel(addr, adapter->regs + A_TPI_ADDR);
+ writel(0, adapter->regs + A_TPI_CSR);
+
+ tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
+ TPI_ATTEMPTS, 3);
+ if (tpi_busy)
+ CH_ALERT("%s: TPI read from 0x%x failed\n",
+ adapter->name, addr);
+ else
+ *valp = readl(adapter->regs + A_TPI_RD_DATA);
+ return tpi_busy;
+}
+
+int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
+{
+ int ret;
+
+ spin_lock(&(adapter)->tpi_lock);
+ ret = __t1_tpi_read(adapter, addr, valp);
+ spin_unlock(&(adapter)->tpi_lock);
+ return ret;
+}
+
+/*
+ * Called when a port's link settings change to propagate the new values to the
+ * associated PHY and MAC. After performing the common tasks it invokes an
+ * OS-specific handler.
+ */
+/* static */ void link_changed(adapter_t *adapter, int port_id)
+{
+ int link_ok, speed, duplex, fc;
+ struct cphy *phy = adapter->port[port_id].phy;
+ struct link_config *lc = &adapter->port[port_id].link_config;
+
+ phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
+
+ lc->speed = speed < 0 ? SPEED_INVALID : speed;
+ lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
+ if (!(lc->requested_fc & PAUSE_AUTONEG))
+ 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. */
+ struct cmac *mac = adapter->port[port_id].mac;
+
+ mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
+ lc->fc = (unsigned char)fc;
+ }
+ t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
+}
+
+static int t1_pci_intr_handler(adapter_t *adapter)
+{
+ u32 pcix_cause;
+
+ pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
+
+ if (pcix_cause) {
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
+ pcix_cause);
+ t1_fatal_err(adapter); /* PCI errors are fatal */
+ }
+ return 0;
+}
+
+
+/*
+ * Wait until Elmer's MI1 interface is ready for new operations.
+ */
+static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
+{
+ int attempts = 100, busy;
+
+ do {
+ u32 val;
+
+ __t1_tpi_read(adapter, mi1_reg, &val);
+ busy = val & F_MI1_OP_BUSY;
+ if (busy)
+ udelay(10);
+ } while (busy && --attempts);
+ if (busy)
+ CH_ALERT("%s: MDIO operation timed out\n",
+ adapter->name);
+ return busy;
+}
+
+/*
+ * MI1 MDIO initialization.
+ */
+static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
+{
+ u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
+ u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
+ V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
+
+ if (!(bi->caps & SUPPORTED_10000baseT_Full))
+ val |= V_MI1_SOF(1);
+ t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
+}
+
+static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int *valp)
+{
+ u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ spin_lock(&(adapter)->tpi_lock);
+
+ /* Write the address we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
+ MI1_OP_INDIRECT_ADDRESS);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Write the operation we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Read the data. */
+ __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+ spin_unlock(&(adapter)->tpi_lock);
+ return 0;
+}
+
+static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
+ int reg_addr, unsigned int val)
+{
+ u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+
+ spin_lock(&(adapter)->tpi_lock);
+
+ /* Write the address we want. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
+ MI1_OP_INDIRECT_ADDRESS);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+
+ /* Write the data. */
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
+ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
+ mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
+ spin_unlock(&(adapter)->tpi_lock);
+ return 0;
+}
+
+static struct mdio_ops mi1_mdio_ext_ops = {
+ mi1_mdio_init,
+ mi1_mdio_ext_read,
+ mi1_mdio_ext_write
+};
+
+enum {
+ CH_BRD_N110_1F,
+ CH_BRD_N210_1F,
+};
+
+static struct board_info t1_board[] = {
+
+{ CHBT_BOARD_N110, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
+ CHBT_MAC_PM3393, CHBT_PHY_88X2010,
+ 125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
+ "Chelsio N110 1x10GBaseX NIC" },
+
+{ CHBT_BOARD_N210, 1/*ports#*/,
+ SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T2,
+ CHBT_MAC_PM3393, CHBT_PHY_88X2010,
+ 125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
+ 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
+ 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
+ &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
+ "Chelsio N210 1x10GBaseX NIC" },
+
+};
+
+struct pci_device_id t1_pci_tbl[] = {
+ CH_DEVICE(7, 0, CH_BRD_N110_1F),
+ CH_DEVICE(10, 1, CH_BRD_N210_1F),
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
+
+/*
+ * Return the board_info structure with a given index. Out-of-range indices
+ * return NULL.
+ */
+const struct board_info *t1_get_board_info(unsigned int board_id)
+{
+ return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
+}
+
+struct chelsio_vpd_t {
+ u32 format_version;
+ u8 serial_number[16];
+ u8 mac_base_address[6];
+ u8 pad[2]; /* make multiple-of-4 size requirement explicit */
+};
+
+#define EEPROMSIZE (8 * 1024)
+#define EEPROM_MAX_POLL 4
+
+/*
+ * Read SEEPROM. A zero is written to the flag register when the addres is
+ * written to the Control register. The hardware device will set the flag to a
+ * one when 4B have been transferred to the Data register.
+ */
+int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
+{
+ int i = EEPROM_MAX_POLL;
+ u16 val;
+
+ if (addr >= EEPROMSIZE || (addr & 3))
+ return -EINVAL;
+
+ pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
+ do {
+ udelay(50);
+ pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
+ } while (!(val & F_VPD_OP_FLAG) && --i);
+
+ if (!(val & F_VPD_OP_FLAG)) {
+ CH_ERR("%s: reading EEPROM address 0x%x failed\n",
+ adapter->name, addr);
+ return -EIO;
+ }
+ pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, data);
+ *data = le32_to_cpu(*data);
+ return 0;
+}
+
+static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
+{
+ int addr, ret = 0;
+
+ for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
+ ret = t1_seeprom_read(adapter, addr,
+ (u32 *)((u8 *)vpd + addr));
+
+ return ret;
+}
+
+/*
+ * Read a port's MAC address from the VPD ROM.
+ */
+static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
+{
+ struct chelsio_vpd_t vpd;
+
+ if (t1_eeprom_vpd_get(adapter, &vpd))
+ return 1;
+ memcpy(mac_addr, vpd.mac_base_address, 5);
+ mac_addr[5] = vpd.mac_base_address[5] + index;
+ return 0;
+}
+
+/*
+ * Set up the MAC/PHY according to the requested link settings.
+ *
+ * If the PHY can auto-negotiate first decide what to advertise, then
+ * enable/disable auto-negotiation as desired and reset.
+ *
+ * If the PHY does not auto-negotiate we just reset it.
+ *
+ * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
+ * otherwise do it later based on the outcome of auto-negotiation.
+ */
+int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
+{
+ unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+
+ if (lc->supported & SUPPORTED_Autoneg) {
+ lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
+ if (fc) {
+ lc->advertising |= ADVERTISED_ASYM_PAUSE;
+ if (fc == (PAUSE_RX | PAUSE_TX))
+ lc->advertising |= ADVERTISED_PAUSE;
+ }
+ phy->ops->advertise(phy, lc->advertising);
+
+ if (lc->autoneg == AUTONEG_DISABLE) {
+ lc->speed = lc->requested_speed;
+ lc->duplex = lc->requested_duplex;
+ lc->fc = (unsigned char)fc;
+ mac->ops->set_speed_duplex_fc(mac, lc->speed,
+ lc->duplex, 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); /* also resets PHY */
+ } else {
+ mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
+ lc->fc = (unsigned char)fc;
+ phy->ops->reset(phy, 0);
+ }
+ return 0;
+}
+
+/*
+ * External interrupt handler for boards using elmer0.
+ */
+int elmer0_ext_intr_handler(adapter_t *adapter)
+{
+ struct cphy *phy;
+ int phy_cause;
+ u32 cause;
+
+ t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
+
+ switch (board_info(adapter)->board) {
+ case CHBT_BOARD_N210:
+ case CHBT_BOARD_N110:
+ if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
+ phy = adapter->port[0].phy;
+ phy_cause = phy->ops->interrupt_handler(phy);
+ if (phy_cause & cphy_cause_link_change)
+ link_changed(adapter, 0);
+ }
+ break;
+ }
+ t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
+ return 0;
+}
+
+/* Enables all interrupts. */
+void t1_interrupts_enable(adapter_t *adapter)
+{
+ unsigned int i;
+ u32 pl_intr;
+
+ adapter->slow_intr_mask = F_PL_INTR_SGE_ERR;
+
+ t1_sge_intr_enable(adapter->sge);
+ if (adapter->espi) {
+ adapter->slow_intr_mask |= F_PL_INTR_ESPI;
+ t1_espi_intr_enable(adapter->espi);
+ }
+
+ /* Enable MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
+ }
+
+ /* Enable PCIX & external chip interrupts on ASIC boards. */
+ pl_intr = readl(adapter->regs + A_PL_ENABLE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
+ 0xffffffff);
+
+ adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
+ writel(pl_intr, adapter->regs + A_PL_ENABLE);
+}
+
+/* Disables all interrupts. */
+void t1_interrupts_disable(adapter_t* adapter)
+{
+ unsigned int i;
+
+ t1_sge_intr_disable(adapter->sge);
+ if (adapter->espi)
+ t1_espi_intr_disable(adapter->espi);
+
+ /* Disable MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
+ }
+
+ /* Disable PCIX & external chip interrupts. */
+ writel(0, adapter->regs + A_PL_ENABLE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
+
+ adapter->slow_intr_mask = 0;
+}
+
+/* Clears all interrupts */
+void t1_interrupts_clear(adapter_t* adapter)
+{
+ unsigned int i;
+ u32 pl_intr;
+
+
+ t1_sge_intr_clear(adapter->sge);
+ if (adapter->espi)
+ t1_espi_intr_clear(adapter->espi);
+
+ /* Clear MAC/PHY interrupts for each port. */
+ for_each_port(adapter, i) {
+ adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
+ adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
+ }
+
+ /* Enable interrupts for external devices. */
+ pl_intr = readl(adapter->regs + A_PL_CAUSE);
+
+ writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
+ adapter->regs + A_PL_CAUSE);
+
+ /* PCI-X interrupts */
+ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
+}
+
+/*
+ * Slow path interrupt handler for ASICs.
+ */
+int t1_slow_intr_handler(adapter_t *adapter)
+{
+ u32 cause = readl(adapter->regs + A_PL_CAUSE);
+
+ cause &= adapter->slow_intr_mask;
+ if (!cause)
+ return 0;
+ if (cause & F_PL_INTR_SGE_ERR)
+ t1_sge_intr_error_handler(adapter->sge);
+ if (cause & F_PL_INTR_ESPI)
+ t1_espi_intr_handler(adapter->espi);
+ if (cause & F_PL_INTR_PCIX)
+ t1_pci_intr_handler(adapter);
+ if (cause & F_PL_INTR_EXT)
+ t1_elmer0_ext_intr(adapter);
+
+ /* Clear the interrupts just processed. */
+ writel(cause, adapter->regs + A_PL_CAUSE);
+ (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */
+ return 1;
+}
+
+/* Pause deadlock avoidance parameters */
+#define DROP_MSEC 16
+#define DROP_PKTS_CNT 1
+
+static void set_csum_offload(adapter_t *adapter, u32 csum_bit, int enable)
+{
+ u32 val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
+
+ if (enable)
+ val |= csum_bit;
+ else
+ val &= ~csum_bit;
+ writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
+}
+
+void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_IP_CSUM, enable);
+}
+
+void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_UDP_CSUM, enable);
+}
+
+void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable)
+{
+ set_csum_offload(adapter, F_TCP_CSUM, enable);
+}
+
+static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk)
+{
+ u32 val;
+
+ val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
+ F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
+ val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
+ F_TP_IN_ESPI_CHECK_TCP_CSUM;
+ writel(val, adapter->regs + A_TP_IN_CONFIG);
+ writel(F_TP_OUT_CSPI_CPL |
+ F_TP_OUT_ESPI_ETHERNET |
+ F_TP_OUT_ESPI_GENERATE_IP_CSUM |
+ F_TP_OUT_ESPI_GENERATE_TCP_CSUM,
+ adapter->regs + A_TP_OUT_CONFIG);
+
+ val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
+ val &= ~(F_IP_CSUM | F_UDP_CSUM | F_TCP_CSUM);
+ writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
+
+ /*
+ * Enable pause frame deadlock prevention.
+ */
+ if (is_T2(adapter)) {
+ u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
+
+ writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
+ V_DROP_TICKS_CNT(drop_ticks) |
+ V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
+ adapter->regs + A_TP_TX_DROP_CONFIG);
+ }
+
+ writel(F_TP_RESET, adapter->regs + A_TP_RESET);
+}
+
+int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ struct adapter_params *p)
+{
+ p->chip_version = bi->chip_term;
+ if (p->chip_version == CHBT_TERM_T1 ||
+ p->chip_version == CHBT_TERM_T2) {
+ u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
+
+ val = G_TP_PC_REV(val);
+ if (val == 2)
+ p->chip_revision = TERM_T1B;
+ else if (val == 3)
+ p->chip_revision = TERM_T2;
+ else
+ return -1;
+ } else
+ return -1;
+ return 0;
+}
+
+/*
+ * Enable board components other than the Chelsio chip, such as external MAC
+ * and PHY.
+ */
+static int board_init(adapter_t *adapter, const struct board_info *bi)
+{
+ switch (bi->board) {
+ case CHBT_BOARD_N110:
+ case CHBT_BOARD_N210:
+ writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR);
+ t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Initialize and configure the Terminator HW modules. Note that external
+ * MAC and PHYs are initialized separately.
+ */
+int t1_init_hw_modules(adapter_t *adapter)
+{
+ int err = -EIO;
+ const struct board_info *bi = board_info(adapter);
+
+ if (!bi->clock_mc4) {
+ u32 val = readl(adapter->regs + A_MC4_CFG);
+
+ writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
+ writel(F_M_BUS_ENABLE | F_TCAM_RESET,
+ adapter->regs + A_MC5_CONFIG);
+ }
+
+ if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
+ bi->espi_nports))
+ goto out_err;
+
+ t1_tp_reset(adapter, bi->clock_core);
+
+ err = t1_sge_configure(adapter->sge, &adapter->params.sge);
+ if (err)
+ goto out_err;
+
+ err = 0;
+ out_err:
+ return err;
+}
+
+/*
+ * Determine a card's PCI mode.
+ */
+static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
+{
+ static unsigned short speed_map[] = { 33, 66, 100, 133 };
+ u32 pci_mode;
+
+ pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
+ p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
+ p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
+ p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
+}
+
+/*
+ * Release the structures holding the SW per-Terminator-HW-module state.
+ */
+void t1_free_sw_modules(adapter_t *adapter)
+{
+ unsigned int i;
+
+ for_each_port(adapter, i) {
+ struct cmac *mac = adapter->port[i].mac;
+ struct cphy *phy = adapter->port[i].phy;
+
+ if (mac)
+ mac->ops->destroy(mac);
+ if (phy)
+ phy->ops->destroy(phy);
+ }
+
+ if (adapter->sge)
+ t1_sge_destroy(adapter->sge);
+ if (adapter->espi)
+ t1_espi_destroy(adapter->espi);
+}
+
+static void __devinit init_link_config(struct link_config *lc,
+ const struct board_info *bi)
+{
+ lc->supported = bi->caps;
+ lc->requested_speed = lc->speed = SPEED_INVALID;
+ lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
+ lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
+ if (lc->supported & SUPPORTED_Autoneg) {
+ lc->advertising = lc->supported;
+ lc->autoneg = AUTONEG_ENABLE;
+ lc->requested_fc |= PAUSE_AUTONEG;
+ } else {
+ lc->advertising = 0;
+ lc->autoneg = AUTONEG_DISABLE;
+ }
+}
+
+
+/*
+ * Allocate and initialize the data structures that hold the SW state of
+ * the Terminator HW modules.
+ */
+int __devinit t1_init_sw_modules(adapter_t *adapter,
+ const struct board_info *bi)
+{
+ unsigned int i;
+
+ adapter->params.brd_info = bi;
+ adapter->params.nports = bi->port_number;
+ adapter->params.stats_update_period = bi->gmac->stats_update_period;
+
+ adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
+ if (!adapter->sge) {
+ CH_ERR("%s: SGE initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+
+ if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
+ CH_ERR("%s: ESPI initialization failed\n",
+ adapter->name);
+ goto error;
+ }
+
+ board_init(adapter, bi);
+ bi->mdio_ops->init(adapter, bi);
+ if (bi->gphy->reset)
+ bi->gphy->reset(adapter);
+ if (bi->gmac->reset)
+ bi->gmac->reset(adapter);
+
+ for_each_port(adapter, i) {
+ u8 hw_addr[6];
+ struct cmac *mac;
+ int phy_addr = bi->mdio_phybaseaddr + i;
+
+ adapter->port[i].phy = bi->gphy->create(adapter, phy_addr,
+ bi->mdio_ops);
+ if (!adapter->port[i].phy) {
+ CH_ERR("%s: PHY %d initialization failed\n",
+ adapter->name, i);
+ goto error;
+ }
+
+ adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
+ if (!mac) {
+ CH_ERR("%s: MAC %d initialization failed\n",
+ adapter->name, i);
+ goto error;
+ }
+
+ /*
+ * Get the port's MAC addresses either from the EEPROM if one
+ * exists or the one hardcoded in the MAC.
+ */
+ if (vpd_macaddress_get(adapter, i, hw_addr)) {
+ CH_ERR("%s: could not read MAC address from VPD ROM\n",
+ adapter->port[i].dev->name);
+ goto error;
+ }
+ memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
+ init_link_config(&adapter->port[i].link_config, bi);
+ }
+
+ get_pci_mode(adapter, &adapter->params.pci);
+ t1_interrupts_clear(adapter);
+ return 0;
+
+ error:
+ t1_free_sw_modules(adapter);
+ return -1;
+}
diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/chelsio/suni1x10gexp_regs.h
new file mode 100644
index 000000000000..81816c2b708a
--- /dev/null
+++ b/drivers/net/chelsio/suni1x10gexp_regs.h
@@ -0,0 +1,213 @@
+/*****************************************************************************
+ * *
+ * File: suni1x10gexp_regs.h *
+ * $Revision: 1.9 $ *
+ * $Date: 2005/06/22 00:17:04 $ *
+ * Description: *
+ * PMC/SIERRA (pm3393) MAC-PHY functionality. *
+ * part of the Chelsio 10Gb Ethernet Driver. *
+ * *
+ * 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. *
+ * *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * http://www.chelsio.com *
+ * *
+ * Maintainers: maintainers@chelsio.com *
+ * *
+ * Authors: PMC/SIERRA *
+ * *
+ * History: *
+ * *
+ ****************************************************************************/
+
+#ifndef _CXGB_SUNI1x10GEXP_REGS_H_
+#define _CXGB_SUNI1x10GEXP_REGS_H_
+
+/******************************************************************************/
+/** S/UNI-1x10GE-XP REGISTER ADDRESS MAP **/
+/******************************************************************************/
+/* Refer to the Register Bit Masks bellow for the naming of each register and */
+/* to the S/UNI-1x10GE-XP Data Sheet for the signification of each bit */
+/******************************************************************************/
+
+#define SUNI1x10GEXP_REG_DEVICE_STATUS 0x0004
+#define SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS 0x000D
+#define SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE 0x000E
+#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE 0x0102
+#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS 0x0104
+#define SUNI1x10GEXP_REG_RXXG_CONFIG_1 0x2040
+#define SUNI1x10GEXP_REG_RXXG_CONFIG_3 0x2042
+#define SUNI1x10GEXP_REG_RXXG_INTERRUPT 0x2043
+#define SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH 0x2045
+#define SUNI1x10GEXP_REG_RXXG_SA_15_0 0x2046
+#define SUNI1x10GEXP_REG_RXXG_SA_31_16 0x2047
+#define SUNI1x10GEXP_REG_RXXG_SA_47_32 0x2048
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW 0x204D
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID 0x204E
+#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH 0x204F
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW 0x206A
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW 0x206B
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH 0x206C
+#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH 0x206D
+#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0 0x206E
+#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2 0x2070
+#define SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE 0x2088
+#define SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS 0x2089
+#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE 0x208B
+#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS 0x208C
+#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE 0x20C7
+#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS 0x20C8
+#define SUNI1x10GEXP_REG_MSTAT_CONTROL 0x2100
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0 0x2101
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1 0x2102
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2 0x2103
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3 0x2104
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0 0x2105
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1 0x2106
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2 0x2107
+#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3 0x2108
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW 0x2110
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW 0x2114
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW 0x2120
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW 0x2124
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW 0x2128
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW 0x2130
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW 0x2138
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW 0x213C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW 0x2140
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW 0x2144
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW 0x214C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW 0x2150
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW 0x2154
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW 0x2158
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW 0x2194
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW 0x219C
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW 0x21A0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW 0x21A8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW 0x21B0
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW 0x21B8
+#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW 0x21BC
+#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE 0x2209
+#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT 0x220A
+#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK 0x2282
+#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT 0x2283
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS 0x2300
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE 0x2301
+#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK 0x2302
+#define SUNI1x10GEXP_REG_TXXG_CONFIG_1 0x3040
+#define SUNI1x10GEXP_REG_TXXG_CONFIG_3 0x3042
+#define SUNI1x10GEXP_REG_TXXG_INTERRUPT 0x3043
+#define SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE 0x3045
+#define SUNI1x10GEXP_REG_TXXG_SA_15_0 0x3047
+#define SUNI1x10GEXP_REG_TXXG_SA_31_16 0x3048
+#define SUNI1x10GEXP_REG_TXXG_SA_47_32 0x3049
+#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS 0x3084
+#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE 0x3085
+#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE 0x30C6
+#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS 0x30C7
+#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE 0x320C
+#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION 0x320D
+#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK 0x3282
+#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT 0x3283
+
+/******************************************************************************/
+/* -- End register offset definitions -- */
+/******************************************************************************/
+
+/******************************************************************************/
+/** SUNI-1x10GE-XP REGISTER BIT MASKS **/
+/******************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * Register 0x0004: S/UNI-1x10GE-XP Device Status
+ * Bit 9 TOP_SXRA_EXPIRED
+ * Bit 8 TOP_MDIO_BUSY
+ * Bit 7 TOP_DTRB
+ * Bit 6 TOP_EXPIRED
+ * Bit 5 TOP_PAUSED
+ * Bit 4 TOP_PL4_ID_DOOL
+ * Bit 3 TOP_PL4_IS_DOOL
+ * Bit 2 TOP_PL4_ID_ROOL
+ * Bit 1 TOP_PL4_IS_ROOL
+ * Bit 0 TOP_PL4_OUT_ROOL
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED 0x0200
+#define SUNI1x10GEXP_BITMSK_TOP_EXPIRED 0x0040
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL 0x0010
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL 0x0008
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL 0x0004
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL 0x0002
+#define SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x000E:PM3393 Global interrupt enable
+ * Bit 15 TOP_INTE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TOP_INTE 0x8000
+
+/*----------------------------------------------------------------------------
+ * Register 0x2040: RXXG Configuration 1
+ * Bit 15 RXXG_RXEN
+ * Bit 14 RXXG_ROCF
+ * Bit 13 RXXG_PAD_STRIP
+ * Bit 10 RXXG_PUREP
+ * Bit 9 RXXG_LONGP
+ * Bit 8 RXXG_PARF
+ * Bit 7 RXXG_FLCHK
+ * Bit 5 RXXG_PASS_CTRL
+ * Bit 3 RXXG_CRC_STRIP
+ * Bit 2-0 RXXG_MIFG
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_RXEN 0x8000
+#define SUNI1x10GEXP_BITMSK_RXXG_PUREP 0x0400
+#define SUNI1x10GEXP_BITMSK_RXXG_FLCHK 0x0080
+#define SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP 0x0008
+
+/*----------------------------------------------------------------------------
+ * Register 0x2070: RXXG Address Filter Control 2
+ * Bit 1 RXXG_PMODE
+ * Bit 0 RXXG_MHASH_EN
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_RXXG_PMODE 0x0002
+#define SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x2100: MSTAT Control
+ * Bit 2 MSTAT_WRITE
+ * Bit 1 MSTAT_CLEAR
+ * Bit 0 MSTAT_SNAP
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_MSTAT_CLEAR 0x0002
+#define SUNI1x10GEXP_BITMSK_MSTAT_SNAP 0x0001
+
+/*----------------------------------------------------------------------------
+ * Register 0x3040: TXXG Configuration Register 1
+ * Bit 15 TXXG_TXEN0
+ * Bit 13 TXXG_HOSTPAUSE
+ * Bit 12-7 TXXG_IPGT
+ * Bit 5 TXXG_32BIT_ALIGN
+ * Bit 4 TXXG_CRCEN
+ * Bit 3 TXXG_FCTX
+ * Bit 2 TXXG_FCRX
+ * Bit 1 TXXG_PADEN
+ * Bit 0 TXXG_SPRE
+ *----------------------------------------------------------------------------*/
+#define SUNI1x10GEXP_BITMSK_TXXG_TXEN0 0x8000
+#define SUNI1x10GEXP_BITOFF_TXXG_IPGT 7
+#define SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN 0x0020
+#define SUNI1x10GEXP_BITMSK_TXXG_CRCEN 0x0010
+#define SUNI1x10GEXP_BITMSK_TXXG_FCTX 0x0008
+#define SUNI1x10GEXP_BITMSK_TXXG_FCRX 0x0004
+#define SUNI1x10GEXP_BITMSK_TXXG_PADEN 0x0002
+
+#endif /* _CXGB_SUNI1x10GEXP_REGS_H_ */
+
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 442670860fca..b68b9cad76e9 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -384,8 +384,8 @@ static unsigned int mdio_phy_addr; /* Transciever address */
static unsigned int network_tr_ctrl_shadow = 0;
/* Network speed indication. */
-static struct timer_list speed_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list clear_led_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(speed_timer, NULL, 0, 0);
+static DEFINE_TIMER(clear_led_timer, NULL, 0, 0);
static int current_speed; /* Speed read from transceiver */
static int current_speed_selection; /* Speed selected by user */
static unsigned long led_next_time;
@@ -393,7 +393,7 @@ static int led_active;
static int rx_queue_len;
/* Duplex */
-static struct timer_list duplex_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(duplex_timer, NULL, 0, 0);
static int full_duplex;
static enum duplex current_duplex;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index b780307093eb..a6078ad9b654 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -140,6 +140,7 @@
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/irq.h>
#if ALLOW_DMA
#include <asm/dma.h>
#endif
@@ -247,6 +248,9 @@ static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer
static int get_eeprom_cksum(int off, int len, int *buffer);
static int set_mac_address(struct net_device *dev, void *addr);
static void count_rx_errors(int status, struct net_local *lp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void net_poll_controller(struct net_device *dev);
+#endif
#if ALLOW_DMA
static void get_dma_channel(struct net_device *dev);
static void release_dma_buff(struct net_local *lp);
@@ -405,6 +409,19 @@ get_eeprom_cksum(int off, int len, int *buffer)
return -1;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ net_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions.
@@ -760,6 +777,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
dev->get_stats = net_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = set_mac_address;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = net_poll_controller;
+#endif
printk("\n");
if (net_debug)
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 521c83137bf6..f130bdab3fd3 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -5,7 +5,7 @@
*
* adopted from sunlance.c by Richard van den Berg
*
- * Copyright (C) 2002, 2003 Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
*
* additional sources:
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
@@ -57,13 +57,15 @@
#include <linux/string.h>
#include <asm/addrspace.h>
+#include <asm/system.h>
+
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/machtype.h>
+#include <asm/dec/system.h>
#include <asm/dec/tc.h>
-#include <asm/system.h>
static char version[] __devinitdata =
"declance.c: v0.009 by Linux MIPS DECstation task force\n";
@@ -79,10 +81,6 @@ MODULE_LICENSE("GPL");
#define PMAD_LANCE 2
#define PMAX_LANCE 3
-#ifndef CONFIG_TC
-unsigned long system_base;
-unsigned long dmaptr;
-#endif
#define LE_CSR0 0
#define LE_CSR1 1
@@ -237,7 +235,7 @@ struct lance_init_block {
/*
* This works *only* for the ring descriptors
*/
-#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
+#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
struct lance_private {
struct net_device *next;
@@ -697,12 +695,13 @@ out:
spin_unlock(&lp->lock);
}
-static void lance_dma_merr_int(const int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
+ struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
printk("%s: DMA error\n", dev->name);
+ return IRQ_HANDLED;
}
static irqreturn_t
@@ -1026,10 +1025,6 @@ static int __init dec_lance_init(const int type, const int slot)
unsigned long esar_base;
unsigned char *esar;
-#ifndef CONFIG_TC
- system_base = KN01_LANCE_BASE;
-#endif
-
if (dec_lance_debug && version_printed++ == 0)
printk(version);
@@ -1062,16 +1057,16 @@ static int __init dec_lance_init(const int type, const int slot)
switch (type) {
#ifdef CONFIG_TC
case ASIC_LANCE:
- dev->base_addr = system_base + IOASIC_LANCE;
+ dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
/* buffer space for the on-board LANCE shared memory */
/*
* FIXME: ugly hack!
*/
- dev->mem_start = KSEG1ADDR(0x00020000);
+ dev->mem_start = CKSEG1ADDR(0x00020000);
dev->mem_end = dev->mem_start + 0x00020000;
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- esar_base = system_base + IOASIC_ESAR;
+ esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
/* Workaround crash with booting KN04 2.1k from Disk */
memset((void *)dev->mem_start, 0,
@@ -1101,14 +1096,14 @@ static int __init dec_lance_init(const int type, const int slot)
/* Setup I/O ASIC LANCE DMA. */
lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
ioasic_write(IO_REG_LANCE_DMA_P,
- PHYSADDR(dev->mem_start) << 3);
+ CPHYSADDR(dev->mem_start) << 3);
break;
case PMAD_LANCE:
claim_tc_card(slot);
- dev->mem_start = get_tc_base_addr(slot);
+ dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
dev->base_addr = dev->mem_start + 0x100000;
dev->irq = get_tc_irq_nr(slot);
esar_base = dev->mem_start + 0x1c0002;
@@ -1137,9 +1132,9 @@ static int __init dec_lance_init(const int type, const int slot)
case PMAX_LANCE:
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
- dev->base_addr = KN01_LANCE_BASE;
- dev->mem_start = KN01_LANCE_BASE + 0x01000000;
- esar_base = KN01_RTC_BASE + 1;
+ dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
+ dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+ esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
lp->dma_irq = -1;
/*
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index c4aa5fe2840e..4d26e5e7d18b 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -254,7 +254,7 @@
#include <linux/unistd.h>
#include <linux/ctype.h>
#include <linux/moduleparam.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 5fddc0ff8878..c0af6fb1fbba 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -48,6 +48,10 @@
* net_device_stats
* * introduced tx_timeout function
* * reworked locking
+ *
+ * 01-Jul-2005 Ben Dooks <ben@simtec.co.uk>
+ * * fixed spinlock call without pointer
+ * * ensure spinlock is initialised
*/
#include <linux/module.h>
@@ -62,6 +66,7 @@
#include <linux/mii.h>
#include <linux/dm9000.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
#include <asm/delay.h>
#include <asm/irq.h>
@@ -148,7 +153,6 @@ static int dm9000_probe(struct device *);
static int dm9000_open(struct net_device *);
static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
static int dm9000_stop(struct net_device *);
-static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int);
static void dm9000_timer(unsigned long);
@@ -322,7 +326,7 @@ static void dm9000_timeout(struct net_device *dev)
/* Save previous register address */
reg_save = readb(db->io_addr);
- spin_lock_irqsave(db->lock,flags);
+ spin_lock_irqsave(&db->lock,flags);
netif_stop_queue(dev);
dm9000_reset(db);
@@ -333,7 +337,7 @@ static void dm9000_timeout(struct net_device *dev)
/* Restore previous register address */
writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(db->lock,flags);
+ spin_unlock_irqrestore(&db->lock,flags);
}
@@ -387,8 +391,6 @@ dm9000_probe(struct device *dev)
int i;
u32 id_val;
- printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
-
/* Init network device */
ndev = alloc_etherdev(sizeof (struct board_info));
if (!ndev) {
@@ -405,6 +407,8 @@ dm9000_probe(struct device *dev)
db = (struct board_info *) ndev->priv;
memset(db, 0, sizeof (*db));
+ spin_lock_init(&db->lock);
+
if (pdev->num_resources < 2) {
ret = -ENODEV;
goto out;
@@ -541,7 +545,6 @@ dm9000_probe(struct device *dev)
ndev->stop = &dm9000_stop;
ndev->get_stats = &dm9000_get_stats;
ndev->set_multicast_list = &dm9000_hash_table;
- ndev->do_ioctl = &dm9000_do_ioctl;
#ifdef DM9000_PROGRAM_EEPROM
program_eeprom(db);
@@ -612,7 +615,7 @@ dm9000_open(struct net_device *dev)
/* set and active a timer process */
init_timer(&db->timer);
- db->timer.expires = DM9000_TIMER_WUT * 2;
+ db->timer.expires = DM9000_TIMER_WUT;
db->timer.data = (unsigned long) dev;
db->timer.function = &dm9000_timer;
add_timer(&db->timer);
@@ -845,15 +848,6 @@ dm9000_get_stats(struct net_device *dev)
return &db->stats;
}
-/*
- * Process the upper socket ioctl command
- */
-static int
-dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- PRINTK1("entering %s\n",__FUNCTION__);
- return 0;
-}
/*
* A periodic timer routine
@@ -864,21 +858,11 @@ dm9000_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
board_info_t *db = (board_info_t *) dev->priv;
- u8 reg_save;
- unsigned long flags;
PRINTK3("dm9000_timer()\n");
- spin_lock_irqsave(db->lock,flags);
- /* Save previous register address */
- reg_save = readb(db->io_addr);
-
mii_check_media(&db->mii, netif_msg_link(db), 0);
- /* Restore previous register address */
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(db->lock,flags);
-
/* Set timer again */
db->timer.expires = DM9000_TIMER_WUT;
add_timer(&db->timer);
@@ -1098,9 +1082,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
board_info_t *db = (board_info_t *) dev->priv;
unsigned long flags;
+ unsigned int reg_save;
int ret;
spin_lock_irqsave(&db->lock,flags);
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1111,6 +1100,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
/* The read data keeps on REG_0D & REG_0E */
ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+ /* restore the previous address */
+ writeb(reg_save, db->io_addr);
+
spin_unlock_irqrestore(&db->lock,flags);
return ret;
@@ -1124,9 +1116,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
{
board_info_t *db = (board_info_t *) dev->priv;
unsigned long flags;
+ unsigned long reg_save;
spin_lock_irqsave(&db->lock,flags);
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1138,15 +1134,18 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
udelay(500); /* Wait write complete */
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
+ /* restore the previous address */
+ writeb(reg_save, db->io_addr);
+
spin_unlock_irqrestore(&db->lock,flags);
}
static int
-dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
+dm9000_drv_suspend(struct device *dev, pm_message_t state)
{
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == SUSPEND_DISABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
netif_device_detach(ndev);
dm9000_shutdown(ndev);
@@ -1156,12 +1155,12 @@ dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
}
static int
-dm9000_drv_resume(struct device *dev, u32 level)
+dm9000_drv_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
board_info_t *db = (board_info_t *) ndev->priv;
- if (ndev && level == RESUME_ENABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
dm9000_reset(db);
@@ -1202,6 +1201,8 @@ static struct device_driver dm9000_driver = {
static int __init
dm9000_init(void)
{
+ printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+
return driver_register(&dm9000_driver); /* search board and register */
}
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index d0fa2448761d..eb169a8e8773 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ 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
@@ -156,7 +156,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.4.8-k2"DRV_EXT
+#define DRV_VERSION "3.4.14-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -785,6 +785,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
}
#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
+#define E100_WAIT_SCB_FAST 20 /* delay like the old code */
static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
@@ -798,7 +799,7 @@ static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
if(likely(!readb(&nic->csr->scb.cmd_lo)))
break;
cpu_relax();
- if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1)))
+ if(unlikely(i > E100_WAIT_SCB_FAST))
udelay(5);
}
if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
@@ -1198,13 +1199,13 @@ static void e100_update_stats(struct nic *nic)
ns->collisions += nic->tx_collisions;
ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
le32_to_cpu(s->tx_lost_crs);
- ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
nic->rx_over_length_errors;
ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+ ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
le32_to_cpu(s->rx_alignment_errors) +
le32_to_cpu(s->rx_short_frame_errors) +
@@ -1307,14 +1308,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
{
cb->command = nic->tx_command;
/* interrupt every 16 packets regardless of delay */
- if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i;
+ if((nic->cbs_avail & ~15) == nic->cbs_avail)
+ cb->command |= cpu_to_le16(cb_i);
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
- // check for mapping failure?
+ /* check for mapping failure? */
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}
@@ -1537,12 +1539,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
if(unlikely(!(rfd_status & cb_ok))) {
/* Don't indicate if hardware indicates errors */
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
- } else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
+ } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else {
nic->net_stats.rx_packets++;
@@ -1706,6 +1706,7 @@ static int e100_poll(struct net_device *netdev, int *budget)
static void e100_netpoll(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
+
e100_disable_irq(nic);
e100_intr(nic->pdev->irq, netdev, NULL);
e100_tx_clean(nic);
@@ -2108,6 +2109,8 @@ static void e100_diag_test(struct net_device *netdev,
}
for(i = 0; i < E100_TEST_LEN; i++)
test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
+
+ msleep_interruptible(4 * 1000);
}
static int e100_phys_id(struct net_device *netdev, u32 data)
@@ -2198,6 +2201,7 @@ static struct ethtool_ops e100_ethtool_ops = {
.phys_id = e100_phys_id,
.get_stats_count = e100_get_stats_count,
.get_ethtool_stats = e100_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -2348,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
e100_phy_init(nic);
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC address from "
"EEPROM, aborting.\n");
err = -EAGAIN;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 092757bc721f..3f653a93e1bc 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,6 +72,10 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
#define BAR_0 0
#define BAR_1 1
@@ -165,10 +169,33 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
-struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
-struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
+
+struct e1000_tx_ring {
+ /* pointer to the descriptor ring memory */
+ void *desc;
+ /* physical address of the descriptor ring */
+ dma_addr_t dma;
+ /* length of descriptor ring in bytes */
+ unsigned int size;
+ /* number of descriptors in the ring */
+ unsigned int count;
+ /* next descriptor to associate a buffer with */
+ unsigned int next_to_use;
+ /* next descriptor to check for DD status bit */
+ unsigned int next_to_clean;
+ /* array of buffer information structs */
+ struct e1000_buffer *buffer_info;
+
+ struct e1000_buffer previous_buffer_info;
+ spinlock_t tx_lock;
+ uint16_t tdh;
+ uint16_t tdt;
+ uint64_t pkt;
+};
-struct e1000_desc_ring {
+struct e1000_rx_ring {
/* pointer to the descriptor ring memory */
void *desc;
/* physical address of the descriptor ring */
@@ -186,6 +213,10 @@ struct e1000_desc_ring {
/* arrays of page information for packet split */
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
+
+ uint16_t rdh;
+ uint16_t rdt;
+ uint64_t pkt;
};
#define E1000_DESC_UNUSED(R) \
@@ -227,9 +258,10 @@ struct e1000_adapter {
unsigned long led_status;
/* TX */
- struct e1000_desc_ring tx_ring;
- struct e1000_buffer previous_buffer_info;
- spinlock_t tx_lock;
+ struct e1000_tx_ring *tx_ring; /* One per active queue */
+#ifdef CONFIG_E1000_MQ
+ struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
+#endif
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -246,19 +278,33 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
- boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
- int work_to_do);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
#else
- boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
#endif
- void (*alloc_rx_buf) (struct e1000_adapter *adapter);
- struct e1000_desc_ring rx_ring;
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring; /* One per active queue */
+#ifdef CONFIG_E1000_NAPI
+ struct net_device *polling_netdev; /* One per active queue */
+#endif
+#ifdef CONFIG_E1000_MQ
+ struct net_device **cpu_netdev; /* per-cpu */
+ struct call_async_data_struct rx_sched_call_data;
+ int cpu_for_queue[4];
+#endif
+ int num_queues;
+
uint64_t hw_csum_err;
uint64_t hw_csum_good;
+ uint64_t rx_hdr_split;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
- boolean_t rx_ps;
+ unsigned int rx_ps_pages;
uint32_t gorcl;
uint64_t gorcl_old;
uint16_t rx_ps_bsize0;
@@ -278,8 +324,8 @@ struct e1000_adapter {
struct e1000_phy_stats phy_stats;
uint32_t test_icr;
- struct e1000_desc_ring test_tx_ring;
- struct e1000_desc_ring test_rx_ring;
+ struct e1000_tx_ring test_tx_ring;
+ struct e1000_rx_ring test_rx_ring;
int msg_enable;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index f133ff0b0b94..9c7feaeaa6a4 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reset(struct e1000_adapter *adapter);
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
extern void e1000_update_stats(struct e1000_adapter *adapter);
struct e1000_stats {
@@ -91,7 +91,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
- { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+ { "rx_header_split", E1000_STAT(rx_hdr_split) },
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -546,8 +547,10 @@ e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_write_eeprom(hw, first_word,
last_word - first_word + 1, eeprom_buff);
- /* Update the checksum over the first part of the EEPROM if needed */
- if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
+ /* Update the checksum over the first part of the EEPROM if needed
+ * and flush shadow RAM for 82573 conrollers */
+ if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
+ (hw->mac_type == e1000_82573)))
e1000_update_eeprom_checksum(hw);
kfree(eeprom_buff);
@@ -576,8 +579,8 @@ e1000_get_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
+ struct e1000_rx_ring *rxdr = adapter->rx_ring;
ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -597,20 +600,40 @@ e1000_set_ringparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
e1000_mac_type mac_type = adapter->hw.mac_type;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
- struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
- int err;
+ struct e1000_tx_ring *txdr, *tx_old, *tx_new;
+ struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
+ int i, err, tx_ring_size, rx_ring_size;
+
+ tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+
+ if (netif_running(adapter->netdev))
+ e1000_down(adapter);
tx_old = adapter->tx_ring;
rx_old = adapter->rx_ring;
+ adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
+ if (!adapter->tx_ring) {
+ err = -ENOMEM;
+ goto err_setup_rx;
+ }
+ memset(adapter->tx_ring, 0, tx_ring_size);
+
+ adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ err = -ENOMEM;
+ goto err_setup_rx;
+ }
+ memset(adapter->rx_ring, 0, rx_ring_size);
+
+ txdr = adapter->tx_ring;
+ rxdr = adapter->rx_ring;
+
if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
- if(netif_running(adapter->netdev))
- e1000_down(adapter);
-
rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -621,11 +644,16 @@ e1000_set_ringparam(struct net_device *netdev,
E1000_MAX_TXD : E1000_MAX_82544_TXD));
E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ for (i = 0; i < adapter->num_queues; i++) {
+ txdr[i].count = txdr->count;
+ rxdr[i].count = rxdr->count;
+ }
+
if(netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
- if((err = e1000_setup_rx_resources(adapter)))
+ if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- if((err = e1000_setup_tx_resources(adapter)))
+ if ((err = e1000_setup_all_tx_resources(adapter)))
goto err_setup_tx;
/* save the new, restore the old in order to free it,
@@ -635,8 +663,10 @@ e1000_set_ringparam(struct net_device *netdev,
tx_new = adapter->tx_ring;
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
- e1000_free_rx_resources(adapter);
- e1000_free_tx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
+ kfree(tx_old);
+ kfree(rx_old);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
if((err = e1000_up(adapter)))
@@ -645,7 +675,7 @@ e1000_set_ringparam(struct net_device *netdev,
return 0;
err_setup_tx:
- e1000_free_rx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
err_setup_rx:
adapter->rx_ring = rx_old;
adapter->tx_ring = tx_old;
@@ -696,6 +726,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
* Some bits that get toggled are ignored.
*/
switch (adapter->hw.mac_type) {
+ /* there are several bits on newer hardware that are r/w */
+ case e1000_82571:
+ case e1000_82572:
+ toggle = 0x7FFFF3FF;
+ break;
case e1000_82573:
toggle = 0x7FFFF033;
break;
@@ -898,8 +933,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
static void
e1000_free_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i;
@@ -930,19 +965,16 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
if(rxdr->desc)
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
- if(txdr->buffer_info)
- kfree(txdr->buffer_info);
- if(rxdr->buffer_info)
- kfree(rxdr->buffer_info);
-
+ kfree(txdr->buffer_info);
+ kfree(rxdr->buffer_info);
return;
}
static int
e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
uint32_t rctl;
int size, i, ret_val;
@@ -1245,6 +1277,8 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
return e1000_integrated_phy_loopback(adapter);
break;
@@ -1340,8 +1374,8 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_run_loopback_test(struct e1000_adapter *adapter)
{
- struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
- struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i, j, k, l, lc, good_cnt, ret_val=0;
unsigned long time;
@@ -1509,6 +1543,7 @@ e1000_diag_test(struct net_device *netdev,
data[2] = 0;
data[3] = 0;
}
+ msleep_interruptible(4 * 1000);
}
static void
@@ -1625,7 +1660,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82573) {
+ if(adapter->hw.mac_type < e1000_82571) {
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1739,6 +1774,7 @@ struct ethtool_ops e1000_ethtool_ops = {
.phys_id = e1000_phys_id,
.get_stats_count = e1000_get_stats_count,
.get_ethtool_stats = e1000_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 045f5426ab9a..8fc876da43b4 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
static const
uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
- { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
- 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
- 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
- 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
- 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
- 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
- 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
- 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+ 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
+ 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
+ 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
+ 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
+ 104, 109, 114, 118, 121, 124};
/******************************************************************************
@@ -286,7 +286,6 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
- case E1000_DEV_ID_82546GB_QUAD_COPPER:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -305,8 +304,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_82571EB_COPPER:
+ case E1000_DEV_ID_82571EB_FIBER:
+ case E1000_DEV_ID_82571EB_SERDES:
+ hw->mac_type = e1000_82571;
+ break;
+ case E1000_DEV_ID_82572EI_COPPER:
+ case E1000_DEV_ID_82572EI_FIBER:
+ case E1000_DEV_ID_82572EI_SERDES:
+ hw->mac_type = e1000_82572;
+ break;
case E1000_DEV_ID_82573E:
case E1000_DEV_ID_82573E_IAMT:
+ case E1000_DEV_ID_82573L:
hw->mac_type = e1000_82573;
break;
default:
@@ -315,6 +325,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
}
switch(hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
hw->eeprom_semaphore_present = TRUE;
/* fall through */
@@ -351,6 +363,8 @@ e1000_set_media_type(struct e1000_hw *hw)
switch (hw->device_id) {
case E1000_DEV_ID_82545GM_SERDES:
case E1000_DEV_ID_82546GB_SERDES:
+ case E1000_DEV_ID_82571EB_SERDES:
+ case E1000_DEV_ID_82572EI_SERDES:
hw->media_type = e1000_media_type_internal_serdes;
break;
default:
@@ -523,6 +537,8 @@ e1000_reset_hw(struct e1000_hw *hw)
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
E1000_WRITE_FLUSH(hw);
/* fall through */
+ case e1000_82571:
+ case e1000_82572:
ret_val = e1000_get_auto_rd_done(hw);
if(ret_val)
/* We don't want to continue accessing MAC registers. */
@@ -683,6 +699,9 @@ e1000_init_hw(struct e1000_hw *hw)
switch (hw->mac_type) {
default:
break;
+ case e1000_82571:
+ case e1000_82572:
+ ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -694,6 +713,26 @@ e1000_init_hw(struct e1000_hw *hw)
e1000_enable_tx_pkt_filtering(hw);
}
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82571:
+ case e1000_82572:
+ ctrl = E1000_READ_REG(hw, TXDCTL1);
+ ctrl &= ~E1000_TXDCTL_WTHRESH;
+ ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
+ ctrl |= (1 << 22);
+ E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+ break;
+ }
+
+
+
+ if (hw->mac_type == e1000_82573) {
+ uint32_t gcr = E1000_READ_REG(hw, GCR);
+ gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+ E1000_WRITE_REG(hw, GCR, gcr);
+ }
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
@@ -878,6 +917,14 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_fiber_serdes_link");
+ /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
+ * until explicitly turned off or a power cycle is performed. A read to
+ * the register does not indicate its status. Therefore, we ensure
+ * loopback mode is disabled during initialization.
+ */
+ if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
+ E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
* set when the optics detect a signal. On older adapters, it will be
* cleared when there is a signal. This applies to fiber media only.
@@ -2943,6 +2990,8 @@ e1000_phy_reset(struct e1000_hw *hw)
switch (hw->mac_type) {
case e1000_82541_rev_2:
+ case e1000_82571:
+ case e1000_82572:
ret_val = e1000_phy_hw_reset(hw);
if(ret_val)
return ret_val;
@@ -2981,6 +3030,16 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
DEBUGFUNC("e1000_detect_gig_phy");
+ /* The 82571 firmware may still be configuring the PHY. In this
+ * case, we cannot access the PHY until the configuration is done. So
+ * we explicitly set the PHY values. */
+ if(hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572) {
+ hw->phy_id = IGP01E1000_I_PHY_ID;
+ hw->phy_type = e1000_phy_igp_2;
+ return E1000_SUCCESS;
+ }
+
/* Read the PHY ID Registers to identify which PHY is onboard. */
ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
if(ret_val)
@@ -3334,6 +3393,21 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->use_eerd = FALSE;
eeprom->use_eewr = FALSE;
break;
+ case e1000_82571:
+ case e1000_82572:
+ eeprom->type = e1000_eeprom_spi;
+ eeprom->opcode_bits = 8;
+ eeprom->delay_usec = 1;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->page_size = 32;
+ eeprom->address_bits = 16;
+ } else {
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ break;
case e1000_82573:
eeprom->type = e1000_eeprom_spi;
eeprom->opcode_bits = 8;
@@ -3543,25 +3617,26 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
eecd = E1000_READ_REG(hw, EECD);
if (hw->mac_type != e1000_82573) {
- /* Request EEPROM Access */
- if(hw->mac_type > e1000_82544) {
- eecd |= E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
- eecd = E1000_READ_REG(hw, EECD);
- while((!(eecd & E1000_EECD_GNT)) &&
- (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
- i++;
- udelay(5);
- eecd = E1000_READ_REG(hw, EECD);
- }
- if(!(eecd & E1000_EECD_GNT)) {
- eecd &= ~E1000_EECD_REQ;
+ /* Request EEPROM Access */
+ if(hw->mac_type > e1000_82544) {
+ eecd |= E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
- DEBUGOUT("Could not acquire EEPROM grant\n");
- return -E1000_ERR_EEPROM;
+ eecd = E1000_READ_REG(hw, EECD);
+ while((!(eecd & E1000_EECD_GNT)) &&
+ (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+ i++;
+ udelay(5);
+ eecd = E1000_READ_REG(hw, EECD);
+ }
+ if(!(eecd & E1000_EECD_GNT)) {
+ eecd &= ~E1000_EECD_REQ;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ DEBUGOUT("Could not acquire EEPROM grant\n");
+ e1000_put_hw_eeprom_semaphore(hw);
+ return -E1000_ERR_EEPROM;
+ }
}
}
- }
/* Setup EEPROM for Read/Write */
@@ -4064,7 +4139,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* 82573 reads only through eerd */
+ /* 82573 writes only through eewr */
if(eeprom->use_eewr == TRUE)
return e1000_write_eeprom_eewr(hw, offset, words, data);
@@ -4353,9 +4428,16 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
}
- if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ case e1000_82571:
+ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
hw->perm_mac_addr[5] ^= 0x01;
+ break;
+ }
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i];
@@ -4385,6 +4467,12 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
e1000_rar_set(hw, hw->mac_addr, 0);
rar_num = E1000_RAR_ENTRIES;
+
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+ rar_num -= 1;
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < rar_num; i++) {
@@ -4427,6 +4515,12 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+ num_rar_entry -= 1;
+
for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -4984,7 +5078,6 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, ICTXQEC);
temp = E1000_READ_REG(hw, ICTXQMTC);
temp = E1000_READ_REG(hw, ICRXDMTC);
-
}
/******************************************************************************
@@ -5151,6 +5244,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
hw->bus_type = e1000_bus_type_pci_express;
hw->bus_speed = e1000_bus_speed_2500;
@@ -5250,6 +5345,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
int32_t ret_val;
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+ uint16_t max_agc = 0;
uint16_t i, phy_data;
uint16_t cable_length;
@@ -5338,6 +5434,40 @@ e1000_get_cable_length(struct e1000_hw *hw,
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
+ } else if (hw->phy_type == e1000_phy_igp_2) {
+ uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+ {IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+ IGP02E1000_PHY_AGC_D};
+ /* Read the AGC registers for all channels */
+ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
+ ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Getting bits 15:9, which represent the combination of course and
+ * fine gain values. The result is a number that can be put into
+ * the lookup table to obtain the approximate cable length. */
+ cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+ IGP02E1000_AGC_LENGTH_MASK;
+
+ /* Remove min & max AGC values from calculation. */
+ if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
+ min_agc = cur_agc;
+ if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
+ max_agc = cur_agc;
+
+ agc_value += e1000_igp_2_cable_length_table[cur_agc];
+ }
+
+ agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
+ agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
+
+ /* Calculate cable length with the error range of +/- 10 meters. */
+ *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+ (agc_value - IGP02E1000_AGC_RANGE) : 0;
+ *max_length = agc_value + IGP02E1000_AGC_RANGE;
}
return E1000_SUCCESS;
@@ -6465,6 +6595,8 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
default:
msec_delay(5);
break;
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
while(timeout) {
if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
@@ -6494,10 +6626,31 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
int32_t
e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
+ int32_t timeout = PHY_CFG_TIMEOUT;
+ uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
+
DEBUGFUNC("e1000_get_phy_cfg_done");
- /* Simply wait for 10ms */
- msec_delay(10);
+ switch (hw->mac_type) {
+ default:
+ msec_delay(10);
+ break;
+ case e1000_82571:
+ case e1000_82572:
+ while (timeout) {
+ if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+ break;
+ else
+ msec_delay(1);
+ timeout--;
+ }
+
+ if (!timeout) {
+ DEBUGOUT("MNG configuration cycle has not completed.\n");
+ return -E1000_ERR_RESET;
+ }
+ break;
+ }
return E1000_SUCCESS;
}
@@ -6569,8 +6722,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
return;
swsm = E1000_READ_REG(hw, SWSM);
- /* Release both semaphores. */
- swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+ swsm &= ~(E1000_SWSM_SWESMBI);
E1000_WRITE_REG(hw, SWSM, swsm);
}
@@ -6606,6 +6758,8 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* if this is the case. We read FWSM to determine the manageability mode.
*/
switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
case e1000_82573:
fwsm = E1000_READ_REG(hw, FWSM);
if((fwsm & E1000_FWSM_MODE_MASK) != 0)
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 93e9f8788751..4f2c196dc314 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -57,6 +57,8 @@ typedef enum {
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
+ e1000_82571,
+ e1000_82572,
e1000_82573,
e1000_num_macs
} e1000_mac_type;
@@ -478,10 +480,16 @@ uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82571EB_COPPER 0x105E
+#define E1000_DEV_ID_82571EB_FIBER 0x105F
+#define E1000_DEV_ID_82571EB_SERDES 0x1060
+#define E1000_DEV_ID_82572EI_COPPER 0x107D
+#define E1000_DEV_ID_82572EI_FIBER 0x107E
+#define E1000_DEV_ID_82572EI_SERDES 0x107F
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
+#define E1000_DEV_ID_82573L 0x109A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -833,6 +841,8 @@ struct e1000_ffvt_entry {
#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_DISABLE_SERDES_LOOPBACK 0x0400
+
/* Register Set. (82543, 82544)
*
* Registers are defined to be 32 bits and should be accessed as 32 bit values.
@@ -853,6 +863,7 @@ struct e1000_ffvt_entry {
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
+#define E1000_SCTL 0x00024 /* SerDes Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
@@ -864,6 +875,12 @@ struct e1000_ffvt_entry {
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* RX Control - RW */
+#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
+#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
+#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
+#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
+#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
+#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
@@ -895,6 +912,12 @@ struct e1000_ffvt_entry {
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
+#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
+#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
+#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
+#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
+#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
+#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
@@ -980,15 +1003,15 @@ struct e1000_ffvt_entry {
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC 0x4100 /* Interrupt Assertion Count */
-#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
@@ -1018,6 +1041,14 @@ struct e1000_ffvt_entry {
#define E1000_FWSM 0x05B54 /* FW Semaphore */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Inteface Control */
+
+/* RSS registers */
+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
+#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
+#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
@@ -1032,6 +1063,7 @@ struct e1000_ffvt_entry {
#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
#define E1000_82542_FLA E1000_FLA
#define E1000_82542_MDIC E1000_MDIC
+#define E1000_82542_SCTL E1000_SCTL
#define E1000_82542_FCAL E1000_FCAL
#define E1000_82542_FCAH E1000_FCAH
#define E1000_82542_FCT E1000_FCT
@@ -1049,6 +1081,18 @@ struct e1000_ffvt_entry {
#define E1000_82542_RDLEN 0x00118
#define E1000_82542_RDH 0x00120
#define E1000_82542_RDT 0x00128
+#define E1000_82542_RDTR0 E1000_82542_RDTR
+#define E1000_82542_RDBAL0 E1000_82542_RDBAL
+#define E1000_82542_RDBAH0 E1000_82542_RDBAH
+#define E1000_82542_RDLEN0 E1000_82542_RDLEN
+#define E1000_82542_RDH0 E1000_82542_RDH
+#define E1000_82542_RDT0 E1000_82542_RDT
+#define E1000_82542_RDTR1 0x00130
+#define E1000_82542_RDBAL1 0x00138
+#define E1000_82542_RDBAH1 0x0013C
+#define E1000_82542_RDLEN1 0x00140
+#define E1000_82542_RDH1 0x00148
+#define E1000_82542_RDT1 0x00150
#define E1000_82542_FCRTH 0x00160
#define E1000_82542_FCRTL 0x00168
#define E1000_82542_FCTTV E1000_FCTTV
@@ -1197,6 +1241,13 @@ struct e1000_ffvt_entry {
#define E1000_82542_ICRXOC E1000_ICRXOC
#define E1000_82542_HICR E1000_HICR
+#define E1000_82542_CPUVEC E1000_CPUVEC
+#define E1000_82542_MRQC E1000_MRQC
+#define E1000_82542_RETA E1000_RETA
+#define E1000_82542_RSSRK E1000_RSSRK
+#define E1000_82542_RSSIM E1000_RSSIM
+#define E1000_82542_RSSIR E1000_RSSIR
+
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
uint64_t crcerrs;
@@ -1270,7 +1321,7 @@ struct e1000_hw_stats {
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t *hw_addr;
+ uint8_t __iomem *hw_addr;
uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
@@ -1336,6 +1387,7 @@ struct e1000_hw {
boolean_t serdes_link_down;
boolean_t tbi_compatibility_en;
boolean_t tbi_compatibility_on;
+ boolean_t laa_is_present;
boolean_t phy_reset_disable;
boolean_t fc_send_xon;
boolean_t fc_strict_ieee;
@@ -1374,6 +1426,7 @@ struct e1000_hw {
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
@@ -1491,6 +1544,8 @@ struct e1000_hw {
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
+#define E1000_CTRL_EXT_CANC 0x04000000 /* Interrupt delay cancellation */
+#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 */
@@ -1524,6 +1579,7 @@ struct e1000_hw {
#define E1000_LEDCTL_LED2_BLINK 0x00800000
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
#define E1000_LEDCTL_LED3_MODE_SHIFT 24
+#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
#define E1000_LEDCTL_LED3_IVRT 0x40000000
#define E1000_LEDCTL_LED3_BLINK 0x80000000
@@ -1784,6 +1840,16 @@ struct e1000_hw {
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+/* Multiple Receive Queue Control */
+#define E1000_MRQC_ENABLE_MASK 0x00000003
+#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
@@ -1928,6 +1994,7 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
#define E1000_GCR_BEM32 0x00400000
+#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
#define E1000_FACTPS_LAN0_VALID 0x00000004
@@ -1980,6 +2047,7 @@ struct e1000_host_command_info {
/* EEPROM Word Offsets */
#define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004
+#define EEPROM_VERSION 0x0005
#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
@@ -1990,6 +2058,8 @@ struct e1000_host_command_info {
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
+#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
+
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
@@ -2108,6 +2178,8 @@ struct e1000_host_command_info {
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
@@ -2592,11 +2664,11 @@ struct e1000_host_command_info {
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
/* The precision error of the cable length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
-#define IGP02E1000_AGC_RANGE 10
+#define IGP02E1000_AGC_RANGE 15
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5e5d2c3c7ce4..efbbda7cbcbf 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -43,7 +43,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.0.60-k2"DRIVERNAPI
+#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -80,6 +80,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1026),
INTEL_E1000_ETHERNET_DEVICE(0x1027),
INTEL_E1000_ETHERNET_DEVICE(0x1028),
+ INTEL_E1000_ETHERNET_DEVICE(0x105E),
+ INTEL_E1000_ETHERNET_DEVICE(0x105F),
+ INTEL_E1000_ETHERNET_DEVICE(0x1060),
INTEL_E1000_ETHERNET_DEVICE(0x1075),
INTEL_E1000_ETHERNET_DEVICE(0x1076),
INTEL_E1000_ETHERNET_DEVICE(0x1077),
@@ -88,10 +91,13 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x107A),
INTEL_E1000_ETHERNET_DEVICE(0x107B),
INTEL_E1000_ETHERNET_DEVICE(0x107C),
+ INTEL_E1000_ETHERNET_DEVICE(0x107D),
+ INTEL_E1000_ETHERNET_DEVICE(0x107E),
+ INTEL_E1000_ETHERNET_DEVICE(0x107F),
INTEL_E1000_ETHERNET_DEVICE(0x108A),
INTEL_E1000_ETHERNET_DEVICE(0x108B),
INTEL_E1000_ETHERNET_DEVICE(0x108C),
- INTEL_E1000_ETHERNET_DEVICE(0x1099),
+ INTEL_E1000_ETHERNET_DEVICE(0x109A),
/* required last entry */
{0,}
};
@@ -102,10 +108,18 @@ int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter);
void e1000_reset(struct e1000_adapter *adapter);
int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr);
+void e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
+void e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
void e1000_update_stats(struct e1000_adapter *adapter);
/* Local Function Prototypes */
@@ -114,14 +128,22 @@ static int e1000_init_module(void);
static void e1000_exit_module(void);
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void __devexit e1000_remove(struct pci_dev *pdev);
+static int e1000_alloc_queues(struct e1000_adapter *adapter);
+#ifdef CONFIG_E1000_MQ
+static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
+#endif
static int e1000_sw_init(struct e1000_adapter *adapter);
static int e1000_open(struct net_device *netdev);
static int e1000_close(struct net_device *netdev);
static void e1000_configure_tx(struct e1000_adapter *adapter);
static void e1000_configure_rx(struct e1000_adapter *adapter);
static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
@@ -132,19 +154,26 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
#ifdef CONFIG_E1000_NAPI
-static int e1000_clean(struct net_device *netdev, int *budget);
+static int e1000_clean(struct net_device *poll_dev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
#else
-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
#endif
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
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);
@@ -162,8 +191,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);
-static int e1000_suspend(struct pci_dev *pdev, uint32_t state);
#ifdef CONFIG_PM
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
static int e1000_resume(struct pci_dev *pdev);
#endif
@@ -172,6 +201,11 @@ static int e1000_resume(struct pci_dev *pdev);
static void e1000_netpoll (struct net_device *netdev);
#endif
+#ifdef CONFIG_E1000_MQ
+/* for multiple Rx queues */
+void e1000_rx_schedule(void *data);
+#endif
+
/* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -289,7 +323,7 @@ int
e1000_up(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int err;
+ int i, err;
/* hardware has been reset, we need to reload some things */
@@ -308,7 +342,8 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- adapter->alloc_rx_buf(adapter);
+ for (i = 0; i < adapter->num_queues; i++)
+ adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2) {
@@ -344,6 +379,9 @@ e1000_down(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
e1000_irq_disable(adapter);
+#ifdef CONFIG_E1000_MQ
+ while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
+#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
if(adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -363,11 +401,10 @@ e1000_down(struct e1000_adapter *adapter)
netif_stop_queue(netdev);
e1000_reset(adapter);
- e1000_clean_tx_ring(adapter);
- e1000_clean_rx_ring(adapter);
+ e1000_clean_all_tx_rings(adapter);
+ e1000_clean_all_rx_rings(adapter);
- /* If WoL is not enabled
- * and management mode is not IAMT
+ /* If WoL is not enabled and management mode is not IAMT
* Power down the PHY so no link is implied when interface is down */
if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
@@ -398,6 +435,10 @@ e1000_reset(struct e1000_adapter *adapter)
case e1000_82547_rev_2:
pba = E1000_PBA_30K;
break;
+ case e1000_82571:
+ case e1000_82572:
+ pba = E1000_PBA_38K;
+ break;
case e1000_82573:
pba = E1000_PBA_12K;
break;
@@ -475,6 +516,7 @@ e1000_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct e1000_adapter *adapter;
unsigned long mmio_start, mmio_len;
+ uint32_t ctrl_ext;
uint32_t swsm;
static int cards_found = 0;
@@ -614,8 +656,9 @@ e1000_probe(struct pci_dev *pdev,
if(e1000_read_mac_addr(&adapter->hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -687,6 +730,12 @@ e1000_probe(struct pci_dev *pdev,
/* Let firmware know the driver has taken over */
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -731,7 +780,11 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ uint32_t ctrl_ext;
uint32_t manc, swsm;
+#ifdef CONFIG_E1000_NAPI
+ int i;
+#endif
flush_scheduled_work();
@@ -745,6 +798,12 @@ e1000_remove(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -756,13 +815,27 @@ e1000_remove(struct pci_dev *pdev)
}
unregister_netdev(netdev);
+#ifdef CONFIG_E1000_NAPI
+ for (i = 0; i < adapter->num_queues; i++)
+ __dev_put(&adapter->polling_netdev[i]);
+#endif
if(!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+#ifdef CONFIG_E1000_NAPI
+ kfree(adapter->polling_netdev);
+#endif
+
iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev);
+#ifdef CONFIG_E1000_MQ
+ free_percpu(adapter->cpu_netdev);
+ free_percpu(adapter->cpu_tx_ring);
+#endif
free_netdev(netdev);
pci_disable_device(pdev);
@@ -783,6 +856,9 @@ e1000_sw_init(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
+#ifdef CONFIG_E1000_NAPI
+ int i;
+#endif
/* PCI config space info */
@@ -840,14 +916,123 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->master_slave = E1000_MASTER_SLAVE;
}
+#ifdef CONFIG_E1000_MQ
+ /* Number of supported queues */
+ switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ adapter->num_queues = 2;
+ break;
+ default:
+ adapter->num_queues = 1;
+ break;
+ }
+ adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+#else
+ adapter->num_queues = 1;
+#endif
+
+ if (e1000_alloc_queues(adapter)) {
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+#ifdef CONFIG_E1000_NAPI
+ for (i = 0; i < adapter->num_queues; i++) {
+ adapter->polling_netdev[i].priv = adapter;
+ adapter->polling_netdev[i].poll = &e1000_clean;
+ adapter->polling_netdev[i].weight = 64;
+ dev_hold(&adapter->polling_netdev[i]);
+ set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+ }
+#endif
+
+#ifdef CONFIG_E1000_MQ
+ e1000_setup_queue_mapping(adapter);
+#endif
+
atomic_set(&adapter->irq_sem, 1);
spin_lock_init(&adapter->stats_lock);
- spin_lock_init(&adapter->tx_lock);
return 0;
}
/**
+ * e1000_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time. The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+
+static int __devinit
+e1000_alloc_queues(struct e1000_adapter *adapter)
+{
+ int size;
+
+ size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ adapter->tx_ring = kmalloc(size, GFP_KERNEL);
+ if (!adapter->tx_ring)
+ return -ENOMEM;
+ memset(adapter->tx_ring, 0, size);
+
+ size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+ adapter->rx_ring = kmalloc(size, GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ return -ENOMEM;
+ }
+ memset(adapter->rx_ring, 0, size);
+
+#ifdef CONFIG_E1000_NAPI
+ size = sizeof(struct net_device) * adapter->num_queues;
+ adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
+ if (!adapter->polling_netdev) {
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+ return -ENOMEM;
+ }
+ memset(adapter->polling_netdev, 0, size);
+#endif
+
+ return E1000_SUCCESS;
+}
+
+#ifdef CONFIG_E1000_MQ
+static void __devinit
+e1000_setup_queue_mapping(struct e1000_adapter *adapter)
+{
+ int i, cpu;
+
+ adapter->rx_sched_call_data.func = e1000_rx_schedule;
+ adapter->rx_sched_call_data.info = adapter->netdev;
+ cpus_clear(adapter->rx_sched_call_data.cpumask);
+
+ adapter->cpu_netdev = alloc_percpu(struct net_device *);
+ adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+
+ lock_cpu_hotplug();
+ i = 0;
+ for_each_online_cpu(cpu) {
+ *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+ /* This is incomplete because we'd like to assign separate
+ * physical cpus to these netdev polling structures and
+ * avoid saturating a subset of cpus.
+ */
+ if (i < adapter->num_queues) {
+ *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
+ adapter->cpu_for_queue[i] = cpu;
+ } else
+ *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
+
+ i++;
+ }
+ unlock_cpu_hotplug();
+}
+#endif
+
+/**
* e1000_open - Called when a network interface is made active
* @netdev: network interface device structure
*
@@ -868,12 +1053,12 @@ e1000_open(struct net_device *netdev)
/* allocate transmit descriptors */
- if((err = e1000_setup_tx_resources(adapter)))
+ if ((err = e1000_setup_all_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
- if((err = e1000_setup_rx_resources(adapter)))
+ if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
if((err = e1000_up(adapter)))
@@ -887,9 +1072,9 @@ e1000_open(struct net_device *netdev)
return E1000_SUCCESS;
err_up:
- e1000_free_rx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
err_setup_rx:
- e1000_free_tx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
err_setup_tx:
e1000_reset(adapter);
@@ -915,8 +1100,8 @@ e1000_close(struct net_device *netdev)
e1000_down(adapter);
- e1000_free_tx_resources(adapter);
- e1000_free_rx_resources(adapter);
+ e1000_free_all_tx_resources(adapter);
+ e1000_free_all_rx_resources(adapter);
if((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
@@ -951,25 +1136,28 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
/**
* e1000_setup_tx_resources - allocate Tx resources (Descriptors)
* @adapter: board private structure
+ * @txdr: tx descriptor ring (for a specific queue) to setup
*
* Return 0 on success, negative on failure
**/
int
-e1000_setup_tx_resources(struct e1000_adapter *adapter)
+e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr)
{
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct e1000_buffer) * txdr->count;
- txdr->buffer_info = vmalloc(size);
+
+ txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
if(!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
+ memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
/* round up to nearest 4K */
@@ -1018,11 +1206,41 @@ setup_tx_desc_die:
txdr->next_to_use = 0;
txdr->next_to_clean = 0;
+ spin_lock_init(&txdr->tx_lock);
return 0;
}
/**
+ * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
+ * (Descriptors) for all queues
+ * @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
+ **/
+
+int
+e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_queues; i++) {
+ err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Tx Queue %u failed\n", i);
+ break;
+ }
+ }
+
+ return err;
+}
+
+/**
* e1000_configure_tx - Configure 8254x Transmit Unit after Reset
* @adapter: board private structure
*
@@ -1032,23 +1250,43 @@ setup_tx_desc_die:
static void
e1000_configure_tx(struct e1000_adapter *adapter)
{
- uint64_t tdba = adapter->tx_ring.dma;
- uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
- uint32_t tctl, tipg;
-
- E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
-
- E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
+ uint64_t tdba;
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t tdlen, tctl, tipg, tarc;
/* Setup the HW Tx Head and Tail descriptor pointers */
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
+ switch (adapter->num_queues) {
+ case 2:
+ tdba = adapter->tx_ring[1].dma;
+ tdlen = adapter->tx_ring[1].count *
+ sizeof(struct e1000_tx_desc);
+ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
+ E1000_WRITE_REG(hw, TDLEN1, tdlen);
+ E1000_WRITE_REG(hw, TDH1, 0);
+ E1000_WRITE_REG(hw, TDT1, 0);
+ adapter->tx_ring[1].tdh = E1000_TDH1;
+ adapter->tx_ring[1].tdt = E1000_TDT1;
+ /* Fall Through */
+ case 1:
+ default:
+ tdba = adapter->tx_ring[0].dma;
+ tdlen = adapter->tx_ring[0].count *
+ sizeof(struct e1000_tx_desc);
+ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+ E1000_WRITE_REG(hw, TDLEN, tdlen);
+ E1000_WRITE_REG(hw, TDH, 0);
+ E1000_WRITE_REG(hw, TDT, 0);
+ adapter->tx_ring[0].tdh = E1000_TDH;
+ adapter->tx_ring[0].tdt = E1000_TDT;
+ break;
+ }
/* Set the default values for the Tx Inter Packet Gap timer */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
@@ -1056,67 +1294,81 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
break;
default:
- if(adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes)
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes)
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
else
tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
}
- E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
+ E1000_WRITE_REG(hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
- E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
- if(adapter->hw.mac_type >= e1000_82540)
- E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay);
+ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+ if (hw->mac_type >= e1000_82540)
+ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
/* Program the Transmit Control Register */
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+ tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_CT;
- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
+ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+ E1000_WRITE_REG(hw, TCTL, tctl);
- e1000_config_collision_dist(&adapter->hw);
+ if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
+ tarc = E1000_READ_REG(hw, TARC0);
+ tarc |= ((1 << 25) | (1 << 21));
+ E1000_WRITE_REG(hw, TARC0, tarc);
+ tarc = E1000_READ_REG(hw, TARC1);
+ tarc |= (1 << 25);
+ if (tctl & E1000_TCTL_MULR)
+ tarc &= ~(1 << 28);
+ else
+ tarc |= (1 << 28);
+ E1000_WRITE_REG(hw, TARC1, tarc);
+ }
+
+ e1000_config_collision_dist(hw);
/* Setup Transmit Descriptor Settings for eop descriptor */
adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
E1000_TXD_CMD_IFCS;
- if(adapter->hw.mac_type < e1000_82543)
+ if (hw->mac_type < e1000_82543)
adapter->txd_cmd |= E1000_TXD_CMD_RPS;
else
adapter->txd_cmd |= E1000_TXD_CMD_RS;
/* Cache if we're 82544 running in PCI-X because we'll
* need this to apply a workaround later in the send path. */
- if(adapter->hw.mac_type == e1000_82544 &&
- adapter->hw.bus_type == e1000_bus_type_pcix)
+ if (hw->mac_type == e1000_82544 &&
+ hw->bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
}
/**
* e1000_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: board private structure
+ * @rxdr: rx descriptor ring (for a specific queue) to setup
*
* Returns 0 on success, negative on failure
**/
int
-e1000_setup_rx_resources(struct e1000_adapter *adapter)
+e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr)
{
- struct e1000_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
- rxdr->buffer_info = vmalloc(size);
- if(!rxdr->buffer_info) {
+ rxdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+ if (!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
@@ -1156,13 +1408,13 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if(!rxdr->desc) {
+ if (!rxdr->desc) {
+ DPRINTK(PROBE, ERR,
+ "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);
- DPRINTK(PROBE, ERR,
- "Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
}
@@ -1174,9 +1426,12 @@ setup_rx_desc_die:
"at %p\n", rxdr->size, rxdr->desc);
/* Try again, without freeing the previous */
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if(!rxdr->desc) {
/* Failed allocation, critical failure */
+ if (!rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory "
+ "for the receive descriptor ring\n");
goto setup_rx_desc_die;
}
@@ -1188,10 +1443,7 @@ setup_rx_desc_die:
DPRINTK(PROBE, ERR,
"Unable to allocate aligned memory "
"for the receive descriptor ring\n");
- vfree(rxdr->buffer_info);
- kfree(rxdr->ps_page);
- kfree(rxdr->ps_page_dma);
- return -ENOMEM;
+ goto setup_rx_desc_die;
} else {
/* Free old allocation, new allocation was successful */
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
@@ -1206,15 +1458,48 @@ setup_rx_desc_die:
}
/**
+ * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
+ * (Descriptors) for all queues
+ * @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
+ **/
+
+int
+e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_queues; i++) {
+ err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Rx Queue %u failed\n", i);
+ break;
+ }
+ }
+
+ return err;
+}
+
+/**
* e1000_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
-
+#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+ (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
static void
e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
+#ifdef CONFIG_E1000_PACKET_SPLIT
+ uint32_t pages = 0;
+#endif
rctl = E1000_READ_REG(&adapter->hw, RCTL);
@@ -1235,7 +1520,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type == e1000_82573) {
+ if(adapter->hw.mac_type >= e1000_82571) {
/* We can now specify buffers in 1K increments.
* BSIZE and BSEX are ignored in this case. */
rctl |= adapter->rx_buffer_len << 0x11;
@@ -1268,11 +1553,14 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
* followed by the page buffers. Therefore, skb->data is
* sized to hold the largest protocol header.
*/
- adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2)
- && (adapter->netdev->mtu
- < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+ pages = PAGE_USE_COUNT(adapter->netdev->mtu);
+ if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) &&
+ PAGE_SIZE <= 16384)
+ adapter->rx_ps_pages = pages;
+ else
+ adapter->rx_ps_pages = 0;
#endif
- if(adapter->rx_ps) {
+ if (adapter->rx_ps_pages) {
/* Configure extra packet-split registers */
rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
@@ -1284,12 +1572,19 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
- psrctl |= PAGE_SIZE >>
- E1000_PSRCTL_BSIZE1_SHIFT;
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE2_SHIFT;
- psrctl |= PAGE_SIZE <<
- E1000_PSRCTL_BSIZE3_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;
+ }
E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
}
@@ -1307,91 +1602,181 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
static void
e1000_configure_rx(struct e1000_adapter *adapter)
{
- uint64_t rdba = adapter->rx_ring.dma;
- uint32_t rdlen, rctl, rxcsum;
+ uint64_t rdba;
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t rdlen, rctl, rxcsum, ctrl_ext;
+#ifdef CONFIG_E1000_MQ
+ uint32_t reta, mrqc;
+ int i;
+#endif
- if(adapter->rx_ps) {
- rdlen = adapter->rx_ring.count *
+ if (adapter->rx_ps_pages) {
+ 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.count * sizeof(struct e1000_rx_desc);
+ 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 = E1000_READ_REG(&adapter->hw, RCTL);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
/* set the Receive Delay Timer Register */
- E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
- if(adapter->hw.mac_type >= e1000_82540) {
- E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
+ if (hw->mac_type >= e1000_82540) {
+ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
if(adapter->itr > 1)
- E1000_WRITE_REG(&adapter->hw, ITR,
+ E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
- /* Setup the Base and Length of the Rx Descriptor Ring */
- E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
+ if (hw->mac_type >= e1000_82571) {
+ /* Reset delay timers after every interrupt */
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_CANC;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+ }
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring */
+ switch (adapter->num_queues) {
+#ifdef CONFIG_E1000_MQ
+ case 2:
+ rdba = adapter->rx_ring[1].dma;
+ E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
+ E1000_WRITE_REG(hw, RDLEN1, rdlen);
+ E1000_WRITE_REG(hw, RDH1, 0);
+ E1000_WRITE_REG(hw, RDT1, 0);
+ adapter->rx_ring[1].rdh = E1000_RDH1;
+ adapter->rx_ring[1].rdt = E1000_RDT1;
+ /* Fall Through */
+#endif
+ case 1:
+ default:
+ rdba = adapter->rx_ring[0].dma;
+ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+ E1000_WRITE_REG(hw, RDLEN, rdlen);
+ E1000_WRITE_REG(hw, RDH, 0);
+ E1000_WRITE_REG(hw, RDT, 0);
+ adapter->rx_ring[0].rdh = E1000_RDH;
+ adapter->rx_ring[0].rdt = E1000_RDT;
+ break;
+ }
+
+#ifdef CONFIG_E1000_MQ
+ if (adapter->num_queues > 1) {
+ uint32_t random[10];
+
+ get_random_bytes(&random[0], 40);
+
+ if (hw->mac_type <= e1000_82572) {
+ E1000_WRITE_REG(hw, RSSIR, 0);
+ E1000_WRITE_REG(hw, RSSIM, 0);
+ }
- E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
+ switch (adapter->num_queues) {
+ case 2:
+ default:
+ reta = 0x00800080;
+ mrqc = E1000_MRQC_ENABLE_RSS_2Q;
+ break;
+ }
- /* Setup the HW Rx Head and Tail Descriptor Pointers */
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ /* Fill out redirection table */
+ for (i = 0; i < 32; i++)
+ E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
+ /* Fill out hash function seeds */
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
+
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP);
+ E1000_WRITE_REG(hw, MRQC, mrqc);
+ }
+
+ /* Multiqueue and packet checksumming are mutually exclusive. */
+ if (hw->mac_type >= e1000_82571) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
+ rxcsum |= E1000_RXCSUM_PCSD;
+ E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+ }
+
+#else
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if(adapter->hw.mac_type >= e1000_82543) {
- rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
+ if (hw->mac_type >= e1000_82543) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
if(adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
- /* Enable 82573 IPv4 payload checksum for UDP fragments
+ /* Enable 82571 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if((adapter->hw.mac_type > e1000_82547_rev_2) &&
- (adapter->rx_ps)) {
+ if ((hw->mac_type >= e1000_82571) &&
+ (adapter->rx_ps_pages)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
rxcsum &= ~E1000_RXCSUM_TUOFL;
/* don't need to clear IPPCSE as it defaults to 0 */
}
- E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
+ E1000_WRITE_REG(hw, RXCSUM, rxcsum);
}
+#endif /* CONFIG_E1000_MQ */
- if (adapter->hw.mac_type == e1000_82573)
- E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+ if (hw->mac_type == e1000_82573)
+ E1000_WRITE_REG(hw, ERT, 0x0100);
/* Enable Receives */
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
}
/**
- * e1000_free_tx_resources - Free Tx Resources
+ * e1000_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
**/
void
-e1000_free_tx_resources(struct e1000_adapter *adapter)
+e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_tx_ring(adapter);
+ e1000_clean_tx_ring(adapter, tx_ring);
- vfree(adapter->tx_ring.buffer_info);
- adapter->tx_ring.buffer_info = NULL;
+ vfree(tx_ring->buffer_info);
+ tx_ring->buffer_info = NULL;
- pci_free_consistent(pdev, adapter->tx_ring.size,
- adapter->tx_ring.desc, adapter->tx_ring.dma);
+ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
- adapter->tx_ring.desc = NULL;
+ tx_ring->desc = NULL;
+}
+
+/**
+ * e1000_free_all_tx_resources - Free Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+void
+e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
static inline void
@@ -1414,21 +1799,22 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
/**
* e1000_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
+ * @tx_ring: ring to be cleaned
**/
static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter)
+e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
/* Free all the Tx ring sk_buffs */
- if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &adapter->previous_buffer_info);
+ &tx_ring->previous_buffer_info);
}
for(i = 0; i < tx_ring->count; i++) {
@@ -1446,24 +1832,39 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
+ writel(0, adapter->hw.hw_addr + tx_ring->tdh);
+ writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+}
+
+/**
+ * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
}
/**
* e1000_free_rx_resources - Free Rx Resources
* @adapter: board private structure
+ * @rx_ring: ring to clean the resources from
*
* Free all receive software resources
**/
void
-e1000_free_rx_resources(struct e1000_adapter *adapter)
+e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
- e1000_clean_rx_ring(adapter);
+ e1000_clean_rx_ring(adapter, rx_ring);
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
@@ -1478,14 +1879,31 @@ e1000_free_rx_resources(struct e1000_adapter *adapter)
}
/**
- * e1000_clean_rx_ring - Free Rx Buffers
+ * e1000_free_all_rx_resources - Free Rx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
+}
+
+/**
+ * e1000_clean_rx_ring - Free Rx Buffers per Queue
* @adapter: board private structure
+ * @rx_ring: ring to free buffers from
**/
static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter)
+e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
@@ -1508,7 +1926,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for(j = 0; j < adapter->rx_ps_pages; j++) {
if(!ps_page->ps_page[j]) break;
pci_unmap_single(pdev,
ps_page_dma->ps_page_dma[j],
@@ -1534,8 +1952,22 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ writel(0, adapter->hw.hw_addr + rx_ring->rdh);
+ writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+}
+
+/**
+ * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_queues; i++)
+ e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
}
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1556,7 +1988,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
mdelay(5);
if(netif_running(netdev))
- e1000_clean_rx_ring(adapter);
+ e1000_clean_all_rx_rings(adapter);
}
static void
@@ -1576,7 +2008,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
if(netif_running(netdev)) {
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter);
+ e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
}
}
@@ -1607,6 +2039,22 @@ e1000_set_mac(struct net_device *netdev, void *p)
e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ /* With 82571 controllers, LAA may be overwritten (with the default)
+ * due to controller reset from the other port. */
+ if (adapter->hw.mac_type == e1000_82571) {
+ /* activate the work around */
+ adapter->hw.laa_is_present = 1;
+
+ /* Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed (in e1000_watchdog), the actual LAA is in one
+ * of the RARs and no incoming packets directed to this port
+ * are dropped. Eventaully the LAA will be in RAR[0] and
+ * RAR[14] */
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ E1000_RAR_ENTRIES - 1);
+ }
+
if(adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
@@ -1629,12 +2077,13 @@ e1000_set_multi(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
- unsigned long flags;
uint32_t rctl;
uint32_t hash_value;
- int i;
+ int i, rar_entries = E1000_RAR_ENTRIES;
- spin_lock_irqsave(&adapter->tx_lock, flags);
+ /* reserve RAR[14] for LAA over-write work-around */
+ if (adapter->hw.mac_type == e1000_82571)
+ rar_entries--;
/* Check for Promiscuous and All Multicast modes */
@@ -1659,11 +2108,12 @@ e1000_set_multi(struct net_device *netdev)
/* load the first 14 multicast address into the exact filters 1-14
* RAR 0 is used for the station MAC adddress
* if there are not 14 addresses, go ahead and clear the filters
+ * -- with 82571 controllers only 0-13 entries are filled here
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < E1000_RAR_ENTRIES; i++) {
- if(mc_ptr) {
+ for(i = 1; i < rar_entries; i++) {
+ if (mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
} else {
@@ -1686,8 +2136,6 @@ e1000_set_multi(struct net_device *netdev)
if(hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
-
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
}
/* Need to wait a few seconds after link up to get diagnostic information from
@@ -1759,7 +2207,7 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_desc_ring *txdr = &adapter->tx_ring;
+ struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
uint32_t link;
e1000_check_for_link(&adapter->hw);
@@ -1818,8 +2266,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if(!netif_carrier_ok(netdev)) {
- if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
+ if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
@@ -1847,6 +2295,11 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = TRUE;
+ /* With 82571 controllers, LAA may be overwritten due to controller
+ * reset from the other port. Set the appropriate LAA in RAR[0] */
+ if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
@@ -1859,7 +2312,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
#define E1000_TX_FLAGS_VLAN_SHIFT 16
static inline int
-e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
@@ -1910,8 +2364,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
- i = adapter->tx_ring.next_to_use;
- context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+ i = tx_ring->next_to_use;
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -1923,8 +2377,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
- if(++i == adapter->tx_ring.count) i = 0;
- adapter->tx_ring.next_to_use = i;
+ if (++i == tx_ring->count) i = 0;
+ tx_ring->next_to_use = i;
return 1;
}
@@ -1934,7 +2388,8 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
}
static inline boolean_t
-e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
unsigned int i;
@@ -1943,8 +2398,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
- i = adapter->tx_ring.next_to_use;
- context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+ i = tx_ring->next_to_use;
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
@@ -1952,8 +2407,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
- if(unlikely(++i == adapter->tx_ring.count)) i = 0;
- adapter->tx_ring.next_to_use = i;
+ if (unlikely(++i == tx_ring->count)) i = 0;
+ tx_ring->next_to_use = i;
return TRUE;
}
@@ -1965,11 +2420,10 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
static inline int
-e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
- unsigned int first, unsigned int max_per_txd,
- unsigned int nr_frags, unsigned int mss)
+e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
+ unsigned int nr_frags, unsigned int mss)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_buffer *buffer_info;
unsigned int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
@@ -2065,9 +2519,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
}
static inline void
-e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
+e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ int tx_flags, int count)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -2113,7 +2567,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
wmb();
tx_ring->next_to_use = i;
- E1000_WRITE_REG(&adapter->hw, TDT, i);
+ writel(i, adapter->hw.hw_addr + tx_ring->tdt);
}
/**
@@ -2206,6 +2660,7 @@ static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_tx_ring *tx_ring;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
@@ -2218,7 +2673,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int f;
len -= skb->data_len;
- if(unlikely(skb->len <= 0)) {
+#ifdef CONFIG_E1000_MQ
+ tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#else
+ tx_ring = adapter->tx_ring;
+#endif
+
+ if (unlikely(skb->len <= 0)) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -2262,21 +2723,42 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(adapter->pcix_82544)
count += nr_frags;
- local_irq_save(flags);
- if (!spin_trylock(&adapter->tx_lock)) {
- /* Collision - tell upper layer to requeue */
- local_irq_restore(flags);
- return NETDEV_TX_LOCKED;
- }
+#ifdef NETIF_F_TSO
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ if (skb_shinfo(skb)->tso_size) {
+ uint8_t hdr_len;
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+ unsigned int pull_size;
+ pull_size = min((unsigned int)4, skb->data_len);
+ if (!__pskb_pull_tail(skb, pull_size)) {
+ printk(KERN_ERR "__pskb_pull_tail failed.\n");
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+ }
+ }
+#endif
+
if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
+ local_irq_save(flags);
+ if (!spin_trylock(&tx_ring->tx_lock)) {
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
- if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
+ if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_BUSY;
}
@@ -2284,7 +2766,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_BUSY;
}
}
@@ -2294,37 +2776,37 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
- first = adapter->tx_ring.next_to_use;
+ first = tx_ring->next_to_use;
- tso = e1000_tso(adapter, skb);
+ tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK;
}
if (likely(tso))
tx_flags |= E1000_TX_FLAGS_TSO;
- else if(likely(e1000_tx_csum(adapter, skb)))
+ else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
/* Old method was to assume IPv4 packet by default if TSO was enabled.
- * 82573 hardware supports TSO capabilities for IPv6 as well...
+ * 82571 hardware supports TSO capabilities for IPv6 as well...
* no longer assume, we must. */
- if(likely(skb->protocol == ntohs(ETH_P_IP)))
+ if (likely(skb->protocol == ntohs(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
- e1000_tx_queue(adapter,
- e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
- tx_flags);
+ e1000_tx_queue(adapter, tx_ring, tx_flags,
+ e1000_tx_map(adapter, tx_ring, skb, first,
+ max_per_txd, nr_frags, mss));
netdev->trans_start = jiffies;
/* Make sure there is space in the ring for the next send. */
- if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
+ if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
netif_stop_queue(netdev);
- spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -2388,9 +2870,18 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
-#define MAX_STD_JUMBO_FRAME_SIZE 9216
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
/* might want this to be bigger enum check... */
- if (adapter->hw.mac_type == e1000_82573 &&
+ /* 82571 controllers limit jumbo frame size to 10500 bytes */
+ if ((adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572) &&
+ max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
+ "on 82571 and 82572 controllers.\n");
+ return -EINVAL;
+ }
+
+ if(adapter->hw.mac_type == e1000_82573 &&
max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
"on 82573\n");
@@ -2544,7 +3035,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.rlec + adapter->stats.mpc +
adapter->stats.cexterr;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
@@ -2579,6 +3069,29 @@ e1000_update_stats(struct e1000_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
+#ifdef CONFIG_E1000_MQ
+void
+e1000_rx_schedule(void *data)
+{
+ struct net_device *poll_dev, *netdev = data;
+ struct e1000_adapter *adapter = netdev->priv;
+ int this_cpu = get_cpu();
+
+ poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
+ if (poll_dev == NULL) {
+ put_cpu();
+ return;
+ }
+
+ if (likely(netif_rx_schedule_prep(poll_dev)))
+ __netif_rx_schedule(poll_dev);
+ else
+ e1000_irq_enable(adapter);
+
+ put_cpu();
+}
+#endif
+
/**
* e1000_intr - Interrupt Handler
* @irq: interrupt number
@@ -2593,8 +3106,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
- unsigned int i;
+#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+ int i;
#endif
if(unlikely(!icr))
@@ -2606,17 +3119,31 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
#ifdef CONFIG_E1000_NAPI
- if(likely(netif_rx_schedule_prep(netdev))) {
-
- /* Disable interrupts and register for poll. The flush
- of the posted write is intentionally left out.
- */
-
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- __netif_rx_schedule(netdev);
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(hw, IMC, ~0);
+ E1000_WRITE_FLUSH(hw);
+#ifdef CONFIG_E1000_MQ
+ if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
+ cpu_set(adapter->cpu_for_queue[0],
+ adapter->rx_sched_call_data.cpumask);
+ for (i = 1; i < adapter->num_queues; i++) {
+ cpu_set(adapter->cpu_for_queue[i],
+ adapter->rx_sched_call_data.cpumask);
+ atomic_inc(&adapter->irq_sem);
+ }
+ atomic_set(&adapter->rx_sched_call_data.count, i);
+ smp_call_async_mask(&adapter->rx_sched_call_data);
+ } else {
+ printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
}
-#else
+#else /* if !CONFIG_E1000_MQ */
+ if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
+ __netif_rx_schedule(&adapter->polling_netdev[0]);
+ else
+ e1000_irq_enable(adapter);
+#endif /* CONFIG_E1000_MQ */
+
+#else /* if !CONFIG_E1000_NAPI */
/* Writing IMC and IMS is needed for 82547.
Due to Hub Link bus being occupied, an interrupt
de-assertion message is not able to be sent.
@@ -2633,13 +3160,14 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
}
for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter) &
- !e1000_clean_tx_irq(adapter)))
+ if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
break;
if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
-#endif
+
+#endif /* CONFIG_E1000_NAPI */
return IRQ_HANDLED;
}
@@ -2651,22 +3179,37 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
**/
static int
-e1000_clean(struct net_device *netdev, int *budget)
+e1000_clean(struct net_device *poll_dev, int *budget)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- int work_to_do = min(*budget, netdev->quota);
- int tx_cleaned;
- int work_done = 0;
+ struct e1000_adapter *adapter;
+ int work_to_do = min(*budget, poll_dev->quota);
+ int tx_cleaned, i = 0, work_done = 0;
+
+ /* Must NOT use netdev_priv macro here. */
+ adapter = poll_dev->priv;
+
+ /* Keep link state information with original netdev */
+ if (!netif_carrier_ok(adapter->netdev))
+ goto quit_polling;
- tx_cleaned = e1000_clean_tx_irq(adapter);
- adapter->clean_rx(adapter, &work_done, work_to_do);
+ while (poll_dev != &adapter->polling_netdev[i]) {
+ i++;
+ if (unlikely(i == adapter->num_queues))
+ BUG();
+ }
+
+ tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+ adapter->clean_rx(adapter, &adapter->rx_ring[i],
+ &work_done, work_to_do);
*budget -= work_done;
- netdev->quota -= work_done;
+ poll_dev->quota -= work_done;
- if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
/* If no Tx and not enough Rx work done, exit the polling mode */
- netif_rx_complete(netdev);
+ if((!tx_cleaned && (work_done == 0)) ||
+ !netif_running(adapter->netdev)) {
+quit_polling:
+ netif_rx_complete(poll_dev);
e1000_irq_enable(adapter);
return 0;
}
@@ -2681,9 +3224,9 @@ e1000_clean(struct net_device *netdev, int *budget)
**/
static boolean_t
-e1000_clean_tx_irq(struct e1000_adapter *adapter)
+e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
@@ -2694,12 +3237,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
- while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
/* Premature writeback of Tx descriptors clear (free buffers
* and unmap pci_mapping) previous_buffer_info */
- if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
e1000_unmap_and_free_tx_resource(adapter,
- &adapter->previous_buffer_info);
+ &tx_ring->previous_buffer_info);
}
for(cleaned = FALSE; !cleaned; ) {
@@ -2715,7 +3258,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
#ifdef NETIF_F_TSO
} else {
if (cleaned) {
- memcpy(&adapter->previous_buffer_info,
+ memcpy(&tx_ring->previous_buffer_info,
buffer_info,
sizeof(struct e1000_buffer));
memset(buffer_info, 0,
@@ -2733,6 +3276,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
if(unlikely(++i == tx_ring->count)) i = 0;
}
+
+ tx_ring->pkt++;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -2740,15 +3285,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
tx_ring->next_to_clean = i;
- spin_lock(&adapter->tx_lock);
+ spin_lock(&tx_ring->tx_lock);
if(unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
- spin_unlock(&adapter->tx_lock);
- if(adapter->detect_tx_hung) {
+ spin_unlock(&tx_ring->tx_lock);
+ if (adapter->detect_tx_hung) {
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = FALSE;
@@ -2767,16 +3312,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%zx>\n"
+ " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
- E1000_READ_REG(&adapter->hw, TDH),
- E1000_READ_REG(&adapter->hw, TDT),
+ readl(adapter->hw.hw_addr + tx_ring->tdh),
+ readl(adapter->hw.hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
i,
- tx_ring->buffer_info[i].dma,
+ (unsigned long long)tx_ring->buffer_info[i].dma,
tx_ring->buffer_info[i].time_stamp,
eop,
jiffies,
@@ -2785,12 +3330,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
}
#ifdef NETIF_F_TSO
-
- if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
+ if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+ time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
e1000_unmap_and_free_tx_resource(
- adapter, &adapter->previous_buffer_info);
-
+ adapter, &tx_ring->previous_buffer_info);
#endif
return cleaned;
}
@@ -2853,13 +3396,14 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
- int work_to_do)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
#endif
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -2945,6 +3489,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
+ rx_ring->pkt++;
next_desc:
rx_desc->status = 0;
@@ -2954,7 +3499,7 @@ next_desc:
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter);
+ adapter->alloc_rx_buf(adapter, rx_ring);
return cleaned;
}
@@ -2966,13 +3511,14 @@ next_desc:
static boolean_t
#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
- int work_to_do)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
#endif
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
union e1000_rx_desc_packet_split *rx_desc;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3028,7 +3574,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for(j = 0; j < adapter->rx_ps_pages; j++) {
if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
@@ -3049,11 +3595,13 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
-#ifdef HAVE_RX_ZERO_COPY
if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP))
+ E1000_RXDPS_HDRSTAT_HDRSP)) {
+ adapter->rx_hdr_split++;
+#ifdef HAVE_RX_ZERO_COPY
skb_shinfo(skb)->zero_copy = TRUE;
#endif
+ }
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -3072,6 +3620,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
+ rx_ring->pkt++;
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
@@ -3082,7 +3631,7 @@ next_desc:
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter);
+ adapter->alloc_rx_buf(adapter, rx_ring);
return cleaned;
}
@@ -3093,9 +3642,9 @@ next_desc:
**/
static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -3179,7 +3728,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- E1000_WRITE_REG(&adapter->hw, RDT, i);
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3195,9 +3744,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
**/
static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
@@ -3216,22 +3765,26 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
for(j = 0; j < PS_PAGE_BUFFERS; j++) {
- if(unlikely(!ps_page->ps_page[j])) {
- ps_page->ps_page[j] =
- alloc_page(GFP_ATOMIC);
- if(unlikely(!ps_page->ps_page[j]))
- 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]);
+ 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]))
+ 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] = ~0;
}
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
@@ -3265,7 +3818,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
* descriptors are 32 bytes...so we increment tail
* twice as much.
*/
- E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+ writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
}
if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3641,8 +4194,9 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
return 0;
}
+#ifdef CONFIG_PM
static int
-e1000_suspend(struct pci_dev *pdev, uint32_t state)
+e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3716,6 +4270,12 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3726,28 +4286,26 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
}
pci_disable_device(pdev);
-
- state = (state > 0) ? 3 : 0;
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
-#ifdef CONFIG_PM
static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t manc, ret_val, swsm;
+ uint32_t ctrl_ext;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
- pci_enable_wake(pdev, 3, 0);
- pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
@@ -3765,6 +4323,12 @@ e1000_resume(struct pci_dev *pdev)
}
switch(adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ break;
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3789,6 +4353,7 @@ e1000_netpoll(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
+ e1000_clean_tx_irq(adapter, adapter->tx_ring);
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 676247f9f1cc..38695d5b4637 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -306,7 +306,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_TXD,
.arg = { .r = { .min = E1000_MIN_TXD }}
};
- struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+ struct e1000_tx_ring *tx_ring = adapter->tx_ring;
+ int i;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD;
@@ -319,6 +320,8 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
tx_ring->count = opt.def;
}
+ for (i = 0; i < adapter->num_queues; i++)
+ tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
struct e1000_option opt = {
@@ -329,7 +332,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.def = E1000_DEFAULT_RXD,
.arg = { .r = { .min = E1000_MIN_RXD }}
};
- struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+ int i;
e1000_mac_type mac_type = adapter->hw.mac_type;
opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
E1000_MAX_82544_RXD;
@@ -342,6 +346,8 @@ e1000_check_options(struct e1000_adapter *adapter)
} else {
rx_ring->count = opt.def;
}
+ for (i = 0; i < adapter->num_queues; i++)
+ rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
struct e1000_option opt = {
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index dcb3028bb60f..a806dfe54d23 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -552,8 +552,7 @@ static int __init do_eepro_probe(struct net_device *dev)
{
unsigned short int WS[32]=WakeupSeq;
- if (check_region(WakeupPort, 2)==0) {
-
+ if (request_region(WakeupPort, 2, "eepro wakeup")) {
if (net_debug>5)
printk(KERN_DEBUG "Waking UP\n");
@@ -563,7 +562,10 @@ static int __init do_eepro_probe(struct net_device *dev)
outb_p(WS[i],WakeupPort);
if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
}
- } else printk(KERN_WARNING "Checkregion Failed!\n");
+
+ release_region(WakeupPort, 2);
+ } else
+ printk(KERN_WARNING "PnP wakeup region busy!\n");
}
#endif
@@ -705,7 +707,7 @@ static void __init eepro_print_info (struct net_device *dev)
dev->name, (unsigned)dev->base_addr);
break;
case LAN595FX:
- printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
+ printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
dev->name, (unsigned)dev->base_addr);
break;
case LAN595TX:
@@ -713,7 +715,7 @@ static void __init eepro_print_info (struct net_device *dev)
dev->name, (unsigned)dev->base_addr);
break;
case LAN595:
- printk("%s: Intel 82595-based lan card at %#x,",
+ printk("%s: Intel 82595-based lan card at %#x,",
dev->name, (unsigned)dev->base_addr);
}
@@ -726,7 +728,7 @@ static void __init eepro_print_info (struct net_device *dev)
if (dev->irq > 2)
printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
- else
+ else
printk(", %s.\n", ifmap[dev->if_port]);
if (net_debug > 3) {
@@ -756,7 +758,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
int err;
/* Grab the region so we can find another board if autoIRQ fails. */
- if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
+ if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
if (!autoprobe)
printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
ioaddr);
@@ -838,15 +840,15 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
/* Mask off INT number */
int count = lp->word[1] & 7;
unsigned irqMask = lp->word[7];
-
+
while (count--)
irqMask &= irqMask - 1;
-
+
count = ffs(irqMask);
-
+
if (count)
dev->irq = count - 1;
-
+
if (dev->irq < 2) {
printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
goto exit;
@@ -854,7 +856,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
dev->irq = 9;
}
}
-
+
dev->open = eepro_open;
dev->stop = eepro_close;
dev->hard_start_xmit = eepro_send_packet;
@@ -863,7 +865,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
dev->tx_timeout = eepro_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->ethtool_ops = &eepro_ethtool_ops;
-
+
/* print boot time info */
eepro_print_info(dev);
@@ -1047,8 +1049,8 @@ static int eepro_open(struct net_device *dev)
/* Initialize the RCV and XMT upper and lower limits */
- outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
- outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
@@ -1065,12 +1067,12 @@ static int eepro_open(struct net_device *dev)
eepro_clear_int(ioaddr);
/* Initialize RCV */
- outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
+ outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
lp->rx_start = lp->rcv_lower_limit;
- outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
+ outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
/* Initialize XMT */
- outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
+ outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
lp->tx_last = 0;
@@ -1411,7 +1413,7 @@ set_multicast_list(struct net_device *dev)
outb(0x08, ioaddr + STATUS_REG);
if (i & 0x20) { /* command ABORTed */
- printk(KERN_NOTICE "%s: multicast setup failed.\n",
+ printk(KERN_NOTICE "%s: multicast setup failed.\n",
dev->name);
break;
} else if ((i & 0x0f) == 0x03) { /* MC-Done */
@@ -1512,7 +1514,7 @@ hardware_send_packet(struct net_device *dev, void *buf, short length)
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
- if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
+ if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
/* Arrrr!!!, must keep the xmt header together,
several days were lost to chase this one down. */
last = lp->xmt_lower_limit;
@@ -1643,7 +1645,7 @@ eepro_rx(struct net_device *dev)
else if (rcv_status & 0x0800)
lp->stats.rx_crc_errors++;
- printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
+ printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
}
@@ -1674,10 +1676,10 @@ eepro_transmit_interrupt(struct net_device *dev)
{
struct eepro_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
- short boguscount = 25;
+ short boguscount = 25;
short xmt_status;
- while ((lp->tx_start != lp->tx_end) && boguscount--) {
+ while ((lp->tx_start != lp->tx_end) && boguscount--) {
outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
xmt_status = inw(ioaddr+IO_PORT);
@@ -1723,7 +1725,7 @@ static int eepro_ethtool_get_settings(struct net_device *dev,
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
- cmd->supported = SUPPORTED_10baseT_Half |
+ cmd->supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_Autoneg;
cmd->advertising = ADVERTISED_10baseT_Half |
@@ -1797,10 +1799,9 @@ MODULE_AUTHOR("Pascal Dupuis and others");
MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_LICENSE("GPL");
-static int num_params;
-module_param_array(io, int, &num_params, 0);
-module_param_array(irq, int, &num_params, 0);
-module_param_array(mem, int, &num_params, 0);
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
module_param(autodetect, int, 0);
MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 1795425f512e..8c62ced2c9b2 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1263,8 +1263,8 @@ speedo_init_rx_ring(struct net_device *dev)
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- /* XXX: do we really want to call this before the NULL check? --hch */
- rx_align(skb); /* Align IP on 16 byte boundary */
+ if (skb)
+ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* OK. Just initially short of Rx bufs. */
@@ -1654,8 +1654,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
struct sk_buff *skb;
/* Get a fresh skbuff to replace the consumed one. */
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- /* XXX: do we really want to call this before the NULL check? --hch */
- rx_align(skb); /* Align IP on 16 byte boundary */
+ if (skb)
+ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[entry] = skb;
if (skb == NULL) {
sp->rx_ringp[entry] = NULL;
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 87f522738bfc..f119ec4e89ea 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
static int epic_poll(struct net_device *dev, int *budget)
{
struct epic_private *ep = dev->priv;
- int work_done, orig_budget;
+ int work_done = 0, orig_budget;
long ioaddr = dev->base_addr;
orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
@@ -1343,7 +1343,7 @@ rx_action:
epic_tx(dev, ep);
- work_done = epic_rx(dev, *budget);
+ work_done += epic_rx(dev, *budget);
epic_rx_err(dev, ep);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 2c7008491378..85504fb900da 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -8,7 +8,7 @@
* describes connections using the internal parallel port I/O, which
* is basically all of Port D.
*
- * Right now, I am very watseful with the buffers. I allocate memory
+ * Right now, I am very wasteful with the buffers. I allocate memory
* pages and then divide them into 2K frame buffers. This way I know I
* have buffers large enough to hold one frame within one buffer descriptor.
* Once I get this working, I will use 64 or 128 byte CPM buffers, which
@@ -19,7 +19,10 @@
* Copyright (c) 2000 Ericsson Radio Systems AB.
*
* Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2005 Macq Electronique SA.
*/
#include <linux/config.h>
@@ -46,7 +49,8 @@
#include <asm/io.h>
#include <asm/pgtable.h>
-#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+ defined(CONFIG_M5272) || defined(CONFIG_M528x)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include "fec.h"
@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
#elif defined(CONFIG_M527x)
(MCF_MBAR + 0x1000),
(MCF_MBAR + 0x1800),
-#elif defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
(MCF_MBAR + 0x1000),
#else
&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@ static unsigned char fec_mac_default[] = {
#define FEC_FLASHMAC 0xffe04000
#elif defined(CONFIG_CANCam)
#define FEC_FLASHMAC 0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define FEC_FLASHMAC (0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC 0xffc0406b
#else
#define FEC_FLASHMAC 0
#endif
-unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
-
/* Forward declarations of some structures to support different PHYs
*/
@@ -158,7 +164,7 @@ typedef struct {
* size bits. Other FEC hardware does not, so we need to take that into
* account when setting it.
*/
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
@@ -196,7 +202,7 @@ struct fec_enet_private {
uint phy_id_done;
uint phy_status;
uint phy_speed;
- phy_info_t *phy;
+ phy_info_t const *phy;
struct work_struct phy_task;
uint sequence_done;
@@ -209,7 +215,6 @@ struct fec_enet_private {
int link;
int old_link;
int full_duplex;
- unsigned char mac_addr[ETH_ALEN];
};
static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@ typedef struct mii_list {
} mii_list_t;
#define NMII 20
-mii_list_t mii_cmds[NMII];
-mii_list_t *mii_free;
-mii_list_t *mii_head;
-mii_list_t *mii_tail;
+static mii_list_t mii_cmds[NMII];
+static mii_list_t *mii_free;
+static mii_list_t *mii_head;
+static mii_list_t *mii_tail;
static int mii_queue(struct net_device *dev, int request,
void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
}
}
#endif
- fec_restart(dev, 0);
+ fec_restart(dev, fep->full_duplex);
netif_wake_queue(dev);
}
@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
if (mii_reg & 0x0004)
- *s |= PHY_STAT_LINK;
+ status |= PHY_STAT_LINK;
if (mii_reg & 0x0010)
- *s |= PHY_STAT_FAULT;
+ status |= PHY_STAT_FAULT;
if (mii_reg & 0x0020)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
+
+ *s = status;
}
static void mii_parse_cr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+ status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
if (mii_reg & 0x1000)
- *s |= PHY_CONF_ANE;
+ status |= PHY_CONF_ANE;
if (mii_reg & 0x4000)
- *s |= PHY_CONF_LOOP;
+ status |= PHY_CONF_LOOP;
+ *s = status;
}
static void mii_parse_anar(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_CONF_SPMASK);
+ status = *s & ~(PHY_CONF_SPMASK);
if (mii_reg & 0x0020)
- *s |= PHY_CONF_10HDX;
+ status |= PHY_CONF_10HDX;
if (mii_reg & 0x0040)
- *s |= PHY_CONF_10FDX;
+ status |= PHY_CONF_10FDX;
if (mii_reg & 0x0080)
- *s |= PHY_CONF_100HDX;
+ status |= PHY_CONF_100HDX;
if (mii_reg & 0x00100)
- *s |= PHY_CONF_100FDX;
+ status |= PHY_CONF_100FDX;
+ *s = status;
}
/* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK);
-
+ status = *s & ~(PHY_STAT_SPMASK);
if (mii_reg & 0x0800) {
if (mii_reg & 0x1000)
- *s |= PHY_STAT_100FDX;
+ status |= PHY_STAT_100FDX;
else
- *s |= PHY_STAT_100HDX;
+ status |= PHY_STAT_100HDX;
} else {
if (mii_reg & 0x1000)
- *s |= PHY_STAT_10FDX;
+ status |= PHY_STAT_10FDX;
else
- *s |= PHY_STAT_10HDX;
+ status |= PHY_STAT_10HDX;
}
+ *s = status;
}
-static phy_info_t phy_info_lxt970 = {
- 0x07810000,
- "LXT970",
-
- (const phy_cmd_t []) { /* config */
+static phy_cmd_t const phy_cmd_lxt970_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
/* read SR and ISR to acknowledge */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
/* find out the current status */
{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_lxt970 = {
+ .id = 0x07810000,
+ .name = "LXT970",
+ .config = phy_cmd_lxt970_config,
+ .startup = phy_cmd_lxt970_startup,
+ .ack_int = phy_cmd_lxt970_ack_int,
+ .shutdown = phy_cmd_lxt970_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
if (mii_reg & 0x0400) {
fep->link = 1;
- *s |= PHY_STAT_LINK;
+ status |= PHY_STAT_LINK;
} else {
fep->link = 0;
}
if (mii_reg & 0x0080)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
if (mii_reg & 0x4000) {
if (mii_reg & 0x0200)
- *s |= PHY_STAT_100FDX;
+ status |= PHY_STAT_100FDX;
else
- *s |= PHY_STAT_100HDX;
+ status |= PHY_STAT_100HDX;
} else {
if (mii_reg & 0x0200)
- *s |= PHY_STAT_10FDX;
+ status |= PHY_STAT_10FDX;
else
- *s |= PHY_STAT_10HDX;
+ status |= PHY_STAT_10HDX;
}
if (mii_reg & 0x0008)
- *s |= PHY_STAT_FAULT;
-}
+ status |= PHY_STAT_FAULT;
-static phy_info_t phy_info_lxt971 = {
- 0x0001378e,
- "LXT971",
+ *s = status;
+}
- (const phy_cmd_t []) { /* config */
- /* limit to 10MBit because my protorype board
+static phy_cmd_t const phy_cmd_lxt971_config[] = {
+ /* limit to 10MBit because my prototype board
* doesn't work with 100. */
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt971_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
* read here to get a valid value in ack_int */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
+ /* acknowledge the int before reading status ! */
+ { mk_mii_read(MII_LXT971_ISR), NULL },
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
- /* we only need to read ISR to acknowledge */
- { mk_mii_read(MII_LXT971_ISR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_lxt971 = {
+ .id = 0x0001378e,
+ .name = "LXT971",
+ .config = phy_cmd_lxt971_config,
+ .startup = phy_cmd_lxt971_startup,
+ .ack_int = phy_cmd_lxt971_ack_int,
+ .shutdown = phy_cmd_lxt971_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK);
+ status = *s & ~(PHY_STAT_SPMASK);
switch((mii_reg >> 2) & 7) {
- case 1: *s |= PHY_STAT_10HDX; break;
- case 2: *s |= PHY_STAT_100HDX; break;
- case 5: *s |= PHY_STAT_10FDX; break;
- case 6: *s |= PHY_STAT_100FDX; break;
- }
+ case 1: status |= PHY_STAT_10HDX; break;
+ case 2: status |= PHY_STAT_100HDX; break;
+ case 5: status |= PHY_STAT_10FDX; break;
+ case 6: status |= PHY_STAT_100FDX; break;
}
-static phy_info_t phy_info_qs6612 = {
- 0x00181440,
- "QS6612",
-
- (const phy_cmd_t []) { /* config */
+ *s = status;
+}
+
+static phy_cmd_t const phy_cmd_qs6612_config[] = {
/* The PHY powers up isolated on the RPX,
* so send a command to allow operation.
*/
@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_qs6612_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
/* we need to read ISR, SR and ANER to acknowledge */
{ mk_mii_read(MII_QS6612_ISR), NULL },
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
/* read pcr to get info */
{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_qs6612 = {
+ .id = 0x00181440,
+ .name = "QS6612",
+ .config = phy_cmd_qs6612_config,
+ .startup = phy_cmd_qs6612_startup,
+ .ack_int = phy_cmd_qs6612_ack_int,
+ .shutdown = phy_cmd_qs6612_shutdown
};
/* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
+ uint status;
- *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+ status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
if (mii_reg & 0x0080)
- *s |= PHY_STAT_ANC;
+ status |= PHY_STAT_ANC;
if (mii_reg & 0x0400)
- *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
+ status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
else
- *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+ status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+
+ *s = status;
}
-static phy_info_t phy_info_am79c874 = {
- 0x00022561,
- "AM79C874",
-
- (const phy_cmd_t []) { /* config */
- /* limit to 10MBit because my protorype board
- * doesn't work with 100. */
+static phy_cmd_t const phy_cmd_am79c874_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup - enable interrupts */
+ };
+static phy_cmd_t const phy_cmd_am79c874_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
/* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_AM79C874_ICSR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ };
+static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_am79c874 = {
+ .id = 0x00022561,
+ .name = "AM79C874",
+ .config = phy_cmd_am79c874_config,
+ .startup = phy_cmd_am79c874_startup,
+ .ack_int = phy_cmd_am79c874_ack_int,
+ .shutdown = phy_cmd_am79c874_shutdown
};
+
/* ------------------------------------------------------------------------- */
/* Kendin KS8721BL phy */
@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
#define MII_KS8721BL_ICSR 22
#define MII_KS8721BL_PHYCR 31
-static phy_info_t phy_info_ks8721bl = {
- 0x00022161,
- "KS8721BL",
-
- (const phy_cmd_t []) { /* config */
+static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* startup */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_startup[] = { /* enable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* ack_int */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
/* find out the current status */
{ mk_mii_read(MII_REG_SR), mii_parse_sr },
/* we only need to read ISR to acknowledge */
{ mk_mii_read(MII_KS8721BL_ICSR), NULL },
{ mk_mii_end, }
- },
- (const phy_cmd_t []) { /* shutdown */
+ };
+static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
{ mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
{ mk_mii_end, }
- },
+ };
+static phy_info_t const phy_info_ks8721bl = {
+ .id = 0x00022161,
+ .name = "KS8721BL",
+ .config = phy_cmd_ks8721bl_config,
+ .startup = phy_cmd_ks8721bl_startup,
+ .ack_int = phy_cmd_ks8721bl_ack_int,
+ .shutdown = phy_cmd_ks8721bl_shutdown
};
/* ------------------------------------------------------------------------- */
-static phy_info_t *phy_info[] = {
+static phy_info_t const * const phy_info[] = {
&phy_info_lxt970,
&phy_info_lxt971,
&phy_info_qs6612,
@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
static void __inline__ fec_request_intrs(struct net_device *dev)
{
volatile unsigned long *icrp;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ } *idp, id[] = {
+ { "fec(RX)", 86, fec_enet_interrupt },
+ { "fec(TX)", 87, fec_enet_interrupt },
+ { "fec(OTHER)", 88, fec_enet_interrupt },
+ { "fec(MII)", 66, mii_link_interrupt },
+ { NULL },
+ };
/* Setup interrupt handlers. */
- if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0)
- printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n");
- if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0)
- printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n");
- if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
- printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
- if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
- printk("FEC: Could not allocate MII IRQ(66)!\n");
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
+ printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
+ }
/* Unmask interrupt at ColdFire 5272 SIM */
icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp;
- unsigned char *iap, tmpaddr[6];
- int i;
+ unsigned char *iap, tmpaddr[ETH_ALEN];
fecp = fep->hwp;
- if (fec_flashmac) {
+ if (FEC_FLASHMAC) {
/*
* Get MAC address from FLASH.
* If it is all 1's or 0's, use the default.
*/
- iap = fec_flashmac;
+ iap = (unsigned char *)FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default;
@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0];
}
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
/* Adjust MAC if using default MAC address */
- if (iap == fec_mac_default) {
- dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
- iap[ETH_ALEN-1] + fep->index;
- }
+ if (iap == fec_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
}
static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
/* ------------------------------------------------------------------------- */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/*
- * Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups.
+ * Code specific to Coldfire 5230/5231/5232/5234/5235,
+ * the 5270/5271/5274/5275 and 5280/5282 setups.
*/
static void __inline__ fec_request_intrs(struct net_device *dev)
{
struct fec_enet_private *fep;
int b;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ } *idp, id[] = {
+ { "fec(TXF)", 23 },
+ { "fec(TXB)", 24 },
+ { "fec(TXFIFO)", 25 },
+ { "fec(TXCR)", 26 },
+ { "fec(RXF)", 27 },
+ { "fec(RXB)", 28 },
+ { "fec(MII)", 29 },
+ { "fec(LC)", 30 },
+ { "fec(HBERR)", 31 },
+ { "fec(GRA)", 32 },
+ { "fec(EBERR)", 33 },
+ { "fec(BABT)", 34 },
+ { "fec(BABR)", 35 },
+ { NULL },
+ };
fep = netdev_priv(dev);
b = (fep->index) ? 128 : 64;
/* Setup interrupt handlers. */
- if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b);
- if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b);
- if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
- if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
- printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
-
- if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
- printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
- if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
- printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
-
- if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
- printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
- if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
- printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
- if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
- printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
- if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
- printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
- if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
- printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
- if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
- printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
- if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
- printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
+ printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+ }
/* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
{
@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
#if defined(CONFIG_M528x)
/* Set up gpio outputs for MII lines */
{
- volatile unsigned short *gpio_paspar;
+ volatile u16 *gpio_paspar;
+ volatile u8 *gpio_pehlpar;
- gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR +
- 0x100056);
- *gpio_paspar = 0x0f00;
+ gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
+ gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+ *gpio_paspar |= 0x0f00;
+ *gpio_pehlpar = 0xc0;
}
#endif
}
@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
volatile fec_t *fecp;
- unsigned char *iap, tmpaddr[6];
- int i;
+ unsigned char *iap, tmpaddr[ETH_ALEN];
fecp = fep->hwp;
- if (fec_flashmac) {
+ if (FEC_FLASHMAC) {
/*
* Get MAC address from FLASH.
* If it is all 1's or 0's, use the default.
*/
- iap = fec_flashmac;
+ iap = FEC_FLASHMAC;
if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
(iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
iap = fec_mac_default;
@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
iap = &tmpaddr[0];
}
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
/* Adjust MAC if using default MAC address */
- if (iap == fec_mac_default) {
- dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
- iap[ETH_ALEN-1] + fep->index;
- }
+ if (iap == fec_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
}
static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
#else
/*
- * Code sepcific to the MPC860T setup.
+ * Code specific to the MPC860T setup.
*/
static void __inline__ fec_request_intrs(struct net_device *dev)
{
@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
static void __inline__ fec_get_mac(struct net_device *dev)
{
- struct fec_enet_private *fep = netdev_priv(dev);
- unsigned char *iap, tmpaddr[6];
bd_t *bd;
- int i;
- iap = bd->bi_enetaddr;
bd = (bd_t *)__res;
+ memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
#ifdef CONFIG_RPXCLASSIC
/* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
* the address bits above something that would have (up to
* now) been allocated.
*/
- for (i=0; i<6; i++)
- tmpaddr[i] = *iap++;
- tmpaddr[3] |= 0x80;
- iap = tmpaddr;
+ dev->dev_adrd[3] |= 0x80;
#endif
-
- for (i=0; i<6; i++)
- dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
}
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
static void mii_display_config(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
- volatile uint *s = &(fep->phy_status);
+ uint status = fep->phy_status;
/*
** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
fep->mii_phy_task_queued = 0;
printk("%s: config: auto-negotiation ", dev->name);
- if (*s & PHY_CONF_ANE)
+ if (status & PHY_CONF_ANE)
printk("on");
else
printk("off");
- if (*s & PHY_CONF_100FDX)
+ if (status & PHY_CONF_100FDX)
printk(", 100FDX");
- if (*s & PHY_CONF_100HDX)
+ if (status & PHY_CONF_100HDX)
printk(", 100HDX");
- if (*s & PHY_CONF_10FDX)
+ if (status & PHY_CONF_10FDX)
printk(", 10FDX");
- if (*s & PHY_CONF_10HDX)
+ if (status & PHY_CONF_10HDX)
printk(", 10HDX");
- if (!(*s & PHY_CONF_SPMASK))
+ if (!(status & PHY_CONF_SPMASK))
printk(", No speed/duplex selected?");
- if (*s & PHY_CONF_LOOP)
+ if (status & PHY_CONF_LOOP)
printk(", loopback enabled");
printk(".\n");
@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task);
}
-/* mii_queue_config is called in user context from fec_enet_open */
+/* mii_queue_config is called in interrupt context from fec_enet_mii */
static void mii_queue_config(uint mii_reg, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
schedule_work(&fep->phy_task);
}
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
- { mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
- { mk_mii_end, } };
-
-
+phy_cmd_t const phy_cmd_relink[] = {
+ { mk_mii_read(MII_REG_CR), mii_queue_relink },
+ { mk_mii_end, }
+ };
+phy_cmd_t const phy_cmd_config[] = {
+ { mk_mii_read(MII_REG_CR), mii_queue_config },
+ { mk_mii_end, }
+ };
/* Read remainder of PHY ID.
*/
@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
static void
fec_set_mac_address(struct net_device *dev)
{
- struct fec_enet_private *fep;
volatile fec_t *fecp;
- fep = netdev_priv(dev);
- fecp = fep->hwp;
+ fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
/* Set station address. */
- fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
- (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
- fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
- (fep->mac_addr[4] << 24);
+ fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+ (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
+ fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
+ (dev->dev_addr[4] << 24);
}
@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
udelay(10);
/* Clear and enable interrupts */
- fecp->fec_ievent = 0xffc0;
+ fecp->fec_ievent = 0xffc00000;
fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
/* setup MII interface */
fec_set_mii(dev, fep);
- printk("%s: FEC ENET Version 0.2, ", dev->name);
- for (i=0; i<5; i++)
- printk("%02x:", dev->dev_addr[i]);
- printk("%02x\n", dev->dev_addr[5]);
-
/* Queue up command to detect the PHY and initialize the
* remainder of the interface.
*/
@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
/* Clear any outstanding interrupt.
*/
- fecp->fec_ievent = 0xffc0;
+ fecp->fec_ievent = 0xffc00000;
fec_enable_phy_intr();
/* Set station address.
*/
- fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
- (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
- fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
- (fep->mac_addr[4] << 24);
-
- for (i=0; i<ETH_ALEN; i++)
- dev->dev_addr[i] = fep->mac_addr[i];
+ fec_set_mac_address(dev);
/* Reset all multicast.
*/
@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */
- while(!(fecp->fec_ievent & 0x10000000));
+ while(!(fecp->fec_ievent & FEC_ENET_GRA));
/* Whack a reset. We should wait for this.
*/
@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
static int __init fec_enet_module_init(void)
{
struct net_device *dev;
- int i, err;
+ int i, j, err;
+
+ printk("FEC ENET Version 0.2\n");
for (i = 0; (i < FEC_MAX_PORTS); i++) {
dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
free_netdev(dev);
return -EIO;
}
+
+ printk("%s: ethernet ", dev->name);
+ for (j = 0; (j < 5); j++)
+ printk("%02x:", dev->dev_addr[j]);
+ printk("%02x\n", dev->dev_addr[5]);
}
return 0;
}
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index c6e4f979ff5d..045761b8a600 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -1,8 +1,9 @@
/****************************************************************************/
/*
- * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5270,
- 5271, 5272, 5274, 5275, 5280 and 5282.
+ * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5230,
+ * 5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
+ * 5280 and 5282.
*
* (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
* (C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
#define FEC_H
/****************************************************************************/
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 64f0f697c958..22aec6ed80f5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -85,6 +85,18 @@
* 0.33: 16 May 2005: Support for MCP51 added.
* 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
* 0.35: 26 Jun 2005: Support for MCP55 added.
+ * 0.36: 28 Jun 2005: Add jumbo frame support.
+ * 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
+ * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
+ * per-packet flags.
+ * 0.39: 18 Jul 2005: Add 64bit descriptor support.
+ * 0.40: 19 Jul 2005: Add support for mac address change.
+ * 0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+ * of nv_remove
+ * 0.42: 06 Aug 2005: Fix lack of link speed initialization
+ * in the second (and later) nv_open call
+ * 0.43: 10 Aug 2005: Add support for tx checksum.
+ * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -96,7 +108,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.35"
+#define FORCEDETH_VERSION "0.44"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -131,11 +143,11 @@
* Hardware access:
*/
-#define DEV_NEED_LASTPACKET1 0x0001 /* set LASTPACKET1 in tx flags */
-#define DEV_IRQMASK_1 0x0002 /* use NVREG_IRQMASK_WANTED_1 for irq mask */
-#define DEV_IRQMASK_2 0x0004 /* use NVREG_IRQMASK_WANTED_2 for irq mask */
-#define DEV_NEED_TIMERIRQ 0x0008 /* set the timer irq flag in the irq mask */
-#define DEV_NEED_LINKTIMER 0x0010 /* poll link settings. Relies on the timer irq */
+#define DEV_NEED_TIMERIRQ 0x0001 /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
enum {
NvRegIrqStatus = 0x000,
@@ -146,13 +158,16 @@ enum {
#define NVREG_IRQ_RX 0x0002
#define NVREG_IRQ_RX_NOBUF 0x0004
#define NVREG_IRQ_TX_ERR 0x0008
-#define NVREG_IRQ_TX2 0x0010
+#define NVREG_IRQ_TX_OK 0x0010
#define NVREG_IRQ_TIMER 0x0020
#define NVREG_IRQ_LINK 0x0040
+#define NVREG_IRQ_TX_ERROR 0x0080
#define NVREG_IRQ_TX1 0x0100
-#define NVREG_IRQMASK_WANTED_1 0x005f
-#define NVREG_IRQMASK_WANTED_2 0x0147
-#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
+#define NVREG_IRQMASK_WANTED 0x00df
+
+#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
+ NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
+ NVREG_IRQ_TX1))
NvRegUnknownSetupReg6 = 0x008,
#define NVREG_UNKSETUP6_VAL 3
@@ -229,6 +244,9 @@ enum {
#define NVREG_TXRXCTL_IDLE 0x0008
#define NVREG_TXRXCTL_RESET 0x0010
#define NVREG_TXRXCTL_RXCHECK 0x0400
+#define NVREG_TXRXCTL_DESC_1 0
+#define NVREG_TXRXCTL_DESC_2 0x02100
+#define NVREG_TXRXCTL_DESC_3 0x02200
NvRegMIIStatus = 0x180,
#define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008
@@ -286,6 +304,18 @@ struct ring_desc {
u32 FlagLen;
};
+struct ring_desc_ex {
+ u32 PacketBufferHigh;
+ u32 PacketBufferLow;
+ u32 Reserved;
+ u32 FlagLen;
+};
+
+typedef union _ring_type {
+ struct ring_desc* orig;
+ struct ring_desc_ex* ex;
+} ring_type;
+
#define FLAG_MASK_V1 0xffff0000
#define FLAG_MASK_V2 0xffffc000
#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
@@ -293,7 +323,7 @@ struct ring_desc {
#define NV_TX_LASTPACKET (1<<16)
#define NV_TX_RETRYERROR (1<<19)
-#define NV_TX_LASTPACKET1 (1<<24)
+#define NV_TX_FORCED_INTERRUPT (1<<24)
#define NV_TX_DEFERRED (1<<26)
#define NV_TX_CARRIERLOST (1<<27)
#define NV_TX_LATECOLLISION (1<<28)
@@ -303,7 +333,7 @@ struct ring_desc {
#define NV_TX2_LASTPACKET (1<<29)
#define NV_TX2_RETRYERROR (1<<18)
-#define NV_TX2_LASTPACKET1 (1<<23)
+#define NV_TX2_FORCED_INTERRUPT (1<<30)
#define NV_TX2_DEFERRED (1<<25)
#define NV_TX2_CARRIERLOST (1<<26)
#define NV_TX2_LATECOLLISION (1<<27)
@@ -311,6 +341,10 @@ struct ring_desc {
/* error and valid are the same for both */
#define NV_TX2_ERROR (1<<30)
#define NV_TX2_VALID (1<<31)
+#define NV_TX2_TSO (1<<28)
+#define NV_TX2_TSO_SHIFT 14
+#define NV_TX2_CHECKSUM_L3 (1<<27)
+#define NV_TX2_CHECKSUM_L4 (1<<26)
#define NV_RX_DESCRIPTORVALID (1<<16)
#define NV_RX_MISSEDFRAME (1<<17)
@@ -379,9 +413,13 @@ struct ring_desc {
#define TX_LIMIT_START 62
/* rx/tx mac addr + type + vlan + align + slack*/
-#define RX_NIC_BUFSIZE (ETH_DATA_LEN + 64)
-/* even more slack */
-#define RX_ALLOC_BUFSIZE (ETH_DATA_LEN + 128)
+#define NV_RX_HEADERS (64)
+/* even more slack. */
+#define NV_RX_ALLOC_PAD (64)
+
+/* maximum mtu size */
+#define NV_PKTLIMIT_1 ETH_DATA_LEN /* hard limit not known */
+#define NV_PKTLIMIT_2 9100 /* Actual limit according to NVidia: 9202 */
#define OOM_REFILL (1+HZ/20)
#define POLL_WAIT (1+HZ/100)
@@ -389,13 +427,14 @@ struct ring_desc {
/*
* desc_ver values:
- * This field has two purposes:
- * - Newer nics uses a different ring layout. The layout is selected by
- * comparing np->desc_ver with DESC_VER_xy.
- * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ * The nic supports three different descriptor types:
+ * - DESC_VER_1: Original
+ * - DESC_VER_2: support for jumbo frames.
+ * - DESC_VER_3: 64-bit format.
*/
-#define DESC_VER_1 0x0
-#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_1 1
+#define DESC_VER_2 2
+#define DESC_VER_3 3
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
@@ -462,17 +501,19 @@ struct fe_priv {
u32 orig_mac[2];
u32 irqmask;
u32 desc_ver;
+ u32 txrxctl_bits;
void __iomem *base;
/* rx specific fields.
* Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
*/
- struct ring_desc *rx_ring;
+ ring_type rx_ring;
unsigned int cur_rx, refill_rx;
struct sk_buff *rx_skbuff[RX_RING];
dma_addr_t rx_dma[RX_RING];
unsigned int rx_buf_sz;
+ unsigned int pkt_limit;
struct timer_list oom_kick;
struct timer_list nic_poll;
@@ -484,7 +525,7 @@ struct fe_priv {
/*
* tx specific fields.
*/
- struct ring_desc *tx_ring;
+ ring_type tx_ring;
unsigned int next_tx, nic_tx;
struct sk_buff *tx_skbuff[TX_RING];
dma_addr_t tx_dma[TX_RING];
@@ -504,7 +545,7 @@ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
static inline u8 __iomem *get_hwbase(struct net_device *dev)
{
- return get_nvpriv(dev)->base;
+ return ((struct fe_priv *)netdev_priv(dev))->base;
}
static inline void pci_push(u8 __iomem *base)
@@ -519,6 +560,11 @@ static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
& ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
}
+static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
+{
+ return le32_to_cpu(prd->FlagLen) & LEN_MASK_V2;
+}
+
static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
int delay, int delaymax, const char *msg)
{
@@ -588,7 +634,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
static int phy_reset(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 miicontrol;
unsigned int tries = 0;
@@ -691,7 +737,7 @@ static int phy_init(struct net_device *dev)
static void nv_start_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
@@ -747,14 +793,14 @@ static void nv_stop_tx(struct net_device *dev)
static void nv_txrx_reset(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
- writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
udelay(NV_TXRX_RESET_DELAY);
- writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
}
@@ -766,7 +812,7 @@ static void nv_txrx_reset(struct net_device *dev)
*/
static struct net_device_stats *nv_get_stats(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
/* It seems that the nic always generates interrupts and doesn't
* accumulate errors internally. Thus the current values in np->stats
@@ -782,7 +828,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
*/
static int nv_alloc_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
unsigned int refill_rx = np->refill_rx;
int nr;
@@ -792,7 +838,7 @@ static int nv_alloc_rx(struct net_device *dev)
nr = refill_rx % RX_RING;
if (np->rx_skbuff[nr] == NULL) {
- skb = dev_alloc_skb(RX_ALLOC_BUFSIZE);
+ skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
if (!skb)
break;
@@ -803,9 +849,16 @@ static int nv_alloc_rx(struct net_device *dev)
}
np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len,
PCI_DMA_FROMDEVICE);
- np->rx_ring[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
- wmb();
- np->rx_ring[nr].FlagLen = cpu_to_le32(RX_NIC_BUFSIZE | NV_RX_AVAIL);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->rx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
+ wmb();
+ np->rx_ring.orig[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
+ } else {
+ np->rx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
+ np->rx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF;
+ wmb();
+ np->rx_ring.ex[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
+ }
dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet %d marked as Available\n",
dev->name, refill_rx);
refill_rx++;
@@ -819,7 +872,7 @@ static int nv_alloc_rx(struct net_device *dev)
static void nv_do_rx_refill(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
disable_irq(dev->irq);
if (nv_alloc_rx(dev)) {
@@ -831,34 +884,80 @@ static void nv_do_rx_refill(unsigned long data)
enable_irq(dev->irq);
}
-static int nv_init_ring(struct net_device *dev)
+static void nv_init_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int i;
- np->next_tx = np->nic_tx = 0;
- for (i = 0; i < TX_RING; i++)
- np->tx_ring[i].FlagLen = 0;
-
np->cur_rx = RX_RING;
np->refill_rx = 0;
for (i = 0; i < RX_RING; i++)
- np->rx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->rx_ring.orig[i].FlagLen = 0;
+ else
+ np->rx_ring.ex[i].FlagLen = 0;
+}
+
+static void nv_init_tx(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ int i;
+
+ np->next_tx = np->nic_tx = 0;
+ for (i = 0; i < TX_RING; i++) {
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[i].FlagLen = 0;
+ else
+ np->tx_ring.ex[i].FlagLen = 0;
+ np->tx_skbuff[i] = NULL;
+ }
+}
+
+static int nv_init_ring(struct net_device *dev)
+{
+ nv_init_tx(dev);
+ nv_init_rx(dev);
return nv_alloc_rx(dev);
}
+static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ struct sk_buff *skb = np->tx_skbuff[skbnr];
+ unsigned int j, entry, fragments;
+
+ dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
+ dev->name, skbnr, np->tx_skbuff[skbnr]);
+
+ entry = skbnr;
+ if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
+ for (j = fragments; j >= 1; j--) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
+ pci_unmap_page(np->pci_dev, np->tx_dma[entry],
+ frag->size,
+ PCI_DMA_TODEVICE);
+ entry = (entry - 1) % TX_RING;
+ }
+ }
+ pci_unmap_single(np->pci_dev, np->tx_dma[entry],
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skb);
+ np->tx_skbuff[skbnr] = NULL;
+}
+
static void nv_drain_tx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
- int i;
+ struct fe_priv *np = netdev_priv(dev);
+ unsigned int i;
+
for (i = 0; i < TX_RING; i++) {
- np->tx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->tx_ring.orig[i].FlagLen = 0;
+ else
+ np->tx_ring.ex[i].FlagLen = 0;
if (np->tx_skbuff[i]) {
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
- np->tx_skbuff[i]->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb(np->tx_skbuff[i]);
- np->tx_skbuff[i] = NULL;
+ nv_release_txskb(dev, i);
np->stats.tx_dropped++;
}
}
@@ -866,10 +965,13 @@ static void nv_drain_tx(struct net_device *dev)
static void nv_drain_rx(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
int i;
for (i = 0; i < RX_RING; i++) {
- np->rx_ring[i].FlagLen = 0;
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ np->rx_ring.orig[i].FlagLen = 0;
+ else
+ np->rx_ring.ex[i].FlagLen = 0;
wmb();
if (np->rx_skbuff[i]) {
pci_unmap_single(np->pci_dev, np->rx_dma[i],
@@ -893,20 +995,69 @@ static void drain_ring(struct net_device *dev)
*/
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
- int nr = np->next_tx % TX_RING;
+ struct fe_priv *np = netdev_priv(dev);
+ u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
+ unsigned int fragments = skb_shinfo(skb)->nr_frags;
+ unsigned int nr = (np->next_tx + fragments) % TX_RING;
+ unsigned int i;
+
+ spin_lock_irq(&np->lock);
+
+ if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
+ spin_unlock_irq(&np->lock);
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
np->tx_skbuff[nr] = skb;
- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
- PCI_DMA_TODEVICE);
+
+ if (fragments) {
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
+ /* setup descriptors in reverse order */
+ for (i = fragments; i >= 1; i--) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+ np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ } else {
+ np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+ np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ }
+
+ nr = (nr - 1) % TX_RING;
- np->tx_ring[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ if (np->desc_ver == DESC_VER_1)
+ tx_flags_extra &= ~NV_TX_LASTPACKET;
+ else
+ tx_flags_extra &= ~NV_TX2_LASTPACKET;
+ }
+ }
- spin_lock_irq(&np->lock);
- wmb();
- np->tx_ring[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
- dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
- dev->name, np->next_tx);
+#ifdef NETIF_F_TSO
+ if (skb_shinfo(skb)->tso_size)
+ tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
+ else
+#endif
+ tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
+ PCI_DMA_TODEVICE);
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ } else {
+ np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+ np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ }
+
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
+ dev->name, np->next_tx, tx_flags_extra);
{
int j;
for (j=0; j<64; j++) {
@@ -917,15 +1068,13 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dprintk("\n");
}
- np->next_tx++;
+ np->next_tx += 1 + fragments;
dev->trans_start = jiffies;
- if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
- netif_stop_queue(dev);
spin_unlock_irq(&np->lock);
- writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
pci_push(get_hwbase(dev));
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -935,49 +1084,56 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static void nv_tx_done(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 Flags;
- int i;
+ unsigned int i;
+ struct sk_buff *skb;
while (np->nic_tx != np->next_tx) {
i = np->nic_tx % TX_RING;
- Flags = le32_to_cpu(np->tx_ring[i].FlagLen);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
+ else
+ Flags = le32_to_cpu(np->tx_ring.ex[i].FlagLen);
dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, Flags 0x%x.\n",
dev->name, np->nic_tx, Flags);
if (Flags & NV_TX_VALID)
break;
if (np->desc_ver == DESC_VER_1) {
- if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
- NV_TX_UNDERFLOW|NV_TX_ERROR)) {
- if (Flags & NV_TX_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
+ if (Flags & NV_TX_LASTPACKET) {
+ skb = np->tx_skbuff[i];
+ if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+ NV_TX_UNDERFLOW|NV_TX_ERROR)) {
+ if (Flags & NV_TX_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += skb->len;
+ }
+ nv_release_txskb(dev, i);
}
} else {
- if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
- NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
- if (Flags & NV_TX2_UNDERFLOW)
- np->stats.tx_fifo_errors++;
- if (Flags & NV_TX2_CARRIERLOST)
- np->stats.tx_carrier_errors++;
- np->stats.tx_errors++;
- } else {
- np->stats.tx_packets++;
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
+ if (Flags & NV_TX2_LASTPACKET) {
+ skb = np->tx_skbuff[i];
+ if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+ NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
+ if (Flags & NV_TX2_UNDERFLOW)
+ np->stats.tx_fifo_errors++;
+ if (Flags & NV_TX2_CARRIERLOST)
+ np->stats.tx_carrier_errors++;
+ np->stats.tx_errors++;
+ } else {
+ np->stats.tx_packets++;
+ np->stats.tx_bytes += skb->len;
+ }
+ nv_release_txskb(dev, i);
}
}
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
- np->tx_skbuff[i]->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(np->tx_skbuff[i]);
- np->tx_skbuff[i] = NULL;
np->nic_tx++;
}
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -990,12 +1146,59 @@ static void nv_tx_done(struct net_device *dev)
*/
static void nv_tx_timeout(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
- dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name,
+ printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
+ {
+ int i;
+
+ printk(KERN_INFO "%s: Ring at %lx: next %d nic %d\n",
+ dev->name, (unsigned long)np->ring_addr,
+ np->next_tx, np->nic_tx);
+ printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
+ for (i=0;i<0x400;i+= 32) {
+ printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ i,
+ readl(base + i + 0), readl(base + i + 4),
+ readl(base + i + 8), readl(base + i + 12),
+ readl(base + i + 16), readl(base + i + 20),
+ readl(base + i + 24), readl(base + i + 28));
+ }
+ printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+ for (i=0;i<TX_RING;i+= 4) {
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+1].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+2].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+2].FlagLen),
+ le32_to_cpu(np->tx_ring.orig[i+3].PacketBuffer),
+ le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
+ } else {
+ printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+1].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+2].FlagLen),
+ le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferHigh),
+ le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferLow),
+ le32_to_cpu(np->tx_ring.ex[i+3].FlagLen));
+ }
+ }
+ }
+
spin_lock_irq(&np->lock);
/* 1) stop tx engine */
@@ -1009,7 +1212,10 @@ static void nv_tx_timeout(struct net_device *dev)
printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name);
nv_drain_tx(dev);
np->next_tx = np->nic_tx = 0;
- writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
netif_wake_queue(dev);
}
@@ -1073,7 +1279,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
static void nv_rx_process(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u32 Flags;
for (;;) {
@@ -1084,8 +1290,13 @@ static void nv_rx_process(struct net_device *dev)
break; /* we scanned the whole ring - do not continue */
i = np->cur_rx % RX_RING;
- Flags = le32_to_cpu(np->rx_ring[i].FlagLen);
- len = nv_descr_getlength(&np->rx_ring[i], np->desc_ver);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
+ len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
+ } else {
+ Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen);
+ len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
+ }
dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
dev->name, np->cur_rx, Flags);
@@ -1207,15 +1418,133 @@ next_pkt:
}
}
+static void set_bufsize(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+
+ if (dev->mtu <= ETH_DATA_LEN)
+ np->rx_buf_sz = ETH_DATA_LEN + NV_RX_HEADERS;
+ else
+ np->rx_buf_sz = dev->mtu + NV_RX_HEADERS;
+}
+
/*
* nv_change_mtu: dev->change_mtu function
* Called with dev_base_lock held for read.
*/
static int nv_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu > ETH_DATA_LEN)
+ struct fe_priv *np = netdev_priv(dev);
+ int old_mtu;
+
+ if (new_mtu < 64 || new_mtu > np->pkt_limit)
return -EINVAL;
+
+ old_mtu = dev->mtu;
dev->mtu = new_mtu;
+
+ /* return early if the buffer sizes will not change */
+ if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN)
+ return 0;
+ if (old_mtu == new_mtu)
+ return 0;
+
+ /* synchronized against open : rtnl_lock() held by caller */
+ if (netif_running(dev)) {
+ u8 __iomem *base = get_hwbase(dev);
+ /*
+ * It seems that the nic preloads valid ring entries into an
+ * internal buffer. The procedure for flushing everything is
+ * guessed, there is probably a simpler approach.
+ * Changing the MTU is a rare event, it shouldn't matter.
+ */
+ disable_irq(dev->irq);
+ spin_lock_bh(&dev->xmit_lock);
+ spin_lock(&np->lock);
+ /* stop engines */
+ nv_stop_rx(dev);
+ nv_stop_tx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+ nv_drain_rx(dev);
+ nv_drain_tx(dev);
+ /* reinit driver view of the rx queue */
+ nv_init_rx(dev);
+ nv_init_tx(dev);
+ /* alloc new rx buffers */
+ set_bufsize(dev);
+ if (nv_alloc_rx(dev)) {
+ if (!np->in_shutdown)
+ mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+ }
+ /* reinit nic view of the rx queue */
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+ writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+ writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+ base + NvRegRingSizes);
+ pci_push(base);
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ pci_push(base);
+
+ /* restart rx engine */
+ nv_start_rx(dev);
+ nv_start_tx(dev);
+ spin_unlock(&np->lock);
+ spin_unlock_bh(&dev->xmit_lock);
+ enable_irq(dev->irq);
+ }
+ return 0;
+}
+
+static void nv_copy_mac_to_hw(struct net_device *dev)
+{
+ u8 __iomem *base = get_hwbase(dev);
+ u32 mac[2];
+
+ mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
+ (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+ mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+
+ writel(mac[0], base + NvRegMacAddrA);
+ writel(mac[1], base + NvRegMacAddrB);
+}
+
+/*
+ * nv_set_mac_address: dev->set_mac_address function
+ * Called with rtnl_lock() held.
+ */
+static int nv_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ struct sockaddr *macaddr = (struct sockaddr*)addr;
+
+ if(!is_valid_ether_addr(macaddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ /* synchronized against open : rtnl_lock() held by caller */
+ memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
+
+ if (netif_running(dev)) {
+ spin_lock_bh(&dev->xmit_lock);
+ spin_lock_irq(&np->lock);
+
+ /* stop rx engine */
+ nv_stop_rx(dev);
+
+ /* set mac address */
+ nv_copy_mac_to_hw(dev);
+
+ /* restart rx engine */
+ nv_start_rx(dev);
+ spin_unlock_irq(&np->lock);
+ spin_unlock_bh(&dev->xmit_lock);
+ } else {
+ nv_copy_mac_to_hw(dev);
+ }
return 0;
}
@@ -1225,7 +1554,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
*/
static void nv_set_multicast(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 addr[2];
u32 mask[2];
@@ -1285,7 +1614,7 @@ static void nv_set_multicast(struct net_device *dev)
static int nv_update_linkspeed(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
int adv, lpa;
int newls = np->linkspeed;
@@ -1455,7 +1784,7 @@ static void nv_link_irq(struct net_device *dev)
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 events;
int i;
@@ -1470,7 +1799,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask))
break;
- if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX2|NVREG_IRQ_TX_ERR)) {
+ if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
spin_lock(&np->lock);
nv_tx_done(dev);
spin_unlock(&np->lock);
@@ -1527,7 +1856,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
static void nv_do_nic_poll(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
disable_irq(dev->irq);
@@ -1551,7 +1880,7 @@ static void nv_poll_controller(struct net_device *dev)
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
strcpy(info->driver, "forcedeth");
strcpy(info->version, FORCEDETH_VERSION);
strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -1559,7 +1888,7 @@ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
wolinfo->supported = WAKE_MAGIC;
spin_lock_irq(&np->lock);
@@ -1570,7 +1899,7 @@ static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
spin_lock_irq(&np->lock);
@@ -1761,6 +2090,50 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return 0;
}
+#define FORCEDETH_REGS_VER 1
+#define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */
+
+static int nv_get_regs_len(struct net_device *dev)
+{
+ return FORCEDETH_REGS_SIZE;
+}
+
+static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ u32 *rbuf = buf;
+ int i;
+
+ regs->version = FORCEDETH_REGS_VER;
+ spin_lock_irq(&np->lock);
+ for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+ rbuf[i] = readl(base + i*sizeof(u32));
+ spin_unlock_irq(&np->lock);
+}
+
+static int nv_nway_reset(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ int ret;
+
+ spin_lock_irq(&np->lock);
+ if (np->autoneg) {
+ int bmcr;
+
+ bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+ spin_unlock_irq(&np->lock);
+
+ return ret;
+}
+
static struct ethtool_ops ops = {
.get_drvinfo = nv_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -1768,11 +2141,15 @@ static struct ethtool_ops ops = {
.set_wol = nv_set_wol,
.get_settings = nv_get_settings,
.set_settings = nv_set_settings,
+ .get_regs_len = nv_get_regs_len,
+ .get_regs = nv_get_regs,
+ .nway_reset = nv_nway_reset,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int nv_open(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
int ret, oom, i;
@@ -1792,6 +2169,7 @@ static int nv_open(struct net_device *dev)
writel(0, base + NvRegAdapterControl);
/* 2) initialize descriptor rings */
+ set_bufsize(dev);
oom = nv_init_ring(dev);
writel(0, base + NvRegLinkSpeed);
@@ -1802,29 +2180,23 @@ static int nv_open(struct net_device *dev)
np->in_shutdown = 0;
/* 3) set mac address */
- {
- u32 mac[2];
-
- mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
- (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
- mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
-
- writel(mac[0], base + NvRegMacAddrA);
- writel(mac[1], base + NvRegMacAddrB);
- }
+ nv_copy_mac_to_hw(dev);
/* 4) give hw rings */
writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);
- writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+ else
+ writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
base + NvRegRingSizes);
/* 5) continue setup */
writel(np->linkspeed, base + NvRegLinkSpeed);
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
- writel(np->desc_ver, base + NvRegTxRxControl);
+ writel(np->txrxctl_bits, base + NvRegTxRxControl);
pci_push(base);
- writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
+ writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
@@ -1837,7 +2209,7 @@ static int nv_open(struct net_device *dev)
writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
- writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
get_random_bytes(&i, sizeof(i));
@@ -1888,6 +2260,9 @@ static int nv_open(struct net_device *dev)
writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
}
+ /* set linkspeed to invalid value, thus force nv_update_linkspeed
+ * to init hw */
+ np->linkspeed = 0;
ret = nv_update_linkspeed(dev);
nv_start_rx(dev);
nv_start_tx(dev);
@@ -1910,7 +2285,7 @@ out_drain:
static int nv_close(struct net_device *dev)
{
- struct fe_priv *np = get_nvpriv(dev);
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base;
spin_lock_irq(&np->lock);
@@ -1942,6 +2317,12 @@ static int nv_close(struct net_device *dev)
if (np->wolenabled)
nv_start_rx(dev);
+ /* special op: write back the misordered MAC address - otherwise
+ * the next nv_probe would see a wrong address.
+ */
+ writel(np->orig_mac[0], base + NvRegMacAddrA);
+ writel(np->orig_mac[1], base + NvRegMacAddrB);
+
/* FIXME: power down nic */
return 0;
@@ -1960,7 +2341,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (!dev)
goto out;
- np = get_nvpriv(dev);
+ np = netdev_priv(dev);
np->pci_dev = pci_dev;
spin_lock_init(&np->lock);
SET_MODULE_OWNER(dev);
@@ -2006,32 +2387,68 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
}
/* handle different descriptor versions */
- if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13)
- np->desc_ver = DESC_VER_1;
- else
+ if (id->driver_data & DEV_HAS_HIGH_DMA) {
+ /* packet format 3: supports 40-bit addressing */
+ np->desc_ver = DESC_VER_3;
+ if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
+ pci_name(pci_dev));
+ } else {
+ dev->features |= NETIF_F_HIGHDMA;
+ }
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
+ } else if (id->driver_data & DEV_HAS_LARGEDESC) {
+ /* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
+ } else {
+ /* original packet format */
+ np->desc_ver = DESC_VER_1;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
+ }
+
+ np->pkt_limit = NV_PKTLIMIT_1;
+ if (id->driver_data & DEV_HAS_LARGEDESC)
+ np->pkt_limit = NV_PKTLIMIT_2;
+
+ if (id->driver_data & DEV_HAS_CHECKSUM) {
+ np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+#ifdef NETIF_F_TSO
+ dev->features |= NETIF_F_TSO;
+#endif
+ }
err = -ENOMEM;
np->base = ioremap(addr, NV_PCI_REGSZ);
if (!np->base)
goto out_relreg;
dev->base_addr = (unsigned long)np->base;
+
dev->irq = pci_dev->irq;
- np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
- &np->ring_addr);
- if (!np->rx_ring)
- goto out_unmap;
- np->tx_ring = &np->rx_ring[RX_RING];
+
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->rx_ring.orig = pci_alloc_consistent(pci_dev,
+ sizeof(struct ring_desc) * (RX_RING + TX_RING),
+ &np->ring_addr);
+ if (!np->rx_ring.orig)
+ goto out_unmap;
+ np->tx_ring.orig = &np->rx_ring.orig[RX_RING];
+ } else {
+ np->rx_ring.ex = pci_alloc_consistent(pci_dev,
+ sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+ &np->ring_addr);
+ if (!np->rx_ring.ex)
+ goto out_unmap;
+ np->tx_ring.ex = &np->rx_ring.ex[RX_RING];
+ }
dev->open = nv_open;
dev->stop = nv_close;
dev->hard_start_xmit = nv_start_xmit;
dev->get_stats = nv_get_stats;
dev->change_mtu = nv_change_mtu;
+ dev->set_mac_address = nv_set_mac_address;
dev->set_multicast_list = nv_set_multicast;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = nv_poll_controller;
@@ -2053,8 +2470,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->dev_addr)) {
+ if (!is_valid_ether_addr(dev->perm_addr)) {
/*
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
@@ -2079,18 +2497,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->wolenabled = 0;
if (np->desc_ver == DESC_VER_1) {
- np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
- if (id->driver_data & DEV_NEED_LASTPACKET1)
- np->tx_flags |= NV_TX_LASTPACKET1;
+ np->tx_flags = NV_TX_VALID;
} else {
- np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
- if (id->driver_data & DEV_NEED_LASTPACKET1)
- np->tx_flags |= NV_TX2_LASTPACKET1;
+ np->tx_flags = NV_TX2_VALID;
}
- if (id->driver_data & DEV_IRQMASK_1)
- np->irqmask = NVREG_IRQMASK_WANTED_1;
- if (id->driver_data & DEV_IRQMASK_2)
- np->irqmask = NVREG_IRQMASK_WANTED_2;
+ np->irqmask = NVREG_IRQMASK_WANTED;
if (id->driver_data & DEV_NEED_TIMERIRQ)
np->irqmask |= NVREG_IRQ_TIMER;
if (id->driver_data & DEV_NEED_LINKTIMER) {
@@ -2155,8 +2566,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
return 0;
out_freering:
- pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
- np->rx_ring, np->ring_addr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
+ np->rx_ring.orig, np->ring_addr);
+ else
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+ np->rx_ring.ex, np->ring_addr);
pci_set_drvdata(pci_dev, NULL);
out_unmap:
iounmap(get_hwbase(dev));
@@ -2173,19 +2588,15 @@ out:
static void __devexit nv_remove(struct pci_dev *pci_dev)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
- struct fe_priv *np = get_nvpriv(dev);
- u8 __iomem *base = get_hwbase(dev);
+ struct fe_priv *np = netdev_priv(dev);
unregister_netdev(dev);
- /* special op: write back the misordered MAC address - otherwise
- * the next nv_probe would see a wrong address.
- */
- writel(np->orig_mac[0], base + NvRegMacAddrA);
- writel(np->orig_mac[1], base + NvRegMacAddrB);
-
/* free all structures */
- pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring, np->ring_addr);
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr);
+ else
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr);
iounmap(get_hwbase(dev));
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
@@ -2195,109 +2606,64 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
static struct pci_device_id pci_tbl[] = {
{ /* nForce Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_1,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce2 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_5,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_6,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* nForce3 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_7,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
},
{ /* CK804 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_8,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* CK804 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_9,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_10,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP04 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_11,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_12,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
},
{ /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_13,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_14,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{ /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_15,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
},
{0,},
};
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
new file mode 100644
index 000000000000..6aaee67dd4b7
--- /dev/null
+++ b/drivers/net/fs_enet/Kconfig
@@ -0,0 +1,20 @@
+config FS_ENET
+ tristate "Freescale Ethernet Driver"
+ depends on NET_ETHERNET && (CPM1 || CPM2)
+ select MII
+
+config FS_ENET_HAS_SCC
+ bool "Chip has an SCC usable for ethernet"
+ depends on FS_ENET && (CPM1 || CPM2)
+ default y
+
+config FS_ENET_HAS_FCC
+ bool "Chip has an FCC usable for ethernet"
+ depends on FS_ENET && CPM2
+ default y
+
+config FS_ENET_HAS_FEC
+ bool "Chip has an FEC usable for ethernet"
+ depends on FS_ENET && CPM1
+ default y
+
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
new file mode 100644
index 000000000000..d6dd3f2fb43e
--- /dev/null
+++ b/drivers/net/fs_enet/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+
+obj-$(CONFIG_FS_ENET) += fs_enet.o
+
+obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
+obj-$(CONFIG_8260) += mac-fcc.o
+
+fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
new file mode 100644
index 000000000000..44fac7373289
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -0,0 +1,1226 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
+MODULE_DESCRIPTION("Freescale Ethernet Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+MODULE_PARM(fs_enet_debug, "i");
+MODULE_PARM_DESC(fs_enet_debug,
+ "Freescale bitmapped debugging message enable value");
+
+int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
+
+static void fs_set_multicast_list(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ (*fep->ops->set_multicast_list)(dev);
+}
+
+/* NAPI receive function */
+static int fs_enet_rx_napi(struct net_device *dev, int *budget)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ cbd_t *bdp;
+ struct sk_buff *skb, *skbn, *skbt;
+ int received = 0;
+ u16 pkt_len, sc;
+ int curidx;
+ int rx_work_limit = 0; /* pacify gcc */
+
+ rx_work_limit = min(dev->quota, *budget);
+
+ if (!netif_running(dev))
+ return 0;
+
+ /*
+ * First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = fep->cur_rx;
+
+ /* clear RX status bits for napi*/
+ (*fep->ops->napi_clear_rx_event)(dev);
+
+ while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+ curidx = bdp - fep->rx_bd_base;
+
+ /*
+ * Since we have allocated space to hold a complete frame,
+ * the last indicator should be set.
+ */
+ if ((sc & BD_ENET_RX_LAST) == 0)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s rcv is not +last\n",
+ dev->name);
+
+ /*
+ * Check for errors.
+ */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+ BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+ fep->stats.rx_errors++;
+ /* Frame too long or too short. */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ fep->stats.rx_length_errors++;
+ /* Frame alignment */
+ if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+ fep->stats.rx_frame_errors++;
+ /* CRC Error */
+ if (sc & BD_ENET_RX_CR)
+ fep->stats.rx_crc_errors++;
+ /* FIFO overrun */
+ if (sc & BD_ENET_RX_OV)
+ fep->stats.rx_crc_errors++;
+
+ skb = fep->rx_skbuff[curidx];
+
+ dma_unmap_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE);
+
+ skbn = skb;
+
+ } else {
+
+ /* napi, got packet but no quota */
+ if (--rx_work_limit < 0)
+ break;
+
+ skb = fep->rx_skbuff[curidx];
+
+ dma_unmap_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE);
+
+ /*
+ * Process the incoming frame.
+ */
+ fep->stats.rx_packets++;
+ pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
+ fep->stats.rx_bytes += pkt_len + 4;
+
+ if (pkt_len <= fpi->rx_copybreak) {
+ /* +2 to make IP header L1 cache aligned */
+ skbn = dev_alloc_skb(pkt_len + 2);
+ if (skbn != NULL) {
+ skb_reserve(skbn, 2); /* align IP header */
+ memcpy(skbn->data, skb->data, pkt_len);
+ /* swap */
+ skbt = skb;
+ skb = skbn;
+ skbn = skbt;
+ }
+ } else
+ skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+ if (skbn != NULL) {
+ skb->dev = dev;
+ skb_put(skb, pkt_len); /* Make room */
+ skb->protocol = eth_type_trans(skb, dev);
+ received++;
+ netif_receive_skb(skb);
+ } else {
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s Memory squeeze, dropping packet.\n",
+ dev->name);
+ fep->stats.rx_dropped++;
+ skbn = skb;
+ }
+ }
+
+ fep->rx_skbuff[curidx] = skbn;
+ CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE));
+ CBDW_DATLEN(bdp, 0);
+ CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+ /*
+ * Update BD pointer to next entry.
+ */
+ if ((sc & BD_ENET_RX_WRAP) == 0)
+ bdp++;
+ else
+ bdp = fep->rx_bd_base;
+
+ (*fep->ops->rx_bd_done)(dev);
+ }
+
+ fep->cur_rx = bdp;
+
+ dev->quota -= received;
+ *budget -= received;
+
+ if (rx_work_limit < 0)
+ return 1; /* not done */
+
+ /* done */
+ netif_rx_complete(dev);
+
+ (*fep->ops->napi_enable_rx)(dev);
+
+ return 0;
+}
+
+/* non NAPI receive function */
+static int fs_enet_rx_non_napi(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ cbd_t *bdp;
+ struct sk_buff *skb, *skbn, *skbt;
+ int received = 0;
+ u16 pkt_len, sc;
+ int curidx;
+ /*
+ * First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = fep->cur_rx;
+
+ while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+ curidx = bdp - fep->rx_bd_base;
+
+ /*
+ * Since we have allocated space to hold a complete frame,
+ * the last indicator should be set.
+ */
+ if ((sc & BD_ENET_RX_LAST) == 0)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s rcv is not +last\n",
+ dev->name);
+
+ /*
+ * Check for errors.
+ */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+ BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+ fep->stats.rx_errors++;
+ /* Frame too long or too short. */
+ if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ fep->stats.rx_length_errors++;
+ /* Frame alignment */
+ if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+ fep->stats.rx_frame_errors++;
+ /* CRC Error */
+ if (sc & BD_ENET_RX_CR)
+ fep->stats.rx_crc_errors++;
+ /* FIFO overrun */
+ if (sc & BD_ENET_RX_OV)
+ fep->stats.rx_crc_errors++;
+
+ skb = fep->rx_skbuff[curidx];
+
+ dma_unmap_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE);
+
+ skbn = skb;
+
+ } else {
+
+ skb = fep->rx_skbuff[curidx];
+
+ dma_unmap_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE);
+
+ /*
+ * Process the incoming frame.
+ */
+ fep->stats.rx_packets++;
+ pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
+ fep->stats.rx_bytes += pkt_len + 4;
+
+ if (pkt_len <= fpi->rx_copybreak) {
+ /* +2 to make IP header L1 cache aligned */
+ skbn = dev_alloc_skb(pkt_len + 2);
+ if (skbn != NULL) {
+ skb_reserve(skbn, 2); /* align IP header */
+ memcpy(skbn->data, skb->data, pkt_len);
+ /* swap */
+ skbt = skb;
+ skb = skbn;
+ skbn = skbt;
+ }
+ } else
+ skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+ if (skbn != NULL) {
+ skb->dev = dev;
+ skb_put(skb, pkt_len); /* Make room */
+ skb->protocol = eth_type_trans(skb, dev);
+ received++;
+ netif_rx(skb);
+ } else {
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s Memory squeeze, dropping packet.\n",
+ dev->name);
+ fep->stats.rx_dropped++;
+ skbn = skb;
+ }
+ }
+
+ fep->rx_skbuff[curidx] = skbn;
+ CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE));
+ CBDW_DATLEN(bdp, 0);
+ CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+ /*
+ * Update BD pointer to next entry.
+ */
+ if ((sc & BD_ENET_RX_WRAP) == 0)
+ bdp++;
+ else
+ bdp = fep->rx_bd_base;
+
+ (*fep->ops->rx_bd_done)(dev);
+ }
+
+ fep->cur_rx = bdp;
+
+ return 0;
+}
+
+static void fs_enet_tx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ cbd_t *bdp;
+ struct sk_buff *skb;
+ int dirtyidx, do_wake, do_restart;
+ u16 sc;
+
+ spin_lock(&fep->lock);
+ bdp = fep->dirty_tx;
+
+ do_wake = do_restart = 0;
+ while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
+
+ dirtyidx = bdp - fep->tx_bd_base;
+
+ if (fep->tx_free == fep->tx_ring)
+ break;
+
+ skb = fep->tx_skbuff[dirtyidx];
+
+ /*
+ * Check for errors.
+ */
+ if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+ BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
+
+ if (sc & BD_ENET_TX_HB) /* No heartbeat */
+ fep->stats.tx_heartbeat_errors++;
+ if (sc & BD_ENET_TX_LC) /* Late collision */
+ fep->stats.tx_window_errors++;
+ if (sc & BD_ENET_TX_RL) /* Retrans limit */
+ fep->stats.tx_aborted_errors++;
+ if (sc & BD_ENET_TX_UN) /* Underrun */
+ fep->stats.tx_fifo_errors++;
+ if (sc & BD_ENET_TX_CSL) /* Carrier lost */
+ fep->stats.tx_carrier_errors++;
+
+ if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ fep->stats.tx_errors++;
+ do_restart = 1;
+ }
+ } else
+ fep->stats.tx_packets++;
+
+ if (sc & BD_ENET_TX_READY)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s HEY! Enet xmit interrupt and TX_READY.\n",
+ dev->name);
+
+ /*
+ * Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (sc & BD_ENET_TX_DEF)
+ fep->stats.collisions++;
+
+ /* unmap */
+ dma_unmap_single(fep->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+ /*
+ * Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(skb);
+ fep->tx_skbuff[dirtyidx] = NULL;
+
+ /*
+ * Update pointer to next buffer descriptor to be transmitted.
+ */
+ if ((sc & BD_ENET_TX_WRAP) == 0)
+ bdp++;
+ else
+ bdp = fep->tx_bd_base;
+
+ /*
+ * Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (!fep->tx_free++)
+ do_wake = 1;
+ }
+
+ fep->dirty_tx = bdp;
+
+ if (do_restart)
+ (*fep->ops->tx_restart)(dev);
+
+ spin_unlock(&fep->lock);
+
+ if (do_wake)
+ netif_wake_queue(dev);
+}
+
+/*
+ * The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static irqreturn_t
+fs_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fs_enet_private *fep;
+ const struct fs_platform_info *fpi;
+ u32 int_events;
+ u32 int_clr_events;
+ int nr, napi_ok;
+ int handled;
+
+ fep = netdev_priv(dev);
+ fpi = fep->fpi;
+
+ nr = 0;
+ while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) {
+
+ nr++;
+
+ int_clr_events = int_events;
+ if (fpi->use_napi)
+ int_clr_events &= ~fep->ev_napi_rx;
+
+ (*fep->ops->clear_int_events)(dev, int_clr_events);
+
+ if (int_events & fep->ev_err)
+ (*fep->ops->ev_error)(dev, int_events);
+
+ if (int_events & fep->ev_rx) {
+ if (!fpi->use_napi)
+ fs_enet_rx_non_napi(dev);
+ else {
+ napi_ok = netif_rx_schedule_prep(dev);
+
+ (*fep->ops->napi_disable_rx)(dev);
+ (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
+
+ /* NOTE: it is possible for FCCs in NAPI mode */
+ /* to submit a spurious interrupt while in poll */
+ if (napi_ok)
+ __netif_rx_schedule(dev);
+ }
+ }
+
+ if (int_events & fep->ev_tx)
+ fs_enet_tx(dev);
+ }
+
+ handled = nr > 0;
+ return IRQ_RETVAL(handled);
+}
+
+void fs_init_bds(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ cbd_t *bdp;
+ struct sk_buff *skb;
+ int i;
+
+ fs_cleanup_bds(dev);
+
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->tx_free = fep->tx_ring;
+ fep->cur_rx = fep->rx_bd_base;
+
+ /*
+ * Initialize the receive buffer descriptors.
+ */
+ for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
+ skb = dev_alloc_skb(ENET_RX_FRSIZE);
+ if (skb == NULL) {
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s Memory squeeze, unable to allocate skb\n",
+ dev->name);
+ break;
+ }
+ fep->rx_skbuff[i] = skb;
+ skb->dev = dev;
+ CBDW_BUFADDR(bdp,
+ dma_map_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE));
+ CBDW_DATLEN(bdp, 0); /* zero */
+ CBDW_SC(bdp, BD_ENET_RX_EMPTY |
+ ((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
+ }
+ /*
+ * if we failed, fillup remainder
+ */
+ for (; i < fep->rx_ring; i++, bdp++) {
+ fep->rx_skbuff[i] = NULL;
+ CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
+ }
+
+ /*
+ * ...and the same for transmit.
+ */
+ for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
+ fep->tx_skbuff[i] = NULL;
+ CBDW_BUFADDR(bdp, 0);
+ CBDW_DATLEN(bdp, 0);
+ CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
+ }
+}
+
+void fs_cleanup_bds(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct sk_buff *skb;
+ int i;
+
+ /*
+ * Reset SKB transmit buffers.
+ */
+ for (i = 0; i < fep->tx_ring; i++) {
+ if ((skb = fep->tx_skbuff[i]) == NULL)
+ continue;
+
+ /* unmap */
+ dma_unmap_single(fep->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+ fep->tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
+
+ /*
+ * Reset SKB receive buffers
+ */
+ for (i = 0; i < fep->rx_ring; i++) {
+ if ((skb = fep->rx_skbuff[i]) == NULL)
+ continue;
+
+ /* unmap */
+ dma_unmap_single(fep->dev, skb->data,
+ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+ DMA_FROM_DEVICE);
+
+ fep->rx_skbuff[i] = NULL;
+
+ dev_kfree_skb(skb);
+ }
+}
+
+/**********************************************************************************/
+
+static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ cbd_t *bdp;
+ int curidx;
+ u16 sc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fep->tx_lock, flags);
+
+ /*
+ * Fill in a Tx ring entry
+ */
+ bdp = fep->cur_tx;
+
+ if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+ /*
+ * Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since the tx queue should be stopped.
+ */
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s tx queue full!.\n", dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ curidx = bdp - fep->tx_bd_base;
+ /*
+ * Clear all of the status flags.
+ */
+ CBDC_SC(bdp, BD_ENET_TX_STATS);
+
+ /*
+ * Save skb pointer.
+ */
+ fep->tx_skbuff[curidx] = skb;
+
+ fep->stats.tx_bytes += skb->len;
+
+ /*
+ * Push the data cache so the CPM does not get stale memory data.
+ */
+ CBDW_BUFADDR(bdp, dma_map_single(fep->dev,
+ skb->data, skb->len, DMA_TO_DEVICE));
+ CBDW_DATLEN(bdp, skb->len);
+
+ dev->trans_start = jiffies;
+
+ /*
+ * If this was the last BD in the ring, start at the beginning again.
+ */
+ if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
+ fep->cur_tx++;
+ else
+ fep->cur_tx = fep->tx_bd_base;
+
+ if (!--fep->tx_free)
+ netif_stop_queue(dev);
+
+ /* Trigger transmission start */
+ sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |
+ BD_ENET_TX_LAST | BD_ENET_TX_TC;
+
+ /* note that while FEC does not have this bit
+ * it marks it as available for software use
+ * yay for hw reuse :) */
+ if (skb->len <= 60)
+ sc |= BD_ENET_TX_PAD;
+ CBDS_SC(bdp, sc);
+
+ (*fep->ops->tx_kickstart)(dev);
+
+ spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+ return NETDEV_TX_OK;
+}
+
+static int fs_request_irq(struct net_device *dev, int irq, const char *name,
+ irqreturn_t (*irqf)(int irq, void *dev_id, struct pt_regs *regs))
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ (*fep->ops->pre_request_irq)(dev, irq);
+ return request_irq(irq, irqf, SA_SHIRQ, 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);
+}
+
+/**********************************************************************************/
+
+/* This interrupt occurs when the PHY detects a link change. */
+static irqreturn_t
+fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fs_enet_private *fep;
+ const struct fs_platform_info *fpi;
+
+ fep = netdev_priv(dev);
+ fpi = fep->fpi;
+
+ /*
+ * Acknowledge the interrupt if possible. If we have not
+ * found the PHY yet we can't process or acknowledge the
+ * interrupt now. Instead we ignore this interrupt for now,
+ * which we can do since it is edge triggered. It will be
+ * acknowledged later by fs_enet_open().
+ */
+ if (!fep->phy)
+ return IRQ_NONE;
+
+ fs_mii_ack_int(dev);
+ fs_mii_link_status_change_check(dev, 0);
+
+ return IRQ_HANDLED;
+}
+
+static void fs_timeout(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int wake = 0;
+
+ fep->stats.tx_errors++;
+
+ spin_lock_irqsave(&fep->lock, flags);
+
+ if (dev->flags & IFF_UP) {
+ (*fep->ops->stop)(dev);
+ (*fep->ops->restart)(dev);
+ }
+
+ wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ if (wake)
+ netif_wake_queue(dev);
+}
+
+static int fs_enet_open(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ int r;
+
+ /* Install our interrupt handler. */
+ r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
+ if (r != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s Could not allocate FEC IRQ!", dev->name);
+ return -EINVAL;
+ }
+
+ /* Install our phy interrupt handler */
+ if (fpi->phy_irq != -1) {
+
+ r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
+ if (r != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s Could not allocate PHY IRQ!", dev->name);
+ fs_free_irq(dev, fep->interrupt);
+ return -EINVAL;
+ }
+ }
+
+ fs_mii_startup(dev);
+ netif_carrier_off(dev);
+ fs_mii_link_status_change_check(dev, 1);
+
+ return 0;
+}
+
+static int fs_enet_close(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ fs_mii_shutdown(dev);
+
+ spin_lock_irqsave(&fep->lock, flags);
+ (*fep->ops->stop)(dev);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ /* release any irqs */
+ if (fpi->phy_irq != -1)
+ fs_free_irq(dev, fpi->phy_irq);
+ fs_free_irq(dev, fep->interrupt);
+
+ return 0;
+}
+
+static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ return &fep->stats;
+}
+
+/*************************************************************************/
+
+static void fs_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int fs_get_regs_len(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ return (*fep->ops->get_regs_len)(dev);
+}
+
+static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int r, len;
+
+ len = regs->len;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ r = (*fep->ops->get_regs)(dev, p, &len);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ if (r == 0)
+ regs->version = 0;
+}
+
+static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = mii_ethtool_gset(&fep->mii_if, cmd);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return rc;
+}
+
+static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = mii_ethtool_sset(&fep->mii_if, cmd);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return rc;
+}
+
+static int fs_nway_reset(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ return mii_nway_restart(&fep->mii_if);
+}
+
+static u32 fs_get_msglevel(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ return fep->msg_enable;
+}
+
+static void fs_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fep->msg_enable = value;
+}
+
+static struct ethtool_ops fs_ethtool_ops = {
+ .get_drvinfo = fs_get_drvinfo,
+ .get_regs_len = fs_get_regs_len,
+ .get_settings = fs_get_settings,
+ .set_settings = fs_set_settings,
+ .nway_reset = fs_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = fs_get_msglevel,
+ .set_msglevel = fs_set_msglevel,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum, /* local! */
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_regs = fs_get_regs,
+};
+
+static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
+ unsigned long flags;
+ int rc;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&fep->lock, flags);
+ rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+ spin_unlock_irqrestore(&fep->lock, flags);
+ return rc;
+}
+
+extern int fs_mii_connect(struct net_device *dev);
+extern void fs_mii_disconnect(struct net_device *dev);
+
+static struct net_device *fs_init_instance(struct device *dev,
+ const struct fs_platform_info *fpi)
+{
+ struct net_device *ndev = NULL;
+ struct fs_enet_private *fep = NULL;
+ int privsize, i, r, err = 0, registered = 0;
+
+ /* guard */
+ if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
+ return ERR_PTR(-EINVAL);
+
+ privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
+ (fpi->rx_ring + fpi->tx_ring));
+
+ ndev = alloc_etherdev(privsize);
+ if (!ndev) {
+ err = -ENOMEM;
+ goto err;
+ }
+ SET_MODULE_OWNER(ndev);
+
+ fep = netdev_priv(ndev);
+ memset(fep, 0, privsize); /* clear everything */
+
+ fep->dev = dev;
+ dev_set_drvdata(dev, ndev);
+ fep->fpi = fpi;
+ if (fpi->init_ioports)
+ fpi->init_ioports();
+
+#ifdef CONFIG_FS_ENET_HAS_FEC
+ if (fs_get_fec_index(fpi->fs_no) >= 0)
+ fep->ops = &fs_fec_ops;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_SCC
+ if (fs_get_scc_index(fpi->fs_no) >=0 )
+ fep->ops = &fs_scc_ops;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_FCC
+ if (fs_get_fcc_index(fpi->fs_no) >= 0)
+ fep->ops = &fs_fcc_ops;
+#endif
+
+ if (fep->ops == NULL) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s No matching ops found (%d).\n",
+ ndev->name, fpi->fs_no);
+ err = -EINVAL;
+ goto err;
+ }
+
+ r = (*fep->ops->setup_data)(ndev);
+ if (r != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s setup_data failed\n",
+ ndev->name);
+ err = r;
+ goto err;
+ }
+
+ /* point rx_skbuff, tx_skbuff */
+ fep->rx_skbuff = (struct sk_buff **)&fep[1];
+ fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+ /* init locks */
+ spin_lock_init(&fep->lock);
+ spin_lock_init(&fep->tx_lock);
+
+ /*
+ * Set the Ethernet address.
+ */
+ for (i = 0; i < 6; i++)
+ ndev->dev_addr[i] = fpi->macaddr[i];
+
+ r = (*fep->ops->allocate_bd)(ndev);
+
+ if (fep->ring_base == NULL) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
+ err = r;
+ goto err;
+ }
+
+ /*
+ * Set receive and transmit descriptor base.
+ */
+ fep->rx_bd_base = fep->ring_base;
+ fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+ /* initialize ring size variables */
+ fep->tx_ring = fpi->tx_ring;
+ fep->rx_ring = fpi->rx_ring;
+
+ /*
+ * The FEC Ethernet specific entries in the device structure.
+ */
+ ndev->open = fs_enet_open;
+ ndev->hard_start_xmit = fs_enet_start_xmit;
+ ndev->tx_timeout = fs_timeout;
+ ndev->watchdog_timeo = 2 * HZ;
+ ndev->stop = fs_enet_close;
+ ndev->get_stats = fs_enet_get_stats;
+ ndev->set_multicast_list = fs_set_multicast_list;
+ if (fpi->use_napi) {
+ ndev->poll = fs_enet_rx_napi;
+ ndev->weight = fpi->napi_weight;
+ }
+ ndev->ethtool_ops = &fs_ethtool_ops;
+ ndev->do_ioctl = fs_ioctl;
+
+ init_timer(&fep->phy_timer_list);
+
+ netif_carrier_off(ndev);
+
+ err = register_netdev(ndev);
+ if (err != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s register_netdev failed.\n", ndev->name);
+ goto err;
+ }
+ registered = 1;
+
+ err = fs_mii_connect(ndev);
+ if (err != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s fs_mii_connect failed.\n", ndev->name);
+ goto err;
+ }
+
+ return ndev;
+
+ err:
+ if (ndev != NULL) {
+
+ if (registered)
+ unregister_netdev(ndev);
+
+ if (fep != NULL) {
+ (*fep->ops->free_bd)(ndev);
+ (*fep->ops->cleanup_data)(ndev);
+ }
+
+ free_netdev(ndev);
+ }
+
+ dev_set_drvdata(dev, NULL);
+
+ return ERR_PTR(err);
+}
+
+static int fs_cleanup_instance(struct net_device *ndev)
+{
+ struct fs_enet_private *fep;
+ const struct fs_platform_info *fpi;
+ struct device *dev;
+
+ if (ndev == NULL)
+ return -EINVAL;
+
+ fep = netdev_priv(ndev);
+ if (fep == NULL)
+ return -EINVAL;
+
+ fpi = fep->fpi;
+
+ fs_mii_disconnect(ndev);
+
+ unregister_netdev(ndev);
+
+ dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+ fep->ring_base, fep->ring_mem_addr);
+
+ /* reset it */
+ (*fep->ops->cleanup_data)(ndev);
+
+ dev = fep->dev;
+ if (dev != NULL) {
+ dev_set_drvdata(dev, NULL);
+ fep->dev = NULL;
+ }
+
+ free_netdev(ndev);
+
+ return 0;
+}
+
+/**************************************************************************************/
+
+/* handy pointer to the immap */
+void *fs_enet_immap = NULL;
+
+static int setup_immap(void)
+{
+ phys_addr_t paddr = 0;
+ unsigned long size = 0;
+
+#ifdef CONFIG_CPM1
+ paddr = IMAP_ADDR;
+ size = 0x10000; /* map 64K */
+#endif
+
+#ifdef CONFIG_CPM2
+ paddr = CPM_MAP_ADDR;
+ size = 0x40000; /* map 256 K */
+#endif
+ fs_enet_immap = ioremap(paddr, size);
+ if (fs_enet_immap == NULL)
+ return -EBADF; /* XXX ahem; maybe just BUG_ON? */
+
+ return 0;
+}
+
+static void cleanup_immap(void)
+{
+ if (fs_enet_immap != NULL) {
+ iounmap(fs_enet_immap);
+ fs_enet_immap = NULL;
+ }
+}
+
+/**************************************************************************************/
+
+static int __devinit fs_enet_probe(struct device *dev)
+{
+ struct net_device *ndev;
+
+ /* no fixup - no device */
+ if (dev->platform_data == NULL) {
+ printk(KERN_INFO "fs_enet: "
+ "probe called with no platform data; "
+ "remove unused devices\n");
+ return -ENODEV;
+ }
+
+ ndev = fs_init_instance(dev, dev->platform_data);
+ if (IS_ERR(ndev))
+ return PTR_ERR(ndev);
+ return 0;
+}
+
+static int fs_enet_remove(struct device *dev)
+{
+ return fs_cleanup_instance(dev_get_drvdata(dev));
+}
+
+static struct device_driver fs_enet_fec_driver = {
+ .name = "fsl-cpm-fec",
+ .bus = &platform_bus_type,
+ .probe = fs_enet_probe,
+ .remove = fs_enet_remove,
+#ifdef CONFIG_PM
+/* .suspend = fs_enet_suspend, TODO */
+/* .resume = fs_enet_resume, TODO */
+#endif
+};
+
+static struct device_driver fs_enet_scc_driver = {
+ .name = "fsl-cpm-scc",
+ .bus = &platform_bus_type,
+ .probe = fs_enet_probe,
+ .remove = fs_enet_remove,
+#ifdef CONFIG_PM
+/* .suspend = fs_enet_suspend, TODO */
+/* .resume = fs_enet_resume, TODO */
+#endif
+};
+
+static struct device_driver fs_enet_fcc_driver = {
+ .name = "fsl-cpm-fcc",
+ .bus = &platform_bus_type,
+ .probe = fs_enet_probe,
+ .remove = fs_enet_remove,
+#ifdef CONFIG_PM
+/* .suspend = fs_enet_suspend, TODO */
+/* .resume = fs_enet_resume, TODO */
+#endif
+};
+
+static int __init fs_init(void)
+{
+ int r;
+
+ printk(KERN_INFO
+ "%s", version);
+
+ r = setup_immap();
+ if (r != 0)
+ return r;
+ r = driver_register(&fs_enet_fec_driver);
+ if (r != 0)
+ goto err;
+
+ r = driver_register(&fs_enet_fcc_driver);
+ if (r != 0)
+ goto err;
+
+ r = driver_register(&fs_enet_scc_driver);
+ if (r != 0)
+ goto err;
+
+ return 0;
+err:
+ cleanup_immap();
+ return r;
+
+}
+
+static void __exit fs_cleanup(void)
+{
+ driver_unregister(&fs_enet_fec_driver);
+ driver_unregister(&fs_enet_fcc_driver);
+ driver_unregister(&fs_enet_scc_driver);
+ cleanup_immap();
+}
+
+/**************************************************************************************/
+
+module_init(fs_init);
+module_exit(fs_cleanup);
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
new file mode 100644
index 000000000000..c6770377ef87
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet-mii.c
@@ -0,0 +1,507 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/*
+ * Generic PHY support.
+ * Should work for all PHYs, but link change is detected by polling
+ */
+
+static void generic_timer_callback(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fep->phy_timer_list.expires = jiffies + HZ / 2;
+
+ add_timer(&fep->phy_timer_list);
+
+ fs_mii_link_status_change_check(dev, 0);
+}
+
+static void generic_startup(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
+ fep->phy_timer_list.data = (unsigned long)dev;
+ fep->phy_timer_list.function = generic_timer_callback;
+ add_timer(&fep->phy_timer_list);
+}
+
+static void generic_shutdown(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ del_timer_sync(&fep->phy_timer_list);
+}
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9161 is used on the NETTA board */
+
+/* register definitions */
+
+#define MII_DM9161_ANAR 4 /* Aux. Config Register */
+#define MII_DM9161_ACR 16 /* Aux. Config Register */
+#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
+#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
+#define MII_DM9161_INTR 21 /* Interrupt Register */
+#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
+#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
+
+static void dm9161_startup(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
+ /* Start autonegotiation */
+ fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ*8);
+}
+
+static void dm9161_ack_int(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
+}
+
+static void dm9161_shutdown(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
+}
+
+/**********************************************************************************/
+
+static const struct phy_info phy_info[] = {
+ {
+ .id = 0x00181b88,
+ .name = "DM9161",
+ .startup = dm9161_startup,
+ .ack_int = dm9161_ack_int,
+ .shutdown = dm9161_shutdown,
+ }, {
+ .id = 0,
+ .name = "GENERIC",
+ .startup = generic_startup,
+ .shutdown = generic_shutdown,
+ },
+};
+
+/**********************************************************************************/
+
+static int phy_id_detect(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ struct fs_enet_mii_bus *bus = fep->mii_bus;
+ int i, r, start, end, phytype, physubtype;
+ const struct phy_info *phy;
+ int phy_hwid, phy_id;
+
+ phy_hwid = -1;
+ fep->phy = NULL;
+
+ /* auto-detect? */
+ if (fpi->phy_addr == -1) {
+ start = 1;
+ end = 32;
+ } else { /* direct */
+ start = fpi->phy_addr;
+ end = start + 1;
+ }
+
+ for (phy_id = start; phy_id < end; phy_id++) {
+ /* skip already used phy addresses on this bus */
+ if (bus->usage_map & (1 << phy_id))
+ continue;
+ r = fs_mii_read(dev, phy_id, MII_PHYSID1);
+ if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
+ continue;
+ r = fs_mii_read(dev, phy_id, MII_PHYSID2);
+ if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
+ continue;
+ phy_hwid = (phytype << 16) | physubtype;
+ if (phy_hwid != -1)
+ break;
+ }
+
+ if (phy_hwid == -1) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s No PHY detected! range=0x%02x-0x%02x\n",
+ dev->name, start, end);
+ return -1;
+ }
+
+ for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
+ if (phy->id == (phy_hwid >> 4) || phy->id == 0)
+ break;
+
+ if (i >= ARRAY_SIZE(phy_info)) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s PHY id 0x%08x is not supported!\n",
+ dev->name, phy_hwid);
+ return -1;
+ }
+
+ fep->phy = phy;
+
+ /* mark this address as used */
+ bus->usage_map |= (1 << phy_id);
+
+ printk(KERN_INFO DRV_MODULE_NAME
+ ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
+ dev->name, phy_id, fep->phy->name, phy_hwid,
+ fpi->phy_addr == -1 ? " (auto-detected)" : "");
+
+ return phy_id;
+}
+
+void fs_mii_startup(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (fep->phy->startup)
+ (*fep->phy->startup) (dev);
+}
+
+void fs_mii_shutdown(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (fep->phy->shutdown)
+ (*fep->phy->shutdown) (dev);
+}
+
+void fs_mii_ack_int(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (fep->phy->ack_int)
+ (*fep->phy->ack_int) (dev);
+}
+
+#define MII_LINK 0x0001
+#define MII_HALF 0x0002
+#define MII_FULL 0x0004
+#define MII_BASE4 0x0008
+#define MII_10M 0x0010
+#define MII_100M 0x0020
+#define MII_1G 0x0040
+#define MII_10G 0x0080
+
+/* return full mii info at one gulp, with a usable form */
+static unsigned int mii_full_status(struct mii_if_info *mii)
+{
+ unsigned int status;
+ int bmsr, adv, lpa, neg;
+ struct fs_enet_private* fep = netdev_priv(mii->dev);
+
+ /* first, a dummy read, needed to latch some MII phys */
+ (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+ bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+
+ /* no link */
+ if ((bmsr & BMSR_LSTATUS) == 0)
+ return 0;
+
+ status = MII_LINK;
+
+ /* Lets look what ANEG says if it's supported - otherwize we shall
+ take the right values from the platform info*/
+ if(!mii->force_media) {
+ /* autoneg not completed; don't bother */
+ if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
+ return 0;
+
+ adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
+ lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
+
+ neg = lpa & adv;
+ } else {
+ neg = fep->fpi->bus_info->lpa;
+ }
+
+ if (neg & LPA_100FULL)
+ status |= MII_FULL | MII_100M;
+ else if (neg & LPA_100BASE4)
+ status |= MII_FULL | MII_BASE4 | MII_100M;
+ else if (neg & LPA_100HALF)
+ status |= MII_HALF | MII_100M;
+ else if (neg & LPA_10FULL)
+ status |= MII_FULL | MII_10M;
+ else
+ status |= MII_HALF | MII_10M;
+
+ return status;
+}
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct mii_if_info *mii = &fep->mii_if;
+ unsigned int mii_status;
+ int ok_to_print, link, duplex, speed;
+ unsigned long flags;
+
+ ok_to_print = netif_msg_link(fep);
+
+ mii_status = mii_full_status(mii);
+
+ if (!init_media && mii_status == fep->last_mii_status)
+ return;
+
+ fep->last_mii_status = mii_status;
+
+ link = !!(mii_status & MII_LINK);
+ duplex = !!(mii_status & MII_FULL);
+ speed = (mii_status & MII_100M) ? 100 : 10;
+
+ if (link == 0) {
+ netif_carrier_off(mii->dev);
+ netif_stop_queue(dev);
+ if (!init_media) {
+ spin_lock_irqsave(&fep->lock, flags);
+ (*fep->ops->stop)(dev);
+ spin_unlock_irqrestore(&fep->lock, flags);
+ }
+
+ if (ok_to_print)
+ printk(KERN_INFO "%s: link down\n", mii->dev->name);
+
+ } else {
+
+ mii->full_duplex = duplex;
+
+ netif_carrier_on(mii->dev);
+
+ spin_lock_irqsave(&fep->lock, flags);
+ fep->duplex = duplex;
+ fep->speed = speed;
+ (*fep->ops->restart)(dev);
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ netif_start_queue(dev);
+
+ if (ok_to_print)
+ printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
+ dev->name, speed, duplex ? "full" : "half");
+ }
+}
+
+/**********************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fs_enet_mii_bus *bus = fep->mii_bus;
+
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&bus->mii_lock, flags);
+ ret = (*bus->mii_read)(bus, phy_id, location);
+ spin_unlock_irqrestore(&bus->mii_lock, flags);
+
+ return ret;
+}
+
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fs_enet_mii_bus *bus = fep->mii_bus;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bus->mii_lock, flags);
+ (*bus->mii_write)(bus, phy_id, location, value);
+ spin_unlock_irqrestore(&bus->mii_lock, flags);
+}
+
+/*****************************************************************************/
+
+/* list of all registered mii buses */
+static LIST_HEAD(fs_mii_bus_list);
+
+static struct fs_enet_mii_bus *lookup_bus(int method, int id)
+{
+ struct list_head *ptr;
+ struct fs_enet_mii_bus *bus;
+
+ list_for_each(ptr, &fs_mii_bus_list) {
+ bus = list_entry(ptr, struct fs_enet_mii_bus, list);
+ if (bus->bus_info->method == method &&
+ bus->bus_info->id == id)
+ return bus;
+ }
+ return NULL;
+}
+
+static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
+{
+ struct fs_enet_mii_bus *bus;
+ int ret = 0;
+
+ bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+ if (bus == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memset(bus, 0, sizeof(*bus));
+ spin_lock_init(&bus->mii_lock);
+ bus->bus_info = bi;
+ bus->refs = 0;
+ bus->usage_map = 0;
+
+ /* perform initialization */
+ switch (bi->method) {
+
+ case fsmii_fixed:
+ ret = fs_mii_fixed_init(bus);
+ if (ret != 0)
+ goto err;
+ break;
+
+ case fsmii_bitbang:
+ ret = fs_mii_bitbang_init(bus);
+ if (ret != 0)
+ goto err;
+ break;
+#ifdef CONFIG_FS_ENET_HAS_FEC
+ case fsmii_fec:
+ ret = fs_mii_fec_init(bus);
+ if (ret != 0)
+ goto err;
+ break;
+#endif
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+
+ list_add(&bus->list, &fs_mii_bus_list);
+
+ return bus;
+
+err:
+ if (bus)
+ kfree(bus);
+ return ERR_PTR(ret);
+}
+
+static void destroy_bus(struct fs_enet_mii_bus *bus)
+{
+ /* remove from bus list */
+ list_del(&bus->list);
+
+ /* nothing more needed */
+ kfree(bus);
+}
+
+int fs_mii_connect(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ struct fs_enet_mii_bus *bus = NULL;
+
+ /* check method validity */
+ switch (fpi->bus_info->method) {
+ case fsmii_fixed:
+ case fsmii_bitbang:
+ break;
+#ifdef CONFIG_FS_ENET_HAS_FEC
+ case fsmii_fec:
+ break;
+#endif
+ default:
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s Unknown MII bus method (%d)!\n",
+ dev->name, fpi->bus_info->method);
+ return -EINVAL;
+ }
+
+ bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
+
+ /* if not found create new bus */
+ if (bus == NULL) {
+ bus = create_bus(fpi->bus_info);
+ if (IS_ERR(bus)) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s MII bus creation failure!\n", dev->name);
+ return PTR_ERR(bus);
+ }
+ }
+
+ bus->refs++;
+
+ fep->mii_bus = bus;
+
+ fep->mii_if.dev = dev;
+ fep->mii_if.phy_id_mask = 0x1f;
+ fep->mii_if.reg_num_mask = 0x1f;
+ fep->mii_if.mdio_read = fs_mii_read;
+ fep->mii_if.mdio_write = fs_mii_write;
+ fep->mii_if.force_media = fpi->bus_info->disable_aneg;
+ fep->mii_if.phy_id = phy_id_detect(dev);
+
+ return 0;
+}
+
+void fs_mii_disconnect(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ struct fs_enet_mii_bus *bus = NULL;
+
+ bus = fep->mii_bus;
+ fep->mii_bus = NULL;
+
+ if (--bus->refs <= 0)
+ destroy_bus(bus);
+}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
new file mode 100644
index 000000000000..1105543b9d88
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -0,0 +1,245 @@
+#ifndef FS_ENET_H
+#define FS_ENET_H
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/list.h>
+
+#include <linux/fs_enet_pd.h>
+
+#include <asm/dma-mapping.h>
+
+#ifdef CONFIG_CPM1
+#include <asm/commproc.h>
+#endif
+
+#ifdef CONFIG_CPM2
+#include <asm/cpm2.h>
+#endif
+
+/* hw driver ops */
+struct fs_ops {
+ int (*setup_data)(struct net_device *dev);
+ int (*allocate_bd)(struct net_device *dev);
+ void (*free_bd)(struct net_device *dev);
+ void (*cleanup_data)(struct net_device *dev);
+ void (*set_multicast_list)(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);
+ void (*rx_bd_done)(struct net_device *dev);
+ void (*tx_kickstart)(struct net_device *dev);
+ u32 (*get_int_events)(struct net_device *dev);
+ void (*clear_int_events)(struct net_device *dev, u32 int_events);
+ void (*ev_error)(struct net_device *dev, u32 int_events);
+ int (*get_regs)(struct net_device *dev, void *p, int *sizep);
+ int (*get_regs_len)(struct net_device *dev);
+ void (*tx_restart)(struct net_device *dev);
+};
+
+struct phy_info {
+ unsigned int id;
+ const char *name;
+ void (*startup) (struct net_device * dev);
+ void (*shutdown) (struct net_device * dev);
+ void (*ack_int) (struct net_device * dev);
+};
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define MAX_MTU 1508 /* Allow fullsized pppoe packets over VLAN */
+#define MIN_MTU 46 /* this is data size */
+#define CRC_LEN 4
+
+#define PKT_MAXBUF_SIZE (MAX_MTU+ETH_HLEN+CRC_LEN)
+#define PKT_MINBUF_SIZE (MIN_MTU+ETH_HLEN+CRC_LEN)
+
+/* Must be a multiple of 32 (to cover both FEC & FCC) */
+#define PKT_MAXBLR_SIZE ((PKT_MAXBUF_SIZE + 31) & ~31)
+/* This is needed so that invalidate_xxx wont invalidate too much */
+#define ENET_RX_FRSIZE L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+
+struct fs_enet_mii_bus {
+ struct list_head list;
+ spinlock_t mii_lock;
+ const struct fs_mii_bus_info *bus_info;
+ int refs;
+ u32 usage_map;
+
+ int (*mii_read)(struct fs_enet_mii_bus *bus,
+ int phy_id, int location);
+
+ void (*mii_write)(struct fs_enet_mii_bus *bus,
+ int phy_id, int location, int value);
+
+ union {
+ struct {
+ unsigned int mii_speed;
+ void *fecp;
+ } fec;
+
+ struct {
+ /* note that the actual port size may */
+ /* be different; cpm(s) handle it OK */
+ u8 mdio_msk;
+ u8 *mdio_dir;
+ u8 *mdio_dat;
+ u8 mdc_msk;
+ u8 *mdc_dir;
+ u8 *mdc_dat;
+ } bitbang;
+
+ struct {
+ u16 lpa;
+ } fixed;
+ };
+};
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
+
+struct fs_enet_private {
+ struct device *dev; /* pointer back to the device (must be initialized first) */
+ spinlock_t lock; /* during all ops except TX pckt processing */
+ spinlock_t tx_lock; /* during fs_start_xmit and fs_tx */
+ const struct fs_platform_info *fpi;
+ const struct fs_ops *ops;
+ int rx_ring, tx_ring;
+ dma_addr_t ring_mem_addr;
+ void *ring_base;
+ struct sk_buff **rx_skbuff;
+ struct sk_buff **tx_skbuff;
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *dirty_tx; /* ring entries to be free()ed. */
+ cbd_t *cur_rx;
+ cbd_t *cur_tx;
+ int tx_free;
+ struct net_device_stats stats;
+ struct timer_list phy_timer_list;
+ const struct phy_info *phy;
+ u32 msg_enable;
+ struct mii_if_info mii_if;
+ unsigned int last_mii_status;
+ struct fs_enet_mii_bus *mii_bus;
+ int interrupt;
+
+ int duplex, speed; /* current settings */
+
+ /* event masks */
+ u32 ev_napi_rx; /* mask of NAPI rx events */
+ u32 ev_rx; /* rx event mask */
+ u32 ev_tx; /* tx event mask */
+ u32 ev_err; /* error event mask */
+
+ u16 bd_rx_empty; /* mask of BD rx empty */
+ u16 bd_rx_err; /* mask of BD rx errors */
+
+ union {
+ struct {
+ int idx; /* FEC1 = 0, FEC2 = 1 */
+ void *fecp; /* hw registers */
+ u32 hthi, htlo; /* state for multicast */
+ } fec;
+
+ struct {
+ int idx; /* FCC1-3 = 0-2 */
+ void *fccp; /* hw registers */
+ void *ep; /* parameter ram */
+ void *fcccp; /* hw registers cont. */
+ void *mem; /* FCC DPRAM */
+ u32 gaddrh, gaddrl; /* group address */
+ } fcc;
+
+ struct {
+ int idx; /* FEC1 = 0, FEC2 = 1 */
+ void *sccp; /* hw registers */
+ void *ep; /* parameter ram */
+ u32 hthi, htlo; /* state for multicast */
+ } scc;
+
+ };
+};
+
+/***************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location);
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
+
+void fs_mii_startup(struct net_device *dev);
+void fs_mii_shutdown(struct net_device *dev);
+void fs_mii_ack_int(struct net_device *dev);
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+
+void fs_init_bds(struct net_device *dev);
+void fs_cleanup_bds(struct net_device *dev);
+
+/***************************************************************************/
+
+#define DRV_MODULE_NAME "fs_enet"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "Aug 8, 2005"
+
+/***************************************************************************/
+
+int fs_enet_platform_init(void);
+void fs_enet_platform_cleanup(void);
+
+/***************************************************************************/
+
+/* buffer descriptor access macros */
+
+/* access macros */
+#if defined(CONFIG_CPM1)
+/* for a a CPM1 __raw_xxx's are sufficient */
+#define __cbd_out32(addr, x) __raw_writel(x, addr)
+#define __cbd_out16(addr, x) __raw_writew(x, addr)
+#define __cbd_in32(addr) __raw_readl(addr)
+#define __cbd_in16(addr) __raw_readw(addr)
+#else
+/* for others play it safe */
+#define __cbd_out32(addr, x) out_be32(addr, x)
+#define __cbd_out16(addr, x) out_be16(addr, x)
+#define __cbd_in32(addr) in_be32(addr)
+#define __cbd_in16(addr) in_be16(addr)
+#endif
+
+/* write */
+#define CBDW_SC(_cbd, _sc) __cbd_out16(&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen) __cbd_out16(&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr) __cbd_out32(&(_cbd)->cbd_bufaddr, (_bufaddr))
+
+/* read */
+#define CBDR_SC(_cbd) __cbd_in16(&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd) __cbd_in16(&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd) __cbd_in32(&(_cbd)->cbd_bufaddr)
+
+/* set bits */
+#define CBDS_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
+
+/* clear bits */
+#define CBDC_SC(_cbd, _sc) CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc))
+
+/*******************************************************************/
+
+extern const struct fs_ops fs_fec_ops;
+extern const struct fs_ops fs_fcc_ops;
+extern const struct fs_ops fs_scc_ops;
+
+/*******************************************************************/
+
+/* handy pointer to the immap */
+extern void *fs_enet_immap;
+
+/*******************************************************************/
+
+#endif
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
new file mode 100644
index 000000000000..a940b96433c7
--- /dev/null
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -0,0 +1,578 @@
+/*
+ * FCC driver for Motorola MPC82xx (PQ2).
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/* FCC access macros */
+
+#define __fcc_out32(addr, x) out_be32((unsigned *)addr, x)
+#define __fcc_out16(addr, x) out_be16((unsigned short *)addr, x)
+#define __fcc_out8(addr, x) out_8((unsigned char *)addr, x)
+#define __fcc_in32(addr) in_be32((unsigned *)addr)
+#define __fcc_in16(addr) in_be16((unsigned short *)addr)
+#define __fcc_in8(addr) in_8((unsigned char *)addr)
+
+/* parameter space */
+
+/* write, read, set bits, clear bits */
+#define W32(_p, _m, _v) __fcc_out32(&(_p)->_m, (_v))
+#define R32(_p, _m) __fcc_in32(&(_p)->_m)
+#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v))
+#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v))
+
+#define W16(_p, _m, _v) __fcc_out16(&(_p)->_m, (_v))
+#define R16(_p, _m) __fcc_in16(&(_p)->_m)
+#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v))
+#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v))
+
+#define W8(_p, _m, _v) __fcc_out8(&(_p)->_m, (_v))
+#define R8(_p, _m) __fcc_in8(&(_p)->_m)
+#define S8(_p, _m, _v) W8(_p, _m, R8(_p, _m) | (_v))
+#define C8(_p, _m, _v) W8(_p, _m, R8(_p, _m) & ~(_v))
+
+/*************************************************/
+
+#define FCC_MAX_MULTICAST_ADDRS 64
+
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end 0
+
+#define MAX_CR_CMD_LOOPS 10000
+
+static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 mcn, u32 op)
+{
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ cpm2_map_t *immap = fs_enet_immap;
+ cpm_cpm2_t *cpmp = &immap->im_cpm;
+ u32 v;
+ int i;
+
+ /* Currently I don't know what feature call will look like. But
+ I guess there'd be something like do_cpm_cmd() which will require page & sblock */
+ v = mk_cr_cmd(fpi->cp_page, fpi->cp_block, mcn, op);
+ W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
+ for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+ if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
+ break;
+
+ if (i >= MAX_CR_CMD_LOOPS) {
+ printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+ __FUNCTION__);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+ struct platform_device *pdev = to_platform_device(fep->dev);
+ struct resource *r;
+
+ /* Fill out IRQ field */
+ fep->interrupt = platform_get_irq(pdev, 0);
+
+ /* Attach the memory for the FCC Parameter RAM */
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
+ fep->fcc.ep = (void *)r->start;
+
+ if (fep->fcc.ep == NULL)
+ return -EINVAL;
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
+ fep->fcc.fccp = (void *)r->start;
+
+ if (fep->fcc.fccp == NULL)
+ return -EINVAL;
+
+ fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+
+ if (fep->fcc.fcccp == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
+#define FCC_RX_EVENT (FCC_ENET_RXF)
+#define FCC_TX_EVENT (FCC_ENET_TXB)
+#define FCC_ERR_EVENT_MSK (FCC_ENET_TXE | FCC_ENET_BSY)
+
+static int setup_data(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
+ if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
+ return -EINVAL;
+
+ fep->fcc.mem = (void *)fpi->mem_offset;
+
+ if (do_pd_setup(fep) != 0)
+ return -EINVAL;
+
+ fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
+ fep->ev_rx = FCC_RX_EVENT;
+ fep->ev_tx = FCC_TX_EVENT;
+ fep->ev_err = FCC_ERR_EVENT_MSK;
+
+ return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ fep->ring_base = dma_alloc_coherent(fep->dev,
+ (fpi->tx_ring + fpi->rx_ring) *
+ sizeof(cbd_t), &fep->ring_mem_addr,
+ GFP_KERNEL);
+ if (fep->ring_base == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ if (fep->ring_base)
+ dma_free_coherent(fep->dev,
+ (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+ fep->ring_base, fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ S32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_enet_t *ep = fep->fcc.ep;
+
+ W32(ep, fen_gaddrh, 0);
+ W32(ep, fen_gaddrl, 0);
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 *mac)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_enet_t *ep = fep->fcc.ep;
+ u16 taddrh, taddrm, taddrl;
+
+ taddrh = ((u16)mac[5] << 8) | mac[4];
+ taddrm = ((u16)mac[3] << 8) | mac[2];
+ taddrl = ((u16)mac[1] << 8) | mac[0];
+
+ W16(ep, fen_taddrh, taddrh);
+ W16(ep, fen_taddrm, taddrm);
+ W16(ep, fen_taddrl, taddrl);
+ fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR);
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+ fcc_enet_t *ep = fep->fcc.ep;
+
+ /* clear promiscuous always */
+ C32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+
+ /* if all multi or too many multicasts; just enable all */
+ if ((dev->flags & IFF_ALLMULTI) != 0 ||
+ dev->mc_count > FCC_MAX_MULTICAST_ADDRS) {
+
+ W32(ep, fen_gaddrh, 0xffffffff);
+ W32(ep, fen_gaddrl, 0xffffffff);
+ }
+
+ /* read back */
+ fep->fcc.gaddrh = R32(ep, fen_gaddrh);
+ fep->fcc.gaddrl = R32(ep, fen_gaddrl);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct dev_mc_list *pmc;
+
+ if ((dev->flags & IFF_PROMISC) == 0) {
+ set_multicast_start(dev);
+ for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ set_multicast_one(dev, pmc->dmi_addr);
+ set_multicast_finish(dev);
+ } else
+ set_promiscuous_mode(dev);
+}
+
+static void restart(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+ fcc_t *fccp = fep->fcc.fccp;
+ fcc_c_t *fcccp = fep->fcc.fcccp;
+ fcc_enet_t *ep = fep->fcc.ep;
+ dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
+ u16 paddrh, paddrm, paddrl;
+ u16 mem_addr;
+ const unsigned char *mac;
+ int i;
+
+ C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+ /* clear everything (slow & steady does it) */
+ for (i = 0; i < sizeof(*ep); i++)
+ __fcc_out8((char *)ep + i, 0);
+
+ /* get physical address */
+ rx_bd_base_phys = fep->ring_mem_addr;
+ tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring;
+
+ /* point to bds */
+ W32(ep, fen_genfcc.fcc_rbase, rx_bd_base_phys);
+ W32(ep, fen_genfcc.fcc_tbase, tx_bd_base_phys);
+
+ /* Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ W16(ep, fen_genfcc.fcc_mrblr, PKT_MAXBLR_SIZE);
+
+ W32(ep, fen_genfcc.fcc_rstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+ W32(ep, fen_genfcc.fcc_tstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+
+ /* Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+
+ mem_addr = (u32) fep->fcc.mem; /* de-fixup dpram offset */
+
+ W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
+ W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
+ W16(ep, fen_padptr, mem_addr + 64);
+
+ /* fill with special symbol... */
+ memset(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
+
+ W32(ep, fen_genfcc.fcc_rbptr, 0);
+ W32(ep, fen_genfcc.fcc_tbptr, 0);
+ W32(ep, fen_genfcc.fcc_rcrc, 0);
+ W32(ep, fen_genfcc.fcc_tcrc, 0);
+ W16(ep, fen_genfcc.fcc_res1, 0);
+ W32(ep, fen_genfcc.fcc_res2, 0);
+
+ /* no CAM */
+ W32(ep, fen_camptr, 0);
+
+ /* Set CRC preset and mask */
+ W32(ep, fen_cmask, 0xdebb20e3);
+ W32(ep, fen_cpres, 0xffffffff);
+
+ W32(ep, fen_crcec, 0); /* CRC Error counter */
+ W32(ep, fen_alec, 0); /* alignment error counter */
+ W32(ep, fen_disfc, 0); /* discard frame counter */
+ W16(ep, fen_retlim, 15); /* Retry limit threshold */
+ W16(ep, fen_pper, 0); /* Normal persistence */
+
+ /* set group address */
+ W32(ep, fen_gaddrh, fep->fcc.gaddrh);
+ W32(ep, fen_gaddrl, fep->fcc.gaddrh);
+
+ /* Clear hash filter tables */
+ W32(ep, fen_iaddrh, 0);
+ W32(ep, fen_iaddrl, 0);
+
+ /* Clear the Out-of-sequence TxBD */
+ W16(ep, fen_tfcstat, 0);
+ W16(ep, fen_tfclen, 0);
+ W32(ep, fen_tfcptr, 0);
+
+ W16(ep, fen_mflr, PKT_MAXBUF_SIZE); /* maximum frame length register */
+ W16(ep, fen_minflr, PKT_MINBUF_SIZE); /* minimum frame length register */
+
+ /* set address */
+ mac = dev->dev_addr;
+ paddrh = ((u16)mac[5] << 8) | mac[4];
+ paddrm = ((u16)mac[3] << 8) | mac[2];
+ paddrl = ((u16)mac[1] << 8) | mac[0];
+
+ W16(ep, fen_paddrh, paddrh);
+ W16(ep, fen_paddrm, paddrm);
+ W16(ep, fen_paddrl, paddrl);
+
+ W16(ep, fen_taddrh, 0);
+ W16(ep, fen_taddrm, 0);
+ W16(ep, fen_taddrl, 0);
+
+ W16(ep, fen_maxd1, 1520); /* maximum DMA1 length */
+ W16(ep, fen_maxd2, 1520); /* maximum DMA2 length */
+
+ /* Clear stat counters, in case we ever enable RMON */
+ W32(ep, fen_octc, 0);
+ W32(ep, fen_colc, 0);
+ W32(ep, fen_broc, 0);
+ W32(ep, fen_mulc, 0);
+ W32(ep, fen_uspc, 0);
+ W32(ep, fen_frgc, 0);
+ W32(ep, fen_ospc, 0);
+ W32(ep, fen_jbrc, 0);
+ W32(ep, fen_p64c, 0);
+ W32(ep, fen_p65c, 0);
+ W32(ep, fen_p128c, 0);
+ W32(ep, fen_p256c, 0);
+ W32(ep, fen_p512c, 0);
+ W32(ep, fen_p1024c, 0);
+
+ W16(ep, fen_rfthr, 0); /* Suggested by manual */
+ W16(ep, fen_rfcnt, 0);
+ W16(ep, fen_cftype, 0);
+
+ fs_init_bds(dev);
+
+ /* adjust to speed (for RMII mode) */
+ if (fpi->use_rmii) {
+ if (fep->speed == 100)
+ C8(fcccp, fcc_gfemr, 0x20);
+ else
+ S8(fcccp, fcc_gfemr, 0x20);
+ }
+
+ fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX);
+
+ /* clear events */
+ W16(fccp, fcc_fcce, 0xffff);
+
+ /* Enable interrupts we wish to service */
+ W16(fccp, fcc_fccm, FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+ /* Set GFMR to enable Ethernet operating mode */
+ W32(fccp, fcc_gfmr, FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+ /* set sync/delimiters */
+ W16(fccp, fcc_fdsr, 0xd555);
+
+ W32(fccp, fcc_fpsmr, FCC_PSMR_ENCRC);
+
+ if (fpi->use_rmii)
+ S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
+
+ /* adjust to duplex mode */
+ if (fep->duplex)
+ S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+ else
+ C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+
+ S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+static void stop(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ /* stop ethernet */
+ C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+ /* clear events */
+ W16(fccp, fcc_fcce, 0xffff);
+
+ /* clear interrupt mask */
+ W16(fccp, fcc_fccm, 0);
+
+ 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);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ return (u32)R16(fccp, fcc_fcce);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ W16(fccp, fcc_fcce, int_events & 0xffff);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t))
+ return -EINVAL;
+
+ memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
+ p = (char *)p + sizeof(fcc_t);
+
+ memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
+ p = (char *)p + sizeof(fcc_c_t);
+
+ memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
+
+ return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+ return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t);
+}
+
+/* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either. Also, To workaround 8260 device erratum
+ * CPM37, we must disable and then re-enable the transmitter
+ * following a Late Collision, Underrun, or Retry Limit error.
+ */
+void tx_restart(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fcc_t *fccp = fep->fcc.fccp;
+
+ C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+ udelay(10);
+ S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+
+ fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX);
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fcc_ops = {
+ .setup_data = setup_data,
+ .cleanup_data = cleanup_data,
+ .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,
+ .rx_bd_done = rx_bd_done,
+ .tx_kickstart = tx_kickstart,
+ .get_int_events = get_int_events,
+ .clear_int_events = clear_int_events,
+ .ev_error = ev_error,
+ .get_regs = get_regs,
+ .get_regs_len = get_regs_len,
+ .tx_restart = tx_restart,
+ .allocate_bd = allocate_bd,
+ .free_bd = free_bd,
+};
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
new file mode 100644
index 000000000000..5ef4e845a387
--- /dev/null
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -0,0 +1,653 @@
+/*
+ * Freescale Ethernet controllers
+ *
+ * Copyright (c) 2005 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#endif
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+#if defined(CONFIG_CPM1)
+/* for a CPM1 __raw_xxx's are sufficient */
+#define __fs_out32(addr, x) __raw_writel(x, addr)
+#define __fs_out16(addr, x) __raw_writew(x, addr)
+#define __fs_in32(addr) __raw_readl(addr)
+#define __fs_in16(addr) __raw_readw(addr)
+#else
+/* for others play it safe */
+#define __fs_out32(addr, x) out_be32(addr, x)
+#define __fs_out16(addr, x) out_be16(addr, x)
+#define __fs_in32(addr) in_be32(addr)
+#define __fs_in16(addr) in_be16(addr)
+#endif
+
+/* write */
+#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
+
+/* read */
+#define FR(_fecp, _reg) __fs_in32(&(_fecp)->fec_ ## _reg)
+
+/* set bits */
+#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
+
+/* clear bits */
+#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
+
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY 0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS 64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
+#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
+#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
+#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
+#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
+#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
+#define FEC_ENET_RXF 0x02000000U /* Full frame received */
+#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
+#define FEC_ENET_MII 0x00800000U /* MII interrupt */
+#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
+
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+#define FEC_ECNTRL_RESET 0x00000001
+
+#define FEC_RCNTRL_BC_REJ 0x00000010
+#define FEC_RCNTRL_PROM 0x00000008
+#define FEC_RCNTRL_MII_MODE 0x00000004
+#define FEC_RCNTRL_DRT 0x00000002
+#define FEC_RCNTRL_LOOP 0x00000001
+
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_GTS 0x00000001
+
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end 0
+
+#define FEC_MII_LOOPS 10000
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY 50
+
+static int whack_reset(fec_t * fecp)
+{
+ int i;
+
+ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
+ for (i = 0; i < FEC_RESET_DELAY; i++) {
+ if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
+ return 0; /* OK */
+ udelay(1);
+ }
+
+ return -1;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+ struct platform_device *pdev = to_platform_device(fep->dev);
+ struct resource *r;
+
+ /* Fill out IRQ field */
+ fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ fep->fec.fecp =(void*)r->start;
+
+ if(fep->fec.fecp == NULL)
+ return -EINVAL;
+
+ return 0;
+
+}
+
+#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
+#define FEC_RX_EVENT (FEC_ENET_RXF)
+#define FEC_TX_EVENT (FEC_ENET_TXF)
+#define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \
+ FEC_ENET_BABT | FEC_ENET_EBERR)
+
+static int setup_data(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (do_pd_setup(fep) != 0)
+ return -EINVAL;
+
+ fep->fec.hthi = 0;
+ fep->fec.htlo = 0;
+
+ fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
+ fep->ev_rx = FEC_RX_EVENT;
+ fep->ev_tx = FEC_TX_EVENT;
+ fep->ev_err = FEC_ERR_EVENT_MSK;
+
+ return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ fep->ring_base = dma_alloc_coherent(fep->dev,
+ (fpi->tx_ring + fpi->rx_ring) *
+ sizeof(cbd_t), &fep->ring_mem_addr,
+ GFP_KERNEL);
+ if (fep->ring_base == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ if(fep->ring_base)
+ dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring)
+ * sizeof(cbd_t),
+ fep->ring_base,
+ fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ fep->fec.hthi = 0;
+ fep->fec.htlo = 0;
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 *mac)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ int temp, hash_index, i, j;
+ u32 crc, csrVal;
+ u8 byte, msb;
+
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ byte = mac[i];
+ for (j = 0; j < 8; j++) {
+ msb = crc >> 31;
+ crc <<= 1;
+ if (msb ^ (byte & 0x1))
+ crc ^= FEC_CRC_POLY;
+ byte >>= 1;
+ }
+ }
+
+ temp = (crc & 0x3f) >> 1;
+ hash_index = ((temp & 0x01) << 4) |
+ ((temp & 0x02) << 2) |
+ ((temp & 0x04)) |
+ ((temp & 0x08) >> 2) |
+ ((temp & 0x10) >> 4);
+ csrVal = 1 << hash_index;
+ if (crc & 1)
+ fep->fec.hthi |= csrVal;
+ else
+ fep->fec.htlo |= csrVal;
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ /* if all multi or too many multicasts; just enable all */
+ if ((dev->flags & IFF_ALLMULTI) != 0 ||
+ dev->mc_count > FEC_MAX_MULTICAST_ADDRS) {
+ fep->fec.hthi = 0xffffffffU;
+ fep->fec.htlo = 0xffffffffU;
+ }
+
+ FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
+ FW(fecp, hash_table_high, fep->fec.hthi);
+ FW(fecp, hash_table_low, fep->fec.htlo);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct dev_mc_list *pmc;
+
+ if ((dev->flags & IFF_PROMISC) == 0) {
+ set_multicast_start(dev);
+ for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ set_multicast_one(dev, pmc->dmi_addr);
+ set_multicast_finish(dev);
+ } else
+ set_promiscuous_mode(dev);
+}
+
+static void restart(struct net_device *dev)
+{
+#ifdef CONFIG_DUET
+ immap_t *immap = fs_enet_immap;
+ u32 cptr;
+#endif
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+ const struct fs_platform_info *fpi = fep->fpi;
+ dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
+ int r;
+ u32 addrhi, addrlo;
+
+ r = whack_reset(fep->fec.fecp);
+ if (r != 0)
+ printk(KERN_ERR DRV_MODULE_NAME
+ ": %s FEC Reset FAILED!\n", dev->name);
+
+ /*
+ * Set station address.
+ */
+ addrhi = ((u32) dev->dev_addr[0] << 24) |
+ ((u32) dev->dev_addr[1] << 16) |
+ ((u32) dev->dev_addr[2] << 8) |
+ (u32) dev->dev_addr[3];
+ addrlo = ((u32) dev->dev_addr[4] << 24) |
+ ((u32) dev->dev_addr[5] << 16);
+ FW(fecp, addr_low, addrhi);
+ FW(fecp, addr_high, addrlo);
+
+ /*
+ * Reset all multicast.
+ */
+ FW(fecp, hash_table_high, fep->fec.hthi);
+ FW(fecp, hash_table_low, fep->fec.htlo);
+
+ /*
+ * Set maximum receive buffer size.
+ */
+ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
+ FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+
+ /* get physical address */
+ rx_bd_base_phys = fep->ring_mem_addr;
+ tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring;
+
+ /*
+ * Set receive and transmit descriptor base.
+ */
+ FW(fecp, r_des_start, rx_bd_base_phys);
+ FW(fecp, x_des_start, tx_bd_base_phys);
+
+ fs_init_bds(dev);
+
+ /*
+ * Enable big endian and don't care about SDMA FC.
+ */
+ FW(fecp, fun_code, 0x78000000);
+
+ /*
+ * Set MII speed.
+ */
+ FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+
+ /*
+ * Clear any outstanding interrupt.
+ */
+ FW(fecp, ievent, 0xffc0);
+ FW(fecp, ivec, (fep->interrupt / 2) << 29);
+
+
+ /*
+ * adjust to speed (only for DUET & RMII)
+ */
+#ifdef CONFIG_DUET
+ if (fpi->use_rmii) {
+ cptr = in_be32(&immap->im_cpm.cp_cptr);
+ switch (fs_get_fec_index(fpi->fs_no)) {
+ case 0:
+ cptr |= 0x100;
+ if (fep->speed == 10)
+ cptr |= 0x0000010;
+ else if (fep->speed == 100)
+ cptr &= ~0x0000010;
+ break;
+ case 1:
+ cptr |= 0x80;
+ if (fep->speed == 10)
+ cptr |= 0x0000008;
+ else if (fep->speed == 100)
+ cptr &= ~0x0000008;
+ break;
+ default:
+ BUG(); /* should never happen */
+ break;
+ }
+ out_be32(&immap->im_cpm.cp_cptr, cptr);
+ }
+#endif
+
+ FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ /*
+ * adjust to duplex mode
+ */
+ if (fep->duplex) {
+ FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
+ FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
+ } else {
+ FS(fecp, r_cntrl, FEC_RCNTRL_DRT);
+ FC(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
+ }
+
+ /*
+ * Enable interrupts we wish to service.
+ */
+ FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB |
+ FEC_ENET_RXF | FEC_ENET_RXB);
+
+ /*
+ * And last, enable the transmit and receive processing.
+ */
+ FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, r_des_active, 0x01000000);
+}
+
+static void stop(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+ struct fs_enet_mii_bus *bus = fep->mii_bus;
+ const struct fs_mii_bus_info *bi = bus->bus_info;
+ int i;
+
+ if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
+ return; /* already down */
+
+ FW(fecp, x_cntrl, 0x01); /* Graceful transmit stop */
+ for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) &&
+ i < FEC_RESET_DELAY; i++)
+ udelay(1);
+
+ if (i == FEC_RESET_DELAY)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s FEC timeout on graceful transmit stop\n",
+ dev->name);
+ /*
+ * Disable FEC. Let only MII interrupts.
+ */
+ FW(fecp, imask, 0);
+ FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN);
+
+ fs_cleanup_bds(dev);
+
+ /* shut down FEC1? that's where the mii bus is */
+ if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
+ FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, ievent, FEC_ENET_MII);
+ FW(fecp, mii_speed, bus->fec.mii_speed);
+ }
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+ 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);
+ }
+}
+
+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);
+ fec_t *fecp = fep->fec.fecp;
+
+ FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FW(fecp, r_des_active, 0x01000000);
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FW(fecp, x_des_active, 0x01000000);
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ return FR(fecp, ievent) & FR(fecp, imask);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ fec_t *fecp = fep->fec.fecp;
+
+ FW(fecp, ievent, int_events);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (*sizep < sizeof(fec_t))
+ return -EINVAL;
+
+ memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t));
+
+ return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+ return sizeof(fec_t);
+}
+
+void tx_restart(struct net_device *dev)
+{
+ /* nothing */
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fec_ops = {
+ .setup_data = setup_data,
+ .cleanup_data = cleanup_data,
+ .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,
+ .rx_bd_done = rx_bd_done,
+ .tx_kickstart = tx_kickstart,
+ .get_int_events = get_int_events,
+ .clear_int_events = clear_int_events,
+ .ev_error = ev_error,
+ .get_regs = get_regs,
+ .get_regs_len = get_regs_len,
+ .tx_restart = tx_restart,
+ .allocate_bd = allocate_bd,
+ .free_bd = free_bd,
+};
+
+/***********************************************************************/
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+ fec_t *fecp = bus->fec.fecp;
+ int i, ret = -1;
+
+ if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+ BUG();
+
+ /* Add PHY address to register command. */
+ FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS) {
+ FW(fecp, ievent, FEC_ENET_MII);
+ ret = FR(fecp, mii_data) & 0xffff;
+ }
+
+ return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
+{
+ fec_t *fecp = bus->fec.fecp;
+ int i;
+
+ /* this must never happen */
+ if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+ BUG();
+
+ /* Add PHY address to register command. */
+ FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
+
+ for (i = 0; i < FEC_MII_LOOPS; i++)
+ if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+ break;
+
+ if (i < FEC_MII_LOOPS)
+ FW(fecp, ievent, FEC_ENET_MII);
+}
+
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
+{
+ bd_t *bd = (bd_t *)__res;
+ const struct fs_mii_bus_info *bi = bus->bus_info;
+ fec_t *fecp;
+
+ if (bi->id != 0)
+ return -1;
+
+ bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
+ bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
+ & 0x3F) << 1;
+
+ fecp = bus->fec.fecp;
+
+ FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+ FW(fecp, ievent, FEC_ENET_MII);
+ FW(fecp, mii_speed, bus->fec.mii_speed);
+
+ bus->mii_read = mii_read;
+ bus->mii_write = mii_write;
+
+ return 0;
+}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
new file mode 100644
index 000000000000..d8c6e9cadcf5
--- /dev/null
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -0,0 +1,524 @@
+/*
+ * Ethernet on Serial Communications Controller (SCC) driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#endif
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+#if defined(CONFIG_CPM1)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __fs_out32(addr, x) __raw_writel(x, addr)
+#define __fs_out16(addr, x) __raw_writew(x, addr)
+#define __fs_out8(addr, x) __raw_writeb(x, addr)
+#define __fs_in32(addr) __raw_readl(addr)
+#define __fs_in16(addr) __raw_readw(addr)
+#define __fs_in8(addr) __raw_readb(addr)
+#else
+/* for others play it safe */
+#define __fs_out32(addr, x) out_be32(addr, x)
+#define __fs_out16(addr, x) out_be16(addr, x)
+#define __fs_in32(addr) in_be32(addr)
+#define __fs_in16(addr) in_be16(addr)
+#endif
+
+/* write, read, set bits, clear bits */
+#define W32(_p, _m, _v) __fs_out32(&(_p)->_m, (_v))
+#define R32(_p, _m) __fs_in32(&(_p)->_m)
+#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v))
+#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v))
+
+#define W16(_p, _m, _v) __fs_out16(&(_p)->_m, (_v))
+#define R16(_p, _m) __fs_in16(&(_p)->_m)
+#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v))
+#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v))
+
+#define W8(_p, _m, _v) __fs_out8(&(_p)->_m, (_v))
+#define R8(_p, _m) __fs_in8(&(_p)->_m)
+#define S8(_p, _m, _v) W8(_p, _m, R8(_p, _m) | (_v))
+#define C8(_p, _m, _v) W8(_p, _m, R8(_p, _m) & ~(_v))
+
+#define SCC_MAX_MULTICAST_ADDRS 64
+
+/*
+ * Delay to wait for SCC reset command to complete (in us)
+ */
+#define SCC_RESET_DELAY 50
+#define MAX_CR_CMD_LOOPS 10000
+
+static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
+{
+ cpm8xx_t *cpmp = &((immap_t *)fs_enet_immap)->im_cpm;
+ u32 v, ch;
+ int i = 0;
+
+ ch = fep->scc.idx << 2;
+ v = mk_cr_cmd(ch, op);
+ W16(cpmp, cp_cpcr, v | CPM_CR_FLG);
+ for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+ if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
+ break;
+
+ if (i >= MAX_CR_CMD_LOOPS) {
+ printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+ __FUNCTION__);
+ return 1;
+ }
+ return 0;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+ struct platform_device *pdev = to_platform_device(fep->dev);
+ struct resource *r;
+
+ /* Fill out IRQ field */
+ fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ fep->scc.sccp = (void *)r->start;
+
+ if (fep->scc.sccp == NULL)
+ return -EINVAL;
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
+ fep->scc.ep = (void *)r->start;
+
+ if (fep->scc.ep == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+#define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB)
+#define SCC_RX_EVENT (SCCE_ENET_RXF)
+#define SCC_TX_EVENT (SCCE_ENET_TXB)
+#define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY)
+
+static int setup_data(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ fep->scc.idx = fs_get_scc_index(fpi->fs_no);
+ if ((unsigned int)fep->fcc.idx > 4) /* max 4 SCCs */
+ return -EINVAL;
+
+ do_pd_setup(fep);
+
+ fep->scc.hthi = 0;
+ fep->scc.htlo = 0;
+
+ fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
+ fep->ev_rx = SCC_RX_EVENT;
+ fep->ev_tx = SCC_TX_EVENT;
+ fep->ev_err = SCC_ERR_EVENT_MSK;
+
+ return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ const struct fs_platform_info *fpi = fep->fpi;
+
+ fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) *
+ sizeof(cbd_t), 8);
+ if (IS_DPERR(fep->ring_mem_addr))
+ return -ENOMEM;
+
+ fep->ring_base = cpm_dpram_addr(fep->ring_mem_addr);
+
+ return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (fep->ring_base)
+ cpm_dpfree(fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+
+ S16(sccp, scc_psmr, SCC_PSMR_PRO);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_enet_t *ep = fep->scc.ep;
+
+ W16(ep, sen_gaddr1, 0);
+ W16(ep, sen_gaddr2, 0);
+ W16(ep, sen_gaddr3, 0);
+ W16(ep, sen_gaddr4, 0);
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 * mac)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_enet_t *ep = fep->scc.ep;
+ u16 taddrh, taddrm, taddrl;
+
+ taddrh = ((u16) mac[5] << 8) | mac[4];
+ taddrm = ((u16) mac[3] << 8) | mac[2];
+ taddrl = ((u16) mac[1] << 8) | mac[0];
+
+ W16(ep, sen_taddrh, taddrh);
+ W16(ep, sen_taddrm, taddrm);
+ W16(ep, sen_taddrl, taddrl);
+ scc_cr_cmd(fep, CPM_CR_SET_GADDR);
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+ scc_enet_t *ep = fep->scc.ep;
+
+ /* clear promiscuous always */
+ C16(sccp, scc_psmr, SCC_PSMR_PRO);
+
+ /* if all multi or too many multicasts; just enable all */
+ if ((dev->flags & IFF_ALLMULTI) != 0 ||
+ dev->mc_count > SCC_MAX_MULTICAST_ADDRS) {
+
+ W16(ep, sen_gaddr1, 0xffff);
+ W16(ep, sen_gaddr2, 0xffff);
+ W16(ep, sen_gaddr3, 0xffff);
+ W16(ep, sen_gaddr4, 0xffff);
+ }
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct dev_mc_list *pmc;
+
+ if ((dev->flags & IFF_PROMISC) == 0) {
+ set_multicast_start(dev);
+ for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+ set_multicast_one(dev, pmc->dmi_addr);
+ set_multicast_finish(dev);
+ } else
+ set_promiscuous_mode(dev);
+}
+
+/*
+ * This function is called to start or restart the FEC during a link
+ * change. This only happens when switching between half and full
+ * duplex.
+ */
+static void restart(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+ scc_enet_t *ep = fep->scc.ep;
+ const struct fs_platform_info *fpi = fep->fpi;
+ u16 paddrh, paddrm, paddrl;
+ const unsigned char *mac;
+ int i;
+
+ C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* clear everything (slow & steady does it) */
+ for (i = 0; i < sizeof(*ep); i++)
+ __fs_out8((char *)ep + i, 0);
+
+ /* point to bds */
+ W16(ep, sen_genscc.scc_rbase, fep->ring_mem_addr);
+ W16(ep, sen_genscc.scc_tbase,
+ fep->ring_mem_addr + sizeof(cbd_t) * fpi->rx_ring);
+
+ /* Initialize function code registers for big-endian.
+ */
+ W8(ep, sen_genscc.scc_rfcr, SCC_EB);
+ W8(ep, sen_genscc.scc_tfcr, SCC_EB);
+
+ /* Set maximum bytes per receive buffer.
+ * This appears to be an Ethernet frame size, not the buffer
+ * fragment size. It must be a multiple of four.
+ */
+ W16(ep, sen_genscc.scc_mrblr, 0x5f0);
+
+ /* Set CRC preset and mask.
+ */
+ W32(ep, sen_cpres, 0xffffffff);
+ W32(ep, sen_cmask, 0xdebb20e3);
+
+ W32(ep, sen_crcec, 0); /* CRC Error counter */
+ W32(ep, sen_alec, 0); /* alignment error counter */
+ W32(ep, sen_disfc, 0); /* discard frame counter */
+
+ W16(ep, sen_pads, 0x8888); /* Tx short frame pad character */
+ W16(ep, sen_retlim, 15); /* Retry limit threshold */
+
+ W16(ep, sen_maxflr, 0x5ee); /* maximum frame length register */
+
+ W16(ep, sen_minflr, PKT_MINBUF_SIZE); /* minimum frame length register */
+
+ W16(ep, sen_maxd1, 0x000005f0); /* maximum DMA1 length */
+ W16(ep, sen_maxd2, 0x000005f0); /* maximum DMA2 length */
+
+ /* Clear hash tables.
+ */
+ W16(ep, sen_gaddr1, 0);
+ W16(ep, sen_gaddr2, 0);
+ W16(ep, sen_gaddr3, 0);
+ W16(ep, sen_gaddr4, 0);
+ W16(ep, sen_iaddr1, 0);
+ W16(ep, sen_iaddr2, 0);
+ W16(ep, sen_iaddr3, 0);
+ W16(ep, sen_iaddr4, 0);
+
+ /* set address
+ */
+ mac = dev->dev_addr;
+ paddrh = ((u16) mac[5] << 8) | mac[4];
+ paddrm = ((u16) mac[3] << 8) | mac[2];
+ paddrl = ((u16) mac[1] << 8) | mac[0];
+
+ W16(ep, sen_paddrh, paddrh);
+ W16(ep, sen_paddrm, paddrm);
+ W16(ep, sen_paddrl, paddrl);
+
+ W16(ep, sen_pper, 0);
+ W16(ep, sen_taddrl, 0);
+ W16(ep, sen_taddrm, 0);
+ W16(ep, sen_taddrh, 0);
+
+ fs_init_bds(dev);
+
+ scc_cr_cmd(fep, CPM_CR_INIT_TRX);
+
+ W16(sccp, scc_scce, 0xffff);
+
+ /* Enable interrupts we wish to service.
+ */
+ W16(sccp, scc_sccm, SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+ /* Set GSMR_H to enable all normal operating modes.
+ * Set GSMR_L to enable Ethernet to MC68160.
+ */
+ W32(sccp, scc_gsmrh, 0);
+ W32(sccp, scc_gsmrl,
+ SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 |
+ SCC_GSMRL_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ W16(sccp, scc_dsr, 0xd555);
+
+ /* Set processing mode. Use Ethernet CRC, catch broadcast, and
+ * start frame search 22 bit times after RENA.
+ */
+ W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+ /* Set full duplex mode if needed */
+ if (fep->duplex)
+ S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
+
+ S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+
+static void stop(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+ int i;
+
+ for (i = 0; (R16(sccp, scc_sccm) == 0) && i < SCC_RESET_DELAY; i++)
+ udelay(1);
+
+ if (i == SCC_RESET_DELAY)
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s SCC timeout on graceful transmit stop\n",
+ dev->name);
+
+ W16(sccp, scc_sccm, 0);
+ C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ fs_cleanup_bds(dev);
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+ 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);
+ }
+}
+
+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);
+ scc_t *sccp = fep->scc.sccp;
+
+ W16(sccp, scc_scce, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+
+ S16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+
+ C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+ /* nothing */
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+
+ return (u32) R16(sccp, scc_scce);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+ scc_t *sccp = fep->scc.sccp;
+
+ W16(sccp, scc_scce, int_events & 0xffff);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+ printk(KERN_WARNING DRV_MODULE_NAME
+ ": %s SCC ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+static int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ if (*sizep < sizeof(scc_t) + sizeof(scc_enet_t))
+ return -EINVAL;
+
+ memcpy_fromio(p, fep->scc.sccp, sizeof(scc_t));
+ p = (char *)p + sizeof(scc_t);
+
+ memcpy_fromio(p, fep->scc.ep, sizeof(scc_enet_t));
+
+ return 0;
+}
+
+static int get_regs_len(struct net_device *dev)
+{
+ return sizeof(scc_t) + sizeof(scc_enet_t);
+}
+
+static void tx_restart(struct net_device *dev)
+{
+ struct fs_enet_private *fep = netdev_priv(dev);
+
+ scc_cr_cmd(fep, CPM_CR_RESTART_TX);
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_scc_ops = {
+ .setup_data = setup_data,
+ .cleanup_data = cleanup_data,
+ .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,
+ .rx_bd_done = rx_bd_done,
+ .tx_kickstart = tx_kickstart,
+ .get_int_events = get_int_events,
+ .clear_int_events = clear_int_events,
+ .ev_error = ev_error,
+ .get_regs = get_regs,
+ .get_regs_len = get_regs_len,
+ .tx_restart = tx_restart,
+ .allocate_bd = allocate_bd,
+ .free_bd = free_bd,
+};
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
new file mode 100644
index 000000000000..24a5e2e23d18
--- /dev/null
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -0,0 +1,405 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+#ifdef CONFIG_8xx
+static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+{
+ immap_t *im = (immap_t *)fs_enet_immap;
+ void *dir, *dat, *ppar;
+ int adv;
+ u8 msk;
+
+ switch (port) {
+ case fsiop_porta:
+ dir = &im->im_ioport.iop_padir;
+ dat = &im->im_ioport.iop_padat;
+ ppar = &im->im_ioport.iop_papar;
+ break;
+
+ case fsiop_portb:
+ dir = &im->im_cpm.cp_pbdir;
+ dat = &im->im_cpm.cp_pbdat;
+ ppar = &im->im_cpm.cp_pbpar;
+ break;
+
+ case fsiop_portc:
+ dir = &im->im_ioport.iop_pcdir;
+ dat = &im->im_ioport.iop_pcdat;
+ ppar = &im->im_ioport.iop_pcpar;
+ break;
+
+ case fsiop_portd:
+ dir = &im->im_ioport.iop_pddir;
+ dat = &im->im_ioport.iop_pddat;
+ ppar = &im->im_ioport.iop_pdpar;
+ break;
+
+ case fsiop_porte:
+ dir = &im->im_cpm.cp_pedir;
+ dat = &im->im_cpm.cp_pedat;
+ ppar = &im->im_cpm.cp_pepar;
+ break;
+
+ default:
+ printk(KERN_ERR DRV_MODULE_NAME
+ "Illegal port value %d!\n", port);
+ return -EINVAL;
+ }
+
+ adv = bit >> 3;
+ dir = (char *)dir + adv;
+ dat = (char *)dat + adv;
+ ppar = (char *)ppar + adv;
+
+ msk = 1 << (7 - (bit & 7));
+ if ((in_8(ppar) & msk) != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ "pin %d on port %d is not general purpose!\n", bit, port);
+ return -EINVAL;
+ }
+
+ *dirp = dir;
+ *datp = dat;
+ *mskp = msk;
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_8260
+static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+{
+ iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
+ void *dir, *dat, *ppar;
+ int adv;
+ u8 msk;
+
+ switch (port) {
+ case fsiop_porta:
+ dir = &io->iop_pdira;
+ dat = &io->iop_pdata;
+ ppar = &io->iop_ppara;
+ break;
+
+ case fsiop_portb:
+ dir = &io->iop_pdirb;
+ dat = &io->iop_pdatb;
+ ppar = &io->iop_pparb;
+ break;
+
+ case fsiop_portc:
+ dir = &io->iop_pdirc;
+ dat = &io->iop_pdatc;
+ ppar = &io->iop_pparc;
+ break;
+
+ case fsiop_portd:
+ dir = &io->iop_pdird;
+ dat = &io->iop_pdatd;
+ ppar = &io->iop_ppard;
+ break;
+
+ default:
+ printk(KERN_ERR DRV_MODULE_NAME
+ "Illegal port value %d!\n", port);
+ return -EINVAL;
+ }
+
+ adv = bit >> 3;
+ dir = (char *)dir + adv;
+ dat = (char *)dat + adv;
+ ppar = (char *)ppar + adv;
+
+ msk = 1 << (7 - (bit & 7));
+ if ((in_8(ppar) & msk) != 0) {
+ printk(KERN_ERR DRV_MODULE_NAME
+ "pin %d on port %d is not general purpose!\n", bit, port);
+ return -EINVAL;
+ }
+
+ *dirp = dir;
+ *datp = dat;
+ *mskp = msk;
+
+ return 0;
+}
+#endif
+
+static inline void bb_set(u8 *p, u8 m)
+{
+ out_8(p, in_8(p) | m);
+}
+
+static inline void bb_clr(u8 *p, u8 m)
+{
+ out_8(p, in_8(p) & ~m);
+}
+
+static inline int bb_read(u8 *p, u8 m)
+{
+ return (in_8(p) & m) != 0;
+}
+
+static inline void mdio_active(struct fs_enet_mii_bus *bus)
+{
+ bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+{
+ bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline int mdio_read(struct fs_enet_mii_bus *bus)
+{
+ return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+{
+ if (what)
+ bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+ else
+ bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+{
+ if (what)
+ bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+ else
+ bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+}
+
+static inline void mii_delay(struct fs_enet_mii_bus *bus)
+{
+ udelay(bus->bus_info->i.bitbang.delay);
+}
+
+/* Utility to send the preamble, address, and register (common to read and write). */
+static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
+{
+ int j;
+
+ /*
+ * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+ * The IEEE spec says this is a PHY optional requirement. The AMD
+ * 79C874 requires one after power up and one after a MII communications
+ * error. This means that we are doing more preambles than we need,
+ * but it is safer and will be much more robust.
+ */
+
+ mdio_active(bus);
+ mdio(bus, 1);
+ for (j = 0; j < 32; j++) {
+ mdc(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ }
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ mdc(bus, 0);
+ mdio(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 0);
+ mdio(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 0);
+ mdio(bus, read);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 0);
+ mdio(bus, !read);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+
+ /* send the PHY address */
+ for (j = 0; j < 5; j++) {
+ mdc(bus, 0);
+ mdio(bus, (addr & 0x10) != 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ addr <<= 1;
+ }
+
+ /* send the register address */
+ for (j = 0; j < 5; j++) {
+ mdc(bus, 0);
+ mdio(bus, (reg & 0x10) != 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ reg <<= 1;
+ }
+}
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+ u16 rdreg;
+ int ret, j;
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+
+ bitbang_pre(bus, 1, addr, reg);
+
+ /* tri-state our MDIO I/O pin so we can read */
+ mdc(bus, 0);
+ mdio_tristate(bus);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+
+ /* check the turnaround bit: the PHY should be driving it to zero */
+ if (mdio_read(bus) != 0) {
+ /* PHY didn't drive TA low */
+ for (j = 0; j < 32; j++) {
+ mdc(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ }
+ ret = -1;
+ goto out;
+ }
+
+ mdc(bus, 0);
+ mii_delay(bus);
+
+ /* read 16 bits of register data, MSB first */
+ rdreg = 0;
+ for (j = 0; j < 16; j++) {
+ mdc(bus, 1);
+ mii_delay(bus);
+ rdreg <<= 1;
+ rdreg |= mdio_read(bus);
+ mdc(bus, 0);
+ mii_delay(bus);
+ }
+
+ mdc(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+
+ ret = rdreg;
+out:
+ return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+ int j;
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+ u16 value = val & 0xffff;
+
+ bitbang_pre(bus, 0, addr, reg);
+
+ /* send the turnaround (10) */
+ mdc(bus, 0);
+ mdio(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ mdc(bus, 0);
+ mdio(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+
+ /* write 16 bits of register data, MSB first */
+ for (j = 0; j < 16; j++) {
+ mdc(bus, 0);
+ mdio(bus, (value & 0x8000) != 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+ value <<= 1;
+ }
+
+ /*
+ * Tri-state the MDIO line.
+ */
+ mdio_tristate(bus);
+ mdc(bus, 0);
+ mii_delay(bus);
+ mdc(bus, 1);
+ mii_delay(bus);
+}
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+{
+ const struct fs_mii_bus_info *bi = bus->bus_info;
+ int r;
+
+ r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
+ &bus->bitbang.mdio_dat,
+ &bus->bitbang.mdio_msk,
+ bi->i.bitbang.mdio_port,
+ bi->i.bitbang.mdio_bit);
+ if (r != 0)
+ return r;
+
+ r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
+ &bus->bitbang.mdc_dat,
+ &bus->bitbang.mdc_msk,
+ bi->i.bitbang.mdc_port,
+ bi->i.bitbang.mdc_bit);
+ if (r != 0)
+ return r;
+
+ bus->mii_read = mii_read;
+ bus->mii_write = mii_write;
+
+ return 0;
+}
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c
new file mode 100644
index 000000000000..b3e192d612e5
--- /dev/null
+++ b/drivers/net/fs_enet/mii-fixed.c
@@ -0,0 +1,92 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+static const u16 mii_regs[7] = {
+ 0x3100,
+ 0x786d,
+ 0x0fff,
+ 0x0fff,
+ 0x01e1,
+ 0x45e1,
+ 0x0003,
+};
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+ int ret = 0;
+
+ if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
+ return -1;
+
+ if (location != 5)
+ ret = mii_regs[location];
+ else
+ ret = bus->fixed.lpa;
+
+ return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+ /* do nothing */
+}
+
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
+{
+ const struct fs_mii_bus_info *bi = bus->bus_info;
+
+ bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */
+
+ /* if speed is fixed at 10Mb, remove 100Mb modes */
+ if (bi->i.fixed.speed == 10)
+ bus->fixed.lpa &= ~LPA_100;
+
+ /* if duplex is half, remove full duplex modes */
+ if (bi->i.fixed.duplex == 0)
+ bus->fixed.lpa &= ~LPA_DUPLEX;
+
+ bus->mii_read = mii_read;
+ bus->mii_write = mii_write;
+
+ return 0;
+}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 6518334b9280..962580f2c4ab 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -29,12 +29,7 @@
* define the configuration needed by the board are defined in a
* board structure in arch/ppc/platforms (though I do not
* discount the possibility that other architectures could one
- * day be supported. One assumption the driver currently makes
- * is that the PHY is configured in such a way to advertise all
- * capabilities. This is a sensible default, and on certain
- * PHYs, changing this default encounters substantial errata
- * issues. Future versions may remove this requirement, but for
- * now, it is best for the firmware to ensure this is the case.
+ * day be supported.
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
@@ -47,7 +42,7 @@
* corresponding bit in the IMASK register is also set (if
* interrupt coalescing is active, then the interrupt may not
* happen immediately, but will wait until either a set number
- * of frames or amount of time have passed.). In NAPI, the
+ * of frames or amount of time have passed). In NAPI, the
* interrupt handler will signal there is work to be done, and
* exit. Without NAPI, the packet(s) will be handled
* immediately. Both methods will start at the last known empty
@@ -75,6 +70,7 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -85,7 +81,7 @@
#include <linux/if_vlan.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
@@ -97,9 +93,11 @@
#include <linux/version.h>
#include <linux/dma-mapping.h>
#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
#define TX_TIMEOUT (1*HZ)
#define SKB_ALLOC_TIMEOUT 1000000
@@ -113,9 +111,8 @@
#endif
const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
-int startup_gfar(struct net_device *dev);
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void gfar_timeout(struct net_device *dev);
@@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
static void adjust_link(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
static int gfar_probe(struct device *device);
static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
@@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *dev, int *budget);
#endif
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *priv)
else
return 0;
}
+
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
static int gfar_probe(struct device *device)
{
u32 tempval;
@@ -175,7 +170,7 @@ static int gfar_probe(struct device *device)
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
- if (einfo == NULL) {
+ if (NULL == einfo) {
printk(KERN_ERR "gfar %d: Missing additional data!\n",
pdev->id);
@@ -185,7 +180,7 @@ static int gfar_probe(struct device *device)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof (*priv));
- if (dev == NULL)
+ if (NULL == dev)
return -ENOMEM;
priv = netdev_priv(dev);
@@ -207,20 +202,11 @@ static int gfar_probe(struct device *device)
priv->regs = (struct gfar *)
ioremap(r->start, sizeof (struct gfar));
- if (priv->regs == NULL) {
+ if (NULL == priv->regs) {
err = -ENOMEM;
goto regs_fail;
}
- /* Set the PHY base address */
- priv->phyregs = (struct gfar *)
- ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
- if (priv->phyregs == NULL) {
- err = -ENOMEM;
- goto phy_regs_fail;
- }
-
spin_lock_init(&priv->lock);
dev_set_drvdata(device, dev);
@@ -386,12 +372,10 @@ static int gfar_probe(struct device *device)
return 0;
register_fail:
- iounmap((void *) priv->phyregs);
-phy_regs_fail:
iounmap((void *) priv->regs);
regs_fail:
free_netdev(dev);
- return -ENOMEM;
+ return err;
}
static int gfar_remove(struct device *device)
@@ -402,108 +386,41 @@ static int gfar_remove(struct device *device)
dev_set_drvdata(device, NULL);
iounmap((void *) priv->regs);
- iounmap((void *) priv->phyregs);
free_netdev(dev);
return 0;
}
-/* Configure the PHY for dev.
- * returns 0 if success. -1 if failure
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
*/
static int init_phy(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct phy_info *curphy;
- unsigned int timeout = PHY_INIT_TIMEOUT;
- struct gfar *phyregs = priv->phyregs;
- struct gfar_mii_info *mii_info;
- int err;
+ uint gigabit_support =
+ priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ SUPPORTED_1000baseT_Full : 0;
+ struct phy_device *phydev;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- mii_info = kmalloc(sizeof(struct gfar_mii_info),
- GFP_KERNEL);
-
- if(NULL == mii_info) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate mii_info\n",
- dev->name);
- return -ENOMEM;
- }
-
- mii_info->speed = SPEED_1000;
- mii_info->duplex = DUPLEX_FULL;
- mii_info->pause = 0;
- mii_info->link = 1;
-
- mii_info->advertising = (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Full);
- mii_info->autoneg = 1;
+ phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
- spin_lock_init(&mii_info->mdio_lock);
-
- mii_info->mii_id = priv->einfo->phyid;
-
- mii_info->dev = dev;
-
- mii_info->mdio_read = &read_phy_reg;
- mii_info->mdio_write = &write_phy_reg;
-
- priv->mii_info = mii_info;
-
- /* Reset the management interface */
- gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
- /* Setup the MII Mgmt clock speed */
- gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
- /* Wait until the bus is free */
- while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
- timeout--)
- cpu_relax();
-
- if(timeout <= 0) {
- printk(KERN_ERR "%s: The MII Bus is stuck!\n",
- dev->name);
- err = -1;
- goto bus_fail;
- }
-
- /* get info for this PHY */
- curphy = get_phy_info(priv->mii_info);
-
- if (curphy == NULL) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: No PHY found\n", dev->name);
- err = -1;
- goto no_phy;
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
}
- mii_info->phyinfo = curphy;
+ /* Remove any features not supported by the controller */
+ phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+ phydev->advertising = phydev->supported;
- /* Run the commands which initialize the PHY */
- if(curphy->init) {
- err = curphy->init(priv->mii_info);
-
- if (err)
- goto phy_init_fail;
- }
+ priv->phydev = phydev;
return 0;
-
-phy_init_fail:
-no_phy:
-bus_fail:
- kfree(mii_info);
-
- return err;
}
static void init_registers(struct net_device *dev)
@@ -603,24 +520,13 @@ void stop_gfar(struct net_device *dev)
struct gfar *regs = priv->regs;
unsigned long flags;
+ phy_stop(priv->phydev);
+
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
- /* Tell the kernel the link is down */
- priv->mii_info->link = 0;
- adjust_link(dev);
-
gfar_halt(dev);
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- /* Clear any pending interrupts */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY Interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
- }
-
spin_unlock_irqrestore(&priv->lock, flags);
/* Free the IRQs */
@@ -629,13 +535,7 @@ void stop_gfar(struct net_device *dev)
free_irq(priv->interruptTransmit, dev);
free_irq(priv->interruptReceive, dev);
} else {
- free_irq(priv->interruptTransmit, dev);
- }
-
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- free_irq(priv->einfo->interruptPHY, dev);
- } else {
- del_timer_sync(&priv->phy_info_timer);
+ free_irq(priv->interruptTransmit, dev);
}
free_skb_resources(priv);
@@ -649,7 +549,7 @@ void stop_gfar(struct net_device *dev)
/* If there are any tx skbs or rx skbs still around, free them.
* Then free tx_skbuff and rx_skbuff */
-void free_skb_resources(struct gfar_private *priv)
+static void free_skb_resources(struct gfar_private *priv)
{
struct rxbd8 *rxbdp;
struct txbd8 *txbdp;
@@ -770,7 +670,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->tx_ring_size, GFP_KERNEL);
- if (priv->tx_skbuff == NULL) {
+ if (NULL == priv->tx_skbuff) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
dev->name);
@@ -785,7 +685,7 @@ int startup_gfar(struct net_device *dev)
(struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
priv->rx_ring_size, GFP_KERNEL);
- if (priv->rx_skbuff == NULL) {
+ if (NULL == priv->rx_skbuff) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
dev->name);
@@ -879,13 +779,7 @@ int startup_gfar(struct net_device *dev)
}
}
- /* Set up the PHY change work queue */
- INIT_WORK(&priv->tq, gfar_phy_change, dev);
-
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_startup_timer;
- priv->phy_info_timer.data = (unsigned long) priv->mii_info;
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
+ phy_start(priv->phydev);
/* Configure the coalescing support */
if (priv->txcoalescing)
@@ -933,11 +827,6 @@ tx_skb_fail:
priv->tx_bd_base,
gfar_read(&regs->tbase0));
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
-
return err;
}
@@ -1035,7 +924,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbdp->status &= TXBD_WRAP;
/* Set up checksumming */
- if ((dev->features & NETIF_F_IP_CSUM)
+ if ((dev->features & NETIF_F_IP_CSUM)
&& (CHECKSUM_HW == skb->ip_summed)) {
fcb = gfar_add_fcb(skb, txbdp);
gfar_tx_checksum(skb, fcb);
@@ -1103,11 +992,9 @@ static int gfar_close(struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
stop_gfar(dev);
- /* Shutdown the PHY */
- if (priv->mii_info->phyinfo->close)
- priv->mii_info->phyinfo->close(priv->mii_info);
-
- kfree(priv->mii_info);
+ /* Disconnect from the PHY */
+ phy_disconnect(priv->phydev);
+ priv->phydev = NULL;
netif_stop_queue(dev);
@@ -1343,7 +1230,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
while ((!skb) && timeout--)
skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
- if (skb == NULL)
+ if (NULL == skb)
return NULL;
/* We need the data buffer to be aligned properly. We will reserve
@@ -1490,7 +1377,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
- if (skb == NULL) {
+ if (NULL == skb) {
if (netif_msg_rx_err(priv))
printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
priv->stats.rx_dropped++;
@@ -1718,131 +1605,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct gfar_private *priv = netdev_priv(dev);
-
- /* Clear the interrupt */
- mii_clear_phy_interrupt(priv->mii_info);
-
- /* Disable PHY interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_DISABLED);
-
- /* Schedule the phy change */
- schedule_work(&priv->tq);
-
- return IRQ_HANDLED;
-}
-
-/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void gfar_phy_change(void *data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
- int result = 0;
-
- /* Delay to give the PHY a chance to change the
- * register state */
- msleep(1);
-
- /* Update the link, speed, duplex */
- result = priv->mii_info->phyinfo->read_status(priv->mii_info);
-
- /* Adjust the known status as long as the link
- * isn't still coming up */
- if((0 == result) || (priv->mii_info->link == 0))
- adjust_link(dev);
-
- /* Reenable interrupts, if needed */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
-}
-
-/* Called every so often on systems that don't interrupt
- * the core for PHY changes */
-static void gfar_phy_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct gfar_private *priv = netdev_priv(dev);
-
- schedule_work(&priv->tq);
-
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
-/* Keep trying aneg for some time
- * If, after GFAR_AN_TIMEOUT seconds, it has not
- * finished, we switch to forced.
- * Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
- * using gfar_phy_timer to check status */
-static void gfar_phy_startup_timer(unsigned long data)
-{
- int result;
- static int secondary = GFAR_AN_TIMEOUT;
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct gfar_private *priv = netdev_priv(mii_info->dev);
-
- /* Configure the Auto-negotiation */
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* If autonegotiation failed to start, and
- * we haven't timed out, reset the timer, and return */
- if (result && secondary--) {
- mod_timer(&priv->phy_info_timer, jiffies + HZ);
- return;
- } else if (result) {
- /* Couldn't start autonegotiation.
- * Try switching to forced */
- mii_info->autoneg = 0;
- result = mii_info->phyinfo->config_aneg(mii_info);
-
- /* Forcing failed! Give up */
- if(result) {
- if (netif_msg_link(priv))
- printk(KERN_ERR "%s: Forcing failed!\n",
- mii_info->dev->name);
- return;
- }
- }
-
- /* Kill the timer so it can be restarted */
- del_timer_sync(&priv->phy_info_timer);
-
- /* Grab the PHY interrupt, if necessary/possible */
- if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- if (request_irq(priv->einfo->interruptPHY,
- phy_interrupt,
- SA_SHIRQ,
- "phy_interrupt",
- mii_info->dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
- mii_info->dev->name,
- priv->einfo->interruptPHY);
- } else {
- mii_configure_phy_interrupt(priv->mii_info,
- MII_INTERRUPT_ENABLED);
- return;
- }
- }
-
- /* Start the timer again, this time in order to
- * handle a change in status */
- init_timer(&priv->phy_info_timer);
- priv->phy_info_timer.function = &gfar_phy_timer;
- priv->phy_info_timer.data = (unsigned long) mii_info->dev;
- mod_timer(&priv->phy_info_timer, jiffies +
- GFAR_PHY_CHANGE_TIME * HZ);
-}
-
/* Called every time the controller might need to be made
* aware of new link state. The PHY code conveys this
- * information through variables in the priv structure, and this
+ * information through variables in the phydev structure, and this
* function converts those variables into the appropriate
* register values, and can bring down the device if needed.
*/
@@ -1850,84 +1615,68 @@ static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
- u32 tempval;
- struct gfar_mii_info *mii_info = priv->mii_info;
+ unsigned long flags;
+ struct phy_device *phydev = priv->phydev;
+ int new_state = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (phydev->link) {
+ u32 tempval = gfar_read(&regs->maccfg2);
- if (mii_info->link) {
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
- if (mii_info->duplex != priv->oldduplex) {
- if (!(mii_info->duplex)) {
- tempval = gfar_read(&regs->maccfg2);
+ if (phydev->duplex != priv->oldduplex) {
+ new_state = 1;
+ if (!(phydev->duplex))
tempval &= ~(MACCFG2_FULL_DUPLEX);
- gfar_write(&regs->maccfg2, tempval);
-
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Half Duplex\n",
- dev->name);
- } else {
- tempval = gfar_read(&regs->maccfg2);
+ else
tempval |= MACCFG2_FULL_DUPLEX;
- gfar_write(&regs->maccfg2, tempval);
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Full Duplex\n",
- dev->name);
- }
-
- priv->oldduplex = mii_info->duplex;
+ priv->oldduplex = phydev->duplex;
}
- if (mii_info->speed != priv->oldspeed) {
- switch (mii_info->speed) {
+ if (phydev->speed != priv->oldspeed) {
+ new_state = 1;
+ switch (phydev->speed) {
case 1000:
- tempval = gfar_read(&regs->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
- gfar_write(&regs->maccfg2, tempval);
break;
case 100:
case 10:
- tempval = gfar_read(&regs->maccfg2);
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
- gfar_write(&regs->maccfg2, tempval);
break;
default:
if (netif_msg_link(priv))
printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, mii_info->speed);
+ "%s: Ack! Speed (%d) is not 10/100/1000!\n",
+ dev->name, phydev->speed);
break;
}
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
- mii_info->speed);
-
- priv->oldspeed = mii_info->speed;
+ priv->oldspeed = phydev->speed;
}
+ gfar_write(&regs->maccfg2, tempval);
+
if (!priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is up\n", dev->name);
+ new_state = 1;
priv->oldlink = 1;
- netif_carrier_on(dev);
netif_schedule(dev);
}
- } else {
- if (priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is down\n",
- dev->name);
- priv->oldlink = 0;
- priv->oldspeed = 0;
- priv->oldduplex = -1;
- netif_carrier_off(dev);
- }
+ } else if (priv->oldlink) {
+ new_state = 1;
+ priv->oldlink = 0;
+ priv->oldspeed = 0;
+ priv->oldduplex = -1;
}
-}
+ if (new_state && netif_msg_link(priv))
+ phy_print_status(phydev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
/* Update the hash table based on the current list of multicast
* addresses we subscribe to. Also, change the promiscuity of
@@ -2122,12 +1871,23 @@ static struct device_driver gfar_driver = {
static int __init gfar_init(void)
{
- return driver_register(&gfar_driver);
+ int err = gfar_mdio_init();
+
+ if (err)
+ return err;
+
+ err = driver_register(&gfar_driver);
+
+ if (err)
+ gfar_mdio_exit();
+
+ return err;
}
static void __exit gfar_exit(void)
{
driver_unregister(&gfar_driver);
+ gfar_mdio_exit();
}
module_init(gfar_init);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 28af087d9fbb..c77ca6c0d04a 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -17,7 +17,6 @@
*
* Still left to do:
* -Add support for module parameters
- * -Add support for ethtool -s
* -Add patch for ethtool phys id
*/
#ifndef __GIANFAR_H
@@ -37,7 +36,8 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/fsl_devices.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -48,7 +48,8 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
-#include "gianfar_phy.h"
+#include <linux/fsl_devices.h>
+#include "gianfar_mii.h"
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
@@ -73,7 +74,7 @@
#define PHY_INIT_TIMEOUT 100000
#define GFAR_PHY_CHANGE_TIME 2
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
#define DRV_NAME "gfar-enet"
extern const char gfar_driver_name[];
extern const char gfar_driver_version[];
@@ -578,12 +579,7 @@ struct gfar {
u32 hafdup; /* 0x.50c - Half Duplex Register */
u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
u8 res18[12];
- u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
- u32 miimcom; /* 0x.524 - MII Management Command Register */
- u32 miimadd; /* 0x.528 - MII Management Address Register */
- u32 miimcon; /* 0x.52c - MII Management Control Register */
- u32 miimstat; /* 0x.530 - MII Management Status Register */
- u32 miimind; /* 0x.534 - MII Management Indicator Register */
+ u8 gfar_mii_regs[24]; /* See gianfar_phy.h */
u8 res19[4];
u32 ifstat; /* 0x.53c - Interface Status Register */
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
@@ -688,9 +684,6 @@ struct gfar_private {
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
u32 *hash_regs[16];
int hash_width;
- struct gfar *phyregs;
- struct work_struct tq;
- struct timer_list phy_info_timer;
struct net_device_stats stats; /* linux network statistics */
struct gfar_extra_stats extra_stats;
spinlock_t lock;
@@ -710,7 +703,8 @@ struct gfar_private {
unsigned int interruptError;
struct gianfar_platform_data *einfo;
- struct gfar_mii_info *mii_info;
+ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
int oldspeed;
int oldduplex;
int oldlink;
@@ -732,4 +726,12 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
extern struct ethtool_ops *gfar_op_array[];
+extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_halt(struct net_device *dev);
+extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
+ int enable, u32 regnum, u32 read);
+void gfar_setup_stashing(struct net_device *dev);
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index a451de629197..68e3578e7613 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -39,17 +39,18 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include "gianfar.h"
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+#define GFAR_MAX_COAL_USECS 0xffff
+#define GFAR_MAX_COAL_FRAMES 0xff
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf);
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
@@ -182,38 +183,32 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
drvinfo->eedump_len = 0;
}
+
+static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+}
+
+
/* Return the current settings in the ethtool_cmd structure */
static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
- uint gigabit_support =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- SUPPORTED_1000baseT_Full : 0;
- uint gigabit_advert =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
- ADVERTISED_1000baseT_Full: 0;
-
- cmd->supported = (SUPPORTED_10baseT_Half
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | gigabit_support | SUPPORTED_Autoneg);
-
- /* For now, we always advertise everything */
- cmd->advertising = (ADVERTISED_10baseT_Half
- | ADVERTISED_100baseT_Half
- | ADVERTISED_100baseT_Full
- | gigabit_advert | ADVERTISED_Autoneg);
-
- cmd->speed = priv->mii_info->speed;
- cmd->duplex = priv->mii_info->duplex;
- cmd->port = PORT_MII;
- cmd->phy_address = priv->mii_info->mii_id;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->autoneg = AUTONEG_ENABLE;
+ struct phy_device *phydev = priv->phydev;
+
+ if (NULL == phydev)
+ return -ENODEV;
+
cmd->maxtxpkt = priv->txcount;
cmd->maxrxpkt = priv->rxcount;
- return 0;
+ return phy_ethtool_gset(phydev, cmd);
}
/* Return the length of the register structure */
@@ -241,14 +236,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -265,14 +260,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
unsigned int count;
/* The timer is different, depending on the interface speed */
- switch (priv->mii_info->speed) {
- case 1000:
+ switch (priv->phydev->speed) {
+ case SPEED_1000:
count = GFAR_GBIT_TIME;
break;
- case 100:
+ case SPEED_100:
count = GFAR_100_TIME;
break;
- case 10:
+ case SPEED_10:
default:
count = GFAR_10_TIME;
break;
@@ -292,6 +287,9 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -348,6 +346,22 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->rxcoalescing = 1;
+ if (NULL == priv->phydev)
+ return -ENODEV;
+
+ /* Check the bounds of the values */
+ if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
priv->rxcount = cvals->rx_max_coalesced_frames;
@@ -358,6 +372,19 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
else
priv->txcoalescing = 1;
+ /* Check the bounds of the values */
+ if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ pr_info("Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
priv->txcount = cvals->tx_max_coalesced_frames;
@@ -536,6 +563,7 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
+ .set_settings = gfar_ssettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
.get_regs = gfar_get_regs,
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
new file mode 100644
index 000000000000..5a74d3d3dbe1
--- /dev/null
+++ b/drivers/net/gianfar_mii.c
@@ -0,0 +1,220 @@
+/*
+ * drivers/net/gianfar_mii.c
+ *
+ * Gianfar Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <asm/ocp.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "gianfar.h"
+#include "gianfar_mii.h"
+
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii *regs = bus->priv;
+
+ /* Set the PHY address and the register address we want to write */
+ gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+ /* Write out the value we want */
+ gfar_write(&regs->miimcon, value);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(&regs->miimind) & MIIMIND_BUSY)
+ cpu_relax();
+
+ return 0;
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii *regs = bus->priv;
+ u16 value;
+
+ /* Set the PHY address and the register address we want to read */
+ gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+ /* Clear miimcom, and then initiate a read */
+ gfar_write(&regs->miimcom, 0);
+ gfar_write(&regs->miimcom, MII_READ_COMMAND);
+
+ /* Wait for the transaction to finish */
+ while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+ cpu_relax();
+
+ /* Grab the value of the register from miimstat */
+ value = gfar_read(&regs->miimstat);
+
+ return value;
+}
+
+
+/* Reset the MIIM registers, and wait for the bus to free */
+int gfar_mdio_reset(struct mii_bus *bus)
+{
+ struct gfar_mii *regs = bus->priv;
+ unsigned int timeout = PHY_INIT_TIMEOUT;
+
+ spin_lock_bh(&bus->mdio_lock);
+
+ /* Reset the management interface */
+ gfar_write(&regs->miimcfg, MIIMCFG_RESET);
+
+ /* Setup the MII Mgmt clock speed */
+ gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+ /* Wait until the bus is free */
+ while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) &&
+ timeout--)
+ cpu_relax();
+
+ spin_unlock_bh(&bus->mdio_lock);
+
+ if(timeout <= 0) {
+ printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+ bus->name);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+
+int gfar_mdio_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gianfar_mdio_data *pdata;
+ struct gfar_mii *regs;
+ struct mii_bus *new_bus;
+ int err = 0;
+
+ if (NULL == dev)
+ return -EINVAL;
+
+ new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (NULL == new_bus)
+ return -ENOMEM;
+
+ new_bus->name = "Gianfar MII Bus",
+ new_bus->read = &gfar_mdio_read,
+ new_bus->write = &gfar_mdio_write,
+ new_bus->reset = &gfar_mdio_reset,
+ new_bus->id = pdev->id;
+
+ pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+ if (NULL == pdata) {
+ printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+ return -ENODEV;
+ }
+
+ /* Set the PHY base address */
+ regs = (struct gfar_mii *) ioremap(pdata->paddr,
+ sizeof (struct gfar_mii));
+
+ if (NULL == regs) {
+ err = -ENOMEM;
+ goto reg_map_fail;
+ }
+
+ new_bus->priv = regs;
+
+ new_bus->irq = pdata->irq;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+ new_bus->name);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ iounmap((void *) regs);
+reg_map_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+int gfar_mdio_remove(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(dev, NULL);
+
+ iounmap((void *) (&bus->priv));
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct device_driver gianfar_mdio_driver = {
+ .name = "fsl-gianfar_mdio",
+ .bus = &platform_bus_type,
+ .probe = gfar_mdio_probe,
+ .remove = gfar_mdio_remove,
+};
+
+int __init gfar_mdio_init(void)
+{
+ return driver_register(&gianfar_mdio_driver);
+}
+
+void __exit gfar_mdio_exit(void)
+{
+ driver_unregister(&gianfar_mdio_driver);
+}
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
new file mode 100644
index 000000000000..56e5665d5c9b
--- /dev/null
+++ b/drivers/net/gianfar_mii.h
@@ -0,0 +1,45 @@
+/*
+ * drivers/net/gianfar_mii.h
+ *
+ * Gianfar Ethernet Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller in the Gianfar register space
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __GIANFAR_MII_H
+#define __GIANFAR_MII_H
+
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_NOTVALID 0x00000004
+
+#define MII_READ_COMMAND 0x00000001
+
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+ | SUPPORTED_Autoneg \
+ | SUPPORTED_MII)
+
+struct gfar_mii {
+ u32 miimcfg; /* 0x.520 - MII Management Config Register */
+ u32 miimcom; /* 0x.524 - MII Management Command Register */
+ u32 miimadd; /* 0x.528 - MII Management Address Register */
+ u32 miimcon; /* 0x.52c - MII Management Control Register */
+ u32 miimstat; /* 0x.530 - MII Management Status Register */
+ u32 miimind; /* 0x.534 - MII Management Indicator Register */
+};
+
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int __init gfar_mdio_init(void);
+void __exit gfar_mdio_exit(void);
+#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
deleted file mode 100644
index 7c965f268a82..000000000000
--- a/drivers/net/gianfar_phy.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * drivers/net/gianfar_phy.c
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-
-#include "gianfar.h"
-#include "gianfar_phy.h"
-
-static void config_genmii_advert(struct gfar_mii_info *mii_info);
-static void genmii_setup_forced(struct gfar_mii_info *mii_info);
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
-static int gbit_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_update_link(struct gfar_mii_info *mii_info);
-static int genmii_read_status(struct gfar_mii_info *mii_info);
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
-
- /* Set the PHY address and the register address we want to write */
- gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
- /* Write out the value we want */
- gfar_write(&regbase->miimcon, value);
-
- /* Wait for the transaction to finish */
- while (gfar_read(&regbase->miimind) & MIIMIND_BUSY)
- cpu_relax();
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value. Clears miimcom first. All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regbase = priv->phyregs;
- u16 value;
-
- /* Set the PHY address and the register address we want to read */
- gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
- /* Clear miimcom, and then initiate a read */
- gfar_write(&regbase->miimcom, 0);
- gfar_write(&regbase->miimcom, MII_READ_COMMAND);
-
- /* Wait for the transaction to finish */
- while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
- cpu_relax();
-
- /* Grab the value of the register from miimstat */
- value = gfar_read(&regbase->miimstat);
-
- return value;
-}
-
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
-{
- if(mii_info->phyinfo->ack_interrupt)
- mii_info->phyinfo->ack_interrupt(mii_info);
-}
-
-
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
-{
- mii_info->interrupts = interrupts;
- if(mii_info->phyinfo->config_intr)
- mii_info->phyinfo->config_intr(mii_info);
-}
-
-
-/* Writes MII_ADVERTISE with the appropriate values, after
- * sanitizing advertise to make sure only supported features
- * are advertised
- */
-static void config_genmii_advert(struct gfar_mii_info *mii_info)
-{
- u32 advertise;
- u16 adv;
-
- /* Only allow advertising what this PHY supports */
- mii_info->advertising &= mii_info->phyinfo->features;
- advertise = mii_info->advertising;
-
- /* Setup standard advertisement */
- adv = phy_read(mii_info, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
- if (advertise & ADVERTISED_10baseT_Half)
- adv |= ADVERTISE_10HALF;
- if (advertise & ADVERTISED_10baseT_Full)
- adv |= ADVERTISE_10FULL;
- if (advertise & ADVERTISED_100baseT_Half)
- adv |= ADVERTISE_100HALF;
- if (advertise & ADVERTISED_100baseT_Full)
- adv |= ADVERTISE_100FULL;
- phy_write(mii_info, MII_ADVERTISE, adv);
-}
-
-static void genmii_setup_forced(struct gfar_mii_info *mii_info)
-{
- u16 ctrl;
- u32 features = mii_info->phyinfo->features;
-
- ctrl = phy_read(mii_info, MII_BMCR);
-
- ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
- ctrl |= BMCR_RESET;
-
- switch(mii_info->speed) {
- case SPEED_1000:
- if(features & (SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full)) {
- ctrl |= BMCR_SPEED1000;
- break;
- }
- mii_info->speed = SPEED_100;
- case SPEED_100:
- if (features & (SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full)) {
- ctrl |= BMCR_SPEED100;
- break;
- }
- mii_info->speed = SPEED_10;
- case SPEED_10:
- if (features & (SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full))
- break;
- default: /* Unsupported speed! */
- printk(KERN_ERR "%s: Bad speed!\n",
- mii_info->dev->name);
- break;
- }
-
- phy_write(mii_info, MII_BMCR, ctrl);
-}
-
-
-/* Enable and Restart Autonegotiation */
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
-{
- u16 ctl;
-
- ctl = phy_read(mii_info, MII_BMCR);
- ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(mii_info, MII_BMCR, ctl);
-}
-
-
-static int gbit_config_aneg(struct gfar_mii_info *mii_info)
-{
- u16 adv;
- u32 advertise;
-
- if(mii_info->autoneg) {
- /* Configure the ADVERTISE register */
- config_genmii_advert(mii_info);
- advertise = mii_info->advertising;
-
- adv = phy_read(mii_info, MII_1000BASETCONTROL);
- adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
- MII_1000BASETCONTROL_HALFDUPLEXCAP);
- if (advertise & SUPPORTED_1000baseT_Half)
- adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
- if (advertise & SUPPORTED_1000baseT_Full)
- adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(mii_info, MII_1000BASETCONTROL, adv);
-
- /* Start/Restart aneg */
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-static int marvell_config_aneg(struct gfar_mii_info *mii_info)
-{
- /* The Marvell PHY has an errata which requires
- * that certain registers get written in order
- * to restart autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_RESET);
-
- phy_write(mii_info, 0x1d, 0x1f);
- phy_write(mii_info, 0x1e, 0x200c);
- phy_write(mii_info, 0x1d, 0x5);
- phy_write(mii_info, 0x1e, 0);
- phy_write(mii_info, 0x1e, 0x100);
-
- gbit_config_aneg(mii_info);
-
- return 0;
-}
-static int genmii_config_aneg(struct gfar_mii_info *mii_info)
-{
- if (mii_info->autoneg) {
- config_genmii_advert(mii_info);
- genmii_restart_aneg(mii_info);
- } else
- genmii_setup_forced(mii_info);
-
- return 0;
-}
-
-
-static int genmii_update_link(struct gfar_mii_info *mii_info)
-{
- u16 status;
-
- /* Do a fake read */
- phy_read(mii_info, MII_BMSR);
-
- /* Read link and autonegotiation status */
- status = phy_read(mii_info, MII_BMSR);
- if ((status & BMSR_LSTATUS) == 0)
- mii_info->link = 0;
- else
- mii_info->link = 1;
-
- /* If we are autonegotiating, and not done,
- * return an error */
- if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
- return -EAGAIN;
-
- return 0;
-}
-
-static int genmii_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- if (mii_info->autoneg) {
- status = phy_read(mii_info, MII_LPA);
-
- if (status & (LPA_10FULL | LPA_100FULL))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- if (status & (LPA_100FULL | LPA_100HALF))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
- mii_info->pause = 0;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
-
- return 0;
-}
-static int marvell_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
- status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
-
-#if 0
- /* If speed and duplex aren't resolved,
- * return an error. Isn't this handled
- * by checking aneg?
- */
- if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
- return -EAGAIN;
-#endif
-
- /* Get the duplexity */
- if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- /* Get the speed */
- speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
- switch(speed) {
- case MII_M1011_PHY_SPEC_STATUS_1000:
- mii_info->speed = SPEED_1000;
- break;
- case MII_M1011_PHY_SPEC_STATUS_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- mii_info->pause = 0;
- }
-
- return 0;
-}
-
-
-static int cis820x_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- int speed;
-
- status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
- if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
-
- speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
-
- switch (speed) {
- case MII_CIS8201_AUXCONSTAT_GBIT:
- mii_info->speed = SPEED_1000;
- break;
- case MII_CIS8201_AUXCONSTAT_100:
- mii_info->speed = SPEED_100;
- break;
- default:
- mii_info->speed = SPEED_10;
- break;
- }
- }
-
- return 0;
-}
-
-static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- /* Clear the interrupts by reading the reg */
- phy_read(mii_info, MII_M1011_IEVENT);
-
- return 0;
-}
-
-static int marvell_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
- else
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
-
- return 0;
-}
-
-static int cis820x_init(struct gfar_mii_info *mii_info)
-{
- phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
- MII_CIS8201_AUXCONSTAT_INIT);
- phy_write(mii_info, MII_CIS8201_EXT_CON1,
- MII_CIS8201_EXTCON1_INIT);
-
- return 0;
-}
-
-static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_CIS8201_ISTAT);
-
- return 0;
-}
-
-static int cis820x_config_intr(struct gfar_mii_info *mii_info)
-{
- if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
- else
- phy_write(mii_info, MII_CIS8201_IMASK, 0);
-
- return 0;
-}
-
-#define DM9161_DELAY 10
-
-static int dm9161_read_status(struct gfar_mii_info *mii_info)
-{
- u16 status;
- int err;
-
- /* Update the link, but return if there
- * was an error */
- err = genmii_update_link(mii_info);
- if (err)
- return err;
-
- /* If the link is up, read the speed and duplex */
- /* If we aren't autonegotiating, assume speeds
- * are as set */
- if (mii_info->autoneg && mii_info->link) {
- status = phy_read(mii_info, MII_DM9161_SCSR);
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
- mii_info->speed = SPEED_100;
- else
- mii_info->speed = SPEED_10;
-
- if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
- mii_info->duplex = DUPLEX_FULL;
- else
- mii_info->duplex = DUPLEX_HALF;
- }
-
- return 0;
-}
-
-
-static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- if(0 == priv->resetdone)
- return -EAGAIN;
-
- return 0;
-}
-
-static void dm9161_timer(unsigned long data)
-{
- struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
- struct dm9161_private *priv = mii_info->priv;
- u16 status = phy_read(mii_info, MII_BMSR);
-
- if (status & BMSR_ANEGCOMPLETE) {
- priv->resetdone = 1;
- } else
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-}
-
-static int dm9161_init(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv;
-
- /* Allocate the private data structure */
- priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
-
- if (NULL == priv)
- return -ENOMEM;
-
- mii_info->priv = priv;
-
- /* Reset is not done yet */
- priv->resetdone = 0;
-
- /* Isolate the PHY */
- phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
-
- /* Do not bypass the scrambler/descrambler */
- phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
-
- /* Clear 10BTCSR to default */
- phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
-
- /* Reconnect the PHY, and enable Autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
-
- /* Start a timer for DM9161_DELAY seconds to wait
- * for the PHY to be ready */
- init_timer(&priv->timer);
- priv->timer.function = &dm9161_timer;
- priv->timer.data = (unsigned long) mii_info;
- mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-
- return 0;
-}
-
-static void dm9161_close(struct gfar_mii_info *mii_info)
-{
- struct dm9161_private *priv = mii_info->priv;
-
- del_timer_sync(&priv->timer);
- kfree(priv);
-}
-
-#if 0
-static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
-{
- phy_read(mii_info, MII_DM9161_INTR);
-
- return 0;
-}
-#endif
-
-/* Cicada 820x */
-static struct phy_info phy_info_cis820x = {
- 0x000fc440,
- "Cicada Cis8204",
- 0x000fffc0,
- .features = MII_GBIT_FEATURES,
- .init = &cis820x_init,
- .config_aneg = &gbit_config_aneg,
- .read_status = &cis820x_read_status,
- .ack_interrupt = &cis820x_ack_interrupt,
- .config_intr = &cis820x_config_intr,
-};
-
-static struct phy_info phy_info_dm9161 = {
- .phy_id = 0x0181b880,
- .name = "Davicom DM9161E",
- .phy_id_mask = 0x0ffffff0,
- .init = dm9161_init,
- .config_aneg = dm9161_config_aneg,
- .read_status = dm9161_read_status,
- .close = dm9161_close,
-};
-
-static struct phy_info phy_info_marvell = {
- .phy_id = 0x01410c00,
- .phy_id_mask = 0xffffff00,
- .name = "Marvell 88E1101/88E1111",
- .features = MII_GBIT_FEATURES,
- .config_aneg = &marvell_config_aneg,
- .read_status = &marvell_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
-};
-
-static struct phy_info phy_info_genmii= {
- .phy_id = 0x00000000,
- .phy_id_mask = 0x00000000,
- .name = "Generic MII",
- .features = MII_BASIC_FEATURES,
- .config_aneg = genmii_config_aneg,
- .read_status = genmii_read_status,
-};
-
-static struct phy_info *phy_info[] = {
- &phy_info_cis820x,
- &phy_info_marvell,
- &phy_info_dm9161,
- &phy_info_genmii,
- NULL
-};
-
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
-{
- u16 retval;
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
- return retval;
-}
-
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- mii_info->mdio_write(mii_info->dev,
- mii_info->mii_id,
- regnum, val);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
-/* Use the PHY ID registers to determine what type of PHY is attached
- * to device dev. return a struct phy_info structure describing that PHY
- */
-struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
-{
- u16 phy_reg;
- u32 phy_ID;
- int i;
- struct phy_info *theInfo = NULL;
- struct net_device *dev = mii_info->dev;
-
- /* Grab the bits from PHYIR1, and put them in the upper half */
- phy_reg = phy_read(mii_info, MII_PHYSID1);
- phy_ID = (phy_reg & 0xffff) << 16;
-
- /* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = phy_read(mii_info, MII_PHYSID2);
- phy_ID |= (phy_reg & 0xffff);
-
- /* loop through all the known PHY types, and find one that */
- /* matches the ID we read from the PHY. */
- for (i = 0; phy_info[i]; i++)
- if (phy_info[i]->phy_id ==
- (phy_ID & phy_info[i]->phy_id_mask)) {
- theInfo = phy_info[i];
- break;
- }
-
- /* This shouldn't happen, as we have generic PHY support */
- if (theInfo == NULL) {
- printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
- return NULL;
- } else {
- printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
- }
-
- return theInfo;
-}
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
deleted file mode 100644
index 1e9b3abf1e6d..000000000000
--- a/drivers/net/gianfar_phy.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * drivers/net/gianfar_phy.h
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY 0x00000001
-#define MIIMIND_NOTVALID 0x00000004
-
-#define GFAR_AN_TIMEOUT 2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL 0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1 0x17
-#define MII_CIS8201_EXTCON1_INIT 0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK 0x19
-#define MII_CIS8201_IMASK_IEN 0x8000
-#define MII_CIS8201_IMASK_SPEED 0x4000
-#define MII_CIS8201_IMASK_LINK 0x2000
-#define MII_CIS8201_IMASK_DUPLEX 0x1000
-#define MII_CIS8201_IMASK_MASK 0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT 0x1a
-#define MII_CIS8201_ISTAT_STATUS 0x8000
-#define MII_CIS8201_ISTAT_SPEED 0x4000
-#define MII_CIS8201_ISTAT_LINK 0x2000
-#define MII_CIS8201_ISTAT_DUPLEX 0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT 0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
-#define MII_CIS8201_AUXCONSTAT_100 0x0008
-
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS 0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
-
-#define MII_M1011_IEVENT 0x13
-#define MII_M1011_IEVENT_CLEAR 0x0000
-
-#define MII_M1011_IMASK 0x12
-#define MII_M1011_IMASK_INIT 0x6400
-#define MII_M1011_IMASK_CLEAR 0x0000
-
-#define MII_DM9161_SCR 0x10
-#define MII_DM9161_SCR_INIT 0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR 0x11
-#define MII_DM9161_SCSR_100F 0x8000
-#define MII_DM9161_SCSR_100H 0x4000
-#define MII_DM9161_SCSR_10F 0x2000
-#define MII_DM9161_SCSR_10H 0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR 0x15
-#define MII_DM9161_INTR_PEND 0x8000
-#define MII_DM9161_INTR_DPLX_MASK 0x0800
-#define MII_DM9161_INTR_SPD_MASK 0x0400
-#define MII_DM9161_INTR_LINK_MASK 0x0200
-#define MII_DM9161_INTR_MASK 0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
-#define MII_DM9161_INTR_SPD_CHANGE 0x0008
-#define MII_DM9161_INTR_LINK_CHANGE 0x0004
-#define MII_DM9161_INTR_INIT 0x0000
-#define MII_DM9161_INTR_STOP \
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR 0x12
-#define MII_DM9161_10BTCSR_INIT 0x7800
-
-#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
- SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | \
- SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | \
- SUPPORTED_TP | \
- SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | \
- SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND 0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
- /* Information about the PHY type */
- /* And management functions */
- struct phy_info *phyinfo;
-
- /* forced speed & duplex (no autoneg)
- * partner speed & duplex & pause (autoneg)
- */
- int speed;
- int duplex;
- int pause;
-
- /* The most recently read link state */
- int link;
-
- /* Enabled Interrupts */
- u32 interrupts;
-
- u32 advertising;
- int autoneg;
- int mii_id;
-
- /* private data pointer */
- /* For use by PHYs to maintain extra state */
- void *priv;
-
- /* Provided by host chip */
- struct net_device *dev;
-
- /* A lock to ensure that only one thing can read/write
- * the MDIO bus at a time */
- spinlock_t mdio_lock;
-
- /* Provided by ethernet driver */
- int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
- void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY. During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is. The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
- u32 phy_id;
- char *name;
- unsigned int phy_id_mask;
- u32 features;
-
- /* Called to initialize the PHY */
- int (*init)(struct gfar_mii_info *mii_info);
-
- /* Called to suspend the PHY for power */
- int (*suspend)(struct gfar_mii_info *mii_info);
-
- /* Reconfigures autonegotiation (or disables it) */
- int (*config_aneg)(struct gfar_mii_info *mii_info);
-
- /* Determines the negotiated speed and duplex */
- int (*read_status)(struct gfar_mii_info *mii_info);
-
- /* Clears any pending interrupts */
- int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
- /* Enables or disables interrupts */
- int (*config_intr)(struct gfar_mii_info *mii_info);
-
- /* Clears up any memory if needed */
- void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
- struct timer_list timer;
- int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index d9df1d9a5739..bc9a3bf8d560 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -204,6 +204,10 @@ KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu>
#define RUN_AT(x) (jiffies + (x))
+#ifndef ADDRLEN
+#define ADDRLEN 32
+#endif
+
/* Condensed bus+endian portability operations. */
#if ADDRLEN == 64
#define cpu_to_leXX(addr) cpu_to_le64(addr)
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index e44f8e9055ef..90999867a32c 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -130,12 +130,11 @@ struct sixpack {
#define AX25_6PACK_HEADER_LEN 0
-static void sp_start_tx_timer(struct sixpack *);
static void sixpack_decode(struct sixpack *, unsigned char[], int);
static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
/*
- * perform the persistence/slottime algorithm for CSMA access. If the
+ * Perform the persistence/slottime algorithm for CSMA access. If the
* persistence check was successful, write the data to the serial driver.
* Note that in case of DAMA operation, the data is not sent here.
*/
@@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
static void sp_xmit_on_air(unsigned long channel)
{
struct sixpack *sp = (struct sixpack *) channel;
- int actual;
+ int actual, when = sp->slottime;
static unsigned char random;
random = random * 17 + 41;
@@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel)
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
sp->status2 = 0;
} else
- sp_start_tx_timer(sp);
+ mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
}
/* ----> 6pack timer interrupt handler and friends. <---- */
-static void sp_start_tx_timer(struct sixpack *sp)
-{
- int when = sp->slottime;
-
- del_timer(&sp->tx_t);
- sp->tx_t.data = (unsigned long) sp;
- sp->tx_t.function = sp_xmit_on_air;
- sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
- add_timer(&sp->tx_t);
-}
/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
@@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
sp->xleft = count;
sp->xhead = sp->xbuff;
sp->status2 = count;
- if (sp->duplex == 0)
- sp_start_tx_timer(sp);
+ sp_xmit_on_air((unsigned long)sp);
}
return;
@@ -305,7 +293,7 @@ static int sp_header(struct sk_buff *skb, struct net_device *dev,
{
#ifdef CONFIG_INET
if (type != htons(ETH_P_AX25))
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+ return ax25_hard_header(skb, dev, type, daddr, saddr, len);
#endif
return 0;
}
@@ -320,12 +308,6 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr_ax25 *sa = addr;
- if (sa->sax25_family != AF_AX25)
- return -EINVAL;
-
- if (!sa->sax25_ndigis)
- return -EINVAL;
-
spin_lock_irq(&dev->xmit_lock);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
@@ -680,6 +662,9 @@ static int sixpack_open(struct tty_struct *tty)
netif_start_queue(dev);
init_timer(&sp->tx_t);
+ sp->tx_t.function = sp_xmit_on_air;
+ sp->tx_t.data = (unsigned long) sp;
+
init_timer(&sp->resync_t);
spin_unlock_bh(&sp->lock);
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 0cd54306e636..896aa02000d7 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -1,6 +1,7 @@
config MKISS
tristate "Serial port KISS driver"
- depends on AX25 && BROKEN_ON_SMP
+ depends on AX25
+ select CRC16
---help---
KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index a7f15d9f13e5..e4188d082f01 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -40,7 +40,7 @@
/*****************************************************************************/
-#include <linux/config.h>
+#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -48,17 +48,12 @@
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/parport.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
#include <linux/if_arp.h>
-#include <linux/kmod.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
+#include <linux/jiffies.h>
#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-#include <linux/crc-ccitt.h>
+#include <asm/uaccess.h>
/* --------------------------------------------------------------------- */
@@ -287,7 +282,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
@@ -1176,13 +1171,8 @@ static void baycom_probe(struct net_device *dev)
/* Fill in the fields of the device structure */
bc->skb = NULL;
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = baycom_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 612ad452bee0..3b1bef1ee215 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -84,6 +84,7 @@
#include <linux/baycom.h>
#include <linux/parport.h>
#include <linux/bitops.h>
+#include <linux/jiffies.h>
#include <asm/bug.h>
#include <asm/system.h>
@@ -165,7 +166,7 @@ static void __inline__ baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 25f270b05378..232793d2ce6b 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -79,6 +79,7 @@
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */
@@ -159,7 +160,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index eead85d00962..be596a3eb3fd 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -69,6 +69,7 @@
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */
@@ -150,7 +151,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
- if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+ if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index ba9f0580e1f9..cb43a9d28774 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -98,7 +98,7 @@ static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char bpq_eth_addr[6];
-static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
+static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
static const char *bpq_print_ethaddr(const unsigned char *);
@@ -144,7 +144,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
{
struct bpqdev *bpq;
- list_for_each_entry(bpq, &bpq_devices, bpq_list) {
+ list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
if (bpq->ethdev == dev)
return bpq->axdev;
}
@@ -165,7 +165,7 @@ static inline int dev_is_ethdev(struct net_device *dev)
/*
* Receive an AX.25 frame via an ethernet interface.
*/
-static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
+static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)
{
int len;
char * ptr;
@@ -399,7 +399,7 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
- list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
+ list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
if (i == *pos)
return bpqdev;
}
@@ -418,7 +418,7 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
p = ((struct bpqdev *)v)->bpq_list.next;
return (p == &bpq_devices) ? NULL
- : list_entry(p, struct bpqdev, bpq_list);
+ : rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
}
static void bpq_seq_stop(struct seq_file *seq, void *v)
@@ -488,7 +488,7 @@ static void bpq_setup(struct net_device *dev)
dev->flags = 0;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
#endif
@@ -561,8 +561,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
- rcu_read_lock();
-
switch (event) {
case NETDEV_UP: /* new ethernet device -> new BPQ interface */
if (bpq_get_ax25_dev(dev) == NULL)
@@ -581,7 +579,6 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
default:
break;
}
- rcu_read_unlock();
return NOTIFY_DONE;
}
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index f515245a3fd0..3be3f916643a 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -449,12 +449,12 @@ module_exit(dmascc_exit);
static void dev_setup(struct net_device *dev)
{
dev->type = ARPHRD_AX25;
- dev->hard_header_len = 73;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
dev->mtu = 1500;
- dev->addr_len = 7;
+ dev->addr_len = AX25_ADDR_LEN;
dev->tx_queue_len = 64;
- memcpy(dev->broadcast, ax25_broadcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
+ memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
}
static int __init setup_adapter(int card_base, int type, int n)
@@ -600,7 +600,7 @@ static int __init setup_adapter(int card_base, int type, int n)
dev->do_ioctl = scc_ioctl;
dev->hard_start_xmit = scc_send_packet;
dev->get_stats = scc_get_stats;
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_set_mac_address;
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b4c836e4fe86..dacc7687b97f 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -42,7 +42,6 @@
/*****************************************************************************/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/net.h>
@@ -52,20 +51,14 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/bitops.h>
-#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/hdlcdrv.h>
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
+#include <asm/uaccess.h>
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
#include <linux/crc-ccitt.h>
/* --------------------------------------------------------------------- */
@@ -708,13 +701,8 @@ static void hdlcdrv_setup(struct net_device *dev)
s->skb = NULL;
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = hdlcdrv_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 3035422f5ad8..3e9accf137e7 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -1,37 +1,27 @@
/*
- * MKISS Driver
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
*
- * This module:
- * This module 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 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.
*
- * This module implements the AX.25 protocol for kernel-based
- * devices like TTYs. It interfaces between a raw TTY, and the
- * kernel's AX.25 protocol layers, just like slip.c.
- * AX.25 needs to be separated from slip.c while slip.c is no
- * longer a static kernel device since it is a module.
- * This method clears the way to implement other kiss protocols
- * like mkiss smack g8bpq ..... so far only mkiss is implemented.
+ * 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.
*
- * Hans Alblas <hans@esrac.ele.tue.nl>
- *
- * History
- * Jonathan (G4KLX) Fixed to match Linux networking changes - 2.1.15.
- * Matthias (DG2FEF) Added support for FlexNet CRC (on special request)
- * Fixed bug in ax25_close(): dev_lock_wait() was
- * called twice, causing a deadlock.
- * Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
- * MOD_*_USE_COUNT
- * Remove cli() and fix rtnl lock usage.
+ * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
+ * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
+ * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
+#include <linux/crc16.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -46,177 +36,337 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
+#include <linux/jiffies.h>
#include <net/ax25.h>
-#include "mkiss.h"
+#define AX_MTU 236
+
+/* SLIP/KISS protocol characters. */
+#define END 0300 /* indicates end of frame */
+#define ESC 0333 /* indicates byte stuffing */
+#define ESC_END 0334 /* ESC ESC_END means END 'data' */
+#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
+
+struct mkiss {
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct net_device *dev; /* easy for intr handling */
+
+ /* These are pointers to the malloc()ed frame buffers. */
+ spinlock_t buflock;/* lock for rbuf and xbuf */
+ unsigned char *rbuff; /* receiver buffer */
+ int rcount; /* received chars counter */
+ unsigned char *xbuff; /* transmitter buffer */
+ unsigned char *xhead; /* pointer to next byte to XMIT */
+ int xleft; /* bytes left in XMIT queue */
+
+ struct net_device_stats stats;
+
+ /* Detailed SLIP statistics. */
+ int mtu; /* Our mtu (to spot changes!) */
+ int buffsize; /* Max buffers sizes */
+
+ unsigned long flags; /* Flag values/ mode etc */
+ /* long req'd: used by set_bit --RR */
+#define AXF_INUSE 0 /* Channel in use */
+#define AXF_ESCAPE 1 /* ESC received */
+#define AXF_ERROR 2 /* Parity, etc. error */
+#define AXF_KEEPTEST 3 /* Keepalive test flag */
+#define AXF_OUTWAIT 4 /* is outpacket was flag */
+
+ int mode;
+ int crcmode; /* MW: for FlexNet, SMACK etc. */
+ int crcauto; /* CRC auto mode */
+
+#define CRC_MODE_NONE 0
+#define CRC_MODE_FLEX 1
+#define CRC_MODE_SMACK 2
+#define CRC_MODE_FLEX_TEST 3
+#define CRC_MODE_SMACK_TEST 4
+
+ atomic_t refcnt;
+ struct semaphore dead_sem;
+};
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#endif
+/*---------------------------------------------------------------------------*/
-static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
+static const unsigned short crc_flex_table[] = {
+ 0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
+ 0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
+ 0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
+ 0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
+ 0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
+ 0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
+ 0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
+ 0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
+ 0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
+ 0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
+ 0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
+ 0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
+ 0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
+ 0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
+ 0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
+ 0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
+ 0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
+ 0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
+ 0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
+ 0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
+ 0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
+ 0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
+ 0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
+ 0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
+ 0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
+ 0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
+ 0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
+ 0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
+ 0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
+ 0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
+ 0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
+ 0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
+};
-typedef struct ax25_ctrl {
- struct ax_disp ctrl; /* */
- struct net_device dev; /* the device */
-} ax25_ctrl_t;
+static unsigned short calc_crc_flex(unsigned char *cp, int size)
+{
+ unsigned short crc = 0xffff;
-static ax25_ctrl_t **ax25_ctrls;
+ while (size--)
+ crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
-int ax25_maxdev = AX25_MAXDEV; /* Can be overridden with insmod! */
+ return crc;
+}
-static struct tty_ldisc ax_ldisc;
+static int check_crc_flex(unsigned char *cp, int size)
+{
+ unsigned short crc = 0xffff;
-static int ax25_init(struct net_device *);
-static int kiss_esc(unsigned char *, unsigned char *, int);
-static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);
-static void kiss_unesc(struct ax_disp *, unsigned char);
+ if (size < 3)
+ return -1;
-/*---------------------------------------------------------------------------*/
+ while (size--)
+ crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
-static const unsigned short Crc_flex_table[] = {
- 0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
- 0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
- 0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
- 0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
- 0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
- 0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
- 0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
- 0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
- 0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
- 0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
- 0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
- 0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
- 0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
- 0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
- 0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
- 0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
- 0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
- 0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
- 0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
- 0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
- 0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
- 0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
- 0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
- 0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
- 0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
- 0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
- 0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
- 0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
- 0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
- 0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
- 0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
- 0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
-};
+ if ((crc & 0xffff) != 0x7070)
+ return -1;
-/*---------------------------------------------------------------------------*/
+ return 0;
+}
-static unsigned short calc_crc_flex(unsigned char *cp, int size)
+static int check_crc_16(unsigned char *cp, int size)
{
- unsigned short crc = 0xffff;
-
- while (size--)
- crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+ unsigned short crc = 0x0000;
+
+ if (size < 3)
+ return -1;
- return crc;
+ crc = crc16(0, cp, size);
+
+ if (crc != 0x0000)
+ return -1;
+
+ return 0;
}
-/*---------------------------------------------------------------------------*/
+/*
+ * Standard encapsulation
+ */
-static int check_crc_flex(unsigned char *cp, int size)
+static int kiss_esc(unsigned char *s, unsigned char *d, int len)
{
- unsigned short crc = 0xffff;
+ unsigned char *ptr = d;
+ unsigned char c;
- if (size < 3)
- return -1;
+ /*
+ * Send an initial END character to flush out any data that may have
+ * accumulated in the receiver due to line noise.
+ */
- while (size--)
- crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
+ *ptr++ = END;
- if ((crc & 0xffff) != 0x7070)
- return -1;
+ while (len-- > 0) {
+ switch (c = *s++) {
+ case END:
+ *ptr++ = ESC;
+ *ptr++ = ESC_END;
+ break;
+ case ESC:
+ *ptr++ = ESC;
+ *ptr++ = ESC_ESC;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
+ }
- return 0;
-}
+ *ptr++ = END;
-/*---------------------------------------------------------------------------*/
+ return ptr - d;
+}
-/* Find a free channel, and link in this `tty' line. */
-static inline struct ax_disp *ax_alloc(void)
+/*
+ * MW:
+ * OK its ugly, but tell me a better solution without copying the
+ * packet to a temporary buffer :-)
+ */
+static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
+ int len)
{
- ax25_ctrl_t *axp=NULL;
- int i;
+ unsigned char *ptr = d;
+ unsigned char c=0;
+
+ *ptr++ = END;
+ while (len > 0) {
+ if (len > 2)
+ c = *s++;
+ else if (len > 1)
+ c = crc >> 8;
+ else if (len > 0)
+ c = crc & 0xff;
- for (i = 0; i < ax25_maxdev; i++) {
- axp = ax25_ctrls[i];
+ len--;
- /* Not allocated ? */
- if (axp == NULL)
+ switch (c) {
+ case END:
+ *ptr++ = ESC;
+ *ptr++ = ESC_END;
break;
-
- /* Not in use ? */
- if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))
+ case ESC:
+ *ptr++ = ESC;
+ *ptr++ = ESC_ESC;
+ break;
+ default:
+ *ptr++ = c;
break;
+ }
}
+ *ptr++ = END;
- /* Sorry, too many, all slots in use */
- if (i >= ax25_maxdev)
- return NULL;
+ return ptr - d;
+}
- /* If no channels are available, allocate one */
- if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
- axp = ax25_ctrls[i];
- }
- memset(axp, 0, sizeof(ax25_ctrl_t));
-
- /* Initialize channel control data */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- sprintf(axp->dev.name, "ax%d", i++);
- axp->ctrl.tty = NULL;
- axp->dev.base_addr = i;
- axp->dev.priv = (void *)&axp->ctrl;
- axp->dev.next = NULL;
- axp->dev.init = ax25_init;
-
- if (axp != NULL) {
- /*
- * register device so that it can be ifconfig'ed
- * ax25_init() will be called as a side-effect
- * SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !
- */
- if (register_netdev(&axp->dev) == 0) {
- /* (Re-)Set the INUSE bit. Very Important! */
- set_bit(AXF_INUSE, &axp->ctrl.flags);
- axp->ctrl.dev = &axp->dev;
- axp->dev.priv = (void *) &axp->ctrl;
-
- return &axp->ctrl;
- } else {
- clear_bit(AXF_INUSE,&axp->ctrl.flags);
- printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");
+/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
+static void ax_bump(struct mkiss *ax)
+{
+ struct sk_buff *skb;
+ int count;
+
+ spin_lock_bh(&ax->buflock);
+ if (ax->rbuff[0] > 0x0f) {
+ if (ax->rbuff[0] & 0x80) {
+ if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
+ ax->stats.rx_errors++;
+ spin_unlock_bh(&ax->buflock);
+
+ return;
+ }
+ if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
+ printk(KERN_INFO
+ "mkiss: %s: Switchting to crc-smack\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_SMACK;
+ }
+ ax->rcount -= 2;
+ *ax->rbuff &= ~0x80;
+ } else if (ax->rbuff[0] & 0x20) {
+ if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+ ax->stats.rx_errors++;
+ spin_unlock_bh(&ax->buflock);
+ return;
+ }
+ if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
+ printk(KERN_INFO
+ "mkiss: %s: Switchting to crc-flexnet\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_FLEX;
+ }
+ ax->rcount -= 2;
+
+ /*
+ * dl9sau bugfix: the trailling two bytes flexnet crc
+ * will not be passed to the kernel. thus we have to
+ * correct the kissparm signature, because it indicates
+ * a crc but there's none
+ */
+ *ax->rbuff &= ~0x20;
}
+ }
+ spin_unlock_bh(&ax->buflock);
+
+ count = ax->rcount;
+
+ if ((skb = dev_alloc_skb(count)) == NULL) {
+ printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
+ ax->dev->name);
+ ax->stats.rx_dropped++;
+ return;
}
- return NULL;
+ spin_lock_bh(&ax->buflock);
+ memcpy(skb_put(skb,count), ax->rbuff, count);
+ spin_unlock_bh(&ax->buflock);
+ skb->protocol = ax25_type_trans(skb, ax->dev);
+ netif_rx(skb);
+ ax->dev->last_rx = jiffies;
+ ax->stats.rx_packets++;
+ ax->stats.rx_bytes += count;
}
-/* Free an AX25 channel. */
-static inline void ax_free(struct ax_disp *ax)
+static void kiss_unesc(struct mkiss *ax, unsigned char s)
{
- /* Free all AX25 frame buffers. */
- if (ax->rbuff)
- kfree(ax->rbuff);
- ax->rbuff = NULL;
- if (ax->xbuff)
- kfree(ax->xbuff);
- ax->xbuff = NULL;
- if (!test_and_clear_bit(AXF_INUSE, &ax->flags))
- printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);
+ switch (s) {
+ case END:
+ /* drop keeptest bit = VSV */
+ if (test_bit(AXF_KEEPTEST, &ax->flags))
+ clear_bit(AXF_KEEPTEST, &ax->flags);
+
+ if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
+ ax_bump(ax);
+
+ clear_bit(AXF_ESCAPE, &ax->flags);
+ ax->rcount = 0;
+ return;
+
+ case ESC:
+ set_bit(AXF_ESCAPE, &ax->flags);
+ return;
+ case ESC_ESC:
+ if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+ s = ESC;
+ break;
+ case ESC_END:
+ if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
+ s = END;
+ break;
+ }
+
+ spin_lock_bh(&ax->buflock);
+ if (!test_bit(AXF_ERROR, &ax->flags)) {
+ if (ax->rcount < ax->buffsize) {
+ ax->rbuff[ax->rcount++] = s;
+ spin_unlock_bh(&ax->buflock);
+ return;
+ }
+
+ ax->stats.rx_over_errors++;
+ set_bit(AXF_ERROR, &ax->flags);
+ }
+ spin_unlock_bh(&ax->buflock);
}
-static void ax_changedmtu(struct ax_disp *ax)
+static int ax_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr_ax25 *sa = addr;
+
+ spin_lock_irq(&dev->xmit_lock);
+ memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+ spin_unlock_irq(&dev->xmit_lock);
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void ax_changedmtu(struct mkiss *ax)
{
struct net_device *dev = ax->dev;
unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
@@ -236,13 +386,12 @@ static void ax_changedmtu(struct ax_disp *ax)
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
- printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
+ printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
+ "MTU change cancelled.\n",
ax->dev->name);
dev->mtu = ax->mtu;
- if (xbuff != NULL)
- kfree(xbuff);
- if (rbuff != NULL)
- kfree(rbuff);
+ kfree(xbuff);
+ kfree(rbuff);
return;
}
@@ -258,7 +407,7 @@ static void ax_changedmtu(struct ax_disp *ax)
memcpy(ax->xbuff, ax->xhead, ax->xleft);
} else {
ax->xleft = 0;
- ax->tx_dropped++;
+ ax->stats.tx_dropped++;
}
}
@@ -269,7 +418,7 @@ static void ax_changedmtu(struct ax_disp *ax)
memcpy(ax->rbuff, orbuff, ax->rcount);
} else {
ax->rcount = 0;
- ax->rx_over_errors++;
+ ax->stats.rx_over_errors++;
set_bit(AXF_ERROR, &ax->flags);
}
}
@@ -279,72 +428,14 @@ static void ax_changedmtu(struct ax_disp *ax)
spin_unlock_bh(&ax->buflock);
- if (oxbuff != NULL)
- kfree(oxbuff);
- if (orbuff != NULL)
- kfree(orbuff);
-}
-
-
-/* Set the "sending" flag. This must be atomic. */
-static inline void ax_lock(struct ax_disp *ax)
-{
- netif_stop_queue(ax->dev);
-}
-
-
-/* Clear the "sending" flag. This must be atomic. */
-static inline void ax_unlock(struct ax_disp *ax)
-{
- netif_start_queue(ax->dev);
-}
-
-/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
-static void ax_bump(struct ax_disp *ax)
-{
- struct sk_buff *skb;
- int count;
-
- spin_lock_bh(&ax->buflock);
- if (ax->rbuff[0] > 0x0f) {
- if (ax->rbuff[0] & 0x20) {
- ax->crcmode = CRC_MODE_FLEX;
- if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
- ax->rx_errors++;
- return;
- }
- ax->rcount -= 2;
- /* dl9sau bugfix: the trailling two bytes flexnet crc
- * will not be passed to the kernel. thus we have
- * to correct the kissparm signature, because it
- * indicates a crc but there's none
- */
- *ax->rbuff &= ~0x20;
- }
- }
- spin_unlock_bh(&ax->buflock);
-
- count = ax->rcount;
-
- if ((skb = dev_alloc_skb(count)) == NULL) {
- printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);
- ax->rx_dropped++;
- return;
- }
-
- spin_lock_bh(&ax->buflock);
- memcpy(skb_put(skb,count), ax->rbuff, count);
- spin_unlock_bh(&ax->buflock);
- skb->protocol = ax25_type_trans(skb, ax->dev);
- netif_rx(skb);
- ax->dev->last_rx = jiffies;
- ax->rx_packets++;
- ax->rx_bytes+=count;
+ kfree(oxbuff);
+ kfree(orbuff);
}
/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
-static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
+static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
{
+ struct mkiss *ax = netdev_priv(dev);
unsigned char *p;
int actual, count;
@@ -354,70 +445,91 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */
len = ax->mtu;
printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
- ax->tx_dropped++;
- ax_unlock(ax);
+ ax->stats.tx_dropped++;
+ netif_start_queue(dev);
return;
}
p = icp;
spin_lock_bh(&ax->buflock);
- switch (ax->crcmode) {
- unsigned short crc;
+ if ((*p & 0x0f) != 0) {
+ /* Configuration Command (kissparms(1).
+ * Protocol spec says: never append CRC.
+ * This fixes a very old bug in the linux
+ * kiss driver. -- dl9sau */
+ switch (*p & 0xff) {
+ case 0x85:
+ /* command from userspace especially for us,
+ * not for delivery to the tnc */
+ if (len > 1) {
+ int cmd = (p[1] & 0xff);
+ switch(cmd) {
+ case 3:
+ ax->crcmode = CRC_MODE_SMACK;
+ break;
+ case 2:
+ ax->crcmode = CRC_MODE_FLEX;
+ break;
+ case 1:
+ ax->crcmode = CRC_MODE_NONE;
+ break;
+ case 0:
+ default:
+ ax->crcmode = CRC_MODE_SMACK_TEST;
+ cmd = 0;
+ }
+ ax->crcauto = (cmd ? 0 : 1);
+ printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
+ }
+ spin_unlock_bh(&ax->buflock);
+ netif_start_queue(dev);
- case CRC_MODE_FLEX:
- *p |= 0x20;
- crc = calc_crc_flex(p, len);
- count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
- break;
+ return;
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ }
+ } else {
+ unsigned short crc;
+ switch (ax->crcmode) {
+ case CRC_MODE_SMACK_TEST:
+ ax->crcmode = CRC_MODE_FLEX_TEST;
+ printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
+ // fall through
+ case CRC_MODE_SMACK:
+ *p |= 0x80;
+ crc = swab16(crc16(0, p, len));
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
+ case CRC_MODE_FLEX_TEST:
+ ax->crcmode = CRC_MODE_NONE;
+ printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
+ // fall through
+ case CRC_MODE_FLEX:
+ *p |= 0x20;
+ crc = calc_crc_flex(p, len);
+ count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+ break;
- default:
- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
- break;
- }
-
- ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ default:
+ count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+ }
+ }
+
+ set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
- ax->tx_packets++;
- ax->tx_bytes+=actual;
+ ax->stats.tx_packets++;
+ ax->stats.tx_bytes += actual;
+
ax->dev->trans_start = jiffies;
ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual;
-
- spin_unlock_bh(&ax->buflock);
-}
-
-/*
- * Called by the driver when there's room for more data. If we have
- * more packets to send, we send them here.
- */
-static void ax25_write_wakeup(struct tty_struct *tty)
-{
- int actual;
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
- return;
- if (ax->xleft <= 0) {
- /* Now serial buffer is almost free & we can start
- * transmission of another packet
- */
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
- netif_wake_queue(ax->dev);
- return;
- }
-
- actual = tty->driver->write(tty, ax->xhead, ax->xleft);
- ax->xleft -= actual;
- ax->xhead += actual;
}
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
if (!netif_running(dev)) {
printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -429,7 +541,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- if (jiffies - dev->trans_start < 20 * HZ) {
+ if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
/* 20 sec timeout not reached */
return 1;
}
@@ -439,20 +551,30 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
"bad line quality" : "driver error");
ax->xleft = 0;
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- ax_unlock(ax);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
+ netif_start_queue(dev);
}
/* We were not busy, so we are now... :-) */
if (skb != NULL) {
- ax_lock(ax);
- ax_encaps(ax, skb->data, skb->len);
+ netif_stop_queue(dev);
+ ax_encaps(dev, skb->data, skb->len);
kfree_skb(skb);
}
return 0;
}
+static int ax_open_dev(struct net_device *dev)
+{
+ struct mkiss *ax = netdev_priv(dev);
+
+ if (ax->tty == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/* Return the frame type ID */
@@ -461,7 +583,7 @@ static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short
{
#ifdef CONFIG_INET
if (type != htons(ETH_P_AX25))
- return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+ return ax25_hard_header(skb, dev, type, daddr, saddr, len);
#endif
return 0;
}
@@ -481,7 +603,7 @@ static int ax_rebuild_header(struct sk_buff *skb)
/* Open the low-level part of the AX25 channel. Easy! */
static int ax_open(struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
unsigned long len;
if (ax->tty == NULL)
@@ -518,7 +640,6 @@ static int ax_open(struct net_device *dev)
spin_lock_init(&ax->buflock);
- netif_start_queue(dev);
return 0;
noxbuff:
@@ -532,68 +653,102 @@ norbuff:
/* Close the low-level part of the AX25 channel. Easy! */
static int ax_close(struct net_device *dev)
{
- struct ax_disp *ax = netdev_priv(dev);
+ struct mkiss *ax = netdev_priv(dev);
- if (ax->tty == NULL)
- return -EBUSY;
-
- ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ if (ax->tty)
+ clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
netif_stop_queue(dev);
return 0;
}
-static int ax25_receive_room(struct tty_struct *tty)
+static struct net_device_stats *ax_get_stats(struct net_device *dev)
{
- return 65536; /* We can handle an infinite amount of data. :-) */
+ struct mkiss *ax = netdev_priv(dev);
+
+ return &ax->stats;
+}
+
+static void ax_setup(struct net_device *dev)
+{
+ static char ax25_bcast[AX25_ADDR_LEN] =
+ {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+ static char ax25_test[AX25_ADDR_LEN] =
+ {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+ /* Finish setting up the DEVICE info. */
+ dev->mtu = AX_MTU;
+ dev->hard_start_xmit = ax_xmit;
+ dev->open = ax_open_dev;
+ dev->stop = ax_close;
+ dev->get_stats = ax_get_stats;
+ dev->set_mac_address = ax_set_mac_address;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_AX25;
+ dev->tx_queue_len = 10;
+ dev->hard_header = ax_header;
+ dev->rebuild_header = ax_rebuild_header;
+
+ memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+
+ dev->flags = IFF_BROADCAST | IFF_MULTICAST;
}
/*
- * Handle the 'receiver data ready' interrupt.
- * This function is called by the 'tty_io' module in the kernel when
- * a block of data has been received, which can now be decapsulated
- * and sent on to the AX.25 layer for further processing.
+ * We have a potential race on dereferencing tty->disc_data, because the tty
+ * layer provides no locking at all - thus one cpu could be running
+ * sixpack_receive_buf while another calls sixpack_close, which zeroes
+ * tty->disc_data and frees the memory that sixpack_receive_buf is using. The
+ * best way to fix this is to use a rwlock in the tty struct, but for now we
+ * use a single global rwlock for all ttys in ppp line discipline.
*/
-static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
-{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+static DEFINE_RWLOCK(disc_data_lock);
- if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
- return;
+static struct mkiss *mkiss_get(struct tty_struct *tty)
+{
+ struct mkiss *ax;
- /*
- * Argh! mtu change time! - costs us the packet part received
- * at the change
- */
- if (ax->mtu != ax->dev->mtu + 73)
- ax_changedmtu(ax);
+ read_lock(&disc_data_lock);
+ ax = tty->disc_data;
+ if (ax)
+ atomic_inc(&ax->refcnt);
+ read_unlock(&disc_data_lock);
- /* Read the characters out of the buffer */
- while (count--) {
- if (fp != NULL && *fp++) {
- if (!test_and_set_bit(AXF_ERROR, &ax->flags))
- ax->rx_errors++;
- cp++;
- continue;
- }
+ return ax;
+}
- kiss_unesc(ax, *cp++);
- }
+static void mkiss_put(struct mkiss *ax)
+{
+ if (atomic_dec_and_test(&ax->refcnt))
+ up(&ax->dead_sem);
}
-static int ax25_open(struct tty_struct *tty)
+static int crc_force = 0; /* Can be overridden with insmod */
+
+static int mkiss_open(struct tty_struct *tty)
{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+ struct net_device *dev;
+ struct mkiss *ax;
int err;
- /* First make sure we're not already connected. */
- if (ax && ax->magic == AX25_MAGIC)
- return -EEXIST;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+ if (!dev) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ ax = netdev_priv(dev);
+ ax->dev = dev;
- /* OK. Find a free AX25 channel to use. */
- if ((ax = ax_alloc()) == NULL)
- return -ENFILE;
+ spin_lock_init(&ax->buflock);
+ atomic_set(&ax->refcnt, 1);
+ init_MUTEX_LOCKED(&ax->dead_sem);
ax->tty = tty;
tty->disc_data = ax;
@@ -602,283 +757,239 @@ static int ax25_open(struct tty_struct *tty)
tty->driver->flush_buffer(tty);
/* Restore default settings */
- ax->dev->type = ARPHRD_AX25;
+ dev->type = ARPHRD_AX25;
/* Perform the low-level AX25 initialization. */
- if ((err = ax_open(ax->dev)))
- return err;
-
- /* Done. We have linked the TTY line to a channel. */
- return ax->dev->base_addr;
-}
+ if ((err = ax_open(ax->dev))) {
+ goto out_free_netdev;
+ }
-static void ax25_close(struct tty_struct *tty)
-{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
+ if (register_netdev(dev))
+ goto out_free_buffers;
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return;
+ /* after register_netdev() - because else printk smashes the kernel */
+ switch (crc_force) {
+ case 3:
+ ax->crcmode = CRC_MODE_SMACK;
+ printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
+ ax->dev->name);
+ break;
+ case 2:
+ ax->crcmode = CRC_MODE_FLEX;
+ printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
+ ax->dev->name);
+ break;
+ case 1:
+ ax->crcmode = CRC_MODE_NONE;
+ printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
+ ax->dev->name);
+ break;
+ case 0:
+ /* fall through */
+ default:
+ crc_force = 0;
+ printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
+ ax->dev->name);
+ ax->crcmode = CRC_MODE_SMACK_TEST;
+ }
+ ax->crcauto = (crc_force ? 0 : 1);
- unregister_netdev(ax->dev);
+ netif_start_queue(dev);
- tty->disc_data = NULL;
- ax->tty = NULL;
+ /* Done. We have linked the TTY line to a channel. */
+ return 0;
- ax_free(ax);
-}
+out_free_buffers:
+ kfree(ax->rbuff);
+ kfree(ax->xbuff);
+out_free_netdev:
+ free_netdev(dev);
-static struct net_device_stats *ax_get_stats(struct net_device *dev)
-{
- static struct net_device_stats stats;
- struct ax_disp *ax = netdev_priv(dev);
-
- memset(&stats, 0, sizeof(struct net_device_stats));
-
- stats.rx_packets = ax->rx_packets;
- stats.tx_packets = ax->tx_packets;
- stats.rx_bytes = ax->rx_bytes;
- stats.tx_bytes = ax->tx_bytes;
- stats.rx_dropped = ax->rx_dropped;
- stats.tx_dropped = ax->tx_dropped;
- stats.tx_errors = ax->tx_errors;
- stats.rx_errors = ax->rx_errors;
- stats.rx_over_errors = ax->rx_over_errors;
-
- return &stats;
+out:
+ return err;
}
+static void mkiss_close(struct tty_struct *tty)
+{
+ struct mkiss *ax;
-/************************************************************************
- * STANDARD ENCAPSULATION *
- ************************************************************************/
+ write_lock(&disc_data_lock);
+ ax = tty->disc_data;
+ tty->disc_data = NULL;
+ write_unlock(&disc_data_lock);
-static int kiss_esc(unsigned char *s, unsigned char *d, int len)
-{
- unsigned char *ptr = d;
- unsigned char c;
+ if (ax == 0)
+ return;
/*
- * Send an initial END character to flush out any
- * data that may have accumulated in the receiver
- * due to line noise.
+ * We have now ensured that nobody can start using ap from now on, but
+ * we have to wait for all existing users to finish.
*/
+ if (!atomic_dec_and_test(&ax->refcnt))
+ down(&ax->dead_sem);
- *ptr++ = END;
-
- while (len-- > 0) {
- switch (c = *s++) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
- }
- }
+ unregister_netdev(ax->dev);
- *ptr++ = END;
+ /* Free all AX25 frame buffers. */
+ kfree(ax->rbuff);
+ kfree(ax->xbuff);
- return ptr - d;
+ ax->tty = NULL;
}
-/*
- * MW:
- * OK its ugly, but tell me a better solution without copying the
- * packet to a temporary buffer :-)
- */
-static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc, int len)
+/* Perform I/O control on an active ax25 channel. */
+static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- unsigned char *ptr = d;
- unsigned char c=0;
-
- *ptr++ = END;
- while (len > 0) {
- if (len > 2)
- c = *s++;
- else if (len > 1)
- c = crc >> 8;
- else if (len > 0)
- c = crc & 0xff;
+ struct mkiss *ax = mkiss_get(tty);
+ struct net_device *dev = ax->dev;
+ unsigned int tmp, err;
- len--;
+ /* First make sure we're connected. */
+ if (ax == NULL)
+ return -ENXIO;
- switch (c) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
+ switch (cmd) {
+ case SIOCGIFNAME:
+ err = copy_to_user((void __user *) arg, ax->dev->name,
+ strlen(ax->dev->name) + 1) ? -EFAULT : 0;
+ break;
+
+ case SIOCGIFENCAP:
+ err = put_user(4, (int __user *) arg);
+ break;
+
+ case SIOCSIFENCAP:
+ if (get_user(tmp, (int __user *) arg)) {
+ err = -EFAULT;
+ break;
}
- }
- *ptr++ = END;
- return ptr - d;
-}
-static void kiss_unesc(struct ax_disp *ax, unsigned char s)
-{
- switch (s) {
- case END:
- /* drop keeptest bit = VSV */
- if (test_bit(AXF_KEEPTEST, &ax->flags))
- clear_bit(AXF_KEEPTEST, &ax->flags);
+ ax->mode = tmp;
+ dev->addr_len = AX25_ADDR_LEN;
+ dev->hard_header_len = AX25_KISS_HEADER_LEN +
+ AX25_MAX_HEADER_LEN + 3;
+ dev->type = ARPHRD_AX25;
- if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
- ax_bump(ax);
+ err = 0;
+ break;
- clear_bit(AXF_ESCAPE, &ax->flags);
- ax->rcount = 0;
- return;
+ case SIOCSIFHWADDR: {
+ char addr[AX25_ADDR_LEN];
- case ESC:
- set_bit(AXF_ESCAPE, &ax->flags);
- return;
- case ESC_ESC:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = ESC;
+ if (copy_from_user(&addr,
+ (void __user *) arg, AX25_ADDR_LEN)) {
+ err = -EFAULT;
break;
- case ESC_END:
- if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
- s = END;
- break;
- }
-
- spin_lock_bh(&ax->buflock);
- if (!test_bit(AXF_ERROR, &ax->flags)) {
- if (ax->rcount < ax->buffsize) {
- ax->rbuff[ax->rcount++] = s;
- spin_unlock_bh(&ax->buflock);
- return;
}
- ax->rx_over_errors++;
- set_bit(AXF_ERROR, &ax->flags);
+ spin_lock_irq(&dev->xmit_lock);
+ memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
+ spin_unlock_irq(&dev->xmit_lock);
+
+ err = 0;
+ break;
+ }
+ default:
+ err = -ENOIOCTLCMD;
}
- spin_unlock_bh(&ax->buflock);
-}
+ mkiss_put(ax);
-static int ax_set_mac_address(struct net_device *dev, void __user *addr)
-{
- if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
- return -EFAULT;
- return 0;
+ return err;
}
-static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of data has been received, which can now be decapsulated
+ * and sent on to the AX.25 layer for further processing.
+ */
+static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ char *fp, int count)
{
- struct sockaddr *sa = addr;
-
- memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
-
- return 0;
-}
+ struct mkiss *ax = mkiss_get(tty);
+ if (!ax)
+ return;
-/* Perform I/O control on an active ax25 channel. */
-static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void __user *arg)
-{
- struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
- unsigned int tmp;
-
- /* First make sure we're connected. */
- if (ax == NULL || ax->magic != AX25_MAGIC)
- return -EINVAL;
+ /*
+ * Argh! mtu change time! - costs us the packet part received
+ * at the change
+ */
+ if (ax->mtu != ax->dev->mtu + 73)
+ ax_changedmtu(ax);
- switch (cmd) {
- case SIOCGIFNAME:
- if (copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1))
- return -EFAULT;
- return 0;
-
- case SIOCGIFENCAP:
- return put_user(4, (int __user *)arg);
-
- case SIOCSIFENCAP:
- if (get_user(tmp, (int __user *)arg))
- return -EFAULT;
- ax->mode = tmp;
- ax->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
- ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
- ax->dev->type = ARPHRD_AX25;
- return 0;
-
- case SIOCSIFHWADDR:
- return ax_set_mac_address(ax->dev, arg);
+ /* Read the characters out of the buffer */
+ while (count--) {
+ if (fp != NULL && *fp++) {
+ if (!test_and_set_bit(AXF_ERROR, &ax->flags))
+ ax->stats.rx_errors++;
+ cp++;
+ continue;
+ }
- default:
- return -ENOIOCTLCMD;
+ kiss_unesc(ax, *cp++);
}
+
+ mkiss_put(ax);
+ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+ && tty->driver->unthrottle)
+ tty->driver->unthrottle(tty);
}
-static int ax_open_dev(struct net_device *dev)
+static int mkiss_receive_room(struct tty_struct *tty)
{
- struct ax_disp *ax = netdev_priv(dev);
-
- if (ax->tty == NULL)
- return -ENODEV;
-
- return 0;
+ return 65536; /* We can handle an infinite amount of data. :-) */
}
-
-/* Initialize the driver. Called by network startup. */
-static int ax25_init(struct net_device *dev)
+/*
+ * Called by the driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ */
+static void mkiss_write_wakeup(struct tty_struct *tty)
{
- struct ax_disp *ax = netdev_priv(dev);
-
- static char ax25_bcast[AX25_ADDR_LEN] =
- {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
- static char ax25_test[AX25_ADDR_LEN] =
- {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
- if (ax == NULL) /* Allocation failed ?? */
- return -ENODEV;
+ struct mkiss *ax = mkiss_get(tty);
+ int actual;
- /* Set up the "AX25 Control Block". (And clear statistics) */
- memset(ax, 0, sizeof (struct ax_disp));
- ax->magic = AX25_MAGIC;
- ax->dev = dev;
+ if (!ax)
+ return;
- /* Finish setting up the DEVICE info. */
- dev->mtu = AX_MTU;
- dev->hard_start_xmit = ax_xmit;
- dev->open = ax_open_dev;
- dev->stop = ax_close;
- dev->get_stats = ax_get_stats;
- dev->set_mac_address = ax_set_dev_mac_address;
- dev->hard_header_len = 0;
- dev->addr_len = 0;
- dev->type = ARPHRD_AX25;
- dev->tx_queue_len = 10;
- dev->hard_header = ax_header;
- dev->rebuild_header = ax_rebuild_header;
+ if (ax->xleft <= 0) {
+ /* Now serial buffer is almost free & we can start
+ * transmission of another packet
+ */
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ netif_wake_queue(ax->dev);
+ goto out;
+ }
- /* New-style flags. */
- dev->flags = IFF_BROADCAST | IFF_MULTICAST;
+ actual = tty->driver->write(tty, ax->xhead, ax->xleft);
+ ax->xleft -= actual;
+ ax->xhead += actual;
- return 0;
+out:
+ mkiss_put(ax);
}
+static struct tty_ldisc ax_ldisc = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "mkiss",
+ .open = mkiss_open,
+ .close = mkiss_close,
+ .ioctl = mkiss_ioctl,
+ .receive_buf = mkiss_receive_buf,
+ .receive_room = mkiss_receive_room,
+ .write_wakeup = mkiss_write_wakeup
+};
-/* ******************************************************************** */
-/* * Init MKISS driver * */
-/* ******************************************************************** */
+static char banner[] __initdata = KERN_INFO \
+ "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
+static char msg_regfail[] __initdata = KERN_ERR \
+ "mkiss: can't register line discipline (err = %d)\n";
static int __init mkiss_init_driver(void)
{
@@ -886,64 +997,29 @@ static int __init mkiss_init_driver(void)
printk(banner);
- if (ax25_maxdev < 4)
- ax25_maxdev = 4; /* Sanity */
+ if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
+ printk(msg_regfail);
- if ((ax25_ctrls = kmalloc(sizeof(void *) * ax25_maxdev, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array!\n");
- return -ENOMEM;
- }
-
- /* Clear the pointer array, we allocate devices when we need them */
- memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
-
- /* Fill in our line protocol discipline, and register it */
- ax_ldisc.magic = TTY_LDISC_MAGIC;
- ax_ldisc.name = "mkiss";
- ax_ldisc.open = ax25_open;
- ax_ldisc.close = ax25_close;
- ax_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
- unsigned int, unsigned long))ax25_disp_ioctl;
- ax_ldisc.receive_buf = ax25_receive_buf;
- ax_ldisc.receive_room = ax25_receive_room;
- ax_ldisc.write_wakeup = ax25_write_wakeup;
-
- if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) {
- printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
- kfree(ax25_ctrls);
- }
return status;
}
+static const char msg_unregfail[] __exitdata = KERN_ERR \
+ "mkiss: can't unregister line discipline (err = %d)\n";
+
static void __exit mkiss_exit_driver(void)
{
- int i;
+ int ret;
- for (i = 0; i < ax25_maxdev; i++) {
- if (ax25_ctrls[i]) {
- /*
- * VSV = if dev->start==0, then device
- * unregistered while close proc.
- */
- if (netif_running(&ax25_ctrls[i]->dev))
- unregister_netdev(&ax25_ctrls[i]->dev);
- kfree(ax25_ctrls[i]);
- }
- }
-
- kfree(ax25_ctrls);
- ax25_ctrls = NULL;
-
- if ((i = tty_unregister_ldisc(N_AX25)))
- printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
+ if ((ret = tty_unregister_ldisc(N_AX25)))
+ printk(msg_unregfail, ret);
}
-MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
+MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-MODULE_PARM(ax25_maxdev, "i");
-MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
+MODULE_PARM(crc_force, "i");
+MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
+
module_init(mkiss_init_driver);
module_exit(mkiss_exit_driver);
-
diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
deleted file mode 100644
index 4ab700478598..000000000000
--- a/drivers/net/hamradio/mkiss.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
- * Defines for the Multi-KISS driver.
- ****************************************************************************/
-
-#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
- This can be overridden with
- insmod -oax25_maxdev=nnn */
-#define AX_MTU 236
-
-/* SLIP/KISS protocol characters. */
-#define END 0300 /* indicates end of frame */
-#define ESC 0333 /* indicates byte stuffing */
-#define ESC_END 0334 /* ESC ESC_END means END 'data' */
-#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-
-struct ax_disp {
- int magic;
-
- /* Various fields. */
- struct tty_struct *tty; /* ptr to TTY structure */
- struct net_device *dev; /* easy for intr handling */
-
- /* These are pointers to the malloc()ed frame buffers. */
- unsigned char *rbuff; /* receiver buffer */
- int rcount; /* received chars counter */
- unsigned char *xbuff; /* transmitter buffer */
- unsigned char *xhead; /* pointer to next byte to XMIT */
- int xleft; /* bytes left in XMIT queue */
-
- /* SLIP interface statistics. */
- unsigned long rx_packets; /* inbound frames counter */
- unsigned long tx_packets; /* outbound frames counter */
- unsigned long rx_bytes; /* inbound bytes counter */
- unsigned long tx_bytes; /* outbound bytes counter */
- unsigned long rx_errors; /* Parity, etc. errors */
- unsigned long tx_errors; /* Planned stuff */
- unsigned long rx_dropped; /* No memory for skb */
- unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
-
- /* Detailed SLIP statistics. */
- int mtu; /* Our mtu (to spot changes!) */
- int buffsize; /* Max buffers sizes */
-
-
- unsigned long flags; /* Flag values/ mode etc */
- /* long req'd: used by set_bit --RR */
-#define AXF_INUSE 0 /* Channel in use */
-#define AXF_ESCAPE 1 /* ESC received */
-#define AXF_ERROR 2 /* Parity, etc. error */
-#define AXF_KEEPTEST 3 /* Keepalive test flag */
-#define AXF_OUTWAIT 4 /* is outpacket was flag */
-
- int mode;
- int crcmode; /* MW: for FlexNet, SMACK etc. */
-#define CRC_MODE_NONE 0
-#define CRC_MODE_FLEX 1
-#define CRC_MODE_SMACK 2
- spinlock_t buflock; /* lock for rbuf and xbuf */
-};
-
-#define AX25_MAGIC 0x5316
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index c27e417f32bf..6ace0e914fd1 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1557,7 +1557,7 @@ static void scc_net_setup(struct net_device *dev)
dev->stop = scc_net_close;
dev->hard_start_xmit = scc_net_tx;
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_net_set_mac_address;
dev->get_stats = scc_net_get_stats;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 41213ef602dc..fe22479eb202 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -60,15 +60,7 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
-
-/* make genksyms happy */
-#include <linux/ip.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
@@ -170,7 +162,7 @@ static char ax25_bcast[7] =
static char ax25_test[7] =
{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-static struct timer_list yam_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(yam_timer, NULL, 0, 0);
/* --------------------------------------------------------------------- */
@@ -1116,23 +1108,17 @@ static void yam_setup(struct net_device *dev)
skb_queue_head_init(&yp->send_queue);
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- dev->hard_header = ax25_encapsulate;
+ dev->hard_header = ax25_hard_header;
dev->rebuild_header = ax25_rebuild_header;
-#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
- dev->hard_header = NULL;
- dev->rebuild_header = NULL;
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = yam_set_mac_address;
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = 73; /* We do digipeaters now */
- dev->mtu = 256; /* AX25 is the default */
- dev->addr_len = 7; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, 7);
- memcpy(dev->dev_addr, ax25_test, 7);
-
+ dev->type = ARPHRD_AX25;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
+ dev->mtu = AX25_MTU;
+ dev->addr_len = AX25_ADDR_LEN;
+ memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
}
static int __init yam_init_driver(void)
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index cf0ac6fda1a1..b71fab6e34f4 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
if (time_after_eq(jiffies, time)) /* no signal->no logout */
@@ -2536,10 +2534,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
#ifdef HP100_DEBUG
@@ -2577,10 +2573,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
hp100_orb(HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */
@@ -2591,10 +2585,8 @@ static int hp100_down_vg_link(struct net_device *dev)
do {
if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
if (time_before_eq(time, jiffies)) {
@@ -2606,10 +2598,8 @@ static int hp100_down_vg_link(struct net_device *dev)
time = jiffies + (2 * HZ); /* This seems to take a while.... */
do {
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
return 0;
@@ -2659,10 +2649,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
/* Start an addressed training and optionally request promiscuous port */
@@ -2697,10 +2685,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
do {
if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
break;
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_before(jiffies, time));
if (time_after_eq(jiffies, time)) {
@@ -2723,10 +2709,8 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
#endif
break;
}
- if (!in_interrupt()) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ if (!in_interrupt())
+ schedule_timeout_interruptible(1);
} while (time_after(time, jiffies));
}
diff --git a/drivers/net/ibm_emac/Makefile b/drivers/net/ibm_emac/Makefile
index 7f583a333c24..f98ddf0e807a 100644
--- a/drivers/net/ibm_emac/Makefile
+++ b/drivers/net/ibm_emac/Makefile
@@ -1,12 +1,11 @@
#
-# Makefile for the IBM PPC4xx EMAC controllers
+# Makefile for the PowerPC 4xx on-chip ethernet driver
#
obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
-ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
-
-# Only need this if you want to see additional debug messages
-ifeq ($(CONFIG_IBM_EMAC_ERRMSG), y)
-ibm_emac-objs += ibm_emac_debug.o
-endif
+ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
+ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += ibm_emac_zmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += ibm_emac_rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_TAH) += ibm_emac_tah.o
+ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += ibm_emac_debug.o
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 15d5a0e82862..28c476f28c20 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -1,110 +1,142 @@
/*
- * ibm_emac.h
+ * drivers/net/ibm_emac/ibm_emac.h
*
+ * Register definitions for PowerPC 4xx on-chip ethernet contoller
*
- * Armin Kuster akuster@mvista.com
- * June, 2002
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Copyright 2002 MontaVista Softare Inc.
+ * Based on original work by
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Armin Kuster <akuster@mvista.com>
+ * Copyright 2002-2004 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
*/
+#ifndef __IBM_EMAC_H_
+#define __IBM_EMAC_H_
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+/* This is a simple check to prevent use of this driver on non-tested SoCs */
+#if !defined(CONFIG_405GP) && !defined(CONFIG_405GPR) && !defined(CONFIG_405EP) && \
+ !defined(CONFIG_440GP) && !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && \
+ !defined(CONFIG_440EP) && !defined(CONFIG_NP405H)
+#error "Unknown SoC. Please, check chip user manual and make sure EMAC defines are OK"
+#endif
+
+/* EMAC registers Write Access rules */
+struct emac_regs {
+ u32 mr0; /* special */
+ u32 mr1; /* Reset */
+ u32 tmr0; /* special */
+ u32 tmr1; /* special */
+ u32 rmr; /* Reset */
+ u32 isr; /* Always */
+ u32 iser; /* Reset */
+ u32 iahr; /* Reset, R, T */
+ u32 ialr; /* Reset, R, T */
+ u32 vtpid; /* Reset, R, T */
+ u32 vtci; /* Reset, R, T */
+ u32 ptr; /* Reset, T */
+ u32 iaht1; /* Reset, R */
+ u32 iaht2; /* Reset, R */
+ u32 iaht3; /* Reset, R */
+ u32 iaht4; /* Reset, R */
+ u32 gaht1; /* Reset, R */
+ u32 gaht2; /* Reset, R */
+ u32 gaht3; /* Reset, R */
+ u32 gaht4; /* Reset, R */
+ u32 lsah;
+ u32 lsal;
+ u32 ipgvr; /* Reset, T */
+ u32 stacr; /* special */
+ u32 trtr; /* special */
+ u32 rwmr; /* Reset */
+ u32 octx;
+ u32 ocrx;
+ u32 ipcr;
+};
+
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_ETHTOOL_REGS_VER 0
+#define EMAC_ETHTOOL_REGS_SIZE (sizeof(struct emac_regs) - sizeof(u32))
+#else
+#define EMAC_ETHTOOL_REGS_VER 1
+#define EMAC_ETHTOOL_REGS_SIZE sizeof(struct emac_regs)
+#endif
-#ifndef _IBM_EMAC_H_
-#define _IBM_EMAC_H_
-/* General defines needed for the driver */
+/* EMACx_MR0 */
+#define EMAC_MR0_RXI 0x80000000
+#define EMAC_MR0_TXI 0x40000000
+#define EMAC_MR0_SRST 0x20000000
+#define EMAC_MR0_TXE 0x10000000
+#define EMAC_MR0_RXE 0x08000000
+#define EMAC_MR0_WKE 0x04000000
-/* Emac */
-typedef struct emac_regs {
- u32 em0mr0;
- u32 em0mr1;
- u32 em0tmr0;
- u32 em0tmr1;
- u32 em0rmr;
- u32 em0isr;
- u32 em0iser;
- u32 em0iahr;
- u32 em0ialr;
- u32 em0vtpid;
- u32 em0vtci;
- u32 em0ptr;
- u32 em0iaht1;
- u32 em0iaht2;
- u32 em0iaht3;
- u32 em0iaht4;
- u32 em0gaht1;
- u32 em0gaht2;
- u32 em0gaht3;
- u32 em0gaht4;
- u32 em0lsah;
- u32 em0lsal;
- u32 em0ipgvr;
- u32 em0stacr;
- u32 em0trtr;
- u32 em0rwmr;
-} emac_t;
+/* EMACx_MR1 */
+#define EMAC_MR1_FDE 0x80000000
+#define EMAC_MR1_ILE 0x40000000
+#define EMAC_MR1_VLE 0x20000000
+#define EMAC_MR1_EIFC 0x10000000
+#define EMAC_MR1_APP 0x08000000
+#define EMAC_MR1_IST 0x01000000
-/* MODE REG 0 */
-#define EMAC_M0_RXI 0x80000000
-#define EMAC_M0_TXI 0x40000000
-#define EMAC_M0_SRST 0x20000000
-#define EMAC_M0_TXE 0x10000000
-#define EMAC_M0_RXE 0x08000000
-#define EMAC_M0_WKE 0x04000000
+#define EMAC_MR1_MF_MASK 0x00c00000
+#define EMAC_MR1_MF_10 0x00000000
+#define EMAC_MR1_MF_100 0x00400000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_MR1_MF_1000 0x00000000
+#define EMAC_MR1_MF_1000GPCS 0x00000000
+#define EMAC_MR1_MF_IPPA(id) 0x00000000
+#else
+#define EMAC_MR1_MF_1000 0x00800000
+#define EMAC_MR1_MF_1000GPCS 0x00c00000
+#define EMAC_MR1_MF_IPPA(id) (((id) & 0x1f) << 6)
+#endif
-/* MODE Reg 1 */
-#define EMAC_M1_FDE 0x80000000
-#define EMAC_M1_ILE 0x40000000
-#define EMAC_M1_VLE 0x20000000
-#define EMAC_M1_EIFC 0x10000000
-#define EMAC_M1_APP 0x08000000
-#define EMAC_M1_AEMI 0x02000000
-#define EMAC_M1_IST 0x01000000
-#define EMAC_M1_MF_1000GPCS 0x00c00000 /* Internal GPCS */
-#define EMAC_M1_MF_1000MBPS 0x00800000 /* External GPCS */
-#define EMAC_M1_MF_100MBPS 0x00400000
-#define EMAC_M1_RFS_16K 0x00280000 /* 000 for 512 byte */
-#define EMAC_M1_TR 0x00008000
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_M1_RFS_8K 0x00200000
-#define EMAC_M1_RFS_4K 0x00180000
-#define EMAC_M1_RFS_2K 0x00100000
-#define EMAC_M1_RFS_1K 0x00080000
-#define EMAC_M1_TX_FIFO_16K 0x00050000 /* 0's for 512 byte */
-#define EMAC_M1_TX_FIFO_8K 0x00040000
-#define EMAC_M1_TX_FIFO_4K 0x00030000
-#define EMAC_M1_TX_FIFO_2K 0x00020000
-#define EMAC_M1_TX_FIFO_1K 0x00010000
-#define EMAC_M1_TX_TR 0x00008000
-#define EMAC_M1_TX_MWSW 0x00001000 /* 0 wait for status */
-#define EMAC_M1_JUMBO_ENABLE 0x00000800 /* Upt to 9Kr status */
-#define EMAC_M1_OPB_CLK_66 0x00000008 /* 66Mhz */
-#define EMAC_M1_OPB_CLK_83 0x00000010 /* 83Mhz */
-#define EMAC_M1_OPB_CLK_100 0x00000018 /* 100Mhz */
-#define EMAC_M1_OPB_CLK_100P 0x00000020 /* 100Mhz+ */
-#else /* CONFIG_IBM_EMAC4 */
-#define EMAC_M1_RFS_4K 0x00300000 /* ~4k for 512 byte */
-#define EMAC_M1_RFS_2K 0x00200000
-#define EMAC_M1_RFS_1K 0x00100000
-#define EMAC_M1_TX_FIFO_2K 0x00080000 /* 0's for 512 byte */
-#define EMAC_M1_TX_FIFO_1K 0x00040000
-#define EMAC_M1_TR0_DEPEND 0x00010000 /* 0'x for single packet */
-#define EMAC_M1_TR1_DEPEND 0x00004000
-#define EMAC_M1_TR1_MULTI 0x00002000
-#define EMAC_M1_JUMBO_ENABLE 0x00001000
-#endif /* CONFIG_IBM_EMAC4 */
-#define EMAC_M1_BASE (EMAC_M1_TX_FIFO_2K | \
- EMAC_M1_APP | \
- EMAC_M1_TR | EMAC_M1_VLE)
+#define EMAC_TX_FIFO_SIZE 2048
-/* Transmit Mode Register 0 */
-#define EMAC_TMR0_GNP0 0x80000000
-#define EMAC_TMR0_GNP1 0x40000000
-#define EMAC_TMR0_GNPD 0x20000000
-#define EMAC_TMR0_FC 0x10000000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_MR1_RFS_4K 0x00300000
+#define EMAC_MR1_RFS_16K 0x00000000
+#define EMAC_RX_FIFO_SIZE(gige) 4096
+#define EMAC_MR1_TFS_2K 0x00080000
+#define EMAC_MR1_TR0_MULT 0x00008000
+#define EMAC_MR1_JPSM 0x00000000
+#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT)
+#else
+#define EMAC_MR1_RFS_4K 0x00180000
+#define EMAC_MR1_RFS_16K 0x00280000
+#define EMAC_RX_FIFO_SIZE(gige) ((gige) ? 16384 : 4096)
+#define EMAC_MR1_TFS_2K 0x00020000
+#define EMAC_MR1_TR 0x00008000
+#define EMAC_MR1_MWSW_001 0x00001000
+#define EMAC_MR1_JPSM 0x00000800
+#define EMAC_MR1_OBCI_MASK 0x00000038
+#define EMAC_MR1_OBCI_50 0x00000000
+#define EMAC_MR1_OBCI_66 0x00000008
+#define EMAC_MR1_OBCI_83 0x00000010
+#define EMAC_MR1_OBCI_100 0x00000018
+#define EMAC_MR1_OBCI_100P 0x00000020
+#define EMAC_MR1_OBCI(freq) ((freq) <= 50 ? EMAC_MR1_OBCI_50 : \
+ (freq) <= 66 ? EMAC_MR1_OBCI_66 : \
+ (freq) <= 83 ? EMAC_MR1_OBCI_83 : \
+ (freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P)
+#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \
+ EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb))
+#endif
+
+/* EMACx_TMR0 */
+#define EMAC_TMR0_GNP 0x80000000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TMR0_DEFAULT 0x00000000
+#else
#define EMAC_TMR0_TFAE_2_32 0x00000001
#define EMAC_TMR0_TFAE_4_64 0x00000002
#define EMAC_TMR0_TFAE_8_128 0x00000003
@@ -112,14 +144,36 @@ typedef struct emac_regs {
#define EMAC_TMR0_TFAE_32_512 0x00000005
#define EMAC_TMR0_TFAE_64_1024 0x00000006
#define EMAC_TMR0_TFAE_128_2048 0x00000007
+#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32
+#endif
+#define EMAC_TMR0_XMIT (EMAC_TMR0_GNP | EMAC_TMR0_DEFAULT)
+
+/* EMACx_TMR1 */
+
+/* IBM manuals are not very clear here.
+ * This is my interpretation of how things are. --ebs
+ */
+#if defined(CONFIG_40x)
+#define EMAC_FIFO_ENTRY_SIZE 8
+#define EMAC_MAL_BURST_SIZE (16 * 4)
+#else
+#define EMAC_FIFO_ENTRY_SIZE 16
+#define EMAC_MAL_BURST_SIZE (64 * 4)
+#endif
+
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TMR1(l,h) (((l) << 27) | (((h) & 0xff) << 16))
+#else
+#define EMAC_TMR1(l,h) (((l) << 27) | (((h) & 0x3ff) << 14))
+#endif
-/* Receive Mode Register */
+/* EMACx_RMR */
#define EMAC_RMR_SP 0x80000000
#define EMAC_RMR_SFCS 0x40000000
-#define EMAC_RMR_ARRP 0x20000000
-#define EMAC_RMR_ARP 0x10000000
-#define EMAC_RMR_AROP 0x08000000
-#define EMAC_RMR_ARPI 0x04000000
+#define EMAC_RMR_RRP 0x20000000
+#define EMAC_RMR_RFP 0x10000000
+#define EMAC_RMR_ROP 0x08000000
+#define EMAC_RMR_RPIR 0x04000000
#define EMAC_RMR_PPP 0x02000000
#define EMAC_RMR_PME 0x01000000
#define EMAC_RMR_PMME 0x00800000
@@ -127,6 +181,9 @@ typedef struct emac_regs {
#define EMAC_RMR_MIAE 0x00200000
#define EMAC_RMR_BAE 0x00100000
#define EMAC_RMR_MAE 0x00080000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_RMR_BASE 0x00000000
+#else
#define EMAC_RMR_RFAF_2_32 0x00000001
#define EMAC_RMR_RFAF_4_64 0x00000002
#define EMAC_RMR_RFAF_8_128 0x00000003
@@ -134,9 +191,21 @@ typedef struct emac_regs {
#define EMAC_RMR_RFAF_32_512 0x00000005
#define EMAC_RMR_RFAF_64_1024 0x00000006
#define EMAC_RMR_RFAF_128_2048 0x00000007
-#define EMAC_RMR_BASE (EMAC_RMR_IAE | EMAC_RMR_BAE)
+#define EMAC_RMR_BASE EMAC_RMR_RFAF_128_2048
+#endif
-/* Interrupt Status & enable Regs */
+/* EMACx_ISR & EMACx_ISER */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_ISR_TXPE 0x00000000
+#define EMAC_ISR_RXPE 0x00000000
+#define EMAC_ISR_TXUE 0x00000000
+#define EMAC_ISR_RXOE 0x00000000
+#else
+#define EMAC_ISR_TXPE 0x20000000
+#define EMAC_ISR_RXPE 0x10000000
+#define EMAC_ISR_TXUE 0x08000000
+#define EMAC_ISR_RXOE 0x04000000
+#endif
#define EMAC_ISR_OVR 0x02000000
#define EMAC_ISR_PP 0x01000000
#define EMAC_ISR_BP 0x00800000
@@ -147,53 +216,62 @@ typedef struct emac_regs {
#define EMAC_ISR_PTLE 0x00040000
#define EMAC_ISR_ORE 0x00020000
#define EMAC_ISR_IRE 0x00010000
-#define EMAC_ISR_DBDM 0x00000200
-#define EMAC_ISR_DB0 0x00000100
-#define EMAC_ISR_SE0 0x00000080
-#define EMAC_ISR_TE0 0x00000040
-#define EMAC_ISR_DB1 0x00000020
-#define EMAC_ISR_SE1 0x00000010
-#define EMAC_ISR_TE1 0x00000008
+#define EMAC_ISR_SQE 0x00000080
+#define EMAC_ISR_TE 0x00000040
#define EMAC_ISR_MOS 0x00000002
#define EMAC_ISR_MOF 0x00000001
-/* STA CONTROL REG */
+/* EMACx_STACR */
+#define EMAC_STACR_PHYD_MASK 0xffff
+#define EMAC_STACR_PHYD_SHIFT 16
#define EMAC_STACR_OC 0x00008000
#define EMAC_STACR_PHYE 0x00004000
-#define EMAC_STACR_WRITE 0x00002000
-#define EMAC_STACR_READ 0x00001000
-#define EMAC_STACR_CLK_83MHZ 0x00000800 /* 0's for 50Mhz */
-#define EMAC_STACR_CLK_66MHZ 0x00000400
-#define EMAC_STACR_CLK_100MHZ 0x00000C00
+#define EMAC_STACR_STAC_MASK 0x00003000
+#define EMAC_STACR_STAC_READ 0x00001000
+#define EMAC_STACR_STAC_WRITE 0x00002000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_STACR_OPBC_MASK 0x00000C00
+#define EMAC_STACR_OPBC_50 0x00000000
+#define EMAC_STACR_OPBC_66 0x00000400
+#define EMAC_STACR_OPBC_83 0x00000800
+#define EMAC_STACR_OPBC_100 0x00000C00
+#define EMAC_STACR_OPBC(freq) ((freq) <= 50 ? EMAC_STACR_OPBC_50 : \
+ (freq) <= 66 ? EMAC_STACR_OPBC_66 : \
+ (freq) <= 83 ? EMAC_STACR_OPBC_83 : EMAC_STACR_OPBC_100)
+#define EMAC_STACR_BASE(opb) EMAC_STACR_OPBC(opb)
+#else
+#define EMAC_STACR_BASE(opb) 0x00000000
+#endif
+#define EMAC_STACR_PCDA_MASK 0x1f
+#define EMAC_STACR_PCDA_SHIFT 5
+#define EMAC_STACR_PRA_MASK 0x1f
+
+/* EMACx_TRTR */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TRTR_SHIFT 27
+#else
+#define EMAC_TRTR_SHIFT 24
+#endif
+#define EMAC_TRTR(size) ((((size) >> 6) - 1) << EMAC_TRTR_SHIFT)
-/* Transmit Request Threshold Register */
-#define EMAC_TRTR_1600 0x18000000 /* 0's for 64 Bytes */
-#define EMAC_TRTR_1024 0x0f000000
-#define EMAC_TRTR_512 0x07000000
-#define EMAC_TRTR_256 0x03000000
-#define EMAC_TRTR_192 0x10000000
-#define EMAC_TRTR_128 0x01000000
+/* EMACx_RWMR */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_RWMR(l,h) (((l) << 23) | ( ((h) & 0x1ff) << 7))
+#else
+#define EMAC_RWMR(l,h) (((l) << 22) | ( ((h) & 0x3ff) << 6))
+#endif
+/* EMAC specific TX descriptor control fields (write access) */
#define EMAC_TX_CTRL_GFCS 0x0200
#define EMAC_TX_CTRL_GP 0x0100
#define EMAC_TX_CTRL_ISA 0x0080
#define EMAC_TX_CTRL_RSA 0x0040
#define EMAC_TX_CTRL_IVT 0x0020
#define EMAC_TX_CTRL_RVT 0x0010
-#define EMAC_TX_CTRL_TAH_CSUM 0x000e /* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG4 0x000a /* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG3 0x0008 /* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG2 0x0006 /* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG1 0x0004 /* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG0 0x0002 /* TAH only */
-#define EMAC_TX_CTRL_TAH_DIS 0x0000 /* TAH only */
+#define EMAC_TX_CTRL_TAH_CSUM 0x000e
-#define EMAC_TX_CTRL_DFLT ( \
- MAL_TX_CTRL_INTR | EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP )
-
-/* madmal transmit status / Control bits */
+/* EMAC specific TX descriptor status fields (read access) */
#define EMAC_TX_ST_BFCS 0x0200
-#define EMAC_TX_ST_BPP 0x0100
#define EMAC_TX_ST_LCS 0x0080
#define EMAC_TX_ST_ED 0x0040
#define EMAC_TX_ST_EC 0x0020
@@ -202,8 +280,16 @@ typedef struct emac_regs {
#define EMAC_TX_ST_SC 0x0004
#define EMAC_TX_ST_UR 0x0002
#define EMAC_TX_ST_SQE 0x0001
+#if !defined(CONFIG_IBM_EMAC_TAH)
+#define EMAC_IS_BAD_TX(v) ((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
+ EMAC_TX_ST_EC | EMAC_TX_ST_LC | \
+ EMAC_TX_ST_MC | EMAC_TX_ST_UR))
+#else
+#define EMAC_IS_BAD_TX(v) ((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
+ EMAC_TX_ST_EC | EMAC_TX_ST_LC))
+#endif
-/* madmal receive status / Control bits */
+/* EMAC specific RX descriptor status fields (read access) */
#define EMAC_RX_ST_OE 0x0200
#define EMAC_RX_ST_PP 0x0100
#define EMAC_RX_ST_BP 0x0080
@@ -214,54 +300,10 @@ typedef struct emac_regs {
#define EMAC_RX_ST_PTL 0x0004
#define EMAC_RX_ST_ORE 0x0002
#define EMAC_RX_ST_IRE 0x0001
-#define EMAC_BAD_RX_PACKET 0x02ff
-#define EMAC_CSUM_VER_ERROR 0x0003
-
-/* identify a bad rx packet dependent on emac features */
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_IS_BAD_RX_PACKET(desc) \
- (((desc & (EMAC_BAD_RX_PACKET & ~EMAC_CSUM_VER_ERROR)) || \
- ((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_ORE) || \
- ((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_IRE)))
-#else
-#define EMAC_IS_BAD_RX_PACKET(desc) \
- (desc & EMAC_BAD_RX_PACKET)
-#endif
-
-/* SoC implementation specific EMAC register defaults */
-#if defined(CONFIG_440GP)
-#define EMAC_RWMR_DEFAULT 0x80009000
-#define EMAC_TMR0_DEFAULT 0x00000000
-#define EMAC_TMR1_DEFAULT 0xf8640000
-#elif defined(CONFIG_440GX)
-#define EMAC_RWMR_DEFAULT 0x1000a200
-#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32
-#define EMAC_TMR1_DEFAULT 0xa00f0000
-#elif defined(CONFIG_440SP)
-#define EMAC_RWMR_DEFAULT 0x08002000
-#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_128_2048
-#define EMAC_TMR1_DEFAULT 0xf8200000
-#else
-#define EMAC_RWMR_DEFAULT 0x0f002000
-#define EMAC_TMR0_DEFAULT 0x00000000
-#define EMAC_TMR1_DEFAULT 0x380f0000
-#endif /* CONFIG_440GP */
-
-/* Revision specific EMAC register defaults */
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_M1_DEFAULT (EMAC_M1_BASE | \
- EMAC_M1_OPB_CLK_83 | \
- EMAC_M1_TX_MWSW)
-#define EMAC_RMR_DEFAULT (EMAC_RMR_BASE | \
- EMAC_RMR_RFAF_128_2048)
-#define EMAC_TMR0_XMIT (EMAC_TMR0_GNP0 | \
- EMAC_TMR0_DEFAULT)
-#define EMAC_TRTR_DEFAULT EMAC_TRTR_1024
-#else /* !CONFIG_IBM_EMAC4 */
-#define EMAC_M1_DEFAULT EMAC_M1_BASE
-#define EMAC_RMR_DEFAULT EMAC_RMR_BASE
-#define EMAC_TMR0_XMIT EMAC_TMR0_GNP0
-#define EMAC_TRTR_DEFAULT EMAC_TRTR_1600
-#endif /* CONFIG_IBM_EMAC4 */
-
-#endif
+#define EMAC_RX_TAH_BAD_CSUM 0x0003
+#define EMAC_BAD_RX_MASK (EMAC_RX_ST_OE | EMAC_RX_ST_BP | \
+ EMAC_RX_ST_RP | EMAC_RX_ST_SE | \
+ EMAC_RX_ST_AE | EMAC_RX_ST_BFCS | \
+ EMAC_RX_ST_PTL | EMAC_RX_ST_ORE | \
+ EMAC_RX_ST_IRE )
+#endif /* __IBM_EMAC_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 6482d994d489..943fbd1546ff 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1,13 +1,14 @@
/*
- * ibm_emac_core.c
+ * drivers/net/ibm_emac/ibm_emac_core.c
*
- * Ethernet driver for the built in ethernet on the IBM 4xx PowerPC
- * processors.
- *
- * (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Driver for PowerPC 4xx on-chip ethernet controller.
*
- * Based on original work by
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
+ * Based on original work by
+ * Matt Porter <mporter@kernel.crashing.org>
+ * (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* Armin Kuster <akuster@mvista.com>
* Johnnie Peters <jpeters@mvista.com>
*
@@ -15,29 +16,24 @@
* 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.
- * TODO
- * - Check for races in the "remove" code path
- * - Add some Power Management to the MAC and the PHY
- * - Audit remaining of non-rewritten code (--BenH)
- * - Cleanup message display using msglevel mecanism
- * - Address all errata
- * - Audit all register update paths to ensure they
- * are being written post soft reset if required.
+ *
*/
+
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ptrace.h>
#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/types.h>
-#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/bitops.h>
@@ -45,1692 +41,1893 @@
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/ocp.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/crc32.h>
-
#include "ibm_emac_core.h"
-
-//#define MDIO_DEBUG(fmt) printk fmt
-#define MDIO_DEBUG(fmt)
-
-//#define LINK_DEBUG(fmt) printk fmt
-#define LINK_DEBUG(fmt)
-
-//#define PKT_DEBUG(fmt) printk fmt
-#define PKT_DEBUG(fmt)
-
-#define DRV_NAME "emac"
-#define DRV_VERSION "2.0"
-#define DRV_AUTHOR "Benjamin Herrenschmidt <benh@kernel.crashing.org>"
-#define DRV_DESC "IBM EMAC Ethernet driver"
+#include "ibm_emac_debug.h"
/*
- * When mdio_idx >= 0, contains a list of emac ocp_devs
- * that have had their initialization deferred until the
- * common MDIO controller has been initialized.
+ * Lack of dma_unmap_???? calls is intentional.
+ *
+ * API-correct usage requires additional support state information to be
+ * maintained for every RX and TX buffer descriptor (BD). Unfortunately, due to
+ * EMAC design (e.g. TX buffer passed from network stack can be split into
+ * several BDs, dma_map_single/dma_map_page can be used to map particular BD),
+ * maintaining such information will add additional overhead.
+ * Current DMA API implementation for 4xx processors only ensures cache coherency
+ * and dma_unmap_???? routines are empty and are likely to stay this way.
+ * I decided to omit dma_unmap_??? calls because I don't want to add additional
+ * complexity just for the sake of following some abstract API, when it doesn't
+ * add any real benefit to the driver. I understand that this decision maybe
+ * controversial, but I really tried to make code API-correct and efficient
+ * at the same time and didn't come up with code I liked :(. --ebs
*/
-LIST_HEAD(emac_init_list);
-MODULE_AUTHOR(DRV_AUTHOR);
+#define DRV_NAME "emac"
+#define DRV_VERSION "3.53"
+#define DRV_DESC "PPC 4xx OCP EMAC driver"
+
MODULE_DESCRIPTION(DRV_DESC);
+MODULE_AUTHOR
+ ("Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>");
MODULE_LICENSE("GPL");
-static int skb_res = SKB_RES;
-module_param(skb_res, int, 0444);
-MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n"
- "The 405 handles a misaligned IP header fine but\n"
- "this can help if you are routing to a tunnel or a\n"
- "device that needs aligned data. 0..2");
-
-#define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev))
+/* minimum number of free TX descriptors required to wake up TX process */
+#define EMAC_TX_WAKEUP_THRESH (NUM_TX_BUFF / 4)
-static unsigned int rgmii_enable[] = {
- RGMII_RTBI,
- RGMII_RGMII,
- RGMII_TBI,
- RGMII_GMII
-};
+/* If packet size is less than this number, we allocate small skb and copy packet
+ * contents into it instead of just sending original big skb up
+ */
+#define EMAC_RX_COPY_THRESH CONFIG_IBM_EMAC_RX_COPY_THRESHOLD
-static unsigned int rgmii_speed_mask[] = {
- RGMII_MII2_SPDMASK,
- RGMII_MII3_SPDMASK
-};
+/* Since multiple EMACs share MDIO lines in various ways, we need
+ * to avoid re-using the same PHY ID in cases where the arch didn't
+ * setup precise phy_map entries
+ */
+static u32 busy_phy_map;
-static unsigned int rgmii_speed100[] = {
- RGMII_MII2_100MB,
- RGMII_MII3_100MB
-};
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && (defined(CONFIG_405EP) || defined(CONFIG_440EP))
+/* 405EP has "EMAC to PHY Control Register" (CPC0_EPCTL) which can help us
+ * with PHY RX clock problem.
+ * 440EP has more sane SDR0_MFR register implementation than 440GX, which
+ * also allows controlling each EMAC clock
+ */
+static inline void EMAC_RX_CLK_TX(int idx)
+{
+ unsigned long flags;
+ local_irq_save(flags);
-static unsigned int rgmii_speed1000[] = {
- RGMII_MII2_1000MB,
- RGMII_MII3_1000MB
-};
+#if defined(CONFIG_405EP)
+ mtdcr(0xf3, mfdcr(0xf3) | (1 << idx));
+#else /* CONFIG_440EP */
+ SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) | (0x08000000 >> idx));
+#endif
-#define ZMII_PRIV(ocpdev) ((struct ibm_ocp_zmii*)ocp_get_drvdata(ocpdev))
+ local_irq_restore(flags);
+}
-static unsigned int zmii_enable[][4] = {
- {ZMII_SMII0, ZMII_RMII0, ZMII_MII0,
- ~(ZMII_MDI1 | ZMII_MDI2 | ZMII_MDI3)},
- {ZMII_SMII1, ZMII_RMII1, ZMII_MII1,
- ~(ZMII_MDI0 | ZMII_MDI2 | ZMII_MDI3)},
- {ZMII_SMII2, ZMII_RMII2, ZMII_MII2,
- ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)},
- {ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)}
-};
+static inline void EMAC_RX_CLK_DEFAULT(int idx)
+{
+ unsigned long flags;
+ local_irq_save(flags);
-static unsigned int mdi_enable[] = {
- ZMII_MDI0,
- ZMII_MDI1,
- ZMII_MDI2,
- ZMII_MDI3
-};
+#if defined(CONFIG_405EP)
+ mtdcr(0xf3, mfdcr(0xf3) & ~(1 << idx));
+#else /* CONFIG_440EP */
+ SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) & ~(0x08000000 >> idx));
+#endif
-static unsigned int zmii_speed = 0x0;
-static unsigned int zmii_speed100[] = {
- ZMII_MII0_100MB,
- ZMII_MII1_100MB,
- ZMII_MII2_100MB,
- ZMII_MII3_100MB
-};
+ local_irq_restore(flags);
+}
+#else
+#define EMAC_RX_CLK_TX(idx) ((void)0)
+#define EMAC_RX_CLK_DEFAULT(idx) ((void)0)
+#endif
-/* Since multiple EMACs share MDIO lines in various ways, we need
- * to avoid re-using the same PHY ID in cases where the arch didn't
- * setup precise phy_map entries
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && defined(CONFIG_440GX)
+/* We can switch Ethernet clock to the internal source through SDR0_MFR[ECS],
+ * unfortunately this is less flexible than 440EP case, because it's a global
+ * setting for all EMACs, therefore we do this clock trick only during probe.
*/
-static u32 busy_phy_map = 0;
+#define EMAC_CLK_INTERNAL SDR_WRITE(DCRN_SDR_MFR, \
+ SDR_READ(DCRN_SDR_MFR) | 0x08000000)
+#define EMAC_CLK_EXTERNAL SDR_WRITE(DCRN_SDR_MFR, \
+ SDR_READ(DCRN_SDR_MFR) & ~0x08000000)
+#else
+#define EMAC_CLK_INTERNAL ((void)0)
+#define EMAC_CLK_EXTERNAL ((void)0)
+#endif
-/* If EMACs share a common MDIO device, this points to it */
-static struct net_device *mdio_ndev = NULL;
+/* I don't want to litter system log with timeout errors
+ * when we have brain-damaged PHY.
+ */
+static inline void emac_report_timeout_error(struct ocp_enet_private *dev,
+ const char *error)
+{
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX)
+ DBG("%d: %s" NL, dev->def->index, error);
+#else
+ if (net_ratelimit())
+ printk(KERN_ERR "emac%d: %s\n", dev->def->index, error);
+#endif
+}
-struct emac_def_dev {
- struct list_head link;
- struct ocp_device *ocpdev;
- struct ibm_ocp_mal *mal;
+/* PHY polling intervals */
+#define PHY_POLL_LINK_ON HZ
+#define PHY_POLL_LINK_OFF (HZ / 5)
+
+/* Please, keep in sync with struct ibm_emac_stats/ibm_emac_error_stats */
+static const char emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = {
+ "rx_packets", "rx_bytes", "tx_packets", "tx_bytes", "rx_packets_csum",
+ "tx_packets_csum", "tx_undo", "rx_dropped_stack", "rx_dropped_oom",
+ "rx_dropped_error", "rx_dropped_resize", "rx_dropped_mtu",
+ "rx_stopped", "rx_bd_errors", "rx_bd_overrun", "rx_bd_bad_packet",
+ "rx_bd_runt_packet", "rx_bd_short_event", "rx_bd_alignment_error",
+ "rx_bd_bad_fcs", "rx_bd_packet_too_long", "rx_bd_out_of_range",
+ "rx_bd_in_range", "rx_parity", "rx_fifo_overrun", "rx_overrun",
+ "rx_bad_packet", "rx_runt_packet", "rx_short_event",
+ "rx_alignment_error", "rx_bad_fcs", "rx_packet_too_long",
+ "rx_out_of_range", "rx_in_range", "tx_dropped", "tx_bd_errors",
+ "tx_bd_bad_fcs", "tx_bd_carrier_loss", "tx_bd_excessive_deferral",
+ "tx_bd_excessive_collisions", "tx_bd_late_collision",
+ "tx_bd_multple_collisions", "tx_bd_single_collision",
+ "tx_bd_underrun", "tx_bd_sqe", "tx_parity", "tx_underrun", "tx_sqe",
+ "tx_errors"
};
-static struct net_device_stats *emac_stats(struct net_device *dev)
+static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs);
+static void emac_clean_tx_ring(struct ocp_enet_private *dev);
+
+static inline int emac_phy_supports_gige(int phy_mode)
{
- struct ocp_enet_private *fep = dev->priv;
- return &fep->stats;
-};
+ return phy_mode == PHY_MODE_GMII ||
+ phy_mode == PHY_MODE_RGMII ||
+ phy_mode == PHY_MODE_TBI ||
+ phy_mode == PHY_MODE_RTBI;
+}
-static int
-emac_init_rgmii(struct ocp_device *rgmii_dev, int input, int phy_mode)
+static inline int emac_phy_gpcs(int phy_mode)
{
- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(rgmii_dev);
- const char *mode_name[] = { "RTBI", "RGMII", "TBI", "GMII" };
- int mode = -1;
+ return phy_mode == PHY_MODE_TBI ||
+ phy_mode == PHY_MODE_RTBI;
+}
- if (!rgmii) {
- rgmii = kmalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
+static inline void emac_tx_enable(struct ocp_enet_private *dev)
+{
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ u32 r;
- if (rgmii == NULL) {
- printk(KERN_ERR
- "rgmii%d: Out of memory allocating RGMII structure!\n",
- rgmii_dev->def->index);
- return -ENOMEM;
- }
+ local_irq_save(flags);
- memset(rgmii, 0, sizeof(*rgmii));
+ DBG("%d: tx_enable" NL, dev->def->index);
- rgmii->base =
- (struct rgmii_regs *)ioremap(rgmii_dev->def->paddr,
- sizeof(*rgmii->base));
- if (rgmii->base == NULL) {
- printk(KERN_ERR
- "rgmii%d: Cannot ioremap bridge registers!\n",
- rgmii_dev->def->index);
+ r = in_be32(&p->mr0);
+ if (!(r & EMAC_MR0_TXE))
+ out_be32(&p->mr0, r | EMAC_MR0_TXE);
+ local_irq_restore(flags);
+}
- kfree(rgmii);
- return -ENOMEM;
- }
- ocp_set_drvdata(rgmii_dev, rgmii);
- }
+static void emac_tx_disable(struct ocp_enet_private *dev)
+{
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ u32 r;
- if (phy_mode) {
- switch (phy_mode) {
- case PHY_MODE_GMII:
- mode = GMII;
- break;
- case PHY_MODE_TBI:
- mode = TBI;
- break;
- case PHY_MODE_RTBI:
- mode = RTBI;
- break;
- case PHY_MODE_RGMII:
- default:
- mode = RGMII;
- }
- rgmii->base->fer &= ~RGMII_FER_MASK(input);
- rgmii->base->fer |= rgmii_enable[mode] << (4 * input);
- } else {
- switch ((rgmii->base->fer & RGMII_FER_MASK(input)) >> (4 *
- input)) {
- case RGMII_RTBI:
- mode = RTBI;
- break;
- case RGMII_RGMII:
- mode = RGMII;
- break;
- case RGMII_TBI:
- mode = TBI;
- break;
- case RGMII_GMII:
- mode = GMII;
- }
- }
+ local_irq_save(flags);
+
+ DBG("%d: tx_disable" NL, dev->def->index);
- /* Set mode to RGMII if nothing valid is detected */
- if (mode < 0)
- mode = RGMII;
+ r = in_be32(&p->mr0);
+ if (r & EMAC_MR0_TXE) {
+ int n = 300;
+ out_be32(&p->mr0, r & ~EMAC_MR0_TXE);
+ while (!(in_be32(&p->mr0) & EMAC_MR0_TXI) && n)
+ --n;
+ if (unlikely(!n))
+ emac_report_timeout_error(dev, "TX disable timeout");
+ }
+ local_irq_restore(flags);
+}
- printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
- rgmii_dev->def->index, input, mode_name[mode]);
+static void emac_rx_enable(struct ocp_enet_private *dev)
+{
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ u32 r;
- rgmii->mode[input] = mode;
- rgmii->users++;
+ local_irq_save(flags);
+ if (unlikely(dev->commac.rx_stopped))
+ goto out;
- return 0;
+ DBG("%d: rx_enable" NL, dev->def->index);
+
+ r = in_be32(&p->mr0);
+ if (!(r & EMAC_MR0_RXE)) {
+ if (unlikely(!(r & EMAC_MR0_RXI))) {
+ /* Wait if previous async disable is still in progress */
+ int n = 100;
+ while (!(r = in_be32(&p->mr0) & EMAC_MR0_RXI) && n)
+ --n;
+ if (unlikely(!n))
+ emac_report_timeout_error(dev,
+ "RX disable timeout");
+ }
+ out_be32(&p->mr0, r | EMAC_MR0_RXE);
+ }
+ out:
+ local_irq_restore(flags);
}
-static void
-emac_rgmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
+static void emac_rx_disable(struct ocp_enet_private *dev)
{
- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
- unsigned int rgmii_speed;
-
- rgmii_speed = in_be32(&rgmii->base->ssr);
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ u32 r;
- rgmii_speed &= ~rgmii_speed_mask[input];
+ local_irq_save(flags);
- if (speed == 1000)
- rgmii_speed |= rgmii_speed1000[input];
- else if (speed == 100)
- rgmii_speed |= rgmii_speed100[input];
+ DBG("%d: rx_disable" NL, dev->def->index);
- out_be32(&rgmii->base->ssr, rgmii_speed);
+ r = in_be32(&p->mr0);
+ if (r & EMAC_MR0_RXE) {
+ int n = 300;
+ out_be32(&p->mr0, r & ~EMAC_MR0_RXE);
+ while (!(in_be32(&p->mr0) & EMAC_MR0_RXI) && n)
+ --n;
+ if (unlikely(!n))
+ emac_report_timeout_error(dev, "RX disable timeout");
+ }
+ local_irq_restore(flags);
}
-static void emac_close_rgmii(struct ocp_device *ocpdev)
+static inline void emac_rx_disable_async(struct ocp_enet_private *dev)
{
- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
- BUG_ON(!rgmii || rgmii->users == 0);
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ u32 r;
- if (!--rgmii->users) {
- ocp_set_drvdata(ocpdev, NULL);
- iounmap((void *)rgmii->base);
- kfree(rgmii);
- }
+ local_irq_save(flags);
+
+ DBG("%d: rx_disable_async" NL, dev->def->index);
+
+ r = in_be32(&p->mr0);
+ if (r & EMAC_MR0_RXE)
+ out_be32(&p->mr0, r & ~EMAC_MR0_RXE);
+ local_irq_restore(flags);
}
-static int emac_init_zmii(struct ocp_device *zmii_dev, int input, int phy_mode)
+static int emac_reset(struct ocp_enet_private *dev)
{
- struct ibm_ocp_zmii *zmii = ZMII_PRIV(zmii_dev);
- const char *mode_name[] = { "SMII", "RMII", "MII" };
- int mode = -1;
+ struct emac_regs *p = dev->emacp;
+ unsigned long flags;
+ int n = 20;
- if (!zmii) {
- zmii = kmalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL);
- if (zmii == NULL) {
- printk(KERN_ERR
- "zmii%d: Out of memory allocating ZMII structure!\n",
- zmii_dev->def->index);
- return -ENOMEM;
- }
- memset(zmii, 0, sizeof(*zmii));
+ DBG("%d: reset" NL, dev->def->index);
- zmii->base =
- (struct zmii_regs *)ioremap(zmii_dev->def->paddr,
- sizeof(*zmii->base));
- if (zmii->base == NULL) {
- printk(KERN_ERR
- "zmii%d: Cannot ioremap bridge registers!\n",
- zmii_dev->def->index);
+ local_irq_save(flags);
- kfree(zmii);
- return -ENOMEM;
- }
- ocp_set_drvdata(zmii_dev, zmii);
+ if (!dev->reset_failed) {
+ /* 40x erratum suggests stopping RX channel before reset,
+ * we stop TX as well
+ */
+ emac_rx_disable(dev);
+ emac_tx_disable(dev);
}
- if (phy_mode) {
- switch (phy_mode) {
- case PHY_MODE_MII:
- mode = MII;
- break;
- case PHY_MODE_RMII:
- mode = RMII;
- break;
- case PHY_MODE_SMII:
- default:
- mode = SMII;
- }
- zmii->base->fer &= ~ZMII_FER_MASK(input);
- zmii->base->fer |= zmii_enable[input][mode];
+ out_be32(&p->mr0, EMAC_MR0_SRST);
+ while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
+ --n;
+ local_irq_restore(flags);
+
+ if (n) {
+ dev->reset_failed = 0;
+ return 0;
} else {
- switch ((zmii->base->fer & ZMII_FER_MASK(input)) << (4 * input)) {
- case ZMII_MII0:
- mode = MII;
- break;
- case ZMII_RMII0:
- mode = RMII;
- break;
- case ZMII_SMII0:
- mode = SMII;
- }
+ emac_report_timeout_error(dev, "reset timeout");
+ dev->reset_failed = 1;
+ return -ETIMEDOUT;
}
+}
- /* Set mode to SMII if nothing valid is detected */
- if (mode < 0)
- mode = SMII;
+static void emac_hash_mc(struct ocp_enet_private *dev)
+{
+ struct emac_regs *p = dev->emacp;
+ u16 gaht[4] = { 0 };
+ struct dev_mc_list *dmi;
- printk(KERN_NOTICE "zmii%d: input %d in %s mode\n",
- zmii_dev->def->index, input, mode_name[mode]);
+ DBG("%d: hash_mc %d" NL, dev->def->index, dev->ndev->mc_count);
- zmii->mode[input] = mode;
- zmii->users++;
+ for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
+ int bit;
+ DBG2("%d: mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
+ dev->def->index,
+ dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
+ dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
- return 0;
+ bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26);
+ gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f);
+ }
+ out_be32(&p->gaht1, gaht[0]);
+ out_be32(&p->gaht2, gaht[1]);
+ out_be32(&p->gaht3, gaht[2]);
+ out_be32(&p->gaht4, gaht[3]);
}
-static void emac_enable_zmii_port(struct ocp_device *ocpdev, int input)
+static inline u32 emac_iff2rmr(struct net_device *ndev)
{
- u32 mask;
- struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
+ u32 r = EMAC_RMR_SP | EMAC_RMR_SFCS | EMAC_RMR_IAE | EMAC_RMR_BAE |
+ EMAC_RMR_BASE;
- mask = in_be32(&zmii->base->fer);
- mask &= zmii_enable[input][MDI]; /* turn all non enabled MDI's off */
- mask |= zmii_enable[input][zmii->mode[input]] | mdi_enable[input];
- out_be32(&zmii->base->fer, mask);
+ if (ndev->flags & IFF_PROMISC)
+ r |= EMAC_RMR_PME;
+ else if (ndev->flags & IFF_ALLMULTI || ndev->mc_count > 32)
+ r |= EMAC_RMR_PMME;
+ else if (ndev->mc_count > 0)
+ r |= EMAC_RMR_MAE;
+
+ return r;
}
-static void
-emac_zmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
+static inline int emac_opb_mhz(void)
{
- struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
-
- if (speed == 100)
- zmii_speed |= zmii_speed100[input];
- else
- zmii_speed &= ~zmii_speed100[input];
-
- out_be32(&zmii->base->ssr, zmii_speed);
+ return (ocp_sys_info.opb_bus_freq + 500000) / 1000000;
}
-static void emac_close_zmii(struct ocp_device *ocpdev)
+/* BHs disabled */
+static int emac_configure(struct ocp_enet_private *dev)
{
- struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
- BUG_ON(!zmii || zmii->users == 0);
+ struct emac_regs *p = dev->emacp;
+ struct net_device *ndev = dev->ndev;
+ int gige;
+ u32 r;
- if (!--zmii->users) {
- ocp_set_drvdata(ocpdev, NULL);
- iounmap((void *)zmii->base);
- kfree(zmii);
- }
-}
+ DBG("%d: configure" NL, dev->def->index);
-int emac_phy_read(struct net_device *dev, int mii_id, int reg)
-{
- int count;
- uint32_t stacr;
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
+ if (emac_reset(dev) < 0)
+ return -ETIMEDOUT;
- MDIO_DEBUG(("%s: phy_read, id: 0x%x, reg: 0x%x\n", dev->name, mii_id,
- reg));
+ tah_reset(dev->tah_dev);
- /* Enable proper ZMII port */
- if (fep->zmii_dev)
- emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
+ /* Mode register */
+ r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST;
+ if (dev->phy.duplex == DUPLEX_FULL)
+ r |= EMAC_MR1_FDE;
+ switch (dev->phy.speed) {
+ case SPEED_1000:
+ if (emac_phy_gpcs(dev->phy.mode)) {
+ r |= EMAC_MR1_MF_1000GPCS |
+ EMAC_MR1_MF_IPPA(dev->phy.address);
- /* Use the EMAC that has the MDIO port */
- if (fep->mdio_dev) {
- dev = fep->mdio_dev;
- fep = dev->priv;
- emacp = fep->emacp;
+ /* Put some arbitrary OUI, Manuf & Rev IDs so we can
+ * identify this GPCS PHY later.
+ */
+ out_be32(&p->ipcr, 0xdeadbeef);
+ } else
+ r |= EMAC_MR1_MF_1000;
+ r |= EMAC_MR1_RFS_16K;
+ gige = 1;
+
+ if (dev->ndev->mtu > ETH_DATA_LEN)
+ r |= EMAC_MR1_JPSM;
+ break;
+ case SPEED_100:
+ r |= EMAC_MR1_MF_100;
+ /* Fall through */
+ default:
+ r |= EMAC_MR1_RFS_4K;
+ gige = 0;
+ break;
}
- count = 0;
- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
- && (count++ < MDIO_DELAY))
- udelay(1);
- MDIO_DEBUG((" (count was %d)\n", count));
+ if (dev->rgmii_dev)
+ rgmii_set_speed(dev->rgmii_dev, dev->rgmii_input,
+ dev->phy.speed);
+ else
+ zmii_set_speed(dev->zmii_dev, dev->zmii_input, dev->phy.speed);
- if ((stacr & EMAC_STACR_OC) == 0) {
- printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
- return -1;
+#if !defined(CONFIG_40x)
+ /* on 40x erratum forces us to NOT use integrated flow control,
+ * let's hope it works on 44x ;)
+ */
+ if (dev->phy.duplex == DUPLEX_FULL) {
+ if (dev->phy.pause)
+ r |= EMAC_MR1_EIFC | EMAC_MR1_APP;
+ else if (dev->phy.asym_pause)
+ r |= EMAC_MR1_APP;
}
+#endif
+ out_be32(&p->mr1, r);
+
+ /* Set individual MAC address */
+ out_be32(&p->iahr, (ndev->dev_addr[0] << 8) | ndev->dev_addr[1]);
+ out_be32(&p->ialr, (ndev->dev_addr[2] << 24) |
+ (ndev->dev_addr[3] << 16) | (ndev->dev_addr[4] << 8) |
+ ndev->dev_addr[5]);
+
+ /* VLAN Tag Protocol ID */
+ out_be32(&p->vtpid, 0x8100);
+
+ /* Receive mode register */
+ r = emac_iff2rmr(ndev);
+ if (r & EMAC_RMR_MAE)
+ emac_hash_mc(dev);
+ out_be32(&p->rmr, r);
+
+ /* FIFOs thresholds */
+ r = EMAC_TMR1((EMAC_MAL_BURST_SIZE / EMAC_FIFO_ENTRY_SIZE) + 1,
+ EMAC_TX_FIFO_SIZE / 2 / EMAC_FIFO_ENTRY_SIZE);
+ out_be32(&p->tmr1, r);
+ out_be32(&p->trtr, EMAC_TRTR(EMAC_TX_FIFO_SIZE / 2));
+
+ /* PAUSE frame is sent when RX FIFO reaches its high-water mark,
+ there should be still enough space in FIFO to allow the our link
+ partner time to process this frame and also time to send PAUSE
+ frame itself.
+
+ Here is the worst case scenario for the RX FIFO "headroom"
+ (from "The Switch Book") (100Mbps, without preamble, inter-frame gap):
+
+ 1) One maximum-length frame on TX 1522 bytes
+ 2) One PAUSE frame time 64 bytes
+ 3) PAUSE frame decode time allowance 64 bytes
+ 4) One maximum-length frame on RX 1522 bytes
+ 5) Round-trip propagation delay of the link (100Mb) 15 bytes
+ ----------
+ 3187 bytes
+
+ I chose to set high-water mark to RX_FIFO_SIZE / 4 (1024 bytes)
+ low-water mark to RX_FIFO_SIZE / 8 (512 bytes)
+ */
+ r = EMAC_RWMR(EMAC_RX_FIFO_SIZE(gige) / 8 / EMAC_FIFO_ENTRY_SIZE,
+ EMAC_RX_FIFO_SIZE(gige) / 4 / EMAC_FIFO_ENTRY_SIZE);
+ out_be32(&p->rwmr, r);
+
+ /* Set PAUSE timer to the maximum */
+ out_be32(&p->ptr, 0xffff);
+
+ /* IRQ sources */
+ out_be32(&p->iser, EMAC_ISR_TXPE | EMAC_ISR_RXPE | /* EMAC_ISR_TXUE |
+ EMAC_ISR_RXOE | */ EMAC_ISR_OVR | EMAC_ISR_BP | EMAC_ISR_SE |
+ EMAC_ISR_ALE | EMAC_ISR_BFCS | EMAC_ISR_PTLE | EMAC_ISR_ORE |
+ EMAC_ISR_IRE | EMAC_ISR_TE);
+
+ /* We need to take GPCS PHY out of isolate mode after EMAC reset */
+ if (emac_phy_gpcs(dev->phy.mode))
+ mii_reset_phy(&dev->phy);
+
+ return 0;
+}
- /* Clear the speed bits and make a read request to the PHY */
- stacr = ((EMAC_STACR_READ | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ);
- stacr |= ((mii_id & 0x1F) << 5);
+/* BHs disabled */
+static void emac_reinitialize(struct ocp_enet_private *dev)
+{
+ DBG("%d: reinitialize" NL, dev->def->index);
- out_be32(&emacp->em0stacr, stacr);
+ if (!emac_configure(dev)) {
+ emac_tx_enable(dev);
+ emac_rx_enable(dev);
+ }
+}
- count = 0;
- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
- && (count++ < MDIO_DELAY))
- udelay(1);
- MDIO_DEBUG((" (count was %d)\n", count));
+/* BHs disabled */
+static void emac_full_tx_reset(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
- if ((stacr & EMAC_STACR_OC) == 0) {
- printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
- return -1;
- }
+ DBG("%d: full_tx_reset" NL, dev->def->index);
- /* Check for a read error */
- if (stacr & EMAC_STACR_PHYE) {
- MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
- return -1;
- }
+ emac_tx_disable(dev);
+ mal_disable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+ emac_clean_tx_ring(dev);
+ dev->tx_cnt = dev->tx_slot = dev->ack_slot = 0;
+
+ emac_configure(dev);
- MDIO_DEBUG((" -> 0x%x\n", stacr >> 16));
+ mal_enable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+ emac_tx_enable(dev);
+ emac_rx_enable(dev);
- return (stacr >> 16);
+ netif_wake_queue(ndev);
}
-void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
+static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg)
{
- int count;
- uint32_t stacr;
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
+ struct emac_regs *p = dev->emacp;
+ u32 r;
+ int n;
- MDIO_DEBUG(("%s phy_write, id: 0x%x, reg: 0x%x, data: 0x%x\n",
- dev->name, mii_id, reg, data));
+ DBG2("%d: mdio_read(%02x,%02x)" NL, dev->def->index, id, reg);
- /* Enable proper ZMII port */
- if (fep->zmii_dev)
- emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
+ /* Enable proper MDIO port */
+ zmii_enable_mdio(dev->zmii_dev, dev->zmii_input);
- /* Use the EMAC that has the MDIO port */
- if (fep->mdio_dev) {
- dev = fep->mdio_dev;
- fep = dev->priv;
- emacp = fep->emacp;
+ /* Wait for management interface to become idle */
+ n = 10;
+ while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
+ udelay(1);
+ if (!--n)
+ goto to;
}
- count = 0;
- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
- && (count++ < MDIO_DELAY))
+ /* Issue read command */
+ out_be32(&p->stacr,
+ EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_READ |
+ (reg & EMAC_STACR_PRA_MASK)
+ | ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT));
+
+ /* Wait for read to complete */
+ n = 100;
+ while (!((r = in_be32(&p->stacr)) & EMAC_STACR_OC)) {
udelay(1);
- MDIO_DEBUG((" (count was %d)\n", count));
+ if (!--n)
+ goto to;
+ }
- if ((stacr & EMAC_STACR_OC) == 0) {
- printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
- return;
+ if (unlikely(r & EMAC_STACR_PHYE)) {
+ DBG("%d: mdio_read(%02x, %02x) failed" NL, dev->def->index,
+ id, reg);
+ return -EREMOTEIO;
}
- /* Clear the speed bits and make a read request to the PHY */
+ r = ((r >> EMAC_STACR_PHYD_SHIFT) & EMAC_STACR_PHYD_MASK);
+ DBG2("%d: mdio_read -> %04x" NL, dev->def->index, r);
+ return r;
+ to:
+ DBG("%d: MII management interface timeout (read)" NL, dev->def->index);
+ return -ETIMEDOUT;
+}
+
+static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg,
+ u16 val)
+{
+ struct emac_regs *p = dev->emacp;
+ int n;
- stacr = ((EMAC_STACR_WRITE | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ);
- stacr |= ((mii_id & 0x1f) << 5) | ((data & 0xffff) << 16);
+ DBG2("%d: mdio_write(%02x,%02x,%04x)" NL, dev->def->index, id, reg,
+ val);
- out_be32(&emacp->em0stacr, stacr);
+ /* Enable proper MDIO port */
+ zmii_enable_mdio(dev->zmii_dev, dev->zmii_input);
- count = 0;
- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
- && (count++ < MDIO_DELAY))
+ /* Wait for management interface to be idle */
+ n = 10;
+ while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
udelay(1);
- MDIO_DEBUG((" (count was %d)\n", count));
+ if (!--n)
+ goto to;
+ }
- if ((stacr & EMAC_STACR_OC) == 0)
- printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
+ /* Issue write command */
+ out_be32(&p->stacr,
+ EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_WRITE |
+ (reg & EMAC_STACR_PRA_MASK) |
+ ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT) |
+ (val << EMAC_STACR_PHYD_SHIFT));
- /* Check for a write error */
- if ((stacr & EMAC_STACR_PHYE) != 0) {
- MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
+ /* Wait for write to complete */
+ n = 100;
+ while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
+ udelay(1);
+ if (!--n)
+ goto to;
}
+ return;
+ to:
+ DBG("%d: MII management interface timeout (write)" NL, dev->def->index);
}
-static void emac_txeob_dev(void *param, u32 chanmask)
+static int emac_mdio_read(struct net_device *ndev, int id, int reg)
{
- struct net_device *dev = param;
- struct ocp_enet_private *fep = dev->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&fep->lock, flags);
-
- PKT_DEBUG(("emac_txeob_dev() entry, tx_cnt: %d\n", fep->tx_cnt));
-
- while (fep->tx_cnt &&
- !(fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_READY)) {
+ struct ocp_enet_private *dev = ndev->priv;
+ int res;
+
+ local_bh_disable();
+ res = __emac_mdio_read(dev->mdio_dev ? dev->mdio_dev : dev, (u8) id,
+ (u8) reg);
+ local_bh_enable();
+ return res;
+}
- if (fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_LAST) {
- /* Tell the system the transmit completed. */
- dma_unmap_single(&fep->ocpdev->dev,
- fep->tx_desc[fep->ack_slot].data_ptr,
- fep->tx_desc[fep->ack_slot].data_len,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(fep->tx_skb[fep->ack_slot]);
+static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
+{
+ struct ocp_enet_private *dev = ndev->priv;
- if (fep->tx_desc[fep->ack_slot].ctrl &
- (EMAC_TX_ST_EC | EMAC_TX_ST_MC | EMAC_TX_ST_SC))
- fep->stats.collisions++;
- }
+ local_bh_disable();
+ __emac_mdio_write(dev->mdio_dev ? dev->mdio_dev : dev, (u8) id,
+ (u8) reg, (u16) val);
+ local_bh_enable();
+}
- fep->tx_skb[fep->ack_slot] = (struct sk_buff *)NULL;
- if (++fep->ack_slot == NUM_TX_BUFF)
- fep->ack_slot = 0;
+/* BHs disabled */
+static void emac_set_multicast_list(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct emac_regs *p = dev->emacp;
+ u32 rmr = emac_iff2rmr(ndev);
+
+ DBG("%d: multicast %08x" NL, dev->def->index, rmr);
+ BUG_ON(!netif_running(dev->ndev));
+
+ /* I decided to relax register access rules here to avoid
+ * full EMAC reset.
+ *
+ * There is a real problem with EMAC4 core if we use MWSW_001 bit
+ * in MR1 register and do a full EMAC reset.
+ * One TX BD status update is delayed and, after EMAC reset, it
+ * never happens, resulting in TX hung (it'll be recovered by TX
+ * timeout handler eventually, but this is just gross).
+ * So we either have to do full TX reset or try to cheat here :)
+ *
+ * The only required change is to RX mode register, so I *think* all
+ * we need is just to stop RX channel. This seems to work on all
+ * tested SoCs. --ebs
+ */
+ emac_rx_disable(dev);
+ if (rmr & EMAC_RMR_MAE)
+ emac_hash_mc(dev);
+ out_be32(&p->rmr, rmr);
+ emac_rx_enable(dev);
+}
- fep->tx_cnt--;
+/* BHs disabled */
+static int emac_resize_rx_ring(struct ocp_enet_private *dev, int new_mtu)
+{
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
+ int rx_sync_size = emac_rx_sync_size(new_mtu);
+ int rx_skb_size = emac_rx_skb_size(new_mtu);
+ int i, ret = 0;
+
+ emac_rx_disable(dev);
+ mal_disable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+
+ if (dev->rx_sg_skb) {
+ ++dev->estats.rx_dropped_resize;
+ dev_kfree_skb(dev->rx_sg_skb);
+ dev->rx_sg_skb = NULL;
}
- if (fep->tx_cnt < NUM_TX_BUFF)
- netif_wake_queue(dev);
- PKT_DEBUG(("emac_txeob_dev() exit, tx_cnt: %d\n", fep->tx_cnt));
+ /* Make a first pass over RX ring and mark BDs ready, dropping
+ * non-processed packets on the way. We need this as a separate pass
+ * to simplify error recovery in the case of allocation failure later.
+ */
+ for (i = 0; i < NUM_RX_BUFF; ++i) {
+ if (dev->rx_desc[i].ctrl & MAL_RX_CTRL_FIRST)
+ ++dev->estats.rx_dropped_resize;
- spin_unlock_irqrestore(&fep->lock, flags);
-}
+ dev->rx_desc[i].data_len = 0;
+ dev->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY |
+ (i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
+ }
-/*
- Fill/Re-fill the rx chain with valid ctrl/ptrs.
- This function will fill from rx_slot up to the parm end.
- So to completely fill the chain pre-set rx_slot to 0 and
- pass in an end of 0.
- */
-static void emac_rx_fill(struct net_device *dev, int end)
-{
- int i;
- struct ocp_enet_private *fep = dev->priv;
-
- i = fep->rx_slot;
- do {
- /* We don't want the 16 bytes skb_reserve done by dev_alloc_skb,
- * it breaks our cache line alignement. However, we still allocate
- * +16 so that we end up allocating the exact same size as
- * dev_alloc_skb() would do.
- * Also, because of the skb_res, the max DMA size we give to EMAC
- * is slighly wrong, causing it to potentially DMA 2 more bytes
- * from a broken/oversized packet. These 16 bytes will take care
- * that we don't walk on somebody else toes with that.
- */
- fep->rx_skb[i] =
- alloc_skb(fep->rx_buffer_size + 16, GFP_ATOMIC);
-
- if (fep->rx_skb[i] == NULL) {
- /* Keep rx_slot here, the next time clean/fill is called
- * we will try again before the MAL wraps back here
- * If the MAL tries to use this descriptor with
- * the EMPTY bit off it will cause the
- * rxde interrupt. That is where we will
- * try again to allocate an sk_buff.
- */
- break;
+ /* Reallocate RX ring only if bigger skb buffers are required */
+ if (rx_skb_size <= dev->rx_skb_size)
+ goto skip;
+ /* Second pass, allocate new skbs */
+ for (i = 0; i < NUM_RX_BUFF; ++i) {
+ struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto oom;
}
- if (skb_res)
- skb_reserve(fep->rx_skb[i], skb_res);
+ BUG_ON(!dev->rx_skb[i]);
+ dev_kfree_skb(dev->rx_skb[i]);
- /* We must NOT dma_map_single the cache line right after the
- * buffer, so we must crop our sync size to account for the
- * reserved space
- */
- fep->rx_desc[i].data_ptr =
- (unsigned char *)dma_map_single(&fep->ocpdev->dev,
- (void *)fep->rx_skb[i]->
- data,
- fep->rx_buffer_size -
- skb_res, DMA_FROM_DEVICE);
-
- /*
- * Some 4xx implementations use the previously
- * reserved bits in data_len to encode the MS
- * 4-bits of a 36-bit physical address (ERPN)
- * This must be initialized.
- */
- fep->rx_desc[i].data_len = 0;
- fep->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR |
- (i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
+ skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+ dev->rx_desc[i].data_ptr =
+ dma_map_single(dev->ldev, skb->data - 2, rx_sync_size,
+ DMA_FROM_DEVICE) + 2;
+ dev->rx_skb[i] = skb;
+ }
+ skip:
+ /* Check if we need to change "Jumbo" bit in MR1 */
+ if ((new_mtu > ETH_DATA_LEN) ^ (dev->ndev->mtu > ETH_DATA_LEN)) {
+ /* This is to prevent starting RX channel in emac_rx_enable() */
+ dev->commac.rx_stopped = 1;
+
+ dev->ndev->mtu = new_mtu;
+ emac_full_tx_reset(dev->ndev);
+ }
- } while ((i = (i + 1) % NUM_RX_BUFF) != end);
+ mal_set_rcbs(dev->mal, emacdata->mal_rx_chan, emac_rx_size(new_mtu));
+ oom:
+ /* Restart RX */
+ dev->commac.rx_stopped = dev->rx_slot = 0;
+ mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+ emac_rx_enable(dev);
- fep->rx_slot = i;
+ return ret;
}
-static void
-emac_rx_csum(struct net_device *dev, unsigned short ctrl, struct sk_buff *skb)
+/* Process ctx, rtnl_lock semaphore */
+static int emac_change_mtu(struct net_device *ndev, int new_mtu)
{
- struct ocp_enet_private *fep = dev->priv;
+ struct ocp_enet_private *dev = ndev->priv;
+ int ret = 0;
- /* Exit if interface has no TAH engine */
- if (!fep->tah_dev) {
- skb->ip_summed = CHECKSUM_NONE;
- return;
- }
+ if (new_mtu < EMAC_MIN_MTU || new_mtu > EMAC_MAX_MTU)
+ return -EINVAL;
- /* Check for TCP/UDP/IP csum error */
- if (ctrl & EMAC_CSUM_VER_ERROR) {
- /* Let the stack verify checksum errors */
- skb->ip_summed = CHECKSUM_NONE;
-/* adapter->hw_csum_err++; */
- } else {
- /* Csum is good */
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-/* adapter->hw_csum_good++; */
- }
-}
+ DBG("%d: change_mtu(%d)" NL, dev->def->index, new_mtu);
-static int emac_rx_clean(struct net_device *dev)
-{
- int i, b, bnum = 0, buf[6];
- int error, frame_length;
- struct ocp_enet_private *fep = dev->priv;
- unsigned short ctrl;
+ local_bh_disable();
+ if (netif_running(ndev)) {
+ /* Check if we really need to reinitalize RX ring */
+ if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu))
+ ret = emac_resize_rx_ring(dev, new_mtu);
+ }
- i = fep->rx_slot;
+ if (!ret) {
+ ndev->mtu = new_mtu;
+ dev->rx_skb_size = emac_rx_skb_size(new_mtu);
+ dev->rx_sync_size = emac_rx_sync_size(new_mtu);
+ }
+ local_bh_enable();
- PKT_DEBUG(("emac_rx_clean() entry, rx_slot: %d\n", fep->rx_slot));
+ return ret;
+}
- do {
- if (fep->rx_skb[i] == NULL)
- continue; /*we have already handled the packet but haved failed to alloc */
- /*
- since rx_desc is in uncached mem we don't keep reading it directly
- we pull out a local copy of ctrl and do the checks on the copy.
- */
- ctrl = fep->rx_desc[i].ctrl;
- if (ctrl & MAL_RX_CTRL_EMPTY)
- break; /*we don't have any more ready packets */
-
- if (EMAC_IS_BAD_RX_PACKET(ctrl)) {
- fep->stats.rx_errors++;
- fep->stats.rx_dropped++;
-
- if (ctrl & EMAC_RX_ST_OE)
- fep->stats.rx_fifo_errors++;
- if (ctrl & EMAC_RX_ST_AE)
- fep->stats.rx_frame_errors++;
- if (ctrl & EMAC_RX_ST_BFCS)
- fep->stats.rx_crc_errors++;
- if (ctrl & (EMAC_RX_ST_RP | EMAC_RX_ST_PTL |
- EMAC_RX_ST_ORE | EMAC_RX_ST_IRE))
- fep->stats.rx_length_errors++;
- } else {
- if ((ctrl & (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) ==
- (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) {
- /* Single descriptor packet */
- emac_rx_csum(dev, ctrl, fep->rx_skb[i]);
- /* Send the skb up the chain. */
- frame_length = fep->rx_desc[i].data_len - 4;
- skb_put(fep->rx_skb[i], frame_length);
- fep->rx_skb[i]->dev = dev;
- fep->rx_skb[i]->protocol =
- eth_type_trans(fep->rx_skb[i], dev);
- error = netif_rx(fep->rx_skb[i]);
-
- if ((error == NET_RX_DROP) ||
- (error == NET_RX_BAD)) {
- fep->stats.rx_dropped++;
- } else {
- fep->stats.rx_packets++;
- fep->stats.rx_bytes += frame_length;
- }
- fep->rx_skb[i] = NULL;
- } else {
- /* Multiple descriptor packet */
- if (ctrl & MAL_RX_CTRL_FIRST) {
- if (fep->rx_desc[(i + 1) % NUM_RX_BUFF].
- ctrl & MAL_RX_CTRL_EMPTY)
- break;
- bnum = 0;
- buf[bnum] = i;
- ++bnum;
- continue;
- }
- if (((ctrl & MAL_RX_CTRL_FIRST) !=
- MAL_RX_CTRL_FIRST) &&
- ((ctrl & MAL_RX_CTRL_LAST) !=
- MAL_RX_CTRL_LAST)) {
- if (fep->rx_desc[(i + 1) %
- NUM_RX_BUFF].ctrl &
- MAL_RX_CTRL_EMPTY) {
- i = buf[0];
- break;
- }
- buf[bnum] = i;
- ++bnum;
- continue;
- }
- if (ctrl & MAL_RX_CTRL_LAST) {
- buf[bnum] = i;
- ++bnum;
- skb_put(fep->rx_skb[buf[0]],
- fep->rx_desc[buf[0]].data_len);
- for (b = 1; b < bnum; b++) {
- /*
- * MAL is braindead, we need
- * to copy the remainder
- * of the packet from the
- * latter descriptor buffers
- * to the first skb. Then
- * dispose of the source
- * skbs.
- *
- * Once the stack is fixed
- * to handle frags on most
- * protocols we can generate
- * a fragmented skb with
- * no copies.
- */
- memcpy(fep->rx_skb[buf[0]]->
- data +
- fep->rx_skb[buf[0]]->len,
- fep->rx_skb[buf[b]]->
- data,
- fep->rx_desc[buf[b]].
- data_len);
- skb_put(fep->rx_skb[buf[0]],
- fep->rx_desc[buf[b]].
- data_len);
- dma_unmap_single(&fep->ocpdev->
- dev,
- fep->
- rx_desc[buf
- [b]].
- data_ptr,
- fep->
- rx_desc[buf
- [b]].
- data_len,
- DMA_FROM_DEVICE);
- dev_kfree_skb(fep->
- rx_skb[buf[b]]);
- }
- emac_rx_csum(dev, ctrl,
- fep->rx_skb[buf[0]]);
-
- fep->rx_skb[buf[0]]->dev = dev;
- fep->rx_skb[buf[0]]->protocol =
- eth_type_trans(fep->rx_skb[buf[0]],
- dev);
- error = netif_rx(fep->rx_skb[buf[0]]);
-
- if ((error == NET_RX_DROP)
- || (error == NET_RX_BAD)) {
- fep->stats.rx_dropped++;
- } else {
- fep->stats.rx_packets++;
- fep->stats.rx_bytes +=
- fep->rx_skb[buf[0]]->len;
- }
- for (b = 0; b < bnum; b++)
- fep->rx_skb[buf[b]] = NULL;
- }
- }
+static void emac_clean_tx_ring(struct ocp_enet_private *dev)
+{
+ int i;
+ for (i = 0; i < NUM_TX_BUFF; ++i) {
+ if (dev->tx_skb[i]) {
+ dev_kfree_skb(dev->tx_skb[i]);
+ dev->tx_skb[i] = NULL;
+ if (dev->tx_desc[i].ctrl & MAL_TX_CTRL_READY)
+ ++dev->estats.tx_dropped;
}
- } while ((i = (i + 1) % NUM_RX_BUFF) != fep->rx_slot);
-
- PKT_DEBUG(("emac_rx_clean() exit, rx_slot: %d\n", fep->rx_slot));
-
- return i;
+ dev->tx_desc[i].ctrl = 0;
+ dev->tx_desc[i].data_ptr = 0;
+ }
}
-static void emac_rxeob_dev(void *param, u32 chanmask)
+static void emac_clean_rx_ring(struct ocp_enet_private *dev)
{
- struct net_device *dev = param;
- struct ocp_enet_private *fep = dev->priv;
- unsigned long flags;
- int n;
+ int i;
+ for (i = 0; i < NUM_RX_BUFF; ++i)
+ if (dev->rx_skb[i]) {
+ dev->rx_desc[i].ctrl = 0;
+ dev_kfree_skb(dev->rx_skb[i]);
+ dev->rx_skb[i] = NULL;
+ dev->rx_desc[i].data_ptr = 0;
+ }
- spin_lock_irqsave(&fep->lock, flags);
- if ((n = emac_rx_clean(dev)) != fep->rx_slot)
- emac_rx_fill(dev, n);
- spin_unlock_irqrestore(&fep->lock, flags);
+ if (dev->rx_sg_skb) {
+ dev_kfree_skb(dev->rx_sg_skb);
+ dev->rx_sg_skb = NULL;
+ }
}
-/*
- * This interrupt should never occurr, we don't program
- * the MAL for contiunous mode.
- */
-static void emac_txde_dev(void *param, u32 chanmask)
+static inline int emac_alloc_rx_skb(struct ocp_enet_private *dev, int slot,
+ int flags)
{
- struct net_device *dev = param;
- struct ocp_enet_private *fep = dev->priv;
+ struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags);
+ if (unlikely(!skb))
+ return -ENOMEM;
- printk(KERN_WARNING "%s: transmit descriptor error\n", dev->name);
+ dev->rx_skb[slot] = skb;
+ dev->rx_desc[slot].data_len = 0;
- emac_mac_dump(dev);
- emac_mal_dump(dev);
+ skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+ dev->rx_desc[slot].data_ptr =
+ dma_map_single(dev->ldev, skb->data - 2, dev->rx_sync_size,
+ DMA_FROM_DEVICE) + 2;
+ barrier();
+ dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY |
+ (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
- /* Reenable the transmit channel */
- mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
+ return 0;
}
-/*
- * This interrupt should be very rare at best. This occurs when
- * the hardware has a problem with the receive descriptors. The manual
- * states that it occurs when the hardware cannot the receive descriptor
- * empty bit is not set. The recovery mechanism will be to
- * traverse through the descriptors, handle any that are marked to be
- * handled and reinitialize each along the way. At that point the driver
- * will be restarted.
- */
-static void emac_rxde_dev(void *param, u32 chanmask)
+static void emac_print_link_status(struct ocp_enet_private *dev)
{
- struct net_device *dev = param;
- struct ocp_enet_private *fep = dev->priv;
- unsigned long flags;
-
- if (net_ratelimit()) {
- printk(KERN_WARNING "%s: receive descriptor error\n",
- fep->ndev->name);
+ if (netif_carrier_ok(dev->ndev))
+ printk(KERN_INFO "%s: link is up, %d %s%s\n",
+ dev->ndev->name, dev->phy.speed,
+ dev->phy.duplex == DUPLEX_FULL ? "FDX" : "HDX",
+ dev->phy.pause ? ", pause enabled" :
+ dev->phy.asym_pause ? ", assymetric pause enabled" : "");
+ else
+ printk(KERN_INFO "%s: link is down\n", dev->ndev->name);
+}
- emac_mac_dump(dev);
- emac_mal_dump(dev);
- emac_desc_dump(dev);
+/* Process ctx, rtnl_lock semaphore */
+static int emac_open(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
+ int err, i;
+
+ DBG("%d: open" NL, dev->def->index);
+
+ /* Setup error IRQ handler */
+ err = request_irq(dev->def->irq, emac_irq, 0, "EMAC", dev);
+ if (err) {
+ printk(KERN_ERR "%s: failed to request IRQ %d\n",
+ ndev->name, dev->def->irq);
+ return err;
}
- /* Disable RX channel */
- spin_lock_irqsave(&fep->lock, flags);
- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
- /* For now, charge the error against all emacs */
- fep->stats.rx_errors++;
-
- /* so do we have any good packets still? */
- emac_rx_clean(dev);
-
- /* When the interface is restarted it resets processing to the
- * first descriptor in the table.
- */
-
- fep->rx_slot = 0;
- emac_rx_fill(dev, 0);
+ /* Allocate RX ring */
+ for (i = 0; i < NUM_RX_BUFF; ++i)
+ if (emac_alloc_rx_skb(dev, i, GFP_KERNEL)) {
+ printk(KERN_ERR "%s: failed to allocate RX ring\n",
+ ndev->name);
+ goto oom;
+ }
- set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, fep->commac.rx_chan_mask);
- set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, fep->commac.rx_chan_mask);
+ local_bh_disable();
+ dev->tx_cnt = dev->tx_slot = dev->ack_slot = dev->rx_slot =
+ dev->commac.rx_stopped = 0;
+ dev->rx_sg_skb = NULL;
+
+ if (dev->phy.address >= 0) {
+ int link_poll_interval;
+ if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ dev->phy.def->ops->read_link(&dev->phy);
+ EMAC_RX_CLK_DEFAULT(dev->def->index);
+ netif_carrier_on(dev->ndev);
+ link_poll_interval = PHY_POLL_LINK_ON;
+ } else {
+ EMAC_RX_CLK_TX(dev->def->index);
+ netif_carrier_off(dev->ndev);
+ link_poll_interval = PHY_POLL_LINK_OFF;
+ }
+ mod_timer(&dev->link_timer, jiffies + link_poll_interval);
+ emac_print_link_status(dev);
+ } else
+ netif_carrier_on(dev->ndev);
+
+ emac_configure(dev);
+ mal_poll_add(dev->mal, &dev->commac);
+ mal_enable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+ mal_set_rcbs(dev->mal, emacdata->mal_rx_chan, emac_rx_size(ndev->mtu));
+ mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+ emac_tx_enable(dev);
+ emac_rx_enable(dev);
+ netif_start_queue(ndev);
+ local_bh_enable();
- /* Reenable the receive channels */
- mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
- spin_unlock_irqrestore(&fep->lock, flags);
+ return 0;
+ oom:
+ emac_clean_rx_ring(dev);
+ free_irq(dev->def->irq, dev);
+ return -ENOMEM;
}
-static irqreturn_t
-emac_mac_irq(int irq, void *dev_instance, struct pt_regs *regs)
+/* BHs disabled */
+static int emac_link_differs(struct ocp_enet_private *dev)
{
- struct net_device *dev = dev_instance;
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
- unsigned long tmp_em0isr;
+ u32 r = in_be32(&dev->emacp->mr1);
- /* EMAC interrupt */
- tmp_em0isr = in_be32(&emacp->em0isr);
- if (tmp_em0isr & (EMAC_ISR_TE0 | EMAC_ISR_TE1)) {
- /* This error is a hard transmit error - could retransmit */
- fep->stats.tx_errors++;
+ int duplex = r & EMAC_MR1_FDE ? DUPLEX_FULL : DUPLEX_HALF;
+ int speed, pause, asym_pause;
- /* Reenable the transmit channel */
- mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
+ if (r & (EMAC_MR1_MF_1000 | EMAC_MR1_MF_1000GPCS))
+ speed = SPEED_1000;
+ else if (r & EMAC_MR1_MF_100)
+ speed = SPEED_100;
+ else
+ speed = SPEED_10;
- } else {
- fep->stats.rx_errors++;
+ switch (r & (EMAC_MR1_EIFC | EMAC_MR1_APP)) {
+ case (EMAC_MR1_EIFC | EMAC_MR1_APP):
+ pause = 1;
+ asym_pause = 0;
+ break;
+ case EMAC_MR1_APP:
+ pause = 0;
+ asym_pause = 1;
+ break;
+ default:
+ pause = asym_pause = 0;
}
-
- if (tmp_em0isr & EMAC_ISR_RP)
- fep->stats.rx_length_errors++;
- if (tmp_em0isr & EMAC_ISR_ALE)
- fep->stats.rx_frame_errors++;
- if (tmp_em0isr & EMAC_ISR_BFCS)
- fep->stats.rx_crc_errors++;
- if (tmp_em0isr & EMAC_ISR_PTLE)
- fep->stats.rx_length_errors++;
- if (tmp_em0isr & EMAC_ISR_ORE)
- fep->stats.rx_length_errors++;
- if (tmp_em0isr & EMAC_ISR_TE0)
- fep->stats.tx_aborted_errors++;
-
- emac_err_dump(dev, tmp_em0isr);
-
- out_be32(&emacp->em0isr, tmp_em0isr);
-
- return IRQ_HANDLED;
+ return speed != dev->phy.speed || duplex != dev->phy.duplex ||
+ pause != dev->phy.pause || asym_pause != dev->phy.asym_pause;
}
-static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+/* BHs disabled */
+static void emac_link_timer(unsigned long data)
{
- unsigned short ctrl;
- unsigned long flags;
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
- int len = skb->len;
- unsigned int offset = 0, size, f, tx_slot_first;
- unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
-
- spin_lock_irqsave(&fep->lock, flags);
+ struct ocp_enet_private *dev = (struct ocp_enet_private *)data;
+ int link_poll_interval;
- len -= skb->data_len;
+ DBG2("%d: link timer" NL, dev->def->index);
- if ((fep->tx_cnt + nr_frags + len / DESC_BUF_SIZE + 1) > NUM_TX_BUFF) {
- PKT_DEBUG(("emac_start_xmit() stopping queue\n"));
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&fep->lock, flags);
- return -EBUSY;
- }
+ if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ if (!netif_carrier_ok(dev->ndev)) {
+ EMAC_RX_CLK_DEFAULT(dev->def->index);
- tx_slot_first = fep->tx_slot;
+ /* Get new link parameters */
+ dev->phy.def->ops->read_link(&dev->phy);
- while (len) {
- size = min(len, DESC_BUF_SIZE);
+ if (dev->tah_dev || emac_link_differs(dev))
+ emac_full_tx_reset(dev->ndev);
- fep->tx_desc[fep->tx_slot].data_len = (short)size;
- fep->tx_desc[fep->tx_slot].data_ptr =
- (unsigned char *)dma_map_single(&fep->ocpdev->dev,
- (void *)((unsigned int)skb->
- data + offset),
- size, DMA_TO_DEVICE);
-
- ctrl = EMAC_TX_CTRL_DFLT;
- if (fep->tx_slot != tx_slot_first)
- ctrl |= MAL_TX_CTRL_READY;
- if ((NUM_TX_BUFF - 1) == fep->tx_slot)
- ctrl |= MAL_TX_CTRL_WRAP;
- if (!nr_frags && (len == size)) {
- ctrl |= MAL_TX_CTRL_LAST;
- fep->tx_skb[fep->tx_slot] = skb;
+ netif_carrier_on(dev->ndev);
+ emac_print_link_status(dev);
+ }
+ link_poll_interval = PHY_POLL_LINK_ON;
+ } else {
+ if (netif_carrier_ok(dev->ndev)) {
+ EMAC_RX_CLK_TX(dev->def->index);
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX)
+ emac_reinitialize(dev);
+#endif
+ netif_carrier_off(dev->ndev);
+ emac_print_link_status(dev);
}
- if (skb->ip_summed == CHECKSUM_HW)
- ctrl |= EMAC_TX_CTRL_TAH_CSUM;
- fep->tx_desc[fep->tx_slot].ctrl = ctrl;
+ /* Retry reset if the previous attempt failed.
+ * This is needed mostly for CONFIG_IBM_EMAC_PHY_RX_CLK_FIX
+ * case, but I left it here because it shouldn't trigger for
+ * sane PHYs anyway.
+ */
+ if (unlikely(dev->reset_failed))
+ emac_reinitialize(dev);
- len -= size;
- offset += size;
+ link_poll_interval = PHY_POLL_LINK_OFF;
+ }
+ mod_timer(&dev->link_timer, jiffies + link_poll_interval);
+}
- /* Bump tx count */
- if (++fep->tx_cnt == NUM_TX_BUFF)
- netif_stop_queue(dev);
+/* BHs disabled */
+static void emac_force_link_update(struct ocp_enet_private *dev)
+{
+ netif_carrier_off(dev->ndev);
+ if (timer_pending(&dev->link_timer))
+ mod_timer(&dev->link_timer, jiffies + PHY_POLL_LINK_OFF);
+}
- /* Next descriptor */
- if (++fep->tx_slot == NUM_TX_BUFF)
- fep->tx_slot = 0;
- }
+/* Process ctx, rtnl_lock semaphore */
+static int emac_close(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
- for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ DBG("%d: close" NL, dev->def->index);
- frag = &skb_shinfo(skb)->frags[f];
- len = frag->size;
- offset = 0;
-
- while (len) {
- size = min(len, DESC_BUF_SIZE);
-
- dma_map_page(&fep->ocpdev->dev,
- frag->page,
- frag->page_offset + offset,
- size, DMA_TO_DEVICE);
-
- ctrl = EMAC_TX_CTRL_DFLT | MAL_TX_CTRL_READY;
- if ((NUM_TX_BUFF - 1) == fep->tx_slot)
- ctrl |= MAL_TX_CTRL_WRAP;
- if ((f == (nr_frags - 1)) && (len == size)) {
- ctrl |= MAL_TX_CTRL_LAST;
- fep->tx_skb[fep->tx_slot] = skb;
- }
+ local_bh_disable();
- if (skb->ip_summed == CHECKSUM_HW)
- ctrl |= EMAC_TX_CTRL_TAH_CSUM;
+ if (dev->phy.address >= 0)
+ del_timer_sync(&dev->link_timer);
- fep->tx_desc[fep->tx_slot].data_len = (short)size;
- fep->tx_desc[fep->tx_slot].data_ptr =
- (char *)((page_to_pfn(frag->page) << PAGE_SHIFT) +
- frag->page_offset + offset);
- fep->tx_desc[fep->tx_slot].ctrl = ctrl;
+ netif_stop_queue(ndev);
+ emac_rx_disable(dev);
+ emac_tx_disable(dev);
+ mal_disable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+ mal_disable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+ mal_poll_del(dev->mal, &dev->commac);
+ local_bh_enable();
- len -= size;
- offset += size;
+ emac_clean_tx_ring(dev);
+ emac_clean_rx_ring(dev);
+ free_irq(dev->def->irq, dev);
- /* Bump tx count */
- if (++fep->tx_cnt == NUM_TX_BUFF)
- netif_stop_queue(dev);
+ return 0;
+}
- /* Next descriptor */
- if (++fep->tx_slot == NUM_TX_BUFF)
- fep->tx_slot = 0;
- }
+static inline u16 emac_tx_csum(struct ocp_enet_private *dev,
+ struct sk_buff *skb)
+{
+#if defined(CONFIG_IBM_EMAC_TAH)
+ if (skb->ip_summed == CHECKSUM_HW) {
+ ++dev->stats.tx_packets_csum;
+ return EMAC_TX_CTRL_TAH_CSUM;
}
+#endif
+ return 0;
+}
- /*
- * Deferred set READY on first descriptor of packet to
- * avoid TX MAL race.
- */
- fep->tx_desc[tx_slot_first].ctrl |= MAL_TX_CTRL_READY;
-
- /* Send the packet out. */
- out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT);
+static inline int emac_xmit_finish(struct ocp_enet_private *dev, int len)
+{
+ struct emac_regs *p = dev->emacp;
+ struct net_device *ndev = dev->ndev;
- fep->stats.tx_packets++;
- fep->stats.tx_bytes += skb->len;
+ /* Send the packet out */
+ out_be32(&p->tmr0, EMAC_TMR0_XMIT);
- PKT_DEBUG(("emac_start_xmit() exitn"));
+ if (unlikely(++dev->tx_cnt == NUM_TX_BUFF)) {
+ netif_stop_queue(ndev);
+ DBG2("%d: stopped TX queue" NL, dev->def->index);
+ }
- spin_unlock_irqrestore(&fep->lock, flags);
+ ndev->trans_start = jiffies;
+ ++dev->stats.tx_packets;
+ dev->stats.tx_bytes += len;
return 0;
}
-static int emac_adjust_to_link(struct ocp_enet_private *fep)
+/* BHs disabled */
+static int emac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
- emac_t *emacp = fep->emacp;
- unsigned long mode_reg;
- int full_duplex, speed;
-
- full_duplex = 0;
- speed = SPEED_10;
+ struct ocp_enet_private *dev = ndev->priv;
+ unsigned int len = skb->len;
+ int slot;
- /* set mode register 1 defaults */
- mode_reg = EMAC_M1_DEFAULT;
+ u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
+ MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb);
- /* Read link mode on PHY */
- if (fep->phy_mii.def->ops->read_link(&fep->phy_mii) == 0) {
- /* If an error occurred, we don't deal with it yet */
- full_duplex = (fep->phy_mii.duplex == DUPLEX_FULL);
- speed = fep->phy_mii.speed;
+ slot = dev->tx_slot++;
+ if (dev->tx_slot == NUM_TX_BUFF) {
+ dev->tx_slot = 0;
+ ctrl |= MAL_TX_CTRL_WRAP;
}
+ DBG2("%d: xmit(%u) %d" NL, dev->def->index, len, slot);
- /* set speed (default is 10Mb) */
- switch (speed) {
- case SPEED_1000:
- mode_reg |= EMAC_M1_RFS_16K;
- if (fep->rgmii_dev) {
- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(fep->rgmii_dev);
-
- if ((rgmii->mode[fep->rgmii_input] == RTBI)
- || (rgmii->mode[fep->rgmii_input] == TBI))
- mode_reg |= EMAC_M1_MF_1000GPCS;
- else
- mode_reg |= EMAC_M1_MF_1000MBPS;
-
- emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
- 1000);
- }
- break;
- case SPEED_100:
- mode_reg |= EMAC_M1_MF_100MBPS | EMAC_M1_RFS_4K;
- if (fep->rgmii_dev)
- emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
- 100);
- if (fep->zmii_dev)
- emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input,
- 100);
- break;
- case SPEED_10:
- default:
- mode_reg = (mode_reg & ~EMAC_M1_MF_100MBPS) | EMAC_M1_RFS_4K;
- if (fep->rgmii_dev)
- emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
- 10);
- if (fep->zmii_dev)
- emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input,
- 10);
- }
-
- if (full_duplex)
- mode_reg |= EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_IST;
- else
- mode_reg &= ~(EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_ILE);
-
- LINK_DEBUG(("%s: adjust to link, speed: %d, duplex: %d, opened: %d\n",
- fep->ndev->name, speed, full_duplex, fep->opened));
+ dev->tx_skb[slot] = skb;
+ dev->tx_desc[slot].data_ptr = dma_map_single(dev->ldev, skb->data, len,
+ DMA_TO_DEVICE);
+ dev->tx_desc[slot].data_len = (u16) len;
+ barrier();
+ dev->tx_desc[slot].ctrl = ctrl;
- printk(KERN_INFO "%s: Speed: %d, %s duplex.\n",
- fep->ndev->name, speed, full_duplex ? "Full" : "Half");
- if (fep->opened)
- out_be32(&emacp->em0mr1, mode_reg);
-
- return 0;
+ return emac_xmit_finish(dev, len);
}
-static int emac_set_mac_address(struct net_device *ndev, void *p)
+#if defined(CONFIG_IBM_EMAC_TAH)
+static inline int emac_xmit_split(struct ocp_enet_private *dev, int slot,
+ u32 pd, int len, int last, u16 base_ctrl)
{
- struct ocp_enet_private *fep = ndev->priv;
- emac_t *emacp = fep->emacp;
- struct sockaddr *addr = p;
+ while (1) {
+ u16 ctrl = base_ctrl;
+ int chunk = min(len, MAL_MAX_TX_SIZE);
+ len -= chunk;
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
+ slot = (slot + 1) % NUM_TX_BUFF;
- memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+ if (last && !len)
+ ctrl |= MAL_TX_CTRL_LAST;
+ if (slot == NUM_TX_BUFF - 1)
+ ctrl |= MAL_TX_CTRL_WRAP;
- /* set the high address */
- out_be32(&emacp->em0iahr,
- (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
+ dev->tx_skb[slot] = NULL;
+ dev->tx_desc[slot].data_ptr = pd;
+ dev->tx_desc[slot].data_len = (u16) chunk;
+ dev->tx_desc[slot].ctrl = ctrl;
+ ++dev->tx_cnt;
- /* set the low address */
- out_be32(&emacp->em0ialr,
- (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16)
- | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]);
+ if (!len)
+ break;
- return 0;
+ pd += chunk;
+ }
+ return slot;
}
-static int emac_change_mtu(struct net_device *dev, int new_mtu)
+/* BHs disabled (SG version for TAH equipped EMACs) */
+static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
{
- struct ocp_enet_private *fep = dev->priv;
- int old_mtu = dev->mtu;
- unsigned long mode_reg;
- emac_t *emacp = fep->emacp;
- u32 em0mr0;
- int i, full;
- unsigned long flags;
+ struct ocp_enet_private *dev = ndev->priv;
+ int nr_frags = skb_shinfo(skb)->nr_frags;
+ int len = skb->len, chunk;
+ int slot, i;
+ u16 ctrl;
+ u32 pd;
- if ((new_mtu < EMAC_MIN_MTU) || (new_mtu > EMAC_MAX_MTU)) {
- printk(KERN_ERR
- "emac: Invalid MTU setting, MTU must be between %d and %d\n",
- EMAC_MIN_MTU, EMAC_MAX_MTU);
- return -EINVAL;
- }
+ /* This is common "fast" path */
+ if (likely(!nr_frags && len <= MAL_MAX_TX_SIZE))
+ return emac_start_xmit(skb, ndev);
- if (old_mtu != new_mtu && netif_running(dev)) {
- /* Stop rx engine */
- em0mr0 = in_be32(&emacp->em0mr0);
- out_be32(&emacp->em0mr0, em0mr0 & ~EMAC_M0_RXE);
-
- /* Wait for descriptors to be empty */
- do {
- full = 0;
- for (i = 0; i < NUM_RX_BUFF; i++)
- if (!(fep->rx_desc[i].ctrl & MAL_RX_CTRL_EMPTY)) {
- printk(KERN_NOTICE
- "emac: RX ring is still full\n");
- full = 1;
- }
- } while (full);
-
- spin_lock_irqsave(&fep->lock, flags);
-
- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
- /* Destroy all old rx skbs */
- for (i = 0; i < NUM_RX_BUFF; i++) {
- dma_unmap_single(&fep->ocpdev->dev,
- fep->rx_desc[i].data_ptr,
- fep->rx_desc[i].data_len,
- DMA_FROM_DEVICE);
- dev_kfree_skb(fep->rx_skb[i]);
- fep->rx_skb[i] = NULL;
- }
+ len -= skb->data_len;
- /* Set new rx_buffer_size, jumbo cap, and advertise new mtu */
- mode_reg = in_be32(&emacp->em0mr1);
- if (new_mtu > ENET_DEF_MTU_SIZE) {
- mode_reg |= EMAC_M1_JUMBO_ENABLE;
- fep->rx_buffer_size = EMAC_MAX_FRAME;
- } else {
- mode_reg &= ~EMAC_M1_JUMBO_ENABLE;
- fep->rx_buffer_size = ENET_DEF_BUF_SIZE;
- }
- dev->mtu = new_mtu;
- out_be32(&emacp->em0mr1, mode_reg);
+ /* Note, this is only an *estimation*, we can still run out of empty
+ * slots because of the additional fragmentation into
+ * MAL_MAX_TX_SIZE-sized chunks
+ */
+ if (unlikely(dev->tx_cnt + nr_frags + mal_tx_chunks(len) > NUM_TX_BUFF))
+ goto stop_queue;
+
+ ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
+ emac_tx_csum(dev, skb);
+ slot = dev->tx_slot;
+
+ /* skb data */
+ dev->tx_skb[slot] = NULL;
+ chunk = min(len, MAL_MAX_TX_SIZE);
+ dev->tx_desc[slot].data_ptr = pd =
+ dma_map_single(dev->ldev, skb->data, len, DMA_TO_DEVICE);
+ dev->tx_desc[slot].data_len = (u16) chunk;
+ len -= chunk;
+ if (unlikely(len))
+ slot = emac_xmit_split(dev, slot, pd + chunk, len, !nr_frags,
+ ctrl);
+ /* skb fragments */
+ for (i = 0; i < nr_frags; ++i) {
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ len = frag->size;
- /* Re-init rx skbs */
- fep->rx_slot = 0;
- emac_rx_fill(dev, 0);
+ if (unlikely(dev->tx_cnt + mal_tx_chunks(len) >= NUM_TX_BUFF))
+ goto undo_frame;
- /* Restart the rx engine */
- mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
- out_be32(&emacp->em0mr0, em0mr0 | EMAC_M0_RXE);
+ pd = dma_map_page(dev->ldev, frag->page, frag->page_offset, len,
+ DMA_TO_DEVICE);
- spin_unlock_irqrestore(&fep->lock, flags);
+ slot = emac_xmit_split(dev, slot, pd, len, i == nr_frags - 1,
+ ctrl);
}
- return 0;
-}
+ DBG2("%d: xmit_sg(%u) %d - %d" NL, dev->def->index, skb->len,
+ dev->tx_slot, slot);
-static void __emac_set_multicast_list(struct net_device *dev)
-{
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
- u32 rmr = in_be32(&emacp->em0rmr);
+ /* Attach skb to the last slot so we don't release it too early */
+ dev->tx_skb[slot] = skb;
- /* First clear all special bits, they can be set later */
- rmr &= ~(EMAC_RMR_PME | EMAC_RMR_PMME | EMAC_RMR_MAE);
+ /* Send the packet out */
+ if (dev->tx_slot == NUM_TX_BUFF - 1)
+ ctrl |= MAL_TX_CTRL_WRAP;
+ barrier();
+ dev->tx_desc[dev->tx_slot].ctrl = ctrl;
+ dev->tx_slot = (slot + 1) % NUM_TX_BUFF;
- if (dev->flags & IFF_PROMISC) {
- rmr |= EMAC_RMR_PME;
- } else if (dev->flags & IFF_ALLMULTI || 32 < dev->mc_count) {
- /*
- * Must be setting up to use multicast
- * Now check for promiscuous multicast
- */
- rmr |= EMAC_RMR_PMME;
- } else if (dev->flags & IFF_MULTICAST && 0 < dev->mc_count) {
- unsigned short em0gaht[4] = { 0, 0, 0, 0 };
- struct dev_mc_list *dmi;
-
- /* Need to hash on the multicast address. */
- for (dmi = dev->mc_list; dmi; dmi = dmi->next) {
- unsigned long mc_crc;
- unsigned int bit_number;
-
- mc_crc = ether_crc(6, (char *)dmi->dmi_addr);
- bit_number = 63 - (mc_crc >> 26); /* MSB: 0 LSB: 63 */
- em0gaht[bit_number >> 4] |=
- 0x8000 >> (bit_number & 0x0f);
- }
- emacp->em0gaht1 = em0gaht[0];
- emacp->em0gaht2 = em0gaht[1];
- emacp->em0gaht3 = em0gaht[2];
- emacp->em0gaht4 = em0gaht[3];
+ return emac_xmit_finish(dev, skb->len);
- /* Turn on multicast addressing */
- rmr |= EMAC_RMR_MAE;
+ undo_frame:
+ /* Well, too bad. Our previous estimation was overly optimistic.
+ * Undo everything.
+ */
+ while (slot != dev->tx_slot) {
+ dev->tx_desc[slot].ctrl = 0;
+ --dev->tx_cnt;
+ if (--slot < 0)
+ slot = NUM_TX_BUFF - 1;
}
- out_be32(&emacp->em0rmr, rmr);
+ ++dev->estats.tx_undo;
+
+ stop_queue:
+ netif_stop_queue(ndev);
+ DBG2("%d: stopped TX queue" NL, dev->def->index);
+ return 1;
}
+#else
+# define emac_start_xmit_sg emac_start_xmit
+#endif /* !defined(CONFIG_IBM_EMAC_TAH) */
-static int emac_init_tah(struct ocp_enet_private *fep)
+/* BHs disabled */
+static void emac_parse_tx_error(struct ocp_enet_private *dev, u16 ctrl)
{
- tah_t *tahp;
-
- /* Initialize TAH and enable checksum verification */
- tahp = (tah_t *) ioremap(fep->tah_dev->def->paddr, sizeof(*tahp));
+ struct ibm_emac_error_stats *st = &dev->estats;
+ DBG("%d: BD TX error %04x" NL, dev->def->index, ctrl);
+
+ ++st->tx_bd_errors;
+ if (ctrl & EMAC_TX_ST_BFCS)
+ ++st->tx_bd_bad_fcs;
+ if (ctrl & EMAC_TX_ST_LCS)
+ ++st->tx_bd_carrier_loss;
+ if (ctrl & EMAC_TX_ST_ED)
+ ++st->tx_bd_excessive_deferral;
+ if (ctrl & EMAC_TX_ST_EC)
+ ++st->tx_bd_excessive_collisions;
+ if (ctrl & EMAC_TX_ST_LC)
+ ++st->tx_bd_late_collision;
+ if (ctrl & EMAC_TX_ST_MC)
+ ++st->tx_bd_multple_collisions;
+ if (ctrl & EMAC_TX_ST_SC)
+ ++st->tx_bd_single_collision;
+ if (ctrl & EMAC_TX_ST_UR)
+ ++st->tx_bd_underrun;
+ if (ctrl & EMAC_TX_ST_SQE)
+ ++st->tx_bd_sqe;
+}
- if (tahp == NULL) {
- printk(KERN_ERR "tah%d: Cannot ioremap TAH registers!\n",
- fep->tah_dev->def->index);
+static void emac_poll_tx(void *param)
+{
+ struct ocp_enet_private *dev = param;
+ DBG2("%d: poll_tx, %d %d" NL, dev->def->index, dev->tx_cnt,
+ dev->ack_slot);
+
+ if (dev->tx_cnt) {
+ u16 ctrl;
+ int slot = dev->ack_slot, n = 0;
+ again:
+ ctrl = dev->tx_desc[slot].ctrl;
+ if (!(ctrl & MAL_TX_CTRL_READY)) {
+ struct sk_buff *skb = dev->tx_skb[slot];
+ ++n;
+
+ if (skb) {
+ dev_kfree_skb(skb);
+ dev->tx_skb[slot] = NULL;
+ }
+ slot = (slot + 1) % NUM_TX_BUFF;
- return -ENOMEM;
- }
+ if (unlikely(EMAC_IS_BAD_TX(ctrl)))
+ emac_parse_tx_error(dev, ctrl);
- out_be32(&tahp->tah_mr, TAH_MR_SR);
+ if (--dev->tx_cnt)
+ goto again;
+ }
+ if (n) {
+ dev->ack_slot = slot;
+ if (netif_queue_stopped(dev->ndev) &&
+ dev->tx_cnt < EMAC_TX_WAKEUP_THRESH)
+ netif_wake_queue(dev->ndev);
- /* wait for reset to complete */
- while (in_be32(&tahp->tah_mr) & TAH_MR_SR) ;
+ DBG2("%d: tx %d pkts" NL, dev->def->index, n);
+ }
+ }
+}
- /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
- out_be32(&tahp->tah_mr,
- TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
- TAH_MR_DIG);
+static inline void emac_recycle_rx_skb(struct ocp_enet_private *dev, int slot,
+ int len)
+{
+ struct sk_buff *skb = dev->rx_skb[slot];
+ DBG2("%d: recycle %d %d" NL, dev->def->index, slot, len);
- iounmap(&tahp);
+ if (len)
+ dma_map_single(dev->ldev, skb->data - 2,
+ EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE);
- return 0;
+ dev->rx_desc[slot].data_len = 0;
+ barrier();
+ dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY |
+ (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
}
-static void emac_init_rings(struct net_device *dev)
+static void emac_parse_rx_error(struct ocp_enet_private *dev, u16 ctrl)
{
- struct ocp_enet_private *ep = dev->priv;
- int loop;
+ struct ibm_emac_error_stats *st = &dev->estats;
+ DBG("%d: BD RX error %04x" NL, dev->def->index, ctrl);
+
+ ++st->rx_bd_errors;
+ if (ctrl & EMAC_RX_ST_OE)
+ ++st->rx_bd_overrun;
+ if (ctrl & EMAC_RX_ST_BP)
+ ++st->rx_bd_bad_packet;
+ if (ctrl & EMAC_RX_ST_RP)
+ ++st->rx_bd_runt_packet;
+ if (ctrl & EMAC_RX_ST_SE)
+ ++st->rx_bd_short_event;
+ if (ctrl & EMAC_RX_ST_AE)
+ ++st->rx_bd_alignment_error;
+ if (ctrl & EMAC_RX_ST_BFCS)
+ ++st->rx_bd_bad_fcs;
+ if (ctrl & EMAC_RX_ST_PTL)
+ ++st->rx_bd_packet_too_long;
+ if (ctrl & EMAC_RX_ST_ORE)
+ ++st->rx_bd_out_of_range;
+ if (ctrl & EMAC_RX_ST_IRE)
+ ++st->rx_bd_in_range;
+}
- ep->tx_desc = (struct mal_descriptor *)((char *)ep->mal->tx_virt_addr +
- (ep->mal_tx_chan *
- MAL_DT_ALIGN));
- ep->rx_desc =
- (struct mal_descriptor *)((char *)ep->mal->rx_virt_addr +
- (ep->mal_rx_chan * MAL_DT_ALIGN));
+static inline void emac_rx_csum(struct ocp_enet_private *dev,
+ struct sk_buff *skb, u16 ctrl)
+{
+#if defined(CONFIG_IBM_EMAC_TAH)
+ if (!ctrl && dev->tah_dev) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ ++dev->stats.rx_packets_csum;
+ }
+#endif
+}
- /* Fill in the transmit descriptor ring. */
- for (loop = 0; loop < NUM_TX_BUFF; loop++) {
- if (ep->tx_skb[loop]) {
- dma_unmap_single(&ep->ocpdev->dev,
- ep->tx_desc[loop].data_ptr,
- ep->tx_desc[loop].data_len,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(ep->tx_skb[loop]);
+static inline int emac_rx_sg_append(struct ocp_enet_private *dev, int slot)
+{
+ if (likely(dev->rx_sg_skb != NULL)) {
+ int len = dev->rx_desc[slot].data_len;
+ int tot_len = dev->rx_sg_skb->len + len;
+
+ if (unlikely(tot_len + 2 > dev->rx_skb_size)) {
+ ++dev->estats.rx_dropped_mtu;
+ dev_kfree_skb(dev->rx_sg_skb);
+ dev->rx_sg_skb = NULL;
+ } else {
+ cacheable_memcpy(dev->rx_sg_skb->tail,
+ dev->rx_skb[slot]->data, len);
+ skb_put(dev->rx_sg_skb, len);
+ emac_recycle_rx_skb(dev, slot, len);
+ return 0;
}
- ep->tx_skb[loop] = NULL;
- ep->tx_desc[loop].ctrl = 0;
- ep->tx_desc[loop].data_len = 0;
- ep->tx_desc[loop].data_ptr = NULL;
- }
- ep->tx_desc[loop - 1].ctrl |= MAL_TX_CTRL_WRAP;
-
- /* Format the receive descriptor ring. */
- ep->rx_slot = 0;
- /* Default is MTU=1500 + Ethernet overhead */
- ep->rx_buffer_size = dev->mtu + ENET_HEADER_SIZE + ENET_FCS_SIZE;
- emac_rx_fill(dev, 0);
- if (ep->rx_slot != 0) {
- printk(KERN_ERR
- "%s: Not enough mem for RxChain durning Open?\n",
- dev->name);
- /*We couldn't fill the ring at startup?
- *We could clean up and fail to open but right now we will try to
- *carry on. It may be a sign of a bad NUM_RX_BUFF value
- */
}
-
- ep->tx_cnt = 0;
- ep->tx_slot = 0;
- ep->ack_slot = 0;
+ emac_recycle_rx_skb(dev, slot, 0);
+ return -1;
}
-static void emac_reset_configure(struct ocp_enet_private *fep)
+/* BHs disabled */
+static int emac_poll_rx(void *param, int budget)
{
- emac_t *emacp = fep->emacp;
- int i;
-
- mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
- /*
- * Check for a link, some PHYs don't provide a clock if
- * no link is present. Some EMACs will not come out of
- * soft reset without a PHY clock present.
- */
- if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) {
- /* Reset the EMAC */
- out_be32(&emacp->em0mr0, EMAC_M0_SRST);
- udelay(20);
- for (i = 0; i < 100; i++) {
- if ((in_be32(&emacp->em0mr0) & EMAC_M0_SRST) == 0)
- break;
- udelay(10);
- }
+ struct ocp_enet_private *dev = param;
+ int slot = dev->rx_slot, received = 0;
- if (i >= 100) {
- printk(KERN_ERR "%s: Cannot reset EMAC\n",
- fep->ndev->name);
- return;
- }
- }
+ DBG2("%d: poll_rx(%d)" NL, dev->def->index, budget);
- /* Switch IRQs off for now */
- out_be32(&emacp->em0iser, 0);
+ again:
+ while (budget > 0) {
+ int len;
+ struct sk_buff *skb;
+ u16 ctrl = dev->rx_desc[slot].ctrl;
- /* Configure MAL rx channel */
- mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);
+ if (ctrl & MAL_RX_CTRL_EMPTY)
+ break;
- /* set the high address */
- out_be32(&emacp->em0iahr,
- (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
+ skb = dev->rx_skb[slot];
+ barrier();
+ len = dev->rx_desc[slot].data_len;
- /* set the low address */
- out_be32(&emacp->em0ialr,
- (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16)
- | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]);
+ if (unlikely(!MAL_IS_SINGLE_RX(ctrl)))
+ goto sg;
- /* Adjust to link */
- if (netif_carrier_ok(fep->ndev))
- emac_adjust_to_link(fep);
+ ctrl &= EMAC_BAD_RX_MASK;
+ if (unlikely(ctrl && ctrl != EMAC_RX_TAH_BAD_CSUM)) {
+ emac_parse_rx_error(dev, ctrl);
+ ++dev->estats.rx_dropped_error;
+ emac_recycle_rx_skb(dev, slot, 0);
+ len = 0;
+ goto next;
+ }
- /* enable broadcast/individual address and RX FIFO defaults */
- out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT);
+ if (len && len < EMAC_RX_COPY_THRESH) {
+ struct sk_buff *copy_skb =
+ alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC);
+ if (unlikely(!copy_skb))
+ goto oom;
+
+ skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
+ cacheable_memcpy(copy_skb->data - 2, skb->data - 2,
+ len + 2);
+ emac_recycle_rx_skb(dev, slot, len);
+ skb = copy_skb;
+ } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC)))
+ goto oom;
+
+ skb_put(skb, len);
+ push_packet:
+ skb->dev = dev->ndev;
+ skb->protocol = eth_type_trans(skb, dev->ndev);
+ emac_rx_csum(dev, skb, ctrl);
+
+ if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+ ++dev->estats.rx_dropped_stack;
+ next:
+ ++dev->stats.rx_packets;
+ skip:
+ dev->stats.rx_bytes += len;
+ slot = (slot + 1) % NUM_RX_BUFF;
+ --budget;
+ ++received;
+ continue;
+ sg:
+ if (ctrl & MAL_RX_CTRL_FIRST) {
+ BUG_ON(dev->rx_sg_skb);
+ if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) {
+ DBG("%d: rx OOM %d" NL, dev->def->index, slot);
+ ++dev->estats.rx_dropped_oom;
+ emac_recycle_rx_skb(dev, slot, 0);
+ } else {
+ dev->rx_sg_skb = skb;
+ skb_put(skb, len);
+ }
+ } else if (!emac_rx_sg_append(dev, slot) &&
+ (ctrl & MAL_RX_CTRL_LAST)) {
+
+ skb = dev->rx_sg_skb;
+ dev->rx_sg_skb = NULL;
+
+ ctrl &= EMAC_BAD_RX_MASK;
+ if (unlikely(ctrl && ctrl != EMAC_RX_TAH_BAD_CSUM)) {
+ emac_parse_rx_error(dev, ctrl);
+ ++dev->estats.rx_dropped_error;
+ dev_kfree_skb(skb);
+ len = 0;
+ } else
+ goto push_packet;
+ }
+ goto skip;
+ oom:
+ DBG("%d: rx OOM %d" NL, dev->def->index, slot);
+ /* Drop the packet and recycle skb */
+ ++dev->estats.rx_dropped_oom;
+ emac_recycle_rx_skb(dev, slot, 0);
+ goto next;
+ }
- /* set transmit request threshold register */
- out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT);
+ if (received) {
+ DBG2("%d: rx %d BDs" NL, dev->def->index, received);
+ dev->rx_slot = slot;
+ }
- /* Reconfigure multicast */
- __emac_set_multicast_list(fep->ndev);
+ if (unlikely(budget && dev->commac.rx_stopped)) {
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
- /* Set receiver/transmitter defaults */
- out_be32(&emacp->em0rwmr, EMAC_RWMR_DEFAULT);
- out_be32(&emacp->em0tmr0, EMAC_TMR0_DEFAULT);
- out_be32(&emacp->em0tmr1, EMAC_TMR1_DEFAULT);
+ barrier();
+ if (!(dev->rx_desc[slot].ctrl & MAL_RX_CTRL_EMPTY)) {
+ DBG2("%d: rx restart" NL, dev->def->index);
+ received = 0;
+ goto again;
+ }
- /* set frame gap */
- out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP);
-
- /* set VLAN Tag Protocol Identifier */
- out_be32(&emacp->em0vtpid, 0x8100);
+ if (dev->rx_sg_skb) {
+ DBG2("%d: dropping partial rx packet" NL,
+ dev->def->index);
+ ++dev->estats.rx_dropped_error;
+ dev_kfree_skb(dev->rx_sg_skb);
+ dev->rx_sg_skb = NULL;
+ }
- /* Init ring buffers */
- emac_init_rings(fep->ndev);
+ dev->commac.rx_stopped = 0;
+ mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+ emac_rx_enable(dev);
+ dev->rx_slot = 0;
+ }
+ return received;
}
-static void emac_kick(struct ocp_enet_private *fep)
+/* BHs disabled */
+static int emac_peek_rx(void *param)
{
- emac_t *emacp = fep->emacp;
- unsigned long emac_ier;
-
- emac_ier = EMAC_ISR_PP | EMAC_ISR_BP | EMAC_ISR_RP |
- EMAC_ISR_SE | EMAC_ISR_PTLE | EMAC_ISR_ALE |
- EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE;
+ struct ocp_enet_private *dev = param;
+ return !(dev->rx_desc[dev->rx_slot].ctrl & MAL_RX_CTRL_EMPTY);
+}
- out_be32(&emacp->em0iser, emac_ier);
+/* BHs disabled */
+static int emac_peek_rx_sg(void *param)
+{
+ struct ocp_enet_private *dev = param;
+ int slot = dev->rx_slot;
+ while (1) {
+ u16 ctrl = dev->rx_desc[slot].ctrl;
+ if (ctrl & MAL_RX_CTRL_EMPTY)
+ return 0;
+ else if (ctrl & MAL_RX_CTRL_LAST)
+ return 1;
- /* enable all MAL transmit and receive channels */
- mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
- mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
+ slot = (slot + 1) % NUM_RX_BUFF;
- /* set transmit and receive enable */
- out_be32(&emacp->em0mr0, EMAC_M0_TXE | EMAC_M0_RXE);
+ /* I'm just being paranoid here :) */
+ if (unlikely(slot == dev->rx_slot))
+ return 0;
+ }
}
-static void
-emac_start_link(struct ocp_enet_private *fep, struct ethtool_cmd *ep)
+/* Hard IRQ */
+static void emac_rxde(void *param)
{
- u32 advertise;
- int autoneg;
- int forced_speed;
- int forced_duplex;
+ struct ocp_enet_private *dev = param;
+ ++dev->estats.rx_stopped;
+ emac_rx_disable_async(dev);
+}
- /* Default advertise */
- advertise = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full;
- autoneg = fep->want_autoneg;
- forced_speed = fep->phy_mii.speed;
- forced_duplex = fep->phy_mii.duplex;
+/* Hard IRQ */
+static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ocp_enet_private *dev = dev_instance;
+ struct emac_regs *p = dev->emacp;
+ struct ibm_emac_error_stats *st = &dev->estats;
+
+ u32 isr = in_be32(&p->isr);
+ out_be32(&p->isr, isr);
+
+ DBG("%d: isr = %08x" NL, dev->def->index, isr);
+
+ if (isr & EMAC_ISR_TXPE)
+ ++st->tx_parity;
+ if (isr & EMAC_ISR_RXPE)
+ ++st->rx_parity;
+ if (isr & EMAC_ISR_TXUE)
+ ++st->tx_underrun;
+ if (isr & EMAC_ISR_RXOE)
+ ++st->rx_fifo_overrun;
+ if (isr & EMAC_ISR_OVR)
+ ++st->rx_overrun;
+ if (isr & EMAC_ISR_BP)
+ ++st->rx_bad_packet;
+ if (isr & EMAC_ISR_RP)
+ ++st->rx_runt_packet;
+ if (isr & EMAC_ISR_SE)
+ ++st->rx_short_event;
+ if (isr & EMAC_ISR_ALE)
+ ++st->rx_alignment_error;
+ if (isr & EMAC_ISR_BFCS)
+ ++st->rx_bad_fcs;
+ if (isr & EMAC_ISR_PTLE)
+ ++st->rx_packet_too_long;
+ if (isr & EMAC_ISR_ORE)
+ ++st->rx_out_of_range;
+ if (isr & EMAC_ISR_IRE)
+ ++st->rx_in_range;
+ if (isr & EMAC_ISR_SQE)
+ ++st->tx_sqe;
+ if (isr & EMAC_ISR_TE)
+ ++st->tx_errors;
- /* Setup link parameters */
- if (ep) {
- if (ep->autoneg == AUTONEG_ENABLE) {
- advertise = ep->advertising;
- autoneg = 1;
- } else {
- autoneg = 0;
- forced_speed = ep->speed;
- forced_duplex = ep->duplex;
- }
- }
+ return IRQ_HANDLED;
+}
- /* Configure PHY & start aneg */
- fep->want_autoneg = autoneg;
- if (autoneg) {
- LINK_DEBUG(("%s: start link aneg, advertise: 0x%x\n",
- fep->ndev->name, advertise));
- fep->phy_mii.def->ops->setup_aneg(&fep->phy_mii, advertise);
- } else {
- LINK_DEBUG(("%s: start link forced, speed: %d, duplex: %d\n",
- fep->ndev->name, forced_speed, forced_duplex));
- fep->phy_mii.def->ops->setup_forced(&fep->phy_mii, forced_speed,
- forced_duplex);
- }
- fep->timer_ticks = 0;
- mod_timer(&fep->link_timer, jiffies + HZ);
+static struct net_device_stats *emac_stats(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct ibm_emac_stats *st = &dev->stats;
+ struct ibm_emac_error_stats *est = &dev->estats;
+ struct net_device_stats *nst = &dev->nstats;
+
+ DBG2("%d: stats" NL, dev->def->index);
+
+ /* Compute "legacy" statistics */
+ local_irq_disable();
+ nst->rx_packets = (unsigned long)st->rx_packets;
+ nst->rx_bytes = (unsigned long)st->rx_bytes;
+ nst->tx_packets = (unsigned long)st->tx_packets;
+ nst->tx_bytes = (unsigned long)st->tx_bytes;
+ nst->rx_dropped = (unsigned long)(est->rx_dropped_oom +
+ est->rx_dropped_error +
+ est->rx_dropped_resize +
+ est->rx_dropped_mtu);
+ nst->tx_dropped = (unsigned long)est->tx_dropped;
+
+ nst->rx_errors = (unsigned long)est->rx_bd_errors;
+ nst->rx_fifo_errors = (unsigned long)(est->rx_bd_overrun +
+ est->rx_fifo_overrun +
+ est->rx_overrun);
+ nst->rx_frame_errors = (unsigned long)(est->rx_bd_alignment_error +
+ est->rx_alignment_error);
+ nst->rx_crc_errors = (unsigned long)(est->rx_bd_bad_fcs +
+ est->rx_bad_fcs);
+ nst->rx_length_errors = (unsigned long)(est->rx_bd_runt_packet +
+ est->rx_bd_short_event +
+ est->rx_bd_packet_too_long +
+ est->rx_bd_out_of_range +
+ est->rx_bd_in_range +
+ est->rx_runt_packet +
+ est->rx_short_event +
+ est->rx_packet_too_long +
+ est->rx_out_of_range +
+ est->rx_in_range);
+
+ nst->tx_errors = (unsigned long)(est->tx_bd_errors + est->tx_errors);
+ nst->tx_fifo_errors = (unsigned long)(est->tx_bd_underrun +
+ est->tx_underrun);
+ nst->tx_carrier_errors = (unsigned long)est->tx_bd_carrier_loss;
+ nst->collisions = (unsigned long)(est->tx_bd_excessive_deferral +
+ est->tx_bd_excessive_collisions +
+ est->tx_bd_late_collision +
+ est->tx_bd_multple_collisions);
+ local_irq_enable();
+ return nst;
}
-static void emac_link_timer(unsigned long data)
+static void emac_remove(struct ocp_device *ocpdev)
{
- struct ocp_enet_private *fep = (struct ocp_enet_private *)data;
- int link;
+ struct ocp_enet_private *dev = ocp_get_drvdata(ocpdev);
- if (fep->going_away)
- return;
+ DBG("%d: remove" NL, dev->def->index);
- spin_lock_irq(&fep->lock);
+ ocp_set_drvdata(ocpdev, 0);
+ unregister_netdev(dev->ndev);
- link = fep->phy_mii.def->ops->poll_link(&fep->phy_mii);
- LINK_DEBUG(("%s: poll_link: %d\n", fep->ndev->name, link));
+ tah_fini(dev->tah_dev);
+ rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
+ zmii_fini(dev->zmii_dev, dev->zmii_input);
- if (link == netif_carrier_ok(fep->ndev)) {
- if (!link && fep->want_autoneg && (++fep->timer_ticks) > 10)
- emac_start_link(fep, NULL);
- goto out;
- }
- printk(KERN_INFO "%s: Link is %s\n", fep->ndev->name,
- link ? "Up" : "Down");
- if (link) {
- netif_carrier_on(fep->ndev);
- /* Chip needs a full reset on config change. That sucks, so I
- * should ultimately move that to some tasklet to limit
- * latency peaks caused by this code
- */
- emac_reset_configure(fep);
- if (fep->opened)
- emac_kick(fep);
- } else {
- fep->timer_ticks = 0;
- netif_carrier_off(fep->ndev);
- }
- out:
- mod_timer(&fep->link_timer, jiffies + HZ);
- spin_unlock_irq(&fep->lock);
+ emac_dbg_register(dev->def->index, 0);
+
+ mal_unregister_commac(dev->mal, &dev->commac);
+ iounmap((void *)dev->emacp);
+ kfree(dev->ndev);
}
-static void emac_set_multicast_list(struct net_device *dev)
-{
- struct ocp_enet_private *fep = dev->priv;
+static struct mal_commac_ops emac_commac_ops = {
+ .poll_tx = &emac_poll_tx,
+ .poll_rx = &emac_poll_rx,
+ .peek_rx = &emac_peek_rx,
+ .rxde = &emac_rxde,
+};
- spin_lock_irq(&fep->lock);
- __emac_set_multicast_list(dev);
- spin_unlock_irq(&fep->lock);
-}
+static struct mal_commac_ops emac_commac_sg_ops = {
+ .poll_tx = &emac_poll_tx,
+ .poll_rx = &emac_poll_rx,
+ .peek_rx = &emac_peek_rx_sg,
+ .rxde = &emac_rxde,
+};
-static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+/* Ethtool support */
+static int emac_ethtool_get_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
{
- struct ocp_enet_private *fep = ndev->priv;
+ struct ocp_enet_private *dev = ndev->priv;
- cmd->supported = fep->phy_mii.def->features;
+ cmd->supported = dev->phy.features;
cmd->port = PORT_MII;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->phy_address = fep->mii_phy_addr;
- spin_lock_irq(&fep->lock);
- cmd->autoneg = fep->want_autoneg;
- cmd->speed = fep->phy_mii.speed;
- cmd->duplex = fep->phy_mii.duplex;
- spin_unlock_irq(&fep->lock);
+ cmd->phy_address = dev->phy.address;
+ cmd->transceiver =
+ dev->phy.address >= 0 ? XCVR_EXTERNAL : XCVR_INTERNAL;
+
+ local_bh_disable();
+ cmd->advertising = dev->phy.advertising;
+ cmd->autoneg = dev->phy.autoneg;
+ cmd->speed = dev->phy.speed;
+ cmd->duplex = dev->phy.duplex;
+ local_bh_enable();
+
return 0;
}
-static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+static int emac_ethtool_set_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
{
- struct ocp_enet_private *fep = ndev->priv;
- unsigned long features = fep->phy_mii.def->features;
+ struct ocp_enet_private *dev = ndev->priv;
+ u32 f = dev->phy.features;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ DBG("%d: set_settings(%d, %d, %d, 0x%08x)" NL, dev->def->index,
+ cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising);
+ /* Basic sanity checks */
+ if (dev->phy.address < 0)
+ return -EOPNOTSUPP;
if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
return -EINVAL;
if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
return -EINVAL;
if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
return -EINVAL;
- if (cmd->autoneg == AUTONEG_DISABLE)
+
+ if (cmd->autoneg == AUTONEG_DISABLE) {
switch (cmd->speed) {
case SPEED_10:
- if (cmd->duplex == DUPLEX_HALF &&
- (features & SUPPORTED_10baseT_Half) == 0)
+ if (cmd->duplex == DUPLEX_HALF
+ && !(f & SUPPORTED_10baseT_Half))
return -EINVAL;
- if (cmd->duplex == DUPLEX_FULL &&
- (features & SUPPORTED_10baseT_Full) == 0)
+ if (cmd->duplex == DUPLEX_FULL
+ && !(f & SUPPORTED_10baseT_Full))
return -EINVAL;
break;
case SPEED_100:
- if (cmd->duplex == DUPLEX_HALF &&
- (features & SUPPORTED_100baseT_Half) == 0)
+ if (cmd->duplex == DUPLEX_HALF
+ && !(f & SUPPORTED_100baseT_Half))
return -EINVAL;
- if (cmd->duplex == DUPLEX_FULL &&
- (features & SUPPORTED_100baseT_Full) == 0)
+ if (cmd->duplex == DUPLEX_FULL
+ && !(f & SUPPORTED_100baseT_Full))
return -EINVAL;
break;
case SPEED_1000:
- if (cmd->duplex == DUPLEX_HALF &&
- (features & SUPPORTED_1000baseT_Half) == 0)
+ if (cmd->duplex == DUPLEX_HALF
+ && !(f & SUPPORTED_1000baseT_Half))
return -EINVAL;
- if (cmd->duplex == DUPLEX_FULL &&
- (features & SUPPORTED_1000baseT_Full) == 0)
+ if (cmd->duplex == DUPLEX_FULL
+ && !(f & SUPPORTED_1000baseT_Full))
return -EINVAL;
break;
default:
return -EINVAL;
- } else if ((features & SUPPORTED_Autoneg) == 0)
- return -EINVAL;
- spin_lock_irq(&fep->lock);
- emac_start_link(fep, cmd);
- spin_unlock_irq(&fep->lock);
+ }
+
+ local_bh_disable();
+ dev->phy.def->ops->setup_forced(&dev->phy, cmd->speed,
+ cmd->duplex);
+
+ } else {
+ if (!(f & SUPPORTED_Autoneg))
+ return -EINVAL;
+
+ local_bh_disable();
+ dev->phy.def->ops->setup_aneg(&dev->phy,
+ (cmd->advertising & f) |
+ (dev->phy.advertising &
+ (ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause)));
+ }
+ emac_force_link_update(dev);
+ local_bh_enable();
+
return 0;
}
-static void
-emac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
+static void emac_ethtool_get_ringparam(struct net_device *ndev,
+ struct ethtool_ringparam *rp)
{
- struct ocp_enet_private *fep = ndev->priv;
-
- strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
- info->fw_version[0] = '\0';
- sprintf(info->bus_info, "IBM EMAC %d", fep->ocpdev->def->index);
- info->regdump_len = 0;
+ rp->rx_max_pending = rp->rx_pending = NUM_RX_BUFF;
+ rp->tx_max_pending = rp->tx_pending = NUM_TX_BUFF;
}
-static int emac_nway_reset(struct net_device *ndev)
+static void emac_ethtool_get_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *pp)
{
- struct ocp_enet_private *fep = ndev->priv;
+ struct ocp_enet_private *dev = ndev->priv;
+
+ local_bh_disable();
+ if ((dev->phy.features & SUPPORTED_Autoneg) &&
+ (dev->phy.advertising & (ADVERTISED_Pause | ADVERTISED_Asym_Pause)))
+ pp->autoneg = 1;
+
+ if (dev->phy.duplex == DUPLEX_FULL) {
+ if (dev->phy.pause)
+ pp->rx_pause = pp->tx_pause = 1;
+ else if (dev->phy.asym_pause)
+ pp->tx_pause = 1;
+ }
+ local_bh_enable();
+}
- if (!fep->want_autoneg)
- return -EINVAL;
- spin_lock_irq(&fep->lock);
- emac_start_link(fep, NULL);
- spin_unlock_irq(&fep->lock);
- return 0;
+static u32 emac_ethtool_get_rx_csum(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ return dev->tah_dev != 0;
}
-static u32 emac_get_link(struct net_device *ndev)
+static int emac_get_regs_len(struct ocp_enet_private *dev)
{
- return netif_carrier_ok(ndev);
+ return sizeof(struct emac_ethtool_regs_subhdr) + EMAC_ETHTOOL_REGS_SIZE;
}
-static struct ethtool_ops emac_ethtool_ops = {
- .get_settings = emac_get_settings,
- .set_settings = emac_set_settings,
- .get_drvinfo = emac_get_drvinfo,
- .nway_reset = emac_nway_reset,
- .get_link = emac_get_link
-};
+static int emac_ethtool_get_regs_len(struct net_device *ndev)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ return sizeof(struct emac_ethtool_regs_hdr) +
+ emac_get_regs_len(dev) + mal_get_regs_len(dev->mal) +
+ zmii_get_regs_len(dev->zmii_dev) +
+ rgmii_get_regs_len(dev->rgmii_dev) +
+ tah_get_regs_len(dev->tah_dev);
+}
-static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static void *emac_dump_regs(struct ocp_enet_private *dev, void *buf)
{
- struct ocp_enet_private *fep = dev->priv;
- uint16_t *data = (uint16_t *) & rq->ifr_ifru;
+ struct emac_ethtool_regs_subhdr *hdr = buf;
- switch (cmd) {
- case SIOCGMIIPHY:
- data[0] = fep->mii_phy_addr;
- /* Fall through */
- case SIOCGMIIREG:
- data[3] = emac_phy_read(dev, fep->mii_phy_addr, data[1]);
- return 0;
- case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ hdr->version = EMAC_ETHTOOL_REGS_VER;
+ hdr->index = dev->def->index;
+ memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE);
+ return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE);
+}
- emac_phy_write(dev, fep->mii_phy_addr, data[1], data[2]);
- return 0;
- default:
- return -EOPNOTSUPP;
+static void emac_ethtool_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *buf)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ struct emac_ethtool_regs_hdr *hdr = buf;
+
+ hdr->components = 0;
+ buf = hdr + 1;
+
+ local_irq_disable();
+ buf = mal_dump_regs(dev->mal, buf);
+ buf = emac_dump_regs(dev, buf);
+ if (dev->zmii_dev) {
+ hdr->components |= EMAC_ETHTOOL_REGS_ZMII;
+ buf = zmii_dump_regs(dev->zmii_dev, buf);
+ }
+ if (dev->rgmii_dev) {
+ hdr->components |= EMAC_ETHTOOL_REGS_RGMII;
+ buf = rgmii_dump_regs(dev->rgmii_dev, buf);
}
+ if (dev->tah_dev) {
+ hdr->components |= EMAC_ETHTOOL_REGS_TAH;
+ buf = tah_dump_regs(dev->tah_dev, buf);
+ }
+ local_irq_enable();
}
-static int emac_open(struct net_device *dev)
+static int emac_ethtool_nway_reset(struct net_device *ndev)
{
- struct ocp_enet_private *fep = dev->priv;
- int rc;
+ struct ocp_enet_private *dev = ndev->priv;
+ int res = 0;
- spin_lock_irq(&fep->lock);
+ DBG("%d: nway_reset" NL, dev->def->index);
- fep->opened = 1;
- netif_carrier_off(dev);
+ if (dev->phy.address < 0)
+ return -EOPNOTSUPP;
- /* Reset & configure the chip */
- emac_reset_configure(fep);
+ local_bh_disable();
+ if (!dev->phy.autoneg) {
+ res = -EINVAL;
+ goto out;
+ }
- spin_unlock_irq(&fep->lock);
+ dev->phy.def->ops->setup_aneg(&dev->phy, dev->phy.advertising);
+ emac_force_link_update(dev);
- /* Request our interrupt lines */
- rc = request_irq(dev->irq, emac_mac_irq, 0, "IBM EMAC MAC", dev);
- if (rc != 0) {
- printk("dev->irq %d failed\n", dev->irq);
- goto bail;
- }
- /* Kick the chip rx & tx channels into life */
- spin_lock_irq(&fep->lock);
- emac_kick(fep);
- spin_unlock_irq(&fep->lock);
+ out:
+ local_bh_enable();
+ return res;
+}
- netif_start_queue(dev);
- bail:
- return rc;
+static int emac_ethtool_get_stats_count(struct net_device *ndev)
+{
+ return EMAC_ETHTOOL_STATS_COUNT;
}
-static int emac_close(struct net_device *dev)
+static void emac_ethtool_get_strings(struct net_device *ndev, u32 stringset,
+ u8 * buf)
{
- struct ocp_enet_private *fep = dev->priv;
- emac_t *emacp = fep->emacp;
+ if (stringset == ETH_SS_STATS)
+ memcpy(buf, &emac_stats_keys, sizeof(emac_stats_keys));
+}
- /* XXX Stop IRQ emitting here */
- spin_lock_irq(&fep->lock);
- fep->opened = 0;
- mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
- netif_carrier_off(dev);
- netif_stop_queue(dev);
+static void emac_ethtool_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *estats,
+ u64 * tmp_stats)
+{
+ struct ocp_enet_private *dev = ndev->priv;
+ local_irq_disable();
+ memcpy(tmp_stats, &dev->stats, sizeof(dev->stats));
+ tmp_stats += sizeof(dev->stats) / sizeof(u64);
+ memcpy(tmp_stats, &dev->estats, sizeof(dev->estats));
+ local_irq_enable();
+}
- /*
- * Check for a link, some PHYs don't provide a clock if
- * no link is present. Some EMACs will not come out of
- * soft reset without a PHY clock present.
- */
- if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) {
- out_be32(&emacp->em0mr0, EMAC_M0_SRST);
- udelay(10);
+static void emac_ethtool_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct ocp_enet_private *dev = ndev->priv;
- if (emacp->em0mr0 & EMAC_M0_SRST) {
- /*not sure what to do here hopefully it clears before another open */
- printk(KERN_ERR
- "%s: Phy SoftReset didn't clear, no link?\n",
- dev->name);
- }
- }
+ strcpy(info->driver, "ibm_emac");
+ strcpy(info->version, DRV_VERSION);
+ info->fw_version[0] = '\0';
+ sprintf(info->bus_info, "PPC 4xx EMAC %d", dev->def->index);
+ info->n_stats = emac_ethtool_get_stats_count(ndev);
+ info->regdump_len = emac_ethtool_get_regs_len(ndev);
+}
+
+static struct ethtool_ops emac_ethtool_ops = {
+ .get_settings = emac_ethtool_get_settings,
+ .set_settings = emac_ethtool_set_settings,
+ .get_drvinfo = emac_ethtool_get_drvinfo,
- /* Free the irq's */
- free_irq(dev->irq, dev);
+ .get_regs_len = emac_ethtool_get_regs_len,
+ .get_regs = emac_ethtool_get_regs,
- spin_unlock_irq(&fep->lock);
+ .nway_reset = emac_ethtool_nway_reset,
- return 0;
-}
+ .get_ringparam = emac_ethtool_get_ringparam,
+ .get_pauseparam = emac_ethtool_get_pauseparam,
-static void emac_remove(struct ocp_device *ocpdev)
-{
- struct net_device *dev = ocp_get_drvdata(ocpdev);
- struct ocp_enet_private *ep = dev->priv;
-
- /* FIXME: locking, races, ... */
- ep->going_away = 1;
- ocp_set_drvdata(ocpdev, NULL);
- if (ep->rgmii_dev)
- emac_close_rgmii(ep->rgmii_dev);
- if (ep->zmii_dev)
- emac_close_zmii(ep->zmii_dev);
-
- unregister_netdev(dev);
- del_timer_sync(&ep->link_timer);
- mal_unregister_commac(ep->mal, &ep->commac);
- iounmap((void *)ep->emacp);
- kfree(dev);
-}
-
-struct mal_commac_ops emac_commac_ops = {
- .txeob = &emac_txeob_dev,
- .txde = &emac_txde_dev,
- .rxeob = &emac_rxeob_dev,
- .rxde = &emac_rxde_dev,
+ .get_rx_csum = emac_ethtool_get_rx_csum,
+
+ .get_strings = emac_ethtool_get_strings,
+ .get_stats_count = emac_ethtool_get_stats_count,
+ .get_ethtool_stats = emac_ethtool_get_ethtool_stats,
+
+ .get_link = ethtool_op_get_link,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
};
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static int emac_netpoll(struct net_device *ndev)
+static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
{
- emac_rxeob_dev((void *)ndev, 0);
- emac_txeob_dev((void *)ndev, 0);
- return 0;
+ struct ocp_enet_private *dev = ndev->priv;
+ uint16_t *data = (uint16_t *) & rq->ifr_ifru;
+
+ DBG("%d: ioctl %08x" NL, dev->def->index, cmd);
+
+ if (dev->phy.address < 0)
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCDEVPRIVATE:
+ data[0] = dev->phy.address;
+ /* Fall through */
+ case SIOCGMIIREG:
+ case SIOCDEVPRIVATE + 1:
+ data[3] = emac_mdio_read(ndev, dev->phy.address, data[1]);
+ return 0;
+
+ case SIOCSMIIREG:
+ case SIOCDEVPRIVATE + 2:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ emac_mdio_write(ndev, dev->phy.address, data[1], data[2]);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
}
-#endif
-static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
+static int __init emac_probe(struct ocp_device *ocpdev)
{
- int deferred_init = 0;
- int rc = 0, i;
+ struct ocp_func_emac_data *emacdata = ocpdev->def->additions;
struct net_device *ndev;
- struct ocp_enet_private *ep;
- struct ocp_func_emac_data *emacdata;
- int commac_reg = 0;
- u32 phy_map;
+ struct ocp_device *maldev;
+ struct ocp_enet_private *dev;
+ int err, i;
+
+ DBG("%d: probe" NL, ocpdev->def->index);
- emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions;
if (!emacdata) {
printk(KERN_ERR "emac%d: Missing additional data!\n",
ocpdev->def->index);
@@ -1739,273 +1936,312 @@ static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
/* Allocate our net_device structure */
ndev = alloc_etherdev(sizeof(struct ocp_enet_private));
- if (ndev == NULL) {
- printk(KERN_ERR
- "emac%d: Could not allocate ethernet device.\n",
+ if (!ndev) {
+ printk(KERN_ERR "emac%d: could not allocate ethernet device!\n",
ocpdev->def->index);
return -ENOMEM;
}
- ep = ndev->priv;
- ep->ndev = ndev;
- ep->ocpdev = ocpdev;
- ndev->irq = ocpdev->def->irq;
- ep->wol_irq = emacdata->wol_irq;
- if (emacdata->mdio_idx >= 0) {
- if (emacdata->mdio_idx == ocpdev->def->index) {
- /* Set the common MDIO net_device */
- mdio_ndev = ndev;
- deferred_init = 1;
- }
- ep->mdio_dev = mdio_ndev;
- } else {
- ep->mdio_dev = ndev;
- }
+ dev = ndev->priv;
+ dev->ndev = ndev;
+ dev->ldev = &ocpdev->dev;
+ dev->def = ocpdev->def;
+ SET_MODULE_OWNER(ndev);
- ocp_set_drvdata(ocpdev, ndev);
-
- spin_lock_init(&ep->lock);
-
- /* Fill out MAL informations and register commac */
- ep->mal = mal;
- ep->mal_tx_chan = emacdata->mal_tx_chan;
- ep->mal_rx_chan = emacdata->mal_rx_chan;
- ep->commac.ops = &emac_commac_ops;
- ep->commac.dev = ndev;
- ep->commac.tx_chan_mask = MAL_CHAN_MASK(ep->mal_tx_chan);
- ep->commac.rx_chan_mask = MAL_CHAN_MASK(ep->mal_rx_chan);
- rc = mal_register_commac(ep->mal, &ep->commac);
- if (rc != 0)
- goto bail;
- commac_reg = 1;
-
- /* Map our MMIOs */
- ep->emacp = (emac_t *) ioremap(ocpdev->def->paddr, sizeof(emac_t));
-
- /* Check if we need to attach to a ZMII */
- if (emacdata->zmii_idx >= 0) {
- ep->zmii_input = emacdata->zmii_mux;
- ep->zmii_dev =
- ocp_find_device(OCP_ANY_ID, OCP_FUNC_ZMII,
- emacdata->zmii_idx);
- if (ep->zmii_dev == NULL)
- printk(KERN_WARNING
- "emac%d: ZMII %d requested but not found !\n",
- ocpdev->def->index, emacdata->zmii_idx);
- else if ((rc =
- emac_init_zmii(ep->zmii_dev, ep->zmii_input,
- emacdata->phy_mode)) != 0)
- goto bail;
+ /* Find MAL device we are connected to */
+ maldev =
+ ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_MAL, emacdata->mal_idx);
+ if (!maldev) {
+ printk(KERN_ERR "emac%d: unknown mal%d device!\n",
+ dev->def->index, emacdata->mal_idx);
+ err = -ENODEV;
+ goto out;
+ }
+ dev->mal = ocp_get_drvdata(maldev);
+ if (!dev->mal) {
+ printk(KERN_ERR "emac%d: mal%d hasn't been initialized yet!\n",
+ dev->def->index, emacdata->mal_idx);
+ err = -ENODEV;
+ goto out;
}
- /* Check if we need to attach to a RGMII */
- if (emacdata->rgmii_idx >= 0) {
- ep->rgmii_input = emacdata->rgmii_mux;
- ep->rgmii_dev =
- ocp_find_device(OCP_ANY_ID, OCP_FUNC_RGMII,
- emacdata->rgmii_idx);
- if (ep->rgmii_dev == NULL)
- printk(KERN_WARNING
- "emac%d: RGMII %d requested but not found !\n",
- ocpdev->def->index, emacdata->rgmii_idx);
- else if ((rc =
- emac_init_rgmii(ep->rgmii_dev, ep->rgmii_input,
- emacdata->phy_mode)) != 0)
- goto bail;
+ /* Register with MAL */
+ dev->commac.ops = &emac_commac_ops;
+ dev->commac.dev = dev;
+ dev->commac.tx_chan_mask = MAL_CHAN_MASK(emacdata->mal_tx_chan);
+ dev->commac.rx_chan_mask = MAL_CHAN_MASK(emacdata->mal_rx_chan);
+ err = mal_register_commac(dev->mal, &dev->commac);
+ if (err) {
+ printk(KERN_ERR "emac%d: failed to register with mal%d!\n",
+ dev->def->index, emacdata->mal_idx);
+ goto out;
+ }
+ dev->rx_skb_size = emac_rx_skb_size(ndev->mtu);
+ dev->rx_sync_size = emac_rx_sync_size(ndev->mtu);
+
+ /* Get pointers to BD rings */
+ dev->tx_desc =
+ dev->mal->bd_virt + mal_tx_bd_offset(dev->mal,
+ emacdata->mal_tx_chan);
+ dev->rx_desc =
+ dev->mal->bd_virt + mal_rx_bd_offset(dev->mal,
+ emacdata->mal_rx_chan);
+
+ DBG("%d: tx_desc %p" NL, ocpdev->def->index, dev->tx_desc);
+ DBG("%d: rx_desc %p" NL, ocpdev->def->index, dev->rx_desc);
+
+ /* Clean rings */
+ memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor));
+ memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor));
+
+ /* If we depend on another EMAC for MDIO, check whether it was probed already */
+ if (emacdata->mdio_idx >= 0 && emacdata->mdio_idx != ocpdev->def->index) {
+ struct ocp_device *mdiodev =
+ ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC,
+ emacdata->mdio_idx);
+ if (!mdiodev) {
+ printk(KERN_ERR "emac%d: unknown emac%d device!\n",
+ dev->def->index, emacdata->mdio_idx);
+ err = -ENODEV;
+ goto out2;
+ }
+ dev->mdio_dev = ocp_get_drvdata(mdiodev);
+ if (!dev->mdio_dev) {
+ printk(KERN_ERR
+ "emac%d: emac%d hasn't been initialized yet!\n",
+ dev->def->index, emacdata->mdio_idx);
+ err = -ENODEV;
+ goto out2;
+ }
}
- /* Check if we need to attach to a TAH */
- if (emacdata->tah_idx >= 0) {
- ep->tah_dev =
- ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
- emacdata->tah_idx);
- if (ep->tah_dev == NULL)
- printk(KERN_WARNING
- "emac%d: TAH %d requested but not found !\n",
- ocpdev->def->index, emacdata->tah_idx);
- else if ((rc = emac_init_tah(ep)) != 0)
- goto bail;
+ /* Attach to ZMII, if needed */
+ if ((err = zmii_attach(dev)) != 0)
+ goto out2;
+
+ /* Attach to RGMII, if needed */
+ if ((err = rgmii_attach(dev)) != 0)
+ goto out3;
+
+ /* Attach to TAH, if needed */
+ if ((err = tah_attach(dev)) != 0)
+ goto out4;
+
+ /* Map EMAC regs */
+ dev->emacp =
+ (struct emac_regs *)ioremap(dev->def->paddr,
+ sizeof(struct emac_regs));
+ if (!dev->emacp) {
+ printk(KERN_ERR "emac%d: could not ioremap device registers!\n",
+ dev->def->index);
+ err = -ENOMEM;
+ goto out5;
}
- if (deferred_init) {
- if (!list_empty(&emac_init_list)) {
- struct list_head *entry;
- struct emac_def_dev *ddev;
+ /* Fill in MAC address */
+ for (i = 0; i < 6; ++i)
+ ndev->dev_addr[i] = emacdata->mac_addr[i];
- list_for_each(entry, &emac_init_list) {
- ddev =
- list_entry(entry, struct emac_def_dev,
- link);
- emac_init_device(ddev->ocpdev, ddev->mal);
- }
+ /* Set some link defaults before we can find out real parameters */
+ dev->phy.speed = SPEED_100;
+ dev->phy.duplex = DUPLEX_FULL;
+ dev->phy.autoneg = AUTONEG_DISABLE;
+ dev->phy.pause = dev->phy.asym_pause = 0;
+ init_timer(&dev->link_timer);
+ dev->link_timer.function = emac_link_timer;
+ dev->link_timer.data = (unsigned long)dev;
+
+ /* Find PHY if any */
+ dev->phy.dev = ndev;
+ dev->phy.mode = emacdata->phy_mode;
+ if (emacdata->phy_map != 0xffffffff) {
+ u32 phy_map = emacdata->phy_map | busy_phy_map;
+ u32 adv;
+
+ DBG("%d: PHY maps %08x %08x" NL, dev->def->index,
+ emacdata->phy_map, busy_phy_map);
+
+ EMAC_RX_CLK_TX(dev->def->index);
+
+ dev->phy.mdio_read = emac_mdio_read;
+ dev->phy.mdio_write = emac_mdio_write;
+
+ /* Configure EMAC with defaults so we can at least use MDIO
+ * This is needed mostly for 440GX
+ */
+ if (emac_phy_gpcs(dev->phy.mode)) {
+ /* XXX
+ * Make GPCS PHY address equal to EMAC index.
+ * We probably should take into account busy_phy_map
+ * and/or phy_map here.
+ */
+ dev->phy.address = dev->def->index;
}
- }
+
+ emac_configure(dev);
+
+ for (i = 0; i < 0x20; phy_map >>= 1, ++i)
+ if (!(phy_map & 1)) {
+ int r;
+ busy_phy_map |= 1 << i;
- /* Init link monitoring timer */
- init_timer(&ep->link_timer);
- ep->link_timer.function = emac_link_timer;
- ep->link_timer.data = (unsigned long)ep;
- ep->timer_ticks = 0;
-
- /* Fill up the mii_phy structure */
- ep->phy_mii.dev = ndev;
- ep->phy_mii.mdio_read = emac_phy_read;
- ep->phy_mii.mdio_write = emac_phy_write;
- ep->phy_mii.mode = emacdata->phy_mode;
-
- /* Find PHY */
- phy_map = emacdata->phy_map | busy_phy_map;
- for (i = 0; i <= 0x1f; i++, phy_map >>= 1) {
- if ((phy_map & 0x1) == 0) {
- int val = emac_phy_read(ndev, i, MII_BMCR);
- if (val != 0xffff && val != -1)
- break;
+ /* Quick check if there is a PHY at the address */
+ r = emac_mdio_read(dev->ndev, i, MII_BMCR);
+ if (r == 0xffff || r < 0)
+ continue;
+ if (!mii_phy_probe(&dev->phy, i))
+ break;
+ }
+ if (i == 0x20) {
+ printk(KERN_WARNING "emac%d: can't find PHY!\n",
+ dev->def->index);
+ goto out6;
}
- }
- if (i == 0x20) {
- printk(KERN_WARNING "emac%d: Can't find PHY.\n",
- ocpdev->def->index);
- rc = -ENODEV;
- goto bail;
- }
- busy_phy_map |= 1 << i;
- ep->mii_phy_addr = i;
- rc = mii_phy_probe(&ep->phy_mii, i);
- if (rc) {
- printk(KERN_WARNING "emac%d: Failed to probe PHY type.\n",
- ocpdev->def->index);
- rc = -ENODEV;
- goto bail;
- }
- /* Setup initial PHY config & startup aneg */
- if (ep->phy_mii.def->ops->init)
- ep->phy_mii.def->ops->init(&ep->phy_mii);
- netif_carrier_off(ndev);
- if (ep->phy_mii.def->features & SUPPORTED_Autoneg)
- ep->want_autoneg = 1;
- emac_start_link(ep, NULL);
+ /* Init PHY */
+ if (dev->phy.def->ops->init)
+ dev->phy.def->ops->init(&dev->phy);
+
+ /* Disable any PHY features not supported by the platform */
+ dev->phy.def->features &= ~emacdata->phy_feat_exc;
+
+ /* Setup initial link parameters */
+ if (dev->phy.features & SUPPORTED_Autoneg) {
+ adv = dev->phy.features;
+#if !defined(CONFIG_40x)
+ adv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+#endif
+ /* Restart autonegotiation */
+ dev->phy.def->ops->setup_aneg(&dev->phy, adv);
+ } else {
+ u32 f = dev->phy.def->features;
+ int speed = SPEED_10, fd = DUPLEX_HALF;
+
+ /* Select highest supported speed/duplex */
+ if (f & SUPPORTED_1000baseT_Full) {
+ speed = SPEED_1000;
+ fd = DUPLEX_FULL;
+ } else if (f & SUPPORTED_1000baseT_Half)
+ speed = SPEED_1000;
+ else if (f & SUPPORTED_100baseT_Full) {
+ speed = SPEED_100;
+ fd = DUPLEX_FULL;
+ } else if (f & SUPPORTED_100baseT_Half)
+ speed = SPEED_100;
+ else if (f & SUPPORTED_10baseT_Full)
+ fd = DUPLEX_FULL;
+
+ /* Force link parameters */
+ dev->phy.def->ops->setup_forced(&dev->phy, speed, fd);
+ }
+ } else {
+ emac_reset(dev);
- /* read the MAC Address */
- for (i = 0; i < 6; i++)
- ndev->dev_addr[i] = emacdata->mac_addr[i];
+ /* PHY-less configuration.
+ * XXX I probably should move these settings to emacdata
+ */
+ dev->phy.address = -1;
+ dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
+ dev->phy.pause = 1;
+ }
/* Fill in the driver function table */
ndev->open = &emac_open;
- ndev->hard_start_xmit = &emac_start_xmit;
+ if (dev->tah_dev) {
+ ndev->hard_start_xmit = &emac_start_xmit_sg;
+ ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ } else
+ ndev->hard_start_xmit = &emac_start_xmit;
+ ndev->tx_timeout = &emac_full_tx_reset;
+ ndev->watchdog_timeo = 5 * HZ;
ndev->stop = &emac_close;
ndev->get_stats = &emac_stats;
- if (emacdata->jumbo)
- ndev->change_mtu = &emac_change_mtu;
- ndev->set_mac_address = &emac_set_mac_address;
ndev->set_multicast_list = &emac_set_multicast_list;
ndev->do_ioctl = &emac_ioctl;
+ if (emac_phy_supports_gige(emacdata->phy_mode)) {
+ ndev->change_mtu = &emac_change_mtu;
+ dev->commac.ops = &emac_commac_sg_ops;
+ }
SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
- if (emacdata->tah_idx >= 0)
- ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- ndev->poll_controller = emac_netpoll;
-#endif
- SET_MODULE_OWNER(ndev);
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+
+ err = register_netdev(ndev);
+ if (err) {
+ printk(KERN_ERR "emac%d: failed to register net device (%d)!\n",
+ dev->def->index, err);
+ goto out6;
+ }
- rc = register_netdev(ndev);
- if (rc != 0)
- goto bail;
+ ocp_set_drvdata(ocpdev, dev);
- printk("%s: IBM emac, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->name,
+ printk("%s: emac%d, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->name, dev->def->index,
ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
- printk(KERN_INFO "%s: Found %s PHY (0x%02x)\n",
- ndev->name, ep->phy_mii.def->name, ep->mii_phy_addr);
- bail:
- if (rc && commac_reg)
- mal_unregister_commac(ep->mal, &ep->commac);
- if (rc && ndev)
- kfree(ndev);
+ if (dev->phy.address >= 0)
+ printk("%s: found %s PHY (0x%02x)\n", ndev->name,
+ dev->phy.def->name, dev->phy.address);
- return rc;
-}
-
-static int emac_probe(struct ocp_device *ocpdev)
-{
- struct ocp_device *maldev;
- struct ibm_ocp_mal *mal;
- struct ocp_func_emac_data *emacdata;
-
- emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions;
- if (emacdata == NULL) {
- printk(KERN_ERR "emac%d: Missing additional datas !\n",
- ocpdev->def->index);
- return -ENODEV;
- }
-
- /* Get the MAL device */
- maldev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_MAL, emacdata->mal_idx);
- if (maldev == NULL) {
- printk("No maldev\n");
- return -ENODEV;
- }
- /*
- * Get MAL driver data, it must be here due to link order.
- * When the driver is modularized, symbol dependencies will
- * ensure the MAL driver is already present if built as a
- * module.
- */
- mal = (struct ibm_ocp_mal *)ocp_get_drvdata(maldev);
- if (mal == NULL) {
- printk("No maldrv\n");
- return -ENODEV;
- }
-
- /* If we depend on another EMAC for MDIO, wait for it to show up */
- if (emacdata->mdio_idx >= 0 &&
- (emacdata->mdio_idx != ocpdev->def->index) && !mdio_ndev) {
- struct emac_def_dev *ddev;
- /* Add this index to the deferred init table */
- ddev = kmalloc(sizeof(struct emac_def_dev), GFP_KERNEL);
- ddev->ocpdev = ocpdev;
- ddev->mal = mal;
- list_add_tail(&ddev->link, &emac_init_list);
- } else {
- emac_init_device(ocpdev, mal);
- }
+ emac_dbg_register(dev->def->index, dev);
return 0;
+ out6:
+ iounmap((void *)dev->emacp);
+ out5:
+ tah_fini(dev->tah_dev);
+ out4:
+ rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
+ out3:
+ zmii_fini(dev->zmii_dev, dev->zmii_input);
+ out2:
+ mal_unregister_commac(dev->mal, &dev->commac);
+ out:
+ kfree(ndev);
+ return err;
}
-/* Structure for a device driver */
static struct ocp_device_id emac_ids[] = {
- {.vendor = OCP_ANY_ID,.function = OCP_FUNC_EMAC},
- {.vendor = OCP_VENDOR_INVALID}
+ { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_EMAC },
+ { .vendor = OCP_VENDOR_INVALID}
};
static struct ocp_driver emac_driver = {
.name = "emac",
.id_table = emac_ids,
-
.probe = emac_probe,
.remove = emac_remove,
};
static int __init emac_init(void)
{
- printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n");
- printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n");
+ printk(KERN_INFO DRV_DESC ", version " DRV_VERSION "\n");
+
+ DBG(": init" NL);
- if (skb_res > 2) {
- printk(KERN_WARNING "Invalid skb_res: %d, cropping to 2\n",
- skb_res);
- skb_res = 2;
+ if (mal_init())
+ return -ENODEV;
+
+ EMAC_CLK_INTERNAL;
+ if (ocp_register_driver(&emac_driver)) {
+ EMAC_CLK_EXTERNAL;
+ ocp_unregister_driver(&emac_driver);
+ mal_exit();
+ return -ENODEV;
}
+ EMAC_CLK_EXTERNAL;
- return ocp_register_driver(&emac_driver);
+ emac_init_debug();
+ return 0;
}
static void __exit emac_exit(void)
{
+ DBG(": exit" NL);
ocp_unregister_driver(&emac_driver);
+ mal_exit();
+ emac_fini_debug();
}
module_init(emac_init);
diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
index 97e6e1ea8c89..e9b44d030ac3 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.h
+++ b/drivers/net/ibm_emac/ibm_emac_core.h
@@ -1,146 +1,221 @@
/*
- * ibm_emac_core.h
+ * drivers/net/ibm_emac/ibm_emac_core.h
*
- * Ethernet driver for the built in ethernet on the IBM 405 PowerPC
- * processor.
+ * Driver for PowerPC 4xx on-chip ethernet controller.
*
- * Armin Kuster akuster@mvista.com
- * Sept, 2001
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Orignial driver
- * Johnnie Peters
- * jpeters@mvista.com
- *
- * Copyright 2000 MontaVista Softare Inc.
+ * Based on original work by
+ * Armin Kuster <akuster@mvista.com>
+ * Johnnie Peters <jpeters@mvista.com>
+ * Copyright 2000, 2001 MontaVista Softare Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
*/
+#ifndef __IBM_EMAC_CORE_H_
+#define __IBM_EMAC_CORE_H_
-#ifndef _IBM_EMAC_CORE_H_
-#define _IBM_EMAC_CORE_H_
-
+#include <linux/config.h>
#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
#include <asm/ocp.h>
-#include <asm/mmu.h> /* For phys_addr_t */
#include "ibm_emac.h"
#include "ibm_emac_phy.h"
-#include "ibm_emac_rgmii.h"
#include "ibm_emac_zmii.h"
+#include "ibm_emac_rgmii.h"
#include "ibm_emac_mal.h"
#include "ibm_emac_tah.h"
-#ifndef CONFIG_IBM_EMAC_TXB
-#define NUM_TX_BUFF 64
-#define NUM_RX_BUFF 64
-#else
-#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
-#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
-#endif
+#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
+#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
-/* This does 16 byte alignment, exactly what we need.
- * The packet length includes FCS, but we don't want to
- * include that when passing upstream as it messes up
- * bridging applications.
- */
-#ifndef CONFIG_IBM_EMAC_SKBRES
-#define SKB_RES 2
-#else
-#define SKB_RES CONFIG_IBM_EMAC_SKBRES
+/* Simple sanity check */
+#if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
+#error Invalid number of buffer descriptors (greater than 256)
#endif
-/* Note about alignement. alloc_skb() returns a cache line
- * aligned buffer. However, dev_alloc_skb() will add 16 more
- * bytes and "reserve" them, so our buffer will actually end
- * on a half cache line. What we do is to use directly
- * alloc_skb, allocate 16 more bytes to match the total amount
- * allocated by dev_alloc_skb(), but we don't reserve.
+// XXX
+#define EMAC_MIN_MTU 46
+#define EMAC_MAX_MTU 9000
+
+/* Maximum L2 header length (VLAN tagged, no FCS) */
+#define EMAC_MTU_OVERHEAD (6 * 2 + 2 + 4)
+
+/* RX BD size for the given MTU */
+static inline int emac_rx_size(int mtu)
+{
+ if (mtu > ETH_DATA_LEN)
+ return MAL_MAX_RX_SIZE;
+ else
+ return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD);
+}
+
+#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment())
+
+#define EMAC_RX_SKB_HEADROOM \
+ EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
+
+/* Size of RX skb for the given MTU */
+static inline int emac_rx_skb_size(int mtu)
+{
+ int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu));
+ return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM;
+}
+
+/* RX DMA sync size */
+static inline int emac_rx_sync_size(int mtu)
+{
+ return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2);
+}
+
+/* Driver statistcs is split into two parts to make it more cache friendly:
+ * - normal statistics (packet count, etc)
+ * - error statistics
+ *
+ * When statistics is requested by ethtool, these parts are concatenated,
+ * normal one goes first.
+ *
+ * Please, keep these structures in sync with emac_stats_keys.
*/
-#define MAX_NUM_BUF_DESC 255
-#define DESC_BUF_SIZE 4080 /* max 4096-16 */
-#define DESC_BUF_SIZE_REG (DESC_BUF_SIZE / 16)
-
-/* Transmitter timeout. */
-#define TX_TIMEOUT (2*HZ)
-
-/* MDIO latency delay */
-#define MDIO_DELAY 250
-
-/* Power managment shift registers */
-#define IBM_CPM_EMMII 0 /* Shift value for MII */
-#define IBM_CPM_EMRX 1 /* Shift value for recv */
-#define IBM_CPM_EMTX 2 /* Shift value for MAC */
-#define IBM_CPM_EMAC(x) (((x)>>IBM_CPM_EMMII) | ((x)>>IBM_CPM_EMRX) | ((x)>>IBM_CPM_EMTX))
-
-#define ENET_HEADER_SIZE 14
-#define ENET_FCS_SIZE 4
-#define ENET_DEF_MTU_SIZE 1500
-#define ENET_DEF_BUF_SIZE (ENET_DEF_MTU_SIZE + ENET_HEADER_SIZE + ENET_FCS_SIZE)
-#define EMAC_MIN_FRAME 64
-#define EMAC_MAX_FRAME 9018
-#define EMAC_MIN_MTU (EMAC_MIN_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
-#define EMAC_MAX_MTU (EMAC_MAX_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
-
-#ifdef CONFIG_IBM_EMAC_ERRMSG
-void emac_serr_dump_0(struct net_device *dev);
-void emac_serr_dump_1(struct net_device *dev);
-void emac_err_dump(struct net_device *dev, int em0isr);
-void emac_phy_dump(struct net_device *);
-void emac_desc_dump(struct net_device *);
-void emac_mac_dump(struct net_device *);
-void emac_mal_dump(struct net_device *);
-#else
-#define emac_serr_dump_0(dev) do { } while (0)
-#define emac_serr_dump_1(dev) do { } while (0)
-#define emac_err_dump(dev,x) do { } while (0)
-#define emac_phy_dump(dev) do { } while (0)
-#define emac_desc_dump(dev) do { } while (0)
-#define emac_mac_dump(dev) do { } while (0)
-#define emac_mal_dump(dev) do { } while (0)
-#endif
+
+/* Normal TX/RX Statistics */
+struct ibm_emac_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ u64 rx_packets_csum;
+ u64 tx_packets_csum;
+};
+
+/* Error statistics */
+struct ibm_emac_error_stats {
+ u64 tx_undo;
+
+ /* Software RX Errors */
+ u64 rx_dropped_stack;
+ u64 rx_dropped_oom;
+ u64 rx_dropped_error;
+ u64 rx_dropped_resize;
+ u64 rx_dropped_mtu;
+ u64 rx_stopped;
+ /* BD reported RX errors */
+ u64 rx_bd_errors;
+ u64 rx_bd_overrun;
+ u64 rx_bd_bad_packet;
+ u64 rx_bd_runt_packet;
+ u64 rx_bd_short_event;
+ u64 rx_bd_alignment_error;
+ u64 rx_bd_bad_fcs;
+ u64 rx_bd_packet_too_long;
+ u64 rx_bd_out_of_range;
+ u64 rx_bd_in_range;
+ /* EMAC IRQ reported RX errors */
+ u64 rx_parity;
+ u64 rx_fifo_overrun;
+ u64 rx_overrun;
+ u64 rx_bad_packet;
+ u64 rx_runt_packet;
+ u64 rx_short_event;
+ u64 rx_alignment_error;
+ u64 rx_bad_fcs;
+ u64 rx_packet_too_long;
+ u64 rx_out_of_range;
+ u64 rx_in_range;
+
+ /* Software TX Errors */
+ u64 tx_dropped;
+ /* BD reported TX errors */
+ u64 tx_bd_errors;
+ u64 tx_bd_bad_fcs;
+ u64 tx_bd_carrier_loss;
+ u64 tx_bd_excessive_deferral;
+ u64 tx_bd_excessive_collisions;
+ u64 tx_bd_late_collision;
+ u64 tx_bd_multple_collisions;
+ u64 tx_bd_single_collision;
+ u64 tx_bd_underrun;
+ u64 tx_bd_sqe;
+ /* EMAC IRQ reported TX errors */
+ u64 tx_parity;
+ u64 tx_underrun;
+ u64 tx_sqe;
+ u64 tx_errors;
+};
+
+#define EMAC_ETHTOOL_STATS_COUNT ((sizeof(struct ibm_emac_stats) + \
+ sizeof(struct ibm_emac_error_stats)) \
+ / sizeof(u64))
struct ocp_enet_private {
- struct sk_buff *tx_skb[NUM_TX_BUFF];
- struct sk_buff *rx_skb[NUM_RX_BUFF];
- struct mal_descriptor *tx_desc;
- struct mal_descriptor *rx_desc;
- struct mal_descriptor *rx_dirty;
- struct net_device_stats stats;
- int tx_cnt;
- int rx_slot;
- int dirty_rx;
- int tx_slot;
- int ack_slot;
- int rx_buffer_size;
-
- struct mii_phy phy_mii;
- int mii_phy_addr;
- int want_autoneg;
- int timer_ticks;
- struct timer_list link_timer;
- struct net_device *mdio_dev;
-
- struct ocp_device *rgmii_dev;
- int rgmii_input;
-
- struct ocp_device *zmii_dev;
- int zmii_input;
-
- struct ibm_ocp_mal *mal;
- int mal_tx_chan, mal_rx_chan;
- struct mal_commac commac;
-
- struct ocp_device *tah_dev;
-
- int opened;
- int going_away;
- int wol_irq;
- emac_t *emacp;
- struct ocp_device *ocpdev;
- struct net_device *ndev;
- spinlock_t lock;
+ struct net_device *ndev; /* 0 */
+ struct emac_regs *emacp;
+
+ struct mal_descriptor *tx_desc;
+ int tx_cnt;
+ int tx_slot;
+ int ack_slot;
+
+ struct mal_descriptor *rx_desc;
+ int rx_slot;
+ struct sk_buff *rx_sg_skb; /* 1 */
+ int rx_skb_size;
+ int rx_sync_size;
+
+ struct ibm_emac_stats stats;
+ struct ocp_device *tah_dev;
+
+ struct ibm_ocp_mal *mal;
+ struct mal_commac commac;
+
+ struct sk_buff *tx_skb[NUM_TX_BUFF];
+ struct sk_buff *rx_skb[NUM_RX_BUFF];
+
+ struct ocp_device *zmii_dev;
+ int zmii_input;
+ struct ocp_enet_private *mdio_dev;
+ struct ocp_device *rgmii_dev;
+ int rgmii_input;
+
+ struct ocp_def *def;
+
+ struct mii_phy phy;
+ struct timer_list link_timer;
+ int reset_failed;
+
+ struct ibm_emac_error_stats estats;
+ struct net_device_stats nstats;
+
+ struct device* ldev;
};
-#endif /* _IBM_EMAC_CORE_H_ */
+
+/* Ethtool get_regs complex data.
+ * We want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH
+ * when available.
+ *
+ * Returned BLOB consists of the ibm_emac_ethtool_regs_hdr,
+ * MAL registers, EMAC registers and optional ZMII, RGMII, TAH registers.
+ * Each register component is preceded with emac_ethtool_regs_subhdr.
+ * Order of the optional headers follows their relative bit posititions
+ * in emac_ethtool_regs_hdr.components
+ */
+#define EMAC_ETHTOOL_REGS_ZMII 0x00000001
+#define EMAC_ETHTOOL_REGS_RGMII 0x00000002
+#define EMAC_ETHTOOL_REGS_TAH 0x00000004
+
+struct emac_ethtool_regs_hdr {
+ u32 components;
+};
+
+struct emac_ethtool_regs_subhdr {
+ u32 version;
+ u32 index;
+};
+
+#endif /* __IBM_EMAC_CORE_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.c b/drivers/net/ibm_emac/ibm_emac_debug.c
index c8512046cf84..75d3b8639041 100644
--- a/drivers/net/ibm_emac/ibm_emac_debug.c
+++ b/drivers/net/ibm_emac/ibm_emac_debug.c
@@ -1,224 +1,213 @@
/*
- * ibm_ocp_debug.c
+ * drivers/net/ibm_emac/ibm_emac_debug.c
*
- * This has all the debug routines that where in *_enet.c
+ * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
- * Armin Kuster akuster@mvista.com
- * April , 2002
- *
- * Copyright 2002 MontaVista Softare Inc.
+ * Copyright (c) 2004, 2005 Zultys Technologies
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.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.
+ *
*/
-
#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/sysrq.h>
#include <asm/io.h>
-#include "ibm_ocp_mal.h"
-#include "ibm_ocp_zmii.h"
-#include "ibm_ocp_enet.h"
-extern int emac_phy_read(struct net_device *dev, int mii_id, int reg);
+#include "ibm_emac_core.h"
+
+static void emac_desc_dump(int idx, struct ocp_enet_private *p)
+{
+ int i;
+ printk("** EMAC%d TX BDs **\n"
+ " tx_cnt = %d tx_slot = %d ack_slot = %d\n",
+ idx, p->tx_cnt, p->tx_slot, p->ack_slot);
+ for (i = 0; i < NUM_TX_BUFF / 2; ++i)
+ printk
+ ("bd[%2d] 0x%08x %c 0x%04x %4u - bd[%2d] 0x%08x %c 0x%04x %4u\n",
+ i, p->tx_desc[i].data_ptr, p->tx_skb[i] ? 'V' : ' ',
+ p->tx_desc[i].ctrl, p->tx_desc[i].data_len,
+ NUM_TX_BUFF / 2 + i,
+ p->tx_desc[NUM_TX_BUFF / 2 + i].data_ptr,
+ p->tx_skb[NUM_TX_BUFF / 2 + i] ? 'V' : ' ',
+ p->tx_desc[NUM_TX_BUFF / 2 + i].ctrl,
+ p->tx_desc[NUM_TX_BUFF / 2 + i].data_len);
+
+ printk("** EMAC%d RX BDs **\n"
+ " rx_slot = %d rx_stopped = %d rx_skb_size = %d rx_sync_size = %d\n"
+ " rx_sg_skb = 0x%p\n",
+ idx, p->rx_slot, p->commac.rx_stopped, p->rx_skb_size,
+ p->rx_sync_size, p->rx_sg_skb);
+ for (i = 0; i < NUM_RX_BUFF / 2; ++i)
+ printk
+ ("bd[%2d] 0x%08x %c 0x%04x %4u - bd[%2d] 0x%08x %c 0x%04x %4u\n",
+ i, p->rx_desc[i].data_ptr, p->rx_skb[i] ? 'V' : ' ',
+ p->rx_desc[i].ctrl, p->rx_desc[i].data_len,
+ NUM_RX_BUFF / 2 + i,
+ p->rx_desc[NUM_RX_BUFF / 2 + i].data_ptr,
+ p->rx_skb[NUM_RX_BUFF / 2 + i] ? 'V' : ' ',
+ p->rx_desc[NUM_RX_BUFF / 2 + i].ctrl,
+ p->rx_desc[NUM_RX_BUFF / 2 + i].data_len);
+}
+
+static void emac_mac_dump(int idx, struct ocp_enet_private *dev)
+{
+ struct emac_regs *p = dev->emacp;
+
+ printk("** EMAC%d registers **\n"
+ "MR0 = 0x%08x MR1 = 0x%08x TMR0 = 0x%08x TMR1 = 0x%08x\n"
+ "RMR = 0x%08x ISR = 0x%08x ISER = 0x%08x\n"
+ "IAR = %04x%08x VTPID = 0x%04x VTCI = 0x%04x\n"
+ "IAHT: 0x%04x 0x%04x 0x%04x 0x%04x "
+ "GAHT: 0x%04x 0x%04x 0x%04x 0x%04x\n"
+ "LSA = %04x%08x IPGVR = 0x%04x\n"
+ "STACR = 0x%08x TRTR = 0x%08x RWMR = 0x%08x\n"
+ "OCTX = 0x%08x OCRX = 0x%08x IPCR = 0x%08x\n",
+ idx, in_be32(&p->mr0), in_be32(&p->mr1),
+ in_be32(&p->tmr0), in_be32(&p->tmr1),
+ in_be32(&p->rmr), in_be32(&p->isr), in_be32(&p->iser),
+ in_be32(&p->iahr), in_be32(&p->ialr), in_be32(&p->vtpid),
+ in_be32(&p->vtci),
+ in_be32(&p->iaht1), in_be32(&p->iaht2), in_be32(&p->iaht3),
+ in_be32(&p->iaht4),
+ in_be32(&p->gaht1), in_be32(&p->gaht2), in_be32(&p->gaht3),
+ in_be32(&p->gaht4),
+ in_be32(&p->lsah), in_be32(&p->lsal), in_be32(&p->ipgvr),
+ in_be32(&p->stacr), in_be32(&p->trtr), in_be32(&p->rwmr),
+ in_be32(&p->octx), in_be32(&p->ocrx), in_be32(&p->ipcr)
+ );
+
+ emac_desc_dump(idx, dev);
+}
+
+static void emac_mal_dump(struct ibm_ocp_mal *mal)
+{
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+ int i;
+
+ printk("** MAL%d Registers **\n"
+ "CFG = 0x%08x ESR = 0x%08x IER = 0x%08x\n"
+ "TX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n"
+ "RX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n",
+ mal->def->index,
+ get_mal_dcrn(mal, MAL_CFG), get_mal_dcrn(mal, MAL_ESR),
+ get_mal_dcrn(mal, MAL_IER),
+ get_mal_dcrn(mal, MAL_TXCASR), get_mal_dcrn(mal, MAL_TXCARR),
+ get_mal_dcrn(mal, MAL_TXEOBISR), get_mal_dcrn(mal, MAL_TXDEIR),
+ get_mal_dcrn(mal, MAL_RXCASR), get_mal_dcrn(mal, MAL_RXCARR),
+ get_mal_dcrn(mal, MAL_RXEOBISR), get_mal_dcrn(mal, MAL_RXDEIR)
+ );
+
+ printk("TX|");
+ for (i = 0; i < maldata->num_tx_chans; ++i) {
+ if (i && !(i % 4))
+ printk("\n ");
+ printk("CTP%d = 0x%08x ", i, get_mal_dcrn(mal, MAL_TXCTPR(i)));
+ }
+ printk("\nRX|");
+ for (i = 0; i < maldata->num_rx_chans; ++i) {
+ if (i && !(i % 4))
+ printk("\n ");
+ printk("CTP%d = 0x%08x ", i, get_mal_dcrn(mal, MAL_RXCTPR(i)));
+ }
+ printk("\n ");
+ for (i = 0; i < maldata->num_rx_chans; ++i) {
+ u32 r = get_mal_dcrn(mal, MAL_RCBS(i));
+ if (i && !(i % 3))
+ printk("\n ");
+ printk("RCBS%d = 0x%08x (%d) ", i, r, r * 16);
+ }
+ printk("\n");
+}
+
+static struct ocp_enet_private *__emacs[4];
+static struct ibm_ocp_mal *__mals[1];
-void emac_phy_dump(struct net_device *dev)
+void emac_dbg_register(int idx, struct ocp_enet_private *dev)
{
- struct ocp_enet_private *fep = dev->priv;
- unsigned long i;
- uint data;
-
- printk(KERN_DEBUG " Prepare for Phy dump....\n");
- for (i = 0; i < 0x1A; i++) {
- data = emac_phy_read(dev, fep->mii_phy_addr, i);
- printk(KERN_DEBUG "Phy reg 0x%lx ==> %4x\n", i, data);
- if (i == 0x07)
- i = 0x0f;
+ unsigned long flags;
+
+ if (idx >= sizeof(__emacs) / sizeof(__emacs[0])) {
+ printk(KERN_WARNING
+ "invalid index %d when registering EMAC for debugging\n",
+ idx);
+ return;
}
+
+ local_irq_save(flags);
+ __emacs[idx] = dev;
+ local_irq_restore(flags);
}
-void emac_desc_dump(struct net_device *dev)
+void mal_dbg_register(int idx, struct ibm_ocp_mal *mal)
{
- struct ocp_enet_private *fep = dev->priv;
- int curr_slot;
-
- printk(KERN_DEBUG
- "dumping the receive descriptors: current slot is %d\n",
- fep->rx_slot);
- for (curr_slot = 0; curr_slot < NUM_RX_BUFF; curr_slot++) {
- printk(KERN_DEBUG
- "Desc %02d: status 0x%04x, length %3d, addr 0x%x\n",
- curr_slot, fep->rx_desc[curr_slot].ctrl,
- fep->rx_desc[curr_slot].data_len,
- (unsigned int)fep->rx_desc[curr_slot].data_ptr);
+ unsigned long flags;
+
+ if (idx >= sizeof(__mals) / sizeof(__mals[0])) {
+ printk(KERN_WARNING
+ "invalid index %d when registering MAL for debugging\n",
+ idx);
+ return;
}
+
+ local_irq_save(flags);
+ __mals[idx] = mal;
+ local_irq_restore(flags);
}
-void emac_mac_dump(struct net_device *dev)
+void emac_dbg_dump_all(void)
{
- struct ocp_enet_private *fep = dev->priv;
- volatile emac_t *emacp = fep->emacp;
-
- printk(KERN_DEBUG "EMAC DEBUG ********** \n");
- printk(KERN_DEBUG "EMAC_M0 ==> 0x%x\n", in_be32(&emacp->em0mr0));
- printk(KERN_DEBUG "EMAC_M1 ==> 0x%x\n", in_be32(&emacp->em0mr1));
- printk(KERN_DEBUG "EMAC_TXM0==> 0x%x\n", in_be32(&emacp->em0tmr0));
- printk(KERN_DEBUG "EMAC_TXM1==> 0x%x\n", in_be32(&emacp->em0tmr1));
- printk(KERN_DEBUG "EMAC_RXM ==> 0x%x\n", in_be32(&emacp->em0rmr));
- printk(KERN_DEBUG "EMAC_ISR ==> 0x%x\n", in_be32(&emacp->em0isr));
- printk(KERN_DEBUG "EMAC_IER ==> 0x%x\n", in_be32(&emacp->em0iser));
- printk(KERN_DEBUG "EMAC_IAH ==> 0x%x\n", in_be32(&emacp->em0iahr));
- printk(KERN_DEBUG "EMAC_IAL ==> 0x%x\n", in_be32(&emacp->em0ialr));
- printk(KERN_DEBUG "EMAC_VLAN_TPID_REG ==> 0x%x\n",
- in_be32(&emacp->em0vtpid));
+ unsigned int i;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ for (i = 0; i < sizeof(__mals) / sizeof(__mals[0]); ++i)
+ if (__mals[i])
+ emac_mal_dump(__mals[i]);
+
+ for (i = 0; i < sizeof(__emacs) / sizeof(__emacs[0]); ++i)
+ if (__emacs[i])
+ emac_mac_dump(i, __emacs[i]);
+
+ local_irq_restore(flags);
}
-void emac_mal_dump(struct net_device *dev)
+#if defined(CONFIG_MAGIC_SYSRQ)
+static void emac_sysrq_handler(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
{
- struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
-
- printk(KERN_DEBUG " MAL DEBUG ********** \n");
- printk(KERN_DEBUG " MCR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALCR));
- printk(KERN_DEBUG " ESR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALESR));
- printk(KERN_DEBUG " IER ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALIER));
-#ifdef CONFIG_40x
- printk(KERN_DEBUG " DBR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALDBR));
-#endif /* CONFIG_40x */
- printk(KERN_DEBUG " TXCASR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCASR));
- printk(KERN_DEBUG " TXCARR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCARR));
- printk(KERN_DEBUG " TXEOBISR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXEOBISR));
- printk(KERN_DEBUG " TXDEIR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXDEIR));
- printk(KERN_DEBUG " RXCASR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCASR));
- printk(KERN_DEBUG " RXCARR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCARR));
- printk(KERN_DEBUG " RXEOBISR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXEOBISR));
- printk(KERN_DEBUG " RXDEIR ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXDEIR));
- printk(KERN_DEBUG " TXCTP0R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP0R));
- printk(KERN_DEBUG " TXCTP1R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP1R));
- printk(KERN_DEBUG " TXCTP2R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP2R));
- printk(KERN_DEBUG " TXCTP3R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP3R));
- printk(KERN_DEBUG " RXCTP0R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCTP0R));
- printk(KERN_DEBUG " RXCTP1R ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCTP1R));
- printk(KERN_DEBUG " RCBS0 ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRCBS0));
- printk(KERN_DEBUG " RCBS1 ==> 0x%x\n",
- (unsigned int)get_mal_dcrn(mal, DCRN_MALRCBS1));
+ emac_dbg_dump_all();
}
-void emac_serr_dump_0(struct net_device *dev)
+static struct sysrq_key_op emac_sysrq_op = {
+ .handler = emac_sysrq_handler,
+ .help_msg = "emaC",
+ .action_msg = "Show EMAC(s) status",
+};
+
+int __init emac_init_debug(void)
{
- struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
- unsigned long int mal_error, plb_error, plb_addr;
-
- mal_error = get_mal_dcrn(mal, DCRN_MALESR);
- printk(KERN_DEBUG "ppc405_eth_serr: %s channel %ld \n",
- (mal_error & 0x40000000) ? "Receive" :
- "Transmit", (mal_error & 0x3e000000) >> 25);
- printk(KERN_DEBUG " ----- latched error -----\n");
- if (mal_error & MALESR_DE)
- printk(KERN_DEBUG " DE: descriptor error\n");
- if (mal_error & MALESR_OEN)
- printk(KERN_DEBUG " ONE: OPB non-fullword error\n");
- if (mal_error & MALESR_OTE)
- printk(KERN_DEBUG " OTE: OPB timeout error\n");
- if (mal_error & MALESR_OSE)
- printk(KERN_DEBUG " OSE: OPB slave error\n");
-
- if (mal_error & MALESR_PEIN) {
- plb_error = mfdcr(DCRN_PLB0_BESR);
- printk(KERN_DEBUG
- " PEIN: PLB error, PLB0_BESR is 0x%x\n",
- (unsigned int)plb_error);
- plb_addr = mfdcr(DCRN_PLB0_BEAR);
- printk(KERN_DEBUG
- " PEIN: PLB error, PLB0_BEAR is 0x%x\n",
- (unsigned int)plb_addr);
- }
+ return register_sysrq_key('c', &emac_sysrq_op);
}
-void emac_serr_dump_1(struct net_device *dev)
+void __exit emac_fini_debug(void)
{
- struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
- int mal_error = get_mal_dcrn(mal, DCRN_MALESR);
-
- printk(KERN_DEBUG " ----- cumulative errors -----\n");
- if (mal_error & MALESR_DEI)
- printk(KERN_DEBUG " DEI: descriptor error interrupt\n");
- if (mal_error & MALESR_ONEI)
- printk(KERN_DEBUG " OPB non-fullword error interrupt\n");
- if (mal_error & MALESR_OTEI)
- printk(KERN_DEBUG " OTEI: timeout error interrupt\n");
- if (mal_error & MALESR_OSEI)
- printk(KERN_DEBUG " OSEI: slave error interrupt\n");
- if (mal_error & MALESR_PBEI)
- printk(KERN_DEBUG " PBEI: PLB bus error interrupt\n");
+ unregister_sysrq_key('c', &emac_sysrq_op);
}
-void emac_err_dump(struct net_device *dev, int em0isr)
+#else
+int __init emac_init_debug(void)
+{
+ return 0;
+}
+void __exit emac_fini_debug(void)
{
- printk(KERN_DEBUG "%s: on-chip ethernet error:\n", dev->name);
-
- if (em0isr & EMAC_ISR_OVR)
- printk(KERN_DEBUG " OVR: overrun\n");
- if (em0isr & EMAC_ISR_PP)
- printk(KERN_DEBUG " PP: control pause packet\n");
- if (em0isr & EMAC_ISR_BP)
- printk(KERN_DEBUG " BP: packet error\n");
- if (em0isr & EMAC_ISR_RP)
- printk(KERN_DEBUG " RP: runt packet\n");
- if (em0isr & EMAC_ISR_SE)
- printk(KERN_DEBUG " SE: short event\n");
- if (em0isr & EMAC_ISR_ALE)
- printk(KERN_DEBUG " ALE: odd number of nibbles in packet\n");
- if (em0isr & EMAC_ISR_BFCS)
- printk(KERN_DEBUG " BFCS: bad FCS\n");
- if (em0isr & EMAC_ISR_PTLE)
- printk(KERN_DEBUG " PTLE: oversized packet\n");
- if (em0isr & EMAC_ISR_ORE)
- printk(KERN_DEBUG
- " ORE: packet length field > max allowed LLC\n");
- if (em0isr & EMAC_ISR_IRE)
- printk(KERN_DEBUG " IRE: In Range error\n");
- if (em0isr & EMAC_ISR_DBDM)
- printk(KERN_DEBUG " DBDM: xmit error or SQE\n");
- if (em0isr & EMAC_ISR_DB0)
- printk(KERN_DEBUG " DB0: xmit error or SQE on TX channel 0\n");
- if (em0isr & EMAC_ISR_SE0)
- printk(KERN_DEBUG
- " SE0: Signal Quality Error test failure from TX channel 0\n");
- if (em0isr & EMAC_ISR_TE0)
- printk(KERN_DEBUG " TE0: xmit channel 0 aborted\n");
- if (em0isr & EMAC_ISR_DB1)
- printk(KERN_DEBUG " DB1: xmit error or SQE on TX channel \n");
- if (em0isr & EMAC_ISR_SE1)
- printk(KERN_DEBUG
- " SE1: Signal Quality Error test failure from TX channel 1\n");
- if (em0isr & EMAC_ISR_TE1)
- printk(KERN_DEBUG " TE1: xmit channel 1 aborted\n");
- if (em0isr & EMAC_ISR_MOS)
- printk(KERN_DEBUG " MOS\n");
- if (em0isr & EMAC_ISR_MOF)
- printk(KERN_DEBUG " MOF\n");
-
- emac_mac_dump(dev);
- emac_mal_dump(dev);
}
+#endif /* CONFIG_MAGIC_SYSRQ */
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.h b/drivers/net/ibm_emac/ibm_emac_debug.h
new file mode 100644
index 000000000000..e85fbe0a8da9
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_debug.h
@@ -0,0 +1,63 @@
+/*
+ * drivers/net/ibm_emac/ibm_ocp_debug.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.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.
+ *
+ */
+#ifndef __IBM_EMAC_DEBUG_H_
+#define __IBM_EMAC_DEBUG_H_
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include "ibm_emac_core.h"
+#include "ibm_emac_mal.h"
+
+#if defined(CONFIG_IBM_EMAC_DEBUG)
+void emac_dbg_register(int idx, struct ocp_enet_private *dev);
+void mal_dbg_register(int idx, struct ibm_ocp_mal *mal);
+int emac_init_debug(void) __init;
+void emac_fini_debug(void) __exit;
+void emac_dbg_dump_all(void);
+# define DBG_LEVEL 1
+#else
+# define emac_dbg_register(x,y) ((void)0)
+# define mal_dbg_register(x,y) ((void)0)
+# define emac_init_debug() ((void)0)
+# define emac_fini_debug() ((void)0)
+# define emac_dbg_dump_all() ((void)0)
+# define DBG_LEVEL 0
+#endif
+
+#if DBG_LEVEL > 0
+# define DBG(f,x...) printk("emac" f, ##x)
+# define MAL_DBG(f,x...) printk("mal" f, ##x)
+# define ZMII_DBG(f,x...) printk("zmii" f, ##x)
+# define RGMII_DBG(f,x...) printk("rgmii" f, ##x)
+# define NL "\n"
+#else
+# define DBG(f,x...) ((void)0)
+# define MAL_DBG(f,x...) ((void)0)
+# define ZMII_DBG(f,x...) ((void)0)
+# define RGMII_DBG(f,x...) ((void)0)
+#endif
+#if DBG_LEVEL > 1
+# define DBG2(f,x...) DBG(f, ##x)
+# define MAL_DBG2(f,x...) MAL_DBG(f, ##x)
+# define ZMII_DBG2(f,x...) ZMII_DBG(f, ##x)
+# define RGMII_DBG2(f,x...) RGMII_DBG(f, ##x)
+#else
+# define DBG2(f,x...) ((void)0)
+# define MAL_DBG2(f,x...) ((void)0)
+# define ZMII_DBG2(f,x...) ((void)0)
+# define RGMII_DBG2(f,x...) ((void)0)
+#endif
+
+#endif /* __IBM_EMAC_DEBUG_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index e59f57f363ca..da88d43081cc 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -1,436 +1,565 @@
/*
- * ibm_ocp_mal.c
+ * drivers/net/ibm_emac/ibm_emac_mal.c
*
- * Armin Kuster akuster@mvista.com
- * Juen, 2002
+ * Memory Access Layer (MAL) support
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Copyright 2002 MontaVista Softare Inc.
+ * Based on original work by
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>,
+ * David Gibson <hermes@gibson.dropbear.id.au>,
+ *
+ * Armin Kuster <akuster@mvista.com>
+ * Copyright 2002 MontaVista Softare Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/ocp.h>
+#include "ibm_emac_core.h"
#include "ibm_emac_mal.h"
+#include "ibm_emac_debug.h"
-// Locking: Should we share a lock with the client ? The client could provide
-// a lock pointer (optionally) in the commac structure... I don't think this is
-// really necessary though
-
-/* This lock protects the commac list. On today UP implementations, it's
- * really only used as IRQ protection in mal_{register,unregister}_commac()
- */
-static DEFINE_RWLOCK(mal_list_lock);
-
-int mal_register_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+int __init mal_register_commac(struct ibm_ocp_mal *mal,
+ struct mal_commac *commac)
{
unsigned long flags;
+ local_irq_save(flags);
- write_lock_irqsave(&mal_list_lock, flags);
+ MAL_DBG("%d: reg(%08x, %08x)" NL, mal->def->index,
+ commac->tx_chan_mask, commac->rx_chan_mask);
- /* Don't let multiple commacs claim the same channel */
+ /* Don't let multiple commacs claim the same channel(s) */
if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
(mal->rx_chan_mask & commac->rx_chan_mask)) {
- write_unlock_irqrestore(&mal_list_lock, flags);
+ local_irq_restore(flags);
+ printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
+ mal->def->index);
return -EBUSY;
}
mal->tx_chan_mask |= commac->tx_chan_mask;
mal->rx_chan_mask |= commac->rx_chan_mask;
+ list_add(&commac->list, &mal->list);
- list_add(&commac->list, &mal->commac);
-
- write_unlock_irqrestore(&mal_list_lock, flags);
-
+ local_irq_restore(flags);
return 0;
}
-int mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+void __exit mal_unregister_commac(struct ibm_ocp_mal *mal,
+ struct mal_commac *commac)
{
unsigned long flags;
+ local_irq_save(flags);
- write_lock_irqsave(&mal_list_lock, flags);
+ MAL_DBG("%d: unreg(%08x, %08x)" NL, mal->def->index,
+ commac->tx_chan_mask, commac->rx_chan_mask);
mal->tx_chan_mask &= ~commac->tx_chan_mask;
mal->rx_chan_mask &= ~commac->rx_chan_mask;
-
list_del_init(&commac->list);
- write_unlock_irqrestore(&mal_list_lock, flags);
-
- return 0;
+ local_irq_restore(flags);
}
int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel, unsigned long size)
{
- switch (channel) {
- case 0:
- set_mal_dcrn(mal, DCRN_MALRCBS0, size);
- break;
-#ifdef DCRN_MALRCBS1
- case 1:
- set_mal_dcrn(mal, DCRN_MALRCBS1, size);
- break;
-#endif
-#ifdef DCRN_MALRCBS2
- case 2:
- set_mal_dcrn(mal, DCRN_MALRCBS2, size);
- break;
-#endif
-#ifdef DCRN_MALRCBS3
- case 3:
- set_mal_dcrn(mal, DCRN_MALRCBS3, size);
- break;
-#endif
- default:
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+ BUG_ON(channel < 0 || channel >= maldata->num_rx_chans ||
+ size > MAL_MAX_RX_SIZE);
+
+ MAL_DBG("%d: set_rbcs(%d, %lu)" NL, mal->def->index, channel, size);
+
+ if (size & 0xf) {
+ printk(KERN_WARNING
+ "mal%d: incorrect RX size %lu for the channel %d\n",
+ mal->def->index, size, channel);
return -EINVAL;
}
+ set_mal_dcrn(mal, MAL_RCBS(channel), size >> 4);
return 0;
}
-static irqreturn_t mal_serr(int irq, void *dev_instance, struct pt_regs *regs)
+int mal_tx_bd_offset(struct ibm_ocp_mal *mal, int channel)
{
- struct ibm_ocp_mal *mal = dev_instance;
- unsigned long mal_error;
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+ BUG_ON(channel < 0 || channel >= maldata->num_tx_chans);
+ return channel * NUM_TX_BUFF;
+}
- /*
- * This SERR applies to one of the devices on the MAL, here we charge
- * it against the first EMAC registered for the MAL.
- */
+int mal_rx_bd_offset(struct ibm_ocp_mal *mal, int channel)
+{
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+ BUG_ON(channel < 0 || channel >= maldata->num_rx_chans);
+ return maldata->num_tx_chans * NUM_TX_BUFF + channel * NUM_RX_BUFF;
+}
- mal_error = get_mal_dcrn(mal, DCRN_MALESR);
+void mal_enable_tx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+ local_bh_disable();
+ MAL_DBG("%d: enable_tx(%d)" NL, mal->def->index, channel);
+ set_mal_dcrn(mal, MAL_TXCASR,
+ get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel));
+ local_bh_enable();
+}
- printk(KERN_ERR "%s: System Error (MALESR=%lx)\n",
- "MAL" /* FIXME: get the name right */ , mal_error);
+void mal_disable_tx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+ set_mal_dcrn(mal, MAL_TXCARR, MAL_CHAN_MASK(channel));
+ MAL_DBG("%d: disable_tx(%d)" NL, mal->def->index, channel);
+}
- /* FIXME: decipher error */
- /* DIXME: distribute to commacs, if possible */
+void mal_enable_rx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+ local_bh_disable();
+ MAL_DBG("%d: enable_rx(%d)" NL, mal->def->index, channel);
+ set_mal_dcrn(mal, MAL_RXCASR,
+ get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel));
+ local_bh_enable();
+}
- /* Clear the error status register */
- set_mal_dcrn(mal, DCRN_MALESR, mal_error);
+void mal_disable_rx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+ set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
+ MAL_DBG("%d: disable_rx(%d)" NL, mal->def->index, channel);
+}
- return IRQ_HANDLED;
+void mal_poll_add(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+{
+ local_bh_disable();
+ MAL_DBG("%d: poll_add(%p)" NL, mal->def->index, commac);
+ list_add_tail(&commac->poll_list, &mal->poll_list);
+ local_bh_enable();
}
-static irqreturn_t mal_txeob(int irq, void *dev_instance, struct pt_regs *regs)
+void mal_poll_del(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+{
+ local_bh_disable();
+ MAL_DBG("%d: poll_del(%p)" NL, mal->def->index, commac);
+ list_del(&commac->poll_list);
+ local_bh_enable();
+}
+
+/* synchronized by mal_poll() */
+static inline void mal_enable_eob_irq(struct ibm_ocp_mal *mal)
+{
+ MAL_DBG2("%d: enable_irq" NL, mal->def->index);
+ set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE);
+}
+
+/* synchronized by __LINK_STATE_RX_SCHED bit in ndev->state */
+static inline void mal_disable_eob_irq(struct ibm_ocp_mal *mal)
+{
+ set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) & ~MAL_CFG_EOPIE);
+ MAL_DBG2("%d: disable_irq" NL, mal->def->index);
+}
+
+static irqreturn_t mal_serr(int irq, void *dev_instance, struct pt_regs *regs)
{
struct ibm_ocp_mal *mal = dev_instance;
- struct list_head *l;
- unsigned long isr;
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
- isr = get_mal_dcrn(mal, DCRN_MALTXEOBISR);
- set_mal_dcrn(mal, DCRN_MALTXEOBISR, isr);
+ /* Clear the error status register */
+ set_mal_dcrn(mal, MAL_ESR, esr);
- read_lock(&mal_list_lock);
- list_for_each(l, &mal->commac) {
- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
+ MAL_DBG("%d: SERR %08x" NL, mal->def->index, esr);
- if (isr & mc->tx_chan_mask) {
- mc->ops->txeob(mc->dev, isr & mc->tx_chan_mask);
+ if (esr & MAL_ESR_EVB) {
+ if (esr & MAL_ESR_DE) {
+ /* We ignore Descriptor error,
+ * TXDE or RXDE interrupt will be generated anyway.
+ */
+ return IRQ_HANDLED;
}
+
+ if (esr & MAL_ESR_PEIN) {
+ /* PLB error, it's probably buggy hardware or
+ * incorrect physical address in BD (i.e. bug)
+ */
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, PLB (ESR = 0x%08x)\n",
+ mal->def->index, esr);
+ return IRQ_HANDLED;
+ }
+
+ /* OPB error, it's probably buggy hardware or incorrect EBC setup */
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, OPB (ESR = 0x%08x)\n",
+ mal->def->index, esr);
}
- read_unlock(&mal_list_lock);
+ return IRQ_HANDLED;
+}
+
+static inline void mal_schedule_poll(struct ibm_ocp_mal *mal)
+{
+ if (likely(netif_rx_schedule_prep(&mal->poll_dev))) {
+ MAL_DBG2("%d: schedule_poll" NL, mal->def->index);
+ mal_disable_eob_irq(mal);
+ __netif_rx_schedule(&mal->poll_dev);
+ } else
+ MAL_DBG2("%d: already in poll" NL, mal->def->index);
+}
+static irqreturn_t mal_txeob(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ibm_ocp_mal *mal = dev_instance;
+ u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);
+ MAL_DBG2("%d: txeob %08x" NL, mal->def->index, r);
+ mal_schedule_poll(mal);
+ set_mal_dcrn(mal, MAL_TXEOBISR, r);
return IRQ_HANDLED;
}
static irqreturn_t mal_rxeob(int irq, void *dev_instance, struct pt_regs *regs)
{
struct ibm_ocp_mal *mal = dev_instance;
- struct list_head *l;
- unsigned long isr;
+ u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);
+ MAL_DBG2("%d: rxeob %08x" NL, mal->def->index, r);
+ mal_schedule_poll(mal);
+ set_mal_dcrn(mal, MAL_RXEOBISR, r);
+ return IRQ_HANDLED;
+}
- isr = get_mal_dcrn(mal, DCRN_MALRXEOBISR);
- set_mal_dcrn(mal, DCRN_MALRXEOBISR, isr);
+static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ibm_ocp_mal *mal = dev_instance;
+ u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
+ set_mal_dcrn(mal, MAL_TXDEIR, deir);
- read_lock(&mal_list_lock);
- list_for_each(l, &mal->commac) {
- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
+ MAL_DBG("%d: txde %08x" NL, mal->def->index, deir);
- if (isr & mc->rx_chan_mask) {
- mc->ops->rxeob(mc->dev, isr & mc->rx_chan_mask);
- }
- }
- read_unlock(&mal_list_lock);
+ if (net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n",
+ mal->def->index, deir);
return IRQ_HANDLED;
}
-static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t mal_rxde(int irq, void *dev_instance, struct pt_regs *regs)
{
struct ibm_ocp_mal *mal = dev_instance;
struct list_head *l;
- unsigned long deir;
+ u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);
- deir = get_mal_dcrn(mal, DCRN_MALTXDEIR);
+ MAL_DBG("%d: rxde %08x" NL, mal->def->index, deir);
- /* FIXME: print which MAL correctly */
- printk(KERN_WARNING "%s: Tx descriptor error (MALTXDEIR=%lx)\n",
- "MAL", deir);
-
- read_lock(&mal_list_lock);
- list_for_each(l, &mal->commac) {
+ list_for_each(l, &mal->list) {
struct mal_commac *mc = list_entry(l, struct mal_commac, list);
-
- if (deir & mc->tx_chan_mask) {
- mc->ops->txde(mc->dev, deir & mc->tx_chan_mask);
+ if (deir & mc->rx_chan_mask) {
+ mc->rx_stopped = 1;
+ mc->ops->rxde(mc->dev);
}
}
- read_unlock(&mal_list_lock);
+
+ mal_schedule_poll(mal);
+ set_mal_dcrn(mal, MAL_RXDEIR, deir);
return IRQ_HANDLED;
}
-/*
- * This interrupt should be very rare at best. This occurs when
- * the hardware has a problem with the receive descriptors. The manual
- * states that it occurs when the hardware cannot the receive descriptor
- * empty bit is not set. The recovery mechanism will be to
- * traverse through the descriptors, handle any that are marked to be
- * handled and reinitialize each along the way. At that point the driver
- * will be restarted.
- */
-static irqreturn_t mal_rxde(int irq, void *dev_instance, struct pt_regs *regs)
+static int mal_poll(struct net_device *ndev, int *budget)
{
- struct ibm_ocp_mal *mal = dev_instance;
+ struct ibm_ocp_mal *mal = ndev->priv;
struct list_head *l;
- unsigned long deir;
-
- deir = get_mal_dcrn(mal, DCRN_MALRXDEIR);
+ int rx_work_limit = min(ndev->quota, *budget), received = 0, done;
+
+ MAL_DBG2("%d: poll(%d) %d ->" NL, mal->def->index, *budget,
+ rx_work_limit);
+ again:
+ /* Process TX skbs */
+ list_for_each(l, &mal->poll_list) {
+ struct mal_commac *mc =
+ list_entry(l, struct mal_commac, poll_list);
+ mc->ops->poll_tx(mc->dev);
+ }
- /*
- * This really is needed. This case encountered in stress testing.
+ /* Process RX skbs.
+ * We _might_ need something more smart here to enforce polling fairness.
*/
- if (deir == 0)
- return IRQ_HANDLED;
-
- /* FIXME: print which MAL correctly */
- printk(KERN_WARNING "%s: Rx descriptor error (MALRXDEIR=%lx)\n",
- "MAL", deir);
-
- read_lock(&mal_list_lock);
- list_for_each(l, &mal->commac) {
- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
+ list_for_each(l, &mal->poll_list) {
+ struct mal_commac *mc =
+ list_entry(l, struct mal_commac, poll_list);
+ int n = mc->ops->poll_rx(mc->dev, rx_work_limit);
+ if (n) {
+ received += n;
+ rx_work_limit -= n;
+ if (rx_work_limit <= 0) {
+ done = 0;
+ goto more_work; // XXX What if this is the last one ?
+ }
+ }
+ }
- if (deir & mc->rx_chan_mask) {
- mc->ops->rxde(mc->dev, deir & mc->rx_chan_mask);
+ /* We need to disable IRQs to protect from RXDE IRQ here */
+ local_irq_disable();
+ __netif_rx_complete(ndev);
+ mal_enable_eob_irq(mal);
+ local_irq_enable();
+
+ done = 1;
+
+ /* Check for "rotting" packet(s) */
+ list_for_each(l, &mal->poll_list) {
+ struct mal_commac *mc =
+ list_entry(l, struct mal_commac, poll_list);
+ if (unlikely(mc->ops->peek_rx(mc->dev) || mc->rx_stopped)) {
+ MAL_DBG2("%d: rotting packet" NL, mal->def->index);
+ if (netif_rx_reschedule(ndev, received))
+ mal_disable_eob_irq(mal);
+ else
+ MAL_DBG2("%d: already in poll list" NL,
+ mal->def->index);
+
+ if (rx_work_limit > 0)
+ goto again;
+ else
+ goto more_work;
}
+ mc->ops->poll_tx(mc->dev);
}
- read_unlock(&mal_list_lock);
- return IRQ_HANDLED;
+ more_work:
+ ndev->quota -= received;
+ *budget -= received;
+
+ MAL_DBG2("%d: poll() %d <- %d" NL, mal->def->index, *budget,
+ done ? 0 : 1);
+ return done ? 0 : 1;
+}
+
+static void mal_reset(struct ibm_ocp_mal *mal)
+{
+ int n = 10;
+ MAL_DBG("%d: reset" NL, mal->def->index);
+
+ set_mal_dcrn(mal, MAL_CFG, MAL_CFG_SR);
+
+ /* Wait for reset to complete (1 system clock) */
+ while ((get_mal_dcrn(mal, MAL_CFG) & MAL_CFG_SR) && n)
+ --n;
+
+ if (unlikely(!n))
+ printk(KERN_ERR "mal%d: reset timeout\n", mal->def->index);
+}
+
+int mal_get_regs_len(struct ibm_ocp_mal *mal)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(struct ibm_mal_regs);
+}
+
+void *mal_dump_regs(struct ibm_ocp_mal *mal, void *buf)
+{
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ struct ibm_mal_regs *regs = (struct ibm_mal_regs *)(hdr + 1);
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+ int i;
+
+ hdr->version = MAL_VERSION;
+ hdr->index = mal->def->index;
+
+ regs->tx_count = maldata->num_tx_chans;
+ regs->rx_count = maldata->num_rx_chans;
+
+ regs->cfg = get_mal_dcrn(mal, MAL_CFG);
+ regs->esr = get_mal_dcrn(mal, MAL_ESR);
+ regs->ier = get_mal_dcrn(mal, MAL_IER);
+ regs->tx_casr = get_mal_dcrn(mal, MAL_TXCASR);
+ regs->tx_carr = get_mal_dcrn(mal, MAL_TXCARR);
+ regs->tx_eobisr = get_mal_dcrn(mal, MAL_TXEOBISR);
+ regs->tx_deir = get_mal_dcrn(mal, MAL_TXDEIR);
+ regs->rx_casr = get_mal_dcrn(mal, MAL_RXCASR);
+ regs->rx_carr = get_mal_dcrn(mal, MAL_RXCARR);
+ regs->rx_eobisr = get_mal_dcrn(mal, MAL_RXEOBISR);
+ regs->rx_deir = get_mal_dcrn(mal, MAL_RXDEIR);
+
+ for (i = 0; i < regs->tx_count; ++i)
+ regs->tx_ctpr[i] = get_mal_dcrn(mal, MAL_TXCTPR(i));
+
+ for (i = 0; i < regs->rx_count; ++i) {
+ regs->rx_ctpr[i] = get_mal_dcrn(mal, MAL_RXCTPR(i));
+ regs->rcbs[i] = get_mal_dcrn(mal, MAL_RCBS(i));
+ }
+ return regs + 1;
}
static int __init mal_probe(struct ocp_device *ocpdev)
{
- struct ibm_ocp_mal *mal = NULL;
+ struct ibm_ocp_mal *mal;
struct ocp_func_mal_data *maldata;
- int err = 0;
+ int err = 0, i, bd_size;
+
+ MAL_DBG("%d: probe" NL, ocpdev->def->index);
- maldata = (struct ocp_func_mal_data *)ocpdev->def->additions;
+ maldata = ocpdev->def->additions;
if (maldata == NULL) {
- printk(KERN_ERR "mal%d: Missing additional datas !\n",
+ printk(KERN_ERR "mal%d: missing additional data!\n",
ocpdev->def->index);
return -ENODEV;
}
- mal = kmalloc(sizeof(struct ibm_ocp_mal), GFP_KERNEL);
- if (mal == NULL) {
+ mal = kzalloc(sizeof(struct ibm_ocp_mal), GFP_KERNEL);
+ if (!mal) {
printk(KERN_ERR
- "mal%d: Out of memory allocating MAL structure !\n",
+ "mal%d: out of memory allocating MAL structure!\n",
ocpdev->def->index);
return -ENOMEM;
}
- memset(mal, 0, sizeof(*mal));
-
- switch (ocpdev->def->index) {
- case 0:
- mal->dcrbase = DCRN_MAL_BASE;
- break;
-#ifdef DCRN_MAL1_BASE
- case 1:
- mal->dcrbase = DCRN_MAL1_BASE;
- break;
-#endif
- default:
- BUG();
- }
-
- /**************************/
+ mal->dcrbase = maldata->dcr_base;
+ mal->def = ocpdev->def;
- INIT_LIST_HEAD(&mal->commac);
+ INIT_LIST_HEAD(&mal->poll_list);
+ set_bit(__LINK_STATE_START, &mal->poll_dev.state);
+ mal->poll_dev.weight = CONFIG_IBM_EMAC_POLL_WEIGHT;
+ mal->poll_dev.poll = mal_poll;
+ mal->poll_dev.priv = mal;
+ atomic_set(&mal->poll_dev.refcnt, 1);
- set_mal_dcrn(mal, DCRN_MALRXCARR, 0xFFFFFFFF);
- set_mal_dcrn(mal, DCRN_MALTXCARR, 0xFFFFFFFF);
+ INIT_LIST_HEAD(&mal->list);
- set_mal_dcrn(mal, DCRN_MALCR, MALCR_MMSR); /* 384 */
- /* FIXME: Add delay */
+ /* Load power-on reset defaults */
+ mal_reset(mal);
/* Set the MAL configuration register */
- set_mal_dcrn(mal, DCRN_MALCR,
- MALCR_PLBB | MALCR_OPBBL | MALCR_LEA |
- MALCR_PLBLT_DEFAULT);
-
- /* It would be nice to allocate buffers separately for each
- * channel, but we can't because the channels share the upper
- * 13 bits of address lines. Each channels buffer must also
- * be 4k aligned, so we allocate 4k for each channel. This is
- * inefficient FIXME: do better, if possible */
- mal->tx_virt_addr = dma_alloc_coherent(&ocpdev->dev,
- MAL_DT_ALIGN *
- maldata->num_tx_chans,
- &mal->tx_phys_addr, GFP_KERNEL);
- if (mal->tx_virt_addr == NULL) {
+ set_mal_dcrn(mal, MAL_CFG, MAL_CFG_DEFAULT | MAL_CFG_PLBB |
+ MAL_CFG_OPBBL | MAL_CFG_LEA);
+
+ mal_enable_eob_irq(mal);
+
+ /* Allocate space for BD rings */
+ BUG_ON(maldata->num_tx_chans <= 0 || maldata->num_tx_chans > 32);
+ BUG_ON(maldata->num_rx_chans <= 0 || maldata->num_rx_chans > 32);
+ bd_size = sizeof(struct mal_descriptor) *
+ (NUM_TX_BUFF * maldata->num_tx_chans +
+ NUM_RX_BUFF * maldata->num_rx_chans);
+ mal->bd_virt =
+ dma_alloc_coherent(&ocpdev->dev, bd_size, &mal->bd_dma, GFP_KERNEL);
+
+ if (!mal->bd_virt) {
printk(KERN_ERR
- "mal%d: Out of memory allocating MAL descriptors !\n",
- ocpdev->def->index);
+ "mal%d: out of memory allocating RX/TX descriptors!\n",
+ mal->def->index);
err = -ENOMEM;
goto fail;
}
+ memset(mal->bd_virt, 0, bd_size);
- /* God, oh, god, I hate DCRs */
- set_mal_dcrn(mal, DCRN_MALTXCTP0R, mal->tx_phys_addr);
-#ifdef DCRN_MALTXCTP1R
- if (maldata->num_tx_chans > 1)
- set_mal_dcrn(mal, DCRN_MALTXCTP1R,
- mal->tx_phys_addr + MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP1R */
-#ifdef DCRN_MALTXCTP2R
- if (maldata->num_tx_chans > 2)
- set_mal_dcrn(mal, DCRN_MALTXCTP2R,
- mal->tx_phys_addr + 2 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP2R */
-#ifdef DCRN_MALTXCTP3R
- if (maldata->num_tx_chans > 3)
- set_mal_dcrn(mal, DCRN_MALTXCTP3R,
- mal->tx_phys_addr + 3 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP3R */
-#ifdef DCRN_MALTXCTP4R
- if (maldata->num_tx_chans > 4)
- set_mal_dcrn(mal, DCRN_MALTXCTP4R,
- mal->tx_phys_addr + 4 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP4R */
-#ifdef DCRN_MALTXCTP5R
- if (maldata->num_tx_chans > 5)
- set_mal_dcrn(mal, DCRN_MALTXCTP5R,
- mal->tx_phys_addr + 5 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP5R */
-#ifdef DCRN_MALTXCTP6R
- if (maldata->num_tx_chans > 6)
- set_mal_dcrn(mal, DCRN_MALTXCTP6R,
- mal->tx_phys_addr + 6 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP6R */
-#ifdef DCRN_MALTXCTP7R
- if (maldata->num_tx_chans > 7)
- set_mal_dcrn(mal, DCRN_MALTXCTP7R,
- mal->tx_phys_addr + 7 * MAL_DT_ALIGN);
-#endif /* DCRN_MALTXCTP7R */
-
- mal->rx_virt_addr = dma_alloc_coherent(&ocpdev->dev,
- MAL_DT_ALIGN *
- maldata->num_rx_chans,
- &mal->rx_phys_addr, GFP_KERNEL);
-
- set_mal_dcrn(mal, DCRN_MALRXCTP0R, mal->rx_phys_addr);
-#ifdef DCRN_MALRXCTP1R
- if (maldata->num_rx_chans > 1)
- set_mal_dcrn(mal, DCRN_MALRXCTP1R,
- mal->rx_phys_addr + MAL_DT_ALIGN);
-#endif /* DCRN_MALRXCTP1R */
-#ifdef DCRN_MALRXCTP2R
- if (maldata->num_rx_chans > 2)
- set_mal_dcrn(mal, DCRN_MALRXCTP2R,
- mal->rx_phys_addr + 2 * MAL_DT_ALIGN);
-#endif /* DCRN_MALRXCTP2R */
-#ifdef DCRN_MALRXCTP3R
- if (maldata->num_rx_chans > 3)
- set_mal_dcrn(mal, DCRN_MALRXCTP3R,
- mal->rx_phys_addr + 3 * MAL_DT_ALIGN);
-#endif /* DCRN_MALRXCTP3R */
+ for (i = 0; i < maldata->num_tx_chans; ++i)
+ set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +
+ sizeof(struct mal_descriptor) *
+ mal_tx_bd_offset(mal, i));
+
+ for (i = 0; i < maldata->num_rx_chans; ++i)
+ set_mal_dcrn(mal, MAL_RXCTPR(i), mal->bd_dma +
+ sizeof(struct mal_descriptor) *
+ mal_rx_bd_offset(mal, i));
err = request_irq(maldata->serr_irq, mal_serr, 0, "MAL SERR", mal);
if (err)
- goto fail;
- err = request_irq(maldata->txde_irq, mal_txde, 0, "MAL TX DE ", mal);
+ goto fail2;
+ err = request_irq(maldata->txde_irq, mal_txde, 0, "MAL TX DE", mal);
if (err)
- goto fail;
+ goto fail3;
err = request_irq(maldata->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
if (err)
- goto fail;
+ goto fail4;
err = request_irq(maldata->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
if (err)
- goto fail;
+ goto fail5;
err = request_irq(maldata->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
if (err)
- goto fail;
+ goto fail6;
- set_mal_dcrn(mal, DCRN_MALIER,
- MALIER_DE | MALIER_NE | MALIER_TE |
- MALIER_OPBE | MALIER_PLBE);
+ /* Enable all MAL SERR interrupt sources */
+ set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);
- /* Advertise me to the rest of the world */
+ /* Advertise this instance to the rest of the world */
ocp_set_drvdata(ocpdev, mal);
- printk(KERN_INFO "mal%d: Initialized, %d tx channels, %d rx channels\n",
- ocpdev->def->index, maldata->num_tx_chans,
- maldata->num_rx_chans);
+ mal_dbg_register(mal->def->index, mal);
+ printk(KERN_INFO "mal%d: initialized, %d TX channels, %d RX channels\n",
+ mal->def->index, maldata->num_tx_chans, maldata->num_rx_chans);
return 0;
+ fail6:
+ free_irq(maldata->rxde_irq, mal);
+ fail5:
+ free_irq(maldata->txeob_irq, mal);
+ fail4:
+ free_irq(maldata->txde_irq, mal);
+ fail3:
+ free_irq(maldata->serr_irq, mal);
+ fail2:
+ dma_free_coherent(&ocpdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail:
- /* FIXME: dispose requested IRQs ! */
- if (err && mal)
- kfree(mal);
+ kfree(mal);
return err;
}
static void __exit mal_remove(struct ocp_device *ocpdev)
{
struct ibm_ocp_mal *mal = ocp_get_drvdata(ocpdev);
- struct ocp_func_mal_data *maldata = ocpdev->def->additions;
+ struct ocp_func_mal_data *maldata = mal->def->additions;
+
+ MAL_DBG("%d: remove" NL, mal->def->index);
- BUG_ON(!maldata);
+ /* Syncronize with scheduled polling,
+ stolen from net/core/dev.c:dev_close()
+ */
+ clear_bit(__LINK_STATE_START, &mal->poll_dev.state);
+ netif_poll_disable(&mal->poll_dev);
+
+ if (!list_empty(&mal->list)) {
+ /* This is *very* bad */
+ printk(KERN_EMERG
+ "mal%d: commac list is not empty on remove!\n",
+ mal->def->index);
+ }
ocp_set_drvdata(ocpdev, NULL);
- /* FIXME: shut down the MAL, deal with dependency with emac */
free_irq(maldata->serr_irq, mal);
free_irq(maldata->txde_irq, mal);
free_irq(maldata->txeob_irq, mal);
free_irq(maldata->rxde_irq, mal);
free_irq(maldata->rxeob_irq, mal);
- if (mal->tx_virt_addr)
- dma_free_coherent(&ocpdev->dev,
- MAL_DT_ALIGN * maldata->num_tx_chans,
- mal->tx_virt_addr, mal->tx_phys_addr);
+ mal_reset(mal);
- if (mal->rx_virt_addr)
- dma_free_coherent(&ocpdev->dev,
- MAL_DT_ALIGN * maldata->num_rx_chans,
- mal->rx_virt_addr, mal->rx_phys_addr);
+ mal_dbg_register(mal->def->index, NULL);
+
+ dma_free_coherent(&ocpdev->dev,
+ sizeof(struct mal_descriptor) *
+ (NUM_TX_BUFF * maldata->num_tx_chans +
+ NUM_RX_BUFF * maldata->num_rx_chans), mal->bd_virt,
+ mal->bd_dma);
kfree(mal);
}
/* Structure for a device driver */
static struct ocp_device_id mal_ids[] = {
- {.vendor = OCP_ANY_ID,.function = OCP_FUNC_MAL},
- {.vendor = OCP_VENDOR_INVALID}
+ { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_MAL },
+ { .vendor = OCP_VENDOR_INVALID}
};
static struct ocp_driver mal_driver = {
@@ -441,23 +570,14 @@ static struct ocp_driver mal_driver = {
.remove = mal_remove,
};
-static int __init init_mals(void)
+int __init mal_init(void)
{
- int rc;
-
- rc = ocp_register_driver(&mal_driver);
- if (rc < 0) {
- ocp_unregister_driver(&mal_driver);
- return -ENODEV;
- }
-
- return 0;
+ MAL_DBG(": init" NL);
+ return ocp_register_driver(&mal_driver);
}
-static void __exit exit_mals(void)
+void __exit mal_exit(void)
{
+ MAL_DBG(": exit" NL);
ocp_unregister_driver(&mal_driver);
}
-
-module_init(init_mals);
-module_exit(exit_mals);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index dd9f0dabc6e0..15b0bdae26ac 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -1,131 +1,267 @@
-#ifndef _IBM_EMAC_MAL_H
-#define _IBM_EMAC_MAL_H
+/*
+ * drivers/net/ibm_emac/ibm_emac_mal.h
+ *
+ * Memory Access Layer (MAL) support
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ * Armin Kuster <akuster@mvista.com>
+ * Copyright 2002 MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __IBM_EMAC_MAL_H_
+#define __IBM_EMAC_MAL_H_
+#include <linux/config.h>
+#include <linux/init.h>
#include <linux/list.h>
+#include <linux/netdevice.h>
-#define MAL_DT_ALIGN (4096) /* Alignment for each channel's descriptor table */
+#include <asm/io.h>
-#define MAL_CHAN_MASK(chan) (0x80000000 >> (chan))
+/*
+ * These MAL "versions" probably aren't the real versions IBM uses for these
+ * MAL cores, I assigned them just to make #ifdefs in this file nicer and
+ * reflect the fact that 40x and 44x have slightly different MALs. --ebs
+ */
+#if defined(CONFIG_405GP) || defined(CONFIG_405GPR) || defined(CONFIG_405EP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_NP405H)
+#define MAL_VERSION 1
+#elif defined(CONFIG_440GP) || defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#define MAL_VERSION 2
+#else
+#error "Unknown SoC, please check chip manual and choose MAL 'version'"
+#endif
+
+/* MALx DCR registers */
+#define MAL_CFG 0x00
+#define MAL_CFG_SR 0x80000000
+#define MAL_CFG_PLBB 0x00004000
+#define MAL_CFG_OPBBL 0x00000080
+#define MAL_CFG_EOPIE 0x00000004
+#define MAL_CFG_LEA 0x00000002
+#define MAL_CFG_SD 0x00000001
+#if MAL_VERSION == 1
+#define MAL_CFG_PLBP_MASK 0x00c00000
+#define MAL_CFG_PLBP_10 0x00800000
+#define MAL_CFG_GA 0x00200000
+#define MAL_CFG_OA 0x00100000
+#define MAL_CFG_PLBLE 0x00080000
+#define MAL_CFG_PLBT_MASK 0x00078000
+#define MAL_CFG_DEFAULT (MAL_CFG_PLBP_10 | MAL_CFG_PLBT_MASK)
+#elif MAL_VERSION == 2
+#define MAL_CFG_RPP_MASK 0x00c00000
+#define MAL_CFG_RPP_10 0x00800000
+#define MAL_CFG_RMBS_MASK 0x00300000
+#define MAL_CFG_WPP_MASK 0x000c0000
+#define MAL_CFG_WPP_10 0x00080000
+#define MAL_CFG_WMBS_MASK 0x00030000
+#define MAL_CFG_PLBLE 0x00008000
+#define MAL_CFG_DEFAULT (MAL_CFG_RMBS_MASK | MAL_CFG_WMBS_MASK | \
+ MAL_CFG_RPP_10 | MAL_CFG_WPP_10)
+#else
+#error "Unknown MAL version"
+#endif
+
+#define MAL_ESR 0x01
+#define MAL_ESR_EVB 0x80000000
+#define MAL_ESR_CIDT 0x40000000
+#define MAL_ESR_CID_MASK 0x3e000000
+#define MAL_ESR_CID_SHIFT 25
+#define MAL_ESR_DE 0x00100000
+#define MAL_ESR_OTE 0x00040000
+#define MAL_ESR_OSE 0x00020000
+#define MAL_ESR_PEIN 0x00010000
+#define MAL_ESR_DEI 0x00000010
+#define MAL_ESR_OTEI 0x00000004
+#define MAL_ESR_OSEI 0x00000002
+#define MAL_ESR_PBEI 0x00000001
+#if MAL_VERSION == 1
+#define MAL_ESR_ONE 0x00080000
+#define MAL_ESR_ONEI 0x00000008
+#elif MAL_VERSION == 2
+#define MAL_ESR_PTE 0x00800000
+#define MAL_ESR_PRE 0x00400000
+#define MAL_ESR_PWE 0x00200000
+#define MAL_ESR_PTEI 0x00000080
+#define MAL_ESR_PREI 0x00000040
+#define MAL_ESR_PWEI 0x00000020
+#else
+#error "Unknown MAL version"
+#endif
+
+#define MAL_IER 0x02
+#define MAL_IER_DE 0x00000010
+#define MAL_IER_OTE 0x00000004
+#define MAL_IER_OE 0x00000002
+#define MAL_IER_PE 0x00000001
+#if MAL_VERSION == 1
+#define MAL_IER_NWE 0x00000008
+#define MAL_IER_SOC_EVENTS MAL_IER_NWE
+#elif MAL_VERSION == 2
+#define MAL_IER_PT 0x00000080
+#define MAL_IER_PRE 0x00000040
+#define MAL_IER_PWE 0x00000020
+#define MAL_IER_SOC_EVENTS (MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE)
+#else
+#error "Unknown MAL version"
+#endif
+#define MAL_IER_EVENTS (MAL_IER_SOC_EVENTS | MAL_IER_OTE | \
+ MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
+
+#define MAL_TXCASR 0x04
+#define MAL_TXCARR 0x05
+#define MAL_TXEOBISR 0x06
+#define MAL_TXDEIR 0x07
+#define MAL_RXCASR 0x10
+#define MAL_RXCARR 0x11
+#define MAL_RXEOBISR 0x12
+#define MAL_RXDEIR 0x13
+#define MAL_TXCTPR(n) ((n) + 0x20)
+#define MAL_RXCTPR(n) ((n) + 0x40)
+#define MAL_RCBS(n) ((n) + 0x60)
+
+/* In reality MAL can handle TX buffers up to 4095 bytes long,
+ * but this isn't a good round number :) --ebs
+ */
+#define MAL_MAX_TX_SIZE 4080
+#define MAL_MAX_RX_SIZE 4080
+
+static inline int mal_rx_size(int len)
+{
+ len = (len + 0xf) & ~0xf;
+ return len > MAL_MAX_RX_SIZE ? MAL_MAX_RX_SIZE : len;
+}
+
+static inline int mal_tx_chunks(int len)
+{
+ return (len + MAL_MAX_TX_SIZE - 1) / MAL_MAX_TX_SIZE;
+}
+
+#define MAL_CHAN_MASK(n) (0x80000000 >> (n))
/* MAL Buffer Descriptor structure */
struct mal_descriptor {
- unsigned short ctrl; /* MAL / Commac status control bits */
- short data_len; /* Max length is 4K-1 (12 bits) */
- unsigned char *data_ptr; /* pointer to actual data buffer */
-} __attribute__ ((packed));
+ u16 ctrl; /* MAL / Commac status control bits */
+ u16 data_len; /* Max length is 4K-1 (12 bits) */
+ u32 data_ptr; /* pointer to actual data buffer */
+};
/* the following defines are for the MadMAL status and control registers. */
/* MADMAL transmit and receive status/control bits */
-#define MAL_RX_CTRL_EMPTY 0x8000
-#define MAL_RX_CTRL_WRAP 0x4000
-#define MAL_RX_CTRL_CM 0x2000
-#define MAL_RX_CTRL_LAST 0x1000
-#define MAL_RX_CTRL_FIRST 0x0800
-#define MAL_RX_CTRL_INTR 0x0400
-
-#define MAL_TX_CTRL_READY 0x8000
-#define MAL_TX_CTRL_WRAP 0x4000
-#define MAL_TX_CTRL_CM 0x2000
-#define MAL_TX_CTRL_LAST 0x1000
-#define MAL_TX_CTRL_INTR 0x0400
+#define MAL_RX_CTRL_EMPTY 0x8000
+#define MAL_RX_CTRL_WRAP 0x4000
+#define MAL_RX_CTRL_CM 0x2000
+#define MAL_RX_CTRL_LAST 0x1000
+#define MAL_RX_CTRL_FIRST 0x0800
+#define MAL_RX_CTRL_INTR 0x0400
+#define MAL_RX_CTRL_SINGLE (MAL_RX_CTRL_LAST | MAL_RX_CTRL_FIRST)
+#define MAL_IS_SINGLE_RX(ctrl) (((ctrl) & MAL_RX_CTRL_SINGLE) == MAL_RX_CTRL_SINGLE)
+
+#define MAL_TX_CTRL_READY 0x8000
+#define MAL_TX_CTRL_WRAP 0x4000
+#define MAL_TX_CTRL_CM 0x2000
+#define MAL_TX_CTRL_LAST 0x1000
+#define MAL_TX_CTRL_INTR 0x0400
struct mal_commac_ops {
- void (*txeob) (void *dev, u32 chanmask);
- void (*txde) (void *dev, u32 chanmask);
- void (*rxeob) (void *dev, u32 chanmask);
- void (*rxde) (void *dev, u32 chanmask);
+ void (*poll_tx) (void *dev);
+ int (*poll_rx) (void *dev, int budget);
+ int (*peek_rx) (void *dev);
+ void (*rxde) (void *dev);
};
struct mal_commac {
- struct mal_commac_ops *ops;
- void *dev;
- u32 tx_chan_mask, rx_chan_mask;
- struct list_head list;
+ struct mal_commac_ops *ops;
+ void *dev;
+ struct list_head poll_list;
+ int rx_stopped;
+
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
+ struct list_head list;
};
struct ibm_ocp_mal {
- int dcrbase;
+ int dcrbase;
- struct list_head commac;
- u32 tx_chan_mask, rx_chan_mask;
+ struct list_head poll_list;
+ struct net_device poll_dev;
- dma_addr_t tx_phys_addr;
- struct mal_descriptor *tx_virt_addr;
+ struct list_head list;
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
- dma_addr_t rx_phys_addr;
- struct mal_descriptor *rx_virt_addr;
-};
+ dma_addr_t bd_dma;
+ struct mal_descriptor *bd_virt;
-#define GET_MAL_STANZA(base,dcrn) \
- case base: \
- x = mfdcr(dcrn(base)); \
- break;
-
-#define SET_MAL_STANZA(base,dcrn, val) \
- case base: \
- mtdcr(dcrn(base), (val)); \
- break;
-
-#define GET_MAL0_STANZA(dcrn) GET_MAL_STANZA(DCRN_MAL_BASE,dcrn)
-#define SET_MAL0_STANZA(dcrn,val) SET_MAL_STANZA(DCRN_MAL_BASE,dcrn,val)
-
-#ifdef DCRN_MAL1_BASE
-#define GET_MAL1_STANZA(dcrn) GET_MAL_STANZA(DCRN_MAL1_BASE,dcrn)
-#define SET_MAL1_STANZA(dcrn,val) SET_MAL_STANZA(DCRN_MAL1_BASE,dcrn,val)
-#else /* ! DCRN_MAL1_BASE */
-#define GET_MAL1_STANZA(dcrn)
-#define SET_MAL1_STANZA(dcrn,val)
-#endif
+ struct ocp_def *def;
+};
-#define get_mal_dcrn(mal, dcrn) ({ \
- u32 x; \
- switch ((mal)->dcrbase) { \
- GET_MAL0_STANZA(dcrn) \
- GET_MAL1_STANZA(dcrn) \
- default: \
- x = 0; \
- BUG(); \
- } \
-x; })
-
-#define set_mal_dcrn(mal, dcrn, val) do { \
- switch ((mal)->dcrbase) { \
- SET_MAL0_STANZA(dcrn,val) \
- SET_MAL1_STANZA(dcrn,val) \
- default: \
- BUG(); \
- } } while (0)
-
-static inline void mal_enable_tx_channels(struct ibm_ocp_mal *mal, u32 chanmask)
+static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- set_mal_dcrn(mal, DCRN_MALTXCASR,
- get_mal_dcrn(mal, DCRN_MALTXCASR) | chanmask);
+ return mfdcr(mal->dcrbase + reg);
}
-static inline void mal_disable_tx_channels(struct ibm_ocp_mal *mal,
- u32 chanmask)
+static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- set_mal_dcrn(mal, DCRN_MALTXCARR, chanmask);
+ mtdcr(mal->dcrbase + reg, val);
}
-static inline void mal_enable_rx_channels(struct ibm_ocp_mal *mal, u32 chanmask)
-{
- set_mal_dcrn(mal, DCRN_MALRXCASR,
- get_mal_dcrn(mal, DCRN_MALRXCASR) | chanmask);
-}
+/* Register MAL devices */
+int mal_init(void) __init;
+void mal_exit(void) __exit;
-static inline void mal_disable_rx_channels(struct ibm_ocp_mal *mal,
- u32 chanmask)
-{
- set_mal_dcrn(mal, DCRN_MALRXCARR, chanmask);
-}
+int mal_register_commac(struct ibm_ocp_mal *mal,
+ struct mal_commac *commac) __init;
+void mal_unregister_commac(struct ibm_ocp_mal *mal,
+ struct mal_commac *commac) __exit;
+int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel, unsigned long size);
+
+/* Returns BD ring offset for a particular channel
+ (in 'struct mal_descriptor' elements)
+*/
+int mal_tx_bd_offset(struct ibm_ocp_mal *mal, int channel);
+int mal_rx_bd_offset(struct ibm_ocp_mal *mal, int channel);
+
+void mal_enable_tx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_disable_tx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_enable_rx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_disable_rx_channel(struct ibm_ocp_mal *mal, int channel);
-extern int mal_register_commac(struct ibm_ocp_mal *mal,
- struct mal_commac *commac);
-extern int mal_unregister_commac(struct ibm_ocp_mal *mal,
- struct mal_commac *commac);
+/* Add/remove EMAC to/from MAL polling list */
+void mal_poll_add(struct ibm_ocp_mal *mal, struct mal_commac *commac);
+void mal_poll_del(struct ibm_ocp_mal *mal, struct mal_commac *commac);
+
+/* Ethtool MAL registers */
+struct ibm_mal_regs {
+ u32 tx_count;
+ u32 rx_count;
+
+ u32 cfg;
+ u32 esr;
+ u32 ier;
+ u32 tx_casr;
+ u32 tx_carr;
+ u32 tx_eobisr;
+ u32 tx_deir;
+ u32 rx_casr;
+ u32 rx_carr;
+ u32 rx_eobisr;
+ u32 rx_deir;
+ u32 tx_ctpr[32];
+ u32 rx_ctpr[32];
+ u32 rcbs[32];
+};
-extern int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel,
- unsigned long size);
+int mal_get_regs_len(struct ibm_ocp_mal *mal);
+void *mal_dump_regs(struct ibm_ocp_mal *mal, void *buf);
-#endif /* _IBM_EMAC_MAL_H */
+#endif /* __IBM_EMAC_MAL_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index 14213f090e91..a27e49cfe43b 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -1,96 +1,80 @@
/*
- * ibm_ocp_phy.c
+ * drivers/net/ibm_emac/ibm_emac_phy.c
*
- * PHY drivers for the ibm ocp ethernet driver. Borrowed
- * from sungem_phy.c, though I only kept the generic MII
+ * Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
+ * Borrowed from sungem_phy.c, though I only kept the generic MII
* driver for now.
*
* This file should be shared with other drivers or eventually
* merged as the "low level" part of miilib
*
* (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
*
*/
-
#include <linux/config.h>
-
#include <linux/module.h>
-
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/types.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
+#include <asm/ocp.h>
+
#include "ibm_emac_phy.h"
-static int reset_one_mii_phy(struct mii_phy *phy, int phy_id)
+static inline int phy_read(struct mii_phy *phy, int reg)
+{
+ return phy->mdio_read(phy->dev, phy->address, reg);
+}
+
+static inline void phy_write(struct mii_phy *phy, int reg, int val)
{
- u16 val;
+ phy->mdio_write(phy->dev, phy->address, reg, val);
+}
+
+int mii_reset_phy(struct mii_phy *phy)
+{
+ int val;
int limit = 10000;
- val = __phy_read(phy, phy_id, MII_BMCR);
+ val = phy_read(phy, MII_BMCR);
val &= ~BMCR_ISOLATE;
val |= BMCR_RESET;
- __phy_write(phy, phy_id, MII_BMCR, val);
+ phy_write(phy, MII_BMCR, val);
- udelay(100);
+ udelay(300);
while (limit--) {
- val = __phy_read(phy, phy_id, MII_BMCR);
- if ((val & BMCR_RESET) == 0)
+ val = phy_read(phy, MII_BMCR);
+ if (val >= 0 && (val & BMCR_RESET) == 0)
break;
udelay(10);
}
if ((val & BMCR_ISOLATE) && limit > 0)
- __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
-
- return (limit <= 0);
-}
-
-static int cis8201_init(struct mii_phy *phy)
-{
- u16 epcr;
-
- epcr = phy_read(phy, MII_CIS8201_EPCR);
- epcr &= ~EPCR_MODE_MASK;
-
- switch (phy->mode) {
- case PHY_MODE_TBI:
- epcr |= EPCR_TBI_MODE;
- break;
- case PHY_MODE_RTBI:
- epcr |= EPCR_RTBI_MODE;
- break;
- case PHY_MODE_GMII:
- epcr |= EPCR_GMII_MODE;
- break;
- case PHY_MODE_RGMII:
- default:
- epcr |= EPCR_RGMII_MODE;
- }
+ phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
- phy_write(phy, MII_CIS8201_EPCR, epcr);
-
- return 0;
+ return limit <= 0;
}
static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
{
- u16 ctl, adv;
+ int ctl, adv;
- phy->autoneg = 1;
+ phy->autoneg = AUTONEG_ENABLE;
phy->speed = SPEED_10;
phy->duplex = DUPLEX_HALF;
- phy->pause = 0;
+ phy->pause = phy->asym_pause = 0;
phy->advertising = advertise;
/* Setup standard advertise */
adv = phy_read(phy, MII_ADVERTISE);
- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (adv < 0)
+ return adv;
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
if (advertise & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF;
if (advertise & ADVERTISED_10baseT_Full)
@@ -99,8 +83,25 @@ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
phy_write(phy, MII_ADVERTISE, adv);
+ if (phy->features &
+ (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
+ adv = phy_read(phy, MII_CTRL1000);
+ if (adv < 0)
+ return adv;
+ adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ if (advertise & ADVERTISED_1000baseT_Full)
+ adv |= ADVERTISE_1000FULL;
+ if (advertise & ADVERTISED_1000baseT_Half)
+ adv |= ADVERTISE_1000HALF;
+ phy_write(phy, MII_CTRL1000, adv);
+ }
+
/* Start/Restart aneg */
ctl = phy_read(phy, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
@@ -111,14 +112,16 @@ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
{
- u16 ctl;
+ int ctl;
- phy->autoneg = 0;
+ phy->autoneg = AUTONEG_DISABLE;
phy->speed = speed;
phy->duplex = fd;
- phy->pause = 0;
+ phy->pause = phy->asym_pause = 0;
ctl = phy_read(phy, MII_BMCR);
+ if (ctl < 0)
+ return ctl;
ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
/* First reset the PHY */
@@ -132,6 +135,8 @@ static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
ctl |= BMCR_SPEED100;
break;
case SPEED_1000:
+ ctl |= BMCR_SPEED1000;
+ break;
default:
return -EINVAL;
}
@@ -144,112 +149,143 @@ static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
static int genmii_poll_link(struct mii_phy *phy)
{
- u16 status;
+ int status;
- (void)phy_read(phy, MII_BMSR);
+ /* Clear latched value with dummy read */
+ phy_read(phy, MII_BMSR);
status = phy_read(phy, MII_BMSR);
- if ((status & BMSR_LSTATUS) == 0)
+ if (status < 0 || (status & BMSR_LSTATUS) == 0)
return 0;
- if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
+ if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE))
return 0;
return 1;
}
-#define MII_CIS8201_ACSR 0x1c
-#define ACSR_DUPLEX_STATUS 0x0020
-#define ACSR_SPEED_1000BASET 0x0010
-#define ACSR_SPEED_100BASET 0x0008
-
-static int cis8201_read_link(struct mii_phy *phy)
+static int genmii_read_link(struct mii_phy *phy)
{
- u16 acsr;
+ if (phy->autoneg == AUTONEG_ENABLE) {
+ int glpa = 0;
+ int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
+ if (lpa < 0)
+ return lpa;
+
+ if (phy->features &
+ (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
+ int adv = phy_read(phy, MII_CTRL1000);
+ glpa = phy_read(phy, MII_STAT1000);
+
+ if (glpa < 0 || adv < 0)
+ return adv;
+
+ glpa &= adv << 2;
+ }
+
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+ phy->pause = phy->asym_pause = 0;
+
+ if (glpa & (LPA_1000FULL | LPA_1000HALF)) {
+ phy->speed = SPEED_1000;
+ if (glpa & LPA_1000FULL)
+ phy->duplex = DUPLEX_FULL;
+ } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phy->speed = SPEED_100;
+ if (lpa & LPA_100FULL)
+ phy->duplex = DUPLEX_FULL;
+ } else if (lpa & LPA_10FULL)
+ phy->duplex = DUPLEX_FULL;
- if (phy->autoneg) {
- acsr = phy_read(phy, MII_CIS8201_ACSR);
+ if (phy->duplex == DUPLEX_FULL) {
+ phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
+ phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
+ }
+ } else {
+ int bmcr = phy_read(phy, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
- if (acsr & ACSR_DUPLEX_STATUS)
+ if (bmcr & BMCR_FULLDPLX)
phy->duplex = DUPLEX_FULL;
else
phy->duplex = DUPLEX_HALF;
- if (acsr & ACSR_SPEED_1000BASET) {
+ if (bmcr & BMCR_SPEED1000)
phy->speed = SPEED_1000;
- } else if (acsr & ACSR_SPEED_100BASET)
+ else if (bmcr & BMCR_SPEED100)
phy->speed = SPEED_100;
else
phy->speed = SPEED_10;
- phy->pause = 0;
- }
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
+ phy->pause = phy->asym_pause = 0;
+ }
return 0;
}
-static int genmii_read_link(struct mii_phy *phy)
+/* Generic implementation for most 10/100/1000 PHYs */
+static struct mii_phy_ops generic_phy_ops = {
+ .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 genmii_phy_def = {
+ .phy_id = 0x00000000,
+ .phy_id_mask = 0x00000000,
+ .name = "Generic MII",
+ .ops = &generic_phy_ops
+};
+
+/* CIS8201 */
+#define MII_CIS8201_EPCR 0x17
+#define EPCR_MODE_MASK 0x3000
+#define EPCR_GMII_MODE 0x0000
+#define EPCR_RGMII_MODE 0x1000
+#define EPCR_TBI_MODE 0x2000
+#define EPCR_RTBI_MODE 0x3000
+
+static int cis8201_init(struct mii_phy *phy)
{
- u16 lpa;
+ int epcr;
- if (phy->autoneg) {
- lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
+ epcr = phy_read(phy, MII_CIS8201_EPCR);
+ if (epcr < 0)
+ return epcr;
- phy->speed = SPEED_10;
- phy->duplex = DUPLEX_HALF;
- phy->pause = 0;
+ epcr &= ~EPCR_MODE_MASK;
- if (lpa & (LPA_100FULL | LPA_100HALF)) {
- phy->speed = SPEED_100;
- if (lpa & LPA_100FULL)
- phy->duplex = DUPLEX_FULL;
- } else if (lpa & LPA_10FULL)
- phy->duplex = DUPLEX_FULL;
+ switch (phy->mode) {
+ case PHY_MODE_TBI:
+ epcr |= EPCR_TBI_MODE;
+ break;
+ case PHY_MODE_RTBI:
+ epcr |= EPCR_RTBI_MODE;
+ break;
+ case PHY_MODE_GMII:
+ epcr |= EPCR_GMII_MODE;
+ break;
+ case PHY_MODE_RGMII:
+ default:
+ epcr |= EPCR_RGMII_MODE;
}
- /* On non-aneg, we assume what we put in BMCR is the speed,
- * though magic-aneg shouldn't prevent this case from occurring
- */
+
+ phy_write(phy, MII_CIS8201_EPCR, epcr);
return 0;
}
-#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
-#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
-
-/* CIS8201 phy ops */
static struct mii_phy_ops cis8201_phy_ops = {
- init:cis8201_init,
- setup_aneg:genmii_setup_aneg,
- setup_forced:genmii_setup_forced,
- poll_link:genmii_poll_link,
- read_link:cis8201_read_link
-};
-
-/* Generic implementation for most 10/100 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
- setup_aneg:genmii_setup_aneg,
- setup_forced:genmii_setup_forced,
- poll_link:genmii_poll_link,
- read_link:genmii_read_link
+ .init = cis8201_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 cis8201_phy_def = {
- phy_id:0x000fc410,
- phy_id_mask:0x000ffff0,
- name:"CIS8201 Gigabit Ethernet",
- features:MII_GBIT_FEATURES,
- magic_aneg:0,
- ops:&cis8201_phy_ops
-};
-
-static struct mii_phy_def genmii_phy_def = {
- phy_id:0x00000000,
- phy_id_mask:0x00000000,
- name:"Generic MII",
- features:MII_BASIC_FEATURES,
- magic_aneg:0,
- ops:&generic_phy_ops
+ .phy_id = 0x000fc410,
+ .phy_id_mask = 0x000ffff0,
+ .name = "CIS8201 Gigabit Ethernet",
+ .ops = &cis8201_phy_ops
};
static struct mii_phy_def *mii_phy_table[] = {
@@ -258,39 +294,60 @@ static struct mii_phy_def *mii_phy_table[] = {
NULL
};
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
+int mii_phy_probe(struct mii_phy *phy, int address)
{
- int rc;
- u32 id;
struct mii_phy_def *def;
int i;
+ u32 id;
- phy->autoneg = 0;
+ phy->autoneg = AUTONEG_DISABLE;
phy->advertising = 0;
- phy->mii_id = mii_id;
- phy->speed = 0;
- phy->duplex = 0;
- phy->pause = 0;
-
- /* Take PHY out of isloate mode and reset it. */
- rc = reset_one_mii_phy(phy, mii_id);
- if (rc)
+ phy->address = address;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+ phy->pause = phy->asym_pause = 0;
+
+ /* Take PHY out of isolate mode and reset it. */
+ if (mii_reset_phy(phy))
return -ENODEV;
/* Read ID and find matching entry */
- id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
- & 0xfffffff0;
+ id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2);
for (i = 0; (def = mii_phy_table[i]) != NULL; i++)
if ((id & def->phy_id_mask) == def->phy_id)
break;
/* Should never be NULL (we have a generic entry), but... */
- if (def == NULL)
+ if (!def)
return -ENODEV;
phy->def = def;
+ /* Determine PHY features if needed */
+ phy->features = def->features;
+ if (!phy->features) {
+ u16 bmsr = phy_read(phy, MII_BMSR);
+ if (bmsr & BMSR_ANEGCAPABLE)
+ phy->features |= SUPPORTED_Autoneg;
+ if (bmsr & BMSR_10HALF)
+ phy->features |= SUPPORTED_10baseT_Half;
+ if (bmsr & BMSR_10FULL)
+ phy->features |= SUPPORTED_10baseT_Full;
+ if (bmsr & BMSR_100HALF)
+ phy->features |= SUPPORTED_100baseT_Half;
+ if (bmsr & BMSR_100FULL)
+ phy->features |= SUPPORTED_100baseT_Full;
+ if (bmsr & BMSR_ESTATEN) {
+ u16 esr = phy_read(phy, MII_ESTATUS);
+ if (esr & ESTATUS_1000_TFULL)
+ phy->features |= SUPPORTED_1000baseT_Full;
+ if (esr & ESTATUS_1000_THALF)
+ phy->features |= SUPPORTED_1000baseT_Half;
+ }
+ phy->features |= SUPPORTED_MII;
+ }
+
/* Setup default advertising */
- phy->advertising = def->features;
+ phy->advertising = phy->features;
return 0;
}
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.h b/drivers/net/ibm_emac/ibm_emac_phy.h
index 61afbea96563..a70e0fea54c4 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.h
+++ b/drivers/net/ibm_emac/ibm_emac_phy.h
@@ -1,65 +1,25 @@
-
/*
- * ibm_emac_phy.h
- *
+ * drivers/net/ibm_emac/ibm_emac_phy.h
*
- * Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * February 2003
+ * Driver for PowerPC 4xx on-chip ethernet controller, PHY support
*
- * 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.
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * February 2003
*
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR 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.
- *
- * 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.
+ * Minor additions by Eugene Surovegin <ebs@ebshome.net>, 2004
*
+ * 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 basically duplicates sungem_phy.{c,h} with different PHYs
* supported. I'm looking into merging that in a single mii layer more
* flexible than mii.c
*/
-#ifndef _IBM_EMAC_PHY_H_
-#define _IBM_EMAC_PHY_H_
-
-/*
- * PHY mode settings
- * Used for multi-mode capable PHYs
- */
-#define PHY_MODE_NA 0
-#define PHY_MODE_MII 1
-#define PHY_MODE_RMII 2
-#define PHY_MODE_SMII 3
-#define PHY_MODE_RGMII 4
-#define PHY_MODE_TBI 5
-#define PHY_MODE_GMII 6
-#define PHY_MODE_RTBI 7
-#define PHY_MODE_SGMII 8
-
-/*
- * PHY specific registers/values
- */
-
-/* CIS8201 */
-#define MII_CIS8201_EPCR 0x17
-#define EPCR_MODE_MASK 0x3000
-#define EPCR_GMII_MODE 0x0000
-#define EPCR_RGMII_MODE 0x1000
-#define EPCR_TBI_MODE 0x2000
-#define EPCR_RTBI_MODE 0x3000
+#ifndef _IBM_OCP_PHY_H_
+#define _IBM_OCP_PHY_H_
struct mii_phy;
@@ -77,7 +37,8 @@ struct mii_phy_ops {
struct mii_phy_def {
u32 phy_id; /* Concatenated ID1 << 16 | ID2 */
u32 phy_id_mask; /* Significant bits */
- u32 features; /* Ethtool SUPPORTED_* defines */
+ u32 features; /* Ethtool SUPPORTED_* defines or
+ 0 for autodetect */
int magic_aneg; /* Autoneg does all speed test for us */
const char *name;
const struct mii_phy_ops *ops;
@@ -86,8 +47,11 @@ struct mii_phy_def {
/* An instance of a PHY, partially borrowed from mii_if_info */
struct mii_phy {
struct mii_phy_def *def;
- int advertising;
- int mii_id;
+ u32 advertising; /* Ethtool ADVERTISED_* defines */
+ u32 features; /* Copied from mii_phy_def.features
+ or determined automaticaly */
+ int address; /* PHY address */
+ int mode; /* PHY mode */
/* 1: autoneg enabled, 0: disabled */
int autoneg;
@@ -98,40 +62,19 @@ struct mii_phy {
int speed;
int duplex;
int pause;
-
- /* PHY mode - if needed */
- int mode;
+ int asym_pause;
/* Provided by host chip */
struct net_device *dev;
- int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
- void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
+ int (*mdio_read) (struct net_device * dev, int addr, int reg);
+ void (*mdio_write) (struct net_device * dev, int addr, int reg,
int val);
};
/* Pass in a struct mii_phy with dev, mdio_read and mdio_write
* filled, the remaining fields will be filled on return
*/
-extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
-
-static inline int __phy_read(struct mii_phy *phy, int id, int reg)
-{
- return phy->mdio_read(phy->dev, id, reg);
-}
-
-static inline void __phy_write(struct mii_phy *phy, int id, int reg, int val)
-{
- phy->mdio_write(phy->dev, id, reg, val);
-}
-
-static inline int phy_read(struct mii_phy *phy, int reg)
-{
- return phy->mdio_read(phy->dev, phy->mii_id, reg);
-}
-
-static inline void phy_write(struct mii_phy *phy, int reg, int val)
-{
- phy->mdio_write(phy->dev, phy->mii_id, reg, val);
-}
+int mii_phy_probe(struct mii_phy *phy, int address);
+int mii_reset_phy(struct mii_phy *phy);
-#endif /* _IBM_EMAC_PHY_H_ */
+#endif /* _IBM_OCP_PHY_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.c b/drivers/net/ibm_emac/ibm_emac_rgmii.c
new file mode 100644
index 000000000000..f0b1ffb2dbbf
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.c
@@ -0,0 +1,201 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_rgmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+#include "ibm_emac_debug.h"
+
+/* RGMIIx_FER */
+#define RGMII_FER_MASK(idx) (0x7 << ((idx) * 4))
+#define RGMII_FER_RTBI(idx) (0x4 << ((idx) * 4))
+#define RGMII_FER_RGMII(idx) (0x5 << ((idx) * 4))
+#define RGMII_FER_TBI(idx) (0x6 << ((idx) * 4))
+#define RGMII_FER_GMII(idx) (0x7 << ((idx) * 4))
+
+/* RGMIIx_SSR */
+#define RGMII_SSR_MASK(idx) (0x7 << ((idx) * 8))
+#define RGMII_SSR_100(idx) (0x2 << ((idx) * 8))
+#define RGMII_SSR_1000(idx) (0x4 << ((idx) * 8))
+
+/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
+static inline int rgmii_valid_mode(int phy_mode)
+{
+ return phy_mode == PHY_MODE_GMII ||
+ phy_mode == PHY_MODE_RGMII ||
+ phy_mode == PHY_MODE_TBI ||
+ phy_mode == PHY_MODE_RTBI;
+}
+
+static inline const char *rgmii_mode_name(int mode)
+{
+ switch (mode) {
+ case PHY_MODE_RGMII:
+ return "RGMII";
+ case PHY_MODE_TBI:
+ return "TBI";
+ case PHY_MODE_GMII:
+ return "GMII";
+ case PHY_MODE_RTBI:
+ return "RTBI";
+ default:
+ BUG();
+ }
+}
+
+static inline u32 rgmii_mode_mask(int mode, int input)
+{
+ switch (mode) {
+ case PHY_MODE_RGMII:
+ return RGMII_FER_RGMII(input);
+ case PHY_MODE_TBI:
+ return RGMII_FER_TBI(input);
+ case PHY_MODE_GMII:
+ return RGMII_FER_GMII(input);
+ case PHY_MODE_RTBI:
+ return RGMII_FER_RTBI(input);
+ default:
+ BUG();
+ }
+}
+
+static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode)
+{
+ struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+ struct rgmii_regs *p;
+
+ RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode);
+
+ if (!dev) {
+ dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
+ if (!dev) {
+ printk(KERN_ERR
+ "rgmii%d: couldn't allocate device structure!\n",
+ ocpdev->def->index);
+ return -ENOMEM;
+ }
+
+ p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr,
+ sizeof(struct rgmii_regs));
+ if (!p) {
+ printk(KERN_ERR
+ "rgmii%d: could not ioremap device registers!\n",
+ ocpdev->def->index);
+ kfree(dev);
+ return -ENOMEM;
+ }
+
+ dev->base = p;
+ ocp_set_drvdata(ocpdev, dev);
+
+ /* Disable all inputs by default */
+ out_be32(&p->fer, 0);
+ } else
+ p = dev->base;
+
+ /* Enable this input */
+ out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));
+
+ printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
+ ocpdev->def->index, input, rgmii_mode_name(mode));
+
+ ++dev->users;
+ return 0;
+}
+
+int __init rgmii_attach(void *emac)
+{
+ struct ocp_enet_private *dev = emac;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+ /* Check if we need to attach to a RGMII */
+ if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) {
+ dev->rgmii_input = emacdata->rgmii_mux;
+ dev->rgmii_dev =
+ ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII,
+ emacdata->rgmii_idx);
+ if (!dev->rgmii_dev) {
+ printk(KERN_ERR "emac%d: unknown rgmii%d!\n",
+ dev->def->index, emacdata->rgmii_idx);
+ return -ENODEV;
+ }
+ if (rgmii_init
+ (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) {
+ printk(KERN_ERR
+ "emac%d: rgmii%d initialization failed!\n",
+ dev->def->index, emacdata->rgmii_idx);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
+{
+ struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+ u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input);
+
+ RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
+
+ if (speed == SPEED_1000)
+ ssr |= RGMII_SSR_1000(input);
+ else if (speed == SPEED_100)
+ ssr |= RGMII_SSR_100(input);
+
+ out_be32(&dev->base->ssr, ssr);
+}
+
+void __exit __rgmii_fini(struct ocp_device *ocpdev, int input)
+{
+ struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+ BUG_ON(!dev || dev->users == 0);
+
+ RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
+
+ /* Disable this input */
+ out_be32(&dev->base->fer,
+ in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input));
+
+ if (!--dev->users) {
+ /* Free everything if this is the last user */
+ ocp_set_drvdata(ocpdev, NULL);
+ iounmap((void *)dev->base);
+ kfree(dev);
+ }
+}
+
+int __rgmii_get_regs_len(struct ocp_device *ocpdev)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(struct rgmii_regs);
+}
+
+void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+ struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
+
+ hdr->version = 0;
+ hdr->index = ocpdev->def->index;
+ memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));
+ return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.h b/drivers/net/ibm_emac/ibm_emac_rgmii.h
index 49f188f4ea6e..a1ffb8a44fff 100644
--- a/drivers/net/ibm_emac/ibm_emac_rgmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.h
@@ -1,5 +1,7 @@
/*
- * Defines for the IBM RGMII bridge
+ * drivers/net/ibm_emac/ibm_emac_rgmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
*
* Based on ocp_zmii.h/ibm_emac_zmii.h
* Armin Kuster akuster@mvista.com
@@ -7,6 +9,9 @@
* Copyright 2004 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.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
@@ -19,47 +24,42 @@
#include <linux/config.h>
/* RGMII bridge */
-typedef struct rgmii_regs {
+struct rgmii_regs {
u32 fer; /* Function enable register */
u32 ssr; /* Speed select register */
-} rgmii_t;
-
-#define RGMII_INPUTS 4
+};
/* RGMII device */
struct ibm_ocp_rgmii {
struct rgmii_regs *base;
- int mode[RGMII_INPUTS];
int users; /* number of EMACs using this RGMII bridge */
};
-/* Fuctional Enable Reg */
-#define RGMII_FER_MASK(x) (0x00000007 << (4*x))
-#define RGMII_RTBI 0x00000004
-#define RGMII_RGMII 0x00000005
-#define RGMII_TBI 0x00000006
-#define RGMII_GMII 0x00000007
-
-/* Speed Selection reg */
+#ifdef CONFIG_IBM_EMAC_RGMII
+int rgmii_attach(void *emac) __init;
-#define RGMII_SP2_100 0x00000002
-#define RGMII_SP2_1000 0x00000004
-#define RGMII_SP3_100 0x00000200
-#define RGMII_SP3_1000 0x00000400
+void __rgmii_fini(struct ocp_device *ocpdev, int input) __exit;
+static inline void rgmii_fini(struct ocp_device *ocpdev, int input)
+{
+ if (ocpdev)
+ __rgmii_fini(ocpdev, input);
+}
-#define RGMII_MII2_SPDMASK 0x00000007
-#define RGMII_MII3_SPDMASK 0x00000700
+void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
-#define RGMII_MII2_100MB RGMII_SP2_100 & ~RGMII_SP2_1000
-#define RGMII_MII2_1000MB RGMII_SP2_1000 & ~RGMII_SP2_100
-#define RGMII_MII2_10MB ~(RGMII_SP2_100 | RGMII_SP2_1000)
-#define RGMII_MII3_100MB RGMII_SP3_100 & ~RGMII_SP3_1000
-#define RGMII_MII3_1000MB RGMII_SP3_1000 & ~RGMII_SP3_100
-#define RGMII_MII3_10MB ~(RGMII_SP3_100 | RGMII_SP3_1000)
+int __rgmii_get_regs_len(struct ocp_device *ocpdev);
+static inline int rgmii_get_regs_len(struct ocp_device *ocpdev)
+{
+ return ocpdev ? __rgmii_get_regs_len(ocpdev) : 0;
+}
-#define RTBI 0
-#define RGMII 1
-#define TBI 2
-#define GMII 3
+void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf);
+#else
+# define rgmii_attach(x) 0
+# define rgmii_fini(x,y) ((void)0)
+# define rgmii_set_speed(x,y,z) ((void)0)
+# define rgmii_get_regs_len(x) 0
+# define rgmii_dump_regs(x,buf) (buf)
+#endif /* !CONFIG_IBM_EMAC_RGMII */
#endif /* _IBM_EMAC_RGMII_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.c b/drivers/net/ibm_emac/ibm_emac_tah.c
new file mode 100644
index 000000000000..af08afc22f9f
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_tah.c
@@ -0,0 +1,111 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_tah.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
+ *
+ * Copyright 2004 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.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.
+ */
+#include <linux/config.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+
+static int __init tah_init(struct ocp_device *ocpdev)
+{
+ struct tah_regs *p;
+
+ if (ocp_get_drvdata(ocpdev)) {
+ printk(KERN_ERR "tah%d: already in use!\n", ocpdev->def->index);
+ return -EBUSY;
+ }
+
+ /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
+ p = (struct tah_regs *)ioremap(ocpdev->def->paddr, sizeof(*p));
+ if (!p) {
+ printk(KERN_ERR "tah%d: could not ioremap device registers!\n",
+ ocpdev->def->index);
+ return -ENOMEM;
+ }
+ ocp_set_drvdata(ocpdev, p);
+ __tah_reset(ocpdev);
+
+ return 0;
+}
+
+int __init tah_attach(void *emac)
+{
+ struct ocp_enet_private *dev = emac;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+ /* Check if we need to attach to a TAH */
+ if (emacdata->tah_idx >= 0) {
+ dev->tah_dev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
+ emacdata->tah_idx);
+ if (!dev->tah_dev) {
+ printk(KERN_ERR "emac%d: unknown tah%d!\n",
+ dev->def->index, emacdata->tah_idx);
+ return -ENODEV;
+ }
+ if (tah_init(dev->tah_dev)) {
+ printk(KERN_ERR
+ "emac%d: tah%d initialization failed!\n",
+ dev->def->index, emacdata->tah_idx);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+void __exit __tah_fini(struct ocp_device *ocpdev)
+{
+ struct tah_regs *p = ocp_get_drvdata(ocpdev);
+ BUG_ON(!p);
+ ocp_set_drvdata(ocpdev, NULL);
+ iounmap((void *)p);
+}
+
+void __tah_reset(struct ocp_device *ocpdev)
+{
+ struct tah_regs *p = ocp_get_drvdata(ocpdev);
+ int n;
+
+ /* Reset TAH */
+ out_be32(&p->mr, TAH_MR_SR);
+ n = 100;
+ while ((in_be32(&p->mr) & TAH_MR_SR) && n)
+ --n;
+
+ if (unlikely(!n))
+ printk(KERN_ERR "tah%d: reset timeout\n", ocpdev->def->index);
+
+ /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
+ out_be32(&p->mr,
+ TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
+ TAH_MR_DIG);
+}
+
+int __tah_get_regs_len(struct ocp_device *ocpdev)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(struct tah_regs);
+}
+
+void *tah_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+ struct tah_regs *dev = ocp_get_drvdata(ocpdev);
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
+
+ hdr->version = 0;
+ hdr->index = ocpdev->def->index;
+ memcpy_fromio(regs, dev, sizeof(struct tah_regs));
+ return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.h b/drivers/net/ibm_emac/ibm_emac_tah.h
index ecfc69805521..9299b5dd7eb1 100644
--- a/drivers/net/ibm_emac/ibm_emac_tah.h
+++ b/drivers/net/ibm_emac/ibm_emac_tah.h
@@ -1,9 +1,13 @@
/*
- * Defines for the IBM TAH
+ * drivers/net/ibm_emac/ibm_emac_tah.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
*
* Copyright 2004 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
+ * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.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
@@ -13,36 +17,72 @@
#ifndef _IBM_EMAC_TAH_H
#define _IBM_EMAC_TAH_H
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
+
/* TAH */
-typedef struct tah_regs {
- u32 tah_revid;
+struct tah_regs {
+ u32 revid;
u32 pad[3];
- u32 tah_mr;
- u32 tah_ssr0;
- u32 tah_ssr1;
- u32 tah_ssr2;
- u32 tah_ssr3;
- u32 tah_ssr4;
- u32 tah_ssr5;
- u32 tah_tsr;
-} tah_t;
+ u32 mr;
+ u32 ssr0;
+ u32 ssr1;
+ u32 ssr2;
+ u32 ssr3;
+ u32 ssr4;
+ u32 ssr5;
+ u32 tsr;
+};
/* TAH engine */
-#define TAH_MR_CVR 0x80000000
-#define TAH_MR_SR 0x40000000
-#define TAH_MR_ST_256 0x01000000
-#define TAH_MR_ST_512 0x02000000
-#define TAH_MR_ST_768 0x03000000
-#define TAH_MR_ST_1024 0x04000000
-#define TAH_MR_ST_1280 0x05000000
-#define TAH_MR_ST_1536 0x06000000
-#define TAH_MR_TFS_16KB 0x00000000
-#define TAH_MR_TFS_2KB 0x00200000
-#define TAH_MR_TFS_4KB 0x00400000
-#define TAH_MR_TFS_6KB 0x00600000
-#define TAH_MR_TFS_8KB 0x00800000
-#define TAH_MR_TFS_10KB 0x00a00000
-#define TAH_MR_DTFP 0x00100000
-#define TAH_MR_DIG 0x00080000
+#define TAH_MR_CVR 0x80000000
+#define TAH_MR_SR 0x40000000
+#define TAH_MR_ST_256 0x01000000
+#define TAH_MR_ST_512 0x02000000
+#define TAH_MR_ST_768 0x03000000
+#define TAH_MR_ST_1024 0x04000000
+#define TAH_MR_ST_1280 0x05000000
+#define TAH_MR_ST_1536 0x06000000
+#define TAH_MR_TFS_16KB 0x00000000
+#define TAH_MR_TFS_2KB 0x00200000
+#define TAH_MR_TFS_4KB 0x00400000
+#define TAH_MR_TFS_6KB 0x00600000
+#define TAH_MR_TFS_8KB 0x00800000
+#define TAH_MR_TFS_10KB 0x00a00000
+#define TAH_MR_DTFP 0x00100000
+#define TAH_MR_DIG 0x00080000
+
+#ifdef CONFIG_IBM_EMAC_TAH
+int tah_attach(void *emac) __init;
+
+void __tah_fini(struct ocp_device *ocpdev) __exit;
+static inline void tah_fini(struct ocp_device *ocpdev)
+{
+ if (ocpdev)
+ __tah_fini(ocpdev);
+}
+
+void __tah_reset(struct ocp_device *ocpdev);
+static inline void tah_reset(struct ocp_device *ocpdev)
+{
+ if (ocpdev)
+ __tah_reset(ocpdev);
+}
+
+int __tah_get_regs_len(struct ocp_device *ocpdev);
+static inline int tah_get_regs_len(struct ocp_device *ocpdev)
+{
+ return ocpdev ? __tah_get_regs_len(ocpdev) : 0;
+}
+
+void *tah_dump_regs(struct ocp_device *ocpdev, void *buf);
+#else
+# define tah_attach(x) 0
+# define tah_fini(x) ((void)0)
+# define tah_reset(x) ((void)0)
+# define tah_get_regs_len(x) 0
+# define tah_dump_regs(x,buf) (buf)
+#endif /* !CONFIG_IBM_EMAC_TAH */
#endif /* _IBM_EMAC_TAH_H */
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.c b/drivers/net/ibm_emac/ibm_emac_zmii.c
new file mode 100644
index 000000000000..35c1185079ed
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.c
@@ -0,0 +1,255 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_zmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ * Armin Kuster <akuster@mvista.com>
+ * Copyright 2001 MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+#include "ibm_emac_debug.h"
+
+/* ZMIIx_FER */
+#define ZMII_FER_MDI(idx) (0x80000000 >> ((idx) * 4))
+#define ZMII_FER_MDI_ALL (ZMII_FER_MDI(0) | ZMII_FER_MDI(1) | \
+ ZMII_FER_MDI(2) | ZMII_FER_MDI(3))
+
+#define ZMII_FER_SMII(idx) (0x40000000 >> ((idx) * 4))
+#define ZMII_FER_RMII(idx) (0x20000000 >> ((idx) * 4))
+#define ZMII_FER_MII(idx) (0x10000000 >> ((idx) * 4))
+
+/* ZMIIx_SSR */
+#define ZMII_SSR_SCI(idx) (0x40000000 >> ((idx) * 4))
+#define ZMII_SSR_FSS(idx) (0x20000000 >> ((idx) * 4))
+#define ZMII_SSR_SP(idx) (0x10000000 >> ((idx) * 4))
+
+/* ZMII only supports MII, RMII and SMII
+ * we also support autodetection for backward compatibility
+ */
+static inline int zmii_valid_mode(int mode)
+{
+ return mode == PHY_MODE_MII ||
+ mode == PHY_MODE_RMII ||
+ mode == PHY_MODE_SMII ||
+ mode == PHY_MODE_NA;
+}
+
+static inline const char *zmii_mode_name(int mode)
+{
+ switch (mode) {
+ case PHY_MODE_MII:
+ return "MII";
+ case PHY_MODE_RMII:
+ return "RMII";
+ case PHY_MODE_SMII:
+ return "SMII";
+ default:
+ BUG();
+ }
+}
+
+static inline u32 zmii_mode_mask(int mode, int input)
+{
+ switch (mode) {
+ case PHY_MODE_MII:
+ return ZMII_FER_MII(input);
+ case PHY_MODE_RMII:
+ return ZMII_FER_RMII(input);
+ case PHY_MODE_SMII:
+ return ZMII_FER_SMII(input);
+ default:
+ return 0;
+ }
+}
+
+static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode)
+{
+ struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+ struct zmii_regs *p;
+
+ ZMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, *mode);
+
+ if (!dev) {
+ dev = kzalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL);
+ if (!dev) {
+ printk(KERN_ERR
+ "zmii%d: couldn't allocate device structure!\n",
+ ocpdev->def->index);
+ return -ENOMEM;
+ }
+ dev->mode = PHY_MODE_NA;
+
+ p = (struct zmii_regs *)ioremap(ocpdev->def->paddr,
+ sizeof(struct zmii_regs));
+ if (!p) {
+ printk(KERN_ERR
+ "zmii%d: could not ioremap device registers!\n",
+ ocpdev->def->index);
+ kfree(dev);
+ return -ENOMEM;
+ }
+ dev->base = p;
+ ocp_set_drvdata(ocpdev, dev);
+
+ /* We may need FER value for autodetection later */
+ dev->fer_save = in_be32(&p->fer);
+
+ /* Disable all inputs by default */
+ out_be32(&p->fer, 0);
+ } else
+ p = dev->base;
+
+ if (!zmii_valid_mode(*mode)) {
+ /* Probably an EMAC connected to RGMII,
+ * but it still may need ZMII for MDIO
+ */
+ goto out;
+ }
+
+ /* Autodetect ZMII mode if not specified.
+ * This is only for backward compatibility with the old driver.
+ * Please, always specify PHY mode in your board port to avoid
+ * any surprises.
+ */
+ if (dev->mode == PHY_MODE_NA) {
+ if (*mode == PHY_MODE_NA) {
+ u32 r = dev->fer_save;
+
+ ZMII_DBG("%d: autodetecting mode, FER = 0x%08x" NL,
+ ocpdev->def->index, r);
+
+ if (r & (ZMII_FER_MII(0) | ZMII_FER_MII(1)))
+ dev->mode = PHY_MODE_MII;
+ else if (r & (ZMII_FER_RMII(0) | ZMII_FER_RMII(1)))
+ dev->mode = PHY_MODE_RMII;
+ else
+ dev->mode = PHY_MODE_SMII;
+ } else
+ dev->mode = *mode;
+
+ printk(KERN_NOTICE "zmii%d: bridge in %s mode\n",
+ ocpdev->def->index, zmii_mode_name(dev->mode));
+ } else {
+ /* All inputs must use the same mode */
+ if (*mode != PHY_MODE_NA && *mode != dev->mode) {
+ printk(KERN_ERR
+ "zmii%d: invalid mode %d specified for input %d\n",
+ ocpdev->def->index, *mode, input);
+ return -EINVAL;
+ }
+ }
+
+ /* Report back correct PHY mode,
+ * it may be used during PHY initialization.
+ */
+ *mode = dev->mode;
+
+ /* Enable this input */
+ out_be32(&p->fer, in_be32(&p->fer) | zmii_mode_mask(dev->mode, input));
+ out:
+ ++dev->users;
+ return 0;
+}
+
+int __init zmii_attach(void *emac)
+{
+ struct ocp_enet_private *dev = emac;
+ struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+ if (emacdata->zmii_idx >= 0) {
+ dev->zmii_input = emacdata->zmii_mux;
+ dev->zmii_dev =
+ ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_ZMII,
+ emacdata->zmii_idx);
+ if (!dev->zmii_dev) {
+ printk(KERN_ERR "emac%d: unknown zmii%d!\n",
+ dev->def->index, emacdata->zmii_idx);
+ return -ENODEV;
+ }
+ if (zmii_init
+ (dev->zmii_dev, dev->zmii_input, &emacdata->phy_mode)) {
+ printk(KERN_ERR
+ "emac%d: zmii%d initialization failed!\n",
+ dev->def->index, emacdata->zmii_idx);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+void __zmii_enable_mdio(struct ocp_device *ocpdev, int input)
+{
+ struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+ u32 fer = in_be32(&dev->base->fer) & ~ZMII_FER_MDI_ALL;
+
+ ZMII_DBG2("%d: mdio(%d)" NL, ocpdev->def->index, input);
+
+ out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input));
+}
+
+void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
+{
+ struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+ u32 ssr = in_be32(&dev->base->ssr);
+
+ ZMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
+
+ if (speed == SPEED_100)
+ ssr |= ZMII_SSR_SP(input);
+ else
+ ssr &= ~ZMII_SSR_SP(input);
+
+ out_be32(&dev->base->ssr, ssr);
+}
+
+void __exit __zmii_fini(struct ocp_device *ocpdev, int input)
+{
+ struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+ BUG_ON(!dev || dev->users == 0);
+
+ ZMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
+
+ /* Disable this input */
+ out_be32(&dev->base->fer,
+ in_be32(&dev->base->fer) & ~zmii_mode_mask(dev->mode, input));
+
+ if (!--dev->users) {
+ /* Free everything if this is the last user */
+ ocp_set_drvdata(ocpdev, NULL);
+ iounmap((void *)dev->base);
+ kfree(dev);
+ }
+}
+
+int __zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+ return sizeof(struct emac_ethtool_regs_subhdr) +
+ sizeof(struct zmii_regs);
+}
+
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+ struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+ struct emac_ethtool_regs_subhdr *hdr = buf;
+ struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1);
+
+ hdr->version = 0;
+ hdr->index = ocpdev->def->index;
+ memcpy_fromio(regs, dev->base, sizeof(struct zmii_regs));
+ return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.h b/drivers/net/ibm_emac/ibm_emac_zmii.h
index 6f6cd2a39e38..0bb26062c0ad 100644
--- a/drivers/net/ibm_emac/ibm_emac_zmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.h
@@ -1,23 +1,27 @@
/*
- * ocp_zmii.h
+ * drivers/net/ibm_emac/ibm_emac_zmii.h
*
- * Defines for the IBM ZMII bridge
+ * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
*
- * Armin Kuster akuster@mvista.com
- * Dec, 2001
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Copyright 2001 MontaVista Softare Inc.
+ * Based on original work by
+ * Armin Kuster <akuster@mvista.com>
+ * Copyright 2001 MontaVista Softare Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
*/
-
#ifndef _IBM_EMAC_ZMII_H_
#define _IBM_EMAC_ZMII_H_
#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
/* ZMII bridge registers */
struct zmii_regs {
@@ -26,68 +30,54 @@ struct zmii_regs {
u32 smiirs; /* SMII status reg */
};
-#define ZMII_INPUTS 4
-
/* ZMII device */
struct ibm_ocp_zmii {
struct zmii_regs *base;
- int mode[ZMII_INPUTS];
+ int mode; /* subset of PHY_MODE_XXXX */
int users; /* number of EMACs using this ZMII bridge */
+ u32 fer_save; /* FER value left by firmware */
};
-/* Fuctional Enable Reg */
-
-#define ZMII_FER_MASK(x) (0xf0000000 >> (4*x))
-
-#define ZMII_MDI0 0x80000000
-#define ZMII_SMII0 0x40000000
-#define ZMII_RMII0 0x20000000
-#define ZMII_MII0 0x10000000
-#define ZMII_MDI1 0x08000000
-#define ZMII_SMII1 0x04000000
-#define ZMII_RMII1 0x02000000
-#define ZMII_MII1 0x01000000
-#define ZMII_MDI2 0x00800000
-#define ZMII_SMII2 0x00400000
-#define ZMII_RMII2 0x00200000
-#define ZMII_MII2 0x00100000
-#define ZMII_MDI3 0x00080000
-#define ZMII_SMII3 0x00040000
-#define ZMII_RMII3 0x00020000
-#define ZMII_MII3 0x00010000
+#ifdef CONFIG_IBM_EMAC_ZMII
+int zmii_attach(void *emac) __init;
-/* Speed Selection reg */
+void __zmii_fini(struct ocp_device *ocpdev, int input) __exit;
+static inline void zmii_fini(struct ocp_device *ocpdev, int input)
+{
+ if (ocpdev)
+ __zmii_fini(ocpdev, input);
+}
-#define ZMII_SCI0 0x40000000
-#define ZMII_FSS0 0x20000000
-#define ZMII_SP0 0x10000000
-#define ZMII_SCI1 0x04000000
-#define ZMII_FSS1 0x02000000
-#define ZMII_SP1 0x01000000
-#define ZMII_SCI2 0x00400000
-#define ZMII_FSS2 0x00200000
-#define ZMII_SP2 0x00100000
-#define ZMII_SCI3 0x00040000
-#define ZMII_FSS3 0x00020000
-#define ZMII_SP3 0x00010000
+void __zmii_enable_mdio(struct ocp_device *ocpdev, int input);
+static inline void zmii_enable_mdio(struct ocp_device *ocpdev, int input)
+{
+ if (ocpdev)
+ __zmii_enable_mdio(ocpdev, input);
+}
-#define ZMII_MII0_100MB ZMII_SP0
-#define ZMII_MII0_10MB ~ZMII_SP0
-#define ZMII_MII1_100MB ZMII_SP1
-#define ZMII_MII1_10MB ~ZMII_SP1
-#define ZMII_MII2_100MB ZMII_SP2
-#define ZMII_MII2_10MB ~ZMII_SP2
-#define ZMII_MII3_100MB ZMII_SP3
-#define ZMII_MII3_10MB ~ZMII_SP3
+void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
+static inline void zmii_set_speed(struct ocp_device *ocpdev, int input,
+ int speed)
+{
+ if (ocpdev)
+ __zmii_set_speed(ocpdev, input, speed);
+}
-/* SMII Status reg */
+int __zmii_get_regs_len(struct ocp_device *ocpdev);
+static inline int zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+ return ocpdev ? __zmii_get_regs_len(ocpdev) : 0;
+}
-#define ZMII_STS0 0xFF000000 /* EMAC0 smii status mask */
-#define ZMII_STS1 0x00FF0000 /* EMAC1 smii status mask */
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf);
-#define SMII 0
-#define RMII 1
-#define MII 2
-#define MDI 3
+#else
+# define zmii_attach(x) 0
+# define zmii_fini(x,y) ((void)0)
+# define zmii_enable_mdio(x,y) ((void)0)
+# define zmii_set_speed(x,y,z) ((void)0)
+# define zmii_get_regs_len(x) 0
+# define zmii_dump_regs(x,buf) (buf)
+#endif /* !CONFIG_IBM_EMAC_ZMII */
#endif /* _IBM_EMAC_ZMII_H_ */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index c39b0609742a..94239f67f3a3 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -96,10 +96,10 @@ static void ibmveth_proc_unregister_driver(void);
static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*);
+static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
#ifdef CONFIG_PROC_FS
-#define IBMVETH_PROC_DIR "ibmveth"
+#define IBMVETH_PROC_DIR "net/ibmveth"
static struct proc_dir_entry *ibmveth_proc_dir;
#endif
@@ -181,6 +181,7 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
atomic_set(&pool->available, 0);
pool->producer_index = 0;
pool->consumer_index = 0;
+ pool->active = 0;
return 0;
}
@@ -236,7 +237,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
if(lpar_rc != H_Success) {
- pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
+ pool->free_map[free_index] = index;
pool->skbuff[index] = NULL;
pool->consumer_index--;
dma_unmap_single(&adapter->vdev->dev,
@@ -255,37 +256,19 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
atomic_add(buffers_added, &(pool->available));
}
-/* check if replenishing is needed. */
-static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter)
-{
- return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) ||
- (atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) ||
- (atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold));
-}
-
-/* kick the replenish tasklet if we need replenishing and it isn't already running */
-static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter)
-{
- if(ibmveth_is_replenishing_needed(adapter) &&
- (atomic_dec_if_positive(&adapter->not_replenishing) == 0)) {
- schedule_work(&adapter->replenish_task);
- }
-}
-
-/* replenish tasklet routine */
+/* replenish routine */
static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
{
+ int i;
+
adapter->replenish_task_cycles++;
- ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
- ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
- ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+ for(i = 0; i < IbmVethNumBufferPools; i++)
+ if(adapter->rx_buff_pool[i].active)
+ ibmveth_replenish_buffer_pool(adapter,
+ &adapter->rx_buff_pool[i]);
adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
-
- atomic_inc(&adapter->not_replenishing);
-
- ibmveth_schedule_replenishing(adapter);
}
/* empty and free ana buffer pool - also used to do cleanup in error paths */
@@ -293,10 +276,8 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibm
{
int i;
- if(pool->free_map) {
- kfree(pool->free_map);
- pool->free_map = NULL;
- }
+ kfree(pool->free_map);
+ pool->free_map = NULL;
if(pool->skbuff && pool->dma_addr) {
for(i = 0; i < pool->size; ++i) {
@@ -321,6 +302,7 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibm
kfree(pool->skbuff);
pool->skbuff = NULL;
}
+ pool->active = 0;
}
/* remove a buffer from a pool */
@@ -379,6 +361,12 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
ibmveth_assert(pool < IbmVethNumBufferPools);
ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+ if(!adapter->rx_buff_pool[pool].active) {
+ ibmveth_rxq_harvest_buffer(adapter);
+ ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
+ return;
+ }
+
desc.desc = 0;
desc.fields.valid = 1;
desc.fields.length = adapter->rx_buff_pool[pool].buff_size;
@@ -409,6 +397,8 @@ static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
{
+ int i;
+
if(adapter->buffer_list_addr != NULL) {
if(!dma_mapping_error(adapter->buffer_list_dma)) {
dma_unmap_single(&adapter->vdev->dev,
@@ -443,26 +433,24 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
adapter->rx_queue.queue_addr = NULL;
}
- ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
- ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
- ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+ for(i = 0; i<IbmVethNumBufferPools; i++)
+ ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
}
static int ibmveth_open(struct net_device *netdev)
{
struct ibmveth_adapter *adapter = netdev->priv;
u64 mac_address = 0;
- int rxq_entries;
+ int rxq_entries = 1;
unsigned long lpar_rc;
int rc;
union ibmveth_buf_desc rxq_desc;
+ int i;
ibmveth_debug_printk("open starting\n");
- rxq_entries =
- adapter->rx_buff_pool[0].size +
- adapter->rx_buff_pool[1].size +
- adapter->rx_buff_pool[2].size + 1;
+ for(i = 0; i<IbmVethNumBufferPools; i++)
+ rxq_entries += adapter->rx_buff_pool[i].size;
adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
@@ -502,14 +490,8 @@ static int ibmveth_open(struct net_device *netdev)
adapter->rx_queue.num_slots = rxq_entries;
adapter->rx_queue.toggle = 1;
- if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) ||
- ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) ||
- ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2]))
- {
- ibmveth_error_printk("unable to allocate buffer pools\n");
- ibmveth_cleanup(adapter);
- return -ENOMEM;
- }
+ /* call change_mtu to init the buffer pools based in initial mtu */
+ ibmveth_change_mtu(netdev, netdev->mtu);
memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
mac_address = mac_address >> 16;
@@ -532,7 +514,7 @@ static int ibmveth_open(struct net_device *netdev)
if(lpar_rc != H_Success) {
ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
- ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n",
+ ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
adapter->buffer_list_dma,
adapter->filter_list_dma,
rxq_desc.desc,
@@ -552,10 +534,10 @@ static int ibmveth_open(struct net_device *netdev)
return rc;
}
- netif_start_queue(netdev);
+ ibmveth_debug_printk("initial replenish cycle\n");
+ ibmveth_interrupt(netdev->irq, netdev, NULL);
- ibmveth_debug_printk("scheduling initial replenish cycle\n");
- ibmveth_schedule_replenishing(adapter);
+ netif_start_queue(netdev);
ibmveth_debug_printk("open complete\n");
@@ -573,9 +555,6 @@ static int ibmveth_close(struct net_device *netdev)
free_irq(netdev->irq, netdev);
- cancel_delayed_work(&adapter->replenish_task);
- flush_scheduled_work();
-
do {
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
} while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
@@ -640,12 +619,18 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
unsigned long lpar_rc;
int nfrags = 0, curfrag;
unsigned long correlator;
+ unsigned long flags;
unsigned int retry_count;
+ unsigned int tx_dropped = 0;
+ unsigned int tx_bytes = 0;
+ unsigned int tx_packets = 0;
+ unsigned int tx_send_failed = 0;
+ unsigned int tx_map_failed = 0;
+
if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) {
- adapter->stats.tx_dropped++;
- dev_kfree_skb(skb);
- return 0;
+ tx_dropped++;
+ goto out;
}
memset(&desc, 0, sizeof(desc));
@@ -664,10 +649,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if(dma_mapping_error(desc[0].fields.address)) {
ibmveth_error_printk("tx: unable to map initial fragment\n");
- adapter->tx_map_failed++;
- adapter->stats.tx_dropped++;
- dev_kfree_skb(skb);
- return 0;
+ tx_map_failed++;
+ tx_dropped++;
+ goto out;
}
curfrag = nfrags;
@@ -684,8 +668,8 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if(dma_mapping_error(desc[curfrag+1].fields.address)) {
ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
- adapter->tx_map_failed++;
- adapter->stats.tx_dropped++;
+ tx_map_failed++;
+ tx_dropped++;
/* Free all the mappings we just created */
while(curfrag < nfrags) {
dma_unmap_single(&adapter->vdev->dev,
@@ -694,8 +678,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
DMA_TO_DEVICE);
curfrag++;
}
- dev_kfree_skb(skb);
- return 0;
+ goto out;
}
}
@@ -720,11 +703,12 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i,
desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address);
}
- adapter->tx_send_failed++;
- adapter->stats.tx_dropped++;
+ tx_send_failed++;
+ tx_dropped++;
} else {
- adapter->stats.tx_packets++;
- adapter->stats.tx_bytes += skb->len;
+ tx_packets++;
+ tx_bytes += skb->len;
+ netdev->trans_start = jiffies;
}
do {
@@ -733,6 +717,14 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
desc[nfrags].fields.length, DMA_TO_DEVICE);
} while(--nfrags >= 0);
+out: spin_lock_irqsave(&adapter->stats_lock, flags);
+ adapter->stats.tx_dropped += tx_dropped;
+ adapter->stats.tx_bytes += tx_bytes;
+ adapter->stats.tx_packets += tx_packets;
+ adapter->tx_send_failed += tx_send_failed;
+ adapter->tx_map_failed += tx_map_failed;
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+
dev_kfree_skb(skb);
return 0;
}
@@ -776,13 +768,14 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
adapter->stats.rx_packets++;
adapter->stats.rx_bytes += length;
frames_processed++;
+ netdev->last_rx = jiffies;
}
} else {
more_work = 0;
}
} while(more_work && (frames_processed < max_frames_to_process));
- ibmveth_schedule_replenishing(adapter);
+ ibmveth_replenish_task(adapter);
if(more_work) {
/* more work to do - return that we are not done yet */
@@ -883,17 +876,54 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
{
- if ((new_mtu < 68) || (new_mtu > (1<<20)))
+ struct ibmveth_adapter *adapter = dev->priv;
+ int i;
+ int prev_smaller = 1;
+
+ if ((new_mtu < 68) ||
+ (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH))
return -EINVAL;
+
+ for(i = 0; i<IbmVethNumBufferPools; i++) {
+ int activate = 0;
+ if (new_mtu > (pool_size[i] - IBMVETH_BUFF_OH)) {
+ activate = 1;
+ prev_smaller= 1;
+ } else {
+ if (prev_smaller)
+ activate = 1;
+ prev_smaller= 0;
+ }
+
+ if (activate && !adapter->rx_buff_pool[i].active) {
+ struct ibmveth_buff_pool *pool =
+ &adapter->rx_buff_pool[i];
+ if(ibmveth_alloc_buffer_pool(pool)) {
+ ibmveth_error_printk("unable to alloc pool\n");
+ return -ENOMEM;
+ }
+ adapter->rx_buff_pool[i].active = 1;
+ } else if (!activate && adapter->rx_buff_pool[i].active) {
+ adapter->rx_buff_pool[i].active = 0;
+ h_free_logical_lan_buffer(adapter->vdev->unit_address,
+ (u64)pool_size[i]);
+ }
+
+ }
+
+ /* kick the interrupt handler so that the new buffer pools get
+ replenished or deallocated */
+ ibmveth_interrupt(dev->irq, dev, NULL);
+
dev->mtu = new_mtu;
return 0;
}
static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
{
- int rc;
+ int rc, i;
struct net_device *netdev;
- struct ibmveth_adapter *adapter;
+ struct ibmveth_adapter *adapter = NULL;
unsigned char *mac_addr_p;
unsigned int *mcastFilterSize_p;
@@ -960,23 +990,21 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
netdev->ethtool_ops = &netdev_ethtool_ops;
netdev->change_mtu = ibmveth_change_mtu;
SET_NETDEV_DEV(netdev, &dev->dev);
+ netdev->features |= NETIF_F_LLTX;
+ spin_lock_init(&adapter->stats_lock);
memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
- ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize);
- ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize);
- ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize);
+ for(i = 0; i<IbmVethNumBufferPools; i++)
+ ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
+ pool_count[i], pool_size[i]);
ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
- INIT_WORK(&adapter->replenish_task, (void*)ibmveth_replenish_task, (void*)adapter);
-
adapter->buffer_list_dma = DMA_ERROR_CODE;
adapter->filter_list_dma = DMA_ERROR_CODE;
adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
- atomic_set(&adapter->not_replenishing, 1);
-
ibmveth_debug_printk("registering netdev...\n");
rc = register_netdev(netdev);
@@ -1010,7 +1038,7 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
#ifdef CONFIG_PROC_FS
static void ibmveth_proc_register_driver(void)
{
- ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net);
+ ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL);
if (ibmveth_proc_dir) {
SET_MODULE_OWNER(ibmveth_proc_dir);
}
@@ -1018,7 +1046,7 @@ static void ibmveth_proc_register_driver(void)
static void ibmveth_proc_unregister_driver(void)
{
- remove_proc_entry(IBMVETH_PROC_DIR, proc_net);
+ remove_proc_entry(IBMVETH_PROC_DIR, NULL);
}
static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
@@ -1144,16 +1172,18 @@ static void ibmveth_proc_unregister_driver(void)
static struct vio_device_id ibmveth_device_table[] __devinitdata= {
{ "network", "IBM,l-lan"},
- { 0,}
+ { "", "" }
};
-
MODULE_DEVICE_TABLE(vio, ibmveth_device_table);
static struct vio_driver ibmveth_driver = {
- .name = (char *)ibmveth_driver_name,
- .id_table = ibmveth_device_table,
- .probe = ibmveth_probe,
- .remove = ibmveth_remove
+ .id_table = ibmveth_device_table,
+ .probe = ibmveth_probe,
+ .remove = ibmveth_remove,
+ .driver = {
+ .name = ibmveth_driver_name,
+ .owner = THIS_MODULE,
+ }
};
static int __init ibmveth_module_init(void)
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index 51a470da9686..46919a814fca 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -49,6 +49,7 @@
#define H_SEND_LOGICAL_LAN 0x120
#define H_MULTICAST_CTRL 0x130
#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
/* hcall macros */
#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
@@ -69,13 +70,15 @@
#define h_change_logical_lan_mac(ua, mac) \
plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
-#define IbmVethNumBufferPools 3
-#define IbmVethPool0DftSize (1024 * 2)
-#define IbmVethPool1DftSize (1024 * 4)
-#define IbmVethPool2DftSize (1024 * 10)
-#define IbmVethPool0DftCnt 256
-#define IbmVethPool1DftCnt 256
-#define IbmVethPool2DftCnt 256
+#define h_free_logical_lan_buffer(ua, bufsize) \
+ plpar_hcall_norets(H_FREE_LOGICAL_LAN_BUFFER, ua, bufsize)
+
+#define IbmVethNumBufferPools 5
+#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
+
+/* pool_size should be sorted */
+static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
+static int pool_count[] = { 256, 768, 256, 256, 256 };
#define IBM_VETH_INVALID_MAP ((u16)0xffff)
@@ -90,6 +93,7 @@ struct ibmveth_buff_pool {
u16 *free_map;
dma_addr_t *dma_addr;
struct sk_buff **skbuff;
+ int active;
};
struct ibmveth_rx_q {
@@ -114,10 +118,6 @@ struct ibmveth_adapter {
dma_addr_t filter_list_dma;
struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
struct ibmveth_rx_q rx_queue;
- atomic_t not_replenishing;
-
- /* helper tasks */
- struct work_struct replenish_task;
/* adapter specific stats */
u64 replenish_task_cycles;
@@ -131,6 +131,7 @@ struct ibmveth_adapter {
u64 tx_linearize_failed;
u64 tx_map_failed;
u64 tx_send_failed;
+ spinlock_t stats_lock;
};
struct ibmveth_buf_desc_fields {
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index d520b5920d6c..49e5467bdd73 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -499,7 +499,7 @@ static int ioc3_mdio_read(struct net_device *dev, int phy, int reg)
ioc3_w_micr((phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG);
while (ioc3_r_micr() & MICR_BUSY);
- return ioc3_r_micr() & MIDR_DATA_MASK;
+ return ioc3_r_midr_r() & MIDR_DATA_MASK;
}
static void ioc3_mdio_write(struct net_device *dev, int phy, int reg, int data)
@@ -1291,7 +1291,6 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->features = NETIF_F_IP_CSUM;
#endif
- ioc3_setup_duplex(ip);
sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1);
sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2);
@@ -1300,6 +1299,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_stop;
mii_check_media(&ip->mii, 1, 1);
+ ioc3_setup_duplex(ip);
vendor = (sw_physid1 << 12) | (sw_physid2 >> 4);
model = (sw_physid2 >> 4) & 0x3f;
@@ -1524,7 +1524,7 @@ static void ioc3_get_drvinfo (struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct ioc3_private *ip = netdev_priv(dev);
-
+
strcpy (info->driver, IOC3_NAME);
strcpy (info->version, IOC3_VERSION);
strcpy (info->bus_info, pci_name(ip->pdev));
@@ -1550,7 +1550,7 @@ static int ioc3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
spin_lock_irq(&ip->ioc3_lock);
rc = mii_ethtool_sset(&ip->mii, cmd);
spin_unlock_irq(&ip->ioc3_lock);
-
+
return rc;
}
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index ca5914091d3a..d54156f11e61 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -400,5 +400,15 @@ config VIA_FIR
To compile it as a module, choose M here: the module will be called
via-ircc.
+config PXA_FICP
+ tristate "Intel PXA2xx Internal FICP"
+ depends on ARCH_PXA && IRDA
+ help
+ Say Y or M here if you want to build support for the PXA2xx
+ built-in IRDA interface which can support both SIR and FIR.
+ This driver relies on platform specific helper routines so
+ available capabilities may vary from one PXA2xx target to
+ another.
+
endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 29a8bd812b21..e7a8b7f7f5dd 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
obj-$(CONFIG_VIA_FIR) += via-ircc.o
+obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 0a08c539c051..0282771b1cbb 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1695,11 +1695,9 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
freebufs:
for (i = 0; i < TX_SLOTS; ++i)
- if (self->tx_bufs[i])
- kfree (self->tx_bufs[i]);
+ kfree (self->tx_bufs[i]);
for (i = 0; i < RX_SLOTS; ++i)
- if (self->rx_bufs[i])
- kfree (self->rx_bufs[i]);
+ kfree (self->rx_bufs[i]);
kfree(self->ringbuf);
freeregion:
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 46e0022d3258..c22c0517883c 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER;
- urb->transfer_flags = URB_ASYNC_UNLINK;
+ urb->transfer_flags = 0;
/* Irq disabled -> GFP_ATOMIC */
if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
@@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
skb->data, IRDA_SKB_MAX_MTU,
write_bulk_callback, skb);
urb->transfer_buffer_length = skb->len;
- /* Note : unlink *must* be Asynchronous because of the code in
- * irda_usb_net_timeout() -> call in irq - Jean II */
- urb->transfer_flags = URB_ASYNC_UNLINK;
/* This flag (URB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD)
* after each of our packets that is exact multiple of the frame size.
* This is how the dongle will detect the end of packet - Jean II */
- urb->transfer_flags |= URB_ZERO_PACKET;
+ urb->transfer_flags = URB_ZERO_PACKET;
/* Generate min turn time. FIXME: can we do better than this? */
/* Trying to a turnaround time at this level is trying to measure
@@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* in completion handler, because urb->status will
* be -ENOENT. We will fix that at the next watchdog,
* leaving more time to USB to recover...
- * Also, we are in interrupt, so we need to have
- * URB_ASYNC_UNLINK to work properly...
* Jean II */
done = 1;
break;
@@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev)
}
}
/* Cancel Tx and speed URB - need to be synchronous to avoid races */
- self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->tx_urb);
- self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->speed_urb);
/* Stop and remove instance of IrLAP */
@@ -1175,10 +1168,8 @@ static inline void irda_usb_close(struct irda_usb_cb *self)
unregister_netdev(self->netdev);
/* Remove the speed buffer */
- if (self->speed_buff != NULL) {
- kfree(self->speed_buff);
- self->speed_buff = NULL;
- }
+ kfree(self->speed_buff);
+ self->speed_buff = NULL;
}
/********************** USB CONFIG SUBROUTINES **********************/
@@ -1521,9 +1512,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Toggle flags to make sure it's synchronous. */
- self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->tx_urb);
- self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
usb_kill_urb(self->speed_urb);
}
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 5971315f3fa0..3d016a498e1d 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -235,8 +235,7 @@ static int irport_close(struct irport_cb *self)
__FUNCTION__, self->io.sir_base);
release_region(self->io.sir_base, self->io.sir_ext);
- if (self->tx_buff.head)
- kfree(self->tx_buff.head);
+ kfree(self->tx_buff.head);
if (self->rx_buff.skb)
kfree_skb(self->rx_buff.skb);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
new file mode 100644
index 000000000000..e1aa9910503b
--- /dev/null
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -0,0 +1,866 @@
+/*
+ * linux/drivers/net/irda/pxaficp_ir.c
+ *
+ * Based on sa1100_ir.c by Russell King
+ *
+ * Changes copyright (C) 2003-2005 MontaVista Software, 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.
+ *
+ * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa-regs.h>
+
+#ifdef CONFIG_MACH_MAINSTONE
+#include <asm/arch/mainstone.h>
+#endif
+
+#define IrSR_RXPL_NEG_IS_ZERO (1<<4)
+#define IrSR_RXPL_POS_IS_ZERO 0x0
+#define IrSR_TXPL_NEG_IS_ZERO (1<<3)
+#define IrSR_TXPL_POS_IS_ZERO 0x0
+#define IrSR_XMODE_PULSE_1_6 (1<<2)
+#define IrSR_XMODE_PULSE_3_16 0x0
+#define IrSR_RCVEIR_IR_MODE (1<<1)
+#define IrSR_RCVEIR_UART_MODE 0x0
+#define IrSR_XMITIR_IR_MODE (1<<0)
+#define IrSR_XMITIR_UART_MODE 0x0
+
+#define IrSR_IR_RECEIVE_ON (\
+ IrSR_RXPL_NEG_IS_ZERO | \
+ IrSR_TXPL_POS_IS_ZERO | \
+ IrSR_XMODE_PULSE_3_16 | \
+ IrSR_RCVEIR_IR_MODE | \
+ IrSR_XMITIR_UART_MODE)
+
+#define IrSR_IR_TRANSMIT_ON (\
+ IrSR_RXPL_NEG_IS_ZERO | \
+ IrSR_TXPL_POS_IS_ZERO | \
+ IrSR_XMODE_PULSE_3_16 | \
+ IrSR_RCVEIR_UART_MODE | \
+ IrSR_XMITIR_IR_MODE)
+
+struct pxa_irda {
+ int speed;
+ int newspeed;
+ unsigned long last_oscr;
+
+ unsigned char *dma_rx_buff;
+ unsigned char *dma_tx_buff;
+ dma_addr_t dma_rx_buff_phy;
+ dma_addr_t dma_tx_buff_phy;
+ unsigned int dma_tx_buff_len;
+ int txdma;
+ int rxdma;
+
+ struct net_device_stats stats;
+ struct irlap_cb *irlap;
+ struct qos_info qos;
+
+ iobuff_t tx_buff;
+ iobuff_t rx_buff;
+
+ struct device *dev;
+ struct pxaficp_platform_data *pdata;
+};
+
+
+#define IS_FIR(si) ((si)->speed >= 4000000)
+#define IRDA_FRAME_SIZE_LIMIT 2047
+
+inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
+{
+ DCSR(si->rxdma) = DCSR_NODESC;
+ DSADR(si->rxdma) = __PREG(ICDR);
+ DTADR(si->rxdma) = si->dma_rx_buff_phy;
+ DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
+ DCSR(si->rxdma) |= DCSR_RUN;
+}
+
+inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
+{
+ DCSR(si->txdma) = DCSR_NODESC;
+ DSADR(si->txdma) = si->dma_tx_buff_phy;
+ DTADR(si->txdma) = __PREG(ICDR);
+ DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
+ DCSR(si->txdma) |= DCSR_RUN;
+}
+
+/*
+ * Set the IrDA communications speed.
+ */
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
+{
+ unsigned long flags;
+ unsigned int divisor;
+
+ switch (speed) {
+ case 9600: case 19200: case 38400:
+ case 57600: case 115200:
+
+ /* refer to PXA250/210 Developer's Manual 10-7 */
+ /* BaudRate = 14.7456 MHz / (16*Divisor) */
+ divisor = 14745600 / (16 * speed);
+
+ local_irq_save(flags);
+
+ if (IS_FIR(si)) {
+ /* stop RX DMA */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ /* disable FICP */
+ ICCR0 = 0;
+ pxa_set_cken(CKEN13_FICP, 0);
+
+ /* set board transceiver to SIR mode */
+ si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
+
+ /* configure GPIO46/47 */
+ pxa_gpio_mode(GPIO46_STRXD_MD);
+ pxa_gpio_mode(GPIO47_STTXD_MD);
+
+ /* enable the STUART clock */
+ pxa_set_cken(CKEN5_STUART, 1);
+ }
+
+ /* disable STUART first */
+ STIER = 0;
+
+ /* access DLL & DLH */
+ STLCR |= LCR_DLAB;
+ STDLL = divisor & 0xff;
+ STDLH = divisor >> 8;
+ STLCR &= ~LCR_DLAB;
+
+ si->speed = speed;
+ STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+
+ local_irq_restore(flags);
+ break;
+
+ case 4000000:
+ local_irq_save(flags);
+
+ /* disable STUART */
+ STIER = 0;
+ STISR = 0;
+ pxa_set_cken(CKEN5_STUART, 0);
+
+ /* disable FICP first */
+ ICCR0 = 0;
+
+ /* set board transceiver to FIR mode */
+ si->pdata->transceiver_mode(si->dev, IR_FIRMODE);
+
+ /* configure GPIO46/47 */
+ pxa_gpio_mode(GPIO46_ICPRXD_MD);
+ pxa_gpio_mode(GPIO47_ICPTXD_MD);
+
+ /* enable the FICP clock */
+ pxa_set_cken(CKEN13_FICP, 1);
+
+ si->speed = speed;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ local_irq_restore(flags);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* SIR interrupt service routine. */
+static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct pxa_irda *si = netdev_priv(dev);
+ int iir, lsr, data;
+
+ iir = STIIR;
+
+ switch (iir & 0x0F) {
+ case 0x06: /* Receiver Line Status */
+ lsr = STLSR;
+ while (lsr & LSR_FIFOE) {
+ data = STRBR;
+ if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
+ printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
+ si->stats.rx_errors++;
+ if (lsr & LSR_FE)
+ si->stats.rx_frame_errors++;
+ if (lsr & LSR_OE)
+ si->stats.rx_fifo_errors++;
+ } else {
+ si->stats.rx_bytes++;
+ async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+ }
+ lsr = STLSR;
+ }
+ dev->last_rx = jiffies;
+ si->last_oscr = OSCR;
+ break;
+
+ case 0x04: /* Received Data Available */
+ /* forth through */
+
+ case 0x0C: /* Character Timeout Indication */
+ do {
+ si->stats.rx_bytes++;
+ async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
+ } while (STLSR & LSR_DR);
+ dev->last_rx = jiffies;
+ si->last_oscr = OSCR;
+ break;
+
+ case 0x02: /* Transmit FIFO Data Request */
+ while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
+ STTHR = *si->tx_buff.data++;
+ si->tx_buff.len -= 1;
+ }
+
+ if (si->tx_buff.len == 0) {
+ si->stats.tx_packets++;
+ si->stats.tx_bytes += si->tx_buff.data -
+ si->tx_buff.head;
+
+ /* We need to ensure that the transmitter has finished. */
+ while ((STLSR & LSR_TEMT) == 0)
+ cpu_relax();
+ si->last_oscr = OSCR;
+
+ /*
+ * Ok, we've finished transmitting. Now enable
+ * the receiver. Sometimes we get a receive IRQ
+ * immediately after a transmit...
+ */
+ if (si->newspeed) {
+ pxa_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
+ } else {
+ /* enable IR Receiver, disable IR Transmitter */
+ STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ /* enable STUART and receive interrupts */
+ STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ }
+ /* I'm hungry! */
+ netif_wake_queue(dev);
+ }
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* FIR Receive DMA interrupt handler */
+static void pxa_irda_fir_dma_rx_irq(int channel, void *data, struct pt_regs *regs)
+{
+ int dcsr = DCSR(channel);
+
+ DCSR(channel) = dcsr & ~DCSR_RUN;
+
+ printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
+}
+
+/* FIR Transmit DMA interrupt handler */
+static void pxa_irda_fir_dma_tx_irq(int channel, void *data, struct pt_regs *regs)
+{
+ struct net_device *dev = data;
+ struct pxa_irda *si = netdev_priv(dev);
+ int dcsr;
+
+ dcsr = DCSR(channel);
+ DCSR(channel) = dcsr & ~DCSR_RUN;
+
+ if (dcsr & DCSR_ENDINTR) {
+ si->stats.tx_packets++;
+ si->stats.tx_bytes += si->dma_tx_buff_len;
+ } else {
+ si->stats.tx_errors++;
+ }
+
+ while (ICSR1 & ICSR1_TBY)
+ cpu_relax();
+ si->last_oscr = OSCR;
+
+ /*
+ * HACK: It looks like the TBY bit is dropped too soon.
+ * Without this delay things break.
+ */
+ udelay(120);
+
+ if (si->newspeed) {
+ pxa_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
+ } else {
+ ICCR0 = 0;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ }
+ netif_wake_queue(dev);
+}
+
+/* EIF(Error in FIFO/End in Frame) handler for FIR */
+static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
+{
+ unsigned int len, stat, data;
+
+ /* Get the current data position. */
+ len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+
+ do {
+ /* Read Status, and then Data. */
+ stat = ICSR1;
+ rmb();
+ data = ICDR;
+
+ if (stat & (ICSR1_CRE | ICSR1_ROR)) {
+ si->stats.rx_errors++;
+ if (stat & ICSR1_CRE) {
+ printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n");
+ si->stats.rx_crc_errors++;
+ }
+ if (stat & ICSR1_ROR) {
+ printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
+ si->stats.rx_frame_errors++;
+ }
+ } else {
+ si->dma_rx_buff[len++] = data;
+ }
+ /* If we hit the end of frame, there's no point in continuing. */
+ if (stat & ICSR1_EOF)
+ break;
+ } while (ICSR0 & ICSR0_EIF);
+
+ if (stat & ICSR1_EOF) {
+ /* end of frame. */
+ struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
+ si->stats.rx_dropped++;
+ return;
+ }
+
+ /* Align IP header to 20 bytes */
+ skb_reserve(skb, 1);
+ memcpy(skb->data, si->dma_rx_buff, len);
+ skb_put(skb, len);
+
+ /* Feed it to IrLAP */
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx(skb);
+
+ si->stats.rx_packets++;
+ si->stats.rx_bytes += len;
+
+ dev->last_rx = jiffies;
+ }
+}
+
+/* FIR interrupt handler */
+static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct pxa_irda *si = netdev_priv(dev);
+ int icsr0;
+
+ /* stop RX DMA */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ si->last_oscr = OSCR;
+ icsr0 = ICSR0;
+
+ if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
+ if (icsr0 & ICSR0_FRE) {
+ printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
+ si->stats.rx_frame_errors++;
+ } else {
+ printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
+ si->stats.rx_errors++;
+ }
+ ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+ }
+
+ if (icsr0 & ICSR0_EIF) {
+ /* An error in FIFO occured, or there is a end of frame */
+ pxa_irda_fir_irq_eif(si, dev);
+ }
+
+ ICCR0 = 0;
+ pxa_irda_fir_dma_rx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ return IRQ_HANDLED;
+}
+
+/* hard_xmit interface of irda device */
+static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ int speed = irda_get_next_speed(skb);
+
+ /*
+ * Does this packet contain a request to change the interface
+ * speed? If so, remember it until we complete the transmission
+ * of this frame.
+ */
+ if (speed != si->speed && speed != -1)
+ si->newspeed = speed;
+
+ /*
+ * If this is an empty frame, we can bypass a lot.
+ */
+ if (skb->len == 0) {
+ if (si->newspeed) {
+ si->newspeed = 0;
+ pxa_irda_set_speed(si, speed);
+ }
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ netif_stop_queue(dev);
+
+ if (!IS_FIR(si)) {
+ si->tx_buff.data = si->tx_buff.head;
+ si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
+
+ /* Disable STUART interrupts and switch to transmit mode. */
+ STIER = 0;
+ STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+
+ /* enable STUART and transmit interrupts */
+ STIER = IER_UUE | IER_TIE;
+ } else {
+ unsigned long mtt = irda_get_mtt(skb);
+
+ si->dma_tx_buff_len = skb->len;
+ memcpy(si->dma_tx_buff, skb->data, skb->len);
+
+ if (mtt)
+ while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
+ cpu_relax();
+
+ /* stop RX DMA, disable FICP */
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ ICCR0 = 0;
+
+ pxa_irda_fir_dma_tx_start(si);
+ ICCR0 = ICCR0_ITR | ICCR0_TXE;
+ }
+
+ dev_kfree_skb(skb);
+ dev->trans_start = jiffies;
+ return 0;
+}
+
+static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+ struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+ struct pxa_irda *si = netdev_priv(dev);
+ int ret;
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH:
+ ret = -EPERM;
+ if (capable(CAP_NET_ADMIN)) {
+ /*
+ * We are unable to set the speed if the
+ * device is not running.
+ */
+ if (netif_running(dev)) {
+ ret = pxa_irda_set_speed(si,
+ rq->ifr_baudrate);
+ } else {
+ printk(KERN_INFO "pxa_ir: SIOCSBANDWIDTH: !netif_running\n");
+ ret = 0;
+ }
+ }
+ break;
+
+ case SIOCSMEDIABUSY:
+ ret = -EPERM;
+ if (capable(CAP_NET_ADMIN)) {
+ irda_device_set_media_busy(dev, TRUE);
+ ret = 0;
+ }
+ break;
+
+ case SIOCGRECEIVING:
+ ret = 0;
+ rq->ifr_receiving = IS_FIR(si) ? 0
+ : si->rx_buff.state != OUTSIDE_FRAME;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static struct net_device_stats *pxa_irda_stats(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ return &si->stats;
+}
+
+static void pxa_irda_startup(struct pxa_irda *si)
+{
+ /* Disable STUART interrupts */
+ STIER = 0;
+ /* enable STUART interrupt to the processor */
+ STMCR = MCR_OUT2;
+ /* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
+ STLCR = LCR_WLS0 | LCR_WLS1;
+ /* enable FIFO, we use FIFO to improve performance */
+ STFCR = FCR_TRFIFOE | FCR_ITL_32;
+
+ /* disable FICP */
+ ICCR0 = 0;
+ /* configure FICP ICCR2 */
+ ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
+
+ /* configure DMAC */
+ DRCMR17 = si->rxdma | DRCMR_MAPVLD;
+ DRCMR18 = si->txdma | DRCMR_MAPVLD;
+
+ /* force SIR reinitialization */
+ si->speed = 4000000;
+ pxa_irda_set_speed(si, 9600);
+
+ printk(KERN_DEBUG "pxa_ir: irda startup\n");
+}
+
+static void pxa_irda_shutdown(struct pxa_irda *si)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* disable STUART and interrupt */
+ STIER = 0;
+ /* disable STUART SIR mode */
+ STISR = 0;
+ /* disable the STUART clock */
+ pxa_set_cken(CKEN5_STUART, 0);
+
+ /* disable DMA */
+ DCSR(si->txdma) &= ~DCSR_RUN;
+ DCSR(si->rxdma) &= ~DCSR_RUN;
+ /* disable FICP */
+ ICCR0 = 0;
+ /* disable the FICP clock */
+ pxa_set_cken(CKEN13_FICP, 0);
+
+ DRCMR17 = 0;
+ DRCMR18 = 0;
+
+ local_irq_restore(flags);
+
+ /* power off board transceiver */
+ si->pdata->transceiver_mode(si->dev, IR_OFF);
+
+ printk(KERN_DEBUG "pxa_ir: irda shutdown\n");
+}
+
+static int pxa_irda_start(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+ int err;
+
+ si->speed = 9600;
+
+ err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
+ if (err)
+ goto err_irq1;
+
+ err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
+ if (err)
+ goto err_irq2;
+
+ /*
+ * The interrupt must remain disabled for now.
+ */
+ disable_irq(IRQ_STUART);
+ disable_irq(IRQ_ICP);
+
+ err = -EBUSY;
+ si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
+ if (si->rxdma < 0)
+ goto err_rx_dma;
+
+ si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
+ if (si->txdma < 0)
+ goto err_tx_dma;
+
+ err = -ENOMEM;
+ si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+ &si->dma_rx_buff_phy, GFP_KERNEL );
+ if (!si->dma_rx_buff)
+ goto err_dma_rx_buff;
+
+ si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+ &si->dma_tx_buff_phy, GFP_KERNEL );
+ if (!si->dma_tx_buff)
+ goto err_dma_tx_buff;
+
+ /* Setup the serial port for the initial speed. */
+ pxa_irda_startup(si);
+
+ /*
+ * Open a new IrLAP layer instance.
+ */
+ si->irlap = irlap_open(dev, &si->qos, "pxa");
+ err = -ENOMEM;
+ if (!si->irlap)
+ goto err_irlap;
+
+ /*
+ * Now enable the interrupt and start the queue
+ */
+ enable_irq(IRQ_STUART);
+ enable_irq(IRQ_ICP);
+ netif_start_queue(dev);
+
+ printk(KERN_DEBUG "pxa_ir: irda driver opened\n");
+
+ return 0;
+
+err_irlap:
+ pxa_irda_shutdown(si);
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+err_dma_tx_buff:
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+err_dma_rx_buff:
+ pxa_free_dma(si->txdma);
+err_tx_dma:
+ pxa_free_dma(si->rxdma);
+err_rx_dma:
+ free_irq(IRQ_ICP, dev);
+err_irq2:
+ free_irq(IRQ_STUART, dev);
+err_irq1:
+
+ return err;
+}
+
+static int pxa_irda_stop(struct net_device *dev)
+{
+ struct pxa_irda *si = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ pxa_irda_shutdown(si);
+
+ /* Stop IrLAP */
+ if (si->irlap) {
+ irlap_close(si->irlap);
+ si->irlap = NULL;
+ }
+
+ free_irq(IRQ_STUART, dev);
+ free_irq(IRQ_ICP, dev);
+
+ pxa_free_dma(si->rxdma);
+ pxa_free_dma(si->txdma);
+
+ if (si->dma_rx_buff)
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+ if (si->dma_tx_buff)
+ dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+
+ printk(KERN_DEBUG "pxa_ir: irda driver closed\n");
+ return 0;
+}
+
+static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+ struct pxa_irda *si;
+
+ if (dev && netif_running(dev)) {
+ si = netdev_priv(dev);
+ netif_device_detach(dev);
+ pxa_irda_shutdown(si);
+ }
+
+ return 0;
+}
+
+static int pxa_irda_resume(struct device *_dev)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+ struct pxa_irda *si;
+
+ if (dev && netif_running(dev)) {
+ si = netdev_priv(dev);
+ pxa_irda_startup(si);
+ netif_device_attach(dev);
+ netif_wake_queue(dev);
+ }
+
+ return 0;
+}
+
+
+static int pxa_irda_init_iobuf(iobuff_t *io, int size)
+{
+ io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
+ if (io->head != NULL) {
+ io->truesize = size;
+ io->in_frame = FALSE;
+ io->state = OUTSIDE_FRAME;
+ io->data = io->head;
+ }
+ return io->head ? 0 : -ENOMEM;
+}
+
+static int pxa_irda_probe(struct device *_dev)
+{
+ struct platform_device *pdev = to_platform_device(_dev);
+ struct net_device *dev;
+ struct pxa_irda *si;
+ unsigned int baudrate_mask;
+ int err;
+
+ if (!pdev->dev.platform_data)
+ return -ENODEV;
+
+ err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
+ if (err)
+ goto err_mem_1;
+
+ err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
+ if (err)
+ goto err_mem_2;
+
+ dev = alloc_irdadev(sizeof(struct pxa_irda));
+ if (!dev)
+ goto err_mem_3;
+
+ si = netdev_priv(dev);
+ si->dev = &pdev->dev;
+ si->pdata = pdev->dev.platform_data;
+
+ /*
+ * Initialise the SIR buffers
+ */
+ err = pxa_irda_init_iobuf(&si->rx_buff, 14384);
+ if (err)
+ goto err_mem_4;
+ err = pxa_irda_init_iobuf(&si->tx_buff, 4000);
+ if (err)
+ goto err_mem_5;
+
+ dev->hard_start_xmit = pxa_irda_hard_xmit;
+ dev->open = pxa_irda_start;
+ dev->stop = pxa_irda_stop;
+ dev->do_ioctl = pxa_irda_ioctl;
+ dev->get_stats = pxa_irda_stats;
+
+ irda_init_max_qos_capabilies(&si->qos);
+
+ baudrate_mask = 0;
+ if (si->pdata->transceiver_cap & IR_SIRMODE)
+ baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ if (si->pdata->transceiver_cap & IR_FIRMODE)
+ baudrate_mask |= IR_4000000 << 8;
+
+ si->qos.baud_rate.bits &= baudrate_mask;
+ si->qos.min_turn_time.bits = 7; /* 1ms or more */
+
+ irda_qos_bits_to_value(&si->qos);
+
+ err = register_netdev(dev);
+
+ if (err == 0)
+ dev_set_drvdata(&pdev->dev, dev);
+
+ if (err) {
+ kfree(si->tx_buff.head);
+err_mem_5:
+ kfree(si->rx_buff.head);
+err_mem_4:
+ free_netdev(dev);
+err_mem_3:
+ release_mem_region(__PREG(FICP), 0x1c);
+err_mem_2:
+ release_mem_region(__PREG(STUART), 0x24);
+ }
+err_mem_1:
+ return err;
+}
+
+static int pxa_irda_remove(struct device *_dev)
+{
+ struct net_device *dev = dev_get_drvdata(_dev);
+
+ if (dev) {
+ struct pxa_irda *si = netdev_priv(dev);
+ unregister_netdev(dev);
+ kfree(si->tx_buff.head);
+ kfree(si->rx_buff.head);
+ free_netdev(dev);
+ }
+
+ release_mem_region(__PREG(STUART), 0x24);
+ release_mem_region(__PREG(FICP), 0x1c);
+
+ return 0;
+}
+
+static struct device_driver pxa_ir_driver = {
+ .name = "pxa2xx-ir",
+ .bus = &platform_bus_type,
+ .probe = pxa_irda_probe,
+ .remove = pxa_irda_remove,
+ .suspend = pxa_irda_suspend,
+ .resume = pxa_irda_resume,
+};
+
+static int __init pxa_irda_init(void)
+{
+ return driver_register(&pxa_ir_driver);
+}
+
+static void __exit pxa_irda_exit(void)
+{
+ driver_unregister(&pxa_ir_driver);
+}
+
+module_init(pxa_irda_init);
+module_exit(pxa_irda_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 8d34ac60d906..76e0b9fb5e96 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -29,7 +29,7 @@
#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <net/irda/irda.h>
@@ -291,12 +291,12 @@ static void sa1100_irda_shutdown(struct sa1100_irda *si)
/*
* Suspend the IrDA interface.
*/
-static int sa1100_irda_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_irda_suspend(struct device *_dev, pm_message_t state)
{
struct net_device *dev = dev_get_drvdata(_dev);
struct sa1100_irda *si;
- if (!dev || level != SUSPEND_DISABLE)
+ if (!dev)
return 0;
si = dev->priv;
@@ -316,12 +316,12 @@ static int sa1100_irda_suspend(struct device *_dev, pm_message_t state, u32 leve
/*
* Resume the IrDA interface.
*/
-static int sa1100_irda_resume(struct device *_dev, u32 level)
+static int sa1100_irda_resume(struct device *_dev)
{
struct net_device *dev = dev_get_drvdata(_dev);
struct sa1100_irda *si;
- if (!dev || level != RESUME_ENABLE)
+ if (!dev)
return 0;
si = dev->priv;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index efc5a8870565..df22b8b532e7 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -490,8 +490,7 @@ static void sirdev_free_buffers(struct sir_dev *dev)
{
if (dev->rx_buff.skb)
kfree_skb(dev->rx_buff.skb);
- if (dev->tx_buff.head)
- kfree(dev->tx_buff.head);
+ kfree(dev->tx_buff.head);
dev->rx_buff.head = dev->tx_buff.head = NULL;
dev->rx_buff.skb = NULL;
}
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 10125a1dba22..a1d207f2fa68 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -4,10 +4,10 @@
* Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Daniele Peri (peri@csai.unipa.it)
- * Created at:
- * Modified at:
- * Modified by:
- *
+ * Created at:
+ * Modified at:
+ * Modified by:
+ *
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
@@ -17,26 +17,26 @@
*
* Copyright (c) 2001 Stefani Seibold
* Copyright (c) 1999-2001 Dag Brattli
- * Copyright (c) 1998-1999 Thomas Davis,
+ * Copyright (c) 1998-1999 Thomas Davis,
*
* and irport.c:
*
* Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, 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
+ *
+ * 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,
+ *
+ * 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
*
********************************************************************/
@@ -53,6 +53,7 @@
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -68,24 +69,42 @@
#include "smsc-ircc2.h"
#include "smsc-sio.h"
+
+MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
+MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
+MODULE_LICENSE("GPL");
+
+static int ircc_dma = 255;
+module_param(ircc_dma, int, 0);
+MODULE_PARM_DESC(ircc_dma, "DMA channel");
+
+static int ircc_irq = 255;
+module_param(ircc_irq, int, 0);
+MODULE_PARM_DESC(ircc_irq, "IRQ line");
+
+static int ircc_fir;
+module_param(ircc_fir, int, 0);
+MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
+
+static int ircc_sir;
+module_param(ircc_sir, int, 0);
+MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
+
+static int ircc_cfg;
+module_param(ircc_cfg, int, 0);
+MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
+
+static int ircc_transceiver;
+module_param(ircc_transceiver, int, 0);
+MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
+
/* Types */
struct smsc_transceiver {
char *name;
- void (*set_for_speed)(int fir_base, u32 speed);
+ void (*set_for_speed)(int fir_base, u32 speed);
int (*probe)(int fir_base);
};
-typedef struct smsc_transceiver smsc_transceiver_t;
-
-#if 0
-struct smc_chip {
- char *name;
- u16 flags;
- u8 devid;
- u8 rev;
-};
-typedef struct smc_chip smc_chip_t;
-#endif
struct smsc_chip {
char *name;
@@ -96,20 +115,18 @@ struct smsc_chip {
u8 devid;
u8 rev;
};
-typedef struct smsc_chip smsc_chip_t;
struct smsc_chip_address {
unsigned int cfg_base;
unsigned int type;
};
-typedef struct smsc_chip_address smsc_chip_address_t;
/* Private data for each instance */
struct smsc_ircc_cb {
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
-
+
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
@@ -119,7 +136,7 @@ struct smsc_ircc_cb {
struct qos_info qos; /* QoS capabilities for this device */
spinlock_t lock; /* For serializing operations */
-
+
__u32 new_speed;
__u32 flags; /* Interface flags */
@@ -127,18 +144,20 @@ struct smsc_ircc_cb {
int tx_len; /* Number of frames in tx_buff */
int transceiver;
- struct pm_dev *pmdev;
+ struct platform_device *pldev;
};
/* Constants */
-static const char *driver_name = "smsc-ircc2";
-#define DIM(x) (sizeof(x)/(sizeof(*(x))))
+#define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2"
+
#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600
#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1
-#define SMSC_IRCC2_C_NET_TIMEOUT 0
+#define SMSC_IRCC2_C_NET_TIMEOUT 0
#define SMSC_IRCC2_C_SIR_STOP 0
+static const char *driver_name = SMSC_IRCC2_DRIVER_NAME;
+
/* Prototypes */
static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
@@ -147,15 +166,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base,
static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
-static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase);
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase);
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self);
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self);
static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self);
static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs);
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase);
-static void smsc_ircc_change_speed(void *priv, u32 speed);
-static void smsc_ircc_set_sir_speed(void *priv, u32 speed);
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs);
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self);
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed);
+static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed);
static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev);
static void smsc_ircc_sir_start(struct smsc_ircc_cb *self);
@@ -171,7 +190,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm
static void smsc_ircc_timeout(struct net_device *dev);
#endif
static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
@@ -179,9 +197,9 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self);
/* Probing */
static int __init smsc_ircc_look_for_chips(void);
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type);
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type);
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
+static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
static int __init smsc_superio_fdc(unsigned short cfg_base);
static int __init smsc_superio_lpc(unsigned short cfg_base);
@@ -196,21 +214,26 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
/* Power Management */
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self);
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self);
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state);
+static int smsc_ircc_resume(struct device *dev);
+static struct device_driver smsc_ircc_driver = {
+ .name = SMSC_IRCC2_DRIVER_NAME,
+ .bus = &platform_bus_type,
+ .suspend = smsc_ircc_suspend,
+ .resume = smsc_ircc_resume,
+};
/* Transceivers for SMSC-ircc */
-static smsc_transceiver_t smsc_transceivers[]=
+static struct smsc_transceiver smsc_transceivers[] =
{
- { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
- { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
- { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc},
- { NULL, NULL}
+ { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800 },
+ { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select },
+ { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc },
+ { NULL, NULL }
};
-#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1)
+#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (ARRAY_SIZE(smsc_transceivers) - 1)
/* SMC SuperIO chipsets definitions */
@@ -221,7 +244,7 @@ static smsc_transceiver_t smsc_transceivers[]=
#define FIR 4 /* SuperIO Chip has fast IRDA */
#define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
-static smsc_chip_t __initdata fdc_chips_flat[]=
+static struct smsc_chip __initdata fdc_chips_flat[] =
{
/* Base address 0x3f0 or 0x370 */
{ "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip cannot be detected */
@@ -235,7 +258,7 @@ static smsc_chip_t __initdata fdc_chips_flat[]=
{ NULL }
};
-static smsc_chip_t __initdata fdc_chips_paged[]=
+static struct smsc_chip __initdata fdc_chips_paged[] =
{
/* Base address 0x3f0 or 0x370 */
{ "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 },
@@ -254,7 +277,7 @@ static smsc_chip_t __initdata fdc_chips_paged[]=
{ NULL }
};
-static smsc_chip_t __initdata lpc_chips_flat[]=
+static struct smsc_chip __initdata lpc_chips_flat[] =
{
/* Base address 0x2E or 0x4E */
{ "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 },
@@ -262,7 +285,7 @@ static smsc_chip_t __initdata lpc_chips_flat[]=
{ NULL }
};
-static smsc_chip_t __initdata lpc_chips_paged[]=
+static struct smsc_chip __initdata lpc_chips_paged[] =
{
/* Base address 0x2E or 0x4E */
{ "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 },
@@ -281,33 +304,25 @@ static smsc_chip_t __initdata lpc_chips_paged[]=
#define SMSCSIO_TYPE_FLAT 4
#define SMSCSIO_TYPE_PAGED 8
-static smsc_chip_address_t __initdata possible_addresses[]=
+static struct smsc_chip_address __initdata possible_addresses[] =
{
- {0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
- {0,0}
+ { 0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED },
+ { 0, 0 }
};
/* Globals */
-static struct smsc_ircc_cb *dev_self[] = { NULL, NULL};
-
-static int ircc_irq=255;
-static int ircc_dma=255;
-static int ircc_fir=0;
-static int ircc_sir=0;
-static int ircc_cfg=0;
-static int ircc_transceiver=0;
-
-static unsigned short dev_count=0;
+static struct smsc_ircc_cb *dev_self[] = { NULL, NULL };
+static unsigned short dev_count;
static inline void register_bank(int iobase, int bank)
{
- outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
- iobase+IRCC_MASTER);
+ outb(((inb(iobase + IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+ iobase + IRCC_MASTER);
}
@@ -327,34 +342,44 @@ static inline void register_bank(int iobase, int bank)
*/
static int __init smsc_ircc_init(void)
{
- int ret=-ENODEV;
+ int ret;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- dev_count=0;
-
- if ((ircc_fir>0)&&(ircc_sir>0)) {
+ ret = driver_register(&smsc_ircc_driver);
+ if (ret) {
+ IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+ return ret;
+ }
+
+ dev_count = 0;
+
+ if (ircc_fir > 0 && ircc_sir > 0) {
IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
- if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0)
- return 0;
-
- return -ENODEV;
- }
+ if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
+ ret = -ENODEV;
+ } else {
+ ret = -ENODEV;
+
+ /* try user provided configuration register base address */
+ if (ircc_cfg > 0) {
+ IRDA_MESSAGE(" Overriding configuration address "
+ "0x%04x\n", ircc_cfg);
+ if (!smsc_superio_fdc(ircc_cfg))
+ ret = 0;
+ if (!smsc_superio_lpc(ircc_cfg))
+ ret = 0;
+ }
- /* try user provided configuration register base address */
- if (ircc_cfg>0) {
- IRDA_MESSAGE(" Overriding configuration address 0x%04x\n",
- ircc_cfg);
- if (!smsc_superio_fdc(ircc_cfg))
- ret = 0;
- if (!smsc_superio_lpc(ircc_cfg))
+ if (smsc_ircc_look_for_chips() > 0)
ret = 0;
}
-
- if(smsc_ircc_look_for_chips()>0) ret = 0;
-
+
+ if (ret)
+ driver_unregister(&smsc_ircc_driver);
+
return ret;
}
@@ -369,15 +394,15 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
struct smsc_ircc_cb *self;
struct net_device *dev;
int err;
-
+
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
err = smsc_ircc_present(fir_base, sir_base);
- if(err)
+ if (err)
goto err_out;
-
+
err = -ENOMEM;
- if (dev_count > DIM(dev_self)) {
+ if (dev_count >= ARRAY_SIZE(dev_self)) {
IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__);
goto err_out1;
}
@@ -396,14 +421,14 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
#if SMSC_IRCC2_C_NET_TIMEOUT
dev->tx_timeout = smsc_ircc_timeout;
- dev->watchdog_timeo = HZ*2; /* Allow enough time for speed change */
+ dev->watchdog_timeo = HZ * 2; /* Allow enough time for speed change */
#endif
dev->open = smsc_ircc_net_open;
dev->stop = smsc_ircc_net_close;
dev->do_ioctl = smsc_ircc_net_ioctl;
dev->get_stats = smsc_ircc_net_get_stats;
-
- self = dev->priv;
+
+ self = netdev_priv(dev);
self->netdev = dev;
/* Make ifconfig display some details */
@@ -411,10 +436,10 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->irq = self->io.irq = irq;
/* Need to store self somewhere */
- dev_self[dev_count++] = self;
+ dev_self[dev_count] = self;
spin_lock_init(&self->lock);
- self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
+ self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
self->rx_buff.head =
@@ -442,33 +467,40 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
self->rx_buff.state = OUTSIDE_FRAME;
self->tx_buff.data = self->tx_buff.head;
self->rx_buff.data = self->rx_buff.head;
-
- smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
+ smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
smsc_ircc_setup_qos(self);
-
smsc_ircc_init_chip(self);
-
- if(ircc_transceiver > 0 &&
- ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
+
+ if (ircc_transceiver > 0 &&
+ ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
self->transceiver = ircc_transceiver;
else
smsc_ircc_probe_transceiver(self);
err = register_netdev(self->netdev);
- if(err) {
+ if (err) {
IRDA_ERROR("%s, Network device registration failed!\n",
driver_name);
goto err_out4;
}
- self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
- if (self->pmdev)
- self->pmdev->data = self;
+ self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME,
+ dev_count, NULL, 0);
+ if (IS_ERR(self->pldev)) {
+ err = PTR_ERR(self->pldev);
+ goto err_out5;
+ }
+ dev_set_drvdata(&self->pldev->dev, self);
IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
+ dev_count++;
return 0;
+
+ err_out5:
+ unregister_netdev(self->netdev);
+
err_out4:
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
@@ -477,7 +509,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
self->rx_buff.head, self->rx_buff_dma);
err_out2:
free_netdev(self->netdev);
- dev_self[--dev_count] = NULL;
+ dev_self[dev_count] = NULL;
err_out1:
release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
@@ -511,16 +543,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
register_bank(fir_base, 3);
- high = inb(fir_base+IRCC_ID_HIGH);
- low = inb(fir_base+IRCC_ID_LOW);
- chip = inb(fir_base+IRCC_CHIP_ID);
- version = inb(fir_base+IRCC_VERSION);
- config = inb(fir_base+IRCC_INTERFACE);
+ high = inb(fir_base + IRCC_ID_HIGH);
+ low = inb(fir_base + IRCC_ID_LOW);
+ chip = inb(fir_base + IRCC_CHIP_ID);
+ version = inb(fir_base + IRCC_VERSION);
+ config = inb(fir_base + IRCC_INTERFACE);
dma = config & IRCC_INTERFACE_DMA_MASK;
irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
- if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
- IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
+ if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
+ IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
__FUNCTION__, fir_base);
goto out3;
}
@@ -529,6 +561,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
chip & 0x0f, version, fir_base, sir_base, dma, irq);
return 0;
+
out3:
release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
out2:
@@ -543,16 +576,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
* Setup I/O
*
*/
-static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
- unsigned int fir_base, unsigned int sir_base,
+static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
+ unsigned int fir_base, unsigned int sir_base,
u8 dma, u8 irq)
{
unsigned char config, chip_dma, chip_irq;
register_bank(fir_base, 3);
- config = inb(fir_base+IRCC_INTERFACE);
- chip_dma = config & IRCC_INTERFACE_DMA_MASK;
- chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
+ config = inb(fir_base + IRCC_INTERFACE);
+ chip_dma = config & IRCC_INTERFACE_DMA_MASK;
+ chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
self->io.fir_base = fir_base;
self->io.sir_base = sir_base;
@@ -566,17 +599,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
driver_name, chip_irq, irq);
self->io.irq = irq;
- }
- else
+ } else
self->io.irq = chip_irq;
-
+
if (dma < 255) {
if (dma != chip_dma)
IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
driver_name, chip_dma, dma);
self->io.dma = dma;
- }
- else
+ } else
self->io.dma = chip_dma;
}
@@ -591,7 +622,7 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
{
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
-
+
self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
@@ -608,43 +639,36 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
*/
static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
{
- int iobase, ir_mode, ctrl, fast;
-
- IRDA_ASSERT( self != NULL, return; );
- iobase = self->io.fir_base;
-
- ir_mode = IRCC_CFGA_IRDA_SIR_A;
- ctrl = 0;
- fast = 0;
+ int iobase = self->io.fir_base;
register_bank(iobase, 0);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
+ outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
register_bank(iobase, 1);
- outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode),
- iobase+IRCC_SCE_CFGA);
+ outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | IRCC_CFGA_IRDA_SIR_A),
+ iobase + IRCC_SCE_CFGA);
#ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
- iobase+IRCC_SCE_CFGB);
-#else
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
- iobase+IRCC_SCE_CFGB);
-#endif
- (void) inb(iobase+IRCC_FIFO_THRESHOLD);
- outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase+IRCC_FIFO_THRESHOLD);
-
+ outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ iobase + IRCC_SCE_CFGB);
+#else
+ outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ iobase + IRCC_SCE_CFGB);
+#endif
+ (void) inb(iobase + IRCC_FIFO_THRESHOLD);
+ outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD);
+
register_bank(iobase, 4);
- outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
-
+ outb((inb(iobase + IRCC_CONTROL) & 0x30), iobase + IRCC_CONTROL);
+
register_bank(iobase, 0);
- outb(fast, iobase+IRCC_LCR_A);
+ outb(0, iobase + IRCC_LCR_A);
smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
-
+
/* Power on device */
- outb(0x00, iobase+IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
}
/*
@@ -662,12 +686,12 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
-
+
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
@@ -703,14 +727,14 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
default:
ret = -EOPNOTSUPP;
}
-
+
return ret;
}
static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) dev->priv;
-
+ struct smsc_ircc_cb *self = netdev_priv(dev);
+
return &self->stats;
}
@@ -724,11 +748,9 @@ static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
static void smsc_ircc_timeout(struct net_device *dev)
{
- struct smsc_ircc_cb *self;
+ struct smsc_ircc_cb *self = netdev_priv(dev);
unsigned long flags;
- self = (struct smsc_ircc_cb *) dev->priv;
-
IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n",
dev->name, self->io.speed);
spin_lock_irqsave(&self->lock, flags);
@@ -751,26 +773,23 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
{
struct smsc_ircc_cb *self;
unsigned long flags;
- int iobase;
s32 speed;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
IRDA_ASSERT(dev != NULL, return 0;);
-
- self = (struct smsc_ircc_cb *) dev->priv;
- IRDA_ASSERT(self != NULL, return 0;);
- iobase = self->io.sir_base;
+ self = netdev_priv(dev);
+ IRDA_ASSERT(self != NULL, return 0;);
netif_stop_queue(dev);
-
+
/* Make sure test of self->io.speed & speed change are atomic */
spin_lock_irqsave(&self->lock, flags);
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
+ if (speed != self->io.speed && speed != -1) {
/* Check for empty frame */
if (!skb->len) {
/*
@@ -787,27 +806,26 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
- } else {
- self->new_speed = speed;
}
+ self->new_speed = speed;
}
/* Init tx buffer */
self->tx_buff.data = self->tx_buff.head;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
- self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
-
+
self->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
- outb(UART_IER_THRI, iobase+UART_IER);
+ outb(UART_IER_THRI, self->io.sir_base + UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
-
+
return 0;
}
@@ -826,9 +844,9 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
self->io.speed = speed;
- switch(speed) {
+ switch (speed) {
default:
- case 576000:
+ case 576000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
ctrl = IRCC_CRC;
fast = 0;
@@ -853,14 +871,14 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
Now in tranceiver!
/* This causes an interrupt */
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast, fir_base + IRCC_LCR_A);
#endif
-
+
register_bank(fir_base, 1);
- outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base+IRCC_SCE_CFGA);
-
+ outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA);
+
register_bank(fir_base, 4);
- outb((inb(fir_base+IRCC_CONTROL) & 0x30) | ctrl, fir_base+IRCC_CONTROL);
+ outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL);
}
/*
@@ -885,31 +903,31 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self)
/* Reset everything */
/* Install FIR transmit handler */
- dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;
+ dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;
/* Clear FIFO */
- outb(inb(fir_base+IRCC_LCR_A)|IRCC_LCR_A_FIFO_RESET, fir_base+IRCC_LCR_A);
+ outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A);
/* Enable interrupt */
- /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/
+ /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/
register_bank(fir_base, 1);
- /* Select the TX/RX interface */
+ /* Select the TX/RX interface */
#ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */
- outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
- fir_base+IRCC_SCE_CFGB);
-#else
- outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
- fir_base+IRCC_SCE_CFGB);
-#endif
- (void) inb(fir_base+IRCC_FIFO_THRESHOLD);
+ outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ fir_base + IRCC_SCE_CFGB);
+#else
+ outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ fir_base + IRCC_SCE_CFGB);
+#endif
+ (void) inb(fir_base + IRCC_FIFO_THRESHOLD);
/* Enable SCE interrupts */
- outb(0, fir_base+IRCC_MASTER);
+ outb(0, fir_base + IRCC_MASTER);
register_bank(fir_base, 0);
- outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, fir_base+IRCC_MASTER);
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER);
}
/*
@@ -923,13 +941,13 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
int fir_base;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(self != NULL, return;);
fir_base = self->io.fir_base;
register_bank(fir_base, 0);
- /*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/
- outb(inb(fir_base+IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base+IRCC_LCR_B);
+ /*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/
+ outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B);
}
@@ -941,18 +959,15 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
* This function *must* be called with spinlock held, because it may
* be called from the irq handler. - Jean II
*/
-static void smsc_ircc_change_speed(void *priv, u32 speed)
+static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
struct net_device *dev;
- int iobase;
int last_speed_was_sir;
-
+
IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);
IRDA_ASSERT(self != NULL, return;);
dev = self->netdev;
- iobase = self->io.fir_base;
last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED;
@@ -961,30 +976,30 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
speed= 1152000;
self->io.speed = speed;
last_speed_was_sir = 0;
- smsc_ircc_fir_start(self);
+ smsc_ircc_fir_start(self);
#endif
-
- if(self->io.speed == 0)
+
+ if (self->io.speed == 0)
smsc_ircc_sir_start(self);
#if 0
- if(!last_speed_was_sir) speed = self->io.speed;
+ if (!last_speed_was_sir) speed = self->io.speed;
#endif
- if(self->io.speed != speed) smsc_ircc_set_transceiver_for_speed(self, speed);
+ if (self->io.speed != speed)
+ smsc_ircc_set_transceiver_for_speed(self, speed);
self->io.speed = speed;
-
- if(speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
- if(!last_speed_was_sir) {
+
+ if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+ if (!last_speed_was_sir) {
smsc_ircc_fir_stop(self);
smsc_ircc_sir_start(self);
}
- smsc_ircc_set_sir_speed(self, speed);
- }
- else {
- if(last_speed_was_sir) {
- #if SMSC_IRCC2_C_SIR_STOP
+ smsc_ircc_set_sir_speed(self, speed);
+ } else {
+ if (last_speed_was_sir) {
+ #if SMSC_IRCC2_C_SIR_STOP
smsc_ircc_sir_stop(self);
#endif
smsc_ircc_fir_start(self);
@@ -994,13 +1009,13 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
#if 0
self->tx_buff.len = 10;
self->tx_buff.data = self->tx_buff.head;
-
- smsc_ircc_dma_xmit(self, iobase, 4000);
+
+ smsc_ircc_dma_xmit(self, 4000);
#endif
/* Be ready for incoming frames */
- smsc_ircc_dma_receive(self, iobase);
+ smsc_ircc_dma_receive(self);
}
-
+
netif_wake_queue(dev);
}
@@ -1010,10 +1025,9 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
* Set speed of IrDA port to specified baudrate
*
*/
-void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
+void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
- int iobase;
+ int iobase;
int fcr; /* FIFO control reg */
int lcr; /* Line control reg */
int divisor;
@@ -1022,38 +1036,36 @@ void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
-
+
/* Update accounting for new speed */
self->io.speed = speed;
/* Turn off interrupts */
- outb(0, iobase+UART_IER);
+ outb(0, iobase + UART_IER);
+
+ divisor = SMSC_IRCC2_MAX_SIR_SPEED / speed;
- divisor = SMSC_IRCC2_MAX_SIR_SPEED/speed;
-
fcr = UART_FCR_ENABLE_FIFO;
- /*
+ /*
* Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
- * about this timeout since it will always be fast enough.
+ * about this timeout since it will always be fast enough.
*/
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
-
+ fcr |= self->io.speed < 38400 ?
+ UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
+
/* IrDA ports use 8N1 */
lcr = UART_LCR_WLEN8;
-
- outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
- outb(divisor & 0xff, iobase+UART_DLL); /* Set speed */
- outb(divisor >> 8, iobase+UART_DLM);
- outb(lcr, iobase+UART_LCR); /* Set 8N1 */
- outb(fcr, iobase+UART_FCR); /* Enable FIFO's */
+
+ outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */
+ outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */
+ outb(divisor >> 8, iobase + UART_DLM);
+ outb(lcr, iobase + UART_LCR); /* Set 8N1 */
+ outb(fcr, iobase + UART_FCR); /* Enable FIFO's */
/* Turn on interrups */
- outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed);
}
@@ -1070,15 +1082,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
struct smsc_ircc_cb *self;
unsigned long flags;
s32 speed;
- int iobase;
int mtt;
IRDA_ASSERT(dev != NULL, return 0;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
- iobase = self->io.fir_base;
-
netif_stop_queue(dev);
/* Make sure test of self->io.speed & speed change are atomic */
@@ -1086,30 +1095,31 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
/* Check if we need to change the speed after this frame */
speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
+ if (speed != self->io.speed && speed != -1) {
/* Check for empty frame */
if (!skb->len) {
/* Note : you should make sure that speed changes
* are not going to corrupt any outgoing frame.
* Look at nsc-ircc for the gory details - Jean II */
- smsc_ircc_change_speed(self, speed);
+ smsc_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
- } else
- self->new_speed = speed;
+ }
+
+ self->new_speed = speed;
}
-
+
memcpy(self->tx_buff.head, skb->data, skb->len);
self->tx_buff.len = skb->len;
self->tx_buff.data = self->tx_buff.head;
-
- mtt = irda_get_mtt(skb);
+
+ mtt = irda_get_mtt(skb);
if (mtt) {
int bofs;
- /*
+ /*
* Compute how many BOFs (STA or PA's) we need to waste the
* min turn time given the speed of the link.
*/
@@ -1117,11 +1127,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
if (bofs > 4095)
bofs = 4095;
- smsc_ircc_dma_xmit(self, iobase, bofs);
+ smsc_ircc_dma_xmit(self, bofs);
} else {
/* Transmit frame */
- smsc_ircc_dma_xmit(self, iobase, 0);
+ smsc_ircc_dma_xmit(self, 0);
}
+
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
@@ -1129,43 +1140,44 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
}
/*
- * Function smsc_ircc_dma_xmit (self, iobase)
+ * Function smsc_ircc_dma_xmit (self, bofs)
*
* Transmit data using DMA
*
*/
-static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs)
{
+ int iobase = self->io.fir_base;
u8 ctrl;
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 1
/* Disable Rx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
self->io.direction = IO_XMIT;
/* Set BOF additional count for generating the min turn time */
register_bank(iobase, 4);
- outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
- ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
- outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+ outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO);
+ ctrl = inb(iobase + IRCC_CONTROL) & 0xf0;
+ outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI);
/* Set max Tx frame size */
- outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
- outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
+ outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI);
+ outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO);
/*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/
-
+
/* Enable burst mode chip Tx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
/* Setup DMA controller (must be done after enabling chip DMA) */
irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,
@@ -1174,50 +1186,52 @@ static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
/* Enable interrupt */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
+
/* Enable transmit */
- outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
+ outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase + IRCC_LCR_B);
}
/*
* Function smsc_ircc_dma_xmit_complete (self)
*
- * The transfer of a frame in finished. This function will only be called
+ * The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
-static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self)
{
+ int iobase = self->io.fir_base;
+
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 0
/* Disable Tx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
- register_bank(self->io.fir_base, 1);
- outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- self->io.fir_base+IRCC_SCE_CFGB);
+ register_bank(iobase, 1);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
/* Check for underrun! */
register_bank(iobase, 0);
- if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
+ if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) {
self->stats.tx_errors++;
self->stats.tx_fifo_errors++;
/* Reset error condition */
register_bank(iobase, 0);
- outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
+ outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
} else {
self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
+ self->stats.tx_bytes += self->tx_buff.len;
}
/* Check if it's time to change the speed */
if (self->new_speed) {
- smsc_ircc_change_speed(self, self->new_speed);
+ smsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -1231,31 +1245,32 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
* if it starts to receive a frame.
*
*/
-static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase)
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self)
{
+ int iobase = self->io.fir_base;
#if 0
/* Turn off chip DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
#endif
-
+
/* Disable Tx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
/* Turn off chip DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase + IRCC_SCE_CFGB);
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
/* Set max Rx frame size */
register_bank(iobase, 4);
- outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
- outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+ outb((2050 >> 8) & 0x0f, iobase + IRCC_RX_SIZE_HI);
+ outb(2050 & 0xff, iobase + IRCC_RX_SIZE_LO);
/* Setup DMA controller */
irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,
@@ -1263,83 +1278,83 @@ static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase)
/* Enable burst mode chip Rx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
- IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);
/* Enable interrupt */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER);
/* Enable receiver */
register_bank(iobase, 0);
- outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
- iobase+IRCC_LCR_B);
-
+ outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
+ iobase + IRCC_LCR_B);
+
return 0;
}
/*
- * Function smsc_ircc_dma_receive_complete(self, iobase)
+ * Function smsc_ircc_dma_receive_complete(self)
*
* Finished with receiving frames
*
*/
-static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase)
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
{
struct sk_buff *skb;
int len, msgcnt, lsr;
-
+ int iobase = self->io.fir_base;
+
register_bank(iobase, 0);
-
+
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
#if 0
/* Disable Rx */
register_bank(iobase, 0);
- outb(0x00, iobase+IRCC_LCR_B);
+ outb(0x00, iobase + IRCC_LCR_B);
#endif
register_bank(iobase, 0);
- outb(inb(iobase+IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase+IRCC_LSAR);
- lsr= inb(iobase+IRCC_LSR);
- msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
+ outb(inb(iobase + IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase + IRCC_LSAR);
+ lsr= inb(iobase + IRCC_LSR);
+ msgcnt = inb(iobase + IRCC_LCR_B) & 0x08;
IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__,
get_dma_residue(self->io.dma));
len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
- /* Look for errors
- */
-
- if(lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
+ /* Look for errors */
+ if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
self->stats.rx_errors++;
- if(lsr & IRCC_LSR_FRAME_ERROR) self->stats.rx_frame_errors++;
- if(lsr & IRCC_LSR_CRC_ERROR) self->stats.rx_crc_errors++;
- if(lsr & IRCC_LSR_SIZE_ERROR) self->stats.rx_length_errors++;
- if(lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) self->stats.rx_length_errors++;
+ if (lsr & IRCC_LSR_FRAME_ERROR)
+ self->stats.rx_frame_errors++;
+ if (lsr & IRCC_LSR_CRC_ERROR)
+ self->stats.rx_crc_errors++;
+ if (lsr & IRCC_LSR_SIZE_ERROR)
+ self->stats.rx_length_errors++;
+ if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN))
+ self->stats.rx_length_errors++;
return;
}
+
/* Remove CRC */
- if (self->io.speed < 4000000)
- len -= 2;
- else
- len -= 4;
+ len -= self->io.speed < 4000000 ? 2 : 4;
- if ((len < 2) || (len > 2050)) {
+ if (len < 2 || len > 2050) {
IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
return;
}
IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len);
- skb = dev_alloc_skb(len+1);
- if (!skb) {
+ skb = dev_alloc_skb(len + 1);
+ if (!skb) {
IRDA_WARNING("%s(), memory squeeze, dropping frame.\n",
__FUNCTION__);
return;
- }
+ }
/* Make sure IP header gets aligned */
- skb_reserve(skb, 1);
+ skb_reserve(skb, 1);
memcpy(skb_put(skb, len), self->rx_buff.data, len);
self->stats.rx_packets++;
@@ -1357,7 +1372,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase
* Receive one frame from the infrared port
*
*/
-static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
+static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
{
int boguscount = 0;
int iobase;
@@ -1366,20 +1381,20 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
iobase = self->io.sir_base;
- /*
- * Receive all characters in Rx FIFO, unwrap and unstuff them.
- * async_unwrap_char will deliver all found frames
+ /*
+ * Receive all characters in Rx FIFO, unwrap and unstuff them.
+ * async_unwrap_char will deliver all found frames
*/
do {
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
- inb(iobase+UART_RX));
+ async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ inb(iobase + UART_RX));
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__);
break;
}
- } while (inb(iobase+UART_LSR) & UART_LSR_DR);
+ } while (inb(iobase + UART_LSR) & UART_LSR_DR);
}
@@ -1397,18 +1412,19 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
irqreturn_t ret = IRQ_NONE;
if (dev == NULL) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
goto irq_ret;
}
- self = (struct smsc_ircc_cb *) dev->priv;
+
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return IRQ_NONE;);
/* Serialise the interrupt handler in various CPUs, stop Tx path */
- spin_lock(&self->lock);
+ spin_lock(&self->lock);
/* Check if we should use the SIR interrupt handler */
- if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+ if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
ret = smsc_ircc_interrupt_sir(dev);
goto irq_ret_unlock;
}
@@ -1416,25 +1432,25 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
iobase = self->io.fir_base;
register_bank(iobase, 0);
- iir = inb(iobase+IRCC_IIR);
- if (iir == 0)
+ iir = inb(iobase + IRCC_IIR);
+ if (iir == 0)
goto irq_ret_unlock;
ret = IRQ_HANDLED;
/* Disable interrupts */
- outb(0, iobase+IRCC_IER);
- lcra = inb(iobase+IRCC_LCR_A);
- lsr = inb(iobase+IRCC_LSR);
-
+ outb(0, iobase + IRCC_IER);
+ lcra = inb(iobase + IRCC_LCR_A);
+ lsr = inb(iobase + IRCC_LSR);
+
IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir);
if (iir & IRCC_IIR_EOM) {
if (self->io.direction == IO_RECV)
- smsc_ircc_dma_receive_complete(self, iobase);
+ smsc_ircc_dma_receive_complete(self);
else
- smsc_ircc_dma_xmit_complete(self, iobase);
-
- smsc_ircc_dma_receive(self, iobase);
+ smsc_ircc_dma_xmit_complete(self);
+
+ smsc_ircc_dma_receive(self);
}
if (iir & IRCC_IIR_ACTIVE_FRAME) {
@@ -1444,7 +1460,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
/* Enable interrupts again */
register_bank(iobase, 0);
- outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+ outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER);
irq_ret_unlock:
spin_unlock(&self->lock);
@@ -1459,7 +1475,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
*/
static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
{
- struct smsc_ircc_cb *self = dev->priv;
+ struct smsc_ircc_cb *self = netdev_priv(dev);
int boguscount = 0;
int iobase;
int iir, lsr;
@@ -1469,14 +1485,14 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
iobase = self->io.sir_base;
- iir = inb(iobase+UART_IIR) & UART_IIR_ID;
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
if (iir == 0)
return IRQ_NONE;
while (iir) {
/* Clear interrupt */
- lsr = inb(iobase+UART_LSR);
+ lsr = inb(iobase + UART_LSR);
- IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
__FUNCTION__, iir, lsr, iobase);
switch (iir) {
@@ -1496,13 +1512,13 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev)
IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n",
__FUNCTION__, iir);
break;
- }
-
+ }
+
/* Make sure we don't stay here to long */
if (boguscount++ > 100)
break;
- iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
}
/*spin_unlock(&self->lock);*/
return IRQ_HANDLED;
@@ -1529,11 +1545,51 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
get_dma_residue(self->io.dma));
status = (self->rx_buff.state != OUTSIDE_FRAME);
-
+
return status;
}
#endif /* unused */
+static int smsc_ircc_request_irq(struct smsc_ircc_cb *self)
+{
+ int error;
+
+ error = request_irq(self->io.irq, smsc_ircc_interrupt, 0,
+ self->netdev->name, self->netdev);
+ if (error)
+ IRDA_DEBUG(0, "%s(), unable to allocate irq=%d, err=%d\n",
+ __FUNCTION__, self->io.irq, error);
+
+ return error;
+}
+
+static void smsc_ircc_start_interrupts(struct smsc_ircc_cb *self)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&self->lock, flags);
+
+ self->io.speed = 0;
+ smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
+
+ spin_unlock_irqrestore(&self->lock, flags);
+}
+
+static void smsc_ircc_stop_interrupts(struct smsc_ircc_cb *self)
+{
+ int iobase = self->io.fir_base;
+ unsigned long flags;
+
+ spin_lock_irqsave(&self->lock, flags);
+
+ register_bank(iobase, 0);
+ outb(0, iobase + IRCC_IER);
+ outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+ outb(0x00, iobase + IRCC_MASTER);
+
+ spin_unlock_irqrestore(&self->lock, flags);
+}
+
/*
* Function smsc_ircc_net_open (dev)
@@ -1544,38 +1600,35 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
static int smsc_ircc_net_open(struct net_device *dev)
{
struct smsc_ircc_cb *self;
- int iobase;
char hwname[16];
- unsigned long flags;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
-
- iobase = self->io.fir_base;
- if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
+ if (self->io.suspended) {
+ IRDA_DEBUG(0, "%s(), device is suspended\n", __FUNCTION__);
+ return -EAGAIN;
+ }
+
+ if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
(void *) dev)) {
IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
__FUNCTION__, self->io.irq);
return -EAGAIN;
}
- spin_lock_irqsave(&self->lock, flags);
- /*smsc_ircc_sir_start(self);*/
- self->io.speed = 0;
- smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
- spin_unlock_irqrestore(&self->lock, flags);
-
+ smsc_ircc_start_interrupts(self);
+
/* Give self a hardware name */
/* It would be cool to offer the chip revision here - Jean II */
sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base);
- /*
+ /*
* Open new IrLAP layer instance, now that everything should be
- * initialized properly
+ * initialized properly
*/
self->irlap = irlap_open(dev, &self->qos, hwname);
@@ -1590,7 +1643,7 @@ static int smsc_ircc_net_open(struct net_device *dev)
__FUNCTION__, self->io.dma);
return -EAGAIN;
}
-
+
netif_start_queue(dev);
return 0;
@@ -1605,73 +1658,79 @@ static int smsc_ircc_net_open(struct net_device *dev)
static int smsc_ircc_net_close(struct net_device *dev)
{
struct smsc_ircc_cb *self;
- int iobase;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
-
+
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct smsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
-
- iobase = self->io.fir_base;
/* Stop device */
netif_stop_queue(dev);
-
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
self->irlap = NULL;
- free_irq(self->io.irq, dev);
+ smsc_ircc_stop_interrupts(self);
- disable_dma(self->io.dma);
+ /* if we are called from smsc_ircc_resume we don't have IRQ reserved */
+ if (!self->io.suspended)
+ free_irq(self->io.irq, dev);
+ disable_dma(self->io.dma);
free_dma(self->io.dma);
return 0;
}
-
-static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state)
{
- IRDA_MESSAGE("%s, Suspending\n", driver_name);
-
- if (self->io.suspended)
- return;
-
- smsc_ircc_net_close(self->netdev);
+ struct smsc_ircc_cb *self = dev_get_drvdata(dev);
- self->io.suspended = 1;
-}
-
-static void smsc_ircc_wakeup(struct smsc_ircc_cb *self)
-{
- if (!self->io.suspended)
- return;
+ if (!self->io.suspended) {
+ IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
- /* The code was doing a "cli()" here, but this can't be right.
- * If you need protection, do it in net_open with a spinlock
- * or give a good reason. - Jean II */
+ rtnl_lock();
+ if (netif_running(self->netdev)) {
+ netif_device_detach(self->netdev);
+ smsc_ircc_stop_interrupts(self);
+ free_irq(self->io.irq, self->netdev);
+ disable_dma(self->io.dma);
+ }
+ self->io.suspended = 1;
+ rtnl_unlock();
+ }
- smsc_ircc_net_open(self->netdev);
-
- IRDA_MESSAGE("%s, Waking up\n", driver_name);
+ return 0;
}
-static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
+static int smsc_ircc_resume(struct device *dev)
{
- struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data;
- if (self) {
- switch (rqst) {
- case PM_SUSPEND:
- smsc_ircc_suspend(self);
- break;
- case PM_RESUME:
- smsc_ircc_wakeup(self);
- break;
- }
- }
+ struct smsc_ircc_cb *self = dev_get_drvdata(dev);
+
+ if (self->io.suspended) {
+ IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
+
+ rtnl_lock();
+ smsc_ircc_init_chip(self);
+ if (netif_running(self->netdev)) {
+ if (smsc_ircc_request_irq(self)) {
+ /*
+ * Don't fail resume process, just kill this
+ * network interface
+ */
+ unregister_netdevice(self->netdev);
+ } else {
+ enable_dma(self->io.dma);
+ smsc_ircc_start_interrupts(self);
+ netif_device_attach(self->netdev);
+ }
+ }
+ self->io.suspended = 0;
+ rtnl_unlock();
+ }
return 0;
}
@@ -1683,36 +1742,16 @@ static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
*/
static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
{
- int iobase;
- unsigned long flags;
-
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
IRDA_ASSERT(self != NULL, return -1;);
- iobase = self->io.fir_base;
-
- if (self->pmdev)
- pm_unregister(self->pmdev);
+ platform_device_unregister(self->pldev);
/* Remove netdevice */
unregister_netdev(self->netdev);
- /* Make sure the irq handler is not exectuting */
- spin_lock_irqsave(&self->lock, flags);
-
- /* Stop interrupts */
- register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(0x00, iobase+IRCC_MASTER);
-#if 0
- /* Reset to SIR mode */
- register_bank(iobase, 1);
- outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
- outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
-#endif
- spin_unlock_irqrestore(&self->lock, flags);
+ smsc_ircc_stop_interrupts(self);
/* Release the PORTS that this driver is using */
IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
@@ -1720,7 +1759,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
release_region(self->io.fir_base, self->io.fir_ext);
- IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
+ IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__,
self->io.sir_base);
release_region(self->io.sir_base, self->io.sir_ext);
@@ -1728,7 +1767,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
if (self->tx_buff.head)
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
-
+
if (self->rx_buff.head)
dma_free_coherent(NULL, self->rx_buff.truesize,
self->rx_buff.head, self->rx_buff_dma);
@@ -1744,10 +1783,12 @@ static void __exit smsc_ircc_cleanup(void)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- for (i=0; i < 2; i++) {
+ for (i = 0; i < 2; i++) {
if (dev_self[i])
smsc_ircc_close(dev_self[i]);
}
+
+ driver_unregister(&smsc_ircc_driver);
}
/*
@@ -1763,34 +1804,34 @@ void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
- IRDA_ASSERT(self != NULL, return;);
- dev= self->netdev;
- IRDA_ASSERT(dev != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ dev = self->netdev;
+ IRDA_ASSERT(dev != NULL, return;);
dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir;
fir_base = self->io.fir_base;
sir_base = self->io.sir_base;
/* Reset everything */
- outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);
+ outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);
#if SMSC_IRCC2_C_SIR_STOP
/*smsc_ircc_sir_stop(self);*/
#endif
register_bank(fir_base, 1);
- outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base+IRCC_SCE_CFGA);
+ outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base + IRCC_SCE_CFGA);
/* Initialize UART */
- outb(UART_LCR_WLEN8, sir_base+UART_LCR); /* Reset DLAB */
- outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base+UART_MCR);
-
+ outb(UART_LCR_WLEN8, sir_base + UART_LCR); /* Reset DLAB */
+ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base + UART_MCR);
+
/* Turn on interrups */
- outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base+UART_IER);
+ outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER);
IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__);
- outb(0x00, fir_base+IRCC_MASTER);
+ outb(0x00, fir_base + IRCC_MASTER);
}
#if SMSC_IRCC2_C_SIR_STOP
@@ -1802,10 +1843,10 @@ void smsc_ircc_sir_stop(struct smsc_ircc_cb *self)
iobase = self->io.sir_base;
/* Reset UART */
- outb(0, iobase+UART_MCR);
-
+ outb(0, iobase + UART_MCR);
+
/* Turn off interrupts */
- outb(0, iobase+UART_IER);
+ outb(0, iobase + UART_IER);
}
#endif
@@ -1831,16 +1872,16 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
/* Finished with frame? */
if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */
- actual = smsc_ircc_sir_write(iobase, self->io.fifo_size,
+ actual = smsc_ircc_sir_write(iobase, self->io.fifo_size,
self->tx_buff.data, self->tx_buff.len);
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
} else {
-
+
/*if (self->tx_buff.len ==0) {*/
-
- /*
- * Now serial buffer is almost free & we can start
+
+ /*
+ * Now serial buffer is almost free & we can start
* transmission of another packet. But first we must check
* if we need to change the speed of the hardware
*/
@@ -1856,21 +1897,19 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
}
self->stats.tx_packets++;
- if(self->io.speed <= 115200) {
- /*
- * Reset Rx FIFO to make sure that all reflected transmit data
- * is discarded. This is needed for half duplex operation
- */
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
+ if (self->io.speed <= 115200) {
+ /*
+ * Reset Rx FIFO to make sure that all reflected transmit data
+ * is discarded. This is needed for half duplex operation
+ */
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
+ fcr |= self->io.speed < 38400 ?
+ UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14;
- outb(fcr, iobase+UART_FCR);
+ outb(fcr, iobase + UART_FCR);
- /* Turn on receive interrupts */
- outb(UART_IER_RDI, iobase+UART_IER);
+ /* Turn on receive interrupts */
+ outb(UART_IER_RDI, iobase + UART_IER);
}
}
}
@@ -1884,17 +1923,17 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
{
int actual = 0;
-
+
/* Tx FIFO should be empty! */
- if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+ if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) {
IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
return 0;
}
-
+
/* Fill FIFO with current frame */
- while ((fifo_size-- > 0) && (actual < len)) {
+ while (fifo_size-- > 0 && actual < len) {
/* Transmit next byte */
- outb(buf[actual], iobase+UART_TX);
+ outb(buf[actual], iobase + UART_TX);
actual++;
}
return actual;
@@ -1921,20 +1960,21 @@ static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
{
unsigned int i;
-
+
IRDA_ASSERT(self != NULL, return;);
-
- for(i=0; smsc_transceivers[i].name!=NULL; i++)
- if((*smsc_transceivers[i].probe)(self->io.fir_base)) {
+
+ for (i = 0; smsc_transceivers[i].name != NULL; i++)
+ if (smsc_transceivers[i].probe(self->io.fir_base)) {
IRDA_MESSAGE(" %s transceiver found\n",
smsc_transceivers[i].name);
- self->transceiver= i+1;
+ self->transceiver= i + 1;
return;
}
+
IRDA_MESSAGE("No transceiver found. Defaulting to %s\n",
smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
-
- self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
+
+ self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
}
@@ -1947,9 +1987,10 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed)
{
unsigned int trx;
-
+
trx = self->transceiver;
- if(trx>0) (*smsc_transceivers[trx-1].set_for_speed)(self->io.fir_base, speed);
+ if (trx > 0)
+ smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed);
}
/*
@@ -1977,16 +2018,14 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s
static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
{
- int iobase;
+ int iobase = self->io.sir_base;
int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US;
-
- iobase = self->io.sir_base;
-
+
/* Calibrated busy loop */
- while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+ while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT))
udelay(1);
- if(count == 0)
+ if (count == 0)
IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
}
@@ -1998,40 +2037,42 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
static int __init smsc_ircc_look_for_chips(void)
{
- smsc_chip_address_t *address;
- char *type;
+ struct smsc_chip_address *address;
+ char *type;
unsigned int cfg_base, found;
-
+
found = 0;
address = possible_addresses;
-
- while(address->cfg_base){
+
+ while (address->cfg_base) {
cfg_base = address->cfg_base;
-
+
/*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/
-
- if( address->type & SMSCSIO_TYPE_FDC){
+
+ if (address->type & SMSCSIO_TYPE_FDC) {
type = "FDC";
- if((address->type) & SMSCSIO_TYPE_FLAT) {
- if(!smsc_superio_flat(fdc_chips_flat,cfg_base, type)) found++;
- }
- if((address->type) & SMSCSIO_TYPE_PAGED) {
- if(!smsc_superio_paged(fdc_chips_paged,cfg_base, type)) found++;
- }
+ if (address->type & SMSCSIO_TYPE_FLAT)
+ if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type))
+ found++;
+
+ if (address->type & SMSCSIO_TYPE_PAGED)
+ if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type))
+ found++;
}
- if( address->type & SMSCSIO_TYPE_LPC){
+ if (address->type & SMSCSIO_TYPE_LPC) {
type = "LPC";
- if((address->type) & SMSCSIO_TYPE_FLAT) {
- if(!smsc_superio_flat(lpc_chips_flat,cfg_base,type)) found++;
- }
- if((address->type) & SMSCSIO_TYPE_PAGED) {
- if(!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) found++;
- }
+ if (address->type & SMSCSIO_TYPE_FLAT)
+ if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type))
+ found++;
+
+ if (address->type & SMSCSIO_TYPE_PAGED)
+ if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type))
+ found++;
}
address++;
}
return found;
-}
+}
/*
* Function smsc_superio_flat (chip, base, type)
@@ -2039,7 +2080,7 @@ static int __init smsc_ircc_look_for_chips(void)
* Try to get configuration of a smc SuperIO chip with flat register model
*
*/
-static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfgbase, char *type)
+static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type)
{
unsigned short firbase, sirbase;
u8 mode, dma, irq;
@@ -2047,39 +2088,37 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type)==NULL)
+ if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL)
return ret;
outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase);
- mode = inb(cfgbase+1);
-
+ mode = inb(cfgbase + 1);
+
/*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/
-
- if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
+
+ if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);
- sirbase = inb(cfgbase+1) << 2;
+ sirbase = inb(cfgbase + 1) << 2;
- /* FIR iobase */
+ /* FIR iobase */
outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase);
- firbase = inb(cfgbase+1) << 3;
+ firbase = inb(cfgbase + 1) << 3;
/* DMA */
outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase);
- dma = inb(cfgbase+1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
-
+ dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
+
/* IRQ */
outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);
- irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+ irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
- if (firbase) {
- if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
- ret=0;
- }
-
+ if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
+ ret = 0;
+
/* Exit configuration */
outb(SMSCSIO_CFGEXITKEY, cfgbase);
@@ -2092,26 +2131,26 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
* Try to get configuration of a smc SuperIO chip with paged register model
*
*/
-static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type)
+static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type)
{
unsigned short fir_io, sir_io;
int ret = -ENODEV;
-
+
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- if (smsc_ircc_probe(cfg_base,0x20,chips,type)==NULL)
+ if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL)
return ret;
-
+
/* Select logical device (UART2) */
outb(0x07, cfg_base);
outb(0x05, cfg_base + 1);
-
+
/* SIR iobase */
outb(0x60, cfg_base);
- sir_io = inb(cfg_base + 1) << 8;
+ sir_io = inb(cfg_base + 1) << 8;
outb(0x61, cfg_base);
sir_io |= inb(cfg_base + 1);
-
+
/* Read FIR base */
outb(0x62, cfg_base);
fir_io = inb(cfg_base + 1) << 8;
@@ -2119,11 +2158,9 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
fir_io |= inb(cfg_base + 1);
outb(0x2b, cfg_base); /* ??? */
- if (fir_io) {
- if (smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
- ret=0;
- }
-
+ if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
+ ret = 0;
+
/* Exit configuration */
outb(SMSCSIO_CFGEXITKEY, cfg_base);
@@ -2131,21 +2168,17 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf
}
-static int __init smsc_access(unsigned short cfg_base,unsigned char reg)
+static int __init smsc_access(unsigned short cfg_base, unsigned char reg)
{
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
outb(reg, cfg_base);
-
- if (inb(cfg_base)!=reg)
- return -1;
-
- return 0;
+ return inb(cfg_base) != reg ? -1 : 0;
}
-static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type)
+static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type)
{
- u8 devid,xdevid,rev;
+ u8 devid, xdevid, rev;
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
@@ -2158,7 +2191,7 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
outb(reg, cfg_base);
- xdevid=inb(cfg_base+1);
+ xdevid = inb(cfg_base + 1);
/* Enter configuration */
@@ -2168,51 +2201,49 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
if (smsc_access(cfg_base,0x55)) /* send second key and check */
return NULL;
#endif
-
+
/* probe device ID */
- if (smsc_access(cfg_base,reg))
+ if (smsc_access(cfg_base, reg))
return NULL;
- devid=inb(cfg_base+1);
-
- if (devid==0) /* typical value for unused port */
- return NULL;
+ devid = inb(cfg_base + 1);
- if (devid==0xff) /* typical value for unused port */
+ if (devid == 0 || devid == 0xff) /* typical values for unused port */
return NULL;
/* probe revision ID */
- if (smsc_access(cfg_base,reg+1))
+ if (smsc_access(cfg_base, reg + 1))
return NULL;
- rev=inb(cfg_base+1);
+ rev = inb(cfg_base + 1);
- if (rev>=128) /* i think this will make no sense */
+ if (rev >= 128) /* i think this will make no sense */
return NULL;
- if (devid==xdevid) /* protection against false positives */
+ if (devid == xdevid) /* protection against false positives */
return NULL;
/* Check for expected device ID; are there others? */
- while(chip->devid!=devid) {
+ while (chip->devid != devid) {
chip++;
- if (chip->name==NULL)
+ if (chip->name == NULL)
return NULL;
}
- IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+ IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",
+ devid, rev, cfg_base, type, chip->name);
- if (chip->rev>rev){
- IRDA_MESSAGE("Revision higher than expected\n");
+ if (chip->rev > rev) {
+ IRDA_MESSAGE("Revision higher than expected\n");
return NULL;
}
-
- if (chip->flags&NoIRDA)
+
+ if (chip->flags & NoIRDA)
IRDA_MESSAGE("chipset does not support IRDA\n");
return chip;
@@ -2226,8 +2257,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base)
IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
__FUNCTION__, cfg_base);
} else {
- if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")
- ||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+ if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") ||
+ !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC"))
ret = 0;
release_region(cfg_base, 2);
@@ -2244,9 +2275,10 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
__FUNCTION__, cfg_base);
} else {
- if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")
- ||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+ if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") ||
+ !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC"))
ret = 0;
+
release_region(cfg_base, 2);
}
return ret;
@@ -2269,18 +2301,23 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed)
{
unsigned long jiffies_now, jiffies_timeout;
- u8 val;
-
- jiffies_now= jiffies;
- jiffies_timeout= jiffies+SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
-
+ u8 val;
+
+ jiffies_now = jiffies;
+ jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
+
/* ATC */
register_bank(fir_base, 4);
- outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC);
- while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout));
- if(val)
+ outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE,
+ fir_base + IRCC_ATC);
+
+ while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) &&
+ !time_after(jiffies, jiffies_timeout))
+ /* empty */;
+
+ if (val)
IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
- inb(fir_base+IRCC_ATC));
+ inb(fir_base + IRCC_ATC));
}
/*
@@ -2298,34 +2335,32 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base)
/*
* Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed)
*
- * Set transceiver
+ * Set transceiver
*
*/
static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed)
{
- u8 fast_mode;
-
- switch(speed)
- {
- default:
- case 576000 :
- fast_mode = 0;
+ u8 fast_mode;
+
+ switch (speed) {
+ default:
+ case 576000 :
+ fast_mode = 0;
break;
- case 1152000 :
- case 4000000 :
+ case 1152000 :
+ case 4000000 :
fast_mode = IRCC_LCR_A_FAST;
break;
-
}
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);
}
/*
* Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base)
*
- * Probe transceiver
+ * Probe transceiver
*
*/
@@ -2337,35 +2372,34 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base)
/*
* Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed)
*
- * Set transceiver
+ * Set transceiver
*
*/
static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed)
{
- u8 fast_mode;
-
- switch(speed)
- {
- default:
- case 576000 :
- fast_mode = 0;
+ u8 fast_mode;
+
+ switch (speed) {
+ default:
+ case 576000 :
+ fast_mode = 0;
break;
- case 1152000 :
- case 4000000 :
+ case 1152000 :
+ case 4000000 :
fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA;
break;
-
+
}
/* This causes an interrupt */
register_bank(fir_base, 0);
- outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+ outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);
}
/*
* Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base)
*
- * Probe transceiver
+ * Probe transceiver
*
*/
@@ -2377,20 +2411,3 @@ static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base)
module_init(smsc_ircc_init);
module_exit(smsc_ircc_cleanup);
-
-MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
-MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
-MODULE_LICENSE("GPL");
-
-module_param(ircc_dma, int, 0);
-MODULE_PARM_DESC(ircc_dma, "DMA channel");
-module_param(ircc_irq, int, 0);
-MODULE_PARM_DESC(ircc_irq, "IRQ line");
-module_param(ircc_fir, int, 0);
-MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
-module_param(ircc_sir, int, 0);
-MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
-module_param(ircc_cfg, int, 0);
-MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
-module_param(ircc_transceiver, int, 0);
-MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
diff --git a/drivers/net/irda/smsc-ircc2.h b/drivers/net/irda/smsc-ircc2.h
index 458611cc0d40..0c36286d87f7 100644
--- a/drivers/net/irda/smsc-ircc2.h
+++ b/drivers/net/irda/smsc-ircc2.h
@@ -1,5 +1,5 @@
/*********************************************************************
- * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
+ * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
*
* Description: Definitions for the SMC IrCC chipset
* Status: Experimental.
@@ -9,25 +9,25 @@
* All Rights Reserved.
*
* Based on smc-ircc.h:
- *
+ *
* Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
* 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
+ *
+ * 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,
+ *
+ * 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
*
********************************************************************/
@@ -112,10 +112,10 @@
#define IRCC_CFGA_COM 0x00
#define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87
-#define IRCC_CFGA_IRDA_SIR_A 0x08
-#define IRCC_CFGA_ASK_SIR 0x10
-#define IRCC_CFGA_IRDA_SIR_B 0x18
-#define IRCC_CFGA_IRDA_HDLC 0x20
+#define IRCC_CFGA_IRDA_SIR_A 0x08
+#define IRCC_CFGA_ASK_SIR 0x10
+#define IRCC_CFGA_IRDA_SIR_B 0x18
+#define IRCC_CFGA_IRDA_HDLC 0x20
#define IRCC_CFGA_IRDA_4PPM 0x28
#define IRCC_CFGA_CONSUMER 0x30
#define IRCC_CFGA_RAW_IR 0x38
@@ -130,7 +130,7 @@
#define IRCC_CFGB_LPBCK_TX_CRC 0x10
#define IRCC_CFGB_NOWAIT 0x08
#define IRCC_CFGB_STRING_MOVE 0x04
-#define IRCC_CFGB_DMA_BURST 0x02
+#define IRCC_CFGB_DMA_BURST 0x02
#define IRCC_CFGB_DMA_ENABLE 0x01
#define IRCC_CFGB_MUX_COM 0x00
@@ -141,11 +141,11 @@
/* Register block 3 - Identification Registers! */
#define IRCC_ID_HIGH 0x00 /* 0x10 */
#define IRCC_ID_LOW 0x01 /* 0xB8 */
-#define IRCC_CHIP_ID 0x02 /* 0xF1 */
+#define IRCC_CHIP_ID 0x02 /* 0xF1 */
#define IRCC_VERSION 0x03 /* 0x01 */
#define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
-#define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */
-#define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */
/* Register block 4 - IrDA */
#define IRCC_CONTROL 0x00
@@ -163,10 +163,10 @@
/* Register block 5 - IrDA */
#define IRCC_ATC 0x00
-#define IRCC_ATC_nPROGREADY 0x80
-#define IRCC_ATC_SPEED 0x40
-#define IRCC_ATC_ENABLE 0x20
-#define IRCC_ATC_MASK 0xE0
+#define IRCC_ATC_nPROGREADY 0x80
+#define IRCC_ATC_SPEED 0x40
+#define IRCC_ATC_ENABLE 0x20
+#define IRCC_ATC_MASK 0xE0
#define IRCC_IRHALFDUPLEX_TIMEOUT 0x01
@@ -178,8 +178,8 @@
*/
#define SMSC_IRCC2_MAX_SIR_SPEED 115200
-#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
-#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
+#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
+#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_FIFO_SIZE 16
#define SMSC_IRCC2_FIFO_THRESHOLD 64
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 15f207323d97..3961a754e920 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -678,10 +678,9 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
return;
ticks = us / (1000000 / HZ);
- if (ticks > 0) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1 + ticks);
- } else
+ if (ticks > 0)
+ schedule_timeout_interruptible(1 + ticks);
+ else
udelay(us);
}
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 006e4f575606..a9f49f058cfb 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -473,8 +473,7 @@ static int vlsi_free_ring(struct vlsi_ring *r)
rd_set_addr_status(rd, 0, 0);
if (busaddr)
pci_unmap_single(r->pdev, busaddr, r->len, r->dir);
- if (rd->buf)
- kfree(rd->buf);
+ kfree(rd->buf);
}
kfree(r);
return 0;
@@ -1749,11 +1748,6 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
struct net_device *ndev = pci_get_drvdata(pdev);
vlsi_irda_dev_t *idev;
- if (state < 1 || state > 3 ) {
- IRDA_ERROR("%s - %s: invalid pm state request: %u\n",
- __FUNCTION__, PCIDEV_NAME(pdev), state);
- return 0;
- }
if (!ndev) {
IRDA_ERROR("%s - %s: no netdevice \n",
__FUNCTION__, PCIDEV_NAME(pdev));
@@ -1762,12 +1756,12 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
idev = ndev->priv;
down(&idev->sem);
if (pdev->current_state != 0) { /* already suspended */
- if (state > pdev->current_state) { /* simply go deeper */
- pci_set_power_state(pdev,state);
- pdev->current_state = state;
+ if (state.event > pdev->current_state) { /* simply go deeper */
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ pdev->current_state = state.event;
}
else
- IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state);
+ IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state.event);
up(&idev->sem);
return 0;
}
@@ -1781,8 +1775,8 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
idev->new_baud = idev->baud;
}
- pci_set_power_state(pdev,state);
- pdev->current_state = state;
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ pdev->current_state = state.event;
idev->resume_ok = 1;
up(&idev->sem);
return 0;
@@ -1807,8 +1801,8 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
return 0;
}
- pci_set_power_state(pdev, 0);
- pdev->current_state = 0;
+ pci_set_power_state(pdev, PCI_D0);
+ pdev->current_state = PM_EVENT_ON;
if (!idev->resume_ok) {
/* should be obsolete now - but used to happen due to:
@@ -1880,11 +1874,11 @@ static int __init vlsi_mod_init(void)
sirpulse = !!sirpulse;
- /* create_proc_entry returns NULL if !CONFIG_PROC_FS.
+ /* proc_mkdir returns NULL if !CONFIG_PROC_FS.
* Failure to create the procfs entry is handled like running
* without procfs - it's not required for the driver to work.
*/
- vlsi_proc_root = create_proc_entry(PROC_DIR, S_IFDIR, NULL);
+ vlsi_proc_root = proc_mkdir(PROC_DIR, NULL);
if (vlsi_proc_root) {
/* protect registered procdir against module removal.
* Because we are in the module init path there's no race
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 414694abf588..741aecc655df 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -69,14 +69,8 @@ typedef void irqreturn_t;
#else /* 2.5 or later */
-/* recent 2.5/2.6 stores pci device names at varying places ;-) */
-#ifdef CONFIG_PCI_NAMES
-/* human readable name */
-#define PCIDEV_NAME(pdev) ((pdev)->pretty_name)
-#else
/* whatever we get from the associated struct device - bus:slot:dev.fn id */
#define PCIDEV_NAME(pdev) (pci_name(pdev))
-#endif
#endif
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 55af32e9bf08..d86d8f055a6c 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -4,6 +4,7 @@
* Copyright (C) 2001 Kyle A. Lucke (klucke@us.ibm.com), IBM Corp.
* Substantially cleaned up by:
* Copyright (C) 2003 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ * Copyright (C) 2004-2005 Michael Ellerman, IBM Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -69,22 +70,66 @@
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/ethtool.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/iSeries_pci.h>
+
+#include <asm/abs_addr.h>
+#include <asm/iseries/mf.h>
#include <asm/uaccess.h>
-#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
#include <asm/iommu.h>
#include <asm/vio.h>
-#include "iseries_veth.h"
+#undef DEBUG
MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>");
MODULE_DESCRIPTION("iSeries Virtual ethernet driver");
MODULE_LICENSE("GPL");
+#define VETH_EVENT_CAP (0)
+#define VETH_EVENT_FRAMES (1)
+#define VETH_EVENT_MONITOR (2)
+#define VETH_EVENT_FRAMES_ACK (3)
+
+#define VETH_MAX_ACKS_PER_MSG (20)
+#define VETH_MAX_FRAMES_PER_MSG (6)
+
+struct veth_frames_data {
+ u32 addr[VETH_MAX_FRAMES_PER_MSG];
+ u16 len[VETH_MAX_FRAMES_PER_MSG];
+ u32 eofmask;
+};
+#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG)
+
+struct veth_frames_ack_data {
+ u16 token[VETH_MAX_ACKS_PER_MSG];
+};
+
+struct veth_cap_data {
+ u8 caps_version;
+ u8 rsvd1;
+ u16 num_buffers;
+ u16 ack_threshold;
+ u16 rsvd2;
+ u32 ack_timeout;
+ u32 rsvd3;
+ u64 rsvd4[3];
+};
+
+struct veth_lpevent {
+ struct HvLpEvent base_event;
+ union {
+ struct veth_cap_data caps_data;
+ struct veth_frames_data frames_data;
+ struct veth_frames_ack_data frames_ack_data;
+ } u;
+
+};
+
+#define DRV_NAME "iseries_veth"
+#define DRV_VERSION "2.0"
+
#define VETH_NUMBUFFERS (120)
#define VETH_ACKTIMEOUT (1000000) /* microseconds */
#define VETH_MAX_MCAST (12)
@@ -113,9 +158,9 @@ MODULE_LICENSE("GPL");
struct veth_msg {
struct veth_msg *next;
- struct VethFramesData data;
+ struct veth_frames_data data;
int token;
- unsigned long in_use;
+ int in_use;
struct sk_buff *skb;
struct device *dev;
};
@@ -125,23 +170,28 @@ struct veth_lpar_connection {
struct work_struct statemachine_wq;
struct veth_msg *msgs;
int num_events;
- struct VethCapData local_caps;
+ struct veth_cap_data local_caps;
+ struct kobject kobject;
struct timer_list ack_timer;
+ struct timer_list reset_timer;
+ unsigned int reset_timeout;
+ unsigned long last_contact;
+ int outstanding_tx;
+
spinlock_t lock;
unsigned long state;
HvLpInstanceId src_inst;
HvLpInstanceId dst_inst;
- struct VethLpEvent cap_event, cap_ack_event;
+ struct veth_lpevent cap_event, cap_ack_event;
u16 pending_acks[VETH_MAX_ACKS_PER_MSG];
u32 num_pending_acks;
int num_ack_events;
- struct VethCapData remote_caps;
+ struct veth_cap_data remote_caps;
u32 ack_timeout;
- spinlock_t msg_stack_lock;
struct veth_msg *msg_stack_head;
};
@@ -151,15 +201,17 @@ struct veth_port {
u64 mac_addr;
HvLpIndexMap lpar_map;
- spinlock_t pending_gate;
- struct sk_buff *pending_skb;
- HvLpIndexMap pending_lpmask;
+ /* queue_lock protects the stopped_map and dev's queue. */
+ spinlock_t queue_lock;
+ HvLpIndexMap stopped_map;
+ /* mcast_gate protects promiscuous, num_mcast & mcast_addr. */
rwlock_t mcast_gate;
int promiscuous;
- int all_mcast;
int num_mcast;
u64 mcast_addr[VETH_MAX_MCAST];
+
+ struct kobject kobject;
};
static HvLpIndex this_lp;
@@ -168,44 +220,56 @@ static struct net_device *veth_dev[HVMAXARCHITECTEDVIRTUALLANS]; /* = 0 */
static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *);
-static void veth_flush_pending(struct veth_lpar_connection *cnx);
-static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *);
-static void veth_timed_ack(unsigned long connectionPtr);
+static void veth_wake_queues(struct veth_lpar_connection *cnx);
+static void veth_stop_queues(struct veth_lpar_connection *cnx);
+static void veth_receive(struct veth_lpar_connection *, struct veth_lpevent *);
+static void veth_release_connection(struct kobject *kobject);
+static void veth_timed_ack(unsigned long ptr);
+static void veth_timed_reset(unsigned long ptr);
/*
* Utility functions
*/
-#define veth_printk(prio, fmt, args...) \
- printk(prio "%s: " fmt, __FILE__, ## args)
+#define veth_info(fmt, args...) \
+ printk(KERN_INFO DRV_NAME ": " fmt, ## args)
#define veth_error(fmt, args...) \
- printk(KERN_ERR "(%s:%3.3d) ERROR: " fmt, __FILE__, __LINE__ , ## args)
+ printk(KERN_ERR DRV_NAME ": Error: " fmt, ## args)
+#ifdef DEBUG
+#define veth_debug(fmt, args...) \
+ printk(KERN_DEBUG DRV_NAME ": " fmt, ## args)
+#else
+#define veth_debug(fmt, args...) do {} while (0)
+#endif
+
+/* You must hold the connection's lock when you call this function. */
static inline void veth_stack_push(struct veth_lpar_connection *cnx,
struct veth_msg *msg)
{
- unsigned long flags;
-
- spin_lock_irqsave(&cnx->msg_stack_lock, flags);
msg->next = cnx->msg_stack_head;
cnx->msg_stack_head = msg;
- spin_unlock_irqrestore(&cnx->msg_stack_lock, flags);
}
+/* You must hold the connection's lock when you call this function. */
static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx)
{
- unsigned long flags;
struct veth_msg *msg;
- spin_lock_irqsave(&cnx->msg_stack_lock, flags);
msg = cnx->msg_stack_head;
if (msg)
cnx->msg_stack_head = cnx->msg_stack_head->next;
- spin_unlock_irqrestore(&cnx->msg_stack_lock, flags);
+
return msg;
}
+/* You must hold the connection's lock when you call this function. */
+static inline int veth_stack_is_empty(struct veth_lpar_connection *cnx)
+{
+ return cnx->msg_stack_head == NULL;
+}
+
static inline HvLpEvent_Rc
veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype,
HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype,
@@ -249,7 +313,7 @@ static int veth_allocate_events(HvLpIndex rlp, int number)
struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 };
mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan,
- sizeof(struct VethLpEvent), number,
+ sizeof(struct veth_lpevent), number,
&veth_complete_allocation, &vc);
wait_for_completion(&vc.c);
@@ -257,6 +321,137 @@ static int veth_allocate_events(HvLpIndex rlp, int number)
}
/*
+ * sysfs support
+ */
+
+struct veth_cnx_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct veth_lpar_connection *, char *buf);
+ ssize_t (*store)(struct veth_lpar_connection *, const char *buf);
+};
+
+static ssize_t veth_cnx_attribute_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct veth_cnx_attribute *cnx_attr;
+ struct veth_lpar_connection *cnx;
+
+ cnx_attr = container_of(attr, struct veth_cnx_attribute, attr);
+ cnx = container_of(kobj, struct veth_lpar_connection, kobject);
+
+ if (!cnx_attr->show)
+ return -EIO;
+
+ return cnx_attr->show(cnx, buf);
+}
+
+#define CUSTOM_CNX_ATTR(_name, _format, _expression) \
+static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\
+{ \
+ return sprintf(buf, _format, _expression); \
+} \
+struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name)
+
+#define SIMPLE_CNX_ATTR(_name) \
+ CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name)
+
+SIMPLE_CNX_ATTR(outstanding_tx);
+SIMPLE_CNX_ATTR(remote_lp);
+SIMPLE_CNX_ATTR(num_events);
+SIMPLE_CNX_ATTR(src_inst);
+SIMPLE_CNX_ATTR(dst_inst);
+SIMPLE_CNX_ATTR(num_pending_acks);
+SIMPLE_CNX_ATTR(num_ack_events);
+CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout));
+CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout));
+CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state);
+CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ?
+ jiffies_to_msecs(jiffies - cnx->last_contact) : 0);
+
+#define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr)
+
+static struct attribute *veth_cnx_default_attrs[] = {
+ GET_CNX_ATTR(outstanding_tx),
+ GET_CNX_ATTR(remote_lp),
+ GET_CNX_ATTR(num_events),
+ GET_CNX_ATTR(reset_timeout),
+ GET_CNX_ATTR(last_contact),
+ GET_CNX_ATTR(state),
+ GET_CNX_ATTR(src_inst),
+ GET_CNX_ATTR(dst_inst),
+ GET_CNX_ATTR(num_pending_acks),
+ GET_CNX_ATTR(num_ack_events),
+ GET_CNX_ATTR(ack_timeout),
+ NULL
+};
+
+static struct sysfs_ops veth_cnx_sysfs_ops = {
+ .show = veth_cnx_attribute_show
+};
+
+static struct kobj_type veth_lpar_connection_ktype = {
+ .release = veth_release_connection,
+ .sysfs_ops = &veth_cnx_sysfs_ops,
+ .default_attrs = veth_cnx_default_attrs
+};
+
+struct veth_port_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct veth_port *, char *buf);
+ ssize_t (*store)(struct veth_port *, const char *buf);
+};
+
+static ssize_t veth_port_attribute_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct veth_port_attribute *port_attr;
+ struct veth_port *port;
+
+ port_attr = container_of(attr, struct veth_port_attribute, attr);
+ port = container_of(kobj, struct veth_port, kobject);
+
+ if (!port_attr->show)
+ return -EIO;
+
+ return port_attr->show(port, buf);
+}
+
+#define CUSTOM_PORT_ATTR(_name, _format, _expression) \
+static ssize_t _name##_show(struct veth_port *port, char *buf) \
+{ \
+ return sprintf(buf, _format, _expression); \
+} \
+struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name)
+
+#define SIMPLE_PORT_ATTR(_name) \
+ CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name)
+
+SIMPLE_PORT_ATTR(promiscuous);
+SIMPLE_PORT_ATTR(num_mcast);
+CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map);
+CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map);
+CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr);
+
+#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr)
+static struct attribute *veth_port_default_attrs[] = {
+ GET_PORT_ATTR(mac_addr),
+ GET_PORT_ATTR(lpar_map),
+ GET_PORT_ATTR(stopped_map),
+ GET_PORT_ATTR(promiscuous),
+ GET_PORT_ATTR(num_mcast),
+ NULL
+};
+
+static struct sysfs_ops veth_port_sysfs_ops = {
+ .show = veth_port_attribute_show
+};
+
+static struct kobj_type veth_port_ktype = {
+ .sysfs_ops = &veth_port_sysfs_ops,
+ .default_attrs = veth_port_default_attrs
+};
+
+/*
* LPAR connection code
*/
@@ -266,7 +461,7 @@ static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx)
}
static void veth_take_cap(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
@@ -278,7 +473,7 @@ static void veth_take_cap(struct veth_lpar_connection *cnx,
HvLpEvent_Type_VirtualLan);
if (cnx->state & VETH_STATE_GOTCAPS) {
- veth_error("Received a second capabilities from lpar %d\n",
+ veth_error("Received a second capabilities from LPAR %d.\n",
cnx->remote_lp);
event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable;
HvCallEvent_ackLpEvent((struct HvLpEvent *) event);
@@ -291,13 +486,13 @@ static void veth_take_cap(struct veth_lpar_connection *cnx,
}
static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
spin_lock_irqsave(&cnx->lock, flags);
if (cnx->state & VETH_STATE_GOTCAPACK) {
- veth_error("Received a second capabilities ack from lpar %d\n",
+ veth_error("Received a second capabilities ack from LPAR %d.\n",
cnx->remote_lp);
} else {
memcpy(&cnx->cap_ack_event, event,
@@ -309,19 +504,24 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx,
}
static void veth_take_monitor_ack(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
unsigned long flags;
spin_lock_irqsave(&cnx->lock, flags);
- veth_printk(KERN_DEBUG, "Monitor ack returned for lpar %d\n",
- cnx->remote_lp);
- cnx->state |= VETH_STATE_RESET;
- veth_kick_statemachine(cnx);
+ veth_debug("cnx %d: lost connection.\n", cnx->remote_lp);
+
+ /* Avoid kicking the statemachine once we're shutdown.
+ * It's unnecessary and it could break veth_stop_connection(). */
+
+ if (! (cnx->state & VETH_STATE_SHUTDOWN)) {
+ cnx->state |= VETH_STATE_RESET;
+ veth_kick_statemachine(cnx);
+ }
spin_unlock_irqrestore(&cnx->lock, flags);
}
-static void veth_handle_ack(struct VethLpEvent *event)
+static void veth_handle_ack(struct veth_lpevent *event)
{
HvLpIndex rlp = event->base_event.xTargetLp;
struct veth_lpar_connection *cnx = veth_cnx[rlp];
@@ -329,58 +529,67 @@ static void veth_handle_ack(struct VethLpEvent *event)
BUG_ON(! cnx);
switch (event->base_event.xSubtype) {
- case VethEventTypeCap:
+ case VETH_EVENT_CAP:
veth_take_cap_ack(cnx, event);
break;
- case VethEventTypeMonitor:
+ case VETH_EVENT_MONITOR:
veth_take_monitor_ack(cnx, event);
break;
default:
- veth_error("Unknown ack type %d from lpar %d\n",
- event->base_event.xSubtype, rlp);
+ veth_error("Unknown ack type %d from LPAR %d.\n",
+ event->base_event.xSubtype, rlp);
};
}
-static void veth_handle_int(struct VethLpEvent *event)
+static void veth_handle_int(struct veth_lpevent *event)
{
HvLpIndex rlp = event->base_event.xSourceLp;
struct veth_lpar_connection *cnx = veth_cnx[rlp];
unsigned long flags;
- int i;
+ int i, acked = 0;
BUG_ON(! cnx);
switch (event->base_event.xSubtype) {
- case VethEventTypeCap:
+ case VETH_EVENT_CAP:
veth_take_cap(cnx, event);
break;
- case VethEventTypeMonitor:
+ case VETH_EVENT_MONITOR:
/* do nothing... this'll hang out here til we're dead,
* and the hypervisor will return it for us. */
break;
- case VethEventTypeFramesAck:
+ case VETH_EVENT_FRAMES_ACK:
spin_lock_irqsave(&cnx->lock, flags);
+
for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) {
u16 msgnum = event->u.frames_ack_data.token[i];
- if (msgnum < VETH_NUMBUFFERS)
+ if (msgnum < VETH_NUMBUFFERS) {
veth_recycle_msg(cnx, cnx->msgs + msgnum);
+ cnx->outstanding_tx--;
+ acked++;
+ }
+ }
+
+ if (acked > 0) {
+ cnx->last_contact = jiffies;
+ veth_wake_queues(cnx);
}
+
spin_unlock_irqrestore(&cnx->lock, flags);
- veth_flush_pending(cnx);
break;
- case VethEventTypeFrames:
+ case VETH_EVENT_FRAMES:
veth_receive(cnx, event);
break;
default:
- veth_error("Unknown interrupt type %d from lpar %d\n",
- event->base_event.xSubtype, rlp);
+ veth_error("Unknown interrupt type %d from LPAR %d.\n",
+ event->base_event.xSubtype, rlp);
};
}
static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
{
- struct VethLpEvent *veth_event = (struct VethLpEvent *)event;
+ struct veth_lpevent *veth_event = (struct veth_lpevent *)event;
if (event->xFlags.xFunction == HvLpEvent_Function_Ack)
veth_handle_ack(veth_event);
@@ -390,7 +599,7 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
static int veth_process_caps(struct veth_lpar_connection *cnx)
{
- struct VethCapData *remote_caps = &cnx->remote_caps;
+ struct veth_cap_data *remote_caps = &cnx->remote_caps;
int num_acks_needed;
/* Convert timer to jiffies */
@@ -400,8 +609,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx)
|| (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG)
|| (remote_caps->ack_threshold == 0)
|| (cnx->ack_timeout == 0) ) {
- veth_error("Received incompatible capabilities from lpar %d\n",
- cnx->remote_lp);
+ veth_error("Received incompatible capabilities from LPAR %d.\n",
+ cnx->remote_lp);
return HvLpEvent_Rc_InvalidSubtypeData;
}
@@ -418,8 +627,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx)
cnx->num_ack_events += num;
if (cnx->num_ack_events < num_acks_needed) {
- veth_error("Couldn't allocate enough ack events for lpar %d\n",
- cnx->remote_lp);
+ veth_error("Couldn't allocate enough ack events "
+ "for LPAR %d.\n", cnx->remote_lp);
return HvLpEvent_Rc_BufferNotAvailable;
}
@@ -440,15 +649,15 @@ static void veth_statemachine(void *p)
restart:
if (cnx->state & VETH_STATE_RESET) {
- int i;
-
- del_timer(&cnx->ack_timer);
-
if (cnx->state & VETH_STATE_OPEN)
HvCallEvent_closeLpEventPath(cnx->remote_lp,
HvLpEvent_Type_VirtualLan);
- /* reset ack data */
+ /*
+ * Reset ack data. This prevents the ack_timer actually
+ * doing anything, even if it runs one more time when
+ * we drop the lock below.
+ */
memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks));
cnx->num_pending_acks = 0;
@@ -458,14 +667,32 @@ static void veth_statemachine(void *p)
| VETH_STATE_SENTCAPACK | VETH_STATE_READY);
/* Clean up any leftover messages */
- if (cnx->msgs)
+ if (cnx->msgs) {
+ int i;
for (i = 0; i < VETH_NUMBUFFERS; ++i)
veth_recycle_msg(cnx, cnx->msgs + i);
+ }
+
+ cnx->outstanding_tx = 0;
+ veth_wake_queues(cnx);
+
+ /* Drop the lock so we can do stuff that might sleep or
+ * take other locks. */
spin_unlock_irq(&cnx->lock);
- veth_flush_pending(cnx);
+
+ del_timer_sync(&cnx->ack_timer);
+ del_timer_sync(&cnx->reset_timer);
+
spin_lock_irq(&cnx->lock);
+
if (cnx->state & VETH_STATE_RESET)
goto restart;
+
+ /* Hack, wait for the other end to reset itself. */
+ if (! (cnx->state & VETH_STATE_SHUTDOWN)) {
+ schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ);
+ goto out;
+ }
}
if (cnx->state & VETH_STATE_SHUTDOWN)
@@ -488,7 +715,7 @@ static void veth_statemachine(void *p)
if ( (cnx->state & VETH_STATE_OPEN)
&& !(cnx->state & VETH_STATE_SENTMON) ) {
- rc = veth_signalevent(cnx, VethEventTypeMonitor,
+ rc = veth_signalevent(cnx, VETH_EVENT_MONITOR,
HvLpEvent_AckInd_DoAck,
HvLpEvent_AckType_DeferredAck,
0, 0, 0, 0, 0, 0);
@@ -498,9 +725,8 @@ static void veth_statemachine(void *p)
} else {
if ( (rc != HvLpEvent_Rc_PartitionDead)
&& (rc != HvLpEvent_Rc_PathClosed) )
- veth_error("Error sending monitor to "
- "lpar %d, rc=%x\n",
- rlp, (int) rc);
+ veth_error("Error sending monitor to LPAR %d, "
+ "rc = %d\n", rlp, rc);
/* Oh well, hope we get a cap from the other
* end and do better when that kicks us */
@@ -512,7 +738,7 @@ static void veth_statemachine(void *p)
&& !(cnx->state & VETH_STATE_SENTCAPS)) {
u64 *rawcap = (u64 *)&cnx->local_caps;
- rc = veth_signalevent(cnx, VethEventTypeCap,
+ rc = veth_signalevent(cnx, VETH_EVENT_CAP,
HvLpEvent_AckInd_DoAck,
HvLpEvent_AckType_ImmediateAck,
0, rawcap[0], rawcap[1], rawcap[2],
@@ -523,9 +749,9 @@ static void veth_statemachine(void *p)
} else {
if ( (rc != HvLpEvent_Rc_PartitionDead)
&& (rc != HvLpEvent_Rc_PathClosed) )
- veth_error("Error sending caps to "
- "lpar %d, rc=%x\n",
- rlp, (int) rc);
+ veth_error("Error sending caps to LPAR %d, "
+ "rc = %d\n", rlp, rc);
+
/* Oh well, hope we get a cap from the other
* end and do better when that kicks us */
goto out;
@@ -534,7 +760,7 @@ static void veth_statemachine(void *p)
if ((cnx->state & VETH_STATE_GOTCAPS)
&& !(cnx->state & VETH_STATE_SENTCAPACK)) {
- struct VethCapData *remote_caps = &cnx->remote_caps;
+ struct veth_cap_data *remote_caps = &cnx->remote_caps;
memcpy(remote_caps, &cnx->cap_event.u.caps_data,
sizeof(*remote_caps));
@@ -565,10 +791,8 @@ static void veth_statemachine(void *p)
add_timer(&cnx->ack_timer);
cnx->state |= VETH_STATE_READY;
} else {
- veth_printk(KERN_ERR, "Caps rejected (rc=%d) by "
- "lpar %d\n",
- cnx->cap_ack_event.base_event.xRc,
- rlp);
+ veth_error("Caps rejected by LPAR %d, rc = %d\n",
+ rlp, cnx->cap_ack_event.base_event.xRc);
goto cant_cope;
}
}
@@ -581,8 +805,8 @@ static void veth_statemachine(void *p)
/* FIXME: we get here if something happens we really can't
* cope with. The link will never work once we get here, and
* all we can do is not lock the rest of the system up */
- veth_error("Badness on connection to lpar %d (state=%04lx) "
- " - shutting down\n", rlp, cnx->state);
+ veth_error("Unrecoverable error on connection to LPAR %d, shutting down"
+ " (state = 0x%04lx)\n", rlp, cnx->state);
cnx->state |= VETH_STATE_SHUTDOWN;
spin_unlock_irq(&cnx->lock);
}
@@ -591,7 +815,7 @@ static int veth_init_connection(u8 rlp)
{
struct veth_lpar_connection *cnx;
struct veth_msg *msgs;
- int i;
+ int i, rc;
if ( (rlp == this_lp)
|| ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) )
@@ -605,22 +829,36 @@ static int veth_init_connection(u8 rlp)
cnx->remote_lp = rlp;
spin_lock_init(&cnx->lock);
INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx);
+
init_timer(&cnx->ack_timer);
cnx->ack_timer.function = veth_timed_ack;
cnx->ack_timer.data = (unsigned long) cnx;
+
+ init_timer(&cnx->reset_timer);
+ cnx->reset_timer.function = veth_timed_reset;
+ cnx->reset_timer.data = (unsigned long) cnx;
+ cnx->reset_timeout = 5 * HZ * (VETH_ACKTIMEOUT / 1000000);
+
memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks));
veth_cnx[rlp] = cnx;
+ /* This gets us 1 reference, which is held on behalf of the driver
+ * infrastructure. It's released at module unload. */
+ kobject_init(&cnx->kobject);
+ cnx->kobject.ktype = &veth_lpar_connection_ktype;
+ rc = kobject_set_name(&cnx->kobject, "cnx%.2d", rlp);
+ if (rc != 0)
+ return rc;
+
msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL);
if (! msgs) {
- veth_error("Can't allocate buffers for lpar %d\n", rlp);
+ veth_error("Can't allocate buffers for LPAR %d.\n", rlp);
return -ENOMEM;
}
cnx->msgs = msgs;
memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg));
- spin_lock_init(&cnx->msg_stack_lock);
for (i = 0; i < VETH_NUMBUFFERS; i++) {
msgs[i].token = i;
@@ -630,8 +868,7 @@ static int veth_init_connection(u8 rlp)
cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS);
if (cnx->num_events < (2 + VETH_NUMBUFFERS)) {
- veth_error("Can't allocate events for lpar %d, only got %d\n",
- rlp, cnx->num_events);
+ veth_error("Can't allocate enough events for LPAR %d.\n", rlp);
return -ENOMEM;
}
@@ -642,11 +879,9 @@ static int veth_init_connection(u8 rlp)
return 0;
}
-static void veth_stop_connection(u8 rlp)
+static void veth_stop_connection(struct veth_lpar_connection *cnx)
{
- struct veth_lpar_connection *cnx = veth_cnx[rlp];
-
- if (! cnx)
+ if (!cnx)
return;
spin_lock_irq(&cnx->lock);
@@ -654,12 +889,23 @@ static void veth_stop_connection(u8 rlp)
veth_kick_statemachine(cnx);
spin_unlock_irq(&cnx->lock);
+ /* There's a slim chance the reset code has just queued the
+ * statemachine to run in five seconds. If so we need to cancel
+ * that and requeue the work to run now. */
+ if (cancel_delayed_work(&cnx->statemachine_wq)) {
+ spin_lock_irq(&cnx->lock);
+ veth_kick_statemachine(cnx);
+ spin_unlock_irq(&cnx->lock);
+ }
+
+ /* Wait for the state machine to run. */
flush_scheduled_work();
+}
- /* FIXME: not sure if this is necessary - will already have
- * been deleted by the state machine, just want to make sure
- * its not running any more */
- del_timer_sync(&cnx->ack_timer);
+static void veth_destroy_connection(struct veth_lpar_connection *cnx)
+{
+ if (!cnx)
+ return;
if (cnx->num_events > 0)
mf_deallocate_lp_events(cnx->remote_lp,
@@ -671,18 +917,18 @@ static void veth_stop_connection(u8 rlp)
HvLpEvent_Type_VirtualLan,
cnx->num_ack_events,
NULL, NULL);
-}
-
-static void veth_destroy_connection(u8 rlp)
-{
- struct veth_lpar_connection *cnx = veth_cnx[rlp];
-
- if (! cnx)
- return;
kfree(cnx->msgs);
+ veth_cnx[cnx->remote_lp] = NULL;
kfree(cnx);
- veth_cnx[rlp] = NULL;
+}
+
+static void veth_release_connection(struct kobject *kobj)
+{
+ struct veth_lpar_connection *cnx;
+ cnx = container_of(kobj, struct veth_lpar_connection, kobject);
+ veth_stop_connection(cnx);
+ veth_destroy_connection(cnx);
}
/*
@@ -726,17 +972,15 @@ static void veth_set_multicast_list(struct net_device *dev)
write_lock_irqsave(&port->mcast_gate, flags);
- if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
- printk(KERN_INFO "%s: Promiscuous mode enabled.\n",
- dev->name);
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
+ (dev->mc_count > VETH_MAX_MCAST)) {
port->promiscuous = 1;
- } else if ( (dev->flags & IFF_ALLMULTI)
- || (dev->mc_count > VETH_MAX_MCAST) ) {
- port->all_mcast = 1;
} else {
struct dev_mc_list *dmi = dev->mc_list;
int i;
+ port->promiscuous = 0;
+
/* Update table */
port->num_mcast = 0;
@@ -758,9 +1002,10 @@ static void veth_set_multicast_list(struct net_device *dev)
static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- strncpy(info->driver, "veth", sizeof(info->driver) - 1);
+ strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
info->driver[sizeof(info->driver) - 1] = '\0';
- strncpy(info->version, "1.0", sizeof(info->version) - 1);
+ strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+ info->version[sizeof(info->version) - 1] = '\0';
}
static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -791,49 +1036,6 @@ static struct ethtool_ops ops = {
.get_link = veth_get_link,
};
-static void veth_tx_timeout(struct net_device *dev)
-{
- struct veth_port *port = (struct veth_port *)dev->priv;
- struct net_device_stats *stats = &port->stats;
- unsigned long flags;
- int i;
-
- stats->tx_errors++;
-
- spin_lock_irqsave(&port->pending_gate, flags);
-
- if (!port->pending_lpmask) {
- spin_unlock_irqrestore(&port->pending_gate, flags);
- return;
- }
-
- printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n",
- dev->name, port->pending_lpmask);
-
- for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
- struct veth_lpar_connection *cnx = veth_cnx[i];
-
- if (! (port->pending_lpmask & (1<<i)))
- continue;
-
- /* If we're pending on it, we must be connected to it,
- * so we should certainly have a structure for it. */
- BUG_ON(! cnx);
-
- /* Theoretically we could be kicking a connection
- * which doesn't deserve it, but in practice if we've
- * had a Tx timeout, the pending_lpmask will have
- * exactly one bit set - the connection causing the
- * problem. */
- spin_lock(&cnx->lock);
- cnx->state |= VETH_STATE_RESET;
- veth_kick_statemachine(cnx);
- spin_unlock(&cnx->lock);
- }
-
- spin_unlock_irqrestore(&port->pending_gate, flags);
-}
-
static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
{
struct net_device *dev;
@@ -848,8 +1050,9 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
port = (struct veth_port *) dev->priv;
- spin_lock_init(&port->pending_gate);
+ spin_lock_init(&port->queue_lock);
rwlock_init(&port->mcast_gate);
+ port->stopped_map = 0;
for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
HvLpVirtualLanIndexMap map;
@@ -882,22 +1085,24 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
dev->set_multicast_list = veth_set_multicast_list;
SET_ETHTOOL_OPS(dev, &ops);
- dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000);
- dev->tx_timeout = veth_tx_timeout;
-
SET_NETDEV_DEV(dev, vdev);
rc = register_netdev(dev);
if (rc != 0) {
- veth_printk(KERN_ERR,
- "Failed to register ethernet device for vlan %d\n",
- vlan);
+ veth_error("Failed registering net device for vlan%d.\n", vlan);
free_netdev(dev);
return NULL;
}
- veth_printk(KERN_DEBUG, "%s attached to iSeries vlan %d (lpar_map=0x%04x)\n",
- dev->name, vlan, port->lpar_map);
+ kobject_init(&port->kobject);
+ port->kobject.parent = &dev->class_dev.kobj;
+ port->kobject.ktype = &veth_port_ktype;
+ kobject_set_name(&port->kobject, "veth_port");
+ if (0 != kobject_add(&port->kobject))
+ veth_error("Failed adding port for %s to sysfs.\n", dev->name);
+
+ veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n",
+ dev->name, vlan, port->lpar_map);
return dev;
}
@@ -912,98 +1117,95 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
struct veth_lpar_connection *cnx = veth_cnx[rlp];
struct veth_port *port = (struct veth_port *) dev->priv;
HvLpEvent_Rc rc;
- u32 dma_address, dma_length;
struct veth_msg *msg = NULL;
- int err = 0;
unsigned long flags;
- if (! cnx) {
- port->stats.tx_errors++;
- dev_kfree_skb(skb);
+ if (! cnx)
return 0;
- }
spin_lock_irqsave(&cnx->lock, flags);
if (! (cnx->state & VETH_STATE_READY))
- goto drop;
+ goto no_error;
- if ((skb->len - 14) > VETH_MAX_MTU)
+ if ((skb->len - ETH_HLEN) > VETH_MAX_MTU)
goto drop;
msg = veth_stack_pop(cnx);
-
- if (! msg) {
- err = 1;
+ if (! msg)
goto drop;
- }
- dma_length = skb->len;
- dma_address = dma_map_single(port->dev, skb->data,
- dma_length, DMA_TO_DEVICE);
+ msg->in_use = 1;
+ msg->skb = skb_get(skb);
- if (dma_mapping_error(dma_address))
+ msg->data.addr[0] = dma_map_single(port->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+
+ if (dma_mapping_error(msg->data.addr[0]))
goto recycle_and_drop;
- /* Is it really necessary to check the length and address
- * fields of the first entry here? */
- msg->skb = skb;
msg->dev = port->dev;
- msg->data.addr[0] = dma_address;
- msg->data.len[0] = dma_length;
+ msg->data.len[0] = skb->len;
msg->data.eofmask = 1 << VETH_EOF_SHIFT;
- set_bit(0, &(msg->in_use));
- rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data);
+
+ rc = veth_signaldata(cnx, VETH_EVENT_FRAMES, msg->token, &msg->data);
if (rc != HvLpEvent_Rc_Good)
goto recycle_and_drop;
+ /* If the timer's not already running, start it now. */
+ if (0 == cnx->outstanding_tx)
+ mod_timer(&cnx->reset_timer, jiffies + cnx->reset_timeout);
+
+ cnx->last_contact = jiffies;
+ cnx->outstanding_tx++;
+
+ if (veth_stack_is_empty(cnx))
+ veth_stop_queues(cnx);
+
+ no_error:
spin_unlock_irqrestore(&cnx->lock, flags);
return 0;
recycle_and_drop:
- msg->skb = NULL;
- /* need to set in use to make veth_recycle_msg in case this
- * was a mapping failure */
- set_bit(0, &msg->in_use);
veth_recycle_msg(cnx, msg);
drop:
- port->stats.tx_errors++;
- dev_kfree_skb(skb);
spin_unlock_irqrestore(&cnx->lock, flags);
- return err;
+ return 1;
}
-static HvLpIndexMap veth_transmit_to_many(struct sk_buff *skb,
+static void veth_transmit_to_many(struct sk_buff *skb,
HvLpIndexMap lpmask,
struct net_device *dev)
{
struct veth_port *port = (struct veth_port *) dev->priv;
- int i;
- int rc;
+ int i, success, error;
+
+ success = error = 0;
for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
if ((lpmask & (1 << i)) == 0)
continue;
- rc = veth_transmit_to_one(skb_get(skb), i, dev);
- if (! rc)
- lpmask &= ~(1<<i);
+ if (veth_transmit_to_one(skb, i, dev))
+ error = 1;
+ else
+ success = 1;
}
- if (! lpmask) {
+ if (error)
+ port->stats.tx_errors++;
+
+ if (success) {
port->stats.tx_packets++;
port->stats.tx_bytes += skb->len;
}
-
- return lpmask;
}
static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *frame = skb->data;
struct veth_port *port = (struct veth_port *) dev->priv;
- unsigned long flags;
HvLpIndexMap lpmask;
if (! (frame[0] & 0x01)) {
@@ -1020,44 +1222,27 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
lpmask = port->lpar_map;
}
- spin_lock_irqsave(&port->pending_gate, flags);
-
- lpmask = veth_transmit_to_many(skb, lpmask, dev);
+ veth_transmit_to_many(skb, lpmask, dev);
- dev->trans_start = jiffies;
-
- if (! lpmask) {
- dev_kfree_skb(skb);
- } else {
- if (port->pending_skb) {
- veth_error("%s: Tx while skb was pending!\n",
- dev->name);
- dev_kfree_skb(skb);
- spin_unlock_irqrestore(&port->pending_gate, flags);
- return 1;
- }
-
- port->pending_skb = skb;
- port->pending_lpmask = lpmask;
- netif_stop_queue(dev);
- }
-
- spin_unlock_irqrestore(&port->pending_gate, flags);
+ dev_kfree_skb(skb);
return 0;
}
+/* You must hold the connection's lock when you call this function. */
static void veth_recycle_msg(struct veth_lpar_connection *cnx,
struct veth_msg *msg)
{
u32 dma_address, dma_length;
- if (test_and_clear_bit(0, &msg->in_use)) {
+ if (msg->in_use) {
+ msg->in_use = 0;
dma_address = msg->data.addr[0];
dma_length = msg->data.len[0];
- dma_unmap_single(msg->dev, dma_address, dma_length,
- DMA_TO_DEVICE);
+ if (!dma_mapping_error(dma_address))
+ dma_unmap_single(msg->dev, dma_address, dma_length,
+ DMA_TO_DEVICE);
if (msg->skb) {
dev_kfree_skb_any(msg->skb);
@@ -1066,15 +1251,16 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx,
memset(&msg->data, 0, sizeof(msg->data));
veth_stack_push(cnx, msg);
- } else
- if (cnx->state & VETH_STATE_OPEN)
- veth_error("Bogus frames ack from lpar %d (#%d)\n",
- cnx->remote_lp, msg->token);
+ } else if (cnx->state & VETH_STATE_OPEN) {
+ veth_error("Non-pending frame (# %d) acked by LPAR %d.\n",
+ cnx->remote_lp, msg->token);
+ }
}
-static void veth_flush_pending(struct veth_lpar_connection *cnx)
+static void veth_wake_queues(struct veth_lpar_connection *cnx)
{
int i;
+
for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
struct net_device *dev = veth_dev[i];
struct veth_port *port;
@@ -1088,22 +1274,79 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx)
if (! (port->lpar_map & (1<<cnx->remote_lp)))
continue;
- spin_lock_irqsave(&port->pending_gate, flags);
- if (port->pending_skb) {
- port->pending_lpmask =
- veth_transmit_to_many(port->pending_skb,
- port->pending_lpmask,
- dev);
- if (! port->pending_lpmask) {
- dev_kfree_skb_any(port->pending_skb);
- port->pending_skb = NULL;
- netif_wake_queue(dev);
- }
+ spin_lock_irqsave(&port->queue_lock, flags);
+
+ port->stopped_map &= ~(1 << cnx->remote_lp);
+
+ if (0 == port->stopped_map && netif_queue_stopped(dev)) {
+ veth_debug("cnx %d: woke queue for %s.\n",
+ cnx->remote_lp, dev->name);
+ netif_wake_queue(dev);
}
- spin_unlock_irqrestore(&port->pending_gate, flags);
+ spin_unlock_irqrestore(&port->queue_lock, flags);
}
}
+static void veth_stop_queues(struct veth_lpar_connection *cnx)
+{
+ int i;
+
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+ struct net_device *dev = veth_dev[i];
+ struct veth_port *port;
+
+ if (! dev)
+ continue;
+
+ port = (struct veth_port *)dev->priv;
+
+ /* If this cnx is not on the vlan for this port, continue */
+ if (! (port->lpar_map & (1 << cnx->remote_lp)))
+ continue;
+
+ spin_lock(&port->queue_lock);
+
+ netif_stop_queue(dev);
+ port->stopped_map |= (1 << cnx->remote_lp);
+
+ veth_debug("cnx %d: stopped queue for %s, map = 0x%x.\n",
+ cnx->remote_lp, dev->name, port->stopped_map);
+
+ spin_unlock(&port->queue_lock);
+ }
+}
+
+static void veth_timed_reset(unsigned long ptr)
+{
+ struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)ptr;
+ unsigned long trigger_time, flags;
+
+ /* FIXME is it possible this fires after veth_stop_connection()?
+ * That would reschedule the statemachine for 5 seconds and probably
+ * execute it after the module's been unloaded. Hmm. */
+
+ spin_lock_irqsave(&cnx->lock, flags);
+
+ if (cnx->outstanding_tx > 0) {
+ trigger_time = cnx->last_contact + cnx->reset_timeout;
+
+ if (trigger_time < jiffies) {
+ cnx->state |= VETH_STATE_RESET;
+ veth_kick_statemachine(cnx);
+ veth_error("%d packets not acked by LPAR %d within %d "
+ "seconds, resetting.\n",
+ cnx->outstanding_tx, cnx->remote_lp,
+ cnx->reset_timeout / HZ);
+ } else {
+ /* Reschedule the timer */
+ trigger_time = jiffies + cnx->reset_timeout;
+ mod_timer(&cnx->reset_timer, trigger_time);
+ }
+ }
+
+ spin_unlock_irqrestore(&cnx->lock, flags);
+}
+
/*
* Rx path
*/
@@ -1117,12 +1360,9 @@ static inline int veth_frame_wanted(struct veth_port *port, u64 mac_addr)
if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) )
return 1;
- if (! (((char *) &mac_addr)[0] & 0x01))
- return 0;
-
read_lock_irqsave(&port->mcast_gate, flags);
- if (port->promiscuous || port->all_mcast) {
+ if (port->promiscuous) {
wanted = 1;
goto out;
}
@@ -1158,13 +1398,13 @@ static inline void veth_build_dma_list(struct dma_chunk *list,
* it just at the granularity of iSeries real->absolute
* mapping? Indeed, given the way the allocator works, can we
* count on them being absolutely contiguous? */
- list[0].addr = ISERIES_HV_ADDR(p);
+ list[0].addr = iseries_hv_addr(p);
list[0].size = min(length,
PAGE_SIZE - ((unsigned long)p & ~PAGE_MASK));
done = list[0].size;
while (done < length) {
- list[i].addr = ISERIES_HV_ADDR(p + done);
+ list[i].addr = iseries_hv_addr(p + done);
list[i].size = min(length-done, PAGE_SIZE);
done += list[i].size;
i++;
@@ -1175,21 +1415,21 @@ static void veth_flush_acks(struct veth_lpar_connection *cnx)
{
HvLpEvent_Rc rc;
- rc = veth_signaldata(cnx, VethEventTypeFramesAck,
+ rc = veth_signaldata(cnx, VETH_EVENT_FRAMES_ACK,
0, &cnx->pending_acks);
if (rc != HvLpEvent_Rc_Good)
- veth_error("Error 0x%x acking frames from lpar %d!\n",
- (unsigned)rc, cnx->remote_lp);
+ veth_error("Failed acking frames from LPAR %d, rc = %d\n",
+ cnx->remote_lp, (int)rc);
cnx->num_pending_acks = 0;
memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks));
}
static void veth_receive(struct veth_lpar_connection *cnx,
- struct VethLpEvent *event)
+ struct veth_lpevent *event)
{
- struct VethFramesData *senddata = &event->u.frames_data;
+ struct veth_frames_data *senddata = &event->u.frames_data;
int startchunk = 0;
int nchunks;
unsigned long flags;
@@ -1216,9 +1456,10 @@ static void veth_receive(struct veth_lpar_connection *cnx,
/* make sure that we have at least 1 EOF entry in the
* remaining entries */
if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) {
- veth_error("missing EOF frag in event "
- "eofmask=0x%x startchunk=%d\n",
- (unsigned) senddata->eofmask, startchunk);
+ veth_error("Missing EOF fragment in event "
+ "eofmask = 0x%x startchunk = %d\n",
+ (unsigned)senddata->eofmask,
+ startchunk);
break;
}
@@ -1237,8 +1478,9 @@ static void veth_receive(struct veth_lpar_connection *cnx,
/* nchunks == # of chunks in this frame */
if ((length - ETH_HLEN) > VETH_MAX_MTU) {
- veth_error("Received oversize frame from lpar %d "
- "(length=%d)\n", cnx->remote_lp, length);
+ veth_error("Received oversize frame from LPAR %d "
+ "(length = %d)\n",
+ cnx->remote_lp, length);
continue;
}
@@ -1255,8 +1497,8 @@ static void veth_receive(struct veth_lpar_connection *cnx,
cnx->dst_inst,
HvLpDma_AddressType_RealAddress,
HvLpDma_AddressType_TceIndex,
- ISERIES_HV_ADDR(&local_list),
- ISERIES_HV_ADDR(&remote_list),
+ iseries_hv_addr(&local_list),
+ iseries_hv_addr(&remote_list),
length);
if (rc != HvLpDma_Rc_Good) {
dev_kfree_skb_irq(skb);
@@ -1331,15 +1573,33 @@ static void veth_timed_ack(unsigned long ptr)
static int veth_remove(struct vio_dev *vdev)
{
- int i = vdev->unit_address;
+ struct veth_lpar_connection *cnx;
struct net_device *dev;
+ struct veth_port *port;
+ int i;
- dev = veth_dev[i];
- if (dev != NULL) {
- veth_dev[i] = NULL;
- unregister_netdev(dev);
- free_netdev(dev);
+ dev = veth_dev[vdev->unit_address];
+
+ if (! dev)
+ return 0;
+
+ port = netdev_priv(dev);
+
+ for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
+ cnx = veth_cnx[i];
+
+ if (cnx && (port->lpar_map & (1 << i))) {
+ /* Drop our reference to connections on our VLAN */
+ kobject_put(&cnx->kobject);
+ }
}
+
+ veth_dev[vdev->unit_address] = NULL;
+ kobject_del(&port->kobject);
+ kobject_put(&port->kobject);
+ unregister_netdev(dev);
+ free_netdev(dev);
+
return 0;
}
@@ -1347,6 +1607,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
int i = vdev->unit_address;
struct net_device *dev;
+ struct veth_port *port;
dev = veth_probe_one(i, &vdev->dev);
if (dev == NULL) {
@@ -1355,11 +1616,23 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
veth_dev[i] = dev;
- /* Start the state machine on each connection, to commence
- * link negotiation */
- for (i = 0; i < HVMAXARCHITECTEDLPS; i++)
- if (veth_cnx[i])
- veth_kick_statemachine(veth_cnx[i]);
+ port = (struct veth_port*)netdev_priv(dev);
+
+ /* Start the state machine on each connection on this vlan. If we're
+ * the first dev to do so this will commence link negotiation */
+ for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
+ struct veth_lpar_connection *cnx;
+
+ if (! (port->lpar_map & (1 << i)))
+ continue;
+
+ cnx = veth_cnx[i];
+ if (!cnx)
+ continue;
+
+ kobject_get(&cnx->kobject);
+ veth_kick_statemachine(cnx);
+ }
return 0;
}
@@ -1370,15 +1643,18 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
*/
static struct vio_device_id veth_device_table[] __devinitdata = {
{ "vlan", "" },
- { NULL, NULL }
+ { "", "" }
};
MODULE_DEVICE_TABLE(vio, veth_device_table);
static struct vio_driver veth_driver = {
- .name = "iseries_veth",
.id_table = veth_device_table,
.probe = veth_probe,
- .remove = veth_remove
+ .remove = veth_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ }
};
/*
@@ -1388,29 +1664,29 @@ static struct vio_driver veth_driver = {
void __exit veth_module_cleanup(void)
{
int i;
+ struct veth_lpar_connection *cnx;
- /* Stop the queues first to stop any new packets being sent. */
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++)
- if (veth_dev[i])
- netif_stop_queue(veth_dev[i]);
-
- /* Stop the connections before we unregister the driver. This
- * ensures there's no skbs lying around holding the device open. */
- for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
- veth_stop_connection(i);
-
+ /* Disconnect our "irq" to stop events coming from the Hypervisor. */
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
- /* Hypervisor callbacks may have scheduled more work while we
- * were stoping connections. Now that we've disconnected from
- * the hypervisor make sure everything's finished. */
+ /* Make sure any work queued from Hypervisor callbacks is finished. */
flush_scheduled_work();
- vio_unregister_driver(&veth_driver);
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ cnx = veth_cnx[i];
+
+ if (!cnx)
+ continue;
- for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
- veth_destroy_connection(i);
+ /* Remove the connection from sysfs */
+ kobject_del(&cnx->kobject);
+ /* Drop the driver's reference to the connection */
+ kobject_put(&cnx->kobject);
+ }
+ /* Unregister the driver, which will close all the netdevs and stop
+ * the connections when they're no longer referenced. */
+ vio_unregister_driver(&veth_driver);
}
module_exit(veth_module_cleanup);
@@ -1423,15 +1699,37 @@ int __init veth_module_init(void)
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
rc = veth_init_connection(i);
- if (rc != 0) {
- veth_module_cleanup();
- return rc;
- }
+ if (rc != 0)
+ goto error;
}
HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan,
&veth_handle_event);
- return vio_register_driver(&veth_driver);
+ rc = vio_register_driver(&veth_driver);
+ if (rc != 0)
+ goto error;
+
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ struct kobject *kobj;
+
+ if (!veth_cnx[i])
+ continue;
+
+ kobj = &veth_cnx[i]->kobject;
+ kobj->parent = &veth_driver.driver.kobj;
+ /* If the add failes, complain but otherwise continue */
+ if (0 != kobject_add(kobj))
+ veth_error("cnx %d: Failed adding to sysfs.\n", i);
+ }
+
+ return 0;
+
+error:
+ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
+ veth_destroy_connection(veth_cnx[i]);
+ }
+
+ return rc;
}
module_init(veth_module_init);
diff --git a/drivers/net/iseries_veth.h b/drivers/net/iseries_veth.h
deleted file mode 100644
index d9370f79b83e..000000000000
--- a/drivers/net/iseries_veth.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* File veth.h created by Kyle A. Lucke on Mon Aug 7 2000. */
-
-#ifndef _ISERIES_VETH_H
-#define _ISERIES_VETH_H
-
-#define VethEventTypeCap (0)
-#define VethEventTypeFrames (1)
-#define VethEventTypeMonitor (2)
-#define VethEventTypeFramesAck (3)
-
-#define VETH_MAX_ACKS_PER_MSG (20)
-#define VETH_MAX_FRAMES_PER_MSG (6)
-
-struct VethFramesData {
- u32 addr[VETH_MAX_FRAMES_PER_MSG];
- u16 len[VETH_MAX_FRAMES_PER_MSG];
- u32 eofmask;
-};
-#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG)
-
-struct VethFramesAckData {
- u16 token[VETH_MAX_ACKS_PER_MSG];
-};
-
-struct VethCapData {
- u8 caps_version;
- u8 rsvd1;
- u16 num_buffers;
- u16 ack_threshold;
- u16 rsvd2;
- u32 ack_timeout;
- u32 rsvd3;
- u64 rsvd4[3];
-};
-
-struct VethLpEvent {
- struct HvLpEvent base_event;
- union {
- struct VethCapData caps_data;
- struct VethFramesData frames_data;
- struct VethFramesAckData frames_ack_data;
- } u;
-
-};
-
-#endif /* _ISERIES_VETH_H */
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index f8d3385c7842..c83271b38621 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -119,7 +119,7 @@ struct ixgb_adapter;
* so a DMA handle can be stored along with the buffer */
struct ixgb_buffer {
struct sk_buff *skb;
- uint64_t dma;
+ dma_addr_t dma;
unsigned long time_stamp;
uint16_t length;
uint16_t next_to_watch;
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 3aae110c5560..661a46b95a61 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -565,24 +565,6 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
}
}
-/******************************************************************************
- * return the compatibility flags from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * compatibility flags if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_compatibility(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->compatibility));
-
- return(0);
-}
/******************************************************************************
* return the Printed Board Assembly number from EEPROM
@@ -602,81 +584,6 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
return(0);
}
-/******************************************************************************
- * return the Initialization Control Word 1 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->init_ctrl_reg_1));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Initialization Control Word 2 from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->init_ctrl_reg_2));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Subsystem Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Subsystem Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->subsystem_id));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Sub Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Sub Vendor Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->subvendor_id));
-
- return(0);
-}
/******************************************************************************
* return the Device Id from EEPROM
@@ -694,81 +601,6 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->device_id));
- return(0);
-}
-
-/******************************************************************************
- * return the Vendor Id from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * Device Id if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->vendor_id));
-
- return(0);
-}
-
-/******************************************************************************
- * return the Software Defined Pins Register from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * SDP Register if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint16_t
-ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->swdpins_reg));
-
- return(0);
+ return (0);
}
-/******************************************************************************
- * return the D3 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d3_power(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->d3_power));
-
- return(0);
-}
-
-/******************************************************************************
- * return the D0 Power Management Bits from EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Returns:
- * D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
- ******************************************************************************/
-uint8_t
-ixgb_get_ee_d0_power(struct ixgb_hw *hw)
-{
- struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
-
- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (le16_to_cpu(ee_map->d0_power));
-
- return(0);
-}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 3fa113854eeb..04e47189d830 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -98,10 +98,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
static int
ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
- ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+ ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
@@ -120,7 +120,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
static int
ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
if(ecmd->autoneg == AUTONEG_ENABLE ||
ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
@@ -130,6 +130,12 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ixgb_down(adapter, TRUE);
ixgb_reset(adapter);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+
} else
ixgb_reset(adapter);
@@ -140,7 +146,7 @@ static void
ixgb_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
pause->autoneg = AUTONEG_DISABLE;
@@ -159,7 +165,7 @@ static int
ixgb_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
if(pause->autoneg == AUTONEG_ENABLE)
@@ -177,6 +183,11 @@ ixgb_set_pauseparam(struct net_device *netdev,
if(netif_running(adapter->netdev)) {
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
} else
ixgb_reset(adapter);
@@ -186,19 +197,26 @@ ixgb_set_pauseparam(struct net_device *netdev,
static uint32_t
ixgb_get_rx_csum(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
return adapter->rx_csum;
}
static int
ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
adapter->rx_csum = data;
if(netif_running(netdev)) {
ixgb_down(adapter,TRUE);
ixgb_up(adapter);
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
} else
ixgb_reset(adapter);
return 0;
@@ -246,14 +264,15 @@ static void
ixgb_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint32_t *reg = p;
uint32_t *reg_start = reg;
uint8_t i;
/* the 1 (one) below indicates an attempt at versioning, if the
- * interface in ethtool or the driver this 1 should be incremented */
+ * interface in ethtool or the driver changes, this 1 should be
+ * incremented */
regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
/* General Registers */
@@ -283,7 +302,8 @@ ixgb_get_regs(struct net_device *netdev,
*reg++ = IXGB_READ_REG(hw, RAIDC); /* 19 */
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
- for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
+ /* there are 16 RAR entries in hardware, we only use 3 */
+ for(i = 0; i < 16; i++) {
*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
}
@@ -391,7 +411,7 @@ static int
ixgb_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
int i, max_len, first_word, last_word;
@@ -439,7 +459,7 @@ static int
ixgb_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
void *ptr;
@@ -497,7 +517,7 @@ static void
ixgb_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
strncpy(drvinfo->driver, ixgb_driver_name, 32);
strncpy(drvinfo->version, ixgb_driver_version, 32);
@@ -512,7 +532,7 @@ static void
ixgb_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
@@ -530,7 +550,7 @@ static int
ixgb_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
@@ -573,6 +593,11 @@ ixgb_set_ringparam(struct net_device *netdev,
adapter->tx_ring = tx_new;
if((err = ixgb_up(adapter)))
return err;
+ /* be optimistic about our link, since we were up before */
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
}
return 0;
@@ -607,7 +632,7 @@ ixgb_led_blink_callback(unsigned long data)
static int
ixgb_phys_id(struct net_device *netdev, uint32_t data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
@@ -620,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
- set_current_state(TASK_INTERRUPTIBLE);
- if(data)
- schedule_timeout(data * HZ);
+ if (data)
+ schedule_timeout_interruptible(data * HZ);
else
- schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+ schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
del_timer_sync(&adapter->blink_timer);
ixgb_led_off(&adapter->hw);
@@ -643,7 +667,7 @@ static void
ixgb_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int i;
ixgb_update_stats(adapter);
@@ -698,6 +722,7 @@ struct ethtool_ops ixgb_ethtool_ops = {
.phys_id = ixgb_phys_id,
.get_stats_count = ixgb_get_stats_count,
.get_ethtool_stats = ixgb_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index 97898efe7cc8..8bcf31ed10c2 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -822,17 +822,8 @@ extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */
void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
-uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
-uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
-uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 097b90ccf575..176680cb153e 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -29,6 +29,11 @@
#include "ixgb.h"
/* Change Log
+ * 1.0.96 04/19/05
+ * - Make needlessly global code static -- bunk@stusta.de
+ * - ethtool cleanup -- shemminger@osdl.org
+ * - Support for MODULE_VERSION -- linville@tuxdriver.com
+ * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
* 1.0.88 01/05/05
* - include fix to the condition that determines when to quit NAPI - Robert Olsson
* - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
@@ -47,10 +52,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-
-#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
+#define DRV_VERSION "1.0.100-k2"DRIVERNAPI
char ixgb_driver_version[] = DRV_VERSION;
-char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -145,10 +149,12 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
/* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */
-#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is
- pushed this many descriptors from head */
#define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0 /* chip considers prefech below
+ * this */
+#define RXDCTL_HTHRESH_DEFAULT 0 /* chip will only prefetch if tail
+ * is pushed this many descriptors
+ * from head */
/**
* ixgb_init_module - Driver Registration Routine
@@ -376,7 +382,7 @@ ixgb_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
@@ -454,8 +460,9 @@ ixgb_probe(struct pci_dev *pdev,
}
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+ memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->perm_addr)) {
err = -EIO;
goto err_eeprom;
}
@@ -512,7 +519,7 @@ static void __devexit
ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
@@ -583,7 +590,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
static int
ixgb_open(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int err;
/* allocate transmit descriptors */
@@ -626,7 +633,7 @@ err_setup_tx:
static int
ixgb_close(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE);
@@ -1017,7 +1024,7 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
static int
ixgb_set_mac(struct net_device *netdev, void *p)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
if(!is_valid_ether_addr(addr->sa_data))
@@ -1043,7 +1050,7 @@ ixgb_set_mac(struct net_device *netdev, void *p)
static void
ixgb_set_multi(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
uint32_t rctl;
@@ -1371,7 +1378,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
static int
ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
unsigned int first;
unsigned int tx_flags = 0;
unsigned long flags;
@@ -1425,7 +1432,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void
ixgb_tx_timeout(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
@@ -1434,7 +1441,7 @@ ixgb_tx_timeout(struct net_device *netdev)
static void
ixgb_tx_timeout_task(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
@@ -1451,7 +1458,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
static struct net_device_stats *
ixgb_get_stats(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
return &adapter->net_stats;
}
@@ -1467,7 +1474,7 @@ ixgb_get_stats(struct net_device *netdev)
static int
ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
@@ -1522,7 +1529,8 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
/* fix up multicast stats by removing broadcasts */
- multi -= bcast;
+ if(multi >= bcast)
+ multi -= bcast;
adapter->stats.mprcl += (multi & 0xFFFFFFFF);
adapter->stats.mprch += (multi >> 32);
@@ -1609,8 +1617,6 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
adapter->stats.icbc +
adapter->stats.ecbc + adapter->stats.mpc;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
-
/* see above
* adapter->net_stats.rx_length_errors = adapter->stats.rlec;
*/
@@ -1641,7 +1647,7 @@ static irqreturn_t
ixgb_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw;
uint32_t icr = IXGB_READ_REG(hw, ICR);
#ifndef CONFIG_IXGB_NAPI
@@ -1688,7 +1694,7 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
static int
ixgb_clean(struct net_device *netdev, int *budget)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
@@ -2017,7 +2023,7 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
static void
ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, rctl;
ixgb_irq_disable(adapter);
@@ -2055,7 +2061,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
static void
ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
/* add VID to filter table */
@@ -2069,7 +2075,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
static void
ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
- struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
ixgb_irq_disable(adapter);
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 7fec613e1675..a74a5cfaf5bc 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -1,5 +1,10 @@
/*
- * sonic.c
+ * jazzsonic.c
+ *
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, and (from the mac68k project) introduced
+ * dhd's support for 16-bit cards.
*
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*
@@ -28,8 +33,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -44,22 +49,20 @@ static struct platform_device *jazz_sonic_device;
#define SONIC_MEM_SIZE 0x100
-#define SREGS_PAD(n) u16 n;
-
#include "sonic.h"
/*
* Macros to access SONIC registers
*/
-#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg))
+#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
#define SONIC_WRITE(reg,val) \
do { \
- *((volatile unsigned int *)base_addr+(reg)) = (val); \
+ *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \
} while (0)
-/* use 0 for production, 1 for verification, >2 for debug */
+/* use 0 for production, 1 for verification, >1 for debug */
#ifdef SONIC_DEBUG
static unsigned int sonic_debug = SONIC_DEBUG;
#else
@@ -85,18 +88,18 @@ static unsigned short known_revisions[] =
0xffff /* end of list */
};
-static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
- unsigned int irq)
+static int __init sonic_probe1(struct net_device *dev)
{
static unsigned version_printed;
unsigned int silicon_revision;
unsigned int val;
- struct sonic_local *lp;
+ struct sonic_local *lp = netdev_priv(dev);
int err = -ENODEV;
int i;
- if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
+ if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
return -EBUSY;
+
/*
* get the Silicon Revision ID. If this is one of the known
* one assume that we found a SONIC ethernet controller at
@@ -120,11 +123,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
if (sonic_debug && version_printed++ == 0)
printk(version);
- printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr);
-
- /* Fill in the 'dev' fields. */
- dev->base_addr = base_addr;
- dev->irq = irq;
+ printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
/*
* Put the sonic into software reset, then
@@ -138,84 +137,44 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
dev->dev_addr[i*2+1] = val >> 8;
}
- printk("HW Address ");
- for (i = 0; i < 6; i++) {
- printk("%2.2x", dev->dev_addr[i]);
- if (i<5)
- printk(":");
- }
-
- printk(" IRQ %d\n", irq);
-
err = -ENOMEM;
/* Initialize the device structure. */
- if (dev->priv == NULL) {
- /*
- * the memory be located in the same 64kb segment
- */
- lp = NULL;
- i = 0;
- do {
- lp = kmalloc(sizeof(*lp), GFP_KERNEL);
- if ((unsigned long) lp >> 16
- != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
- /* FIXME, free the memory later */
- kfree(lp);
- lp = NULL;
- }
- } while (lp == NULL && i++ < 20);
-
- if (lp == NULL) {
- printk("%s: couldn't allocate memory for descriptors\n",
- dev->name);
- goto out;
- }
- memset(lp, 0, sizeof(struct sonic_local));
-
- /* get the virtual dma address */
- lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
- if (lp->cda_laddr == ~0UL) {
- printk("%s: couldn't get DMA page entry for "
- "descriptors\n", dev->name);
- goto out1;
- }
-
- lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
- lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
- lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
-
- /* allocate receive buffer area */
- /* FIXME, maybe we should use skbs */
- lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL);
- if (!lp->rba) {
- printk("%s: couldn't allocate receive buffers\n",
- dev->name);
- goto out2;
- }
+ lp->dma_bitmode = SONIC_BITMODE32;
- /* get virtual dma address */
- lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba),
- SONIC_NUM_RRS * SONIC_RBSIZE);
- if (lp->rba_laddr == ~0UL) {
- printk("%s: couldn't get DMA page entry for receive "
- "buffers\n",dev->name);
- goto out3;
- }
-
- /* now convert pointer to KSEG1 pointer */
- lp->rba = (char *)KSEG1ADDR(lp->rba);
- flush_cache_all();
- dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+ /* Allocate the entire chunk of memory for the descriptors.
+ Note that this cannot cross a 64K boundary. */
+ if ((lp->descriptors = dma_alloc_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
+ goto out;
}
- lp = (struct sonic_local *)dev->priv;
+ /* Now set up the pointers to point to the appropriate places */
+ lp->cda = lp->descriptors;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ lp->cda_laddr = lp->descriptors_laddr;
+ lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
dev->open = sonic_open;
dev->stop = sonic_close;
dev->hard_start_xmit = sonic_send_packet;
- dev->get_stats = sonic_get_stats;
+ dev->get_stats = sonic_get_stats;
dev->set_multicast_list = &sonic_multicast_list;
+ dev->tx_timeout = sonic_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
/*
@@ -226,14 +185,8 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
SONIC_WRITE(SONIC_MPT,0xffff);
return 0;
-out3:
- kfree(lp->rba);
-out2:
- vdma_free(lp->cda_laddr);
-out1:
- kfree(lp);
out:
- release_region(base_addr, SONIC_MEM_SIZE);
+ release_region(dev->base_addr, SONIC_MEM_SIZE);
return err;
}
@@ -245,7 +198,6 @@ static int __init jazz_sonic_probe(struct device *device)
{
struct net_device *dev;
struct sonic_local *lp;
- unsigned long base_addr;
int err = 0;
int i;
@@ -255,21 +207,26 @@ static int __init jazz_sonic_probe(struct device *device)
if (mips_machgroup != MACH_GROUP_JAZZ)
return -ENODEV;
- dev = alloc_etherdev(0);
+ dev = alloc_etherdev(sizeof(struct sonic_local));
if (!dev)
return -ENOMEM;
+ lp = netdev_priv(dev);
+ lp->device = device;
+ SET_NETDEV_DEV(dev, device);
+ SET_MODULE_OWNER(dev);
+
netdev_boot_setup_check(dev);
- base_addr = dev->base_addr;
- if (base_addr >= KSEG0) { /* Check a single specified location. */
- err = sonic_probe1(dev, base_addr, dev->irq);
- } else if (base_addr != 0) { /* Don't probe at all. */
+ if (dev->base_addr >= KSEG0) { /* Check a single specified location. */
+ err = sonic_probe1(dev);
+ } else if (dev->base_addr != 0) { /* Don't probe at all. */
err = -ENXIO;
} else {
for (i = 0; sonic_portlist[i].port; i++) {
- int io = sonic_portlist[i].port;
- if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
+ dev->base_addr = sonic_portlist[i].port;
+ dev->irq = sonic_portlist[i].irq;
+ if (sonic_probe1(dev) == 0)
break;
}
if (!sonic_portlist[i].port)
@@ -281,14 +238,17 @@ static int __init jazz_sonic_probe(struct device *device)
if (err)
goto out1;
+ printk("%s: MAC ", dev->name);
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ printk(" IRQ %d\n", dev->irq);
+
return 0;
out1:
- lp = dev->priv;
- vdma_free(lp->rba_laddr);
- kfree(lp->rba);
- vdma_free(lp->cda_laddr);
- kfree(lp);
release_region(dev->base_addr, SONIC_MEM_SIZE);
out:
free_netdev(dev);
@@ -296,21 +256,22 @@ out:
return err;
}
-/*
- * SONIC uses a normal IRQ
- */
-#define sonic_request_irq request_irq
-#define sonic_free_irq free_irq
+MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
+MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
-#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x))
+#define SONIC_IRQ_FLAG SA_INTERRUPT
#include "sonic.c"
static int __devexit jazz_sonic_device_remove (struct device *device)
{
struct net_device *dev = device->driver_data;
+ struct sonic_local* lp = netdev_priv(dev);
unregister_netdev (dev);
+ dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ lp->descriptors, lp->descriptors_laddr);
release_region (dev->base_addr, SONIC_MEM_SIZE);
free_netdev (dev);
@@ -323,7 +284,7 @@ static struct device_driver jazz_sonic_driver = {
.probe = jazz_sonic_probe,
.remove = __devexit_p(jazz_sonic_device_remove),
};
-
+
static void jazz_sonic_platform_release (struct device *device)
{
struct platform_device *pldev;
@@ -336,10 +297,11 @@ static void jazz_sonic_platform_release (struct device *device)
static int __init jazz_sonic_init_module(void)
{
struct platform_device *pldev;
+ int err;
- if (driver_register(&jazz_sonic_driver)) {
+ if ((err = driver_register(&jazz_sonic_driver))) {
printk(KERN_ERR "Driver registration failed\n");
- return -ENOMEM;
+ return err;
}
jazz_sonic_device = NULL;
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index b4929beb33b2..1d75ca0bb939 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -298,7 +298,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_
static unsigned char lance_need_isa_bounce_buffers = 1;
static int lance_open(struct net_device *dev);
-static void lance_init_ring(struct net_device *dev, int mode);
+static void lance_init_ring(struct net_device *dev, gfp_t mode);
static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int lance_rx(struct net_device *dev);
static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -846,7 +846,7 @@ lance_purge_ring(struct net_device *dev)
/* Initialize the LANCE Rx and Tx rings. */
static void
-lance_init_ring(struct net_device *dev, int gfp)
+lance_init_ring(struct net_device *dev, gfp_t gfp)
{
struct lance_private *lp = dev->priv;
int i;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 41bad07ac1ac..f7b7238d8352 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -415,6 +415,10 @@ static int rx_ring_size = RX_RING_SIZE;
static int ticks_limit = 100;
static int max_cmd_backlog = TX_RING_SIZE-1;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
static inline void CA(struct net_device *dev)
{
@@ -636,11 +640,11 @@ static int init_i596_mem(struct net_device *dev)
disable_irq(dev->irq); /* disable IRQs from LAN */
DEB(DEB_INIT,
- printk("RESET 82596 port: %p (with IRQ %d disabled)\n",
- (void*)(dev->base_addr + PA_I82596_RESET),
+ printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
+ (dev->base_addr + PA_I82596_RESET),
dev->irq));
- gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
+ gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
udelay(100); /* Wait 100us - seems to help */
/* change the scp address */
@@ -1209,6 +1213,9 @@ static int __devinit i82596_probe(struct net_device *dev,
dev->set_multicast_list = set_multicast_list;
dev->tx_timeout = i596_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = i596_poll_controller;
+#endif
dev->priv = (void *)(dev->mem_start);
@@ -1242,6 +1249,14 @@ static int __devinit i82596_probe(struct net_device *dev,
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ i596_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1528,17 +1543,18 @@ lan_init_chip(struct parisc_device *dev)
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
- __FILE__, dev->hpa);
+ __FILE__, dev->hpa.start);
return -ENODEV;
}
- printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa, dev->irq);
+ printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
+ dev->irq);
netdevice = alloc_etherdev(0);
if (!netdevice)
return -ENOMEM;
- netdevice->base_addr = dev->hpa;
+ netdevice->base_addr = dev->hpa.start;
netdevice->irq = dev->irq;
retval = i82596_probe(netdevice, &dev->dev);
@@ -1566,7 +1582,7 @@ static struct parisc_device_id lan_tbl[] = {
MODULE_DEVICE_TABLE(parisc, lan_tbl);
static struct parisc_driver lan_driver = {
- .name = "Apricot",
+ .name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
};
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 27f0d8ac4c40..309d254842cf 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -298,7 +298,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
return 0;
unmap:
if (ei_status.reg0)
- iounmap((void *)dev->mem_start);
+ iounmap(ei_status.mem);
cleanup:
free_irq(dev->irq, dev);
return ret;
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b33111e21313..690a1aae0b34 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -68,6 +68,7 @@ static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
* of largesending device modulo TCP checksum, which is ignored for loopback.
*/
+#ifdef LOOPBACK_TSO
static void emulate_large_send_offload(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
@@ -119,6 +120,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
dev_kfree_skb(skb);
}
+#endif /* LOOPBACK_TSO */
/*
* The higher levels take care of making this non-reentrant (it's
@@ -130,12 +132,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
skb_orphan(skb);
- skb->protocol=eth_type_trans(skb,dev);
- skb->dev=dev;
+ skb->protocol = eth_type_trans(skb,dev);
+ skb->dev = dev;
#ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif
+#ifdef LOOPBACK_TSO
if (skb_shinfo(skb)->tso_size) {
BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
@@ -143,14 +146,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
emulate_large_send_offload(skb);
return 0;
}
-
+#endif
dev->last_rx = jiffies;
lb_stats = &per_cpu(loopback_stats, get_cpu());
lb_stats->rx_bytes += skb->len;
- lb_stats->tx_bytes += skb->len;
+ lb_stats->tx_bytes = lb_stats->rx_bytes;
lb_stats->rx_packets++;
- lb_stats->tx_packets++;
+ lb_stats->tx_packets = lb_stats->rx_packets;
put_cpu();
netif_rx(skb);
@@ -208,13 +211,16 @@ struct net_device loopback_dev = {
.type = ARPHRD_LOOPBACK, /* 0x0001*/
.rebuild_header = eth_rebuild_header,
.flags = IFF_LOOPBACK,
- .features = NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
- |NETIF_F_LLTX,
+ .features = NETIF_F_SG | NETIF_F_FRAGLIST
+#ifdef LOOPBACK_TSO
+ | NETIF_F_TSO
+#endif
+ | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
+ | NETIF_F_LLTX,
.ethtool_ops = &loopback_ethtool_ops,
};
-/* Setup and register the of the LOOPBACK device. */
+/* Setup and register the loopback device. */
int __init loopback_init(void)
{
struct net_device_stats *stats;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 81d0a26e4f41..2a5add257b8f 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -1016,6 +1016,7 @@ static struct of_device_id mace_match[] =
},
{},
};
+MODULE_DEVICE_TABLE (of, mace_match);
static struct macio_driver mace_driver =
{
@@ -1035,10 +1036,8 @@ static void __exit mace_cleanup(void)
{
macio_unregister_driver(&mace_driver);
- if (dummy_buf) {
- kfree(dummy_buf);
- dummy_buf = NULL;
- }
+ kfree(dummy_buf);
+ dummy_buf = NULL;
}
MODULE_AUTHOR("Paul Mackerras");
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index be28c65de729..e9c999d7eb39 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -1,6 +1,12 @@
/*
* macsonic.c
*
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, converted to unified driver model, made it work as
+ * a module again, and from the mac68k project, introduced more 32-bit cards
+ * and dhd's support for 16-bit cards.
+ *
* (C) 1998 Alan Cox
*
* Debugging Andreas Ehliar, Michael Schmitz
@@ -26,8 +32,8 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/types.h>
-#include <linux/ctype.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -41,8 +47,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -54,25 +60,28 @@
#include <asm/macints.h>
#include <asm/mac_via.h>
-#define SREGS_PAD(n) u16 n;
+static char mac_sonic_string[] = "macsonic";
+static struct platform_device *mac_sonic_device;
#include "sonic.h"
-#define SONIC_READ(reg) \
- nubus_readl(base_addr+(reg))
-#define SONIC_WRITE(reg,val) \
- nubus_writel((val), base_addr+(reg))
-#define sonic_read(dev, reg) \
- nubus_readl((dev)->base_addr+(reg))
-#define sonic_write(dev, reg, val) \
- nubus_writel((val), (dev)->base_addr+(reg))
-
+/* These should basically be bus-size and endian independent (since
+ the SONIC is at least smart enough that it uses the same endianness
+ as the host, unlike certain less enlightened Macintosh NICs) */
+#define SONIC_READ(reg) (nubus_readw(dev->base_addr + (reg * 4) \
+ + lp->reg_offset))
+#define SONIC_WRITE(reg,val) (nubus_writew(val, dev->base_addr + (reg * 4) \
+ + lp->reg_offset))
+
+/* use 0 for production, 1 for verification, >1 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else
+static unsigned int sonic_debug = 1;
+#endif
-static int sonic_debug;
static int sonic_version_printed;
-static int reg_offset;
-
extern int mac_onboard_sonic_probe(struct net_device* dev);
extern int mac_nubus_sonic_probe(struct net_device* dev);
@@ -108,40 +117,6 @@ enum macsonic_type {
#define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)
-struct net_device * __init macsonic_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(0);
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0)
- sprintf(dev->name, "eth%d", unit);
-
- SET_MODULE_OWNER(dev);
-
- /* This will catch fatal stuff like -ENOMEM as well as success */
- err = mac_onboard_sonic_probe(dev);
- if (err == 0)
- goto found;
- if (err != -ENODEV)
- goto out;
- err = mac_nubus_sonic_probe(dev);
- if (err)
- goto out;
-found:
- err = register_netdev(dev);
- if (err)
- goto out1;
- return dev;
-out1:
- kfree(dev->priv);
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* For reversing the PROM address
*/
@@ -160,103 +135,55 @@ static inline void bit_reverse_addr(unsigned char addr[6])
int __init macsonic_init(struct net_device* dev)
{
- struct sonic_local* lp = NULL;
- int i;
+ struct sonic_local* lp = netdev_priv(dev);
/* Allocate the entire chunk of memory for the descriptors.
Note that this cannot cross a 64K boundary. */
- for (i = 0; i < 20; i++) {
- unsigned long desc_base, desc_top;
- if((lp = kmalloc(sizeof(struct sonic_local), GFP_KERNEL | GFP_DMA)) == NULL) {
- printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
- return -ENOMEM;
- }
-
- desc_base = (unsigned long) lp;
- desc_top = desc_base + sizeof(struct sonic_local);
- if ((desc_top & 0xffff) >= (desc_base & 0xffff))
- break;
- /* Hmm. try again (FIXME: does this actually work?) */
- kfree(lp);
- printk(KERN_DEBUG
- "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
- dev->name, desc_base, desc_top);
- }
-
- if (lp == NULL) {
- printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
- dev->name);
+ if ((lp->descriptors = dma_alloc_coherent(lp->device,
+ SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
return -ENOMEM;
- }
-
- dev->priv = lp;
-
-#if 0
- /* this code is only here as a curiousity... mainly, where the
- fuck did SONIC_BUS_SCALE come from, and what was it supposed
- to do? the normal allocation works great for 32 bit stuffs.. */
+ }
/* Now set up the pointers to point to the appropriate places */
- lp->cda = lp->sonic_desc;
- lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->cda = lp->descriptors;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
- * SONIC_BUS_SCALE(lp->dma_bitmode));
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
- * SONIC_BUS_SCALE(lp->dma_bitmode));
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
-#endif
-
- memset(lp, 0, sizeof(struct sonic_local));
-
- lp->cda_laddr = (unsigned int)&(lp->cda);
- lp->tda_laddr = (unsigned int)lp->tda;
- lp->rra_laddr = (unsigned int)lp->rra;
- lp->rda_laddr = (unsigned int)lp->rda;
-
- /* FIXME, maybe we should use skbs */
- if ((lp->rba = (char *)
- kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
- printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
- dev->priv = NULL;
- kfree(lp);
- return -ENOMEM;
- }
-
- lp->rba_laddr = (unsigned int)lp->rba;
-
- {
- int rs, ds;
-
- /* almost always 12*4096, but let's not take chances */
- rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
- /* almost always under a page, but let's not take chances */
- ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096;
- kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
- kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER);
- }
-
-#if 0
- flush_cache_all();
-#endif
+ lp->cda_laddr = lp->descriptors_laddr;
+ lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
dev->open = sonic_open;
dev->stop = sonic_close;
dev->hard_start_xmit = sonic_send_packet;
dev->get_stats = sonic_get_stats;
dev->set_multicast_list = &sonic_multicast_list;
+ dev->tx_timeout = sonic_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/*
* clear tally counter
*/
- sonic_write(dev, SONIC_CRCT, 0xffff);
- sonic_write(dev, SONIC_FAET, 0xffff);
- sonic_write(dev, SONIC_MPT, 0xffff);
+ SONIC_WRITE(SONIC_CRCT, 0xffff);
+ SONIC_WRITE(SONIC_FAET, 0xffff);
+ SONIC_WRITE(SONIC_MPT, 0xffff);
return 0;
}
int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
{
+ struct sonic_local *lp = netdev_priv(dev);
const int prom_addr = ONBOARD_SONIC_PROM_BASE;
int i;
@@ -270,6 +197,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
why this is so. */
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
bit_reverse_addr(dev->dev_addr);
else
@@ -281,22 +209,23 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
the card... */
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
{
unsigned short val;
printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_CEP, 15);
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ SONIC_WRITE(SONIC_CEP, 15);
- val = sonic_read(dev, SONIC_CAP2);
+ val = SONIC_READ(SONIC_CAP2);
dev->dev_addr[5] = val >> 8;
dev->dev_addr[4] = val & 0xff;
- val = sonic_read(dev, SONIC_CAP1);
+ val = SONIC_READ(SONIC_CAP1);
dev->dev_addr[3] = val >> 8;
dev->dev_addr[2] = val & 0xff;
- val = sonic_read(dev, SONIC_CAP0);
+ val = SONIC_READ(SONIC_CAP0);
dev->dev_addr[1] = val >> 8;
dev->dev_addr[0] = val & 0xff;
@@ -311,6 +240,7 @@ int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
memcmp(dev->dev_addr, "\x00\x05\x02", 3))
{
/*
@@ -325,8 +255,9 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
{
/* Bwahahaha */
static int once_is_more_than_enough;
- int i;
- int dma_bitmode;
+ struct sonic_local* lp = netdev_priv(dev);
+ int sr;
+ int commslot = 0;
if (once_is_more_than_enough)
return -ENODEV;
@@ -335,20 +266,18 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
if (!MACH_IS_MAC)
return -ENODEV;
- printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
-
if (macintosh_config->ether_type != MAC_ETHER_SONIC)
- {
- printk("none.\n");
return -ENODEV;
- }
-
+
+ printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
+
/* Bogus probing, on the models which may or may not have
Ethernet (BTW, the Ethernet *is* always at the same
address, and nothing else lives there, at least if Apple's
documentation is to be believed) */
if (macintosh_config->ident == MAC_MODEL_Q630 ||
macintosh_config->ident == MAC_MODEL_P588 ||
+ macintosh_config->ident == MAC_MODEL_P575 ||
macintosh_config->ident == MAC_MODEL_C610) {
unsigned long flags;
int card_present;
@@ -361,13 +290,13 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
printk("none.\n");
return -ENODEV;
}
+ commslot = 1;
}
printk("yes\n");
- /* Danger! My arms are flailing wildly! You *must* set this
- before using sonic_read() */
-
+ /* Danger! My arms are flailing wildly! You *must* set lp->reg_offset
+ * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
dev->base_addr = ONBOARD_SONIC_REGISTERS;
if (via_alt_mapping)
dev->irq = IRQ_AUTO_3;
@@ -379,84 +308,66 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
sonic_version_printed = 1;
}
printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
- dev->name, dev->base_addr);
-
- /* Now do a song and dance routine in an attempt to determine
- the bus width */
+ lp->device->bus_id, dev->base_addr);
/* The PowerBook's SONIC is 16 bit always. */
if (macintosh_config->ident == MAC_MODEL_PB520) {
- reg_offset = 0;
- dma_bitmode = 0;
- } else if (macintosh_config->ident == MAC_MODEL_C610) {
- reg_offset = 0;
- dma_bitmode = 1;
- } else {
+ lp->reg_offset = 0;
+ lp->dma_bitmode = SONIC_BITMODE16;
+ sr = SONIC_READ(SONIC_SR);
+ } else if (commslot) {
/* Some of the comm-slot cards are 16 bit. But some
- of them are not. The 32-bit cards use offset 2 and
- pad with zeroes or sometimes ones (I think...)
- Therefore, if we try offset 0 and get a silicon
- revision of 0, we assume 16 bit. */
- int sr;
-
- /* Technically this is not necessary since we zeroed
- it above */
- reg_offset = 0;
- dma_bitmode = 0;
- sr = sonic_read(dev, SONIC_SR);
- if (sr == 0 || sr == 0xffff) {
- reg_offset = 2;
- /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
- sr = sonic_read(dev, SONIC_SR);
- dma_bitmode = 1;
-
+ of them are not. The 32-bit cards use offset 2 and
+ have known revisions, we try reading the revision
+ register at offset 2, if we don't get a known revision
+ we assume 16 bit at offset 0. */
+ lp->reg_offset = 2;
+ lp->dma_bitmode = SONIC_BITMODE16;
+
+ sr = SONIC_READ(SONIC_SR);
+ if (sr == 0x0004 || sr == 0x0006 || sr == 0x0100 || sr == 0x0101)
+ /* 83932 is 0x0004 or 0x0006, 83934 is 0x0100 or 0x0101 */
+ lp->dma_bitmode = SONIC_BITMODE32;
+ else {
+ lp->dma_bitmode = SONIC_BITMODE16;
+ lp->reg_offset = 0;
+ sr = SONIC_READ(SONIC_SR);
}
- printk(KERN_INFO
- "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
- dev->name, sr, dma_bitmode?32:16, reg_offset);
+ } else {
+ /* All onboard cards are at offset 2 with 32 bit DMA. */
+ lp->reg_offset = 2;
+ lp->dma_bitmode = SONIC_BITMODE32;
+ sr = SONIC_READ(SONIC_SR);
}
-
+ printk(KERN_INFO
+ "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset);
- /* this carries my sincere apologies -- by the time I got to updating
- the driver, support for "reg_offsets" appeares nowhere in the sonic
- code, going back for over a year. Fortunately, my Mac does't seem
- to use whatever this was.
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+ printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+ SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
- If you know how this is supposed to be implemented, either fix it,
- or contact me (sammy@oh.verio.com) to explain what it is. --Sam */
-
- if(reg_offset) {
- printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name);
- return -ENODEV;
- }
-
/* Software reset, then initialize control registers. */
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
- SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
- (dma_bitmode ? SONIC_DCR_DW : 0));
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+
+ SONIC_WRITE(SONIC_DCR, SONIC_DCR_EXBUS | SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ (lp->dma_bitmode ? SONIC_DCR_DW : 0));
/* This *must* be written back to in order to restore the
- extended programmable output bits */
- sonic_write(dev, SONIC_DCR2, 0);
+ * extended programmable output bits, as it may not have been
+ * initialised since the hardware reset. */
+ SONIC_WRITE(SONIC_DCR2, 0);
/* Clear *and* disable interrupts to be on the safe side */
- sonic_write(dev, SONIC_ISR,0x7fff);
- sonic_write(dev, SONIC_IMR,0);
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
/* Now look for the MAC address. */
if (mac_onboard_sonic_ethernet_addr(dev) != 0)
return -ENODEV;
- printk(KERN_INFO "MAC ");
- for (i = 0; i < 6; i++) {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
-
- printk(" IRQ %d\n", dev->irq);
-
/* Shared init code */
return macsonic_init(dev);
}
@@ -468,8 +379,10 @@ int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
int i;
for(i = 0; i < 6; i++)
dev->dev_addr[i] = SONIC_READ_PROM(i);
- /* For now we are going to assume that they're all bit-reversed */
- bit_reverse_addr(dev->dev_addr);
+
+ /* Some of the addresses are bit-reversed */
+ if (id != MACSONIC_DAYNA)
+ bit_reverse_addr(dev->dev_addr);
return 0;
}
@@ -487,6 +400,15 @@ int __init macsonic_ident(struct nubus_dev* ndev)
else
return MACSONIC_APPLE;
}
+
+ if (ndev->dr_hw == NUBUS_DRHW_SMC9194 &&
+ ndev->dr_sw == NUBUS_DRSW_DAYNA)
+ return MACSONIC_DAYNA;
+
+ if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
+ ndev->dr_sw == 0) { /* huh? */
+ return MACSONIC_APPLE16;
+ }
return -1;
}
@@ -494,12 +416,12 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
{
static int slots;
struct nubus_dev* ndev = NULL;
+ struct sonic_local* lp = netdev_priv(dev);
unsigned long base_addr, prom_addr;
u16 sonic_dcr;
- int id;
- int i;
- int dma_bitmode;
-
+ int id = -1;
+ int reg_offset, dma_bitmode;
+
/* Find the first SONIC that hasn't been initialized already */
while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
NUBUS_TYPE_ETHERNET, ndev)) != NULL)
@@ -521,51 +443,52 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
case MACSONIC_DUODOCK:
base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
- sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1
- | SONIC_DCR_TFT0;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1 |
+ SONIC_DCR_TFT0;
reg_offset = 2;
- dma_bitmode = 1;
+ dma_bitmode = SONIC_BITMODE32;
break;
case MACSONIC_APPLE:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
reg_offset = 0;
- dma_bitmode = 1;
+ dma_bitmode = SONIC_BITMODE32;
break;
case MACSONIC_APPLE16:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
- sonic_dcr = SONIC_DCR_EXBUS
- | SONIC_DCR_RFT1 | SONIC_DCR_TFT0
- | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ SONIC_DCR_PO1 | SONIC_DCR_BMS;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
case MACSONIC_DAYNALINK:
base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
- sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0
- | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
+ SONIC_DCR_PO1 | SONIC_DCR_BMS;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
case MACSONIC_DAYNA:
base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
- sonic_dcr = SONIC_DCR_BMS
- | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
+ sonic_dcr = SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
reg_offset = 0;
- dma_bitmode = 0;
+ dma_bitmode = SONIC_BITMODE16;
break;
default:
printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
return -ENODEV;
}
- /* Danger! My arms are flailing wildly! You *must* set this
- before using sonic_read() */
+ /* Danger! My arms are flailing wildly! You *must* set lp->reg_offset
+ * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
dev->base_addr = base_addr;
+ lp->reg_offset = reg_offset;
+ lp->dma_bitmode = dma_bitmode;
dev->irq = SLOT2IRQ(ndev->board->slot);
if (!sonic_version_printed) {
@@ -573,29 +496,66 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
sonic_version_printed = 1;
}
printk(KERN_INFO "%s: %s in slot %X\n",
- dev->name, ndev->board->name, ndev->board->slot);
+ lp->device->bus_id, ndev->board->name, ndev->board->slot);
printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
- dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
+ lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
- if(reg_offset) {
- printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name);
- return -ENODEV;
- }
+#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
+ printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
+ SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
+#endif
/* Software reset, then initialize control registers. */
- sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
- sonic_write(dev, SONIC_DCR, sonic_dcr
- | (dma_bitmode ? SONIC_DCR_DW : 0));
+ SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ SONIC_WRITE(SONIC_DCR, sonic_dcr | (dma_bitmode ? SONIC_DCR_DW : 0));
+ /* This *must* be written back to in order to restore the
+ * extended programmable output bits, since it may not have been
+ * initialised since the hardware reset. */
+ SONIC_WRITE(SONIC_DCR2, 0);
/* Clear *and* disable interrupts to be on the safe side */
- sonic_write(dev, SONIC_ISR,0x7fff);
- sonic_write(dev, SONIC_IMR,0);
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
/* Now look for the MAC address. */
if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
return -ENODEV;
- printk(KERN_INFO "MAC ");
+ /* Shared init code */
+ return macsonic_init(dev);
+}
+
+static int __init mac_sonic_probe(struct device *device)
+{
+ struct net_device *dev;
+ struct sonic_local *lp;
+ int err;
+ int i;
+
+ dev = alloc_etherdev(sizeof(struct sonic_local));
+ if (!dev)
+ return -ENOMEM;
+
+ lp = netdev_priv(dev);
+ lp->device = device;
+ SET_NETDEV_DEV(dev, device);
+ SET_MODULE_OWNER(dev);
+
+ /* This will catch fatal stuff like -ENOMEM as well as success */
+ err = mac_onboard_sonic_probe(dev);
+ if (err == 0)
+ goto found;
+ if (err != -ENODEV)
+ goto out;
+ err = mac_nubus_sonic_probe(dev);
+ if (err)
+ goto out;
+found:
+ err = register_netdev(dev);
+ if (err)
+ goto out;
+
+ printk("%s: MAC ", dev->name);
for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i < 5)
@@ -603,55 +563,95 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
}
printk(" IRQ %d\n", dev->irq);
- /* Shared init code */
- return macsonic_init(dev);
-}
+ return 0;
-#ifdef MODULE
-static struct net_device *dev_macsonic;
+out:
+ free_netdev(dev);
-MODULE_PARM(sonic_debug, "i");
+ return err;
+}
+
+MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
+module_param(sonic_debug, int, 0);
MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
-int
-init_module(void)
+#define SONIC_IRQ_FLAG IRQ_FLG_FAST
+
+#include "sonic.c"
+
+static int __devexit mac_sonic_device_remove (struct device *device)
{
- dev_macsonic = macsonic_probe(-1);
- if (IS_ERR(dev_macsonic)) {
- printk(KERN_WARNING "macsonic.c: No card found\n");
- return PTR_ERR(dev_macsonic);
- }
+ struct net_device *dev = device->driver_data;
+ struct sonic_local* lp = netdev_priv(dev);
+
+ unregister_netdev (dev);
+ dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+ lp->descriptors, lp->descriptors_laddr);
+ free_netdev (dev);
+
return 0;
}
-void
-cleanup_module(void)
+static struct device_driver mac_sonic_driver = {
+ .name = mac_sonic_string,
+ .bus = &platform_bus_type,
+ .probe = mac_sonic_probe,
+ .remove = __devexit_p(mac_sonic_device_remove),
+};
+
+static void mac_sonic_platform_release(struct device *device)
{
- unregister_netdev(dev_macsonic);
- kfree(dev_macsonic->priv);
- free_netdev(dev_macsonic);
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device (device);
+ kfree (pldev);
}
-#endif /* MODULE */
+static int __init mac_sonic_init_module(void)
+{
+ struct platform_device *pldev;
+ int err;
-#define vdma_alloc(foo, bar) ((u32)foo)
-#define vdma_free(baz)
-#define sonic_chiptomem(bat) (bat)
-#define PHYSADDR(quux) (quux)
-#define CPHYSADDR(quux) (quux)
+ if ((err = driver_register(&mac_sonic_driver))) {
+ printk(KERN_ERR "Driver registration failed\n");
+ return err;
+ }
-#define sonic_request_irq request_irq
-#define sonic_free_irq free_irq
+ mac_sonic_device = NULL;
-#include "sonic.c"
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+ goto out_unregister;
+ }
-/*
- * Local variables:
- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o macsonic.o macsonic.c"
- * version-control: t
- * kept-new-versions: 5
- * c-indent-level: 8
- * tab-width: 8
- * End:
- *
- */
+ memset(pldev, 0, sizeof (*pldev));
+ pldev->name = mac_sonic_string;
+ pldev->id = 0;
+ pldev->dev.release = mac_sonic_platform_release;
+ mac_sonic_device = pldev;
+
+ if (platform_device_register (pldev)) {
+ kfree(pldev);
+ mac_sonic_device = NULL;
+ }
+
+ return 0;
+
+out_unregister:
+ platform_device_unregister(pldev);
+
+ return -ENOMEM;
+}
+
+static void __exit mac_sonic_cleanup_module(void)
+{
+ driver_unregister(&mac_sonic_driver);
+
+ if (mac_sonic_device) {
+ platform_device_unregister(mac_sonic_device);
+ mac_sonic_device = NULL;
+ }
+}
+
+module_init(mac_sonic_init_module);
+module_exit(mac_sonic_cleanup_module);
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index c33cb3dc942b..e42aa797f08b 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -207,6 +207,20 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
return 0;
}
+int mii_check_gmii_support(struct mii_if_info *mii)
+{
+ int reg;
+
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+ if (reg & BMSR_ESTATEN) {
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
+ if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
+ return 1;
+ }
+
+ return 0;
+}
+
int mii_link_ok (struct mii_if_info *mii)
{
/* first, a dummy read, needed to latch some MII phys */
@@ -394,5 +408,6 @@ EXPORT_SYMBOL(mii_ethtool_gset);
EXPORT_SYMBOL(mii_ethtool_sset);
EXPORT_SYMBOL(mii_check_link);
EXPORT_SYMBOL(mii_check_media);
+EXPORT_SYMBOL(mii_check_gmii_support);
EXPORT_SYMBOL(generic_mii_ioctl);
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
new file mode 100644
index 000000000000..bbffb585b3b3
--- /dev/null
+++ b/drivers/net/mipsnet.c
@@ -0,0 +1,372 @@
+/*
+ * 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.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/mips-boards/simint.h>
+
+#include "mipsnet.h" /* actual device IO mapping */
+
+#define MIPSNET_VERSION "2005-06-20"
+
+#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
+
+struct mipsnet_priv {
+ struct net_device_stats stats;
+};
+
+static struct platform_device *mips_plat_dev;
+
+static char mipsnet_string[] = "mipsnet";
+
+/*
+ * Copy data from the MIPSNET rx data port
+ */
+static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
+ int len)
+{
+ uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+ if (available_len < len)
+ return -EFAULT;
+
+ for (; len > 0; len--, kdata++) {
+ *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
+ }
+
+ return inl(mipsnet_reg_address(dev, rxDataCount));
+}
+
+static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
+ struct sk_buff *skb)
+{
+ int count_to_go = skb->len;
+ char *buf_ptr = skb->data;
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ outl(skb->len, mipsnet_reg_address(dev, txDataCount));
+
+ pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ for (; count_to_go; buf_ptr++, count_to_go--) {
+ outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
+ }
+
+ mp->stats.tx_packets++;
+ mp->stats.tx_bytes += skb->len;
+
+ return skb->len;
+}
+
+static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ pr_debug("%s:%s(): transmitting %d bytes\n",
+ dev->name, __FUNCTION__, skb->len);
+
+ /* Only one packet at a time. Once TXDONE interrupt is serviced, the
+ * queue will be restarted.
+ */
+ netif_stop_queue(dev);
+ mipsnet_put_todevice(dev, skb);
+
+ return 0;
+}
+
+static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+{
+ struct sk_buff *skb;
+ size_t len = count;
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+ mp->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_reserve(skb, 2);
+ if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+ return -EFAULT;
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ pr_debug("%s:%s(): pushing RXed data to kernel\n",
+ dev->name, __FUNCTION__);
+ netif_rx(skb);
+
+ mp->stats.rx_packets++;
+ mp->stats.rx_bytes += len;
+
+ return count;
+}
+
+static irqreturn_t
+mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+
+ irqreturn_t retval = IRQ_NONE;
+ uint64_t interruptFlags;
+
+ if (irq == dev->irq) {
+ pr_debug("%s:%s(): irq %d for device\n",
+ dev->name, __FUNCTION__, irq);
+
+ retval = IRQ_HANDLED;
+
+ interruptFlags =
+ inl(mipsnet_reg_address(dev, interruptControl));
+ pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
+ __FUNCTION__, interruptFlags);
+
+ if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+ pr_debug("%s:%s(): got TXDone\n",
+ dev->name, __FUNCTION__);
+ outl(MIPSNET_INTCTL_TXDONE,
+ mipsnet_reg_address(dev, interruptControl));
+ // only one packet at a time, we are done.
+ netif_wake_queue(dev);
+ } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
+ pr_debug("%s:%s(): got RX data\n",
+ dev->name, __FUNCTION__);
+ mipsnet_get_fromdev(dev,
+ inl(mipsnet_reg_address(dev, rxDataCount)));
+ pr_debug("%s:%s(): clearing RX int\n",
+ dev->name, __FUNCTION__);
+ outl(MIPSNET_INTCTL_RXDONE,
+ mipsnet_reg_address(dev, interruptControl));
+
+ } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+ pr_debug("%s:%s(): got test interrupt\n",
+ dev->name, __FUNCTION__);
+ // TESTBIT is cleared on read.
+ // And takes effect after a write with 0
+ outl(0, mipsnet_reg_address(dev, interruptControl));
+ } else {
+ pr_debug("%s:%s(): no valid fags 0x%016llx\n",
+ dev->name, __FUNCTION__, interruptFlags);
+ // Maybe shared IRQ, just ignore, no clearing.
+ retval = IRQ_NONE;
+ }
+
+ } else {
+ printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
+ dev->name, __FUNCTION__, irq);
+ retval = IRQ_NONE;
+ }
+ return retval;
+} //mipsnet_interrupt()
+
+static int mipsnet_open(struct net_device *dev)
+{
+ int err;
+ pr_debug("%s: mipsnet_open\n", dev->name);
+
+ err = request_irq(dev->irq, &mipsnet_interrupt,
+ SA_SHIRQ, dev->name, (void *) dev);
+
+ if (err) {
+ pr_debug("%s: %s(): can't get irq %d\n",
+ dev->name, __FUNCTION__, dev->irq);
+ release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+ return err;
+ }
+
+ pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
+ dev->name, __FUNCTION__, dev->base_addr, dev->irq);
+
+
+ netif_start_queue(dev);
+
+ // test interrupt handler
+ outl(MIPSNET_INTCTL_TESTBIT,
+ mipsnet_reg_address(dev, interruptControl));
+
+
+ return 0;
+}
+
+static int mipsnet_close(struct net_device *dev)
+{
+ pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
+ netif_stop_queue(dev);
+ return 0;
+}
+
+static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
+{
+ struct mipsnet_priv *mp = netdev_priv(dev);
+
+ return &mp->stats;
+}
+
+static void mipsnet_set_mclist(struct net_device *dev)
+{
+ // we don't do anything
+ return;
+}
+
+static int __init mipsnet_probe(struct device *dev)
+{
+ struct net_device *netdev;
+ int err;
+
+ netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ dev_set_drvdata(dev, netdev);
+
+ netdev->open = mipsnet_open;
+ netdev->stop = mipsnet_close;
+ netdev->hard_start_xmit = mipsnet_xmit;
+ netdev->get_stats = mipsnet_get_stats;
+ netdev->set_multicast_list = mipsnet_set_mclist;
+
+ /*
+ * TODO: probe for these or load them from PARAM
+ */
+ netdev->base_addr = 0x4200;
+ netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+ inl(mipsnet_reg_address(netdev, interruptInfo));
+
+ // Get the io region now, get irq on open()
+ if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
+ pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
+ "for dev is not availble.\n", netdev->name,
+ __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
+ err = -EBUSY;
+ goto out_free_netdev;
+ }
+
+ /*
+ * Lacking any better mechanism to allocate a MAC address we use a
+ * random one ...
+ */
+ random_ether_addr(netdev->dev_addr);
+
+ err = register_netdev(netdev);
+ if (err) {
+ printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
+ goto out_free_region;
+ }
+
+ return 0;
+
+out_free_region:
+ release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
+
+out_free_netdev:
+ free_netdev(netdev);
+
+out:
+ return err;
+}
+
+static int __devexit mipsnet_device_remove(struct device *device)
+{
+ struct net_device *dev = dev_get_drvdata(device);
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+ free_netdev(dev);
+ dev_set_drvdata(device, NULL);
+
+ return 0;
+}
+
+static struct device_driver mipsnet_driver = {
+ .name = mipsnet_string,
+ .bus = &platform_bus_type,
+ .probe = mipsnet_probe,
+ .remove = __devexit_p(mipsnet_device_remove),
+};
+
+static void mipsnet_platform_release(struct device *device)
+{
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device(device);
+ kfree(pldev);
+}
+
+static int __init mipsnet_init_module(void)
+{
+ struct platform_device *pldev;
+ int err;
+
+ printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
+ "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
+
+ if (driver_register(&mipsnet_driver)) {
+ printk(KERN_ERR "Driver registration failed\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto out_unregister_driver;
+ }
+
+ memset (pldev, 0, sizeof (*pldev));
+ pldev->name = mipsnet_string;
+ pldev->id = 0;
+ pldev->dev.release = mipsnet_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);
+ }
+
+ mips_plat_dev = pldev;
+
+ return 0;
+
+out_free_pldev:
+ kfree(pldev);
+
+out_unregister_driver:
+ driver_unregister(&mipsnet_driver);
+out:
+ return err;
+}
+
+static void __exit mipsnet_exit_module(void)
+{
+ pr_debug("MIPSNet Ethernet driver exiting\n");
+
+ driver_unregister(&mipsnet_driver);
+}
+
+module_init(mipsnet_init_module);
+module_exit(mipsnet_exit_module);
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
new file mode 100644
index 000000000000..878535953cb1
--- /dev/null
+++ b/drivers/net/mipsnet.h
@@ -0,0 +1,127 @@
+//
+// <COPYRIGHT CLASS="1B" YEAR="2005">
+// Unpublished work (c) MIPS Technologies, Inc. All rights reserved.
+// Unpublished rights reserved under the copyright laws of the U.S.A. and
+// other countries.
+//
+// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
+// FOR INTERNAL USE ONLY.
+//
+// Under no circumstances (contract or otherwise) may this information be
+// disclosed to, or copied, modified or used by anyone other than employees
+// or contractors of MIPS Technologies having a need to know.
+// </COPYRIGHT>
+//
+//++
+// File: MIPS_Net.h
+//
+// Description:
+// The definition of the emulated MIPSNET device's interface.
+//
+// Notes: This include file needs to work from a Linux device drivers.
+//
+//--
+//
+
+#ifndef __MIPSNET_H
+#define __MIPSNET_H
+
+/*
+ * Id of this Net device, as seen by the core.
+ */
+#define MIPS_NET_DEV_ID ((uint64_t) \
+ ((uint64_t)'M'<< 0)| \
+ ((uint64_t)'I'<< 8)| \
+ ((uint64_t)'P'<<16)| \
+ ((uint64_t)'S'<<24)| \
+ ((uint64_t)'N'<<32)| \
+ ((uint64_t)'E'<<40)| \
+ ((uint64_t)'T'<<48)| \
+ ((uint64_t)'0'<<56))
+
+/*
+ * Net status/control block as seen by sw in the core.
+ * (Why not use bit fields? can't be bothered with cross-platform struct
+ * packing.)
+ */
+typedef struct _net_control_block {
+ /// dev info for probing
+ /// reads as MIPSNET%d where %d is some form of version
+ uint64_t devId; /*0x00 */
+
+ /*
+ * read only busy flag.
+ * Set and cleared by the Net Device to indicate that an rx or a tx
+ * is in progress.
+ */
+ uint32_t busy; /*0x08 */
+
+ /*
+ * Set by the Net Device.
+ * The device will set it once data has been received.
+ * The value is the number of bytes that should be read from
+ * rxDataBuffer. The value will decrease till 0 until all the data
+ * from rxDataBuffer has been read.
+ */
+ uint32_t rxDataCount; /*0x0c */
+#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
+
+ /*
+ * Settable from the MIPS core, cleared by the Net Device.
+ * The core should set the number of bytes it wants to send,
+ * then it should write those bytes of data to txDataBuffer.
+ * The device will clear txDataCount has been processed (not necessarily sent).
+ */
+ uint32_t txDataCount; /*0x10 */
+
+ /*
+ * Interrupt control
+ *
+ * Used to clear the interrupted generated by this dev.
+ * Write a 1 to clear the interrupt. (except bit31).
+ *
+ * Bit0 is set if it was a tx-done interrupt.
+ * Bit1 is set when new rx-data is available.
+ * Until this bit is cleared there will be no other RXs.
+ *
+ * Bit31 is used for testing, it clears after a read.
+ * Writing 1 to this bit will cause an interrupt to be generated.
+ * To clear the test interrupt, write 0 to this register.
+ */
+ uint32_t interruptControl; /*0x14 */
+#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0))
+#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1))
+#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31))
+#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT)
+
+ /*
+ * Readonly core-specific interrupt info for the device to signal the core.
+ * The meaning of the contents of this field might change.
+ */
+ /*###\todo: the whole memIntf interrupt scheme is messy: the device should have
+ * no control what so ever of what VPE/register set is being used.
+ * The MemIntf should only expose interrupt lines, and something in the
+ * config should be responsible for the line<->core/vpe bindings.
+ */
+ uint32_t interruptInfo; /*0x18 */
+
+ /*
+ * This is where the received data is read out.
+ * There is more data to read until rxDataReady is 0.
+ * Only 1 byte at this regs offset is used.
+ */
+ uint32_t rxDataBuffer; /*0x1c */
+
+ /*
+ * This is where the data to transmit is written.
+ * Data should be written for the amount specified in the txDataCount register.
+ * Only 1 byte at this regs offset is used.
+ */
+ uint32_t txDataBuffer; /*0x20 */
+} MIPS_T_NetControl;
+
+#define MIPSNET_IO_EXTENT 0x40 /* being generous */
+
+#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+
+#endif /* __MIPSNET_H */
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 0405e1f0d3df..71f2c6705bc3 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -39,6 +39,8 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
#include <asm/types.h>
#include <asm/pgtable.h>
@@ -58,11 +60,10 @@
#define INT_CAUSE_UNMASK_ALL 0x0007ffff
#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
#define INT_CAUSE_MASK_ALL 0x00000000
+#define INT_CAUSE_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
-#endif
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
@@ -95,7 +96,7 @@ static char mv643xx_driver_version[] = "1.0";
static void __iomem *mv643xx_eth_shared_base;
/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
-static spinlock_t mv643xx_eth_phy_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
static inline u32 mv_read(int offset)
{
@@ -259,14 +260,13 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev)
static void mv643xx_eth_set_rx_mode(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
- u32 config_reg;
- config_reg = ethernet_get_config_reg(mp->port_num);
if (dev->flags & IFF_PROMISC)
- config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
else
- config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
- ethernet_set_config_reg(mp->port_num, config_reg);
+ mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+
+ mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
}
/*
@@ -369,15 +369,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
-
- /*
- * Decrement the number of outstanding skbs counter on
- * the TX queue.
- */
- if (mp->tx_ring_skbs == 0)
- panic("ERROR - TX outstanding SKBs"
- " counter is corrupted");
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -412,15 +403,13 @@ static int mv643xx_eth_receive_queue(struct net_device *dev)
struct pkt_info pkt_info;
#ifdef MV643XX_NAPI
- while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+ while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
#else
while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
#endif
mp->rx_ring_skbs--;
received_packets++;
-#ifdef MV643XX_NAPI
- budget--;
-#endif
+
/* Update statistics. Note byte count includes 4 byte CRC count */
stats->rx_packets++;
stats->rx_bytes += pkt_info.byte_cnt;
@@ -1044,9 +1033,6 @@ static void mv643xx_tx(struct net_device *dev)
DMA_TO_DEVICE);
dev_kfree_skb_irq(pkt_info.return_info);
-
- if (mp->tx_ring_skbs)
- mp->tx_ring_skbs--;
} else
dma_unmap_page(NULL, pkt_info.buf_ptr,
pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -1157,16 +1143,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_shinfo(skb)->nr_frags) {
linear:
if (skb->ip_summed != CHECKSUM_HW) {
+ /* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+ ETH_TX_FIRST_DESC |
+ ETH_TX_LAST_DESC |
+ 5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
- u32 ipheader = skb->nh.iph->ihl << 11;
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
- ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ ETH_TX_FIRST_DESC |
+ ETH_TX_LAST_DESC |
+ ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM |
+ skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1185,7 +1175,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1193,7 +1182,6 @@ linear:
stats->tx_bytes += pkt_info.byte_cnt;
} else {
unsigned int frag;
- u32 ipheader;
/* Since hardware can't handle unaligned fragments smaller
* than 9 bytes, if we find any, we linearize the skb
@@ -1222,12 +1210,16 @@ linear:
DMA_TO_DEVICE);
pkt_info.l4i_chk = 0;
pkt_info.return_info = 0;
- pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
- if (skb->ip_summed == CHECKSUM_HW) {
- ipheader = skb->nh.iph->ihl << 11;
- pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ if (skb->ip_summed != CHECKSUM_HW)
+ /* Errata BTS #50, IHL must be 5 if no HW checksum */
+ pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+ 5 << ETH_TX_IHL_SHIFT;
+ else {
+ pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+ ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM |
+ skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1267,7 +1259,6 @@ linear:
pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
ETH_TX_LAST_DESC;
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
} else {
pkt_info.return_info = 0;
}
@@ -1304,7 +1295,6 @@ linear:
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1349,6 +1339,43 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
return &mp->stats;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
+{
+ int port_num = mp->port_num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL_EXT);
+ spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void mv643xx_netpoll(struct net_device *netdev)
+{
+ struct mv643xx_private *mp = netdev_priv(netdev);
+
+ mv643xx_disable_irq(mp);
+ mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
+ mv643xx_enable_irq(mp);
+}
+#endif
+
/*/
* mv643xx_eth_probe
*
@@ -1399,6 +1426,10 @@ static int mv643xx_eth_probe(struct device *ddev)
dev->weight = 64;
#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = mv643xx_netpoll;
+#endif
+
dev->watchdog_timeo = 2 * HZ;
dev->tx_queue_len = mp->tx_ring_size;
dev->base_addr = 0;
@@ -1504,6 +1535,9 @@ static int mv643xx_eth_probe(struct device *ddev)
printk(KERN_NOTICE "%s: RX NAPI Enabled \n", dev->name);
#endif
+ if (mp->tx_sram_size > 0)
+ printk(KERN_NOTICE "%s: Using SRAM\n", dev->name);
+
return 0;
out:
@@ -1876,6 +1910,9 @@ static void eth_port_start(struct mv643xx_private *mp)
/* Enable port Rx. */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
mp->port_rx_queue_command);
+
+ /* Disable port bandwidth limits by clearing MTU register */
+ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
}
/*
@@ -2285,34 +2322,6 @@ static void eth_port_reset(unsigned int port_num)
mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
-/*
- * ethernet_set_config_reg - Set specified bits in configuration register.
- *
- * DESCRIPTION:
- * This function sets specified bits in the given ethernet
- * configuration register.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int value 32 bit value.
- *
- * OUTPUT:
- * The set bits in the value parameter are set in the configuration
- * register.
- *
- * RETURN:
- * None.
- *
- */
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
- eth_config_reg |= value;
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
-}
static int eth_port_autoneg_supported(unsigned int eth_port_num)
{
@@ -2339,31 +2348,6 @@ static int eth_port_link_is_up(unsigned int eth_port_num)
}
/*
- * ethernet_get_config_reg - Get the port configuration register
- *
- * DESCRIPTION:
- * This function returns the configuration register value of the given
- * ethernet port.
- *
- * INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- *
- * OUTPUT:
- * None.
- *
- * RETURN:
- * Port configuration register value.
- */
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
-{
- unsigned int eth_config_reg;
-
- eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
- (eth_port_num));
- return eth_config_reg;
-}
-
-/*
* eth_port_read_smi_reg - Read PHY registers
*
* DESCRIPTION:
@@ -2521,6 +2505,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
return ETH_ERROR;
}
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2587,6 +2574,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ mp->tx_ring_skbs++;
+ BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
@@ -2687,6 +2677,9 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
/* Any Tx return cancels the Tx resource error status */
mp->tx_resource_err = 0;
+ BUG_ON(mp->tx_ring_skbs == 0);
+ mp->tx_ring_skbs--;
+
return ETH_OK;
}
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
index 57c4f8fbfdb6..bcfda5192da0 100644
--- a/drivers/net/mv643xx_eth.h
+++ b/drivers/net/mv643xx_eth.h
@@ -49,7 +49,7 @@
/* Checksum offload for Tx works for most packets, but
* fails if previous packet sent did not use hw csum
*/
-#undef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MV643XX_CHECKSUM_OFFLOAD_TX
#define MV643XX_NAPI
#define MV643XX_TX_FAST_REFILL
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
@@ -217,6 +217,8 @@
#define ETH_TX_ENABLE_INTERRUPT (BIT23)
#define ETH_AUTO_MODE (BIT30)
+#define ETH_TX_IHL_SHIFT 11
+
/* typedefs */
typedef enum _eth_func_ret_status {
@@ -406,10 +408,6 @@ static void eth_port_init(struct mv643xx_private *mp);
static void eth_port_reset(unsigned int eth_port_num);
static void eth_port_start(struct mv643xx_private *mp);
-static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value);
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
-
/* Port MAC address routines */
static void eth_port_uc_addr_set(unsigned int eth_port_num,
unsigned char *p_addr);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index f0996ce5c268..6c86dca62e2a 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -277,7 +277,7 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
struct recvq __iomem *rq = mp->rq;
struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
struct net_device *dev = mp->dev;
- int gfp_flags = GFP_KERNEL;
+ gfp_t gfp_flags = GFP_KERNEL;
int i;
if (from_irq || in_interrupt())
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 9391e55a5e92..47722f708a41 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -296,7 +296,7 @@ struct myri_eth {
/* We use this to acquire receive skb's that we can DMA directly into. */
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
{
struct sk_buff *skb;
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index d209a1556b2e..0de8fdd2aa86 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -54,6 +54,10 @@ static const char version2[] =
#include <asm/system.h>
#include <asm/io.h>
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+#include <asm/tx4938/rbtx4938.h>
+#endif
+
#include "8390.h"
#define DRV_NAME "ne"
@@ -111,6 +115,9 @@ bad_clone_list[] __initdata = {
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
{"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+ {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
+#endif
{"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
{NULL,}
};
@@ -226,6 +233,10 @@ struct net_device * __init ne_probe(int unit)
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
+#ifdef CONFIG_TOSHIBA_RBTX4938
+ dev->base_addr = 0x07f20280;
+ dev->irq = RBTX4938_RTL_8019_IRQ;
+#endif
err = do_ne_probe(dev);
if (err)
goto out;
@@ -506,6 +517,10 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+ wordlength = 1;
+#endif
+
#ifdef CONFIG_PLAT_OAKS32R
ei_status.word16 = 0;
#else
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index f1c01ac29102..d11821dd86ed 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -372,6 +372,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
dev->dev_addr[i] = SA_prom[i];
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0;
@@ -637,6 +638,7 @@ static struct ethtool_ops ne2k_pci_ethtool_ops = {
.get_drvinfo = ne2k_pci_get_drvinfo,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
@@ -673,7 +675,6 @@ static int ne2k_pci_resume (struct pci_dev *pdev)
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
pci_enable_device(pdev);
- pci_set_master(pdev);
NS8390_init(dev, 1);
netif_device_attach(dev);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index 6c92f0969015..73501d846588 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -26,9 +26,6 @@
Updated to EISA probing API 5/2003 by Marc Zyngier.
*/
-static const char *version =
- "ne3210.c: Driver revision v0.03, 30/09/98\n";
-
#include <linux/module.h>
#include <linux/eisa.h>
#include <linux/kernel.h>
@@ -197,7 +194,7 @@ static int __init ne3210_eisa_probe (struct device *device)
ei_status.priv = phys_mem;
if (ei_debug > 0)
- printk(version);
+ printk("ne3210 loaded.\n");
ei_status.reset_8390 = &ne3210_reset_8390;
ei_status.block_input = &ne3210_block_input;
@@ -360,12 +357,12 @@ MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(eisa, ne3210_ids);
-int ne3210_init(void)
+static int ne3210_init(void)
{
return eisa_driver_register (&ne3210_eisa_driver);
}
-void ne3210_cleanup(void)
+static void ne3210_cleanup(void)
{
eisa_driver_unregister (&ne3210_eisa_driver);
}
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 925d1dfcc4dc..bb42ff218484 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -696,8 +696,7 @@ static void ni65_free_buffer(struct priv *p)
return;
for(i=0;i<TMDNUM;i++) {
- if(p->tmdbounce[i])
- kfree(p->tmdbounce[i]);
+ kfree(p->tmdbounce[i]);
#ifdef XMT_VIA_SKB
if(p->tmd_skb[i])
dev_kfree_skb(p->tmd_skb[i]);
@@ -710,12 +709,10 @@ static void ni65_free_buffer(struct priv *p)
if(p->recv_skb[i])
dev_kfree_skb(p->recv_skb[i]);
#else
- if(p->recvbounce[i])
- kfree(p->recvbounce[i]);
+ kfree(p->recvbounce[i]);
#endif
}
- if(p->self)
- kfree(p->self);
+ kfree(p->self);
}
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index e64df4d0800b..a3c3fc9c0d8a 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -584,7 +584,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
return 0;
}
-static inline int rx_refill(struct net_device *ndev, int gfp)
+static inline int rx_refill(struct net_device *ndev, gfp_t gfp)
{
struct ns83820 *dev = PRIV(ndev);
unsigned i;
@@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab
timed_out = 1;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (status & fail)
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 4a391ea0f58a..a1ac4bd1696e 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -486,9 +486,9 @@ struct netdrv_private {
MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM (max_interrupt_work, "i");
-MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");
+module_param(multicast_filter_limit, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param_array(media, int, NULL, 0);
MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses");
MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt");
MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex");
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 9d8197bb293a..384a736a0d2f 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -134,7 +134,7 @@ typedef struct local_info_t {
u_char mc_filter[8];
} local_info_t;
-#define MC_FILTERBREAK 64
+#define MC_FILTERBREAK 8
/*====================================================================*/
/*
@@ -1012,7 +1012,7 @@ static void fjn_reset(struct net_device *dev)
outb(BANK_1U, ioaddr + CONFIG_1);
/* set the multicast table to accept none. */
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 8; i++)
outb(0x00, ioaddr + MAR_ADR + i);
/* Switch to bank 2 (runtime mode) */
@@ -1269,6 +1269,16 @@ static void set_rx_mode(struct net_device *dev)
u_long flags;
int i;
+ int saved_config_0 = inb(ioaddr + CONFIG_0);
+
+ local_irq_save(flags);
+
+ /* Disable Tx and Rx */
+ if (sram_config == 0)
+ outb(CONFIG0_RST, ioaddr + CONFIG_0);
+ else
+ outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name);
@@ -1290,20 +1300,23 @@ static void set_rx_mode(struct net_device *dev)
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
unsigned int bit =
- ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f;
- mc_filter[bit >> 3] |= (1 << bit);
+ ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
+ mc_filter[bit >> 3] |= (1 << (bit & 7));
}
+ outb(2, ioaddr + RX_MODE); /* Use normal mode. */
}
- local_irq_save(flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inb(ioaddr + CONFIG_1);
/* Switch to bank 1 and set the multicast table. */
outb(0xe4, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++)
- outb(mc_filter[i], ioaddr + 8 + i);
+ outb(mc_filter[i], ioaddr + MAR_ADR + i);
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outb(saved_bank, ioaddr + CONFIG_1);
}
+
+ outb(saved_config_0, ioaddr + CONFIG_0);
+
local_irq_restore(flags);
}
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 9f22d138e3ad..818c185d6438 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1020,6 +1020,12 @@ static void set_misc_reg(struct net_device *dev)
} else {
outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
}
+ } else if (info->flags & IS_DL10019) {
+ /* Advertise 100F, 100H, 10F, 10H */
+ mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+ /* Restart MII autonegotiation */
+ mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+ mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
}
}
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index d652e1eddb45..c7cca842e5ee 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1832,7 +1832,7 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
{
struct dev_mc_list *mc_addr;
- for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) {
+ for (mc_addr = addrs; mc_addr && count-- > 0; mc_addr = mc_addr->next) {
u_int position = ether_crc(6, mc_addr->dmi_addr);
#ifndef final_version /* Verify multicast address. */
if ((mc_addr->dmi_addr[0] & 1) == 0)
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 113b68099216..70fe81a89df9 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.30j"
-#define DRV_RELDATE "29.04.2005"
+#define DRV_VERSION "1.31a"
+#define DRV_RELDATE "12.Sep.2005"
#define PFX DRV_NAME ": "
static const char *version =
@@ -257,6 +257,9 @@ static int homepna[MAX_UNITS];
* v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
* v1.30i 28 Jun 2004 Don Fry change to use module_param.
* v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test.
+ * v1.31 02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
+ * v1.31a 12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
+ * to allow loopback test to work unchanged.
*/
@@ -266,17 +269,17 @@ static int homepna[MAX_UNITS];
* That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
*/
#ifndef PCNET32_LOG_TX_BUFFERS
-#define PCNET32_LOG_TX_BUFFERS 4
-#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_TX_BUFFERS 4
+#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_MAX_TX_BUFFERS 9 /* 2^9 == 512 */
+#define PCNET32_LOG_MAX_RX_BUFFERS 9
#endif
#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS ((PCNET32_LOG_TX_BUFFERS) << 12)
+#define TX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_TX_BUFFERS))
#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4)
+#define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS))
#define PKT_BUF_SZ 1544
@@ -334,14 +337,14 @@ struct pcnet32_access {
};
/*
- * The first three fields of pcnet32_private are read by the ethernet device
- * so we allocate the structure should be allocated by pci_alloc_consistent().
+ * The first field of pcnet32_private is read by the ethernet device
+ * so the structure should be allocated using pci_alloc_consistent().
*/
struct pcnet32_private {
- /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
- struct pcnet32_rx_head rx_ring[RX_RING_SIZE];
- struct pcnet32_tx_head tx_ring[TX_RING_SIZE];
struct pcnet32_init_block init_block;
+ /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+ struct pcnet32_rx_head *rx_ring;
+ struct pcnet32_tx_head *tx_ring;
dma_addr_t dma_addr; /* DMA address of beginning of this
object, returned by
pci_alloc_consistent */
@@ -349,13 +352,21 @@ struct pcnet32_private {
structure */
const char *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
- struct sk_buff *tx_skbuff[TX_RING_SIZE];
- struct sk_buff *rx_skbuff[RX_RING_SIZE];
- dma_addr_t tx_dma_addr[TX_RING_SIZE];
- dma_addr_t rx_dma_addr[RX_RING_SIZE];
+ struct sk_buff **tx_skbuff;
+ struct sk_buff **rx_skbuff;
+ dma_addr_t *tx_dma_addr;
+ dma_addr_t *rx_dma_addr;
struct pcnet32_access a;
spinlock_t lock; /* Guard lock */
unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int rx_ring_size; /* current rx ring size */
+ unsigned int tx_ring_size; /* current tx ring size */
+ unsigned int rx_mod_mask; /* rx ring modular mask */
+ unsigned int tx_mod_mask; /* tx ring modular mask */
+ unsigned short rx_len_bits;
+ unsigned short tx_len_bits;
+ dma_addr_t rx_ring_dma_addr;
+ dma_addr_t tx_ring_dma_addr;
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
char tx_full;
@@ -397,6 +408,9 @@ static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
static void pcnet32_purge_tx_ring(struct net_device *dev);
+static int pcnet32_alloc_ring(struct net_device *dev);
+static void pcnet32_free_ring(struct net_device *dev);
+
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -613,10 +627,62 @@ static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringpar
{
struct pcnet32_private *lp = dev->priv;
- ering->tx_max_pending = TX_RING_SIZE - 1;
- ering->tx_pending = lp->cur_tx - lp->dirty_tx;
- ering->rx_max_pending = RX_RING_SIZE - 1;
- ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+ ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
+ ering->tx_pending = lp->tx_ring_size - 1;
+ ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
+ ering->rx_pending = lp->rx_ring_size - 1;
+}
+
+static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+ struct pcnet32_private *lp = dev->priv;
+ unsigned long flags;
+ int i;
+
+ if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ pcnet32_close(dev);
+
+ spin_lock_irqsave(&lp->lock, flags);
+ pcnet32_free_ring(dev);
+ lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
+ lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
+
+ /* set the minimum ring size to 4, to allow the loopback test to work
+ * unchanged.
+ */
+ for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+ if (lp->tx_ring_size <= (1 << i))
+ break;
+ }
+ lp->tx_ring_size = (1 << i);
+ lp->tx_mod_mask = lp->tx_ring_size - 1;
+ lp->tx_len_bits = (i << 12);
+
+ for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+ if (lp->rx_ring_size <= (1 << i))
+ break;
+ }
+ lp->rx_ring_size = (1 << i);
+ lp->rx_mod_mask = lp->rx_ring_size - 1;
+ lp->rx_len_bits = (i << 4);
+
+ if (pcnet32_alloc_ring(dev)) {
+ pcnet32_free_ring(dev);
+ return -ENOMEM;
+ }
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
+
+ if (netif_running(dev))
+ pcnet32_open(dev);
+
+ return 0;
}
static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -948,6 +1014,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.nway_reset = pcnet32_nway_reset,
.get_link = pcnet32_get_link,
.get_ringparam = pcnet32_get_ringparam,
+ .set_ringparam = pcnet32_set_ringparam,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.get_tso = ethtool_op_get_tso,
@@ -957,6 +1024,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/* only probes for non-PCI devices, the rest are handled by
@@ -1185,9 +1253,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
memcpy(dev->dev_addr, promaddr, 6);
}
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
- if (!is_valid_ether_addr(dev->dev_addr))
+ if (!is_valid_ether_addr(dev->perm_addr))
memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
if (pcnet32_debug & NETIF_MSG_PROBE) {
@@ -1239,6 +1308,12 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dev->priv = lp;
lp->name = chipname;
lp->shared_irq = shared;
+ lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
+ lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */
+ lp->tx_mod_mask = lp->tx_ring_size - 1;
+ lp->rx_mod_mask = lp->rx_ring_size - 1;
+ lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
+ lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
lp->mii_if.full_duplex = fdx;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
@@ -1265,21 +1340,23 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
}
lp->a = *a;
+ if (pcnet32_alloc_ring(dev)) {
+ ret = -ENOMEM;
+ goto err_free_ring;
+ }
/* detect special T1/E1 WAN card by checking for MAC address */
if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
&& dev->dev_addr[2] == 0x75)
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
- lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
lp->init_block.filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000;
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, rx_ring));
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, tx_ring));
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
/* switch pcnet32 to 32bit mode */
a->write_bcr(ioaddr, 20, 2);
@@ -1310,7 +1387,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", failed to detect IRQ line.\n");
ret = -ENODEV;
- goto err_free_consistent;
+ goto err_free_ring;
}
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", probed IRQ %d.\n", dev->irq);
@@ -1341,7 +1418,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
/* Fill in the generic fields of the device structure. */
if (register_netdev(dev))
- goto err_free_consistent;
+ goto err_free_ring;
if (pdev) {
pci_set_drvdata(pdev, dev);
@@ -1359,6 +1436,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
return 0;
+err_free_ring:
+ pcnet32_free_ring(dev);
err_free_consistent:
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
err_free_netdev:
@@ -1369,6 +1448,86 @@ err_release_region:
}
+static int pcnet32_alloc_ring(struct net_device *dev)
+{
+ struct pcnet32_private *lp = dev->priv;
+
+ if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+ &lp->tx_ring_dma_addr)) == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
+ if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+ &lp->rx_ring_dma_addr)) == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
+ if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
+
+ if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
+
+ if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
+
+ if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk(KERN_ERR PFX "Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+ memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
+
+ return 0;
+}
+
+
+static void pcnet32_free_ring(struct net_device *dev)
+{
+ struct pcnet32_private *lp = dev->priv;
+
+ kfree(lp->tx_skbuff);
+ lp->tx_skbuff = NULL;
+
+ kfree(lp->rx_skbuff);
+ lp->rx_skbuff = NULL;
+
+ kfree(lp->tx_dma_addr);
+ lp->tx_dma_addr = NULL;
+
+ kfree(lp->rx_dma_addr);
+ lp->rx_dma_addr = NULL;
+
+ if (lp->tx_ring) {
+ pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+ lp->tx_ring, lp->tx_ring_dma_addr);
+ lp->tx_ring = NULL;
+ }
+
+ if (lp->rx_ring) {
+ pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+ lp->rx_ring, lp->rx_ring_dma_addr);
+ lp->rx_ring = NULL;
+ }
+}
+
+
static int
pcnet32_open(struct net_device *dev)
{
@@ -1400,8 +1559,8 @@ pcnet32_open(struct net_device *dev)
if (netif_msg_ifup(lp))
printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
dev->name, dev->irq,
- (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
- (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
+ (u32) (lp->tx_ring_dma_addr),
+ (u32) (lp->rx_ring_dma_addr),
(u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
/* set/reset autoselect bit */
@@ -1521,7 +1680,7 @@ pcnet32_open(struct net_device *dev)
err_free_ring:
/* free any allocated skbuffs */
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
@@ -1531,6 +1690,9 @@ err_free_ring:
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
+
+ pcnet32_free_ring(dev);
+
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
@@ -1562,7 +1724,7 @@ pcnet32_purge_tx_ring(struct net_device *dev)
struct pcnet32_private *lp = dev->priv;
int i;
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -1587,7 +1749,7 @@ pcnet32_init_ring(struct net_device *dev)
lp->cur_rx = lp->cur_tx = 0;
lp->dirty_rx = lp->dirty_tx = 0;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
if (rx_skbuff == NULL) {
if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
@@ -1611,20 +1773,18 @@ pcnet32_init_ring(struct net_device *dev)
}
/* The Tx buffer address is filled in as needed, but we do need to clear
* the upper ownership bit. */
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
lp->tx_ring[i].base = 0;
lp->tx_dma_addr[i] = 0;
}
- lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
- lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, rx_ring));
- lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
- offsetof(struct pcnet32_private, tx_ring));
+ lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+ lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
wmb(); /* Make sure all changes are visible */
return 0;
}
@@ -1682,13 +1842,13 @@ pcnet32_tx_timeout (struct net_device *dev)
printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
lp->cur_rx);
- for (i = 0 ; i < RX_RING_SIZE; i++)
+ for (i = 0 ; i < lp->rx_ring_size; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->rx_ring[i].base),
(-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
le32_to_cpu(lp->rx_ring[i].msg_length),
le16_to_cpu(lp->rx_ring[i].status));
- for (i = 0 ; i < TX_RING_SIZE; i++)
+ for (i = 0 ; i < lp->tx_ring_size; i++)
printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
le32_to_cpu(lp->tx_ring[i].base),
(-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
@@ -1729,7 +1889,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Fill in a Tx ring entry */
/* Mask to ring buffer boundary. */
- entry = lp->cur_tx & TX_RING_MOD_MASK;
+ entry = lp->cur_tx & lp->tx_mod_mask;
/* Caution: the write order is important here, set the status
* with the "ownership" bits last. */
@@ -1753,7 +1913,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
+ if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
lp->tx_full = 1;
netif_stop_queue(dev);
}
@@ -1806,7 +1966,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int delta;
while (dirty_tx != lp->cur_tx) {
- int entry = dirty_tx & TX_RING_MOD_MASK;
+ int entry = dirty_tx & lp->tx_mod_mask;
int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
if (status < 0)
@@ -1864,18 +2024,18 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dirty_tx++;
}
- delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
- if (delta > TX_RING_SIZE) {
+ delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+ if (delta > lp->tx_ring_size) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
- dirty_tx += TX_RING_SIZE;
- delta -= TX_RING_SIZE;
+ dirty_tx += lp->tx_ring_size;
+ delta -= lp->tx_ring_size;
}
if (lp->tx_full &&
netif_queue_stopped(dev) &&
- delta < TX_RING_SIZE - 2) {
+ delta < lp->tx_ring_size - 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
netif_wake_queue (dev);
@@ -1932,8 +2092,8 @@ static int
pcnet32_rx(struct net_device *dev)
{
struct pcnet32_private *lp = dev->priv;
- int entry = lp->cur_rx & RX_RING_MOD_MASK;
- int boguscnt = RX_RING_SIZE / 2;
+ int entry = lp->cur_rx & lp->rx_mod_mask;
+ int boguscnt = lp->rx_ring_size / 2;
/* If we own the next entry, it's a new packet. Send it up. */
while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
@@ -1998,12 +2158,12 @@ pcnet32_rx(struct net_device *dev)
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
dev->name);
- for (i = 0; i < RX_RING_SIZE; i++)
+ for (i = 0; i < lp->rx_ring_size; i++)
if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
- & RX_RING_MOD_MASK].status) < 0)
+ & lp->rx_mod_mask].status) < 0)
break;
- if (i > RX_RING_SIZE -2) {
+ if (i > lp->rx_ring_size -2) {
lp->stats.rx_dropped++;
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
wmb(); /* Make sure adapter sees owner change */
@@ -2041,7 +2201,7 @@ pcnet32_rx(struct net_device *dev)
lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
wmb(); /* Make sure owner changes after all others are visible */
lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
- entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+ entry = (++lp->cur_rx) & lp->rx_mod_mask;
if (--boguscnt <= 0) break; /* don't stay in loop forever */
}
@@ -2084,7 +2244,7 @@ pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
@@ -2096,7 +2256,7 @@ pcnet32_close(struct net_device *dev)
lp->rx_dma_addr[i] = 0;
}
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
@@ -2265,6 +2425,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
struct pcnet32_private *lp = dev->priv;
unregister_netdev(dev);
+ pcnet32_free_ring(dev);
release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(dev);
@@ -2340,6 +2501,7 @@ static void __exit pcnet32_cleanup_module(void)
struct pcnet32_private *lp = pcnet32_dev->priv;
next_dev = lp->next;
unregister_netdev(pcnet32_dev);
+ pcnet32_free_ring(pcnet32_dev);
release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
free_netdev(pcnet32_dev);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
new file mode 100644
index 000000000000..c782a6329805
--- /dev/null
+++ b/drivers/net/phy/Kconfig
@@ -0,0 +1,49 @@
+#
+# PHY Layer Configuration
+#
+
+menu "PHY device support"
+
+config PHYLIB
+ tristate "PHY Device support and infrastructure"
+ depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
+ help
+ Ethernet controllers are usually attached to PHY
+ devices. This option provides infrastructure for
+ managing PHY devices.
+
+comment "MII PHY device drivers"
+ depends on PHYLIB
+
+config MARVELL_PHY
+ tristate "Drivers for Marvell PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently has a driver for the 88E1011S
+
+config DAVICOM_PHY
+ tristate "Drivers for Davicom PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports dm9161e and dm9131
+
+config QSEMI_PHY
+ tristate "Drivers for Quality Semiconductor PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the qs6612
+
+config LXT_PHY
+ tristate "Drivers for the Intel LXT PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the lxt970, lxt971
+
+config CICADA_PHY
+ tristate "Drivers for the Cicada PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the cis8204
+
+endmenu
+
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
new file mode 100644
index 000000000000..e4116a5fbb4c
--- /dev/null
+++ b/drivers/net/phy/Makefile
@@ -0,0 +1,10 @@
+# Makefile for Linux PHY drivers
+
+libphy-objs := phy.o phy_device.o mdio_bus.o
+
+obj-$(CONFIG_PHYLIB) += libphy.o
+obj-$(CONFIG_MARVELL_PHY) += marvell.o
+obj-$(CONFIG_DAVICOM_PHY) += davicom.o
+obj-$(CONFIG_CICADA_PHY) += cicada.o
+obj-$(CONFIG_LXT_PHY) += lxt.o
+obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
new file mode 100644
index 000000000000..c47fb2ecd147
--- /dev/null
+++ b/drivers/net/phy/cicada.c
@@ -0,0 +1,134 @@
+/*
+ * drivers/net/phy/cicada.c
+ *
+ * Driver for Cicada PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1 0x17
+#define MII_CIS8201_EXTCON1_INIT 0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK 0x19
+#define MII_CIS8201_IMASK_IEN 0x8000
+#define MII_CIS8201_IMASK_SPEED 0x4000
+#define MII_CIS8201_IMASK_LINK 0x2000
+#define MII_CIS8201_IMASK_DUPLEX 0x1000
+#define MII_CIS8201_IMASK_MASK 0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT 0x1a
+#define MII_CIS8201_ISTAT_STATUS 0x8000
+#define MII_CIS8201_ISTAT_SPEED 0x4000
+#define MII_CIS8201_ISTAT_LINK 0x2000
+#define MII_CIS8201_ISTAT_DUPLEX 0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT 0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
+#define MII_CIS8201_AUXCONSTAT_100 0x0008
+
+MODULE_DESCRIPTION("Cicadia PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int cis820x_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
+ MII_CIS8201_AUXCONSTAT_INIT);
+
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_CIS8201_EXT_CON1,
+ MII_CIS8201_EXTCON1_INIT);
+
+ return err;
+}
+
+static int cis820x_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_CIS8201_ISTAT);
+
+ return (err < 0) ? err : 0;
+}
+
+static int cis820x_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_CIS8201_IMASK,
+ MII_CIS8201_IMASK_MASK);
+ else
+ err = phy_write(phydev, MII_CIS8201_IMASK, 0);
+
+ return err;
+}
+
+/* Cicada 820x */
+static struct phy_driver cis8204_driver = {
+ .phy_id = 0x000fc440,
+ .name = "Cicada Cis8204",
+ .phy_id_mask = 0x000fffc0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &cis820x_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &cis820x_ack_interrupt,
+ .config_intr = &cis820x_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init cis8204_init(void)
+{
+ return phy_driver_register(&cis8204_driver);
+}
+
+static void __exit cis8204_exit(void)
+{
+ phy_driver_unregister(&cis8204_driver);
+}
+
+module_init(cis8204_init);
+module_exit(cis8204_exit);
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
new file mode 100644
index 000000000000..6caf499fae32
--- /dev/null
+++ b/drivers/net/phy/davicom.c
@@ -0,0 +1,195 @@
+/*
+ * drivers/net/phy/davicom.c
+ *
+ * Driver for Davicom PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_DM9161_SCR 0x10
+#define MII_DM9161_SCR_INIT 0x0610
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR 0x15
+#define MII_DM9161_INTR_PEND 0x8000
+#define MII_DM9161_INTR_DPLX_MASK 0x0800
+#define MII_DM9161_INTR_SPD_MASK 0x0400
+#define MII_DM9161_INTR_LINK_MASK 0x0200
+#define MII_DM9161_INTR_MASK 0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
+#define MII_DM9161_INTR_SPD_CHANGE 0x0008
+#define MII_DM9161_INTR_LINK_CHANGE 0x0004
+#define MII_DM9161_INTR_INIT 0x0000
+#define MII_DM9161_INTR_STOP \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR 0x12
+#define MII_DM9161_10BTCSR_INIT 0x7800
+
+MODULE_DESCRIPTION("Davicom PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+
+#define DM9161_DELAY 1
+static int dm9161_config_intr(struct phy_device *phydev)
+{
+ int temp;
+
+ temp = phy_read(phydev, MII_DM9161_INTR);
+
+ if (temp < 0)
+ return temp;
+
+ if(PHY_INTERRUPT_ENABLED == phydev->interrupts )
+ temp &= ~(MII_DM9161_INTR_STOP);
+ else
+ temp |= MII_DM9161_INTR_STOP;
+
+ temp = phy_write(phydev, MII_DM9161_INTR, temp);
+
+ return temp;
+}
+
+static int dm9161_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ /* Isolate the PHY */
+ err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+ if (err < 0)
+ return err;
+
+ /* Configure the new settings */
+ err = genphy_config_aneg(phydev);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int dm9161_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ /* Isolate the PHY */
+ err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+ if (err < 0)
+ return err;
+
+ /* Do not bypass the scrambler/descrambler */
+ err = phy_write(phydev, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+ if (err < 0)
+ return err;
+
+ /* Clear 10BTCSR to default */
+ err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+ if (err < 0)
+ return err;
+
+ /* Reconnect the PHY, and enable Autonegotiation */
+ err = phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int dm9161_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_DM9161_INTR);
+
+ return (err < 0) ? err : 0;
+}
+
+static struct phy_driver dm9161_driver = {
+ .phy_id = 0x0181b880,
+ .name = "Davicom DM9161E",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .config_init = dm9161_config_init,
+ .config_aneg = dm9161_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver dm9131_driver = {
+ .phy_id = 0x00181b80,
+ .name = "Davicom DM9131",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = dm9161_ack_interrupt,
+ .config_intr = dm9161_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init davicom_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&dm9161_driver);
+ if (ret)
+ goto err1;
+
+ ret = phy_driver_register(&dm9131_driver);
+ if (ret)
+ goto err2;
+ return 0;
+
+ err2:
+ phy_driver_unregister(&dm9161_driver);
+ err1:
+ return ret;
+}
+
+static void __exit davicom_exit(void)
+{
+ phy_driver_unregister(&dm9161_driver);
+ phy_driver_unregister(&dm9131_driver);
+}
+
+module_init(davicom_init);
+module_exit(davicom_exit);
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
new file mode 100644
index 000000000000..4c840448ec86
--- /dev/null
+++ b/drivers/net/phy/lxt.c
@@ -0,0 +1,179 @@
+/*
+ * drivers/net/phy/lxt.c
+ *
+ * Driver for Intel LXT PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* The Level one LXT970 is used by many boards */
+
+#define MII_LXT970_IER 17 /* Interrupt Enable Register */
+
+#define MII_LXT970_IER_IEN 0x0002
+
+#define MII_LXT970_ISR 18 /* Interrupt Status Register */
+
+#define MII_LXT970_CONFIG 19 /* Configuration Register */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards */
+
+/* register definitions for the 971 */
+#define MII_LXT971_IER 18 /* Interrupt Enable Register */
+#define MII_LXT971_IER_IEN 0x00f2
+
+#define MII_LXT971_ISR 19 /* Interrupt Status Register */
+
+
+MODULE_DESCRIPTION("Intel LXT PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int lxt970_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, MII_BMSR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_LXT970_ISR);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int lxt970_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN);
+ else
+ err = phy_write(phydev, MII_LXT970_IER, 0);
+
+ return err;
+}
+
+static int lxt970_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_LXT970_CONFIG, 0);
+
+ return err;
+}
+
+
+static int lxt971_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_LXT971_ISR);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int lxt971_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN);
+ else
+ err = phy_write(phydev, MII_LXT971_IER, 0);
+
+ return err;
+}
+
+static struct phy_driver lxt970_driver = {
+ .phy_id = 0x07810000,
+ .name = "LXT970",
+ .phy_id_mask = 0x0fffffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = lxt970_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = lxt970_ack_interrupt,
+ .config_intr = lxt970_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static struct phy_driver lxt971_driver = {
+ .phy_id = 0x0001378e,
+ .name = "LXT971",
+ .phy_id_mask = 0x0fffffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = lxt971_ack_interrupt,
+ .config_intr = lxt971_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init lxt_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&lxt970_driver);
+ if (ret)
+ goto err1;
+
+ ret = phy_driver_register(&lxt971_driver);
+ if (ret)
+ goto err2;
+ return 0;
+
+ err2:
+ phy_driver_unregister(&lxt970_driver);
+ err1:
+ return ret;
+}
+
+static void __exit lxt_exit(void)
+{
+ phy_driver_unregister(&lxt970_driver);
+ phy_driver_unregister(&lxt971_driver);
+}
+
+module_init(lxt_init);
+module_exit(lxt_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
new file mode 100644
index 000000000000..4a72b025006b
--- /dev/null
+++ b/drivers/net/phy/marvell.c
@@ -0,0 +1,140 @@
+/*
+ * drivers/net/phy/marvell.c
+ *
+ * Driver for Marvell PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_M1011_IEVENT 0x13
+#define MII_M1011_IEVENT_CLEAR 0x0000
+
+#define MII_M1011_IMASK 0x12
+#define MII_M1011_IMASK_INIT 0x6400
+#define MII_M1011_IMASK_CLEAR 0x0000
+
+MODULE_DESCRIPTION("Marvell PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+static int marvell_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ /* Clear the interrupts by reading the reg */
+ err = phy_read(phydev, MII_M1011_IEVENT);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int marvell_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+ else
+ err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+ return err;
+}
+
+static int marvell_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ /* The Marvell PHY has an errata which requires
+ * that certain registers get written in order
+ * to restart autonegotiation */
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x1f);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x200c);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x5);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x100);
+ if (err < 0)
+ return err;
+
+
+ err = genphy_config_aneg(phydev);
+
+ return err;
+}
+
+
+static struct phy_driver m88e1101_driver = {
+ .phy_id = 0x01410c00,
+ .phy_id_mask = 0xffffff00,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init marvell_init(void)
+{
+ return phy_driver_register(&m88e1101_driver);
+}
+
+static void __exit marvell_exit(void)
+{
+ phy_driver_unregister(&m88e1101_driver);
+}
+
+module_init(marvell_init);
+module_exit(marvell_exit);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
new file mode 100644
index 000000000000..ad93b0da87f0
--- /dev/null
+++ b/drivers/net/phy/mdio_bus.c
@@ -0,0 +1,168 @@
+/*
+ * drivers/net/phy/mdio_bus.c
+ *
+ * MDIO Bus interface
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* mdiobus_register
+ *
+ * description: Called by a bus driver to bring up all the PHYs
+ * on a given bus, and attach them to the bus
+ */
+int mdiobus_register(struct mii_bus *bus)
+{
+ int i;
+ int err = 0;
+
+ spin_lock_init(&bus->mdio_lock);
+
+ if (NULL == bus || NULL == bus->name ||
+ NULL == bus->read ||
+ NULL == bus->write)
+ return -EINVAL;
+
+ if (bus->reset)
+ bus->reset(bus);
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *phydev;
+
+ phydev = get_phy_device(bus, i);
+
+ if (IS_ERR(phydev))
+ return PTR_ERR(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 */
+ if (phydev) {
+ phydev->irq = bus->irq[i];
+
+ phydev->dev.parent = bus->dev;
+ phydev->dev.bus = &mdio_bus_type;
+ sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+
+ phydev->bus = bus;
+
+ err = device_register(&phydev->dev);
+
+ if (err)
+ printk(KERN_ERR "phy %d failed to register\n",
+ i);
+ }
+
+ bus->phy_map[i] = phydev;
+ }
+
+ pr_info("%s: probed\n", bus->name);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_register);
+
+void mdiobus_unregister(struct mii_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if (bus->phy_map[i]) {
+ device_unregister(&bus->phy_map[i]->dev);
+ kfree(bus->phy_map[i]);
+ }
+ }
+}
+EXPORT_SYMBOL(mdiobus_unregister);
+
+/* mdio_bus_match
+ *
+ * description: Given a PHY device, and a PHY driver, return 1 if
+ * the driver supports the device. Otherwise, return 0
+ */
+static int mdio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct phy_device *phydev = to_phy_device(dev);
+ struct phy_driver *phydrv = to_phy_driver(drv);
+
+ return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask));
+}
+
+/* Suspend and resume. Copied from platform_suspend and
+ * platform_resume
+ */
+static int mdio_bus_suspend(struct device * dev, pm_message_t state)
+{
+ int ret = 0;
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->suspend)
+ ret = drv->suspend(dev, state);
+
+ return ret;
+}
+
+static int mdio_bus_resume(struct device * dev)
+{
+ int ret = 0;
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->resume)
+ ret = drv->resume(dev);
+
+ return ret;
+}
+
+struct bus_type mdio_bus_type = {
+ .name = "mdio_bus",
+ .match = mdio_bus_match,
+ .suspend = mdio_bus_suspend,
+ .resume = mdio_bus_resume,
+};
+
+int __init mdio_bus_init(void)
+{
+ return bus_register(&mdio_bus_type);
+}
+
+void mdio_bus_exit(void)
+{
+ bus_unregister(&mdio_bus_type);
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
new file mode 100644
index 000000000000..9209da9dde0d
--- /dev/null
+++ b/drivers/net/phy/phy.c
@@ -0,0 +1,863 @@
+/*
+ * drivers/net/phy/phy.c
+ *
+ * Framework for configuring and reading PHY devices
+ * Based on code in sungem_phy.c and gianfar_phy.c
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* Convenience function to print out the current phy status
+ */
+void phy_print_status(struct phy_device *phydev)
+{
+ pr_info("%s: Link is %s", phydev->dev.bus_id,
+ phydev->link ? "Up" : "Down");
+ if (phydev->link)
+ printk(" - %d/%s", phydev->speed,
+ DUPLEX_FULL == phydev->duplex ?
+ "Full" : "Half");
+
+ printk("\n");
+}
+EXPORT_SYMBOL(phy_print_status);
+
+
+/* Convenience functions for reading/writing a given PHY
+ * register. They 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;
+
+ spin_lock_bh(&bus->mdio_lock);
+ retval = bus->read(bus, phydev->addr, regnum);
+ spin_unlock_bh(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(phy_read);
+
+int phy_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+ int err;
+ struct mii_bus *bus = phydev->bus;
+
+ spin_lock_bh(&bus->mdio_lock);
+ err = bus->write(bus, phydev->addr, regnum, val);
+ spin_unlock_bh(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_write);
+
+
+int phy_clear_interrupt(struct phy_device *phydev)
+{
+ int err = 0;
+
+ if (phydev->drv->ack_interrupt)
+ err = phydev->drv->ack_interrupt(phydev);
+
+ return err;
+}
+
+
+int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
+{
+ int err = 0;
+
+ phydev->interrupts = interrupts;
+ if (phydev->drv->config_intr)
+ err = phydev->drv->config_intr(phydev);
+
+ return err;
+}
+
+
+/* phy_aneg_done
+ *
+ * description: Reads the status register and returns 0 either if
+ * auto-negotiation is incomplete, or if there was an error.
+ * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ */
+static inline int phy_aneg_done(struct phy_device *phydev)
+{
+ int retval;
+
+ retval = phy_read(phydev, MII_BMSR);
+
+ return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+
+/* A structure for mapping a particular speed and duplex
+ * combination to a particular SUPPORTED and ADVERTISED value */
+struct phy_setting {
+ int speed;
+ int duplex;
+ u32 setting;
+};
+
+/* A mapping of all SUPPORTED settings to speed/duplex */
+static struct phy_setting settings[] = {
+ {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10000baseT_Full,
+ },
+ {
+ .speed = SPEED_1000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_1000baseT_Full,
+ },
+ {
+ .speed = SPEED_1000,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_1000baseT_Half,
+ },
+ {
+ .speed = SPEED_100,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_100baseT_Full,
+ },
+ {
+ .speed = SPEED_100,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_100baseT_Half,
+ },
+ {
+ .speed = SPEED_10,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10baseT_Full,
+ },
+ {
+ .speed = SPEED_10,
+ .duplex = DUPLEX_HALF,
+ .setting = SUPPORTED_10baseT_Half,
+ },
+};
+
+#define MAX_NUM_SETTINGS (sizeof(settings)/sizeof(struct phy_setting))
+
+/* phy_find_setting
+ *
+ * description: Searches the settings array for the setting which
+ * matches the desired speed and duplex, and returns the index
+ * of that setting. Returns the index of the last setting if
+ * none of the others match.
+ */
+static inline int phy_find_setting(int speed, int duplex)
+{
+ int idx = 0;
+
+ while (idx < ARRAY_SIZE(settings) &&
+ (settings[idx].speed != speed ||
+ settings[idx].duplex != duplex))
+ idx++;
+
+ return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_find_valid
+ * idx: The first index in settings[] to search
+ * features: A mask of the valid settings
+ *
+ * description: Returns the index of the first valid setting less
+ * than or equal to the one pointed to by idx, as determined by
+ * the mask in features. Returns the index of the last setting
+ * if nothing else matches.
+ */
+static inline int phy_find_valid(int idx, u32 features)
+{
+ while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
+ idx++;
+
+ return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
+}
+
+/* phy_sanitize_settings
+ *
+ * description: Make sure the PHY is set to supported speeds and
+ * duplexes. Drop down by one in this order: 1000/FULL,
+ * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF
+ */
+void phy_sanitize_settings(struct phy_device *phydev)
+{
+ u32 features = phydev->supported;
+ int idx;
+
+ /* Sanitize settings based on PHY capabilities */
+ if ((features & SUPPORTED_Autoneg) == 0)
+ phydev->autoneg = 0;
+
+ idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
+ features);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+}
+EXPORT_SYMBOL(phy_sanitize_settings);
+
+/* phy_ethtool_sset:
+ * A generic ethtool sset function. Handles all the details
+ *
+ * A few notes about parameter checking:
+ * - We don't set port or transceiver, so we don't care what they
+ * were set to.
+ * - phy_start_aneg() will make sure forced settings are sane, and
+ * choose the next best ones from the ones selected, so we don't
+ * care if ethtool tries to give us bad values
+ *
+ */
+int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+ if (cmd->phy_address != phydev->addr)
+ return -EINVAL;
+
+ /* We make sure that we don't pass unsupported
+ * values in to the PHY */
+ cmd->advertising &= phydev->supported;
+
+ /* Verify the settings we care about. */
+ if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_DISABLE
+ && ((cmd->speed != SPEED_1000
+ && cmd->speed != SPEED_100
+ && cmd->speed != SPEED_10)
+ || (cmd->duplex != DUPLEX_HALF
+ && cmd->duplex != DUPLEX_FULL)))
+ return -EINVAL;
+
+ phydev->autoneg = cmd->autoneg;
+
+ phydev->speed = cmd->speed;
+
+ phydev->advertising = cmd->advertising;
+
+ if (AUTONEG_ENABLE == cmd->autoneg)
+ phydev->advertising |= ADVERTISED_Autoneg;
+ else
+ phydev->advertising &= ~ADVERTISED_Autoneg;
+
+ phydev->duplex = cmd->duplex;
+
+ /* Restart the PHY */
+ phy_start_aneg(phydev);
+
+ return 0;
+}
+
+int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = phydev->supported;
+
+ cmd->advertising = phydev->advertising;
+
+ cmd->speed = phydev->speed;
+ cmd->duplex = phydev->duplex;
+ cmd->port = PORT_MII;
+ cmd->phy_address = phydev->addr;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->autoneg = phydev->autoneg;
+
+ return 0;
+}
+
+
+/* Note that this function is currently incompatible with the
+ * PHYCONTROL layer. It changes registers without regard to
+ * current state. Use at own risk
+ */
+int phy_mii_ioctl(struct phy_device *phydev,
+ struct mii_ioctl_data *mii_data, int cmd)
+{
+ u16 val = mii_data->val_in;
+
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ mii_data->phy_id = phydev->addr;
+ break;
+ case SIOCGMIIREG:
+ mii_data->val_out = phy_read(phydev, mii_data->reg_num);
+ break;
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (mii_data->phy_id == phydev->addr) {
+ switch(mii_data->reg_num) {
+ case MII_BMCR:
+ if (val & (BMCR_RESET|BMCR_ANENABLE))
+ phydev->autoneg = AUTONEG_DISABLE;
+ else
+ phydev->autoneg = AUTONEG_ENABLE;
+ if ((!phydev->autoneg) && (val & BMCR_FULLDPLX))
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+ break;
+ case MII_ADVERTISE:
+ phydev->advertising = val;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ phy_write(phydev, mii_data->reg_num, val);
+
+ if (mii_data->reg_num == MII_BMCR
+ && val & BMCR_RESET
+ && phydev->drv->config_init)
+ phydev->drv->config_init(phydev);
+ break;
+ }
+
+ return 0;
+}
+
+/* phy_start_aneg
+ *
+ * description: Sanitizes the settings (if we're not
+ * autonegotiating them), and then calls the driver's
+ * config_aneg function. If the PHYCONTROL Layer is operating,
+ * we change the state to reflect the beginning of
+ * Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ spin_lock(&phydev->lock);
+
+ if (AUTONEG_DISABLE == phydev->autoneg)
+ phy_sanitize_settings(phydev);
+
+ err = phydev->drv->config_aneg(phydev);
+
+ if (err < 0)
+ goto out_unlock;
+
+ if (phydev->state != PHY_HALTED) {
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ phydev->state = PHY_AN;
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+ } else {
+ phydev->state = PHY_FORCING;
+ phydev->link_timeout = PHY_FORCE_TIMEOUT;
+ }
+ }
+
+out_unlock:
+ spin_unlock(&phydev->lock);
+ return err;
+}
+EXPORT_SYMBOL(phy_start_aneg);
+
+
+static void phy_change(void *data);
+static void phy_timer(unsigned long data);
+
+/* phy_start_machine:
+ *
+ * description: The PHY infrastructure can run a state machine
+ * which tracks whether the PHY is starting up, negotiating,
+ * etc. This function starts the timer which tracks the state
+ * of the PHY. If you want to be notified when the state
+ * changes, pass in the callback, otherwise, pass NULL. If you
+ * want to maintain your own state machine, do not call this
+ * function. */
+void phy_start_machine(struct phy_device *phydev,
+ void (*handler)(struct net_device *))
+{
+ phydev->adjust_state = handler;
+
+ init_timer(&phydev->phy_timer);
+ phydev->phy_timer.function = &phy_timer;
+ phydev->phy_timer.data = (unsigned long) phydev;
+ mod_timer(&phydev->phy_timer, jiffies + HZ);
+}
+
+/* phy_stop_machine
+ *
+ * description: Stops the state machine timer, sets the state to
+ * UP (unless it wasn't up yet), and then frees the interrupt,
+ * if it is in use. This function must be called BEFORE
+ * phy_detach.
+ */
+void phy_stop_machine(struct phy_device *phydev)
+{
+ del_timer_sync(&phydev->phy_timer);
+
+ spin_lock(&phydev->lock);
+ if (phydev->state > PHY_UP)
+ phydev->state = PHY_UP;
+ spin_unlock(&phydev->lock);
+
+ if (phydev->irq != PHY_POLL)
+ phy_stop_interrupts(phydev);
+
+ phydev->adjust_state = NULL;
+}
+
+/* phy_force_reduction
+ *
+ * description: Reduces the speed/duplex settings by
+ * one notch. The order is so:
+ * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF,
+ * 10/FULL, 10/HALF. The function bottoms out at 10/HALF.
+ */
+static void phy_force_reduction(struct phy_device *phydev)
+{
+ int idx;
+
+ idx = phy_find_setting(phydev->speed, phydev->duplex);
+
+ idx++;
+
+ idx = phy_find_valid(idx, phydev->supported);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+
+ pr_info("Trying %d/%s\n", phydev->speed,
+ DUPLEX_FULL == phydev->duplex ?
+ "FULL" : "HALF");
+}
+
+
+/* phy_error:
+ *
+ * Moves the PHY to the HALTED state in response to a read
+ * or write error, and tells the controller the link is down.
+ * Must not be called from interrupt context, or while the
+ * phydev->lock is held.
+ */
+void phy_error(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+ phydev->state = PHY_HALTED;
+ spin_unlock(&phydev->lock);
+}
+
+/* phy_interrupt
+ *
+ * description: When a PHY interrupt occurs, the handler disables
+ * interrupts, and schedules a work task to clear the interrupt.
+ */
+static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
+{
+ struct phy_device *phydev = phy_dat;
+
+ /* The MDIO bus is not allowed to be written in interrupt
+ * context, so we need to disable the irq here. A work
+ * queue will write the PHY to disable and clear the
+ * interrupt, and then reenable the irq line. */
+ disable_irq_nosync(irq);
+
+ schedule_work(&phydev->phy_queue);
+
+ return IRQ_HANDLED;
+}
+
+/* Enable the interrupts from the PHY side */
+int phy_enable_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_clear_interrupt(phydev);
+
+ if (err < 0)
+ return err;
+
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_enable_interrupts);
+
+/* Disable the PHY interrupts from the PHY side */
+int phy_disable_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ /* Disable PHY interrupts */
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+
+ if (err)
+ goto phy_err;
+
+ /* Clear the interrupt */
+ err = phy_clear_interrupt(phydev);
+
+ if (err)
+ goto phy_err;
+
+ return 0;
+
+phy_err:
+ phy_error(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_disable_interrupts);
+
+/* phy_start_interrupts
+ *
+ * description: Request the interrupt for the given PHY. If
+ * this fails, then we set irq to PHY_POLL.
+ * Otherwise, we enable the interrupts in the PHY.
+ * Returns 0 on success.
+ * This should only be called with a valid IRQ number.
+ */
+int phy_start_interrupts(struct phy_device *phydev)
+{
+ int err = 0;
+
+ INIT_WORK(&phydev->phy_queue, phy_change, phydev);
+
+ if (request_irq(phydev->irq, phy_interrupt,
+ SA_SHIRQ,
+ "phy_interrupt",
+ phydev) < 0) {
+ printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n",
+ phydev->bus->name,
+ phydev->irq);
+ phydev->irq = PHY_POLL;
+ return 0;
+ }
+
+ err = phy_enable_interrupts(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_start_interrupts);
+
+int phy_stop_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_disable_interrupts(phydev);
+
+ if (err)
+ phy_error(phydev);
+
+ free_irq(phydev->irq, phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(phy_stop_interrupts);
+
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void phy_change(void *data)
+{
+ int err;
+ struct phy_device *phydev = data;
+
+ err = phy_disable_interrupts(phydev);
+
+ if (err)
+ goto phy_err;
+
+ spin_lock(&phydev->lock);
+ if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
+ phydev->state = PHY_CHANGELINK;
+ spin_unlock(&phydev->lock);
+
+ enable_irq(phydev->irq);
+
+ /* Reenable interrupts */
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
+
+ if (err)
+ goto irq_enable_err;
+
+ return;
+
+irq_enable_err:
+ disable_irq(phydev->irq);
+phy_err:
+ phy_error(phydev);
+}
+
+/* Bring down the PHY link, and stop checking the status. */
+void phy_stop(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+
+ if (PHY_HALTED == phydev->state)
+ goto out_unlock;
+
+ if (phydev->irq != PHY_POLL) {
+ /* Clear any pending interrupts */
+ phy_clear_interrupt(phydev);
+
+ /* Disable PHY Interrupts */
+ phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+ }
+
+ phydev->state = PHY_HALTED;
+
+out_unlock:
+ spin_unlock(&phydev->lock);
+}
+
+
+/* phy_start
+ *
+ * description: Indicates the attached device's readiness to
+ * handle PHY-related work. Used during startup to start the
+ * PHY, and after a call to phy_stop() to resume operation.
+ * Also used to indicate the MDIO bus has cleared an error
+ * condition.
+ */
+void phy_start(struct phy_device *phydev)
+{
+ spin_lock(&phydev->lock);
+
+ switch (phydev->state) {
+ case PHY_STARTING:
+ phydev->state = PHY_PENDING;
+ break;
+ case PHY_READY:
+ phydev->state = PHY_UP;
+ break;
+ case PHY_HALTED:
+ phydev->state = PHY_RESUMING;
+ default:
+ break;
+ }
+ spin_unlock(&phydev->lock);
+}
+EXPORT_SYMBOL(phy_stop);
+EXPORT_SYMBOL(phy_start);
+
+/* PHY timer which handles the state machine */
+static void phy_timer(unsigned long data)
+{
+ struct phy_device *phydev = (struct phy_device *)data;
+ int needs_aneg = 0;
+ int err = 0;
+
+ spin_lock(&phydev->lock);
+
+ if (phydev->adjust_state)
+ phydev->adjust_state(phydev->attached_dev);
+
+ switch(phydev->state) {
+ case PHY_DOWN:
+ case PHY_STARTING:
+ case PHY_READY:
+ case PHY_PENDING:
+ break;
+ case PHY_UP:
+ needs_aneg = 1;
+
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+
+ break;
+ case PHY_AN:
+ /* Check if negotiation is done. Break
+ * if there's an error */
+ err = phy_aneg_done(phydev);
+ if (err < 0)
+ break;
+
+ /* If auto-negotiation is done, we change to
+ * either RUNNING, or NOLINK */
+ if (err > 0) {
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ phydev->state = PHY_NOLINK;
+ netif_carrier_off(phydev->attached_dev);
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+
+ } else if (0 == phydev->link_timeout--) {
+ /* The counter expired, so either we
+ * switch to forced mode, or the
+ * magic_aneg bit exists, and we try aneg
+ * again */
+ if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) {
+ int idx;
+
+ /* We'll start from the
+ * fastest speed, and work
+ * our way down */
+ idx = phy_find_valid(0,
+ phydev->supported);
+
+ phydev->speed = settings[idx].speed;
+ phydev->duplex = settings[idx].duplex;
+
+ phydev->autoneg = AUTONEG_DISABLE;
+ phydev->state = PHY_FORCING;
+ phydev->link_timeout =
+ PHY_FORCE_TIMEOUT;
+
+ pr_info("Trying %d/%s\n",
+ phydev->speed,
+ DUPLEX_FULL ==
+ phydev->duplex ?
+ "FULL" : "HALF");
+ }
+
+ needs_aneg = 1;
+ }
+ break;
+ case PHY_NOLINK:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ }
+ break;
+ case PHY_FORCING:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ if (0 == phydev->link_timeout--) {
+ phy_force_reduction(phydev);
+ needs_aneg = 1;
+ }
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+ break;
+ case PHY_RUNNING:
+ /* Only register a CHANGE if we are
+ * polling */
+ if (PHY_POLL == phydev->irq)
+ phydev->state = PHY_CHANGELINK;
+ break;
+ case PHY_CHANGELINK:
+ err = phy_read_status(phydev);
+
+ if (err)
+ break;
+
+ if (phydev->link) {
+ phydev->state = PHY_RUNNING;
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ phydev->state = PHY_NOLINK;
+ netif_carrier_off(phydev->attached_dev);
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+
+ if (PHY_POLL != phydev->irq)
+ err = phy_config_interrupt(phydev,
+ PHY_INTERRUPT_ENABLED);
+ break;
+ case PHY_HALTED:
+ if (phydev->link) {
+ phydev->link = 0;
+ netif_carrier_off(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ }
+ break;
+ case PHY_RESUMING:
+
+ err = phy_clear_interrupt(phydev);
+
+ if (err)
+ break;
+
+ err = phy_config_interrupt(phydev,
+ PHY_INTERRUPT_ENABLED);
+
+ if (err)
+ break;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ err = phy_aneg_done(phydev);
+ if (err < 0)
+ break;
+
+ /* err > 0 if AN is done.
+ * Otherwise, it's 0, and we're
+ * still waiting for AN */
+ if (err > 0) {
+ phydev->state = PHY_RUNNING;
+ } else {
+ phydev->state = PHY_AN;
+ phydev->link_timeout = PHY_AN_TIMEOUT;
+ }
+ } else
+ phydev->state = PHY_RUNNING;
+ break;
+ }
+
+ spin_unlock(&phydev->lock);
+
+ if (needs_aneg)
+ err = phy_start_aneg(phydev);
+
+ if (err < 0)
+ phy_error(phydev);
+
+ mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
+}
+
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
new file mode 100644
index 000000000000..6da1aa0706a1
--- /dev/null
+++ b/drivers/net/phy/phy_device.c
@@ -0,0 +1,693 @@
+/*
+ * drivers/net/phy/phy_device.c
+ *
+ * Framework for finding and configuring PHYs.
+ * Also contains generic PHY driver
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+static struct phy_driver genphy_driver;
+extern int mdio_bus_init(void);
+extern void mdio_bus_exit(void);
+
+/* get_phy_device
+ *
+ * description: Reads the ID registers of the PHY at addr on the
+ * bus, then allocates and returns the phy_device to
+ * represent it.
+ */
+struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
+{
+ int phy_reg;
+ u32 phy_id;
+ struct phy_device *dev = NULL;
+
+ /* Grab the bits from PHYIR1, and put them
+ * in the upper half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID1);
+
+ if (phy_reg < 0)
+ return ERR_PTR(phy_reg);
+
+ phy_id = (phy_reg & 0xffff) << 16;
+
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID2);
+
+ if (phy_reg < 0)
+ return ERR_PTR(phy_reg);
+
+ phy_id |= (phy_reg & 0xffff);
+
+ /* If the phy_id is all Fs, there is no device there */
+ if (0xffffffff == phy_id)
+ return NULL;
+
+ /* Otherwise, we allocate the device, and initialize the
+ * default values */
+ dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+
+ if (NULL == dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->speed = 0;
+ dev->duplex = -1;
+ dev->pause = dev->asym_pause = 0;
+ dev->link = 1;
+
+ dev->autoneg = AUTONEG_ENABLE;
+
+ dev->addr = addr;
+ dev->phy_id = phy_id;
+ dev->bus = bus;
+
+ dev->state = PHY_DOWN;
+
+ spin_lock_init(&dev->lock);
+
+ return dev;
+}
+
+/* phy_prepare_link:
+ *
+ * description: Tells the PHY infrastructure to handle the
+ * gory details on monitoring link status (whether through
+ * polling or an interrupt), and to call back to the
+ * connected device driver when the link status changes.
+ * If you want to monitor your own link state, don't call
+ * this function */
+void phy_prepare_link(struct phy_device *phydev,
+ void (*handler)(struct net_device *))
+{
+ phydev->adjust_link = handler;
+}
+
+/* phy_connect:
+ *
+ * description: Convenience function for connecting ethernet
+ * devices to PHY devices. The default behavior is for
+ * the PHY infrastructure to handle everything, and only notify
+ * the connected driver when the link status changes. If you
+ * don't want, or can't use the provided functionality, you may
+ * choose to call only the subset of functions which provide
+ * the desired functionality.
+ */
+struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+ void (*handler)(struct net_device *), u32 flags)
+{
+ struct phy_device *phydev;
+
+ phydev = phy_attach(dev, phy_id, flags);
+
+ if (IS_ERR(phydev))
+ return phydev;
+
+ phy_prepare_link(phydev, handler);
+
+ phy_start_machine(phydev, NULL);
+
+ if (phydev->irq > 0)
+ phy_start_interrupts(phydev);
+
+ return phydev;
+}
+EXPORT_SYMBOL(phy_connect);
+
+void phy_disconnect(struct phy_device *phydev)
+{
+ if (phydev->irq > 0)
+ phy_stop_interrupts(phydev);
+
+ phy_stop_machine(phydev);
+
+ phydev->adjust_link = NULL;
+
+ phy_detach(phydev);
+}
+EXPORT_SYMBOL(phy_disconnect);
+
+/* phy_attach:
+ *
+ * description: Called by drivers to attach to a particular PHY
+ * device. The phy_device is found, and properly hooked up
+ * to the phy_driver. If no driver is attached, then the
+ * genphy_driver is used. The phy_device is given a ptr to
+ * the attaching device, and given a callback for link status
+ * change. The phy_device is returned to the attaching
+ * driver.
+ */
+static int phy_compare_id(struct device *dev, void *data)
+{
+ return strcmp((char *)data, dev->bus_id) ? 0 : 1;
+}
+
+struct phy_device *phy_attach(struct net_device *dev,
+ const char *phy_id, u32 flags)
+{
+ struct bus_type *bus = &mdio_bus_type;
+ struct phy_device *phydev;
+ struct device *d;
+
+ /* Search the list of PHY devices on the mdio bus for the
+ * PHY with the requested name */
+ d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
+
+ if (d) {
+ phydev = to_phy_device(d);
+ } else {
+ printk(KERN_ERR "%s not found\n", phy_id);
+ return ERR_PTR(-ENODEV);
+ }
+
+ /* Assume that if there is no driver, that it doesn't
+ * exist, and we should use the genphy driver. */
+ if (NULL == d->driver) {
+ int err;
+ down_write(&d->bus->subsys.rwsem);
+ d->driver = &genphy_driver.driver;
+
+ err = d->driver->probe(d);
+
+ if (err < 0)
+ return ERR_PTR(err);
+
+ device_bind_driver(d);
+ up_write(&d->bus->subsys.rwsem);
+ }
+
+ if (phydev->attached_dev) {
+ printk(KERN_ERR "%s: %s already attached\n",
+ dev->name, phy_id);
+ return ERR_PTR(-EBUSY);
+ }
+
+ phydev->attached_dev = dev;
+
+ phydev->dev_flags = flags;
+
+ return phydev;
+}
+EXPORT_SYMBOL(phy_attach);
+
+void phy_detach(struct phy_device *phydev)
+{
+ phydev->attached_dev = NULL;
+
+ /* If the device had no specific driver before (i.e. - it
+ * was using the generic driver), we unbind the device
+ * from the generic driver so that there's a chance a
+ * real driver could be loaded */
+ if (phydev->dev.driver == &genphy_driver.driver) {
+ down_write(&phydev->dev.bus->subsys.rwsem);
+ device_release_driver(&phydev->dev);
+ up_write(&phydev->dev.bus->subsys.rwsem);
+ }
+}
+EXPORT_SYMBOL(phy_detach);
+
+
+/* Generic PHY support and helper functions */
+
+/* genphy_config_advert
+ *
+ * description: Writes MII_ADVERTISE with the appropriate values,
+ * after sanitizing the values to make sure we only advertise
+ * what is supported
+ */
+int genphy_config_advert(struct phy_device *phydev)
+{
+ u32 advertise;
+ int adv;
+ int err;
+
+ /* Only allow advertising what
+ * this PHY supports */
+ phydev->advertising &= phydev->supported;
+ advertise = phydev->advertising;
+
+ /* Setup standard advertisement */
+ adv = phy_read(phydev, MII_ADVERTISE);
+
+ if (adv < 0)
+ return adv;
+
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
+
+ err = phy_write(phydev, MII_ADVERTISE, adv);
+
+ if (err < 0)
+ return err;
+
+ /* Configure gigabit if it's supported */
+ if (phydev->supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full)) {
+ adv = phy_read(phydev, MII_CTRL1000);
+
+ if (adv < 0)
+ return adv;
+
+ adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ if (advertise & SUPPORTED_1000baseT_Half)
+ adv |= ADVERTISE_1000HALF;
+ if (advertise & SUPPORTED_1000baseT_Full)
+ adv |= ADVERTISE_1000FULL;
+ err = phy_write(phydev, MII_CTRL1000, adv);
+
+ if (err < 0)
+ return err;
+ }
+
+ return adv;
+}
+EXPORT_SYMBOL(genphy_config_advert);
+
+/* genphy_setup_forced
+ *
+ * description: Configures MII_BMCR to force speed/duplex
+ * to the values in phydev. Assumes that the values are valid.
+ * Please see phy_sanitize_settings() */
+int genphy_setup_forced(struct phy_device *phydev)
+{
+ int ctl = BMCR_RESET;
+
+ phydev->pause = phydev->asym_pause = 0;
+
+ if (SPEED_1000 == phydev->speed)
+ ctl |= BMCR_SPEED1000;
+ else if (SPEED_100 == phydev->speed)
+ ctl |= BMCR_SPEED100;
+
+ if (DUPLEX_FULL == phydev->duplex)
+ ctl |= BMCR_FULLDPLX;
+
+ ctl = phy_write(phydev, MII_BMCR, ctl);
+
+ if (ctl < 0)
+ return ctl;
+
+ /* We just reset the device, so we'd better configure any
+ * settings the PHY requires to operate */
+ if (phydev->drv->config_init)
+ ctl = phydev->drv->config_init(phydev);
+
+ return ctl;
+}
+
+
+/* Enable and Restart Autonegotiation */
+int genphy_restart_aneg(struct phy_device *phydev)
+{
+ int ctl;
+
+ ctl = phy_read(phydev, MII_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+
+ /* Don't isolate the PHY if we're negotiating */
+ ctl &= ~(BMCR_ISOLATE);
+
+ ctl = phy_write(phydev, MII_BMCR, ctl);
+
+ return ctl;
+}
+
+
+/* genphy_config_aneg
+ *
+ * description: If auto-negotiation is enabled, we configure the
+ * advertising, and then restart auto-negotiation. If it is not
+ * enabled, then we write the BMCR
+ */
+int genphy_config_aneg(struct phy_device *phydev)
+{
+ int err = 0;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ err = genphy_config_advert(phydev);
+
+ if (err < 0)
+ return err;
+
+ err = genphy_restart_aneg(phydev);
+ } else
+ err = genphy_setup_forced(phydev);
+
+ return err;
+}
+EXPORT_SYMBOL(genphy_config_aneg);
+
+/* genphy_update_link
+ *
+ * description: Update the value in phydev->link to reflect the
+ * current link value. In order to do this, we need to read
+ * the status register twice, keeping the second value
+ */
+int genphy_update_link(struct phy_device *phydev)
+{
+ int status;
+
+ /* Do a fake read */
+ status = phy_read(phydev, MII_BMSR);
+
+ if (status < 0)
+ return status;
+
+ /* Read link and autonegotiation status */
+ status = phy_read(phydev, MII_BMSR);
+
+ if (status < 0)
+ return status;
+
+ if ((status & BMSR_LSTATUS) == 0)
+ phydev->link = 0;
+ else
+ phydev->link = 1;
+
+ return 0;
+}
+
+/* genphy_read_status
+ *
+ * description: Check the link, then figure out the current state
+ * by comparing what we advertise with what the link partner
+ * advertises. Start by checking the gigabit possibilities,
+ * then move on to 10/100.
+ */
+int genphy_read_status(struct phy_device *phydev)
+{
+ int adv;
+ int err;
+ int lpa;
+ int lpagb = 0;
+
+ /* Update the link, but return if there
+ * was an error */
+ err = genphy_update_link(phydev);
+ if (err)
+ return err;
+
+ if (AUTONEG_ENABLE == phydev->autoneg) {
+ if (phydev->supported & (SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full)) {
+ lpagb = phy_read(phydev, MII_STAT1000);
+
+ if (lpagb < 0)
+ return lpagb;
+
+ adv = phy_read(phydev, MII_CTRL1000);
+
+ if (adv < 0)
+ return adv;
+
+ lpagb &= adv << 2;
+ }
+
+ lpa = phy_read(phydev, MII_LPA);
+
+ if (lpa < 0)
+ return lpa;
+
+ adv = phy_read(phydev, MII_ADVERTISE);
+
+ if (adv < 0)
+ return adv;
+
+ lpa &= adv;
+
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+ phydev->pause = phydev->asym_pause = 0;
+
+ if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+ phydev->speed = SPEED_1000;
+
+ if (lpagb & LPA_1000FULL)
+ phydev->duplex = DUPLEX_FULL;
+ } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phydev->speed = SPEED_100;
+
+ if (lpa & LPA_100FULL)
+ phydev->duplex = DUPLEX_FULL;
+ } else
+ if (lpa & LPA_10FULL)
+ phydev->duplex = DUPLEX_FULL;
+
+ if (phydev->duplex == DUPLEX_FULL){
+ phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
+ phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
+ }
+ } else {
+ int bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
+ if (bmcr & BMCR_FULLDPLX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+ if (bmcr & BMCR_SPEED1000)
+ phydev->speed = SPEED_1000;
+ else if (bmcr & BMCR_SPEED100)
+ phydev->speed = SPEED_100;
+ else
+ phydev->speed = SPEED_10;
+
+ phydev->pause = phydev->asym_pause = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_read_status);
+
+static int genphy_config_init(struct phy_device *phydev)
+{
+ u32 val;
+ u32 features;
+
+ /* For now, I'll claim that the generic driver supports
+ * all possible port types */
+ features = (SUPPORTED_TP | SUPPORTED_MII
+ | SUPPORTED_AUI | SUPPORTED_FIBRE |
+ SUPPORTED_BNC);
+
+ /* Do we support autonegotiation? */
+ val = phy_read(phydev, MII_BMSR);
+
+ if (val < 0)
+ return val;
+
+ if (val & BMSR_ANEGCAPABLE)
+ features |= SUPPORTED_Autoneg;
+
+ if (val & BMSR_100FULL)
+ features |= SUPPORTED_100baseT_Full;
+ if (val & BMSR_100HALF)
+ features |= SUPPORTED_100baseT_Half;
+ if (val & BMSR_10FULL)
+ features |= SUPPORTED_10baseT_Full;
+ if (val & BMSR_10HALF)
+ features |= SUPPORTED_10baseT_Half;
+
+ if (val & BMSR_ESTATEN) {
+ val = phy_read(phydev, MII_ESTATUS);
+
+ if (val < 0)
+ return val;
+
+ if (val & ESTATUS_1000_TFULL)
+ features |= SUPPORTED_1000baseT_Full;
+ if (val & ESTATUS_1000_THALF)
+ features |= SUPPORTED_1000baseT_Half;
+ }
+
+ phydev->supported = features;
+ phydev->advertising = features;
+
+ return 0;
+}
+
+
+/* phy_probe
+ *
+ * description: Take care of setting up the phy_device structure,
+ * set the state to READY (the driver's init function should
+ * set it to STARTING if needed).
+ */
+static int phy_probe(struct device *dev)
+{
+ struct phy_device *phydev;
+ struct phy_driver *phydrv;
+ struct device_driver *drv;
+ int err = 0;
+
+ phydev = to_phy_device(dev);
+
+ /* Make sure the driver is held.
+ * XXX -- Is this correct? */
+ drv = get_driver(phydev->dev.driver);
+ phydrv = to_phy_driver(drv);
+ phydev->drv = phydrv;
+
+ /* Disable the interrupt if the PHY doesn't support it */
+ if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+ phydev->irq = PHY_POLL;
+
+ spin_lock(&phydev->lock);
+
+ /* Start out supporting everything. Eventually,
+ * a controller will attach, and may modify one
+ * or both of these values */
+ phydev->supported = phydrv->features;
+ phydev->advertising = phydrv->features;
+
+ /* Set the state to READY by default */
+ phydev->state = PHY_READY;
+
+ if (phydev->drv->probe)
+ err = phydev->drv->probe(phydev);
+
+ spin_unlock(&phydev->lock);
+
+ if (err < 0)
+ return err;
+
+ if (phydev->drv->config_init)
+ err = phydev->drv->config_init(phydev);
+
+ return err;
+}
+
+static int phy_remove(struct device *dev)
+{
+ struct phy_device *phydev;
+
+ phydev = to_phy_device(dev);
+
+ spin_lock(&phydev->lock);
+ phydev->state = PHY_DOWN;
+ spin_unlock(&phydev->lock);
+
+ if (phydev->drv->remove)
+ phydev->drv->remove(phydev);
+
+ put_driver(dev->driver);
+ phydev->drv = NULL;
+
+ return 0;
+}
+
+int phy_driver_register(struct phy_driver *new_driver)
+{
+ int retval;
+
+ memset(&new_driver->driver, 0, sizeof(new_driver->driver));
+ new_driver->driver.name = new_driver->name;
+ new_driver->driver.bus = &mdio_bus_type;
+ new_driver->driver.probe = phy_probe;
+ new_driver->driver.remove = phy_remove;
+
+ retval = driver_register(&new_driver->driver);
+
+ if (retval) {
+ printk(KERN_ERR "%s: Error %d in registering driver\n",
+ new_driver->name, retval);
+
+ return retval;
+ }
+
+ pr_info("%s: Registered new driver\n", new_driver->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_driver_register);
+
+void phy_driver_unregister(struct phy_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(phy_driver_unregister);
+
+static struct phy_driver genphy_driver = {
+ .phy_id = 0xffffffff,
+ .phy_id_mask = 0xffffffff,
+ .name = "Generic PHY",
+ .config_init = genphy_config_init,
+ .features = 0,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = {.owner= THIS_MODULE, },
+};
+
+static int __init phy_init(void)
+{
+ int rc;
+
+ rc = mdio_bus_init();
+ if (rc)
+ return rc;
+
+ rc = phy_driver_register(&genphy_driver);
+ if (rc)
+ mdio_bus_exit();
+
+ return rc;
+}
+
+static void __exit phy_exit(void)
+{
+ phy_driver_unregister(&genphy_driver);
+ mdio_bus_exit();
+}
+
+subsys_initcall(phy_init);
+module_exit(phy_exit);
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
new file mode 100644
index 000000000000..d461ba457631
--- /dev/null
+++ b/drivers/net/phy/qsemi.c
@@ -0,0 +1,143 @@
+/*
+ * drivers/net/phy/qsemi.c
+ *
+ * Driver for Quality Semiconductor PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF */
+
+/* register definitions */
+
+#define MII_QS6612_MCR 17 /* Mode Control Register */
+#define MII_QS6612_FTR 27 /* Factory Test Register */
+#define MII_QS6612_MCO 28 /* Misc. Control Register */
+#define MII_QS6612_ISR 29 /* Interrupt Source Register */
+#define MII_QS6612_IMR 30 /* Interrupt Mask Register */
+#define MII_QS6612_IMR_INIT 0x003a
+#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */
+
+#define QS6612_PCR_AN_COMPLETE 0x1000
+#define QS6612_PCR_RLBEN 0x0200
+#define QS6612_PCR_DCREN 0x0100
+#define QS6612_PCR_4B5BEN 0x0040
+#define QS6612_PCR_TX_ISOLATE 0x0020
+#define QS6612_PCR_MLT3_DIS 0x0002
+#define QS6612_PCR_SCRM_DESCRM 0x0001
+
+MODULE_DESCRIPTION("Quality Semiconductor PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+/* Returns 0, unless there's a write error */
+static int qs6612_config_init(struct phy_device *phydev)
+{
+ /* The PHY powers up isolated on the RPX,
+ * so send a command to allow operation.
+ * XXX - My docs indicate this should be 0x0940
+ * ...or something. The current value sets three
+ * reserved bits, bit 11, which specifies it should be
+ * set to one, bit 10, which specifies it should be set
+ * to 0, and bit 7, which doesn't specify. However, my
+ * docs are preliminary, and I will leave it like this
+ * until someone more knowledgable corrects me or it.
+ * -- Andy Fleming
+ */
+ return phy_write(phydev, MII_QS6612_PCR, 0x0dc0);
+}
+
+static int qs6612_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, MII_QS6612_ISR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_BMSR);
+
+ if (err < 0)
+ return err;
+
+ err = phy_read(phydev, MII_EXPANSION);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int qs6612_config_intr(struct phy_device *phydev)
+{
+ int err;
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_QS6612_IMR,
+ MII_QS6612_IMR_INIT);
+ else
+ err = phy_write(phydev, MII_QS6612_IMR, 0);
+
+ return err;
+
+}
+
+static struct phy_driver qs6612_driver = {
+ .phy_id = 0x00181440,
+ .name = "QS6612",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = qs6612_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = qs6612_ack_interrupt,
+ .config_intr = qs6612_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init qs6612_init(void)
+{
+ return phy_driver_register(&qs6612_driver);
+}
+
+static void __exit qs6612_exit(void)
+{
+ phy_driver_unregister(&qs6612_driver);
+}
+
+module_init(qs6612_init);
+module_exit(qs6612_exit);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index a32668e88e09..d3c9958b00d0 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -863,7 +863,7 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+ class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
if (err)
@@ -1232,9 +1232,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
navail = 0; /* total # of usable channels (not deregistered) */
hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
i = 0;
- list = &ppp->channels;
- while ((list = list->next) != &ppp->channels) {
- pch = list_entry(list, struct channel, clist);
+ list_for_each_entry(pch, &ppp->channels, clist) {
navail += pch->avail = (pch->chan != NULL);
if (pch->avail) {
if (skb_queue_empty(&pch->file.xq) ||
@@ -1280,6 +1278,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
/* skip to the channel after the one we last used
and start at that one */
+ list = &ppp->channels;
for (i = 0; i < ppp->nxchan; ++i) {
list = list->next;
if (list == &ppp->channels) {
@@ -1657,7 +1656,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
skb->dev = ppp->dev;
skb->protocol = htons(npindex_to_ethertype[npi]);
skb->mac.raw = skb->data;
- skb->input_dev = ppp->dev;
netif_rx(skb);
ppp->dev->last_rx = jiffies;
}
@@ -1731,7 +1729,7 @@ static void
ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
u32 mask, seq;
- struct list_head *l;
+ struct channel *ch;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
@@ -1785,8 +1783,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
* The list of channels can't change because we have the receive
* side of the ppp unit locked.
*/
- for (l = ppp->channels.next; l != &ppp->channels; l = l->next) {
- struct channel *ch = list_entry(l, struct channel, clist);
+ list_for_each_entry(ch, &ppp->channels, clist) {
if (seq_before(ch->lastseq, seq))
seq = ch->lastseq;
}
@@ -2272,10 +2269,8 @@ static struct compressor_entry *
find_comp_entry(int proto)
{
struct compressor_entry *ce;
- struct list_head *list = &compressor_list;
- while ((list = list->next) != &compressor_list) {
- ce = list_entry(list, struct compressor_entry, list);
+ list_for_each_entry(ce, &compressor_list, list) {
if (ce->comp->compress_proto == proto)
return ce;
}
@@ -2541,20 +2536,15 @@ static struct channel *
ppp_find_channel(int unit)
{
struct channel *pch;
- struct list_head *list;
- list = &new_channels;
- while ((list = list->next) != &new_channels) {
- pch = list_entry(list, struct channel, list);
+ list_for_each_entry(pch, &new_channels, list) {
if (pch->file.index == unit) {
list_del(&pch->list);
list_add(&pch->list, &all_channels);
return pch;
}
}
- list = &all_channels;
- while ((list = list->next) != &all_channels) {
- pch = list_entry(list, struct channel, list);
+ list_for_each_entry(pch, &all_channels, list) {
if (pch->file.index == unit)
return pch;
}
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index ce1a9bf7b9a7..a842ecc60a34 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -377,7 +377,8 @@ abort_kfree:
***********************************************************************/
static int pppoe_rcv(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct pppoe_hdr *ph;
@@ -426,7 +427,8 @@ out:
***********************************************************************/
static int pppoe_disc_rcv(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct net_device *orig_dev)
{
struct pppoe_hdr *ph;
@@ -1068,7 +1070,7 @@ static int __init pppoe_proc_init(void)
{
struct proc_dir_entry *p;
- p = create_proc_entry("pppoe", S_IRUGO, proc_net);
+ p = create_proc_entry("net/pppoe", S_IRUGO, NULL);
if (!p)
return -ENOMEM;
@@ -1140,7 +1142,7 @@ static void __exit pppoe_exit(void)
dev_remove_pack(&pppoes_ptype);
dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
- remove_proc_entry("pppoe", proc_net);
+ remove_proc_entry("net/pppoe", NULL);
proto_unregister(&pppoe_sk_proto);
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index d5afe05cd826..159b56a56ef4 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -92,19 +92,18 @@ VERSION 2.2LK <2005/01/25>
#endif /* RTL8169_DEBUG */
#define R8169_MSG_DEFAULT \
- (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
- NETIF_MSG_IFDOWN)
+ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
#define TX_BUFFS_AVAIL(tp) \
(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
#ifdef CONFIG_R8169_NAPI
#define rtl8169_rx_skb netif_receive_skb
-#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx
+#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb
#define rtl8169_rx_quota(count, quota) min(count, quota)
#else
#define rtl8169_rx_skb netif_rx
-#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb
+#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx
#define rtl8169_rx_quota(count, quota) count
#endif
@@ -187,6 +186,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
{ PCI_DEVICE(0x16ec, 0x0116), },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, },
{0,},
};
@@ -1027,6 +1027,7 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1511,6 +1512,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Get MAC address. FIXME: read EEPROM */
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);
dev->open = rtl8169_open;
dev->hard_start_xmit = rtl8169_start_xmit;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644
index 000000000000..12cde0604580
--- /dev/null
+++ b/drivers/net/rionet.c
@@ -0,0 +1,574 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME "rionet"
+#define DRV_VERSION "0.2"
+#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL \
+ (NETIF_MSG_DRV | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR)
+
+#define RIONET_DOORBELL_JOIN 0x1000
+#define RIONET_DOORBELL_LEAVE 0x1001
+
+#define RIONET_MAILBOX 0
+
+#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+ struct rio_mport *mport;
+ struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+ struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+ struct net_device_stats stats;
+ int rx_slot;
+ int tx_slot;
+ int tx_cnt;
+ int ack_slot;
+ spinlock_t lock;
+ spinlock_t tx_lock;
+ u32 msg_enable;
+};
+
+struct rionet_peer {
+ struct list_head node;
+ struct rio_dev *rdev;
+ struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops) \
+ ((pef & RIO_PEF_INB_MBOX) && \
+ (pef & RIO_PEF_INB_DOORBELL) && \
+ (src_ops & RIO_SRC_OPS_DOORBELL) && \
+ (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+ is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+ return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+ int i;
+ int error = 0;
+ struct rionet_private *rnet = ndev->priv;
+ void *data;
+
+ i = rnet->rx_slot;
+
+ do {
+ if (!rnet->rx_skb[i])
+ continue;
+
+ if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+ break;
+
+ rnet->rx_skb[i]->data = data;
+ skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+ rnet->rx_skb[i]->dev = ndev;
+ rnet->rx_skb[i]->protocol =
+ eth_type_trans(rnet->rx_skb[i], ndev);
+ error = netif_rx(rnet->rx_skb[i]);
+
+ if (error == NET_RX_DROP) {
+ rnet->stats.rx_dropped++;
+ } else if (error == NET_RX_BAD) {
+ if (netif_msg_rx_err(rnet))
+ printk(KERN_WARNING "%s: bad rx packet\n",
+ DRV_NAME);
+ rnet->stats.rx_errors++;
+ } else {
+ rnet->stats.rx_packets++;
+ rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+ }
+
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+ return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+
+ i = rnet->rx_slot;
+ do {
+ rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+ if (!rnet->rx_skb[i])
+ break;
+
+ rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+ rnet->rx_skb[i]->data);
+ } while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+ rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+ struct rio_dev *rdev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+ rnet->tx_skb[rnet->tx_slot] = skb;
+
+ rnet->stats.tx_packets++;
+ rnet->stats.tx_bytes += skb->len;
+
+ if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+ netif_stop_queue(ndev);
+
+ ++rnet->tx_slot;
+ rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+
+ if (netif_msg_tx_queued(rnet))
+ printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+ (u32) skb, skb->len);
+
+ return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int i;
+ struct rionet_private *rnet = ndev->priv;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
+ u16 destid;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!spin_trylock(&rnet->tx_lock)) {
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
+
+ if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+ netif_stop_queue(ndev);
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+ printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+ ndev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (eth->h_dest[0] & 0x01) {
+ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+ if (rionet_active[i])
+ rionet_queue_tx_msg(skb, ndev,
+ rionet_active[i]);
+ } else if (RIONET_MAC_MATCH(eth->h_dest)) {
+ destid = RIONET_GET_DESTID(eth->h_dest);
+ if (rionet_active[destid])
+ rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+ }
+
+ spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+ return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
+ u16 info)
+{
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = ndev->priv;
+ struct rionet_peer *peer;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+ DRV_NAME, sid, tid, info);
+ if (info == RIONET_DOORBELL_JOIN) {
+ if (!rionet_active[sid]) {
+ list_for_each_entry(peer, &rionet_peers, node) {
+ if (peer->rdev->destid == sid)
+ rionet_active[sid] = peer->rdev;
+ }
+ rio_mport_send_doorbell(mport, sid,
+ RIONET_DOORBELL_JOIN);
+ }
+ } else if (info == RIONET_DOORBELL_LEAVE) {
+ rionet_active[sid] = NULL;
+ } else {
+ if (netif_msg_intr(rnet))
+ printk(KERN_WARNING "%s: unhandled doorbell\n",
+ DRV_NAME);
+ }
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+ int n;
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ spin_lock(&rnet->lock);
+ if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+ rionet_rx_fill(ndev, n);
+ spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = ndev->priv;
+
+ spin_lock(&rnet->lock);
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO
+ "%s: outbound message event, mbox %d slot %d\n",
+ DRV_NAME, mbox, slot);
+
+ while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+ /* dma unmap single */
+ dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+ rnet->tx_skb[rnet->ack_slot] = NULL;
+ ++rnet->ack_slot;
+ rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+ rnet->tx_cnt--;
+ }
+
+ if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+ netif_wake_queue(ndev);
+
+ spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+ int i, rc = 0;
+ struct rionet_peer *peer, *tmp;
+ u32 pwdcsr;
+ struct rionet_private *rnet = ndev->priv;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+ if ((rc = rio_request_inb_dbell(rnet->mport,
+ (void *)ndev,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE,
+ rionet_dbell_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_inb_mbox(rnet->mport,
+ (void *)ndev,
+ RIONET_MAILBOX,
+ RIONET_RX_RING_SIZE,
+ rionet_inb_msg_event)) < 0)
+ goto out;
+
+ if ((rc = rio_request_outb_mbox(rnet->mport,
+ (void *)ndev,
+ RIONET_MAILBOX,
+ RIONET_TX_RING_SIZE,
+ rionet_outb_msg_event)) < 0)
+ goto out;
+
+ /* Initialize inbound message ring */
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ rnet->rx_skb[i] = NULL;
+ rnet->rx_slot = 0;
+ rionet_rx_fill(ndev, 0);
+
+ rnet->tx_slot = 0;
+ rnet->tx_cnt = 0;
+ rnet->ack_slot = 0;
+
+ netif_carrier_on(ndev);
+ netif_start_queue(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+ RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE)))
+ {
+ printk(KERN_ERR "%s: error requesting doorbells\n",
+ DRV_NAME);
+ continue;
+ }
+
+ /*
+ * If device has initialized inbound doorbells,
+ * send a join message
+ */
+ rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+ if (pwdcsr & RIO_DOORBELL_AVAIL)
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+ }
+
+ out:
+ return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+ struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ struct rionet_peer *peer, *tmp;
+ int i;
+
+ if (netif_msg_ifup(rnet))
+ printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+ if (rnet->rx_skb[i])
+ kfree_skb(rnet->rx_skb[i]);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ if (rionet_active[peer->rdev->destid]) {
+ rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+ rionet_active[peer->rdev->destid] = NULL;
+ }
+ rio_release_outb_dbell(peer->rdev, peer->res);
+ }
+
+ rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+ RIONET_DOORBELL_LEAVE);
+ rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+ rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+ return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+ struct net_device *ndev = NULL;
+ struct rionet_peer *peer, *tmp;
+
+ unregister_netdev(ndev);
+ kfree(ndev);
+
+ list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+ list_del(&peer->node);
+ kfree(peer);
+ }
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "n/a");
+ strcpy(info->bus_info, rnet->mport->name);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct rionet_private *rnet = ndev->priv;
+
+ rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+ .get_drvinfo = rionet_get_drvinfo,
+ .get_msglevel = rionet_get_msglevel,
+ .set_msglevel = rionet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+ int rc = 0;
+ struct net_device *ndev = NULL;
+ struct rionet_private *rnet;
+ u16 device_id;
+
+ /* Allocate our net_device structure */
+ ndev = alloc_etherdev(sizeof(struct rionet_private));
+ if (ndev == NULL) {
+ printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+ DRV_NAME);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Set up private area */
+ rnet = (struct rionet_private *)ndev->priv;
+ rnet->mport = mport;
+
+ /* Set the default MAC address */
+ device_id = rio_local_get_device_id(mport);
+ ndev->dev_addr[0] = 0x00;
+ ndev->dev_addr[1] = 0x01;
+ ndev->dev_addr[2] = 0x00;
+ ndev->dev_addr[3] = 0x01;
+ ndev->dev_addr[4] = device_id >> 8;
+ ndev->dev_addr[5] = device_id & 0xff;
+
+ /* Fill in the driver function table */
+ ndev->open = &rionet_open;
+ ndev->hard_start_xmit = &rionet_start_xmit;
+ ndev->stop = &rionet_close;
+ ndev->get_stats = &rionet_stats;
+ ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+ ndev->features = NETIF_F_LLTX;
+ SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+ SET_MODULE_OWNER(ndev);
+
+ spin_lock_init(&rnet->lock);
+ spin_lock_init(&rnet->tx_lock);
+
+ rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+ rc = register_netdev(ndev);
+ if (rc != 0)
+ goto out;
+
+ printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ndev->name,
+ DRV_NAME,
+ DRV_DESC,
+ DRV_VERSION,
+ ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+ ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+ out:
+ return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+ int rc = -ENODEV;
+ u32 lpef, lsrc_ops, ldst_ops;
+ struct rionet_peer *peer;
+
+ /* If local device is not rionet capable, give up quickly */
+ if (!rionet_capable)
+ goto out;
+
+ /*
+ * First time through, make sure local device is rionet
+ * capable, setup netdev, and set flags so this is skipped
+ * on later probes
+ */
+ if (!rionet_check) {
+ rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+ rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+ &lsrc_ops);
+ rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+ &ldst_ops);
+ if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+ printk(KERN_ERR
+ "%s: local device is not network capable\n",
+ DRV_NAME);
+ rionet_check = 1;
+ rionet_capable = 0;
+ goto out;
+ }
+
+ rc = rionet_setup_netdev(rdev->net->hport);
+ rionet_check = 1;
+ }
+
+ /*
+ * If the remote device has mailbox/doorbell capabilities,
+ * add it to the peer list.
+ */
+ if (dev_rionet_capable(rdev)) {
+ if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ peer->rdev = rdev;
+ list_add_tail(&peer->node, &rionet_peers);
+ }
+
+ out:
+ return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+ {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+ .name = "rionet",
+ .id_table = rionet_id_table,
+ .probe = rionet_probe,
+ .remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+ return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+ rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 12a86f96d973..19c2df9c86fe 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1429,6 +1429,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rr_private *rrpriv = netdev_priv(dev);
struct rr_regs __iomem *regs = rrpriv->regs;
+ struct hippi_cb *hcb = (struct hippi_cb *) skb->cb;
struct ring_ctrl *txctrl;
unsigned long flags;
u32 index, len = skb->len;
@@ -1460,7 +1461,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
ifield = (u32 *)skb_push(skb, 8);
ifield[0] = 0;
- ifield[1] = skb->private.ifield;
+ ifield[1] = hcb->ifield;
/*
* We don't need the lock before we are actually going to start
@@ -1709,10 +1710,8 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
error = -EFAULT;
}
wf_out:
- if (oldimage)
- kfree(oldimage);
- if (image)
- kfree(image);
+ kfree(oldimage);
+ kfree(image);
return error;
case SIOCRRID:
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 7092ca6b277e..00179bc3437f 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -1,5 +1,5 @@
/************************************************************************
- * regs.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * regs.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -62,6 +62,7 @@ typedef struct _XENA_dev_config {
#define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6)
#define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7)
#define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8)
+#define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE vBIT(0x0F,8,8)
#define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8)
#define ADAPTER_STATUS_MC_DRAM_READY BIT(24)
#define ADAPTER_STATUS_MC_QUEUES_READY BIT(25)
@@ -77,21 +78,34 @@ typedef struct _XENA_dev_config {
#define ADAPTER_ECC_EN BIT(55)
u64 serr_source;
-#define SERR_SOURCE_PIC BIT(0)
-#define SERR_SOURCE_TXDMA BIT(1)
-#define SERR_SOURCE_RXDMA BIT(2)
+#define SERR_SOURCE_PIC BIT(0)
+#define SERR_SOURCE_TXDMA BIT(1)
+#define SERR_SOURCE_RXDMA BIT(2)
#define SERR_SOURCE_MAC BIT(3)
#define SERR_SOURCE_MC BIT(4)
#define SERR_SOURCE_XGXS BIT(5)
-#define SERR_SOURCE_ANY (SERR_SOURCE_PIC | \
- SERR_SOURCE_TXDMA | \
- SERR_SOURCE_RXDMA | \
- SERR_SOURCE_MAC | \
- SERR_SOURCE_MC | \
- SERR_SOURCE_XGXS)
-
-
- u8 unused_0[0x800 - 0x120];
+#define SERR_SOURCE_ANY (SERR_SOURCE_PIC | \
+ SERR_SOURCE_TXDMA | \
+ SERR_SOURCE_RXDMA | \
+ SERR_SOURCE_MAC | \
+ SERR_SOURCE_MC | \
+ SERR_SOURCE_XGXS)
+
+ u64 pci_mode;
+#define GET_PCI_MODE(val) ((val & vBIT(0xF, 0, 4)) >> 60)
+#define PCI_MODE_PCI_33 0
+#define PCI_MODE_PCI_66 0x1
+#define PCI_MODE_PCIX_M1_66 0x2
+#define PCI_MODE_PCIX_M1_100 0x3
+#define PCI_MODE_PCIX_M1_133 0x4
+#define PCI_MODE_PCIX_M2_66 0x5
+#define PCI_MODE_PCIX_M2_100 0x6
+#define PCI_MODE_PCIX_M2_133 0x7
+#define PCI_MODE_UNSUPPORTED BIT(0)
+#define PCI_MODE_32_BITS BIT(8)
+#define PCI_MODE_UNKNOWN_MODE BIT(9)
+
+ u8 unused_0[0x800 - 0x128];
/* PCI-X Controller registers */
u64 pic_int_status;
@@ -153,7 +167,11 @@ typedef struct _XENA_dev_config {
u8 unused4[0x08];
u64 gpio_int_reg;
+#define GPIO_INT_REG_LINK_DOWN BIT(1)
+#define GPIO_INT_REG_LINK_UP BIT(2)
u64 gpio_int_mask;
+#define GPIO_INT_MASK_LINK_DOWN BIT(1)
+#define GPIO_INT_MASK_LINK_UP BIT(2)
u64 gpio_alarms;
u8 unused5[0x38];
@@ -223,19 +241,16 @@ typedef struct _XENA_dev_config {
u64 xmsi_data;
u64 rx_mat;
+#define RX_MAT_SET(ring, msi) vBIT(msi, (8 * ring), 8)
u8 unused6[0x8];
- u64 tx_mat0_7;
- u64 tx_mat8_15;
- u64 tx_mat16_23;
- u64 tx_mat24_31;
- u64 tx_mat32_39;
- u64 tx_mat40_47;
- u64 tx_mat48_55;
- u64 tx_mat56_63;
+ u64 tx_mat0_n[0x8];
+#define TX_MAT_SET(fifo, msi) vBIT(msi, (8 * fifo), 8)
- u8 unused_1[0x10];
+ u8 unused_1[0x8];
+ u64 stat_byte_cnt;
+#define STAT_BC(n) vBIT(n,4,12)
/* Automated statistics collection */
u64 stat_cfg;
@@ -246,6 +261,7 @@ typedef struct _XENA_dev_config {
#define STAT_TRSF_PER(n) TBD
#define PER_SEC 0x208d5
#define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32)
+#define SET_UPDT_CLICKS(val) vBIT(val, 32, 32)
u64 stat_addr;
@@ -267,8 +283,15 @@ typedef struct _XENA_dev_config {
u64 gpio_control;
#define GPIO_CTRL_GPIO_0 BIT(8)
+ u64 misc_control;
+#define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3)
+
+ u8 unused7_1[0x240 - 0x208];
+
+ u64 wreq_split_mask;
+#define WREQ_SPLIT_MASK_SET_MASK(val) vBIT(val, 52, 12)
- u8 unused7[0x600];
+ u8 unused7_2[0x800 - 0x248];
/* TxDMA registers */
u64 txdma_int_status;
@@ -290,6 +313,7 @@ typedef struct _XENA_dev_config {
u64 pcc_err_reg;
#define PCC_FB_ECC_DB_ERR vBIT(0xFF, 16, 8)
+#define PCC_ENABLE_FOUR vBIT(0x0F,0,8)
u64 pcc_err_mask;
u64 pcc_err_alarm;
@@ -468,6 +492,7 @@ typedef struct _XENA_dev_config {
#define PRC_CTRL_NO_SNOOP (BIT(22)|BIT(23))
#define PRC_CTRL_NO_SNOOP_DESC BIT(22)
#define PRC_CTRL_NO_SNOOP_BUFF BIT(23)
+#define PRC_CTRL_BIMODAL_INTERRUPT BIT(37)
#define PRC_CTRL_RXD_BACKOFF_INTERVAL(val) vBIT(val,40,24)
u64 prc_alarm_action;
@@ -688,9 +713,16 @@ typedef struct _XENA_dev_config {
u64 mc_err_reg;
#define MC_ERR_REG_ECC_DB_ERR_L BIT(14)
#define MC_ERR_REG_ECC_DB_ERR_U BIT(15)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_0 BIT(18)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_1 BIT(20)
#define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22)
#define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23)
#define MC_ERR_REG_SM_ERR BIT(31)
+#define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\
+ BIT(6) | BIT(7) | BIT(17) | BIT(19))
+#define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\
+ BIT(13) | BIT(14) | BIT(15) |\
+ BIT(18) | BIT(20))
u64 mc_err_mask;
u64 mc_err_alarm;
@@ -736,7 +768,19 @@ typedef struct _XENA_dev_config {
u64 mc_rldram_test_d1;
u8 unused24[0x300 - 0x288];
u64 mc_rldram_test_d2;
- u8 unused25[0x700 - 0x308];
+
+ u8 unused24_1[0x360 - 0x308];
+ u64 mc_rldram_ctrl;
+#define MC_RLDRAM_ENABLE_ODT BIT(7)
+
+ u8 unused24_2[0x640 - 0x368];
+ u64 mc_rldram_ref_per_herc;
+#define MC_RLDRAM_SET_REF_PERIOD(val) vBIT(val, 0, 16)
+
+ u8 unused24_3[0x660 - 0x648];
+ u64 mc_rldram_mrs_herc;
+
+ u8 unused25[0x700 - 0x668];
u64 mc_debug_ctrl;
u8 unused26[0x3000 - 0x2f08];
@@ -770,6 +814,17 @@ typedef struct _XENA_dev_config {
u64 rxgxs_ber_0; /* CHANGED */
u64 rxgxs_ber_1; /* CHANGED */
+ u64 spi_control;
+#define SPI_CONTROL_KEY(key) vBIT(key,0,4)
+#define SPI_CONTROL_BYTECNT(cnt) vBIT(cnt,29,3)
+#define SPI_CONTROL_CMD(cmd) vBIT(cmd,32,8)
+#define SPI_CONTROL_ADDR(addr) vBIT(addr,40,24)
+#define SPI_CONTROL_SEL1 BIT(4)
+#define SPI_CONTROL_REQ BIT(7)
+#define SPI_CONTROL_NACK BIT(5)
+#define SPI_CONTROL_DONE BIT(6)
+ u64 spi_data;
+#define SPI_DATA_WRITE(data,len) vBIT(data,0,len)
} XENA_dev_config_t;
#define XENA_REG_SPACE sizeof(XENA_dev_config_t)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index ea638b162d3f..3f5e93aad5c7 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,5 +1,5 @@
/************************************************************************
- * s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -11,29 +11,28 @@
* See the file COPYING in this distribution for more information.
*
* Credits:
- * Jeff Garzik : For pointing out the improper error condition
- * check in the s2io_xmit routine and also some
- * issues in the Tx watch dog function. Also for
- * patiently answering all those innumerable
+ * Jeff Garzik : For pointing out the improper error condition
+ * check in the s2io_xmit routine and also some
+ * issues in the Tx watch dog function. Also for
+ * patiently answering all those innumerable
* questions regaring the 2.6 porting issues.
* Stephen Hemminger : Providing proper 2.6 porting mechanism for some
* macros available only in 2.6 Kernel.
- * Francois Romieu : For pointing out all code part that were
+ * Francois Romieu : For pointing out all code part that were
* deprecated and also styling related comments.
- * Grant Grundler : For helping me get rid of some Architecture
+ * Grant Grundler : For helping me get rid of some Architecture
* dependent code.
* Christopher Hellwig : Some more 2.6 specific issues in the driver.
- *
+ *
* The module loadable parameters that are supported by the driver and a brief
* explaination of all the variables.
- * rx_ring_num : This can be used to program the number of receive rings used
- * in the driver.
- * rx_ring_len: This defines the number of descriptors each ring can have. This
+ * rx_ring_num : This can be used to program the number of receive rings used
+ * in the driver.
+ * rx_ring_sz: This defines the number of descriptors each ring can have. This
* is also an array of size 8.
* tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
- * tx_fifo_len: This too is an array of 8. Each element defines the number of
+ * tx_fifo_len: This too is an array of 8. Each element defines the number of
* Tx descriptors that can be associated with each corresponding FIFO.
- * in PCI Configuration space.
************************************************************************/
#include <linux/config.h>
@@ -56,27 +55,41 @@
#include <linux/ethtool.h>
#include <linux/version.h>
#include <linux/workqueue.h>
+#include <linux/if_vlan.h>
-#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
/* local include */
#include "s2io.h"
#include "s2io-regs.h"
+#define DRV_VERSION "Version 2.0.9.1"
+
/* S2io Driver name & version. */
-static char s2io_driver_name[] = "s2io";
-static char s2io_driver_version[] = "Version 1.7.7.1";
+static char s2io_driver_name[] = "Neterion";
+static char s2io_driver_version[] = DRV_VERSION;
+
+static inline int RXD_IS_UP2DT(RxD_t *rxdp)
+{
+ int ret;
+
+ ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
+ (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
+
+ return ret;
+}
-/*
+/*
* Cards with following subsystem_id have a link state indication
* problem, 600B, 600C, 600D, 640B, 640C and 640D.
* macro below identifies these cards given the subsystem_id.
*/
-#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \
- (((subid >= 0x600B) && (subid <= 0x600D)) || \
- ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0
+#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
+ (dev_type == XFRAME_I_DEVICE) ? \
+ ((((subid >= 0x600B) && (subid <= 0x600D)) || \
+ ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
#define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
@@ -86,9 +99,12 @@ static char s2io_driver_version[] = "Version 1.7.7.1";
static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
{
int level = 0;
- if ((sp->pkt_cnt[ring] - rxb_size) > 16) {
+ mac_info_t *mac_control;
+
+ mac_control = &sp->mac_control;
+ if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
level = LOW;
- if ((sp->pkt_cnt[ring] - rxb_size) < MAX_RXDS_PER_BLOCK) {
+ if (rxb_size <= MAX_RXDS_PER_BLOCK) {
level = PANIC;
}
}
@@ -145,6 +161,9 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
{"rmac_pause_cnt"},
{"rmac_accepted_ip"},
{"rmac_err_tcp"},
+ {"\n DRIVER STATISTICS"},
+ {"single_bit_ecc_errs"},
+ {"double_bit_ecc_errs"},
};
#define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
@@ -153,8 +172,37 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
#define S2IO_TEST_LEN sizeof(s2io_gstrings) / ETH_GSTRING_LEN
#define S2IO_STRINGS_LEN S2IO_TEST_LEN * ETH_GSTRING_LEN
+#define S2IO_TIMER_CONF(timer, handle, arg, exp) \
+ init_timer(&timer); \
+ timer.function = handle; \
+ timer.data = (unsigned long) arg; \
+ mod_timer(&timer, (jiffies + exp)) \
+
+/* Add the vlan */
+static void s2io_vlan_rx_register(struct net_device *dev,
+ struct vlan_group *grp)
+{
+ nic_t *nic = dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nic->tx_lock, flags);
+ nic->vlgrp = grp;
+ spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
+
+/* Unregister the vlan */
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+{
+ nic_t *nic = dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nic->tx_lock, flags);
+ if (nic->vlgrp)
+ nic->vlgrp->vlan_devices[vid] = NULL;
+ spin_unlock_irqrestore(&nic->tx_lock, flags);
+}
-/*
+/*
* Constants to be programmed into the Xena's registers, to configure
* the XAUI.
*/
@@ -162,7 +210,28 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL
#define END_SIGN 0x0
-static u64 default_mdio_cfg[] = {
+static u64 herc_act_dtx_cfg[] = {
+ /* Set address */
+ 0x8000051536750000ULL, 0x80000515367500E0ULL,
+ /* Write data */
+ 0x8000051536750004ULL, 0x80000515367500E4ULL,
+ /* Set address */
+ 0x80010515003F0000ULL, 0x80010515003F00E0ULL,
+ /* Write data */
+ 0x80010515003F0004ULL, 0x80010515003F00E4ULL,
+ /* Set address */
+ 0x801205150D440000ULL, 0x801205150D4400E0ULL,
+ /* Write data */
+ 0x801205150D440004ULL, 0x801205150D4400E4ULL,
+ /* Set address */
+ 0x80020515F2100000ULL, 0x80020515F21000E0ULL,
+ /* Write data */
+ 0x80020515F2100004ULL, 0x80020515F21000E4ULL,
+ /* Done */
+ END_SIGN
+};
+
+static u64 xena_mdio_cfg[] = {
/* Reset PMA PLL */
0xC001010000000000ULL, 0xC0010100000000E0ULL,
0xC0010100008000E4ULL,
@@ -172,7 +241,7 @@ static u64 default_mdio_cfg[] = {
END_SIGN
};
-static u64 default_dtx_cfg[] = {
+static u64 xena_dtx_cfg[] = {
0x8000051500000000ULL, 0x80000515000000E0ULL,
0x80000515D93500E4ULL, 0x8001051500000000ULL,
0x80010515000000E0ULL, 0x80010515001E00E4ULL,
@@ -196,8 +265,7 @@ static u64 default_dtx_cfg[] = {
END_SIGN
};
-
-/*
+/*
* Constants for Fixing the MacAddress problem seen mostly on
* Alpha machines.
*/
@@ -226,20 +294,27 @@ static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
static unsigned int rx_ring_num = 1;
static unsigned int rx_ring_sz[MAX_RX_RINGS] =
{[0 ...(MAX_RX_RINGS - 1)] = 0 };
-static unsigned int Stats_refresh_time = 4;
+static unsigned int rts_frm_len[MAX_RX_RINGS] =
+ {[0 ...(MAX_RX_RINGS - 1)] = 0 };
+static unsigned int use_continuous_tx_intrs = 1;
static unsigned int rmac_pause_time = 65535;
static unsigned int mc_pause_threshold_q0q3 = 187;
static unsigned int mc_pause_threshold_q4q7 = 187;
static unsigned int shared_splits;
static unsigned int tmac_util_period = 5;
static unsigned int rmac_util_period = 5;
+static unsigned int bimodal = 0;
#ifndef CONFIG_S2IO_NAPI
static unsigned int indicate_max_pkts;
#endif
+/* Frequency of Rx desc syncs expressed as power of 2 */
+static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
-/*
+/*
* S2IO device table.
- * This table lists all the devices that this driver supports.
+ * This table lists all the devices that this driver supports.
*/
static struct pci_device_id s2io_tbl[] __devinitdata = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
@@ -247,9 +322,9 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
- PCI_ANY_ID, PCI_ANY_ID},
- {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
- PCI_ANY_ID, PCI_ANY_ID},
+ PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+ PCI_ANY_ID, PCI_ANY_ID},
{0,}
};
@@ -268,8 +343,8 @@ static struct pci_driver s2io_driver = {
/**
* init_shared_mem - Allocation and Initialization of Memory
* @nic: Device private variable.
- * Description: The function allocates all the memory areas shared
- * between the NIC and the driver. This includes Tx descriptors,
+ * Description: The function allocates all the memory areas shared
+ * between the NIC and the driver. This includes Tx descriptors,
* Rx descriptors and the statistics block.
*/
@@ -279,7 +354,7 @@ static int init_shared_mem(struct s2io_nic *nic)
void *tmp_v_addr, *tmp_v_addr_next;
dma_addr_t tmp_p_addr, tmp_p_addr_next;
RxD_block_t *pre_rxd_blk = NULL;
- int i, j, blk_cnt;
+ int i, j, blk_cnt, rx_sz, tx_sz;
int lst_size, lst_per_page;
struct net_device *dev = nic->dev;
#ifdef CONFIG_2BUFF_MODE
@@ -300,36 +375,41 @@ static int init_shared_mem(struct s2io_nic *nic)
size += config->tx_cfg[i].fifo_len;
}
if (size > MAX_AVAILABLE_TXDS) {
- DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ",
- dev->name);
- DBG_PRINT(ERR_DBG, "exceeds the maximum value ");
- DBG_PRINT(ERR_DBG, "that can be used\n");
+ DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
+ __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
return FAILURE;
}
lst_size = (sizeof(TxD_t) * config->max_txds);
+ tx_sz = lst_size * size;
lst_per_page = PAGE_SIZE / lst_size;
for (i = 0; i < config->tx_fifo_num; i++) {
int fifo_len = config->tx_cfg[i].fifo_len;
int list_holder_size = fifo_len * sizeof(list_info_hold_t);
- nic->list_info[i] = kmalloc(list_holder_size, GFP_KERNEL);
- if (!nic->list_info[i]) {
+ mac_control->fifos[i].list_info = kmalloc(list_holder_size,
+ GFP_KERNEL);
+ if (!mac_control->fifos[i].list_info) {
DBG_PRINT(ERR_DBG,
"Malloc failed for list_info\n");
return -ENOMEM;
}
- memset(nic->list_info[i], 0, list_holder_size);
+ memset(mac_control->fifos[i].list_info, 0, list_holder_size);
}
for (i = 0; i < config->tx_fifo_num; i++) {
int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
lst_per_page);
- mac_control->tx_curr_put_info[i].offset = 0;
- mac_control->tx_curr_put_info[i].fifo_len =
+ mac_control->fifos[i].tx_curr_put_info.offset = 0;
+ mac_control->fifos[i].tx_curr_put_info.fifo_len =
config->tx_cfg[i].fifo_len - 1;
- mac_control->tx_curr_get_info[i].offset = 0;
- mac_control->tx_curr_get_info[i].fifo_len =
+ mac_control->fifos[i].tx_curr_get_info.offset = 0;
+ mac_control->fifos[i].tx_curr_get_info.fifo_len =
config->tx_cfg[i].fifo_len - 1;
+ mac_control->fifos[i].fifo_no = i;
+ mac_control->fifos[i].nic = nic;
+ mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
+
for (j = 0; j < page_num; j++) {
int k = 0;
dma_addr_t tmp_p;
@@ -342,19 +422,38 @@ static int init_shared_mem(struct s2io_nic *nic)
DBG_PRINT(ERR_DBG, "failed for TxDL\n");
return -ENOMEM;
}
+ /* If we got a zero DMA address(can happen on
+ * certain platforms like PPC), reallocate.
+ * Store virtual address of page we don't want,
+ * to be freed later.
+ */
+ if (!tmp_p) {
+ mac_control->zerodma_virt_addr = tmp_v;
+ DBG_PRINT(INIT_DBG,
+ "%s: Zero DMA address for TxDL. ", dev->name);
+ DBG_PRINT(INIT_DBG,
+ "Virtual address %p\n", tmp_v);
+ tmp_v = pci_alloc_consistent(nic->pdev,
+ PAGE_SIZE, &tmp_p);
+ if (!tmp_v) {
+ DBG_PRINT(ERR_DBG,
+ "pci_alloc_consistent ");
+ DBG_PRINT(ERR_DBG, "failed for TxDL\n");
+ return -ENOMEM;
+ }
+ }
while (k < lst_per_page) {
int l = (j * lst_per_page) + k;
if (l == config->tx_cfg[i].fifo_len)
- goto end_txd_alloc;
- nic->list_info[i][l].list_virt_addr =
+ break;
+ mac_control->fifos[i].list_info[l].list_virt_addr =
tmp_v + (k * lst_size);
- nic->list_info[i][l].list_phy_addr =
+ mac_control->fifos[i].list_info[l].list_phy_addr =
tmp_p + (k * lst_size);
k++;
}
}
}
- end_txd_alloc:
/* Allocation and initialization of RXDs in Rings */
size = 0;
@@ -367,21 +466,26 @@ static int init_shared_mem(struct s2io_nic *nic)
return FAILURE;
}
size += config->rx_cfg[i].num_rxd;
- nic->block_count[i] =
+ mac_control->rings[i].block_count =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- nic->pkt_cnt[i] =
- config->rx_cfg[i].num_rxd - nic->block_count[i];
+ mac_control->rings[i].pkt_cnt =
+ config->rx_cfg[i].num_rxd - mac_control->rings[i].block_count;
}
+ size = (size * (sizeof(RxD_t)));
+ rx_sz = size;
for (i = 0; i < config->rx_ring_num; i++) {
- mac_control->rx_curr_get_info[i].block_index = 0;
- mac_control->rx_curr_get_info[i].offset = 0;
- mac_control->rx_curr_get_info[i].ring_len =
+ mac_control->rings[i].rx_curr_get_info.block_index = 0;
+ mac_control->rings[i].rx_curr_get_info.offset = 0;
+ mac_control->rings[i].rx_curr_get_info.ring_len =
config->rx_cfg[i].num_rxd - 1;
- mac_control->rx_curr_put_info[i].block_index = 0;
- mac_control->rx_curr_put_info[i].offset = 0;
- mac_control->rx_curr_put_info[i].ring_len =
+ mac_control->rings[i].rx_curr_put_info.block_index = 0;
+ mac_control->rings[i].rx_curr_put_info.offset = 0;
+ mac_control->rings[i].rx_curr_put_info.ring_len =
config->rx_cfg[i].num_rxd - 1;
+ mac_control->rings[i].nic = nic;
+ mac_control->rings[i].ring_no = i;
+
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
/* Allocating all the Rx blocks */
@@ -395,32 +499,36 @@ static int init_shared_mem(struct s2io_nic *nic)
&tmp_p_addr);
if (tmp_v_addr == NULL) {
/*
- * In case of failure, free_shared_mem()
- * is called, which should free any
- * memory that was alloced till the
+ * In case of failure, free_shared_mem()
+ * is called, which should free any
+ * memory that was alloced till the
* failure happened.
*/
- nic->rx_blocks[i][j].block_virt_addr =
+ mac_control->rings[i].rx_blocks[j].block_virt_addr =
tmp_v_addr;
return -ENOMEM;
}
memset(tmp_v_addr, 0, size);
- nic->rx_blocks[i][j].block_virt_addr = tmp_v_addr;
- nic->rx_blocks[i][j].block_dma_addr = tmp_p_addr;
+ mac_control->rings[i].rx_blocks[j].block_virt_addr =
+ tmp_v_addr;
+ mac_control->rings[i].rx_blocks[j].block_dma_addr =
+ tmp_p_addr;
}
/* Interlinking all Rx Blocks */
for (j = 0; j < blk_cnt; j++) {
- tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
+ tmp_v_addr =
+ mac_control->rings[i].rx_blocks[j].block_virt_addr;
tmp_v_addr_next =
- nic->rx_blocks[i][(j + 1) %
+ mac_control->rings[i].rx_blocks[(j + 1) %
blk_cnt].block_virt_addr;
- tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+ tmp_p_addr =
+ mac_control->rings[i].rx_blocks[j].block_dma_addr;
tmp_p_addr_next =
- nic->rx_blocks[i][(j + 1) %
+ mac_control->rings[i].rx_blocks[(j + 1) %
blk_cnt].block_dma_addr;
pre_rxd_blk = (RxD_block_t *) tmp_v_addr;
- pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
+ pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
* marker.
*/
#ifndef CONFIG_2BUFF_MODE
@@ -433,28 +541,28 @@ static int init_shared_mem(struct s2io_nic *nic)
}
#ifdef CONFIG_2BUFF_MODE
- /*
+ /*
* Allocation of Storages for buffer addresses in 2BUFF mode
* and the buffers as well.
*/
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
+ mac_control->rings[i].ba = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
GFP_KERNEL);
- if (!nic->ba[i])
+ if (!mac_control->rings[i].ba)
return -ENOMEM;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) *
+ mac_control->rings[i].ba[j] = kmalloc((sizeof(buffAdd_t) *
(MAX_RXDS_PER_BLOCK + 1)),
GFP_KERNEL);
- if (!nic->ba[i][j])
+ if (!mac_control->rings[i].ba[j])
return -ENOMEM;
while (k != MAX_RXDS_PER_BLOCK) {
- ba = &nic->ba[i][j][k];
+ ba = &mac_control->rings[i].ba[j][k];
- ba->ba_0_org = kmalloc
+ ba->ba_0_org = (void *) kmalloc
(BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
if (!ba->ba_0_org)
return -ENOMEM;
@@ -463,7 +571,7 @@ static int init_shared_mem(struct s2io_nic *nic)
tmp &= ~((unsigned long) ALIGN_SIZE);
ba->ba_0 = (void *) tmp;
- ba->ba_1_org = kmalloc
+ ba->ba_1_org = (void *) kmalloc
(BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
if (!ba->ba_1_org)
return -ENOMEM;
@@ -483,9 +591,9 @@ static int init_shared_mem(struct s2io_nic *nic)
(nic->pdev, size, &mac_control->stats_mem_phy);
if (!mac_control->stats_mem) {
- /*
- * In case of failure, free_shared_mem() is called, which
- * should free any memory that was alloced till the
+ /*
+ * In case of failure, free_shared_mem() is called, which
+ * should free any memory that was alloced till the
* failure happened.
*/
return -ENOMEM;
@@ -495,15 +603,14 @@ static int init_shared_mem(struct s2io_nic *nic)
tmp_v_addr = mac_control->stats_mem;
mac_control->stats_info = (StatInfo_t *) tmp_v_addr;
memset(tmp_v_addr, 0, size);
-
DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,
(unsigned long long) tmp_p_addr);
return SUCCESS;
}
-/**
- * free_shared_mem - Free the allocated Memory
+/**
+ * free_shared_mem - Free the allocated Memory
* @nic: Device private variable.
* Description: This function is to free all memory locations allocated by
* the init_shared_mem() function and return it to the kernel.
@@ -517,7 +624,7 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_info_t *mac_control;
struct config_param *config;
int lst_size, lst_per_page;
-
+ struct net_device *dev = nic->dev;
if (!nic)
return;
@@ -533,15 +640,33 @@ static void free_shared_mem(struct s2io_nic *nic)
lst_per_page);
for (j = 0; j < page_num; j++) {
int mem_blks = (j * lst_per_page);
- if (!nic->list_info[i][mem_blks].list_virt_addr)
+ if (!mac_control->fifos[i].list_info)
+ return;
+ if (!mac_control->fifos[i].list_info[mem_blks].
+ list_virt_addr)
break;
pci_free_consistent(nic->pdev, PAGE_SIZE,
- nic->list_info[i][mem_blks].
+ mac_control->fifos[i].
+ list_info[mem_blks].
list_virt_addr,
- nic->list_info[i][mem_blks].
+ mac_control->fifos[i].
+ list_info[mem_blks].
list_phy_addr);
}
- kfree(nic->list_info[i]);
+ /* If we got a zero DMA address during allocation,
+ * free the page now
+ */
+ if (mac_control->zerodma_virt_addr) {
+ pci_free_consistent(nic->pdev, PAGE_SIZE,
+ mac_control->zerodma_virt_addr,
+ (dma_addr_t)0);
+ DBG_PRINT(INIT_DBG,
+ "%s: Freeing TxDL with zero DMA addr. ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+ mac_control->zerodma_virt_addr);
+ }
+ kfree(mac_control->fifos[i].list_info);
}
#ifndef CONFIG_2BUFF_MODE
@@ -550,10 +675,12 @@ static void free_shared_mem(struct s2io_nic *nic)
size = SIZE_OF_BLOCK;
#endif
for (i = 0; i < config->rx_ring_num; i++) {
- blk_cnt = nic->block_count[i];
+ blk_cnt = mac_control->rings[i].block_count;
for (j = 0; j < blk_cnt; j++) {
- tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr;
- tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;
+ tmp_v_addr = mac_control->rings[i].rx_blocks[j].
+ block_virt_addr;
+ tmp_p_addr = mac_control->rings[i].rx_blocks[j].
+ block_dma_addr;
if (tmp_v_addr == NULL)
break;
pci_free_consistent(nic->pdev, size,
@@ -566,35 +693,20 @@ static void free_shared_mem(struct s2io_nic *nic)
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
- if (!nic->ba[i])
- goto end_free;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- if (!nic->ba[i][j]) {
- kfree(nic->ba[i]);
- goto end_free;
- }
+ if (!mac_control->rings[i].ba[j])
+ continue;
while (k != MAX_RXDS_PER_BLOCK) {
- buffAdd_t *ba = &nic->ba[i][j][k];
- if (!ba || !ba->ba_0_org || !ba->ba_1_org)
- {
- kfree(nic->ba[i]);
- kfree(nic->ba[i][j]);
- if(ba->ba_0_org)
- kfree(ba->ba_0_org);
- if(ba->ba_1_org)
- kfree(ba->ba_1_org);
- goto end_free;
- }
+ buffAdd_t *ba = &mac_control->rings[i].ba[j][k];
kfree(ba->ba_0_org);
kfree(ba->ba_1_org);
k++;
}
- kfree(nic->ba[i][j]);
+ kfree(mac_control->rings[i].ba[j]);
}
- kfree(nic->ba[i]);
+ kfree(mac_control->rings[i].ba);
}
-end_free:
#endif
if (mac_control->stats_mem) {
@@ -605,12 +717,93 @@ end_free:
}
}
-/**
- * init_nic - Initialization of hardware
+/**
+ * s2io_verify_pci_mode -
+ */
+
+static int s2io_verify_pci_mode(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ register u64 val64 = 0;
+ int mode;
+
+ val64 = readq(&bar0->pci_mode);
+ mode = (u8)GET_PCI_MODE(val64);
+
+ if ( val64 & PCI_MODE_UNKNOWN_MODE)
+ return -1; /* Unknown PCI mode */
+ return mode;
+}
+
+
+/**
+ * s2io_print_pci_mode -
+ */
+static int s2io_print_pci_mode(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ register u64 val64 = 0;
+ int mode;
+ struct config_param *config = &nic->config;
+
+ val64 = readq(&bar0->pci_mode);
+ mode = (u8)GET_PCI_MODE(val64);
+
+ if ( val64 & PCI_MODE_UNKNOWN_MODE)
+ return -1; /* Unknown PCI mode */
+
+ if (val64 & PCI_MODE_32_BITS) {
+ DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
+ } else {
+ DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
+ }
+
+ switch(mode) {
+ case PCI_MODE_PCI_33:
+ DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
+ config->bus_speed = 33;
+ break;
+ case PCI_MODE_PCI_66:
+ DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
+ config->bus_speed = 133;
+ break;
+ case PCI_MODE_PCIX_M1_66:
+ DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
+ config->bus_speed = 133; /* Herc doubles the clock rate */
+ break;
+ case PCI_MODE_PCIX_M1_100:
+ DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
+ config->bus_speed = 200;
+ break;
+ case PCI_MODE_PCIX_M1_133:
+ DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
+ config->bus_speed = 266;
+ break;
+ case PCI_MODE_PCIX_M2_66:
+ DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
+ config->bus_speed = 133;
+ break;
+ case PCI_MODE_PCIX_M2_100:
+ DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
+ config->bus_speed = 200;
+ break;
+ case PCI_MODE_PCIX_M2_133:
+ DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
+ config->bus_speed = 266;
+ break;
+ default:
+ return -1; /* Unsupported bus speed */
+ }
+
+ return mode;
+}
+
+/**
+ * init_nic - Initialization of hardware
* @nic: device peivate variable
- * Description: The function sequentially configures every block
- * of the H/W from their reset values.
- * Return Value: SUCCESS on success and
+ * Description: The function sequentially configures every block
+ * of the H/W from their reset values.
+ * Return Value: SUCCESS on success and
* '-1' on failure (endian settings incorrect).
*/
@@ -626,21 +819,32 @@ static int init_nic(struct s2io_nic *nic)
struct config_param *config;
int mdio_cnt = 0, dtx_cnt = 0;
unsigned long long mem_share;
+ int mem_size;
mac_control = &nic->mac_control;
config = &nic->config;
- /* Initialize swapper control register */
- if (s2io_set_swapper(nic)) {
+ /* to set the swapper controle on the card */
+ if(s2io_set_swapper(nic)) {
DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
return -1;
}
+ /*
+ * Herc requires EOI to be removed from reset before XGXS, so..
+ */
+ if (nic->device_type & XFRAME_II_DEVICE) {
+ val64 = 0xA500000000ULL;
+ writeq(val64, &bar0->sw_reset);
+ msleep(500);
+ val64 = readq(&bar0->sw_reset);
+ }
+
/* Remove XGXS from reset state */
val64 = 0;
writeq(val64, &bar0->sw_reset);
- val64 = readq(&bar0->sw_reset);
msleep(500);
+ val64 = readq(&bar0->sw_reset);
/* Enable Receiving broadcasts */
add = &bar0->mac_cfg;
@@ -660,48 +864,58 @@ static int init_nic(struct s2io_nic *nic)
val64 = dev->mtu;
writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
- /*
- * Configuring the XAUI Interface of Xena.
+ /*
+ * Configuring the XAUI Interface of Xena.
* ***************************************
- * To Configure the Xena's XAUI, one has to write a series
- * of 64 bit values into two registers in a particular
- * sequence. Hence a macro 'SWITCH_SIGN' has been defined
- * which will be defined in the array of configuration values
- * (default_dtx_cfg & default_mdio_cfg) at appropriate places
- * to switch writing from one regsiter to another. We continue
+ * To Configure the Xena's XAUI, one has to write a series
+ * of 64 bit values into two registers in a particular
+ * sequence. Hence a macro 'SWITCH_SIGN' has been defined
+ * which will be defined in the array of configuration values
+ * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
+ * to switch writing from one regsiter to another. We continue
* writing these values until we encounter the 'END_SIGN' macro.
- * For example, After making a series of 21 writes into
- * dtx_control register the 'SWITCH_SIGN' appears and hence we
+ * For example, After making a series of 21 writes into
+ * dtx_control register the 'SWITCH_SIGN' appears and hence we
* start writing into mdio_control until we encounter END_SIGN.
*/
- while (1) {
- dtx_cfg:
- while (default_dtx_cfg[dtx_cnt] != END_SIGN) {
- if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
- dtx_cnt++;
- goto mdio_cfg;
- }
- SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt],
+ if (nic->device_type & XFRAME_II_DEVICE) {
+ while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
+ SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
&bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
+ if (dtx_cnt & 0x1)
+ msleep(1); /* Necessary!! */
dtx_cnt++;
}
- mdio_cfg:
- while (default_mdio_cfg[mdio_cnt] != END_SIGN) {
- if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+ } else {
+ while (1) {
+ dtx_cfg:
+ while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+ if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
+ dtx_cnt++;
+ goto mdio_cfg;
+ }
+ SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+ &bar0->dtx_control, UF);
+ val64 = readq(&bar0->dtx_control);
+ dtx_cnt++;
+ }
+ mdio_cfg:
+ while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
+ if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+ mdio_cnt++;
+ goto dtx_cfg;
+ }
+ SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
+ &bar0->mdio_control, UF);
+ val64 = readq(&bar0->mdio_control);
mdio_cnt++;
+ }
+ if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
+ (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
+ break;
+ } else {
goto dtx_cfg;
}
- SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt],
- &bar0->mdio_control, UF);
- val64 = readq(&bar0->mdio_control);
- mdio_cnt++;
- }
- if ((default_dtx_cfg[dtx_cnt] == END_SIGN) &&
- (default_mdio_cfg[mdio_cnt] == END_SIGN)) {
- break;
- } else {
- goto dtx_cfg;
}
}
@@ -748,12 +962,20 @@ static int init_nic(struct s2io_nic *nic)
val64 |= BIT(0); /* To enable the FIFO partition. */
writeq(val64, &bar0->tx_fifo_partition_0);
+ /*
+ * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
+ * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
+ */
+ if ((nic->device_type == XFRAME_I_DEVICE) &&
+ (get_xena_rev_id(nic->pdev) < 4))
+ writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
+
val64 = readq(&bar0->tx_fifo_partition_0);
DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
&bar0->tx_fifo_partition_0, (unsigned long long) val64);
- /*
- * Initialization of Tx_PA_CONFIG register to ignore packet
+ /*
+ * Initialization of Tx_PA_CONFIG register to ignore packet
* integrity checking.
*/
val64 = readq(&bar0->tx_pa_cfg);
@@ -770,85 +992,304 @@ static int init_nic(struct s2io_nic *nic)
}
writeq(val64, &bar0->rx_queue_priority);
- /*
- * Allocating equal share of memory to all the
+ /*
+ * Allocating equal share of memory to all the
* configured Rings.
*/
val64 = 0;
+ if (nic->device_type & XFRAME_II_DEVICE)
+ mem_size = 32;
+ else
+ mem_size = 64;
+
for (i = 0; i < config->rx_ring_num; i++) {
switch (i) {
case 0:
- mem_share = (64 / config->rx_ring_num +
- 64 % config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num +
+ mem_size % config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);
continue;
case 1:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);
continue;
case 2:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);
continue;
case 3:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);
continue;
case 4:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);
continue;
case 5:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);
continue;
case 6:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);
continue;
case 7:
- mem_share = (64 / config->rx_ring_num);
+ mem_share = (mem_size / config->rx_ring_num);
val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);
continue;
}
}
writeq(val64, &bar0->rx_queue_cfg);
- /*
- * Initializing the Tx round robin registers to 0.
- * Filling Tx and Rx round robin registers as per the
- * number of FIFOs and Rings is still TODO.
- */
- writeq(0, &bar0->tx_w_round_robin_0);
- writeq(0, &bar0->tx_w_round_robin_1);
- writeq(0, &bar0->tx_w_round_robin_2);
- writeq(0, &bar0->tx_w_round_robin_3);
- writeq(0, &bar0->tx_w_round_robin_4);
-
- /*
- * TODO
- * Disable Rx steering. Hard coding all packets be steered to
- * Queue 0 for now.
+ /*
+ * Filling Tx round robin registers
+ * as per the number of FIFOs
*/
- val64 = 0x8080808080808080ULL;
- writeq(val64, &bar0->rts_qos_steering);
+ switch (config->tx_fifo_num) {
+ case 1:
+ val64 = 0x0000000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 2:
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0100000100000100ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0001000001000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0100000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 3:
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0001020000010001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0200000100010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001020000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 4:
+ val64 = 0x0001020300010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0100000102030001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0200010000010203ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001020001000001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0203000100000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 5:
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001000000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 6:
+ val64 = 0x0001020304000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0304050001020001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0203000100000102ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304000102030405ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0001000200000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 7:
+ val64 = 0x0001020001020300ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0102030400010203ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0405060001020001ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304050000010200ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0102030000000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ case 8:
+ val64 = 0x0001020300040105ULL;
+ writeq(val64, &bar0->tx_w_round_robin_0);
+ val64 = 0x0200030106000204ULL;
+ writeq(val64, &bar0->tx_w_round_robin_1);
+ val64 = 0x0103000502010007ULL;
+ writeq(val64, &bar0->tx_w_round_robin_2);
+ val64 = 0x0304010002060500ULL;
+ writeq(val64, &bar0->tx_w_round_robin_3);
+ val64 = 0x0103020400000000ULL;
+ writeq(val64, &bar0->tx_w_round_robin_4);
+ break;
+ }
+
+ /* Filling the Rx round robin registers as per the
+ * number of Rings and steering based on QoS.
+ */
+ switch (config->rx_ring_num) {
+ case 1:
+ val64 = 0x8080808080808080ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 2:
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0100000100000100ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0001000001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0000010000010000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0100000000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080808040404040ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 3:
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0001020000010001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0200000100010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001000102000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001020000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080804040402020ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 4:
+ val64 = 0x0001020300010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0100000102030001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0200010000010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001020001000001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0203000100000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020201010ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 5:
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0001000203000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0001020001030004ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001000000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020201008ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 6:
+ val64 = 0x0001020304000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0304050001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0203000100000102ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304000102030405ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0001000200000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080404020100804ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 7:
+ val64 = 0x0001020001020300ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0102030400010203ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0405060001020001ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304050000010200ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0102030000000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8080402010080402ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ case 8:
+ val64 = 0x0001020300040105ULL;
+ writeq(val64, &bar0->rx_w_round_robin_0);
+ val64 = 0x0200030106000204ULL;
+ writeq(val64, &bar0->rx_w_round_robin_1);
+ val64 = 0x0103000502010007ULL;
+ writeq(val64, &bar0->rx_w_round_robin_2);
+ val64 = 0x0304010002060500ULL;
+ writeq(val64, &bar0->rx_w_round_robin_3);
+ val64 = 0x0103020400000000ULL;
+ writeq(val64, &bar0->rx_w_round_robin_4);
+
+ val64 = 0x8040201008040201ULL;
+ writeq(val64, &bar0->rts_qos_steering);
+ break;
+ }
/* UDP Fix */
val64 = 0;
- for (i = 1; i < 8; i++)
+ for (i = 0; i < 8; i++)
+ writeq(val64, &bar0->rts_frm_len_n[i]);
+
+ /* Set the default rts frame length for the rings configured */
+ val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22);
+ for (i = 0 ; i < config->rx_ring_num ; i++)
writeq(val64, &bar0->rts_frm_len_n[i]);
- /* Set rts_frm_len register for fifo 0 */
- writeq(MAC_RTS_FRM_LEN_SET(dev->mtu + 22),
- &bar0->rts_frm_len_n[0]);
+ /* Set the frame length for the configured rings
+ * desired by the user
+ */
+ for (i = 0; i < config->rx_ring_num; i++) {
+ /* If rts_frm_len[i] == 0 then it is assumed that user not
+ * specified frame length steering.
+ * If the user provides the frame length then program
+ * the rts_frm_len register for those values or else
+ * leave it as it is.
+ */
+ if (rts_frm_len[i] != 0) {
+ writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
+ &bar0->rts_frm_len_n[i]);
+ }
+ }
- /* Enable statistics */
+ /* Program statistics memory */
writeq(mac_control->stats_mem_phy, &bar0->stat_addr);
- val64 = SET_UPDT_PERIOD(Stats_refresh_time) |
- STAT_CFG_STAT_RO | STAT_CFG_STAT_EN;
- writeq(val64, &bar0->stat_cfg);
- /*
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = STAT_BC(0x320);
+ writeq(val64, &bar0->stat_byte_cnt);
+ }
+
+ /*
* Initializing the sampling rate for the device to calculate the
* bandwidth utilization.
*/
@@ -857,30 +1298,38 @@ static int init_nic(struct s2io_nic *nic)
writeq(val64, &bar0->mac_link_util);
- /*
- * Initializing the Transmit and Receive Traffic Interrupt
+ /*
+ * Initializing the Transmit and Receive Traffic Interrupt
* Scheme.
*/
- /* TTI Initialization. Default Tx timer gets us about
+ /*
+ * TTI Initialization. Default Tx timer gets us about
* 250 interrupts per sec. Continuous interrupts are enabled
* by default.
*/
- val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
- TTI_DATA1_MEM_TX_URNG_A(0xA) |
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ int count = (nic->config.bus_speed * 125)/2;
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
+ } else {
+
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
+ }
+ val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
TTI_DATA1_MEM_TX_URNG_B(0x10) |
- TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
- TTI_DATA1_MEM_TX_TIMER_CI_EN;
+ TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
+ if (use_continuous_tx_intrs)
+ val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
TTI_DATA2_MEM_TX_UFC_B(0x20) |
- TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
+ TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80);
writeq(val64, &bar0->tti_data2_mem);
val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
writeq(val64, &bar0->tti_command_mem);
- /*
+ /*
* Once the operation completes, the Strobe bit of the command
* register will be reset. We poll for this particular condition
* We wait for a maximum of 500ms for the operation to complete,
@@ -901,45 +1350,95 @@ static int init_nic(struct s2io_nic *nic)
time++;
}
- /* RTI Initialization */
- val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) |
- RTI_DATA1_MEM_RX_URNG_A(0xA) |
- RTI_DATA1_MEM_RX_URNG_B(0x10) |
- RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
-
- writeq(val64, &bar0->rti_data1_mem);
+ if (nic->config.bimodal) {
+ int k = 0;
+ for (k = 0; k < config->rx_ring_num; k++) {
+ val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
+ val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
+ writeq(val64, &bar0->tti_command_mem);
+
+ /*
+ * Once the operation completes, the Strobe bit of the command
+ * register will be reset. We poll for this particular condition
+ * We wait for a maximum of 500ms for the operation to complete,
+ * if it's not complete by then we return error.
+ */
+ time = 0;
+ while (TRUE) {
+ val64 = readq(&bar0->tti_command_mem);
+ if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
+ break;
+ }
+ if (time > 10) {
+ DBG_PRINT(ERR_DBG,
+ "%s: TTI init Failed\n",
+ dev->name);
+ return -1;
+ }
+ time++;
+ msleep(50);
+ }
+ }
+ } else {
- val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
- RTI_DATA2_MEM_RX_UFC_B(0x2) |
- RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
- writeq(val64, &bar0->rti_data2_mem);
+ /* RTI Initialization */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ /*
+ * Programmed to generate Apprx 500 Intrs per
+ * second
+ */
+ int count = (nic->config.bus_speed * 125)/4;
+ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+ } else {
+ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
+ }
+ val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+ RTI_DATA1_MEM_RX_URNG_B(0x10) |
+ RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+
+ writeq(val64, &bar0->rti_data1_mem);
+
+ val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+ RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+ if (nic->intr_type == MSI_X)
+ val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+ RTI_DATA2_MEM_RX_UFC_D(0x40));
+ else
+ val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+ RTI_DATA2_MEM_RX_UFC_D(0x80));
+ writeq(val64, &bar0->rti_data2_mem);
- val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD;
- writeq(val64, &bar0->rti_command_mem);
+ for (i = 0; i < config->rx_ring_num; i++) {
+ val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
+ | RTI_CMD_MEM_OFFSET(i);
+ writeq(val64, &bar0->rti_command_mem);
- /*
- * Once the operation completes, the Strobe bit of the command
- * register will be reset. We poll for this particular condition
- * We wait for a maximum of 500ms for the operation to complete,
- * if it's not complete by then we return error.
- */
- time = 0;
- while (TRUE) {
- val64 = readq(&bar0->rti_command_mem);
- if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
- break;
- }
- if (time > 10) {
- DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
- dev->name);
- return -1;
+ /*
+ * Once the operation completes, the Strobe bit of the
+ * command register will be reset. We poll for this
+ * particular condition. We wait for a maximum of 500ms
+ * for the operation to complete, if it's not complete
+ * by then we return error.
+ */
+ time = 0;
+ while (TRUE) {
+ val64 = readq(&bar0->rti_command_mem);
+ if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
+ break;
+ }
+ if (time > 10) {
+ DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
+ dev->name);
+ return -1;
+ }
+ time++;
+ msleep(50);
+ }
}
- time++;
- msleep(50);
}
- /*
- * Initializing proper values as Pause threshold into all
+ /*
+ * Initializing proper values as Pause threshold into all
* the 8 Queues on Rx side.
*/
writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);
@@ -955,8 +1454,8 @@ static int init_nic(struct s2io_nic *nic)
writel((u32) (val64 >> 32), (add + 4));
val64 = readq(&bar0->mac_cfg);
- /*
- * Set the time value to be inserted in the pause frame
+ /*
+ * Set the time value to be inserted in the pause frame
* generated by xena.
*/
val64 = readq(&bar0->rmac_pause_cfg);
@@ -964,7 +1463,7 @@ static int init_nic(struct s2io_nic *nic)
val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);
writeq(val64, &bar0->rmac_pause_cfg);
- /*
+ /*
* Set the Threshold Limit for Generating the pause frame
* If the amount of data in any Queue exceeds ratio of
* (mac_control.mc_pause_threshold_q0q3 or q4q7)/256
@@ -988,25 +1487,52 @@ static int init_nic(struct s2io_nic *nic)
}
writeq(val64, &bar0->mc_pause_thresh_q4q7);
- /*
- * TxDMA will stop Read request if the number of read split has
+ /*
+ * TxDMA will stop Read request if the number of read split has
* exceeded the limit pointed by shared_splits
*/
val64 = readq(&bar0->pic_control);
val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
writeq(val64, &bar0->pic_control);
+ /*
+ * Programming the Herc to split every write transaction
+ * that does not start on an ADB to reduce disconnects.
+ */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = WREQ_SPLIT_MASK_SET_MASK(255);
+ writeq(val64, &bar0->wreq_split_mask);
+ }
+
+ /* Setting Link stability period to 64 ms */
+ if (nic->device_type == XFRAME_II_DEVICE) {
+ val64 = MISC_LINK_STABILITY_PRD(3);
+ writeq(val64, &bar0->misc_control);
+ }
+
return SUCCESS;
}
+#define LINK_UP_DOWN_INTERRUPT 1
+#define MAC_RMAC_ERR_TIMER 2
+
+int s2io_link_fault_indication(nic_t *nic)
+{
+ if (nic->intr_type != INTA)
+ return MAC_RMAC_ERR_TIMER;
+ if (nic->device_type == XFRAME_II_DEVICE)
+ return LINK_UP_DOWN_INTERRUPT;
+ else
+ return MAC_RMAC_ERR_TIMER;
+}
-/**
- * en_dis_able_nic_intrs - Enable or Disable the interrupts
+/**
+ * en_dis_able_nic_intrs - Enable or Disable the interrupts
* @nic: device private variable,
* @mask: A mask indicating which Intr block must be modified and,
* @flag: A flag indicating whether to enable or disable the Intrs.
* Description: This function will either disable or enable the interrupts
- * depending on the flag argument. The mask argument can be used to
- * enable/disable any Intr block.
+ * depending on the flag argument. The mask argument can be used to
+ * enable/disable any Intr block.
* Return Value: NONE.
*/
@@ -1024,20 +1550,31 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * Disabled all PCIX, Flash, MDIO, IIC and GPIO
- * interrupts for now.
- * TODO
+ /*
+ * If Hercules adapter enable GPIO otherwise
+ * disabled all PCIX, Flash, MDIO, IIC and GPIO
+ * interrupts for now.
+ * TODO
*/
- writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
- /*
+ if (s2io_link_fault_indication(nic) ==
+ LINK_UP_DOWN_INTERRUPT ) {
+ temp64 = readq(&bar0->pic_int_mask);
+ temp64 &= ~((u64) PIC_INT_GPIO);
+ writeq(temp64, &bar0->pic_int_mask);
+ temp64 = readq(&bar0->gpio_int_mask);
+ temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
+ writeq(temp64, &bar0->gpio_int_mask);
+ } else {
+ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
+ }
+ /*
* No MSI Support is available presently, so TTI and
* RTI interrupts are also disabled.
*/
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable PIC Intrs in the general
- * intr mask register
+ /*
+ * Disable PIC Intrs in the general
+ * intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1055,27 +1592,27 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * Keep all interrupts other than PFC interrupt
+ /*
+ * Keep all interrupts other than PFC interrupt
* and PCC interrupt disabled in DMA level.
*/
val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M |
TXDMA_PCC_INT_M);
writeq(val64, &bar0->txdma_int_mask);
- /*
- * Enable only the MISC error 1 interrupt in PFC block
+ /*
+ * Enable only the MISC error 1 interrupt in PFC block
*/
val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1);
writeq(val64, &bar0->pfc_err_mask);
- /*
- * Enable only the FB_ECC error interrupt in PCC block
+ /*
+ * Enable only the FB_ECC error interrupt in PCC block
*/
val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR);
writeq(val64, &bar0->pcc_err_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable TxDMA Intrs in the general intr mask
- * register
+ /*
+ * Disable TxDMA Intrs in the general intr mask
+ * register
*/
writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask);
writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask);
@@ -1093,15 +1630,15 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All RxDMA block interrupts are disabled for now
- * TODO
+ /*
+ * All RxDMA block interrupts are disabled for now
+ * TODO
*/
writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable RxDMA Intrs in the general intr mask
- * register
+ /*
+ * Disable RxDMA Intrs in the general intr mask
+ * register
*/
writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1118,22 +1655,13 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All MAC block error interrupts are disabled for now
- * except the link status change interrupt.
+ /*
+ * All MAC block error interrupts are disabled for now
* TODO
*/
- val64 = MAC_INT_STATUS_RMAC_INT;
- temp64 = readq(&bar0->mac_int_mask);
- temp64 &= ~((u64) val64);
- writeq(temp64, &bar0->mac_int_mask);
-
- val64 = readq(&bar0->mac_rmac_err_mask);
- val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT);
- writeq(val64, &bar0->mac_rmac_err_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable MAC Intrs in the general intr mask register
+ /*
+ * Disable MAC Intrs in the general intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
writeq(DISABLE_ALL_INTRS,
@@ -1152,14 +1680,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
+ /*
* All XGXS block error interrupts are disabled for now
- * TODO
+ * TODO
*/
writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable MC Intrs in the general intr mask register
+ /*
+ * Disable MC Intrs in the general intr mask register
*/
writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);
temp64 = readq(&bar0->general_int_mask);
@@ -1175,11 +1703,11 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
- * All MC block error interrupts are disabled for now
- * TODO
+ /*
+ * Enable all MC Intrs.
*/
- writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask);
+ writeq(0x0, &bar0->mc_int_mask);
+ writeq(0x0, &bar0->mc_err_mask);
} else if (flag == DISABLE_INTRS) {
/*
* Disable MC Intrs in the general intr mask register
@@ -1199,14 +1727,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
temp64 = readq(&bar0->general_int_mask);
temp64 &= ~((u64) val64);
writeq(temp64, &bar0->general_int_mask);
- /*
+ /*
* Enable all the Tx side interrupts
- * writing 0 Enables all 64 TX interrupt levels
+ * writing 0 Enables all 64 TX interrupt levels
*/
writeq(0x0, &bar0->tx_traffic_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable Tx Traffic Intrs in the general intr mask
+ /*
+ * Disable Tx Traffic Intrs in the general intr mask
* register.
*/
writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
@@ -1226,8 +1754,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
/* writing 0 Enables all 8 RX interrupt levels */
writeq(0x0, &bar0->rx_traffic_mask);
} else if (flag == DISABLE_INTRS) {
- /*
- * Disable Rx Traffic Intrs in the general intr mask
+ /*
+ * Disable Rx Traffic Intrs in the general intr mask
* register.
*/
writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
@@ -1238,24 +1766,66 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
}
}
-/**
- * verify_xena_quiescence - Checks whether the H/W is ready
+static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc)
+{
+ int ret = 0;
+
+ if (flag == FALSE) {
+ if ((!herc && (rev_id >= 4)) || herc) {
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+ ret = 1;
+ }
+ }else {
+ if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+ ret = 1;
+ }
+ }
+ } else {
+ if ((!herc && (rev_id >= 4)) || herc) {
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
+ ADAPTER_STATUS_RMAC_PCC_IDLE) &&
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+ ret = 1;
+ }
+ } else {
+ if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
+ ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) &&
+ (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
+ ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
+ ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
+ ret = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+/**
+ * verify_xena_quiescence - Checks whether the H/W is ready
* @val64 : Value read from adapter status register.
* @flag : indicates if the adapter enable bit was ever written once
* before.
* Description: Returns whether the H/W is ready to go or not. Depending
- * on whether adapter enable bit was written or not the comparison
+ * on whether adapter enable bit was written or not the comparison
* differs and the calling function passes the input argument flag to
* indicate this.
- * Return: 1 If xena is quiescence
+ * Return: 1 If xena is quiescence
* 0 If Xena is not quiescence
*/
-static int verify_xena_quiescence(u64 val64, int flag)
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
{
- int ret = 0;
+ int ret = 0, herc;
u64 tmp64 = ~((u64) val64);
+ int rev_id = get_xena_rev_id(sp->pdev);
+ herc = (sp->device_type == XFRAME_II_DEVICE);
if (!
(tmp64 &
(ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY |
@@ -1263,25 +1833,7 @@ static int verify_xena_quiescence(u64 val64, int flag)
ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |
ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |
ADAPTER_STATUS_P_PLL_LOCK))) {
- if (flag == FALSE) {
- if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) &&
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
- ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
-
- ret = 1;
-
- }
- } else {
- if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
- ADAPTER_STATUS_RMAC_PCC_IDLE) &&
- (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ||
- ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
- ADAPTER_STATUS_RC_PRC_QUIESCENT))) {
-
- ret = 1;
-
- }
- }
+ ret = check_prc_pcc_state(val64, flag, rev_id, herc);
}
return ret;
@@ -1290,12 +1842,12 @@ static int verify_xena_quiescence(u64 val64, int flag)
/**
* fix_mac_address - Fix for Mac addr problem on Alpha platforms
* @sp: Pointer to device specifc structure
- * Description :
+ * Description :
* New procedure to clear mac address reading problems on Alpha platforms
*
*/
-static void fix_mac_address(nic_t * sp)
+void fix_mac_address(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
@@ -1303,20 +1855,21 @@ static void fix_mac_address(nic_t * sp)
while (fix_mac[i] != END_SIGN) {
writeq(fix_mac[i++], &bar0->gpio_control);
+ udelay(10);
val64 = readq(&bar0->gpio_control);
}
}
/**
- * start_nic - Turns the device on
+ * start_nic - Turns the device on
* @nic : device private variable.
- * Description:
- * This function actually turns the device on. Before this function is
- * called,all Registers are configured from their reset states
- * and shared memory is allocated but the NIC is still quiescent. On
+ * Description:
+ * This function actually turns the device on. Before this function is
+ * called,all Registers are configured from their reset states
+ * and shared memory is allocated but the NIC is still quiescent. On
* calling this function, the device interrupts are cleared and the NIC is
* literally switched on by writing into the adapter control register.
- * Return Value:
+ * Return Value:
* SUCCESS on success and -1 on failure.
*/
@@ -1325,8 +1878,8 @@ static int start_nic(struct s2io_nic *nic)
XENA_dev_config_t __iomem *bar0 = nic->bar0;
struct net_device *dev = nic->dev;
register u64 val64 = 0;
- u16 interruptible, i;
- u16 subid;
+ u16 interruptible;
+ u16 subid, i;
mac_info_t *mac_control;
struct config_param *config;
@@ -1335,10 +1888,12 @@ static int start_nic(struct s2io_nic *nic)
/* PRC Initialization and configuration */
for (i = 0; i < config->rx_ring_num; i++) {
- writeq((u64) nic->rx_blocks[i][0].block_dma_addr,
+ writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,
&bar0->prc_rxd0_n[i]);
val64 = readq(&bar0->prc_ctrl_n[i]);
+ if (nic->config.bimodal)
+ val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
#ifndef CONFIG_2BUFF_MODE
val64 |= PRC_CTRL_RC_ENABLED;
#else
@@ -1354,7 +1909,7 @@ static int start_nic(struct s2io_nic *nic)
writeq(val64, &bar0->rx_pa_cfg);
#endif
- /*
+ /*
* Enabling MC-RLDRAM. After enabling the device, we timeout
* for around 100ms, which is approximately the time required
* for the device to be ready for operation.
@@ -1364,27 +1919,27 @@ static int start_nic(struct s2io_nic *nic)
SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
val64 = readq(&bar0->mc_rldram_mrs);
- msleep(100); /* Delay by around 100 ms. */
+ msleep(100); /* Delay by around 100 ms. */
/* Enabling ECC Protection. */
val64 = readq(&bar0->adapter_control);
val64 &= ~ADAPTER_ECC_EN;
writeq(val64, &bar0->adapter_control);
- /*
- * Clearing any possible Link state change interrupts that
+ /*
+ * Clearing any possible Link state change interrupts that
* could have popped up just before Enabling the card.
*/
val64 = readq(&bar0->mac_rmac_err_reg);
if (val64)
writeq(val64, &bar0->mac_rmac_err_reg);
- /*
- * Verify if the device is ready to be enabled, if so enable
+ /*
+ * Verify if the device is ready to be enabled, if so enable
* it.
*/
val64 = readq(&bar0->adapter_status);
- if (!verify_xena_quiescence(val64, nic->device_enabled_once)) {
+ if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
(unsigned long long) val64);
@@ -1392,16 +1947,21 @@ static int start_nic(struct s2io_nic *nic)
}
/* Enable select interrupts */
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
- RX_MAC_INTR;
- en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+ if (nic->intr_type != INTA)
+ en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+ else {
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+ en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+ }
- /*
+ /*
* With some switches, link might be already up at this point.
- * Because of this weird behavior, when we enable laser,
- * we may not get link. We need to handle this. We cannot
- * figure out which switch is misbehaving. So we are forced to
- * make a global change.
+ * Because of this weird behavior, when we enable laser,
+ * we may not get link. We need to handle this. We cannot
+ * figure out which switch is misbehaving. So we are forced to
+ * make a global change.
*/
/* Enabling Laser. */
@@ -1411,44 +1971,30 @@ static int start_nic(struct s2io_nic *nic)
/* SXE-002: Initialize link and activity LED */
subid = nic->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if (((subid & 0xFF) >= 0x07) &&
+ (nic->device_type == XFRAME_I_DEVICE)) {
val64 = readq(&bar0->gpio_control);
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) bar0 + 0x2700);
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
}
- /*
- * Don't see link state interrupts on certain switches, so
+ /*
+ * Don't see link state interrupts on certain switches, so
* directly scheduling a link state task from here.
*/
schedule_work(&nic->set_link_task);
- /*
- * Here we are performing soft reset on XGXS to
- * force link down. Since link is already up, we will get
- * link state change interrupt after this reset
- */
- SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
- SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
- SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF);
- val64 = readq(&bar0->dtx_control);
- udelay(50);
-
return SUCCESS;
}
-/**
- * free_tx_buffers - Free all queued Tx buffers
+/**
+ * free_tx_buffers - Free all queued Tx buffers
* @nic : device private variable.
- * Description:
+ * Description:
* Free all queued Tx buffers.
- * Return Value: void
+ * Return Value: void
*/
static void free_tx_buffers(struct s2io_nic *nic)
@@ -1459,39 +2005,61 @@ static void free_tx_buffers(struct s2io_nic *nic)
int i, j;
mac_info_t *mac_control;
struct config_param *config;
- int cnt = 0;
+ int cnt = 0, frg_cnt;
mac_control = &nic->mac_control;
config = &nic->config;
for (i = 0; i < config->tx_fifo_num; i++) {
for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
- txdp = (TxD_t *) nic->list_info[i][j].
+ txdp = (TxD_t *) mac_control->fifos[i].list_info[j].
list_virt_addr;
skb =
(struct sk_buff *) ((unsigned long) txdp->
Host_Control);
if (skb == NULL) {
- memset(txdp, 0, sizeof(TxD_t));
+ memset(txdp, 0, sizeof(TxD_t) *
+ config->max_txds);
continue;
}
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txdp->Buffer_Pointer,
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ if (frg_cnt) {
+ TxD_t *temp;
+ temp = txdp;
+ txdp++;
+ for (j = 0; j < frg_cnt; j++, txdp++) {
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[j];
+ pci_unmap_page(nic->pdev,
+ (dma_addr_t)
+ txdp->
+ Buffer_Pointer,
+ frag->size,
+ PCI_DMA_TODEVICE);
+ }
+ txdp = temp;
+ }
dev_kfree_skb(skb);
- memset(txdp, 0, sizeof(TxD_t));
+ memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
cnt++;
}
DBG_PRINT(INTR_DBG,
"%s:forcibly freeing %d skbs on FIFO%d\n",
dev->name, cnt, i);
- mac_control->tx_curr_get_info[i].offset = 0;
- mac_control->tx_curr_put_info[i].offset = 0;
+ mac_control->fifos[i].tx_curr_get_info.offset = 0;
+ mac_control->fifos[i].tx_curr_put_info.offset = 0;
}
}
-/**
- * stop_nic - To stop the nic
+/**
+ * stop_nic - To stop the nic
* @nic ; device private variable.
- * Description:
- * This function does exactly the opposite of what the start_nic()
+ * Description:
+ * This function does exactly the opposite of what the start_nic()
* function does. This function is called to stop the device.
* Return Value:
* void.
@@ -1509,8 +2077,9 @@ static void stop_nic(struct s2io_nic *nic)
config = &nic->config;
/* Disable all interrupts */
- interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
- RX_MAC_INTR;
+ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+ interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+ interruptible |= TX_MAC_INTR | RX_MAC_INTR;
en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
/* Disable PRCs */
@@ -1521,11 +2090,11 @@ static void stop_nic(struct s2io_nic *nic)
}
}
-/**
- * fill_rx_buffers - Allocates the Rx side skbs
+/**
+ * fill_rx_buffers - Allocates the Rx side skbs
* @nic: device private variable
- * @ring_no: ring number
- * Description:
+ * @ring_no: ring number
+ * Description:
* The function allocates Rx side skbs and puts the physical
* address of these buffers into the RxD buffer pointers, so that the NIC
* can DMA the received frame into these locations.
@@ -1533,8 +2102,8 @@ static void stop_nic(struct s2io_nic *nic)
* 1. single buffer,
* 2. three buffer and
* 3. Five buffer modes.
- * Each mode defines how many fragments the received frame will be split
- * up into by the NIC. The frame is split into L3 header, L4 Header,
+ * Each mode defines how many fragments the received frame will be split
+ * up into by the NIC. The frame is split into L3 header, L4 Header,
* L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself
* is split into 3 fragments. As of now only single buffer mode is
* supported.
@@ -1542,7 +2111,7 @@ static void stop_nic(struct s2io_nic *nic)
* SUCCESS on success or an appropriate -ve value on failure.
*/
-static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
{
struct net_device *dev = nic->dev;
struct sk_buff *skb;
@@ -1550,34 +2119,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
int off, off1, size, block_no, block_no1;
int offset, offset1;
u32 alloc_tab = 0;
- u32 alloc_cnt = nic->pkt_cnt[ring_no] -
- atomic_read(&nic->rx_bufs_left[ring_no]);
+ u32 alloc_cnt;
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
RxD_t *rxdpnext;
int nextblk;
- unsigned long tmp;
+ u64 tmp;
buffAdd_t *ba;
dma_addr_t rxdpphys;
#endif
#ifndef CONFIG_S2IO_NAPI
unsigned long flags;
#endif
+ RxD_t *first_rxdp = NULL;
mac_control = &nic->mac_control;
config = &nic->config;
-
+ alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
+ atomic_read(&nic->rx_bufs_left[ring_no]);
size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
while (alloc_tab < alloc_cnt) {
- block_no = mac_control->rx_curr_put_info[ring_no].
+ block_no = mac_control->rings[ring_no].rx_curr_put_info.
block_index;
- block_no1 = mac_control->rx_curr_get_info[ring_no].
+ block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
block_index;
- off = mac_control->rx_curr_put_info[ring_no].offset;
- off1 = mac_control->rx_curr_get_info[ring_no].offset;
+ off = mac_control->rings[ring_no].rx_curr_put_info.offset;
+ off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
#ifndef CONFIG_2BUFF_MODE
offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1;
@@ -1586,7 +2156,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;
#endif
- rxdp = nic->rx_blocks[ring_no][block_no].
+ rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr + off;
if ((offset == offset1) && (rxdp->Host_Control)) {
DBG_PRINT(INTR_DBG, "%s: Get and Put", dev->name);
@@ -1595,15 +2165,15 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
}
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
block_index++;
- mac_control->rx_curr_put_info[ring_no].
- block_index %= nic->block_count[ring_no];
- block_no = mac_control->rx_curr_put_info
- [ring_no].block_index;
+ mac_control->rings[ring_no].rx_curr_put_info.
+ block_index %= mac_control->rings[ring_no].block_count;
+ block_no = mac_control->rings[ring_no].rx_curr_put_info.
+ block_index;
off++;
off %= (MAX_RXDS_PER_BLOCK + 1);
- mac_control->rx_curr_put_info[ring_no].offset =
+ mac_control->rings[ring_no].rx_curr_put_info.offset =
off;
rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2);
DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
@@ -1611,30 +2181,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
- nic->put_pos[ring_no] =
+ mac_control->rings[ring_no].put_pos =
(block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
#else
if (rxdp->Host_Control == END_OF_BLOCK) {
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
block_index++;
- mac_control->rx_curr_put_info[ring_no].
- block_index %= nic->block_count[ring_no];
- block_no = mac_control->rx_curr_put_info
- [ring_no].block_index;
+ mac_control->rings[ring_no].rx_curr_put_info.block_index
+ %= mac_control->rings[ring_no].block_count;
+ block_no = mac_control->rings[ring_no].rx_curr_put_info
+ .block_index;
off = 0;
DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",
dev->name, block_no,
(unsigned long long) rxdp->Control_1);
- mac_control->rx_curr_put_info[ring_no].offset =
+ mac_control->rings[ring_no].rx_curr_put_info.offset =
off;
- rxdp = nic->rx_blocks[ring_no][block_no].
+ rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr;
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
- nic->put_pos[ring_no] = (block_no *
+ mac_control->rings[ring_no].put_pos = (block_no *
(MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
@@ -1646,27 +2216,27 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
if (rxdp->Control_2 & BIT(0))
#endif
{
- mac_control->rx_curr_put_info[ring_no].
+ mac_control->rings[ring_no].rx_curr_put_info.
offset = off;
goto end;
}
#ifdef CONFIG_2BUFF_MODE
- /*
- * RxDs Spanning cache lines will be replenished only
- * if the succeeding RxD is also owned by Host. It
- * will always be the ((8*i)+3) and ((8*i)+6)
- * descriptors for the 48 byte descriptor. The offending
+ /*
+ * RxDs Spanning cache lines will be replenished only
+ * if the succeeding RxD is also owned by Host. It
+ * will always be the ((8*i)+3) and ((8*i)+6)
+ * descriptors for the 48 byte descriptor. The offending
* decsriptor is of-course the 3rd descriptor.
*/
- rxdpphys = nic->rx_blocks[ring_no][block_no].
+ rxdpphys = mac_control->rings[ring_no].rx_blocks[block_no].
block_dma_addr + (off * sizeof(RxD_t));
if (((u64) (rxdpphys)) % 128 > 80) {
- rxdpnext = nic->rx_blocks[ring_no][block_no].
+ rxdpnext = mac_control->rings[ring_no].rx_blocks[block_no].
block_virt_addr + (off + 1);
if (rxdpnext->Host_Control == END_OF_BLOCK) {
nextblk = (block_no + 1) %
- (nic->block_count[ring_no]);
- rxdpnext = nic->rx_blocks[ring_no]
+ (mac_control->rings[ring_no].block_count);
+ rxdpnext = mac_control->rings[ring_no].rx_blocks
[nextblk].block_virt_addr;
}
if (rxdpnext->Control_2 & BIT(0))
@@ -1682,6 +2252,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
if (!skb) {
DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
return -ENOMEM;
}
#ifndef CONFIG_2BUFF_MODE
@@ -1692,12 +2266,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);
rxdp->Control_2 |= SET_BUFFER0_SIZE(size);
rxdp->Host_Control = (unsigned long) (skb);
- rxdp->Control_1 |= RXD_OWN_XENA;
+ if (alloc_tab & ((1 << rxsync_frequency) - 1))
+ rxdp->Control_1 |= RXD_OWN_XENA;
off++;
off %= (MAX_RXDS_PER_BLOCK + 1);
- mac_control->rx_curr_put_info[ring_no].offset = off;
+ mac_control->rings[ring_no].rx_curr_put_info.offset = off;
#else
- ba = &nic->ba[ring_no][block_no][off];
+ ba = &mac_control->rings[ring_no].ba[block_no][off];
skb_reserve(skb, BUF0_LEN);
tmp = ((unsigned long) skb->data & ALIGN_SIZE);
if (tmp)
@@ -1719,22 +2294,41 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */
rxdp->Host_Control = (u64) ((unsigned long) (skb));
- rxdp->Control_1 |= RXD_OWN_XENA;
+ if (alloc_tab & ((1 << rxsync_frequency) - 1))
+ rxdp->Control_1 |= RXD_OWN_XENA;
off++;
- mac_control->rx_curr_put_info[ring_no].offset = off;
+ mac_control->rings[ring_no].rx_curr_put_info.offset = off;
#endif
+ rxdp->Control_2 |= SET_RXD_MARKER;
+
+ if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
+ first_rxdp = rxdp;
+ }
atomic_inc(&nic->rx_bufs_left[ring_no]);
alloc_tab++;
}
end:
+ /* Transfer ownership of first descriptor to adapter just before
+ * exiting. Before that, use memory barrier so that ownership
+ * and other fields are seen by adapter correctly.
+ */
+ if (first_rxdp) {
+ wmb();
+ first_rxdp->Control_1 |= RXD_OWN_XENA;
+ }
+
return SUCCESS;
}
/**
- * free_rx_buffers - Frees all Rx buffers
+ * free_rx_buffers - Frees all Rx buffers
* @sp: device private variable.
- * Description:
+ * Description:
* This function will free all Rx buffers allocated by host.
* Return Value:
* NONE.
@@ -1758,7 +2352,8 @@ static void free_rx_buffers(struct s2io_nic *sp)
for (i = 0; i < config->rx_ring_num; i++) {
for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) {
off = j % (MAX_RXDS_PER_BLOCK + 1);
- rxdp = sp->rx_blocks[i][blk].block_virt_addr + off;
+ rxdp = mac_control->rings[i].rx_blocks[blk].
+ block_virt_addr + off;
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
@@ -1793,7 +2388,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
HEADER_SNAP_SIZE,
PCI_DMA_FROMDEVICE);
#else
- ba = &sp->ba[i][blk][off];
+ ba = &mac_control->rings[i].ba[blk][off];
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
BUF0_LEN,
@@ -1813,10 +2408,10 @@ static void free_rx_buffers(struct s2io_nic *sp)
}
memset(rxdp, 0, sizeof(RxD_t));
}
- mac_control->rx_curr_put_info[i].block_index = 0;
- mac_control->rx_curr_get_info[i].block_index = 0;
- mac_control->rx_curr_put_info[i].offset = 0;
- mac_control->rx_curr_get_info[i].offset = 0;
+ mac_control->rings[i].rx_curr_put_info.block_index = 0;
+ mac_control->rings[i].rx_curr_get_info.block_index = 0;
+ mac_control->rings[i].rx_curr_put_info.offset = 0;
+ mac_control->rings[i].rx_curr_get_info.offset = 0;
atomic_set(&sp->rx_bufs_left[i], 0);
DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
dev->name, buf_cnt, i);
@@ -1826,7 +2421,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
/**
* s2io_poll - Rx interrupt handler for NAPI support
* @dev : pointer to the device structure.
- * @budget : The number of packets that were budgeted to be processed
+ * @budget : The number of packets that were budgeted to be processed
* during one pass through the 'Poll" function.
* Description:
* Comes into picture only if NAPI support has been incorporated. It does
@@ -1836,160 +2431,36 @@ static void free_rx_buffers(struct s2io_nic *sp)
* 0 on success and 1 if there are No Rx packets to be processed.
*/
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
static int s2io_poll(struct net_device *dev, int *budget)
{
nic_t *nic = dev->priv;
- XENA_dev_config_t __iomem *bar0 = nic->bar0;
- int pkts_to_process = *budget, pkt_cnt = 0;
- register u64 val64 = 0;
- rx_curr_get_info_t get_info, put_info;
- int i, get_block, put_block, get_offset, put_offset, ring_bufs;
-#ifndef CONFIG_2BUFF_MODE
- u16 val16, cksum;
-#endif
- struct sk_buff *skb;
- RxD_t *rxdp;
+ int pkt_cnt = 0, org_pkts_to_process;
mac_info_t *mac_control;
struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
- buffAdd_t *ba;
-#endif
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 val64;
+ int i;
+ atomic_inc(&nic->isr_cnt);
mac_control = &nic->mac_control;
config = &nic->config;
- if (pkts_to_process > dev->quota)
- pkts_to_process = dev->quota;
+ nic->pkts_to_process = *budget;
+ if (nic->pkts_to_process > dev->quota)
+ nic->pkts_to_process = dev->quota;
+ org_pkts_to_process = nic->pkts_to_process;
val64 = readq(&bar0->rx_traffic_int);
writeq(val64, &bar0->rx_traffic_int);
for (i = 0; i < config->rx_ring_num; i++) {
- get_info = mac_control->rx_curr_get_info[i];
- get_block = get_info.block_index;
- put_info = mac_control->rx_curr_put_info[i];
- put_block = put_info.block_index;
- ring_bufs = config->rx_cfg[i].num_rxd;
- rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
-#ifndef CONFIG_2BUFF_MODE
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
- put_info.offset;
- while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (--pkts_to_process < 0) {
- goto no_rx;
- }
- if (rxdp->Control_1 == END_OF_BLOCK) {
- rxdp =
- (RxD_t *) ((unsigned long) rxdp->
- Control_2);
- get_info.offset++;
- get_info.offset %=
- (MAX_RXDS_PER_BLOCK + 1);
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- continue;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- skb =
- (struct sk_buff *) ((unsigned long) rxdp->
- Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- goto no_rx;
- }
- val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- val16 = (u16) (val64 >> 48);
- cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- dev->mtu +
- HEADER_ETHERNET_II_802_3_SIZE +
- HEADER_802_2_SIZE +
- HEADER_SNAP_SIZE,
- PCI_DMA_FROMDEVICE);
- rx_osm_handler(nic, val16, rxdp, i);
- pkt_cnt++;
- get_info.offset++;
- get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- }
-#else
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
- put_info.offset;
- while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- !(rxdp->Control_2 & BIT(0))) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (--pkts_to_process < 0) {
- goto no_rx;
- }
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- goto no_rx;
- }
-
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- BUF0_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer1_ptr,
- BUF1_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer2_ptr,
- dev->mtu + BUF0_LEN + 4,
- PCI_DMA_FROMDEVICE);
- ba = &nic->ba[i][get_block][get_info.offset];
-
- rx_osm_handler(nic, rxdp, i, ba);
-
- get_info.offset++;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
-
- if (get_info.offset &&
- (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
- get_info.offset = 0;
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- rxdp =
- nic->rx_blocks[i][get_block].
- block_virt_addr;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- pkt_cnt++;
+ rx_intr_handler(&mac_control->rings[i]);
+ pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
+ if (!nic->pkts_to_process) {
+ /* Quota for the current iteration has been met */
+ goto no_rx;
}
-#endif
}
if (!pkt_cnt)
pkt_cnt = 1;
@@ -2007,9 +2478,10 @@ static int s2io_poll(struct net_device *dev, int *budget)
}
/* Re enable the Rx interrupts. */
en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
+ atomic_dec(&nic->isr_cnt);
return 0;
- no_rx:
+no_rx:
dev->quota -= pkt_cnt;
*budget -= pkt_cnt;
@@ -2020,279 +2492,211 @@ static int s2io_poll(struct net_device *dev, int *budget)
break;
}
}
+ atomic_dec(&nic->isr_cnt);
return 1;
}
-#else
-/**
+#endif
+
+/**
* rx_intr_handler - Rx interrupt handler
* @nic: device private variable.
- * Description:
- * If the interrupt is because of a received frame or if the
+ * Description:
+ * If the interrupt is because of a received frame or if the
* receive ring contains fresh as yet un-processed frames,this function is
- * called. It picks out the RxD at which place the last Rx processing had
- * stopped and sends the skb to the OSM's Rx handler and then increments
+ * called. It picks out the RxD at which place the last Rx processing had
+ * stopped and sends the skb to the OSM's Rx handler and then increments
* the offset.
* Return Value:
* NONE.
*/
-
-static void rx_intr_handler(struct s2io_nic *nic)
+static void rx_intr_handler(ring_info_t *ring_data)
{
+ nic_t *nic = ring_data->nic;
struct net_device *dev = (struct net_device *) nic->dev;
- XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+ int get_block, get_offset, put_block, put_offset, ring_bufs;
rx_curr_get_info_t get_info, put_info;
RxD_t *rxdp;
struct sk_buff *skb;
-#ifndef CONFIG_2BUFF_MODE
- u16 val16, cksum;
-#endif
- register u64 val64 = 0;
- int get_block, get_offset, put_block, put_offset, ring_bufs;
- int i, pkt_cnt = 0;
- mac_info_t *mac_control;
- struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
- buffAdd_t *ba;
+#ifndef CONFIG_S2IO_NAPI
+ int pkt_cnt = 0;
#endif
+ spin_lock(&nic->rx_lock);
+ if (atomic_read(&nic->card_state) == CARD_DOWN) {
+ DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
+ __FUNCTION__, dev->name);
+ spin_unlock(&nic->rx_lock);
+ return;
+ }
- mac_control = &nic->mac_control;
- config = &nic->config;
-
- /*
- * rx_traffic_int reg is an R1 register, hence we read and write back
- * the samevalue in the register to clear it.
- */
- val64 = readq(&bar0->rx_traffic_int);
- writeq(val64, &bar0->rx_traffic_int);
-
- for (i = 0; i < config->rx_ring_num; i++) {
- get_info = mac_control->rx_curr_get_info[i];
- get_block = get_info.block_index;
- put_info = mac_control->rx_curr_put_info[i];
- put_block = put_info.block_index;
- ring_bufs = config->rx_cfg[i].num_rxd;
- rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
+ get_info = ring_data->rx_curr_get_info;
+ get_block = get_info.block_index;
+ put_info = ring_data->rx_curr_put_info;
+ put_block = put_info.block_index;
+ ring_bufs = get_info.ring_len+1;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
get_info.offset;
-#ifndef CONFIG_2BUFF_MODE
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- spin_lock(&nic->put_lock);
- put_offset = nic->put_pos[i];
- spin_unlock(&nic->put_lock);
- while ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- if (rxdp->Control_1 == END_OF_BLOCK) {
- rxdp = (RxD_t *) ((unsigned long)
- rxdp->Control_2);
- get_info.offset++;
- get_info.offset %=
- (MAX_RXDS_PER_BLOCK + 1);
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- continue;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
- get_info.offset;
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- return;
- }
- val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- val16 = (u16) (val64 >> 48);
- cksum = RXD_GET_L4_CKSUM(rxdp->Control_1);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- dev->mtu +
- HEADER_ETHERNET_II_802_3_SIZE +
- HEADER_802_2_SIZE +
- HEADER_SNAP_SIZE,
- PCI_DMA_FROMDEVICE);
- rx_osm_handler(nic, val16, rxdp, i);
- get_info.offset++;
- get_info.offset %= (MAX_RXDS_PER_BLOCK + 1);
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- pkt_cnt++;
- if ((indicate_max_pkts)
- && (pkt_cnt > indicate_max_pkts))
- break;
+ get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ get_info.offset;
+#ifndef CONFIG_S2IO_NAPI
+ spin_lock(&nic->put_lock);
+ put_offset = ring_data->put_pos;
+ spin_unlock(&nic->put_lock);
+#else
+ put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ put_info.offset;
+#endif
+ while (RXD_IS_UP2DT(rxdp) &&
+ (((get_offset + 1) % ring_bufs) != put_offset)) {
+ skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
+ if (skb == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: The skb is ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+ spin_unlock(&nic->rx_lock);
+ return;
}
+#ifndef CONFIG_2BUFF_MODE
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer0_ptr,
+ dev->mtu +
+ HEADER_ETHERNET_II_802_3_SIZE +
+ HEADER_802_2_SIZE +
+ HEADER_SNAP_SIZE,
+ PCI_DMA_FROMDEVICE);
#else
- get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer0_ptr,
+ BUF0_LEN, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer1_ptr,
+ BUF1_LEN, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ rxdp->Buffer2_ptr,
+ dev->mtu + BUF0_LEN + 4,
+ PCI_DMA_FROMDEVICE);
+#endif
+ rx_osm_handler(ring_data, rxdp);
+ get_info.offset++;
+ ring_data->rx_curr_get_info.offset =
get_info.offset;
- spin_lock(&nic->put_lock);
- put_offset = nic->put_pos[i];
- spin_unlock(&nic->put_lock);
- while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
- !(rxdp->Control_2 & BIT(0))) &&
- (((get_offset + 1) % ring_bufs) != put_offset)) {
- skb = (struct sk_buff *) ((unsigned long)
- rxdp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: The skb is ",
- dev->name);
- DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
- return;
- }
-
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer0_ptr,
- BUF0_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer1_ptr,
- BUF1_LEN, PCI_DMA_FROMDEVICE);
- pci_unmap_single(nic->pdev, (dma_addr_t)
- rxdp->Buffer2_ptr,
- dev->mtu + BUF0_LEN + 4,
- PCI_DMA_FROMDEVICE);
- ba = &nic->ba[i][get_block][get_info.offset];
-
- rx_osm_handler(nic, rxdp, i, ba);
-
- get_info.offset++;
- mac_control->rx_curr_get_info[i].offset =
- get_info.offset;
- rxdp =
- nic->rx_blocks[i][get_block].block_virt_addr +
- get_info.offset;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
+ get_info.offset;
+ if (get_info.offset &&
+ (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
+ get_info.offset = 0;
+ ring_data->rx_curr_get_info.offset
+ = get_info.offset;
+ get_block++;
+ get_block %= ring_data->block_count;
+ ring_data->rx_curr_get_info.block_index
+ = get_block;
+ rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
+ }
- if (get_info.offset &&
- (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
- get_info.offset = 0;
- mac_control->rx_curr_get_info[i].
- offset = get_info.offset;
- get_block++;
- get_block %= nic->block_count[i];
- mac_control->rx_curr_get_info[i].
- block_index = get_block;
- rxdp =
- nic->rx_blocks[i][get_block].
- block_virt_addr;
- }
- get_offset =
- (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
+ get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
- pkt_cnt++;
- if ((indicate_max_pkts)
- && (pkt_cnt > indicate_max_pkts))
- break;
- }
-#endif
+#ifdef CONFIG_S2IO_NAPI
+ nic->pkts_to_process -= 1;
+ if (!nic->pkts_to_process)
+ break;
+#else
+ pkt_cnt++;
if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
break;
+#endif
}
+ spin_unlock(&nic->rx_lock);
}
-#endif
-/**
+
+/**
* tx_intr_handler - Transmit interrupt handler
* @nic : device private variable
- * Description:
- * If an interrupt was raised to indicate DMA complete of the
- * Tx packet, this function is called. It identifies the last TxD
- * whose buffer was freed and frees all skbs whose data have already
+ * Description:
+ * If an interrupt was raised to indicate DMA complete of the
+ * Tx packet, this function is called. It identifies the last TxD
+ * whose buffer was freed and frees all skbs whose data have already
* DMA'ed into the NICs internal memory.
* Return Value:
* NONE
*/
-static void tx_intr_handler(struct s2io_nic *nic)
+static void tx_intr_handler(fifo_info_t *fifo_data)
{
- XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ nic_t *nic = fifo_data->nic;
struct net_device *dev = (struct net_device *) nic->dev;
tx_curr_get_info_t get_info, put_info;
struct sk_buff *skb;
TxD_t *txdlp;
- register u64 val64 = 0;
- int i;
u16 j, frg_cnt;
- mac_info_t *mac_control;
- struct config_param *config;
-
- mac_control = &nic->mac_control;
- config = &nic->config;
- /*
- * tx_traffic_int reg is an R1 register, hence we read and write
- * back the samevalue in the register to clear it.
- */
- val64 = readq(&bar0->tx_traffic_int);
- writeq(val64, &bar0->tx_traffic_int);
-
- for (i = 0; i < config->tx_fifo_num; i++) {
- get_info = mac_control->tx_curr_get_info[i];
- put_info = mac_control->tx_curr_put_info[i];
- txdlp = (TxD_t *) nic->list_info[i][get_info.offset].
- list_virt_addr;
- while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
- (get_info.offset != put_info.offset) &&
- (txdlp->Host_Control)) {
- /* Check for TxD errors */
- if (txdlp->Control_1 & TXD_T_CODE) {
- unsigned long long err;
- err = txdlp->Control_1 & TXD_T_CODE;
- DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
- err);
+ get_info = fifo_data->tx_curr_get_info;
+ put_info = fifo_data->tx_curr_put_info;
+ txdlp = (TxD_t *) fifo_data->list_info[get_info.offset].
+ list_virt_addr;
+ while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
+ (get_info.offset != put_info.offset) &&
+ (txdlp->Host_Control)) {
+ /* Check for TxD errors */
+ if (txdlp->Control_1 & TXD_T_CODE) {
+ unsigned long long err;
+ err = txdlp->Control_1 & TXD_T_CODE;
+ if ((err >> 48) == 0xA) {
+ DBG_PRINT(TX_DBG, "TxD returned due \
+to loss of link\n");
}
-
- skb = (struct sk_buff *) ((unsigned long)
- txdlp->Host_Control);
- if (skb == NULL) {
- DBG_PRINT(ERR_DBG, "%s: Null skb ",
- dev->name);
- DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
- return;
+ else {
+ DBG_PRINT(ERR_DBG, "***TxD error \
+%llx\n", err);
}
- nic->tx_pkt_count++;
+ }
- frg_cnt = skb_shinfo(skb)->nr_frags;
+ skb = (struct sk_buff *) ((unsigned long)
+ txdlp->Host_Control);
+ if (skb == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Null skb ",
+ __FUNCTION__);
+ DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+ return;
+ }
- /* For unfragmented skb */
- pci_unmap_single(nic->pdev, (dma_addr_t)
- txdlp->Buffer_Pointer,
- skb->len - skb->data_len,
- PCI_DMA_TODEVICE);
- if (frg_cnt) {
- TxD_t *temp = txdlp;
- txdlp++;
- for (j = 0; j < frg_cnt; j++, txdlp++) {
- skb_frag_t *frag =
- &skb_shinfo(skb)->frags[j];
- pci_unmap_page(nic->pdev,
- (dma_addr_t)
- txdlp->
- Buffer_Pointer,
- frag->size,
- PCI_DMA_TODEVICE);
- }
- txdlp = temp;
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ nic->tx_pkt_count++;
+
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txdlp->Buffer_Pointer,
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ if (frg_cnt) {
+ TxD_t *temp;
+ temp = txdlp;
+ txdlp++;
+ for (j = 0; j < frg_cnt; j++, txdlp++) {
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[j];
+ if (!txdlp->Buffer_Pointer)
+ break;
+ pci_unmap_page(nic->pdev,
+ (dma_addr_t)
+ txdlp->
+ Buffer_Pointer,
+ frag->size,
+ PCI_DMA_TODEVICE);
}
- memset(txdlp, 0,
- (sizeof(TxD_t) * config->max_txds));
-
- /* Updating the statistics block */
- nic->stats.tx_packets++;
- nic->stats.tx_bytes += skb->len;
- dev_kfree_skb_irq(skb);
-
- get_info.offset++;
- get_info.offset %= get_info.fifo_len + 1;
- txdlp = (TxD_t *) nic->list_info[i]
- [get_info.offset].list_virt_addr;
- mac_control->tx_curr_get_info[i].offset =
- get_info.offset;
+ txdlp = temp;
}
+ memset(txdlp, 0,
+ (sizeof(TxD_t) * fifo_data->max_txds));
+
+ /* Updating the statistics block */
+ nic->stats.tx_bytes += skb->len;
+ dev_kfree_skb_irq(skb);
+
+ get_info.offset++;
+ get_info.offset %= get_info.fifo_len + 1;
+ txdlp = (TxD_t *) fifo_data->list_info
+ [get_info.offset].list_virt_addr;
+ fifo_data->tx_curr_get_info.offset =
+ get_info.offset;
}
spin_lock(&nic->tx_lock);
@@ -2301,13 +2705,13 @@ static void tx_intr_handler(struct s2io_nic *nic)
spin_unlock(&nic->tx_lock);
}
-/**
+/**
* alarm_intr_handler - Alarm Interrrupt handler
* @nic: device private variable
- * Description: If the interrupt was neither because of Rx packet or Tx
+ * Description: If the interrupt was neither because of Rx packet or Tx
* complete, this function is called. If the interrupt was to indicate
- * a loss of link, the OSM link status handler is invoked for any other
- * alarm interrupt the block that raised the interrupt is displayed
+ * a loss of link, the OSM link status handler is invoked for any other
+ * alarm interrupt the block that raised the interrupt is displayed
* and a H/W reset is issued.
* Return Value:
* NONE
@@ -2320,17 +2724,44 @@ static void alarm_intr_handler(struct s2io_nic *nic)
register u64 val64 = 0, err_reg = 0;
/* Handling link status change error Intr */
- err_reg = readq(&bar0->mac_rmac_err_reg);
- writeq(err_reg, &bar0->mac_rmac_err_reg);
- if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
- schedule_work(&nic->set_link_task);
+ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+ err_reg = readq(&bar0->mac_rmac_err_reg);
+ writeq(err_reg, &bar0->mac_rmac_err_reg);
+ if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
+ schedule_work(&nic->set_link_task);
+ }
+ }
+
+ /* Handling Ecc errors */
+ val64 = readq(&bar0->mc_err_reg);
+ writeq(val64, &bar0->mc_err_reg);
+ if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
+ if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
+ nic->mac_control.stats_info->sw_stat.
+ double_ecc_errs++;
+ DBG_PRINT(INIT_DBG, "%s: Device indicates ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "double ECC error!!\n");
+ if (nic->device_type != XFRAME_II_DEVICE) {
+ /* Reset XframeI only if critical error */
+ if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+ MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
+ netif_stop_queue(dev);
+ schedule_work(&nic->rst_timer_task);
+ }
+ }
+ } else {
+ nic->mac_control.stats_info->sw_stat.
+ single_ecc_errs++;
+ }
}
/* In case of a serious error, the device will be Reset. */
val64 = readq(&bar0->serr_source);
if (val64 & SERR_SOURCE_ANY) {
DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
- DBG_PRINT(ERR_DBG, "serious error!!\n");
+ DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
+ (unsigned long long)val64);
netif_stop_queue(dev);
schedule_work(&nic->rst_timer_task);
}
@@ -2338,7 +2769,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
/*
* Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
* Error occurs, the adapter will be recycled by disabling the
- * adapter enable bit and enabling it again after the device
+ * adapter enable bit and enabling it again after the device
* becomes Quiescent.
*/
val64 = readq(&bar0->pcc_err_reg);
@@ -2354,18 +2785,18 @@ static void alarm_intr_handler(struct s2io_nic *nic)
/* Other type of interrupts are not being handled now, TODO */
}
-/**
+/**
* wait_for_cmd_complete - waits for a command to complete.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * Description: Function that waits for a command to Write into RMAC
- * ADDR DATA registers to be completed and returns either success or
- * error depending on whether the command was complete or not.
+ * Description: Function that waits for a command to Write into RMAC
+ * ADDR DATA registers to be completed and returns either success or
+ * error depending on whether the command was complete or not.
* Return value:
* SUCCESS on success and FAILURE on failure.
*/
-static int wait_for_cmd_complete(nic_t * sp)
+int wait_for_cmd_complete(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
int ret = FAILURE, cnt = 0;
@@ -2385,29 +2816,32 @@ static int wait_for_cmd_complete(nic_t * sp)
return ret;
}
-/**
- * s2io_reset - Resets the card.
+/**
+ * s2io_reset - Resets the card.
* @sp : private member of the device structure.
* Description: Function to Reset the card. This function then also
- * restores the previously saved PCI configuration space registers as
+ * restores the previously saved PCI configuration space registers as
* the card reset also resets the configuration space.
* Return value:
* void.
*/
-static void s2io_reset(nic_t * sp)
+void s2io_reset(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
- u16 subid;
+ u16 subid, pci_cmd;
+
+ /* 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));
val64 = SW_RESET_ALL;
writeq(val64, &bar0->sw_reset);
- /*
- * At this stage, if the PCI write is indeed completed, the
- * card is reset and so is the PCI Config space of the device.
- * So a read cannot be issued at this stage on any of the
+ /*
+ * At this stage, if the PCI write is indeed completed, the
+ * card is reset and so is the PCI Config space of the device.
+ * So a read cannot be issued at this stage on any of the
* registers to ensure the write into "sw_reset" register
* has gone through.
* Question: Is there any system call that will explicitly force
@@ -2418,42 +2852,75 @@ static void s2io_reset(nic_t * sp)
*/
msleep(250);
- /* Restore the PCI state saved during initializarion. */
+ /* Restore the PCI state saved during initialization. */
pci_restore_state(sp->pdev);
+ pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+ pci_cmd);
s2io_init_pci(sp);
msleep(250);
+ /* Set swapper to enable I/O register access */
+ s2io_set_swapper(sp);
+
+ /* Restore the MSIX table entries from local variables */
+ restore_xmsi_data(sp);
+
+ /* Clear certain PCI/PCI-X fields after reset */
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ /* Clear parity err detect bit */
+ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
+
+ /* Clearing PCIX Ecc status register */
+ pci_write_config_dword(sp->pdev, 0x68, 0x7C);
+
+ /* Clearing PCI_STATUS error reflected here */
+ writeq(BIT(62), &bar0->txpic_int_reg);
+ }
+
+ /* Reset device statistics maintained by OS */
+ memset(&sp->stats, 0, sizeof (struct net_device_stats));
+
/* SXE-002: Configure link and activity LED to turn it off */
subid = sp->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if (((subid & 0xFF) >= 0x07) &&
+ (sp->device_type == XFRAME_I_DEVICE)) {
val64 = readq(&bar0->gpio_control);
val64 |= 0x0000800000000000ULL;
writeq(val64, &bar0->gpio_control);
val64 = 0x0411040400000000ULL;
- writeq(val64, (void __iomem *) bar0 + 0x2700);
+ writeq(val64, (void __iomem *)bar0 + 0x2700);
+ }
+
+ /*
+ * Clear spurious ECC interrupts that would have occured on
+ * XFRAME II cards after reset.
+ */
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ val64 = readq(&bar0->pcc_err_reg);
+ writeq(val64, &bar0->pcc_err_reg);
}
sp->device_enabled_once = FALSE;
}
/**
- * s2io_set_swapper - to set the swapper controle on the card
- * @sp : private member of the device structure,
+ * s2io_set_swapper - to set the swapper controle on the card
+ * @sp : private member of the device structure,
* pointer to the s2io_nic structure.
- * Description: Function to set the swapper control on the card
+ * Description: Function to set the swapper control on the card
* correctly depending on the 'endianness' of the system.
* Return value:
* SUCCESS on success and FAILURE on failure.
*/
-static int s2io_set_swapper(nic_t * sp)
+int s2io_set_swapper(nic_t * sp)
{
struct net_device *dev = sp->dev;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64, valt, valr;
- /*
+ /*
* Set proper endian settings and verify the same by reading
* the PIF Feed-back register.
*/
@@ -2505,8 +2972,9 @@ static int s2io_set_swapper(nic_t * sp)
i++;
}
if(i == 4) {
+ unsigned long long x = val64;
DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
- DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64);
+ DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);
return FAILURE;
}
}
@@ -2514,8 +2982,8 @@ static int s2io_set_swapper(nic_t * sp)
val64 &= 0xFFFF000000000000ULL;
#ifdef __BIG_ENDIAN
- /*
- * The device by default set to a big endian format, so a
+ /*
+ * The device by default set to a big endian format, so a
* big endian driver need not set anything.
*/
val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2527,13 +2995,14 @@ static int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_FE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+ if (sp->intr_type == INTA)
+ val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#else
- /*
+ /*
* Initially we enable all bits to make it accessible by the
- * driver, then we selectively enable only those bits that
+ * driver, then we selectively enable only those bits that
* we want to set.
*/
val64 |= (SWAPPER_CTRL_TXP_FE |
@@ -2549,14 +3018,15 @@ static int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_RXD_W_SE |
SWAPPER_CTRL_RXF_W_FE |
SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+ if (sp->intr_type == INTA)
+ val64 |= SWAPPER_CTRL_XMSI_SE;
writeq(val64, &bar0->swapper_ctrl);
#endif
val64 = readq(&bar0->swapper_ctrl);
- /*
- * Verifying if endian settings are accurate by reading a
+ /*
+ * Verifying if endian settings are accurate by reading a
* feedback register.
*/
val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -2572,59 +3042,332 @@ static int s2io_set_swapper(nic_t * sp)
return SUCCESS;
}
+int wait_for_msix_trans(nic_t *nic, int i)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 val64;
+ int ret = 0, cnt = 0;
+
+ do {
+ val64 = readq(&bar0->xmsi_access);
+ if (!(val64 & BIT(15)))
+ break;
+ mdelay(1);
+ cnt++;
+ } while(cnt < 5);
+ if (cnt == 5) {
+ DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void restore_xmsi_data(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 val64;
+ int i;
+
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
+ writeq(nic->msix_info[i].data, &bar0->xmsi_data);
+ val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+ writeq(val64, &bar0->xmsi_access);
+ if (wait_for_msix_trans(nic, i)) {
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ continue;
+ }
+ }
+}
+
+void store_xmsi_data(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 val64, addr, data;
+ int i;
+
+ /* Store and display */
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ val64 = (BIT(15) | vBIT(i, 26, 6));
+ writeq(val64, &bar0->xmsi_access);
+ if (wait_for_msix_trans(nic, i)) {
+ DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+ continue;
+ }
+ addr = readq(&bar0->xmsi_address);
+ data = readq(&bar0->xmsi_data);
+ if (addr && data) {
+ nic->msix_info[i].addr = addr;
+ nic->msix_info[i].data = data;
+ }
+ }
+}
+
+int s2io_enable_msi(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u16 msi_ctrl, msg_val;
+ struct config_param *config = &nic->config;
+ struct net_device *dev = nic->dev;
+ u64 val64, tx_mat, rx_mat;
+ int i, err;
+
+ val64 = readq(&bar0->pic_control);
+ val64 &= ~BIT(1);
+ writeq(val64, &bar0->pic_control);
+
+ err = pci_enable_msi(nic->pdev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
+ nic->dev->name);
+ return err;
+ }
+
+ /*
+ * Enable MSI and use MSI-1 in stead of the standard MSI-0
+ * for interrupt handling.
+ */
+ pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+ msg_val ^= 0x1;
+ pci_write_config_word(nic->pdev, 0x4c, msg_val);
+ pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+
+ pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
+ msi_ctrl |= 0x10;
+ pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
+
+ /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
+ tx_mat = readq(&bar0->tx_mat0_n[0]);
+ for (i=0; i<config->tx_fifo_num; i++) {
+ tx_mat |= TX_MAT_SET(i, 1);
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+ rx_mat = readq(&bar0->rx_mat);
+ for (i=0; i<config->rx_ring_num; i++) {
+ rx_mat |= RX_MAT_SET(i, 1);
+ }
+ writeq(rx_mat, &bar0->rx_mat);
+
+ dev->irq = nic->pdev->irq;
+ return 0;
+}
+
+int s2io_enable_msi_x(nic_t *nic)
+{
+ XENA_dev_config_t __iomem *bar0 = nic->bar0;
+ u64 tx_mat, rx_mat;
+ u16 msi_control; /* Temp variable */
+ int ret, i, j, msix_indx = 1;
+
+ nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (nic->entries == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+
+ nic->s2io_entries =
+ kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+ GFP_KERNEL);
+ if (nic->s2io_entries == NULL) {
+ DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+ kfree(nic->entries);
+ return -ENOMEM;
+ }
+ memset(nic->s2io_entries, 0,
+ MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+
+ for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+ nic->entries[i].entry = i;
+ nic->s2io_entries[i].entry = i;
+ nic->s2io_entries[i].arg = NULL;
+ nic->s2io_entries[i].in_use = 0;
+ }
+
+ tx_mat = readq(&bar0->tx_mat0_n[0]);
+ for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
+ tx_mat |= TX_MAT_SET(i, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
+ nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+ if (!nic->config.bimodal) {
+ rx_mat = readq(&bar0->rx_mat);
+ for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+ rx_mat |= RX_MAT_SET(j, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+ nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(rx_mat, &bar0->rx_mat);
+ } else {
+ tx_mat = readq(&bar0->tx_mat0_n[7]);
+ for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+ tx_mat |= TX_MAT_SET(i, msix_indx);
+ nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+ nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+ nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+ }
+ writeq(tx_mat, &bar0->tx_mat0_n[7]);
+ }
+
+ ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+ kfree(nic->entries);
+ kfree(nic->s2io_entries);
+ nic->entries = NULL;
+ nic->s2io_entries = NULL;
+ return -ENOMEM;
+ }
+
+ /*
+ * To enable MSI-X, MSI also needs to be enabled, due to a bug
+ * in the herc NIC. (Temp change, needs to be removed later)
+ */
+ pci_read_config_word(nic->pdev, 0x42, &msi_control);
+ msi_control |= 0x1; /* Enable MSI */
+ pci_write_config_word(nic->pdev, 0x42, msi_control);
+
+ return 0;
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
-/**
+/**
* s2io_open - open entry point of the driver
* @dev : pointer to the device structure.
* Description:
* This function is the open entry point of the driver. It mainly calls a
* function to allocate Rx buffers and inserts them into the buffer
- * descriptors and then enables the Rx part of the NIC.
+ * descriptors and then enables the Rx part of the NIC.
* Return value:
* 0 on success and an appropriate (-)ve integer as defined in errno.h
* file on failure.
*/
-static int s2io_open(struct net_device *dev)
+int s2io_open(struct net_device *dev)
{
nic_t *sp = dev->priv;
int err = 0;
+ int i;
+ u16 msi_control; /* Temp variable */
- /*
- * Make sure you have link off by default every time
+ /*
+ * Make sure you have link off by default every time
* Nic is initialized
*/
netif_carrier_off(dev);
- sp->last_link_state = LINK_DOWN;
+ sp->last_link_state = 0;
/* Initialize H/W and enable interrupts */
if (s2io_card_up(sp)) {
DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
dev->name);
- return -ENODEV;
+ err = -ENODEV;
+ goto hw_init_failed;
}
+ /* Store the values of the MSIX table in the nic_t structure */
+ store_xmsi_data(sp);
+
/* After proper initialization of H/W, register ISR */
- err = request_irq((int) sp->irq, s2io_isr, SA_SHIRQ,
- sp->name, dev);
- if (err) {
- s2io_reset(sp);
- DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
- dev->name);
- return err;
+ if (sp->intr_type == MSI) {
+ err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
+ SA_SHIRQ, sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+ goto isr_registration_failed;
+ }
+ }
+ if (sp->intr_type == MSI_X) {
+ for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+ if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+ sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_fifo_handle, 0, sp->desc1,
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
+ sp->msix_info[i].addr);
+ } else {
+ sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+ dev->name, i);
+ err = request_irq(sp->entries[i].vector,
+ s2io_msix_ring_handle, 0, sp->desc2,
+ sp->s2io_entries[i].arg);
+ DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
+ sp->msix_info[i].addr);
+ }
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+ DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+ goto isr_registration_failed;
+ }
+ sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+ }
+ }
+ if (sp->intr_type == INTA) {
+ err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+ sp->name, dev);
+ if (err) {
+ DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+ dev->name);
+ goto isr_registration_failed;
+ }
}
if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
- s2io_reset(sp);
- return -ENODEV;
+ err = -ENODEV;
+ goto setting_mac_address_failed;
}
netif_start_queue(dev);
return 0;
+
+setting_mac_address_failed:
+ if (sp->intr_type != MSI_X)
+ free_irq(sp->pdev->irq, dev);
+isr_registration_failed:
+ del_timer_sync(&sp->alarm_timer);
+ if (sp->intr_type == MSI_X) {
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ for (i=1; (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS); i++) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+
+ free_irq(vector, arg);
+ }
+ pci_disable_msix(sp->pdev);
+
+ /* Temp */
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+ }
+ }
+ else if (sp->intr_type == MSI)
+ pci_disable_msi(sp->pdev);
+ s2io_reset(sp);
+hw_init_failed:
+ if (sp->intr_type == MSI_X) {
+ if (sp->entries)
+ kfree(sp->entries);
+ if (sp->s2io_entries)
+ kfree(sp->s2io_entries);
+ }
+ return err;
}
/**
@@ -2640,16 +3383,38 @@ static int s2io_open(struct net_device *dev)
* file on failure.
*/
-static int s2io_close(struct net_device *dev)
+int s2io_close(struct net_device *dev)
{
nic_t *sp = dev->priv;
+ int i;
+ u16 msi_control;
flush_scheduled_work();
netif_stop_queue(dev);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- free_irq(dev->irq, dev);
+ if (sp->intr_type == MSI_X) {
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ for (i=1; (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS); i++) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+
+ free_irq(vector, arg);
+ }
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+ }
+ }
+ else {
+ free_irq(sp->pdev->irq, dev);
+ if (sp->intr_type == MSI)
+ pci_disable_msi(sp->pdev);
+ }
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -2667,7 +3432,7 @@ static int s2io_close(struct net_device *dev)
* 0 on success & 1 on failure.
*/
-static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
{
nic_t *sp = dev->priv;
u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -2678,37 +3443,56 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef NETIF_F_TSO
int mss;
#endif
+ u16 vlan_tag = 0;
+ int vlan_priority = 0;
mac_info_t *mac_control;
struct config_param *config;
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
mac_control = &sp->mac_control;
config = &sp->config;
- DBG_PRINT(TX_DBG, "%s: In S2IO Tx routine\n", dev->name);
+ DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name);
spin_lock_irqsave(&sp->tx_lock, flags);
-
if (atomic_read(&sp->card_state) == CARD_DOWN) {
- DBG_PRINT(ERR_DBG, "%s: Card going down for reset\n",
+ DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
dev->name);
spin_unlock_irqrestore(&sp->tx_lock, flags);
- return 1;
+ dev_kfree_skb(skb);
+ return 0;
}
queue = 0;
- put_off = (u16) mac_control->tx_curr_put_info[queue].offset;
- get_off = (u16) mac_control->tx_curr_get_info[queue].offset;
- txdp = (TxD_t *) sp->list_info[queue][put_off].list_virt_addr;
- queue_len = mac_control->tx_curr_put_info[queue].fifo_len + 1;
+ /* Get Fifo number to Transmit based on vlan priority */
+ if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+ vlan_tag = vlan_tx_tag_get(skb);
+ vlan_priority = vlan_tag >> 13;
+ queue = config->fifo_mapping[vlan_priority];
+ }
+
+ put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset;
+ get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset;
+ txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off].
+ list_virt_addr;
+
+ queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
/* Avoid "put" pointer going beyond "get" pointer */
if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
- DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n");
+ DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
netif_stop_queue(dev);
dev_kfree_skb(skb);
spin_unlock_irqrestore(&sp->tx_lock, flags);
return 0;
}
+
+ /* A buffer with no data will be dropped */
+ if (!skb->len) {
+ DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&sp->tx_lock, flags);
+ return 0;
+ }
+
#ifdef NETIF_F_TSO
mss = skb_shinfo(skb)->tso_size;
if (mss) {
@@ -2720,9 +3504,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
frg_cnt = skb_shinfo(skb)->nr_frags;
frg_len = skb->len - skb->data_len;
- txdp->Host_Control = (unsigned long) skb;
txdp->Buffer_Pointer = pci_map_single
(sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
+ txdp->Host_Control = (unsigned long) skb;
if (skb->ip_summed == CHECKSUM_HW) {
txdp->Control_2 |=
(TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
@@ -2731,6 +3515,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Control_2 |= config->tx_intr_type;
+ if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+ txdp->Control_2 |= TXD_VLAN_ENABLE;
+ txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+ }
+
txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
TXD_GATHER_CODE_FIRST);
txdp->Control_1 |= TXD_LIST_OWN_XENA;
@@ -2738,6 +3527,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
/* For fragmented SKB. */
for (i = 0; i < frg_cnt; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ /* A '0' length fragment will be ignored */
+ if (!frag->size)
+ continue;
txdp++;
txdp->Buffer_Pointer = (u64) pci_map_page
(sp->pdev, frag->page, frag->page_offset,
@@ -2747,23 +3539,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Control_1 |= TXD_GATHER_CODE_LAST;
tx_fifo = mac_control->tx_FIFO_start[queue];
- val64 = sp->list_info[queue][put_off].list_phy_addr;
+ val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
writeq(val64, &tx_fifo->TxDL_Pointer);
val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
TX_FIFO_LAST_LIST);
+
#ifdef NETIF_F_TSO
if (mss)
val64 |= TX_FIFO_SPECIAL_FUNC;
#endif
writeq(val64, &tx_fifo->List_Control);
- /* Perform a PCI read to flush previous writes */
- val64 = readq(&bar0->general_int_status);
+ mmiowb();
put_off++;
- put_off %= mac_control->tx_curr_put_info[queue].fifo_len + 1;
- mac_control->tx_curr_put_info[queue].offset = put_off;
+ put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+ mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
/* Avoid "put" pointer going beyond "get" pointer */
if (((put_off + 1) % queue_len) == get_off) {
@@ -2779,18 +3571,172 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
+static void
+s2io_alarm_handle(unsigned long data)
+{
+ nic_t *sp = (nic_t *)data;
+
+ alarm_intr_handler(sp);
+ mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
+}
+
+static irqreturn_t
+s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ nic_t *sp = dev->priv;
+ int i;
+ int ret;
+ mac_info_t *mac_control;
+ struct config_param *config;
+
+ atomic_inc(&sp->isr_cnt);
+ mac_control = &sp->mac_control;
+ config = &sp->config;
+ DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
+
+ /* If Intr is because of Rx Traffic */
+ for (i = 0; i < config->rx_ring_num; i++)
+ rx_intr_handler(&mac_control->rings[i]);
+
+ /* If Intr is because of Tx Traffic */
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
+
+ /*
+ * If the Rx buffer count is below the panic threshold then
+ * reallocate the buffers from the interrupt handler itself,
+ * else schedule a tasklet to reallocate the buffers.
+ */
+ for (i = 0; i < config->rx_ring_num; i++) {
+ int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+ int level = rx_buffer_level(sp, rxb_size, i);
+
+ if ((level == PANIC) && (!TASKLET_IN_USE)) {
+ DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+ DBG_PRINT(INTR_DBG, "PANIC levels\n");
+ if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+ DBG_PRINT(ERR_DBG, "%s:Out of memory",
+ dev->name);
+ DBG_PRINT(ERR_DBG, " in ISR!!\n");
+ clear_bit(0, (&sp->tasklet_status));
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+ }
+ clear_bit(0, (&sp->tasklet_status));
+ } else if (level == LOW) {
+ tasklet_schedule(&sp->task);
+ }
+ }
+
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ ring_info_t *ring = (ring_info_t *)dev_id;
+ nic_t *sp = ring->nic;
+ int rxb_size, level, rng_n;
+
+ atomic_inc(&sp->isr_cnt);
+ rx_intr_handler(ring);
+
+ rng_n = ring->ring_no;
+ rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+ level = rx_buffer_level(sp, rxb_size, rng_n);
+
+ if ((level == PANIC) && (!TASKLET_IN_USE)) {
+ int ret;
+ DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+ DBG_PRINT(INTR_DBG, "PANIC levels\n");
+ if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+ DBG_PRINT(ERR_DBG, "Out of memory in %s",
+ __FUNCTION__);
+ clear_bit(0, (&sp->tasklet_status));
+ return IRQ_HANDLED;
+ }
+ clear_bit(0, (&sp->tasklet_status));
+ } else if (level == LOW) {
+ tasklet_schedule(&sp->task);
+ }
+ atomic_dec(&sp->isr_cnt);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ fifo_info_t *fifo = (fifo_info_t *)dev_id;
+ nic_t *sp = fifo->nic;
+
+ atomic_inc(&sp->isr_cnt);
+ tx_intr_handler(fifo);
+ atomic_dec(&sp->isr_cnt);
+ return IRQ_HANDLED;
+}
+
+static void s2io_txpic_intr_handle(nic_t *sp)
+{
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64;
+
+ val64 = readq(&bar0->pic_int_status);
+ if (val64 & PIC_INT_GPIO) {
+ val64 = readq(&bar0->gpio_int_reg);
+ if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
+ (val64 & GPIO_INT_REG_LINK_UP)) {
+ val64 |= GPIO_INT_REG_LINK_DOWN;
+ val64 |= GPIO_INT_REG_LINK_UP;
+ writeq(val64, &bar0->gpio_int_reg);
+ goto masking;
+ }
+
+ if (((sp->last_link_state == LINK_UP) &&
+ (val64 & GPIO_INT_REG_LINK_DOWN)) ||
+ ((sp->last_link_state == LINK_DOWN) &&
+ (val64 & GPIO_INT_REG_LINK_UP))) {
+ val64 = readq(&bar0->gpio_int_mask);
+ val64 |= GPIO_INT_MASK_LINK_DOWN;
+ val64 |= GPIO_INT_MASK_LINK_UP;
+ writeq(val64, &bar0->gpio_int_mask);
+ s2io_set_link((unsigned long)sp);
+ }
+masking:
+ if (sp->last_link_state == LINK_UP) {
+ /*enable down interrupt */
+ val64 = readq(&bar0->gpio_int_mask);
+ /* unmasks link down intr */
+ val64 &= ~GPIO_INT_MASK_LINK_DOWN;
+ /* masks link up intr */
+ val64 |= GPIO_INT_MASK_LINK_UP;
+ writeq(val64, &bar0->gpio_int_mask);
+ } else {
+ /*enable UP Interrupt */
+ val64 = readq(&bar0->gpio_int_mask);
+ /* unmasks link up interrupt */
+ val64 &= ~GPIO_INT_MASK_LINK_UP;
+ /* masks link down interrupt */
+ val64 |= GPIO_INT_MASK_LINK_DOWN;
+ writeq(val64, &bar0->gpio_int_mask);
+ }
+ }
+}
+
/**
* s2io_isr - ISR handler of the device .
* @irq: the irq of the device.
* @dev_id: a void pointer to the dev structure of the NIC.
* @pt_regs: pointer to the registers pushed on the stack.
- * Description: This function is the ISR handler of the device. It
- * identifies the reason for the interrupt and calls the relevant
- * service routines. As a contongency measure, this ISR allocates the
+ * Description: This function is the ISR handler of the device. It
+ * identifies the reason for the interrupt and calls the relevant
+ * service routines. As a contongency measure, this ISR allocates the
* recv buffers, if their numbers are below the panic value which is
* presently set to 25% of the original number of rcv buffers allocated.
* Return value:
- * IRQ_HANDLED: will be returned if IRQ was handled by this routine
+ * IRQ_HANDLED: will be returned if IRQ was handled by this routine
* IRQ_NONE: will be returned if interrupt is not from our device
*/
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2798,40 +3744,31 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = (struct net_device *) dev_id;
nic_t *sp = dev->priv;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
-#ifndef CONFIG_S2IO_NAPI
- int i, ret;
-#endif
- u64 reason = 0;
+ int i;
+ u64 reason = 0, val64;
mac_info_t *mac_control;
struct config_param *config;
+ atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
- /*
+ /*
* Identify the cause for interrupt and call the appropriate
* interrupt handler. Causes for the interrupt could be;
* 1. Rx of packet.
* 2. Tx complete.
* 3. Link down.
- * 4. Error in any functional blocks of the NIC.
+ * 4. Error in any functional blocks of the NIC.
*/
reason = readq(&bar0->general_int_status);
if (!reason) {
/* The interrupt was not raised by Xena. */
+ atomic_dec(&sp->isr_cnt);
return IRQ_NONE;
}
- /* If Intr is because of Tx Traffic */
- if (reason & GEN_INTR_TXTRAFFIC) {
- tx_intr_handler(sp);
- }
-
- /* If Intr is because of an error */
- if (reason & (GEN_ERROR_INTR))
- alarm_intr_handler(sp);
-
#ifdef CONFIG_S2IO_NAPI
if (reason & GEN_INTR_RXTRAFFIC) {
if (netif_rx_schedule_prep(dev)) {
@@ -2843,17 +3780,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
#else
/* If Intr is because of Rx Traffic */
if (reason & GEN_INTR_RXTRAFFIC) {
- rx_intr_handler(sp);
+ /*
+ * rx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit get's
+ * cleared and hence a read can be avoided.
+ */
+ val64 = 0xFFFFFFFFFFFFFFFFULL;
+ writeq(val64, &bar0->rx_traffic_int);
+ for (i = 0; i < config->rx_ring_num; i++) {
+ rx_intr_handler(&mac_control->rings[i]);
+ }
}
#endif
- /*
- * If the Rx buffer count is below the panic threshold then
- * reallocate the buffers from the interrupt handler itself,
+ /* If Intr is because of Tx Traffic */
+ if (reason & GEN_INTR_TXTRAFFIC) {
+ /*
+ * tx_traffic_int reg is an R1 register, writing all 1's
+ * will ensure that the actual interrupt causing bit get's
+ * cleared and hence a read can be avoided.
+ */
+ val64 = 0xFFFFFFFFFFFFFFFFULL;
+ writeq(val64, &bar0->tx_traffic_int);
+
+ for (i = 0; i < config->tx_fifo_num; i++)
+ tx_intr_handler(&mac_control->fifos[i]);
+ }
+
+ if (reason & GEN_INTR_TXPIC)
+ s2io_txpic_intr_handle(sp);
+ /*
+ * If the Rx buffer count is below the panic threshold then
+ * reallocate the buffers from the interrupt handler itself,
* else schedule a tasklet to reallocate the buffers.
*/
#ifndef CONFIG_S2IO_NAPI
for (i = 0; i < config->rx_ring_num; i++) {
+ int ret;
int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
int level = rx_buffer_level(sp, rxb_size, i);
@@ -2865,6 +3828,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
dev->name);
DBG_PRINT(ERR_DBG, " in ISR!!\n");
clear_bit(0, (&sp->tasklet_status));
+ atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
clear_bit(0, (&sp->tasklet_status));
@@ -2874,33 +3838,69 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
}
#endif
+ atomic_dec(&sp->isr_cnt);
return IRQ_HANDLED;
}
/**
- * s2io_get_stats - Updates the device statistics structure.
+ * s2io_updt_stats -
+ */
+static void s2io_updt_stats(nic_t *sp)
+{
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64;
+ int cnt = 0;
+
+ if (atomic_read(&sp->card_state) == CARD_UP) {
+ /* Apprx 30us on a 133 MHz bus */
+ val64 = SET_UPDT_CLICKS(10) |
+ STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN;
+ writeq(val64, &bar0->stat_cfg);
+ do {
+ udelay(100);
+ val64 = readq(&bar0->stat_cfg);
+ if (!(val64 & BIT(0)))
+ break;
+ cnt++;
+ if (cnt == 5)
+ break; /* Updt failed */
+ } while(1);
+ }
+}
+
+/**
+ * s2io_get_stats - Updates the device statistics structure.
* @dev : pointer to the device structure.
* Description:
- * This function updates the device statistics structure in the s2io_nic
+ * This function updates the device statistics structure in the s2io_nic
* structure and returns a pointer to the same.
* Return value:
* pointer to the updated net_device_stats structure.
*/
-static struct net_device_stats *s2io_get_stats(struct net_device *dev)
+struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
nic_t *sp = dev->priv;
mac_info_t *mac_control;
struct config_param *config;
+
mac_control = &sp->mac_control;
config = &sp->config;
- sp->stats.tx_errors = mac_control->stats_info->tmac_any_err_frms;
- sp->stats.rx_errors = mac_control->stats_info->rmac_drop_frms;
- sp->stats.multicast = mac_control->stats_info->rmac_vld_mcst_frms;
+ /* Configure Stats for immediate updt */
+ s2io_updt_stats(sp);
+
+ sp->stats.tx_packets =
+ le32_to_cpu(mac_control->stats_info->tmac_frms);
+ sp->stats.tx_errors =
+ le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
+ sp->stats.rx_errors =
+ le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+ sp->stats.multicast =
+ le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
sp->stats.rx_length_errors =
- mac_control->stats_info->rmac_long_frms;
+ le32_to_cpu(mac_control->stats_info->rmac_long_frms);
return (&sp->stats);
}
@@ -2909,8 +3909,8 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
* s2io_set_multicast - entry point for multicast address enable/disable.
* @dev : pointer to the device structure
* Description:
- * This function is a driver entry point which gets called by the kernel
- * whenever multicast addresses must be enabled/disabled. This also gets
+ * This function is a driver entry point which gets called by the kernel
+ * whenever multicast addresses must be enabled/disabled. This also gets
* called to set/reset promiscuous mode. Depending on the deivce flag, we
* determine, if multicast address must be enabled or if promiscuous mode
* is to be disabled etc.
@@ -2948,6 +3948,8 @@ static void s2io_set_multicast(struct net_device *dev)
/* Disable all Multicast addresses */
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
&bar0->rmac_addr_data0_mem);
+ writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0),
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
@@ -2972,7 +3974,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 1;
- DBG_PRINT(ERR_DBG, "%s: entered promiscuous mode\n",
+ DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
dev->name);
} else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) {
/* Remove the NIC from promiscuous mode */
@@ -2987,7 +3989,7 @@ static void s2io_set_multicast(struct net_device *dev)
val64 = readq(&bar0->mac_cfg);
sp->promisc_flg = 0;
- DBG_PRINT(ERR_DBG, "%s: left promiscuous mode\n",
+ DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
dev->name);
}
@@ -3010,7 +4012,7 @@ static void s2io_set_multicast(struct net_device *dev)
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
&bar0->rmac_addr_data0_mem);
writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
- &bar0->rmac_addr_data1_mem);
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
@@ -3039,8 +4041,7 @@ static void s2io_set_multicast(struct net_device *dev)
writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
&bar0->rmac_addr_data0_mem);
writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
- &bar0->rmac_addr_data1_mem);
-
+ &bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
@@ -3059,12 +4060,12 @@ static void s2io_set_multicast(struct net_device *dev)
}
/**
- * s2io_set_mac_addr - Programs the Xframe mac address
+ * s2io_set_mac_addr - Programs the Xframe mac address
* @dev : pointer to the device structure.
* @addr: a uchar pointer to the new mac address which is to be set.
- * Description : This procedure will program the Xframe to receive
+ * Description : This procedure will program the Xframe to receive
* frames with new Mac Address
- * Return value: SUCCESS on success and an appropriate (-)ve integer
+ * Return value: SUCCESS on success and an appropriate (-)ve integer
* as defined in errno.h file on failure.
*/
@@ -3075,10 +4076,10 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
register u64 val64, mac_addr = 0;
int i;
- /*
+ /*
* Set the new MAC address as the new unicast filter and reflect this
* change on the device address registered with the OS. It will be
- * at offset 0.
+ * at offset 0.
*/
for (i = 0; i < ETH_ALEN; i++) {
mac_addr <<= 8;
@@ -3102,12 +4103,12 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
}
/**
- * s2io_ethtool_sset - Sets different link parameters.
+ * s2io_ethtool_sset - Sets different link parameters.
* @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
* @info: pointer to the structure with parameters given by ethtool to set
* link information.
* Description:
- * The function sets different link parameters provided by the user onto
+ * The function sets different link parameters provided by the user onto
* the NIC.
* Return value:
* 0 on success.
@@ -3129,7 +4130,7 @@ static int s2io_ethtool_sset(struct net_device *dev,
}
/**
- * s2io_ethtol_gset - Return link specific information.
+ * s2io_ethtol_gset - Return link specific information.
* @sp : private member of the device structure, pointer to the
* s2io_nic structure.
* @info : pointer to the structure with parameters given by ethtool
@@ -3161,8 +4162,8 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
}
/**
- * s2io_ethtool_gdrvinfo - Returns driver specific information.
- * @sp : private member of the device structure, which is a pointer to the
+ * s2io_ethtool_gdrvinfo - Returns driver specific information.
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @info : pointer to the structure with parameters given by ethtool to
* return driver information.
@@ -3177,11 +4178,10 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
{
nic_t *sp = dev->priv;
- strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
- strncpy(info->version, s2io_driver_version,
- sizeof(s2io_driver_version));
- strncpy(info->fw_version, "", 32);
- strncpy(info->bus_info, pci_name(sp->pdev), 32);
+ strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
+ strncpy(info->version, s2io_driver_version, sizeof(info->version));
+ strncpy(info->fw_version, "", sizeof(info->fw_version));
+ strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
info->regdump_len = XENA_REG_SPACE;
info->eedump_len = XENA_EEPROM_SPACE;
info->testinfo_len = S2IO_TEST_LEN;
@@ -3190,9 +4190,9 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
/**
* s2io_ethtool_gregs - dumps the entire space of Xfame into the buffer.
- * @sp: private member of the device structure, which is a pointer to the
+ * @sp: private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @regs : pointer to the structure with parameters given by ethtool for
+ * @regs : pointer to the structure with parameters given by ethtool for
* dumping the registers.
* @reg_space: The input argumnet into which all the registers are dumped.
* Description:
@@ -3221,11 +4221,11 @@ static void s2io_ethtool_gregs(struct net_device *dev,
/**
* s2io_phy_id - timer function that alternates adapter LED.
- * @data : address of the private member of the device structure, which
+ * @data : address of the private member of the device structure, which
* is a pointer to the s2io_nic structure, provided as an u32.
- * Description: This is actually the timer function that alternates the
- * adapter LED bit of the adapter control bit to set/reset every time on
- * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
+ * Description: This is actually the timer function that alternates the
+ * adapter LED bit of the adapter control bit to set/reset every time on
+ * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
* once every second.
*/
static void s2io_phy_id(unsigned long data)
@@ -3236,7 +4236,8 @@ static void s2io_phy_id(unsigned long data)
u16 subid;
subid = sp->pdev->subsystem_device;
- if ((subid & 0xFF) >= 0x07) {
+ if ((sp->device_type == XFRAME_II_DEVICE) ||
+ ((subid & 0xFF) >= 0x07)) {
val64 = readq(&bar0->gpio_control);
val64 ^= GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -3253,12 +4254,12 @@ static void s2io_phy_id(unsigned long data)
* s2io_ethtool_idnic - To physically identify the nic on the system.
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @id : pointer to the structure with identification parameters given by
+ * @id : pointer to the structure with identification parameters given by
* ethtool.
* Description: Used to physically identify the NIC on the system.
- * The Link LED will blink for a time specified by the user for
+ * The Link LED will blink for a time specified by the user for
* identification.
- * NOTE: The Link has to be Up to be able to blink the LED. Hence
+ * NOTE: The Link has to be Up to be able to blink the LED. Hence
* identification is possible only if it's link is up.
* Return value:
* int , returns 0 on success
@@ -3273,7 +4274,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
subid = sp->pdev->subsystem_device;
last_gpio_ctrl_val = readq(&bar0->gpio_control);
- if ((subid & 0xFF) < 0x07) {
+ if ((sp->device_type == XFRAME_I_DEVICE) &&
+ ((subid & 0xFF) < 0x07)) {
val64 = readq(&bar0->adapter_control);
if (!(val64 & ADAPTER_CNTL_EN)) {
printk(KERN_ERR
@@ -3288,12 +4290,12 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
}
mod_timer(&sp->id_timer, jiffies);
if (data)
- msleep(data * 1000);
+ msleep_interruptible(data * HZ);
else
- msleep(0xFFFFFFFF);
+ msleep_interruptible(MAX_FLICKER_TIME);
del_timer_sync(&sp->id_timer);
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) {
writeq(last_gpio_ctrl_val, &bar0->gpio_control);
last_gpio_ctrl_val = readq(&bar0->gpio_control);
}
@@ -3303,7 +4305,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
/**
* s2io_ethtool_getpause_data -Pause frame frame generation and reception.
- * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
+ * @sp : private member of the device structure, which is a pointer to the
+ * s2io_nic structure.
* @ep : pointer to the structure with pause parameters given by ethtool.
* Description:
* Returns the Pause frame generation and reception capability of the NIC.
@@ -3327,7 +4330,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
/**
* s2io_ethtool_setpause_data - set/reset pause frame generation.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @ep : pointer to the structure with pause parameters given by ethtool.
* Description:
@@ -3338,7 +4341,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
*/
static int s2io_ethtool_setpause_data(struct net_device *dev,
- struct ethtool_pauseparam *ep)
+ struct ethtool_pauseparam *ep)
{
u64 val64;
nic_t *sp = dev->priv;
@@ -3359,13 +4362,13 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
/**
* read_eeprom - reads 4 bytes of data from user given offset.
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @off : offset at which the data must be written
* @data : Its an output parameter where the data read at the given
- * offset is stored.
+ * offset is stored.
* Description:
- * Will read 4 bytes of data from the user given offset and return the
+ * Will read 4 bytes of data from the user given offset and return the
* read data.
* NOTE: Will allow to read only part of the EEPROM visible through the
* I2C bus.
@@ -3374,29 +4377,53 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
*/
#define S2IO_DEV_ID 5
-static int read_eeprom(nic_t * sp, int off, u32 * data)
+static int read_eeprom(nic_t * sp, int off, u64 * data)
{
int ret = -1;
u32 exit_cnt = 0;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- *data = I2C_CONTROL_GET_DATA(val64);
- ret = 0;
- break;
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ *data = I2C_CONTROL_GET_DATA(val64);
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
}
- msleep(50);
- exit_cnt++;
}
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+ SPI_CONTROL_BYTECNT(0x3) |
+ SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ val64 |= SPI_CONTROL_REQ;
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->spi_control);
+ if (val64 & SPI_CONTROL_NACK) {
+ ret = 1;
+ break;
+ } else if (val64 & SPI_CONTROL_DONE) {
+ *data = readq(&bar0->spi_data);
+ *data &= 0xffffff;
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
+ }
+ }
return ret;
}
@@ -3406,7 +4433,7 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
* s2io_nic structure.
* @off : offset at which the data must be written
* @data : The data that is to be written
- * @cnt : Number of bytes of the data that are actually to be written into
+ * @cnt : Number of bytes of the data that are actually to be written into
* the Eeprom. (max of 3)
* Description:
* Actually writes the relevant part of the data value into the Eeprom
@@ -3415,35 +4442,60 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
* 0 on success, -1 on failure.
*/
-static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
{
int exit_cnt = 0, ret = -1;
u64 val64;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
- I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
- I2C_CONTROL_CNTL_START;
- SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+ I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
+ I2C_CONTROL_CNTL_START;
+ SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->i2c_control);
+ if (I2C_CONTROL_CNTL_END(val64)) {
+ if (!(val64 & I2C_CONTROL_NACK))
+ ret = 0;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
+ }
+ }
- while (exit_cnt < 5) {
- val64 = readq(&bar0->i2c_control);
- if (I2C_CONTROL_CNTL_END(val64)) {
- if (!(val64 & I2C_CONTROL_NACK))
+ if (sp->device_type == XFRAME_II_DEVICE) {
+ int write_cnt = (cnt == 8) ? 0 : cnt;
+ writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+
+ val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+ SPI_CONTROL_BYTECNT(write_cnt) |
+ SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ val64 |= SPI_CONTROL_REQ;
+ SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+ while (exit_cnt < 5) {
+ val64 = readq(&bar0->spi_control);
+ if (val64 & SPI_CONTROL_NACK) {
+ ret = 1;
+ break;
+ } else if (val64 & SPI_CONTROL_DONE) {
ret = 0;
- break;
+ break;
+ }
+ msleep(50);
+ exit_cnt++;
}
- msleep(50);
- exit_cnt++;
}
-
return ret;
}
/**
* s2io_ethtool_geeprom - reads the value stored in the Eeprom.
* @sp : private member of the device structure, which is a pointer to the * s2io_nic structure.
- * @eeprom : pointer to the user level structure provided by ethtool,
+ * @eeprom : pointer to the user level structure provided by ethtool,
* containing all relevant information.
* @data_buf : user defined value to be written into Eeprom.
* Description: Reads the values stored in the Eeprom at given offset
@@ -3454,9 +4506,10 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
*/
static int s2io_ethtool_geeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 * data_buf)
+ struct ethtool_eeprom *eeprom, u8 * data_buf)
{
- u32 data, i, valid;
+ u32 i, valid;
+ u64 data;
nic_t *sp = dev->priv;
eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -3479,7 +4532,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev,
* s2io_ethtool_seeprom - tries to write the user provided value in Eeprom
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @eeprom : pointer to the user level structure provided by ethtool,
+ * @eeprom : pointer to the user level structure provided by ethtool,
* containing all relevant information.
* @data_buf ; user defined value to be written into Eeprom.
* Description:
@@ -3494,7 +4547,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
u8 * data_buf)
{
int len = eeprom->len, cnt = 0;
- u32 valid = 0, data;
+ u64 valid = 0, data;
nic_t *sp = dev->priv;
if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -3527,8 +4580,8 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
}
/**
- * s2io_register_test - reads and writes into all clock domains.
- * @sp : private member of the device structure, which is a pointer to the
+ * s2io_register_test - reads and writes into all clock domains.
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data : variable that returns the result of each of the test conducted b
* by the driver.
@@ -3542,11 +4595,11 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
static int s2io_register_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- u64 val64 = 0;
+ u64 val64 = 0, exp_val;
int fail = 0;
- val64 = readq(&bar0->pcc_enable);
- if (val64 != 0xff00000000000000ULL) {
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 != 0x123456789abcdefULL) {
fail = 1;
DBG_PRINT(INFO_DBG, "Read Test level 1 fails\n");
}
@@ -3558,7 +4611,11 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
val64 = readq(&bar0->rx_queue_cfg);
- if (val64 != 0x0808080808080808ULL) {
+ if (sp->device_type == XFRAME_II_DEVICE)
+ exp_val = 0x0404040404040404ULL;
+ else
+ exp_val = 0x0808080808080808ULL;
+ if (val64 != exp_val) {
fail = 1;
DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
}
@@ -3586,17 +4643,17 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
}
*data = fail;
- return 0;
+ return fail;
}
/**
- * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.
+ * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data:variable that returns the result of each of the test conducted by
* the driver.
* Description:
- * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
+ * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
* register.
* Return value:
* 0 on success.
@@ -3605,70 +4662,95 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)
static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
{
int fail = 0;
- u32 ret_data;
+ u64 ret_data, org_4F0, org_7F0;
+ u8 saved_4F0 = 0, saved_7F0 = 0;
+ struct net_device *dev = sp->dev;
/* Test Write Error at offset 0 */
- if (!write_eeprom(sp, 0, 0, 3))
- fail = 1;
+ /* Note that SPI interface allows write access to all areas
+ * of EEPROM. Hence doing all negative testing only for Xframe I.
+ */
+ if (sp->device_type == XFRAME_I_DEVICE)
+ if (!write_eeprom(sp, 0, 0, 3))
+ fail = 1;
+
+ /* Save current values at offsets 0x4F0 and 0x7F0 */
+ if (!read_eeprom(sp, 0x4F0, &org_4F0))
+ saved_4F0 = 1;
+ if (!read_eeprom(sp, 0x7F0, &org_7F0))
+ saved_7F0 = 1;
/* Test Write at offset 4f0 */
- if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
+ if (write_eeprom(sp, 0x4F0, 0x012345, 3))
fail = 1;
if (read_eeprom(sp, 0x4F0, &ret_data))
fail = 1;
- if (ret_data != 0x01234567)
+ if (ret_data != 0x012345) {
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
fail = 1;
+ }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
+ write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
/* Test Write Request Error at offset 0x7c */
- if (!write_eeprom(sp, 0x07C, 0, 3))
- fail = 1;
+ if (sp->device_type == XFRAME_I_DEVICE)
+ if (!write_eeprom(sp, 0x07C, 0, 3))
+ fail = 1;
- /* Test Write Request at offset 0x7fc */
- if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
+ /* Test Write Request at offset 0x7f0 */
+ if (write_eeprom(sp, 0x7F0, 0x012345, 3))
fail = 1;
- if (read_eeprom(sp, 0x7FC, &ret_data))
+ if (read_eeprom(sp, 0x7F0, &ret_data))
fail = 1;
- if (ret_data != 0x01234567)
+ if (ret_data != 0x012345) {
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
fail = 1;
+ }
/* Reset the EEPROM data go FFFF */
- write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+ write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
- /* Test Write Error at offset 0x80 */
- if (!write_eeprom(sp, 0x080, 0, 3))
- fail = 1;
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ /* Test Write Error at offset 0x80 */
+ if (!write_eeprom(sp, 0x080, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 0xfc */
- if (!write_eeprom(sp, 0x0FC, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0xfc */
+ if (!write_eeprom(sp, 0x0FC, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 0x100 */
- if (!write_eeprom(sp, 0x100, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 0x100 */
+ if (!write_eeprom(sp, 0x100, 0, 3))
+ fail = 1;
- /* Test Write Error at offset 4ec */
- if (!write_eeprom(sp, 0x4EC, 0, 3))
- fail = 1;
+ /* Test Write Error at offset 4ec */
+ if (!write_eeprom(sp, 0x4EC, 0, 3))
+ fail = 1;
+ }
+
+ /* Restore values at offsets 0x4F0 and 0x7F0 */
+ if (saved_4F0)
+ write_eeprom(sp, 0x4F0, org_4F0, 3);
+ if (saved_7F0)
+ write_eeprom(sp, 0x7F0, org_7F0, 3);
*data = fail;
- return 0;
+ return fail;
}
/**
* s2io_bist_test - invokes the MemBist test of the card .
- * @sp : private member of the device structure, which is a pointer to the
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @data:variable that returns the result of each of the test conducted by
+ * @data:variable that returns the result of each of the test conducted by
* the driver.
* Description:
* This invokes the MemBist test of the card. We give around
* 2 secs time for the Test to complete. If it's still not complete
- * within this peiod, we consider that the test failed.
+ * within this peiod, we consider that the test failed.
* Return value:
* 0 on success and -1 on failure.
*/
@@ -3697,13 +4779,13 @@ static int s2io_bist_test(nic_t * sp, uint64_t * data)
}
/**
- * s2io-link_test - verifies the link state of the nic
- * @sp ; private member of the device structure, which is a pointer to the
+ * s2io-link_test - verifies the link state of the nic
+ * @sp ; private member of the device structure, which is a pointer to the
* s2io_nic structure.
* @data: variable that returns the result of each of the test conducted by
* the driver.
* Description:
- * The function verifies the link state of the NIC and updates the input
+ * The function verifies the link state of the NIC and updates the input
* argument 'data' appropriately.
* Return value:
* 0 on success.
@@ -3722,13 +4804,13 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
}
/**
- * s2io_rldram_test - offline test for access to the RldRam chip on the NIC
- * @sp - private member of the device structure, which is a pointer to the
+ * s2io_rldram_test - offline test for access to the RldRam chip on the NIC
+ * @sp - private member of the device structure, which is a pointer to the
* s2io_nic structure.
- * @data - variable that returns the result of each of the test
+ * @data - variable that returns the result of each of the test
* conducted by the driver.
* Description:
- * This is one of the offline test that tests the read and write
+ * This is one of the offline test that tests the read and write
* access to the RldRam chip on the NIC.
* Return value:
* 0 on success.
@@ -3738,7 +4820,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
- int cnt, iteration = 0, test_pass = 0;
+ int cnt, iteration = 0, test_fail = 0;
val64 = readq(&bar0->adapter_control);
val64 &= ~ADAPTER_ECC_EN;
@@ -3746,7 +4828,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
val64 = readq(&bar0->mc_rldram_test_ctrl);
val64 |= MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
val64 = readq(&bar0->mc_rldram_mrs);
val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -3774,17 +4856,12 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
}
writeq(val64, &bar0->mc_rldram_test_d2);
- val64 = (u64) (0x0000003fffff0000ULL);
+ val64 = (u64) (0x0000003ffffe0100ULL);
writeq(val64, &bar0->mc_rldram_test_add);
-
- val64 = MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
-
- val64 |=
- MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
- MC_RLDRAM_TEST_GO;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+ MC_RLDRAM_TEST_GO;
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -3796,11 +4873,8 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
if (cnt == 5)
break;
- val64 = MC_RLDRAM_TEST_MODE;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
-
- val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
- writeq(val64, &bar0->mc_rldram_test_ctrl);
+ val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+ SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
for (cnt = 0; cnt < 5; cnt++) {
val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -3813,18 +4887,18 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
break;
val64 = readq(&bar0->mc_rldram_test_ctrl);
- if (val64 & MC_RLDRAM_TEST_PASS)
- test_pass = 1;
+ if (!(val64 & MC_RLDRAM_TEST_PASS))
+ test_fail = 1;
iteration++;
}
- if (!test_pass)
- *data = 1;
- else
- *data = 0;
+ *data = test_fail;
- return 0;
+ /* Bring the adapter out of test mode */
+ SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+
+ return test_fail;
}
/**
@@ -3833,7 +4907,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
* s2io_nic structure.
* @ethtest : pointer to a ethtool command specific structure that will be
* returned to the user.
- * @data : variable that returns the result of each of the test
+ * @data : variable that returns the result of each of the test
* conducted by the driver.
* Description:
* This function conducts 6 tests ( 4 offline and 2 online) to determine
@@ -3851,23 +4925,18 @@ static void s2io_ethtool_test(struct net_device *dev,
if (ethtest->flags == ETH_TEST_FL_OFFLINE) {
/* Offline Tests. */
- if (orig_state) {
+ if (orig_state)
s2io_close(sp->dev);
- s2io_set_swapper(sp);
- } else
- s2io_set_swapper(sp);
if (s2io_register_test(sp, &data[0]))
ethtest->flags |= ETH_TEST_FL_FAILED;
s2io_reset(sp);
- s2io_set_swapper(sp);
if (s2io_rldram_test(sp, &data[3]))
ethtest->flags |= ETH_TEST_FL_FAILED;
s2io_reset(sp);
- s2io_set_swapper(sp);
if (s2io_eeprom_test(sp, &data[1]))
ethtest->flags |= ETH_TEST_FL_FAILED;
@@ -3910,61 +4979,111 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
nic_t *sp = dev->priv;
StatInfo_t *stat_info = sp->mac_control.stats_info;
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+ s2io_updt_stats(sp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_data_octets);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_mcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_bcst_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_any_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_vld_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_drop_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_icmp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_rst_tcp);
tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
- tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->tmac_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_data_octets);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_vld_bcst_frms);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_discarded_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_usized_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_osized_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_frag_frms);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_jabber_frms);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_ip);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_drop_ip);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_icmp);
tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
- tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+ tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_err_drp_udp);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_pause_cnt);
+ tmp_stats[i++] =
+ (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
+ le32_to_cpu(stat_info->rmac_accepted_ip);
tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
+ tmp_stats[i++] = 0;
+ tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
+ tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
}
-static int s2io_ethtool_get_regs_len(struct net_device *dev)
+int s2io_ethtool_get_regs_len(struct net_device *dev)
{
return (XENA_REG_SPACE);
}
-static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
{
nic_t *sp = dev->priv;
return (sp->rx_csum);
}
-
-static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
{
nic_t *sp = dev->priv;
@@ -3975,19 +5094,17 @@ static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
-
-static int s2io_get_eeprom_len(struct net_device *dev)
+int s2io_get_eeprom_len(struct net_device *dev)
{
return (XENA_EEPROM_SPACE);
}
-static int s2io_ethtool_self_test_count(struct net_device *dev)
+int s2io_ethtool_self_test_count(struct net_device *dev)
{
return (S2IO_TEST_LEN);
}
-
-static void s2io_ethtool_get_strings(struct net_device *dev,
- u32 stringset, u8 * data)
+void s2io_ethtool_get_strings(struct net_device *dev,
+ u32 stringset, u8 * data)
{
switch (stringset) {
case ETH_SS_TEST:
@@ -3998,13 +5115,12 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
sizeof(ethtool_stats_keys));
}
}
-
static int s2io_ethtool_get_stats_count(struct net_device *dev)
{
return (S2IO_STAT_LEN);
}
-static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
{
if (data)
dev->features |= NETIF_F_IP_CSUM;
@@ -4046,21 +5162,18 @@ static struct ethtool_ops netdev_ethtool_ops = {
};
/**
- * s2io_ioctl - Entry point for the Ioctl
+ * s2io_ioctl - Entry point for the Ioctl
* @dev : Device pointer.
* @ifr : An IOCTL specefic structure, that can contain a pointer to
* a proprietary structure used to pass information to the driver.
* @cmd : This is used to distinguish between the different commands that
* can be passed to the IOCTL functions.
* Description:
- * This function has support for ethtool, adding multiple MAC addresses on
- * the NIC and some DBG commands for the util tool.
- * Return value:
- * Currently the IOCTL supports no operations, hence by default this
- * function returns OP NOT SUPPORTED value.
+ * Currently there are no special functionality supported in IOCTL, hence
+ * function always return EOPNOTSUPPORTED
*/
-static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
return -EOPNOTSUPP;
}
@@ -4076,17 +5189,9 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* file on failure.
*/
-static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+int s2io_change_mtu(struct net_device *dev, int new_mtu)
{
nic_t *sp = dev->priv;
- XENA_dev_config_t __iomem *bar0 = sp->bar0;
- register u64 val64;
-
- if (netif_running(dev)) {
- DBG_PRINT(ERR_DBG, "%s: Must be stopped to ", dev->name);
- DBG_PRINT(ERR_DBG, "change its MTU \n");
- return -EBUSY;
- }
if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
@@ -4094,11 +5199,22 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
return -EPERM;
}
- /* Set the new MTU into the PYLD register of the NIC */
- val64 = new_mtu;
- writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
-
dev->mtu = new_mtu;
+ if (netif_running(dev)) {
+ s2io_card_down(sp);
+ netif_stop_queue(dev);
+ if (s2io_card_up(sp)) {
+ DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ __FUNCTION__);
+ }
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ } else { /* Device is down */
+ XENA_dev_config_t __iomem *bar0 = sp->bar0;
+ u64 val64 = new_mtu;
+
+ writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
+ }
return 0;
}
@@ -4108,9 +5224,9 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
* @dev_adr : address of the device structure in dma_addr_t format.
* Description:
* This is the tasklet or the bottom half of the ISR. This is
- * an extension of the ISR which is scheduled by the scheduler to be run
+ * an extension of the ISR which is scheduled by the scheduler to be run
* when the load on the CPU is low. All low priority tasks of the ISR can
- * be pushed into the tasklet. For now the tasklet is used only to
+ * be pushed into the tasklet. For now the tasklet is used only to
* replenish the Rx buffers in the Rx buffer descriptors.
* Return value:
* void.
@@ -4166,19 +5282,22 @@ static void s2io_set_link(unsigned long data)
}
subid = nic->pdev->subsystem_device;
- /*
- * Allow a small delay for the NICs self initiated
- * cleanup to complete.
- */
- msleep(100);
+ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+ /*
+ * Allow a small delay for the NICs self initiated
+ * cleanup to complete.
+ */
+ msleep(100);
+ }
val64 = readq(&bar0->adapter_status);
- if (verify_xena_quiescence(val64, nic->device_enabled_once)) {
+ if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
if (LINK_IS_UP(val64)) {
val64 = readq(&bar0->adapter_control);
val64 |= ADAPTER_CNTL_EN;
writeq(val64, &bar0->adapter_control);
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+ subid)) {
val64 = readq(&bar0->gpio_control);
val64 |= GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -4187,20 +5306,24 @@ static void s2io_set_link(unsigned long data)
val64 |= ADAPTER_LED_ON;
writeq(val64, &bar0->adapter_control);
}
- val64 = readq(&bar0->adapter_status);
- if (!LINK_IS_UP(val64)) {
- DBG_PRINT(ERR_DBG, "%s:", dev->name);
- DBG_PRINT(ERR_DBG, " Link down");
- DBG_PRINT(ERR_DBG, "after ");
- DBG_PRINT(ERR_DBG, "enabling ");
- DBG_PRINT(ERR_DBG, "device \n");
+ if (s2io_link_fault_indication(nic) ==
+ MAC_RMAC_ERR_TIMER) {
+ val64 = readq(&bar0->adapter_status);
+ if (!LINK_IS_UP(val64)) {
+ DBG_PRINT(ERR_DBG, "%s:", dev->name);
+ DBG_PRINT(ERR_DBG, " Link down");
+ DBG_PRINT(ERR_DBG, "after ");
+ DBG_PRINT(ERR_DBG, "enabling ");
+ DBG_PRINT(ERR_DBG, "device \n");
+ }
}
if (nic->device_enabled_once == FALSE) {
nic->device_enabled_once = TRUE;
}
s2io_link(nic, LINK_UP);
} else {
- if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
+ if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
+ subid)) {
val64 = readq(&bar0->gpio_control);
val64 &= ~GPIO_CTRL_GPIO_0;
writeq(val64, &bar0->gpio_control);
@@ -4223,9 +5346,11 @@ static void s2io_card_down(nic_t * sp)
unsigned long flags;
register u64 val64 = 0;
+ del_timer_sync(&sp->alarm_timer);
/* If s2io_set_link task is executing, wait till it completes. */
- while (test_and_set_bit(0, &(sp->link_state)))
+ while (test_and_set_bit(0, &(sp->link_state))) {
msleep(50);
+ }
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
@@ -4237,7 +5362,7 @@ static void s2io_card_down(nic_t * sp)
/* Check if the device is Quiescent and then Reset the NIC */
do {
val64 = readq(&bar0->adapter_status);
- if (verify_xena_quiescence(val64, sp->device_enabled_once)) {
+ if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
break;
}
@@ -4251,20 +5376,33 @@ static void s2io_card_down(nic_t * sp)
break;
}
} while (1);
- spin_lock_irqsave(&sp->tx_lock, flags);
s2io_reset(sp);
- /* Free all unused Tx and Rx buffers */
+ /* Waiting till all Interrupt handlers are complete */
+ cnt = 0;
+ do {
+ msleep(10);
+ if (!atomic_read(&sp->isr_cnt))
+ break;
+ cnt++;
+ } while(cnt < 5);
+
+ spin_lock_irqsave(&sp->tx_lock, flags);
+ /* Free all Tx buffers */
free_tx_buffers(sp);
+ spin_unlock_irqrestore(&sp->tx_lock, flags);
+
+ /* Free all Rx buffers */
+ spin_lock_irqsave(&sp->rx_lock, flags);
free_rx_buffers(sp);
+ spin_unlock_irqrestore(&sp->rx_lock, flags);
- spin_unlock_irqrestore(&sp->tx_lock, flags);
clear_bit(0, &(sp->link_state));
}
static int s2io_card_up(nic_t * sp)
{
- int i, ret;
+ int i, ret = 0;
mac_info_t *mac_control;
struct config_param *config;
struct net_device *dev = (struct net_device *) sp->dev;
@@ -4276,8 +5414,17 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
- /*
- * Initializing the Rx buffers. For now we are considering only 1
+ if (sp->intr_type == MSI)
+ ret = s2io_enable_msi(sp);
+ else if (sp->intr_type == MSI_X)
+ ret = s2io_enable_msi_x(sp);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+ sp->intr_type = INTA;
+ }
+
+ /*
+ * Initializing the Rx buffers. For now we are considering only 1
* Rx ring and initializing buffers into 30 Rx blocks
*/
mac_control = &sp->mac_control;
@@ -4311,16 +5458,18 @@ static int s2io_card_up(nic_t * sp)
return -ENODEV;
}
+ S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+
atomic_set(&sp->card_state, CARD_UP);
return 0;
}
-/**
+/**
* s2io_restart_nic - Resets the NIC.
* @data : long pointer to the device private structure
* Description:
* This function is scheduled to be run by the s2io_tx_watchdog
- * function after 0.5 secs to reset the NIC. The idea is to reduce
+ * function after 0.5 secs to reset the NIC. The idea is to reduce
* the run time of the watch dog routine which is run holding a
* spin lock.
*/
@@ -4338,10 +5487,11 @@ static void s2io_restart_nic(unsigned long data)
netif_wake_queue(dev);
DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
dev->name);
+
}
-/**
- * s2io_tx_watchdog - Watchdog for transmit side.
+/**
+ * s2io_tx_watchdog - Watchdog for transmit side.
* @dev : Pointer to net device structure
* Description:
* This function is triggered if the Tx Queue is stopped
@@ -4369,7 +5519,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
* @len : length of the packet
* @cksum : FCS checksum of the frame.
* @ring_no : the ring from which this RxD was extracted.
- * Description:
+ * Description:
* This function is called by the Tx interrupt serivce routine to perform
* some OS related operations on the SKB before passing it to the upper
* layers. It mainly checks if the checksum is OK, if so adds it to the
@@ -4379,35 +5529,68 @@ static void s2io_tx_watchdog(struct net_device *dev)
* Return value:
* SUCCESS on success and -1 on failure.
*/
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no)
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
- buffAdd_t * ba)
-#endif
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
{
+ nic_t *sp = ring_data->nic;
struct net_device *dev = (struct net_device *) sp->dev;
- struct sk_buff *skb =
- (struct sk_buff *) ((unsigned long) rxdp->Host_Control);
+ struct sk_buff *skb = (struct sk_buff *)
+ ((unsigned long) rxdp->Host_Control);
+ int ring_no = ring_data->ring_no;
u16 l3_csum, l4_csum;
#ifdef CONFIG_2BUFF_MODE
- int buf0_len, buf2_len;
+ int buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
+ int buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
+ int get_block = ring_data->rx_curr_get_info.block_index;
+ int get_off = ring_data->rx_curr_get_info.offset;
+ buffAdd_t *ba = &ring_data->ba[get_block][get_off];
unsigned char *buff;
+#else
+ u16 len = (u16) ((RXD_GET_BUFFER0_SIZE(rxdp->Control_2)) >> 48);;
+#endif
+ skb->dev = dev;
+ if (rxdp->Control_1 & RXD_T_CODE) {
+ unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
+ DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+ dev->name, err);
+ dev_kfree_skb(skb);
+ sp->stats.rx_crc_errors++;
+ atomic_dec(&sp->rx_bufs_left[ring_no]);
+ rxdp->Host_Control = 0;
+ return 0;
+ }
+
+ /* Updating statistics */
+ rxdp->Host_Control = 0;
+ sp->rx_pkt_count++;
+ sp->stats.rx_packets++;
+#ifndef CONFIG_2BUFF_MODE
+ sp->stats.rx_bytes += len;
+#else
+ sp->stats.rx_bytes += buf0_len + buf2_len;
+#endif
+
+#ifndef CONFIG_2BUFF_MODE
+ skb_put(skb, len);
+#else
+ buff = skb_push(skb, buf0_len);
+ memcpy(buff, ba->ba_0, buf0_len);
+ skb_put(skb, buf2_len);
#endif
- l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
- if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) {
+ if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
+ (sp->rx_csum)) {
+ l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) {
- /*
+ /*
* NIC verifies if the Checksum of the received
* frame is Ok or not and accordingly returns
* a flag in the RxD.
*/
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
- /*
- * Packet with erroneous checksum, let the
+ /*
+ * Packet with erroneous checksum, let the
* upper layers deal with it.
*/
skb->ip_summed = CHECKSUM_NONE;
@@ -4416,44 +5599,26 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
skb->ip_summed = CHECKSUM_NONE;
}
- if (rxdp->Control_1 & RXD_T_CODE) {
- unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
- DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
- dev->name, err);
- }
-#ifdef CONFIG_2BUFF_MODE
- buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
- buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
-#endif
-
- skb->dev = dev;
-#ifndef CONFIG_2BUFF_MODE
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, dev);
-#else
- buff = skb_push(skb, buf0_len);
- memcpy(buff, ba->ba_0, buf0_len);
- skb_put(skb, buf2_len);
skb->protocol = eth_type_trans(skb, dev);
-#endif
-
#ifdef CONFIG_S2IO_NAPI
- netif_receive_skb(skb);
+ if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+ /* Queueing the vlan frame to the upper layer */
+ vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+ RXD_GET_VLAN_TAG(rxdp->Control_2));
+ } else {
+ netif_receive_skb(skb);
+ }
#else
- netif_rx(skb);
+ if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+ /* Queueing the vlan frame to the upper layer */
+ vlan_hwaccel_rx(skb, sp->vlgrp,
+ RXD_GET_VLAN_TAG(rxdp->Control_2));
+ } else {
+ netif_rx(skb);
+ }
#endif
-
dev->last_rx = jiffies;
- sp->rx_pkt_count++;
- sp->stats.rx_packets++;
-#ifndef CONFIG_2BUFF_MODE
- sp->stats.rx_bytes += len;
-#else
- sp->stats.rx_bytes += buf0_len + buf2_len;
-#endif
-
atomic_dec(&sp->rx_bufs_left[ring_no]);
- rxdp->Host_Control = 0;
return SUCCESS;
}
@@ -4464,13 +5629,13 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
* @link : inidicates whether link is UP/DOWN.
* Description:
* This function stops/starts the Tx queue depending on whether the link
- * status of the NIC is is down or up. This is called by the Alarm
- * interrupt handler whenever a link change interrupt comes up.
+ * status of the NIC is is down or up. This is called by the Alarm
+ * interrupt handler whenever a link change interrupt comes up.
* Return value:
* void.
*/
-static void s2io_link(nic_t * sp, int link)
+void s2io_link(nic_t * sp, int link)
{
struct net_device *dev = (struct net_device *) sp->dev;
@@ -4487,8 +5652,25 @@ static void s2io_link(nic_t * sp, int link)
}
/**
- * s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
- * @sp : private member of the device structure, which is a pointer to the
+ * get_xena_rev_id - to identify revision ID of xena.
+ * @pdev : PCI Dev structure
+ * Description:
+ * Function to identify the Revision ID of xena.
+ * Return value:
+ * returns the revision ID of the device.
+ */
+
+int get_xena_rev_id(struct pci_dev *pdev)
+{
+ u8 id = 0;
+ int ret;
+ ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
+ return id;
+}
+
+/**
+ * s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
+ * @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
* Description:
* This function initializes a few of the PCI and PCI-X configuration registers
@@ -4499,15 +5681,15 @@ static void s2io_link(nic_t * sp, int link)
static void s2io_init_pci(nic_t * sp)
{
- u16 pci_cmd = 0;
+ u16 pci_cmd = 0, pcix_cmd = 0;
/* Enable Data Parity Error Recovery in PCI-X command register. */
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- (sp->pcix_cmd | 1));
+ (pcix_cmd | 1));
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
/* Set the PErr Response bit in PCI command register. */
pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
@@ -4515,53 +5697,46 @@ static void s2io_init_pci(nic_t * sp)
(pci_cmd | PCI_COMMAND_PARITY));
pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
- /* Set MMRB count to 1024 in PCI-X Command register. */
- sp->pcix_cmd &= 0xFFF3;
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, (sp->pcix_cmd | (0x1 << 2))); /* MMRBC 1K */
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
-
- /* Setting Maximum outstanding splits based on system type. */
- sp->pcix_cmd &= 0xFF8F;
-
- sp->pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1); /* 2 splits. */
- pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- sp->pcix_cmd);
- pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
/* Forcibly disabling relaxed ordering capability of the card. */
- sp->pcix_cmd &= 0xfffd;
+ pcix_cmd &= 0xfffd;
pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- sp->pcix_cmd);
+ pcix_cmd);
pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
- &(sp->pcix_cmd));
+ &(pcix_cmd));
}
MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
module_param(tx_fifo_num, int, 0);
-module_param_array(tx_fifo_len, int, NULL, 0);
module_param(rx_ring_num, int, 0);
-module_param_array(rx_ring_sz, int, NULL, 0);
-module_param(Stats_refresh_time, int, 0);
+module_param_array(tx_fifo_len, uint, NULL, 0);
+module_param_array(rx_ring_sz, uint, NULL, 0);
+module_param_array(rts_frm_len, uint, NULL, 0);
+module_param(use_continuous_tx_intrs, int, 1);
module_param(rmac_pause_time, int, 0);
module_param(mc_pause_threshold_q0q3, int, 0);
module_param(mc_pause_threshold_q4q7, int, 0);
module_param(shared_splits, int, 0);
module_param(tmac_util_period, int, 0);
module_param(rmac_util_period, int, 0);
+module_param(bimodal, bool, 0);
#ifndef CONFIG_S2IO_NAPI
module_param(indicate_max_pkts, int, 0);
#endif
+module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
+
/**
- * s2io_init_nic - Initialization of the adapter .
+ * s2io_init_nic - Initialization of the adapter .
* @pdev : structure containing the PCI related information of the device.
* @pre: List of PCI devices supported by the driver listed in s2io_tbl.
* Description:
* The function initializes an adapter identified by the pci_dec structure.
- * All OS related initialization including memory and device structure and
- * initlaization of the device private variable is done. Also the swapper
- * control register is initialized to enable read and write into the I/O
+ * All OS related initialization including memory and device structure and
+ * initlaization of the device private variable is done. Also the swapper
+ * control register is initialized to enable read and write into the I/O
* registers of the device.
* Return value:
* returns 0 on success and negative on failure.
@@ -4572,7 +5747,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
{
nic_t *sp;
struct net_device *dev;
- char *dev_name = "S2IO 10GE NIC";
int i, j, ret;
int dma_flag = FALSE;
u32 mac_up, mac_down;
@@ -4581,10 +5755,18 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
u16 subid;
mac_info_t *mac_control;
struct config_param *config;
+ int mode;
+ u8 dev_intr_type = intr_type;
-
- DBG_PRINT(ERR_DBG, "Loading S2IO driver with %s\n",
- s2io_driver_version);
+#ifdef CONFIG_S2IO_NAPI
+ if (dev_intr_type != INTA) {
+ DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+ dev_intr_type = INTA;
+ }
+ else
+ DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+#endif
if ((ret = pci_enable_device(pdev))) {
DBG_PRINT(ERR_DBG,
@@ -4595,7 +5777,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
dma_flag = TRUE;
-
if (pci_set_consistent_dma_mask
(pdev, DMA_64BIT_MASK)) {
DBG_PRINT(ERR_DBG,
@@ -4611,10 +5792,35 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
return -ENOMEM;
}
- if (pci_request_regions(pdev, s2io_driver_name)) {
- DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
- pci_disable_device(pdev);
- return -ENODEV;
+ if ((dev_intr_type == MSI_X) &&
+ ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+ (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+ DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+ dev_intr_type = INTA;
+ }
+ if (dev_intr_type != MSI_X) {
+ if (pci_request_regions(pdev, s2io_driver_name)) {
+ DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+ }
+ else {
+ if (!(request_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0), s2io_driver_name))) {
+ DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+ if (!(request_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2), s2io_driver_name))) {
+ DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
}
dev = alloc_etherdev(sizeof(nic_t));
@@ -4635,34 +5841,43 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
memset(sp, 0, sizeof(nic_t));
sp->dev = dev;
sp->pdev = pdev;
- sp->vendor_id = pdev->vendor;
- sp->device_id = pdev->device;
sp->high_dma_flag = dma_flag;
- sp->irq = pdev->irq;
sp->device_enabled_once = FALSE;
- strcpy(sp->name, dev_name);
+ sp->intr_type = dev_intr_type;
+
+ if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
+ (pdev->device == PCI_DEVICE_ID_HERC_UNI))
+ sp->device_type = XFRAME_II_DEVICE;
+ else
+ sp->device_type = XFRAME_I_DEVICE;
+
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
- /*
+ /*
* Setting the device configuration parameters.
- * Most of these parameters can be specified by the user during
- * module insertion as they are module loadable parameters. If
- * these parameters are not not specified during load time, they
+ * Most of these parameters can be specified by the user during
+ * module insertion as they are module loadable parameters. If
+ * these parameters are not not specified during load time, they
* are initialized with default values.
*/
mac_control = &sp->mac_control;
config = &sp->config;
/* Tx side parameters. */
- tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
+ if (tx_fifo_len[0] == 0)
+ tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
config->tx_fifo_num = tx_fifo_num;
for (i = 0; i < MAX_TX_FIFOS; i++) {
config->tx_cfg[i].fifo_len = tx_fifo_len[i];
config->tx_cfg[i].fifo_priority = i;
}
+ /* mapping the QoS priority to the configured fifos */
+ for (i = 0; i < MAX_TX_FIFOS; i++)
+ config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
+
config->tx_intr_type = TXD_INT_TYPE_UTILZ;
for (i = 0; i < config->tx_fifo_num; i++) {
config->tx_cfg[i].f_no_snoop =
@@ -4672,10 +5887,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
break;
}
}
- config->max_txds = MAX_SKB_FRAGS;
+ config->max_txds = MAX_SKB_FRAGS + 1;
/* Rx side parameters. */
- rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
+ if (rx_ring_sz[0] == 0)
+ rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
config->rx_ring_num = rx_ring_num;
for (i = 0; i < MAX_RX_RINGS; i++) {
config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -4699,10 +5915,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
for (i = 0; i < config->rx_ring_num; i++)
atomic_set(&sp->rx_bufs_left[i], 0);
+ /* Initialize the number of ISRs currently running */
+ atomic_set(&sp->isr_cnt, 0);
+
/* initialize the shared memory used by the NIC and the host */
if (init_shared_mem(sp)) {
DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
- dev->name);
+ __FUNCTION__);
ret = -ENOMEM;
goto mem_alloc_failed;
}
@@ -4743,13 +5962,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->do_ioctl = &s2io_ioctl;
dev->change_mtu = &s2io_change_mtu;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_rx_register = s2io_vlan_rx_register;
+ dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
+
/*
* will use eth_mac_addr() for dev->set_mac_address
* mac address will be set every time dev->open() is called
*/
-#ifdef CONFIG_S2IO_NAPI
+#if defined(CONFIG_S2IO_NAPI)
dev->poll = s2io_poll;
- dev->weight = 90;
+ dev->weight = 32;
#endif
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
@@ -4776,22 +5999,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto set_swap_failed;
}
- /* Fix for all "FFs" MAC address problems observed on Alpha platforms */
- fix_mac_address(sp);
- s2io_reset(sp);
+ /* Verify if the Herc works on the slot its placed into */
+ 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, " Unsupported PCI bus mode\n");
+ ret = -EBADSLT;
+ goto set_swap_failed;
+ }
+ }
- /*
- * Setting swapper control on the NIC, so the MAC address can be read.
- */
- if (s2io_set_swapper(sp)) {
- DBG_PRINT(ERR_DBG,
- "%s: S2IO: swapper settings are wrong\n",
- dev->name);
- ret = -EAGAIN;
- goto set_swap_failed;
+ /* Not needed for Herc */
+ if (sp->device_type & XFRAME_I_DEVICE) {
+ /*
+ * Fix for all "FFs" MAC address problems observed on
+ * Alpha platforms
+ */
+ fix_mac_address(sp);
+ s2io_reset(sp);
}
- /*
+ /*
* MAC address initialization.
* For now only one mac address will be read and used.
*/
@@ -4814,37 +6043,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);
sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24);
- DBG_PRINT(INIT_DBG,
- "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n",
- sp->def_mac_addr[0].mac_addr[0],
- sp->def_mac_addr[0].mac_addr[1],
- sp->def_mac_addr[0].mac_addr[2],
- sp->def_mac_addr[0].mac_addr[3],
- sp->def_mac_addr[0].mac_addr[4],
- sp->def_mac_addr[0].mac_addr[5]);
-
/* Set the factory defined MAC address initially */
dev->addr_len = ETH_ALEN;
memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
/*
- * Initialize the tasklet status and link state flags
- * and the card statte parameter
+ * Initialize the tasklet status and link state flags
+ * and the card state parameter
*/
atomic_set(&(sp->card_state), 0);
sp->tasklet_status = 0;
sp->link_state = 0;
-
/* Initialize spinlocks */
spin_lock_init(&sp->tx_lock);
#ifndef CONFIG_S2IO_NAPI
spin_lock_init(&sp->put_lock);
#endif
+ spin_lock_init(&sp->rx_lock);
- /*
- * SXE-002: Configure link and activity LED to init state
- * on driver load.
+ /*
+ * SXE-002: Configure link and activity LED to init state
+ * on driver load.
*/
subid = sp->pdev->subsystem_device;
if ((subid & 0xFF) >= 0x07) {
@@ -4864,13 +6084,92 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto register_failed;
}
- /*
- * Make Link state as off at this point, when the Link change
- * interrupt comes the state will be automatically changed to
+ if (sp->device_type & XFRAME_II_DEVICE) {
+ DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+ get_xena_rev_id(sp->pdev),
+ s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+ DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+ switch(sp->intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, ", Intr type INTA");
+ break;
+ case MSI:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI");
+ break;
+ case MSI_X:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+ break;
+ }
+
+ DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+ DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ sp->def_mac_addr[0].mac_addr[0],
+ sp->def_mac_addr[0].mac_addr[1],
+ sp->def_mac_addr[0].mac_addr[2],
+ sp->def_mac_addr[0].mac_addr[3],
+ sp->def_mac_addr[0].mac_addr[4],
+ sp->def_mac_addr[0].mac_addr[5]);
+ mode = s2io_print_pci_mode(sp);
+ if (mode < 0) {
+ DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+ ret = -EBADSLT;
+ goto set_swap_failed;
+ }
+ } else {
+ DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+ get_xena_rev_id(sp->pdev),
+ s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+ DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+ switch(sp->intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, ", Intr type INTA");
+ break;
+ case MSI:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI");
+ break;
+ case MSI_X:
+ DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+ break;
+ }
+ DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
+ DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ sp->def_mac_addr[0].mac_addr[0],
+ sp->def_mac_addr[0].mac_addr[1],
+ sp->def_mac_addr[0].mac_addr[2],
+ sp->def_mac_addr[0].mac_addr[3],
+ sp->def_mac_addr[0].mac_addr[4],
+ sp->def_mac_addr[0].mac_addr[5]);
+ }
+
+ /* Initialize device name */
+ strcpy(sp->name, dev->name);
+ if (sp->device_type & XFRAME_II_DEVICE)
+ strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
+ else
+ strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+
+ /* Initialize bimodal Interrupts */
+ sp->config.bimodal = bimodal;
+ if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
+ sp->config.bimodal = 0;
+ DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
+ dev->name);
+ }
+
+ /*
+ * Make Link state as off at this point, when the Link change
+ * interrupt comes the state will be automatically changed to
* the right state.
*/
netif_carrier_off(dev);
- sp->last_link_state = LINK_DOWN;
return 0;
@@ -4883,7 +6182,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
mem_alloc_failed:
free_shared_mem(sp);
pci_disable_device(pdev);
- pci_release_regions(pdev);
+ if (dev_intr_type != MSI_X)
+ pci_release_regions(pdev);
+ else {
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ release_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ }
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
@@ -4891,11 +6197,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
}
/**
- * s2io_rem_nic - Free the PCI device
+ * s2io_rem_nic - Free the PCI device
* @pdev: structure containing the PCI related information of the device.
- * Description: This function is called by the Pci subsystem to release a
+ * Description: This function is called by the Pci subsystem to release a
* PCI device and free up all resource held up by the device. This could
- * be in response to a Hot plug event or when the driver is to be removed
+ * be in response to a Hot plug event or when the driver is to be removed
* from memory.
*/
@@ -4917,9 +6223,15 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
iounmap(sp->bar0);
iounmap(sp->bar1);
pci_disable_device(pdev);
- pci_release_regions(pdev);
+ if (sp->intr_type != MSI_X)
+ pci_release_regions(pdev);
+ else {
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ release_mem_region(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ }
pci_set_drvdata(pdev, NULL);
-
free_netdev(dev);
}
@@ -4935,11 +6247,11 @@ int __init s2io_starter(void)
}
/**
- * s2io_closer - Cleanup routine for the driver
+ * s2io_closer - Cleanup routine for the driver
* Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
*/
-static void s2io_closer(void)
+void s2io_closer(void)
{
pci_unregister_driver(&s2io_driver);
DBG_PRINT(INIT_DBG, "cleanup done\n");
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 1711c8c3dc99..1cc24b56760e 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -1,5 +1,5 @@
/************************************************************************
- * s2io.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.h: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
* Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
@@ -31,6 +31,9 @@
#define SUCCESS 0
#define FAILURE -1
+/* Maximum time to flicker LED when asked to identify NIC using ethtool */
+#define MAX_FLICKER_TIME 60000 /* 60 Secs */
+
/* Maximum outstanding splits to be configured into xena. */
typedef enum xena_max_outstanding_splits {
XENA_ONE_SPLIT_TRANSACTION = 0,
@@ -45,10 +48,10 @@ typedef enum xena_max_outstanding_splits {
#define XENA_MAX_OUTSTANDING_SPLITS(n) (n << 4)
/* OS concerned variables and constants */
-#define WATCH_DOG_TIMEOUT 5*HZ
-#define EFILL 0x1234
-#define ALIGN_SIZE 127
-#define PCIX_COMMAND_REGISTER 0x62
+#define WATCH_DOG_TIMEOUT 15*HZ
+#define EFILL 0x1234
+#define ALIGN_SIZE 127
+#define PCIX_COMMAND_REGISTER 0x62
/*
* Debug related variables.
@@ -61,7 +64,7 @@ typedef enum xena_max_outstanding_splits {
#define INTR_DBG 4
/* Global variable that defines the present debug level of the driver. */
-static int debug_level = ERR_DBG; /* Default level. */
+int debug_level = ERR_DBG; /* Default level. */
/* DEBUG message print. */
#define DBG_PRINT(dbg_level, args...) if(!(debug_level<dbg_level)) printk(args)
@@ -71,6 +74,12 @@ static int debug_level = ERR_DBG; /* Default level. */
#define L4_CKSUM_OK 0xFFFF
#define S2IO_JUMBO_SIZE 9600
+/* Driver statistics maintained by driver */
+typedef struct {
+ unsigned long long single_ecc_errs;
+ unsigned long long double_ecc_errs;
+} swStat_t;
+
/* The statistics block of Xena */
typedef struct stat_block {
/* Tx MAC statistics counters. */
@@ -186,12 +195,90 @@ typedef struct stat_block {
u32 rxd_rd_cnt;
u32 rxf_wr_cnt;
u32 txf_rd_cnt;
+
+/* Tx MAC statistics overflow counters. */
+ u32 tmac_data_octets_oflow;
+ u32 tmac_frms_oflow;
+ u32 tmac_bcst_frms_oflow;
+ u32 tmac_mcst_frms_oflow;
+ u32 tmac_ucst_frms_oflow;
+ u32 tmac_ttl_octets_oflow;
+ u32 tmac_any_err_frms_oflow;
+ u32 tmac_nucst_frms_oflow;
+ u64 tmac_vlan_frms;
+ u32 tmac_drop_ip_oflow;
+ u32 tmac_vld_ip_oflow;
+ u32 tmac_rst_tcp_oflow;
+ u32 tmac_icmp_oflow;
+ u32 tpa_unknown_protocol;
+ u32 tmac_udp_oflow;
+ u32 reserved_10;
+ u32 tpa_parse_failure;
+
+/* Rx MAC Statistics overflow counters. */
+ u32 rmac_data_octets_oflow;
+ u32 rmac_vld_frms_oflow;
+ u32 rmac_vld_bcst_frms_oflow;
+ u32 rmac_vld_mcst_frms_oflow;
+ u32 rmac_accepted_ucst_frms_oflow;
+ u32 rmac_ttl_octets_oflow;
+ u32 rmac_discarded_frms_oflow;
+ u32 rmac_accepted_nucst_frms_oflow;
+ u32 rmac_usized_frms_oflow;
+ u32 rmac_drop_events_oflow;
+ u32 rmac_frag_frms_oflow;
+ u32 rmac_osized_frms_oflow;
+ u32 rmac_ip_oflow;
+ u32 rmac_jabber_frms_oflow;
+ u32 rmac_icmp_oflow;
+ u32 rmac_drop_ip_oflow;
+ u32 rmac_err_drp_udp_oflow;
+ u32 rmac_udp_oflow;
+ u32 reserved_11;
+ u32 rmac_pause_cnt_oflow;
+ u64 rmac_ttl_1519_4095_frms;
+ u64 rmac_ttl_4096_8191_frms;
+ u64 rmac_ttl_8192_max_frms;
+ u64 rmac_ttl_gt_max_frms;
+ u64 rmac_osized_alt_frms;
+ u64 rmac_jabber_alt_frms;
+ u64 rmac_gt_max_alt_frms;
+ u64 rmac_vlan_frms;
+ u32 rmac_len_discard;
+ u32 rmac_fcs_discard;
+ u32 rmac_pf_discard;
+ u32 rmac_da_discard;
+ u32 rmac_red_discard;
+ u32 rmac_rts_discard;
+ u32 reserved_12;
+ u32 rmac_ingm_full_discard;
+ u32 reserved_13;
+ u32 rmac_accepted_ip_oflow;
+ u32 reserved_14;
+ u32 link_fault_cnt;
+ swStat_t sw_stat;
} StatInfo_t;
-/* Structures representing different init time configuration
+/*
+ * Structures representing different init time configuration
* parameters of the NIC.
*/
+#define MAX_TX_FIFOS 8
+#define MAX_RX_RINGS 8
+
+/* FIFO mappings for all possible number of fifos configured */
+int fifo_map[][MAX_TX_FIFOS] = {
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 1},
+ {0, 0, 0, 1, 1, 1, 2, 2},
+ {0, 0, 1, 1, 2, 2, 3, 3},
+ {0, 0, 1, 1, 2, 2, 3, 4},
+ {0, 0, 1, 1, 2, 3, 4, 5},
+ {0, 0, 1, 2, 3, 4, 5, 6},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+};
+
/* Maintains Per FIFO related information. */
typedef struct tx_fifo_config {
#define MAX_AVAILABLE_TXDS 8192
@@ -237,14 +324,14 @@ typedef struct rx_ring_config {
#define NO_SNOOP_RXD_BUFFER 0x02
} rx_ring_config_t;
-/* This structure provides contains values of the tunable parameters
- * of the H/W
+/* This structure provides contains values of the tunable parameters
+ * of the H/W
*/
struct config_param {
/* Tx Side */
u32 tx_fifo_num; /*Number of Tx FIFOs */
-#define MAX_TX_FIFOS 8
+ u8 fifo_mapping[MAX_TX_FIFOS];
tx_fifo_config_t tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */
u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */
u64 tx_intr_type;
@@ -252,10 +339,10 @@ struct config_param {
/* Rx Side */
u32 rx_ring_num; /*Number of receive rings */
-#define MAX_RX_RINGS 8
#define MAX_RX_BLOCKS_PER_RING 150
rx_ring_config_t rx_cfg[MAX_RX_RINGS]; /*Per-Rx Ring config */
+ u8 bimodal; /*Flag for setting bimodal interrupts*/
#define HEADER_ETHERNET_II_802_3_SIZE 14
#define HEADER_802_2_SIZE 3
@@ -269,6 +356,7 @@ struct config_param {
#define MAX_PYLD_JUMBO 9600
#define MAX_MTU_JUMBO (MAX_PYLD_JUMBO+18)
#define MAX_MTU_JUMBO_VLAN (MAX_PYLD_JUMBO+22)
+ u16 bus_speed;
};
/* Structure representing MAC Addrs */
@@ -277,7 +365,7 @@ typedef struct mac_addr {
} macaddr_t;
/* Structure that represent every FIFO element in the BAR1
- * Address location.
+ * Address location.
*/
typedef struct _TxFIFO_element {
u64 TxDL_Pointer;
@@ -339,6 +427,7 @@ typedef struct _RxD_t {
#define RXD_FRAME_PROTO vBIT(0xFFFF,24,8)
#define RXD_FRAME_PROTO_IPV4 BIT(27)
#define RXD_FRAME_PROTO_IPV6 BIT(28)
+#define RXD_FRAME_IP_FRAG BIT(29)
#define RXD_FRAME_PROTO_TCP BIT(30)
#define RXD_FRAME_PROTO_UDP BIT(31)
#define TCP_OR_UDP_FRAME (RXD_FRAME_PROTO_TCP | RXD_FRAME_PROTO_UDP)
@@ -346,11 +435,15 @@ typedef struct _RxD_t {
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
u64 Control_2;
+#define THE_RXD_MARK 0x3
+#define SET_RXD_MARKER vBIT(THE_RXD_MARK, 0, 2)
+#define GET_RXD_MARKER(ctrl) ((ctrl & SET_RXD_MARKER) >> 62)
+
#ifndef CONFIG_2BUFF_MODE
-#define MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16)
-#define SET_BUFFER0_SIZE(val) vBIT(val,0,16)
+#define MASK_BUFFER0_SIZE vBIT(0x3FFF,2,14)
+#define SET_BUFFER0_SIZE(val) vBIT(val,2,14)
#else
-#define MASK_BUFFER0_SIZE vBIT(0xFF,0,16)
+#define MASK_BUFFER0_SIZE vBIT(0xFF,2,14)
#define MASK_BUFFER1_SIZE vBIT(0xFFFF,16,16)
#define MASK_BUFFER2_SIZE vBIT(0xFFFF,32,16)
#define SET_BUFFER0_SIZE(val) vBIT(val,8,8)
@@ -363,7 +456,7 @@ typedef struct _RxD_t {
#define SET_NUM_TAG(val) vBIT(val,16,32)
#ifndef CONFIG_2BUFF_MODE
-#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0xFFFF,0,16)))
+#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0x3FFF,2,14)))
#else
#define RXD_GET_BUFFER0_SIZE(Control_2) (u8)((Control_2 & MASK_BUFFER0_SIZE) \
>> 48)
@@ -382,7 +475,7 @@ typedef struct _RxD_t {
#endif
} RxD_t;
-/* Structure that represents the Rx descriptor block which contains
+/* Structure that represents the Rx descriptor block which contains
* 128 Rx descriptors.
*/
#ifndef CONFIG_2BUFF_MODE
@@ -392,11 +485,11 @@ typedef struct _RxD_block {
u64 reserved_0;
#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
- u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last
+ u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last
* Rxd in this blk */
u64 reserved_2_pNext_RxD_block; /* Logical ptr to next */
u64 pNext_RxD_Blk_physical; /* Buff0_ptr.In a 32 bit arch
- * the upper 32 bits should
+ * the upper 32 bits should
* be 0 */
} RxD_block_t;
#else
@@ -405,13 +498,13 @@ typedef struct _RxD_block {
RxD_t rxd[MAX_RXDS_PER_BLOCK];
#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
- u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
+ u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
* in this blk */
u64 pNext_RxD_Blk_physical; /* Phy ponter to next blk. */
} RxD_block_t;
#define SIZE_OF_BLOCK 4096
-/* Structure to hold virtual addresses of Buf0 and Buf1 in
+/* Structure to hold virtual addresses of Buf0 and Buf1 in
* 2buf mode. */
typedef struct bufAdd {
void *ba_0_org;
@@ -423,8 +516,8 @@ typedef struct bufAdd {
/* Structure which stores all the MAC control parameters */
-/* This structure stores the offset of the RxD in the ring
- * from which the Rx Interrupt processor can start picking
+/* This structure stores the offset of the RxD in the ring
+ * from which the Rx Interrupt processor can start picking
* up the RxDs for processing.
*/
typedef struct _rx_curr_get_info_t {
@@ -436,7 +529,7 @@ typedef struct _rx_curr_get_info_t {
typedef rx_curr_get_info_t rx_curr_put_info_t;
/* This structure stores the offset of the TxDl in the FIFO
- * from which the Tx Interrupt processor can start picking
+ * from which the Tx Interrupt processor can start picking
* up the TxDLs for send complete interrupt processing.
*/
typedef struct {
@@ -446,32 +539,99 @@ typedef struct {
typedef tx_curr_get_info_t tx_curr_put_info_t;
-/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
- * is maintained in this structure.
- */
-typedef struct mac_info {
-/* rx side stuff */
- /* Put pointer info which indictes which RxD has to be replenished
+/* Structure that holds the Phy and virt addresses of the Blocks */
+typedef struct rx_block_info {
+ RxD_t *block_virt_addr;
+ dma_addr_t block_dma_addr;
+} rx_block_info_t;
+
+/* pre declaration of the nic structure */
+typedef struct s2io_nic nic_t;
+
+/* Ring specific structure */
+typedef struct ring_info {
+ /* The ring number */
+ int ring_no;
+
+ /*
+ * Place holders for the virtual and physical addresses of
+ * all the Rx Blocks
+ */
+ rx_block_info_t rx_blocks[MAX_RX_BLOCKS_PER_RING];
+ int block_count;
+ int pkt_cnt;
+
+ /*
+ * Put pointer info which indictes which RxD has to be replenished
* with a new buffer.
*/
- rx_curr_put_info_t rx_curr_put_info[MAX_RX_RINGS];
+ rx_curr_put_info_t rx_curr_put_info;
- /* Get pointer info which indictes which is the last RxD that was
+ /*
+ * Get pointer info which indictes which is the last RxD that was
* processed by the driver.
*/
- rx_curr_get_info_t rx_curr_get_info[MAX_RX_RINGS];
+ rx_curr_get_info_t rx_curr_get_info;
- u16 rmac_pause_time;
- u16 mc_pause_threshold_q0q3;
- u16 mc_pause_threshold_q4q7;
+#ifndef CONFIG_S2IO_NAPI
+ /* Index to the absolute position of the put pointer of Rx ring */
+ int put_pos;
+#endif
+
+#ifdef CONFIG_2BUFF_MODE
+ /* Buffer Address store. */
+ buffAdd_t **ba;
+#endif
+ nic_t *nic;
+} ring_info_t;
+
+/* Fifo specific structure */
+typedef struct fifo_info {
+ /* FIFO number */
+ int fifo_no;
+
+ /* Maximum TxDs per TxDL */
+ int max_txds;
+
+ /* Place holder of all the TX List's Phy and Virt addresses. */
+ list_info_hold_t *list_info;
+ /*
+ * Current offset within the tx FIFO where driver would write
+ * new Tx frame
+ */
+ tx_curr_put_info_t tx_curr_put_info;
+
+ /*
+ * Current offset within tx FIFO from where the driver would start freeing
+ * the buffers
+ */
+ tx_curr_get_info_t tx_curr_get_info;
+
+ nic_t *nic;
+}fifo_info_t;
+
+/* Infomation related to the Tx and Rx FIFOs and Rings of Xena
+ * is maintained in this structure.
+ */
+typedef struct mac_info {
/* tx side stuff */
/* logical pointer of start of each Tx FIFO */
TxFIFO_element_t __iomem *tx_FIFO_start[MAX_TX_FIFOS];
-/* Current offset within tx_FIFO_start, where driver would write new Tx frame*/
- tx_curr_put_info_t tx_curr_put_info[MAX_TX_FIFOS];
- tx_curr_get_info_t tx_curr_get_info[MAX_TX_FIFOS];
+ /* Fifo specific structure */
+ fifo_info_t fifos[MAX_TX_FIFOS];
+
+ /* Save virtual address of TxD page with zero DMA addr(if any) */
+ void *zerodma_virt_addr;
+
+/* rx side stuff */
+ /* Ring specific structure */
+ ring_info_t rings[MAX_RX_RINGS];
+
+ u16 rmac_pause_time;
+ u16 mc_pause_threshold_q0q3;
+ u16 mc_pause_threshold_q4q7;
void *stats_mem; /* orignal pointer to allocated mem */
dma_addr_t stats_mem_phy; /* Physical address of the stat block */
@@ -485,12 +645,6 @@ typedef struct {
int usage_cnt;
} usr_addr_t;
-/* Structure that holds the Phy and virt addresses of the Blocks */
-typedef struct rx_block_info {
- RxD_t *block_virt_addr;
- dma_addr_t block_dma_addr;
-} rx_block_info_t;
-
/* Default Tunable parameters of the NIC. */
#define DEFAULT_FIFO_LEN 4096
#define SMALL_RXD_CNT 30 * (MAX_RXDS_PER_BLOCK+1)
@@ -498,8 +652,45 @@ typedef struct rx_block_info {
#define SMALL_BLK_CNT 30
#define LARGE_BLK_CNT 100
+/*
+ * Structure to keep track of the MSI-X vectors and the corresponding
+ * argument registered against each vector
+ */
+#define MAX_REQUESTED_MSI_X 17
+struct s2io_msix_entry
+{
+ u16 vector;
+ u16 entry;
+ void *arg;
+
+ u8 type;
+#define MSIX_FIFO_TYPE 1
+#define MSIX_RING_TYPE 2
+
+ u8 in_use;
+#define MSIX_REGISTERED_SUCCESS 0xAA
+};
+
+struct msix_info_st {
+ u64 addr;
+ u64 data;
+};
+
/* Structure representing one instance of the NIC */
-typedef struct s2io_nic {
+struct s2io_nic {
+#ifdef CONFIG_S2IO_NAPI
+ /*
+ * Count of packets to be processed in a given iteration, it will be indicated
+ * by the quota field of the device structure when NAPI is enabled.
+ */
+ int pkts_to_process;
+#endif
+ struct net_device *dev;
+ mac_info_t mac_control;
+ struct config_param config;
+ struct pci_dev *pdev;
+ void __iomem *bar0;
+ void __iomem *bar1;
#define MAX_MAC_SUPPORTED 16
#define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
@@ -507,33 +698,20 @@ typedef struct s2io_nic {
macaddr_t pre_mac_addr[MAX_MAC_SUPPORTED];
struct net_device_stats stats;
- void __iomem *bar0;
- void __iomem *bar1;
- struct config_param config;
- mac_info_t mac_control;
int high_dma_flag;
int device_close_flag;
int device_enabled_once;
- char name[32];
+ char name[50];
struct tasklet_struct task;
volatile unsigned long tasklet_status;
- struct timer_list timer;
- struct net_device *dev;
- struct pci_dev *pdev;
- u16 vendor_id;
- u16 device_id;
- u16 ccmd;
- u32 cbar0_1;
- u32 cbar0_2;
- u32 cbar1_1;
- u32 cbar1_2;
- u32 cirq;
- u8 cache_line;
- u32 rom_expansion;
- u16 pcix_cmd;
- u32 irq;
+ /* Timer that handles I/O errors/exceptions */
+ struct timer_list alarm_timer;
+
+ /* Space to back up the PCI config space */
+ u32 config_space[256 / sizeof(u32)];
+
atomic_t rx_bufs_left[MAX_RX_RINGS];
spinlock_t tx_lock;
@@ -558,43 +736,22 @@ typedef struct s2io_nic {
u16 tx_err_count;
u16 rx_err_count;
-#ifndef CONFIG_S2IO_NAPI
- /* Index to the absolute position of the put pointer of Rx ring. */
- int put_pos[MAX_RX_RINGS];
-#endif
-
- /*
- * Place holders for the virtual and physical addresses of
- * all the Rx Blocks
- */
- rx_block_info_t rx_blocks[MAX_RX_RINGS][MAX_RX_BLOCKS_PER_RING];
- int block_count[MAX_RX_RINGS];
- int pkt_cnt[MAX_RX_RINGS];
-
- /* Place holder of all the TX List's Phy and Virt addresses. */
- list_info_hold_t *list_info[MAX_TX_FIFOS];
-
/* Id timer, used to blink NIC to physically identify NIC. */
struct timer_list id_timer;
/* Restart timer, used to restart NIC if the device is stuck and
- * a schedule task that will set the correct Link state once the
+ * a schedule task that will set the correct Link state once the
* NIC's PHY has stabilized after a state change.
*/
-#ifdef INIT_TQUEUE
- struct tq_struct rst_timer_task;
- struct tq_struct set_link_task;
-#else
struct work_struct rst_timer_task;
struct work_struct set_link_task;
-#endif
- /* Flag that can be used to turn on or turn off the Rx checksum
+ /* Flag that can be used to turn on or turn off the Rx checksum
* offload feature.
*/
int rx_csum;
- /* after blink, the adapter must be restored with original
+ /* after blink, the adapter must be restored with original
* values.
*/
u64 adapt_ctrl_org;
@@ -604,16 +761,32 @@ typedef struct s2io_nic {
#define LINK_DOWN 1
#define LINK_UP 2
-#ifdef CONFIG_2BUFF_MODE
- /* Buffer Address store. */
- buffAdd_t **ba[MAX_RX_RINGS];
-#endif
int task_flag;
#define CARD_DOWN 1
#define CARD_UP 2
atomic_t card_state;
volatile unsigned long link_state;
-} nic_t;
+ struct vlan_group *vlgrp;
+#define MSIX_FLG 0xA5
+ struct msix_entry *entries;
+ struct s2io_msix_entry *s2io_entries;
+ char desc1[35];
+ char desc2[35];
+
+ struct msix_info_st msix_info[0x3f];
+
+#define XFRAME_I_DEVICE 1
+#define XFRAME_II_DEVICE 2
+ u8 device_type;
+
+#define INTA 0
+#define MSI 1
+#define MSI_X 2
+ u8 intr_type;
+
+ spinlock_t rx_lock;
+ atomic_t isr_cnt;
+};
#define RESET_ERROR 1;
#define CMD_ERROR 2;
@@ -622,7 +795,8 @@ typedef struct s2io_nic {
#ifndef readq
static inline u64 readq(void __iomem *addr)
{
- u64 ret = readl(addr + 4);
+ u64 ret = 0;
+ ret = readl(addr + 4);
ret <<= 32;
ret |= readl(addr);
@@ -637,10 +811,10 @@ static inline void writeq(u64 val, void __iomem *addr)
writel((u32) (val >> 32), (addr + 4));
}
-/* In 32 bit modes, some registers have to be written in a
+/* In 32 bit modes, some registers have to be written in a
* particular order to expect correct hardware operation. The
- * macro SPECIAL_REG_WRITE is used to perform such ordered
- * writes. Defines UF (Upper First) and LF (Lower First) will
+ * macro SPECIAL_REG_WRITE is used to perform such ordered
+ * writes. Defines UF (Upper First) and LF (Lower First) will
* be used to specify the required write order.
*/
#define UF 1
@@ -716,6 +890,7 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
#define PCC_FB_ECC_ERR vBIT(0xff, 16, 8) /* Interrupt to indicate
PCC_FB_ECC Error. */
+#define RXD_GET_VLAN_TAG(Control_2) (u16)(Control_2 & MASK_VLAN_TAG)
/*
* Prototype declaration.
*/
@@ -725,36 +900,38 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev);
static int init_shared_mem(struct s2io_nic *sp);
static void free_shared_mem(struct s2io_nic *sp);
static int init_nic(struct s2io_nic *nic);
-#ifndef CONFIG_S2IO_NAPI
-static void rx_intr_handler(struct s2io_nic *sp);
-#endif
-static void tx_intr_handler(struct s2io_nic *sp);
+static void rx_intr_handler(ring_info_t *ring_data);
+static void tx_intr_handler(fifo_info_t *fifo_data);
static void alarm_intr_handler(struct s2io_nic *sp);
static int s2io_starter(void);
-static void s2io_closer(void);
+void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr);
static void s2io_set_multicast(struct net_device *dev);
-#ifndef CONFIG_2BUFF_MODE
-static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no);
-#else
-static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
- buffAdd_t * ba);
-#endif
-static void s2io_link(nic_t * sp, int link);
-static void s2io_reset(nic_t * sp);
-#ifdef CONFIG_S2IO_NAPI
+static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp);
+void s2io_link(nic_t * sp, int link);
+void s2io_reset(nic_t * sp);
+#if defined(CONFIG_S2IO_NAPI)
static int s2io_poll(struct net_device *dev, int *budget);
#endif
static void s2io_init_pci(nic_t * sp);
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static void s2io_alarm_handle(unsigned long data);
+static int s2io_enable_msi(nic_t *nic);
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
+int s2io_enable_msi_x(nic_t *nic);
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
-static int verify_xena_quiescence(u64 val64, int flag);
+static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(unsigned long data);
-static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t * nic);
-static int s2io_card_up(nic_t * nic);
-
+int s2io_set_swapper(nic_t * sp);
+static void s2io_card_down(nic_t *nic);
+static int s2io_card_up(nic_t *nic);
+int get_xena_rev_id(struct pci_dev *pdev);
+void restore_xmsi_data(nic_t *nic);
#endif /* _S2IO_H */
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index fd0167077fbe..110e777f206e 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -997,10 +997,7 @@ static void __devexit saa9730_remove_one(struct pci_dev *pdev)
if (dev) {
unregister_netdev(dev);
-
- if (dev->priv)
- kfree(dev->priv);
-
+ kfree(dev->priv);
free_netdev(dev);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -1096,8 +1093,7 @@ static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq)
return 0;
out:
- if (dev->priv)
- kfree(dev->priv);
+ kfree(dev->priv);
return ret;
}
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 7abd55a4fb21..aa4ca1821759 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -10,7 +10,7 @@
* 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.
@@ -118,8 +118,6 @@ MODULE_PARM_DESC(int_timeout, "Timeout value");
********************************************************************* */
-typedef unsigned long sbmac_port_t;
-
typedef enum { sbmac_speed_auto, sbmac_speed_10,
sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
@@ -129,7 +127,7 @@ typedef enum { sbmac_duplex_auto, sbmac_duplex_half,
typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
-typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
sbmac_state_broken } sbmac_state_t;
@@ -144,17 +142,13 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
-#define SBMAC_READCSR(t) __raw_readq((unsigned long)t)
-#define SBMAC_WRITECSR(t,v) __raw_writeq(v, (unsigned long)t)
-
-
#define SBMAC_MAX_TXDESCR 32
#define SBMAC_MAX_RXDESCR 32
#define ETHER_ALIGN 2
#define ETHER_ADDR_LEN 6
-#define ENET_PACKET_SIZE 1518
-/*#define ENET_PACKET_SIZE 9216 */
+#define ENET_PACKET_SIZE 1518
+/*#define ENET_PACKET_SIZE 9216 */
/**********************************************************************
* DMA Descriptor structure
@@ -172,12 +166,12 @@ typedef unsigned long paddr_t;
********************************************************************* */
typedef struct sbmacdma_s {
-
- /*
+
+ /*
* This stuff is used to identify the channel and the registers
* associated with it.
*/
-
+
struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */
int sbdma_channel; /* channel number */
int sbdma_txdir; /* direction (1=transmit) */
@@ -187,21 +181,21 @@ typedef struct sbmacdma_s {
int sbdma_int_timeout; /* # usec rx/tx interrupt */
#endif
- sbmac_port_t sbdma_config0; /* DMA config register 0 */
- sbmac_port_t sbdma_config1; /* DMA config register 1 */
- sbmac_port_t sbdma_dscrbase; /* Descriptor base address */
- sbmac_port_t sbdma_dscrcnt; /* Descriptor count register */
- sbmac_port_t sbdma_curdscr; /* current descriptor address */
-
+ volatile void __iomem *sbdma_config0; /* DMA config register 0 */
+ volatile void __iomem *sbdma_config1; /* DMA config register 1 */
+ volatile void __iomem *sbdma_dscrbase; /* Descriptor base address */
+ volatile void __iomem *sbdma_dscrcnt; /* Descriptor count register */
+ volatile void __iomem *sbdma_curdscr; /* current descriptor address */
+
/*
* This stuff is for maintenance of the ring
*/
-
+
sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */
sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */
-
+
struct sk_buff **sbdma_ctxtable; /* context table, one per descr */
-
+
paddr_t sbdma_dscrtable_phys; /* and also the phys addr */
sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */
sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */
@@ -213,15 +207,15 @@ typedef struct sbmacdma_s {
********************************************************************* */
struct sbmac_softc {
-
+
/*
* Linux-specific things
*/
-
+
struct net_device *sbm_dev; /* pointer to linux device */
spinlock_t sbm_lock; /* spin lock */
struct timer_list sbm_timer; /* for monitoring MII */
- struct net_device_stats sbm_stats;
+ struct net_device_stats sbm_stats;
int sbm_devflags; /* current device flags */
int sbm_phy_oldbmsr;
@@ -229,31 +223,31 @@ struct sbmac_softc {
int sbm_phy_oldk1stsr;
int sbm_phy_oldlinkstat;
int sbm_buffersize;
-
+
unsigned char sbm_phys[2];
-
+
/*
* Controller-specific things
*/
-
- unsigned long sbm_base; /* MAC's base address */
+
+ volatile void __iomem *sbm_base; /* MAC's base address */
sbmac_state_t sbm_state; /* current state */
-
- sbmac_port_t sbm_macenable; /* MAC Enable Register */
- sbmac_port_t sbm_maccfg; /* MAC Configuration Register */
- sbmac_port_t sbm_fifocfg; /* FIFO configuration register */
- sbmac_port_t sbm_framecfg; /* Frame configuration register */
- sbmac_port_t sbm_rxfilter; /* receive filter register */
- sbmac_port_t sbm_isr; /* Interrupt status register */
- sbmac_port_t sbm_imr; /* Interrupt mask register */
- sbmac_port_t sbm_mdio; /* MDIO register */
-
+
+ volatile void __iomem *sbm_macenable; /* MAC Enable Register */
+ volatile void __iomem *sbm_maccfg; /* MAC Configuration Register */
+ volatile void __iomem *sbm_fifocfg; /* FIFO configuration register */
+ volatile void __iomem *sbm_framecfg; /* Frame configuration register */
+ volatile void __iomem *sbm_rxfilter; /* receive filter register */
+ volatile void __iomem *sbm_isr; /* Interrupt status register */
+ volatile void __iomem *sbm_imr; /* Interrupt mask register */
+ volatile void __iomem *sbm_mdio; /* MDIO register */
+
sbmac_speed_t sbm_speed; /* current speed */
sbmac_duplex_t sbm_duplex; /* current duplex */
sbmac_fc_t sbm_fc; /* current flow control setting */
-
+
unsigned char sbm_hwaddr[ETHER_ADDR_LEN];
-
+
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
sbmacdma_t sbm_rxdma;
int rx_hw_checksum;
@@ -302,6 +296,7 @@ static void sbmac_set_rx_mode(struct net_device *dev);
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int sbmac_close(struct net_device *dev);
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
+static int sbmac_mii_probe(struct net_device *dev);
static void sbmac_mii_sync(struct sbmac_softc *s);
static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
@@ -439,6 +434,9 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
#define MII_BMCR 0x00 /* Basic mode control register (rw) */
#define MII_BMSR 0x01 /* Basic mode status register (ro) */
+#define MII_PHYIDR1 0x02
+#define MII_PHYIDR2 0x03
+
#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
@@ -450,13 +448,13 @@ static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
/**********************************************************************
* SBMAC_MII_SYNC(s)
- *
+ *
* Synchronize with the MII - send a pattern of bits to the MII
* that will guarantee that it is ready to accept a command.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -467,25 +465,25 @@ static void sbmac_mii_sync(struct sbmac_softc *s)
uint64_t bits;
int mac_mdio_genc;
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
-
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-
+
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
for (cnt = 0; cnt < 32; cnt++) {
- SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
}
}
/**********************************************************************
* SBMAC_MII_SENDDATA(s,data,bitcnt)
- *
+ *
* Send some bits to the MII. The bits to be sent are right-
* justified in the 'data' parameter.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* data - data to send
* bitcnt - number of bits to send
@@ -498,20 +496,20 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
unsigned int curmask;
int mac_mdio_genc;
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
bits = M_MAC_MDIO_DIR_OUTPUT;
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
curmask = 1 << (bitcnt - 1);
-
+
for (i = 0; i < bitcnt; i++) {
if (data & curmask)
bits |= M_MAC_MDIO_OUT;
else bits &= ~M_MAC_MDIO_OUT;
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
curmask >>= 1;
}
}
@@ -520,14 +518,14 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
/**********************************************************************
* SBMAC_MII_READ(s,phyaddr,regidx)
- *
+ *
* Read a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY's address
* regidx = index of register to read
- *
+ *
* Return value:
* value read, or 0 if an error occurred.
********************************************************************* */
@@ -543,9 +541,9 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* Synchronize ourselves so that the PHY knows the next
* thing coming down is a command
*/
-
+
sbmac_mii_sync(s);
-
+
/*
* Send the data to the PHY. The sequence is
* a "start" command (2 bits)
@@ -553,59 +551,55 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
* the PHY addr (5 bits)
* the register index (5 bits)
*/
-
+
sbmac_mii_senddata(s,MII_COMMAND_START, 2);
sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
sbmac_mii_senddata(s,phyaddr, 5);
sbmac_mii_senddata(s,regidx, 5);
-
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-
- /*
+
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
+ /*
* Switch the port around without a clock transition.
*/
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
/*
* Send out a clock pulse to signal we want the status
*/
-
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
- /*
+
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
+ /*
* If an error occurred, the PHY will signal '1' back
*/
- error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
-
- /*
+ error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
+
+ /*
* Issue an 'idle' clock pulse, but keep the direction
* the same.
*/
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
regval = 0;
-
+
for (idx = 0; idx < 16; idx++) {
regval <<= 1;
-
+
if (error == 0) {
- if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
+ if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
regval |= 1;
}
-
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc);
- SBMAC_WRITECSR(s->sbm_mdio,
- M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+ __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
}
-
+
/* Switch back to output */
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
-
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+
if (error == 0)
return regval;
return 0;
@@ -614,15 +608,15 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
/**********************************************************************
* SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
- *
+ *
* Write a value to a PHY register.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* phyaddr - PHY to use
* regidx - register within the PHY
* regval - data to write to register
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -633,7 +627,7 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
int mac_mdio_genc;
sbmac_mii_sync(s);
-
+
sbmac_mii_senddata(s,MII_COMMAND_START,2);
sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
sbmac_mii_senddata(s,phyaddr, 5);
@@ -641,27 +635,27 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
sbmac_mii_senddata(s,regval,16);
- mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+ mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
- SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
+ __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
}
/**********************************************************************
* SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
- *
+ *
* Initialize a DMA channel context. Since there are potentially
* eight DMA channels per MAC, it's nice to do this in a standard
- * way.
- *
- * Input parameters:
+ * way.
+ *
+ * Input parameters:
* d - sbmacdma_t structure (DMA channel context)
* s - sbmac_softc structure (pointer to a MAC)
* chan - channel number (0..1 right now)
* txrx - Identifies DMA_TX or DMA_RX for channel direction
* maxdescr - number of descriptors
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -672,101 +666,87 @@ static void sbdma_initctx(sbmacdma_t *d,
int txrx,
int maxdescr)
{
- /*
- * Save away interesting stuff in the structure
+ /*
+ * Save away interesting stuff in the structure
*/
-
+
d->sbdma_eth = s;
d->sbdma_channel = chan;
d->sbdma_txdir = txrx;
-
+
#if 0
/* RMON clearing */
s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
#endif
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
- SBMAC_WRITECSR(IOADDR(
- A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
-
- /*
- * initialize register pointers
- */
-
- d->sbdma_config0 =
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
+ __raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
+
+ /*
+ * initialize register pointers
+ */
+
+ d->sbdma_config0 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
- d->sbdma_config1 =
+ d->sbdma_config1 =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
- d->sbdma_dscrbase =
+ d->sbdma_dscrbase =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
- d->sbdma_dscrcnt =
+ d->sbdma_dscrcnt =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
- d->sbdma_curdscr =
+ d->sbdma_curdscr =
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
-
+
/*
* Allocate memory for the ring
*/
-
+
d->sbdma_maxdescr = maxdescr;
-
- d->sbdma_dscrtable = (sbdmadscr_t *)
- kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
-
+
+ d->sbdma_dscrtable = (sbdmadscr_t *)
+ kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
+
+ /*
+ * The descriptor table must be aligned to at least 16 bytes or the
+ * MAC will corrupt it.
+ */
+ d->sbdma_dscrtable = (sbdmadscr_t *)
+ ALIGN((unsigned long)d->sbdma_dscrtable, sizeof(sbdmadscr_t));
+
memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
-
+
d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
-
+
d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
-
+
/*
* And context table
*/
-
- d->sbdma_ctxtable = (struct sk_buff **)
+
+ d->sbdma_ctxtable = (struct sk_buff **)
kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
-
+
memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Setup Rx/Tx DMA coalescing defaults
@@ -777,7 +757,7 @@ static void sbdma_initctx(sbmacdma_t *d,
} else {
d->sbdma_int_pktcnt = 1;
}
-
+
if ( int_timeout ) {
d->sbdma_int_timeout = int_timeout;
} else {
@@ -789,13 +769,13 @@ static void sbdma_initctx(sbmacdma_t *d,
/**********************************************************************
* SBDMA_CHANNEL_START(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
* rxtx - DMA_RX or DMA_TX depending on what type of channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -805,24 +785,21 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/*
* Turn on the DMA channel
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
- SBMAC_WRITECSR(d->sbdma_config1,
- V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
- 0);
- SBMAC_WRITECSR(d->sbdma_config0,
- M_DMA_EOP_INT_EN |
+ __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+ 0, d->sbdma_config1);
+ __raw_writeq(M_DMA_EOP_INT_EN |
V_DMA_RINGSZ(d->sbdma_maxdescr) |
V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
- 0);
+ 0, d->sbdma_config0);
#else
- SBMAC_WRITECSR(d->sbdma_config1,0);
- SBMAC_WRITECSR(d->sbdma_config0,
- V_DMA_RINGSZ(d->sbdma_maxdescr) |
- 0);
+ __raw_writeq(0, d->sbdma_config1);
+ __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
+ 0, d->sbdma_config0);
#endif
- SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+ __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
/*
* Initialize ring pointers
@@ -834,12 +811,12 @@ static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
/**********************************************************************
* SBDMA_CHANNEL_STOP(d)
- *
+ *
* Initialize the hardware registers for a DMA channel.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel to init (context must be previously init'd
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -849,44 +826,44 @@ static void sbdma_channel_stop(sbmacdma_t *d)
/*
* Turn off the DMA channel
*/
-
- SBMAC_WRITECSR(d->sbdma_config1,0);
-
- SBMAC_WRITECSR(d->sbdma_dscrbase,0);
-
- SBMAC_WRITECSR(d->sbdma_config0,0);
-
+
+ __raw_writeq(0, d->sbdma_config1);
+
+ __raw_writeq(0, d->sbdma_dscrbase);
+
+ __raw_writeq(0, d->sbdma_config0);
+
/*
* Zero ring pointers
*/
-
- d->sbdma_addptr = 0;
- d->sbdma_remptr = 0;
+
+ d->sbdma_addptr = NULL;
+ d->sbdma_remptr = NULL;
}
static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
{
unsigned long addr;
unsigned long newaddr;
-
+
addr = (unsigned long) skb->data;
-
+
newaddr = (addr + power2 - 1) & ~(power2 - 1);
-
+
skb_reserve(skb,newaddr-addr+offset);
}
/**********************************************************************
* SBDMA_ADD_RCVBUFFER(d,sb)
- *
+ *
* Add a buffer to the specified DMA channel. For receive channels,
* this queues a buffer for inbound packets.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add, or NULL if we should allocate one
- *
+ *
* Return value:
* 0 if buffer could not be added (ring is full)
* 1 if buffer added successfully
@@ -899,24 +876,24 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
sbdmadscr_t *nextdsc;
struct sk_buff *sb_new = NULL;
int pktsize = ENET_PACKET_SIZE;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
- /*
- * Allocate a sk_buff if we don't already have one.
+ /*
+ * Allocate a sk_buff if we don't already have one.
* If we do have an sk_buff, reset it so that it's empty.
*
* Note: sk_buffs don't seem to be guaranteed to have any sort
@@ -925,7 +902,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
*
* 1. the data does not start in the middle of a cache line.
* 2. The data does not end in the middle of a cache line
- * 3. The buffer can be aligned such that the IP addresses are
+ * 3. The buffer can be aligned such that the IP addresses are
* naturally aligned.
*
* Remember, the SOCs MAC writes whole cache lines at a time,
@@ -933,7 +910,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
* data portion starts in the middle of a cache line, the SOC
* DMA will trash the beginning (and ending) portions.
*/
-
+
if (sb == NULL) {
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
if (sb_new == NULL) {
@@ -949,23 +926,22 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
}
else {
sb_new = sb;
- /*
+ /*
* nothing special to reinit buffer, it's already aligned
* and sb->data already points to a good place.
*/
}
-
+
/*
- * fill in the descriptor
+ * fill in the descriptor
*/
-
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Do not interrupt per DMA transfer.
*/
dsc->dscr_a = virt_to_phys(sb_new->data) |
- V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
- 0;
+ V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
#else
dsc->dscr_a = virt_to_phys(sb_new->data) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
@@ -974,38 +950,38 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
/* receiving: no options */
dsc->dscr_b = 0;
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-
+
+ __raw_writeq(1, d->sbdma_dscrcnt);
+
return 0; /* we did it */
}
/**********************************************************************
* SBDMA_ADD_TXBUFFER(d,sb)
- *
+ *
* Add a transmit buffer to the specified DMA channel, causing a
* transmit to start.
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel descriptor
* sb - sk_buff to add
- *
+ *
* Return value:
* 0 transmit queued successfully
* otherwise error code
@@ -1019,70 +995,70 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
uint64_t phys;
uint64_t ncb;
int length;
-
+
/* get pointer to our current place in the ring */
-
+
dsc = d->sbdma_addptr;
nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-
+
/*
* figure out if the ring is full - if the next descriptor
* is the same as the one that we're going to remove from
* the ring, the ring is full
*/
-
+
if (nextdsc == d->sbdma_remptr) {
return -ENOSPC;
}
-
+
/*
* Under Linux, it's not necessary to copy/coalesce buffers
* like it is on NetBSD. We think they're all contiguous,
* but that may not be true for GBE.
*/
-
+
length = sb->len;
-
+
/*
* fill in the descriptor. Note that the number of cache
* blocks in the descriptor is the number of blocks
* *spanned*, so we need to add in the offset (if any)
* while doing the calculation.
*/
-
+
phys = virt_to_phys(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
- dsc->dscr_a = phys |
+ dsc->dscr_a = phys |
V_DMA_DSCRA_A_SIZE(ncb) |
#ifndef CONFIG_SBMAC_COALESCE
M_DMA_DSCRA_INTERRUPT |
#endif
M_DMA_ETHTX_SOP;
-
+
/* transmitting: set outbound options and length */
dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
V_DMA_DSCRB_PKT_SIZE(length);
-
+
/*
- * fill in the context
+ * fill in the context
*/
-
+
d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
-
- /*
- * point at next packet
+
+ /*
+ * point at next packet
*/
-
+
d->sbdma_addptr = nextdsc;
-
- /*
+
+ /*
* Give the buffer to the DMA engine.
*/
-
- SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-
+
+ __raw_writeq(1, d->sbdma_dscrcnt);
+
return 0; /* we did it */
}
@@ -1091,12 +1067,12 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
/**********************************************************************
* SBDMA_EMPTYRING(d)
- *
+ *
* Free all allocated sk_buffs on the specified DMA channel;
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1105,7 +1081,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
{
int idx;
struct sk_buff *sb;
-
+
for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
sb = d->sbdma_ctxtable[idx];
if (sb) {
@@ -1118,13 +1094,13 @@ static void sbdma_emptyring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_FILLRING(d)
- *
+ *
* Fill the specified DMA channel (must be receive channel)
* with sk_buffs
- *
- * Input parameters:
+ *
+ * Input parameters:
* d - DMA channel
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1132,7 +1108,7 @@ static void sbdma_emptyring(sbmacdma_t *d)
static void sbdma_fillring(sbmacdma_t *d)
{
int idx;
-
+
for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
if (sbdma_add_rcvbuffer(d,NULL) != 0)
break;
@@ -1142,16 +1118,16 @@ static void sbdma_fillring(sbmacdma_t *d)
/**********************************************************************
* SBDMA_RX_PROCESS(sc,d)
- *
- * Process "completed" receive buffers on the specified DMA channel.
+ *
+ * Process "completed" receive buffers on the specified DMA channel.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1163,56 +1139,56 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sbdmadscr_t *dsc;
struct sk_buff *sb;
int len;
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
-
+
/*
* If they're the same, that means we've processed all
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
-
+
/*
* Check packet status. If good, process it.
* If not, silently drop it and put it back on the
* receive ring.
*/
-
+
if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
-
+
/*
* Add a new buffer to replace the old one. If we fail
* to allocate a buffer, we're going to drop this
* packet and put it right back on the receive ring.
*/
-
+
if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
sc->sbm_stats.rx_dropped++;
sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
@@ -1221,7 +1197,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* Set length into the packet
*/
skb_put(sb,len);
-
+
/*
* Buffer has been replaced on the
* receive ring. Pass the buffer to
@@ -1240,7 +1216,7 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sb->ip_summed = CHECKSUM_NONE;
}
}
-
+
netif_rx(sb);
}
} else {
@@ -1251,14 +1227,14 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
sc->sbm_stats.rx_errors++;
sbdma_add_rcvbuffer(d,sb);
}
-
-
- /*
+
+
+ /*
* .. and advance to the next buffer.
*/
-
+
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
}
@@ -1266,17 +1242,17 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
/**********************************************************************
* SBDMA_TX_PROCESS(sc,d)
- *
- * Process "completed" transmit buffers on the specified DMA channel.
+ *
+ * Process "completed" transmit buffers on the specified DMA channel.
* This is normally called within the interrupt service routine.
* Note that this isn't really ideal for priority channels, since
- * it processes all of the packets on a given channel before
- * returning.
+ * it processes all of the packets on a given channel before
+ * returning.
*
- * Input parameters:
+ * Input parameters:
* sc - softc structure
* d - DMA channel context
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1290,21 +1266,21 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
unsigned long flags;
spin_lock_irqsave(&(sc->sbm_lock), flags);
-
+
for (;;) {
- /*
+ /*
* figure out where we are (as an index) and where
* the hardware is (also as an index)
*
- * This could be done faster if (for example) the
+ * This could be done faster if (for example) the
* descriptor table was page-aligned and contiguous in
* both virtual and physical memory -- you could then
* just compare the low-order bits of the virtual address
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
*/
-
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
- hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+ hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
/*
@@ -1312,75 +1288,75 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* of the descriptors up to (but not including) the one that
* the hardware is working on right now.
*/
-
+
if (curidx == hwidx)
break;
-
+
/*
* Otherwise, get the packet's sk_buff ptr back
*/
-
+
dsc = &(d->sbdma_dscrtable[curidx]);
sb = d->sbdma_ctxtable[curidx];
d->sbdma_ctxtable[curidx] = NULL;
-
+
/*
* Stats
*/
-
+
sc->sbm_stats.tx_bytes += sb->len;
sc->sbm_stats.tx_packets++;
-
+
/*
* for transmits, we just free buffers.
*/
-
+
dev_kfree_skb_irq(sb);
-
- /*
+
+ /*
* .. and advance to the next buffer.
*/
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+
}
-
+
/*
* Decide if we should wake up the protocol or not.
* Other drivers seem to do this when we reach a low
* watermark on the transmit queue.
*/
-
+
netif_wake_queue(d->sbdma_eth->sbm_dev);
-
+
spin_unlock_irqrestore(&(sc->sbm_lock), flags);
-
+
}
/**********************************************************************
* SBMAC_INITCTX(s)
- *
+ *
* Initialize an Ethernet context structure - this is called
* once per MAC on the 1250. Memory is allocated here, so don't
* call it again from inside the ioctl routines that bring the
* interface up/down
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac context structure
- *
+ *
* Return value:
* 0
********************************************************************* */
static int sbmac_initctx(struct sbmac_softc *s)
{
-
- /*
- * figure out the addresses of some ports
+
+ /*
+ * figure out the addresses of some ports
*/
-
+
s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
s->sbm_maccfg = s->sbm_base + R_MAC_CFG;
s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG;
@@ -1397,29 +1373,29 @@ static int sbmac_initctx(struct sbmac_softc *s)
s->sbm_phy_oldanlpar = 0;
s->sbm_phy_oldk1stsr = 0;
s->sbm_phy_oldlinkstat = 0;
-
+
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
*/
-
+
sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-
+
/*
* initial state is OFF
*/
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Initial speed is (XXX TEMP) 10MBit/s HDX no FC
*/
-
+
s->sbm_speed = sbmac_speed_10;
s->sbm_duplex = sbmac_duplex_half;
s->sbm_fc = sbmac_fc_disabled;
-
+
return 0;
}
@@ -1430,7 +1406,7 @@ static void sbdma_uninitctx(struct sbmacdma_s *d)
kfree(d->sbdma_dscrtable);
d->sbdma_dscrtable = NULL;
}
-
+
if (d->sbdma_ctxtable) {
kfree(d->sbdma_ctxtable);
d->sbdma_ctxtable = NULL;
@@ -1447,12 +1423,12 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_CHANNEL_START(s)
- *
+ *
* Start packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1460,49 +1436,49 @@ static void sbmac_uninitctx(struct sbmac_softc *sc)
static void sbmac_channel_start(struct sbmac_softc *s)
{
uint64_t reg;
- sbmac_port_t port;
+ volatile void __iomem *port;
uint64_t cfg,fifo,framecfg;
int idx, th_value;
-
+
/*
* Don't do this if running
*/
if (s->sbm_state == sbmac_state_on)
return;
-
+
/*
* Bring the controller out of reset, but leave it off.
*/
-
- SBMAC_WRITECSR(s->sbm_macenable,0);
-
+
+ __raw_writeq(0, s->sbm_macenable);
+
/*
* Ignore all received packets
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
-
- /*
+
+ __raw_writeq(0, s->sbm_rxfilter);
+
+ /*
* Calculate values for various control registers.
*/
-
+
cfg = M_MAC_RETRY_EN |
- M_MAC_TX_HOLD_SOP_EN |
+ M_MAC_TX_HOLD_SOP_EN |
V_MAC_TX_PAUSE_CNT_16K |
M_MAC_AP_STAT_EN |
M_MAC_FAST_SYNC |
M_MAC_SS_EN |
0;
-
- /*
+
+ /*
* Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
* and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
* Use a larger RD_THRSH for gigabit
*/
- if (periph_rev >= 2)
+ if (periph_rev >= 2)
th_value = 64;
- else
+ else
th_value = 28;
fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
@@ -1520,51 +1496,51 @@ static void sbmac_channel_start(struct sbmac_softc *s)
V_MAC_BACKOFF_SEL(1);
/*
- * Clear out the hash address map
+ * Clear out the hash address map
*/
-
+
port = s->sbm_base + R_MAC_HASH_BASE;
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the exact-match table
*/
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Clear out the DMA Channel mapping table registers
*/
-
+
port = s->sbm_base + R_MAC_CHUP0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
port = s->sbm_base + R_MAC_CHLO0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
port += sizeof(uint64_t);
}
-
+
/*
* Program the hardware address. It goes into the hardware-address
* register as well as the first filter register.
*/
-
+
reg = sbmac_addr2reg(s->sbm_hwaddr);
-
+
port = s->sbm_base + R_MAC_ADDR_BASE;
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
port = s->sbm_base + R_MAC_ETHERNET_ADDR;
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -1573,108 +1549,105 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* destination address in the R_MAC_ETHERNET_ADDR register.
* Set the value to zero.
*/
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
#else
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
#endif
-
+
/*
* Set the receive filter for no packets, and write values
* to the various config registers
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
- SBMAC_WRITECSR(s->sbm_imr,0);
- SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
- SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(0, s->sbm_rxfilter);
+ __raw_writeq(0, s->sbm_imr);
+ __raw_writeq(framecfg, s->sbm_framecfg);
+ __raw_writeq(fifo, s->sbm_fifocfg);
+ __raw_writeq(cfg, s->sbm_maccfg);
+
/*
* Initialize DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
-
+
/*
* Configure the speed, duplex, and flow control
*/
sbmac_set_speed(s,s->sbm_speed);
sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
-
+
/*
* Fill the receive ring
*/
-
+
sbdma_fillring(&(s->sbm_rxdma));
-
- /*
+
+ /*
* Turn on the rest of the bits in the enable register
- */
-
- SBMAC_WRITECSR(s->sbm_macenable,
- M_MAC_RXDMA_EN0 |
+ */
+
+ __raw_writeq(M_MAC_RXDMA_EN0 |
M_MAC_TXDMA_EN0 |
M_MAC_RX_ENABLE |
- M_MAC_TX_ENABLE);
-
-
+ M_MAC_TX_ENABLE, s->sbm_macenable);
+
+
#ifdef CONFIG_SBMAC_COALESCE
/*
* Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
*/
- SBMAC_WRITECSR(s->sbm_imr,
- ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
- ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+ __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+ ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
#else
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
*/
- SBMAC_WRITECSR(s->sbm_imr,
- (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
- (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+ __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+ (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
#endif
-
- /*
- * Enable receiving unicasts and broadcasts
+
+ /*
+ * Enable receiving unicasts and broadcasts
*/
-
- SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
-
+
+ __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
+
/*
- * we're running now.
+ * we're running now.
*/
-
+
s->sbm_state = sbmac_state_on;
-
- /*
- * Program multicast addresses
+
+ /*
+ * Program multicast addresses
*/
-
+
sbmac_setmulti(s);
-
- /*
- * If channel was in promiscuous mode before, turn that on
+
+ /*
+ * If channel was in promiscuous mode before, turn that on
*/
-
+
if (s->sbm_devflags & IFF_PROMISC) {
sbmac_promiscuous_mode(s,1);
}
-
+
}
/**********************************************************************
* SBMAC_CHANNEL_STOP(s)
- *
+ *
* Stop packet processing on this MAC.
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1682,49 +1655,49 @@ static void sbmac_channel_start(struct sbmac_softc *s)
static void sbmac_channel_stop(struct sbmac_softc *s)
{
/* don't do this if already stopped */
-
+
if (s->sbm_state == sbmac_state_off)
return;
-
+
/* don't accept any packets, disable all interrupts */
-
- SBMAC_WRITECSR(s->sbm_rxfilter,0);
- SBMAC_WRITECSR(s->sbm_imr,0);
-
+
+ __raw_writeq(0, s->sbm_rxfilter);
+ __raw_writeq(0, s->sbm_imr);
+
/* Turn off ticker */
-
+
/* XXX */
-
+
/* turn off receiver and transmitter */
-
- SBMAC_WRITECSR(s->sbm_macenable,0);
-
+
+ __raw_writeq(0, s->sbm_macenable);
+
/* We're stopped now. */
-
+
s->sbm_state = sbmac_state_off;
-
+
/*
* Stop DMA channels (rings should be ok now)
*/
-
+
sbdma_channel_stop(&(s->sbm_rxdma));
sbdma_channel_stop(&(s->sbm_txdma));
-
+
/* Empty the receive and transmit rings */
-
+
sbdma_emptyring(&(s->sbm_rxdma));
sbdma_emptyring(&(s->sbm_txdma));
-
+
}
/**********************************************************************
* SBMAC_SET_CHANNEL_STATE(state)
- *
+ *
* Set the channel's state ON or OFF
- *
- * Input parameters:
+ *
+ * Input parameters:
* state - new state
- *
+ *
* Return value:
* old state
********************************************************************* */
@@ -1732,43 +1705,43 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
sbmac_state_t state)
{
sbmac_state_t oldstate = sc->sbm_state;
-
+
/*
* If same as previous state, return
*/
-
+
if (state == oldstate) {
return oldstate;
}
-
+
/*
- * If new state is ON, turn channel on
+ * If new state is ON, turn channel on
*/
-
+
if (state == sbmac_state_on) {
sbmac_channel_start(sc);
}
else {
sbmac_channel_stop(sc);
}
-
+
/*
* Return previous state
*/
-
+
return oldstate;
}
/**********************************************************************
* SBMAC_PROMISCUOUS_MODE(sc,onoff)
- *
+ *
* Turn on or off promiscuous mode
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
* onoff - 1 to turn on, 0 to turn off
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1776,30 +1749,30 @@ static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
{
uint64_t reg;
-
+
if (sc->sbm_state != sbmac_state_on)
return;
-
+
if (onoff) {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= M_MAC_ALLPKT_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
- }
+ __raw_writeq(reg, sc->sbm_rxfilter);
+ }
else {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~M_MAC_ALLPKT_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
}
}
/**********************************************************************
* SBMAC_SETIPHDR_OFFSET(sc,onoff)
- *
+ *
* Set the iphdr offset as 15 assuming ethernet encapsulation
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -1807,12 +1780,12 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
{
uint64_t reg;
-
+
/* Hard code the off set to 15 for now */
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-
+ __raw_writeq(reg, sc->sbm_rxfilter);
+
/* read system identification to determine revision */
if (periph_rev >= 2) {
sc->rx_hw_checksum = ENABLE;
@@ -1824,13 +1797,13 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
/**********************************************************************
* SBMAC_ADDR2REG(ptr)
- *
+ *
* Convert six bytes into the 64-bit register value that
* we typically write into the SBMAC's address/mcast registers
- *
- * Input parameters:
+ *
+ * Input parameters:
* ptr - pointer to 6 bytes
- *
+ *
* Return value:
* register value
********************************************************************* */
@@ -1838,35 +1811,35 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
static uint64_t sbmac_addr2reg(unsigned char *ptr)
{
uint64_t reg = 0;
-
+
ptr += 6;
-
- reg |= (uint64_t) *(--ptr);
+
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
+ reg |= (uint64_t) *(--ptr);
reg <<= 8;
- reg |= (uint64_t) *(--ptr);
-
+ reg |= (uint64_t) *(--ptr);
+
return reg;
}
/**********************************************************************
* SBMAC_SET_SPEED(s,speed)
- *
+ *
* Configure LAN speed for the specified MAC.
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* speed - speed to set MAC to (see sbmac_speed_t enum)
- *
+ *
* Return value:
* 1 if successful
* 0 indicates invalid parameters
@@ -1880,31 +1853,31 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
/*
* Save new current values
*/
-
+
s->sbm_speed = speed;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = SBMAC_READCSR(s->sbm_maccfg);
- framecfg = SBMAC_READCSR(s->sbm_framecfg);
-
+
+ cfg = __raw_readq(s->sbm_maccfg);
+ framecfg = __raw_readq(s->sbm_framecfg);
+
/*
* Mask out the stuff we want to change
*/
-
+
cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
M_MAC_SLOT_SIZE);
-
+
/*
* Now add in the new bits
*/
-
+
switch (speed) {
case sbmac_speed_10:
framecfg |= V_MAC_IFG_RX_10 |
@@ -1913,7 +1886,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_10;
cfg |= V_MAC_SPEED_SEL_10MBPS;
break;
-
+
case sbmac_speed_100:
framecfg |= V_MAC_IFG_RX_100 |
V_MAC_IFG_TX_100 |
@@ -1921,7 +1894,7 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_100;
cfg |= V_MAC_SPEED_SEL_100MBPS ;
break;
-
+
case sbmac_speed_1000:
framecfg |= V_MAC_IFG_RX_1000 |
V_MAC_IFG_TX_1000 |
@@ -1929,34 +1902,34 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
V_MAC_SLOT_SIZE_1000;
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;
-
+
case sbmac_speed_auto: /* XXX not implemented */
/* fall through */
default:
return 0;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(framecfg, s->sbm_framecfg);
+ __raw_writeq(cfg, s->sbm_maccfg);
+
return 1;
}
/**********************************************************************
* SBMAC_SET_DUPLEX(s,duplex,fc)
- *
+ *
* Set Ethernet duplex and flow control options for this MAC
* Warning: must be called when MAC is off!
- *
- * Input parameters:
+ *
+ * Input parameters:
* s - sbmac structure
* duplex - duplex setting (see sbmac_duplex_t)
* fc - flow control setting (see sbmac_fc_t)
- *
+ *
* Return value:
* 1 if ok
* 0 if an invalid parameter combination was specified
@@ -1965,67 +1938,67 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
{
uint64_t cfg;
-
+
/*
* Save new current values
*/
-
+
s->sbm_duplex = duplex;
s->sbm_fc = fc;
-
+
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
-
+
/*
- * Read current register values
+ * Read current register values
*/
-
- cfg = SBMAC_READCSR(s->sbm_maccfg);
-
+
+ cfg = __raw_readq(s->sbm_maccfg);
+
/*
* Mask off the stuff we're about to change
*/
-
+
cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
-
-
+
+
switch (duplex) {
case sbmac_duplex_half:
switch (fc) {
case sbmac_fc_disabled:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_collision:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_carrier:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
break;
-
+
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
return 0;
}
break;
-
+
case sbmac_duplex_full:
switch (fc) {
case sbmac_fc_disabled:
cfg |= V_MAC_FC_CMD_DISABLED;
break;
-
+
case sbmac_fc_frame:
cfg |= V_MAC_FC_CMD_ENABLED;
break;
-
+
case sbmac_fc_collision: /* not valid in full duplex */
case sbmac_fc_carrier: /* not valid in full duplex */
case sbmac_fc_auto: /* XXX not implemented */
- /* fall through */
+ /* fall through */
default:
return 0;
}
@@ -2034,13 +2007,13 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/* XXX not implemented */
break;
}
-
+
/*
- * Send the bits back to the hardware
+ * Send the bits back to the hardware
*/
-
- SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-
+
+ __raw_writeq(cfg, s->sbm_maccfg);
+
return 1;
}
@@ -2049,12 +2022,12 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
/**********************************************************************
* SBMAC_INTR()
- *
+ *
* Interrupt handler for MAC interrupts
- *
- * Input parameters:
+ *
+ * Input parameters:
* MAC structure
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2066,27 +2039,27 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
int handled = 0;
for (;;) {
-
+
/*
* Read the ISR (this clears the bits in the real
* register, except for counter addr)
*/
-
- isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
-
+
+ isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
+
if (isr == 0)
break;
handled = 1;
-
+
/*
* Transmits on channel 0
*/
-
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
sbdma_tx_process(sc,&(sc->sbm_txdma));
}
-
+
/*
* Receives on channel 0
*/
@@ -2106,8 +2079,8 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
* EOP_SEEN here takes care of this case.
* (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
*/
-
-
+
+
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
sbdma_rx_process(sc,&(sc->sbm_rxdma));
}
@@ -2118,29 +2091,29 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
/**********************************************************************
* SBMAC_START_TX(skb,dev)
- *
- * Start output on the specified interface. Basically, we
+ *
+ * Start output on the specified interface. Basically, we
* queue as many buffers as we can until the ring fills up, or
* we run off the end of the queue, whichever comes first.
- *
- * Input parameters:
- *
- *
+ *
+ * Input parameters:
+ *
+ *
* Return value:
* nothing
********************************************************************* */
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
/* lock eth irq */
spin_lock_irq (&sc->sbm_lock);
-
+
/*
- * Put the buffer on the transmit ring. If we
+ * Put the buffer on the transmit ring. If we
* don't have room, stop the queue.
*/
-
+
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
/* XXX save skb that we could not send */
netif_stop_queue(dev);
@@ -2148,24 +2121,24 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
return 1;
}
-
+
dev->trans_start = jiffies;
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
return 0;
}
/**********************************************************************
* SBMAC_SETMULTI(sc)
- *
+ *
* Reprogram the multicast table into the hardware, given
* the list of multicasts associated with the interface
* structure.
- *
- * Input parameters:
+ *
+ * Input parameters:
* sc - softc
- *
+ *
* Return value:
* nothing
********************************************************************* */
@@ -2173,75 +2146,75 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
static void sbmac_setmulti(struct sbmac_softc *sc)
{
uint64_t reg;
- sbmac_port_t port;
+ volatile void __iomem *port;
int idx;
struct dev_mc_list *mclist;
struct net_device *dev = sc->sbm_dev;
-
- /*
+
+ /*
* Clear out entire multicast table. We do this by nuking
* the entire hash table and all the direct matches except
- * the first one, which is used for our station address
+ * the first one, which is used for our station address
*/
-
+
for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
}
-
+
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
- SBMAC_WRITECSR(port,0);
+ __raw_writeq(0, port);
}
-
+
/*
* Clear the filter to say we don't want any multicasts.
*/
-
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+
+ reg = __raw_readq(sc->sbm_rxfilter);
reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-
+ __raw_writeq(reg, sc->sbm_rxfilter);
+
if (dev->flags & IFF_ALLMULTI) {
- /*
- * Enable ALL multicasts. Do this by inverting the
- * multicast enable bit.
+ /*
+ * Enable ALL multicasts. Do this by inverting the
+ * multicast enable bit.
*/
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
return;
}
-
- /*
+
+ /*
* Progam new multicast entries. For now, only use the
* perfect filter. In the future we'll need to use the
* hash filter if the perfect filter overflows
*/
-
+
/* XXX only using perfect filter for now, need to use hash
* XXX if the table overflows */
-
+
idx = 1; /* skip station address */
mclist = dev->mc_list;
while (mclist && (idx < MAC_ADDR_COUNT)) {
reg = sbmac_addr2reg(mclist->dmi_addr);
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
- SBMAC_WRITECSR(port,reg);
+ __raw_writeq(reg, port);
idx++;
mclist = mclist->next;
}
-
- /*
+
+ /*
* Enable the "accept multicast bits" if we programmed at least one
- * multicast.
+ * multicast.
*/
-
+
if (idx > 1) {
- reg = SBMAC_READCSR(sc->sbm_rxfilter);
+ reg = __raw_readq(sc->sbm_rxfilter);
reg |= M_MAC_MCAST_EN;
- SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+ __raw_writeq(reg, sc->sbm_rxfilter);
}
}
@@ -2250,12 +2223,12 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
/**********************************************************************
* SBMAC_PARSE_XDIGIT(str)
- *
+ *
* Parse a hex digit, returning its value
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - character
- *
+ *
* Return value:
* hex value, or -1 if invalid
********************************************************************* */
@@ -2263,7 +2236,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
static int sbmac_parse_xdigit(char str)
{
int digit;
-
+
if ((str >= '0') && (str <= '9'))
digit = str - '0';
else if ((str >= 'a') && (str <= 'f'))
@@ -2272,20 +2245,20 @@ static int sbmac_parse_xdigit(char str)
digit = str - 'A' + 10;
else
return -1;
-
+
return digit;
}
/**********************************************************************
* SBMAC_PARSE_HWADDR(str,hwaddr)
- *
+ *
* Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
* Ethernet address.
- *
- * Input parameters:
+ *
+ * Input parameters:
* str - string
* hwaddr - pointer to hardware address
- *
+ *
* Return value:
* 0 if ok, else -1
********************************************************************* */
@@ -2294,7 +2267,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
{
int digit1,digit2;
int idx = 6;
-
+
while (*str && (idx > 0)) {
digit1 = sbmac_parse_xdigit(*str);
if (digit1 < 0)
@@ -2302,7 +2275,7 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
str++;
if (!*str)
return -1;
-
+
if ((*str == ':') || (*str == '-')) {
digit2 = digit1;
digit1 = 0;
@@ -2313,10 +2286,10 @@ static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
return -1;
str++;
}
-
+
*hwaddr++ = (digit1 << 4) | digit2;
idx--;
-
+
if (*str == '-')
str++;
if (*str == ':')
@@ -2337,12 +2310,12 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
/**********************************************************************
* SBMAC_INIT(dev)
- *
+ *
* Attach routine - init hardware and hook ourselves into linux
- *
- * Input parameters:
+ *
+ * Input parameters:
* dev - net_device structure
- *
+ *
* Return value:
* status
********************************************************************* */
@@ -2354,53 +2327,53 @@ static int sbmac_init(struct net_device *dev, int idx)
uint64_t ea_reg;
int i;
int err;
-
+
sc = netdev_priv(dev);
-
+
/* Determine controller base address */
-
+
sc->sbm_base = IOADDR(dev->base_addr);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
-
+
eaddr = sc->sbm_hwaddr;
-
- /*
+
+ /*
* Read the ethernet address. The firwmare left this programmed
* for us in the ethernet address register for each mac.
*/
-
- ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
- SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
+
+ ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+ __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
for (i = 0; i < 6; i++) {
eaddr[i] = (uint8_t) (ea_reg & 0xFF);
ea_reg >>= 8;
}
-
+
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = eaddr[i];
}
-
-
+
+
/*
- * Init packet size
+ * Init packet size
*/
-
+
sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
- /*
+ /*
* Initialize context (get pointers to registers and stuff), then
* allocate the memory for the descriptor tables.
*/
-
+
sbmac_initctx(sc);
-
+
/*
* Set up Linux device callins
*/
-
+
spin_lock_init(&(sc->sbm_lock));
-
+
dev->open = sbmac_open;
dev->hard_start_xmit = sbmac_start_tx;
dev->stop = sbmac_close;
@@ -2419,7 +2392,7 @@ static int sbmac_init(struct net_device *dev, int idx)
if (err)
goto out_uninit;
- if (periph_rev >= 2) {
+ if (sc->rx_hw_checksum == ENABLE) {
printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
sc->sbm_dev->name);
}
@@ -2430,10 +2403,10 @@ static int sbmac_init(struct net_device *dev, int idx)
* was being displayed)
*/
printk(KERN_INFO
- "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
dev->name, dev->base_addr,
eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
-
+
return 0;
@@ -2447,54 +2420,86 @@ out_uninit:
static int sbmac_open(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
if (debug > 1) {
printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
}
-
- /*
+
+ /*
* map/route interrupt (clear status first, in case something
* weird is pending; we haven't initialized the mac registers
* yet)
*/
- SBMAC_READCSR(sc->sbm_isr);
+ __raw_readq(sc->sbm_isr);
if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
return -EBUSY;
/*
- * Configure default speed
+ * Probe phy address
+ */
+
+ if(sbmac_mii_probe(dev) == -1) {
+ printk("%s: failed to probe PHY.\n", dev->name);
+ return -EINVAL;
+ }
+
+ /*
+ * Configure default speed
*/
sbmac_mii_poll(sc,noisy_mii);
-
+
/*
* Turn on the channel
*/
sbmac_set_channel_state(sc,sbmac_state_on);
-
+
/*
* XXX Station address is in dev->dev_addr
*/
-
+
if (dev->if_port == 0)
- dev->if_port = 0;
-
+ dev->if_port = 0;
+
netif_start_queue(dev);
-
+
sbmac_set_rx_mode(dev);
-
+
/* Set the timer to check for link beat. */
init_timer(&sc->sbm_timer);
sc->sbm_timer.expires = jiffies + 2 * HZ/100;
sc->sbm_timer.data = (unsigned long)dev;
sc->sbm_timer.function = &sbmac_timer;
add_timer(&sc->sbm_timer);
-
+
return 0;
}
+static int sbmac_mii_probe(struct net_device *dev)
+{
+ int i;
+ struct sbmac_softc *s = netdev_priv(dev);
+ u16 bmsr, id1, id2;
+ u32 vendor, device;
+
+ for (i=1; i<31; i++) {
+ bmsr = sbmac_mii_read(s, i, MII_BMSR);
+ if (bmsr != 0) {
+ s->sbm_phys[0] = i;
+ id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
+ id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
+ vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
+ device = (id2 >> 4) & 0x3f;
+
+ printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
+ dev->name, i, vendor, device);
+ return i;
+ }
+ }
+ return -1;
+}
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
@@ -2609,20 +2614,20 @@ static void sbmac_timer(unsigned long data)
int mii_status;
spin_lock_irq (&sc->sbm_lock);
-
+
/* make IFF_RUNNING follow the MII status bit "Link established" */
mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
-
+
if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
if (mii_status & BMSR_LINKSTAT) {
netif_carrier_on(dev);
}
else {
- netif_carrier_off(dev);
+ netif_carrier_off(dev);
}
}
-
+
/*
* Poll the PHY to see what speed we should be running at
*/
@@ -2640,9 +2645,9 @@ static void sbmac_timer(unsigned long data)
sbmac_channel_start(sc);
}
}
-
+
spin_unlock_irq (&sc->sbm_lock);
-
+
sc->sbm_timer.expires = jiffies + next_tick;
add_timer(&sc->sbm_timer);
}
@@ -2651,13 +2656,13 @@ static void sbmac_timer(unsigned long data)
static void sbmac_tx_timeout (struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
-
+
spin_lock_irq (&sc->sbm_lock);
-
-
+
+
dev->trans_start = jiffies;
sc->sbm_stats.tx_errors++;
-
+
spin_unlock_irq (&sc->sbm_lock);
printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
@@ -2670,13 +2675,13 @@ static struct net_device_stats *sbmac_get_stats(struct net_device *dev)
{
struct sbmac_softc *sc = netdev_priv(dev);
unsigned long flags;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
-
+
/* XXX update other stats here */
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
return &sc->sbm_stats;
}
@@ -2693,8 +2698,8 @@ static void sbmac_set_rx_mode(struct net_device *dev)
/*
* Promiscuous changed.
*/
-
- if (dev->flags & IFF_PROMISC) {
+
+ if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
msg_flag = 1;
sbmac_promiscuous_mode(sc,1);
@@ -2705,18 +2710,18 @@ static void sbmac_set_rx_mode(struct net_device *dev)
}
}
spin_unlock_irqrestore(&sc->sbm_lock, flags);
-
+
if (msg_flag) {
printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
dev->name,(msg_flag==1)?"en":"dis");
}
-
+
/*
* Program the multicasts. Do this every time.
*/
-
+
sbmac_setmulti(sc);
-
+
}
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2725,10 +2730,10 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
u16 *data = (u16 *)&rq->ifr_ifru;
unsigned long flags;
int retval;
-
+
spin_lock_irqsave(&sc->sbm_lock, flags);
retval = 0;
-
+
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = sc->sbm_phys[0] & 0x1f;
@@ -2750,7 +2755,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
default:
retval = -EOPNOTSUPP;
}
-
+
spin_unlock_irqrestore(&sc->sbm_lock, flags);
return retval;
}
@@ -2781,7 +2786,7 @@ static int sbmac_close(struct net_device *dev)
sbdma_emptyring(&(sc->sbm_txdma));
sbdma_emptyring(&(sc->sbm_rxdma));
-
+
return 0;
}
@@ -2793,13 +2798,13 @@ sbmac_setup_hwaddr(int chan,char *addr)
{
uint8_t eaddr[6];
uint64_t val;
- sbmac_port_t port;
+ unsigned long port;
port = A_MAC_CHANNEL_BASE(chan);
sbmac_parse_hwaddr(addr,eaddr);
val = sbmac_addr2reg(eaddr);
- SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val);
- val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ __raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
+ val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
}
#endif
@@ -2810,9 +2815,9 @@ sbmac_init_module(void)
{
int idx;
struct net_device *dev;
- sbmac_port_t port;
+ unsigned long port;
int chip_max_units;
-
+
/*
* For bringup when not using the firmware, we can pre-fill
* the MAC addresses using the environment variables
@@ -2858,13 +2863,13 @@ sbmac_init_module(void)
port = A_MAC_CHANNEL_BASE(idx);
- /*
+ /*
* The R_MAC_ETHERNET_ADDR register will be set to some nonzero
* value for us by the firmware if we're going to use this MAC.
* If we find a zero, skip this MAC.
*/
- sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+ sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
if (sbmac_orig_hwaddr[idx] == 0) {
printk(KERN_DEBUG "sbmac: not configuring MAC at "
"%lx\n", port);
@@ -2876,7 +2881,7 @@ sbmac_init_module(void)
*/
dev = alloc_etherdev(sizeof(struct sbmac_softc));
- if (!dev)
+ if (!dev)
return -ENOMEM; /* return ENOMEM */
printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
@@ -2886,8 +2891,7 @@ sbmac_init_module(void)
dev->mem_end = 0;
if (sbmac_init(dev, idx)) {
port = A_MAC_CHANNEL_BASE(idx);
- SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
- sbmac_orig_hwaddr[idx]);
+ __raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
free_netdev(dev);
continue;
}
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 9bc3b1c0dd6a..a4614df38a90 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -32,8 +32,6 @@
#include "sgiseeq.h"
-static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
-
static char *sgiseeqstr = "SGI Seeq8003";
/*
@@ -113,9 +111,9 @@ static struct net_device *root_sgiseeq_dev;
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
- hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
+ hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
udelay(20);
- hregs->rx_reset = 0;
+ hregs->reset = 0;
}
static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
@@ -252,7 +250,6 @@ void sgiseeq_dump_rings(void)
#define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
#define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
-#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
struct sgiseeq_regs *sregs)
@@ -274,8 +271,6 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
sregs->tstat = TSTAT_INIT_SEEQ;
}
- hregs->rx_dconfig |= RDMACFG_INIT;
-
hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
@@ -446,7 +441,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
spin_lock(&sp->tx_lock);
/* Ack the IRQ and set software state. */
- hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
+ hregs->reset = HPC3_ERST_CLRIRQ;
/* Always check for received packets. */
sgiseeq_rx(dev, sp, hregs, sregs);
@@ -493,11 +488,13 @@ static int sgiseeq_close(struct net_device *dev)
{
struct sgiseeq_private *sp = netdev_priv(dev);
struct sgiseeq_regs *sregs = sp->sregs;
+ unsigned int irq = dev->irq;
netif_stop_queue(dev);
/* Shutdown the Seeq. */
reset_hpc3_and_seeq(sp->hregs, sregs);
+ free_irq(irq, dev);
return 0;
}
@@ -644,7 +641,7 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
-static int sgiseeq_init(struct hpc3_regs* regs, int irq)
+static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
{
struct sgiseeq_init_block *sr;
struct sgiseeq_private *sp;
@@ -680,8 +677,8 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
gpriv = sp;
gdev = dev;
#endif
- sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
- sp->hregs = &hpc3c0->ethregs;
+ sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
+ sp->hregs = &hpcregs->ethregs;
sp->name = sgiseeqstr;
sp->mode = SEEQ_RCMD_RBCAST;
@@ -698,6 +695,11 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
+ /* Setup PIO and DMA transfer timing */
+ sp->hregs->pconfig = 0x161;
+ sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
+ HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
+
/* Reset the chip. */
hpc3_eth_reset(sp->hregs);
@@ -724,7 +726,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
goto err_out_free_page;
}
- printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
+ printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
@@ -734,7 +736,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
return 0;
err_out_free_page:
- free_page((unsigned long) sp);
+ free_page((unsigned long) sp->srings);
err_out_free_dev:
kfree(dev);
@@ -744,8 +746,6 @@ err_out:
static int __init sgiseeq_probe(void)
{
- printk(version);
-
/* On board adapter on 1st HPC is always present */
return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
}
@@ -754,15 +754,12 @@ static void __exit sgiseeq_exit(void)
{
struct net_device *next, *dev;
struct sgiseeq_private *sp;
- int irq;
for (dev = root_sgiseeq_dev; dev; dev = next) {
sp = (struct sgiseeq_private *) netdev_priv(dev);
next = sp->next_module;
- irq = dev->irq;
unregister_netdev(dev);
- free_irq(irq, dev);
- free_page((unsigned long) sp);
+ free_page((unsigned long) sp->srings);
free_netdev(dev);
}
}
@@ -770,4 +767,6 @@ static void __exit sgiseeq_exit(void)
module_init(sgiseeq_probe);
module_exit(sgiseeq_exit);
+MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index 3ad0b6751f6f..221354eea21f 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -156,52 +156,6 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
SHAPERCB(skb)->shapelen= shaper_clocks(shaper,skb);
-#ifdef SHAPER_COMPLEX /* and broken.. */
-
- while(ptr && ptr!=(struct sk_buff *)&shaper->sendq)
- {
- if(ptr->pri<skb->pri
- && jiffies - SHAPERCB(ptr)->shapeclock < SHAPER_MAXSLIP)
- {
- struct sk_buff *tmp=ptr->prev;
-
- /*
- * It goes before us therefore we slip the length
- * of the new frame.
- */
-
- SHAPERCB(ptr)->shapeclock+=SHAPERCB(skb)->shapelen;
- SHAPERCB(ptr)->shapelatency+=SHAPERCB(skb)->shapelen;
-
- /*
- * The packet may have slipped so far back it
- * fell off.
- */
- if(SHAPERCB(ptr)->shapelatency > SHAPER_LATENCY)
- {
- skb_unlink(ptr);
- dev_kfree_skb(ptr);
- }
- ptr=tmp;
- }
- else
- break;
- }
- if(ptr==NULL || ptr==(struct sk_buff *)&shaper->sendq)
- skb_queue_head(&shaper->sendq,skb);
- else
- {
- struct sk_buff *tmp;
- /*
- * Set the packet clock out time according to the
- * frames ahead. Im sure a bit of thought could drop
- * this loop.
- */
- for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=ptr; tmp=tmp->next)
- SHAPERCB(skb)->shapeclock+=tmp->shapelen;
- skb_append(ptr,skb);
- }
-#else
{
struct sk_buff *tmp;
/*
@@ -220,7 +174,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
} else
skb_queue_tail(&shaper->sendq, skb);
}
-#endif
+
if(sh_debug)
printk("Frame queued.\n");
if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN)
@@ -302,7 +256,7 @@ static void shaper_kick(struct shaper *shaper)
* Pull the frame and get interrupts back on.
*/
- skb_unlink(skb);
+ skb_unlink(skb, &shaper->sendq);
if (shaper->recovery <
SHAPERCB(skb)->shapeclock + SHAPERCB(skb)->shapelen)
shaper->recovery = SHAPERCB(skb)->shapeclock + SHAPERCB(skb)->shapelen;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
new file mode 100644
index 000000000000..478791e09bf7
--- /dev/null
+++ b/drivers/net/sis190.c
@@ -0,0 +1,1884 @@
+/*
+ sis190.c: Silicon Integrated Systems SiS190 ethernet driver
+
+ Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
+ Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
+ Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
+
+ Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
+ genuine driver.
+
+ This software may be used and distributed according to the terms of
+ the GNU General Public License (GPL), incorporated herein by reference.
+ Drivers based on or derived from this code fall under the GPL and must
+ retain the authorship, copyright and license notice. This file is not
+ a complete program and may only be used when the entire operating
+ system is licensed under the GPL.
+
+ See the file COPYING in this distribution for more information.
+
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/mii.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <asm/irq.h>
+
+#define net_drv(p, arg...) if (netif_msg_drv(p)) \
+ printk(arg)
+#define net_probe(p, arg...) if (netif_msg_probe(p)) \
+ printk(arg)
+#define net_link(p, arg...) if (netif_msg_link(p)) \
+ printk(arg)
+#define net_intr(p, arg...) if (netif_msg_intr(p)) \
+ printk(arg)
+#define net_tx_err(p, arg...) if (netif_msg_tx_err(p)) \
+ printk(arg)
+
+#define PHY_MAX_ADDR 32
+#define PHY_ID_ANY 0x1f
+#define MII_REG_ANY 0x1f
+
+#ifdef CONFIG_SIS190_NAPI
+#define NAPI_SUFFIX "-NAPI"
+#else
+#define NAPI_SUFFIX ""
+#endif
+
+#define DRV_VERSION "1.2" NAPI_SUFFIX
+#define DRV_NAME "sis190"
+#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
+#define PFX DRV_NAME ": "
+
+#ifdef CONFIG_SIS190_NAPI
+#define sis190_rx_skb netif_receive_skb
+#define sis190_rx_quota(count, quota) min(count, quota)
+#else
+#define sis190_rx_skb netif_rx
+#define sis190_rx_quota(count, quota) count
+#endif
+
+#define MAC_ADDR_LEN 6
+
+#define NUM_TX_DESC 64 /* [8..1024] */
+#define NUM_RX_DESC 64 /* [8..8192] */
+#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
+#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
+#define RX_BUF_SIZE 1536
+#define RX_BUF_MASK 0xfff8
+
+#define SIS190_REGS_SIZE 0x80
+#define SIS190_TX_TIMEOUT (6*HZ)
+#define SIS190_PHY_TIMEOUT (10*HZ)
+#define SIS190_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+ NETIF_MSG_IFDOWN)
+
+/* Enhanced PHY access register bit definitions */
+#define EhnMIIread 0x0000
+#define EhnMIIwrite 0x0020
+#define EhnMIIdataShift 16
+#define EhnMIIpmdShift 6 /* 7016 only */
+#define EhnMIIregShift 11
+#define EhnMIIreq 0x0010
+#define EhnMIInotDone 0x0010
+
+/* Write/read MMIO register */
+#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
+#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
+#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
+#define SIS_R8(reg) readb (ioaddr + (reg))
+#define SIS_R16(reg) readw (ioaddr + (reg))
+#define SIS_R32(reg) readl (ioaddr + (reg))
+
+#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
+
+enum sis190_registers {
+ TxControl = 0x00,
+ TxDescStartAddr = 0x04,
+ rsv0 = 0x08, // reserved
+ TxSts = 0x0c, // unused (Control/Status)
+ RxControl = 0x10,
+ RxDescStartAddr = 0x14,
+ rsv1 = 0x18, // reserved
+ RxSts = 0x1c, // unused
+ IntrStatus = 0x20,
+ IntrMask = 0x24,
+ IntrControl = 0x28,
+ IntrTimer = 0x2c, // unused (Interupt Timer)
+ PMControl = 0x30, // unused (Power Mgmt Control/Status)
+ rsv2 = 0x34, // reserved
+ ROMControl = 0x38,
+ ROMInterface = 0x3c,
+ StationControl = 0x40,
+ GMIIControl = 0x44,
+ GIoCR = 0x48, // unused (GMAC IO Compensation)
+ GIoCtrl = 0x4c, // unused (GMAC IO Control)
+ TxMacControl = 0x50,
+ TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
+ RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
+ rsv3 = 0x5c, // reserved
+ RxMacControl = 0x60,
+ RxMacAddr = 0x62,
+ RxHashTable = 0x68,
+ // Undocumented = 0x6c,
+ RxWolCtrl = 0x70,
+ RxWolData = 0x74, // unused (Rx WOL Data Access)
+ RxMPSControl = 0x78, // unused (Rx MPS Control)
+ rsv4 = 0x7c, // reserved
+};
+
+enum sis190_register_content {
+ /* IntrStatus */
+ SoftInt = 0x40000000, // unused
+ Timeup = 0x20000000, // unused
+ PauseFrame = 0x00080000, // unused
+ MagicPacket = 0x00040000, // unused
+ WakeupFrame = 0x00020000, // unused
+ LinkChange = 0x00010000,
+ RxQEmpty = 0x00000080,
+ RxQInt = 0x00000040,
+ TxQ1Empty = 0x00000020, // unused
+ TxQ1Int = 0x00000010,
+ TxQ0Empty = 0x00000008, // unused
+ TxQ0Int = 0x00000004,
+ RxHalt = 0x00000002,
+ TxHalt = 0x00000001,
+
+ /* {Rx/Tx}CmdBits */
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08, // unused
+ CmdTxEnb = 0x01,
+ RxBufEmpty = 0x01, // unused
+
+ /* Cfg9346Bits */
+ Cfg9346_Lock = 0x00, // unused
+ Cfg9346_Unlock = 0xc0, // unused
+
+ /* RxMacControl */
+ AcceptErr = 0x20, // unused
+ AcceptRunt = 0x10, // unused
+ AcceptBroadcast = 0x0800,
+ AcceptMulticast = 0x0400,
+ AcceptMyPhys = 0x0200,
+ AcceptAllPhys = 0x0100,
+
+ /* RxConfigBits */
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8, // 0x1a in RxControl ?
+
+ /* TxConfigBits */
+ TxInterFrameGapShift = 24,
+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+
+ LinkStatus = 0x02, // unused
+ FullDup = 0x01, // unused
+
+ /* TBICSRBit */
+ TBILinkOK = 0x02000000, // unused
+};
+
+struct TxDesc {
+ __le32 PSize;
+ __le32 status;
+ __le32 addr;
+ __le32 size;
+};
+
+struct RxDesc {
+ __le32 PSize;
+ __le32 status;
+ __le32 addr;
+ __le32 size;
+};
+
+enum _DescStatusBit {
+ /* _Desc.status */
+ OWNbit = 0x80000000, // RXOWN/TXOWN
+ INTbit = 0x40000000, // RXINT/TXINT
+ CRCbit = 0x00020000, // CRCOFF/CRCEN
+ PADbit = 0x00010000, // PREADD/PADEN
+ /* _Desc.size */
+ RingEnd = 0x80000000,
+ /* TxDesc.status */
+ LSEN = 0x08000000, // TSO ? -- FR
+ IPCS = 0x04000000,
+ TCPCS = 0x02000000,
+ UDPCS = 0x01000000,
+ BSTEN = 0x00800000,
+ EXTEN = 0x00400000,
+ DEFEN = 0x00200000,
+ BKFEN = 0x00100000,
+ CRSEN = 0x00080000,
+ COLEN = 0x00040000,
+ THOL3 = 0x30000000,
+ THOL2 = 0x20000000,
+ THOL1 = 0x10000000,
+ THOL0 = 0x00000000,
+ /* RxDesc.status */
+ IPON = 0x20000000,
+ TCPON = 0x10000000,
+ UDPON = 0x08000000,
+ Wakup = 0x00400000,
+ Magic = 0x00200000,
+ Pause = 0x00100000,
+ DEFbit = 0x00200000,
+ BCAST = 0x000c0000,
+ MCAST = 0x00080000,
+ UCAST = 0x00040000,
+ /* RxDesc.PSize */
+ TAGON = 0x80000000,
+ RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
+ ABORT = 0x00800000,
+ SHORT = 0x00400000,
+ LIMIT = 0x00200000,
+ MIIER = 0x00100000,
+ OVRUN = 0x00080000,
+ NIBON = 0x00040000,
+ COLON = 0x00020000,
+ CRCOK = 0x00010000,
+ RxSizeMask = 0x0000ffff
+ /*
+ * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
+ * provide two (unused with Linux) Tx queues. No publically
+ * available documentation alas.
+ */
+};
+
+enum sis190_eeprom_access_register_bits {
+ EECS = 0x00000001, // unused
+ EECLK = 0x00000002, // unused
+ EEDO = 0x00000008, // unused
+ EEDI = 0x00000004, // unused
+ EEREQ = 0x00000080,
+ EEROP = 0x00000200,
+ EEWOP = 0x00000100 // unused
+};
+
+/* EEPROM Addresses */
+enum sis190_eeprom_address {
+ EEPROMSignature = 0x00,
+ EEPROMCLK = 0x01, // unused
+ EEPROMInfo = 0x02,
+ EEPROMMACAddr = 0x03
+};
+
+enum sis190_feature {
+ F_HAS_RGMII = 1,
+ F_PHY_88E1111 = 2,
+ F_PHY_BCM5461 = 4
+};
+
+struct sis190_private {
+ void __iomem *mmio_addr;
+ struct pci_dev *pci_dev;
+ struct net_device_stats stats;
+ spinlock_t lock;
+ u32 rx_buf_sz;
+ u32 cur_rx;
+ u32 cur_tx;
+ u32 dirty_rx;
+ u32 dirty_tx;
+ dma_addr_t rx_dma;
+ dma_addr_t tx_dma;
+ struct RxDesc *RxDescRing;
+ struct TxDesc *TxDescRing;
+ struct sk_buff *Rx_skbuff[NUM_RX_DESC];
+ struct sk_buff *Tx_skbuff[NUM_TX_DESC];
+ struct work_struct phy_task;
+ struct timer_list timer;
+ u32 msg_enable;
+ struct mii_if_info mii_if;
+ struct list_head first_phy;
+ u32 features;
+};
+
+struct sis190_phy {
+ struct list_head list;
+ int phy_id;
+ u16 id[2];
+ u16 status;
+ u8 type;
+};
+
+enum sis190_phy_type {
+ UNKNOWN = 0x00,
+ HOME = 0x01,
+ LAN = 0x02,
+ MIX = 0x03
+};
+
+static struct mii_chip_info {
+ const char *name;
+ u16 id[2];
+ unsigned int type;
+ u32 feature;
+} mii_chip_table[] = {
+ { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+ { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
+ { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
+ { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
+ { NULL, }
+};
+
+const static struct {
+ const char *name;
+} sis_chip_info[] = {
+ { "SiS 190 PCI Fast Ethernet adapter" },
+ { "SiS 191 PCI Gigabit Ethernet adapter" },
+};
+
+static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, sis190_pci_tbl);
+
+static int rx_copybreak = 200;
+
+static struct {
+ u32 msg_enable;
+} debug = { -1 };
+
+MODULE_DESCRIPTION("SiS sis190 Gigabit Ethernet driver");
+module_param(rx_copybreak, int, 0);
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+module_param_named(debug, debug.msg_enable, int, 0);
+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>, Ueimor <romieu@fr.zoreil.com>");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
+static const u32 sis190_intr_mask =
+ RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
+
+/*
+ * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+ * The chips use a 64 element hash table based on the Ethernet CRC.
+ */
+static int multicast_filter_limit = 32;
+
+static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
+{
+ unsigned int i;
+
+ SIS_W32(GMIIControl, ctl);
+
+ msleep(1);
+
+ for (i = 0; i < 100; i++) {
+ if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
+ break;
+ msleep(1);
+ }
+
+ if (i > 999)
+ printk(KERN_ERR PFX "PHY command failed !\n");
+}
+
+static void mdio_write(void __iomem *ioaddr, int phy_id, int reg, int val)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
+ (((u32) val) << EhnMIIdataShift));
+}
+
+static int mdio_read(void __iomem *ioaddr, int phy_id, int reg)
+{
+ __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
+ (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
+
+ return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
+}
+
+static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ mdio_write(tp->mmio_addr, phy_id, reg, val);
+}
+
+static int __mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mdio_read(tp->mmio_addr, phy_id, reg);
+}
+
+static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
+{
+ mdio_read(ioaddr, phy_id, reg);
+ return mdio_read(ioaddr, phy_id, reg);
+}
+
+static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
+{
+ u16 data = 0xffff;
+ unsigned int i;
+
+ if (!(SIS_R32(ROMControl) & 0x0002))
+ return 0;
+
+ SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
+
+ for (i = 0; i < 200; i++) {
+ if (!(SIS_R32(ROMInterface) & EEREQ)) {
+ data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
+ break;
+ }
+ msleep(1);
+ }
+
+ return data;
+}
+
+static void sis190_irq_mask_and_ack(void __iomem *ioaddr)
+{
+ SIS_W32(IntrMask, 0x00);
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_PCI_COMMIT();
+}
+
+static void sis190_asic_down(void __iomem *ioaddr)
+{
+ /* Stop the chip's Tx and Rx DMA processes. */
+
+ SIS_W32(TxControl, 0x1a00);
+ SIS_W32(RxControl, 0x1a00);
+
+ sis190_irq_mask_and_ack(ioaddr);
+}
+
+static void sis190_mark_as_last_descriptor(struct RxDesc *desc)
+{
+ desc->size |= cpu_to_le32(RingEnd);
+}
+
+static inline void sis190_give_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
+{
+ u32 eor = le32_to_cpu(desc->size) & RingEnd;
+
+ desc->PSize = 0x0;
+ desc->size = cpu_to_le32((rx_buf_sz & RX_BUF_MASK) | eor);
+ wmb();
+ desc->status = cpu_to_le32(OWNbit | INTbit);
+}
+
+static inline void sis190_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
+ u32 rx_buf_sz)
+{
+ desc->addr = cpu_to_le32(mapping);
+ sis190_give_to_asic(desc, rx_buf_sz);
+}
+
+static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
+{
+ desc->PSize = 0x0;
+ desc->addr = 0xdeadbeef;
+ desc->size &= cpu_to_le32(RingEnd);
+ wmb();
+ desc->status = 0x0;
+}
+
+static int sis190_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+ struct RxDesc *desc, u32 rx_buf_sz)
+{
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ int ret = 0;
+
+ skb = dev_alloc_skb(rx_buf_sz);
+ if (!skb)
+ goto err_out;
+
+ *sk_buff = skb;
+
+ mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+
+ sis190_map_to_asic(desc, mapping, rx_buf_sz);
+out:
+ return ret;
+
+err_out:
+ ret = -ENOMEM;
+ sis190_make_unusable_by_asic(desc);
+ goto out;
+}
+
+static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
+ u32 start, u32 end)
+{
+ u32 cur;
+
+ for (cur = start; cur < end; cur++) {
+ int ret, i = cur % NUM_RX_DESC;
+
+ if (tp->Rx_skbuff[i])
+ continue;
+
+ ret = sis190_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+ tp->RxDescRing + i, tp->rx_buf_sz);
+ if (ret < 0)
+ break;
+ }
+ return cur - start;
+}
+
+static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+ struct RxDesc *desc, int rx_buf_sz)
+{
+ int ret = -1;
+
+ if (pkt_size < rx_copybreak) {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
+ if (skb) {
+ skb_reserve(skb, NET_IP_ALIGN);
+ eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+ *sk_buff = skb;
+ sis190_give_to_asic(desc, rx_buf_sz);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
+{
+#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
+
+ if ((status & CRCOK) && !(status & ErrMask))
+ return 0;
+
+ if (!(status & CRCOK))
+ stats->rx_crc_errors++;
+ else if (status & OVRUN)
+ stats->rx_over_errors++;
+ else if (status & (SHORT | LIMIT))
+ stats->rx_length_errors++;
+ else if (status & (MIIER | NIBON | COLON))
+ stats->rx_frame_errors++;
+
+ stats->rx_errors++;
+ return -1;
+}
+
+static int sis190_rx_interrupt(struct net_device *dev,
+ struct sis190_private *tp, void __iomem *ioaddr)
+{
+ struct net_device_stats *stats = &tp->stats;
+ u32 rx_left, cur_rx = tp->cur_rx;
+ u32 delta, count;
+
+ rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+ rx_left = sis190_rx_quota(rx_left, (u32) dev->quota);
+
+ for (; rx_left > 0; rx_left--, cur_rx++) {
+ unsigned int entry = cur_rx % NUM_RX_DESC;
+ struct RxDesc *desc = tp->RxDescRing + entry;
+ u32 status;
+
+ if (desc->status & OWNbit)
+ break;
+
+ status = le32_to_cpu(desc->PSize);
+
+ // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name,
+ // status);
+
+ if (sis190_rx_pkt_err(status, stats) < 0)
+ sis190_give_to_asic(desc, tp->rx_buf_sz);
+ else {
+ struct sk_buff *skb = tp->Rx_skbuff[entry];
+ int pkt_size = (status & RxSizeMask) - 4;
+ void (*pci_action)(struct pci_dev *, dma_addr_t,
+ size_t, int) = pci_dma_sync_single_for_device;
+
+ if (unlikely(pkt_size > tp->rx_buf_sz)) {
+ net_intr(tp, KERN_INFO
+ "%s: (frag) status = %08x.\n",
+ dev->name, status);
+ stats->rx_dropped++;
+ stats->rx_length_errors++;
+ sis190_give_to_asic(desc, tp->rx_buf_sz);
+ continue;
+ }
+
+ pci_dma_sync_single_for_cpu(tp->pci_dev,
+ le32_to_cpu(desc->addr), tp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+
+ if (sis190_try_rx_copy(&skb, pkt_size, desc,
+ tp->rx_buf_sz)) {
+ pci_action = pci_unmap_single;
+ tp->Rx_skbuff[entry] = NULL;
+ sis190_make_unusable_by_asic(desc);
+ }
+
+ pci_action(tp->pci_dev, le32_to_cpu(desc->addr),
+ tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+
+ skb->dev = dev;
+ skb_put(skb, pkt_size);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ sis190_rx_skb(skb);
+
+ dev->last_rx = jiffies;
+ stats->rx_packets++;
+ stats->rx_bytes += pkt_size;
+ if ((status & BCAST) == MCAST)
+ stats->multicast++;
+ }
+ }
+ count = cur_rx - tp->cur_rx;
+ tp->cur_rx = cur_rx;
+
+ delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+ if (!delta && count && netif_msg_intr(tp))
+ printk(KERN_INFO "%s: no Rx buffer allocated.\n", dev->name);
+ tp->dirty_rx += delta;
+
+ if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx) && netif_msg_intr(tp))
+ printk(KERN_EMERG "%s: Rx buffers exhausted.\n", dev->name);
+
+ return count;
+}
+
+static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+ struct TxDesc *desc)
+{
+ unsigned int len;
+
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+ pci_unmap_single(pdev, le32_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+
+ memset(desc, 0x00, sizeof(*desc));
+}
+
+static void sis190_tx_interrupt(struct net_device *dev,
+ struct sis190_private *tp, void __iomem *ioaddr)
+{
+ u32 pending, dirty_tx = tp->dirty_tx;
+ /*
+ * It would not be needed if queueing was allowed to be enabled
+ * again too early (hint: think preempt and unclocked smp systems).
+ */
+ unsigned int queue_stopped;
+
+ smp_rmb();
+ pending = tp->cur_tx - dirty_tx;
+ queue_stopped = (pending == NUM_TX_DESC);
+
+ for (; pending; pending--, dirty_tx++) {
+ unsigned int entry = dirty_tx % NUM_TX_DESC;
+ struct TxDesc *txd = tp->TxDescRing + entry;
+ struct sk_buff *skb;
+
+ if (le32_to_cpu(txd->status) & OWNbit)
+ break;
+
+ skb = tp->Tx_skbuff[entry];
+
+ tp->stats.tx_packets++;
+ tp->stats.tx_bytes += skb->len;
+
+ sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
+ tp->Tx_skbuff[entry] = NULL;
+ dev_kfree_skb_irq(skb);
+ }
+
+ if (tp->dirty_tx != dirty_tx) {
+ tp->dirty_tx = dirty_tx;
+ smp_wmb();
+ if (queue_stopped)
+ netif_wake_queue(dev);
+ }
+}
+
+/*
+ * The interrupt handler does all of the Rx thread work and cleans up after
+ * the Tx thread.
+ */
+static irqreturn_t sis190_interrupt(int irq, void *__dev, struct pt_regs *regs)
+{
+ struct net_device *dev = __dev;
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned int handled = 0;
+ u32 status;
+
+ status = SIS_R32(IntrStatus);
+
+ if ((status == 0xffffffff) || !status)
+ goto out;
+
+ handled = 1;
+
+ if (unlikely(!netif_running(dev))) {
+ sis190_asic_down(ioaddr);
+ goto out;
+ }
+
+ SIS_W32(IntrStatus, status);
+
+ // net_intr(tp, KERN_INFO "%s: status = %08x.\n", dev->name, status);
+
+ if (status & LinkChange) {
+ net_intr(tp, KERN_INFO "%s: link change.\n", dev->name);
+ schedule_work(&tp->phy_task);
+ }
+
+ if (status & RxQInt)
+ sis190_rx_interrupt(dev, tp, ioaddr);
+
+ if (status & TxQ0Int)
+ sis190_tx_interrupt(dev, tp, ioaddr);
+out:
+ return IRQ_RETVAL(handled);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void sis190_netpoll(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+
+ disable_irq(pdev->irq);
+ sis190_interrupt(pdev->irq, dev, NULL);
+ enable_irq(pdev->irq);
+}
+#endif
+
+static void sis190_free_rx_skb(struct sis190_private *tp,
+ struct sk_buff **sk_buff, struct RxDesc *desc)
+{
+ struct pci_dev *pdev = tp->pci_dev;
+
+ pci_unmap_single(pdev, le32_to_cpu(desc->addr), tp->rx_buf_sz,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(*sk_buff);
+ *sk_buff = NULL;
+ sis190_make_unusable_by_asic(desc);
+}
+
+static void sis190_rx_clear(struct sis190_private *tp)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ if (!tp->Rx_skbuff[i])
+ continue;
+ sis190_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescRing + i);
+ }
+}
+
+static void sis190_init_ring_indexes(struct sis190_private *tp)
+{
+ tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
+}
+
+static int sis190_init_ring(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_init_ring_indexes(tp);
+
+ memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+ memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
+
+ if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+ goto err_rx_clear;
+
+ sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
+
+ return 0;
+
+err_rx_clear:
+ sis190_rx_clear(tp);
+ return -ENOMEM;
+}
+
+static void sis190_set_rx_mode(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned long flags;
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u16 rx_mode;
+
+ if (dev->flags & IFF_PROMISC) {
+ /* Unconditionally log net taps. */
+ net_drv(tp, KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+ dev->name);
+ rx_mode =
+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+ AcceptAllPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else if ((dev->mc_count > multicast_filter_limit) ||
+ (dev->flags & IFF_ALLMULTI)) {
+ /* Too many to filter perfectly -- accept all multicasts. */
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else {
+ struct dev_mc_list *mclist;
+ unsigned int i;
+
+ rx_mode = AcceptBroadcast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0;
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next) {
+ int bit_nr =
+ ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f;
+ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+ rx_mode |= AcceptMulticast;
+ }
+ }
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ SIS_W16(RxMacControl, rx_mode | 0x2);
+ SIS_W32(RxHashTable, mc_filter[0]);
+ SIS_W32(RxHashTable + 4, mc_filter[1]);
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static void sis190_soft_reset(void __iomem *ioaddr)
+{
+ SIS_W32(IntrControl, 0x8000);
+ SIS_PCI_COMMIT();
+ msleep(1);
+ SIS_W32(IntrControl, 0x0);
+ sis190_asic_down(ioaddr);
+ msleep(1);
+}
+
+static void sis190_hw_start(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ sis190_soft_reset(ioaddr);
+
+ SIS_W32(TxDescStartAddr, tp->tx_dma);
+ SIS_W32(RxDescStartAddr, tp->rx_dma);
+
+ SIS_W32(IntrStatus, 0xffffffff);
+ SIS_W32(IntrMask, 0x0);
+ SIS_W32(GMIIControl, 0x0);
+ SIS_W32(TxMacControl, 0x60);
+ SIS_W16(RxMacControl, 0x02);
+ SIS_W32(RxHashTable, 0x0);
+ SIS_W32(0x6c, 0x0);
+ SIS_W32(RxWolCtrl, 0x0);
+ SIS_W32(RxWolData, 0x0);
+
+ SIS_PCI_COMMIT();
+
+ sis190_set_rx_mode(dev);
+
+ /* Enable all known interrupts by setting the interrupt mask. */
+ SIS_W32(IntrMask, sis190_intr_mask);
+
+ SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
+ SIS_W32(RxControl, 0x1a1d);
+
+ netif_start_queue(dev);
+}
+
+static void sis190_phy_task(void * data)
+{
+ struct net_device *dev = data;
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 val;
+
+ rtnl_lock();
+
+ val = mdio_read(ioaddr, phy_id, MII_BMCR);
+ if (val & BMCR_RESET) {
+ // FIXME: needlessly high ? -- FR 02/07/2005
+ mod_timer(&tp->timer, jiffies + HZ/10);
+ } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
+ BMSR_ANEGCOMPLETE)) {
+ net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
+ dev->name);
+ netif_carrier_off(dev);
+ mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
+ mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
+ } else {
+ /* Rejoice ! */
+ struct {
+ int val;
+ u32 ctl;
+ const char *msg;
+ } reg31[] = {
+ { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
+ "1000 Mbps Full Duplex" },
+ { LPA_1000XHALF | LPA_SLCT, 0x07000c00,
+ "1000 Mbps Half Duplex" },
+ { LPA_100FULL, 0x04000800 | 0x00001000,
+ "100 Mbps Full Duplex" },
+ { LPA_100HALF, 0x04000800,
+ "100 Mbps Half Duplex" },
+ { LPA_10FULL, 0x04000400 | 0x00001000,
+ "10 Mbps Full Duplex" },
+ { LPA_10HALF, 0x04000400,
+ "10 Mbps Half Duplex" },
+ { 0, 0x04000400, "unknown" }
+ }, *p;
+ u16 adv;
+
+ val = mdio_read(ioaddr, phy_id, 0x1f);
+ net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val);
+
+ val = mdio_read(ioaddr, phy_id, MII_LPA);
+ adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+ net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n",
+ dev->name, val, adv);
+
+ val &= adv;
+
+ for (p = reg31; p->val; p++) {
+ if ((val & p->val) == p->val)
+ break;
+ }
+
+ p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
+
+ if ((tp->features & F_HAS_RGMII) &&
+ (tp->features & F_PHY_BCM5461)) {
+ // Set Tx Delay in RGMII mode.
+ mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+ p->ctl |= 0x03000000;
+ }
+
+ SIS_W32(StationControl, p->ctl);
+
+ if (tp->features & F_HAS_RGMII) {
+ SIS_W32(RGDelay, 0x0441);
+ SIS_W32(RGDelay, 0x0440);
+ }
+
+ net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
+ p->msg);
+ netif_carrier_on(dev);
+ }
+
+ rtnl_unlock();
+}
+
+static void sis190_phy_timer(unsigned long __opaque)
+{
+ struct net_device *dev = (struct net_device *)__opaque;
+ struct sis190_private *tp = netdev_priv(dev);
+
+ if (likely(netif_running(dev)))
+ schedule_work(&tp->phy_task);
+}
+
+static inline void sis190_delete_timer(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ del_timer_sync(&tp->timer);
+}
+
+static inline void sis190_request_timer(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct timer_list *timer = &tp->timer;
+
+ init_timer(timer);
+ timer->expires = jiffies + SIS190_PHY_TIMEOUT;
+ timer->data = (unsigned long)dev;
+ timer->function = sis190_phy_timer;
+ add_timer(timer);
+}
+
+static void sis190_set_rxbufsize(struct sis190_private *tp,
+ struct net_device *dev)
+{
+ unsigned int mtu = dev->mtu;
+
+ tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
+ /* RxDesc->size has a licence to kill the lower bits */
+ if (tp->rx_buf_sz & 0x07) {
+ tp->rx_buf_sz += 8;
+ tp->rx_buf_sz &= RX_BUF_MASK;
+ }
+}
+
+static int sis190_open(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+ int rc = -ENOMEM;
+
+ sis190_set_rxbufsize(tp, dev);
+
+ /*
+ * Rx and Tx descriptors need 256 bytes alignment.
+ * pci_alloc_consistent() guarantees a stronger alignment.
+ */
+ tp->TxDescRing = pci_alloc_consistent(pdev, TX_RING_BYTES, &tp->tx_dma);
+ if (!tp->TxDescRing)
+ goto out;
+
+ tp->RxDescRing = pci_alloc_consistent(pdev, RX_RING_BYTES, &tp->rx_dma);
+ if (!tp->RxDescRing)
+ goto err_free_tx_0;
+
+ rc = sis190_init_ring(dev);
+ if (rc < 0)
+ goto err_free_rx_1;
+
+ INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+
+ sis190_request_timer(dev);
+
+ rc = request_irq(dev->irq, sis190_interrupt, SA_SHIRQ, dev->name, dev);
+ if (rc < 0)
+ goto err_release_timer_2;
+
+ sis190_hw_start(dev);
+out:
+ return rc;
+
+err_release_timer_2:
+ sis190_delete_timer(dev);
+ sis190_rx_clear(tp);
+err_free_rx_1:
+ pci_free_consistent(tp->pci_dev, RX_RING_BYTES, tp->RxDescRing,
+ tp->rx_dma);
+err_free_tx_0:
+ pci_free_consistent(tp->pci_dev, TX_RING_BYTES, tp->TxDescRing,
+ tp->tx_dma);
+ goto out;
+}
+
+static void sis190_tx_clear(struct sis190_private *tp)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_TX_DESC; i++) {
+ struct sk_buff *skb = tp->Tx_skbuff[i];
+
+ if (!skb)
+ continue;
+
+ sis190_unmap_tx_skb(tp->pci_dev, skb, tp->TxDescRing + i);
+ tp->Tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+
+ tp->stats.tx_dropped++;
+ }
+ tp->cur_tx = tp->dirty_tx = 0;
+}
+
+static void sis190_down(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ unsigned int poll_locked = 0;
+
+ sis190_delete_timer(dev);
+
+ netif_stop_queue(dev);
+
+ flush_scheduled_work();
+
+ do {
+ spin_lock_irq(&tp->lock);
+
+ sis190_asic_down(ioaddr);
+
+ spin_unlock_irq(&tp->lock);
+
+ synchronize_irq(dev->irq);
+
+ if (!poll_locked) {
+ netif_poll_disable(dev);
+ poll_locked++;
+ }
+
+ synchronize_sched();
+
+ } while (SIS_R32(IntrMask));
+
+ sis190_tx_clear(tp);
+ sis190_rx_clear(tp);
+}
+
+static int sis190_close(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *pdev = tp->pci_dev;
+
+ sis190_down(dev);
+
+ free_irq(dev->irq, dev);
+
+ netif_poll_enable(dev);
+
+ pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
+ pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
+
+ tp->TxDescRing = NULL;
+ tp->RxDescRing = NULL;
+
+ return 0;
+}
+
+static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u32 len, entry, dirty_tx;
+ struct TxDesc *desc;
+ dma_addr_t mapping;
+
+ if (unlikely(skb->len < ETH_ZLEN)) {
+ skb = skb_padto(skb, ETH_ZLEN);
+ if (!skb) {
+ tp->stats.tx_dropped++;
+ goto out;
+ }
+ len = ETH_ZLEN;
+ } else {
+ len = skb->len;
+ }
+
+ entry = tp->cur_tx % NUM_TX_DESC;
+ desc = tp->TxDescRing + entry;
+
+ if (unlikely(le32_to_cpu(desc->status) & OWNbit)) {
+ netif_stop_queue(dev);
+ net_tx_err(tp, KERN_ERR PFX
+ "%s: BUG! Tx Ring full when queue awake!\n",
+ dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
+
+ tp->Tx_skbuff[entry] = skb;
+
+ desc->PSize = cpu_to_le32(len);
+ desc->addr = cpu_to_le32(mapping);
+
+ desc->size = cpu_to_le32(len);
+ if (entry == (NUM_TX_DESC - 1))
+ desc->size |= cpu_to_le32(RingEnd);
+
+ wmb();
+
+ desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
+
+ tp->cur_tx++;
+
+ smp_wmb();
+
+ SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
+
+ dev->trans_start = jiffies;
+
+ dirty_tx = tp->dirty_tx;
+ if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
+ netif_stop_queue(dev);
+ smp_rmb();
+ if (dirty_tx != tp->dirty_tx)
+ netif_wake_queue(dev);
+ }
+out:
+ return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *sis190_get_stats(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return &tp->stats;
+}
+
+static void sis190_free_phy(struct list_head *first_phy)
+{
+ struct sis190_phy *cur, *next;
+
+ list_for_each_entry_safe(cur, next, first_phy, list) {
+ kfree(cur);
+ }
+}
+
+/**
+ * sis190_default_phy - Select default PHY for sis190 mac.
+ * @dev: the net device to probe for
+ *
+ * Select first detected PHY with link as default.
+ * If no one is link on, select PHY whose types is HOME as default.
+ * If HOME doesn't exist, select LAN.
+ */
+static u16 sis190_default_phy(struct net_device *dev)
+{
+ struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
+ struct sis190_private *tp = netdev_priv(dev);
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 status;
+
+ phy_home = phy_default = phy_lan = NULL;
+
+ list_for_each_entry(phy, &tp->first_phy, list) {
+ status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
+
+ // Link ON & Not select default PHY & not ghost PHY.
+ if ((status & BMSR_LSTATUS) &&
+ !phy_default &&
+ (phy->type != UNKNOWN)) {
+ phy_default = phy;
+ } else {
+ status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
+ mdio_write(ioaddr, phy->phy_id, MII_BMCR,
+ status | BMCR_ANENABLE | BMCR_ISOLATE);
+ if (phy->type == HOME)
+ phy_home = phy;
+ else if (phy->type == LAN)
+ phy_lan = phy;
+ }
+ }
+
+ if (!phy_default) {
+ if (phy_home)
+ phy_default = phy_home;
+ else if (phy_lan)
+ phy_default = phy_lan;
+ else
+ phy_default = list_entry(&tp->first_phy,
+ struct sis190_phy, list);
+ }
+
+ if (mii_if->phy_id != phy_default->phy_id) {
+ mii_if->phy_id = phy_default->phy_id;
+ net_probe(tp, KERN_INFO
+ "%s: Using transceiver at address %d as default.\n",
+ pci_name(tp->pci_dev), mii_if->phy_id);
+ }
+
+ status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
+ status &= (~BMCR_ISOLATE);
+
+ mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
+ status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
+
+ return status;
+}
+
+static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp,
+ struct sis190_phy *phy, unsigned int phy_id,
+ u16 mii_status)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct mii_chip_info *p;
+
+ INIT_LIST_HEAD(&phy->list);
+ phy->status = mii_status;
+ phy->phy_id = phy_id;
+
+ phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
+ phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
+
+ for (p = mii_chip_table; p->type; p++) {
+ if ((p->id[0] == phy->id[0]) &&
+ (p->id[1] == (phy->id[1] & 0xfff0))) {
+ break;
+ }
+ }
+
+ if (p->id[1]) {
+ phy->type = (p->type == MIX) ?
+ ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
+ LAN : HOME) : p->type;
+ tp->features |= p->feature;
+ } else
+ phy->type = UNKNOWN;
+
+ net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
+ pci_name(tp->pci_dev),
+ (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
+}
+
+static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+{
+ if (tp->features & F_PHY_88E1111) {
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ u16 reg[2][2] = {
+ { 0x808b, 0x0ce1 },
+ { 0x808f, 0x0c60 }
+ }, *p;
+
+ p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
+
+ mdio_write(ioaddr, phy_id, 0x1b, p[0]);
+ udelay(200);
+ mdio_write(ioaddr, phy_id, 0x14, p[1]);
+ udelay(200);
+ }
+}
+
+/**
+ * sis190_mii_probe - Probe MII PHY for sis190
+ * @dev: the net device to probe for
+ *
+ * Search for total of 32 possible mii phy addresses.
+ * Identify and set current phy if found one,
+ * return error if it failed to found.
+ */
+static int __devinit sis190_mii_probe(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct mii_if_info *mii_if = &tp->mii_if;
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id;
+ int rc = 0;
+
+ INIT_LIST_HEAD(&tp->first_phy);
+
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ struct sis190_phy *phy;
+ u16 status;
+
+ status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
+
+ // Try next mii if the current one is not accessible.
+ if (status == 0xffff || status == 0x0000)
+ continue;
+
+ phy = kmalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy) {
+ sis190_free_phy(&tp->first_phy);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ sis190_init_phy(dev, tp, phy, phy_id, status);
+
+ list_add(&tp->first_phy, &phy->list);
+ }
+
+ if (list_empty(&tp->first_phy)) {
+ net_probe(tp, KERN_INFO "%s: No MII transceivers found!\n",
+ pci_name(tp->pci_dev));
+ rc = -EIO;
+ goto out;
+ }
+
+ /* Select default PHY for mac */
+ sis190_default_phy(dev);
+
+ sis190_mii_probe_88e1111_fixup(tp);
+
+ mii_if->dev = dev;
+ mii_if->mdio_read = __mdio_read;
+ mii_if->mdio_write = __mdio_write;
+ mii_if->phy_id_mask = PHY_ID_ANY;
+ mii_if->reg_num_mask = MII_REG_ANY;
+out:
+ return rc;
+}
+
+static void __devexit sis190_mii_remove(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ sis190_free_phy(&tp->first_phy);
+}
+
+static void sis190_release_board(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct sis190_private *tp = netdev_priv(dev);
+
+ iounmap(tp->mmio_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ free_netdev(dev);
+}
+
+static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
+{
+ struct sis190_private *tp;
+ struct net_device *dev;
+ void __iomem *ioaddr;
+ int rc;
+
+ dev = alloc_etherdev(sizeof(*tp));
+ if (!dev) {
+ net_drv(&debug, KERN_ERR PFX "unable to alloc new ethernet\n");
+ rc = -ENOMEM;
+ goto err_out_0;
+ }
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ tp = netdev_priv(dev);
+ tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
+
+ rc = pci_enable_device(pdev);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR "%s: enable failure\n", pci_name(pdev));
+ goto err_free_dev_1;
+ }
+
+ rc = -ENODEV;
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ net_probe(tp, KERN_ERR "%s: region #0 is no MMIO resource.\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+ if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) {
+ net_probe(tp, KERN_ERR "%s: invalid PCI region size(s).\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR PFX "%s: could not request regions.\n",
+ pci_name(pdev));
+ goto err_pci_disable_2;
+ }
+
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc < 0) {
+ net_probe(tp, KERN_ERR "%s: DMA configuration failed.\n",
+ pci_name(pdev));
+ goto err_free_res_3;
+ }
+
+ pci_set_master(pdev);
+
+ ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE);
+ if (!ioaddr) {
+ net_probe(tp, KERN_ERR "%s: cannot remap MMIO, aborting\n",
+ pci_name(pdev));
+ rc = -EIO;
+ goto err_free_res_3;
+ }
+
+ tp->pci_dev = pdev;
+ tp->mmio_addr = ioaddr;
+
+ sis190_irq_mask_and_ack(ioaddr);
+
+ sis190_soft_reset(ioaddr);
+out:
+ return dev;
+
+err_free_res_3:
+ pci_release_regions(pdev);
+err_pci_disable_2:
+ pci_disable_device(pdev);
+err_free_dev_1:
+ free_netdev(dev);
+err_out_0:
+ dev = ERR_PTR(rc);
+ goto out;
+}
+
+static void sis190_tx_timeout(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u8 tmp8;
+
+ /* Disable Tx, if not already */
+ tmp8 = SIS_R8(TxControl);
+ if (tmp8 & CmdTxEnb)
+ SIS_W8(TxControl, tmp8 & ~CmdTxEnb);
+
+
+ net_tx_err(tp, KERN_INFO "%s: Transmit timeout, status %08x %08x.\n",
+ dev->name, SIS_R32(TxControl), SIS_R32(TxSts));
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ SIS_W32(IntrMask, 0x0000);
+
+ /* Stop a shared interrupt from scavenging while we are. */
+ spin_lock_irq(&tp->lock);
+ sis190_tx_clear(tp);
+ spin_unlock_irq(&tp->lock);
+
+ /* ...and finally, reset everything. */
+ sis190_hw_start(dev);
+
+ netif_wake_queue(dev);
+}
+
+static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+{
+ tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+}
+
+static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 sig;
+ int i;
+
+ net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n",
+ pci_name(pdev));
+
+ /* Check to see if there is a sane EEPROM */
+ sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
+
+ if ((sig == 0xffff) || (sig == 0x0000)) {
+ net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n",
+ pci_name(pdev), sig);
+ return -EIO;
+ }
+
+ /* Get MAC address from EEPROM */
+ for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
+ __le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
+
+ ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
+ }
+
+ sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
+
+ return 0;
+}
+
+/**
+ * sis190_get_mac_addr_from_apc - Get MAC address for SiS965 model
+ * @pdev: PCI device
+ * @dev: network device to get address for
+ *
+ * SiS965 model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
+ struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ struct pci_dev *isa_bridge;
+ u8 reg, tmp8;
+ int i;
+
+ net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n",
+ pci_name(pdev));
+
+ isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0965, NULL);
+ if (!isa_bridge) {
+ net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
+ pci_name(pdev));
+ return -EIO;
+ }
+
+ /* Enable port 78h & 79h to access APC Registers. */
+ pci_read_config_byte(isa_bridge, 0x48, &tmp8);
+ reg = (tmp8 & ~0x02);
+ pci_write_config_byte(isa_bridge, 0x48, reg);
+ udelay(50);
+ pci_read_config_byte(isa_bridge, 0x48, &reg);
+
+ for (i = 0; i < MAC_ADDR_LEN; i++) {
+ outb(0x9 + i, 0x78);
+ dev->dev_addr[i] = inb(0x79);
+ }
+
+ outb(0x12, 0x78);
+ reg = inb(0x79);
+
+ sis190_set_rgmii(tp, reg);
+
+ /* Restore the value to ISA Bridge */
+ pci_write_config_byte(isa_bridge, 0x48, tmp8);
+ pci_dev_put(isa_bridge);
+
+ return 0;
+}
+
+/**
+ * sis190_init_rxfilter - Initialize the Rx filter
+ * @dev: network device to initialize
+ *
+ * Set receive filter address to our MAC address
+ * and enable packet filtering.
+ */
+static inline void sis190_init_rxfilter(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ u16 ctl;
+ int i;
+
+ ctl = SIS_R16(RxMacControl);
+ /*
+ * Disable packet filtering before setting filter.
+ * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
+ * only and followed by RxMacAddr (6 bytes). Strange. -- FR
+ */
+ SIS_W16(RxMacControl, ctl & ~0x0f00);
+
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+ SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
+
+ SIS_W16(RxMacControl, ctl);
+ SIS_PCI_COMMIT();
+}
+
+static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
+{
+ u8 from;
+
+ pci_read_config_byte(pdev, 0x73, &from);
+
+ return (from & 0x00000001) ?
+ sis190_get_mac_addr_from_apc(pdev, dev) :
+ sis190_get_mac_addr_from_eeprom(pdev, dev);
+}
+
+static void sis190_set_speed_auto(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ int phy_id = tp->mii_if.phy_id;
+ int val;
+
+ net_link(tp, KERN_INFO "%s: Enabling Auto-negotiation.\n", dev->name);
+
+ val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
+
+ // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
+ // unchanged.
+ mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
+ ADVERTISE_100FULL | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_10HALF);
+
+ // Enable 1000 Full Mode.
+ mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
+
+ // Enable auto-negotiation and restart auto-negotiation.
+ mdio_write(ioaddr, phy_id, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
+}
+
+static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_ethtool_gset(&tp->mii_if, cmd);
+}
+
+static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_ethtool_sset(&tp->mii_if, cmd);
+}
+
+static void sis190_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(tp->pci_dev));
+}
+
+static int sis190_get_regs_len(struct net_device *dev)
+{
+ return SIS190_REGS_SIZE;
+}
+
+static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+ unsigned long flags;
+
+ if (regs->len > SIS190_REGS_SIZE)
+ regs->len = SIS190_REGS_SIZE;
+
+ spin_lock_irqsave(&tp->lock, flags);
+ memcpy_fromio(p, tp->mmio_addr, regs->len);
+ spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static int sis190_nway_reset(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return mii_nway_restart(&tp->mii_if);
+}
+
+static u32 sis190_get_msglevel(struct net_device *dev)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return tp->msg_enable;
+}
+
+static void sis190_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ tp->msg_enable = value;
+}
+
+static struct ethtool_ops sis190_ethtool_ops = {
+ .get_settings = sis190_get_settings,
+ .set_settings = sis190_set_settings,
+ .get_drvinfo = sis190_get_drvinfo,
+ .get_regs_len = sis190_get_regs_len,
+ .get_regs = sis190_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = sis190_get_msglevel,
+ .set_msglevel = sis190_set_msglevel,
+ .nway_reset = sis190_nway_reset,
+};
+
+static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct sis190_private *tp = netdev_priv(dev);
+
+ return !netif_running(dev) ? -EINVAL :
+ generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
+}
+
+static int __devinit sis190_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ struct sis190_private *tp;
+ struct net_device *dev;
+ void __iomem *ioaddr;
+ int rc;
+
+ if (!printed_version) {
+ net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
+ printed_version = 1;
+ }
+
+ dev = sis190_init_board(pdev);
+ if (IS_ERR(dev)) {
+ rc = PTR_ERR(dev);
+ goto out;
+ }
+
+ tp = netdev_priv(dev);
+ ioaddr = tp->mmio_addr;
+
+ rc = sis190_get_mac_addr(pdev, dev);
+ if (rc < 0)
+ goto err_release_board;
+
+ sis190_init_rxfilter(dev);
+
+ INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+
+ dev->open = sis190_open;
+ dev->stop = sis190_close;
+ dev->do_ioctl = sis190_ioctl;
+ dev->get_stats = sis190_get_stats;
+ dev->tx_timeout = sis190_tx_timeout;
+ dev->watchdog_timeo = SIS190_TX_TIMEOUT;
+ dev->hard_start_xmit = sis190_start_xmit;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = sis190_netpoll;
+#endif
+ dev->set_multicast_list = sis190_set_rx_mode;
+ SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
+ dev->irq = pdev->irq;
+ dev->base_addr = (unsigned long) 0xdead;
+
+ spin_lock_init(&tp->lock);
+
+ rc = sis190_mii_probe(dev);
+ if (rc < 0)
+ goto err_release_board;
+
+ rc = register_netdev(dev);
+ if (rc < 0)
+ goto err_remove_mii;
+
+ pci_set_drvdata(pdev, dev);
+
+ net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+ pci_name(pdev), sis_chip_info[ent->driver_data].name,
+ ioaddr, dev->irq,
+ dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3],
+ dev->dev_addr[4], dev->dev_addr[5]);
+
+ net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
+ (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
+
+ netif_carrier_off(dev);
+
+ sis190_set_speed_auto(dev);
+out:
+ return rc;
+
+err_remove_mii:
+ sis190_mii_remove(dev);
+err_release_board:
+ sis190_release_board(pdev);
+ goto out;
+}
+
+static void __devexit sis190_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ sis190_mii_remove(dev);
+ unregister_netdev(dev);
+ sis190_release_board(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver sis190_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = sis190_pci_tbl,
+ .probe = sis190_init_one,
+ .remove = __devexit_p(sis190_remove_one),
+};
+
+static int __init sis190_init_module(void)
+{
+ return pci_module_init(&sis190_pci_driver);
+}
+
+static void __exit sis190_cleanup_module(void)
+{
+ pci_unregister_driver(&sis190_pci_driver);
+}
+
+module_init(sis190_init_module);
+module_exit(sis190_cleanup_module);
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 23b713c700b3..1d4d88680db1 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1696,15 +1696,20 @@ static int sis900_rx(struct net_device *net_dev)
long ioaddr = net_dev->base_addr;
unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
+ int rx_work_limit;
if (netif_msg_rx_status(sis_priv))
printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
"status:0x%8.8x\n",
sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
+ rx_work_limit = sis_priv->dirty_rx + NUM_RX_DESC - sis_priv->cur_rx;
while (rx_status & OWN) {
unsigned int rx_size;
+ if (--rx_work_limit < 0)
+ break;
+
rx_size = (rx_status & DSIZE) - CRC_SIZE;
if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
@@ -1732,9 +1737,11 @@ static int sis900_rx(struct net_device *net_dev)
we are working on NULL sk_buff :-( */
if (sis_priv->rx_skbuff[entry] == NULL) {
if (netif_msg_rx_err(sis_priv))
- printk(KERN_INFO "%s: NULL pointer "
- "encountered in Rx ring, skipping\n",
- net_dev->name);
+ printk(KERN_WARNING "%s: NULL pointer "
+ "encountered in Rx ring\n"
+ "cur_rx:%4.4d, dirty_rx:%4.4d\n",
+ net_dev->name, sis_priv->cur_rx,
+ sis_priv->dirty_rx);
break;
}
@@ -1770,6 +1777,7 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv->rx_ring[entry].cmdsts = 0;
sis_priv->rx_ring[entry].bufptr = 0;
sis_priv->stats.rx_dropped++;
+ sis_priv->cur_rx++;
break;
}
skb->dev = net_dev;
@@ -1787,7 +1795,7 @@ static int sis900_rx(struct net_device *net_dev)
/* refill the Rx buffer, what if the rate of refilling is slower
* than consuming ?? */
- for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
+ for (; sis_priv->cur_rx != sis_priv->dirty_rx; sis_priv->dirty_rx++) {
struct sk_buff *skb;
entry = sis_priv->dirty_rx % NUM_RX_DESC;
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 6ee4771addf1..b18c92cb629e 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -235,7 +235,7 @@ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
* Extern Function Prototypes
*
******************************************************************************/
-static const char SKRootName[] = "sk98lin";
+static const char SKRootName[] = "net/sk98lin";
static struct proc_dir_entry *pSkRootDir;
extern struct file_operations sk_proc_fops;
@@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl[] = {
{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
- { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0, }
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
@@ -5244,20 +5242,20 @@ static int __init skge_init(void)
{
int error;
- pSkRootDir = proc_mkdir(SKRootName, proc_net);
+ pSkRootDir = proc_mkdir(SKRootName, NULL);
if (pSkRootDir)
pSkRootDir->owner = THIS_MODULE;
error = pci_register_driver(&skge_driver);
if (error)
- proc_net_remove(SKRootName);
+ remove_proc_entry(SKRootName, NULL);
return error;
}
static void __exit skge_exit(void)
{
pci_unregister_driver(&skge_driver);
- proc_net_remove(SKRootName);
+ remove_proc_entry(SKRootName, NULL);
}
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index f17c05cbe44b..99a776a51fb5 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -1896,7 +1896,7 @@ void smt_swap_para(struct smt_header *sm, int len, int direction)
static void smt_string_swap(char *data, const char *format, int len)
{
- const char *open_paren = 0 ;
+ const char *open_paren = NULL ;
int x ;
while (len > 0 && *format) {
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f15739481d62..572f121b1f4e 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "1.1"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -79,8 +79,8 @@ static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
- { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -105,41 +105,28 @@ static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 };
-/* Don't need to look at whole 16K.
- * last interesting register is descriptor poll timer.
- */
-#define SKGE_REGS_LEN (29*128)
-
static int skge_get_regs_len(struct net_device *dev)
{
- return SKGE_REGS_LEN;
+ return 0x4000;
}
/*
- * Returns copy of control register region
- * I/O region is divided into banks and certain regions are unreadable
+ * Returns copy of whole control register region
+ * Note: skip RAM address register because accessing it will
+ * cause bus hangs!
*/
static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
const struct skge_port *skge = netdev_priv(dev);
- unsigned long offs;
const void __iomem *io = skge->hw->regs;
- static const unsigned long bankmap
- = (1<<0) | (1<<2) | (1<<8) | (1<<9)
- | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16)
- | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23)
- | (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28);
regs->version = 1;
- for (offs = 0; offs < regs->len; offs += 128) {
- u32 len = min_t(u32, 128, regs->len - offs);
+ memset(p, 0, regs->len);
+ memcpy_fromio(p, io, B3_RAM_ADDR);
- if (bankmap & (1<<(offs/128)))
- memcpy_fromio(p + offs, io + offs, len);
- else
- memset(p + offs, 0, len);
- }
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+ regs->len - B3_RI_WTO_R1);
}
/* Wake on Lan only supported on Yukon chps with rev 1 or above */
@@ -189,7 +176,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
{
u32 supported;
- if (iscopper(hw)) {
+ if (hw->copper) {
supported = SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
@@ -222,7 +209,7 @@ static int skge_get_settings(struct net_device *dev,
ecmd->transceiver = XCVR_INTERNAL;
ecmd->supported = skge_supported_modes(hw);
- if (iscopper(hw)) {
+ if (hw->copper) {
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
} else
@@ -669,7 +656,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
PHY_M_LED_BLINK_RT(BLINK_84MS) |
PHY_M_LEDC_TX_CTRL |
PHY_M_LEDC_DP_CTRL);
-
+
gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_RX(MO_LED_OFF) |
(skge->speed == SPEED_100 ?
@@ -743,6 +730,7 @@ static struct ethtool_ops skge_ethtool_ops = {
.phys_id = skge_phys_id,
.get_stats_count = skge_get_stats_count,
.get_ethtool_stats = skge_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/*
@@ -775,17 +763,6 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
return 0;
}
-static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size)
-{
- struct sk_buff *skb = dev_alloc_skb(size);
-
- if (likely(skb)) {
- skb->dev = dev;
- skb_reserve(skb, NET_IP_ALIGN);
- }
- return skb;
-}
-
/* Allocate and setup a new buffer for receiving */
static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
struct sk_buff *skb, unsigned int bufsize)
@@ -858,16 +835,17 @@ static int skge_rx_fill(struct skge_port *skge)
{
struct skge_ring *ring = &skge->rx_ring;
struct skge_element *e;
- unsigned int bufsize = skge->rx_buf_size;
e = ring->start;
do {
- struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize);
+ struct sk_buff *skb;
+ skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN);
if (!skb)
return -ENOMEM;
- skge_rx_setup(skge, e, skb, bufsize);
+ skb_reserve(skb, NET_IP_ALIGN);
+ skge_rx_setup(skge, e, skb, skge->rx_buf_size);
} while ( (e = e->next) != ring->start);
ring->to_clean = ring->start;
@@ -876,6 +854,9 @@ static int skge_rx_fill(struct skge_port *skge)
static void skge_link_up(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+
netif_carrier_on(skge->netdev);
if (skge->tx_avail > MAX_SKB_FRAGS + 1)
netif_wake_queue(skge->netdev);
@@ -894,6 +875,7 @@ static void skge_link_up(struct skge_port *skge)
static void skge_link_down(struct skge_port *skge)
{
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
netif_carrier_off(skge->netdev);
netif_stop_queue(skge->netdev);
@@ -983,6 +965,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
@@ -1017,8 +1001,6 @@ static void bcom_check_link(struct skge_hw *hw, int port)
(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
- pr_debug("bcom_check_link status=0x%x\n", status);
-
if ((status & PHY_ST_LSYNC) == 0) {
u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1102,8 +1084,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
- pr_debug("bcom_phy_init\n");
-
/* read Id from external PHY (all have the same address) */
id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
@@ -1336,6 +1316,8 @@ static void genesis_stop(struct skge_port *skge)
int port = skge->port;
u32 reg;
+ genesis_reset(hw, port);
+
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1461,7 +1443,6 @@ static void genesis_link_up(struct skge_port *skge)
u16 cmd;
u32 mode, msk;
- pr_debug("genesis_link_up\n");
cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
@@ -1574,7 +1555,6 @@ static void yukon_init(struct skge_hw *hw, int port)
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@@ -1599,7 +1579,7 @@ static void yukon_init(struct skge_hw *hw, int port)
adv = PHY_AN_CSMA;
if (skge->autoneg == AUTONEG_ENABLE) {
- if (iscopper(hw)) {
+ if (hw->copper) {
if (skge->advertising & ADVERTISED_1000baseT_Full)
ct1000 |= PHY_M_1000C_AFD;
if (skge->advertising & ADVERTISED_1000baseT_Half)
@@ -1664,6 +1644,22 @@ static void yukon_reset(struct skge_hw *hw, int port)
| GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
}
+/* Apparently, early versions of Yukon-Lite had wrong chip_id? */
+static int is_yukon_lite_a0(struct skge_hw *hw)
+{
+ u32 reg;
+ int ret;
+
+ if (hw->chip_id != CHIP_ID_YUKON)
+ return 0;
+
+ reg = skge_read32(hw, B2_FAR);
+ skge_write8(hw, B2_FAR + 3, 0xff);
+ ret = (skge_read8(hw, B2_FAR + 3) != 0);
+ skge_write32(hw, B2_FAR, reg);
+ return ret;
+}
+
static void yukon_mac_init(struct skge_hw *hw, int port)
{
struct skge_port *skge = netdev_priv(hw->dev[port]);
@@ -1673,9 +1669,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* hard reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -1683,15 +1681,17 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
- & ~GP_IO_9);
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
- reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+ reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
/* Clear GMC reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
@@ -1725,7 +1725,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
}
gma_write16(hw, port, GM_GP_CTRL, reg);
- skge_read16(hw, GMAC_IRQ_SRC);
+ skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
yukon_init(hw, port);
@@ -1775,12 +1775,19 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* Configure Rx MAC FIFO */
skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
- if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
+
+ /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+ if (is_yukon_lite_a0(hw))
reg &= ~GMF_RX_F_FL_ON;
+
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
- skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+ /*
+ * because Pause Packet Truncation in GMAC is not working
+ * we have to increase the Flush Threshold to 64 bytes
+ * in order to flush pause packets in Rx FIFO on Yukon-1
+ */
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
/* Configure Tx MAC FIFO */
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1792,20 +1799,26 @@ static void yukon_stop(struct skge_port *skge)
struct skge_hw *hw = skge->hw;
int port = skge->port;
- if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
- skge_write32(hw, B2_GP_IO,
- skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
- }
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ yukon_reset(hw, port);
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ u32 io = skge_read32(hw, B2_GP_IO);
+
+ io |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, io);
+ skge_read32(hw, B2_GP_IO);
+ }
+
/* set GPHY Control reset */
- skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
- skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1864,10 +1877,8 @@ static void yukon_link_up(struct skge_port *skge)
int port = skge->port;
u16 reg;
- pr_debug("yukon_link_up\n");
-
/* Enable Transmit FIFO Underrun */
- skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1887,7 +1898,6 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
u16 ctrl;
- pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2103,7 +2113,6 @@ static int skge_up(struct net_device *dev)
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
- pr_debug("skge_up completed\n");
return 0;
free_rx_ring:
@@ -2126,15 +2135,20 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ hw->intr_mask &= ~portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
RB_RST_SET|RB_DIS_OP_MD);
- if (hw->chip_id == CHIP_ID_GENESIS)
- genesis_stop(skge);
- else
- yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2358,8 +2372,6 @@ static void genesis_set_multicast(struct net_device *dev)
u32 mode;
u8 filter[8];
- pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
@@ -2426,6 +2438,14 @@ static void yukon_set_multicast(struct net_device *dev)
gma_write16(hw, port, GM_RX_CTRL, reg);
}
+static inline u16 phy_length(const struct skge_hw *hw, u32 status)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ return status >> XMR_FS_LEN_SHIFT;
+ else
+ return status >> GMR_FS_LEN_SHIFT;
+}
+
static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
{
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2435,80 +2455,99 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
(status & GMR_FS_RX_OK) == 0;
}
-static void skge_rx_error(struct skge_port *skge, int slot,
- u32 control, u32 status)
-{
- if (netif_msg_rx_err(skge))
- printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
- skge->netdev->name, slot, control, status);
-
- if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
- skge->net_stats.rx_length_errors++;
- else if (skge->hw->chip_id == CHIP_ID_GENESIS) {
- if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
- skge->net_stats.rx_length_errors++;
- if (status & XMR_FS_FRA_ERR)
- skge->net_stats.rx_frame_errors++;
- if (status & XMR_FS_FCS_ERR)
- skge->net_stats.rx_crc_errors++;
- } else {
- if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
- skge->net_stats.rx_length_errors++;
- if (status & GMR_FS_FRAGMENT)
- skge->net_stats.rx_frame_errors++;
- if (status & GMR_FS_CRC_ERR)
- skge->net_stats.rx_crc_errors++;
- }
-}
/* Get receive buffer from descriptor.
* Handles copy of small buffers and reallocation failures
*/
static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
struct skge_element *e,
- unsigned int len)
+ u32 control, u32 status, u16 csum)
{
- struct sk_buff *nskb, *skb;
+ struct sk_buff *skb;
+ u16 len = control & BMU_BBC;
+
+ if (unlikely(netif_msg_rx_status(skge)))
+ printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
+ skge->netdev->name, e - skge->rx_ring.start,
+ status, len);
+
+ if (len > skge->rx_buf_size)
+ goto error;
+
+ if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
+ goto error;
+
+ if (bad_phy_status(skge->hw, status))
+ goto error;
+
+ if (phy_length(skge->hw, status) != len)
+ goto error;
if (len < RX_COPY_THRESHOLD) {
- nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN);
- if (unlikely(!nskb))
- return NULL;
+ skb = dev_alloc_skb(len + 2);
+ if (!skb)
+ goto resubmit;
+ skb_reserve(skb, 2);
pci_dma_sync_single_for_cpu(skge->hw->pdev,
pci_unmap_addr(e, mapaddr),
len, PCI_DMA_FROMDEVICE);
- memcpy(nskb->data, e->skb->data, len);
+ memcpy(skb->data, e->skb->data, len);
pci_dma_sync_single_for_device(skge->hw->pdev,
pci_unmap_addr(e, mapaddr),
len, PCI_DMA_FROMDEVICE);
-
- if (skge->rx_csum) {
- struct skge_rx_desc *rd = e->desc;
- nskb->csum = le16_to_cpu(rd->csum2);
- nskb->ip_summed = CHECKSUM_HW;
- }
skge_rx_reuse(e, skge->rx_buf_size);
- return nskb;
} else {
- nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size);
- if (unlikely(!nskb))
- return NULL;
+ struct sk_buff *nskb;
+ nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN);
+ if (!nskb)
+ goto resubmit;
pci_unmap_single(skge->hw->pdev,
pci_unmap_addr(e, mapaddr),
pci_unmap_len(e, maplen),
PCI_DMA_FROMDEVICE);
skb = e->skb;
- if (skge->rx_csum) {
- struct skge_rx_desc *rd = e->desc;
- skb->csum = le16_to_cpu(rd->csum2);
- skb->ip_summed = CHECKSUM_HW;
- }
-
+ prefetch(skb->data);
skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
- return skb;
}
+
+ skb_put(skb, len);
+ skb->dev = skge->netdev;
+ if (skge->rx_csum) {
+ skb->csum = csum;
+ skb->ip_summed = CHECKSUM_HW;
+ }
+
+ skb->protocol = eth_type_trans(skb, skge->netdev);
+
+ return skb;
+error:
+
+ if (netif_msg_rx_err(skge))
+ printk(KERN_DEBUG PFX "%s: rx err, slot %td control 0x%x status 0x%x\n",
+ skge->netdev->name, e - skge->rx_ring.start,
+ control, status);
+
+ if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+ if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+ skge->net_stats.rx_length_errors++;
+ if (status & XMR_FS_FRA_ERR)
+ skge->net_stats.rx_frame_errors++;
+ if (status & XMR_FS_FCS_ERR)
+ skge->net_stats.rx_crc_errors++;
+ } else {
+ if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+ skge->net_stats.rx_length_errors++;
+ if (status & GMR_FS_FRAGMENT)
+ skge->net_stats.rx_frame_errors++;
+ if (status & GMR_FS_CRC_ERR)
+ skge->net_stats.rx_crc_errors++;
+ }
+
+resubmit:
+ skge_rx_reuse(e, skge->rx_buf_size);
+ return NULL;
}
@@ -2521,37 +2560,19 @@ static int skge_poll(struct net_device *dev, int *budget)
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
- pr_debug("skge_poll\n");
-
for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
struct sk_buff *skb;
- u32 control, len, status;
+ u32 control;
rmb();
control = rd->control;
if (control & BMU_OWN)
break;
- len = control & BMU_BBC;
- status = rd->status;
-
- if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
- || bad_phy_status(hw, status))) {
- skge_rx_error(skge, e - ring->start, control, status);
- skge_rx_reuse(e, skge->rx_buf_size);
- continue;
- }
-
- if (netif_msg_rx_status(skge))
- printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
- dev->name, e - ring->start, rd->status, len);
-
- skb = skge_rx_get(skge, e, len);
+ skb = skge_rx_get(skge, e, control, rd->status,
+ le16_to_cpu(rd->csum2));
if (likely(skb)) {
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, dev);
-
dev->last_rx = jiffies;
netif_receive_skb(skb);
@@ -2663,25 +2684,13 @@ static void skge_error_irq(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
-
- if (hwstatus & IS_IRQ_SENSOR) {
- /* no sensors on 32-bit Yukon */
- if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
- printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
- skge_write32(hw, B0_HWE_IMSK,
- IS_ERR_MSK & ~IS_IRQ_SENSOR);
- } else
- printk(KERN_WARNING PFX "sensor interrupt\n");
- }
-
-
}
if (hwstatus & IS_RAM_RD_PAR) {
@@ -2712,9 +2721,10 @@ static void skge_error_irq(struct skge_hw *hw)
skge_pci_clear(hw);
+ /* if error still set then just ignore it */
hwstatus = skge_read32(hw, B0_HWE_ISRC);
if (hwstatus & IS_IRQ_STAT) {
- printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+ pr_debug("IRQ status %x: still set ignoring hardware errors\n",
hwstatus);
hw->intr_mask &= ~IS_HW_ERR;
}
@@ -2828,21 +2838,29 @@ static void skge_netpoll(struct net_device *dev)
static int skge_set_mac_address(struct net_device *dev, void *p)
{
struct skge_port *skge = netdev_priv(dev);
- struct sockaddr *addr = p;
- int err = 0;
+ struct skge_hw *hw = skge->hw;
+ unsigned port = skge->port;
+ const struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- skge_down(dev);
+ spin_lock_bh(&hw->phy_lock);
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
- memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8,
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8,
dev->dev_addr, ETH_ALEN);
- memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8,
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8,
dev->dev_addr, ETH_ALEN);
- if (dev->flags & IFF_UP)
- err = skge_up(dev);
- return err;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ xm_outaddr(hw, port, XM_SA, dev->dev_addr);
+ else {
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
+ }
+ spin_unlock_bh(&hw->phy_lock);
+
+ return 0;
}
static const struct {
@@ -2876,7 +2894,7 @@ static const char *skge_board_name(const struct skge_hw *hw)
static int skge_reset(struct skge_hw *hw)
{
u16 ctst;
- u8 t8, mac_cfg;
+ u8 t8, mac_cfg, pmd_type, phy_type;
int i;
ctst = skge_read16(hw, B0_CTST);
@@ -2895,18 +2913,19 @@ static int skge_reset(struct skge_hw *hw)
ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
hw->chip_id = skge_read8(hw, B2_CHIP_ID);
- hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
- hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+ phy_type = skge_read8(hw, B2_E_1) & 0xf;
+ pmd_type = skge_read8(hw, B2_PMD_TYP);
+ hw->copper = (pmd_type == 'T' || pmd_type == '1');
switch (hw->chip_id) {
case CHIP_ID_GENESIS:
- switch (hw->phy_type) {
+ switch (phy_type) {
case SK_PHY_BCOM:
hw->phy_addr = PHY_ADDR_BCOM;
break;
default:
printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
- pci_name(hw->pdev), hw->phy_type);
+ pci_name(hw->pdev), phy_type);
return -EOPNOTSUPP;
}
break;
@@ -2914,13 +2933,10 @@ static int skge_reset(struct skge_hw *hw)
case CHIP_ID_YUKON:
case CHIP_ID_YUKON_LITE:
case CHIP_ID_YUKON_LP:
- if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
- hw->phy_type = SK_PHY_MARV_COPPER;
+ if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+ hw->copper = 1;
hw->phy_addr = PHY_ADDR_MARV;
- if (!iscopper(hw))
- hw->phy_type = SK_PHY_MARV_FIBER;
-
break;
default:
@@ -2948,12 +2964,20 @@ static int skge_reset(struct skge_hw *hw)
else
hw->ram_size = t8 * 4096;
+ hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_init(hw);
else {
/* switch power to VCC (WA for VAUX problem) */
skge_write8(hw, B0_POWER_CTRL,
PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+ /* avoid boards with stuck Hardware error bits */
+ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) &&
+ (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) {
+ printk(KERN_WARNING PFX "stuck hardware sensor bit\n");
+ hw->intr_mask &= ~IS_HW_ERR;
+ }
+
for (i = 0; i < hw->ports; i++) {
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
@@ -2994,12 +3018,8 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
skge_write32(hw, B2_IRQM_CTRL, TIM_START);
- hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask);
- if (hw->chip_id != CHIP_ID_GENESIS)
- skge_write8(hw, GMAC_IRQ_MSK, 0);
-
spin_lock_bh(&hw->phy_lock);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3077,6 +3097,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
/* read the mac address */
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* device is off until link detection */
netif_carrier_off(dev);
@@ -3227,6 +3248,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ skge_write32(hw, B0_IMSK, 0);
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_pci_clear(hw);
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+
tasklet_kill(&hw->ext_tasklet);
free_irq(pdev->irq, hw);
@@ -3235,7 +3261,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
if (dev1)
free_netdev(dev1);
free_netdev(dev0);
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+
iounmap(hw->regs);
kfree(hw);
pci_set_drvdata(pdev, NULL);
@@ -3254,7 +3280,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
netif_carrier_off(dev);
- skge_down(dev);
+ if (skge->wol)
+ netif_stop_queue(dev);
+ else
+ skge_down(dev);
}
netif_device_detach(dev);
wol |= skge->wol;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index b432f1bb8168..72c175b87a5a 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -214,8 +214,6 @@ enum {
/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
enum {
- IS_ERR_MSK = 0x00003fff,/* All Error bits */
-
IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
@@ -230,6 +228,12 @@ enum {
IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
+
+ IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT
+ | IS_NO_STAT_M1 | IS_NO_STAT_M2
+ | IS_RAM_RD_PAR | IS_RAM_WR_PAR
+ | IS_M1_PAR_ERR | IS_M2_PAR_ERR
+ | IS_R1_PAR_ERR | IS_R2_PAR_ERR,
};
/* B2_TST_CTRL1 8 bit Test Control Register 1 */
@@ -949,6 +953,7 @@ enum {
*/
enum {
XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */
+ XMR_FS_LEN_SHIFT = 18,
XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/
XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/
XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */
@@ -1864,6 +1869,7 @@ enum {
/* Receive Frame Status Encoding */
enum {
GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_LEN_SHIFT = 16,
GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */
GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */
GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */
@@ -2004,7 +2010,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
/* Bits 15.. 2: reserved */
@@ -2456,24 +2462,17 @@ struct skge_hw {
u8 chip_id;
u8 chip_rev;
- u8 phy_type;
- u8 pmd_type;
- u16 phy_addr;
+ u8 copper;
u8 ports;
u32 ram_size;
u32 ram_offset;
+ u16 phy_addr;
struct tasklet_struct ext_tasklet;
spinlock_t phy_lock;
};
-
-static inline int iscopper(const struct skge_hw *hw)
-{
- return (hw->pmd_type == 'T');
-}
-
enum {
FLOW_MODE_NONE = 0, /* No Flow-Control */
FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 6d9dae60a697..ba8593ac3f8a 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -68,6 +68,7 @@ static const char version[] =
#include <linux/etherdevice.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/system.h>
#include "8390.h"
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 1438fdd20826..74d5f1a6fdea 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -77,7 +77,7 @@ static const char version[] =
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/crc32.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -1983,6 +1983,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
if (lp->version >= (CHIP_91100 << 4))
smc_phy_detect(dev);
+ /* then shut everything down to save power */
+ smc_shutdown(dev);
+ smc_phy_powerdown(dev);
+
/* Set default parameters */
lp->msg_enable = NETIF_MSG_LINK;
lp->ctl_rfduplx = 0;
@@ -2291,11 +2295,11 @@ static int smc_drv_remove(struct device *dev)
return 0;
}
-static int smc_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int smc_drv_suspend(struct device *dev, pm_message_t state)
{
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == SUSPEND_DISABLE) {
+ if (ndev) {
if (netif_running(ndev)) {
netif_device_detach(ndev);
smc_shutdown(ndev);
@@ -2305,12 +2309,12 @@ static int smc_drv_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int smc_drv_resume(struct device *dev, u32 level)
+static int smc_drv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = dev_get_drvdata(dev);
- if (ndev && level == RESUME_ENABLE) {
+ if (ndev) {
struct smc_local *lp = netdev_priv(ndev);
smc_enable_device(pdev);
if (netif_running(ndev)) {
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index a9b06b8d8e3f..817f200742c3 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -230,12 +230,12 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 0
-#define SMC_inb(a, r) inb((a) + (r) - 0xa0000000)
-#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000)
-#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000)
-#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
-#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l)
-#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l)
+#define SMC_inb(a, r) inb((u32)a) + (r))
+#define SMC_inw(a, r) inw(((u32)a) + (r))
+#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r))
+#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r))
+#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
#define set_irq_type(irq, type) do {} while(0)
@@ -986,7 +986,7 @@ static const char * chip_ids[ 16 ] = {
})
#endif
-#if SMC_CAN_USE_DATACS
+#ifdef SMC_CAN_USE_DATACS
#define SMC_PUSH_DATA(p, l) \
if ( lp->datacs ) { \
unsigned char *__ptr = (p); \
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index cdc9cc873e06..90b818a8de6e 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -1,6 +1,11 @@
/*
* sonic.c
*
+ * (C) 2005 Finn Thain
+ *
+ * Converted to DMA API, added zero-copy buffer handling, and
+ * (from the mac68k project) introduced dhd's support for 16-bit cards.
+ *
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*
* This driver is based on work from Andreas Busse, but most of
@@ -9,12 +14,23 @@
* (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
*
* Core code included by system sonic drivers
+ *
+ * And... partially rewritten again by David Huggins-Daines in order
+ * to cope with screwed up Macintosh NICs that may or may not use
+ * 16-bit DMA.
+ *
+ * (C) 1999 David Huggins-Daines <dhd@debian.org>
+ *
*/
/*
* Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
* National Semiconductors data sheet for the DP83932B Sonic Ethernet
* controller, and the files "8390.c" and "skeleton.c" in this directory.
+ *
+ * Additional sources: Nat Semi data sheet for the DP83932C and Nat Semi
+ * Application Note AN-746, the files "lance.c" and "ibmlana.c". See also
+ * the NetBSD file "sys/arch/mac68k/dev/if_sn.c".
*/
@@ -28,6 +44,9 @@
*/
static int sonic_open(struct net_device *dev)
{
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
+
if (sonic_debug > 2)
printk("sonic_open: initializing sonic driver.\n");
@@ -40,14 +59,59 @@ static int sonic_open(struct net_device *dev)
* This means that during execution of the handler interrupt are disabled
* covering another bug otherwise corrupting data. This doesn't mean
* this glue works ok under all situations.
+ *
+ * Note (dhd): this also appears to prevent lockups on the Macintrash
+ * when more than one Ethernet card is installed (knock on wood)
+ *
+ * Note (fthain): whether the above is still true is anyones guess. Certainly
+ * the buffer handling algorithms will not tolerate re-entrance without some
+ * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
+ * rx code to make this a faster "fast interrupt".
*/
-// if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
- if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT,
- "sonic", dev)) {
- printk("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
+ if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
+ printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
return -EAGAIN;
}
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ if (skb == NULL) {
+ while(i > 0) { /* free any that were allocated successfully */
+ i--;
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ printk(KERN_ERR "%s: couldn't allocate receive buffers\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ skb->dev = dev;
+ /* align IP header unless DMA requires otherwise */
+ if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+ skb_reserve(skb, 2);
+ lp->rx_skb[i] = skb;
+ }
+
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE),
+ SONIC_RBSIZE, DMA_FROM_DEVICE);
+ if (!laddr) {
+ while(i > 0) { /* free any that were mapped successfully */
+ i--;
+ dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ lp->rx_laddr[i] = (dma_addr_t)0;
+ }
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ printk(KERN_ERR "%s: couldn't map rx DMA buffers\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ lp->rx_laddr[i] = laddr;
+ }
+
/*
* Initialize the SONIC
*/
@@ -67,7 +131,8 @@ static int sonic_open(struct net_device *dev)
*/
static int sonic_close(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
if (sonic_debug > 2)
printk("sonic_close\n");
@@ -77,20 +142,56 @@ static int sonic_close(struct net_device *dev)
/*
* stop the SONIC, disable interrupts
*/
- SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
- sonic_free_irq(dev->irq, dev); /* release the IRQ */
+ /* unmap and free skbs that haven't been transmitted */
+ for (i = 0; i < SONIC_NUM_TDS; i++) {
+ if(lp->tx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+ lp->tx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->tx_skb[i]) {
+ dev_kfree_skb(lp->tx_skb[i]);
+ lp->tx_skb[i] = NULL;
+ }
+ }
+
+ /* unmap and free the receive buffers */
+ for (i = 0; i < SONIC_NUM_RRS; i++) {
+ if(lp->rx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ lp->rx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->rx_skb[i]) {
+ dev_kfree_skb(lp->rx_skb[i]);
+ lp->rx_skb[i] = NULL;
+ }
+ }
+
+ free_irq(dev->irq, dev); /* release the IRQ */
return 0;
}
static void sonic_tx_timeout(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- printk("%s: transmit timed out.\n", dev->name);
-
+ struct sonic_local *lp = netdev_priv(dev);
+ int i;
+ /* Stop the interrupts for this */
+ SONIC_WRITE(SONIC_IMR, 0);
+ /* We could resend the original skbs. Easier to re-initialise. */
+ for (i = 0; i < SONIC_NUM_TDS; i++) {
+ if(lp->tx_laddr[i]) {
+ dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE);
+ lp->tx_laddr[i] = (dma_addr_t)0;
+ }
+ if(lp->tx_skb[i]) {
+ dev_kfree_skb(lp->tx_skb[i]);
+ lp->tx_skb[i] = NULL;
+ }
+ }
/* Try to restart the adaptor. */
sonic_init(dev);
lp->stats.tx_errors++;
@@ -100,60 +201,92 @@ static void sonic_tx_timeout(struct net_device *dev)
/*
* transmit packet
+ *
+ * Appends new TD during transmission thus avoiding any TX interrupts
+ * until we run out of TDs.
+ * This routine interacts closely with the ISR in that it may,
+ * set tx_skb[i]
+ * reset the status flags of the new TD
+ * set and reset EOL flags
+ * stop the tx queue
+ * The ISR interacts with this routine in various ways. It may,
+ * reset tx_skb[i]
+ * test the EOL and status flags of the TDs
+ * wake the tx queue
+ * Concurrently with all of this, the SONIC is potentially writing to
+ * the status flags of the TDs.
+ * Until some mutual exclusion is added, this code will not work with SMP. However,
+ * MIPS Jazz machines and m68k Macs were all uni-processor machines.
*/
+
static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
- unsigned int laddr;
- int entry, length;
-
- netif_stop_queue(dev);
+ struct sonic_local *lp = netdev_priv(dev);
+ dma_addr_t laddr;
+ int length;
+ int entry = lp->next_tx;
if (sonic_debug > 2)
printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);
+ length = skb->len;
+ if (length < ETH_ZLEN) {
+ skb = skb_padto(skb, ETH_ZLEN);
+ if (skb == NULL)
+ return 0;
+ length = ETH_ZLEN;
+ }
+
/*
* Map the packet data into the logical DMA address space
*/
- if ((laddr = vdma_alloc(CPHYSADDR(skb->data), skb->len)) == ~0UL) {
- printk("%s: no VDMA entry for transmit available.\n",
- dev->name);
+
+ laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
+ if (!laddr) {
+ printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
dev_kfree_skb(skb);
- netif_start_queue(dev);
return 1;
}
- entry = lp->cur_tx & SONIC_TDS_MASK;
+
+ sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */
+ sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_L, laddr & 0xffff);
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_PTR_H, laddr >> 16);
+ sonic_tda_put(dev, entry, SONIC_TD_FRAG_SIZE, length);
+ sonic_tda_put(dev, entry, SONIC_TD_LINK,
+ sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
+
+ /*
+ * Must set tx_skb[entry] only after clearing status, and
+ * before clearing EOL and before stopping queue
+ */
+ wmb();
+ lp->tx_len[entry] = length;
lp->tx_laddr[entry] = laddr;
lp->tx_skb[entry] = skb;
- length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- flush_cache_all();
+ wmb();
+ sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK,
+ sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL);
+ lp->eol_tx = entry;
- /*
- * Setup the transmit descriptor and issue the transmit command.
- */
- lp->tda[entry].tx_status = 0; /* clear status */
- lp->tda[entry].tx_frag_count = 1; /* single fragment */
- lp->tda[entry].tx_pktsize = length; /* length of packet */
- lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
- lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
- lp->tda[entry].tx_frag_size = length;
- lp->cur_tx++;
- lp->stats.tx_bytes += length;
+ lp->next_tx = (entry + 1) & SONIC_TDS_MASK;
+ if (lp->tx_skb[lp->next_tx] != NULL) {
+ /* The ring is full, the ISR has yet to process the next TD. */
+ if (sonic_debug > 3)
+ printk("%s: stopping queue\n", dev->name);
+ netif_stop_queue(dev);
+ /* after this packet, wait for ISR to free up some TDAs */
+ } else netif_start_queue(dev);
if (sonic_debug > 2)
- printk("sonic_send_packet: issueing Tx command\n");
+ printk("sonic_send_packet: issuing Tx command\n");
SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
dev->trans_start = jiffies;
- if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS)
- netif_start_queue(dev);
- else
- lp->tx_full = 1;
-
return 0;
}
@@ -164,175 +297,199 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
- unsigned int base_addr = dev->base_addr;
- struct sonic_local *lp;
+ struct sonic_local *lp = netdev_priv(dev);
int status;
if (dev == NULL) {
- printk("sonic_interrupt: irq %d for unknown device.\n", irq);
+ printk(KERN_ERR "sonic_interrupt: irq %d for unknown device.\n", irq);
return IRQ_NONE;
}
- lp = (struct sonic_local *) dev->priv;
-
- status = SONIC_READ(SONIC_ISR);
- SONIC_WRITE(SONIC_ISR, 0x7fff); /* clear all bits */
-
- if (sonic_debug > 2)
- printk("sonic_interrupt: ISR=%x\n", status);
-
- if (status & SONIC_INT_PKTRX) {
- sonic_rx(dev); /* got packet(s) */
- }
-
- if (status & SONIC_INT_TXDN) {
- int dirty_tx = lp->dirty_tx;
-
- while (dirty_tx < lp->cur_tx) {
- int entry = dirty_tx & SONIC_TDS_MASK;
- int status = lp->tda[entry].tx_status;
+ if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
+ return IRQ_NONE;
- if (sonic_debug > 3)
- printk
- ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
- status, lp->cur_tx, lp->dirty_tx);
+ do {
+ if (status & SONIC_INT_PKTRX) {
+ if (sonic_debug > 2)
+ printk("%s: packet rx\n", dev->name);
+ sonic_rx(dev); /* got packet(s) */
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_PKTRX); /* clear the interrupt */
+ }
- if (status == 0) {
- /* It still hasn't been Txed, kick the sonic again */
- SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
- break;
- }
+ if (status & SONIC_INT_TXDN) {
+ int entry = lp->cur_tx;
+ int td_status;
+ int freed_some = 0;
- /* put back EOL and free descriptor */
- lp->tda[entry].tx_frag_count = 0;
- lp->tda[entry].tx_status = 0;
-
- if (status & 0x0001)
- lp->stats.tx_packets++;
- else {
- lp->stats.tx_errors++;
- if (status & 0x0642)
- lp->stats.tx_aborted_errors++;
- if (status & 0x0180)
- lp->stats.tx_carrier_errors++;
- if (status & 0x0020)
- lp->stats.tx_window_errors++;
- if (status & 0x0004)
- lp->stats.tx_fifo_errors++;
- }
+ /* At this point, cur_tx is the index of a TD that is one of:
+ * unallocated/freed (status set & tx_skb[entry] clear)
+ * allocated and sent (status set & tx_skb[entry] set )
+ * allocated and not yet sent (status clear & tx_skb[entry] set )
+ * still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+ */
- /* We must free the original skb */
- if (lp->tx_skb[entry]) {
+ if (sonic_debug > 2)
+ printk("%s: tx done\n", dev->name);
+
+ while (lp->tx_skb[entry] != NULL) {
+ if ((td_status = sonic_tda_get(dev, entry, SONIC_TD_STATUS)) == 0)
+ break;
+
+ if (td_status & 0x0001) {
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE);
+ } else {
+ lp->stats.tx_errors++;
+ if (td_status & 0x0642)
+ lp->stats.tx_aborted_errors++;
+ if (td_status & 0x0180)
+ lp->stats.tx_carrier_errors++;
+ if (td_status & 0x0020)
+ lp->stats.tx_window_errors++;
+ if (td_status & 0x0004)
+ lp->stats.tx_fifo_errors++;
+ }
+
+ /* We must free the original skb */
dev_kfree_skb_irq(lp->tx_skb[entry]);
- lp->tx_skb[entry] = 0;
+ lp->tx_skb[entry] = NULL;
+ /* and unmap DMA buffer */
+ dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE);
+ lp->tx_laddr[entry] = (dma_addr_t)0;
+ freed_some = 1;
+
+ if (sonic_tda_get(dev, entry, SONIC_TD_LINK) & SONIC_EOL) {
+ entry = (entry + 1) & SONIC_TDS_MASK;
+ break;
+ }
+ entry = (entry + 1) & SONIC_TDS_MASK;
}
- /* and the VDMA address */
- vdma_free(lp->tx_laddr[entry]);
- dirty_tx++;
- }
- if (lp->tx_full
- && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) {
- /* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
- netif_wake_queue(dev);
+ if (freed_some || lp->tx_skb[entry] == NULL)
+ netif_wake_queue(dev); /* The ring is no longer full */
+ lp->cur_tx = entry;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_TXDN); /* clear the interrupt */
}
- lp->dirty_tx = dirty_tx;
- }
+ /*
+ * check error conditions
+ */
+ if (status & SONIC_INT_RFO) {
+ if (sonic_debug > 1)
+ printk("%s: rx fifo overrun\n", dev->name);
+ lp->stats.rx_fifo_errors++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RFO); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_RDE) {
+ if (sonic_debug > 1)
+ printk("%s: rx descriptors exhausted\n", dev->name);
+ lp->stats.rx_dropped++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RDE); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_RBAE) {
+ if (sonic_debug > 1)
+ printk("%s: rx buffer area exceeded\n", dev->name);
+ lp->stats.rx_dropped++;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RBAE); /* clear the interrupt */
+ }
- /*
- * check error conditions
- */
- if (status & SONIC_INT_RFO) {
- printk("%s: receive fifo underrun\n", dev->name);
- lp->stats.rx_fifo_errors++;
- }
- if (status & SONIC_INT_RDE) {
- printk("%s: receive descriptors exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
- if (status & SONIC_INT_RBE) {
- printk("%s: receive buffer exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
- if (status & SONIC_INT_RBAE) {
- printk("%s: receive buffer area exhausted\n", dev->name);
- lp->stats.rx_dropped++;
- }
+ /* counter overruns; all counters are 16bit wide */
+ if (status & SONIC_INT_FAE) {
+ lp->stats.rx_frame_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_FAE); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_CRC) {
+ lp->stats.rx_crc_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_CRC); /* clear the interrupt */
+ }
+ if (status & SONIC_INT_MP) {
+ lp->stats.rx_missed_errors += 65536;
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_MP); /* clear the interrupt */
+ }
- /* counter overruns; all counters are 16bit wide */
- if (status & SONIC_INT_FAE)
- lp->stats.rx_frame_errors += 65536;
- if (status & SONIC_INT_CRC)
- lp->stats.rx_crc_errors += 65536;
- if (status & SONIC_INT_MP)
- lp->stats.rx_missed_errors += 65536;
+ /* transmit error */
+ if (status & SONIC_INT_TXER) {
+ if ((SONIC_READ(SONIC_TCR) & SONIC_TCR_FU) && (sonic_debug > 2))
+ printk(KERN_ERR "%s: tx fifo underrun\n", dev->name);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_TXER); /* clear the interrupt */
+ }
- /* transmit error */
- if (status & SONIC_INT_TXER)
- lp->stats.tx_errors++;
+ /* bus retry */
+ if (status & SONIC_INT_BR) {
+ printk(KERN_ERR "%s: Bus retry occurred! Device interrupt disabled.\n",
+ dev->name);
+ /* ... to help debug DMA problems causing endless interrupts. */
+ /* Bounce the eth interface to turn on the interrupt again. */
+ SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_BR); /* clear the interrupt */
+ }
- /*
- * clear interrupt bits and return
- */
- SONIC_WRITE(SONIC_ISR, status);
+ /* load CAM done */
+ if (status & SONIC_INT_LCD)
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
+ } while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
return IRQ_HANDLED;
}
/*
- * We have a good packet(s), get it/them out of the buffers.
+ * We have a good packet(s), pass it/them up the network stack.
*/
static void sonic_rx(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];
+ struct sonic_local *lp = netdev_priv(dev);
int status;
-
- while (rd->in_use == 0) {
- struct sk_buff *skb;
+ int entry = lp->cur_rx;
+
+ while (sonic_rda_get(dev, entry, SONIC_RD_IN_USE) == 0) {
+ struct sk_buff *used_skb;
+ struct sk_buff *new_skb;
+ dma_addr_t new_laddr;
+ u16 bufadr_l;
+ u16 bufadr_h;
int pkt_len;
- unsigned char *pkt_ptr;
- status = rd->rx_status;
- if (sonic_debug > 3)
- printk("status %x, cur_rx %d, cur_rra %x\n",
- status, lp->cur_rx, lp->cur_rra);
+ status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
if (status & SONIC_RCR_PRX) {
- pkt_len = rd->rx_pktlen;
- pkt_ptr =
- (char *)
- sonic_chiptomem((rd->rx_pktptr_h << 16) +
- rd->rx_pktptr_l);
-
- if (sonic_debug > 3)
- printk
- ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n",
- pkt_ptr, lp->rba, rd->rx_pktptr_h,
- rd->rx_pktptr_l,
- SONIC_READ(SONIC_RBWC1),
- SONIC_READ(SONIC_RBWC0));
-
/* Malloc up new buffer. */
- skb = dev_alloc_skb(pkt_len + 2);
- if (skb == NULL) {
- printk
- ("%s: Memory squeeze, dropping packet.\n",
- dev->name);
+ new_skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ if (new_skb == NULL) {
+ printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ break;
+ }
+ new_skb->dev = dev;
+ /* provide 16 byte IP header alignment unless DMA requires otherwise */
+ if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+ skb_reserve(new_skb, 2);
+
+ new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE),
+ SONIC_RBSIZE, DMA_FROM_DEVICE);
+ if (!new_laddr) {
+ dev_kfree_skb(new_skb);
+ printk(KERN_ERR "%s: Failed to map rx buffer, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->dev = dev;
- skb_reserve(skb, 2); /* 16 byte align */
- skb_put(skb, pkt_len); /* Make room */
- eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb); /* pass the packet to upper layers */
+
+ /* now we have a new skb to replace it, pass the used one up the stack */
+ dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
+ used_skb = lp->rx_skb[entry];
+ pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
+ skb_trim(used_skb, pkt_len);
+ used_skb->protocol = eth_type_trans(used_skb, dev);
+ netif_rx(used_skb);
dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
+ /* and insert the new skb */
+ lp->rx_laddr[entry] = new_laddr;
+ lp->rx_skb[entry] = new_skb;
+
+ bufadr_l = (unsigned long)new_laddr & 0xffff;
+ bufadr_h = (unsigned long)new_laddr >> 16;
+ sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
+ sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
} else {
/* This should only happen, if we enable accepting broken packets. */
lp->stats.rx_errors++;
@@ -341,29 +498,35 @@ static void sonic_rx(struct net_device *dev)
if (status & SONIC_RCR_CRCR)
lp->stats.rx_crc_errors++;
}
-
- rd->in_use = 1;
- rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK];
- /* now give back the buffer to the receive buffer area */
if (status & SONIC_RCR_LPKT) {
/*
- * this was the last packet out of the current receice buffer
+ * this was the last packet out of the current receive buffer
* give the buffer back to the SONIC
*/
- lp->cur_rra += sizeof(sonic_rr_t);
- if (lp->cur_rra >
- (lp->rra_laddr +
- (SONIC_NUM_RRS -
- 1) * sizeof(sonic_rr_t))) lp->cur_rra =
- lp->rra_laddr;
- SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff);
+ lp->cur_rwp += SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode);
+ if (lp->cur_rwp >= lp->rra_end) lp->cur_rwp = lp->rra_laddr & 0xffff;
+ SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
+ if (SONIC_READ(SONIC_ISR) & SONIC_INT_RBE) {
+ if (sonic_debug > 2)
+ printk("%s: rx buffer exhausted\n", dev->name);
+ SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
+ }
} else
- printk
- ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
+ printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
dev->name);
+ /*
+ * give back the descriptor
+ */
+ sonic_rda_put(dev, entry, SONIC_RD_LINK,
+ sonic_rda_get(dev, entry, SONIC_RD_LINK) | SONIC_EOL);
+ sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
+ sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK,
+ sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK) & ~SONIC_EOL);
+ lp->eol_rx = entry;
+ lp->cur_rx = entry = (entry + 1) & SONIC_RDS_MASK;
}
/*
- * If any worth-while packets have been received, dev_rint()
+ * If any worth-while packets have been received, netif_rx()
* has done a mark_bh(NET_BH) for us and will work on them
* when we get to the bottom-half routine.
*/
@@ -376,8 +539,7 @@ static void sonic_rx(struct net_device *dev)
*/
static struct net_device_stats *sonic_get_stats(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
/* read the tally counter from the SONIC and reset them */
lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT);
@@ -396,8 +558,7 @@ static struct net_device_stats *sonic_get_stats(struct net_device *dev)
*/
static void sonic_multicast_list(struct net_device *dev)
{
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int base_addr = dev->base_addr;
+ struct sonic_local *lp = netdev_priv(dev);
unsigned int rcr;
struct dev_mc_list *dmi = dev->mc_list;
unsigned char *addr;
@@ -413,20 +574,15 @@ static void sonic_multicast_list(struct net_device *dev)
rcr |= SONIC_RCR_AMC;
} else {
if (sonic_debug > 2)
- printk
- ("sonic_multicast_list: mc_count %d\n",
- dev->mc_count);
- lp->cda.cam_enable = 1; /* always enable our own address */
+ printk("sonic_multicast_list: mc_count %d\n", dev->mc_count);
+ sonic_set_cam_enable(dev, 1); /* always enable our own address */
for (i = 1; i <= dev->mc_count; i++) {
addr = dmi->dmi_addr;
dmi = dmi->next;
- lp->cda.cam_desc[i].cam_cap0 =
- addr[1] << 8 | addr[0];
- lp->cda.cam_desc[i].cam_cap1 =
- addr[3] << 8 | addr[2];
- lp->cda.cam_desc[i].cam_cap2 =
- addr[5] << 8 | addr[4];
- lp->cda.cam_enable |= (1 << i);
+ sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]);
+ sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]);
+ sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]);
+ sonic_set_cam_enable(dev, sonic_get_cam_enable(dev) | (1 << i));
}
SONIC_WRITE(SONIC_CDC, 16);
/* issue Load CAM command */
@@ -447,19 +603,16 @@ static void sonic_multicast_list(struct net_device *dev)
*/
static int sonic_init(struct net_device *dev)
{
- unsigned int base_addr = dev->base_addr;
unsigned int cmd;
- struct sonic_local *lp = (struct sonic_local *) dev->priv;
- unsigned int rra_start;
- unsigned int rra_end;
+ struct sonic_local *lp = netdev_priv(dev);
int i;
/*
* put the Sonic into software-reset mode and
* disable all interrupts
*/
- SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_IMR, 0);
+ SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
/*
@@ -475,34 +628,32 @@ static int sonic_init(struct net_device *dev)
if (sonic_debug > 2)
printk("sonic_init: initialize receive resource area\n");
- rra_start = lp->rra_laddr & 0xffff;
- rra_end =
- (rra_start + (SONIC_NUM_RRS * sizeof(sonic_rr_t))) & 0xffff;
-
for (i = 0; i < SONIC_NUM_RRS; i++) {
- lp->rra[i].rx_bufadr_l =
- (lp->rba_laddr + i * SONIC_RBSIZE) & 0xffff;
- lp->rra[i].rx_bufadr_h =
- (lp->rba_laddr + i * SONIC_RBSIZE) >> 16;
- lp->rra[i].rx_bufsize_l = SONIC_RBSIZE >> 1;
- lp->rra[i].rx_bufsize_h = 0;
+ u16 bufadr_l = (unsigned long)lp->rx_laddr[i] & 0xffff;
+ u16 bufadr_h = (unsigned long)lp->rx_laddr[i] >> 16;
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
+ sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
+ sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_L, SONIC_RBSIZE >> 1);
+ sonic_rra_put(dev, i, SONIC_RR_BUFSIZE_H, 0);
}
/* initialize all RRA registers */
- SONIC_WRITE(SONIC_RSA, rra_start);
- SONIC_WRITE(SONIC_REA, rra_end);
- SONIC_WRITE(SONIC_RRP, rra_start);
- SONIC_WRITE(SONIC_RWP, rra_end);
+ lp->rra_end = (lp->rra_laddr + SONIC_NUM_RRS * SIZEOF_SONIC_RR *
+ SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+ lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR *
+ SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
+
+ SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff);
+ SONIC_WRITE(SONIC_REA, lp->rra_end);
+ SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff);
+ SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16);
- SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE - 2) >> 1);
-
- lp->cur_rra =
- lp->rra_laddr + (SONIC_NUM_RRS - 1) * sizeof(sonic_rr_t);
+ SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1));
/* load the resource pointers */
if (sonic_debug > 3)
- printk("sonic_init: issueing RRRA command\n");
-
+ printk("sonic_init: issuing RRRA command\n");
+
SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
i = 0;
while (i++ < 100) {
@@ -511,27 +662,30 @@ static int sonic_init(struct net_device *dev)
}
if (sonic_debug > 2)
- printk("sonic_init: status=%x\n", SONIC_READ(SONIC_CMD));
-
+ printk("sonic_init: status=%x i=%d\n", SONIC_READ(SONIC_CMD), i);
+
/*
* Initialize the receive descriptors so that they
* become a circular linked list, ie. let the last
* descriptor point to the first again.
*/
if (sonic_debug > 2)
- printk("sonic_init: initialize receive descriptors\n");
- for (i = 0; i < SONIC_NUM_RDS; i++) {
- lp->rda[i].rx_status = 0;
- lp->rda[i].rx_pktlen = 0;
- lp->rda[i].rx_pktptr_l = 0;
- lp->rda[i].rx_pktptr_h = 0;
- lp->rda[i].rx_seqno = 0;
- lp->rda[i].in_use = 1;
- lp->rda[i].link =
- lp->rda_laddr + (i + 1) * sizeof(sonic_rd_t);
+ printk("sonic_init: initialize receive descriptors\n");
+ for (i=0; i<SONIC_NUM_RDS; i++) {
+ sonic_rda_put(dev, i, SONIC_RD_STATUS, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTLEN, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTPTR_L, 0);
+ sonic_rda_put(dev, i, SONIC_RD_PKTPTR_H, 0);
+ sonic_rda_put(dev, i, SONIC_RD_SEQNO, 0);
+ sonic_rda_put(dev, i, SONIC_RD_IN_USE, 1);
+ sonic_rda_put(dev, i, SONIC_RD_LINK,
+ lp->rda_laddr +
+ ((i+1) * SIZEOF_SONIC_RD * SONIC_BUS_SCALE(lp->dma_bitmode)));
}
/* fix last descriptor */
- lp->rda[SONIC_NUM_RDS - 1].link = lp->rda_laddr;
+ sonic_rda_put(dev, SONIC_NUM_RDS - 1, SONIC_RD_LINK,
+ (lp->rda_laddr & 0xffff) | SONIC_EOL);
+ lp->eol_rx = SONIC_NUM_RDS - 1;
lp->cur_rx = 0;
SONIC_WRITE(SONIC_URDA, lp->rda_laddr >> 16);
SONIC_WRITE(SONIC_CRDA, lp->rda_laddr & 0xffff);
@@ -542,34 +696,34 @@ static int sonic_init(struct net_device *dev)
if (sonic_debug > 2)
printk("sonic_init: initialize transmit descriptors\n");
for (i = 0; i < SONIC_NUM_TDS; i++) {
- lp->tda[i].tx_status = 0;
- lp->tda[i].tx_config = 0;
- lp->tda[i].tx_pktsize = 0;
- lp->tda[i].tx_frag_count = 0;
- lp->tda[i].link =
- (lp->tda_laddr +
- (i + 1) * sizeof(sonic_td_t)) | SONIC_END_OF_LINKS;
+ sonic_tda_put(dev, i, SONIC_TD_STATUS, 0);
+ sonic_tda_put(dev, i, SONIC_TD_CONFIG, 0);
+ sonic_tda_put(dev, i, SONIC_TD_PKTSIZE, 0);
+ sonic_tda_put(dev, i, SONIC_TD_FRAG_COUNT, 0);
+ sonic_tda_put(dev, i, SONIC_TD_LINK,
+ (lp->tda_laddr & 0xffff) +
+ (i + 1) * SIZEOF_SONIC_TD * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->tx_skb[i] = NULL;
}
- lp->tda[SONIC_NUM_TDS - 1].link =
- (lp->tda_laddr & 0xffff) | SONIC_END_OF_LINKS;
+ /* fix last descriptor */
+ sonic_tda_put(dev, SONIC_NUM_TDS - 1, SONIC_TD_LINK,
+ (lp->tda_laddr & 0xffff));
SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16);
SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff);
- lp->cur_tx = lp->dirty_tx = 0;
-
+ lp->cur_tx = lp->next_tx = 0;
+ lp->eol_tx = SONIC_NUM_TDS - 1;
+
/*
* put our own address to CAM desc[0]
*/
- lp->cda.cam_desc[0].cam_cap0 =
- dev->dev_addr[1] << 8 | dev->dev_addr[0];
- lp->cda.cam_desc[0].cam_cap1 =
- dev->dev_addr[3] << 8 | dev->dev_addr[2];
- lp->cda.cam_desc[0].cam_cap2 =
- dev->dev_addr[5] << 8 | dev->dev_addr[4];
- lp->cda.cam_enable = 1;
+ sonic_cda_put(dev, 0, SONIC_CD_CAP0, dev->dev_addr[1] << 8 | dev->dev_addr[0]);
+ sonic_cda_put(dev, 0, SONIC_CD_CAP1, dev->dev_addr[3] << 8 | dev->dev_addr[2]);
+ sonic_cda_put(dev, 0, SONIC_CD_CAP2, dev->dev_addr[5] << 8 | dev->dev_addr[4]);
+ sonic_set_cam_enable(dev, 1);
for (i = 0; i < 16; i++)
- lp->cda.cam_desc[i].cam_entry_pointer = i;
+ sonic_cda_put(dev, i, SONIC_CD_ENTRY_POINTER, i);
/*
* initialize CAM registers
@@ -588,8 +742,8 @@ static int sonic_init(struct net_device *dev)
break;
}
if (sonic_debug > 2) {
- printk("sonic_init: CMD=%x, ISR=%x\n",
- SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR));
+ printk("sonic_init: CMD=%x, ISR=%x\n, i=%d",
+ SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i);
}
/*
@@ -604,7 +758,7 @@ static int sonic_init(struct net_device *dev)
cmd = SONIC_READ(SONIC_CMD);
if ((cmd & SONIC_CR_RXEN) == 0 || (cmd & SONIC_CR_STP) == 0)
- printk("sonic_init: failed, status=%x\n", cmd);
+ printk(KERN_ERR "sonic_init: failed, status=%x\n", cmd);
if (sonic_debug > 2)
printk("sonic_init: new status=%x\n",
diff --git a/drivers/net/sonic.h b/drivers/net/sonic.h
index c4a6d58e4afb..cede969a8baa 100644
--- a/drivers/net/sonic.h
+++ b/drivers/net/sonic.h
@@ -1,5 +1,5 @@
/*
- * Helpfile for sonic.c
+ * Header file for sonic.c
*
* (C) Waldorf Electronics, Germany
* Written by Andreas Busse
@@ -9,10 +9,16 @@
* and pad structure members must be exchanged. Also, the structures
* need to be changed accordingly to the bus size.
*
- * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian),
- * see CONFIG_MACSONIC branch below.
+ * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian)
*
+ * 990611 David Huggins-Daines <dhd@debian.org>: This machine abstraction
+ * does not cope with 16-bit bus sizes very well. Therefore I have
+ * rewritten it with ugly macros and evil inlines.
+ *
+ * 050625 Finn Thain: introduced more 32-bit cards and dhd's support
+ * for 16-bit cards (from the mac68k project).
*/
+
#ifndef SONIC_H
#define SONIC_H
@@ -83,6 +89,7 @@
/*
* Error counters
*/
+
#define SONIC_CRCT 0x2c
#define SONIC_FAET 0x2d
#define SONIC_MPT 0x2e
@@ -182,14 +189,14 @@
#define SONIC_INT_BR 0x4000
#define SONIC_INT_HBL 0x2000
-#define SONIC_INT_LCD 0x1000
-#define SONIC_INT_PINT 0x0800
-#define SONIC_INT_PKTRX 0x0400
-#define SONIC_INT_TXDN 0x0200
-#define SONIC_INT_TXER 0x0100
-#define SONIC_INT_TC 0x0080
-#define SONIC_INT_RDE 0x0040
-#define SONIC_INT_RBE 0x0020
+#define SONIC_INT_LCD 0x1000
+#define SONIC_INT_PINT 0x0800
+#define SONIC_INT_PKTRX 0x0400
+#define SONIC_INT_TXDN 0x0200
+#define SONIC_INT_TXER 0x0100
+#define SONIC_INT_TC 0x0080
+#define SONIC_INT_RDE 0x0040
+#define SONIC_INT_RBE 0x0020
#define SONIC_INT_RBAE 0x0010
#define SONIC_INT_CRC 0x0008
#define SONIC_INT_FAE 0x0004
@@ -201,224 +208,61 @@
* The interrupts we allow.
*/
-#define SONIC_IMR_DEFAULT (SONIC_INT_BR | \
- SONIC_INT_LCD | \
- SONIC_INT_PINT | \
+#define SONIC_IMR_DEFAULT ( SONIC_INT_BR | \
+ SONIC_INT_LCD | \
+ SONIC_INT_RFO | \
SONIC_INT_PKTRX | \
SONIC_INT_TXDN | \
SONIC_INT_TXER | \
SONIC_INT_RDE | \
- SONIC_INT_RBE | \
SONIC_INT_RBAE | \
SONIC_INT_CRC | \
SONIC_INT_FAE | \
SONIC_INT_MP)
-#define SONIC_END_OF_LINKS 0x0001
-
-
-#ifdef CONFIG_MACSONIC
-/*
- * Big endian like structures on 680x0 Macs
- */
-
-typedef struct {
- u32 rx_bufadr_l; /* receive buffer ptr */
- u32 rx_bufadr_h;
-
- u32 rx_bufsize_l; /* no. of words in the receive buffer */
- u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
- SREGS_PAD(pad0);
- u16 rx_status; /* status after reception of a packet */
- SREGS_PAD(pad1);
- u16 rx_pktlen; /* length of the packet incl. CRC */
-
- /*
- * Pointers to the location in the receive buffer area (RBA)
- * where the packet resides. A packet is always received into
- * a contiguous piece of memory.
- */
- SREGS_PAD(pad2);
- u16 rx_pktptr_l;
- SREGS_PAD(pad3);
- u16 rx_pktptr_h;
-
- SREGS_PAD(pad4);
- u16 rx_seqno; /* sequence no. */
-
- SREGS_PAD(pad5);
- u16 link; /* link to next RDD (end if EOL bit set) */
-
- /*
- * Owner of this descriptor, 0= driver, 1=sonic
- */
-
- SREGS_PAD(pad6);
- u16 in_use;
-
- caddr_t rda_next; /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
- SREGS_PAD(pad0);
- u16 tx_status; /* status after transmission of a packet */
- SREGS_PAD(pad1);
- u16 tx_config; /* transmit configuration for this packet */
- SREGS_PAD(pad2);
- u16 tx_pktsize; /* size of the packet to be transmitted */
- SREGS_PAD(pad3);
- u16 tx_frag_count; /* no. of fragments */
-
- SREGS_PAD(pad4);
- u16 tx_frag_ptr_l;
- SREGS_PAD(pad5);
- u16 tx_frag_ptr_h;
- SREGS_PAD(pad6);
- u16 tx_frag_size;
-
- SREGS_PAD(pad7);
- u16 link; /* ptr to next descriptor */
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
- SREGS_PAD(pad0);
- u16 cam_entry_pointer;
- SREGS_PAD(pad1);
- u16 cam_cap0;
- SREGS_PAD(pad2);
- u16 cam_cap1;
- SREGS_PAD(pad3);
- u16 cam_cap2;
-} sonic_cd_t;
-
+#define SONIC_EOL 0x0001
#define CAM_DESCRIPTORS 16
-
-typedef struct {
- sonic_cd_t cam_desc[CAM_DESCRIPTORS];
- SREGS_PAD(pad);
- u16 cam_enable;
-} sonic_cda_t;
-
-#else /* original declarations, little endian 32 bit */
-
-/*
- * structure definitions
- */
-
-typedef struct {
- u32 rx_bufadr_l; /* receive buffer ptr */
- u32 rx_bufadr_h;
-
- u32 rx_bufsize_l; /* no. of words in the receive buffer */
- u32 rx_bufsize_h;
-} sonic_rr_t;
-
-/*
- * Sonic receive descriptor. Receive descriptors are
- * kept in a linked list of these structures.
- */
-
-typedef struct {
- u16 rx_status; /* status after reception of a packet */
- SREGS_PAD(pad0);
- u16 rx_pktlen; /* length of the packet incl. CRC */
- SREGS_PAD(pad1);
-
- /*
- * Pointers to the location in the receive buffer area (RBA)
- * where the packet resides. A packet is always received into
- * a contiguous piece of memory.
- */
- u16 rx_pktptr_l;
- SREGS_PAD(pad2);
- u16 rx_pktptr_h;
- SREGS_PAD(pad3);
-
- u16 rx_seqno; /* sequence no. */
- SREGS_PAD(pad4);
-
- u16 link; /* link to next RDD (end if EOL bit set) */
- SREGS_PAD(pad5);
-
- /*
- * Owner of this descriptor, 0= driver, 1=sonic
- */
-
- u16 in_use;
- SREGS_PAD(pad6);
-
- caddr_t rda_next; /* pointer to next RD */
-} sonic_rd_t;
-
-
-/*
- * Describes a Transmit Descriptor
- */
-typedef struct {
- u16 tx_status; /* status after transmission of a packet */
- SREGS_PAD(pad0);
- u16 tx_config; /* transmit configuration for this packet */
- SREGS_PAD(pad1);
- u16 tx_pktsize; /* size of the packet to be transmitted */
- SREGS_PAD(pad2);
- u16 tx_frag_count; /* no. of fragments */
- SREGS_PAD(pad3);
-
- u16 tx_frag_ptr_l;
- SREGS_PAD(pad4);
- u16 tx_frag_ptr_h;
- SREGS_PAD(pad5);
- u16 tx_frag_size;
- SREGS_PAD(pad6);
-
- u16 link; /* ptr to next descriptor */
- SREGS_PAD(pad7);
-} sonic_td_t;
-
-
-/*
- * Describes an entry in the CAM Descriptor Area.
- */
-
-typedef struct {
- u16 cam_entry_pointer;
- SREGS_PAD(pad0);
- u16 cam_cap0;
- SREGS_PAD(pad1);
- u16 cam_cap1;
- SREGS_PAD(pad2);
- u16 cam_cap2;
- SREGS_PAD(pad3);
-} sonic_cd_t;
-
-#define CAM_DESCRIPTORS 16
-
-
-typedef struct {
- sonic_cd_t cam_desc[CAM_DESCRIPTORS];
- u16 cam_enable;
- SREGS_PAD(pad);
-} sonic_cda_t;
-#endif /* endianness */
+/* Offsets in the various DMA buffers accessed by the SONIC */
+
+#define SONIC_BITMODE16 0
+#define SONIC_BITMODE32 1
+#define SONIC_BUS_SCALE(bitmode) ((bitmode) ? 4 : 2)
+/* Note! These are all measured in bus-size units, so use SONIC_BUS_SCALE */
+#define SIZEOF_SONIC_RR 4
+#define SONIC_RR_BUFADR_L 0
+#define SONIC_RR_BUFADR_H 1
+#define SONIC_RR_BUFSIZE_L 2
+#define SONIC_RR_BUFSIZE_H 3
+
+#define SIZEOF_SONIC_RD 7
+#define SONIC_RD_STATUS 0
+#define SONIC_RD_PKTLEN 1
+#define SONIC_RD_PKTPTR_L 2
+#define SONIC_RD_PKTPTR_H 3
+#define SONIC_RD_SEQNO 4
+#define SONIC_RD_LINK 5
+#define SONIC_RD_IN_USE 6
+
+#define SIZEOF_SONIC_TD 8
+#define SONIC_TD_STATUS 0
+#define SONIC_TD_CONFIG 1
+#define SONIC_TD_PKTSIZE 2
+#define SONIC_TD_FRAG_COUNT 3
+#define SONIC_TD_FRAG_PTR_L 4
+#define SONIC_TD_FRAG_PTR_H 5
+#define SONIC_TD_FRAG_SIZE 6
+#define SONIC_TD_LINK 7
+
+#define SIZEOF_SONIC_CD 4
+#define SONIC_CD_ENTRY_POINTER 0
+#define SONIC_CD_CAP0 1
+#define SONIC_CD_CAP1 2
+#define SONIC_CD_CAP2 3
+
+#define SIZEOF_SONIC_CDA ((CAM_DESCRIPTORS * SIZEOF_SONIC_CD) + 1)
+#define SONIC_CDA_CAM_ENABLE (CAM_DESCRIPTORS * SIZEOF_SONIC_CD)
/*
* Some tunables for the buffer areas. Power of 2 is required
@@ -426,44 +270,60 @@ typedef struct {
*
* MSch: use more buffer space for the slow m68k Macs!
*/
-#ifdef CONFIG_MACSONIC
-#define SONIC_NUM_RRS 32 /* number of receive resources */
-#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS 32 /* number of transmit descriptors */
-#else
-#define SONIC_NUM_RRS 16 /* number of receive resources */
-#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
-#define SONIC_NUM_TDS 16 /* number of transmit descriptors */
-#endif
-#define SONIC_RBSIZE 1520 /* size of one resource buffer */
+#define SONIC_NUM_RRS 16 /* number of receive resources */
+#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */
+#define SONIC_NUM_TDS 16 /* number of transmit descriptors */
-#define SONIC_RDS_MASK (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK (SONIC_NUM_TDS-1)
+#define SONIC_RDS_MASK (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK (SONIC_NUM_TDS-1)
+#define SONIC_RBSIZE 1520 /* size of one resource buffer */
+
+/* Again, measured in bus size units! */
+#define SIZEOF_SONIC_DESC (SIZEOF_SONIC_CDA \
+ + (SIZEOF_SONIC_TD * SONIC_NUM_TDS) \
+ + (SIZEOF_SONIC_RD * SONIC_NUM_RDS) \
+ + (SIZEOF_SONIC_RR * SONIC_NUM_RRS))
/* Information that need to be kept for each board. */
struct sonic_local {
- sonic_cda_t cda; /* virtual CPU address of CDA */
- sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */
- sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource area */
- sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */
- struct sk_buff *tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
- unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
- unsigned char *rba; /* start of receive buffer areas */
- unsigned int cda_laddr; /* logical DMA address of CDA */
- unsigned int tda_laddr; /* logical DMA address of TDA */
- unsigned int rra_laddr; /* logical DMA address of RRA */
- unsigned int rda_laddr; /* logical DMA address of RDA */
- unsigned int rba_laddr; /* logical DMA address of RBA */
- unsigned int cur_rra; /* current indexes to resource areas */
+ /* Bus size. 0 == 16 bits, 1 == 32 bits. */
+ int dma_bitmode;
+ /* Register offset within the longword (independent of endianness,
+ and varies from one type of Macintosh SONIC to another
+ (Aarrgh)) */
+ int reg_offset;
+ void *descriptors;
+ /* Crud. These areas have to be within the same 64K. Therefore
+ we allocate a desriptors page, and point these to places within it. */
+ void *cda; /* CAM descriptor area */
+ void *tda; /* Transmit descriptor area */
+ void *rra; /* Receive resource area */
+ void *rda; /* Receive descriptor area */
+ struct sk_buff* volatile rx_skb[SONIC_NUM_RRS]; /* packets to be received */
+ struct sk_buff* volatile tx_skb[SONIC_NUM_TDS]; /* packets to be transmitted */
+ unsigned int tx_len[SONIC_NUM_TDS]; /* lengths of tx DMA mappings */
+ /* Logical DMA addresses on MIPS, bus addresses on m68k
+ * (so "laddr" is a bit misleading) */
+ dma_addr_t descriptors_laddr;
+ u32 cda_laddr; /* logical DMA address of CDA */
+ u32 tda_laddr; /* logical DMA address of TDA */
+ u32 rra_laddr; /* logical DMA address of RRA */
+ u32 rda_laddr; /* logical DMA address of RDA */
+ dma_addr_t rx_laddr[SONIC_NUM_RRS]; /* logical DMA addresses of rx skbuffs */
+ dma_addr_t tx_laddr[SONIC_NUM_TDS]; /* logical DMA addresses of tx skbuffs */
+ unsigned int rra_end;
+ unsigned int cur_rwp;
unsigned int cur_rx;
- unsigned int cur_tx;
- unsigned int dirty_tx; /* last unacked transmit packet */
- char tx_full;
+ unsigned int cur_tx; /* first unacked transmit packet */
+ unsigned int eol_rx;
+ unsigned int eol_tx; /* last unacked transmit packet */
+ unsigned int next_tx; /* next free TD */
+ struct device *device; /* generic device */
struct net_device_stats stats;
};
-#define TX_TIMEOUT 6
+#define TX_TIMEOUT (3 * HZ)
/* Index to functions, as function prototypes. */
@@ -477,6 +337,114 @@ static void sonic_multicast_list(struct net_device *dev);
static int sonic_init(struct net_device *dev);
static void sonic_tx_timeout(struct net_device *dev);
+/* Internal inlines for reading/writing DMA buffers. Note that bus
+ size and endianness matter here, whereas they don't for registers,
+ as far as we can tell. */
+/* OpenBSD calls this "SWO". I'd like to think that sonic_buf_put()
+ is a much better name. */
+static inline void sonic_buf_put(void* base, int bitmode,
+ int offset, __u16 val)
+{
+ if (bitmode)
+#ifdef __BIG_ENDIAN
+ ((__u16 *) base + (offset*2))[1] = val;
+#else
+ ((__u16 *) base + (offset*2))[0] = val;
+#endif
+ else
+ ((__u16 *) base)[offset] = val;
+}
+
+static inline __u16 sonic_buf_get(void* base, int bitmode,
+ int offset)
+{
+ if (bitmode)
+#ifdef __BIG_ENDIAN
+ return ((volatile __u16 *) base + (offset*2))[1];
+#else
+ return ((volatile __u16 *) base + (offset*2))[0];
+#endif
+ else
+ return ((volatile __u16 *) base)[offset];
+}
+
+/* Inlines that you should actually use for reading/writing DMA buffers */
+static inline void sonic_cda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->cda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_CD) + offset, val);
+}
+
+static inline __u16 sonic_cda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->cda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_CD) + offset);
+}
+
+static inline void sonic_set_cam_enable(struct net_device* dev, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE, val);
+}
+
+static inline __u16 sonic_get_cam_enable(struct net_device* dev)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE);
+}
+
+static inline void sonic_tda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->tda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_TD) + offset, val);
+}
+
+static inline __u16 sonic_tda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->tda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_TD) + offset);
+}
+
+static inline void sonic_rda_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->rda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RD) + offset, val);
+}
+
+static inline __u16 sonic_rda_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->rda, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RD) + offset);
+}
+
+static inline void sonic_rra_put(struct net_device* dev, int entry,
+ int offset, __u16 val)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ sonic_buf_put(lp->rra, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RR) + offset, val);
+}
+
+static inline __u16 sonic_rra_get(struct net_device* dev, int entry,
+ int offset)
+{
+ struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ return sonic_buf_get(lp->rra, lp->dma_bitmode,
+ (entry * SIZEOF_SONIC_RR) + offset);
+}
+
static const char *version =
"sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
new file mode 100644
index 000000000000..c796f41b4a52
--- /dev/null
+++ b/drivers/net/spider_net.c
@@ -0,0 +1,2338 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.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, 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/config.h>
+
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/if_vlan.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <asm/bitops.h>
+#include <asm/pci-bridge.h>
+#include <net/checksum.h>
+
+#include "spider_net.h"
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com> and Jens Osterkamp " \
+ "<Jens.Osterkamp@de.ibm.com>");
+MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
+static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
+
+module_param(rx_descriptors, int, 0644);
+module_param(tx_descriptors, int, 0644);
+
+MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \
+ "in rx chains");
+MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \
+ "in tx chain");
+
+char spider_net_driver_name[] = "spidernet";
+
+static struct pci_device_id spider_net_pci_tbl[] = {
+ { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);
+
+/**
+ * spider_net_read_reg - reads an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to read from
+ *
+ * returns the content of the specified SMMIO register.
+ */
+static u32
+spider_net_read_reg(struct spider_net_card *card, u32 reg)
+{
+ u32 value;
+
+ value = readl(card->regs + reg);
+ value = le32_to_cpu(value);
+
+ return value;
+}
+
+/**
+ * spider_net_write_reg - writes to an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to write to
+ * @value: value to write into the specified SMMIO register
+ */
+static void
+spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
+{
+ value = cpu_to_le32(value);
+ writel(value, card->regs + reg);
+}
+
+/**
+ * spider_net_write_reg_sync - writes to an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to write to
+ * @value: value to write into the specified SMMIO register
+ *
+ * Unlike spider_net_write_reg, this will also make sure the
+ * data arrives on the card by reading the reg again.
+ */
+static void
+spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
+{
+ value = cpu_to_le32(value);
+ writel(value, card->regs + reg);
+ (void)readl(card->regs + reg);
+}
+
+/**
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
+ * @card: device structure
+ *
+ * switches off rx irq by masking them out in the GHIINTnMSK register
+ */
+static void
+spider_net_rx_irq_off(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue &= ~SPIDER_NET_RXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/** spider_net_write_phy - write to phy register
+ * @netdev: adapter to be written to
+ * @mii_id: id of MII
+ * @reg: PHY register
+ * @val: value to be written to phy register
+ *
+ * spider_net_write_phy_register writes to an arbitrary PHY
+ * register via the spider GPCWOPCMD register. We assume the queue does
+ * not run full (not more than 15 commands outstanding).
+ **/
+static void
+spider_net_write_phy(struct net_device *netdev, int mii_id,
+ int reg, int val)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 writevalue;
+
+ writevalue = ((u32)mii_id << 21) |
+ ((u32)reg << 16) | ((u32)val);
+
+ spider_net_write_reg(card, SPIDER_NET_GPCWOPCMD, writevalue);
+}
+
+/** spider_net_read_phy - read from phy register
+ * @netdev: network device to be read from
+ * @mii_id: id of MII
+ * @reg: PHY register
+ *
+ * Returns value read from PHY register
+ *
+ * spider_net_write_phy reads from an arbitrary PHY
+ * register via the spider GPCROPCMD register
+ **/
+static int
+spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 readvalue;
+
+ readvalue = ((u32)mii_id << 21) | ((u32)reg << 16);
+ spider_net_write_reg(card, SPIDER_NET_GPCROPCMD, readvalue);
+
+ /* we don't use semaphores to wait for an SPIDER_NET_GPROPCMPINT
+ * interrupt, as we poll for the completion of the read operation
+ * in spider_net_read_phy. Should take about 50 us */
+ do {
+ readvalue = spider_net_read_reg(card, SPIDER_NET_GPCROPCMD);
+ } while (readvalue & SPIDER_NET_GPREXEC);
+
+ readvalue &= SPIDER_NET_GPRDAT_MASK;
+
+ return readvalue;
+}
+
+/**
+ * spider_net_rx_irq_on - switch on rx irq on this spider card
+ * @card: device structure
+ *
+ * switches on rx irq by enabling them in the GHIINTnMSK register
+ */
+static void
+spider_net_rx_irq_on(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue |= SPIDER_NET_RXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_tx_irq_off - switch off tx irq on this spider card
+ * @card: device structure
+ *
+ * switches off tx irq by masking them out in the GHIINTnMSK register
+ */
+static void
+spider_net_tx_irq_off(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue &= ~SPIDER_NET_TXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_tx_irq_on - switch on tx irq on this spider card
+ * @card: device structure
+ *
+ * switches on tx irq by enabling them in the GHIINTnMSK register
+ */
+static void
+spider_net_tx_irq_on(struct spider_net_card *card)
+{
+ u32 regvalue;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->intmask_lock, flags);
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ regvalue |= SPIDER_NET_TXINT;
+ spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
+ spin_unlock_irqrestore(&card->intmask_lock, flags);
+}
+
+/**
+ * spider_net_set_promisc - sets the unicast address or the promiscuous mode
+ * @card: card structure
+ *
+ * spider_net_set_promisc sets the unicast destination address filter and
+ * thus either allows for non-promisc mode or promisc mode
+ */
+static void
+spider_net_set_promisc(struct spider_net_card *card)
+{
+ u32 macu, macl;
+ struct net_device *netdev = card->netdev;
+
+ if (netdev->flags & IFF_PROMISC) {
+ /* clear destination entry 0 */
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
+ SPIDER_NET_PROMISC_VALUE);
+ } else {
+ macu = netdev->dev_addr[0];
+ macu <<= 8;
+ macu |= netdev->dev_addr[1];
+ memcpy(&macl, &netdev->dev_addr[2], sizeof(macl));
+
+ macu |= SPIDER_NET_UA_DESCR_VALUE;
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR, macu);
+ spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + 0x04, macl);
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R,
+ SPIDER_NET_NONPROMISC_VALUE);
+ }
+}
+
+/**
+ * spider_net_get_mac_address - read mac address from spider card
+ * @card: device structure
+ *
+ * reads MAC address from GMACUNIMACU and GMACUNIMACL registers
+ */
+static int
+spider_net_get_mac_address(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 macl, macu;
+
+ macl = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACL);
+ macu = spider_net_read_reg(card, SPIDER_NET_GMACUNIMACU);
+
+ netdev->dev_addr[0] = (macu >> 24) & 0xff;
+ netdev->dev_addr[1] = (macu >> 16) & 0xff;
+ netdev->dev_addr[2] = (macu >> 8) & 0xff;
+ netdev->dev_addr[3] = macu & 0xff;
+ netdev->dev_addr[4] = (macl >> 8) & 0xff;
+ netdev->dev_addr[5] = macl & 0xff;
+
+ if (!is_valid_ether_addr(&netdev->dev_addr[0]))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * spider_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum spider_net_descr_status
+spider_net_get_descr_status(struct spider_net_descr *descr)
+{
+ u32 cmd_status;
+ rmb();
+ cmd_status = descr->dmac_cmd_status;
+ rmb();
+ cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
+ /* no need to mask out any bits, as cmd_status is 32 bits wide only
+ * (and unsigned) */
+ return cmd_status;
+}
+
+/**
+ * spider_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void
+spider_net_set_descr_status(struct spider_net_descr *descr,
+ enum spider_net_descr_status status)
+{
+ u32 cmd_status;
+ /* read the status */
+ mb();
+ cmd_status = descr->dmac_cmd_status;
+ /* clean the upper 4 bits */
+ cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
+ /* add the status to it */
+ cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
+ /* and write it back */
+ descr->dmac_cmd_status = cmd_status;
+ wmb();
+}
+
+/**
+ * spider_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ *
+ */
+static void
+spider_net_free_chain(struct spider_net_card *card,
+ struct spider_net_descr_chain *chain)
+{
+ struct spider_net_descr *descr;
+
+ for (descr = chain->tail; !descr->bus_addr; descr = descr->next) {
+ pci_unmap_single(card->pdev, descr->bus_addr,
+ SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+ descr->bus_addr = 0;
+ }
+}
+
+/**
+ * spider_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_init_chain(struct spider_net_card *card,
+ struct spider_net_descr_chain *chain,
+ struct spider_net_descr *start_descr, int no)
+{
+ int i;
+ struct spider_net_descr *descr;
+
+ spin_lock_init(&card->chain_lock);
+
+ descr = start_descr;
+ memset(descr, 0, sizeof(*descr) * no);
+
+ /* set up the hardware pointers in each descriptor */
+ for (i=0; i<no; i++, descr++) {
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+
+ descr->bus_addr =
+ pci_map_single(card->pdev, descr,
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+
+ if (descr->bus_addr == DMA_ERROR_CODE)
+ goto iommu_error;
+
+ descr->next = descr + 1;
+ descr->prev = descr - 1;
+
+ }
+ /* do actual circular list */
+ (descr-1)->next = start_descr;
+ start_descr->prev = descr-1;
+
+ descr = start_descr;
+ for (i=0; i < no; i++, descr++) {
+ descr->next_descr_addr = descr->next->bus_addr;
+ }
+
+ chain->head = start_descr;
+ chain->tail = start_descr;
+
+ return 0;
+
+iommu_error:
+ descr = start_descr;
+ for (i=0; i < no; i++, descr++)
+ if (descr->bus_addr)
+ pci_unmap_single(card->pdev, descr->bus_addr,
+ SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
+ return -ENOMEM;
+}
+
+/**
+ * spider_net_free_rx_chain_contents - frees descr contents in rx chain
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static void
+spider_net_free_rx_chain_contents(struct spider_net_card *card)
+{
+ struct spider_net_descr *descr;
+
+ descr = card->rx_chain.head;
+ while (descr->next != card->rx_chain.head) {
+ if (descr->skb) {
+ dev_kfree_skb(descr->skb);
+ pci_unmap_single(card->pdev, descr->buf_addr,
+ SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+ }
+ descr = descr->next;
+ }
+}
+
+/**
+ * spider_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int
+spider_net_prepare_rx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ int error = 0;
+ int offset;
+ int bufsize;
+
+ /* we need to round up the buffer size to a multiple of 128 */
+ bufsize = (SPIDER_NET_MAX_MTU + SPIDER_NET_RXBUF_ALIGN - 1) &
+ (~(SPIDER_NET_RXBUF_ALIGN - 1));
+
+ /* and we need to have it 128 byte aligned, therefore we allocate a
+ * bit more */
+ /* allocate an skb */
+ descr->skb = dev_alloc_skb(bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
+ if (!descr->skb) {
+ if (net_ratelimit())
+ if (netif_msg_rx_err(card))
+ pr_err("Not enough memory to allocate "
+ "rx buffer\n");
+ return -ENOMEM;
+ }
+ descr->buf_size = bufsize;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_status = 0;
+ descr->data_error = 0;
+
+ offset = ((unsigned long)descr->skb->data) &
+ (SPIDER_NET_RXBUF_ALIGN - 1);
+ if (offset)
+ skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
+ /* io-mmu-map the skb */
+ descr->buf_addr = pci_map_single(card->pdev, descr->skb->data,
+ SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+ if (descr->buf_addr == DMA_ERROR_CODE) {
+ dev_kfree_skb_any(descr->skb);
+ if (netif_msg_rx_err(card))
+ pr_err("Could not iommu-map rx buffer\n");
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ } else {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_RX_CARDOWNED;
+ }
+
+ return error;
+}
+
+/**
+ * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * @card: card structure
+ *
+ * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * chip by writing to the appropriate register. DMA is enabled in
+ * spider_net_enable_rxdmac.
+ */
+static void
+spider_net_enable_rxchtails(struct spider_net_card *card)
+{
+ /* assume chain is aligned correctly */
+ spider_net_write_reg(card, SPIDER_NET_GDADCHA ,
+ card->rx_chain.tail->bus_addr);
+}
+
+/**
+ * spider_net_enable_rxdmac - enables a receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static void
+spider_net_enable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_VALUE);
+}
+
+/**
+ * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * refills descriptors in all chains (last used chain first): allocates skbs
+ * and iommu-maps them.
+ */
+static void
+spider_net_refill_rx_chain(struct spider_net_card *card)
+{
+ struct spider_net_descr_chain *chain;
+ int count = 0;
+ unsigned long flags;
+
+ chain = &card->rx_chain;
+
+ spin_lock_irqsave(&card->chain_lock, flags);
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ count++;
+ chain->head = chain->head->next;
+ }
+ spin_unlock_irqrestore(&card->chain_lock, flags);
+
+ /* could be optimized, only do that, if we know the DMA processing
+ * has terminated */
+ if (count)
+ spider_net_enable_rxdmac(card);
+}
+
+/**
+ * spider_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_alloc_rx_skbs(struct spider_net_card *card)
+{
+ int result;
+ struct spider_net_descr_chain *chain;
+
+ result = -ENOMEM;
+
+ chain = &card->rx_chain;
+ /* put at least one buffer into the chain. if this fails,
+ * we've got a problem. if not, spider_net_refill_rx_chain
+ * will do the rest at the end of this function */
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ goto error;
+ else
+ chain->head = chain->head->next;
+
+ /* this will allocate the rest of the rx buffers; if not, it's
+ * business as usual later on */
+ spider_net_refill_rx_chain(card);
+ return 0;
+
+error:
+ spider_net_free_rx_chain_contents(card);
+ return result;
+}
+
+/**
+ * spider_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void
+spider_net_release_tx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ struct sk_buff *skb;
+
+ /* unmap the skb */
+ skb = descr->skb;
+ pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
+ PCI_DMA_BIDIRECTIONAL);
+
+ dev_kfree_skb_any(skb);
+
+ /* set status to not used */
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+}
+
+/**
+ * spider_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @brutal: if set, don't care about whether descriptor seems to be in use
+ *
+ * releases the tx descriptors that spider has finished with (if non-brutal)
+ * or simply release tx descriptors (if brutal)
+ */
+static void
+spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
+{
+ struct spider_net_descr_chain *tx_chain = &card->tx_chain;
+ enum spider_net_descr_status status;
+
+ spider_net_tx_irq_off(card);
+
+ /* no lock for chain needed, if this is only executed once at a time */
+again:
+ for (;;) {
+ status = spider_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case SPIDER_NET_DESCR_CARDOWNED:
+ if (!brutal) goto out;
+ /* fallthrough, if we release the descriptors
+ * brutally (then we don't care about
+ * SPIDER_NET_DESCR_CARDOWNED) */
+ case SPIDER_NET_DESCR_RESPONSE_ERROR:
+ case SPIDER_NET_DESCR_PROTECTION_ERROR:
+ case SPIDER_NET_DESCR_FORCE_END:
+ if (netif_msg_tx_err(card))
+ pr_err("%s: forcing end of tx descriptor "
+ "with status x%02x\n",
+ card->netdev->name, status);
+ card->netdev_stats.tx_dropped++;
+ break;
+
+ case SPIDER_NET_DESCR_COMPLETE:
+ card->netdev_stats.tx_packets++;
+ card->netdev_stats.tx_bytes +=
+ tx_chain->tail->skb->len;
+ break;
+
+ default: /* any other value (== SPIDER_NET_DESCR_NOT_IN_USE) */
+ goto out;
+ }
+ spider_net_release_tx_descr(card, tx_chain->tail);
+ tx_chain->tail = tx_chain->tail->next;
+ }
+out:
+ netif_wake_queue(card->netdev);
+
+ if (!brutal) {
+ /* switch on tx irqs (while we are still in the interrupt
+ * handler, so we don't get an interrupt), check again
+ * for done descriptors. This results in fewer interrupts */
+ spider_net_tx_irq_on(card);
+ status = spider_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case SPIDER_NET_DESCR_RESPONSE_ERROR:
+ case SPIDER_NET_DESCR_PROTECTION_ERROR:
+ case SPIDER_NET_DESCR_FORCE_END:
+ case SPIDER_NET_DESCR_COMPLETE:
+ goto again;
+ default:
+ break;
+ }
+ }
+
+}
+
+/**
+ * spider_net_get_multicast_hash - generates hash for multicast filter table
+ * @addr: multicast address
+ *
+ * returns the hash value.
+ *
+ * spider_net_get_multicast_hash calculates a hash value for a given multicast
+ * address, that is used to set the multicast filter tables
+ */
+static u8
+spider_net_get_multicast_hash(struct net_device *netdev, __u8 *addr)
+{
+ /* FIXME: an addr of 01:00:5e:00:00:01 must result in 0xa9,
+ * ff:ff:ff:ff:ff:ff must result in 0xfd */
+ u32 crc;
+ u8 hash;
+
+ crc = crc32_be(~0, addr, netdev->addr_len);
+
+ hash = (crc >> 27);
+ hash <<= 3;
+ hash |= crc & 7;
+
+ return hash;
+}
+
+/**
+ * spider_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * spider_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void
+spider_net_set_multi(struct net_device *netdev)
+{
+ struct dev_mc_list *mc;
+ u8 hash;
+ int i;
+ u32 reg;
+ struct spider_net_card *card = netdev_priv(netdev);
+ unsigned long bitmask[SPIDER_NET_MULTICAST_HASHES / BITS_PER_LONG] =
+ {0, };
+
+ spider_net_set_promisc(card);
+
+ if (netdev->flags & IFF_ALLMULTI) {
+ for (i = 0; i < SPIDER_NET_MULTICAST_HASHES; i++) {
+ set_bit(i, bitmask);
+ }
+ goto write_hash;
+ }
+
+ /* well, we know, what the broadcast hash value is: it's xfd
+ hash = spider_net_get_multicast_hash(netdev, netdev->broadcast); */
+ set_bit(0xfd, bitmask);
+
+ for (mc = netdev->mc_list; mc; mc = mc->next) {
+ hash = spider_net_get_multicast_hash(netdev, mc->dmi_addr);
+ set_bit(hash, bitmask);
+ }
+
+write_hash:
+ for (i = 0; i < SPIDER_NET_MULTICAST_HASHES / 4; i++) {
+ reg = 0;
+ if (test_bit(i * 4, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 1, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 2, bitmask))
+ reg += 0x08;
+ reg <<= 8;
+ if (test_bit(i * 4 + 3, bitmask))
+ reg += 0x08;
+
+ spider_net_write_reg(card, SPIDER_NET_GMRMHFILnR + i * 4, reg);
+ }
+}
+
+/**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
+ * spider_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+int
+spider_net_stop(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+
+ netif_poll_disable(netdev);
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ /* disable/mask all interrupts */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+
+ /* free_irq(netdev->irq, netdev);*/
+ free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_FEND_VALUE);
+
+ /* turn off DMA, force end */
+ spider_net_disable_rxdmac(card);
+
+ /* release chains */
+ spider_net_release_tx_chain(card, 1);
+
+ spider_net_free_chain(card, &card->tx_chain);
+ spider_net_free_chain(card, &card->rx_chain);
+
+ return 0;
+}
+
+/**
+ * spider_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct spider_net_descr *
+spider_net_get_next_tx_descr(struct spider_net_card *card)
+{
+ /* check, if head points to not-in-use descr */
+ if ( spider_net_get_descr_status(card->tx_chain.head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE ) {
+ return card->tx_chain.head;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * spider_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void
+spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
+ struct sk_buff *skb)
+{
+ if (skb->ip_summed != CHECKSUM_HW) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
+ return;
+ }
+
+ /* is packet ip?
+ * if yes: tcp? udp? */
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
+ } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
+ } else { /* the stack should checksum non-tcp and non-udp
+ packets on his own: NETIF_F_IP_CSUM */
+ descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
+ }
+ }
+}
+
+/**
+ * spider_net_prepare_tx_descr - fill tx descriptor with skb data
+ * @card: card structure
+ * @descr: descriptor structure to fill out
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ * fills out the descriptor structure with skb data and len. Copies data,
+ * if needed (32bit DMA!)
+ */
+static int
+spider_net_prepare_tx_descr(struct spider_net_card *card,
+ struct spider_net_descr *descr,
+ struct sk_buff *skb)
+{
+ descr->buf_addr = pci_map_single(card->pdev, skb->data,
+ skb->len, PCI_DMA_BIDIRECTIONAL);
+ if (descr->buf_addr == DMA_ERROR_CODE) {
+ if (netif_msg_tx_err(card))
+ pr_err("could not iommu-map packet (%p, %i). "
+ "Dropping packet\n", skb->data, skb->len);
+ return -ENOMEM;
+ }
+
+ descr->buf_size = skb->len;
+ descr->skb = skb;
+ descr->data_status = 0;
+
+ /* make sure the above values are in memory before we change the
+ * status */
+ wmb();
+
+ spider_net_set_txdescr_cmdstat(descr,skb);
+
+ return 0;
+}
+
+/**
+ * spider_net_kick_tx_dma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ * spider_net_kick_tx_dma writes the current tx chain head as start address
+ * of the tx descriptor chain and enables the transmission DMA engine
+ */
+static void
+spider_net_kick_tx_dma(struct spider_net_card *card,
+ struct spider_net_descr *descr)
+{
+ /* this is the only descriptor in the output chain.
+ * Enable TX DMA */
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+ descr->bus_addr);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_VALUE);
+}
+
+/**
+ * spider_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ struct spider_net_descr *descr;
+ int result;
+
+ descr = spider_net_get_next_tx_descr(card);
+
+ if (!descr) {
+ netif_stop_queue(netdev);
+
+ descr = spider_net_get_next_tx_descr(card);
+ if (!descr)
+ goto error;
+ else
+ netif_start_queue(netdev);
+ }
+
+ result = spider_net_prepare_tx_descr(card, descr, skb);
+ if (result)
+ goto error;
+
+ card->tx_chain.head = card->tx_chain.head->next;
+
+ /* make sure the status from spider_net_prepare_tx_descr is in
+ * memory before we check out the previous descriptor */
+ wmb();
+
+ if (spider_net_get_descr_status(descr->prev) !=
+ SPIDER_NET_DESCR_CARDOWNED)
+ spider_net_kick_tx_dma(card, descr);
+
+ return NETDEV_TX_OK;
+
+error:
+ card->netdev_stats.tx_dropped++;
+ return NETDEV_TX_LOCKED;
+}
+
+/**
+ * spider_net_do_ioctl - called for device ioctls
+ * @netdev: interface device structure
+ * @ifr: request parameter structure for ioctl
+ * @cmd: command code for ioctl
+ *
+ * returns 0 on success, <0 on failure. Currently, we have no special ioctls.
+ * -EOPNOTSUPP is returned, if an unknown ioctl was requested
+ */
+static int
+spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * returns 1 on success, 0 if no packet was passed to the stack
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static int
+spider_net_pass_skb_up(struct spider_net_descr *descr,
+ struct spider_net_card *card)
+{
+ struct sk_buff *skb;
+ struct net_device *netdev;
+ u32 data_status, data_error;
+
+ data_status = descr->data_status;
+ data_error = descr->data_error;
+
+ netdev = card->netdev;
+
+ /* check for errors in the data_error flag */
+ if ((data_error & SPIDER_NET_DATA_ERROR_MASK) &&
+ netif_msg_rx_err(card))
+ pr_err("error in received descriptor found, "
+ "data_status=x%08x, data_error=x%08x\n",
+ data_status, data_error);
+
+ /* prepare skb, unmap descriptor */
+ skb = descr->skb;
+ pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_MTU,
+ PCI_DMA_BIDIRECTIONAL);
+
+ /* the cases we'll throw away the packet immediately */
+ if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+ return 0;
+
+ skb->dev = netdev;
+ skb_put(skb, descr->valid_size);
+
+ /* the card seems to add 2 bytes of junk in front
+ * of the ethernet frame */
+#define SPIDER_MISALIGN 2
+ skb_pull(skb, SPIDER_MISALIGN);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ /* checksum offload */
+ if (card->options.rx_csum) {
+ if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
+ (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
+ if (data_status & SPIDER_NET_VLAN_PACKET) {
+ /* further enhancements: HW-accel VLAN
+ * vlan_hwaccel_receive_skb
+ */
+ }
+
+ /* pass skb up to stack */
+ netif_receive_skb(skb);
+
+ /* update netdevice statistics */
+ card->netdev_stats.rx_packets++;
+ card->netdev_stats.rx_bytes += skb->len;
+
+ return 1;
+}
+
+/**
+ * spider_net_decode_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int
+spider_net_decode_one_descr(struct spider_net_card *card)
+{
+ enum spider_net_descr_status status;
+ struct spider_net_descr *descr;
+ struct spider_net_descr_chain *chain;
+ int result;
+
+ chain = &card->rx_chain;
+ descr = chain->tail;
+
+ status = spider_net_get_descr_status(descr);
+
+ if (status == SPIDER_NET_DESCR_CARDOWNED) {
+ /* nothing in the descriptor yet */
+ return 0;
+ }
+
+ if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
+ /* not initialized yet, I bet chain->tail == chain->head
+ * and the ring is empty */
+ spider_net_refill_rx_chain(card);
+ return 0;
+ }
+
+ /* descriptor definitively used -- move on head */
+ chain->tail = descr->next;
+
+ result = 0;
+ if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
+ (status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
+ (status == SPIDER_NET_DESCR_FORCE_END) ) {
+ if (netif_msg_rx_err(card))
+ pr_err("%s: dropping RX descriptor with state %d\n",
+ card->netdev->name, status);
+ card->netdev_stats.rx_dropped++;
+ goto refill;
+ }
+
+ if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
+ (status != SPIDER_NET_DESCR_FRAME_END) ) {
+ if (netif_msg_rx_err(card))
+ pr_err("%s: RX descriptor with state %d\n",
+ card->netdev->name, status);
+ goto refill;
+ }
+
+ /* ok, we've got a packet in descr */
+ result = spider_net_pass_skb_up(descr, card);
+refill:
+ spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ /* change the descriptor state: */
+ spider_net_refill_rx_chain(card);
+
+ return result;
+}
+
+/**
+ * spider_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ * spider_net_poll returns all packets from the rx descriptors to the stack
+ * (using netif_receive_skb). If all/enough packets are up, the driver
+ * reenables interrupts and returns 0. If not, 1 is returned.
+ */
+static int
+spider_net_poll(struct net_device *netdev, int *budget)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ int packets_to_do, packets_done = 0;
+ int no_more_packets = 0;
+
+ packets_to_do = min(*budget, netdev->quota);
+
+ while (packets_to_do) {
+ if (spider_net_decode_one_descr(card)) {
+ packets_done++;
+ packets_to_do--;
+ } else {
+ /* no more packets for the stack */
+ no_more_packets = 1;
+ break;
+ }
+ }
+
+ netdev->quota -= packets_done;
+ *budget -= packets_done;
+
+ /* if all packets are in the stack, enable interrupts and return 0 */
+ /* if not, return 1 */
+ if (no_more_packets) {
+ netif_rx_complete(netdev);
+ spider_net_rx_irq_on(card);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * spider_net_vlan_rx_reg - initializes VLAN structures in the driver and card
+ * @netdev: interface device structure
+ * @grp: vlan_group structure that is registered (NULL on destroying interface)
+ */
+static void
+spider_net_vlan_rx_reg(struct net_device *netdev, struct vlan_group *grp)
+{
+ /* further enhancement... yet to do */
+ return;
+}
+
+/**
+ * spider_net_vlan_rx_add - adds VLAN id to the card filter
+ * @netdev: interface device structure
+ * @vid: VLAN id to add
+ */
+static void
+spider_net_vlan_rx_add(struct net_device *netdev, uint16_t vid)
+{
+ /* further enhancement... yet to do */
+ /* add vid to card's VLAN filter table */
+ return;
+}
+
+/**
+ * spider_net_vlan_rx_kill - removes VLAN id to the card filter
+ * @netdev: interface device structure
+ * @vid: VLAN id to remove
+ */
+static void
+spider_net_vlan_rx_kill(struct net_device *netdev, uint16_t vid)
+{
+ /* further enhancement... yet to do */
+ /* remove vid from card's VLAN filter table */
+}
+
+/**
+ * spider_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the spider_net_card struct
+ */
+static struct net_device_stats *
+spider_net_get_stats(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ struct net_device_stats *stats = &card->netdev_stats;
+ return stats;
+}
+
+/**
+ * spider_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int
+spider_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+ * and mtu is outbound only anyway */
+ if ( (new_mtu < SPIDER_NET_MIN_MTU ) ||
+ (new_mtu > SPIDER_NET_MAX_MTU) )
+ return -EINVAL;
+ netdev->mtu = new_mtu;
+ return 0;
+}
+
+/**
+ * spider_net_set_mac - sets the MAC of an interface
+ * @netdev: interface device structure
+ * @ptr: pointer to new MAC address
+ *
+ * Returns 0 on success, <0 on failure. Currently, we don't support this
+ * and will always return EOPNOTSUPP.
+ */
+static int
+spider_net_set_mac(struct net_device *netdev, void *p)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 macl, macu, regvalue;
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ /* switch off GMACTPE and GMACRPE */
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+ regvalue &= ~((1 << 5) | (1 << 6));
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
+ /* write mac */
+ macu = (addr->sa_data[0]<<24) + (addr->sa_data[1]<<16) +
+ (addr->sa_data[2]<<8) + (addr->sa_data[3]);
+ macl = (addr->sa_data[4]<<8) + (addr->sa_data[5]);
+ spider_net_write_reg(card, SPIDER_NET_GMACUNIMACU, macu);
+ spider_net_write_reg(card, SPIDER_NET_GMACUNIMACL, macl);
+
+ /* switch GMACTPE and GMACRPE back on */
+ regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+ regvalue |= ((1 << 5) | (1 << 6));
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
+ spider_net_set_promisc(card);
+
+ /* look up, whether we have been successful */
+ if (spider_net_get_mac_address(netdev))
+ return -EADDRNOTAVAIL;
+ if (memcmp(netdev->dev_addr,addr->sa_data,netdev->addr_len))
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+
+/**
+ * spider_net_enable_txdmac - enables a TX DMA controller
+ * @card: card structure
+ *
+ * spider_net_enable_txdmac enables the TX DMA controller by setting the
+ * descriptor chain tail address
+ */
+static void
+spider_net_enable_txdmac(struct spider_net_card *card)
+{
+ /* assume chain is aligned correctly */
+ spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+ card->tx_chain.tail->bus_addr);
+}
+
+/**
+ * spider_net_handle_error_irq - handles errors raised by an interrupt
+ * @card: card structure
+ * @status_reg: interrupt status register 0 (GHIINT0STS)
+ *
+ * spider_net_handle_error_irq treats or ignores all error conditions
+ * found when an interrupt is presented
+ */
+static void
+spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
+{
+ u32 error_reg1, error_reg2;
+ u32 i;
+ int show_error = 1;
+
+ error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
+ error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+
+ /* check GHIINT0STS ************************************/
+ if (status_reg)
+ for (i = 0; i < 32; i++)
+ if (status_reg & (1<<i))
+ switch (i)
+ {
+ /* let error_reg1 and error_reg2 evaluation decide, what to do
+ case SPIDER_NET_PHYINT:
+ case SPIDER_NET_GMAC2INT:
+ case SPIDER_NET_GMAC1INT:
+ case SPIDER_NET_GIPSINT:
+ case SPIDER_NET_GFIFOINT:
+ case SPIDER_NET_DMACINT:
+ case SPIDER_NET_GSYSINT:
+ break; */
+
+ case SPIDER_NET_GPWOPCMPINT:
+ /* PHY write operation completed */
+ show_error = 0;
+ break;
+ case SPIDER_NET_GPROPCMPINT:
+ /* PHY read operation completed */
+ /* we don't use semaphores, as we poll for the completion
+ * of the read operation in spider_net_read_phy. Should take
+ * about 50 us */
+ show_error = 0;
+ break;
+ case SPIDER_NET_GPWFFINT:
+ /* PHY command queue full */
+ if (netif_msg_intr(card))
+ pr_err("PHY write queue full\n");
+ show_error = 0;
+ break;
+
+ /* case SPIDER_NET_GRMDADRINT: not used. print a message */
+ /* case SPIDER_NET_GRMARPINT: not used. print a message */
+ /* case SPIDER_NET_GRMMPINT: not used. print a message */
+
+ case SPIDER_NET_GDTDEN0INT:
+ /* someone has set TX_DMA_EN to 0 */
+ show_error = 0;
+ break;
+
+ case SPIDER_NET_GDDDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDCDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDBDEN0INT: /* fallthrough */
+ case SPIDER_NET_GDADEN0INT:
+ /* someone has set RX_DMA_EN to 0 */
+ show_error = 0;
+ break;
+
+ /* RX interrupts */
+ case SPIDER_NET_GDDFDCINT:
+ case SPIDER_NET_GDCFDCINT:
+ case SPIDER_NET_GDBFDCINT:
+ case SPIDER_NET_GDAFDCINT:
+ /* case SPIDER_NET_GDNMINT: not used. print a message */
+ /* case SPIDER_NET_GCNMINT: not used. print a message */
+ /* case SPIDER_NET_GBNMINT: not used. print a message */
+ /* case SPIDER_NET_GANMINT: not used. print a message */
+ /* case SPIDER_NET_GRFNMINT: not used. print a message */
+ show_error = 0;
+ break;
+
+ /* TX interrupts */
+ case SPIDER_NET_GDTFDCINT:
+ show_error = 0;
+ break;
+ case SPIDER_NET_GTTEDINT:
+ show_error = 0;
+ break;
+ case SPIDER_NET_GDTDCEINT:
+ /* chain end. If a descriptor should be sent, kick off
+ * tx dma
+ if (card->tx_chain.tail == card->tx_chain.head)
+ spider_net_kick_tx_dma(card);
+ show_error = 0; */
+ break;
+
+ /* case SPIDER_NET_G1TMCNTINT: not used. print a message */
+ /* case SPIDER_NET_GFREECNTINT: not used. print a message */
+ }
+
+ /* check GHIINT1STS ************************************/
+ if (error_reg1)
+ for (i = 0; i < 32; i++)
+ if (error_reg1 & (1<<i))
+ switch (i)
+ {
+ case SPIDER_NET_GTMFLLINT:
+ if (netif_msg_intr(card))
+ pr_err("Spider TX RAM full\n");
+ show_error = 0;
+ break;
+ case SPIDER_NET_GRMFLLINT:
+ if (netif_msg_intr(card))
+ pr_err("Spider RX RAM full, incoming packets "
+ "might be discarded !\n");
+ netif_rx_schedule(card->netdev);
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+ break;
+
+ /* case SPIDER_NET_GTMSHTINT: problem, print a message */
+ case SPIDER_NET_GDTINVDINT:
+ /* allrighty. tx from previous descr ok */
+ show_error = 0;
+ break;
+ /* case SPIDER_NET_GRFDFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFCFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFBFLLINT: print a message down there */
+ /* case SPIDER_NET_GRFAFLLINT: print a message down there */
+
+ /* chain end */
+ case SPIDER_NET_GDDDCEINT: /* fallthrough */
+ case SPIDER_NET_GDCDCEINT: /* fallthrough */
+ case SPIDER_NET_GDBDCEINT: /* fallthrough */
+ case SPIDER_NET_GDADCEINT:
+ if (netif_msg_intr(card))
+ pr_err("got descriptor chain end interrupt, "
+ "restarting DMAC %c.\n",
+ 'D'+i-SPIDER_NET_GDDDCEINT);
+ spider_net_refill_rx_chain(card);
+ show_error = 0;
+ break;
+
+ /* invalid descriptor */
+ case SPIDER_NET_GDDINVDINT: /* fallthrough */
+ case SPIDER_NET_GDCINVDINT: /* fallthrough */
+ case SPIDER_NET_GDBINVDINT: /* fallthrough */
+ case SPIDER_NET_GDAINVDINT:
+ /* could happen when rx chain is full */
+ spider_net_refill_rx_chain(card);
+ show_error = 0;
+ break;
+
+ /* case SPIDER_NET_GDTRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDDRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDCRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDBRSERINT: problem, print a message */
+ /* case SPIDER_NET_GDARSERINT: problem, print a message */
+ /* case SPIDER_NET_GDSERINT: problem, print a message */
+ /* case SPIDER_NET_GDTPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDDPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDCPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDBPTERINT: problem, print a message */
+ /* case SPIDER_NET_GDAPTERINT: problem, print a message */
+ default:
+ show_error = 1;
+ break;
+ }
+
+ /* check GHIINT2STS ************************************/
+ if (error_reg2)
+ for (i = 0; i < 32; i++)
+ if (error_reg2 & (1<<i))
+ switch (i)
+ {
+ /* there is nothing we can (want to) do at this time. Log a
+ * message, we can switch on and off the specific values later on
+ case SPIDER_NET_GPROPERINT:
+ case SPIDER_NET_GMCTCRSNGINT:
+ case SPIDER_NET_GMCTLCOLINT:
+ case SPIDER_NET_GMCTTMOTINT:
+ case SPIDER_NET_GMCRCAERINT:
+ case SPIDER_NET_GMCRCALERINT:
+ case SPIDER_NET_GMCRALNERINT:
+ case SPIDER_NET_GMCROVRINT:
+ case SPIDER_NET_GMCRRNTINT:
+ case SPIDER_NET_GMCRRXERINT:
+ case SPIDER_NET_GTITCSERINT:
+ case SPIDER_NET_GTIFMTERINT:
+ case SPIDER_NET_GTIPKTRVKINT:
+ case SPIDER_NET_GTISPINGINT:
+ case SPIDER_NET_GTISADNGINT:
+ case SPIDER_NET_GTISPDNGINT:
+ case SPIDER_NET_GRIFMTERINT:
+ case SPIDER_NET_GRIPKTRVKINT:
+ case SPIDER_NET_GRISPINGINT:
+ case SPIDER_NET_GRISADNGINT:
+ case SPIDER_NET_GRISPDNGINT:
+ break;
+ */
+ default:
+ break;
+ }
+
+ if ((show_error) && (netif_msg_intr(card)))
+ pr_err("Got error interrupt, GHIINT0STS = 0x%08x, "
+ "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
+ status_reg, error_reg1, error_reg2);
+
+ /* clear interrupt sources */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1STS, error_reg1);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2STS, error_reg2);
+}
+
+/**
+ * spider_net_interrupt - interrupt handler for spider_net
+ * @irq: interupt number
+ * @ptr: pointer to net_device
+ * @regs: PU registers
+ *
+ * returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no
+ * interrupt found raised by card.
+ *
+ * This is the interrupt handler, that turns off
+ * interrupts for this device and makes the stack poll the driver
+ */
+static irqreturn_t
+spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ struct net_device *netdev = ptr;
+ struct spider_net_card *card = netdev_priv(netdev);
+ u32 status_reg;
+
+ status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+
+ if (!status_reg)
+ return IRQ_NONE;
+
+ if (status_reg & SPIDER_NET_TXINT)
+ spider_net_release_tx_chain(card, 0);
+
+ if (status_reg & SPIDER_NET_RXINT ) {
+ spider_net_rx_irq_off(card);
+ netif_rx_schedule(netdev);
+ }
+
+ /* we do this after rx and tx processing, as we want the tx chain
+ * processed to see, whether we should restart tx dma processing */
+ spider_net_handle_error_irq(card, status_reg);
+
+ /* clear interrupt sources */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * spider_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void
+spider_net_poll_controller(struct net_device *netdev)
+{
+ disable_irq(netdev->irq);
+ spider_net_interrupt(netdev->irq, netdev, NULL);
+ enable_irq(netdev->irq);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * spider_net_init_card - initializes the card
+ * @card: card structure
+ *
+ * spider_net_init_card initializes the card so that other registers can
+ * be used
+ */
+static void
+spider_net_init_card(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+}
+
+/**
+ * spider_net_enable_card - enables the card by setting all kinds of regs
+ * @card: card structure
+ *
+ * spider_net_enable_card sets a lot of SMMIO registers to enable the device
+ */
+static void
+spider_net_enable_card(struct spider_net_card *card)
+{
+ int i;
+ /* the following array consists of (register),(value) pairs
+ * that are set in this function. A register of 0 ends the list */
+ u32 regs[][2] = {
+ { SPIDER_NET_GRESUMINTNUM, 0 },
+ { SPIDER_NET_GREINTNUM, 0 },
+
+ /* set interrupt frame number registers */
+ /* clear the single DMA engine registers first */
+ { SPIDER_NET_GFAFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFBFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFCFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ { SPIDER_NET_GFDFRMNUM, SPIDER_NET_GFXFRAMES_VALUE },
+ /* then set, what we really need */
+ { SPIDER_NET_GFFRMNUM, SPIDER_NET_FRAMENUM_VALUE },
+
+ /* timer counter registers and stuff */
+ { SPIDER_NET_GFREECNNUM, 0 },
+ { SPIDER_NET_GONETIMENUM, 0 },
+ { SPIDER_NET_GTOUTFRMNUM, 0 },
+
+ /* RX mode setting */
+ { SPIDER_NET_GRXMDSET, SPIDER_NET_RXMODE_VALUE },
+ /* TX mode setting */
+ { SPIDER_NET_GTXMDSET, SPIDER_NET_TXMODE_VALUE },
+ /* IPSEC mode setting */
+ { SPIDER_NET_GIPSECINIT, SPIDER_NET_IPSECINIT_VALUE },
+
+ { SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
+
+ { SPIDER_NET_GMRWOLCTRL, 0 },
+ { SPIDER_NET_GTESTMD, 0 },
+
+ { SPIDER_NET_GMACINTEN, 0 },
+
+ /* flow control stuff */
+ { SPIDER_NET_GMACAPAUSE, SPIDER_NET_MACAPAUSE_VALUE },
+ { SPIDER_NET_GMACTXPAUSE, SPIDER_NET_TXPAUSE_VALUE },
+
+ { SPIDER_NET_GMACBSTLMT, SPIDER_NET_BURSTLMT_VALUE },
+ { 0, 0}
+ };
+
+ i = 0;
+ while (regs[i][0]) {
+ spider_net_write_reg(card, regs[i][0], regs[i][1]);
+ i++;
+ }
+
+ /* clear unicast filter table entries 1 to 14 */
+ for (i = 1; i <= 14; i++) {
+ spider_net_write_reg(card,
+ SPIDER_NET_GMRUAFILnR + i * 8,
+ 0x00080000);
+ spider_net_write_reg(card,
+ SPIDER_NET_GMRUAFILnR + i * 8 + 4,
+ 0x00000000);
+ }
+
+ spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R, 0x08080000);
+
+ spider_net_write_reg(card, SPIDER_NET_ECMODE, SPIDER_NET_ECMODE_VALUE);
+
+ /* set chain tail adress for RX chains and
+ * enable DMA */
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+
+ spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE);
+
+ /* set chain tail adress for TX chain */
+ spider_net_enable_txdmac(card);
+
+ spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
+ SPIDER_NET_LENLMT_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GMACMODE,
+ SPIDER_NET_MACMODE_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
+ SPIDER_NET_OPMODE_VALUE);
+
+ /* set interrupt mask registers */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+ SPIDER_NET_INT0_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+ SPIDER_NET_INT1_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+ SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+int
+spider_net_open(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+ int result;
+
+ result = -ENOMEM;
+ if (spider_net_init_chain(card, &card->tx_chain,
+ card->descr, tx_descriptors))
+ goto alloc_tx_failed;
+ if (spider_net_init_chain(card, &card->rx_chain,
+ card->descr + tx_descriptors, rx_descriptors))
+ goto alloc_rx_failed;
+
+ /* allocate rx skbs */
+ if (spider_net_alloc_rx_skbs(card))
+ goto alloc_skbs_failed;
+
+ spider_net_set_multi(netdev);
+
+ /* further enhancement: setup hw vlan, if needed */
+
+ result = -EBUSY;
+ if (request_irq(netdev->irq, spider_net_interrupt,
+ SA_SHIRQ, netdev->name, netdev))
+ goto register_int_failed;
+
+ spider_net_enable_card(card);
+
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ netif_poll_enable(netdev);
+
+ return 0;
+
+register_int_failed:
+ spider_net_free_rx_chain_contents(card);
+alloc_skbs_failed:
+ spider_net_free_chain(card, &card->rx_chain);
+alloc_rx_failed:
+ spider_net_free_chain(card, &card->tx_chain);
+alloc_tx_failed:
+ return result;
+}
+
+/**
+ * spider_net_setup_phy - setup PHY
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * spider_net_setup_phy is used as part of spider_net_probe. Sets
+ * the PHY to 1000 Mbps
+ **/
+static int
+spider_net_setup_phy(struct spider_net_card *card)
+{
+ struct mii_phy *phy = &card->phy;
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMASEL,
+ SPIDER_NET_DMASEL_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GPCCTRL,
+ SPIDER_NET_PHY_CTRL_VALUE);
+ phy->mii_id = 1;
+ phy->dev = card->netdev;
+ phy->mdio_read = spider_net_read_phy;
+ phy->mdio_write = spider_net_write_phy;
+
+ mii_phy_probe(phy, phy->mii_id);
+
+ if (phy->def->ops->setup_forced)
+ phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
+
+ /* the following two writes could be moved to sungem_phy.c */
+ /* enable fiber mode */
+ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x9020);
+ /* LEDs active in both modes, autosense prio = fiber */
+ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
+
+ /* switch off fibre autoneg */
+ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
+ spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+
+ phy->def->ops->read_link(phy);
+ pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
+ phy->speed, phy->duplex==1 ? "Full" : "Half");
+
+ return 0;
+}
+
+/**
+ * spider_net_download_firmware - loads firmware into the adapter
+ * @card: card structure
+ * @firmware: firmware pointer
+ *
+ * spider_net_download_firmware loads the firmware opened by
+ * spider_net_init_firmware into the adapter.
+ */
+static void
+spider_net_download_firmware(struct spider_net_card *card,
+ const struct firmware *firmware)
+{
+ int sequencer, i;
+ u32 *fw_ptr = (u32 *)firmware->data;
+
+ /* stop sequencers */
+ spider_net_write_reg(card, SPIDER_NET_GSINIT,
+ SPIDER_NET_STOP_SEQ_VALUE);
+
+ for (sequencer = 0; sequencer < 6; sequencer++) {
+ spider_net_write_reg(card,
+ SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
+ for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, *fw_ptr);
+ fw_ptr++;
+ }
+ }
+
+ spider_net_write_reg(card, SPIDER_NET_GSINIT,
+ SPIDER_NET_RUN_SEQ_VALUE);
+}
+
+/**
+ * spider_net_init_firmware - reads in firmware parts
+ * @card: card structure
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_init_firmware opens the sequencer firmware and does some basic
+ * checks. This function opens and releases the firmware structure. A call
+ * to download the firmware is performed before the release.
+ *
+ * Firmware format
+ * ===============
+ * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being
+ * the program for each sequencer. Use the command
+ * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \
+ * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \
+ * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin
+ *
+ * to generate spider_fw.bin, if you have sequencer programs with something
+ * like the following contents for each sequencer:
+ * <ONE LINE COMMENT>
+ * <FIRST 4-BYTES-WORD FOR SEQUENCER>
+ * <SECOND 4-BYTES-WORD FOR SEQUENCER>
+ * ...
+ * <1024th 4-BYTES-WORD FOR SEQUENCER>
+ */
+static int
+spider_net_init_firmware(struct spider_net_card *card)
+{
+ const struct firmware *firmware;
+ int err = -EIO;
+
+ if (request_firmware(&firmware,
+ SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) < 0) {
+ if (netif_msg_probe(card))
+ pr_err("Couldn't read in sequencer data file %s.\n",
+ SPIDER_NET_FIRMWARE_NAME);
+ firmware = NULL;
+ goto out;
+ }
+
+ if (firmware->size != 6 * SPIDER_NET_FIRMWARE_LEN * sizeof(u32)) {
+ if (netif_msg_probe(card))
+ pr_err("Invalid size of sequencer data file %s.\n",
+ SPIDER_NET_FIRMWARE_NAME);
+ goto out;
+ }
+
+ spider_net_download_firmware(card, firmware);
+
+ err = 0;
+out:
+ release_firmware(firmware);
+
+ return err;
+}
+
+/**
+ * spider_net_workaround_rxramfull - work around firmware bug
+ * @card: card structure
+ *
+ * no return value
+ **/
+static void
+spider_net_workaround_rxramfull(struct spider_net_card *card)
+{
+ int i, sequencer = 0;
+
+ /* cancel reset */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+
+ /* empty sequencer data */
+ for (sequencer = 0; sequencer < 6; sequencer++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, 0x0);
+ for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ sequencer * 8, 0x0);
+ }
+ }
+
+ /* set sequencer operation */
+ spider_net_write_reg(card, SPIDER_NET_GSINIT, 0x000000fe);
+
+ /* reset */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+}
+
+/**
+ * spider_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @data: data, is interface device structure
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void
+spider_net_tx_timeout_task(void *data)
+{
+ struct net_device *netdev = data;
+ struct spider_net_card *card = netdev_priv(netdev);
+
+ if (!(netdev->flags & IFF_UP))
+ goto out;
+
+ netif_device_detach(netdev);
+ spider_net_stop(netdev);
+
+ spider_net_workaround_rxramfull(card);
+ spider_net_init_card(card);
+
+ if (spider_net_setup_phy(card))
+ goto out;
+ if (spider_net_init_firmware(card))
+ goto out;
+
+ spider_net_open(netdev);
+ spider_net_kick_tx_dma(card, card->tx_chain.head);
+ netif_device_attach(netdev);
+
+out:
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * spider_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void
+spider_net_tx_timeout(struct net_device *netdev)
+{
+ struct spider_net_card *card;
+
+ card = netdev_priv(netdev);
+ atomic_inc(&card->tx_timeout_task_counter);
+ if (netdev->flags & IFF_UP)
+ schedule_work(&card->tx_timeout_task);
+ else
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * spider_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void
+spider_net_setup_netdev_ops(struct net_device *netdev)
+{
+ netdev->open = &spider_net_open;
+ netdev->stop = &spider_net_stop;
+ netdev->hard_start_xmit = &spider_net_xmit;
+ netdev->get_stats = &spider_net_get_stats;
+ netdev->set_multicast_list = &spider_net_set_multi;
+ netdev->set_mac_address = &spider_net_set_mac;
+ netdev->change_mtu = &spider_net_change_mtu;
+ netdev->do_ioctl = &spider_net_do_ioctl;
+ /* tx watchdog */
+ netdev->tx_timeout = &spider_net_tx_timeout;
+ netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT;
+ /* NAPI */
+ netdev->poll = &spider_net_poll;
+ netdev->weight = SPIDER_NET_NAPI_WEIGHT;
+ /* HW VLAN */
+ netdev->vlan_rx_register = &spider_net_vlan_rx_reg;
+ netdev->vlan_rx_add_vid = &spider_net_vlan_rx_add;
+ netdev->vlan_rx_kill_vid = &spider_net_vlan_rx_kill;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ /* poll controller */
+ netdev->poll_controller = &spider_net_poll_controller;
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+ /* ethtool ops */
+ netdev->ethtool_ops = &spider_net_ethtool_ops;
+}
+
+/**
+ * spider_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * spider_net_setup_netdev initializes the net_device structure
+ **/
+static int
+spider_net_setup_netdev(struct spider_net_card *card)
+{
+ int result;
+ struct net_device *netdev = card->netdev;
+ struct device_node *dn;
+ struct sockaddr addr;
+ u8 *mac;
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &card->pdev->dev);
+
+ pci_set_drvdata(card->pdev, netdev);
+ spin_lock_init(&card->intmask_lock);
+ netdev->irq = card->pdev->irq;
+
+ card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
+
+ spider_net_setup_netdev_ops(netdev);
+
+ netdev->features = 0;
+ /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+ * NETIF_F_HW_VLAN_FILTER */
+
+ netdev->irq = card->pdev->irq;
+
+ dn = pci_device_to_OF_node(card->pdev);
+ if (!dn)
+ return -EIO;
+
+ mac = (u8 *)get_property(dn, "local-mac-address", NULL);
+ if (!mac)
+ return -EIO;
+ memcpy(addr.sa_data, mac, ETH_ALEN);
+
+ result = spider_net_set_mac(netdev, &addr);
+ if ((result) && (netif_msg_probe(card)))
+ pr_err("Failed to set MAC address: %i\n", result);
+
+ result = register_netdev(netdev);
+ if (result) {
+ if (netif_msg_probe(card))
+ pr_err("Couldn't register net_device: %i\n",
+ result);
+ return result;
+ }
+
+ if (netif_msg_probe(card))
+ pr_info("Initialized device %s.\n", netdev->name);
+
+ return 0;
+}
+
+/**
+ * spider_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct spider_net_card *
+spider_net_alloc_card(void)
+{
+ struct net_device *netdev;
+ struct spider_net_card *card;
+ size_t alloc_size;
+
+ alloc_size = sizeof (*card) +
+ sizeof (struct spider_net_descr) * rx_descriptors +
+ sizeof (struct spider_net_descr) * tx_descriptors;
+ netdev = alloc_etherdev(alloc_size);
+ if (!netdev)
+ return NULL;
+
+ card = netdev_priv(netdev);
+ card->netdev = netdev;
+ card->msg_enable = SPIDER_NET_DEFAULT_MSG;
+ INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev);
+ init_waitqueue_head(&card->waitq);
+ atomic_set(&card->tx_timeout_task_counter, 0);
+
+ return card;
+}
+
+/**
+ * spider_net_undo_pci_setup - releases PCI ressources
+ * @card: card structure
+ *
+ * spider_net_undo_pci_setup releases the mapped regions
+ */
+static void
+spider_net_undo_pci_setup(struct spider_net_card *card)
+{
+ iounmap(card->regs);
+ pci_release_regions(card->pdev);
+}
+
+/**
+ * spider_net_setup_pci_dev - sets up the device in terms of PCI operations
+ * @card: card structure
+ * @pdev: PCI device
+ *
+ * Returns the card structure or NULL if any errors occur
+ *
+ * spider_net_setup_pci_dev initializes pdev and together with the
+ * functions called in spider_net_open configures the device so that
+ * data can be transferred over it
+ * The net_device structure is attached to the card structure, if the
+ * function returns without error.
+ **/
+static struct spider_net_card *
+spider_net_setup_pci_dev(struct pci_dev *pdev)
+{
+ struct spider_net_card *card;
+ unsigned long mmio_start, mmio_len;
+
+ if (pci_enable_device(pdev)) {
+ pr_err("Couldn't enable PCI device\n");
+ return NULL;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ pr_err("Couldn't find proper PCI device base address.\n");
+ goto out_disable_dev;
+ }
+
+ if (pci_request_regions(pdev, spider_net_driver_name)) {
+ pr_err("Couldn't obtain PCI resources, aborting.\n");
+ goto out_disable_dev;
+ }
+
+ pci_set_master(pdev);
+
+ card = spider_net_alloc_card();
+ if (!card) {
+ pr_err("Couldn't allocate net_device structure, "
+ "aborting.\n");
+ goto out_release_regions;
+ }
+ card->pdev = pdev;
+
+ /* fetch base address and length of first resource */
+ mmio_start = pci_resource_start(pdev, 0);
+ mmio_len = pci_resource_len(pdev, 0);
+
+ card->netdev->mem_start = mmio_start;
+ card->netdev->mem_end = mmio_start + mmio_len;
+ card->regs = ioremap(mmio_start, mmio_len);
+
+ if (!card->regs) {
+ pr_err("Couldn't obtain PCI resources, aborting.\n");
+ goto out_release_regions;
+ }
+
+ return card;
+
+out_release_regions:
+ pci_release_regions(pdev);
+out_disable_dev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return NULL;
+}
+
+/**
+ * spider_net_probe - initialization of a device
+ * @pdev: PCI device
+ * @ent: entry in the device id list
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_probe initializes pdev and registers a net_device
+ * structure for it. After that, the device can be ifconfig'ed up
+ **/
+static int __devinit
+spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -EIO;
+ struct spider_net_card *card;
+
+ card = spider_net_setup_pci_dev(pdev);
+ if (!card)
+ goto out;
+
+ spider_net_workaround_rxramfull(card);
+ spider_net_init_card(card);
+
+ err = spider_net_setup_phy(card);
+ if (err)
+ goto out_undo_pci;
+
+ err = spider_net_init_firmware(card);
+ if (err)
+ goto out_undo_pci;
+
+ err = spider_net_setup_netdev(card);
+ if (err)
+ goto out_undo_pci;
+
+ return 0;
+
+out_undo_pci:
+ spider_net_undo_pci_setup(card);
+ free_netdev(card->netdev);
+out:
+ return err;
+}
+
+/**
+ * spider_net_remove - removal of a device
+ * @pdev: PCI device
+ *
+ * Returns 0 on success, <0 on failure
+ *
+ * spider_net_remove is called to remove the device and unregisters the
+ * net_device
+ **/
+static void __devexit
+spider_net_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev;
+ struct spider_net_card *card;
+
+ netdev = pci_get_drvdata(pdev);
+ card = netdev_priv(netdev);
+
+ wait_event(card->waitq,
+ atomic_read(&card->tx_timeout_task_counter) == 0);
+
+ unregister_netdev(netdev);
+
+ /* switch off card */
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_STOP_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+ SPIDER_NET_CKRCTRL_RUN_VALUE);
+
+ spider_net_undo_pci_setup(card);
+ free_netdev(netdev);
+}
+
+static struct pci_driver spider_net_driver = {
+ .owner = THIS_MODULE,
+ .name = spider_net_driver_name,
+ .id_table = spider_net_pci_tbl,
+ .probe = spider_net_probe,
+ .remove = __devexit_p(spider_net_remove)
+};
+
+/**
+ * spider_net_init - init function when the driver is loaded
+ *
+ * spider_net_init registers the device driver
+ */
+static int __init spider_net_init(void)
+{
+ if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) {
+ rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN;
+ pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
+ }
+ if (rx_descriptors > SPIDER_NET_RX_DESCRIPTORS_MAX) {
+ rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MAX;
+ pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
+ }
+ if (tx_descriptors < SPIDER_NET_TX_DESCRIPTORS_MIN) {
+ tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_MIN;
+ pr_info("adjusting tx descriptors to %i.\n", tx_descriptors);
+ }
+ if (tx_descriptors > SPIDER_NET_TX_DESCRIPTORS_MAX) {
+ tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_MAX;
+ pr_info("adjusting tx descriptors to %i.\n", tx_descriptors);
+ }
+
+ return pci_register_driver(&spider_net_driver);
+}
+
+/**
+ * spider_net_cleanup - exit function when driver is unloaded
+ *
+ * spider_net_cleanup unregisters the device driver
+ */
+static void __exit spider_net_cleanup(void)
+{
+ pci_unregister_driver(&spider_net_driver);
+}
+
+module_init(spider_net_init);
+module_exit(spider_net_cleanup);
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
new file mode 100644
index 000000000000..22b2f2347351
--- /dev/null
+++ b/drivers/net/spider_net.h
@@ -0,0 +1,469 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.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, 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 _SPIDER_NET_H
+#define _SPIDER_NET_H
+
+#include "sungem_phy.h"
+
+extern int spider_net_stop(struct net_device *netdev);
+extern int spider_net_open(struct net_device *netdev);
+
+extern struct ethtool_ops spider_net_ethtool_ops;
+
+extern char spider_net_driver_name[];
+
+#define SPIDER_NET_MAX_MTU 2308
+#define SPIDER_NET_MIN_MTU 64
+
+#define SPIDER_NET_RXBUF_ALIGN 128
+
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_RX_DESCRIPTORS_MIN 16
+#define SPIDER_NET_RX_DESCRIPTORS_MAX 256
+
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
+#define SPIDER_NET_TX_DESCRIPTORS_MAX 256
+
+#define SPIDER_NET_RX_CSUM_DEFAULT 1
+
+#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
+#define SPIDER_NET_NAPI_WEIGHT 64
+
+#define SPIDER_NET_FIRMWARE_LEN 1024
+#define SPIDER_NET_FIRMWARE_NAME "spider_fw.bin"
+
+/** spider_net SMMIO registers */
+#define SPIDER_NET_GHIINT0STS 0x00000000
+#define SPIDER_NET_GHIINT1STS 0x00000004
+#define SPIDER_NET_GHIINT2STS 0x00000008
+#define SPIDER_NET_GHIINT0MSK 0x00000010
+#define SPIDER_NET_GHIINT1MSK 0x00000014
+#define SPIDER_NET_GHIINT2MSK 0x00000018
+
+#define SPIDER_NET_GRESUMINTNUM 0x00000020
+#define SPIDER_NET_GREINTNUM 0x00000024
+
+#define SPIDER_NET_GFFRMNUM 0x00000028
+#define SPIDER_NET_GFAFRMNUM 0x0000002c
+#define SPIDER_NET_GFBFRMNUM 0x00000030
+#define SPIDER_NET_GFCFRMNUM 0x00000034
+#define SPIDER_NET_GFDFRMNUM 0x00000038
+
+/* clear them (don't use it) */
+#define SPIDER_NET_GFREECNNUM 0x0000003c
+#define SPIDER_NET_GONETIMENUM 0x00000040
+
+#define SPIDER_NET_GTOUTFRMNUM 0x00000044
+
+#define SPIDER_NET_GTXMDSET 0x00000050
+#define SPIDER_NET_GPCCTRL 0x00000054
+#define SPIDER_NET_GRXMDSET 0x00000058
+#define SPIDER_NET_GIPSECINIT 0x0000005c
+#define SPIDER_NET_GFTRESTRT 0x00000060
+#define SPIDER_NET_GRXDMAEN 0x00000064
+#define SPIDER_NET_GMRWOLCTRL 0x00000068
+#define SPIDER_NET_GPCWOPCMD 0x0000006c
+#define SPIDER_NET_GPCROPCMD 0x00000070
+#define SPIDER_NET_GTTFRMCNT 0x00000078
+#define SPIDER_NET_GTESTMD 0x0000007c
+
+#define SPIDER_NET_GSINIT 0x00000080
+#define SPIDER_NET_GSnPRGADR 0x00000084
+#define SPIDER_NET_GSnPRGDAT 0x00000088
+
+#define SPIDER_NET_GMACOPEMD 0x00000100
+#define SPIDER_NET_GMACLENLMT 0x00000108
+#define SPIDER_NET_GMACINTEN 0x00000118
+#define SPIDER_NET_GMACPHYCTRL 0x00000120
+
+#define SPIDER_NET_GMACAPAUSE 0x00000154
+#define SPIDER_NET_GMACTXPAUSE 0x00000164
+
+#define SPIDER_NET_GMACMODE 0x000001b0
+#define SPIDER_NET_GMACBSTLMT 0x000001b4
+
+#define SPIDER_NET_GMACUNIMACU 0x000001c0
+#define SPIDER_NET_GMACUNIMACL 0x000001c8
+
+#define SPIDER_NET_GMRMHFILnR 0x00000400
+#define SPIDER_NET_MULTICAST_HASHES 256
+
+#define SPIDER_NET_GMRUAFILnR 0x00000500
+#define SPIDER_NET_GMRUA0FIL15R 0x00000578
+
+/* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
+ * 0x00000b.. for DMA controller B, etc. */
+#define SPIDER_NET_GDADCHA 0x00000a00
+#define SPIDER_NET_GDADMACCNTR 0x00000a04
+#define SPIDER_NET_GDACTDPA 0x00000a08
+#define SPIDER_NET_GDACTDCNT 0x00000a0c
+#define SPIDER_NET_GDACDBADDR 0x00000a20
+#define SPIDER_NET_GDACDBSIZE 0x00000a24
+#define SPIDER_NET_GDACNEXTDA 0x00000a28
+#define SPIDER_NET_GDACCOMST 0x00000a2c
+#define SPIDER_NET_GDAWBCOMST 0x00000a30
+#define SPIDER_NET_GDAWBRSIZE 0x00000a34
+#define SPIDER_NET_GDAWBVSIZE 0x00000a38
+#define SPIDER_NET_GDAWBTRST 0x00000a3c
+#define SPIDER_NET_GDAWBTRERR 0x00000a40
+
+/* TX DMA controller registers */
+#define SPIDER_NET_GDTDCHA 0x00000e00
+#define SPIDER_NET_GDTDMACCNTR 0x00000e04
+#define SPIDER_NET_GDTCDPA 0x00000e08
+#define SPIDER_NET_GDTDMASEL 0x00000e14
+
+#define SPIDER_NET_ECMODE 0x00000f00
+/* clock and reset control register */
+#define SPIDER_NET_CKRCTRL 0x00000ff0
+
+/** SCONFIG registers */
+#define SPIDER_NET_SCONFIG_IOACTE 0x00002810
+
+/** hardcoded register values */
+#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe3ff
+#define SPIDER_NET_INT1_MASK_VALUE 0xffffffff
+/* no MAC aborts -> auto retransmission */
+#define SPIDER_NET_INT2_MASK_VALUE 0xfffffff1
+
+/* clear counter when interrupt sources are cleared
+#define SPIDER_NET_FRAMENUM_VALUE 0x0001f001 */
+/* we rely on flagged descriptor interrupts */
+#define SPIDER_NET_FRAMENUM_VALUE 0x00000000
+/* set this first, then the FRAMENUM_VALUE */
+#define SPIDER_NET_GFXFRAMES_VALUE 0x00000000
+
+#define SPIDER_NET_STOP_SEQ_VALUE 0x00000000
+#define SPIDER_NET_RUN_SEQ_VALUE 0x0000007e
+
+#define SPIDER_NET_PHY_CTRL_VALUE 0x00040040
+/* #define SPIDER_NET_PHY_CTRL_VALUE 0x01070080*/
+#define SPIDER_NET_RXMODE_VALUE 0x00000011
+/* auto retransmission in case of MAC aborts */
+#define SPIDER_NET_TXMODE_VALUE 0x00010000
+#define SPIDER_NET_RESTART_VALUE 0x00000000
+#define SPIDER_NET_WOL_VALUE 0x00001111
+#if 0
+#define SPIDER_NET_WOL_VALUE 0x00000000
+#endif
+#define SPIDER_NET_IPSECINIT_VALUE 0x00f000f8
+
+/* pause frames: automatic, no upper retransmission count */
+/* outside loopback mode: ETOMOD signal dont matter, not connected */
+#define SPIDER_NET_OPMODE_VALUE 0x00000063
+/*#define SPIDER_NET_OPMODE_VALUE 0x001b0062*/
+#define SPIDER_NET_LENLMT_VALUE 0x00000908
+
+#define SPIDER_NET_MACAPAUSE_VALUE 0x00000800 /* about 1 ms */
+#define SPIDER_NET_TXPAUSE_VALUE 0x00000000
+
+#define SPIDER_NET_MACMODE_VALUE 0x00000001
+#define SPIDER_NET_BURSTLMT_VALUE 0x00000200 /* about 16 us */
+
+/* 1(0) enable r/tx dma
+ * 0000000 fixed to 0
+ *
+ * 000000 fixed to 0
+ * 0(1) en/disable descr writeback on force end
+ * 0(1) force end
+ *
+ * 000000 fixed to 0
+ * 00 burst alignment: 128 bytes
+ *
+ * 00000 fixed to 0
+ * 0 descr writeback size 32 bytes
+ * 0(1) descr chain end interrupt enable
+ * 0(1) descr status writeback enable */
+
+/* to set RX_DMA_EN */
+#define SPIDER_NET_DMA_RX_VALUE 0x80000000
+#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
+/* to set TX_DMA_EN */
+#define SPIDER_NET_DMA_TX_VALUE 0x80000000
+#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
+
+/* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */
+#define SPIDER_NET_UA_DESCR_VALUE 0x00080000
+#define SPIDER_NET_PROMISC_VALUE 0x00080000
+#define SPIDER_NET_NONPROMISC_VALUE 0x00000000
+
+#define SPIDER_NET_DMASEL_VALUE 0x00000001
+
+#define SPIDER_NET_ECMODE_VALUE 0x00000000
+
+#define SPIDER_NET_CKRCTRL_RUN_VALUE 0x1fff010f
+#define SPIDER_NET_CKRCTRL_STOP_VALUE 0x0000010f
+
+#define SPIDER_NET_SBIMSTATE_VALUE 0x00000000
+#define SPIDER_NET_SBTMSTATE_VALUE 0x00000000
+
+/* SPIDER_NET_GHIINT0STS bits, in reverse order so that they can be used
+ * with 1 << SPIDER_NET_... */
+enum spider_net_int0_status {
+ SPIDER_NET_GPHYINT = 0,
+ SPIDER_NET_GMAC2INT,
+ SPIDER_NET_GMAC1INT,
+ SPIDER_NET_GIPSINT,
+ SPIDER_NET_GFIFOINT,
+ SPIDER_NET_GDMACINT,
+ SPIDER_NET_GSYSINT,
+ SPIDER_NET_GPWOPCMPINT,
+ SPIDER_NET_GPROPCMPINT,
+ SPIDER_NET_GPWFFINT,
+ SPIDER_NET_GRMDADRINT,
+ SPIDER_NET_GRMARPINT,
+ SPIDER_NET_GRMMPINT,
+ SPIDER_NET_GDTDEN0INT,
+ SPIDER_NET_GDDDEN0INT,
+ SPIDER_NET_GDCDEN0INT,
+ SPIDER_NET_GDBDEN0INT,
+ SPIDER_NET_GDADEN0INT,
+ SPIDER_NET_GDTFDCINT,
+ SPIDER_NET_GDDFDCINT,
+ SPIDER_NET_GDCFDCINT,
+ SPIDER_NET_GDBFDCINT,
+ SPIDER_NET_GDAFDCINT,
+ SPIDER_NET_GTTEDINT,
+ SPIDER_NET_GDTDCEINT,
+ SPIDER_NET_GRFDNMINT,
+ SPIDER_NET_GRFCNMINT,
+ SPIDER_NET_GRFBNMINT,
+ SPIDER_NET_GRFANMINT,
+ SPIDER_NET_GRFNMINT,
+ SPIDER_NET_G1TMCNTINT,
+ SPIDER_NET_GFREECNTINT
+};
+/* GHIINT1STS bits */
+enum spider_net_int1_status {
+ SPIDER_NET_GTMFLLINT = 0,
+ SPIDER_NET_GRMFLLINT,
+ SPIDER_NET_GTMSHTINT,
+ SPIDER_NET_GDTINVDINT,
+ SPIDER_NET_GRFDFLLINT,
+ SPIDER_NET_GDDDCEINT,
+ SPIDER_NET_GDDINVDINT,
+ SPIDER_NET_GRFCFLLINT,
+ SPIDER_NET_GDCDCEINT,
+ SPIDER_NET_GDCINVDINT,
+ SPIDER_NET_GRFBFLLINT,
+ SPIDER_NET_GDBDCEINT,
+ SPIDER_NET_GDBINVDINT,
+ SPIDER_NET_GRFAFLLINT,
+ SPIDER_NET_GDADCEINT,
+ SPIDER_NET_GDAINVDINT,
+ SPIDER_NET_GDTRSERINT,
+ SPIDER_NET_GDDRSERINT,
+ SPIDER_NET_GDCRSERINT,
+ SPIDER_NET_GDBRSERINT,
+ SPIDER_NET_GDARSERINT,
+ SPIDER_NET_GDSERINT,
+ SPIDER_NET_GDTPTERINT,
+ SPIDER_NET_GDDPTERINT,
+ SPIDER_NET_GDCPTERINT,
+ SPIDER_NET_GDBPTERINT,
+ SPIDER_NET_GDAPTERINT
+};
+/* GHIINT2STS bits */
+enum spider_net_int2_status {
+ SPIDER_NET_GPROPERINT = 0,
+ SPIDER_NET_GMCTCRSNGINT,
+ SPIDER_NET_GMCTLCOLINT,
+ SPIDER_NET_GMCTTMOTINT,
+ SPIDER_NET_GMCRCAERINT,
+ SPIDER_NET_GMCRCALERINT,
+ SPIDER_NET_GMCRALNERINT,
+ SPIDER_NET_GMCROVRINT,
+ SPIDER_NET_GMCRRNTINT,
+ SPIDER_NET_GMCRRXERINT,
+ SPIDER_NET_GTITCSERINT,
+ SPIDER_NET_GTIFMTERINT,
+ SPIDER_NET_GTIPKTRVKINT,
+ SPIDER_NET_GTISPINGINT,
+ SPIDER_NET_GTISADNGINT,
+ SPIDER_NET_GTISPDNGINT,
+ SPIDER_NET_GRIFMTERINT,
+ SPIDER_NET_GRIPKTRVKINT,
+ SPIDER_NET_GRISPINGINT,
+ SPIDER_NET_GRISADNGINT,
+ SPIDER_NET_GRISPDNGINT
+};
+
+#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GTTEDINT) | \
+ (1 << SPIDER_NET_GDTDCEINT) | \
+ (1 << SPIDER_NET_GDTFDCINT) )
+
+/* we rely on flagged descriptor interrupts*/
+#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
+ (1 << SPIDER_NET_GRMFLLINT) )
+
+#define SPIDER_NET_GPREXEC 0x80000000
+#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
+
+/* descriptor bits
+ *
+ * 1010 descriptor ready
+ * 0 descr in middle of chain
+ * 000 fixed to 0
+ *
+ * 0 no interrupt on completion
+ * 000 fixed to 0
+ * 1 no ipsec processing
+ * 1 last descriptor for this frame
+ * 00 no checksum
+ * 10 tcp checksum
+ * 11 udp checksum
+ *
+ * 00 fixed to 0
+ * 0 fixed to 0
+ * 0 no interrupt on response errors
+ * 0 no interrupt on invalid descr
+ * 0 no interrupt on dma process termination
+ * 0 no interrupt on descr chain end
+ * 0 no interrupt on descr complete
+ *
+ * 000 fixed to 0
+ * 0 response error interrupt status
+ * 0 invalid descr status
+ * 0 dma termination status
+ * 0 descr chain end status
+ * 0 descr complete status */
+#define SPIDER_NET_DMAC_CMDSTAT_NOCS 0xa00c0000
+#define SPIDER_NET_DMAC_CMDSTAT_TCPCS 0xa00e0000
+#define SPIDER_NET_DMAC_CMDSTAT_UDPCS 0xa00f0000
+#define SPIDER_NET_DESCR_IND_PROC_SHIFT 28
+#define SPIDER_NET_DESCR_IND_PROC_MASKO 0x0fffffff
+
+/* descr ready, descr is in middle of chain, get interrupt on completion */
+#define SPIDER_NET_DMAC_RX_CARDOWNED 0xa0800000
+
+/* multicast is no problem */
+#define SPIDER_NET_DATA_ERROR_MASK 0xffffbfff
+
+enum spider_net_descr_status {
+ SPIDER_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
+ SPIDER_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
+ SPIDER_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
+ SPIDER_NET_DESCR_FRAME_END = 0x04, /* used in rx */
+ SPIDER_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
+ SPIDER_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
+ SPIDER_NET_DESCR_NOT_IN_USE /* any other value */
+};
+
+struct spider_net_descr {
+ /* as defined by the hardware */
+ dma_addr_t buf_addr;
+ u32 buf_size;
+ dma_addr_t next_descr_addr;
+ u32 dmac_cmd_status;
+ u32 result_size;
+ u32 valid_size; /* all zeroes for tx */
+ u32 data_status;
+ u32 data_error; /* all zeroes for tx */
+
+ /* used in the driver */
+ struct sk_buff *skb;
+ dma_addr_t bus_addr;
+ struct spider_net_descr *next;
+ struct spider_net_descr *prev;
+} __attribute__((aligned(32)));
+
+struct spider_net_descr_chain {
+ /* we walk from tail to head */
+ struct spider_net_descr *head;
+ struct spider_net_descr *tail;
+};
+
+/* descriptor data_status bits */
+#define SPIDER_NET_RXIPCHK 29
+#define SPIDER_NET_TCPUDPIPCHK 28
+#define SPIDER_NET_DATA_STATUS_CHK_MASK (1 << SPIDER_NET_RXIPCHK | \
+ 1 << SPIDER_NET_TCPUDPIPCHK)
+
+#define SPIDER_NET_VLAN_PACKET 21
+
+/* descriptor data_error bits */
+#define SPIDER_NET_RXIPCHKERR 27
+#define SPIDER_NET_RXTCPCHKERR 26
+#define SPIDER_NET_DATA_ERROR_CHK_MASK (1 << SPIDER_NET_RXIPCHKERR | \
+ 1 << SPIDER_NET_RXTCPCHKERR)
+
+/* the cases we don't pass the packet to the stack */
+#define SPIDER_NET_DESTROY_RX_FLAGS 0x70138000
+
+#define SPIDER_NET_DESCR_SIZE 32
+
+/* this will be bigger some time */
+struct spider_net_options {
+ int rx_csum; /* for rx: if 0 ip_summed=NONE,
+ if 1 and hw has verified, ip_summed=UNNECESSARY */
+};
+
+#define SPIDER_NET_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 )
+
+struct spider_net_card {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct mii_phy phy;
+
+ void __iomem *regs;
+
+ struct spider_net_descr_chain tx_chain;
+ struct spider_net_descr_chain rx_chain;
+ spinlock_t chain_lock;
+
+ struct net_device_stats netdev_stats;
+
+ struct spider_net_options options;
+
+ spinlock_t intmask_lock;
+
+ struct work_struct tx_timeout_task;
+ atomic_t tx_timeout_task_counter;
+ wait_queue_head_t waitq;
+
+ /* for ethtool */
+ int msg_enable;
+
+ struct spider_net_descr descr[0];
+};
+
+#define pr_err(fmt,arg...) \
+ printk(KERN_ERR fmt ,##arg)
+
+#endif
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
new file mode 100644
index 000000000000..d42e60ba74ce
--- /dev/null
+++ b/drivers/net/spider_net_ethtool.c
@@ -0,0 +1,126 @@
+/*
+ * Network device driver for Cell Processor-Based Blade
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.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, 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+
+#include "spider_net.h"
+
+static int
+spider_net_ethtool_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+
+ cmd->supported = (SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE);
+ cmd->advertising = (ADVERTISED_1000baseT_Full |
+ ADVERTISED_FIBRE);
+ cmd->port = PORT_FIBRE;
+ cmd->speed = card->phy.speed;
+ cmd->duplex = DUPLEX_FULL;
+
+ return 0;
+}
+
+static void
+spider_net_ethtool_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+
+ /* clear and fill out info */
+ memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+ strncpy(drvinfo->driver, spider_net_driver_name, 32);
+ strncpy(drvinfo->version, "0.1", 32);
+ strcpy(drvinfo->fw_version, "no information");
+ strncpy(drvinfo->bus_info, pci_name(card->pdev), 32);
+}
+
+static void
+spider_net_ethtool_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wolinfo)
+{
+ /* no support for wol */
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
+}
+
+static u32
+spider_net_ethtool_get_msglevel(struct net_device *netdev)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+ return card->msg_enable;
+}
+
+static void
+spider_net_ethtool_set_msglevel(struct net_device *netdev,
+ u32 level)
+{
+ struct spider_net_card *card;
+ card = netdev_priv(netdev);
+ card->msg_enable = level;
+}
+
+static int
+spider_net_ethtool_nway_reset(struct net_device *netdev)
+{
+ if (netif_running(netdev)) {
+ spider_net_stop(netdev);
+ spider_net_open(netdev);
+ }
+ return 0;
+}
+
+static u32
+spider_net_ethtool_get_rx_csum(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev->priv;
+
+ return card->options.rx_csum;
+}
+
+static int
+spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
+{
+ struct spider_net_card *card = netdev->priv;
+
+ card->options.rx_csum = n;
+ return 0;
+}
+
+struct ethtool_ops spider_net_ethtool_ops = {
+ .get_settings = spider_net_ethtool_get_settings,
+ .get_drvinfo = spider_net_ethtool_get_drvinfo,
+ .get_wol = spider_net_ethtool_get_wol,
+ .get_msglevel = spider_net_ethtool_get_msglevel,
+ .set_msglevel = spider_net_ethtool_set_msglevel,
+ .nway_reset = spider_net_ethtool_nway_reset,
+ .get_rx_csum = spider_net_ethtool_get_rx_csum,
+ .set_rx_csum = spider_net_ethtool_set_rx_csum,
+};
+
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 88b89dc95c77..38b2b0a3ce96 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -133,14 +133,18 @@
- finally added firmware (GPL'ed by Adaptec)
- removed compatibility code for 2.2.x
+ LK1.4.2.1 (Ion Badulescu)
+ - fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM
+ - added 32-bit padding to outgoing skb's, removed previous workaround
+
TODO: - fix forced speed/duplexing code (broken a long time ago, when
somebody converted the driver to use the generic MII code)
- fix VLAN support
*/
#define DRV_NAME "starfire"
-#define DRV_VERSION "1.03+LK1.4.2"
-#define DRV_RELDATE "January 19, 2005"
+#define DRV_VERSION "1.03+LK1.4.2.1"
+#define DRV_RELDATE "October 3, 2005"
#include <linux/config.h>
#include <linux/version.h>
@@ -165,6 +169,14 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when
* of length 1. If and when this is fixed, the #define below can be removed.
*/
#define HAS_BROKEN_FIRMWARE
+
+/*
+ * If using the broken firmware, data must be padded to the next 32-bit boundary.
+ */
+#ifdef HAS_BROKEN_FIRMWARE
+#define PADDING_MASK 3
+#endif
+
/*
* Define this if using the driver with the zero-copy patch
*/
@@ -257,9 +269,10 @@ static int full_duplex[MAX_UNITS] = {0, };
* This SUCKS.
* We need a much better method to determine if dma_addr_t is 64-bit.
*/
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM) && (LINUX_VERSION_CODE > 0x20500 || defined(CONFIG_HIGHMEM64G))) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
/* 64-bit dma_addr_t */
#define ADDR_64BITS /* This chip uses 64 bit addresses. */
+#define netdrv_addr_t u64
#define cpu_to_dma(x) cpu_to_le64(x)
#define dma_to_cpu(x) le64_to_cpu(x)
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
@@ -268,6 +281,7 @@ static int full_duplex[MAX_UNITS] = {0, };
#define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
#define RX_DESC_ADDR_SIZE RxDescAddr64bit
#else /* 32-bit dma_addr_t */
+#define netdrv_addr_t u32
#define cpu_to_dma(x) cpu_to_le32(x)
#define dma_to_cpu(x) le32_to_cpu(x)
#define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
@@ -1077,8 +1091,10 @@ static int netdev_open(struct net_device *dev)
rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
- if (np->queue_mem == 0)
+ if (np->queue_mem == NULL) {
+ free_irq(dev->irq, dev);
return -ENOMEM;
+ }
np->tx_done_q = np->queue_mem;
np->tx_done_q_dma = np->queue_mem_dma;
@@ -1333,21 +1349,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
}
#if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
- {
- int has_bad_length = 0;
-
- if (skb_first_frag_len(skb) == 1)
- has_bad_length = 1;
- else {
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
- if (skb_shinfo(skb)->frags[i].size == 1) {
- has_bad_length = 1;
- break;
- }
- }
-
- if (has_bad_length)
- skb_checksum_help(skb, 0);
+ if (skb->ip_summed == CHECKSUM_HW) {
+ skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK);
+ if (skb == NULL)
+ return NETDEV_TX_OK;
}
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
@@ -2127,13 +2132,12 @@ static int __init starfire_init (void)
#endif
#endif
-#ifndef ADDR_64BITS
/* we can do this test only at run-time... sigh */
- if (sizeof(dma_addr_t) == sizeof(u64)) {
- printk("This driver has not been ported to this 64-bit architecture yet\n");
+ if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
+ printk("This driver has dma_addr_t issues, please send email to maintainer\n");
return -ENODEV;
}
-#endif /* not ADDR_64BITS */
+
return pci_module_init (&starfire_driver);
}
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 1f43bbfbc1c7..5c8fcd40ef4d 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -162,7 +162,7 @@ struct lance_private {
#define MEM lp->mem
#define DREG lp->iobase[0]
#define AREG lp->iobase[1]
-#define REGA(a) ( AREG = (a), DREG )
+#define REGA(a) (*( AREG = (a), &DREG ))
/* Definitions for the Lance */
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index f88f5e32b714..cfaf47c63c58 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -214,7 +214,8 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
{
struct bmac_init_block *bb = bp->bmac_block;
struct net_device *dev = bp->dev;
- int i, gfp_flags = GFP_KERNEL;
+ int i;
+ gfp_t gfp_flags = GFP_KERNEL;
if (from_irq || in_interrupt())
gfp_flags = GFP_ATOMIC;
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index 5674003fc38a..b0dbc5187143 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -339,7 +339,7 @@ struct bigmac {
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, gfp_t gfp_flags)
{
struct sk_buff *skb;
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index d500a5771dbc..0ab9c38b4a34 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -80,7 +80,7 @@
I/O access could affect performance in ARM-based system
- Add Linux software VLAN support
- Version LK1.08 (D-Link):
+ Version LK1.08 (Philippe De Muyter phdm@macqel.be):
- Fix bug of custom mac address
(StationAddr register only accept word write)
@@ -91,11 +91,14 @@
Version LK1.09a (ICPlus):
- Add the delay time in reading the contents of EEPROM
+ Version LK1.10 (Philippe De Muyter phdm@macqel.be):
+ - Make 'unblock interface after Tx underrun' work
+
*/
#define DRV_NAME "sundance"
-#define DRV_VERSION "1.01+LK1.09a"
-#define DRV_RELDATE "10-Jul-2003"
+#define DRV_VERSION "1.01+LK1.10"
+#define DRV_RELDATE "28-Oct-2005"
/* The user-configurable values.
@@ -263,8 +266,10 @@ IV. Notes
IVb. References
The Sundance ST201 datasheet, preliminary version.
-http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+The Kendin KS8723 datasheet, preliminary version.
+The ICplus IP100 datasheet, preliminary version.
+http://www.scyld.com/expert/100mbps.html
+http://www.scyld.com/expert/NWay.html
IVc. Errata
@@ -500,6 +505,25 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int netdev_close(struct net_device *dev);
static struct ethtool_ops ethtool_ops;
+static void sundance_reset(struct net_device *dev, unsigned long reset_cmd)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->base + ASICCtrl;
+ int countdown;
+
+ /* ST201 documentation states ASICCtrl is a 32bit register */
+ iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr);
+ /* ST201 documentation states reset can take up to 1 ms */
+ countdown = 10 + 1;
+ while (ioread32 (ioaddr) & (ResetBusy << 16)) {
+ if (--countdown == 0) {
+ printk(KERN_WARNING "%s : reset not completed !!\n", dev->name);
+ break;
+ }
+ udelay(100);
+ }
+}
+
static int __devinit sundance_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -518,6 +542,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
#else
int bar = 1;
#endif
+ int phy, phy_idx = 0;
/* when built into the kernel, we only print version if device is found */
@@ -549,6 +574,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] =
le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
@@ -605,33 +631,31 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
- if (1) {
- int phy, phy_idx = 0;
- np->phys[0] = 1; /* Default setting */
- np->mii_preamble_required++;
- for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
- int mii_status = mdio_read(dev, phy, MII_BMSR);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- np->phys[phy_idx++] = phy;
- np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
- if ((mii_status & 0x0040) == 0)
- np->mii_preamble_required++;
- printk(KERN_INFO "%s: MII PHY found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- dev->name, phy, mii_status, np->mii_if.advertising);
- }
- }
- np->mii_preamble_required--;
-
- if (phy_idx == 0) {
- printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
- dev->name, ioread32(ioaddr + ASICCtrl));
- goto err_out_unregister;
+ np->phys[0] = 1; /* Default setting */
+ np->mii_preamble_required++;
+ for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(dev, phy, MII_BMSR);
+ int phyx = phy & 0x1f;
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ np->phys[phy_idx++] = phyx;
+ np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0)
+ np->mii_preamble_required++;
+ printk(KERN_INFO "%s: MII PHY found at address %d, status "
+ "0x%4.4x advertising %4.4x.\n",
+ dev->name, phyx, mii_status, np->mii_if.advertising);
}
+ }
+ np->mii_preamble_required--;
- np->mii_if.phy_id = np->phys[0];
+ if (phy_idx == 0) {
+ printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
+ dev->name, ioread32(ioaddr + ASICCtrl));
+ goto err_out_unregister;
}
+ np->mii_if.phy_id = np->phys[0];
+
/* Parse override configuration */
np->an_enable = 1;
if (card_idx < MAX_UNITS) {
@@ -692,7 +716,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
/* Reset the chip to erase previous misconfiguration. */
if (netif_msg_hw(np))
printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
- iowrite16(0x007f, ioaddr + ASICCtrl + 2);
+ iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
if (netif_msg_hw(np))
printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
@@ -1190,23 +1214,33 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
("%s: Transmit status is %2.2x.\n",
dev->name, tx_status);
if (tx_status & 0x1e) {
+ if (netif_msg_tx_err(np))
+ printk("%s: Transmit error status %4.4x.\n",
+ dev->name, tx_status);
np->stats.tx_errors++;
if (tx_status & 0x10)
np->stats.tx_fifo_errors++;
if (tx_status & 0x08)
np->stats.collisions++;
+ if (tx_status & 0x04)
+ np->stats.tx_fifo_errors++;
if (tx_status & 0x02)
np->stats.tx_window_errors++;
- /* This reset has not been verified!. */
- if (tx_status & 0x10) { /* Reset the Tx. */
- np->stats.tx_fifo_errors++;
- spin_lock(&np->lock);
- reset_tx(dev);
- spin_unlock(&np->lock);
+ /*
+ ** This reset has been verified on
+ ** DFE-580TX boards ! phdm@macqel.be.
+ */
+ if (tx_status & 0x10) { /* TxUnderrun */
+ unsigned short txthreshold;
+
+ txthreshold = ioread16 (ioaddr + TxStartThresh);
+ /* Restart Tx FIFO and transmitter */
+ sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
+ iowrite16 (txthreshold, ioaddr + TxStartThresh);
+ /* No need to reset the Tx pointer here */
}
- if (tx_status & 0x1e) /* Restart the Tx. */
- iowrite16 (TxEnable,
- ioaddr + MACCtrl1);
+ /* Restart the Tx. */
+ iowrite16 (TxEnable, ioaddr + MACCtrl1);
}
/* Yup, this is a documentation bug. It cost me *hours*. */
iowrite16 (0, ioaddr + TxStatus);
@@ -1619,6 +1653,7 @@ static struct ethtool_ops ethtool_ops = {
.get_link = get_link,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 2608e7a3d214..de399563a9db 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -948,6 +948,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u32 gem_status = readl(gp->regs + GREG_STAT);
if (gem_status == 0) {
+ netif_poll_enable(dev);
spin_unlock_irqrestore(&gp->lock, flags);
return IRQ_NONE;
}
@@ -2816,7 +2817,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
#if (!defined(__sparc__) && !defined(CONFIG_PPC_PMAC))
/* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
{
int this_offset;
@@ -2837,35 +2838,27 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
- break;
+ return 1;
}
+ return 0;
}
static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
{
- u32 rom_reg_orig;
- void __iomem *p;
-
- if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
- if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
- goto use_random;
- }
+ size_t size;
+ void __iomem *p = pci_map_rom(pdev, &size);
- pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
- pci_write_config_dword(pdev, pdev->rom_base_reg,
- rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+ if (p) {
+ int found;
- p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
- if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
- find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
-
- if (p != NULL)
- iounmap(p);
-
- pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
- return;
+ found = readb(p) == 0x55 &&
+ readb(p + 1) == 0xaa &&
+ find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
+ pci_unmap_rom(pdev, p);
+ if (found)
+ return;
+ }
-use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr[0] = 0x08;
dev_addr[1] = 0x00;
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index 7143fd7cf3f8..13006d759ad8 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -1020,7 +1020,7 @@ struct gem {
struct gem_init_block *init_block;
struct sk_buff *rx_skbs[RX_RING_SIZE];
- struct sk_buff *tx_skbs[RX_RING_SIZE];
+ struct sk_buff *tx_skbs[TX_RING_SIZE];
dma_addr_t gblock_dvma;
struct pci_dev *pdev;
@@ -1035,7 +1035,8 @@ struct gem {
#define ALIGNED_RX_SKB_ADDR(addr) \
((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
-static __inline__ struct sk_buff *gem_alloc_skb(int size, int gfp_flags)
+static __inline__ struct sk_buff *gem_alloc_skb(int size,
+ gfp_t gfp_flags)
{
struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index f02fe4119b2c..9f046cae2f71 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2954,7 +2954,7 @@ static int is_quattro_p(struct pci_dev *pdev)
}
/* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
{
int this_offset;
@@ -2977,42 +2977,33 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, uns
for (i = 0; i < 6; i++)
dev_addr[i] = readb(p + i);
- break;
+ return 1;
}
index--;
}
+ return 0;
}
static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
{
- u32 rom_reg_orig;
- void __iomem *p;
- int index;
+ size_t size;
+ void __iomem *p = pci_map_rom(pdev, &size);
- index = 0;
- if (is_quattro_p(pdev))
- index = PCI_SLOT(pdev->devfn);
-
- if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
- if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
- goto use_random;
- }
+ if (p) {
+ int index = 0;
+ int found;
- pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
- pci_write_config_dword(pdev, pdev->rom_base_reg,
- rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+ if (is_quattro_p(pdev))
+ index = PCI_SLOT(pdev->devfn);
- p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
- if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
- find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
-
- if (p != NULL)
- iounmap(p);
-
- pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
- return;
+ found = readb(p) == 0x55 &&
+ readb(p + 1) == 0xaa &&
+ find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
+ pci_unmap_rom(pdev, p);
+ if (found)
+ return;
+ }
-use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr[0] = 0x08;
dev_addr[1] = 0x00;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 201a550f0bcc..1828a6bf8458 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -36,6 +36,8 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/workqueue.h>
+#include <linux/prefetch.h>
+#include <linux/dma-mapping.h>
#include <net/checksum.h>
@@ -66,8 +68,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.34"
-#define DRV_MODULE_RELDATE "July 25, 2005"
+#define DRV_MODULE_VERSION "3.43"
+#define DRV_MODULE_RELDATE "Oct 24, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -121,12 +123,9 @@
TG3_RX_RCB_RING_SIZE(tp))
#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \
TG3_TX_RING_SIZE)
-#define TX_RING_GAP(TP) \
- (TG3_TX_RING_SIZE - (TP)->tx_pending)
#define TX_BUFFS_AVAIL(TP) \
- (((TP)->tx_cons <= (TP)->tx_prod) ? \
- (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod : \
- (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP))
+ ((TP)->tx_pending - \
+ (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1)))
#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
#define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64)
@@ -221,6 +220,10 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
@@ -340,41 +343,92 @@ static struct {
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{
- if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- spin_lock_bh(&tp->indirect_lock);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_bh(&tp->indirect_lock);
- } else {
- writel(val, tp->regs + off);
- if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0)
- readl(tp->regs + off);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+}
+
+static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val)
+{
+ writel(val, tp->regs + off);
+ readl(tp->regs + off);
+}
+
+static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ return val;
+}
+
+static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
+{
+ unsigned long flags;
+
+ if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+ if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
+ TG3_64BIT_REG_LOW, val);
+ return;
+ }
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+
+ /* In indirect mode when disabling interrupts, we also need
+ * to clear the interrupt bit in the GRC local ctrl register.
+ */
+ if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
+ (val == 0x1)) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
+ tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
}
}
+static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
+ pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
+ pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ return val;
+}
+
static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
{
- if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- spin_lock_bh(&tp->indirect_lock);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_bh(&tp->indirect_lock);
- } else {
- void __iomem *dest = tp->regs + off;
- writel(val, dest);
- readl(dest); /* always flush PCI write */
- }
+ tp->write32(tp, off, val);
+ if (!(tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) &&
+ !(tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) &&
+ !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
+ tp->read32(tp, off); /* flush */
}
-static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
+static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
{
- void __iomem *mbox = tp->regs + off;
- writel(val, mbox);
- if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
- readl(mbox);
+ tp->write32_mbox(tp, off, val);
+ if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
+ !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
+ tp->read32_mbox(tp, off);
}
-static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
+static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
{
void __iomem *mbox = tp->regs + off;
writel(val, mbox);
@@ -384,51 +438,72 @@ static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
readl(mbox);
}
-#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tp->regs + (reg))
-#define tw32_rx_mbox(reg, val) _tw32_rx_mbox(tp, reg, val)
-#define tw32_tx_mbox(reg, val) _tw32_tx_mbox(tp, reg, val)
+static void tg3_write32(struct tg3 *tp, u32 off, u32 val)
+{
+ writel(val, tp->regs + off);
+}
-#define tw32(reg,val) tg3_write_indirect_reg32(tp,(reg),(val))
+static u32 tg3_read32(struct tg3 *tp, u32 off)
+{
+ return (readl(tp->regs + off));
+}
+
+#define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val)
+#define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val))
+#define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
+#define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val)
+#define tr32_mailbox(reg) tp->read32_mbox(tp, reg)
+
+#define tw32(reg,val) tp->write32(tp, reg, val)
#define tw32_f(reg,val) _tw32_flush(tp,(reg),(val))
-#define tw16(reg,val) writew(((val) & 0xffff), tp->regs + (reg))
-#define tw8(reg,val) writeb(((val) & 0xff), tp->regs + (reg))
-#define tr32(reg) readl(tp->regs + (reg))
-#define tr16(reg) readw(tp->regs + (reg))
-#define tr8(reg) readb(tp->regs + (reg))
+#define tr32(reg) tp->read32(tp, reg)
static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
{
- spin_lock_bh(&tp->indirect_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_bh(&tp->indirect_lock);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
+}
+
+static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
+{
+ /* If no workaround is needed, write to mem space directly */
+ if (tp->write32 != tg3_write_indirect_reg32)
+ tw32(NIC_SRAM_WIN_BASE + off, val);
+ else
+ tg3_write_mem(tp, off, val);
}
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
{
- spin_lock_bh(&tp->indirect_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->indirect_lock, flags);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_bh(&tp->indirect_lock);
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
static void tg3_disable_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
}
static inline void tg3_cond_int(struct tg3 *tp)
{
- if (tp->hw_status->status & SD_STATUS_UPDATED)
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+ (tp->hw_status->status & SD_STATUS_UPDATED))
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
}
@@ -439,9 +514,8 @@ static void tg3_enable_ints(struct tg3 *tp)
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- (tp->last_tag << 24));
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ (tp->last_tag << 24));
tg3_cond_int(tp);
}
@@ -472,8 +546,6 @@ static inline unsigned int tg3_has_work(struct tg3 *tp)
*/
static void tg3_restart_ints(struct tg3 *tp)
{
- tw32(TG3PCI_MISC_HOST_CTRL,
- (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
tp->last_tag << 24);
mmiowb();
@@ -512,7 +584,7 @@ static void tg3_switch_clocks(struct tg3 *tp)
u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
u32 orig_clock_ctrl;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
return;
orig_clock_ctrl = clock_ctrl;
@@ -1152,7 +1224,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
CLOCK_CTRL_ALTCLK |
CLOCK_CTRL_PWRDOWN_PLL133);
udelay(40);
- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ } else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
/* do nothing */
} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
@@ -2821,9 +2893,13 @@ static void tg3_tx(struct tg3 *tp)
tp->tx_cons = sw_idx;
- if (netif_queue_stopped(tp->dev) &&
- (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
- netif_wake_queue(tp->dev);
+ if (unlikely(netif_queue_stopped(tp->dev))) {
+ spin_lock(&tp->tx_lock);
+ if (netif_queue_stopped(tp->dev) &&
+ (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+ netif_wake_queue(tp->dev);
+ spin_unlock(&tp->tx_lock);
+ }
}
/* Returns size of skb allocated or < 0 on error.
@@ -3139,9 +3215,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
/* run TX completion thread */
if (sblk->idx[0].tx_consumer != tp->tx_cons) {
- spin_lock(&tp->tx_lock);
tg3_tx(tp);
- spin_unlock(&tp->tx_lock);
}
/* run RX thread, within the bounds set by NAPI.
@@ -3161,18 +3235,17 @@ static int tg3_poll(struct net_device *netdev, int *budget)
netdev->quota -= work_done;
}
- if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
tp->last_tag = sblk->status_tag;
- rmb();
- sblk->status &= ~SD_STATUS_UPDATED;
+ rmb();
+ } else
+ sblk->status &= ~SD_STATUS_UPDATED;
/* if no more work, tell net stack and NIC we're done */
done = !tg3_has_work(tp);
if (done) {
- spin_lock(&tp->lock);
netif_rx_complete(netdev);
tg3_restart_ints(tp);
- spin_unlock(&tp->lock);
}
return (done ? 0 : 1);
@@ -3220,8 +3293,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
- struct tg3_hw_status *sblk = tp->hw_status;
+ prefetch(tp->hw_status);
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
/*
* Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
@@ -3230,19 +3304,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
* event coalescing.
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
- tp->last_tag = sblk->status_tag;
- rmb();
- if (tg3_irq_sync(tp))
- goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
+ if (likely(!tg3_irq_sync(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
- /* No work, re-enable interrupts. */
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- tp->last_tag << 24);
- }
-out:
+
return IRQ_RETVAL(1);
}
@@ -3272,15 +3336,15 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (tg3_irq_sync(tp))
goto out;
sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
+ if (likely(tg3_has_work(tp))) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
+ } else {
/* No work, shared interrupt perhaps? re-enable
* interrupts, and flush that PCI write
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000000);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
} else { /* shared interrupt */
handled = 0;
@@ -3301,7 +3365,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
* Reading the PCI State register will confirm whether the
* interrupt is ours and will flush the status block.
*/
- if ((sblk->status & SD_STATUS_UPDATED) ||
+ if ((sblk->status_tag != tp->last_tag) ||
!(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
/*
* writing any value to intr-mbox-0 clears PCI INTA# and
@@ -3312,20 +3376,17 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
- tp->last_tag = sblk->status_tag;
- rmb();
if (tg3_irq_sync(tp))
goto out;
- sblk->status &= ~SD_STATUS_UPDATED;
- if (likely(tg3_has_work(tp)))
- netif_rx_schedule(dev); /* schedule NAPI poll */
- else {
- /* no work, shared interrupt perhaps? re-enable
- * interrupts, and flush that PCI write
+ if (netif_rx_schedule_prep(dev)) {
+ prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+ /* Update last_tag to mark that this status has been
+ * seen. Because interrupt may be shared, we may be
+ * racing with tg3_poll(), so only update last_tag
+ * if tg3_poll() is not scheduled.
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- tp->last_tag << 24);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tp->last_tag = sblk->status_tag;
+ __netif_rx_schedule(dev);
}
} else { /* shared interrupt */
handled = 0;
@@ -3342,7 +3403,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
struct tg3 *tp = netdev_priv(dev);
struct tg3_hw_status *sblk = tp->hw_status;
- if (sblk->status & SD_STATUS_UPDATED) {
+ if ((sblk->status & SD_STATUS_UPDATED) ||
+ !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
return IRQ_RETVAL(1);
@@ -3395,31 +3457,47 @@ static void tg3_tx_timeout(struct net_device *dev)
schedule_work(&tp->reset_task);
}
+/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
+static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+{
+ u32 base = (u32) mapping & 0xffffffff;
+
+ return ((base > 0xffffdcc0) &&
+ (base + len + 8 < base));
+}
+
static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
- u32 guilty_entry, int guilty_len,
- u32 last_plus_one, u32 *start, u32 mss)
+ u32 last_plus_one, u32 *start,
+ u32 base_flags, u32 mss)
{
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
- dma_addr_t new_addr;
+ dma_addr_t new_addr = 0;
u32 entry = *start;
- int i;
+ int i, ret = 0;
if (!new_skb) {
- dev_kfree_skb(skb);
- return -1;
+ ret = -1;
+ } 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);
+ /* 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)) {
+ ret = -1;
+ dev_kfree_skb(new_skb);
+ new_skb = NULL;
+ } else {
+ tg3_set_txd(tp, entry, new_addr, new_skb->len,
+ base_flags, 1 | (mss << 1));
+ *start = NEXT_TX(entry);
+ }
}
- /* 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);
- tg3_set_txd(tp, entry, new_addr, new_skb->len,
- (skb->ip_summed == CHECKSUM_HW) ?
- TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
- *start = NEXT_TX(entry);
-
/* Now clean up the sw ring entries. */
i = 0;
while (entry != last_plus_one) {
@@ -3444,7 +3522,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
dev_kfree_skb(skb);
- return 0;
+ return ret;
}
static void tg3_set_txd(struct tg3 *tp, int entry,
@@ -3470,19 +3548,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
}
-static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
-{
- u32 base = (u32) mapping & 0xffffffff;
-
- return ((base > 0xffffdcc0) &&
- (base + len + 8 < base));
-}
-
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
dma_addr_t mapping;
- unsigned int i;
u32 len, entry, base_flags, mss;
int would_hit_hwbug;
@@ -3577,7 +3646,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
would_hit_hwbug = 0;
if (tg3_4g_overflow_test(mapping, len))
- would_hit_hwbug = entry + 1;
+ would_hit_hwbug = 1;
tg3_set_txd(tp, entry, mapping, len, base_flags,
(skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -3601,12 +3670,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
tp->tx_buffers[entry].skb = NULL;
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
- if (tg3_4g_overflow_test(mapping, len)) {
- /* Only one should match. */
- if (would_hit_hwbug)
- BUG();
- would_hit_hwbug = entry + 1;
- }
+ if (tg3_4g_overflow_test(mapping, len))
+ would_hit_hwbug = 1;
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
tg3_set_txd(tp, entry, mapping, len,
@@ -3622,34 +3687,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (would_hit_hwbug) {
u32 last_plus_one = entry;
u32 start;
- unsigned int len = 0;
-
- would_hit_hwbug -= 1;
- entry = entry - 1 - skb_shinfo(skb)->nr_frags;
- entry &= (TG3_TX_RING_SIZE - 1);
- start = entry;
- i = 0;
- while (entry != last_plus_one) {
- if (i == 0)
- len = skb_headlen(skb);
- else
- len = skb_shinfo(skb)->frags[i-1].size;
- if (entry == would_hit_hwbug)
- break;
-
- i++;
- entry = NEXT_TX(entry);
-
- }
+ start = entry - 1 - skb_shinfo(skb)->nr_frags;
+ start &= (TG3_TX_RING_SIZE - 1);
/* If the workaround fails due to memory/mapping
* failure, silently drop this packet.
*/
- if (tigon3_4gb_hwbug_workaround(tp, skb,
- entry, len,
- last_plus_one,
- &start, mss))
+ if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+ &start, base_flags, mss))
goto out_unlock;
entry = start;
@@ -3659,8 +3705,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
tp->tx_prod = entry;
- if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
+ if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
netif_stop_queue(dev);
+ if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+ netif_wake_queue(tp->dev);
+ }
out_unlock:
mmiowb();
@@ -3677,14 +3726,14 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
dev->mtu = new_mtu;
if (new_mtu > ETH_DATA_LEN) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
ethtool_op_set_tso(dev, 0);
}
else
tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
} else {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE;
}
@@ -3815,7 +3864,7 @@ static void tg3_init_rings(struct tg3 *tp)
memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
tp->rx_pkt_buf_sz = RX_PKT_BUF_SZ;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) &&
+ if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
(tp->dev->mtu > ETH_DATA_LEN))
tp->rx_pkt_buf_sz = RX_JUMBO_PKT_BUF_SZ;
@@ -3870,10 +3919,8 @@ static void tg3_init_rings(struct tg3 *tp)
*/
static void tg3_free_consistent(struct tg3 *tp)
{
- if (tp->rx_std_buffers) {
- kfree(tp->rx_std_buffers);
- tp->rx_std_buffers = NULL;
- }
+ kfree(tp->rx_std_buffers);
+ tp->rx_std_buffers = NULL;
if (tp->rx_std) {
pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
tp->rx_std, tp->rx_std_mapping);
@@ -4216,7 +4263,7 @@ static void tg3_stop_fw(struct tg3 *);
static int tg3_chip_reset(struct tg3 *tp)
{
u32 val;
- u32 flags_save;
+ void (*write_op)(struct tg3 *, u32, u32);
int i;
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
@@ -4228,8 +4275,9 @@ static int tg3_chip_reset(struct tg3 *tp)
* fun things. So, temporarily disable the 5701
* hardware workaround, while we do the reset.
*/
- flags_save = tp->tg3_flags;
- tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG;
+ write_op = tp->write32;
+ if (write_op == tg3_write_flush_reg32)
+ tp->write32 = tg3_write32;
/* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET;
@@ -4248,8 +4296,8 @@ static int tg3_chip_reset(struct tg3 *tp)
val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
tw32(GRC_MISC_CFG, val);
- /* restore 5701 hardware bug workaround flag */
- tp->tg3_flags = flags_save;
+ /* restore 5701 hardware bug workaround write method */
+ tp->write32 = write_op;
/* Unfortunately, we have to delay before the PCI read back.
* Some 575X chips even will not respond to a PCI cfg access
@@ -4311,7 +4359,7 @@ static int tg3_chip_reset(struct tg3 *tp)
val &= ~PCIX_CAPS_RELAXED_ORDERING;
pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
u32 val;
/* Chip reset on 5780 will reset MSI enable bit,
@@ -4635,7 +4683,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
int cpu_scratch_size, struct fw_info *info)
{
int err, i;
- u32 orig_tg3_flags = tp->tg3_flags;
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
@@ -4651,11 +4698,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
else
write_op = tg3_write_indirect_reg32;
- /* Force use of PCI config space for indirect register
- * write calls.
- */
- tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
-
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
@@ -4691,7 +4733,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
err = 0;
out:
- tp->tg3_flags = orig_tg3_flags;
return err;
}
@@ -5367,6 +5408,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
struct tg3 *tp = netdev_priv(dev);
struct sockaddr *addr = p;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_bh(&tp->lock);
@@ -5778,6 +5822,13 @@ static int tg3_reset_hw(struct tg3 *tp)
}
memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+ tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
+ /* reset to prevent losing 1st rx packet intermittently */
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ }
+
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
@@ -5808,8 +5859,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
udelay(100);
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
tp->last_tag = 0;
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
@@ -5965,7 +6015,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780))
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
limit = 8;
else
limit = 16;
@@ -6153,14 +6203,16 @@ static void tg3_timer(unsigned long __opaque)
tp->timer_counter = tp->timer_multiplier;
}
- /* Heartbeat is only sent once every 120 seconds. */
+ /* Heartbeat is only sent once every 2 seconds. */
if (!--tp->asf_counter) {
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
u32 val;
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 3);
+ tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
+ FWCMD_NICDRV_ALIVE2);
+ tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+ /* 5 seconds timeout */
+ tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
val = tr32(GRC_RX_CPU_EVENT);
val |= (1 << 14);
tw32(GRC_RX_CPU_EVENT, val);
@@ -6192,13 +6244,15 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (err)
return err;
+ tp->hw_status->status &= ~SD_STATUS_UPDATED;
tg3_enable_ints(tp);
tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
HOSTCC_MODE_NOW);
for (i = 0; i < 5; i++) {
- int_mbox = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
+ TG3_64BIT_REG_LOW);
if (int_mbox != 0)
break;
msleep(10);
@@ -6369,7 +6423,7 @@ static int tg3_open(struct net_device *dev)
tp->timer_counter = tp->timer_multiplier =
(HZ / tp->timer_offset);
tp->asf_counter = tp->asf_multiplier =
- ((HZ / tp->timer_offset) * 120);
+ ((HZ / tp->timer_offset) * 2);
init_timer(&tp->timer);
tp->timer.expires = jiffies + tp->timer_offset;
@@ -6598,10 +6652,10 @@ static int tg3_open(struct net_device *dev)
/* Mailboxes */
printk("DEBUG: SNDHOST_PROD[%08x%08x] SNDNIC_PROD[%08x%08x]\n",
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0),
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4),
- tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0),
- tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4));
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0),
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4),
+ tr32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0),
+ tr32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4));
/* NIC side send descriptors. */
for (i = 0; i < 6; i++) {
@@ -6848,8 +6902,7 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
get_stat64(&hw_stats->tx_octets);
stats->rx_errors = old_stats->rx_errors +
- get_stat64(&hw_stats->rx_errors) +
- get_stat64(&hw_stats->rx_discards);
+ get_stat64(&hw_stats->rx_errors);
stats->tx_errors = old_stats->tx_errors +
get_stat64(&hw_stats->tx_errors) +
get_stat64(&hw_stats->tx_mac_errors) +
@@ -6877,6 +6930,9 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
stats->rx_crc_errors = old_stats->rx_crc_errors +
calc_crc_errors(tp);
+ stats->rx_missed_errors = old_stats->rx_missed_errors +
+ get_stat64(&hw_stats->rx_discards);
+
return stats;
}
@@ -7195,7 +7251,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->supported |= (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
- if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
+ if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
cmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
@@ -7222,7 +7278,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct tg3 *tp = netdev_priv(dev);
- if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
/* These are the only valid advertisement bits allowed. */
if (cmd->autoneg == AUTONEG_ENABLE &&
(cmd->advertising & ~(ADVERTISED_1000baseT_Half |
@@ -7230,7 +7286,17 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
ADVERTISED_Autoneg |
ADVERTISED_FIBRE)))
return -EINVAL;
- }
+ /* Fiber can only do SPEED_1000. */
+ else if ((cmd->autoneg != AUTONEG_ENABLE) &&
+ (cmd->speed != SPEED_1000))
+ return -EINVAL;
+ /* Copper cannot force SPEED_1000. */
+ } else if ((cmd->autoneg != AUTONEG_ENABLE) &&
+ (cmd->speed == SPEED_1000))
+ return -EINVAL;
+ else if ((cmd->speed == SPEED_1000) &&
+ (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY))
+ return -EINVAL;
tg3_full_lock(tp, 0);
@@ -7329,12 +7395,17 @@ static int tg3_nway_reset(struct net_device *dev)
if (!netif_running(dev))
return -EAGAIN;
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ return -EINVAL;
+
spin_lock_bh(&tp->lock);
r = -EINVAL;
tg3_readphy(tp, MII_BMCR, &bmcr);
if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
- (bmcr & BMCR_ANENABLE)) {
- tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
+ ((bmcr & BMCR_ANENABLE) ||
+ (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
+ tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
+ BMCR_ANENABLE);
r = 0;
}
spin_unlock_bh(&tp->lock);
@@ -7506,6 +7577,38 @@ static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
}
}
+static int tg3_phys_id(struct net_device *dev, u32 data)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ int i;
+
+ if (!netif_running(tp->dev))
+ return -EAGAIN;
+
+ if (data == 0)
+ data = 2;
+
+ for (i = 0; i < (data * 2); i++) {
+ if ((i % 2) == 0)
+ tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+ LED_CTRL_1000MBPS_ON |
+ LED_CTRL_100MBPS_ON |
+ LED_CTRL_10MBPS_ON |
+ LED_CTRL_TRAFFIC_OVERRIDE |
+ LED_CTRL_TRAFFIC_BLINK |
+ LED_CTRL_TRAFFIC_LED);
+
+ else
+ tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+ LED_CTRL_TRAFFIC_OVERRIDE);
+
+ if (msleep_interruptible(500))
+ break;
+ }
+ tw32(MAC_LED_CTRL, tp->led_ctrl);
+ return 0;
+}
+
static void tg3_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
@@ -7565,7 +7668,7 @@ static int tg3_test_link(struct tg3 *tp)
if (!netif_running(tp->dev))
return -ENODEV;
- if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
max = TG3_SERDES_TIMEOUT_SEC;
else
max = TG3_COPPER_TIMEOUT_SEC;
@@ -7850,9 +7953,12 @@ static int tg3_test_memory(struct tg3 *tp)
return err;
}
-static int tg3_test_loopback(struct tg3 *tp)
+#define TG3_MAC_LOOPBACK 0
+#define TG3_PHY_LOOPBACK 1
+
+static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
{
- u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
+ u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
u32 desc_idx;
struct sk_buff *skb, *rx_skb;
u8 *tx_data;
@@ -7860,19 +7966,38 @@ static int tg3_test_loopback(struct tg3 *tp)
int num_pkts, tx_len, rx_len, i, err;
struct tg3_rx_buffer_desc *desc;
- if (!netif_running(tp->dev))
- return -ENODEV;
-
- err = -EIO;
-
- tg3_abort_hw(tp, 1);
+ if (loopback_mode == TG3_MAC_LOOPBACK) {
+ /* HW errata - mac loopback fails in some cases on 5780.
+ * Normal traffic and PHY loopback are not affected by
+ * errata.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ return 0;
- tg3_reset_hw(tp);
+ mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+ MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
+ MAC_MODE_PORT_MODE_GMII;
+ tw32(MAC_MODE, mac_mode);
+ } else if (loopback_mode == TG3_PHY_LOOPBACK) {
+ tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+ BMCR_SPEED1000);
+ udelay(40);
+ /* reset to prevent losing 1st rx packet intermittently */
+ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ }
+ mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+ MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ tw32(MAC_MODE, mac_mode);
+ }
+ else
+ return -EINVAL;
- mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
- MAC_MODE_PORT_MODE_GMII;
- tw32(MAC_MODE, mac_mode);
+ err = -EIO;
tx_len = 1514;
skb = dev_alloc_skb(tx_len);
@@ -7894,16 +8019,16 @@ static int tg3_test_loopback(struct tg3 *tp)
rx_start_idx = tp->hw_status->idx[0].rx_producer;
- send_idx = 0;
num_pkts = 0;
- tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
+ tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
- send_idx++;
+ tp->tx_prod++;
num_pkts++;
- tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
- tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+ tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW,
+ tp->tx_prod);
+ tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
udelay(10);
@@ -7915,7 +8040,7 @@ static int tg3_test_loopback(struct tg3 *tp)
tx_idx = tp->hw_status->idx[0].tx_consumer;
rx_idx = tp->hw_status->idx[0].rx_producer;
- if ((tx_idx == send_idx) &&
+ if ((tx_idx == tp->tx_prod) &&
(rx_idx == (rx_start_idx + num_pkts)))
break;
}
@@ -7923,7 +8048,7 @@ static int tg3_test_loopback(struct tg3 *tp)
pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
- if (tx_idx != send_idx)
+ if (tx_idx != tp->tx_prod)
goto out;
if (rx_idx != rx_start_idx + num_pkts)
@@ -7959,6 +8084,30 @@ out:
return err;
}
+#define TG3_MAC_LOOPBACK_FAILED 1
+#define TG3_PHY_LOOPBACK_FAILED 2
+#define TG3_LOOPBACK_FAILED (TG3_MAC_LOOPBACK_FAILED | \
+ TG3_PHY_LOOPBACK_FAILED)
+
+static int tg3_test_loopback(struct tg3 *tp)
+{
+ int err = 0;
+
+ if (!netif_running(tp->dev))
+ return TG3_LOOPBACK_FAILED;
+
+ tg3_reset_hw(tp);
+
+ if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
+ err |= TG3_MAC_LOOPBACK_FAILED;
+ if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
+ err |= TG3_PHY_LOOPBACK_FAILED;
+ }
+
+ return err;
+}
+
static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
u64 *data)
{
@@ -7999,10 +8148,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
etest->flags |= ETH_TEST_FL_FAILED;
data[3] = 1;
}
- if (tg3_test_loopback(tp) != 0) {
+ if ((data[4] = tg3_test_loopback(tp)) != 0)
etest->flags |= ETH_TEST_FL_FAILED;
- data[4] = 1;
- }
tg3_full_unlock(tp);
@@ -8190,10 +8337,12 @@ static struct ethtool_ops tg3_ethtool_ops = {
.self_test_count = tg3_get_test_count,
.self_test = tg3_self_test,
.get_strings = tg3_get_strings,
+ .phys_id = tg3_phys_id,
.get_stats_count = tg3_get_stats_count,
.get_ethtool_stats = tg3_get_ethtool_stats,
.get_coalesce = tg3_get_coalesce,
.set_coalesce = tg3_set_coalesce,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -8254,7 +8403,8 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
tw32(NVRAM_CFG1, nvcfg1);
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -8668,8 +8818,9 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
if (i == (len - 4))
nvram_cmd |= NVRAM_CMD_LAST;
- if ((tp->nvram_jedecnum == JEDEC_ST) &&
- (nvram_cmd & NVRAM_CMD_FIRST)) {
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+ (tp->nvram_jedecnum == JEDEC_ST) &&
+ (nvram_cmd & NVRAM_CMD_FIRST)) {
if ((ret = tg3_nvram_exec_cmd(tp,
NVRAM_CMD_WREN | NVRAM_CMD_GO |
@@ -8853,7 +9004,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->phy_id = eeprom_phy_id;
if (eeprom_phy_serdes) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
else
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
@@ -8970,6 +9121,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
tp->phy_id = hw_phy_id;
if (hw_phy_id_masked == PHY_ID_BCM8002)
tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+ else
+ tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES;
} else {
if (tp->phy_id != PHY_ID_INVALID) {
/* Do nothing, phy ID already set up in
@@ -9153,16 +9306,10 @@ static int __devinit tg3_is_sun_570X(struct tg3 *tp)
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AA_8) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AB_8) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_11) },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_6) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8385_0) },
{ },
};
u32 misc_ctrl_reg;
@@ -9177,15 +9324,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
#endif
- /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
- * reordering to the mailbox registers done by the host
- * controller can cause major troubles. We read back from
- * every mailbox register write to force the writes to be
- * posted to the chip in order.
- */
- if (pci_dev_present(write_reorder_chipsets))
- tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
-
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
* The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
@@ -9215,9 +9353,75 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+ /* If we have 5702/03 A1 or A2 on certain ICH chipsets,
+ * we need to disable memory and use config. cycles
+ * only to access all registers. The 5702/03 chips
+ * can mistakenly decode the special cycles from the
+ * ICH chipsets as memory write cycles, causing corruption
+ * of register and memory space. Only certain ICH bridges
+ * will drive special cycles with non-zero data during the
+ * address phase which can fall within the 5703's address
+ * range. This is not an ICH bug as the PCI spec allows
+ * non-zero address during special cycles. However, only
+ * these ICH bridges are known to drive non-zero addresses
+ * during special cycles.
+ *
+ * Since special cycles do not cross PCI bridges, we only
+ * enable this workaround if the 5703 is on the secondary
+ * bus of these ICH bridges.
+ */
+ if ((tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) ||
+ (tp->pci_chip_rev_id == CHIPREV_ID_5703_A2)) {
+ static struct tg3_dev_id {
+ u32 vendor;
+ u32 device;
+ u32 rev;
+ } ich_chipsets[] = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_8,
+ PCI_ANY_ID },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_8,
+ PCI_ANY_ID },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_11,
+ 0xa },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_6,
+ PCI_ANY_ID },
+ { },
+ };
+ struct tg3_dev_id *pci_id = &ich_chipsets[0];
+ struct pci_dev *bridge = NULL;
+
+ while (pci_id->vendor != 0) {
+ bridge = pci_get_device(pci_id->vendor, pci_id->device,
+ bridge);
+ if (!bridge) {
+ pci_id++;
+ continue;
+ }
+ if (pci_id->rev != PCI_ANY_ID) {
+ u8 rev;
+
+ pci_read_config_byte(bridge, PCI_REVISION_ID,
+ &rev);
+ if (rev > pci_id->rev)
+ continue;
+ }
+ if (bridge->subordinate &&
+ (bridge->subordinate->number ==
+ tp->pdev->bus->number)) {
+
+ tp->tg3_flags2 |= TG3_FLG2_ICH_WORKAROUND;
+ pci_dev_put(bridge);
+ break;
+ }
+ }
+ }
+
/* Find msi capability. */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
+ }
/* Initialize misc host control in PCI block. */
tp->misc_host_ctrl |= (misc_ctrl_reg &
@@ -9235,7 +9439,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
@@ -9253,6 +9457,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+ /* If we have an AMD 762 or VIA K8T800 chipset, write
+ * reordering to the mailbox registers done by the host
+ * controller can cause major troubles. We read back from
+ * every mailbox register write to force the writes to be
+ * posted to the chip in order.
+ */
+ if (pci_dev_present(write_reorder_chipsets) &&
+ !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+ tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
tp->pci_lat_timer < 64) {
tp->pci_lat_timer = 64;
@@ -9302,6 +9516,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
}
+ /* 5700 BX chips need to have their TX producer index mailboxes
+ * written twice to workaround a bug.
+ */
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
+ tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
+
/* Back to back register writes can cause problems on this chip,
* the workaround is to read back all reg writes except those to
* mailbox regs. See tg3_write_indirect_reg32().
@@ -9325,6 +9545,43 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
}
+ /* Default fast path register access methods */
+ tp->read32 = tg3_read32;
+ tp->write32 = tg3_write32;
+ tp->read32_mbox = tg3_read32;
+ tp->write32_mbox = tg3_write32;
+ tp->write32_tx_mbox = tg3_write32;
+ tp->write32_rx_mbox = tg3_write32;
+
+ /* Various workaround register access methods */
+ if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
+ tp->write32 = tg3_write_indirect_reg32;
+ else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+ tp->write32 = tg3_write_flush_reg32;
+
+ if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
+ (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
+ tp->write32_tx_mbox = tg3_write32_tx_mbox;
+ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+ tp->write32_rx_mbox = tg3_write_flush_reg32;
+ }
+
+ if (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND) {
+ tp->read32 = tg3_read_indirect_reg32;
+ tp->write32 = tg3_write_indirect_reg32;
+ tp->read32_mbox = tg3_read_indirect_mbox;
+ tp->write32_mbox = tg3_write_indirect_mbox;
+ tp->write32_tx_mbox = tg3_write_indirect_mbox;
+ tp->write32_rx_mbox = tg3_write_indirect_mbox;
+
+ iounmap(tp->regs);
+ tp->regs = NULL;
+
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_MEMORY;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ }
+
/* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
* determined before calling tg3_set_power_state() so that
@@ -9377,7 +9634,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* ether_setup() via the alloc_etherdev() call
*/
if (tp->dev->mtu > ETH_DATA_LEN &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780)
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
/* Determine WakeOnLan speed to use. */
@@ -9539,14 +9796,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
- /* 5700 BX chips need to have their TX producer index mailboxes
- * written twice to workaround a bug.
- */
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
- tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
- else
- tp->tg3_flags &= ~TG3_FLAG_TXD_MBOX_HWBUG;
-
/* It seems all chips can get confused if TX buffers
* straddle the 4GB address boundary in some cases.
*/
@@ -9578,6 +9827,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
if (prom_getproplen(node, "local-mac-address") == 6) {
prom_getproperty(node, "local-mac-address",
dev->dev_addr, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, 6);
return 0;
}
}
@@ -9589,6 +9839,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
struct net_device *dev = tp->dev;
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
+ memcpy(dev->perm_addr, idprom->id_ethaddr, 6);
return 0;
}
#endif
@@ -9606,7 +9857,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
mac_offset = 0x7c;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
!(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
mac_offset = 0xcc;
if (tg3_nvram_lock(tp))
@@ -9658,6 +9909,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
#endif
return -EINVAL;
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
return 0;
}
@@ -9923,6 +10175,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
/* 5780 always in PCIX mode */
tp->dma_rwctrl |= 0x00144000;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+ /* 5714 always in PCIX mode */
+ tp->dma_rwctrl |= 0x00148000;
} else {
tp->dma_rwctrl |= 0x001b000f;
}
@@ -10122,6 +10377,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
case PHY_ID_BCM5705: return "5705";
case PHY_ID_BCM5750: return "5750";
case PHY_ID_BCM5752: return "5752";
+ case PHY_ID_BCM5714: return "5714";
case PHY_ID_BCM5780: return "5780";
case PHY_ID_BCM8002: return "8002/serdes";
case 0: return "serdes";
@@ -10129,6 +10385,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
};
}
+static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+{
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ strcpy(str, "PCI Express");
+ return str;
+ } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
+ u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
+
+ strcpy(str, "PCIX:");
+
+ if ((clock_ctrl == 7) ||
+ ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) ==
+ GRC_MISC_CFG_BOARD_ID_5704CIOBE))
+ strcat(str, "133MHz");
+ else if (clock_ctrl == 0)
+ strcat(str, "33MHz");
+ else if (clock_ctrl == 2)
+ strcat(str, "50MHz");
+ else if (clock_ctrl == 4)
+ strcat(str, "66MHz");
+ else if (clock_ctrl == 6)
+ strcat(str, "100MHz");
+ else if (clock_ctrl == 7)
+ strcat(str, "133MHz");
+ } else {
+ strcpy(str, "PCI:");
+ if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED)
+ strcat(str, "66MHz");
+ else
+ strcat(str, "33MHz");
+ }
+ if (tp->tg3_flags & TG3_FLAG_PCI_32BIT)
+ strcat(str, ":32-bit");
+ else
+ strcat(str, ":64-bit");
+ return str;
+}
+
static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
{
struct pci_dev *peer;
@@ -10191,6 +10485,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
struct net_device *dev;
struct tg3 *tp;
int i, err, pci_using_dac, pm_cap;
+ char str[40];
if (tg3_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -10228,17 +10523,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
}
/* Configure DMA attributes. */
- err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (!err) {
pci_using_dac = 1;
- err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (err < 0) {
printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
"for consistent allocations\n");
goto err_out_free_res;
}
} else {
- err = pci_set_dma_mask(pdev, 0xffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
@@ -10421,6 +10716,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_init_coal(tp);
+ /* Now that we have fully setup the chip, save away a snapshot
+ * of the PCI config space. We need to restore this after
+ * GRC_MISC_CFG core clock resets and some resume events.
+ */
+ pci_save_state(tp->pdev);
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
@@ -10430,22 +10731,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
- /* Now that we have fully setup the chip, save away a snapshot
- * of the PCI config space. We need to restore this after
- * GRC_MISC_CFG core clock resets and some resume events.
- */
- pci_save_state(tp->pdev);
-
- printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
+ printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
dev->name,
tp->board_part_number,
tp->pci_chip_rev_id,
tg3_phy_string(tp),
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
- ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
- ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
- ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
+ tg3_bus_string(tp, str),
(tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
for (i = 0; i < 6; i++)
@@ -10469,7 +10760,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
return 0;
err_out_iounmap:
- iounmap(tp->regs);
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = NULL;
+ }
err_out_free_dev:
free_netdev(dev);
@@ -10491,7 +10785,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
struct tg3 *tp = netdev_priv(dev);
unregister_netdev(dev);
- iounmap(tp->regs);
+ if (tp->regs) {
+ iounmap(tp->regs);
+ tp->regs = NULL;
+ }
free_netdev(dev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5c4433c147fa..fb7e2a5f4a08 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -137,6 +137,7 @@
#define ASIC_REV_5750 0x04
#define ASIC_REV_5752 0x06
#define ASIC_REV_5780 0x08
+#define ASIC_REV_5714 0x09
#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
#define CHIPREV_5700_AX 0x70
#define CHIPREV_5700_BX 0x71
@@ -531,6 +532,8 @@
#define MAC_SERDES_CFG_EDGE_SELECT 0x00001000
#define MAC_SERDES_STAT 0x00000594
/* 0x598 --> 0x5b0 unused */
+#define SERDES_RX_CTRL 0x000005b0 /* 5780/5714 only */
+#define SERDES_RX_SIG_DETECT 0x00000400
#define SG_DIG_CTRL 0x000005b0
#define SG_DIG_USING_HW_AUTONEG 0x80000000
#define SG_DIG_SOFT_RESET 0x40000000
@@ -1329,6 +1332,8 @@
#define GRC_LCLCTRL_CLEARINT 0x00000002
#define GRC_LCLCTRL_SETINT 0x00000004
#define GRC_LCLCTRL_INT_ON_ATTN 0x00000008
+#define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */
+#define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */
#define GRC_LCLCTRL_GPIO_INPUT3 0x00000020
#define GRC_LCLCTRL_GPIO_OE3 0x00000040
#define GRC_LCLCTRL_GPIO_OUTPUT3 0x00000080
@@ -1507,6 +1512,7 @@
#define FWCMD_NICDRV_IPV6ADDR_CHG 0x00000004
#define FWCMD_NICDRV_FIX_DMAR 0x00000005
#define FWCMD_NICDRV_FIX_DMAW 0x00000006
+#define FWCMD_NICDRV_ALIVE2 0x0000000d
#define NIC_SRAM_FW_CMD_LEN_MBOX 0x00000b7c
#define NIC_SRAM_FW_CMD_DATA_MBOX 0x00000b80
#define NIC_SRAM_FW_ASF_STATUS_MBOX 0x00000c00
@@ -2049,6 +2055,11 @@ struct tg3 {
spinlock_t lock;
spinlock_t indirect_lock;
+ u32 (*read32) (struct tg3 *, u32);
+ void (*write32) (struct tg3 *, u32, u32);
+ u32 (*read32_mbox) (struct tg3 *, u32);
+ void (*write32_mbox) (struct tg3 *, u32,
+ u32);
void __iomem *regs;
struct net_device *dev;
struct pci_dev *pdev;
@@ -2060,6 +2071,8 @@ struct tg3 {
u32 msg_enable;
/* begin "tx thread" cacheline section */
+ void (*write32_tx_mbox) (struct tg3 *, u32,
+ u32);
u32 tx_prod;
u32 tx_cons;
u32 tx_pending;
@@ -2071,6 +2084,8 @@ struct tg3 {
dma_addr_t tx_desc_mapping;
/* begin "rx thread" cacheline section */
+ void (*write32_rx_mbox) (struct tg3 *, u32,
+ u32);
u32 rx_rcb_ptr;
u32 rx_std_ptr;
u32 rx_jumbo_ptr;
@@ -2165,6 +2180,8 @@ struct tg3 {
#define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \
TG3_FLG2_MII_SERDES)
#define TG3_FLG2_PARALLEL_DETECT 0x01000000
+#define TG3_FLG2_ICH_WORKAROUND 0x02000000
+#define TG3_FLG2_5780_CLASS 0x04000000
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
@@ -2212,6 +2229,7 @@ struct tg3 {
#define PHY_ID_BCM5705 0x600081a0
#define PHY_ID_BCM5750 0x60008180
#define PHY_ID_BCM5752 0x60008100
+#define PHY_ID_BCM5714 0x60008340
#define PHY_ID_BCM5780 0x60008350
#define PHY_ID_BCM8002 0x60010140
#define PHY_ID_INVALID 0xffffffff
@@ -2236,7 +2254,8 @@ struct tg3 {
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
- (X) == PHY_ID_BCM8002)
+ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
+ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002)
struct tg3_hw_stats *hw_stats;
dma_addr_t stats_mapping;
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index 23d0fa4bbceb..e4cfc80b283b 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -84,7 +84,7 @@ config 3C359
config TMS380TR
tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
- depends on TR && (PCI || ISA)
+ depends on TR && (PCI || ISA && ISA_DMA_API || MCA)
select FW_LOADER
---help---
This driver provides generic support for token ring adapters
@@ -158,7 +158,7 @@ config ABYSS
config MADGEMC
tristate "Madge Smart 16/4 Ringnode MicroChannel"
- depends on TR && TMS380TR && MCA_LEGACY
+ depends on TR && TMS380TR && MCA
help
This tms380 module supports the Madge Smart 16/4 MC16 and MC32
MicroChannel adapters.
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 87103c400999..9345e68c451e 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -139,7 +139,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
*/
dev->base_addr += 0x10;
- ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
printk("%s: unable to get memory for dev->priv.\n",
dev->name);
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index e7b001017b9a..9f491563944e 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct net_device *dev)
if (dev->base_addr) {
outb(0,dev->base_addr+ADAPTRESET);
- schedule_timeout(TR_RST_TIME); /* wait 50ms */
+ schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
outb(0,dev->base_addr+ADAPTRESETREL);
}
@@ -531,7 +531,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
if (!time_after(jiffies, timeout)) continue;
DPRINTK( "Hardware timeout during initialization.\n");
iounmap(t_mmio);
- kfree(ti);
return -ENODEV;
}
ti->sram_phys =
@@ -645,7 +644,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
DPRINTK("Unknown shared ram paging info %01X\n",
ti->shared_ram_paging);
iounmap(t_mmio);
- kfree(ti);
return -ENODEV;
break;
} /*end switch shared_ram_paging */
@@ -675,7 +673,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
"driver limit (%05x), adapter not started.\n",
chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE);
iounmap(t_mmio);
- kfree(ti);
return -ENODEV;
} else { /* seems cool, record what we have figured out */
ti->sram_base = new_base >> 12;
@@ -690,7 +687,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",
irq);
iounmap(t_mmio);
- kfree(ti);
return -ENODEV;
}
/*?? Now, allocate some of the PIO PORTs for this driver.. */
@@ -699,7 +695,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
DPRINTK("Could not grab PIO range. Halting driver.\n");
free_irq(dev->irq, dev);
iounmap(t_mmio);
- kfree(ti);
return -EBUSY;
}
@@ -859,8 +854,7 @@ static int tok_init_card(struct net_device *dev)
writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
outb(0, PIOaddr + ADAPTRESET);
- current->state=TASK_UNINTERRUPTIBLE;
- schedule_timeout(TR_RST_TIME); /* wait 50ms */
+ schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
outb(0, PIOaddr + ADAPTRESETREL);
#ifdef ENABLE_PAGING
@@ -908,8 +902,8 @@ static int tok_open(struct net_device *dev)
DPRINTK("Adapter is up and running\n");
return 0;
}
- current->state=TASK_INTERRUPTIBLE;
- i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
+ i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
+ /* wait 30 seconds */
if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
}
outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 659cbdbef7f3..3a25d191ea4a 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -20,7 +20,7 @@
static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
#include <linux/module.h>
-#include <linux/mca-legacy.h>
+#include <linux/mca.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -38,9 +38,7 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
#define MADGEMC_IO_EXTENT 32
#define MADGEMC_SIF_OFFSET 0x08
-struct madgemc_card {
- struct net_device *dev;
-
+struct card_info {
/*
* These are read from the BIA ROM.
*/
@@ -57,16 +55,12 @@ struct madgemc_card {
unsigned int arblevel:4;
unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */
unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */
-
- struct madgemc_card *next;
};
-static struct madgemc_card *madgemc_card_list;
-
static int madgemc_open(struct net_device *dev);
static int madgemc_close(struct net_device *dev);
static int madgemc_chipset_init(struct net_device *dev);
-static void madgemc_read_rom(struct madgemc_card *card);
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card);
static unsigned short madgemc_setnselout_pins(struct net_device *dev);
static void madgemc_setcabletype(struct net_device *dev, int type);
@@ -151,261 +145,237 @@ static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsign
-static int __init madgemc_probe(void)
+static int __devinit madgemc_probe(struct device *device)
{
static int versionprinted;
struct net_device *dev;
struct net_local *tp;
- struct madgemc_card *card;
- int i,slot = 0;
- __u8 posreg[4];
-
- if (!MCA_bus)
- return -1;
-
- while (slot != MCA_NOTFOUND) {
- /*
- * Currently we only support the MC16/32 (MCA ID 002d)
- */
- slot = mca_find_unused_adapter(0x002d, slot);
- if (slot == MCA_NOTFOUND)
- break;
-
- /*
- * If we get here, we have an adapter.
- */
- if (versionprinted++ == 0)
- printk("%s", version);
-
- dev = alloc_trdev(sizeof(struct net_local));
- if (dev == NULL) {
- printk("madgemc: unable to allocate dev space\n");
- if (madgemc_card_list)
- return 0;
- return -1;
- }
+ struct card_info *card;
+ struct mca_device *mdev = to_mca_device(device);
+ int ret = 0, i = 0;
+
+ if (versionprinted++ == 0)
+ printk("%s", version);
+
+ if(mca_device_claimed(mdev))
+ return -EBUSY;
+ mca_device_set_claim(mdev, 1);
+
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev) {
+ printk("madgemc: unable to allocate dev space\n");
+ mca_device_set_claim(mdev, 0);
+ ret = -ENOMEM;
+ goto getout;
+ }
- SET_MODULE_OWNER(dev);
- dev->dma = 0;
+ SET_MODULE_OWNER(dev);
+ dev->dma = 0;
- /*
- * Fetch MCA config registers
- */
- for(i=0;i<4;i++)
- posreg[i] = mca_read_stored_pos(slot, i+2);
-
- card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL);
- if (card==NULL) {
- printk("madgemc: unable to allocate card struct\n");
- free_netdev(dev);
- if (madgemc_card_list)
- return 0;
- return -1;
- }
- card->dev = dev;
-
- /*
- * Parse configuration information. This all comes
- * directly from the publicly available @002d.ADF.
- * Get it from Madge or your local ADF library.
- */
-
- /*
- * Base address
- */
- dev->base_addr = 0x0a20 +
- ((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) +
- ((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) +
- ((posreg[3] & MC16_POS3_ADDR3)?0x2000:0);
-
- /*
- * Interrupt line
- */
- switch(posreg[0] >> 6) { /* upper two bits */
+ card = kmalloc(sizeof(struct card_info), GFP_KERNEL);
+ if (card==NULL) {
+ printk("madgemc: unable to allocate card struct\n");
+ ret = -ENOMEM;
+ goto getout1;
+ }
+
+ /*
+ * Parse configuration information. This all comes
+ * directly from the publicly available @002d.ADF.
+ * Get it from Madge or your local ADF library.
+ */
+
+ /*
+ * Base address
+ */
+ dev->base_addr = 0x0a20 +
+ ((mdev->pos[2] & MC16_POS2_ADDR2)?0x0400:0) +
+ ((mdev->pos[0] & MC16_POS0_ADDR1)?0x1000:0) +
+ ((mdev->pos[3] & MC16_POS3_ADDR3)?0x2000:0);
+
+ /*
+ * Interrupt line
+ */
+ switch(mdev->pos[0] >> 6) { /* upper two bits */
case 0x1: dev->irq = 3; break;
case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */
case 0x3: dev->irq = 10; break;
default: dev->irq = 0; break;
- }
+ }
- if (dev->irq == 0) {
- printk("%s: invalid IRQ\n", dev->name);
- goto getout1;
- }
+ if (dev->irq == 0) {
+ printk("%s: invalid IRQ\n", dev->name);
+ ret = -EBUSY;
+ goto getout2;
+ }
- if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT,
- "madgemc")) {
- printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
- dev->base_addr += MADGEMC_SIF_OFFSET;
- goto getout1;
- }
+ if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT,
+ "madgemc")) {
+ printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", mdev->slot, dev->base_addr);
dev->base_addr += MADGEMC_SIF_OFFSET;
+ ret = -EBUSY;
+ goto getout2;
+ }
+ dev->base_addr += MADGEMC_SIF_OFFSET;
+
+ /*
+ * Arbitration Level
+ */
+ card->arblevel = ((mdev->pos[0] >> 1) & 0x7) + 8;
+
+ /*
+ * Burst mode and Fairness
+ */
+ card->burstmode = ((mdev->pos[2] >> 6) & 0x3);
+ card->fairness = ((mdev->pos[2] >> 4) & 0x1);
+
+ /*
+ * Ring Speed
+ */
+ if ((mdev->pos[1] >> 2)&0x1)
+ card->ringspeed = 2; /* not selected */
+ else if ((mdev->pos[2] >> 5) & 0x1)
+ card->ringspeed = 1; /* 16Mb */
+ else
+ card->ringspeed = 0; /* 4Mb */
+
+ /*
+ * Cable type
+ */
+ if ((mdev->pos[1] >> 6)&0x1)
+ card->cabletype = 1; /* STP/DB9 */
+ else
+ card->cabletype = 0; /* UTP/RJ-45 */
+
+
+ /*
+ * ROM Info. This requires us to actually twiddle
+ * bits on the card, so we must ensure above that
+ * the base address is free of conflict (request_region above).
+ */
+ madgemc_read_rom(dev, card);
- /*
- * Arbitration Level
- */
- card->arblevel = ((posreg[0] >> 1) & 0x7) + 8;
-
- /*
- * Burst mode and Fairness
- */
- card->burstmode = ((posreg[2] >> 6) & 0x3);
- card->fairness = ((posreg[2] >> 4) & 0x1);
-
- /*
- * Ring Speed
- */
- if ((posreg[1] >> 2)&0x1)
- card->ringspeed = 2; /* not selected */
- else if ((posreg[2] >> 5) & 0x1)
- card->ringspeed = 1; /* 16Mb */
- else
- card->ringspeed = 0; /* 4Mb */
-
- /*
- * Cable type
- */
- if ((posreg[1] >> 6)&0x1)
- card->cabletype = 1; /* STP/DB9 */
- else
- card->cabletype = 0; /* UTP/RJ-45 */
-
-
- /*
- * ROM Info. This requires us to actually twiddle
- * bits on the card, so we must ensure above that
- * the base address is free of conflict (request_region above).
- */
- madgemc_read_rom(card);
-
- if (card->manid != 0x4d) { /* something went wrong */
- printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
- goto getout;
- }
+ if (card->manid != 0x4d) { /* something went wrong */
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
+ goto getout3;
+ }
- if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
- printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
- goto getout;
- }
+ if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
+ ret = -EIO;
+ goto getout3;
+ }
- /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
- if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
- card->ramsize = 128;
- else
- card->ramsize = 256;
-
- printk("%s: %s Rev %d at 0x%04lx IRQ %d\n",
- dev->name,
- (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
- MADGEMC32_CARDNAME, card->cardrev,
- dev->base_addr, dev->irq);
-
- if (card->cardtype == 0x0d)
- printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name);
-
- if (card->ringspeed==2) { /* Unknown */
- printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
- card->ringspeed = 1; /* default to 16mb */
- }
+ /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
+ if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
+ card->ramsize = 128;
+ else
+ card->ramsize = 256;
+
+ printk("%s: %s Rev %d at 0x%04lx IRQ %d\n",
+ dev->name,
+ (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
+ MADGEMC32_CARDNAME, card->cardrev,
+ dev->base_addr, dev->irq);
+
+ if (card->cardtype == 0x0d)
+ printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name);
+
+ if (card->ringspeed==2) { /* Unknown */
+ printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
+ card->ringspeed = 1; /* default to 16mb */
+ }
- printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize);
+ printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize);
- printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name,
- (card->ringspeed)?16:4,
- card->cabletype?"STP/DB9":"UTP/RJ-45");
- printk("%s: Arbitration Level: %d\n", dev->name,
- card->arblevel);
+ printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name,
+ (card->ringspeed)?16:4,
+ card->cabletype?"STP/DB9":"UTP/RJ-45");
+ printk("%s: Arbitration Level: %d\n", dev->name,
+ card->arblevel);
- printk("%s: Burst Mode: ", dev->name);
- switch(card->burstmode) {
+ printk("%s: Burst Mode: ", dev->name);
+ switch(card->burstmode) {
case 0: printk("Cycle steal"); break;
case 1: printk("Limited burst"); break;
case 2: printk("Delayed release"); break;
case 3: printk("Immediate release"); break;
- }
- printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
-
-
- /*
- * Enable SIF before we assign the interrupt handler,
- * just in case we get spurious interrupts that need
- * handling.
- */
- outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
- madgemc_setsifsel(dev, 1);
- if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
- "madgemc", dev))
- goto getout;
-
- madgemc_chipset_init(dev); /* enables interrupts! */
- madgemc_setcabletype(dev, card->cabletype);
+ }
+ printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
- /* Setup MCA structures */
- mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
- mca_set_adapter_procfn(slot, madgemc_mcaproc, dev);
- mca_mark_as_used(slot);
- printk("%s: Ring Station Address: ", dev->name);
- printk("%2.2x", dev->dev_addr[0]);
- for (i = 1; i < 6; i++)
- printk(":%2.2x", dev->dev_addr[i]);
- printk("\n");
-
- /* XXX is ISA_MAX_ADDRESS correct here? */
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) {
- printk("%s: unable to get memory for dev->priv.\n",
- dev->name);
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
- MADGEMC_IO_EXTENT);
-
- kfree(card);
- tmsdev_term(dev);
- free_netdev(dev);
- if (madgemc_card_list)
- return 0;
- return -1;
- }
- tp = netdev_priv(dev);
-
- /*
- * The MC16 is physically a 32bit card. However, Madge
- * insists on calling it 16bit, so I'll assume here that
- * they know what they're talking about. Cut off DMA
- * at 16mb.
- */
- tp->setnselout = madgemc_setnselout_pins;
- tp->sifwriteb = madgemc_sifwriteb;
- tp->sifreadb = madgemc_sifreadb;
- tp->sifwritew = madgemc_sifwritew;
- tp->sifreadw = madgemc_sifreadw;
- tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
-
- memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1);
-
- dev->open = madgemc_open;
- dev->stop = madgemc_close;
-
- if (register_netdev(dev) == 0) {
- /* Enlist in the card list */
- card->next = madgemc_card_list;
- madgemc_card_list = card;
- slot++;
- continue; /* successful, try to find another */
- }
-
- free_irq(dev->irq, dev);
- getout:
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
- MADGEMC_IO_EXTENT);
- getout1:
- kfree(card);
- free_netdev(dev);
- slot++;
+ /*
+ * Enable SIF before we assign the interrupt handler,
+ * just in case we get spurious interrupts that need
+ * handling.
+ */
+ outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
+ madgemc_setsifsel(dev, 1);
+ if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
+ "madgemc", dev)) {
+ ret = -EBUSY;
+ goto getout3;
}
- if (madgemc_card_list)
+ madgemc_chipset_init(dev); /* enables interrupts! */
+ madgemc_setcabletype(dev, card->cabletype);
+
+ /* Setup MCA structures */
+ mca_device_set_name(mdev, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
+ mca_set_adapter_procfn(mdev->slot, madgemc_mcaproc, dev);
+
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ if (tmsdev_init(dev, device)) {
+ printk("%s: unable to get memory for dev->priv.\n",
+ dev->name);
+ ret = -ENOMEM;
+ goto getout4;
+ }
+ tp = netdev_priv(dev);
+
+ /*
+ * The MC16 is physically a 32bit card. However, Madge
+ * insists on calling it 16bit, so I'll assume here that
+ * they know what they're talking about. Cut off DMA
+ * at 16mb.
+ */
+ tp->setnselout = madgemc_setnselout_pins;
+ tp->sifwriteb = madgemc_sifwriteb;
+ tp->sifreadb = madgemc_sifreadb;
+ tp->sifwritew = madgemc_sifwritew;
+ tp->sifreadw = madgemc_sifreadw;
+ tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
+
+ memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1);
+
+ dev->open = madgemc_open;
+ dev->stop = madgemc_close;
+
+ tp->tmspriv = card;
+ dev_set_drvdata(device, dev);
+
+ if (register_netdev(dev) == 0)
return 0;
- return -1;
+
+ dev_set_drvdata(device, NULL);
+ ret = -ENOMEM;
+getout4:
+ free_irq(dev->irq, dev);
+getout3:
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
+ MADGEMC_IO_EXTENT);
+getout2:
+ kfree(card);
+getout1:
+ free_netdev(dev);
+getout:
+ mca_device_set_claim(mdev, 0);
+ return ret;
}
/*
@@ -664,12 +634,12 @@ static void madgemc_chipset_close(struct net_device *dev)
* is complete.
*
*/
-static void madgemc_read_rom(struct madgemc_card *card)
+static void madgemc_read_rom(struct net_device *dev, struct card_info *card)
{
unsigned long ioaddr;
unsigned char reg0, reg1, tmpreg0, i;
- ioaddr = card->dev->base_addr;
+ ioaddr = dev->base_addr;
reg0 = inb(ioaddr + MC_CONTROL_REG0);
reg1 = inb(ioaddr + MC_CONTROL_REG1);
@@ -686,9 +656,9 @@ static void madgemc_read_rom(struct madgemc_card *card)
outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);
/* Read BIA */
- card->dev->addr_len = 6;
+ dev->addr_len = 6;
for (i = 0; i < 6; i++)
- card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
+ dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
/* Restore original register values */
outb(reg0, ioaddr + MC_CONTROL_REG0);
@@ -721,14 +691,10 @@ static int madgemc_close(struct net_device *dev)
static int madgemc_mcaproc(char *buf, int slot, void *d)
{
struct net_device *dev = (struct net_device *)d;
- struct madgemc_card *curcard = madgemc_card_list;
+ struct net_local *tp = dev->priv;
+ struct card_info *curcard = tp->tmspriv;
int len = 0;
- while (curcard) { /* search for card struct */
- if (curcard->dev == dev)
- break;
- curcard = curcard->next;
- }
len += sprintf(buf+len, "-------\n");
if (curcard) {
struct net_local *tp = netdev_priv(dev);
@@ -763,25 +729,56 @@ static int madgemc_mcaproc(char *buf, int slot, void *d)
return len;
}
-static void __exit madgemc_exit(void)
+static int __devexit madgemc_remove(struct device *device)
{
- struct net_device *dev;
- struct madgemc_card *this_card;
-
- while (madgemc_card_list) {
- dev = madgemc_card_list->dev;
- unregister_netdev(dev);
- release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
- free_irq(dev->irq, dev);
- tmsdev_term(dev);
- free_netdev(dev);
- this_card = madgemc_card_list;
- madgemc_card_list = this_card->next;
- kfree(this_card);
- }
+ struct net_device *dev = dev_get_drvdata(device);
+ struct net_local *tp;
+ struct card_info *card;
+
+ if (!dev)
+ BUG();
+
+ tp = dev->priv;
+ card = tp->tmspriv;
+ kfree(card);
+ tp->tmspriv = NULL;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ dev_set_drvdata(device, NULL);
+
+ return 0;
+}
+
+static short madgemc_adapter_ids[] __initdata = {
+ 0x002d,
+ 0x0000
+};
+
+static struct mca_driver madgemc_driver = {
+ .id_table = madgemc_adapter_ids,
+ .driver = {
+ .name = "madgemc",
+ .bus = &mca_bus_type,
+ .probe = madgemc_probe,
+ .remove = __devexit_p(madgemc_remove),
+ },
+};
+
+static int __init madgemc_init (void)
+{
+ return mca_register_driver (&madgemc_driver);
+}
+
+static void __exit madgemc_exit (void)
+{
+ mca_unregister_driver (&madgemc_driver);
}
-module_init(madgemc_probe);
+module_init(madgemc_init);
module_exit(madgemc_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 9e7923192a49..05477d24fd49 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_device *dev)
while(olympic_priv->srb_queued) {
- t = schedule_timeout(60*HZ);
+ t = schedule_timeout_interruptible(60*HZ);
if(signal_pending(current)) {
printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 40ad0fde28af..d04c918ebef8 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -29,6 +29,7 @@ static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/trdevice.h>
+#include <linux/platform_device.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -62,8 +63,7 @@ static int dmalist[] __initdata = {
};
static char cardname[] = "Proteon 1392\0";
-
-struct net_device *proteon_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
static int proteon_open(struct net_device *dev);
static void proteon_read_eeprom(struct net_device *dev);
static unsigned short proteon_setnselout_pins(struct net_device *dev);
@@ -116,7 +116,7 @@ nodev:
return -ENODEV;
}
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
{
struct net_local *tp;
static int versionprinted;
@@ -137,7 +137,7 @@ static int __init setup_card(struct net_device *dev)
}
}
if (err)
- goto out4;
+ goto out5;
/* At this point we have found a valid card. */
@@ -145,14 +145,15 @@ static int __init setup_card(struct net_device *dev)
printk(KERN_DEBUG "%s", version);
err = -EIO;
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ pdev->dma_mask = &dma_mask;
+ if (tmsdev_init(dev, pdev))
goto out4;
dev->base_addr &= ~3;
proteon_read_eeprom(dev);
- printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk(KERN_DEBUG "proteon.c: Ring Station Address: ");
printk("%2.2x", dev->dev_addr[0]);
for (j = 1; j < 6; j++)
printk(":%2.2x", dev->dev_addr[j]);
@@ -185,7 +186,7 @@ static int __init setup_card(struct net_device *dev)
if(irqlist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ printk(KERN_INFO "proteon.c: AutoSelect no IRQ available\n");
goto out3;
}
}
@@ -196,15 +197,15 @@ static int __init setup_card(struct net_device *dev)
break;
if (irqlist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "proteon.c: Illegal IRQ %d specified\n",
+ dev->irq);
goto out3;
}
if (request_irq(dev->irq, tms380tr_interrupt, 0,
cardname, dev))
{
- printk(KERN_INFO "%s: Selected IRQ %d not available\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "proteon.c: Selected IRQ %d not available\n",
+ dev->irq);
goto out3;
}
}
@@ -220,7 +221,7 @@ static int __init setup_card(struct net_device *dev)
if(dmalist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ printk(KERN_INFO "proteon.c: AutoSelect no DMA available\n");
goto out2;
}
}
@@ -231,25 +232,25 @@ static int __init setup_card(struct net_device *dev)
break;
if (dmalist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal DMA %d specified\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "proteon.c: Illegal DMA %d specified\n",
+ dev->dma);
goto out2;
}
if (request_dma(dev->dma, cardname))
{
- printk(KERN_INFO "%s: Selected DMA %d not available\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "proteon.c: Selected DMA %d not available\n",
+ dev->dma);
goto out2;
}
}
- printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
- dev->name, dev->base_addr, dev->irq, dev->dma);
-
err = register_netdev(dev);
if (err)
goto out;
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
return 0;
out:
free_dma(dev->dma);
@@ -258,34 +259,11 @@ out2:
out3:
tmsdev_term(dev);
out4:
- release_region(dev->base_addr, PROTEON_IO_EXTENT);
+ release_region(dev->base_addr, PROTEON_IO_EXTENT);
+out5:
return err;
}
-struct net_device * __init proteon_probe(int unit)
-{
- struct net_device *dev = alloc_trdev(sizeof(struct net_local));
- int err = 0;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0) {
- sprintf(dev->name, "tr%d", unit);
- netdev_boot_setup_check(dev);
- }
-
- err = setup_card(dev);
- if (err)
- goto out;
-
- return dev;
-
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* Reads MAC address from adapter RAM, which should've read it from
* the onboard ROM.
@@ -352,8 +330,6 @@ static int proteon_open(struct net_device *dev)
return tms380tr_open(dev);
}
-#ifdef MODULE
-
#define ISATR_MAX_ADAPTERS 3
static int io[ISATR_MAX_ADAPTERS];
@@ -366,13 +342,23 @@ module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param_array(dma, int, NULL, 0);
-static struct net_device *proteon_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];
+
+static struct device_driver proteon_driver = {
+ .name = "proteon",
+ .bus = &platform_bus_type,
+};
-int init_module(void)
+static int __init proteon_init(void)
{
struct net_device *dev;
+ struct platform_device *pdev;
int i, num = 0, err = 0;
+ err = driver_register(&proteon_driver);
+ if (err)
+ return err;
+
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
dev = alloc_trdev(sizeof(struct net_local));
if (!dev)
@@ -381,11 +367,15 @@ int init_module(void)
dev->base_addr = io[i];
dev->irq = irq[i];
dev->dma = dma[i];
- err = setup_card(dev);
+ pdev = platform_device_register_simple("proteon",
+ i, NULL, 0);
+ err = setup_card(dev, &pdev->dev);
if (!err) {
- proteon_dev[i] = dev;
+ proteon_dev[i] = pdev;
+ dev_set_drvdata(&pdev->dev, dev);
++num;
} else {
+ platform_device_unregister(pdev);
free_netdev(dev);
}
}
@@ -399,23 +389,28 @@ int init_module(void)
return (0);
}
-void cleanup_module(void)
+static void __exit proteon_cleanup(void)
{
+ struct net_device *dev;
int i;
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
- struct net_device *dev = proteon_dev[i];
+ struct platform_device *pdev = proteon_dev[i];
- if (!dev)
+ if (!pdev)
continue;
-
+ dev = dev_get_drvdata(&pdev->dev);
unregister_netdev(dev);
release_region(dev->base_addr, PROTEON_IO_EXTENT);
free_irq(dev->irq, dev);
free_dma(dev->dma);
tmsdev_term(dev);
free_netdev(dev);
+ dev_set_drvdata(&pdev->dev, NULL);
+ platform_device_unregister(pdev);
}
+ driver_unregister(&proteon_driver);
}
-#endif /* MODULE */
+module_init(proteon_init);
+module_exit(proteon_cleanup);
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index f26796e2d0e5..72cf708396be 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -36,6 +36,7 @@ static const char version[] = "skisa.c: v1.03 09/12/2002 by Jochen Friedrich\n";
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/trdevice.h>
+#include <linux/platform_device.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -68,8 +69,7 @@ static int dmalist[] __initdata = {
};
static char isa_cardname[] = "SK NET TR 4/16 ISA\0";
-
-struct net_device *sk_isa_probe(int unit);
+static u64 dma_mask = ISA_MAX_ADDRESS;
static int sk_isa_open(struct net_device *dev);
static void sk_isa_read_eeprom(struct net_device *dev);
static unsigned short sk_isa_setnselout_pins(struct net_device *dev);
@@ -133,7 +133,7 @@ static int __init sk_isa_probe1(struct net_device *dev, int ioaddr)
return 0;
}
-static int __init setup_card(struct net_device *dev)
+static int __init setup_card(struct net_device *dev, struct device *pdev)
{
struct net_local *tp;
static int versionprinted;
@@ -154,7 +154,7 @@ static int __init setup_card(struct net_device *dev)
}
}
if (err)
- goto out4;
+ goto out5;
/* At this point we have found a valid card. */
@@ -162,14 +162,15 @@ static int __init setup_card(struct net_device *dev)
printk(KERN_DEBUG "%s", version);
err = -EIO;
- if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ pdev->dma_mask = &dma_mask;
+ if (tmsdev_init(dev, pdev))
goto out4;
dev->base_addr &= ~3;
sk_isa_read_eeprom(dev);
- printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk(KERN_DEBUG "skisa.c: Ring Station Address: ");
printk("%2.2x", dev->dev_addr[0]);
for (j = 1; j < 6; j++)
printk(":%2.2x", dev->dev_addr[j]);
@@ -202,7 +203,7 @@ static int __init setup_card(struct net_device *dev)
if(irqlist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ printk(KERN_INFO "skisa.c: AutoSelect no IRQ available\n");
goto out3;
}
}
@@ -213,15 +214,15 @@ static int __init setup_card(struct net_device *dev)
break;
if (irqlist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "skisa.c: Illegal IRQ %d specified\n",
+ dev->irq);
goto out3;
}
if (request_irq(dev->irq, tms380tr_interrupt, 0,
isa_cardname, dev))
{
- printk(KERN_INFO "%s: Selected IRQ %d not available\n",
- dev->name, dev->irq);
+ printk(KERN_INFO "skisa.c: Selected IRQ %d not available\n",
+ dev->irq);
goto out3;
}
}
@@ -237,7 +238,7 @@ static int __init setup_card(struct net_device *dev)
if(dmalist[j] == 0)
{
- printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ printk(KERN_INFO "skisa.c: AutoSelect no DMA available\n");
goto out2;
}
}
@@ -248,25 +249,25 @@ static int __init setup_card(struct net_device *dev)
break;
if (dmalist[j] == 0)
{
- printk(KERN_INFO "%s: Illegal DMA %d specified\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "skisa.c: Illegal DMA %d specified\n",
+ dev->dma);
goto out2;
}
if (request_dma(dev->dma, isa_cardname))
{
- printk(KERN_INFO "%s: Selected DMA %d not available\n",
- dev->name, dev->dma);
+ printk(KERN_INFO "skisa.c: Selected DMA %d not available\n",
+ dev->dma);
goto out2;
}
}
- printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
- dev->name, dev->base_addr, dev->irq, dev->dma);
-
err = register_netdev(dev);
if (err)
goto out;
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
return 0;
out:
free_dma(dev->dma);
@@ -275,33 +276,11 @@ out2:
out3:
tmsdev_term(dev);
out4:
- release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+ release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+out5:
return err;
}
-struct net_device * __init sk_isa_probe(int unit)
-{
- struct net_device *dev = alloc_trdev(sizeof(struct net_local));
- int err = 0;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0) {
- sprintf(dev->name, "tr%d", unit);
- netdev_boot_setup_check(dev);
- }
-
- err = setup_card(dev);
- if (err)
- goto out;
-
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
/*
* Reads MAC address from adapter RAM, which should've read it from
* the onboard ROM.
@@ -361,8 +340,6 @@ static int sk_isa_open(struct net_device *dev)
return tms380tr_open(dev);
}
-#ifdef MODULE
-
#define ISATR_MAX_ADAPTERS 3
static int io[ISATR_MAX_ADAPTERS];
@@ -375,13 +352,23 @@ module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param_array(dma, int, NULL, 0);
-static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
+static struct platform_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
-int init_module(void)
+static struct device_driver sk_isa_driver = {
+ .name = "skisa",
+ .bus = &platform_bus_type,
+};
+
+static int __init sk_isa_init(void)
{
struct net_device *dev;
+ struct platform_device *pdev;
int i, num = 0, err = 0;
+ err = driver_register(&sk_isa_driver);
+ if (err)
+ return err;
+
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
dev = alloc_trdev(sizeof(struct net_local));
if (!dev)
@@ -390,12 +377,15 @@ int init_module(void)
dev->base_addr = io[i];
dev->irq = irq[i];
dev->dma = dma[i];
- err = setup_card(dev);
-
+ pdev = platform_device_register_simple("skisa",
+ i, NULL, 0);
+ err = setup_card(dev, &pdev->dev);
if (!err) {
- sk_isa_dev[i] = dev;
+ sk_isa_dev[i] = pdev;
+ dev_set_drvdata(&sk_isa_dev[i]->dev, dev);
++num;
} else {
+ platform_device_unregister(pdev);
free_netdev(dev);
}
}
@@ -409,23 +399,28 @@ int init_module(void)
return (0);
}
-void cleanup_module(void)
+static void __exit sk_isa_cleanup(void)
{
+ struct net_device *dev;
int i;
for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
- struct net_device *dev = sk_isa_dev[i];
+ struct platform_device *pdev = sk_isa_dev[i];
- if (!dev)
+ if (!pdev)
continue;
-
+ dev = dev_get_drvdata(&pdev->dev);
unregister_netdev(dev);
release_region(dev->base_addr, SK_ISA_IO_EXTENT);
free_irq(dev->irq, dev);
free_dma(dev->dma);
tmsdev_term(dev);
free_netdev(dev);
+ dev_set_drvdata(&pdev->dev, NULL);
+ platform_device_unregister(pdev);
}
+ driver_unregister(&sk_isa_driver);
}
-#endif /* MODULE */
+module_init(sk_isa_init);
+module_exit(sk_isa_cleanup);
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 5e0b0ce98ed7..c1925590a0e1 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -62,6 +62,7 @@
* normal operation.
* 30-Dec-02 JF Removed incorrect __init from
* tms380tr_init_card.
+ * 22-Jul-05 JF Converted to dma-mapping.
*
* To do:
* 1. Multi/Broadcast packet handling (this may have fixed itself)
@@ -89,7 +90,7 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -114,8 +115,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
#endif
static unsigned int tms380tr_debug = TMS380TR_DEBUG;
-static struct device tms_device;
-
/* Index to functions, as function prototypes.
* Alphabetical by function name.
*/
@@ -434,7 +433,7 @@ static void tms380tr_init_net_local(struct net_device *dev)
skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
/* data unreachable for DMA ? then use local buffer */
- dmabuf = pci_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
{
tp->Rpl[i].SkbStat = SKB_DATA_COPY;
@@ -638,10 +637,10 @@ static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device
/* Is buffer reachable for Busmaster-DMA? */
length = skb->len;
- dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
+ dmabuf = dma_map_single(tp->pdev, skb->data, length, DMA_TO_DEVICE);
if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) {
/* Copy frame to local buffer */
- pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, dmabuf, length, DMA_TO_DEVICE);
dmabuf = 0;
i = tp->TplFree->TPLIndex;
buf = tp->LocalTxBuffers[i];
@@ -1244,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
tmp = jiffies + time/(1000000/HZ);
do {
- current->state = TASK_INTERRUPTIBLE;
- tmp = schedule_timeout(tmp);
+ tmp = schedule_timeout_interruptible(tmp);
} while(time_after(tmp, jiffies));
#else
udelay(time);
@@ -1284,9 +1282,7 @@ static int tms380tr_reset_adapter(struct net_device *dev)
unsigned short count, c, count2;
const struct firmware *fw_entry = NULL;
- strncpy(tms_device.bus_id,dev->name, BUS_ID_SIZE);
-
- if (request_firmware(&fw_entry, "tms380tr.bin", &tms_device) != 0) {
+ if (request_firmware(&fw_entry, "tms380tr.bin", tp->pdev) != 0) {
printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
dev->name, "tms380tr.bin");
return (-1);
@@ -2021,7 +2017,7 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp)
printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
if (tpl->DMABuff)
- pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(tpl->Skb);
}
@@ -2090,7 +2086,7 @@ static void tms380tr_tx_status_irq(struct net_device *dev)
tp->MacStat.tx_packets++;
if (tpl->DMABuff)
- pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);
dev_kfree_skb_irq(tpl->Skb);
tpl->BusyFlag = 0; /* "free" TPL */
}
@@ -2209,7 +2205,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
tp->MacStat.rx_errors++;
}
if (rpl->DMABuff)
- pci_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, PCI_DMA_TODEVICE);
+ dma_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, DMA_TO_DEVICE);
rpl->DMABuff = 0;
/* Allocate new skb for rpl */
@@ -2227,7 +2223,7 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
skb_put(rpl->Skb, tp->MaxPacketSize);
/* Data unreachable for DMA ? then use local buffer */
- dmabuf = pci_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);
if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
{
rpl->SkbStat = SKB_DATA_COPY;
@@ -2332,23 +2328,26 @@ void tmsdev_term(struct net_device *dev)
struct net_local *tp;
tp = netdev_priv(dev);
- pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
- PCI_DMA_BIDIRECTIONAL);
+ dma_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
+ DMA_BIDIRECTIONAL);
}
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
- struct pci_dev *pdev)
+int tmsdev_init(struct net_device *dev, struct device *pdev)
{
struct net_local *tms_local;
memset(dev->priv, 0, sizeof(struct net_local));
tms_local = netdev_priv(dev);
init_waitqueue_head(&tms_local->wait_for_tok_int);
- tms_local->dmalimit = dmalimit;
+ if (pdev->dma_mask)
+ tms_local->dmalimit = *pdev->dma_mask;
+ else
+ return -ENOMEM;
tms_local->pdev = pdev;
- tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local,
- sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL);
- if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit)
+ tms_local->dmabuffer = dma_map_single(pdev, (void *)tms_local,
+ sizeof(struct net_local), DMA_BIDIRECTIONAL);
+ if (tms_local->dmabuffer + sizeof(struct net_local) >
+ tms_local->dmalimit)
{
printk(KERN_INFO "%s: Memory not accessible for DMA\n",
dev->name);
@@ -2370,8 +2369,6 @@ int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
return 0;
}
-#ifdef MODULE
-
EXPORT_SYMBOL(tms380tr_open);
EXPORT_SYMBOL(tms380tr_close);
EXPORT_SYMBOL(tms380tr_interrupt);
@@ -2379,6 +2376,8 @@ EXPORT_SYMBOL(tmsdev_init);
EXPORT_SYMBOL(tmsdev_term);
EXPORT_SYMBOL(tms380tr_wait);
+#ifdef MODULE
+
static struct module *TMS380_module = NULL;
int init_module(void)
diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h
index f2c5ba0f37a5..30452c67bb68 100644
--- a/drivers/net/tokenring/tms380tr.h
+++ b/drivers/net/tokenring/tms380tr.h
@@ -17,8 +17,7 @@
int tms380tr_open(struct net_device *dev);
int tms380tr_close(struct net_device *dev);
irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
- struct pci_dev *pdev);
+int tmsdev_init(struct net_device *dev, struct device *pdev);
void tmsdev_term(struct net_device *dev);
void tms380tr_wait(unsigned long time);
@@ -719,7 +718,7 @@ struct s_TPL { /* Transmit Parameter List (align on even word boundaries) */
struct sk_buff *Skb;
unsigned char TPLIndex;
volatile unsigned char BusyFlag;/* Flag: TPL busy? */
- dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
};
/* ---------------------Receive Functions-------------------------------*
@@ -1060,7 +1059,7 @@ struct s_RPL { /* Receive Parameter List */
struct sk_buff *Skb;
SKB_STAT SkbStat;
int RPLIndex;
- dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
};
/* Information that need to be kept for each board. */
@@ -1091,7 +1090,7 @@ typedef struct net_local {
RPL *RplTail;
unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
- struct pci_dev *pdev;
+ struct device *pdev;
int DataRate;
unsigned char ScbInUse;
unsigned short CMDqueue;
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 2e18c0a46482..ab47c0547a3b 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -100,7 +100,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
unsigned int pci_irq_line;
unsigned long pci_ioaddr;
struct card_info *cardinfo = &card_info_table[ent->driver_data];
-
+
if (versionprinted++ == 0)
printk("%s", version);
@@ -143,7 +143,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
printk(":%2.2x", dev->dev_addr[i]);
printk("\n");
- ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
printk("%s: unable to get memory for dev->priv.\n", dev->name);
goto err_out_irq;
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c
index 5db694c4eb02..683f14b01c06 100644
--- a/drivers/net/tulip/21142.c
+++ b/drivers/net/tulip/21142.c
@@ -172,7 +172,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5)
int i;
for (i = 0; i < tp->mtable->leafcount; i++)
if (tp->mtable->mleaf[i].media == dev->if_port) {
- int startup = ! ((tp->chip_id == DC21143 && tp->revision == 65));
+ int startup = ! ((tp->chip_id == DC21143 && (tp->revision == 48 || tp->revision == 65)));
tp->cur_index = i;
tulip_select_media(dev, startup);
setup_done = 1;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index e2cdaf876201..8c9634a98c11 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -135,6 +135,18 @@ config DM9102
<file:Documentation/networking/net-modules.txt>. The module will
be called dmfe.
+config ULI526X
+ tristate "ULi M526x controller support"
+ depends on NET_TULIP && PCI
+ select CRC32
+ ---help---
+ This driver is for ULi M5261/M5263 10/100M Ethernet Controller
+ (<http://www.uli.com.tw/>).
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will
+ be called uli526x.
+
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
depends on NET_TULIP && CARDBUS
diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile
index 8bb9b4683979..451090d6fcca 100644
--- a/drivers/net/tulip/Makefile
+++ b/drivers/net/tulip/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_WINBOND_840) += winbond-840.o
obj-$(CONFIG_DE2104X) += de2104x.o
obj-$(CONFIG_TULIP) += tulip.o
obj-$(CONFIG_DE4X5) += de4x5.o
+obj-$(CONFIG_ULI526X) += uli526x.o
# Declare multi-part drivers.
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index fc353e348f9a..d7fb3ffe06ac 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1787,10 +1787,15 @@ static void __init de21041_get_srom_info (struct de_private *de)
/* DEC now has a specification but early board makers
just put the address in the first EEPROM locations. */
/* This does memcmp(eedata, eedata+16, 8) */
+
+#ifndef CONFIG_MIPS_COBALT
+
for (i = 0; i < 8; i ++)
if (ee_data[i] != ee_data[16+i])
sa_offset = 20;
+#endif
+
/* store MAC address */
for (i = 0; i < 6; i ++)
de->dev->dev_addr[i] = ee_data[i + sa_offset];
@@ -1934,7 +1939,7 @@ static int __init de_init_one (struct pci_dev *pdev,
struct de_private *de;
int rc;
void __iomem *regs;
- long pciaddr;
+ unsigned long pciaddr;
static int board_idx = -1;
board_idx++;
@@ -2071,8 +2076,7 @@ static int __init de_init_one (struct pci_dev *pdev,
return 0;
err_out_iomap:
- if (de->ee_data)
- kfree(de->ee_data);
+ kfree(de->ee_data);
iounmap(regs);
err_out_res:
pci_release_regions(pdev);
@@ -2091,8 +2095,7 @@ static void __exit de_remove_one (struct pci_dev *pdev)
if (!dev)
BUG();
unregister_netdev(dev);
- if (de->ee_data)
- kfree(de->ee_data);
+ kfree(de->ee_data);
iounmap(de->regs);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 93800c126e86..ee48bfd67349 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -2144,9 +2144,9 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
int i, j, cfrv;
struct de4x5_private *lp = netdev_priv(dev);
- struct list_head *walk = &pdev->bus_list;
+ struct list_head *walk;
- for (walk = walk->next; walk != &pdev->bus_list; walk = walk->next) {
+ list_for_each(walk, &pdev->bus_list) {
struct pci_dev *this_dev = pci_dev_b(walk);
/* Skip the pci_bus list entry */
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index e26c31f944bf..f53396fe79c9 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -81,25 +81,6 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
return retval & 0xffff;
}
- if(tp->chip_id == ULI526X && tp->revision >= 0x40) {
- int value;
- int i = 1000;
-
- value = ioread32(ioaddr + CSR9);
- iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-
- value = (phy_id << 21) | (location << 16) | 0x08000000;
- iowrite32(value, ioaddr + CSR10);
-
- while(--i > 0) {
- mdio_delay();
- if(ioread32(ioaddr + CSR10) & 0x10000000)
- break;
- }
- retval = ioread32(ioaddr + CSR10);
- spin_unlock_irqrestore(&tp->mii_lock, flags);
- return retval & 0xFFFF;
- }
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -159,23 +140,6 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
spin_unlock_irqrestore(&tp->mii_lock, flags);
return;
}
- if (tp->chip_id == ULI526X && tp->revision >= 0x40) {
- int value;
- int i = 1000;
-
- value = ioread32(ioaddr + CSR9);
- iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
-
- value = (phy_id << 21) | (location << 16) | 0x04000000 | (val & 0xFFFF);
- iowrite32(value, ioaddr + CSR10);
-
- while(--i > 0) {
- if (ioread32(ioaddr + CSR10) & 0x10000000)
- break;
- }
- spin_unlock_irqrestore(&tp->mii_lock, flags);
- return;
- }
/* Establish sync by sending 32 logic ones. */
for (i = 32; i >= 0; i--) {
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
index 691568283553..e058a9fbfe88 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/tulip/timer.c
@@ -39,7 +39,6 @@ void tulip_timer(unsigned long data)
case MX98713:
case COMPEX9881:
case DM910X:
- case ULI526X:
default: {
struct medialeaf *mleaf;
unsigned char *p;
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 20346d847d9e..05d2d96f7be2 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -88,7 +88,6 @@ enum chips {
I21145,
DM910X,
CONEXANT,
- ULI526X
};
@@ -482,11 +481,8 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
static inline void tulip_restart_rxtx(struct tulip_private *tp)
{
- if(!(tp->chip_id == ULI526X &&
- (tp->revision == 0x40 || tp->revision == 0x50))) {
- tulip_stop_rxtx(tp);
- udelay(5);
- }
+ tulip_stop_rxtx(tp);
+ udelay(5);
tulip_start_rxtx(tp);
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index d45d8f56e5b4..125ed00e95a5 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -199,9 +199,6 @@ struct tulip_chip_table tulip_tbl[] = {
{ "Conexant LANfinity", 256, 0x0001ebef,
HAS_MII | HAS_ACPI, tulip_timer },
- /* ULi526X */
- { "ULi M5261/M5263", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, tulip_timer },
};
@@ -239,10 +236,9 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1737, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
- { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
- { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
{ 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+ { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -522,7 +518,7 @@ static void tulip_tx_timeout(struct net_device *dev)
dev->name);
} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
|| tp->chip_id == MX98713 || tp->chip_id == COMPEX9881
- || tp->chip_id == DM910X || tp->chip_id == ULI526X) {
+ || tp->chip_id == DM910X) {
printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
"SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
@@ -1103,18 +1099,16 @@ static void set_rx_mode(struct net_device *dev)
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
- /* Avoid a chip errata by prefixing a dummy entry. Don't do
- this on the ULI526X as it triggers a different problem */
- if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
- tp->tx_buffers[entry].skb = NULL;
- tp->tx_buffers[entry].mapping = 0;
- tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
- tp->tx_ring[entry].buffer1 = 0;
- /* Must set DescOwned later to avoid race with chip */
- dummy = entry;
- entry = tp->cur_tx++ % TX_RING_SIZE;
- }
+ /* Avoid a chip errata by prefixing a dummy entry. */
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ /* Must set DescOwned later to avoid race with chip */
+ dummy = entry;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+
}
tp->tx_buffers[entry].skb = NULL;
@@ -1235,10 +1229,6 @@ static int tulip_uli_dm_quirk(struct pci_dev *pdev)
{
if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5261)
- return 1;
- if (pdev->vendor == 0x10b9 && pdev->device == 0x5263)
- return 1;
return 0;
}
@@ -1680,7 +1670,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
switch (chip_idx) {
case DC21140:
case DM910X:
- case ULI526X:
default:
if (tp->mtable)
iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
@@ -1738,8 +1727,7 @@ err_out_free_ring:
tp->rx_ring, tp->rx_ring_dma);
err_out_mtable:
- if (tp->mtable)
- kfree (tp->mtable);
+ kfree (tp->mtable);
pci_iounmap(pdev, ioaddr);
err_out_free_res:
@@ -1817,8 +1805,7 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
tp->rx_ring, tp->rx_ring_dma);
- if (tp->mtable)
- kfree (tp->mtable);
+ kfree (tp->mtable);
pci_iounmap(pdev, tp->base_addr);
free_netdev (dev);
pci_release_regions (pdev);
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
new file mode 100644
index 000000000000..1a4316336256
--- /dev/null
+++ b/drivers/net/tulip/uli526x.c
@@ -0,0 +1,1749 @@
+/*
+ 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.
+
+
+*/
+
+#define DRV_NAME "uli526x"
+#define DRV_VERSION "0.9.3"
+#define DRV_RELDATE "2005-7-29"
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.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/spinlock.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+
+/* Board/System/Debug information/definition ---------------- */
+#define PCI_ULI5261_ID 0x526110B9 /* ULi M5261 ID*/
+#define PCI_ULI5263_ID 0x526310B9 /* ULi M5263 ID*/
+
+#define ULI526X_IO_SIZE 0x100
+#define TX_DESC_CNT 0x20 /* Allocated Tx descriptors */
+#define RX_DESC_CNT 0x30 /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x600
+#define RX_ALLOC_SIZE 0x620
+#define ULI526X_RESET 1
+#define CR0_DEFAULT 0
+#define CR6_DEFAULT 0x22200000
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define ULI5261_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+
+#define ULI526X_10MHF 0
+#define ULI526X_100MHF 1
+#define ULI526X_10MFD 4
+#define ULI526X_100MFD 5
+#define ULI526X_AUTO 8
+
+#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */
+#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */
+#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */
+#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */
+#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */
+#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+#define ULI526X_TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */
+#define ULI526X_TX_TIMEOUT ((16*HZ)/2) /* tx packet time-out time 8 s" */
+#define ULI526X_TX_KICK (4*HZ/2) /* tx packet Kick-out time 2 s" */
+
+#define ULI526X_DBUG(dbug_now, msg, value) if (uli526x_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) \
+ outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
+ udelay(5);
+
+/* Structure/enum declaration ------------------------------- */
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ char *tx_buf_ptr; /* Data for us */
+ struct tx_desc *next_tx_desc;
+} __attribute__(( aligned(32) ));
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ struct sk_buff *rx_skb_ptr; /* Data for us */
+ struct rx_desc *next_rx_desc;
+} __attribute__(( aligned(32) ));
+
+struct uli526x_board_info {
+ u32 chip_id; /* Chip vendor/Device ID */
+ struct net_device *next_dev; /* next device */
+ struct pci_dev *pdev; /* PCI device */
+ spinlock_t lock;
+
+ long ioaddr; /* I/O base address */
+ u32 cr0_data;
+ u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ /* pointer for memory physical address */
+ dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */
+ dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */
+ dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */
+ dma_addr_t first_tx_desc_dma;
+ dma_addr_t first_rx_desc_dma;
+
+ /* descriptor pointer */
+ unsigned char *buf_pool_ptr; /* Tx buffer pool memory */
+ unsigned char *buf_pool_start; /* Tx buffer pool align dword */
+ unsigned char *desc_pool_ptr; /* descriptor pool memory */
+ struct tx_desc *first_tx_desc;
+ struct tx_desc *tx_insert_ptr;
+ struct tx_desc *tx_remove_ptr;
+ struct rx_desc *first_rx_desc;
+ struct rx_desc *rx_insert_ptr;
+ struct rx_desc *rx_ready_ptr; /* packet come pointer */
+ unsigned long tx_packet_cnt; /* transmitted packet count */
+ unsigned long rx_avail_cnt; /* available rx descriptor count */
+ unsigned long interval_rx_cnt; /* rx packet count a callback time */
+
+ u16 dbug_cnt;
+ u16 NIC_capability; /* NIC media capability */
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work media mode */
+ u8 phy_addr;
+ u8 link_failed; /* Ever link failed */
+ u8 wait_reset; /* Hardware failed, need to reset */
+ struct timer_list timer;
+
+ /* System defined statistic counter */
+ struct net_device_stats stats;
+
+ /* Driver defined statistic counter */
+ unsigned long tx_fifo_underrun;
+ unsigned long tx_loss_carrier;
+ unsigned long tx_no_carrier;
+ unsigned long tx_late_collision;
+ unsigned long tx_excessive_collision;
+ unsigned long tx_jabber_timeout;
+ unsigned long reset_count;
+ unsigned long reset_cr8;
+ unsigned long reset_fatal;
+ unsigned long reset_TXtimeout;
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+ u8 init;
+};
+
+enum uli526x_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+ DCR15 = 0x78
+};
+
+enum uli526x_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration ----------------------------- */
+static int __devinitdata printed_version;
+static char version[] __devinitdata =
+ KERN_INFO DRV_NAME ": ULi M5261/M5263 net driver, version "
+ DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static int uli526x_debug;
+static unsigned char uli526x_media_mode = ULI526X_AUTO;
+static u32 uli526x_cr6_user_set;
+
+/* For module input parameter */
+static int debug;
+static u32 cr6set;
+static unsigned char mode = 8;
+
+/* function declaration ------------------------------------- */
+static int uli526x_open(struct net_device *);
+static int uli526x_start_xmit(struct sk_buff *, struct net_device *);
+static int uli526x_stop(struct net_device *);
+static struct net_device_stats * uli526x_get_stats(struct net_device *);
+static void uli526x_set_filter_mode(struct net_device *);
+static struct ethtool_ops netdev_ethtool_ops;
+static u16 read_srom_word(long, int);
+static irqreturn_t uli526x_interrupt(int, void *, struct pt_regs *);
+static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
+static void allocate_rx_buffer(struct uli526x_board_info *);
+static void update_cr6(u32, unsigned long);
+static void send_filter_frame(struct net_device *, int);
+static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 phy_readby_cr10(unsigned long, u8, u8);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_writeby_cr10(unsigned long, u8, u8, u16);
+static void phy_write_1bit(unsigned long, u32, u32);
+static u16 phy_read_1bit(unsigned long, u32);
+static u8 uli526x_sense_speed(struct uli526x_board_info *);
+static void uli526x_process_mode(struct uli526x_board_info *);
+static void uli526x_timer(unsigned long);
+static void uli526x_rx_packet(struct net_device *, struct uli526x_board_info *);
+static void uli526x_free_tx_pkt(struct net_device *, struct uli526x_board_info *);
+static void uli526x_reuse_skb(struct uli526x_board_info *, struct sk_buff *);
+static void uli526x_dynamic_reset(struct net_device *);
+static void uli526x_free_rxbuffer(struct uli526x_board_info *);
+static void uli526x_init(struct net_device *);
+static void uli526x_set_phyxcer(struct uli526x_board_info *);
+
+/* ULI526X network board routine ---------------------------- */
+
+/*
+ * Search ULI526X board, allocate space and register it
+ */
+
+static int __devinit uli526x_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct uli526x_board_info *db; /* board information structure */
+ struct net_device *dev;
+ int i, err;
+
+ ULI526X_DBUG(0, "uli526x_init_one()", 0);
+
+ if (!printed_version++)
+ printk(version);
+
+ /* Init network device */
+ dev = alloc_etherdev(sizeof(*db));
+ if (dev == NULL)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
+ err = -ENODEV;
+ goto err_out_free;
+ }
+
+ /* Enable Master/IO access, Disable memory access */
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_out_free;
+
+ if (!pci_resource_start(pdev, 0)) {
+ printk(KERN_ERR DRV_NAME ": I/O base is zero\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ if (pci_resource_len(pdev, 0) < (ULI526X_IO_SIZE) ) {
+ printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ if (pci_request_regions(pdev, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ /* Init system & device */
+ db = netdev_priv(dev);
+
+ /* Allocate Tx/Rx descriptor memory */
+ db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+ if(db->desc_pool_ptr == NULL)
+ {
+ err = -ENOMEM;
+ goto err_out_nomem;
+ }
+ db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+ if(db->buf_pool_ptr == NULL)
+ {
+ err = -ENOMEM;
+ goto err_out_nomem;
+ }
+
+ db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+ db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+ db->buf_pool_start = db->buf_pool_ptr;
+ db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+ db->chip_id = ent->driver_data;
+ db->ioaddr = pci_resource_start(pdev, 0);
+
+ db->pdev = pdev;
+ db->init = 1;
+
+ dev->base_addr = db->ioaddr;
+ dev->irq = pdev->irq;
+ pci_set_drvdata(pdev, dev);
+
+ /* Register some necessary functions */
+ dev->open = &uli526x_open;
+ dev->hard_start_xmit = &uli526x_start_xmit;
+ dev->stop = &uli526x_stop;
+ dev->get_stats = &uli526x_get_stats;
+ dev->set_multicast_list = &uli526x_set_filter_mode;
+ dev->ethtool_ops = &netdev_ethtool_ops;
+ spin_lock_init(&db->lock);
+
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+
+ /* Set Node address */
+ if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0) /* SROM absent, so read MAC address from ID Table */
+ {
+ outl(0x10000, db->ioaddr + DCR0); //Diagnosis mode
+ outl(0x1c0, db->ioaddr + DCR13); //Reset dianostic pointer port
+ outl(0, db->ioaddr + DCR14); //Clear reset port
+ outl(0x10, db->ioaddr + DCR14); //Reset ID Table pointer
+ outl(0, db->ioaddr + DCR14); //Clear reset port
+ outl(0, db->ioaddr + DCR13); //Clear CR13
+ outl(0x1b0, db->ioaddr + DCR13); //Select ID Table access port
+ //Read MAC address from CR14
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = inl(db->ioaddr + DCR14);
+ //Read end
+ outl(0, db->ioaddr + DCR13); //Clear CR13
+ outl(0, db->ioaddr + DCR0); //Clear CR0
+ udelay(10);
+ }
+ else /*Exist SROM*/
+ {
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = db->srom[20 + i];
+ }
+ err = register_netdev (dev);
+ if (err)
+ goto err_out_res;
+
+ printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev));
+
+ for (i = 0; i < 6; i++)
+ printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
+ printk(", irq %d.\n", dev->irq);
+
+ pci_set_master(pdev);
+
+ return 0;
+
+err_out_res:
+ pci_release_regions(pdev);
+err_out_nomem:
+ if(db->desc_pool_ptr)
+ pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
+ db->desc_pool_ptr, db->desc_pool_dma_ptr);
+
+ if(db->buf_pool_ptr != NULL)
+ pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ db->buf_pool_ptr, db->buf_pool_dma_ptr);
+err_out_disable:
+ pci_disable_device(pdev);
+err_out_free:
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(dev);
+
+ return err;
+}
+
+
+static void __devexit uli526x_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_remove_one()", 0);
+
+ pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
+ DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
+ db->desc_pool_dma_ptr);
+ pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ db->buf_pool_ptr, db->buf_pool_dma_ptr);
+ unregister_netdev(dev);
+ pci_release_regions(pdev);
+ free_netdev(dev); /* free board information */
+ pci_set_drvdata(pdev, NULL);
+ pci_disable_device(pdev);
+ ULI526X_DBUG(0, "uli526x_remove_one() exit", 0);
+}
+
+
+/*
+ * Open the interface.
+ * The interface is opened whenever "ifconfig" activates it.
+ */
+
+static int uli526x_open(struct net_device *dev)
+{
+ int ret;
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_open", 0);
+
+ ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
+ if (ret)
+ return ret;
+
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
+ db->tx_packet_cnt = 0;
+ db->rx_avail_cnt = 0;
+ db->link_failed = 1;
+ netif_carrier_off(dev);
+ db->wait_reset = 0;
+
+ db->NIC_capability = 0xf; /* All capability*/
+ db->PHY_reg4 = 0x1e0;
+
+ /* CR6 operation mode decision */
+ db->cr6_data |= ULI526X_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+
+ /* Initialize ULI526X board */
+ uli526x_init(dev);
+
+ /* Active System Interface */
+ netif_wake_queue(dev);
+
+ /* set and active a timer process */
+ init_timer(&db->timer);
+ db->timer.expires = ULI526X_TIMER_WUT + HZ * 2;
+ db->timer.data = (unsigned long)dev;
+ db->timer.function = &uli526x_timer;
+ add_timer(&db->timer);
+
+ return 0;
+}
+
+
+/* Initialize ULI526X board
+ * Reset ULI526X board
+ * Initialize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void uli526x_init(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = db->ioaddr;
+ u8 phy_tmp;
+ u16 phy_value;
+ u16 phy_reg_reset;
+
+ ULI526X_DBUG(0, "uli526x_init()", 0);
+
+ /* Reset M526x MAC controller */
+ outl(ULI526X_RESET, ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : In some boards,M5261/M5263 phy address != 1 */
+ db->phy_addr = 1;
+ for(phy_tmp=0;phy_tmp<32;phy_tmp++)
+ {
+ phy_value=phy_read(db->ioaddr,phy_tmp,3,db->chip_id);//peer add
+ if(phy_value != 0xffff&&phy_value!=0)
+ {
+ db->phy_addr = phy_tmp;
+ break;
+ }
+ }
+ if(phy_tmp == 32)
+ printk(KERN_WARNING "Can not find the phy address!!!");
+ /* Parser SROM and media mode */
+ db->media_mode = uli526x_media_mode;
+
+ /* Phyxcer capability setting */
+ phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
+ phy_reg_reset = (phy_reg_reset | 0x8000);
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+ udelay(500);
+
+ /* Process Phyxcer Media Mode */
+ uli526x_set_phyxcer(db);
+
+ /* Media Mode Process */
+ if ( !(db->media_mode & ULI526X_AUTO) )
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initialize Transmit/Receive decriptor and CR3/4 */
+ uli526x_descriptor_init(db, ioaddr);
+
+ /* Init CR6 to program M526X operation */
+ update_cr6(db->cr6_data, ioaddr);
+
+ /* Send setup frame */
+ send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, ioaddr + DCR7);
+
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, ioaddr + DCR15);
+
+ /* Enable ULI526X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC;
+ update_cr6(db->cr6_data, ioaddr);
+}
+
+
+/*
+ * Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+
+static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ struct tx_desc *txptr;
+ unsigned long flags;
+
+ ULI526X_DBUG(0, "uli526x_start_xmit", 0);
+
+ /* Resource flag check */
+ netif_stop_queue(dev);
+
+ /* Too large packet check */
+ if (skb->len > MAX_PACKET_SIZE) {
+ printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ /* No Tx resource check, it never happen nromally */
+ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
+ spin_unlock_irqrestore(&db->lock, flags);
+ printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt);
+ return 1;
+ }
+
+ /* Disable NIC interrupt */
+ outl(0, dev->base_addr + DCR7);
+
+ /* transmit this packet */
+ txptr = db->tx_insert_ptr;
+ memcpy(txptr->tx_buf_ptr, skb->data, skb->len);
+ txptr->tdes1 = cpu_to_le32(0xe1000000 | skb->len);
+
+ /* Point to next transmit free descriptor */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+
+ /* Transmit Packet Process */
+ if ( (db->tx_packet_cnt < TX_DESC_CNT) ) {
+ txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
+ db->tx_packet_cnt++; /* Ready to send */
+ outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ dev->trans_start = jiffies; /* saved time stamp */
+ }
+
+ /* Tx resource check */
+ if ( db->tx_packet_cnt < TX_FREE_DESC_CNT )
+ netif_wake_queue(dev);
+
+ /* Restore CR7 to enable interrupt */
+ spin_unlock_irqrestore(&db->lock, flags);
+ outl(db->cr7_data, dev->base_addr + DCR7);
+
+ /* free this SKB */
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+
+/*
+ * Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+
+static int uli526x_stop(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = dev->base_addr;
+
+ ULI526X_DBUG(0, "uli526x_stop", 0);
+
+ /* disable system */
+ netif_stop_queue(dev);
+
+ /* deleted timer */
+ del_timer_sync(&db->timer);
+
+ /* Reset & stop ULI526X board */
+ outl(ULI526X_RESET, ioaddr + DCR0);
+ udelay(5);
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+
+ /* free interrupt */
+ free_irq(dev->irq, dev);
+
+ /* free allocated rx buffer */
+ uli526x_free_rxbuffer(db);
+
+#if 0
+ /* show statistic counter */
+ printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+ db->tx_fifo_underrun, db->tx_excessive_collision,
+ db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
+ db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
+ db->reset_fatal, db->reset_TXtimeout);
+#endif
+
+ return 0;
+}
+
+
+/*
+ * M5261/M5263 insterrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+
+static irqreturn_t uli526x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ if (!dev) {
+ ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
+ return IRQ_NONE;
+ }
+
+ spin_lock_irqsave(&db->lock, flags);
+ outl(0, ioaddr + DCR7);
+
+ /* Got ULI526X status */
+ db->cr5_data = inl(ioaddr + DCR5);
+ outl(db->cr5_data, ioaddr + DCR5);
+ if ( !(db->cr5_data & 0x180c1) ) {
+ spin_unlock_irqrestore(&db->lock, flags);
+ outl(db->cr7_data, ioaddr + DCR7);
+ return IRQ_HANDLED;
+ }
+
+ /* Check system status */
+ if (db->cr5_data & 0x2000) {
+ /* system bus error happen */
+ ULI526X_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
+ db->reset_fatal++;
+ db->wait_reset = 1; /* Need to RESET */
+ spin_unlock_irqrestore(&db->lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ /* Received the coming packet */
+ if ( (db->cr5_data & 0x40) && db->rx_avail_cnt )
+ uli526x_rx_packet(dev, db);
+
+ /* reallocate rx descriptor buffer */
+ if (db->rx_avail_cnt<RX_DESC_CNT)
+ allocate_rx_buffer(db);
+
+ /* Free the transmitted descriptor */
+ if ( db->cr5_data & 0x01)
+ uli526x_free_tx_pkt(dev, db);
+
+ /* Restore CR7 to enable interrupt mask */
+ outl(db->cr7_data, ioaddr + DCR7);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * Free TX resource after TX complete
+ */
+
+static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_info * db)
+{
+ struct tx_desc *txptr;
+ u32 tdes0;
+
+ txptr = db->tx_remove_ptr;
+ while(db->tx_packet_cnt) {
+ tdes0 = le32_to_cpu(txptr->tdes0);
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ if (tdes0 & 0x80000000)
+ break;
+
+ /* A packet sent completed */
+ db->tx_packet_cnt--;
+ db->stats.tx_packets++;
+
+ /* Transmit statistic counter */
+ if ( tdes0 != 0x7fffffff ) {
+ /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
+ db->stats.collisions += (tdes0 >> 3) & 0xf;
+ db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+ if (tdes0 & TDES0_ERR_MASK) {
+ db->stats.tx_errors++;
+ if (tdes0 & 0x0002) { /* UnderRun */
+ db->tx_fifo_underrun++;
+ if ( !(db->cr6_data & CR6_SFT) ) {
+ db->cr6_data = db->cr6_data | CR6_SFT;
+ update_cr6(db->cr6_data, db->ioaddr);
+ }
+ }
+ if (tdes0 & 0x0100)
+ db->tx_excessive_collision++;
+ if (tdes0 & 0x0200)
+ db->tx_late_collision++;
+ if (tdes0 & 0x0400)
+ db->tx_no_carrier++;
+ if (tdes0 & 0x0800)
+ db->tx_loss_carrier++;
+ if (tdes0 & 0x4000)
+ db->tx_jabber_timeout++;
+ }
+ }
+
+ txptr = txptr->next_tx_desc;
+ }/* End of while */
+
+ /* Update TX remove pointer to next */
+ db->tx_remove_ptr = txptr;
+
+ /* Resource available check */
+ if ( db->tx_packet_cnt < TX_WAKE_DESC_CNT )
+ netif_wake_queue(dev); /* Active upper layer, send again */
+}
+
+
+/*
+ * Receive the come packet and pass to upper layer
+ */
+
+static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info * db)
+{
+ struct rx_desc *rxptr;
+ struct sk_buff *skb;
+ int rxlen;
+ u32 rdes0;
+
+ rxptr = db->rx_ready_ptr;
+
+ while(db->rx_avail_cnt) {
+ rdes0 = le32_to_cpu(rxptr->rdes0);
+ if (rdes0 & 0x80000000) /* packet owner check */
+ {
+ break;
+ }
+
+ db->rx_avail_cnt--;
+ db->interval_rx_cnt++;
+
+ pci_unmap_single(db->pdev, le32_to_cpu(rxptr->rdes2), RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
+ if ( (rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ /* reuse this SKB */
+ ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ( (rdes0 >> 16) & 0x3fff) - 4;
+
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ /* This is a error packet */
+ //printk(DRV_NAME ": rdes0: %lx\n", rdes0);
+ db->stats.rx_errors++;
+ if (rdes0 & 1)
+ db->stats.rx_fifo_errors++;
+ if (rdes0 & 2)
+ db->stats.rx_crc_errors++;
+ if (rdes0 & 0x80)
+ db->stats.rx_length_errors++;
+ }
+
+ if ( !(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
+ skb = rxptr->rx_skb_ptr;
+
+ /* Good packet, send to upper layer */
+ /* Shorst packet used new SKB */
+ if ( (rxlen < RX_COPY_SIZE) &&
+ ( (skb = dev_alloc_skb(rxlen + 2) )
+ != NULL) ) {
+ /* size less than COPY_SIZE, allocate a rxlen SKB */
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16byte align */
+ memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ } else {
+ skb->dev = dev;
+ skb_put(skb, rxlen);
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ db->stats.rx_packets++;
+ db->stats.rx_bytes += rxlen;
+
+ } else {
+ /* Reuse SKB buffer when the packet is error */
+ ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+ uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
+ }
+ }
+
+ rxptr = rxptr->next_rx_desc;
+ }
+
+ db->rx_ready_ptr = rxptr;
+}
+
+
+/*
+ * Get statistics from driver.
+ */
+
+static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_get_stats", 0);
+ return &db->stats;
+}
+
+
+/*
+ * Set ULI526X multicast address
+ */
+
+static void uli526x_set_filter_mode(struct net_device * dev)
+{
+ struct uli526x_board_info *db = dev->priv;
+ unsigned long flags;
+
+ ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
+ spin_lock_irqsave(&db->lock, flags);
+
+ if (dev->flags & IFF_PROMISC) {
+ ULI526X_DBUG(0, "Enable PROM Mode", 0);
+ db->cr6_data |= CR6_PM | CR6_PBF;
+ update_cr6(db->cr6_data, db->ioaddr);
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) {
+ ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);
+ db->cr6_data &= ~(CR6_PM | CR6_PBF);
+ db->cr6_data |= CR6_PAM;
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ ULI526X_DBUG(0, "Set multicast address", dev->mc_count);
+ send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */
+ spin_unlock_irqrestore(&db->lock, flags);
+}
+
+static void
+ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
+{
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_MII);
+
+ ecmd->advertising = (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_Autoneg |
+ ADVERTISED_MII);
+
+
+ ecmd->port = PORT_MII;
+ ecmd->phy_address = db->phy_addr;
+
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ ecmd->speed = 10;
+ ecmd->duplex = DUPLEX_HALF;
+
+ if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+ {
+ ecmd->speed = 100;
+ }
+ if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+ {
+ ecmd->duplex = DUPLEX_FULL;
+ }
+ if(db->link_failed)
+ {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ if (db->media_mode & ULI526X_AUTO)
+ {
+ ecmd->autoneg = AUTONEG_ENABLE;
+ }
+}
+
+static void netdev_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ if (np->pdev)
+ strcpy(info->bus_info, pci_name(np->pdev));
+ else
+ sprintf(info->bus_info, "EISA 0x%lx %d",
+ dev->base_addr, dev->irq);
+}
+
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ ULi_ethtool_gset(np, cmd);
+
+ return 0;
+}
+
+static u32 netdev_get_link(struct net_device *dev) {
+ struct uli526x_board_info *np = netdev_priv(dev);
+
+ if(np->link_failed)
+ return 0;
+ else
+ return 1;
+}
+
+static void uli526x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ wol->supported = WAKE_PHY | WAKE_MAGIC;
+ wol->wolopts = 0;
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+ .get_drvinfo = netdev_get_drvinfo,
+ .get_settings = netdev_get_settings,
+ .get_link = netdev_get_link,
+ .get_wol = uli526x_get_wol,
+};
+
+/*
+ * A periodic timer routine
+ * Dynamic media sense, allocate Rx buffer...
+ */
+
+static void uli526x_timer(unsigned long data)
+{
+ u32 tmp_cr8;
+ unsigned char tmp_cr12=0;
+ struct net_device *dev = (struct net_device *) data;
+ struct uli526x_board_info *db = netdev_priv(dev);
+ unsigned long flags;
+ u8 TmpSpeed=10;
+
+ //ULI526X_DBUG(0, "uli526x_timer()", 0);
+ spin_lock_irqsave(&db->lock, flags);
+
+
+ /* Dynamic reset ULI526X : system error or transmit time-out */
+ tmp_cr8 = inl(db->ioaddr + DCR8);
+ if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
+ db->reset_cr8++;
+ db->wait_reset = 1;
+ }
+ db->interval_rx_cnt = 0;
+
+ /* TX polling kick monitor */
+ if ( db->tx_packet_cnt &&
+ time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
+ outl(0x1, dev->base_addr + DCR1); // Tx polling again
+
+ // TX Timeout
+ if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
+ db->reset_TXtimeout++;
+ db->wait_reset = 1;
+ printk( "%s: Tx timeout - resetting\n",
+ dev->name);
+ }
+ }
+
+ if (db->wait_reset) {
+ ULI526X_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);
+ db->reset_count++;
+ uli526x_dynamic_reset(dev);
+ db->timer.expires = ULI526X_TIMER_WUT;
+ add_timer(&db->timer);
+ spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+
+ /* Link status check, Dynamic media type change */
+ if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)
+ tmp_cr12 = 3;
+
+ if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
+ /* Link Failed */
+ ULI526X_DBUG(0, "Link Failed", tmp_cr12);
+ netif_carrier_off(dev);
+ printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+ db->link_failed = 1;
+
+ /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
+ /* AUTO don't need */
+ if ( !(db->media_mode & 0x8) )
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+
+ /* AUTO mode, if INT phyxcer link failed, select EXT device */
+ if (db->media_mode & ULI526X_AUTO) {
+ db->cr6_data&=~0x00000200; /* bit9=0, HD mode */
+ update_cr6(db->cr6_data, db->ioaddr);
+ }
+ } else
+ if ((tmp_cr12 & 0x3) && db->link_failed) {
+ ULI526X_DBUG(0, "Link link OK", tmp_cr12);
+ db->link_failed = 0;
+
+ /* Auto Sense Speed */
+ if ( (db->media_mode & ULI526X_AUTO) &&
+ uli526x_sense_speed(db) )
+ db->link_failed = 1;
+ uli526x_process_mode(db);
+
+ if(db->link_failed==0)
+ {
+ if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
+ {
+ TmpSpeed = 100;
+ }
+ if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed);
+ }
+ else
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed);
+ }
+ netif_carrier_on(dev);
+ }
+ /* SHOW_MEDIA_TYPE(db->op_mode); */
+ }
+ else if(!(tmp_cr12 & 0x3) && db->link_failed)
+ {
+ if(db->init==1)
+ {
+ printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);
+ netif_carrier_off(dev);
+ }
+ }
+ db->init=0;
+
+ /* Timer active again */
+ db->timer.expires = ULI526X_TIMER_WUT;
+ add_timer(&db->timer);
+ spin_unlock_irqrestore(&db->lock, flags);
+}
+
+
+/*
+ * Dynamic reset the ULI526X board
+ * Stop ULI526X board
+ * Free Tx/Rx allocated memory
+ * Reset ULI526X board
+ * Re-initialize ULI526X board
+ */
+
+static void uli526x_dynamic_reset(struct net_device *dev)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+
+ ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0);
+
+ /* Sopt MAC controller */
+ db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
+ update_cr6(db->cr6_data, dev->base_addr);
+ outl(0, dev->base_addr + DCR7); /* Disable Interrupt */
+ outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
+
+ /* Disable upper layer interface */
+ netif_stop_queue(dev);
+
+ /* Free Rx Allocate buffer */
+ uli526x_free_rxbuffer(db);
+
+ /* system variable init */
+ db->tx_packet_cnt = 0;
+ db->rx_avail_cnt = 0;
+ db->link_failed = 1;
+ db->init=1;
+ db->wait_reset = 0;
+
+ /* Re-initialize ULI526X board */
+ uli526x_init(dev);
+
+ /* Restart upper layer interface */
+ netif_wake_queue(dev);
+}
+
+
+/*
+ * free all allocated rx buffer
+ */
+
+static void uli526x_free_rxbuffer(struct uli526x_board_info * db)
+{
+ ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);
+
+ /* free allocated rx buffer */
+ while (db->rx_avail_cnt) {
+ dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
+ db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;
+ db->rx_avail_cnt--;
+ }
+}
+
+
+/*
+ * Reuse the SK buffer
+ */
+
+static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * skb)
+{
+ struct rx_desc *rxptr = db->rx_insert_ptr;
+
+ if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
+ rxptr->rx_skb_ptr = skb;
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ db->rx_avail_cnt++;
+ db->rx_insert_ptr = rxptr->next_rx_desc;
+ } else
+ ULI526X_DBUG(0, "SK Buffer reuse method error", db->rx_avail_cnt);
+}
+
+
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr)
+{
+ struct tx_desc *tmp_tx;
+ struct rx_desc *tmp_rx;
+ unsigned char *tmp_buf;
+ dma_addr_t tmp_tx_dma, tmp_rx_dma;
+ dma_addr_t tmp_buf_dma;
+ int i;
+
+ ULI526X_DBUG(0, "uli526x_descriptor_init()", 0);
+
+ /* tx descriptor start pointer */
+ db->tx_insert_ptr = db->first_tx_desc;
+ db->tx_remove_ptr = db->first_tx_desc;
+ outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->first_rx_desc_dma = db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->rx_insert_ptr = db->first_rx_desc;
+ db->rx_ready_ptr = db->first_rx_desc;
+ outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+
+ /* Init Transmit chain */
+ tmp_buf = db->buf_pool_start;
+ tmp_buf_dma = db->buf_pool_dma_start;
+ tmp_tx_dma = db->first_tx_desc_dma;
+ for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
+ tmp_tx->tx_buf_ptr = tmp_buf;
+ tmp_tx->tdes0 = cpu_to_le32(0);
+ tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+ tmp_tx_dma += sizeof(struct tx_desc);
+ tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
+ tmp_tx->next_tx_desc = tmp_tx + 1;
+ tmp_buf = tmp_buf + TX_BUF_ALLOC;
+ tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
+ }
+ (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
+ tmp_tx->next_tx_desc = db->first_tx_desc;
+
+ /* Init Receive descriptor chain */
+ tmp_rx_dma=db->first_rx_desc_dma;
+ for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {
+ tmp_rx->rdes0 = cpu_to_le32(0);
+ tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+ tmp_rx_dma += sizeof(struct rx_desc);
+ tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
+ tmp_rx->next_rx_desc = tmp_rx + 1;
+ }
+ (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
+ tmp_rx->next_rx_desc = db->first_rx_desc;
+
+ /* pre-allocate Rx buffer */
+ allocate_rx_buffer(db);
+}
+
+
+/*
+ * Update CR6 value
+ * Firstly stop ULI526X, then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+
+/*
+ * Send a setup frame for M5261/M5263
+ * This setup frame initialize ULI526X address filter mode
+ */
+
+static void send_filter_frame(struct net_device *dev, int mc_cnt)
+{
+ struct uli526x_board_info *db = netdev_priv(dev);
+ struct dev_mc_list *mcptr;
+ struct tx_desc *txptr;
+ u16 * addrptr;
+ u32 * suptr;
+ int i;
+
+ ULI526X_DBUG(0, "send_filter_frame()", 0);
+
+ txptr = db->tx_insert_ptr;
+ suptr = (u32 *) txptr->tx_buf_ptr;
+
+ /* Node address */
+ addrptr = (u16 *) dev->dev_addr;
+ *suptr++ = addrptr[0];
+ *suptr++ = addrptr[1];
+ *suptr++ = addrptr[2];
+
+ /* broadcast address */
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+
+ /* fit the multicast address */
+ for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ addrptr = (u16 *) mcptr->dmi_addr;
+ *suptr++ = addrptr[0];
+ *suptr++ = addrptr[1];
+ *suptr++ = addrptr[2];
+ }
+
+ for (; i<14; i++) {
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ *suptr++ = 0xffff;
+ }
+
+ /* prepare the setup frame */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+ txptr->tdes1 = cpu_to_le32(0x890000c0);
+
+ /* Resource Check and Send the setup packet */
+ if (db->tx_packet_cnt < TX_DESC_CNT) {
+ /* Resource Empty */
+ db->tx_packet_cnt++;
+ txptr->tdes0 = cpu_to_le32(0x80000000);
+ update_cr6(db->cr6_data | 0x2000, dev->base_addr);
+ outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, dev->base_addr);
+ dev->trans_start = jiffies;
+ } else
+ printk(KERN_ERR DRV_NAME ": No Tx resource - Send_filter_frame!\n");
+}
+
+
+/*
+ * Allocate rx buffer,
+ * As possible as allocate maxiumn Rx buffer
+ */
+
+static void allocate_rx_buffer(struct uli526x_board_info *db)
+{
+ struct rx_desc *rxptr;
+ struct sk_buff *skb;
+
+ rxptr = db->rx_insert_ptr;
+
+ while(db->rx_avail_cnt < RX_DESC_CNT) {
+ if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
+ break;
+ rxptr->rx_skb_ptr = skb; /* FIXME (?) */
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ wmb();
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ rxptr = rxptr->next_rx_desc;
+ db->rx_avail_cnt++;
+ }
+
+ db->rx_insert_ptr = rxptr;
+}
+
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+
+/*
+ * Auto sense the media mode
+ */
+
+static u8 uli526x_sense_speed(struct uli526x_board_info * db)
+{
+ u8 ErrFlag = 0;
+ u16 phy_mode;
+
+ phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+ phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+
+ if ( (phy_mode & 0x24) == 0x24 ) {
+
+ phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
+ if(phy_mode&0x8000)
+ phy_mode = 0x8000;
+ else if(phy_mode&0x4000)
+ phy_mode = 0x4000;
+ else if(phy_mode&0x2000)
+ phy_mode = 0x2000;
+ else
+ phy_mode = 0x1000;
+
+ /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
+ switch (phy_mode) {
+ case 0x1000: db->op_mode = ULI526X_10MHF; break;
+ case 0x2000: db->op_mode = ULI526X_10MFD; break;
+ case 0x4000: db->op_mode = ULI526X_100MHF; break;
+ case 0x8000: db->op_mode = ULI526X_100MFD; break;
+ default: db->op_mode = ULI526X_10MHF; ErrFlag = 1; break;
+ }
+ } else {
+ db->op_mode = ULI526X_10MHF;
+ ULI526X_DBUG(0, "Link Failed :", phy_mode);
+ ErrFlag = 1;
+ }
+
+ return ErrFlag;
+}
+
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void uli526x_set_phyxcer(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & ULI526X_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch(db->media_mode) {
+ case ULI526X_10MHF: phy_reg |= 0x20; break;
+ case ULI526X_10MFD: phy_reg |= 0x40; break;
+ case ULI526X_100MHF: phy_reg |= 0x80; break;
+ case ULI526X_100MFD: phy_reg |= 0x100; break;
+ }
+
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if ( !(phy_reg & 0x01e0)) {
+ phy_reg|=db->PHY_reg4;
+ db->media_mode|=ULI526X_AUTO;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+ udelay(50);
+}
+
+
+/*
+ * Process op-mode
+ AUTO mode : PHY controller in Auto-negotiation Mode
+ * Force mode: PHY controller in force mode with HUB
+ * N-way force capability with SWITCH
+ */
+
+static void uli526x_process_mode(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Full Duplex Mode Check */
+ if (db->op_mode & 0x4)
+ db->cr6_data |= CR6_FDM; /* Set Full Duplex Bit */
+ else
+ db->cr6_data &= ~CR6_FDM; /* Clear Full Duplex Bit */
+
+ update_cr6(db->cr6_data, db->ioaddr);
+
+ /* 10/100M phyxcer force mode need */
+ if ( !(db->media_mode & 0x8)) {
+ /* Forece Mode */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);
+ if ( !(phy_reg & 0x1) ) {
+ /* parter without N-Way capability */
+ phy_reg = 0x0;
+ switch(db->op_mode) {
+ case ULI526X_10MHF: phy_reg = 0x0; break;
+ case ULI526X_10MFD: phy_reg = 0x100; break;
+ case ULI526X_100MHF: phy_reg = 0x2000; break;
+ case ULI526X_100MFD: phy_reg = 0x2100; break;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+ phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+ }
+ }
+}
+
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if(chip_id == PCI_ULI5263_ID)
+ {
+ phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
+ return;
+ }
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Write a word data to PHY controller */
+ for ( i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+}
+
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if(chip_id == PCI_ULI5263_ID)
+ return phy_readby_cr10(iobase, phy_addr, offset);
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr, chip_id);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr, chip_id);
+ }
+
+ return phy_data;
+}
+
+static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+{
+ unsigned long ioaddr,cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x08000000;
+ outl(cr10_value,ioaddr);
+ udelay(1);
+ while(1)
+ {
+ cr10_value = inl(ioaddr);
+ if(cr10_value&0x10000000)
+ break;
+ }
+ return (cr10_value&0x0ffff);
+}
+
+static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
+{
+ unsigned long ioaddr,cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
+ outl(cr10_value,ioaddr);
+ udelay(1);
+}
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+{
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+{
+ u16 phy_data;
+
+ outl(0x50000 , ioaddr);
+ udelay(1);
+ phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
+ outl(0x40000 , ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+
+static struct pci_device_id uli526x_pci_tbl[] = {
+ { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
+ { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, uli526x_pci_tbl);
+
+
+static struct pci_driver uli526x_driver = {
+ .name = "uli526x",
+ .id_table = uli526x_pci_tbl,
+ .probe = uli526x_init_one,
+ .remove = __devexit_p(uli526x_remove_one),
+};
+
+MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw");
+MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM(mode, "i");
+MODULE_PARM(cr6set, "i");
+MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)");
+MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA");
+
+/* Description:
+ * when user used insmod to add module, system invoked init_module()
+ * to register the services.
+ */
+
+static int __init uli526x_init_module(void)
+{
+ int rc;
+
+ printk(version);
+ printed_version = 1;
+
+ ULI526X_DBUG(0, "init_module() ", debug);
+
+ if (debug)
+ uli526x_debug = debug; /* set debug flag */
+ if (cr6set)
+ uli526x_cr6_user_set = cr6set;
+
+ switch(mode) {
+ case ULI526X_10MHF:
+ case ULI526X_100MHF:
+ case ULI526X_10MFD:
+ case ULI526X_100MFD:
+ uli526x_media_mode = mode;
+ break;
+ default:uli526x_media_mode = ULI526X_AUTO;
+ break;
+ }
+
+ rc = pci_module_init(&uli526x_driver);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+
+/*
+ * Description:
+ * when user used rmmod to delete module, system invoked clean_module()
+ * to un-register all registered services.
+ */
+
+static void __exit uli526x_cleanup_module(void)
+{
+ ULI526X_DBUG(0, "uli526x_clean_module() ", debug);
+ pci_unregister_driver(&uli526x_driver);
+}
+
+module_init(uli526x_init_module);
+module_exit(uli526x_cleanup_module);
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 26cc4f6378c7..60d1e05ab732 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -117,7 +117,7 @@ static int xircom_open(struct net_device *dev);
static int xircom_close(struct net_device *dev);
static void xircom_up(struct xircom_private *card);
static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-#if CONFIG_NET_POLL_CONTROLLER
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev);
#endif
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index effab0b9adca..50b8c6754b1e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -18,6 +18,9 @@
/*
* Changes:
*
+ * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
+ * Add TUNSETLINK ioctl to set the link encapsulation
+ *
* Mark Smith <markzzzsmith@yahoo.com.au>
* Use random_ether_addr() for tap MAC address.
*
@@ -612,6 +615,18 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
break;
+ case TUNSETLINK:
+ /* Only allow setting the type when the interface is down */
+ if (tun->dev->flags & IFF_UP) {
+ DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
+ tun->dev->name);
+ return -EBUSY;
+ } else {
+ tun->dev->type = (int) arg;
+ DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
+ }
+ break;
+
#ifdef TUN_DEBUG
case TUNSETDEBUG:
tun->debug = arg;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index ecfa6f8805ce..4c76cb794bfb 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
TYPHOON_STATUS_WAITING_FOR_HOST)
goto out;
- if(wait_type == WaitSleep) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } else
+ if(wait_type == WaitSleep)
+ schedule_timeout_uninterruptible(1);
+ else
udelay(TYPHOON_UDELAY);
}
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index fc7738ffbfff..241871589283 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -490,6 +490,8 @@ struct rhine_private {
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if;
+ struct work_struct tx_timeout_task;
+ struct work_struct check_media_task;
void __iomem *base;
};
@@ -497,6 +499,8 @@ 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 rhine_open(struct net_device *dev);
static void rhine_tx_timeout(struct net_device *dev);
+static void rhine_tx_timeout_task(struct net_device *dev);
+static void rhine_check_media_task(struct net_device *dev);
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void rhine_tx(struct net_device *dev);
@@ -814,8 +818,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
for (i = 0; i < 6; i++)
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->dev_addr)) {
+ if (!is_valid_ether_addr(dev->perm_addr)) {
rc = -EIO;
printk(KERN_ERR "Invalid MAC address\n");
goto err_out_unmap;
@@ -850,6 +855,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
+ INIT_WORK(&rp->tx_timeout_task,
+ (void (*)(void *))rhine_tx_timeout_task, dev);
+
+ INIT_WORK(&rp->check_media_task,
+ (void (*)(void *))rhine_check_media_task, dev);
+
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
@@ -1076,6 +1087,11 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
ioaddr + ChipCmd1);
}
+static void rhine_check_media_task(struct net_device *dev)
+{
+ rhine_check_media(dev, 0);
+}
+
static void init_registers(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
@@ -1129,8 +1145,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
if (quirks & rqRhineI) {
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
- /* Can be called from ISR. Evil. */
- mdelay(1);
+ /* Do not call from ISR! */
+ msleep(1);
/* 0x80 must be set immediately before turning it off */
iowrite8(0x80, ioaddr + MIICmd);
@@ -1220,6 +1236,16 @@ static int rhine_open(struct net_device *dev)
static void rhine_tx_timeout(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
+
+ /*
+ * Move bulk of work outside of interrupt context
+ */
+ schedule_work(&rp->tx_timeout_task);
+}
+
+static void rhine_tx_timeout_task(struct net_device *dev)
+{
+ struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
@@ -1625,7 +1651,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
spin_lock(&rp->lock);
if (intr_status & IntrLinkChange)
- rhine_check_media(dev, 0);
+ schedule_work(&rp->check_media_task);
if (intr_status & IntrStatsMax) {
rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1829,6 +1855,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
.set_wol = rhine_set_wol,
.get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1872,6 +1899,9 @@ static int rhine_close(struct net_device *dev)
spin_unlock_irq(&rp->lock);
free_irq(rp->pdev->irq, dev);
+
+ flush_scheduled_work();
+
free_rbufs(dev);
free_tbufs(dev);
free_ring(dev);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index abc5cee6eedc..a368d08e7d19 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1212,10 +1212,8 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
velocity_free_td_ring_entry(vptr, j, i);
}
- if (vptr->td_infos[j]) {
- kfree(vptr->td_infos[j]);
- vptr->td_infos[j] = NULL;
- }
+ kfree(vptr->td_infos[j]);
+ vptr->td_infos[j] = NULL;
}
}
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7ff814fd65d0..e392ee8b37a1 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -400,7 +400,7 @@ static int __init cosa_init(void)
goto out_chrdev;
}
for (i=0; i<nr_cards; i++) {
- class_device_create(cosa_class, MKDEV(cosa_major, i),
+ class_device_create(cosa_class, NULL, MKDEV(cosa_major, i),
NULL, "cosa%d", i);
err = devfs_mk_cdev(MKDEV(cosa_major, i),
S_IFCHR|S_IRUSR|S_IWUSR,
@@ -1617,8 +1617,7 @@ static int get_wait_data(struct cosa_data *cosa)
return r;
}
/* sleep if not ready to read */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
@@ -1644,8 +1643,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
}
#if 0
/* sleep if not ready to read */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
#endif
}
printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 6e74af62ca08..e6d005726aad 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -56,7 +56,7 @@
#include <linux/sched.h> /* for jiffies, HZ, etc. */
#include <linux/cycx_drv.h> /* API definitions */
#include <linux/cycx_cfm.h> /* CYCX firmware module definitions */
-#include <linux/delay.h> /* udelay */
+#include <linux/delay.h> /* udelay, msleep_interruptible */
#include <asm/io.h> /* read[wl], write[wl], ioremap, iounmap */
#define MOD_VERSION 0
@@ -74,7 +74,6 @@ static int reset_cyc2x(void __iomem *addr);
static int detect_cyc2x(void __iomem *addr);
/* Miscellaneous functions */
-static void delay_cycx(int sec);
static int get_option_index(long *optlist, long optval);
static u16 checksum(u8 *buf, u32 len);
@@ -110,7 +109,7 @@ static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
* < 0 error.
* Context: process */
-int __init cycx_drv_init(void)
+static int __init cycx_drv_init(void)
{
printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
copyright);
@@ -120,7 +119,7 @@ int __init cycx_drv_init(void)
/* Module 'remove' entry point.
* o release all remaining system resources */
-void cycx_drv_cleanup(void)
+static void cycx_drv_cleanup(void)
{
}
@@ -185,8 +184,7 @@ int cycx_down(struct cycx_hw *hw)
}
/* Enable interrupt generation. */
-EXPORT_SYMBOL(cycx_inten);
-void cycx_inten(struct cycx_hw *hw)
+static void cycx_inten(struct cycx_hw *hw)
{
writeb(0, hw->dpmbase);
}
@@ -259,7 +257,7 @@ static int memory_exists(void __iomem *addr)
if (readw(addr + 0x10) == TEST_PATTERN)
return 1;
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
return 0;
@@ -316,7 +314,7 @@ static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len)
/* 80186 was in hold, go */
writeb(0, addr + START_CPU);
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
/* Load data.bin file through boot (reset) interface. */
@@ -462,13 +460,13 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size);
/* reset is waiting for boot */
writew(GEN_POWER_ON, pt_cycld);
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
for (j = 0 ; j < 3 ; j++)
if (!readw(pt_cycld))
goto reset_loaded;
else
- delay_cycx(1);
+ msleep_interruptible(1 * 1000);
}
printk(KERN_ERR "%s: reset not started.\n", modname);
@@ -495,7 +493,7 @@ reset_loaded:
/* Arthur Ganzert's tip: wait a while after the firmware loading...
seg abr 26 17:17:12 EST 1999 - acme */
- delay_cycx(7);
+ msleep_interruptible(7 * 1000);
printk(KERN_INFO "%s: firmware loaded!\n", modname);
/* enable interrupts */
@@ -547,20 +545,13 @@ static int get_option_index(long *optlist, long optval)
static int reset_cyc2x(void __iomem *addr)
{
writeb(0, addr + RST_ENABLE);
- delay_cycx(2);
+ msleep_interruptible(2 * 1000);
writeb(0, addr + RST_DISABLE);
- delay_cycx(2);
+ msleep_interruptible(2 * 1000);
return memory_exists(addr);
}
-/* Delay */
-static void delay_cycx(int sec)
-{
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(sec * HZ);
-}
-
/* Calculate 16-bit CRC using CCITT polynomial. */
static u16 checksum(u8 *buf, u32 len)
{
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 7b48064364dc..430b1f630fb4 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_array; /* adapter data space */
* < 0 error.
* Context: process
*/
-int __init cycx_init(void)
+static int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 02d57c0b4243..a631d1c2fa14 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -78,6 +78,7 @@
#define CYCLOMX_X25_DEBUG 1
+#include <linux/ctype.h> /* isdigit() */
#include <linux/errno.h> /* return codes */
#include <linux/if_arp.h> /* ARPHRD_HWX25 */
#include <linux/kernel.h> /* printk(), and other useful stuff */
@@ -418,7 +419,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
/* Set channel timeouts (default if not specified) */
chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
- } else if (is_digit(conf->addr[0])) { /* PVC */
+ } else if (isdigit(conf->addr[0])) { /* PVC */
s16 lcn = dec_to_uint(conf->addr, 0);
if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
@@ -1531,7 +1532,7 @@ static unsigned dec_to_uint(u8 *str, int len)
if (!len)
len = strlen(str);
- for (; len && is_digit(*str); ++str, --len)
+ for (; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned) '0');
return val;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 520a77a798e2..2f61a47b4716 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv,
return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
}
-int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
- const char *msg)
+static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
+ struct net_device *dev, const char *msg)
{
int ret = 0;
@@ -466,8 +466,9 @@ int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
return ret;
}
-void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
- char *msg)
+static void dscc4_tx_print(struct net_device *dev,
+ struct dscc4_dev_priv *dpriv,
+ char *msg)
{
printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
@@ -507,7 +508,8 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv)
}
}
-inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
+ struct net_device *dev)
{
unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
struct RxFD *rx_fd = dpriv->rx_fd + dirty;
@@ -542,8 +544,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
msg, i);
goto done;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
@@ -588,8 +589,7 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv)
(dpriv->iqtx[cur] & Xpr))
break;
smp_rmb();
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
} while (++i > 0);
return (i >= 0 ) ? i : -EAGAIN;
@@ -1035,8 +1035,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
/* Flush posted writes */
readl(ioaddr + GSTAR);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
for (i = 0; i < 16; i++)
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
@@ -1894,7 +1893,7 @@ try:
* It failed and locked solid. Thus the introduction of a dummy skb.
* Problem is acknowledged in errata sheet DS5. Joy :o/
*/
-struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
{
struct sk_buff *skb;
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 2c83cca34b86..7981a2c7906e 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
/*
* Modules parameters and associated varaibles
*/
-int fst_txq_low = FST_LOW_WATER_MARK;
-int fst_txq_high = FST_HIGH_WATER_MARK;
-int fst_max_reads = 7;
-int fst_excluded_cards = 0;
-int fst_excluded_list[FST_MAX_CARDS];
+static int fst_txq_low = FST_LOW_WATER_MARK;
+static int fst_txq_high = FST_HIGH_WATER_MARK;
+static int fst_max_reads = 7;
+static int fst_excluded_cards = 0;
+static int fst_excluded_list[FST_MAX_CARDS];
module_param(fst_txq_low, int, 0);
module_param(fst_txq_high, int, 0);
@@ -572,13 +572,13 @@ static void do_bottom_half_rx(struct fst_card_info *card);
static void fst_process_tx_work_q(unsigned long work_q);
static void fst_process_int_work_q(unsigned long work_q);
-DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
-struct fst_card_info *fst_card_array[FST_MAX_CARDS];
-spinlock_t fst_work_q_lock;
-u64 fst_work_txq;
-u64 fst_work_intq;
+static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+static spinlock_t fst_work_q_lock;
+static u64 fst_work_txq;
+static u64 fst_work_intq;
static void
fst_q_work_item(u64 * queue, int card_index)
@@ -980,8 +980,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
/* Wait for any previous command to complete */
while (mbval > NAK) {
spin_unlock_irqrestore(&card->card_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&card->card_lock, flags);
if (++safety > 2000) {
@@ -1498,7 +1497,7 @@ do_bottom_half_rx(struct fst_card_info *card)
* The interrupt service routine
* Dev_id is our fst_card_info pointer
*/
-irqreturn_t
+static irqreturn_t
fst_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct fst_card_info *card;
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 48c03c11cd9a..a01efa6d5c62 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
}
skb_reserve(skb, 4);
cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
- data = (cisco_packet*)skb->data;
+ data = (cisco_packet*)(skb->data + 4);
data->type = htonl(type);
data->par1 = htonl(par1);
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index a5d6891c9d4c..e1601d35dced 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -330,7 +330,7 @@ static int pvc_close(struct net_device *dev)
-int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
pvc_device *pvc = dev_to_pvc(dev);
fr_proto_pvc_info info;
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index a63f6a2cc4f7..cdd4c09c2d90 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -61,7 +61,7 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *p)
+ struct packet_type *p, struct net_device *orig_dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.netif_rx)
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 7f2e3653c5e5..6c302e9dbca2 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -86,7 +86,7 @@ static __inline__ int dev_is_ethdev(struct net_device *dev)
/*
* Receive a LAPB frame via an ethernet interface.
*/
-static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
+static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev)
{
int len, err;
struct lapbethdev *lapbeth;
diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
index 9dccd9546a17..3b94352b0d03 100644
--- a/drivers/net/wan/lmc/lmc_debug.c
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -8,10 +8,10 @@
/*
* Prints out len, max to 80 octets using printk, 20 per line
*/
-void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
-{
#ifdef DEBUG
#ifdef LMC_PACKET_LOG
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
int iNewLine = 1;
char str[80], *pstr;
@@ -43,26 +43,24 @@ void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
}
sprintf(pstr, "\n");
printk(str);
+}
#endif
#endif
-}
#ifdef DEBUG
u_int32_t lmcEventLogIndex = 0;
u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#endif
void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
{
-#ifdef DEBUG
lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
lmcEventLogBuf[lmcEventLogIndex++] = arg2;
lmcEventLogBuf[lmcEventLogIndex++] = arg3;
lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
-#endif
}
+#endif /* DEBUG */
void lmc_trace(struct net_device *dev, char *msg){
#ifdef LMC_TRACE
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
index f55ce76b00ed..af8b55fdd9d9 100644
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -48,14 +48,6 @@
*/
/*
- * For lack of a better place, put the SSI cable stuff here.
- */
-char *lmc_t1_cables[] = {
- "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
- "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
-};
-
-/*
* protocol independent method.
*/
static void lmc_set_protocol (lmc_softc_t * const, lmc_ctl_t *);
diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
index 73401b0f0151..2024b26b99e6 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/net/wan/pc300.h
@@ -472,24 +472,8 @@ enum pc300_loopback_cmds {
#ifdef __KERNEL__
/* Function Prototypes */
-int dma_buf_write(pc300_t *, int, ucchar *, int);
-int dma_buf_read(pc300_t *, int, struct sk_buff *);
void tx_dma_start(pc300_t *, int);
-void rx_dma_start(pc300_t *, int);
-void tx_dma_stop(pc300_t *, int);
-void rx_dma_stop(pc300_t *, int);
-int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(struct net_device *);
-void cpc_sca_status(pc300_t *, int);
-int cpc_change_mtu(struct net_device *, int);
-int cpc_ioctl(struct net_device *, struct ifreq *, int);
-int ch_config(pc300dev_t *);
-int rx_config(pc300dev_t *);
-int tx_config(pc300dev_t *);
-void cpc_opench(pc300dev_t *);
-void cpc_closech(pc300dev_t *);
int cpc_open(struct net_device *dev);
-int cpc_close(struct net_device *dev);
int cpc_set_media(hdlc_device *, int);
#endif /* __KERNEL__ */
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 3e7753b10717..a3e65d1bc19b 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -291,6 +291,7 @@ static uclong detect_ram(pc300_t *);
static void plx_init(pc300_t *);
static void cpc_trace(struct net_device *, struct sk_buff *, char);
static int cpc_attach(struct net_device *, unsigned short, unsigned short);
+static int cpc_close(struct net_device *dev);
#ifdef CONFIG_PC300_MLPPP
void cpc_tty_init(pc300dev_t * dev);
@@ -437,7 +438,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
printk("\n");
}
-int dma_get_rx_frame_size(pc300_t * card, int ch)
+static int dma_get_rx_frame_size(pc300_t * card, int ch)
{
volatile pcsca_bd_t __iomem *ptdescr;
ucshort first_bd = card->chan[ch].rx_first_bd;
@@ -462,7 +463,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
* dma_buf_write: writes a frame to the Tx DMA buffers
* NOTE: this function writes one frame at a time.
*/
-int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
+static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
{
int i, nchar;
volatile pcsca_bd_t __iomem *ptdescr;
@@ -503,7 +504,7 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
* dma_buf_read: reads a frame from the Rx DMA buffers
* NOTE: this function reads one frame at a time.
*/
-int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
{
int nchar;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -560,7 +561,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
return (rcvd);
}
-void tx_dma_stop(pc300_t * card, int ch)
+static void tx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (5 + 2 * ch);
@@ -571,7 +572,7 @@ void tx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-void rx_dma_stop(pc300_t * card, int ch)
+static void rx_dma_stop(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
ucchar drr_ena_bit = 1 << (4 + 2 * ch);
@@ -582,7 +583,7 @@ void rx_dma_stop(pc300_t * card, int ch)
cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
}
-void rx_dma_start(pc300_t * card, int ch)
+static void rx_dma_start(pc300_t * card, int ch)
{
void __iomem *scabase = card->hw.scabase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -607,7 +608,7 @@ void rx_dma_start(pc300_t * card, int ch)
/*************************/
/*** FALC Routines ***/
/*************************/
-void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
+static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
{
void __iomem *falcbase = card->hw.falcbase;
unsigned long i = 0;
@@ -622,7 +623,7 @@ void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
}
-void falc_intr_enable(pc300_t * card, int ch)
+static void falc_intr_enable(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -672,7 +673,7 @@ void falc_intr_enable(pc300_t * card, int ch)
}
}
-void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -688,7 +689,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
(0x80 >> (timeslot & 0x07)));
}
-void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
{
void __iomem *falcbase = card->hw.falcbase;
ucchar tshf = card->chan[ch].falc.offset;
@@ -704,7 +705,7 @@ void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
~(0x80 >> (timeslot & 0x07)));
}
-void falc_close_all_timeslots(pc300_t * card, int ch)
+static void falc_close_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -726,7 +727,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
}
}
-void falc_open_all_timeslots(pc300_t * card, int ch)
+static void falc_open_all_timeslots(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -758,7 +759,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
}
}
-void falc_init_timeslot(pc300_t * card, int ch)
+static void falc_init_timeslot(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -776,7 +777,7 @@ void falc_init_timeslot(pc300_t * card, int ch)
}
}
-void falc_enable_comm(pc300_t * card, int ch)
+static void falc_enable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -792,7 +793,7 @@ void falc_enable_comm(pc300_t * card, int ch)
~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-void falc_disable_comm(pc300_t * card, int ch)
+static void falc_disable_comm(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -806,7 +807,7 @@ void falc_disable_comm(pc300_t * card, int ch)
((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
}
-void falc_init_t1(pc300_t * card, int ch)
+static void falc_init_t1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -975,7 +976,7 @@ void falc_init_t1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-void falc_init_e1(pc300_t * card, int ch)
+static void falc_init_e1(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1155,7 +1156,7 @@ void falc_init_e1(pc300_t * card, int ch)
falc_close_all_timeslots(card, ch);
}
-void falc_init_hdlc(pc300_t * card, int ch)
+static void falc_init_hdlc(pc300_t * card, int ch)
{
void __iomem *falcbase = card->hw.falcbase;
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -1181,7 +1182,7 @@ void falc_init_hdlc(pc300_t * card, int ch)
falc_intr_enable(card, ch);
}
-void te_config(pc300_t * card, int ch)
+static void te_config(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1241,7 +1242,7 @@ void te_config(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1397,7 +1398,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
}
}
-void falc_update_stats(pc300_t * card, int ch)
+static void falc_update_stats(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1450,7 +1451,7 @@ void falc_update_stats(pc300_t * card, int ch)
* the synchronizer and then sent to the system interface.
*----------------------------------------------------------------------------
*/
-void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1495,7 +1496,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
* coding must be identical.
*----------------------------------------------------------------------------
*/
-void falc_local_loop(pc300_t * card, int ch, int loop_on)
+static void falc_local_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1522,7 +1523,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
* looped. They are originated by the FALC-LH transmitter.
*----------------------------------------------------------------------------
*/
-void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1576,7 +1577,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
* Description: Turns XLU bit off in the proper register
*----------------------------------------------------------------------------
*/
-void turn_off_xlu(pc300_t * card, int ch)
+static void turn_off_xlu(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1597,7 +1598,7 @@ void turn_off_xlu(pc300_t * card, int ch)
* Description: Turns XLD bit off in the proper register
*----------------------------------------------------------------------------
*/
-void turn_off_xld(pc300_t * card, int ch)
+static void turn_off_xld(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1619,7 +1620,7 @@ void turn_off_xld(pc300_t * card, int ch)
* to generate a LOOP activation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-void falc_generate_loop_up_code(pc300_t * card, int ch)
+static void falc_generate_loop_up_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1652,7 +1653,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
* to generate a LOOP deactivation code over a T1/E1 line.
*----------------------------------------------------------------------------
*/
-void falc_generate_loop_down_code(pc300_t * card, int ch)
+static void falc_generate_loop_down_code(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1682,7 +1683,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
* it on the reception side.
*----------------------------------------------------------------------------
*/
-void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1729,7 +1730,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
* Description: This routine returns the bit error counter value
*----------------------------------------------------------------------------
*/
-ucshort falc_pattern_test_error(pc300_t * card, int ch)
+static ucshort falc_pattern_test_error(pc300_t * card, int ch)
{
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1769,7 +1770,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
netif_rx(skb);
}
-void cpc_tx_timeout(struct net_device *dev)
+static void cpc_tx_timeout(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1797,7 +1798,7 @@ void cpc_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1880,7 +1881,7 @@ int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-void cpc_net_rx(struct net_device *dev)
+static void cpc_net_rx(struct net_device *dev)
{
pc300dev_t *d = (pc300dev_t *) dev->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -2403,7 +2404,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void cpc_sca_status(pc300_t * card, int ch)
+static void cpc_sca_status(pc300_t * card, int ch)
{
ucchar ilar;
void __iomem *scabase = card->hw.scabase;
@@ -2495,7 +2496,7 @@ void cpc_sca_status(pc300_t * card, int ch)
}
}
-void cpc_falc_status(pc300_t * card, int ch)
+static void cpc_falc_status(pc300_t * card, int ch)
{
pc300ch_t *chan = &card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
@@ -2523,7 +2524,7 @@ void cpc_falc_status(pc300_t * card, int ch)
CPC_UNLOCK(card, flags);
}
-int cpc_change_mtu(struct net_device *dev, int new_mtu)
+static int cpc_change_mtu(struct net_device *dev, int new_mtu)
{
if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
return -EINVAL;
@@ -2531,7 +2532,7 @@ int cpc_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
@@ -2856,7 +2857,7 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
}
}
-int ch_config(pc300dev_t * d)
+static int ch_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -3004,7 +3005,7 @@ int ch_config(pc300dev_t * d)
return 0;
}
-int rx_config(pc300dev_t * d)
+static int rx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3035,7 +3036,7 @@ int rx_config(pc300dev_t * d)
return 0;
}
-int tx_config(pc300dev_t * d)
+static int tx_config(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3098,7 +3099,7 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding,
return 0;
}
-void cpc_opench(pc300dev_t * d)
+static void cpc_opench(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3116,7 +3117,7 @@ void cpc_opench(pc300dev_t * d)
cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
}
-void cpc_closech(pc300dev_t * d)
+static void cpc_closech(pc300dev_t * d)
{
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
@@ -3173,7 +3174,7 @@ int cpc_open(struct net_device *dev)
return 0;
}
-int cpc_close(struct net_device *dev)
+static int cpc_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
pc300dev_t *d = (pc300dev_t *) dev->priv;
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 8454bf6caaa7..52f26b9c69d2 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -112,10 +112,10 @@ typedef struct _st_cpc_tty_area {
static struct tty_driver serial_drv;
/* local variables */
-st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
+static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
-int cpc_tty_cnt=0; /* number of intrfaces configured with MLPPP */
-int cpc_tty_unreg_flag = 0;
+static int cpc_tty_cnt = 0; /* number of intrfaces configured with MLPPP */
+static int cpc_tty_unreg_flag = 0;
/* TTY functions prototype */
static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
@@ -132,9 +132,9 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
-int pc300_tiocmset(struct tty_struct *, struct file *,
- unsigned int, unsigned int);
-int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, struct file *,
+ unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *, struct file *);
/* functions called by PC300 driver */
void cpc_tty_init(pc300dev_t *dev);
@@ -538,8 +538,8 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
return(0);
}
-int pc300_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
st_cpc_tty_area *cpc_tty;
@@ -565,7 +565,7 @@ int pc300_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
{
unsigned int result;
unsigned char status;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3ac9a45b20fa..036adc4f8ba7 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -182,7 +182,7 @@ static char sdla_byte(struct net_device *dev, int addr)
return(byte);
}
-void sdla_stop(struct net_device *dev)
+static void sdla_stop(struct net_device *dev)
{
struct frad_local *flp;
@@ -209,7 +209,7 @@ void sdla_stop(struct net_device *dev)
}
}
-void sdla_start(struct net_device *dev)
+static void sdla_start(struct net_device *dev)
{
struct frad_local *flp;
@@ -247,7 +247,7 @@ void sdla_start(struct net_device *dev)
*
***************************************************/
-int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
{
unsigned long start, done, now;
char resp, *temp;
@@ -505,7 +505,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
static int sdla_reconfig(struct net_device *dev);
-int sdla_activate(struct net_device *slave, struct net_device *master)
+static int sdla_activate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -527,7 +527,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_deactivate(struct net_device *slave, struct net_device *master)
+static int sdla_deactivate(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -549,7 +549,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_assoc(struct net_device *slave, struct net_device *master)
+static int sdla_assoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -585,7 +585,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_deassoc(struct net_device *slave, struct net_device *master)
+static int sdla_deassoc(struct net_device *slave, struct net_device *master)
{
struct frad_local *flp;
int i;
@@ -613,7 +613,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
return(0);
}
-int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
+static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
{
struct frad_local *flp;
struct dlci_local *dlp;
@@ -1324,7 +1324,7 @@ NOTE: This is rather a useless action right now, as the
return(0);
}
-int sdla_change_mtu(struct net_device *dev, int new_mtu)
+static int sdla_change_mtu(struct net_device *dev, int new_mtu)
{
struct frad_local *flp;
@@ -1337,7 +1337,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
return(-EOPNOTSUPP);
}
-int sdla_set_config(struct net_device *dev, struct ifmap *map)
+static int sdla_set_config(struct net_device *dev, struct ifmap *map)
{
struct frad_local *flp;
int i;
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index c5f5e62aab8b..7f1ce9d4333e 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -445,7 +445,7 @@ void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags);
void s508_s514_lock(sdla_t *card, unsigned long *smp_flags);
unsigned short calc_checksum (char *, int);
-static int setup_fr_header(struct sk_buff** skb,
+static int setup_fr_header(struct sk_buff *skb,
struct net_device* dev, char op_mode);
@@ -822,7 +822,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->card = card;
/* verify media address */
- if (is_digit(conf->addr[0])) {
+ if (isdigit(conf->addr[0])) {
dlci = dec_to_uint(conf->addr, 0);
@@ -1372,7 +1372,7 @@ static int if_send(struct sk_buff* skb, struct net_device* dev)
/* Move the if_header() code to here. By inserting frame
* relay header in if_header() we would break the
* tcpdump and other packet sniffers */
- chan->fr_header_len = setup_fr_header(&skb,dev,chan->common.usedby);
+ chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby);
if (chan->fr_header_len < 0 ){
++chan->ifstats.tx_dropped;
++card->wandev.stats.tx_dropped;
@@ -1597,8 +1597,6 @@ static int setup_for_delayed_transmit(struct net_device* dev,
return 1;
}
- skb_unlink(skb);
-
chan->transmit_length = len;
chan->delay_skb = skb;
@@ -3458,7 +3456,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && is_digit(*str); ++str, --len)
+ for (val = 0; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
@@ -4871,18 +4869,15 @@ static void unconfig_fr (sdla_t *card)
}
}
-static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
+static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
char op_mode)
{
- struct sk_buff *skb = *skb_orig;
fr_channel_t *chan=dev->priv;
- if (op_mode == WANPIPE){
-
+ if (op_mode == WANPIPE) {
chan->fr_header[0]=Q922_UI;
switch (htons(skb->protocol)){
-
case ETH_P_IP:
chan->fr_header[1]=NLPID_IP;
break;
@@ -4894,16 +4889,14 @@ static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
}
/* If we are in bridging mode, we must apply
- * an Ethernet header */
- if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){
-
-
+ * an Ethernet header
+ */
+ if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) {
/* Encapsulate the packet as a bridged Ethernet frame. */
#ifdef DEBUG
printk(KERN_INFO "%s: encapsulating skb for frame relay\n",
dev->name);
#endif
-
chan->fr_header[0] = 0x03;
chan->fr_header[1] = 0x00;
chan->fr_header[2] = 0x80;
@@ -4916,7 +4909,6 @@ static int setup_fr_header(struct sk_buff **skb_orig, struct net_device* dev,
/* Yuck. */
skb->protocol = ETH_P_802_3;
return 8;
-
}
return 0;
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index 8a95d61a2f8f..63f846d6f3a6 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -957,7 +957,7 @@ static int new_if(struct wan_device* wandev, struct net_device* dev,
chan->hold_timeout = (conf->hold_timeout) ?
conf->hold_timeout : 10;
- }else if (is_digit(conf->addr[0])){ /* PVC */
+ }else if (isdigit(conf->addr[0])){ /* PVC */
int lcn = dec_to_uint(conf->addr, 0);
if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
@@ -3875,7 +3875,7 @@ static unsigned int dec_to_uint (unsigned char* str, int len)
if (!len)
len = strlen(str);
- for (val = 0; len && is_digit(*str); ++str, --len)
+ for (val = 0; len && isdigit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0');
return val;
@@ -3896,9 +3896,9 @@ static unsigned int hex_to_uint (unsigned char* str, int len)
for (val = 0; len; ++str, --len)
{
ch = *str;
- if (is_digit(ch))
+ if (isdigit(ch))
val = (val << 4) + (ch - (unsigned)'0');
- else if (is_hex_digit(ch))
+ else if (isxdigit(ch))
val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
else break;
}
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index c8bc6da57a41..7c2cf2e76300 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -642,9 +642,7 @@ int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
* Enable interrupt generation.
*/
-EXPORT_SYMBOL(sdla_inten);
-
-int sdla_inten (sdlahw_t* hw)
+static int sdla_inten (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
@@ -698,8 +696,7 @@ int sdla_inten (sdlahw_t* hw)
* Disable interrupt generation.
*/
-EXPORT_SYMBOL(sdla_intde);
-
+#if 0
int sdla_intde (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -748,14 +745,13 @@ int sdla_intde (sdlahw_t* hw)
}
return 0;
}
+#endif /* 0 */
/*============================================================================
* Acknowledge SDLA hardware interrupt.
*/
-EXPORT_SYMBOL(sdla_intack);
-
-int sdla_intack (sdlahw_t* hw)
+static int sdla_intack (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp;
@@ -827,8 +823,7 @@ void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
* Generate an interrupt to adapter's CPU.
*/
-EXPORT_SYMBOL(sdla_intr);
-
+#if 0
int sdla_intr (sdlahw_t* hw)
{
unsigned port = hw->port;
@@ -863,6 +858,7 @@ int sdla_intr (sdlahw_t* hw)
}
return 0;
}
+#endif /* 0 */
/*============================================================================
* Execute Adapter Command.
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
index 74e151acef3e..7a8b22a7ea31 100644
--- a/drivers/net/wan/sdlamain.c
+++ b/drivers/net/wan/sdlamain.c
@@ -57,6 +57,7 @@
#include <linux/ioport.h> /* request_region(), release_region() */
#include <linux/wanrouter.h> /* WAN router definitions */
#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
+#include <linux/rcupdate.h>
#include <linux/in.h>
#include <asm/io.h> /* phys_to_virt() */
@@ -1268,37 +1269,41 @@ unsigned long get_ip_address(struct net_device *dev, int option)
struct in_ifaddr *ifaddr;
struct in_device *in_dev;
+ unsigned long addr = 0;
- if ((in_dev = __in_dev_get(dev)) == NULL){
- return 0;
+ rcu_read_lock();
+ if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
+ goto out;
}
if ((ifaddr = in_dev->ifa_list)== NULL ){
- return 0;
+ goto out;
}
switch (option){
case WAN_LOCAL_IP:
- return ifaddr->ifa_local;
+ addr = ifaddr->ifa_local;
break;
case WAN_POINTOPOINT_IP:
- return ifaddr->ifa_address;
+ addr = ifaddr->ifa_address;
break;
case WAN_NETMASK_IP:
- return ifaddr->ifa_mask;
+ addr = ifaddr->ifa_mask;
break;
case WAN_BROADCAST_IP:
- return ifaddr->ifa_broadcast;
+ addr = ifaddr->ifa_broadcast;
break;
default:
- return 0;
+ break;
}
- return 0;
+out:
+ rcu_read_unlock();
+ return addr;
}
void add_gateway(sdla_t *card, struct net_device *dev)
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 84b65c60c799..2d1bba06a085 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sppp *p)
* here.
*/
-void sppp_input (struct net_device *dev, struct sk_buff *skb)
+static void sppp_input (struct net_device *dev, struct sk_buff *skb)
{
struct ppp_header *h;
struct sppp *sp = (struct sppp *)sppp_of(dev);
@@ -355,8 +355,6 @@ done:
return;
}
-EXPORT_SYMBOL(sppp_input);
-
/*
* Handle transmit packets.
*/
@@ -769,7 +767,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
#ifdef CONFIG_INET
rcu_read_lock();
- if ((in_dev = __in_dev_get(dev)) != NULL)
+ if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
{
for (ifa=in_dev->ifa_list; ifa != NULL;
ifa=ifa->ifa_next) {
@@ -990,7 +988,7 @@ EXPORT_SYMBOL(sppp_reopen);
* the mtu is out of range.
*/
-int sppp_change_mtu(struct net_device *dev, int new_mtu)
+static int sppp_change_mtu(struct net_device *dev, int new_mtu)
{
if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
return -EINVAL;
@@ -998,8 +996,6 @@ int sppp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-EXPORT_SYMBOL(sppp_change_mtu);
-
/**
* sppp_do_ioctl - Ioctl handler for ppp/hdlc
* @dev: Device subject to ioctl
@@ -1440,6 +1436,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
* @skb: The buffer to process
* @dev: The device it arrived on
* @p: Unused
+ * @orig_dev: Unused
*
* Protocol glue. This drives the deferred processing mode the poorer
* cards use. This can be called directly by cards that do not have
@@ -1447,7 +1444,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
* after interrupt servicing to process frames queued via netif_rx.
*/
-static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p)
+static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
{
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
@@ -1455,7 +1452,7 @@ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_t
return 0;
}
-struct packet_type sppp_packet_type = {
+static struct packet_type sppp_packet_type = {
.type = __constant_htons(ETH_P_WAN_PPP),
.func = sppp_rcv,
};
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 1d3231cc471a..7187958e40ca 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -137,9 +137,113 @@ config PCMCIA_RAYCS
comment "Wireless 802.11b ISA/PCI cards support"
depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
+config IPW2100
+ tristate "Intel PRO/Wireless 2100 Network Connection"
+ depends on NET_RADIO && PCI && IEEE80211
+ select FW_LOADER
+ ---help---
+ A driver for the Intel PRO/Wireless 2100 Network
+ Connection 802.11b wireless network adapter.
+
+ See <file:Documentation/networking/README.ipw2100> for information on
+ the capabilities currently enabled in this driver and for tips
+ for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2100.sf.net/>. Once you have the firmware image, you
+ will need to place it in /etc/firmware.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and remvoed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ipw2100.ko.
+
+config IPW2100_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2100
+ ---help---
+ Enables promiscuous/monitor mode support for the ipw2100 driver.
+ With this feature compiled into the driver, you can switch to
+ promiscuous mode via the Wireless Tool's Monitor mode. While in this
+ mode, no packets can be sent.
+
+config IPW_DEBUG
+ bool "Enable full debugging output in IPW2100 module."
+ depends on IPW2100
+ ---help---
+ This option will enable debug tracing output for the IPW2100.
+
+ This will result in the kernel module being ~60k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/bus/pci/drivers/ipw2100/debug_level
+
+ This entry will only exist if this option is enabled.
+
+ If you are not trying to debug or develop the IPW2100 driver, you
+ most likely want to say N here.
+
+config IPW2200
+ tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
+ depends on IEEE80211 && PCI
+ select FW_LOADER
+ ---help---
+ A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
+ Connection adapters.
+
+ See <file:Documentation/networking/README.ipw2200> for
+ information on the capabilities currently enabled in this
+ driver and for tips for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2200.sf.net/>. See the above referenced README.ipw2200
+ for information on where to install the firmare images.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and remvoed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ipw2200.ko.
+
+config IPW_DEBUG
+ bool "Enable full debugging output in IPW2200 module."
+ depends on IPW2200
+ ---help---
+ This option will enable debug tracing output for the IPW2200.
+
+ This will result in the kernel module being ~100k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/bus/pci/drivers/ipw2200/debug_level
+
+ This entry will only exist if this option is enabled.
+
+ To set a value, simply echo an 8-byte hex value to the same file:
+
+ % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level
+
+ You can find the list of debug mask values in
+ drivers/net/wireless/ipw2200.h
+
+ If you are not trying to debug or develop the IPW2200 driver, you
+ most likely want to say N here.
+
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
- depends on NET_RADIO && ISA && (PCI || BROKEN)
+ depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
---help---
This is the standard Linux driver to support Cisco/Aironet ISA and
PCI 802.11 wireless cards.
@@ -185,8 +289,8 @@ config APPLE_AIRPORT
a non-standard interface
config PLX_HERMES
- tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in PLX9052 based PCI adaptors. These
@@ -195,12 +299,9 @@ config PLX_HERMES
802.11b PCMCIA cards can be used in desktop machines. The Netgear
MA301 is such an adaptor.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
-
config TMD_HERMES
- tristate "Hermes in TMD7160 based PCI adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Hermes in TMD7160 based PCI adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCMCIA cards supported by the "Hermes" (aka
orinoco) driver when used in TMD7160 based PCI adaptors. These
@@ -208,12 +309,18 @@ config TMD_HERMES
PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
802.11b PCMCIA cards can be used in desktop machines.
- Support for these adaptors is so far still incomplete and buggy.
- You have been warned.
+config NORTEL_HERMES
+ tristate "Nortel emobility PCI adaptor support"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in Nortel emobility PCI adaptors. These
+ adaptors are not full PCMCIA controllers, but act as a more limited
+ PCI <-> PCMCIA bridge.
config PCI_HERMES
- tristate "Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)"
- depends on PCI && HERMES && EXPERIMENTAL
+ tristate "Prism 2.5 PCI 802.11b adaptor support"
+ depends on PCI && HERMES
help
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
@@ -268,9 +375,22 @@ config PCMCIA_HERMES
configure your card and that /etc/pcmcia/wireless.opts works:
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+config PCMCIA_SPECTRUM
+ tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+ depends on NET_RADIO && PCMCIA && HERMES
+ ---help---
+
+ This is a driver for 802.11b cards using RAM-loadable Symbol
+ firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+ cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+ This driver requires firmware download on startup. Utilities
+ for downloading Symbol firmware are available at
+ <http://sourceforge.net/projects/orinoco/>
+
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
- depends on NET_RADIO && PCMCIA
+ depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
---help---
This is the standard Linux driver to support Cisco/Aironet PCMCIA
802.11 wireless cards. This driver is the same as the Aironet
@@ -355,6 +475,8 @@ config PRISM54
say M here and read <file:Documentation/modules.txt>. The module
will be called prism54.ko.
+source "drivers/net/wireless/hostap/Kconfig"
+
# yes, this works even when no drivers are selected
config NET_WIRELESS
bool
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 2b87841322cc..3a6f7ba326ca 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -2,6 +2,10 @@
# Makefile for the Linux Wireless network device drivers.
#
+obj-$(CONFIG_IPW2100) += ipw2100.o
+
+obj-$(CONFIG_IPW2200) += ipw2200.o
+
obj-$(CONFIG_STRIP) += strip.o
obj-$(CONFIG_ARLAN) += arlan.o
@@ -18,6 +22,8 @@ obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
obj-$(CONFIG_AIRO) += airo.o
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
@@ -28,6 +34,8 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
obj-$(CONFIG_PRISM54) += prism54/
+obj-$(CONFIG_HOSTAP) += hostap/
+
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index df20adcd0730..750c0167539c 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -35,6 +35,7 @@
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/bitops.h>
+#include <linux/scatterlist.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -1040,13 +1041,12 @@ typedef struct {
u16 status;
} WifiCtlHdr;
-WifiCtlHdr wifictlhdr8023 = {
+static WifiCtlHdr wifictlhdr8023 = {
.ctlhdr = {
.ctl = HOST_DONT_RLSE,
}
};
-#ifdef WIRELESS_EXT
// Frequency list (map channels to frequencies)
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1067,7 +1067,6 @@ typedef struct wep_key_t {
/* List of Wireless Handlers (new API) */
static const struct iw_handler_def airo_handler_def;
-#endif /* WIRELESS_EXT */
static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
@@ -1110,14 +1109,12 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
-struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
+static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
-int flashcard(struct net_device *dev, aironet_ioctl *comp);
+static int flashcard(struct net_device *dev, aironet_ioctl *comp);
#endif /* CISCO_EXT */
#ifdef MICSUPPORT
static void micinit(struct airo_info *ai);
@@ -1187,12 +1184,10 @@ struct airo_info {
int fid;
} xmit, xmit11;
struct net_device *wifidev;
-#ifdef WIRELESS_EXT
struct iw_statistics wstats; // wireless stats
unsigned long scan_timestamp; /* Time started to scan */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT */
#ifdef MICSUPPORT
/* MIC stuff */
struct crypto_tfm *tfm;
@@ -1226,6 +1221,12 @@ static int setup_proc_entry( struct net_device *dev,
static int takedown_proc_entry( struct net_device *dev,
struct airo_info *apriv );
+static int cmdreset(struct airo_info *ai);
+static int setflashmode (struct airo_info *ai);
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
+static int flashputbuf(struct airo_info *ai);
+static int flashrestart(struct airo_info *ai,struct net_device *dev);
+
#ifdef MICSUPPORT
/***********************************************************************
* MIC ROUTINES *
@@ -1234,10 +1235,11 @@ static int takedown_proc_entry( struct net_device *dev,
static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
static void MoveWindow(miccntx *context, u32 micSeq);
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
-void emmh32_init(emmh32_context *context);
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
-void emmh32_final(emmh32_context *context, u8 digest[4]);
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
+static void emmh32_init(emmh32_context *context);
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
+static void emmh32_final(emmh32_context *context, u8 digest[4]);
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
/* micinit - Initialize mic seed */
@@ -1301,7 +1303,7 @@ static int micsetup(struct airo_info *ai) {
int i;
if (ai->tfm == NULL)
- ai->tfm = crypto_alloc_tfm("aes", 0);
+ ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
if (ai->tfm == NULL) {
printk(KERN_ERR "airo: failed to load transform for AES\n");
@@ -1315,7 +1317,7 @@ static int micsetup(struct airo_info *ai) {
return SUCCESS;
}
-char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
/*===========================================================================
* Description: Mic a packet
@@ -1570,7 +1572,7 @@ static void MoveWindow(miccntx *context, u32 micSeq)
static unsigned char aes_counter[16];
/* expand the key to fill the MMH coefficient array */
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
{
/* take the keying material, expand if necessary, truncate at 16-bytes */
/* run through AES counter mode to generate context->coeff[] */
@@ -1589,11 +1591,9 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
aes_counter[12] = (u8)(counter >> 24);
counter++;
memcpy (plain, aes_counter, 16);
- sg[0].page = virt_to_page(plain);
- sg[0].offset = ((long) plain & ~PAGE_MASK);
- sg[0].length = 16;
+ sg_set_buf(sg, plain, 16);
crypto_cipher_encrypt(tfm, sg, sg, 16);
- cipher = kmap(sg[0].page) + sg[0].offset;
+ cipher = kmap(sg->page) + sg->offset;
for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
j += 4;
@@ -1602,7 +1602,7 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
}
/* prepare for calculation of a new mic */
-void emmh32_init(emmh32_context *context)
+static void emmh32_init(emmh32_context *context)
{
/* prepare for new mic calculation */
context->accum = 0;
@@ -1610,7 +1610,7 @@ void emmh32_init(emmh32_context *context)
}
/* add some bytes to the mic calculation */
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
{
int coeff_position, byte_position;
@@ -1652,7 +1652,7 @@ void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
/* calculate the mic */
-void emmh32_final(emmh32_context *context, u8 digest[4])
+static void emmh32_final(emmh32_context *context, u8 digest[4])
{
int coeff_position, byte_position;
u32 val;
@@ -2232,7 +2232,7 @@ static void airo_read_stats(struct airo_info *ai) {
u32 *vals = stats_rid.vals;
clear_bit(JOB_STATS, &ai->flags);
- if (ai->power) {
+ if (ai->power.event) {
up(&ai->sem);
return;
}
@@ -2255,7 +2255,7 @@ static void airo_read_stats(struct airo_info *ai) {
ai->stats.rx_fifo_errors = vals[0];
}
-struct net_device_stats *airo_get_stats(struct net_device *dev)
+static struct net_device_stats *airo_get_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
@@ -2380,14 +2380,10 @@ void stop_airo_card( struct net_device *dev, int freeres )
dev_kfree_skb(skb);
}
- if (ai->flash)
- kfree(ai->flash);
- if (ai->rssi)
- kfree(ai->rssi);
- if (ai->APList)
- kfree(ai->APList);
- if (ai->SSID)
- kfree(ai->SSID);
+ kfree(ai->flash);
+ kfree(ai->rssi);
+ kfree(ai->APList);
+ kfree(ai->SSID);
if (freeres) {
/* PCMCIA frees this stuff, so only for PCI and ISA */
release_region( dev->base_addr, 64 );
@@ -2403,8 +2399,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
}
}
#ifdef MICSUPPORT
- if (ai->tfm)
- crypto_free_tfm(ai->tfm);
+ crypto_free_tfm(ai->tfm);
#endif
del_airo_dev( dev );
free_netdev( dev );
@@ -2414,7 +2409,7 @@ EXPORT_SYMBOL(stop_airo_card);
static int add_airo_dev( struct net_device *dev );
-int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
+static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
return ETH_ALEN;
@@ -2521,7 +2516,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
unsigned long mem_start, mem_len, aux_start, aux_len;
int rc = -1;
int i;
- unsigned char *busaddroff,*vpackoff;
+ dma_addr_t busaddroff;
+ unsigned char *vpackoff;
unsigned char __iomem *pciaddroff;
mem_start = pci_resource_start(pci, 1);
@@ -2564,7 +2560,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/*
* Setup descriptor RX, TX, CONFIG
*/
- busaddroff = (unsigned char *)ai->shared_dma;
+ busaddroff = ai->shared_dma;
pciaddroff = ai->pciaux + AUX_OFFSET;
vpackoff = ai->shared;
@@ -2573,7 +2569,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->rxfids[i].pending = 0;
ai->rxfids[i].card_ram_off = pciaddroff;
ai->rxfids[i].virtual_host_addr = vpackoff;
- ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->rxfids[i].rx_desc.host_addr = busaddroff;
ai->rxfids[i].rx_desc.valid = 1;
ai->rxfids[i].rx_desc.len = PKTSIZE;
ai->rxfids[i].rx_desc.rdy = 0;
@@ -2588,7 +2584,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
ai->txfids[i].card_ram_off = pciaddroff;
ai->txfids[i].virtual_host_addr = vpackoff;
ai->txfids[i].tx_desc.valid = 1;
- ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->txfids[i].tx_desc.host_addr = busaddroff;
memcpy(ai->txfids[i].virtual_host_addr,
&wifictlhdr8023, sizeof(wifictlhdr8023));
@@ -2601,8 +2597,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/* Rid descriptor setup */
ai->config_desc.card_ram_off = pciaddroff;
ai->config_desc.virtual_host_addr = vpackoff;
- ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
- ai->ridbus = (dma_addr_t)busaddroff;
+ ai->config_desc.rid_desc.host_addr = busaddroff;
+ ai->ridbus = busaddroff;
ai->config_desc.rid_desc.rid = 0;
ai->config_desc.rid_desc.len = RIDSIZE;
ai->config_desc.rid_desc.valid = 1;
@@ -2641,9 +2637,7 @@ static void wifi_setup(struct net_device *dev)
dev->get_stats = &airo_get_stats;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -2669,9 +2663,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
dev->priv = ethdev->priv;
dev->irq = ethdev->irq;
dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
err = register_netdev(dev);
if (err<0) {
@@ -2681,7 +2673,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
return dev;
}
-int reset_card( struct net_device *dev , int lock) {
+static int reset_card( struct net_device *dev , int lock) {
struct airo_info *ai = dev->priv;
if (lock && down_interruptible(&ai->sem))
@@ -2696,9 +2688,9 @@ int reset_card( struct net_device *dev , int lock) {
return 0;
}
-struct net_device *_init_airo_card( unsigned short irq, int port,
- int is_pcmcia, struct pci_dev *pci,
- struct device *dmdev )
+static struct net_device *_init_airo_card( unsigned short irq, int port,
+ int is_pcmcia, struct pci_dev *pci,
+ struct device *dmdev )
{
struct net_device *dev;
struct airo_info *ai;
@@ -2749,11 +2741,9 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
dev->set_multicast_list = &airo_set_multicast_list;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
ai->wireless_data.spy_data = &ai->spy_data;
dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
@@ -2962,7 +2952,7 @@ static int airo_thread(void *data) {
break;
}
- if (ai->power || test_bit(FLAG_FLASHING, &ai->flags)) {
+ if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
up(&ai->sem);
continue;
}
@@ -3252,7 +3242,7 @@ badrx:
wstats.noise = apriv->wstats.qual.noise;
wstats.updated = IW_QUAL_LEVEL_UPDATED
| IW_QUAL_QUAL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(dev, sa, &wstats);
}
@@ -3598,7 +3588,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
wstats.noise = ai->wstats.qual.noise;
wstats.updated = IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(ai->dev, sa, &wstats);
}
@@ -3631,10 +3621,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
int rc;
memset( &mySsid, 0, sizeof( mySsid ) );
- if (ai->flash) {
- kfree (ai->flash);
- ai->flash = NULL;
- }
+ kfree (ai->flash);
+ ai->flash = NULL;
/* The NOP is the first step in getting the card going */
cmd.cmd = NOP;
@@ -3671,14 +3659,10 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
tdsRssiRid rssi_rid;
CapabilityRid cap_rid;
- if (ai->APList) {
- kfree(ai->APList);
- ai->APList = NULL;
- }
- if (ai->SSID) {
- kfree(ai->SSID);
- ai->SSID = NULL;
- }
+ kfree(ai->APList);
+ ai->APList = NULL;
+ kfree(ai->SSID);
+ ai->SSID = NULL;
// general configuration (read/modify/write)
status = readConfigRid(ai, lock);
if ( status != SUCCESS ) return ERROR;
@@ -3692,10 +3676,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
}
else {
- if (ai->rssi) {
- kfree(ai->rssi);
- ai->rssi = NULL;
- }
+ kfree(ai->rssi);
+ ai->rssi = NULL;
if (cap_rid.softCap & 8)
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
@@ -5374,11 +5356,13 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
static int proc_close( struct inode *inode, struct file *file )
{
- struct proc_data *data = (struct proc_data *)file->private_data;
- if ( data->on_close != NULL ) data->on_close( inode, file );
- if ( data->rbuffer ) kfree( data->rbuffer );
- if ( data->wbuffer ) kfree( data->wbuffer );
- kfree( data );
+ struct proc_data *data = file->private_data;
+
+ if (data->on_close != NULL)
+ data->on_close(inode, file);
+ kfree(data->rbuffer);
+ kfree(data->wbuffer);
+ kfree(data);
return 0;
}
@@ -5509,12 +5493,13 @@ static int airo_pci_resume(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct airo_info *ai = dev->priv;
Resp rsp;
+ pci_power_t prev_state = pdev->current_state;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
+ pci_enable_wake(pdev, PCI_D0, 0);
- if (ai->power > 1) {
+ if (prev_state != PCI_D1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
@@ -5592,7 +5577,6 @@ static void __exit airo_cleanup_module( void )
remove_proc_entry("aironet", proc_root_driver);
}
-#ifdef WIRELESS_EXT
/*
* Initial Wireless Extension code for Aironet driver by :
* Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
@@ -6483,22 +6467,20 @@ static int airo_get_range(struct net_device *dev,
range->max_qual.qual = 100; /* % */
else
range->max_qual.qual = airo_get_max_quality(&cap_rid);
- range->max_qual.level = 0; /* 0 means we use dBm */
- range->max_qual.noise = 0;
- range->max_qual.updated = 0;
+ range->max_qual.level = 0x100 - 120; /* -120 dBm */
+ range->max_qual.noise = 0x100 - 120; /* -120 dBm */
/* Experimental measurements - boundary 11/5.5 Mb/s */
/* Note : with or without the (local->rssi), results
* are somewhat different. - Jean II */
if (local->rssi) {
- range->avg_qual.qual = 50; /* % */
- range->avg_qual.level = 186; /* -70 dBm */
+ range->avg_qual.qual = 50; /* % */
+ range->avg_qual.level = 0x100 - 70; /* -70 dBm */
} else {
range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
- range->avg_qual.level = 176; /* -80 dBm */
+ range->avg_qual.level = 0x100 - 80; /* -80 dBm */
}
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 0;
+ range->avg_qual.noise = 0x100 - 85; /* -85 dBm */
for(i = 0 ; i < 8 ; i++) {
range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
@@ -6721,15 +6703,17 @@ static int airo_get_aplist(struct net_device *dev,
if (local->rssi) {
qual[i].level = 0x100 - BSSList.dBm;
qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
- qual[i].updated = IW_QUAL_QUAL_UPDATED;
+ qual[i].updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
qual[i].level = (BSSList.dBm + 321) / 2;
qual[i].qual = 0;
- qual[i].updated = IW_QUAL_QUAL_INVALID;
+ qual[i].updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
qual[i].noise = local->wstats.qual.noise;
- qual[i].updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
if (BSSList.index == 0xffff)
break;
}
@@ -6846,7 +6830,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+ /* iwe.u.freq.m containt the channel (starting 1), our
+ * frequency_list array start at index 0...
+ */
+ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
@@ -6855,15 +6842,17 @@ static inline char *airo_translate_scan(struct net_device *dev,
if (ai->rssi) {
iwe.u.qual.level = 0x100 - bss->dBm;
iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
iwe.u.qual.level = (bss->dBm + 321) / 2;
iwe.u.qual.qual = 0;
- iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
+ iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
iwe.u.qual.noise = ai->wstats.qual.noise;
- iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
/* Add encryption capability */
@@ -7096,8 +7085,6 @@ static const struct iw_handler_def airo_handler_def =
.get_wireless_stats = airo_get_wireless_stats,
};
-#endif /* WIRELESS_EXT */
-
/*
* This defines the configuration part of the Wireless Extensions
* Note : irq and spinlock protection will occur in the subroutines
@@ -7116,7 +7103,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int rc = 0;
struct airo_info *ai = (struct airo_info *)dev->priv;
- if (ai->power)
+ if (ai->power.event)
return 0;
switch (cmd) {
@@ -7176,7 +7163,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
-#ifdef WIRELESS_EXT
/*
* Get the Wireless stats out of the driver
* Note : irq and spinlock protection will occur in the subroutines
@@ -7195,7 +7181,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
/* Get stats out of the card */
clear_bit(JOB_WSTATS, &local->flags);
- if (local->power) {
+ if (local->power.event) {
up(&local->sem);
return;
}
@@ -7216,13 +7202,12 @@ static void airo_read_wireless_stats(struct airo_info *local)
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
}
- local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
if (status_rid.len >= 124) {
local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
- local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
+ local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
} else {
local->wstats.qual.noise = 0;
- local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+ local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
}
/* Packets discarded in the wireless adapter due to wireless
@@ -7235,7 +7220,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
local->wstats.miss.beacon = vals[34];
}
-struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
@@ -7250,7 +7235,6 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
return &local->wstats;
}
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
/*
@@ -7450,14 +7434,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
* Flash command switch table
*/
-int flashcard(struct net_device *dev, aironet_ioctl *comp) {
+static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
int z;
- int cmdreset(struct airo_info *);
- int setflashmode(struct airo_info *);
- int flashgchar(struct airo_info *,int,int);
- int flashpchar(struct airo_info *,int,int);
- int flashputbuf(struct airo_info *);
- int flashrestart(struct airo_info *,struct net_device *);
/* Only super-user can modify flash */
if (!capable(CAP_NET_ADMIN))
@@ -7515,7 +7493,7 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
* card.
*/
-int cmdreset(struct airo_info *ai) {
+static int cmdreset(struct airo_info *ai) {
disable_MAC(ai, 1);
if(!waitbusy (ai)){
@@ -7539,7 +7517,7 @@ int cmdreset(struct airo_info *ai) {
* mode
*/
-int setflashmode (struct airo_info *ai) {
+static int setflashmode (struct airo_info *ai) {
set_bit (FLAG_FLASHING, &ai->flags);
OUT4500(ai, SWS0, FLASH_COMMAND);
@@ -7566,7 +7544,7 @@ int setflashmode (struct airo_info *ai) {
* x 50us for echo .
*/
-int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
int echo;
int waittime;
@@ -7606,7 +7584,7 @@ int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
* Get a character from the card matching matchbyte
* Step 3)
*/
-int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
int rchar;
unsigned char rbyte=0;
@@ -7637,7 +7615,7 @@ int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
* send to the card
*/
-int flashputbuf(struct airo_info *ai){
+static int flashputbuf(struct airo_info *ai){
int nwords;
/* Write stuff */
@@ -7659,7 +7637,7 @@ int flashputbuf(struct airo_info *ai){
/*
*
*/
-int flashrestart(struct airo_info *ai,struct net_device *dev){
+static int flashrestart(struct airo_info *ai,struct net_device *dev){
int i,status;
ssleep(1); /* Added 12/7/00 */
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index bf25584d68d3..784de9109113 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -258,9 +258,7 @@ static void airo_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
- if (link->priv) {
- kfree(link->priv);
- }
+ kfree(link->priv);
kfree(link);
} /* airo_detach */
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 9d496703c465..7b321f7cf358 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -15,28 +15,11 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/current.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
+#include <linux/delay.h>
#include <asm/pmac_feature.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
#include "orinoco.h"
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 18a7d38d2a13..1fbe027d26b6 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -68,7 +68,7 @@
#include <linux/device.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
-#include "ieee802_11.h"
+#include <net/ieee80211.h>
#include "atmel.h"
#define DRIVER_MAJOR 0
@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_private *priv);
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
static int start_tx (struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr_4addr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -863,17 +863,17 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
return 1;
}
- frame_ctl = IEEE802_11_FTYPE_DATA;
+ frame_ctl = IEEE80211_FTYPE_DATA;
header.duration_id = 0;
header.seq_ctl = 0;
if (priv->wep_is_on)
- frame_ctl |= IEEE802_11_FCTL_WEP;
+ frame_ctl |= IEEE80211_FCTL_PROTECTED;
if (priv->operating_mode == IW_MODE_ADHOC) {
memcpy(&header.addr1, skb->data, 6);
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, priv->BSSID, 6);
} else {
- frame_ctl |= IEEE802_11_FCTL_TODS;
+ frame_ctl |= IEEE80211_FCTL_TODS;
memcpy(&header.addr1, priv->CurrentBSSID, 6);
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, skb->data, 6);
@@ -902,7 +902,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee802_11_hdr *header,
+ struct ieee80211_hdr_4addr *header,
u8 *body, int body_len)
{
u16 buff;
@@ -917,7 +917,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
-static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
@@ -955,7 +955,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
}
memcpy(skbp, header->addr1, 6); /* destination address */
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(&skbp[6], header->addr3, 6);
else
memcpy(&skbp[6], header->addr2, 6); /* source address */
@@ -990,14 +990,14 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return (crc ^ 0xffffffff) == netcrc;
}
-static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
{
u8 mac4[6];
u8 source[6];
struct sk_buff *skb;
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(source, header->addr3, 6);
else
memcpy(source, header->addr2, 6);
@@ -1082,7 +1082,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *head
static void rx_done_irq(struct atmel_private *priv)
{
int i;
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr_4addr header;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -1117,7 +1117,7 @@ static void rx_done_irq(struct atmel_private *priv)
/* probe for CRC use here if needed once five packets have arrived with
the same crc status, we assume we know what's happening and stop probing */
if (priv->probe_crc) {
- if (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
+ if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
} else {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
@@ -1132,16 +1132,16 @@ static void rx_done_irq(struct atmel_private *priv)
}
/* don't CRC header when WEP in use */
- if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
+ if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
}
msdu_size -= 24; /* header */
- if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) {
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
- int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;
- u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;
- u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;
+ int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
+ u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
+ u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
if (!more_fragments && packet_fragment_no == 0 ) {
fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
@@ -1151,7 +1151,7 @@ static void rx_done_irq(struct atmel_private *priv)
}
}
- if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
/* copy rest of packet into buffer */
atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
@@ -1593,7 +1593,6 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT
dev->set_mac_address = atmel_set_mac_address;
dev->hard_start_xmit = start_tx;
dev->get_stats = atmel_get_stats;
- dev->get_wireless_stats = atmel_get_wireless_stats;
dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
dev->do_ioctl = atmel_ioctl;
dev->irq = irq;
@@ -1654,8 +1653,7 @@ void stop_atmel_card(struct net_device *dev, int freeres)
unregister_netdev(dev);
remove_proc_entry("driver/atmel", NULL);
free_irq(dev->irq, dev);
- if (priv->firmware)
- kfree(priv->firmware);
+ kfree(priv->firmware);
if (freeres) {
/* PCMCIA frees this stuff, so only for PCI */
release_region(dev->base_addr, 64);
@@ -2411,7 +2409,8 @@ static const struct iw_handler_def atmel_handler_def =
.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
.standard = (iw_handler *) atmel_handler,
.private = (iw_handler *) atmel_private_handler,
- .private_args = (struct iw_priv_args *) atmel_private_args
+ .private_args = (struct iw_priv_args *) atmel_private_args,
+ .get_wireless_stats = atmel_get_wireless_stats
};
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2424,19 +2423,6 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
char domain[REGDOMAINSZ+1];
switch (cmd) {
- case SIOCGIWPRIV:
- if(wrq->u.data.pointer) {
- /* Set the number of ioctl available */
- wrq->u.data.length = sizeof(atmel_private_args) / sizeof(atmel_private_args[0]);
-
- /* Copy structure to the user buffer */
- if (copy_to_user(wrq->u.data.pointer,
- (u_char *) atmel_private_args,
- sizeof(atmel_private_args)))
- rc = -EFAULT;
- }
- break;
-
case ATMELIDIFC:
wrq->u.param.value = ATMELMAGIC;
break;
@@ -2463,8 +2449,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
}
- if (priv->firmware)
- kfree(priv->firmware);
+ kfree(priv->firmware);
priv->firmware = new_firmware;
priv->firmware_length = com.len;
@@ -2663,10 +2648,10 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
{
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr_4addr header;
struct auth_body auth;
- header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH);
+ header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
@@ -2677,7 +2662,7 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng
auth.alg = cpu_to_le16(C80211_MGMT_AAN_SHAREDKEY);
/* no WEP for authentication frames with TrSeqNo 1 */
if (priv->CurrentAuthentTransactionSeqNum != 1)
- header.frame_ctl |= cpu_to_le16(IEEE802_11_FCTL_WEP);
+ header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
} else {
auth.alg = cpu_to_le16(C80211_MGMT_AAN_OPENSYSTEM);
}
@@ -2701,7 +2686,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
{
u8 *ssid_el_p;
int bodysize;
- struct ieee802_11_hdr header;
+ struct ieee80211_hdr_4addr header;
struct ass_req_format {
u16 capability;
u16 listen_interval;
@@ -2714,8 +2699,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
u8 rates[4];
} body;
- header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT |
- (is_reassoc ? IEEE802_11_STYPE_REASSOC_REQ : IEEE802_11_STYPE_ASSOC_REQ));
+ header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ (is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
@@ -2751,9 +2736,9 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
}
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee802_11_hdr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
{
- if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
else
return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
@@ -2801,7 +2786,7 @@ static int retrieve_bss(struct atmel_private *priv)
}
-static void store_bss_info(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
u8 ssid_len, u8 *ssid, int is_beacon)
{
@@ -3085,12 +3070,12 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
- switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_STYPE) {
+ switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
case C80211_SUBTYPE_MGMT_BEACON :
case C80211_SUBTYPE_MGMT_ProbeResponse:
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index ff031a3985b3..195cb36619e8 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -259,8 +259,7 @@ static void atmel_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
- if (link->priv)
- kfree(link->priv);
+ kfree(link->priv);
kfree(link);
}
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 21c3d0d227e6..579480dad374 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -39,17 +39,10 @@
*/
#include <linux/config.h>
-
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/net.h>
-#include <asm/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
#include "hermes.h"
@@ -451,6 +444,43 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
return err;
}
+/* Write a block of data to the chip's buffer with padding if
+ * neccessary, via the BAP. Synchronization/serialization is the
+ * caller's problem. len must be even.
+ *
+ * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
+ */
+int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len,
+ u16 id, u16 offset)
+{
+ int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+ int err = 0;
+
+ if (len < 0 || len % 2 || data_len > len)
+ return -EINVAL;
+
+ err = hermes_bap_seek(hw, bap, id, offset);
+ if (err)
+ goto out;
+
+ /* Transfer all the complete words of data */
+ hermes_write_words(hw, dreg, buf, data_len/2);
+ /* If there is an odd byte left over pad and transfer it */
+ if (data_len & 1) {
+ u8 end[2];
+ end[1] = 0;
+ end[0] = ((unsigned char *)buf)[data_len - 1];
+ hermes_write_words(hw, dreg, end, 1);
+ data_len ++;
+ }
+ /* Now send zeros for the padding */
+ if (data_len < len)
+ hermes_clear_words(hw, dreg, (len - data_len) / 2);
+ /* Complete */
+ out:
+ return err;
+}
+
/* Read a Length-Type-Value record from the card.
*
* If length is NULL, we ignore the length read from the card, and
@@ -538,6 +568,7 @@ EXPORT_SYMBOL(hermes_allocate);
EXPORT_SYMBOL(hermes_bap_pread);
EXPORT_SYMBOL(hermes_bap_pwrite);
+EXPORT_SYMBOL(hermes_bap_pwrite_pad);
EXPORT_SYMBOL(hermes_read_ltv);
EXPORT_SYMBOL(hermes_write_ltv);
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 8c9e874c9118..a6bd472d75d4 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -30,9 +30,8 @@
* access to the hermes_t structure, and to the hardware
*/
-#include <linux/delay.h>
#include <linux/if_ether.h>
-#include <asm/byteorder.h>
+#include <asm/io.h>
/*
* Limits and constants
@@ -192,13 +191,13 @@
#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
struct hermes_tx_descriptor {
- u16 status;
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
+ __le16 status;
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 sw_support;
u8 retry_count;
u8 tx_rate;
- u16 tx_control;
+ __le16 tx_control;
} __attribute__ ((packed));
#define HERMES_TXSTAT_RETRYERR (0x0001)
@@ -222,60 +221,60 @@ struct hermes_tx_descriptor {
#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
struct hermes_tallies_frame {
- u16 TxUnicastFrames;
- u16 TxMulticastFrames;
- u16 TxFragments;
- u16 TxUnicastOctets;
- u16 TxMulticastOctets;
- u16 TxDeferredTransmissions;
- u16 TxSingleRetryFrames;
- u16 TxMultipleRetryFrames;
- u16 TxRetryLimitExceeded;
- u16 TxDiscards;
- u16 RxUnicastFrames;
- u16 RxMulticastFrames;
- u16 RxFragments;
- u16 RxUnicastOctets;
- u16 RxMulticastOctets;
- u16 RxFCSErrors;
- u16 RxDiscards_NoBuffer;
- u16 TxDiscardsWrongSA;
- u16 RxWEPUndecryptable;
- u16 RxMsgInMsgFragments;
- u16 RxMsgInBadMsgFragments;
+ __le16 TxUnicastFrames;
+ __le16 TxMulticastFrames;
+ __le16 TxFragments;
+ __le16 TxUnicastOctets;
+ __le16 TxMulticastOctets;
+ __le16 TxDeferredTransmissions;
+ __le16 TxSingleRetryFrames;
+ __le16 TxMultipleRetryFrames;
+ __le16 TxRetryLimitExceeded;
+ __le16 TxDiscards;
+ __le16 RxUnicastFrames;
+ __le16 RxMulticastFrames;
+ __le16 RxFragments;
+ __le16 RxUnicastOctets;
+ __le16 RxMulticastOctets;
+ __le16 RxFCSErrors;
+ __le16 RxDiscards_NoBuffer;
+ __le16 TxDiscardsWrongSA;
+ __le16 RxWEPUndecryptable;
+ __le16 RxMsgInMsgFragments;
+ __le16 RxMsgInBadMsgFragments;
/* Those last are probably not available in very old firmwares */
- u16 RxDiscards_WEPICVError;
- u16 RxDiscards_WEPExcluded;
+ __le16 RxDiscards_WEPICVError;
+ __le16 RxDiscards_WEPExcluded;
} __attribute__ ((packed));
/* Grabbed from wlan-ng - Thanks Mark... - Jean II
* This is the result of a scan inquiry command */
/* Structure describing info about an Access Point */
struct prism2_scan_apinfo {
- u16 channel; /* Channel where the AP sits */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 channel; /* Channel where the AP sits */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
- u16 essid_len; /* ESSID length */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
u8 rates[10]; /* Bit rate supported */
- u16 proberesp_rate; /* Data rate of the response frame */
- u16 atim; /* ATIM window time, Kus (hostscan only) */
+ __le16 proberesp_rate; /* Data rate of the response frame */
+ __le16 atim; /* ATIM window time, Kus (hostscan only) */
} __attribute__ ((packed));
/* Same stuff for the Lucent/Agere card.
* Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
struct agere_scan_apinfo {
- u16 channel; /* Channel where the AP sits */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 channel; /* Channel where the AP sits */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- u16 essid_len; /* ESSID length */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
} __attribute__ ((packed));
@@ -283,16 +282,16 @@ struct agere_scan_apinfo {
struct symbol_scan_apinfo {
u8 channel; /* Channel where the AP sits */
u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
- u16 noise; /* Noise level */
- u16 level; /* Signal level */
+ __le16 noise; /* Noise level */
+ __le16 level; /* Signal level */
u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
- u16 beacon_interv; /* Beacon interval */
- u16 capabilities; /* Capabilities */
+ __le16 beacon_interv; /* Beacon interval */
+ __le16 capabilities; /* Capabilities */
/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
- u16 essid_len; /* ESSID length */
+ __le16 essid_len; /* ESSID length */
u8 essid[32]; /* ESSID of the network */
- u16 rates[5]; /* Bit rate supported */
- u16 basic_rates; /* Basic rates bitmask */
+ __le16 rates[5]; /* Bit rate supported */
+ __le16 basic_rates; /* Basic rates bitmask */
u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
} __attribute__ ((packed));
@@ -312,7 +311,7 @@ union hermes_scan_info {
#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
struct hermes_linkstatus {
- u16 linkstatus; /* Link status */
+ __le16 linkstatus; /* Link status */
} __attribute__ ((packed));
struct hermes_response {
@@ -321,8 +320,8 @@ struct hermes_response {
/* "ID" structure - used for ESSID and station nickname */
struct hermes_idstring {
- u16 len;
- u16 val[16];
+ __le16 len;
+ __le16 val[16];
} __attribute__ ((packed));
struct hermes_multicast {
@@ -377,6 +376,8 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
u16 id, u16 offset);
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
u16 id, u16 offset);
+int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
+ unsigned data_len, unsigned len, u16 id, u16 offset);
int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
u16 *length, void *buf);
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
@@ -447,7 +448,7 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
{
- u16 rec;
+ __le16 rec;
int err;
err = HERMES_READ_RECORD(hw, bap, rid, &rec);
@@ -457,7 +458,7 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
{
- u16 rec = cpu_to_le16(word);
+ __le16 rec = cpu_to_le16(word);
return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
}
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
new file mode 100644
index 000000000000..56f41c714d38
--- /dev/null
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -0,0 +1,73 @@
+config HOSTAP
+ tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
+ depends on NET_RADIO
+ select IEEE80211
+ select IEEE80211_CRYPT_WEP
+ ---help---
+ Shared driver code for IEEE 802.11b wireless cards based on
+ Intersil Prism2/2.5/3 chipset. This driver supports so called
+ Host AP mode that allows the card to act as an IEEE 802.11
+ access point.
+
+ See <http://hostap.epitest.fi/> for more information about the
+ Host AP driver configuration and tools. This site includes
+ information and tools (hostapd and wpa_supplicant) for WPA/WPA2
+ support.
+
+ This option includes the base Host AP driver code that is shared by
+ different hardware models. You will also need to enable support for
+ PLX/PCI/CS version of the driver to actually use the driver.
+
+ The driver can be compiled as a module and it will be called
+ "hostap.ko".
+
+config HOSTAP_FIRMWARE
+ bool "Support downloading firmware images with Host AP driver"
+ depends on HOSTAP
+ ---help---
+ Configure Host AP driver to include support for firmware image
+ download. Current version supports only downloading to volatile, i.e.,
+ RAM memory. Flash upgrade is not yet supported.
+
+ Firmware image downloading needs user space tool, prism2_srec. It is
+ available from http://hostap.epitest.fi/.
+
+config HOSTAP_PLX
+ tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
+ depends on PCI && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based
+ PCI adaptors.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_plx.ko".
+
+config HOSTAP_PCI
+ tristate "Host AP driver for Prism2.5 PCI adaptors"
+ depends on PCI && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2.5 PCI adaptors.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_pci.ko".
+
+config HOSTAP_CS
+ tristate "Host AP driver for Prism2/2.5/3 PC Cards"
+ depends on PCMCIA!=n && HOSTAP
+ ---help---
+ Host AP driver's version for Prism2/2.5/3 PC Cards.
+
+ "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this
+ driver and its help text includes more information about the Host AP
+ driver.
+
+ The driver can be compiled as a module and will be named
+ "hostap_cs.ko".
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
new file mode 100644
index 000000000000..fc62235bfc24
--- /dev/null
+++ b/drivers/net/wireless/hostap/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HOSTAP) += hostap.o
+
+obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
+obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o
+obj-$(CONFIG_HOSTAP_PCI) += hostap_pci.o
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
new file mode 100644
index 000000000000..6a96cd9f2685
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap.c
@@ -0,0 +1,1192 @@
+/*
+ * Host AP (software wireless LAN access point) driver for
+ * Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/workqueue.h>
+#include <linux/kmod.h>
+#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211_crypt.h>
+#include <asm/uaccess.h>
+
+#include "hostap_wlan.h"
+#include "hostap_80211.h"
+#include "hostap_ap.h"
+#include "hostap.h"
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP common routines");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+#define TX_TIMEOUT (2 * HZ)
+
+#define PRISM2_MAX_FRAME_SIZE 2304
+#define PRISM2_MIN_MTU 256
+/* FIX: */
+#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */))
+
+
+/* hostap.c */
+static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked);
+static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove);
+
+/* hostap_ap.c */
+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist);
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+static int prism2_hostapd(struct ap_data *ap,
+ struct prism2_hostapd_param *param);
+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt);
+static void ap_control_kickall(struct ap_data *ap);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac);
+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac);
+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
+ u8 *mac);
+#endif /* !PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+#define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
+
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
+
+/* FIX: these could be compiled separately and linked together to hostap.o */
+#include "hostap_ap.c"
+#include "hostap_info.c"
+#include "hostap_ioctl.c"
+#include "hostap_proc.c"
+#include "hostap_80211_rx.c"
+#include "hostap_80211_tx.c"
+
+
+struct net_device * hostap_add_interface(struct local_info *local,
+ int type, int rtnl_locked,
+ const char *prefix,
+ const char *name)
+{
+ struct net_device *dev, *mdev;
+ struct hostap_interface *iface;
+ int ret;
+
+ dev = alloc_etherdev(sizeof(struct hostap_interface));
+ if (dev == NULL)
+ return NULL;
+
+ iface = netdev_priv(dev);
+ iface->dev = dev;
+ iface->local = local;
+ iface->type = type;
+ list_add(&iface->list, &local->hostap_interfaces);
+
+ mdev = local->dev;
+ memcpy(dev->dev_addr, mdev->dev_addr, ETH_ALEN);
+ dev->base_addr = mdev->base_addr;
+ dev->irq = mdev->irq;
+ dev->mem_start = mdev->mem_start;
+ dev->mem_end = mdev->mem_end;
+
+ hostap_setup_dev(dev, local, 0);
+ dev->destructor = free_netdev;
+
+ sprintf(dev->name, "%s%s", prefix, name);
+ if (!rtnl_locked)
+ rtnl_lock();
+
+ ret = 0;
+ if (strchr(dev->name, '%'))
+ ret = dev_alloc_name(dev, dev->name);
+
+ SET_NETDEV_DEV(dev, mdev->class_dev.dev);
+ if (ret >= 0)
+ ret = register_netdevice(dev);
+
+ if (!rtnl_locked)
+ rtnl_unlock();
+
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: failed to add new netdevice!\n",
+ dev->name);
+ free_netdev(dev);
+ return NULL;
+ }
+
+ printk(KERN_DEBUG "%s: registered netdevice %s\n",
+ mdev->name, dev->name);
+
+ return dev;
+}
+
+
+void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
+ int remove_from_list)
+{
+ struct hostap_interface *iface;
+
+ if (!dev)
+ return;
+
+ iface = netdev_priv(dev);
+
+ if (remove_from_list) {
+ list_del(&iface->list);
+ }
+
+ if (dev == iface->local->ddev)
+ iface->local->ddev = NULL;
+ else if (dev == iface->local->apdev)
+ iface->local->apdev = NULL;
+ else if (dev == iface->local->stadev)
+ iface->local->stadev = NULL;
+
+ if (rtnl_locked)
+ unregister_netdevice(dev);
+ else
+ unregister_netdev(dev);
+
+ /* dev->destructor = free_netdev() will free the device data, including
+ * private data, when removing the device */
+}
+
+
+static inline int prism2_wds_special_addr(u8 *addr)
+{
+ if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5])
+ return 0;
+
+ return 1;
+}
+
+
+static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked)
+{
+ struct net_device *dev;
+ struct list_head *ptr;
+ struct hostap_interface *iface, *empty, *match;
+
+ empty = match = NULL;
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+
+ if (prism2_wds_special_addr(iface->u.wds.remote_addr))
+ empty = iface;
+ else if (memcmp(iface->u.wds.remote_addr, remote_addr,
+ ETH_ALEN) == 0) {
+ match = iface;
+ break;
+ }
+ }
+ if (!match && empty && !prism2_wds_special_addr(remote_addr)) {
+ /* take pre-allocated entry into use */
+ memcpy(empty->u.wds.remote_addr, remote_addr, ETH_ALEN);
+ read_unlock_bh(&local->iface_lock);
+ printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n",
+ local->dev->name, empty->dev->name);
+ return 0;
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ if (!prism2_wds_special_addr(remote_addr)) {
+ if (match)
+ return -EEXIST;
+ hostap_add_sta(local->ap, remote_addr);
+ }
+
+ if (local->wds_connections >= local->wds_max_connections)
+ return -ENOBUFS;
+
+ /* verify that there is room for wds# postfix in the interface name */
+ if (strlen(local->dev->name) > IFNAMSIZ - 5) {
+ printk(KERN_DEBUG "'%s' too long base device name\n",
+ local->dev->name);
+ return -EINVAL;
+ }
+
+ dev = hostap_add_interface(local, HOSTAP_INTERFACE_WDS, rtnl_locked,
+ local->ddev->name, "wds%d");
+ if (dev == NULL)
+ return -ENOMEM;
+
+ iface = netdev_priv(dev);
+ memcpy(iface->u.wds.remote_addr, remote_addr, ETH_ALEN);
+
+ local->wds_connections++;
+
+ return 0;
+}
+
+
+static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct hostap_interface *iface, *selected = NULL;
+
+ write_lock_irqsave(&local->iface_lock, flags);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+
+ if (memcmp(iface->u.wds.remote_addr, remote_addr,
+ ETH_ALEN) == 0) {
+ selected = iface;
+ break;
+ }
+ }
+ if (selected && !do_not_remove)
+ list_del(&selected->list);
+ write_unlock_irqrestore(&local->iface_lock, flags);
+
+ if (selected) {
+ if (do_not_remove)
+ memset(selected->u.wds.remote_addr, 0, ETH_ALEN);
+ else {
+ hostap_remove_interface(selected->dev, rtnl_locked, 0);
+ local->wds_connections--;
+ }
+ }
+
+ return selected ? 0 : -ENODEV;
+}
+
+
+u16 hostap_tx_callback_register(local_info_t *local,
+ void (*func)(struct sk_buff *, int ok, void *),
+ void *data)
+{
+ unsigned long flags;
+ struct hostap_tx_callback_info *entry;
+
+ entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
+ GFP_ATOMIC);
+ if (entry == NULL)
+ return 0;
+
+ entry->func = func;
+ entry->data = data;
+
+ spin_lock_irqsave(&local->lock, flags);
+ entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1;
+ entry->next = local->tx_callback;
+ local->tx_callback = entry;
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ return entry->idx;
+}
+
+
+int hostap_tx_callback_unregister(local_info_t *local, u16 idx)
+{
+ unsigned long flags;
+ struct hostap_tx_callback_info *cb, *prev = NULL;
+
+ spin_lock_irqsave(&local->lock, flags);
+ cb = local->tx_callback;
+ while (cb != NULL && cb->idx != idx) {
+ prev = cb;
+ cb = cb->next;
+ }
+ if (cb) {
+ if (prev == NULL)
+ local->tx_callback = cb->next;
+ else
+ prev->next = cb->next;
+ kfree(cb);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ return cb ? 0 : -1;
+}
+
+
+/* val is in host byte order */
+int hostap_set_word(struct net_device *dev, int rid, u16 val)
+{
+ struct hostap_interface *iface;
+ u16 tmp = cpu_to_le16(val);
+ iface = netdev_priv(dev);
+ return iface->local->func->set_rid(dev, rid, &tmp, 2);
+}
+
+
+int hostap_set_string(struct net_device *dev, int rid, const char *val)
+{
+ struct hostap_interface *iface;
+ char buf[MAX_SSID_LEN + 2];
+ int len;
+
+ iface = netdev_priv(dev);
+ len = strlen(val);
+ if (len > MAX_SSID_LEN)
+ return -1;
+ memset(buf, 0, sizeof(buf));
+ buf[0] = len; /* little endian 16 bit word */
+ memcpy(buf + 2, val, len);
+
+ return iface->local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2);
+}
+
+
+u16 hostap_get_porttype(local_info_t *local)
+{
+ if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc)
+ return HFA384X_PORTTYPE_PSEUDO_IBSS;
+ if (local->iw_mode == IW_MODE_ADHOC)
+ return HFA384X_PORTTYPE_IBSS;
+ if (local->iw_mode == IW_MODE_INFRA)
+ return HFA384X_PORTTYPE_BSS;
+ if (local->iw_mode == IW_MODE_REPEAT)
+ return HFA384X_PORTTYPE_WDS;
+ if (local->iw_mode == IW_MODE_MONITOR)
+ return HFA384X_PORTTYPE_PSEUDO_IBSS;
+ return HFA384X_PORTTYPE_HOSTAP;
+}
+
+
+int hostap_set_encryption(local_info_t *local)
+{
+ u16 val, old_val;
+ int i, keylen, len, idx;
+ char keybuf[WEP_KEY_LEN + 1];
+ enum { NONE, WEP, OTHER } encrypt_type;
+
+ idx = local->tx_keyidx;
+ if (local->crypt[idx] == NULL || local->crypt[idx]->ops == NULL)
+ encrypt_type = NONE;
+ else if (strcmp(local->crypt[idx]->ops->name, "WEP") == 0)
+ encrypt_type = WEP;
+ else
+ encrypt_type = OTHER;
+
+ if (local->func->get_rid(local->dev, HFA384X_RID_CNFWEPFLAGS, &val, 2,
+ 1) < 0) {
+ printk(KERN_DEBUG "Could not read current WEP flags.\n");
+ goto fail;
+ }
+ le16_to_cpus(&val);
+ old_val = val;
+
+ if (encrypt_type != NONE || local->privacy_invoked)
+ val |= HFA384X_WEPFLAGS_PRIVACYINVOKED;
+ else
+ val &= ~HFA384X_WEPFLAGS_PRIVACYINVOKED;
+
+ if (local->open_wep || encrypt_type == NONE ||
+ ((local->ieee_802_1x || local->wpa) && local->host_decrypt))
+ val &= ~HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
+ else
+ val |= HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
+
+ if ((encrypt_type != NONE || local->privacy_invoked) &&
+ (encrypt_type == OTHER || local->host_encrypt))
+ val |= HFA384X_WEPFLAGS_HOSTENCRYPT;
+ else
+ val &= ~HFA384X_WEPFLAGS_HOSTENCRYPT;
+ if ((encrypt_type != NONE || local->privacy_invoked) &&
+ (encrypt_type == OTHER || local->host_decrypt))
+ val |= HFA384X_WEPFLAGS_HOSTDECRYPT;
+ else
+ val &= ~HFA384X_WEPFLAGS_HOSTDECRYPT;
+
+ if (val != old_val &&
+ hostap_set_word(local->dev, HFA384X_RID_CNFWEPFLAGS, val)) {
+ printk(KERN_DEBUG "Could not write new WEP flags (0x%x)\n",
+ val);
+ goto fail;
+ }
+
+ if (encrypt_type != WEP)
+ return 0;
+
+ /* 104-bit support seems to require that all the keys are set to the
+ * same keylen */
+ keylen = 6; /* first 5 octets */
+ len = local->crypt[idx]->ops->get_key(keybuf, sizeof(keybuf),
+ NULL, local->crypt[idx]->priv);
+ if (idx >= 0 && idx < WEP_KEYS && len > 5)
+ keylen = WEP_KEY_LEN + 1; /* first 13 octets */
+
+ for (i = 0; i < WEP_KEYS; i++) {
+ memset(keybuf, 0, sizeof(keybuf));
+ if (local->crypt[i]) {
+ (void) local->crypt[i]->ops->get_key(
+ keybuf, sizeof(keybuf),
+ NULL, local->crypt[i]->priv);
+ }
+ if (local->func->set_rid(local->dev,
+ HFA384X_RID_CNFDEFAULTKEY0 + i,
+ keybuf, keylen)) {
+ printk(KERN_DEBUG "Could not set key %d (len=%d)\n",
+ i, keylen);
+ goto fail;
+ }
+ }
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPDEFAULTKEYID, idx)) {
+ printk(KERN_DEBUG "Could not set default keyid %d\n", idx);
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ printk(KERN_DEBUG "%s: encryption setup failed\n", local->dev->name);
+ return -1;
+}
+
+
+int hostap_set_antsel(local_info_t *local)
+{
+ u16 val;
+ int ret = 0;
+
+ if (local->antsel_tx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_TX_CONFIGURE,
+ NULL, &val) == 0) {
+ val &= ~(BIT(2) | BIT(1));
+ switch (local->antsel_tx) {
+ case HOSTAP_ANTSEL_DIVERSITY:
+ val |= BIT(1);
+ break;
+ case HOSTAP_ANTSEL_LOW:
+ break;
+ case HOSTAP_ANTSEL_HIGH:
+ val |= BIT(2);
+ break;
+ }
+
+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_TX_CONFIGURE, &val, NULL)) {
+ printk(KERN_INFO "%s: setting TX AntSel failed\n",
+ local->dev->name);
+ ret = -1;
+ }
+ }
+
+ if (local->antsel_rx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
+ local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_RX_CONFIGURE,
+ NULL, &val) == 0) {
+ val &= ~(BIT(1) | BIT(0));
+ switch (local->antsel_rx) {
+ case HOSTAP_ANTSEL_DIVERSITY:
+ break;
+ case HOSTAP_ANTSEL_LOW:
+ val |= BIT(0);
+ break;
+ case HOSTAP_ANTSEL_HIGH:
+ val |= BIT(0) | BIT(1);
+ break;
+ }
+
+ if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_RX_CONFIGURE, &val, NULL)) {
+ printk(KERN_INFO "%s: setting RX AntSel failed\n",
+ local->dev->name);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+
+int hostap_set_roaming(local_info_t *local)
+{
+ u16 val;
+
+ switch (local->host_roaming) {
+ case 1:
+ val = HFA384X_ROAMING_HOST;
+ break;
+ case 2:
+ val = HFA384X_ROAMING_DISABLED;
+ break;
+ case 0:
+ default:
+ val = HFA384X_ROAMING_FIRMWARE;
+ break;
+ }
+
+ return hostap_set_word(local->dev, HFA384X_RID_CNFROAMINGMODE, val);
+}
+
+
+int hostap_set_auth_algs(local_info_t *local)
+{
+ int val = local->auth_algs;
+ /* At least STA f/w v0.6.2 seems to have issues with cnfAuthentication
+ * set to include both Open and Shared Key flags. It tries to use
+ * Shared Key authentication in that case even if WEP keys are not
+ * configured.. STA f/w v0.7.6 is able to handle such configuration,
+ * but it is unknown when this was fixed between 0.6.2 .. 0.7.6. */
+ if (local->sta_fw_ver < PRISM2_FW_VER(0,7,0) &&
+ val != PRISM2_AUTH_OPEN && val != PRISM2_AUTH_SHARED_KEY)
+ val = PRISM2_AUTH_OPEN;
+
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFAUTHENTICATION, val)) {
+ printk(KERN_INFO "%s: cnfAuthentication setting to 0x%x "
+ "failed\n", local->dev->name, local->auth_algs);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
+{
+ u16 status, fc;
+
+ status = __le16_to_cpu(rx->status);
+
+ printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, "
+ "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; "
+ "jiffies=%ld\n",
+ name, status, (status >> 8) & 0x07, status >> 13, status & 1,
+ rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies);
+
+ fc = __le16_to_cpu(rx->frame_control);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
+ "data_len=%d%s%s\n",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl),
+ __le16_to_cpu(rx->data_len),
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
+ MACSTR "\n",
+ MAC2STR(rx->addr1), MAC2STR(rx->addr2), MAC2STR(rx->addr3),
+ MAC2STR(rx->addr4));
+
+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
+ MAC2STR(rx->dst_addr), MAC2STR(rx->src_addr),
+ __be16_to_cpu(rx->len));
+}
+
+
+void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
+{
+ u16 fc;
+
+ printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d "
+ "tx_control=0x%04x; jiffies=%ld\n",
+ name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate,
+ __le16_to_cpu(tx->tx_control), jiffies);
+
+ fc = __le16_to_cpu(tx->frame_control);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
+ "data_len=%d%s%s\n",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl),
+ __le16_to_cpu(tx->data_len),
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
+ MACSTR "\n",
+ MAC2STR(tx->addr1), MAC2STR(tx->addr2), MAC2STR(tx->addr3),
+ MAC2STR(tx->addr4));
+
+ printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
+ MAC2STR(tx->dst_addr), MAC2STR(tx->src_addr),
+ __be16_to_cpu(tx->len));
+}
+
+
+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); /* addr2 */
+ return ETH_ALEN;
+}
+
+
+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ if (*(u32 *)skb->mac.raw == LWNG_CAP_DID_BASE) {
+ memcpy(haddr, skb->mac.raw +
+ sizeof(struct linux_wlan_ng_prism_hdr) + 10,
+ ETH_ALEN); /* addr2 */
+ } else { /* (*(u32 *)skb->mac.raw == htonl(LWNG_CAPHDR_VERSION)) */
+ memcpy(haddr, skb->mac.raw +
+ sizeof(struct linux_wlan_ng_cap_hdr) + 10,
+ ETH_ALEN); /* addr2 */
+ }
+ return ETH_ALEN;
+}
+
+
+int hostap_80211_get_hdrlen(u16 fc)
+{
+ int hdrlen = 24;
+
+ switch (WLAN_FC_GET_TYPE(fc)) {
+ case IEEE80211_FTYPE_DATA:
+ if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+ hdrlen = 30; /* Addr4 */
+ break;
+ case IEEE80211_FTYPE_CTL:
+ switch (WLAN_FC_GET_STYPE(fc)) {
+ case IEEE80211_STYPE_CTS:
+ case IEEE80211_STYPE_ACK:
+ hdrlen = 10;
+ break;
+ default:
+ hdrlen = 16;
+ break;
+ }
+ break;
+ }
+
+ return hdrlen;
+}
+
+
+struct net_device_stats *hostap_get_stats(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ iface = netdev_priv(dev);
+ return &iface->stats;
+}
+
+
+static int prism2_close(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ PDEBUG(DEBUG_FLOW, "%s: prism2_close\n", dev->name);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (dev == local->ddev) {
+ prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
+ }
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (!local->hostapd && dev == local->dev &&
+ (!local->func->card_present || local->func->card_present(local)) &&
+ local->hw_ready && local->ap && local->iw_mode == IW_MODE_MASTER)
+ hostap_deauth_all_stas(dev, local->ap, 1);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ if (dev == local->dev) {
+ local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
+ }
+
+ if (netif_running(dev)) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+
+ flush_scheduled_work();
+
+ module_put(local->hw_module);
+
+ local->num_dev_open--;
+
+ if (dev != local->dev && local->dev->flags & IFF_UP &&
+ local->master_dev_auto_open && local->num_dev_open == 1) {
+ /* Close master radio interface automatically if it was also
+ * opened automatically and we are now closing the last
+ * remaining non-master device. */
+ dev_close(local->dev);
+ }
+
+ return 0;
+}
+
+
+static int prism2_open(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ PDEBUG(DEBUG_FLOW, "%s: prism2_open\n", dev->name);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: could not set interface UP - no PRI "
+ "f/w\n", dev->name);
+ return 1;
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ if (!try_module_get(local->hw_module))
+ return -ENODEV;
+ local->num_dev_open++;
+
+ if (!local->dev_enabled && local->func->hw_enable(dev, 1)) {
+ printk(KERN_WARNING "%s: could not enable MAC port\n",
+ dev->name);
+ prism2_close(dev);
+ return 1;
+ }
+ if (!local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_ENABLE);
+ local->dev_enabled = 1;
+
+ if (dev != local->dev && !(local->dev->flags & IFF_UP)) {
+ /* Master radio interface is needed for all operation, so open
+ * it automatically when any virtual net_device is opened. */
+ local->master_dev_auto_open = 1;
+ dev_open(local->dev);
+ }
+
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+
+static int prism2_set_mac_address(struct net_device *dev, void *p)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct list_head *ptr;
+ struct sockaddr *addr = p;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->set_rid(dev, HFA384X_RID_CNFOWNMACADDR, addr->sa_data,
+ ETH_ALEN) < 0 || local->func->reset_port(dev))
+ return -EINVAL;
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ memcpy(iface->dev->dev_addr, addr->sa_data, ETH_ALEN);
+ }
+ memcpy(local->dev->dev_addr, addr->sa_data, ETH_ALEN);
+ read_unlock_bh(&local->iface_lock);
+
+ return 0;
+}
+
+
+/* TODO: to be further implemented as soon as Prism2 fully supports
+ * GroupAddresses and correct documentation is available */
+void hostap_set_multicast_list_queue(void *data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
+ local->is_promisc)) {
+ printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",
+ dev->name, local->is_promisc ? "en" : "dis");
+ }
+}
+
+
+static void hostap_set_multicast_list(struct net_device *dev)
+{
+#if 0
+ /* FIX: promiscuous mode seems to be causing a lot of problems with
+ * some station firmware versions (FCSErr frames, invalid MACPort, etc.
+ * corrupted incoming frames). This code is now commented out while the
+ * problems are investigated. */
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if ((dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) {
+ local->is_promisc = 1;
+ } else {
+ local->is_promisc = 0;
+ }
+
+ schedule_work(&local->set_multicast_list_queue);
+#endif
+}
+
+
+static int prism2_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+
+static void prism2_tx_timeout(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_regs regs;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_WARNING "%s Tx timed out! Resetting card\n", dev->name);
+ netif_stop_queue(local->dev);
+
+ local->func->read_regs(dev, &regs);
+ printk(KERN_DEBUG "%s: CMD=%04x EVSTAT=%04x "
+ "OFFSET0=%04x OFFSET1=%04x SWSUPPORT0=%04x\n",
+ dev->name, regs.cmd, regs.evstat, regs.offset0, regs.offset1,
+ regs.swsupport0);
+
+ local->func->schedule_reset(local);
+}
+
+
+void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+ int main_dev)
+{
+ struct hostap_interface *iface;
+
+ iface = netdev_priv(dev);
+ ether_setup(dev);
+
+ /* kernel callbacks */
+ dev->get_stats = hostap_get_stats;
+ if (iface) {
+ /* Currently, we point to the proper spy_data only on
+ * the main_dev. This could be fixed. Jean II */
+ iface->wireless_data.spy_data = &iface->spy_data;
+ dev->wireless_data = &iface->wireless_data;
+ }
+ dev->wireless_handlers =
+ (struct iw_handler_def *) &hostap_iw_handler_def;
+ dev->do_ioctl = hostap_ioctl;
+ dev->open = prism2_open;
+ dev->stop = prism2_close;
+ dev->hard_start_xmit = hostap_data_start_xmit;
+ dev->set_mac_address = prism2_set_mac_address;
+ dev->set_multicast_list = hostap_set_multicast_list;
+ dev->change_mtu = prism2_change_mtu;
+ dev->tx_timeout = prism2_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->mtu = local->mtu;
+ if (!main_dev) {
+ /* use main radio device queue */
+ dev->tx_queue_len = 0;
+ }
+
+ SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
+
+ netif_stop_queue(dev);
+}
+
+
+static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ if (local->apdev)
+ return -EEXIST;
+
+ printk(KERN_DEBUG "%s: enabling hostapd mode\n", dev->name);
+
+ local->apdev = hostap_add_interface(local, HOSTAP_INTERFACE_AP,
+ rtnl_locked, local->ddev->name,
+ "ap");
+ if (local->apdev == NULL)
+ return -ENOMEM;
+
+ local->apdev->hard_start_xmit = hostap_mgmt_start_xmit;
+ local->apdev->type = ARPHRD_IEEE80211;
+ local->apdev->hard_header_parse = hostap_80211_header_parse;
+
+ return 0;
+}
+
+
+static int hostap_disable_hostapd(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name);
+
+ hostap_remove_interface(local->apdev, rtnl_locked, 1);
+ local->apdev = NULL;
+
+ return 0;
+}
+
+
+static int hostap_enable_hostapd_sta(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ if (local->stadev)
+ return -EEXIST;
+
+ printk(KERN_DEBUG "%s: enabling hostapd STA mode\n", dev->name);
+
+ local->stadev = hostap_add_interface(local, HOSTAP_INTERFACE_STA,
+ rtnl_locked, local->ddev->name,
+ "sta");
+ if (local->stadev == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+
+static int hostap_disable_hostapd_sta(local_info_t *local, int rtnl_locked)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name);
+
+ hostap_remove_interface(local->stadev, rtnl_locked, 1);
+ local->stadev = NULL;
+
+ return 0;
+}
+
+
+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked)
+{
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ if (local->hostapd == val)
+ return 0;
+
+ if (val) {
+ ret = hostap_enable_hostapd(local, rtnl_locked);
+ if (ret == 0)
+ local->hostapd = 1;
+ } else {
+ local->hostapd = 0;
+ ret = hostap_disable_hostapd(local, rtnl_locked);
+ if (ret != 0)
+ local->hostapd = 1;
+ }
+
+ return ret;
+}
+
+
+int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked)
+{
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ if (local->hostapd_sta == val)
+ return 0;
+
+ if (val) {
+ ret = hostap_enable_hostapd_sta(local, rtnl_locked);
+ if (ret == 0)
+ local->hostapd_sta = 1;
+ } else {
+ local->hostapd_sta = 0;
+ ret = hostap_disable_hostapd_sta(local, rtnl_locked);
+ if (ret != 0)
+ local->hostapd_sta = 1;
+ }
+
+
+ return ret;
+}
+
+
+int prism2_update_comms_qual(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+ struct hfa384x_comms_quality sq;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ if (!local->sta_fw_ver)
+ ret = -1;
+ else if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) {
+ if (local->func->get_rid(local->dev,
+ HFA384X_RID_DBMCOMMSQUALITY,
+ &sq, sizeof(sq), 1) >= 0) {
+ local->comms_qual = (s16) le16_to_cpu(sq.comm_qual);
+ local->avg_signal = (s16) le16_to_cpu(sq.signal_level);
+ local->avg_noise = (s16) le16_to_cpu(sq.noise_level);
+ local->last_comms_qual_update = jiffies;
+ } else
+ ret = -1;
+ } else {
+ if (local->func->get_rid(local->dev, HFA384X_RID_COMMSQUALITY,
+ &sq, sizeof(sq), 1) >= 0) {
+ local->comms_qual = le16_to_cpu(sq.comm_qual);
+ local->avg_signal = HFA384X_LEVEL_TO_dBm(
+ le16_to_cpu(sq.signal_level));
+ local->avg_noise = HFA384X_LEVEL_TO_dBm(
+ le16_to_cpu(sq.noise_level));
+ local->last_comms_qual_update = jiffies;
+ } else
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
+ u8 *body, size_t bodylen)
+{
+ struct sk_buff *skb;
+ struct hostap_ieee80211_mgmt *mgmt;
+ struct hostap_skb_tx_data *meta;
+ struct net_device *dev = local->dev;
+
+ skb = dev_alloc_skb(IEEE80211_MGMT_HDR_LEN + bodylen);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ mgmt = (struct hostap_ieee80211_mgmt *)
+ skb_put(skb, IEEE80211_MGMT_HDR_LEN);
+ memset(mgmt, 0, IEEE80211_MGMT_HDR_LEN);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
+ memcpy(mgmt->da, dst, ETH_ALEN);
+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->bssid, dst, ETH_ALEN);
+ if (body)
+ memcpy(skb_put(skb, bodylen), body, bodylen);
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = netdev_priv(dev);
+
+ skb->dev = dev;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ dev_queue_xmit(skb);
+
+ return 0;
+}
+
+
+int prism2_sta_deauth(local_info_t *local, u16 reason)
+{
+ union iwreq_data wrqu;
+ int ret;
+
+ if (local->iw_mode != IW_MODE_INFRA ||
+ memcmp(local->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 ||
+ memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0)
+ return 0;
+
+ reason = cpu_to_le16(reason);
+ ret = prism2_sta_send_mgmt(local, local->bssid, IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+ return ret;
+}
+
+
+struct proc_dir_entry *hostap_proc;
+
+static int __init hostap_init(void)
+{
+ if (proc_net != NULL) {
+ hostap_proc = proc_mkdir("hostap", proc_net);
+ if (!hostap_proc)
+ printk(KERN_WARNING "Failed to mkdir "
+ "/proc/net/hostap\n");
+ } else
+ hostap_proc = NULL;
+
+ return 0;
+}
+
+
+static void __exit hostap_exit(void)
+{
+ if (hostap_proc != NULL) {
+ hostap_proc = NULL;
+ remove_proc_entry("hostap", proc_net);
+ }
+}
+
+
+EXPORT_SYMBOL(hostap_set_word);
+EXPORT_SYMBOL(hostap_set_string);
+EXPORT_SYMBOL(hostap_get_porttype);
+EXPORT_SYMBOL(hostap_set_encryption);
+EXPORT_SYMBOL(hostap_set_antsel);
+EXPORT_SYMBOL(hostap_set_roaming);
+EXPORT_SYMBOL(hostap_set_auth_algs);
+EXPORT_SYMBOL(hostap_dump_rx_header);
+EXPORT_SYMBOL(hostap_dump_tx_header);
+EXPORT_SYMBOL(hostap_80211_header_parse);
+EXPORT_SYMBOL(hostap_80211_prism_header_parse);
+EXPORT_SYMBOL(hostap_80211_get_hdrlen);
+EXPORT_SYMBOL(hostap_get_stats);
+EXPORT_SYMBOL(hostap_setup_dev);
+EXPORT_SYMBOL(hostap_proc);
+EXPORT_SYMBOL(hostap_set_multicast_list_queue);
+EXPORT_SYMBOL(hostap_set_hostapd);
+EXPORT_SYMBOL(hostap_set_hostapd_sta);
+EXPORT_SYMBOL(hostap_add_interface);
+EXPORT_SYMBOL(hostap_remove_interface);
+EXPORT_SYMBOL(prism2_update_comms_qual);
+
+module_init(hostap_init);
+module_exit(hostap_exit);
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
new file mode 100644
index 000000000000..5fac89b8ce3a
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -0,0 +1,57 @@
+#ifndef HOSTAP_H
+#define HOSTAP_H
+
+/* hostap.c */
+
+extern struct proc_dir_entry *hostap_proc;
+
+u16 hostap_tx_callback_register(local_info_t *local,
+ void (*func)(struct sk_buff *, int ok, void *),
+ void *data);
+int hostap_tx_callback_unregister(local_info_t *local, u16 idx);
+int hostap_set_word(struct net_device *dev, int rid, u16 val);
+int hostap_set_string(struct net_device *dev, int rid, const char *val);
+u16 hostap_get_porttype(local_info_t *local);
+int hostap_set_encryption(local_info_t *local);
+int hostap_set_antsel(local_info_t *local);
+int hostap_set_roaming(local_info_t *local);
+int hostap_set_auth_algs(local_info_t *local);
+void hostap_dump_rx_header(const char *name,
+ const struct hfa384x_rx_frame *rx);
+void hostap_dump_tx_header(const char *name,
+ const struct hfa384x_tx_frame *tx);
+int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr);
+int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr);
+int hostap_80211_get_hdrlen(u16 fc);
+struct net_device_stats *hostap_get_stats(struct net_device *dev);
+void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+ int main_dev);
+void hostap_set_multicast_list_queue(void *data);
+int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked);
+int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked);
+void hostap_cleanup(local_info_t *local);
+void hostap_cleanup_handler(void *data);
+struct net_device * hostap_add_interface(struct local_info *local,
+ int type, int rtnl_locked,
+ const char *prefix, const char *name);
+void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
+ int remove_from_list);
+int prism2_update_comms_qual(struct net_device *dev);
+int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype,
+ u8 *body, size_t bodylen);
+int prism2_sta_deauth(local_info_t *local, u16 reason);
+
+
+/* hostap_proc.c */
+
+void hostap_init_proc(local_info_t *local);
+void hostap_remove_proc(local_info_t *local);
+
+
+/* hostap_info.c */
+
+void hostap_info_init(local_info_t *local);
+void hostap_info_process(local_info_t *local, struct sk_buff *skb);
+
+
+#endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
new file mode 100644
index 000000000000..bf506f50d722
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -0,0 +1,96 @@
+#ifndef HOSTAP_80211_H
+#define HOSTAP_80211_H
+
+struct hostap_ieee80211_mgmt {
+ u16 frame_control;
+ u16 duration;
+ u8 da[6];
+ u8 sa[6];
+ u8 bssid[6];
+ u16 seq_ctrl;
+ union {
+ struct {
+ u16 auth_alg;
+ u16 auth_transaction;
+ u16 status_code;
+ /* possibly followed by Challenge text */
+ u8 variable[0];
+ } __attribute__ ((packed)) auth;
+ struct {
+ u16 reason_code;
+ } __attribute__ ((packed)) deauth;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) assoc_req;
+ struct {
+ u16 capab_info;
+ u16 status_code;
+ u16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) assoc_resp, reassoc_resp;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[6];
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } __attribute__ ((packed)) reassoc_req;
+ struct {
+ u16 reason_code;
+ } __attribute__ ((packed)) disassoc;
+ struct {
+ } __attribute__ ((packed)) probe_req;
+ struct {
+ u8 timestamp[8];
+ u16 beacon_int;
+ u16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+ } __attribute__ ((packed)) beacon, probe_resp;
+ } u;
+} __attribute__ ((packed));
+
+
+#define IEEE80211_MGMT_HDR_LEN 24
+#define IEEE80211_DATA_HDR3_LEN 24
+#define IEEE80211_DATA_HDR4_LEN 30
+
+
+struct hostap_80211_rx_status {
+ u32 mac_time;
+ u8 signal;
+ u8 noise;
+ u16 rate; /* in 100 kbps */
+};
+
+
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+
+
+/* prism2_rx_80211 'type' argument */
+enum {
+ PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC,
+ PRISM2_RX_NULLFUNC_ACK
+};
+
+int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int type);
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+
+void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
+int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
+int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
+struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt);
+int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
+
+#endif /* HOSTAP_80211_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
new file mode 100644
index 000000000000..ffac50899454
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -0,0 +1,1092 @@
+#include <linux/etherdevice.h>
+
+#include "hostap_80211.h"
+#include "hostap.h"
+
+void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+
+ printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
+ "jiffies=%ld\n",
+ name, rx_stats->signal, rx_stats->noise, rx_stats->rate,
+ skb->len, jiffies);
+
+ if (skb->len < 2)
+ return;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ printk("\n");
+ return;
+ }
+
+ printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
+ le16_to_cpu(hdr->seq_ctl));
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
+ if (skb->len >= 30)
+ printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
+ printk("\n");
+}
+
+
+/* Send RX frame to netif with 802.11 (and possible prism) header.
+ * Called from hardware or software IRQ context. */
+int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int type)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int hdrlen, phdrlen, head_need, tail_need;
+ u16 fc;
+ int prism_header, ret;
+ struct ieee80211_hdr_4addr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ dev->last_rx = jiffies;
+
+ if (dev->type == ARPHRD_IEEE80211_PRISM) {
+ if (local->monitor_type == PRISM2_MONITOR_PRISM) {
+ prism_header = 1;
+ phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);
+ } else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */
+ prism_header = 2;
+ phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
+ }
+ } else {
+ prism_header = 0;
+ phdrlen = 0;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
+ printk(KERN_DEBUG "%s: dropped management frame with header "
+ "version %d\n", dev->name, fc & IEEE80211_FCTL_VERS);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ /* check if there is enough room for extra data; if not, expand skb
+ * buffer to be large enough for the changes */
+ head_need = phdrlen;
+ tail_need = 0;
+#ifdef PRISM2_ADD_BOGUS_CRC
+ tail_need += 4;
+#endif /* PRISM2_ADD_BOGUS_CRC */
+
+ head_need -= skb_headroom(skb);
+ tail_need -= skb_tailroom(skb);
+
+ if (head_need > 0 || tail_need > 0) {
+ if (pskb_expand_head(skb, head_need > 0 ? head_need : 0,
+ tail_need > 0 ? tail_need : 0,
+ GFP_ATOMIC)) {
+ printk(KERN_DEBUG "%s: prism2_rx_80211 failed to "
+ "reallocate skb buffer\n", dev->name);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ }
+
+ /* We now have an skb with enough head and tail room, so just insert
+ * the extra data */
+
+#ifdef PRISM2_ADD_BOGUS_CRC
+ memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */
+#endif /* PRISM2_ADD_BOGUS_CRC */
+
+ if (prism_header == 1) {
+ struct linux_wlan_ng_prism_hdr *hdr;
+ hdr = (struct linux_wlan_ng_prism_hdr *)
+ skb_push(skb, phdrlen);
+ memset(hdr, 0, phdrlen);
+ hdr->msgcode = LWNG_CAP_DID_BASE;
+ hdr->msglen = sizeof(*hdr);
+ memcpy(hdr->devname, dev->name, sizeof(hdr->devname));
+#define LWNG_SETVAL(f,i,s,l,d) \
+hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \
+hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
+ LWNG_SETVAL(hosttime, 1, 0, 4, jiffies);
+ LWNG_SETVAL(mactime, 2, 0, 4, rx_stats->mac_time);
+ LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0);
+ LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal);
+ LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise);
+ LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5);
+ LWNG_SETVAL(istx, 9, 0, 4, 0);
+ LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen);
+#undef LWNG_SETVAL
+ } else if (prism_header == 2) {
+ struct linux_wlan_ng_cap_hdr *hdr;
+ hdr = (struct linux_wlan_ng_cap_hdr *)
+ skb_push(skb, phdrlen);
+ memset(hdr, 0, phdrlen);
+ hdr->version = htonl(LWNG_CAPHDR_VERSION);
+ hdr->length = htonl(phdrlen);
+ hdr->mactime = __cpu_to_be64(rx_stats->mac_time);
+ hdr->hosttime = __cpu_to_be64(jiffies);
+ hdr->phytype = htonl(4); /* dss_dot11_b */
+ hdr->channel = htonl(local->channel);
+ hdr->datarate = htonl(rx_stats->rate);
+ hdr->antenna = htonl(0); /* unknown */
+ hdr->priority = htonl(0); /* unknown */
+ hdr->ssi_type = htonl(3); /* raw */
+ hdr->ssi_signal = htonl(rx_stats->signal);
+ hdr->ssi_noise = htonl(rx_stats->noise);
+ hdr->preamble = htonl(0); /* unknown */
+ hdr->encoding = htonl(1); /* cck */
+ }
+
+ ret = skb->len - phdrlen;
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ skb_pull(skb, hdrlen);
+ if (prism_header)
+ skb_pull(skb, phdrlen);
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = __constant_htons(ETH_P_802_2);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void monitor_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device_stats *stats;
+ int len;
+
+ len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR);
+ stats = hostap_get_stats(dev);
+ stats->rx_packets++;
+ stats->rx_bytes += len;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static struct prism2_frag_entry *
+prism2_frag_cache_find(local_info_t *local, unsigned int seq,
+ unsigned int frag, u8 *src, u8 *dst)
+{
+ struct prism2_frag_entry *entry;
+ int i;
+
+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
+ entry = &local->frag_cache[i];
+ if (entry->skb != NULL &&
+ time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ printk(KERN_DEBUG "%s: expiring fragment cache entry "
+ "seq=%u last_frag=%u\n",
+ local->dev->name, entry->seq, entry->last_frag);
+ dev_kfree_skb(entry->skb);
+ entry->skb = NULL;
+ }
+
+ if (entry->skb != NULL && entry->seq == seq &&
+ (entry->last_frag + 1 == frag || frag == -1) &&
+ memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
+ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
+ return entry;
+ }
+
+ return NULL;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+{
+ struct sk_buff *skb = NULL;
+ u16 sc;
+ unsigned int frag, seq;
+ struct prism2_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
+
+ if (frag == 0) {
+ /* Reserve enough space to fit maximum frame length */
+ skb = dev_alloc_skb(local->dev->mtu +
+ sizeof(struct ieee80211_hdr_4addr) +
+ 8 /* LLC */ +
+ 2 /* alignment */ +
+ 8 /* WEP */ + ETH_ALEN /* WDS */);
+ if (skb == NULL)
+ return NULL;
+
+ entry = &local->frag_cache[local->frag_next_idx];
+ local->frag_next_idx++;
+ if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN)
+ local->frag_next_idx = 0;
+
+ if (entry->skb != NULL)
+ dev_kfree_skb(entry->skb);
+
+ entry->first_frag_time = jiffies;
+ entry->seq = seq;
+ entry->last_frag = frag;
+ entry->skb = skb;
+ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+ } else {
+ /* received a fragment of a frame for which the head fragment
+ * should have already been received */
+ entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2,
+ hdr->addr1);
+ if (entry != NULL) {
+ entry->last_frag = frag;
+ skb = entry->skb;
+ }
+ }
+
+ return skb;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int prism2_frag_cache_invalidate(local_info_t *local,
+ struct ieee80211_hdr_4addr *hdr)
+{
+ u16 sc;
+ unsigned int seq;
+ struct prism2_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ seq = WLAN_GET_SEQ_SEQ(sc) >> 4;
+
+ entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);
+
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: could not invalidate fragment cache "
+ "entry (seq=%u)\n",
+ local->dev->name, seq);
+ return -1;
+ }
+
+ entry->skb = NULL;
+ return 0;
+}
+
+
+static struct hostap_bss_info *__hostap_get_bss(local_info_t *local, u8 *bssid,
+ u8 *ssid, size_t ssid_len)
+{
+ struct list_head *ptr;
+ struct hostap_bss_info *bss;
+
+ list_for_each(ptr, &local->bss_list) {
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
+ (ssid == NULL ||
+ (ssid_len == bss->ssid_len &&
+ memcmp(ssid, bss->ssid, ssid_len) == 0))) {
+ list_move(&bss->list, &local->bss_list);
+ return bss;
+ }
+ }
+
+ return NULL;
+}
+
+
+static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid,
+ u8 *ssid, size_t ssid_len)
+{
+ struct hostap_bss_info *bss;
+
+ if (local->num_bss_info >= HOSTAP_MAX_BSS_COUNT) {
+ bss = list_entry(local->bss_list.prev,
+ struct hostap_bss_info, list);
+ list_del(&bss->list);
+ local->num_bss_info--;
+ } else {
+ bss = (struct hostap_bss_info *)
+ kmalloc(sizeof(*bss), GFP_ATOMIC);
+ if (bss == NULL)
+ return NULL;
+ }
+
+ memset(bss, 0, sizeof(*bss));
+ memcpy(bss->bssid, bssid, ETH_ALEN);
+ memcpy(bss->ssid, ssid, ssid_len);
+ bss->ssid_len = ssid_len;
+ local->num_bss_info++;
+ list_add(&bss->list, &local->bss_list);
+ return bss;
+}
+
+
+static void __hostap_expire_bss(local_info_t *local)
+{
+ struct hostap_bss_info *bss;
+
+ while (local->num_bss_info > 0) {
+ bss = list_entry(local->bss_list.prev,
+ struct hostap_bss_info, list);
+ if (!time_after(jiffies, bss->last_update + 60 * HZ))
+ break;
+
+ list_del(&bss->list);
+ local->num_bss_info--;
+ kfree(bss);
+ }
+}
+
+
+/* Both IEEE 802.11 Beacon and Probe Response frames have similar structure, so
+ * the same routine can be used to parse both of them. */
+static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
+ int stype)
+{
+ struct hostap_ieee80211_mgmt *mgmt;
+ int left, chan = 0;
+ u8 *pos;
+ u8 *ssid = NULL, *wpa = NULL, *rsn = NULL;
+ size_t ssid_len = 0, wpa_len = 0, rsn_len = 0;
+ struct hostap_bss_info *bss;
+
+ if (skb->len < IEEE80211_MGMT_HDR_LEN + sizeof(mgmt->u.beacon))
+ return;
+
+ mgmt = (struct hostap_ieee80211_mgmt *) skb->data;
+ pos = mgmt->u.beacon.variable;
+ left = skb->len - (pos - skb->data);
+
+ while (left >= 2) {
+ if (2 + pos[1] > left)
+ return; /* parse failed */
+ switch (*pos) {
+ case WLAN_EID_SSID:
+ ssid = pos + 2;
+ ssid_len = pos[1];
+ break;
+ case WLAN_EID_GENERIC:
+ if (pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 1) {
+ wpa = pos;
+ wpa_len = pos[1] + 2;
+ }
+ break;
+ case WLAN_EID_RSN:
+ rsn = pos;
+ rsn_len = pos[1] + 2;
+ break;
+ case WLAN_EID_DS_PARAMS:
+ if (pos[1] >= 1)
+ chan = pos[2];
+ break;
+ }
+ left -= 2 + pos[1];
+ pos += 2 + pos[1];
+ }
+
+ if (wpa_len > MAX_WPA_IE_LEN)
+ wpa_len = MAX_WPA_IE_LEN;
+ if (rsn_len > MAX_WPA_IE_LEN)
+ rsn_len = MAX_WPA_IE_LEN;
+ if (ssid_len > sizeof(bss->ssid))
+ ssid_len = sizeof(bss->ssid);
+
+ spin_lock(&local->lock);
+ bss = __hostap_get_bss(local, mgmt->bssid, ssid, ssid_len);
+ if (bss == NULL)
+ bss = __hostap_add_bss(local, mgmt->bssid, ssid, ssid_len);
+ if (bss) {
+ bss->last_update = jiffies;
+ bss->count++;
+ bss->capab_info = le16_to_cpu(mgmt->u.beacon.capab_info);
+ if (wpa) {
+ memcpy(bss->wpa_ie, wpa, wpa_len);
+ bss->wpa_ie_len = wpa_len;
+ } else
+ bss->wpa_ie_len = 0;
+ if (rsn) {
+ memcpy(bss->rsn_ie, rsn, rsn_len);
+ bss->rsn_ie_len = rsn_len;
+ } else
+ bss->rsn_ie_len = 0;
+ bss->chan = chan;
+ }
+ __hostap_expire_bss(local);
+ spin_unlock(&local->lock);
+}
+
+
+static inline int
+hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, u16 type,
+ u16 stype)
+{
+ if (local->iw_mode == IW_MODE_MASTER) {
+ hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
+ skb->data);
+ }
+
+ if (local->hostapd && type == IEEE80211_FTYPE_MGMT) {
+ if (stype == IEEE80211_STYPE_BEACON &&
+ local->iw_mode == IW_MODE_MASTER) {
+ struct sk_buff *skb2;
+ /* Process beacon frames also in kernel driver to
+ * update STA(AP) table statistics */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2)
+ hostap_rx(skb2->dev, skb2, rx_stats);
+ }
+
+ /* send management frames to the user space daemon for
+ * processing */
+ local->apdevstats.rx_packets++;
+ local->apdevstats.rx_bytes += skb->len;
+ if (local->apdev == NULL)
+ return -1;
+ prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT);
+ return 0;
+ }
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ if (type != IEEE80211_FTYPE_MGMT &&
+ type != IEEE80211_FTYPE_CTL) {
+ printk(KERN_DEBUG "%s: unknown management frame "
+ "(type=0x%02x, stype=0x%02x) dropped\n",
+ skb->dev->name, type >> 2, stype >> 4);
+ return -1;
+ }
+
+ hostap_rx(skb->dev, skb, rx_stats);
+ return 0;
+ } else if (type == IEEE80211_FTYPE_MGMT &&
+ (stype == IEEE80211_STYPE_BEACON ||
+ stype == IEEE80211_STYPE_PROBE_RESP)) {
+ hostap_rx_sta_beacon(local, skb, stype);
+ return -1;
+ } else if (type == IEEE80211_FTYPE_MGMT &&
+ (stype == IEEE80211_STYPE_ASSOC_RESP ||
+ stype == IEEE80211_STYPE_REASSOC_RESP)) {
+ /* Ignore (Re)AssocResp silently since these are not currently
+ * needed but are still received when WPA/RSN mode is enabled.
+ */
+ return -1;
+ } else {
+ printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: dropped unhandled"
+ " management frame in non-Host AP mode (type=%d:%d)\n",
+ skb->dev->name, type >> 2, stype >> 4);
+ return -1;
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
+ u8 *addr)
+{
+ struct hostap_interface *iface = NULL;
+ struct list_head *ptr;
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_WDS &&
+ memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0)
+ break;
+ iface = NULL;
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ return iface ? iface->dev : NULL;
+}
+
+
+static inline int
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+ u16 fc, struct net_device **wds)
+{
+ /* FIX: is this really supposed to accept WDS frames only in Master
+ * mode? What about Repeater or Managed with WDS frames? */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=
+ (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS) &&
+ (local->iw_mode != IW_MODE_MASTER || !(fc & IEEE80211_FCTL_TODS)))
+ return 0; /* not a WDS frame */
+
+ /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS)
+ * or own non-standard frame with 4th address after payload */
+ if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 &&
+ (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||
+ hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
+ hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
+ /* RA (or BSSID) is not ours - drop */
+ PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with "
+ "not own or broadcast %s=" MACSTR "\n",
+ local->dev->name,
+ fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
+ MAC2STR(hdr->addr1));
+ return -1;
+ }
+
+ /* check if the frame came from a registered WDS connection */
+ *wds = prism2_rx_get_wds(local, hdr->addr2);
+ if (*wds == NULL && fc & IEEE80211_FCTL_FROMDS &&
+ (local->iw_mode != IW_MODE_INFRA ||
+ !(local->wds_type & HOSTAP_WDS_AP_CLIENT) ||
+ memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) {
+ /* require that WDS link has been registered with TA or the
+ * frame is from current AP when using 'AP client mode' */
+ PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
+ "from unknown TA=" MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ if (local->ap && local->ap->autom_ap_wds)
+ hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
+ return -1;
+ }
+
+ if (*wds && !(fc & IEEE80211_FCTL_FROMDS) && local->ap &&
+ hostap_is_sta_assoc(local->ap, hdr->addr2)) {
+ /* STA is actually associated with us even though it has a
+ * registered WDS link. Assume it is in 'AP client' mode.
+ * Since this is a 3-addr frame, assume it is not (bogus) WDS
+ * frame and process it like any normal ToDS frame from
+ * associated STA. */
+ *wds = NULL;
+ }
+
+ return 0;
+}
+
+
+static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
+{
+ struct net_device *dev = local->dev;
+ u16 fc, ethertype;
+ struct ieee80211_hdr_4addr *hdr;
+ u8 *pos;
+
+ if (skb->len < 24)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* check that the frame is unicast frame to us */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
+ memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ /* ToDS frame with own addr BSSID and DA */
+ } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ /* FromDS frame with own addr as DA */
+ } else
+ return 0;
+
+ if (skb->len < 24 + 8)
+ return 0;
+
+ /* check for port access entity Ethernet type */
+ pos = skb->data + 24;
+ ethertype = (pos[6] << 8) | pos[7];
+ if (ethertype == ETH_P_PAE)
+ return 1;
+
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline int
+hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr_4addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ if (local->tkip_countermeasures &&
+ strcmp(crypt->ops->name, "TKIP") == 0) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "received packet from " MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ }
+ return -1;
+ }
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: decryption failed (SA=" MACSTR
+ ") res=%d\n",
+ local->dev->name, MAC2STR(hdr->addr2), res);
+ local->comm_tallies.rx_discards_wep_undecryptable++;
+ return -1;
+ }
+
+ return res;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static inline int
+hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
+ int keyidx, struct ieee80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr_4addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
+ " (SA=" MACSTR " keyidx=%d)\n",
+ local->dev->name, MAC2STR(hdr->addr2), keyidx);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ). */
+void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr_4addr *hdr;
+ size_t hdrlen;
+ u16 fc, type, stype, sc;
+ struct net_device *wds = NULL;
+ struct net_device_stats *stats;
+ unsigned int frag;
+ u8 *payload;
+ struct sk_buff *skb2 = NULL;
+ u16 ethertype;
+ int frame_authorized = 0;
+ int from_assoc_ap = 0;
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ struct ieee80211_crypt_data *crypt = NULL;
+ void *sta = NULL;
+ int keyidx = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ iface->stats.rx_packets++;
+ iface->stats.rx_bytes += skb->len;
+
+ /* dev is the master radio device; change this to be the default
+ * virtual interface (this may be changed to WDS device below) */
+ dev = local->ddev;
+ iface = netdev_priv(dev);
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ stats = hostap_get_stats(dev);
+
+ if (skb->len < 10)
+ goto rx_dropped;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ /* Put this code here so that we avoid duplicating it in all
+ * Rx paths. - Jean II */
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ /* If spy monitoring on */
+ if (iface->spy_data.spy_number > 0) {
+ struct iw_quality wstats;
+ wstats.level = rx_stats->signal;
+ wstats.noise = rx_stats->noise;
+ wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
+ | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
+ /* Update spy records */
+ wireless_spy_update(dev, hdr->addr2, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+ hostap_update_rx_stats(local->ap, hdr, rx_stats);
+
+ if (local->iw_mode == IW_MODE_MONITOR) {
+ monitor_rx(dev, skb, rx_stats);
+ return;
+ }
+
+ if (local->host_decrypt) {
+ int idx = 0;
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+ crypt = local->crypt[idx];
+ sta = NULL;
+
+ /* Use station specific key to override default keys if the
+ * receiver address is a unicast address ("individual RA"). If
+ * bcrx_sta_key parameter is set, station specific key is used
+ * even with broad/multicast targets (this is against IEEE
+ * 802.11, but makes it easier to use different keys with
+ * stations that do not support WEP key mapping). */
+
+ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ (void) hostap_handle_sta_crypto(local, hdr, &crypt,
+ &sta);
+
+ /* allow NULL decrypt to indicate an station specific override
+ * for default encryption */
+ if (crypt && (crypt->ops == NULL ||
+ crypt->ops->decrypt_mpdu == NULL))
+ crypt = NULL;
+
+ if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
+#if 0
+ /* This seems to be triggered by some (multicast?)
+ * frames from other than current BSS, so just drop the
+ * frames silently instead of filling system log with
+ * these reports. */
+ printk(KERN_DEBUG "%s: WEP decryption failed (not set)"
+ " (SA=" MACSTR ")\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+#endif
+ local->comm_tallies.rx_discards_wep_undecryptable++;
+ goto rx_dropped;
+ }
+ }
+
+ if (type != IEEE80211_FTYPE_DATA) {
+ if (type == IEEE80211_FTYPE_MGMT &&
+ stype == IEEE80211_STYPE_AUTH &&
+ fc & IEEE80211_FCTL_PROTECTED && local->host_decrypt &&
+ (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
+ {
+ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
+ "from " MACSTR "\n", dev->name,
+ MAC2STR(hdr->addr2));
+ /* TODO: could inform hostapd about this so that it
+ * could send auth failure report */
+ goto rx_dropped;
+ }
+
+ if (hostap_rx_frame_mgmt(local, skb, rx_stats, type, stype))
+ goto rx_dropped;
+ else
+ goto rx_exit;
+ }
+
+ /* Data frame - extract src/dst addresses */
+ if (skb->len < IEEE80211_DATA_HDR3_LEN)
+ goto rx_dropped;
+
+ switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr3, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ if (skb->len < IEEE80211_DATA_HDR4_LEN)
+ goto rx_dropped;
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+ break;
+ case 0:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ }
+
+ if (hostap_rx_frame_wds(local, hdr, fc, &wds))
+ goto rx_dropped;
+ if (wds) {
+ skb->dev = dev = wds;
+ stats = hostap_get_stats(dev);
+ }
+
+ if (local->iw_mode == IW_MODE_MASTER && !wds &&
+ (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ local->stadev &&
+ memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) {
+ /* Frame from BSSID of the AP for which we are a client */
+ skb->dev = dev = local->stadev;
+ stats = hostap_get_stats(dev);
+ from_assoc_ap = 1;
+ }
+
+ dev->last_rx = jiffies;
+
+ if ((local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT) &&
+ !from_assoc_ap) {
+ switch (hostap_handle_sta_rx(local, dev, skb, rx_stats,
+ wds != NULL)) {
+ case AP_RX_CONTINUE_NOT_AUTHORIZED:
+ frame_authorized = 0;
+ break;
+ case AP_RX_CONTINUE:
+ frame_authorized = 1;
+ break;
+ case AP_RX_DROP:
+ goto rx_dropped;
+ case AP_RX_EXIT:
+ goto rx_exit;
+ }
+ }
+
+ /* Nullfunc frames may have PS-bit set, so they must be passed to
+ * hostap_handle_sta_rx() before being dropped here. */
+ if (stype != IEEE80211_STYPE_DATA &&
+ stype != IEEE80211_STYPE_DATA_CFACK &&
+ stype != IEEE80211_STYPE_DATA_CFPOLL &&
+ stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
+ if (stype != IEEE80211_STYPE_NULLFUNC)
+ printk(KERN_DEBUG "%s: RX: dropped data frame "
+ "with no data (type=0x%02x, subtype=0x%02x)\n",
+ dev->name, type >> 2, stype >> 4);
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
+ goto rx_dropped;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+
+ /* skb: hdr + (possibly fragmented) plaintext payload */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ (frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
+ int flen;
+ struct sk_buff *frag_skb =
+ prism2_frag_cache_get(local, hdr);
+ if (!frag_skb) {
+ printk(KERN_DEBUG "%s: Rx cannot get skb from "
+ "fragment cache (morefrag=%d seq=%u frag=%u)\n",
+ dev->name, (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
+ WLAN_GET_SEQ_SEQ(sc) >> 4, frag);
+ goto rx_dropped;
+ }
+
+ flen = skb->len;
+ if (frag != 0)
+ flen -= hdrlen;
+
+ if (frag_skb->tail + flen > frag_skb->end) {
+ printk(KERN_WARNING "%s: host decrypted and "
+ "reassembled frame did not fit skb\n",
+ dev->name);
+ prism2_frag_cache_invalidate(local, hdr);
+ goto rx_dropped;
+ }
+
+ if (frag == 0) {
+ /* copy first fragment (including full headers) into
+ * beginning of the fragment cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data, flen);
+ } else {
+ /* append frame payload to the end of the fragment
+ * cache skb */
+ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+ flen);
+ }
+ dev_kfree_skb(skb);
+ skb = NULL;
+
+ if (fc & IEEE80211_FCTL_MOREFRAGS) {
+ /* more fragments expected - leave the skb in fragment
+ * cache for now; it will be delivered to upper layers
+ * after all fragments have been received */
+ goto rx_exit;
+ }
+
+ /* this was the last fragment and the frame will be
+ * delivered, so remove skb from fragment cache */
+ skb = frag_skb;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ prism2_frag_cache_invalidate(local, hdr);
+ }
+
+ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+ * encrypted/authenticated */
+
+ if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
+ if (local->ieee_802_1x &&
+ hostap_is_eapol_frame(local, skb)) {
+ /* pass unencrypted EAPOL frames even if encryption is
+ * configured */
+ PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X - passing "
+ "unencrypted EAPOL frame\n", local->dev->name);
+ } else {
+ printk(KERN_DEBUG "%s: encryption configured, but RX "
+ "frame not encrypted (SA=" MACSTR ")\n",
+ local->dev->name, MAC2STR(hdr->addr2));
+ goto rx_dropped;
+ }
+ }
+
+ if (local->drop_unencrypted && !(fc & IEEE80211_FCTL_PROTECTED) &&
+ !hostap_is_eapol_frame(local, skb)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: dropped unencrypted RX data "
+ "frame from " MACSTR " (drop_unencrypted=1)\n",
+ dev->name, MAC2STR(hdr->addr2));
+ }
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possible reassembled) full plaintext payload */
+
+ payload = skb->data + hdrlen;
+ ethertype = (payload[6] << 8) | payload[7];
+
+ /* If IEEE 802.1X is used, check whether the port is authorized to send
+ * the received frame. */
+ if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) {
+ if (ethertype == ETH_P_PAE) {
+ PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X frame\n",
+ dev->name);
+ if (local->hostapd && local->apdev) {
+ /* Send IEEE 802.1X frames to the user
+ * space daemon for processing */
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_MGMT);
+ local->apdevstats.rx_packets++;
+ local->apdevstats.rx_bytes += skb->len;
+ goto rx_exit;
+ }
+ } else if (!frame_authorized) {
+ printk(KERN_DEBUG "%s: dropped frame from "
+ "unauthorized port (IEEE 802.1X): "
+ "ethertype=0x%04x\n",
+ dev->name, ethertype);
+ goto rx_dropped;
+ }
+ }
+
+ /* convert hdr + possible LLC headers into Ethernet header */
+ if (skb->len - hdrlen >= 8 &&
+ ((memcmp(payload, rfc1042_header, 6) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(payload, bridge_tunnel_header, 6) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+ * replace EtherType */
+ skb_pull(skb, hdrlen + 6);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ u16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ skb_pull(skb, hdrlen);
+ len = htons(skb->len);
+ memcpy(skb_push(skb, 2), &len, 2);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ }
+
+ if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS) &&
+ skb->len >= ETH_HLEN + ETH_ALEN) {
+ /* Non-standard frame: get addr4 from its bogus location after
+ * the payload */
+ memcpy(skb->data + ETH_ALEN,
+ skb->data + skb->len - ETH_ALEN, ETH_ALEN);
+ skb_trim(skb, skb->len - ETH_ALEN);
+ }
+
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+
+ if (local->iw_mode == IW_MODE_MASTER && !wds &&
+ local->ap->bridge_packets) {
+ if (dst[0] & 0x01) {
+ /* copy multicast frame both to the higher layers and
+ * to the wireless media */
+ local->ap->bridged_multicast++;
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ printk(KERN_DEBUG "%s: skb_clone failed for "
+ "multicast frame\n", dev->name);
+ } else if (hostap_is_sta_authorized(local->ap, dst)) {
+ /* send frame directly to the associated STA using
+ * wireless media and not passing to higher layers */
+ local->ap->bridged_unicast++;
+ skb2 = skb;
+ skb = NULL;
+ }
+ }
+
+ if (skb2 != NULL) {
+ /* send to wireless media */
+ skb2->protocol = __constant_htons(ETH_P_802_3);
+ skb2->mac.raw = skb2->nh.raw = skb2->data;
+ /* skb2->nh.raw = skb2->data + ETH_HLEN; */
+ skb2->dev = dev;
+ dev_queue_xmit(skb2);
+ }
+
+ if (skb) {
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->dev = dev;
+ netif_rx(skb);
+ }
+
+ rx_exit:
+ if (sta)
+ hostap_handle_sta_release(sta);
+ return;
+
+ rx_dropped:
+ dev_kfree_skb(skb);
+
+ stats->rx_dropped++;
+ goto rx_exit;
+}
+
+
+EXPORT_SYMBOL(hostap_80211_rx);
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
new file mode 100644
index 000000000000..9d24f8a38ac5
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -0,0 +1,524 @@
+void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
+{
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+
+ printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
+ name, skb->len, jiffies);
+
+ if (skb->len < 2)
+ return;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
+ fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ printk("\n");
+ return;
+ }
+
+ printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
+ le16_to_cpu(hdr->seq_ctl));
+
+ printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
+ if (skb->len >= 30)
+ printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
+ printk("\n");
+}
+
+
+/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta)
+ * Convert Ethernet header into a suitable IEEE 802.11 header depending on
+ * device configuration. */
+int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int need_headroom, need_tailroom = 0;
+ struct ieee80211_hdr_4addr hdr;
+ u16 fc, ethertype = 0;
+ enum {
+ WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
+ } use_wds = WDS_NO;
+ u8 *encaps_data;
+ int hdr_len, encaps_len, skip_header_bytes;
+ int to_assoc_ap = 0;
+ struct hostap_skb_tx_data *meta;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < ETH_HLEN) {
+ printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ kfree_skb(skb);
+ return 0;
+ }
+
+ if (local->ddev != dev) {
+ use_wds = (local->iw_mode == IW_MODE_MASTER &&
+ !(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ?
+ WDS_OWN_FRAME : WDS_COMPLIANT_FRAME;
+ if (dev == local->stadev) {
+ to_assoc_ap = 1;
+ use_wds = WDS_NO;
+ } else if (dev == local->apdev) {
+ printk(KERN_DEBUG "%s: prism2_tx: trying to use "
+ "AP device with Ethernet net dev\n", dev->name);
+ kfree_skb(skb);
+ return 0;
+ }
+ } else {
+ if (local->iw_mode == IW_MODE_REPEAT) {
+ printk(KERN_DEBUG "%s: prism2_tx: trying to use "
+ "non-WDS link in Repeater mode\n", dev->name);
+ kfree_skb(skb);
+ return 0;
+ } else if (local->iw_mode == IW_MODE_INFRA &&
+ (local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
+ memcmp(skb->data + ETH_ALEN, dev->dev_addr,
+ ETH_ALEN) != 0) {
+ /* AP client mode: send frames with foreign src addr
+ * using 4-addr WDS frames */
+ use_wds = WDS_COMPLIANT_FRAME;
+ }
+ }
+
+ /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload
+ * ==>
+ * Prism2 TX frame with 802.11 header:
+ * txdesc (address order depending on used mode; includes dst_addr and
+ * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel;
+ * proto[2], payload {, possible addr4[6]} */
+
+ ethertype = (skb->data[12] << 8) | skb->data[13];
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ /* Length of data after IEEE 802.11 header */
+ encaps_data = NULL;
+ encaps_len = 0;
+ skip_header_bytes = ETH_HLEN;
+ if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
+ encaps_data = bridge_tunnel_header;
+ encaps_len = sizeof(bridge_tunnel_header);
+ skip_header_bytes -= 2;
+ } else if (ethertype >= 0x600) {
+ encaps_data = rfc1042_header;
+ encaps_len = sizeof(rfc1042_header);
+ skip_header_bytes -= 2;
+ }
+
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+ hdr_len = IEEE80211_DATA_HDR3_LEN;
+
+ if (use_wds != WDS_NO) {
+ /* Note! Prism2 station firmware has problems with sending real
+ * 802.11 frames with four addresses; until these problems can
+ * be fixed or worked around, 4-addr frames needed for WDS are
+ * using incompatible format: FromDS flag is not set and the
+ * fourth address is added after the frame payload; it is
+ * assumed, that the receiving station knows how to handle this
+ * frame format */
+
+ if (use_wds == WDS_COMPLIANT_FRAME) {
+ fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
+ /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA,
+ * Addr4 = SA */
+ memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ hdr_len += ETH_ALEN;
+ } else {
+ /* bogus 4-addr format to workaround Prism2 station
+ * f/w bug */
+ fc |= IEEE80211_FCTL_TODS;
+ /* From DS: Addr1 = DA (used as RA),
+ * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA),
+ */
+
+ /* SA from skb->data + ETH_ALEN will be added after
+ * frame payload; use hdr.addr4 as a temporary buffer
+ */
+ memcpy(&hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ need_tailroom += ETH_ALEN;
+ }
+
+ /* send broadcast and multicast frames to broadcast RA, if
+ * configured; otherwise, use unicast RA of the WDS link */
+ if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) &&
+ skb->data[0] & 0x01)
+ memset(&hdr.addr1, 0xff, ETH_ALEN);
+ else if (iface->type == HOSTAP_INTERFACE_WDS)
+ memcpy(&hdr.addr1, iface->u.wds.remote_addr,
+ ETH_ALEN);
+ else
+ memcpy(&hdr.addr1, local->bssid, ETH_ALEN);
+ memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) {
+ fc |= IEEE80211_FCTL_FROMDS;
+ /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */
+ memcpy(&hdr.addr1, skb->data, ETH_ALEN);
+ memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) {
+ fc |= IEEE80211_FCTL_TODS;
+ /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
+ memcpy(&hdr.addr1, to_assoc_ap ?
+ local->assoc_ap_addr : local->bssid, ETH_ALEN);
+ memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+ memcpy(&hdr.addr3, skb->data, ETH_ALEN);
+ } else if (local->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
+ memcpy(&hdr.addr1, skb->data, ETH_ALEN);
+ memcpy(&hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+ memcpy(&hdr.addr3, local->bssid, ETH_ALEN);
+ }
+
+ hdr.frame_ctl = cpu_to_le16(fc);
+
+ skb_pull(skb, skip_header_bytes);
+ need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len;
+ if (skb_tailroom(skb) < need_tailroom) {
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ if (pskb_expand_head(skb, need_headroom, need_tailroom,
+ GFP_ATOMIC)) {
+ kfree_skb(skb);
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ } else if (skb_headroom(skb) < need_headroom) {
+ struct sk_buff *tmp = skb;
+ skb = skb_realloc_headroom(skb, need_headroom);
+ kfree_skb(tmp);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ } else {
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL) {
+ iface->stats.tx_dropped++;
+ return 0;
+ }
+ }
+
+ if (encaps_data)
+ memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
+ memcpy(skb_push(skb, hdr_len), &hdr, hdr_len);
+ if (use_wds == WDS_OWN_FRAME) {
+ memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN);
+ }
+
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+
+ skb->mac.raw = skb->data;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ if (use_wds)
+ meta->flags |= HOSTAP_TX_FLAGS_WDS;
+ meta->ethertype = ethertype;
+ meta->iface = iface;
+
+ /* Send IEEE 802.11 encapsulated frame using the master radio device */
+ skb->dev = local->dev;
+ dev_queue_xmit(skb);
+ return 0;
+}
+
+
+/* hard_start_xmit function for hostapd wlan#ap interfaces */
+int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hostap_skb_tx_data *meta;
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < 10) {
+ printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ kfree_skb(skb);
+ return 0;
+ }
+
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = iface;
+
+ if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
+ u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN +
+ sizeof(rfc1042_header)];
+ meta->ethertype = (pos[0] << 8) | pos[1];
+ }
+ }
+
+ /* Send IEEE 802.11 encapsulated frame using the master radio device */
+ skb->dev = local->dev;
+ dev_queue_xmit(skb);
+ return 0;
+}
+
+
+/* Called only from software IRQ */
+struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc;
+ int hdr_len, res;
+
+ iface = netdev_priv(skb->dev);
+ local = iface->local;
+
+ if (skb->len < IEEE80211_DATA_HDR3_LEN) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ if (local->tkip_countermeasures &&
+ crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "TX packet to " MACSTR "\n",
+ local->dev->name, MAC2STR(hdr->addr1));
+ }
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
+ skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
+ pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
+ crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hdr_len = hostap_80211_get_hdrlen(fc);
+
+ /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+ * call both MSDU and MPDU encryption functions from here. */
+ atomic_inc(&crypt->refcnt);
+ res = 0;
+ if (crypt->ops->encrypt_msdu)
+ res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv);
+ if (res == 0 && crypt->ops->encrypt_mpdu)
+ res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ return skb;
+}
+
+
+/* hard_start_xmit function for master radio interface wifi#.
+ * AP processing (TX rate control, power save buffering, etc.).
+ * Use hardware TX function to send the frame. */
+int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 1;
+ u16 fc;
+ struct hostap_tx_data tx;
+ ap_tx_ret tx_ret;
+ struct hostap_skb_tx_data *meta;
+ int no_encrypt = 0;
+ struct ieee80211_hdr_4addr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ tx.skb = skb;
+ tx.sta_ptr = NULL;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
+ printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
+ "expected 0x%08x)\n",
+ dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+
+ if (local->host_encrypt) {
+ /* Set crypt to default algorithm and key; will be replaced in
+ * AP code if STA has own alg/key */
+ tx.crypt = local->crypt[local->tx_keyidx];
+ tx.host_encrypt = 1;
+ } else {
+ tx.crypt = NULL;
+ tx.host_encrypt = 0;
+ }
+
+ if (skb->len < 24) {
+ printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
+ "(len=%d)\n", dev->name, skb->len);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+
+ /* FIX (?):
+ * Wi-Fi 802.11b test plan suggests that AP should ignore power save
+ * bit in authentication and (re)association frames and assume tha
+ * STA remains awake for the response. */
+ tx_ret = hostap_handle_sta_tx(local, &tx);
+ skb = tx.skb;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ switch (tx_ret) {
+ case AP_TX_CONTINUE:
+ break;
+ case AP_TX_CONTINUE_NOT_AUTHORIZED:
+ if (local->ieee_802_1x &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ meta->ethertype != ETH_P_PAE &&
+ !(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
+ printk(KERN_DEBUG "%s: dropped frame to unauthorized "
+ "port (IEEE 802.1X): ethertype=0x%04x\n",
+ dev->name, meta->ethertype);
+ hostap_dump_tx_80211(dev->name, skb);
+
+ ret = 0; /* drop packet */
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+ break;
+ case AP_TX_DROP:
+ ret = 0; /* drop packet */
+ iface->stats.tx_dropped++;
+ goto fail;
+ case AP_TX_RETRY:
+ goto fail;
+ case AP_TX_BUFFERED:
+ /* do not free skb here, it will be freed when the
+ * buffered frame is sent/timed out */
+ ret = 0;
+ goto tx_exit;
+ }
+
+ /* Request TX callback if protocol version is 2 in 802.11 header;
+ * this version 2 is a special case used between hostapd and kernel
+ * driver */
+ if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) &&
+ local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) {
+ meta->tx_cb_idx = local->ap->tx_callback_idx;
+
+ /* remove special version from the frame header */
+ fc &= ~IEEE80211_FCTL_VERS;
+ hdr->frame_ctl = cpu_to_le16(fc);
+ }
+
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) {
+ no_encrypt = 1;
+ tx.crypt = NULL;
+ }
+
+ if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
+ !(fc & IEEE80211_FCTL_VERS)) {
+ no_encrypt = 1;
+ PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
+ "unencrypted EAPOL frame\n", dev->name);
+ tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */
+ }
+
+ if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
+ tx.crypt = NULL;
+ else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {
+ /* Add ISWEP flag both for firmware and host based encryption
+ */
+ fc |= IEEE80211_FCTL_PROTECTED;
+ hdr->frame_ctl = cpu_to_le16(fc);
+ } else if (local->drop_unencrypted &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ meta->ethertype != ETH_P_PAE) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: dropped unencrypted TX data "
+ "frame (drop_unencrypted=1)\n", dev->name);
+ }
+ iface->stats.tx_dropped++;
+ ret = 0;
+ goto fail;
+ }
+
+ if (tx.crypt) {
+ skb = hostap_tx_encrypt(skb, tx.crypt);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: TX - encryption failed\n",
+ dev->name);
+ ret = 0;
+ goto fail;
+ }
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) {
+ printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
+ "expected 0x%08x) after hostap_tx_encrypt\n",
+ dev->name, meta->magic,
+ HOSTAP_SKB_TX_DATA_MAGIC);
+ ret = 0;
+ iface->stats.tx_dropped++;
+ goto fail;
+ }
+ }
+
+ if (local->func->tx == NULL || local->func->tx(skb, dev)) {
+ ret = 0;
+ iface->stats.tx_dropped++;
+ } else {
+ ret = 0;
+ iface->stats.tx_packets++;
+ iface->stats.tx_bytes += skb->len;
+ }
+
+ fail:
+ if (!ret && skb)
+ dev_kfree_skb(skb);
+ tx_exit:
+ if (tx.sta_ptr)
+ hostap_handle_sta_release(tx.sta_ptr);
+ return ret;
+}
+
+
+EXPORT_SYMBOL(hostap_dump_tx_80211);
+EXPORT_SYMBOL(hostap_tx_encrypt);
+EXPORT_SYMBOL(hostap_master_start_xmit);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
new file mode 100644
index 000000000000..9da94ab7f05f
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -0,0 +1,3288 @@
+/*
+ * Intersil Prism2 driver with Host AP (software access point) support
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This file is to be included into hostap.c when S/W AP functionality is
+ * compiled.
+ *
+ * AP: FIX:
+ * - if unicast Class 2 (assoc,reassoc,disassoc) frame received from
+ * unauthenticated STA, send deauth. frame (8802.11: 5.5)
+ * - if unicast Class 3 (data with to/from DS,deauth,pspoll) frame received
+ * from authenticated, but unassoc STA, send disassoc frame (8802.11: 5.5)
+ * - if unicast Class 3 received from unauthenticated STA, send deauth. frame
+ * (8802.11: 5.5)
+ */
+
+static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
+ DEF_INTS };
+module_param_array(other_ap_policy, int, NULL, 0444);
+MODULE_PARM_DESC(other_ap_policy, "Other AP beacon monitoring policy (0-3)");
+
+static int ap_max_inactivity[MAX_PARM_DEVICES] = { AP_MAX_INACTIVITY_SEC,
+ DEF_INTS };
+module_param_array(ap_max_inactivity, int, NULL, 0444);
+MODULE_PARM_DESC(ap_max_inactivity, "AP timeout (in seconds) for station "
+ "inactivity");
+
+static int ap_bridge_packets[MAX_PARM_DEVICES] = { 1, DEF_INTS };
+module_param_array(ap_bridge_packets, int, NULL, 0444);
+MODULE_PARM_DESC(ap_bridge_packets, "Bridge packets directly between "
+ "stations");
+
+static int autom_ap_wds[MAX_PARM_DEVICES] = { 0, DEF_INTS };
+module_param_array(autom_ap_wds, int, NULL, 0444);
+MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs "
+ "automatically");
+
+
+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta);
+static void hostap_event_expired_sta(struct net_device *dev,
+ struct sta_info *sta);
+static void handle_add_proc_queue(void *data);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static void handle_wds_oper_queue(void *data);
+static void prism2_send_mgmt(struct net_device *dev,
+ u16 type_subtype, char *body,
+ int body_len, u8 *addr, u16 tx_cb_idx);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int ap_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast);
+ p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast);
+ p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ);
+ p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets);
+ p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack);
+ p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds);
+ p += sprintf(p, "auth_algs=%u\n", ap->local->auth_algs);
+ p += sprintf(p, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc);
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta)
+{
+ sta->hnext = ap->sta_hash[STA_HASH(sta->addr)];
+ ap->sta_hash[STA_HASH(sta->addr)] = sta;
+}
+
+static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
+{
+ struct sta_info *s;
+
+ s = ap->sta_hash[STA_HASH(sta->addr)];
+ if (s == NULL) return;
+ if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+ ap->sta_hash[STA_HASH(sta->addr)] = s->hnext;
+ return;
+ }
+
+ while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, ETH_ALEN)
+ != 0)
+ s = s->hnext;
+ if (s->hnext != NULL)
+ s->hnext = s->hnext->hnext;
+ else
+ printk("AP: could not remove STA " MACSTR " from hash table\n",
+ MAC2STR(sta->addr));
+}
+
+static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
+{
+ if (sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+
+ if (ap->proc != NULL) {
+ char name[20];
+ sprintf(name, MACSTR, MAC2STR(sta->addr));
+ remove_proc_entry(name, ap->proc);
+ }
+
+ if (sta->crypt) {
+ sta->crypt->ops->deinit(sta->crypt->priv);
+ kfree(sta->crypt);
+ sta->crypt = NULL;
+ }
+
+ skb_queue_purge(&sta->tx_buf);
+
+ ap->num_sta--;
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->aid > 0)
+ ap->sta_aid[sta->aid - 1] = NULL;
+
+ if (!sta->ap && sta->u.sta.challenge)
+ kfree(sta->u.sta.challenge);
+ del_timer(&sta->timer);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ kfree(sta);
+}
+
+
+static void hostap_set_tim(local_info_t *local, int aid, int set)
+{
+ if (local->func->set_tim)
+ local->func->set_tim(local->dev, aid, set);
+}
+
+
+static void hostap_event_new_sta(struct net_device *dev, struct sta_info *sta)
+{
+ union iwreq_data wrqu;
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVREGISTERED, &wrqu, NULL);
+}
+
+
+static void hostap_event_expired_sta(struct net_device *dev,
+ struct sta_info *sta)
+{
+ union iwreq_data wrqu;
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVEXPIRED, &wrqu, NULL);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void ap_handle_timer(unsigned long data)
+{
+ struct sta_info *sta = (struct sta_info *) data;
+ local_info_t *local;
+ struct ap_data *ap;
+ unsigned long next_time = 0;
+ int was_assoc;
+
+ if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) {
+ PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n");
+ return;
+ }
+
+ local = sta->local;
+ ap = local->ap;
+ was_assoc = sta->flags & WLAN_STA_ASSOC;
+
+ if (atomic_read(&sta->users) != 0)
+ next_time = jiffies + HZ;
+ else if ((sta->flags & WLAN_STA_PERM) && !(sta->flags & WLAN_STA_AUTH))
+ next_time = jiffies + ap->max_inactivity;
+
+ if (time_before(jiffies, sta->last_rx + ap->max_inactivity)) {
+ /* station activity detected; reset timeout state */
+ sta->timeout_next = STA_NULLFUNC;
+ next_time = sta->last_rx + ap->max_inactivity;
+ } else if (sta->timeout_next == STA_DISASSOC &&
+ !(sta->flags & WLAN_STA_PENDING_POLL)) {
+ /* STA ACKed data nullfunc frame poll */
+ sta->timeout_next = STA_NULLFUNC;
+ next_time = jiffies + ap->max_inactivity;
+ }
+
+ if (next_time) {
+ sta->timer.expires = next_time;
+ add_timer(&sta->timer);
+ return;
+ }
+
+ if (sta->ap)
+ sta->timeout_next = STA_DEAUTH;
+
+ if (sta->timeout_next == STA_DEAUTH && !(sta->flags & WLAN_STA_PERM)) {
+ spin_lock(&ap->sta_table_lock);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ spin_unlock(&ap->sta_table_lock);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ } else if (sta->timeout_next == STA_DISASSOC)
+ sta->flags &= ~WLAN_STA_ASSOC;
+
+ if (was_assoc && !(sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+
+ if (sta->timeout_next == STA_DEAUTH && sta->aid > 0 &&
+ !skb_queue_empty(&sta->tx_buf)) {
+ hostap_set_tim(local, sta->aid, 0);
+ sta->flags &= ~WLAN_STA_TIM;
+ }
+
+ if (sta->ap) {
+ if (ap->autom_ap_wds) {
+ PDEBUG(DEBUG_AP, "%s: removing automatic WDS "
+ "connection to AP " MACSTR "\n",
+ local->dev->name, MAC2STR(sta->addr));
+ hostap_wds_link_oper(local, sta->addr, WDS_DEL);
+ }
+ } else if (sta->timeout_next == STA_NULLFUNC) {
+ /* send data frame to poll STA and check whether this frame
+ * is ACKed */
+ /* FIX: IEEE80211_STYPE_NULLFUNC would be more appropriate, but
+ * it is apparently not retried so TX Exc events are not
+ * received for it */
+ sta->flags |= WLAN_STA_PENDING_POLL;
+ prism2_send_mgmt(local->dev, IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_DATA, NULL, 0,
+ sta->addr, ap->tx_callback_poll);
+ } else {
+ int deauth = sta->timeout_next == STA_DEAUTH;
+ u16 resp;
+ PDEBUG(DEBUG_AP, "%s: sending %s info to STA " MACSTR
+ "(last=%lu, jiffies=%lu)\n",
+ local->dev->name,
+ deauth ? "deauthentication" : "disassociation",
+ MAC2STR(sta->addr), sta->last_rx, jiffies);
+
+ resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID :
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
+ prism2_send_mgmt(local->dev, IEEE80211_FTYPE_MGMT |
+ (deauth ? IEEE80211_STYPE_DEAUTH :
+ IEEE80211_STYPE_DISASSOC),
+ (char *) &resp, 2, sta->addr, 0);
+ }
+
+ if (sta->timeout_next == STA_DEAUTH) {
+ if (sta->flags & WLAN_STA_PERM) {
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " would have been "
+ "removed, but it has 'perm' flag\n",
+ local->dev->name, MAC2STR(sta->addr));
+ } else
+ ap_free_sta(ap, sta);
+ return;
+ }
+
+ if (sta->timeout_next == STA_NULLFUNC) {
+ sta->timeout_next = STA_DISASSOC;
+ sta->timer.expires = jiffies + AP_DISASSOC_DELAY;
+ } else {
+ sta->timeout_next = STA_DEAUTH;
+ sta->timer.expires = jiffies + AP_DEAUTH_DELAY;
+ }
+
+ add_timer(&sta->timer);
+}
+
+
+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
+ int resend)
+{
+ u8 addr[ETH_ALEN];
+ u16 resp;
+ int i;
+
+ PDEBUG(DEBUG_AP, "%s: Deauthenticate all stations\n", dev->name);
+ memset(addr, 0xff, ETH_ALEN);
+
+ resp = __constant_cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+ /* deauth message sent; try to resend it few times; the message is
+ * broadcast, so it may be delayed until next DTIM; there is not much
+ * else we can do at this point since the driver is going to be shut
+ * down */
+ for (i = 0; i < 5; i++) {
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_DEAUTH,
+ (char *) &resp, 2, addr, 0);
+
+ if (!resend || ap->num_sta <= 0)
+ return;
+
+ mdelay(50);
+ }
+}
+
+
+static int ap_control_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+ char *policy_txt;
+ struct list_head *ptr;
+ struct mac_entry *entry;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ switch (ap->mac_restrictions.policy) {
+ case MAC_POLICY_OPEN:
+ policy_txt = "open";
+ break;
+ case MAC_POLICY_ALLOW:
+ policy_txt = "allow";
+ break;
+ case MAC_POLICY_DENY:
+ policy_txt = "deny";
+ break;
+ default:
+ policy_txt = "unknown";
+ break;
+ };
+ p += sprintf(p, "MAC policy: %s\n", policy_txt);
+ p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
+ p += sprintf(p, "MAC list:\n");
+ spin_lock_bh(&ap->mac_restrictions.lock);
+ for (ptr = ap->mac_restrictions.mac_list.next;
+ ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+ if (p - page > PAGE_SIZE - 80) {
+ p += sprintf(p, "All entries did not fit one page.\n");
+ break;
+ }
+
+ entry = list_entry(ptr, struct mac_entry, list);
+ p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
+ }
+ spin_unlock_bh(&ap->mac_restrictions.lock);
+
+ return (p - page);
+}
+
+
+static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct mac_entry *entry;
+
+ entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL);
+ if (entry == NULL)
+ return -1;
+
+ memcpy(entry->addr, mac, ETH_ALEN);
+
+ spin_lock_bh(&mac_restrictions->lock);
+ list_add_tail(&entry->list, &mac_restrictions->mac_list);
+ mac_restrictions->entries++;
+ spin_unlock_bh(&mac_restrictions->lock);
+
+ return 0;
+}
+
+
+static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct list_head *ptr;
+ struct mac_entry *entry;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next;
+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+
+ if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+ list_del(ptr);
+ kfree(entry);
+ mac_restrictions->entries--;
+ spin_unlock_bh(&mac_restrictions->lock);
+ return 0;
+ }
+ }
+ spin_unlock_bh(&mac_restrictions->lock);
+ return -1;
+}
+
+
+static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
+ u8 *mac)
+{
+ struct list_head *ptr;
+ struct mac_entry *entry;
+ int found = 0;
+
+ if (mac_restrictions->policy == MAC_POLICY_OPEN)
+ return 0;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next;
+ ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+
+ if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock_bh(&mac_restrictions->lock);
+
+ if (mac_restrictions->policy == MAC_POLICY_ALLOW)
+ return !found;
+ else
+ return found;
+}
+
+
+static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+{
+ struct list_head *ptr, *n;
+ struct mac_entry *entry;
+
+ if (mac_restrictions->entries == 0)
+ return;
+
+ spin_lock_bh(&mac_restrictions->lock);
+ for (ptr = mac_restrictions->mac_list.next, n = ptr->next;
+ ptr != &mac_restrictions->mac_list;
+ ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct mac_entry, list);
+ list_del(ptr);
+ kfree(entry);
+ }
+ mac_restrictions->entries = 0;
+ spin_unlock_bh(&mac_restrictions->lock);
+}
+
+
+static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
+ u8 *mac)
+{
+ struct sta_info *sta;
+ u16 resp;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, mac);
+ if (sta) {
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -EINVAL;
+
+ resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH,
+ (char *) &resp, 2, sta->addr, 0);
+
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(dev, sta);
+
+ ap_free_sta(ap, sta);
+
+ return 0;
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static void ap_control_kickall(struct ap_data *ap)
+{
+ struct list_head *ptr, *n;
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list;
+ ptr = n, n = ptr->next) {
+ sta = list_entry(ptr, struct sta_info, list);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+#define PROC_LIMIT (PAGE_SIZE - 80)
+
+static int prism2_ap_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct ap_data *ap = (struct ap_data *) data;
+ struct list_head *ptr;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ if (!sta->ap)
+ continue;
+
+ p += sprintf(p, MACSTR " %d %d %d %d '", MAC2STR(sta->addr),
+ sta->u.ap.channel, sta->last_rx_signal,
+ sta->last_rx_silence, sta->last_rx_rate);
+ for (i = 0; i < sta->u.ap.ssid_len; i++)
+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
+ sta->u.ap.ssid[i] < 127) ?
+ "%c" : "<%02x>"),
+ sta->u.ap.ssid[i]);
+ p += sprintf(p, "'");
+ if (sta->capability & WLAN_CAPABILITY_ESS)
+ p += sprintf(p, " [ESS]");
+ if (sta->capability & WLAN_CAPABILITY_IBSS)
+ p += sprintf(p, " [IBSS]");
+ if (sta->capability & WLAN_CAPABILITY_PRIVACY)
+ p += sprintf(p, " [WEP]");
+ p += sprintf(p, "\n");
+
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "hostap: ap proc did not fit\n");
+ break;
+ }
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver)
+{
+ if (!ap)
+ return;
+
+ if (sta_fw_ver == PRISM2_FW_VER(0,8,0)) {
+ PDEBUG(DEBUG_AP, "Using data::nullfunc ACK workaround - "
+ "firmware upgrade recommended\n");
+ ap->nullfunc_ack = 1;
+ } else
+ ap->nullfunc_ack = 0;
+
+ if (sta_fw_ver == PRISM2_FW_VER(1,4,2)) {
+ printk(KERN_WARNING "%s: Warning: secondary station firmware "
+ "version 1.4.2 does not seem to work in Host AP mode\n",
+ ap->local->dev->name);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ u16 fc;
+ struct ieee80211_hdr_4addr *hdr;
+
+ if (!ap->local->hostapd || !ap->local->apdev) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* Pass the TX callback frame to the hostapd; use 802.11 header version
+ * 1 to indicate failure (no ACK) and 2 success (frame ACKed) */
+
+ fc &= ~IEEE80211_FCTL_VERS;
+ fc |= ok ? BIT(1) : BIT(0);
+ hdr->frame_ctl = cpu_to_le16(fc);
+
+ skb->dev = ap->local->apdev;
+ skb_pull(skb, hostap_80211_get_hdrlen(fc));
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = __constant_htons(ETH_P_802_2);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct net_device *dev = ap->local->dev;
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc, *pos, auth_alg, auth_transaction, status;
+ struct sta_info *sta = NULL;
+ char *txt = NULL;
+
+ if (ap->local->hostapd) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
+ skb->len < IEEE80211_MGMT_HDR_LEN + 6) {
+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid "
+ "frame\n", dev->name);
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ auth_alg = le16_to_cpu(*pos++);
+ auth_transaction = le16_to_cpu(*pos++);
+ status = le16_to_cpu(*pos++);
+
+ if (!ok) {
+ txt = "frame was not ACKed";
+ goto done;
+ }
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&ap->sta_table_lock);
+
+ if (!sta) {
+ txt = "STA not found";
+ goto done;
+ }
+
+ if (status == WLAN_STATUS_SUCCESS &&
+ ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
+ (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
+ txt = "STA authenticated";
+ sta->flags |= WLAN_STA_AUTH;
+ sta->last_auth = jiffies;
+ } else if (status != WLAN_STATUS_SUCCESS)
+ txt = "authentication failed";
+
+ done:
+ if (sta)
+ atomic_dec(&sta->users);
+ if (txt) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth_cb - alg=%d trans#=%d "
+ "status=%d - %s\n",
+ dev->name, MAC2STR(hdr->addr1), auth_alg,
+ auth_transaction, status, txt);
+ }
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct net_device *dev = ap->local->dev;
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc, *pos, status;
+ struct sta_info *sta = NULL;
+ char *txt = NULL;
+
+ if (ap->local->hostapd) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
+ (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
+ WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_REASSOC_RESP) ||
+ skb->len < IEEE80211_MGMT_HDR_LEN + 4) {
+ printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid "
+ "frame\n", dev->name);
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (!ok) {
+ txt = "frame was not ACKed";
+ goto done;
+ }
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&ap->sta_table_lock);
+
+ if (!sta) {
+ txt = "STA not found";
+ goto done;
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos++;
+ status = le16_to_cpu(*pos++);
+ if (status == WLAN_STATUS_SUCCESS) {
+ if (!(sta->flags & WLAN_STA_ASSOC))
+ hostap_event_new_sta(dev, sta);
+ txt = "STA associated";
+ sta->flags |= WLAN_STA_ASSOC;
+ sta->last_assoc = jiffies;
+ } else
+ txt = "association failed";
+
+ done:
+ if (sta)
+ atomic_dec(&sta->users);
+ if (txt) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " assoc_cb - %s\n",
+ dev->name, MAC2STR(hdr->addr1), txt);
+ }
+ dev_kfree_skb(skb);
+}
+
+/* Called only as a tasklet (software IRQ); TX callback for poll frames used
+ * in verifying whether the STA is still present. */
+static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct ieee80211_hdr_4addr *hdr;
+ struct sta_info *sta;
+
+ if (skb->len < 24)
+ goto fail;
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ if (ok) {
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+ spin_unlock(&ap->sta_table_lock);
+ } else {
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " did not ACK activity "
+ "poll frame\n", ap->local->dev->name,
+ MAC2STR(hdr->addr1));
+ }
+
+ fail:
+ dev_kfree_skb(skb);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+void hostap_init_data(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+
+ if (ap == NULL) {
+ printk(KERN_WARNING "hostap_init_data: ap == NULL\n");
+ return;
+ }
+ memset(ap, 0, sizeof(struct ap_data));
+ ap->local = local;
+
+ ap->ap_policy = GET_INT_PARM(other_ap_policy, local->card_idx);
+ ap->bridge_packets = GET_INT_PARM(ap_bridge_packets, local->card_idx);
+ ap->max_inactivity =
+ GET_INT_PARM(ap_max_inactivity, local->card_idx) * HZ;
+ ap->autom_ap_wds = GET_INT_PARM(autom_ap_wds, local->card_idx);
+
+ spin_lock_init(&ap->sta_table_lock);
+ INIT_LIST_HEAD(&ap->sta_list);
+
+ /* Initialize task queue structure for AP management */
+ INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap);
+
+ ap->tx_callback_idx =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb, ap);
+ if (ap->tx_callback_idx == 0)
+ printk(KERN_WARNING "%s: failed to register TX callback for "
+ "AP\n", local->dev->name);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local);
+
+ ap->tx_callback_auth =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap);
+ ap->tx_callback_assoc =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap);
+ ap->tx_callback_poll =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_poll, ap);
+ if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0 ||
+ ap->tx_callback_poll == 0)
+ printk(KERN_WARNING "%s: failed to register TX callback for "
+ "AP\n", local->dev->name);
+
+ spin_lock_init(&ap->mac_restrictions.lock);
+ INIT_LIST_HEAD(&ap->mac_restrictions.mac_list);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ ap->initialized = 1;
+}
+
+
+void hostap_init_ap_proc(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+
+ ap->proc = local->proc;
+ if (ap->proc == NULL)
+ return;
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("ap_debug", 0, ap->proc,
+ ap_debug_proc_read, ap);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ create_proc_read_entry("ap_control", 0, ap->proc,
+ ap_control_proc_read, ap);
+ create_proc_read_entry("ap", 0, ap->proc,
+ prism2_ap_proc_read, ap);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+}
+
+
+void hostap_free_data(struct ap_data *ap)
+{
+ struct list_head *n, *ptr;
+
+ if (ap == NULL || !ap->initialized) {
+ printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
+ "initialized - skip resource freeing\n");
+ return;
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (ap->crypt)
+ ap->crypt->deinit(ap->crypt_priv);
+ ap->crypt = ap->crypt_priv = NULL;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ list_for_each_safe(ptr, n, &ap->sta_list) {
+ struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+ }
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ if (ap->proc != NULL) {
+ remove_proc_entry("ap_debug", ap->proc);
+ }
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (ap->proc != NULL) {
+ remove_proc_entry("ap", ap->proc);
+ remove_proc_entry("ap_control", ap->proc);
+ }
+ ap_control_flush_macs(&ap->mac_restrictions);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ ap->initialized = 0;
+}
+
+
+/* caller should have mutex for AP STA list handling */
+static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta)
+{
+ struct sta_info *s;
+
+ s = ap->sta_hash[STA_HASH(sta)];
+ while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0)
+ s = s->hnext;
+ return s;
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+/* Called from timer handler and from scheduled AP queue handlers */
+static void prism2_send_mgmt(struct net_device *dev,
+ u16 type_subtype, char *body,
+ int body_len, u8 *addr, u16 tx_cb_idx)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ieee80211_hdr_4addr *hdr;
+ u16 fc;
+ struct sk_buff *skb;
+ struct hostap_skb_tx_data *meta;
+ int hdrlen;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ dev = local->dev; /* always use master radio device */
+ iface = netdev_priv(dev);
+
+ if (!(dev->flags & IFF_UP)) {
+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt - device is not UP - "
+ "cannot send frame\n", dev->name);
+ return;
+ }
+
+ skb = dev_alloc_skb(sizeof(*hdr) + body_len);
+ if (skb == NULL) {
+ PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt failed to allocate "
+ "skb\n", dev->name);
+ return;
+ }
+
+ fc = type_subtype;
+ hdrlen = hostap_80211_get_hdrlen(fc);
+ hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
+ if (body)
+ memcpy(skb_put(skb, body_len), body, body_len);
+
+ memset(hdr, 0, hdrlen);
+
+ /* FIX: ctrl::ack sending used special HFA384X_TX_CTRL_802_11
+ * tx_control instead of using local->tx_control */
+
+
+ memcpy(hdr->addr1, addr, ETH_ALEN); /* DA / RA */
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) {
+ fc |= IEEE80211_FCTL_FROMDS;
+ memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */
+ memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* SA */
+ } else if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL) {
+ /* control:ACK does not have addr2 or addr3 */
+ memset(hdr->addr2, 0, ETH_ALEN);
+ memset(hdr->addr3, 0, ETH_ALEN);
+ } else {
+ memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* SA */
+ memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */
+ }
+
+ hdr->frame_ctl = cpu_to_le16(fc);
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ memset(meta, 0, sizeof(*meta));
+ meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
+ meta->iface = iface;
+ meta->tx_cb_idx = tx_cb_idx;
+
+ skb->dev = dev;
+ skb->mac.raw = skb->nh.raw = skb->data;
+ dev_queue_xmit(skb);
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+static int prism2_sta_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ struct sta_info *sta = (struct sta_info *) data;
+ int i;
+
+ /* FIX: possible race condition.. the STA data could have just expired,
+ * but proc entry was still here so that the read could have started;
+ * some locking should be done here.. */
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "%s=" MACSTR "\nusers=%d\naid=%d\n"
+ "flags=0x%04x%s%s%s%s%s%s%s\n"
+ "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
+ sta->ap ? "AP" : "STA",
+ MAC2STR(sta->addr), atomic_read(&sta->users), sta->aid,
+ sta->flags,
+ sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
+ sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
+ sta->flags & WLAN_STA_PS ? " PS" : "",
+ sta->flags & WLAN_STA_TIM ? " TIM" : "",
+ sta->flags & WLAN_STA_PERM ? " PERM" : "",
+ sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",
+ sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",
+ sta->capability, sta->listen_interval);
+ /* supported_rates: 500 kbit/s units with msb ignored */
+ for (i = 0; i < sizeof(sta->supported_rates); i++)
+ if (sta->supported_rates[i] != 0)
+ p += sprintf(p, "%d%sMbps ",
+ (sta->supported_rates[i] & 0x7f) / 2,
+ sta->supported_rates[i] & 1 ? ".5" : "");
+ p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n"
+ "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n"
+ "tx_packets=%lu\n"
+ "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n"
+ "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n"
+ "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"
+ "tx[11M]=%d\n"
+ "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",
+ jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,
+ sta->last_tx,
+ sta->rx_packets, sta->tx_packets, sta->rx_bytes,
+ sta->tx_bytes, skb_queue_len(&sta->tx_buf),
+ sta->last_rx_silence,
+ sta->last_rx_signal, sta->last_rx_rate / 10,
+ sta->last_rx_rate % 10 ? ".5" : "",
+ sta->tx_rate, sta->tx_count[0], sta->tx_count[1],
+ sta->tx_count[2], sta->tx_count[3], sta->rx_count[0],
+ sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);
+ if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats)
+ p = sta->crypt->ops->print_stats(p, sta->crypt->priv);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->ap) {
+ if (sta->u.ap.channel >= 0)
+ p += sprintf(p, "channel=%d\n", sta->u.ap.channel);
+ p += sprintf(p, "ssid=");
+ for (i = 0; i < sta->u.ap.ssid_len; i++)
+ p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&
+ sta->u.ap.ssid[i] < 127) ?
+ "%c" : "<%02x>"),
+ sta->u.ap.ssid[i]);
+ p += sprintf(p, "\n");
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ return (p - page);
+}
+
+
+static void handle_add_proc_queue(void *data)
+{
+ struct ap_data *ap = (struct ap_data *) data;
+ struct sta_info *sta;
+ char name[20];
+ struct add_sta_proc_data *entry, *prev;
+
+ entry = ap->add_sta_proc_entries;
+ ap->add_sta_proc_entries = NULL;
+
+ while (entry) {
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, entry->addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (sta) {
+ sprintf(name, MACSTR, MAC2STR(sta->addr));
+ sta->proc = create_proc_read_entry(
+ name, 0, ap->proc,
+ prism2_sta_proc_read, sta);
+
+ atomic_dec(&sta->users);
+ }
+
+ prev = entry;
+ entry = entry->next;
+ kfree(prev);
+ }
+}
+
+
+static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr)
+{
+ struct sta_info *sta;
+
+ sta = (struct sta_info *)
+ kmalloc(sizeof(struct sta_info), GFP_ATOMIC);
+ if (sta == NULL) {
+ PDEBUG(DEBUG_AP, "AP: kmalloc failed\n");
+ return NULL;
+ }
+
+ /* initialize STA info data */
+ memset(sta, 0, sizeof(struct sta_info));
+ sta->local = ap->local;
+ skb_queue_head_init(&sta->tx_buf);
+ memcpy(sta->addr, addr, ETH_ALEN);
+
+ atomic_inc(&sta->users);
+ spin_lock_bh(&ap->sta_table_lock);
+ list_add(&sta->list, &ap->sta_list);
+ ap->num_sta++;
+ ap_sta_hash_add(ap, sta);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (ap->proc) {
+ struct add_sta_proc_data *entry;
+ /* schedule a non-interrupt context process to add a procfs
+ * entry for the STA since procfs code use GFP_KERNEL */
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry) {
+ memcpy(entry->addr, sta->addr, ETH_ALEN);
+ entry->next = ap->add_sta_proc_entries;
+ ap->add_sta_proc_entries = entry;
+ schedule_work(&ap->add_sta_proc_queue);
+ } else
+ printk(KERN_DEBUG "Failed to add STA proc data\n");
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ init_timer(&sta->timer);
+ sta->timer.expires = jiffies + ap->max_inactivity;
+ sta->timer.data = (unsigned long) sta;
+ sta->timer.function = ap_handle_timer;
+ if (!ap->local->hostapd)
+ add_timer(&sta->timer);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ return sta;
+}
+
+
+static int ap_tx_rate_ok(int rateidx, struct sta_info *sta,
+ local_info_t *local)
+{
+ if (rateidx > sta->tx_max_rate ||
+ !(sta->tx_supp_rates & (1 << rateidx)))
+ return 0;
+
+ if (local->tx_rate_control != 0 &&
+ !(local->tx_rate_control & (1 << rateidx)))
+ return 0;
+
+ return 1;
+}
+
+
+static void prism2_check_tx_rates(struct sta_info *sta)
+{
+ int i;
+
+ sta->tx_supp_rates = 0;
+ for (i = 0; i < sizeof(sta->supported_rates); i++) {
+ if ((sta->supported_rates[i] & 0x7f) == 2)
+ sta->tx_supp_rates |= WLAN_RATE_1M;
+ if ((sta->supported_rates[i] & 0x7f) == 4)
+ sta->tx_supp_rates |= WLAN_RATE_2M;
+ if ((sta->supported_rates[i] & 0x7f) == 11)
+ sta->tx_supp_rates |= WLAN_RATE_5M5;
+ if ((sta->supported_rates[i] & 0x7f) == 22)
+ sta->tx_supp_rates |= WLAN_RATE_11M;
+ }
+ sta->tx_max_rate = sta->tx_rate = sta->tx_rate_idx = 0;
+ if (sta->tx_supp_rates & WLAN_RATE_1M) {
+ sta->tx_max_rate = 0;
+ if (ap_tx_rate_ok(0, sta, sta->local)) {
+ sta->tx_rate = 10;
+ sta->tx_rate_idx = 0;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_2M) {
+ sta->tx_max_rate = 1;
+ if (ap_tx_rate_ok(1, sta, sta->local)) {
+ sta->tx_rate = 20;
+ sta->tx_rate_idx = 1;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_5M5) {
+ sta->tx_max_rate = 2;
+ if (ap_tx_rate_ok(2, sta, sta->local)) {
+ sta->tx_rate = 55;
+ sta->tx_rate_idx = 2;
+ }
+ }
+ if (sta->tx_supp_rates & WLAN_RATE_11M) {
+ sta->tx_max_rate = 3;
+ if (ap_tx_rate_ok(3, sta, sta->local)) {
+ sta->tx_rate = 110;
+ sta->tx_rate_idx = 3;
+ }
+ }
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void ap_crypt_init(struct ap_data *ap)
+{
+ ap->crypt = ieee80211_get_crypto_ops("WEP");
+
+ if (ap->crypt) {
+ if (ap->crypt->init) {
+ ap->crypt_priv = ap->crypt->init(0);
+ if (ap->crypt_priv == NULL)
+ ap->crypt = NULL;
+ else {
+ u8 key[WEP_KEY_LEN];
+ get_random_bytes(key, WEP_KEY_LEN);
+ ap->crypt->set_key(key, WEP_KEY_LEN, NULL,
+ ap->crypt_priv);
+ }
+ }
+ }
+
+ if (ap->crypt == NULL) {
+ printk(KERN_WARNING "AP could not initialize WEP: load module "
+ "ieee80211_crypt_wep.ko\n");
+ }
+}
+
+
+/* Generate challenge data for shared key authentication. IEEE 802.11 specifies
+ * that WEP algorithm is used for generating challange. This should be unique,
+ * but otherwise there is not really need for randomness etc. Initialize WEP
+ * with pseudo random key and then use increasing IV to get unique challenge
+ * streams.
+ *
+ * Called only as a scheduled task for pending AP frames.
+ */
+static char * ap_auth_make_challenge(struct ap_data *ap)
+{
+ char *tmpbuf;
+ struct sk_buff *skb;
+
+ if (ap->crypt == NULL) {
+ ap_crypt_init(ap);
+ if (ap->crypt == NULL)
+ return NULL;
+ }
+
+ tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
+ if (tmpbuf == NULL) {
+ PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");
+ return NULL;
+ }
+
+ skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
+ ap->crypt->extra_mpdu_prefix_len +
+ ap->crypt->extra_mpdu_postfix_len);
+ if (skb == NULL) {
+ kfree(tmpbuf);
+ return NULL;
+ }
+
+ skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
+ memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
+ WLAN_AUTH_CHALLENGE_LEN);
+ if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
+ dev_kfree_skb(skb);
+ kfree(tmpbuf);
+ return NULL;
+ }
+
+ memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
+ WLAN_AUTH_CHALLENGE_LEN);
+ dev_kfree_skb(skb);
+
+ return tmpbuf;
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_authen(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ size_t hdrlen;
+ struct ap_data *ap = local->ap;
+ char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
+ int len, olen;
+ u16 auth_alg, auth_transaction, status_code, *pos;
+ u16 resp = WLAN_STATUS_SUCCESS, fc;
+ struct sta_info *sta = NULL;
+ struct ieee80211_crypt_data *crypt;
+ char *txt = "";
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hdrlen = hostap_80211_get_hdrlen(fc);
+
+ if (len < 6) {
+ PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "
+ "(len=%d) from " MACSTR "\n", dev->name, len,
+ MAC2STR(hdr->addr2));
+ return;
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta && sta->crypt)
+ crypt = sta->crypt;
+ else {
+ int idx = 0;
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+ crypt = local->crypt[idx];
+ }
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ auth_alg = __le16_to_cpu(*pos);
+ pos++;
+ auth_transaction = __le16_to_cpu(*pos);
+ pos++;
+ status_code = __le16_to_cpu(*pos);
+ pos++;
+
+ if (memcmp(dev->dev_addr, hdr->addr2, ETH_ALEN) == 0 ||
+ ap_control_mac_deny(&ap->mac_restrictions, hdr->addr2)) {
+ txt = "authentication denied";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ if (((local->auth_algs & PRISM2_AUTH_OPEN) &&
+ auth_alg == WLAN_AUTH_OPEN) ||
+ ((local->auth_algs & PRISM2_AUTH_SHARED_KEY) &&
+ crypt && auth_alg == WLAN_AUTH_SHARED_KEY)) {
+ } else {
+ txt = "unsupported algorithm";
+ resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
+ goto fail;
+ }
+
+ if (len >= 8) {
+ u8 *u = (u8 *) pos;
+ if (*u == WLAN_EID_CHALLENGE) {
+ if (*(u + 1) != WLAN_AUTH_CHALLENGE_LEN) {
+ txt = "invalid challenge len";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+ if (len - 8 < WLAN_AUTH_CHALLENGE_LEN) {
+ txt = "challenge underflow";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+ challenge = (char *) (u + 2);
+ }
+ }
+
+ if (sta && sta->ap) {
+ if (time_after(jiffies, sta->u.ap.last_beacon +
+ (10 * sta->listen_interval * HZ) / 1024)) {
+ PDEBUG(DEBUG_AP, "%s: no beacons received for a while,"
+ " assuming AP " MACSTR " is now STA\n",
+ dev->name, MAC2STR(sta->addr));
+ sta->ap = 0;
+ sta->flags = 0;
+ sta->u.sta.challenge = NULL;
+ } else {
+ txt = "AP trying to authenticate?";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+
+ if ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) ||
+ (auth_alg == WLAN_AUTH_SHARED_KEY &&
+ (auth_transaction == 1 ||
+ (auth_transaction == 3 && sta != NULL &&
+ sta->u.sta.challenge != NULL)))) {
+ } else {
+ txt = "unknown authentication transaction number";
+ resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
+ goto fail;
+ }
+
+ if (sta == NULL) {
+ txt = "new STA";
+
+ if (local->ap->num_sta >= MAX_STA_COUNT) {
+ /* FIX: might try to remove some old STAs first? */
+ txt = "no more room for new STAs";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ sta = ap_add_sta(local->ap, hdr->addr2);
+ if (sta == NULL) {
+ txt = "ap_add_sta failed";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+
+ switch (auth_alg) {
+ case WLAN_AUTH_OPEN:
+ txt = "authOK";
+ /* IEEE 802.11 standard is not completely clear about
+ * whether STA is considered authenticated after
+ * authentication OK frame has been send or after it
+ * has been ACKed. In order to reduce interoperability
+ * issues, mark the STA authenticated before ACK. */
+ sta->flags |= WLAN_STA_AUTH;
+ break;
+
+ case WLAN_AUTH_SHARED_KEY:
+ if (auth_transaction == 1) {
+ if (sta->u.sta.challenge == NULL) {
+ sta->u.sta.challenge =
+ ap_auth_make_challenge(local->ap);
+ if (sta->u.sta.challenge == NULL) {
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ }
+ } else {
+ if (sta->u.sta.challenge == NULL ||
+ challenge == NULL ||
+ memcmp(sta->u.sta.challenge, challenge,
+ WLAN_AUTH_CHALLENGE_LEN) != 0 ||
+ !(fc & IEEE80211_FCTL_PROTECTED)) {
+ txt = "challenge response incorrect";
+ resp = WLAN_STATUS_CHALLENGE_FAIL;
+ goto fail;
+ }
+
+ txt = "challenge OK - authOK";
+ /* IEEE 802.11 standard is not completely clear about
+ * whether STA is considered authenticated after
+ * authentication OK frame has been send or after it
+ * has been ACKed. In order to reduce interoperability
+ * issues, mark the STA authenticated before ACK. */
+ sta->flags |= WLAN_STA_AUTH;
+ kfree(sta->u.sta.challenge);
+ sta->u.sta.challenge = NULL;
+ }
+ break;
+ }
+
+ fail:
+ pos = (u16 *) body;
+ *pos = cpu_to_le16(auth_alg);
+ pos++;
+ *pos = cpu_to_le16(auth_transaction + 1);
+ pos++;
+ *pos = cpu_to_le16(resp); /* status_code */
+ pos++;
+ olen = 6;
+
+ if (resp == WLAN_STATUS_SUCCESS && sta != NULL &&
+ sta->u.sta.challenge != NULL &&
+ auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 1) {
+ u8 *tmp = (u8 *) pos;
+ *tmp++ = WLAN_EID_CHALLENGE;
+ *tmp++ = WLAN_AUTH_CHALLENGE_LEN;
+ pos++;
+ memcpy(pos, sta->u.sta.challenge, WLAN_AUTH_CHALLENGE_LEN);
+ olen += 2 + WLAN_AUTH_CHALLENGE_LEN;
+ }
+
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH,
+ body, olen, hdr->addr2, ap->tx_callback_auth);
+
+ if (sta) {
+ sta->last_rx = jiffies;
+ atomic_dec(&sta->users);
+ }
+
+ if (resp) {
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " auth (alg=%d trans#=%d "
+ "stat=%d len=%d fc=%04x) ==> %d (%s)\n",
+ dev->name, MAC2STR(hdr->addr2), auth_alg,
+ auth_transaction, status_code, len, fc, resp, txt);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_assoc(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats, int reassoc)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ char body[12], *p, *lpos;
+ int len, left;
+ u16 *pos;
+ u16 resp = WLAN_STATUS_SUCCESS;
+ struct sta_info *sta = NULL;
+ int send_deauth = 0;
+ char *txt = "";
+ u8 prev_ap[ETH_ALEN];
+
+ left = len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < (reassoc ? 10 : 4)) {
+ PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload "
+ "(len=%d, reassoc=%d) from " MACSTR "\n",
+ dev->name, len, reassoc, MAC2STR(hdr->addr2));
+ return;
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ txt = "trying to associate before authentication";
+ send_deauth = 1;
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ sta = NULL; /* do not decrement sta->users */
+ goto fail;
+ }
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ sta->capability = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+ sta->listen_interval = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+
+ if (reassoc) {
+ memcpy(prev_ap, pos, ETH_ALEN);
+ pos++; pos++; pos++; left -= 6;
+ } else
+ memset(prev_ap, 0, ETH_ALEN);
+
+ if (left >= 2) {
+ unsigned int ileft;
+ unsigned char *u = (unsigned char *) pos;
+
+ if (*u == WLAN_EID_SSID) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft > MAX_SSID_LEN) {
+ txt = "SSID overflow";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ if (ileft != strlen(local->essid) ||
+ memcmp(local->essid, u, ileft) != 0) {
+ txt = "not our SSID";
+ resp = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
+ goto fail;
+ }
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (left >= 2 && *u == WLAN_EID_SUPP_RATES) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft == 0 ||
+ ileft > WLAN_SUPP_RATES_MAX) {
+ txt = "SUPP_RATES len error";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ memset(sta->supported_rates, 0,
+ sizeof(sta->supported_rates));
+ memcpy(sta->supported_rates, u, ileft);
+ prism2_check_tx_rates(sta);
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (left > 0) {
+ PDEBUG(DEBUG_AP, "%s: assoc from " MACSTR " with extra"
+ " data (%d bytes) [",
+ dev->name, MAC2STR(hdr->addr2), left);
+ while (left > 0) {
+ PDEBUG2(DEBUG_AP, "<%02x>", *u);
+ u++; left--;
+ }
+ PDEBUG2(DEBUG_AP, "]\n");
+ }
+ } else {
+ txt = "frame underflow";
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+
+ /* get a unique AID */
+ if (sta->aid > 0)
+ txt = "OK, old AID";
+ else {
+ spin_lock_bh(&local->ap->sta_table_lock);
+ for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
+ if (local->ap->sta_aid[sta->aid - 1] == NULL)
+ break;
+ if (sta->aid > MAX_AID_TABLE_SIZE) {
+ sta->aid = 0;
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ txt = "no room for more AIDs";
+ } else {
+ local->ap->sta_aid[sta->aid - 1] = sta;
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ txt = "OK, new AID";
+ }
+ }
+
+ fail:
+ pos = (u16 *) body;
+
+ if (send_deauth) {
+ *pos = __constant_cpu_to_le16(
+ WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
+ pos++;
+ } else {
+ /* FIX: CF-Pollable and CF-PollReq should be set to match the
+ * values in beacons/probe responses */
+ /* FIX: how about privacy and WEP? */
+ /* capability */
+ *pos = __constant_cpu_to_le16(WLAN_CAPABILITY_ESS);
+ pos++;
+
+ /* status_code */
+ *pos = __cpu_to_le16(resp);
+ pos++;
+
+ *pos = __cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) |
+ BIT(14) | BIT(15)); /* AID */
+ pos++;
+
+ /* Supported rates (Information element) */
+ p = (char *) pos;
+ *p++ = WLAN_EID_SUPP_RATES;
+ lpos = p;
+ *p++ = 0; /* len */
+ if (local->tx_rate_control & WLAN_RATE_1M) {
+ *p++ = local->basic_rates & WLAN_RATE_1M ? 0x82 : 0x02;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_2M) {
+ *p++ = local->basic_rates & WLAN_RATE_2M ? 0x84 : 0x04;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_5M5) {
+ *p++ = local->basic_rates & WLAN_RATE_5M5 ?
+ 0x8b : 0x0b;
+ (*lpos)++;
+ }
+ if (local->tx_rate_control & WLAN_RATE_11M) {
+ *p++ = local->basic_rates & WLAN_RATE_11M ?
+ 0x96 : 0x16;
+ (*lpos)++;
+ }
+ pos = (u16 *) p;
+ }
+
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ (send_deauth ? IEEE80211_STYPE_DEAUTH :
+ (reassoc ? IEEE80211_STYPE_REASSOC_RESP :
+ IEEE80211_STYPE_ASSOC_RESP)),
+ body, (u8 *) pos - (u8 *) body,
+ hdr->addr2,
+ send_deauth ? 0 : local->ap->tx_callback_assoc);
+
+ if (sta) {
+ if (resp == WLAN_STATUS_SUCCESS) {
+ sta->last_rx = jiffies;
+ /* STA will be marked associated from TX callback, if
+ * AssocResp is ACKed */
+ }
+ atomic_dec(&sta->users);
+ }
+
+#if 0
+ PDEBUG(DEBUG_AP, "%s: " MACSTR " %sassoc (len=%d prev_ap=" MACSTR
+ ") => %d(%d) (%s)\n",
+ dev->name, MAC2STR(hdr->addr2), reassoc ? "re" : "", len,
+ MAC2STR(prev_ap), resp, send_deauth, txt);
+#endif
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_deauth(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ int len;
+ u16 reason_code, *pos;
+ struct sta_info *sta = NULL;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 2) {
+ printk("handle_deauth - too short payload (len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ reason_code = __le16_to_cpu(*pos);
+
+ PDEBUG(DEBUG_AP, "%s: deauthentication: " MACSTR " len=%d, "
+ "reason_code=%d\n", dev->name, MAC2STR(hdr->addr2), len,
+ reason_code);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL) {
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ }
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ if (sta == NULL) {
+ printk("%s: deauthentication from " MACSTR ", "
+ "reason_code=%d, but STA not authenticated\n", dev->name,
+ MAC2STR(hdr->addr2), reason_code);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ int len;
+ u16 reason_code, *pos;
+ struct sta_info *sta = NULL;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 2) {
+ printk("handle_disassoc - too short payload (len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ reason_code = __le16_to_cpu(*pos);
+
+ PDEBUG(DEBUG_AP, "%s: disassociation: " MACSTR " len=%d, "
+ "reason_code=%d\n", dev->name, MAC2STR(hdr->addr2), len,
+ reason_code);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL) {
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ hostap_event_expired_sta(local->dev, sta);
+ sta->flags &= ~WLAN_STA_ASSOC;
+ }
+ spin_unlock_bh(&local->ap->sta_table_lock);
+ if (sta == NULL) {
+ printk("%s: disassociation from " MACSTR ", "
+ "reason_code=%d, but STA not authenticated\n",
+ dev->name, MAC2STR(hdr->addr2), reason_code);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void ap_handle_data_nullfunc(local_info_t *local,
+ struct ieee80211_hdr_4addr *hdr)
+{
+ struct net_device *dev = local->dev;
+
+ /* some STA f/w's seem to require control::ACK frame for
+ * data::nullfunc, but at least Prism2 station f/w version 0.8.0 does
+ * not send this..
+ * send control::ACK for the data::nullfunc */
+
+ printk(KERN_DEBUG "Sending control::ACK for data::nullfunc\n");
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK,
+ NULL, 0, hdr->addr2, 0);
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void ap_handle_dropped_data(local_info_t *local,
+ struct ieee80211_hdr_4addr *hdr)
+{
+ struct net_device *dev = local->dev;
+ struct sta_info *sta;
+ u16 reason;
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC)) {
+ PDEBUG(DEBUG_AP, "ap_handle_dropped_data: STA is now okay?\n");
+ atomic_dec(&sta->users);
+ return;
+ }
+
+ reason = __constant_cpu_to_le16(
+ WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
+ ((sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) ?
+ IEEE80211_STYPE_DEAUTH : IEEE80211_STYPE_DISASSOC),
+ (char *) &reason, sizeof(reason), hdr->addr2, 0);
+
+ if (sta)
+ atomic_dec(&sta->users);
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
+ struct sk_buff *skb)
+{
+ struct hostap_skb_tx_data *meta;
+
+ if (!(sta->flags & WLAN_STA_PS)) {
+ /* Station has moved to non-PS mode, so send all buffered
+ * frames using normal device queue. */
+ dev_queue_xmit(skb);
+ return;
+ }
+
+ /* add a flag for hostap_handle_sta_tx() to know that this skb should
+ * be passed through even though STA is using PS */
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ meta->flags |= HOSTAP_TX_FLAGS_BUFFERED_FRAME;
+ if (!skb_queue_empty(&sta->tx_buf)) {
+ /* indicate to STA that more frames follow */
+ meta->flags |= HOSTAP_TX_FLAGS_ADD_MOREDATA;
+ }
+ dev_queue_xmit(skb);
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_pspoll(local_info_t *local,
+ struct ieee80211_hdr_4addr *hdr,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct net_device *dev = local->dev;
+ struct sta_info *sta;
+ u16 aid;
+ struct sk_buff *skb;
+
+ PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MACSTR ", TA=" MACSTR
+ " PWRMGT=%d\n",
+ MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
+ !!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM));
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr1));
+ return;
+ }
+
+ aid = __le16_to_cpu(hdr->duration_id);
+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) {
+ PDEBUG(DEBUG_PS, " PSPOLL and AID[15:14] not set\n");
+ return;
+ }
+ aid &= ~BIT(15) & ~BIT(14);
+ if (aid == 0 || aid > MAX_AID_TABLE_SIZE) {
+ PDEBUG(DEBUG_PS, " invalid aid=%d\n", aid);
+ return;
+ }
+ PDEBUG(DEBUG_PS2, " aid=%d\n", aid);
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta == NULL) {
+ PDEBUG(DEBUG_PS, " STA not found\n");
+ return;
+ }
+ if (sta->aid != aid) {
+ PDEBUG(DEBUG_PS, " received aid=%i does not match with "
+ "assoc.aid=%d\n", aid, sta->aid);
+ return;
+ }
+
+ /* FIX: todo:
+ * - add timeout for buffering (clear aid in TIM vector if buffer timed
+ * out (expiry time must be longer than ListenInterval for
+ * the corresponding STA; "8802-11: 11.2.1.9 AP aging function"
+ * - what to do, if buffered, pspolled, and sent frame is not ACKed by
+ * sta; store buffer for later use and leave TIM aid bit set? use
+ * TX event to check whether frame was ACKed?
+ */
+
+ while ((skb = skb_dequeue(&sta->tx_buf)) != NULL) {
+ /* send buffered frame .. */
+ PDEBUG(DEBUG_PS2, "Sending buffered frame to STA after PS POLL"
+ " (buffer_count=%d)\n", skb_queue_len(&sta->tx_buf));
+
+ pspoll_send_buffered(local, sta, skb);
+
+ if (sta->flags & WLAN_STA_PS) {
+ /* send only one buffered packet per PS Poll */
+ /* FIX: should ignore further PS Polls until the
+ * buffered packet that was just sent is acknowledged
+ * (Tx or TxExc event) */
+ break;
+ }
+ }
+
+ if (skb_queue_empty(&sta->tx_buf)) {
+ /* try to clear aid from TIM */
+ if (!(sta->flags & WLAN_STA_TIM))
+ PDEBUG(DEBUG_PS2, "Re-unsetting TIM for aid %d\n",
+ aid);
+ hostap_set_tim(local, aid, 0);
+ sta->flags &= ~WLAN_STA_TIM;
+ }
+
+ atomic_dec(&sta->users);
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+
+static void handle_wds_oper_queue(void *data)
+{
+ local_info_t *local = data;
+ struct wds_oper_data *entry, *prev;
+
+ spin_lock_bh(&local->lock);
+ entry = local->ap->wds_oper_entries;
+ local->ap->wds_oper_entries = NULL;
+ spin_unlock_bh(&local->lock);
+
+ while (entry) {
+ PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection "
+ "to AP " MACSTR "\n",
+ local->dev->name,
+ entry->type == WDS_ADD ? "adding" : "removing",
+ MAC2STR(entry->addr));
+ if (entry->type == WDS_ADD)
+ prism2_wds_add(local, entry->addr, 0);
+ else if (entry->type == WDS_DEL)
+ prism2_wds_del(local, entry->addr, 0, 1);
+
+ prev = entry;
+ entry = entry->next;
+ kfree(prev);
+ }
+}
+
+
+/* Called only as a scheduled task for pending AP frames. */
+static void handle_beacon(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
+ int len, left;
+ u16 *pos, beacon_int, capability;
+ char *ssid = NULL;
+ unsigned char *supp_rates = NULL;
+ int ssid_len = 0, supp_rates_len = 0;
+ struct sta_info *sta = NULL;
+ int new_sta = 0, channel = -1;
+
+ len = skb->len - IEEE80211_MGMT_HDR_LEN;
+
+ if (len < 8 + 2 + 2) {
+ printk(KERN_DEBUG "handle_beacon - too short payload "
+ "(len=%d)\n", len);
+ return;
+ }
+
+ pos = (u16 *) body;
+ left = len;
+
+ /* Timestamp (8 octets) */
+ pos += 4; left -= 8;
+ /* Beacon interval (2 octets) */
+ beacon_int = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+ /* Capability information (2 octets) */
+ capability = __le16_to_cpu(*pos);
+ pos++; left -= 2;
+
+ if (local->ap->ap_policy != AP_OTHER_AP_EVEN_IBSS &&
+ capability & WLAN_CAPABILITY_IBSS)
+ return;
+
+ if (left >= 2) {
+ unsigned int ileft;
+ unsigned char *u = (unsigned char *) pos;
+
+ if (*u == WLAN_EID_SSID) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft > MAX_SSID_LEN) {
+ PDEBUG(DEBUG_AP, "SSID: overflow\n");
+ return;
+ }
+
+ if (local->ap->ap_policy == AP_OTHER_AP_SAME_SSID &&
+ (ileft != strlen(local->essid) ||
+ memcmp(local->essid, u, ileft) != 0)) {
+ /* not our SSID */
+ return;
+ }
+
+ ssid = u;
+ ssid_len = ileft;
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (*u == WLAN_EID_SUPP_RATES) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft == 0 || ileft > 8) {
+ PDEBUG(DEBUG_AP, " - SUPP_RATES len error\n");
+ return;
+ }
+
+ supp_rates = u;
+ supp_rates_len = ileft;
+
+ u += ileft;
+ left -= ileft;
+ }
+
+ if (*u == WLAN_EID_DS_PARAMS) {
+ u++; left--;
+ ileft = *u;
+ u++; left--;
+
+ if (ileft > left || ileft != 1) {
+ PDEBUG(DEBUG_AP, " - DS_PARAMS len error\n");
+ return;
+ }
+
+ channel = *u;
+
+ u += ileft;
+ left -= ileft;
+ }
+ }
+
+ spin_lock_bh(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta != NULL)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&local->ap->sta_table_lock);
+
+ if (sta == NULL) {
+ /* add new AP */
+ new_sta = 1;
+ sta = ap_add_sta(local->ap, hdr->addr2);
+ if (sta == NULL) {
+ printk(KERN_INFO "prism2: kmalloc failed for AP "
+ "data structure\n");
+ return;
+ }
+ hostap_event_new_sta(local->dev, sta);
+
+ /* mark APs authentication and associated for pseudo ad-hoc
+ * style communication */
+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+
+ if (local->ap->autom_ap_wds) {
+ hostap_wds_link_oper(local, sta->addr, WDS_ADD);
+ }
+ }
+
+ sta->ap = 1;
+ if (ssid) {
+ sta->u.ap.ssid_len = ssid_len;
+ memcpy(sta->u.ap.ssid, ssid, ssid_len);
+ sta->u.ap.ssid[ssid_len] = '\0';
+ } else {
+ sta->u.ap.ssid_len = 0;
+ sta->u.ap.ssid[0] = '\0';
+ }
+ sta->u.ap.channel = channel;
+ sta->rx_packets++;
+ sta->rx_bytes += len;
+ sta->u.ap.last_beacon = sta->last_rx = jiffies;
+ sta->capability = capability;
+ sta->listen_interval = beacon_int;
+
+ atomic_dec(&sta->users);
+
+ if (new_sta) {
+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
+ memcpy(sta->supported_rates, supp_rates, supp_rates_len);
+ prism2_check_tx_rates(sta);
+ }
+}
+
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+/* Called only as a tasklet. */
+static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ struct net_device *dev = local->dev;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ u16 fc, type, stype;
+ struct ieee80211_hdr_4addr *hdr;
+
+ /* FIX: should give skb->len to handler functions and check that the
+ * buffer is long enough */
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (!local->hostapd && type == IEEE80211_FTYPE_DATA) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - data frame\n");
+
+ if (!(fc & IEEE80211_FCTL_TODS) ||
+ (fc & IEEE80211_FCTL_FROMDS)) {
+ if (stype == IEEE80211_STYPE_NULLFUNC) {
+ /* no ToDS nullfunc seems to be used to check
+ * AP association; so send reject message to
+ * speed up re-association */
+ ap_handle_dropped_data(local, hdr);
+ goto done;
+ }
+ PDEBUG(DEBUG_AP, " not ToDS frame (fc=0x%04x)\n",
+ fc);
+ goto done;
+ }
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)="
+ MACSTR " not own MAC\n",
+ MAC2STR(hdr->addr1));
+ goto done;
+ }
+
+ if (local->ap->nullfunc_ack &&
+ stype == IEEE80211_STYPE_NULLFUNC)
+ ap_handle_data_nullfunc(local, hdr);
+ else
+ ap_handle_dropped_data(local, hdr);
+ goto done;
+ }
+
+ if (type == IEEE80211_FTYPE_MGMT && stype == IEEE80211_STYPE_BEACON) {
+ handle_beacon(local, skb, rx_stats);
+ goto done;
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ if (type == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL) {
+ handle_pspoll(local, hdr, rx_stats);
+ goto done;
+ }
+
+ if (local->hostapd) {
+ PDEBUG(DEBUG_AP, "Unknown frame in AP queue: type=0x%02x "
+ "subtype=0x%02x\n", type, stype);
+ goto done;
+ }
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (type != IEEE80211_FTYPE_MGMT) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - not a management frame?\n");
+ goto done;
+ }
+
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr1));
+ goto done;
+ }
+
+ if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) {
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MACSTR
+ " not own MAC\n", MAC2STR(hdr->addr3));
+ goto done;
+ }
+
+ switch (stype) {
+ case IEEE80211_STYPE_ASSOC_REQ:
+ handle_assoc(local, skb, rx_stats, 0);
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ PDEBUG(DEBUG_AP, "==> ASSOC RESP (ignored)\n");
+ break;
+ case IEEE80211_STYPE_REASSOC_REQ:
+ handle_assoc(local, skb, rx_stats, 1);
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ PDEBUG(DEBUG_AP, "==> REASSOC RESP (ignored)\n");
+ break;
+ case IEEE80211_STYPE_ATIM:
+ PDEBUG(DEBUG_AP, "==> ATIM (ignored)\n");
+ break;
+ case IEEE80211_STYPE_DISASSOC:
+ handle_disassoc(local, skb, rx_stats);
+ break;
+ case IEEE80211_STYPE_AUTH:
+ handle_authen(local, skb, rx_stats);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ handle_deauth(local, skb, rx_stats);
+ break;
+ default:
+ PDEBUG(DEBUG_AP, "Unknown mgmt frame subtype 0x%02x\n",
+ stype >> 4);
+ break;
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ done:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 fc;
+ struct ieee80211_hdr_4addr *hdr;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (skb->len < 16)
+ goto drop;
+
+ local->stats.rx_packets++;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT &&
+ WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_BEACON)
+ goto drop;
+
+ skb->protocol = __constant_htons(ETH_P_HOSTAP);
+ handle_ap_item(local, skb, rx_stats);
+ return;
+
+ drop:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
+{
+ struct sk_buff *skb;
+ struct ieee80211_hdr_4addr *hdr;
+ struct hostap_80211_rx_status rx_stats;
+
+ if (skb_queue_empty(&sta->tx_buf))
+ return;
+
+ skb = dev_alloc_skb(16);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: schedule_packet_send: skb alloc "
+ "failed\n", local->dev->name);
+ return;
+ }
+
+ hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
+
+ /* Generate a fake pspoll frame to start packet delivery */
+ hdr->frame_ctl = __constant_cpu_to_le16(
+ IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
+ memcpy(hdr->addr1, local->dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->addr2, sta->addr, ETH_ALEN);
+ hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14));
+
+ PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for "
+ "STA " MACSTR "\n", local->dev->name, MAC2STR(sta->addr));
+
+ skb->dev = local->dev;
+
+ memset(&rx_stats, 0, sizeof(rx_stats));
+ hostap_rx(local->dev, skb, &rx_stats);
+}
+
+
+static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist)
+{
+ struct ap_data *ap = local->ap;
+ struct list_head *ptr;
+ int count = 0;
+
+ spin_lock_bh(&ap->sta_table_lock);
+
+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list;
+ ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ if (aplist && !sta->ap)
+ continue;
+ addr[count].sa_family = ARPHRD_ETHER;
+ memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
+ if (sta->last_rx_silence == 0)
+ qual[count].qual = sta->last_rx_signal < 27 ?
+ 0 : (sta->last_rx_signal - 27) * 92 / 127;
+ else
+ qual[count].qual = sta->last_rx_signal -
+ sta->last_rx_silence - 35;
+ qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+ qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+ qual[count].updated = sta->last_rx_updated;
+
+ sta->last_rx_updated = IW_QUAL_DBM;
+
+ count++;
+ if (count >= buf_size)
+ break;
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ return count;
+}
+
+
+/* Translate our list of Access Points & Stations to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct ap_data *ap;
+ struct list_head *ptr;
+ struct iw_event iwe;
+ char *current_ev = buffer;
+ char *end_buf = buffer + IW_SCAN_MAX_DATA;
+#if !defined(PRISM2_NO_KERNEL_IEEE80211_MGMT)
+ char buf[64];
+#endif
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ ap = local->ap;
+
+ spin_lock_bh(&ap->sta_table_lock);
+
+ for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list;
+ ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+
+ /* First entry *MUST* be the AP MAC address */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN);
+ iwe.len = IW_EV_ADDR_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_ADDR_LEN);
+
+ /* Use the mode to indicate if it's a station or
+ * an Access Point */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWMODE;
+ if (sta->ap)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_INFRA;
+ iwe.len = IW_EV_UINT_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_UINT_LEN);
+
+ /* Some quality */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVQUAL;
+ if (sta->last_rx_silence == 0)
+ iwe.u.qual.qual = sta->last_rx_signal < 27 ?
+ 0 : (sta->last_rx_signal - 27) * 92 / 127;
+ else
+ iwe.u.qual.qual = sta->last_rx_signal -
+ sta->last_rx_silence - 35;
+ iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+ iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+ iwe.u.qual.updated = sta->last_rx_updated;
+ iwe.len = IW_EV_QUAL_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_QUAL_LEN);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ if (sta->ap) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = sta->u.ap.ssid_len;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe,
+ sta->u.ap.ssid);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWENCODE;
+ if (sta->capability & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags =
+ IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe,
+ sta->u.ap.ssid
+ /* 0 byte memcpy */);
+
+ if (sta->u.ap.channel > 0 &&
+ sta->u.ap.channel <= FREQ_COUNT) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = freq_list[sta->u.ap.channel - 1]
+ * 100000;
+ iwe.u.freq.e = 1;
+ current_ev = iwe_stream_add_event(
+ current_ev, end_buf, &iwe,
+ IW_EV_FREQ_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "beacon_interval=%d",
+ sta->listen_interval);
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe, buf);
+ }
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+ sta->last_rx_updated = IW_QUAL_DBM;
+
+ /* To be continued, we should make good use of IWEVCUSTOM */
+ }
+
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ return current_ev - buffer;
+}
+
+
+static int prism2_hostapd_add_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (sta == NULL) {
+ sta = ap_add_sta(ap, param->sta_addr);
+ if (sta == NULL)
+ return -1;
+ }
+
+ if (!(sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_new_sta(sta->local->dev, sta);
+
+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ sta->last_rx = jiffies;
+ sta->aid = param->u.add_sta.aid;
+ sta->capability = param->u.add_sta.capability;
+ sta->tx_supp_rates = param->u.add_sta.tx_supp_rates;
+ if (sta->tx_supp_rates & WLAN_RATE_1M)
+ sta->supported_rates[0] = 2;
+ if (sta->tx_supp_rates & WLAN_RATE_2M)
+ sta->supported_rates[1] = 4;
+ if (sta->tx_supp_rates & WLAN_RATE_5M5)
+ sta->supported_rates[2] = 11;
+ if (sta->tx_supp_rates & WLAN_RATE_11M)
+ sta->supported_rates[3] = 22;
+ prism2_check_tx_rates(sta);
+ atomic_dec(&sta->users);
+ return 0;
+}
+
+
+static int prism2_hostapd_remove_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ ap_sta_hash_del(ap, sta);
+ list_del(&sta->list);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
+ hostap_event_expired_sta(sta->local->dev, sta);
+ ap_free_sta(ap, sta);
+
+ return 0;
+}
+
+
+static int prism2_hostapd_get_info_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ param->u.get_info_sta.inactive_sec = (jiffies - sta->last_rx) / HZ;
+
+ atomic_dec(&sta->users);
+
+ return 1;
+}
+
+
+static int prism2_hostapd_set_flags_sta(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ sta->flags |= param->u.set_flags_sta.flags_or;
+ sta->flags &= param->u.set_flags_sta.flags_and;
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ return 0;
+}
+
+
+static int prism2_hostapd_sta_clear_stats(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ struct sta_info *sta;
+ int rate;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, param->sta_addr);
+ if (sta) {
+ sta->rx_packets = sta->tx_packets = 0;
+ sta->rx_bytes = sta->tx_bytes = 0;
+ for (rate = 0; rate < WLAN_RATE_COUNT; rate++) {
+ sta->tx_count[rate] = 0;
+ sta->rx_count[rate] = 0;
+ }
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta)
+ return -ENOENT;
+
+ return 0;
+}
+
+
+static int prism2_hostapd(struct ap_data *ap,
+ struct prism2_hostapd_param *param)
+{
+ switch (param->cmd) {
+ case PRISM2_HOSTAPD_FLUSH:
+ ap_control_kickall(ap);
+ return 0;
+ case PRISM2_HOSTAPD_ADD_STA:
+ return prism2_hostapd_add_sta(ap, param);
+ case PRISM2_HOSTAPD_REMOVE_STA:
+ return prism2_hostapd_remove_sta(ap, param);
+ case PRISM2_HOSTAPD_GET_INFO_STA:
+ return prism2_hostapd_get_info_sta(ap, param);
+ case PRISM2_HOSTAPD_SET_FLAGS_STA:
+ return prism2_hostapd_set_flags_sta(ap, param);
+ case PRISM2_HOSTAPD_STA_CLEAR_STATS:
+ return prism2_hostapd_sta_clear_stats(ap, param);
+ default:
+ printk(KERN_WARNING "prism2_hostapd: unknown cmd=%d\n",
+ param->cmd);
+ return -EOPNOTSUPP;
+ }
+}
+
+
+/* Update station info for host-based TX rate control and return current
+ * TX rate */
+static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev)
+{
+ int ret = sta->tx_rate;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ sta->tx_count[sta->tx_rate_idx]++;
+ sta->tx_since_last_failure++;
+ sta->tx_consecutive_exc = 0;
+ if (sta->tx_since_last_failure >= WLAN_RATE_UPDATE_COUNT &&
+ sta->tx_rate_idx < sta->tx_max_rate) {
+ /* use next higher rate */
+ int old_rate, new_rate;
+ old_rate = new_rate = sta->tx_rate_idx;
+ while (new_rate < sta->tx_max_rate) {
+ new_rate++;
+ if (ap_tx_rate_ok(new_rate, sta, local)) {
+ sta->tx_rate_idx = new_rate;
+ break;
+ }
+ }
+ if (old_rate != sta->tx_rate_idx) {
+ switch (sta->tx_rate_idx) {
+ case 0: sta->tx_rate = 10; break;
+ case 1: sta->tx_rate = 20; break;
+ case 2: sta->tx_rate = 55; break;
+ case 3: sta->tx_rate = 110; break;
+ default: sta->tx_rate = 0; break;
+ }
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate raised to"
+ " %d\n", dev->name, MAC2STR(sta->addr),
+ sta->tx_rate);
+ }
+ sta->tx_since_last_failure = 0;
+ }
+
+ return ret;
+}
+
+
+/* Called only from software IRQ. Called for each TX frame prior possible
+ * encryption and transmit. */
+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
+{
+ struct sta_info *sta = NULL;
+ struct sk_buff *skb = tx->skb;
+ int set_tim, ret;
+ struct ieee80211_hdr_4addr *hdr;
+ struct hostap_skb_tx_data *meta;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+ ret = AP_TX_CONTINUE;
+ if (local->ap == NULL || skb->len < 10 ||
+ meta->iface->type == HOSTAP_INTERFACE_STA)
+ goto out;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+
+ if (hdr->addr1[0] & 0x01) {
+ /* broadcast/multicast frame - no AP related processing */
+ goto out;
+ }
+
+ /* unicast packet - check whether destination STA is associated */
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr1);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (local->iw_mode == IW_MODE_MASTER && sta == NULL &&
+ !(meta->flags & HOSTAP_TX_FLAGS_WDS) &&
+ meta->iface->type != HOSTAP_INTERFACE_MASTER &&
+ meta->iface->type != HOSTAP_INTERFACE_AP) {
+#if 0
+ /* This can happen, e.g., when wlan0 is added to a bridge and
+ * bridging code does not know which port is the correct target
+ * for a unicast frame. In this case, the packet is send to all
+ * ports of the bridge. Since this is a valid scenario, do not
+ * print out any errors here. */
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "AP: drop packet to non-associated "
+ "STA " MACSTR "\n", MAC2STR(hdr->addr1));
+ }
+#endif
+ local->ap->tx_drop_nonassoc++;
+ ret = AP_TX_DROP;
+ goto out;
+ }
+
+ if (sta == NULL)
+ goto out;
+
+ if (!(sta->flags & WLAN_STA_AUTHORIZED))
+ ret = AP_TX_CONTINUE_NOT_AUTHORIZED;
+
+ /* Set tx_rate if using host-based TX rate control */
+ if (!local->fw_tx_rate_control)
+ local->ap->last_tx_rate = meta->rate =
+ ap_update_sta_tx_rate(sta, local->dev);
+
+ if (local->iw_mode != IW_MODE_MASTER)
+ goto out;
+
+ if (!(sta->flags & WLAN_STA_PS))
+ goto out;
+
+ if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) {
+ /* indicate to STA that more frames follow */
+ hdr->frame_ctl |=
+ __constant_cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ }
+
+ if (meta->flags & HOSTAP_TX_FLAGS_BUFFERED_FRAME) {
+ /* packet was already buffered and now send due to
+ * PS poll, so do not rebuffer it */
+ goto out;
+ }
+
+ if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) {
+ PDEBUG(DEBUG_PS, "%s: No more space in STA (" MACSTR ")'s PS "
+ "mode buffer\n", local->dev->name, MAC2STR(sta->addr));
+ /* Make sure that TIM is set for the station (it might not be
+ * after AP wlan hw reset). */
+ /* FIX: should fix hw reset to restore bits based on STA
+ * buffer state.. */
+ hostap_set_tim(local, sta->aid, 1);
+ sta->flags |= WLAN_STA_TIM;
+ ret = AP_TX_DROP;
+ goto out;
+ }
+
+ /* STA in PS mode, buffer frame for later delivery */
+ set_tim = skb_queue_empty(&sta->tx_buf);
+ skb_queue_tail(&sta->tx_buf, skb);
+ /* FIX: could save RX time to skb and expire buffered frames after
+ * some time if STA does not poll for them */
+
+ if (set_tim) {
+ if (sta->flags & WLAN_STA_TIM)
+ PDEBUG(DEBUG_PS2, "Re-setting TIM for aid %d\n",
+ sta->aid);
+ hostap_set_tim(local, sta->aid, 1);
+ sta->flags |= WLAN_STA_TIM;
+ }
+
+ ret = AP_TX_BUFFERED;
+
+ out:
+ if (sta != NULL) {
+ if (ret == AP_TX_CONTINUE ||
+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) {
+ sta->tx_packets++;
+ sta->tx_bytes += skb->len;
+ sta->last_tx = jiffies;
+ }
+
+ if ((ret == AP_TX_CONTINUE ||
+ ret == AP_TX_CONTINUE_NOT_AUTHORIZED) &&
+ sta->crypt && tx->host_encrypt) {
+ tx->crypt = sta->crypt;
+ tx->sta_ptr = sta; /* hostap_handle_sta_release() will
+ * be called to release sta info
+ * later */
+ } else
+ atomic_dec(&sta->users);
+ }
+
+ return ret;
+}
+
+
+void hostap_handle_sta_release(void *ptr)
+{
+ struct sta_info *sta = ptr;
+ atomic_dec(&sta->users);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
+{
+ struct sta_info *sta;
+ struct ieee80211_hdr_4addr *hdr;
+ struct hostap_skb_tx_data *meta;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr1);
+ if (!sta) {
+ spin_unlock(&local->ap->sta_table_lock);
+ PDEBUG(DEBUG_AP, "%s: Could not find STA " MACSTR " for this "
+ "TX error (@%lu)\n",
+ local->dev->name, MAC2STR(hdr->addr1), jiffies);
+ return;
+ }
+
+ sta->tx_since_last_failure = 0;
+ sta->tx_consecutive_exc++;
+
+ if (sta->tx_consecutive_exc >= WLAN_RATE_DECREASE_THRESHOLD &&
+ sta->tx_rate_idx > 0 && meta->rate <= sta->tx_rate) {
+ /* use next lower rate */
+ int old, rate;
+ old = rate = sta->tx_rate_idx;
+ while (rate > 0) {
+ rate--;
+ if (ap_tx_rate_ok(rate, sta, local)) {
+ sta->tx_rate_idx = rate;
+ break;
+ }
+ }
+ if (old != sta->tx_rate_idx) {
+ switch (sta->tx_rate_idx) {
+ case 0: sta->tx_rate = 10; break;
+ case 1: sta->tx_rate = 20; break;
+ case 2: sta->tx_rate = 55; break;
+ case 3: sta->tx_rate = 110; break;
+ default: sta->tx_rate = 0; break;
+ }
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " TX rate lowered "
+ "to %d\n", local->dev->name, MAC2STR(sta->addr),
+ sta->tx_rate);
+ }
+ sta->tx_consecutive_exc = 0;
+ }
+ spin_unlock(&local->ap->sta_table_lock);
+}
+
+
+static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
+ int pwrmgt, int type, int stype)
+{
+ if (pwrmgt && !(sta->flags & WLAN_STA_PS)) {
+ sta->flags |= WLAN_STA_PS;
+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to use PS "
+ "mode (type=0x%02X, stype=0x%02X)\n",
+ MAC2STR(sta->addr), type >> 2, stype >> 4);
+ } else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) {
+ sta->flags &= ~WLAN_STA_PS;
+ PDEBUG(DEBUG_PS2, "STA " MACSTR " changed to not use "
+ "PS mode (type=0x%02X, stype=0x%02X)\n",
+ MAC2STR(sta->addr), type >> 2, stype >> 4);
+ if (type != IEEE80211_FTYPE_CTL ||
+ stype != IEEE80211_STYPE_PSPOLL)
+ schedule_packet_send(local, sta);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ). Called for each RX frame to update
+ * STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
+{
+ struct sta_info *sta;
+ u16 fc;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (!sta)
+ return -1;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM,
+ WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc));
+
+ atomic_dec(&sta->users);
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ). Called for each RX frame after
+ * getting RX header and payload from hardware. */
+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
+ struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats,
+ int wds)
+{
+ int ret;
+ struct sta_info *sta;
+ u16 fc, type, stype;
+ struct ieee80211_hdr_4addr *hdr;
+
+ if (local->ap == NULL)
+ return AP_RX_CONTINUE;
+
+ hdr = (struct ieee80211_hdr_4addr *) skb->data;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (sta && !(sta->flags & WLAN_STA_AUTHORIZED))
+ ret = AP_RX_CONTINUE_NOT_AUTHORIZED;
+ else
+ ret = AP_RX_CONTINUE;
+
+
+ if (fc & IEEE80211_FCTL_TODS) {
+ if (!wds && (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NON_ASSOC);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ printk(KERN_DEBUG "%s: dropped received packet"
+ " from non-associated STA " MACSTR
+ " (type=0x%02x, subtype=0x%02x)\n",
+ dev->name, MAC2STR(hdr->addr2),
+ type >> 2, stype >> 4);
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ }
+ } else if (fc & IEEE80211_FCTL_FROMDS) {
+ if (!wds) {
+ /* FromDS frame - not for us; probably
+ * broadcast/multicast in another BSS - drop */
+ if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ printk(KERN_DEBUG "Odd.. FromDS packet "
+ "received with own BSSID\n");
+ hostap_dump_rx_80211(dev->name, skb, rx_stats);
+ }
+ ret = AP_RX_DROP;
+ goto out;
+ }
+ } else if (stype == IEEE80211_STYPE_NULLFUNC && sta == NULL &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NON_ASSOC);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ /* At least Lucent f/w seems to send data::nullfunc
+ * frames with no ToDS flag when the current AP returns
+ * after being unavailable for some time. Speed up
+ * re-association by informing the station about it not
+ * being associated. */
+ printk(KERN_DEBUG "%s: rejected received nullfunc "
+ "frame without ToDS from not associated STA "
+ MACSTR "\n",
+ dev->name, MAC2STR(hdr->addr2));
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ } else if (stype == IEEE80211_STYPE_NULLFUNC) {
+ /* At least Lucent cards seem to send periodic nullfunc
+ * frames with ToDS. Let these through to update SQ
+ * stats and PS state. Nullfunc frames do not contain
+ * any data and they will be dropped below. */
+ } else {
+ /* If BSSID (Addr3) is foreign, this frame is a normal
+ * broadcast frame from an IBSS network. Drop it silently.
+ * If BSSID is own, report the dropping of this frame. */
+ if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ printk(KERN_DEBUG "%s: dropped received packet from "
+ MACSTR " with no ToDS flag (type=0x%02x, "
+ "subtype=0x%02x)\n", dev->name,
+ MAC2STR(hdr->addr2), type >> 2, stype >> 4);
+ hostap_dump_rx_80211(dev->name, skb, rx_stats);
+ }
+ ret = AP_RX_DROP;
+ goto out;
+ }
+
+ if (sta) {
+ hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM,
+ type, stype);
+
+ sta->rx_packets++;
+ sta->rx_bytes += skb->len;
+ sta->last_rx = jiffies;
+ }
+
+ if (local->ap->nullfunc_ack && stype == IEEE80211_STYPE_NULLFUNC &&
+ fc & IEEE80211_FCTL_TODS) {
+ if (local->hostapd) {
+ prism2_rx_80211(local->apdev, skb, rx_stats,
+ PRISM2_RX_NULLFUNC_ACK);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ } else {
+ /* some STA f/w's seem to require control::ACK frame
+ * for data::nullfunc, but Prism2 f/w 0.8.0 (at least
+ * from Compaq) does not send this.. Try to generate
+ * ACK for these frames from the host driver to make
+ * power saving work with, e.g., Lucent WaveLAN f/w */
+ hostap_rx(dev, skb, rx_stats);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+ }
+ ret = AP_RX_EXIT;
+ goto out;
+ }
+
+ out:
+ if (sta)
+ atomic_dec(&sta->users);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_handle_sta_crypto(local_info_t *local,
+ struct ieee80211_hdr_4addr *hdr,
+ struct ieee80211_crypt_data **crypt,
+ void **sta_ptr)
+{
+ struct sta_info *sta;
+
+ spin_lock(&local->ap->sta_table_lock);
+ sta = ap_get_sta(local->ap, hdr->addr2);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock(&local->ap->sta_table_lock);
+
+ if (!sta)
+ return -1;
+
+ if (sta->crypt) {
+ *crypt = sta->crypt;
+ *sta_ptr = sta;
+ /* hostap_handle_sta_release() will be called to release STA
+ * info */
+ } else
+ atomic_dec(&sta->users);
+
+ return 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 0;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap)
+ ret = 1;
+ spin_unlock(&ap->sta_table_lock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 0;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap &&
+ ((sta->flags & WLAN_STA_AUTHORIZED) ||
+ ap->local->ieee_802_1x == 0))
+ ret = 1;
+ spin_unlock(&ap->sta_table_lock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
+{
+ struct sta_info *sta;
+ int ret = 1;
+
+ if (!ap)
+ return -1;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, sta_addr);
+ if (sta)
+ ret = 0;
+ spin_unlock(&ap->sta_table_lock);
+
+ if (ret == 1) {
+ sta = ap_add_sta(ap, sta_addr);
+ if (!sta)
+ ret = -1;
+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ sta->ap = 1;
+ memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
+ /* No way of knowing which rates are supported since we did not
+ * get supported rates element from beacon/assoc req. Assume
+ * that remote end supports all 802.11b rates. */
+ sta->supported_rates[0] = 0x82;
+ sta->supported_rates[1] = 0x84;
+ sta->supported_rates[2] = 0x0b;
+ sta->supported_rates[3] = 0x16;
+ sta->tx_supp_rates = WLAN_RATE_1M | WLAN_RATE_2M |
+ WLAN_RATE_5M5 | WLAN_RATE_11M;
+ sta->tx_rate = 110;
+ sta->tx_max_rate = sta->tx_rate_idx = 3;
+ }
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+int hostap_update_rx_stats(struct ap_data *ap,
+ struct ieee80211_hdr_4addr *hdr,
+ struct hostap_80211_rx_status *rx_stats)
+{
+ struct sta_info *sta;
+
+ if (!ap)
+ return -1;
+
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr2);
+ if (sta) {
+ sta->last_rx_silence = rx_stats->noise;
+ sta->last_rx_signal = rx_stats->signal;
+ sta->last_rx_rate = rx_stats->rate;
+ sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ if (rx_stats->rate == 10)
+ sta->rx_count[0]++;
+ else if (rx_stats->rate == 20)
+ sta->rx_count[1]++;
+ else if (rx_stats->rate == 55)
+ sta->rx_count[2]++;
+ else if (rx_stats->rate == 110)
+ sta->rx_count[3]++;
+ }
+ spin_unlock(&ap->sta_table_lock);
+
+ return sta ? 0 : -1;
+}
+
+
+void hostap_update_rates(local_info_t *local)
+{
+ struct list_head *ptr;
+ struct ap_data *ap = local->ap;
+
+ if (!ap)
+ return;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
+ struct sta_info *sta = (struct sta_info *) ptr;
+ prism2_check_tx_rates(sta);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+}
+
+
+static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt)
+{
+ struct sta_info *sta;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, addr);
+ if (sta)
+ atomic_inc(&sta->users);
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ if (!sta && permanent)
+ sta = ap_add_sta(ap, addr);
+
+ if (!sta)
+ return NULL;
+
+ if (permanent)
+ sta->flags |= WLAN_STA_PERM;
+
+ *crypt = &sta->crypt;
+
+ return sta;
+}
+
+
+void hostap_add_wds_links(local_info_t *local)
+{
+ struct ap_data *ap = local->ap;
+ struct list_head *ptr;
+
+ spin_lock_bh(&ap->sta_table_lock);
+ list_for_each(ptr, &ap->sta_list) {
+ struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ if (sta->ap)
+ hostap_wds_link_oper(local, sta->addr, WDS_ADD);
+ }
+ spin_unlock_bh(&ap->sta_table_lock);
+
+ schedule_work(&local->ap->wds_oper_queue);
+}
+
+
+void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type)
+{
+ struct wds_oper_data *entry;
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return;
+ memcpy(entry->addr, addr, ETH_ALEN);
+ entry->type = type;
+ spin_lock_bh(&local->lock);
+ entry->next = local->ap->wds_oper_entries;
+ local->ap->wds_oper_entries = entry;
+ spin_unlock_bh(&local->lock);
+
+ schedule_work(&local->ap->wds_oper_queue);
+}
+
+
+EXPORT_SYMBOL(hostap_init_data);
+EXPORT_SYMBOL(hostap_init_ap_proc);
+EXPORT_SYMBOL(hostap_free_data);
+EXPORT_SYMBOL(hostap_check_sta_fw_version);
+EXPORT_SYMBOL(hostap_handle_sta_tx);
+EXPORT_SYMBOL(hostap_handle_sta_release);
+EXPORT_SYMBOL(hostap_handle_sta_tx_exc);
+EXPORT_SYMBOL(hostap_update_sta_ps);
+EXPORT_SYMBOL(hostap_handle_sta_rx);
+EXPORT_SYMBOL(hostap_is_sta_assoc);
+EXPORT_SYMBOL(hostap_is_sta_authorized);
+EXPORT_SYMBOL(hostap_add_sta);
+EXPORT_SYMBOL(hostap_update_rates);
+EXPORT_SYMBOL(hostap_add_wds_links);
+EXPORT_SYMBOL(hostap_wds_link_oper);
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+EXPORT_SYMBOL(hostap_deauth_all_stas);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
new file mode 100644
index 000000000000..6d00df69c2e3
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -0,0 +1,261 @@
+#ifndef HOSTAP_AP_H
+#define HOSTAP_AP_H
+
+/* AP data structures for STAs */
+
+/* maximum number of frames to buffer per STA */
+#define STA_MAX_TX_BUFFER 32
+
+/* STA flags */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+ * controlling whether STA is authorized to
+ * send and receive non-IEEE 802.1X frames
+ */
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
+
+#define WLAN_RATE_1M BIT(0)
+#define WLAN_RATE_2M BIT(1)
+#define WLAN_RATE_5M5 BIT(2)
+#define WLAN_RATE_11M BIT(3)
+#define WLAN_RATE_COUNT 4
+
+/* Maximum size of Supported Rates info element. IEEE 802.11 has a limit of 8,
+ * but some pre-standard IEEE 802.11g products use longer elements. */
+#define WLAN_SUPP_RATES_MAX 32
+
+/* Try to increase TX rate after # successfully sent consecutive packets */
+#define WLAN_RATE_UPDATE_COUNT 50
+
+/* Decrease TX rate after # consecutive dropped packets */
+#define WLAN_RATE_DECREASE_THRESHOLD 2
+
+struct sta_info {
+ struct list_head list;
+ struct sta_info *hnext; /* next entry in hash table list */
+ atomic_t users; /* number of users (do not remove if > 0) */
+ struct proc_dir_entry *proc;
+
+ u8 addr[6];
+ u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
+ u32 flags;
+ u16 capability;
+ u16 listen_interval; /* or beacon_int for APs */
+ u8 supported_rates[WLAN_SUPP_RATES_MAX];
+
+ unsigned long last_auth;
+ unsigned long last_assoc;
+ unsigned long last_rx;
+ unsigned long last_tx;
+ unsigned long rx_packets, tx_packets;
+ unsigned long rx_bytes, tx_bytes;
+ struct sk_buff_head tx_buf;
+ /* FIX: timeout buffers with an expiry time somehow derived from
+ * listen_interval */
+
+ s8 last_rx_silence; /* Noise in dBm */
+ s8 last_rx_signal; /* Signal strength in dBm */
+ u8 last_rx_rate; /* TX rate in 0.1 Mbps */
+ u8 last_rx_updated; /* IWSPY's struct iw_quality::updated */
+
+ u8 tx_supp_rates; /* bit field of supported TX rates */
+ u8 tx_rate; /* current TX rate (in 0.1 Mbps) */
+ u8 tx_rate_idx; /* current TX rate (WLAN_RATE_*) */
+ u8 tx_max_rate; /* max TX rate (WLAN_RATE_*) */
+ u32 tx_count[WLAN_RATE_COUNT]; /* number of frames sent (per rate) */
+ u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate)
+ */
+ u32 tx_since_last_failure;
+ u32 tx_consecutive_exc;
+
+ struct ieee80211_crypt_data *crypt;
+
+ int ap; /* whether this station is an AP */
+
+ local_info_t *local;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ union {
+ struct {
+ char *challenge; /* shared key authentication
+ * challenge */
+ } sta;
+ struct {
+ int ssid_len;
+ unsigned char ssid[MAX_SSID_LEN + 1]; /* AP's ssid */
+ int channel;
+ unsigned long last_beacon; /* last RX beacon time */
+ } ap;
+ } u;
+
+ struct timer_list timer;
+ enum { STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH } timeout_next;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+};
+
+
+#define MAX_STA_COUNT 1024
+
+/* Maximum number of AIDs to use for STAs; must be 2007 or lower
+ * (8802.11 limitation) */
+#define MAX_AID_TABLE_SIZE 128
+
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+
+
+/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY_SEC
+ * has passed since last received frame from the station, a nullfunc data
+ * frame is sent to the station. If this frame is not acknowledged and no other
+ * frames have been received, the station will be disassociated after
+ * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after
+ * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with
+ * max inactivity timer. */
+#define AP_MAX_INACTIVITY_SEC (5 * 60)
+#define AP_DISASSOC_DELAY (HZ)
+#define AP_DEAUTH_DELAY (HZ)
+
+/* ap_policy: whether to accept frames to/from other APs/IBSS */
+typedef enum {
+ AP_OTHER_AP_SKIP_ALL = 0,
+ AP_OTHER_AP_SAME_SSID = 1,
+ AP_OTHER_AP_ALL = 2,
+ AP_OTHER_AP_EVEN_IBSS = 3
+} ap_policy_enum;
+
+#define PRISM2_AUTH_OPEN BIT(0)
+#define PRISM2_AUTH_SHARED_KEY BIT(1)
+
+
+/* MAC address-based restrictions */
+struct mac_entry {
+ struct list_head list;
+ u8 addr[6];
+};
+
+struct mac_restrictions {
+ enum { MAC_POLICY_OPEN = 0, MAC_POLICY_ALLOW, MAC_POLICY_DENY } policy;
+ unsigned int entries;
+ struct list_head mac_list;
+ spinlock_t lock;
+};
+
+
+struct add_sta_proc_data {
+ u8 addr[ETH_ALEN];
+ struct add_sta_proc_data *next;
+};
+
+
+typedef enum { WDS_ADD, WDS_DEL } wds_oper_type;
+struct wds_oper_data {
+ wds_oper_type type;
+ u8 addr[ETH_ALEN];
+ struct wds_oper_data *next;
+};
+
+
+struct ap_data {
+ int initialized; /* whether ap_data has been initialized */
+ local_info_t *local;
+ int bridge_packets; /* send packet to associated STAs directly to the
+ * wireless media instead of higher layers in the
+ * kernel */
+ unsigned int bridged_unicast; /* number of unicast frames bridged on
+ * wireless media */
+ unsigned int bridged_multicast; /* number of non-unicast frames
+ * bridged on wireless media */
+ unsigned int tx_drop_nonassoc; /* number of unicast TX packets dropped
+ * because they were to an address that
+ * was not associated */
+ int nullfunc_ack; /* use workaround for nullfunc frame ACKs */
+
+ spinlock_t sta_table_lock;
+ int num_sta; /* number of entries in sta_list */
+ struct list_head sta_list; /* STA info list head */
+ struct sta_info *sta_hash[STA_HASH_SIZE];
+
+ struct proc_dir_entry *proc;
+
+ ap_policy_enum ap_policy;
+ unsigned int max_inactivity;
+ int autom_ap_wds;
+
+ struct mac_restrictions mac_restrictions; /* MAC-based auth */
+ int last_tx_rate;
+
+ struct work_struct add_sta_proc_queue;
+ struct add_sta_proc_data *add_sta_proc_entries;
+
+ struct work_struct wds_oper_queue;
+ struct wds_oper_data *wds_oper_entries;
+
+ u16 tx_callback_idx;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ /* pointers to STA info; based on allocated AID or NULL if AID free
+ * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
+ * and so on
+ */
+ struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
+
+ u16 tx_callback_auth, tx_callback_assoc, tx_callback_poll;
+
+ /* WEP operations for generating challenges to be used with shared key
+ * authentication */
+ struct ieee80211_crypto_ops *crypt;
+ void *crypt_priv;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+};
+
+
+void hostap_rx(struct net_device *dev, struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_init_data(local_info_t *local);
+void hostap_init_ap_proc(local_info_t *local);
+void hostap_free_data(struct ap_data *ap);
+void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver);
+
+typedef enum {
+ AP_TX_CONTINUE, AP_TX_DROP, AP_TX_RETRY, AP_TX_BUFFERED,
+ AP_TX_CONTINUE_NOT_AUTHORIZED
+} ap_tx_ret;
+struct hostap_tx_data {
+ struct sk_buff *skb;
+ int host_encrypt;
+ struct ieee80211_crypt_data *crypt;
+ void *sta_ptr;
+};
+ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
+void hostap_handle_sta_release(void *ptr);
+void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
+typedef enum {
+ AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
+} ap_rx_ret;
+ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
+ struct sk_buff *skb,
+ struct hostap_80211_rx_status *rx_stats,
+ int wds);
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
+ struct ieee80211_crypt_data **crypt,
+ void **sta_ptr);
+int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
+int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
+int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
+ struct hostap_80211_rx_status *rx_stats);
+void hostap_update_rates(local_info_t *local);
+void hostap_add_wds_links(local_info_t *local);
+void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type);
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
+ int resend);
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+#endif /* HOSTAP_AP_H */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
new file mode 100644
index 000000000000..6f4fa9dc308f
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -0,0 +1,435 @@
+#ifndef HOSTAP_COMMON_H
+#define HOSTAP_COMMON_H
+
+#define BIT(x) (1 << (x))
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+
+/* IEEE 802.11 defines */
+
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_CHALLENGE 16
+#define WLAN_EID_RSN 48
+#define WLAN_EID_GENERIC 221
+
+
+/* HFA384X Configuration RIDs */
+#define HFA384X_RID_CNFPORTTYPE 0xFC00
+#define HFA384X_RID_CNFOWNMACADDR 0xFC01
+#define HFA384X_RID_CNFDESIREDSSID 0xFC02
+#define HFA384X_RID_CNFOWNCHANNEL 0xFC03
+#define HFA384X_RID_CNFOWNSSID 0xFC04
+#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05
+#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06
+#define HFA384X_RID_CNFMAXDATALEN 0xFC07
+#define HFA384X_RID_CNFWDSADDRESS 0xFC08
+#define HFA384X_RID_CNFPMENABLED 0xFC09
+#define HFA384X_RID_CNFPMEPS 0xFC0A
+#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B
+#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C
+#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D
+#define HFA384X_RID_CNFOWNNAME 0xFC0E
+#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10
+#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */
+#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */
+#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */
+#define HFA384X_RID_UNKNOWN1 0xFC20
+#define HFA384X_RID_UNKNOWN2 0xFC21
+#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23
+#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24
+#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25
+#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26
+#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27
+#define HFA384X_RID_CNFWEPFLAGS 0xFC28
+#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
+#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A
+#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */
+#define HFA384X_RID_CNFTXCONTROL 0xFC2C
+#define HFA384X_RID_CNFROAMINGMODE 0xFC2D
+#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */
+#define HFA384X_RID_CNFRCVCRCERROR 0xFC30
+#define HFA384X_RID_CNFMMLIFE 0xFC31
+#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32
+#define HFA384X_RID_CNFBEACONINT 0xFC33
+#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */
+#define HFA384X_RID_CNFSTAPCFINFO 0xFC35
+#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37
+#define HFA384X_RID_CNFTIMCTRL 0xFC40
+#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */
+#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */
+#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */
+#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0;
+ * write only */
+#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_GROUPADDRESSES 0xFC80
+#define HFA384X_RID_CREATEIBSS 0xFC81
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82
+#define HFA384X_RID_RTSTHRESHOLD 0xFC83
+#define HFA384X_RID_TXRATECONTROL 0xFC84
+#define HFA384X_RID_PROMISCUOUSMODE 0xFC85
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */
+#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */
+#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */
+#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */
+#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0
+#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
+#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
+#define HFA384X_RID_CNFBASICRATES 0xFCB3
+#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4
+#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */
+#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */
+#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */
+#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */
+#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */
+#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */
+#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */
+#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */
+#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */
+#define HFA384X_RID_TICKTIME 0xFCE0
+#define HFA384X_RID_SCANREQUEST 0xFCE1
+#define HFA384X_RID_JOINREQUEST 0xFCE2
+#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */
+#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */
+#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */
+
+/* HFA384X Information RIDs */
+#define HFA384X_RID_MAXLOADTIME 0xFD00
+#define HFA384X_RID_DOWNLOADBUFFER 0xFD01
+#define HFA384X_RID_PRIID 0xFD02
+#define HFA384X_RID_PRISUPRANGE 0xFD03
+#define HFA384X_RID_CFIACTRANGES 0xFD04
+#define HFA384X_RID_NICSERNUM 0xFD0A
+#define HFA384X_RID_NICID 0xFD0B
+#define HFA384X_RID_MFISUPRANGE 0xFD0C
+#define HFA384X_RID_CFISUPRANGE 0xFD0D
+#define HFA384X_RID_CHANNELLIST 0xFD10
+#define HFA384X_RID_REGULATORYDOMAINS 0xFD11
+#define HFA384X_RID_TEMPTYPE 0xFD12
+#define HFA384X_RID_CIS 0xFD13
+#define HFA384X_RID_STAID 0xFD20
+#define HFA384X_RID_STASUPRANGE 0xFD21
+#define HFA384X_RID_MFIACTRANGES 0xFD22
+#define HFA384X_RID_CFIACTRANGES2 0xFD23
+#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1;
+ * only Prism2.5(?) */
+#define HFA384X_RID_PORTSTATUS 0xFD40
+#define HFA384X_RID_CURRENTSSID 0xFD41
+#define HFA384X_RID_CURRENTBSSID 0xFD42
+#define HFA384X_RID_COMMSQUALITY 0xFD43
+#define HFA384X_RID_CURRENTTXRATE 0xFD44
+#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45
+#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46
+#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47
+#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48
+#define HFA384X_RID_LONGRETRYLIMIT 0xFD49
+#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A
+#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B
+#define HFA384X_RID_CFPOLLABLE 0xFD4C
+#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D
+#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
+#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */
+#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */
+#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */
+#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */
+#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */
+#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */
+#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */
+#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */
+#define HFA384X_RID_PHYTYPE 0xFDC0
+#define HFA384X_RID_CURRENTCHANNEL 0xFDC1
+#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2
+#define HFA384X_RID_CCAMODE 0xFDC3
+#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6
+#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */
+#define HFA384X_RID_BUILDSEQ 0xFFFE
+#define HFA384X_RID_FWID 0xFFFF
+
+
+struct hfa384x_comp_ident
+{
+ u16 id;
+ u16 variant;
+ u16 major;
+ u16 minor;
+} __attribute__ ((packed));
+
+#define HFA384X_COMP_ID_PRI 0x15
+#define HFA384X_COMP_ID_STA 0x1f
+#define HFA384X_COMP_ID_FW_AP 0x14b
+
+struct hfa384x_sup_range
+{
+ u16 role;
+ u16 id;
+ u16 variant;
+ u16 bottom;
+ u16 top;
+} __attribute__ ((packed));
+
+
+struct hfa384x_build_id
+{
+ u16 pri_seq;
+ u16 sec_seq;
+} __attribute__ ((packed));
+
+/* FD01 - Download Buffer */
+struct hfa384x_rid_download_buffer
+{
+ u16 page;
+ u16 offset;
+ u16 length;
+} __attribute__ ((packed));
+
+/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */
+struct hfa384x_comms_quality {
+ u16 comm_qual; /* 0 .. 92 */
+ u16 signal_level; /* 27 .. 154 */
+ u16 noise_level; /* 27 .. 154 */
+} __attribute__ ((packed));
+
+
+/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
+
+/* New wireless extensions API - SET/GET convention (even ioctl numbers are
+ * root only)
+ */
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
+#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
+#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
+#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
+#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
+#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
+#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
+#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
+#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
+#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
+#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
+#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
+#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
+
+/* following are not in SIOCGIWPRIV list; check permission in the driver code
+ */
+#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
+#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
+
+
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
+enum {
+ /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_TXRATECTRL = 2,
+ PRISM2_PARAM_BEACON_INT = 3,
+ PRISM2_PARAM_PSEUDO_IBSS = 4,
+ PRISM2_PARAM_ALC = 5,
+ /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_DUMP = 7,
+ PRISM2_PARAM_OTHER_AP_POLICY = 8,
+ PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
+ PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
+ PRISM2_PARAM_DTIM_PERIOD = 11,
+ PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
+ PRISM2_PARAM_MAX_WDS = 13,
+ PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
+ PRISM2_PARAM_AP_AUTH_ALGS = 15,
+ PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
+ PRISM2_PARAM_HOST_ENCRYPT = 17,
+ PRISM2_PARAM_HOST_DECRYPT = 18,
+ /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, REMOVED 2005-08-14 */
+ /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, REMOVED 2005-08-14 */
+ PRISM2_PARAM_HOST_ROAMING = 21,
+ PRISM2_PARAM_BCRX_STA_KEY = 22,
+ PRISM2_PARAM_IEEE_802_1X = 23,
+ PRISM2_PARAM_ANTSEL_TX = 24,
+ PRISM2_PARAM_ANTSEL_RX = 25,
+ PRISM2_PARAM_MONITOR_TYPE = 26,
+ PRISM2_PARAM_WDS_TYPE = 27,
+ PRISM2_PARAM_HOSTSCAN = 28,
+ PRISM2_PARAM_AP_SCAN = 29,
+ PRISM2_PARAM_ENH_SEC = 30,
+ PRISM2_PARAM_IO_DEBUG = 31,
+ PRISM2_PARAM_BASIC_RATES = 32,
+ PRISM2_PARAM_OPER_RATES = 33,
+ PRISM2_PARAM_HOSTAPD = 34,
+ PRISM2_PARAM_HOSTAPD_STA = 35,
+ PRISM2_PARAM_WPA = 36,
+ PRISM2_PARAM_PRIVACY_INVOKED = 37,
+ PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
+ PRISM2_PARAM_DROP_UNENCRYPTED = 39,
+ PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
+};
+
+enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
+ HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
+
+
+/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
+enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
+ AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
+ AP_MAC_CMD_KICKALL = 4 };
+
+
+/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
+enum {
+ PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
+ /* Note! Old versions of prism2_srec have a fatal error in CRC-16
+ * calculation, which will corrupt all non-volatile downloads.
+ * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
+ * prevent use of old versions of prism2_srec for non-volatile
+ * download. */
+ PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
+ PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
+ /* Persistent versions of volatile download commands (keep firmware
+ * data in memory and automatically re-download after hw_reset */
+ PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
+ PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
+};
+
+struct prism2_download_param {
+ u32 dl_cmd;
+ u32 start_addr;
+ u32 num_areas;
+ struct prism2_download_area {
+ u32 addr; /* wlan card address */
+ u32 len;
+ void __user *ptr; /* pointer to data in user space */
+ } data[0];
+};
+
+#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
+#define PRISM2_MAX_DOWNLOAD_LEN 262144
+
+
+/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
+enum {
+ PRISM2_HOSTAPD_FLUSH = 1,
+ PRISM2_HOSTAPD_ADD_STA = 2,
+ PRISM2_HOSTAPD_REMOVE_STA = 3,
+ PRISM2_HOSTAPD_GET_INFO_STA = 4,
+ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
+ PRISM2_SET_ENCRYPTION = 6,
+ PRISM2_GET_ENCRYPTION = 7,
+ PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
+ PRISM2_HOSTAPD_GET_RID = 9,
+ PRISM2_HOSTAPD_SET_RID = 10,
+ PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
+ PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+ PRISM2_HOSTAPD_MLME = 13,
+ PRISM2_HOSTAPD_SCAN_REQ = 14,
+ PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
+};
+
+#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
+#define PRISM2_HOSTAPD_RID_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+
+/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
+ */
+#define HOSTAP_CRYPT_ALG_NAME_LEN 16
+
+
+struct prism2_hostapd_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u16 aid;
+ u16 capability;
+ u8 tx_supp_rates;
+ } add_sta;
+ struct {
+ u32 inactive_sec;
+ } get_info_sta;
+ struct {
+ u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
+ u32 flags;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+ struct {
+ u32 flags_and;
+ u32 flags_or;
+ } set_flags_sta;
+ struct {
+ u16 rid;
+ u16 len;
+ u8 data[0];
+ } rid;
+ struct {
+ u8 len;
+ u8 data[0];
+ } generic_elem;
+ struct {
+#define MLME_STA_DEAUTH 0
+#define MLME_STA_DISASSOC 1
+ u16 cmd;
+ u16 reason_code;
+ } mlme;
+ struct {
+ u8 ssid_len;
+ u8 ssid[32];
+ } scan_req;
+ } u;
+};
+
+#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
+#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
+
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
+#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
+#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
+
+
+#endif /* HOSTAP_COMMON_H */
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
new file mode 100644
index 000000000000..7ed3425d08c1
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -0,0 +1,55 @@
+#ifndef HOSTAP_CONFIG_H
+#define HOSTAP_CONFIG_H
+
+#define PRISM2_VERSION "0.4.4-kernel"
+
+/* In the previous versions of Host AP driver, support for user space version
+ * of IEEE 802.11 management (hostapd) used to be disabled in the default
+ * configuration. From now on, support for hostapd is always included and it is
+ * possible to disable kernel driver version of IEEE 802.11 management with a
+ * separate define, PRISM2_NO_KERNEL_IEEE80211_MGMT. */
+/* #define PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+/* Maximum number of events handler per one interrupt */
+#define PRISM2_MAX_INTERRUPT_EVENTS 20
+
+/* Include code for downloading firmware images into volatile RAM. */
+#define PRISM2_DOWNLOAD_SUPPORT
+
+/* Allow kernel configuration to enable download support. */
+#if !defined(PRISM2_DOWNLOAD_SUPPORT) && defined(CONFIG_HOSTAP_FIRMWARE)
+#define PRISM2_DOWNLOAD_SUPPORT
+#endif
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+/* Allow writing firmware images into flash, i.e., to non-volatile storage.
+ * Before you enable this option, you should make absolutely sure that you are
+ * using prism2_srec utility that comes with THIS version of the driver!
+ * In addition, please note that it is possible to kill your card with
+ * non-volatile download if you are using incorrect image. This feature has not
+ * been fully tested, so please be careful with it. */
+/* #define PRISM2_NON_VOLATILE_DOWNLOAD */
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+/* Save low-level I/O for debugging. This should not be enabled in normal use.
+ */
+/* #define PRISM2_IO_DEBUG */
+
+/* Following defines can be used to remove unneeded parts of the driver, e.g.,
+ * to limit the size of the kernel module. Definitions can be added here in
+ * hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
+ * e.g.,
+ * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
+ */
+
+/* Do not include debug messages into the driver */
+/* #define PRISM2_NO_DEBUG */
+
+/* Do not include /proc/net/prism2/wlan#/{registers,debug} */
+/* #define PRISM2_NO_PROCFS_DEBUG */
+
+/* Do not include station functionality (i.e., allow only Master (Host AP) mode
+ */
+/* #define PRISM2_NO_STATION_MODES */
+
+#endif /* HOSTAP_CONFIG_H */
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
new file mode 100644
index 000000000000..2643976a6677
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -0,0 +1,1006 @@
+#define PRISM2_PCCARD
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static dev_info_t dev_info = "hostap_cs";
+static dev_link_t *dev_list = NULL;
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
+ "cards (PC Card).");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+static int ignore_cis_vcc;
+module_param(ignore_cis_vcc, int, 0444);
+MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
+
+
+/* struct local_info::hw_priv */
+struct hostap_cs_priv {
+ dev_node_t node;
+ dev_link_t *link;
+ int sandisk_connectplus;
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ outb(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ v = inb(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ outw(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ v = inw(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
+ outsw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline void hfa384x_insw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
+ insw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
+
+#else /* PRISM2_IO_DEBUG */
+
+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
+#define HFA384X_INB(a) inb(dev->base_addr + (a))
+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
+#define HFA384X_INW(a) inw(dev->base_addr + (a))
+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_INSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_OUTSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+
+
+static void prism2_detach(dev_link_t *link);
+static void prism2_release(u_long arg);
+static int prism2_event(event_t event, int priority,
+ event_callback_args_t *args);
+
+
+static int prism2_pccard_card_present(local_info_t *local)
+{
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+ if (hw_priv != NULL && hw_priv->link != NULL &&
+ ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
+ (DEV_PRESENT | DEV_CONFIG)))
+ return 1;
+ return 0;
+}
+
+
+/*
+ * SanDisk CompactFlash WLAN Flashcard - Product Manual v1.0
+ * Document No. 20-10-00058, January 2004
+ * http://www.sandisk.com/pdf/industrial/ProdManualCFWLANv1.0.pdf
+ */
+#define SANDISK_WLAN_ACTIVATION_OFF 0x40
+#define SANDISK_HCR_OFF 0x42
+
+
+static void sandisk_set_iobase(local_info_t *local)
+{
+ int res;
+ conf_reg_t reg;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = 0x10; /* 0x3f0 IO base 1 */
+ reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
+ " res=%d\n", res);
+ }
+ udelay(10);
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = 0x12; /* 0x3f2 IO base 2 */
+ reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
+ " res=%d\n", res);
+ }
+}
+
+
+static void sandisk_write_hcr(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+ int i;
+
+ HFA384X_OUTB(0x80, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(50);
+ for (i = 0; i < 10; i++) {
+ HFA384X_OUTB(hcr, SANDISK_HCR_OFF);
+ }
+ udelay(55);
+ HFA384X_OUTB(0x45, SANDISK_WLAN_ACTIVATION_OFF);
+}
+
+
+static int sandisk_enable_wireless(struct net_device *dev)
+{
+ int res, ret = 0;
+ conf_reg_t reg;
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ tuple_t tuple;
+ cisparse_t *parse = NULL;
+ u_char buf[64];
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (hw_priv->link->io.NumPorts1 < 0x42) {
+ /* Not enough ports to be SanDisk multi-function card */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
+ if (parse == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ tuple.DesiredTuple = CISTPL_MANFID;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
+ /* No SanDisk manfid found */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
+ if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ parse->longlink_mfc.nfn < 2) {
+ /* No multi-function links found */
+ ret = -ENODEV;
+ goto done;
+ }
+
+ printk(KERN_DEBUG "%s: Multi-function SanDisk ConnectPlus detected"
+ " - using vendor-specific initialization\n", dev->name);
+ hw_priv->sandisk_connectplus = 1;
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
+ dev->name, res);
+ goto done;
+ }
+ mdelay(5);
+
+ reg.Function = 0;
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ /*
+ * Do not enable interrupts here to avoid some bogus events. Interrupts
+ * will be enabled during the first cor_sreset call.
+ */
+ reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
+ dev->name, res);
+ goto done;
+ }
+ mdelay(5);
+
+ sandisk_set_iobase(local);
+
+ HFA384X_OUTB(0xc5, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(10);
+ HFA384X_OUTB(0x4b, SANDISK_WLAN_ACTIVATION_OFF);
+ udelay(10);
+
+done:
+ kfree(parse);
+ return ret;
+}
+
+
+static void prism2_pccard_cor_sreset(local_info_t *local)
+{
+ int res;
+ conf_reg_t reg;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (!prism2_pccard_card_present(local))
+ return;
+
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ reg.Value = 0;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
+ res);
+ return;
+ }
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n",
+ reg.Value);
+
+ reg.Action = CS_WRITE;
+ reg.Value |= COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
+ res);
+ return;
+ }
+
+ mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
+
+ reg.Value &= ~COR_SOFT_RESET;
+ if (hw_priv->sandisk_connectplus)
+ reg.Value |= COR_IREQ_ENA;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
+ res);
+ return;
+ }
+
+ mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
+
+ if (hw_priv->sandisk_connectplus)
+ sandisk_set_iobase(local);
+}
+
+
+static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
+{
+ int res;
+ conf_reg_t reg;
+ int old_cor;
+ struct hostap_cs_priv *hw_priv = local->hw_priv;
+
+ if (!prism2_pccard_card_present(local))
+ return;
+
+ if (hw_priv->sandisk_connectplus) {
+ sandisk_write_hcr(local, hcr);
+ return;
+ }
+
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ reg.Value = 0;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
+ "(%d)\n", res);
+ return;
+ }
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset: original COR %02x\n",
+ reg.Value);
+ old_cor = reg.Value;
+
+ reg.Action = CS_WRITE;
+ reg.Value |= COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
+ "(%d)\n", res);
+ return;
+ }
+
+ mdelay(10);
+
+ /* Setup Genesis mode */
+ reg.Action = CS_WRITE;
+ reg.Value = hcr;
+ reg.Offset = CISREG_CCSR;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
+ "(%d)\n", res);
+ return;
+ }
+ mdelay(10);
+
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = old_cor & ~COR_SOFT_RESET;
+ res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ &reg);
+ if (res != CS_SUCCESS) {
+ printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
+ "(%d)\n", res);
+ return;
+ }
+
+ mdelay(10);
+}
+
+
+static struct prism2_helper_functions prism2_pccard_funcs =
+{
+ .card_present = prism2_pccard_card_present,
+ .cor_sreset = prism2_pccard_cor_sreset,
+ .genesis_reset = prism2_pccard_genesis_reset,
+ .hw_type = HOSTAP_HW_PCCARD,
+};
+
+
+/* allocate local data and register with CardServices
+ * initialize dev_link structure, but do not configure the card yet */
+static dev_link_t *prism2_attach(void)
+{
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret;
+
+ link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
+ if (link == NULL)
+ return NULL;
+
+ memset(link, 0, sizeof(dev_link_t));
+
+ PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
+ link->conf.Vcc = 33;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* register with CardServices */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ prism2_detach(link);
+ return NULL;
+ }
+ return link;
+}
+
+
+static void prism2_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+
+ PDEBUG(DEBUG_FLOW, "prism2_detach\n");
+
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+ if (*linkp == NULL) {
+ printk(KERN_WARNING "%s: Attempt to detach non-existing "
+ "PCMCIA client\n", dev_info);
+ return;
+ }
+
+ if (link->state & DEV_CONFIG) {
+ prism2_release((u_long)link);
+ }
+
+ if (link->handle) {
+ int res = pcmcia_deregister_client(link->handle);
+ if (res) {
+ printk("CardService(DeregisterClient) => %d\n", res);
+ cs_error(link->handle, DeregisterClient, res);
+ }
+ }
+
+ *linkp = link->next;
+ /* release net devices */
+ if (link->priv) {
+ struct hostap_cs_priv *hw_priv;
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ dev = link->priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ prism2_free_local_data(dev);
+ kfree(hw_priv);
+ }
+ kfree(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->handle, 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(dev_link_t *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 = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (parse == NULL || hw_priv == NULL) {
+ kfree(parse);
+ kfree(hw_priv);
+ ret = -ENOMEM;
+ goto failed;
+ }
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse));
+ link->conf.ConfigBase = parse->config.base;
+ link->conf.Present = parse->config.rmask[0];
+
+ CS_CHECK(GetConfigurationInfo,
+ pcmcia_get_configuration_info(link->handle, &conf));
+ PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
+ ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
+ link->conf.Vcc = conf.Vcc;
+
+ /* Look for an appropriate configuration table entry in the CIS */
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+ for (;;) {
+ cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
+ CFG_CHECK2(GetTupleData,
+ pcmcia_get_tuple_data(link->handle, &tuple));
+ CFG_CHECK2(ParseTuple,
+ pcmcia_parse_tuple(link->handle, &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.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ 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->handle, &link->io));
+
+ /* This configuration table entry is OK */
+ break;
+
+ next_entry:
+ CS_CHECK(GetNextTuple,
+ pcmcia_get_next_tuple(link->handle, &tuple));
+ }
+
+ /* Need to allocate net_device before requesting IRQ handler */
+ dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
+ &handle_to_dev(link->handle));
+ if (dev == NULL)
+ goto failed;
+ link->priv = dev;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ hw_priv->link = link;
+ strcpy(hw_priv->node.dev_name, dev->name);
+ link->dev = &hw_priv->node;
+
+ /*
+ * 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) {
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Handler = prism2_interrupt;
+ link->irq.Instance = dev;
+ 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));
+
+ dev->irq = link->irq.AssignedIRQ;
+ dev->base_addr = link->io.BasePort1;
+
+ /* Finally, report what we've done */
+ printk(KERN_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;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ local->shutdown = 0;
+
+ sandisk_enable_wireless(dev);
+
+ ret = prism2_hw_config(dev, 1);
+ if (!ret) {
+ ret = hostap_hw_ready(dev);
+ if (ret == 0 && local->ddev)
+ strcpy(hw_priv->node.dev_name, local->ddev->name);
+ }
+ kfree(parse);
+ return ret;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+ kfree(parse);
+ kfree(hw_priv);
+ prism2_release((u_long)link);
+ return ret;
+}
+
+
+static void prism2_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+
+ PDEBUG(DEBUG_FLOW, "prism2_release\n");
+
+ if (link->priv) {
+ struct net_device *dev = link->priv;
+ struct hostap_interface *iface;
+
+ iface = netdev_priv(dev);
+ if (link->state & DEV_CONFIG)
+ prism2_hw_shutdown(dev, 0);
+ iface->local->shutdown = 1;
+ }
+
+ 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;
+
+ PDEBUG(DEBUG_FLOW, "release - done\n");
+}
+
+
+static int prism2_event(event_t event, int priority,
+ event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ struct net_device *dev = (struct net_device *) link->priv;
+ int dev_open = 0;
+
+ if (link->state & DEV_CONFIG) {
+ struct hostap_interface *iface = netdev_priv(dev);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
+ }
+
+ switch (event) {
+ case CS_EVENT_CARD_INSERTION:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info);
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ if (prism2_config(link)) {
+ PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+ }
+ break;
+
+ case CS_EVENT_CARD_REMOVAL:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ prism2_release((u_long) link);
+ }
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+ link->state |= DEV_SUSPEND;
+ /* fall through */
+
+ case CS_EVENT_RESET_PHYSICAL:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
+ if (link->state & DEV_CONFIG) {
+ if (dev_open) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+ prism2_suspend(dev);
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+ link->state &= ~DEV_SUSPEND;
+ /* fall through */
+
+ case CS_EVENT_CARD_RESET:
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle,
+ &link->conf);
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, dev_open ? 0 : 1);
+ if (dev_open) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ }
+ }
+ break;
+
+ default:
+ PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
+ dev_info, event);
+ break;
+ }
+ return 0;
+}
+
+
+static struct pcmcia_device_id hostap_cs_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
+ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777),
+ PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000),
+ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b),
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612),
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001),
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001),
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
+ PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
+ PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
+ 0x7a954bd9, 0x74be00c6),
+ PCMCIA_DEVICE_PROD_ID1234(
+ "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P",
+ "Eval-RevA",
+ 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e),
+ PCMCIA_DEVICE_PROD_ID123(
+ "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
+ 0xe6ec52ce, 0x08649af2, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02",
+ 0x71b18589, 0xb6f1b0ab, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "Instant Wireless ", " Network PC CARD", "Version 01.02",
+ 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID123(
+ "SMC", "SMC2632W", "Version 01.02",
+ 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G",
+ 0x2decece3, 0x82067c18),
+ PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card",
+ 0x54f7c49c, 0x15a75e5b),
+ PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE",
+ 0x74c5e40d, 0xdb472a18),
+ PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card",
+ 0x0733cc81, 0x0c52f395),
+ PCMCIA_DEVICE_PROD_ID12(
+ "ZoomAir 11Mbps High", "Rate wireless Networking",
+ 0x273fe3db, 0x32a1eaee),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
+
+
+static struct pcmcia_driver hostap_driver = {
+ .drv = {
+ .name = "hostap_cs",
+ },
+ .attach = prism2_attach,
+ .detach = prism2_detach,
+ .owner = THIS_MODULE,
+ .event = prism2_event,
+ .id_table = hostap_cs_ids,
+};
+
+static int __init init_prism2_pccard(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+ return pcmcia_register_driver(&hostap_driver);
+}
+
+static void __exit exit_prism2_pccard(void)
+{
+ pcmcia_unregister_driver(&hostap_driver);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_pccard);
+module_exit(exit_prism2_pccard);
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
new file mode 100644
index 000000000000..ab26b52b3e76
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -0,0 +1,766 @@
+static int prism2_enable_aux_port(struct net_device *dev, int enable)
+{
+ u16 val, reg;
+ int i, tries;
+ unsigned long flags;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ if (enable) {
+ PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
+ "port is already enabled\n", dev->name);
+ }
+ return 0;
+ }
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+
+ /* wait until busy bit is clear */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+ printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
+ dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ val = HFA384X_INW(HFA384X_CONTROL_OFF);
+
+ if (enable) {
+ HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
+
+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
+ printk("prism2_enable_aux_port: was not disabled!?\n");
+ val &= ~HFA384X_AUX_PORT_MASK;
+ val |= HFA384X_AUX_PORT_ENABLE;
+ } else {
+ HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+
+ if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
+ printk("prism2_enable_aux_port: was not enabled!?\n");
+ val &= ~HFA384X_AUX_PORT_MASK;
+ val |= HFA384X_AUX_PORT_DISABLE;
+ }
+ HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
+
+ udelay(5);
+
+ i = 10000;
+ while (i > 0) {
+ val = HFA384X_INW(HFA384X_CONTROL_OFF);
+ val &= HFA384X_AUX_PORT_MASK;
+
+ if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
+ (!enable && val == HFA384X_AUX_PORT_DISABLED))
+ break;
+
+ udelay(10);
+ i--;
+ }
+
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (i == 0) {
+ printk("prism2_enable_aux_port(%d) timed out\n",
+ enable);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+
+static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
+ void *buf)
+{
+ u16 page, offset;
+ if (addr & 1 || len & 1)
+ return -1;
+
+ page = addr >> 7;
+ offset = addr & 0x7f;
+
+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
+
+ udelay(5);
+
+#ifdef PRISM2_PCI
+ {
+ u16 *pos = (u16 *) buf;
+ while (len > 0) {
+ *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
+ len -= 2;
+ }
+ }
+#else /* PRISM2_PCI */
+ HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
+#endif /* PRISM2_PCI */
+
+ return 0;
+}
+
+
+static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
+ void *buf)
+{
+ u16 page, offset;
+ if (addr & 1 || len & 1)
+ return -1;
+
+ page = addr >> 7;
+ offset = addr & 0x7f;
+
+ HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
+ HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
+
+ udelay(5);
+
+#ifdef PRISM2_PCI
+ {
+ u16 *pos = (u16 *) buf;
+ while (len > 0) {
+ HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
+ len -= 2;
+ }
+ }
+#else /* PRISM2_PCI */
+ HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
+#endif /* PRISM2_PCI */
+
+ return 0;
+}
+
+
+static int prism2_pda_ok(u8 *buf)
+{
+ u16 *pda = (u16 *) buf;
+ int pos;
+ u16 len, pdr;
+
+ if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
+ buf[3] == 0x00)
+ return 0;
+
+ pos = 0;
+ while (pos + 1 < PRISM2_PDA_SIZE / 2) {
+ len = le16_to_cpu(pda[pos]);
+ pdr = le16_to_cpu(pda[pos + 1]);
+ if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
+ return 0;
+
+ if (pdr == 0x0000 && len == 2) {
+ /* PDA end found */
+ return 1;
+ }
+
+ pos += len + 1;
+ }
+
+ return 0;
+}
+
+
+static int prism2_download_aux_dump(struct net_device *dev,
+ unsigned int addr, int len, u8 *buf)
+{
+ int res;
+
+ prism2_enable_aux_port(dev, 1);
+ res = hfa384x_from_aux(dev, addr, len, buf);
+ prism2_enable_aux_port(dev, 0);
+ if (res)
+ return -1;
+
+ return 0;
+}
+
+
+static u8 * prism2_read_pda(struct net_device *dev)
+{
+ u8 *buf;
+ int res, i, found = 0;
+#define NUM_PDA_ADDRS 4
+ unsigned int pda_addr[NUM_PDA_ADDRS] = {
+ 0x7f0000 /* others than HFA3841 */,
+ 0x3f0000 /* HFA3841 */,
+ 0x390000 /* apparently used in older cards */,
+ 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
+ };
+
+ buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
+ if (buf == NULL)
+ return NULL;
+
+ /* Note: wlan card should be in initial state (just after init cmd)
+ * and no other operations should be performed concurrently. */
+
+ prism2_enable_aux_port(dev, 1);
+
+ for (i = 0; i < NUM_PDA_ADDRS; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
+ dev->name, pda_addr[i]);
+ res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
+ if (res)
+ continue;
+ if (res == 0 && prism2_pda_ok(buf)) {
+ PDEBUG2(DEBUG_EXTRA2, ": OK\n");
+ found = 1;
+ break;
+ } else {
+ PDEBUG2(DEBUG_EXTRA2, ": failed\n");
+ }
+ }
+
+ prism2_enable_aux_port(dev, 0);
+
+ if (!found) {
+ printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
+ kfree(buf);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+
+static int prism2_download_volatile(local_info_t *local,
+ struct prism2_download_data *param)
+{
+ struct net_device *dev = local->dev;
+ int ret = 0, i;
+ u16 param0, param1;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -1;
+ }
+
+ local->hw_downloading = 1;
+ if (local->pri_only) {
+ hfa384x_disable_interrupts(dev);
+ } else {
+ prism2_hw_shutdown(dev, 0);
+
+ if (prism2_hw_init(dev, 0)) {
+ printk(KERN_WARNING "%s: Could not initialize card for"
+ " download\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_WARNING "%s: Could not enable AUX port\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ param0 = param->start_addr & 0xffff;
+ param1 = param->start_addr >> 16;
+
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
+ param0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
+ dev->name, param->data[i].len, param->data[i].addr);
+ if (hfa384x_to_aux(dev, param->data[i].addr,
+ param->data[i].len, param->data[i].data)) {
+ printk(KERN_WARNING "%s: RAM download at 0x%08x "
+ "(len=%d) failed\n", dev->name,
+ param->data[i].addr, param->data[i].len);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_DISABLE << 8), param0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+ /* ProgMode disable causes the hardware to restart itself from the
+ * given starting address. Give hw some time and ACK command just in
+ * case restart did not happen. */
+ mdelay(5);
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
+ dev->name);
+ /* continue anyway.. restart should have taken care of this */
+ }
+
+ mdelay(5);
+ local->hw_downloading = 0;
+ if (prism2_hw_config(dev, 2)) {
+ printk(KERN_WARNING "%s: Card configuration after RAM "
+ "download failed\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+
+
+static int prism2_enable_genesis(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+ u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
+ u8 readbuf[4];
+
+ printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
+ dev->name, hcr);
+ local->func->cor_sreset(local);
+ hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
+ local->func->genesis_reset(local, hcr);
+
+ /* Readback test */
+ hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
+ hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
+ hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
+
+ if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
+ printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
+ hcr);
+ return 0;
+ } else {
+ printk(KERN_DEBUG "Readback test failed, HCR 0x%02x "
+ "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
+ hcr, initseq[0], initseq[1], initseq[2], initseq[3],
+ readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
+ return 1;
+ }
+}
+
+
+static int prism2_get_ram_size(local_info_t *local)
+{
+ int ret;
+
+ /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
+ if (prism2_enable_genesis(local, 0x1f) == 0)
+ ret = 8;
+ else if (prism2_enable_genesis(local, 0x0f) == 0)
+ ret = 16;
+ else
+ ret = -1;
+
+ /* Disable genesis mode */
+ local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
+
+ return ret;
+}
+
+
+static int prism2_download_genesis(local_info_t *local,
+ struct prism2_download_data *param)
+{
+ struct net_device *dev = local->dev;
+ int ram16 = 0, i;
+ int ret = 0;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -EBUSY;
+ }
+
+ if (!local->func->genesis_reset || !local->func->cor_sreset) {
+ printk(KERN_INFO "%s: Genesis mode downloading not supported "
+ "with this hwmodel\n", dev->name);
+ return -EOPNOTSUPP;
+ }
+
+ local->hw_downloading = 1;
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_DEBUG "%s: failed to enable AUX port\n",
+ dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (local->sram_type == -1) {
+ /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
+ if (prism2_enable_genesis(local, 0x1f) == 0) {
+ ram16 = 0;
+ PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
+ "SRAM\n", dev->name);
+ } else if (prism2_enable_genesis(local, 0x0f) == 0) {
+ ram16 = 1;
+ PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
+ "SRAM\n", dev->name);
+ } else {
+ printk(KERN_DEBUG "%s: Could not initiate genesis "
+ "mode\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+ } else {
+ if (prism2_enable_genesis(local, local->sram_type == 8 ?
+ 0x1f : 0x0f)) {
+ printk(KERN_DEBUG "%s: Failed to set Genesis "
+ "mode (sram_type=%d)\n", dev->name,
+ local->sram_type);
+ ret = -EIO;
+ goto out;
+ }
+ ram16 = local->sram_type != 8;
+ }
+
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
+ dev->name, param->data[i].len, param->data[i].addr);
+ if (hfa384x_to_aux(dev, param->data[i].addr,
+ param->data[i].len, param->data[i].data)) {
+ printk(KERN_WARNING "%s: RAM download at 0x%08x "
+ "(len=%d) failed\n", dev->name,
+ param->data[i].addr, param->data[i].len);
+ ret = -EIO;
+ goto out;
+ }
+ }
+
+ PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
+ local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
+ dev->name);
+ }
+
+ mdelay(5);
+ local->hw_downloading = 0;
+
+ PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
+ /*
+ * Make sure the INIT command does not generate a command completion
+ * event by disabling interrupts.
+ */
+ hfa384x_disable_interrupts(dev);
+ if (prism2_hw_init(dev, 1)) {
+ printk(KERN_DEBUG "%s: Initialization after genesis mode "
+ "download failed\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
+ if (prism2_hw_init2(dev, 1)) {
+ printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
+ "download failed\n", dev->name);
+ ret = -EIO;
+ goto out;
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+
+
+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
+/* Note! Non-volatile downloading functionality has not yet been tested
+ * thoroughly and it may corrupt flash image and effectively kill the card that
+ * is being updated. You have been warned. */
+
+static inline int prism2_download_block(struct net_device *dev,
+ u32 addr, u8 *data,
+ u32 bufaddr, int rest_len)
+{
+ u16 param0, param1;
+ int block_len;
+
+ block_len = rest_len < 4096 ? rest_len : 4096;
+
+ param0 = addr & 0xffff;
+ param1 = addr >> 16;
+
+ HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
+ param0)) {
+ printk(KERN_WARNING "%s: Flash download command execution "
+ "failed\n", dev->name);
+ return -1;
+ }
+
+ if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
+ printk(KERN_WARNING "%s: flash download at 0x%08x "
+ "(len=%d) failed\n", dev->name, addr, block_len);
+ return -1;
+ }
+
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
+ 0)) {
+ printk(KERN_WARNING "%s: Flash write command execution "
+ "failed\n", dev->name);
+ return -1;
+ }
+
+ return block_len;
+}
+
+
+static int prism2_download_nonvolatile(local_info_t *local,
+ struct prism2_download_data *dl)
+{
+ struct net_device *dev = local->dev;
+ int ret = 0, i;
+ struct {
+ u16 page;
+ u16 offset;
+ u16 len;
+ } dlbuffer;
+ u32 bufaddr;
+
+ if (local->hw_downloading) {
+ printk(KERN_WARNING "%s: Already downloading - aborting new "
+ "request\n", dev->name);
+ return -1;
+ }
+
+ ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
+ &dlbuffer, 6, 0);
+
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: Could not read download buffer "
+ "parameters\n", dev->name);
+ goto out;
+ }
+
+ dlbuffer.page = le16_to_cpu(dlbuffer.page);
+ dlbuffer.offset = le16_to_cpu(dlbuffer.offset);
+ dlbuffer.len = le16_to_cpu(dlbuffer.len);
+
+ printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
+ dlbuffer.len, dlbuffer.page, dlbuffer.offset);
+
+ bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
+
+ local->hw_downloading = 1;
+
+ if (!local->pri_only) {
+ prism2_hw_shutdown(dev, 0);
+
+ if (prism2_hw_init(dev, 0)) {
+ printk(KERN_WARNING "%s: Could not initialize card for"
+ " download\n", dev->name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ hfa384x_disable_interrupts(dev);
+
+ if (prism2_enable_aux_port(dev, 1)) {
+ printk(KERN_WARNING "%s: Could not enable AUX port\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
+ for (i = 0; i < dl->num_areas; i++) {
+ int rest_len = dl->data[i].len;
+ int data_off = 0;
+
+ while (rest_len > 0) {
+ int block_len;
+
+ block_len = prism2_download_block(
+ dev, dl->data[i].addr + data_off,
+ dl->data[i].data + data_off, bufaddr,
+ rest_len);
+
+ if (block_len < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ rest_len -= block_len;
+ data_off += block_len;
+ }
+ }
+
+ HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+ (HFA384X_PROGMODE_DISABLE << 8), 0)) {
+ printk(KERN_WARNING "%s: Download command execution failed\n",
+ dev->name);
+ ret = -1;
+ goto out;
+ }
+
+ if (prism2_enable_aux_port(dev, 0)) {
+ printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
+ dev->name);
+ /* continue anyway.. restart should have taken care of this */
+ }
+
+ mdelay(5);
+
+ local->func->hw_reset(dev);
+ local->hw_downloading = 0;
+ if (prism2_hw_config(dev, 2)) {
+ printk(KERN_WARNING "%s: Card configuration after flash "
+ "download failed\n", dev->name);
+ ret = -1;
+ } else {
+ printk(KERN_INFO "%s: Card initialized successfully after "
+ "flash download\n", dev->name);
+ }
+
+ out:
+ local->hw_downloading = 0;
+ return ret;
+}
+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
+
+
+static void prism2_download_free_data(struct prism2_download_data *dl)
+{
+ int i;
+
+ if (dl == NULL)
+ return;
+
+ for (i = 0; i < dl->num_areas; i++)
+ kfree(dl->data[i].data);
+ kfree(dl);
+}
+
+
+static int prism2_download(local_info_t *local,
+ struct prism2_download_param *param)
+{
+ int ret = 0;
+ int i;
+ u32 total_len = 0;
+ struct prism2_download_data *dl = NULL;
+
+ printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
+ "num_areas=%d\n",
+ param->dl_cmd, param->start_addr, param->num_areas);
+
+ if (param->num_areas > 100) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dl = kmalloc(sizeof(*dl) + param->num_areas *
+ sizeof(struct prism2_download_data_area), GFP_KERNEL);
+ if (dl == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memset(dl, 0, sizeof(*dl) + param->num_areas *
+ sizeof(struct prism2_download_data_area));
+ dl->dl_cmd = param->dl_cmd;
+ dl->start_addr = param->start_addr;
+ dl->num_areas = param->num_areas;
+ for (i = 0; i < param->num_areas; i++) {
+ PDEBUG(DEBUG_EXTRA2,
+ " area %d: addr=0x%08x len=%d ptr=0x%p\n",
+ i, param->data[i].addr, param->data[i].len,
+ param->data[i].ptr);
+
+ dl->data[i].addr = param->data[i].addr;
+ dl->data[i].len = param->data[i].len;
+
+ total_len += param->data[i].len;
+ if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
+ total_len > PRISM2_MAX_DOWNLOAD_LEN) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
+ if (dl->data[i].data == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(dl->data[i].data, param->data[i].ptr,
+ param->data[i].len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+
+ switch (param->dl_cmd) {
+ case PRISM2_DOWNLOAD_VOLATILE:
+ case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
+ ret = prism2_download_volatile(local, dl);
+ break;
+ case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
+ case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
+ ret = prism2_download_genesis(local, dl);
+ break;
+ case PRISM2_DOWNLOAD_NON_VOLATILE:
+#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
+ ret = prism2_download_nonvolatile(local, dl);
+#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
+ printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
+ local->dev->name);
+ ret = -EOPNOTSUPP;
+#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
+ break;
+ default:
+ printk(KERN_DEBUG "%s: unsupported download command %d\n",
+ local->dev->name, param->dl_cmd);
+ ret = -EINVAL;
+ break;
+ };
+
+ out:
+ if (ret == 0 && dl &&
+ param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
+ prism2_download_free_data(local->dl_pri);
+ local->dl_pri = dl;
+ } else if (ret == 0 && dl &&
+ param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
+ prism2_download_free_data(local->dl_sec);
+ local->dl_sec = dl;
+ } else
+ prism2_download_free_data(dl);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
new file mode 100644
index 000000000000..59fc15572395
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -0,0 +1,3447 @@
+/*
+ * Host AP (software wireless LAN access point) driver for
+ * Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ *
+ * FIX:
+ * - there is currently no way of associating TX packets to correct wds device
+ * when TX Exc/OK event occurs, so all tx_packets and some
+ * tx_errors/tx_dropped are added to the main netdevice; using sw_support
+ * field in txdesc might be used to fix this (using Alloc event to increment
+ * tx_packets would need some further info in txfid table)
+ *
+ * Buffer Access Path (BAP) usage:
+ * Prism2 cards have two separate BAPs for accessing the card memory. These
+ * should allow concurrent access to two different frames and the driver
+ * previously used BAP0 for sending data and BAP1 for receiving data.
+ * However, there seems to be number of issues with concurrent access and at
+ * least one know hardware bug in using BAP0 and BAP1 concurrently with PCI
+ * Prism2.5. Therefore, the driver now only uses BAP0 for moving data between
+ * host and card memories. BAP0 accesses are protected with local->baplock
+ * (spin_lock_bh) to prevent concurrent use.
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211_crypt.h>
+#include <asm/irq.h>
+
+#include "hostap_80211.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+
+/* #define final_version */
+
+static int mtu = 1500;
+module_param(mtu, int, 0444);
+MODULE_PARM_DESC(mtu, "Maximum transfer unit");
+
+static int channel[MAX_PARM_DEVICES] = { 3, DEF_INTS };
+module_param_array(channel, int, NULL, 0444);
+MODULE_PARM_DESC(channel, "Initial channel");
+
+static char essid[33] = "test";
+module_param_string(essid, essid, sizeof(essid), 0444);
+MODULE_PARM_DESC(essid, "Host AP's ESSID");
+
+static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS };
+module_param_array(iw_mode, int, NULL, 0444);
+MODULE_PARM_DESC(iw_mode, "Initial operation mode");
+
+static int beacon_int[MAX_PARM_DEVICES] = { 100, DEF_INTS };
+module_param_array(beacon_int, int, NULL, 0444);
+MODULE_PARM_DESC(beacon_int, "Beacon interval (1 = 1024 usec)");
+
+static int dtim_period[MAX_PARM_DEVICES] = { 1, DEF_INTS };
+module_param_array(dtim_period, int, NULL, 0444);
+MODULE_PARM_DESC(dtim_period, "DTIM period");
+
+static char dev_template[16] = "wlan%d";
+module_param_string(dev_template, dev_template, sizeof(dev_template), 0444);
+MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: "
+ "wlan%d)");
+
+#ifdef final_version
+#define EXTRA_EVENTS_WTERR 0
+#else
+/* check WTERR events (Wait Time-out) in development versions */
+#define EXTRA_EVENTS_WTERR HFA384X_EV_WTERR
+#endif
+
+/* Events that will be using BAP0 */
+#define HFA384X_BAP0_EVENTS \
+ (HFA384X_EV_TXEXC | HFA384X_EV_RX | HFA384X_EV_INFO | HFA384X_EV_TX)
+
+/* event mask, i.e., events that will result in an interrupt */
+#define HFA384X_EVENT_MASK \
+ (HFA384X_BAP0_EVENTS | HFA384X_EV_ALLOC | HFA384X_EV_INFDROP | \
+ HFA384X_EV_CMD | HFA384X_EV_TICK | \
+ EXTRA_EVENTS_WTERR)
+
+/* Default TX control flags: use 802.11 headers and request interrupt for
+ * failed transmits. Frames that request ACK callback, will add
+ * _TX_OK flag and _ALT_RTRY flag may be used to select different retry policy.
+ */
+#define HFA384X_TX_CTRL_FLAGS \
+ (HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX)
+
+
+/* ca. 1 usec */
+#define HFA384X_CMD_BUSY_TIMEOUT 5000
+#define HFA384X_BAP_BUSY_TIMEOUT 50000
+
+/* ca. 10 usec */
+#define HFA384X_CMD_COMPL_TIMEOUT 20000
+#define HFA384X_DL_COMPL_TIMEOUT 1000000
+
+/* Wait times for initialization; yield to other processes to avoid busy
+ * waiting for long time. */
+#define HFA384X_INIT_TIMEOUT (HZ / 2) /* 500 ms */
+#define HFA384X_ALLOC_COMPL_TIMEOUT (HZ / 20) /* 50 ms */
+
+
+static void prism2_hw_reset(struct net_device *dev);
+static void prism2_check_sta_fw_version(local_info_t *local);
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+/* hostap_download.c */
+static int prism2_download_aux_dump(struct net_device *dev,
+ unsigned int addr, int len, u8 *buf);
+static u8 * prism2_read_pda(struct net_device *dev);
+static int prism2_download(local_info_t *local,
+ struct prism2_download_param *param);
+static void prism2_download_free_data(struct prism2_download_data *dl);
+static int prism2_download_volatile(local_info_t *local,
+ struct prism2_download_data *param);
+static int prism2_download_genesis(local_info_t *local,
+ struct prism2_download_data *param);
+static int prism2_get_ram_size(local_info_t *local);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+
+
+
+#ifndef final_version
+/* magic value written to SWSUPPORT0 reg. for detecting whether card is still
+ * present */
+#define HFA384X_MAGIC 0x8A32
+#endif
+
+
+static u16 hfa384x_read_reg(struct net_device *dev, u16 reg)
+{
+ return HFA384X_INW(reg);
+}
+
+
+static void hfa384x_read_regs(struct net_device *dev,
+ struct hfa384x_regs *regs)
+{
+ regs->cmd = HFA384X_INW(HFA384X_CMD_OFF);
+ regs->evstat = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ regs->offset0 = HFA384X_INW(HFA384X_OFFSET0_OFF);
+ regs->offset1 = HFA384X_INW(HFA384X_OFFSET1_OFF);
+ regs->swsupport0 = HFA384X_INW(HFA384X_SWSUPPORT0_OFF);
+}
+
+
+/**
+ * __hostap_cmd_queue_free - Free Prism2 command queue entry (private)
+ * @local: pointer to private Host AP driver data
+ * @entry: Prism2 command queue entry to be freed
+ * @del_req: request the entry to be removed
+ *
+ * Internal helper function for freeing Prism2 command queue entries.
+ * Caller must have acquired local->cmdlock before calling this function.
+ */
+static inline void __hostap_cmd_queue_free(local_info_t *local,
+ struct hostap_cmd_queue *entry,
+ int del_req)
+{
+ if (del_req) {
+ entry->del_req = 1;
+ if (!list_empty(&entry->list)) {
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+ }
+ }
+
+ if (atomic_dec_and_test(&entry->usecnt) && entry->del_req)
+ kfree(entry);
+}
+
+
+/**
+ * hostap_cmd_queue_free - Free Prism2 command queue entry
+ * @local: pointer to private Host AP driver data
+ * @entry: Prism2 command queue entry to be freed
+ * @del_req: request the entry to be removed
+ *
+ * Free a Prism2 command queue entry.
+ */
+static inline void hostap_cmd_queue_free(local_info_t *local,
+ struct hostap_cmd_queue *entry,
+ int del_req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ __hostap_cmd_queue_free(local, entry, del_req);
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+}
+
+
+/**
+ * prism2_clear_cmd_queue - Free all pending Prism2 command queue entries
+ * @local: pointer to private Host AP driver data
+ */
+static void prism2_clear_cmd_queue(local_info_t *local)
+{
+ struct list_head *ptr, *n;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ list_for_each_safe(ptr, n, &local->cmd_queue) {
+ entry = list_entry(ptr, struct hostap_cmd_queue, list);
+ atomic_inc(&entry->usecnt);
+ printk(KERN_DEBUG "%s: removed pending cmd_queue entry "
+ "(type=%d, cmd=0x%04x, param0=0x%04x)\n",
+ local->dev->name, entry->type, entry->cmd,
+ entry->param0);
+ __hostap_cmd_queue_free(local, entry, 1);
+ }
+ if (local->cmd_queue_len) {
+ /* This should not happen; print debug message and clear
+ * queue length. */
+ printk(KERN_DEBUG "%s: cmd_queue_len (%d) not zero after "
+ "flush\n", local->dev->name, local->cmd_queue_len);
+ local->cmd_queue_len = 0;
+ }
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+}
+
+
+/**
+ * hfa384x_cmd_issue - Issue a Prism2 command to the hardware
+ * @dev: pointer to net_device
+ * @entry: Prism2 command queue entry to be issued
+ */
+static inline int hfa384x_cmd_issue(struct net_device *dev,
+ struct hostap_cmd_queue *entry)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int tries;
+ u16 reg;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->card_present && !local->func->card_present(local))
+ return -ENODEV;
+
+ if (entry->issued) {
+ printk(KERN_DEBUG "%s: driver bug - re-issuing command @%p\n",
+ dev->name, entry);
+ }
+
+ /* wait until busy bit is clear; this should always be clear since the
+ * commands are serialized */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+#ifndef final_version
+ if (tries != HFA384X_CMD_BUSY_TIMEOUT) {
+ prism2_io_debug_error(dev, 1);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue: cmd reg was busy "
+ "for %d usec\n", dev->name,
+ HFA384X_CMD_BUSY_TIMEOUT - tries);
+ }
+#endif
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ prism2_io_debug_error(dev, 2);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_issue - timeout - "
+ "reg=0x%04x\n", dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ /* write command */
+ spin_lock_irqsave(&local->cmdlock, flags);
+ HFA384X_OUTW(entry->param0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(entry->param1, HFA384X_PARAM1_OFF);
+ HFA384X_OUTW(entry->cmd, HFA384X_CMD_OFF);
+ entry->issued = 1;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ return 0;
+}
+
+
+/**
+ * hfa384x_cmd - Issue a Prism2 command and wait (sleep) for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @param1: value for Param1 register (pointer; %NULL if not used)
+ * @resp0: pointer for Resp0 data or %NULL if Resp0 is not needed
+ *
+ * Issue given command (possibly after waiting in command queue) and sleep
+ * until the command is completed (or timed out or interrupted). This can be
+ * called only from user process context.
+ */
+static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
+ u16 *param1, u16 *resp0)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int err, res, issue, issued = 0;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+ DECLARE_WAITQUEUE(wait, current);
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (in_interrupt()) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd called from interrupt "
+ "context\n", dev->name);
+ return -1;
+ }
+
+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",
+ dev->name);
+ return -1;
+ }
+
+ if (signal_pending(current))
+ return -EINTR;
+
+ entry = (struct hostap_cmd_queue *)
+ kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n",
+ dev->name);
+ return -ENOMEM;
+ }
+ memset(entry, 0, sizeof(*entry));
+ atomic_set(&entry->usecnt, 1);
+ entry->type = CMD_SLEEP;
+ entry->cmd = cmd;
+ entry->param0 = param0;
+ if (param1)
+ entry->param1 = *param1;
+ init_waitqueue_head(&entry->compl);
+
+ /* prepare to wait for command completion event, but do not sleep yet
+ */
+ add_wait_queue(&entry->compl, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ issue = list_empty(&local->cmd_queue);
+ if (issue)
+ entry->issuing = 1;
+ list_add_tail(&entry->list, &local->cmd_queue);
+ local->cmd_queue_len++;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ err = 0;
+ if (!issue)
+ goto wait_completion;
+
+ if (signal_pending(current))
+ err = -EINTR;
+
+ if (!err) {
+ if (hfa384x_cmd_issue(dev, entry))
+ err = -ETIMEDOUT;
+ else
+ issued = 1;
+ }
+
+ wait_completion:
+ if (!err && entry->type != CMD_COMPLETED) {
+ /* sleep until command is completed or timed out */
+ res = schedule_timeout(2 * HZ);
+ } else
+ res = -1;
+
+ if (!err && signal_pending(current))
+ err = -EINTR;
+
+ if (err && issued) {
+ /* the command was issued, so a CmdCompl event should occur
+ * soon; however, there's a pending signal and
+ * schedule_timeout() would be interrupted; wait a short period
+ * of time to avoid removing entry from the list before
+ * CmdCompl event */
+ udelay(300);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&entry->compl, &wait);
+
+ /* If entry->list is still in the list, it must be removed
+ * first and in this case prism2_cmd_ev() does not yet have
+ * local reference to it, and the data can be kfree()'d
+ * here. If the command completion event is still generated,
+ * it will be assigned to next (possibly) pending command, but
+ * the driver will reset the card anyway due to timeout
+ *
+ * If the entry is not in the list prism2_cmd_ev() has a local
+ * reference to it, but keeps cmdlock as long as the data is
+ * needed, so the data can be kfree()'d here. */
+
+ /* FIX: if the entry->list is in the list, it has not been completed
+ * yet, so removing it here is somewhat wrong.. this could cause
+ * references to freed memory and next list_del() causing NULL pointer
+ * dereference.. it would probably be better to leave the entry in the
+ * list and the list should be emptied during hw reset */
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ if (!list_empty(&entry->list)) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: entry still in list? "
+ "(entry=%p, type=%d, res=%d)\n", dev->name, entry,
+ entry->type, res);
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+ }
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (err) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: interrupted; err=%d\n",
+ dev->name, err);
+ res = err;
+ goto done;
+ }
+
+ if (entry->type != CMD_COMPLETED) {
+ u16 reg = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ printk(KERN_DEBUG "%s: hfa384x_cmd: command was not "
+ "completed (res=%d, entry=%p, type=%d, cmd=0x%04x, "
+ "param0=0x%04x, EVSTAT=%04x INTEN=%04x)\n", dev->name,
+ res, entry, entry->type, entry->cmd, entry->param0, reg,
+ HFA384X_INW(HFA384X_INTEN_OFF));
+ if (reg & HFA384X_EV_CMD) {
+ /* Command completion event is pending, but the
+ * interrupt was not delivered - probably an issue
+ * with pcmcia-cs configuration. */
+ printk(KERN_WARNING "%s: interrupt delivery does not "
+ "seem to work\n", dev->name);
+ }
+ prism2_io_debug_error(dev, 3);
+ res = -ETIMEDOUT;
+ goto done;
+ }
+
+ if (resp0 != NULL)
+ *resp0 = entry->resp0;
+#ifndef final_version
+ if (entry->res) {
+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x, "
+ "resp0=0x%04x\n",
+ dev->name, cmd, entry->res, entry->resp0);
+ }
+#endif /* final_version */
+
+ res = entry->res;
+ done:
+ hostap_cmd_queue_free(local, entry, 1);
+ return res;
+}
+
+
+/**
+ * hfa384x_cmd_callback - Issue a Prism2 command; callback when completed
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @callback: command completion callback function (%NULL = no callback)
+ * @context: context data to be given to the callback function
+ *
+ * Issue given command (possibly after waiting in command queue) and use
+ * callback function to indicate command completion. This can be called both
+ * from user and interrupt context. The callback function will be called in
+ * hardware IRQ context. It can be %NULL, when no function is called when
+ * command is completed.
+ */
+static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
+ void (*callback)(struct net_device *dev,
+ long context, u16 resp0,
+ u16 status),
+ long context)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int issue, ret;
+ unsigned long flags;
+ struct hostap_cmd_queue *entry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN + 2) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",
+ dev->name);
+ return -1;
+ }
+
+ entry = (struct hostap_cmd_queue *)
+ kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (entry == NULL) {
+ printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc "
+ "failed\n", dev->name);
+ return -ENOMEM;
+ }
+ memset(entry, 0, sizeof(*entry));
+ atomic_set(&entry->usecnt, 1);
+ entry->type = CMD_CALLBACK;
+ entry->cmd = cmd;
+ entry->param0 = param0;
+ entry->callback = callback;
+ entry->context = context;
+
+ spin_lock_irqsave(&local->cmdlock, flags);
+ issue = list_empty(&local->cmd_queue);
+ if (issue)
+ entry->issuing = 1;
+ list_add_tail(&entry->list, &local->cmd_queue);
+ local->cmd_queue_len++;
+ spin_unlock_irqrestore(&local->cmdlock, flags);
+
+ if (issue && hfa384x_cmd_issue(dev, entry))
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+
+ hostap_cmd_queue_free(local, entry, ret);
+
+ return ret;
+}
+
+
+/**
+ * __hfa384x_cmd_no_wait - Issue a Prism2 command (private)
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ * @io_debug_num: I/O debug error number
+ *
+ * Shared helper function for hfa384x_cmd_wait() and hfa384x_cmd_no_wait().
+ */
+static int __hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, u16 param0,
+ int io_debug_num)
+{
+ int tries;
+ u16 reg;
+
+ /* wait until busy bit is clear; this should always be clear since the
+ * commands are serialized */
+ tries = HFA384X_CMD_BUSY_TIMEOUT;
+ while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
+ tries--;
+ udelay(1);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_CMD_OFF);
+ prism2_io_debug_error(dev, io_debug_num);
+ printk(KERN_DEBUG "%s: __hfa384x_cmd_no_wait(%d) - timeout - "
+ "reg=0x%04x\n", dev->name, io_debug_num, reg);
+ return -ETIMEDOUT;
+ }
+
+ /* write command */
+ HFA384X_OUTW(param0, HFA384X_PARAM0_OFF);
+ HFA384X_OUTW(cmd, HFA384X_CMD_OFF);
+
+ return 0;
+}
+
+
+/**
+ * hfa384x_cmd_wait - Issue a Prism2 command and busy wait for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ */
+static int hfa384x_cmd_wait(struct net_device *dev, u16 cmd, u16 param0)
+{
+ int res, tries;
+ u16 reg;
+
+ res = __hfa384x_cmd_no_wait(dev, cmd, param0, 4);
+ if (res)
+ return res;
+
+ /* wait for command completion */
+ if ((cmd & HFA384X_CMDCODE_MASK) == HFA384X_CMDCODE_DOWNLOAD)
+ tries = HFA384X_DL_COMPL_TIMEOUT;
+ else
+ tries = HFA384X_CMD_COMPL_TIMEOUT;
+
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&
+ tries > 0) {
+ tries--;
+ udelay(10);
+ }
+ if (tries == 0) {
+ reg = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ prism2_io_debug_error(dev, 5);
+ printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout2 - "
+ "reg=0x%04x\n", dev->name, reg);
+ return -ETIMEDOUT;
+ }
+
+ res = (HFA384X_INW(HFA384X_STATUS_OFF) &
+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) |
+ BIT(8))) >> 8;
+#ifndef final_version
+ if (res) {
+ printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x\n",
+ dev->name, cmd, res);
+ }
+#endif
+
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ return res;
+}
+
+
+/**
+ * hfa384x_cmd_no_wait - Issue a Prism2 command; do not wait for completion
+ * @dev: pointer to net_device
+ * @cmd: Prism2 command code (HFA384X_CMD_CODE_*)
+ * @param0: value for Param0 register
+ */
+static inline int hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd,
+ u16 param0)
+{
+ return __hfa384x_cmd_no_wait(dev, cmd, param0, 6);
+}
+
+
+/**
+ * prism2_cmd_ev - Prism2 command completion event handler
+ * @dev: pointer to net_device
+ *
+ * Interrupt handler for command completion events. Called by the main
+ * interrupt handler in hardware IRQ context. Read Resp0 and status registers
+ * from the hardware and ACK the event. Depending on the issued command type
+ * either wake up the sleeping process that is waiting for command completion
+ * or call the callback function. Issue the next command, if one is pending.
+ */
+static void prism2_cmd_ev(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hostap_cmd_queue *entry = NULL;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock(&local->cmdlock);
+ if (!list_empty(&local->cmd_queue)) {
+ entry = list_entry(local->cmd_queue.next,
+ struct hostap_cmd_queue, list);
+ atomic_inc(&entry->usecnt);
+ list_del_init(&entry->list);
+ local->cmd_queue_len--;
+
+ if (!entry->issued) {
+ printk(KERN_DEBUG "%s: Command completion event, but "
+ "cmd not issued\n", dev->name);
+ __hostap_cmd_queue_free(local, entry, 1);
+ entry = NULL;
+ }
+ }
+ spin_unlock(&local->cmdlock);
+
+ if (!entry) {
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: Command completion event, but no "
+ "pending commands\n", dev->name);
+ return;
+ }
+
+ entry->resp0 = HFA384X_INW(HFA384X_RESP0_OFF);
+ entry->res = (HFA384X_INW(HFA384X_STATUS_OFF) &
+ (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) |
+ BIT(9) | BIT(8))) >> 8;
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+
+ /* TODO: rest of the CmdEv handling could be moved to tasklet */
+ if (entry->type == CMD_SLEEP) {
+ entry->type = CMD_COMPLETED;
+ wake_up_interruptible(&entry->compl);
+ } else if (entry->type == CMD_CALLBACK) {
+ if (entry->callback)
+ entry->callback(dev, entry->context, entry->resp0,
+ entry->res);
+ } else {
+ printk(KERN_DEBUG "%s: Invalid command completion type %d\n",
+ dev->name, entry->type);
+ }
+ hostap_cmd_queue_free(local, entry, 1);
+
+ /* issue next command, if pending */
+ entry = NULL;
+ spin_lock(&local->cmdlock);
+ if (!list_empty(&local->cmd_queue)) {
+ entry = list_entry(local->cmd_queue.next,
+ struct hostap_cmd_queue, list);
+ if (entry->issuing) {
+ /* hfa384x_cmd() has already started issuing this
+ * command, so do not start here */
+ entry = NULL;
+ }
+ if (entry)
+ atomic_inc(&entry->usecnt);
+ }
+ spin_unlock(&local->cmdlock);
+
+ if (entry) {
+ /* issue next command; if command issuing fails, remove the
+ * entry from cmd_queue */
+ int res = hfa384x_cmd_issue(dev, entry);
+ spin_lock(&local->cmdlock);
+ __hostap_cmd_queue_free(local, entry, res);
+ spin_unlock(&local->cmdlock);
+ }
+}
+
+
+static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off)
+{
+ int tries = HFA384X_BAP_BUSY_TIMEOUT;
+ int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;
+
+ while (res && tries > 0) {
+ tries--;
+ udelay(1);
+ res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY;
+ }
+ return res;
+}
+
+
+/* Offset must be even */
+static int hfa384x_setup_bap(struct net_device *dev, u16 bap, u16 id,
+ int offset)
+{
+ u16 o_off, s_off;
+ int ret = 0;
+
+ if (offset % 2 || bap > 1)
+ return -EINVAL;
+
+ if (bap == BAP1) {
+ o_off = HFA384X_OFFSET1_OFF;
+ s_off = HFA384X_SELECT1_OFF;
+ } else {
+ o_off = HFA384X_OFFSET0_OFF;
+ s_off = HFA384X_SELECT0_OFF;
+ }
+
+ if (hfa384x_wait_offset(dev, o_off)) {
+ prism2_io_debug_error(dev, 7);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout before\n",
+ dev->name);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ HFA384X_OUTW(id, s_off);
+ HFA384X_OUTW(offset, o_off);
+
+ if (hfa384x_wait_offset(dev, o_off)) {
+ prism2_io_debug_error(dev, 8);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout after\n",
+ dev->name);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+#ifndef final_version
+ if (HFA384X_INW(o_off) & HFA384X_OFFSET_ERR) {
+ prism2_io_debug_error(dev, 9);
+ printk(KERN_DEBUG "%s: hfa384x_setup_bap - offset error "
+ "(%d,0x04%x,%d); reg=0x%04x\n",
+ dev->name, bap, id, offset, HFA384X_INW(o_off));
+ ret = -EINVAL;
+ }
+#endif
+
+ out:
+ return ret;
+}
+
+
+static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len,
+ int exact_len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res, rlen = 0;
+ struct hfa384x_rid_hdr rec;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: cannot get RID %04x (len=%d) - no PRI "
+ "f/w\n", dev->name, rid, len);
+ return -ENOTTY; /* Well.. not really correct, but return
+ * something unique enough.. */
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ res = down_interruptible(&local->rid_bap_sem);
+ if (res)
+ return res;
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS, rid, NULL, NULL);
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_get_rid: CMDCODE_ACCESS failed "
+ "(res=%d, rid=%04x, len=%d)\n",
+ dev->name, res, rid, len);
+ up(&local->rid_bap_sem);
+ return res;
+ }
+
+ spin_lock_bh(&local->baplock);
+
+ res = hfa384x_setup_bap(dev, BAP0, rid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
+
+ if (le16_to_cpu(rec.len) == 0) {
+ /* RID not available */
+ res = -ENODATA;
+ }
+
+ rlen = (le16_to_cpu(rec.len) - 1) * 2;
+ if (!res && exact_len && rlen != len) {
+ printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: "
+ "rid=0x%04x, len=%d (expected %d)\n",
+ dev->name, rid, rlen, len);
+ res = -ENODATA;
+ }
+
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, buf, len);
+
+ spin_unlock_bh(&local->baplock);
+ up(&local->rid_bap_sem);
+
+ if (res) {
+ if (res != -ENODATA)
+ printk(KERN_DEBUG "%s: hfa384x_get_rid (rid=%04x, "
+ "len=%d) - failed - res=%d\n", dev->name, rid,
+ len, res);
+ if (res == -ETIMEDOUT)
+ prism2_hw_reset(dev);
+ return res;
+ }
+
+ return rlen;
+}
+
+
+static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_rid_hdr rec;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ printk(KERN_DEBUG "%s: cannot set RID %04x (len=%d) - no PRI "
+ "f/w\n", dev->name, rid, len);
+ return -ENOTTY; /* Well.. not really correct, but return
+ * something unique enough.. */
+ }
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ local->hw_downloading)
+ return -ENODEV;
+
+ rec.rid = cpu_to_le16(rid);
+ /* RID len in words and +1 for rec.rid */
+ rec.len = cpu_to_le16(len / 2 + len % 2 + 1);
+
+ res = down_interruptible(&local->rid_bap_sem);
+ if (res)
+ return res;
+
+ spin_lock_bh(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, rid, 0);
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, &rec, sizeof(rec));
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, buf, len);
+ spin_unlock_bh(&local->baplock);
+
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_set_rid (rid=%04x, len=%d) - "
+ "failed - res=%d\n", dev->name, rid, len, res);
+ up(&local->rid_bap_sem);
+ return res;
+ }
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL);
+ up(&local->rid_bap_sem);
+ if (res) {
+ printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
+ "failed (res=%d, rid=%04x, len=%d)\n",
+ dev->name, res, rid, len);
+ return res;
+ }
+
+ if (res == -ETIMEDOUT)
+ prism2_hw_reset(dev);
+
+ return res;
+}
+
+
+static void hfa384x_disable_interrupts(struct net_device *dev)
+{
+ /* disable interrupts and clear event status */
+ HFA384X_OUTW(0, HFA384X_INTEN_OFF);
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+}
+
+
+static void hfa384x_enable_interrupts(struct net_device *dev)
+{
+ /* ack pending events and enable interrupts from selected events */
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_no_bap0(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EVENT_MASK & ~HFA384X_BAP0_EVENTS,
+ HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_all(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF);
+}
+
+
+static void hfa384x_events_only_cmd(struct net_device *dev)
+{
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_INTEN_OFF);
+}
+
+
+static u16 hfa384x_allocate_fid(struct net_device *dev, int len)
+{
+ u16 fid;
+ unsigned long delay;
+
+ /* FIX: this could be replace with hfa384x_cmd() if the Alloc event
+ * below would be handled like CmdCompl event (sleep here, wake up from
+ * interrupt handler */
+ if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_ALLOC, len)) {
+ printk(KERN_DEBUG "%s: cannot allocate fid, len=%d\n",
+ dev->name, len);
+ return 0xffff;
+ }
+
+ delay = jiffies + HFA384X_ALLOC_COMPL_TIMEOUT;
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC) &&
+ time_before(jiffies, delay))
+ yield();
+ if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC)) {
+ printk("%s: fid allocate, len=%d - timeout\n", dev->name, len);
+ return 0xffff;
+ }
+
+ fid = HFA384X_INW(HFA384X_ALLOCFID_OFF);
+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF);
+
+ return fid;
+}
+
+
+static int prism2_reset_port(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (!local->dev_enabled)
+ return 0;
+
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0,
+ NULL, NULL);
+ if (res)
+ printk(KERN_DEBUG "%s: reset port failed to disable port\n",
+ dev->name);
+ else {
+ res = hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0,
+ NULL, NULL);
+ if (res)
+ printk(KERN_DEBUG "%s: reset port failed to enable "
+ "port\n", dev->name);
+ }
+
+ /* It looks like at least some STA firmware versions reset
+ * fragmentation threshold back to 2346 after enable command. Restore
+ * the configured value, if it differs from this default. */
+ if (local->fragm_threshold != 2346 &&
+ hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ local->fragm_threshold)) {
+ printk(KERN_DEBUG "%s: failed to restore fragmentation "
+ "threshold (%d) after Port0 enable\n",
+ dev->name, local->fragm_threshold);
+ }
+
+ return res;
+}
+
+
+static int prism2_get_version_info(struct net_device *dev, u16 rid,
+ const char *txt)
+{
+ struct hfa384x_comp_ident comp;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->no_pri) {
+ /* PRI f/w not yet available - cannot read RIDs */
+ return -1;
+ }
+ if (hfa384x_get_rid(dev, rid, &comp, sizeof(comp), 1) < 0) {
+ printk(KERN_DEBUG "Could not get RID for component %s\n", txt);
+ return -1;
+ }
+
+ printk(KERN_INFO "%s: %s: id=0x%02x v%d.%d.%d\n", dev->name, txt,
+ __le16_to_cpu(comp.id), __le16_to_cpu(comp.major),
+ __le16_to_cpu(comp.minor), __le16_to_cpu(comp.variant));
+ return 0;
+}
+
+
+static int prism2_setup_rids(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 tmp;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ hostap_set_word(dev, HFA384X_RID_TICKTIME, 2000);
+
+ if (!local->fw_ap) {
+ tmp = hostap_get_porttype(local);
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp);
+ if (ret) {
+ printk("%s: Port type setting to %d failed\n",
+ dev->name, tmp);
+ goto fail;
+ }
+ }
+
+ /* Setting SSID to empty string seems to kill the card in Host AP mode
+ */
+ if (local->iw_mode != IW_MODE_MASTER || local->essid[0] != '\0') {
+ ret = hostap_set_string(dev, HFA384X_RID_CNFOWNSSID,
+ local->essid);
+ if (ret) {
+ printk("%s: AP own SSID setting failed\n", dev->name);
+ goto fail;
+ }
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXDATALEN,
+ PRISM2_DATA_MAXLEN);
+ if (ret) {
+ printk("%s: MAC data length setting to %d failed\n",
+ dev->name, PRISM2_DATA_MAXLEN);
+ goto fail;
+ }
+
+ if (hfa384x_get_rid(dev, HFA384X_RID_CHANNELLIST, &tmp, 2, 1) < 0) {
+ printk("%s: Channel list read failed\n", dev->name);
+ ret = -EINVAL;
+ goto fail;
+ }
+ local->channel_mask = __le16_to_cpu(tmp);
+
+ if (local->channel < 1 || local->channel > 14 ||
+ !(local->channel_mask & (1 << (local->channel - 1)))) {
+ printk(KERN_WARNING "%s: Channel setting out of range "
+ "(%d)!\n", dev->name, local->channel);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel);
+ if (ret) {
+ printk("%s: Channel setting to %d failed\n",
+ dev->name, local->channel);
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFBEACONINT,
+ local->beacon_int);
+ if (ret) {
+ printk("%s: Beacon interval setting to %d failed\n",
+ dev->name, local->beacon_int);
+ /* this may fail with Symbol/Lucent firmware */
+ if (ret == -ETIMEDOUT)
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD,
+ local->dtim_period);
+ if (ret) {
+ printk("%s: DTIM period setting to %d failed\n",
+ dev->name, local->dtim_period);
+ /* this may fail with Symbol/Lucent firmware */
+ if (ret == -ETIMEDOUT)
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
+ local->is_promisc);
+ if (ret)
+ printk(KERN_INFO "%s: Setting promiscuous mode (%d) failed\n",
+ dev->name, local->is_promisc);
+
+ if (!local->fw_ap) {
+ ret = hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID,
+ local->essid);
+ if (ret) {
+ printk("%s: Desired SSID setting failed\n", dev->name);
+ goto fail;
+ }
+ }
+
+ /* Setup TXRateControl, defaults to allow use of 1, 2, 5.5, and
+ * 11 Mbps in automatic TX rate fallback and 1 and 2 Mbps as basic
+ * rates */
+ if (local->tx_rate_control == 0) {
+ local->tx_rate_control =
+ HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS |
+ HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ }
+ if (local->basic_rates == 0)
+ local->basic_rates = HFA384X_RATES_1MBPS | HFA384X_RATES_2MBPS;
+
+ if (!local->fw_ap) {
+ ret = hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
+ local->tx_rate_control);
+ if (ret) {
+ printk("%s: TXRateControl setting to %d failed\n",
+ dev->name, local->tx_rate_control);
+ goto fail;
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
+ local->tx_rate_control);
+ if (ret) {
+ printk("%s: cnfSupportedRates setting to %d failed\n",
+ dev->name, local->tx_rate_control);
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ local->basic_rates);
+ if (ret) {
+ printk("%s: cnfBasicRates setting to %d failed\n",
+ dev->name, local->basic_rates);
+ }
+
+ ret = hostap_set_word(dev, HFA384X_RID_CREATEIBSS, 1);
+ if (ret) {
+ printk("%s: Create IBSS setting to 1 failed\n",
+ dev->name);
+ }
+ }
+
+ if (local->name_set)
+ (void) hostap_set_string(dev, HFA384X_RID_CNFOWNNAME,
+ local->name);
+
+ if (hostap_set_encryption(local)) {
+ printk(KERN_INFO "%s: could not configure encryption\n",
+ dev->name);
+ }
+
+ (void) hostap_set_antsel(local);
+
+ if (hostap_set_roaming(local)) {
+ printk(KERN_INFO "%s: could not set host roaming\n",
+ dev->name);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,6,3) &&
+ hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, local->enh_sec))
+ printk(KERN_INFO "%s: cnfEnhSecurity setting to 0x%x failed\n",
+ dev->name, local->enh_sec);
+
+ /* 32-bit tallies were added in STA f/w 0.8.0, but they were apparently
+ * not working correctly (last seven counters report bogus values).
+ * This has been fixed in 0.8.2, so enable 32-bit tallies only
+ * beginning with that firmware version. Another bug fix for 32-bit
+ * tallies in 1.4.0; should 16-bit tallies be used for some other
+ * versions, too? */
+ if (local->sta_fw_ver >= PRISM2_FW_VER(0,8,2)) {
+ if (hostap_set_word(dev, HFA384X_RID_CNFTHIRTY2TALLY, 1)) {
+ printk(KERN_INFO "%s: cnfThirty2Tally setting "
+ "failed\n", dev->name);
+ local->tallies32 = 0;
+ } else
+ local->tallies32 = 1;
+ } else
+ local->tallies32 = 0;
+
+ hostap_set_auth_algs(local);
+
+ if (hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ local->fragm_threshold)) {
+ printk(KERN_INFO "%s: setting FragmentationThreshold to %d "
+ "failed\n", dev->name, local->fragm_threshold);
+ }
+
+ if (hostap_set_word(dev, HFA384X_RID_RTSTHRESHOLD,
+ local->rts_threshold)) {
+ printk(KERN_INFO "%s: setting RTSThreshold to %d failed\n",
+ dev->name, local->rts_threshold);
+ }
+
+ if (local->manual_retry_count >= 0 &&
+ hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
+ local->manual_retry_count)) {
+ printk(KERN_INFO "%s: setting cnfAltRetryCount to %d failed\n",
+ dev->name, local->manual_retry_count);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1) &&
+ hfa384x_get_rid(dev, HFA384X_RID_CNFDBMADJUST, &tmp, 2, 1) == 2) {
+ local->rssi_to_dBm = le16_to_cpu(tmp);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->wpa &&
+ hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1)) {
+ printk(KERN_INFO "%s: setting ssnHandlingMode to 1 failed\n",
+ dev->name);
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->generic_elem &&
+ hfa384x_set_rid(dev, HFA384X_RID_GENERICELEMENT,
+ local->generic_elem, local->generic_elem_len)) {
+ printk(KERN_INFO "%s: setting genericElement failed\n",
+ dev->name);
+ }
+
+ fail:
+ return ret;
+}
+
+
+static int prism2_hw_init(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret, first = 1;
+ unsigned long start, delay;
+
+ PDEBUG(DEBUG_FLOW, "prism2_hw_init()\n");
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits);
+
+ init:
+ /* initialize HFA 384x */
+ ret = hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_INIT, 0);
+ if (ret) {
+ printk(KERN_INFO "%s: first command failed - assuming card "
+ "does not have primary firmware\n", dev_info);
+ }
+
+ if (first && (HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) {
+ /* EvStat has Cmd bit set in some cases, so retry once if no
+ * wait was needed */
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: init command completed too quickly - "
+ "retrying\n", dev->name);
+ first = 0;
+ goto init;
+ }
+
+ start = jiffies;
+ delay = jiffies + HFA384X_INIT_TIMEOUT;
+ while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&
+ time_before(jiffies, delay))
+ yield();
+ if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) {
+ printk(KERN_DEBUG "%s: assuming no Primary image in "
+ "flash - card initialization not completed\n",
+ dev_info);
+ local->no_pri = 1;
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ if (local->sram_type == -1)
+ local->sram_type = prism2_get_ram_size(local);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+ return 1;
+ }
+ local->no_pri = 0;
+ printk(KERN_DEBUG "prism2_hw_init: initialized in %lu ms\n",
+ (jiffies - start) * 1000 / HZ);
+ HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
+ return 0;
+}
+
+
+static int prism2_hw_init2(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ kfree(local->pda);
+ if (local->no_pri)
+ local->pda = NULL;
+ else
+ local->pda = prism2_read_pda(dev);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ hfa384x_disable_interrupts(dev);
+
+#ifndef final_version
+ HFA384X_OUTW(HFA384X_MAGIC, HFA384X_SWSUPPORT0_OFF);
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) {
+ printk("SWSUPPORT0 write/read failed: %04X != %04X\n",
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF), HFA384X_MAGIC);
+ goto failed;
+ }
+#endif
+
+ if (initial || local->pri_only) {
+ hfa384x_events_only_cmd(dev);
+ /* get card version information */
+ if (prism2_get_version_info(dev, HFA384X_RID_NICID, "NIC") ||
+ prism2_get_version_info(dev, HFA384X_RID_PRIID, "PRI")) {
+ hfa384x_disable_interrupts(dev);
+ goto failed;
+ }
+
+ if (prism2_get_version_info(dev, HFA384X_RID_STAID, "STA")) {
+ printk(KERN_DEBUG "%s: Failed to read STA f/w version "
+ "- only Primary f/w present\n", dev->name);
+ local->pri_only = 1;
+ return 0;
+ }
+ local->pri_only = 0;
+ hfa384x_disable_interrupts(dev);
+ }
+
+ /* FIX: could convert allocate_fid to use sleeping CmdCompl wait and
+ * enable interrupts before this. This would also require some sort of
+ * sleeping AllocEv waiting */
+
+ /* allocate TX FIDs */
+ local->txfid_len = PRISM2_TXFID_LEN;
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++) {
+ local->txfid[i] = hfa384x_allocate_fid(dev, local->txfid_len);
+ if (local->txfid[i] == 0xffff && local->txfid_len > 1600) {
+ local->txfid[i] = hfa384x_allocate_fid(dev, 1600);
+ if (local->txfid[i] != 0xffff) {
+ printk(KERN_DEBUG "%s: Using shorter TX FID "
+ "(1600 bytes)\n", dev->name);
+ local->txfid_len = 1600;
+ }
+ }
+ if (local->txfid[i] == 0xffff)
+ goto failed;
+ local->intransmitfid[i] = PRISM2_TXFID_EMPTY;
+ }
+
+ hfa384x_events_only_cmd(dev);
+
+ if (initial) {
+ struct list_head *ptr;
+ prism2_check_sta_fw_version(local);
+
+ if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR,
+ &dev->dev_addr, 6, 1) < 0) {
+ printk("%s: could not get own MAC address\n",
+ dev->name);
+ }
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ memcpy(iface->dev->dev_addr, dev->dev_addr, ETH_ALEN);
+ }
+ } else if (local->fw_ap)
+ prism2_check_sta_fw_version(local);
+
+ prism2_setup_rids(dev);
+
+ /* MAC is now configured, but port 0 is not yet enabled */
+ return 0;
+
+ failed:
+ if (!local->no_pri)
+ printk(KERN_WARNING "%s: Initialization failed\n", dev_info);
+ return 1;
+}
+
+
+static int prism2_hw_enable(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int was_resetting;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ was_resetting = local->hw_resetting;
+
+ if (hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, NULL)) {
+ printk("%s: MAC port 0 enabling failed\n", dev->name);
+ return 1;
+ }
+
+ local->hw_ready = 1;
+ local->hw_reset_tries = 0;
+ local->hw_resetting = 0;
+ hfa384x_enable_interrupts(dev);
+
+ /* at least D-Link DWL-650 seems to require additional port reset
+ * before it starts acting as an AP, so reset port automatically
+ * here just in case */
+ if (initial && prism2_reset_port(dev)) {
+ printk("%s: MAC port 0 reseting failed\n", dev->name);
+ return 1;
+ }
+
+ if (was_resetting && netif_queue_stopped(dev)) {
+ /* If hw_reset() was called during pending transmit, netif
+ * queue was stopped. Wake it up now since the wlan card has
+ * been resetted. */
+ netif_wake_queue(dev);
+ }
+
+ return 0;
+}
+
+
+static int prism2_hw_config(struct net_device *dev, int initial)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->hw_downloading)
+ return 1;
+
+ if (prism2_hw_init(dev, initial)) {
+ return local->no_pri ? 0 : 1;
+ }
+
+ if (prism2_hw_init2(dev, initial))
+ return 1;
+
+ /* Enable firmware if secondary image is loaded and at least one of the
+ * netdevices is up. */
+ if (!local->pri_only &&
+ (initial == 0 || (initial == 2 && local->num_dev_open > 0))) {
+ if (!local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_ENABLE);
+ local->dev_enabled = 1;
+ return prism2_hw_enable(dev, initial);
+ }
+
+ return 0;
+}
+
+
+static void prism2_hw_shutdown(struct net_device *dev, int no_disable)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Allow only command completion events during disable */
+ hfa384x_events_only_cmd(dev);
+
+ local->hw_ready = 0;
+ if (local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_DISABLE);
+ local->dev_enabled = 0;
+
+ if (local->func->card_present && !local->func->card_present(local)) {
+ printk(KERN_DEBUG "%s: card already removed or not configured "
+ "during shutdown\n", dev->name);
+ return;
+ }
+
+ if ((no_disable & HOSTAP_HW_NO_DISABLE) == 0 &&
+ hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, NULL))
+ printk(KERN_WARNING "%s: Shutdown failed\n", dev_info);
+
+ hfa384x_disable_interrupts(dev);
+
+ if (no_disable & HOSTAP_HW_ENABLE_CMDCOMPL)
+ hfa384x_events_only_cmd(dev);
+ else
+ prism2_clear_cmd_queue(local);
+}
+
+
+static void prism2_hw_reset(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+#if 0
+ static long last_reset = 0;
+
+ /* do not reset card more than once per second to avoid ending up in a
+ * busy loop reseting the card */
+ if (time_before_eq(jiffies, last_reset + HZ))
+ return;
+ last_reset = jiffies;
+#endif
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (in_interrupt()) {
+ printk(KERN_DEBUG "%s: driver bug - prism2_hw_reset() called "
+ "in interrupt context\n", dev->name);
+ return;
+ }
+
+ if (local->hw_downloading)
+ return;
+
+ if (local->hw_resetting) {
+ printk(KERN_WARNING "%s: %s: already resetting card - "
+ "ignoring reset request\n", dev_info, dev->name);
+ return;
+ }
+
+ local->hw_reset_tries++;
+ if (local->hw_reset_tries > 10) {
+ printk(KERN_WARNING "%s: too many reset tries, skipping\n",
+ dev->name);
+ return;
+ }
+
+ printk(KERN_WARNING "%s: %s: resetting card\n", dev_info, dev->name);
+ hfa384x_disable_interrupts(dev);
+ local->hw_resetting = 1;
+ if (local->func->cor_sreset) {
+ /* Host system seems to hang in some cases with high traffic
+ * load or shared interrupts during COR sreset. Disable shared
+ * interrupts during reset to avoid these crashes. COS sreset
+ * takes quite a long time, so it is unfortunate that this
+ * seems to be needed. Anyway, I do not know of any better way
+ * of avoiding the crash. */
+ disable_irq(dev->irq);
+ local->func->cor_sreset(local);
+ enable_irq(dev->irq);
+ }
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, 0);
+ local->hw_resetting = 0;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ if (local->dl_pri) {
+ printk(KERN_DEBUG "%s: persistent download of primary "
+ "firmware\n", dev->name);
+ if (prism2_download_genesis(local, local->dl_pri) < 0)
+ printk(KERN_WARNING "%s: download (PRI) failed\n",
+ dev->name);
+ }
+
+ if (local->dl_sec) {
+ printk(KERN_DEBUG "%s: persistent download of secondary "
+ "firmware\n", dev->name);
+ if (prism2_download_volatile(local, local->dl_sec) < 0)
+ printk(KERN_WARNING "%s: download (SEC) failed\n",
+ dev->name);
+ }
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ /* TODO: restore beacon TIM bits for STAs that have buffered frames */
+}
+
+
+static void prism2_schedule_reset(local_info_t *local)
+{
+ schedule_work(&local->reset_queue);
+}
+
+
+/* Called only as scheduled task after noticing card timeout in interrupt
+ * context */
+static void handle_reset_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name);
+ prism2_hw_reset(local->dev);
+
+ if (netif_queue_stopped(local->dev)) {
+ int i;
+
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++)
+ if (local->intransmitfid[i] == PRISM2_TXFID_EMPTY) {
+ PDEBUG(DEBUG_EXTRA, "prism2_tx_timeout: "
+ "wake up queue\n");
+ netif_wake_queue(local->dev);
+ break;
+ }
+ }
+}
+
+
+static int prism2_get_txfid_idx(local_info_t *local)
+{
+ int idx, end;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->txfidlock, flags);
+ end = idx = local->next_txfid;
+ do {
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) {
+ local->intransmitfid[idx] = PRISM2_TXFID_RESERVED;
+ spin_unlock_irqrestore(&local->txfidlock, flags);
+ return idx;
+ }
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != end);
+ spin_unlock_irqrestore(&local->txfidlock, flags);
+
+ PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: "
+ "packet dropped\n");
+ local->stats.tx_dropped++;
+
+ return -1;
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_transmit_cb(struct net_device *dev, long context,
+ u16 resp0, u16 res)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int idx = (int) context;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (res) {
+ printk(KERN_DEBUG "%s: prism2_transmit_cb - res=0x%02x\n",
+ dev->name, res);
+ return;
+ }
+
+ if (idx < 0 || idx >= PRISM2_TXFID_COUNT) {
+ printk(KERN_DEBUG "%s: prism2_transmit_cb called with invalid "
+ "idx=%d\n", dev->name, idx);
+ return;
+ }
+
+ if (!test_and_clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: driver bug: prism2_transmit_cb called "
+ "with no pending transmit\n", dev->name);
+ }
+
+ if (netif_queue_stopped(dev)) {
+ /* ready for next TX, so wake up queue that was stopped in
+ * prism2_transmit() */
+ netif_wake_queue(dev);
+ }
+
+ spin_lock(&local->txfidlock);
+
+ /* With reclaim, Resp0 contains new txfid for transmit; the old txfid
+ * will be automatically allocated for the next TX frame */
+ local->intransmitfid[idx] = resp0;
+
+ PDEBUG(DEBUG_FID, "%s: prism2_transmit_cb: txfid[%d]=0x%04x, "
+ "resp0=0x%04x, transmit_txfid=0x%04x\n",
+ dev->name, idx, local->txfid[idx],
+ resp0, local->intransmitfid[local->next_txfid]);
+
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ local->next_txfid = idx;
+
+ /* check if all TX buffers are occupied */
+ do {
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) {
+ spin_unlock(&local->txfidlock);
+ return;
+ }
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != local->next_txfid);
+ spin_unlock(&local->txfidlock);
+
+ /* no empty TX buffers, stop queue */
+ netif_stop_queue(dev);
+}
+
+
+/* Called only from software IRQ if PCI bus master is not used (with bus master
+ * this can be called both from software and hardware IRQ) */
+static int prism2_transmit(struct net_device *dev, int idx)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* The driver tries to stop netif queue so that there would not be
+ * more than one attempt to transmit frames going on; check that this
+ * is really the case */
+
+ if (test_and_set_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: driver bug - prism2_transmit() called "
+ "when previous TX was pending\n", dev->name);
+ return -1;
+ }
+
+ /* stop the queue for the time that transmit is pending */
+ netif_stop_queue(dev);
+
+ /* transmit packet */
+ res = hfa384x_cmd_callback(
+ dev,
+ HFA384X_CMDCODE_TRANSMIT | HFA384X_CMD_TX_RECLAIM,
+ local->txfid[idx],
+ prism2_transmit_cb, (long) idx);
+
+ if (res) {
+ struct net_device_stats *stats;
+ printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT "
+ "failed (res=%d)\n", dev->name, res);
+ stats = hostap_get_stats(dev);
+ stats->tx_dropped++;
+ netif_wake_queue(dev);
+ return -1;
+ }
+ dev->trans_start = jiffies;
+
+ /* Since we did not wait for command completion, the card continues
+ * to process on the background and we will finish handling when
+ * command completion event is handled (prism2_cmd_ev() function) */
+
+ return 0;
+}
+
+
+/* Send IEEE 802.11 frame (convert the header into Prism2 TX descriptor and
+ * send the payload with this descriptor) */
+/* Called only from software IRQ */
+static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_tx_frame txdesc;
+ struct hostap_skb_tx_data *meta;
+ int hdr_len, data_len, idx, res, ret = -1;
+ u16 tx_control, fc;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ meta = (struct hostap_skb_tx_data *) skb->cb;
+
+ prism2_callback(local, PRISM2_CALLBACK_TX_START);
+
+ if ((local->func->card_present && !local->func->card_present(local)) ||
+ !local->hw_ready || local->hw_downloading || local->pri_only) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: prism2_tx_80211: hw not ready -"
+ " skipping\n", dev->name);
+ }
+ goto fail;
+ }
+
+ memset(&txdesc, 0, sizeof(txdesc));
+
+ /* skb->data starts with txdesc->frame_control */
+ hdr_len = 24;
+ memcpy(&txdesc.frame_control, skb->data, hdr_len);
+ fc = le16_to_cpu(txdesc.frame_control);
+ if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
+ (fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS) &&
+ skb->len >= 30) {
+ /* Addr4 */
+ memcpy(txdesc.addr4, skb->data + hdr_len, ETH_ALEN);
+ hdr_len += ETH_ALEN;
+ }
+
+ tx_control = local->tx_control;
+ if (meta->tx_cb_idx) {
+ tx_control |= HFA384X_TX_CTRL_TX_OK;
+ txdesc.sw_support = cpu_to_le16(meta->tx_cb_idx);
+ }
+ txdesc.tx_control = cpu_to_le16(tx_control);
+ txdesc.tx_rate = meta->rate;
+
+ data_len = skb->len - hdr_len;
+ txdesc.data_len = cpu_to_le16(data_len);
+ txdesc.len = cpu_to_be16(data_len);
+
+ idx = prism2_get_txfid_idx(local);
+ if (idx < 0)
+ goto fail;
+
+ if (local->frame_dump & PRISM2_DUMP_TX_HDR)
+ hostap_dump_tx_header(dev->name, &txdesc);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0);
+
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc));
+ if (!res)
+ res = hfa384x_to_bap(dev, BAP0, skb->data + hdr_len,
+ skb->len - hdr_len);
+ spin_unlock(&local->baplock);
+
+ if (!res)
+ res = prism2_transmit(dev, idx);
+ if (res) {
+ printk(KERN_DEBUG "%s: prism2_tx_80211 - to BAP0 failed\n",
+ dev->name);
+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY;
+ schedule_work(&local->reset_queue);
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ prism2_callback(local, PRISM2_CALLBACK_TX_END);
+ return ret;
+}
+
+
+/* Some SMP systems have reported number of odd errors with hostap_pci. fid
+ * register has changed values between consecutive reads for an unknown reason.
+ * This should really not happen, so more debugging is needed. This test
+ * version is a big slower, but it will detect most of such register changes
+ * and will try to get the correct fid eventually. */
+#define EXTRA_FID_READ_TESTS
+
+static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg)
+{
+#ifdef EXTRA_FID_READ_TESTS
+ u16 val, val2, val3;
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ val = HFA384X_INW(reg);
+ val2 = HFA384X_INW(reg);
+ val3 = HFA384X_INW(reg);
+
+ if (val == val2 && val == val3)
+ return val;
+
+ printk(KERN_DEBUG "%s: detected fid change (try=%d, reg=%04x):"
+ " %04x %04x %04x\n",
+ dev->name, i, reg, val, val2, val3);
+ if ((val == val2 || val == val3) && val != 0)
+ return val;
+ if (val2 == val3 && val2 != 0)
+ return val2;
+ }
+ printk(KERN_WARNING "%s: Uhhuh.. could not read good fid from reg "
+ "%04x (%04x %04x %04x)\n", dev->name, reg, val, val2, val3);
+ return val;
+#else /* EXTRA_FID_READ_TESTS */
+ return HFA384X_INW(reg);
+#endif /* EXTRA_FID_READ_TESTS */
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_rx(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ int res, rx_pending = 0;
+ u16 len, hdr_len, rxfid, status, macport;
+ struct net_device_stats *stats;
+ struct hfa384x_rx_frame rxdesc;
+ struct sk_buff *skb = NULL;
+
+ prism2_callback(local, PRISM2_CALLBACK_RX_START);
+ stats = hostap_get_stats(dev);
+
+ rxfid = prism2_read_fid_reg(dev, HFA384X_RXFID_OFF);
+#ifndef final_version
+ if (rxfid == 0) {
+ rxfid = HFA384X_INW(HFA384X_RXFID_OFF);
+ printk(KERN_DEBUG "prism2_rx: rxfid=0 (next 0x%04x)\n",
+ rxfid);
+ if (rxfid == 0) {
+ schedule_work(&local->reset_queue);
+ goto rx_dropped;
+ }
+ /* try to continue with the new rxfid value */
+ }
+#endif
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, rxfid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &rxdesc, sizeof(rxdesc));
+
+ if (res) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: copy from BAP0 failed %d\n", dev->name,
+ res);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ goto rx_dropped;
+ }
+
+ len = le16_to_cpu(rxdesc.data_len);
+ hdr_len = sizeof(rxdesc);
+ status = le16_to_cpu(rxdesc.status);
+ macport = (status >> 8) & 0x07;
+
+ /* Drop frames with too large reported payload length. Monitor mode
+ * seems to sometimes pass frames (e.g., ctrl::ack) with signed and
+ * negative value, so allow also values 65522 .. 65534 (-14 .. -2) for
+ * macport 7 */
+ if (len > PRISM2_DATA_MAXLEN + 8 /* WEP */) {
+ if (macport == 7 && local->iw_mode == IW_MODE_MONITOR) {
+ if (len >= (u16) -14) {
+ hdr_len -= 65535 - len;
+ hdr_len--;
+ }
+ len = 0;
+ } else {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Received frame with invalid "
+ "length 0x%04x\n", dev->name, len);
+ hostap_dump_rx_header(dev->name, &rxdesc);
+ goto rx_dropped;
+ }
+ }
+
+ skb = dev_alloc_skb(len + hdr_len);
+ if (!skb) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: RX failed to allocate skb\n",
+ dev->name);
+ goto rx_dropped;
+ }
+ skb->dev = dev;
+ memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len);
+
+ if (len > 0)
+ res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len);
+ spin_unlock(&local->baplock);
+ if (res) {
+ printk(KERN_DEBUG "%s: RX failed to read "
+ "frame data\n", dev->name);
+ goto rx_dropped;
+ }
+
+ skb_queue_tail(&local->rx_list, skb);
+ tasklet_schedule(&local->rx_tasklet);
+
+ rx_exit:
+ prism2_callback(local, PRISM2_CALLBACK_RX_END);
+ if (!rx_pending) {
+ HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF);
+ }
+
+ return;
+
+ rx_dropped:
+ stats->rx_dropped++;
+ if (skb)
+ dev_kfree_skb(skb);
+ goto rx_exit;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb)
+{
+ struct hfa384x_rx_frame *rxdesc;
+ struct net_device *dev = skb->dev;
+ struct hostap_80211_rx_status stats;
+ int hdrlen, rx_hdrlen;
+
+ rx_hdrlen = sizeof(*rxdesc);
+ if (skb->len < sizeof(*rxdesc)) {
+ /* Allow monitor mode to receive shorter frames */
+ if (local->iw_mode == IW_MODE_MONITOR &&
+ skb->len >= sizeof(*rxdesc) - 30) {
+ rx_hdrlen = skb->len;
+ } else {
+ dev_kfree_skb(skb);
+ return;
+ }
+ }
+
+ rxdesc = (struct hfa384x_rx_frame *) skb->data;
+
+ if (local->frame_dump & PRISM2_DUMP_RX_HDR &&
+ skb->len >= sizeof(*rxdesc))
+ hostap_dump_rx_header(dev->name, rxdesc);
+
+ if (le16_to_cpu(rxdesc->status) & HFA384X_RX_STATUS_FCSERR &&
+ (!local->monitor_allow_fcserr ||
+ local->iw_mode != IW_MODE_MONITOR))
+ goto drop;
+
+ if (skb->len > PRISM2_DATA_MAXLEN) {
+ printk(KERN_DEBUG "%s: RX: len(%d) > MAX(%d)\n",
+ dev->name, skb->len, PRISM2_DATA_MAXLEN);
+ goto drop;
+ }
+
+ stats.mac_time = le32_to_cpu(rxdesc->time);
+ stats.signal = rxdesc->signal - local->rssi_to_dBm;
+ stats.noise = rxdesc->silence - local->rssi_to_dBm;
+ stats.rate = rxdesc->rate;
+
+ /* Convert Prism2 RX structure into IEEE 802.11 header */
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(rxdesc->frame_control));
+ if (hdrlen > rx_hdrlen)
+ hdrlen = rx_hdrlen;
+
+ memmove(skb_pull(skb, rx_hdrlen - hdrlen),
+ &rxdesc->frame_control, hdrlen);
+
+ hostap_80211_rx(dev, skb, &stats);
+ return;
+
+ drop:
+ dev_kfree_skb(skb);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_rx_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->rx_list)) != NULL)
+ hostap_rx_skb(local, skb);
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_alloc_ev(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int idx;
+ u16 fid;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ fid = prism2_read_fid_reg(dev, HFA384X_ALLOCFID_OFF);
+
+ PDEBUG(DEBUG_FID, "FID: interrupt: ALLOC - fid=0x%04x\n", fid);
+
+ spin_lock(&local->txfidlock);
+ idx = local->next_alloc;
+
+ do {
+ if (local->txfid[idx] == fid) {
+ PDEBUG(DEBUG_FID, "FID: found matching txfid[%d]\n",
+ idx);
+
+#ifndef final_version
+ if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY)
+ printk("Already released txfid found at idx "
+ "%d\n", idx);
+ if (local->intransmitfid[idx] == PRISM2_TXFID_RESERVED)
+ printk("Already reserved txfid found at idx "
+ "%d\n", idx);
+#endif
+ local->intransmitfid[idx] = PRISM2_TXFID_EMPTY;
+ idx++;
+ local->next_alloc = idx >= PRISM2_TXFID_COUNT ? 0 :
+ idx;
+
+ if (!test_bit(HOSTAP_BITS_TRANSMIT, &local->bits) &&
+ netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+
+ spin_unlock(&local->txfidlock);
+ return;
+ }
+
+ idx++;
+ if (idx >= PRISM2_TXFID_COUNT)
+ idx = 0;
+ } while (idx != local->next_alloc);
+
+ printk(KERN_WARNING "%s: could not find matching txfid (0x%04x, new "
+ "read 0x%04x) for alloc event\n", dev->name, fid,
+ HFA384X_INW(HFA384X_ALLOCFID_OFF));
+ printk(KERN_DEBUG "TXFIDs:");
+ for (idx = 0; idx < PRISM2_TXFID_COUNT; idx++)
+ printk(" %04x[%04x]", local->txfid[idx],
+ local->intransmitfid[idx]);
+ printk("\n");
+ spin_unlock(&local->txfidlock);
+
+ /* FIX: should probably schedule reset; reference to one txfid was lost
+ * completely.. Bad things will happen if we run out of txfids
+ * Actually, this will cause netdev watchdog to notice TX timeout and
+ * then card reset after all txfids have been leaked. */
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_tx_callback(local_info_t *local,
+ struct hfa384x_tx_frame *txdesc, int ok,
+ char *payload)
+{
+ u16 sw_support, hdrlen, len;
+ struct sk_buff *skb;
+ struct hostap_tx_callback_info *cb;
+
+ /* Make sure that frame was from us. */
+ if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) {
+ printk(KERN_DEBUG "%s: TX callback - foreign frame\n",
+ local->dev->name);
+ return;
+ }
+
+ sw_support = le16_to_cpu(txdesc->sw_support);
+
+ spin_lock(&local->lock);
+ cb = local->tx_callback;
+ while (cb != NULL && cb->idx != sw_support)
+ cb = cb->next;
+ spin_unlock(&local->lock);
+
+ if (cb == NULL) {
+ printk(KERN_DEBUG "%s: could not find TX callback (idx %d)\n",
+ local->dev->name, sw_support);
+ return;
+ }
+
+ hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(txdesc->frame_control));
+ len = le16_to_cpu(txdesc->data_len);
+ skb = dev_alloc_skb(hdrlen + len);
+ if (skb == NULL) {
+ printk(KERN_DEBUG "%s: hostap_tx_callback failed to allocate "
+ "skb\n", local->dev->name);
+ return;
+ }
+
+ memcpy(skb_put(skb, hdrlen), (void *) &txdesc->frame_control, hdrlen);
+ if (payload)
+ memcpy(skb_put(skb, len), payload, len);
+
+ skb->dev = local->dev;
+ skb->mac.raw = skb->data;
+
+ cb->func(skb, ok, cb->data);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int hostap_tx_compl_read(local_info_t *local, int error,
+ struct hfa384x_tx_frame *txdesc,
+ char **payload)
+{
+ u16 fid, len;
+ int res, ret = 0;
+ struct net_device *dev = local->dev;
+
+ fid = prism2_read_fid_reg(dev, HFA384X_TXCOMPLFID_OFF);
+
+ PDEBUG(DEBUG_FID, "interrupt: TX (err=%d) - fid=0x%04x\n", fid, error);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, fid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, txdesc, sizeof(*txdesc));
+ if (res) {
+ PDEBUG(DEBUG_EXTRA, "%s: TX (err=%d) - fid=0x%04x - could not "
+ "read txdesc\n", dev->name, error, fid);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ ret = -1;
+ goto fail;
+ }
+ if (txdesc->sw_support) {
+ len = le16_to_cpu(txdesc->data_len);
+ if (len < PRISM2_DATA_MAXLEN) {
+ *payload = (char *) kmalloc(len, GFP_ATOMIC);
+ if (*payload == NULL ||
+ hfa384x_from_bap(dev, BAP0, *payload, len)) {
+ PDEBUG(DEBUG_EXTRA, "%s: could not read TX "
+ "frame payload\n", dev->name);
+ kfree(*payload);
+ *payload = NULL;
+ ret = -1;
+ goto fail;
+ }
+ }
+ }
+
+ fail:
+ spin_unlock(&local->baplock);
+
+ return ret;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_tx_ev(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ char *payload = NULL;
+ struct hfa384x_tx_frame txdesc;
+
+ if (hostap_tx_compl_read(local, 0, &txdesc, &payload))
+ goto fail;
+
+ if (local->frame_dump & PRISM2_DUMP_TX_HDR) {
+ PDEBUG(DEBUG_EXTRA, "%s: TX - status=0x%04x "
+ "retry_count=%d tx_rate=%d seq_ctrl=%d "
+ "duration_id=%d\n",
+ dev->name, le16_to_cpu(txdesc.status),
+ txdesc.retry_count, txdesc.tx_rate,
+ le16_to_cpu(txdesc.seq_ctrl),
+ le16_to_cpu(txdesc.duration_id));
+ }
+
+ if (txdesc.sw_support)
+ hostap_tx_callback(local, &txdesc, 1, payload);
+ kfree(payload);
+
+ fail:
+ HFA384X_OUTW(HFA384X_EV_TX, HFA384X_EVACK_OFF);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_sta_tx_exc_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->sta_tx_exc_list)) != NULL) {
+ struct hfa384x_tx_frame *txdesc =
+ (struct hfa384x_tx_frame *) skb->data;
+
+ if (skb->len >= sizeof(*txdesc)) {
+ /* Convert Prism2 RX structure into IEEE 802.11 header
+ */
+ u16 fc = le16_to_cpu(txdesc->frame_control);
+ int hdrlen = hostap_80211_get_hdrlen(fc);
+ memmove(skb_pull(skb, sizeof(*txdesc) - hdrlen),
+ &txdesc->frame_control, hdrlen);
+
+ hostap_handle_sta_tx_exc(local, skb);
+ }
+ dev_kfree_skb(skb);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_txexc(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 status, fc;
+ int show_dump, res;
+ char *payload = NULL;
+ struct hfa384x_tx_frame txdesc;
+
+ show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR;
+ local->stats.tx_errors++;
+
+ res = hostap_tx_compl_read(local, 1, &txdesc, &payload);
+ HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF);
+ if (res)
+ return;
+
+ status = le16_to_cpu(txdesc.status);
+
+ /* We produce a TXDROP event only for retry or lifetime
+ * exceeded, because that's the only status that really mean
+ * that this particular node went away.
+ * Other errors means that *we* screwed up. - Jean II */
+ if (status & (HFA384X_TX_STATUS_RETRYERR | HFA384X_TX_STATUS_AGEDERR))
+ {
+ union iwreq_data wrqu;
+
+ /* Copy 802.11 dest address. */
+ memcpy(wrqu.addr.sa_data, txdesc.addr1, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
+ } else
+ show_dump = 1;
+
+ if (local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT ||
+ local->wds_type & HOSTAP_WDS_AP_CLIENT) {
+ struct sk_buff *skb;
+ skb = dev_alloc_skb(sizeof(txdesc));
+ if (skb) {
+ memcpy(skb_put(skb, sizeof(txdesc)), &txdesc,
+ sizeof(txdesc));
+ skb_queue_tail(&local->sta_tx_exc_list, skb);
+ tasklet_schedule(&local->sta_tx_exc_tasklet);
+ }
+ }
+
+ if (txdesc.sw_support)
+ hostap_tx_callback(local, &txdesc, 0, payload);
+ kfree(payload);
+
+ if (!show_dump)
+ return;
+
+ PDEBUG(DEBUG_EXTRA, "%s: TXEXC - status=0x%04x (%s%s%s%s)"
+ " tx_control=%04x\n",
+ dev->name, status,
+ status & HFA384X_TX_STATUS_RETRYERR ? "[RetryErr]" : "",
+ status & HFA384X_TX_STATUS_AGEDERR ? "[AgedErr]" : "",
+ status & HFA384X_TX_STATUS_DISCON ? "[Discon]" : "",
+ status & HFA384X_TX_STATUS_FORMERR ? "[FormErr]" : "",
+ le16_to_cpu(txdesc.tx_control));
+
+ fc = le16_to_cpu(txdesc.frame_control);
+ PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x "
+ "(%s%s%s::%d%s%s)\n",
+ txdesc.retry_count, txdesc.tx_rate, fc,
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_MGMT ? "Mgmt" : "",
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL ? "Ctrl" : "",
+ WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA ? "Data" : "",
+ WLAN_FC_GET_STYPE(fc) >> 4,
+ fc & IEEE80211_FCTL_TODS ? " ToDS" : "",
+ fc & IEEE80211_FCTL_FROMDS ? " FromDS" : "");
+ PDEBUG(DEBUG_EXTRA, " A1=" MACSTR " A2=" MACSTR " A3="
+ MACSTR " A4=" MACSTR "\n",
+ MAC2STR(txdesc.addr1), MAC2STR(txdesc.addr2),
+ MAC2STR(txdesc.addr3), MAC2STR(txdesc.addr4));
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_info_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&local->info_list)) != NULL) {
+ hostap_info_process(local, skb);
+ dev_kfree_skb(skb);
+ }
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 fid;
+ int res, left;
+ struct hfa384x_info_frame info;
+ struct sk_buff *skb;
+
+ fid = HFA384X_INW(HFA384X_INFOFID_OFF);
+
+ spin_lock(&local->baplock);
+ res = hfa384x_setup_bap(dev, BAP0, fid, 0);
+ if (!res)
+ res = hfa384x_from_bap(dev, BAP0, &info, sizeof(info));
+ if (res) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "Could not get info frame (fid=0x%04x)\n",
+ fid);
+ if (res == -ETIMEDOUT) {
+ schedule_work(&local->reset_queue);
+ }
+ goto out;
+ }
+
+ le16_to_cpus(&info.len);
+ le16_to_cpus(&info.type);
+ left = (info.len - 1) * 2;
+
+ if (info.len & 0x8000 || info.len == 0 || left > 2060) {
+ /* data register seems to give 0x8000 in some error cases even
+ * though busy bit is not set in offset register;
+ * in addition, length must be at least 1 due to type field */
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Received info frame with invalid "
+ "length 0x%04x (type 0x%04x)\n", dev->name, info.len,
+ info.type);
+ goto out;
+ }
+
+ skb = dev_alloc_skb(sizeof(info) + left);
+ if (skb == NULL) {
+ spin_unlock(&local->baplock);
+ printk(KERN_DEBUG "%s: Could not allocate skb for info "
+ "frame\n", dev->name);
+ goto out;
+ }
+
+ memcpy(skb_put(skb, sizeof(info)), &info, sizeof(info));
+ if (left > 0 && hfa384x_from_bap(dev, BAP0, skb_put(skb, left), left))
+ {
+ spin_unlock(&local->baplock);
+ printk(KERN_WARNING "%s: Info frame read failed (fid=0x%04x, "
+ "len=0x%04x, type=0x%04x\n",
+ dev->name, fid, info.len, info.type);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+ spin_unlock(&local->baplock);
+
+ skb_queue_tail(&local->info_list, skb);
+ tasklet_schedule(&local->info_tasklet);
+
+ out:
+ HFA384X_OUTW(HFA384X_EV_INFO, HFA384X_EVACK_OFF);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void hostap_bap_tasklet(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct net_device *dev = local->dev;
+ u16 ev;
+ int frames = 30;
+
+ if (local->func->card_present && !local->func->card_present(local))
+ return;
+
+ set_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits);
+
+ /* Process all pending BAP events without generating new interrupts
+ * for them */
+ while (frames-- > 0) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev == 0xffff || !(ev & HFA384X_BAP0_EVENTS))
+ break;
+ if (ev & HFA384X_EV_RX)
+ prism2_rx(local);
+ if (ev & HFA384X_EV_INFO)
+ prism2_info(local);
+ if (ev & HFA384X_EV_TX)
+ prism2_tx_ev(local);
+ if (ev & HFA384X_EV_TXEXC)
+ prism2_txexc(local);
+ }
+
+ set_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits);
+ clear_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits);
+
+ /* Enable interrupts for new BAP events */
+ hfa384x_events_all(dev);
+ clear_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits);
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_infdrop(struct net_device *dev)
+{
+ static unsigned long last_inquire = 0;
+
+ PDEBUG(DEBUG_EXTRA, "%s: INFDROP event\n", dev->name);
+
+ /* some firmware versions seem to get stuck with
+ * full CommTallies in high traffic load cases; every
+ * packet will then cause INFDROP event and CommTallies
+ * info frame will not be sent automatically. Try to
+ * get out of this state by inquiring CommTallies. */
+ if (!last_inquire || time_after(jiffies, last_inquire + HZ)) {
+ hfa384x_cmd_callback(dev, HFA384X_CMDCODE_INQUIRE,
+ HFA384X_INFO_COMMTALLIES, NULL, 0);
+ last_inquire = jiffies;
+ }
+}
+
+
+/* Called only from hardware IRQ */
+static void prism2_ev_tick(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 evstat, inten;
+ static int prev_stuck = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (time_after(jiffies, local->last_tick_timer + 5 * HZ) &&
+ local->last_tick_timer) {
+ evstat = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ inten = HFA384X_INW(HFA384X_INTEN_OFF);
+ if (!prev_stuck) {
+ printk(KERN_INFO "%s: SW TICK stuck? "
+ "bits=0x%lx EvStat=%04x IntEn=%04x\n",
+ dev->name, local->bits, evstat, inten);
+ }
+ local->sw_tick_stuck++;
+ if ((evstat & HFA384X_BAP0_EVENTS) &&
+ (inten & HFA384X_BAP0_EVENTS)) {
+ printk(KERN_INFO "%s: trying to recover from IRQ "
+ "hang\n", dev->name);
+ hfa384x_events_no_bap0(dev);
+ }
+ prev_stuck = 1;
+ } else
+ prev_stuck = 0;
+}
+
+
+/* Called only from hardware IRQ */
+static inline void prism2_check_magic(local_info_t *local)
+{
+ /* at least PCI Prism2.5 with bus mastering seems to sometimes
+ * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the
+ * register once or twice seems to get the correct value.. PCI cards
+ * cannot anyway be removed during normal operation, so there is not
+ * really any need for this verification with them. */
+
+#ifndef PRISM2_PCI
+#ifndef final_version
+ static unsigned long last_magic_err = 0;
+ struct net_device *dev = local->dev;
+
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) {
+ if (!local->hw_ready)
+ return;
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ if (time_after(jiffies, last_magic_err + 10 * HZ)) {
+ printk("%s: Interrupt, but SWSUPPORT0 does not match: "
+ "%04X != %04X - card removed?\n", dev->name,
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF),
+ HFA384X_MAGIC);
+ last_magic_err = jiffies;
+ } else if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: interrupt - SWSUPPORT0=%04x "
+ "MAGIC=%04x\n", dev->name,
+ HFA384X_INW(HFA384X_SWSUPPORT0_OFF),
+ HFA384X_MAGIC);
+ }
+ if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != 0xffff)
+ schedule_work(&local->reset_queue);
+ return;
+ }
+#endif /* final_version */
+#endif /* !PRISM2_PCI */
+}
+
+
+/* Called only from hardware IRQ */
+static irqreturn_t prism2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int events = 0;
+ u16 ev;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
+
+ if (local->func->card_present && !local->func->card_present(local)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: Interrupt, but dev not OK\n",
+ dev->name);
+ }
+ return IRQ_HANDLED;
+ }
+
+ prism2_check_magic(local);
+
+ for (;;) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev == 0xffff) {
+ if (local->shutdown)
+ return IRQ_HANDLED;
+ HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF);
+ printk(KERN_DEBUG "%s: prism2_interrupt: ev=0xffff\n",
+ dev->name);
+ return IRQ_HANDLED;
+ }
+
+ ev &= HFA384X_INW(HFA384X_INTEN_OFF);
+ if (ev == 0)
+ break;
+
+ if (ev & HFA384X_EV_CMD) {
+ prism2_cmd_ev(dev);
+ }
+
+ /* Above events are needed even before hw is ready, but other
+ * events should be skipped during initialization. This may
+ * change for AllocEv if allocate_fid is implemented without
+ * busy waiting. */
+ if (!local->hw_ready || local->hw_resetting ||
+ !local->dev_enabled) {
+ ev = HFA384X_INW(HFA384X_EVSTAT_OFF);
+ if (ev & HFA384X_EV_CMD)
+ goto next_event;
+ if ((ev & HFA384X_EVENT_MASK) == 0)
+ return IRQ_HANDLED;
+ if (local->dev_enabled && (ev & ~HFA384X_EV_TICK) &&
+ net_ratelimit()) {
+ printk(KERN_DEBUG "%s: prism2_interrupt: hw "
+ "not ready; skipping events 0x%04x "
+ "(IntEn=0x%04x)%s%s%s\n",
+ dev->name, ev,
+ HFA384X_INW(HFA384X_INTEN_OFF),
+ !local->hw_ready ? " (!hw_ready)" : "",
+ local->hw_resetting ?
+ " (hw_resetting)" : "",
+ !local->dev_enabled ?
+ " (!dev_enabled)" : "");
+ }
+ HFA384X_OUTW(ev, HFA384X_EVACK_OFF);
+ return IRQ_HANDLED;
+ }
+
+ if (ev & HFA384X_EV_TICK) {
+ prism2_ev_tick(dev);
+ HFA384X_OUTW(HFA384X_EV_TICK, HFA384X_EVACK_OFF);
+ }
+
+ if (ev & HFA384X_EV_ALLOC) {
+ prism2_alloc_ev(dev);
+ HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF);
+ }
+
+ /* Reading data from the card is quite time consuming, so do it
+ * in tasklets. TX, TXEXC, RX, and INFO events will be ACKed
+ * and unmasked after needed data has been read completely. */
+ if (ev & HFA384X_BAP0_EVENTS) {
+ hfa384x_events_no_bap0(dev);
+ tasklet_schedule(&local->bap_tasklet);
+ }
+
+#ifndef final_version
+ if (ev & HFA384X_EV_WTERR) {
+ PDEBUG(DEBUG_EXTRA, "%s: WTERR event\n", dev->name);
+ HFA384X_OUTW(HFA384X_EV_WTERR, HFA384X_EVACK_OFF);
+ }
+#endif /* final_version */
+
+ if (ev & HFA384X_EV_INFDROP) {
+ prism2_infdrop(dev);
+ HFA384X_OUTW(HFA384X_EV_INFDROP, HFA384X_EVACK_OFF);
+ }
+
+ next_event:
+ events++;
+ if (events >= PRISM2_MAX_INTERRUPT_EVENTS) {
+ PDEBUG(DEBUG_EXTRA, "prism2_interrupt: >%d events "
+ "(EvStat=0x%04x)\n",
+ PRISM2_MAX_INTERRUPT_EVENTS,
+ HFA384X_INW(HFA384X_EVSTAT_OFF));
+ break;
+ }
+ }
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 1);
+ return IRQ_RETVAL(events);
+}
+
+
+static void prism2_check_sta_fw_version(local_info_t *local)
+{
+ struct hfa384x_comp_ident comp;
+ int id, variant, major, minor;
+
+ if (hfa384x_get_rid(local->dev, HFA384X_RID_STAID,
+ &comp, sizeof(comp), 1) < 0)
+ return;
+
+ local->fw_ap = 0;
+ id = le16_to_cpu(comp.id);
+ if (id != HFA384X_COMP_ID_STA) {
+ if (id == HFA384X_COMP_ID_FW_AP)
+ local->fw_ap = 1;
+ return;
+ }
+
+ major = __le16_to_cpu(comp.major);
+ minor = __le16_to_cpu(comp.minor);
+ variant = __le16_to_cpu(comp.variant);
+ local->sta_fw_ver = PRISM2_FW_VER(major, minor, variant);
+
+ /* Station firmware versions before 1.4.x seem to have a bug in
+ * firmware-based WEP encryption when using Host AP mode, so use
+ * host_encrypt as a default for them. Firmware version 1.4.9 is the
+ * first one that has been seen to produce correct encryption, but the
+ * bug might be fixed before that (although, at least 1.4.2 is broken).
+ */
+ local->fw_encrypt_ok = local->sta_fw_ver >= PRISM2_FW_VER(1,4,9);
+
+ if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
+ !local->fw_encrypt_ok) {
+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
+ "a workaround for firmware bug in Host AP mode WEP\n",
+ local->dev->name);
+ local->host_encrypt = 1;
+ }
+
+ /* IEEE 802.11 standard compliant WDS frames (4 addresses) were broken
+ * in station firmware versions before 1.5.x. With these versions, the
+ * driver uses a workaround with bogus frame format (4th address after
+ * the payload). This is not compatible with other AP devices. Since
+ * the firmware bug is fixed in the latest station firmware versions,
+ * automatically enable standard compliant mode for cards using station
+ * firmware version 1.5.0 or newer. */
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,5,0))
+ local->wds_type |= HOSTAP_WDS_STANDARD_FRAME;
+ else {
+ printk(KERN_DEBUG "%s: defaulting to bogus WDS frame as a "
+ "workaround for firmware bug in Host AP mode WDS\n",
+ local->dev->name);
+ }
+
+ hostap_check_sta_fw_version(local->ap, local->sta_fw_ver);
+}
+
+
+static void prism2_crypt_deinit_entries(local_info_t *local, int force)
+{
+ struct list_head *ptr, *n;
+ struct ieee80211_crypt_data *entry;
+
+ for (ptr = local->crypt_deinit_list.next, n = ptr->next;
+ ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct ieee80211_crypt_data, list);
+
+ if (atomic_read(&entry->refcnt) != 0 && !force)
+ continue;
+
+ list_del(ptr);
+
+ if (entry->ops)
+ entry->ops->deinit(entry->priv);
+ kfree(entry);
+ }
+}
+
+
+static void prism2_crypt_deinit_handler(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_crypt_deinit_entries(local, 0);
+ if (!list_empty(&local->crypt_deinit_list)) {
+ printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
+ "deletion list\n", local->dev->name);
+ local->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&local->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+}
+
+
+static void hostap_passive_scan(unsigned long data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct net_device *dev = local->dev;
+ u16 channel;
+
+ if (local->passive_scan_interval <= 0)
+ return;
+
+ if (local->passive_scan_state == PASSIVE_SCAN_LISTEN) {
+ int max_tries = 16;
+
+ /* Even though host system does not really know when the WLAN
+ * MAC is sending frames, try to avoid changing channels for
+ * passive scanning when a host-generated frame is being
+ * transmitted */
+ if (test_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) {
+ printk(KERN_DEBUG "%s: passive scan detected pending "
+ "TX - delaying\n", dev->name);
+ local->passive_scan_timer.expires = jiffies + HZ / 10;
+ add_timer(&local->passive_scan_timer);
+ return;
+ }
+
+ do {
+ local->passive_scan_channel++;
+ if (local->passive_scan_channel > 14)
+ local->passive_scan_channel = 1;
+ max_tries--;
+ } while (!(local->channel_mask &
+ (1 << (local->passive_scan_channel - 1))) &&
+ max_tries > 0);
+
+ if (max_tries == 0) {
+ printk(KERN_INFO "%s: no allowed passive scan channels"
+ " found\n", dev->name);
+ return;
+ }
+
+ printk(KERN_DEBUG "%s: passive scan channel %d\n",
+ dev->name, local->passive_scan_channel);
+ channel = local->passive_scan_channel;
+ local->passive_scan_state = PASSIVE_SCAN_WAIT;
+ local->passive_scan_timer.expires = jiffies + HZ / 10;
+ } else {
+ channel = local->channel;
+ local->passive_scan_state = PASSIVE_SCAN_LISTEN;
+ local->passive_scan_timer.expires = jiffies +
+ local->passive_scan_interval * HZ;
+ }
+
+ if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CHANGE_CHANNEL << 8),
+ channel, NULL, 0))
+ printk(KERN_ERR "%s: passive scan channel set %d "
+ "failed\n", dev->name, channel);
+
+ add_timer(&local->passive_scan_timer);
+}
+
+
+/* Called only as a scheduled task when communications quality values should
+ * be updated. */
+static void handle_comms_qual_update(void *data)
+{
+ local_info_t *local = data;
+ prism2_update_comms_qual(local->dev);
+}
+
+
+/* Software watchdog - called as a timer. Hardware interrupt (Tick event) is
+ * used to monitor that local->last_tick_timer is being updated. If not,
+ * interrupt busy-loop is assumed and driver tries to recover by masking out
+ * some events. */
+static void hostap_tick_timer(unsigned long data)
+{
+ static unsigned long last_inquire = 0;
+ local_info_t *local = (local_info_t *) data;
+ local->last_tick_timer = jiffies;
+
+ /* Inquire CommTallies every 10 seconds to keep the statistics updated
+ * more often during low load and when using 32-bit tallies. */
+ if ((!last_inquire || time_after(jiffies, last_inquire + 10 * HZ)) &&
+ !local->hw_downloading && local->hw_ready &&
+ !local->hw_resetting && local->dev_enabled) {
+ hfa384x_cmd_callback(local->dev, HFA384X_CMDCODE_INQUIRE,
+ HFA384X_INFO_COMMTALLIES, NULL, 0);
+ last_inquire = jiffies;
+ }
+
+ if ((local->last_comms_qual_update == 0 ||
+ time_after(jiffies, local->last_comms_qual_update + 10 * HZ)) &&
+ (local->iw_mode == IW_MODE_INFRA ||
+ local->iw_mode == IW_MODE_ADHOC)) {
+ schedule_work(&local->comms_qual_update);
+ }
+
+ local->tick_timer.expires = jiffies + 2 * HZ;
+ add_timer(&local->tick_timer);
+}
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int prism2_registers_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+#define SHOW_REG(n) \
+p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF))
+
+ SHOW_REG(CMD);
+ SHOW_REG(PARAM0);
+ SHOW_REG(PARAM1);
+ SHOW_REG(PARAM2);
+ SHOW_REG(STATUS);
+ SHOW_REG(RESP0);
+ SHOW_REG(RESP1);
+ SHOW_REG(RESP2);
+ SHOW_REG(INFOFID);
+ SHOW_REG(CONTROL);
+ SHOW_REG(SELECT0);
+ SHOW_REG(SELECT1);
+ SHOW_REG(OFFSET0);
+ SHOW_REG(OFFSET1);
+ SHOW_REG(RXFID);
+ SHOW_REG(ALLOCFID);
+ SHOW_REG(TXCOMPLFID);
+ SHOW_REG(SWSUPPORT0);
+ SHOW_REG(SWSUPPORT1);
+ SHOW_REG(SWSUPPORT2);
+ SHOW_REG(EVSTAT);
+ SHOW_REG(INTEN);
+ SHOW_REG(EVACK);
+ /* Do not read data registers, because they change the state of the
+ * MAC (offset += 2) */
+ /* SHOW_REG(DATA0); */
+ /* SHOW_REG(DATA1); */
+ SHOW_REG(AUXPAGE);
+ SHOW_REG(AUXOFFSET);
+ /* SHOW_REG(AUXDATA); */
+#ifdef PRISM2_PCI
+ SHOW_REG(PCICOR);
+ SHOW_REG(PCIHCR);
+ SHOW_REG(PCI_M0_ADDRH);
+ SHOW_REG(PCI_M0_ADDRL);
+ SHOW_REG(PCI_M0_LEN);
+ SHOW_REG(PCI_M0_CTL);
+ SHOW_REG(PCI_STATUS);
+ SHOW_REG(PCI_M1_ADDRH);
+ SHOW_REG(PCI_M1_ADDRL);
+ SHOW_REG(PCI_M1_LEN);
+ SHOW_REG(PCI_M1_CTL);
+#endif /* PRISM2_PCI */
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+struct set_tim_data {
+ struct list_head list;
+ int aid;
+ int set;
+};
+
+static int prism2_set_tim(struct net_device *dev, int aid, int set)
+{
+ struct list_head *ptr;
+ struct set_tim_data *new_entry;
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ new_entry = (struct set_tim_data *)
+ kmalloc(sizeof(*new_entry), GFP_ATOMIC);
+ if (new_entry == NULL) {
+ printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n",
+ local->dev->name);
+ return -ENOMEM;
+ }
+ memset(new_entry, 0, sizeof(*new_entry));
+ new_entry->aid = aid;
+ new_entry->set = set;
+
+ spin_lock_bh(&local->set_tim_lock);
+ list_for_each(ptr, &local->set_tim_list) {
+ struct set_tim_data *entry =
+ list_entry(ptr, struct set_tim_data, list);
+ if (entry->aid == aid) {
+ PDEBUG(DEBUG_PS2, "%s: prism2_set_tim: aid=%d "
+ "set=%d ==> %d\n",
+ local->dev->name, aid, entry->set, set);
+ entry->set = set;
+ kfree(new_entry);
+ new_entry = NULL;
+ break;
+ }
+ }
+ if (new_entry)
+ list_add_tail(&new_entry->list, &local->set_tim_list);
+ spin_unlock_bh(&local->set_tim_lock);
+
+ schedule_work(&local->set_tim_queue);
+
+ return 0;
+}
+
+
+static void handle_set_tim_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+ struct set_tim_data *entry;
+ u16 val;
+
+ for (;;) {
+ entry = NULL;
+ spin_lock_bh(&local->set_tim_lock);
+ if (!list_empty(&local->set_tim_list)) {
+ entry = list_entry(local->set_tim_list.next,
+ struct set_tim_data, list);
+ list_del(&entry->list);
+ }
+ spin_unlock_bh(&local->set_tim_lock);
+ if (!entry)
+ break;
+
+ PDEBUG(DEBUG_PS2, "%s: handle_set_tim_queue: aid=%d set=%d\n",
+ local->dev->name, entry->aid, entry->set);
+
+ val = entry->aid;
+ if (entry->set)
+ val |= 0x8000;
+ if (hostap_set_word(local->dev, HFA384X_RID_CNFTIMCTRL, val)) {
+ printk(KERN_DEBUG "%s: set_tim failed (aid=%d "
+ "set=%d)\n",
+ local->dev->name, entry->aid, entry->set);
+ }
+
+ kfree(entry);
+ }
+}
+
+
+static void prism2_clear_set_tim_queue(local_info_t *local)
+{
+ struct list_head *ptr, *n;
+
+ list_for_each_safe(ptr, n, &local->set_tim_list) {
+ struct set_tim_data *entry;
+ entry = list_entry(ptr, struct set_tim_data, list);
+ list_del(&entry->list);
+ kfree(entry);
+ }
+}
+
+
+static struct net_device *
+prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
+ struct device *sdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ struct local_info *local;
+ int len, i, ret;
+
+ if (funcs == NULL)
+ return NULL;
+
+ len = strlen(dev_template);
+ if (len >= IFNAMSIZ || strstr(dev_template, "%d") == NULL) {
+ printk(KERN_WARNING "hostap: Invalid dev_template='%s'\n",
+ dev_template);
+ return NULL;
+ }
+
+ len = sizeof(struct hostap_interface) +
+ 3 + sizeof(struct local_info) +
+ 3 + sizeof(struct ap_data);
+
+ dev = alloc_etherdev(len);
+ if (dev == NULL)
+ return NULL;
+
+ iface = netdev_priv(dev);
+ local = (struct local_info *) ((((long) (iface + 1)) + 3) & ~3);
+ local->ap = (struct ap_data *) ((((long) (local + 1)) + 3) & ~3);
+ local->dev = iface->dev = dev;
+ iface->local = local;
+ iface->type = HOSTAP_INTERFACE_MASTER;
+ INIT_LIST_HEAD(&local->hostap_interfaces);
+
+ local->hw_module = THIS_MODULE;
+
+#ifdef PRISM2_IO_DEBUG
+ local->io_debug_enabled = 1;
+#endif /* PRISM2_IO_DEBUG */
+
+ local->func = funcs;
+ local->func->cmd = hfa384x_cmd;
+ local->func->read_regs = hfa384x_read_regs;
+ local->func->get_rid = hfa384x_get_rid;
+ local->func->set_rid = hfa384x_set_rid;
+ local->func->hw_enable = prism2_hw_enable;
+ local->func->hw_config = prism2_hw_config;
+ local->func->hw_reset = prism2_hw_reset;
+ local->func->hw_shutdown = prism2_hw_shutdown;
+ local->func->reset_port = prism2_reset_port;
+ local->func->schedule_reset = prism2_schedule_reset;
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ local->func->read_aux = prism2_download_aux_dump;
+ local->func->download = prism2_download;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+ local->func->tx = prism2_tx_80211;
+ local->func->set_tim = prism2_set_tim;
+ local->func->need_tx_headroom = 0; /* no need to add txdesc in
+ * skb->data (FIX: maybe for DMA bus
+ * mastering? */
+
+ local->mtu = mtu;
+
+ rwlock_init(&local->iface_lock);
+ spin_lock_init(&local->txfidlock);
+ spin_lock_init(&local->cmdlock);
+ spin_lock_init(&local->baplock);
+ spin_lock_init(&local->lock);
+ init_MUTEX(&local->rid_bap_sem);
+
+ if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
+ card_idx = 0;
+ local->card_idx = card_idx;
+
+ len = strlen(essid);
+ memcpy(local->essid, essid,
+ len > MAX_SSID_LEN ? MAX_SSID_LEN : len);
+ local->essid[MAX_SSID_LEN] = '\0';
+ i = GET_INT_PARM(iw_mode, card_idx);
+ if ((i >= IW_MODE_ADHOC && i <= IW_MODE_REPEAT) ||
+ i == IW_MODE_MONITOR) {
+ local->iw_mode = i;
+ } else {
+ printk(KERN_WARNING "prism2: Unknown iw_mode %d; using "
+ "IW_MODE_MASTER\n", i);
+ local->iw_mode = IW_MODE_MASTER;
+ }
+ local->channel = GET_INT_PARM(channel, card_idx);
+ local->beacon_int = GET_INT_PARM(beacon_int, card_idx);
+ local->dtim_period = GET_INT_PARM(dtim_period, card_idx);
+ local->wds_max_connections = 16;
+ local->tx_control = HFA384X_TX_CTRL_FLAGS;
+ local->manual_retry_count = -1;
+ local->rts_threshold = 2347;
+ local->fragm_threshold = 2346;
+ local->rssi_to_dBm = 100; /* default; to be overriden by
+ * cnfDbmAdjust, if available */
+ local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY;
+ local->sram_type = -1;
+ local->scan_channel_mask = 0xffff;
+
+ /* Initialize task queue structures */
+ INIT_WORK(&local->reset_queue, handle_reset_queue, local);
+ INIT_WORK(&local->set_multicast_list_queue,
+ hostap_set_multicast_list_queue, local->dev);
+
+ INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local);
+ INIT_LIST_HEAD(&local->set_tim_list);
+ spin_lock_init(&local->set_tim_lock);
+
+ INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local);
+
+ /* Initialize tasklets for handling hardware IRQ related operations
+ * outside hw IRQ handler */
+#define HOSTAP_TASKLET_INIT(q, f, d) \
+do { memset((q), 0, sizeof(*(q))); (q)->func = (f); (q)->data = (d); } \
+while (0)
+ HOSTAP_TASKLET_INIT(&local->bap_tasklet, hostap_bap_tasklet,
+ (unsigned long) local);
+
+ HOSTAP_TASKLET_INIT(&local->info_tasklet, hostap_info_tasklet,
+ (unsigned long) local);
+ hostap_info_init(local);
+
+ HOSTAP_TASKLET_INIT(&local->rx_tasklet,
+ hostap_rx_tasklet, (unsigned long) local);
+ skb_queue_head_init(&local->rx_list);
+
+ HOSTAP_TASKLET_INIT(&local->sta_tx_exc_tasklet,
+ hostap_sta_tx_exc_tasklet, (unsigned long) local);
+ skb_queue_head_init(&local->sta_tx_exc_list);
+
+ INIT_LIST_HEAD(&local->cmd_queue);
+ init_waitqueue_head(&local->hostscan_wq);
+ INIT_LIST_HEAD(&local->crypt_deinit_list);
+ init_timer(&local->crypt_deinit_timer);
+ local->crypt_deinit_timer.data = (unsigned long) local;
+ local->crypt_deinit_timer.function = prism2_crypt_deinit_handler;
+
+ init_timer(&local->passive_scan_timer);
+ local->passive_scan_timer.data = (unsigned long) local;
+ local->passive_scan_timer.function = hostap_passive_scan;
+
+ init_timer(&local->tick_timer);
+ local->tick_timer.data = (unsigned long) local;
+ local->tick_timer.function = hostap_tick_timer;
+ local->tick_timer.expires = jiffies + 2 * HZ;
+ add_timer(&local->tick_timer);
+
+ INIT_LIST_HEAD(&local->bss_list);
+
+ hostap_setup_dev(dev, local, 1);
+ local->saved_eth_header_parse = dev->hard_header_parse;
+
+ dev->hard_start_xmit = hostap_master_start_xmit;
+ dev->type = ARPHRD_IEEE80211;
+ dev->hard_header_parse = hostap_80211_header_parse;
+
+ rtnl_lock();
+ ret = dev_alloc_name(dev, "wifi%d");
+ SET_NETDEV_DEV(dev, sdev);
+ if (ret >= 0)
+ ret = register_netdevice(dev);
+ rtnl_unlock();
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: register netdevice failed!\n",
+ dev_info);
+ goto fail;
+ }
+ printk(KERN_INFO "%s: Registered netdevice %s\n", dev_info, dev->name);
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("registers", 0, local->proc,
+ prism2_registers_proc_read, local);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+ hostap_init_data(local);
+ return dev;
+
+ fail:
+ free_netdev(dev);
+ return NULL;
+}
+
+
+static int hostap_hw_ready(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ struct local_info *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->ddev = hostap_add_interface(local, HOSTAP_INTERFACE_MAIN, 0,
+ "", dev_template);
+
+ if (local->ddev) {
+ if (local->iw_mode == IW_MODE_INFRA ||
+ local->iw_mode == IW_MODE_ADHOC) {
+ netif_carrier_off(local->dev);
+ netif_carrier_off(local->ddev);
+ }
+ hostap_init_proc(local);
+ hostap_init_ap_proc(local);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static void prism2_free_local_data(struct net_device *dev)
+{
+ struct hostap_tx_callback_info *tx_cb, *tx_cb_prev;
+ int i;
+ struct hostap_interface *iface;
+ struct local_info *local;
+ struct list_head *ptr, *n;
+
+ if (dev == NULL)
+ return;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Unregister all netdevs before freeing local data. */
+ list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type == HOSTAP_INTERFACE_MASTER) {
+ /* special handling for this interface below */
+ continue;
+ }
+ hostap_remove_interface(iface->dev, 0, 1);
+ }
+
+ unregister_netdev(local->dev);
+
+ flush_scheduled_work();
+
+ if (timer_pending(&local->crypt_deinit_timer))
+ del_timer(&local->crypt_deinit_timer);
+ prism2_crypt_deinit_entries(local, 1);
+
+ if (timer_pending(&local->passive_scan_timer))
+ del_timer(&local->passive_scan_timer);
+
+ if (timer_pending(&local->tick_timer))
+ del_timer(&local->tick_timer);
+
+ prism2_clear_cmd_queue(local);
+
+ skb_queue_purge(&local->info_list);
+ skb_queue_purge(&local->rx_list);
+ skb_queue_purge(&local->sta_tx_exc_list);
+
+ if (local->dev_enabled)
+ prism2_callback(local, PRISM2_CALLBACK_DISABLE);
+
+ for (i = 0; i < WEP_KEYS; i++) {
+ struct ieee80211_crypt_data *crypt = local->crypt[i];
+ if (crypt) {
+ if (crypt->ops)
+ crypt->ops->deinit(crypt->priv);
+ kfree(crypt);
+ local->crypt[i] = NULL;
+ }
+ }
+
+ if (local->ap != NULL)
+ hostap_free_data(local->ap);
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ if (local->proc != NULL)
+ remove_proc_entry("registers", local->proc);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ hostap_remove_proc(local);
+
+ tx_cb = local->tx_callback;
+ while (tx_cb != NULL) {
+ tx_cb_prev = tx_cb;
+ tx_cb = tx_cb->next;
+ kfree(tx_cb_prev);
+ }
+
+ hostap_set_hostapd(local, 0, 0);
+ hostap_set_hostapd_sta(local, 0, 0);
+
+ for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
+ if (local->frag_cache[i].skb != NULL)
+ dev_kfree_skb(local->frag_cache[i].skb);
+ }
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ prism2_download_free_data(local->dl_pri);
+ prism2_download_free_data(local->dl_sec);
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ prism2_clear_set_tim_queue(local);
+
+ list_for_each_safe(ptr, n, &local->bss_list) {
+ struct hostap_bss_info *bss =
+ list_entry(ptr, struct hostap_bss_info, list);
+ kfree(bss);
+ }
+
+ kfree(local->pda);
+ kfree(local->last_scan_results);
+ kfree(local->generic_elem);
+
+ free_netdev(local->dev);
+}
+
+
+#ifndef PRISM2_PLX
+static void prism2_suspend(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ struct local_info *local;
+ union iwreq_data wrqu;
+
+ iface = dev->priv;
+ local = iface->local;
+
+ /* Send disconnect event, e.g., to trigger reassociation after resume
+ * if wpa_supplicant is used. */
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+
+ /* Disable hardware and firmware */
+ prism2_hw_shutdown(dev, 0);
+}
+#endif /* PRISM2_PLX */
+
+
+/* These might at some point be compiled separately and used as separate
+ * kernel modules or linked into one */
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+#include "hostap_download.c"
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+#ifdef PRISM2_CALLBACK
+/* External hostap_callback.c file can be used to, e.g., blink activity led.
+ * This can use platform specific code and must define prism2_callback()
+ * function (if PRISM2_CALLBACK is not defined, these function calls are not
+ * used. */
+#include "hostap_callback.c"
+#endif /* PRISM2_CALLBACK */
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
new file mode 100644
index 000000000000..5aa998fdf1c4
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -0,0 +1,499 @@
+/* Host AP driver Info Frame processing (part of hostap.o module) */
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ struct hfa384x_comm_tallies *tallies;
+
+ if (left < sizeof(struct hfa384x_comm_tallies)) {
+ printk(KERN_DEBUG "%s: too short (len=%d) commtallies "
+ "info frame\n", local->dev->name, left);
+ return;
+ }
+
+ tallies = (struct hfa384x_comm_tallies *) buf;
+#define ADD_COMM_TALLIES(name) \
+local->comm_tallies.name += le16_to_cpu(tallies->name)
+ ADD_COMM_TALLIES(tx_unicast_frames);
+ ADD_COMM_TALLIES(tx_multicast_frames);
+ ADD_COMM_TALLIES(tx_fragments);
+ ADD_COMM_TALLIES(tx_unicast_octets);
+ ADD_COMM_TALLIES(tx_multicast_octets);
+ ADD_COMM_TALLIES(tx_deferred_transmissions);
+ ADD_COMM_TALLIES(tx_single_retry_frames);
+ ADD_COMM_TALLIES(tx_multiple_retry_frames);
+ ADD_COMM_TALLIES(tx_retry_limit_exceeded);
+ ADD_COMM_TALLIES(tx_discards);
+ ADD_COMM_TALLIES(rx_unicast_frames);
+ ADD_COMM_TALLIES(rx_multicast_frames);
+ ADD_COMM_TALLIES(rx_fragments);
+ ADD_COMM_TALLIES(rx_unicast_octets);
+ ADD_COMM_TALLIES(rx_multicast_octets);
+ ADD_COMM_TALLIES(rx_fcs_errors);
+ ADD_COMM_TALLIES(rx_discards_no_buffer);
+ ADD_COMM_TALLIES(tx_discards_wrong_sa);
+ ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
+ ADD_COMM_TALLIES(rx_message_in_msg_fragments);
+ ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
+#undef ADD_COMM_TALLIES
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies32(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ struct hfa384x_comm_tallies32 *tallies;
+
+ if (left < sizeof(struct hfa384x_comm_tallies32)) {
+ printk(KERN_DEBUG "%s: too short (len=%d) commtallies32 "
+ "info frame\n", local->dev->name, left);
+ return;
+ }
+
+ tallies = (struct hfa384x_comm_tallies32 *) buf;
+#define ADD_COMM_TALLIES(name) \
+local->comm_tallies.name += le32_to_cpu(tallies->name)
+ ADD_COMM_TALLIES(tx_unicast_frames);
+ ADD_COMM_TALLIES(tx_multicast_frames);
+ ADD_COMM_TALLIES(tx_fragments);
+ ADD_COMM_TALLIES(tx_unicast_octets);
+ ADD_COMM_TALLIES(tx_multicast_octets);
+ ADD_COMM_TALLIES(tx_deferred_transmissions);
+ ADD_COMM_TALLIES(tx_single_retry_frames);
+ ADD_COMM_TALLIES(tx_multiple_retry_frames);
+ ADD_COMM_TALLIES(tx_retry_limit_exceeded);
+ ADD_COMM_TALLIES(tx_discards);
+ ADD_COMM_TALLIES(rx_unicast_frames);
+ ADD_COMM_TALLIES(rx_multicast_frames);
+ ADD_COMM_TALLIES(rx_fragments);
+ ADD_COMM_TALLIES(rx_unicast_octets);
+ ADD_COMM_TALLIES(rx_multicast_octets);
+ ADD_COMM_TALLIES(rx_fcs_errors);
+ ADD_COMM_TALLIES(rx_discards_no_buffer);
+ ADD_COMM_TALLIES(tx_discards_wrong_sa);
+ ADD_COMM_TALLIES(rx_discards_wep_undecryptable);
+ ADD_COMM_TALLIES(rx_message_in_msg_fragments);
+ ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments);
+#undef ADD_COMM_TALLIES
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_commtallies(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ if (local->tallies32)
+ prism2_info_commtallies32(local, buf, left);
+ else
+ prism2_info_commtallies16(local, buf, left);
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+#ifndef PRISM2_NO_DEBUG
+static const char* hfa384x_linkstatus_str(u16 linkstatus)
+{
+ switch (linkstatus) {
+ case HFA384X_LINKSTATUS_CONNECTED:
+ return "Connected";
+ case HFA384X_LINKSTATUS_DISCONNECTED:
+ return "Disconnected";
+ case HFA384X_LINKSTATUS_AP_CHANGE:
+ return "Access point change";
+ case HFA384X_LINKSTATUS_AP_OUT_OF_RANGE:
+ return "Access point out of range";
+ case HFA384X_LINKSTATUS_AP_IN_RANGE:
+ return "Access point in range";
+ case HFA384X_LINKSTATUS_ASSOC_FAILED:
+ return "Association failed";
+ default:
+ return "Unknown";
+ }
+}
+#endif /* PRISM2_NO_DEBUG */
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_linkstatus(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ u16 val;
+ int non_sta_mode;
+
+ /* Alloc new JoinRequests to occur since LinkStatus for the previous
+ * has been received */
+ local->last_join_time = 0;
+
+ if (left != 2) {
+ printk(KERN_DEBUG "%s: invalid linkstatus info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ non_sta_mode = local->iw_mode == IW_MODE_MASTER ||
+ local->iw_mode == IW_MODE_REPEAT ||
+ local->iw_mode == IW_MODE_MONITOR;
+
+ val = buf[0] | (buf[1] << 8);
+ if (!non_sta_mode || val != HFA384X_LINKSTATUS_DISCONNECTED) {
+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus=%d (%s)\n",
+ local->dev->name, val, hfa384x_linkstatus_str(val));
+ }
+
+ if (non_sta_mode) {
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ return;
+ }
+
+ /* Get current BSSID later in scheduled task */
+ set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info);
+ local->prev_link_status = val;
+ schedule_work(&local->info_queue);
+}
+
+
+static void prism2_host_roaming(local_info_t *local)
+{
+ struct hfa384x_join_request req;
+ struct net_device *dev = local->dev;
+ struct hfa384x_hostscan_result *selected, *entry;
+ int i;
+ unsigned long flags;
+
+ if (local->last_join_time &&
+ time_before(jiffies, local->last_join_time + 10 * HZ)) {
+ PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been "
+ "completed - waiting for it before issuing new one\n",
+ dev->name);
+ return;
+ }
+
+ /* ScanResults are sorted: first ESS results in decreasing signal
+ * quality then IBSS results in similar order.
+ * Trivial roaming policy: just select the first entry.
+ * This could probably be improved by adding hysteresis to limit
+ * number of handoffs, etc.
+ *
+ * Could do periodic RID_SCANREQUEST or Inquire F101 to get new
+ * ScanResults */
+ spin_lock_irqsave(&local->lock, flags);
+ if (local->last_scan_results == NULL ||
+ local->last_scan_results_count == 0) {
+ spin_unlock_irqrestore(&local->lock, flags);
+ PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n",
+ dev->name);
+ return;
+ }
+
+ selected = &local->last_scan_results[0];
+
+ if (local->preferred_ap[0] || local->preferred_ap[1] ||
+ local->preferred_ap[2] || local->preferred_ap[3] ||
+ local->preferred_ap[4] || local->preferred_ap[5]) {
+ /* Try to find preferred AP */
+ PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n",
+ dev->name, MAC2STR(local->preferred_ap));
+ for (i = 0; i < local->last_scan_results_count; i++) {
+ entry = &local->last_scan_results[i];
+ if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
+ {
+ PDEBUG(DEBUG_EXTRA, "%s: using preferred AP "
+ "selection\n", dev->name);
+ selected = entry;
+ break;
+ }
+ }
+ }
+
+ memcpy(req.bssid, selected->bssid, 6);
+ req.channel = selected->chid;
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n",
+ dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel));
+ if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
+ sizeof(req))) {
+ printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
+ }
+ local->last_join_time = jiffies;
+}
+
+
+static void hostap_report_scan_complete(local_info_t *local)
+{
+ union iwreq_data wrqu;
+
+ /* Inform user space about new scan results (just empty event,
+ * SIOCGIWSCAN can be used to fetch data */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL);
+
+ /* Allow SIOCGIWSCAN handling to occur since we have received
+ * scanning result */
+ local->scan_timestamp = 0;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
+ int left)
+{
+ u16 *pos;
+ int new_count, i;
+ unsigned long flags;
+ struct hfa384x_scan_result *res;
+ struct hfa384x_hostscan_result *results, *prev;
+
+ if (left < 4) {
+ printk(KERN_DEBUG "%s: invalid scanresult info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ pos = (u16 *) buf;
+ pos++;
+ pos++;
+ left -= 4;
+
+ new_count = left / sizeof(struct hfa384x_scan_result);
+ results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+ GFP_ATOMIC);
+ if (results == NULL)
+ return;
+
+ /* Convert to hostscan result format. */
+ res = (struct hfa384x_scan_result *) pos;
+ for (i = 0; i < new_count; i++) {
+ memcpy(&results[i], &res[i],
+ sizeof(struct hfa384x_scan_result));
+ results[i].atim = 0;
+ }
+
+ spin_lock_irqsave(&local->lock, flags);
+ local->last_scan_type = PRISM2_SCAN;
+ prev = local->last_scan_results;
+ local->last_scan_results = results;
+ local->last_scan_results_count = new_count;
+ spin_unlock_irqrestore(&local->lock, flags);
+ kfree(prev);
+
+ hostap_report_scan_complete(local);
+
+ /* Perform rest of ScanResults handling later in scheduled task */
+ set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info);
+ schedule_work(&local->info_queue);
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static void prism2_info_hostscanresults(local_info_t *local,
+ unsigned char *buf, int left)
+{
+ int i, result_size, copy_len, new_count;
+ struct hfa384x_hostscan_result *results, *prev;
+ unsigned long flags;
+ u16 *pos;
+ u8 *ptr;
+
+ wake_up_interruptible(&local->hostscan_wq);
+
+ if (left < 4) {
+ printk(KERN_DEBUG "%s: invalid hostscanresult info frame "
+ "length %d\n", local->dev->name, left);
+ return;
+ }
+
+ pos = (u16 *) buf;
+ copy_len = result_size = le16_to_cpu(*pos);
+ if (result_size == 0) {
+ printk(KERN_DEBUG "%s: invalid result_size (0) in "
+ "hostscanresults\n", local->dev->name);
+ return;
+ }
+ if (copy_len > sizeof(struct hfa384x_hostscan_result))
+ copy_len = sizeof(struct hfa384x_hostscan_result);
+
+ pos++;
+ pos++;
+ left -= 4;
+ ptr = (u8 *) pos;
+
+ new_count = left / result_size;
+ results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+ GFP_ATOMIC);
+ if (results == NULL)
+ return;
+ memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result));
+
+ for (i = 0; i < new_count; i++) {
+ memcpy(&results[i], ptr, copy_len);
+ ptr += result_size;
+ left -= result_size;
+ }
+
+ if (left) {
+ printk(KERN_DEBUG "%s: short HostScan result entry (%d/%d)\n",
+ local->dev->name, left, result_size);
+ }
+
+ spin_lock_irqsave(&local->lock, flags);
+ local->last_scan_type = PRISM2_HOSTSCAN;
+ prev = local->last_scan_results;
+ local->last_scan_results = results;
+ local->last_scan_results_count = new_count;
+ spin_unlock_irqrestore(&local->lock, flags);
+ kfree(prev);
+
+ hostap_report_scan_complete(local);
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+/* Called only as a tasklet (software IRQ) */
+void hostap_info_process(local_info_t *local, struct sk_buff *skb)
+{
+ struct hfa384x_info_frame *info;
+ unsigned char *buf;
+ int left;
+#ifndef PRISM2_NO_DEBUG
+ int i;
+#endif /* PRISM2_NO_DEBUG */
+
+ info = (struct hfa384x_info_frame *) skb->data;
+ buf = skb->data + sizeof(*info);
+ left = skb->len - sizeof(*info);
+
+ switch (info->type) {
+ case HFA384X_INFO_COMMTALLIES:
+ prism2_info_commtallies(local, buf, left);
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case HFA384X_INFO_LINKSTATUS:
+ prism2_info_linkstatus(local, buf, left);
+ break;
+
+ case HFA384X_INFO_SCANRESULTS:
+ prism2_info_scanresults(local, buf, left);
+ break;
+
+ case HFA384X_INFO_HOSTSCANRESULTS:
+ prism2_info_hostscanresults(local, buf, left);
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+#ifndef PRISM2_NO_DEBUG
+ default:
+ PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n",
+ local->dev->name, info->len, info->type);
+ PDEBUG(DEBUG_EXTRA, "Unknown info frame:");
+ for (i = 0; i < (left < 100 ? left : 100); i++)
+ PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]);
+ PDEBUG2(DEBUG_EXTRA, "\n");
+ break;
+#endif /* PRISM2_NO_DEBUG */
+ }
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static void handle_info_queue_linkstatus(local_info_t *local)
+{
+ int val = local->prev_link_status;
+ int connected;
+ union iwreq_data wrqu;
+
+ connected =
+ val == HFA384X_LINKSTATUS_CONNECTED ||
+ val == HFA384X_LINKSTATUS_AP_CHANGE ||
+ val == HFA384X_LINKSTATUS_AP_IN_RANGE;
+
+ if (local->func->get_rid(local->dev, HFA384X_RID_CURRENTBSSID,
+ local->bssid, ETH_ALEN, 1) < 0) {
+ printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
+ "LinkStatus event\n", local->dev->name);
+ } else {
+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=" MACSTR "\n",
+ local->dev->name,
+ MAC2STR((unsigned char *) local->bssid));
+ if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
+ hostap_add_sta(local->ap, local->bssid);
+ }
+
+ /* Get BSSID if we have a valid AP address */
+ if (connected) {
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ memcpy(wrqu.ap_addr.sa_data, local->bssid, ETH_ALEN);
+ } else {
+ netif_carrier_off(local->dev);
+ netif_carrier_off(local->ddev);
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ }
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ /*
+ * Filter out sequential disconnect events in order not to cause a
+ * flood of SIOCGIWAP events that have a race condition with EAPOL
+ * frames and can confuse wpa_supplicant about the current association
+ * status.
+ */
+ if (connected || local->prev_linkstatus_connected)
+ wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+ local->prev_linkstatus_connected = connected;
+}
+
+
+static void handle_info_queue_scanresults(local_info_t *local)
+{
+ if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA)
+ prism2_host_roaming(local);
+
+ if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA &&
+ memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00",
+ ETH_ALEN) != 0) {
+ /*
+ * Firmware seems to be getting into odd state in host_roaming
+ * mode 2 when hostscan is used without join command, so try
+ * to fix this by re-joining the current AP. This does not
+ * actually trigger a new association if the current AP is
+ * still in the scan results.
+ */
+ prism2_host_roaming(local);
+ }
+}
+
+
+/* Called only as scheduled task after receiving info frames (used to avoid
+ * pending too much time in HW IRQ handler). */
+static void handle_info_queue(void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS,
+ &local->pending_info))
+ handle_info_queue_linkstatus(local);
+
+ if (test_and_clear_bit(PRISM2_INFO_PENDING_SCANRESULTS,
+ &local->pending_info))
+ handle_info_queue_scanresults(local);
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+void hostap_info_init(local_info_t *local)
+{
+ skb_queue_head_init(&local->info_list);
+#ifndef PRISM2_NO_STATION_MODES
+ INIT_WORK(&local->info_queue, handle_info_queue, local);
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+EXPORT_SYMBOL(hostap_info_init);
+EXPORT_SYMBOL(hostap_info_process);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
new file mode 100644
index 000000000000..2617d70bcda9
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -0,0 +1,4090 @@
+/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
+
+#ifdef in_atomic
+/* Get kernel_locked() for in_atomic() */
+#include <linux/smp_lock.h>
+#endif
+#include <linux/ethtool.h>
+
+
+static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct iw_statistics *wstats;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Why are we doing that ? Jean II */
+ if (iface->type != HOSTAP_INTERFACE_MAIN)
+ return NULL;
+
+ wstats = &local->wstats;
+
+ wstats->status = 0;
+ wstats->discard.code =
+ local->comm_tallies.rx_discards_wep_undecryptable;
+ wstats->discard.misc =
+ local->comm_tallies.rx_fcs_errors +
+ local->comm_tallies.rx_discards_no_buffer +
+ local->comm_tallies.tx_discards_wrong_sa;
+
+ wstats->discard.retries =
+ local->comm_tallies.tx_retry_limit_exceeded;
+ wstats->discard.fragment =
+ local->comm_tallies.rx_message_in_bad_msg_fragments;
+
+ if (local->iw_mode != IW_MODE_MASTER &&
+ local->iw_mode != IW_MODE_REPEAT) {
+ int update = 1;
+#ifdef in_atomic
+ /* RID reading might sleep and it must not be called in
+ * interrupt context or while atomic. However, this
+ * function seems to be called while atomic (at least in Linux
+ * 2.5.59). Update signal quality values only if in suitable
+ * context. Otherwise, previous values read from tick timer
+ * will be used. */
+ if (in_atomic())
+ update = 0;
+#endif /* in_atomic */
+
+ if (update && prism2_update_comms_qual(dev) == 0)
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED |
+ IW_QUAL_DBM;
+
+ wstats->qual.qual = local->comms_qual;
+ wstats->qual.level = local->avg_signal;
+ wstats->qual.noise = local->avg_noise;
+ } else {
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = IW_QUAL_ALL_INVALID;
+ }
+
+ return wstats;
+}
+
+
+static int prism2_get_datarates(struct net_device *dev, u8 *rates)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u8 buf[12];
+ int len;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf,
+ sizeof(buf), 0);
+ if (len < 2)
+ return 0;
+
+ val = le16_to_cpu(*(u16 *) buf); /* string length */
+
+ if (len - 2 < val || val > 10)
+ return 0;
+
+ memcpy(rates, buf + 2, val);
+ return val;
+}
+
+
+static int prism2_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *name, char *extra)
+{
+ u8 rates[10];
+ int len, i, over2 = 0;
+
+ len = prism2_get_datarates(dev, rates);
+
+ for (i = 0; i < len; i++) {
+ if (rates[i] == 0x0b || rates[i] == 0x16) {
+ over2 = 1;
+ break;
+ }
+ }
+
+ strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS");
+
+ return 0;
+}
+
+
+static void prism2_crypt_delayed_deinit(local_info_t *local,
+ struct ieee80211_crypt_data **crypt)
+{
+ struct ieee80211_crypt_data *tmp;
+ unsigned long flags;
+
+ tmp = *crypt;
+ *crypt = NULL;
+
+ if (tmp == NULL)
+ return;
+
+ /* must not run ops->deinit() while there may be pending encrypt or
+ * decrypt operations. Use a list of delayed deinits to avoid needing
+ * locking. */
+
+ spin_lock_irqsave(&local->lock, flags);
+ list_add(&tmp->list, &local->crypt_deinit_list);
+ if (!timer_pending(&local->crypt_deinit_timer)) {
+ local->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&local->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+
+static int prism2_ioctl_siwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *keybuf)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i;
+ struct ieee80211_crypt_data **crypt;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > 4)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ crypt = &local->crypt[i];
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ if (*crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ if (*crypt != NULL && (*crypt)->ops != NULL &&
+ strcmp((*crypt)->ops->name, "WEP") != 0) {
+ /* changing to use WEP; deinit previously used algorithm */
+ prism2_crypt_delayed_deinit(local, crypt);
+ }
+
+ if (*crypt == NULL) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ /* take WEP into use */
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL)
+ return -ENOMEM;
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ if (!new_crypt->ops) {
+ request_module("ieee80211_crypt_wep");
+ new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ }
+ if (new_crypt->ops)
+ new_crypt->priv = new_crypt->ops->init(i);
+ if (!new_crypt->ops || !new_crypt->priv) {
+ kfree(new_crypt);
+ new_crypt = NULL;
+
+ printk(KERN_WARNING "%s: could not initialize WEP: "
+ "load module hostap_crypt_wep.o\n",
+ dev->name);
+ return -EOPNOTSUPP;
+ }
+ *crypt = new_crypt;
+ }
+
+ if (erq->length > 0) {
+ int len = erq->length <= 5 ? 5 : 13;
+ int first = 1, j;
+ if (len > erq->length)
+ memset(keybuf + erq->length, 0, len - erq->length);
+ (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
+ for (j = 0; j < WEP_KEYS; j++) {
+ if (j != i && local->crypt[j]) {
+ first = 0;
+ break;
+ }
+ }
+ if (first)
+ local->tx_keyidx = i;
+ } else {
+ /* No key data - just set the default TX key index */
+ local->tx_keyidx = i;
+ }
+
+ done:
+ local->open_wep = erq->flags & IW_ENCODE_OPEN;
+
+ if (hostap_set_encryption(local)) {
+ printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name);
+ return -EINVAL;
+ }
+
+ /* Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode. */
+ if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) {
+ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_giwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int i, len;
+ u16 val;
+ struct ieee80211_crypt_data *crypt;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > 4)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ crypt = local->crypt[i];
+ erq->flags = i + 1;
+
+ if (crypt == NULL || crypt->ops == NULL) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+
+ if (strcmp(crypt->ops->name, "WEP") != 0) {
+ /* only WEP is supported with wireless extensions, so just
+ * report that encryption is used */
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_ENABLED;
+ return 0;
+ }
+
+ /* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show
+ * the keys from driver buffer */
+ len = crypt->ops->get_key(key, WEP_KEY_LEN, NULL, crypt->priv);
+ erq->length = (len >= 0 ? len : 0);
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0)
+ {
+ printk("CNFWEPFLAGS reading failed\n");
+ return -EOPNOTSUPP;
+ }
+ le16_to_cpus(&val);
+ if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED)
+ erq->flags |= IW_ENCODE_ENABLED;
+ else
+ erq->flags |= IW_ENCODE_DISABLED;
+ if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
+
+ return 0;
+}
+
+
+static int hostap_set_rate(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret, basic_rates;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ basic_rates = local->basic_rates & local->tx_rate_control;
+ if (!basic_rates || basic_rates != local->basic_rates) {
+ printk(KERN_INFO "%s: updating basic rate set automatically "
+ "to match with the new supported rate set\n",
+ dev->name);
+ if (!basic_rates)
+ basic_rates = local->tx_rate_control;
+
+ local->basic_rates = basic_rates;
+ if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ basic_rates))
+ printk(KERN_WARNING "%s: failed to set "
+ "cnfBasicRates\n", dev->name);
+ }
+
+ ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
+ local->tx_rate_control) ||
+ hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
+ local->tx_rate_control) ||
+ local->func->reset_port(dev));
+
+ if (ret) {
+ printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates "
+ "setting to 0x%x failed\n",
+ dev->name, local->tx_rate_control);
+ }
+
+ /* Update TX rate configuration for all STAs based on new operational
+ * rate set. */
+ hostap_update_rates(local);
+
+ return ret;
+}
+
+
+static int prism2_ioctl_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->fixed) {
+ switch (rrq->value) {
+ case 11000000:
+ local->tx_rate_control = HFA384X_RATES_11MBPS;
+ break;
+ case 5500000:
+ local->tx_rate_control = HFA384X_RATES_5MBPS;
+ break;
+ case 2000000:
+ local->tx_rate_control = HFA384X_RATES_2MBPS;
+ break;
+ case 1000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS;
+ break;
+ default:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ }
+ } else {
+ switch (rrq->value) {
+ case 11000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ case 5500000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS;
+ break;
+ case 2000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS;
+ break;
+ case 1000000:
+ local->tx_rate_control = HFA384X_RATES_1MBPS;
+ break;
+ default:
+ local->tx_rate_control = HFA384X_RATES_1MBPS |
+ HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
+ HFA384X_RATES_11MBPS;
+ break;
+ }
+ }
+
+ return hostap_set_rate(dev);
+}
+
+
+static int prism2_ioctl_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ u16 val;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ if ((val & 0x1) && (val > 1))
+ rrq->fixed = 0;
+ else
+ rrq->fixed = 1;
+
+ if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL &&
+ !local->fw_tx_rate_control) {
+ /* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in
+ * Host AP mode, so use the recorded TX rate of the last sent
+ * frame */
+ rrq->value = local->ap->last_tx_rate > 0 ?
+ local->ap->last_tx_rate * 100000 : 11000000;
+ return 0;
+ }
+
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ switch (val) {
+ case HFA384X_RATES_1MBPS:
+ rrq->value = 1000000;
+ break;
+ case HFA384X_RATES_2MBPS:
+ rrq->value = 2000000;
+ break;
+ case HFA384X_RATES_5MBPS:
+ rrq->value = 5500000;
+ break;
+ case HFA384X_RATES_11MBPS:
+ rrq->value = 11000000;
+ break;
+ default:
+ /* should not happen */
+ rrq->value = 11000000;
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_siwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Set the desired AP density */
+ if (sens->value < 1 || sens->value > 3)
+ return -EINVAL;
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Get the current AP density */
+ if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ sens->value = __le16_to_cpu(val);
+ sens->fixed = 1;
+
+ return 0;
+}
+
+
+/* Deprecated in new wireless extension API */
+static int prism2_ioctl_giwaplist(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct sockaddr *addr;
+ struct iw_quality *qual;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->iw_mode != IW_MODE_MASTER) {
+ printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported "
+ "in Host AP mode\n");
+ data->length = 0;
+ return -EOPNOTSUPP;
+ }
+
+ addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL);
+ qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL);
+ if (addr == NULL || qual == NULL) {
+ kfree(addr);
+ kfree(qual);
+ data->length = 0;
+ return -ENOMEM;
+ }
+
+ data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
+
+ memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+ data->flags = 1; /* has quality information */
+ memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+ sizeof(struct iw_quality) * data->length);
+
+ kfree(addr);
+ kfree(qual);
+ return 0;
+}
+
+
+static int prism2_ioctl_siwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rts->disabled)
+ val = __constant_cpu_to_le16(2347);
+ else if (rts->value < 0 || rts->value > 2347)
+ return -EINVAL;
+ else
+ val = __cpu_to_le16(rts->value);
+
+ if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ local->rts_threshold = rts->value;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ rts->value = __le16_to_cpu(val);
+ rts->disabled = (rts->value == 2347);
+ rts->fixed = 1;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rts->disabled)
+ val = __constant_cpu_to_le16(2346);
+ else if (rts->value < 256 || rts->value > 2346)
+ return -EINVAL;
+ else
+ val = __cpu_to_le16(rts->value & ~0x1); /* even numbers only */
+
+ local->fragm_threshold = rts->value & ~0x1;
+ if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val,
+ 2)
+ || local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
+ &val, 2, 1) < 0)
+ return -EINVAL;
+
+ rts->value = __le16_to_cpu(val);
+ rts->disabled = (rts->value == 2346);
+ rts->fixed = 1;
+
+ return 0;
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static int hostap_join_ap(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_join_request req;
+ unsigned long flags;
+ int i;
+ struct hfa384x_hostscan_result *entry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memcpy(req.bssid, local->preferred_ap, ETH_ALEN);
+ req.channel = 0;
+
+ spin_lock_irqsave(&local->lock, flags);
+ for (i = 0; i < local->last_scan_results_count; i++) {
+ if (!local->last_scan_results)
+ break;
+ entry = &local->last_scan_results[i];
+ if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) {
+ req.channel = entry->chid;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+
+ if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
+ sizeof(req))) {
+ printk(KERN_DEBUG "%s: JoinRequest " MACSTR
+ " failed\n",
+ dev->name, MAC2STR(local->preferred_ap));
+ return -1;
+ }
+
+ printk(KERN_DEBUG "%s: Trying to join BSSID " MACSTR "\n",
+ dev->name, MAC2STR(local->preferred_ap));
+
+ return 0;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+static int prism2_ioctl_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN);
+
+ if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) {
+ struct hfa384x_scan_request scan_req;
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST,
+ &scan_req, sizeof(scan_req))) {
+ printk(KERN_DEBUG "%s: ScanResults request failed - "
+ "preferred AP delayed to next unsolicited "
+ "scan\n", dev->name);
+ }
+ } else if (local->host_roaming == 2 &&
+ local->iw_mode == IW_MODE_INFRA) {
+ if (hostap_join_ap(dev))
+ return -EINVAL;
+ } else {
+ printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only "
+ "in Managed mode when host_roaming is enabled\n",
+ dev->name);
+ }
+
+ return 0;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+static int prism2_ioctl_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ ap_addr->sa_family = ARPHRD_ETHER;
+ switch (iface->type) {
+ case HOSTAP_INTERFACE_AP:
+ memcpy(&ap_addr->sa_data, dev->dev_addr, ETH_ALEN);
+ break;
+ case HOSTAP_INTERFACE_STA:
+ memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN);
+ break;
+ case HOSTAP_INTERFACE_WDS:
+ memcpy(&ap_addr->sa_data, iface->u.wds.remote_addr, ETH_ALEN);
+ break;
+ default:
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID,
+ &ap_addr->sa_data, ETH_ALEN, 1) < 0)
+ return -EOPNOTSUPP;
+
+ /* local->bssid is also updated in LinkStatus handler when in
+ * station mode */
+ memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN);
+ break;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(local->name, 0, sizeof(local->name));
+ memcpy(local->name, nickname, data->length);
+ local->name_set = 1;
+
+ if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int len;
+ char name[MAX_NAME_LEN + 3];
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME,
+ &name, MAX_NAME_LEN + 2, 0);
+ val = __le16_to_cpu(*(u16 *) name);
+ if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN)
+ return -EOPNOTSUPP;
+
+ name[val + 2] = '\0';
+ data->length = val + 1;
+ memcpy(nickname, name + 2, val + 1);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* freq => chan. */
+ if (freq->e == 1 &&
+ freq->m / 100000 >= freq_list[0] &&
+ freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) {
+ int ch;
+ int fr = freq->m / 100000;
+ for (ch = 0; ch < FREQ_COUNT; ch++) {
+ if (fr == freq_list[ch]) {
+ freq->e = 0;
+ freq->m = ch + 1;
+ break;
+ }
+ }
+ }
+
+ if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT ||
+ !(local->channel_mask & (1 << (freq->m - 1))))
+ return -EINVAL;
+
+ local->channel = freq->m; /* channel is used in prism2_setup_rids() */
+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) <
+ 0)
+ return -EINVAL;
+
+ le16_to_cpus(&val);
+ if (val < 1 || val > FREQ_COUNT)
+ return -EINVAL;
+
+ freq->m = freq_list[val - 1] * 100000;
+ freq->e = 1;
+
+ return 0;
+}
+
+
+static void hostap_monitor_set_type(local_info_t *local)
+{
+ struct net_device *dev = local->ddev;
+
+ if (dev == NULL)
+ return;
+
+ if (local->monitor_type == PRISM2_MONITOR_PRISM ||
+ local->monitor_type == PRISM2_MONITOR_CAPHDR) {
+ dev->type = ARPHRD_IEEE80211_PRISM;
+ dev->hard_header_parse =
+ hostap_80211_prism_header_parse;
+ } else {
+ dev->type = ARPHRD_IEEE80211;
+ dev->hard_header_parse = hostap_80211_header_parse;
+ }
+}
+
+
+static int prism2_ioctl_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (iface->type == HOSTAP_INTERFACE_WDS)
+ return -EOPNOTSUPP;
+
+ if (data->flags == 0)
+ ssid[0] = '\0'; /* ANY */
+
+ if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') {
+ /* Setting SSID to empty string seems to kill the card in
+ * Host AP mode */
+ printk(KERN_DEBUG "%s: Host AP mode does not support "
+ "'Any' essid\n", dev->name);
+ return -EINVAL;
+ }
+
+ memcpy(local->essid, ssid, data->length);
+ local->essid[data->length] = '\0';
+
+ if ((!local->fw_ap &&
+ hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid))
+ || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int prism2_ioctl_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (iface->type == HOSTAP_INTERFACE_WDS)
+ return -EOPNOTSUPP;
+
+ data->flags = 1; /* active */
+ if (local->iw_mode == IW_MODE_MASTER) {
+ data->length = strlen(local->essid);
+ memcpy(essid, local->essid, IW_ESSID_MAX_SIZE);
+ } else {
+ int len;
+ char ssid[MAX_SSID_LEN + 2];
+ memset(ssid, 0, sizeof(ssid));
+ len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID,
+ &ssid, MAX_SSID_LEN + 2, 0);
+ val = __le16_to_cpu(*(u16 *) ssid);
+ if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) {
+ return -EOPNOTSUPP;
+ }
+ data->length = val;
+ memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE);
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_giwrange(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct iw_range *range = (struct iw_range *) extra;
+ u8 rates[10];
+ u16 val;
+ int i, len, over2;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ data->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
+ /* TODO: could fill num_txpower and txpower array with
+ * something; however, there are 128 different values.. */
+
+ range->txpower_capa = IW_TXPOW_DBM;
+
+ if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC)
+ {
+ range->min_pmp = 1 * 1024;
+ range->max_pmp = 65535 * 1024;
+ range->min_pmt = 1 * 1024;
+ range->max_pmt = 1000 * 1024;
+ range->pmp_flags = IW_POWER_PERIOD;
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
+ IW_POWER_UNICAST_R | IW_POWER_ALL_R;
+ }
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 18;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->min_retry = 0;
+ range->max_retry = 255;
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ if (local->channel_mask & (1 << i)) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = freq_list[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) {
+ range->max_qual.qual = 70; /* what is correct max? This was not
+ * documented exactly. At least
+ * 69 has been observed. */
+ range->max_qual.level = 0; /* dB */
+ range->max_qual.noise = 0; /* dB */
+
+ /* What would be suitable values for "average/typical" qual? */
+ range->avg_qual.qual = 20;
+ range->avg_qual.level = -60;
+ range->avg_qual.noise = -95;
+ } else {
+ range->max_qual.qual = 92; /* 0 .. 92 */
+ range->max_qual.level = 154; /* 27 .. 154 */
+ range->max_qual.noise = 154; /* 27 .. 154 */
+ }
+ range->sensitivity = 3;
+
+ range->max_encoding_tokens = WEP_KEYS;
+ range->num_encoding_sizes = 2;
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+
+ over2 = 0;
+ len = prism2_get_datarates(dev, rates);
+ range->num_bitrates = 0;
+ for (i = 0; i < len; i++) {
+ if (range->num_bitrates < IW_MAX_BITRATES) {
+ range->bitrate[range->num_bitrates] =
+ rates[i] * 500000;
+ range->num_bitrates++;
+ }
+ if (rates[i] == 0x0b || rates[i] == 0x16)
+ over2 = 1;
+ }
+ /* estimated maximum TCP throughput values (bps) */
+ range->throughput = over2 ? 5500000 : 1500000;
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ /* Event capability (kernel + driver) */
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
+ IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
+ IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
+ IW_EVENT_CAPA_MASK(IWEVEXPIRED));
+
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+ return 0;
+}
+
+
+static int hostap_monitor_mode_enable(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+
+ printk(KERN_DEBUG "Enabling monitor mode\n");
+ hostap_monitor_set_type(local);
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_PSEUDO_IBSS)) {
+ printk(KERN_DEBUG "Port type setting for monitor mode "
+ "failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Host decrypt is needed to get the IV and ICV fields;
+ * however, monitor mode seems to remove WEP flag from frame
+ * control field */
+ if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
+ HFA384X_WEPFLAGS_HOSTENCRYPT |
+ HFA384X_WEPFLAGS_HOSTDECRYPT)) {
+ printk(KERN_DEBUG "WEP flags setting failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (local->func->reset_port(dev) ||
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_MONITOR << 8),
+ 0, NULL, NULL)) {
+ printk(KERN_DEBUG "Setting monitor mode failed\n");
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+
+static int hostap_monitor_mode_disable(local_info_t *local)
+{
+ struct net_device *dev = local->ddev;
+
+ if (dev == NULL)
+ return -1;
+
+ printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name);
+ dev->type = ARPHRD_ETHER;
+ dev->hard_header_parse = local->saved_eth_header_parse;
+ if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_STOP << 8),
+ 0, NULL, NULL))
+ return -1;
+ return hostap_set_encryption(local);
+}
+
+
+static int prism2_ioctl_siwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int double_reset = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
+ *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT &&
+ *mode != IW_MODE_MONITOR)
+ return -EOPNOTSUPP;
+
+#ifdef PRISM2_NO_STATION_MODES
+ if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA)
+ return -EOPNOTSUPP;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ if (*mode == local->iw_mode)
+ return 0;
+
+ if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') {
+ printk(KERN_WARNING "%s: empty SSID not allowed in Master "
+ "mode\n", dev->name);
+ return -EINVAL;
+ }
+
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_mode_disable(local);
+
+ if ((local->iw_mode == IW_MODE_ADHOC ||
+ local->iw_mode == IW_MODE_MONITOR) && *mode == IW_MODE_MASTER) {
+ /* There seems to be a firmware bug in at least STA f/w v1.5.6
+ * that leaves beacon frames to use IBSS type when moving from
+ * IBSS to Host AP mode. Doing double Port0 reset seems to be
+ * enough to workaround this. */
+ double_reset = 1;
+ }
+
+ printk(KERN_DEBUG "prism2: %s: operating mode changed "
+ "%d -> %d\n", dev->name, local->iw_mode, *mode);
+ local->iw_mode = *mode;
+
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_mode_enable(local);
+ else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
+ !local->fw_encrypt_ok) {
+ printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
+ "a workaround for firmware bug in Host AP mode WEP\n",
+ dev->name);
+ local->host_encrypt = 1;
+ }
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ hostap_get_porttype(local)))
+ return -EOPNOTSUPP;
+
+ if (local->func->reset_port(dev))
+ return -EINVAL;
+ if (double_reset && local->func->reset_port(dev))
+ return -EINVAL;
+
+ if (local->iw_mode != IW_MODE_INFRA && local->iw_mode != IW_MODE_ADHOC)
+ {
+ /* netif_carrier is used only in client modes for now, so make
+ * sure carrier is on when moving to non-client modes. */
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_giwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (iface->type) {
+ case HOSTAP_INTERFACE_STA:
+ *mode = IW_MODE_INFRA;
+ break;
+ case HOSTAP_INTERFACE_WDS:
+ *mode = IW_MODE_REPEAT;
+ break;
+ default:
+ *mode = local->iw_mode;
+ break;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ int ret = 0;
+
+ if (wrq->disabled)
+ return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0);
+
+ switch (wrq->flags & IW_POWER_MODE) {
+ case IW_POWER_UNICAST_R:
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ break;
+ case IW_POWER_ALL_R:
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ break;
+ case IW_POWER_ON:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (wrq->flags & IW_POWER_TIMEOUT) {
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION,
+ wrq->value / 1024);
+ if (ret)
+ return ret;
+ }
+ if (wrq->flags & IW_POWER_PERIOD) {
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
+ if (ret)
+ return ret;
+ ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
+ wrq->value / 1024);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 enable, mcast;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1)
+ < 0)
+ return -EINVAL;
+
+ if (!__le16_to_cpu(enable)) {
+ rrq->disabled = 1;
+ return 0;
+ }
+
+ rrq->disabled = 0;
+
+ if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+ u16 timeout;
+ if (local->func->get_rid(dev,
+ HFA384X_RID_CNFPMHOLDOVERDURATION,
+ &timeout, 2, 1) < 0)
+ return -EINVAL;
+
+ rrq->flags = IW_POWER_TIMEOUT;
+ rrq->value = __le16_to_cpu(timeout) * 1024;
+ } else {
+ u16 period;
+ if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
+ &period, 2, 1) < 0)
+ return -EINVAL;
+
+ rrq->flags = IW_POWER_PERIOD;
+ rrq->value = __le16_to_cpu(period) * 1024;
+ }
+
+ if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast,
+ 2, 1) < 0)
+ return -EINVAL;
+
+ if (__le16_to_cpu(mcast))
+ rrq->flags |= IW_POWER_ALL_R;
+ else
+ rrq->flags |= IW_POWER_UNICAST_R;
+
+ return 0;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_siwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->disabled)
+ return -EINVAL;
+
+ /* setting retry limits is not supported with the current station
+ * firmware code; simulate this with alternative retry count for now */
+ if (rrq->flags == IW_RETRY_LIMIT) {
+ if (rrq->value < 0) {
+ /* disable manual retry count setting and use firmware
+ * defaults */
+ local->manual_retry_count = -1;
+ local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY;
+ } else {
+ if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
+ rrq->value)) {
+ printk(KERN_DEBUG "%s: Alternate retry count "
+ "setting to %d failed\n",
+ dev->name, rrq->value);
+ return -EOPNOTSUPP;
+ }
+
+ local->manual_retry_count = rrq->value;
+ local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY;
+ }
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+
+#if 0
+ /* what could be done, if firmware would support this.. */
+
+ if (rrq->flags & IW_RETRY_LIMIT) {
+ if (rrq->flags & IW_RETRY_MAX)
+ HFA384X_RID_LONGRETRYLIMIT = rrq->value;
+ else if (rrq->flags & IW_RETRY_MIN)
+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
+ else {
+ HFA384X_RID_LONGRETRYLIMIT = rrq->value;
+ HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
+ }
+
+ }
+
+ if (rrq->flags & IW_RETRY_LIFETIME) {
+ HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024;
+ }
+
+ return 0;
+#endif /* 0 */
+}
+
+static int prism2_ioctl_giwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 shortretry, longretry, lifetime, altretry;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry,
+ 2, 1) < 0 ||
+ local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry,
+ 2, 1) < 0 ||
+ local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME,
+ &lifetime, 2, 1) < 0)
+ return -EINVAL;
+
+ le16_to_cpus(&shortretry);
+ le16_to_cpus(&longretry);
+ le16_to_cpus(&lifetime);
+
+ rrq->disabled = 0;
+
+ if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+ rrq->flags = IW_RETRY_LIFETIME;
+ rrq->value = lifetime * 1024;
+ } else {
+ if (local->manual_retry_count >= 0) {
+ rrq->flags = IW_RETRY_LIMIT;
+ if (local->func->get_rid(dev,
+ HFA384X_RID_CNFALTRETRYCOUNT,
+ &altretry, 2, 1) >= 0)
+ rrq->value = le16_to_cpu(altretry);
+ else
+ rrq->value = local->manual_retry_count;
+ } else if ((rrq->flags & IW_RETRY_MAX)) {
+ rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ rrq->value = longretry;
+ } else {
+ rrq->flags = IW_RETRY_LIMIT;
+ rrq->value = shortretry;
+ if (shortretry != longretry)
+ rrq->flags |= IW_RETRY_MIN;
+ }
+ }
+ return 0;
+}
+
+
+/* Note! This TX power controlling is experimental and should not be used in
+ * production use. It just sets raw power register and does not use any kind of
+ * feedback information from the measured TX power (CR58). This is now
+ * commented out to make sure that it is not used by accident. TX power
+ * configuration will be enabled again after proper algorithm using feedback
+ * has been implemented. */
+
+#ifdef RAW_TXPOWER_SETTING
+/* Map HFA386x's CR31 to and from dBm with some sort of ad hoc mapping..
+ * This version assumes following mapping:
+ * CR31 is 7-bit value with -64 to +63 range.
+ * -64 is mapped into +20dBm and +63 into -43dBm.
+ * This is certainly not an exact mapping for every card, but at least
+ * increasing dBm value should correspond to increasing TX power.
+ */
+
+static int prism2_txpower_hfa386x_to_dBm(u16 val)
+{
+ signed char tmp;
+
+ if (val > 255)
+ val = 255;
+
+ tmp = val;
+ tmp >>= 2;
+
+ return -12 - tmp;
+}
+
+static u16 prism2_txpower_dBm_to_hfa386x(int val)
+{
+ signed char tmp;
+
+ if (val > 20)
+ return 128;
+ else if (val < -43)
+ return 127;
+
+ tmp = val;
+ tmp = -12 - tmp;
+ tmp <<= 2;
+
+ return (unsigned char) tmp;
+}
+#endif /* RAW_TXPOWER_SETTING */
+
+
+static int prism2_ioctl_siwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+#ifdef RAW_TXPOWER_SETTING
+ char *tmp;
+#endif
+ u16 val;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (rrq->disabled) {
+ if (local->txpower_type != PRISM2_TXPOWER_OFF) {
+ val = 0xff; /* use all standby and sleep modes */
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_A_D_TEST_MODES2,
+ &val, NULL);
+ printk(KERN_DEBUG "%s: Turning radio off: %s\n",
+ dev->name, ret ? "failed" : "OK");
+ local->txpower_type = PRISM2_TXPOWER_OFF;
+ }
+ return (ret ? -EOPNOTSUPP : 0);
+ }
+
+ if (local->txpower_type == PRISM2_TXPOWER_OFF) {
+ val = 0; /* disable all standby and sleep modes */
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_A_D_TEST_MODES2, &val, NULL);
+ printk(KERN_DEBUG "%s: Turning radio on: %s\n",
+ dev->name, ret ? "failed" : "OK");
+ local->txpower_type = PRISM2_TXPOWER_UNKNOWN;
+ }
+
+#ifdef RAW_TXPOWER_SETTING
+ if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) {
+ printk(KERN_DEBUG "Setting ALC on\n");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL);
+ local->txpower_type = PRISM2_TXPOWER_AUTO;
+ return 0;
+ }
+
+ if (local->txpower_type != PRISM2_TXPOWER_FIXED) {
+ printk(KERN_DEBUG "Setting ALC off\n");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
+ local->txpower_type = PRISM2_TXPOWER_FIXED;
+ }
+
+ if (rrq->flags == IW_TXPOW_DBM)
+ tmp = "dBm";
+ else if (rrq->flags == IW_TXPOW_MWATT)
+ tmp = "mW";
+ else
+ tmp = "UNKNOWN";
+ printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp);
+
+ if (rrq->flags != IW_TXPOW_DBM) {
+ printk("SIOCSIWTXPOW with mW is not supported; use dBm\n");
+ return -EOPNOTSUPP;
+ }
+
+ local->txpower = rrq->value;
+ val = prism2_txpower_dBm_to_hfa386x(local->txpower);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL))
+ ret = -EOPNOTSUPP;
+#else /* RAW_TXPOWER_SETTING */
+ if (rrq->fixed)
+ ret = -EOPNOTSUPP;
+#endif /* RAW_TXPOWER_SETTING */
+
+ return ret;
+}
+
+static int prism2_ioctl_giwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+#ifdef RAW_TXPOWER_SETTING
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 resp0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ rrq->flags = IW_TXPOW_DBM;
+ rrq->disabled = 0;
+ rrq->fixed = 0;
+
+ if (local->txpower_type == PRISM2_TXPOWER_AUTO) {
+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF,
+ HFA386X_CR_MANUAL_TX_POWER,
+ NULL, &resp0) == 0) {
+ rrq->value = prism2_txpower_hfa386x_to_dBm(resp0);
+ } else {
+ /* Could not get real txpower; guess 15 dBm */
+ rrq->value = 15;
+ }
+ } else if (local->txpower_type == PRISM2_TXPOWER_OFF) {
+ rrq->value = 0;
+ rrq->disabled = 1;
+ } else if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
+ rrq->value = local->txpower;
+ rrq->fixed = 1;
+ } else {
+ printk("SIOCGIWTXPOW - unknown txpower_type=%d\n",
+ local->txpower_type);
+ }
+ return 0;
+#else /* RAW_TXPOWER_SETTING */
+ return -EOPNOTSUPP;
+#endif /* RAW_TXPOWER_SETTING */
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+
+/* HostScan request works with and without host_roaming mode. In addition, it
+ * does not break current association. However, it requires newer station
+ * firmware version (>= 1.3.1) than scan request. */
+static int prism2_request_hostscan(struct net_device *dev,
+ u8 *ssid, u8 ssid_len)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_hostscan_request scan_req;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = cpu_to_le16(local->channel_mask &
+ local->scan_channel_mask);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+ if (ssid) {
+ if (ssid_len > 32)
+ return -EINVAL;
+ scan_req.target_ssid_len = cpu_to_le16(ssid_len);
+ memcpy(scan_req.target_ssid, ssid, ssid_len);
+ }
+
+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "%s: HOSTSCAN failed\n", dev->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int prism2_request_scan(struct net_device *dev)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ struct hfa384x_scan_request scan_req;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = cpu_to_le16(local->channel_mask &
+ local->scan_channel_mask);
+ scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+
+ /* FIX:
+ * It seems to be enough to set roaming mode for a short moment to
+ * host-based and then setup scanrequest data and return the mode to
+ * firmware-based.
+ *
+ * Master mode would need to drop to Managed mode for a short while
+ * to make scanning work.. Or sweep through the different channels and
+ * use passive scan based on beacons. */
+
+ if (!local->host_roaming)
+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
+ HFA384X_ROAMING_HOST);
+
+ if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "SCANREQUEST failed\n");
+ ret = -EINVAL;
+ }
+
+ if (!local->host_roaming)
+ hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
+ HFA384X_ROAMING_FIRMWARE);
+
+ return 0;
+}
+
+#else /* !PRISM2_NO_STATION_MODES */
+
+static inline int prism2_request_hostscan(struct net_device *dev,
+ u8 *ssid, u8 ssid_len)
+{
+ return -EOPNOTSUPP;
+}
+
+
+static inline int prism2_request_scan(struct net_device *dev)
+{
+ return -EOPNOTSUPP;
+}
+
+#endif /* !PRISM2_NO_STATION_MODES */
+
+
+static int prism2_ioctl_siwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret;
+ u8 *ssid = NULL, ssid_len = 0;
+ struct iw_scan_req *req = (struct iw_scan_req *) extra;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (data->length < sizeof(struct iw_scan_req))
+ req = NULL;
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ /* In master mode, we just return the results of our local
+ * tables, so we don't need to start anything...
+ * Jean II */
+ data->length = 0;
+ return 0;
+ }
+
+ if (!local->dev_enabled)
+ return -ENETDOWN;
+
+ if (req && data->flags & IW_SCAN_THIS_ESSID) {
+ ssid = req->essid;
+ ssid_len = req->essid_len;
+
+ if (ssid_len &&
+ ((local->iw_mode != IW_MODE_INFRA &&
+ local->iw_mode != IW_MODE_ADHOC) ||
+ (local->sta_fw_ver < PRISM2_FW_VER(1,3,1))))
+ return -EOPNOTSUPP;
+ }
+
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
+ ret = prism2_request_hostscan(dev, ssid, ssid_len);
+ else
+ ret = prism2_request_scan(dev);
+
+ if (ret == 0)
+ local->scan_timestamp = jiffies;
+
+ /* Could inquire F101, F103 or wait for SIOCGIWSCAN and read RID */
+
+ return ret;
+}
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static char * __prism2_translate_scan(local_info_t *local,
+ struct hfa384x_hostscan_result *scan,
+ struct hostap_bss_info *bss,
+ char *current_ev, char *end_buf)
+{
+ int i, chan;
+ struct iw_event iwe;
+ char *current_val;
+ u16 capabilities;
+ u8 *pos;
+ u8 *ssid, *bssid;
+ size_t ssid_len;
+ char *buf;
+
+ if (bss) {
+ ssid = bss->ssid;
+ ssid_len = bss->ssid_len;
+ bssid = bss->bssid;
+ } else {
+ ssid = scan->ssid;
+ ssid_len = le16_to_cpu(scan->ssid_len);
+ bssid = scan->bssid;
+ }
+ if (ssid_len > 32)
+ ssid_len = 32;
+
+ /* First entry *MUST* be the AP MAC address */
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_ADDR_LEN);
+
+ /* Other entries will be displayed in the order we give them */
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = ssid_len;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWMODE;
+ if (bss) {
+ capabilities = bss->capab_info;
+ } else {
+ capabilities = le16_to_cpu(scan->capability);
+ }
+ 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;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_UINT_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWFREQ;
+ if (scan) {
+ chan = scan->chid;
+ } else if (bss) {
+ chan = bss->chan;
+ } else {
+ chan = 0;
+ }
+
+ if (chan > 0) {
+ iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+ iwe.u.freq.e = 1;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_FREQ_LEN);
+ }
+
+ if (scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVQUAL;
+ if (local->last_scan_type == PRISM2_HOSTSCAN) {
+ iwe.u.qual.level = le16_to_cpu(scan->sl);
+ iwe.u.qual.noise = le16_to_cpu(scan->anl);
+ } else {
+ iwe.u.qual.level =
+ HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->sl));
+ iwe.u.qual.noise =
+ HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
+ }
+ iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_UPDATED
+ | IW_QUAL_QUAL_INVALID
+ | IW_QUAL_DBM;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+ IW_EV_QUAL_LEN);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ 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(current_ev, end_buf, &iwe, "");
+
+ /* TODO: add SuppRates into BSS table */
+ if (scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = SIOCGIWRATE;
+ current_val = current_ev + IW_EV_LCP_LEN;
+ pos = scan->sup_rates;
+ for (i = 0; i < sizeof(scan->sup_rates); i++) {
+ if (pos[i] == 0)
+ break;
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000);
+ current_val = iwe_stream_add_value(
+ current_ev, current_val, end_buf, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any event */
+ if ((current_val - current_ev) > IW_EV_LCP_LEN)
+ current_ev = current_val;
+ }
+
+ /* TODO: add BeaconInt,resp_rate,atim into BSS table */
+ buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
+ if (buf && scan) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+ buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+ buf);
+
+ if (local->last_scan_type == PRISM2_HOSTSCAN &&
+ (capabilities & WLAN_CAPABILITY_IBSS)) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ sprintf(buf, "atim=%d", le16_to_cpu(scan->atim));
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(current_ev, end_buf,
+ &iwe, buf);
+ }
+ }
+ kfree(buf);
+
+ if (bss && bss->wpa_ie_len > 0 && bss->wpa_ie_len <= MAX_WPA_IE_LEN) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->wpa_ie_len;
+ current_ev = iwe_stream_add_point(
+ current_ev, end_buf, &iwe, bss->wpa_ie);
+ }
+
+ if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) {
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->rsn_ie_len;
+ current_ev = iwe_stream_add_point(
+ current_ev, end_buf, &iwe, bss->rsn_ie);
+ }
+
+ return current_ev;
+}
+
+
+/* Translate scan data returned from the card to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static inline int prism2_translate_scan(local_info_t *local,
+ char *buffer, int buflen)
+{
+ struct hfa384x_hostscan_result *scan;
+ int entry, hostscan;
+ char *current_ev = buffer;
+ char *end_buf = buffer + buflen;
+ struct list_head *ptr;
+
+ spin_lock_bh(&local->lock);
+
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ bss->included = 0;
+ }
+
+ hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
+ for (entry = 0; entry < local->last_scan_results_count; entry++) {
+ int found = 0;
+ scan = &local->last_scan_results[entry];
+
+ /* Report every SSID if the AP is using multiple SSIDs. If no
+ * BSS record is found (e.g., when WPA mode is disabled),
+ * report the AP once. */
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) {
+ bss->included = 1;
+ current_ev = __prism2_translate_scan(
+ local, scan, bss, current_ev, end_buf);
+ found++;
+ }
+ }
+ if (!found) {
+ current_ev = __prism2_translate_scan(
+ local, scan, NULL, current_ev, end_buf);
+ }
+ /* Check if there is space for one more entry */
+ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a bigger buffer */
+ spin_unlock_bh(&local->lock);
+ return -E2BIG;
+ }
+ }
+
+ /* Prism2 firmware has limits (32 at least in some versions) for number
+ * of BSSes in scan results. Extend this limit by using local BSS list.
+ */
+ list_for_each(ptr, &local->bss_list) {
+ struct hostap_bss_info *bss;
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ if (bss->included)
+ continue;
+ current_ev = __prism2_translate_scan(local, NULL, bss,
+ current_ev, end_buf);
+ /* Check if there is space for one more entry */
+ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a bigger buffer */
+ spin_unlock_bh(&local->lock);
+ return -E2BIG;
+ }
+ }
+
+ spin_unlock_bh(&local->lock);
+
+ return current_ev - buffer;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+static inline int prism2_ioctl_giwscan_sta(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+#ifdef PRISM2_NO_STATION_MODES
+ return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ /* Wait until the scan is finished. We can probably do better
+ * than that - Jean II */
+ if (local->scan_timestamp &&
+ time_before(jiffies, local->scan_timestamp + 3 * HZ)) {
+ /* Important note : we don't want to block the caller
+ * until results are ready for various reasons.
+ * First, managing wait queues is complex and racy
+ * (there may be multiple simultaneous callers).
+ * Second, we grab some rtnetlink lock before comming
+ * here (in dev_ioctl()).
+ * Third, the caller can wait on the Wireless Event
+ * - Jean II */
+ return -EAGAIN;
+ }
+ local->scan_timestamp = 0;
+
+ res = prism2_translate_scan(local, extra, data->length);
+
+ if (res >= 0) {
+ data->length = res;
+ return 0;
+ } else {
+ data->length = 0;
+ return res;
+ }
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_giwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int res;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ /* In MASTER mode, it doesn't make sense to go around
+ * scanning the frequencies and make the stations we serve
+ * wait when what the user is really interested about is the
+ * list of stations and access points we are talking to.
+ * So, just extract results from our cache...
+ * Jean II */
+
+ /* Translate to WE format */
+ res = prism2_ap_translate_scan(dev, extra);
+ if (res >= 0) {
+ printk(KERN_DEBUG "Scan result translation succeeded "
+ "(length=%d)\n", res);
+ data->length = res;
+ return 0;
+ } else {
+ printk(KERN_DEBUG
+ "Scan result translation failed (res=%d)\n",
+ res);
+ data->length = 0;
+ return res;
+ }
+ } else {
+ /* Station mode */
+ return prism2_ioctl_giwscan_sta(dev, info, data, extra);
+ }
+}
+
+
+static const struct iw_priv_args prism2_priv[] = {
+ { PRISM2_IOCTL_MONITOR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" },
+ { PRISM2_IOCTL_READMIF,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" },
+ { PRISM2_IOCTL_WRITEMIF,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" },
+ { PRISM2_IOCTL_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" },
+ { PRISM2_IOCTL_INQUIRE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" },
+ { PRISM2_IOCTL_SET_RID_WORD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" },
+ { PRISM2_IOCTL_MACCMD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" },
+ { PRISM2_IOCTL_WDS_ADD,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" },
+ { PRISM2_IOCTL_WDS_DEL,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" },
+ { PRISM2_IOCTL_ADDMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" },
+ { PRISM2_IOCTL_DELMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" },
+ { PRISM2_IOCTL_KICKMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" },
+ /* --- raw access to sub-ioctls --- */
+ { PRISM2_IOCTL_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" },
+ { PRISM2_IOCTL_GET_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" },
+ /* --- sub-ioctls handlers --- */
+ { PRISM2_IOCTL_PRISM2_PARAM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
+ { PRISM2_IOCTL_GET_PRISM2_PARAM,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
+ /* --- sub-ioctls definitions --- */
+ { PRISM2_PARAM_TXRATECTRL,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" },
+ { PRISM2_PARAM_TXRATECTRL,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" },
+ { PRISM2_PARAM_BEACON_INT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" },
+ { PRISM2_PARAM_BEACON_INT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" },
+#ifndef PRISM2_NO_STATION_MODES
+ { PRISM2_PARAM_PSEUDO_IBSS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" },
+ { PRISM2_PARAM_PSEUDO_IBSS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" },
+#endif /* PRISM2_NO_STATION_MODES */
+ { PRISM2_PARAM_ALC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" },
+ { PRISM2_PARAM_ALC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" },
+ { PRISM2_PARAM_DUMP,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" },
+ { PRISM2_PARAM_DUMP,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" },
+ { PRISM2_PARAM_OTHER_AP_POLICY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" },
+ { PRISM2_PARAM_OTHER_AP_POLICY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" },
+ { PRISM2_PARAM_AP_MAX_INACTIVITY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" },
+ { PRISM2_PARAM_AP_MAX_INACTIVITY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" },
+ { PRISM2_PARAM_AP_BRIDGE_PACKETS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" },
+ { PRISM2_PARAM_AP_BRIDGE_PACKETS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" },
+ { PRISM2_PARAM_DTIM_PERIOD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" },
+ { PRISM2_PARAM_DTIM_PERIOD,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" },
+ { PRISM2_PARAM_AP_NULLFUNC_ACK,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" },
+ { PRISM2_PARAM_AP_NULLFUNC_ACK,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" },
+ { PRISM2_PARAM_MAX_WDS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" },
+ { PRISM2_PARAM_MAX_WDS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" },
+ { PRISM2_PARAM_AP_AUTOM_AP_WDS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" },
+ { PRISM2_PARAM_AP_AUTOM_AP_WDS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" },
+ { PRISM2_PARAM_AP_AUTH_ALGS,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" },
+ { PRISM2_PARAM_AP_AUTH_ALGS,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" },
+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" },
+ { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" },
+ { PRISM2_PARAM_HOST_ENCRYPT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" },
+ { PRISM2_PARAM_HOST_ENCRYPT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" },
+ { PRISM2_PARAM_HOST_DECRYPT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" },
+ { PRISM2_PARAM_HOST_DECRYPT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },
+#ifndef PRISM2_NO_STATION_MODES
+ { PRISM2_PARAM_HOST_ROAMING,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" },
+ { PRISM2_PARAM_HOST_ROAMING,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" },
+#endif /* PRISM2_NO_STATION_MODES */
+ { PRISM2_PARAM_BCRX_STA_KEY,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" },
+ { PRISM2_PARAM_BCRX_STA_KEY,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" },
+ { PRISM2_PARAM_IEEE_802_1X,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" },
+ { PRISM2_PARAM_IEEE_802_1X,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" },
+ { PRISM2_PARAM_ANTSEL_TX,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" },
+ { PRISM2_PARAM_ANTSEL_TX,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" },
+ { PRISM2_PARAM_ANTSEL_RX,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" },
+ { PRISM2_PARAM_ANTSEL_RX,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" },
+ { PRISM2_PARAM_MONITOR_TYPE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" },
+ { PRISM2_PARAM_MONITOR_TYPE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" },
+ { PRISM2_PARAM_WDS_TYPE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" },
+ { PRISM2_PARAM_WDS_TYPE,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" },
+ { PRISM2_PARAM_HOSTSCAN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" },
+ { PRISM2_PARAM_HOSTSCAN,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" },
+ { PRISM2_PARAM_AP_SCAN,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" },
+ { PRISM2_PARAM_AP_SCAN,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" },
+ { PRISM2_PARAM_ENH_SEC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" },
+ { PRISM2_PARAM_ENH_SEC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" },
+#ifdef PRISM2_IO_DEBUG
+ { PRISM2_PARAM_IO_DEBUG,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" },
+ { PRISM2_PARAM_IO_DEBUG,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" },
+#endif /* PRISM2_IO_DEBUG */
+ { PRISM2_PARAM_BASIC_RATES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" },
+ { PRISM2_PARAM_BASIC_RATES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" },
+ { PRISM2_PARAM_OPER_RATES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" },
+ { PRISM2_PARAM_OPER_RATES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" },
+ { PRISM2_PARAM_HOSTAPD,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" },
+ { PRISM2_PARAM_HOSTAPD,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" },
+ { PRISM2_PARAM_HOSTAPD_STA,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd_sta" },
+ { PRISM2_PARAM_HOSTAPD_STA,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd_sta" },
+ { PRISM2_PARAM_WPA,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wpa" },
+ { PRISM2_PARAM_WPA,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwpa" },
+ { PRISM2_PARAM_PRIVACY_INVOKED,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "privacy_invoked" },
+ { PRISM2_PARAM_PRIVACY_INVOKED,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprivacy_invo" },
+ { PRISM2_PARAM_TKIP_COUNTERMEASURES,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tkip_countermea" },
+ { PRISM2_PARAM_TKIP_COUNTERMEASURES,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettkip_counter" },
+ { PRISM2_PARAM_DROP_UNENCRYPTED,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "drop_unencrypte" },
+ { PRISM2_PARAM_DROP_UNENCRYPTED,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdrop_unencry" },
+ { PRISM2_PARAM_SCAN_CHANNEL_MASK,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "scan_channels" },
+ { PRISM2_PARAM_SCAN_CHANNEL_MASK,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getscan_channel" },
+};
+
+
+static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int *i = (int *) extra;
+ int param = *i;
+ int value = *(i + 1);
+ int ret = 0;
+ u16 val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (param) {
+ case PRISM2_PARAM_TXRATECTRL:
+ local->fw_tx_rate_control = value;
+ break;
+
+ case PRISM2_PARAM_BEACON_INT:
+ if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ else
+ local->beacon_int = value;
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case PRISM2_PARAM_PSEUDO_IBSS:
+ if (value == local->pseudo_adhoc)
+ break;
+
+ if (value != 0 && value != 1) {
+ ret = -EINVAL;
+ break;
+ }
+
+ printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n",
+ dev->name, local->pseudo_adhoc, value);
+ local->pseudo_adhoc = value;
+ if (local->iw_mode != IW_MODE_ADHOC)
+ break;
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ hostap_get_porttype(local))) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ case PRISM2_PARAM_ALC:
+ printk(KERN_DEBUG "%s: %s ALC\n", dev->name,
+ value == 0 ? "Disabling" : "Enabling");
+ val = HFA384X_TEST_CFG_BIT_ALC;
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+ (HFA384X_TEST_CFG_BITS << 8),
+ value == 0 ? 0 : 1, &val, NULL);
+ break;
+
+ case PRISM2_PARAM_DUMP:
+ local->frame_dump = value;
+ break;
+
+ case PRISM2_PARAM_OTHER_AP_POLICY:
+ if (value < 0 || value > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ if (local->ap != NULL)
+ local->ap->ap_policy = value;
+ break;
+
+ case PRISM2_PARAM_AP_MAX_INACTIVITY:
+ if (value < 0 || value > 7 * 24 * 60 * 60) {
+ ret = -EINVAL;
+ break;
+ }
+ if (local->ap != NULL)
+ local->ap->max_inactivity = value * HZ;
+ break;
+
+ case PRISM2_PARAM_AP_BRIDGE_PACKETS:
+ if (local->ap != NULL)
+ local->ap->bridge_packets = value;
+ break;
+
+ case PRISM2_PARAM_DTIM_PERIOD:
+ if (value < 0 || value > 65535) {
+ ret = -EINVAL;
+ break;
+ }
+ if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value)
+ || local->func->reset_port(dev))
+ ret = -EINVAL;
+ else
+ local->dtim_period = value;
+ break;
+
+ case PRISM2_PARAM_AP_NULLFUNC_ACK:
+ if (local->ap != NULL)
+ local->ap->nullfunc_ack = value;
+ break;
+
+ case PRISM2_PARAM_MAX_WDS:
+ local->wds_max_connections = value;
+ break;
+
+ case PRISM2_PARAM_AP_AUTOM_AP_WDS:
+ if (local->ap != NULL) {
+ if (!local->ap->autom_ap_wds && value) {
+ /* add WDS link to all APs in STA table */
+ hostap_add_wds_links(local);
+ }
+ local->ap->autom_ap_wds = value;
+ }
+ break;
+
+ case PRISM2_PARAM_AP_AUTH_ALGS:
+ local->auth_algs = value;
+ if (hostap_set_auth_algs(local))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
+ local->monitor_allow_fcserr = value;
+ break;
+
+ case PRISM2_PARAM_HOST_ENCRYPT:
+ local->host_encrypt = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_HOST_DECRYPT:
+ local->host_decrypt = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+#ifndef PRISM2_NO_STATION_MODES
+ case PRISM2_PARAM_HOST_ROAMING:
+ if (value < 0 || value > 2) {
+ ret = -EINVAL;
+ break;
+ }
+ local->host_roaming = value;
+ if (hostap_set_roaming(local) || local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+#endif /* PRISM2_NO_STATION_MODES */
+
+ case PRISM2_PARAM_BCRX_STA_KEY:
+ local->bcrx_sta_key = value;
+ break;
+
+ case PRISM2_PARAM_IEEE_802_1X:
+ local->ieee_802_1x = value;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_TX:
+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
+ ret = -EINVAL;
+ break;
+ }
+ local->antsel_tx = value;
+ hostap_set_antsel(local);
+ break;
+
+ case PRISM2_PARAM_ANTSEL_RX:
+ if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
+ ret = -EINVAL;
+ break;
+ }
+ local->antsel_rx = value;
+ hostap_set_antsel(local);
+ break;
+
+ case PRISM2_PARAM_MONITOR_TYPE:
+ if (value != PRISM2_MONITOR_80211 &&
+ value != PRISM2_MONITOR_CAPHDR &&
+ value != PRISM2_MONITOR_PRISM) {
+ ret = -EINVAL;
+ break;
+ }
+ local->monitor_type = value;
+ if (local->iw_mode == IW_MODE_MONITOR)
+ hostap_monitor_set_type(local);
+ break;
+
+ case PRISM2_PARAM_WDS_TYPE:
+ local->wds_type = value;
+ break;
+
+ case PRISM2_PARAM_HOSTSCAN:
+ {
+ struct hfa384x_hostscan_request scan_req;
+ u16 rate;
+
+ memset(&scan_req, 0, sizeof(scan_req));
+ scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
+ switch (value) {
+ case 1: rate = HFA384X_RATES_1MBPS; break;
+ case 2: rate = HFA384X_RATES_2MBPS; break;
+ case 3: rate = HFA384X_RATES_5MBPS; break;
+ case 4: rate = HFA384X_RATES_11MBPS; break;
+ default: rate = HFA384X_RATES_1MBPS; break;
+ }
+ scan_req.txrate = cpu_to_le16(rate);
+ /* leave SSID empty to accept all SSIDs */
+
+ if (local->iw_mode == IW_MODE_MASTER) {
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_BSS) ||
+ local->func->reset_port(dev))
+ printk(KERN_DEBUG "Leaving Host AP mode "
+ "for HostScan failed\n");
+ }
+
+ if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
+ sizeof(scan_req))) {
+ printk(KERN_DEBUG "HOSTSCAN failed\n");
+ ret = -EINVAL;
+ }
+ if (local->iw_mode == IW_MODE_MASTER) {
+ wait_queue_t __wait;
+ init_waitqueue_entry(&__wait, current);
+ add_wait_queue(&local->hostscan_wq, &__wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ if (signal_pending(current))
+ ret = -EINTR;
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&local->hostscan_wq, &__wait);
+
+ if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+ HFA384X_PORTTYPE_HOSTAP) ||
+ local->func->reset_port(dev))
+ printk(KERN_DEBUG "Returning to Host AP mode "
+ "after HostScan failed\n");
+ }
+ break;
+ }
+
+ case PRISM2_PARAM_AP_SCAN:
+ local->passive_scan_interval = value;
+ if (timer_pending(&local->passive_scan_timer))
+ del_timer(&local->passive_scan_timer);
+ if (value > 0) {
+ local->passive_scan_timer.expires = jiffies +
+ local->passive_scan_interval * HZ;
+ add_timer(&local->passive_scan_timer);
+ }
+ break;
+
+ case PRISM2_PARAM_ENH_SEC:
+ if (value < 0 || value > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ local->enh_sec = value;
+ if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY,
+ local->enh_sec) ||
+ local->func->reset_port(dev)) {
+ printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w "
+ "1.6.3 or newer\n", dev->name);
+ ret = -EOPNOTSUPP;
+ }
+ break;
+
+#ifdef PRISM2_IO_DEBUG
+ case PRISM2_PARAM_IO_DEBUG:
+ local->io_debug_enabled = value;
+ break;
+#endif /* PRISM2_IO_DEBUG */
+
+ case PRISM2_PARAM_BASIC_RATES:
+ if ((value & local->tx_rate_control) != value || value == 0) {
+ printk(KERN_INFO "%s: invalid basic rate set - basic "
+ "rates must be in supported rate set\n",
+ dev->name);
+ ret = -EINVAL;
+ break;
+ }
+ local->basic_rates = value;
+ if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
+ local->basic_rates) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_OPER_RATES:
+ local->tx_rate_control = value;
+ if (hostap_set_rate(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD:
+ ret = hostap_set_hostapd(local, value, 1);
+ break;
+
+ case PRISM2_PARAM_HOSTAPD_STA:
+ ret = hostap_set_hostapd_sta(local, value, 1);
+ break;
+
+ case PRISM2_PARAM_WPA:
+ local->wpa = value;
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ ret = -EOPNOTSUPP;
+ else if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
+ value ? 1 : 0))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_PRIVACY_INVOKED:
+ local->privacy_invoked = value;
+ if (hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ ret = -EINVAL;
+ break;
+
+ case PRISM2_PARAM_TKIP_COUNTERMEASURES:
+ local->tkip_countermeasures = value;
+ break;
+
+ case PRISM2_PARAM_DROP_UNENCRYPTED:
+ local->drop_unencrypted = value;
+ break;
+
+ case PRISM2_PARAM_SCAN_CHANNEL_MASK:
+ local->scan_channel_mask = value;
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n",
+ dev->name, param);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int *param = (int *) extra;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (*param) {
+ case PRISM2_PARAM_TXRATECTRL:
+ *param = local->fw_tx_rate_control;
+ break;
+
+ case PRISM2_PARAM_BEACON_INT:
+ *param = local->beacon_int;
+ break;
+
+ case PRISM2_PARAM_PSEUDO_IBSS:
+ *param = local->pseudo_adhoc;
+ break;
+
+ case PRISM2_PARAM_ALC:
+ ret = -EOPNOTSUPP; /* FIX */
+ break;
+
+ case PRISM2_PARAM_DUMP:
+ *param = local->frame_dump;
+ break;
+
+ case PRISM2_PARAM_OTHER_AP_POLICY:
+ if (local->ap != NULL)
+ *param = local->ap->ap_policy;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_MAX_INACTIVITY:
+ if (local->ap != NULL)
+ *param = local->ap->max_inactivity / HZ;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_BRIDGE_PACKETS:
+ if (local->ap != NULL)
+ *param = local->ap->bridge_packets;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_DTIM_PERIOD:
+ *param = local->dtim_period;
+ break;
+
+ case PRISM2_PARAM_AP_NULLFUNC_ACK:
+ if (local->ap != NULL)
+ *param = local->ap->nullfunc_ack;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_MAX_WDS:
+ *param = local->wds_max_connections;
+ break;
+
+ case PRISM2_PARAM_AP_AUTOM_AP_WDS:
+ if (local->ap != NULL)
+ *param = local->ap->autom_ap_wds;
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_AUTH_ALGS:
+ *param = local->auth_algs;
+ break;
+
+ case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
+ *param = local->monitor_allow_fcserr;
+ break;
+
+ case PRISM2_PARAM_HOST_ENCRYPT:
+ *param = local->host_encrypt;
+ break;
+
+ case PRISM2_PARAM_HOST_DECRYPT:
+ *param = local->host_decrypt;
+ break;
+
+ case PRISM2_PARAM_HOST_ROAMING:
+ *param = local->host_roaming;
+ break;
+
+ case PRISM2_PARAM_BCRX_STA_KEY:
+ *param = local->bcrx_sta_key;
+ break;
+
+ case PRISM2_PARAM_IEEE_802_1X:
+ *param = local->ieee_802_1x;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_TX:
+ *param = local->antsel_tx;
+ break;
+
+ case PRISM2_PARAM_ANTSEL_RX:
+ *param = local->antsel_rx;
+ break;
+
+ case PRISM2_PARAM_MONITOR_TYPE:
+ *param = local->monitor_type;
+ break;
+
+ case PRISM2_PARAM_WDS_TYPE:
+ *param = local->wds_type;
+ break;
+
+ case PRISM2_PARAM_HOSTSCAN:
+ ret = -EOPNOTSUPP;
+ break;
+
+ case PRISM2_PARAM_AP_SCAN:
+ *param = local->passive_scan_interval;
+ break;
+
+ case PRISM2_PARAM_ENH_SEC:
+ *param = local->enh_sec;
+ break;
+
+#ifdef PRISM2_IO_DEBUG
+ case PRISM2_PARAM_IO_DEBUG:
+ *param = local->io_debug_enabled;
+ break;
+#endif /* PRISM2_IO_DEBUG */
+
+ case PRISM2_PARAM_BASIC_RATES:
+ *param = local->basic_rates;
+ break;
+
+ case PRISM2_PARAM_OPER_RATES:
+ *param = local->tx_rate_control;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD:
+ *param = local->hostapd;
+ break;
+
+ case PRISM2_PARAM_HOSTAPD_STA:
+ *param = local->hostapd_sta;
+ break;
+
+ case PRISM2_PARAM_WPA:
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ ret = -EOPNOTSUPP;
+ *param = local->wpa;
+ break;
+
+ case PRISM2_PARAM_PRIVACY_INVOKED:
+ *param = local->privacy_invoked;
+ break;
+
+ case PRISM2_PARAM_TKIP_COUNTERMEASURES:
+ *param = local->tkip_countermeasures;
+ break;
+
+ case PRISM2_PARAM_DROP_UNENCRYPTED:
+ *param = local->drop_unencrypted;
+ break;
+
+ case PRISM2_PARAM_SCAN_CHANNEL_MASK:
+ *param = local->scan_channel_mask;
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n",
+ dev->name, *param);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_readmif(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 resp0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL,
+ &resp0))
+ return -EOPNOTSUPP;
+ else
+ *extra = resp0;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_writemif(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu, char *extra)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ u16 cr, val;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ cr = *extra;
+ val = *(extra + 1);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+ u32 mode;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
+ "- update software to use iwconfig mode monitor\n",
+ dev->name, current->pid, current->comm);
+
+ /* Backward compatibility code - this can be removed at some point */
+
+ if (*i == 0) {
+ /* Disable monitor mode - old mode was not saved, so go to
+ * Master mode */
+ mode = IW_MODE_MASTER;
+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
+ } else if (*i == 1) {
+ /* netlink socket mode is not supported anymore since it did
+ * not separate different devices from each other and was not
+ * best method for delivering large amount of packets to
+ * user space */
+ ret = -EOPNOTSUPP;
+ } else if (*i == 2 || *i == 3) {
+ switch (*i) {
+ case 2:
+ local->monitor_type = PRISM2_MONITOR_80211;
+ break;
+ case 3:
+ local->monitor_type = PRISM2_MONITOR_PRISM;
+ break;
+ }
+ mode = IW_MODE_MONITOR;
+ ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
+ hostap_monitor_mode_enable(local);
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+
+static int prism2_ioctl_priv_reset(struct net_device *dev, int *i)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i);
+ switch (*i) {
+ case 0:
+ /* Disable and enable card */
+ local->func->hw_shutdown(dev, 1);
+ local->func->hw_config(dev, 0);
+ break;
+
+ case 1:
+ /* COR sreset */
+ local->func->hw_reset(dev);
+ break;
+
+ case 2:
+ /* Disable and enable port 0 */
+ local->func->reset_port(dev);
+ break;
+
+ case 3:
+ prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
+ if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL,
+ NULL))
+ return -EINVAL;
+ break;
+
+ case 4:
+ if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL,
+ NULL))
+ return -EINVAL;
+ break;
+
+ default:
+ printk(KERN_DEBUG "Unknown reset request %d\n", *i);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+
+static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i)
+{
+ int rid = *i;
+ int value = *(i + 1);
+
+ printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value);
+
+ if (hostap_set_word(dev, rid, value))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd)
+{
+ int ret = 0;
+
+ switch (*cmd) {
+ case AP_MAC_CMD_POLICY_OPEN:
+ local->ap->mac_restrictions.policy = MAC_POLICY_OPEN;
+ break;
+ case AP_MAC_CMD_POLICY_ALLOW:
+ local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW;
+ break;
+ case AP_MAC_CMD_POLICY_DENY:
+ local->ap->mac_restrictions.policy = MAC_POLICY_DENY;
+ break;
+ case AP_MAC_CMD_FLUSH:
+ ap_control_flush_macs(&local->ap->mac_restrictions);
+ break;
+ case AP_MAC_CMD_KICKALL:
+ ap_control_kickall(local->ap);
+ hostap_deauth_all_stas(local->dev, local->ap, 0);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
+{
+ struct prism2_download_param *param;
+ int ret = 0;
+
+ if (p->length < sizeof(struct prism2_download_param) ||
+ p->length > 1024 || !p->pointer)
+ return -EINVAL;
+
+ param = (struct prism2_download_param *)
+ kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (p->length < sizeof(struct prism2_download_param) +
+ param->num_areas * sizeof(struct prism2_download_area)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = local->func->download(local, param);
+
+ out:
+ kfree(param);
+ return ret;
+}
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+
+static int prism2_set_genericelement(struct net_device *dev, u8 *elem,
+ size_t len)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ u8 *buf;
+
+ /*
+ * Add 16-bit length in the beginning of the buffer because Prism2 RID
+ * includes it.
+ */
+ buf = kmalloc(len + 2, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ *((u16 *) buf) = cpu_to_le16(len);
+ memcpy(buf + 2, elem, len);
+
+ kfree(local->generic_elem);
+ local->generic_elem = buf;
+ local->generic_elem_len = len + 2;
+
+ return local->func->set_rid(local->dev, HFA384X_RID_GENERICELEMENT,
+ buf, len + 2);
+}
+
+
+static int prism2_ioctl_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * Host AP driver does not use these parameters and allows
+ * wpa_supplicant to control them internally.
+ */
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ local->tkip_countermeasures = data->value;
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ local->drop_unencrypted = data->value;
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ local->auth_algs = data->value;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ if (data->value == 0) {
+ local->wpa = 0;
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ break;
+ prism2_set_genericelement(dev, "", 0);
+ local->host_roaming = 0;
+ local->privacy_invoked = 0;
+ if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
+ 0) ||
+ hostap_set_roaming(local) ||
+ hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+ break;
+ }
+ if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
+ return -EOPNOTSUPP;
+ local->host_roaming = 2;
+ local->privacy_invoked = 1;
+ local->wpa = 1;
+ if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1) ||
+ hostap_set_roaming(local) ||
+ hostap_set_encryption(local) ||
+ local->func->reset_port(dev))
+ return -EINVAL;
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ local->ieee_802_1x = data->value;
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
+ local->privacy_invoked = data->value;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * Host AP driver does not use these parameters and allows
+ * wpa_supplicant to control them internally.
+ */
+ return -EOPNOTSUPP;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ data->value = local->tkip_countermeasures;
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ data->value = local->drop_unencrypted;
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ data->value = local->auth_algs;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ data->value = local->wpa;
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ data->value = local->ieee_802_1x;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+static int prism2_ioctl_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+ int i, ret = 0;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ u8 *addr;
+ const char *alg, *module;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i > WEP_KEYS)
+ return -EINVAL;
+ if (i < 1 || i > WEP_KEYS)
+ i = local->tx_keyidx;
+ else
+ i--;
+ if (i < 0 || i >= WEP_KEYS)
+ return -EINVAL;
+
+ addr = ext->addr.sa_data;
+ if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
+ addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
+ sta_ptr = NULL;
+ crypt = &local->crypt[i];
+ } else {
+ if (i != 0)
+ return -EINVAL;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
+ if (sta_ptr == NULL) {
+ if (local->iw_mode == IW_MODE_INFRA) {
+ /*
+ * TODO: add STA entry for the current AP so
+ * that unicast key can be used. For now, this
+ * is emulated by using default key idx 0.
+ */
+ i = 0;
+ crypt = &local->crypt[i];
+ } else
+ return -EINVAL;
+ }
+ }
+
+ if ((erq->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ if (*crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_WEP:
+ alg = "WEP";
+ module = "ieee80211_crypt_wep";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg = "TKIP";
+ module = "ieee80211_crypt_tkip";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg = "CCMP";
+ module = "ieee80211_crypt_ccmp";
+ break;
+ default:
+ printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
+ local->dev->name, ext->alg);
+ ret = -EOPNOTSUPP;
+ goto done;
+ }
+
+ ops = ieee80211_get_crypto_ops(alg);
+ if (ops == NULL) {
+ request_module(module);
+ ops = ieee80211_get_crypto_ops(alg);
+ }
+ if (ops == NULL) {
+ printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
+ local->dev->name, alg);
+ ret = -EOPNOTSUPP;
+ goto done;
+ }
+
+ if (sta_ptr || ext->alg != IW_ENCODE_ALG_WEP) {
+ /*
+ * Per station encryption and other than WEP algorithms
+ * require host-based encryption, so force them on
+ * automatically.
+ */
+ local->host_decrypt = local->host_encrypt = 1;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ prism2_crypt_delayed_deinit(local, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ new_crypt->priv = new_crypt->ops->init(i);
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ /*
+ * TODO: if ext_flags does not have IW_ENCODE_EXT_RX_SEQ_VALID, the
+ * existing seq# should not be changed.
+ * TODO: if ext_flags has IW_ENCODE_EXT_TX_SEQ_VALID, next TX seq#
+ * should be changed to something else than zero.
+ */
+ if ((!(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) || ext->key_len > 0)
+ && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+ (*crypt)->priv) < 0) {
+ printk(KERN_DEBUG "%s: key setting failed\n",
+ local->dev->name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ if (!sta_ptr)
+ local->tx_keyidx = i;
+ else if (i) {
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+
+
+ if (sta_ptr == NULL && ext->key_len > 0) {
+ int first = 1, j;
+ for (j = 0; j < WEP_KEYS; j++) {
+ if (j != i && local->crypt[j]) {
+ first = 0;
+ break;
+ }
+ }
+ if (first)
+ local->tx_keyidx = i;
+ }
+
+ done:
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ local->open_wep = erq->flags & IW_ENCODE_OPEN;
+
+ /*
+ * Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode.
+ */
+ if (ret == 0 &&
+ (hostap_set_encryption(local) ||
+ (local->iw_mode != IW_MODE_INFRA &&
+ local->func->reset_port(local->dev))))
+ ret = -EINVAL;
+
+ return ret;
+}
+
+
+static int prism2_ioctl_giwencodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ int max_key_len, i;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+ u8 *addr;
+
+ max_key_len = erq->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ i = erq->flags & IW_ENCODE_INDEX;
+ if (i < 1 || i > WEP_KEYS)
+ i = local->tx_keyidx;
+ else
+ i--;
+
+ addr = ext->addr.sa_data;
+ if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
+ addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
+ sta_ptr = NULL;
+ crypt = &local->crypt[i];
+ } else {
+ i = 0;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
+ if (sta_ptr == NULL)
+ return -EINVAL;
+ }
+ erq->flags = i + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (*crypt == NULL || (*crypt)->ops == NULL) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (strcmp((*crypt)->ops->name, "WEP") == 0)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else if (strcmp((*crypt)->ops->name, "TKIP") == 0)
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ else if (strcmp((*crypt)->ops->name, "CCMP") == 0)
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ else
+ return -EINVAL;
+
+ if ((*crypt)->ops->get_key) {
+ ext->key_len =
+ (*crypt)->ops->get_key(ext->key,
+ max_key_len,
+ ext->tx_seq,
+ (*crypt)->priv);
+ if (ext->key_len &&
+ (ext->alg == IW_ENCODE_ALG_TKIP ||
+ ext->alg == IW_ENCODE_ALG_CCMP))
+ ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+ }
+ }
+
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_set_encryption(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int ret = 0;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len !=
+ (int) ((char *) param->u.crypt.key - (char *) param) +
+ param->u.crypt.key_len)
+ return -EINVAL;
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS)
+ return -EINVAL;
+ sta_ptr = NULL;
+ crypt = &local->crypt[param->u.crypt.idx];
+ } else {
+ if (param->u.crypt.idx)
+ return -EINVAL;
+ sta_ptr = ap_crypt_get_ptrs(
+ local->ap, param->sta_addr,
+ (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT),
+ &crypt);
+
+ if (sta_ptr == NULL) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+ return -EINVAL;
+ }
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0) {
+ if (crypt)
+ prism2_crypt_delayed_deinit(local, crypt);
+ goto done;
+ }
+
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+ request_module("ieee80211_crypt_wep");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ request_module("ieee80211_crypt_tkip");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ request_module("ieee80211_crypt_ccmp");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ }
+ if (ops == NULL) {
+ printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
+ local->dev->name, param->u.crypt.alg);
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* station based encryption and other than WEP algorithms require
+ * host-based encryption, so force them on automatically */
+ local->host_decrypt = local->host_encrypt = 1;
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ prism2_crypt_delayed_deinit(local, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ param->u.crypt.err =
+ HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) ||
+ param->u.crypt.key_len > 0) && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(param->u.crypt.key,
+ param->u.crypt.key_len, param->u.crypt.seq,
+ (*crypt)->priv) < 0) {
+ printk(KERN_DEBUG "%s: key setting failed\n",
+ local->dev->name);
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
+ if (!sta_ptr)
+ local->tx_keyidx = param->u.crypt.idx;
+ else if (param->u.crypt.idx) {
+ printk(KERN_DEBUG "%s: TX key idx setting failed\n",
+ local->dev->name);
+ param->u.crypt.err =
+ HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+
+ done:
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ /* Do not reset port0 if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. Prism2 documentation seem to require port reset
+ * after WEP configuration. However, keys are apparently changed at
+ * least in Managed mode. */
+ if (ret == 0 &&
+ (hostap_set_encryption(local) ||
+ (local->iw_mode != IW_MODE_INFRA &&
+ local->func->reset_port(local->dev)))) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED;
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+static int prism2_ioctl_get_encryption(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ struct ieee80211_crypt_data **crypt;
+ void *sta_ptr;
+ int max_key_len;
+
+ param->u.crypt.err = 0;
+
+ max_key_len = param_len -
+ (int) ((char *) param->u.crypt.key - (char *) param);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ sta_ptr = NULL;
+ if (param->u.crypt.idx >= WEP_KEYS)
+ param->u.crypt.idx = local->tx_keyidx;
+ crypt = &local->crypt[param->u.crypt.idx];
+ } else {
+ param->u.crypt.idx = 0;
+ sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
+ &crypt);
+
+ if (sta_ptr == NULL) {
+ param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
+ return -EINVAL;
+ }
+ }
+
+ if (*crypt == NULL || (*crypt)->ops == NULL) {
+ memcpy(param->u.crypt.alg, "none", 5);
+ param->u.crypt.key_len = 0;
+ param->u.crypt.idx = 0xff;
+ } else {
+ strncpy(param->u.crypt.alg, (*crypt)->ops->name,
+ HOSTAP_CRYPT_ALG_NAME_LEN);
+ param->u.crypt.key_len = 0;
+
+ memset(param->u.crypt.seq, 0, 8);
+ if ((*crypt)->ops->get_key) {
+ param->u.crypt.key_len =
+ (*crypt)->ops->get_key(param->u.crypt.key,
+ max_key_len,
+ param->u.crypt.seq,
+ (*crypt)->priv);
+ }
+ }
+
+ if (sta_ptr)
+ hostap_handle_sta_release(sta_ptr);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_get_rid(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len, res;
+
+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
+ if (max_len < 0)
+ return -EINVAL;
+
+ res = local->func->get_rid(local->dev, param->u.rid.rid,
+ param->u.rid.data, param->u.rid.len, 0);
+ if (res >= 0) {
+ param->u.rid.len = res;
+ return 0;
+ }
+
+ return res;
+}
+
+
+static int prism2_ioctl_set_rid(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len;
+
+ max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
+ if (max_len < 0 || max_len < param->u.rid.len)
+ return -EINVAL;
+
+ return local->func->set_rid(local->dev, param->u.rid.rid,
+ param->u.rid.data, param->u.rid.len);
+}
+
+
+static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ printk(KERN_DEBUG "%ssta: associated as client with AP " MACSTR "\n",
+ local->dev->name, MAC2STR(param->sta_addr));
+ memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
+ return 0;
+}
+
+
+static int prism2_ioctl_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ return prism2_set_genericelement(dev, extra, data->length);
+}
+
+
+static int prism2_ioctl_giwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ int len = local->generic_elem_len - 2;
+
+ if (len <= 0 || local->generic_elem == NULL) {
+ data->length = 0;
+ return 0;
+ }
+
+ if (data->length < len)
+ return -E2BIG;
+
+ data->length = len;
+ memcpy(extra, local->generic_elem + 2, len);
+
+ return 0;
+}
+
+
+static int prism2_ioctl_set_generic_element(local_info_t *local,
+ struct prism2_hostapd_param *param,
+ int param_len)
+{
+ int max_len, len;
+
+ len = param->u.generic_elem.len;
+ max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
+ if (max_len < 0 || max_len < len)
+ return -EINVAL;
+
+ return prism2_set_genericelement(local->dev,
+ param->u.generic_elem.data, len);
+}
+
+
+static int prism2_ioctl_siwmlme(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct hostap_interface *iface = dev->priv;
+ local_info_t *local = iface->local;
+ struct iw_mlme *mlme = (struct iw_mlme *) extra;
+ u16 reason;
+
+ reason = cpu_to_le16(mlme->reason_code);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
+ IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ case IW_MLME_DISASSOC:
+ return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
+ IEEE80211_STYPE_DISASSOC,
+ (u8 *) &reason, 2);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+
+static int prism2_ioctl_mlme(local_info_t *local,
+ struct prism2_hostapd_param *param)
+{
+ u16 reason;
+
+ reason = cpu_to_le16(param->u.mlme.reason_code);
+ switch (param->u.mlme.cmd) {
+ case MLME_STA_DEAUTH:
+ return prism2_sta_send_mgmt(local, param->sta_addr,
+ IEEE80211_STYPE_DEAUTH,
+ (u8 *) &reason, 2);
+ case MLME_STA_DISASSOC:
+ return prism2_sta_send_mgmt(local, param->sta_addr,
+ IEEE80211_STYPE_DISASSOC,
+ (u8 *) &reason, 2);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+
+static int prism2_ioctl_scan_req(local_info_t *local,
+ struct prism2_hostapd_param *param)
+{
+#ifndef PRISM2_NO_STATION_MODES
+ if ((local->iw_mode != IW_MODE_INFRA &&
+ local->iw_mode != IW_MODE_ADHOC) ||
+ (local->sta_fw_ver < PRISM2_FW_VER(1,3,1)))
+ return -EOPNOTSUPP;
+
+ if (!local->dev_enabled)
+ return -ENETDOWN;
+
+ return prism2_request_hostscan(local->dev, param->u.scan_req.ssid,
+ param->u.scan_req.ssid_len);
+#else /* PRISM2_NO_STATION_MODES */
+ return -EOPNOTSUPP;
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p)
+{
+ struct prism2_hostapd_param *param;
+ int ret = 0;
+ int ap_ioctl = 0;
+
+ if (p->length < sizeof(struct prism2_hostapd_param) ||
+ p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
+ return -EINVAL;
+
+ param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ switch (param->cmd) {
+ case PRISM2_SET_ENCRYPTION:
+ ret = prism2_ioctl_set_encryption(local, param, p->length);
+ break;
+ case PRISM2_GET_ENCRYPTION:
+ ret = prism2_ioctl_get_encryption(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_GET_RID:
+ ret = prism2_ioctl_get_rid(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_RID:
+ ret = prism2_ioctl_set_rid(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR:
+ ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length);
+ break;
+ case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT:
+ ret = prism2_ioctl_set_generic_element(local, param,
+ p->length);
+ break;
+ case PRISM2_HOSTAPD_MLME:
+ ret = prism2_ioctl_mlme(local, param);
+ break;
+ case PRISM2_HOSTAPD_SCAN_REQ:
+ ret = prism2_ioctl_scan_req(local, param);
+ break;
+ default:
+ ret = prism2_hostapd(local->ap, param);
+ ap_ioctl = 1;
+ break;
+ }
+
+ if (ret == 1 || !ap_ioctl) {
+ if (copy_to_user(p->pointer, param, p->length)) {
+ ret = -EFAULT;
+ goto out;
+ } else if (ap_ioctl)
+ ret = 0;
+ }
+
+ out:
+ kfree(param);
+ return ret;
+}
+
+
+static void prism2_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
+ strncpy(info->version, PRISM2_VERSION,
+ sizeof(info->version) - 1);
+ snprintf(info->fw_version, sizeof(info->fw_version) - 1,
+ "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
+ (local->sta_fw_ver >> 8) & 0xff,
+ local->sta_fw_ver & 0xff);
+}
+
+static struct ethtool_ops prism2_ethtool_ops = {
+ .get_drvinfo = prism2_get_drvinfo
+};
+
+
+/* Structures to export the Wireless Handlers */
+
+static const iw_handler prism2_handler[] =
+{
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) prism2_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) prism2_ioctl_siwfreq, /* SIOCSIWFREQ */
+ (iw_handler) prism2_ioctl_giwfreq, /* SIOCGIWFREQ */
+ (iw_handler) prism2_ioctl_siwmode, /* SIOCSIWMODE */
+ (iw_handler) prism2_ioctl_giwmode, /* SIOCGIWMODE */
+ (iw_handler) prism2_ioctl_siwsens, /* SIOCSIWSENS */
+ (iw_handler) prism2_ioctl_giwsens, /* SIOCGIWSENS */
+ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
+ (iw_handler) prism2_ioctl_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_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+ (iw_handler) prism2_ioctl_siwap, /* SIOCSIWAP */
+ (iw_handler) prism2_ioctl_giwap, /* SIOCGIWAP */
+ (iw_handler) prism2_ioctl_siwmlme, /* SIOCSIWMLME */
+ (iw_handler) prism2_ioctl_giwaplist, /* SIOCGIWAPLIST */
+ (iw_handler) prism2_ioctl_siwscan, /* SIOCSIWSCAN */
+ (iw_handler) prism2_ioctl_giwscan, /* SIOCGIWSCAN */
+ (iw_handler) prism2_ioctl_siwessid, /* SIOCSIWESSID */
+ (iw_handler) prism2_ioctl_giwessid, /* SIOCGIWESSID */
+ (iw_handler) prism2_ioctl_siwnickn, /* SIOCSIWNICKN */
+ (iw_handler) prism2_ioctl_giwnickn, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) prism2_ioctl_siwrate, /* SIOCSIWRATE */
+ (iw_handler) prism2_ioctl_giwrate, /* SIOCGIWRATE */
+ (iw_handler) prism2_ioctl_siwrts, /* SIOCSIWRTS */
+ (iw_handler) prism2_ioctl_giwrts, /* SIOCGIWRTS */
+ (iw_handler) prism2_ioctl_siwfrag, /* SIOCSIWFRAG */
+ (iw_handler) prism2_ioctl_giwfrag, /* SIOCGIWFRAG */
+ (iw_handler) prism2_ioctl_siwtxpow, /* SIOCSIWTXPOW */
+ (iw_handler) prism2_ioctl_giwtxpow, /* SIOCGIWTXPOW */
+ (iw_handler) prism2_ioctl_siwretry, /* SIOCSIWRETRY */
+ (iw_handler) prism2_ioctl_giwretry, /* SIOCGIWRETRY */
+ (iw_handler) prism2_ioctl_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) prism2_ioctl_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) prism2_ioctl_siwpower, /* SIOCSIWPOWER */
+ (iw_handler) prism2_ioctl_giwpower, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) prism2_ioctl_siwgenie, /* SIOCSIWGENIE */
+ (iw_handler) prism2_ioctl_giwgenie, /* SIOCGIWGENIE */
+ (iw_handler) prism2_ioctl_siwauth, /* SIOCSIWAUTH */
+ (iw_handler) prism2_ioctl_giwauth, /* SIOCGIWAUTH */
+ (iw_handler) prism2_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) prism2_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
+ (iw_handler) NULL, /* -- hole -- */
+};
+
+static const iw_handler prism2_private_handler[] =
+{ /* SIOCIWFIRSTPRIV + */
+ (iw_handler) prism2_ioctl_priv_prism2_param, /* 0 */
+ (iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */
+ (iw_handler) prism2_ioctl_priv_writemif, /* 2 */
+ (iw_handler) prism2_ioctl_priv_readmif, /* 3 */
+};
+
+static const struct iw_handler_def hostap_iw_handler_def =
+{
+ .num_standard = sizeof(prism2_handler) / sizeof(iw_handler),
+ .num_private = sizeof(prism2_private_handler) / sizeof(iw_handler),
+ .num_private_args = sizeof(prism2_priv) / sizeof(struct iw_priv_args),
+ .standard = (iw_handler *) prism2_handler,
+ .private = (iw_handler *) prism2_private_handler,
+ .private_args = (struct iw_priv_args *) prism2_priv,
+ .get_wireless_stats = hostap_get_wireless_stats,
+};
+
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct iwreq *wrq = (struct iwreq *) ifr;
+ struct hostap_interface *iface;
+ local_info_t *local;
+ int ret = 0;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ switch (cmd) {
+ /* Private ioctls (iwpriv) that have not yet been converted
+ * into new wireless extensions API */
+
+ case PRISM2_IOCTL_INQUIRE:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_MONITOR:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_RESET:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_WDS_ADD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1);
+ break;
+
+ case PRISM2_IOCTL_WDS_DEL:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0);
+ break;
+
+ case PRISM2_IOCTL_SET_RID_WORD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_set_rid_word(dev,
+ (int *) wrq->u.name);
+ break;
+
+#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
+ case PRISM2_IOCTL_MACCMD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name);
+ break;
+
+ case PRISM2_IOCTL_ADDMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_add_mac(&local->ap->mac_restrictions,
+ wrq->u.ap_addr.sa_data);
+ break;
+ case PRISM2_IOCTL_DELMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_del_mac(&local->ap->mac_restrictions,
+ wrq->u.ap_addr.sa_data);
+ break;
+ case PRISM2_IOCTL_KICKMAC:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = ap_control_kick_mac(local->ap, local->dev,
+ wrq->u.ap_addr.sa_data);
+ break;
+#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
+
+
+ /* Private ioctls that are not used with iwpriv;
+ * in SIOCDEVPRIVATE range */
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ case PRISM2_IOCTL_DOWNLOAD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_download(local, &wrq->u.data);
+ break;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+ case PRISM2_IOCTL_HOSTAPD:
+ if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
+ else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
new file mode 100644
index 000000000000..da0c80fb941c
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -0,0 +1,474 @@
+#define PRISM2_PCI
+
+/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
+ * driver patches from Reyk Floeter <reyk@vantronix.net> and
+ * Andy Warner <andyw@pobox.com> */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *dev_info = "hostap_pci";
+
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
+ "PCI cards.");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+/* struct local_info::hw_priv */
+struct hostap_pci_priv {
+ void __iomem *mem_start;
+};
+
+
+/* FIX: do we need mb/wmb/rmb with memory operations? */
+
+
+static struct pci_device_id prism2_pci_id_table[] __devinitdata = {
+ /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
+ { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
+ /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
+ { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
+ /* Samsung MagicLAN SWL-2210P */
+ { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ hw_priv = local->hw_priv;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ writeb(v, hw_priv->mem_start + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ hw_priv = local->hw_priv;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = readb(hw_priv->mem_start + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ hw_priv = local->hw_priv;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ writew(v, hw_priv->mem_start + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+ hw_priv = local->hw_priv;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = readw(hw_priv->mem_start + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v)))
+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a)))
+
+#else /* PRISM2_IO_DEBUG */
+
+static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ writeb(v, hw_priv->mem_start + a);
+}
+
+static inline u8 hfa384x_inb(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ return readb(hw_priv->mem_start + a);
+}
+
+static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ writew(v, hw_priv->mem_start + a);
+}
+
+static inline u16 hfa384x_inw(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+ return readw(hw_priv->mem_start + a);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw(dev, (a))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), cpu_to_le16((v)))
+#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw(dev, (a)))
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ for ( ; len > 1; len -= 2)
+ *pos++ = HFA384X_INW_DATA(d_off);
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ for ( ; len > 1; len -= 2)
+ HFA384X_OUTW_DATA(*pos++, d_off);
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+static void prism2_pci_cor_sreset(local_info_t *local)
+{
+ struct net_device *dev = local->dev;
+ u16 reg;
+
+ reg = HFA384X_INB(HFA384X_PCICOR_OFF);
+ printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
+
+ /* linux-wlan-ng uses extremely long hold and settle times for
+ * COR sreset. A comment in the driver code mentions that the long
+ * delays appear to be necessary. However, at least IBM 22P6901 seems
+ * to work fine with shorter delays.
+ *
+ * Longer delays can be configured by uncommenting following line: */
+/* #define PRISM2_PCI_USE_LONG_DELAYS */
+
+#ifdef PRISM2_PCI_USE_LONG_DELAYS
+ int i;
+
+ HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
+ mdelay(250);
+
+ HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
+ mdelay(500);
+
+ /* Wait for f/w to complete initialization (CMD:BUSY == 0) */
+ i = 2000000 / 10;
+ while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
+ udelay(10);
+
+#else /* PRISM2_PCI_USE_LONG_DELAYS */
+
+ HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
+ mdelay(2);
+ HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
+ mdelay(2);
+
+#endif /* PRISM2_PCI_USE_LONG_DELAYS */
+
+ if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
+ printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
+ }
+}
+
+
+static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
+{
+ struct net_device *dev = local->dev;
+
+ HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
+ mdelay(10);
+ HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
+ mdelay(10);
+ HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
+ mdelay(10);
+}
+
+
+static struct prism2_helper_functions prism2_pci_funcs =
+{
+ .card_present = NULL,
+ .cor_sreset = prism2_pci_cor_sreset,
+ .genesis_reset = prism2_pci_genesis_reset,
+ .hw_type = HOSTAP_HW_PCI,
+};
+
+
+static int prism2_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ unsigned long phymem;
+ void __iomem *mem = NULL;
+ local_info_t *local = NULL;
+ struct net_device *dev = NULL;
+ static int cards_found /* = 0 */;
+ int irq_registered = 0;
+ struct hostap_interface *iface;
+ struct hostap_pci_priv *hw_priv;
+
+ hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (hw_priv == NULL)
+ return -ENOMEM;
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ 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");
+ goto err_out_disable;
+ }
+
+ mem = ioremap(phymem, pci_resource_len(pdev, 0));
+ if (mem == NULL) {
+ printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
+ goto fail;
+ }
+
+ dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
+ &pdev->dev);
+ if (dev == NULL)
+ goto fail;
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ cards_found++;
+
+ dev->irq = pdev->irq;
+ hw_priv->mem_start = mem;
+
+ prism2_pci_cor_sreset(local);
+
+ pci_set_drvdata(pdev, dev);
+
+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
+ dev)) {
+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
+ goto fail;
+ } else
+ irq_registered = 1;
+
+ if (!local->pri_only && prism2_hw_config(dev, 1)) {
+ printk(KERN_DEBUG "%s: hardware initialization failed\n",
+ dev_info);
+ goto fail;
+ }
+
+ printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
+ "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
+
+ return hostap_hw_ready(dev);
+
+ fail:
+ if (irq_registered && dev)
+ free_irq(dev->irq, dev);
+
+ if (mem)
+ iounmap(mem);
+
+ release_mem_region(phymem, pci_resource_len(pdev, 0));
+
+ err_out_disable:
+ pci_disable_device(pdev);
+ prism2_free_local_data(dev);
+ kfree(hw_priv);
+
+ return -ENODEV;
+}
+
+
+static void prism2_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ void __iomem *mem_start;
+ struct hostap_pci_priv *hw_priv;
+
+ dev = pci_get_drvdata(pdev);
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+
+ /* Reset the hardware, and ensure interrupts are disabled. */
+ prism2_pci_cor_sreset(iface->local);
+ hfa384x_disable_interrupts(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ mem_start = hw_priv->mem_start;
+ prism2_free_local_data(dev);
+ kfree(hw_priv);
+
+ iounmap(mem_start);
+
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
+}
+
+
+#ifdef CONFIG_PM
+static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (netif_running(dev)) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ }
+ prism2_suspend(dev);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
+}
+
+static int prism2_pci_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ pci_enable_device(pdev);
+ pci_restore_state(pdev);
+ prism2_hw_config(dev, 0);
+ if (netif_running(dev)) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
+
+static struct pci_driver prism2_pci_drv_id = {
+ .name = "hostap_pci",
+ .id_table = prism2_pci_id_table,
+ .probe = prism2_pci_probe,
+ .remove = prism2_pci_remove,
+#ifdef CONFIG_PM
+ .suspend = prism2_pci_suspend,
+ .resume = prism2_pci_resume,
+#endif /* CONFIG_PM */
+ /* Linux 2.4.6 added save_state and enable_wake that are not used here
+ */
+};
+
+
+static int __init init_prism2_pci(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
+ return pci_register_driver(&prism2_pci_drv_id);
+}
+
+
+static void __exit exit_prism2_pci(void)
+{
+ pci_unregister_driver(&prism2_pci_drv_id);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_pci);
+module_exit(exit_prism2_pci);
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
new file mode 100644
index 000000000000..78d67b408b2f
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -0,0 +1,640 @@
+#define PRISM2_PLX
+
+/* Host AP driver's support for PC Cards on PCI adapters using PLX9052 is
+ * based on:
+ * - Host AP driver patch from james@madingley.org
+ * - linux-wlan-ng driver, Copyright (C) AbsoluteValue Systems, Inc.
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "hostap_wlan.h"
+
+
+static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
+static char *dev_info = "hostap_plx";
+
+
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
+ "cards (PLX).");
+MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PRISM2_VERSION);
+
+
+static int ignore_cis;
+module_param(ignore_cis, int, 0444);
+MODULE_PARM_DESC(ignore_cis, "Do not verify manfid information in CIS");
+
+
+/* struct local_info::hw_priv */
+struct hostap_plx_priv {
+ void __iomem *attr_mem;
+ unsigned int cor_offset;
+};
+
+
+#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */
+#define COR_SRESET 0x80
+#define COR_LEVLREQ 0x40
+#define COR_ENABLE_FUNC 0x01
+/* PCI Configuration Registers */
+#define PLX_PCIIPR 0x3d /* PCI Interrupt Pin */
+/* Local Configuration Registers */
+#define PLX_INTCSR 0x4c /* Interrupt Control/Status Register */
+#define PLX_INTCSR_PCI_INTEN BIT(6) /* PCI Interrupt Enable */
+#define PLX_CNTRL 0x50
+#define PLX_CNTRL_SERIAL_EEPROM_PRESENT BIT(28)
+
+
+#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID }
+
+static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
+ PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
+ PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
+ PLXDEV(0x126c, 0x8030, "Nortel emobility"),
+ PLXDEV(0x1385, 0x4100, "Netgear MA301"),
+ PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
+ PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
+ PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
+ PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
+ PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
+ PLXDEV(0x16ab, 0x1103, "Longshine 8031"),
+ PLXDEV(0x16ec, 0x3685, "US Robotics USR2415"),
+ PLXDEV(0xec80, 0xec00, "Belkin F5D6000"),
+ { 0 }
+};
+
+
+/* Array of known Prism2/2.5 PC Card manufactured ids. If your card's manfid
+ * is not listed here, you will need to add it here to get the driver
+ * initialized. */
+static struct prism2_plx_manfid {
+ u16 manfid1, manfid2;
+} prism2_plx_known_manfids[] = {
+ { 0x000b, 0x7110 } /* D-Link DWL-650 Rev. P1 */,
+ { 0x000b, 0x7300 } /* Philips 802.11b WLAN PCMCIA */,
+ { 0x0101, 0x0777 } /* 3Com AirConnect PCI 777A */,
+ { 0x0126, 0x8000 } /* Proxim RangeLAN */,
+ { 0x0138, 0x0002 } /* Compaq WL100 */,
+ { 0x0156, 0x0002 } /* Intersil Prism II Ref. Design (and others) */,
+ { 0x026f, 0x030b } /* Buffalo WLI-CF-S11G */,
+ { 0x0274, 0x1612 } /* Linksys WPC11 Ver 2.5 */,
+ { 0x0274, 0x1613 } /* Linksys WPC11 Ver 3 */,
+ { 0x028a, 0x0002 } /* D-Link DRC-650 */,
+ { 0x0250, 0x0002 } /* Samsung SWL2000-N */,
+ { 0xc250, 0x0002 } /* EMTAC A2424i */,
+ { 0xd601, 0x0002 } /* Z-Com XI300 */,
+ { 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */,
+ { 0, 0}
+};
+
+
+#ifdef PRISM2_IO_DEBUG
+
+static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
+ outb(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u8 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = inb(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
+ outw(v, dev->base_addr + a);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+ u16 v;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ v = inw(dev->base_addr + a);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
+ spin_unlock_irqrestore(&local->lock, flags);
+ return v;
+}
+
+static inline void hfa384x_outsw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc);
+ outsw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+static inline void hfa384x_insw_debug(struct net_device *dev, int a,
+ u8 *buf, int wc)
+{
+ struct hostap_interface *iface;
+ local_info_t *local;
+ unsigned long flags;
+
+ iface = netdev_priv(dev);
+ local = iface->local;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
+ insw(dev->base_addr + a, buf, wc);
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
+#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
+#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
+#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
+#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc))
+#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc))
+
+#else /* PRISM2_IO_DEBUG */
+
+#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a))
+#define HFA384X_INB(a) inb(dev->base_addr + (a))
+#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a))
+#define HFA384X_INW(a) inw(dev->base_addr + (a))
+#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc)
+#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc)
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
+ int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_INSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ *((char *) pos) = HFA384X_INB(d_off);
+
+ return 0;
+}
+
+
+static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
+{
+ u16 d_off;
+ u16 *pos;
+
+ d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
+ pos = (u16 *) buf;
+
+ if (len / 2)
+ HFA384X_OUTSW(d_off, buf, len / 2);
+ pos += len / 2;
+
+ if (len & 1)
+ HFA384X_OUTB(*((char *) pos), d_off);
+
+ return 0;
+}
+
+
+/* FIX: This might change at some point.. */
+#include "hostap_hw.c"
+
+
+static void prism2_plx_cor_sreset(local_info_t *local)
+{
+ unsigned char corsave;
+ struct hostap_plx_priv *hw_priv = local->hw_priv;
+
+ printk(KERN_DEBUG "%s: Doing reset via direct COR access.\n",
+ dev_info);
+
+ /* Set sreset bit of COR and clear it after hold time */
+
+ if (hw_priv->attr_mem == NULL) {
+ /* TMD7160 - COR at card's first I/O addr */
+ corsave = inb(hw_priv->cor_offset);
+ outb(corsave | COR_SRESET, hw_priv->cor_offset);
+ mdelay(2);
+ outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
+ mdelay(2);
+ } else {
+ /* PLX9052 */
+ corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
+ writeb(corsave | COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(2);
+ writeb(corsave & ~COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(2);
+ }
+}
+
+
+static void prism2_plx_genesis_reset(local_info_t *local, int hcr)
+{
+ unsigned char corsave;
+ struct hostap_plx_priv *hw_priv = local->hw_priv;
+
+ if (hw_priv->attr_mem == NULL) {
+ /* TMD7160 - COR at card's first I/O addr */
+ corsave = inb(hw_priv->cor_offset);
+ outb(corsave | COR_SRESET, hw_priv->cor_offset);
+ mdelay(10);
+ outb(hcr, hw_priv->cor_offset + 2);
+ mdelay(10);
+ outb(corsave & ~COR_SRESET, hw_priv->cor_offset);
+ mdelay(10);
+ } else {
+ /* PLX9052 */
+ corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset);
+ writeb(corsave | COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(10);
+ writeb(hcr, hw_priv->attr_mem + hw_priv->cor_offset + 2);
+ mdelay(10);
+ writeb(corsave & ~COR_SRESET,
+ hw_priv->attr_mem + hw_priv->cor_offset);
+ mdelay(10);
+ }
+}
+
+
+static struct prism2_helper_functions prism2_plx_funcs =
+{
+ .card_present = NULL,
+ .cor_sreset = prism2_plx_cor_sreset,
+ .genesis_reset = prism2_plx_genesis_reset,
+ .hw_type = HOSTAP_HW_PLX,
+};
+
+
+static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
+ unsigned int *cor_offset,
+ unsigned int *cor_index)
+{
+#define CISTPL_CONFIG 0x1A
+#define CISTPL_MANFID 0x20
+#define CISTPL_END 0xFF
+#define CIS_MAX_LEN 256
+ u8 *cis;
+ int i, pos;
+ unsigned int rmsz, rasz, manfid1, manfid2;
+ struct prism2_plx_manfid *manfid;
+
+ cis = kmalloc(CIS_MAX_LEN, GFP_KERNEL);
+ if (cis == NULL)
+ return -ENOMEM;
+
+ /* read CIS; it is in even offsets in the beginning of attr_mem */
+ for (i = 0; i < CIS_MAX_LEN; i++)
+ cis[i] = readb(attr_mem + 2 * i);
+ printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n",
+ dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]);
+
+ /* set reasonable defaults for Prism2 cards just in case CIS parsing
+ * fails */
+ *cor_offset = 0x3e0;
+ *cor_index = 0x01;
+ manfid1 = manfid2 = 0;
+
+ pos = 0;
+ while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) {
+ if (pos + cis[pos + 1] >= CIS_MAX_LEN)
+ goto cis_error;
+
+ switch (cis[pos]) {
+ case CISTPL_CONFIG:
+ if (cis[pos + 1] < 1)
+ goto cis_error;
+ rmsz = (cis[pos + 2] & 0x3c) >> 2;
+ rasz = cis[pos + 2] & 0x03;
+ if (4 + rasz + rmsz > cis[pos + 1])
+ goto cis_error;
+ *cor_index = cis[pos + 3] & 0x3F;
+ *cor_offset = 0;
+ for (i = 0; i <= rasz; i++)
+ *cor_offset += cis[pos + 4 + i] << (8 * i);
+ printk(KERN_DEBUG "%s: cor_index=0x%x "
+ "cor_offset=0x%x\n", dev_info,
+ *cor_index, *cor_offset);
+ if (*cor_offset > attr_len) {
+ printk(KERN_ERR "%s: COR offset not within "
+ "attr_mem\n", dev_info);
+ kfree(cis);
+ return -1;
+ }
+ break;
+
+ case CISTPL_MANFID:
+ if (cis[pos + 1] < 4)
+ goto cis_error;
+ manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
+ manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
+ printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n",
+ dev_info, manfid1, manfid2);
+ break;
+ }
+
+ pos += cis[pos + 1] + 2;
+ }
+
+ if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END)
+ goto cis_error;
+
+ for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++)
+ if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) {
+ kfree(cis);
+ return 0;
+ }
+
+ printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is"
+ " not supported card\n", dev_info, manfid1, manfid2);
+ goto fail;
+
+ cis_error:
+ printk(KERN_WARNING "%s: invalid CIS data\n", dev_info);
+
+ fail:
+ kfree(cis);
+ if (ignore_cis) {
+ printk(KERN_INFO "%s: ignore_cis parameter set - ignoring "
+ "errors during CIS verification\n", dev_info);
+ return 0;
+ }
+ return -1;
+}
+
+
+static int prism2_plx_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ unsigned int pccard_ioaddr, plx_ioaddr;
+ unsigned long pccard_attr_mem;
+ unsigned int pccard_attr_len;
+ void __iomem *attr_mem = NULL;
+ unsigned int cor_offset, cor_index;
+ u32 reg;
+ local_info_t *local = NULL;
+ struct net_device *dev = NULL;
+ struct hostap_interface *iface;
+ static int cards_found /* = 0 */;
+ int irq_registered = 0;
+ int tmd7160;
+ struct hostap_plx_priv *hw_priv;
+
+ hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
+ if (hw_priv == NULL)
+ return -ENOMEM;
+ memset(hw_priv, 0, sizeof(*hw_priv));
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ /* National Datacomm NCP130 based on TMD7160, not PLX9052. */
+ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131);
+
+ plx_ioaddr = pci_resource_start(pdev, 1);
+ pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3);
+
+ if (tmd7160) {
+ /* TMD7160 */
+ attr_mem = NULL; /* no access to PC Card attribute memory */
+
+ printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, "
+ "irq=%d, pccard_io=0x%x\n",
+ plx_ioaddr, pdev->irq, pccard_ioaddr);
+
+ cor_offset = plx_ioaddr;
+ cor_index = 0x04;
+
+ outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr);
+ mdelay(1);
+ reg = inb(plx_ioaddr);
+ if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) {
+ printk(KERN_ERR "%s: Error setting COR (expected="
+ "0x%02x, was=0x%02x)\n", dev_info,
+ cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg);
+ goto fail;
+ }
+ } else {
+ /* PLX9052 */
+ pccard_attr_mem = pci_resource_start(pdev, 2);
+ pccard_attr_len = pci_resource_len(pdev, 2);
+ if (pccard_attr_len < PLX_MIN_ATTR_LEN)
+ goto fail;
+
+
+ attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);
+ if (attr_mem == NULL) {
+ printk(KERN_ERR "%s: cannot remap attr_mem\n",
+ dev_info);
+ goto fail;
+ }
+
+ printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: "
+ "mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n",
+ pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr);
+
+ if (prism2_plx_check_cis(attr_mem, pccard_attr_len,
+ &cor_offset, &cor_index)) {
+ printk(KERN_INFO "Unknown PC Card CIS - not a "
+ "Prism2/2.5 card?\n");
+ goto fail;
+ }
+
+ printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 "
+ "adapter\n");
+
+ /* Write COR to enable PC Card */
+ writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC,
+ attr_mem + cor_offset);
+
+ /* Enable PCI interrupts if they are not already enabled */
+ reg = inl(plx_ioaddr + PLX_INTCSR);
+ printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg);
+ if (!(reg & PLX_INTCSR_PCI_INTEN)) {
+ outl(reg | PLX_INTCSR_PCI_INTEN,
+ plx_ioaddr + PLX_INTCSR);
+ if (!(inl(plx_ioaddr + PLX_INTCSR) &
+ PLX_INTCSR_PCI_INTEN)) {
+ printk(KERN_WARNING "%s: Could not enable "
+ "Local Interrupts\n", dev_info);
+ goto fail;
+ }
+ }
+
+ reg = inl(plx_ioaddr + PLX_CNTRL);
+ printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM "
+ "present=%d)\n",
+ reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0);
+ /* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is
+ * not present; but are there really such cards in use(?) */
+ }
+
+ dev = prism2_init_local_data(&prism2_plx_funcs, cards_found,
+ &pdev->dev);
+ if (dev == NULL)
+ goto fail;
+ iface = netdev_priv(dev);
+ local = iface->local;
+ local->hw_priv = hw_priv;
+ cards_found++;
+
+ dev->irq = pdev->irq;
+ dev->base_addr = pccard_ioaddr;
+ hw_priv->attr_mem = attr_mem;
+ hw_priv->cor_offset = cor_offset;
+
+ pci_set_drvdata(pdev, dev);
+
+ if (request_irq(dev->irq, prism2_interrupt, SA_SHIRQ, dev->name,
+ dev)) {
+ printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
+ goto fail;
+ } else
+ irq_registered = 1;
+
+ if (prism2_hw_config(dev, 1)) {
+ printk(KERN_DEBUG "%s: hardware initialization failed\n",
+ dev_info);
+ goto fail;
+ }
+
+ return hostap_hw_ready(dev);
+
+ fail:
+ prism2_free_local_data(dev);
+ kfree(hw_priv);
+
+ if (irq_registered && dev)
+ free_irq(dev->irq, dev);
+
+ if (attr_mem)
+ iounmap(attr_mem);
+
+ pci_disable_device(pdev);
+
+ return -ENODEV;
+}
+
+
+static void prism2_plx_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev;
+ struct hostap_interface *iface;
+ struct hostap_plx_priv *hw_priv;
+
+ dev = pci_get_drvdata(pdev);
+ iface = netdev_priv(dev);
+ hw_priv = iface->local->hw_priv;
+
+ /* Reset the hardware, and ensure interrupts are disabled. */
+ prism2_plx_cor_sreset(iface->local);
+ hfa384x_disable_interrupts(dev);
+
+ if (hw_priv->attr_mem)
+ iounmap(hw_priv->attr_mem);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ prism2_free_local_data(dev);
+ kfree(hw_priv);
+ pci_disable_device(pdev);
+}
+
+
+MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
+
+static struct pci_driver prism2_plx_drv_id = {
+ .name = "hostap_plx",
+ .id_table = prism2_plx_id_table,
+ .probe = prism2_plx_probe,
+ .remove = prism2_plx_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .enable_wake = NULL
+};
+
+
+static int __init init_prism2_plx(void)
+{
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
+ return pci_register_driver(&prism2_plx_drv_id);
+}
+
+
+static void __exit exit_prism2_plx(void)
+{
+ pci_unregister_driver(&prism2_plx_drv_id);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+
+
+module_init(init_prism2_plx);
+module_exit(exit_prism2_plx);
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
new file mode 100644
index 000000000000..a0a4cbd4937a
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -0,0 +1,448 @@
+/* /proc routines for Host AP driver */
+
+#define PROC_LIMIT (PAGE_SIZE - 80)
+
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+static int prism2_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int i;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
+ local->next_txfid, local->next_alloc);
+ for (i = 0; i < PRISM2_TXFID_COUNT; i++)
+ p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
+ local->txfid[i], local->intransmitfid[i]);
+ p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
+ p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
+ p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
+ p += sprintf(p, "wds_max_connections=%d\n",
+ local->wds_max_connections);
+ p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
+ p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (local->crypt[i] && local->crypt[i]->ops) {
+ p += sprintf(p, "crypt[%d]=%s\n",
+ i, local->crypt[i]->ops->name);
+ }
+ }
+ p += sprintf(p, "pri_only=%d\n", local->pri_only);
+ p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
+ p += sprintf(p, "sram_type=%d\n", local->sram_type);
+ p += sprintf(p, "no_pri=%d\n", local->no_pri);
+
+ return (p - page);
+}
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+
+
+static int prism2_stats_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
+ &local->comm_tallies;
+
+ if (off != 0) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
+ p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
+ p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
+ p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
+ p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
+ p += sprintf(p, "TxDeferredTransmissions=%u\n",
+ sums->tx_deferred_transmissions);
+ p += sprintf(p, "TxSingleRetryFrames=%u\n",
+ sums->tx_single_retry_frames);
+ p += sprintf(p, "TxMultipleRetryFrames=%u\n",
+ sums->tx_multiple_retry_frames);
+ p += sprintf(p, "TxRetryLimitExceeded=%u\n",
+ sums->tx_retry_limit_exceeded);
+ p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
+ p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
+ p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
+ p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
+ p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
+ p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
+ p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
+ p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
+ sums->rx_discards_no_buffer);
+ p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
+ p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
+ sums->rx_discards_wep_undecryptable);
+ p += sprintf(p, "RxMessageInMsgFragments=%u\n",
+ sums->rx_message_in_msg_fragments);
+ p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
+ sums->rx_message_in_bad_msg_fragments);
+ /* FIX: this may grow too long for one page(?) */
+
+ return (p - page);
+}
+
+
+static int prism2_wds_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct list_head *ptr;
+ struct hostap_interface *iface;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ read_lock_bh(&local->iface_lock);
+ list_for_each(ptr, &local->hostap_interfaces) {
+ iface = list_entry(ptr, struct hostap_interface, list);
+ if (iface->type != HOSTAP_INTERFACE_WDS)
+ continue;
+ p += sprintf(p, "%s\t" MACSTR "\n",
+ iface->dev->name,
+ MAC2STR(iface->u.wds.remote_addr));
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "%s: wds proc did not fit\n",
+ local->dev->name);
+ break;
+ }
+ }
+ read_unlock_bh(&local->iface_lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ struct list_head *ptr;
+ struct hostap_bss_info *bss;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
+ "SSID(hex)\tWPA IE\n");
+ spin_lock_bh(&local->lock);
+ list_for_each(ptr, &local->bss_list) {
+ bss = list_entry(ptr, struct hostap_bss_info, list);
+ p += sprintf(p, MACSTR "\t%lu\t%u\t0x%x\t",
+ MAC2STR(bss->bssid), bss->last_update,
+ bss->count, bss->capab_info);
+ for (i = 0; i < bss->ssid_len; i++) {
+ p += sprintf(p, "%c",
+ bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
+ bss->ssid[i] : '_');
+ }
+ p += sprintf(p, "\t");
+ for (i = 0; i < bss->ssid_len; i++) {
+ p += sprintf(p, "%02x", bss->ssid[i]);
+ }
+ p += sprintf(p, "\t");
+ for (i = 0; i < bss->wpa_ie_len; i++) {
+ p += sprintf(p, "%02x", bss->wpa_ie[i]);
+ }
+ p += sprintf(p, "\n");
+ if ((p - page) > PROC_LIMIT) {
+ printk(KERN_DEBUG "%s: BSS proc did not fit\n",
+ local->dev->name);
+ break;
+ }
+ }
+ spin_unlock_bh(&local->lock);
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_crypt_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int i;
+
+ if (off > PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (local->crypt[i] && local->crypt[i]->ops &&
+ local->crypt[i]->ops->print_stats) {
+ p = local->crypt[i]->ops->print_stats(
+ p, local->crypt[i]->priv);
+ }
+ }
+
+ if ((p - page) <= off) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = page + off;
+
+ return (p - page - off);
+}
+
+
+static int prism2_pda_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
+ *eof = 1;
+ return 0;
+ }
+
+ if (off + count > PRISM2_PDA_SIZE)
+ count = PRISM2_PDA_SIZE - off;
+
+ memcpy(page, local->pda + off, count);
+ return count;
+}
+
+
+static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+
+ if (local->func->read_aux == NULL) {
+ *eof = 1;
+ return 0;
+ }
+
+ if (local->func->read_aux(local->dev, off, count, page)) {
+ *eof = 1;
+ return 0;
+ }
+ *start = page;
+
+ return count;
+}
+
+
+#ifdef PRISM2_IO_DEBUG
+static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ local_info_t *local = (local_info_t *) data;
+ int head = local->io_debug_head;
+ int start_bytes, left, copy, copied;
+
+ if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
+ *eof = 1;
+ if (off >= PRISM2_IO_DEBUG_SIZE * 4)
+ return 0;
+ count = PRISM2_IO_DEBUG_SIZE * 4 - off;
+ }
+
+ copied = 0;
+ start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
+ left = count;
+
+ if (off < start_bytes) {
+ copy = start_bytes - off;
+ if (copy > count)
+ copy = count;
+ memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
+ left -= copy;
+ if (left > 0)
+ memcpy(&page[copy], local->io_debug, left);
+ } else {
+ memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
+ left);
+ }
+
+ *start = page;
+
+ return count;
+}
+#endif /* PRISM2_IO_DEBUG */
+
+
+#ifndef PRISM2_NO_STATION_MODES
+static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ local_info_t *local = (local_info_t *) data;
+ int entry, i, len, total = 0;
+ struct hfa384x_hostscan_result *scanres;
+ u8 *pos;
+
+ p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
+ "SSID\n");
+
+ spin_lock_bh(&local->lock);
+ for (entry = 0; entry < local->last_scan_results_count; entry++) {
+ scanres = &local->last_scan_results[entry];
+
+ if (total + (p - page) <= off) {
+ total += p - page;
+ p = page;
+ }
+ if (total + (p - page) > off + count)
+ break;
+ if ((p - page) > (PAGE_SIZE - 200))
+ break;
+
+ p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR " %d ",
+ le16_to_cpu(scanres->chid),
+ (s16) le16_to_cpu(scanres->anl),
+ (s16) le16_to_cpu(scanres->sl),
+ le16_to_cpu(scanres->beacon_interval),
+ le16_to_cpu(scanres->capability),
+ le16_to_cpu(scanres->rate),
+ MAC2STR(scanres->bssid),
+ le16_to_cpu(scanres->atim));
+
+ pos = scanres->sup_rates;
+ for (i = 0; i < sizeof(scanres->sup_rates); i++) {
+ if (pos[i] == 0)
+ break;
+ p += sprintf(p, "<%02x>", pos[i]);
+ }
+ p += sprintf(p, " ");
+
+ pos = scanres->ssid;
+ len = le16_to_cpu(scanres->ssid_len);
+ if (len > 32)
+ len = 32;
+ for (i = 0; i < len; i++) {
+ unsigned char c = pos[i];
+ if (c >= 32 && c < 127)
+ p += sprintf(p, "%c", c);
+ else
+ p += sprintf(p, "<%02x>", c);
+ }
+ p += sprintf(p, "\n");
+ }
+ spin_unlock_bh(&local->lock);
+
+ total += (p - page);
+ if (total >= off + count)
+ *eof = 1;
+
+ if (total < off) {
+ *eof = 1;
+ return 0;
+ }
+
+ len = total - off;
+ if (len > (p - page))
+ len = p - page;
+ *start = p - len;
+ if (len > count)
+ len = count;
+
+ return len;
+}
+#endif /* PRISM2_NO_STATION_MODES */
+
+
+void hostap_init_proc(local_info_t *local)
+{
+ local->proc = NULL;
+
+ if (hostap_proc == NULL) {
+ printk(KERN_WARNING "%s: hostap proc directory not created\n",
+ local->dev->name);
+ return;
+ }
+
+ local->proc = proc_mkdir(local->ddev->name, hostap_proc);
+ if (local->proc == NULL) {
+ printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
+ local->ddev->name);
+ return;
+ }
+
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ create_proc_read_entry("debug", 0, local->proc,
+ prism2_debug_proc_read, local);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ create_proc_read_entry("stats", 0, local->proc,
+ prism2_stats_proc_read, local);
+ create_proc_read_entry("wds", 0, local->proc,
+ prism2_wds_proc_read, local);
+ create_proc_read_entry("pda", 0, local->proc,
+ prism2_pda_proc_read, local);
+ create_proc_read_entry("aux_dump", 0, local->proc,
+ prism2_aux_dump_proc_read, local);
+ create_proc_read_entry("bss_list", 0, local->proc,
+ prism2_bss_list_proc_read, local);
+ create_proc_read_entry("crypt", 0, local->proc,
+ prism2_crypt_proc_read, local);
+#ifdef PRISM2_IO_DEBUG
+ create_proc_read_entry("io_debug", 0, local->proc,
+ prism2_io_debug_proc_read, local);
+#endif /* PRISM2_IO_DEBUG */
+#ifndef PRISM2_NO_STATION_MODES
+ create_proc_read_entry("scan_results", 0, local->proc,
+ prism2_scan_results_proc_read, local);
+#endif /* PRISM2_NO_STATION_MODES */
+}
+
+
+void hostap_remove_proc(local_info_t *local)
+{
+ if (local->proc != NULL) {
+#ifndef PRISM2_NO_STATION_MODES
+ remove_proc_entry("scan_results", local->proc);
+#endif /* PRISM2_NO_STATION_MODES */
+#ifdef PRISM2_IO_DEBUG
+ remove_proc_entry("io_debug", local->proc);
+#endif /* PRISM2_IO_DEBUG */
+ remove_proc_entry("pda", local->proc);
+ remove_proc_entry("aux_dump", local->proc);
+ remove_proc_entry("wds", local->proc);
+ remove_proc_entry("stats", local->proc);
+ remove_proc_entry("bss_list", local->proc);
+ remove_proc_entry("crypt", local->proc);
+#ifndef PRISM2_NO_PROCFS_DEBUG
+ remove_proc_entry("debug", local->proc);
+#endif /* PRISM2_NO_PROCFS_DEBUG */
+ if (hostap_proc != NULL)
+ remove_proc_entry(local->proc->name, hostap_proc);
+ }
+}
+
+
+EXPORT_SYMBOL(hostap_init_proc);
+EXPORT_SYMBOL(hostap_remove_proc);
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
new file mode 100644
index 000000000000..cfd801559492
--- /dev/null
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -0,0 +1,1031 @@
+#ifndef HOSTAP_WLAN_H
+#define HOSTAP_WLAN_H
+
+#include "hostap_config.h"
+#include "hostap_common.h"
+
+#define MAX_PARM_DEVICES 8
+#define PARM_MIN_MAX "1-" __MODULE_STRING(MAX_PARM_DEVICES)
+#define DEF_INTS -1, -1, -1, -1, -1, -1, -1
+#define GET_INT_PARM(var,idx) var[var[idx] < 0 ? 0 : idx]
+
+
+/* Specific skb->protocol value that indicates that the packet already contains
+ * txdesc header.
+ * FIX: This might need own value that would be allocated especially for Prism2
+ * txdesc; ETH_P_CONTROL is commented as "Card specific control frames".
+ * However, these skb's should have only minimal path in the kernel side since
+ * prism2_send_mgmt() sends these with dev_queue_xmit() to prism2_tx(). */
+#define ETH_P_HOSTAP ETH_P_CONTROL
+
+/* ARPHRD_IEEE80211_PRISM uses a bloated version of Prism2 RX frame header
+ * (from linux-wlan-ng) */
+struct linux_wlan_ng_val {
+ u32 did;
+ u16 status, len;
+ u32 data;
+} __attribute__ ((packed));
+
+struct linux_wlan_ng_prism_hdr {
+ u32 msgcode, msglen;
+ char devname[16];
+ struct linux_wlan_ng_val hosttime, mactime, channel, rssi, sq, signal,
+ noise, rate, istx, frmlen;
+} __attribute__ ((packed));
+
+struct linux_wlan_ng_cap_hdr {
+ u32 version;
+ u32 length;
+ u64 mactime;
+ u64 hosttime;
+ u32 phytype;
+ u32 channel;
+ u32 datarate;
+ u32 antenna;
+ u32 priority;
+ u32 ssi_type;
+ s32 ssi_signal;
+ s32 ssi_noise;
+ u32 preamble;
+ u32 encoding;
+} __attribute__ ((packed));
+
+#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */
+#define LWNG_CAPHDR_VERSION 0x80211001
+
+struct hfa384x_rx_frame {
+ /* HFA384X RX frame descriptor */
+ u16 status; /* HFA384X_RX_STATUS_ flags */
+ u32 time; /* timestamp, 1 microsecond resolution */
+ u8 silence; /* 27 .. 154; seems to be 0 */
+ u8 signal; /* 27 .. 154 */
+ u8 rate; /* 10, 20, 55, or 110 */
+ u8 rxflow;
+ u32 reserved;
+
+ /* 802.11 */
+ u16 frame_control;
+ u16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6];
+ u8 addr3[6];
+ u16 seq_ctrl;
+ u8 addr4[6];
+ u16 data_len;
+
+ /* 802.3 */
+ u8 dst_addr[6];
+ u8 src_addr[6];
+ u16 len;
+
+ /* followed by frame data; max 2304 bytes */
+} __attribute__ ((packed));
+
+
+struct hfa384x_tx_frame {
+ /* HFA384X TX frame descriptor */
+ u16 status; /* HFA384X_TX_STATUS_ flags */
+ u16 reserved1;
+ u16 reserved2;
+ u32 sw_support;
+ u8 retry_count; /* not yet implemented */
+ u8 tx_rate; /* Host AP only; 0 = firmware, or 10, 20, 55, 110 */
+ u16 tx_control; /* HFA384X_TX_CTRL_ flags */
+
+ /* 802.11 */
+ u16 frame_control; /* parts not used */
+ u16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6]; /* filled by firmware */
+ u8 addr3[6];
+ u16 seq_ctrl; /* filled by firmware */
+ u8 addr4[6];
+ u16 data_len;
+
+ /* 802.3 */
+ u8 dst_addr[6];
+ u8 src_addr[6];
+ u16 len;
+
+ /* followed by frame data; max 2304 bytes */
+} __attribute__ ((packed));
+
+
+struct hfa384x_rid_hdr
+{
+ u16 len;
+ u16 rid;
+} __attribute__ ((packed));
+
+
+/* Macro for converting signal levels (range 27 .. 154) to wireless ext
+ * dBm value with some accuracy */
+#define HFA384X_LEVEL_TO_dBm(v) 0x100 + (v) * 100 / 255 - 100
+
+#define HFA384X_LEVEL_TO_dBm_sign(v) (v) * 100 / 255 - 100
+
+struct hfa384x_scan_request {
+ u16 channel_list;
+ u16 txrate; /* HFA384X_RATES_* */
+} __attribute__ ((packed));
+
+struct hfa384x_hostscan_request {
+ u16 channel_list;
+ u16 txrate;
+ u16 target_ssid_len;
+ u8 target_ssid[32];
+} __attribute__ ((packed));
+
+struct hfa384x_join_request {
+ u8 bssid[6];
+ u16 channel;
+} __attribute__ ((packed));
+
+struct hfa384x_info_frame {
+ u16 len;
+ u16 type;
+} __attribute__ ((packed));
+
+struct hfa384x_comm_tallies {
+ u16 tx_unicast_frames;
+ u16 tx_multicast_frames;
+ u16 tx_fragments;
+ u16 tx_unicast_octets;
+ u16 tx_multicast_octets;
+ u16 tx_deferred_transmissions;
+ u16 tx_single_retry_frames;
+ u16 tx_multiple_retry_frames;
+ u16 tx_retry_limit_exceeded;
+ u16 tx_discards;
+ u16 rx_unicast_frames;
+ u16 rx_multicast_frames;
+ u16 rx_fragments;
+ u16 rx_unicast_octets;
+ u16 rx_multicast_octets;
+ u16 rx_fcs_errors;
+ u16 rx_discards_no_buffer;
+ u16 tx_discards_wrong_sa;
+ u16 rx_discards_wep_undecryptable;
+ u16 rx_message_in_msg_fragments;
+ u16 rx_message_in_bad_msg_fragments;
+} __attribute__ ((packed));
+
+struct hfa384x_comm_tallies32 {
+ u32 tx_unicast_frames;
+ u32 tx_multicast_frames;
+ u32 tx_fragments;
+ u32 tx_unicast_octets;
+ u32 tx_multicast_octets;
+ u32 tx_deferred_transmissions;
+ u32 tx_single_retry_frames;
+ u32 tx_multiple_retry_frames;
+ u32 tx_retry_limit_exceeded;
+ u32 tx_discards;
+ u32 rx_unicast_frames;
+ u32 rx_multicast_frames;
+ u32 rx_fragments;
+ u32 rx_unicast_octets;
+ u32 rx_multicast_octets;
+ u32 rx_fcs_errors;
+ u32 rx_discards_no_buffer;
+ u32 tx_discards_wrong_sa;
+ u32 rx_discards_wep_undecryptable;
+ u32 rx_message_in_msg_fragments;
+ u32 rx_message_in_bad_msg_fragments;
+} __attribute__ ((packed));
+
+struct hfa384x_scan_result_hdr {
+ u16 reserved;
+ u16 scan_reason;
+#define HFA384X_SCAN_IN_PROGRESS 0 /* no results available yet */
+#define HFA384X_SCAN_HOST_INITIATED 1
+#define HFA384X_SCAN_FIRMWARE_INITIATED 2
+#define HFA384X_SCAN_INQUIRY_FROM_HOST 3
+} __attribute__ ((packed));
+
+#define HFA384X_SCAN_MAX_RESULTS 32
+
+struct hfa384x_scan_result {
+ u16 chid;
+ u16 anl;
+ u16 sl;
+ u8 bssid[6];
+ u16 beacon_interval;
+ u16 capability;
+ u16 ssid_len;
+ u8 ssid[32];
+ u8 sup_rates[10];
+ u16 rate;
+} __attribute__ ((packed));
+
+struct hfa384x_hostscan_result {
+ u16 chid;
+ u16 anl;
+ u16 sl;
+ u8 bssid[6];
+ u16 beacon_interval;
+ u16 capability;
+ u16 ssid_len;
+ u8 ssid[32];
+ u8 sup_rates[10];
+ u16 rate;
+ u16 atim;
+} __attribute__ ((packed));
+
+struct comm_tallies_sums {
+ unsigned int tx_unicast_frames;
+ unsigned int tx_multicast_frames;
+ unsigned int tx_fragments;
+ unsigned int tx_unicast_octets;
+ unsigned int tx_multicast_octets;
+ unsigned int tx_deferred_transmissions;
+ unsigned int tx_single_retry_frames;
+ unsigned int tx_multiple_retry_frames;
+ unsigned int tx_retry_limit_exceeded;
+ unsigned int tx_discards;
+ unsigned int rx_unicast_frames;
+ unsigned int rx_multicast_frames;
+ unsigned int rx_fragments;
+ unsigned int rx_unicast_octets;
+ unsigned int rx_multicast_octets;
+ unsigned int rx_fcs_errors;
+ unsigned int rx_discards_no_buffer;
+ unsigned int tx_discards_wrong_sa;
+ unsigned int rx_discards_wep_undecryptable;
+ unsigned int rx_message_in_msg_fragments;
+ unsigned int rx_message_in_bad_msg_fragments;
+};
+
+
+struct hfa384x_regs {
+ u16 cmd;
+ u16 evstat;
+ u16 offset0;
+ u16 offset1;
+ u16 swsupport0;
+};
+
+
+#if defined(PRISM2_PCCARD) || defined(PRISM2_PLX)
+/* I/O ports for HFA384X Controller access */
+#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_CONTROL_OFF 0x14
+#define HFA384X_SELECT0_OFF 0x18
+#define HFA384X_SELECT1_OFF 0x1A
+#define HFA384X_OFFSET0_OFF 0x1C
+#define HFA384X_OFFSET1_OFF 0x1E
+#define HFA384X_RXFID_OFF 0x20
+#define HFA384X_ALLOCFID_OFF 0x22
+#define HFA384X_TXCOMPLFID_OFF 0x24
+#define HFA384X_SWSUPPORT0_OFF 0x28
+#define HFA384X_SWSUPPORT1_OFF 0x2A
+#define HFA384X_SWSUPPORT2_OFF 0x2C
+#define HFA384X_EVSTAT_OFF 0x30
+#define HFA384X_INTEN_OFF 0x32
+#define HFA384X_EVACK_OFF 0x34
+#define HFA384X_DATA0_OFF 0x36
+#define HFA384X_DATA1_OFF 0x38
+#define HFA384X_AUXPAGE_OFF 0x3A
+#define HFA384X_AUXOFFSET_OFF 0x3C
+#define HFA384X_AUXDATA_OFF 0x3E
+#endif /* PRISM2_PCCARD || PRISM2_PLX */
+
+#ifdef PRISM2_PCI
+/* Memory addresses for ISL3874 controller access */
+#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_CONTROL_OFF 0x28
+#define HFA384X_SELECT0_OFF 0x30
+#define HFA384X_SELECT1_OFF 0x34
+#define HFA384X_OFFSET0_OFF 0x38
+#define HFA384X_OFFSET1_OFF 0x3C
+#define HFA384X_RXFID_OFF 0x40
+#define HFA384X_ALLOCFID_OFF 0x44
+#define HFA384X_TXCOMPLFID_OFF 0x48
+#define HFA384X_PCICOR_OFF 0x4C
+#define HFA384X_SWSUPPORT0_OFF 0x50
+#define HFA384X_SWSUPPORT1_OFF 0x54
+#define HFA384X_SWSUPPORT2_OFF 0x58
+#define HFA384X_PCIHCR_OFF 0x5C
+#define HFA384X_EVSTAT_OFF 0x60
+#define HFA384X_INTEN_OFF 0x64
+#define HFA384X_EVACK_OFF 0x68
+#define HFA384X_DATA0_OFF 0x6C
+#define HFA384X_DATA1_OFF 0x70
+#define HFA384X_AUXPAGE_OFF 0x74
+#define HFA384X_AUXOFFSET_OFF 0x78
+#define HFA384X_AUXDATA_OFF 0x7C
+#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
+
+/* PCI bus master control bits (these are undocumented; based on guessing and
+ * experimenting..) */
+#define HFA384X_PCI_CTL_FROM_BAP (BIT(5) | BIT(1) | BIT(0))
+#define HFA384X_PCI_CTL_TO_BAP (BIT(5) | BIT(0))
+
+#endif /* PRISM2_PCI */
+
+
+/* Command codes for CMD reg. */
+#define HFA384X_CMDCODE_INIT 0x00
+#define HFA384X_CMDCODE_ENABLE 0x01
+#define HFA384X_CMDCODE_DISABLE 0x02
+#define HFA384X_CMDCODE_ALLOC 0x0A
+#define HFA384X_CMDCODE_TRANSMIT 0x0B
+#define HFA384X_CMDCODE_INQUIRE 0x11
+#define HFA384X_CMDCODE_ACCESS 0x21
+#define HFA384X_CMDCODE_ACCESS_WRITE (0x21 | BIT(8))
+#define HFA384X_CMDCODE_DOWNLOAD 0x22
+#define HFA384X_CMDCODE_READMIF 0x30
+#define HFA384X_CMDCODE_WRITEMIF 0x31
+#define HFA384X_CMDCODE_TEST 0x38
+
+#define HFA384X_CMDCODE_MASK 0x3F
+
+/* Test mode operations */
+#define HFA384X_TEST_CHANGE_CHANNEL 0x08
+#define HFA384X_TEST_MONITOR 0x0B
+#define HFA384X_TEST_STOP 0x0F
+#define HFA384X_TEST_CFG_BITS 0x15
+#define HFA384X_TEST_CFG_BIT_ALC BIT(3)
+
+#define HFA384X_CMD_BUSY BIT(15)
+
+#define HFA384X_CMD_TX_RECLAIM BIT(8)
+
+#define HFA384X_OFFSET_ERR BIT(14)
+#define HFA384X_OFFSET_BUSY BIT(15)
+
+
+/* ProgMode for download command */
+#define HFA384X_PROGMODE_DISABLE 0
+#define HFA384X_PROGMODE_ENABLE_VOLATILE 1
+#define HFA384X_PROGMODE_ENABLE_NON_VOLATILE 2
+#define HFA384X_PROGMODE_PROGRAM_NON_VOLATILE 3
+
+#define HFA384X_AUX_MAGIC0 0xfe01
+#define HFA384X_AUX_MAGIC1 0xdc23
+#define HFA384X_AUX_MAGIC2 0xba45
+
+#define HFA384X_AUX_PORT_DISABLED 0
+#define HFA384X_AUX_PORT_DISABLE BIT(14)
+#define HFA384X_AUX_PORT_ENABLE BIT(15)
+#define HFA384X_AUX_PORT_ENABLED (BIT(14) | BIT(15))
+#define HFA384X_AUX_PORT_MASK (BIT(14) | BIT(15))
+
+#define PRISM2_PDA_SIZE 1024
+
+
+/* Events; EvStat, Interrupt mask (IntEn), and acknowledge bits (EvAck) */
+#define HFA384X_EV_TICK BIT(15)
+#define HFA384X_EV_WTERR BIT(14)
+#define HFA384X_EV_INFDROP BIT(13)
+#ifdef PRISM2_PCI
+#define HFA384X_EV_PCI_M1 BIT(9)
+#define HFA384X_EV_PCI_M0 BIT(8)
+#endif /* PRISM2_PCI */
+#define HFA384X_EV_INFO BIT(7)
+#define HFA384X_EV_DTIM BIT(5)
+#define HFA384X_EV_CMD BIT(4)
+#define HFA384X_EV_ALLOC BIT(3)
+#define HFA384X_EV_TXEXC BIT(2)
+#define HFA384X_EV_TX BIT(1)
+#define HFA384X_EV_RX BIT(0)
+
+
+/* HFA384X Information frames */
+#define HFA384X_INFO_HANDOVERADDR 0xF000 /* AP f/w ? */
+#define HFA384X_INFO_HANDOVERDEAUTHADDR 0xF001 /* AP f/w 1.3.7 */
+#define HFA384X_INFO_COMMTALLIES 0xF100
+#define HFA384X_INFO_SCANRESULTS 0xF101
+#define HFA384X_INFO_CHANNELINFORESULTS 0xF102 /* AP f/w only */
+#define HFA384X_INFO_HOSTSCANRESULTS 0xF103
+#define HFA384X_INFO_LINKSTATUS 0xF200
+#define HFA384X_INFO_ASSOCSTATUS 0xF201 /* ? */
+#define HFA384X_INFO_AUTHREQ 0xF202 /* ? */
+#define HFA384X_INFO_PSUSERCNT 0xF203 /* ? */
+#define HFA384X_INFO_KEYIDCHANGED 0xF204 /* ? */
+
+enum { HFA384X_LINKSTATUS_CONNECTED = 1,
+ HFA384X_LINKSTATUS_DISCONNECTED = 2,
+ HFA384X_LINKSTATUS_AP_CHANGE = 3,
+ HFA384X_LINKSTATUS_AP_OUT_OF_RANGE = 4,
+ HFA384X_LINKSTATUS_AP_IN_RANGE = 5,
+ HFA384X_LINKSTATUS_ASSOC_FAILED = 6 };
+
+enum { HFA384X_PORTTYPE_BSS = 1, HFA384X_PORTTYPE_WDS = 2,
+ HFA384X_PORTTYPE_PSEUDO_IBSS = 3, HFA384X_PORTTYPE_IBSS = 0,
+ HFA384X_PORTTYPE_HOSTAP = 6 };
+
+#define HFA384X_RATES_1MBPS BIT(0)
+#define HFA384X_RATES_2MBPS BIT(1)
+#define HFA384X_RATES_5MBPS BIT(2)
+#define HFA384X_RATES_11MBPS BIT(3)
+
+#define HFA384X_ROAMING_FIRMWARE 1
+#define HFA384X_ROAMING_HOST 2
+#define HFA384X_ROAMING_DISABLED 3
+
+#define HFA384X_WEPFLAGS_PRIVACYINVOKED BIT(0)
+#define HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED BIT(1)
+#define HFA384X_WEPFLAGS_HOSTENCRYPT BIT(4)
+#define HFA384X_WEPFLAGS_HOSTDECRYPT BIT(7)
+
+#define HFA384X_RX_STATUS_MSGTYPE (BIT(15) | BIT(14) | BIT(13))
+#define HFA384X_RX_STATUS_PCF BIT(12)
+#define HFA384X_RX_STATUS_MACPORT (BIT(10) | BIT(9) | BIT(8))
+#define HFA384X_RX_STATUS_UNDECR BIT(1)
+#define HFA384X_RX_STATUS_FCSERR BIT(0)
+
+#define HFA384X_RX_STATUS_GET_MSGTYPE(s) \
+(((s) & HFA384X_RX_STATUS_MSGTYPE) >> 13)
+#define HFA384X_RX_STATUS_GET_MACPORT(s) \
+(((s) & HFA384X_RX_STATUS_MACPORT) >> 8)
+
+enum { HFA384X_RX_MSGTYPE_NORMAL = 0, HFA384X_RX_MSGTYPE_RFC1042 = 1,
+ HFA384X_RX_MSGTYPE_BRIDGETUNNEL = 2, HFA384X_RX_MSGTYPE_MGMT = 4 };
+
+
+#define HFA384X_TX_CTRL_ALT_RTRY BIT(5)
+#define HFA384X_TX_CTRL_802_11 BIT(3)
+#define HFA384X_TX_CTRL_802_3 0
+#define HFA384X_TX_CTRL_TX_EX BIT(2)
+#define HFA384X_TX_CTRL_TX_OK BIT(1)
+
+#define HFA384X_TX_STATUS_RETRYERR BIT(0)
+#define HFA384X_TX_STATUS_AGEDERR BIT(1)
+#define HFA384X_TX_STATUS_DISCON BIT(2)
+#define HFA384X_TX_STATUS_FORMERR BIT(3)
+
+/* HFA3861/3863 (BBP) Control Registers */
+#define HFA386X_CR_TX_CONFIGURE 0x12 /* CR9 */
+#define HFA386X_CR_RX_CONFIGURE 0x14 /* CR10 */
+#define HFA386X_CR_A_D_TEST_MODES2 0x1A /* CR13 */
+#define HFA386X_CR_MANUAL_TX_POWER 0x3E /* CR31 */
+#define HFA386X_CR_MEASURED_TX_POWER 0x74 /* CR58 */
+
+
+#ifdef __KERNEL__
+
+#define PRISM2_TXFID_COUNT 8
+#define PRISM2_DATA_MAXLEN 2304
+#define PRISM2_TXFID_LEN (PRISM2_DATA_MAXLEN + sizeof(struct hfa384x_tx_frame))
+#define PRISM2_TXFID_EMPTY 0xffff
+#define PRISM2_TXFID_RESERVED 0xfffe
+#define PRISM2_DUMMY_FID 0xffff
+#define MAX_SSID_LEN 32
+#define MAX_NAME_LEN 32 /* this is assumed to be equal to MAX_SSID_LEN */
+
+#define PRISM2_DUMP_RX_HDR BIT(0)
+#define PRISM2_DUMP_TX_HDR BIT(1)
+#define PRISM2_DUMP_TXEXC_HDR BIT(2)
+
+struct hostap_tx_callback_info {
+ u16 idx;
+ void (*func)(struct sk_buff *, int ok, void *);
+ void *data;
+ struct hostap_tx_callback_info *next;
+};
+
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+#define PRISM2_FRAG_CACHE_LEN 4
+
+struct prism2_frag_entry {
+ unsigned long first_frag_time;
+ unsigned int seq;
+ unsigned int last_frag;
+ struct sk_buff *skb;
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+};
+
+
+struct hostap_cmd_queue {
+ struct list_head list;
+ wait_queue_head_t compl;
+ volatile enum { CMD_SLEEP, CMD_CALLBACK, CMD_COMPLETED } type;
+ void (*callback)(struct net_device *dev, long context, u16 resp0,
+ u16 res);
+ long context;
+ u16 cmd, param0, param1;
+ u16 resp0, res;
+ volatile int issued, issuing;
+
+ atomic_t usecnt;
+ int del_req;
+};
+
+/* options for hw_shutdown */
+#define HOSTAP_HW_NO_DISABLE BIT(0)
+#define HOSTAP_HW_ENABLE_CMDCOMPL BIT(1)
+
+typedef struct local_info local_info_t;
+
+struct prism2_helper_functions {
+ /* these functions are defined in hardware model specific files
+ * (hostap_{cs,plx,pci}.c */
+ int (*card_present)(local_info_t *local);
+ void (*cor_sreset)(local_info_t *local);
+ void (*genesis_reset)(local_info_t *local, int hcr);
+
+ /* the following functions are from hostap_hw.c, but they may have some
+ * hardware model specific code */
+
+ /* FIX: low-level commands like cmd might disappear at some point to
+ * make it easier to change them if needed (e.g., cmd would be replaced
+ * with write_mif/read_mif/testcmd/inquire); at least get_rid and
+ * set_rid might move to hostap_{cs,plx,pci}.c */
+ int (*cmd)(struct net_device *dev, u16 cmd, u16 param0, u16 *param1,
+ u16 *resp0);
+ void (*read_regs)(struct net_device *dev, struct hfa384x_regs *regs);
+ int (*get_rid)(struct net_device *dev, u16 rid, void *buf, int len,
+ int exact_len);
+ int (*set_rid)(struct net_device *dev, u16 rid, void *buf, int len);
+ int (*hw_enable)(struct net_device *dev, int initial);
+ int (*hw_config)(struct net_device *dev, int initial);
+ void (*hw_reset)(struct net_device *dev);
+ void (*hw_shutdown)(struct net_device *dev, int no_disable);
+ int (*reset_port)(struct net_device *dev);
+ void (*schedule_reset)(local_info_t *local);
+ int (*download)(local_info_t *local,
+ struct prism2_download_param *param);
+ int (*tx)(struct sk_buff *skb, struct net_device *dev);
+ int (*set_tim)(struct net_device *dev, int aid, int set);
+ int (*read_aux)(struct net_device *dev, unsigned addr, int len,
+ u8 *buf);
+
+ int need_tx_headroom; /* number of bytes of headroom needed before
+ * IEEE 802.11 header */
+ enum { HOSTAP_HW_PCCARD, HOSTAP_HW_PLX, HOSTAP_HW_PCI } hw_type;
+};
+
+
+struct prism2_download_data {
+ u32 dl_cmd;
+ u32 start_addr;
+ u32 num_areas;
+ struct prism2_download_data_area {
+ u32 addr; /* wlan card address */
+ u32 len;
+ u8 *data; /* allocated data */
+ } data[0];
+};
+
+
+#define HOSTAP_MAX_BSS_COUNT 64
+#define MAX_WPA_IE_LEN 64
+
+struct hostap_bss_info {
+ struct list_head list;
+ unsigned long last_update;
+ unsigned int count;
+ u8 bssid[ETH_ALEN];
+ u16 capab_info;
+ u8 ssid[32];
+ size_t ssid_len;
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ size_t wpa_ie_len;
+ u8 rsn_ie[MAX_WPA_IE_LEN];
+ size_t rsn_ie_len;
+ int chan;
+ int included;
+};
+
+
+/* Per radio private Host AP data - shared by all net devices interfaces used
+ * by each radio (wlan#, wlan#ap, wlan#sta, WDS).
+ * ((struct hostap_interface *) netdev_priv(dev))->local points to this
+ * structure. */
+struct local_info {
+ struct module *hw_module;
+ int card_idx;
+ int dev_enabled;
+ int master_dev_auto_open; /* was master device opened automatically */
+ int num_dev_open; /* number of open devices */
+ struct net_device *dev; /* master radio device */
+ struct net_device *ddev; /* main data device */
+ struct list_head hostap_interfaces; /* Host AP interface list (contains
+ * struct hostap_interface entries)
+ */
+ rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
+ * when removing entries from the list.
+ * TX and RX paths can use read lock. */
+ spinlock_t cmdlock, baplock, lock;
+ struct semaphore rid_bap_sem;
+ u16 infofid; /* MAC buffer id for info frame */
+ /* txfid, intransmitfid, next_txtid, and next_alloc are protected by
+ * txfidlock */
+ spinlock_t txfidlock;
+ int txfid_len; /* length of allocated TX buffers */
+ u16 txfid[PRISM2_TXFID_COUNT]; /* buffer IDs for TX frames */
+ /* buffer IDs for intransmit frames or PRISM2_TXFID_EMPTY if
+ * corresponding txfid is free for next TX frame */
+ u16 intransmitfid[PRISM2_TXFID_COUNT];
+ int next_txfid; /* index to the next txfid to be checked for
+ * availability */
+ int next_alloc; /* index to the next intransmitfid to be checked for
+ * allocation events */
+
+ /* bitfield for atomic bitops */
+#define HOSTAP_BITS_TRANSMIT 0
+#define HOSTAP_BITS_BAP_TASKLET 1
+#define HOSTAP_BITS_BAP_TASKLET2 2
+ long bits;
+
+ struct ap_data *ap;
+
+ char essid[MAX_SSID_LEN + 1];
+ char name[MAX_NAME_LEN + 1];
+ int name_set;
+ u16 channel_mask; /* mask of allowed channels */
+ u16 scan_channel_mask; /* mask of channels to be scanned */
+ struct comm_tallies_sums comm_tallies;
+ struct net_device_stats stats;
+ struct proc_dir_entry *proc;
+ int iw_mode; /* operating mode (IW_MODE_*) */
+ int pseudo_adhoc; /* 0: IW_MODE_ADHOC is real 802.11 compliant IBSS
+ * 1: IW_MODE_ADHOC is "pseudo IBSS" */
+ char bssid[ETH_ALEN];
+ int channel;
+ int beacon_int;
+ int dtim_period;
+ int mtu;
+ int frame_dump; /* dump RX/TX frame headers, PRISM2_DUMP_ flags */
+ int fw_tx_rate_control;
+ u16 tx_rate_control;
+ u16 basic_rates;
+ int hw_resetting;
+ int hw_ready;
+ int hw_reset_tries; /* how many times reset has been tried */
+ int hw_downloading;
+ int shutdown;
+ int pri_only;
+ int no_pri; /* no PRI f/w present */
+ int sram_type; /* 8 = x8 SRAM, 16 = x16 SRAM, -1 = unknown */
+
+ enum {
+ PRISM2_TXPOWER_AUTO = 0, PRISM2_TXPOWER_OFF,
+ PRISM2_TXPOWER_FIXED, PRISM2_TXPOWER_UNKNOWN
+ } txpower_type;
+ int txpower; /* if txpower_type == PRISM2_TXPOWER_FIXED */
+
+ /* command queue for hfa384x_cmd(); protected with cmdlock */
+ struct list_head cmd_queue;
+ /* max_len for cmd_queue; in addition, cmd_callback can use two
+ * additional entries to prevent sleeping commands from stopping
+ * transmits */
+#define HOSTAP_CMD_QUEUE_MAX_LEN 16
+ int cmd_queue_len; /* number of entries in cmd_queue */
+
+ /* if card timeout is detected in interrupt context, reset_queue is
+ * used to schedule card reseting to be done in user context */
+ struct work_struct reset_queue;
+
+ /* For scheduling a change of the promiscuous mode RID */
+ int is_promisc;
+ struct work_struct set_multicast_list_queue;
+
+ struct work_struct set_tim_queue;
+ struct list_head set_tim_list;
+ spinlock_t set_tim_lock;
+
+ int wds_max_connections;
+ int wds_connections;
+#define HOSTAP_WDS_BROADCAST_RA BIT(0)
+#define HOSTAP_WDS_AP_CLIENT BIT(1)
+#define HOSTAP_WDS_STANDARD_FRAME BIT(2)
+ u32 wds_type;
+ u16 tx_control; /* flags to be used in TX description */
+ int manual_retry_count; /* -1 = use f/w default; otherwise retry count
+ * to be used with all frames */
+
+ struct iw_statistics wstats;
+ unsigned long scan_timestamp; /* Time started to scan */
+ enum {
+ PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1,
+ PRISM2_MONITOR_CAPHDR = 2
+ } monitor_type;
+ int (*saved_eth_header_parse)(struct sk_buff *skb,
+ unsigned char *haddr);
+ int monitor_allow_fcserr;
+
+ int hostapd; /* whether user space daemon, hostapd, is used for AP
+ * management */
+ int hostapd_sta; /* whether hostapd is used with an extra STA interface
+ */
+ struct net_device *apdev;
+ struct net_device_stats apdevstats;
+
+ char assoc_ap_addr[ETH_ALEN];
+ struct net_device *stadev;
+ struct net_device_stats stadevstats;
+
+#define WEP_KEYS 4
+#define WEP_KEY_LEN 13
+ struct ieee80211_crypt_data *crypt[WEP_KEYS];
+ int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+ struct timer_list crypt_deinit_timer;
+ struct list_head crypt_deinit_list;
+
+ int open_wep; /* allow unencrypted frames */
+ int host_encrypt;
+ int host_decrypt;
+ int privacy_invoked; /* force privacy invoked flag even if no keys are
+ * configured */
+ int fw_encrypt_ok; /* whether firmware-based WEP encrypt is working
+ * in Host AP mode (STA f/w 1.4.9 or newer) */
+ int bcrx_sta_key; /* use individual keys to override default keys even
+ * with RX of broad/multicast frames */
+
+ struct prism2_frag_entry frag_cache[PRISM2_FRAG_CACHE_LEN];
+ unsigned int frag_next_idx;
+
+ int ieee_802_1x; /* is IEEE 802.1X used */
+
+ int antsel_tx, antsel_rx;
+ int rts_threshold; /* dot11RTSThreshold */
+ int fragm_threshold; /* dot11FragmentationThreshold */
+ int auth_algs; /* PRISM2_AUTH_ flags */
+
+ int enh_sec; /* cnfEnhSecurity options (broadcast SSID hide/ignore) */
+ int tallies32; /* 32-bit tallies in use */
+
+ struct prism2_helper_functions *func;
+
+ u8 *pda;
+ int fw_ap;
+#define PRISM2_FW_VER(major, minor, variant) \
+(((major) << 16) | ((minor) << 8) | variant)
+ u32 sta_fw_ver;
+
+ /* Tasklets for handling hardware IRQ related operations outside hw IRQ
+ * handler */
+ struct tasklet_struct bap_tasklet;
+
+ struct tasklet_struct info_tasklet;
+ struct sk_buff_head info_list; /* info frames as skb's for
+ * info_tasklet */
+
+ struct hostap_tx_callback_info *tx_callback; /* registered TX callbacks
+ */
+
+ struct tasklet_struct rx_tasklet;
+ struct sk_buff_head rx_list;
+
+ struct tasklet_struct sta_tx_exc_tasklet;
+ struct sk_buff_head sta_tx_exc_list;
+
+ int host_roaming;
+ unsigned long last_join_time; /* time of last JoinRequest */
+ struct hfa384x_hostscan_result *last_scan_results;
+ int last_scan_results_count;
+ enum { PRISM2_SCAN, PRISM2_HOSTSCAN } last_scan_type;
+ struct work_struct info_queue;
+ long pending_info; /* bit field of pending info_queue items */
+#define PRISM2_INFO_PENDING_LINKSTATUS 0
+#define PRISM2_INFO_PENDING_SCANRESULTS 1
+ int prev_link_status; /* previous received LinkStatus info */
+ int prev_linkstatus_connected;
+ u8 preferred_ap[6]; /* use this AP if possible */
+
+#ifdef PRISM2_CALLBACK
+ void *callback_data; /* Can be used in callbacks; e.g., allocate
+ * on enable event and free on disable event.
+ * Host AP driver code does not touch this. */
+#endif /* PRISM2_CALLBACK */
+
+ wait_queue_head_t hostscan_wq;
+
+ /* Passive scan in Host AP mode */
+ struct timer_list passive_scan_timer;
+ int passive_scan_interval; /* in seconds, 0 = disabled */
+ int passive_scan_channel;
+ enum { PASSIVE_SCAN_WAIT, PASSIVE_SCAN_LISTEN } passive_scan_state;
+
+ struct timer_list tick_timer;
+ unsigned long last_tick_timer;
+ unsigned int sw_tick_stuck;
+
+ /* commsQuality / dBmCommsQuality data from periodic polling; only
+ * valid for Managed and Ad-hoc modes */
+ unsigned long last_comms_qual_update;
+ int comms_qual; /* in some odd unit.. */
+ int avg_signal; /* in dB (note: negative) */
+ int avg_noise; /* in dB (note: negative) */
+ struct work_struct comms_qual_update;
+
+ /* RSSI to dBm adjustment (for RX descriptor fields) */
+ int rssi_to_dBm; /* substract from RSSI to get approximate dBm value */
+
+ /* BSS list / protected by local->lock */
+ struct list_head bss_list;
+ int num_bss_info;
+ int wpa; /* WPA support enabled */
+ int tkip_countermeasures;
+ int drop_unencrypted;
+ /* Generic IEEE 802.11 info element to be added to
+ * ProbeResp/Beacon/(Re)AssocReq */
+ u8 *generic_elem;
+ size_t generic_elem_len;
+
+#ifdef PRISM2_DOWNLOAD_SUPPORT
+ /* Persistent volatile download data */
+ struct prism2_download_data *dl_pri;
+ struct prism2_download_data *dl_sec;
+#endif /* PRISM2_DOWNLOAD_SUPPORT */
+
+#ifdef PRISM2_IO_DEBUG
+#define PRISM2_IO_DEBUG_SIZE 10000
+ u32 io_debug[PRISM2_IO_DEBUG_SIZE];
+ int io_debug_head;
+ int io_debug_enabled;
+#endif /* PRISM2_IO_DEBUG */
+
+ /* Pointer to hardware model specific (cs,pci,plx) private data. */
+ void *hw_priv;
+};
+
+
+/* Per interface private Host AP data
+ * Allocated for each net device that Host AP uses (wlan#, wlan#ap, wlan#sta,
+ * WDS) and netdev_priv(dev) points to this structure. */
+struct hostap_interface {
+ struct list_head list; /* list entry in Host AP interface list */
+ struct net_device *dev; /* pointer to this device */
+ struct local_info *local; /* pointer to shared private data */
+ struct net_device_stats stats;
+ struct iw_spy_data spy_data; /* iwspy support */
+ struct iw_public_data wireless_data;
+
+ enum {
+ HOSTAP_INTERFACE_MASTER,
+ HOSTAP_INTERFACE_MAIN,
+ HOSTAP_INTERFACE_AP,
+ HOSTAP_INTERFACE_STA,
+ HOSTAP_INTERFACE_WDS,
+ } type;
+
+ union {
+ struct hostap_interface_wds {
+ u8 remote_addr[ETH_ALEN];
+ } wds;
+ } u;
+};
+
+
+#define HOSTAP_SKB_TX_DATA_MAGIC 0xf08a36a2
+
+/*
+ * TX meta data - stored in skb->cb buffer, so this must not be increased over
+ * the 40-byte limit
+ */
+struct hostap_skb_tx_data {
+ u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */
+ u8 rate; /* transmit rate */
+#define HOSTAP_TX_FLAGS_WDS BIT(0)
+#define HOSTAP_TX_FLAGS_BUFFERED_FRAME BIT(1)
+#define HOSTAP_TX_FLAGS_ADD_MOREDATA BIT(2)
+ u8 flags; /* HOSTAP_TX_FLAGS_* */
+ u16 tx_cb_idx;
+ struct hostap_interface *iface;
+ unsigned long jiffies; /* queueing timestamp */
+ unsigned short ethertype;
+};
+
+
+#ifndef PRISM2_NO_DEBUG
+
+#define DEBUG_FID BIT(0)
+#define DEBUG_PS BIT(1)
+#define DEBUG_FLOW BIT(2)
+#define DEBUG_AP BIT(3)
+#define DEBUG_HW BIT(4)
+#define DEBUG_EXTRA BIT(5)
+#define DEBUG_EXTRA2 BIT(6)
+#define DEBUG_PS2 BIT(7)
+#define DEBUG_MASK (DEBUG_PS | DEBUG_AP | DEBUG_HW | DEBUG_EXTRA)
+#define PDEBUG(n, args...) \
+do { if ((n) & DEBUG_MASK) printk(KERN_DEBUG args); } while (0)
+#define PDEBUG2(n, args...) \
+do { if ((n) & DEBUG_MASK) printk(args); } while (0)
+
+#else /* PRISM2_NO_DEBUG */
+
+#define PDEBUG(n, args...)
+#define PDEBUG2(n, args...)
+
+#endif /* PRISM2_NO_DEBUG */
+
+enum { BAP0 = 0, BAP1 = 1 };
+
+#define PRISM2_IO_DEBUG_CMD_INB 0
+#define PRISM2_IO_DEBUG_CMD_INW 1
+#define PRISM2_IO_DEBUG_CMD_INSW 2
+#define PRISM2_IO_DEBUG_CMD_OUTB 3
+#define PRISM2_IO_DEBUG_CMD_OUTW 4
+#define PRISM2_IO_DEBUG_CMD_OUTSW 5
+#define PRISM2_IO_DEBUG_CMD_ERROR 6
+#define PRISM2_IO_DEBUG_CMD_INTERRUPT 7
+
+#ifdef PRISM2_IO_DEBUG
+
+#define PRISM2_IO_DEBUG_ENTRY(cmd, reg, value) \
+(((cmd) << 24) | ((reg) << 16) | value)
+
+static inline void prism2_io_debug_add(struct net_device *dev, int cmd,
+ int reg, int value)
+{
+ struct hostap_interface *iface = netdev_priv(dev);
+ local_info_t *local = iface->local;
+
+ if (!local->io_debug_enabled)
+ return;
+
+ local->io_debug[local->io_debug_head] = jiffies & 0xffffffff;
+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE)
+ local->io_debug_head = 0;
+ local->io_debug[local->io_debug_head] =
+ PRISM2_IO_DEBUG_ENTRY(cmd, reg, value);
+ if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE)
+ local->io_debug_head = 0;
+}
+
+
+static inline void prism2_io_debug_error(struct net_device *dev, int err)
+{
+ struct hostap_interface *iface = netdev_priv(dev);
+ local_info_t *local = iface->local;
+ unsigned long flags;
+
+ if (!local->io_debug_enabled)
+ return;
+
+ spin_lock_irqsave(&local->lock, flags);
+ prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_ERROR, 0, err);
+ if (local->io_debug_enabled == 1) {
+ local->io_debug_enabled = 0;
+ printk(KERN_DEBUG "%s: I/O debug stopped\n", dev->name);
+ }
+ spin_unlock_irqrestore(&local->lock, flags);
+}
+
+#else /* PRISM2_IO_DEBUG */
+
+static inline void prism2_io_debug_add(struct net_device *dev, int cmd,
+ int reg, int value)
+{
+}
+
+static inline void prism2_io_debug_error(struct net_device *dev, int err)
+{
+}
+
+#endif /* PRISM2_IO_DEBUG */
+
+
+#ifdef PRISM2_CALLBACK
+enum {
+ /* Called when card is enabled */
+ PRISM2_CALLBACK_ENABLE,
+
+ /* Called when card is disabled */
+ PRISM2_CALLBACK_DISABLE,
+
+ /* Called when RX/TX starts/ends */
+ PRISM2_CALLBACK_RX_START, PRISM2_CALLBACK_RX_END,
+ PRISM2_CALLBACK_TX_START, PRISM2_CALLBACK_TX_END
+};
+void prism2_callback(local_info_t *local, int event);
+#else /* PRISM2_CALLBACK */
+#define prism2_callback(d, e) do { } while (0)
+#endif /* PRISM2_CALLBACK */
+
+#endif /* __KERNEL__ */
+
+#endif /* HOSTAP_WLAN_H */
diff --git a/drivers/net/wireless/ieee802_11.h b/drivers/net/wireless/ieee802_11.h
deleted file mode 100644
index 53dd5248f9f1..000000000000
--- a/drivers/net/wireless/ieee802_11.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _IEEE802_11_H
-#define _IEEE802_11_H
-
-#define IEEE802_11_DATA_LEN 2304
-/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
- 6.2.1.1.2.
-
- The figure in section 7.1.2 suggests a body size of up to 2312
- bytes is allowed, which is a bit confusing, I suspect this
- represents the 2304 bytes of real data, plus a possible 8 bytes of
- WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
-
-
-#define IEEE802_11_HLEN 30
-#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
-
-struct ieee802_11_hdr {
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-/* Frame control field constants */
-#define IEEE802_11_FCTL_VERS 0x0002
-#define IEEE802_11_FCTL_FTYPE 0x000c
-#define IEEE802_11_FCTL_STYPE 0x00f0
-#define IEEE802_11_FCTL_TODS 0x0100
-#define IEEE802_11_FCTL_FROMDS 0x0200
-#define IEEE802_11_FCTL_MOREFRAGS 0x0400
-#define IEEE802_11_FCTL_RETRY 0x0800
-#define IEEE802_11_FCTL_PM 0x1000
-#define IEEE802_11_FCTL_MOREDATA 0x2000
-#define IEEE802_11_FCTL_WEP 0x4000
-#define IEEE802_11_FCTL_ORDER 0x8000
-
-#define IEEE802_11_FTYPE_MGMT 0x0000
-#define IEEE802_11_FTYPE_CTL 0x0004
-#define IEEE802_11_FTYPE_DATA 0x0008
-
-/* management */
-#define IEEE802_11_STYPE_ASSOC_REQ 0x0000
-#define IEEE802_11_STYPE_ASSOC_RESP 0x0010
-#define IEEE802_11_STYPE_REASSOC_REQ 0x0020
-#define IEEE802_11_STYPE_REASSOC_RESP 0x0030
-#define IEEE802_11_STYPE_PROBE_REQ 0x0040
-#define IEEE802_11_STYPE_PROBE_RESP 0x0050
-#define IEEE802_11_STYPE_BEACON 0x0080
-#define IEEE802_11_STYPE_ATIM 0x0090
-#define IEEE802_11_STYPE_DISASSOC 0x00A0
-#define IEEE802_11_STYPE_AUTH 0x00B0
-#define IEEE802_11_STYPE_DEAUTH 0x00C0
-
-/* control */
-#define IEEE802_11_STYPE_PSPOLL 0x00A0
-#define IEEE802_11_STYPE_RTS 0x00B0
-#define IEEE802_11_STYPE_CTS 0x00C0
-#define IEEE802_11_STYPE_ACK 0x00D0
-#define IEEE802_11_STYPE_CFEND 0x00E0
-#define IEEE802_11_STYPE_CFENDACK 0x00F0
-
-/* data */
-#define IEEE802_11_STYPE_DATA 0x0000
-#define IEEE802_11_STYPE_DATA_CFACK 0x0010
-#define IEEE802_11_STYPE_DATA_CFPOLL 0x0020
-#define IEEE802_11_STYPE_DATA_CFACKPOLL 0x0030
-#define IEEE802_11_STYPE_NULLFUNC 0x0040
-#define IEEE802_11_STYPE_CFACK 0x0050
-#define IEEE802_11_STYPE_CFPOLL 0x0060
-#define IEEE802_11_STYPE_CFACKPOLL 0x0070
-
-#define IEEE802_11_SCTL_FRAG 0x000F
-#define IEEE802_11_SCTL_SEQ 0xFFF0
-
-#endif /* _IEEE802_11_H */
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
new file mode 100644
index 000000000000..ad7f8cd76db9
--- /dev/null
+++ b/drivers/net/wireless/ipw2100.c
@@ -0,0 +1,8676 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ 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, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+ Portions of this file are based on the sample_* files provided by Wireless
+ Extensions 0.26 package and copyright (c) 1997-2003 Jean Tourrilhes
+ <jt@hpl.hp.com>
+
+ Portions of this file are based on the Host AP project,
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and
+ ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c
+ available in the 2.4.25 kernel sources, and are copyright (c) Alan Cox
+
+******************************************************************************/
+/*
+
+ Initial driver on which this is based was developed by Janusz Gorycki,
+ Maciej Urbaniak, and Maciej Sosnowski.
+
+ Promiscuous mode support added by Jacek Wysoczynski and Maciej Urbaniak.
+
+Theory of Operation
+
+Tx - Commands and Data
+
+Firmware and host share a circular queue of Transmit Buffer Descriptors (TBDs)
+Each TBD contains a pointer to the physical (dma_addr_t) address of data being
+sent to the firmware as well as the length of the data.
+
+The host writes to the TBD queue at the WRITE index. The WRITE index points
+to the _next_ packet to be written and is advanced when after the TBD has been
+filled.
+
+The firmware pulls from the TBD queue at the READ index. The READ index points
+to the currently being read entry, and is advanced once the firmware is
+done with a packet.
+
+When data is sent to the firmware, the first TBD is used to indicate to the
+firmware if a Command or Data is being sent. If it is Command, all of the
+command information is contained within the physical address referred to by the
+TBD. If it is Data, the first TBD indicates the type of data packet, number
+of fragments, etc. The next TBD then referrs to the actual packet location.
+
+The Tx flow cycle is as follows:
+
+1) ipw2100_tx() is called by kernel with SKB to transmit
+2) Packet is move from the tx_free_list and appended to the transmit pending
+ list (tx_pend_list)
+3) work is scheduled to move pending packets into the shared circular queue.
+4) when placing packet in the circular queue, the incoming SKB is DMA mapped
+ to a physical address. That address is entered into a TBD. Two TBDs are
+ filled out. The first indicating a data packet, the second referring to the
+ actual payload data.
+5) the packet is removed from tx_pend_list and placed on the end of the
+ firmware pending list (fw_pend_list)
+6) firmware is notified that the WRITE index has
+7) Once the firmware has processed the TBD, INTA is triggered.
+8) For each Tx interrupt received from the firmware, the READ index is checked
+ to see which TBDs are done being processed.
+9) For each TBD that has been processed, the ISR pulls the oldest packet
+ from the fw_pend_list.
+10)The packet structure contained in the fw_pend_list is then used
+ to unmap the DMA address and to free the SKB originally passed to the driver
+ from the kernel.
+11)The packet structure is placed onto the tx_free_list
+
+The above steps are the same for commands, only the msg_free_list/msg_pend_list
+are used instead of tx_free_list/tx_pend_list
+
+...
+
+Critical Sections / Locking :
+
+There are two locks utilized. The first is the low level lock (priv->low_lock)
+that protects the following:
+
+- Access to the Tx/Rx queue lists via priv->low_lock. The lists are as follows:
+
+ tx_free_list : Holds pre-allocated Tx buffers.
+ TAIL modified in __ipw2100_tx_process()
+ HEAD modified in ipw2100_tx()
+
+ tx_pend_list : Holds used Tx buffers waiting to go into the TBD ring
+ TAIL modified ipw2100_tx()
+ HEAD modified by ipw2100_tx_send_data()
+
+ msg_free_list : Holds pre-allocated Msg (Command) buffers
+ TAIL modified in __ipw2100_tx_process()
+ HEAD modified in ipw2100_hw_send_command()
+
+ msg_pend_list : Holds used Msg buffers waiting to go into the TBD ring
+ TAIL modified in ipw2100_hw_send_command()
+ HEAD modified in ipw2100_tx_send_commands()
+
+ The flow of data on the TX side is as follows:
+
+ MSG_FREE_LIST + COMMAND => MSG_PEND_LIST => TBD => MSG_FREE_LIST
+ TX_FREE_LIST + DATA => TX_PEND_LIST => TBD => TX_FREE_LIST
+
+ The methods that work on the TBD ring are protected via priv->low_lock.
+
+- The internal data state of the device itself
+- Access to the firmware read/write indexes for the BD queues
+ and associated logic
+
+All external entry functions are locked with the priv->action_lock to ensure
+that only one external action is invoked at a time.
+
+
+*/
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#define __KERNEL_SYSCALLS__
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/unistd.h>
+#include <linux/stringify.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/time.h>
+#include <linux/firmware.h>
+#include <linux/acpi.h>
+#include <linux/ctype.h>
+
+#include "ipw2100.h"
+
+#define IPW2100_VERSION "1.1.0"
+
+#define DRV_NAME "ipw2100"
+#define DRV_VERSION IPW2100_VERSION
+#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
+
+
+/* Debugging stuff */
+#ifdef CONFIG_IPW_DEBUG
+#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */
+#endif
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static int mode = 0;
+static int channel = 0;
+static int associate = 1;
+static int disable = 0;
+#ifdef CONFIG_PM
+static struct ipw2100_fw ipw2100_firmware;
+#endif
+
+#include <linux/moduleparam.h>
+module_param(debug, int, 0444);
+module_param(mode, int, 0444);
+module_param(channel, int, 0444);
+module_param(associate, int, 0444);
+module_param(disable, int, 0444);
+
+MODULE_PARM_DESC(debug, "debug level");
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
+MODULE_PARM_DESC(channel, "channel");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+
+static u32 ipw2100_debug_level = IPW_DL_NONE;
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_DEBUG(level, message...) \
+do { \
+ if (ipw2100_debug_level & (level)) { \
+ printk(KERN_DEBUG "ipw2100: %c %s ", \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__); \
+ printk(message); \
+ } \
+} while (0)
+#else
+#define IPW_DEBUG(level, message...) do {} while (0)
+#endif /* CONFIG_IPW_DEBUG */
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *command_types[] = {
+ "undefined",
+ "unused", /* HOST_ATTENTION */
+ "HOST_COMPLETE",
+ "unused", /* SLEEP */
+ "unused", /* HOST_POWER_DOWN */
+ "unused",
+ "SYSTEM_CONFIG",
+ "unused", /* SET_IMR */
+ "SSID",
+ "MANDATORY_BSSID",
+ "AUTHENTICATION_TYPE",
+ "ADAPTER_ADDRESS",
+ "PORT_TYPE",
+ "INTERNATIONAL_MODE",
+ "CHANNEL",
+ "RTS_THRESHOLD",
+ "FRAG_THRESHOLD",
+ "POWER_MODE",
+ "TX_RATES",
+ "BASIC_TX_RATES",
+ "WEP_KEY_INFO",
+ "unused",
+ "unused",
+ "unused",
+ "unused",
+ "WEP_KEY_INDEX",
+ "WEP_FLAGS",
+ "ADD_MULTICAST",
+ "CLEAR_ALL_MULTICAST",
+ "BEACON_INTERVAL",
+ "ATIM_WINDOW",
+ "CLEAR_STATISTICS",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "TX_POWER_INDEX",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "undefined",
+ "BROADCAST_SCAN",
+ "CARD_DISABLE",
+ "PREFERRED_BSSID",
+ "SET_SCAN_OPTIONS",
+ "SCAN_DWELL_TIME",
+ "SWEEP_TABLE",
+ "AP_OR_STATION_TABLE",
+ "GROUP_ORDINALS",
+ "SHORT_RETRY_LIMIT",
+ "LONG_RETRY_LIMIT",
+ "unused", /* SAVE_CALIBRATION */
+ "unused", /* RESTORE_CALIBRATION */
+ "undefined",
+ "undefined",
+ "undefined",
+ "HOST_PRE_POWER_DOWN",
+ "unused", /* HOST_INTERRUPT_COALESCING */
+ "undefined",
+ "CARD_DISABLE_PHY_OFF",
+ "MSDU_TX_RATES"
+ "undefined",
+ "undefined",
+ "SET_STATION_STAT_BITS",
+ "CLEAR_STATIONS_STAT_BITS",
+ "LEAP_ROGUE_MODE",
+ "SET_SECURITY_INFORMATION",
+ "DISASSOCIATION_BSSID",
+ "SET_WPA_ASS_IE"
+};
+#endif
+
+
+/* Pre-decl until we get the code solid and then we can clean it up */
+static void ipw2100_tx_send_commands(struct ipw2100_priv *priv);
+static void ipw2100_tx_send_data(struct ipw2100_priv *priv);
+static int ipw2100_adapter_setup(struct ipw2100_priv *priv);
+
+static void ipw2100_queues_initialize(struct ipw2100_priv *priv);
+static void ipw2100_queues_free(struct ipw2100_priv *priv);
+static int ipw2100_queues_allocate(struct ipw2100_priv *priv);
+
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv);
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev);
+static struct iw_handler_def ipw2100_wx_handler_def;
+
+
+static inline void read_register(struct net_device *dev, u32 reg, u32 *val)
+{
+ *val = readl((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val);
+}
+
+static inline void write_register(struct net_device *dev, u32 reg, u32 val)
+{
+ writel(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val);
+}
+
+static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val)
+{
+ *val = readw((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val);
+}
+
+static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val)
+{
+ *val = readb((void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val);
+}
+
+static inline void write_register_word(struct net_device *dev, u32 reg, u16 val)
+{
+ writew(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val);
+}
+
+
+static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val)
+{
+ writeb(val, (void __iomem *)(dev->base_addr + reg));
+ IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val);
+}
+
+static inline void read_nic_dword(struct net_device *dev, u32 addr, u32 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_dword(struct net_device *dev, u32 addr, u32 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void read_nic_word(struct net_device *dev, u32 addr, u16 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_word(struct net_device *dev, u32 addr, u16 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void read_nic_byte(struct net_device *dev, u32 addr, u8 *val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_byte(struct net_device *dev, u32 addr, u8 val)
+{
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+ write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
+}
+
+static inline void write_nic_auto_inc_address(struct net_device *dev, u32 addr)
+{
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ addr & IPW_REG_INDIRECT_ADDR_MASK);
+}
+
+static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val)
+{
+ write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val);
+}
+
+static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
+ const u8 *buf)
+{
+ u32 aligned_addr;
+ u32 aligned_len;
+ u32 dif_len;
+ u32 i;
+
+ /* read first nibble byte by byte */
+ aligned_addr = addr & (~0x3);
+ dif_len = addr - aligned_addr;
+ if (dif_len) {
+ /* Start reading at aligned_addr + dif_len */
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ write_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i,
+ *buf);
+
+ len -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* read DWs through autoincrement registers */
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ aligned_addr);
+ aligned_len = len & (~0x3);
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ write_register(
+ dev, IPW_REG_AUTOINCREMENT_DATA, *(u32 *)buf);
+
+ /* copy the last nibble */
+ dif_len = len - aligned_len;
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ write_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i, *buf);
+}
+
+static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
+ u8 *buf)
+{
+ u32 aligned_addr;
+ u32 aligned_len;
+ u32 dif_len;
+ u32 i;
+
+ /* read first nibble byte by byte */
+ aligned_addr = addr & (~0x3);
+ dif_len = addr - aligned_addr;
+ if (dif_len) {
+ /* Start reading at aligned_addr + dif_len */
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ read_register_byte(
+ dev, IPW_REG_INDIRECT_ACCESS_DATA + i, buf);
+
+ len -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* read DWs through autoincrement registers */
+ write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
+ aligned_addr);
+ aligned_len = len & (~0x3);
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ read_register(dev, IPW_REG_AUTOINCREMENT_DATA,
+ (u32 *)buf);
+
+ /* copy the last nibble */
+ dif_len = len - aligned_len;
+ write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS,
+ aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA +
+ i, buf);
+}
+
+static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev)
+{
+ return (dev->base_addr &&
+ (readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
+ == IPW_DATA_DOA_DEBUG_VALUE));
+}
+
+static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord,
+ void *val, u32 *len)
+{
+ struct ipw2100_ordinals *ordinals = &priv->ordinals;
+ u32 addr;
+ u32 field_info;
+ u16 field_len;
+ u16 field_count;
+ u32 total_length;
+
+ if (ordinals->table1_addr == 0) {
+ printk(KERN_WARNING DRV_NAME ": attempt to use fw ordinals "
+ "before they have been loaded.\n");
+ return -EINVAL;
+ }
+
+ if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) {
+ if (*len < IPW_ORD_TAB_1_ENTRY_SIZE) {
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ printk(KERN_WARNING DRV_NAME
+ ": ordinal buffer length too small, need %zd\n",
+ IPW_ORD_TAB_1_ENTRY_SIZE);
+
+ return -EINVAL;
+ }
+
+ read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2),
+ &addr);
+ read_nic_dword(priv->net_dev, addr, val);
+
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ return 0;
+ }
+
+ if (IS_ORDINAL_TABLE_TWO(ordinals, ord)) {
+
+ ord -= IPW_START_ORD_TAB_2;
+
+ /* get the address of statistic */
+ read_nic_dword(priv->net_dev, ordinals->table2_addr + (ord << 3),
+ &addr);
+
+ /* get the second DW of statistics ;
+ * two 16-bit words - first is length, second is count */
+ read_nic_dword(priv->net_dev,
+ ordinals->table2_addr + (ord << 3) + sizeof(u32),
+ &field_info);
+
+ /* get each entry length */
+ field_len = *((u16 *)&field_info);
+
+ /* get number of entries */
+ field_count = *(((u16 *)&field_info) + 1);
+
+ /* abort if no enought memory */
+ total_length = field_len * field_count;
+ if (total_length > *len) {
+ *len = total_length;
+ return -EINVAL;
+ }
+
+ *len = total_length;
+ if (!total_length)
+ return 0;
+
+ /* read the ordinal data from the SRAM */
+ read_nic_memory(priv->net_dev, addr, total_length, val);
+
+ return 0;
+ }
+
+ printk(KERN_WARNING DRV_NAME ": ordinal %d neither in table 1 nor "
+ "in table 2\n", ord);
+
+ return -EINVAL;
+}
+
+static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 *val,
+ u32 *len)
+{
+ struct ipw2100_ordinals *ordinals = &priv->ordinals;
+ u32 addr;
+
+ if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) {
+ if (*len != IPW_ORD_TAB_1_ENTRY_SIZE) {
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+ IPW_DEBUG_INFO("wrong size\n");
+ return -EINVAL;
+ }
+
+ read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2),
+ &addr);
+
+ write_nic_dword(priv->net_dev, addr, *val);
+
+ *len = IPW_ORD_TAB_1_ENTRY_SIZE;
+
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("wrong table\n");
+ if (IS_ORDINAL_TABLE_TWO(ordinals, ord))
+ return -EINVAL;
+
+ return -EINVAL;
+}
+
+static char *snprint_line(char *buf, size_t count,
+ const u8 *data, u32 len, u32 ofs)
+{
+ int out, i, j, l;
+ char c;
+
+ out = snprintf(buf, count, "%08X", ofs);
+
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++)
+ out += snprintf(buf + out, count - out, "%02X ",
+ data[(i * 8 + j)]);
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ out += snprintf(buf + out, count - out, " ");
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++) {
+ c = data[(i * 8 + j)];
+ if (!isascii(c) || !isprint(c))
+ c = '.';
+
+ out += snprintf(buf + out, count - out, "%c", c);
+ }
+
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ return buf;
+}
+
+static void printk_buf(int level, const u8 *data, u32 len)
+{
+ char line[81];
+ u32 ofs = 0;
+ if (!(ipw2100_debug_level & level))
+ return;
+
+ while (len) {
+ printk(KERN_DEBUG "%s\n",
+ snprint_line(line, sizeof(line), &data[ofs],
+ min(len, 16U), ofs));
+ ofs += 16;
+ len -= min(len, 16U);
+ }
+}
+
+
+
+#define MAX_RESET_BACKOFF 10
+
+static inline void schedule_reset(struct ipw2100_priv *priv)
+{
+ unsigned long now = get_seconds();
+
+ /* If we haven't received a reset request within the backoff period,
+ * then we can reset the backoff interval so this reset occurs
+ * immediately */
+ if (priv->reset_backoff &&
+ (now - priv->last_reset > priv->reset_backoff))
+ priv->reset_backoff = 0;
+
+ priv->last_reset = get_seconds();
+
+ if (!(priv->status & STATUS_RESET_PENDING)) {
+ IPW_DEBUG_INFO("%s: Scheduling firmware restart (%ds).\n",
+ priv->net_dev->name, priv->reset_backoff);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ priv->status |= STATUS_RESET_PENDING;
+ if (priv->reset_backoff)
+ queue_delayed_work(priv->workqueue, &priv->reset_work,
+ priv->reset_backoff * HZ);
+ else
+ queue_work(priv->workqueue, &priv->reset_work);
+
+ if (priv->reset_backoff < MAX_RESET_BACKOFF)
+ priv->reset_backoff++;
+
+ wake_up_interruptible(&priv->wait_command_queue);
+ } else
+ IPW_DEBUG_INFO("%s: Firmware restart already in progress.\n",
+ priv->net_dev->name);
+
+}
+
+#define HOST_COMPLETE_TIMEOUT (2 * HZ)
+static int ipw2100_hw_send_command(struct ipw2100_priv *priv,
+ struct host_command * cmd)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ unsigned long flags;
+ int err = 0;
+
+ IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n",
+ command_types[cmd->host_command], cmd->host_command,
+ cmd->host_command_length);
+ printk_buf(IPW_DL_HC, (u8*)cmd->host_command_parameters,
+ cmd->host_command_length);
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->fatal_error) {
+ IPW_DEBUG_INFO("Attempt to send command while hardware in fatal error condition.\n");
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ if (!(priv->status & STATUS_RUNNING)) {
+ IPW_DEBUG_INFO("Attempt to send command while hardware is not running.\n");
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ if (priv->status & STATUS_CMD_ACTIVE) {
+ IPW_DEBUG_INFO("Attempt to send command while another command is pending.\n");
+ err = -EBUSY;
+ goto fail_unlock;
+ }
+
+ if (list_empty(&priv->msg_free_list)) {
+ IPW_DEBUG_INFO("no available msg buffers\n");
+ goto fail_unlock;
+ }
+
+ priv->status |= STATUS_CMD_ACTIVE;
+ priv->messages_sent++;
+
+ element = priv->msg_free_list.next;
+
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+ packet->jiffy_start = jiffies;
+
+ /* initialize the firmware command packet */
+ packet->info.c_struct.cmd->host_command_reg = cmd->host_command;
+ packet->info.c_struct.cmd->host_command_reg1 = cmd->host_command1;
+ packet->info.c_struct.cmd->host_command_len_reg = cmd->host_command_length;
+ packet->info.c_struct.cmd->sequence = cmd->host_command_sequence;
+
+ memcpy(packet->info.c_struct.cmd->host_command_params_reg,
+ cmd->host_command_parameters,
+ sizeof(packet->info.c_struct.cmd->host_command_params_reg));
+
+ list_del(element);
+ DEC_STAT(&priv->msg_free_stat);
+
+ list_add_tail(element, &priv->msg_pend_list);
+ INC_STAT(&priv->msg_pend_stat);
+
+ ipw2100_tx_send_commands(priv);
+ ipw2100_tx_send_data(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ /*
+ * We must wait for this command to complete before another
+ * command can be sent... but if we wait more than 3 seconds
+ * then there is a problem.
+ */
+
+ err = wait_event_interruptible_timeout(
+ priv->wait_command_queue, !(priv->status & STATUS_CMD_ACTIVE),
+ HOST_COMPLETE_TIMEOUT);
+
+ if (err == 0) {
+ IPW_DEBUG_INFO("Command completion failed out after %dms.\n",
+ HOST_COMPLETE_TIMEOUT / (HZ / 100));
+ priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT;
+ priv->status &= ~STATUS_CMD_ACTIVE;
+ schedule_reset(priv);
+ return -EIO;
+ }
+
+ if (priv->fatal_error) {
+ printk(KERN_WARNING DRV_NAME ": %s: firmware fatal error\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* !!!!! HACK TEST !!!!!
+ * When lots of debug trace statements are enabled, the driver
+ * doesn't seem to have as many firmware restart cycles...
+ *
+ * As a test, we're sticking in a 1/100s delay here */
+ schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+ return 0;
+
+ fail_unlock:
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ return err;
+}
+
+
+/*
+ * Verify the values and data access of the hardware
+ * No locks needed or used. No functions called.
+ */
+static int ipw2100_verify(struct ipw2100_priv *priv)
+{
+ u32 data1, data2;
+ u32 address;
+
+ u32 val1 = 0x76543210;
+ u32 val2 = 0xFEDCBA98;
+
+ /* Domain 0 check - all values should be DOA_DEBUG */
+ for (address = IPW_REG_DOA_DEBUG_AREA_START;
+ address < IPW_REG_DOA_DEBUG_AREA_END;
+ address += sizeof(u32)) {
+ read_register(priv->net_dev, address, &data1);
+ if (data1 != IPW_DATA_DOA_DEBUG_VALUE)
+ return -EIO;
+ }
+
+ /* Domain 1 check - use arbitrary read/write compare */
+ for (address = 0; address < 5; address++) {
+ /* The memory area is not used now */
+ write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32,
+ val1);
+ write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36,
+ val2);
+ read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32,
+ &data1);
+ read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36,
+ &data2);
+ if (val1 == data1 && val2 == data2)
+ return 0;
+ }
+
+ return -EIO;
+}
+
+/*
+ *
+ * Loop until the CARD_DISABLED bit is the same value as the
+ * supplied parameter
+ *
+ * TODO: See if it would be more efficient to do a wait/wake
+ * cycle and have the completion event trigger the wakeup
+ *
+ */
+#define IPW_CARD_DISABLE_COMPLETE_WAIT 100 // 100 milli
+static int ipw2100_wait_for_card_state(struct ipw2100_priv *priv, int state)
+{
+ int i;
+ u32 card_state;
+ u32 len = sizeof(card_state);
+ int err;
+
+ for (i = 0; i <= IPW_CARD_DISABLE_COMPLETE_WAIT * 1000; i += 50) {
+ err = ipw2100_get_ordinal(priv, IPW_ORD_CARD_DISABLED,
+ &card_state, &len);
+ if (err) {
+ IPW_DEBUG_INFO("Query of CARD_DISABLED ordinal "
+ "failed.\n");
+ return 0;
+ }
+
+ /* We'll break out if either the HW state says it is
+ * in the state we want, or if HOST_COMPLETE command
+ * finishes */
+ if ((card_state == state) ||
+ ((priv->status & STATUS_ENABLED) ?
+ IPW_HW_STATE_ENABLED : IPW_HW_STATE_DISABLED) == state) {
+ if (state == IPW_HW_STATE_ENABLED)
+ priv->status |= STATUS_ENABLED;
+ else
+ priv->status &= ~STATUS_ENABLED;
+
+ return 0;
+ }
+
+ udelay(50);
+ }
+
+ IPW_DEBUG_INFO("ipw2100_wait_for_card_state to %s state timed out\n",
+ state ? "DISABLED" : "ENABLED");
+ return -EIO;
+}
+
+
+/*********************************************************************
+ Procedure : sw_reset_and_clock
+ Purpose : Asserts s/w reset, asserts clock initialization
+ and waits for clock stabilization
+ ********************************************************************/
+static int sw_reset_and_clock(struct ipw2100_priv *priv)
+{
+ int i;
+ u32 r;
+
+ // assert s/w reset
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+ // wait for clock stabilization
+ for (i = 0; i < 1000; i++) {
+ udelay(IPW_WAIT_RESET_ARC_COMPLETE_DELAY);
+
+ // check clock ready bit
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &r);
+ if (r & IPW_AUX_HOST_RESET_REG_PRINCETON_RESET)
+ break;
+ }
+
+ if (i == 1000)
+ return -EIO; // TODO: better error value
+
+ /* set "initialization complete" bit to move adapter to
+ * D0 state */
+ write_register(priv->net_dev, IPW_REG_GP_CNTRL,
+ IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE);
+
+ /* wait for clock stabilization */
+ for (i = 0; i < 10000; i++) {
+ udelay(IPW_WAIT_CLOCK_STABILIZATION_DELAY * 4);
+
+ /* check clock ready bit */
+ read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r);
+ if (r & IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY)
+ break;
+ }
+
+ if (i == 10000)
+ return -EIO; /* TODO: better error value */
+
+ /* set D0 standby bit */
+ read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r);
+ write_register(priv->net_dev, IPW_REG_GP_CNTRL,
+ r | IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY);
+
+ return 0;
+}
+
+/*********************************************************************
+ Procedure : ipw2100_download_firmware
+ Purpose : Initiaze adapter after power on.
+ The sequence is:
+ 1. assert s/w reset first!
+ 2. awake clocks & wait for clock stabilization
+ 3. hold ARC (don't ask me why...)
+ 4. load Dino ucode and reset/clock init again
+ 5. zero-out shared mem
+ 6. download f/w
+ *******************************************************************/
+static int ipw2100_download_firmware(struct ipw2100_priv *priv)
+{
+ u32 address;
+ int err;
+
+#ifndef CONFIG_PM
+ /* Fetch the firmware and microcode */
+ struct ipw2100_fw ipw2100_firmware;
+#endif
+
+ if (priv->fatal_error) {
+ IPW_DEBUG_ERROR("%s: ipw2100_download_firmware called after "
+ "fatal error %d. Interface must be brought down.\n",
+ priv->net_dev->name, priv->fatal_error);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_PM
+ if (!ipw2100_firmware.version) {
+ err = ipw2100_get_firmware(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",
+ priv->net_dev->name, err);
+ priv->fatal_error = IPW2100_ERR_FW_LOAD;
+ goto fail;
+ }
+ }
+#else
+ err = ipw2100_get_firmware(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",
+ priv->net_dev->name, err);
+ priv->fatal_error = IPW2100_ERR_FW_LOAD;
+ goto fail;
+ }
+#endif
+ priv->firmware_version = ipw2100_firmware.version;
+
+ /* s/w reset and clock stabilization */
+ err = sw_reset_and_clock(priv);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: sw_reset_and_clock failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ err = ipw2100_verify(priv);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: ipw2100_verify failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* Hold ARC */
+ write_nic_dword(priv->net_dev,
+ IPW_INTERNAL_REGISTER_HALT_AND_RESET,
+ 0x80000000);
+
+ /* allow ARC to run */
+ write_register(priv->net_dev, IPW_REG_RESET_REG, 0);
+
+ /* load microcode */
+ err = ipw2100_ucode_download(priv, &ipw2100_firmware);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Error loading microcode: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* release ARC */
+ write_nic_dword(priv->net_dev,
+ IPW_INTERNAL_REGISTER_HALT_AND_RESET,
+ 0x00000000);
+
+ /* s/w reset and clock stabilization (again!!!) */
+ err = sw_reset_and_clock(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: sw_reset_and_clock failed: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+ /* load f/w */
+ err = ipw2100_fw_download(priv, &ipw2100_firmware);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: Error loading firmware: %d\n",
+ priv->net_dev->name, err);
+ goto fail;
+ }
+
+#ifndef CONFIG_PM
+ /*
+ * When the .resume method of the driver is called, the other
+ * part of the system, i.e. the ide driver could still stay in
+ * the suspend stage. This prevents us from loading the firmware
+ * from the disk. --YZ
+ */
+
+ /* free any storage allocated for firmware image */
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+#endif
+
+ /* zero out Domain 1 area indirectly (Si requirement) */
+ for (address = IPW_HOST_FW_SHARED_AREA0;
+ address < IPW_HOST_FW_SHARED_AREA0_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA1;
+ address < IPW_HOST_FW_SHARED_AREA1_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA2;
+ address < IPW_HOST_FW_SHARED_AREA2_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_SHARED_AREA3;
+ address < IPW_HOST_FW_SHARED_AREA3_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+ for (address = IPW_HOST_FW_INTERRUPT_AREA;
+ address < IPW_HOST_FW_INTERRUPT_AREA_END; address += 4)
+ write_nic_dword(priv->net_dev, address, 0);
+
+ return 0;
+
+ fail:
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+ return err;
+}
+
+static inline void ipw2100_enable_interrupts(struct ipw2100_priv *priv)
+{
+ if (priv->status & STATUS_INT_ENABLED)
+ return;
+ priv->status |= STATUS_INT_ENABLED;
+ write_register(priv->net_dev, IPW_REG_INTA_MASK, IPW_INTERRUPT_MASK);
+}
+
+static inline void ipw2100_disable_interrupts(struct ipw2100_priv *priv)
+{
+ if (!(priv->status & STATUS_INT_ENABLED))
+ return;
+ priv->status &= ~STATUS_INT_ENABLED;
+ write_register(priv->net_dev, IPW_REG_INTA_MASK, 0x0);
+}
+
+
+static void ipw2100_initialize_ordinals(struct ipw2100_priv *priv)
+{
+ struct ipw2100_ordinals *ord = &priv->ordinals;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1,
+ &ord->table1_addr);
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2,
+ &ord->table2_addr);
+
+ read_nic_dword(priv->net_dev, ord->table1_addr, &ord->table1_size);
+ read_nic_dword(priv->net_dev, ord->table2_addr, &ord->table2_size);
+
+ ord->table2_size &= 0x0000FFFF;
+
+ IPW_DEBUG_INFO("table 1 size: %d\n", ord->table1_size);
+ IPW_DEBUG_INFO("table 2 size: %d\n", ord->table2_size);
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv)
+{
+ u32 reg = 0;
+ /*
+ * Set GPIO 3 writable by FW; GPIO 1 writable
+ * by driver and enable clock
+ */
+ reg = (IPW_BIT_GPIO_GPIO3_MASK | IPW_BIT_GPIO_GPIO1_ENABLE |
+ IPW_BIT_GPIO_LED_OFF);
+ write_register(priv->net_dev, IPW_REG_GPIO, reg);
+}
+
+static inline int rf_kill_active(struct ipw2100_priv *priv)
+{
+#define MAX_RF_KILL_CHECKS 5
+#define RF_KILL_CHECK_DELAY 40
+
+ unsigned short value = 0;
+ u32 reg = 0;
+ int i;
+
+ if (!(priv->hw_features & HW_FEATURE_RFKILL)) {
+ priv->status &= ~STATUS_RF_KILL_HW;
+ return 0;
+ }
+
+ for (i = 0; i < MAX_RF_KILL_CHECKS; i++) {
+ udelay(RF_KILL_CHECK_DELAY);
+ read_register(priv->net_dev, IPW_REG_GPIO, &reg);
+ value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);
+ }
+
+ if (value == 0)
+ priv->status |= STATUS_RF_KILL_HW;
+ else
+ priv->status &= ~STATUS_RF_KILL_HW;
+
+ return (value == 0);
+}
+
+static int ipw2100_get_hw_features(struct ipw2100_priv *priv)
+{
+ u32 addr, len;
+ u32 val;
+
+ /*
+ * EEPROM_SRAM_DB_START_ADDRESS using ordinal in ordinal table 1
+ */
+ len = sizeof(addr);
+ if (ipw2100_get_ordinal(
+ priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS,
+ &addr, &len)) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return -EIO;
+ }
+
+ IPW_DEBUG_INFO("EEPROM address: %08X\n", addr);
+
+ /*
+ * EEPROM version is the byte at offset 0xfd in firmware
+ * We read 4 bytes, then shift out the byte we actually want */
+ read_nic_dword(priv->net_dev, addr + 0xFC, &val);
+ priv->eeprom_version = (val >> 24) & 0xFF;
+ IPW_DEBUG_INFO("EEPROM version: %d\n", priv->eeprom_version);
+
+ /*
+ * HW RF Kill enable is bit 0 in byte at offset 0x21 in firmware
+ *
+ * notice that the EEPROM bit is reverse polarity, i.e.
+ * bit = 0 signifies HW RF kill switch is supported
+ * bit = 1 signifies HW RF kill switch is NOT supported
+ */
+ read_nic_dword(priv->net_dev, addr + 0x20, &val);
+ if (!((val >> 24) & 0x01))
+ priv->hw_features |= HW_FEATURE_RFKILL;
+
+ IPW_DEBUG_INFO("HW RF Kill: %ssupported.\n",
+ (priv->hw_features & HW_FEATURE_RFKILL) ?
+ "" : "not ");
+
+ return 0;
+}
+
+/*
+ * Start firmware execution after power on and intialization
+ * The sequence is:
+ * 1. Release ARC
+ * 2. Wait for f/w initialization completes;
+ */
+static int ipw2100_start_adapter(struct ipw2100_priv *priv)
+{
+ int i;
+ u32 inta, inta_mask, gpio;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->status & STATUS_RUNNING)
+ return 0;
+
+ /*
+ * Initialize the hw - drive adapter to DO state by setting
+ * init_done bit. Wait for clk_ready bit and Download
+ * fw & dino ucode
+ */
+ if (ipw2100_download_firmware(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to power on the adapter.\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* Clear the Tx, Rx and Msg queues and the r/w indexes
+ * in the firmware RBD and TBD ring queue */
+ ipw2100_queues_initialize(priv);
+
+ ipw2100_hw_set_gpio(priv);
+
+ /* TODO -- Look at disabling interrupts here to make sure none
+ * get fired during FW initialization */
+
+ /* Release ARC - clear reset bit */
+ write_register(priv->net_dev, IPW_REG_RESET_REG, 0);
+
+ /* wait for f/w intialization complete */
+ IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
+ i = 5000;
+ do {
+ schedule_timeout_uninterruptible(msecs_to_jiffies(40));
+ /* Todo... wait for sync command ... */
+
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+
+ /* check "init done" bit */
+ if (inta & IPW2100_INTA_FW_INIT_DONE) {
+ /* reset "init done" bit */
+ write_register(priv->net_dev, IPW_REG_INTA,
+ IPW2100_INTA_FW_INIT_DONE);
+ break;
+ }
+
+ /* check error conditions : we check these after the firmware
+ * check so that if there is an error, the interrupt handler
+ * will see it and the adapter will be reset */
+ if (inta &
+ (IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR)) {
+ /* clear error conditions */
+ write_register(priv->net_dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR);
+ }
+ } while (i--);
+
+ /* Clear out any pending INTAs since we aren't supposed to have
+ * interrupts enabled at this point... */
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+ read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask);
+ inta &= IPW_INTERRUPT_MASK;
+ /* Clear out any pending interrupts */
+ if (inta & inta_mask)
+ write_register(priv->net_dev, IPW_REG_INTA, inta);
+
+ IPW_DEBUG_FW("f/w initialization complete: %s\n",
+ i ? "SUCCESS" : "FAILED");
+
+ if (!i) {
+ printk(KERN_WARNING DRV_NAME ": %s: Firmware did not initialize.\n",
+ priv->net_dev->name);
+ return -EIO;
+ }
+
+ /* allow firmware to write to GPIO1 & GPIO3 */
+ read_register(priv->net_dev, IPW_REG_GPIO, &gpio);
+
+ gpio |= (IPW_BIT_GPIO_GPIO1_MASK | IPW_BIT_GPIO_GPIO3_MASK);
+
+ write_register(priv->net_dev, IPW_REG_GPIO, gpio);
+
+ /* Ready to receive commands */
+ priv->status |= STATUS_RUNNING;
+
+ /* The adapter has been reset; we are not associated */
+ priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static inline void ipw2100_reset_fatalerror(struct ipw2100_priv *priv)
+{
+ if (!priv->fatal_error)
+ return;
+
+ priv->fatal_errors[priv->fatal_index++] = priv->fatal_error;
+ priv->fatal_index %= IPW2100_ERROR_QUEUE;
+ priv->fatal_error = 0;
+}
+
+
+/* NOTE: Our interrupt is disabled when this method is called */
+static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
+{
+ u32 reg;
+ int i;
+
+ IPW_DEBUG_INFO("Power cycling the hardware.\n");
+
+ ipw2100_hw_set_gpio(priv);
+
+ /* Step 1. Stop Master Assert */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+
+ /* Step 2. Wait for stop Master Assert
+ * (not more then 50us, otherwise ret error */
+ i = 5;
+ do {
+ udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ } while(i--);
+
+ priv->status &= ~STATUS_RESET_PENDING;
+
+ if (!i) {
+ IPW_DEBUG_INFO("exit - waited too long for master assert stop\n");
+ return -EIO;
+ }
+
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+
+ /* Reset any fatal_error conditions */
+ ipw2100_reset_fatalerror(priv);
+
+ /* At this point, the adapter is now stopped and disabled */
+ priv->status &= ~(STATUS_RUNNING | STATUS_ASSOCIATING |
+ STATUS_ASSOCIATED | STATUS_ENABLED);
+
+ return 0;
+}
+
+/*
+ * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it
+ *
+ * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent.
+ *
+ * STATUS_CARD_DISABLE_NOTIFICATION will be sent regardless of
+ * if STATUS_ASSN_LOST is sent.
+ */
+static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
+{
+
+#define HW_PHY_OFF_LOOP_DELAY (HZ / 5000)
+
+ struct host_command cmd = {
+ .host_command = CARD_DISABLE_PHY_OFF,
+ .host_command_sequence = 0,
+ .host_command_length = 0,
+ };
+ int err, i;
+ u32 val1, val2;
+
+ IPW_DEBUG_HC("CARD_DISABLE_PHY_OFF\n");
+
+ /* Turn off the radio */
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ for (i = 0; i < 2500; i++) {
+ read_nic_dword(priv->net_dev, IPW2100_CONTROL_REG, &val1);
+ read_nic_dword(priv->net_dev, IPW2100_COMMAND, &val2);
+
+ if ((val1 & IPW2100_CONTROL_PHY_OFF) &&
+ (val2 & IPW2100_COMMAND_PHY_OFF))
+ return 0;
+
+ schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
+ }
+
+ return -EIO;
+}
+
+
+static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = HOST_COMPLETE,
+ .host_command_sequence = 0,
+ .host_command_length = 0
+ };
+ int err = 0;
+
+ IPW_DEBUG_HC("HOST_COMPLETE\n");
+
+ if (priv->status & STATUS_ENABLED)
+ return 0;
+
+ down(&priv->adapter_sem);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_HC("Command aborted due to RF kill active.\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ IPW_DEBUG_INFO("Failed to send HOST_COMPLETE command\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_ENABLED);
+ if (err) {
+ IPW_DEBUG_INFO(
+ "%s: card not responding to init command.\n",
+ priv->net_dev->name);
+ goto fail_up;
+ }
+
+ if (priv->stop_hang_check) {
+ priv->stop_hang_check = 0;
+ queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+ }
+
+fail_up:
+ up(&priv->adapter_sem);
+ return err;
+}
+
+static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
+{
+#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
+
+ struct host_command cmd = {
+ .host_command = HOST_PRE_POWER_DOWN,
+ .host_command_sequence = 0,
+ .host_command_length = 0,
+ };
+ int err, i;
+ u32 reg;
+
+ if (!(priv->status & STATUS_RUNNING))
+ return 0;
+
+ priv->status |= STATUS_STOPPING;
+
+ /* We can only shut down the card if the firmware is operational. So,
+ * if we haven't reset since a fatal_error, then we can not send the
+ * shutdown commands. */
+ if (!priv->fatal_error) {
+ /* First, make sure the adapter is enabled so that the PHY_OFF
+ * command can shut it down */
+ ipw2100_enable_adapter(priv);
+
+ err = ipw2100_hw_phy_off(priv);
+ if (err)
+ printk(KERN_WARNING DRV_NAME ": Error disabling radio %d\n", err);
+
+ /*
+ * If in D0-standby mode going directly to D3 may cause a
+ * PCI bus violation. Therefore we must change out of the D0
+ * state.
+ *
+ * Sending the PREPARE_FOR_POWER_DOWN will restrict the
+ * hardware from going into standby mode and will transition
+ * out of D0-standy if it is already in that state.
+ *
+ * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the
+ * driver upon completion. Once received, the driver can
+ * proceed to the D3 state.
+ *
+ * Prepare for power down command to fw. This command would
+ * take HW out of D0-standby and prepare it for D3 state.
+ *
+ * Currently FW does not support event notification for this
+ * event. Therefore, skip waiting for it. Just wait a fixed
+ * 100ms
+ */
+ IPW_DEBUG_HC("HOST_PRE_POWER_DOWN\n");
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Power down command failed: Error %d\n",
+ priv->net_dev->name, err);
+ else
+ schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
+ }
+
+ priv->status &= ~STATUS_ENABLED;
+
+ /*
+ * Set GPIO 3 writable by FW; GPIO 1 writable
+ * by driver and enable clock
+ */
+ ipw2100_hw_set_gpio(priv);
+
+ /*
+ * Power down adapter. Sequence:
+ * 1. Stop master assert (RESET_REG[9]=1)
+ * 2. Wait for stop master (RESET_REG[8]==1)
+ * 3. S/w reset assert (RESET_REG[7] = 1)
+ */
+
+ /* Stop master assert */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+
+ /* wait stop master not more than 50 usec.
+ * Otherwise return error. */
+ for (i = 5; i > 0; i--) {
+ udelay(10);
+
+ /* Check master stop bit */
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ }
+
+ if (i == 0)
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Could now power down adapter.\n",
+ priv->net_dev->name);
+
+ /* assert s/w reset */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_SW_RESET);
+
+ priv->status &= ~(STATUS_RUNNING | STATUS_STOPPING);
+
+ return 0;
+}
+
+
+static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = CARD_DISABLE,
+ .host_command_sequence = 0,
+ .host_command_length = 0
+ };
+ int err = 0;
+
+ IPW_DEBUG_HC("CARD_DISABLE\n");
+
+ if (!(priv->status & STATUS_ENABLED))
+ return 0;
+
+ /* Make sure we clear the associated state */
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+
+ if (!priv->stop_hang_check) {
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+ }
+
+ down(&priv->adapter_sem);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": exit - failed to send CARD_DISABLE command\n");
+ goto fail_up;
+ }
+
+ err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_DISABLED);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": exit - card failed to change to DISABLED\n");
+ goto fail_up;
+ }
+
+ IPW_DEBUG_INFO("TODO: implement scan state machine\n");
+
+fail_up:
+ up(&priv->adapter_sem);
+ return err;
+}
+
+static int ipw2100_set_scan_options(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = SET_SCAN_OPTIONS,
+ .host_command_sequence = 0,
+ .host_command_length = 8
+ };
+ int err;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ IPW_DEBUG_SCAN("setting scan options\n");
+
+ cmd.host_command_parameters[0] = 0;
+
+ if (!(priv->config & CFG_ASSOCIATE))
+ cmd.host_command_parameters[0] |= IPW_SCAN_NOASSOCIATE;
+ if ((priv->sec.flags & SEC_ENABLED) && priv->sec.enabled)
+ cmd.host_command_parameters[0] |= IPW_SCAN_MIXED_CELL;
+ if (priv->config & CFG_PASSIVE_SCAN)
+ cmd.host_command_parameters[0] |= IPW_SCAN_PASSIVE;
+
+ cmd.host_command_parameters[1] = priv->channel_mask;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ IPW_DEBUG_HC("SET_SCAN_OPTIONS 0x%04X\n",
+ cmd.host_command_parameters[0]);
+
+ return err;
+}
+
+static int ipw2100_start_scan(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = BROADCAST_SCAN,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ IPW_DEBUG_HC("START_SCAN\n");
+
+ cmd.host_command_parameters[0] = 0;
+
+ /* No scanning if in monitor mode */
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ return 1;
+
+ if (priv->status & STATUS_SCANNING) {
+ IPW_DEBUG_SCAN("Scan requested while already in scan...\n");
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("enter\n");
+
+ /* Not clearing here; doing so makes iwlist always return nothing...
+ *
+ * We should modify the table logic to use aging tables vs. clearing
+ * the table on each scan start.
+ */
+ IPW_DEBUG_SCAN("starting scan\n");
+
+ priv->status |= STATUS_SCANNING;
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ priv->status &= ~STATUS_SCANNING;
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return err;
+}
+
+static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
+{
+ unsigned long flags;
+ int rc = 0;
+ u32 lock;
+ u32 ord_len = sizeof(lock);
+
+ /* Quite if manually disabled. */
+ if (priv->status & STATUS_RF_KILL_SW) {
+ IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable "
+ "switch\n", priv->net_dev->name);
+ return 0;
+ }
+
+ /* If the interrupt is enabled, turn it off... */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+
+ /* Reset any fatal_error conditions */
+ ipw2100_reset_fatalerror(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ if (priv->status & STATUS_POWERED ||
+ (priv->status & STATUS_RESET_PENDING)) {
+ /* Power cycle the card ... */
+ if (ipw2100_power_cycle_adapter(priv)) {
+ printk(KERN_WARNING DRV_NAME ": %s: Could not cycle adapter.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+ } else
+ priv->status |= STATUS_POWERED;
+
+ /* Load the firmware, start the clocks, etc. */
+ if (ipw2100_start_adapter(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to start the firmware.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ ipw2100_initialize_ordinals(priv);
+
+ /* Determine capabilities of this particular HW configuration */
+ if (ipw2100_get_hw_features(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to determine HW features.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ lock = LOCK_NONE;
+ if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to clear ordinal lock.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ priv->status &= ~STATUS_SCANNING;
+
+ if (rf_kill_active(priv)) {
+ printk(KERN_INFO "%s: Radio is disabled by RF switch.\n",
+ priv->net_dev->name);
+
+ if (priv->stop_rf_kill) {
+ priv->stop_rf_kill = 0;
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ }
+
+ deferred = 1;
+ }
+
+ /* Turn on the interrupt so that commands can be processed */
+ ipw2100_enable_interrupts(priv);
+
+ /* Send all of the commands that must be sent prior to
+ * HOST_COMPLETE */
+ if (ipw2100_adapter_setup(priv)) {
+ printk(KERN_ERR DRV_NAME ": %s: Failed to start the card.\n",
+ priv->net_dev->name);
+ rc = 1;
+ goto exit;
+ }
+
+ if (!deferred) {
+ /* Enable the adapter - sends HOST_COMPLETE */
+ if (ipw2100_enable_adapter(priv)) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: failed in call to enable adapter.\n",
+ priv->net_dev->name);
+ ipw2100_hw_stop_adapter(priv);
+ rc = 1;
+ goto exit;
+ }
+
+
+ /* Start a scan . . . */
+ ipw2100_set_scan_options(priv);
+ ipw2100_start_scan(priv);
+ }
+
+ exit:
+ return rc;
+}
+
+/* Called by register_netdev() */
+static int ipw2100_net_init(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ipw2100_up(priv, 1);
+}
+
+static void ipw2100_down(struct ipw2100_priv *priv)
+{
+ unsigned long flags;
+ union iwreq_data wrqu = {
+ .ap_addr = {
+ .sa_family = ARPHRD_ETHER
+ }
+ };
+ int associated = priv->status & STATUS_ASSOCIATED;
+
+ /* Kill the RF switch timer */
+ if (!priv->stop_rf_kill) {
+ priv->stop_rf_kill = 1;
+ cancel_delayed_work(&priv->rf_kill);
+ }
+
+ /* Kill the firmare hang check timer */
+ if (!priv->stop_hang_check) {
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+ }
+
+ /* Kill any pending resets */
+ if (priv->status & STATUS_RESET_PENDING)
+ cancel_delayed_work(&priv->reset_work);
+
+ /* Make sure the interrupt is on so that FW commands will be
+ * processed correctly */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_enable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ if (ipw2100_hw_stop_adapter(priv))
+ printk(KERN_ERR DRV_NAME ": %s: Error stopping adapter.\n",
+ priv->net_dev->name);
+
+ /* Do not disable the interrupt until _after_ we disable
+ * the adaptor. Otherwise the CARD_DISABLE command will never
+ * be ack'd by the firmware */
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ if (priv->config & CFG_C3_DISABLED) {
+ IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n");
+ acpi_set_cstate_limit(priv->cstate_limit);
+ priv->config &= ~CFG_C3_DISABLED;
+ }
+#endif
+
+ /* We have to signal any supplicant if we are disassociating */
+ if (associated)
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+}
+
+static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
+{
+ unsigned long flags;
+ union iwreq_data wrqu = {
+ .ap_addr = {
+ .sa_family = ARPHRD_ETHER
+ }
+ };
+ int associated = priv->status & STATUS_ASSOCIATED;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ IPW_DEBUG_INFO(DRV_NAME ": %s: Restarting adapter.\n",
+ priv->net_dev->name);
+ priv->resets++;
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+ priv->status |= STATUS_SECURITY_UPDATED;
+
+ /* Force a power cycle even if interface hasn't been opened
+ * yet */
+ cancel_delayed_work(&priv->reset_work);
+ priv->status |= STATUS_RESET_PENDING;
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ down(&priv->action_sem);
+ /* stop timed checks so that they don't interfere with reset */
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->hang_check);
+
+ /* We have to signal any supplicant if we are disassociating */
+ if (associated)
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ ipw2100_up(priv, 0);
+ up(&priv->action_sem);
+
+}
+
+
+static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
+{
+
+#define MAC_ASSOCIATION_READ_DELAY (HZ)
+ int ret, len, essid_len;
+ char essid[IW_ESSID_MAX_SIZE];
+ u32 txrate;
+ u32 chan;
+ char *txratename;
+ u8 bssid[ETH_ALEN];
+
+ /*
+ * TBD: BSSID is usually 00:00:00:00:00:00 here and not
+ * an actual MAC of the AP. Seems like FW sets this
+ * address too late. Read it later and expose through
+ * /proc or schedule a later task to query and update
+ */
+
+ essid_len = IW_ESSID_MAX_SIZE;
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID,
+ essid, &essid_len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+
+ len = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE,
+ &txrate, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+
+ len = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+ len = ETH_ALEN;
+ ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len);
+ if (ret) {
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+ return;
+ }
+ memcpy(priv->ieee->bssid, bssid, ETH_ALEN);
+
+
+ switch (txrate) {
+ case TX_RATE_1_MBIT:
+ txratename = "1Mbps";
+ break;
+ case TX_RATE_2_MBIT:
+ txratename = "2Mbsp";
+ break;
+ case TX_RATE_5_5_MBIT:
+ txratename = "5.5Mbps";
+ break;
+ case TX_RATE_11_MBIT:
+ txratename = "11Mbps";
+ break;
+ default:
+ IPW_DEBUG_INFO("Unknown rate: %d\n", txrate);
+ txratename = "unknown rate";
+ break;
+ }
+
+ IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="
+ MAC_FMT ")\n",
+ priv->net_dev->name, escape_essid(essid, essid_len),
+ txratename, chan, MAC_ARG(bssid));
+
+ /* now we copy read ssid into dev */
+ if (!(priv->config & CFG_STATIC_ESSID)) {
+ priv->essid_len = min((u8)essid_len, (u8)IW_ESSID_MAX_SIZE);
+ memcpy(priv->essid, essid, priv->essid_len);
+ }
+ priv->channel = chan;
+ memcpy(priv->bssid, bssid, ETH_ALEN);
+
+ priv->status |= STATUS_ASSOCIATING;
+ priv->connect_start = get_seconds();
+
+ queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10);
+}
+
+
+static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
+ int length, int batch_mode)
+{
+ int ssid_len = min(length, IW_ESSID_MAX_SIZE);
+ struct host_command cmd = {
+ .host_command = SSID,
+ .host_command_sequence = 0,
+ .host_command_length = ssid_len
+ };
+ int err;
+
+ IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len));
+
+ if (ssid_len)
+ memcpy((char*)cmd.host_command_parameters,
+ essid, ssid_len);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ /* Bug in FW currently doesn't honor bit 0 in SET_SCAN_OPTIONS to
+ * disable auto association -- so we cheat by setting a bogus SSID */
+ if (!ssid_len && !(priv->config & CFG_ASSOCIATE)) {
+ int i;
+ u8 *bogus = (u8*)cmd.host_command_parameters;
+ for (i = 0; i < IW_ESSID_MAX_SIZE; i++)
+ bogus[i] = 0x18 + i;
+ cmd.host_command_length = IW_ESSID_MAX_SIZE;
+ }
+
+ /* NOTE: We always send the SSID command even if the provided ESSID is
+ * the same as what we currently think is set. */
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (!err) {
+ memset(priv->essid + ssid_len, 0,
+ IW_ESSID_MAX_SIZE - ssid_len);
+ memcpy(priv->essid, essid, ssid_len);
+ priv->essid_len = ssid_len;
+ }
+
+ if (!batch_mode) {
+ if (ipw2100_enable_adapter(priv))
+ err = -EIO;
+ }
+
+ return err;
+}
+
+static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
+ "disassociated: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid, priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
+
+ if (priv->status & STATUS_STOPPING) {
+ IPW_DEBUG_INFO("Card is stopping itself, discard ASSN_LOST.\n");
+ return;
+ }
+
+ memset(priv->bssid, 0, ETH_ALEN);
+ memset(priv->ieee->bssid, 0, ETH_ALEN);
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+
+ if (!(priv->status & STATUS_RUNNING))
+ return;
+
+ if (priv->status & STATUS_SECURITY_UPDATED)
+ queue_work(priv->workqueue, &priv->security_work);
+
+ queue_work(priv->workqueue, &priv->wx_event_work);
+}
+
+static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_INFO("%s: RF Kill state changed to radio OFF.\n",
+ priv->net_dev->name);
+
+ /* RF_KILL is now enabled (else we wouldn't be here) */
+ priv->status |= STATUS_RF_KILL_HW;
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ if (priv->config & CFG_C3_DISABLED) {
+ IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n");
+ acpi_set_cstate_limit(priv->cstate_limit);
+ priv->config &= ~CFG_C3_DISABLED;
+ }
+#endif
+
+ /* Make sure the RF Kill check timer is running */
+ priv->stop_rf_kill = 0;
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+}
+
+static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_SCAN("scan complete\n");
+ /* Age the scan results... */
+ priv->ieee->scans++;
+ priv->status &= ~STATUS_SCANNING;
+}
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW2100_HANDLER(v, f) { v, f, # v }
+struct ipw2100_status_indicator {
+ int status;
+ void (*cb)(struct ipw2100_priv *priv, u32 status);
+ char *name;
+};
+#else
+#define IPW2100_HANDLER(v, f) { v, f }
+struct ipw2100_status_indicator {
+ int status;
+ void (*cb)(struct ipw2100_priv *priv, u32 status);
+};
+#endif /* CONFIG_IPW_DEBUG */
+
+static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status)
+{
+ IPW_DEBUG_SCAN("Scanning...\n");
+ priv->status |= STATUS_SCANNING;
+}
+
+static const struct ipw2100_status_indicator status_handlers[] = {
+ IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL),
+ IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL),
+ IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),
+ IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost),
+ IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL),
+ IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete),
+ IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL),
+ IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL),
+ IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill),
+ IPW2100_HANDLER(IPW_STATE_DISABLED, NULL),
+ IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL),
+ IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning),
+ IPW2100_HANDLER(-1, NULL)
+};
+
+
+static void isr_status_change(struct ipw2100_priv *priv, int status)
+{
+ int i;
+
+ if (status == IPW_STATE_SCANNING &&
+ priv->status & STATUS_ASSOCIATED &&
+ !(priv->status & STATUS_SCANNING)) {
+ IPW_DEBUG_INFO("Scan detected while associated, with "
+ "no scan request. Restarting firmware.\n");
+
+ /* Wake up any sleeping jobs */
+ schedule_reset(priv);
+ }
+
+ for (i = 0; status_handlers[i].status != -1; i++) {
+ if (status == status_handlers[i].status) {
+ IPW_DEBUG_NOTIF("Status change: %s\n",
+ status_handlers[i].name);
+ if (status_handlers[i].cb)
+ status_handlers[i].cb(priv, status);
+ priv->wstats.status = status;
+ return;
+ }
+ }
+
+ IPW_DEBUG_NOTIF("unknown status received: %04x\n", status);
+}
+
+static void isr_rx_complete_command(
+ struct ipw2100_priv *priv,
+ struct ipw2100_cmd_header *cmd)
+{
+#ifdef CONFIG_IPW_DEBUG
+ if (cmd->host_command_reg < ARRAY_SIZE(command_types)) {
+ IPW_DEBUG_HC("Command completed '%s (%d)'\n",
+ command_types[cmd->host_command_reg],
+ cmd->host_command_reg);
+ }
+#endif
+ if (cmd->host_command_reg == HOST_COMPLETE)
+ priv->status |= STATUS_ENABLED;
+
+ if (cmd->host_command_reg == CARD_DISABLE)
+ priv->status &= ~STATUS_ENABLED;
+
+ priv->status &= ~STATUS_CMD_ACTIVE;
+
+ wake_up_interruptible(&priv->wait_command_queue);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *frame_types[] = {
+ "COMMAND_STATUS_VAL",
+ "STATUS_CHANGE_VAL",
+ "P80211_DATA_VAL",
+ "P8023_DATA_VAL",
+ "HOST_NOTIFICATION_VAL"
+};
+#endif
+
+
+static inline int ipw2100_alloc_skb(
+ struct ipw2100_priv *priv,
+ struct ipw2100_rx_packet *packet)
+{
+ packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));
+ if (!packet->skb)
+ return -ENOMEM;
+
+ packet->rxp = (struct ipw2100_rx *)packet->skb->data;
+ packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+ /* NOTE: pci_map_single does not return an error code, and 0 is a valid
+ * dma_addr */
+
+ return 0;
+}
+
+
+#define SEARCH_ERROR 0xffffffff
+#define SEARCH_FAIL 0xfffffffe
+#define SEARCH_SUCCESS 0xfffffff0
+#define SEARCH_DISCARD 0
+#define SEARCH_SNAPSHOT 1
+
+#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff))
+static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
+{
+ int i;
+ if (priv->snapshot[0])
+ return 1;
+ for (i = 0; i < 0x30; i++) {
+ priv->snapshot[i] = (u8*)kmalloc(0x1000, GFP_ATOMIC);
+ if (!priv->snapshot[i]) {
+ IPW_DEBUG_INFO("%s: Error allocating snapshot "
+ "buffer %d\n", priv->net_dev->name, i);
+ while (i > 0)
+ kfree(priv->snapshot[--i]);
+ priv->snapshot[0] = NULL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+{
+ int i;
+ if (!priv->snapshot[0])
+ return;
+ for (i = 0; i < 0x30; i++)
+ kfree(priv->snapshot[i]);
+ priv->snapshot[0] = NULL;
+}
+
+static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 *in_buf,
+ size_t len, int mode)
+{
+ u32 i, j;
+ u32 tmp;
+ u8 *s, *d;
+ u32 ret;
+
+ s = in_buf;
+ if (mode == SEARCH_SNAPSHOT) {
+ if (!ipw2100_snapshot_alloc(priv))
+ mode = SEARCH_DISCARD;
+ }
+
+ for (ret = SEARCH_FAIL, i = 0; i < 0x30000; i += 4) {
+ read_nic_dword(priv->net_dev, i, &tmp);
+ if (mode == SEARCH_SNAPSHOT)
+ *(u32 *)SNAPSHOT_ADDR(i) = tmp;
+ if (ret == SEARCH_FAIL) {
+ d = (u8*)&tmp;
+ for (j = 0; j < 4; j++) {
+ if (*s != *d) {
+ s = in_buf;
+ continue;
+ }
+
+ s++;
+ d++;
+
+ if ((s - in_buf) == len)
+ ret = (i + j) - len + 1;
+ }
+ } else if (mode == SEARCH_DISCARD)
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * 0) Disconnect the SKB from the firmware (just unmap)
+ * 1) Pack the ETH header into the SKB
+ * 2) Pass the SKB to the network stack
+ *
+ * When packet is provided by the firmware, it contains the following:
+ *
+ * . ieee80211_hdr
+ * . ieee80211_snap_hdr
+ *
+ * The size of the constructed ethernet
+ *
+ */
+#ifdef CONFIG_IPW2100_RX_DEBUG
+static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
+#endif
+
+static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv,
+ int i)
+{
+#ifdef CONFIG_IPW_DEBUG_C3
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ u32 match, reg;
+ int j;
+#endif
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ int limit;
+#endif
+
+ IPW_DEBUG_INFO(DRV_NAME ": PCI latency error detected at "
+ "0x%04zX.\n", i * sizeof(struct ipw2100_status));
+
+#ifdef ACPI_CSTATE_LIMIT_DEFINED
+ IPW_DEBUG_INFO(DRV_NAME ": Disabling C3 transitions.\n");
+ limit = acpi_get_cstate_limit();
+ if (limit > 2) {
+ priv->cstate_limit = limit;
+ acpi_set_cstate_limit(2);
+ priv->config |= CFG_C3_DISABLED;
+ }
+#endif
+
+#ifdef CONFIG_IPW_DEBUG_C3
+ /* Halt the fimrware so we can get a good image */
+ write_register(priv->net_dev, IPW_REG_RESET_REG,
+ IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+ j = 5;
+ do {
+ udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);
+ read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);
+
+ if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
+ break;
+ } while (j--);
+
+ match = ipw2100_match_buf(priv, (u8*)status,
+ sizeof(struct ipw2100_status),
+ SEARCH_SNAPSHOT);
+ if (match < SEARCH_SUCCESS)
+ IPW_DEBUG_INFO("%s: DMA status match in Firmware at "
+ "offset 0x%06X, length %d:\n",
+ priv->net_dev->name, match,
+ sizeof(struct ipw2100_status));
+ else
+ IPW_DEBUG_INFO("%s: No DMA status match in "
+ "Firmware.\n", priv->net_dev->name);
+
+ printk_buf((u8*)priv->status_queue.drv,
+ sizeof(struct ipw2100_status) * RX_QUEUE_LENGTH);
+#endif
+
+ priv->fatal_error = IPW2100_ERR_C3_CORRUPTION;
+ priv->ieee->stats.rx_errors++;
+ schedule_reset(priv);
+}
+
+static inline void isr_rx(struct ipw2100_priv *priv, int i,
+ struct ieee80211_rx_stats *stats)
+{
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+ IPW_DEBUG_RX("Handler...\n");
+
+ if (unlikely(status->frame_size > skb_tailroom(packet->skb))) {
+ IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"
+ " Dropping.\n",
+ priv->net_dev->name,
+ status->frame_size, skb_tailroom(packet->skb));
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ if (unlikely(!netif_running(priv->net_dev))) {
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+ return;
+ }
+
+ if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&
+ status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
+ IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR &&
+ !(priv->status & STATUS_ASSOCIATED))) {
+ IPW_DEBUG_DROP("Dropping packet while not associated.\n");
+ priv->wstats.discard.misc++;
+ return;
+ }
+
+
+ pci_unmap_single(priv->pci_dev,
+ packet->dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+
+ skb_put(packet->skb, status->frame_size);
+
+#ifdef CONFIG_IPW2100_RX_DEBUG
+ /* Make a copy of the frame so we can dump it to the logs if
+ * ieee80211_rx fails */
+ memcpy(packet_data, packet->skb->data,
+ min_t(u32, status->frame_size, IPW_RX_NIC_BUFFER_LENGTH));
+#endif
+
+ if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
+#ifdef CONFIG_IPW2100_RX_DEBUG
+ IPW_DEBUG_DROP("%s: Non consumed packet:\n",
+ priv->net_dev->name);
+ printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
+#endif
+ priv->ieee->stats.rx_errors++;
+
+ /* ieee80211_rx failed, so it didn't free the SKB */
+ dev_kfree_skb_any(packet->skb);
+ packet->skb = NULL;
+ }
+
+ /* We need to allocate a new SKB and attach it to the RDB. */
+ if (unlikely(ipw2100_alloc_skb(priv, packet))) {
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Unable to allocate SKB onto RBD ring - disabling "
+ "adapter.\n", priv->net_dev->name);
+ /* TODO: schedule adapter shutdown */
+ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n");
+ }
+
+ /* Update the RDB entry */
+ priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+}
+
+static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
+{
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ struct ipw2100_rx *u = priv->rx_buffers[i].rxp;
+ u16 frame_type = status->status_fields & STATUS_TYPE_MASK;
+
+ switch (frame_type) {
+ case COMMAND_STATUS_VAL:
+ return (status->frame_size != sizeof(u->rx_data.command));
+ case STATUS_CHANGE_VAL:
+ return (status->frame_size != sizeof(u->rx_data.status));
+ case HOST_NOTIFICATION_VAL:
+ return (status->frame_size < sizeof(u->rx_data.notification));
+ case P80211_DATA_VAL:
+ case P8023_DATA_VAL:
+#ifdef CONFIG_IPW2100_MONITOR
+ return 0;
+#else
+ switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ case IEEE80211_FTYPE_CTL:
+ return 0;
+ case IEEE80211_FTYPE_DATA:
+ return (status->frame_size >
+ IPW_MAX_802_11_PAYLOAD_LENGTH);
+ }
+#endif
+ }
+
+ return 1;
+}
+
+/*
+ * ipw2100 interrupts are disabled at this point, and the ISR
+ * is the only code that calls this method. So, we do not need
+ * to play with any locks.
+ *
+ * RX Queue works as follows:
+ *
+ * Read index - firmware places packet in entry identified by the
+ * Read index and advances Read index. In this manner,
+ * Read index will always point to the next packet to
+ * be filled--but not yet valid.
+ *
+ * Write index - driver fills this entry with an unused RBD entry.
+ * This entry has not filled by the firmware yet.
+ *
+ * In between the W and R indexes are the RBDs that have been received
+ * but not yet processed.
+ *
+ * The process of handling packets will start at WRITE + 1 and advance
+ * until it reaches the READ index.
+ *
+ * The WRITE index is cached in the variable 'priv->rx_queue.next'.
+ *
+ */
+static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
+{
+ struct ipw2100_bd_queue *rxq = &priv->rx_queue;
+ struct ipw2100_status_queue *sq = &priv->status_queue;
+ struct ipw2100_rx_packet *packet;
+ u16 frame_type;
+ u32 r, w, i, s;
+ struct ipw2100_rx *u;
+ struct ieee80211_rx_stats stats = {
+ .mac_time = jiffies,
+ };
+
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_READ_INDEX, &r);
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, &w);
+
+ if (r >= rxq->entries) {
+ IPW_DEBUG_RX("exit - bad read index\n");
+ return;
+ }
+
+ i = (rxq->next + 1) % rxq->entries;
+ s = i;
+ while (i != r) {
+ /* IPW_DEBUG_RX("r = %d : w = %d : processing = %d\n",
+ r, rxq->next, i); */
+
+ packet = &priv->rx_buffers[i];
+
+ /* Sync the DMA for the STATUS buffer so CPU is sure to get
+ * the correct values */
+ pci_dma_sync_single_for_cpu(
+ priv->pci_dev,
+ sq->nic + sizeof(struct ipw2100_status) * i,
+ sizeof(struct ipw2100_status),
+ PCI_DMA_FROMDEVICE);
+
+ /* Sync the DMA for the RX buffer so CPU is sure to get
+ * the correct values */
+ pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+
+ if (unlikely(ipw2100_corruption_check(priv, i))) {
+ ipw2100_corruption_detected(priv, i);
+ goto increment;
+ }
+
+ u = packet->rxp;
+ frame_type = sq->drv[i].status_fields &
+ STATUS_TYPE_MASK;
+ stats.rssi = sq->drv[i].rssi + IPW2100_RSSI_TO_DBM;
+ stats.len = sq->drv[i].frame_size;
+
+ stats.mask = 0;
+ if (stats.rssi != 0)
+ stats.mask |= IEEE80211_STATMASK_RSSI;
+ stats.freq = IEEE80211_24GHZ_BAND;
+
+ IPW_DEBUG_RX(
+ "%s: '%s' frame type received (%d).\n",
+ priv->net_dev->name, frame_types[frame_type],
+ stats.len);
+
+ switch (frame_type) {
+ case COMMAND_STATUS_VAL:
+ /* Reset Rx watchdog */
+ isr_rx_complete_command(
+ priv, &u->rx_data.command);
+ break;
+
+ case STATUS_CHANGE_VAL:
+ isr_status_change(priv, u->rx_data.status);
+ break;
+
+ case P80211_DATA_VAL:
+ case P8023_DATA_VAL:
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ isr_rx(priv, i, &stats);
+ break;
+ }
+#endif
+ if (stats.len < sizeof(u->rx_data.header))
+ break;
+ switch (WLAN_FC_GET_TYPE(u->rx_data.header.
+ frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ ieee80211_rx_mgt(priv->ieee,
+ &u->rx_data.header,
+ &stats);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+ break;
+
+ case IEEE80211_FTYPE_DATA:
+ isr_rx(priv, i, &stats);
+ break;
+
+ }
+ break;
+ }
+
+ increment:
+ /* clear status field associated with this RBD */
+ rxq->drv[i].status.info.field = 0;
+
+ i = (i + 1) % rxq->entries;
+ }
+
+ if (i != s) {
+ /* backtrack one entry, wrapping to end if at 0 */
+ rxq->next = (i ? i : rxq->entries) - 1;
+
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_RX_WRITE_INDEX,
+ rxq->next);
+ }
+}
+
+
+/*
+ * __ipw2100_tx_process
+ *
+ * This routine will determine whether the next packet on
+ * the fw_pend_list has been processed by the firmware yet.
+ *
+ * If not, then it does nothing and returns.
+ *
+ * If so, then it removes the item from the fw_pend_list, frees
+ * any associated storage, and places the item back on the
+ * free list of its source (either msg_free_list or tx_free_list)
+ *
+ * TX Queue works as follows:
+ *
+ * Read index - points to the next TBD that the firmware will
+ * process. The firmware will read the data, and once
+ * done processing, it will advance the Read index.
+ *
+ * Write index - driver fills this entry with an constructed TBD
+ * entry. The Write index is not advanced until the
+ * packet has been configured.
+ *
+ * In between the W and R indexes are the TBDs that have NOT been
+ * processed. Lagging behind the R index are packets that have
+ * been processed but have not been freed by the driver.
+ *
+ * In order to free old storage, an internal index will be maintained
+ * that points to the next packet to be freed. When all used
+ * packets have been freed, the oldest index will be the same as the
+ * firmware's read index.
+ *
+ * The OLDEST index is cached in the variable 'priv->tx_queue.oldest'
+ *
+ * Because the TBD structure can not contain arbitrary data, the
+ * driver must keep an internal queue of cached allocations such that
+ * it can put that data back into the tx_free_list and msg_free_list
+ * for use by future command and data packets.
+ *
+ */
+static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
+{
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ int descriptors_used;
+ int e, i;
+ u32 r, w, frag_num = 0;
+
+ if (list_empty(&priv->fw_pend_list))
+ return 0;
+
+ element = priv->fw_pend_list.next;
+
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+ tbd = &txq->drv[packet->index];
+
+ /* Determine how many TBD entries must be finished... */
+ switch (packet->type) {
+ case COMMAND:
+ /* COMMAND uses only one slot; don't advance */
+ descriptors_used = 1;
+ e = txq->oldest;
+ break;
+
+ case DATA:
+ /* DATA uses two slots; advance and loop position. */
+ descriptors_used = tbd->num_fragments;
+ frag_num = tbd->num_fragments - 1;
+ e = txq->oldest + frag_num;
+ e %= txq->entries;
+ break;
+
+ default:
+ printk(KERN_WARNING DRV_NAME ": %s: Bad fw_pend_list entry!\n",
+ priv->net_dev->name);
+ return 0;
+ }
+
+ /* if the last TBD is not done by NIC yet, then packet is
+ * not ready to be released.
+ *
+ */
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX,
+ &r);
+ read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ &w);
+ if (w != txq->next)
+ printk(KERN_WARNING DRV_NAME ": %s: write index mismatch\n",
+ priv->net_dev->name);
+
+ /*
+ * txq->next is the index of the last packet written txq->oldest is
+ * the index of the r is the index of the next packet to be read by
+ * firmware
+ */
+
+
+ /*
+ * Quick graphic to help you visualize the following
+ * if / else statement
+ *
+ * ===>| s---->|===============
+ * e>|
+ * | a | b | c | d | e | f | g | h | i | j | k | l
+ * r---->|
+ * w
+ *
+ * w - updated by driver
+ * r - updated by firmware
+ * s - start of oldest BD entry (txq->oldest)
+ * e - end of oldest BD entry
+ *
+ */
+ if (!((r <= w && (e < r || e >= w)) || (e < r && e >= w))) {
+ IPW_DEBUG_TX("exit - no processed packets ready to release.\n");
+ return 0;
+ }
+
+ list_del(element);
+ DEC_STAT(&priv->fw_pend_stat);
+
+#ifdef CONFIG_IPW_DEBUG
+ {
+ int i = txq->oldest;
+ IPW_DEBUG_TX(
+ "TX%d V=%p P=%04X T=%04X L=%d\n", i,
+ &txq->drv[i],
+ (u32)(txq->nic + i * sizeof(struct ipw2100_bd)),
+ txq->drv[i].host_addr,
+ txq->drv[i].buf_length);
+
+ if (packet->type == DATA) {
+ i = (i + 1) % txq->entries;
+
+ IPW_DEBUG_TX(
+ "TX%d V=%p P=%04X T=%04X L=%d\n", i,
+ &txq->drv[i],
+ (u32)(txq->nic + i *
+ sizeof(struct ipw2100_bd)),
+ (u32)txq->drv[i].host_addr,
+ txq->drv[i].buf_length);
+ }
+ }
+#endif
+
+ switch (packet->type) {
+ case DATA:
+ if (txq->drv[txq->oldest].status.info.fields.txType != 0)
+ printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. "
+ "Expecting DATA TBD but pulled "
+ "something else: ids %d=%d.\n",
+ priv->net_dev->name, txq->oldest, packet->index);
+
+ /* DATA packet; we have to unmap and free the SKB */
+ priv->ieee->stats.tx_packets++;
+ for (i = 0; i < frag_num; i++) {
+ tbd = &txq->drv[(packet->index + 1 + i) %
+ txq->entries];
+
+ IPW_DEBUG_TX(
+ "TX%d P=%08x L=%d\n",
+ (packet->index + 1 + i) % txq->entries,
+ tbd->host_addr, tbd->buf_length);
+
+ pci_unmap_single(priv->pci_dev,
+ tbd->host_addr,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+ }
+
+ priv->ieee->stats.tx_bytes += packet->info.d_struct.txb->payload_size;
+ ieee80211_txb_free(packet->info.d_struct.txb);
+ packet->info.d_struct.txb = NULL;
+
+ list_add_tail(element, &priv->tx_free_list);
+ INC_STAT(&priv->tx_free_stat);
+
+ /* We have a free slot in the Tx queue, so wake up the
+ * transmit layer if it is stopped. */
+ if (priv->status & STATUS_ASSOCIATED &&
+ netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_INFO(KERN_INFO
+ "%s: Waking net queue.\n",
+ priv->net_dev->name);
+ netif_wake_queue(priv->net_dev);
+ }
+
+ /* A packet was processed by the hardware, so update the
+ * watchdog */
+ priv->net_dev->trans_start = jiffies;
+
+ break;
+
+ case COMMAND:
+ if (txq->drv[txq->oldest].status.info.fields.txType != 1)
+ printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. "
+ "Expecting COMMAND TBD but pulled "
+ "something else: ids %d=%d.\n",
+ priv->net_dev->name, txq->oldest, packet->index);
+
+#ifdef CONFIG_IPW_DEBUG
+ if (packet->info.c_struct.cmd->host_command_reg <
+ sizeof(command_types) / sizeof(*command_types))
+ IPW_DEBUG_TX(
+ "Command '%s (%d)' processed: %d.\n",
+ command_types[packet->info.c_struct.cmd->host_command_reg],
+ packet->info.c_struct.cmd->host_command_reg,
+ packet->info.c_struct.cmd->cmd_status_reg);
+#endif
+
+ list_add_tail(element, &priv->msg_free_list);
+ INC_STAT(&priv->msg_free_stat);
+ break;
+ }
+
+ /* advance oldest used TBD pointer to start of next entry */
+ txq->oldest = (e + 1) % txq->entries;
+ /* increase available TBDs number */
+ txq->available += descriptors_used;
+ SET_STAT(&priv->txq_stat, txq->available);
+
+ IPW_DEBUG_TX("packet latency (send to process) %ld jiffies\n",
+ jiffies - packet->jiffy_start);
+
+ return (!list_empty(&priv->fw_pend_list));
+}
+
+
+static inline void __ipw2100_tx_complete(struct ipw2100_priv *priv)
+{
+ int i = 0;
+
+ while (__ipw2100_tx_process(priv) && i < 200) i++;
+
+ if (i == 200) {
+ printk(KERN_WARNING DRV_NAME ": "
+ "%s: Driver is running slow (%d iters).\n",
+ priv->net_dev->name, i);
+ }
+}
+
+
+static void ipw2100_tx_send_commands(struct ipw2100_priv *priv)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ int next = txq->next;
+
+ while (!list_empty(&priv->msg_pend_list)) {
+ /* if there isn't enough space in TBD queue, then
+ * don't stuff a new one in.
+ * NOTE: 3 are needed as a command will take one,
+ * and there is a minimum of 2 that must be
+ * maintained between the r and w indexes
+ */
+ if (txq->available <= 3) {
+ IPW_DEBUG_TX("no room in tx_queue\n");
+ break;
+ }
+
+ element = priv->msg_pend_list.next;
+ list_del(element);
+ DEC_STAT(&priv->msg_pend_stat);
+
+ packet = list_entry(element,
+ struct ipw2100_tx_packet, list);
+
+ IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n",
+ &txq->drv[txq->next],
+ (void*)(txq->nic + txq->next *
+ sizeof(struct ipw2100_bd)));
+
+ packet->index = txq->next;
+
+ tbd = &txq->drv[txq->next];
+
+ /* initialize TBD */
+ tbd->host_addr = packet->info.c_struct.cmd_phys;
+ tbd->buf_length = sizeof(struct ipw2100_cmd_header);
+ /* not marking number of fragments causes problems
+ * with f/w debug version */
+ tbd->num_fragments = 1;
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_COMMAND |
+ IPW_BD_STATUS_TX_INTERRUPT_ENABLE;
+
+ /* update TBD queue counters */
+ txq->next++;
+ txq->next %= txq->entries;
+ txq->available--;
+ DEC_STAT(&priv->txq_stat);
+
+ list_add_tail(element, &priv->fw_pend_list);
+ INC_STAT(&priv->fw_pend_stat);
+ }
+
+ if (txq->next != next) {
+ /* kick off the DMA by notifying firmware the
+ * write index has moved; make sure TBD stores are sync'd */
+ wmb();
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ txq->next);
+ }
+}
+
+
+/*
+ * ipw2100_tx_send_data
+ *
+ */
+static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
+{
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ struct ipw2100_bd_queue *txq = &priv->tx_queue;
+ struct ipw2100_bd *tbd;
+ int next = txq->next;
+ int i = 0;
+ struct ipw2100_data_header *ipw_hdr;
+ struct ieee80211_hdr_3addr *hdr;
+
+ while (!list_empty(&priv->tx_pend_list)) {
+ /* if there isn't enough space in TBD queue, then
+ * don't stuff a new one in.
+ * NOTE: 4 are needed as a data will take two,
+ * and there is a minimum of 2 that must be
+ * maintained between the r and w indexes
+ */
+ element = priv->tx_pend_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ if (unlikely(1 + packet->info.d_struct.txb->nr_frags >
+ IPW_MAX_BDS)) {
+ /* TODO: Support merging buffers if more than
+ * IPW_MAX_BDS are used */
+ IPW_DEBUG_INFO(
+ "%s: Maximum BD theshold exceeded. "
+ "Increase fragmentation level.\n",
+ priv->net_dev->name);
+ }
+
+ if (txq->available <= 3 +
+ packet->info.d_struct.txb->nr_frags) {
+ IPW_DEBUG_TX("no room in tx_queue\n");
+ break;
+ }
+
+ list_del(element);
+ DEC_STAT(&priv->tx_pend_stat);
+
+ tbd = &txq->drv[txq->next];
+
+ packet->index = txq->next;
+
+ ipw_hdr = packet->info.d_struct.data;
+ hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
+ fragments[0]->data;
+
+ if (priv->ieee->iw_mode == IW_MODE_INFRA) {
+ /* To DS: Addr1 = BSSID, Addr2 = SA,
+ Addr3 = DA */
+ memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(ipw_hdr->dst_addr, hdr->addr3, ETH_ALEN);
+ } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA,
+ Addr3 = BSSID */
+ memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(ipw_hdr->dst_addr, hdr->addr1, ETH_ALEN);
+ }
+
+ ipw_hdr->host_command_reg = SEND;
+ ipw_hdr->host_command_reg1 = 0;
+
+ /* For now we only support host based encryption */
+ ipw_hdr->needs_encryption = 0;
+ ipw_hdr->encrypted = packet->info.d_struct.txb->encrypted;
+ if (packet->info.d_struct.txb->nr_frags > 1)
+ ipw_hdr->fragment_size =
+ packet->info.d_struct.txb->frag_size - IEEE80211_3ADDR_LEN;
+ else
+ ipw_hdr->fragment_size = 0;
+
+ tbd->host_addr = packet->info.d_struct.data_phys;
+ tbd->buf_length = sizeof(struct ipw2100_data_header);
+ tbd->num_fragments = 1 + packet->info.d_struct.txb->nr_frags;
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT;
+ txq->next++;
+ txq->next %= txq->entries;
+
+ IPW_DEBUG_TX(
+ "data header tbd TX%d P=%08x L=%d\n",
+ packet->index, tbd->host_addr,
+ tbd->buf_length);
+#ifdef CONFIG_IPW_DEBUG
+ if (packet->info.d_struct.txb->nr_frags > 1)
+ IPW_DEBUG_FRAG("fragment Tx: %d frames\n",
+ packet->info.d_struct.txb->nr_frags);
+#endif
+
+ for (i = 0; i < packet->info.d_struct.txb->nr_frags; i++) {
+ tbd = &txq->drv[txq->next];
+ if (i == packet->info.d_struct.txb->nr_frags - 1)
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_INTERRUPT_ENABLE;
+ else
+ tbd->status.info.field =
+ IPW_BD_STATUS_TX_FRAME_802_3 |
+ IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT;
+
+ tbd->buf_length = packet->info.d_struct.txb->
+ fragments[i]->len - IEEE80211_3ADDR_LEN;
+
+ tbd->host_addr = pci_map_single(
+ priv->pci_dev,
+ packet->info.d_struct.txb->fragments[i]->data +
+ IEEE80211_3ADDR_LEN,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+
+ IPW_DEBUG_TX(
+ "data frag tbd TX%d P=%08x L=%d\n",
+ txq->next, tbd->host_addr, tbd->buf_length);
+
+ pci_dma_sync_single_for_device(
+ priv->pci_dev, tbd->host_addr,
+ tbd->buf_length,
+ PCI_DMA_TODEVICE);
+
+ txq->next++;
+ txq->next %= txq->entries;
+ }
+
+ txq->available -= 1 + packet->info.d_struct.txb->nr_frags;
+ SET_STAT(&priv->txq_stat, txq->available);
+
+ list_add_tail(element, &priv->fw_pend_list);
+ INC_STAT(&priv->fw_pend_stat);
+ }
+
+ if (txq->next != next) {
+ /* kick off the DMA by notifying firmware the
+ * write index has moved; make sure TBD stores are sync'd */
+ write_register(priv->net_dev,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX,
+ txq->next);
+ }
+ return;
+}
+
+static void ipw2100_irq_tasklet(struct ipw2100_priv *priv)
+{
+ struct net_device *dev = priv->net_dev;
+ unsigned long flags;
+ u32 inta, tmp;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ ipw2100_disable_interrupts(priv);
+
+ read_register(dev, IPW_REG_INTA, &inta);
+
+ IPW_DEBUG_ISR("enter - INTA: 0x%08lX\n",
+ (unsigned long)inta & IPW_INTERRUPT_MASK);
+
+ priv->in_isr++;
+ priv->interrupts++;
+
+ /* We do not loop and keep polling for more interrupts as this
+ * is frowned upon and doesn't play nicely with other potentially
+ * chained IRQs */
+ IPW_DEBUG_ISR("INTA: 0x%08lX\n",
+ (unsigned long)inta & IPW_INTERRUPT_MASK);
+
+ if (inta & IPW2100_INTA_FATAL_ERROR) {
+ printk(KERN_WARNING DRV_NAME
+ ": Fatal interrupt. Scheduling firmware restart.\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR);
+
+ read_nic_dword(dev, IPW_NIC_FATAL_ERROR, &priv->fatal_error);
+ IPW_DEBUG_INFO("%s: Fatal error value: 0x%08X\n",
+ priv->net_dev->name, priv->fatal_error);
+
+ read_nic_dword(dev, IPW_ERROR_ADDR(priv->fatal_error), &tmp);
+ IPW_DEBUG_INFO("%s: Fatal error address value: 0x%08X\n",
+ priv->net_dev->name, tmp);
+
+ /* Wake up any sleeping jobs */
+ schedule_reset(priv);
+ }
+
+ if (inta & IPW2100_INTA_PARITY_ERROR) {
+ printk(KERN_ERR DRV_NAME ": ***** PARITY ERROR INTERRUPT !!!! \n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_PARITY_ERROR);
+ }
+
+ if (inta & IPW2100_INTA_RX_TRANSFER) {
+ IPW_DEBUG_ISR("RX interrupt\n");
+
+ priv->rx_interrupts++;
+
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_RX_TRANSFER);
+
+ __ipw2100_rx_process(priv);
+ __ipw2100_tx_complete(priv);
+ }
+
+ if (inta & IPW2100_INTA_TX_TRANSFER) {
+ IPW_DEBUG_ISR("TX interrupt\n");
+
+ priv->tx_interrupts++;
+
+ write_register(dev, IPW_REG_INTA,
+ IPW2100_INTA_TX_TRANSFER);
+
+ __ipw2100_tx_complete(priv);
+ ipw2100_tx_send_commands(priv);
+ ipw2100_tx_send_data(priv);
+ }
+
+ if (inta & IPW2100_INTA_TX_COMPLETE) {
+ IPW_DEBUG_ISR("TX complete\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_TX_COMPLETE);
+
+ __ipw2100_tx_complete(priv);
+ }
+
+ if (inta & IPW2100_INTA_EVENT_INTERRUPT) {
+ /* ipw2100_handle_event(dev); */
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_EVENT_INTERRUPT);
+ }
+
+ if (inta & IPW2100_INTA_FW_INIT_DONE) {
+ IPW_DEBUG_ISR("FW init done interrupt\n");
+ priv->inta_other++;
+
+ read_register(dev, IPW_REG_INTA, &tmp);
+ if (tmp & (IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR)) {
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_FATAL_ERROR |
+ IPW2100_INTA_PARITY_ERROR);
+ }
+
+ write_register(dev, IPW_REG_INTA,
+ IPW2100_INTA_FW_INIT_DONE);
+ }
+
+ if (inta & IPW2100_INTA_STATUS_CHANGE) {
+ IPW_DEBUG_ISR("Status change interrupt\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_STATUS_CHANGE);
+ }
+
+ if (inta & IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE) {
+ IPW_DEBUG_ISR("slave host mode interrupt\n");
+ priv->inta_other++;
+ write_register(
+ dev, IPW_REG_INTA,
+ IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE);
+ }
+
+ priv->in_isr--;
+ ipw2100_enable_interrupts(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ IPW_DEBUG_ISR("exit\n");
+}
+
+
+static irqreturn_t ipw2100_interrupt(int irq, void *data,
+ struct pt_regs *regs)
+{
+ struct ipw2100_priv *priv = data;
+ u32 inta, inta_mask;
+
+ if (!data)
+ return IRQ_NONE;
+
+ spin_lock(&priv->low_lock);
+
+ /* We check to see if we should be ignoring interrupts before
+ * we touch the hardware. During ucode load if we try and handle
+ * an interrupt we can cause keyboard problems as well as cause
+ * the ucode to fail to initialize */
+ if (!(priv->status & STATUS_INT_ENABLED)) {
+ /* Shared IRQ */
+ goto none;
+ }
+
+ read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask);
+ read_register(priv->net_dev, IPW_REG_INTA, &inta);
+
+ if (inta == 0xFFFFFFFF) {
+ /* Hardware disappeared */
+ printk(KERN_WARNING DRV_NAME ": IRQ INTA == 0xFFFFFFFF\n");
+ goto none;
+ }
+
+ inta &= IPW_INTERRUPT_MASK;
+
+ if (!(inta & inta_mask)) {
+ /* Shared interrupt */
+ goto none;
+ }
+
+ /* We disable the hardware interrupt here just to prevent unneeded
+ * calls to be made. We disable this again within the actual
+ * work tasklet, so if another part of the code re-enables the
+ * interrupt, that is fine */
+ ipw2100_disable_interrupts(priv);
+
+ tasklet_schedule(&priv->irq_tasklet);
+ spin_unlock(&priv->low_lock);
+
+ return IRQ_HANDLED;
+ none:
+ spin_unlock(&priv->low_lock);
+ return IRQ_NONE;
+}
+
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
+ int pri)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_INFO("Can not transmit when not connected.\n");
+ priv->ieee->stats.tx_carrier_errors++;
+ netif_stop_queue(dev);
+ goto fail_unlock;
+ }
+
+ if (list_empty(&priv->tx_free_list))
+ goto fail_unlock;
+
+ element = priv->tx_free_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ packet->info.d_struct.txb = txb;
+
+ IPW_DEBUG_TX("Sending fragment (%d bytes):\n",
+ txb->fragments[0]->len);
+ printk_buf(IPW_DL_TX, txb->fragments[0]->data,
+ txb->fragments[0]->len);
+
+ packet->jiffy_start = jiffies;
+
+ list_del(element);
+ DEC_STAT(&priv->tx_free_stat);
+
+ list_add_tail(element, &priv->tx_pend_list);
+ INC_STAT(&priv->tx_pend_stat);
+
+ ipw2100_tx_send_data(priv);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+ return 0;
+
+ fail_unlock:
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+ return 1;
+}
+
+
+static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+ void *v;
+ dma_addr_t p;
+
+ priv->msg_buffers = (struct ipw2100_tx_packet *)kmalloc(
+ IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet),
+ GFP_KERNEL);
+ if (!priv->msg_buffers) {
+ printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg "
+ "buffers.\n", priv->net_dev->name);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
+ v = pci_alloc_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ &p);
+ if (!v) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: PCI alloc failed for msg "
+ "buffers.\n",
+ priv->net_dev->name);
+ err = -ENOMEM;
+ break;
+ }
+
+ memset(v, 0, sizeof(struct ipw2100_cmd_header));
+
+ priv->msg_buffers[i].type = COMMAND;
+ priv->msg_buffers[i].info.c_struct.cmd =
+ (struct ipw2100_cmd_header*)v;
+ priv->msg_buffers[i].info.c_struct.cmd_phys = p;
+ }
+
+ if (i == IPW_COMMAND_POOL_SIZE)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ priv->msg_buffers[j].info.c_struct.cmd,
+ priv->msg_buffers[j].info.c_struct.cmd_phys);
+ }
+
+ kfree(priv->msg_buffers);
+ priv->msg_buffers = NULL;
+
+ return err;
+}
+
+static int ipw2100_msg_initialize(struct ipw2100_priv *priv)
+{
+ int i;
+
+ INIT_LIST_HEAD(&priv->msg_free_list);
+ INIT_LIST_HEAD(&priv->msg_pend_list);
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++)
+ list_add_tail(&priv->msg_buffers[i].list, &priv->msg_free_list);
+ SET_STAT(&priv->msg_free_stat, i);
+
+ return 0;
+}
+
+static void ipw2100_msg_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ if (!priv->msg_buffers)
+ return;
+
+ for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
+ pci_free_consistent(priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ priv->msg_buffers[i].info.c_struct.cmd,
+ priv->msg_buffers[i].info.c_struct.cmd_phys);
+ }
+
+ kfree(priv->msg_buffers);
+ priv->msg_buffers = NULL;
+}
+
+static ssize_t show_pci(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_dev = container_of(d, struct pci_dev, dev);
+ char *out = buf;
+ int i, j;
+ u32 val;
+
+ for (i = 0; i < 16; i++) {
+ out += sprintf(out, "[%08X] ", i * 16);
+ for (j = 0; j < 16; j += 4) {
+ pci_read_config_dword(pci_dev, i * 16 + j, &val);
+ out += sprintf(out, "%08X ", val);
+ }
+ out += sprintf(out, "\n");
+ }
+
+ return out - buf;
+}
+static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL);
+
+static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->config);
+}
+static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL);
+
+static ssize_t show_status(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->status);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+static ssize_t show_capability(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->capability);
+}
+static DEVICE_ATTR(capability, S_IRUGO, show_capability, NULL);
+
+
+#define IPW2100_REG(x) { IPW_ ##x, #x }
+static const struct {
+ u32 addr;
+ const char *name;
+} hw_data[] = {
+ IPW2100_REG(REG_GP_CNTRL),
+ IPW2100_REG(REG_GPIO),
+ IPW2100_REG(REG_INTA),
+ IPW2100_REG(REG_INTA_MASK),
+ IPW2100_REG(REG_RESET_REG),
+};
+#define IPW2100_NIC(x, s) { x, #x, s }
+static const struct {
+ u32 addr;
+ const char *name;
+ size_t size;
+} nic_data[] = {
+ IPW2100_NIC(IPW2100_CONTROL_REG, 2),
+ IPW2100_NIC(0x210014, 1),
+ IPW2100_NIC(0x210000, 1),
+};
+#define IPW2100_ORD(x, d) { IPW_ORD_ ##x, #x, d }
+static const struct {
+ u8 index;
+ const char *name;
+ const char *desc;
+} ord_data[] = {
+ IPW2100_ORD(STAT_TX_HOST_REQUESTS, "requested Host Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_HOST_COMPLETE, "successful Host Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_DIR_DATA, "successful Directed Tx's (MSDU)"),
+ IPW2100_ORD(STAT_TX_DIR_DATA1, "successful Directed Tx's (MSDU) @ 1MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA2, "successful Directed Tx's (MSDU) @ 2MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA5_5, "successful Directed Tx's (MSDU) @ 5_5MB"),
+ IPW2100_ORD(STAT_TX_DIR_DATA11, "successful Directed Tx's (MSDU) @ 11MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA1, "successful Non_Directed Tx's (MSDU) @ 1MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA2, "successful Non_Directed Tx's (MSDU) @ 2MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA5_5, "successful Non_Directed Tx's (MSDU) @ 5.5MB"),
+ IPW2100_ORD(STAT_TX_NODIR_DATA11, "successful Non_Directed Tx's (MSDU) @ 11MB"),
+ IPW2100_ORD(STAT_NULL_DATA, "successful NULL data Tx's"),
+ IPW2100_ORD(STAT_TX_RTS, "successful Tx RTS"),
+ IPW2100_ORD(STAT_TX_CTS, "successful Tx CTS"),
+ IPW2100_ORD(STAT_TX_ACK, "successful Tx ACK"),
+ IPW2100_ORD(STAT_TX_ASSN, "successful Association Tx's"),
+ IPW2100_ORD(STAT_TX_ASSN_RESP, "successful Association response Tx's"),
+ IPW2100_ORD(STAT_TX_REASSN, "successful Reassociation Tx's"),
+ IPW2100_ORD(STAT_TX_REASSN_RESP, "successful Reassociation response Tx's"),
+ IPW2100_ORD(STAT_TX_PROBE, "probes successfully transmitted"),
+ IPW2100_ORD(STAT_TX_PROBE_RESP, "probe responses successfully transmitted"),
+ IPW2100_ORD(STAT_TX_BEACON, "tx beacon"),
+ IPW2100_ORD(STAT_TX_ATIM, "Tx ATIM"),
+ IPW2100_ORD(STAT_TX_DISASSN, "successful Disassociation TX"),
+ IPW2100_ORD(STAT_TX_AUTH, "successful Authentication Tx"),
+ IPW2100_ORD(STAT_TX_DEAUTH, "successful Deauthentication TX"),
+ IPW2100_ORD(STAT_TX_TOTAL_BYTES, "Total successful Tx data bytes"),
+ IPW2100_ORD(STAT_TX_RETRIES, "Tx retries"),
+ IPW2100_ORD(STAT_TX_RETRY1, "Tx retries at 1MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY2, "Tx retries at 2MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY5_5, "Tx retries at 5.5MBPS"),
+ IPW2100_ORD(STAT_TX_RETRY11, "Tx retries at 11MBPS"),
+ IPW2100_ORD(STAT_TX_FAILURES, "Tx Failures"),
+ IPW2100_ORD(STAT_TX_MAX_TRIES_IN_HOP,"times max tries in a hop failed"),
+ IPW2100_ORD(STAT_TX_DISASSN_FAIL, "times disassociation failed"),
+ IPW2100_ORD(STAT_TX_ERR_CTS, "missed/bad CTS frames"),
+ IPW2100_ORD(STAT_TX_ERR_ACK, "tx err due to acks"),
+ IPW2100_ORD(STAT_RX_HOST, "packets passed to host"),
+ IPW2100_ORD(STAT_RX_DIR_DATA, "directed packets"),
+ IPW2100_ORD(STAT_RX_DIR_DATA1, "directed packets at 1MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA2, "directed packets at 2MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA5_5, "directed packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_DIR_DATA11, "directed packets at 11MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA,"nondirected packets"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA1, "nondirected packets at 1MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA2, "nondirected packets at 2MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA5_5, "nondirected packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_NODIR_DATA11, "nondirected packets at 11MB"),
+ IPW2100_ORD(STAT_RX_NULL_DATA, "null data rx's"),
+ IPW2100_ORD(STAT_RX_RTS, "Rx RTS"),
+ IPW2100_ORD(STAT_RX_CTS, "Rx CTS"),
+ IPW2100_ORD(STAT_RX_ACK, "Rx ACK"),
+ IPW2100_ORD(STAT_RX_CFEND, "Rx CF End"),
+ IPW2100_ORD(STAT_RX_CFEND_ACK, "Rx CF End + CF Ack"),
+ IPW2100_ORD(STAT_RX_ASSN, "Association Rx's"),
+ IPW2100_ORD(STAT_RX_ASSN_RESP, "Association response Rx's"),
+ IPW2100_ORD(STAT_RX_REASSN, "Reassociation Rx's"),
+ IPW2100_ORD(STAT_RX_REASSN_RESP, "Reassociation response Rx's"),
+ IPW2100_ORD(STAT_RX_PROBE, "probe Rx's"),
+ IPW2100_ORD(STAT_RX_PROBE_RESP, "probe response Rx's"),
+ IPW2100_ORD(STAT_RX_BEACON, "Rx beacon"),
+ IPW2100_ORD(STAT_RX_ATIM, "Rx ATIM"),
+ IPW2100_ORD(STAT_RX_DISASSN, "disassociation Rx"),
+ IPW2100_ORD(STAT_RX_AUTH, "authentication Rx"),
+ IPW2100_ORD(STAT_RX_DEAUTH, "deauthentication Rx"),
+ IPW2100_ORD(STAT_RX_TOTAL_BYTES,"Total rx data bytes received"),
+ IPW2100_ORD(STAT_RX_ERR_CRC, "packets with Rx CRC error"),
+ IPW2100_ORD(STAT_RX_ERR_CRC1, "Rx CRC errors at 1MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC2, "Rx CRC errors at 2MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC5_5, "Rx CRC errors at 5.5MB"),
+ IPW2100_ORD(STAT_RX_ERR_CRC11, "Rx CRC errors at 11MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE1, "duplicate rx packets at 1MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE2, "duplicate rx packets at 2MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE5_5, "duplicate rx packets at 5.5MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE11, "duplicate rx packets at 11MB"),
+ IPW2100_ORD(STAT_RX_DUPLICATE, "duplicate rx packets"),
+ IPW2100_ORD(PERS_DB_LOCK, "locking fw permanent db"),
+ IPW2100_ORD(PERS_DB_SIZE, "size of fw permanent db"),
+ IPW2100_ORD(PERS_DB_ADDR, "address of fw permanent db"),
+ IPW2100_ORD(STAT_RX_INVALID_PROTOCOL, "rx frames with invalid protocol"),
+ IPW2100_ORD(SYS_BOOT_TIME, "Boot time"),
+ IPW2100_ORD(STAT_RX_NO_BUFFER, "rx frames rejected due to no buffer"),
+ IPW2100_ORD(STAT_RX_MISSING_FRAG, "rx frames dropped due to missing fragment"),
+ IPW2100_ORD(STAT_RX_ORPHAN_FRAG, "rx frames dropped due to non-sequential fragment"),
+ IPW2100_ORD(STAT_RX_ORPHAN_FRAME, "rx frames dropped due to unmatched 1st frame"),
+ IPW2100_ORD(STAT_RX_FRAG_AGEOUT, "rx frames dropped due to uncompleted frame"),
+ IPW2100_ORD(STAT_RX_ICV_ERRORS, "ICV errors during decryption"),
+ IPW2100_ORD(STAT_PSP_SUSPENSION,"times adapter suspended"),
+ IPW2100_ORD(STAT_PSP_BCN_TIMEOUT, "beacon timeout"),
+ IPW2100_ORD(STAT_PSP_POLL_TIMEOUT, "poll response timeouts"),
+ IPW2100_ORD(STAT_PSP_NONDIR_TIMEOUT, "timeouts waiting for last {broad,multi}cast pkt"),
+ IPW2100_ORD(STAT_PSP_RX_DTIMS, "PSP DTIMs received"),
+ IPW2100_ORD(STAT_PSP_RX_TIMS, "PSP TIMs received"),
+ IPW2100_ORD(STAT_PSP_STATION_ID,"PSP Station ID"),
+ IPW2100_ORD(LAST_ASSN_TIME, "RTC time of last association"),
+ IPW2100_ORD(STAT_PERCENT_MISSED_BCNS,"current calculation of % missed beacons"),
+ IPW2100_ORD(STAT_PERCENT_RETRIES,"current calculation of % missed tx retries"),
+ IPW2100_ORD(ASSOCIATED_AP_PTR, "0 if not associated, else pointer to AP table entry"),
+ IPW2100_ORD(AVAILABLE_AP_CNT, "AP's decsribed in the AP table"),
+ IPW2100_ORD(AP_LIST_PTR, "Ptr to list of available APs"),
+ IPW2100_ORD(STAT_AP_ASSNS, "associations"),
+ IPW2100_ORD(STAT_ASSN_FAIL, "association failures"),
+ IPW2100_ORD(STAT_ASSN_RESP_FAIL,"failures due to response fail"),
+ IPW2100_ORD(STAT_FULL_SCANS, "full scans"),
+ IPW2100_ORD(CARD_DISABLED, "Card Disabled"),
+ IPW2100_ORD(STAT_ROAM_INHIBIT, "times roaming was inhibited due to activity"),
+ IPW2100_ORD(RSSI_AT_ASSN, "RSSI of associated AP at time of association"),
+ IPW2100_ORD(STAT_ASSN_CAUSE1, "reassociation: no probe response or TX on hop"),
+ IPW2100_ORD(STAT_ASSN_CAUSE2, "reassociation: poor tx/rx quality"),
+ IPW2100_ORD(STAT_ASSN_CAUSE3, "reassociation: tx/rx quality (excessive AP load"),
+ IPW2100_ORD(STAT_ASSN_CAUSE4, "reassociation: AP RSSI level"),
+ IPW2100_ORD(STAT_ASSN_CAUSE5, "reassociations due to load leveling"),
+ IPW2100_ORD(STAT_AUTH_FAIL, "times authentication failed"),
+ IPW2100_ORD(STAT_AUTH_RESP_FAIL,"times authentication response failed"),
+ IPW2100_ORD(STATION_TABLE_CNT, "entries in association table"),
+ IPW2100_ORD(RSSI_AVG_CURR, "Current avg RSSI"),
+ IPW2100_ORD(POWER_MGMT_MODE, "Power mode - 0=CAM, 1=PSP"),
+ IPW2100_ORD(COUNTRY_CODE, "IEEE country code as recv'd from beacon"),
+ IPW2100_ORD(COUNTRY_CHANNELS, "channels suported by country"),
+ IPW2100_ORD(RESET_CNT, "adapter resets (warm)"),
+ IPW2100_ORD(BEACON_INTERVAL, "Beacon interval"),
+ IPW2100_ORD(ANTENNA_DIVERSITY, "TRUE if antenna diversity is disabled"),
+ IPW2100_ORD(DTIM_PERIOD, "beacon intervals between DTIMs"),
+ IPW2100_ORD(OUR_FREQ, "current radio freq lower digits - channel ID"),
+ IPW2100_ORD(RTC_TIME, "current RTC time"),
+ IPW2100_ORD(PORT_TYPE, "operating mode"),
+ IPW2100_ORD(CURRENT_TX_RATE, "current tx rate"),
+ IPW2100_ORD(SUPPORTED_RATES, "supported tx rates"),
+ IPW2100_ORD(ATIM_WINDOW, "current ATIM Window"),
+ IPW2100_ORD(BASIC_RATES, "basic tx rates"),
+ IPW2100_ORD(NIC_HIGHEST_RATE, "NIC highest tx rate"),
+ IPW2100_ORD(AP_HIGHEST_RATE, "AP highest tx rate"),
+ IPW2100_ORD(CAPABILITIES, "Management frame capability field"),
+ IPW2100_ORD(AUTH_TYPE, "Type of authentication"),
+ IPW2100_ORD(RADIO_TYPE, "Adapter card platform type"),
+ IPW2100_ORD(RTS_THRESHOLD, "Min packet length for RTS handshaking"),
+ IPW2100_ORD(INT_MODE, "International mode"),
+ IPW2100_ORD(FRAGMENTATION_THRESHOLD, "protocol frag threshold"),
+ IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_START_ADDRESS, "EEPROM offset in SRAM"),
+ IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_SIZE, "EEPROM size in SRAM"),
+ IPW2100_ORD(EEPROM_SKU_CAPABILITY, "EEPROM SKU Capability"),
+ IPW2100_ORD(EEPROM_IBSS_11B_CHANNELS, "EEPROM IBSS 11b channel set"),
+ IPW2100_ORD(MAC_VERSION, "MAC Version"),
+ IPW2100_ORD(MAC_REVISION, "MAC Revision"),
+ IPW2100_ORD(RADIO_VERSION, "Radio Version"),
+ IPW2100_ORD(NIC_MANF_DATE_TIME, "MANF Date/Time STAMP"),
+ IPW2100_ORD(UCODE_VERSION, "Ucode Version"),
+};
+
+
+static ssize_t show_registers(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char * out = buf;
+ u32 val = 0;
+
+ out += sprintf(out, "%30s [Address ] : Hex\n", "Register");
+
+ for (i = 0; i < (sizeof(hw_data) / sizeof(*hw_data)); i++) {
+ read_register(dev, hw_data[i].addr, &val);
+ out += sprintf(out, "%30s [%08X] : %08X\n",
+ hw_data[i].name, hw_data[i].addr, val);
+ }
+
+ return out - buf;
+}
+static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
+
+
+static ssize_t show_hardware(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char * out = buf;
+ int i;
+
+ out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry");
+
+ for (i = 0; i < (sizeof(nic_data) / sizeof(*nic_data)); i++) {
+ u8 tmp8;
+ u16 tmp16;
+ u32 tmp32;
+
+ switch (nic_data[i].size) {
+ case 1:
+ read_nic_byte(dev, nic_data[i].addr, &tmp8);
+ out += sprintf(out, "%30s [%08X] : %02X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp8);
+ break;
+ case 2:
+ read_nic_word(dev, nic_data[i].addr, &tmp16);
+ out += sprintf(out, "%30s [%08X] : %04X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp16);
+ break;
+ case 4:
+ read_nic_dword(dev, nic_data[i].addr, &tmp32);
+ out += sprintf(out, "%30s [%08X] : %08X\n",
+ nic_data[i].name, nic_data[i].addr,
+ tmp32);
+ break;
+ }
+ }
+ return out - buf;
+}
+static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL);
+
+
+static ssize_t show_memory(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ static unsigned long loop = 0;
+ int len = 0;
+ u32 buffer[4];
+ int i;
+ char line[81];
+
+ if (loop >= 0x30000)
+ loop = 0;
+
+ /* sysfs provides us PAGE_SIZE buffer */
+ while (len < PAGE_SIZE - 128 && loop < 0x30000) {
+
+ if (priv->snapshot[0]) for (i = 0; i < 4; i++)
+ buffer[i] = *(u32 *)SNAPSHOT_ADDR(loop + i * 4);
+ else for (i = 0; i < 4; i++)
+ read_nic_dword(dev, loop + i * 4, &buffer[i]);
+
+ if (priv->dump_raw)
+ len += sprintf(buf + len,
+ "%c%c%c%c"
+ "%c%c%c%c"
+ "%c%c%c%c"
+ "%c%c%c%c",
+ ((u8*)buffer)[0x0],
+ ((u8*)buffer)[0x1],
+ ((u8*)buffer)[0x2],
+ ((u8*)buffer)[0x3],
+ ((u8*)buffer)[0x4],
+ ((u8*)buffer)[0x5],
+ ((u8*)buffer)[0x6],
+ ((u8*)buffer)[0x7],
+ ((u8*)buffer)[0x8],
+ ((u8*)buffer)[0x9],
+ ((u8*)buffer)[0xa],
+ ((u8*)buffer)[0xb],
+ ((u8*)buffer)[0xc],
+ ((u8*)buffer)[0xd],
+ ((u8*)buffer)[0xe],
+ ((u8*)buffer)[0xf]);
+ else
+ len += sprintf(buf + len, "%s\n",
+ snprint_line(line, sizeof(line),
+ (u8*)buffer, 16, loop));
+ loop += 16;
+ }
+
+ return len;
+}
+
+static ssize_t store_memory(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ const char *p = buf;
+
+ if (count < 1)
+ return count;
+
+ if (p[0] == '1' ||
+ (count >= 2 && tolower(p[0]) == 'o' && tolower(p[1]) == 'n')) {
+ IPW_DEBUG_INFO("%s: Setting memory dump to RAW mode.\n",
+ dev->name);
+ priv->dump_raw = 1;
+
+ } else if (p[0] == '0' || (count >= 2 && tolower(p[0]) == 'o' &&
+ tolower(p[1]) == 'f')) {
+ IPW_DEBUG_INFO("%s: Setting memory dump to HEX mode.\n",
+ dev->name);
+ priv->dump_raw = 0;
+
+ } else if (tolower(p[0]) == 'r') {
+ IPW_DEBUG_INFO("%s: Resetting firmware snapshot.\n",
+ dev->name);
+ ipw2100_snapshot_free(priv);
+
+ } else
+ IPW_DEBUG_INFO("%s: Usage: 0|on = HEX, 1|off = RAW, "
+ "reset = clear memory snapshot\n",
+ dev->name);
+
+ return count;
+}
+static DEVICE_ATTR(memory, S_IWUSR|S_IRUGO, show_memory, store_memory);
+
+
+static ssize_t show_ordinals(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ u32 val = 0;
+ int len = 0;
+ u32 val_len;
+ static int loop = 0;
+
+ if (loop >= sizeof(ord_data) / sizeof(*ord_data))
+ loop = 0;
+
+ /* sysfs provides us PAGE_SIZE buffer */
+ while (len < PAGE_SIZE - 128 &&
+ loop < (sizeof(ord_data) / sizeof(*ord_data))) {
+
+ val_len = sizeof(u32);
+
+ if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val,
+ &val_len))
+ len += sprintf(buf + len, "[0x%02X] = ERROR %s\n",
+ ord_data[loop].index,
+ ord_data[loop].desc);
+ else
+ len += sprintf(buf + len, "[0x%02X] = 0x%08X %s\n",
+ ord_data[loop].index, val,
+ ord_data[loop].desc);
+ loop++;
+ }
+
+ return len;
+}
+static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL);
+
+
+static ssize_t show_stats(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char * out = buf;
+
+ out += sprintf(out, "interrupts: %d {tx: %d, rx: %d, other: %d}\n",
+ priv->interrupts, priv->tx_interrupts,
+ priv->rx_interrupts, priv->inta_other);
+ out += sprintf(out, "firmware resets: %d\n", priv->resets);
+ out += sprintf(out, "firmware hangs: %d\n", priv->hangs);
+#ifdef CONFIG_IPW_DEBUG
+ out += sprintf(out, "packet mismatch image: %s\n",
+ priv->snapshot[0] ? "YES" : "NO");
+#endif
+
+ return out - buf;
+}
+static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+
+static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
+{
+ int err;
+
+ if (mode == priv->ieee->iw_mode)
+ return 0;
+
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+
+ switch (mode) {
+ case IW_MODE_INFRA:
+ priv->net_dev->type = ARPHRD_ETHER;
+ break;
+ case IW_MODE_ADHOC:
+ priv->net_dev->type = ARPHRD_ETHER;
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ priv->last_mode = priv->ieee->iw_mode;
+ priv->net_dev->type = ARPHRD_IEEE80211;
+ break;
+#endif /* CONFIG_IPW2100_MONITOR */
+ }
+
+ priv->ieee->iw_mode = mode;
+
+#ifdef CONFIG_PM
+ /* Indicate ipw2100_download_firmware download firmware
+ * from disk instead of memory. */
+ ipw2100_firmware.version = 0;
+#endif
+
+ printk(KERN_INFO "%s: Reseting on mode change.\n",
+ priv->net_dev->name);
+ priv->reset_backoff = 0;
+ schedule_reset(priv);
+
+ return 0;
+}
+
+static ssize_t show_internals(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ int len = 0;
+
+#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" # y "\n", priv-> x)
+
+ if (priv->status & STATUS_ASSOCIATED)
+ len += sprintf(buf + len, "connected: %lu\n",
+ get_seconds() - priv->connect_start);
+ else
+ len += sprintf(buf + len, "not connected\n");
+
+ DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], p);
+ DUMP_VAR(status, 08lx);
+ DUMP_VAR(config, 08lx);
+ DUMP_VAR(capability, 08lx);
+
+ len += sprintf(buf + len, "last_rtc: %lu\n", (unsigned long)priv->last_rtc);
+
+ DUMP_VAR(fatal_error, d);
+ DUMP_VAR(stop_hang_check, d);
+ DUMP_VAR(stop_rf_kill, d);
+ DUMP_VAR(messages_sent, d);
+
+ DUMP_VAR(tx_pend_stat.value, d);
+ DUMP_VAR(tx_pend_stat.hi, d);
+
+ DUMP_VAR(tx_free_stat.value, d);
+ DUMP_VAR(tx_free_stat.lo, d);
+
+ DUMP_VAR(msg_free_stat.value, d);
+ DUMP_VAR(msg_free_stat.lo, d);
+
+ DUMP_VAR(msg_pend_stat.value, d);
+ DUMP_VAR(msg_pend_stat.hi, d);
+
+ DUMP_VAR(fw_pend_stat.value, d);
+ DUMP_VAR(fw_pend_stat.hi, d);
+
+ DUMP_VAR(txq_stat.value, d);
+ DUMP_VAR(txq_stat.lo, d);
+
+ DUMP_VAR(ieee->scans, d);
+ DUMP_VAR(reset_backoff, d);
+
+ return len;
+}
+static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL);
+
+
+static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ u8 bssid[ETH_ALEN];
+ u32 chan = 0;
+ char * out = buf;
+ int length;
+ int ret;
+
+ memset(essid, 0, sizeof(essid));
+ memset(bssid, 0, sizeof(bssid));
+
+ length = IW_ESSID_MAX_SIZE;
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID, essid, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ length = sizeof(bssid);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID,
+ bssid, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ length = sizeof(u32);
+ ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &length);
+ if (ret)
+ IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
+ __LINE__);
+
+ out += sprintf(out, "ESSID: %s\n", essid);
+ out += sprintf(out, "BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ bssid[0], bssid[1], bssid[2],
+ bssid[3], bssid[4], bssid[5]);
+ out += sprintf(out, "Channel: %d\n", chan);
+
+ return out - buf;
+}
+static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL);
+
+
+#ifdef CONFIG_IPW_DEBUG
+static ssize_t show_debug_level(struct device_driver *d, char *buf)
+{
+ return sprintf(buf, "0x%08X\n", ipw2100_debug_level);
+}
+
+static ssize_t store_debug_level(struct device_driver *d, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ u32 val;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buf)
+ IPW_DEBUG_INFO(DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ipw2100_debug_level = val;
+
+ return strnlen(buf, count);
+}
+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level,
+ store_debug_level);
+#endif /* CONFIG_IPW_DEBUG */
+
+
+static ssize_t show_fatal_error(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ char *out = buf;
+ int i;
+
+ if (priv->fatal_error)
+ out += sprintf(out, "0x%08X\n",
+ priv->fatal_error);
+ else
+ out += sprintf(out, "0\n");
+
+ for (i = 1; i <= IPW2100_ERROR_QUEUE; i++) {
+ if (!priv->fatal_errors[(priv->fatal_index - i) %
+ IPW2100_ERROR_QUEUE])
+ continue;
+
+ out += sprintf(out, "%d. 0x%08X\n", i,
+ priv->fatal_errors[(priv->fatal_index - i) %
+ IPW2100_ERROR_QUEUE]);
+ }
+
+ return out - buf;
+}
+
+static ssize_t store_fatal_error(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ schedule_reset(priv);
+ return count;
+}
+static DEVICE_ATTR(fatal_error, S_IWUSR|S_IRUGO, show_fatal_error, store_fatal_error);
+
+
+static ssize_t show_scan_age(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ return sprintf(buf, "%d\n", priv->ieee->scan_age);
+}
+
+static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ struct net_device *dev = priv->net_dev;
+ char buffer[] = "00000000";
+ unsigned long len =
+ (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
+ unsigned long val;
+ char *p = buffer;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ strncpy(buffer, buf, len);
+ buffer[len] = 0;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buffer) {
+ IPW_DEBUG_INFO("%s: user supplied invalid value.\n",
+ dev->name);
+ } else {
+ priv->ieee->scan_age = val;
+ IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age);
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+ return len;
+}
+static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
+
+
+static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ /* 0 - RF kill not enabled
+ 1 - SW based RF kill active (sysfs)
+ 2 - HW based RF kill active
+ 3 - Both HW and SW baed RF kill active */
+ struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data;
+ int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
+ (rf_kill_active(priv) ? 0x2 : 0x0);
+ return sprintf(buf, "%i\n", val);
+}
+
+static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
+{
+ if ((disable_radio ? 1 : 0) ==
+ (priv->status & STATUS_RF_KILL_SW ? 1 : 0))
+ return 0 ;
+
+ IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n",
+ disable_radio ? "OFF" : "ON");
+
+ down(&priv->action_sem);
+
+ if (disable_radio) {
+ priv->status |= STATUS_RF_KILL_SW;
+ ipw2100_down(priv);
+ } else {
+ priv->status &= ~STATUS_RF_KILL_SW;
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by HW switch\n");
+ /* Make sure the RF_KILL check timer is running */
+ priv->stop_rf_kill = 0;
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ HZ);
+ } else
+ schedule_reset(priv);
+ }
+
+ up(&priv->action_sem);
+ return 1;
+}
+
+static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw2100_priv *priv = dev_get_drvdata(d);
+ ipw_radio_kill_sw(priv, buf[0] == '1');
+ return count;
+}
+static DEVICE_ATTR(rf_kill, S_IWUSR|S_IRUGO, show_rf_kill, store_rf_kill);
+
+
+static struct attribute *ipw2100_sysfs_entries[] = {
+ &dev_attr_hardware.attr,
+ &dev_attr_registers.attr,
+ &dev_attr_ordinals.attr,
+ &dev_attr_pci.attr,
+ &dev_attr_stats.attr,
+ &dev_attr_internals.attr,
+ &dev_attr_bssinfo.attr,
+ &dev_attr_memory.attr,
+ &dev_attr_scan_age.attr,
+ &dev_attr_fatal_error.attr,
+ &dev_attr_rf_kill.attr,
+ &dev_attr_cfg.attr,
+ &dev_attr_status.attr,
+ &dev_attr_capability.attr,
+ NULL,
+};
+
+static struct attribute_group ipw2100_attribute_group = {
+ .attrs = ipw2100_sysfs_entries,
+};
+
+
+static int status_queue_allocate(struct ipw2100_priv *priv, int entries)
+{
+ struct ipw2100_status_queue *q = &priv->status_queue;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ q->size = entries * sizeof(struct ipw2100_status);
+ q->drv = (struct ipw2100_status *)pci_alloc_consistent(
+ priv->pci_dev, q->size, &q->nic);
+ if (!q->drv) {
+ IPW_DEBUG_WARNING(
+ "Can not allocate status queue.\n");
+ return -ENOMEM;
+ }
+
+ memset(q->drv, 0, q->size);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static void status_queue_free(struct ipw2100_priv *priv)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->status_queue.drv) {
+ pci_free_consistent(
+ priv->pci_dev, priv->status_queue.size,
+ priv->status_queue.drv, priv->status_queue.nic);
+ priv->status_queue.drv = NULL;
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static int bd_queue_allocate(struct ipw2100_priv *priv,
+ struct ipw2100_bd_queue *q, int entries)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ memset(q, 0, sizeof(struct ipw2100_bd_queue));
+
+ q->entries = entries;
+ q->size = entries * sizeof(struct ipw2100_bd);
+ q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic);
+ if (!q->drv) {
+ IPW_DEBUG_INFO("can't allocate shared memory for buffer descriptors\n");
+ return -ENOMEM;
+ }
+ memset(q->drv, 0, q->size);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+static void bd_queue_free(struct ipw2100_priv *priv,
+ struct ipw2100_bd_queue *q)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ if (!q)
+ return;
+
+ if (q->drv) {
+ pci_free_consistent(priv->pci_dev,
+ q->size, q->drv, q->nic);
+ q->drv = NULL;
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void bd_queue_initialize(
+ struct ipw2100_priv *priv, struct ipw2100_bd_queue * q,
+ u32 base, u32 size, u32 r, u32 w)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ IPW_DEBUG_INFO("initializing bd queue at virt=%p, phys=%08x\n", q->drv, (u32)q->nic);
+
+ write_register(priv->net_dev, base, q->nic);
+ write_register(priv->net_dev, size, q->entries);
+ write_register(priv->net_dev, r, q->oldest);
+ write_register(priv->net_dev, w, q->next);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void ipw2100_kill_workqueue(struct ipw2100_priv *priv)
+{
+ if (priv->workqueue) {
+ priv->stop_rf_kill = 1;
+ priv->stop_hang_check = 1;
+ cancel_delayed_work(&priv->reset_work);
+ cancel_delayed_work(&priv->security_work);
+ cancel_delayed_work(&priv->wx_event_work);
+ cancel_delayed_work(&priv->hang_check);
+ cancel_delayed_work(&priv->rf_kill);
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ }
+}
+
+static int ipw2100_tx_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+ void *v;
+ dma_addr_t p;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = bd_queue_allocate(priv, &priv->tx_queue, TX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_ERROR("%s: failed bd_queue_allocate\n",
+ priv->net_dev->name);
+ return err;
+ }
+
+ priv->tx_buffers = (struct ipw2100_tx_packet *)kmalloc(
+ TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet),
+ GFP_ATOMIC);
+ if (!priv->tx_buffers) {
+ printk(KERN_ERR DRV_NAME ": %s: alloc failed form tx buffers.\n",
+ priv->net_dev->name);
+ bd_queue_free(priv, &priv->tx_queue);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ v = pci_alloc_consistent(
+ priv->pci_dev, sizeof(struct ipw2100_data_header), &p);
+ if (!v) {
+ printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for tx "
+ "buffers.\n", priv->net_dev->name);
+ err = -ENOMEM;
+ break;
+ }
+
+ priv->tx_buffers[i].type = DATA;
+ priv->tx_buffers[i].info.d_struct.data = (struct ipw2100_data_header*)v;
+ priv->tx_buffers[i].info.d_struct.data_phys = p;
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+
+ if (i == TX_PENDED_QUEUE_LENGTH)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_data_header),
+ priv->tx_buffers[j].info.d_struct.data,
+ priv->tx_buffers[j].info.d_struct.data_phys);
+ }
+
+ kfree(priv->tx_buffers);
+ priv->tx_buffers = NULL;
+
+ return err;
+}
+
+static void ipw2100_tx_initialize(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ /*
+ * reinitialize packet info lists
+ */
+ INIT_LIST_HEAD(&priv->fw_pend_list);
+ INIT_STAT(&priv->fw_pend_stat);
+
+ /*
+ * reinitialize lists
+ */
+ INIT_LIST_HEAD(&priv->tx_pend_list);
+ INIT_LIST_HEAD(&priv->tx_free_list);
+ INIT_STAT(&priv->tx_pend_stat);
+ INIT_STAT(&priv->tx_free_stat);
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ /* We simply drop any SKBs that have been queued for
+ * transmit */
+ if (priv->tx_buffers[i].info.d_struct.txb) {
+ ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb);
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+
+ list_add_tail(&priv->tx_buffers[i].list, &priv->tx_free_list);
+ }
+
+ SET_STAT(&priv->tx_free_stat, i);
+
+ priv->tx_queue.oldest = 0;
+ priv->tx_queue.available = priv->tx_queue.entries;
+ priv->tx_queue.next = 0;
+ INIT_STAT(&priv->txq_stat);
+ SET_STAT(&priv->txq_stat, priv->tx_queue.available);
+
+ bd_queue_initialize(priv, &priv->tx_queue,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX,
+ IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX);
+
+ IPW_DEBUG_INFO("exit\n");
+
+}
+
+static void ipw2100_tx_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ bd_queue_free(priv, &priv->tx_queue);
+
+ if (!priv->tx_buffers)
+ return;
+
+ for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
+ if (priv->tx_buffers[i].info.d_struct.txb) {
+ ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb);
+ priv->tx_buffers[i].info.d_struct.txb = NULL;
+ }
+ if (priv->tx_buffers[i].info.d_struct.data)
+ pci_free_consistent(
+ priv->pci_dev,
+ sizeof(struct ipw2100_data_header),
+ priv->tx_buffers[i].info.d_struct.data,
+ priv->tx_buffers[i].info.d_struct.data_phys);
+ }
+
+ kfree(priv->tx_buffers);
+ priv->tx_buffers = NULL;
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+
+
+static int ipw2100_rx_allocate(struct ipw2100_priv *priv)
+{
+ int i, j, err = -EINVAL;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = bd_queue_allocate(priv, &priv->rx_queue, RX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_INFO("failed bd_queue_allocate\n");
+ return err;
+ }
+
+ err = status_queue_allocate(priv, RX_QUEUE_LENGTH);
+ if (err) {
+ IPW_DEBUG_INFO("failed status_queue_allocate\n");
+ bd_queue_free(priv, &priv->rx_queue);
+ return err;
+ }
+
+ /*
+ * allocate packets
+ */
+ priv->rx_buffers = (struct ipw2100_rx_packet *)
+ kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet),
+ GFP_KERNEL);
+ if (!priv->rx_buffers) {
+ IPW_DEBUG_INFO("can't allocate rx packet buffer table\n");
+
+ bd_queue_free(priv, &priv->rx_queue);
+
+ status_queue_free(priv);
+
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < RX_QUEUE_LENGTH; i++) {
+ struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+ err = ipw2100_alloc_skb(priv, packet);
+ if (unlikely(err)) {
+ err = -ENOMEM;
+ break;
+ }
+
+ /* The BD holds the cache aligned address */
+ priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+ priv->rx_queue.drv[i].buf_length = IPW_RX_NIC_BUFFER_LENGTH;
+ priv->status_queue.drv[i].status_fields = 0;
+ }
+
+ if (i == RX_QUEUE_LENGTH)
+ return 0;
+
+ for (j = 0; j < i; j++) {
+ pci_unmap_single(priv->pci_dev, priv->rx_buffers[j].dma_addr,
+ sizeof(struct ipw2100_rx_packet),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(priv->rx_buffers[j].skb);
+ }
+
+ kfree(priv->rx_buffers);
+ priv->rx_buffers = NULL;
+
+ bd_queue_free(priv, &priv->rx_queue);
+
+ status_queue_free(priv);
+
+ return err;
+}
+
+static void ipw2100_rx_initialize(struct ipw2100_priv *priv)
+{
+ IPW_DEBUG_INFO("enter\n");
+
+ priv->rx_queue.oldest = 0;
+ priv->rx_queue.available = priv->rx_queue.entries - 1;
+ priv->rx_queue.next = priv->rx_queue.entries - 1;
+
+ INIT_STAT(&priv->rxq_stat);
+ SET_STAT(&priv->rxq_stat, priv->rx_queue.available);
+
+ bd_queue_initialize(priv, &priv->rx_queue,
+ IPW_MEM_HOST_SHARED_RX_BD_BASE,
+ IPW_MEM_HOST_SHARED_RX_BD_SIZE,
+ IPW_MEM_HOST_SHARED_RX_READ_INDEX,
+ IPW_MEM_HOST_SHARED_RX_WRITE_INDEX);
+
+ /* set up the status queue */
+ write_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_STATUS_BASE,
+ priv->status_queue.nic);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static void ipw2100_rx_free(struct ipw2100_priv *priv)
+{
+ int i;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ bd_queue_free(priv, &priv->rx_queue);
+ status_queue_free(priv);
+
+ if (!priv->rx_buffers)
+ return;
+
+ for (i = 0; i < RX_QUEUE_LENGTH; i++) {
+ if (priv->rx_buffers[i].rxp) {
+ pci_unmap_single(priv->pci_dev,
+ priv->rx_buffers[i].dma_addr,
+ sizeof(struct ipw2100_rx),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(priv->rx_buffers[i].skb);
+ }
+ }
+
+ kfree(priv->rx_buffers);
+ priv->rx_buffers = NULL;
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
+{
+ u32 length = ETH_ALEN;
+ u8 mac[ETH_ALEN];
+
+ int err;
+
+ err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC,
+ mac, &length);
+ if (err) {
+ IPW_DEBUG_INFO("MAC address read failed\n");
+ return -EIO;
+ }
+ IPW_DEBUG_INFO("card MAC is %02X:%02X:%02X:%02X:%02X:%02X\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ memcpy(priv->net_dev->dev_addr, mac, ETH_ALEN);
+
+ return 0;
+}
+
+/********************************************************************
+ *
+ * Firmware Commands
+ *
+ ********************************************************************/
+
+static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = ADAPTER_ADDRESS,
+ .host_command_sequence = 0,
+ .host_command_length = ETH_ALEN
+ };
+ int err;
+
+ IPW_DEBUG_HC("SET_MAC_ADDRESS\n");
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->config & CFG_CUSTOM_MAC) {
+ memcpy(cmd.host_command_parameters, priv->mac_addr,
+ ETH_ALEN);
+ memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
+ } else
+ memcpy(cmd.host_command_parameters, priv->net_dev->dev_addr,
+ ETH_ALEN);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ IPW_DEBUG_INFO("exit\n");
+ return err;
+}
+
+static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = PORT_TYPE,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(u32)
+ };
+ int err;
+
+ switch (port_type) {
+ case IW_MODE_INFRA:
+ cmd.host_command_parameters[0] = IPW_BSS;
+ break;
+ case IW_MODE_ADHOC:
+ cmd.host_command_parameters[0] = IPW_IBSS;
+ break;
+ }
+
+ IPW_DEBUG_HC("PORT_TYPE: %s\n",
+ port_type == IPW_IBSS ? "Ad-Hoc" : "Managed");
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+
+static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = CHANNEL,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(u32)
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = channel;
+
+ IPW_DEBUG_HC("CHANNEL: %d\n", channel);
+
+ /* If BSS then we don't support channel selection */
+ if (priv->ieee->iw_mode == IW_MODE_INFRA)
+ return 0;
+
+ if ((channel != 0) &&
+ ((channel < REG_MIN_CHANNEL) || (channel > REG_MAX_CHANNEL)))
+ return -EINVAL;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err) {
+ IPW_DEBUG_INFO("Failed to set channel to %d",
+ channel);
+ return err;
+ }
+
+ if (channel)
+ priv->config |= CFG_STATIC_CHANNEL;
+ else
+ priv->config &= ~CFG_STATIC_CHANNEL;
+
+ priv->channel = channel;
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SYSTEM_CONFIG,
+ .host_command_sequence = 0,
+ .host_command_length = 12,
+ };
+ u32 ibss_mask, len = sizeof(u32);
+ int err;
+
+ /* Set system configuration */
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC)
+ cmd.host_command_parameters[0] |= IPW_CFG_IBSS_AUTO_START;
+
+ cmd.host_command_parameters[0] |= IPW_CFG_IBSS_MASK |
+ IPW_CFG_BSS_MASK |
+ IPW_CFG_802_1x_ENABLE;
+
+ if (!(priv->config & CFG_LONG_PREAMBLE))
+ cmd.host_command_parameters[0] |= IPW_CFG_PREAMBLE_AUTO;
+
+ err = ipw2100_get_ordinal(priv,
+ IPW_ORD_EEPROM_IBSS_11B_CHANNELS,
+ &ibss_mask, &len);
+ if (err)
+ ibss_mask = IPW_IBSS_11B_DEFAULT_MASK;
+
+ cmd.host_command_parameters[1] = REG_CHANNEL_MASK;
+ cmd.host_command_parameters[2] = REG_CHANNEL_MASK & ibss_mask;
+
+ /* 11b only */
+ /*cmd.host_command_parameters[0] |= DIVERSITY_ANTENNA_A;*/
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+/* If IPv6 is configured in the kernel then we don't want to filter out all
+ * of the multicast packets as IPv6 needs some. */
+#if !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+ cmd.host_command = ADD_MULTICAST;
+ cmd.host_command_sequence = 0;
+ cmd.host_command_length = 0;
+
+ ipw2100_hw_send_command(priv, &cmd);
+#endif
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = BASIC_TX_RATES,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = rate & TX_RATE_MASK;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ /* Set BASIC TX Rate first */
+ ipw2100_hw_send_command(priv, &cmd);
+
+ /* Set TX Rate */
+ cmd.host_command = TX_RATES;
+ ipw2100_hw_send_command(priv, &cmd);
+
+ /* Set MSDU TX Rate */
+ cmd.host_command = MSDU_TX_RATES;
+ ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ priv->tx_rates = rate;
+
+ return 0;
+}
+
+static int ipw2100_set_power_mode(struct ipw2100_priv *priv,
+ int power_level)
+{
+ struct host_command cmd = {
+ .host_command = POWER_MODE,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = power_level;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ if (power_level == IPW_POWER_MODE_CAM)
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ else
+ priv->power_mode = IPW_POWER_ENABLED | power_level;
+
+#ifdef CONFIG_IPW2100_TX_POWER
+ if (priv->port_type == IBSS &&
+ priv->adhoc_power != DFTL_IBSS_TX_POWER) {
+ /* Set beacon interval */
+ cmd.host_command = TX_POWER_INDEX;
+ cmd.host_command_parameters[0] = (u32)priv->adhoc_power;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+ }
+#endif
+
+ return 0;
+}
+
+
+static int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold)
+{
+ struct host_command cmd = {
+ .host_command = RTS_THRESHOLD,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ if (threshold & RTS_DISABLED)
+ cmd.host_command_parameters[0] = MAX_RTS_THRESHOLD;
+ else
+ cmd.host_command_parameters[0] = threshold & ~RTS_DISABLED;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->rts_threshold = threshold;
+
+ return 0;
+}
+
+#if 0
+int ipw2100_set_fragmentation_threshold(struct ipw2100_priv *priv,
+ u32 threshold, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = FRAG_THRESHOLD,
+ .host_command_sequence = 0,
+ .host_command_length = 4,
+ .host_command_parameters[0] = 0,
+ };
+ int err;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (threshold == 0)
+ threshold = DEFAULT_FRAG_THRESHOLD;
+ else {
+ threshold = max(threshold, MIN_FRAG_THRESHOLD);
+ threshold = min(threshold, MAX_FRAG_THRESHOLD);
+ }
+
+ cmd.host_command_parameters[0] = threshold;
+
+ IPW_DEBUG_HC("FRAG_THRESHOLD: %u\n", threshold);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ if (!err)
+ priv->frag_threshold = threshold;
+
+ return err;
+}
+#endif
+
+static int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry)
+{
+ struct host_command cmd = {
+ .host_command = SHORT_RETRY_LIMIT,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = retry;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->short_retry_limit = retry;
+
+ return 0;
+}
+
+static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry)
+{
+ struct host_command cmd = {
+ .host_command = LONG_RETRY_LIMIT,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = retry;
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (err)
+ return err;
+
+ priv->long_retry_limit = retry;
+
+ return 0;
+}
+
+
+static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = MANDATORY_BSSID,
+ .host_command_sequence = 0,
+ .host_command_length = (bssid == NULL) ? 0 : ETH_ALEN
+ };
+ int err;
+
+#ifdef CONFIG_IPW_DEBUG
+ if (bssid != NULL)
+ IPW_DEBUG_HC(
+ "MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4],
+ bssid[5]);
+ else
+ IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n");
+#endif
+ /* if BSSID is empty then we disable mandatory bssid mode */
+ if (bssid != NULL)
+ memcpy((u8 *)cmd.host_command_parameters, bssid, ETH_ALEN);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+#ifdef CONFIG_IEEE80211_WPA
+static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv)
+{
+ struct host_command cmd = {
+ .host_command = DISASSOCIATION_BSSID,
+ .host_command_sequence = 0,
+ .host_command_length = ETH_ALEN
+ };
+ int err;
+ int len;
+
+ IPW_DEBUG_HC("DISASSOCIATION_BSSID\n");
+
+ len = ETH_ALEN;
+ /* The Firmware currently ignores the BSSID and just disassociates from
+ * the currently associated AP -- but in the off chance that a future
+ * firmware does use the BSSID provided here, we go ahead and try and
+ * set it to the currently associated AP's BSSID */
+ memcpy(cmd.host_command_parameters, priv->bssid, ETH_ALEN);
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ return err;
+}
+#endif
+
+/*
+ * Pseudo code for setting up wpa_frame:
+ */
+#if 0
+void x(struct ieee80211_assoc_frame *wpa_assoc)
+{
+ struct ipw2100_wpa_assoc_frame frame;
+ frame->fixed_ie_mask = IPW_WPA_CAPABILTIES |
+ IPW_WPA_LISTENINTERVAL |
+ IPW_WPA_AP_ADDRESS;
+ frame->capab_info = wpa_assoc->capab_info;
+ frame->lisen_interval = wpa_assoc->listent_interval;
+ memcpy(frame->current_ap, wpa_assoc->current_ap, ETH_ALEN);
+
+ /* UNKNOWN -- I'm not postivive about this part; don't have any WPA
+ * setup here to test it with.
+ *
+ * Walk the IEs in the wpa_assoc and figure out the total size of all
+ * that data. Stick that into frame->var_ie_len. Then memcpy() all of
+ * the IEs from wpa_frame into frame.
+ */
+ frame->var_ie_len = calculate_ie_len(wpa_assoc);
+ memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len);
+
+ ipw2100_set_wpa_ie(priv, &frame, 0);
+}
+#endif
+
+
+
+
+static int ipw2100_set_wpa_ie(struct ipw2100_priv *,
+ struct ipw2100_wpa_assoc_frame *, int)
+__attribute__ ((unused));
+
+static int ipw2100_set_wpa_ie(struct ipw2100_priv *priv,
+ struct ipw2100_wpa_assoc_frame *wpa_frame,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SET_WPA_IE,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct ipw2100_wpa_assoc_frame),
+ };
+ int err;
+
+ IPW_DEBUG_HC("SET_WPA_IE\n");
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ memcpy(cmd.host_command_parameters, wpa_frame,
+ sizeof(struct ipw2100_wpa_assoc_frame));
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ if (ipw2100_enable_adapter(priv))
+ err = -EIO;
+ }
+
+ return err;
+}
+
+struct security_info_params {
+ u32 allowed_ciphers;
+ u16 version;
+ u8 auth_mode;
+ u8 replay_counters_number;
+ u8 unicast_using_group;
+} __attribute__ ((packed));
+
+static int ipw2100_set_security_information(struct ipw2100_priv *priv,
+ int auth_mode,
+ int security_level,
+ int unicast_using_group,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = SET_SECURITY_INFORMATION,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct security_info_params)
+ };
+ struct security_info_params *security =
+ (struct security_info_params *)&cmd.host_command_parameters;
+ int err;
+ memset(security, 0, sizeof(*security));
+
+ /* If shared key AP authentication is turned on, then we need to
+ * configure the firmware to try and use it.
+ *
+ * Actual data encryption/decryption is handled by the host. */
+ security->auth_mode = auth_mode;
+ security->unicast_using_group = unicast_using_group;
+
+ switch (security_level) {
+ default:
+ case SEC_LEVEL_0:
+ security->allowed_ciphers = IPW_NONE_CIPHER;
+ break;
+ case SEC_LEVEL_1:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER;
+ break;
+ case SEC_LEVEL_2:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_TKIP_CIPHER;
+ break;
+ case SEC_LEVEL_2_CKIP:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_CKIP_CIPHER;
+ break;
+ case SEC_LEVEL_3:
+ security->allowed_ciphers = IPW_WEP40_CIPHER |
+ IPW_WEP104_CIPHER | IPW_TKIP_CIPHER | IPW_CCMP_CIPHER;
+ break;
+ }
+
+ IPW_DEBUG_HC(
+ "SET_SECURITY_INFORMATION: auth:%d cipher:0x%02X (level %d)\n",
+ security->auth_mode, security->allowed_ciphers, security_level);
+
+ security->replay_counters_number = 0;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+static int ipw2100_set_tx_power(struct ipw2100_priv *priv,
+ u32 tx_power)
+{
+ struct host_command cmd = {
+ .host_command = TX_POWER_INDEX,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err = 0;
+
+ cmd.host_command_parameters[0] = tx_power;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC)
+ err = ipw2100_hw_send_command(priv, &cmd);
+ if (!err)
+ priv->tx_power = tx_power;
+
+ return 0;
+}
+
+static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv,
+ u32 interval, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = BEACON_INTERVAL,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = interval;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ err = ipw2100_enable_adapter(priv);
+ if (err)
+ return err;
+ }
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+void ipw2100_queues_initialize(struct ipw2100_priv *priv)
+{
+ ipw2100_tx_initialize(priv);
+ ipw2100_rx_initialize(priv);
+ ipw2100_msg_initialize(priv);
+}
+
+void ipw2100_queues_free(struct ipw2100_priv *priv)
+{
+ ipw2100_tx_free(priv);
+ ipw2100_rx_free(priv);
+ ipw2100_msg_free(priv);
+}
+
+int ipw2100_queues_allocate(struct ipw2100_priv *priv)
+{
+ if (ipw2100_tx_allocate(priv) ||
+ ipw2100_rx_allocate(priv) ||
+ ipw2100_msg_allocate(priv))
+ goto fail;
+
+ return 0;
+
+ fail:
+ ipw2100_tx_free(priv);
+ ipw2100_rx_free(priv);
+ ipw2100_msg_free(priv);
+ return -ENOMEM;
+}
+
+#define IPW_PRIVACY_CAPABLE 0x0008
+
+static int ipw2100_set_wep_flags(struct ipw2100_priv *priv, u32 flags,
+ int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = WEP_FLAGS,
+ .host_command_sequence = 0,
+ .host_command_length = 4
+ };
+ int err;
+
+ cmd.host_command_parameters[0] = flags;
+
+ IPW_DEBUG_HC("WEP_FLAGS: flags = 0x%08X\n", flags);
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+struct ipw2100_wep_key {
+ u8 idx;
+ u8 len;
+ u8 key[13];
+};
+
+/* Macros to ease up priting WEP keys */
+#define WEP_FMT_64 "%02X%02X%02X%02X-%02X"
+#define WEP_FMT_128 "%02X%02X%02X%02X-%02X%02X%02X%02X-%02X%02X%02X"
+#define WEP_STR_64(x) x[0],x[1],x[2],x[3],x[4]
+#define WEP_STR_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10]
+
+
+/**
+ * Set a the wep key
+ *
+ * @priv: struct to work on
+ * @idx: index of the key we want to set
+ * @key: ptr to the key data to set
+ * @len: length of the buffer at @key
+ * @batch_mode: FIXME perform the operation in batch mode, not
+ * disabling the device.
+ *
+ * @returns 0 if OK, < 0 errno code on error.
+ *
+ * Fill out a command structure with the new wep key, length an
+ * index and send it down the wire.
+ */
+static int ipw2100_set_key(struct ipw2100_priv *priv,
+ int idx, char *key, int len, int batch_mode)
+{
+ int keylen = len ? (len <= 5 ? 5 : 13) : 0;
+ struct host_command cmd = {
+ .host_command = WEP_KEY_INFO,
+ .host_command_sequence = 0,
+ .host_command_length = sizeof(struct ipw2100_wep_key),
+ };
+ struct ipw2100_wep_key *wep_key = (void*)cmd.host_command_parameters;
+ int err;
+
+ IPW_DEBUG_HC("WEP_KEY_INFO: index = %d, len = %d/%d\n",
+ idx, keylen, len);
+
+ /* NOTE: We don't check cached values in case the firmware was reset
+ * or some other problem is occuring. If the user is setting the key,
+ * then we push the change */
+
+ wep_key->idx = idx;
+ wep_key->len = keylen;
+
+ if (keylen) {
+ memcpy(wep_key->key, key, len);
+ memset(wep_key->key + len, 0, keylen - len);
+ }
+
+ /* Will be optimized out on debug not being configured in */
+ if (keylen == 0)
+ IPW_DEBUG_WEP("%s: Clearing key %d\n",
+ priv->net_dev->name, wep_key->idx);
+ else if (keylen == 5)
+ IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_64 "\n",
+ priv->net_dev->name, wep_key->idx, wep_key->len,
+ WEP_STR_64(wep_key->key));
+ else
+ IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_128
+ "\n",
+ priv->net_dev->name, wep_key->idx, wep_key->len,
+ WEP_STR_128(wep_key->key));
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ /* FIXME: IPG: shouldn't this prink be in _disable_adapter()? */
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode) {
+ int err2 = ipw2100_enable_adapter(priv);
+ if (err == 0)
+ err = err2;
+ }
+ return err;
+}
+
+static int ipw2100_set_key_index(struct ipw2100_priv *priv,
+ int idx, int batch_mode)
+{
+ struct host_command cmd = {
+ .host_command = WEP_KEY_INDEX,
+ .host_command_sequence = 0,
+ .host_command_length = 4,
+ .host_command_parameters = { idx },
+ };
+ int err;
+
+ IPW_DEBUG_HC("WEP_KEY_INDEX: index = %d\n", idx);
+
+ if (idx < 0 || idx > 3)
+ return -EINVAL;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n",
+ priv->net_dev->name, err);
+ return err;
+ }
+ }
+
+ /* send cmd to firmware */
+ err = ipw2100_hw_send_command(priv, &cmd);
+
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+
+static int ipw2100_configure_security(struct ipw2100_priv *priv,
+ int batch_mode)
+{
+ int i, err, auth_mode, sec_level, use_group;
+
+ if (!(priv->status & STATUS_RUNNING))
+ return 0;
+
+ if (!batch_mode) {
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+ }
+
+ if (!priv->sec.enabled) {
+ err = ipw2100_set_security_information(
+ priv, IPW_AUTH_OPEN, SEC_LEVEL_0, 0, 1);
+ } else {
+ auth_mode = IPW_AUTH_OPEN;
+ if ((priv->sec.flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode == WLAN_AUTH_SHARED_KEY))
+ auth_mode = IPW_AUTH_SHARED;
+
+ sec_level = SEC_LEVEL_0;
+ if (priv->sec.flags & SEC_LEVEL)
+ sec_level = priv->sec.level;
+
+ use_group = 0;
+ if (priv->sec.flags & SEC_UNICAST_GROUP)
+ use_group = priv->sec.unicast_uses_group;
+
+ err = ipw2100_set_security_information(
+ priv, auth_mode, sec_level, use_group, 1);
+ }
+
+ if (err)
+ goto exit;
+
+ if (priv->sec.enabled) {
+ for (i = 0; i < 4; i++) {
+ if (!(priv->sec.flags & (1 << i))) {
+ memset(priv->sec.keys[i], 0, WEP_KEY_LEN);
+ priv->sec.key_sizes[i] = 0;
+ } else {
+ err = ipw2100_set_key(priv, i,
+ priv->sec.keys[i],
+ priv->sec.key_sizes[i],
+ 1);
+ if (err)
+ goto exit;
+ }
+ }
+
+ ipw2100_set_key_index(priv, priv->ieee->tx_keyidx, 1);
+ }
+
+ /* Always enable privacy so the Host can filter WEP packets if
+ * encrypted data is sent up */
+ err = ipw2100_set_wep_flags(
+ priv, priv->sec.enabled ? IPW_PRIVACY_CAPABLE : 0, 1);
+ if (err)
+ goto exit;
+
+ priv->status &= ~STATUS_SECURITY_UPDATED;
+
+ exit:
+ if (!batch_mode)
+ ipw2100_enable_adapter(priv);
+
+ return err;
+}
+
+static void ipw2100_security_work(struct ipw2100_priv *priv)
+{
+ /* If we happen to have reconnected before we get a chance to
+ * process this, then update the security settings--which causes
+ * a disassociation to occur */
+ if (!(priv->status & STATUS_ASSOCIATED) &&
+ priv->status & STATUS_SECURITY_UPDATED)
+ ipw2100_configure_security(priv, 0);
+}
+
+static void shim__set_security(struct net_device *dev,
+ struct ieee80211_security *sec)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int i, force_update = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED))
+ goto done;
+
+ for (i = 0; i < 4; i++) {
+ if (sec->flags & (1 << i)) {
+ priv->sec.key_sizes[i] = sec->key_sizes[i];
+ if (sec->key_sizes[i] == 0)
+ priv->sec.flags &= ~(1 << i);
+ else
+ memcpy(priv->sec.keys[i], sec->keys[i],
+ sec->key_sizes[i]);
+ priv->sec.flags |= (1 << i);
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+ }
+
+ if ((sec->flags & SEC_ACTIVE_KEY) &&
+ priv->sec.active_key != sec->active_key) {
+ if (sec->active_key <= 3) {
+ priv->sec.active_key = sec->active_key;
+ priv->sec.flags |= SEC_ACTIVE_KEY;
+ } else
+ priv->sec.flags &= ~SEC_ACTIVE_KEY;
+
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if ((sec->flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode != sec->auth_mode)) {
+ priv->sec.auth_mode = sec->auth_mode;
+ priv->sec.flags |= SEC_AUTH_MODE;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if (sec->flags & SEC_ENABLED &&
+ priv->sec.enabled != sec->enabled) {
+ priv->sec.flags |= SEC_ENABLED;
+ priv->sec.enabled = sec->enabled;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ force_update = 1;
+ }
+
+ if (sec->flags & SEC_LEVEL &&
+ priv->sec.level != sec->level) {
+ priv->sec.level = sec->level;
+ priv->sec.flags |= SEC_LEVEL;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ IPW_DEBUG_WEP("Security flags: %c %c%c%c%c %c%c%c%c\n",
+ priv->sec.flags & (1<<8) ? '1' : '0',
+ priv->sec.flags & (1<<7) ? '1' : '0',
+ priv->sec.flags & (1<<6) ? '1' : '0',
+ priv->sec.flags & (1<<5) ? '1' : '0',
+ priv->sec.flags & (1<<4) ? '1' : '0',
+ priv->sec.flags & (1<<3) ? '1' : '0',
+ priv->sec.flags & (1<<2) ? '1' : '0',
+ priv->sec.flags & (1<<1) ? '1' : '0',
+ priv->sec.flags & (1<<0) ? '1' : '0');
+
+/* As a temporary work around to enable WPA until we figure out why
+ * wpa_supplicant toggles the security capability of the driver, which
+ * forces a disassocation with force_update...
+ *
+ * if (force_update || !(priv->status & STATUS_ASSOCIATED))*/
+ if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
+ ipw2100_configure_security(priv, 0);
+done:
+ up(&priv->action_sem);
+}
+
+static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
+{
+ int err;
+ int batch_mode = 1;
+ u8 *bssid;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ err = ipw2100_disable_adapter(priv);
+ if (err)
+ return err;
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ err = ipw2100_set_channel(priv, priv->channel, batch_mode);
+ if (err)
+ return err;
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+ }
+#endif /* CONFIG_IPW2100_MONITOR */
+
+ err = ipw2100_read_mac_address(priv);
+ if (err)
+ return -EIO;
+
+ err = ipw2100_set_mac_address(priv, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_port_type(priv, priv->ieee->iw_mode, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ err = ipw2100_set_channel(priv, priv->channel, batch_mode);
+ if (err)
+ return err;
+ }
+
+ err = ipw2100_system_config(priv, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_tx_rates(priv, priv->tx_rates, batch_mode);
+ if (err)
+ return err;
+
+ /* Default to power mode OFF */
+ err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM);
+ if (err)
+ return err;
+
+ err = ipw2100_set_rts_threshold(priv, priv->rts_threshold);
+ if (err)
+ return err;
+
+ if (priv->config & CFG_STATIC_BSSID)
+ bssid = priv->bssid;
+ else
+ bssid = NULL;
+ err = ipw2100_set_mandatory_bssid(priv, bssid, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->config & CFG_STATIC_ESSID)
+ err = ipw2100_set_essid(priv, priv->essid, priv->essid_len,
+ batch_mode);
+ else
+ err = ipw2100_set_essid(priv, NULL, 0, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_configure_security(priv, batch_mode);
+ if (err)
+ return err;
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ err = ipw2100_set_ibss_beacon_interval(
+ priv, priv->beacon_interval, batch_mode);
+ if (err)
+ return err;
+
+ err = ipw2100_set_tx_power(priv, priv->tx_power);
+ if (err)
+ return err;
+ }
+
+ /*
+ err = ipw2100_set_fragmentation_threshold(
+ priv, priv->frag_threshold, batch_mode);
+ if (err)
+ return err;
+ */
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+/*************************************************************************
+ *
+ * EXTERNALLY CALLED METHODS
+ *
+ *************************************************************************/
+
+/* This method is called by the network layer -- not to be confused with
+ * ipw2100_set_mac_address() declared above called by this driver (and this
+ * method as well) to talk to the firmware */
+static int ipw2100_set_address(struct net_device *dev, void *p)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct sockaddr *addr = p;
+ int err = 0;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ down(&priv->action_sem);
+
+ priv->config |= CFG_CUSTOM_MAC;
+ memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
+
+ err = ipw2100_set_mac_address(priv, 0);
+ if (err)
+ goto done;
+
+ priv->reset_backoff = 0;
+ up(&priv->action_sem);
+ ipw2100_reset_adapter(priv);
+ return 0;
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_open(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+ IPW_DEBUG_INFO("dev->open\n");
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+ if (priv->status & STATUS_ASSOCIATED) {
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+ }
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ return 0;
+}
+
+static int ipw2100_close(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+ struct list_head *element;
+ struct ipw2100_tx_packet *packet;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->status & STATUS_ASSOCIATED)
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ /* Flush the TX queue ... */
+ while (!list_empty(&priv->tx_pend_list)) {
+ element = priv->tx_pend_list.next;
+ packet = list_entry(element, struct ipw2100_tx_packet, list);
+
+ list_del(element);
+ DEC_STAT(&priv->tx_pend_stat);
+
+ ieee80211_txb_free(packet->info.d_struct.txb);
+ packet->info.d_struct.txb = NULL;
+
+ list_add_tail(element, &priv->tx_free_list);
+ INC_STAT(&priv->tx_free_stat);
+ }
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+
+ IPW_DEBUG_INFO("exit\n");
+
+ return 0;
+}
+
+
+
+/*
+ * TODO: Fix this function... its just wrong
+ */
+static void ipw2100_tx_timeout(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ priv->ieee->stats.tx_errors++;
+
+#ifdef CONFIG_IPW2100_MONITOR
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ return;
+#endif
+
+ IPW_DEBUG_INFO("%s: TX timed out. Scheduling firmware restart.\n",
+ dev->name);
+ schedule_reset(priv);
+}
+
+
+/*
+ * TODO: reimplement it so that it reads statistics
+ * from the adapter using ordinal tables
+ * instead of/in addition to collecting them
+ * in the driver
+ */
+static struct net_device_stats *ipw2100_stats(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ return &priv->ieee->stats;
+}
+
+/* Support for wpa_supplicant. Will be replaced with WEXT once
+ * they get WPA support. */
+#ifdef CONFIG_IEEE80211_WPA
+
+/* following definitions must match definitions in driver_ipw2100.c */
+
+#define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
+
+#define IPW2100_CMD_SET_WPA_PARAM 1
+#define IPW2100_CMD_SET_WPA_IE 2
+#define IPW2100_CMD_SET_ENCRYPTION 3
+#define IPW2100_CMD_MLME 4
+
+#define IPW2100_PARAM_WPA_ENABLED 1
+#define IPW2100_PARAM_TKIP_COUNTERMEASURES 2
+#define IPW2100_PARAM_DROP_UNENCRYPTED 3
+#define IPW2100_PARAM_PRIVACY_INVOKED 4
+#define IPW2100_PARAM_AUTH_ALGS 5
+#define IPW2100_PARAM_IEEE_802_1X 6
+
+#define IPW2100_MLME_STA_DEAUTH 1
+#define IPW2100_MLME_STA_DISASSOC 2
+
+#define IPW2100_CRYPT_ERR_UNKNOWN_ALG 2
+#define IPW2100_CRYPT_ERR_UNKNOWN_ADDR 3
+#define IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define IPW2100_CRYPT_ERR_KEY_SET_FAILED 5
+#define IPW2100_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define IPW2100_CRYPT_ERR_CARD_CONF_FAILED 7
+
+#define IPW2100_CRYPT_ALG_NAME_LEN 16
+
+struct ipw2100_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u8 name;
+ u32 value;
+ } wpa_param;
+ struct {
+ u32 len;
+ u8 *data;
+ } wpa_ie;
+ struct{
+ int command;
+ int reason_code;
+ } mlme;
+ struct {
+ u8 alg[IPW2100_CRYPT_ALG_NAME_LEN];
+ u8 set_tx;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+
+ } u;
+};
+
+/* end of driver_ipw2100.c code */
+
+static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value){
+
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_security sec = {
+ .flags = SEC_LEVEL | SEC_ENABLED,
+ };
+ int ret = 0;
+
+ ieee->wpa_enabled = value;
+
+ if (value){
+ sec.level = SEC_LEVEL_3;
+ sec.enabled = 1;
+ } else {
+ sec.level = SEC_LEVEL_0;
+ sec.enabled = 0;
+ }
+
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+ else
+ ret = -EOPNOTSUPP;
+
+ return ret;
+}
+
+#define AUTH_ALG_OPEN_SYSTEM 0x1
+#define AUTH_ALG_SHARED_KEY 0x2
+
+static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value){
+
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_security sec = {
+ .flags = SEC_AUTH_MODE,
+ };
+ int ret = 0;
+
+ if (value & AUTH_ALG_SHARED_KEY){
+ sec.auth_mode = WLAN_AUTH_SHARED_KEY;
+ ieee->open_wep = 0;
+ } else {
+ sec.auth_mode = WLAN_AUTH_OPEN;
+ ieee->open_wep = 1;
+ }
+
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+ else
+ ret = -EOPNOTSUPP;
+
+ return ret;
+}
+
+
+static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int ret=0;
+
+ switch(name){
+ case IPW2100_PARAM_WPA_ENABLED:
+ ret = ipw2100_wpa_enable(priv, value);
+ break;
+
+ case IPW2100_PARAM_TKIP_COUNTERMEASURES:
+ priv->ieee->tkip_countermeasures=value;
+ break;
+
+ case IPW2100_PARAM_DROP_UNENCRYPTED:
+ priv->ieee->drop_unencrypted=value;
+ break;
+
+ case IPW2100_PARAM_PRIVACY_INVOKED:
+ priv->ieee->privacy_invoked=value;
+ break;
+
+ case IPW2100_PARAM_AUTH_ALGS:
+ ret = ipw2100_wpa_set_auth_algs(priv, value);
+ break;
+
+ case IPW2100_PARAM_IEEE_802_1X:
+ priv->ieee->ieee802_1x=value;
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n",
+ dev->name, name);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int ret=0;
+
+ switch(command){
+ case IPW2100_MLME_STA_DEAUTH:
+ // silently ignore
+ break;
+
+ case IPW2100_MLME_STA_DISASSOC:
+ ipw2100_disassociate_bssid(priv);
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n",
+ dev->name, command);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+
+void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
+ char *wpa_ie, int wpa_ie_len){
+
+ struct ipw2100_wpa_assoc_frame frame;
+
+ frame.fixed_ie_mask = 0;
+
+ /* copy WPA IE */
+ memcpy(frame.var_ie, wpa_ie, wpa_ie_len);
+ frame.var_ie_len = wpa_ie_len;
+
+ /* make sure WPA is enabled */
+ ipw2100_wpa_enable(priv, 1);
+ ipw2100_set_wpa_ie(priv, &frame, 0);
+}
+
+
+static int ipw2100_wpa_set_wpa_ie(struct net_device *dev,
+ struct ipw2100_param *param, int plen){
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee;
+ u8 *buf;
+
+ if (! ieee->wpa_enabled)
+ return -EOPNOTSUPP;
+
+ if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
+ (param->u.wpa_ie.len &&
+ param->u.wpa_ie.data==NULL))
+ return -EINVAL;
+
+ if (param->u.wpa_ie.len){
+ buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
+
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = buf;
+ ieee->wpa_ie_len = param->u.wpa_ie.len;
+
+ } else {
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = NULL;
+ ieee->wpa_ie_len = 0;
+ }
+
+ ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
+
+ return 0;
+}
+
+/* implementation borrowed from hostap driver */
+
+static int ipw2100_wpa_set_encryption(struct net_device *dev,
+ struct ipw2100_param *param, int param_len){
+
+ int ret = 0;
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee;
+ struct ieee80211_crypto_ops *ops;
+ struct ieee80211_crypt_data **crypt;
+
+ struct ieee80211_security sec = {
+ .flags = 0,
+ };
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IPW2100_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len !=
+ (int) ((char *) param->u.crypt.key - (char *) param) +
+ param->u.crypt.key_len){
+ IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, param->u.crypt.key_len);
+ return -EINVAL;
+ }
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS)
+ return -EINVAL;
+ crypt = &ieee->crypt[param->u.crypt.idx];
+ } else {
+ return -EINVAL;
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0) {
+ if (crypt){
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL;
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+ }
+ goto done;
+ }
+ sec.enabled = 1;
+ sec.flags |= SEC_ENABLED;
+
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+ request_module("ieee80211_crypt_wep");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ request_module("ieee80211_crypt_tkip");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ request_module("ieee80211_crypt_ccmp");
+ ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ }
+ if (ops == NULL) {
+ IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n",
+ dev->name, param->u.crypt.alg);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_UNKNOWN_ALG;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct ieee80211_crypt_data *new_crypt;
+
+ ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+ new_crypt = (struct ieee80211_crypt_data *)
+ kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+ new_crypt->ops = ops;
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
+
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ param->u.crypt.err =
+ IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(param->u.crypt.key,
+ param->u.crypt.key_len, param->u.crypt.seq,
+ (*crypt)->priv) < 0) {
+ IPW_DEBUG_INFO("%s: key setting failed\n",
+ dev->name);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (param->u.crypt.set_tx){
+ ieee->tx_keyidx = param->u.crypt.idx;
+ sec.active_key = param->u.crypt.idx;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+
+ if (ops->name != NULL){
+
+ if (strcmp(ops->name, "WEP") == 0) {
+ memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, param->u.crypt.key_len);
+ sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
+ sec.flags |= (1 << param->u.crypt.idx);
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ } else if (strcmp(ops->name, "TKIP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_2;
+ } else if (strcmp(ops->name, "CCMP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_3;
+ }
+ }
+ done:
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack. */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port &&
+ ieee->reset_port(dev)) {
+ IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name);
+ param->u.crypt.err = IPW2100_CRYPT_ERR_CARD_CONF_FAILED;
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){
+
+ struct ipw2100_param *param;
+ int ret=0;
+
+ IPW_DEBUG_IOCTL("wpa_supplicant: len=%d\n", p->length);
+
+ if (p->length < sizeof(struct ipw2100_param) || !p->pointer)
+ return -EINVAL;
+
+ param = (struct ipw2100_param *)kmalloc(p->length, GFP_KERNEL);
+ if (param == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)){
+ kfree(param);
+ return -EFAULT;
+ }
+
+ switch (param->cmd){
+
+ case IPW2100_CMD_SET_WPA_PARAM:
+ ret = ipw2100_wpa_set_param(dev, param->u.wpa_param.name,
+ param->u.wpa_param.value);
+ break;
+
+ case IPW2100_CMD_SET_WPA_IE:
+ ret = ipw2100_wpa_set_wpa_ie(dev, param, p->length);
+ break;
+
+ case IPW2100_CMD_SET_ENCRYPTION:
+ ret = ipw2100_wpa_set_encryption(dev, param, p->length);
+ break;
+
+ case IPW2100_CMD_MLME:
+ ret = ipw2100_wpa_mlme(dev, param->u.mlme.command,
+ param->u.mlme.reason_code);
+ break;
+
+ default:
+ printk(KERN_ERR DRV_NAME ": %s: Unknown WPA supplicant request: %d\n",
+ dev->name, param->cmd);
+ ret = -EOPNOTSUPP;
+
+ }
+
+ if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+ ret = -EFAULT;
+
+ kfree(param);
+ return ret;
+}
+#endif /* CONFIG_IEEE80211_WPA */
+
+static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+#ifdef CONFIG_IEEE80211_WPA
+ struct iwreq *wrq = (struct iwreq *) rq;
+ int ret=-1;
+ switch (cmd){
+ case IPW2100_IOCTL_WPA_SUPPLICANT:
+ ret = ipw2100_wpa_supplicant(dev, &wrq->u.data);
+ return ret;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+#endif /* CONFIG_IEEE80211_WPA */
+
+ return -EOPNOTSUPP;
+}
+
+
+static void ipw_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ char fw_ver[64], ucode_ver[64];
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+
+ ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
+ ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
+
+ snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
+ fw_ver, priv->eeprom_version, ucode_ver);
+
+ strcpy(info->bus_info, pci_name(priv->pci_dev));
+}
+
+static u32 ipw2100_ethtool_get_link(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return (priv->status & STATUS_ASSOCIATED) ? 1 : 0;
+}
+
+
+static struct ethtool_ops ipw2100_ethtool_ops = {
+ .get_link = ipw2100_ethtool_get_link,
+ .get_drvinfo = ipw_ethtool_get_drvinfo,
+};
+
+static void ipw2100_hang_check(void *adapter)
+{
+ struct ipw2100_priv *priv = adapter;
+ unsigned long flags;
+ u32 rtc = 0xa5a5a5a5;
+ u32 len = sizeof(rtc);
+ int restart = 0;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (priv->fatal_error != 0) {
+ /* If fatal_error is set then we need to restart */
+ IPW_DEBUG_INFO("%s: Hardware fatal error detected.\n",
+ priv->net_dev->name);
+
+ restart = 1;
+ } else if (ipw2100_get_ordinal(priv, IPW_ORD_RTC_TIME, &rtc, &len) ||
+ (rtc == priv->last_rtc)) {
+ /* Check if firmware is hung */
+ IPW_DEBUG_INFO("%s: Firmware RTC stalled.\n",
+ priv->net_dev->name);
+
+ restart = 1;
+ }
+
+ if (restart) {
+ /* Kill timer */
+ priv->stop_hang_check = 1;
+ priv->hangs++;
+
+ /* Restart the NIC */
+ schedule_reset(priv);
+ }
+
+ priv->last_rtc = rtc;
+
+ if (!priv->stop_hang_check)
+ queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+}
+
+
+static void ipw2100_rf_kill(void *adapter)
+{
+ struct ipw2100_priv *priv = adapter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->low_lock, flags);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
+ if (!priv->stop_rf_kill)
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ goto exit_unlock;
+ }
+
+ /* RF Kill is now disabled, so bring the device back up */
+
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting "
+ "device\n");
+ schedule_reset(priv);
+ } else
+ IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still "
+ "enabled\n");
+
+ exit_unlock:
+ spin_unlock_irqrestore(&priv->low_lock, flags);
+}
+
+static void ipw2100_irq_tasklet(struct ipw2100_priv *priv);
+
+/* Look into using netdev destructor to shutdown ieee80211? */
+
+static struct net_device *ipw2100_alloc_device(
+ struct pci_dev *pci_dev,
+ void __iomem *base_addr,
+ unsigned long mem_start,
+ unsigned long mem_len)
+{
+ struct ipw2100_priv *priv;
+ struct net_device *dev;
+
+ dev = alloc_ieee80211(sizeof(struct ipw2100_priv));
+ if (!dev)
+ return NULL;
+ priv = ieee80211_priv(dev);
+ priv->ieee = netdev_priv(dev);
+ priv->pci_dev = pci_dev;
+ priv->net_dev = dev;
+
+ priv->ieee->hard_start_xmit = ipw2100_tx;
+ priv->ieee->set_security = shim__set_security;
+
+ dev->open = ipw2100_open;
+ dev->stop = ipw2100_close;
+ dev->init = ipw2100_net_init;
+ dev->do_ioctl = ipw2100_ioctl;
+ dev->get_stats = ipw2100_stats;
+ dev->ethtool_ops = &ipw2100_ethtool_ops;
+ dev->tx_timeout = ipw2100_tx_timeout;
+ dev->wireless_handlers = &ipw2100_wx_handler_def;
+ dev->get_wireless_stats = ipw2100_wx_wireless_stats;
+ dev->set_mac_address = ipw2100_set_address;
+ dev->watchdog_timeo = 3*HZ;
+ dev->irq = 0;
+
+ dev->base_addr = (unsigned long)base_addr;
+ dev->mem_start = mem_start;
+ dev->mem_end = dev->mem_start + mem_len - 1;
+
+ /* NOTE: We don't use the wireless_handlers hook
+ * in dev as the system will start throwing WX requests
+ * to us before we're actually initialized and it just
+ * ends up causing problems. So, we just handle
+ * the WX extensions through the ipw2100_ioctl interface */
+
+
+ /* memset() puts everything to 0, so we only have explicitely set
+ * those values that need to be something else */
+
+ /* If power management is turned on, default to AUTO mode */
+ priv->power_mode = IPW_POWER_AUTO;
+
+
+
+#ifdef CONFIG_IEEE80211_WPA
+ priv->ieee->wpa_enabled = 0;
+ priv->ieee->tkip_countermeasures = 0;
+ priv->ieee->drop_unencrypted = 0;
+ priv->ieee->privacy_invoked = 0;
+ priv->ieee->ieee802_1x = 1;
+#endif /* CONFIG_IEEE80211_WPA */
+
+ /* Set module parameters */
+ switch (mode) {
+ case 1:
+ priv->ieee->iw_mode = IW_MODE_ADHOC;
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case 2:
+ priv->ieee->iw_mode = IW_MODE_MONITOR;
+ break;
+#endif
+ default:
+ case 0:
+ priv->ieee->iw_mode = IW_MODE_INFRA;
+ break;
+ }
+
+ if (disable == 1)
+ priv->status |= STATUS_RF_KILL_SW;
+
+ if (channel != 0 &&
+ ((channel >= REG_MIN_CHANNEL) &&
+ (channel <= REG_MAX_CHANNEL))) {
+ priv->config |= CFG_STATIC_CHANNEL;
+ priv->channel = channel;
+ }
+
+ if (associate)
+ priv->config |= CFG_ASSOCIATE;
+
+ priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
+ priv->short_retry_limit = DEFAULT_SHORT_RETRY_LIMIT;
+ priv->long_retry_limit = DEFAULT_LONG_RETRY_LIMIT;
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD | RTS_DISABLED;
+ priv->frag_threshold = DEFAULT_FTS | FRAG_DISABLED;
+ priv->tx_power = IPW_TX_POWER_DEFAULT;
+ priv->tx_rates = DEFAULT_TX_RATES;
+
+ strcpy(priv->nick, "ipw2100");
+
+ spin_lock_init(&priv->low_lock);
+ sema_init(&priv->action_sem, 1);
+ sema_init(&priv->adapter_sem, 1);
+
+ init_waitqueue_head(&priv->wait_command_queue);
+
+ netif_carrier_off(dev);
+
+ INIT_LIST_HEAD(&priv->msg_free_list);
+ INIT_LIST_HEAD(&priv->msg_pend_list);
+ INIT_STAT(&priv->msg_free_stat);
+ INIT_STAT(&priv->msg_pend_stat);
+
+ INIT_LIST_HEAD(&priv->tx_free_list);
+ INIT_LIST_HEAD(&priv->tx_pend_list);
+ INIT_STAT(&priv->tx_free_stat);
+ INIT_STAT(&priv->tx_pend_stat);
+
+ INIT_LIST_HEAD(&priv->fw_pend_list);
+ INIT_STAT(&priv->fw_pend_stat);
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND2
+ priv->workqueue = create_workqueue(DRV_NAME, 0);
+#else
+ priv->workqueue = create_workqueue(DRV_NAME);
+#endif
+ INIT_WORK(&priv->reset_work,
+ (void (*)(void *))ipw2100_reset_adapter, priv);
+ INIT_WORK(&priv->security_work,
+ (void (*)(void *))ipw2100_security_work, priv);
+ INIT_WORK(&priv->wx_event_work,
+ (void (*)(void *))ipw2100_wx_event_work, priv);
+ INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv);
+ INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv);
+
+ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ ipw2100_irq_tasklet, (unsigned long)priv);
+
+ /* NOTE: We do not start the deferred work for status checks yet */
+ priv->stop_rf_kill = 1;
+ priv->stop_hang_check = 1;
+
+ return dev;
+}
+
+static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
+ const struct pci_device_id *ent)
+{
+ unsigned long mem_start, mem_len, mem_flags;
+ void __iomem *base_addr = NULL;
+ struct net_device *dev = NULL;
+ struct ipw2100_priv *priv = NULL;
+ int err = 0;
+ int registered = 0;
+ u32 val;
+
+ IPW_DEBUG_INFO("enter\n");
+
+ mem_start = pci_resource_start(pci_dev, 0);
+ mem_len = pci_resource_len(pci_dev, 0);
+ mem_flags = pci_resource_flags(pci_dev, 0);
+
+ if ((mem_flags & IORESOURCE_MEM) != IORESOURCE_MEM) {
+ IPW_DEBUG_INFO("weird - resource type is not memory\n");
+ err = -ENODEV;
+ goto fail;
+ }
+
+ base_addr = ioremap_nocache(mem_start, mem_len);
+ if (!base_addr) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling ioremap_nocache.\n");
+ err = -EIO;
+ goto fail;
+ }
+
+ /* allocate and initialize our net_device */
+ dev = ipw2100_alloc_device(pci_dev, base_addr, mem_start, mem_len);
+ if (!dev) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling ipw2100_alloc_device.\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ /* set up PCI mappings for device */
+ err = pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_enable_device.\n");
+ return err;
+ }
+
+ priv = ieee80211_priv(dev);
+
+ pci_set_master(pci_dev);
+ pci_set_drvdata(pci_dev, priv);
+
+ err = pci_set_dma_mask(pci_dev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_set_dma_mask.\n");
+ pci_disable_device(pci_dev);
+ return err;
+ }
+
+ err = pci_request_regions(pci_dev, DRV_NAME);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling pci_request_regions.\n");
+ pci_disable_device(pci_dev);
+ return err;
+ }
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_read_config_dword(pci_dev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff);
+
+ pci_set_power_state(pci_dev, PCI_D0);
+
+ if (!ipw2100_hw_is_adapter_in_system(dev)) {
+ printk(KERN_WARNING DRV_NAME
+ "Device not found via register read.\n");
+ err = -ENODEV;
+ goto fail;
+ }
+
+ SET_NETDEV_DEV(dev, &pci_dev->dev);
+
+ /* Force interrupts to be shut off on the device */
+ priv->status |= STATUS_INT_ENABLED;
+ ipw2100_disable_interrupts(priv);
+
+ /* Allocate and initialize the Tx/Rx queues and lists */
+ if (ipw2100_queues_allocate(priv)) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calilng ipw2100_queues_allocate.\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+ ipw2100_queues_initialize(priv);
+
+ err = request_irq(pci_dev->irq,
+ ipw2100_interrupt, SA_SHIRQ,
+ dev->name, priv);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling request_irq: %d.\n",
+ pci_dev->irq);
+ goto fail;
+ }
+ dev->irq = pci_dev->irq;
+
+ IPW_DEBUG_INFO("Attempting to register device...\n");
+
+ SET_MODULE_OWNER(dev);
+
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2100 Network Connection\n");
+
+ /* Bring up the interface. Pre 0.46, after we registered the
+ * network device we would call ipw2100_up. This introduced a race
+ * condition with newer hotplug configurations (network was coming
+ * up and making calls before the device was initialized).
+ *
+ * If we called ipw2100_up before we registered the device, then the
+ * device name wasn't registered. So, we instead use the net_dev->init
+ * member to call a function that then just turns and calls ipw2100_up.
+ * net_dev->init is called after name allocation but before the
+ * notifier chain is called */
+ down(&priv->action_sem);
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME
+ "Error calling register_netdev.\n");
+ goto fail_unlock;
+ }
+ registered = 1;
+
+ IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev));
+
+ /* perform this after register_netdev so that dev->name is set */
+ sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+ netif_carrier_off(dev);
+
+ /* If the RF Kill switch is disabled, go ahead and complete the
+ * startup sequence */
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ /* Enable the adapter - sends HOST_COMPLETE */
+ if (ipw2100_enable_adapter(priv)) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: failed in call to enable adapter.\n",
+ priv->net_dev->name);
+ ipw2100_hw_stop_adapter(priv);
+ err = -EIO;
+ goto fail_unlock;
+ }
+
+ /* Start a scan . . . */
+ ipw2100_set_scan_options(priv);
+ ipw2100_start_scan(priv);
+ }
+
+ IPW_DEBUG_INFO("exit\n");
+
+ priv->status |= STATUS_INITIALIZED;
+
+ up(&priv->action_sem);
+
+ return 0;
+
+ fail_unlock:
+ up(&priv->action_sem);
+
+ fail:
+ if (dev) {
+ if (registered)
+ unregister_netdev(dev);
+
+ ipw2100_hw_stop_adapter(priv);
+
+ ipw2100_disable_interrupts(priv);
+
+ if (dev->irq)
+ free_irq(dev->irq, priv);
+
+ ipw2100_kill_workqueue(priv);
+
+ /* These are safe to call even if they weren't allocated */
+ ipw2100_queues_free(priv);
+ sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+
+ free_ieee80211(dev);
+ pci_set_drvdata(pci_dev, NULL);
+ }
+
+ if (base_addr)
+ iounmap(base_addr);
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
+
+ return err;
+}
+
+static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev;
+
+ if (priv) {
+ down(&priv->action_sem);
+
+ priv->status &= ~STATUS_INITIALIZED;
+
+ dev = priv->net_dev;
+ sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group);
+
+#ifdef CONFIG_PM
+ if (ipw2100_firmware.version)
+ ipw2100_release_firmware(priv, &ipw2100_firmware);
+#endif
+ /* Take down the hardware */
+ ipw2100_down(priv);
+
+ /* Release the semaphore so that the network subsystem can
+ * complete any needed calls into the driver... */
+ up(&priv->action_sem);
+
+ /* Unregister the device first - this results in close()
+ * being called if the device is open. If we free storage
+ * first, then close() will crash. */
+ unregister_netdev(dev);
+
+ /* ipw2100_down will ensure that there is no more pending work
+ * in the workqueue's, so we can safely remove them now. */
+ ipw2100_kill_workqueue(priv);
+
+ ipw2100_queues_free(priv);
+
+ /* Free potential debugging firmware snapshot */
+ ipw2100_snapshot_free(priv);
+
+ if (dev->irq)
+ free_irq(dev->irq, priv);
+
+ if (dev->base_addr)
+ iounmap((void __iomem *)dev->base_addr);
+
+ free_ieee80211(dev);
+ }
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
+
+ IPW_DEBUG_INFO("exit\n");
+}
+
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+static int ipw2100_suspend(struct pci_dev *pci_dev, u32 state)
+#else
+static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
+#endif
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev = priv->net_dev;
+
+ IPW_DEBUG_INFO("%s: Going into suspend...\n",
+ dev->name);
+
+ down(&priv->action_sem);
+ if (priv->status & STATUS_INITIALIZED) {
+ /* Take down the device; powers it off, etc. */
+ ipw2100_down(priv);
+ }
+
+ /* Remove the PRESENT state of the device */
+ netif_device_detach(dev);
+
+ pci_save_state(pci_dev);
+ pci_disable_device (pci_dev);
+ pci_set_power_state(pci_dev, PCI_D3hot);
+
+ up(&priv->action_sem);
+
+ return 0;
+}
+
+static int ipw2100_resume(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ struct net_device *dev = priv->net_dev;
+ u32 val;
+
+ if (IPW2100_PM_DISABLED)
+ return 0;
+
+ down(&priv->action_sem);
+
+ IPW_DEBUG_INFO("%s: Coming out of suspend...\n",
+ dev->name);
+
+ pci_set_power_state(pci_dev, PCI_D0);
+ pci_enable_device(pci_dev);
+ pci_restore_state(pci_dev);
+
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
+ * from interfering with C3 CPU state. pci_restore_state won't help
+ * here since it only restores the first 64 bytes pci config header.
+ */
+ pci_read_config_dword(pci_dev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff);
+
+ /* Set the device back into the PRESENT state; this will also wake
+ * the queue of needed */
+ netif_device_attach(dev);
+
+ /* Bring the device back up */
+ if (!(priv->status & STATUS_RF_KILL_SW))
+ ipw2100_up(priv, 0);
+
+ up(&priv->action_sem);
+
+ return 0;
+}
+#endif
+
+
+#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
+
+static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
+ IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */
+ IPW2100_DEV_ID(0x2522), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2523), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2527), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2528), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2529), /* IN 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x252B), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x252C), /* IN 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x252D), /* IN 2100 mPCI 3A */
+
+ IPW2100_DEV_ID(0x2550), /* IB 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2551), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2553), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2554), /* IB 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2555), /* IB 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2560), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2562), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2563), /* DE 2100A mPCI 3A */
+ IPW2100_DEV_ID(0x2561), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2565), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2566), /* DE 2100 mPCI 3A */
+ IPW2100_DEV_ID(0x2567), /* DE 2100 mPCI 3A */
+
+ IPW2100_DEV_ID(0x2570), /* GA 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2580), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2582), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2583), /* TO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2581), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2585), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2586), /* TO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2587), /* TO 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x2590), /* SO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2592), /* SO 2100A mPCI 3B */
+ IPW2100_DEV_ID(0x2591), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2593), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2596), /* SO 2100 mPCI 3B */
+ IPW2100_DEV_ID(0x2598), /* SO 2100 mPCI 3B */
+
+ IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, ipw2100_pci_id_table);
+
+static struct pci_driver ipw2100_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ipw2100_pci_id_table,
+ .probe = ipw2100_pci_init_one,
+ .remove = __devexit_p(ipw2100_pci_remove_one),
+#ifdef CONFIG_PM
+ .suspend = ipw2100_suspend,
+ .resume = ipw2100_resume,
+#endif
+};
+
+
+/**
+ * Initialize the ipw2100 driver/module
+ *
+ * @returns 0 if ok, < 0 errno node con error.
+ *
+ * Note: we cannot init the /proc stuff until the PCI driver is there,
+ * or we risk an unlikely race condition on someone accessing
+ * uninitialized data in the PCI dev struct through /proc.
+ */
+static int __init ipw2100_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+ printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT);
+
+#ifdef CONFIG_IEEE80211_NOWEP
+ IPW_DEBUG_INFO(DRV_NAME ": Compiled with WEP disabled.\n");
+#endif
+
+ ret = pci_module_init(&ipw2100_pci_driver);
+
+#ifdef CONFIG_IPW_DEBUG
+ ipw2100_debug_level = debug;
+ driver_create_file(&ipw2100_pci_driver.driver,
+ &driver_attr_debug_level);
+#endif
+
+ return ret;
+}
+
+
+/**
+ * Cleanup ipw2100 driver registration
+ */
+static void __exit ipw2100_exit(void)
+{
+ /* FIXME: IPG: check that we have no instances of the devices open */
+#ifdef CONFIG_IPW_DEBUG
+ driver_remove_file(&ipw2100_pci_driver.driver,
+ &driver_attr_debug_level);
+#endif
+ pci_unregister_driver(&ipw2100_pci_driver);
+}
+
+module_init(ipw2100_init);
+module_exit(ipw2100_exit);
+
+#define WEXT_USECHANNELS 1
+
+static const long ipw2100_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT (sizeof(ipw2100_frequencies) / \
+ sizeof(ipw2100_frequencies[0]))
+
+static const long ipw2100_rates_11b[] = {
+ 1000000,
+ 2000000,
+ 5500000,
+ 11000000
+};
+
+#define RATE_COUNT (sizeof(ipw2100_rates_11b) / sizeof(ipw2100_rates_11b[0]))
+
+static int ipw2100_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ if (!(priv->status & STATUS_ASSOCIATED))
+ strcpy(wrqu->name, "unassociated");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
+
+ IPW_DEBUG_WX("Name: %s\n", wrqu->name);
+ return 0;
+}
+
+
+static int ipw2100_wx_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_freq *fwrq = &wrqu->freq;
+ int err = 0;
+
+ if (priv->ieee->iw_mode == IW_MODE_INFRA)
+ return -EOPNOTSUPP;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ /* if setting by freq convert to channel */
+ if (fwrq->e == 1) {
+ if ((fwrq->m >= (int) 2.412e8 &&
+ fwrq->m <= (int) 2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+
+ while ((c < REG_MAX_CHANNEL) &&
+ (f != ipw2100_frequencies[c]))
+ c++;
+
+ /* hack to fall through */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ }
+
+ if (fwrq->e > 0 || fwrq->m > 1000)
+ return -EOPNOTSUPP;
+ else { /* Set the channel */
+ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+ err = ipw2100_set_channel(priv, fwrq->m, 0);
+ }
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+
+static int ipw2100_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->freq.e = 0;
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured CHANNEL then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_CHANNEL ||
+ priv->status & STATUS_ASSOCIATED)
+ wrqu->freq.m = priv->channel;
+ else
+ wrqu->freq.m = 0;
+
+ IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+ return 0;
+
+}
+
+static int ipw2100_wx_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode);
+
+ if (wrqu->mode == priv->ieee->iw_mode)
+ return 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ switch (wrqu->mode) {
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ err = ipw2100_switch_mode(priv, IW_MODE_MONITOR);
+ break;
+#endif /* CONFIG_IPW2100_MONITOR */
+ case IW_MODE_ADHOC:
+ err = ipw2100_switch_mode(priv, IW_MODE_ADHOC);
+ break;
+ case IW_MODE_INFRA:
+ case IW_MODE_AUTO:
+ default:
+ err = ipw2100_switch_mode(priv, IW_MODE_INFRA);
+ break;
+ }
+
+done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->mode = priv->ieee->iw_mode;
+ IPW_DEBUG_WX("GET Mode -> %d\n", wrqu->mode);
+
+ return 0;
+}
+
+
+#define POWER_MODES 5
+
+/* Values are in microsecond */
+static const s32 timeout_duration[POWER_MODES] = {
+ 350000,
+ 250000,
+ 75000,
+ 37000,
+ 25000,
+};
+
+static const s32 period_duration[POWER_MODES] = {
+ 400000,
+ 700000,
+ 1000000,
+ 1000000,
+ 1000000
+};
+
+static int ipw2100_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_range *range = (struct iw_range *)extra;
+ u16 val;
+ int i, level;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* Let's try to keep this struct in the same order as in
+ * linux/include/wireless.h
+ */
+
+ /* TODO: See what values we can set, and remove the ones we can't
+ * set, or fill them with some default data.
+ */
+
+ /* ~5 Mb/s real (802.11b) */
+ range->throughput = 5 * 1000 * 1000;
+
+// range->sensitivity; /* signal level threshold range */
+
+ range->max_qual.qual = 100;
+ /* TODO: Find real max RSSI and stick here */
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 20 + IPW2100_RSSI_TO_DBM;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = RATE_COUNT;
+
+ for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
+ range->bitrate[i] = ipw2100_rates_11b[i];
+ }
+
+ range->min_rts = MIN_RTS_THRESHOLD;
+ range->max_rts = MAX_RTS_THRESHOLD;
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->min_pmp = period_duration[0]; /* Minimal PM period */
+ range->max_pmp = period_duration[POWER_MODES-1];/* Maximal PM period */
+ range->min_pmt = timeout_duration[POWER_MODES-1]; /* Minimal PM timeout */
+ range->max_pmt = timeout_duration[0];/* Maximal PM timeout */
+
+ /* How to decode max/min PM period */
+ range->pmp_flags = IW_POWER_PERIOD;
+ /* How to decode max/min PM period */
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ /* What PM options are supported */
+ range->pm_capa = IW_POWER_TIMEOUT | IW_POWER_PERIOD;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13; /* Different token sizes */
+ range->num_encoding_sizes = 2; /* Number of entry in the list */
+ range->max_encoding_tokens = WEP_KEYS; /* Max number of tokens */
+// range->encoding_login_index; /* token index for login token */
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ range->txpower_capa = IW_TXPOW_DBM;
+ range->num_txpower = IW_MAX_TXPOWER;
+ for (i = 0, level = (IPW_TX_POWER_MAX_DBM * 16); i < IW_MAX_TXPOWER;
+ i++, level -= ((IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM) * 16) /
+ (IW_MAX_TXPOWER - 1))
+ range->txpower[i] = level / 16;
+ } else {
+ range->txpower_capa = 0;
+ range->num_txpower = 0;
+ }
+
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+// range->retry_capa; /* What retry options are supported */
+// range->retry_flags; /* How to decode max/min retry limit */
+// range->r_time_flags; /* How to decode max/min retry life */
+// range->min_retry; /* Minimal number of retries */
+// range->max_retry; /* Maximal number of retries */
+// range->min_r_time; /* Minimal retry lifetime */
+// range->max_r_time; /* Maximal retry lifetime */
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ // TODO: Include only legal frequencies for some countries
+// if (local->channel_mask & (1 << i)) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = ipw2100_frequencies[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+// }
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ IPW_DEBUG_WX("GET Range\n");
+
+ return 0;
+}
+
+static int ipw2100_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ static const unsigned char any[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ static const unsigned char off[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // sanity checks
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
+ !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ /* we disable mandatory BSSID association */
+ IPW_DEBUG_WX("exit - disable mandatory BSSID\n");
+ priv->config &= ~CFG_STATIC_BSSID;
+ err = ipw2100_set_mandatory_bssid(priv, NULL, 0);
+ goto done;
+ }
+
+ priv->config |= CFG_STATIC_BSSID;
+ memcpy(priv->mandatory_bssid_mac, wrqu->ap_addr.sa_data, ETH_ALEN);
+
+ err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0);
+
+ IPW_DEBUG_WX("SET BSSID -> %02X:%02X:%02X:%02X:%02X:%02X\n",
+ wrqu->ap_addr.sa_data[0] & 0xff,
+ wrqu->ap_addr.sa_data[1] & 0xff,
+ wrqu->ap_addr.sa_data[2] & 0xff,
+ wrqu->ap_addr.sa_data[3] & 0xff,
+ wrqu->ap_addr.sa_data[4] & 0xff,
+ wrqu->ap_addr.sa_data[5] & 0xff);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured BSSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_BSSID ||
+ priv->status & STATUS_ASSOCIATED) {
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN);
+ } else
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+ IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+ return 0;
+}
+
+static int ipw2100_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ char *essid = ""; /* ANY */
+ int length = 0;
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ length = wrqu->essid.length - 1;
+ essid = extra;
+ }
+
+ if (length == 0) {
+ IPW_DEBUG_WX("Setting ESSID to ANY\n");
+ priv->config &= ~CFG_STATIC_ESSID;
+ err = ipw2100_set_essid(priv, NULL, 0, 0);
+ goto done;
+ }
+
+ length = min(length, IW_ESSID_MAX_SIZE);
+
+ priv->config |= CFG_STATIC_ESSID;
+
+ if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
+ IPW_DEBUG_WX("ESSID set to current ESSID.\n");
+ err = 0;
+ goto done;
+ }
+
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
+ length);
+
+ priv->essid_len = length;
+ memcpy(priv->essid, essid, priv->essid_len);
+
+ err = ipw2100_set_essid(priv, essid, length, 0);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured ESSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_ESSID ||
+ priv->status & STATUS_ASSOCIATED) {
+ IPW_DEBUG_WX("Getting essid: '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ memcpy(extra, priv->essid, priv->essid_len);
+ wrqu->essid.length = priv->essid_len;
+ wrqu->essid.flags = 1; /* active */
+ } else {
+ IPW_DEBUG_WX("Getting essid: ANY\n");
+ wrqu->essid.length = 0;
+ wrqu->essid.flags = 0; /* active */
+ }
+
+ return 0;
+}
+
+static int ipw2100_wx_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+ return -E2BIG;
+
+ wrqu->data.length = min((size_t)wrqu->data.length, sizeof(priv->nick));
+ memset(priv->nick, 0, sizeof(priv->nick));
+ memcpy(priv->nick, extra, wrqu->data.length);
+
+ IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick);
+
+ return 0;
+}
+
+static int ipw2100_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->data.length = strlen(priv->nick) + 1;
+ memcpy(extra, priv->nick, wrqu->data.length);
+ wrqu->data.flags = 1; /* active */
+
+ IPW_DEBUG_WX("GET Nickname -> %s \n", extra);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ u32 target_rate = wrqu->bitrate.value;
+ u32 rate;
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ rate = 0;
+
+ if (target_rate == 1000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 1000000))
+ rate |= TX_RATE_1_MBIT;
+ if (target_rate == 2000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 2000000))
+ rate |= TX_RATE_2_MBIT;
+ if (target_rate == 5500000 ||
+ (!wrqu->bitrate.fixed && target_rate > 5500000))
+ rate |= TX_RATE_5_5_MBIT;
+ if (target_rate == 11000000 ||
+ (!wrqu->bitrate.fixed && target_rate > 11000000))
+ rate |= TX_RATE_11_MBIT;
+ if (rate == 0)
+ rate = DEFAULT_TX_RATES;
+
+ err = ipw2100_set_tx_rates(priv, rate, 0);
+
+ IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+
+static int ipw2100_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int val;
+ int len = sizeof(val);
+ int err = 0;
+
+ if (!(priv->status & STATUS_ENABLED) ||
+ priv->status & STATUS_RF_KILL_MASK ||
+ !(priv->status & STATUS_ASSOCIATED)) {
+ wrqu->bitrate.value = 0;
+ return 0;
+ }
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ err = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &val, &len);
+ if (err) {
+ IPW_DEBUG_WX("failed querying ordinals.\n");
+ return err;
+ }
+
+ switch (val & TX_RATE_MASK) {
+ case TX_RATE_1_MBIT:
+ wrqu->bitrate.value = 1000000;
+ break;
+ case TX_RATE_2_MBIT:
+ wrqu->bitrate.value = 2000000;
+ break;
+ case TX_RATE_5_5_MBIT:
+ wrqu->bitrate.value = 5500000;
+ break;
+ case TX_RATE_11_MBIT:
+ wrqu->bitrate.value = 11000000;
+ break;
+ default:
+ wrqu->bitrate.value = 0;
+ }
+
+ IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int value, err;
+
+ /* Auto RTS not yet supported */
+ if (wrqu->rts.fixed == 0)
+ return -EINVAL;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->rts.disabled)
+ value = priv->rts_threshold | RTS_DISABLED;
+ else {
+ if (wrqu->rts.value < 1 ||
+ wrqu->rts.value > 2304) {
+ err = -EINVAL;
+ goto done;
+ }
+ value = wrqu->rts.value;
+ }
+
+ err = ipw2100_set_rts_threshold(priv, value);
+
+ IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->rts.value = priv->rts_threshold & ~RTS_DISABLED;
+ wrqu->rts.fixed = 1; /* no auto select */
+
+ /* If RTS is set to the default value, then it is disabled */
+ wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0, value;
+
+ if (priv->ieee->iw_mode != IW_MODE_ADHOC)
+ return -EINVAL;
+
+ if (wrqu->txpower.disabled == 1 || wrqu->txpower.fixed == 0)
+ value = IPW_TX_POWER_DEFAULT;
+ else {
+ if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM ||
+ wrqu->txpower.value > IPW_TX_POWER_MAX_DBM)
+ return -EINVAL;
+
+ value = (wrqu->txpower.value - IPW_TX_POWER_MIN_DBM) * 16 /
+ (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
+ }
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ err = ipw2100_set_tx_power(priv, value);
+
+ IPW_DEBUG_WX("SET TX Power -> %d \n", value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (priv->ieee->iw_mode != IW_MODE_ADHOC) {
+ wrqu->power.disabled = 1;
+ return 0;
+ }
+
+ if (priv->tx_power == IPW_TX_POWER_DEFAULT) {
+ wrqu->power.fixed = 0;
+ wrqu->power.value = IPW_TX_POWER_MAX_DBM;
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ wrqu->power.fixed = 1;
+ wrqu->power.value =
+ (priv->tx_power *
+ (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM)) /
+ (IPW_TX_POWER_MAX - IPW_TX_POWER_MIN) +
+ IPW_TX_POWER_MIN_DBM;
+ }
+
+ wrqu->power.flags = IW_TXPOW_DBM;
+
+ IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->power.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (!wrqu->frag.fixed)
+ return -EINVAL;
+
+ if (wrqu->frag.disabled) {
+ priv->frag_threshold |= FRAG_DISABLED;
+ priv->ieee->fts = DEFAULT_FTS;
+ } else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ priv->ieee->fts = wrqu->frag.value & ~0x1;
+ priv->frag_threshold = priv->ieee->fts;
+ }
+
+ IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts);
+
+ return 0;
+}
+
+static int ipw2100_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ wrqu->frag.value = priv->frag_threshold & ~FRAG_DISABLED;
+ wrqu->frag.fixed = 0; /* no auto select */
+ wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
+ wrqu->retry.disabled)
+ return -EINVAL;
+
+ if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
+ return 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->retry.flags & IW_RETRY_MIN) {
+ err = ipw2100_set_short_retry(priv, wrqu->retry.value);
+ IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
+ wrqu->retry.value);
+ goto done;
+ }
+
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ err = ipw2100_set_long_retry(priv, wrqu->retry.value);
+ IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
+ wrqu->retry.value);
+ goto done;
+ }
+
+ err = ipw2100_set_short_retry(priv, wrqu->retry.value);
+ if (!err)
+ err = ipw2100_set_long_retry(priv, wrqu->retry.value);
+
+ IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ wrqu->retry.disabled = 0; /* can't be disabled */
+
+ if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
+ IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
+ wrqu->retry.value = priv->long_retry_limit;
+ } else {
+ wrqu->retry.flags =
+ (priv->short_retry_limit !=
+ priv->long_retry_limit) ?
+ IW_RETRY_LIMIT & IW_RETRY_MIN : IW_RETRY_LIMIT;
+
+ wrqu->retry.value = priv->short_retry_limit;
+ }
+
+ IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value);
+
+ return 0;
+}
+
+static int ipw2100_wx_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ IPW_DEBUG_WX("Initiating scan...\n");
+ if (ipw2100_set_scan_options(priv) ||
+ ipw2100_start_scan(priv)) {
+ IPW_DEBUG_WX("Start scan failed.\n");
+
+ /* TODO: Mark a scan as pending so when hardware initialized
+ * a scan starts */
+ }
+
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra);
+}
+
+
+/*
+ * Implementation based on code in hostap-driver v0.1.3 hostap_ioctl.c
+ */
+static int ipw2100_wx_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ /*
+ * No check of STATUS_INITIALIZED required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw2100_wx_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw2100_wx_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (wrqu->power.disabled) {
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM);
+ IPW_DEBUG_WX("SET Power Management Mode -> off\n");
+ goto done;
+ }
+
+ switch (wrqu->power.flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ break;
+ default: /* Otherwise we don't support it */
+ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
+ wrqu->power.flags);
+ err = -EOPNOTSUPP;
+ goto done;
+ }
+
+ /* If the user hasn't specified a power management mode yet, default
+ * to BATTERY */
+ priv->power_mode = IPW_POWER_ENABLED | priv->power_mode;
+ err = ipw2100_set_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
+
+ IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n",
+ priv->power_mode);
+
+ done:
+ up(&priv->action_sem);
+ return err;
+
+}
+
+static int ipw2100_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ wrqu->power.flags = 0;
+ }
+
+ IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
+
+ return 0;
+}
+
+
+/*
+ *
+ * IWPRIV handlers
+ *
+ */
+#ifdef CONFIG_IPW2100_MONITOR
+static int ipw2100_wx_set_promisc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int *parms = (int *)extra;
+ int enable = (parms[0] > 0);
+ int err = 0;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (enable) {
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ err = ipw2100_set_channel(priv, parms[1], 0);
+ goto done;
+ }
+ priv->channel = parms[1];
+ err = ipw2100_switch_mode(priv, IW_MODE_MONITOR);
+ } else {
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ err = ipw2100_switch_mode(priv, priv->last_mode);
+ }
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_reset(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ if (priv->status & STATUS_INITIALIZED)
+ schedule_reset(priv);
+ return 0;
+}
+
+#endif
+
+static int ipw2100_wx_set_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err = 0, mode = *(int *)extra;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if ((mode < 1) || (mode > POWER_MODES))
+ mode = IPW_POWER_AUTO;
+
+ if (priv->power_mode != mode)
+ err = ipw2100_set_power_mode(priv, mode);
+ done:
+ up(&priv->action_sem);
+ return err;
+}
+
+#define MAX_POWER_STRING 80
+static int ipw2100_wx_get_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int level = IPW_POWER_LEVEL(priv->power_mode);
+ s32 timeout, period;
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (Off)", level);
+ } else {
+ switch (level) {
+ case IPW_POWER_MODE_CAM:
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (None)", level);
+ break;
+ case IPW_POWER_AUTO:
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d (Auto)", 0);
+ break;
+ default:
+ timeout = timeout_duration[level - 1] / 1000;
+ period = period_duration[level - 1] / 1000;
+ snprintf(extra, MAX_POWER_STRING,
+ "Power save level: %d "
+ "(Timeout %dms, Period %dms)",
+ level, timeout, period);
+ }
+ }
+
+ wrqu->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+
+static int ipw2100_wx_set_preamble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ int err, mode = *(int *)extra;
+
+ down(&priv->action_sem);
+ if (!(priv->status & STATUS_INITIALIZED)) {
+ err = -EIO;
+ goto done;
+ }
+
+ if (mode == 1)
+ priv->config |= CFG_LONG_PREAMBLE;
+ else if (mode == 0)
+ priv->config &= ~CFG_LONG_PREAMBLE;
+ else {
+ err = -EINVAL;
+ goto done;
+ }
+
+ err = ipw2100_system_config(priv, 0);
+
+done:
+ up(&priv->action_sem);
+ return err;
+}
+
+static int ipw2100_wx_get_preamble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ /*
+ * This can be called at any time. No action lock required
+ */
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+
+ if (priv->config & CFG_LONG_PREAMBLE)
+ snprintf(wrqu->name, IFNAMSIZ, "long (1)");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "auto (0)");
+
+ return 0;
+}
+
+static iw_handler ipw2100_wx_handlers[] =
+{
+ NULL, /* SIOCSIWCOMMIT */
+ ipw2100_wx_get_name, /* SIOCGIWNAME */
+ NULL, /* SIOCSIWNWID */
+ NULL, /* SIOCGIWNWID */
+ ipw2100_wx_set_freq, /* SIOCSIWFREQ */
+ ipw2100_wx_get_freq, /* SIOCGIWFREQ */
+ ipw2100_wx_set_mode, /* SIOCSIWMODE */
+ ipw2100_wx_get_mode, /* SIOCGIWMODE */
+ NULL, /* SIOCSIWSENS */
+ NULL, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ ipw2100_wx_get_range, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+ NULL, /* SIOCSIWSPY */
+ NULL, /* SIOCGIWSPY */
+ NULL, /* SIOCGIWTHRSPY */
+ NULL, /* SIOCWIWTHRSPY */
+ ipw2100_wx_set_wap, /* SIOCSIWAP */
+ ipw2100_wx_get_wap, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST -- deprecated */
+ ipw2100_wx_set_scan, /* SIOCSIWSCAN */
+ ipw2100_wx_get_scan, /* SIOCGIWSCAN */
+ ipw2100_wx_set_essid, /* SIOCSIWESSID */
+ ipw2100_wx_get_essid, /* SIOCGIWESSID */
+ ipw2100_wx_set_nick, /* SIOCSIWNICKN */
+ ipw2100_wx_get_nick, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ ipw2100_wx_set_rate, /* SIOCSIWRATE */
+ ipw2100_wx_get_rate, /* SIOCGIWRATE */
+ ipw2100_wx_set_rts, /* SIOCSIWRTS */
+ ipw2100_wx_get_rts, /* SIOCGIWRTS */
+ ipw2100_wx_set_frag, /* SIOCSIWFRAG */
+ ipw2100_wx_get_frag, /* SIOCGIWFRAG */
+ ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */
+ ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */
+ ipw2100_wx_set_retry, /* SIOCSIWRETRY */
+ ipw2100_wx_get_retry, /* SIOCGIWRETRY */
+ ipw2100_wx_set_encode, /* SIOCSIWENCODE */
+ ipw2100_wx_get_encode, /* SIOCGIWENCODE */
+ ipw2100_wx_set_power, /* SIOCSIWPOWER */
+ ipw2100_wx_get_power, /* SIOCGIWPOWER */
+};
+
+#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV
+#define IPW2100_PRIV_RESET SIOCIWFIRSTPRIV+1
+#define IPW2100_PRIV_SET_POWER SIOCIWFIRSTPRIV+2
+#define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3
+#define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4
+#define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5
+
+static const struct iw_priv_args ipw2100_private_args[] = {
+
+#ifdef CONFIG_IPW2100_MONITOR
+ {
+ IPW2100_PRIV_SET_MONITOR,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"
+ },
+ {
+ IPW2100_PRIV_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"
+ },
+#endif /* CONFIG_IPW2100_MONITOR */
+
+ {
+ IPW2100_PRIV_SET_POWER,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power"
+ },
+ {
+ IPW2100_PRIV_GET_POWER,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_POWER_STRING, "get_power"
+ },
+ {
+ IPW2100_PRIV_SET_LONGPREAMBLE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"
+ },
+ {
+ IPW2100_PRIV_GET_LONGPREAMBLE,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"
+ },
+};
+
+static iw_handler ipw2100_private_handler[] = {
+#ifdef CONFIG_IPW2100_MONITOR
+ ipw2100_wx_set_promisc,
+ ipw2100_wx_reset,
+#else /* CONFIG_IPW2100_MONITOR */
+ NULL,
+ NULL,
+#endif /* CONFIG_IPW2100_MONITOR */
+ ipw2100_wx_set_powermode,
+ ipw2100_wx_get_powermode,
+ ipw2100_wx_set_preamble,
+ ipw2100_wx_get_preamble,
+};
+
+static struct iw_handler_def ipw2100_wx_handler_def =
+{
+ .standard = ipw2100_wx_handlers,
+ .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler),
+ .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler),
+ .num_private_args = sizeof(ipw2100_private_args) /
+ sizeof(struct iw_priv_args),
+ .private = (iw_handler *)ipw2100_private_handler,
+ .private_args = (struct iw_priv_args *)ipw2100_private_args,
+};
+
+/*
+ * Get wireless statistics.
+ * Called by /proc/net/wireless
+ * Also called by SIOCGIWSTATS
+ */
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev)
+{
+ enum {
+ POOR = 30,
+ FAIR = 60,
+ GOOD = 80,
+ VERY_GOOD = 90,
+ EXCELLENT = 95,
+ PERFECT = 100
+ };
+ int rssi_qual;
+ int tx_qual;
+ int beacon_qual;
+
+ struct ipw2100_priv *priv = ieee80211_priv(dev);
+ struct iw_statistics *wstats;
+ u32 rssi, quality, tx_retries, missed_beacons, tx_failures;
+ u32 ord_len = sizeof(u32);
+
+ if (!priv)
+ return (struct iw_statistics *) NULL;
+
+ wstats = &priv->wstats;
+
+ /* if hw is disabled, then ipw2100_get_ordinal() can't be called.
+ * ipw2100_wx_wireless_stats seems to be called before fw is
+ * initialized. STATUS_ASSOCIATED will only be set if the hw is up
+ * and associated; if not associcated, the values are all meaningless
+ * anyway, so set them all to NULL and INVALID */
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 0;
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 7;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ return wstats;
+ }
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_MISSED_BCNS,
+ &missed_beacons, &ord_len))
+ goto fail_get_ordinal;
+
+ /* If we don't have a connection the quality and level is 0*/
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ } else {
+ if (ipw2100_get_ordinal(priv, IPW_ORD_RSSI_AVG_CURR,
+ &rssi, &ord_len))
+ goto fail_get_ordinal;
+ wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM;
+ if (rssi < 10)
+ rssi_qual = rssi * POOR / 10;
+ else if (rssi < 15)
+ rssi_qual = (rssi - 10) * (FAIR - POOR) / 5 + POOR;
+ else if (rssi < 20)
+ rssi_qual = (rssi - 15) * (GOOD - FAIR) / 5 + FAIR;
+ else if (rssi < 30)
+ rssi_qual = (rssi - 20) * (VERY_GOOD - GOOD) /
+ 10 + GOOD;
+ else
+ rssi_qual = (rssi - 30) * (PERFECT - VERY_GOOD) /
+ 10 + VERY_GOOD;
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_RETRIES,
+ &tx_retries, &ord_len))
+ goto fail_get_ordinal;
+
+ if (tx_retries > 75)
+ tx_qual = (90 - tx_retries) * POOR / 15;
+ else if (tx_retries > 70)
+ tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
+ else if (tx_retries > 65)
+ tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
+ else if (tx_retries > 50)
+ tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
+ 15 + GOOD;
+ else
+ tx_qual = (50 - tx_retries) *
+ (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+
+ if (missed_beacons > 50)
+ beacon_qual = (60 - missed_beacons) * POOR / 10;
+ else if (missed_beacons > 40)
+ beacon_qual = (50 - missed_beacons) * (FAIR - POOR) /
+ 10 + POOR;
+ else if (missed_beacons > 32)
+ beacon_qual = (40 - missed_beacons) * (GOOD - FAIR) /
+ 18 + FAIR;
+ else if (missed_beacons > 20)
+ beacon_qual = (32 - missed_beacons) *
+ (VERY_GOOD - GOOD) / 20 + GOOD;
+ else
+ beacon_qual = (20 - missed_beacons) *
+ (PERFECT - VERY_GOOD) / 20 + VERY_GOOD;
+
+ quality = min(beacon_qual, min(tx_qual, rssi_qual));
+
+#ifdef CONFIG_IPW_DEBUG
+ if (beacon_qual == quality)
+ IPW_DEBUG_WX("Quality clamped by Missed Beacons\n");
+ else if (tx_qual == quality)
+ IPW_DEBUG_WX("Quality clamped by Tx Retries\n");
+ else if (quality != 100)
+ IPW_DEBUG_WX("Quality clamped by Signal Strength\n");
+ else
+ IPW_DEBUG_WX("Quality not clamped.\n");
+#endif
+
+ wstats->qual.qual = quality;
+ wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM;
+ }
+
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 7;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
+
+ /* FIXME: this is percent and not a # */
+ wstats->miss.beacon = missed_beacons;
+
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURES,
+ &tx_failures, &ord_len))
+ goto fail_get_ordinal;
+ wstats->discard.retries = tx_failures;
+
+ return wstats;
+
+ fail_get_ordinal:
+ IPW_DEBUG_WX("failed querying ordinals.\n");
+
+ return (struct iw_statistics *) NULL;
+}
+
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
+{
+ union iwreq_data wrqu;
+ int len = ETH_ALEN;
+
+ if (priv->status & STATUS_STOPPING)
+ return;
+
+ down(&priv->action_sem);
+
+ IPW_DEBUG_WX("enter\n");
+
+ up(&priv->action_sem);
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ /* Fetch BSSID from the hardware */
+ if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) ||
+ priv->status & STATUS_RF_KILL_MASK ||
+ ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID,
+ &priv->bssid, &len)) {
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ } else {
+ /* We now have the BSSID, so can finish setting to the full
+ * associated state */
+ memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN);
+ memcpy(&priv->ieee->bssid, priv->bssid, ETH_ALEN);
+ priv->status &= ~STATUS_ASSOCIATING;
+ priv->status |= STATUS_ASSOCIATED;
+ netif_carrier_on(priv->net_dev);
+ if (netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_INFO("Waking net queue.\n");
+ netif_wake_queue(priv->net_dev);
+ } else {
+ IPW_DEBUG_INFO("Starting net queue.\n");
+ netif_start_queue(priv->net_dev);
+ }
+ }
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_WX("Configuring ESSID\n");
+ down(&priv->action_sem);
+ /* This is a disassociation event, so kick the firmware to
+ * look for another AP */
+ if (priv->config & CFG_STATIC_ESSID)
+ ipw2100_set_essid(priv, priv->essid, priv->essid_len, 0);
+ else
+ ipw2100_set_essid(priv, NULL, 0, 0);
+ up(&priv->action_sem);
+ }
+
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+#define IPW2100_FW_MAJOR_VERSION 1
+#define IPW2100_FW_MINOR_VERSION 3
+
+#define IPW2100_FW_MINOR(x) ((x & 0xff) >> 8)
+#define IPW2100_FW_MAJOR(x) (x & 0xff)
+
+#define IPW2100_FW_VERSION ((IPW2100_FW_MINOR_VERSION << 8) | \
+ IPW2100_FW_MAJOR_VERSION)
+
+#define IPW2100_FW_PREFIX "ipw2100-" __stringify(IPW2100_FW_MAJOR_VERSION) \
+"." __stringify(IPW2100_FW_MINOR_VERSION)
+
+#define IPW2100_FW_NAME(x) IPW2100_FW_PREFIX "" x ".fw"
+
+
+/*
+
+BINARY FIRMWARE HEADER FORMAT
+
+offset length desc
+0 2 version
+2 2 mode == 0:BSS,1:IBSS,2:MONITOR
+4 4 fw_len
+8 4 uc_len
+C fw_len firmware data
+12 + fw_len uc_len microcode data
+
+*/
+
+struct ipw2100_fw_header {
+ short version;
+ short mode;
+ unsigned int fw_size;
+ unsigned int uc_size;
+} __attribute__ ((packed));
+
+
+
+static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw)
+{
+ struct ipw2100_fw_header *h =
+ (struct ipw2100_fw_header *)fw->fw_entry->data;
+
+ if (IPW2100_FW_MAJOR(h->version) != IPW2100_FW_MAJOR_VERSION) {
+ printk(KERN_WARNING DRV_NAME ": Firmware image not compatible "
+ "(detected version id of %u). "
+ "See Documentation/networking/README.ipw2100\n",
+ h->version);
+ return 1;
+ }
+
+ fw->version = h->version;
+ fw->fw.data = fw->fw_entry->data + sizeof(struct ipw2100_fw_header);
+ fw->fw.size = h->fw_size;
+ fw->uc.data = fw->fw.data + h->fw_size;
+ fw->uc.size = h->uc_size;
+
+ return 0;
+}
+
+
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ char *fw_name;
+ int rc;
+
+ IPW_DEBUG_INFO("%s: Using hotplug firmware load.\n",
+ priv->net_dev->name);
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ fw_name = IPW2100_FW_NAME("-i");
+ break;
+#ifdef CONFIG_IPW2100_MONITOR
+ case IW_MODE_MONITOR:
+ fw_name = IPW2100_FW_NAME("-p");
+ break;
+#endif
+ case IW_MODE_INFRA:
+ default:
+ fw_name = IPW2100_FW_NAME("");
+ break;
+ }
+
+ rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
+
+ if (rc < 0) {
+ printk(KERN_ERR DRV_NAME ": "
+ "%s: Firmware '%s' not available or load failed.\n",
+ priv->net_dev->name, fw_name);
+ return rc;
+ }
+ IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data,
+ fw->fw_entry->size);
+
+ ipw2100_mod_firmware_load(fw);
+
+ return 0;
+}
+
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ fw->version = 0;
+ if (fw->fw_entry)
+ release_firmware(fw->fw_entry);
+ fw->fw_entry = NULL;
+}
+
+
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
+{
+ char ver[MAX_FW_VERSION_LEN];
+ u32 len = MAX_FW_VERSION_LEN;
+ u32 tmp;
+ int i;
+ /* firmware version is an ascii string (max len of 14) */
+ if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_FW_VER_NUM,
+ ver, &len))
+ return -EIO;
+ tmp = max;
+ if (len >= max)
+ len = max - 1;
+ for (i = 0; i < len; i++)
+ buf[i] = ver[i];
+ buf[i] = '\0';
+ return tmp;
+}
+
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
+{
+ u32 ver;
+ u32 len = sizeof(ver);
+ /* microcode version is a 32 bit integer */
+ if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION,
+ &ver, &len))
+ return -EIO;
+ return snprintf(buf, max, "%08X", ver);
+}
+
+/*
+ * On exit, the firmware will have been freed from the fw list
+ */
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ /* firmware is constructed of N contiguous entries, each entry is
+ * structured as:
+ *
+ * offset sie desc
+ * 0 4 address to write to
+ * 4 2 length of data run
+ * 6 length data
+ */
+ unsigned int addr;
+ unsigned short len;
+
+ const unsigned char *firmware_data = fw->fw.data;
+ unsigned int firmware_data_left = fw->fw.size;
+
+ while (firmware_data_left > 0) {
+ addr = *(u32 *)(firmware_data);
+ firmware_data += 4;
+ firmware_data_left -= 4;
+
+ len = *(u16 *)(firmware_data);
+ firmware_data += 2;
+ firmware_data_left -= 2;
+
+ if (len > 32) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Invalid firmware run-length of %d bytes\n",
+ len);
+ return -EINVAL;
+ }
+
+ write_nic_memory(priv->net_dev, addr, len, firmware_data);
+ firmware_data += len;
+ firmware_data_left -= len;
+ }
+
+ return 0;
+}
+
+struct symbol_alive_response {
+ u8 cmd_id;
+ u8 seq_num;
+ u8 ucode_rev;
+ u8 eeprom_valid;
+ u16 valid_flags;
+ u8 IEEE_addr[6];
+ u16 flags;
+ u16 pcb_rev;
+ u16 clock_settle_time; // 1us LSB
+ u16 powerup_settle_time; // 1us LSB
+ u16 hop_settle_time; // 1us LSB
+ u8 date[3]; // month, day, year
+ u8 time[2]; // hours, minutes
+ u8 ucode_valid;
+};
+
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
+{
+ struct net_device *dev = priv->net_dev;
+ const unsigned char *microcode_data = fw->uc.data;
+ unsigned int microcode_data_left = fw->uc.size;
+ void __iomem *reg = (void __iomem *)dev->base_addr;
+
+ struct symbol_alive_response response;
+ int i, j;
+ u8 data;
+
+ /* Symbol control */
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
+ readl(reg);
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
+ readl(reg);
+
+ /* HW config */
+ write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
+ readl(reg);
+ write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */
+ readl(reg);
+
+ /* EN_CS_ACCESS bit to reset control store pointer */
+ write_nic_byte(dev, 0x210000, 0x40);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x40);
+ readl(reg);
+
+ /* copy microcode from buffer into Symbol */
+
+ while (microcode_data_left > 0) {
+ write_nic_byte(dev, 0x210010, *microcode_data++);
+ write_nic_byte(dev, 0x210010, *microcode_data++);
+ microcode_data_left -= 2;
+ }
+
+ /* EN_CS_ACCESS bit to reset the control store pointer */
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+
+ /* Enable System (Reg 0)
+ * first enable causes garbage in RX FIFO */
+ write_nic_byte(dev, 0x210000, 0x0);
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x80);
+ readl(reg);
+
+ /* Reset External Baseband Reg */
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
+ readl(reg);
+ write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
+ readl(reg);
+
+ /* HW Config (Reg 5) */
+ write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
+ readl(reg);
+ write_nic_byte(dev, 0x210014, 0x72); // fifo width =16
+ readl(reg);
+
+ /* Enable System (Reg 0)
+ * second enable should be OK */
+ write_nic_byte(dev, 0x210000, 0x00); // clear enable system
+ readl(reg);
+ write_nic_byte(dev, 0x210000, 0x80); // set enable system
+
+ /* check Symbol is enabled - upped this from 5 as it wasn't always
+ * catching the update */
+ for (i = 0; i < 10; i++) {
+ udelay(10);
+
+ /* check Dino is enabled bit */
+ read_nic_byte(dev, 0x210000, &data);
+ if (data & 0x1)
+ break;
+ }
+
+ if (i == 10) {
+ printk(KERN_ERR DRV_NAME ": %s: Error initializing Symbol\n",
+ dev->name);
+ return -EIO;
+ }
+
+ /* Get Symbol alive response */
+ for (i = 0; i < 30; i++) {
+ /* Read alive response structure */
+ for (j = 0;
+ j < (sizeof(struct symbol_alive_response) >> 1);
+ j++)
+ read_nic_word(dev, 0x210004,
+ ((u16 *)&response) + j);
+
+ if ((response.cmd_id == 1) &&
+ (response.ucode_valid == 0x1))
+ break;
+ udelay(10);
+ }
+
+ if (i == 30) {
+ printk(KERN_ERR DRV_NAME ": %s: No response from Symbol - hw not alive\n",
+ dev->name);
+ printk_buf(IPW_DL_ERROR, (u8*)&response, sizeof(response));
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
new file mode 100644
index 000000000000..c9e99ce15d66
--- /dev/null
+++ b/drivers/net/wireless/ipw2100.h
@@ -0,0 +1,1167 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ 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, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#ifndef _IPW2100_H
+#define _IPW2100_H
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+#include <linux/socket.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/version.h>
+#include <net/iw_handler.h> // new driver API
+
+#include <net/ieee80211.h>
+
+#include <linux/workqueue.h>
+
+struct ipw2100_priv;
+struct ipw2100_tx_packet;
+struct ipw2100_rx_packet;
+
+#define IPW_DL_UNINIT 0x80000000
+#define IPW_DL_NONE 0x00000000
+#define IPW_DL_ALL 0x7FFFFFFF
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IPW_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IPW2100_xxxx_DEBUG() macro definition for your
+ * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw2100/debug_level
+ *
+ * you simply need to add your entry to the ipw2100_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw2100 then you do not have
+ * CONFIG_IPW_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IPW_DL_ERROR (1<<0)
+#define IPW_DL_WARNING (1<<1)
+#define IPW_DL_INFO (1<<2)
+#define IPW_DL_WX (1<<3)
+#define IPW_DL_HC (1<<5)
+#define IPW_DL_STATE (1<<6)
+
+#define IPW_DL_NOTIF (1<<10)
+#define IPW_DL_SCAN (1<<11)
+#define IPW_DL_ASSOC (1<<12)
+#define IPW_DL_DROP (1<<13)
+
+#define IPW_DL_IOCTL (1<<14)
+#define IPW_DL_RF_KILL (1<<17)
+
+
+#define IPW_DL_MANAGE (1<<15)
+#define IPW_DL_FW (1<<16)
+
+#define IPW_DL_FRAG (1<<21)
+#define IPW_DL_WEP (1<<22)
+#define IPW_DL_TX (1<<23)
+#define IPW_DL_RX (1<<24)
+#define IPW_DL_ISR (1<<25)
+#define IPW_DL_IO (1<<26)
+#define IPW_DL_TRACE (1<<28)
+
+#define IPW_DEBUG_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_INFO(f...) IPW_DEBUG(IPW_DL_INFO, ## f)
+#define IPW_DEBUG_WX(f...) IPW_DEBUG(IPW_DL_WX, ## f)
+#define IPW_DEBUG_SCAN(f...) IPW_DEBUG(IPW_DL_SCAN, ## f)
+#define IPW_DEBUG_NOTIF(f...) IPW_DEBUG(IPW_DL_NOTIF, ## f)
+#define IPW_DEBUG_TRACE(f...) IPW_DEBUG(IPW_DL_TRACE, ## f)
+#define IPW_DEBUG_RX(f...) IPW_DEBUG(IPW_DL_RX, ## f)
+#define IPW_DEBUG_TX(f...) IPW_DEBUG(IPW_DL_TX, ## f)
+#define IPW_DEBUG_ISR(f...) IPW_DEBUG(IPW_DL_ISR, ## f)
+#define IPW_DEBUG_MANAGEMENT(f...) IPW_DEBUG(IPW_DL_MANAGE, ## f)
+#define IPW_DEBUG_WEP(f...) IPW_DEBUG(IPW_DL_WEP, ## f)
+#define IPW_DEBUG_HC(f...) IPW_DEBUG(IPW_DL_HC, ## f)
+#define IPW_DEBUG_FRAG(f...) IPW_DEBUG(IPW_DL_FRAG, ## f)
+#define IPW_DEBUG_FW(f...) IPW_DEBUG(IPW_DL_FW, ## f)
+#define IPW_DEBUG_RF_KILL(f...) IPW_DEBUG(IPW_DL_RF_KILL, ## f)
+#define IPW_DEBUG_DROP(f...) IPW_DEBUG(IPW_DL_DROP, ## f)
+#define IPW_DEBUG_IO(f...) IPW_DEBUG(IPW_DL_IO, ## f)
+#define IPW_DEBUG_IOCTL(f...) IPW_DEBUG(IPW_DL_IOCTL, ## f)
+#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+
+enum {
+ IPW_HW_STATE_DISABLED = 1,
+ IPW_HW_STATE_ENABLED = 0
+};
+
+struct ssid_context {
+ char ssid[IW_ESSID_MAX_SIZE + 1];
+ int ssid_len;
+ unsigned char bssid[ETH_ALEN];
+ int port_type;
+ int channel;
+
+};
+
+extern const char *port_type_str[];
+extern const char *band_str[];
+
+#define NUMBER_OF_BD_PER_COMMAND_PACKET 1
+#define NUMBER_OF_BD_PER_DATA_PACKET 2
+
+#define IPW_MAX_BDS 6
+#define NUMBER_OF_OVERHEAD_BDS_PER_PACKETR 2
+#define NUMBER_OF_BDS_TO_LEAVE_FOR_COMMANDS 1
+
+#define REQUIRED_SPACE_IN_RING_FOR_COMMAND_PACKET \
+ (IPW_BD_QUEUE_W_R_MIN_SPARE + NUMBER_OF_BD_PER_COMMAND_PACKET)
+
+struct bd_status {
+ union {
+ struct { u8 nlf:1, txType:2, intEnabled:1, reserved:4;} fields;
+ u8 field;
+ } info;
+} __attribute__ ((packed));
+
+struct ipw2100_bd {
+ u32 host_addr;
+ u32 buf_length;
+ struct bd_status status;
+ /* number of fragments for frame (should be set only for
+ * 1st TBD) */
+ u8 num_fragments;
+ u8 reserved[6];
+} __attribute__ ((packed));
+
+#define IPW_BD_QUEUE_LENGTH(n) (1<<n)
+#define IPW_BD_ALIGNMENT(L) (L*sizeof(struct ipw2100_bd))
+
+#define IPW_BD_STATUS_TX_FRAME_802_3 0x00
+#define IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT 0x01
+#define IPW_BD_STATUS_TX_FRAME_COMMAND 0x02
+#define IPW_BD_STATUS_TX_FRAME_802_11 0x04
+#define IPW_BD_STATUS_TX_INTERRUPT_ENABLE 0x08
+
+struct ipw2100_bd_queue {
+ /* driver (virtual) pointer to queue */
+ struct ipw2100_bd *drv;
+
+ /* firmware (physical) pointer to queue */
+ dma_addr_t nic;
+
+ /* Length of phy memory allocated for BDs */
+ u32 size;
+
+ /* Number of BDs in queue (and in array) */
+ u32 entries;
+
+ /* Number of available BDs (invalid for NIC BDs) */
+ u32 available;
+
+ /* Offset of oldest used BD in array (next one to
+ * check for completion) */
+ u32 oldest;
+
+ /* Offset of next available (unused) BD */
+ u32 next;
+};
+
+#define RX_QUEUE_LENGTH 256
+#define TX_QUEUE_LENGTH 256
+#define HW_QUEUE_LENGTH 256
+
+#define TX_PENDED_QUEUE_LENGTH (TX_QUEUE_LENGTH / NUMBER_OF_BD_PER_DATA_PACKET)
+
+#define STATUS_TYPE_MASK 0x0000000f
+#define COMMAND_STATUS_VAL 0
+#define STATUS_CHANGE_VAL 1
+#define P80211_DATA_VAL 2
+#define P8023_DATA_VAL 3
+#define HOST_NOTIFICATION_VAL 4
+
+#define IPW2100_RSSI_TO_DBM (-98)
+
+struct ipw2100_status {
+ u32 frame_size;
+ u16 status_fields;
+ u8 flags;
+#define IPW_STATUS_FLAG_DECRYPTED (1<<0)
+#define IPW_STATUS_FLAG_WEP_ENCRYPTED (1<<1)
+#define IPW_STATUS_FLAG_CRC_ERROR (1<<2)
+ u8 rssi;
+} __attribute__ ((packed));
+
+struct ipw2100_status_queue {
+ /* driver (virtual) pointer to queue */
+ struct ipw2100_status *drv;
+
+ /* firmware (physical) pointer to queue */
+ dma_addr_t nic;
+
+ /* Length of phy memory allocated for BDs */
+ u32 size;
+};
+
+#define HOST_COMMAND_PARAMS_REG_LEN 100
+#define CMD_STATUS_PARAMS_REG_LEN 3
+
+#define IPW_WPA_CAPABILITIES 0x1
+#define IPW_WPA_LISTENINTERVAL 0x2
+#define IPW_WPA_AP_ADDRESS 0x4
+
+#define IPW_MAX_VAR_IE_LEN ((HOST_COMMAND_PARAMS_REG_LEN - 4) * sizeof(u32))
+
+struct ipw2100_wpa_assoc_frame {
+ u16 fixed_ie_mask;
+ struct {
+ u16 capab_info;
+ u16 listen_interval;
+ u8 current_ap[ETH_ALEN];
+ } fixed_ies;
+ u32 var_ie_len;
+ u8 var_ie[IPW_MAX_VAR_IE_LEN];
+};
+
+#define IPW_BSS 1
+#define IPW_MONITOR 2
+#define IPW_IBSS 3
+
+/**
+ * @struct _tx_cmd - HWCommand
+ * @brief H/W command structure.
+ */
+struct ipw2100_cmd_header {
+ u32 host_command_reg;
+ u32 host_command_reg1;
+ u32 sequence;
+ u32 host_command_len_reg;
+ u32 host_command_params_reg[HOST_COMMAND_PARAMS_REG_LEN];
+ u32 cmd_status_reg;
+ u32 cmd_status_params_reg[CMD_STATUS_PARAMS_REG_LEN];
+ u32 rxq_base_ptr;
+ u32 rxq_next_ptr;
+ u32 rxq_host_ptr;
+ u32 txq_base_ptr;
+ u32 txq_next_ptr;
+ u32 txq_host_ptr;
+ u32 tx_status_reg;
+ u32 reserved;
+ u32 status_change_reg;
+ u32 reserved1[3];
+ u32 *ordinal1_ptr;
+ u32 *ordinal2_ptr;
+} __attribute__ ((packed));
+
+struct ipw2100_data_header {
+ u32 host_command_reg;
+ u32 host_command_reg1;
+ u8 encrypted; // BOOLEAN in win! TRUE if frame is enc by driver
+ u8 needs_encryption; // BOOLEAN in win! TRUE if frma need to be enc in NIC
+ u8 wep_index; // 0 no key, 1-4 key index, 0xff immediate key
+ u8 key_size; // 0 no imm key, 0x5 64bit encr, 0xd 128bit encr, 0x10 128bit encr and 128bit IV
+ u8 key[16];
+ u8 reserved[10]; // f/w reserved
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+ u16 fragment_size;
+} __attribute__ ((packed));
+
+/* Host command data structure */
+struct host_command {
+ u32 host_command; // COMMAND ID
+ u32 host_command1; // COMMAND ID
+ u32 host_command_sequence; // UNIQUE COMMAND NUMBER (ID)
+ u32 host_command_length; // LENGTH
+ u32 host_command_parameters[HOST_COMMAND_PARAMS_REG_LEN]; // COMMAND PARAMETERS
+} __attribute__ ((packed));
+
+
+typedef enum {
+ POWER_ON_RESET,
+ EXIT_POWER_DOWN_RESET,
+ SW_RESET,
+ EEPROM_RW,
+ SW_RE_INIT
+} ipw2100_reset_event;
+
+enum {
+ COMMAND = 0xCAFE,
+ DATA,
+ RX
+};
+
+
+struct ipw2100_tx_packet {
+ int type;
+ int index;
+ union {
+ struct { /* COMMAND */
+ struct ipw2100_cmd_header* cmd;
+ dma_addr_t cmd_phys;
+ } c_struct;
+ struct { /* DATA */
+ struct ipw2100_data_header* data;
+ dma_addr_t data_phys;
+ struct ieee80211_txb *txb;
+ } d_struct;
+ } info;
+ int jiffy_start;
+
+ struct list_head list;
+};
+
+
+struct ipw2100_rx_packet {
+ struct ipw2100_rx *rxp;
+ dma_addr_t dma_addr;
+ int jiffy_start;
+ struct sk_buff *skb;
+ struct list_head list;
+};
+
+#define FRAG_DISABLED (1<<31)
+#define RTS_DISABLED (1<<31)
+#define MAX_RTS_THRESHOLD 2304U
+#define MIN_RTS_THRESHOLD 1U
+#define DEFAULT_RTS_THRESHOLD 1000U
+
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+struct ipw2100_ordinals {
+ u32 table1_addr;
+ u32 table2_addr;
+ u32 table1_size;
+ u32 table2_size;
+};
+
+/* Host Notification header */
+struct ipw2100_notification {
+ u32 hnhdr_subtype; /* type of host notification */
+ u32 hnhdr_size; /* size in bytes of data
+ or number of entries, if table.
+ Does NOT include header */
+} __attribute__ ((packed));
+
+#define MAX_KEY_SIZE 16
+#define MAX_KEYS 8
+
+#define IPW2100_WEP_ENABLE (1<<1)
+#define IPW2100_WEP_DROP_CLEAR (1<<2)
+
+#define IPW_NONE_CIPHER (1<<0)
+#define IPW_WEP40_CIPHER (1<<1)
+#define IPW_TKIP_CIPHER (1<<2)
+#define IPW_CCMP_CIPHER (1<<4)
+#define IPW_WEP104_CIPHER (1<<5)
+#define IPW_CKIP_CIPHER (1<<6)
+
+#define IPW_AUTH_OPEN 0
+#define IPW_AUTH_SHARED 1
+
+struct statistic {
+ int value;
+ int hi;
+ int lo;
+};
+
+#define INIT_STAT(x) do { \
+ (x)->value = (x)->hi = 0; \
+ (x)->lo = 0x7fffffff; \
+} while (0)
+#define SET_STAT(x,y) do { \
+ (x)->value = y; \
+ if ((x)->value > (x)->hi) (x)->hi = (x)->value; \
+ if ((x)->value < (x)->lo) (x)->lo = (x)->value; \
+} while (0)
+#define INC_STAT(x) do { if (++(x)->value > (x)->hi) (x)->hi = (x)->value; } \
+while (0)
+#define DEC_STAT(x) do { if (--(x)->value < (x)->lo) (x)->lo = (x)->value; } \
+while (0)
+
+#define IPW2100_ERROR_QUEUE 5
+
+/* Power management code: enable or disable? */
+enum {
+#ifdef CONFIG_PM
+ IPW2100_PM_DISABLED = 0,
+ PM_STATE_SIZE = 16,
+#else
+ IPW2100_PM_DISABLED = 1,
+ PM_STATE_SIZE = 0,
+#endif
+};
+
+#define STATUS_POWERED (1<<0)
+#define STATUS_CMD_ACTIVE (1<<1) /**< host command in progress */
+#define STATUS_RUNNING (1<<2) /* Card initialized, but not enabled */
+#define STATUS_ENABLED (1<<3) /* Card enabled -- can scan,Tx,Rx */
+#define STATUS_STOPPING (1<<4) /* Card is in shutdown phase */
+#define STATUS_INITIALIZED (1<<5) /* Card is ready for external calls */
+#define STATUS_ASSOCIATING (1<<9) /* Associated, but no BSSID yet */
+#define STATUS_ASSOCIATED (1<<10) /* Associated and BSSID valid */
+#define STATUS_INT_ENABLED (1<<11)
+#define STATUS_RF_KILL_HW (1<<12)
+#define STATUS_RF_KILL_SW (1<<13)
+#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW)
+#define STATUS_EXIT_PENDING (1<<14)
+
+#define STATUS_SCAN_PENDING (1<<23)
+#define STATUS_SCANNING (1<<24)
+#define STATUS_SCAN_ABORTING (1<<25)
+#define STATUS_SCAN_COMPLETE (1<<26)
+#define STATUS_WX_EVENT_PENDING (1<<27)
+#define STATUS_RESET_PENDING (1<<29)
+#define STATUS_SECURITY_UPDATED (1<<30) /* Security sync needed */
+
+
+
+/* Internal NIC states */
+#define IPW_STATE_INITIALIZED (1<<0)
+#define IPW_STATE_COUNTRY_FOUND (1<<1)
+#define IPW_STATE_ASSOCIATED (1<<2)
+#define IPW_STATE_ASSN_LOST (1<<3)
+#define IPW_STATE_ASSN_CHANGED (1<<4)
+#define IPW_STATE_SCAN_COMPLETE (1<<5)
+#define IPW_STATE_ENTERED_PSP (1<<6)
+#define IPW_STATE_LEFT_PSP (1<<7)
+#define IPW_STATE_RF_KILL (1<<8)
+#define IPW_STATE_DISABLED (1<<9)
+#define IPW_STATE_POWER_DOWN (1<<10)
+#define IPW_STATE_SCANNING (1<<11)
+
+
+
+#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */
+#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */
+#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */
+#define CFG_CUSTOM_MAC (1<<3)
+#define CFG_LONG_PREAMBLE (1<<4)
+#define CFG_ASSOCIATE (1<<6)
+#define CFG_FIXED_RATE (1<<7)
+#define CFG_ADHOC_CREATE (1<<8)
+#define CFG_C3_DISABLED (1<<9)
+#define CFG_PASSIVE_SCAN (1<<10)
+
+#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */
+#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */
+
+struct ipw2100_priv {
+
+ int stop_hang_check; /* Set 1 when shutting down to kill hang_check */
+ int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */
+
+ struct ieee80211_device *ieee;
+ unsigned long status;
+ unsigned long config;
+ unsigned long capability;
+
+ /* Statistics */
+ int resets;
+ int reset_backoff;
+
+ /* Context */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u8 bssid[ETH_ALEN];
+ u8 channel;
+ int last_mode;
+ int cstate_limit;
+
+ unsigned long connect_start;
+ unsigned long last_reset;
+
+ u32 channel_mask;
+ u32 fatal_error;
+ u32 fatal_errors[IPW2100_ERROR_QUEUE];
+ u32 fatal_index;
+ int eeprom_version;
+ int firmware_version;
+ unsigned long hw_features;
+ int hangs;
+ u32 last_rtc;
+ int dump_raw; /* 1 to dump raw bytes in /sys/.../memory */
+ u8* snapshot[0x30];
+
+ u8 mandatory_bssid_mac[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
+
+ int power_mode;
+
+ /* WEP data */
+ struct ieee80211_security sec;
+ int messages_sent;
+
+
+ int short_retry_limit;
+ int long_retry_limit;
+
+ u32 rts_threshold;
+ u32 frag_threshold;
+
+ int in_isr;
+
+ u32 tx_rates;
+ int tx_power;
+ u32 beacon_interval;
+
+ char nick[IW_ESSID_MAX_SIZE + 1];
+
+ struct ipw2100_status_queue status_queue;
+
+ struct statistic txq_stat;
+ struct statistic rxq_stat;
+ struct ipw2100_bd_queue rx_queue;
+ struct ipw2100_bd_queue tx_queue;
+ struct ipw2100_rx_packet *rx_buffers;
+
+ struct statistic fw_pend_stat;
+ struct list_head fw_pend_list;
+
+ struct statistic msg_free_stat;
+ struct statistic msg_pend_stat;
+ struct list_head msg_free_list;
+ struct list_head msg_pend_list;
+ struct ipw2100_tx_packet *msg_buffers;
+
+ struct statistic tx_free_stat;
+ struct statistic tx_pend_stat;
+ struct list_head tx_free_list;
+ struct list_head tx_pend_list;
+ struct ipw2100_tx_packet *tx_buffers;
+
+ struct ipw2100_ordinals ordinals;
+
+ struct pci_dev *pci_dev;
+
+ struct proc_dir_entry *dir_dev;
+
+ struct net_device *net_dev;
+ struct iw_statistics wstats;
+
+ struct tasklet_struct irq_tasklet;
+
+ struct workqueue_struct *workqueue;
+ struct work_struct reset_work;
+ struct work_struct security_work;
+ struct work_struct wx_event_work;
+ struct work_struct hang_check;
+ struct work_struct rf_kill;
+
+ u32 interrupts;
+ int tx_interrupts;
+ int rx_interrupts;
+ int inta_other;
+
+ spinlock_t low_lock;
+ struct semaphore action_sem;
+ struct semaphore adapter_sem;
+
+ wait_queue_head_t wait_command_queue;
+};
+
+
+/*********************************************************
+ * Host Command -> From Driver to FW
+ *********************************************************/
+
+/**
+ * Host command identifiers
+ */
+#define HOST_COMPLETE 2
+#define SYSTEM_CONFIG 6
+#define SSID 8
+#define MANDATORY_BSSID 9
+#define AUTHENTICATION_TYPE 10
+#define ADAPTER_ADDRESS 11
+#define PORT_TYPE 12
+#define INTERNATIONAL_MODE 13
+#define CHANNEL 14
+#define RTS_THRESHOLD 15
+#define FRAG_THRESHOLD 16
+#define POWER_MODE 17
+#define TX_RATES 18
+#define BASIC_TX_RATES 19
+#define WEP_KEY_INFO 20
+#define WEP_KEY_INDEX 25
+#define WEP_FLAGS 26
+#define ADD_MULTICAST 27
+#define CLEAR_ALL_MULTICAST 28
+#define BEACON_INTERVAL 29
+#define ATIM_WINDOW 30
+#define CLEAR_STATISTICS 31
+#define SEND 33
+#define TX_POWER_INDEX 36
+#define BROADCAST_SCAN 43
+#define CARD_DISABLE 44
+#define PREFERRED_BSSID 45
+#define SET_SCAN_OPTIONS 46
+#define SCAN_DWELL_TIME 47
+#define SWEEP_TABLE 48
+#define AP_OR_STATION_TABLE 49
+#define GROUP_ORDINALS 50
+#define SHORT_RETRY_LIMIT 51
+#define LONG_RETRY_LIMIT 52
+
+#define HOST_PRE_POWER_DOWN 58
+#define CARD_DISABLE_PHY_OFF 61
+#define MSDU_TX_RATES 62
+
+
+/* Rogue AP Detection */
+#define SET_STATION_STAT_BITS 64
+#define CLEAR_STATIONS_STAT_BITS 65
+#define LEAP_ROGUE_MODE 66 //TODO tbw replaced by CFG_LEAP_ROGUE_AP
+#define SET_SECURITY_INFORMATION 67
+#define DISASSOCIATION_BSSID 68
+#define SET_WPA_IE 69
+
+
+
+/* system configuration bit mask: */
+#define IPW_CFG_MONITOR 0x00004
+#define IPW_CFG_PREAMBLE_AUTO 0x00010
+#define IPW_CFG_IBSS_AUTO_START 0x00020
+#define IPW_CFG_LOOPBACK 0x00100
+#define IPW_CFG_ANSWER_BCSSID_PROBE 0x00800
+#define IPW_CFG_BT_SIDEBAND_SIGNAL 0x02000
+#define IPW_CFG_802_1x_ENABLE 0x04000
+#define IPW_CFG_BSS_MASK 0x08000
+#define IPW_CFG_IBSS_MASK 0x10000
+
+#define IPW_SCAN_NOASSOCIATE (1<<0)
+#define IPW_SCAN_MIXED_CELL (1<<1)
+/* RESERVED (1<<2) */
+#define IPW_SCAN_PASSIVE (1<<3)
+
+#define IPW_NIC_FATAL_ERROR 0x2A7F0
+#define IPW_ERROR_ADDR(x) (x & 0x3FFFF)
+#define IPW_ERROR_CODE(x) ((x & 0xFF000000) >> 24)
+#define IPW2100_ERR_C3_CORRUPTION (0x10 << 24)
+#define IPW2100_ERR_MSG_TIMEOUT (0x11 << 24)
+#define IPW2100_ERR_FW_LOAD (0x12 << 24)
+
+#define IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND 0x200
+#define IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x0D80
+
+#define IPW_MEM_HOST_SHARED_RX_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x40)
+#define IPW_MEM_HOST_SHARED_RX_STATUS_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x44)
+#define IPW_MEM_HOST_SHARED_RX_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x48)
+#define IPW_MEM_HOST_SHARED_RX_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0xa0)
+
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x00)
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x04)
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x80)
+
+#define IPW_MEM_HOST_SHARED_RX_WRITE_INDEX \
+ (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND + 0x20)
+
+#define IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX \
+ (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND)
+
+#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x180)
+#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x184)
+
+#define IPW2100_INTA_TX_TRANSFER (0x00000001) // Bit 0 (LSB)
+#define IPW2100_INTA_RX_TRANSFER (0x00000002) // Bit 1
+#define IPW2100_INTA_TX_COMPLETE (0x00000004) // Bit 2
+#define IPW2100_INTA_EVENT_INTERRUPT (0x00000008) // Bit 3
+#define IPW2100_INTA_STATUS_CHANGE (0x00000010) // Bit 4
+#define IPW2100_INTA_BEACON_PERIOD_EXPIRED (0x00000020) // Bit 5
+#define IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE (0x00010000) // Bit 16
+#define IPW2100_INTA_FW_INIT_DONE (0x01000000) // Bit 24
+#define IPW2100_INTA_FW_CALIBRATION_CALC (0x02000000) // Bit 25
+#define IPW2100_INTA_FATAL_ERROR (0x40000000) // Bit 30
+#define IPW2100_INTA_PARITY_ERROR (0x80000000) // Bit 31 (MSB)
+
+#define IPW_AUX_HOST_RESET_REG_PRINCETON_RESET (0x00000001)
+#define IPW_AUX_HOST_RESET_REG_FORCE_NMI (0x00000002)
+#define IPW_AUX_HOST_RESET_REG_PCI_HOST_CLUSTER_FATAL_NMI (0x00000004)
+#define IPW_AUX_HOST_RESET_REG_CORE_FATAL_NMI (0x00000008)
+#define IPW_AUX_HOST_RESET_REG_SW_RESET (0x00000080)
+#define IPW_AUX_HOST_RESET_REG_MASTER_DISABLED (0x00000100)
+#define IPW_AUX_HOST_RESET_REG_STOP_MASTER (0x00000200)
+
+#define IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY (0x00000001) // Bit 0 (LSB)
+#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY (0x00000002) // Bit 1
+#define IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE (0x00000004) // Bit 2
+#define IPW_AUX_HOST_GP_CNTRL_BITS_SYS_CONFIG (0x000007c0) // Bits 6-10
+#define IPW_AUX_HOST_GP_CNTRL_BIT_BUS_TYPE (0x00000200) // Bit 9
+#define IPW_AUX_HOST_GP_CNTRL_BIT_BAR0_BLOCK_SIZE (0x00000400) // Bit 10
+#define IPW_AUX_HOST_GP_CNTRL_BIT_USB_MODE (0x20000000) // Bit 29
+#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_FORCES_SYS_CLK (0x40000000) // Bit 30
+#define IPW_AUX_HOST_GP_CNTRL_BIT_FW_FORCES_SYS_CLK (0x80000000) // Bit 31 (MSB)
+
+#define IPW_BIT_GPIO_GPIO1_MASK 0x0000000C
+#define IPW_BIT_GPIO_GPIO3_MASK 0x000000C0
+#define IPW_BIT_GPIO_GPIO1_ENABLE 0x00000008
+#define IPW_BIT_GPIO_RF_KILL 0x00010000
+
+#define IPW_BIT_GPIO_LED_OFF 0x00002000 // Bit 13 = 1
+
+#define IPW_REG_DOMAIN_0_OFFSET 0x0000
+#define IPW_REG_DOMAIN_1_OFFSET IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND
+
+#define IPW_REG_INTA IPW_REG_DOMAIN_0_OFFSET + 0x0008
+#define IPW_REG_INTA_MASK IPW_REG_DOMAIN_0_OFFSET + 0x000C
+#define IPW_REG_INDIRECT_ACCESS_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0010
+#define IPW_REG_INDIRECT_ACCESS_DATA IPW_REG_DOMAIN_0_OFFSET + 0x0014
+#define IPW_REG_AUTOINCREMENT_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0018
+#define IPW_REG_AUTOINCREMENT_DATA IPW_REG_DOMAIN_0_OFFSET + 0x001C
+#define IPW_REG_RESET_REG IPW_REG_DOMAIN_0_OFFSET + 0x0020
+#define IPW_REG_GP_CNTRL IPW_REG_DOMAIN_0_OFFSET + 0x0024
+#define IPW_REG_GPIO IPW_REG_DOMAIN_0_OFFSET + 0x0030
+#define IPW_REG_FW_TYPE IPW_REG_DOMAIN_1_OFFSET + 0x0188
+#define IPW_REG_FW_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x018C
+#define IPW_REG_FW_COMPATABILITY_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x0190
+
+#define IPW_REG_INDIRECT_ADDR_MASK 0x00FFFFFC
+
+#define IPW_INTERRUPT_MASK 0xC1010013
+
+#define IPW2100_CONTROL_REG 0x220000
+#define IPW2100_CONTROL_PHY_OFF 0x8
+
+#define IPW2100_COMMAND 0x00300004
+#define IPW2100_COMMAND_PHY_ON 0x0
+#define IPW2100_COMMAND_PHY_OFF 0x1
+
+/* in DEBUG_AREA, values of memory always 0xd55555d5 */
+#define IPW_REG_DOA_DEBUG_AREA_START IPW_REG_DOMAIN_0_OFFSET + 0x0090
+#define IPW_REG_DOA_DEBUG_AREA_END IPW_REG_DOMAIN_0_OFFSET + 0x00FF
+#define IPW_DATA_DOA_DEBUG_VALUE 0xd55555d5
+
+#define IPW_INTERNAL_REGISTER_HALT_AND_RESET 0x003000e0
+
+#define IPW_WAIT_CLOCK_STABILIZATION_DELAY 50 // micro seconds
+#define IPW_WAIT_RESET_ARC_COMPLETE_DELAY 10 // micro seconds
+#define IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY 10 // micro seconds
+
+// BD ring queue read/write difference
+#define IPW_BD_QUEUE_W_R_MIN_SPARE 2
+
+#define IPW_CACHE_LINE_LENGTH_DEFAULT 0x80
+
+#define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli
+#define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli
+
+
+
+
+#define IPW_HEADER_802_11_SIZE sizeof(struct ieee80211_hdr_3addr)
+#define IPW_MAX_80211_PAYLOAD_SIZE 2304U
+#define IPW_MAX_802_11_PAYLOAD_LENGTH 2312
+#define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536
+#define IPW_MIN_ACCEPTABLE_RX_FRAME_LENGTH 60
+#define IPW_MAX_ACCEPTABLE_RX_FRAME_LENGTH \
+ (IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH + IPW_HEADER_802_11_SIZE - \
+ sizeof(struct ethhdr))
+
+#define IPW_802_11_FCS_LENGTH 4
+#define IPW_RX_NIC_BUFFER_LENGTH \
+ (IPW_MAX_802_11_PAYLOAD_LENGTH + IPW_HEADER_802_11_SIZE + \
+ IPW_802_11_FCS_LENGTH)
+
+#define IPW_802_11_PAYLOAD_OFFSET \
+ (sizeof(struct ieee80211_hdr_3addr) + \
+ sizeof(struct ieee80211_snap_hdr))
+
+struct ipw2100_rx {
+ union {
+ unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
+ struct ieee80211_hdr_4addr header;
+ u32 status;
+ struct ipw2100_notification notification;
+ struct ipw2100_cmd_header command;
+ } rx_data;
+} __attribute__ ((packed));
+
+/* Bit 0-7 are for 802.11b tx rates - . Bit 5-7 are reserved */
+#define TX_RATE_1_MBIT 0x0001
+#define TX_RATE_2_MBIT 0x0002
+#define TX_RATE_5_5_MBIT 0x0004
+#define TX_RATE_11_MBIT 0x0008
+#define TX_RATE_MASK 0x000F
+#define DEFAULT_TX_RATES 0x000F
+
+#define IPW_POWER_MODE_CAM 0x00 //(always on)
+#define IPW_POWER_INDEX_1 0x01
+#define IPW_POWER_INDEX_2 0x02
+#define IPW_POWER_INDEX_3 0x03
+#define IPW_POWER_INDEX_4 0x04
+#define IPW_POWER_INDEX_5 0x05
+#define IPW_POWER_AUTO 0x06
+#define IPW_POWER_MASK 0x0F
+#define IPW_POWER_ENABLED 0x10
+#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK)
+
+#define IPW_TX_POWER_AUTO 0
+#define IPW_TX_POWER_ENHANCED 1
+
+#define IPW_TX_POWER_DEFAULT 32
+#define IPW_TX_POWER_MIN 0
+#define IPW_TX_POWER_MAX 16
+#define IPW_TX_POWER_MIN_DBM (-12)
+#define IPW_TX_POWER_MAX_DBM 16
+
+#define FW_SCAN_DONOT_ASSOCIATE 0x0001 // Dont Attempt to Associate after Scan
+#define FW_SCAN_PASSIVE 0x0008 // Force PASSSIVE Scan
+
+#define REG_MIN_CHANNEL 0
+#define REG_MAX_CHANNEL 14
+
+#define REG_CHANNEL_MASK 0x00003FFF
+#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff
+
+#define DIVERSITY_EITHER 0 // Use both antennas
+#define DIVERSITY_ANTENNA_A 1 // Use antenna A
+#define DIVERSITY_ANTENNA_B 2 // Use antenna B
+
+
+#define HOST_COMMAND_WAIT 0
+#define HOST_COMMAND_NO_WAIT 1
+
+#define LOCK_NONE 0
+#define LOCK_DRIVER 1
+#define LOCK_FW 2
+
+#define TYPE_SWEEP_ORD 0x000D
+#define TYPE_IBSS_STTN_ORD 0x000E
+#define TYPE_BSS_AP_ORD 0x000F
+#define TYPE_RAW_BEACON_ENTRY 0x0010
+#define TYPE_CALIBRATION_DATA 0x0011
+#define TYPE_ROGUE_AP_DATA 0x0012
+#define TYPE_ASSOCIATION_REQUEST 0x0013
+#define TYPE_REASSOCIATION_REQUEST 0x0014
+
+
+#define HW_FEATURE_RFKILL (0x0001)
+#define RF_KILLSWITCH_OFF (1)
+#define RF_KILLSWITCH_ON (0)
+
+#define IPW_COMMAND_POOL_SIZE 40
+
+#define IPW_START_ORD_TAB_1 1
+#define IPW_START_ORD_TAB_2 1000
+
+#define IPW_ORD_TAB_1_ENTRY_SIZE sizeof(u32)
+
+#define IS_ORDINAL_TABLE_ONE(mgr,id) \
+ ((id >= IPW_START_ORD_TAB_1) && (id < mgr->table1_size))
+#define IS_ORDINAL_TABLE_TWO(mgr,id) \
+ ((id >= IPW_START_ORD_TAB_2) && (id < (mgr->table2_size + IPW_START_ORD_TAB_2)))
+
+#define BSS_ID_LENGTH 6
+
+// Fixed size data: Ordinal Table 1
+typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW
+// Transmit statistics
+ IPW_ORD_STAT_TX_HOST_REQUESTS = 1,// # of requested Host Tx's (MSDU)
+ IPW_ORD_STAT_TX_HOST_COMPLETE, // # of successful Host Tx's (MSDU)
+ IPW_ORD_STAT_TX_DIR_DATA, // # of successful Directed Tx's (MSDU)
+
+ IPW_ORD_STAT_TX_DIR_DATA1 = 4, // # of successful Directed Tx's (MSDU) @ 1MB
+ IPW_ORD_STAT_TX_DIR_DATA2, // # of successful Directed Tx's (MSDU) @ 2MB
+ IPW_ORD_STAT_TX_DIR_DATA5_5, // # of successful Directed Tx's (MSDU) @ 5_5MB
+ IPW_ORD_STAT_TX_DIR_DATA11, // # of successful Directed Tx's (MSDU) @ 11MB
+ IPW_ORD_STAT_TX_DIR_DATA22, // # of successful Directed Tx's (MSDU) @ 22MB
+
+ IPW_ORD_STAT_TX_NODIR_DATA1 = 13,// # of successful Non_Directed Tx's (MSDU) @ 1MB
+ IPW_ORD_STAT_TX_NODIR_DATA2, // # of successful Non_Directed Tx's (MSDU) @ 2MB
+ IPW_ORD_STAT_TX_NODIR_DATA5_5, // # of successful Non_Directed Tx's (MSDU) @ 5.5MB
+ IPW_ORD_STAT_TX_NODIR_DATA11, // # of successful Non_Directed Tx's (MSDU) @ 11MB
+
+ IPW_ORD_STAT_NULL_DATA = 21, // # of successful NULL data Tx's
+ IPW_ORD_STAT_TX_RTS, // # of successful Tx RTS
+ IPW_ORD_STAT_TX_CTS, // # of successful Tx CTS
+ IPW_ORD_STAT_TX_ACK, // # of successful Tx ACK
+ IPW_ORD_STAT_TX_ASSN, // # of successful Association Tx's
+ IPW_ORD_STAT_TX_ASSN_RESP, // # of successful Association response Tx's
+ IPW_ORD_STAT_TX_REASSN, // # of successful Reassociation Tx's
+ IPW_ORD_STAT_TX_REASSN_RESP, // # of successful Reassociation response Tx's
+ IPW_ORD_STAT_TX_PROBE, // # of probes successfully transmitted
+ IPW_ORD_STAT_TX_PROBE_RESP, // # of probe responses successfully transmitted
+ IPW_ORD_STAT_TX_BEACON, // # of tx beacon
+ IPW_ORD_STAT_TX_ATIM, // # of Tx ATIM
+ IPW_ORD_STAT_TX_DISASSN, // # of successful Disassociation TX
+ IPW_ORD_STAT_TX_AUTH, // # of successful Authentication Tx
+ IPW_ORD_STAT_TX_DEAUTH, // # of successful Deauthentication TX
+
+ IPW_ORD_STAT_TX_TOTAL_BYTES = 41,// Total successful Tx data bytes
+ IPW_ORD_STAT_TX_RETRIES, // # of Tx retries
+ IPW_ORD_STAT_TX_RETRY1, // # of Tx retries at 1MBPS
+ IPW_ORD_STAT_TX_RETRY2, // # of Tx retries at 2MBPS
+ IPW_ORD_STAT_TX_RETRY5_5, // # of Tx retries at 5.5MBPS
+ IPW_ORD_STAT_TX_RETRY11, // # of Tx retries at 11MBPS
+
+ IPW_ORD_STAT_TX_FAILURES = 51, // # of Tx Failures
+ IPW_ORD_STAT_TX_ABORT_AT_HOP, //NS // # of Tx's aborted at hop time
+ IPW_ORD_STAT_TX_MAX_TRIES_IN_HOP,// # of times max tries in a hop failed
+ IPW_ORD_STAT_TX_ABORT_LATE_DMA, //NS // # of times tx aborted due to late dma setup
+ IPW_ORD_STAT_TX_ABORT_STX, //NS // # of times backoff aborted
+ IPW_ORD_STAT_TX_DISASSN_FAIL, // # of times disassociation failed
+ IPW_ORD_STAT_TX_ERR_CTS, // # of missed/bad CTS frames
+ IPW_ORD_STAT_TX_BPDU, //NS // # of spanning tree BPDUs sent
+ IPW_ORD_STAT_TX_ERR_ACK, // # of tx err due to acks
+
+ // Receive statistics
+ IPW_ORD_STAT_RX_HOST = 61, // # of packets passed to host
+ IPW_ORD_STAT_RX_DIR_DATA, // # of directed packets
+ IPW_ORD_STAT_RX_DIR_DATA1, // # of directed packets at 1MB
+ IPW_ORD_STAT_RX_DIR_DATA2, // # of directed packets at 2MB
+ IPW_ORD_STAT_RX_DIR_DATA5_5, // # of directed packets at 5.5MB
+ IPW_ORD_STAT_RX_DIR_DATA11, // # of directed packets at 11MB
+ IPW_ORD_STAT_RX_DIR_DATA22, // # of directed packets at 22MB
+
+ IPW_ORD_STAT_RX_NODIR_DATA = 71,// # of nondirected packets
+ IPW_ORD_STAT_RX_NODIR_DATA1, // # of nondirected packets at 1MB
+ IPW_ORD_STAT_RX_NODIR_DATA2, // # of nondirected packets at 2MB
+ IPW_ORD_STAT_RX_NODIR_DATA5_5, // # of nondirected packets at 5.5MB
+ IPW_ORD_STAT_RX_NODIR_DATA11, // # of nondirected packets at 11MB
+
+ IPW_ORD_STAT_RX_NULL_DATA = 80, // # of null data rx's
+ IPW_ORD_STAT_RX_POLL, //NS // # of poll rx
+ IPW_ORD_STAT_RX_RTS, // # of Rx RTS
+ IPW_ORD_STAT_RX_CTS, // # of Rx CTS
+ IPW_ORD_STAT_RX_ACK, // # of Rx ACK
+ IPW_ORD_STAT_RX_CFEND, // # of Rx CF End
+ IPW_ORD_STAT_RX_CFEND_ACK, // # of Rx CF End + CF Ack
+ IPW_ORD_STAT_RX_ASSN, // # of Association Rx's
+ IPW_ORD_STAT_RX_ASSN_RESP, // # of Association response Rx's
+ IPW_ORD_STAT_RX_REASSN, // # of Reassociation Rx's
+ IPW_ORD_STAT_RX_REASSN_RESP, // # of Reassociation response Rx's
+ IPW_ORD_STAT_RX_PROBE, // # of probe Rx's
+ IPW_ORD_STAT_RX_PROBE_RESP, // # of probe response Rx's
+ IPW_ORD_STAT_RX_BEACON, // # of Rx beacon
+ IPW_ORD_STAT_RX_ATIM, // # of Rx ATIM
+ IPW_ORD_STAT_RX_DISASSN, // # of disassociation Rx
+ IPW_ORD_STAT_RX_AUTH, // # of authentication Rx
+ IPW_ORD_STAT_RX_DEAUTH, // # of deauthentication Rx
+
+ IPW_ORD_STAT_RX_TOTAL_BYTES = 101,// Total rx data bytes received
+ IPW_ORD_STAT_RX_ERR_CRC, // # of packets with Rx CRC error
+ IPW_ORD_STAT_RX_ERR_CRC1, // # of Rx CRC errors at 1MB
+ IPW_ORD_STAT_RX_ERR_CRC2, // # of Rx CRC errors at 2MB
+ IPW_ORD_STAT_RX_ERR_CRC5_5, // # of Rx CRC errors at 5.5MB
+ IPW_ORD_STAT_RX_ERR_CRC11, // # of Rx CRC errors at 11MB
+
+ IPW_ORD_STAT_RX_DUPLICATE1 = 112, // # of duplicate rx packets at 1MB
+ IPW_ORD_STAT_RX_DUPLICATE2, // # of duplicate rx packets at 2MB
+ IPW_ORD_STAT_RX_DUPLICATE5_5, // # of duplicate rx packets at 5.5MB
+ IPW_ORD_STAT_RX_DUPLICATE11, // # of duplicate rx packets at 11MB
+ IPW_ORD_STAT_RX_DUPLICATE = 119, // # of duplicate rx packets
+
+ IPW_ORD_PERS_DB_LOCK = 120, // # locking fw permanent db
+ IPW_ORD_PERS_DB_SIZE, // # size of fw permanent db
+ IPW_ORD_PERS_DB_ADDR, // # address of fw permanent db
+ IPW_ORD_STAT_RX_INVALID_PROTOCOL, // # of rx frames with invalid protocol
+ IPW_ORD_SYS_BOOT_TIME, // # Boot time
+ IPW_ORD_STAT_RX_NO_BUFFER, // # of rx frames rejected due to no buffer
+ IPW_ORD_STAT_RX_ABORT_LATE_DMA, //NS // # of rx frames rejected due to dma setup too late
+ IPW_ORD_STAT_RX_ABORT_AT_HOP, //NS // # of rx frames aborted due to hop
+ IPW_ORD_STAT_RX_MISSING_FRAG, // # of rx frames dropped due to missing fragment
+ IPW_ORD_STAT_RX_ORPHAN_FRAG, // # of rx frames dropped due to non-sequential fragment
+ IPW_ORD_STAT_RX_ORPHAN_FRAME, // # of rx frames dropped due to unmatched 1st frame
+ IPW_ORD_STAT_RX_FRAG_AGEOUT, // # of rx frames dropped due to uncompleted frame
+ IPW_ORD_STAT_RX_BAD_SSID, //NS // Bad SSID (unused)
+ IPW_ORD_STAT_RX_ICV_ERRORS, // # of ICV errors during decryption
+
+// PSP Statistics
+ IPW_ORD_STAT_PSP_SUSPENSION = 137,// # of times adapter suspended
+ IPW_ORD_STAT_PSP_BCN_TIMEOUT, // # of beacon timeout
+ IPW_ORD_STAT_PSP_POLL_TIMEOUT, // # of poll response timeouts
+ IPW_ORD_STAT_PSP_NONDIR_TIMEOUT,// # of timeouts waiting for last broadcast/muticast pkt
+ IPW_ORD_STAT_PSP_RX_DTIMS, // # of PSP DTIMs received
+ IPW_ORD_STAT_PSP_RX_TIMS, // # of PSP TIMs received
+ IPW_ORD_STAT_PSP_STATION_ID, // PSP Station ID
+
+// Association and roaming
+ IPW_ORD_LAST_ASSN_TIME = 147, // RTC time of last association
+ IPW_ORD_STAT_PERCENT_MISSED_BCNS,// current calculation of % missed beacons
+ IPW_ORD_STAT_PERCENT_RETRIES, // current calculation of % missed tx retries
+ IPW_ORD_ASSOCIATED_AP_PTR, // If associated, this is ptr to the associated
+ // AP table entry. set to 0 if not associated
+ IPW_ORD_AVAILABLE_AP_CNT, // # of AP's decsribed in the AP table
+ IPW_ORD_AP_LIST_PTR, // Ptr to list of available APs
+ IPW_ORD_STAT_AP_ASSNS, // # of associations
+ IPW_ORD_STAT_ASSN_FAIL, // # of association failures
+ IPW_ORD_STAT_ASSN_RESP_FAIL, // # of failuresdue to response fail
+ IPW_ORD_STAT_FULL_SCANS, // # of full scans
+
+ IPW_ORD_CARD_DISABLED, // # Card Disabled
+ IPW_ORD_STAT_ROAM_INHIBIT, // # of times roaming was inhibited due to ongoing activity
+ IPW_FILLER_40,
+ IPW_ORD_RSSI_AT_ASSN = 160, // RSSI of associated AP at time of association
+ IPW_ORD_STAT_ASSN_CAUSE1, // # of reassociations due to no tx from AP in last N
+ // hops or no prob_ responses in last 3 minutes
+ IPW_ORD_STAT_ASSN_CAUSE2, // # of reassociations due to poor tx/rx quality
+ IPW_ORD_STAT_ASSN_CAUSE3, // # of reassociations due to tx/rx quality with excessive
+ // load at the AP
+ IPW_ORD_STAT_ASSN_CAUSE4, // # of reassociations due to AP RSSI level fell below
+ // eligible group
+ IPW_ORD_STAT_ASSN_CAUSE5, // # of reassociations due to load leveling
+ IPW_ORD_STAT_ASSN_CAUSE6, //NS // # of reassociations due to dropped by Ap
+ IPW_FILLER_41,
+ IPW_FILLER_42,
+ IPW_FILLER_43,
+ IPW_ORD_STAT_AUTH_FAIL, // # of times authentication failed
+ IPW_ORD_STAT_AUTH_RESP_FAIL, // # of times authentication response failed
+ IPW_ORD_STATION_TABLE_CNT, // # of entries in association table
+
+// Other statistics
+ IPW_ORD_RSSI_AVG_CURR = 173, // Current avg RSSI
+ IPW_ORD_STEST_RESULTS_CURR, //NS // Current self test results word
+ IPW_ORD_STEST_RESULTS_CUM, //NS // Cummulative self test results word
+ IPW_ORD_SELF_TEST_STATUS, //NS //
+ IPW_ORD_POWER_MGMT_MODE, // Power mode - 0=CAM, 1=PSP
+ IPW_ORD_POWER_MGMT_INDEX, //NS //
+ IPW_ORD_COUNTRY_CODE, // IEEE country code as recv'd from beacon
+ IPW_ORD_COUNTRY_CHANNELS, // channels suported by country
+// IPW_ORD_COUNTRY_CHANNELS:
+// For 11b the lower 2-byte are used for channels from 1-14
+// and the higher 2-byte are not used.
+ IPW_ORD_RESET_CNT, // # of adapter resets (warm)
+ IPW_ORD_BEACON_INTERVAL, // Beacon interval
+
+ IPW_ORD_PRINCETON_VERSION = 184, //NS // Princeton Version
+ IPW_ORD_ANTENNA_DIVERSITY, // TRUE if antenna diversity is disabled
+ IPW_ORD_CCA_RSSI, //NS // CCA RSSI value (factory programmed)
+ IPW_ORD_STAT_EEPROM_UPDATE, //NS // # of times config EEPROM updated
+ IPW_ORD_DTIM_PERIOD, // # of beacon intervals between DTIMs
+ IPW_ORD_OUR_FREQ, // current radio freq lower digits - channel ID
+
+ IPW_ORD_RTC_TIME = 190, // current RTC time
+ IPW_ORD_PORT_TYPE, // operating mode
+ IPW_ORD_CURRENT_TX_RATE, // current tx rate
+ IPW_ORD_SUPPORTED_RATES, // Bitmap of supported tx rates
+ IPW_ORD_ATIM_WINDOW, // current ATIM Window
+ IPW_ORD_BASIC_RATES, // bitmap of basic tx rates
+ IPW_ORD_NIC_HIGHEST_RATE, // bitmap of basic tx rates
+ IPW_ORD_AP_HIGHEST_RATE, // bitmap of basic tx rates
+ IPW_ORD_CAPABILITIES, // Management frame capability field
+ IPW_ORD_AUTH_TYPE, // Type of authentication
+ IPW_ORD_RADIO_TYPE, // Adapter card platform type
+ IPW_ORD_RTS_THRESHOLD = 201, // Min length of packet after which RTS handshaking is used
+ IPW_ORD_INT_MODE, // International mode
+ IPW_ORD_FRAGMENTATION_THRESHOLD, // protocol frag threshold
+ IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, // EEPROM offset in SRAM
+ IPW_ORD_EEPROM_SRAM_DB_BLOCK_SIZE, // EEPROM size in SRAM
+ IPW_ORD_EEPROM_SKU_CAPABILITY, // EEPROM SKU Capability 206 =
+ IPW_ORD_EEPROM_IBSS_11B_CHANNELS, // EEPROM IBSS 11b channel set
+
+ IPW_ORD_MAC_VERSION = 209, // MAC Version
+ IPW_ORD_MAC_REVISION, // MAC Revision
+ IPW_ORD_RADIO_VERSION, // Radio Version
+ IPW_ORD_NIC_MANF_DATE_TIME, // MANF Date/Time STAMP
+ IPW_ORD_UCODE_VERSION, // Ucode Version
+ IPW_ORD_HW_RF_SWITCH_STATE = 214, // HW RF Kill Switch State
+} ORDINALTABLE1;
+
+// ordinal table 2
+// Variable length data:
+#define IPW_FIRST_VARIABLE_LENGTH_ORDINAL 1001
+
+typedef enum _ORDINAL_TABLE_2 { // NS - means Not Supported by FW
+ IPW_ORD_STAT_BASE = 1000, // contains number of variable ORDs
+ IPW_ORD_STAT_ADAPTER_MAC = 1001, // 6 bytes: our adapter MAC address
+ IPW_ORD_STAT_PREFERRED_BSSID = 1002, // 6 bytes: BSSID of the preferred AP
+ IPW_ORD_STAT_MANDATORY_BSSID = 1003, // 6 bytes: BSSID of the mandatory AP
+ IPW_FILL_1, //NS //
+ IPW_ORD_STAT_COUNTRY_TEXT = 1005, // 36 bytes: Country name text, First two bytes are Country code
+ IPW_ORD_STAT_ASSN_SSID = 1006, // 32 bytes: ESSID String
+ IPW_ORD_STATION_TABLE = 1007, // ? bytes: Station/AP table (via Direct SSID Scans)
+ IPW_ORD_STAT_SWEEP_TABLE = 1008, // ? bytes: Sweep/Host Table table (via Broadcast Scans)
+ IPW_ORD_STAT_ROAM_LOG = 1009, // ? bytes: Roaming log
+ IPW_ORD_STAT_RATE_LOG = 1010, //NS // 0 bytes: Rate log
+ IPW_ORD_STAT_FIFO = 1011, //NS // 0 bytes: Fifo buffer data structures
+ IPW_ORD_STAT_FW_VER_NUM = 1012, // 14 bytes: fw version ID string as in (a.bb.ccc; "0.08.011")
+ IPW_ORD_STAT_FW_DATE = 1013, // 14 bytes: fw date string (mmm dd yyyy; "Mar 13 2002")
+ IPW_ORD_STAT_ASSN_AP_BSSID = 1014, // 6 bytes: MAC address of associated AP
+ IPW_ORD_STAT_DEBUG = 1015, //NS // ? bytes:
+ IPW_ORD_STAT_NIC_BPA_NUM = 1016, // 11 bytes: NIC BPA number in ASCII
+ IPW_ORD_STAT_UCODE_DATE = 1017, // 5 bytes: uCode date
+ IPW_ORD_SECURITY_NGOTIATION_RESULT = 1018,
+} ORDINALTABLE2; // NS - means Not Supported by FW
+
+#define IPW_LAST_VARIABLE_LENGTH_ORDINAL 1018
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY // enable iwspy support
+#endif
+
+#define IPW_HOST_FW_SHARED_AREA0 0x0002f200
+#define IPW_HOST_FW_SHARED_AREA0_END 0x0002f510 // 0x310 bytes
+
+#define IPW_HOST_FW_SHARED_AREA1 0x0002f610
+#define IPW_HOST_FW_SHARED_AREA1_END 0x0002f630 // 0x20 bytes
+
+#define IPW_HOST_FW_SHARED_AREA2 0x0002fa00
+#define IPW_HOST_FW_SHARED_AREA2_END 0x0002fa20 // 0x20 bytes
+
+#define IPW_HOST_FW_SHARED_AREA3 0x0002fc00
+#define IPW_HOST_FW_SHARED_AREA3_END 0x0002fc10 // 0x10 bytes
+
+#define IPW_HOST_FW_INTERRUPT_AREA 0x0002ff80
+#define IPW_HOST_FW_INTERRUPT_AREA_END 0x00030000 // 0x80 bytes
+
+struct ipw2100_fw_chunk {
+ unsigned char *buf;
+ long len;
+ long pos;
+ struct list_head list;
+};
+
+struct ipw2100_fw_chunk_set {
+ const void *data;
+ unsigned long size;
+};
+
+struct ipw2100_fw {
+ int version;
+ struct ipw2100_fw_chunk_set fw;
+ struct ipw2100_fw_chunk_set uc;
+ const struct firmware *fw_entry;
+};
+
+#define MAX_FW_VERSION_LEN 14
+
+#endif /* _IPW2100_H */
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
new file mode 100644
index 000000000000..3db0c32afe82
--- /dev/null
+++ b/drivers/net/wireless/ipw2200.c
@@ -0,0 +1,7386 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ 802.11 status code portion of this file from ethereal-0.10.6:
+ Copyright 2000, Axis Communications AB
+ Ethereal - Network traffic analyzer
+ By Gerald Combs <gerald@ethereal.com>
+ Copyright 1998 Gerald Combs
+
+ 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, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#include "ipw2200.h"
+
+#define IPW2200_VERSION "1.0.0"
+#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
+#define DRV_VERSION IPW2200_VERSION
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static int channel = 0;
+static char *ifname;
+static int mode = 0;
+
+static u32 ipw_debug_level;
+static int associate = 1;
+static int auto_create = 1;
+static int disable = 0;
+static const char ipw_modes[] = {
+ 'a', 'b', 'g', '?'
+};
+
+static void ipw_rx(struct ipw_priv *priv);
+static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq, int qindex);
+static int ipw_queue_reset(struct ipw_priv *priv);
+
+static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
+ int len, int sync);
+
+static void ipw_tx_queue_free(struct ipw_priv *);
+
+static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *);
+static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *);
+static void ipw_rx_queue_replenish(void *);
+
+static int ipw_up(struct ipw_priv *);
+static void ipw_down(struct ipw_priv *);
+static int ipw_config(struct ipw_priv *);
+static int init_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *prates);
+
+static u8 band_b_active_channel[MAX_B_CHANNELS] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0
+};
+static u8 band_a_active_channel[MAX_A_CHANNELS] = {
+ 36, 40, 44, 48, 149, 153, 157, 161, 165, 52, 56, 60, 64, 0
+};
+
+static int is_valid_channel(int mode_mask, int channel)
+{
+ int i;
+
+ if (!channel)
+ return 0;
+
+ if (mode_mask & IEEE_A)
+ for (i = 0; i < MAX_A_CHANNELS; i++)
+ if (band_a_active_channel[i] == channel)
+ return IEEE_A;
+
+ if (mode_mask & (IEEE_B | IEEE_G))
+ for (i = 0; i < MAX_B_CHANNELS; i++)
+ if (band_b_active_channel[i] == channel)
+ return mode_mask & (IEEE_B | IEEE_G);
+
+ return 0;
+}
+
+static char *snprint_line(char *buf, size_t count,
+ const u8 * data, u32 len, u32 ofs)
+{
+ int out, i, j, l;
+ char c;
+
+ out = snprintf(buf, count, "%08X", ofs);
+
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++)
+ out += snprintf(buf + out, count - out, "%02X ",
+ data[(i * 8 + j)]);
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ out += snprintf(buf + out, count - out, " ");
+ for (l = 0, i = 0; i < 2; i++) {
+ out += snprintf(buf + out, count - out, " ");
+ for (j = 0; j < 8 && l < len; j++, l++) {
+ c = data[(i * 8 + j)];
+ if (!isascii(c) || !isprint(c))
+ c = '.';
+
+ out += snprintf(buf + out, count - out, "%c", c);
+ }
+
+ for (; j < 8; j++)
+ out += snprintf(buf + out, count - out, " ");
+ }
+
+ return buf;
+}
+
+static void printk_buf(int level, const u8 * data, u32 len)
+{
+ char line[81];
+ u32 ofs = 0;
+ if (!(ipw_debug_level & level))
+ return;
+
+ while (len) {
+ printk(KERN_DEBUG "%s\n",
+ snprint_line(line, sizeof(line), &data[ofs],
+ min(len, 16U), ofs));
+ ofs += 16;
+ len -= min(len, 16U);
+ }
+}
+
+static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg);
+#define ipw_read_reg32(a, b) _ipw_read_reg32(a, b)
+
+static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg);
+#define ipw_read_reg8(a, b) _ipw_read_reg8(a, b)
+
+static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value);
+static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect8(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg8(a, b, c);
+}
+
+static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value);
+static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect16(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg16(a, b, c);
+}
+
+static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value);
+static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
+{
+ IPW_DEBUG_IO("%s %d: write_indirect32(0x%08X, 0x%08X)\n", __FILE__,
+ __LINE__, (u32) (b), (u32) (c));
+ _ipw_write_reg32(a, b, c);
+}
+
+#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
+#define ipw_write8(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write8(ipw, ofs, val)
+
+#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
+#define ipw_write16(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write16(ipw, ofs, val)
+
+#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
+#define ipw_write32(ipw, ofs, val) \
+ IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
+ _ipw_write32(ipw, ofs, val)
+
+#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
+static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read8(ipw, ofs);
+}
+
+#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
+
+#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
+static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read16(ipw, ofs);
+}
+
+#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
+
+#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
+static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
+{
+ IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
+ return _ipw_read32(ipw, ofs);
+}
+
+#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
+
+static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
+#define ipw_read_indirect(a, b, c, d) \
+ IPW_DEBUG_IO("%s %d: read_inddirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
+ _ipw_read_indirect(a, b, c, d)
+
+static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
+ int num);
+#define ipw_write_indirect(a, b, c, d) \
+ IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
+ _ipw_write_indirect(a, b, c, d)
+
+/* indirect write s */
+static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
+{
+ IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg);
+ _ipw_write32(priv, CX2_INDIRECT_DATA, value);
+}
+
+static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value)
+{
+ IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ _ipw_write8(priv, CX2_INDIRECT_DATA, value);
+ IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n",
+ (unsigned long)(priv->hw_base + CX2_INDIRECT_DATA), value);
+}
+
+static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value)
+{
+ IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ _ipw_write16(priv, CX2_INDIRECT_DATA, value);
+}
+
+/* indirect read s */
+
+static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
+{
+ u32 word;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK);
+ IPW_DEBUG_IO(" reg = 0x%8X : \n", reg);
+ word = _ipw_read32(priv, CX2_INDIRECT_DATA);
+ return (word >> ((reg & 0x3) * 8)) & 0xff;
+}
+
+static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
+{
+ u32 value;
+
+ IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg);
+
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, reg);
+ value = _ipw_read32(priv, CX2_INDIRECT_DATA);
+ IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value);
+ return value;
+}
+
+/* iterative/auto-increment 32 bit reads and writes */
+static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
+ int num)
+{
+ u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK;
+ u32 dif_len = addr - aligned_addr;
+ u32 aligned_len;
+ u32 i;
+
+ IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);
+
+ /* Read the first nibble byte by byte */
+ if (unlikely(dif_len)) {
+ /* Start reading at aligned_addr + dif_len */
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ *buf = _ipw_read8(priv, CX2_INDIRECT_DATA + i);
+ num -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* Read DWs through autoinc register */
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr);
+ aligned_len = num & CX2_INDIRECT_ADDR_MASK;
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ *(u32 *) buf = ipw_read32(priv, CX2_AUTOINC_DATA);
+
+ /* Copy the last nibble */
+ dif_len = num - aligned_len;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ *buf = ipw_read8(priv, CX2_INDIRECT_DATA + i);
+}
+
+static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
+ int num)
+{
+ u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK;
+ u32 dif_len = addr - aligned_addr;
+ u32 aligned_len;
+ u32 i;
+
+ IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num);
+
+ /* Write the first nibble byte by byte */
+ if (unlikely(dif_len)) {
+ /* Start writing at aligned_addr + dif_len */
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = dif_len; i < 4; i++, buf++)
+ _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf);
+ num -= dif_len;
+ aligned_addr += 4;
+ }
+
+ /* Write DWs through autoinc register */
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr);
+ aligned_len = num & CX2_INDIRECT_ADDR_MASK;
+ for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4)
+ _ipw_write32(priv, CX2_AUTOINC_DATA, *(u32 *) buf);
+
+ /* Copy the last nibble */
+ dif_len = num - aligned_len;
+ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr);
+ for (i = 0; i < dif_len; i++, buf++)
+ _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf);
+}
+
+static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf,
+ int num)
+{
+ memcpy_toio((priv->hw_base + addr), buf, num);
+}
+
+static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask)
+{
+ ipw_write32(priv, reg, ipw_read32(priv, reg) | mask);
+}
+
+static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask)
+{
+ ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
+}
+
+static inline void ipw_enable_interrupts(struct ipw_priv *priv)
+{
+ if (priv->status & STATUS_INT_ENABLED)
+ return;
+ priv->status |= STATUS_INT_ENABLED;
+ ipw_write32(priv, CX2_INTA_MASK_R, CX2_INTA_MASK_ALL);
+}
+
+static inline void ipw_disable_interrupts(struct ipw_priv *priv)
+{
+ if (!(priv->status & STATUS_INT_ENABLED))
+ return;
+ priv->status &= ~STATUS_INT_ENABLED;
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+}
+
+static char *ipw_error_desc(u32 val)
+{
+ switch (val) {
+ case IPW_FW_ERROR_OK:
+ return "ERROR_OK";
+ case IPW_FW_ERROR_FAIL:
+ return "ERROR_FAIL";
+ case IPW_FW_ERROR_MEMORY_UNDERFLOW:
+ return "MEMORY_UNDERFLOW";
+ case IPW_FW_ERROR_MEMORY_OVERFLOW:
+ return "MEMORY_OVERFLOW";
+ case IPW_FW_ERROR_BAD_PARAM:
+ return "ERROR_BAD_PARAM";
+ case IPW_FW_ERROR_BAD_CHECKSUM:
+ return "ERROR_BAD_CHECKSUM";
+ case IPW_FW_ERROR_NMI_INTERRUPT:
+ return "ERROR_NMI_INTERRUPT";
+ case IPW_FW_ERROR_BAD_DATABASE:
+ return "ERROR_BAD_DATABASE";
+ case IPW_FW_ERROR_ALLOC_FAIL:
+ return "ERROR_ALLOC_FAIL";
+ case IPW_FW_ERROR_DMA_UNDERRUN:
+ return "ERROR_DMA_UNDERRUN";
+ case IPW_FW_ERROR_DMA_STATUS:
+ return "ERROR_DMA_STATUS";
+ case IPW_FW_ERROR_DINOSTATUS_ERROR:
+ return "ERROR_DINOSTATUS_ERROR";
+ case IPW_FW_ERROR_EEPROMSTATUS_ERROR:
+ return "ERROR_EEPROMSTATUS_ERROR";
+ case IPW_FW_ERROR_SYSASSERT:
+ return "ERROR_SYSASSERT";
+ case IPW_FW_ERROR_FATAL_ERROR:
+ return "ERROR_FATALSTATUS_ERROR";
+ default:
+ return "UNKNOWNSTATUS_ERROR";
+ }
+}
+
+static void ipw_dump_nic_error_log(struct ipw_priv *priv)
+{
+ u32 desc, time, blink1, blink2, ilink1, ilink2, idata, i, count, base;
+
+ base = ipw_read32(priv, IPWSTATUS_ERROR_LOG);
+ count = ipw_read_reg32(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IPW_ERROR("Start IPW Error Log Dump:\n");
+ IPW_ERROR("Status: 0x%08X, Config: %08X\n",
+ priv->status, priv->config);
+ }
+
+ for (i = ERROR_START_OFFSET;
+ i <= count * ERROR_ELEM_SIZE; i += ERROR_ELEM_SIZE) {
+ desc = ipw_read_reg32(priv, base + i);
+ time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32));
+ blink1 = ipw_read_reg32(priv, base + i + 2 * sizeof(u32));
+ blink2 = ipw_read_reg32(priv, base + i + 3 * sizeof(u32));
+ ilink1 = ipw_read_reg32(priv, base + i + 4 * sizeof(u32));
+ ilink2 = ipw_read_reg32(priv, base + i + 5 * sizeof(u32));
+ idata = ipw_read_reg32(priv, base + i + 6 * sizeof(u32));
+
+ IPW_ERROR("%s %i 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ipw_error_desc(desc), time, blink1, blink2,
+ ilink1, ilink2, idata);
+ }
+}
+
+static void ipw_dump_nic_event_log(struct ipw_priv *priv)
+{
+ u32 ev, time, data, i, count, base;
+
+ base = ipw_read32(priv, IPW_EVENT_LOG);
+ count = ipw_read_reg32(priv, base);
+
+ if (EVENT_START_OFFSET <= count * EVENT_ELEM_SIZE)
+ IPW_ERROR("Start IPW Event Log Dump:\n");
+
+ for (i = EVENT_START_OFFSET;
+ i <= count * EVENT_ELEM_SIZE; i += EVENT_ELEM_SIZE) {
+ ev = ipw_read_reg32(priv, base + i);
+ time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32));
+ data = ipw_read_reg32(priv, base + i + 2 * sizeof(u32));
+
+#ifdef CONFIG_IPW_DEBUG
+ IPW_ERROR("%i\t0x%08x\t%i\n", time, data, ev);
+#endif
+ }
+}
+
+static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len)
+{
+ u32 addr, field_info, field_len, field_count, total_len;
+
+ IPW_DEBUG_ORD("ordinal = %i\n", ord);
+
+ if (!priv || !val || !len) {
+ IPW_DEBUG_ORD("Invalid argument\n");
+ return -EINVAL;
+ }
+
+ /* verify device ordinal tables have been initialized */
+ if (!priv->table0_addr || !priv->table1_addr || !priv->table2_addr) {
+ IPW_DEBUG_ORD("Access ordinals before initialization\n");
+ return -EINVAL;
+ }
+
+ switch (IPW_ORD_TABLE_ID_MASK & ord) {
+ case IPW_ORD_TABLE_0_MASK:
+ /*
+ * TABLE 0: Direct access to a table of 32 bit values
+ *
+ * This is a very simple table with the data directly
+ * read from the table
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table0_len) {
+ IPW_DEBUG_ORD("ordinal value (%i) longer then "
+ "max (%i)\n", ord, priv->table0_len);
+ return -EINVAL;
+ }
+
+ /* verify we have enough room to store the value */
+ if (*len < sizeof(u32)) {
+ IPW_DEBUG_ORD("ordinal buffer length too small, "
+ "need %zd\n", sizeof(u32));
+ return -EINVAL;
+ }
+
+ IPW_DEBUG_ORD("Reading TABLE0[%i] from offset 0x%08x\n",
+ ord, priv->table0_addr + (ord << 2));
+
+ *len = sizeof(u32);
+ ord <<= 2;
+ *((u32 *) val) = ipw_read32(priv, priv->table0_addr + ord);
+ break;
+
+ case IPW_ORD_TABLE_1_MASK:
+ /*
+ * TABLE 1: Indirect access to a table of 32 bit values
+ *
+ * This is a fairly large table of u32 values each
+ * representing starting addr for the data (which is
+ * also a u32)
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table1_len) {
+ IPW_DEBUG_ORD("ordinal value too long\n");
+ return -EINVAL;
+ }
+
+ /* verify we have enough room to store the value */
+ if (*len < sizeof(u32)) {
+ IPW_DEBUG_ORD("ordinal buffer length too small, "
+ "need %zd\n", sizeof(u32));
+ return -EINVAL;
+ }
+
+ *((u32 *) val) =
+ ipw_read_reg32(priv, (priv->table1_addr + (ord << 2)));
+ *len = sizeof(u32);
+ break;
+
+ case IPW_ORD_TABLE_2_MASK:
+ /*
+ * TABLE 2: Indirect access to a table of variable sized values
+ *
+ * This table consist of six values, each containing
+ * - dword containing the starting offset of the data
+ * - dword containing the lengh in the first 16bits
+ * and the count in the second 16bits
+ */
+
+ /* remove the table id from the ordinal */
+ ord &= IPW_ORD_TABLE_VALUE_MASK;
+
+ /* boundary check */
+ if (ord > priv->table2_len) {
+ IPW_DEBUG_ORD("ordinal value too long\n");
+ return -EINVAL;
+ }
+
+ /* get the address of statistic */
+ addr = ipw_read_reg32(priv, priv->table2_addr + (ord << 3));
+
+ /* get the second DW of statistics ;
+ * two 16-bit words - first is length, second is count */
+ field_info =
+ ipw_read_reg32(priv,
+ priv->table2_addr + (ord << 3) +
+ sizeof(u32));
+
+ /* get each entry length */
+ field_len = *((u16 *) & field_info);
+
+ /* get number of entries */
+ field_count = *(((u16 *) & field_info) + 1);
+
+ /* abort if not enought memory */
+ total_len = field_len * field_count;
+ if (total_len > *len) {
+ *len = total_len;
+ return -EINVAL;
+ }
+
+ *len = total_len;
+ if (!total_len)
+ return 0;
+
+ IPW_DEBUG_ORD("addr = 0x%08x, total_len = %i, "
+ "field_info = 0x%08x\n",
+ addr, total_len, field_info);
+ ipw_read_indirect(priv, addr, val, total_len);
+ break;
+
+ default:
+ IPW_DEBUG_ORD("Invalid ordinal!\n");
+ return -EINVAL;
+
+ }
+
+ return 0;
+}
+
+static void ipw_init_ordinals(struct ipw_priv *priv)
+{
+ priv->table0_addr = IPW_ORDINALS_TABLE_LOWER;
+ priv->table0_len = ipw_read32(priv, priv->table0_addr);
+
+ IPW_DEBUG_ORD("table 0 offset at 0x%08x, len = %i\n",
+ priv->table0_addr, priv->table0_len);
+
+ priv->table1_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_1);
+ priv->table1_len = ipw_read_reg32(priv, priv->table1_addr);
+
+ IPW_DEBUG_ORD("table 1 offset at 0x%08x, len = %i\n",
+ priv->table1_addr, priv->table1_len);
+
+ priv->table2_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_2);
+ priv->table2_len = ipw_read_reg32(priv, priv->table2_addr);
+ priv->table2_len &= 0x0000ffff; /* use first two bytes */
+
+ IPW_DEBUG_ORD("table 2 offset at 0x%08x, len = %i\n",
+ priv->table2_addr, priv->table2_len);
+
+}
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
+ * used for controling the debug level.
+ *
+ * See the level definitions in ipw for details.
+ */
+static ssize_t show_debug_level(struct device_driver *d, char *buf)
+{
+ return sprintf(buf, "0x%08X\n", ipw_debug_level);
+}
+static ssize_t store_debug_level(struct device_driver *d,
+ const char *buf, size_t count)
+{
+ char *p = (char *)buf;
+ u32 val;
+
+ if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+ p++;
+ if (p[0] == 'x' || p[0] == 'X')
+ p++;
+ val = simple_strtoul(p, &p, 16);
+ } else
+ val = simple_strtoul(p, &p, 10);
+ if (p == buf)
+ printk(KERN_INFO DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ipw_debug_level = val;
+
+ return strnlen(buf, count);
+}
+
+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ show_debug_level, store_debug_level);
+
+static ssize_t show_status(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->status);
+}
+
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
+static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ return sprintf(buf, "0x%08x\n", (int)p->config);
+}
+
+static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL);
+
+static ssize_t show_nic_type(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct ipw_priv *p = d->driver_data;
+ u8 type = p->eeprom[EEPROM_NIC_TYPE];
+
+ switch (type) {
+ case EEPROM_NIC_TYPE_STANDARD:
+ return sprintf(buf, "STANDARD\n");
+ case EEPROM_NIC_TYPE_DELL:
+ return sprintf(buf, "DELL\n");
+ case EEPROM_NIC_TYPE_FUJITSU:
+ return sprintf(buf, "FUJITSU\n");
+ case EEPROM_NIC_TYPE_IBM:
+ return sprintf(buf, "IBM\n");
+ case EEPROM_NIC_TYPE_HP:
+ return sprintf(buf, "HP\n");
+ }
+
+ return sprintf(buf, "UNKNOWN\n");
+}
+
+static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL);
+
+static ssize_t dump_error_log(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+ ipw_dump_nic_error_log((struct ipw_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
+
+static ssize_t dump_event_log(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+ ipw_dump_nic_event_log((struct ipw_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
+
+static ssize_t show_ucode_version(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 len = sizeof(u32), tmp = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len))
+ return 0;
+
+ return sprintf(buf, "0x%08x\n", tmp);
+}
+
+static DEVICE_ATTR(ucode_version, S_IWUSR | S_IRUGO, show_ucode_version, NULL);
+
+static ssize_t show_rtc(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ u32 len = sizeof(u32), tmp = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len))
+ return 0;
+
+ return sprintf(buf, "0x%08x\n", tmp);
+}
+
+static DEVICE_ATTR(rtc, S_IWUSR | S_IRUGO, show_rtc, NULL);
+
+/*
+ * Add a device attribute to view/control the delay between eeprom
+ * operations.
+ */
+static ssize_t show_eeprom_delay(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ int n = ((struct ipw_priv *)d->driver_data)->eeprom_delay;
+ return sprintf(buf, "%i\n", n);
+}
+static ssize_t store_eeprom_delay(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *p = d->driver_data;
+ sscanf(buf, "%i", &p->eeprom_delay);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(eeprom_delay, S_IWUSR | S_IRUGO,
+ show_eeprom_delay, store_eeprom_delay);
+
+static ssize_t show_command_event_reg(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ reg = ipw_read_reg32(p, CX2_INTERNAL_CMD_EVENT);
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_command_event_reg(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 reg;
+ struct ipw_priv *p = d->driver_data;
+
+ sscanf(buf, "%x", &reg);
+ ipw_write_reg32(p, CX2_INTERNAL_CMD_EVENT, reg);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(command_event_reg, S_IWUSR | S_IRUGO,
+ show_command_event_reg, store_command_event_reg);
+
+static ssize_t show_mem_gpio_reg(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *p = d->driver_data;
+
+ reg = ipw_read_reg32(p, 0x301100);
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_mem_gpio_reg(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 reg;
+ struct ipw_priv *p = d->driver_data;
+
+ sscanf(buf, "%x", &reg);
+ ipw_write_reg32(p, 0x301100, reg);
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(mem_gpio_reg, S_IWUSR | S_IRUGO,
+ show_mem_gpio_reg, store_mem_gpio_reg);
+
+static ssize_t show_indirect_dword(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+ if (priv->status & STATUS_INDIRECT_DWORD)
+ reg = ipw_read_reg32(priv, priv->indirect_dword);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_indirect_dword(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->indirect_dword);
+ priv->status |= STATUS_INDIRECT_DWORD;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(indirect_dword, S_IWUSR | S_IRUGO,
+ show_indirect_dword, store_indirect_dword);
+
+static ssize_t show_indirect_byte(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u8 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+ if (priv->status & STATUS_INDIRECT_BYTE)
+ reg = ipw_read_reg8(priv, priv->indirect_byte);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%02x\n", reg);
+}
+static ssize_t store_indirect_byte(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->indirect_byte);
+ priv->status |= STATUS_INDIRECT_BYTE;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(indirect_byte, S_IWUSR | S_IRUGO,
+ show_indirect_byte, store_indirect_byte);
+
+static ssize_t show_direct_dword(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg = 0;
+ struct ipw_priv *priv = d->driver_data;
+
+ if (priv->status & STATUS_DIRECT_DWORD)
+ reg = ipw_read32(priv, priv->direct_dword);
+ else
+ reg = 0;
+
+ return sprintf(buf, "0x%08x\n", reg);
+}
+static ssize_t store_direct_dword(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ sscanf(buf, "%x", &priv->direct_dword);
+ priv->status |= STATUS_DIRECT_DWORD;
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,
+ show_direct_dword, store_direct_dword);
+
+static inline int rf_kill_active(struct ipw_priv *priv)
+{
+ if (0 == (ipw_read32(priv, 0x30) & 0x10000))
+ priv->status |= STATUS_RF_KILL_HW;
+ else
+ priv->status &= ~STATUS_RF_KILL_HW;
+
+ return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;
+}
+
+static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ /* 0 - RF kill not enabled
+ 1 - SW based RF kill active (sysfs)
+ 2 - HW based RF kill active
+ 3 - Both HW and SW baed RF kill active */
+ struct ipw_priv *priv = d->driver_data;
+ int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
+ (rf_kill_active(priv) ? 0x2 : 0x0);
+ return sprintf(buf, "%i\n", val);
+}
+
+static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
+{
+ if ((disable_radio ? 1 : 0) ==
+ (priv->status & STATUS_RF_KILL_SW ? 1 : 0))
+ return 0;
+
+ IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n",
+ disable_radio ? "OFF" : "ON");
+
+ if (disable_radio) {
+ priv->status |= STATUS_RF_KILL_SW;
+
+ if (priv->workqueue) {
+ cancel_delayed_work(&priv->request_scan);
+ }
+ wake_up_interruptible(&priv->wait_command_queue);
+ queue_work(priv->workqueue, &priv->down);
+ } else {
+ priv->status &= ~STATUS_RF_KILL_SW;
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("Can not turn radio back on - "
+ "disabled by HW switch\n");
+ /* Make sure the RF_KILL check timer is running */
+ cancel_delayed_work(&priv->rf_kill);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ 2 * HZ);
+ } else
+ queue_work(priv->workqueue, &priv->up);
+ }
+
+ return 1;
+}
+
+static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ipw_priv *priv = d->driver_data;
+
+ ipw_radio_kill_sw(priv, buf[0] == '1');
+
+ return count;
+}
+
+static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
+
+static void ipw_irq_tasklet(struct ipw_priv *priv)
+{
+ u32 inta, inta_mask, handled = 0;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ inta = ipw_read32(priv, CX2_INTA_RW);
+ inta_mask = ipw_read32(priv, CX2_INTA_MASK_R);
+ inta &= (CX2_INTA_MASK_ALL & inta_mask);
+
+ /* Add any cached INTA values that need to be handled */
+ inta |= priv->isr_inta;
+
+ /* handle all the justifications for the interrupt */
+ if (inta & CX2_INTA_BIT_RX_TRANSFER) {
+ ipw_rx(priv);
+ handled |= CX2_INTA_BIT_RX_TRANSFER;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_CMD_QUEUE) {
+ IPW_DEBUG_HC("Command completed.\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1);
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ wake_up_interruptible(&priv->wait_command_queue);
+ handled |= CX2_INTA_BIT_TX_CMD_QUEUE;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_1) {
+ IPW_DEBUG_TX("TX_QUEUE_1\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0);
+ handled |= CX2_INTA_BIT_TX_QUEUE_1;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_2) {
+ IPW_DEBUG_TX("TX_QUEUE_2\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1);
+ handled |= CX2_INTA_BIT_TX_QUEUE_2;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_3) {
+ IPW_DEBUG_TX("TX_QUEUE_3\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2);
+ handled |= CX2_INTA_BIT_TX_QUEUE_3;
+ }
+
+ if (inta & CX2_INTA_BIT_TX_QUEUE_4) {
+ IPW_DEBUG_TX("TX_QUEUE_4\n");
+ rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3);
+ handled |= CX2_INTA_BIT_TX_QUEUE_4;
+ }
+
+ if (inta & CX2_INTA_BIT_STATUS_CHANGE) {
+ IPW_WARNING("STATUS_CHANGE\n");
+ handled |= CX2_INTA_BIT_STATUS_CHANGE;
+ }
+
+ if (inta & CX2_INTA_BIT_BEACON_PERIOD_EXPIRED) {
+ IPW_WARNING("TX_PERIOD_EXPIRED\n");
+ handled |= CX2_INTA_BIT_BEACON_PERIOD_EXPIRED;
+ }
+
+ if (inta & CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) {
+ IPW_WARNING("HOST_CMD_DONE\n");
+ handled |= CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FW_INITIALIZATION_DONE) {
+ IPW_WARNING("FW_INITIALIZATION_DONE\n");
+ handled |= CX2_INTA_BIT_FW_INITIALIZATION_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) {
+ IPW_WARNING("PHY_OFF_DONE\n");
+ handled |= CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_RF_KILL_DONE) {
+ IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
+ priv->status |= STATUS_RF_KILL_HW;
+ wake_up_interruptible(&priv->wait_command_queue);
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ cancel_delayed_work(&priv->request_scan);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+ handled |= CX2_INTA_BIT_RF_KILL_DONE;
+ }
+
+ if (inta & CX2_INTA_BIT_FATAL_ERROR) {
+ IPW_ERROR("Firmware error detected. Restarting.\n");
+#ifdef CONFIG_IPW_DEBUG
+ if (ipw_debug_level & IPW_DL_FW_ERRORS) {
+ ipw_dump_nic_error_log(priv);
+ ipw_dump_nic_event_log(priv);
+ }
+#endif
+ queue_work(priv->workqueue, &priv->adapter_restart);
+ handled |= CX2_INTA_BIT_FATAL_ERROR;
+ }
+
+ if (inta & CX2_INTA_BIT_PARITY_ERROR) {
+ IPW_ERROR("Parity error\n");
+ handled |= CX2_INTA_BIT_PARITY_ERROR;
+ }
+
+ if (handled != inta) {
+ IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
+ }
+
+ /* enable all interrupts */
+ ipw_enable_interrupts(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_CMD(x) case IPW_CMD_ ## x : return #x
+static char *get_cmd_string(u8 cmd)
+{
+ switch (cmd) {
+ IPW_CMD(HOST_COMPLETE);
+ IPW_CMD(POWER_DOWN);
+ IPW_CMD(SYSTEM_CONFIG);
+ IPW_CMD(MULTICAST_ADDRESS);
+ IPW_CMD(SSID);
+ IPW_CMD(ADAPTER_ADDRESS);
+ IPW_CMD(PORT_TYPE);
+ IPW_CMD(RTS_THRESHOLD);
+ IPW_CMD(FRAG_THRESHOLD);
+ IPW_CMD(POWER_MODE);
+ IPW_CMD(WEP_KEY);
+ IPW_CMD(TGI_TX_KEY);
+ IPW_CMD(SCAN_REQUEST);
+ IPW_CMD(SCAN_REQUEST_EXT);
+ IPW_CMD(ASSOCIATE);
+ IPW_CMD(SUPPORTED_RATES);
+ IPW_CMD(SCAN_ABORT);
+ IPW_CMD(TX_FLUSH);
+ IPW_CMD(QOS_PARAMETERS);
+ IPW_CMD(DINO_CONFIG);
+ IPW_CMD(RSN_CAPABILITIES);
+ IPW_CMD(RX_KEY);
+ IPW_CMD(CARD_DISABLE);
+ IPW_CMD(SEED_NUMBER);
+ IPW_CMD(TX_POWER);
+ IPW_CMD(COUNTRY_INFO);
+ IPW_CMD(AIRONET_INFO);
+ IPW_CMD(AP_TX_POWER);
+ IPW_CMD(CCKM_INFO);
+ IPW_CMD(CCX_VER_INFO);
+ IPW_CMD(SET_CALIBRATION);
+ IPW_CMD(SENSITIVITY_CALIB);
+ IPW_CMD(RETRY_LIMIT);
+ IPW_CMD(IPW_PRE_POWER_DOWN);
+ IPW_CMD(VAP_BEACON_TEMPLATE);
+ IPW_CMD(VAP_DTIM_PERIOD);
+ IPW_CMD(EXT_SUPPORTED_RATES);
+ IPW_CMD(VAP_LOCAL_TX_PWR_CONSTRAINT);
+ IPW_CMD(VAP_QUIET_INTERVALS);
+ IPW_CMD(VAP_CHANNEL_SWITCH);
+ IPW_CMD(VAP_MANDATORY_CHANNELS);
+ IPW_CMD(VAP_CELL_PWR_LIMIT);
+ IPW_CMD(VAP_CF_PARAM_SET);
+ IPW_CMD(VAP_SET_BEACONING_STATE);
+ IPW_CMD(MEASUREMENT);
+ IPW_CMD(POWER_CAPABILITY);
+ IPW_CMD(SUPPORTED_CHANNELS);
+ IPW_CMD(TPC_REPORT);
+ IPW_CMD(WME_INFO);
+ IPW_CMD(PRODUCTION_COMMAND);
+ default:
+ return "UNKNOWN";
+ }
+}
+#endif /* CONFIG_IPW_DEBUG */
+
+#define HOST_COMPLETE_TIMEOUT HZ
+static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
+{
+ int rc = 0;
+
+ if (priv->status & STATUS_HCMD_ACTIVE) {
+ IPW_ERROR("Already sending a command\n");
+ return -1;
+ }
+
+ priv->status |= STATUS_HCMD_ACTIVE;
+
+ IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n",
+ get_cmd_string(cmd->cmd), cmd->cmd, cmd->len);
+ printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
+
+ rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);
+ if (rc)
+ return rc;
+
+ rc = wait_event_interruptible_timeout(priv->wait_command_queue,
+ !(priv->
+ status & STATUS_HCMD_ACTIVE),
+ HOST_COMPLETE_TIMEOUT);
+ if (rc == 0) {
+ IPW_DEBUG_INFO("Command completion failed out after %dms.\n",
+ jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ return -EIO;
+ }
+ if (priv->status & STATUS_RF_KILL_MASK) {
+ IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ipw_send_host_complete(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_HOST_COMPLETE,
+ .len = 0
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send HOST_COMPLETE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_system_config(struct ipw_priv *priv,
+ struct ipw_sys_config *config)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SYSTEM_CONFIG,
+ .len = sizeof(*config)
+ };
+
+ if (!priv || !config) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, config, sizeof(*config));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SYSTEM_CONFIG command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SSID,
+ .len = min(len, IW_ESSID_MAX_SIZE)
+ };
+
+ if (!priv || !ssid) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, ssid, cmd.len);
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SSID command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_ADAPTER_ADDRESS,
+ .len = ETH_ALEN
+ };
+
+ if (!priv || !mac) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n",
+ priv->net_dev->name, MAC_ARG(mac));
+
+ memcpy(&cmd.param, mac, ETH_ALEN);
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send ADAPTER_ADDRESS command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void ipw_adapter_restart(void *adapter)
+{
+ struct ipw_priv *priv = adapter;
+
+ if (priv->status & STATUS_RF_KILL_MASK)
+ return;
+
+ ipw_down(priv);
+ if (ipw_up(priv)) {
+ IPW_ERROR("Failed to up device\n");
+ return;
+ }
+}
+
+#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
+
+static void ipw_scan_check(void *data)
+{
+ struct ipw_priv *priv = data;
+ if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
+ IPW_DEBUG_SCAN("Scan completion watchdog resetting "
+ "adapter (%dms).\n",
+ IPW_SCAN_CHECK_WATCHDOG / 100);
+ ipw_adapter_restart(priv);
+ }
+}
+
+static int ipw_send_scan_request_ext(struct ipw_priv *priv,
+ struct ipw_scan_request_ext *request)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SCAN_REQUEST_EXT,
+ .len = sizeof(*request)
+ };
+
+ if (!priv || !request) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, request, sizeof(*request));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n");
+ return -1;
+ }
+
+ queue_delayed_work(priv->workqueue, &priv->scan_check,
+ IPW_SCAN_CHECK_WATCHDOG);
+ return 0;
+}
+
+static int ipw_send_scan_abort(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SCAN_ABORT,
+ .len = 0
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SCAN_ABORT command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SENSITIVITY_CALIB,
+ .len = sizeof(struct ipw_sensitivity_calib)
+ };
+ struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *)
+ &cmd.param;
+ calib->beacon_rssi_raw = sens;
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SENSITIVITY CALIB command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_associate(struct ipw_priv *priv,
+ struct ipw_associate *associate)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_ASSOCIATE,
+ .len = sizeof(*associate)
+ };
+
+ if (!priv || !associate) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, associate, sizeof(*associate));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send ASSOCIATE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *rates)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SUPPORTED_RATES,
+ .len = sizeof(*rates)
+ };
+
+ if (!priv || !rates) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, rates, sizeof(*rates));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SUPPORTED_RATES command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_set_random_seed(struct ipw_priv *priv)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_SEED_NUMBER,
+ .len = sizeof(u32)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ get_random_bytes(&cmd.param, sizeof(u32));
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send SEED_NUMBER command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+#if 0
+static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_CARD_DISABLE,
+ .len = sizeof(u32)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ *((u32 *) & cmd.param) = phy_off;
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send CARD_DISABLE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_TX_POWER,
+ .len = sizeof(*power)
+ };
+
+ if (!priv || !power) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, power, sizeof(*power));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send TX_POWER command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts)
+{
+ struct ipw_rts_threshold rts_threshold = {
+ .rts_threshold = rts,
+ };
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_RTS_THRESHOLD,
+ .len = sizeof(rts_threshold)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, &rts_threshold, sizeof(rts_threshold));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send RTS_THRESHOLD command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
+{
+ struct ipw_frag_threshold frag_threshold = {
+ .frag_threshold = frag,
+ };
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_FRAG_THRESHOLD,
+ .len = sizeof(frag_threshold)
+ };
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ memcpy(&cmd.param, &frag_threshold, sizeof(frag_threshold));
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send FRAG_THRESHOLD command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
+{
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_POWER_MODE,
+ .len = sizeof(u32)
+ };
+ u32 *param = (u32 *) (&cmd.param);
+
+ if (!priv) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
+ /* If on battery, set to 3, if AC set to CAM, else user
+ * level */
+ switch (mode) {
+ case IPW_POWER_BATTERY:
+ *param = IPW_POWER_INDEX_3;
+ break;
+ case IPW_POWER_AC:
+ *param = IPW_POWER_MODE_CAM;
+ break;
+ default:
+ *param = mode;
+ break;
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send POWER_MODE command\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * The IPW device contains a Microwire compatible EEPROM that stores
+ * various data like the MAC address. Usually the firmware has exclusive
+ * access to the eeprom, but during device initialization (before the
+ * device driver has sent the HostComplete command to the firmware) the
+ * device driver has read access to the EEPROM by way of indirect addressing
+ * through a couple of memory mapped registers.
+ *
+ * The following is a simplified implementation for pulling data out of the
+ * the eeprom, along with some helper functions to find information in
+ * the per device private data's copy of the eeprom.
+ *
+ * NOTE: To better understand how these functions work (i.e what is a chip
+ * select and why do have to keep driving the eeprom clock?), read
+ * just about any data sheet for a Microwire compatible EEPROM.
+ */
+
+/* write a 32 bit value into the indirect accessor register */
+static inline void eeprom_write_reg(struct ipw_priv *p, u32 data)
+{
+ ipw_write_reg32(p, FW_MEM_REG_EEPROM_ACCESS, data);
+
+ /* the eeprom requires some time to complete the operation */
+ udelay(p->eeprom_delay);
+
+ return;
+}
+
+/* perform a chip select operation */
+static inline void eeprom_cs(struct ipw_priv *priv)
+{
+ eeprom_write_reg(priv, 0);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+}
+
+/* perform a chip select operation */
+static inline void eeprom_disable_cs(struct ipw_priv *priv)
+{
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ eeprom_write_reg(priv, 0);
+ eeprom_write_reg(priv, EEPROM_BIT_SK);
+}
+
+/* push a single bit down to the eeprom */
+static inline void eeprom_write_bit(struct ipw_priv *p, u8 bit)
+{
+ int d = (bit ? EEPROM_BIT_DI : 0);
+ eeprom_write_reg(p, EEPROM_BIT_CS | d);
+ eeprom_write_reg(p, EEPROM_BIT_CS | d | EEPROM_BIT_SK);
+}
+
+/* push an opcode followed by an address down to the eeprom */
+static void eeprom_op(struct ipw_priv *priv, u8 op, u8 addr)
+{
+ int i;
+
+ eeprom_cs(priv);
+ eeprom_write_bit(priv, 1);
+ eeprom_write_bit(priv, op & 2);
+ eeprom_write_bit(priv, op & 1);
+ for (i = 7; i >= 0; i--) {
+ eeprom_write_bit(priv, addr & (1 << i));
+ }
+}
+
+/* pull 16 bits off the eeprom, one bit at a time */
+static u16 eeprom_read_u16(struct ipw_priv *priv, u8 addr)
+{
+ int i;
+ u16 r = 0;
+
+ /* Send READ Opcode */
+ eeprom_op(priv, EEPROM_CMD_READ, addr);
+
+ /* Send dummy bit */
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+
+ /* Read the byte off the eeprom one bit at a time */
+ for (i = 0; i < 16; i++) {
+ u32 data = 0;
+ eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK);
+ eeprom_write_reg(priv, EEPROM_BIT_CS);
+ data = ipw_read_reg32(priv, FW_MEM_REG_EEPROM_ACCESS);
+ r = (r << 1) | ((data & EEPROM_BIT_DO) ? 1 : 0);
+ }
+
+ /* Send another dummy bit */
+ eeprom_write_reg(priv, 0);
+ eeprom_disable_cs(priv);
+
+ return r;
+}
+
+/* helper function for pulling the mac address out of the private */
+/* data's copy of the eeprom data */
+static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac)
+{
+ u8 *ee = (u8 *) priv->eeprom;
+ memcpy(mac, &ee[EEPROM_MAC_ADDRESS], 6);
+}
+
+/*
+ * Either the device driver (i.e. the host) or the firmware can
+ * load eeprom data into the designated region in SRAM. If neither
+ * happens then the FW will shutdown with a fatal error.
+ *
+ * In order to signal the FW to load the EEPROM, the EEPROM_LOAD_DISABLE
+ * bit needs region of shared SRAM needs to be non-zero.
+ */
+static void ipw_eeprom_init_sram(struct ipw_priv *priv)
+{
+ int i;
+ u16 *eeprom = (u16 *) priv->eeprom;
+
+ IPW_DEBUG_TRACE(">>\n");
+
+ /* read entire contents of eeprom into private buffer */
+ for (i = 0; i < 128; i++)
+ eeprom[i] = eeprom_read_u16(priv, (u8) i);
+
+ /*
+ If the data looks correct, then copy it to our private
+ copy. Otherwise let the firmware know to perform the operation
+ on it's own
+ */
+ if ((priv->eeprom + EEPROM_VERSION) != 0) {
+ IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
+
+ /* write the eeprom data to sram */
+ for (i = 0; i < CX2_EEPROM_IMAGE_SIZE; i++)
+ ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]);
+
+ /* Do not load eeprom data on fatal error or suspend */
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
+ } else {
+ IPW_DEBUG_INFO("Enabling FW initializationg of SRAM\n");
+
+ /* Load eeprom data on fatal error or suspend */
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 1);
+ }
+
+ IPW_DEBUG_TRACE("<<\n");
+}
+
+static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
+{
+ count >>= 2;
+ if (!count)
+ return;
+ _ipw_write32(priv, CX2_AUTOINC_ADDR, start);
+ while (count--)
+ _ipw_write32(priv, CX2_AUTOINC_DATA, 0);
+}
+
+static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv)
+{
+ ipw_zero_memory(priv, CX2_SHARED_SRAM_DMA_CONTROL,
+ CB_NUMBER_OF_ELEMENTS_SMALL *
+ sizeof(struct command_block));
+}
+
+static int ipw_fw_dma_enable(struct ipw_priv *priv)
+{ /* start dma engine but no transfers yet */
+
+ IPW_DEBUG_FW(">> : \n");
+
+ /* Start the dma */
+ ipw_fw_dma_reset_command_blocks(priv);
+
+ /* Write CB base address */
+ ipw_write_reg32(priv, CX2_DMA_I_CB_BASE, CX2_SHARED_SRAM_DMA_CONTROL);
+
+ IPW_DEBUG_FW("<< : \n");
+ return 0;
+}
+
+static void ipw_fw_dma_abort(struct ipw_priv *priv)
+{
+ u32 control = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+
+ //set the Stop and Abort bit
+ control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT;
+ ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control);
+ priv->sram_desc.last_cb_index = 0;
+
+ IPW_DEBUG_FW("<< \n");
+}
+
+static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index,
+ struct command_block *cb)
+{
+ u32 address =
+ CX2_SHARED_SRAM_DMA_CONTROL +
+ (sizeof(struct command_block) * index);
+ IPW_DEBUG_FW(">> :\n");
+
+ ipw_write_indirect(priv, address, (u8 *) cb,
+ (int)sizeof(struct command_block));
+
+ IPW_DEBUG_FW("<< :\n");
+ return 0;
+
+}
+
+static int ipw_fw_dma_kick(struct ipw_priv *priv)
+{
+ u32 control = 0;
+ u32 index = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+
+ for (index = 0; index < priv->sram_desc.last_cb_index; index++)
+ ipw_fw_dma_write_command_block(priv, index,
+ &priv->sram_desc.cb_list[index]);
+
+ /* Enable the DMA in the CSR register */
+ ipw_clear_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED |
+ CX2_RESET_REG_STOP_MASTER);
+
+ /* Set the Start bit. */
+ control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START;
+ ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control);
+
+ IPW_DEBUG_FW("<< :\n");
+ return 0;
+}
+
+static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv)
+{
+ u32 address;
+ u32 register_value = 0;
+ u32 cb_fields_address = 0;
+
+ IPW_DEBUG_FW(">> :\n");
+ address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB);
+ IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address);
+
+ /* Read the DMA Controlor register */
+ register_value = ipw_read_reg32(priv, CX2_DMA_I_DMA_CONTROL);
+ IPW_DEBUG_FW_INFO("CX2_DMA_I_DMA_CONTROL is 0x%x \n", register_value);
+
+ /* Print the CB values */
+ cb_fields_address = address;
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n",
+ register_value);
+
+ cb_fields_address += sizeof(u32);
+ register_value = ipw_read_reg32(priv, cb_fields_address);
+ IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value);
+
+ IPW_DEBUG_FW(">> :\n");
+}
+
+static int ipw_fw_dma_command_block_index(struct ipw_priv *priv)
+{
+ u32 current_cb_address = 0;
+ u32 current_cb_index = 0;
+
+ IPW_DEBUG_FW("<< :\n");
+ current_cb_address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB);
+
+ current_cb_index = (current_cb_address - CX2_SHARED_SRAM_DMA_CONTROL) /
+ sizeof(struct command_block);
+
+ IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n",
+ current_cb_index, current_cb_address);
+
+ IPW_DEBUG_FW(">> :\n");
+ return current_cb_index;
+
+}
+
+static int ipw_fw_dma_add_command_block(struct ipw_priv *priv,
+ u32 src_address,
+ u32 dest_address,
+ u32 length,
+ int interrupt_enabled, int is_last)
+{
+
+ u32 control = CB_VALID | CB_SRC_LE | CB_DEST_LE | CB_SRC_AUTOINC |
+ CB_SRC_IO_GATED | CB_DEST_AUTOINC | CB_SRC_SIZE_LONG |
+ CB_DEST_SIZE_LONG;
+ struct command_block *cb;
+ u32 last_cb_element = 0;
+
+ IPW_DEBUG_FW_INFO("src_address=0x%x dest_address=0x%x length=0x%x\n",
+ src_address, dest_address, length);
+
+ if (priv->sram_desc.last_cb_index >= CB_NUMBER_OF_ELEMENTS_SMALL)
+ return -1;
+
+ last_cb_element = priv->sram_desc.last_cb_index;
+ cb = &priv->sram_desc.cb_list[last_cb_element];
+ priv->sram_desc.last_cb_index++;
+
+ /* Calculate the new CB control word */
+ if (interrupt_enabled)
+ control |= CB_INT_ENABLED;
+
+ if (is_last)
+ control |= CB_LAST_VALID;
+
+ control |= length;
+
+ /* Calculate the CB Element's checksum value */
+ cb->status = control ^ src_address ^ dest_address;
+
+ /* Copy the Source and Destination addresses */
+ cb->dest_addr = dest_address;
+ cb->source_addr = src_address;
+
+ /* Copy the Control Word last */
+ cb->control = control;
+
+ return 0;
+}
+
+static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
+ u32 src_phys, u32 dest_address, u32 length)
+{
+ u32 bytes_left = length;
+ u32 src_offset = 0;
+ u32 dest_offset = 0;
+ int status = 0;
+ IPW_DEBUG_FW(">> \n");
+ IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n",
+ src_phys, dest_address, length);
+ while (bytes_left > CB_MAX_LENGTH) {
+ status = ipw_fw_dma_add_command_block(priv,
+ src_phys + src_offset,
+ dest_address +
+ dest_offset,
+ CB_MAX_LENGTH, 0, 0);
+ if (status) {
+ IPW_DEBUG_FW_INFO(": Failed\n");
+ return -1;
+ } else
+ IPW_DEBUG_FW_INFO(": Added new cb\n");
+
+ src_offset += CB_MAX_LENGTH;
+ dest_offset += CB_MAX_LENGTH;
+ bytes_left -= CB_MAX_LENGTH;
+ }
+
+ /* add the buffer tail */
+ if (bytes_left > 0) {
+ status =
+ ipw_fw_dma_add_command_block(priv, src_phys + src_offset,
+ dest_address + dest_offset,
+ bytes_left, 0, 0);
+ if (status) {
+ IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n");
+ return -1;
+ } else
+ IPW_DEBUG_FW_INFO
+ (": Adding new cb - the buffer tail\n");
+ }
+
+ IPW_DEBUG_FW("<< \n");
+ return 0;
+}
+
+static int ipw_fw_dma_wait(struct ipw_priv *priv)
+{
+ u32 current_index = 0;
+ u32 watchdog = 0;
+
+ IPW_DEBUG_FW(">> : \n");
+
+ current_index = ipw_fw_dma_command_block_index(priv);
+ IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n",
+ (int)priv->sram_desc.last_cb_index);
+
+ while (current_index < priv->sram_desc.last_cb_index) {
+ udelay(50);
+ current_index = ipw_fw_dma_command_block_index(priv);
+
+ watchdog++;
+
+ if (watchdog > 400) {
+ IPW_DEBUG_FW_INFO("Timeout\n");
+ ipw_fw_dma_dump_command_block(priv);
+ ipw_fw_dma_abort(priv);
+ return -1;
+ }
+ }
+
+ ipw_fw_dma_abort(priv);
+
+ /*Disable the DMA in the CSR register */
+ ipw_set_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED | CX2_RESET_REG_STOP_MASTER);
+
+ IPW_DEBUG_FW("<< dmaWaitSync \n");
+ return 0;
+}
+
+static void ipw_remove_current_network(struct ipw_priv *priv)
+{
+ struct list_head *element, *safe;
+ struct ieee80211_network *network = NULL;
+ list_for_each_safe(element, safe, &priv->ieee->network_list) {
+ network = list_entry(element, struct ieee80211_network, list);
+ if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+ list_del(element);
+ list_add_tail(&network->list,
+ &priv->ieee->network_free_list);
+ }
+ }
+}
+
+/**
+ * Check that card is still alive.
+ * Reads debug register from domain0.
+ * If card is present, pre-defined value should
+ * be found there.
+ *
+ * @param priv
+ * @return 1 if card is present, 0 otherwise
+ */
+static inline int ipw_alive(struct ipw_priv *priv)
+{
+ return ipw_read32(priv, 0x90) == 0xd55555d5;
+}
+
+static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
+ int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((ipw_read32(priv, addr) & mask) == mask)
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIME;
+}
+
+/* These functions load the firmware and micro code for the operation of
+ * the ipw hardware. It assumes the buffer has all the bits for the
+ * image and the caller is handling the memory allocation and clean up.
+ */
+
+static int ipw_stop_master(struct ipw_priv *priv)
+{
+ int rc;
+
+ IPW_DEBUG_TRACE(">> \n");
+ /* stop master. typical delay - 0 */
+ ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER);
+
+ rc = ipw_poll_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED, 100);
+ if (rc < 0) {
+ IPW_ERROR("stop master failed in 10ms\n");
+ return -1;
+ }
+
+ IPW_DEBUG_INFO("stop master %dms\n", rc);
+
+ return rc;
+}
+
+static void ipw_arc_release(struct ipw_priv *priv)
+{
+ IPW_DEBUG_TRACE(">> \n");
+ mdelay(5);
+
+ ipw_clear_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET);
+
+ /* no one knows timing, for safety add some delay */
+ mdelay(5);
+}
+
+struct fw_header {
+ u32 version;
+ u32 mode;
+};
+
+struct fw_chunk {
+ u32 address;
+ u32 length;
+};
+
+#define IPW_FW_MAJOR_VERSION 2
+#define IPW_FW_MINOR_VERSION 2
+
+#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
+#define IPW_FW_MAJOR(x) (x & 0xff)
+
+#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | \
+ IPW_FW_MAJOR_VERSION)
+
+#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \
+"." __stringify(IPW_FW_MINOR_VERSION) "-"
+
+#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0
+#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw"
+#else
+#define IPW_FW_NAME(x) "ipw2200_" x ".fw"
+#endif
+
+static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
+{
+ int rc = 0, i, addr;
+ u8 cr = 0;
+ u16 *image;
+
+ image = (u16 *) data;
+
+ IPW_DEBUG_TRACE(">> \n");
+
+ rc = ipw_stop_master(priv);
+
+ if (rc < 0)
+ return rc;
+
+// spin_lock_irqsave(&priv->lock, flags);
+
+ for (addr = CX2_SHARED_LOWER_BOUND;
+ addr < CX2_REGISTER_DOMAIN1_END; addr += 4) {
+ ipw_write32(priv, addr, 0);
+ }
+
+ /* no ucode (yet) */
+ memset(&priv->dino_alive, 0, sizeof(priv->dino_alive));
+ /* destroy DMA queues */
+ /* reset sequence */
+
+ ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_ON);
+ ipw_arc_release(priv);
+ ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_OFF);
+ mdelay(1);
+
+ /* reset PHY */
+ ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, CX2_BASEBAND_POWER_DOWN);
+ mdelay(1);
+
+ ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, 0);
+ mdelay(1);
+
+ /* enable ucode store */
+ ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0);
+ ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS);
+ mdelay(1);
+
+ /* write ucode */
+ /**
+ * @bug
+ * Do NOT set indirect address register once and then
+ * store data to indirect data register in the loop.
+ * It seems very reasonable, but in this case DINO do not
+ * accept ucode. It is essential to set address each time.
+ */
+ /* load new ipw uCode */
+ for (i = 0; i < len / 2; i++)
+ ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, image[i]);
+
+ /* enable DINO */
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0);
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM);
+
+ /* this is where the igx / win driver deveates from the VAP driver. */
+
+ /* wait for alive response */
+ for (i = 0; i < 100; i++) {
+ /* poll for incoming data */
+ cr = ipw_read_reg8(priv, CX2_BASEBAND_CONTROL_STATUS);
+ if (cr & DINO_RXFIFO_DATA)
+ break;
+ mdelay(1);
+ }
+
+ if (cr & DINO_RXFIFO_DATA) {
+ /* alive_command_responce size is NOT multiple of 4 */
+ u32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4];
+
+ for (i = 0; i < ARRAY_SIZE(response_buffer); i++)
+ response_buffer[i] =
+ ipw_read_reg32(priv, CX2_BASEBAND_RX_FIFO_READ);
+ memcpy(&priv->dino_alive, response_buffer,
+ sizeof(priv->dino_alive));
+ if (priv->dino_alive.alive_command == 1
+ && priv->dino_alive.ucode_valid == 1) {
+ rc = 0;
+ IPW_DEBUG_INFO
+ ("Microcode OK, rev. %d (0x%x) dev. %d (0x%x) "
+ "of %02d/%02d/%02d %02d:%02d\n",
+ priv->dino_alive.software_revision,
+ priv->dino_alive.software_revision,
+ priv->dino_alive.device_identifier,
+ priv->dino_alive.device_identifier,
+ priv->dino_alive.time_stamp[0],
+ priv->dino_alive.time_stamp[1],
+ priv->dino_alive.time_stamp[2],
+ priv->dino_alive.time_stamp[3],
+ priv->dino_alive.time_stamp[4]);
+ } else {
+ IPW_DEBUG_INFO("Microcode is not alive\n");
+ rc = -EINVAL;
+ }
+ } else {
+ IPW_DEBUG_INFO("No alive response from DINO\n");
+ rc = -ETIME;
+ }
+
+ /* disable DINO, otherwise for some reason
+ firmware have problem getting alive resp. */
+ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0);
+
+// spin_unlock_irqrestore(&priv->lock, flags);
+
+ return rc;
+}
+
+static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
+{
+ int rc = -1;
+ int offset = 0;
+ struct fw_chunk *chunk;
+ dma_addr_t shared_phys;
+ u8 *shared_virt;
+
+ IPW_DEBUG_TRACE("<< : \n");
+ shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys);
+
+ if (!shared_virt)
+ return -ENOMEM;
+
+ memmove(shared_virt, data, len);
+
+ /* Start the Dma */
+ rc = ipw_fw_dma_enable(priv);
+
+ if (priv->sram_desc.last_cb_index > 0) {
+ /* the DMA is already ready this would be a bug. */
+ BUG();
+ goto out;
+ }
+
+ do {
+ chunk = (struct fw_chunk *)(data + offset);
+ offset += sizeof(struct fw_chunk);
+ /* build DMA packet and queue up for sending */
+ /* dma to chunk->address, the chunk->length bytes from data +
+ * offeset*/
+ /* Dma loading */
+ rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
+ chunk->address, chunk->length);
+ if (rc) {
+ IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
+ goto out;
+ }
+
+ offset += chunk->length;
+ } while (offset < len);
+
+ /* Run the DMA and wait for the answer */
+ rc = ipw_fw_dma_kick(priv);
+ if (rc) {
+ IPW_ERROR("dmaKick Failed\n");
+ goto out;
+ }
+
+ rc = ipw_fw_dma_wait(priv);
+ if (rc) {
+ IPW_ERROR("dmaWaitSync Failed\n");
+ goto out;
+ }
+ out:
+ pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys);
+ return rc;
+}
+
+/* stop nic */
+static int ipw_stop_nic(struct ipw_priv *priv)
+{
+ int rc = 0;
+
+ /* stop */
+ ipw_write32(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER);
+
+ rc = ipw_poll_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED, 500);
+ if (rc < 0) {
+ IPW_ERROR("wait for reg master disabled failed\n");
+ return rc;
+ }
+
+ ipw_set_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET);
+
+ return rc;
+}
+
+static void ipw_start_nic(struct ipw_priv *priv)
+{
+ IPW_DEBUG_TRACE(">>\n");
+
+ /* prvHwStartNic release ARC */
+ ipw_clear_bit(priv, CX2_RESET_REG,
+ CX2_RESET_REG_MASTER_DISABLED |
+ CX2_RESET_REG_STOP_MASTER |
+ CBD_RESET_REG_PRINCETON_RESET);
+
+ /* enable power management */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW,
+ CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY);
+
+ IPW_DEBUG_TRACE("<<\n");
+}
+
+static int ipw_init_nic(struct ipw_priv *priv)
+{
+ int rc;
+
+ IPW_DEBUG_TRACE(">>\n");
+ /* reset */
+ /*prvHwInitNic */
+ /* set "initialization complete" bit to move adapter to D0 state */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE);
+
+ /* low-level PLL activation */
+ ipw_write32(priv, CX2_READ_INT_REGISTER,
+ CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER);
+
+ /* wait for clock stabilization */
+ rc = ipw_poll_bit(priv, CX2_GP_CNTRL_RW,
+ CX2_GP_CNTRL_BIT_CLOCK_READY, 250);
+ if (rc < 0)
+ IPW_DEBUG_INFO("FAILED wait for clock stablization\n");
+
+ /* assert SW reset */
+ ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_SW_RESET);
+
+ udelay(10);
+
+ /* set "initialization complete" bit to move adapter to D0 state */
+ ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE);
+
+ IPW_DEBUG_TRACE(">>\n");
+ return 0;
+}
+
+/* Call this function from process context, it will sleep in request_firmware.
+ * Probe is an ok place to call this from.
+ */
+static int ipw_reset_nic(struct ipw_priv *priv)
+{
+ int rc = 0;
+
+ IPW_DEBUG_TRACE(">>\n");
+
+ rc = ipw_init_nic(priv);
+
+ /* Clear the 'host command active' bit... */
+ priv->status &= ~STATUS_HCMD_ACTIVE;
+ wake_up_interruptible(&priv->wait_command_queue);
+
+ IPW_DEBUG_TRACE("<<\n");
+ return rc;
+}
+
+static int ipw_get_fw(struct ipw_priv *priv,
+ const struct firmware **fw, const char *name)
+{
+ struct fw_header *header;
+ int rc;
+
+ /* ask firmware_class module to get the boot firmware off disk */
+ rc = request_firmware(fw, name, &priv->pci_dev->dev);
+ if (rc < 0) {
+ IPW_ERROR("%s load failed: Reason %d\n", name, rc);
+ return rc;
+ }
+
+ header = (struct fw_header *)(*fw)->data;
+ if (IPW_FW_MAJOR(header->version) != IPW_FW_MAJOR_VERSION) {
+ IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n",
+ name,
+ IPW_FW_MAJOR(header->version), IPW_FW_MAJOR_VERSION);
+ return -EINVAL;
+ }
+
+ IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n",
+ name,
+ IPW_FW_MAJOR(header->version),
+ IPW_FW_MINOR(header->version),
+ (*fw)->size - sizeof(struct fw_header));
+ return 0;
+}
+
+#define CX2_RX_BUF_SIZE (3000)
+
+static inline void ipw_rx_queue_reset(struct ipw_priv *priv,
+ struct ipw_rx_queue *rxq)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+ /* In the reset function, these buffers may have been allocated
+ * to an SKB, so we need to unmap and free potential storage */
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+ }
+
+ /* Set us so that we have processed and used all buffers, but have
+ * not restocked the Rx queue with fresh buffers */
+ rxq->read = rxq->write = 0;
+ rxq->processed = RX_QUEUE_SIZE - 1;
+ rxq->free_count = 0;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+#ifdef CONFIG_PM
+static int fw_loaded = 0;
+static const struct firmware *bootfw = NULL;
+static const struct firmware *firmware = NULL;
+static const struct firmware *ucode = NULL;
+#endif
+
+static int ipw_load(struct ipw_priv *priv)
+{
+#ifndef CONFIG_PM
+ const struct firmware *bootfw = NULL;
+ const struct firmware *firmware = NULL;
+ const struct firmware *ucode = NULL;
+#endif
+ int rc = 0, retries = 3;
+
+#ifdef CONFIG_PM
+ if (!fw_loaded) {
+#endif
+ rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
+ if (rc)
+ goto error;
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ rc = ipw_get_fw(priv, &ucode,
+ IPW_FW_NAME("ibss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss"));
+ break;
+
+#ifdef CONFIG_IPW_PROMISC
+ case IW_MODE_MONITOR:
+ rc = ipw_get_fw(priv, &ucode,
+ IPW_FW_NAME("ibss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware,
+ IPW_FW_NAME("sniffer"));
+ break;
+#endif
+ case IW_MODE_INFRA:
+ rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode"));
+ if (rc)
+ goto error;
+
+ rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss"));
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+
+ if (rc)
+ goto error;
+
+#ifdef CONFIG_PM
+ fw_loaded = 1;
+ }
+#endif
+
+ if (!priv->rxq)
+ priv->rxq = ipw_rx_queue_alloc(priv);
+ else
+ ipw_rx_queue_reset(priv, priv->rxq);
+ if (!priv->rxq) {
+ IPW_ERROR("Unable to initialize Rx queue\n");
+ goto error;
+ }
+
+ retry:
+ /* Ensure interrupts are disabled */
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+ priv->status &= ~STATUS_INT_ENABLED;
+
+ /* ack pending interrupts */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
+
+ ipw_stop_nic(priv);
+
+ rc = ipw_reset_nic(priv);
+ if (rc) {
+ IPW_ERROR("Unable to reset NIC\n");
+ goto error;
+ }
+
+ ipw_zero_memory(priv, CX2_NIC_SRAM_LOWER_BOUND,
+ CX2_NIC_SRAM_UPPER_BOUND - CX2_NIC_SRAM_LOWER_BOUND);
+
+ /* DMA the initial boot firmware into the device */
+ rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header),
+ bootfw->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load boot firmware\n");
+ goto error;
+ }
+
+ /* kick start the device */
+ ipw_start_nic(priv);
+
+ /* wait for the device to finish it's initial startup sequence */
+ rc = ipw_poll_bit(priv, CX2_INTA_RW,
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500);
+ if (rc < 0) {
+ IPW_ERROR("device failed to boot initial fw image\n");
+ goto error;
+ }
+ IPW_DEBUG_INFO("initial device response after %dms\n", rc);
+
+ /* ack fw init done interrupt */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE);
+
+ /* DMA the ucode into the device */
+ rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header),
+ ucode->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load ucode\n");
+ goto error;
+ }
+
+ /* stop nic */
+ ipw_stop_nic(priv);
+
+ /* DMA bss firmware into the device */
+ rc = ipw_load_firmware(priv, firmware->data +
+ sizeof(struct fw_header),
+ firmware->size - sizeof(struct fw_header));
+ if (rc < 0) {
+ IPW_ERROR("Unable to load firmware\n");
+ goto error;
+ }
+
+ ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
+
+ rc = ipw_queue_reset(priv);
+ if (rc) {
+ IPW_ERROR("Unable to initialize queues\n");
+ goto error;
+ }
+
+ /* Ensure interrupts are disabled */
+ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
+
+ /* kick start the device */
+ ipw_start_nic(priv);
+
+ if (ipw_read32(priv, CX2_INTA_RW) & CX2_INTA_BIT_PARITY_ERROR) {
+ if (retries > 0) {
+ IPW_WARNING("Parity error. Retrying init.\n");
+ retries--;
+ goto retry;
+ }
+
+ IPW_ERROR("TODO: Handle parity error -- schedule restart?\n");
+ rc = -EIO;
+ goto error;
+ }
+
+ /* wait for the device */
+ rc = ipw_poll_bit(priv, CX2_INTA_RW,
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500);
+ if (rc < 0) {
+ IPW_ERROR("device failed to start after 500ms\n");
+ goto error;
+ }
+ IPW_DEBUG_INFO("device response after %dms\n", rc);
+
+ /* ack fw init done interrupt */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE);
+
+ /* read eeprom data and initialize the eeprom region of sram */
+ priv->eeprom_delay = 1;
+ ipw_eeprom_init_sram(priv);
+
+ /* enable interrupts */
+ ipw_enable_interrupts(priv);
+
+ /* Ensure our queue has valid packets */
+ ipw_rx_queue_replenish(priv);
+
+ ipw_write32(priv, CX2_RX_READ_INDEX, priv->rxq->read);
+
+ /* ack pending interrupts */
+ ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
+
+#ifndef CONFIG_PM
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+#endif
+ return 0;
+
+ error:
+ if (priv->rxq) {
+ ipw_rx_queue_free(priv, priv->rxq);
+ priv->rxq = NULL;
+ }
+ ipw_tx_queue_free(priv);
+ if (bootfw)
+ release_firmware(bootfw);
+ if (ucode)
+ release_firmware(ucode);
+ if (firmware)
+ release_firmware(firmware);
+#ifdef CONFIG_PM
+ fw_loaded = 0;
+ bootfw = ucode = firmware = NULL;
+#endif
+
+ return rc;
+}
+
+/**
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A queue is a circular buffers with 'Read' and 'Write' pointers.
+ * 2 empty entries always kept in the buffer to protect from overflow.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ * The IPW operates with six queues, one receive queue in the device's
+ * sram, one transmit queue for sending commands to the device firmware,
+ * and four transmit queues for data.
+ *
+ * The four transmit queues allow for performing quality of service (qos)
+ * transmissions as per the 802.11 protocol. Currently Linux does not
+ * provide a mechanism to the user for utilizing prioritized queues, so
+ * we only utilize the first data transmit queue (queue1).
+ */
+
+/**
+ * Driver allocates buffers of this size for Rx
+ */
+
+static inline int ipw_queue_space(const struct clx2_queue *q)
+{
+ int s = q->last_used - q->first_empty;
+ if (s <= 0)
+ s += q->n_bd;
+ s -= 2; /* keep some reserve to not confuse empty and full situations */
+ if (s < 0)
+ s = 0;
+ return s;
+}
+
+static inline int ipw_queue_inc_wrap(int index, int n_bd)
+{
+ return (++index == n_bd) ? 0 : index;
+}
+
+/**
+ * Initialize common DMA queue structure
+ *
+ * @param q queue to init
+ * @param count Number of BD's to allocate. Should be power of 2
+ * @param read_register Address for 'read' register
+ * (not offset within BAR, full address)
+ * @param write_register Address for 'write' register
+ * (not offset within BAR, full address)
+ * @param base_register Address for 'base' register
+ * (not offset within BAR, full address)
+ * @param size Address for 'size' register
+ * (not offset within BAR, full address)
+ */
+static void ipw_queue_init(struct ipw_priv *priv, struct clx2_queue *q,
+ int count, u32 read, u32 write, u32 base, u32 size)
+{
+ q->n_bd = count;
+
+ q->low_mark = q->n_bd / 4;
+ if (q->low_mark < 4)
+ q->low_mark = 4;
+
+ q->high_mark = q->n_bd / 8;
+ if (q->high_mark < 2)
+ q->high_mark = 2;
+
+ q->first_empty = q->last_used = 0;
+ q->reg_r = read;
+ q->reg_w = write;
+
+ ipw_write32(priv, base, q->dma_addr);
+ ipw_write32(priv, size, count);
+ ipw_write32(priv, read, 0);
+ ipw_write32(priv, write, 0);
+
+ _ipw_read32(priv, 0x90);
+}
+
+static int ipw_queue_tx_init(struct ipw_priv *priv,
+ struct clx2_tx_queue *q,
+ int count, u32 read, u32 write, u32 base, u32 size)
+{
+ struct pci_dev *dev = priv->pci_dev;
+
+ q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL);
+ if (!q->txb) {
+ IPW_ERROR("vmalloc for auxilary BD structures failed\n");
+ return -ENOMEM;
+ }
+
+ q->bd =
+ pci_alloc_consistent(dev, sizeof(q->bd[0]) * count, &q->q.dma_addr);
+ if (!q->bd) {
+ IPW_ERROR("pci_alloc_consistent(%zd) failed\n",
+ sizeof(q->bd[0]) * count);
+ kfree(q->txb);
+ q->txb = NULL;
+ return -ENOMEM;
+ }
+
+ ipw_queue_init(priv, &q->q, count, read, write, base, size);
+ return 0;
+}
+
+/**
+ * Free one TFD, those at index [txq->q.last_used].
+ * Do NOT advance any indexes
+ *
+ * @param dev
+ * @param txq
+ */
+static void ipw_queue_tx_free_tfd(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq)
+{
+ struct tfd_frame *bd = &txq->bd[txq->q.last_used];
+ struct pci_dev *dev = priv->pci_dev;
+ int i;
+
+ /* classify bd */
+ if (bd->control_flags.message_type == TX_HOST_COMMAND_TYPE)
+ /* nothing to cleanup after for host commands */
+ return;
+
+ /* sanity check */
+ if (bd->u.data.num_chunks > NUM_TFD_CHUNKS) {
+ IPW_ERROR("Too many chunks: %i\n", bd->u.data.num_chunks);
+ /** @todo issue fatal error, it is quite serious situation */
+ return;
+ }
+
+ /* unmap chunks if any */
+ for (i = 0; i < bd->u.data.num_chunks; i++) {
+ pci_unmap_single(dev, bd->u.data.chunk_ptr[i],
+ bd->u.data.chunk_len[i], PCI_DMA_TODEVICE);
+ if (txq->txb[txq->q.last_used]) {
+ ieee80211_txb_free(txq->txb[txq->q.last_used]);
+ txq->txb[txq->q.last_used] = NULL;
+ }
+ }
+}
+
+/**
+ * Deallocate DMA queue.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ *
+ * @param dev
+ * @param q
+ */
+static void ipw_queue_tx_free(struct ipw_priv *priv, struct clx2_tx_queue *txq)
+{
+ struct clx2_queue *q = &txq->q;
+ struct pci_dev *dev = priv->pci_dev;
+
+ if (q->n_bd == 0)
+ return;
+
+ /* first, empty all BD's */
+ for (; q->first_empty != q->last_used;
+ q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) {
+ ipw_queue_tx_free_tfd(priv, txq);
+ }
+
+ /* free buffers belonging to queue itself */
+ pci_free_consistent(dev, sizeof(txq->bd[0]) * q->n_bd, txq->bd,
+ q->dma_addr);
+ kfree(txq->txb);
+
+ /* 0 fill whole structure */
+ memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * Destroy all DMA queues and structures
+ *
+ * @param priv
+ */
+static void ipw_tx_queue_free(struct ipw_priv *priv)
+{
+ /* Tx CMD queue */
+ ipw_queue_tx_free(priv, &priv->txq_cmd);
+
+ /* Tx queues */
+ ipw_queue_tx_free(priv, &priv->txq[0]);
+ ipw_queue_tx_free(priv, &priv->txq[1]);
+ ipw_queue_tx_free(priv, &priv->txq[2]);
+ ipw_queue_tx_free(priv, &priv->txq[3]);
+}
+
+static void inline __maybe_wake_tx(struct ipw_priv *priv)
+{
+ if (netif_running(priv->net_dev)) {
+ switch (priv->port_type) {
+ case DCR_TYPE_MU_BSS:
+ case DCR_TYPE_MU_IBSS:
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ return;
+ }
+ }
+ netif_wake_queue(priv->net_dev);
+ }
+
+}
+
+static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
+{
+ /* First 3 bytes are manufacturer */
+ bssid[0] = priv->mac_addr[0];
+ bssid[1] = priv->mac_addr[1];
+ bssid[2] = priv->mac_addr[2];
+
+ /* Last bytes are random */
+ get_random_bytes(&bssid[3], ETH_ALEN - 3);
+
+ bssid[0] &= 0xfe; /* clear multicast bit */
+ bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */
+}
+
+static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
+{
+ struct ipw_station_entry entry;
+ int i;
+
+ for (i = 0; i < priv->num_stations; i++) {
+ if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) {
+ /* Another node is active in network */
+ priv->missed_adhoc_beacons = 0;
+ if (!(priv->config & CFG_STATIC_CHANNEL))
+ /* when other nodes drop out, we drop out */
+ priv->config &= ~CFG_ADHOC_PERSIST;
+
+ return i;
+ }
+ }
+
+ if (i == MAX_STATIONS)
+ return IPW_INVALID_STATION;
+
+ IPW_DEBUG_SCAN("Adding AdHoc station: " MAC_FMT "\n", MAC_ARG(bssid));
+
+ entry.reserved = 0;
+ entry.support_mode = 0;
+ memcpy(entry.mac_addr, bssid, ETH_ALEN);
+ memcpy(priv->stations[i], bssid, ETH_ALEN);
+ ipw_write_direct(priv, IPW_STATION_TABLE_LOWER + i * sizeof(entry),
+ &entry, sizeof(entry));
+ priv->num_stations++;
+
+ return i;
+}
+
+static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
+{
+ int i;
+
+ for (i = 0; i < priv->num_stations; i++)
+ if (!memcmp(priv->stations[i], bssid, ETH_ALEN))
+ return i;
+
+ return IPW_INVALID_STATION;
+}
+
+static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
+{
+ int err;
+
+ if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))) {
+ IPW_DEBUG_ASSOC("Disassociating while not associated.\n");
+ return;
+ }
+
+ IPW_DEBUG_ASSOC("Disassocation attempt from " MAC_FMT " "
+ "on channel %d.\n",
+ MAC_ARG(priv->assoc_request.bssid),
+ priv->assoc_request.channel);
+
+ priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
+ priv->status |= STATUS_DISASSOCIATING;
+
+ if (quiet)
+ priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
+ else
+ priv->assoc_request.assoc_type = HC_DISASSOCIATE;
+ err = ipw_send_associate(priv, &priv->assoc_request);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send [dis]associate command "
+ "failed.\n");
+ return;
+ }
+
+}
+
+static void ipw_disassociate(void *data)
+{
+ ipw_send_disassociate(data, 0);
+}
+
+static void notify_wx_assoc_event(struct ipw_priv *priv)
+{
+ union iwreq_data wrqu;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (priv->status & STATUS_ASSOCIATED)
+ memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN);
+ else
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+struct ipw_status_code {
+ u16 status;
+ const char *reason;
+};
+
+static const struct ipw_status_code ipw_status_codes[] = {
+ {0x00, "Successful"},
+ {0x01, "Unspecified failure"},
+ {0x0A, "Cannot support all requested capabilities in the "
+ "Capability information field"},
+ {0x0B, "Reassociation denied due to inability to confirm that "
+ "association exists"},
+ {0x0C, "Association denied due to reason outside the scope of this "
+ "standard"},
+ {0x0D,
+ "Responding station does not support the specified authentication "
+ "algorithm"},
+ {0x0E,
+ "Received an Authentication frame with authentication sequence "
+ "transaction sequence number out of expected sequence"},
+ {0x0F, "Authentication rejected because of challenge failure"},
+ {0x10, "Authentication rejected due to timeout waiting for next "
+ "frame in sequence"},
+ {0x11, "Association denied because AP is unable to handle additional "
+ "associated stations"},
+ {0x12,
+ "Association denied due to requesting station not supporting all "
+ "of the datarates in the BSSBasicServiceSet Parameter"},
+ {0x13,
+ "Association denied due to requesting station not supporting "
+ "short preamble operation"},
+ {0x14,
+ "Association denied due to requesting station not supporting "
+ "PBCC encoding"},
+ {0x15,
+ "Association denied due to requesting station not supporting "
+ "channel agility"},
+ {0x19,
+ "Association denied due to requesting station not supporting "
+ "short slot operation"},
+ {0x1A,
+ "Association denied due to requesting station not supporting "
+ "DSSS-OFDM operation"},
+ {0x28, "Invalid Information Element"},
+ {0x29, "Group Cipher is not valid"},
+ {0x2A, "Pairwise Cipher is not valid"},
+ {0x2B, "AKMP is not valid"},
+ {0x2C, "Unsupported RSN IE version"},
+ {0x2D, "Invalid RSN IE Capabilities"},
+ {0x2E, "Cipher suite is rejected per security policy"},
+};
+
+#ifdef CONFIG_IPW_DEBUG
+static const char *ipw_get_status_code(u16 status)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ipw_status_codes); i++)
+ if (ipw_status_codes[i].status == status)
+ return ipw_status_codes[i].reason;
+ return "Unknown status value.";
+}
+#endif
+
+static void inline average_init(struct average *avg)
+{
+ memset(avg, 0, sizeof(*avg));
+}
+
+static void inline average_add(struct average *avg, s16 val)
+{
+ avg->sum -= avg->entries[avg->pos];
+ avg->sum += val;
+ avg->entries[avg->pos++] = val;
+ if (unlikely(avg->pos == AVG_ENTRIES)) {
+ avg->init = 1;
+ avg->pos = 0;
+ }
+}
+
+static s16 inline average_value(struct average *avg)
+{
+ if (!unlikely(avg->init)) {
+ if (avg->pos)
+ return avg->sum / avg->pos;
+ return 0;
+ }
+
+ return avg->sum / AVG_ENTRIES;
+}
+
+static void ipw_reset_stats(struct ipw_priv *priv)
+{
+ u32 len = sizeof(u32);
+
+ priv->quality = 0;
+
+ average_init(&priv->average_missed_beacons);
+ average_init(&priv->average_rssi);
+ average_init(&priv->average_noise);
+
+ priv->last_rate = 0;
+ priv->last_missed_beacons = 0;
+ priv->last_rx_packets = 0;
+ priv->last_tx_packets = 0;
+ priv->last_tx_failures = 0;
+
+ /* Firmware managed, reset only when NIC is restarted, so we have to
+ * normalize on the current value */
+ ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC,
+ &priv->last_rx_err, &len);
+ ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE,
+ &priv->last_tx_failures, &len);
+
+ /* Driver managed, reset with each association */
+ priv->missed_adhoc_beacons = 0;
+ priv->missed_beacons = 0;
+ priv->tx_packets = 0;
+ priv->rx_packets = 0;
+
+}
+
+static inline u32 ipw_get_max_rate(struct ipw_priv *priv)
+{
+ u32 i = 0x80000000;
+ u32 mask = priv->rates_mask;
+ /* If currently associated in B mode, restrict the maximum
+ * rate match to B rates */
+ if (priv->assoc_request.ieee_mode == IPW_B_MODE)
+ mask &= IEEE80211_CCK_RATES_MASK;
+
+ /* TODO: Verify that the rate is supported by the current rates
+ * list. */
+
+ while (i && !(mask & i))
+ i >>= 1;
+ switch (i) {
+ case IEEE80211_CCK_RATE_1MB_MASK: return 1000000;
+ case IEEE80211_CCK_RATE_2MB_MASK: return 2000000;
+ case IEEE80211_CCK_RATE_5MB_MASK: return 5500000;
+ case IEEE80211_OFDM_RATE_6MB_MASK: return 6000000;
+ case IEEE80211_OFDM_RATE_9MB_MASK: return 9000000;
+ case IEEE80211_CCK_RATE_11MB_MASK: return 11000000;
+ case IEEE80211_OFDM_RATE_12MB_MASK: return 12000000;
+ case IEEE80211_OFDM_RATE_18MB_MASK: return 18000000;
+ case IEEE80211_OFDM_RATE_24MB_MASK: return 24000000;
+ case IEEE80211_OFDM_RATE_36MB_MASK: return 36000000;
+ case IEEE80211_OFDM_RATE_48MB_MASK: return 48000000;
+ case IEEE80211_OFDM_RATE_54MB_MASK: return 54000000;
+ }
+
+ if (priv->ieee->mode == IEEE_B)
+ return 11000000;
+ else
+ return 54000000;
+}
+
+static u32 ipw_get_current_rate(struct ipw_priv *priv)
+{
+ u32 rate, len = sizeof(rate);
+ int err;
+
+ if (!(priv->status & STATUS_ASSOCIATED))
+ return 0;
+
+ if (priv->tx_packets > IPW_REAL_RATE_RX_PACKET_THRESHOLD) {
+ err = ipw_get_ordinal(priv, IPW_ORD_STAT_TX_CURR_RATE, &rate,
+ &len);
+ if (err) {
+ IPW_DEBUG_INFO("failed querying ordinals.\n");
+ return 0;
+ }
+ } else
+ return ipw_get_max_rate(priv);
+
+ switch (rate) {
+ case IPW_TX_RATE_1MB: return 1000000;
+ case IPW_TX_RATE_2MB: return 2000000;
+ case IPW_TX_RATE_5MB: return 5500000;
+ case IPW_TX_RATE_6MB: return 6000000;
+ case IPW_TX_RATE_9MB: return 9000000;
+ case IPW_TX_RATE_11MB: return 11000000;
+ case IPW_TX_RATE_12MB: return 12000000;
+ case IPW_TX_RATE_18MB: return 18000000;
+ case IPW_TX_RATE_24MB: return 24000000;
+ case IPW_TX_RATE_36MB: return 36000000;
+ case IPW_TX_RATE_48MB: return 48000000;
+ case IPW_TX_RATE_54MB: return 54000000;
+ }
+
+ return 0;
+}
+
+#define PERFECT_RSSI (-50)
+#define WORST_RSSI (-85)
+#define IPW_STATS_INTERVAL (2 * HZ)
+static void ipw_gather_stats(struct ipw_priv *priv)
+{
+ u32 rx_err, rx_err_delta, rx_packets_delta;
+ u32 tx_failures, tx_failures_delta, tx_packets_delta;
+ u32 missed_beacons_percent, missed_beacons_delta;
+ u32 quality = 0;
+ u32 len = sizeof(u32);
+ s16 rssi;
+ u32 beacon_quality, signal_quality, tx_quality, rx_quality,
+ rate_quality;
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ priv->quality = 0;
+ return;
+ }
+
+ /* Update the statistics */
+ ipw_get_ordinal(priv, IPW_ORD_STAT_MISSED_BEACONS,
+ &priv->missed_beacons, &len);
+ missed_beacons_delta = priv->missed_beacons - priv->last_missed_beacons;
+ priv->last_missed_beacons = priv->missed_beacons;
+ if (priv->assoc_request.beacon_interval) {
+ missed_beacons_percent = missed_beacons_delta *
+ (HZ * priv->assoc_request.beacon_interval) /
+ (IPW_STATS_INTERVAL * 10);
+ } else {
+ missed_beacons_percent = 0;
+ }
+ average_add(&priv->average_missed_beacons, missed_beacons_percent);
+
+ ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC, &rx_err, &len);
+ rx_err_delta = rx_err - priv->last_rx_err;
+ priv->last_rx_err = rx_err;
+
+ ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE, &tx_failures, &len);
+ tx_failures_delta = tx_failures - priv->last_tx_failures;
+ priv->last_tx_failures = tx_failures;
+
+ rx_packets_delta = priv->rx_packets - priv->last_rx_packets;
+ priv->last_rx_packets = priv->rx_packets;
+
+ tx_packets_delta = priv->tx_packets - priv->last_tx_packets;
+ priv->last_tx_packets = priv->tx_packets;
+
+ /* Calculate quality based on the following:
+ *
+ * Missed beacon: 100% = 0, 0% = 70% missed
+ * Rate: 60% = 1Mbs, 100% = Max
+ * Rx and Tx errors represent a straight % of total Rx/Tx
+ * RSSI: 100% = > -50, 0% = < -80
+ * Rx errors: 100% = 0, 0% = 50% missed
+ *
+ * The lowest computed quality is used.
+ *
+ */
+#define BEACON_THRESHOLD 5
+ beacon_quality = 100 - missed_beacons_percent;
+ if (beacon_quality < BEACON_THRESHOLD)
+ beacon_quality = 0;
+ else
+ beacon_quality = (beacon_quality - BEACON_THRESHOLD) * 100 /
+ (100 - BEACON_THRESHOLD);
+ IPW_DEBUG_STATS("Missed beacon: %3d%% (%d%%)\n",
+ beacon_quality, missed_beacons_percent);
+
+ priv->last_rate = ipw_get_current_rate(priv);
+ rate_quality = priv->last_rate * 40 / priv->last_rate + 60;
+ IPW_DEBUG_STATS("Rate quality : %3d%% (%dMbs)\n",
+ rate_quality, priv->last_rate / 1000000);
+
+ if (rx_packets_delta > 100 && rx_packets_delta + rx_err_delta)
+ rx_quality = 100 - (rx_err_delta * 100) /
+ (rx_packets_delta + rx_err_delta);
+ else
+ rx_quality = 100;
+ IPW_DEBUG_STATS("Rx quality : %3d%% (%u errors, %u packets)\n",
+ rx_quality, rx_err_delta, rx_packets_delta);
+
+ if (tx_packets_delta > 100 && tx_packets_delta + tx_failures_delta)
+ tx_quality = 100 - (tx_failures_delta * 100) /
+ (tx_packets_delta + tx_failures_delta);
+ else
+ tx_quality = 100;
+ IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n",
+ tx_quality, tx_failures_delta, tx_packets_delta);
+
+ rssi = average_value(&priv->average_rssi);
+ if (rssi > PERFECT_RSSI)
+ signal_quality = 100;
+ else if (rssi < WORST_RSSI)
+ signal_quality = 0;
+ else
+ signal_quality = (rssi - WORST_RSSI) * 100 /
+ (PERFECT_RSSI - WORST_RSSI);
+ IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
+ signal_quality, rssi);
+
+ quality = min(beacon_quality,
+ min(rate_quality,
+ min(tx_quality, min(rx_quality, signal_quality))));
+ if (quality == beacon_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n",
+ quality);
+ if (quality == rate_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to rate quality.\n",
+ quality);
+ if (quality == tx_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to Tx quality.\n",
+ quality);
+ if (quality == rx_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to Rx quality.\n",
+ quality);
+ if (quality == signal_quality)
+ IPW_DEBUG_STATS("Quality (%d%%): Clamped to signal quality.\n",
+ quality);
+
+ priv->quality = quality;
+
+ queue_delayed_work(priv->workqueue, &priv->gather_stats,
+ IPW_STATS_INTERVAL);
+}
+
+/**
+ * Handle host notification packet.
+ * Called from interrupt routine
+ */
+static inline void ipw_rx_notification(struct ipw_priv *priv,
+ struct ipw_rx_notification *notif)
+{
+ IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size);
+
+ switch (notif->subtype) {
+ case HOST_NOTIFICATION_STATUS_ASSOCIATED:{
+ struct notif_association *assoc = &notif->u.assoc;
+
+ switch (assoc->state) {
+ case CMAS_ASSOCIATED:{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "associated: '%s' " MAC_FMT
+ " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_INFRA:
+ memcpy(priv->ieee->bssid,
+ priv->bssid, ETH_ALEN);
+ break;
+
+ case IW_MODE_ADHOC:
+ memcpy(priv->ieee->bssid,
+ priv->bssid, ETH_ALEN);
+
+ /* clear out the station table */
+ priv->num_stations = 0;
+
+ IPW_DEBUG_ASSOC
+ ("queueing adhoc check\n");
+ queue_delayed_work(priv->
+ workqueue,
+ &priv->
+ adhoc_check,
+ priv->
+ assoc_request.
+ beacon_interval);
+ break;
+ }
+
+ priv->status &= ~STATUS_ASSOCIATING;
+ priv->status |= STATUS_ASSOCIATED;
+
+ netif_carrier_on(priv->net_dev);
+ if (netif_queue_stopped(priv->net_dev)) {
+ IPW_DEBUG_NOTIF
+ ("waking queue\n");
+ netif_wake_queue(priv->net_dev);
+ } else {
+ IPW_DEBUG_NOTIF
+ ("starting queue\n");
+ netif_start_queue(priv->
+ net_dev);
+ }
+
+ ipw_reset_stats(priv);
+ /* Ensure the rate is updated immediately */
+ priv->last_rate =
+ ipw_get_current_rate(priv);
+ schedule_work(&priv->gather_stats);
+ notify_wx_assoc_event(priv);
+
+/* queue_delayed_work(priv->workqueue,
+ &priv->request_scan,
+ SCAN_ASSOCIATED_INTERVAL);
+*/
+ break;
+ }
+
+ case CMAS_AUTHENTICATED:{
+ if (priv->
+ status & (STATUS_ASSOCIATED |
+ STATUS_AUTH)) {
+#ifdef CONFIG_IPW_DEBUG
+ struct notif_authenticate *auth
+ = &notif->u.auth;
+ IPW_DEBUG(IPW_DL_NOTIF |
+ IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "deauthenticated: '%s' "
+ MAC_FMT
+ ": (0x%04X) - %s \n",
+ escape_essid(priv->
+ essid,
+ priv->
+ essid_len),
+ MAC_ARG(priv->bssid),
+ ntohs(auth->status),
+ ipw_get_status_code
+ (ntohs
+ (auth->status)));
+#endif
+
+ priv->status &=
+ ~(STATUS_ASSOCIATING |
+ STATUS_AUTH |
+ STATUS_ASSOCIATED);
+
+ netif_carrier_off(priv->
+ net_dev);
+ netif_stop_queue(priv->net_dev);
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ notify_wx_assoc_event(priv);
+ break;
+ }
+
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "authenticated: '%s' " MAC_FMT
+ "\n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ break;
+ }
+
+ case CMAS_INIT:{
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "disassociated: '%s' " MAC_FMT
+ " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &=
+ ~(STATUS_DISASSOCIATING |
+ STATUS_ASSOCIATING |
+ STATUS_ASSOCIATED | STATUS_AUTH);
+
+ netif_stop_queue(priv->net_dev);
+ if (!(priv->status & STATUS_ROAMING)) {
+ netif_carrier_off(priv->
+ net_dev);
+ notify_wx_assoc_event(priv);
+
+ /* Cancel any queued work ... */
+ cancel_delayed_work(&priv->
+ request_scan);
+ cancel_delayed_work(&priv->
+ adhoc_check);
+
+ /* Queue up another scan... */
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+
+ cancel_delayed_work(&priv->
+ gather_stats);
+ } else {
+ priv->status |= STATUS_ROAMING;
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ }
+
+ ipw_reset_stats(priv);
+ break;
+ }
+
+ default:
+ IPW_ERROR("assoc: unknown (%d)\n",
+ assoc->state);
+ break;
+ }
+
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_AUTHENTICATE:{
+ struct notif_authenticate *auth = &notif->u.auth;
+ switch (auth->state) {
+ case CMAS_AUTHENTICATED:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "authenticated: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ priv->status |= STATUS_AUTH;
+ break;
+
+ case CMAS_INIT:
+ if (priv->status & STATUS_AUTH) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "authentication failed (0x%04X): %s\n",
+ ntohs(auth->status),
+ ipw_get_status_code(ntohs
+ (auth->
+ status)));
+ }
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "deauthenticated: '%s' " MAC_FMT "\n",
+ escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ priv->status &= ~(STATUS_ASSOCIATING |
+ STATUS_AUTH |
+ STATUS_ASSOCIATED);
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+ notify_wx_assoc_event(priv);
+ break;
+
+ case CMAS_TX_AUTH_SEQ_1:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1\n");
+ break;
+ case CMAS_RX_AUTH_SEQ_2:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_2\n");
+ break;
+ case CMAS_AUTH_SEQ_1_PASS:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1_PASS\n");
+ break;
+ case CMAS_AUTH_SEQ_1_FAIL:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_1_FAIL\n");
+ break;
+ case CMAS_TX_AUTH_SEQ_3:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_3\n");
+ break;
+ case CMAS_RX_AUTH_SEQ_4:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "RX_AUTH_SEQ_4\n");
+ break;
+ case CMAS_AUTH_SEQ_2_PASS:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUTH_SEQ_2_PASS\n");
+ break;
+ case CMAS_AUTH_SEQ_2_FAIL:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "AUT_SEQ_2_FAIL\n");
+ break;
+ case CMAS_TX_ASSOC:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "TX_ASSOC\n");
+ break;
+ case CMAS_RX_ASSOC_RESP:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "RX_ASSOC_RESP\n");
+ break;
+ case CMAS_ASSOCIATED:
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC, "ASSOCIATED\n");
+ break;
+ default:
+ IPW_DEBUG_NOTIF("auth: failure - %d\n",
+ auth->state);
+ break;
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT:{
+ struct notif_channel_result *x =
+ &notif->u.channel_result;
+
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG_SCAN("Scan result for channel %d\n",
+ x->channel_num);
+ } else {
+ IPW_DEBUG_SCAN("Scan result of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_SCAN_COMPLETED:{
+ struct notif_scan_complete *x = &notif->u.scan_complete;
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG_SCAN
+ ("Scan completed: type %d, %d channels, "
+ "%d status\n", x->scan_type,
+ x->num_channels, x->status);
+ } else {
+ IPW_ERROR("Scan completed of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+
+ priv->status &=
+ ~(STATUS_SCANNING | STATUS_SCAN_ABORTING);
+
+ cancel_delayed_work(&priv->scan_check);
+
+ if (!(priv->status & (STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING |
+ STATUS_ROAMING |
+ STATUS_DISASSOCIATING)))
+ queue_work(priv->workqueue, &priv->associate);
+ else if (priv->status & STATUS_ROAMING) {
+ /* If a scan completed and we are in roam mode, then
+ * the scan that completed was the one requested as a
+ * result of entering roam... so, schedule the
+ * roam work */
+ queue_work(priv->workqueue, &priv->roam);
+ } else if (priv->status & STATUS_SCAN_PENDING)
+ queue_work(priv->workqueue,
+ &priv->request_scan);
+
+ priv->ieee->scans++;
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{
+ struct notif_frag_length *x = &notif->u.frag_len;
+
+ if (notif->size == sizeof(*x)) {
+ IPW_ERROR("Frag length: %d\n", x->frag_length);
+ } else {
+ IPW_ERROR("Frag length of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_LINK_DETERIORATION:{
+ struct notif_link_deterioration *x =
+ &notif->u.link_deterioration;
+ if (notif->size == sizeof(*x)) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "link deterioration: '%s' " MAC_FMT
+ " \n", escape_essid(priv->essid,
+ priv->essid_len),
+ MAC_ARG(priv->bssid));
+ memcpy(&priv->last_link_deterioration, x,
+ sizeof(*x));
+ } else {
+ IPW_ERROR("Link Deterioration of wrong size %d "
+ "(should be %zd)\n",
+ notif->size, sizeof(*x));
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_DINO_CONFIG_RESPONSE:{
+ IPW_ERROR("Dino config\n");
+ if (priv->hcmd
+ && priv->hcmd->cmd == HOST_CMD_DINO_CONFIG) {
+ /* TODO: Do anything special? */
+ } else {
+ IPW_ERROR("Unexpected DINO_CONFIG_RESPONSE\n");
+ }
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_BEACON_STATE:{
+ struct notif_beacon_state *x = &notif->u.beacon_state;
+ if (notif->size != sizeof(*x)) {
+ IPW_ERROR
+ ("Beacon state of wrong size %d (should "
+ "be %zd)\n", notif->size, sizeof(*x));
+ break;
+ }
+
+ if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING) {
+ if (priv->status & STATUS_SCANNING) {
+ /* Stop scan to keep fw from getting
+ * stuck... */
+ queue_work(priv->workqueue,
+ &priv->abort_scan);
+ }
+
+ if (x->number > priv->missed_beacon_threshold &&
+ priv->status & STATUS_ASSOCIATED) {
+ IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
+ IPW_DL_STATE,
+ "Missed beacon: %d - disassociate\n",
+ x->number);
+ queue_work(priv->workqueue,
+ &priv->disassociate);
+ } else if (x->number > priv->roaming_threshold) {
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
+ "Missed beacon: %d - initiate "
+ "roaming\n", x->number);
+ queue_work(priv->workqueue,
+ &priv->roam);
+ } else {
+ IPW_DEBUG_NOTIF("Missed beacon: %d\n",
+ x->number);
+ }
+
+ priv->notif_missed_beacons = x->number;
+
+ }
+
+ break;
+ }
+
+ case HOST_NOTIFICATION_STATUS_TGI_TX_KEY:{
+ struct notif_tgi_tx_key *x = &notif->u.tgi_tx_key;
+ if (notif->size == sizeof(*x)) {
+ IPW_ERROR("TGi Tx Key: state 0x%02x sec type "
+ "0x%02x station %d\n",
+ x->key_state, x->security_type,
+ x->station_index);
+ break;
+ }
+
+ IPW_ERROR
+ ("TGi Tx Key of wrong size %d (should be %zd)\n",
+ notif->size, sizeof(*x));
+ break;
+ }
+
+ case HOST_NOTIFICATION_CALIB_KEEP_RESULTS:{
+ struct notif_calibration *x = &notif->u.calibration;
+
+ if (notif->size == sizeof(*x)) {
+ memcpy(&priv->calib, x, sizeof(*x));
+ IPW_DEBUG_INFO("TODO: Calibration\n");
+ break;
+ }
+
+ IPW_ERROR
+ ("Calibration of wrong size %d (should be %zd)\n",
+ notif->size, sizeof(*x));
+ break;
+ }
+
+ case HOST_NOTIFICATION_NOISE_STATS:{
+ if (notif->size == sizeof(u32)) {
+ priv->last_noise =
+ (u8) (notif->u.noise.value & 0xff);
+ average_add(&priv->average_noise,
+ priv->last_noise);
+ break;
+ }
+
+ IPW_ERROR
+ ("Noise stat is wrong size %d (should be %zd)\n",
+ notif->size, sizeof(u32));
+ break;
+ }
+
+ default:
+ IPW_ERROR("Unknown notification: "
+ "subtype=%d,flags=0x%2x,size=%d\n",
+ notif->subtype, notif->flags, notif->size);
+ }
+}
+
+/**
+ * Destroys all DMA structures and initialise them again
+ *
+ * @param priv
+ * @return error code
+ */
+static int ipw_queue_reset(struct ipw_priv *priv)
+{
+ int rc = 0;
+ /** @todo customize queue sizes */
+ int nTx = 64, nTxCmd = 8;
+ ipw_tx_queue_free(priv);
+ /* Tx CMD queue */
+ rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd,
+ CX2_TX_CMD_QUEUE_READ_INDEX,
+ CX2_TX_CMD_QUEUE_WRITE_INDEX,
+ CX2_TX_CMD_QUEUE_BD_BASE,
+ CX2_TX_CMD_QUEUE_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx Cmd queue init failed\n");
+ goto error;
+ }
+ /* Tx queue(s) */
+ rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx,
+ CX2_TX_QUEUE_0_READ_INDEX,
+ CX2_TX_QUEUE_0_WRITE_INDEX,
+ CX2_TX_QUEUE_0_BD_BASE, CX2_TX_QUEUE_0_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 0 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx,
+ CX2_TX_QUEUE_1_READ_INDEX,
+ CX2_TX_QUEUE_1_WRITE_INDEX,
+ CX2_TX_QUEUE_1_BD_BASE, CX2_TX_QUEUE_1_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 1 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx,
+ CX2_TX_QUEUE_2_READ_INDEX,
+ CX2_TX_QUEUE_2_WRITE_INDEX,
+ CX2_TX_QUEUE_2_BD_BASE, CX2_TX_QUEUE_2_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 2 queue init failed\n");
+ goto error;
+ }
+ rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx,
+ CX2_TX_QUEUE_3_READ_INDEX,
+ CX2_TX_QUEUE_3_WRITE_INDEX,
+ CX2_TX_QUEUE_3_BD_BASE, CX2_TX_QUEUE_3_BD_SIZE);
+ if (rc) {
+ IPW_ERROR("Tx 3 queue init failed\n");
+ goto error;
+ }
+ /* statistics */
+ priv->rx_bufs_min = 0;
+ priv->rx_pend_max = 0;
+ return rc;
+
+ error:
+ ipw_tx_queue_free(priv);
+ return rc;
+}
+
+/**
+ * Reclaim Tx queue entries no more used by NIC.
+ *
+ * When FW adwances 'R' index, all entries between old and
+ * new 'R' index need to be reclaimed. As result, some free space
+ * forms. If there is enough free space (> low mark), wake Tx queue.
+ *
+ * @note Need to protect against garbage in 'R' index
+ * @param priv
+ * @param txq
+ * @param qindex
+ * @return Number of used entries remains in the queue
+ */
+static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
+ struct clx2_tx_queue *txq, int qindex)
+{
+ u32 hw_tail;
+ int used;
+ struct clx2_queue *q = &txq->q;
+
+ hw_tail = ipw_read32(priv, q->reg_r);
+ if (hw_tail >= q->n_bd) {
+ IPW_ERROR
+ ("Read index for DMA queue (%d) is out of range [0-%d)\n",
+ hw_tail, q->n_bd);
+ goto done;
+ }
+ for (; q->last_used != hw_tail;
+ q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) {
+ ipw_queue_tx_free_tfd(priv, txq);
+ priv->tx_packets++;
+ }
+ done:
+ if (ipw_queue_space(q) > q->low_mark && qindex >= 0) {
+ __maybe_wake_tx(priv);
+ }
+ used = q->first_empty - q->last_used;
+ if (used < 0)
+ used += q->n_bd;
+
+ return used;
+}
+
+static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf,
+ int len, int sync)
+{
+ struct clx2_tx_queue *txq = &priv->txq_cmd;
+ struct clx2_queue *q = &txq->q;
+ struct tfd_frame *tfd;
+
+ if (ipw_queue_space(q) < (sync ? 1 : 2)) {
+ IPW_ERROR("No space for Tx\n");
+ return -EBUSY;
+ }
+
+ tfd = &txq->bd[q->first_empty];
+ txq->txb[q->first_empty] = NULL;
+
+ memset(tfd, 0, sizeof(*tfd));
+ tfd->control_flags.message_type = TX_HOST_COMMAND_TYPE;
+ tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK;
+ priv->hcmd_seq++;
+ tfd->u.cmd.index = hcmd;
+ tfd->u.cmd.length = len;
+ memcpy(tfd->u.cmd.payload, buf, len);
+ q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
+ ipw_write32(priv, q->reg_w, q->first_empty);
+ _ipw_read32(priv, 0x90);
+
+ return 0;
+}
+
+/*
+ * Rx theory of operation
+ *
+ * The host allocates 32 DMA target addresses and passes the host address
+ * to the firmware at register CX2_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
+ * 0 to 31
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer it will advance the READ index
+ * and fire the RX interrupt. The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free. When
+ * ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ * to replensish the ipw->rxq->rx_free.
+ * + In ipw_rx_queue_replenish (scheduled) if 'processed' != 'read' then the
+ * ipw->rxq is replenished and the READ INDEX is updated (updating the
+ * 'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ * detached from the ipw->rxq. The driver 'processed' index is updated.
+ * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free
+ * list. If there are no allocated buffers in ipw->rxq->rx_free, the READ
+ * INDEX is not incremented and ipw->status(RX_STALLED) is set. If there
+ * were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * ipw_rx_queue_alloc() Allocates rx_free
+ * ipw_rx_queue_replenish() Replenishes rx_free list from rx_used, and calls
+ * ipw_rx_queue_restock
+ * ipw_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * queue, updates firmware pointers, and updates
+ * the WRITE index. If insufficient rx_free buffers
+ * are available, schedules ipw_rx_queue_replenish
+ *
+ * -- enable interrupts --
+ * ISR - ipw_rx() Detach ipw_rx_mem_buffers from pool up to the
+ * READ INDEX, detaching the SKB from the pool.
+ * Moves the packet buffer from queue to rx_used.
+ * Calls ipw_rx_queue_restock to refill any empty
+ * slots.
+ * ...
+ *
+ */
+
+/*
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void ipw_rx_queue_restock(struct ipw_priv *priv)
+{
+ struct ipw_rx_queue *rxq = priv->rxq;
+ struct list_head *element;
+ struct ipw_rx_mem_buffer *rxb;
+ unsigned long flags;
+ int write;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ write = rxq->write;
+ while ((rxq->write != rxq->processed) && (rxq->free_count)) {
+ element = rxq->rx_free.next;
+ rxb = list_entry(element, struct ipw_rx_mem_buffer, list);
+ list_del(element);
+
+ ipw_write32(priv, CX2_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE,
+ rxb->dma_addr);
+ rxq->queue[rxq->write] = rxb;
+ rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE;
+ rxq->free_count--;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ /* If the pre-allocated buffer pool is dropping low, schedule to
+ * refill it */
+ if (rxq->free_count <= RX_LOW_WATERMARK)
+ queue_work(priv->workqueue, &priv->rx_replenish);
+
+ /* If we've added more space for the firmware to place data, tell it */
+ if (write != rxq->write)
+ ipw_write32(priv, CX2_RX_WRITE_INDEX, rxq->write);
+}
+
+/*
+ * Move all used packet from rx_used to rx_free, allocating a new SKB for each.
+ * Also restock the Rx queue via ipw_rx_queue_restock.
+ *
+ * This is called as a scheduled work item (except for during intialization)
+ */
+static void ipw_rx_queue_replenish(void *data)
+{
+ struct ipw_priv *priv = data;
+ struct ipw_rx_queue *rxq = priv->rxq;
+ struct list_head *element;
+ struct ipw_rx_mem_buffer *rxb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ while (!list_empty(&rxq->rx_used)) {
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct ipw_rx_mem_buffer, list);
+ rxb->skb = alloc_skb(CX2_RX_BUF_SIZE, GFP_ATOMIC);
+ if (!rxb->skb) {
+ printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n",
+ priv->net_dev->name);
+ /* We don't reschedule replenish work here -- we will
+ * call the restock method and if it still needs
+ * more buffers it will schedule replenish */
+ break;
+ }
+ list_del(element);
+
+ rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data;
+ rxb->dma_addr =
+ pci_map_single(priv->pci_dev, rxb->skb->data,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ ipw_rx_queue_restock(priv);
+}
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+static void ipw_rx_queue_free(struct ipw_priv *priv, struct ipw_rx_queue *rxq)
+{
+ int i;
+
+ if (!rxq)
+ return;
+
+ for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+ }
+
+ kfree(rxq);
+}
+
+static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv)
+{
+ struct ipw_rx_queue *rxq;
+ int i;
+
+ rxq = (struct ipw_rx_queue *)kmalloc(sizeof(*rxq), GFP_KERNEL);
+ if (unlikely(!rxq)) {
+ IPW_ERROR("memory allocation failed\n");
+ return NULL;
+ }
+ memset(rxq, 0, sizeof(*rxq));
+ spin_lock_init(&rxq->lock);
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
+ /* Set us so that we have processed and used all buffers, but have
+ * not restocked the Rx queue with fresh buffers */
+ rxq->read = rxq->write = 0;
+ rxq->processed = RX_QUEUE_SIZE - 1;
+ rxq->free_count = 0;
+
+ return rxq;
+}
+
+static int ipw_is_rate_in_mask(struct ipw_priv *priv, int ieee_mode, u8 rate)
+{
+ rate &= ~IEEE80211_BASIC_RATE_MASK;
+ if (ieee_mode == IEEE_A) {
+ switch (rate) {
+ case IEEE80211_OFDM_RATE_6MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ?
+ 1 : 0;
+ case IEEE80211_OFDM_RATE_9MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ?
+ 1 : 0;
+ case IEEE80211_OFDM_RATE_12MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_18MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_24MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_36MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_48MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_54MB:
+ return priv->
+ rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
+ default:
+ return 0;
+ }
+ }
+
+ /* B and G mixed */
+ switch (rate) {
+ case IEEE80211_CCK_RATE_1MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_1MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_2MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_2MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_5MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_5MB_MASK ? 1 : 0;
+ case IEEE80211_CCK_RATE_11MB:
+ return priv->rates_mask & IEEE80211_CCK_RATE_11MB_MASK ? 1 : 0;
+ }
+
+ /* If we are limited to B modulations, bail at this point */
+ if (ieee_mode == IEEE_B)
+ return 0;
+
+ /* G */
+ switch (rate) {
+ case IEEE80211_OFDM_RATE_6MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_9MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_12MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_18MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_24MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_36MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_48MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
+ case IEEE80211_OFDM_RATE_54MB:
+ return priv->rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
+ }
+
+ return 0;
+}
+
+static int ipw_compatible_rates(struct ipw_priv *priv,
+ const struct ieee80211_network *network,
+ struct ipw_supported_rates *rates)
+{
+ int num_rates, i;
+
+ memset(rates, 0, sizeof(*rates));
+ num_rates = min(network->rates_len, (u8) IPW_MAX_RATES);
+ rates->num_rates = 0;
+ for (i = 0; i < num_rates; i++) {
+ if (!ipw_is_rate_in_mask
+ (priv, network->mode, network->rates[i])) {
+ IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
+ network->rates[i], priv->rates_mask);
+ continue;
+ }
+
+ rates->supported_rates[rates->num_rates++] = network->rates[i];
+ }
+
+ num_rates =
+ min(network->rates_ex_len, (u8) (IPW_MAX_RATES - num_rates));
+ for (i = 0; i < num_rates; i++) {
+ if (!ipw_is_rate_in_mask
+ (priv, network->mode, network->rates_ex[i])) {
+ IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
+ network->rates_ex[i], priv->rates_mask);
+ continue;
+ }
+
+ rates->supported_rates[rates->num_rates++] =
+ network->rates_ex[i];
+ }
+
+ return rates->num_rates;
+}
+
+static inline void ipw_copy_rates(struct ipw_supported_rates *dest,
+ const struct ipw_supported_rates *src)
+{
+ u8 i;
+ for (i = 0; i < src->num_rates; i++)
+ dest->supported_rates[i] = src->supported_rates[i];
+ dest->num_rates = src->num_rates;
+}
+
+/* TODO: Look at sniffed packets in the air to determine if the basic rate
+ * mask should ever be used -- right now all callers to add the scan rates are
+ * set with the modulation = CCK, so BASIC_RATE_MASK is never set... */
+static void ipw_add_cck_scan_rates(struct ipw_supported_rates *rates,
+ u8 modulation, u32 rate_mask)
+{
+ u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ?
+ IEEE80211_BASIC_RATE_MASK : 0;
+
+ if (rate_mask & IEEE80211_CCK_RATE_1MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_2MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_5MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_CCK_RATE_5MB;
+
+ if (rate_mask & IEEE80211_CCK_RATE_11MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_CCK_RATE_11MB;
+}
+
+static void ipw_add_ofdm_scan_rates(struct ipw_supported_rates *rates,
+ u8 modulation, u32 rate_mask)
+{
+ u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ?
+ IEEE80211_BASIC_RATE_MASK : 0;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_6MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_6MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_9MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_9MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_12MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_12MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_18MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_18MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_24MB_MASK)
+ rates->supported_rates[rates->num_rates++] = basic_mask |
+ IEEE80211_OFDM_RATE_24MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_36MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_36MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_48MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_48MB;
+
+ if (rate_mask & IEEE80211_OFDM_RATE_54MB_MASK)
+ rates->supported_rates[rates->num_rates++] =
+ IEEE80211_OFDM_RATE_54MB;
+}
+
+struct ipw_network_match {
+ struct ieee80211_network *network;
+ struct ipw_supported_rates rates;
+};
+
+static int ipw_best_network(struct ipw_priv *priv,
+ struct ipw_network_match *match,
+ struct ieee80211_network *network, int roaming)
+{
+ struct ipw_supported_rates rates;
+
+ /* Verify that this network's capability is compatible with the
+ * current mode (AdHoc or Infrastructure) */
+ if ((priv->ieee->iw_mode == IW_MODE_INFRA &&
+ !(network->capability & WLAN_CAPABILITY_ESS)) ||
+ (priv->ieee->iw_mode == IW_MODE_ADHOC &&
+ !(network->capability & WLAN_CAPABILITY_IBSS))) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded due to "
+ "capability mismatch.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ /* If we do not have an ESSID for this AP, we can not associate with
+ * it */
+ if (network->flags & NETWORK_EMPTY_ESSID) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of hidden ESSID.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ if (unlikely(roaming)) {
+ /* If we are roaming, then ensure check if this is a valid
+ * network to try and roam to */
+ if ((network->ssid_len != match->network->ssid_len) ||
+ memcmp(network->ssid, match->network->ssid,
+ network->ssid_len)) {
+ IPW_DEBUG_ASSOC("Netowrk '%s (" MAC_FMT ")' excluded "
+ "because of non-network ESSID.\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+ } else {
+ /* If an ESSID has been configured then compare the broadcast
+ * ESSID to ours */
+ if ((priv->config & CFG_STATIC_ESSID) &&
+ ((network->ssid_len != priv->essid_len) ||
+ memcmp(network->ssid, priv->essid,
+ min(network->ssid_len, priv->essid_len)))) {
+ char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+ strncpy(escaped,
+ escape_essid(network->ssid, network->ssid_len),
+ sizeof(escaped));
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of ESSID mismatch: '%s'.\n",
+ escaped, MAC_ARG(network->bssid),
+ escape_essid(priv->essid,
+ priv->essid_len));
+ return 0;
+ }
+ }
+
+ /* If the old network rate is better than this one, don't bother
+ * testing everything else. */
+ if (match->network && match->network->stats.rssi > network->stats.rssi) {
+ char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+ strncpy(escaped,
+ escape_essid(network->ssid, network->ssid_len),
+ sizeof(escaped));
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded because "
+ "'%s (" MAC_FMT ")' has a stronger signal.\n",
+ escaped, MAC_ARG(network->bssid),
+ escape_essid(match->network->ssid,
+ match->network->ssid_len),
+ MAC_ARG(match->network->bssid));
+ return 0;
+ }
+
+ /* If this network has already had an association attempt within the
+ * last 3 seconds, do not try and associate again... */
+ if (network->last_associate &&
+ time_after(network->last_associate + (HZ * 5UL), jiffies)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of storming (%lu since last "
+ "assoc attempt).\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ (jiffies - network->last_associate) / HZ);
+ return 0;
+ }
+
+ /* Now go through and see if the requested network is valid... */
+ if (priv->ieee->scan_age != 0 &&
+ jiffies - network->last_scanned > priv->ieee->scan_age) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of age: %lums.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ (jiffies - network->last_scanned) / (HZ / 100));
+ return 0;
+ }
+
+ if ((priv->config & CFG_STATIC_CHANNEL) &&
+ (network->channel != priv->channel)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of channel mismatch: %d != %d.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ network->channel, priv->channel);
+ return 0;
+ }
+
+ /* Verify privacy compatability */
+ if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
+ ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of privacy mismatch: %s != %s.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid),
+ priv->capability & CAP_PRIVACY_ON ? "on" :
+ "off",
+ network->capability &
+ WLAN_CAPABILITY_PRIVACY ? "on" : "off");
+ return 0;
+ }
+
+ if ((priv->config & CFG_STATIC_BSSID) &&
+ memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of BSSID mismatch: " MAC_FMT ".\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid), MAC_ARG(priv->bssid));
+ return 0;
+ }
+
+ /* Filter out any incompatible freq / mode combinations */
+ if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of invalid frequency/mode "
+ "combination.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ ipw_compatible_rates(priv, network, &rates);
+ if (rates.num_rates == 0) {
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
+ "because of no compatible rates.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+ return 0;
+ }
+
+ /* TODO: Perform any further minimal comparititive tests. We do not
+ * want to put too much policy logic here; intelligent scan selection
+ * should occur within a generic IEEE 802.11 user space tool. */
+
+ /* Set up 'new' AP to this network */
+ ipw_copy_rates(&match->rates, &rates);
+ match->network = network;
+
+ IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' is a viable match.\n",
+ escape_essid(network->ssid, network->ssid_len),
+ MAC_ARG(network->bssid));
+
+ return 1;
+}
+
+static void ipw_adhoc_create(struct ipw_priv *priv,
+ struct ieee80211_network *network)
+{
+ /*
+ * For the purposes of scanning, we can set our wireless mode
+ * to trigger scans across combinations of bands, but when it
+ * comes to creating a new ad-hoc network, we have tell the FW
+ * exactly which band to use.
+ *
+ * We also have the possibility of an invalid channel for the
+ * chossen band. Attempting to create a new ad-hoc network
+ * with an invalid channel for wireless mode will trigger a
+ * FW fatal error.
+ */
+ network->mode = is_valid_channel(priv->ieee->mode, priv->channel);
+ if (network->mode) {
+ network->channel = priv->channel;
+ } else {
+ IPW_WARNING("Overriding invalid channel\n");
+ if (priv->ieee->mode & IEEE_A) {
+ network->mode = IEEE_A;
+ priv->channel = band_a_active_channel[0];
+ } else if (priv->ieee->mode & IEEE_G) {
+ network->mode = IEEE_G;
+ priv->channel = band_b_active_channel[0];
+ } else {
+ network->mode = IEEE_B;
+ priv->channel = band_b_active_channel[0];
+ }
+ }
+
+ network->channel = priv->channel;
+ priv->config |= CFG_ADHOC_PERSIST;
+ ipw_create_bssid(priv, network->bssid);
+ network->ssid_len = priv->essid_len;
+ memcpy(network->ssid, priv->essid, priv->essid_len);
+ memset(&network->stats, 0, sizeof(network->stats));
+ network->capability = WLAN_CAPABILITY_IBSS;
+ if (priv->capability & CAP_PRIVACY_ON)
+ network->capability |= WLAN_CAPABILITY_PRIVACY;
+ network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH);
+ memcpy(network->rates, priv->rates.supported_rates, network->rates_len);
+ network->rates_ex_len = priv->rates.num_rates - network->rates_len;
+ memcpy(network->rates_ex,
+ &priv->rates.supported_rates[network->rates_len],
+ network->rates_ex_len);
+ network->last_scanned = 0;
+ network->flags = 0;
+ network->last_associate = 0;
+ network->time_stamp[0] = 0;
+ network->time_stamp[1] = 0;
+ network->beacon_interval = 100; /* Default */
+ network->listen_interval = 10; /* Default */
+ network->atim_window = 0; /* Default */
+#ifdef CONFIG_IEEE80211_WPA
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+#endif /* CONFIG_IEEE80211_WPA */
+}
+
+static void ipw_send_wep_keys(struct ipw_priv *priv)
+{
+ struct ipw_wep_key *key;
+ int i;
+ struct host_cmd cmd = {
+ .cmd = IPW_CMD_WEP_KEY,
+ .len = sizeof(*key)
+ };
+
+ key = (struct ipw_wep_key *)&cmd.param;
+ key->cmd_id = DINO_CMD_WEP_KEY;
+ key->seq_num = 0;
+
+ for (i = 0; i < 4; i++) {
+ key->key_index = i;
+ if (!(priv->sec.flags & (1 << i))) {
+ key->key_size = 0;
+ } else {
+ key->key_size = priv->sec.key_sizes[i];
+ memcpy(key->key, priv->sec.keys[i], key->key_size);
+ }
+
+ if (ipw_send_cmd(priv, &cmd)) {
+ IPW_ERROR("failed to send WEP_KEY command\n");
+ return;
+ }
+ }
+}
+
+static void ipw_adhoc_check(void *data)
+{
+ struct ipw_priv *priv = data;
+
+ if (priv->missed_adhoc_beacons++ > priv->missed_beacon_threshold &&
+ !(priv->config & CFG_ADHOC_PERSIST)) {
+ IPW_DEBUG_SCAN("Disassociating due to missed beacons\n");
+ ipw_remove_current_network(priv);
+ ipw_disassociate(priv);
+ return;
+ }
+
+ queue_delayed_work(priv->workqueue, &priv->adhoc_check,
+ priv->assoc_request.beacon_interval);
+}
+
+#ifdef CONFIG_IPW_DEBUG
+static void ipw_debug_config(struct ipw_priv *priv)
+{
+ IPW_DEBUG_INFO("Scan completed, no valid APs matched "
+ "[CFG 0x%08X]\n", priv->config);
+ if (priv->config & CFG_STATIC_CHANNEL)
+ IPW_DEBUG_INFO("Channel locked to %d\n", priv->channel);
+ else
+ IPW_DEBUG_INFO("Channel unlocked.\n");
+ if (priv->config & CFG_STATIC_ESSID)
+ IPW_DEBUG_INFO("ESSID locked to '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ else
+ IPW_DEBUG_INFO("ESSID unlocked.\n");
+ if (priv->config & CFG_STATIC_BSSID)
+ IPW_DEBUG_INFO("BSSID locked to %d\n", priv->channel);
+ else
+ IPW_DEBUG_INFO("BSSID unlocked.\n");
+ if (priv->capability & CAP_PRIVACY_ON)
+ IPW_DEBUG_INFO("PRIVACY on\n");
+ else
+ IPW_DEBUG_INFO("PRIVACY off\n");
+ IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask);
+}
+#else
+#define ipw_debug_config(x) do {} while (0)
+#endif
+
+static inline void ipw_set_fixed_rate(struct ipw_priv *priv,
+ struct ieee80211_network *network)
+{
+ /* TODO: Verify that this works... */
+ struct ipw_fixed_rate fr = {
+ .tx_rates = priv->rates_mask
+ };
+ u32 reg;
+ u16 mask = 0;
+
+ /* Identify 'current FW band' and match it with the fixed
+ * Tx rates */
+
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_52GHZ_BAND: /* A only */
+ /* IEEE_A */
+ if (priv->rates_mask & ~IEEE80211_OFDM_RATES_MASK) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ break;
+ }
+
+ fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A;
+ break;
+
+ default: /* 2.4Ghz or Mixed */
+ /* IEEE_B */
+ if (network->mode == IEEE_B) {
+ if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ }
+ break;
+ }
+
+ /* IEEE_G */
+ if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK |
+ IEEE80211_OFDM_RATES_MASK)) {
+ /* Invalid fixed rate mask */
+ fr.tx_rates = 0;
+ break;
+ }
+
+ if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK;
+ }
+
+ if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK;
+ }
+
+ if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) {
+ mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1);
+ fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK;
+ }
+
+ fr.tx_rates |= mask;
+ break;
+ }
+
+ reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE);
+ ipw_write_reg32(priv, reg, *(u32 *) & fr);
+}
+
+static int ipw_associate_network(struct ipw_priv *priv,
+ struct ieee80211_network *network,
+ struct ipw_supported_rates *rates, int roaming)
+{
+ int err;
+
+ if (priv->config & CFG_FIXED_RATE)
+ ipw_set_fixed_rate(priv, network);
+
+ if (!(priv->config & CFG_STATIC_ESSID)) {
+ priv->essid_len = min(network->ssid_len,
+ (u8) IW_ESSID_MAX_SIZE);
+ memcpy(priv->essid, network->ssid, priv->essid_len);
+ }
+
+ network->last_associate = jiffies;
+
+ memset(&priv->assoc_request, 0, sizeof(priv->assoc_request));
+ priv->assoc_request.channel = network->channel;
+ if ((priv->capability & CAP_PRIVACY_ON) &&
+ (priv->capability & CAP_SHARED_KEY)) {
+ priv->assoc_request.auth_type = AUTH_SHARED_KEY;
+ priv->assoc_request.auth_key = priv->sec.active_key;
+ } else {
+ priv->assoc_request.auth_type = AUTH_OPEN;
+ priv->assoc_request.auth_key = 0;
+ }
+
+ if (priv->capability & CAP_PRIVACY_ON)
+ ipw_send_wep_keys(priv);
+
+ /*
+ * It is valid for our ieee device to support multiple modes, but
+ * when it comes to associating to a given network we have to choose
+ * just one mode.
+ */
+ if (network->mode & priv->ieee->mode & IEEE_A)
+ priv->assoc_request.ieee_mode = IPW_A_MODE;
+ else if (network->mode & priv->ieee->mode & IEEE_G)
+ priv->assoc_request.ieee_mode = IPW_G_MODE;
+ else if (network->mode & priv->ieee->mode & IEEE_B)
+ priv->assoc_request.ieee_mode = IPW_B_MODE;
+
+ IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, "
+ "802.11%c [%d], enc=%s%s%s%c%c\n",
+ roaming ? "Rea" : "A",
+ escape_essid(priv->essid, priv->essid_len),
+ network->channel,
+ ipw_modes[priv->assoc_request.ieee_mode],
+ rates->num_rates,
+ priv->capability & CAP_PRIVACY_ON ? "on " : "off",
+ priv->capability & CAP_PRIVACY_ON ?
+ (priv->capability & CAP_SHARED_KEY ? "(shared)" :
+ "(open)") : "",
+ priv->capability & CAP_PRIVACY_ON ? " key=" : "",
+ priv->capability & CAP_PRIVACY_ON ?
+ '1' + priv->sec.active_key : '.',
+ priv->capability & CAP_PRIVACY_ON ? '.' : ' ');
+
+ priv->assoc_request.beacon_interval = network->beacon_interval;
+ if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+ (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) {
+ priv->assoc_request.assoc_type = HC_IBSS_START;
+ priv->assoc_request.assoc_tsf_msw = 0;
+ priv->assoc_request.assoc_tsf_lsw = 0;
+ } else {
+ if (unlikely(roaming))
+ priv->assoc_request.assoc_type = HC_REASSOCIATE;
+ else
+ priv->assoc_request.assoc_type = HC_ASSOCIATE;
+ priv->assoc_request.assoc_tsf_msw = network->time_stamp[1];
+ priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0];
+ }
+
+ memcpy(&priv->assoc_request.bssid, network->bssid, ETH_ALEN);
+
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
+ memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN);
+ priv->assoc_request.atim_window = network->atim_window;
+ } else {
+ memcpy(&priv->assoc_request.dest, network->bssid, ETH_ALEN);
+ priv->assoc_request.atim_window = 0;
+ }
+
+ priv->assoc_request.capability = network->capability;
+ priv->assoc_request.listen_interval = network->listen_interval;
+
+ err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send SSID command failed.\n");
+ return err;
+ }
+
+ rates->ieee_mode = priv->assoc_request.ieee_mode;
+ rates->purpose = IPW_RATE_CONNECT;
+ ipw_send_supported_rates(priv, rates);
+
+ if (priv->assoc_request.ieee_mode == IPW_G_MODE)
+ priv->sys_config.dot11g_auto_detection = 1;
+ else
+ priv->sys_config.dot11g_auto_detection = 0;
+ err = ipw_send_system_config(priv, &priv->sys_config);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send sys config command failed.\n");
+ return err;
+ }
+
+ IPW_DEBUG_ASSOC("Association sensitivity: %d\n", network->stats.rssi);
+ err = ipw_set_sensitivity(priv, network->stats.rssi);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send associate command failed.\n");
+ return err;
+ }
+
+ /*
+ * If preemption is enabled, it is possible for the association
+ * to complete before we return from ipw_send_associate. Therefore
+ * we have to be sure and update our priviate data first.
+ */
+ priv->channel = network->channel;
+ memcpy(priv->bssid, network->bssid, ETH_ALEN);
+ priv->status |= STATUS_ASSOCIATING;
+ priv->status &= ~STATUS_SECURITY_UPDATED;
+
+ priv->assoc_network = network;
+
+ err = ipw_send_associate(priv, &priv->assoc_request);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send associate command failed.\n");
+ return err;
+ }
+
+ IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
+ escape_essid(priv->essid, priv->essid_len),
+ MAC_ARG(priv->bssid));
+
+ return 0;
+}
+
+static void ipw_roam(void *data)
+{
+ struct ipw_priv *priv = data;
+ struct ieee80211_network *network = NULL;
+ struct ipw_network_match match = {
+ .network = priv->assoc_network
+ };
+
+ /* The roaming process is as follows:
+ *
+ * 1. Missed beacon threshold triggers the roaming process by
+ * setting the status ROAM bit and requesting a scan.
+ * 2. When the scan completes, it schedules the ROAM work
+ * 3. The ROAM work looks at all of the known networks for one that
+ * is a better network than the currently associated. If none
+ * found, the ROAM process is over (ROAM bit cleared)
+ * 4. If a better network is found, a disassociation request is
+ * sent.
+ * 5. When the disassociation completes, the roam work is again
+ * scheduled. The second time through, the driver is no longer
+ * associated, and the newly selected network is sent an
+ * association request.
+ * 6. At this point ,the roaming process is complete and the ROAM
+ * status bit is cleared.
+ */
+
+ /* If we are no longer associated, and the roaming bit is no longer
+ * set, then we are not actively roaming, so just return */
+ if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ROAMING)))
+ return;
+
+ if (priv->status & STATUS_ASSOCIATED) {
+ /* First pass through ROAM process -- look for a better
+ * network */
+ u8 rssi = priv->assoc_network->stats.rssi;
+ priv->assoc_network->stats.rssi = -128;
+ list_for_each_entry(network, &priv->ieee->network_list, list) {
+ if (network != priv->assoc_network)
+ ipw_best_network(priv, &match, network, 1);
+ }
+ priv->assoc_network->stats.rssi = rssi;
+
+ if (match.network == priv->assoc_network) {
+ IPW_DEBUG_ASSOC("No better APs in this network to "
+ "roam to.\n");
+ priv->status &= ~STATUS_ROAMING;
+ ipw_debug_config(priv);
+ return;
+ }
+
+ ipw_send_disassociate(priv, 1);
+ priv->assoc_network = match.network;
+
+ return;
+ }
+
+ /* Second pass through ROAM process -- request association */
+ ipw_compatible_rates(priv, priv->assoc_network, &match.rates);
+ ipw_associate_network(priv, priv->assoc_network, &match.rates, 1);
+ priv->status &= ~STATUS_ROAMING;
+}
+
+static void ipw_associate(void *data)
+{
+ struct ipw_priv *priv = data;
+
+ struct ieee80211_network *network = NULL;
+ struct ipw_network_match match = {
+ .network = NULL
+ };
+ struct ipw_supported_rates *rates;
+ struct list_head *element;
+
+ if (!(priv->config & CFG_ASSOCIATE) &&
+ !(priv->config & (CFG_STATIC_ESSID |
+ CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) {
+ IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n");
+ return;
+ }
+
+ list_for_each_entry(network, &priv->ieee->network_list, list)
+ ipw_best_network(priv, &match, network, 0);
+
+ network = match.network;
+ rates = &match.rates;
+
+ if (network == NULL &&
+ priv->ieee->iw_mode == IW_MODE_ADHOC &&
+ priv->config & CFG_ADHOC_CREATE &&
+ priv->config & CFG_STATIC_ESSID &&
+ !list_empty(&priv->ieee->network_free_list)) {
+ element = priv->ieee->network_free_list.next;
+ network = list_entry(element, struct ieee80211_network, list);
+ ipw_adhoc_create(priv, network);
+ rates = &priv->rates;
+ list_del(element);
+ list_add_tail(&network->list, &priv->ieee->network_list);
+ }
+
+ /* If we reached the end of the list, then we don't have any valid
+ * matching APs */
+ if (!network) {
+ ipw_debug_config(priv);
+
+ queue_delayed_work(priv->workqueue, &priv->request_scan,
+ SCAN_INTERVAL);
+
+ return;
+ }
+
+ ipw_associate_network(priv, network, rates, 0);
+}
+
+static inline void ipw_handle_data_packet(struct ipw_priv *priv,
+ struct ipw_rx_mem_buffer *rxb,
+ struct ieee80211_rx_stats *stats)
+{
+ struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
+
+ /* We received data from the HW, so stop the watchdog */
+ priv->net_dev->trans_start = jiffies;
+
+ /* We only process data packets if the
+ * interface is open */
+ if (unlikely((pkt->u.frame.length + IPW_RX_FRAME_SIZE) >
+ skb_tailroom(rxb->skb))) {
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
+ return;
+ } else if (unlikely(!netif_running(priv->net_dev))) {
+ priv->ieee->stats.rx_dropped++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+ return;
+ }
+
+ /* Advance skb->data to the start of the actual payload */
+ skb_reserve(rxb->skb, offsetof(struct ipw_rx_packet, u.frame.data));
+
+ /* Set the size of the skb to the size of the frame */
+ skb_put(rxb->skb, pkt->u.frame.length);
+
+ IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
+
+ if (!ieee80211_rx(priv->ieee, rxb->skb, stats))
+ priv->ieee->stats.rx_errors++;
+ else /* ieee80211_rx succeeded, so it now owns the SKB */
+ rxb->skb = NULL;
+}
+
+/*
+ * Main entry function for recieving a packet with 80211 headers. This
+ * should be called when ever the FW has notified us that there is a new
+ * skb in the recieve queue.
+ */
+static void ipw_rx(struct ipw_priv *priv)
+{
+ struct ipw_rx_mem_buffer *rxb;
+ struct ipw_rx_packet *pkt;
+ struct ieee80211_hdr_4addr *header;
+ u32 r, w, i;
+ u8 network_packet;
+
+ r = ipw_read32(priv, CX2_RX_READ_INDEX);
+ w = ipw_read32(priv, CX2_RX_WRITE_INDEX);
+ i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE;
+
+ while (i != r) {
+ rxb = priv->rxq->queue[i];
+#ifdef CONFIG_IPW_DEBUG
+ if (unlikely(rxb == NULL)) {
+ printk(KERN_CRIT "Queue not allocated!\n");
+ break;
+ }
+#endif
+ priv->rxq->queue[i] = NULL;
+
+ pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
+ CX2_RX_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ pkt = (struct ipw_rx_packet *)rxb->skb->data;
+ IPW_DEBUG_RX("Packet: type=%02X seq=%02X bits=%02X\n",
+ pkt->header.message_type,
+ pkt->header.rx_seq_num, pkt->header.control_bits);
+
+ switch (pkt->header.message_type) {
+ case RX_FRAME_TYPE: /* 802.11 frame */ {
+ struct ieee80211_rx_stats stats = {
+ .rssi = pkt->u.frame.rssi_dbm -
+ IPW_RSSI_TO_DBM,
+ .signal = pkt->u.frame.signal,
+ .rate = pkt->u.frame.rate,
+ .mac_time = jiffies,
+ .received_channel =
+ pkt->u.frame.received_channel,
+ .freq =
+ (pkt->u.frame.
+ control & (1 << 0)) ?
+ IEEE80211_24GHZ_BAND :
+ IEEE80211_52GHZ_BAND,
+ .len = pkt->u.frame.length,
+ };
+
+ if (stats.rssi != 0)
+ stats.mask |= IEEE80211_STATMASK_RSSI;
+ if (stats.signal != 0)
+ stats.mask |= IEEE80211_STATMASK_SIGNAL;
+ if (stats.rate != 0)
+ stats.mask |= IEEE80211_STATMASK_RATE;
+
+ priv->rx_packets++;
+
+#ifdef CONFIG_IPW_PROMISC
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
+ ipw_handle_data_packet(priv, rxb,
+ &stats);
+ break;
+ }
+#endif
+
+ header =
+ (struct ieee80211_hdr_4addr *)(rxb->skb->
+ data +
+ IPW_RX_FRAME_SIZE);
+ /* TODO: Check Ad-Hoc dest/source and make sure
+ * that we are actually parsing these packets
+ * correctly -- we should probably use the
+ * frame control of the packet and disregard
+ * the current iw_mode */
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ network_packet =
+ !memcmp(header->addr1,
+ priv->net_dev->dev_addr,
+ ETH_ALEN) ||
+ !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN) ||
+ is_broadcast_ether_addr(header->
+ addr1)
+ || is_multicast_ether_addr(header->
+ addr1);
+ break;
+
+ case IW_MODE_INFRA:
+ default:
+ network_packet =
+ !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN) ||
+ !memcmp(header->addr1,
+ priv->net_dev->dev_addr,
+ ETH_ALEN) ||
+ is_broadcast_ether_addr(header->
+ addr1)
+ || is_multicast_ether_addr(header->
+ addr1);
+ break;
+ }
+
+ if (network_packet && priv->assoc_network) {
+ priv->assoc_network->stats.rssi =
+ stats.rssi;
+ average_add(&priv->average_rssi,
+ stats.rssi);
+ priv->last_rx_rssi = stats.rssi;
+ }
+
+ IPW_DEBUG_RX("Frame: len=%u\n",
+ pkt->u.frame.length);
+
+ if (pkt->u.frame.length < frame_hdr_len(header)) {
+ IPW_DEBUG_DROP
+ ("Received packet is too small. "
+ "Dropping.\n");
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ break;
+ }
+
+ switch (WLAN_FC_GET_TYPE(header->frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ ieee80211_rx_mgt(priv->ieee, header,
+ &stats);
+ if (priv->ieee->iw_mode == IW_MODE_ADHOC
+ &&
+ ((WLAN_FC_GET_STYPE
+ (header->frame_ctl) ==
+ IEEE80211_STYPE_PROBE_RESP)
+ ||
+ (WLAN_FC_GET_STYPE
+ (header->frame_ctl) ==
+ IEEE80211_STYPE_BEACON))
+ && !memcmp(header->addr3,
+ priv->bssid, ETH_ALEN))
+ ipw_add_station(priv,
+ header->addr2);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+ break;
+
+ case IEEE80211_FTYPE_DATA:
+ if (network_packet)
+ ipw_handle_data_packet(priv,
+ rxb,
+ &stats);
+ else
+ IPW_DEBUG_DROP("Dropping: "
+ MAC_FMT ", "
+ MAC_FMT ", "
+ MAC_FMT "\n",
+ MAC_ARG(header->
+ addr1),
+ MAC_ARG(header->
+ addr2),
+ MAC_ARG(header->
+ addr3));
+ break;
+ }
+ break;
+ }
+
+ case RX_HOST_NOTIFICATION_TYPE:{
+ IPW_DEBUG_RX
+ ("Notification: subtype=%02X flags=%02X size=%d\n",
+ pkt->u.notification.subtype,
+ pkt->u.notification.flags,
+ pkt->u.notification.size);
+ ipw_rx_notification(priv, &pkt->u.notification);
+ break;
+ }
+
+ default:
+ IPW_DEBUG_RX("Bad Rx packet of type %d\n",
+ pkt->header.message_type);
+ break;
+ }
+
+ /* For now we just don't re-use anything. We can tweak this
+ * later to try and re-use notification packets and SKBs that
+ * fail to Rx correctly */
+ if (rxb->skb != NULL) {
+ dev_kfree_skb_any(rxb->skb);
+ rxb->skb = NULL;
+ }
+
+ pci_unmap_single(priv->pci_dev, rxb->dma_addr,
+ CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ list_add_tail(&rxb->list, &priv->rxq->rx_used);
+
+ i = (i + 1) % RX_QUEUE_SIZE;
+ }
+
+ /* Backtrack one entry */
+ priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1;
+
+ ipw_rx_queue_restock(priv);
+}
+
+static void ipw_abort_scan(struct ipw_priv *priv)
+{
+ int err;
+
+ if (priv->status & STATUS_SCAN_ABORTING) {
+ IPW_DEBUG_HC("Ignoring concurrent scan abort request.\n");
+ return;
+ }
+ priv->status |= STATUS_SCAN_ABORTING;
+
+ err = ipw_send_scan_abort(priv);
+ if (err)
+ IPW_DEBUG_HC("Request to abort scan failed.\n");
+}
+
+static int ipw_request_scan(struct ipw_priv *priv)
+{
+ struct ipw_scan_request_ext scan;
+ int channel_index = 0;
+ int i, err, scan_type;
+
+ if (priv->status & STATUS_EXIT_PENDING) {
+ IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ if (priv->status & STATUS_SCANNING) {
+ IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ ipw_abort_scan(priv);
+ return 0;
+ }
+
+ if (priv->status & STATUS_SCAN_ABORTING) {
+ IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ if (priv->status & STATUS_RF_KILL_MASK) {
+ IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n");
+ priv->status |= STATUS_SCAN_PENDING;
+ return 0;
+ }
+
+ memset(&scan, 0, sizeof(scan));
+
+ scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20;
+ scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20;
+ scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20;
+
+ scan.full_scan_index = ieee80211_get_scans(priv->ieee);
+ /* If we are roaming, then make this a directed scan for the current
+ * network. Otherwise, ensure that every other scan is a fast
+ * channel hop scan */
+ if ((priv->status & STATUS_ROAMING)
+ || (!(priv->status & STATUS_ASSOCIATED)
+ && (priv->config & CFG_STATIC_ESSID)
+ && (scan.full_scan_index % 2))) {
+ err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
+ if (err) {
+ IPW_DEBUG_HC("Attempt to send SSID command failed.\n");
+ return err;
+ }
+
+ scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN;
+ } else {
+ scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN;
+ }
+
+ if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) {
+ int start = channel_index;
+ for (i = 0; i < MAX_A_CHANNELS; i++) {
+ if (band_a_active_channel[i] == 0)
+ break;
+ if ((priv->status & STATUS_ASSOCIATED) &&
+ band_a_active_channel[i] == priv->channel)
+ continue;
+ channel_index++;
+ scan.channels_list[channel_index] =
+ band_a_active_channel[i];
+ ipw_set_scan_type(&scan, channel_index, scan_type);
+ }
+
+ if (start != channel_index) {
+ scan.channels_list[start] = (u8) (IPW_A_MODE << 6) |
+ (channel_index - start);
+ channel_index++;
+ }
+ }
+
+ if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) {
+ int start = channel_index;
+ for (i = 0; i < MAX_B_CHANNELS; i++) {
+ if (band_b_active_channel[i] == 0)
+ break;
+ if ((priv->status & STATUS_ASSOCIATED) &&
+ band_b_active_channel[i] == priv->channel)
+ continue;
+ channel_index++;
+ scan.channels_list[channel_index] =
+ band_b_active_channel[i];
+ ipw_set_scan_type(&scan, channel_index, scan_type);
+ }
+
+ if (start != channel_index) {
+ scan.channels_list[start] = (u8) (IPW_B_MODE << 6) |
+ (channel_index - start);
+ }
+ }
+
+ err = ipw_send_scan_request_ext(priv, &scan);
+ if (err) {
+ IPW_DEBUG_HC("Sending scan command failed: %08X\n", err);
+ return -EIO;
+ }
+
+ priv->status |= STATUS_SCANNING;
+ priv->status &= ~STATUS_SCAN_PENDING;
+
+ return 0;
+}
+
+/*
+ * This file defines the Wireless Extension handlers. It does not
+ * define any methods of hardware manipulation and relies on the
+ * functions defined in ipw_main to provide the HW interaction.
+ *
+ * The exception to this is the use of the ipw_get_ordinal()
+ * function used to poll the hardware vs. making unecessary calls.
+ *
+ */
+
+static int ipw_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ if (!(priv->status & STATUS_ASSOCIATED))
+ strcpy(wrqu->name, "unassociated");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
+ ipw_modes[priv->assoc_request.ieee_mode]);
+ IPW_DEBUG_WX("Name: %s\n", wrqu->name);
+ return 0;
+}
+
+static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
+{
+ if (channel == 0) {
+ IPW_DEBUG_INFO("Setting channel to ANY (0)\n");
+ priv->config &= ~CFG_STATIC_CHANNEL;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ priv->config |= CFG_STATIC_CHANNEL;
+
+ if (priv->channel == channel) {
+ IPW_DEBUG_INFO("Request to set channel to current value (%d)\n",
+ channel);
+ return 0;
+ }
+
+ IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel);
+ priv->channel = channel;
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new channel (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to channel change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_freq *fwrq = &wrqu->freq;
+
+ /* if setting by freq convert to channel */
+ if (fwrq->e == 1) {
+ if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+
+ while ((c < REG_MAX_CHANNEL) &&
+ (f != ipw_frequencies[c]))
+ c++;
+
+ /* hack to fall through */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ }
+
+ if (fwrq->e > 0 || fwrq->m > 1000)
+ return -EOPNOTSUPP;
+
+ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+ return ipw_set_channel(priv, (u8) fwrq->m);
+}
+
+static int ipw_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->freq.e = 0;
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured CHANNEL then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_CHANNEL ||
+ priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
+ wrqu->freq.m = priv->channel;
+ else
+ wrqu->freq.m = 0;
+
+ IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+ return 0;
+}
+
+static int ipw_wx_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode);
+
+ if (wrqu->mode == priv->ieee->iw_mode)
+ return 0;
+
+ switch (wrqu->mode) {
+#ifdef CONFIG_IPW_PROMISC
+ case IW_MODE_MONITOR:
+#endif
+ case IW_MODE_ADHOC:
+ case IW_MODE_INFRA:
+ break;
+ case IW_MODE_AUTO:
+ wrqu->mode = IW_MODE_INFRA;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_IPW_PROMISC
+ if (priv->ieee->iw_mode == IW_MODE_MONITOR)
+ priv->net_dev->type = ARPHRD_ETHER;
+
+ if (wrqu->mode == IW_MODE_MONITOR)
+ priv->net_dev->type = ARPHRD_IEEE80211;
+#endif /* CONFIG_IPW_PROMISC */
+
+#ifdef CONFIG_PM
+ /* Free the existing firmware and reset the fw_loaded
+ * flag so ipw_load() will bring in the new firmawre */
+ if (fw_loaded) {
+ fw_loaded = 0;
+ }
+
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+ bootfw = ucode = firmware = NULL;
+#endif
+
+ priv->ieee->iw_mode = wrqu->mode;
+ ipw_adapter_restart(priv);
+
+ return err;
+}
+
+static int ipw_wx_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->mode = priv->ieee->iw_mode;
+ IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode);
+
+ return 0;
+}
+
+#define DEFAULT_RTS_THRESHOLD 2304U
+#define MIN_RTS_THRESHOLD 1U
+#define MAX_RTS_THRESHOLD 2304U
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+/* Values are in microsecond */
+static const s32 timeout_duration[] = {
+ 350000,
+ 250000,
+ 75000,
+ 37000,
+ 25000,
+};
+
+static const s32 period_duration[] = {
+ 400000,
+ 700000,
+ 1000000,
+ 1000000,
+ 1000000
+};
+
+static int ipw_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_range *range = (struct iw_range *)extra;
+ u16 val;
+ int i;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* 54Mbs == ~27 Mb/s real (802.11g) */
+ range->throughput = 27 * 1000 * 1000;
+
+ range->max_qual.qual = 100;
+ /* TODO: Find real max RSSI and stick here */
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 70;
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 0; /* FIXME to real average level */
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
+
+ for (i = 0; i < range->num_bitrates; i++)
+ range->bitrate[i] = (priv->rates.supported_rates[i] & 0x7F) *
+ 500000;
+
+ range->max_rts = DEFAULT_RTS_THRESHOLD;
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = WEP_KEYS;
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+ range->num_channels = FREQ_COUNT;
+
+ val = 0;
+ for (i = 0; i < FREQ_COUNT; i++) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = ipw_frequencies[i] * 100000;
+ range->freq[val].e = 1;
+ val++;
+
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+
+ IPW_DEBUG_WX("GET Range\n");
+ return 0;
+}
+
+static int ipw_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ static const unsigned char any[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ static const unsigned char off[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
+ !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ /* we disable mandatory BSSID association */
+ IPW_DEBUG_WX("Setting AP BSSID to ANY\n");
+ priv->config &= ~CFG_STATIC_BSSID;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ priv->config |= CFG_STATIC_BSSID;
+ if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
+ IPW_DEBUG_WX("BSSID set to current BSSID.\n");
+ return 0;
+ }
+
+ IPW_DEBUG_WX("Setting mandatory BSSID to " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+
+ memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new BSSID (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ /* If we are associated, trying to associate, or have a statically
+ * configured BSSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_BSSID ||
+ priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN);
+ } else
+ memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+
+ IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
+ MAC_ARG(wrqu->ap_addr.sa_data));
+ return 0;
+}
+
+static int ipw_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ char *essid = ""; /* ANY */
+ int length = 0;
+
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ length = wrqu->essid.length - 1;
+ essid = extra;
+ }
+ if (length == 0) {
+ IPW_DEBUG_WX("Setting ESSID to ANY\n");
+ priv->config &= ~CFG_STATIC_ESSID;
+ if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED |
+ STATUS_ASSOCIATING))) {
+ IPW_DEBUG_ASSOC("Attempting to associate with new "
+ "parameters.\n");
+ ipw_associate(priv);
+ }
+
+ return 0;
+ }
+
+ length = min(length, IW_ESSID_MAX_SIZE);
+
+ priv->config |= CFG_STATIC_ESSID;
+
+ if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
+ IPW_DEBUG_WX("ESSID set to current ESSID.\n");
+ return 0;
+ }
+
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
+ length);
+
+ priv->essid_len = length;
+ memcpy(priv->essid, essid, priv->essid_len);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new ESSID (causing us to disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n");
+ ipw_disassociate(priv);
+ } else {
+ ipw_associate(priv);
+ }
+
+ return 0;
+}
+
+static int ipw_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ /* If we are associated, trying to associate, or have a statically
+ * configured ESSID then return that; otherwise return ANY */
+ if (priv->config & CFG_STATIC_ESSID ||
+ priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ IPW_DEBUG_WX("Getting essid: '%s'\n",
+ escape_essid(priv->essid, priv->essid_len));
+ memcpy(extra, priv->essid, priv->essid_len);
+ wrqu->essid.length = priv->essid_len;
+ wrqu->essid.flags = 1; /* active */
+ } else {
+ IPW_DEBUG_WX("Getting essid: ANY\n");
+ wrqu->essid.length = 0;
+ wrqu->essid.flags = 0; /* active */
+ }
+
+ return 0;
+}
+
+static int ipw_wx_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ IPW_DEBUG_WX("Setting nick to '%s'\n", extra);
+ if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+ return -E2BIG;
+
+ wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+ memset(priv->nick, 0, sizeof(priv->nick));
+ memcpy(priv->nick, extra, wrqu->data.length);
+ IPW_DEBUG_TRACE("<<\n");
+ return 0;
+
+}
+
+static int ipw_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("Getting nick\n");
+ wrqu->data.length = strlen(priv->nick) + 1;
+ memcpy(extra, priv->nick, wrqu->data.length);
+ wrqu->data.flags = 1; /* active */
+ return 0;
+}
+
+static int ipw_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->bitrate.value = priv->last_rate;
+
+ IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+ return 0;
+}
+
+static int ipw_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->rts.disabled)
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
+ else {
+ if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
+ wrqu->rts.value > MAX_RTS_THRESHOLD)
+ return -EINVAL;
+
+ priv->rts_threshold = wrqu->rts.value;
+ }
+
+ ipw_send_rts_threshold(priv, priv->rts_threshold);
+ IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
+ return 0;
+}
+
+static int ipw_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->rts.value = priv->rts_threshold;
+ wrqu->rts.fixed = 0; /* no auto select */
+ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
+
+ IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
+ return 0;
+}
+
+static int ipw_wx_set_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct ipw_tx_power tx_power;
+ int i;
+
+ if (ipw_radio_kill_sw(priv, wrqu->power.disabled))
+ return -EINPROGRESS;
+
+ if (wrqu->power.flags != IW_TXPOW_DBM)
+ return -EINVAL;
+
+ if ((wrqu->power.value > 20) || (wrqu->power.value < -12))
+ return -EINVAL;
+
+ priv->tx_power = wrqu->power.value;
+
+ memset(&tx_power, 0, sizeof(tx_power));
+
+ /* configure device for 'G' band */
+ tx_power.ieee_mode = IPW_G_MODE;
+ tx_power.num_channels = 11;
+ for (i = 0; i < 11; i++) {
+ tx_power.channels_tx_power[i].channel_number = i + 1;
+ tx_power.channels_tx_power[i].tx_power = priv->tx_power;
+ }
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* configure device to also handle 'B' band */
+ tx_power.ieee_mode = IPW_B_MODE;
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ return 0;
+
+ error:
+ return -EIO;
+}
+
+static int ipw_wx_get_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ wrqu->power.value = priv->tx_power;
+ wrqu->power.fixed = 1;
+ wrqu->power.flags = IW_TXPOW_DBM;
+ wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
+
+ IPW_DEBUG_WX("GET TX Power -> %s %d \n",
+ wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value);
+
+ return 0;
+}
+
+static int ipw_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (wrqu->frag.disabled)
+ priv->ieee->fts = DEFAULT_FTS;
+ else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ priv->ieee->fts = wrqu->frag.value & ~0x1;
+ }
+
+ ipw_send_frag_threshold(priv, wrqu->frag.value);
+ IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
+ return 0;
+}
+
+static int ipw_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ wrqu->frag.value = priv->ieee->fts;
+ wrqu->frag.fixed = 0; /* no auto select */
+ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
+
+ IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+
+ return 0;
+}
+
+static int ipw_wx_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu);
+ return -EOPNOTSUPP;
+}
+
+static int ipw_wx_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("Start scan\n");
+ if (ipw_request_scan(priv))
+ return -EIO;
+ return 0;
+}
+
+static int ipw_wx_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra);
+}
+
+static int ipw_wx_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw_wx_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return ieee80211_wx_get_encode(priv->ieee, info, wrqu, key);
+}
+
+static int ipw_wx_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int err;
+
+ if (wrqu->power.disabled) {
+ priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
+ err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM);
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+
+ IPW_DEBUG_WX("SET Power Management Mode -> off\n");
+
+ return 0;
+ }
+
+ switch (wrqu->power.flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ break;
+ default: /* Otherwise we don't support it */
+ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
+ wrqu->power.flags);
+ return -EOPNOTSUPP;
+ }
+
+ /* If the user hasn't specified a power management mode yet, default
+ * to BATTERY */
+ if (IPW_POWER_LEVEL(priv->power_mode) == IPW_POWER_AC)
+ priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY;
+ else
+ priv->power_mode = IPW_POWER_ENABLED | priv->power_mode;
+ err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+
+ IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
+
+ return 0;
+}
+
+static int ipw_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED)) {
+ wrqu->power.disabled = 1;
+ } else {
+ wrqu->power.disabled = 0;
+ }
+
+ IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
+
+ return 0;
+}
+
+static int ipw_wx_set_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int mode = *(int *)extra;
+ int err;
+
+ if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
+ mode = IPW_POWER_AC;
+ priv->power_mode = mode;
+ } else {
+ priv->power_mode = IPW_POWER_ENABLED | mode;
+ }
+
+ if (priv->power_mode != mode) {
+ err = ipw_send_power_mode(priv, mode);
+
+ if (err) {
+ IPW_DEBUG_WX("failed setting power mode.\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+#define MAX_WX_STRING 80
+static int ipw_wx_get_powermode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int level = IPW_POWER_LEVEL(priv->power_mode);
+ char *p = extra;
+
+ p += snprintf(p, MAX_WX_STRING, "Power save level: %d ", level);
+
+ switch (level) {
+ case IPW_POWER_AC:
+ p += snprintf(p, MAX_WX_STRING - (p - extra), "(AC)");
+ break;
+ case IPW_POWER_BATTERY:
+ p += snprintf(p, MAX_WX_STRING - (p - extra), "(BATTERY)");
+ break;
+ default:
+ p += snprintf(p, MAX_WX_STRING - (p - extra),
+ "(Timeout %dms, Period %dms)",
+ timeout_duration[level - 1] / 1000,
+ period_duration[level - 1] / 1000);
+ }
+
+ if (!(priv->power_mode & IPW_POWER_ENABLED))
+ p += snprintf(p, MAX_WX_STRING - (p - extra), " OFF");
+
+ wrqu->data.length = p - extra + 1;
+
+ return 0;
+}
+
+static int ipw_wx_set_wireless_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int mode = *(int *)extra;
+ u8 band = 0, modulation = 0;
+
+ if (mode == 0 || mode & ~IEEE_MODE_MASK) {
+ IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ if (priv->adapter == IPW_2915ABG) {
+ priv->ieee->abg_true = 1;
+ if (mode & IEEE_A) {
+ band |= IEEE80211_52GHZ_BAND;
+ modulation |= IEEE80211_OFDM_MODULATION;
+ } else
+ priv->ieee->abg_true = 0;
+ } else {
+ if (mode & IEEE_A) {
+ IPW_WARNING("Attempt to set 2200BG into "
+ "802.11a mode\n");
+ return -EINVAL;
+ }
+
+ priv->ieee->abg_true = 0;
+ }
+
+ if (mode & IEEE_B) {
+ band |= IEEE80211_24GHZ_BAND;
+ modulation |= IEEE80211_CCK_MODULATION;
+ } else
+ priv->ieee->abg_true = 0;
+
+ if (mode & IEEE_G) {
+ band |= IEEE80211_24GHZ_BAND;
+ modulation |= IEEE80211_OFDM_MODULATION;
+ } else
+ priv->ieee->abg_true = 0;
+
+ priv->ieee->mode = mode;
+ priv->ieee->freq_band = band;
+ priv->ieee->modulation = modulation;
+ init_supported_rates(priv, &priv->rates);
+
+ /* If we are currently associated, or trying to associate
+ * then see if this is a new configuration (causing us to
+ * disassociate) */
+ if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
+ /* The resulting association will trigger
+ * the new rates to be sent to the device */
+ IPW_DEBUG_ASSOC("Disassociating due to mode change.\n");
+ ipw_disassociate(priv);
+ } else
+ ipw_send_supported_rates(priv, &priv->rates);
+
+ IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
+ mode & IEEE_A ? 'a' : '.',
+ mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
+ return 0;
+}
+
+static int ipw_wx_get_wireless_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_24GHZ_BAND:
+ switch (priv->ieee->modulation) {
+ case IEEE80211_CCK_MODULATION:
+ strncpy(extra, "802.11b (2)", MAX_WX_STRING);
+ break;
+ case IEEE80211_OFDM_MODULATION:
+ strncpy(extra, "802.11g (4)", MAX_WX_STRING);
+ break;
+ default:
+ strncpy(extra, "802.11bg (6)", MAX_WX_STRING);
+ break;
+ }
+ break;
+
+ case IEEE80211_52GHZ_BAND:
+ strncpy(extra, "802.11a (1)", MAX_WX_STRING);
+ break;
+
+ default: /* Mixed Band */
+ switch (priv->ieee->modulation) {
+ case IEEE80211_CCK_MODULATION:
+ strncpy(extra, "802.11ab (3)", MAX_WX_STRING);
+ break;
+ case IEEE80211_OFDM_MODULATION:
+ strncpy(extra, "802.11ag (5)", MAX_WX_STRING);
+ break;
+ default:
+ strncpy(extra, "802.11abg (7)", MAX_WX_STRING);
+ break;
+ }
+ break;
+ }
+
+ IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
+
+ wrqu->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+#ifdef CONFIG_IPW_PROMISC
+static int ipw_wx_set_promisc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int *parms = (int *)extra;
+ int enable = (parms[0] > 0);
+
+ IPW_DEBUG_WX("SET PROMISC: %d %d\n", enable, parms[1]);
+ if (enable) {
+ if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+ priv->net_dev->type = ARPHRD_IEEE80211;
+ ipw_adapter_restart(priv);
+ }
+
+ ipw_set_channel(priv, parms[1]);
+ } else {
+ if (priv->ieee->iw_mode != IW_MODE_MONITOR)
+ return 0;
+ priv->net_dev->type = ARPHRD_ETHER;
+ ipw_adapter_restart(priv);
+ }
+ return 0;
+}
+
+static int ipw_wx_reset(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_WX("RESET\n");
+ ipw_adapter_restart(priv);
+ return 0;
+}
+#endif // CONFIG_IPW_PROMISC
+
+/* Rebase the WE IOCTLs to zero for the handler array */
+#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+static iw_handler ipw_wx_handlers[] = {
+ IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name,
+ IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
+ IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
+ IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
+ IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode,
+ IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range,
+ IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap,
+ IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap,
+ IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan,
+ IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan,
+ IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid,
+ IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid,
+ IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick,
+ IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick,
+ IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate,
+ IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate,
+ IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts,
+ IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts,
+ IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag,
+ IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag,
+ IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow,
+ IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow,
+ IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry,
+ IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry,
+ IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode,
+ IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode,
+ IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power,
+ IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power,
+};
+
+#define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV
+#define IPW_PRIV_GET_POWER SIOCIWFIRSTPRIV+1
+#define IPW_PRIV_SET_MODE SIOCIWFIRSTPRIV+2
+#define IPW_PRIV_GET_MODE SIOCIWFIRSTPRIV+3
+#define IPW_PRIV_SET_PROMISC SIOCIWFIRSTPRIV+4
+#define IPW_PRIV_RESET SIOCIWFIRSTPRIV+5
+
+static struct iw_priv_args ipw_priv_args[] = {
+ {
+ .cmd = IPW_PRIV_SET_POWER,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_power"},
+ {
+ .cmd = IPW_PRIV_GET_POWER,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_power"},
+ {
+ .cmd = IPW_PRIV_SET_MODE,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_mode"},
+ {
+ .cmd = IPW_PRIV_GET_MODE,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_mode"},
+#ifdef CONFIG_IPW_PROMISC
+ {
+ IPW_PRIV_SET_PROMISC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"},
+ {
+ IPW_PRIV_RESET,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"},
+#endif /* CONFIG_IPW_PROMISC */
+};
+
+static iw_handler ipw_priv_handler[] = {
+ ipw_wx_set_powermode,
+ ipw_wx_get_powermode,
+ ipw_wx_set_wireless_mode,
+ ipw_wx_get_wireless_mode,
+#ifdef CONFIG_IPW_PROMISC
+ ipw_wx_set_promisc,
+ ipw_wx_reset,
+#endif
+};
+
+static struct iw_handler_def ipw_wx_handler_def = {
+ .standard = ipw_wx_handlers,
+ .num_standard = ARRAY_SIZE(ipw_wx_handlers),
+ .num_private = ARRAY_SIZE(ipw_priv_handler),
+ .num_private_args = ARRAY_SIZE(ipw_priv_args),
+ .private = ipw_priv_handler,
+ .private_args = ipw_priv_args,
+};
+
+/*
+ * Get wireless statistics.
+ * Called by /proc/net/wireless
+ * Also called by SIOCGIWSTATS
+ */
+static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct iw_statistics *wstats;
+
+ wstats = &priv->wstats;
+
+ /* if hw is disabled, then ipw2100_get_ordinal() can't be called.
+ * ipw2100_wx_wireless_stats seems to be called before fw is
+ * initialized. STATUS_ASSOCIATED will only be set if the hw is up
+ * and associated; if not associcated, the values are all meaningless
+ * anyway, so set them all to NULL and INVALID */
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 0;
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 7;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ return wstats;
+ }
+
+ wstats->qual.qual = priv->quality;
+ wstats->qual.level = average_value(&priv->average_rssi);
+ wstats->qual.noise = average_value(&priv->average_noise);
+ wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+ IW_QUAL_NOISE_UPDATED;
+
+ wstats->miss.beacon = average_value(&priv->average_missed_beacons);
+ wstats->discard.retries = priv->last_tx_failures;
+ wstats->discard.code = priv->ieee->ieee_stats.rx_discards_undecryptable;
+
+/* if (ipw_get_ordinal(priv, IPW_ORD_STAT_TX_RETRY, &tx_retry, &len))
+ goto fail_get_ordinal;
+ wstats->discard.retries += tx_retry; */
+
+ return wstats;
+}
+
+/* net device stuff */
+
+static inline void init_sys_config(struct ipw_sys_config *sys_config)
+{
+ memset(sys_config, 0, sizeof(struct ipw_sys_config));
+ sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */
+ sys_config->answer_broadcast_ssid_probe = 0;
+ sys_config->accept_all_data_frames = 0;
+ sys_config->accept_non_directed_frames = 1;
+ sys_config->exclude_unicast_unencrypted = 0;
+ sys_config->disable_unicast_decryption = 1;
+ sys_config->exclude_multicast_unencrypted = 0;
+ sys_config->disable_multicast_decryption = 1;
+ sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH;
+ sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */
+ sys_config->dot11g_auto_detection = 0;
+ sys_config->enable_cts_to_self = 0;
+ sys_config->bt_coexist_collision_thr = 0;
+ sys_config->pass_noise_stats_to_host = 1;
+}
+
+static int ipw_net_open(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ IPW_DEBUG_INFO("dev->open\n");
+ /* we should be verifying the device is ready to be opened */
+ if (!(priv->status & STATUS_RF_KILL_MASK) &&
+ (priv->status & STATUS_ASSOCIATED))
+ netif_start_queue(dev);
+ return 0;
+}
+
+static int ipw_net_stop(struct net_device *dev)
+{
+ IPW_DEBUG_INFO("dev->close\n");
+ netif_stop_queue(dev);
+ return 0;
+}
+
+/*
+todo:
+
+modify to send one tfd per fragment instead of using chunking. otherwise
+we need to heavily modify the ieee80211_skb_to_txb.
+*/
+
+static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
+{
+ struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+ txb->fragments[0]->data;
+ int i = 0;
+ struct tfd_frame *tfd;
+ struct clx2_tx_queue *txq = &priv->txq[0];
+ struct clx2_queue *q = &txq->q;
+ u8 id, hdr_len, unicast;
+ u16 remaining_bytes;
+
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ hdr_len = IEEE80211_3ADDR_LEN;
+ unicast = !is_broadcast_ether_addr(hdr->addr1) &&
+ !is_multicast_ether_addr(hdr->addr1);
+ id = ipw_find_station(priv, hdr->addr1);
+ if (id == IPW_INVALID_STATION) {
+ id = ipw_add_station(priv, hdr->addr1);
+ if (id == IPW_INVALID_STATION) {
+ IPW_WARNING("Attempt to send data to "
+ "invalid cell: " MAC_FMT "\n",
+ MAC_ARG(hdr->addr1));
+ goto drop;
+ }
+ }
+ break;
+
+ case IW_MODE_INFRA:
+ default:
+ unicast = !is_broadcast_ether_addr(hdr->addr3) &&
+ !is_multicast_ether_addr(hdr->addr3);
+ hdr_len = IEEE80211_3ADDR_LEN;
+ id = 0;
+ break;
+ }
+
+ tfd = &txq->bd[q->first_empty];
+ txq->txb[q->first_empty] = txb;
+ memset(tfd, 0, sizeof(*tfd));
+ tfd->u.data.station_number = id;
+
+ tfd->control_flags.message_type = TX_FRAME_TYPE;
+ tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK;
+
+ tfd->u.data.cmd_id = DINO_CMD_TX;
+ tfd->u.data.len = txb->payload_size;
+ remaining_bytes = txb->payload_size;
+ if (unlikely(!unicast))
+ tfd->u.data.tx_flags = DCT_FLAG_NO_WEP;
+ else
+ tfd->u.data.tx_flags = DCT_FLAG_NO_WEP | DCT_FLAG_ACK_REQD;
+
+ if (priv->assoc_request.ieee_mode == IPW_B_MODE)
+ tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_CCK;
+ else
+ tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_OFDM;
+
+ if (priv->config & CFG_PREAMBLE)
+ tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREMBL;
+
+ memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len);
+
+ /* payload */
+ tfd->u.data.num_chunks = min((u8) (NUM_TFD_CHUNKS - 2), txb->nr_frags);
+ for (i = 0; i < tfd->u.data.num_chunks; i++) {
+ IPW_DEBUG_TX("Dumping TX packet frag %i of %i (%d bytes):\n",
+ i, tfd->u.data.num_chunks,
+ txb->fragments[i]->len - hdr_len);
+ printk_buf(IPW_DL_TX, txb->fragments[i]->data + hdr_len,
+ txb->fragments[i]->len - hdr_len);
+
+ tfd->u.data.chunk_ptr[i] =
+ pci_map_single(priv->pci_dev,
+ txb->fragments[i]->data + hdr_len,
+ txb->fragments[i]->len - hdr_len,
+ PCI_DMA_TODEVICE);
+ tfd->u.data.chunk_len[i] = txb->fragments[i]->len - hdr_len;
+ }
+
+ if (i != txb->nr_frags) {
+ struct sk_buff *skb;
+ u16 remaining_bytes = 0;
+ int j;
+
+ for (j = i; j < txb->nr_frags; j++)
+ remaining_bytes += txb->fragments[j]->len - hdr_len;
+
+ printk(KERN_INFO "Trying to reallocate for %d bytes\n",
+ remaining_bytes);
+ skb = alloc_skb(remaining_bytes, GFP_ATOMIC);
+ if (skb != NULL) {
+ tfd->u.data.chunk_len[i] = remaining_bytes;
+ for (j = i; j < txb->nr_frags; j++) {
+ int size = txb->fragments[j]->len - hdr_len;
+ printk(KERN_INFO "Adding frag %d %d...\n",
+ j, size);
+ memcpy(skb_put(skb, size),
+ txb->fragments[j]->data + hdr_len, size);
+ }
+ dev_kfree_skb_any(txb->fragments[i]);
+ txb->fragments[i] = skb;
+ tfd->u.data.chunk_ptr[i] =
+ pci_map_single(priv->pci_dev, skb->data,
+ tfd->u.data.chunk_len[i],
+ PCI_DMA_TODEVICE);
+ tfd->u.data.num_chunks++;
+ }
+ }
+
+ /* kick DMA */
+ q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
+ ipw_write32(priv, q->reg_w, q->first_empty);
+
+ if (ipw_queue_space(q) < q->high_mark)
+ netif_stop_queue(priv->net_dev);
+
+ return;
+
+ drop:
+ IPW_DEBUG_DROP("Silently dropping Tx packet.\n");
+ ieee80211_txb_free(txb);
+}
+
+static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
+ struct net_device *dev, int pri)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ unsigned long flags;
+
+ IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!(priv->status & STATUS_ASSOCIATED)) {
+ IPW_DEBUG_INFO("Tx attempt while not associated.\n");
+ priv->ieee->stats.tx_carrier_errors++;
+ netif_stop_queue(dev);
+ goto fail_unlock;
+ }
+
+ ipw_tx_skb(priv, txb);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+
+ fail_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return 1;
+}
+
+static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ priv->ieee->stats.tx_packets = priv->tx_packets;
+ priv->ieee->stats.rx_packets = priv->rx_packets;
+ return &priv->ieee->stats;
+}
+
+static void ipw_net_set_multicast_list(struct net_device *dev)
+{
+
+}
+
+static int ipw_net_set_mac_address(struct net_device *dev, void *p)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ struct sockaddr *addr = p;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+ priv->config |= CFG_CUSTOM_MAC;
+ memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
+ printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
+ priv->net_dev->name, MAC_ARG(priv->mac_addr));
+ ipw_adapter_restart(priv);
+ return 0;
+}
+
+static void ipw_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+ char vers[64];
+ char date[32];
+ u32 len;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+
+ len = sizeof(vers);
+ ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
+ len = sizeof(date);
+ ipw_get_ordinal(p, IPW_ORD_STAT_FW_DATE, date, &len);
+
+ snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
+ vers, date);
+ strcpy(info->bus_info, pci_name(p->pci_dev));
+ info->eedump_len = CX2_EEPROM_IMAGE_SIZE;
+}
+
+static u32 ipw_ethtool_get_link(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ return (priv->status & STATUS_ASSOCIATED) != 0;
+}
+
+static int ipw_ethtool_get_eeprom_len(struct net_device *dev)
+{
+ return CX2_EEPROM_IMAGE_SIZE;
+}
+
+static int ipw_ethtool_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * bytes)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+
+ if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
+ return -EINVAL;
+
+ memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len);
+ return 0;
+}
+
+static int ipw_ethtool_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * bytes)
+{
+ struct ipw_priv *p = ieee80211_priv(dev);
+ int i;
+
+ if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
+ return -EINVAL;
+
+ memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len);
+ for (i = IPW_EEPROM_DATA;
+ i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++)
+ ipw_write8(p, i, p->eeprom[i]);
+
+ return 0;
+}
+
+static struct ethtool_ops ipw_ethtool_ops = {
+ .get_link = ipw_ethtool_get_link,
+ .get_drvinfo = ipw_ethtool_get_drvinfo,
+ .get_eeprom_len = ipw_ethtool_get_eeprom_len,
+ .get_eeprom = ipw_ethtool_get_eeprom,
+ .set_eeprom = ipw_ethtool_set_eeprom,
+};
+
+static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
+{
+ struct ipw_priv *priv = data;
+ u32 inta, inta_mask;
+
+ if (!priv)
+ return IRQ_NONE;
+
+ spin_lock(&priv->lock);
+
+ if (!(priv->status & STATUS_INT_ENABLED)) {
+ /* Shared IRQ */
+ goto none;
+ }
+
+ inta = ipw_read32(priv, CX2_INTA_RW);
+ inta_mask = ipw_read32(priv, CX2_INTA_MASK_R);
+
+ if (inta == 0xFFFFFFFF) {
+ /* Hardware disappeared */
+ IPW_WARNING("IRQ INTA == 0xFFFFFFFF\n");
+ goto none;
+ }
+
+ if (!(inta & (CX2_INTA_MASK_ALL & inta_mask))) {
+ /* Shared interrupt */
+ goto none;
+ }
+
+ /* tell the device to stop sending interrupts */
+ ipw_disable_interrupts(priv);
+
+ /* ack current interrupts */
+ inta &= (CX2_INTA_MASK_ALL & inta_mask);
+ ipw_write32(priv, CX2_INTA_RW, inta);
+
+ /* Cache INTA value for our tasklet */
+ priv->isr_inta = inta;
+
+ tasklet_schedule(&priv->irq_tasklet);
+
+ spin_unlock(&priv->lock);
+
+ return IRQ_HANDLED;
+ none:
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+}
+
+static void ipw_rf_kill(void *adapter)
+{
+ struct ipw_priv *priv = adapter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (rf_kill_active(priv)) {
+ IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
+ if (priv->workqueue)
+ queue_delayed_work(priv->workqueue,
+ &priv->rf_kill, 2 * HZ);
+ goto exit_unlock;
+ }
+
+ /* RF Kill is now disabled, so bring the device back up */
+
+ if (!(priv->status & STATUS_RF_KILL_MASK)) {
+ IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting "
+ "device\n");
+
+ /* we can not do an adapter restart while inside an irq lock */
+ queue_work(priv->workqueue, &priv->adapter_restart);
+ } else
+ IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still "
+ "enabled\n");
+
+ exit_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int ipw_setup_deferred_work(struct ipw_priv *priv)
+{
+ int ret = 0;
+
+ priv->workqueue = create_workqueue(DRV_NAME);
+ init_waitqueue_head(&priv->wait_command_queue);
+
+ INIT_WORK(&priv->adhoc_check, ipw_adhoc_check, priv);
+ INIT_WORK(&priv->associate, ipw_associate, priv);
+ INIT_WORK(&priv->disassociate, ipw_disassociate, priv);
+ INIT_WORK(&priv->rx_replenish, ipw_rx_queue_replenish, priv);
+ INIT_WORK(&priv->adapter_restart, ipw_adapter_restart, priv);
+ INIT_WORK(&priv->rf_kill, ipw_rf_kill, priv);
+ INIT_WORK(&priv->up, (void (*)(void *))ipw_up, priv);
+ INIT_WORK(&priv->down, (void (*)(void *))ipw_down, priv);
+ INIT_WORK(&priv->request_scan,
+ (void (*)(void *))ipw_request_scan, priv);
+ INIT_WORK(&priv->gather_stats,
+ (void (*)(void *))ipw_gather_stats, priv);
+ INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv);
+ INIT_WORK(&priv->roam, ipw_roam, priv);
+ INIT_WORK(&priv->scan_check, ipw_scan_check, priv);
+
+ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ ipw_irq_tasklet, (unsigned long)priv);
+
+ return ret;
+}
+
+static void shim__set_security(struct net_device *dev,
+ struct ieee80211_security *sec)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (sec->flags & (1 << i)) {
+ priv->sec.key_sizes[i] = sec->key_sizes[i];
+ if (sec->key_sizes[i] == 0)
+ priv->sec.flags &= ~(1 << i);
+ else
+ memcpy(priv->sec.keys[i], sec->keys[i],
+ sec->key_sizes[i]);
+ priv->sec.flags |= (1 << i);
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+ }
+
+ if ((sec->flags & SEC_ACTIVE_KEY) &&
+ priv->sec.active_key != sec->active_key) {
+ if (sec->active_key <= 3) {
+ priv->sec.active_key = sec->active_key;
+ priv->sec.flags |= SEC_ACTIVE_KEY;
+ } else
+ priv->sec.flags &= ~SEC_ACTIVE_KEY;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if ((sec->flags & SEC_AUTH_MODE) &&
+ (priv->sec.auth_mode != sec->auth_mode)) {
+ priv->sec.auth_mode = sec->auth_mode;
+ priv->sec.flags |= SEC_AUTH_MODE;
+ if (sec->auth_mode == WLAN_AUTH_SHARED_KEY)
+ priv->capability |= CAP_SHARED_KEY;
+ else
+ priv->capability &= ~CAP_SHARED_KEY;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) {
+ priv->sec.flags |= SEC_ENABLED;
+ priv->sec.enabled = sec->enabled;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ if (sec->enabled)
+ priv->capability |= CAP_PRIVACY_ON;
+ else
+ priv->capability &= ~CAP_PRIVACY_ON;
+ }
+
+ if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) {
+ priv->sec.level = sec->level;
+ priv->sec.flags |= SEC_LEVEL;
+ priv->status |= STATUS_SECURITY_UPDATED;
+ }
+
+ /* To match current functionality of ipw2100 (which works well w/
+ * various supplicants, we don't force a disassociate if the
+ * privacy capability changes ... */
+#if 0
+ if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) &&
+ (((priv->assoc_request.capability &
+ WLAN_CAPABILITY_PRIVACY) && !sec->enabled) ||
+ (!(priv->assoc_request.capability &
+ WLAN_CAPABILITY_PRIVACY) && sec->enabled))) {
+ IPW_DEBUG_ASSOC("Disassociating due to capability "
+ "change.\n");
+ ipw_disassociate(priv);
+ }
+#endif
+}
+
+static int init_supported_rates(struct ipw_priv *priv,
+ struct ipw_supported_rates *rates)
+{
+ /* TODO: Mask out rates based on priv->rates_mask */
+
+ memset(rates, 0, sizeof(*rates));
+ /* configure supported rates */
+ switch (priv->ieee->freq_band) {
+ case IEEE80211_52GHZ_BAND:
+ rates->ieee_mode = IPW_A_MODE;
+ rates->purpose = IPW_RATE_CAPABILITIES;
+ ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_OFDM_DEFAULT_RATES_MASK);
+ break;
+
+ default: /* Mixed or 2.4Ghz */
+ rates->ieee_mode = IPW_G_MODE;
+ rates->purpose = IPW_RATE_CAPABILITIES;
+ ipw_add_cck_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_CCK_DEFAULT_RATES_MASK);
+ if (priv->ieee->modulation & IEEE80211_OFDM_MODULATION) {
+ ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION,
+ IEEE80211_OFDM_DEFAULT_RATES_MASK);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int ipw_config(struct ipw_priv *priv)
+{
+ int i;
+ struct ipw_tx_power tx_power;
+
+ memset(&priv->sys_config, 0, sizeof(priv->sys_config));
+ memset(&tx_power, 0, sizeof(tx_power));
+
+ /* This is only called from ipw_up, which resets/reloads the firmware
+ so, we don't need to first disable the card before we configure
+ it */
+
+ /* configure device for 'G' band */
+ tx_power.ieee_mode = IPW_G_MODE;
+ tx_power.num_channels = 11;
+ for (i = 0; i < 11; i++) {
+ tx_power.channels_tx_power[i].channel_number = i + 1;
+ tx_power.channels_tx_power[i].tx_power = priv->tx_power;
+ }
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* configure device to also handle 'B' band */
+ tx_power.ieee_mode = IPW_B_MODE;
+ if (ipw_send_tx_power(priv, &tx_power))
+ goto error;
+
+ /* initialize adapter address */
+ if (ipw_send_adapter_address(priv, priv->net_dev->dev_addr))
+ goto error;
+
+ /* set basic system config settings */
+ init_sys_config(&priv->sys_config);
+ if (ipw_send_system_config(priv, &priv->sys_config))
+ goto error;
+
+ init_supported_rates(priv, &priv->rates);
+ if (ipw_send_supported_rates(priv, &priv->rates))
+ goto error;
+
+ /* Set request-to-send threshold */
+ if (priv->rts_threshold) {
+ if (ipw_send_rts_threshold(priv, priv->rts_threshold))
+ goto error;
+ }
+
+ if (ipw_set_random_seed(priv))
+ goto error;
+
+ /* final state transition to the RUN state */
+ if (ipw_send_host_complete(priv))
+ goto error;
+
+ /* If configured to try and auto-associate, kick off a scan */
+ if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv))
+ goto error;
+
+ return 0;
+
+ error:
+ return -EIO;
+}
+
+#define MAX_HW_RESTARTS 5
+static int ipw_up(struct ipw_priv *priv)
+{
+ int rc, i;
+
+ if (priv->status & STATUS_EXIT_PENDING)
+ return -EIO;
+
+ for (i = 0; i < MAX_HW_RESTARTS; i++) {
+ /* Load the microcode, firmware, and eeprom.
+ * Also start the clocks. */
+ rc = ipw_load(priv);
+ if (rc) {
+ IPW_ERROR("Unable to load firmware: 0x%08X\n", rc);
+ return rc;
+ }
+
+ ipw_init_ordinals(priv);
+ if (!(priv->config & CFG_CUSTOM_MAC))
+ eeprom_parse_mac(priv, priv->mac_addr);
+ memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
+
+ if (priv->status & STATUS_RF_KILL_MASK)
+ return 0;
+
+ rc = ipw_config(priv);
+ if (!rc) {
+ IPW_DEBUG_INFO("Configured device on count %i\n", i);
+ priv->notif_missed_beacons = 0;
+ netif_start_queue(priv->net_dev);
+ return 0;
+ } else {
+ IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n",
+ rc);
+ }
+
+ IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n",
+ i, MAX_HW_RESTARTS);
+
+ /* We had an error bringing up the hardware, so take it
+ * all the way back down so we can try again */
+ ipw_down(priv);
+ }
+
+ /* tried to restart and config the device for as long as our
+ * patience could withstand */
+ IPW_ERROR("Unable to initialize device after %d attempts.\n", i);
+ return -EIO;
+}
+
+static void ipw_down(struct ipw_priv *priv)
+{
+ /* Attempt to disable the card */
+#if 0
+ ipw_send_card_disable(priv, 0);
+#endif
+
+ /* tell the device to stop sending interrupts */
+ ipw_disable_interrupts(priv);
+
+ /* Clear all bits but the RF Kill */
+ priv->status &= STATUS_RF_KILL_MASK;
+
+ netif_carrier_off(priv->net_dev);
+ netif_stop_queue(priv->net_dev);
+
+ ipw_stop_nic(priv);
+}
+
+/* Called by register_netdev() */
+static int ipw_net_init(struct net_device *dev)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+
+ if (priv->status & STATUS_RF_KILL_SW) {
+ IPW_WARNING("Radio disabled by module parameter.\n");
+ return 0;
+ } else if (rf_kill_active(priv)) {
+ IPW_WARNING("Radio Frequency Kill Switch is On:\n"
+ "Kill switch must be turned off for "
+ "wireless networking to work.\n");
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+ return 0;
+ }
+
+ if (ipw_up(priv))
+ return -EIO;
+
+ return 0;
+}
+
+/* PCI driver stuff */
+static struct pci_device_id card_ids[] = {
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2712, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2721, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2722, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2731, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2732, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2741, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x103c, 0x2741, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2742, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2751, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2752, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2753, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
+ {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 2225BG */
+ {PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+ {PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+
+ /* required last entry */
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, card_ids);
+
+static struct attribute *ipw_sysfs_entries[] = {
+ &dev_attr_rf_kill.attr,
+ &dev_attr_direct_dword.attr,
+ &dev_attr_indirect_byte.attr,
+ &dev_attr_indirect_dword.attr,
+ &dev_attr_mem_gpio_reg.attr,
+ &dev_attr_command_event_reg.attr,
+ &dev_attr_nic_type.attr,
+ &dev_attr_status.attr,
+ &dev_attr_cfg.attr,
+ &dev_attr_dump_errors.attr,
+ &dev_attr_dump_events.attr,
+ &dev_attr_eeprom_delay.attr,
+ &dev_attr_ucode_version.attr,
+ &dev_attr_rtc.attr,
+ NULL
+};
+
+static struct attribute_group ipw_attribute_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = ipw_sysfs_entries,
+};
+
+static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = 0;
+ struct net_device *net_dev;
+ void __iomem *base;
+ u32 length, val;
+ struct ipw_priv *priv;
+ int band, modulation;
+
+ net_dev = alloc_ieee80211(sizeof(struct ipw_priv));
+ if (net_dev == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ priv = ieee80211_priv(net_dev);
+ priv->ieee = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ priv->pci_dev = pdev;
+#ifdef CONFIG_IPW_DEBUG
+ ipw_debug_level = debug;
+#endif
+ spin_lock_init(&priv->lock);
+
+ if (pci_enable_device(pdev)) {
+ err = -ENODEV;
+ goto out_free_ieee80211;
+ }
+
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
+ goto out_pci_disable_device;
+ }
+
+ pci_set_drvdata(pdev, priv);
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err)
+ goto out_pci_disable_device;
+
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ length = pci_resource_len(pdev, 0);
+ priv->hw_len = length;
+
+ base = ioremap_nocache(pci_resource_start(pdev, 0), length);
+ if (!base) {
+ err = -ENODEV;
+ goto out_pci_release_regions;
+ }
+
+ priv->hw_base = base;
+ IPW_DEBUG_INFO("pci_resource_len = 0x%08x\n", length);
+ IPW_DEBUG_INFO("pci_resource_base = %p\n", base);
+
+ err = ipw_setup_deferred_work(priv);
+ if (err) {
+ IPW_ERROR("Unable to setup deferred work\n");
+ goto out_iounmap;
+ }
+
+ /* Initialize module parameter values here */
+ if (ifname)
+ strncpy(net_dev->name, ifname, IFNAMSIZ);
+
+ if (associate)
+ priv->config |= CFG_ASSOCIATE;
+ else
+ IPW_DEBUG_INFO("Auto associate disabled.\n");
+
+ if (auto_create)
+ priv->config |= CFG_ADHOC_CREATE;
+ else
+ IPW_DEBUG_INFO("Auto adhoc creation disabled.\n");
+
+ if (disable) {
+ priv->status |= STATUS_RF_KILL_SW;
+ IPW_DEBUG_INFO("Radio disabled.\n");
+ }
+
+ if (channel != 0) {
+ priv->config |= CFG_STATIC_CHANNEL;
+ priv->channel = channel;
+ IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
+ IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
+ /* TODO: Validate that provided channel is in range */
+ }
+
+ switch (mode) {
+ case 1:
+ priv->ieee->iw_mode = IW_MODE_ADHOC;
+ break;
+#ifdef CONFIG_IPW_PROMISC
+ case 2:
+ priv->ieee->iw_mode = IW_MODE_MONITOR;
+ break;
+#endif
+ default:
+ case 0:
+ priv->ieee->iw_mode = IW_MODE_INFRA;
+ break;
+ }
+
+ if ((priv->pci_dev->device == 0x4223) ||
+ (priv->pci_dev->device == 0x4224)) {
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2915ABG Network "
+ "Connection\n");
+ priv->ieee->abg_true = 1;
+ band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
+ modulation = IEEE80211_OFDM_MODULATION |
+ IEEE80211_CCK_MODULATION;
+ priv->adapter = IPW_2915ABG;
+ priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B;
+ } else {
+ if (priv->pci_dev->device == 0x4221)
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2225BG Network "
+ "Connection\n");
+ else
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel PRO/Wireless 2200BG Network "
+ "Connection\n");
+
+ priv->ieee->abg_true = 0;
+ band = IEEE80211_24GHZ_BAND;
+ modulation = IEEE80211_OFDM_MODULATION |
+ IEEE80211_CCK_MODULATION;
+ priv->adapter = IPW_2200BG;
+ priv->ieee->mode = IEEE_G | IEEE_B;
+ }
+
+ priv->ieee->freq_band = band;
+ priv->ieee->modulation = modulation;
+
+ priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK;
+
+ priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT;
+ priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;
+
+ priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
+
+ /* If power management is turned on, default to AC mode */
+ priv->power_mode = IPW_POWER_AC;
+ priv->tx_power = IPW_DEFAULT_TX_POWER;
+
+ err = request_irq(pdev->irq, ipw_isr, SA_SHIRQ, DRV_NAME, priv);
+ if (err) {
+ IPW_ERROR("Error allocating IRQ %d\n", pdev->irq);
+ goto out_destroy_workqueue;
+ }
+
+ SET_MODULE_OWNER(net_dev);
+ SET_NETDEV_DEV(net_dev, &pdev->dev);
+
+ priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
+ priv->ieee->set_security = shim__set_security;
+
+ net_dev->open = ipw_net_open;
+ net_dev->stop = ipw_net_stop;
+ net_dev->init = ipw_net_init;
+ net_dev->get_stats = ipw_net_get_stats;
+ net_dev->set_multicast_list = ipw_net_set_multicast_list;
+ net_dev->set_mac_address = ipw_net_set_mac_address;
+ net_dev->get_wireless_stats = ipw_get_wireless_stats;
+ net_dev->wireless_handlers = &ipw_wx_handler_def;
+ net_dev->ethtool_ops = &ipw_ethtool_ops;
+ net_dev->irq = pdev->irq;
+ net_dev->base_addr = (unsigned long)priv->hw_base;
+ net_dev->mem_start = pci_resource_start(pdev, 0);
+ net_dev->mem_end = net_dev->mem_start + pci_resource_len(pdev, 0) - 1;
+
+ err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
+ if (err) {
+ IPW_ERROR("failed to create sysfs device attributes\n");
+ goto out_release_irq;
+ }
+
+ err = register_netdev(net_dev);
+ if (err) {
+ IPW_ERROR("failed to register network device\n");
+ goto out_remove_group;
+ }
+
+ return 0;
+
+ out_remove_group:
+ sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
+ out_release_irq:
+ free_irq(pdev->irq, priv);
+ out_destroy_workqueue:
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ out_iounmap:
+ iounmap(priv->hw_base);
+ out_pci_release_regions:
+ pci_release_regions(pdev);
+ out_pci_disable_device:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ out_free_ieee80211:
+ free_ieee80211(priv->net_dev);
+ out:
+ return err;
+}
+
+static void ipw_pci_remove(struct pci_dev *pdev)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ if (!priv)
+ return;
+
+ priv->status |= STATUS_EXIT_PENDING;
+
+ sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
+
+ ipw_down(priv);
+
+ unregister_netdev(priv->net_dev);
+
+ if (priv->rxq) {
+ ipw_rx_queue_free(priv, priv->rxq);
+ priv->rxq = NULL;
+ }
+ ipw_tx_queue_free(priv);
+
+ /* ipw_down will ensure that there is no more pending work
+ * in the workqueue's, so we can safely remove them now. */
+ if (priv->workqueue) {
+ cancel_delayed_work(&priv->adhoc_check);
+ cancel_delayed_work(&priv->gather_stats);
+ cancel_delayed_work(&priv->request_scan);
+ cancel_delayed_work(&priv->rf_kill);
+ cancel_delayed_work(&priv->scan_check);
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
+ }
+
+ free_irq(pdev->irq, priv);
+ iounmap(priv->hw_base);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ free_ieee80211(priv->net_dev);
+
+#ifdef CONFIG_PM
+ if (fw_loaded) {
+ release_firmware(bootfw);
+ release_firmware(ucode);
+ release_firmware(firmware);
+ fw_loaded = 0;
+ }
+#endif
+}
+
+#ifdef CONFIG_PM
+static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ struct net_device *dev = priv->net_dev;
+
+ printk(KERN_INFO "%s: Going into suspend...\n", dev->name);
+
+ /* Take down the device; powers it off, etc. */
+ ipw_down(priv);
+
+ /* Remove the PRESENT state of the device */
+ netif_device_detach(dev);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int ipw_pci_resume(struct pci_dev *pdev)
+{
+ struct ipw_priv *priv = pci_get_drvdata(pdev);
+ struct net_device *dev = priv->net_dev;
+ u32 val;
+
+ printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name);
+
+ pci_set_power_state(pdev, 0);
+ pci_enable_device(pdev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+ pci_restore_state(pdev, priv->pm_state);
+#else
+ pci_restore_state(pdev);
+#endif
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
+ * from interfering with C3 CPU state. pci_restore_state won't help
+ * here since it only restores the first 64 bytes pci config header.
+ */
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ /* Set the device back into the PRESENT state; this will also wake
+ * the queue of needed */
+ netif_device_attach(dev);
+
+ /* Bring the device back up */
+ queue_work(priv->workqueue, &priv->up);
+
+ return 0;
+}
+#endif
+
+/* driver initialization stuff */
+static struct pci_driver ipw_driver = {
+ .name = DRV_NAME,
+ .id_table = card_ids,
+ .probe = ipw_pci_probe,
+ .remove = __devexit_p(ipw_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = ipw_pci_suspend,
+ .resume = ipw_pci_resume,
+#endif
+};
+
+static int __init ipw_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+
+ ret = pci_module_init(&ipw_driver);
+ if (ret) {
+ IPW_ERROR("Unable to initialize PCI module\n");
+ return ret;
+ }
+
+ ret = driver_create_file(&ipw_driver.driver, &driver_attr_debug_level);
+ if (ret) {
+ IPW_ERROR("Unable to create driver sysfs file\n");
+ pci_unregister_driver(&ipw_driver);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void __exit ipw_exit(void)
+{
+ driver_remove_file(&ipw_driver.driver, &driver_attr_debug_level);
+ pci_unregister_driver(&ipw_driver);
+}
+
+module_param(disable, int, 0444);
+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+
+module_param(associate, int, 0444);
+MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+
+module_param(auto_create, int, 0444);
+MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
+
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "debug output mask");
+
+module_param(channel, int, 0444);
+MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
+
+module_param(ifname, charp, 0444);
+MODULE_PARM_DESC(ifname, "network device name (default eth%d)");
+
+#ifdef CONFIG_IPW_PROMISC
+module_param(mode, int, 0444);
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
+#else
+module_param(mode, int, 0444);
+MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
+#endif
+
+module_exit(ipw_exit);
+module_init(ipw_init);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
new file mode 100644
index 000000000000..e9cf32bf3e31
--- /dev/null
+++ b/drivers/net/wireless/ipw2200.h
@@ -0,0 +1,1680 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ 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, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#ifndef __ipw2200_h__
+#define __ipw2200_h__
+
+#define WEXT_USECHANNELS 1
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/firmware.h>
+#include <linux/wireless.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+
+#include <net/ieee80211.h>
+
+#define DRV_NAME "ipw2200"
+
+#include <linux/workqueue.h>
+
+/* Authentication and Association States */
+enum connection_manager_assoc_states {
+ CMAS_INIT = 0,
+ CMAS_TX_AUTH_SEQ_1,
+ CMAS_RX_AUTH_SEQ_2,
+ CMAS_AUTH_SEQ_1_PASS,
+ CMAS_AUTH_SEQ_1_FAIL,
+ CMAS_TX_AUTH_SEQ_3,
+ CMAS_RX_AUTH_SEQ_4,
+ CMAS_AUTH_SEQ_2_PASS,
+ CMAS_AUTH_SEQ_2_FAIL,
+ CMAS_AUTHENTICATED,
+ CMAS_TX_ASSOC,
+ CMAS_RX_ASSOC_RESP,
+ CMAS_ASSOCIATED,
+ CMAS_LAST
+};
+
+#define IPW_WAIT (1<<0)
+#define IPW_QUIET (1<<1)
+#define IPW_ROAMING (1<<2)
+
+#define IPW_POWER_MODE_CAM 0x00 //(always on)
+#define IPW_POWER_INDEX_1 0x01
+#define IPW_POWER_INDEX_2 0x02
+#define IPW_POWER_INDEX_3 0x03
+#define IPW_POWER_INDEX_4 0x04
+#define IPW_POWER_INDEX_5 0x05
+#define IPW_POWER_AC 0x06
+#define IPW_POWER_BATTERY 0x07
+#define IPW_POWER_LIMIT 0x07
+#define IPW_POWER_MASK 0x0F
+#define IPW_POWER_ENABLED 0x10
+#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK)
+
+#define IPW_CMD_HOST_COMPLETE 2
+#define IPW_CMD_POWER_DOWN 4
+#define IPW_CMD_SYSTEM_CONFIG 6
+#define IPW_CMD_MULTICAST_ADDRESS 7
+#define IPW_CMD_SSID 8
+#define IPW_CMD_ADAPTER_ADDRESS 11
+#define IPW_CMD_PORT_TYPE 12
+#define IPW_CMD_RTS_THRESHOLD 15
+#define IPW_CMD_FRAG_THRESHOLD 16
+#define IPW_CMD_POWER_MODE 17
+#define IPW_CMD_WEP_KEY 18
+#define IPW_CMD_TGI_TX_KEY 19
+#define IPW_CMD_SCAN_REQUEST 20
+#define IPW_CMD_ASSOCIATE 21
+#define IPW_CMD_SUPPORTED_RATES 22
+#define IPW_CMD_SCAN_ABORT 23
+#define IPW_CMD_TX_FLUSH 24
+#define IPW_CMD_QOS_PARAMETERS 25
+#define IPW_CMD_SCAN_REQUEST_EXT 26
+#define IPW_CMD_DINO_CONFIG 30
+#define IPW_CMD_RSN_CAPABILITIES 31
+#define IPW_CMD_RX_KEY 32
+#define IPW_CMD_CARD_DISABLE 33
+#define IPW_CMD_SEED_NUMBER 34
+#define IPW_CMD_TX_POWER 35
+#define IPW_CMD_COUNTRY_INFO 36
+#define IPW_CMD_AIRONET_INFO 37
+#define IPW_CMD_AP_TX_POWER 38
+#define IPW_CMD_CCKM_INFO 39
+#define IPW_CMD_CCX_VER_INFO 40
+#define IPW_CMD_SET_CALIBRATION 41
+#define IPW_CMD_SENSITIVITY_CALIB 42
+#define IPW_CMD_RETRY_LIMIT 51
+#define IPW_CMD_IPW_PRE_POWER_DOWN 58
+#define IPW_CMD_VAP_BEACON_TEMPLATE 60
+#define IPW_CMD_VAP_DTIM_PERIOD 61
+#define IPW_CMD_EXT_SUPPORTED_RATES 62
+#define IPW_CMD_VAP_LOCAL_TX_PWR_CONSTRAINT 63
+#define IPW_CMD_VAP_QUIET_INTERVALS 64
+#define IPW_CMD_VAP_CHANNEL_SWITCH 65
+#define IPW_CMD_VAP_MANDATORY_CHANNELS 66
+#define IPW_CMD_VAP_CELL_PWR_LIMIT 67
+#define IPW_CMD_VAP_CF_PARAM_SET 68
+#define IPW_CMD_VAP_SET_BEACONING_STATE 69
+#define IPW_CMD_MEASUREMENT 80
+#define IPW_CMD_POWER_CAPABILITY 81
+#define IPW_CMD_SUPPORTED_CHANNELS 82
+#define IPW_CMD_TPC_REPORT 83
+#define IPW_CMD_WME_INFO 84
+#define IPW_CMD_PRODUCTION_COMMAND 85
+#define IPW_CMD_LINKSYS_EOU_INFO 90
+
+#define RFD_SIZE 4
+#define NUM_TFD_CHUNKS 6
+
+#define TX_QUEUE_SIZE 32
+#define RX_QUEUE_SIZE 32
+
+#define DINO_CMD_WEP_KEY 0x08
+#define DINO_CMD_TX 0x0B
+#define DCT_ANTENNA_A 0x01
+#define DCT_ANTENNA_B 0x02
+
+#define IPW_A_MODE 0
+#define IPW_B_MODE 1
+#define IPW_G_MODE 2
+
+/*
+ * TX Queue Flag Definitions
+ */
+
+/* abort attempt if mgmt frame is rx'd */
+#define DCT_FLAG_ABORT_MGMT 0x01
+
+/* require CTS */
+#define DCT_FLAG_CTS_REQUIRED 0x02
+
+/* use short preamble */
+#define DCT_FLAG_SHORT_PREMBL 0x04
+
+/* RTS/CTS first */
+#define DCT_FLAG_RTS_REQD 0x08
+
+/* dont calculate duration field */
+#define DCT_FLAG_DUR_SET 0x10
+
+/* even if MAC WEP set (allows pre-encrypt) */
+#define DCT_FLAG_NO_WEP 0x20
+
+/* overwrite TSF field */
+#define DCT_FLAG_TSF_REQD 0x40
+
+/* ACK rx is expected to follow */
+#define DCT_FLAG_ACK_REQD 0x80
+
+#define DCT_FLAG_EXT_MODE_CCK 0x01
+#define DCT_FLAG_EXT_MODE_OFDM 0x00
+
+#define TX_RX_TYPE_MASK 0xFF
+#define TX_FRAME_TYPE 0x00
+#define TX_HOST_COMMAND_TYPE 0x01
+#define RX_FRAME_TYPE 0x09
+#define RX_HOST_NOTIFICATION_TYPE 0x03
+#define RX_HOST_CMD_RESPONSE_TYPE 0x04
+#define RX_TX_FRAME_RESPONSE_TYPE 0x05
+#define TFD_NEED_IRQ_MASK 0x04
+
+#define HOST_CMD_DINO_CONFIG 30
+
+#define HOST_NOTIFICATION_STATUS_ASSOCIATED 10
+#define HOST_NOTIFICATION_STATUS_AUTHENTICATE 11
+#define HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT 12
+#define HOST_NOTIFICATION_STATUS_SCAN_COMPLETED 13
+#define HOST_NOTIFICATION_STATUS_FRAG_LENGTH 14
+#define HOST_NOTIFICATION_STATUS_LINK_DETERIORATION 15
+#define HOST_NOTIFICATION_DINO_CONFIG_RESPONSE 16
+#define HOST_NOTIFICATION_STATUS_BEACON_STATE 17
+#define HOST_NOTIFICATION_STATUS_TGI_TX_KEY 18
+#define HOST_NOTIFICATION_TX_STATUS 19
+#define HOST_NOTIFICATION_CALIB_KEEP_RESULTS 20
+#define HOST_NOTIFICATION_MEASUREMENT_STARTED 21
+#define HOST_NOTIFICATION_MEASUREMENT_ENDED 22
+#define HOST_NOTIFICATION_CHANNEL_SWITCHED 23
+#define HOST_NOTIFICATION_RX_DURING_QUIET_PERIOD 24
+#define HOST_NOTIFICATION_NOISE_STATS 25
+#define HOST_NOTIFICATION_S36_MEASUREMENT_ACCEPTED 30
+#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31
+
+#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1
+#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24
+#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8
+#define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300
+
+#define MACADRR_BYTE_LEN 6
+
+#define DCR_TYPE_AP 0x01
+#define DCR_TYPE_WLAP 0x02
+#define DCR_TYPE_MU_ESS 0x03
+#define DCR_TYPE_MU_IBSS 0x04
+#define DCR_TYPE_MU_PIBSS 0x05
+#define DCR_TYPE_SNIFFER 0x06
+#define DCR_TYPE_MU_BSS DCR_TYPE_MU_ESS
+
+/**
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct clx2_queue {
+ int n_bd; /**< number of BDs in this queue */
+ int first_empty; /**< 1-st empty entry (index) */
+ int last_used; /**< last used entry (index) */
+ u32 reg_w; /**< 'write' reg (queue head), addr in domain 1 */
+ u32 reg_r; /**< 'read' reg (queue tail), addr in domain 1 */
+ dma_addr_t dma_addr; /**< physical addr for BD's */
+ int low_mark; /**< low watermark, resume queue if free space more than this */
+ int high_mark; /**< high watermark, stop queue if free space less than this */
+} __attribute__ ((packed));
+
+struct machdr32 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+ u16 qos_ctrl;
+} __attribute__ ((packed));
+
+struct machdr30 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+} __attribute__ ((packed));
+
+struct machdr26 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+ u16 qos_ctrl;
+} __attribute__ ((packed));
+
+struct machdr24 {
+ u16 frame_ctl;
+ u16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+ u16 seq_ctrl; // more endians!
+} __attribute__ ((packed));
+
+// TX TFD with 32 byte MAC Header
+struct tx_tfd_32 {
+ struct machdr32 mchdr; // 32
+ u32 uivplaceholder[2]; // 8
+} __attribute__ ((packed));
+
+// TX TFD with 30 byte MAC Header
+struct tx_tfd_30 {
+ struct machdr30 mchdr; // 30
+ u8 reserved[2]; // 2
+ u32 uivplaceholder[2]; // 8
+} __attribute__ ((packed));
+
+// tx tfd with 26 byte mac header
+struct tx_tfd_26 {
+ struct machdr26 mchdr; // 26
+ u8 reserved1[2]; // 2
+ u32 uivplaceholder[2]; // 8
+ u8 reserved2[4]; // 4
+} __attribute__ ((packed));
+
+// tx tfd with 24 byte mac header
+struct tx_tfd_24 {
+ struct machdr24 mchdr; // 24
+ u32 uivplaceholder[2]; // 8
+ u8 reserved[8]; // 8
+} __attribute__ ((packed));
+
+#define DCT_WEP_KEY_FIELD_LENGTH 16
+
+struct tfd_command {
+ u8 index;
+ u8 length;
+ u16 reserved;
+ u8 payload[0];
+} __attribute__ ((packed));
+
+struct tfd_data {
+ /* Header */
+ u32 work_area_ptr;
+ u8 station_number; /* 0 for BSS */
+ u8 reserved1;
+ u16 reserved2;
+
+ /* Tx Parameters */
+ u8 cmd_id;
+ u8 seq_num;
+ u16 len;
+ u8 priority;
+ u8 tx_flags;
+ u8 tx_flags_ext;
+ u8 key_index;
+ u8 wepkey[DCT_WEP_KEY_FIELD_LENGTH];
+ u8 rate;
+ u8 antenna;
+ u16 next_packet_duration;
+ u16 next_frag_len;
+ u16 back_off_counter; //////txop;
+ u8 retrylimit;
+ u16 cwcurrent;
+ u8 reserved3;
+
+ /* 802.11 MAC Header */
+ union {
+ struct tx_tfd_24 tfd_24;
+ struct tx_tfd_26 tfd_26;
+ struct tx_tfd_30 tfd_30;
+ struct tx_tfd_32 tfd_32;
+ } tfd;
+
+ /* Payload DMA info */
+ u32 num_chunks;
+ u32 chunk_ptr[NUM_TFD_CHUNKS];
+ u16 chunk_len[NUM_TFD_CHUNKS];
+} __attribute__ ((packed));
+
+struct txrx_control_flags {
+ u8 message_type;
+ u8 rx_seq_num;
+ u8 control_bits;
+ u8 reserved;
+} __attribute__ ((packed));
+
+#define TFD_SIZE 128
+#define TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH (TFD_SIZE - sizeof(struct txrx_control_flags))
+
+struct tfd_frame {
+ struct txrx_control_flags control_flags;
+ union {
+ struct tfd_data data;
+ struct tfd_command cmd;
+ u8 raw[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+ } u;
+} __attribute__ ((packed));
+
+typedef void destructor_func(const void *);
+
+/**
+ * Tx Queue for DMA. Queue consists of circular buffer of
+ * BD's and required locking structures.
+ */
+struct clx2_tx_queue {
+ struct clx2_queue q;
+ struct tfd_frame *bd;
+ struct ieee80211_txb **txb;
+};
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 32
+#define RX_LOW_WATERMARK 8
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS (8)
+#define SUP_RATE_11B_MAX_NUM_CHANNELS (4)
+#define SUP_RATE_11G_MAX_NUM_CHANNELS (12)
+
+// Used for passing to driver number of successes and failures per rate
+struct rate_histogram {
+ union {
+ u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } success;
+ union {
+ u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } failed;
+} __attribute__ ((packed));
+
+/* statistics command response */
+struct ipw_cmd_stats {
+ u8 cmd_id;
+ u8 seq_num;
+ u16 good_sfd;
+ u16 bad_plcp;
+ u16 wrong_bssid;
+ u16 valid_mpdu;
+ u16 bad_mac_header;
+ u16 reserved_frame_types;
+ u16 rx_ina;
+ u16 bad_crc32;
+ u16 invalid_cts;
+ u16 invalid_acks;
+ u16 long_distance_ina_fina;
+ u16 dsp_silence_unreachable;
+ u16 accumulated_rssi;
+ u16 rx_ovfl_frame_tossed;
+ u16 rssi_silence_threshold;
+ u16 rx_ovfl_frame_supplied;
+ u16 last_rx_frame_signal;
+ u16 last_rx_frame_noise;
+ u16 rx_autodetec_no_ofdm;
+ u16 rx_autodetec_no_barker;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct notif_channel_result {
+ u8 channel_num;
+ struct ipw_cmd_stats stats;
+ u8 uReserved;
+} __attribute__ ((packed));
+
+struct notif_scan_complete {
+ u8 scan_type;
+ u8 num_channels;
+ u8 status;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct notif_frag_length {
+ u16 frag_length;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct notif_beacon_state {
+ u32 state;
+ u32 number;
+} __attribute__ ((packed));
+
+struct notif_tgi_tx_key {
+ u8 key_state;
+ u8 security_type;
+ u8 station_index;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct notif_link_deterioration {
+ struct ipw_cmd_stats stats;
+ u8 rate;
+ u8 modulation;
+ struct rate_histogram histogram;
+ u8 reserved1;
+ u16 reserved2;
+} __attribute__ ((packed));
+
+struct notif_association {
+ u8 state;
+} __attribute__ ((packed));
+
+struct notif_authenticate {
+ u8 state;
+ struct machdr24 addr;
+ u16 status;
+} __attribute__ ((packed));
+
+struct notif_calibration {
+ u8 data[104];
+} __attribute__ ((packed));
+
+struct notif_noise {
+ u32 value;
+} __attribute__ ((packed));
+
+struct ipw_rx_notification {
+ u8 reserved[8];
+ u8 subtype;
+ u8 flags;
+ u16 size;
+ union {
+ struct notif_association assoc;
+ struct notif_authenticate auth;
+ struct notif_channel_result channel_result;
+ struct notif_scan_complete scan_complete;
+ struct notif_frag_length frag_len;
+ struct notif_beacon_state beacon_state;
+ struct notif_tgi_tx_key tgi_tx_key;
+ struct notif_link_deterioration link_deterioration;
+ struct notif_calibration calibration;
+ struct notif_noise noise;
+ u8 raw[0];
+ } u;
+} __attribute__ ((packed));
+
+struct ipw_rx_frame {
+ u32 reserved1;
+ u8 parent_tsf[4]; // fw_use[0] is boolean for OUR_TSF_IS_GREATER
+ u8 received_channel; // The channel that this frame was received on.
+ // Note that for .11b this does not have to be
+ // the same as the channel that it was sent.
+ // Filled by LMAC
+ u8 frameStatus;
+ u8 rate;
+ u8 rssi;
+ u8 agc;
+ u8 rssi_dbm;
+ u16 signal;
+ u16 noise;
+ u8 antennaAndPhy;
+ u8 control; // control bit should be on in bg
+ u8 rtscts_rate; // rate of rts or cts (in rts cts sequence rate
+ // is identical)
+ u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen
+ u16 length;
+ u8 data[0];
+} __attribute__ ((packed));
+
+struct ipw_rx_header {
+ u8 message_type;
+ u8 rx_seq_num;
+ u8 control_bits;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_rx_packet {
+ struct ipw_rx_header header;
+ union {
+ struct ipw_rx_frame frame;
+ struct ipw_rx_notification notification;
+ } u;
+} __attribute__ ((packed));
+
+#define IPW_RX_NOTIFICATION_SIZE sizeof(struct ipw_rx_header) + 12
+#define IPW_RX_FRAME_SIZE sizeof(struct ipw_rx_header) + \
+ sizeof(struct ipw_rx_frame)
+
+struct ipw_rx_mem_buffer {
+ dma_addr_t dma_addr;
+ struct ipw_rx_buffer *rxb;
+ struct sk_buff *skb;
+ struct list_head list;
+}; /* Not transferred over network, so not __attribute__ ((packed)) */
+
+struct ipw_rx_queue {
+ struct ipw_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct ipw_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ u32 processed; /* Internal index to last handled Rx packet */
+ u32 read; /* Shared index to newest available Rx buffer */
+ u32 write; /* Shared index to oldest written Rx packet */
+ u32 free_count; /* Number of pre-allocated buffers in rx_free */
+ /* Each of these lists is used as a FIFO for ipw_rx_mem_buffers */
+ struct list_head rx_free; /* Own an SKBs */
+ struct list_head rx_used; /* No SKB allocated */
+ spinlock_t lock;
+}; /* Not transferred over network, so not __attribute__ ((packed)) */
+
+struct alive_command_responce {
+ u8 alive_command;
+ u8 sequence_number;
+ u16 software_revision;
+ u8 device_identifier;
+ u8 reserved1[5];
+ u16 reserved2;
+ u16 reserved3;
+ u16 clock_settle_time;
+ u16 powerup_settle_time;
+ u16 reserved4;
+ u8 time_stamp[5]; /* month, day, year, hours, minutes */
+ u8 ucode_valid;
+} __attribute__ ((packed));
+
+#define IPW_MAX_RATES 12
+
+struct ipw_rates {
+ u8 num_rates;
+ u8 rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct command_block {
+ unsigned int control;
+ u32 source_addr;
+ u32 dest_addr;
+ unsigned int status;
+} __attribute__ ((packed));
+
+#define CB_NUMBER_OF_ELEMENTS_SMALL 64
+struct fw_image_desc {
+ unsigned long last_cb_index;
+ unsigned long current_cb_index;
+ struct command_block cb_list[CB_NUMBER_OF_ELEMENTS_SMALL];
+ void *v_addr;
+ unsigned long p_addr;
+ unsigned long len;
+};
+
+struct ipw_sys_config {
+ u8 bt_coexistence;
+ u8 reserved1;
+ u8 answer_broadcast_ssid_probe;
+ u8 accept_all_data_frames;
+ u8 accept_non_directed_frames;
+ u8 exclude_unicast_unencrypted;
+ u8 disable_unicast_decryption;
+ u8 exclude_multicast_unencrypted;
+ u8 disable_multicast_decryption;
+ u8 antenna_diversity;
+ u8 pass_crc_to_host;
+ u8 dot11g_auto_detection;
+ u8 enable_cts_to_self;
+ u8 enable_multicast_filtering;
+ u8 bt_coexist_collision_thr;
+ u8 reserved2;
+ u8 accept_all_mgmt_bcpr;
+ u8 accept_all_mgtm_frames;
+ u8 pass_noise_stats_to_host;
+ u8 reserved3;
+} __attribute__ ((packed));
+
+struct ipw_multicast_addr {
+ u8 num_of_multicast_addresses;
+ u8 reserved[3];
+ u8 mac1[6];
+ u8 mac2[6];
+ u8 mac3[6];
+ u8 mac4[6];
+} __attribute__ ((packed));
+
+struct ipw_wep_key {
+ u8 cmd_id;
+ u8 seq_num;
+ u8 key_index;
+ u8 key_size;
+ u8 key[16];
+} __attribute__ ((packed));
+
+struct ipw_tgi_tx_key {
+ u8 key_id;
+ u8 security_type;
+ u8 station_index;
+ u8 flags;
+ u8 key[16];
+ u32 tx_counter[2];
+} __attribute__ ((packed));
+
+#define IPW_SCAN_CHANNELS 54
+
+struct ipw_scan_request {
+ u8 scan_type;
+ u16 dwell_time;
+ u8 channels_list[IPW_SCAN_CHANNELS];
+ u8 channels_reserved[3];
+} __attribute__ ((packed));
+
+enum {
+ IPW_SCAN_PASSIVE_TILL_FIRST_BEACON_SCAN = 0,
+ IPW_SCAN_PASSIVE_FULL_DWELL_SCAN,
+ IPW_SCAN_ACTIVE_DIRECT_SCAN,
+ IPW_SCAN_ACTIVE_BROADCAST_SCAN,
+ IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN,
+ IPW_SCAN_TYPES
+};
+
+struct ipw_scan_request_ext {
+ u32 full_scan_index;
+ u8 channels_list[IPW_SCAN_CHANNELS];
+ u8 scan_type[IPW_SCAN_CHANNELS / 2];
+ u8 reserved;
+ u16 dwell_time[IPW_SCAN_TYPES];
+} __attribute__ ((packed));
+
+extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
+{
+ if (index % 2)
+ return scan->scan_type[index / 2] & 0x0F;
+ else
+ return (scan->scan_type[index / 2] & 0xF0) >> 4;
+}
+
+extern inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+ u8 index, u8 scan_type)
+{
+ if (index % 2)
+ scan->scan_type[index / 2] =
+ (scan->scan_type[index / 2] & 0xF0) | (scan_type & 0x0F);
+ else
+ scan->scan_type[index / 2] =
+ (scan->scan_type[index / 2] & 0x0F) |
+ ((scan_type & 0x0F) << 4);
+}
+
+struct ipw_associate {
+ u8 channel;
+ u8 auth_type:4, auth_key:4;
+ u8 assoc_type;
+ u8 reserved;
+ u16 policy_support;
+ u8 preamble_length;
+ u8 ieee_mode;
+ u8 bssid[ETH_ALEN];
+ u32 assoc_tsf_msw;
+ u32 assoc_tsf_lsw;
+ u16 capability;
+ u16 listen_interval;
+ u16 beacon_interval;
+ u8 dest[ETH_ALEN];
+ u16 atim_window;
+ u8 smr;
+ u8 reserved1;
+ u16 reserved2;
+} __attribute__ ((packed));
+
+struct ipw_supported_rates {
+ u8 ieee_mode;
+ u8 num_rates;
+ u8 purpose;
+ u8 reserved;
+ u8 supported_rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct ipw_rts_threshold {
+ u16 rts_threshold;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_frag_threshold {
+ u16 frag_threshold;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_retry_limit {
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_dino_config {
+ u32 dino_config_addr;
+ u16 dino_config_size;
+ u8 dino_response;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_aironet_info {
+ u8 id;
+ u8 length;
+ u16 reserved;
+} __attribute__ ((packed));
+
+struct ipw_rx_key {
+ u8 station_index;
+ u8 key_type;
+ u8 key_id;
+ u8 key_flag;
+ u8 key[16];
+ u8 station_address[6];
+ u8 key_index;
+ u8 reserved;
+} __attribute__ ((packed));
+
+struct ipw_country_channel_info {
+ u8 first_channel;
+ u8 no_channels;
+ s8 max_tx_power;
+} __attribute__ ((packed));
+
+struct ipw_country_info {
+ u8 id;
+ u8 length;
+ u8 country_str[3];
+ struct ipw_country_channel_info groups[7];
+} __attribute__ ((packed));
+
+struct ipw_channel_tx_power {
+ u8 channel_number;
+ s8 tx_power;
+} __attribute__ ((packed));
+
+#define SCAN_ASSOCIATED_INTERVAL (HZ)
+#define SCAN_INTERVAL (HZ / 10)
+#define MAX_A_CHANNELS 37
+#define MAX_B_CHANNELS 14
+
+struct ipw_tx_power {
+ u8 num_channels;
+ u8 ieee_mode;
+ struct ipw_channel_tx_power channels_tx_power[MAX_A_CHANNELS];
+} __attribute__ ((packed));
+
+struct ipw_qos_parameters {
+ u16 cw_min[4];
+ u16 cw_max[4];
+ u8 aifs[4];
+ u8 flag[4];
+ u16 tx_op_limit[4];
+} __attribute__ ((packed));
+
+struct ipw_rsn_capabilities {
+ u8 id;
+ u8 length;
+ u16 version;
+} __attribute__ ((packed));
+
+struct ipw_sensitivity_calib {
+ u16 beacon_rssi_raw;
+ u16 reserved;
+} __attribute__ ((packed));
+
+/**
+ * Host command structure.
+ *
+ * On input, the following fields should be filled:
+ * - cmd
+ * - len
+ * - status_len
+ * - param (if needed)
+ *
+ * On output,
+ * - \a status contains status;
+ * - \a param filled with status parameters.
+ */
+struct ipw_cmd {
+ u32 cmd; /**< Host command */
+ u32 status;/**< Status */
+ u32 status_len;
+ /**< How many 32 bit parameters in the status */
+ u32 len; /**< incoming parameters length, bytes */
+ /**
+ * command parameters.
+ * There should be enough space for incoming and
+ * outcoming parameters.
+ * Incoming parameters listed 1-st, followed by outcoming params.
+ * nParams=(len+3)/4+status_len
+ */
+ u32 param[0];
+} __attribute__ ((packed));
+
+#define STATUS_HCMD_ACTIVE (1<<0) /**< host command in progress */
+
+#define STATUS_INT_ENABLED (1<<1)
+#define STATUS_RF_KILL_HW (1<<2)
+#define STATUS_RF_KILL_SW (1<<3)
+#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW)
+
+#define STATUS_INIT (1<<5)
+#define STATUS_AUTH (1<<6)
+#define STATUS_ASSOCIATED (1<<7)
+#define STATUS_STATE_MASK (STATUS_INIT | STATUS_AUTH | STATUS_ASSOCIATED)
+
+#define STATUS_ASSOCIATING (1<<8)
+#define STATUS_DISASSOCIATING (1<<9)
+#define STATUS_ROAMING (1<<10)
+#define STATUS_EXIT_PENDING (1<<11)
+#define STATUS_DISASSOC_PENDING (1<<12)
+#define STATUS_STATE_PENDING (1<<13)
+
+#define STATUS_SCAN_PENDING (1<<20)
+#define STATUS_SCANNING (1<<21)
+#define STATUS_SCAN_ABORTING (1<<22)
+
+#define STATUS_INDIRECT_BYTE (1<<28) /* sysfs entry configured for access */
+#define STATUS_INDIRECT_DWORD (1<<29) /* sysfs entry configured for access */
+#define STATUS_DIRECT_DWORD (1<<30) /* sysfs entry configured for access */
+
+#define STATUS_SECURITY_UPDATED (1<<31) /* Security sync needed */
+
+#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */
+#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */
+#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */
+#define CFG_CUSTOM_MAC (1<<3)
+#define CFG_PREAMBLE (1<<4)
+#define CFG_ADHOC_PERSIST (1<<5)
+#define CFG_ASSOCIATE (1<<6)
+#define CFG_FIXED_RATE (1<<7)
+#define CFG_ADHOC_CREATE (1<<8)
+
+#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */
+#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */
+
+#define MAX_STATIONS 32
+#define IPW_INVALID_STATION (0xff)
+
+struct ipw_station_entry {
+ u8 mac_addr[ETH_ALEN];
+ u8 reserved;
+ u8 support_mode;
+};
+
+#define AVG_ENTRIES 8
+struct average {
+ s16 entries[AVG_ENTRIES];
+ u8 pos;
+ u8 init;
+ s32 sum;
+};
+
+struct ipw_priv {
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_device *ieee;
+ struct ieee80211_security sec;
+
+ /* spinlock */
+ spinlock_t lock;
+
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+ struct net_device *net_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+ unsigned long hw_len;
+
+ struct fw_image_desc sram_desc;
+
+ /* result of ucode download */
+ struct alive_command_responce dino_alive;
+
+ wait_queue_head_t wait_command_queue;
+ wait_queue_head_t wait_state;
+
+ /* Rx and Tx DMA processing queues */
+ struct ipw_rx_queue *rxq;
+ struct clx2_tx_queue txq_cmd;
+ struct clx2_tx_queue txq[4];
+ u32 status;
+ u32 config;
+ u32 capability;
+
+ u8 last_rx_rssi;
+ u8 last_noise;
+ struct average average_missed_beacons;
+ struct average average_rssi;
+ struct average average_noise;
+ u32 port_type;
+ int rx_bufs_min; /**< minimum number of bufs in Rx queue */
+ int rx_pend_max; /**< maximum pending buffers for one IRQ */
+ u32 hcmd_seq; /**< sequence number for hcmd */
+ u32 missed_beacon_threshold;
+ u32 roaming_threshold;
+
+ struct ipw_associate assoc_request;
+ struct ieee80211_network *assoc_network;
+
+ unsigned long ts_scan_abort;
+ struct ipw_supported_rates rates;
+ struct ipw_rates phy[3]; /**< PHY restrictions, per band */
+ struct ipw_rates supp; /**< software defined */
+ struct ipw_rates extended; /**< use for corresp. IE, AP only */
+
+ struct notif_link_deterioration last_link_deterioration; /** for statistics */
+ struct ipw_cmd *hcmd; /**< host command currently executed */
+
+ wait_queue_head_t hcmd_wq; /**< host command waits for execution */
+ u32 tsf_bcn[2]; /**< TSF from latest beacon */
+
+ struct notif_calibration calib; /**< last calibration */
+
+ /* ordinal interface with firmware */
+ u32 table0_addr;
+ u32 table0_len;
+ u32 table1_addr;
+ u32 table1_len;
+ u32 table2_addr;
+ u32 table2_len;
+
+ /* context information */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u8 nick[IW_ESSID_MAX_SIZE];
+ u16 rates_mask;
+ u8 channel;
+ struct ipw_sys_config sys_config;
+ u32 power_mode;
+ u8 bssid[ETH_ALEN];
+ u16 rts_threshold;
+ u8 mac_addr[ETH_ALEN];
+ u8 num_stations;
+ u8 stations[MAX_STATIONS][ETH_ALEN];
+
+ u32 notif_missed_beacons;
+
+ /* Statistics and counters normalized with each association */
+ u32 last_missed_beacons;
+ u32 last_tx_packets;
+ u32 last_rx_packets;
+ u32 last_tx_failures;
+ u32 last_rx_err;
+ u32 last_rate;
+
+ u32 missed_adhoc_beacons;
+ u32 missed_beacons;
+ u32 rx_packets;
+ u32 tx_packets;
+ u32 quality;
+
+ /* eeprom */
+ u8 eeprom[0x100]; /* 256 bytes of eeprom */
+ int eeprom_delay;
+
+ struct iw_statistics wstats;
+
+ struct workqueue_struct *workqueue;
+
+ struct work_struct adhoc_check;
+ struct work_struct associate;
+ struct work_struct disassociate;
+ struct work_struct rx_replenish;
+ struct work_struct request_scan;
+ struct work_struct adapter_restart;
+ struct work_struct rf_kill;
+ struct work_struct up;
+ struct work_struct down;
+ struct work_struct gather_stats;
+ struct work_struct abort_scan;
+ struct work_struct roam;
+ struct work_struct scan_check;
+
+ struct tasklet_struct irq_tasklet;
+
+#define IPW_2200BG 1
+#define IPW_2915ABG 2
+ u8 adapter;
+
+#define IPW_DEFAULT_TX_POWER 0x14
+ u8 tx_power;
+
+#ifdef CONFIG_PM
+ u32 pm_state[16];
+#endif
+
+ /* network state */
+
+ /* Used to pass the current INTA value from ISR to Tasklet */
+ u32 isr_inta;
+
+ /* debugging info */
+ u32 indirect_dword;
+ u32 direct_dword;
+ u32 indirect_byte;
+}; /*ipw_priv */
+
+/* debug macros */
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_DEBUG(level, fmt, args...) \
+do { if (ipw_debug_level & (level)) \
+ printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+#else
+#define IPW_DEBUG(level, fmt, args...) do {} while (0)
+#endif /* CONFIG_IPW_DEBUG */
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IPW_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IPW_xxxx_DEBUG() macro definition for your
+ * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw then you do not have
+ * CONFIG_IPW_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IPW_DL_ERROR (1<<0)
+#define IPW_DL_WARNING (1<<1)
+#define IPW_DL_INFO (1<<2)
+#define IPW_DL_WX (1<<3)
+#define IPW_DL_HOST_COMMAND (1<<5)
+#define IPW_DL_STATE (1<<6)
+
+#define IPW_DL_NOTIF (1<<10)
+#define IPW_DL_SCAN (1<<11)
+#define IPW_DL_ASSOC (1<<12)
+#define IPW_DL_DROP (1<<13)
+#define IPW_DL_IOCTL (1<<14)
+
+#define IPW_DL_MANAGE (1<<15)
+#define IPW_DL_FW (1<<16)
+#define IPW_DL_RF_KILL (1<<17)
+#define IPW_DL_FW_ERRORS (1<<18)
+
+#define IPW_DL_ORD (1<<20)
+
+#define IPW_DL_FRAG (1<<21)
+#define IPW_DL_WEP (1<<22)
+#define IPW_DL_TX (1<<23)
+#define IPW_DL_RX (1<<24)
+#define IPW_DL_ISR (1<<25)
+#define IPW_DL_FW_INFO (1<<26)
+#define IPW_DL_IO (1<<27)
+#define IPW_DL_TRACE (1<<28)
+
+#define IPW_DL_STATS (1<<29)
+
+#define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+#define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+#define IPW_DEBUG_INFO(f, a...) IPW_DEBUG(IPW_DL_INFO, f, ## a)
+
+#define IPW_DEBUG_WX(f, a...) IPW_DEBUG(IPW_DL_WX, f, ## a)
+#define IPW_DEBUG_SCAN(f, a...) IPW_DEBUG(IPW_DL_SCAN, f, ## a)
+#define IPW_DEBUG_STATUS(f, a...) IPW_DEBUG(IPW_DL_STATUS, f, ## a)
+#define IPW_DEBUG_TRACE(f, a...) IPW_DEBUG(IPW_DL_TRACE, f, ## a)
+#define IPW_DEBUG_RX(f, a...) IPW_DEBUG(IPW_DL_RX, f, ## a)
+#define IPW_DEBUG_TX(f, a...) IPW_DEBUG(IPW_DL_TX, f, ## a)
+#define IPW_DEBUG_ISR(f, a...) IPW_DEBUG(IPW_DL_ISR, f, ## a)
+#define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a)
+#define IPW_DEBUG_WEP(f, a...) IPW_DEBUG(IPW_DL_WEP, f, ## a)
+#define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a)
+#define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a)
+#define IPW_DEBUG_FW(f, a...) IPW_DEBUG(IPW_DL_FW, f, ## a)
+#define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a)
+#define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a)
+#define IPW_DEBUG_IO(f, a...) IPW_DEBUG(IPW_DL_IO, f, ## a)
+#define IPW_DEBUG_ORD(f, a...) IPW_DEBUG(IPW_DL_ORD, f, ## a)
+#define IPW_DEBUG_FW_INFO(f, a...) IPW_DEBUG(IPW_DL_FW_INFO, f, ## a)
+#define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a)
+#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
+#define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a)
+
+#include <linux/ctype.h>
+
+/*
+* Register bit definitions
+*/
+
+/* Dino control registers bits */
+
+#define DINO_ENABLE_SYSTEM 0x80
+#define DINO_ENABLE_CS 0x40
+#define DINO_RXFIFO_DATA 0x01
+#define DINO_CONTROL_REG 0x00200000
+
+#define CX2_INTA_RW 0x00000008
+#define CX2_INTA_MASK_R 0x0000000C
+#define CX2_INDIRECT_ADDR 0x00000010
+#define CX2_INDIRECT_DATA 0x00000014
+#define CX2_AUTOINC_ADDR 0x00000018
+#define CX2_AUTOINC_DATA 0x0000001C
+#define CX2_RESET_REG 0x00000020
+#define CX2_GP_CNTRL_RW 0x00000024
+
+#define CX2_READ_INT_REGISTER 0xFF4
+
+#define CX2_GP_CNTRL_BIT_INIT_DONE 0x00000004
+
+#define CX2_REGISTER_DOMAIN1_END 0x00001000
+#define CX2_SRAM_READ_INT_REGISTER 0x00000ff4
+
+#define CX2_SHARED_LOWER_BOUND 0x00000200
+#define CX2_INTERRUPT_AREA_LOWER_BOUND 0x00000f80
+
+#define CX2_NIC_SRAM_LOWER_BOUND 0x00000000
+#define CX2_NIC_SRAM_UPPER_BOUND 0x00030000
+
+#define CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER (1 << 29)
+#define CX2_GP_CNTRL_BIT_CLOCK_READY 0x00000001
+#define CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY 0x00000002
+
+/*
+ * RESET Register Bit Indexes
+ */
+#define CBD_RESET_REG_PRINCETON_RESET 0x00000001 /* Bit 0 (LSB) */
+#define CX2_RESET_REG_SW_RESET 0x00000080 /* Bit 7 */
+#define CX2_RESET_REG_MASTER_DISABLED 0x00000100 /* Bit 8 */
+#define CX2_RESET_REG_STOP_MASTER 0x00000200 /* Bit 9 */
+#define CX2_ARC_KESHET_CONFIG 0x08000000 /* Bit 27 */
+#define CX2_START_STANDBY 0x00000004 /* Bit 2 */
+
+#define CX2_CSR_CIS_UPPER_BOUND 0x00000200
+#define CX2_DOMAIN_0_END 0x1000
+#define CLX_MEM_BAR_SIZE 0x1000
+
+#define CX2_BASEBAND_CONTROL_STATUS 0X00200000
+#define CX2_BASEBAND_TX_FIFO_WRITE 0X00200004
+#define CX2_BASEBAND_RX_FIFO_READ 0X00200004
+#define CX2_BASEBAND_CONTROL_STORE 0X00200010
+
+#define CX2_INTERNAL_CMD_EVENT 0X00300004
+#define CX2_BASEBAND_POWER_DOWN 0x00000001
+
+#define CX2_MEM_HALT_AND_RESET 0x003000e0
+
+/* defgroup bits_halt_reset MEM_HALT_AND_RESET register bits */
+#define CX2_BIT_HALT_RESET_ON 0x80000000
+#define CX2_BIT_HALT_RESET_OFF 0x00000000
+
+#define CB_LAST_VALID 0x20000000
+#define CB_INT_ENABLED 0x40000000
+#define CB_VALID 0x80000000
+#define CB_SRC_LE 0x08000000
+#define CB_DEST_LE 0x04000000
+#define CB_SRC_AUTOINC 0x00800000
+#define CB_SRC_IO_GATED 0x00400000
+#define CB_DEST_AUTOINC 0x00080000
+#define CB_SRC_SIZE_LONG 0x00200000
+#define CB_DEST_SIZE_LONG 0x00020000
+
+/* DMA DEFINES */
+
+#define DMA_CONTROL_SMALL_CB_CONST_VALUE 0x00540000
+#define DMA_CB_STOP_AND_ABORT 0x00000C00
+#define DMA_CB_START 0x00000100
+
+#define CX2_SHARED_SRAM_SIZE 0x00030000
+#define CX2_SHARED_SRAM_DMA_CONTROL 0x00027000
+#define CB_MAX_LENGTH 0x1FFF
+
+#define CX2_HOST_EEPROM_DATA_SRAM_SIZE 0xA18
+#define CX2_EEPROM_IMAGE_SIZE 0x100
+
+/* DMA defs */
+#define CX2_DMA_I_CURRENT_CB 0x003000D0
+#define CX2_DMA_O_CURRENT_CB 0x003000D4
+#define CX2_DMA_I_DMA_CONTROL 0x003000A4
+#define CX2_DMA_I_CB_BASE 0x003000A0
+
+#define CX2_TX_CMD_QUEUE_BD_BASE (0x00000200)
+#define CX2_TX_CMD_QUEUE_BD_SIZE (0x00000204)
+#define CX2_TX_QUEUE_0_BD_BASE (0x00000208)
+#define CX2_TX_QUEUE_0_BD_SIZE (0x0000020C)
+#define CX2_TX_QUEUE_1_BD_BASE (0x00000210)
+#define CX2_TX_QUEUE_1_BD_SIZE (0x00000214)
+#define CX2_TX_QUEUE_2_BD_BASE (0x00000218)
+#define CX2_TX_QUEUE_2_BD_SIZE (0x0000021C)
+#define CX2_TX_QUEUE_3_BD_BASE (0x00000220)
+#define CX2_TX_QUEUE_3_BD_SIZE (0x00000224)
+#define CX2_RX_BD_BASE (0x00000240)
+#define CX2_RX_BD_SIZE (0x00000244)
+#define CX2_RFDS_TABLE_LOWER (0x00000500)
+
+#define CX2_TX_CMD_QUEUE_READ_INDEX (0x00000280)
+#define CX2_TX_QUEUE_0_READ_INDEX (0x00000284)
+#define CX2_TX_QUEUE_1_READ_INDEX (0x00000288)
+#define CX2_TX_QUEUE_2_READ_INDEX (0x0000028C)
+#define CX2_TX_QUEUE_3_READ_INDEX (0x00000290)
+#define CX2_RX_READ_INDEX (0x000002A0)
+
+#define CX2_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80)
+#define CX2_TX_QUEUE_0_WRITE_INDEX (0x00000F84)
+#define CX2_TX_QUEUE_1_WRITE_INDEX (0x00000F88)
+#define CX2_TX_QUEUE_2_WRITE_INDEX (0x00000F8C)
+#define CX2_TX_QUEUE_3_WRITE_INDEX (0x00000F90)
+#define CX2_RX_WRITE_INDEX (0x00000FA0)
+
+/*
+ * EEPROM Related Definitions
+ */
+
+#define IPW_EEPROM_DATA_SRAM_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x814)
+#define IPW_EEPROM_DATA_SRAM_SIZE (CX2_SHARED_LOWER_BOUND + 0x818)
+#define IPW_EEPROM_LOAD_DISABLE (CX2_SHARED_LOWER_BOUND + 0x81C)
+#define IPW_EEPROM_DATA (CX2_SHARED_LOWER_BOUND + 0x820)
+#define IPW_EEPROM_UPPER_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x9E0)
+
+#define IPW_STATION_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0xA0C)
+#define IPW_STATION_TABLE_UPPER (CX2_SHARED_LOWER_BOUND + 0xB0C)
+#define IPW_REQUEST_ATIM (CX2_SHARED_LOWER_BOUND + 0xB0C)
+#define IPW_ATIM_SENT (CX2_SHARED_LOWER_BOUND + 0xB10)
+#define IPW_WHO_IS_AWAKE (CX2_SHARED_LOWER_BOUND + 0xB14)
+#define IPW_DURING_ATIM_WINDOW (CX2_SHARED_LOWER_BOUND + 0xB18)
+
+#define MSB 1
+#define LSB 0
+#define WORD_TO_BYTE(_word) ((_word) * sizeof(u16))
+
+#define GET_EEPROM_ADDR(_wordoffset,_byteoffset) \
+ ( WORD_TO_BYTE(_wordoffset) + (_byteoffset) )
+
+/* EEPROM access by BYTE */
+#define EEPROM_PME_CAPABILITY (GET_EEPROM_ADDR(0x09,MSB)) /* 1 byte */
+#define EEPROM_MAC_ADDRESS (GET_EEPROM_ADDR(0x21,LSB)) /* 6 byte */
+#define EEPROM_VERSION (GET_EEPROM_ADDR(0x24,MSB)) /* 1 byte */
+#define EEPROM_NIC_TYPE (GET_EEPROM_ADDR(0x25,LSB)) /* 1 byte */
+#define EEPROM_SKU_CAPABILITY (GET_EEPROM_ADDR(0x25,MSB)) /* 1 byte */
+#define EEPROM_COUNTRY_CODE (GET_EEPROM_ADDR(0x26,LSB)) /* 3 bytes */
+#define EEPROM_IBSS_CHANNELS_BG (GET_EEPROM_ADDR(0x28,LSB)) /* 2 bytes */
+#define EEPROM_IBSS_CHANNELS_A (GET_EEPROM_ADDR(0x29,MSB)) /* 5 bytes */
+#define EEPROM_BSS_CHANNELS_BG (GET_EEPROM_ADDR(0x2c,LSB)) /* 2 bytes */
+#define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */
+
+/* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/
+#define EEPROM_NIC_TYPE_STANDARD 0
+#define EEPROM_NIC_TYPE_DELL 1
+#define EEPROM_NIC_TYPE_FUJITSU 2
+#define EEPROM_NIC_TYPE_IBM 3
+#define EEPROM_NIC_TYPE_HP 4
+
+#define FW_MEM_REG_LOWER_BOUND 0x00300000
+#define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40)
+
+#define EEPROM_BIT_SK (1<<0)
+#define EEPROM_BIT_CS (1<<1)
+#define EEPROM_BIT_DI (1<<2)
+#define EEPROM_BIT_DO (1<<4)
+
+#define EEPROM_CMD_READ 0x2
+
+/* Interrupts masks */
+#define CX2_INTA_NONE 0x00000000
+
+#define CX2_INTA_BIT_RX_TRANSFER 0x00000002
+#define CX2_INTA_BIT_STATUS_CHANGE 0x00000010
+#define CX2_INTA_BIT_BEACON_PERIOD_EXPIRED 0x00000020
+
+//Inta Bits for CF
+#define CX2_INTA_BIT_TX_CMD_QUEUE 0x00000800
+#define CX2_INTA_BIT_TX_QUEUE_1 0x00001000
+#define CX2_INTA_BIT_TX_QUEUE_2 0x00002000
+#define CX2_INTA_BIT_TX_QUEUE_3 0x00004000
+#define CX2_INTA_BIT_TX_QUEUE_4 0x00008000
+
+#define CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE 0x00010000
+
+#define CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN 0x00100000
+#define CX2_INTA_BIT_POWER_DOWN 0x00200000
+
+#define CX2_INTA_BIT_FW_INITIALIZATION_DONE 0x01000000
+#define CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE 0x02000000
+#define CX2_INTA_BIT_RF_KILL_DONE 0x04000000
+#define CX2_INTA_BIT_FATAL_ERROR 0x40000000
+#define CX2_INTA_BIT_PARITY_ERROR 0x80000000
+
+/* Interrupts enabled at init time. */
+#define CX2_INTA_MASK_ALL \
+ (CX2_INTA_BIT_TX_QUEUE_1 | \
+ CX2_INTA_BIT_TX_QUEUE_2 | \
+ CX2_INTA_BIT_TX_QUEUE_3 | \
+ CX2_INTA_BIT_TX_QUEUE_4 | \
+ CX2_INTA_BIT_TX_CMD_QUEUE | \
+ CX2_INTA_BIT_RX_TRANSFER | \
+ CX2_INTA_BIT_FATAL_ERROR | \
+ CX2_INTA_BIT_PARITY_ERROR | \
+ CX2_INTA_BIT_STATUS_CHANGE | \
+ CX2_INTA_BIT_FW_INITIALIZATION_DONE | \
+ CX2_INTA_BIT_BEACON_PERIOD_EXPIRED | \
+ CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE | \
+ CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN | \
+ CX2_INTA_BIT_POWER_DOWN | \
+ CX2_INTA_BIT_RF_KILL_DONE )
+
+#define IPWSTATUS_ERROR_LOG (CX2_SHARED_LOWER_BOUND + 0x410)
+#define IPW_EVENT_LOG (CX2_SHARED_LOWER_BOUND + 0x414)
+
+/* FW event log definitions */
+#define EVENT_ELEM_SIZE (3 * sizeof(u32))
+#define EVENT_START_OFFSET (1 * sizeof(u32) + 2 * sizeof(u16))
+
+/* FW error log definitions */
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+
+enum {
+ IPW_FW_ERROR_OK = 0,
+ IPW_FW_ERROR_FAIL,
+ IPW_FW_ERROR_MEMORY_UNDERFLOW,
+ IPW_FW_ERROR_MEMORY_OVERFLOW,
+ IPW_FW_ERROR_BAD_PARAM,
+ IPW_FW_ERROR_BAD_CHECKSUM,
+ IPW_FW_ERROR_NMI_INTERRUPT,
+ IPW_FW_ERROR_BAD_DATABASE,
+ IPW_FW_ERROR_ALLOC_FAIL,
+ IPW_FW_ERROR_DMA_UNDERRUN,
+ IPW_FW_ERROR_DMA_STATUS,
+ IPW_FW_ERROR_DINOSTATUS_ERROR,
+ IPW_FW_ERROR_EEPROMSTATUS_ERROR,
+ IPW_FW_ERROR_SYSASSERT,
+ IPW_FW_ERROR_FATAL_ERROR
+};
+
+#define AUTH_OPEN 0
+#define AUTH_SHARED_KEY 1
+#define AUTH_IGNORE 3
+
+#define HC_ASSOCIATE 0
+#define HC_REASSOCIATE 1
+#define HC_DISASSOCIATE 2
+#define HC_IBSS_START 3
+#define HC_IBSS_RECONF 4
+#define HC_DISASSOC_QUIET 5
+
+#define IPW_RATE_CAPABILITIES 1
+#define IPW_RATE_CONNECT 0
+
+/*
+ * Rate values and masks
+ */
+#define IPW_TX_RATE_1MB 0x0A
+#define IPW_TX_RATE_2MB 0x14
+#define IPW_TX_RATE_5MB 0x37
+#define IPW_TX_RATE_6MB 0x0D
+#define IPW_TX_RATE_9MB 0x0F
+#define IPW_TX_RATE_11MB 0x6E
+#define IPW_TX_RATE_12MB 0x05
+#define IPW_TX_RATE_18MB 0x07
+#define IPW_TX_RATE_24MB 0x09
+#define IPW_TX_RATE_36MB 0x0B
+#define IPW_TX_RATE_48MB 0x01
+#define IPW_TX_RATE_54MB 0x03
+
+#define IPW_ORD_TABLE_ID_MASK 0x0000FF00
+#define IPW_ORD_TABLE_VALUE_MASK 0x000000FF
+
+#define IPW_ORD_TABLE_0_MASK 0x0000F000
+#define IPW_ORD_TABLE_1_MASK 0x0000F100
+#define IPW_ORD_TABLE_2_MASK 0x0000F200
+#define IPW_ORD_TABLE_3_MASK 0x0000F300
+#define IPW_ORD_TABLE_4_MASK 0x0000F400
+#define IPW_ORD_TABLE_5_MASK 0x0000F500
+#define IPW_ORD_TABLE_6_MASK 0x0000F600
+#define IPW_ORD_TABLE_7_MASK 0x0000F700
+
+/*
+ * Table 0 Entries (all entries are 32 bits)
+ */
+enum {
+ IPW_ORD_STAT_TX_CURR_RATE = IPW_ORD_TABLE_0_MASK + 1,
+ IPW_ORD_STAT_FRAG_TRESHOLD,
+ IPW_ORD_STAT_RTS_THRESHOLD,
+ IPW_ORD_STAT_TX_HOST_REQUESTS,
+ IPW_ORD_STAT_TX_HOST_COMPLETE,
+ IPW_ORD_STAT_TX_DIR_DATA,
+ IPW_ORD_STAT_TX_DIR_DATA_B_1,
+ IPW_ORD_STAT_TX_DIR_DATA_B_2,
+ IPW_ORD_STAT_TX_DIR_DATA_B_5_5,
+ IPW_ORD_STAT_TX_DIR_DATA_B_11,
+ /* Hole */
+
+ IPW_ORD_STAT_TX_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 19,
+ IPW_ORD_STAT_TX_DIR_DATA_G_2,
+ IPW_ORD_STAT_TX_DIR_DATA_G_5_5,
+ IPW_ORD_STAT_TX_DIR_DATA_G_6,
+ IPW_ORD_STAT_TX_DIR_DATA_G_9,
+ IPW_ORD_STAT_TX_DIR_DATA_G_11,
+ IPW_ORD_STAT_TX_DIR_DATA_G_12,
+ IPW_ORD_STAT_TX_DIR_DATA_G_18,
+ IPW_ORD_STAT_TX_DIR_DATA_G_24,
+ IPW_ORD_STAT_TX_DIR_DATA_G_36,
+ IPW_ORD_STAT_TX_DIR_DATA_G_48,
+ IPW_ORD_STAT_TX_DIR_DATA_G_54,
+ IPW_ORD_STAT_TX_NON_DIR_DATA,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_1,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_2,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_5_5,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_B_11,
+ /* Hole */
+
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 44,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_2,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_5_5,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_6,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_9,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_11,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_12,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_18,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_24,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_36,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_48,
+ IPW_ORD_STAT_TX_NON_DIR_DATA_G_54,
+ IPW_ORD_STAT_TX_RETRY,
+ IPW_ORD_STAT_TX_FAILURE,
+ IPW_ORD_STAT_RX_ERR_CRC,
+ IPW_ORD_STAT_RX_ERR_ICV,
+ IPW_ORD_STAT_RX_NO_BUFFER,
+ IPW_ORD_STAT_FULL_SCANS,
+ IPW_ORD_STAT_PARTIAL_SCANS,
+ IPW_ORD_STAT_TGH_ABORTED_SCANS,
+ IPW_ORD_STAT_TX_TOTAL_BYTES,
+ IPW_ORD_STAT_CURR_RSSI_RAW,
+ IPW_ORD_STAT_RX_BEACON,
+ IPW_ORD_STAT_MISSED_BEACONS,
+ IPW_ORD_TABLE_0_LAST
+};
+
+#define IPW_RSSI_TO_DBM 112
+
+/* Table 1 Entries
+ */
+enum {
+ IPW_ORD_TABLE_1_LAST = IPW_ORD_TABLE_1_MASK | 1,
+};
+
+/*
+ * Table 2 Entries
+ *
+ * FW_VERSION: 16 byte string
+ * FW_DATE: 16 byte string (only 14 bytes used)
+ * UCODE_VERSION: 4 byte version code
+ * UCODE_DATE: 5 bytes code code
+ * ADDAPTER_MAC: 6 byte MAC address
+ * RTC: 4 byte clock
+ */
+enum {
+ IPW_ORD_STAT_FW_VERSION = IPW_ORD_TABLE_2_MASK | 1,
+ IPW_ORD_STAT_FW_DATE,
+ IPW_ORD_STAT_UCODE_VERSION,
+ IPW_ORD_STAT_UCODE_DATE,
+ IPW_ORD_STAT_ADAPTER_MAC,
+ IPW_ORD_STAT_RTC,
+ IPW_ORD_TABLE_2_LAST
+};
+
+/* Table 3 */
+enum {
+ IPW_ORD_STAT_TX_PACKET = IPW_ORD_TABLE_3_MASK | 0,
+ IPW_ORD_STAT_TX_PACKET_FAILURE,
+ IPW_ORD_STAT_TX_PACKET_SUCCESS,
+ IPW_ORD_STAT_TX_PACKET_ABORTED,
+ IPW_ORD_TABLE_3_LAST
+};
+
+/* Table 4 */
+enum {
+ IPW_ORD_TABLE_4_LAST = IPW_ORD_TABLE_4_MASK
+};
+
+/* Table 5 */
+enum {
+ IPW_ORD_STAT_AVAILABLE_AP_COUNT = IPW_ORD_TABLE_5_MASK,
+ IPW_ORD_STAT_AP_ASSNS,
+ IPW_ORD_STAT_ROAM,
+ IPW_ORD_STAT_ROAM_CAUSE_MISSED_BEACONS,
+ IPW_ORD_STAT_ROAM_CAUSE_UNASSOC,
+ IPW_ORD_STAT_ROAM_CAUSE_RSSI,
+ IPW_ORD_STAT_ROAM_CAUSE_LINK_QUALITY,
+ IPW_ORD_STAT_ROAM_CAUSE_AP_LOAD_BALANCE,
+ IPW_ORD_STAT_ROAM_CAUSE_AP_NO_TX,
+ IPW_ORD_STAT_LINK_UP,
+ IPW_ORD_STAT_LINK_DOWN,
+ IPW_ORD_ANTENNA_DIVERSITY,
+ IPW_ORD_CURR_FREQ,
+ IPW_ORD_TABLE_5_LAST
+};
+
+/* Table 6 */
+enum {
+ IPW_ORD_COUNTRY_CODE = IPW_ORD_TABLE_6_MASK,
+ IPW_ORD_CURR_BSSID,
+ IPW_ORD_CURR_SSID,
+ IPW_ORD_TABLE_6_LAST
+};
+
+/* Table 7 */
+enum {
+ IPW_ORD_STAT_PERCENT_MISSED_BEACONS = IPW_ORD_TABLE_7_MASK,
+ IPW_ORD_STAT_PERCENT_TX_RETRIES,
+ IPW_ORD_STAT_PERCENT_LINK_QUALITY,
+ IPW_ORD_STAT_CURR_RSSI_DBM,
+ IPW_ORD_TABLE_7_LAST
+};
+
+#define IPW_ORDINALS_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0x500)
+#define IPW_ORDINALS_TABLE_0 (CX2_SHARED_LOWER_BOUND + 0x180)
+#define IPW_ORDINALS_TABLE_1 (CX2_SHARED_LOWER_BOUND + 0x184)
+#define IPW_ORDINALS_TABLE_2 (CX2_SHARED_LOWER_BOUND + 0x188)
+#define IPW_MEM_FIXED_OVERRIDE (CX2_SHARED_LOWER_BOUND + 0x41C)
+
+struct ipw_fixed_rate {
+ u16 tx_rates;
+ u16 reserved;
+} __attribute__ ((packed));
+
+#define CX2_INDIRECT_ADDR_MASK (~0x3ul)
+
+struct host_cmd {
+ u8 cmd;
+ u8 len;
+ u16 reserved;
+ u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+} __attribute__ ((packed));
+
+#define CFG_BT_COEXISTENCE_MIN 0x00
+#define CFG_BT_COEXISTENCE_DEFER 0x02
+#define CFG_BT_COEXISTENCE_KILL 0x04
+#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08
+#define CFG_BT_COEXISTENCE_OOB 0x10
+#define CFG_BT_COEXISTENCE_MAX 0xFF
+#define CFG_BT_COEXISTENCE_DEF 0x80 /* read Bt from EEPROM */
+
+#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x0
+#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x1
+#define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN
+
+#define CFG_SYS_ANTENNA_BOTH 0x000
+#define CFG_SYS_ANTENNA_A 0x001
+#define CFG_SYS_ANTENNA_B 0x003
+
+/*
+ * The definitions below were lifted off the ipw2100 driver, which only
+ * supports 'b' mode, so I'm sure these are not exactly correct.
+ *
+ * Somebody fix these!!
+ */
+#define REG_MIN_CHANNEL 0
+#define REG_MAX_CHANNEL 14
+
+#define REG_CHANNEL_MASK 0x00003FFF
+#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff
+
+static const long ipw_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT ARRAY_SIZE(ipw_frequencies)
+
+#define IPW_MAX_CONFIG_RETRIES 10
+
+static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
+{
+ u32 retval;
+ u16 fc;
+
+ retval = sizeof(struct ieee80211_hdr_3addr);
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /*
+ * Function ToDS FromDS
+ * IBSS 0 0
+ * To AP 1 0
+ * From AP 0 1
+ * WDS (bridge) 1 1
+ *
+ * Only WDS frames use Address4 among them. --YZ
+ */
+ if (!(fc & IEEE80211_FCTL_TODS) || !(fc & IEEE80211_FCTL_FROMDS))
+ retval -= ETH_ALEN;
+
+ return retval;
+}
+
+#endif /* __ipw2200_h__ */
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 5f507c49907b..92793b958e32 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -57,9 +57,7 @@
#include <linux/bitops.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
-#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
-#endif /* WIRELESS_EXT > 12 */
#endif
#include <pcmcia/cs_types.h>
@@ -225,10 +223,7 @@ static void update_stats(struct net_device *dev);
static struct net_device_stats *netwave_get_stats(struct net_device *dev);
/* Wireless extensions */
-#ifdef WIRELESS_EXT
static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
-#endif
-static int netwave_ioctl(struct net_device *, struct ifreq *, int);
static void set_multicast_list(struct net_device *dev);
@@ -260,26 +255,7 @@ static dev_link_t *dev_list;
because they generally can't be allocated dynamically.
*/
-#if WIRELESS_EXT <= 12
-/* Wireless extensions backward compatibility */
-
-/* Part of iw_handler prototype we need */
-struct iw_request_info
-{
- __u16 cmd; /* Wireless Extension command */
- __u16 flags; /* More to come ;-) */
-};
-
-/* Wireless Extension Backward compatibility - Jean II
- * If the new wireless device private ioctl range is not defined,
- * default to standard device private ioctl range */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
-#else /* WIRELESS_EXT <= 12 */
static const struct iw_handler_def netwave_handler_def;
-#endif /* WIRELESS_EXT <= 12 */
#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */
@@ -319,9 +295,7 @@ typedef struct netwave_private {
struct timer_list watchdog; /* To avoid blocking state */
struct site_survey nss;
struct net_device_stats stats;
-#ifdef WIRELESS_EXT
struct iw_statistics iw_stats; /* Wireless stats */
-#endif
} netwave_private;
#ifdef NETWAVE_STATS
@@ -353,7 +327,6 @@ static inline void wait_WOC(unsigned int iobase)
while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ;
}
-#ifdef WIRELESS_EXT
static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
kio_addr_t iobase) {
u_short resultBuffer;
@@ -376,9 +349,7 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
sizeof(struct site_survey));
}
}
-#endif
-#ifdef WIRELESS_EXT
/*
* Function netwave_get_wireless_stats (dev)
*
@@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
return &priv->iw_stats;
}
-#endif
/*
* Function netwave_attach (void)
@@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
dev->get_stats = &netwave_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* wireless extensions */
-#ifdef WIRELESS_EXT
- dev->get_wireless_stats = &netwave_get_wireless_stats;
-#if WIRELESS_EXT > 12
dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
-#endif /* WIRELESS_EXT > 12 */
-#endif /* WIRELESS_EXT */
- dev->do_ioctl = &netwave_ioctl;
dev->tx_timeout = &netwave_watchdog;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -576,13 +540,8 @@ static int netwave_set_nwid(struct net_device *dev,
/* Disable interrupts & save flags */
spin_lock_irqsave(&priv->spinlock, flags);
-#if WIRELESS_EXT > 8
if(!wrqu->nwid.disabled) {
domain = wrqu->nwid.value;
-#else /* WIRELESS_EXT > 8 */
- if(wrqu->nwid.on) {
- domain = wrqu->nwid.nwid;
-#endif /* WIRELESS_EXT > 8 */
printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
(domain >> 8) & 0x01, domain & 0xff);
wait_WOC(iobase);
@@ -606,15 +565,9 @@ static int netwave_get_nwid(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
-#if WIRELESS_EXT > 8
wrqu->nwid.value = domain;
wrqu->nwid.disabled = 0;
wrqu->nwid.fixed = 1;
-#else /* WIRELESS_EXT > 8 */
- wrqu->nwid.nwid = domain;
- wrqu->nwid.on = 1;
-#endif /* WIRELESS_EXT > 8 */
-
return 0;
}
@@ -657,17 +610,11 @@ static int netwave_get_scramble(struct net_device *dev,
{
key[1] = scramble_key & 0xff;
key[0] = (scramble_key>>8) & 0xff;
-#if WIRELESS_EXT > 8
wrqu->encoding.flags = IW_ENCODE_ENABLED;
wrqu->encoding.length = 2;
-#else /* WIRELESS_EXT > 8 */
- wrqu->encoding.method = 1;
-#endif /* WIRELESS_EXT > 8 */
-
return 0;
}
-#if WIRELESS_EXT > 8
/*
* Wireless Handler : get mode
*/
@@ -683,7 +630,6 @@ static int netwave_get_mode(struct net_device *dev,
return 0;
}
-#endif /* WIRELESS_EXT > 8 */
/*
* Wireless Handler : get range info
@@ -702,11 +648,9 @@ static int netwave_get_range(struct net_device *dev,
/* Set all the info we don't care or don't know about to zero */
memset(range, 0, sizeof(struct iw_range));
-#if WIRELESS_EXT > 10
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 9; /* Nothing for us in v10 and v11 */
-#endif /* WIRELESS_EXT > 10 */
/* Set information in the range struct */
range->throughput = 450 * 1000; /* don't argue on this ! */
@@ -720,16 +664,12 @@ static int netwave_get_range(struct net_device *dev,
range->max_qual.level = 255;
range->max_qual.noise = 0;
-#if WIRELESS_EXT > 7
range->num_bitrates = 1;
range->bitrate[0] = 1000000; /* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
-#if WIRELESS_EXT > 8
range->encoding_size[0] = 2; /* 16 bits scrambling */
range->num_encoding_sizes = 1;
range->max_encoding_tokens = 1; /* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
return ret;
}
@@ -775,8 +715,6 @@ static const struct iw_priv_args netwave_private_args[] = {
"getsitesurvey" },
};
-#if WIRELESS_EXT > 12
-
static const iw_handler netwave_handler[] =
{
NULL, /* SIOCSIWNAME */
@@ -839,128 +777,8 @@ static const struct iw_handler_def netwave_handler_def =
.standard = (iw_handler *) netwave_handler,
.private = (iw_handler *) netwave_private_handler,
.private_args = (struct iw_priv_args *) netwave_private_args,
+ .get_wireless_stats = netwave_get_wireless_stats,
};
-#endif /* WIRELESS_EXT > 12 */
-
-/*
- * Function netwave_ioctl (dev, rq, cmd)
- *
- * Perform ioctl : config & info stuff
- * This is the stuff that are treated the wireless extensions (iwconfig)
- *
- */
-static int netwave_ioctl(struct net_device *dev, /* ioctl device */
- struct ifreq *rq, /* Data passed */
- int cmd) /* Ioctl number */
-{
- int ret = 0;
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
- struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-#endif
-
- DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
-
- /* Look what is the request */
- switch(cmd) {
- /* --------------- WIRELESS EXTENSIONS --------------- */
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
- case SIOCGIWNAME:
- netwave_get_name(dev, NULL, &(wrq->u), NULL);
- break;
- case SIOCSIWNWID:
- ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
- break;
- case SIOCGIWNWID:
- ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
- break;
-#if WIRELESS_EXT > 8 /* Note : The API did change... */
- case SIOCGIWENCODE:
- /* Get scramble key */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- char key[2];
- ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
- if(copy_to_user(wrq->u.encoding.pointer, key, 2))
- ret = -EFAULT;
- }
- break;
- case SIOCSIWENCODE:
- /* Set scramble key */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- char key[2];
- if(copy_from_user(key, wrq->u.encoding.pointer, 2))
- {
- ret = -EFAULT;
- break;
- }
- ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
- }
- break;
- case SIOCGIWMODE:
- /* Mode of operation */
- ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
- break;
-#else /* WIRELESS_EXT > 8 */
- case SIOCGIWENCODE:
- /* Get scramble key */
- ret = netwave_get_scramble(dev, NULL, &(wrq->u),
- (char *) &wrq->u.encoding.code);
- break;
- case SIOCSIWENCODE:
- /* Set scramble key */
- ret = netwave_set_scramble(dev, NULL, &(wrq->u),
- (char *) &wrq->u.encoding.code);
- break;
-#endif /* WIRELESS_EXT > 8 */
- case SIOCGIWRANGE:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_range range;
- ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
- if (copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- ret = -EFAULT;
- }
- break;
- case SIOCGIWPRIV:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0) {
- /* Set the number of ioctl available */
- wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
-
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer,
- (u_char *) netwave_private_args,
- sizeof(netwave_private_args)))
- ret = -EFAULT;
- }
- break;
- case SIOCGIPSNAP:
- if(wrq->u.data.pointer != (caddr_t) 0) {
- char buffer[sizeof( struct site_survey)];
- ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer,
- buffer,
- sizeof( struct site_survey)))
- {
- printk(KERN_DEBUG "Bad buffer!\n");
- break;
- }
- }
- break;
-#endif /* WIRELESS_EXT <= 12 */
-#endif /* WIRELESS_EXT */
- default:
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
/*
* Function netwave_pcmcia_config (link)
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index aabcdc2be05e..488ab06fb79f 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -77,31 +77,18 @@
#define DRIVER_NAME "orinoco"
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.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.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
-#include "ieee802_11.h"
/********************************************************************/
/* Module information */
@@ -136,7 +123,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
-#define SPY_NUMBER(priv) (priv->spy_number)
+#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
#else
#define SPY_NUMBER(priv) 0
#endif /* WIRELESS_SPY */
@@ -150,7 +137,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
#define ORINOCO_MIN_MTU 256
-#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
+#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
#define SYMBOL_MAX_VER_LEN (14)
#define USER_BAP 0
@@ -215,31 +202,32 @@ static struct {
/********************************************************************/
/* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
+ * We avoid nested structures as they break on ARM -- Moustafa */
struct hermes_tx_descriptor_802_11 {
/* hermes_tx_descriptor */
- u16 status;
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
+ __le16 status;
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 sw_support;
u8 retry_count;
u8 tx_rate;
- u16 tx_control;
+ __le16 tx_control;
- /* ieee802_11_hdr */
- u16 frame_ctl;
- u16 duration_id;
+ /* ieee80211_hdr */
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
+ __le16 seq_ctl;
u8 addr4[ETH_ALEN];
- u16 data_len;
+
+ __le16 data_len;
/* ethhdr */
- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
- unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_proto; /* packet type ID field */
+ u8 h_dest[ETH_ALEN]; /* destination eth addr */
+ u8 h_source[ETH_ALEN]; /* source ether addr */
+ __be16 h_proto; /* packet type ID field */
/* p8022_hdr */
u8 dsap;
@@ -247,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
u8 ctrl;
u8 oui[3];
- u16 ethertype;
+ __be16 ethertype;
} __attribute__ ((packed));
/* Rx frame header except compatibility 802.3 header */
struct hermes_rx_descriptor {
/* Control */
- u16 status;
- u32 time;
+ __le16 status;
+ __le32 time;
u8 silence;
u8 signal;
u8 rate;
u8 rxflow;
- u32 reserved;
+ __le32 reserved;
/* 802.11 header */
- u16 frame_ctl;
- u16 duration_id;
+ __le16 frame_ctl;
+ __le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
- u16 seq_ctl;
+ __le16 seq_ctl;
u8 addr4[ETH_ALEN];
/* Data length */
- u16 data_len;
+ __le16 data_len;
} __attribute__ ((packed));
/********************************************************************/
@@ -395,14 +383,14 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* If a spy address is defined, we report stats of the
* first spy address - Jean II */
if (SPY_NUMBER(priv)) {
- wstats->qual.qual = priv->spy_stat[0].qual;
- wstats->qual.level = priv->spy_stat[0].level;
- wstats->qual.noise = priv->spy_stat[0].noise;
- wstats->qual.updated = priv->spy_stat[0].updated;
+ wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
+ wstats->qual.level = priv->spy_data.spy_stat[0].level;
+ wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
+ wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
}
} else {
struct {
- u16 qual, signal, noise;
+ __le16 qual, signal, noise;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -442,7 +430,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
return -EINVAL;
- if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
+ if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
(priv->nicbuf_size - ETH_HLEN) )
return -EINVAL;
@@ -504,7 +492,11 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
/* Length of the packet body */
/* FIXME: what if the skb is smaller than this? */
- len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+ len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
+ skb = skb_padto(skb, len);
+ if (skb == NULL)
+ goto fail;
+ len -= ETH_HLEN;
eh = (struct ethhdr *)skb->data;
@@ -550,14 +542,21 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_errors++;
goto fail;
}
+ /* Actual xfer length - allow for padding */
+ len = ALIGN(data_len, 2);
+ if (len < ETH_ZLEN - ETH_HLEN)
+ len = ETH_ZLEN - ETH_HLEN;
} else { /* IEEE 802.3 frame */
data_len = len + ETH_HLEN;
data_off = HERMES_802_3_OFFSET;
p = skb->data;
+ /* Actual xfer length - round up for odd length packets */
+ len = ALIGN(data_len, 2);
+ if (len < ETH_ZLEN)
+ len = ETH_ZLEN;
}
- /* Round up for odd length packets */
- err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
+ err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
txfid, data_off);
if (err) {
printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
@@ -573,8 +572,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
txfid, NULL);
if (err) {
netif_start_queue(dev);
- printk(KERN_ERR "%s: Error %d transmitting packet\n",
- dev->name, err);
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Error %d transmitting packet\n",
+ dev->name, err);
stats->tx_errors++;
goto fail;
}
@@ -628,16 +628,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+ u16 status;
struct hermes_tx_descriptor_802_11 hdr;
int err = 0;
if (fid == DUMMY_FID)
return; /* Nothing's really happened */
- /* Read the frame header */
+ /* Read part of the frame header - we need status and addr1 */
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
- sizeof(struct hermes_tx_descriptor) +
- sizeof(struct ieee80211_hdr),
+ offsetof(struct hermes_tx_descriptor_802_11,
+ addr2),
fid, 0);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -657,8 +658,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
* exceeded, because that's the only status that really mean
* that this particular node went away.
* Other errors means that *we* screwed up. - Jean II */
- hdr.status = le16_to_cpu(hdr.status);
- if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+ status = le16_to_cpu(hdr.status);
+ if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
union iwreq_data wrqu;
/* Copy 802.11 dest address.
@@ -717,18 +718,13 @@ static inline int is_ethersnap(void *_hdr)
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
int level, int noise)
{
- struct orinoco_private *priv = netdev_priv(dev);
- 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 < priv->spy_number; i++)
- if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
- priv->spy_stat[i].level = level - 0x95;
- priv->spy_stat[i].noise = noise - 0x95;
- priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
- priv->spy_stat[i].updated = 7;
- }
+ struct iw_quality wstats;
+ wstats.level = level - 0x95;
+ wstats.noise = noise - 0x95;
+ wstats.qual = (level > noise) ? (level - noise) : 0;
+ wstats.updated = 7;
+ /* Update spy records */
+ wireless_spy_update(dev, mac, &wstats);
}
static void orinoco_stat_gather(struct net_device *dev,
@@ -918,7 +914,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
data. */
return;
}
- if (length > IEEE802_11_DATA_LEN) {
+ if (length > IEEE80211_DATA_LEN) {
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
dev->name, length);
stats->rx_length_errors++;
@@ -1049,11 +1045,12 @@ static void orinoco_join_ap(struct net_device *dev)
unsigned long flags;
struct join_req {
u8 bssid[ETH_ALEN];
- u16 channel;
+ __le16 channel;
} __attribute__ ((packed)) req;
const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
- struct prism2_scan_apinfo *atom;
+ struct prism2_scan_apinfo *atom = NULL;
int offset = 4;
+ int found = 0;
u8 *buf;
u16 len;
@@ -1063,7 +1060,7 @@ static void orinoco_join_ap(struct net_device *dev)
return;
if (orinoco_lock(priv, &flags) != 0)
- goto out;
+ goto fail_lock;
/* Sanity checks in case user changed something in the meantime */
if (! priv->bssid_fixed)
@@ -1088,15 +1085,18 @@ static void orinoco_join_ap(struct net_device *dev)
* we were requested to join */
for (; offset + atom_len <= len; offset += atom_len) {
atom = (struct prism2_scan_apinfo *) (buf + offset);
- if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
- goto found;
+ if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
+ found = 1;
+ break;
+ }
}
- DEBUG(1, "%s: Requested AP not found in scan results\n",
- dev->name);
- goto out;
+ if (! found) {
+ DEBUG(1, "%s: Requested AP not found in scan results\n",
+ dev->name);
+ goto out;
+ }
- found:
memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
req.channel = atom->channel; /* both are little-endian */
err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
@@ -1105,8 +1105,10 @@ static void orinoco_join_ap(struct net_device *dev)
printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
out:
- kfree(buf);
orinoco_unlock(priv, &flags);
+
+ fail_lock:
+ kfree(buf);
}
/* Send new BSSID to userspace */
@@ -1124,12 +1126,14 @@ static void orinoco_send_wevents(struct net_device *dev)
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
- return;
+ goto out;
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/* Send event to user space */
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+
+ out:
orinoco_unlock(priv, &flags);
}
@@ -1138,8 +1142,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
u16 infofid;
struct {
- u16 len;
- u16 type;
+ __le16 len;
+ __le16 type;
} __attribute__ ((packed)) info;
int len, type;
int err;
@@ -1283,8 +1287,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
/* Read scan data */
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
infofid, sizeof(info));
- if (err)
+ if (err) {
+ kfree(buf);
break;
+ }
#ifdef ORINOCO_DEBUG
{
@@ -2272,7 +2278,7 @@ static int orinoco_init(struct net_device *dev)
/* No need to lock, the hw_unavailable flag is already set in
* alloc_orinocodev() */
- priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
+ priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
/* Initialize the firmware */
err = orinoco_reinit_firmware(dev);
@@ -2451,8 +2457,11 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->watchdog_timeo = HZ; /* 1 second timeout */
dev->get_stats = orinoco_get_stats;
dev->ethtool_ops = &orinoco_ethtool_ops;
- dev->get_wireless_stats = orinoco_get_wireless_stats;
dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+#ifdef WIRELESS_SPY
+ priv->wireless_data.spy_data = &priv->spy_data;
+ dev->wireless_data = &priv->wireless_data;
+#endif
dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2824,7 +2833,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
}
}
- if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
+ if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
/* Quality stats meaningless in ad-hoc mode */
} else {
range->max_qual.qual = 0x8b - 0x2f;
@@ -2871,6 +2880,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
range->min_r_time = 0;
range->max_r_time = 65535 * 1000; /* ??? */
+ /* Event capability (kernel) */
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+ /* Event capability (driver) */
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+
TRACE_EXIT(dev->name);
return 0;
@@ -3830,92 +3847,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err;
}
-/* Spy is used for link quality/strength measurements in Ad-Hoc mode
- * Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
- int number = srq->length;
- int i;
- unsigned long flags;
-
- /* Make sure nobody mess with the structure while we do */
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* orinoco_lock() doesn't disable interrupts, so make sure the
- * interrupt rx path don't get confused while we copy */
- priv->spy_number = 0;
-
- if (number > 0) {
- /* Extract the addresses */
- for (i = 0; i < number; i++)
- memcpy(priv->spy_address[i], address[i].sa_data,
- ETH_ALEN);
- /* Reset stats */
- memset(priv->spy_stat, 0,
- sizeof(struct iw_quality) * IW_MAX_SPY);
- /* Set number of addresses */
- priv->spy_number = number;
- }
-
- /* Now, let the others play */
- orinoco_unlock(priv, &flags);
-
- /* Do NOT call commit handler */
- return 0;
-}
-
-static int orinoco_ioctl_getspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
- int number;
- int i;
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- number = priv->spy_number;
- /* Create address struct */
- for (i = 0; i < number; i++) {
- memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
- address[i].sa_family = AF_UNIX;
- }
- if (number > 0) {
- /* Create address struct */
- for (i = 0; i < number; i++) {
- memcpy(address[i].sa_data, priv->spy_address[i],
- ETH_ALEN);
- address[i].sa_family = AF_UNIX;
- }
- /* Copy stats */
- /* In theory, we should disable irqs while copying the stats
- * because the rx path might update it in the middle...
- * Bah, who care ? - Jean II */
- memcpy(extra + (sizeof(struct sockaddr) * number),
- priv->spy_stat, sizeof(struct iw_quality) * number);
- }
- /* Reset updated flags. */
- for (i = 0; i < number; i++)
- priv->spy_stat[i].updated = 0;
-
- orinoco_unlock(priv, &flags);
-
- srq->length = number;
-
- return 0;
-}
-
/* Trigger a scan (look for other cells in the vicinity */
static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info,
@@ -3988,7 +3919,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
HERMES_HOSTSCAN_SYMBOL_BCAST);
break;
case FIRMWARE_TYPE_INTERSIL: {
- u16 req[3];
+ __le16 req[3];
req[0] = cpu_to_le16(0x3fff); /* All channels */
req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
@@ -4020,7 +3951,8 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
}
/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
+ * format that the Wireless Tools will understand - Jean II
+ * Return message length or -errno for fatal errors */
static inline int orinoco_translate_scan(struct net_device *dev,
char *buffer,
char *scan,
@@ -4060,13 +3992,19 @@ static inline int orinoco_translate_scan(struct net_device *dev,
break;
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
- if (priv->has_hostscan)
- atom_len = scan[0] + (scan[1] << 8);
- else
+ if (priv->has_hostscan) {
+ atom_len = le16_to_cpup((__le16 *)scan);
+ /* Sanity check for atom_len */
+ if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+ printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
+ dev->name, atom_len);
+ return -EIO;
+ }
+ } else
atom_len = offsetof(struct prism2_scan_apinfo, atim);
break;
default:
- return 0;
+ return -EOPNOTSUPP;
}
/* Check that we got an whole number of atoms */
@@ -4074,7 +4012,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
printk(KERN_ERR "%s: Unexpected scan data length %d, "
"atom_len %d, offset %d\n", dev->name, scan_len,
atom_len, offset);
- return 0;
+ return -EIO;
}
/* Read the entries one by one */
@@ -4209,33 +4147,41 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
/* We have some results to push back to user space */
/* Translate to WE format */
- srq->length = orinoco_translate_scan(dev, extra,
- priv->scan_result,
- priv->scan_len);
-
- /* Return flags */
- srq->flags = (__u16) priv->scan_mode;
+ int ret = orinoco_translate_scan(dev, extra,
+ priv->scan_result,
+ priv->scan_len);
+
+ if (ret < 0) {
+ err = ret;
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
+ } else {
+ srq->length = ret;
- /* Results are here, so scan no longer in progress */
- priv->scan_inprogress = 0;
+ /* Return flags */
+ srq->flags = (__u16) priv->scan_mode;
- /* In any case, Scan results will be cleaned up in the
- * reset function and when exiting the driver.
- * The person triggering the scanning may never come to
- * pick the results, so we need to do it in those places.
- * Jean II */
+ /* In any case, Scan results will be cleaned up in the
+ * reset function and when exiting the driver.
+ * The person triggering the scanning may never come to
+ * pick the results, so we need to do it in those places.
+ * Jean II */
#ifdef SCAN_SINGLE_READ
- /* If you enable this option, only one client (the first
- * one) will be able to read the result (and only one
- * time). If there is multiple concurent clients that
- * want to read scan results, this behavior is not
- * advisable - Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
+ /* If you enable this option, only one client (the first
+ * one) will be able to read the result (and only one
+ * time). If there is multiple concurent clients that
+ * want to read scan results, this behavior is not
+ * advisable - Jean II */
+ kfree(priv->scan_result);
+ priv->scan_result = NULL;
#endif /* SCAN_SINGLE_READ */
- /* Here, if too much time has elapsed since last scan,
- * we may want to clean up scan results... - Jean II */
+ /* Here, if too much time has elapsed since last scan,
+ * we may want to clean up scan results... - Jean II */
+ }
+
+ /* Scan is no longer in progress */
+ priv->scan_inprogress = 0;
}
orinoco_unlock(priv, &flags);
@@ -4322,36 +4268,38 @@ static const struct iw_priv_args orinoco_privtab[] = {
*/
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) orinoco_ioctl_setspy,
- [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
- [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,
+ [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,
};
@@ -4359,15 +4307,15 @@ static const iw_handler orinoco_handler[] = {
Added typecasting since we no longer use iwreq_data -- Moustafa
*/
static const iw_handler orinoco_private_handler[] = {
- [0] (iw_handler) orinoco_ioctl_reset,
- [1] (iw_handler) orinoco_ioctl_reset,
- [2] (iw_handler) orinoco_ioctl_setport3,
- [3] (iw_handler) orinoco_ioctl_getport3,
- [4] (iw_handler) orinoco_ioctl_setpreamble,
- [5] (iw_handler) orinoco_ioctl_getpreamble,
- [6] (iw_handler) orinoco_ioctl_setibssport,
- [7] (iw_handler) orinoco_ioctl_getibssport,
- [9] (iw_handler) orinoco_ioctl_getrid,
+ [0] = (iw_handler) orinoco_ioctl_reset,
+ [1] = (iw_handler) orinoco_ioctl_reset,
+ [2] = (iw_handler) orinoco_ioctl_setport3,
+ [3] = (iw_handler) orinoco_ioctl_getport3,
+ [4] = (iw_handler) orinoco_ioctl_setpreamble,
+ [5] = (iw_handler) orinoco_ioctl_getpreamble,
+ [6] = (iw_handler) orinoco_ioctl_setibssport,
+ [7] = (iw_handler) orinoco_ioctl_getibssport,
+ [9] = (iw_handler) orinoco_ioctl_getrid,
};
static const struct iw_handler_def orinoco_handler_def = {
@@ -4377,6 +4325,7 @@ static const struct iw_handler_def orinoco_handler_def = {
.standard = orinoco_handler,
.private = orinoco_private_handler,
.private_args = orinoco_privtab,
+ .get_wireless_stats = orinoco_get_wireless_stats,
};
static void orinoco_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 2f213a7103fe..7a17bb31fc89 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,12 +7,11 @@
#ifndef _ORINOCO_H
#define _ORINOCO_H
-#define DRIVER_VERSION "0.15rc2"
+#define DRIVER_VERSION "0.15rc3"
-#include <linux/types.h>
-#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
+#include <net/iw_handler.h>
#include <linux/version.h>
#include "hermes.h"
@@ -28,7 +27,7 @@
#define ORINOCO_MAX_KEYS 4
struct orinoco_key {
- u16 len; /* always stored as little-endian */
+ __le16 len; /* always stored as little-endian */
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
@@ -36,14 +35,14 @@ struct header_struct {
/* 802.3 */
u8 dest[ETH_ALEN];
u8 src[ETH_ALEN];
- u16 len;
+ __be16 len;
/* 802.2 */
u8 dsap;
u8 ssap;
u8 ctrl;
/* SNAP */
u8 oui[3];
- u16 ethertype;
+ unsigned short ethertype;
} __attribute__ ((packed));
typedef enum {
@@ -112,9 +111,8 @@ struct orinoco_private {
u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble;
#ifdef WIRELESS_SPY
- int spy_number;
- u_char spy_address[IW_MAX_SPY][ETH_ALEN];
- struct iw_quality spy_stat[IW_MAX_SPY];
+ struct iw_spy_data spy_data; /* iwspy support */
+ struct iw_public_data wireless_data;
#endif
/* Configuration dependent variables */
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1cc1492083c9..dc1128a00971 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -14,33 +14,16 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-#ifdef __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
#include "orinoco.h"
/********************************************************************/
@@ -97,17 +80,8 @@ static dev_link_t *dev_list; /* = NULL */
/* Function prototypes */
/********************************************************************/
-/* device methods */
-static int orinoco_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void orinoco_cs_config(dev_link_t * link);
-static void orinoco_cs_release(dev_link_t * link);
-static int orinoco_cs_event(event_t event, int priority,
- event_callback_args_t * args);
-
-static dev_link_t *orinoco_cs_attach(void);
-static void orinoco_cs_detach(dev_link_t *);
+static void orinoco_cs_release(dev_link_t *link);
+static void orinoco_cs_detach(dev_link_t *link);
/********************************************************************/
/* Device methods */
@@ -603,49 +577,85 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
"Pavel Roskin <proski@gnu.org>, et al)";
static struct pcmcia_device_id orinoco_cs_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
- PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
- PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
- PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
- PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+ PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+ PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
+ PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+ PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
+ PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
+ PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
+ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
+ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
+ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+ PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
+ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
+ PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
+ PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
+ PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
+ PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
- PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
+ PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
+ PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
+ PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+ PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+ PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
+ PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+ PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+ PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
+ PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+ PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+ PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
+ PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
+ PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+ PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
+ PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+ PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
+ PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
+ PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+ PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
+ PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+ PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
+ PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
- PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
+ PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
+ PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+ PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
+ PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
@@ -656,8 +666,8 @@ static struct pcmcia_driver orinoco_driver = {
.name = DRIVER_NAME,
},
.attach = orinoco_cs_attach,
- .event = orinoco_cs_event,
.detach = orinoco_cs_detach,
+ .event = orinoco_cs_event,
.id_table = orinoco_cs_ids,
};
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
new file mode 100644
index 000000000000..d8afd51ff8a5
--- /dev/null
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -0,0 +1,308 @@
+/* orinoco_nortel.c
+ *
+ * Driver for Prism II devices which would usually be driven by orinoco_cs,
+ * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter.
+ *
+ * Copyright (C) 2002 Tobias Hoffmann
+ * (C) 2003 Christoph Jungegger <disdos@traum404.de>
+ *
+ * Some of this code is borrowed from orinoco_plx.c
+ * Copyright (C) 2001 Daniel Barlow
+ * Some of this code is borrowed from orinoco_pci.c
+ * Copyright (C) 2001 Jean Tourrilhes
+ * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
+ * has been copied from it. linux-wlan-ng-0.1.10 is originally :
+ * Copyright (C) 1999 AbsoluteValue 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.
+ */
+
+#define DRIVER_NAME "orinoco_nortel"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <pcmcia/cisreg.h>
+
+#include "orinoco.h"
+
+#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+
+
+/* Nortel specific data */
+struct nortel_pci_card {
+ unsigned long iobase1;
+ unsigned long iobase2;
+};
+
+/*
+ * Do a soft reset of the PCI card using the Configuration Option Register
+ * We need this to get going...
+ * This is the part of the code that is strongly inspired from wlan-ng
+ *
+ * Note bis : Don't try to access HERMES_CMD during the reset phase.
+ * It just won't work !
+ */
+static int nortel_pci_cor_reset(struct orinoco_private *priv)
+{
+ struct nortel_pci_card *card = priv->card;
+
+ /* Assert the reset until the card notice */
+ outw_p(8, card->iobase1 + 2);
+ inw(card->iobase2 + COR_OFFSET);
+ outw_p(0x80, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* Give time for the card to recover from this hard effort */
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ outw_p(0, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ /* set COR as usual */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+
+ outw_p(0x228, card->iobase1 + 2);
+
+ return 0;
+}
+
+static int nortel_pci_hw_init(struct nortel_pci_card *card)
+{
+ int i;
+ u32 reg;
+
+ /* setup bridge */
+ if (inw(card->iobase1) & 1) {
+ printk(KERN_ERR PFX "brg1 answer1 wrong\n");
+ return -EBUSY;
+ }
+ outw_p(0x118, card->iobase1 + 2);
+ outw_p(0x108, card->iobase1 + 2);
+ mdelay(30);
+ outw_p(0x8, card->iobase1 + 2);
+ for (i = 0; i < 30; i++) {
+ mdelay(30);
+ if (inw(card->iobase1) & 0x10) {
+ break;
+ }
+ }
+ if (i == 30) {
+ printk(KERN_ERR PFX "brg1 timed out\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe0) & 1) {
+ printk(KERN_ERR PFX "brg2 answer1 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe2) & 1) {
+ printk(KERN_ERR PFX "brg2 answer2 wrong\n");
+ return -EBUSY;
+ }
+ if (inw(card->iobase2 + 0xe4) & 1) {
+ printk(KERN_ERR PFX "brg2 answer3 wrong\n");
+ return -EBUSY;
+ }
+
+ /* set the PCMCIA COR-Register */
+ outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+ mdelay(1);
+ reg = inw(card->iobase2 + COR_OFFSET);
+ if (reg != COR_VALUE) {
+ printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
+ reg);
+ return -EBUSY;
+ }
+
+ /* set leds */
+ outw_p(1, card->iobase1 + 10);
+ return 0;
+}
+
+static int nortel_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int err;
+ struct orinoco_private *priv;
+ struct nortel_pci_card *card;
+ struct net_device *dev;
+ void __iomem *iomem;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
+ }
+
+ iomem = pci_iomap(pdev, 3, 0);
+ if (!iomem) {
+ err = -ENOMEM;
+ goto fail_map_io;
+ }
+
+ /* Allocate network device */
+ dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+ if (!dev) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
+ err = -ENOMEM;
+ goto fail_alloc;
+ }
+
+ priv = netdev_priv(dev);
+ card = priv->card;
+ card->iobase1 = pci_resource_start(pdev, 0);
+ card->iobase2 = pci_resource_start(pdev, 1);
+ dev->base_addr = pci_resource_start(pdev, 2);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
+
+ printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
+ "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+
+ err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
+ err = -EBUSY;
+ goto fail_irq;
+ }
+ dev->irq = pdev->irq;
+
+ err = nortel_pci_hw_init(card);
+ if (err) {
+ printk(KERN_ERR PFX "Hardware initialization failed\n");
+ goto fail;
+ }
+
+ err = nortel_pci_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
+ goto fail;
+ }
+
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register network device\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ return 0;
+
+ fail:
+ free_irq(pdev->irq, dev);
+
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+
+ fail_alloc:
+ pci_iounmap(pdev, iomem);
+
+ fail_map_io:
+ pci_release_regions(pdev);
+
+ fail_resources:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct nortel_pci_card *card = priv->card;
+
+ /* clear leds */
+ outw_p(0, card->iobase1 + 10);
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+ pci_iounmap(pdev, priv->hw.iobase);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+
+static struct pci_device_id nortel_pci_id_table[] = {
+ /* Nortel emobility PCI */
+ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+
+static struct pci_driver nortel_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = nortel_pci_id_table,
+ .probe = nortel_pci_init_one,
+ .remove = __devexit_p(nortel_pci_remove_one),
+};
+
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
+MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
+MODULE_DESCRIPTION
+ ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_LICENSE("Dual MPL/GPL");
+
+static int __init nortel_pci_init(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+ return pci_module_init(&nortel_pci_driver);
+}
+
+static void __exit nortel_pci_exit(void)
+{
+ pci_unregister_driver(&nortel_pci_driver);
+ ssleep(1);
+}
+
+module_init(nortel_pci_init);
+module_exit(nortel_pci_exit);
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 7a6f52ea7faa..5362c214fc8e 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -93,28 +93,12 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include "hermes.h"
#include "orinoco.h"
/* All the magic there is from wlan-ng */
@@ -301,8 +285,6 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
unsigned long flags;
int err;
- printk(KERN_DEBUG "%s: Orinoco-PCI entering sleep mode (state=%d)\n",
- dev->name, state);
err = orinoco_lock(priv, &flags);
if (err) {
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 7ab05b89fb3f..210e73776545 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -117,29 +117,13 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
#include <pcmcia/cisreg.h>
-#include "hermes.h"
#include "orinoco.h"
#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 85893f42445b..5e68b7026186 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -53,29 +53,13 @@
#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/fcntl.h>
-
#include <pcmcia/cisreg.h>
-#include "hermes.h"
#include "orinoco.h"
#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 0f29a9c7bc2c..5c1a1adf1ff8 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -462,14 +462,12 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
/* txpower is supported in dBm's */
range->txpower_capa = IW_TXPOW_DBM;
-#if WIRELESS_EXT > 16
/* Event capability (kernel + driver) */
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
IW_EVENT_CAPA_MASK(SIOCGIWAP));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
-#endif /* WIRELESS_EXT > 16 */
if (islpci_get_state(priv) < PRV_STATE_INIT)
return 0;
@@ -693,14 +691,13 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
extra + dwrq->length,
&(bsslist->bsslist[i]),
noise);
-#if WIRELESS_EXT > 16
+
/* Check if there is space for one more entry */
if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
/* Ask user space to try again with a bigger buffer */
rvalue = -E2BIG;
break;
}
-#endif /* WIRELESS_EXT > 16 */
}
kfree(bsslist);
@@ -2727,9 +2724,7 @@ const struct iw_handler_def prism54_handler_def = {
.standard = (iw_handler *) prism54_handler,
.private = (iw_handler *) prism54_private_handler,
.private_args = (struct iw_priv_args *) prism54_private_args,
-#if WIRELESS_EXT == 16
- .spy_offset = offsetof(islpci_private, spy_data),
-#endif /* WIRELESS_EXT == 16 */
+ .get_wireless_stats = prism54_get_wireless_stats,
};
/* For wpa_supplicant */
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index efab07e9e24e..78bdb359835e 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -439,8 +439,7 @@ prism54_bring_down(islpci_private *priv)
wmb();
/* wait a while for the device to reset */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(50*HZ/1000);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(50));
return 0;
}
@@ -491,8 +490,7 @@ islpci_reset_if(islpci_private *priv)
/* The software reset acknowledge needs about 220 msec here.
* Be conservative and wait for up to one second. */
- set_current_state(TASK_UNINTERRUPTIBLE);
- remaining = schedule_timeout(HZ);
+ remaining = schedule_timeout_uninterruptible(HZ);
if(remaining > 0) {
result = 0;
@@ -756,8 +754,7 @@ islpci_free_memory(islpci_private *priv)
pci_unmap_single(priv->pdev, buf->pci_addr,
buf->size, PCI_DMA_FROMDEVICE);
buf->pci_addr = 0;
- if (buf->mem)
- kfree(buf->mem);
+ kfree(buf->mem);
buf->size = 0;
buf->mem = NULL;
}
@@ -815,7 +812,6 @@ islpci_setup(struct pci_dev *pdev)
ndev->open = &islpci_open;
ndev->stop = &islpci_close;
ndev->get_stats = &islpci_statistics;
- ndev->get_wireless_stats = &prism54_get_wireless_stats;
ndev->do_ioctl = &prism54_ioctl;
ndev->wireless_handlers =
(struct iw_handler_def *) &prism54_handler_def;
@@ -840,11 +836,9 @@ islpci_setup(struct pci_dev *pdev)
priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
priv->monitor_type : ARPHRD_ETHER;
-#if WIRELESS_EXT > 16
/* Add pointers to enable iwspy support. */
priv->wireless_data.spy_data = &priv->spy_data;
ndev->wireless_data = &priv->wireless_data;
-#endif /* WIRELESS_EXT > 16 */
/* save the start and end address of the PCI memory area */
ndev->mem_start = (unsigned long) priv->device_base;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 32a1019f1b36..efbed4397951 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -100,9 +100,7 @@ typedef struct {
struct iw_spy_data spy_data; /* iwspy support */
-#if WIRELESS_EXT > 16
struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT > 16 */
int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 5952e9960499..3b49efa37ee5 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -97,12 +97,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
/* lock the driver code */
spin_lock_irqsave(&priv->slock, flags);
- /* determine the amount of fragments needed to store the frame */
-
- frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- if (init_wds)
- frame_size += 6;
-
/* check whether the destination queue has enough fragments for the frame */
curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
@@ -213,6 +207,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
/* store the skb address for future freeing */
priv->data_low_tx[index] = skb;
/* set the proper fragment start address and size information */
+ frame_size = skb->len;
fragment->size = cpu_to_le16(frame_size);
fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */
fragment->address = cpu_to_le32(pci_map_address);
@@ -246,12 +241,10 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
return 0;
drop_free:
- /* free the skbuf structure before aborting */
- dev_kfree_skb(skb);
- skb = NULL;
-
priv->statistics.tx_dropped++;
spin_unlock_irqrestore(&priv->slock, flags);
+ dev_kfree_skb(skb);
+ skb = NULL;
return err;
}
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index c17391d947f3..dc040caab7d7 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -267,8 +267,6 @@ prism54_suspend(struct pci_dev *pdev, pm_message_t state)
islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
BUG_ON(!priv);
- printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
- ndev->name, state);
pci_save_state(pdev);
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index b6f2e5a223be..6a60c5970cb5 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -137,7 +137,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev)
PCI_DMA_FROMDEVICE);
if (!buf->pci_addr) {
printk(KERN_WARNING
- "Failed to make memory DMA'able\n.");
+ "Failed to make memory DMA'able.\n");
return -ENOMEM;
}
}
@@ -455,7 +455,7 @@ islpci_mgt_transaction(struct net_device *ndev,
struct islpci_mgmtframe **recvframe)
{
islpci_private *priv = netdev_priv(ndev);
- const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
+ const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10);
long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
int err;
DEFINE_WAIT(wait);
@@ -475,8 +475,7 @@ islpci_mgt_transaction(struct net_device *ndev,
int timeleft;
struct islpci_mgmtframe *frame;
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeleft = schedule_timeout(wait_cycle_jiffies);
+ timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies);
frame = xchg(&priv->mgmt_received, NULL);
if (frame) {
if (frame->header->oid == oid) {
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index 12123e24b113..eea2f04c8c6d 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -268,11 +268,10 @@ mgt_clean(islpci_private *priv)
if (!priv->mib)
return;
- for (i = 0; i < OID_NUM_LAST; i++)
- if (priv->mib[i]) {
- kfree(priv->mib[i]);
- priv->mib[i] = NULL;
- }
+ for (i = 0; i < OID_NUM_LAST; i++) {
+ kfree(priv->mib[i]);
+ priv->mib[i] = NULL;
+ }
kfree(priv->mib);
priv->mib = NULL;
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 0e0ba614259a..70fd6fd8feb9 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -53,6 +53,7 @@
#include <pcmcia/ds.h>
#include <pcmcia/mem_op.h>
+#include <net/ieee80211.h>
#include <linux/wireless.h>
#include <asm/io.h>
@@ -64,7 +65,6 @@
#define WIRELESS_SPY /* Enable spying addresses */
/* Definitions we need for spy */
typedef struct iw_statistics iw_stats;
-typedef struct iw_quality iw_qual;
typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */
#include "rayctl.h"
@@ -101,7 +101,6 @@ static int ray_dev_close(struct net_device *dev);
static int ray_dev_config(struct net_device *dev, struct ifmap *map);
static struct net_device_stats *ray_get_stats(struct net_device *dev);
static int ray_dev_init(struct net_device *dev);
-static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static struct ethtool_ops netdev_ethtool_ops;
@@ -114,9 +113,8 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
unsigned char *data);
static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
static iw_stats * ray_get_wireless_stats(struct net_device * dev);
-#endif /* WIRELESS_EXT > 7 */
+static const struct iw_handler_def ray_handler_def;
/***** Prototypes for raylink functions **************************************/
static int asc_to_int(char a);
@@ -373,11 +371,12 @@ static dev_link_t *ray_attach(void)
dev->hard_start_xmit = &ray_dev_start_xmit;
dev->set_config = &ray_dev_config;
dev->get_stats = &ray_get_stats;
- dev->do_ioctl = &ray_dev_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
- dev->get_wireless_stats = ray_get_wireless_stats;
-#endif
+ dev->wireless_handlers = &ray_handler_def;
+#ifdef WIRELESS_SPY
+ local->wireless_data.spy_data = &local->spy_data;
+ dev->wireless_data = &local->wireless_data;
+#endif /* WIRELESS_SPY */
dev->set_multicast_list = &set_multicast_list;
@@ -1201,436 +1200,420 @@ static struct ethtool_ops netdev_ethtool_ops = {
/*====================================================================*/
-static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get protocol name
+ */
+static int ray_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *cwrq,
+ char *extra)
{
- ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
- int err = 0;
-#if WIRELESS_EXT > 7
- struct iwreq *wrq = (struct iwreq *) ifr;
-#endif /* WIRELESS_EXT > 7 */
-#ifdef WIRELESS_SPY
- struct sockaddr address[IW_MAX_SPY];
-#endif /* WIRELESS_SPY */
+ strcpy(cwrq, "IEEE 802.11-FH");
+ return 0;
+}
- if (!(link->state & DEV_PRESENT)) {
- DEBUG(2,"ray_dev_ioctl - device not present\n");
- return -1;
- }
- DEBUG(2,"ray_cs IOCTL dev=%p, ifr=%p, cmd = 0x%x\n",dev,ifr,cmd);
- /* Validate the command */
- switch (cmd)
- {
-#if WIRELESS_EXT > 7
- /* --------------- WIRELESS EXTENSIONS --------------- */
- /* Get name */
- case SIOCGIWNAME:
- strcpy(wrq->u.name, "IEEE 802.11-FH");
- break;
-
- /* Get frequency/channel */
- case SIOCGIWFREQ:
- wrq->u.freq.m = local->sparm.b5.a_hop_pattern;
- wrq->u.freq.e = 0;
- break;
-
- /* Set frequency/channel */
- case SIOCSIWFREQ:
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int ray_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int err = -EINPROGRESS; /* Call commit handler */
- /* Setting by channel number */
- if ((wrq->u.freq.m > USA_HOP_MOD) || (wrq->u.freq.e > 0))
- err = -EOPNOTSUPP;
- else
- local->sparm.b5.a_hop_pattern = wrq->u.freq.m;
- break;
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
- /* Get current network name (ESSID) */
- case SIOCGIWESSID:
- if (wrq->u.data.pointer)
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
- /* Get the essid that was set */
- memcpy(essid, local->sparm.b5.a_current_ess_id,
- IW_ESSID_MAX_SIZE);
- essid[IW_ESSID_MAX_SIZE] = '\0';
-
- /* Push it out ! */
- wrq->u.data.length = strlen(essid) + 1;
- wrq->u.data.flags = 1; /* active */
- if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)))
- err = -EFAULT;
- }
- break;
+ /* Setting by channel number */
+ if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0))
+ err = -EOPNOTSUPP;
+ else
+ local->sparm.b5.a_hop_pattern = fwrq->m;
- /* Set desired network name (ESSID) */
- case SIOCSIWESSID:
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+ return err;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int ray_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- if (wrq->u.data.pointer)
- {
- char card_essid[IW_ESSID_MAX_SIZE + 1];
-
- /* Check if we asked for `any' */
- if(wrq->u.data.flags == 0)
- {
+ fwrq->m = local->sparm.b5.a_hop_pattern;
+ fwrq->e = 0;
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set ESSID
+ */
+static int ray_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* Check if we asked for `any' */
+ if(dwrq->flags == 0) {
/* Corey : can you do that ? */
- err = -EOPNOTSUPP;
- }
- else
- {
+ return -EOPNOTSUPP;
+ } else {
/* Check the size of the string */
- if(wrq->u.data.length >
- IW_ESSID_MAX_SIZE + 1)
- {
- err = -E2BIG;
- break;
- }
- if (copy_from_user(card_essid,
- wrq->u.data.pointer,
- wrq->u.data.length)) {
- err = -EFAULT;
- break;
+ if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+ return -E2BIG;
}
- card_essid[IW_ESSID_MAX_SIZE] = '\0';
/* Set the ESSID in the card */
- memcpy(local->sparm.b5.a_current_ess_id, card_essid,
- IW_ESSID_MAX_SIZE);
- }
+ memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE);
+ memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length);
}
- break;
-
- /* Get current Access Point (BSSID in our case) */
- case SIOCGIWAP:
- memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN);
- wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
- break;
-
- /* Get the current bit-rate */
- case SIOCGIWRATE:
- if(local->net_default_tx_rate == 3)
- wrq->u.bitrate.value = 2000000; /* Hum... */
- else
- wrq->u.bitrate.value = local->net_default_tx_rate * 500000;
- wrq->u.bitrate.fixed = 0; /* We are in auto mode */
- break;
-
- /* Set the desired bit-rate */
- case SIOCSIWRATE:
- /* Check if rate is in range */
- if((wrq->u.bitrate.value != 1000000) &&
- (wrq->u.bitrate.value != 2000000))
- {
- err = -EINVAL;
- break;
- }
- /* Hack for 1.5 Mb/s instead of 2 Mb/s */
- if((local->fw_ver == 0x55) && /* Please check */
- (wrq->u.bitrate.value == 2000000))
- local->net_default_tx_rate = 3;
- else
- local->net_default_tx_rate = wrq->u.bitrate.value/500000;
- break;
-
- /* Get the current RTS threshold */
- case SIOCGIWRTS:
- wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8)
- + local->sparm.b5.a_rts_threshold[1];
-#if WIRELESS_EXT > 8
- wrq->u.rts.disabled = (wrq->u.rts.value == 32767);
-#endif /* WIRELESS_EXT > 8 */
- wrq->u.rts.fixed = 1;
- break;
-
- /* Set the desired RTS threshold */
- case SIOCSIWRTS:
- {
- int rthr = wrq->u.rts.value;
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* if(wrq->u.rts.fixed == 0) we should complain */
-#if WIRELESS_EXT > 8
- if(wrq->u.rts.disabled)
- rthr = 32767;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get ESSID
+ */
+static int ray_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Get the essid that was set */
+ memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
+ extra[IW_ESSID_MAX_SIZE] = '\0';
+
+ /* Push it out ! */
+ dwrq->length = strlen(extra) + 1;
+ dwrq->flags = 1; /* active */
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get AP address
+ */
+static int ray_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ memcpy(awrq->sa_data, local->bss_id, ETH_ALEN);
+ awrq->sa_family = ARPHRD_ETHER;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Bit-Rate
+ */
+static int ray_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* Check if rate is in range */
+ if((vwrq->value != 1000000) && (vwrq->value != 2000000))
+ return -EINVAL;
+
+ /* Hack for 1.5 Mb/s instead of 2 Mb/s */
+ if((local->fw_ver == 0x55) && /* Please check */
+ (vwrq->value == 2000000))
+ local->net_default_tx_rate = 3;
else
-#endif /* WIRELESS_EXT > 8 */
- if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */
- {
- err = -EINVAL;
- break;
- }
+ local->net_default_tx_rate = vwrq->value/500000;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Bit-Rate
+ */
+static int ray_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ if(local->net_default_tx_rate == 3)
+ vwrq->value = 2000000; /* Hum... */
+ else
+ vwrq->value = local->net_default_tx_rate * 500000;
+ vwrq->fixed = 0; /* We are in auto mode */
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set RTS threshold
+ */
+static int ray_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int rthr = vwrq->value;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ /* if(wrq->u.rts.fixed == 0) we should complain */
+ if(vwrq->disabled)
+ rthr = 32767;
+ else {
+ if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */
+ return -EINVAL;
+ }
local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF;
local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF;
- }
- break;
- /* Get the current fragmentation threshold */
- case SIOCGIWFRAG:
- wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8)
- + local->sparm.b5.a_frag_threshold[1];
-#if WIRELESS_EXT > 8
- wrq->u.frag.disabled = (wrq->u.frag.value == 32767);
-#endif /* WIRELESS_EXT > 8 */
- wrq->u.frag.fixed = 1;
- break;
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* Set the desired fragmentation threshold */
- case SIOCSIWFRAG:
- {
- int fthr = wrq->u.frag.value;
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get RTS threshold
+ */
+static int ray_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+
+ vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8)
+ + local->sparm.b5.a_rts_threshold[1];
+ vwrq->disabled = (vwrq->value == 32767);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Fragmentation threshold
+ */
+static int ray_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int fthr = vwrq->value;
+
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
/* if(wrq->u.frag.fixed == 0) should complain */
-#if WIRELESS_EXT > 8
- if(wrq->u.frag.disabled)
- fthr = 32767;
- else
-#endif /* WIRELESS_EXT > 8 */
- if((fthr < 256) || (fthr > 2347)) /* To check out ! */
- {
- err = -EINVAL;
- break;
- }
+ if(vwrq->disabled)
+ fthr = 32767;
+ else {
+ if((fthr < 256) || (fthr > 2347)) /* To check out ! */
+ return -EINVAL;
+ }
local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF;
local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF;
- }
- break;
-#endif /* WIRELESS_EXT > 7 */
-#if WIRELESS_EXT > 8
+ return -EINPROGRESS; /* Call commit handler */
+}
- /* Get the current mode of operation */
- case SIOCGIWMODE:
- if(local->sparm.b5.a_network_type)
- wrq->u.mode = IW_MODE_INFRA;
- else
- wrq->u.mode = IW_MODE_ADHOC;
- break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Fragmentation threshold
+ */
+static int ray_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- /* Set the current mode of operation */
- case SIOCSIWMODE:
- {
+ vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8)
+ + local->sparm.b5.a_frag_threshold[1];
+ vwrq->disabled = (vwrq->value == 32767);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set Mode of Operation
+ */
+static int ray_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ int err = -EINPROGRESS; /* Call commit handler */
char card_mode = 1;
-
- /* Reject if card is already initialised */
- if(local->card_status != CARD_AWAITING_PARAM)
- {
- err = -EBUSY;
- break;
- }
- switch (wrq->u.mode)
+ /* Reject if card is already initialised */
+ if(local->card_status != CARD_AWAITING_PARAM)
+ return -EBUSY;
+
+ switch (*uwrq)
{
case IW_MODE_ADHOC:
- card_mode = 0;
- // Fall through
+ card_mode = 0;
+ // Fall through
case IW_MODE_INFRA:
- local->sparm.b5.a_network_type = card_mode;
- break;
+ local->sparm.b5.a_network_type = card_mode;
+ break;
default:
- err = -EINVAL;
+ err = -EINVAL;
}
- }
- break;
-#endif /* WIRELESS_EXT > 8 */
-#if WIRELESS_EXT > 7
- /* ------------------ IWSPY SUPPORT ------------------ */
- /* Define the range (variations) of above parameters */
- case SIOCGIWRANGE:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_range range;
- memset((char *) &range, 0, sizeof(struct iw_range));
-
- /* Set the length (very important for backward compatibility) */
- wrq->u.data.length = sizeof(struct iw_range);
-
-#if WIRELESS_EXT > 10
- /* Set the Wireless Extension versions */
- range.we_version_compiled = WIRELESS_EXT;
- range.we_version_source = 9;
-#endif /* WIRELESS_EXT > 10 */
-
- /* Set information in the range struct */
- range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */
- range.num_channels = hop_pattern_length[(int)country];
- range.num_frequency = 0;
- range.max_qual.qual = 0;
- range.max_qual.level = 255; /* What's the correct value ? */
- range.max_qual.noise = 255; /* Idem */
- range.num_bitrates = 2;
- range.bitrate[0] = 1000000; /* 1 Mb/s */
- range.bitrate[1] = 2000000; /* 2 Mb/s */
-
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- err = -EFAULT;
- }
- break;
+ return err;
+}
-#ifdef WIRELESS_SPY
- /* Set addresses to spy */
- case SIOCSIWSPY:
- /* Check the number of addresses */
- if(wrq->u.data.length > IW_MAX_SPY)
- {
- err = -E2BIG;
- break;
- }
- local->spy_number = wrq->u.data.length;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get Mode of Operation
+ */
+static int ray_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
- /* If there is some addresses to copy */
- if(local->spy_number > 0)
- {
- int i;
-
- /* Copy addresses to the driver */
- if(copy_from_user(address, wrq->u.data.pointer,
- sizeof(struct sockaddr) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Copy addresses to the lp structure */
- for(i = 0; i < local->spy_number; i++)
- memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
-
- /* Reset structure... */
- memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
-
-#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
- for(i = 0; i < local->spy_number; i++)
- printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
- local->spy_address[i][0],
- local->spy_address[i][1],
- local->spy_address[i][2],
- local->spy_address[i][3],
- local->spy_address[i][4],
- local->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
- }
- break;
+ if(local->sparm.b5.a_network_type)
+ *uwrq = IW_MODE_INFRA;
+ else
+ *uwrq = IW_MODE_ADHOC;
- /* Get the spy list and spy stats */
- case SIOCGIWSPY:
- /* Set the number of addresses */
- wrq->u.data.length = local->spy_number;
+ return 0;
+}
- /* If the user want to have the addresses back... */
- if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
- {
- int i;
-
- /* Copy addresses from the lp structure */
- for(i = 0; i < local->spy_number; i++)
- {
- memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
- address[i].sa_family = ARPHRD_ETHER;
- }
-
- /* Copy addresses to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, address,
- sizeof(struct sockaddr) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Copy stats to the user buffer (just after) */
- if(copy_to_user(wrq->u.data.pointer +
- (sizeof(struct sockaddr) * local->spy_number),
- local->spy_stat, sizeof(iw_qual) * local->spy_number))
- {
- err = -EFAULT;
- break;
- }
-
- /* Reset updated flags */
- for(i = 0; i < local->spy_number; i++)
- local->spy_stat[i].updated = 0x0;
- } /* if(pointer != NULL) */
-
- break;
-#endif /* WIRELESS_SPY */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int ray_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+
+ memset((char *) range, 0, sizeof(struct iw_range));
+
+ /* Set the length (very important for backward compatibility) */
+ dwrq->length = sizeof(struct iw_range);
+
+ /* Set the Wireless Extension versions */
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 9;
+
+ /* Set information in the range struct */
+ range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */
+ range->num_channels = hop_pattern_length[(int)country];
+ range->num_frequency = 0;
+ range->max_qual.qual = 0;
+ range->max_qual.level = 255; /* What's the correct value ? */
+ range->max_qual.noise = 255; /* Idem */
+ range->num_bitrates = 2;
+ range->bitrate[0] = 1000000; /* 1 Mb/s */
+ range->bitrate[1] = 2000000; /* 2 Mb/s */
+ return 0;
+}
- /* ------------------ PRIVATE IOCTL ------------------ */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
-#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */
-#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
- case SIOCSIPFRAMING:
- if(!capable(CAP_NET_ADMIN)) /* For private IOCTLs, we need to check permissions */
- {
- err = -EPERM;
- break;
- }
- translate = *(wrq->u.name); /* Set framing mode */
- break;
- case SIOCGIPFRAMING:
- *(wrq->u.name) = translate;
- break;
- case SIOCGIPCOUNTRY:
- *(wrq->u.name) = country;
- break;
- case SIOCGIWPRIV:
- /* Export our "private" intercace */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_priv_args priv[] =
- { /* cmd, set_args, get_args, name */
- { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
- { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
- { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
- };
- /* Set the number of ioctl available */
- wrq->u.data.length = 3;
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
- sizeof(priv)))
- err = -EFAULT;
- }
- break;
-#endif /* WIRELESS_EXT > 7 */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set framing mode
+ */
+static int ray_set_framing(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ translate = *(extra); /* Set framing mode */
+ return 0;
+}
- default:
- DEBUG(0,"ray_dev_ioctl cmd = 0x%x\n", cmd);
- err = -EOPNOTSUPP;
- }
- return err;
-} /* end ray_dev_ioctl */
-/*===========================================================================*/
-#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get framing mode
+ */
+static int ray_get_framing(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ *(extra) = translate;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get country
+ */
+static int ray_get_country(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ *(extra) = country;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Commit handler : called after a bunch of SET operations
+ */
+static int ray_commit(struct net_device *dev,
+ struct iw_request_info *info, /* NULL */
+ void *zwrq, /* NULL */
+ char *extra) /* NULL */
+{
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Stats handler : return Wireless Stats
+ */
static iw_stats * ray_get_wireless_stats(struct net_device * dev)
{
ray_dev_t * local = (ray_dev_t *) dev->priv;
@@ -1642,13 +1625,13 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
local->wstats.status = local->card_status;
#ifdef WIRELESS_SPY
- if((local->spy_number > 0) && (local->sparm.b5.a_network_type == 0))
+ if((local->spy_data.spy_number > 0) && (local->sparm.b5.a_network_type == 0))
{
/* Get it from the first node in spy list */
- local->wstats.qual.qual = local->spy_stat[0].qual;
- local->wstats.qual.level = local->spy_stat[0].level;
- local->wstats.qual.noise = local->spy_stat[0].noise;
- local->wstats.qual.updated = local->spy_stat[0].updated;
+ local->wstats.qual.qual = local->spy_data.spy_stat[0].qual;
+ local->wstats.qual.level = local->spy_data.spy_stat[0].level;
+ local->wstats.qual.noise = local->spy_data.spy_stat[0].noise;
+ local->wstats.qual.updated = local->spy_data.spy_stat[0].updated;
}
#endif /* WIRELESS_SPY */
@@ -1659,7 +1642,65 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
return &local->wstats;
} /* end ray_get_wireless_stats */
-#endif /* WIRELESS_EXT > 7 */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const iw_handler ray_handler[] = {
+ [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit,
+ [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) ray_get_name,
+ [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) ray_set_freq,
+ [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) ray_get_freq,
+ [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) ray_set_mode,
+ [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) ray_get_mode,
+ [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range,
+#ifdef WIRELESS_SPY
+ [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,
+#endif /* WIRELESS_SPY */
+ [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) ray_get_wap,
+ [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid,
+ [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid,
+ [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) ray_set_rate,
+ [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) ray_get_rate,
+ [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) ray_set_rts,
+ [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) ray_get_rts,
+ [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) ray_set_frag,
+ [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) ray_get_frag,
+};
+
+#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
+#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */
+#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
+
+static const iw_handler ray_private_handler[] = {
+ [0] = (iw_handler) ray_set_framing,
+ [1] = (iw_handler) ray_get_framing,
+ [3] = (iw_handler) ray_get_country,
+};
+
+static const struct iw_priv_args ray_private_args[] = {
+/* cmd, set_args, get_args, name */
+{ SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
+{ SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
+{ SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
+};
+
+static const struct iw_handler_def ray_handler_def =
+{
+ .num_standard = sizeof(ray_handler)/sizeof(iw_handler),
+ .num_private = sizeof(ray_private_handler)/sizeof(iw_handler),
+ .num_private_args = sizeof(ray_private_args)/sizeof(struct iw_priv_args),
+ .standard = ray_handler,
+ .private = ray_private_handler,
+ .private_args = ray_private_args,
+ .get_wireless_stats = ray_get_wireless_stats,
+};
+
/*===========================================================================*/
static int ray_open(struct net_device *dev)
{
@@ -2392,20 +2433,15 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned i
/*local->wstats.qual.noise = none ? */
local->wstats.qual.updated = 0x2;
}
- /* Now, for the addresses in the spy list */
+ /* Now, update the spy stuff */
{
- int i;
- /* Look all addresses */
- for(i = 0; i < local->spy_number; i++)
- /* If match */
- if(!memcmp(linksrcaddr, local->spy_address[i], ETH_ALEN))
- {
- /* Update statistics */
- /*local->spy_stat[i].qual = none ? */
- local->spy_stat[i].level = siglev;
- /*local->spy_stat[i].noise = none ? */
- local->spy_stat[i].updated = 0x2;
- }
+ struct iw_quality wstats;
+ wstats.level = siglev;
+ /* wstats.noise = none ? */
+ /* wstats.qual = none ? */
+ wstats.updated = 0x2;
+ /* Update spy records */
+ wireless_spy_update(dev, linksrcaddr, &wstats);
}
#endif /* WIRELESS_SPY */
} /* end rx_data */
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index c77afa14fa86..42660fe64bfd 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -63,13 +63,10 @@ typedef struct ray_dev_t {
UCHAR last_rsl;
int beacon_rxed;
struct beacon_rx last_bcn;
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless specific stats */
-#endif
#ifdef WIRELESS_SPY
- int spy_number; /* Number of addresses to spy */
- mac_addr spy_address[IW_MAX_SPY + 1]; /* The addresses to spy */
- iw_qual spy_stat[IW_MAX_SPY + 1]; /* Statistics gathered */
+ struct iw_spy_data spy_data;
+ struct iw_public_data wireless_data;
#endif /* WIRELESS_SPY */
} ray_dev_t;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
new file mode 100644
index 000000000000..b1bbc8e8e91f
--- /dev/null
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -0,0 +1,1073 @@
+/*
+ * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
+ * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Communications and Intel PRO/Wireless 2011B.
+ *
+ * The driver implements Symbol firmware download. The rest is handled
+ * in hermes.c and orinoco.c.
+ *
+ * Utilities for downloading the Symbol firmware are available at
+ * http://sourceforge.net/projects/orinoco/
+ *
+ * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
+ * Portions based on orinoco_cs.c:
+ * Copyright (C) David Gibson, Linuxcare Australia
+ * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
+ * Copyright (C) Symbol Technologies.
+ *
+ * See copyright notice in file orinoco.c.
+ */
+
+#define DRIVER_NAME "spectrum_cs"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+#include <linux/module.h>
+#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>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include "orinoco.h"
+
+static unsigned char *primsym;
+static unsigned char *secsym;
+static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
+static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
+
+/********************************************************************/
+/* Module stuff */
+/********************************************************************/
+
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
+MODULE_LICENSE("Dual MPL/GPL");
+
+/* Module parameters */
+
+/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+ * don't have any CIS entry for it. This workaround it... */
+static int ignore_cis_vcc; /* = 0 */
+module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
+
+/********************************************************************/
+/* Magic constants */
+/********************************************************************/
+
+/*
+ * The dev_info variable is the "key" that is used to match up this
+ * device driver with appropriate cards, through the card
+ * configuration database.
+ */
+static dev_info_t dev_info = DRIVER_NAME;
+
+/********************************************************************/
+/* Data structures */
+/********************************************************************/
+
+/* PCMCIA specific device information (goes in the card field of
+ * struct orinoco_private */
+struct orinoco_pccard {
+ dev_link_t link;
+ dev_node_t node;
+};
+
+/*
+ * A linked list of "instances" of the device. Each actual PCMCIA
+ * card corresponds to one device instance, and is described by one
+ * dev_link_t structure (defined in ds.h).
+ */
+static dev_link_t *dev_list; /* = NULL */
+
+/********************************************************************/
+/* Function prototypes */
+/********************************************************************/
+
+static void spectrum_cs_release(dev_link_t *link);
+static void spectrum_cs_detach(dev_link_t *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)
+
+/*
+ * Reset the card using configuration registers COR and CCSR.
+ * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
+ */
+static int
+spectrum_reset(dev_link_t *link, int idle)
+{
+ int last_ret, last_fn;
+ conf_reg_t reg;
+ u_int save_cor;
+
+ /* Doing it if hardware is gone is guaranteed crash */
+ if (!(link->state & DEV_CONFIG))
+ return -ENODEV;
+
+ /* Save original COR value */
+ reg.Function = 0;
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_COR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ save_cor = reg.Value;
+
+ /* Soft-Reset card */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor | COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ udelay(1000);
+
+ /* Read CCSR */
+ reg.Action = CS_READ;
+ reg.Offset = CISREG_CCSR;
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+
+ /*
+ * Start or stop the firmware. Memory width bit should be
+ * preserved from the value we've just read.
+ */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_CCSR;
+ reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ udelay(1000);
+
+ /* Restore original COR configuration index */
+ reg.Action = CS_WRITE;
+ reg.Offset = CISREG_COR;
+ reg.Value = (save_cor & ~COR_SOFT_RESET);
+ CS_CHECK(AccessConfigurationRegister,
+ pcmcia_access_configuration_register(link->handle, &reg));
+ udelay(1000);
+ return 0;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+ return -ENODEV;
+}
+
+
+/*
+ * 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_words(hw, HERMES_AUXDATA, pdi->data,
+ pdi_len(pdi) / 2);
+
+ 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_words(hw, HERMES_AUXDATA, blk->data,
+ blklen / 2);
+
+ 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, dev_link_t *link,
+ const unsigned char *image)
+{
+ 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 (image != primsym) {
+ 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 (image != primsym) {
+ 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 (image != primsym && 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
+spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+{
+ int ret;
+ client_handle_t handle = link->handle;
+ const struct firmware *fw_entry;
+
+ if (request_firmware(&fw_entry, primary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ primsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ primary_fw_name);
+ return -ENOENT;
+ }
+
+ if (request_firmware(&fw_entry, secondary_fw_name,
+ &handle_to_dev(handle)) == 0) {
+ secsym = fw_entry->data;
+ } else {
+ printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+ secondary_fw_name);
+ return -ENOENT;
+ }
+
+ /* Load primary firmware */
+ ret = spectrum_dl_image(hw, link, primsym);
+ if (ret) {
+ printk(KERN_ERR PFX "Primary firmware download failed\n");
+ return ret;
+ }
+
+ /* Load secondary firmware */
+ ret = spectrum_dl_image(hw, link, secsym);
+
+ 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)
+{
+ struct orinoco_pccard *card = priv->card;
+ dev_link_t *link = &card->link;
+ int err;
+
+ if (!hermes_present(&priv->hw)) {
+ /* The firmware needs to be reloaded */
+ if (spectrum_dl_firmware(&priv->hw, &card->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;
+}
+
+/********************************************************************/
+/* PCMCIA stuff */
+/********************************************************************/
+
+/*
+ * This creates an "instance" of the driver, allocating local data
+ * structures for one device. The device is registered with Card
+ * Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a card
+ * insertion event. */
+static dev_link_t *
+spectrum_cs_attach(void)
+{
+ struct net_device *dev;
+ struct orinoco_private *priv;
+ struct orinoco_pccard *card;
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret;
+
+ dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+ if (! dev)
+ return NULL;
+ priv = netdev_priv(dev);
+ card = priv->card;
+
+ /* Link both structures together */
+ link = &card->link;
+ link->priv = dev;
+
+ /* Interrupt setup */
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.Handler = orinoco_interrupt;
+ link->irq.Instance = dev;
+
+ /* General socket configuration defaults can go here. In this
+ * client, we assume very little, and rely on the CIS for
+ * almost everything. In most clients, many details (i.e.,
+ * number, sizes, and attributes of IO windows) are fixed by
+ * the nature of the device, and can be hard-wired here. */
+ link->conf.Attributes = 0;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ /* FIXME: need a lock? */
+ link->next = dev_list;
+ dev_list = link;
+
+ client_reg.dev_info = &dev_info;
+ client_reg.Version = 0x0210; /* FIXME: what does this mean? */
+ client_reg.event_callback_args.client_data = link;
+
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ spectrum_cs_detach(link);
+ return NULL;
+ }
+
+ return link;
+} /* spectrum_cs_attach */
+
+/*
+ * This deletes a driver "instance". The device is de-registered with
+ * Card Services. If it has been released, all local data structures
+ * are freed. Otherwise, the structures will be freed when the device
+ * is released.
+ */
+static void spectrum_cs_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+ struct net_device *dev = link->priv;
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+
+ BUG_ON(*linkp == NULL);
+
+ if (link->state & DEV_CONFIG)
+ spectrum_cs_release(link);
+
+ /* Break the link with Card Services */
+ if (link->handle)
+ pcmcia_deregister_client(link->handle);
+
+ /* Unlink device structure, and free it */
+ *linkp = link->next;
+ DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
+ if (link->dev) {
+ DEBUG(0, PFX "About to unregister net device %p\n",
+ dev);
+ unregister_netdev(dev);
+ }
+ free_orinocodev(dev);
+} /* spectrum_cs_detach */
+
+/*
+ * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
+ * event is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+
+static void
+spectrum_cs_config(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ client_handle_t handle = link->handle;
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_pccard *card = priv->card;
+ hermes_t *hw = &priv->hw;
+ int last_fn, last_ret;
+ u_char buf[64];
+ config_info_t conf;
+ cisinfo_t info;
+ tuple_t tuple;
+ cisparse_t parse;
+ void __iomem *mem;
+
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+
+ /*
+ * This reads the card's CONFIG tuple to find its
+ * configuration registers.
+ */
+ 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;
+
+ /* Look up the current Vcc */
+ CS_CHECK(GetConfigurationInfo,
+ pcmcia_get_configuration_info(handle, &conf));
+ link->conf.Vcc = conf.Vcc;
+
+ /*
+ * 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(handle, &tuple));
+ while (1) {
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ cistpl_cftable_entry_t dflt = { .index = 0 };
+
+ if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
+ || (pcmcia_parse_tuple(handle, &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->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.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ 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->handle, &link->io) != 0)
+ goto next_entry;
+ }
+
+
+ /* If we got this far, we're cool! */
+
+ break;
+
+ next_entry:
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ if (last_ret == CS_NO_MORE_ITEMS) {
+ printk(KERN_ERR PFX "GetNextTuple(): No matching "
+ "CIS configuration. Maybe you need the "
+ "ignore_cis_vcc=1 parameter.\n");
+ goto cs_failed;
+ }
+ }
+
+ /*
+ * 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.
+ */
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+
+ /* We initialize the hermes structure before completing PCMCIA
+ * configuration just in case the interrupt handler gets
+ * called. */
+ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+ if (!mem)
+ goto cs_failed;
+
+ hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+
+ /*
+ * 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));
+
+ /* Ok, we have the configuration, prepare to register the netdev */
+ dev->base_addr = link->io.BasePort1;
+ dev->irq = link->irq.AssignedIRQ;
+ SET_MODULE_OWNER(dev);
+ card->node.major = card->node.minor = 0;
+
+ /* Reset card and download firmware */
+ if (spectrum_cs_hard_reset(priv) != 0) {
+ goto failed;
+ }
+
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ /* Tell the stack we exist */
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR PFX "register_netdev() failed\n");
+ goto failed;
+ }
+
+ /* At this point, the dev_node_t structure(s) needs to be
+ * initialized and arranged in a linked list at link->dev. */
+ strcpy(card->node.dev_name, dev->name);
+ link->dev = &card->node; /* link->dev being non-NULL is also
+ used to indicate that the
+ net_device has been registered */
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ /* Finally, report what we've done */
+ printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
+ dev->name, 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);
+ 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");
+
+ return;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+ spectrum_cs_release(link);
+} /* spectrum_cs_config */
+
+/*
+ * After a card is removed, spectrum_cs_release() will unregister the
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void
+spectrum_cs_release(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ /* We're committed to taking the device away now, so mark the
+ * hardware as unavailable */
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Don't bother checking to see if these succeed or not */
+ 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;
+ if (priv->hw.iobase)
+ ioport_unmap(priv->hw.iobase);
+} /* spectrum_cs_release */
+
+/*
+ * The card status event handler. Mostly, this schedules other stuff
+ * to run after an event is received.
+ */
+static int
+spectrum_cs_event(event_t event, int priority,
+ event_callback_args_t * args)
+{
+ dev_link_t *link = args->client_data;
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ int err = 0;
+ unsigned long flags;
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ spectrum_cs_config(link);
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ /* Mark the device as stopped, to block IO until later */
+ if (link->state & DEV_CONFIG) {
+ /* This is probably racy, but I can't think of
+ a better way, short of rewriting the PCMCIA
+ layer to not suck :-( */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
+ dev->name,
+ event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
+ err);
+
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ pcmcia_release_configuration(link->handle);
+ }
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG) {
+ /* FIXME: should we double check that this is
+ * the same card as we had before */
+ pcmcia_request_configuration(link->handle, &link->conf);
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
+ }
+ break;
+ }
+
+ return err;
+} /* spectrum_cs_event */
+
+/********************************************************************/
+/* Module initialization */
+/********************************************************************/
+
+/* Can't be declared "const" or the whole __initdata section will
+ * become const */
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Pavel Roskin <proski@gnu.org>,"
+ " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
+
+static struct pcmcia_device_id spectrum_cs_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
+ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
+ PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
+
+static struct pcmcia_driver orinoco_driver = {
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = DRIVER_NAME,
+ },
+ .attach = spectrum_cs_attach,
+ .detach = spectrum_cs_detach,
+ .event = spectrum_cs_event,
+ .id_table = spectrum_cs_ids,
+};
+
+static int __init
+init_spectrum_cs(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+
+ return pcmcia_register_driver(&orinoco_driver);
+}
+
+static void __exit
+exit_spectrum_cs(void)
+{
+ pcmcia_unregister_driver(&orinoco_driver);
+ BUG_ON(dev_list != NULL);
+}
+
+module_init(init_spectrum_cs);
+module_exit(exit_spectrum_cs);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 6c42b573a95a..d25264ba0c0e 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -209,7 +209,7 @@ enum {
NoStructure = 0, /* Really old firmware */
StructuredMessages = 1, /* Parsable AT response msgs */
ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */
-} FirmwareLevel;
+};
struct strip {
int magic;
@@ -860,12 +860,9 @@ static int allocate_buffers(struct strip *strip_info, int mtu)
strip_info->mtu = dev->mtu = mtu;
return (1);
}
- if (r)
- kfree(r);
- if (s)
- kfree(s);
- if (t)
- kfree(t);
+ kfree(r);
+ kfree(s);
+ kfree(t);
return (0);
}
@@ -922,13 +919,9 @@ static int strip_change_mtu(struct net_device *dev, int new_mtu)
printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n",
strip_info->dev->name, old_mtu, strip_info->mtu);
- if (orbuff)
- kfree(orbuff);
- if (osbuff)
- kfree(osbuff);
- if (otbuff)
- kfree(otbuff);
-
+ kfree(orbuff);
+ kfree(osbuff);
+ kfree(otbuff);
return 0;
}
@@ -1352,7 +1345,7 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
struct in_device *in_dev;
rcu_read_lock();
- in_dev = __in_dev_get(strip_info->dev);
+ in_dev = __in_dev_get_rcu(strip_info->dev);
if (in_dev == NULL) {
rcu_read_unlock();
return NULL;
@@ -1508,7 +1501,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
brd = addr = 0;
rcu_read_lock();
- in_dev = __in_dev_get(strip_info->dev);
+ in_dev = __in_dev_get_rcu(strip_info->dev);
if (in_dev) {
if (in_dev->ifa_list) {
brd = in_dev->ifa_list->ifa_broadcast;
@@ -2498,18 +2491,13 @@ static int strip_close_low(struct net_device *dev)
/*
* Free all STRIP frame buffers.
*/
- if (strip_info->rx_buff) {
- kfree(strip_info->rx_buff);
- strip_info->rx_buff = NULL;
- }
- if (strip_info->sx_buff) {
- kfree(strip_info->sx_buff);
- strip_info->sx_buff = NULL;
- }
- if (strip_info->tx_buff) {
- kfree(strip_info->tx_buff);
- strip_info->tx_buff = NULL;
- }
+ kfree(strip_info->rx_buff);
+ strip_info->rx_buff = NULL;
+ kfree(strip_info->sx_buff);
+ strip_info->sx_buff = NULL;
+ kfree(strip_info->tx_buff);
+ strip_info->tx_buff = NULL;
+
del_timer(&strip_info->idle_timer);
return 0;
}
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 7a5e20a17890..b0d8b5b03152 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -430,7 +430,6 @@ static void fee_read(unsigned long ioaddr, /* I/O port of the card */
}
}
-#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -514,7 +513,6 @@ static void fee_write(unsigned long ioaddr, /* I/O port of the card */
fee_wait(ioaddr, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
-#endif /* WIRELESS_EXT */
/************************ I82586 SUBROUTINES *************************/
/*
@@ -973,11 +971,9 @@ static void wv_mmc_show(struct net_device * dev)
mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
/* Don't forget to update statistics */
lp->wstats.discard.nwid +=
(m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
#ifdef DEBUG_SHOW_UNUSED
@@ -1499,7 +1495,6 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
}
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -2473,7 +2468,6 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
#endif
return &lp->wstats;
}
-#endif /* WIRELESS_EXT */
/************************* PACKET RECEPTION *************************/
/*
@@ -4194,11 +4188,9 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr)
dev->set_mac_address = &wavelan_set_mac_address;
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
dev->wireless_handlers = &wavelan_handler_def;
lp->wireless_data.spy_data = &lp->spy_data;
dev->wireless_data = &lp->wireless_data;
-#endif
dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 509ff22a6caa..166e28b9a4f7 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -409,11 +409,9 @@
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */
#undef SET_MAC_ADDRESS /* Experimental */
-#ifdef WIRELESS_EXT /* If wireless extensions exist in the kernel */
/* Warning: this stuff will slow down the driver. */
#define WIRELESS_SPY /* Enable spying addresses. */
#undef HISTOGRAM /* Enable histogram of signal level. */
-#endif
/****************************** DEBUG ******************************/
@@ -506,12 +504,10 @@ struct net_local
u_short tx_first_free;
u_short tx_first_in_use;
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless-specific statistics */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif
#ifdef HISTOGRAM
int his_number; /* number of intervals */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index f6130a53b796..4b3c98f5c564 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -59,6 +59,12 @@
/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */
#include "wavelan_cs.p.h" /* Private header */
+#ifdef WAVELAN_ROAMING
+static void wl_cell_expiry(unsigned long data);
+static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp);
+static void wv_nwid_filter(unsigned char mode, net_local *lp);
+#endif /* WAVELAN_ROAMING */
+
/************************* MISC SUBROUTINES **************************/
/*
* Subroutines which won't fit in one of the following category
@@ -409,7 +415,6 @@ fee_read(u_long base, /* i/o port of the card */
}
}
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -494,15 +499,14 @@ fee_write(u_long base, /* i/o port of the card */
fee_wait(base, 10, 100);
#endif /* EEPROM_IS_PROTECTED */
}
-#endif /* WIRELESS_EXT */
/******************* WaveLAN Roaming routines... ********************/
#ifdef WAVELAN_ROAMING /* Conditional compile, see wavelan_cs.h */
-unsigned char WAVELAN_BEACON_ADDRESS[]= {0x09,0x00,0x0e,0x20,0x03,0x00};
+static unsigned char WAVELAN_BEACON_ADDRESS[] = {0x09,0x00,0x0e,0x20,0x03,0x00};
-void wv_roam_init(struct net_device *dev)
+static void wv_roam_init(struct net_device *dev)
{
net_local *lp= netdev_priv(dev);
@@ -531,7 +535,7 @@ void wv_roam_init(struct net_device *dev)
printk(KERN_DEBUG "WaveLAN: Roaming enabled on device %s\n",dev->name);
}
-void wv_roam_cleanup(struct net_device *dev)
+static void wv_roam_cleanup(struct net_device *dev)
{
wavepoint_history *ptr,*old_ptr;
net_local *lp= netdev_priv(dev);
@@ -550,7 +554,7 @@ void wv_roam_cleanup(struct net_device *dev)
}
/* Enable/Disable NWID promiscuous mode on a given device */
-void wv_nwid_filter(unsigned char mode, net_local *lp)
+static void wv_nwid_filter(unsigned char mode, net_local *lp)
{
mm_t m;
unsigned long flags;
@@ -575,7 +579,7 @@ void wv_nwid_filter(unsigned char mode, net_local *lp)
}
/* Find a record in the WavePoint table matching a given NWID */
-wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
+static wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
{
wavepoint_history *ptr=lp->wavepoint_table.head;
@@ -588,7 +592,7 @@ wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp)
}
/* Create a new wavepoint table entry */
-wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
+static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp)
{
wavepoint_history *new_wavepoint;
@@ -624,7 +628,7 @@ wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_
}
/* Remove a wavepoint entry from WavePoint table */
-void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
+static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
{
if(wavepoint==NULL)
return;
@@ -646,7 +650,7 @@ void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp)
}
/* Timer callback function - checks WavePoint table for stale entries */
-void wl_cell_expiry(unsigned long data)
+static void wl_cell_expiry(unsigned long data)
{
net_local *lp=(net_local *)data;
wavepoint_history *wavepoint=lp->wavepoint_table.head,*old_point;
@@ -686,7 +690,7 @@ void wl_cell_expiry(unsigned long data)
}
/* Update SNR history of a wavepoint */
-void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
+static void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)
{
int i=0,num_missed=0,ptr=0;
int average_fast=0,average_slow=0;
@@ -723,7 +727,7 @@ void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsi
}
/* Perform a handover to a new WavePoint */
-void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
+static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
{
kio_addr_t base = lp->dev->base_addr;
mm_t m;
@@ -1155,10 +1159,8 @@ wv_mmc_show(struct net_device * dev)
mmc_read(base, 0, (u_char *)&m, sizeof(m));
mmc_out(base, mmwoff(0, mmw_freeze), 0);
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/* Don't forget to update statistics */
lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
spin_unlock_irqrestore(&lp->spinlock, flags);
@@ -1544,7 +1546,6 @@ wavelan_set_mac_address(struct net_device * dev,
}
#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -2787,7 +2788,6 @@ wavelan_get_wireless_stats(struct net_device * dev)
#endif
return &lp->wstats;
}
-#endif /* WIRELESS_EXT */
/************************* PACKET RECEPTION *************************/
/*
@@ -4673,11 +4673,9 @@ wavelan_attach(void)
dev->watchdog_timeo = WATCHDOG_JIFFIES;
SET_ETHTOOL_OPS(dev, &ops);
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
dev->wireless_handlers = &wavelan_handler_def;
lp->wireless_data.spy_data = &lp->spy_data;
dev->wireless_data = &lp->wireless_data;
-#endif
/* Other specific data */
dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/net/wireless/wavelan_cs.h
index 29cff6daf860..fabc63ee153c 100644
--- a/drivers/net/wireless/wavelan_cs.h
+++ b/drivers/net/wireless/wavelan_cs.h
@@ -62,7 +62,7 @@
* like DEC RoamAbout, or Digital Ocean, Epson, ...), you must modify this
* part to accommodate your hardware...
*/
-const unsigned char MAC_ADDRESSES[][3] =
+static const unsigned char MAC_ADDRESSES[][3] =
{
{ 0x08, 0x00, 0x0E }, /* AT&T Wavelan (standard) & DEC RoamAbout */
{ 0x08, 0x00, 0x6A }, /* AT&T Wavelan (alternate) */
@@ -79,14 +79,14 @@ const unsigned char MAC_ADDRESSES[][3] =
* (as read in the offset register of the dac area).
* Used to map channel numbers used by `wfreqsel' to frequencies
*/
-const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
+static const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8,
0xD0, 0xF0, 0xF8, 0x150 };
/* Frequencies of the 1.0 modem (fixed frequencies).
* Use to map the PSA `subband' to a frequency
* Note : all frequencies apart from the first one need to be multiplied by 10
*/
-const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
+static const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
/*************************** PC INTERFACE ****************************/
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 677ff71883cb..724a715089c9 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -472,11 +472,9 @@
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical) */
#undef SET_MAC_ADDRESS /* Experimental */
-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
/* Warning : these stuff will slow down the driver... */
#define WIRELESS_SPY /* Enable spying addresses */
#undef HISTOGRAM /* Enable histogram of sig level... */
-#endif
/****************************** DEBUG ******************************/
@@ -624,12 +622,10 @@ struct net_local
int rfp; /* Last DMA machine receive pointer */
int overrunning; /* Receiver overrun flag */
-#ifdef WIRELESS_EXT
iw_stats wstats; /* Wireless specific stats */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif
#ifdef HISTOGRAM
int his_number; /* Number of intervals */
@@ -647,23 +643,6 @@ struct net_local
void __iomem *mem;
};
-/**************************** PROTOTYPES ****************************/
-
-#ifdef WAVELAN_ROAMING
-/* ---------------------- ROAMING SUBROUTINES -----------------------*/
-
-wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp);
-wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local *lp);
-void wl_del_wavepoint(wavepoint_history *wavepoint, net_local *lp);
-void wl_cell_expiry(unsigned long data);
-wavepoint_history *wl_best_sigqual(int fast_search, net_local *lp);
-void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq);
-void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp);
-void wv_nwid_filter(unsigned char mode, net_local *lp);
-void wv_roam_init(struct net_device *dev);
-void wv_roam_cleanup(struct net_device *dev);
-#endif /* WAVELAN_ROAMING */
-
/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
static inline u_char /* data */
hasr_read(u_long); /* Read the host interface : base address */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 8636d9306785..4303c50c2ab6 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -2,7 +2,7 @@
#define __WL3501_H__
#include <linux/spinlock.h>
-#include "ieee802_11.h"
+#include <net/ieee80211.h>
/* define for WLA 2.0 */
#define WL3501_BLKSZ 256
@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
struct wl3501_80211_tx_hdr {
struct wl3501_80211_tx_plcp_hdr pclp_hdr;
- struct ieee802_11_hdr mac_hdr;
+ struct ieee80211_hdr_4addr mac_hdr;
} __attribute__ ((packed));
/*
@@ -609,6 +609,7 @@ struct wl3501_card {
struct net_device_stats stats;
struct iw_statistics wstats;
struct iw_spy_data spy_data;
+ struct iw_public_data wireless_data;
struct dev_node_t node;
};
#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index dd902126d018..3f8c27f0871b 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -296,7 +296,8 @@ static int wl3501_get_flash_mac_addr(struct wl3501_card *this)
*
* Move 'size' bytes from PC to card. (Shouldn't be interrupted)
*/
-void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
+static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src,
+ int size)
{
/* switch to SRAM Page 0 */
wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 :
@@ -317,8 +318,8 @@ void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, int size)
*
* Move 'size' bytes from card to PC. (Shouldn't be interrupted)
*/
-void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
- int size)
+static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest,
+ int size)
{
/* switch to SRAM Page 0 */
wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 :
@@ -1438,14 +1439,14 @@ fail:
goto out;
}
-struct net_device_stats *wl3501_get_stats(struct net_device *dev)
+static struct net_device_stats *wl3501_get_stats(struct net_device *dev)
{
struct wl3501_card *this = dev->priv;
return &this->stats;
}
-struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
{
struct wl3501_card *this = dev->priv;
struct iw_statistics *wstats = &this->wstats;
@@ -1943,7 +1944,7 @@ static const iw_handler wl3501_handler[] = {
static const struct iw_handler_def wl3501_handler_def = {
.num_standard = sizeof(wl3501_handler) / sizeof(iw_handler),
.standard = (iw_handler *)wl3501_handler,
- .spy_offset = offsetof(struct wl3501_card, spy_data),
+ .get_wireless_stats = wl3501_get_wireless_stats,
};
/**
@@ -1960,6 +1961,7 @@ static dev_link_t *wl3501_attach(void)
client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
+ struct wl3501_card *this;
int ret;
/* Initialize the dev_link_t structure */
@@ -1994,7 +1996,9 @@ static dev_link_t *wl3501_attach(void)
dev->tx_timeout = wl3501_tx_timeout;
dev->watchdog_timeo = 5 * HZ;
dev->get_stats = wl3501_get_stats;
- dev->get_wireless_stats = wl3501_get_wireless_stats;
+ this = dev->priv;
+ this->wireless_data.spy_data = &this->spy_data;
+ dev->wireless_data = &this->wireless_data;
dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def;
SET_ETHTOOL_OPS(dev, &ops);
netif_stop_queue(dev);
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index 388609967133..558420bc9f88 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -77,12 +77,12 @@ asp_init_chip(struct parisc_device *dev)
struct gsc_irq gsc_irq;
int ret;
- asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+ asp.version = gsc_readb(dev->hpa.start + ASP_VER_OFFSET) & 0xf;
asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
asp.hpa = ASP_INTERRUPT_ADDR;
printk(KERN_INFO "%s version %d at 0x%lx found.\n",
- asp.name, asp.version, dev->hpa);
+ asp.name, asp.version, dev->hpa.start);
/* the IRQ ASP should use */
ret = -EBUSY;
@@ -126,7 +126,7 @@ static struct parisc_device_id asp_tbl[] = {
};
struct parisc_driver asp_driver = {
- .name = "Asp",
+ .name = "asp",
.id_table = asp_tbl,
.probe = asp_init_chip,
};
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 0e98a9d9834c..9e0229f7e25f 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -100,9 +100,9 @@
#define DBG_RUN_SG(x...)
#endif
-#define CCIO_INLINE /* inline */
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
-#define READ_U32(addr) gsc_readl((u32 *)(addr))
+#define CCIO_INLINE inline
+#define WRITE_U32(value, addr) __raw_writel(value, addr)
+#define READ_U32(addr) __raw_readl(addr)
#define U2_IOA_RUNWAY 0x580
#define U2_BC_GSC 0x501
@@ -115,28 +115,28 @@
struct ioa_registers {
/* Runway Supervisory Set */
- volatile int32_t unused1[12];
- volatile uint32_t io_command; /* Offset 12 */
- volatile uint32_t io_status; /* Offset 13 */
- volatile uint32_t io_control; /* Offset 14 */
- volatile int32_t unused2[1];
+ int32_t unused1[12];
+ uint32_t io_command; /* Offset 12 */
+ uint32_t io_status; /* Offset 13 */
+ uint32_t io_control; /* Offset 14 */
+ int32_t unused2[1];
/* Runway Auxiliary Register Set */
- volatile uint32_t io_err_resp; /* Offset 0 */
- volatile uint32_t io_err_info; /* Offset 1 */
- volatile uint32_t io_err_req; /* Offset 2 */
- volatile uint32_t io_err_resp_hi; /* Offset 3 */
- volatile uint32_t io_tlb_entry_m; /* Offset 4 */
- volatile uint32_t io_tlb_entry_l; /* Offset 5 */
- volatile uint32_t unused3[1];
- volatile uint32_t io_pdir_base; /* Offset 7 */
- volatile uint32_t io_io_low_hv; /* Offset 8 */
- volatile uint32_t io_io_high_hv; /* Offset 9 */
- volatile uint32_t unused4[1];
- volatile uint32_t io_chain_id_mask; /* Offset 11 */
- volatile uint32_t unused5[2];
- volatile uint32_t io_io_low; /* Offset 14 */
- volatile uint32_t io_io_high; /* Offset 15 */
+ uint32_t io_err_resp; /* Offset 0 */
+ uint32_t io_err_info; /* Offset 1 */
+ uint32_t io_err_req; /* Offset 2 */
+ uint32_t io_err_resp_hi; /* Offset 3 */
+ uint32_t io_tlb_entry_m; /* Offset 4 */
+ uint32_t io_tlb_entry_l; /* Offset 5 */
+ uint32_t unused3[1];
+ uint32_t io_pdir_base; /* Offset 7 */
+ uint32_t io_io_low_hv; /* Offset 8 */
+ uint32_t io_io_high_hv; /* Offset 9 */
+ uint32_t unused4[1];
+ uint32_t io_chain_id_mask; /* Offset 11 */
+ uint32_t unused5[2];
+ uint32_t io_io_low; /* Offset 14 */
+ uint32_t io_io_high; /* Offset 15 */
};
/*
@@ -226,7 +226,7 @@ struct ioa_registers {
*/
struct ioc {
- struct ioa_registers *ioc_hpa; /* I/O MMU base address */
+ struct ioa_registers __iomem *ioc_regs; /* I/O MMU base address */
u8 *res_map; /* resource map, bit == pdir entry */
u64 *pdir_base; /* physical base address */
u32 pdir_size; /* bytes, function of IOV Space size */
@@ -595,7 +595,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
** Grab virtual index [0:11]
** Deposit virt_idx bits into I/O PDIR word
*/
- asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
@@ -613,7 +613,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
** the real mode coherence index generation of U2, the PDIR entry
** must be flushed to memory to retain coherence."
*/
- asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
asm volatile("sync");
}
@@ -636,7 +636,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt)
byte_cnt += chain_size;
while(byte_cnt > chain_size) {
- WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
+ WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_regs->io_command);
iovp += chain_size;
byte_cnt -= chain_size;
}
@@ -684,7 +684,7 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
** Hopefully someone figures out how to patch (NOP) the
** FDC/SYNC out at boot time.
*/
- asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
iovp += IOVP_SIZE;
byte_cnt -= IOVP_SIZE;
@@ -836,7 +836,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* This function implements the pci_alloc_consistent function.
*/
static void *
-ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
void *ret;
#if 0
@@ -1251,7 +1251,7 @@ static struct parisc_device_id ccio_tbl[] = {
static int ccio_probe(struct parisc_device *dev);
static struct parisc_driver ccio_driver = {
- .name = "U2:Uturn",
+ .name = "ccio",
.id_table = ccio_tbl,
.probe = ccio_probe,
};
@@ -1314,14 +1314,13 @@ ccio_ioc_init(struct ioc *ioc)
ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
- BUG_ON(ioc->pdir_size >= 4 * 1024 * 1024); /* max pdir size < 4MB */
+ BUG_ON(ioc->pdir_size > 8 * 1024 * 1024); /* max pdir size <= 8MB */
/* Verify it's a power of two */
BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
- DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
- __FUNCTION__,
- ioc->ioc_hpa,
+ DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
+ __FUNCTION__, ioc->ioc_regs,
(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
iova_space_size>>20,
iov_order + PAGE_SHIFT);
@@ -1329,13 +1328,12 @@ ccio_ioc_init(struct ioc *ioc)
ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->pdir_size));
if(NULL == ioc->pdir_base) {
- panic("%s:%s() could not allocate I/O Page Table\n", __FILE__,
- __FUNCTION__);
+ panic("%s() could not allocate I/O Page Table\n", __FUNCTION__);
}
memset(ioc->pdir_base, 0, ioc->pdir_size);
BUG_ON((((unsigned long)ioc->pdir_base) & PAGE_MASK) != (unsigned long)ioc->pdir_base);
- DBG_INIT(" base %p", ioc->pdir_base);
+ DBG_INIT(" base %p\n", ioc->pdir_base);
/* resource map size dictated by pdir_size */
ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
@@ -1344,8 +1342,7 @@ ccio_ioc_init(struct ioc *ioc)
ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->res_size));
if(NULL == ioc->res_map) {
- panic("%s:%s() could not allocate resource map\n", __FILE__,
- __FUNCTION__);
+ panic("%s() could not allocate resource map\n", __FUNCTION__);
}
memset(ioc->res_map, 0, ioc->res_size);
@@ -1366,44 +1363,58 @@ ccio_ioc_init(struct ioc *ioc)
** Initialize IOA hardware
*/
WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift,
- &ioc->ioc_hpa->io_chain_id_mask);
+ &ioc->ioc_regs->io_chain_id_mask);
WRITE_U32(virt_to_phys(ioc->pdir_base),
- &ioc->ioc_hpa->io_pdir_base);
+ &ioc->ioc_regs->io_pdir_base);
/*
** Go to "Virtual Mode"
*/
- WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control);
+ WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_regs->io_control);
/*
** Initialize all I/O TLB entries to 0 (Valid bit off).
*/
- WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m);
- WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l);
+ WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_m);
+ WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_l);
for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)),
- &ioc->ioc_hpa->io_command);
+ &ioc->ioc_regs->io_command);
}
}
static void
-ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr)
+ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
{
int result;
res->parent = NULL;
res->flags = IORESOURCE_MEM;
- res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
- res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
+ /*
+ * bracing ((signed) ...) are required for 64bit kernel because
+ * we only want to sign extend the lower 16 bits of the register.
+ * The upper 16-bits of range registers are hardcoded to 0xffff.
+ */
+ res->start = (unsigned long)((signed) READ_U32(ioaddr) << 16);
+ res->end = (unsigned long)((signed) (READ_U32(ioaddr + 4) << 16) - 1);
res->name = name;
+ /*
+ * Check if this MMIO range is disable
+ */
if (res->end + 1 == res->start)
return;
- result = request_resource(&iomem_resource, res);
+
+ /* On some platforms (e.g. K-Class), we have already registered
+ * resources for devices reported by firmware. Some are children
+ * of ccio.
+ * "insert" ccio ranges in the mmio hierarchy (/proc/iomem).
+ */
+ result = insert_resource(&iomem_resource, res);
if (result < 0) {
- printk(KERN_ERR "%s: failed to claim CCIO bus address space (%08lx,%08lx)\n",
- __FILE__, res->start, res->end);
+ printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n",
+ __FUNCTION__, res->start, res->end);
}
}
@@ -1414,9 +1425,8 @@ static void __init ccio_init_resources(struct ioc *ioc)
sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
- ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low);
- ccio_init_resource(res + 1, name,
- (unsigned long)&ioc->ioc_hpa->io_io_low_hv);
+ ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
+ ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
}
static int new_ioc_area(struct resource *res, unsigned long size,
@@ -1427,7 +1437,12 @@ static int new_ioc_area(struct resource *res, unsigned long size,
res->start = (max - size + 1) &~ (align - 1);
res->end = res->start + size;
- if (!request_resource(&iomem_resource, res))
+
+ /* We might be trying to expand the MMIO range to include
+ * a child device that has already registered it's MMIO space.
+ * Use "insert" instead of request_resource().
+ */
+ if (!insert_resource(&iomem_resource, res))
return 0;
return new_ioc_area(res, size, min, max - size, align);
@@ -1486,15 +1501,15 @@ int ccio_allocate_resource(const struct parisc_device *dev,
if (!expand_ioc_area(parent, size, min, max, align)) {
__raw_writel(((parent->start)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_low));
+ &ioc->ioc_regs->io_io_low);
__raw_writel(((parent->end)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_high));
+ &ioc->ioc_regs->io_io_high);
} else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
parent++;
__raw_writel(((parent->start)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_low_hv));
+ &ioc->ioc_regs->io_io_low_hv);
__raw_writel(((parent->end)>>16) | 0xffff0000,
- (unsigned long)&(ioc->ioc_hpa->io_io_high_hv));
+ &ioc->ioc_regs->io_io_high_hv);
} else {
return -EBUSY;
}
@@ -1521,7 +1536,12 @@ int ccio_request_resource(const struct parisc_device *dev,
return -EBUSY;
}
- return request_resource(parent, res);
+ /* "transparent" bus bridges need to register MMIO resources
+ * firmware assigned them. e.g. children of hppb.c (e.g. K-class)
+ * registered their resources in the PDC "bus walk" (See
+ * arch/parisc/kernel/inventory.c).
+ */
+ return insert_resource(parent, res);
}
/**
@@ -1546,7 +1566,7 @@ static int ccio_probe(struct parisc_device *dev)
ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
- printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
+ printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa.start);
for (i = 0; i < ioc_count; i++) {
ioc_p = &(*ioc_p)->next;
@@ -1554,7 +1574,7 @@ static int ccio_probe(struct parisc_device *dev)
*ioc_p = ioc;
ioc->hw_path = dev->hw_path;
- ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
+ ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
diff --git a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c
index 57e6385976e2..356b8357bccc 100644
--- a/drivers/parisc/ccio-rm-dma.c
+++ b/drivers/parisc/ccio-rm-dma.c
@@ -167,7 +167,7 @@ ccio_probe(struct parisc_device *dev)
{
printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
- dev->hpa);
+ dev->hpa.start);
/*
** FIXME - should check U2 registers to verify it's really running
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 2f2dbef2c3b7..5ab75334c579 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -178,6 +178,8 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
void __iomem *base_addr = d->hba.base_addr;
unsigned long flags;
+ DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+ size);
spin_lock_irqsave(&d->dinosaur_pen, flags);
/* tell HW which CFG address */
@@ -211,6 +213,8 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
void __iomem *base_addr = d->hba.base_addr;
unsigned long flags;
+ DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+ size);
spin_lock_irqsave(&d->dinosaur_pen, flags);
/* avoid address stepping feature */
@@ -295,7 +299,7 @@ static void dino_disable_irq(unsigned int irq)
struct dino_device *dino_dev = irq_desc[irq].handler_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
- DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+ DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
/* Clear the matching bit in the IMR register */
dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
@@ -308,7 +312,7 @@ static void dino_enable_irq(unsigned int irq)
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
u32 tmp;
- DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+ DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
/*
** clear pending IRQ bits
@@ -490,7 +494,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr)
if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB)))
break;
}
- DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n",
+ DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %p\n",
i, res->start, base_addr + DINO_IO_ADDR_EN);
__raw_writel(1 << i, base_addr + DINO_IO_ADDR_EN);
}
@@ -683,6 +687,14 @@ static void __init
dino_card_init(struct dino_device *dino_dev)
{
u32 brdg_feat = 0x00784e05;
+ unsigned long status;
+
+ status = __raw_readl(dino_dev->hba.base_addr+DINO_IO_STATUS);
+ if (status & 0x0000ff80) {
+ __raw_writel(0x00000005,
+ dino_dev->hba.base_addr+DINO_IO_COMMAND);
+ udelay(1);
+ }
__raw_writel(0x00000000, dino_dev->hba.base_addr+DINO_GMASK);
__raw_writel(0x00000001, dino_dev->hba.base_addr+DINO_IO_FBB_EN);
@@ -902,15 +914,15 @@ void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp);
** If so, initialize the chip appropriately (card-mode vs bridge mode).
** Much of the initialization is common though.
*/
-static int __init
-dino_driver_callback(struct parisc_device *dev)
+static int __init dino_probe(struct parisc_device *dev)
{
struct dino_device *dino_dev; // Dino specific control struct
const char *version = "unknown";
char *name;
int is_cujo = 0;
struct pci_bus *bus;
-
+ unsigned long hpa = dev->hpa.start;
+
name = "Dino";
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
@@ -928,11 +940,11 @@ dino_driver_callback(struct parisc_device *dev)
}
}
- printk("%s version %s found at 0x%lx\n", name, version, dev->hpa);
+ printk("%s version %s found at 0x%lx\n", name, version, hpa);
- if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) {
+ if (!request_mem_region(hpa, PAGE_SIZE, name)) {
printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n",
- dev->hpa);
+ hpa);
return 1;
}
@@ -940,12 +952,12 @@ dino_driver_callback(struct parisc_device *dev)
if (is_cujo && dev->id.hversion_rev == 1) {
#ifdef CONFIG_IOMMU_CCIO
printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n");
- if (dev->hpa == (unsigned long)CUJO_RAVEN_ADDR) {
+ if (hpa == (unsigned long)CUJO_RAVEN_ADDR) {
ccio_cujo20_fixup(dev, CUJO_RAVEN_BADPAGE);
- } else if (dev->hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
+ } else if (hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
ccio_cujo20_fixup(dev, CUJO_FIREHAWK_BADPAGE);
} else {
- printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", dev->hpa);
+ printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", hpa);
}
#endif
} else if (!is_cujo && !is_card_dino(&dev->id) &&
@@ -970,7 +982,7 @@ dino_driver_callback(struct parisc_device *dev)
memset(dino_dev, 0, sizeof(struct dino_device));
dino_dev->hba.dev = dev;
- dino_dev->hba.base_addr = ioremap(dev->hpa, 4096); /* faster access */
+ dino_dev->hba.base_addr = ioremap(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
spin_lock_init(&dino_dev->dinosaur_pen);
dino_dev->hba.iommu = ccio_get_iommu(dev);
@@ -1027,9 +1039,9 @@ static struct parisc_device_id dino_tbl[] = {
};
static struct parisc_driver dino_driver = {
- .name = "Dino",
+ .name = "dino",
.id_table = dino_tbl,
- .probe = dino_driver_callback,
+ .probe = dino_probe,
};
/*
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 043d47aea75b..6362bf99eff6 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -315,7 +315,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
char *name = is_mongoose(dev) ? "Mongoose" : "Wax";
printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n",
- name, dev->hpa);
+ name, dev->hpa.start);
eisa_dev.hba.dev = dev;
eisa_dev.hba.iommu = ccio_get_iommu(dev);
@@ -397,7 +397,7 @@ static struct parisc_device_id eisa_tbl[] = {
MODULE_DEVICE_TABLE(parisc, eisa_tbl);
static struct parisc_driver eisa_driver = {
- .name = "EISA Bus Adapter",
+ .name = "eisa_ba",
.id_table = eisa_tbl,
.probe = eisa_probe,
};
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index af5e02526a18..16d40f95978d 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -183,12 +183,20 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
*irqp = irq;
}
+static struct device *next_device(struct klist_iter *i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
void (*choose_irq)(struct parisc_device *, void *))
{
struct device *dev;
+ struct klist_iter i;
- list_for_each_entry(dev, &parent->dev.children, node) {
+ klist_iter_init(&parent->dev.klist_children, &i);
+ while ((dev = next_device(&i))) {
struct parisc_device *padev = to_parisc_device(dev);
/* work-around for 715/64 and others which have parent
@@ -197,6 +205,7 @@ void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
return gsc_fixup_irqs(padev, ctrl, choose_irq);
choose_irq(padev, ctrl);
}
+ klist_iter_exit(&i);
}
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index e869c6020370..5edf93f80757 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -68,14 +68,14 @@ static int hppb_probe(struct parisc_device *dev)
memset(card->next, '\0', sizeof(struct hppb_card));
card = card->next;
}
- printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa);
+ printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
- card->hpa = dev->hpa;
+ card->hpa = dev->hpa.start;
card->mmio_region.name = "HP-PB Bus";
card->mmio_region.flags = IORESOURCE_MEM;
- card->mmio_region.start = __raw_readl(dev->hpa + IO_IO_LOW);
- card->mmio_region.end = __raw_readl(dev->hpa + IO_IO_HIGH) - 1;
+ card->mmio_region.start = gsc_readl(dev->hpa.start + IO_IO_LOW);
+ card->mmio_region.end = gsc_readl(dev->hpa.start + IO_IO_HIGH) - 1;
status = ccio_request_resource(dev, &card->mmio_region);
if(status < 0) {
@@ -93,7 +93,7 @@ static struct parisc_device_id hppb_tbl[] = {
};
static struct parisc_driver hppb_driver = {
- .name = "Gecko Boa",
+ .name = "gecko_boa",
.id_table = hppb_tbl,
.probe = hppb_probe,
};
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 91df0bf181dd..a39fbfef789a 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -215,7 +215,7 @@ static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 va
#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
-static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(iosapic_lock);
static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
{
@@ -244,7 +244,7 @@ static struct irt_entry *iosapic_alloc_irt(int num_entries)
* 4-byte alignment on 32-bit kernels
*/
a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
- a = (a + 7) & ~7;
+ a = (a + 7UL) & ~7UL;
return (struct irt_entry *)a;
}
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 731855053392..a8c20396ffbe 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm.h>
-#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
@@ -176,7 +175,7 @@ lasi_init_chip(struct parisc_device *dev)
return -ENOMEM;
lasi->name = "Lasi";
- lasi->hpa = dev->hpa;
+ lasi->hpa = dev->hpa.start;
/* Check the 4-bit (yes, only 4) version register */
lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf;
@@ -234,7 +233,7 @@ static struct parisc_device_id lasi_tbl[] = {
};
struct parisc_driver lasi_driver = {
- .name = "Lasi",
+ .name = "lasi",
.id_table = lasi_tbl,
.probe = lasi_init_chip,
};
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 7fdd80b7eb47..5e495dcbc58a 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1288,7 +1288,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** Adjust "window" for this rope.
*/
rsize /= ROPES_PER_IOC;
- r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa);
+ r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa.start);
r->end = r->start + rsize;
} else {
r->end = r->start = 0; /* Not enabled. */
@@ -1458,7 +1458,7 @@ lba_driver_probe(struct parisc_device *dev)
u32 func_class;
void *tmp_obj;
char *version;
- void __iomem *addr = ioremap(dev->hpa, 4096);
+ void __iomem *addr = ioremap(dev->hpa.start, 4096);
/* Read HW Rev First */
func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1476,7 +1476,7 @@ lba_driver_probe(struct parisc_device *dev)
}
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
- MODULE_NAME, version, func_class & 0xf, dev->hpa);
+ MODULE_NAME, version, func_class & 0xf, dev->hpa.start);
if (func_class < 2) {
printk(KERN_WARNING "Can't support LBA older than "
@@ -1503,17 +1503,17 @@ lba_driver_probe(struct parisc_device *dev)
* but for the mask for func_class.
*/
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
- MODULE_NAME, version, func_class & 0xff, dev->hpa);
+ MODULE_NAME, version, func_class & 0xff, dev->hpa.start);
cfg_ops = &mercury_cfg_ops;
} else {
- printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa);
+ printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start);
return -ENODEV;
}
/*
** Tell I/O SAPIC driver we have a IRQ handler/region.
*/
- tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE);
+ tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE);
/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
** have an IRT entry will get NULL back from iosapic code.
@@ -1635,7 +1635,7 @@ void __init lba_init(void)
*/
void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
{
- void __iomem * base_addr = ioremap(lba->hpa, 4096);
+ void __iomem * base_addr = ioremap(lba->hpa.start, 4096);
imask <<= 2; /* adjust for hints - 2 more bits */
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index e90fb72a6962..95bd07b8b61b 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -18,6 +18,9 @@
* Changes:
* - Audit copy_from_user in led_proc_write.
* Daniele Bellucci <bellucda@tiscali.it>
+ * - Switch from using a tasklet to a work queue, so the led_LCD_driver
+ * can sleep.
+ * David Pye <dmp@davidmpye.dyndns.org>
*/
#include <linux/config.h>
@@ -37,6 +40,8 @@
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/blkdev.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/hardware.h>
@@ -46,25 +51,30 @@
#include <asm/uaccess.h>
/* The control of the LEDs and LCDs on PARISC-machines have to be done
- completely in software. The necessary calculations are done in a tasklet
- which is scheduled at every timer interrupt and since the calculations
- may consume relatively much CPU-time some of the calculations can be
+ completely in software. The necessary calculations are done in a work queue
+ task which is scheduled regularly, and since the calculations may consume a
+ relatively large amount of CPU time, some of the calculations can be
turned off with the following variables (controlled via procfs) */
static int led_type = -1;
-static int led_heartbeat = 1;
-static int led_diskio = 1;
-static int led_lanrxtx = 1;
+static unsigned char lastleds; /* LED state from most recent update */
+static unsigned int led_heartbeat = 1;
+static unsigned int led_diskio = 1;
+static unsigned int led_lanrxtx = 1;
static char lcd_text[32];
static char lcd_text_default[32];
+
+static struct workqueue_struct *led_wq;
+static void led_work_func(void *);
+static DECLARE_WORK(led_task, led_work_func, NULL);
+
#if 0
#define DPRINTK(x) printk x
#else
#define DPRINTK(x)
#endif
-
struct lcd_block {
unsigned char command; /* stores the command byte */
unsigned char on; /* value for turning LED on */
@@ -115,12 +125,27 @@ lcd_info __attribute__((aligned(8))) =
#define LCD_DATA_REG lcd_info.lcd_data_reg_addr
#define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */
+#define LED_HASLCD 1
+#define LED_NOLCD 0
+
+/* The workqueue must be created at init-time */
+static int start_task(void)
+{
+ /* Display the default text now */
+ if (led_type == LED_HASLCD) lcd_print( lcd_text_default );
+
+ /* Create the work queue and queue the LED task */
+ led_wq = create_singlethread_workqueue("led_wq");
+ queue_work(led_wq, &led_task);
+
+ return 0;
+}
+
+device_initcall(start_task);
/* ptr to LCD/LED-specific function */
static void (*led_func_ptr) (unsigned char);
-#define LED_HASLCD 1
-#define LED_NOLCD 0
#ifdef CONFIG_PROC_FS
static int led_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
@@ -285,52 +310,35 @@ static void led_LASI_driver(unsigned char leds)
/*
**
** led_LCD_driver()
- **
- ** The logic of the LCD driver is, that we write at every scheduled call
- ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
- ** That way we don't need to let this tasklet busywait for min_cmd_delay
- ** milliseconds.
- **
- ** TODO: check the value of "min_cmd_delay" against the value of HZ.
**
*/
static void led_LCD_driver(unsigned char leds)
{
- static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
- static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
- struct lcd_block *block_ptr;
- int value;
-
- switch (last_index) {
- case 0: block_ptr = &lcd_info.heartbeat;
- value = leds & LED_HEARTBEAT;
- break;
- case 1: block_ptr = &lcd_info.disk_io;
- value = leds & LED_DISK_IO;
- break;
- case 2: block_ptr = &lcd_info.lan_rcv;
- value = leds & LED_LAN_RCV;
- break;
- case 3: block_ptr = &lcd_info.lan_tx;
- value = leds & LED_LAN_TX;
- break;
- default: /* should never happen: */
- return;
- }
-
- if (last_was_cmd) {
- /* write the value to the LCD data port */
- gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG );
- } else {
- /* write the command-byte to the LCD command register */
- gsc_writeb( block_ptr->command, LCD_CMD_REG );
- }
+ static int i;
+ static unsigned char mask[4] = { LED_HEARTBEAT, LED_DISK_IO,
+ LED_LAN_RCV, LED_LAN_TX };
- /* now update the vars for the next interrupt iteration */
- if (++last_was_cmd == 2) { /* switch between cmd & data */
- last_was_cmd = 0;
- if (++last_index == 4)
- last_index = 0; /* switch back to heartbeat index */
+ static struct lcd_block * blockp[4] = {
+ &lcd_info.heartbeat,
+ &lcd_info.disk_io,
+ &lcd_info.lan_rcv,
+ &lcd_info.lan_tx
+ };
+
+ /* Convert min_cmd_delay to milliseconds */
+ unsigned int msec_cmd_delay = 1 + (lcd_info.min_cmd_delay / 1000);
+
+ for (i=0; i<4; ++i)
+ {
+ if ((leds & mask[i]) != (lastleds & mask[i]))
+ {
+ gsc_writeb( blockp[i]->command, LCD_CMD_REG );
+ msleep(msec_cmd_delay);
+
+ gsc_writeb( leds & mask[i] ? blockp[i]->on :
+ blockp[i]->off, LCD_DATA_REG );
+ msleep(msec_cmd_delay);
+ }
}
}
@@ -355,12 +363,13 @@ static __inline__ int led_get_net_activity(void)
rx_total = tx_total = 0;
- /* we are running as tasklet, so locking dev_base
+ /* we are running as a workqueue task, so locking dev_base
* for reading should be OK */
read_lock(&dev_base_lock);
+ rcu_read_lock();
for (dev = dev_base; dev; dev = dev->next) {
struct net_device_stats *stats;
- struct in_device *in_dev = __in_dev_get(dev);
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
if (!in_dev || !in_dev->ifa_list)
continue;
if (LOOPBACK(in_dev->ifa_list->ifa_local))
@@ -371,6 +380,7 @@ static __inline__ int led_get_net_activity(void)
rx_total += stats->rx_packets;
tx_total += stats->tx_packets;
}
+ rcu_read_unlock();
read_unlock(&dev_base_lock);
retval = 0;
@@ -402,7 +412,7 @@ static __inline__ int led_get_diskio_activity(void)
static unsigned long last_pgpgin, last_pgpgout;
struct page_state pgstat;
int changed;
-
+
get_full_page_state(&pgstat); /* get no of sectors in & out */
/* Just use a very simple calculation here. Do not care about overflow,
@@ -410,86 +420,70 @@ static __inline__ int led_get_diskio_activity(void)
changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
last_pgpgin = pgstat.pgpgin;
last_pgpgout = pgstat.pgpgout;
-
+
return (changed ? LED_DISK_IO : 0);
}
/*
- ** led_tasklet_func()
+ ** led_work_func()
**
- ** is scheduled at every timer interrupt from time.c and
- ** updates the chassis LCD/LED
+ ** manages when and which chassis LCD/LED gets updated
TODO:
- display load average (older machines like 715/64 have 4 "free" LED's for that)
- optimizations
*/
-#define HEARTBEAT_LEN (HZ*6/100)
-#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
+#define HEARTBEAT_LEN (HZ*10/100)
+#define HEARTBEAT_2ND_RANGE_START (HZ*28/100)
#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
-#define NORMALIZED_COUNT(count) (count/(HZ/100))
+#define LED_UPDATE_INTERVAL (1 + (HZ*19/1000))
-static void led_tasklet_func(unsigned long unused)
+static void led_work_func (void *unused)
{
- static unsigned char lastleds;
- unsigned char currentleds; /* stores current value of the LEDs */
- static unsigned long count; /* static incremented value, not wrapped */
+ static unsigned long last_jiffies;
static unsigned long count_HZ; /* counter in range 0..HZ */
+ unsigned char currentleds = 0; /* stores current value of the LEDs */
/* exit if not initialized */
if (!led_func_ptr)
return;
- /* increment the local counters */
- ++count;
- if (++count_HZ == HZ)
+ /* increment the heartbeat timekeeper */
+ count_HZ += jiffies - last_jiffies;
+ last_jiffies = jiffies;
+ if (count_HZ >= HZ)
count_HZ = 0;
- currentleds = lastleds;
-
- if (led_heartbeat)
- {
- /* flash heartbeat-LED like a real heart (2 x short then a long delay) */
- if (count_HZ<HEARTBEAT_LEN ||
- (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END))
- currentleds |= LED_HEARTBEAT;
- else
- currentleds &= ~LED_HEARTBEAT;
- }
-
- /* look for network activity and flash LEDs respectively */
- if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
+ if (likely(led_heartbeat))
{
- currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
- currentleds |= led_get_net_activity();
+ /* flash heartbeat-LED like a real heart
+ * (2 x short then a long delay)
+ */
+ if (count_HZ < HEARTBEAT_LEN ||
+ (count_HZ >= HEARTBEAT_2ND_RANGE_START &&
+ count_HZ < HEARTBEAT_2ND_RANGE_END))
+ currentleds |= LED_HEARTBEAT;
}
- /* avoid to calculate diskio-stats at same irq as netio-stats */
- if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
- {
- currentleds &= ~LED_DISK_IO;
- currentleds |= led_get_diskio_activity();
- }
+ if (likely(led_lanrxtx)) currentleds |= led_get_net_activity();
+ if (likely(led_diskio)) currentleds |= led_get_diskio_activity();
/* blink all LEDs twice a second if we got an Oops (HPMC) */
- if (oops_in_progress) {
+ if (unlikely(oops_in_progress))
currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
- }
-
- /* update the LCD/LEDs */
- if (currentleds != lastleds) {
- led_func_ptr(currentleds);
- lastleds = currentleds;
- }
-}
-/* main led tasklet struct (scheduled from time.c) */
-DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);
+ if (currentleds != lastleds)
+ {
+ led_func_ptr(currentleds); /* Update the LCD/LEDs */
+ lastleds = currentleds;
+ }
+ queue_delayed_work(led_wq, &led_task, LED_UPDATE_INTERVAL);
+}
/*
** led_halt()
@@ -519,9 +513,13 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
default: return NOTIFY_DONE;
}
- /* completely stop the LED/LCD tasklet */
- tasklet_disable(&led_tasklet);
-
+ /* Cancel the work item and delete the queue */
+ if (led_wq) {
+ cancel_rearming_delayed_workqueue(led_wq, &led_task);
+ destroy_workqueue(led_wq);
+ led_wq = NULL;
+ }
+
if (lcd_info.model == DISPLAY_MODEL_LCD)
lcd_print(txt);
else
@@ -556,7 +554,6 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d
printk(KERN_INFO "LCD display at %lx,%lx registered\n",
LCD_CMD_REG , LCD_DATA_REG);
led_func_ptr = led_LCD_driver;
- lcd_print( lcd_text_default );
led_type = LED_HASLCD;
break;
@@ -586,9 +583,11 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d
initialized++;
register_reboot_notifier(&led_notifier);
- /* start the led tasklet for the first time */
- tasklet_enable(&led_tasklet);
-
+ /* Ensure the work is queued */
+ if (led_wq) {
+ queue_work(led_wq, &led_task);
+ }
+
return 0;
}
@@ -623,8 +622,8 @@ void __init register_led_regions(void)
** lcd_print()
**
** Displays the given string on the LCD-Display of newer machines.
- ** lcd_print() disables the timer-based led tasklet during its
- ** execution and enables it afterwards again.
+ ** lcd_print() disables/enables the timer-based led work queue to
+ ** avoid a race condition while writing the CMD/DATA register pair.
**
*/
int lcd_print( char *str )
@@ -634,12 +633,13 @@ int lcd_print( char *str )
if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)
return 0;
- /* temporarily disable the led tasklet */
- tasklet_disable(&led_tasklet);
+ /* temporarily disable the led work task */
+ if (led_wq)
+ cancel_rearming_delayed_workqueue(led_wq, &led_task);
/* copy display string to buffer for procfs */
strlcpy(lcd_text, str, sizeof(lcd_text));
-
+
/* Set LCD Cursor to 1st character */
gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
udelay(lcd_info.min_cmd_delay);
@@ -653,8 +653,10 @@ int lcd_print( char *str )
udelay(lcd_info.min_cmd_delay);
}
- /* re-enable the led tasklet */
- tasklet_enable(&led_tasklet);
+ /* re-queue the work */
+ if (led_wq) {
+ queue_work(led_wq, &led_task);
+ }
return lcd_info.lcd_width;
}
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 67c8f3b44848..273a74179720 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -536,7 +536,7 @@ pdcs_info_read(struct subsystem *entry, char *buf)
out += sprintf(out, "Memory tested: ");
if ((result & 0x0F) < 0x0E)
- out += sprintf(out, "%.3f MB", 0.256*(1<<(result & 0x0F)));
+ out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
else
out += sprintf(out, "All");
out += sprintf(out, "\n");
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 82ea68b55df4..c85653f315aa 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -91,8 +91,8 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define DBG_RES(x...)
#endif
-#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
-/* "low end" PA8800 machines use ZX1 chipset */
+#if defined(CONFIG_64BIT)
+/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
#define ZX1_SUPPORT
#endif
@@ -231,7 +231,7 @@ struct ioc {
spinlock_t res_lock;
unsigned int res_bitshift; /* from the LEFT! */
unsigned int res_size; /* size of resource map in bytes */
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
/* FIXME : DMA HINTs not used */
unsigned long hint_mask_pdir; /* bits used for DMA hints */
unsigned int hint_shift_pdir;
@@ -294,7 +294,7 @@ static unsigned long piranha_bad_128k = 0;
/* Looks nice and keeps the compiler happy */
#define SBA_DEV(d) ((struct sba_device *) (d))
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
static int reserve_sba_gart = 1;
#endif
@@ -314,7 +314,7 @@ static int reserve_sba_gart = 1;
#define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
#define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
#define READ_REG(addr) READ_REG64(addr)
#define WRITE_REG(value, addr) WRITE_REG64(value, addr)
#else
@@ -324,7 +324,7 @@ static int reserve_sba_gart = 1;
#ifdef DEBUG_SBA_INIT
-/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+/* NOTE: When CONFIG_64BIT isn't defined, READ_REG64() is two 32-bit reads */
/**
* sba_dump_ranges - debugging only - print ranges assigned to this IOA
@@ -364,7 +364,7 @@ static void sba_dump_tlb(void __iomem *hpa)
#else
#define sba_dump_ranges(x)
#define sba_dump_tlb(x)
-#endif
+#endif /* DEBUG_SBA_INIT */
#ifdef ASSERT_PDIR_SANITY
@@ -674,7 +674,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
*
***************************************************************/
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
#endif
@@ -743,9 +743,8 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
* (bit #61, big endian), we have to flush and sync every time
* IO-PDIR is changed in Ike/Astro.
*/
- if (ioc_needs_fdc) {
- asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr));
- }
+ if (ioc_needs_fdc)
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
}
@@ -769,42 +768,57 @@ static SBA_INLINE void
sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
{
u32 iovp = (u32) SBA_IOVP(ioc,iova);
-
- /* Even though this is a big-endian machine, the entries
- ** in the iopdir are little endian. That's why we clear the byte
- ** at +7 instead of at +0.
- */
- int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
+ u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
#ifdef ASSERT_PDIR_SANITY
- /* Assert first pdir entry is set */
- if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
+ /* Assert first pdir entry is set.
+ **
+ ** Even though this is a big-endian machine, the entries
+ ** in the iopdir are little endian. That's why we look at
+ ** the byte at +7 instead of at +0.
+ */
+ if (0x80 != (((u8 *) pdir_ptr)[7])) {
sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
}
#endif
- if (byte_cnt <= IOVP_SIZE)
+ if (byte_cnt > IOVP_SIZE)
{
- iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+#if 0
+ unsigned long entries_per_cacheline = ioc_needs_fdc ?
+ L1_CACHE_ALIGN(((unsigned long) pdir_ptr))
+ - (unsigned long) pdir_ptr;
+ : 262144;
+#endif
- /*
- ** clear I/O PDIR entry "valid" bit
- ** Do NOT clear the rest - save it for debugging.
- ** We should only clear bits that have previously
- ** been enabled.
- */
- ((u8 *)(ioc->pdir_base))[off] = 0;
- } else {
- u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+ /* set "size" field for PCOM */
+ iovp |= get_order(byte_cnt) + PAGE_SHIFT;
- iovp |= t;
do {
/* clear I/O Pdir entry "valid" bit first */
- ((u8 *)(ioc->pdir_base))[off] = 0;
- off += sizeof(u64);
+ ((u8 *) pdir_ptr)[7] = 0;
+ if (ioc_needs_fdc) {
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
+#if 0
+ entries_per_cacheline = L1_CACHE_SHIFT - 3;
+#endif
+ }
+ pdir_ptr++;
byte_cnt -= IOVP_SIZE;
- } while (byte_cnt > 0);
- }
+ } while (byte_cnt > IOVP_SIZE);
+ } else
+ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+
+ /*
+ ** clear I/O PDIR entry "valid" bit.
+ ** We have to R/M/W the cacheline regardless how much of the
+ ** pdir entry that we clobber.
+ ** The rest of the entry would be useful for debugging if we
+ ** could dump core on HPMC.
+ */
+ ((u8 *) pdir_ptr)[7] = 0;
+ if (ioc_needs_fdc)
+ asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
WRITE_REG( SBA_IOVA(ioc, iovp, 0, 0), ioc->ioc_hpa+IOC_PCOM);
}
@@ -819,18 +833,29 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
static int sba_dma_supported( struct device *dev, u64 mask)
{
struct ioc *ioc;
+
if (dev == NULL) {
printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
BUG();
return(0);
}
- ioc = GET_IOC(dev);
+ /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first,
+ * then fall back to 32-bit if that fails.
+ * We are just "encouraging" 32-bit DMA masks here since we can
+ * never allow IOMMU bypass unless we add special support for ZX1.
+ */
+ if (mask > ~0U)
+ return 0;
- /* check if mask is > than the largest IO Virt Address */
+ ioc = GET_IOC(dev);
- return((int) (mask >= (ioc->ibase +
- (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
+ /*
+ * check if mask is >= than the current max IO Virt Address
+ * The max IO Virt address will *always* < 30 bits.
+ */
+ return((int)(mask >= (ioc->ibase - 1 +
+ (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
}
@@ -898,11 +923,17 @@ sba_map_single(struct device *dev, void *addr, size_t size,
size -= IOVP_SIZE;
pdir_start++;
}
- /* form complete address */
+
+ /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
#ifdef ASSERT_PDIR_SANITY
sba_check_pdir(ioc,"Check after sba_map_single()");
#endif
spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+ /* form complete address */
return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
}
@@ -958,12 +989,19 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
d--;
}
ioc->saved_cnt = 0;
+
READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
}
#else /* DELAYED_RESOURCE_CNT == 0 */
sba_free_range(ioc, iova, size);
+
+ /* If fdc's were issued, force fdc's to be visible now */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */
#endif /* DELAYED_RESOURCE_CNT == 0 */
+
spin_unlock_irqrestore(&ioc->res_lock, flags);
/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
@@ -986,7 +1024,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* See Documentation/DMA-mapping.txt
*/
static void *sba_alloc_consistent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, int gfp)
+ dma_addr_t *dma_handle, gfp_t gfp)
{
void *ret;
@@ -1106,6 +1144,10 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
*/
filled = iommu_fill_pdir(ioc, sglist, nents, 0, sba_io_pdir_entry);
+ /* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+ if (ioc_needs_fdc)
+ asm volatile("sync" : : );
+
#ifdef ASSERT_PDIR_SANITY
if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
{
@@ -1234,8 +1276,10 @@ sba_alloc_pdir(unsigned int pdir_size)
unsigned long pdir_order = get_order(pdir_size);
pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
- if (NULL == (void *) pdir_base)
- panic("sba_ioc_init() could not allocate I/O Page Table\n");
+ if (NULL == (void *) pdir_base) {
+ panic("%s() could not allocate I/O Page Table\n",
+ __FUNCTION__);
+ }
/* If this is not PA8700 (PCX-W2)
** OR newer than ver 2.2
@@ -1322,19 +1366,29 @@ sba_alloc_pdir(unsigned int pdir_size)
return (void *) pdir_base;
}
+static struct device *next_device(struct klist_iter *i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
/* setup Mercury or Elroy IBASE/IMASK registers. */
-static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+static void
+setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
{
- /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
+ /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
extern void lba_set_iregs(struct parisc_device *, u32, u32);
struct device *dev;
+ struct klist_iter i;
- list_for_each_entry(dev, &sba->dev.children, node) {
+ klist_iter_init(&sba->dev.klist_children, &i);
+ while ((dev = next_device(&i))) {
struct parisc_device *lba = to_parisc_device(dev);
- int rope_num = (lba->hpa >> 13) & 0xf;
+ int rope_num = (lba->hpa.start >> 13) & 0xf;
if (rope_num >> 3 == ioc_num)
lba_set_iregs(lba, ioc->ibase, ioc->imask);
}
+ klist_iter_exit(&i);
}
static void
@@ -1343,7 +1397,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
u32 iova_space_mask;
u32 iova_space_size;
int iov_order, tcnfg;
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
int agp_found = 0;
#endif
/*
@@ -1380,7 +1434,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
DBG_INIT("%s() pdir %p size %x\n",
__FUNCTION__, ioc->pdir_base, ioc->pdir_size);
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
@@ -1404,7 +1458,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
/*
** Setting the upper bits makes checking for bypass addresses
** a little faster later on.
@@ -1437,7 +1491,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
*/
WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
/*
** If an AGP device is present, only use half of the IOV space
** for PCI DMA. Unfortunately we can't know ahead of time
@@ -1489,11 +1543,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
iova_space_size = 1 << (20 - PAGE_SHIFT);
}
-#ifdef __LP64__
else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
iova_space_size = 1 << (30 - PAGE_SHIFT);
}
-#endif
/*
** iova space must be log2() in size.
@@ -1519,7 +1571,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
DBG_INIT("%s() pdir %p size %x\n",
__FUNCTION__, ioc->pdir_base, pdir_size);
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
/* FIXME : DMA HINTs not used */
ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
@@ -1590,7 +1642,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
{
- return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
+ return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
}
static void sba_hw_init(struct sba_device *sba_dev)
@@ -1968,7 +2020,7 @@ sba_driver_callback(struct parisc_device *dev)
u32 func_class;
int i;
char *version;
- void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
+ void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
sba_dump_ranges(sba_addr);
@@ -2010,7 +2062,7 @@ sba_driver_callback(struct parisc_device *dev)
}
printk(KERN_INFO "%s found %s at 0x%lx\n",
- MODULE_NAME, version, dev->hpa);
+ MODULE_NAME, version, dev->hpa.start);
sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
if (!sba_dev) {
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index e0efed796b92..bab3bcabcb6e 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -11,6 +11,7 @@
* (C) Copyright 2000 Alex deVries <alex@onefishtwo.ca>
* (C) Copyright 2001 John Marvin <jsm fc hp com>
* (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
+ * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -405,6 +406,7 @@ static void __devinit superio_serial_init(void)
serial[0].iobase = sio_dev.sp1_base;
serial[0].irq = SP1_IRQ;
+ spin_lock_init(&serial[0].lock);
retval = early_serial_setup(&serial[0]);
if (retval < 0) {
@@ -414,6 +416,7 @@ static void __devinit superio_serial_init(void)
serial[1].iobase = sio_dev.sp2_base;
serial[1].irq = SP2_IRQ;
+ spin_lock_init(&serial[1].lock);
retval = early_serial_setup(&serial[1]);
if (retval < 0)
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index e547d7d024d8..17dce2adf7fe 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -81,7 +81,7 @@ wax_init_chip(struct parisc_device *dev)
return -ENOMEM;
wax->name = "wax";
- wax->hpa = dev->hpa;
+ wax->hpa = dev->hpa.start;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 16a2e6ae37f4..725a14119f2a 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -34,7 +34,7 @@ config PARPORT
config PARPORT_PC
tristate "PC-style hardware"
- depends on PARPORT && (!SPARC64 || PCI) && !SPARC32
+ depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index 694bae162fed..5b887ba5aaf9 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -196,7 +196,7 @@ int parport_wait_peripheral(struct parport *port,
return 1;
/* 40ms of slow polling. */
- deadline = jiffies + (HZ + 24) / 25;
+ deadline = jiffies + msecs_to_jiffies(40);
while (time_before (jiffies, deadline)) {
int ret;
@@ -205,7 +205,7 @@ int parport_wait_peripheral(struct parport *port,
/* Wait for 10ms (or until an interrupt occurs if
* the handler is set) */
- if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)
+ if ((ret = parport_wait_event (port, msecs_to_jiffies(10))) < 0)
return ret;
status = parport_read_status (port);
@@ -216,8 +216,7 @@ int parport_wait_peripheral(struct parport *port,
/* parport_wait_event didn't time out, but the
* peripheral wasn't actually ready either.
* Wait for another 10ms. */
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ+ 99) / 100);
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
}
}
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index 6624278c6ed8..ce1e2aad8b10 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -60,7 +60,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
parport_data_forward (port);
while (count < len) {
unsigned long expire = jiffies + dev->timeout;
- long wait = (HZ + 99) / 100;
+ long wait = msecs_to_jiffies(10);
unsigned char mask = (PARPORT_STATUS_ERROR
| PARPORT_STATUS_BUSY);
unsigned char val = (PARPORT_STATUS_ERROR
@@ -97,8 +97,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
our interrupt handler called. */
if (count && no_irq) {
parport_release (dev);
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout (wait);
+ schedule_timeout_interruptible(wait);
parport_claim_or_block (dev);
}
else
@@ -542,13 +541,12 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
/* Yield the port for a while. */
if (count && dev->port->irq != PARPORT_IRQ_NONE) {
parport_release (dev);
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ + 24) / 25);
+ schedule_timeout_interruptible(msecs_to_jiffies(40));
parport_claim_or_block (dev);
}
else
/* We must have the device claimed here. */
- parport_wait_event (port, (HZ + 24) / 25);
+ parport_wait_event (port, msecs_to_jiffies(40));
/* Is there a signal pending? */
if (signal_pending (current))
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 02d72acd1c89..fde29a75f888 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -359,11 +359,12 @@ static int __devinit parport_init_chip(struct parisc_device *dev)
unsigned long port;
if (!dev->irq) {
- printk("IRQ not found for parallel device at 0x%lx\n", dev->hpa);
+ printk(KERN_WARNING "IRQ not found for parallel device at 0x%lx\n",
+ dev->hpa.start);
return -ENODEV;
}
- port = dev->hpa + PARPORT_GSC_OFFSET;
+ port = dev->hpa.start + PARPORT_GSC_OFFSET;
/* some older machines with ASP-chip don't support
* the enhanced parport modes.
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 4598c6a9212d..c6493ad7c0c8 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -173,8 +173,7 @@ static int change_mode(struct parport *p, int m)
if (time_after_eq (jiffies, expire))
/* The FIFO is stuck. */
return -EBUSY;
- __set_current_state (TASK_INTERRUPTIBLE);
- schedule_timeout ((HZ + 99) / 100);
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
if (signal_pending (current))
break;
}
@@ -2739,6 +2738,7 @@ enum parport_pc_pci_cards {
syba_2p_epp,
syba_1p_ecp,
titan_010l,
+ titan_1284p1,
titan_1284p2,
avlab_1p,
avlab_2p,
@@ -2811,6 +2811,7 @@ static struct parport_pc_pci {
/* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } },
/* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } },
/* titan_010l */ { 1, { { 3, -1 }, } },
+ /* titan_1284p1 */ { 1, { { 0, 1 }, } },
/* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } },
/* avlab_1p */ { 1, { { 0, 1}, } },
/* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} },
@@ -2884,6 +2885,7 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+ { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 },
{ 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */
@@ -3007,7 +3009,7 @@ static int __init parport_pc_init_superio (int autoirq, int autodma)
struct pci_dev *pdev = NULL;
int ret = 0;
- while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+ for_each_pci_dev(pdev) {
id = pci_match_id(parport_pc_pci_tbl, pdev);
if (id == NULL || id->driver_data >= last_sio)
continue;
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 00498e2f1205..d3dad0aac7cb 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -23,13 +23,8 @@
#include <linux/pci.h>
#include <linux/parport.h>
#include <linux/parport_pc.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/list.h>
#include <linux/8250_pci.h>
-#include <asm/serial.h>
-
enum parport_pc_pci_cards {
titan_110l = 0,
titan_210l,
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
-struct pci_board_no_ids {
- int flags;
- int num_ports;
- int base_baud;
- int uart_offset;
- int reg_shift;
- int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
- int enable);
- int first_uart_offset;
-};
-
-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- return pci_siig10x_fn(dev, enable);
-}
-
-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- return pci_siig20x_fn(dev, enable);
-}
-
-static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
- board->num_ports = dev->subsystem_device & 0xf;
- return 0;
-}
-
-static struct pci_board_no_ids pci_boards[] __devinitdata = {
- /*
- * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
- * Offset to get to next UART's registers,
- * Register shift to use for memory-mapped I/O,
- * Initialization function, first UART offset
- */
-
-// Cards not tested are marked n/t
-// If you have one of these cards and it works for you, please tell me..
-
-/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
-/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
-/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* siig_1s1p_10x */ { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
-/* siig_2s1p_10x */ { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
-/* siig_2p1s_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_1s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_2s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/*
+ * This table describes the serial "geometry" of these boards. Any
+ * quirks for these can be found in drivers/serial/8250_pci.c
+ *
+ * Cards not tested are marked n/t
+ * If you have one of these cards and it works for you, please tell me..
+ */
+static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
+ [titan_110l] = {
+ .flags = FL_BASE1 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [titan_210l] = {
+ .flags = FL_BASE1 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [netmos_9xx5_combo] = {
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [netmos_9855] = {
+ .flags = FL_BASE2 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s1p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_1s2p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 1,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p] = { /* n/t */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p_650] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [avlab_2s1p_850] = { /* nt */
+ .flags = FL_BASE0 | FL_BASE_BARS,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+ [siig_1s1p_10x] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 460800,
+ .uart_offset = 8,
+ },
+ [siig_2s1p_10x] = {
+ .flags = FL_BASE2,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_2p1s_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_1s1p_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [siig_2s1p_20x] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
};
struct parport_serial_private {
- int num_ser;
- int line[20];
- struct pci_board_no_ids ser;
+ struct serial_private *serial;
int num_par;
struct parport *port[PARPORT_MAX];
struct parport_pc_pci par;
};
-static int __devinit get_pci_port (struct pci_dev *dev,
- struct pci_board_no_ids *board,
- struct serial_struct *req,
- int idx)
-{
- unsigned long port;
- int base_idx;
- int max_port;
- int offset;
-
- base_idx = SPCI_FL_GET_BASE(board->flags);
- if (board->flags & SPCI_FL_BASE_TABLE)
- base_idx += idx;
-
- if (board->flags & SPCI_FL_REGION_SZ_CAP) {
- max_port = pci_resource_len(dev, base_idx) / 8;
- if (idx >= max_port)
- return 1;
- }
-
- offset = board->first_uart_offset;
-
- /* Timedia/SUNIX uses a mixture of BARs and offsets */
- /* Ugh, this is ugly as all hell --- TYT */
- if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
- switch(idx) {
- case 0: base_idx=0;
- break;
- case 1: base_idx=0; offset=8;
- break;
- case 2: base_idx=1;
- break;
- case 3: base_idx=1; offset=8;
- break;
- case 4: /* BAR 2*/
- case 5: /* BAR 3 */
- case 6: /* BAR 4*/
- case 7: base_idx=idx-2; /* BAR 5*/
- }
-
- port = pci_resource_start(dev, base_idx) + offset;
-
- if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
- port += idx * (board->uart_offset ? board->uart_offset : 8);
-
- if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
- int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
- req->port = port;
- if (high_bits_offset)
- req->port_high = port >> high_bits_offset;
- else
- req->port_high = 0;
- return 0;
- }
- req->io_type = SERIAL_IO_MEM;
- req->iomem_base = ioremap(port, board->uart_offset);
- req->iomem_reg_shift = board->reg_shift;
- req->port = 0;
- return req->iomem_base ? 0 : 1;
-}
-
/* Register the serial port(s) of a PCI card. */
static int __devinit serial_register (struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct pci_board_no_ids *board;
struct parport_serial_private *priv = pci_get_drvdata (dev);
- struct serial_struct serial_req;
- int base_baud;
- int k;
- int success = 0;
-
- priv->ser = pci_boards[id->driver_data];
- board = &priv->ser;
- if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
- return 1;
-
- base_baud = board->base_baud;
- if (!base_baud)
- base_baud = BASE_BAUD;
- memset (&serial_req, 0, sizeof (serial_req));
-
- for (k = 0; k < board->num_ports; k++) {
- int line;
+ struct pciserial_board *board;
+ struct serial_private *serial;
- if (priv->num_ser == ARRAY_SIZE (priv->line)) {
- printk (KERN_WARNING
- "parport_serial: %s: only %u serial lines "
- "supported (%d reported)\n", pci_name (dev),
- ARRAY_SIZE (priv->line), board->num_ports);
- break;
- }
+ board = &pci_parport_serial_boards[id->driver_data];
+ serial = pciserial_init_ports(dev, board);
- serial_req.irq = dev->irq;
- if (get_pci_port (dev, board, &serial_req, k))
- break;
- serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
- serial_req.baud_base = base_baud;
- line = register_serial (&serial_req);
- if (line < 0) {
- printk (KERN_DEBUG
- "parport_serial: register_serial failed\n");
- continue;
- }
- priv->line[priv->num_ser++] = line;
- success = 1;
- }
+ if (IS_ERR(serial))
+ return PTR_ERR(serial);
- return success ? 0 : 1;
+ priv->serial = serial;
+ return 0;
}
/* Register the parallel port(s) of a PCI card. */
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
priv = kmalloc (sizeof *priv, GFP_KERNEL);
if (!priv)
return -ENOMEM;
- priv->num_ser = priv->num_par = 0;
+ memset(priv, 0, sizeof(struct parport_serial_private));
pci_set_drvdata (dev, priv);
err = pci_enable_device (dev);
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
struct parport_serial_private *priv = pci_get_drvdata (dev);
int i;
+ pci_set_drvdata(dev, NULL);
+
// Serial ports
- for (i = 0; i < priv->num_ser; i++) {
- unregister_serial (priv->line[i]);
+ if (priv->serial)
+ pciserial_remove_ports(priv->serial);
- if (priv->ser.init_fn)
- (priv->ser.init_fn) (dev, &priv->ser, 0);
- }
- pci_set_drvdata (dev, NULL);
-
// Parallel ports
for (i = 0; i < priv->num_par; i++)
parport_pc_unregister_port (priv->port[i]);
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
return;
}
+static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+ if (priv->serial)
+ pciserial_suspend_ports(priv->serial);
+
+ /* FIXME: What about parport? */
+
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ return 0;
+}
+
+static int parport_serial_pci_resume(struct pci_dev *dev)
+{
+ struct parport_serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ /*
+ * The device may have been disabled. Re-enable it.
+ */
+ pci_enable_device(dev);
+
+ if (priv->serial)
+ pciserial_resume_ports(priv->serial);
+
+ /* FIXME: What about parport? */
+
+ return 0;
+}
+
static struct pci_driver parport_serial_pci_driver = {
.name = "parport_serial",
.id_table = parport_serial_pci_tbl,
.probe = parport_serial_pci_probe,
.remove = __devexit_p(parport_serial_pci_remove),
+ .suspend = parport_serial_pci_suspend,
+ .resume = parport_serial_pci_resume,
};
diff --git a/drivers/pci/.gitignore b/drivers/pci/.gitignore
new file mode 100644
index 000000000000..f297ca8d313e
--- /dev/null
+++ b/drivers/pci/.gitignore
@@ -0,0 +1,4 @@
+classlist.h
+devlist.h
+gen-devlist
+
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7f31991772ea..f187fd8aeed6 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -30,23 +30,6 @@ config PCI_LEGACY_PROC
When in doubt, say N.
-config PCI_NAMES
- bool "PCI device name database"
- depends on PCI
- ---help---
- By default, the kernel contains a database of all known PCI device
- names to make the information in /proc/pci, /proc/ioports and
- similar files comprehensible to the user.
-
- This database increases size of the kernel image by about 80KB. This
- memory is freed after the system boots up if CONFIG_HOTPLUG is not set.
-
- Anyway, if you are building an installation floppy or kernel for an
- embedded system where kernel image size really matters, you can disable
- this feature and you'll get device ID numbers instead of names.
-
- When in doubt, say Y.
-
config PCI_DEBUG
bool "PCI Debugging"
depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 3657f6199c48..716df015f8d0 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -3,14 +3,9 @@
#
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
- names.o pci-driver.o search.o pci-sysfs.o \
- rom.o
+ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
obj-$(CONFIG_PROC_FS) += proc.o
-ifndef CONFIG_SPARC64
-obj-y += setup-res.o
-endif
-
obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to
@@ -46,21 +41,6 @@ ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-hostprogs-y := gen-devlist
-
-# Dependencies on generated files need to be listed explicitly
-$(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h
-$(obj)/classlist.h: $(obj)/devlist.h
-
-# And that's how to generate them
-quiet_cmd_devlist = DEVLIST $@
- cmd_devlist = ( cd $(obj); ./gen-devlist ) < $<
-$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
- $(call cmd,devlist)
-
-# Files generated that shall be removed upon make clean
-clean-files := devlist.h classlist.h
-
# Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 24a76de49f41..2a42add7f563 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword);
EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
+{
+ u32 data;
+
+ data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
+ data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
+ return data;
+}
+
+#define PCI_USER_READ_CONFIG(size,type) \
+int pci_user_read_config_##size \
+ (struct pci_dev *dev, int pos, type *val) \
+{ \
+ unsigned long flags; \
+ int ret = 0; \
+ u32 data = -1; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ spin_lock_irqsave(&pci_lock, flags); \
+ if (likely(!dev->block_ucfg_access)) \
+ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
+ pos, sizeof(type), &data); \
+ else if (pos < sizeof(dev->saved_config_space)) \
+ data = pci_user_cached_config(dev, pos); \
+ spin_unlock_irqrestore(&pci_lock, flags); \
+ *val = (type)data; \
+ return ret; \
+}
+
+#define PCI_USER_WRITE_CONFIG(size,type) \
+int pci_user_write_config_##size \
+ (struct pci_dev *dev, int pos, type val) \
+{ \
+ unsigned long flags; \
+ int ret = -EIO; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ spin_lock_irqsave(&pci_lock, flags); \
+ if (likely(!dev->block_ucfg_access)) \
+ ret = dev->bus->ops->write(dev->bus, dev->devfn, \
+ pos, sizeof(type), val); \
+ spin_unlock_irqrestore(&pci_lock, flags); \
+ return ret; \
+}
+
+PCI_USER_READ_CONFIG(byte, u8)
+PCI_USER_READ_CONFIG(word, u16)
+PCI_USER_READ_CONFIG(dword, u32)
+PCI_USER_WRITE_CONFIG(byte, u8)
+PCI_USER_WRITE_CONFIG(word, u16)
+PCI_USER_WRITE_CONFIG(dword, u32)
+
+/**
+ * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * This function blocks any userspace PCI config accesses from occurring.
+ * When blocked, any writes will be bit bucketed and reads will return the
+ * data saved using pci_save_state for the first 64 bytes of config
+ * space and return 0xff for all other config reads.
+ **/
+void pci_block_user_cfg_access(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ pci_save_state(dev);
+
+ /* spinlock to synchronize with anyone reading config space now */
+ spin_lock_irqsave(&pci_lock, flags);
+ dev->block_ucfg_access = 1;
+ spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+
+/**
+ * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * This function allows userspace PCI config accesses to resume.
+ **/
+void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ /* spinlock to synchronize with anyone reading saved config space */
+ spin_lock_irqsave(&pci_lock, flags);
+ dev->block_ucfg_access = 0;
+ spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index fb9a11243d2a..eed67d9e73bc 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -140,16 +140,65 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
void pci_enable_bridges(struct pci_bus *bus)
{
struct pci_dev *dev;
+ int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->subordinate) {
- pci_enable_device(dev);
+ retval = pci_enable_device(dev);
pci_set_master(dev);
pci_enable_bridges(dev->subordinate);
}
}
}
+/** pci_walk_bus - walk devices on/under bus, calling callback.
+ * @top bus whose devices should be walked
+ * @cb callback to be called for each device found
+ * @userdata arbitrary pointer to be passed to callback.
+ *
+ * Walk the given bus, including any bridged devices
+ * on buses under this bus. Call the provided callback
+ * on each device found.
+ */
+void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+ void *userdata)
+{
+ struct pci_dev *dev;
+ struct pci_bus *bus;
+ struct list_head *next;
+
+ bus = top;
+ spin_lock(&pci_bus_lock);
+ next = top->devices.next;
+ for (;;) {
+ if (next == &bus->devices) {
+ /* end of this bus, go up or finish */
+ if (bus == top)
+ break;
+ next = bus->self->bus_list.next;
+ bus = bus->self->bus;
+ continue;
+ }
+ dev = list_entry(next, struct pci_dev, bus_list);
+ pci_dev_get(dev);
+ if (dev->subordinate) {
+ /* this is a pci-pci bridge, do its devices next */
+ next = dev->subordinate->devices.next;
+ bus = dev->subordinate;
+ } else
+ next = dev->bus_list.next;
+ spin_unlock(&pci_bus_lock);
+
+ /* Run device routines with the bus unlocked */
+ cb(dev, userdata);
+
+ spin_lock(&pci_bus_lock);
+ pci_dev_put(dev);
+ }
+ spin_unlock(&pci_bus_lock);
+}
+EXPORT_SYMBOL_GPL(pci_walk_bus);
+
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);
EXPORT_SYMBOL(pci_bus_add_devices);
diff --git a/drivers/pci/gen-devlist.c b/drivers/pci/gen-devlist.c
deleted file mode 100644
index 8abfc499fdef..000000000000
--- a/drivers/pci/gen-devlist.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Generate devlist.h and classlist.h from the PCI ID file.
- *
- * (c) 1999--2002 Martin Mares <mj@ucw.cz>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define MAX_NAME_SIZE 200
-
-static void
-pq(FILE *f, const char *c, int len)
-{
- int i = 1;
- while (*c && i != len) {
- if (*c == '"')
- fprintf(f, "\\\"");
- else {
- fputc(*c, f);
- if (*c == '?' && c[1] == '?') {
- /* Avoid trigraphs */
- fprintf(f, "\" \"");
- }
- }
- c++;
- i++;
- }
-}
-
-int
-main(void)
-{
- char line[1024], *c, *bra, vend[8];
- int vendors = 0;
- int mode = 0;
- int lino = 0;
- int vendor_len = 0;
- FILE *devf, *clsf;
-
- devf = fopen("devlist.h", "w");
- clsf = fopen("classlist.h", "w");
- if (!devf || !clsf) {
- fprintf(stderr, "Cannot create output file!\n");
- return 1;
- }
-
- while (fgets(line, sizeof(line)-1, stdin)) {
- lino++;
- if ((c = strchr(line, '\n')))
- *c = 0;
- if (!line[0] || line[0] == '#')
- continue;
- if (line[1] == ' ') {
- if (line[0] == 'C' && strlen(line) > 4 && line[4] == ' ') {
- vend[0] = line[2];
- vend[1] = line[3];
- vend[2] = 0;
- mode = 2;
- } else goto err;
- }
- else if (line[0] == '\t') {
- if (line[1] == '\t')
- continue;
- switch (mode) {
- case 1:
- if (strlen(line) > 5 && line[5] == ' ') {
- c = line + 5;
- while (*c == ' ')
- *c++ = 0;
- if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
- /* Too long, try cutting off long description */
- bra = strchr(c, '[');
- if (bra && bra > c && bra[-1] == ' ')
- bra[-1] = 0;
- if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
- fprintf(stderr, "Line %d: Device name too long. Name truncated.\n", lino);
- fprintf(stderr, "%s\n", c);
- /*return 1;*/
- }
- }
- fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1);
- pq(devf, c, MAX_NAME_SIZE - vendor_len - 1);
- fputs("\")\n", devf);
- } else goto err;
- break;
- case 2:
- if (strlen(line) > 3 && line[3] == ' ') {
- c = line + 3;
- while (*c == ' ')
- *c++ = 0;
- fprintf(clsf, "CLASS(%s%s, \"%s\")\n", vend, line+1, c);
- } else goto err;
- break;
- default:
- goto err;
- }
- } else if (strlen(line) > 4 && line[4] == ' ') {
- c = line + 4;
- while (*c == ' ')
- *c++ = 0;
- if (vendors)
- fputs("ENDVENDOR()\n\n", devf);
- vendors++;
- strcpy(vend, line);
- vendor_len = strlen(c);
- if (vendor_len + 24 > MAX_NAME_SIZE) {
- fprintf(stderr, "Line %d: Vendor name too long\n", lino);
- return 1;
- }
- fprintf(devf, "VENDOR(%s,\"", vend);
- pq(devf, c, 0);
- fputs("\")\n", devf);
- mode = 1;
- } else {
- err:
- fprintf(stderr, "Line %d: Syntax error in mode %d: %s\n", lino, mode, line);
- return 1;
- }
- }
- fputs("ENDVENDOR()\n\
-\n\
-#undef VENDOR\n\
-#undef DEVICE\n\
-#undef ENDVENDOR\n", devf);
- fputs("\n#undef CLASS\n", clsf);
-
- fclose(devf);
- fclose(clsf);
-
- return 0;
-}
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index b844bc972324..e1743be31909 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -7,7 +7,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct pci_dev *pdev;
- char *scratch;
int i = 0;
int length = 0;
@@ -18,48 +17,34 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
if (!pdev)
return -ENODEV;
- scratch = buffer;
-
- /* stuff we want to pass to /sbin/hotplug */
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
- pdev->class);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_CLASS=%04X", pdev->class))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
- pdev->vendor, pdev->device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+ pdev->subsystem_device))
return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
- pci_name(pdev));
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device,
- (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
- (u8)(pdev->class));
- if ((buffer_size - length <= 0) || (i >= num_envp))
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class)))
return -ENOMEM;
envp[i] = NULL;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 9c4a39ee89b5..2f1289eebb3c 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -78,7 +78,7 @@ config HOTPLUG_PCI_IBM
config HOTPLUG_PCI_ACPI
tristate "ACPI PCI Hotplug driver"
- depends on ACPI_BUS && HOTPLUG_PCI
+ depends on ACPI && HOTPLUG_PCI
help
Say Y here if you have a system that supports PCI Hotplug using
ACPI.
@@ -157,7 +157,7 @@ config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
config HOTPLUG_PCI_SHPC_PHPRM_LEGACY
bool "For AMD SHPC only: Use $HRT for resource/configuration"
- depends on HOTPLUG_PCI_SHPC && !ACPI_BUS
+ depends on HOTPLUG_PCI_SHPC && !ACPI
help
Say Y here for AMD SHPC. You have to select this option if you are
using this driver on platform with AMD SHPC.
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 31a307004b94..3c71e3077ff1 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -41,8 +41,7 @@ acpiphp-objs := acpiphp_core.o \
rpaphp-objs := rpaphp_core.o \
rpaphp_pci.o \
- rpaphp_slot.o \
- rpaphp_vio.o
+ rpaphp_slot.o
rpadlpar_io-objs := rpadlpar_core.o \
rpadlpar_sysfs.o
@@ -51,7 +50,7 @@ pciehp-objs := pciehp_core.o \
pciehp_ctrl.o \
pciehp_pci.o \
pciehp_hpc.o
-ifdef CONFIG_ACPI_BUS
+ifdef CONFIG_ACPI
pciehp-objs += pciehprm_acpi.o
else
pciehp-objs += pciehprm_nonacpi.o
@@ -62,7 +61,7 @@ shpchp-objs := shpchp_core.o \
shpchp_pci.o \
shpchp_sysfs.o \
shpchp_hpc.o
-ifdef CONFIG_ACPI_BUS
+ifdef CONFIG_ACPI
shpchp-objs += shpchprm_acpi.o
else
ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 424e7de181ae..8e21f6ab89a1 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);
static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
static void handle_hotplug_event_func (acpi_handle, u32, void *);
+static void acpiphp_sanitize_bus(struct pci_bus *bus);
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
+
/*
* initialization & terminatation routines
@@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot)
}
}
+ pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
+ acpiphp_sanitize_bus(bus);
+ pci_enable_bridges(bus);
pci_bus_add_devices(bus);
+ acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
+ acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
/* associate pci_dev to our representation */
list_for_each (l, &slot->funcs) {
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index a62a4345b466..2d4639d6841f 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/string.h>
#include "cpci_hotplug.h"
#define DRIVER_VERSION "0.1"
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index e9928024be78..f7cb00da38df 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/signal.h> /* SA_SHIRQ */
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"
@@ -78,11 +79,20 @@ static void __iomem *csr_int_mask;
static int zt5550_hc_config(struct pci_dev *pdev)
{
+ int ret;
+
/* Since we know that no boards exist with two HC chips, treat it as an error */
if(hc_dev) {
err("too many host controller devices?");
return -EBUSY;
}
+
+ ret = pci_enable_device(pdev);
+ if(ret) {
+ err("cannot enable %s\n", pci_name(pdev));
+ return ret;
+ }
+
hc_dev = pdev;
dbg("hc_dev = %p", hc_dev);
dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
@@ -91,7 +101,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!request_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1), MY_NAME)) {
err("cannot reserve MMIO region");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto exit_disable_device;
}
hc_registers =
@@ -99,9 +110,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!hc_registers) {
err("cannot remap MMIO region %lx @ %lx",
pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
- release_mem_region(pci_resource_start(hc_dev, 1),
- pci_resource_len(hc_dev, 1));
- return -ENODEV;
+ ret = -ENODEV;
+ goto exit_release_region;
}
csr_hc_index = hc_registers + CSR_HCINDEX;
@@ -124,6 +134,13 @@ static int zt5550_hc_config(struct pci_dev *pdev)
writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
dbg("disabled timer0, timer1 and ENUM interrupts");
return 0;
+
+exit_release_region:
+ release_mem_region(pci_resource_start(hc_dev, 1),
+ pci_resource_len(hc_dev, 1));
+exit_disable_device:
+ pci_disable_device(hc_dev);
+ return ret;
}
static int zt5550_hc_cleanup(void)
@@ -134,6 +151,7 @@ static int zt5550_hc_cleanup(void)
iounmap(hc_registers);
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
+ pci_disable_device(hc_dev);
return 0;
}
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 8c6d3987d461..9aed8efe6a11 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u32 rc;
struct controller *ctrl;
struct pci_func *func;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+ pci_name(pdev), err);
+ return err;
+ }
// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
err(msg_HPC_non_compaq_or_intel);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
dbg("Vendor ID: %x\n", vendor_id);
@@ -807,7 +816,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dbg("revision: %d\n", rev);
if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
err(msg_HPC_rev_error);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
/* Check for the proper subsytem ID's
@@ -820,18 +830,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
if (rc) {
err("%s : pci_read_config_word failed\n", __FUNCTION__);
- return rc;
+ goto err_disable_device;
}
dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
err(msg_HPC_non_compaq_or_intel);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err_disable_device;
}
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_disable_device;
}
memset(ctrl, 0, sizeof(struct controller));
@@ -1264,6 +1276,8 @@ err_free_bus:
kfree(ctrl->pci_bus);
err_free_ctrl:
kfree(ctrl);
+err_disable_device:
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 8e47fa66e25e..060d74775d7b 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -37,6 +37,8 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "pci_hotplug.h"
#include "../pci.h"
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 0392e004258f..aabf1e70b528 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -1077,7 +1077,7 @@ static int enable_slot(struct hotplug_slot *hs)
if (rc) {
err("Adding this card exceeds the limitations of this bus.\n");
err("(i.e., >1 133MHz cards running on same bus, or "
- ">2 66 PCI cards running on same bus\n.");
+ ">2 66 PCI cards running on same bus.\n");
err("Try hot-adding into another bus\n");
rc = -EINVAL;
goto error_nopower;
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 8122fe734aa7..b1ba429e0a2d 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func)
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
- pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
+ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
return 0;
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 46b294a12418..061ead21ef14 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
#ifndef _PCIEHP_H
@@ -302,7 +302,7 @@ static inline void return_resource(struct pci_resource **head, struct pci_resour
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
- snprintf(buffer, buffer_size, "%d", slot->number);
+ snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
}
enum php_ctlr_type {
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index df4915dbc321..cafc7eadcf80 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0dbcf04aa35e..898f6da6f0de 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
@@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func,
int cloop;
u8 temp_byte;
u8 class_code;
- u16 temp_word;
u32 rc;
u32 temp_register;
u32 base;
@@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func,
} /* End of base register loop */
/* disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+ rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
/* Set HP parameters (Cache Line Size, Latency Timer) */
rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 1cda30bd6e47..7a0e27f0e063 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 723b12c0bb7c..ff17d8e07e94 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
@@ -113,7 +113,7 @@ int pciehp_unconfigure_device(struct pci_func* func)
*/
int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
int rc;
u16 temp_word;
struct pci_dev fakedev;
diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h
index 966775ffb0ff..05f20fbc5f50 100644
--- a/drivers/pci/hotplug/pciehprm.h
+++ b/drivers/pci/hotplug/pciehprm.h
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index 57f4e6d1b27c..1406db35b089 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -20,7 +20,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <dely.l.sy@intel.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
*
*/
@@ -1696,15 +1696,15 @@ void pciehprm_enable_card(
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+ rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+ rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
}
- cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+ command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+ bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA;
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
if (ab) {
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index 79a0aa6238ef..33b2c69a0829 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
@@ -33,10 +33,13 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/slab.h>
+
#include <asm/uaccess.h>
#ifdef CONFIG_IA64
#include <asm/iosapic.h>
#endif
+
#include "pciehp.h"
#include "pciehprm.h"
#include "pciehprm_nonacpi.h"
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h
index 87c90e85ede9..b10603b0e958 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.h
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.h
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 86b384e42717..fcb66b9a0e28 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -16,36 +16,42 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/string.h>
+
#include <asm/pci-bridge.h>
#include <asm/semaphore.h>
#include <asm/rtas.h>
+#include <asm/vio.h>
+
#include "../pci.h"
#include "rpaphp.h"
#include "rpadlpar.h"
static DECLARE_MUTEX(rpadlpar_sem);
+#define DLPAR_MODULE_NAME "rpadlpar_io"
+
#define NODE_TYPE_VIO 1
#define NODE_TYPE_SLOT 2
#define NODE_TYPE_PHB 3
-static struct device_node *find_php_slot_vio_node(char *drc_name)
+static struct device_node *find_vio_slot_node(char *drc_name)
{
- struct device_node *child;
struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
- char *loc_code;
+ struct device_node *dn = NULL;
+ char *name;
+ int rc;
if (!parent)
return NULL;
- for (child = of_get_next_child(parent, NULL);
- child; child = of_get_next_child(parent, child)) {
- loc_code = get_property(child, "ibm,loc-code", NULL);
- if (loc_code && !strncmp(loc_code, drc_name, strlen(drc_name)))
- return child;
+ while ((dn = of_get_next_child(parent, dn))) {
+ rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
+ if ((rc == 0) && (!strcmp(drc_name, name)))
+ break;
}
- return NULL;
+ return dn;
}
/* Find dlpar-capable pci node that contains the specified name and type */
@@ -67,7 +73,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
return np;
}
-static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
+static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
{
struct device_node *dn;
@@ -83,7 +89,7 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
return dn;
}
- dn = find_php_slot_vio_node(drc_name);
+ dn = find_vio_slot_node(drc_name);
if (dn) {
*node_type = NODE_TYPE_VIO;
return dn;
@@ -92,14 +98,14 @@ static struct device_node *find_newly_added_node(char *drc_name, int *node_type)
return NULL;
}
-static struct slot *find_slot(char *drc_name)
+static struct slot *find_slot(struct device_node *dn)
{
struct list_head *tmp, *n;
struct slot *slot;
list_for_each_safe(tmp, n, &rpaphp_slot_head) {
slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (strcmp(slot->location, drc_name) == 0)
+ if (slot->dn == dn)
return slot;
}
@@ -131,7 +137,8 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b)
static int pci_add_secondary_bus(struct device_node *dn,
struct pci_dev *bridge_dev)
{
- struct pci_controller *hose = dn->phb;
+ struct pci_dn *pdn = dn->data;
+ struct pci_controller *hose = pdn->phb;
struct pci_bus *child;
u8 sec_busno;
@@ -156,7 +163,7 @@ static int pci_add_secondary_bus(struct device_node *dn,
if (hose->last_busno < child->number)
hose->last_busno = child->number;
- dn->bussubno = child->number;
+ pdn->bussubno = child->number;
/* ioremap() for child bus, which may or may not succeed */
remap_bus_range(child);
@@ -164,13 +171,28 @@ static int pci_add_secondary_bus(struct device_node *dn,
return 0;
}
+static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
+ struct device_node *dev_dn)
+{
+ struct pci_dev *tmp = NULL;
+ struct device_node *child_dn;
+
+ list_for_each_entry(tmp, &parent->devices, bus_list) {
+ child_dn = pci_device_to_OF_node(tmp);
+ if (child_dn == dev_dn)
+ return tmp;
+ }
+ return NULL;
+}
+
static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
{
- struct pci_controller *hose = dn->phb;
+ struct pci_dn *pdn = dn->data;
+ struct pci_controller *hose = pdn->phb;
struct pci_dev *dev = NULL;
/* Scan phb bus for EADS device, adding new one to bus->devices */
- if (!pci_scan_single_device(hose->bus, dn->devfn)) {
+ if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
return NULL;
}
@@ -179,49 +201,28 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
pci_bus_add_devices(hose->bus);
/* Confirm new bridge dev was created */
- dev = rpaphp_find_pci_dev(dn);
- if (!dev) {
- printk(KERN_ERR "%s: failed to add pci device\n", __FUNCTION__);
- return NULL;
- }
+ dev = dlpar_find_new_dev(hose->bus, dn);
+ if (dev) {
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ printk(KERN_ERR "%s: unexpected header type %d\n",
+ __FUNCTION__, dev->hdr_type);
+ return NULL;
+ }
- if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
- printk(KERN_ERR "%s: unexpected header type %d\n",
- __FUNCTION__, dev->hdr_type);
- return NULL;
+ if (pci_add_secondary_bus(dn, dev))
+ return NULL;
}
- if (pci_add_secondary_bus(dn, dev))
- return NULL;
-
return dev;
}
-static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
+static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
{
- struct pci_bus *secondary_bus;
+ struct pci_dev *dev;
+ int rc;
- if (!bridge_dev) {
- printk(KERN_ERR "%s: unexpected null device\n",
- __FUNCTION__);
+ if (rpaphp_find_pci_bus(dn))
return -EINVAL;
- }
-
- secondary_bus = bridge_dev->subordinate;
-
- if (unmap_bus_range(secondary_bus)) {
- printk(KERN_ERR "%s: failed to unmap bus range\n",
- __FUNCTION__);
- return -ERANGE;
- }
-
- pci_remove_bus_device(bridge_dev);
- return 0;
-}
-
-static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
-{
- struct pci_dev *dev;
/* Add pci bus */
dev = dlpar_pci_add_bus(dn);
@@ -231,6 +232,21 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
return -EIO;
}
+ if (dn->child) {
+ rc = rpaphp_config_pci_adapter(dev->subordinate);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: unable to enable slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
+ }
+
+ /* Add hotplug slot */
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
return 0;
}
@@ -255,47 +271,69 @@ static int dlpar_remove_root_bus(struct pci_controller *phb)
return 0;
}
-static int dlpar_remove_phb(struct slot *slot)
+static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
{
- struct pci_controller *phb;
- struct device_node *dn;
+ struct slot *slot;
+ struct pci_dn *pdn;
int rc = 0;
- dn = slot->dn;
- if (!dn) {
- printk(KERN_ERR "%s: unexpected NULL slot device node\n",
- __FUNCTION__);
- return -EIO;
- }
-
- phb = dn->phb;
- if (!phb) {
- printk(KERN_ERR "%s: unexpected NULL phb pointer\n",
- __FUNCTION__);
- return -EIO;
- }
+ if (!rpaphp_find_pci_bus(dn))
+ return -EINVAL;
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, slot->location);
- return -EIO;
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
- rc = dlpar_remove_root_bus(phb);
+ pdn = dn->data;
+ BUG_ON(!pdn || !pdn->phb);
+ rc = dlpar_remove_root_bus(pdn->phb);
if (rc < 0)
return rc;
+ pdn->phb = NULL;
+
return 0;
}
-static int dlpar_add_phb(struct device_node *dn)
+static int dlpar_add_phb(char *drc_name, struct device_node *dn)
{
struct pci_controller *phb;
+ if (PCI_DN(dn)->phb) {
+ /* PHB already exists */
+ return -EINVAL;
+ }
+
phb = init_phb_dynamic(dn);
if (!phb)
+ return -EIO;
+
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
+{
+ if (vio_find_node(dn))
return -EINVAL;
+ if (!vio_register_device_node(dn)) {
+ printk(KERN_ERR
+ "%s: failed to register vio node %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
return 0;
}
@@ -316,18 +354,13 @@ int dlpar_add_slot(char *drc_name)
{
struct device_node *dn = NULL;
int node_type;
- int rc = 0;
+ int rc = -EIO;
if (down_interruptible(&rpadlpar_sem))
return -ERESTARTSYS;
- /* Check for existing hotplug slot */
- if (find_slot(drc_name)) {
- rc = -EINVAL;
- goto exit;
- }
-
- dn = find_newly_added_node(drc_name, &node_type);
+ /* Find newly added node */
+ dn = find_dlpar_node(drc_name, &node_type);
if (!dn) {
rc = -ENODEV;
goto exit;
@@ -335,24 +368,17 @@ int dlpar_add_slot(char *drc_name)
switch (node_type) {
case NODE_TYPE_VIO:
- /* Just add hotplug slot */
+ rc = dlpar_add_vio_slot(drc_name, dn);
break;
case NODE_TYPE_SLOT:
rc = dlpar_add_pci_slot(drc_name, dn);
break;
case NODE_TYPE_PHB:
- rc = dlpar_add_phb(dn);
+ rc = dlpar_add_phb(drc_name, dn);
break;
- default:
- printk("%s: unexpected node type\n", __FUNCTION__);
- return -EIO;
}
- if (!rc && rpaphp_add_slot(dn)) {
- printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
- __FUNCTION__, drc_name);
- rc = -EIO;
- }
+ printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;
@@ -366,17 +392,17 @@ exit:
* of an I/O Slot.
* Return Codes:
* 0 Success
- * -EIO Internal Error
+ * -EINVAL Vio dev doesn't exist
*/
-int dlpar_remove_vio_slot(struct slot *slot, char *drc_name)
+static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
{
- /* Remove hotplug slot */
+ struct vio_dev *vio_dev;
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
- }
+ vio_dev = vio_find_node(dn);
+ if (!vio_dev)
+ return -EINVAL;
+
+ vio_unregister_device(vio_dev);
return 0;
}
@@ -391,31 +417,34 @@ int dlpar_remove_vio_slot(struct slot *slot, char *drc_name)
* -ENODEV Not a valid drc_name
* -EIO Internal PCI Error
*/
-int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
+int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
{
- struct pci_dev *bridge_dev;
+ struct pci_bus *bus;
+ struct slot *slot;
- bridge_dev = slot->bridge;
- if (!bridge_dev) {
- printk(KERN_ERR "%s: unexpected null bridge device\n",
- __FUNCTION__);
- return -EIO;
- }
+ bus = rpaphp_find_pci_bus(dn);
+ if (!bus)
+ return -EINVAL;
- /* Remove hotplug slot */
- if (rpaphp_remove_slot(slot)) {
- printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
+ slot = find_slot(dn);
+ if (slot) {
+ /* Remove hotplug slot */
+ if (rpaphp_remove_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+ __FUNCTION__, drc_name);
+ return -EIO;
+ }
}
- /* Remove pci bus */
-
- if (dlpar_pci_remove_bus(bridge_dev)) {
- printk(KERN_ERR "%s: unable to remove pci bus %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
+ if (unmap_bus_range(bus)) {
+ printk(KERN_ERR "%s: failed to unmap bus range\n",
+ __FUNCTION__);
+ return -ERANGE;
}
+
+ BUG_ON(!bus->self);
+ pci_remove_bus_device(bus->self);
return 0;
}
@@ -434,38 +463,31 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
*/
int dlpar_remove_slot(char *drc_name)
{
- struct slot *slot;
+ struct device_node *dn;
+ int node_type;
int rc = 0;
if (down_interruptible(&rpadlpar_sem))
return -ERESTARTSYS;
- if (!find_php_slot_vio_node(drc_name) &&
- !find_php_slot_pci_node(drc_name, "SLOT") &&
- !find_php_slot_pci_node(drc_name, "PHB")) {
+ dn = find_dlpar_node(drc_name, &node_type);
+ if (!dn) {
rc = -ENODEV;
goto exit;
}
- slot = find_slot(drc_name);
- if (!slot) {
- rc = -EINVAL;
- goto exit;
- }
-
- if (slot->type == PHB) {
- rc = dlpar_remove_phb(slot);
- } else {
- switch (slot->dev_type) {
- case PCI_DEV:
- rc = dlpar_remove_pci_slot(slot, drc_name);
- break;
-
- case VIO_DEV:
- rc = dlpar_remove_vio_slot(slot, drc_name);
- break;
- }
+ switch (node_type) {
+ case NODE_TYPE_VIO:
+ rc = dlpar_remove_vio_slot(drc_name, dn);
+ break;
+ case NODE_TYPE_PHB:
+ rc = dlpar_remove_phb(drc_name, dn);
+ break;
+ case NODE_TYPE_SLOT:
+ rc = dlpar_remove_pci_slot(drc_name, dn);
+ break;
}
+ printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
exit:
up(&rpadlpar_sem);
return rc;
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index 752e6513c447..db69be85b458 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -62,7 +62,7 @@ static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr,
char drc_name[MAX_DRC_NAME_LEN];
char *end;
- if (nbytes > MAX_DRC_NAME_LEN)
+ if (nbytes >= MAX_DRC_NAME_LEN)
return 0;
memcpy(drc_name, buf, nbytes);
@@ -83,7 +83,7 @@ static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr,
char drc_name[MAX_DRC_NAME_LEN];
char *end;
- if (nbytes > MAX_DRC_NAME_LEN)
+ if (nbytes >= MAX_DRC_NAME_LEN)
return 0;
memcpy(drc_name, buf, nbytes);
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 81746e6e0e0f..71ea5f9bb284 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -30,10 +30,6 @@
#include <linux/pci.h>
#include "pci_hotplug.h"
-#define PHB 2
-#define HOTPLUG 1
-#define EMBEDDED 0
-
#define DR_INDICATOR 9002
#define DR_ENTITY_SENSE 9003
@@ -61,10 +57,6 @@ extern int debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-/* slot types */
-#define VIO_DEV 1
-#define PCI_DEV 2
-
/* slot states */
#define NOT_VALID 3
@@ -72,11 +64,6 @@ extern int debug;
#define CONFIGURED 1
#define EMPTY 0
-struct rpaphp_pci_func {
- struct pci_dev *pci_dev;
- struct list_head sibling;
-};
-
/*
* struct slot - slot information for each *physical* slot
*/
@@ -88,15 +75,9 @@ struct slot {
u32 power_domain;
char *name;
char *location;
- u8 removable;
- u8 dev_type; /* VIO or PCI */
- struct device_node *dn; /* slot's device_node in OFDT */
- /* dn has phb info */
- struct pci_dev *bridge; /* slot's pci_dev in pci_devices */
- union {
- struct list_head *pci_devs; /* pci_devs in PCI slot */
- struct vio_dev *vio_dev; /* vio_dev in VIO slot */
- } dev;
+ struct device_node *dn;
+ struct pci_bus *bus;
+ struct list_head *pci_devs;
struct hotplug_slot *hotplug_slot;
};
@@ -107,13 +88,14 @@ extern int num_slots;
/* function prototypes */
/* rpaphp_pci.c */
-extern struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn);
+extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
extern int register_pci_slot(struct slot *slot);
-extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev);
+
+extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
/* rpaphp_core.c */
extern int rpaphp_add_slot(struct device_node *dn);
@@ -121,12 +103,6 @@ extern int rpaphp_remove_slot(struct slot *slot);
extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
char **drc_name, char **drc_type, int *drc_power_domain);
-/* rpaphp_vio.c */
-extern int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 * value);
-extern int rpaphp_unconfig_vio_adapter(struct slot *slot);
-extern int register_vio_slot(struct device_node *dn);
-extern int rpaphp_enable_vio_slot(struct slot *slot);
-
/* rpaphp_slot.c */
extern void dealloc_slot_struct(struct slot *slot);
extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 29117a3a3287..cf075c34b578 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -152,17 +152,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
int retval = 0;
down(&rpaphp_sem);
- /* have to go through this */
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_get_pci_adapter_status(slot, 0, value);
- break;
- case VIO_DEV:
- retval = rpaphp_get_vio_adapter_status(slot, 0, value);
- break;
- default:
- retval = -EINVAL;
- }
+ retval = rpaphp_get_pci_adapter_status(slot, 0, value);
up(&rpaphp_sem);
return retval;
}
@@ -317,34 +307,6 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names,
return 0;
}
-static int is_dr_dn(struct device_node *dn, int **indexes, int **names,
- int **types, int **power_domains, int **my_drc_index)
-{
- int rc;
-
- *my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL);
- if(!*my_drc_index)
- return (0);
-
- if (!dn->parent)
- return (0);
-
- rc = get_children_props(dn->parent, indexes, names, types,
- power_domains);
- return (rc >= 0);
-}
-
-static inline int is_vdevice_root(struct device_node *dn)
-{
- return !strcmp(dn->name, "vdevice");
-}
-
-int is_dlpar_type(const char *type_str)
-{
- /* Only register DLPAR-capable nodes of drc-type PHB or SLOT */
- return (!strcmp(type_str, "PHB") || !strcmp(type_str, "SLOT"));
-}
-
/****************************************************************
* rpaphp not only registers PCI hotplug slots(HOTPLUG),
* but also logical DR slots(EMBEDDED).
@@ -356,54 +318,33 @@ int rpaphp_add_slot(struct device_node *dn)
{
struct slot *slot;
int retval = 0;
- int i, *my_drc_index, slot_type;
+ int i;
int *indexes, *names, *types, *power_domains;
char *name, *type;
dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
- if (dn->parent && is_vdevice_root(dn->parent)) {
- /* register a VIO device */
- retval = register_vio_slot(dn);
- goto exit;
- }
-
/* register PCI devices */
if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
- if (is_php_dn(dn, &indexes, &names, &types, &power_domains))
- slot_type = HOTPLUG;
- else if (is_dr_dn(dn, &indexes, &names, &types, &power_domains, &my_drc_index))
- slot_type = EMBEDDED;
- else goto exit;
+ if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+ goto exit;
name = (char *) &names[1];
type = (char *) &types[1];
for (i = 0; i < indexes[0]; i++,
- name += (strlen(name) + 1), type += (strlen(type) + 1)) {
-
- if (slot_type == HOTPLUG ||
- (slot_type == EMBEDDED &&
- indexes[i + 1] == my_drc_index[0] &&
- is_dlpar_type(type))) {
- if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
- power_domains[i + 1]))) {
- retval = -ENOMEM;
- goto exit;
- }
- if (!strcmp(type, "PHB"))
- slot->type = PHB;
- else if (slot_type == EMBEDDED)
- slot->type = EMBEDDED;
- else
- slot->type = simple_strtoul(type, NULL, 10);
+ name += (strlen(name) + 1), type += (strlen(type) + 1)) {
+
+ if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
+ power_domains[i + 1]))) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ slot->type = simple_strtoul(type, NULL, 10);
- dbg(" Found drc-index:0x%x drc-name:%s drc-type:%s\n",
+ dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
indexes[i + 1], name, type);
- retval = register_pci_slot(slot);
- if (slot_type == EMBEDDED)
- goto exit;
- }
+ retval = register_pci_slot(slot);
}
}
exit:
@@ -412,31 +353,6 @@ exit:
return retval;
}
-/*
- * init_slots - initialize 'struct slot' structures for each slot
- *
- */
-static void init_slots(void)
-{
- struct device_node *dn;
-
- for (dn = find_all_nodes(); dn; dn = dn->next)
- rpaphp_add_slot(dn);
-}
-
-static int __init init_rpa(void)
-{
-
- init_MUTEX(&rpaphp_sem);
-
- /* initialize internal data structure etc. */
- init_slots();
- if (!num_slots)
- return -ENODEV;
-
- return 0;
-}
-
static void __exit cleanup_slots(void)
{
struct list_head *tmp, *n;
@@ -458,10 +374,18 @@ static void __exit cleanup_slots(void)
static int __init rpaphp_init(void)
{
+ struct device_node *dn = NULL;
+
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ init_MUTEX(&rpaphp_sem);
- /* read all the PRA info from the system */
- return init_rpa();
+ while ((dn = of_find_node_by_type(dn, "pci")))
+ rpaphp_add_slot(dn);
+
+ if (!num_slots)
+ return -ENODEV;
+
+ return 0;
}
static void __exit rpaphp_exit(void)
@@ -481,16 +405,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
dbg("ENABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_enable_pci_slot(slot);
- break;
- case VIO_DEV:
- retval = rpaphp_enable_vio_slot(slot);
- break;
- default:
- retval = -EINVAL;
- }
+ retval = rpaphp_enable_pci_slot(slot);
up(&rpaphp_sem);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
@@ -511,17 +426,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
dbg("DISABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
- switch (slot->dev_type) {
- case PCI_DEV:
- retval = rpaphp_unconfig_pci_adapter(slot);
- break;
- case VIO_DEV:
- retval = rpaphp_unconfig_vio_adapter(slot);
- break;
- default:
- retval = -ENODEV;
- }
+ retval = rpaphp_unconfig_pci_adapter(slot->bus);
up(&rpaphp_sem);
+ slot->state = NOT_CONFIGURED;
+ info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
+ slot->name);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index d8305a935aab..f7c12d7dfcfc 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -23,29 +23,44 @@
*
*/
#include <linux/pci.h>
+#include <linux/string.h>
+
#include <asm/pci-bridge.h>
#include <asm/rtas.h>
#include <asm/machdep.h>
-#include "../pci.h" /* for pci_add_new_bus */
+#include "../pci.h" /* for pci_add_new_bus */
#include "rpaphp.h"
-struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
+static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
+ struct device_node *dn)
{
- struct pci_dev *dev = NULL;
- char bus_id[BUS_ID_SIZE];
+ struct pci_bus *child = NULL;
+ struct list_head *tmp;
+ struct device_node *busdn;
- sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number,
- dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn));
- for_each_pci_dev(dev) {
- if (!strcmp(pci_name(dev), bus_id)) {
+ busdn = pci_bus_to_OF_node(bus);
+ if (busdn == dn)
+ return bus;
+
+ list_for_each(tmp, &bus->children) {
+ child = find_bus_among_children(pci_bus_b(tmp), dn);
+ if (child)
break;
- }
}
- return dev;
+ return child;
}
-EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev);
+struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
+{
+ struct pci_dn *pdn = dn->data;
+
+ if (!pdn || !pdn->phb || !pdn->phb->bus)
+ return NULL;
+
+ return find_bus_among_children(pdn->phb->bus, dn);
+}
+EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
int rpaphp_claim_resource(struct pci_dev *dev, int resource)
{
@@ -69,11 +84,6 @@ int rpaphp_claim_resource(struct pci_dev *dev, int resource)
EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
-static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
-{
- return rpaphp_find_pci_dev(slot->dn);
-}
-
static int rpaphp_get_sensor_state(struct slot *slot, int *state)
{
int rc;
@@ -116,39 +126,27 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state)
*/
int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
{
+ struct pci_bus *bus;
int state, rc;
- struct device_node *child_dn;
- struct pci_dev *child_dev = NULL;
*value = NOT_VALID;
rc = rpaphp_get_sensor_state(slot, &state);
if (rc)
goto exit;
- if ((state == EMPTY) || (slot->type == PHB)) {
- dbg("slot is empty\n");
+ if (state == EMPTY)
*value = EMPTY;
- }
else if (state == PRESENT) {
if (!is_init) {
/* at run-time slot->state can be changed by */
/* config/unconfig adapter */
*value = slot->state;
} else {
- child_dn = slot->dn->child;
- if (child_dn)
- child_dev = rpaphp_find_pci_dev(child_dn);
-
- if (child_dev)
- *value = CONFIGURED;
- else if (!child_dn)
- dbg("%s: %s is not valid OFDT node\n",
- __FUNCTION__, slot->dn->full_name);
- else {
- err("%s: can't find pdev of adapter in slot[%s]\n",
- __FUNCTION__, slot->dn->full_name);
+ bus = rpaphp_find_pci_bus(slot->dn);
+ if (bus && !list_empty(&bus->devices))
+ *value = CONFIGURED;
+ else
*value = NOT_CONFIGURED;
- }
}
}
exit:
@@ -186,39 +184,6 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
}
}
-static int rpaphp_pci_config_bridge(struct pci_dev *dev);
-
-/*****************************************************************************
- rpaphp_pci_config_slot() will configure all devices under the
- given slot->dn and return the the first pci_dev.
- *****************************************************************************/
-static struct pci_dev *
-rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus)
-{
- struct device_node *eads_first_child = dn->child;
- struct pci_dev *dev = NULL;
- int num;
-
- dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
-
- if (eads_first_child) {
- /* pci_scan_slot should find all children of EADs */
- num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0));
- if (num) {
- rpaphp_fixup_new_pci_devices(bus, 1);
- pci_bus_add_devices(bus);
- }
- dev = rpaphp_find_pci_dev(eads_first_child);
- if (!dev) {
- err("No new device found\n");
- return NULL;
- }
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- rpaphp_pci_config_bridge(dev);
- }
- return dev;
-}
-
static int rpaphp_pci_config_bridge(struct pci_dev *dev)
{
u8 sec_busno;
@@ -252,6 +217,42 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev)
return 0;
}
+/*****************************************************************************
+ rpaphp_pci_config_slot() will configure all devices under the
+ given slot->dn and return the the first pci_dev.
+ *****************************************************************************/
+static struct pci_dev *
+rpaphp_pci_config_slot(struct pci_bus *bus)
+{
+ struct device_node *dn = pci_bus_to_OF_node(bus);
+ struct pci_dev *dev = NULL;
+ int slotno;
+ int num;
+
+ dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
+ if (!dn || !dn->child)
+ return NULL;
+
+ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+
+ /* pci_scan_slot should find all children */
+ num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+ if (num) {
+ rpaphp_fixup_new_pci_devices(bus, 1);
+ pci_bus_add_devices(bus);
+ }
+ if (list_empty(&bus->devices)) {
+ err("%s: No new device found\n", __FUNCTION__);
+ return NULL;
+ }
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ rpaphp_pci_config_bridge(dev);
+ }
+
+ return dev;
+}
+
static void enable_eeh(struct device_node *dn)
{
struct device_node *sib;
@@ -263,49 +264,44 @@ static void enable_eeh(struct device_node *dn)
}
-static void print_slot_pci_funcs(struct slot *slot)
+static void print_slot_pci_funcs(struct pci_bus *bus)
{
+ struct device_node *dn;
struct pci_dev *dev;
- if (slot->dev_type == PCI_DEV) {
- dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->name);
- list_for_each_entry (dev, slot->dev.pci_devs, bus_list)
- dbg("\t%s\n", pci_name(dev));
- }
+ dn = pci_bus_to_OF_node(bus);
+ if (!dn)
+ return;
+
+ dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
+ list_for_each_entry (dev, &bus->devices, bus_list)
+ dbg("\t%s\n", pci_name(dev));
return;
}
-static int rpaphp_config_pci_adapter(struct slot *slot)
+int rpaphp_config_pci_adapter(struct pci_bus *bus)
{
- struct pci_bus *pci_bus;
+ struct device_node *dn = pci_bus_to_OF_node(bus);
struct pci_dev *dev;
int rc = -ENODEV;
- dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
-
- if (slot->bridge) {
+ dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
+ if (!dn)
+ goto exit;
- pci_bus = slot->bridge->subordinate;
- if (!pci_bus) {
- err("%s: can't find bus structure\n", __FUNCTION__);
- goto exit;
- }
- enable_eeh(slot->dn);
- dev = rpaphp_pci_config_slot(slot->dn, pci_bus);
- if (!dev) {
- err("%s: can't find any devices.\n", __FUNCTION__);
- goto exit;
- }
- print_slot_pci_funcs(slot);
- rc = 0;
- } else {
- /* slot is not enabled */
- err("slot doesn't have pci_dev structure\n");
+ enable_eeh(dn);
+ dev = rpaphp_pci_config_slot(bus);
+ if (!dev) {
+ err("%s: can't find any devices.\n", __FUNCTION__);
+ goto exit;
}
+ print_slot_pci_funcs(bus);
+ rc = 0;
exit:
dbg("Exit %s: rc=%d\n", __FUNCTION__, rc);
return rc;
}
+EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
{
@@ -325,19 +321,15 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
return;
}
-int rpaphp_unconfig_pci_adapter(struct slot *slot)
+int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
{
- struct pci_dev *dev;
- int retval = 0;
+ struct pci_dev *dev, *tmp;
- list_for_each_entry(dev, slot->dev.pci_devs, bus_list)
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
rpaphp_eeh_remove_bus_device(dev);
-
- pci_remove_behind_bridge(slot->bridge);
- slot->state = NOT_CONFIGURED;
- info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
- slot->name);
- return retval;
+ pci_remove_bus_device(dev);
+ }
+ return 0;
}
static int setup_pci_hotplug_slot_info(struct slot *slot)
@@ -356,66 +348,41 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
return 0;
}
-static int set_phb_slot_name(struct slot *slot)
+static void set_slot_name(struct slot *slot)
{
- struct device_node *dn;
- struct pci_controller *phb;
- struct pci_bus *bus;
+ struct pci_bus *bus = slot->bus;
+ struct pci_dev *bridge;
- dn = slot->dn;
- if (!dn) {
- return -EINVAL;
- }
- phb = dn->phb;
- if (!phb) {
- return -EINVAL;
- }
- bus = phb->bus;
- if (!bus) {
- return -EINVAL;
- }
-
- sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus),
- bus->number, 0, 0);
- return 0;
+ bridge = bus->self;
+ if (bridge)
+ strcpy(slot->name, pci_name(bridge));
+ else
+ sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
+ bus->number);
}
static int setup_pci_slot(struct slot *slot)
{
+ struct device_node *dn = slot->dn;
struct pci_bus *bus;
- int rc;
-
- if (slot->type == PHB) {
- rc = set_phb_slot_name(slot);
- if (rc < 0) {
- err("%s: failed to set phb slot name\n", __FUNCTION__);
- goto exit_rc;
- }
- } else {
- slot->bridge = rpaphp_find_bridge_pdev(slot);
- if (!slot->bridge) {
- /* slot being added doesn't have pci_dev yet */
- err("%s: no pci_dev for bridge dn %s\n",
- __FUNCTION__, slot->name);
- goto exit_rc;
- }
-
- bus = slot->bridge->subordinate;
- if (!bus)
- goto exit_rc;
- slot->dev.pci_devs = &bus->devices;
- dbg("%s set slot->name to %s\n", __FUNCTION__,
- pci_name(slot->bridge));
- strcpy(slot->name, pci_name(slot->bridge));
+ BUG_ON(!dn);
+ bus = rpaphp_find_pci_bus(dn);
+ if (!bus) {
+ err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
+ goto exit_rc;
}
+ slot->bus = bus;
+ slot->pci_devs = &bus->devices;
+ set_slot_name(slot);
+
/* find slot's pci_dev if it's not empty */
if (slot->hotplug_slot->info->adapter_status == EMPTY) {
slot->state = EMPTY; /* slot is empty */
} else {
/* slot is occupied */
- if (!(slot->dn->child)) {
+ if (!dn->child) {
/* non-empty slot has to have child */
err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
__FUNCTION__, slot->name);
@@ -425,7 +392,7 @@ static int setup_pci_slot(struct slot *slot)
if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
dbg("%s CONFIGURING pci adapter in slot[%s]\n",
__FUNCTION__, slot->name);
- if (rpaphp_config_pci_adapter(slot)) {
+ if (rpaphp_config_pci_adapter(slot->bus)) {
err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
goto exit_rc;
}
@@ -435,8 +402,8 @@ static int setup_pci_slot(struct slot *slot)
__FUNCTION__, slot->name);
goto exit_rc;
}
- print_slot_pci_funcs(slot);
- if (!list_empty(slot->dev.pci_devs)) {
+ print_slot_pci_funcs(slot->bus);
+ if (!list_empty(slot->pci_devs)) {
slot->state = CONFIGURED;
} else {
/* DLPAR add as opposed to
@@ -454,11 +421,6 @@ int register_pci_slot(struct slot *slot)
{
int rc = -EINVAL;
- slot->dev_type = PCI_DEV;
- if ((slot->type == EMBEDDED) || (slot->type == PHB))
- slot->removable = 0;
- else
- slot->removable = 1;
if (setup_pci_hotplug_slot_info(slot))
goto exit_rc;
if (setup_pci_slot(slot))
@@ -479,7 +441,7 @@ int rpaphp_enable_pci_slot(struct slot *slot)
/* if slot is not empty, enable the adapter */
if (state == PRESENT) {
dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
- retval = rpaphp_config_pci_adapter(slot);
+ retval = rpaphp_config_pci_adapter(slot->bus);
if (!retval) {
slot->state = CONFIGURED;
dbg("%s: PCI devices in slot[%s] has been configured\n",
@@ -502,37 +464,3 @@ exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
}
-
-struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev)
-{
- struct list_head *tmp, *n;
- struct slot *slot;
-
- list_for_each_safe(tmp, n, &rpaphp_slot_head) {
- struct pci_bus *bus;
- struct list_head *ln;
-
- slot = list_entry(tmp, struct slot, rpaphp_slot_list);
- if (slot->bridge == NULL) {
- if (slot->dev_type == PCI_DEV) {
- printk(KERN_WARNING "PCI slot missing bridge %s %s \n",
- slot->name, slot->location);
- }
- continue;
- }
-
- bus = slot->bridge->subordinate;
- if (!bus) {
- continue; /* should never happen? */
- }
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev == dev)
- return slot->hotplug_slot;
- }
- }
-
- return NULL;
-}
-
-EXPORT_SYMBOL_GPL(rpaphp_find_hotplug_slot);
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index ff2cbf0652d8..daa89ae57123 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -27,38 +27,12 @@
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
#include <asm/rtas.h>
#include "rpaphp.h"
-static ssize_t removable_read_file (struct hotplug_slot *php_slot, char *buf)
-{
- u8 value;
- int retval = -ENOENT;
- struct slot *slot = (struct slot *)php_slot->private;
-
- if (!slot)
- return retval;
-
- value = slot->removable;
- retval = sprintf (buf, "%d\n", value);
- return retval;
-}
-
-static struct hotplug_slot_attribute hotplug_slot_attr_removable = {
- .attr = {.name = "phy_removable", .mode = S_IFREG | S_IRUGO},
- .show = removable_read_file,
-};
-
-static void rpaphp_sysfs_add_attr_removable (struct hotplug_slot *slot)
-{
- sysfs_create_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
-}
-
-static void rpaphp_sysfs_remove_attr_removable (struct hotplug_slot *slot)
-{
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
-}
-
static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
{
char *value;
@@ -176,9 +150,6 @@ int deregister_slot(struct slot *slot)
/* remove "phy_location" file */
rpaphp_sysfs_remove_attr_location(php_slot);
- /* remove "phy_removable" file */
- rpaphp_sysfs_remove_attr_removable(php_slot);
-
retval = pci_hp_deregister(php_slot);
if (retval)
err("Problem unregistering a slot %s\n", slot->name);
@@ -212,21 +183,13 @@ int register_slot(struct slot *slot)
/* create "phy_locatoin" file */
rpaphp_sysfs_add_attr_location(slot->hotplug_slot);
- /* create "phy_removable" file */
- rpaphp_sysfs_add_attr_removable(slot->hotplug_slot);
-
/* add slot to our internal list */
dbg("%s adding slot[%s] to rpaphp_slot_list\n",
__FUNCTION__, slot->name);
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-
- if (slot->dev_type == VIO_DEV)
- info("Slot [%s](VIO location=%s) registered\n",
- slot->name, slot->location);
- else
- info("Slot [%s](PCI location=%s) registered\n",
- slot->name, slot->location);
+ info("Slot [%s](PCI location=%s) registered\n", slot->name,
+ slot->location);
num_slots++;
return 0;
}
@@ -235,21 +198,17 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value)
{
int rc = 0, level;
- if (slot->type == HOTPLUG) {
- rc = rtas_get_power_level(slot->power_domain, &level);
- if (!rc) {
- dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
- __FUNCTION__, slot->name, slot->power_domain, level);
- *value = level;
- } else
- err("failed to get power-level for slot(%s), rc=0x%x\n",
- slot->location, rc);
- } else {
- dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n",
- __FUNCTION__, slot->location);
- *value = (u8) POWER_ON;
+ rc = rtas_get_power_level(slot->power_domain, &level);
+ if (rc < 0) {
+ err("failed to get power-level for slot(%s), rc=0x%x\n",
+ slot->location, rc);
+ return rc;
}
+ dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
+ __FUNCTION__, slot->name, slot->power_domain, level);
+ *value = level;
+
return rc;
}
diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
deleted file mode 100644
index 74df6a305e64..000000000000
--- a/drivers/pci/hotplug/rpaphp_vio.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * RPA Hot Plug Virtual I/O device functions
- * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <lxie@us.ibm.com>
- *
- */
-#include <asm/vio.h>
-#include "rpaphp.h"
-
-/*
- * get_vio_adapter_status - get the status of a slot
- *
- * status:
- *
- * 1-- adapter is configured
- * 2-- adapter is not configured
- * 3-- not valid
- */
-inline int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 *value)
-{
- *value = slot->state;
- return 0;
-}
-
-int rpaphp_unconfig_vio_adapter(struct slot *slot)
-{
- int retval = 0;
-
- dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
- if (!slot->dev.vio_dev) {
- info("%s: no VIOA in slot[%s]\n", __FUNCTION__, slot->name);
- retval = -EINVAL;
- goto exit;
- }
- /* remove the device from the vio core */
- vio_unregister_device(slot->dev.vio_dev);
- slot->state = NOT_CONFIGURED;
- info("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, slot->name);
-exit:
- dbg("Exit %s, rc=0x%x\n", __FUNCTION__, retval);
- return retval;
-}
-
-static int setup_vio_hotplug_slot_info(struct slot *slot)
-{
- slot->hotplug_slot->info->power_status = 1;
- rpaphp_get_vio_adapter_status(slot, 1,
- &slot->hotplug_slot->info->adapter_status);
- return 0;
-}
-
-int register_vio_slot(struct device_node *dn)
-{
- u32 *index;
- char *name;
- int rc = -EINVAL;
- struct slot *slot = NULL;
-
- rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
- if (rc < 0)
- goto exit_rc;
- index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL);
- if (!index)
- goto exit_rc;
- if (!(slot = alloc_slot_struct(dn, *index, name, 0))) {
- rc = -ENOMEM;
- goto exit_rc;
- }
- slot->dev_type = VIO_DEV;
- slot->dev.vio_dev = vio_find_node(dn);
- if (slot->dev.vio_dev) {
- /*
- * rpaphp is the only owner of vio devices and
- * does not need extra reference taken by
- * vio_find_node
- */
- put_device(&slot->dev.vio_dev->dev);
- } else
- slot->dev.vio_dev = vio_register_device_node(dn);
- if (slot->dev.vio_dev)
- slot->state = CONFIGURED;
- else
- slot->state = NOT_CONFIGURED;
- if (setup_vio_hotplug_slot_info(slot))
- goto exit_rc;
- strcpy(slot->name, slot->dev.vio_dev->dev.bus_id);
- info("%s: registered VIO device[name=%s vio_dev=%p]\n",
- __FUNCTION__, slot->name, slot->dev.vio_dev);
- rc = register_slot(slot);
-exit_rc:
- if (rc && slot)
- dealloc_slot_struct(slot);
- return (rc);
-}
-
-int rpaphp_enable_vio_slot(struct slot *slot)
-{
- int retval = 0;
-
- if ((slot->dev.vio_dev = vio_register_device_node(slot->dn))) {
- info("%s: VIO adapter %s in slot[%s] has been configured\n",
- __FUNCTION__, slot->dn->name, slot->name);
- slot->state = CONFIGURED;
- } else {
- info("%s: no vio_dev struct for adapter in slot[%s]\n",
- __FUNCTION__, slot->name);
- slot->state = NOT_CONFIGURED;
- }
-
- return retval;
-}
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 323041fd41dc..a32ae82e5922 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -32,14 +32,15 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
-#define PCIIO_ASIC_TYPE_TIOCA 4
-#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
-#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
-#define PCI_L1_ERR 7 /* L1 console command error */
-#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
-#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
-#define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */
-#define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */
+#define PCIIO_ASIC_TYPE_TIOCA 4
+#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
+#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
+#define PCI_L1_ERR 7 /* L1 console command error */
+#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
+#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
+#define SN_MAX_HP_SLOTS 32 /* max hotplug slots */
+#define SGI_HOTPLUG_PROM_REV 0x0430 /* Min. required PROM version */
+#define SN_SLOT_NAME_SIZE 33 /* size of name string */
/* internal list head */
static struct list_head sn_hp_list;
@@ -51,6 +52,7 @@ struct slot {
/* this struct for glue internal only */
struct hotplug_slot *hotplug_slot;
struct list_head hp_list;
+ char physical_path[SN_SLOT_NAME_SIZE];
};
struct pcibr_slot_enable_resp {
@@ -70,7 +72,7 @@ enum sn_pci_req_e {
static int enable_slot(struct hotplug_slot *slot);
static int disable_slot(struct hotplug_slot *slot);
-static int get_power_status(struct hotplug_slot *slot, u8 *value);
+static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
static struct hotplug_slot_ops sn_hotplug_slot_ops = {
.owner = THIS_MODULE,
@@ -81,6 +83,21 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
static DECLARE_MUTEX(sn_hotplug_sem);
+static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
+ char *buf)
+{
+ int retval = -ENOENT;
+ struct slot *slot = bss_hotplug_slot->private;
+
+ if (!slot)
+ return retval;
+
+ retval = sprintf (buf, "%s\n", slot->physical_path);
+ return retval;
+}
+
+static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
+
static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
{
struct pcibus_info *pcibus_info;
@@ -120,15 +137,15 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus)
/* Only register slots in I/O Bricks that support hotplug */
bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
switch (bricktype) {
- case L1_BRICKTYPE_IX:
- case L1_BRICKTYPE_PX:
- case L1_BRICKTYPE_IA:
- case L1_BRICKTYPE_PA:
- return 1;
- break;
- default:
- return -EPERM;
- break;
+ case L1_BRICKTYPE_IX:
+ case L1_BRICKTYPE_PX:
+ case L1_BRICKTYPE_IA:
+ case L1_BRICKTYPE_PA:
+ return 1;
+ break;
+ default:
+ return -EPERM;
+ break;
}
return -EIO;
@@ -142,13 +159,12 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
- bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
- GFP_KERNEL);
- if (!bss_hotplug_slot->private)
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
return -ENOMEM;
- slot = (struct slot *)bss_hotplug_slot->private;
+ bss_hotplug_slot->private = slot;
- bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
+ bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL);
if (!bss_hotplug_slot->name) {
kfree(bss_hotplug_slot->private);
return -ENOMEM;
@@ -156,16 +172,16 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
slot->device_num = device;
slot->pci_bus = pci_bus;
-
- sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
+ sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
+ pci_domain_nr(pci_bus),
+ ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
+ device + 1);
+ sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
'0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
'0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
'0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
- MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
- ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
- device + 1);
-
+ MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
slot->hotplug_slot = bss_hotplug_slot;
list_add(&slot->hp_list, &sn_hp_list);
@@ -175,14 +191,14 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
static struct hotplug_slot * sn_hp_destroy(void)
{
struct slot *slot;
- struct list_head *list;
struct hotplug_slot *bss_hotplug_slot = NULL;
- list_for_each(list, &sn_hp_list) {
- slot = list_entry(list, struct slot, hp_list);
+ list_for_each_entry(slot, &sn_hp_list, hp_list) {
bss_hotplug_slot = slot->hotplug_slot;
list_del(&((struct slot *)bss_hotplug_slot->private)->
hp_list);
+ sysfs_remove_file(&bss_hotplug_slot->kobj,
+ &sn_slot_path_attr.attr);
break;
}
return bss_hotplug_slot;
@@ -190,7 +206,6 @@ static struct hotplug_slot * sn_hp_destroy(void)
static void sn_bus_alloc_data(struct pci_dev *dev)
{
- struct list_head *node;
struct pci_bus *subordinate_bus;
struct pci_dev *child;
@@ -199,66 +214,29 @@ static void sn_bus_alloc_data(struct pci_dev *dev)
/* Recursively sets up the sn_irq_info structs */
if (dev->subordinate) {
subordinate_bus = dev->subordinate;
- list_for_each(node, &subordinate_bus->devices) {
- child = list_entry(node, struct pci_dev, bus_list);
+ list_for_each_entry(child, &subordinate_bus->devices, bus_list)
sn_bus_alloc_data(child);
- }
}
}
static void sn_bus_free_data(struct pci_dev *dev)
{
- struct list_head *node;
struct pci_bus *subordinate_bus;
struct pci_dev *child;
/* Recursively clean up sn_irq_info structs */
if (dev->subordinate) {
subordinate_bus = dev->subordinate;
- list_for_each(node, &subordinate_bus->devices) {
- child = list_entry(node, struct pci_dev, bus_list);
+ list_for_each_entry(child, &subordinate_bus->devices, bus_list)
sn_bus_free_data(child);
- }
}
sn_pci_unfixup_slot(dev);
}
-static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
- u8 retval;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
-
- return retval ? 1 : 0;
-}
-
-static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
- int device_num)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices |= (1 << device_num);
-}
-
-static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
- int device_num)
-{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
- struct pcibus_info *pcibus_info;
-
- pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
-}
-
static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
int device_num)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pcibus_info *pcibus_info;
struct pcibr_slot_enable_resp resp;
int rc;
@@ -273,7 +251,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
if (rc == PCI_SLOT_ALREADY_UP) {
dev_dbg(slot->pci_bus->self, "is already active\n");
- return -EPERM;
+ return 1; /* return 1 to user */
}
if (rc == PCI_L1_ERR) {
@@ -290,7 +268,8 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
return -EIO;
}
- sn_slot_mark_enable(bss_hotplug_slot, device_num);
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+ pcibus_info->pbi_enabled_devices |= (1 << device_num);
return 0;
}
@@ -298,7 +277,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
int device_num, int action)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pcibus_info *pcibus_info;
struct pcibr_slot_disable_resp resp;
int rc;
@@ -307,43 +286,44 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) &&
+ (rc == PCI_SLOT_ALREADY_DOWN)) {
dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
- return -ENODEV;
+ return 1; /* return 1 to user */
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) {
dev_dbg(slot->pci_bus->self,
"Cannot remove last 33MHz card\n");
return -EPERM;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) {
dev_dbg(slot->pci_bus->self,
"L1 failure %d with message \n%s\n",
resp.resp_sub_errno, resp.resp_l1_msg);
return -EPERM;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) {
dev_dbg(slot->pci_bus->self,
"remove failed with error %d sub-error %d\n",
rc, resp.resp_sub_errno);
return -EIO;
}
- if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
+ if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc)
return 0;
- if (action == PCI_REQ_SLOT_DISABLE && !rc) {
- sn_slot_mark_disable(bss_hotplug_slot, device_num);
+ if ((action == PCI_REQ_SLOT_DISABLE) && !rc) {
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+ pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
dev_dbg(slot->pci_bus->self, "remove successful\n");
return 0;
}
- if (action == PCI_REQ_SLOT_DISABLE && rc) {
+ if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
- return rc;
}
return rc;
@@ -351,7 +331,7 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pci_bus *new_bus = NULL;
struct pci_dev *dev;
int func, num_funcs;
@@ -371,8 +351,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
return rc;
}
- num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
- PCI_FUNC(0)));
+ num_funcs = pci_scan_slot(slot->pci_bus,
+ PCI_DEVFN(slot->device_num + 1, 0));
if (!num_funcs) {
dev_dbg(slot->pci_bus->self, "no device in slot\n");
up(&sn_hotplug_sem);
@@ -391,8 +371,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
-
-
if (dev) {
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
unsigned char sec_bus;
@@ -431,7 +409,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
{
- struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+ struct slot *slot = bss_hotplug_slot->private;
struct pci_dev *dev;
int func;
int rc;
@@ -448,7 +426,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
/* Free the SN resources assigned to the Linux device.*/
for (func = 0; func < 8; func++) {
dev = pci_get_slot(slot->pci_bus,
- PCI_DEVFN(slot->device_num+1,
+ PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
/*
@@ -477,10 +455,15 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
return rc;
}
-static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
+static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
+ u8 *value)
{
+ struct slot *slot = bss_hotplug_slot->private;
+ struct pcibus_info *pcibus_info;
+
+ pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
down(&sn_hotplug_sem);
- *value = sn_power_status_get(bss_hotplug_slot);
+ *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
up(&sn_hotplug_sem);
return 0;
}
@@ -508,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
if (sn_pci_slot_valid(pci_bus, device) != 1)
continue;
- bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
+ bss_hotplug_slot = kzalloc(sizeof(*bss_hotplug_slot),
GFP_KERNEL);
if (!bss_hotplug_slot) {
rc = -ENOMEM;
@@ -516,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
}
bss_hotplug_slot->info =
- kcalloc(1,sizeof(struct hotplug_slot_info),
+ kzalloc(sizeof(struct hotplug_slot_info),
GFP_KERNEL);
if (!bss_hotplug_slot->info) {
rc = -ENOMEM;
@@ -535,6 +518,11 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
rc = pci_hp_register(bss_hotplug_slot);
if (rc)
goto register_err;
+
+ rc = sysfs_create_file(&bss_hotplug_slot->kobj,
+ &sn_slot_path_attr.attr);
+ if (rc)
+ goto register_err;
}
dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
return rc;
@@ -564,14 +552,14 @@ static int sn_pci_hotplug_init(void)
int rc;
int registered = 0;
- INIT_LIST_HEAD(&sn_hp_list);
-
if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
- printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
+ printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
__FUNCTION__);
return -EPERM;
}
+ INIT_LIST_HEAD(&sn_hp_list);
+
while ((pci_bus = pci_find_next_bus(pci_bus))) {
if (!pci_bus->sysdata)
continue;
@@ -584,9 +572,9 @@ static int sn_pci_hotplug_init(void)
dev_dbg(pci_bus->self, "valid hotplug bus\n");
rc = sn_hotplug_slot_register(pci_bus);
- if (!rc)
+ if (!rc) {
registered = 1;
- else {
+ } else {
registered = 0;
break;
}
@@ -599,9 +587,8 @@ static void sn_pci_hotplug_exit(void)
{
struct hotplug_slot *bss_hotplug_slot;
- while ((bss_hotplug_slot = sn_hp_destroy())) {
+ while ((bss_hotplug_slot = sn_hp_destroy()))
pci_hp_deregister(bss_hotplug_slot);
- }
if (!list_empty(&sn_hp_list))
printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 67b6a3370ceb..08ad26a0cae7 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
*
*/
#ifndef _SHPCHP_H
@@ -32,8 +32,8 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
+#include <linux/sched.h> /* signal_pending(), struct timer_list */
+
#include "pci_hotplug.h"
#if !defined(MODULE)
@@ -52,42 +52,18 @@ extern int shpchp_debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-struct pci_func {
- struct pci_func *next;
- u8 bus;
- u8 device;
- u8 function;
- u8 is_a_board;
- u16 status;
- u8 configured;
- u8 switch_save;
- u8 presence_save;
- u8 pwr_save;
- u32 base_length[0x06];
- u8 base_type[0x06];
- u16 reserved2;
- u32 config_space[0x20];
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct pci_dev* pci_dev;
-};
-
#define SLOT_MAGIC 0x67267321
struct slot {
u32 magic;
struct slot *next;
u8 bus;
u8 device;
+ u16 status;
u32 number;
u8 is_a_board;
- u8 configured;
u8 state;
- u8 switch_save;
u8 presence_save;
- u32 capabilities;
- u16 reserved2;
+ u8 pwr_save;
struct timer_list task_event;
u8 hp_slot;
struct controller *ctrl;
@@ -96,12 +72,6 @@ struct slot {
struct list_head slot_list;
};
-struct pci_resource {
- struct pci_resource * next;
- u32 base;
- u32 length;
-};
-
struct event_info {
u32 event_type;
u8 hp_slot;
@@ -110,13 +80,9 @@ struct event_info {
struct controller {
struct controller *next;
struct semaphore crit_sect; /* critical section semaphore */
- void * hpc_ctlr_handle; /* HPC controller handle */
+ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
struct pci_dev *pci_dev;
struct pci_bus *pci_bus;
struct event_info event_queue[10];
@@ -124,33 +90,21 @@ struct controller {
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
u8 next_event;
- u8 seg;
u8 bus;
u8 device;
u8 function;
- u8 rev;
u8 slot_device_offset;
u8 add_support;
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
- u8 push_flag;
- u16 ctlrcap;
- u16 vendor_id;
-};
-
-struct irq_mapping {
- u8 barber_pole;
- u8 valid_INT;
- u8 interrupt[4];
};
-struct resource_lists {
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct irq_mapping *irqs;
+struct hotplug_params {
+ u8 cache_line_size;
+ u8 latency_timer;
+ u8 enable_serr;
+ u8 enable_perr;
};
/* Define AMD SHPC ID */
@@ -194,24 +148,16 @@ struct resource_lists {
* error Messages
*/
#define msg_initialization_err "Initialization failure, error=%d\n"
-#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
-#define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
-#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
/* sysfs functions for the hotplug controller info */
extern void shpchp_create_ctrl_files (struct controller *ctrl);
/* controller functions */
-extern int shpchprm_find_available_resources(struct controller *ctrl);
extern int shpchp_event_start_thread(void);
extern void shpchp_event_stop_thread(void);
-extern struct pci_func *shpchp_slot_create(unsigned char busnumber);
-extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
extern int shpchp_enable_slot(struct slot *slot);
extern int shpchp_disable_slot(struct slot *slot);
@@ -220,29 +166,20 @@ extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
-/* resource functions */
-extern int shpchp_resource_sort_and_combine(struct pci_resource **head);
-
/* pci functions */
-extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
-extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
-extern void shpchp_destroy_board_resources(struct pci_func * func);
-extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
-extern void shpchp_destroy_resource_list(struct resource_lists * resources);
-extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
-extern int shpchp_unconfigure_device(struct pci_func* func);
+extern int shpchp_configure_device(struct slot *p_slot);
+extern int shpchp_unconfigure_device(struct slot *p_slot);
+extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
+extern void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
+ u32 *sun, u8 busnum, u8 devnum);
+extern void shpchp_remove_ctrl_files(struct controller *ctrl);
/* Global variables */
extern struct controller *shpchp_ctrl_list;
-extern struct pci_func *shpchp_slot_list[256];
-
-/* These are added to support AMD shpc */
-extern u8 shpchp_nic_irq;
-extern u8 shpchp_disk_irq;
struct ctrl_reg {
volatile u32 base_offset;
@@ -298,7 +235,7 @@ enum ctrl_offsets {
SLOT11 = offsetof(struct ctrl_reg, slot11),
SLOT12 = offsetof(struct ctrl_reg, slot12),
};
-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
struct php_ctlr_state_s {
struct php_ctlr_state_s *pnext;
struct pci_dev *pci_dev;
@@ -359,12 +296,9 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
p_slot = ctrl->slot;
- dbg("p_slot = %p\n", p_slot);
-
while (p_slot && (p_slot->device != device)) {
tmp_slot = p_slot;
p_slot = p_slot->next;
- dbg("In while loop, p_slot = %p\n", p_slot);
}
if (p_slot == NULL) {
err("ERROR: shpchp_find_slot device=0x%x\n", device);
@@ -379,8 +313,6 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
DECLARE_WAITQUEUE(wait, current);
int retval = 0;
- dbg("%s : start\n",__FUNCTION__);
-
add_wait_queue(&ctrl->queue, &wait);
if (!shpchp_poll_mode) {
@@ -394,24 +326,14 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
if (signal_pending(current))
retval = -EINTR;
- dbg("%s : end\n", __FUNCTION__);
return retval;
}
-/* Puts node back in the resource list pointed to by head */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
-{
- if (!node || !head)
- return;
- node->next = *head;
- *head = node;
-}
-
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
- snprintf(buffer, buffer_size, "%d", slot->number);
+ snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
}
enum php_ctlr_type {
@@ -420,11 +342,7 @@ enum php_ctlr_type {
ACPI
};
-int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
int shpc_get_ctlr_slot_config( struct controller *ctrl,
int *num_ctlr_slots,
@@ -437,8 +355,6 @@ struct hpc_ops {
int (*power_on_slot ) (struct slot *slot);
int (*slot_enable ) (struct slot *slot);
int (*slot_disable ) (struct slot *slot);
- int (*enable_all_slots) (struct slot *slot);
- int (*pwr_on_all_slots) (struct slot *slot);
int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed);
int (*get_power_status) (struct slot *slot, u8 *status);
int (*get_attention_status) (struct slot *slot, u8 *status);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a70a5c5705f2..63628e01dd43 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -23,30 +23,22 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
#include "shpchp.h"
-#include "shpchprm.h"
/* Global variables */
int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
struct controller *shpchp_ctrl_list; /* = NULL */
-struct pci_func *shpchp_slot_list[256];
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -113,8 +105,6 @@ static int init_slots(struct controller *ctrl)
u32 slot_number, sun;
int result = -ENOMEM;
- dbg("%s\n",__FUNCTION__);
-
number_of_slots = ctrl->num_slots;
slot_device = ctrl->slot_device_offset;
slot_number = ctrl->first_slot;
@@ -352,6 +342,17 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
return 0;
}
+static int is_shpc_capable(struct pci_dev *dev)
+{
+ if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
+ PCI_DEVICE_ID_AMD_GOLAM_7450))
+ return 1;
+ if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
+ return 1;
+
+ return 0;
+}
+
static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc;
@@ -360,6 +361,9 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int first_device_num; /* first PCI device number supported by this SHPC */
int num_ctlr_slots; /* number of slots supported by this SHPC */
+ if (!is_shpc_capable(pdev))
+ return -ENODEV;
+
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
@@ -367,19 +371,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
memset(ctrl, 0, sizeof(struct controller));
- dbg("DRV_thread pid = %d\n", current->pid);
-
- rc = shpc_init(ctrl, pdev,
- (php_intr_callback_t) shpchp_handle_attention_button,
- (php_intr_callback_t) shpchp_handle_switch_change,
- (php_intr_callback_t) shpchp_handle_presence_change,
- (php_intr_callback_t) shpchp_handle_power_fault);
+ rc = shpc_init(ctrl, pdev);
if (rc) {
dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
goto err_out_free_ctrl;
}
- dbg("%s: controller initialization success\n", __FUNCTION__);
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
pci_set_drvdata(pdev, ctrl);
@@ -411,23 +408,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
first_device_num = ctrl->slot_device_offset;
num_ctlr_slots = ctrl->num_slots;
- /* Store PCI Config Space for all devices on this bus */
- rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
- if (rc) {
- err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
- goto err_out_free_ctrl_bus;
- }
-
- /* Get IO, memory, and IRQ resources for new devices */
- rc = shpchprm_find_available_resources(ctrl);
- ctrl->add_support = !rc;
+ ctrl->add_support = 1;
- if (rc) {
- dbg("shpchprm_find_available_resources = %#x\n", rc);
- err("unable to locate PCI configuration resources for hot plug add.\n");
- goto err_out_free_ctrl_bus;
- }
-
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
@@ -477,7 +459,6 @@ err_out_none:
static int shpc_start_thread(void)
{
- int loop;
int retval = 0;
dbg("Initialize + Start the notification/polling mechanism \n");
@@ -488,48 +469,21 @@ static int shpc_start_thread(void)
return retval;
}
- dbg("Initialize slot lists\n");
- /* One slot list for each bus in the system */
- for (loop = 0; loop < 256; loop++) {
- shpchp_slot_list[loop] = NULL;
- }
-
return retval;
}
-static inline void __exit
-free_shpchp_res(struct pci_resource *res)
-{
- struct pci_resource *tres;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
static void __exit unload_shpchpd(void)
{
- struct pci_func *next;
- struct pci_func *TempSlot;
- int loop;
struct controller *ctrl;
struct controller *tctrl;
ctrl = shpchp_ctrl_list;
while (ctrl) {
+ shpchp_remove_ctrl_files(ctrl);
cleanup_slots(ctrl);
- free_shpchp_res(ctrl->io_head);
- free_shpchp_res(ctrl->mem_head);
- free_shpchp_res(ctrl->p_mem_head);
- free_shpchp_res(ctrl->bus_head);
-
kfree (ctrl->pci_bus);
-
- dbg("%s: calling release_ctlr\n", __FUNCTION__);
ctrl->hpc_ops->release_ctlr(ctrl);
tctrl = ctrl;
@@ -538,20 +492,6 @@ static void __exit unload_shpchpd(void)
kfree(tctrl);
}
- for (loop = 0; loop < 256; loop++) {
- next = shpchp_slot_list[loop];
- while (next != NULL) {
- free_shpchp_res(next->io_head);
- free_shpchp_res(next->mem_head);
- free_shpchp_res(next->p_mem_head);
- free_shpchp_res(next->bus_head);
-
- TempSlot = next;
- next = next->next;
- kfree(TempSlot);
- }
- }
-
/* Stop the notification mechanism */
shpchp_event_stop_thread();
@@ -596,20 +536,14 @@ static int __init shpcd_init(void)
if (retval)
goto error_hpc_init;
- retval = shpchprm_init(PCI);
- if (!retval) {
- retval = pci_register_driver(&shpc_driver);
- dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- }
+ retval = pci_register_driver(&shpc_driver);
+ dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
error_hpc_init:
if (retval) {
- shpchprm_cleanup();
shpchp_event_stop_thread();
- } else
- shpchprm_print_pirt();
-
+ }
return retval;
}
@@ -618,9 +552,6 @@ static void __exit shpcd_cleanup(void)
dbg("unload_shpchpd()\n");
unload_shpchpd();
- shpchprm_cleanup();
-
- dbg("pci_unregister_driver\n");
pci_unregister_driver(&shpc_driver);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 490a9553a062..58619359ad08 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -23,28 +23,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <linux/pci.h>
+#include "../pci.h"
#include "shpchp.h"
-#include "shpchprm.h"
-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
static void interrupt_event_handler(struct controller *ctrl);
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
@@ -52,28 +42,22 @@ static struct semaphore event_exit; /* guard ensure thread has exited before ca
static int event_finished;
static unsigned long pushbutton_pending; /* = 0 */
-u8 shpchp_disk_irq;
-u8 shpchp_nic_irq;
-
u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
{
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Attention Button Change */
dbg("shpchp: Attention button interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread what to do */
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
ctrl->next_event = (ctrl->next_event + 1) % 10;
@@ -118,14 +102,11 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Switch Change */
dbg("shpchp: Switch interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -135,19 +116,18 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
rc++;
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
- func->presence_save, func->pwr_save);
+ p_slot->presence_save, p_slot->pwr_save);
if (getstatus) {
/*
* Switch opened
*/
info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0;
taskInfo->event_type = INT_SWITCH_OPEN;
- if (func->pwr_save && func->presence_save) {
+ if (p_slot->pwr_save && p_slot->presence_save) {
taskInfo->event_type = INT_POWER_FAULT;
err("Surprise Removal of card\n");
}
@@ -156,7 +136,6 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
* Switch closed
*/
info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0x10;
taskInfo->event_type = INT_SWITCH_CLOSE;
}
@@ -172,14 +151,11 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
/*u8 temp_byte;*/
- struct pci_func *func;
struct event_info *taskInfo;
/* Presence Change */
dbg("shpchp: Presence/Notify input change.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -193,8 +169,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
/*
* Save the presence state
*/
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
- if (func->presence_save) {
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ if (p_slot->presence_save) {
/*
* Card Present
*/
@@ -219,14 +195,11 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 rc = 0;
- struct pci_func *func;
struct event_info *taskInfo;
/* Power fault */
dbg("shpchp: Power fault interrupt received.\n");
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
@@ -242,7 +215,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
* Power fault Cleared
*/
info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->status = 0x00;
+ p_slot->status = 0x00;
taskInfo->event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
@@ -251,7 +224,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
taskInfo->event_type = INT_POWER_FAULT;
/* set power fault status for this board */
- func->status = 0xFF;
+ p_slot->status = 0xFF;
info("power fault bit %x set\n", hp_slot);
}
if (rc)
@@ -260,799 +233,13 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
return rc;
}
-
-/*
- * sort_by_size
- *
- * Sorts nodes on the list by their length.
- * Smallest first.
- *
- */
-static int sort_by_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return(1);
-
- if (!((*head)->next))
- return(0);
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length > (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length > current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return(0);
-}
-
-
-/*
- * sort_by_max_size
- *
- * Sorts nodes on the list by their length.
- * Largest first.
- *
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return(1);
-
- if (!((*head)->next))
- return(0);
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length < (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length < current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return(0);
-}
-
-
-/*
- * do_pre_bridge_resource_split
- *
- * Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 rc;
- u32 temp_dword;
- dbg("do_pre_bridge_resource_split\n");
-
- if (!(*head) || !(*orig_head))
- return(NULL);
-
- rc = shpchp_resource_sort_and_combine(head);
-
- if (rc)
- return(NULL);
-
- if ((*head)->base != (*orig_head)->base)
- return(NULL);
-
- if ((*head)->length == (*orig_head)->length)
- return(NULL);
-
-
- /* If we got here, there the bridge requires some of the resource, but
- * we may be able to split some off of the front
- */
- node = *head;
-
- if (node->length & (alignment -1)) {
- /* This one isn't an aligned length, so we'll make a new entry
- * and split it up.
- */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- temp_dword = (node->length | (alignment-1)) + 1 - alignment;
-
- split_node->base = node->base;
- split_node->length = temp_dword;
-
- node->length -= temp_dword;
- node->base += split_node->length;
-
- /* Put it in the list */
- *head = split_node;
- split_node->next = node;
- }
-
- if (node->length < alignment) {
- return(NULL);
- }
-
- /* Now unlink it */
- if (*head == node) {
- *head = node->next;
- node->next = NULL;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- node->next = NULL;
- }
-
- return(node);
-}
-
-
-/*
- * do_bridge_resource_split
- *
- * Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- u32 rc;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- rc = shpchp_resource_sort_and_combine(head);
-
- if (rc)
- return(NULL);
-
- node = *head;
-
- while (node->next) {
- prevnode = node;
- node = node->next;
- kfree(prevnode);
- }
-
- if (node->length < alignment) {
- kfree(node);
- return(NULL);
- }
-
- if (node->base & (alignment - 1)) {
- /* Short circuit if adjusted size is too small */
- temp_dword = (node->base | (alignment-1)) + 1;
- if ((node->length - (temp_dword - node->base)) < alignment) {
- kfree(node);
- return(NULL);
- }
-
- node->length -= (temp_dword - node->base);
- node->base = temp_dword;
- }
-
- if (node->length & (alignment - 1)) {
- /* There's stuff in use after this node */
- kfree(node);
- return(NULL);
- }
-
- return(node);
-}
-
-
-/*
- * get_io_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window. If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node = NULL;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- if ( shpchp_resource_sort_and_combine(head) )
- return(NULL);
-
- if ( sort_by_size(head) )
- return(NULL);
-
- for (node = *head; node; node = node->next) {
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- /* This one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /*/ Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- /* This one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- /* For IO make sure it's not in the ISA aliasing space */
- if (node->base & 0x300L)
- continue;
-
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
-
- return(node);
-}
-
-
-/*
- * get_max_resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head. It aligns the node on top and bottom
- * to "size" alignment before returning it.
- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
- * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
- */
-static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *max;
- struct pci_resource *temp;
- struct pci_resource *split_node;
- u32 temp_dword;
- u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
- int i;
-
- if (!(*head))
- return(NULL);
-
- if (shpchp_resource_sort_and_combine(head))
- return(NULL);
-
- if (sort_by_max_size(head))
- return(NULL);
-
- for (max = *head;max; max = max->next) {
-
- /* If not big enough we could probably just bail,
- instead we'll continue to the next. */
- if (max->length < size)
- continue;
-
- if (max->base & (size - 1)) {
- /* This one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (max->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((max->length - (temp_dword - max->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = max->base;
- split_node->length = temp_dword - max->base;
- max->base = temp_dword;
- max->length -= split_node->length;
-
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- if ((max->base + max->length) & (size - 1)) {
- /* This one isn't end aligned properly at the top
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
- temp_dword = ((max->base + max->length) & ~(size - 1));
- split_node->base = temp_dword;
- split_node->length = max->length + max->base
- - split_node->base;
- max->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- /* Make sure it didn't shrink too much when we aligned it */
- if (max->length < size)
- continue;
-
- for ( i = 0; max_size[i] > size; i++) {
- if (max->length > max_size[i]) {
- split_node = kmalloc(sizeof(*split_node),
- GFP_KERNEL);
- if (!split_node)
- break; /* return (NULL); */
- split_node->base = max->base + max_size[i];
- split_node->length = max->length - max_size[i];
- max->length = max_size[i];
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- break;
- }
- }
-
- /* Now take it out of the list */
- temp = (struct pci_resource*) *head;
- if (temp == max) {
- *head = max->next;
- } else {
- while (temp && temp->next != max) {
- temp = temp->next;
- }
-
- temp->next = max->next;
- }
-
- max->next = NULL;
- return(max);
- }
-
- /* If we get here, we couldn't find one */
- return(NULL);
-}
-
-
-/*
- * get_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length. If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 temp_dword;
-
- if (!(*head))
- return(NULL);
-
- if ( shpchp_resource_sort_and_combine(head) )
- return(NULL);
-
- if ( sort_by_size(head) )
- return(NULL);
-
- for (node = *head; node; node = node->next) {
- dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
- __FUNCTION__, size, node, node->base, node->length);
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- dbg("%s: not aligned\n", __FUNCTION__);
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- dbg("%s: too big\n", __FUNCTION__);
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
- if (!split_node)
- return(NULL);
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- dbg("%s: got one!!!\n", __FUNCTION__);
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
- return(node);
-}
-
-
-/*
- * shpchp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses. Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int shpchp_resource_sort_and_combine(struct pci_resource **head)
-{
- struct pci_resource *node1;
- struct pci_resource *node2;
- int out_of_order = 1;
-
- dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
-
- if (!(*head))
- return(1);
-
- dbg("*head->next = %p\n",(*head)->next);
-
- if (!(*head)->next)
- return(0); /* only one item on the list, already sorted! */
-
- dbg("*head->base = 0x%x\n",(*head)->base);
- dbg("*head->next->base = 0x%x\n",(*head)->next->base);
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->base > (*head)->next->base)) {
- node1 = *head;
- (*head) = (*head)->next;
- node1->next = (*head)->next;
- (*head)->next = node1;
- out_of_order++;
- }
-
- node1 = (*head);
-
- while (node1->next && node1->next->next) {
- if (node1->next->base > node1->next->next->base) {
- out_of_order++;
- node2 = node1->next;
- node1->next = node1->next->next;
- node1 = node1->next;
- node2->next = node1->next;
- node1->next = node2;
- } else
- node1 = node1->next;
- }
- } /* End of out_of_order loop */
-
- node1 = *head;
-
- while (node1 && node1->next) {
- if ((node1->base + node1->length) == node1->next->base) {
- /* Combine */
- dbg("8..\n");
- node1->length += node1->next->length;
- node2 = node1->next;
- node1->next = node1->next->next;
- kfree(node2);
- } else
- node1 = node1->next;
- }
-
- return(0);
-}
-
-
-/**
- * shpchp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
- *
- * Returns pointer to the new node or NULL if unsuccessful
- */
-struct pci_func *shpchp_slot_create(u8 busnumber)
-{
- struct pci_func *new_slot;
- struct pci_func *next;
-
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
-
- if (new_slot == NULL) {
- return(new_slot);
- }
-
- memset(new_slot, 0, sizeof(struct pci_func));
-
- new_slot->next = NULL;
- new_slot->configured = 1;
-
- if (shpchp_slot_list[busnumber] == NULL) {
- shpchp_slot_list[busnumber] = new_slot;
- } else {
- next = shpchp_slot_list[busnumber];
- while (next->next != NULL)
- next = next->next;
- next->next = new_slot;
- }
- return(new_slot);
-}
-
-
-/*
- * slot_remove - Removes a node from the linked list of slots.
- * @old_slot: slot to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int slot_remove(struct pci_func * old_slot)
-{
- struct pci_func *next;
-
- if (old_slot == NULL)
- return(1);
-
- next = shpchp_slot_list[old_slot->bus];
-
- if (next == NULL) {
- return(1);
- }
-
- if (next == old_slot) {
- shpchp_slot_list[old_slot->bus] = old_slot->next;
- shpchp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return(0);
- }
-
- while ((next->next != old_slot) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == old_slot) {
- next->next = old_slot->next;
- shpchp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return(0);
- } else
- return(2);
-}
-
-
-/**
- * bridge_slot_remove - Removes a node from the linked list of slots.
- * @bridge: bridge to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int bridge_slot_remove(struct pci_func *bridge)
-{
- u8 subordinateBus, secondaryBus;
- u8 tempBus;
- struct pci_func *next;
-
- if (bridge == NULL)
- return(1);
-
- secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
- subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
-
- for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
- next = shpchp_slot_list[tempBus];
-
- while (!slot_remove(next)) {
- next = shpchp_slot_list[tempBus];
- }
- }
-
- next = shpchp_slot_list[bridge->bus];
-
- if (next == NULL) {
- return(1);
- }
-
- if (next == bridge) {
- shpchp_slot_list[bridge->bus] = bridge->next;
- kfree(bridge);
- return(0);
- }
-
- while ((next->next != bridge) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == bridge) {
- next->next = bridge->next;
- kfree(bridge);
- return(0);
- } else
- return(2);
-}
-
-
-/**
- * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
- * @bus: bus to find
- * @device: device to find
- * @index: is 0 for first function found, 1 for the second...
- *
- * Returns pointer to the node if successful, %NULL otherwise.
- */
-struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
-{
- int found = -1;
- struct pci_func *func;
-
- func = shpchp_slot_list[bus];
-
- if ((func == NULL) || ((func->device == device) && (index == 0)))
- return(func);
-
- if (func->device == device)
- found++;
-
- while (func->next != NULL) {
- func = func->next;
-
- if (func->device == device)
- found++;
-
- if (found == index)
- return(func);
- }
-
- return(NULL);
-}
-
-static int is_bridge(struct pci_func * func)
-{
- /* Check the header type */
- if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
- return 1;
- else
- return 0;
-}
-
-
/* The following routines constitute the bulk of the
hotplug controller logic
*/
-static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
+static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+ enum pci_bus_speed speed)
{
- u32 rc = 0;
+ int rc = 0;
dbg("%s: change to speed %d\n", __FUNCTION__, speed);
down(&ctrl->crit_sect);
@@ -1074,10 +261,11 @@ static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum p
return rc;
}
-static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag,
-enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
+static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+ u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
+ enum pci_bus_speed msp)
{
- u32 rc = 0;
+ int rc = 0;
if (flag != 0) { /* Other slots on the same bus are occupied */
if ( asp < bsp ) {
@@ -1116,23 +304,20 @@ enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
* Configures board
*
*/
-static u32 board_added(struct pci_func * func, struct controller * ctrl)
+static int board_added(struct slot *p_slot)
{
u8 hp_slot;
u8 slots_not_empty = 0;
- int index;
- u32 temp_register = 0xFFFFFFFF;
- u32 retval, rc = 0;
- struct pci_func *new_func = NULL;
- struct slot *p_slot;
- struct resource_lists res_lists;
+ int rc = 0;
enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
u8 pi, mode;
+ struct controller *ctrl = p_slot->ctrl;
- p_slot = shpchp_find_slot(ctrl, func->device);
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
- dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+ dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+ __FUNCTION__, p_slot->device,
+ ctrl->slot_device_offset, hp_slot);
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1320,143 +505,68 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
up(&ctrl->crit_sect);
/* Wait for ~1 second */
- dbg("%s: before long_delay\n", __FUNCTION__);
wait_for_ctrl_irq (ctrl);
- dbg("%s: after long_delay\n", __FUNCTION__);
- dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+ dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
/* Check for a power fault */
- if (func->status == 0xFF) {
+ if (p_slot->status == 0xFF) {
/* power fault occurred, but it was benign */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+ dbg("%s: power fault\n", __FUNCTION__);
rc = POWER_FAILURE;
- func->status = 0;
- } else {
- /* Get vendor/device ID u32 */
- rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function),
- PCI_VENDOR_ID, &temp_register);
- dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
- dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
-
- if (rc != 0) {
- /* Something's wrong here */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
- }
- /* Preset return code. It will be changed later if things go okay. */
- rc = NO_ADAPTER_PRESENT;
+ p_slot->status = 0;
+ goto err_exit;
}
- /* All F's is an empty slot or an invalid board */
- if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
- res_lists.irqs = NULL;
-
- rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
- dbg("%s: back from configure_new_device\n", __FUNCTION__);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
-
- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->io_head));
- shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- if (rc) {
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
-
- /* turn off slot, turn on Amber LED, turn off Green LED */
- retval = p_slot->hpc_ops->slot_disable(p_slot);
- if (retval) {
- err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return retval;
- }
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
- retval = p_slot->hpc_ops->check_cmd_status(ctrl);
- if (retval) {
- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return retval;
- }
-
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
+ if (shpchp_configure_device(p_slot)) {
+ err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
+ p_slot->device);
+ goto err_exit;
+ }
- return(rc);
- }
- shpchp_save_slot_config(ctrl, func);
+ p_slot->status = 0;
+ p_slot->is_a_board = 0x01;
+ p_slot->pwr_save = 1;
- func->status = 0;
- func->switch_save = 0x10;
- func->is_a_board = 0x01;
- func->pwr_save = 1;
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
- /* Next, we will instantiate the linux pci_dev structures
- * (with appropriate driver notification, if already present)
- */
- index = 0;
- do {
- new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
- if (new_func && !new_func->pci_dev) {
- dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
- shpchp_configure_device(ctrl, new_func);
- }
- } while (new_func);
+ p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
+ /* Wait for the command to complete */
+ wait_for_ctrl_irq (ctrl);
- p_slot->hpc_ops->green_led_on(p_slot);
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
+ return 0;
+err_exit:
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
+ /* turn off slot, turn on Amber LED, turn off Green LED */
+ rc = p_slot->hpc_ops->slot_disable(p_slot);
+ if (rc) {
+ err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
+ return rc;
+ }
+ /* Wait for the command to complete */
+ wait_for_ctrl_irq (ctrl);
- } else {
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
-
- /* turn off slot, turn on Amber LED, turn off Green LED */
- rc = p_slot->hpc_ops->slot_disable(p_slot);
- if (rc) {
- err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return rc;
- }
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
- rc = p_slot->hpc_ops->check_cmd_status(ctrl);
- if (rc) {
- err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- return rc;
- }
-
+ rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+ if (rc) {
+ err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
-
- return(rc);
+ return rc;
}
- return 0;
+
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+
+ return(rc);
}
@@ -1464,55 +574,23 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
* remove_board - Turns off slot and LED's
*
*/
-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+static int remove_board(struct slot *p_slot)
{
- int index;
- u8 skip = 0;
- u8 device;
+ struct controller *ctrl = p_slot->ctrl;
u8 hp_slot;
- u32 rc;
- struct resource_lists res_lists;
- struct pci_func *temp_func;
- struct slot *p_slot;
-
- if (func == NULL)
- return(1);
+ int rc;
- if (shpchp_unconfigure_device(func))
+ if (shpchp_unconfigure_device(p_slot))
return(1);
- device = func->device;
-
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
- if ((ctrl->add_support) &&
- !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
- /* Here we check to see if we've saved any of the board's
- * resources already. If so, we'll skip the attempt to
- * determine what's being used.
- */
- index = 0;
-
- temp_func = func;
-
- while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) {
- if (temp_func->bus_head || temp_func->mem_head
- || temp_func->p_mem_head || temp_func->io_head) {
- skip = 1;
- break;
- }
- }
-
- if (!skip)
- rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
- }
/* Change status to shutdown */
- if (func->is_a_board)
- func->status = 0x01;
- func->configured = 0;
+ if (p_slot->is_a_board)
+ p_slot->status = 0x01;
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1549,55 +627,8 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
- if (ctrl->add_support) {
- while (func) {
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
-
- dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus,
- func->device, func->function);
-
- shpchp_return_board_resources(func, &res_lists);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
-
- shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- shpchp_resource_sort_and_combine(&(ctrl->io_head));
- shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- if (is_bridge(func)) {
- dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
- func->device, func->function);
- bridge_slot_remove(func);
- } else
- dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
- func->device, func->function);
- slot_remove(func);
-
- func = shpchp_slot_find(ctrl->slot_bus, device, 0);
- }
-
- /* Setup slot structure with entry for empty slot */
- func = shpchp_slot_create(ctrl->slot_bus);
-
- if (func == NULL) {
- return(1);
- }
-
- func->bus = ctrl->slot_bus;
- func->device = device;
- func->function = 0;
- func->configured = 0;
- func->switch_save = 0x10;
- func->pwr_save = 0;
- func->is_a_board = 0;
- }
+ p_slot->pwr_save = 0;
+ p_slot->is_a_board = 0;
return 0;
}
@@ -1633,13 +664,11 @@ static void shpchp_pushbutton_thread (unsigned long slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = POWEROFF_STATE;
- dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
shpchp_disable_slot(p_slot);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
if (shpchp_enable_slot(p_slot)) {
/* Wait for exclusive access to hardware */
@@ -1701,7 +730,6 @@ int shpchp_event_start_thread (void)
err ("Can't start up our event thread\n");
return -1;
}
- dbg("Our event thread pid = %d\n", pid);
return 0;
}
@@ -1709,9 +737,7 @@ int shpchp_event_start_thread (void)
void shpchp_event_stop_thread (void)
{
event_finished = 1;
- dbg("event_thread finish command given\n");
up(&event_semaphore);
- dbg("wait for event_thread to exit\n");
down(&event_exit);
}
@@ -1739,12 +765,10 @@ static void interrupt_event_handler(struct controller *ctrl)
{
int loop = 0;
int change = 1;
- struct pci_func *func;
u8 hp_slot;
u8 getstatus;
struct slot *p_slot;
- dbg("%s:\n", __FUNCTION__);
while (change) {
change = 0;
@@ -1754,12 +778,8 @@ static void interrupt_event_handler(struct controller *ctrl)
ctrl->event_queue[loop].event_type);
hp_slot = ctrl->event_queue[loop].hp_slot;
- func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
-
if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
dbg("%s: button cancel\n", __FUNCTION__);
del_timer(&p_slot->task_event);
@@ -1880,13 +900,6 @@ int shpchp_enable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc;
- struct pci_func *func;
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
- if (!func) {
- dbg("%s: Error! slot NULL\n", __FUNCTION__);
- return -ENODEV;
- }
/* Check to see if (latch closed, card present, power off) */
down(&p_slot->ctrl->crit_sect);
@@ -1910,72 +923,34 @@ int shpchp_enable_slot (struct slot *p_slot)
}
up(&p_slot->ctrl->crit_sect);
- slot_remove(func);
-
- func = shpchp_slot_create(p_slot->bus);
- if (func == NULL)
- return -ENOMEM;
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
+ p_slot->is_a_board = 1;
/* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
- p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
- dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+ dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
- rc = board_added(func, p_slot->ctrl);
+ rc = board_added(p_slot);
if (rc) {
- if (is_bridge(func))
- bridge_slot_remove(func);
- else
- slot_remove(func);
-
- /* Setup slot structure with entry for empty slot */
- func = shpchp_slot_create(p_slot->bus);
- if (func == NULL)
- return -ENOMEM; /* Out of memory */
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
-
- /* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+ p_slot->hpc_ops->get_adapter_status(p_slot,
+ &(p_slot->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
}
- if (p_slot)
- update_slot_info(p_slot);
-
+ update_slot_info(p_slot);
return rc;
}
int shpchp_disable_slot (struct slot *p_slot)
{
- u8 class_code, header_type, BCR;
- u8 index = 0;
u8 getstatus = 0;
- u32 rc = 0;
int ret = 0;
- unsigned int devfn;
- struct pci_bus *pci_bus;
- struct pci_func *func;
if (!p_slot->ctrl)
return -ENODEV;
- pci_bus = p_slot->ctrl->pci_dev->subordinate;
-
/* Check to see if (latch closed, card present, power on) */
down(&p_slot->ctrl->crit_sect);
@@ -1999,850 +974,8 @@ int shpchp_disable_slot (struct slot *p_slot)
}
up(&p_slot->ctrl->crit_sect);
- func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-
- /* Make sure there are no video controllers here
- * for all func of p_slot
- */
- while (func && !rc) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check the Class Code */
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
- if (rc)
- return -ENODEV;
-
- if (class_code == PCI_BASE_CLASS_DISPLAY) {
- /* Display/Video adapter (not supported) */
- rc = REMOVE_NOT_SUPPORTED;
- } else {
- /* See if it's a bridge */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- if (rc)
- return -ENODEV;
-
- /* If it's a bridge, check the VGA Enable bit */
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
- if (rc)
- return -ENODEV;
-
- /* If the VGA Enable bit is set, remove isn't supported */
- if (BCR & PCI_BRIDGE_CTL_VGA) {
- rc = REMOVE_NOT_SUPPORTED;
- }
- }
- }
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
- }
-
- func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
- if ((func != NULL) && !rc) {
- rc = remove_board(func, p_slot->ctrl);
- } else if (!rc)
- rc = -ENODEV;
-
- if (p_slot)
- update_slot_info(p_slot);
-
- return rc;
-}
-
-
-/**
- * configure_new_device - Configures the PCI header information of one board.
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Returns 0 if success
- *
- */
-static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
- u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
-{
- u8 temp_byte, function, max_functions, stop_it;
- int rc;
- u32 ID;
- struct pci_func *new_slot;
- struct pci_bus lpci_bus, *pci_bus;
- int index;
-
- new_slot = func;
-
- dbg("%s\n", __FUNCTION__);
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
-
- /* Check for Multi-function device */
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
- if (rc) {
- dbg("%s: rc = %d\n", __FUNCTION__, rc);
- return rc;
- }
-
- if (temp_byte & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
-
- if (rc) {
- dbg("configure_new_function failed %d\n",rc);
- index = 0;
-
- while (new_slot) {
- new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
-
- if (new_slot)
- shpchp_return_board_resources(new_slot, resources);
- }
-
- return(rc);
- }
-
- function++;
-
- stop_it = 0;
-
- /* The following loop skips to the next present function
- * and creates a board structure
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
-
- if (ID == 0xFFFFFFFF) { /* There's nothing there. */
- function++;
- } else { /* There's something there */
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(func->bus);
-
- if (new_slot == NULL) {
- /* Out of memory */
- return(1);
- }
-
- new_slot->bus = func->bus;
- new_slot->device = func->device;
- new_slot->function = function;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- dbg("returning from configure_new_device\n");
-
- return 0;
-}
-
-
-/*
- * Configuration logic that involves the hotplug data structures and
- * their bookkeeping
- */
-
-
-/**
- * configure_new_function - Configures the PCI header information of one device
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
- */
-static int configure_new_function (struct controller * ctrl, struct pci_func * func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
-{
- int cloop;
- u8 temp_byte;
- u8 device;
- u8 class_code;
- u16 temp_word;
- u32 rc;
- u32 temp_register;
- u32 base;
- u32 ID;
- unsigned int devfn;
- struct pci_resource *mem_node;
- struct pci_resource *p_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_resource *hold_mem_node;
- struct pci_resource *hold_p_mem_node;
- struct pci_resource *hold_IO_node;
- struct pci_resource *hold_bus_node;
- struct irq_mapping irqs;
- struct pci_func *new_slot;
- struct pci_bus lpci_bus, *pci_bus;
- struct resource_lists temp_resources;
-#if defined(CONFIG_X86_64)
- u8 IRQ=0;
-#endif
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check for Bridge */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
- if (rc)
- return rc;
-
- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- /* set Primary bus */
- dbg("set Primary bus = 0x%x\n", func->bus);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
- if (rc)
- return rc;
-
- /* find range of busses to use */
- bus_node = get_max_resource(&resources->bus_head, 1L);
-
- /* If we don't have any busses to allocate, we can't continue */
- if (!bus_node) {
- err("Got NO bus resource to use\n");
- return -ENOMEM;
- }
- dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
-
- /* set Secondary bus */
- temp_byte = (u8)bus_node->base;
- dbg("set Secondary bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* set subordinate bus */
- temp_byte = (u8)(bus_node->base + bus_node->length - 1);
- dbg("set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
- if (rc)
- return rc;
-
- /* Setup the IO, memory, and prefetchable windows */
-
- io_node = get_max_resource(&(resources->io_head), 0x1000L);
- if (io_node) {
- dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
- }
-
- mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- if (mem_node) {
- dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
- }
-
- if (resources->p_mem_head)
- p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
- else {
- /*
- * In some platform implementation, MEM and PMEM are not
- * distinguished, and hence ACPI _CRS has only MEM entries
- * for both MEM and PMEM.
- */
- dbg("using MEM for PMEM\n");
- p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- }
- if (p_mem_node) {
- dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
- }
-
- /* set up the IRQ info */
- if (!resources->irqs) {
- irqs.barber_pole = 0;
- irqs.interrupt[0] = 0;
- irqs.interrupt[1] = 0;
- irqs.interrupt[2] = 0;
- irqs.interrupt[3] = 0;
- irqs.valid_INT = 0;
- } else {
- irqs.barber_pole = resources->irqs->barber_pole;
- irqs.interrupt[0] = resources->irqs->interrupt[0];
- irqs.interrupt[1] = resources->irqs->interrupt[1];
- irqs.interrupt[2] = resources->irqs->interrupt[2];
- irqs.interrupt[3] = resources->irqs->interrupt[3];
- irqs.valid_INT = resources->irqs->valid_INT;
- }
-
- /* set up resource lists that are now aligned on top and bottom
- * for anything behind the bridge.
- */
- temp_resources.bus_head = bus_node;
- temp_resources.io_head = io_node;
- temp_resources.mem_head = mem_node;
- temp_resources.p_mem_head = p_mem_node;
- temp_resources.irqs = &irqs;
-
- /* Make copies of the nodes we are going to pass down so that
- * if there is a problem,we can just use these to free resources
- */
- hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
- hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
- hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
- hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);
-
- if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
- kfree(hold_bus_node);
- kfree(hold_IO_node);
- kfree(hold_mem_node);
- kfree(hold_p_mem_node);
-
- return 1;
- }
-
- memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
-
- bus_node->base += 1;
- bus_node->length -= 1;
- bus_node->next = NULL;
-
- /* If we have IO resources copy them and fill in the bridge's
- * IO range registers
- */
- if (io_node) {
- memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
- io_node->next = NULL;
-
- /* set IO base and Limit registers */
- RES_CHECK(io_node->base, 8);
- temp_byte = (u8)(io_node->base >> 8);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- RES_CHECK(io_node->base + io_node->length - 1, 8);
- temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
- } else {
- kfree(hold_IO_node);
- hold_IO_node = NULL;
- }
-
- /* If we have memory resources copy them and fill in the bridge's
- * memory range registers. Otherwise, fill in the range
- * registers with values that disable them.
- */
- if (mem_node) {
- memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
- mem_node->next = NULL;
-
- /* set Mem base and Limit registers */
- RES_CHECK(mem_node->base, 16);
- temp_word = (u32)(mem_node->base >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- RES_CHECK(mem_node->base + mem_node->length - 1, 16);
- temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- kfree(hold_mem_node);
- hold_mem_node = NULL;
- }
-
- /* If we have prefetchable memory resources copy them and
- * fill in the bridge's memory range registers. Otherwise,
- * fill in the range registers with values that disable them.
- */
- if (p_mem_node) {
- memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
- p_mem_node->next = NULL;
-
- /* set Pre Mem base and Limit registers */
- RES_CHECK(p_mem_node->base, 16);
- temp_word = (u32)(p_mem_node->base >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
- temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- kfree(hold_p_mem_node);
- hold_p_mem_node = NULL;
- }
-
- /* Adjust this to compensate for extra adjustment in first loop */
- irqs.barber_pole--;
-
- rc = 0;
-
- /* Here we actually find the devices and configure them */
- for (device = 0; (device <= 0x1F) && !rc; device++) {
- irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
-
- ID = 0xFFFFFFFF;
- pci_bus->number = hold_bus_node->base;
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
- PCI_VENDOR_ID, &ID);
- pci_bus->number = func->bus;
-
- if (ID != 0xFFFFFFFF) { /* device Present */
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(hold_bus_node->base);
-
- if (new_slot == NULL) {
- /* Out of memory */
- rc = -ENOMEM;
- continue;
- }
-
- new_slot->bus = hold_bus_node->base;
- new_slot->device = device;
- new_slot->function = 0;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
- dbg("configure_new_device rc=0x%x\n",rc);
- } /* End of IF (device in slot?) */
- } /* End of FOR loop */
-
- if (rc) {
- shpchp_destroy_resource_list(&temp_resources);
-
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return(rc);
- }
-
- /* save the interrupt routing information */
- if (resources->irqs) {
- resources->irqs->interrupt[0] = irqs.interrupt[0];
- resources->irqs->interrupt[1] = irqs.interrupt[1];
- resources->irqs->interrupt[2] = irqs.interrupt[2];
- resources->irqs->interrupt[3] = irqs.interrupt[3];
- resources->irqs->valid_INT = irqs.valid_INT;
- } else if (!behind_bridge) {
- /* We need to hook up the interrupts here */
- for (cloop = 0; cloop < 4; cloop++) {
- if (irqs.valid_INT & (0x01 << cloop)) {
- rc = shpchp_set_irq(func->bus, func->device,
- 0x0A + cloop, irqs.interrupt[cloop]);
- if (rc) {
- shpchp_destroy_resource_list (&temp_resources);
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return rc;
- }
- }
- } /* end of for loop */
- }
-
- /* Return unused bus resources
- * First use the temporary node to store information for the board
- */
- if (hold_bus_node && bus_node && temp_resources.bus_head) {
- hold_bus_node->length = bus_node->base - hold_bus_node->base;
-
- hold_bus_node->next = func->bus_head;
- func->bus_head = hold_bus_node;
-
- temp_byte = (u8)(temp_resources.bus_head->base - 1);
-
- /* set subordinate bus */
- dbg("re-set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-
- if (temp_resources.bus_head->length == 0) {
- kfree(temp_resources.bus_head);
- temp_resources.bus_head = NULL;
- } else {
- dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
- func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
- return_resource(&(resources->bus_head), temp_resources.bus_head);
- }
- }
-
- /* If we have IO space available and there is some left,
- * return the unused portion
- */
- if (hold_IO_node && temp_resources.io_head) {
- io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
- &hold_IO_node, 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- hold_IO_node->base = io_node->base + io_node->length;
-
- RES_CHECK(hold_IO_node->base, 8);
- temp_byte = (u8)((hold_IO_node->base) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- }
-
- io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- /* First use the temporary node to store information for the board */
- hold_IO_node->length = io_node->base - hold_IO_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_IO_node->length) {
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
-
- RES_CHECK(io_node->base - 1, 8);
- temp_byte = (u8)((io_node->base - 1) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- } else {
- /* it doesn't need any IO */
- temp_byte = 0x00;
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- kfree(hold_IO_node);
- }
- } else {
- /* it used most of the range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
- } else if (hold_IO_node) {
- /* it used the whole range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
-
- /* If we have memory space available and there is some left,
- * return the unused portion
- */
- if (hold_mem_node && temp_resources.mem_head) {
- mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- hold_mem_node->base = mem_node->base + mem_node->length;
-
- RES_CHECK(hold_mem_node->base, 16);
- temp_word = (u32)((hold_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- }
-
- mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- /* First use the temporary node to store information for the board */
- hold_mem_node->length = mem_node->base - hold_mem_node->base;
-
- if (hold_mem_node->length) {
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
-
- /* configure end address */
- RES_CHECK(mem_node->base - 1, 16);
- temp_word = (u32)((mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- /* Return unused resources to the pool */
- return_resource(&(resources->mem_head), mem_node);
- } else {
- /* it doesn't need any Mem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- kfree(hold_mem_node);
- }
- } else {
- /* it used most of the range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
- } else if (hold_mem_node) {
- /* it used the whole range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
-
- /* If we have prefetchable memory space available and there is some
- * left at the end, return the unused portion
- */
- if (hold_p_mem_node && temp_resources.p_mem_head) {
- p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
- &hold_p_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
-
- RES_CHECK(hold_p_mem_node->base, 16);
- temp_word = (u32)((hold_p_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- }
-
- p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- /* First use the temporary node to store information for the board */
- hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_p_mem_node->length) {
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
-
- RES_CHECK(p_mem_node->base - 1, 16);
- temp_word = (u32)((p_mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- } else {
- /* it doesn't need any PMem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- kfree(hold_p_mem_node);
- }
- } else {
- /* it used the most of the range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
- } else if (hold_p_mem_node) {
- /* it used the whole range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
-
- /* We should be configuring an IRQ and the bridge's base address
- * registers if it needs them. Although we have never seen such
- * a device
- */
-
- shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-
- dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
- } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- /* Standard device */
- u64 base64;
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
- if (class_code == PCI_BASE_CLASS_DISPLAY)
- return (DEVICE_TYPE_NOT_SUPPORTED);
-
- /* Figure out IO and memory needs */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- temp_register = 0xFFFFFFFF;
-
- rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
- dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device,
- func->function);
-
- if (!temp_register)
- continue;
-
- base64 = 0L;
- if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
- /* Map IO */
-
- /* set base = amount of IO space */
- base = temp_register & 0xFFFFFFFC;
- base = ~base + 1;
-
- dbg("NEED IO length(0x%x)\n", base);
- io_node = get_io_resource(&(resources->io_head),(ulong)base);
-
- /* allocate the resource to the board */
- if (io_node) {
- dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
- base = (u32)io_node->base;
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else {
- err("Got NO IO resource(length=0x%x)\n", base);
- return -ENOMEM;
- }
- } else { /* map MEM */
- int prefetchable = 1;
- struct pci_resource **res_node = &func->p_mem_head;
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
- prefetchable = 0;
- res_node = &func->mem_head;
- res_type_str++;
- }
-
- base = temp_register & 0xFFFFFFF0;
- base = ~base + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node=get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base = (u32)mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base,
- mem_node->length);
- } else {
- err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2,
- temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node = get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base64 = mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32),
- (u32)base64, mem_node->length);
- } else {
- err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- default:
- dbg("reserved BAR type=0x%x\n", temp_register);
- break;
- }
-
- }
-
- if (base64) {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- cloop += 4;
- base64 >>= 32;
-
- if (base64) {
- dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
- base64 = 0x0L;
- }
-
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- } else {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
- }
- } /* End of base register loop */
-
-#if defined(CONFIG_X86_64)
- /* Figure out which interrupt pin this function uses */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
-
- /* If this function needs an interrupt and we are behind a bridge
- and the pin is tied to something that's alread mapped,
- set this one the same
- */
- if (temp_byte && resources->irqs &&
- (resources->irqs->valid_INT &
- (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
- /* We have to share with something already set up */
- IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
- } else {
- /* Program IRQ based on card type */
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
- if (class_code == PCI_BASE_CLASS_STORAGE) {
- IRQ = shpchp_disk_irq;
- } else {
- IRQ = shpchp_nic_irq;
- }
- }
-
- /* IRQ Line */
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
-
- if (!behind_bridge) {
- rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
- if (rc)
- return(1);
- } else {
- /* TBD - this code may also belong in the other clause of this If statement */
- resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
- resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
- }
-#endif
- /* Disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
- if (rc)
- return rc;
-
- shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-
- dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
- } /* End of Not-A-Bridge else */
- else {
- /* It's some strange type of PCI adapter (Cardbus?) */
- return(DEVICE_TYPE_NOT_SUPPORTED);
- }
-
- func->configured = 1;
-
- return 0;
+ ret = remove_board(p_slot);
+ update_slot_info(p_slot);
+ return ret;
}
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 38c5d9066697..40905a6c8094 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -23,21 +23,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-#include <asm/system.h>
#include "shpchp.h"
#ifdef DEBUG
@@ -282,7 +275,7 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u16 cmd_status;
int retval = 0;
u16 temp_word;
@@ -320,7 +313,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
* command.
*/
writew(temp_word, php_ctlr->creg + CMD);
- dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
DBG_LEAVE_ROUTINE
return retval;
@@ -328,7 +320,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
static int hpc_check_cmd_status(struct controller *ctrl)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
u16 cmd_status;
int retval = 0;
@@ -368,7 +360,7 @@ static int hpc_check_cmd_status(struct controller *ctrl)
static int hpc_get_attention_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 atten_led_state;
@@ -408,7 +400,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
static int hpc_get_power_status(struct slot * slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 slot_state;
@@ -450,7 +442,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
static int hpc_get_latch_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
@@ -473,7 +465,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
static int hpc_get_adapter_status(struct slot *slot, u8 *status)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 card_state;
@@ -496,7 +488,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -513,7 +505,7 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status, sec_bus_status;
u8 m66_cap, pcix_cap, pi;
@@ -594,7 +586,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u16 sec_bus_status;
u8 pi;
int retval = 0;
@@ -623,7 +615,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
static int hpc_query_power_fault(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u32 slot_reg;
u16 slot_status;
u8 pwr_fault_state, status;
@@ -647,7 +639,7 @@ static int hpc_query_power_fault(struct slot * slot)
static int hpc_set_attention_status(struct slot *slot, u8 value)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd = 0;
int rc = 0;
@@ -683,7 +675,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
static void hpc_set_green_led_on(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -705,7 +697,7 @@ static void hpc_set_green_led_on(struct slot *slot)
static void hpc_set_green_led_off(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -727,7 +719,7 @@ static void hpc_set_green_led_off(struct slot *slot)
static void hpc_set_green_led_blink(struct slot *slot)
{
- struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
if (!slot->ctrl->hpc_ctlr_handle) {
@@ -754,7 +746,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
int *updown, /* physical_slot_num increament: 1 or -1 */
int *flags)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -776,7 +768,7 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
static void hpc_release_ctlr(struct controller *ctrl)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
struct php_ctlr_state_s *p, *p_prev;
DBG_ENTER_ROUTINE
@@ -796,10 +788,8 @@ static void hpc_release_ctlr(struct controller *ctrl)
}
}
if (php_ctlr->pci_dev) {
- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
iounmap(php_ctlr->creg);
release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
- dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
php_ctlr->pci_dev = NULL;
}
@@ -828,7 +818,7 @@ DBG_LEAVE_ROUTINE
static int hpc_power_on_slot(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -859,7 +849,7 @@ static int hpc_power_on_slot(struct slot * slot)
static int hpc_slot_enable(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -890,7 +880,7 @@ static int hpc_slot_enable(struct slot * slot)
static int hpc_slot_disable(struct slot * slot)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u8 slot_cmd;
int retval = 0;
@@ -920,51 +910,12 @@ static int hpc_slot_disable(struct slot * slot)
return retval;
}
-static int hpc_enable_all_slots( struct slot *slot )
-{
- int retval = 0;
-
- DBG_ENTER_ROUTINE
-
- if (!slot->ctrl->hpc_ctlr_handle) {
- err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
- return -1;
- }
-
- retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
- if (retval) {
- err("%s: Write command failed!\n", __FUNCTION__);
- return -1;
- }
-
- DBG_LEAVE_ROUTINE
-
- return retval;
-}
-
-static int hpc_pwr_on_all_slots(struct slot *slot)
-{
- int retval = 0;
-
- DBG_ENTER_ROUTINE
-
- retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
-
- if (retval) {
- err("%s: Write command failed!\n", __FUNCTION__);
- return -1;
- }
-
- DBG_LEAVE_ROUTINE
- return retval;
-}
-
static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
{
u8 slot_cmd;
u8 pi;
int retval = 0;
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
DBG_ENTER_ROUTINE
@@ -1089,18 +1040,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (!intr_loc)
return IRQ_NONE;
- dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
if(!shpchp_poll_mode) {
/* Mask Global Interrupt Mask - see implementation note on p. 139 */
/* of SHPC spec rev 1.0*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: Before masking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword |= 0x00000001;
- dbg("%s: After masking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
@@ -1114,11 +1060,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
* Detect bit in Controller SERR-INT register
*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: Before clearing CCIP, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffeffff;
- dbg("%s: After clearing CCIP, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
wake_up_interruptible(&ctrl->queue);
}
@@ -1126,11 +1068,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if ((intr_loc = (intr_loc >> 1)) == 0) {
/* Unmask Global Interrupt Mask */
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffffffe;
- dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
return IRQ_NONE;
@@ -1140,11 +1078,9 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* To find out which slot has interrupt pending */
if ((intr_loc >> hp_slot) & 0x01) {
temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
- dbg("%s: Slot %x with intr, temp_dword = %x\n",
- __FUNCTION__, hp_slot, temp_dword);
+ dbg("%s: Slot %x with intr, slot register = %x\n",
+ __FUNCTION__, hp_slot, temp_dword);
temp_byte = (temp_dword >> 16) & 0xFF;
- dbg("%s: Slot with intr, temp_byte = %x\n",
- __FUNCTION__, temp_byte);
if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
schedule_flag += php_ctlr->switch_change_callback(
hp_slot, php_ctlr->callback_instance_id);
@@ -1160,8 +1096,6 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear all slot events */
temp_dword = 0xe01f3fff;
- dbg("%s: Clearing slot events, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
intr_loc2 = readl(php_ctlr->creg + INTR_LOC);
@@ -1171,11 +1105,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (!shpchp_poll_mode) {
/* Unmask Global Interrupt Mask */
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
temp_dword &= 0xfffffffe;
- dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
- __FUNCTION__, temp_dword);
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
}
@@ -1184,7 +1114,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
int retval = 0;
u8 pi;
@@ -1253,7 +1183,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
{
- struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
u16 sec_bus_status;
int retval = 0;
@@ -1367,8 +1297,6 @@ static struct hpc_ops shpchp_hpc_ops = {
.power_on_slot = hpc_power_on_slot,
.slot_enable = hpc_slot_enable,
.slot_disable = hpc_slot_disable,
- .enable_all_slots = hpc_enable_all_slots,
- .pwr_on_all_slots = hpc_pwr_on_all_slots,
.set_bus_speed_mode = hpc_set_bus_speed_mode,
.set_attention_status = hpc_set_attention_status,
.get_power_status = hpc_get_power_status,
@@ -1391,12 +1319,7 @@ static struct hpc_ops shpchp_hpc_ops = {
.check_cmd_status = hpc_check_cmd_status,
};
-int shpc_init(struct controller * ctrl,
- struct pci_dev * pdev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback)
+int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
@@ -1405,7 +1328,6 @@ int shpc_init(struct controller * ctrl,
static int first = 1;
u32 shpc_cap_offset, shpc_base_offset;
u32 tempdword, slot_reg;
- u16 vendor_id, device_id;
u8 i;
DBG_ENTER_ROUTINE
@@ -1422,21 +1344,8 @@ int shpc_init(struct controller * ctrl,
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
- rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
- dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
- if (rc) {
- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
- dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
- if (rc) {
- err("%s: unable to read PCI configuration data\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
+ PCI_DEVICE_ID_AMD_GOLAM_7450)) {
shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */
} else {
if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
@@ -1469,7 +1378,8 @@ int shpc_init(struct controller * ctrl,
err("%s : pci_read_config_dword failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
+ dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
+ tempdword);
}
}
@@ -1478,13 +1388,6 @@ int shpc_init(struct controller * ctrl,
first = 0;
}
- dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn), pdev->irq);
- for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
- if (pci_resource_len(pdev, rc) > 0)
- dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc,
- pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
-
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
pdev->subsystem_device);
@@ -1504,7 +1407,6 @@ int shpc_init(struct controller * ctrl,
goto abort_free_ctlr;
}
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
- dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
init_MUTEX(&ctrl->crit_sect);
/* Setup wait queue */
@@ -1512,13 +1414,10 @@ int shpc_init(struct controller * ctrl,
/* Find the IRQ */
php_ctlr->irq = pdev->irq;
- dbg("HPC interrupt = %d\n", php_ctlr->irq);
-
- /* Save interrupt callback info */
- php_ctlr->attention_button_callback = attention_button_callback;
- php_ctlr->switch_change_callback = switch_change_callback;
- php_ctlr->presence_change_callback = presence_change_callback;
- php_ctlr->power_fault_callback = power_fault_callback;
+ php_ctlr->attention_button_callback = shpchp_handle_attention_button,
+ php_ctlr->switch_change_callback = shpchp_handle_switch_change;
+ php_ctlr->presence_change_callback = shpchp_handle_presence_change;
+ php_ctlr->power_fault_callback = shpchp_handle_power_fault;
php_ctlr->callback_instance_id = instance_id;
/* Return PCI Controller Info */
@@ -1556,7 +1455,6 @@ int shpc_init(struct controller * ctrl,
if (rc) {
info("Can't get msi for the hotplug controller\n");
info("Use INTx for the hotplug controller\n");
- dbg("%s: rc = %x\n", __FUNCTION__, rc);
} else
php_ctlr->irq = pdev->irq;
@@ -1566,9 +1464,11 @@ int shpc_init(struct controller * ctrl,
err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
goto abort_free_ctlr;
}
- /* Execute OSHP method here */
}
- dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+ dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
+ get_hp_hw_control_from_firmware(pdev);
/* Add this HPC instance into the HPC list */
spin_lock(&list_lock);
@@ -1607,7 +1507,6 @@ int shpc_init(struct controller * ctrl,
dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
}
- dbg("%s: Leaving shpc_init\n", __FUNCTION__);
DBG_LEAVE_ROUTINE
return 0;
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 90113e9cd69b..b8e95acea3b6 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -23,788 +23,155 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
#include <linux/pci.h>
#include "../pci.h"
#include "shpchp.h"
-#ifndef CONFIG_IA64
-#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
-#endif
-int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)
+void program_fw_provided_values(struct pci_dev *dev)
{
- unsigned char bus;
- struct pci_bus *child;
- int num;
-
- if (func->pci_dev == NULL)
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-
- /* Still NULL ? Well then scan for it ! */
- if (func->pci_dev == NULL) {
- num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
- if (num) {
- dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
- ctrl->pci_dev->subordinate->number);
- pci_bus_add_devices(ctrl->pci_dev->subordinate);
- }
-
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
- if (func->pci_dev == NULL) {
- dbg("ERROR: pci_dev still null\n");
- return 0;
+ u16 pci_cmd, pci_bctl;
+ struct pci_dev *cdev;
+ struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+
+ /* Program hpp values for this device */
+ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+ return;
+
+ get_hp_params_from_firmware(dev, &hpp);
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+ if (hpp.enable_serr)
+ pci_cmd |= PCI_COMMAND_SERR;
+ else
+ pci_cmd &= ~PCI_COMMAND_SERR;
+ if (hpp.enable_perr)
+ pci_cmd |= PCI_COMMAND_PARITY;
+ else
+ pci_cmd &= ~PCI_COMMAND_PARITY;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+ /* Program bridge control value and child devices */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+ hpp.latency_timer);
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+ if (hpp.enable_serr)
+ pci_bctl |= PCI_BRIDGE_CTL_SERR;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+ if (hpp.enable_perr)
+ pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+ if (dev->subordinate) {
+ list_for_each_entry(cdev, &dev->subordinate->devices,
+ bus_list)
+ program_fw_provided_values(cdev);
}
}
-
- if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
- child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
- pci_do_scan_bus(child);
-
- }
-
- return 0;
}
-
-int shpchp_unconfigure_device(struct pci_func* func)
+int shpchp_configure_device(struct slot *p_slot)
{
- int rc = 0;
- int j;
-
- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
- func->device, func->function);
-
- for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(func->bus,
- (func->device << 3) | j);
- if (temp) {
- pci_remove_bus_device(temp);
- }
+ struct pci_dev *dev;
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ int num, fn;
+
+ dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+ if (dev) {
+ err("Device %s already exists at %x:%x, cannot hot-add\n",
+ pci_name(dev), p_slot->bus, p_slot->device);
+ return -EINVAL;
}
- return rc;
-}
-
-/*
- * shpchp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
-{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
- int rc;
- u16 temp_word;
- struct pci_dev fakedev;
- struct pci_bus fakebus;
- fakedev.devfn = dev_num << 3;
- fakedev.bus = &fakebus;
- fakebus.number = bus_num;
- dbg("%s: dev %d, bus %d, pin %d, num %d\n",
- __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
- rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
- dbg("%s: rc %d\n", __FUNCTION__, rc);
- if (!rc)
- return !rc;
-
- /* set the Edge Level Control Register (ELCR) */
- temp_word = inb(0x4d0);
- temp_word |= inb(0x4d1) << 8;
-
- temp_word |= 0x01 << irq_num;
-
- /* This should only be for x86 as it sets the Edge Level Control Register */
- outb((u8) (temp_word & 0xFF), 0x4d0);
- outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-#endif
- return 0;
-}
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * shpchp_save_config
- *
- * Reads configuration for all slots in a PCI bus and saves info.
- *
- * Note: For non-hot plug busses, the slot # saved is the device #
- *
- * returns 0 if success
- */
-int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- struct pci_func *new_slot;
- int sub_bus;
- int FirstSupported;
- int LastSupported;
- int max_functions;
- int function;
- u8 DevError;
- int device = 0;
- int cloop = 0;
- int stop_it;
- int index;
- int is_hot_plug = num_ctlr_slots || first_device_num;
- struct pci_bus lpci_bus, *pci_bus;
-
- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
- num_ctlr_slots, first_device_num);
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
- num_ctlr_slots, first_device_num);
-
- /* Decide which slots are supported */
- if (is_hot_plug) {
- /*********************************
- * is_hot_plug is the slot mask
- *********************************/
- FirstSupported = first_device_num;
- LastSupported = FirstSupported + num_ctlr_slots - 1;
- } else {
- FirstSupported = 0;
- LastSupported = 0x1F;
+ num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
+ if (num == 0) {
+ err("No new device found\n");
+ return -ENODEV;
}
- dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
- LastSupported);
-
- /* Save PCI configuration space for all devices in supported slots */
- pci_bus->number = busnumber;
- for (device = FirstSupported; device <= LastSupported; device++) {
- ID = 0xFFFFFFFF;
- rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
-
- /* If multi-function device, set max_functions to 8 */
- if (header_type & 0x80)
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- DevError = 0;
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
- /* Recurse the subordinate bus
- * get the subordinate bus number
- */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
- if (rc) {
- return rc;
- } else {
- sub_bus = (int) secondary_bus;
-
- /* Save secondary bus cfg spc with this recursive call. */
- rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
- if (rc)
- return rc;
- }
- }
-
- index = 0;
- new_slot = shpchp_slot_find(busnumber, device, index++);
-
- dbg("new_slot = %p\n", new_slot);
-
- while (new_slot && (new_slot->function != (u8) function)) {
- new_slot = shpchp_slot_find(busnumber, device, index++);
- dbg("new_slot = %p\n", new_slot);
- }
- if (!new_slot) {
- /* Setup slot structure. */
- new_slot = shpchp_slot_create(busnumber);
- dbg("new_slot = %p\n", new_slot);
-
- if (new_slot == NULL)
- return(1);
- }
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = (u8) function;
- new_slot->is_a_board = 1;
- new_slot->switch_save = 0x10;
- new_slot->pwr_save = 1;
- /* In case of unsupported board */
- new_slot->status = DevError;
- new_slot->pci_dev = pci_find_slot(new_slot->bus,
- (new_slot->device << 3) | new_slot->function);
- dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
- /* dbg("new_slot->config_space[%x] = %x\n",
- cloop, new_slot->config_space[cloop]); */
- if (rc)
- return rc;
- }
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in Class Code and Header type.
- */
-
- while ((function < max_functions)&&(!stop_it)) {
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- dbg("Nothing there\n");
- } else { /* Something there */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n",
- class_code, header_type);
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- /* End of IF (device in slot?) */
- } else if (is_hot_plug) {
- /* Setup slot structure with entry for empty slot */
- new_slot = shpchp_slot_create(busnumber);
-
- if (new_slot == NULL) {
- return(1);
- }
- dbg("new_slot = %p\n", new_slot);
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = 0;
- new_slot->is_a_board = 0;
- new_slot->presence_save = 0;
- new_slot->switch_save = 0;
+ for (fn = 0; fn < 8; fn++) {
+ if (!(dev = pci_find_slot(p_slot->bus,
+ PCI_DEVFN(p_slot->device, fn))))
+ continue;
+ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot hot-add display device %s\n",
+ pci_name(dev));
+ continue;
}
- } /* End of FOR loop */
-
- return(0);
-}
-
-
-/*
- * shpchp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- int sub_bus;
- int max_functions;
- int function;
- int cloop = 0;
- int stop_it;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = new_slot->bus;
-
- ID = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_HEADER_TYPE, &header_type);
-
- if (header_type & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- /* Recurse the subordinate bus */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
-
- sub_bus = (int) secondary_bus;
-
- /* Save the config headers for the secondary bus. */
- rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-
- if (rc)
- return rc;
-
- } /* End of IF */
-
- new_slot->status = 0;
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
+ if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+ (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+ /* Find an unused bus number for the new bridge */
+ struct pci_bus *child;
+ unsigned char busnr, start = parent->secondary;
+ unsigned char end = parent->subordinate;
+ for (busnr = start; busnr <= end; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(parent),
+ busnr))
+ break;
}
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in the Class Code and the Header type.
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- } else { /* Something there */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_HEADER_TYPE, &header_type);
-
- stop_it++;
- }
+ if (busnr >= end) {
+ err("No free bus for hot-added bridge\n");
+ continue;
}
-
- } while (function < max_functions);
- } /* End of IF (device in slot?) */
- else {
- return 2;
+ child = pci_add_new_bus(parent, dev, busnr);
+ if (!child) {
+ err("Cannot add new bus for %s\n",
+ pci_name(dev));
+ continue;
+ }
+ child->subordinate = pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
+ }
+ program_fw_provided_values(dev);
}
+ pci_bus_assign_resources(parent);
+ pci_bus_add_devices(parent);
+ pci_enable_bridges(parent);
return 0;
}
-
-/*
- * shpchp_save_used_resources
- *
- * Stores used resource information for existing boards. this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- * if disable == 1(DISABLE_CARD),
- * it loops for all functions of the slot and disables them.
- * else, it just get resources of the function and return.
- */
-int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
+int shpchp_unconfigure_device(struct slot *p_slot)
{
- u8 cloop;
- u8 header_type;
- u8 secondary_bus;
- u8 temp_byte;
- u16 command;
- u16 save_command;
- u16 w_base, w_length;
- u32 temp_register;
- u32 save_base;
- u32 base, length;
- u64 base64 = 0;
- int index = 0;
- unsigned int devfn;
- struct pci_resource *mem_node = NULL;
- struct pci_resource *p_mem_node = NULL;
- struct pci_resource *t_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- if (disable)
- func = shpchp_slot_find(func->bus, func->device, index++);
-
- while ((func != NULL) && func->is_a_board) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Save the command register */
- pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
+ int rc = 0;
+ int j;
+ u8 bctl = 0;
+
+ dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
- if (disable) {
- /* disable card */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
+ for (j=0; j<8 ; j++) {
+ struct pci_dev* temp = pci_find_slot(p_slot->bus,
+ (p_slot->device << 3) | j);
+ if (!temp)
+ continue;
+ if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
}
-
- /* Check for Bridge */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
- if (disable) {
- /* Clear Bridge Control Register */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ if (bctl & PCI_BRIDGE_CTL_VGA) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
}
-
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
- bus_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!bus_node)
- return -ENOMEM;
-
- bus_node->base = (ulong)secondary_bus;
- bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
-
- bus_node->next = func->bus_head;
- func->bus_head = bus_node;
-
- /* Save IO base and Limit registers */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
- base = temp_byte;
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
- length = temp_byte;
-
- if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
- io_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
- io_node->length = (ulong)(length - base + 0x10) << 8;
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- }
-
- /* Save memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!mem_node)
- return -ENOMEM;
-
- mem_node->base = (ulong)w_base << 16;
- mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- /* Save prefetchable memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- p_mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!p_mem_node)
- return -ENOMEM;
-
- p_mem_node->base = (ulong)w_base << 16;
- p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- }
- } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
-
- /* Figure out IO and memory base lengths */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
-
- temp_register = 0xFFFFFFFF;
- pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-
- if (!disable)
- pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
-
- if (!temp_register)
- continue;
-
- base = temp_register;
-
- if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
- (!disable || (save_command & PCI_COMMAND_IO))) {
- /* IO base */
- /* set temp_register = amount of IO space requested */
- base = base & 0xFFFFFFFCL;
- base = (~base) + 1;
-
- io_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
- io_node->length = (ulong)base;
- dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
- io_node->base, io_node->length);
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else { /* map Memory */
- int prefetchable = 1;
- /* struct pci_resources **res_node; */
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- t_mem_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!t_mem_node)
- return -ENOMEM;
-
- if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
- (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- prefetchable = 0;
- mem_node = t_mem_node;
- res_type_str++;
- } else
- p_mem_node = t_mem_node;
-
- base = base & 0xFFFFFFF0L;
- base = (~base) + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- if (prefetchable) {
- p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- base64 = temp_register2;
- base64 = (base64 << 32) | save_base;
-
- if (temp_register2) {
- dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
- res_type_str, temp_register2, (u32)base64);
- base64 &= 0x00000000FFFFFFFFL;
- }
-
- if (prefetchable) {
- p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- cloop += 4;
- break;
- default:
- dbg("asur: reserved BAR type=0x%x\n",
- temp_register);
- break;
- }
- }
- } /* End of base register loop */
- } else { /* Some other unknown header type */
- dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
- func->bus, func->device);
}
-
- /* find the next device in this slot */
- if (!disable)
- break;
- func = shpchp_slot_find(func->bus, func->device, index++);
+ pci_remove_bus_device(temp);
}
-
- return 0;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-return_resource_list(struct pci_resource **func, struct pci_resource **res)
-{
- struct pci_resource *node;
- struct pci_resource *t_node;
-
- node = *func;
- *func = NULL;
- while (node) {
- t_node = node->next;
- return_resource(res, node);
- node = t_node;
- }
-}
-
-/*
- * shpchp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int shpchp_return_board_resources(struct pci_func * func,
- struct resource_lists * resources)
-{
- int rc;
- dbg("%s\n", __FUNCTION__);
-
- if (!func)
- return 1;
-
- return_resource_list(&(func->io_head),&(resources->io_head));
- return_resource_list(&(func->mem_head),&(resources->mem_head));
- return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
- return_resource_list(&(func->bus_head),&(resources->bus_head));
-
- rc = shpchp_resource_sort_and_combine(&(resources->mem_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
- rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
-
return rc;
}
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-kfree_resource_list(struct pci_resource **r)
-{
- struct pci_resource *res, *tres;
-
- res = *r;
- *r = NULL;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
-/**
- * shpchp_destroy_resource_list: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_resource_list(struct resource_lists *resources)
-{
- kfree_resource_list(&(resources->io_head));
- kfree_resource_list(&(resources->mem_head));
- kfree_resource_list(&(resources->p_mem_head));
- kfree_resource_list(&(resources->bus_head));
-}
-
-/**
- * shpchp_destroy_board_resources: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_board_resources(struct pci_func * func)
-{
- kfree_resource_list(&(func->io_head));
- kfree_resource_list(&(func->mem_head));
- kfree_resource_list(&(func->p_mem_head));
- kfree_resource_list(&(func->bus_head));
-}
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index c9445ebda5c7..f5cfbf2c047c 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -26,12 +26,9 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
#include "shpchp.h"
@@ -40,104 +37,60 @@
static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
+ struct pci_dev *pdev;
char * out = buf;
- int index;
- struct pci_resource *res;
+ int index, busnr;
+ struct resource *res;
+ struct pci_bus *bus;
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
+ pdev = container_of (dev, struct pci_dev, dev);
+ bus = pdev->subordinate;
out += sprintf(buf, "Free resources: memory\n");
- index = 11;
- res = ctrl->mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_MEM) &&
+ !(res->flags & IORESOURCE_PREFETCH)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: prefetchable memory\n");
- index = 11;
- res = ctrl->p_mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_MEM) &&
+ (res->flags & IORESOURCE_PREFETCH)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: IO\n");
- index = 11;
- res = ctrl->io_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+ res = bus->resource[index];
+ if (res && (res->flags & IORESOURCE_IO)) {
+ out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+ res->start, (res->end - res->start));
+ }
}
out += sprintf(out, "Free resources: bus numbers\n");
- index = 11;
- res = ctrl->bus_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
+ for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(bus), busnr))
+ break;
}
+ if (busnr < bus->subordinate)
+ out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+ busnr, (bus->subordinate - busnr));
return out - buf;
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+void shpchp_create_ctrl_files (struct controller *ctrl)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
- char * out = buf;
- int index;
- struct pci_resource *res;
- struct pci_func *new_slot;
- struct slot *slot;
-
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
-
- slot=ctrl->slot;
-
- while (slot) {
- new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
- if (!new_slot)
- break;
- out += sprintf(out, "assigned resources: memory\n");
- index = 11;
- res = new_slot->mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: prefetchable memory\n");
- index = 11;
- res = new_slot->p_mem_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: IO\n");
- index = 11;
- res = new_slot->io_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- out += sprintf(out, "assigned resources: bus numbers\n");
- index = 11;
- res = new_slot->bus_head;
- while (res && index--) {
- out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
- res = res->next;
- }
- slot=slot->next;
- }
-
- return out - buf;
+ device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-void shpchp_create_ctrl_files (struct controller *ctrl)
+void shpchp_remove_ctrl_files(struct controller *ctrl)
{
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+ device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
diff --git a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h
deleted file mode 100644
index 88aeb978c911..000000000000
--- a/drivers/pci/hotplug/shpchprm.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_H_
-#define _SHPCHPRM_H_
-
-#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-#include "shpchprm_legacy.h"
-#else
-#include "shpchprm_nonacpi.h"
-#endif
-
-int shpchprm_init(enum php_ctlr_type ct);
-void shpchprm_cleanup(void);
-int shpchprm_print_pirt(void);
-int shpchprm_find_available_resources(struct controller *ctrl);
-int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
-void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
-
-#ifdef DEBUG
-#define RES_CHECK(this, bits) \
- { if (((this) & (bits - 1))) \
- printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
-#else
-#define RES_CHECK(this, bits)
-#endif
-
-#endif /* _SHPCHPRM_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index 7957cdc72cd0..17145e52223a 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -20,95 +20,23 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <dely.l.sy@intel.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
#include "shpchp.h"
-#include "shpchprm.h"
-
-#define PCI_MAX_BUS 0x100
-#define ACPI_STA_DEVICE_PRESENT 0x01
#define METHOD_NAME__SUN "_SUN"
#define METHOD_NAME__HPP "_HPP"
#define METHOD_NAME_OSHP "OSHP"
-#define PHP_RES_BUS 0xA0
-#define PHP_RES_IO 0xA1
-#define PHP_RES_MEM 0xA2
-#define PHP_RES_PMEM 0xA3
-
-#define BRIDGE_TYPE_P2P 0x00
-#define BRIDGE_TYPE_HOST 0x01
-
-/* this should go to drivers/acpi/include/ */
-struct acpi__hpp {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
-
-struct acpi_php_slot {
- struct acpi_php_slot *next;
- struct acpi_bridge *bridge;
- acpi_handle handle;
- int seg;
- int bus;
- int dev;
- int fun;
- u32 sun;
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- void *slot_ops; /* _STA, _EJx, etc */
- struct slot *slot;
-}; /* per func */
-
-struct acpi_bridge {
- struct acpi_bridge *parent;
- struct acpi_bridge *next;
- struct acpi_bridge *child;
- acpi_handle handle;
- int seg;
- int pbus; /* pdev->bus->number */
- int pdevice; /* PCI_SLOT(pdev->devfn) */
- int pfunction; /* PCI_DEVFN(pdev->devfn) */
- int bus; /* pdev->subordinate->number */
- struct acpi__hpp *_hpp;
- struct acpi_php_slot *slots;
- struct pci_resource *tmem_head; /* total from crs */
- struct pci_resource *tp_mem_head; /* total from crs */
- struct pci_resource *tio_head; /* total from crs */
- struct pci_resource *tbus_head; /* total from crs */
- struct pci_resource *mem_head; /* available */
- struct pci_resource *p_mem_head; /* available */
- struct pci_resource *io_head; /* available */
- struct pci_resource *bus_head; /* available */
- int scanned;
- int type;
-};
-
-static struct acpi_bridge *acpi_bridges_head;
-
static u8 * acpi_path_name( acpi_handle handle)
{
acpi_status status;
@@ -124,82 +52,43 @@ static u8 * acpi_path_name( acpi_handle handle)
return path_name;
}
-static void acpi_get__hpp ( struct acpi_bridge *ab);
-static void acpi_run_oshp ( struct acpi_bridge *ab);
-
-static int acpi_add_slot_to_php_slots(
- struct acpi_bridge *ab,
- int bus_num,
- acpi_handle handle,
- u32 adr,
- u32 sun
- )
-{
- struct acpi_php_slot *aps;
- static long samesun = -1;
-
- aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
- if (!aps) {
- err ("acpi_shpchprm: alloc for aps fail\n");
- return -1;
- }
- memset(aps, 0, sizeof(struct acpi_php_slot));
-
- aps->handle = handle;
- aps->bus = bus_num;
- aps->dev = (adr >> 16) & 0xffff;
- aps->fun = adr & 0xffff;
- aps->sun = sun;
-
- aps->next = ab->slots; /* cling to the bridge */
- aps->bridge = ab;
- ab->slots = aps;
-
- ab->scanned += 1;
- if (!ab->_hpp)
- acpi_get__hpp(ab);
-
- acpi_run_oshp(ab);
-
- if (sun != samesun) {
- info("acpi_shpchprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg,
- aps->bus, aps->dev, aps->fun);
- samesun = sun;
- }
- return 0;
-}
-
-static void acpi_get__hpp ( struct acpi_bridge *ab)
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
{
acpi_status status;
u8 nui[4];
struct acpi_buffer ret_buf = { 0, NULL};
union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(ab->handle);
+ u8 *path_name = acpi_path_name(handle);
int i, len = 0;
/* get _hpp */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
switch (status) {
case AE_BUFFER_OVERFLOW:
ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
if (!ret_buf.pointer) {
- err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name);
- return;
+ err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
+ path_name);
+ return AE_NO_MEMORY;
}
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+ NULL, &ret_buf);
if (ACPI_SUCCESS(status))
break;
default:
if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status);
- return;
+ dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+ path_name, status);
+ return status;
}
}
ext_obj = (union acpi_object *) ret_buf.pointer;
if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name);
+ err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
@@ -212,1353 +101,41 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
nui[i] = (u8)ext_obj->integer.value;
break;
default:
- err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name);
+ err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
}
- ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
- if (!ab->_hpp) {
- err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name);
- goto free_and_return;
- }
- memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+ hpp->cache_line_size = nui[0];
+ hpp->latency_timer = nui[1];
+ hpp->enable_serr = nui[2];
+ hpp->enable_perr = nui[3];
- ab->_hpp->cache_line_size = nui[0];
- ab->_hpp->latency_timer = nui[1];
- ab->_hpp->enable_serr = nui[2];
- ab->_hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
+ dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+ dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
+ dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
+ dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
free_and_return:
kfree(ret_buf.pointer);
-}
-
-static void acpi_run_oshp ( struct acpi_bridge *ab)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
- } else
- dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
- return;
-}
-
-static acpi_status acpi_evaluate_crs(
- acpi_handle handle,
- struct acpi_resource **retbuf
- )
-{
- acpi_status status;
- struct acpi_buffer crsbuf;
- u8 *path_name = acpi_path_name(handle);
-
- crsbuf.length = 0;
- crsbuf.pointer = NULL;
-
- status = acpi_get_current_resources (handle, &crsbuf);
-
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- break; /* found */
- case AE_NOT_FOUND:
- dbg("acpi_shpchprm:%s _CRS not found\n", path_name);
- return status;
- default:
- err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
- return status;
- }
-
- crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
- if (!crsbuf.pointer) {
- err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
- return AE_NO_MEMORY;
- }
-
- status = acpi_get_current_resources (handle, &crsbuf);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status);
- kfree(crsbuf.pointer);
- return status;
- }
-
- *retbuf = crsbuf.pointer;
-
- return status;
-}
-
-static void free_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res, *next;
-
- for (res = aprh; res; res = next) {
- next = res->next;
- kfree(res);
- }
-}
-
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-static void print_slot_resources( struct acpi_php_slot *aps)
-{
- if (aps->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (aps->bus_head);
- }
-
- if (aps->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (aps->io_head);
- }
-
- if (aps->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (aps->mem_head);
- }
-
- if (aps->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (aps->p_mem_head);
- }
-}
-
-static void print_pci_resources( struct acpi_bridge *ab)
-{
- if (ab->tbus_head) {
- dbg(" Total BUS Resources:\n");
- print_pci_resource (ab->tbus_head);
- }
- if (ab->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (ab->bus_head);
- }
-
- if (ab->tio_head) {
- dbg(" Total IO Resources:\n");
- print_pci_resource (ab->tio_head);
- }
- if (ab->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (ab->io_head);
- }
-
- if (ab->tmem_head) {
- dbg(" Total MEM Resources:\n");
- print_pci_resource (ab->tmem_head);
- }
- if (ab->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (ab->mem_head);
- }
-
- if (ab->tp_mem_head) {
- dbg(" Total PMEM Resources:\n");
- print_pci_resource (ab->tp_mem_head);
- }
- if (ab->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (ab->p_mem_head);
- }
- if (ab->_hpp) {
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
- }
-}
-
-static int shpchprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- shpchp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-static int shpchprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- shpchprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-static int shpchprm_add_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
-
- for (res = *aprh; res; res = res->next) {
- if ((res->base + res->length) == base) {
- res->length += size;
- size = 0L;
- break;
- }
- if (res->next == *aprh)
- break;
- }
-
- if (size) {
- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!res) {
- err ("acpi_shpchprm: alloc for res fail\n");
- return -ENOMEM;
- }
- memset(res, 0, sizeof (struct pci_resource));
-
- res->base = base;
- res->length = size;
- res->next = *aprh;
- *aprh = res;
- }
-
- return 0;
-}
-
-static int shpchprm_add_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
- int rc = 0;
-
- for (res = this; res && !rc; res = res->next)
- rc = shpchprm_add_resource(aprh, res->base, res->length);
-
- return rc;
-}
-
-static void acpi_parse_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
-{
- struct acpi_resource_io *dataio;
- dataio = (struct acpi_resource_io *) data;
-
- dbg("Io Resource\n");
- dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
- dbg(" Range minimum base: %08X\n", dataio->min_base_address);
- dbg(" Range maximum base: %08X\n", dataio->max_base_address);
- dbg(" Alignment: %08X\n", dataio->alignment);
- dbg(" Range Length: %08X\n", dataio->range_length);
-}
-
-static void acpi_parse_fixed_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
-{
- struct acpi_resource_fixed_io *datafio;
- datafio = (struct acpi_resource_fixed_io *) data;
-
- dbg("Fixed Io Resource\n");
- dbg(" Range base address: %08X", datafio->base_address);
- dbg(" Range length: %08X", datafio->range_length);
-}
-
-static void acpi_parse_address16_32 (
- struct acpi_bridge *ab,
- union acpi_resource_data *data,
- acpi_resource_type id
- )
-{
- /*
- * acpi_resource_address16 == acpi_resource_address32
- * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
- */
- struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
- struct pci_resource **aprh, **tprh;
-
- if (id == ACPI_RSTYPE_ADDRESS16)
- dbg("acpi_shpchprm:16-Bit Address Space Resource\n");
- else
- dbg("acpi_shpchprm:32-Bit Address Space Resource\n");
-
- switch (data32->resource_type) {
- case ACPI_MEMORY_RANGE:
- dbg(" Resource Type: Memory Range\n");
- aprh = &ab->mem_head;
- tprh = &ab->tmem_head;
-
- switch (data32->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- dbg(" Type Specific: Noncacheable memory\n");
- break;
- case ACPI_CACHABLE_MEMORY:
- dbg(" Type Specific: Cacheable memory\n");
- break;
- case ACPI_WRITE_COMBINING_MEMORY:
- dbg(" Type Specific: Write-combining memory\n");
- break;
- case ACPI_PREFETCHABLE_MEMORY:
- aprh = &ab->p_mem_head;
- dbg(" Type Specific: Prefetchable memory\n");
- break;
- default:
- dbg(" Type Specific: Invalid cache attribute\n");
- break;
- }
-
- dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
- break;
-
- case ACPI_IO_RANGE:
- dbg(" Resource Type: I/O Range\n");
- aprh = &ab->io_head;
- tprh = &ab->tio_head;
-
- switch (data32->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- dbg(" Type Specific: Non-ISA Io Addresses\n");
- break;
- case ACPI_ISA_ONLY_RANGES:
- dbg(" Type Specific: ISA Io Addresses\n");
- break;
- case ACPI_ENTIRE_RANGE:
- dbg(" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
- default:
- dbg(" Type Specific: Invalid range attribute\n");
- break;
- }
- break;
-
- case ACPI_BUS_NUMBER_RANGE:
- dbg(" Resource Type: Bus Number Range(fixed)\n");
- /* fixup to be compatible with the rest of php driver */
- data32->min_address_range++;
- data32->address_length--;
- aprh = &ab->bus_head;
- tprh = &ab->tbus_head;
- break;
- default:
- dbg(" Resource Type: Invalid resource type. Exiting.\n");
- return;
- }
-
- dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
- dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
- dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
- dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
- dbg(" Granularity: %08X\n", data32->granularity);
- dbg(" Address range min: %08X\n", data32->min_address_range);
- dbg(" Address range max: %08X\n", data32->max_address_range);
- dbg(" Address translation offset: %08X\n", data32->address_translation_offset);
- dbg(" Address Length: %08X\n", data32->address_length);
-
- if (0xFF != data32->resource_source.index) {
- dbg(" Resource Source Index: %X\n", data32->resource_source.index);
- /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */
- }
-
- shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);
-}
-
-static acpi_status acpi_parse_crs(
- struct acpi_bridge *ab,
- struct acpi_resource *crsbuf
- )
-{
- acpi_status status = AE_OK;
- struct acpi_resource *resource = crsbuf;
- u8 count = 0;
- u8 done = 0;
-
- while (!done) {
- dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
- switch (resource->id) {
- case ACPI_RSTYPE_IRQ:
- dbg("Irq -------- Resource\n");
- break;
- case ACPI_RSTYPE_DMA:
- dbg("DMA -------- Resource\n");
- break;
- case ACPI_RSTYPE_START_DPF:
- dbg("Start DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_DPF:
- dbg("End DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_IO:
- acpi_parse_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_FIXED_IO:
- acpi_parse_fixed_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_VENDOR:
- dbg("Vendor -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_TAG:
- dbg("End_tag -------- Resource\n");
- done = 1;
- break;
- case ACPI_RSTYPE_MEM24:
- dbg("Mem24 -------- Resource\n");
- break;
- case ACPI_RSTYPE_MEM32:
- dbg("Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_FIXED_MEM32:
- dbg("Fixed Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_ADDRESS16:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
- break;
- case ACPI_RSTYPE_ADDRESS32:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
- break;
- case ACPI_RSTYPE_ADDRESS64:
- info("Address64 -------- Resource unparsed\n");
- break;
- case ACPI_RSTYPE_EXT_IRQ:
- dbg("Ext Irq -------- Resource\n");
- break;
- default:
- dbg("Invalid -------- resource type 0x%x\n", resource->id);
- break;
- }
-
- resource = (struct acpi_resource *) ((char *)resource + resource->length);
- }
-
return status;
}
-static acpi_status acpi_get_crs( struct acpi_bridge *ab)
+static void acpi_run_oshp(acpi_handle handle)
{
acpi_status status;
- struct acpi_resource *crsbuf;
-
- status = acpi_evaluate_crs(ab->handle, &crsbuf);
- if (ACPI_SUCCESS(status)) {
- status = acpi_parse_crs(ab, crsbuf);
- kfree(crsbuf);
-
- shpchp_resource_sort_and_combine(&ab->bus_head);
- shpchp_resource_sort_and_combine(&ab->io_head);
- shpchp_resource_sort_and_combine(&ab->mem_head);
- shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
- shpchprm_add_resources (&ab->tio_head, ab->io_head);
- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
- shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
- }
-
- return status;
-}
-
-/* find acpi_bridge downword from ab. */
-static struct acpi_bridge *
-find_acpi_bridge_by_bus(
- struct acpi_bridge *ab,
- int seg,
- int bus /* pdev->subordinate->number */
- )
-{
- struct acpi_bridge *lab = NULL;
-
- if (!ab)
- return NULL;
-
- if ((ab->bus == bus) && (ab->seg == seg))
- return ab;
-
- if (ab->child)
- lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
-
- if (!lab)
- if (ab->next)
- lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
-
- return lab;
-}
-
-/*
- * Build a device tree of ACPI PCI Bridges
- */
-static void shpchprm_acpi_register_a_bridge (
- struct acpi_bridge **head,
- struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
- struct acpi_bridge *cab /* child bridge to add */
- )
-{
- struct acpi_bridge *lpab;
- struct acpi_bridge *lcab;
-
- lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
- if (!lpab) {
- if (!(pab->type & BRIDGE_TYPE_HOST))
- warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
- pab->next = *head;
- *head = pab;
- lpab = pab;
- }
-
- if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
- return;
-
- lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
- if (lcab) {
- if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
- err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
- return;
- } else
- lcab = cab;
-
- lcab->parent = lpab;
- lcab->next = lpab->child;
- lpab->child = lcab;
-}
-
-static acpi_status shpchprm_acpi_build_php_slots_callback(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong bus_num;
- ulong seg_num;
- ulong sun, adr;
- ulong padr = 0;
- acpi_handle phandle = NULL;
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *lab;
- acpi_status status;
u8 *path_name = acpi_path_name(handle);
- /* get _SUN */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
- switch(status) {
- case AE_NOT_FOUND:
- return AE_OK;
- default:
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
- return status;
- }
- }
-
- /* get _ADR. _ADR must exist if _SUN exists */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return status;
- }
-
- dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
-
- status = acpi_get_parent(handle, &phandle);
+ /* run OSHP */
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
- return (status);
- }
-
- bus_num = pab->bus;
- seg_num = pab->seg;
-
- if (pab->bus == bus_num) {
- lab = pab;
+ err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+ status);
} else {
- dbg("WARN: pab is not parent\n");
- lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
- if (!lab) {
- dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
- lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!lab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return AE_NO_MEMORY;
- }
- memset(lab, 0, sizeof(struct acpi_bridge));
-
- lab->handle = phandle;
- lab->pbus = pab->bus;
- lab->pdevice = (int)(padr >> 16) & 0xffff;
- lab->pfunction = (int)(padr & 0xffff);
- lab->bus = (int)bus_num;
- lab->scanned = 0;
- lab->type = BRIDGE_TYPE_P2P;
-
- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
- } else
- dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
}
-
- acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
- return (status);
-}
-
-static int shpchprm_acpi_build_php_slots(
- struct acpi_bridge *ab,
- u32 depth
- )
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
-
- /* Walk down this pci bridge to get _SUNs if any behind P2P */
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- ab->handle,
- depth,
- shpchprm_acpi_build_php_slots_callback,
- ab,
- NULL );
- if (ACPI_FAILURE(status)) {
- dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
- return -1;
- }
-
- return 0;
-}
-
-static void build_a_bridge(
- struct acpi_bridge *pab,
- struct acpi_bridge *ab
- )
-{
- u8 *path_name = acpi_path_name(ab->handle);
-
- shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("acpi_shpchprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- };
-
- /* build any immediate PHP slots under this pci bridge */
- shpchprm_acpi_build_php_slots(ab, 1);
-}
-
-static struct acpi_bridge * add_p2p_bridge(
- acpi_handle handle,
- struct acpi_bridge *pab, /* parent */
- ulong adr
- )
-{
- struct acpi_bridge *ab;
- struct pci_dev *pdev;
- ulong devnum, funcnum;
- u8 *path_name = acpi_path_name(handle);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev || !pdev->subordinate) {
- err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
- kfree(ab);
- return NULL;
- }
-
- ab->handle = handle;
- ab->seg = pab->seg;
- ab->pbus = pab->bus; /* or pdev->bus->number */
- ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
- ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
- ab->bus = pdev->subordinate->number;
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_P2P;
-
- dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
- pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- pab->bus, (u32)devnum, (u32)funcnum, path_name);
-
- build_a_bridge(pab, ab);
-
- return ab;
-}
-
-static acpi_status scan_p2p_bridge(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *ab;
- acpi_status status;
- ulong adr = 0;
- u8 *path_name = acpi_path_name(handle);
- ulong devnum, funcnum;
- struct pci_dev *pdev;
-
- /* get device, function */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND)
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return AE_OK;
- }
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev)
- return AE_OK;
- if (!pdev->subordinate)
- return AE_OK;
-
- ab = add_p2p_bridge(handle, pab, adr);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- (u32)1,
- scan_p2p_bridge,
- ab,
- NULL);
- if (ACPI_FAILURE(status))
- dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
- }
-
- return AE_OK;
-}
-
-static struct acpi_bridge * add_host_bridge(
- acpi_handle handle,
- ulong segnum,
- ulong busnum
- )
-{
- ulong adr = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get device, function: host br adr is always 0000 though. */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
- return NULL;
- }
- dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum,
- (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_shpchprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- ab->handle = handle;
- ab->seg = (int)segnum;
- ab->bus = ab->pbus = (int)busnum;
- ab->pdevice = (int)(adr >> 16) & 0xffff;
- ab->pfunction = (int)(adr & 0xffff);
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_HOST;
-
- /* get root pci bridge's current resources */
- status = acpi_get_crs(ab);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
- kfree(ab);
- return NULL;
- }
- build_a_bridge(ab, ab);
-
- return ab;
-}
-
-static acpi_status acpi_scan_from_root_pci_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong segnum = 0;
- ulong busnum = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND) {
- err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
- return status;
- }
- segnum = 0;
- }
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
- return (status);
- }
-
- ab = add_host_bridge(handle, segnum, busnum);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- 1,
- scan_p2p_bridge,
- ab,
- NULL);
- if (ACPI_FAILURE(status))
- dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
- }
-
- return AE_OK;
-}
-
-static int shpchprm_acpi_scan_pci (void)
-{
- acpi_status status;
-
- /*
- * TBD: traverse LDM device tree with the help of
- * unified ACPI augmented for php device population.
- */
- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
- acpi_scan_from_root_pci_callback,
- NULL,
- NULL );
- if (ACPI_FAILURE(status)) {
- err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
- return -1;
- }
-
- return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctlr_type)
-{
- int rc;
-
- if (ctlr_type != PCI)
- return -ENODEV;
-
- dbg("shpchprm ACPI init <enter>\n");
- acpi_bridges_head = NULL;
-
- /* construct PCI bus:device tree of acpi_handles */
- rc = shpchprm_acpi_scan_pci();
- if (rc)
- return rc;
-
- dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
- return rc;
-}
-
-static void free_a_slot(struct acpi_php_slot *aps)
-{
- dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
-
- free_pci_resource (aps->io_head);
- free_pci_resource (aps->bus_head);
- free_pci_resource (aps->mem_head);
- free_pci_resource (aps->p_mem_head);
-
- kfree(aps);
-}
-
-static void free_a_bridge( struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps, *next;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- };
-
- /* free slots first */
- for (aps = ab->slots; aps; aps = next) {
- next = aps->next;
- free_a_slot(aps);
- }
-
- free_pci_resource (ab->io_head);
- free_pci_resource (ab->tio_head);
- free_pci_resource (ab->bus_head);
- free_pci_resource (ab->tbus_head);
- free_pci_resource (ab->mem_head);
- free_pci_resource (ab->tmem_head);
- free_pci_resource (ab->p_mem_head);
- free_pci_resource (ab->tp_mem_head);
-
- kfree(ab);
-}
-
-static void shpchprm_free_bridges ( struct acpi_bridge *ab)
-{
- if (!ab)
- return;
-
- if (ab->child)
- shpchprm_free_bridges (ab->child);
-
- if (ab->next)
- shpchprm_free_bridges (ab->next);
-
- free_a_bridge(ab);
-}
-
-void shpchprm_cleanup(void)
-{
- shpchprm_free_bridges (acpi_bridges_head);
-}
-
-static int get_number_of_slots (
- struct acpi_bridge *ab,
- int selfonly
- )
-{
- struct acpi_php_slot *aps;
- int prev_slot = -1;
- int slot_num = 0;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->dev != prev_slot) {
- prev_slot = aps->dev;
- slot_num++;
- }
-
- if (ab->child)
- slot_num += get_number_of_slots (ab->child, 0);
-
- if (selfonly)
- return slot_num;
-
- if (ab->next)
- slot_num += get_number_of_slots (ab->next, 0);
-
- return slot_num;
-}
-
-static int print_acpi_resources (struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps;
- int i;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
- break;
- case BRIDGE_TYPE_P2P:
- dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
- break;
- };
-
- print_pci_resources (ab);
-
- for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
- if (aps->dev == i)
- continue;
- dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
- print_slot_resources(aps);
- i = aps->dev;
- }
-
- if (ab->child)
- print_acpi_resources (ab->child);
-
- if (ab->next)
- print_acpi_resources (ab->next);
-
- return 0;
-}
-
-int shpchprm_print_pirt(void)
-{
- dbg("SHPCHPRM ACPI Slots\n");
- if (acpi_bridges_head)
- print_acpi_resources (acpi_bridges_head);
- return 0;
-}
-
-static struct acpi_php_slot * get_acpi_slot (
- struct acpi_bridge *ab,
- u32 sun
- )
-{
- struct acpi_php_slot *aps = NULL;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->sun == sun)
- return aps;
-
- if (!aps && ab->child) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
- if (aps)
- return aps;
- }
-
- if (!aps && ab->next) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
- if (aps)
- return aps;
- }
-
- return aps;
-
-}
-
-#if 0
-static void * shpchprm_get_slot(struct slot *slot)
-{
- struct acpi_bridge *ab = acpi_bridges_head;
- struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number);
-
- aps->slot = slot;
-
- dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-
- return (void *)aps;
-}
-#endif
-
-static void shpchprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static void shpchprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-static int shpchprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = shpchprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- func = shpchp_slot_find(busn, devn, funn);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- shpchprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- shpchprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
- return 0;
-}
-
-static int bind_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int status = 0;
-
- if (ab->bus_head) {
- dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
- if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))
- warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->io_head) {
- dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
- if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))
- warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->mem_head) {
- dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
- if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))
- warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->p_mem_head) {
- dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus);
- status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
- if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
- warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus);
-
- return status;
-}
-
-static int no_pci_resources( struct acpi_bridge *ab)
-{
- return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
-}
-
-static int find_pci_bridge_resources (
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
- struct pci_func func;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ab->pbus;
- func.device = ab->pdevice;
- func.function = ab->pfunction;
- func.is_a_board = 1;
-
- /* Get used resources for this PCI bridge */
- rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-
- ab->io_head = func.io_head;
- ab->mem_head = func.mem_head;
- ab->p_mem_head = func.p_mem_head;
- ab->bus_head = func.bus_head;
- if (ab->bus_head)
- shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);
-
- return rc;
-}
-
-static int get_pci_resources_from_bridge(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
-
- rc = find_pci_bridge_resources (ctrl, ab);
-
- shpchp_resource_sort_and_combine(&ab->bus_head);
- shpchp_resource_sort_and_combine(&ab->io_head);
- shpchp_resource_sort_and_combine(&ab->mem_head);
- shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
- shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
- shpchprm_add_resources (&ab->tio_head, ab->io_head);
- shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
- shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-
- return rc;
-}
-
-static int get_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- if (no_pci_resources(ab)) {
- dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
- rc = get_pci_resources_from_bridge(ctrl, ab);
- }
-
- return rc;
}
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
@@ -1570,144 +147,40 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-/*
- * Get resources for this ctrl.
- * 1. get total resources from ACPI _CRS or bridge (this ctrl)
- * 2. find used resources of existing adapters
- * 3. subtract used resources from total resources
- */
-int shpchprm_find_available_resources( struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- int rc = 0;
- struct acpi_bridge *ab;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
- if (!ab) {
- err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
- return -1;
- }
- if (no_pci_resources(ab)) {
- rc = get_pci_resources(ctrl, ab);
- if (rc) {
- err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);
- return -1;
- }
- }
-
- rc = bind_pci_resources(ctrl, ab);
- dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- shpchprm_dump_ctrl_res(ctrl);
-
- bind_pci_resources_to_slots (ctrl);
-
- dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- shpchprm_dump_ctrl_res(ctrl);
-
- return rc;
-}
-
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type
- )
-{
- struct acpi_bridge *ab;
- struct pci_bus lpci_bus, *pci_bus;
- int rc = 0;
- unsigned int devfn;
- u8 cls= 0x08; /* default cache line size */
- u8 lt = 0x40; /* default latency timer */
- u8 ep = 0;
- u8 es = 0;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-
- if (ab) {
- if (ab->_hpp) {
- lt = (u8)ab->_hpp->latency_timer;
- cls = (u8)ab->_hpp->cache_line_size;
- ep = (u8)ab->_hpp->enable_perr;
- es = (u8)ab->_hpp->enable_serr;
- } else
- dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
- } else
- dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
- }
-
- /* set base Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
- dbg(" set latency timer =0x%02x: %x\n", lt, rc);
-
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
- dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
-
- return rc;
+ /*
+ * OSHP is an optional ACPI firmware control method. If present,
+ * we need to run it to inform BIOS that we will control SHPC
+ * hardware from now on.
+ */
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ if (!handle)
+ return;
+ acpi_run_oshp(handle);
}
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- u16 command, cmd, bcommand, bcmd;
- struct pci_bus lpci_bus, *pci_bus;
- struct acpi_bridge *ab;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
- }
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = dev;
- cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
- if (ab) {
- if (ab->_hpp) {
- if (ab->_hpp->enable_perr) {
- command |= PCI_COMMAND_PARITY;
- bcommand |= PCI_BRIDGE_CTL_PARITY;
- } else {
- command &= ~PCI_COMMAND_PARITY;
- bcommand &= ~PCI_BRIDGE_CTL_PARITY;
- }
- if (ab->_hpp->enable_serr) {
- command |= PCI_COMMAND_SERR;
- bcommand |= PCI_BRIDGE_CTL_SERR;
- } else {
- command &= ~PCI_COMMAND_SERR;
- bcommand &= ~PCI_BRIDGE_CTL_SERR;
- }
- } else
- dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
- } else
- dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-
- if (command != cmd) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
- }
- if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+ /*
+ * _HPP settings apply to all child buses, until another _HPP is
+ * encountered. If we don't find an _HPP for the input pci dev,
+ * look for it in the parent device scope since that would apply to
+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
+ */
+ while (pdev && (ACPI_FAILURE(status))) {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+ if (!handle)
+ break;
+ status = acpi_run_hpp(handle, hpp);
+ if (!(pdev->bus->parent))
+ break;
+ /* Check if a parent object supports _HPP */
+ pdev = pdev->bus->parent->self;
}
}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c
index 37fa77a98289..ed6c1254bf6f 100644
--- a/drivers/pci/hotplug/shpchprm_legacy.c
+++ b/drivers/pci/hotplug/shpchprm_legacy.c
@@ -23,37 +23,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>,<dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
#include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_legacy.h"
-
-static void __iomem *shpchp_rom_start;
-static u16 unused_IRQ;
-
-void shpchprm_cleanup(void)
-{
- if (shpchp_rom_start)
- iounmap(shpchp_rom_start);
-}
-
-int shpchprm_print_pirt(void)
-{
- return 0;
-}
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
{
@@ -63,377 +41,14 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-/* Find the Hot Plug Resource Table in the specified region of memory */
-static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- void __iomem *fp;
- void __iomem *endp;
- u8 temp1, temp2, temp3, temp4;
- int status = 0;
-
- endp = (end - sizeof(struct hrt) + 1);
-
- for (fp = begin; fp <= endp; fp += 16) {
- temp1 = readb(fp + SIG0);
- temp2 = readb(fp + SIG1);
- temp3 = readb(fp + SIG2);
- temp4 = readb(fp + SIG3);
- if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
- status = 1;
- break;
- }
- }
-
- if (!status)
- fp = NULL;
-
- dbg("Discovered Hotplug Resource Table at %p\n", fp);
- return fp;
+ return;
}
-/*
- * shpchprm_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- u8 populated_slot;
- u8 bridged_slot;
- void __iomem *one_slot;
- struct pci_func *func = NULL;
- int i = 10, index = 0;
- u32 temp_dword, rc;
- ulong temp_ulong;
- struct pci_resource *mem_node;
- struct pci_resource *p_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- void __iomem *rom_resource_table;
- struct pci_bus lpci_bus, *pci_bus;
- u8 cfgspc_irq, temp;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
- dbg("rom_resource_table = %p\n", rom_resource_table);
- if (rom_resource_table == NULL)
- return -ENODEV;
-
- /* Sum all resources and setup resource maps */
- unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
- dbg("unused_IRQ = %x\n", unused_IRQ);
-
- temp = 0;
- while (unused_IRQ) {
- if (unused_IRQ & 1) {
- shpchp_disk_irq = temp;
- break;
- }
- unused_IRQ = unused_IRQ >> 1;
- temp++;
- }
-
- dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
- unused_IRQ = unused_IRQ >> 1;
- temp++;
-
- while (unused_IRQ) {
- if (unused_IRQ & 1) {
- shpchp_nic_irq = temp;
- break;
- }
- unused_IRQ = unused_IRQ >> 1;
- temp++;
- }
-
- dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
- unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
- temp = 0;
-
- pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
-
- if (!shpchp_nic_irq) {
- shpchp_nic_irq = cfgspc_irq;
- }
-
- if (!shpchp_disk_irq) {
- shpchp_disk_irq = cfgspc_irq;
- }
-
- dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
-
- one_slot = rom_resource_table + sizeof(struct hrt);
-
- i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
- dbg("number_of_entries = %d\n", i);
-
- if (!readb(one_slot + SECONDARY_BUS))
- return (1);
-
- dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
-
- while (i && readb(one_slot + SECONDARY_BUS)) {
- u8 dev_func = readb(one_slot + DEV_FUNC);
- u8 primary_bus = readb(one_slot + PRIMARY_BUS);
- u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
- u8 max_bus = readb(one_slot + MAX_BUS);
- u16 io_base = readw(one_slot + IO_BASE);
- u16 io_length = readw(one_slot + IO_LENGTH);
- u16 mem_base = readw(one_slot + MEM_BASE);
- u16 mem_length = readw(one_slot + MEM_LENGTH);
- u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
- u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
- dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
- dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
- primary_bus, secondary_bus, max_bus);
-
- /* If this entry isn't for our controller's bus, ignore it */
- if (primary_bus != ctrl->slot_bus) {
- i--;
- one_slot += sizeof(struct slot_rt);
- continue;
- }
- /* find out if this entry is for an occupied slot */
- temp_dword = 0xFFFFFFFF;
- pci_bus->number = primary_bus;
- pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-
- dbg("temp_D_word = %x\n", temp_dword);
-
- if (temp_dword != 0xFFFFFFFF) {
- index = 0;
- func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
-
- while (func && (func->function != (dev_func & 0x07))) {
- dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
- func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
- }
-
- /* If we can't find a match, skip this table entry */
- if (!func) {
- i--;
- one_slot += sizeof(struct slot_rt);
- continue;
- }
- /* this may not work and shouldn't be used */
- if (secondary_bus != primary_bus)
- bridged_slot = 1;
- else
- bridged_slot = 0;
-
- populated_slot = 1;
- } else {
- populated_slot = 0;
- bridged_slot = 0;
- }
- dbg("slot populated =%s \n", populated_slot?"yes":"no");
-
- /* If we've got a valid IO base, use it */
-
- temp_ulong = io_base + io_length;
-
- if ((io_base) && (temp_ulong <= 0x10000)) {
- io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)io_base;
- io_node->length = (ulong)io_length;
- dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-
- if (!populated_slot) {
- io_node->next = ctrl->io_head;
- ctrl->io_head = io_node;
- } else {
- io_node->next = func->io_head;
- func->io_head = io_node;
- }
- }
-
- /* If we've got a valid memory base, use it */
- temp_ulong = mem_base + mem_length;
- if ((mem_base) && (temp_ulong <= 0x10000)) {
- mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!mem_node)
- return -ENOMEM;
-
- mem_node->base = (ulong)mem_base << 16;
- mem_node->length = (ulong)(mem_length << 16);
- dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-
- if (!populated_slot) {
- mem_node->next = ctrl->mem_head;
- ctrl->mem_head = mem_node;
- } else {
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- }
-
- /*
- * If we've got a valid prefetchable memory base, and
- * the base + length isn't greater than 0xFFFF
- */
- temp_ulong = pre_mem_base + pre_mem_length;
- if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
- p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!p_mem_node)
- return -ENOMEM;
-
- p_mem_node->base = (ulong)pre_mem_base << 16;
- p_mem_node->length = (ulong)pre_mem_length << 16;
- dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-
- if (!populated_slot) {
- p_mem_node->next = ctrl->p_mem_head;
- ctrl->p_mem_head = p_mem_node;
- } else {
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- }
- }
-
- /*
- * If we've got a valid bus number, use it
- * The second condition is to ignore bus numbers on
- * populated slots that don't have PCI-PCI bridges
- */
- if (secondary_bus && (secondary_bus != primary_bus)) {
- bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!bus_node)
- return -ENOMEM;
-
- bus_node->base = (ulong)secondary_bus;
- bus_node->length = (ulong)(max_bus - secondary_bus + 1);
- dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-
- if (!populated_slot) {
- bus_node->next = ctrl->bus_head;
- ctrl->bus_head = bus_node;
- } else {
- bus_node->next = func->bus_head;
- func->bus_head = bus_node;
- }
- }
-
- i--;
- one_slot += sizeof(struct slot_rt);
- }
-
- /* If all of the following fail, we don't have any resources for hot plug add */
- rc = 1;
- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- return (rc);
+ return;
}
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u32 rc;
- u8 temp_byte;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- temp_byte = 0x40; /* hard coded value for LT */
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
- if (rc) {
- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus,
- func->device, func->function);
- return rc;
- }
- }
-
- /* set base Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
- if (rc) {
- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- return rc;
- }
-
- /* set Cache Line size */
- temp_byte = 0x08; /* hard coded value for CLS */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
- if (rc) {
- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- }
-
- /* set enable_perr */
- /* set enable_serr */
-
- return rc;
-}
-
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, bcommand;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
- | PCI_BRIDGE_CTL_NO_ISA;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
- shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
- if (!shpchp_rom_start) {
- err("Could not ioremap memory region for ROM\n");
- return -EIO;
- }
-
- return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctrl_type)
-{
- int retval;
-
- switch (ctrl_type) {
- case PCI:
- retval = legacy_shpchprm_init_pci();
- break;
- default:
- retval = -ENODEV;
- break;
- }
-
- return retval;
-}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h
deleted file mode 100644
index 29ccea5e57e5..000000000000
--- a/drivers/pci/hotplug/shpchprm_legacy.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_LEGACY_H_
-#define _SHPCHPRM_LEGACY_H_
-
-#define ROM_PHY_ADDR 0x0F0000
-#define ROM_PHY_LEN 0x00FFFF
-
-struct slot_rt {
- u8 dev_func;
- u8 primary_bus;
- u8 secondary_bus;
- u8 max_bus;
- u16 io_base;
- u16 io_length;
- u16 mem_base;
- u16 mem_length;
- u16 pre_mem_base;
- u16 pre_mem_length;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
-enum slot_rt_offsets {
- DEV_FUNC = offsetof(struct slot_rt, dev_func),
- PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
- SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
- MAX_BUS = offsetof(struct slot_rt, max_bus),
- IO_BASE = offsetof(struct slot_rt, io_base),
- IO_LENGTH = offsetof(struct slot_rt, io_length),
- MEM_BASE = offsetof(struct slot_rt, mem_base),
- MEM_LENGTH = offsetof(struct slot_rt, mem_length),
- PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
- PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
-};
-
-struct hrt {
- char sig0;
- char sig1;
- char sig2;
- char sig3;
- u16 unused_IRQ;
- u16 PCIIRQ;
- u8 number_of_entries;
- u8 revision;
- u16 reserved1;
- u32 reserved2;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug resource table registers based on the above structure layout */
-enum hrt_offsets {
- SIG0 = offsetof(struct hrt, sig0),
- SIG1 = offsetof(struct hrt, sig1),
- SIG2 = offsetof(struct hrt, sig2),
- SIG3 = offsetof(struct hrt, sig3),
- UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
- PCIIRQ = offsetof(struct hrt, PCIIRQ),
- NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
- REVISION = offsetof(struct hrt, revision),
- HRT_RESERVED1 = offsetof(struct hrt, reserved1),
- HRT_RESERVED2 = offsetof(struct hrt, reserved2),
-};
-
-struct irq_info {
- u8 bus, devfn; /* bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__ ((packed)) irq[4];
- u8 slot; /* slot number, 0=onboard */
- u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif /* _SHPCHPRM_LEGACY_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c
index 88f4d9f41886..c6b40998eeb3 100644
--- a/drivers/pci/hotplug/shpchprm_nonacpi.c
+++ b/drivers/pci/hotplug/shpchprm_nonacpi.c
@@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
+ * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
@@ -32,24 +32,9 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
-#include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_nonacpi.h"
+#include <linux/slab.h>
-void shpchprm_cleanup(void)
-{
- return;
-}
-
-int shpchprm_print_pirt(void)
-{
- return 0;
-}
+#include "shpchp.h"
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
{
@@ -60,375 +45,13 @@ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busn
return 0;
}
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-
-static void phprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static int phprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int phprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- shpchp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-
-static int phprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- phprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = phprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- func = shpchp_slot_find(busn, devn, funn);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- phprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- phprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
- return 0;
-}
-
-static void phprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-/*
- * phprm_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
-{
- struct pci_func func;
- u32 rc;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ctrl->bus;
- func.device = ctrl->device;
- func.function = ctrl->function;
- func.is_a_board = 1;
-
- /* Get resources for this PCI bridge */
- rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
- dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc);
-
- if (func.mem_head)
- func.mem_head->next = ctrl->mem_head;
- ctrl->mem_head = func.mem_head;
-
- if (func.p_mem_head)
- func.p_mem_head->next = ctrl->p_mem_head;
- ctrl->p_mem_head = func.p_mem_head;
-
- if (func.io_head)
- func.io_head->next = ctrl->io_head;
- ctrl->io_head = func.io_head;
-
- if(func.bus_head)
- func.bus_head->next = ctrl->bus_head;
- ctrl->bus_head = func.bus_head;
- if (ctrl->bus_head)
- phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
- dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
- bind_pci_resources_to_slots (ctrl);
-
- dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
-
-
- /* If all of the following fail, we don't have any resources for hot plug add */
- rc = 1;
- rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
- rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
- return (rc);
-}
-
-int shpchprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- u32 rc;
- u8 temp_byte;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- temp_byte = 0x40; /* hard coded value for LT */
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus,
- func->device, func->function);
- return rc;
- }
- }
-
- /* set base Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- return rc;
- }
-
- /* set Cache Line size */
- temp_byte = 0x08; /* hard coded value for CLS */
-
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
- if (rc) {
- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- }
-
- /* set enable_perr */
- /* set enable_serr */
-
- return rc;
-}
-
-void shpchprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, bcommand;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-
- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
- | PCI_BRIDGE_CTL_NO_ISA;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
- return 0;
+ return;
}
-int shpchprm_init(enum php_ctlr_type ctrl_type)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- int retval;
-
- switch (ctrl_type) {
- case PCI:
- retval = legacy_shpchprm_init_pci();
- break;
- default:
- retval = -ENODEV;
- break;
- }
-
- return retval;
+ return;
}
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h
deleted file mode 100644
index 6bc8668023c3..000000000000
--- a/drivers/pci/hotplug/shpchprm_nonacpi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_NONACPI_H_
-#define _SHPCHPRM_NONACPI_H_
-
-struct irq_info {
- u8 bus, devfn; /* bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__ ((packed)) irq[4];
- u8 slot; /* slot number, 0=onboard */
- u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif /* _SHPCHPRM_NONACPI_H_ */
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index b5ab9aa6ff7c..a2033552423c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -91,6 +91,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
struct msi_desc *entry;
struct msg_address address;
+ unsigned int irq = vector;
entry = (struct msi_desc *)msi_desc[vector];
if (!entry || !entry->dev)
@@ -112,6 +113,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
address.lo_address.value);
+ set_native_irq_info(irq, cpu_mask);
break;
}
case PCI_CAP_ID_MSIX:
@@ -125,22 +127,13 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
MSI_TARGET_CPU_SHIFT);
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
writel(address.lo_address.value, entry->mask_base + offset);
+ set_native_irq_info(irq, cpu_mask);
break;
}
default:
break;
}
}
-
-#ifdef CONFIG_IRQBALANCE
-static inline void move_msi(int vector)
-{
- if (!cpus_empty(pending_irq_balance_cpumask[vector])) {
- set_msi_affinity(vector, pending_irq_balance_cpumask[vector]);
- cpus_clear(pending_irq_balance_cpumask[vector]);
- }
-}
-#endif /* CONFIG_IRQBALANCE */
#endif /* CONFIG_SMP */
static void mask_MSI_irq(unsigned int vector)
@@ -191,13 +184,13 @@ static void shutdown_msi_irq(unsigned int vector)
static void end_msi_irq_wo_maskbit(unsigned int vector)
{
- move_msi(vector);
+ move_native_irq(vector);
ack_APIC_irq();
}
static void end_msi_irq_w_maskbit(unsigned int vector)
{
- move_msi(vector);
+ move_native_irq(vector);
unmask_MSI_irq(vector);
ack_APIC_irq();
}
@@ -446,14 +439,11 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u16 cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_intx(dev, 0); /* disable intx */
}
}
-static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
+void disable_msi_mode(struct pci_dev *dev, int pos, int type)
{
u16 control;
@@ -468,10 +458,7 @@ static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
}
if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
/* PCI Express Endpoint device detected */
- u16 cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_intx(dev, 1); /* enable intx */
}
}
@@ -588,6 +575,8 @@ static int msi_capability_init(struct pci_dev *dev)
/**
* msix_capability_init - configure device's MSI-X capability
* @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @entries: pointer to an array of struct msix_entry entries
+ * @nvec: number of @entries
*
* Setup the MSI-X capability structure of device function with a
* single MSI-X vector. A return of zero indicates the successful setup of
@@ -699,6 +688,9 @@ int pci_enable_msi(struct pci_dev* dev)
if (!pci_msi_enable || !dev)
return status;
+ if (dev->no_msi)
+ return status;
+
temp = dev->irq;
if ((status = msi_init()) < 0)
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 390f1851c0f1..402136a5c9e4 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -19,7 +19,6 @@
#define NR_HP_RESERVED_VECTORS 20
extern int vector_irq[NR_VECTORS];
-extern cpumask_t pending_irq_balance_cpumask[NR_IRQS];
extern void (*interrupt[NR_IRQS])(void);
extern int pci_vector_resources(int last, int nr_released);
@@ -29,10 +28,6 @@ extern int pci_vector_resources(int last, int nr_released);
#define set_msi_irq_affinity NULL
#endif
-#ifndef CONFIG_IRQBALANCE
-static inline void move_msi(int vector) {}
-#endif
-
/*
* MSI-X Address Register
*/
diff --git a/drivers/pci/names.c b/drivers/pci/names.c
deleted file mode 100644
index ad224aada7c9..000000000000
--- a/drivers/pci/names.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * PCI Class and Device Name Tables
- *
- * Copyright 1993--1999 Drew Eckhardt, Frederic Potter,
- * David Mosberger-Tang, Martin Mares
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#ifdef CONFIG_PCI_NAMES
-
-struct pci_device_info {
- unsigned short device;
- unsigned short seen;
- const char *name;
-};
-
-struct pci_vendor_info {
- unsigned short vendor;
- unsigned short nr;
- const char *name;
- struct pci_device_info *devices;
-};
-
-/*
- * This is ridiculous, but we want the strings in
- * the .init section so that they don't take up
- * real memory.. Parse the same file multiple times
- * to get all the info.
- */
-#define VENDOR( vendor, name ) static char __vendorstr_##vendor[] __devinitdata = name;
-#define ENDVENDOR()
-#define DEVICE( vendor, device, name ) static char __devicestr_##vendor##device[] __devinitdata = name;
-#include "devlist.h"
-
-
-#define VENDOR( vendor, name ) static struct pci_device_info __devices_##vendor[] __devinitdata = {
-#define ENDVENDOR() };
-#define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device },
-#include "devlist.h"
-
-static struct pci_vendor_info __devinitdata pci_vendor_list[] = {
-#define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor },
-#define ENDVENDOR()
-#define DEVICE( vendor, device, name )
-#include "devlist.h"
-};
-
-#define VENDORS (sizeof(pci_vendor_list)/sizeof(struct pci_vendor_info))
-
-void __devinit pci_name_device(struct pci_dev *dev)
-{
- const struct pci_vendor_info *vendor_p = pci_vendor_list;
- int i = VENDORS;
- char *name = dev->pretty_name;
-
- do {
- if (vendor_p->vendor == dev->vendor)
- goto match_vendor;
- vendor_p++;
- } while (--i);
-
- /* Couldn't find either the vendor nor the device */
- sprintf(name, "PCI device %04x:%04x", dev->vendor, dev->device);
- return;
-
- match_vendor: {
- struct pci_device_info *device_p = vendor_p->devices;
- int i = vendor_p->nr;
-
- while (i > 0) {
- if (device_p->device == dev->device)
- goto match_device;
- device_p++;
- i--;
- }
-
- /* Ok, found the vendor, but unknown device */
- sprintf(name, "PCI device %04x:%04x (%." PCI_NAME_HALF "s)",
- dev->vendor, dev->device, vendor_p->name);
- return;
-
- /* Full match */
- match_device: {
- char *n = name + sprintf(name, "%s %s",
- vendor_p->name, device_p->name);
- int nr = device_p->seen + 1;
- device_p->seen = nr;
- if (nr > 1)
- sprintf(n, " (#%d)", nr);
- }
- }
-}
-
-/*
- * Class names. Not in .init section as they are needed in runtime.
- */
-
-static u16 pci_class_numbers[] = {
-#define CLASS(x,y) 0x##x,
-#include "classlist.h"
-};
-
-static char *pci_class_names[] = {
-#define CLASS(x,y) y,
-#include "classlist.h"
-};
-
-char *
-pci_class_name(u32 class)
-{
- int i;
-
- for(i=0; i<sizeof(pci_class_numbers)/sizeof(pci_class_numbers[0]); i++)
- if (pci_class_numbers[i] == class)
- return pci_class_names[i];
- return NULL;
-}
-
-#else
-
-void __devinit pci_name_device(struct pci_dev *dev)
-{
-}
-
-char *
-pci_class_name(u32 class)
-{
- return NULL;
-}
-
-#endif /* CONFIG_PCI_NAMES */
-
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e4115a0d5ba6..ae986e590b48 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -7,6 +7,9 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/mempolicy.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "pci.h"
/*
@@ -25,7 +28,10 @@ struct pci_dynid {
#ifdef CONFIG_HOTPLUG
/**
- * store_new_id
+ * store_new_id - add a new PCI device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
*
* Adds a new dynamic pci device ID to this driver,
* and causes the driver to probe for all devices again.
@@ -163,10 +169,40 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv,
return NULL;
}
+static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ int error;
+#ifdef CONFIG_NUMA
+ /* Execute driver initialization on node where the
+ device's bus is attached to. This way the driver likely
+ allocates its local memory on the right node without
+ any need to change it. */
+ struct mempolicy *oldpol;
+ cpumask_t oldmask = current->cpus_allowed;
+ int node = pcibus_to_node(dev->bus);
+ if (node >= 0 && node_online(node))
+ set_cpus_allowed(current, node_to_cpumask(node));
+ /* And set default memory allocation policy */
+ oldpol = current->mempolicy;
+ current->mempolicy = &default_policy;
+ mpol_get(current->mempolicy);
+#endif
+ error = drv->probe(dev, id);
+#ifdef CONFIG_NUMA
+ set_cpus_allowed(current, oldmask);
+ mpol_free(current->mempolicy);
+ current->mempolicy = oldpol;
+#endif
+ return error;
+}
+
/**
* __pci_device_probe()
+ * @drv: driver to call to check if it wants the PCI device
+ * @pci_dev: PCI device being probed
*
- * returns 0 on success, else error.
+ * returns 0 on success, else error.
* side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
*/
static int
@@ -180,7 +216,7 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
id = pci_match_device(drv, pci_dev);
if (id)
- error = drv->probe(pci_dev, id);
+ error = pci_call_probe(drv, pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
error = 0;
@@ -243,17 +279,19 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
}
-/*
+/*
* Default resume method for devices that have no driver provided resume,
* or not even a driver at all.
*/
static void pci_default_resume(struct pci_dev *pci_dev)
{
+ int retval;
+
/* restore the PCI config space */
pci_restore_state(pci_dev);
/* if the device was enabled before suspend, reenable */
if (pci_dev->is_enabled)
- pci_enable_device(pci_dev);
+ retval = pci_enable_device(pci_dev);
/* if the device was busmaster before the suspend, make it busmaster again */
if (pci_dev->is_busmaster)
pci_set_master(pci_dev);
@@ -346,6 +384,10 @@ int pci_register_driver(struct pci_driver *drv)
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
drv->driver.shutdown = pci_device_shutdown;
+ else
+ printk(KERN_WARNING "Warning: PCI driver %s has a struct "
+ "device_driver shutdown method, please update!\n",
+ drv->name);
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
@@ -405,11 +447,11 @@ pci_dev_driver(const struct pci_dev *dev)
/**
* pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
- * @ids: array of PCI device id structures to search in
* @dev: the PCI device structure to match against
+ * @drv: the device driver to search for matching PCI device id structures
*
* Used by a driver to check whether a PCI device present in the
- * system is in its list of supported devices.Returns the matching
+ * system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
static int pci_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index cc9d65388e62..965a5934623a 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -44,10 +44,14 @@ pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");
-static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t local_cpus_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
- int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
+ cpumask_t mask;
+ int len;
+
+ mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
strcat(buf,"\n");
return 1+len;
}
@@ -126,7 +130,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 1) && size) {
u8 val;
- pci_read_config_byte(dev, off, &val);
+ pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
size--;
@@ -134,7 +138,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 3) && size > 2) {
u16 val;
- pci_read_config_word(dev, off, &val);
+ pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
@@ -143,7 +147,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
while (size > 3) {
u32 val;
- pci_read_config_dword(dev, off, &val);
+ pci_user_read_config_dword(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
data[off - init_off + 2] = (val >> 16) & 0xff;
@@ -154,7 +158,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size >= 2) {
u16 val;
- pci_read_config_word(dev, off, &val);
+ pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
@@ -163,7 +167,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size > 0) {
u8 val;
- pci_read_config_byte(dev, off, &val);
+ pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
--size;
@@ -188,7 +192,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
if ((off & 1) && size) {
- pci_write_config_byte(dev, off, data[off - init_off]);
+ pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
size--;
}
@@ -196,7 +200,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if ((off & 3) && size > 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
- pci_write_config_word(dev, off, val);
+ pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}
@@ -206,7 +210,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
val |= (u32) data[off - init_off + 1] << 8;
val |= (u32) data[off - init_off + 2] << 16;
val |= (u32) data[off - init_off + 3] << 24;
- pci_write_config_dword(dev, off, val);
+ pci_user_write_config_dword(dev, off, val);
off += 4;
size -= 4;
}
@@ -214,13 +218,13 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
if (size >= 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
- pci_write_config_word(dev, off, val);
+ pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}
if (size) {
- pci_write_config_byte(dev, off, data[off - init_off]);
+ pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
--size;
}
@@ -356,7 +360,7 @@ pci_create_resource_files(struct pci_dev *pdev)
continue;
/* allocate attribute structure, piggyback attribute name */
- res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC);
+ res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
if (res_attr) {
char *res_attr_name = (char *)(res_attr + 1);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1b34fc56067e..e74d75843047 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -222,6 +223,39 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
}
/**
+ * pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
+ * @dev: PCI device to have its BARs restored
+ *
+ * Restore the BAR values for a given device, so as to make it
+ * accessible by its driver.
+ */
+void
+pci_restore_bars(struct pci_dev *dev)
+{
+ int i, numres;
+
+ switch (dev->hdr_type) {
+ case PCI_HEADER_TYPE_NORMAL:
+ numres = 6;
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ numres = 2;
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+ numres = 1;
+ break;
+ default:
+ /* Should never get here, but just in case... */
+ return;
+ }
+
+ for (i = 0; i < numres; i ++)
+ pci_update_resource(dev, &dev->resource[i], i);
+}
+
+int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
+
+/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
* @state: PCI power state (D0, D1, D2, D3hot, D3cold) we're entering
@@ -235,11 +269,10 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
* -EIO if device does not support PCI PM.
* 0 if we can successfully change the power state.
*/
-int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
int
pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
- int pm;
+ int pm, need_restore = 0;
u16 pmcsr, pmc;
/* bound the state we're entering */
@@ -263,7 +296,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
return -EIO;
pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
- if ((pmc & PCI_PM_CAP_VER_MASK) > 2) {
+ if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
printk(KERN_DEBUG
"PCI: %s has unsupported PM cap regs version (%u)\n",
pci_name(dev), pmc & PCI_PM_CAP_VER_MASK);
@@ -271,23 +304,32 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
}
/* check if this device supports the desired state */
- if (state == PCI_D1 || state == PCI_D2) {
- if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
- return -EIO;
- else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
- return -EIO;
- }
+ if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
+ return -EIO;
+ else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
+ return -EIO;
- /* If we're in D3, force entire word to 0.
+ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+
+ /* If we're (effectively) in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= PCI_D3hot)
- pmcsr = 0;
- else {
- pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+ switch (dev->current_state) {
+ case PCI_D0:
+ case PCI_D1:
+ case PCI_D2:
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= state;
+ break;
+ case PCI_UNKNOWN: /* Boot-up */
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
+ && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ need_restore = 1;
+ /* Fall-through: force to D0 */
+ default:
+ pmcsr = 0;
+ break;
}
/* enter specified state */
@@ -308,6 +350,22 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
platform_pci_set_power_state(dev, state);
dev->current_state = state;
+
+ /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
+ * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
+ * from D3hot to D0 _may_ perform an internal reset, thereby
+ * going to "D0 Uninitialized" rather than "D0 Initialized".
+ * For example, at least some versions of the 3c905B and the
+ * 3c556B exhibit this behaviour.
+ *
+ * At least some laptop BIOSen (e.g. the Thinkpad T21) leave
+ * devices in a D3hot state at boot. Consequently, we need to
+ * restore at least the BARs so that the device will be
+ * accessible to its driver.
+ */
+ if (need_restore)
+ pci_restore_bars(dev);
+
return 0;
}
@@ -333,13 +391,17 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
if (platform_pci_choose_state) {
ret = platform_pci_choose_state(dev, state);
if (ret >= 0)
- state = ret;
+ state.event = ret;
}
- switch (state) {
- case 0: return PCI_D0;
- case 3: return PCI_D3hot;
+
+ switch (state.event) {
+ case PM_EVENT_ON:
+ return PCI_D0;
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_SUSPEND:
+ return PCI_D3hot;
default:
- printk("They asked me for state %d\n", state);
+ printk("They asked me for state %d\n", state.event);
BUG();
}
return PCI_D0;
@@ -390,8 +452,11 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
{
int err;
- pci_set_power_state(dev, PCI_D0);
- if ((err = pcibios_enable_device(dev, bars)) < 0)
+ err = pci_set_power_state(dev, PCI_D0);
+ if (err < 0 && err != -EIO)
+ return err;
+ err = pcibios_enable_device(dev, bars);
+ if (err < 0)
return err;
return 0;
}
@@ -743,6 +808,31 @@ pci_clear_mwi(struct pci_dev *dev)
}
}
+/**
+ * pci_intx - enables/disables PCI INTx for device dev
+ * @pdev: the PCI device to operate on
+ * @enable: boolean: whether to enable or disable PCI INTx
+ *
+ * Enables/disables PCI INTx for device dev
+ */
+void
+pci_intx(struct pci_dev *pdev, int enable)
+{
+ u16 pci_command, new;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
+ if (enable) {
+ new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+ } else {
+ new = pci_command | PCI_COMMAND_INTX_DISABLE;
+ }
+
+ if (new != pci_command) {
+ pci_write_config_word(pdev, PCI_COMMAND, new);
+ }
+}
+
#ifndef HAVE_ARCH_PCI_SET_DMA_MASK
/*
* These can be overridden by arch-specific implementations
@@ -805,6 +895,7 @@ struct pci_dev *isa_bridge;
EXPORT_SYMBOL(isa_bridge);
#endif
+EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_enable_device_bars);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_device);
@@ -819,6 +910,7 @@ EXPORT_SYMBOL(pci_request_region);
EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
+EXPORT_SYMBOL_GPL(pci_intx);
EXPORT_SYMBOL(pci_set_dma_mask);
EXPORT_SYMBOL(pci_set_consistent_dma_mask);
EXPORT_SYMBOL(pci_assign_resource);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d94d7af4f7a0..6527b36c9a61 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
+extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
+extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
@@ -29,7 +36,6 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif
/* Functions for PCI Hotplug drivers to use */
-extern struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
extern int pci_remove_device_safe(struct pci_dev *dev);
extern unsigned char pci_max_busnr(void);
@@ -47,6 +53,12 @@ extern int pci_msi_quirk;
#define pci_msi_quirk 0
#endif
+#ifdef CONFIG_PCI_MSI
+void disable_msi_mode(struct pci_dev *dev, int pos, int type);
+#else
+static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
+#endif
+
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
extern struct class_device_attribute class_device_attr_cpuaffinity;
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
deleted file mode 100644
index 1d2ef1e2ffc6..000000000000
--- a/drivers/pci/pci.ids
+++ /dev/null
@@ -1,10180 +0,0 @@
-#
-# List of PCI ID's
-#
-# Maintained by Martin Mares <mj@ucw.cz> and other volunteers from the
-# Linux PCI ID's Project at http://pciids.sf.net/. New data are always
-# welcome (if they are accurate), we're eagerly expecting new entries,
-# so if you have anything to contribute, please visit the home page or
-# send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
-#
-# Daily snapshot on Tue 2005-03-08 10:11:48
-#
-
-# Vendors, devices and subsystems. Please keep sorted.
-
-# Syntax:
-# vendor vendor_name
-# device device_name <-- single tab
-# subvendor subdevice subsystem_name <-- two tabs
-
-0000 Gammagraphx, Inc.
-001a Ascend Communications, Inc.
-0033 Paradyne corp.
-003d Lockheed Martin-Marietta Corp
-# Real TJN ID is e159, but they got it wrong several times --mj
-0059 Tiger Jet Network Inc. (Wrong ID)
-0070 Hauppauge computer works Inc.
- 4000 WinTV PVR-350
- 4001 WinTV PVR-250 (v1)
- 4009 WinTV PVR-250
- 4801 WinTV PVR-250 MCE
-0071 Nebula Electronics Ltd.
-0095 Silicon Image, Inc. (Wrong ID)
- 0680 Ultra ATA/133 IDE RAID CONTROLLER CARD
-0100 Ncipher Corp Ltd
-# 018a is not LevelOne but there is a board misprogrammed
-018a LevelOne
- 0106 FPC-0106TX misprogrammed [RTL81xx]
-# 021b is not Compaq but there is a board misprogrammed
-021b Compaq Computer Corporation
- 8139 HNE-300 (RealTek RTL8139c) [iPaq Networking]
-# http://www.davicom.com.tw/
-0291 Davicom Semiconductor, Inc.
- 8212 DM9102A(DM9102AE, SM9102AF) Ethernet 100/10 MBit(Rev 40)
-# SpeedStream is Efficient Networks, Inc, a Siemens Company
-02ac SpeedStream
- 1012 1012 PCMCIA 10/100 Ethernet Card [RTL81xx]
-0357 TTTech AG
- 000a TTP-Monitoring Card V2.0
-0432 SCM Microsystems, Inc.
- 0001 Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet]
-05e3 CyberDoor
- 0701 CBD516
-0675 Dynalink
- 1700 IS64PH ISDN Adapter
- 1702 IS64PH ISDN Adapter
-# Wrong ID used in subsystem ID of VIA USB controllers.
-0925 VIA Technologies, Inc. (Wrong ID)
-09c1 Arris
- 0704 CM 200E Cable Modem
-0a89 BREA Technologies Inc
-0b49 ASCII Corporation
-# see http://homepage1.nifty.com/mcn/lab/machines/trance_vibrator/usbview.vib.txt
- 064f Trance Vibrator
-0e11 Compaq Computer Corporation
- 0001 PCI to EISA Bridge
- 0002 PCI to ISA Bridge
- 0046 Smart Array 64xx
- 0e11 409a Smart Array 641
- 0e11 409b Smart Array 642
- 0e11 409c Smart Array 6400
- 0e11 409d Smart Array 6400 EM
- 0049 NC7132 Gigabit Upgrade Module
- 004a NC6136 Gigabit Server Adapter
- 007c NC7770 1000BaseTX
- 007d NC6770 1000BaseTX
- 0085 NC7780 1000BaseTX
- 00bb NC7760
- 00ca NC7771
- 00cb NC7781
- 00cf NC7772
- 00d0 NC7782
- 00d1 NC7783
- 00e3 NC7761
- 0508 Netelligent 4/16 Token Ring
- 1000 Triflex/Pentium Bridge, Model 1000
- 2000 Triflex/Pentium Bridge, Model 2000
- 3032 QVision 1280/p
- 3033 QVision 1280/p
- 3034 QVision 1280/p
- 4000 4000 [Triflex]
- 4030 SMART-2/P
- 4031 SMART-2SL
- 4032 Smart Array 3200
- 4033 Smart Array 3100ES
- 4034 Smart Array 221
- 4040 Integrated Array
- 4048 Compaq Raid LC2
- 4050 Smart Array 4200
- 4051 Smart Array 4250ES
- 4058 Smart Array 431
- 4070 Smart Array 5300
- 4080 Smart Array 5i
- 4082 Smart Array 532
- 4083 Smart Array 5312
- 4091 Smart Array 6i
- 409a Smart Array 641
- 409b Smart Array 642
- 409c Smart Array 6400
- 409d Smart Array 6400 EM
- 6010 HotPlug PCI Bridge 6010
- 7020 USB Controller
- a0ec Fibre Channel Host Controller
- a0f0 Advanced System Management Controller
- a0f3 Triflex PCI to ISA Bridge
- a0f7 PCI Hotplug Controller
- 8086 002a PCI Hotplug Controller A
- 8086 002b PCI Hotplug Controller B
- a0f8 ZFMicro Chipset USB
- a0fc FibreChannel HBA Tachyon
- ae10 Smart-2/P RAID Controller
- 0e11 4030 Smart-2/P Array Controller
- 0e11 4031 Smart-2SL Array Controller
- 0e11 4032 Smart Array Controller
- 0e11 4033 Smart 3100ES Array Controller
- ae29 MIS-L
- ae2a MPC
- ae2b MIS-E
- ae31 System Management Controller
- ae32 Netelligent 10/100 TX PCI UTP
- ae33 Triflex Dual EIDE Controller
- ae34 Netelligent 10 T PCI UTP
- ae35 Integrated NetFlex-3/P
- ae40 Netelligent Dual 10/100 TX PCI UTP
- ae43 Netelligent Integrated 10/100 TX UTP
- ae69 CETUS-L
- ae6c Northstar
- ae6d NorthStar CPU to PCI Bridge
- b011 Netelligent 10/100 TX Embedded UTP
- b012 Netelligent 10 T/2 PCI UTP/Coax
- b01e NC3120 Fast Ethernet NIC
- b01f NC3122 Fast Ethernet NIC
- b02f NC1120 Ethernet NIC
- b030 Netelligent 10/100 TX UTP
- b04a 10/100 TX PCI Intel WOL UTP Controller
- b060 Smart Array 5300 Controller
- b0c6 NC3161 Fast Ethernet NIC
- b0c7 NC3160 Fast Ethernet NIC
- b0d7 NC3121 Fast Ethernet NIC
- b0dd NC3131 Fast Ethernet NIC
- b0de NC3132 Fast Ethernet Module
- b0df NC6132 Gigabit Module
- b0e0 NC6133 Gigabit Module
- b0e1 NC3133 Fast Ethernet Module
- b123 NC6134 Gigabit NIC
- b134 NC3163 Fast Ethernet NIC
- b13c NC3162 Fast Ethernet NIC
- b144 NC3123 Fast Ethernet NIC
- b163 NC3134 Fast Ethernet NIC
- b164 NC3165 Fast Ethernet Upgrade Module
- b178 Smart Array 5i/532
- 0e11 4080 Smart Array 5i
- 0e11 4082 Smart Array 532
- 0e11 4083 Smart Array 5312
- b1a4 NC7131 Gigabit Server Adapter
-# HP Memory Hot-Plug Controller
- b200 Memory Hot-Plug Controller
- b203 Integrated Lights Out Controller
- b204 Integrated Lights Out Processor
- f130 NetFlex-3/P ThunderLAN 1.0
- f150 NetFlex-3/P ThunderLAN 2.3
-0e55 HaSoTec GmbH
-# Formerly NCR
-1000 LSI Logic / Symbios Logic
- 0001 53c810
- 1000 1000 LSI53C810AE PCI to SCSI I/O Processor
- 0002 53c820
- 0003 53c825
- 1000 1000 LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)
- 0004 53c815
- 0005 53c810AP
- 0006 53c860
- 1000 1000 LSI53C860E PCI to Ultra SCSI I/O Processor
- 000a 53c1510
- 1000 1000 LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
- 000b 53C896/897
- 0e11 6004 EOB003 Series SCSI host adapter
- 1000 1000 LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
- 1000 1010 LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
- 1000 1020 LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
-# multifunction PCI card: Dual U2W SCSI, dual 10/100TX, graphics
- 13e9 1000 6221L-4U
- 000c 53c895
- 1000 1010 LSI8951U PCI to Ultra2 SCSI host adapter
- 1000 1020 LSI8952U PCI to Ultra2 SCSI host adapter
- 1de1 3906 DC-390U2B SCSI adapter
- 1de1 3907 DC-390U2W
- 000d 53c885
- 000f 53c875
- 0e11 7004 Embedded Ultra Wide SCSI Controller
- 1000 1000 LSI53C876/E PCI to Dual Channel SCSI Controller
- 1000 1010 LSI22801 PCI to Dual Channel Ultra SCSI host adapter
- 1000 1020 LSI22802 PCI to Dual Channel Ultra SCSI host adapter
- 1092 8760 FirePort 40 Dual SCSI Controller
- 1de1 3904 DC390F/U Ultra Wide SCSI Adapter
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1050 CT7 mainboard
- 0010 53C1510
- 0e11 4040 Integrated Array Controller
- 0e11 4048 RAID LC2 Controller
- 1000 1000 53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
- 0012 53c895a
- 1000 1000 LSI53C895A PCI to Ultra2 SCSI Controller
- 0013 53c875a
- 1000 1000 LSI53C875A PCI to Ultra SCSI Controller
- 0020 53c1010 Ultra3 SCSI Adapter
- 1000 1000 LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller
- 1de1 1020 DC-390U3W
- 0021 53c1010 66MHz Ultra3 SCSI Adapter
- 1000 1000 LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
- 1000 1010 Asus TR-DLS onboard 53C1010-66
- 124b 1070 PMC-USCSI3
- 4c53 1080 CT8 mainboard
- 4c53 1300 P017 mezzanine (32-bit PMC)
- 4c53 1310 P017 mezzanine (64-bit PMC)
- 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1028 0123 PowerEdge 2600
- 1028 014a PowerEdge 1750
- 1028 016c PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)
- 1028 0183 PowerEdge 1800
- 1028 1010 LSI U320 SCSI Controller
- 0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
- 0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1000 1000 LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller
- 0033 1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 0040 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
- 1000 0033 MegaRAID SCSI 320-2XR
- 1000 0066 MegaRAID SCSI 320-2XRWS
- 0041 53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
- 008f 53c875J
- 1092 8000 FirePort 40 SCSI Controller
- 1092 8760 FirePort 40 Dual SCSI Host Adapter
- 0407 MegaRAID
- 1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller
- 1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller
- 1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller
- 1028 0531 PowerEdge Expandable RAID Controller 4/QC
- 1028 0533 PowerEdge Expandable RAID Controller 4/QC
- 8086 0530 MegaRAID Intel RAID Controller SRCZCRX
- 8086 0532 MegaRAID Intel RAID Controller SRCU42X
- 0408 MegaRAID
- 1000 0001 MegaRAID SCSI 320-1E RAID Controller
- 1000 0002 MegaRAID SCSI 320-2E RAID Controller
- 1025 004d MegaRAID ACER ROMB-2E RAID Controller
- 1028 0001 PowerEdge RAID Controller PERC4e/SC
- 1028 0002 PowerEdge RAID Controller PERC4e/DC
- 1734 1065 FSC MegaRAID PCI Express ROMB
- 8086 0002 MegaRAID Intel RAID Controller SRCU42E
- 0409 MegaRAID
- 1000 3004 MegaRAID SATA 300-4X RAID Controller
- 1000 3008 MegaRAID SATA 300-8X RAID Controller
- 8086 3008 MegaRAID RAID Controller SRCS28X
- 8086 3431 MegaRAID RAID Controller Alief SROMBU42E
- 8086 3499 MegaRAID RAID Controller Harwich SROMBU42E
- 0621 FC909 Fibre Channel Adapter
- 0622 FC929 Fibre Channel Adapter
- 1000 1020 44929 O Dual Fibre Channel card
- 0623 FC929 LAN
- 0624 FC919 Fibre Channel Adapter
- 0625 FC919 LAN
- 0626 FC929X Fibre Channel Adapter
- 1000 1010 7202-XP-LC Dual Fibre Channel card
- 0627 FC929X LAN
- 0628 FC919X Fibre Channel Adapter
- 0629 FC919X LAN
- 0701 83C885 NT50 DigitalScape Fast Ethernet
- 0702 Yellowfin G-NIC gigabit ethernet
- 1318 0000 PEI100X
- 0804 SA2010
- 0805 SA2010ZC
- 0806 SA2020
- 0807 SA2020ZC
- 0901 61C102
- 1000 63C815
- 1960 MegaRAID
- 1000 0518 MegaRAID 518 SCSI 320-2 Controller
- 1000 0520 MegaRAID 520 SCSI 320-1 Controller
- 1000 0522 MegaRAID 522 i4 133 RAID Controller
- 1000 0523 MegaRAID SATA 150-6 RAID Controller
- 1000 4523 MegaRAID SATA 150-4 RAID Controller
- 1000 a520 MegaRAID ZCR SCSI 320-0 Controller
- 1028 0518 MegaRAID 518 DELL PERC 4/DC RAID Controller
- 1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller
- 1028 0531 PowerEdge Expandable RAID Controller 4/QC
- 1028 0533 PowerEdge Expandable RAID Controller 4/QC
- 8086 0520 MegaRAIDRAID Controller SRCU41L
- 8086 0523 MegaRAID RAID Controller SRCS16
-1001 Kolter Electronic
- 0010 PCI 1616 Measurement card with 32 digital I/O lines
- 0011 OPTO-PCI Opto-Isolated digital I/O board
- 0012 PCI-AD/DA Analogue I/O board
- 0013 PCI-OPTO-RELAIS Digital I/O board with relay outputs
- 0014 PCI-Counter/Timer Counter Timer board
- 0015 PCI-DAC416 Analogue output board
- 0016 PCI-MFB Analogue I/O board
- 0017 PROTO-3 PCI Prototyping board
- 9100 INI-9100/9100W SCSI Host
-1002 ATI Technologies Inc
- 3150 M24 1P [Radeon Mobility X600]
- 3154 M24 1T [FireGL M24 GL]
- 3e50 RV380 0x3e50 [Radeon X600]
- 3e54 RV380 0x3e54 [FireGL V3200]
- 3e70 RV380 [Radeon X600] Secondary
- 4136 Radeon IGP 320 M
- 4137 Radeon IGP330/340/350
- 4144 R300 AD [Radeon 9500 Pro]
-# New PCI ID provided by ATI developer relations (correction to above)
- 4145 R300 AE [Radeon 9700 Pro]
-# New PCI ID provided by ATI developer relations (oops, correction to above)
- 4146 R300 AF [Radeon 9700 Pro]
- 4147 R300 AG [FireGL Z1/X1]
- 4148 R350 AH [Radeon 9800]
- 4149 R350 AI [Radeon 9800]
- 414a R350 AJ [Radeon 9800]
- 414b R350 AK [Fire GL X2]
-# New PCI ID provided by ATI developer relations
- 4150 RV350 AP [Radeon 9600]
- 1002 0002 R9600 Pro primary (Asus OEM for HP)
- 1002 0003 R9600 Pro secondary (Asus OEM for HP)
- 1458 4024 Giga-Byte GV-R96128D Primary
- 148c 2064 PowerColor R96A-C3N
- 148c 2066 PowerColor R96A-C3N
- 174b 7c19 Sapphire Atlantis Radeon 9600 Pro
- 174b 7c29 GC-R9600PRO Primary [Sapphire]
- 17ee 2002 Radeon 9600 256Mb Primary
- 18bc 0101 GC-R9600PRO Primary
-# New PCI ID provided by ATI developer relations
- 4151 RV350 AQ [Radeon 9600]
- 1043 c004 A9600SE
-# New PCI ID provided by ATI developer relations
- 4152 RV350 AR [Radeon 9600]
- 1002 0002 Radeon 9600XT
- 1043 c002 Radeon 9600 XT TVD
- 174b 7c29 Sapphire Radeon 9600XT
- 1787 4002 Radeon 9600 XT
- 4153 RV350 AS [Radeon 9600 AS]
- 4154 RV350 AT [Fire GL T2]
- 4155 RV350 AU [Fire GL T2]
- 4156 RV350 AV [Fire GL T2]
- 4157 RV350 AW [Fire GL T2]
- 4158 68800AX [Mach32]
-# The PCI ID is unrelated to any DVI output.
- 4164 R300 AD [Radeon 9500 Pro] (Secondary)
-# New PCI ID info provided by ATI developer relations
- 4165 R300 AE [Radeon 9700 Pro] (Secondary)
-# New PCI ID info provided by ATI developer relations
- 4166 R300 AF [Radeon 9700 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations
- 4168 Radeon R350 [Radeon 9800] (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4170 RV350 AP [Radeon 9600] (Secondary)
- 1458 4025 Giga-Byte GV-R96128D Secondary
- 148c 2067 PowerColor R96A-C3N (Secondary)
- 174b 7c28 GC-R9600PRO Secondary [Sapphire]
- 17ee 2003 Radeon 9600 256Mb Secondary
- 18bc 0100 GC-R9600PRO Secondary
-# New PCI ID provided by ATI developer relations (correction to above)
- 4171 RV350 AQ [Radeon 9600] (Secondary)
- 1043 c005 A9600SE (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4172 RV350 AR [Radeon 9600] (Secondary)
- 1002 0003 Radeon 9600XT (Secondary)
- 1043 c003 A9600XT (Secondary)
- 174b 7c28 Sapphire Radeon 9600XT (Secondary)
- 1787 4003 Radeon 9600 XT (Secondary)
- 4173 RV350 ?? [Radeon 9550] (Secondary)
- 4237 Radeon 7000 IGP
- 4242 R200 BB [Radeon All in Wonder 8500DV]
- 1002 02aa Radeon 8500 AIW DV Edition
- 4243 R200 BC [Radeon All in Wonder 8500]
- 4336 Radeon Mobility U1
- 103c 0024 Pavilion ze4400 builtin Video
- 4337 Radeon IGP 330M/340M/350M
- 1014 053a ThinkPad R40e (2684-HVG) builtin VGA controller
- 103c 0850 Radeon IGP 345M
- 4341 IXP150 AC'97 Audio Controller
- 4345 EHCI USB Controller
- 4347 OHCI USB Controller #1
- 4348 OHCI USB Controller #2
- 4349 ATI Dual Channel Bus Master PCI IDE Controller
- 434d IXP AC'97 Modem
- 4353 ATI SMBus
- 4354 215CT [Mach64 CT]
- 4358 210888CX [Mach64 CX]
- 4363 ATI SMBus
- 436e ATI 436E Serial ATA Controller
- 4372 ATI SMBus
- 4376 Standard Dual Channel PCI IDE Controller ATI
- 4379 ATI 4379 Serial ATA Controller
- 437a ATI 437A Serial ATA Controller
- 4437 Radeon Mobility 7000 IGP
- 4554 210888ET [Mach64 ET]
- 4654 Mach64 VT
- 4742 3D Rage Pro AGP 1X/2X
- 1002 0040 Rage Pro Turbo AGP 2X
- 1002 0044 Rage Pro Turbo AGP 2X
- 1002 0061 Rage Pro AIW AGP 2X
- 1002 0062 Rage Pro AIW AGP 2X
- 1002 0063 Rage Pro AIW AGP 2X
- 1002 0080 Rage Pro Turbo AGP 2X
- 1002 0084 Rage Pro Turbo AGP 2X
- 1002 4742 Rage Pro Turbo AGP 2X
- 1002 8001 Rage Pro Turbo AGP 2X
- 1028 0082 Rage Pro Turbo AGP 2X
- 1028 4082 Optiplex GX1 Onboard Display Adapter
- 1028 8082 Rage Pro Turbo AGP 2X
- 1028 c082 Rage Pro Turbo AGP 2X
- 8086 4152 Xpert 98D AGP 2X
- 8086 464a Rage Pro Turbo AGP 2X
- 4744 3D Rage Pro AGP 1X
- 1002 4744 Rage Pro Turbo AGP
- 4747 3D Rage Pro
- 4749 3D Rage Pro
- 1002 0061 Rage Pro AIW
- 1002 0062 Rage Pro AIW
- 474c Rage XC
- 474d Rage XL AGP 2X
- 1002 0004 Xpert 98 RXL AGP 2X
- 1002 0008 Xpert 98 RXL AGP 2X
- 1002 0080 Rage XL AGP 2X
- 1002 0084 Xpert 98 AGP 2X
- 1002 474d Rage XL AGP
- 1033 806a Rage XL AGP
- 474e Rage XC AGP
- 1002 474e Rage XC AGP
- 474f Rage XL
- 1002 0008 Rage XL
- 1002 474f Rage XL
- 4750 3D Rage Pro 215GP
- 1002 0040 Rage Pro Turbo
- 1002 0044 Rage Pro Turbo
- 1002 0080 Rage Pro Turbo
- 1002 0084 Rage Pro Turbo
- 1002 4750 Rage Pro Turbo
- 4751 3D Rage Pro 215GQ
- 4752 Rage XL
- 1002 0008 Rage XL
- 1002 4752 Rage XL
- 1002 8008 Rage XL
- 1028 00ce PowerEdge 1400
- 1028 00d1 PowerEdge 2550
- 1028 00d9 PowerEdge 2500
- 8086 3411 SDS2 Mainboard
- 8086 3427 S875WP1-E mainboard
- 4753 Rage XC
- 1002 4753 Rage XC
- 4754 3D Rage I/II 215GT [Mach64 GT]
- 4755 3D Rage II+ 215GTB [Mach64 GTB]
- 4756 3D Rage IIC 215IIC [Mach64 GT IIC]
- 1002 4756 Rage IIC
- 4757 3D Rage IIC AGP
- 1002 4757 Rage IIC AGP
- 1028 0089 Rage 3D IIC
- 1028 4082 Rage 3D IIC
- 1028 8082 Rage 3D IIC
- 1028 c082 Rage 3D IIC
- 4758 210888GX [Mach64 GX]
- 4759 3D Rage IIC
- 475a 3D Rage IIC AGP
- 1002 0084 Rage 3D Pro AGP 2x XPERT 98
- 1002 0087 Rage 3D IIC
- 1002 475a Rage IIC AGP
- 4964 Radeon RV250 Id [Radeon 9000]
- 4965 Radeon RV250 Ie [Radeon 9000]
- 4966 Radeon RV250 If [Radeon 9000]
- 10f1 0002 RV250 If [Tachyon G9000 PRO]
- 148c 2039 RV250 If [Radeon 9000 Pro "Evil Commando"]
- 1509 9a00 RV250 If [Radeon 9000 "AT009"]
-# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified.
- 1681 0040 RV250 If [3D prophet 9000]
- 174b 7176 RV250 If [Sapphire Radeon 9000 Pro]
- 174b 7192 RV250 If [Radeon 9000 "Atlantis"]
- 17af 2005 RV250 If [Excalibur Radeon 9000 Pro]
- 17af 2006 RV250 If [Excalibur Radeon 9000]
- 4967 Radeon RV250 Ig [Radeon 9000]
- 496e Radeon RV250 [Radeon 9000] (Secondary)
- 4a48 R420 JH [Radeon X800]
- 4a49 R420 JI [Radeon X800PRO]
- 4a4a R420 JJ [Radeon X800SE]
- 4a4b R420 JK [Radeon X800]
- 4a4c R420 JL [Radeon X800]
- 4a4d R420 JM [FireGL X3]
- 4a4e M18 JN [Radeon Mobility 9800]
- 4a50 R420 JP [Radeon X800XT]
- 4a70 R420 [X800XT-PE] (Secondary)
- 4c42 3D Rage LT Pro AGP-133
- 0e11 b0e7 Rage LT Pro (Compaq Presario 5240)
- 0e11 b0e8 Rage 3D LT Pro
- 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750)
- 1002 0040 Rage LT Pro AGP 2X
- 1002 0044 Rage LT Pro AGP 2X
- 1002 4c42 Rage LT Pro AGP 2X
- 1002 8001 Rage LT Pro AGP 2X
- 1028 0085 Rage 3D LT Pro
- 4c44 3D Rage LT Pro AGP-66
- 4c45 Rage Mobility M3 AGP
- 4c46 Rage Mobility M3 AGP 2x
- 1028 00b1 Latitude C600
- 4c47 3D Rage LT-G 215LG
- 4c49 3D Rage LT Pro
- 1002 0004 Rage LT Pro
- 1002 0040 Rage LT Pro
- 1002 0044 Rage LT Pro
- 1002 4c49 Rage LT Pro
- 4c4d Rage Mobility P/M AGP 2x
- 0e11 b111 Armada M700
- 0e11 b160 Armada E500
- 1002 0084 Xpert 98 AGP 2X (Mobility)
- 1014 0154 ThinkPad A20m
- 1028 00aa Latitude CPt
- 1028 00bb Latitude CPx
- 4c4e Rage Mobility L AGP 2x
- 4c50 3D Rage LT Pro
- 1002 4c50 Rage LT Pro
- 4c51 3D Rage LT Pro
- 4c52 Rage Mobility P/M
- 1033 8112 Versa Note VXi
- 4c53 Rage Mobility L
- 4c54 264LT [Mach64 LT]
- 4c57 Radeon Mobility M7 LW [Radeon Mobility 7500]
- 1014 0517 ThinkPad T30
- 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100)
- 1028 012a Latitude C640
- 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4
- 4c58 Radeon RV200 LX [Mobility FireGL 7800 M7]
- 4c59 Radeon Mobility M6 LY
- 1014 0235 ThinkPad A30/A30p (2652/2653)
- 1014 0239 ThinkPad X22/X23/X24
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 4c5a Radeon Mobility M6 LZ
- 4c64 Radeon R250 Ld [Radeon Mobility 9000 M9]
- 4c65 Radeon R250 Le [Radeon Mobility 9000 M9]
- 4c66 Radeon R250 Lf [FireGL 9000]
- 4c67 Radeon R250 Lg [Radeon Mobility 9000 M9]
-# Secondary chip to the Lf
- 4c6e Radeon R250 Ln [Radeon Mobility 9000 M9] [Secondary]
- 4d46 Rage Mobility M4 AGP
- 4d4c Rage Mobility M4 AGP
- 4e44 Radeon R300 ND [Radeon 9700 Pro]
- 4e45 Radeon R300 NE [Radeon 9500 Pro]
- 1002 0002 Radeon R300 NE [Radeon 9500 Pro]
- 1681 0002 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]
-# New PCI ID provided by ATI developer relations (correction to above)
- 4e46 RV350 NF [Radeon 9600]
- 4e47 Radeon R300 NG [FireGL X1]
-# (added pro)
- 4e48 Radeon R350 [Radeon 9800 Pro]
-# New PCI ID provided by ATI developer relations
- 4e49 Radeon R350 [Radeon 9800]
- 4e4a RV350 NJ [Radeon 9800 XT]
- 4e4b R350 NK [Fire GL X2]
-# New PCI ID provided by ATI developer relations
- 4e50 RV350 [Mobility Radeon 9600 M10]
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1734 1055 Amilo M1420W
- 4e51 M10 NQ [Radeon Mobility 9600]
- 4e52 RV350 [Mobility Radeon 9600 M10]
- 4e53 M10 NS [Radeon Mobility 9600]
- 4e54 M10 NT [FireGL Mobility T2]
- 4e56 M11 NV [FireGL Mobility T2e]
- 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary)
- 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary)
- 1002 0003 Radeon R300 NE [Radeon 9500 Pro]
- 1681 0003 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations (correction to above)
- 4e66 RV350 NF [Radeon 9600] (Secondary)
- 4e67 Radeon R300 [FireGL X1] (Secondary)
-# (added pro)
- 4e68 Radeon R350 [Radeon 9800 Pro] (Secondary)
-# New PCI ID provided by ATI developer relations
- 4e69 Radeon R350 [Radeon 9800] (Secondary)
- 4e6a RV350 NJ [Radeon 9800 XT] (Secondary)
- 1002 4e71 ATI Technologies Inc M10 NQ [Radeon Mobility 9600]
- 5041 Rage 128 PA/PRO
- 5042 Rage 128 PB/PRO AGP 2x
- 5043 Rage 128 PC/PRO AGP 4x
- 5044 Rage 128 PD/PRO TMDS
- 1002 0028 Rage 128 AIW
- 1002 0029 Rage 128 AIW
- 5045 Rage 128 PE/PRO AGP 2x TMDS
- 5046 Rage 128 PF/PRO AGP 4x TMDS
- 1002 0004 Rage Fury Pro
- 1002 0008 Rage Fury Pro/Xpert 2000 Pro
- 1002 0014 Rage Fury Pro
- 1002 0018 Rage Fury Pro/Xpert 2000 Pro
- 1002 0028 Rage 128 Pro AIW AGP
- 1002 002a Rage 128 Pro AIW AGP
- 1002 0048 Rage Fury Pro
- 1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device)
- 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)
- 5047 Rage 128 PG/PRO
- 5048 Rage 128 PH/PRO AGP 2x
- 5049 Rage 128 PI/PRO AGP 4x
- 504a Rage 128 PJ/PRO TMDS
- 504b Rage 128 PK/PRO AGP 2x TMDS
- 504c Rage 128 PL/PRO AGP 4x TMDS
- 504d Rage 128 PM/PRO
- 504e Rage 128 PN/PRO AGP 2x
- 504f Rage 128 PO/PRO AGP 4x
- 5050 Rage 128 PP/PRO TMDS [Xpert 128]
- 1002 0008 Xpert 128
- 5051 Rage 128 PQ/PRO AGP 2x TMDS
- 5052 Rage 128 PR/PRO AGP 4x TMDS
- 5053 Rage 128 PS/PRO
- 5054 Rage 128 PT/PRO AGP 2x
- 5055 Rage 128 PU/PRO AGP 4x
- 5056 Rage 128 PV/PRO TMDS
- 5057 Rage 128 PW/PRO AGP 2x TMDS
- 5058 Rage 128 PX/PRO AGP 4x TMDS
- 5144 Radeon R100 QD [Radeon 7200]
- 1002 0008 Radeon 7000/Radeon VE
- 1002 0009 Radeon 7000/Radeon
- 1002 000a Radeon 7000/Radeon
- 1002 001a Radeon 7000/Radeon
- 1002 0029 Radeon AIW
- 1002 0038 Radeon 7000/Radeon
- 1002 0039 Radeon 7000/Radeon
- 1002 008a Radeon 7000/Radeon
- 1002 00ba Radeon 7000/Radeon
- 1002 0139 Radeon 7000/Radeon
- 1002 028a Radeon 7000/Radeon
- 1002 02aa Radeon AIW
- 1002 053a Radeon 7000/Radeon
- 5145 Radeon R100 QE
- 5146 Radeon R100 QF
- 5147 Radeon R100 QG
- 5148 Radeon R200 QH [Radeon 8500]
- 1002 010a FireGL 8800 64Mb
- 1002 0152 FireGL 8800 128Mb
- 1002 0162 FireGL 8700 32Mb
- 1002 0172 FireGL 8700 64Mb
- 5149 Radeon R200 QI
- 514a Radeon R200 QJ
- 514b Radeon R200 QK
- 514c Radeon R200 QL [Radeon 8500 LE]
- 1002 003a Radeon R200 QL [Radeon 8500 LE]
- 1002 013a Radeon 8500
- 148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition]
- 1681 0010 Radeon 8500 [3D Prophet 8500 128Mb]
- 174b 7149 Radeon R200 QL [Sapphire Radeon 8500 LE]
- 514d Radeon R200 QM [Radeon 9100]
- 514e Radeon R200 QN [Radeon 8500LE]
- 514f Radeon R200 QO [Radeon 8500LE]
- 5154 R200 QT [Radeon 8500]
- 5155 R200 QU [Radeon 9100]
- 5157 Radeon RV200 QW [Radeon 7500]
- 1002 013a Radeon 7500
- 1002 103a Dell Optiplex GX260
- 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR]
- 148c 2024 RV200 QW [Radeon 7500LE Dual Display]
- 148c 2025 RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
- 148c 2036 RV200 QW [Radeon 7500 PCI Dual Display]
- 174b 7146 RV200 QW [Radeon 7500 LE]
- 174b 7147 RV200 QW [Sapphire Radeon 7500LE]
- 174b 7161 Radeon RV200 QW [Radeon 7500 LE]
- 17af 0202 RV200 QW [Excalibur Radeon 7500LE]
- 5158 Radeon RV200 QX [Radeon 7500]
- 5159 Radeon RV100 QY [Radeon 7000/VE]
- 1002 000a Radeon 7000/Radeon VE
- 1002 000b Radeon 7000
- 1002 0038 Radeon 7000/Radeon VE
- 1002 003a Radeon 7000/Radeon VE
- 1002 00ba Radeon 7000/Radeon VE
- 1002 013a Radeon 7000/Radeon VE
- 1458 4002 RV100 QY [RADEON 7000 PRO MAYA AV Series]
- 148c 2003 RV100 QY [Radeon 7000 Multi-Display Edition]
- 148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display]
- 174b 7112 RV100 QY [Sapphire Radeon VE 7000]
- 174b 7c28 Sapphire Radeon VE 7000 DDR
- 1787 0202 RV100 QY [Excalibur Radeon 7000]
- 515a Radeon RV100 QZ [Radeon 7000/VE]
- 5168 Radeon R200 Qh
- 5169 Radeon R200 Qi
- 516a Radeon R200 Qj
- 516b Radeon R200 Qk
-# This one is not in ATI documentation, but is in XFree86 source code
- 516c Radeon R200 Ql
- 5245 Rage 128 RE/SG
- 1002 0008 Xpert 128
- 1002 0028 Rage 128 AIW
- 1002 0029 Rage 128 AIW
- 1002 0068 Rage 128 AIW
- 5246 Rage 128 RF/SG AGP
- 1002 0004 Magnum/Xpert 128/Xpert 99
- 1002 0008 Magnum/Xpert128/X99/Xpert2000
- 1002 0028 Rage 128 AIW AGP
- 1002 0044 Rage Fury/Xpert 128/Xpert 2000
- 1002 0068 Rage 128 AIW AGP
- 1002 0448 Rage Fury
- 5247 Rage 128 RG
- 524b Rage 128 RK/VR
- 524c Rage 128 RL/VR AGP
- 1002 0008 Xpert 99/Xpert 2000
- 1002 0088 Xpert 99
- 5345 Rage 128 SE/4x
- 5346 Rage 128 SF/4x AGP 2x
- 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL
- 5347 Rage 128 SG/4x AGP 4x
- 5348 Rage 128 SH
- 534b Rage 128 SK/4x
- 534c Rage 128 SL/4x AGP 2x
- 534d Rage 128 SM/4x AGP 4x
- 1002 0008 Xpert 99/Xpert 2000
- 1002 0018 Xpert 2000
- 534e Rage 128 4x
- 5354 Mach 64 VT
- 1002 5654 Mach 64 reference
- 5446 Rage 128 Pro Ultra TF
- 1002 0004 Rage Fury Pro
- 1002 0008 Rage Fury Pro/Xpert 2000 Pro
- 1002 0018 Rage Fury Pro/Xpert 2000 Pro
- 1002 0028 Rage 128 AIW Pro AGP
- 1002 0029 Rage 128 AIW
- 1002 002a Rage 128 AIW Pro AGP
- 1002 002b Rage 128 AIW
- 1002 0048 Xpert 2000 Pro
- 544c Rage 128 Pro Ultra TL
- 5452 Rage 128 Pro Ultra TR
- 1002 001c Rage 128 Pro 4XL
- 103c 1279 Rage 128 Pro 4XL
- 5453 Rage 128 Pro Ultra TS
- 5454 Rage 128 Pro Ultra TT
- 5455 Rage 128 Pro Ultra TU
- 5460 M22 [Radeon Mobility M300]
- 5464 M22 [FireGL GL]
- 5548 R423 UH [Radeon X800 (PCIE)]
- 5549 R423 UI [Radeon X800PRO (PCIE)]
- 554a R423 UJ [Radeon X800LE (PCIE)]
- 554b R423 UK [Radeon X800SE (PCIE)]
- 5551 R423 UQ [FireGL V7200 (PCIE)]
- 5552 R423 UR [FireGL V5100 (PCIE)]
- 5554 R423 UT [FireGL V7100 (PCIE)]
- 556b Radeon R423 UK (PCIE) [X800 SE] (Secondary)
- 5654 264VT [Mach64 VT]
- 1002 5654 Mach64VT Reference
- 5655 264VT3 [Mach64 VT3]
- 5656 264VT4 [Mach64 VT4]
- 5830 RS300 Host Bridge
- 5831 RS300 Host Bridge
- 5832 RS300 Host Bridge
- 5833 Radeon 9100 IGP Host Bridge
- 5834 Radeon 9100 IGP
- 5835 RS300M AGP [Radeon Mobility 9100IGP]
- 5838 Radeon 9100 IGP AGP Bridge
- 5941 RV280 [Radeon 9200] (Secondary)
- 1458 4019 Gigabyte Radeon 9200
- 174b 7c12 Sapphire Radeon 9200
-# http://www.hightech.com.hk/html/9200.htm
- 17af 200d Excalibur Radeon 9200
- 18bc 0050 GeXcube GC-R9200-C3 (Secondary)
- 5944 RV280 [Radeon 9200 SE (PCI)]
- 5960 RV280 [Radeon 9200 PRO]
- 5961 RV280 [Radeon 9200]
- 1002 2f72 All-in-Wonder 9200 Series
- 1019 4c30 Radeon 9200 VIVO
- 12ab 5961 YUAN SMARTVGA Radeon 9200
- 1458 4018 Gigabyte Radeon 9200
- 174b 7c13 Sapphire Radeon 9200
-# http://www.hightech.com.hk/html/9200.htm
- 17af 200c Excalibur Radeon 9200
- 18bc 0050 Radeon 9200 Game Buster
- 18bc 0051 GeXcube GC-R9200-C3
- 18bc 0053 Radeon 9200 Game Buster VIVO
- 5962 RV280 [Radeon 9200]
- 5964 RV280 [Radeon 9200 SE]
- 1043 c006 ASUS Radeon 9200 SE / TD / 128M
- 1458 4018 Radeon 9200 SE
- 148c 2073 CN-AG92E
- 174b 7c13 Sapphire Radeon 9200 SE
- 1787 5964 Excalibur 9200SE VIVO 128M
- 17af 2012 Radeon 9200 SE Excalibur
- 18bc 0170 Sapphire Radeon 9200 SE 128MB Game Buster
-# 128MB DDR, DVI/VGA/TV out
- 18bc 0173 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
- 5b60 RV370 5B60 [Radeon X300 (PCIE)]
- 1043 002a Extreme AX300SE-X
- 1043 032e Extreme AX300/TD
- 5b62 RV370 5B62 [Radeon X600 (PCIE)]
- 5b64 RV370 5B64 [FireGL V3100 (PCIE)]
- 5b65 RV370 5B65 [FireGL D1100 (PCIE)]
- 5c61 M9+ 5C61 [Radeon Mobility 9200 (AGP)]
- 5c63 M9+ 5C63 [Radeon Mobility 9200 (AGP)]
- 5d44 RV280 [Radeon 9200 SE] (Secondary)
- 1458 4019 Radeon 9200 SE (Secondary)
- 174b 7c12 Sapphire Radeon 9200 SE (Secondary)
- 1787 5965 Excalibur 9200SE VIVO 128M (Secondary)
- 17af 2013 Radeon 9200 SE Excalibur (Secondary)
- 18bc 0171 Radeon 9200 SE 128MB Game Buster (Secondary)
- 18bc 0172 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
- 5d4d R480 [Radeon X850XT Platinum]
- 5d57 R423 5F57 [Radeon X800XT (PCIE)]
- 700f PCI Bridge [IGP 320M]
- 7010 PCI Bridge [IGP 340M]
- 7834 Radeon 9100 PRO IGP
- 7835 Radeon Mobility 9200 IGP
- 7c37 RV350 AQ [Radeon 9600 SE]
- cab0 AGP Bridge [IGP 320M]
- cab2 RS200/RS200M AGP Bridge [IGP 340M]
- cbb2 RS200/RS200M AGP Bridge [IGP 340M]
-1003 ULSI Systems
- 0201 US201
-1004 VLSI Technology Inc
- 0005 82C592-FC1
- 0006 82C593-FC1
- 0007 82C594-AFC2
- 0008 82C596/7 [Wildcat]
- 0009 82C597-AFC2
- 000c 82C541 [Lynx]
- 000d 82C543 [Lynx]
- 0101 82C532
- 0102 82C534 [Eagle]
- 0103 82C538
- 0104 82C535
- 0105 82C147
- 0200 82C975
- 0280 82C925
- 0304 QSound ThunderBird PCI Audio
- 1004 0304 QSound ThunderBird PCI Audio
- 122d 1206 DSP368 Audio
- 1483 5020 XWave Thunder 3D Audio
- 0305 QSound ThunderBird PCI Audio Gameport
- 1004 0305 QSound ThunderBird PCI Audio Gameport
- 122d 1207 DSP368 Audio Gameport
- 1483 5021 XWave Thunder 3D Audio Gameport
- 0306 QSound ThunderBird PCI Audio Support Registers
- 1004 0306 QSound ThunderBird PCI Audio Support Registers
- 122d 1208 DSP368 Audio Support Registers
- 1483 5022 XWave Thunder 3D Audio Support Registers
- 0307 Thunderbird
- 0308 Thunderbird
- 0702 VAS96011 [Golden Gate II]
- 0703 Tollgate
-1005 Avance Logic Inc. [ALI]
- 2064 ALG2032/2064
- 2128 ALG2364A
- 2301 ALG2301
- 2302 ALG2302
- 2364 ALG2364
- 2464 ALG2364A
- 2501 ALG2564A/25128A
-1006 Reply Group
-1007 NetFrame Systems Inc
-1008 Epson
-100a Phoenix Technologies
-100b National Semiconductor Corporation
- 0001 DP83810
- 0002 87415/87560 IDE
- 000e 87560 Legacy I/O
- 000f FireWire Controller
- 0011 NS87560 National PCI System I/O
- 0012 USB Controller
- 0020 DP83815 (MacPhyter) Ethernet Controller
- 103c 0024 Pavilion ze4400 builtin Network
- 1385 f311 FA311 / FA312 (FA311 with WoL HW)
- 0022 DP83820 10/100/1000 Ethernet Controller
- 0028 Geode GX2 Host Bridge
- 002a CS5535 South Bridge
- 002b CS5535 ISA bridge
- 002d CS5535 IDE
- 002e CS5535 Audio
- 002f CS5535 USB
- 0030 Geode GX2 Graphics Processor
- 0035 DP83065 [Saturn] 10/100/1000 Ethernet Controller
- 0500 SCx200 Bridge
- 0501 SCx200 SMI
- 0502 SCx200 IDE
- 0503 SCx200 Audio
- 0504 SCx200 Video
- 0505 SCx200 XBus
- 0510 SC1100 Bridge
- 0511 SC1100 SMI
- 0515 SC1100 XBus
- d001 87410 IDE
-100c Tseng Labs Inc
- 3202 ET4000/W32p rev A
- 3205 ET4000/W32p rev B
- 3206 ET4000/W32p rev C
- 3207 ET4000/W32p rev D
- 3208 ET6000
- 4702 ET6300
-100d AST Research Inc
-100e Weitek
- 9000 P9000 Viper
- 9001 P9000 Viper
- 9002 P9000 Viper
- 9100 P9100 Viper Pro/SE
-1010 Video Logic, Ltd.
-1011 Digital Equipment Corporation
- 0001 DECchip 21050
- 0002 DECchip 21040 [Tulip]
- 0004 DECchip 21030 [TGA]
- 0007 NVRAM [Zephyr NVRAM]
- 0008 KZPSA [KZPSA]
- 0009 DECchip 21140 [FasterNet]
- 1025 0310 21140 Fast Ethernet
- 10b8 2001 SMC9332BDT EtherPower 10/100
- 10b8 2002 SMC9332BVT EtherPower T4 10/100
- 10b8 2003 SMC9334BDT EtherPower 10/100 (1-port)
- 1109 2400 ANA-6944A/TX Fast Ethernet
- 1112 2300 RNS2300 Fast Ethernet
- 1112 2320 RNS2320 Fast Ethernet
- 1112 2340 RNS2340 Fast Ethernet
- 1113 1207 EN-1207-TX Fast Ethernet
- 1186 1100 DFE-500TX Fast Ethernet
- 1186 1112 DFE-570TX Fast Ethernet
- 1186 1140 DFE-660 Cardbus Ethernet 10/100
- 1186 1142 DFE-660 Cardbus Ethernet 10/100
- 11f6 0503 Freedomline Fast Ethernet
- 1282 9100 AEF-380TXD Fast Ethernet
- 1385 1100 FA310TX Fast Ethernet
- 2646 0001 KNE100TX Fast Ethernet
- 000a 21230 Video Codec
- 000d PBXGB [TGA2]
- 000f DEFPA
- 0014 DECchip 21041 [Tulip Pass 3]
- 1186 0100 DE-530+
- 0016 DGLPB [OPPO]
- 0017 PV-PCI Graphics Controller (ZLXp-L)
- 0019 DECchip 21142/43
- 1011 500a DE500A Fast Ethernet
- 1011 500b DE500B Fast Ethernet
- 1014 0001 10/100 EtherJet Cardbus
- 1025 0315 ALN315 Fast Ethernet
- 1033 800c PC-9821-CS01 100BASE-TX Interface Card
- 1033 800d PC-9821NR-B06 100BASE-TX Interface Card
- 108d 0016 Rapidfire 2327 10/100 Ethernet
- 108d 0017 GoCard 2250 Ethernet 10/100 Cardbus
- 10b8 2005 SMC8032DT Extreme Ethernet 10/100
- 10b8 8034 SMC8034 Extreme Ethernet 10/100
- 10ef 8169 Cardbus Fast Ethernet
- 1109 2a00 ANA-6911A/TX Fast Ethernet
- 1109 2b00 ANA-6911A/TXC Fast Ethernet
- 1109 3000 ANA-6922/TX Fast Ethernet
- 1113 1207 Cheetah Fast Ethernet
- 1113 2220 Cardbus Fast Ethernet
- 115d 0002 Cardbus Ethernet 10/100
- 1179 0203 Fast Ethernet
- 1179 0204 Cardbus Fast Ethernet
- 1186 1100 DFE-500TX Fast Ethernet
- 1186 1101 DFE-500TX Fast Ethernet
- 1186 1102 DFE-500TX Fast Ethernet
- 1186 1112 DFE-570TX Quad Fast Ethernet
- 1259 2800 AT-2800Tx Fast Ethernet
- 1266 0004 Eagle Fast EtherMAX
- 12af 0019 NetFlyer Cardbus Fast Ethernet
- 1374 0001 Cardbus Ethernet Card 10/100
- 1374 0002 Cardbus Ethernet Card 10/100
- 1374 0007 Cardbus Ethernet Card 10/100
- 1374 0008 Cardbus Ethernet Card 10/100
- 1385 2100 FA510
- 1395 0001 10/100 Ethernet CardBus PC Card
- 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200)
- 14cb 0100 LNDL-100N 100Base-TX Ethernet PC Card
- 8086 0001 EtherExpress PRO/100 Mobile CardBus 32
- 001a Farallon PN9000SX Gigabit Ethernet
- 0021 DECchip 21052
- 0022 DECchip 21150
- 0023 DECchip 21150
- 0024 DECchip 21152
- 0025 DECchip 21153
- 0026 DECchip 21154
- 0034 56k Modem Cardbus
- 1374 0003 56k Modem Cardbus
- 0045 DECchip 21553
- 0046 DECchip 21554
- 0e11 4050 Integrated Smart Array
- 0e11 4051 Integrated Smart Array
- 0e11 4058 Integrated Smart Array
- 103c 10c2 Hewlett-Packard NetRAID-4M
- 12d9 000a IP Telephony card
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 9005 0364 5400S (Mustang)
- 9005 0365 5400S (Mustang)
- 9005 1364 Dell PowerEdge RAID Controller 2
- 9005 1365 Dell PowerEdge RAID Controller 2
- e4bf 1000 CC8-1-BLUES
- 1065 StrongARM DC21285
- 1069 0020 DAC960P / DAC1164P
-1012 Micronics Computers Inc
-1013 Cirrus Logic
- 0038 GD 7548
- 0040 GD 7555 Flat Panel GUI Accelerator
- 004c GD 7556 Video/Graphics LCD/CRT Ctrlr
- 00a0 GD 5430/40 [Alpine]
- 00a2 GD 5432 [Alpine]
- 00a4 GD 5434-4 [Alpine]
- 00a8 GD 5434-8 [Alpine]
- 00ac GD 5436 [Alpine]
- 00b0 GD 5440
- 00b8 GD 5446
- 00bc GD 5480
- 1013 00bc CL-GD5480
- 00d0 GD 5462
- 00d2 GD 5462 [Laguna I]
- 00d4 GD 5464 [Laguna]
- 00d5 GD 5464 BD [Laguna]
- 00d6 GD 5465 [Laguna]
- 13ce 8031 Barco Metheus 2 Megapixel, Dual Head
- 13cf 8031 Barco Metheus 2 Megapixel, Dual Head
- 00e8 GD 5436U
- 1100 CL 6729
- 1110 PD 6832 PCMCIA/CardBus Ctrlr
- 1112 PD 6834 PCMCIA/CardBus Ctrlr
- 1113 PD 6833 PCMCIA/CardBus Ctrlr
- 1200 GD 7542 [Nordic]
- 1202 GD 7543 [Viking]
- 1204 GD 7541 [Nordic Light]
- 4000 MD 5620 [CLM Data Fax Voice]
- 4400 CD 4400
- 6001 CS 4610/11 [CrystalClear SoundFusion Audio Accelerator]
- 1014 1010 CS4610 SoundFusion Audio Accelerator
- 6003 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator]
- 1013 4280 Crystal SoundFusion PCI Audio Accelerator
- 153b 1136 SiXPack 5.1+
- 1681 0050 Game Theater XP
- 1681 a011 Fortissimo III 7.1
- 6004 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator]
- 6005 Crystal CS4281 PCI Audio
- 1013 4281 Crystal CS4281 PCI Audio
- 10cf 10a8 Crystal CS4281 PCI Audio
- 10cf 10a9 Crystal CS4281 PCI Audio
- 10cf 10aa Crystal CS4281 PCI Audio
- 10cf 10ab Crystal CS4281 PCI Audio
- 10cf 10ac Crystal CS4281 PCI Audio
- 10cf 10ad Crystal CS4281 PCI Audio
- 10cf 10b4 Crystal CS4281 PCI Audio
- 1179 0001 Crystal CS4281 PCI Audio
- 14c0 000c Crystal CS4281 PCI Audio
-1014 IBM
- 0002 PCI to MCA Bridge
- 0005 Alta Lite
- 0007 Alta MP
- 000a Fire Coral
- 0017 CPU to PCI Bridge
- 0018 TR Auto LANstreamer
- 001b GXT-150P
- 001c Carrera
- 001d 82G2675
- 0020 GXT1000 Graphics Adapter
- 0022 IBM27-82351
- 002d Python
-# [official name in AIX 5]
- 002e SCSI RAID Adapter [ServeRAID]
- 1014 002e ServeRAID-3x
- 1014 022e ServeRAID-4H
- 0031 2 Port Serial Adapter
-# AS400 iSeries PCI sync serial card
- 1014 0031 2721 WAN IOA - 2 Port Sync Serial Adapter
- 0036 Miami
- 0037 82660 CPU to PCI Bridge
- 003a CPU to PCI Bridge
- 003c GXT250P/GXT255P Graphics Adapter
- 003e 16/4 Token ring UTP/STP controller
- 1014 003e Token-Ring Adapter
- 1014 00cd Token-Ring Adapter + Wake-On-LAN
- 1014 00ce 16/4 Token-Ring Adapter 2
- 1014 00cf 16/4 Token-Ring Adapter Special
- 1014 00e4 High-Speed 100/16/4 Token-Ring Adapter
- 1014 00e5 16/4 Token-Ring Adapter 2 + Wake-On-LAN
- 1014 016d iSeries 2744 Card
- 0045 SSA Adapter
- 0046 MPIC interrupt controller
- 0047 PCI to PCI Bridge
- 0048 PCI to PCI Bridge
- 0049 Warhead SCSI Controller
- 004e ATM Controller (14104e00)
- 004f ATM Controller (14104f00)
- 0050 ATM Controller (14105000)
- 0053 25 MBit ATM Controller
- 0054 GXT500P/GXT550P Graphics Adapter
- 0057 MPEG PCI Bridge
- 005c i82557B 10/100
- 005e GXT800P Graphics Adapter
- 007c ATM Controller (14107c00)
- 007d 3780IDSP [MWave]
- 008b EADS PCI to PCI Bridge
- 008e GXT3000P Graphics Adapter
- 0090 GXT 3000P
- 1014 008e GXT-3000P
- 0091 SSA Adapter
- 0095 20H2999 PCI Docking Bridge
- 0096 Chukar chipset SCSI controller
- 1014 0097 iSeries 2778 DASD IOA
- 1014 0098 iSeries 2763 DASD IOA
- 1014 0099 iSeries 2748 DASD IOA
- 009f PCI 4758 Cryptographic Accelerator
- 00a5 ATM Controller (1410a500)
- 00a6 ATM 155MBPS MM Controller (1410a600)
- 00b7 256-bit Graphics Rasterizer [Fire GL1]
- 1092 00b8 FireGL1 AGP 32Mb
- 00b8 GXT2000P Graphics Adapter
- 00be ATM 622MBPS Controller (1410be00)
- 00dc Advanced Systems Management Adapter (ASMA)
- 00fc CPC710 Dual Bridge and Memory Controller (PCI-64)
- 0104 Gigabit Ethernet-SX Adapter
- 0105 CPC710 Dual Bridge and Memory Controller (PCI-32)
- 010f Remote Supervisor Adapter (RSA)
- 0142 Yotta Video Compositor Input
- 1014 0143 Yotta Input Controller (ytin)
- 0144 Yotta Video Compositor Output
- 1014 0145 Yotta Output Controller (ytout)
- 0156 405GP PLB to PCI Bridge
- 015e 622Mbps ATM PCI Adapter
- 0160 64bit/66MHz PCI ATM 155 MMF
- 016e GXT4000P Graphics Adapter
- 0170 GXT6000P Graphics Adapter
- 017d GXT300P Graphics Adapter
- 0180 Snipe chipset SCSI controller
- 1014 0241 iSeries 2757 DASD IOA
- 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
- 0188 EADS-X PCI-X to PCI-X Bridge
- 01a7 PCI-X to PCI-X Bridge
- 01bd ServeRAID Controller
- 1014 01be ServeRAID-4M
- 1014 01bf ServeRAID-4L
- 1014 0208 ServeRAID-4Mx
- 1014 020e ServeRAID-4Lx
- 1014 022e ServeRAID-4H
- 1014 0258 ServeRAID-5i
- 1014 0259 ServeRAID-5i
- 01c1 64bit/66MHz PCI ATM 155 UTP
- 01e6 Cryptographic Accelerator
- 01ff 10/100 Mbps Ethernet
- 0219 Multiport Serial Adapter
- 1014 021a Dual RVX
- 1014 0251 Internal Modem/RVX
- 1014 0252 Quad Internal Modem
- 021b GXT6500P Graphics Adapter
- 021c GXT4500P Graphics Adapter
- 0233 GXT135P Graphics Adapter
- 0266 PCI-X Dual Channel SCSI
- 0268 Gigabit Ethernet-SX Adapter (PCI-X)
- 0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X)
- 028c Citrine chipset SCSI controller
- 1014 028D Dual Channel PCI-X DDR SAS RAID Adapter (572E)
- 1014 02BE Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B)
- 1014 02C0 Dual Channel PCI-X DDR U320 SCSI Adapter (571A)
- 0302 X-Architecture Bridge [Summit]
- 0314 ZISC 036 Neural accelerator card
- ffff MPIC-2 interrupt controller
-1015 LSI Logic Corp of Canada
-1016 ICL Personal Systems
-1017 SPEA Software AG
- 5343 SPEA 3D Accelerator
-1018 Unisys Systems
-1019 Elitegroup Computer Systems
-101a AT&T GIS (NCR)
- 0005 100VG ethernet
-101b Vitesse Semiconductor
-101c Western Digital
- 0193 33C193A
- 0196 33C196A
- 0197 33C197A
- 0296 33C296A
- 3193 7193
- 3197 7197
- 3296 33C296A
- 4296 34C296
- 9710 Pipeline 9710
- 9712 Pipeline 9712
- c24a 90C
-101e American Megatrends Inc.
- 1960 MegaRAID
- 101e 0471 MegaRAID 471 Enterprise 1600 RAID Controller
- 101e 0475 MegaRAID 475 Express 500/500LC RAID Controller
- 101e 0477 MegaRAID 477 Elite 3100 RAID Controller
- 101e 0493 MegaRAID 493 Elite 1600 RAID Controller
- 101e 0494 MegaRAID 494 Elite 1650 RAID Controller
- 101e 0503 MegaRAID 503 Enterprise 1650 RAID Controller
- 101e 0511 MegaRAID 511 i4 IDE RAID Controller
- 101e 0522 MegaRAID 522 i4133 RAID Controller
- 1028 0471 PowerEdge RAID Controller 3/QC
- 1028 0475 PowerEdge RAID Controller 3/SC
- 1028 0493 PowerEdge RAID Controller 3/DC
- 1028 0511 PowerEdge Cost Effective RAID Controller ATA100/4Ch
- 9010 MegaRAID 428 Ultra RAID Controller
- 9030 EIDE Controller
- 9031 EIDE Controller
- 9032 EIDE & SCSI Controller
- 9033 SCSI Controller
- 9040 Multimedia card
- 9060 MegaRAID 434 Ultra GT RAID Controller
- 9063 MegaRAC
- 101e 0767 Dell Remote Assistant Card 2
-101f PictureTel
-1020 Hitachi Computer Products
-1021 OKI Electric Industry Co. Ltd.
-1022 Advanced Micro Devices [AMD]
- 1100 K8 [Athlon64/Opteron] HyperTransport Technology Configuration
- 1101 K8 [Athlon64/Opteron] Address Map
- 1102 K8 [Athlon64/Opteron] DRAM Controller
- 1103 K8 [Athlon64/Opteron] Miscellaneous Control
- 2000 79c970 [PCnet32 LANCE]
- 1014 2000 NetFinity 10/100 Fast Ethernet
- 1022 2000 PCnet - Fast 79C971
- 103c 104c Ethernet with LAN remote power Adapter
- 103c 1064 Ethernet with LAN remote power Adapter
- 103c 1065 Ethernet with LAN remote power Adapter
- 103c 106c Ethernet with LAN remote power Adapter
- 103c 106e Ethernet with LAN remote power Adapter
- 103c 10ea Ethernet with LAN remote power Adapter
- 1113 1220 EN1220 10/100 Fast Ethernet
- 1259 2450 AT-2450 10/100 Fast Ethernet
- 1259 2454 AT-2450v4 10Mb Ethernet Adapter
- 1259 2700 AT-2700TX 10/100 Fast Ethernet
- 1259 2701 AT-2700FX 100Mb Ethernet
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1010 CP5/CR6 mainboard
- 4c53 1020 VR6 mainboard
- 4c53 1030 PC5 mainboard
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 2001 79c978 [HomePNA]
- 1092 0a78 Multimedia Home Network Adapter
- 1668 0299 ActionLink Home Network Adapter
- 2003 Am 1771 MBW [Alchemy]
- 2020 53c974 [PCscsi]
- 2040 79c974
- 3000 ELanSC520 Microcontroller
- 7006 AMD-751 [Irongate] System Controller
- 7007 AMD-751 [Irongate] AGP Bridge
- 700a AMD-IGR4 AGP Host to PCI Bridge
- 700b AMD-IGR4 PCI to PCI Bridge
- 700c AMD-760 MP [IGD4-2P] System Controller
- 700d AMD-760 MP [IGD4-2P] AGP Bridge
- 700e AMD-760 [IGD4-1P] System Controller
- 700f AMD-760 [IGD4-1P] AGP Bridge
- 7400 AMD-755 [Cobra] ISA
- 7401 AMD-755 [Cobra] IDE
- 7403 AMD-755 [Cobra] ACPI
- 7404 AMD-755 [Cobra] USB
- 7408 AMD-756 [Viper] ISA
- 7409 AMD-756 [Viper] IDE
- 740b AMD-756 [Viper] ACPI
- 740c AMD-756 [Viper] USB
- 7410 AMD-766 [ViperPlus] ISA
- 7411 AMD-766 [ViperPlus] IDE
- 7413 AMD-766 [ViperPlus] ACPI
- 7414 AMD-766 [ViperPlus] USB
- 7440 AMD-768 [Opus] ISA
- 1043 8044 A7M-D Mainboard
- 7441 AMD-768 [Opus] IDE
- 7443 AMD-768 [Opus] ACPI
- 1043 8044 A7M-D Mainboard
- 7445 AMD-768 [Opus] Audio
- 7446 AMD-768 [Opus] MC97 Modem (Smart Link HAMR5600 compatible)
- 7448 AMD-768 [Opus] PCI
- 7449 AMD-768 [Opus] USB
- 7450 AMD-8131 PCI-X Bridge
- 7451 AMD-8131 PCI-X APIC
- 7454 AMD-8151 System Controller
- 7455 AMD-8151 AGP Bridge
- 7460 AMD-8111 PCI
- 161f 3017 HDAMB
- 7461 AMD-8111 USB
- 7462 AMD-8111 Ethernet
- 7464 AMD-8111 USB
- 161f 3017 HDAMB
- 7468 AMD-8111 LPC
- 161f 3017 HDAMB
- 7469 AMD-8111 IDE
- 161f 3017 HDAMB
- 746a AMD-8111 SMBus 2.0
- 746b AMD-8111 ACPI
- 161f 3017 HDAMB
- 746d AMD-8111 AC97 Audio
- 161f 3017 HDAMB
- 746e AMD-8111 MC97 Modem
- 756b AMD-8111 ACPI
-1023 Trident Microsystems
- 0194 82C194
- 2000 4DWave DX
- 2001 4DWave NX
- 122d 1400 Trident PCI288-Q3DII (NX)
- 2100 CyberBlade XP4m32
- 2200 XGI Volari XP5
- 8400 CyberBlade/i7
- 1023 8400 CyberBlade i7 AGP
- 8420 CyberBlade/i7d
- 0e11 b15a CyberBlade i7 AGP
- 8500 CyberBlade/i1
- 8520 CyberBlade i1
- 0e11 b16e CyberBlade i1 AGP
- 1023 8520 CyberBlade i1 AGP
- 8620 CyberBlade/i1
- 1014 0502 ThinkPad R30/T30
- 8820 CyberBlade XPAi1
- 9320 TGUI 9320
- 9350 GUI Accelerator
- 9360 Flat panel GUI Accelerator
- 9382 Cyber 9382 [Reference design]
- 9383 Cyber 9383 [Reference design]
- 9385 Cyber 9385 [Reference design]
- 9386 Cyber 9386
- 9388 Cyber 9388
- 9397 Cyber 9397
- 939a Cyber 9397DVD
- 9420 TGUI 9420
- 9430 TGUI 9430
- 9440 TGUI 9440
- 9460 TGUI 9460
- 9470 TGUI 9470
- 9520 Cyber 9520
- 9525 Cyber 9525
- 10cf 1094 Lifebook C6155
- 9540 Cyber 9540
- 9660 TGUI 9660/938x/968x
- 9680 TGUI 9680
- 9682 TGUI 9682
- 9683 TGUI 9683
- 9685 ProVIDIA 9685
- 9750 3DImage 9750
- 1014 9750 3DImage 9750
- 1023 9750 3DImage 9750
- 9753 TGUI 9753
- 9754 TGUI 9754
- 9759 TGUI 975
- 9783 TGUI 9783
- 9785 TGUI 9785
- 9850 3DImage 9850
- 9880 Blade 3D PCI/AGP
- 1023 9880 Blade 3D
- 9910 CyberBlade/XP
- 9930 CyberBlade/XPm
-1024 Zenith Data Systems
-1025 Acer Incorporated [ALI]
- 1435 M1435
- 1445 M1445
- 1449 M1449
- 1451 M1451
- 1461 M1461
- 1489 M1489
- 1511 M1511
- 1512 ALI M1512 Aladdin
- 1513 M1513
- 1521 ALI M1521 Aladdin III CPU Bridge
- 10b9 1521 ALI M1521 Aladdin III CPU Bridge
- 1523 ALI M1523 ISA Bridge
- 10b9 1523 ALI M1523 ISA Bridge
- 1531 M1531 Northbridge [Aladdin IV/IV+]
- 1533 M1533 PCI-to-ISA Bridge
- 10b9 1533 ALI M1533 Aladdin IV/V ISA South Bridge
- 1535 M1535 PCI Bridge + Super I/O + FIR
- 1541 M1541 Northbridge [Aladdin V]
- 10b9 1541 ALI M1541 Aladdin V/V+ AGP+PCI North Bridge
- 1542 M1542 Northbridge [Aladdin V]
- 1543 M1543 PCI-to-ISA Bridge + Super I/O + FIR
- 1561 M1561 Northbridge [Aladdin 7]
- 1621 M1621 Northbridge [Aladdin-Pro II]
- 1631 M1631 Northbridge+3D Graphics [Aladdin TNT2]
- 1641 M1641 Northbridge [Aladdin-Pro IV]
- 1647 M1647 [MaGiK1] PCI North Bridge
- 1671 M1671 Northbridge [ALADDiN-P4]
- 1672 Northbridge [CyberALADDiN-P4]
- 3141 M3141
- 3143 M3143
- 3145 M3145
- 3147 M3147
- 3149 M3149
- 3151 M3151
- 3307 M3307 MPEG-I Video Controller
- 3309 M3309 MPEG-II Video w/ Software Audio Decoder
- 3321 M3321 MPEG-II Audio/Video Decoder
- 5212 M4803
- 5215 ALI PCI EIDE Controller
- 5217 M5217H
- 5219 M5219
- 5225 M5225
- 5229 M5229
- 5235 M5235
- 5237 M5237 PCI USB Host Controller
- 5240 EIDE Controller
- 5241 PCMCIA Bridge
- 5242 General Purpose Controller
- 5243 PCI to PCI Bridge Controller
- 5244 Floppy Disk Controller
- 5247 M1541 PCI to PCI Bridge
- 5251 M5251 P1394 Controller
- 5427 PCI to AGP Bridge
- 5451 M5451 PCI AC-Link Controller Audio Device
- 5453 M5453 PCI AC-Link Controller Modem Device
- 7101 M7101 PCI PMU Power Management Controller
- 10b9 7101 M7101 PCI PMU Power Management Controller
-1028 Dell
- 0001 PowerEdge Expandable RAID Controller 2/Si
- 1028 0001 PowerEdge 2400
- 0002 PowerEdge Expandable RAID Controller 3/Di
- 1028 0002 PowerEdge 4400
- 0003 PowerEdge Expandable RAID Controller 3/Si
- 1028 0003 PowerEdge 2450
- 0006 PowerEdge Expandable RAID Controller 3/Di
- 0007 Remote Access Card III
- 0008 Remote Access Card III
- 0009 Remote Access Card III: BMC/SMIC device not present
- 000a PowerEdge Expandable RAID Controller 3/Di
- 000c Embedded Remote Access or ERA/O
- 000d Embedded Remote Access: BMC/SMIC device
- 000e PowerEdge Expandable RAID controller 4/Di
- 000f PowerEdge Expandable RAID controller 4/Di
- 0010 Remote Access Card 4
- 0011 Remote Access Card 4 Daughter Card
- 0012 Remote Access Card 4 Daughter Card Virtual UART
- 0013 PowerEdge Expandable RAID controller 4
- 1028 016c PowerEdge Expandable RAID Controller 4e/Si
- 1028 016d PowerEdge Expandable RAID Controller 4e/Di
- 1028 016e PowerEdge Expandable RAID Controller 4e/Di
- 1028 016f PowerEdge Expandable RAID Controller 4e/Di
- 1028 0170 PowerEdge Expandable RAID Controller 4e/Di
- 0014 Remote Access Card 4 Daughter Card SMIC interface
-1029 Siemens Nixdorf IS
-102a LSI Logic
- 0000 HYDRA
- 0010 ASPEN
- 001f AHA-2940U2/U2W /7890/7891 SCSI Controllers
- 9005 000f 2940U2W SCSI Controller
- 9005 0106 2940U2W SCSI Controller
- 9005 a180 2940U2W SCSI Controller
- 00c5 AIC-7899 U160/m SCSI Controller
- 1028 00c5 PowerEdge 2550/2650/4600
- 00cf AIC-7899P U160/m
- 1028 0106 PowerEdge 4600
- 1028 0121 PowerEdge 2650
-102b Matrox Graphics, Inc.
-# DJ: I've a suspicion that 0010 is a duplicate of 0d10.
- 0010 MGA-I [Impression?]
- 0100 MGA 1064SG [Mystique]
- 0518 MGA-II [Athena]
- 0519 MGA 2064W [Millennium]
- 051a MGA 1064SG [Mystique]
- 102b 0100 MGA-1064SG Mystique
- 102b 1100 MGA-1084SG Mystique
- 102b 1200 MGA-1084SG Mystique
- 1100 102b MGA-1084SG Mystique
- 110a 0018 Scenic Pro C5 (D1025)
- 051b MGA 2164W [Millennium II]
- 102b 051b MGA-2164W Millennium II
- 102b 1100 MGA-2164W Millennium II
- 102b 1200 MGA-2164W Millennium II
- 051e MGA 1064SG [Mystique] AGP
- 051f MGA 2164W [Millennium II] AGP
- 0520 MGA G200
- 102b dbc2 G200 Multi-Monitor
- 102b dbc8 G200 Multi-Monitor
- 102b dbe2 G200 Multi-Monitor
- 102b dbe8 G200 Multi-Monitor
- 102b ff03 Millennium G200 SD
- 102b ff04 Marvel G200
- 0521 MGA G200 AGP
- 1014 ff03 Millennium G200 AGP
- 102b 48e9 Mystique G200 AGP
- 102b 48f8 Millennium G200 SD AGP
- 102b 4a60 Millennium G200 LE AGP
- 102b 4a64 Millennium G200 AGP
- 102b c93c Millennium G200 AGP
- 102b c9b0 Millennium G200 AGP
- 102b c9bc Millennium G200 AGP
- 102b ca60 Millennium G250 LE AGP
- 102b ca6c Millennium G250 AGP
- 102b dbbc Millennium G200 AGP
- 102b dbc2 Millennium G200 MMS (Dual G200)
- 102b dbc3 G200 Multi-Monitor
- 102b dbc8 Millennium G200 MMS (Dual G200)
- 102b dbd2 G200 Multi-Monitor
- 102b dbd3 G200 Multi-Monitor
- 102b dbd4 G200 Multi-Monitor
- 102b dbd5 G200 Multi-Monitor
- 102b dbd8 G200 Multi-Monitor
- 102b dbd9 G200 Multi-Monitor
- 102b dbe2 Millennium G200 MMS (Quad G200)
- 102b dbe3 G200 Multi-Monitor
- 102b dbe8 Millennium G200 MMS (Quad G200)
- 102b dbf2 G200 Multi-Monitor
- 102b dbf3 G200 Multi-Monitor
- 102b dbf4 G200 Multi-Monitor
- 102b dbf5 G200 Multi-Monitor
- 102b dbf8 G200 Multi-Monitor
- 102b dbf9 G200 Multi-Monitor
- 102b f806 Mystique G200 Video AGP
- 102b ff00 MGA-G200 AGP
- 102b ff02 Mystique G200 AGP
- 102b ff03 Millennium G200 AGP
- 102b ff04 Marvel G200 AGP
- 110a 0032 MGA-G200 AGP
- 0525 MGA G400 AGP
- 0e11 b16f MGA-G400 AGP
- 102b 0328 Millennium G400 16Mb SDRAM
- 102b 0338 Millennium G400 16Mb SDRAM
- 102b 0378 Millennium G400 32Mb SDRAM
- 102b 0541 Millennium G450 Dual Head
- 102b 0542 Millennium G450 Dual Head LX
- 102b 0543 Millennium G450 Single Head LX
- 102b 0641 Millennium G450 32Mb SDRAM Dual Head
- 102b 0642 Millennium G450 32Mb SDRAM Dual Head LX
- 102b 0643 Millennium G450 32Mb SDRAM Single Head LX
- 102b 07c0 Millennium G450 Dual Head LE
- 102b 07c1 Millennium G450 SDR Dual Head LE
- 102b 0d41 Millennium G450 Dual Head PCI
- 102b 0d42 Millennium G450 Dual Head LX PCI
- 102b 0d43 Millennium G450 32Mb Dual Head PCI
- 102b 0e00 Marvel G450 eTV
- 102b 0e01 Marvel G450 eTV
- 102b 0e02 Marvel G450 eTV
- 102b 0e03 Marvel G450 eTV
- 102b 0f80 Millennium G450 Low Profile
- 102b 0f81 Millennium G450 Low Profile
- 102b 0f82 Millennium G450 Low Profile DVI
- 102b 0f83 Millennium G450 Low Profile DVI
- 102b 19d8 Millennium G400 16Mb SGRAM
- 102b 19f8 Millennium G400 32Mb SGRAM
- 102b 2159 Millennium G400 Dual Head 16Mb
- 102b 2179 Millennium G400 MAX/Dual Head 32Mb
- 102b 217d Millennium G400 Dual Head Max
- 102b 23c0 Millennium G450
- 102b 23c1 Millennium G450
- 102b 23c2 Millennium G450 DVI
- 102b 23c3 Millennium G450 DVI
- 102b 2f58 Millennium G400
- 102b 2f78 Millennium G400
- 102b 3693 Marvel G400 AGP
- 102b 5dd0 4Sight II
- 102b 5f50 4Sight II
- 102b 5f51 4Sight II
- 102b 5f52 4Sight II
- 102b 9010 Millennium G400 Dual Head
- 1458 0400 GA-G400
- 1705 0001 Millennium G450 32MB SGRAM
- 1705 0002 Millennium G450 16MB SGRAM
- 1705 0003 Millennium G450 32MB
- 1705 0004 Millennium G450 16MB
- 0527 MGA Parhelia AGP
- 102b 0840 Parhelia 128Mb
- 0d10 MGA Ultima/Impression
- 1000 MGA G100 [Productiva]
- 102b ff01 Productiva G100
- 102b ff05 Productiva G100 Multi-Monitor
- 1001 MGA G100 [Productiva] AGP
- 102b 1001 MGA-G100 AGP
- 102b ff00 MGA-G100 AGP
- 102b ff01 MGA-G100 Productiva AGP
- 102b ff03 Millennium G100 AGP
- 102b ff04 MGA-G100 AGP
- 102b ff05 MGA-G100 Productiva AGP Multi-Monitor
- 110a 001e MGA-G100 AGP
- 2007 MGA Mistral
- 2527 MGA G550 AGP
- 102b 0f83 Millennium G550
- 102b 0f84 Millennium G550 Dual Head DDR 32Mb
- 102b 1e41 Millennium G550
- 2537 MGA G650 AGP
- 4536 VIA Framegrabber
- 6573 Shark 10/100 Multiport SwitchNIC
-102c Chips and Technologies
- 00b8 F64310
- 00c0 F69000 HiQVideo
- 102c 00c0 F69000 HiQVideo
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1010 CP5/CR6 mainboard
- 4c53 1020 VR6 mainboard
- 4c53 1030 PC5 mainboard
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 00d0 F65545
- 00d8 F65545
- 00dc F65548
- 00e0 F65550
- 00e4 F65554
- 00e5 F65555 HiQVPro
- 0e11 b049 Armada 1700 Laptop Display Controller
- 00f0 F68554
- 00f4 F68554 HiQVision
- 00f5 F68555
- 0c30 F69030
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
-# C5C project cancelled
- 4c53 1080 CT8 mainboard
-102d Wyse Technology Inc.
- 50dc 3328 Audio
-102e Olivetti Advanced Technology
-102f Toshiba America
- 0009 r4x00
- 000a TX3927 MIPS RISC PCI Controller
- 0020 ATM Meteor 155
- 102f 00f8 ATM Meteor 155
- 0030 TC35815CF PCI 10/100 Mbit Ethernet Controller
- 0031 TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL
- 0105 TC86C001 [goku-s] IDE
- 0106 TC86C001 [goku-s] USB 1.1 Host
- 0107 TC86C001 [goku-s] USB Device Controller
- 0108 TC86C001 [goku-s] I2C/SIO/GPIO Controller
- 0180 TX4927/38 MIPS RISC PCI Controller
- 0181 TX4925 MIPS RISC PCI Controller
- 0182 TX4937 MIPS RISC PCI Controller
-1030 TMC Research
-1031 Miro Computer Products AG
- 5601 DC20 ASIC
- 5607 Video I/O & motion JPEG compressor
- 5631 Media 3D
- 6057 MiroVideo DC10/DC30+
-1032 Compaq
-1033 NEC Corporation
- 0000 Vr4181A USB Host or Function Control Unit
- 0001 PCI to 486-like bus Bridge
- 0002 PCI to VL98 Bridge
- 0003 ATM Controller
- 0004 R4000 PCI Bridge
- 0005 PCI to 486-like bus Bridge
- 0006 PC-9800 Graphic Accelerator
- 0007 PCI to UX-Bus Bridge
- 0008 PC-9800 Graphic Accelerator
- 0009 PCI to PC9800 Core-Graph Bridge
- 0016 PCI to VL Bridge
- 001a [Nile II]
- 0021 Vrc4373 [Nile I]
- 0029 PowerVR PCX1
- 002a PowerVR 3D
- 002c Star Alpha 2
- 002d PCI to C-bus Bridge
- 0035 USB
- 1179 0001 USB
- 12ee 7000 Root Hub
- 1799 0001 Root Hub
- 807d 0035 PCI-USB2 (OHCI subsystem)
- 003b PCI to C-bus Bridge
- 003e NAPCCARD Cardbus Controller
- 0046 PowerVR PCX2 [midas]
- 005a Vrc5074 [Nile 4]
- 0063 Firewarden
- 0067 PowerVR Neon 250 Chipset
- 1010 0020 PowerVR Neon 250 AGP 32Mb
- 1010 0080 PowerVR Neon 250 AGP 16Mb
- 1010 0088 PowerVR Neon 250 16Mb
- 1010 0090 PowerVR Neon 250 AGP 16Mb
- 1010 0098 PowerVR Neon 250 16Mb
- 1010 00a0 PowerVR Neon 250 AGP 32Mb
- 1010 00a8 PowerVR Neon 250 32Mb
- 1010 0120 PowerVR Neon 250 AGP 32Mb
- 0072 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr
- 0074 56k Voice Modem
- 1033 8014 RCV56ACF 56k Voice Modem
- 009b Vrc5476
- 00a5 VRC4173
- 00a6 VRC5477 AC97
- 00cd IEEE 1394 [OrangeLink] Host Controller
- 12ee 8011 Root hub
- 00ce IEEE 1394 Host Controller
- 00df Vr4131
- 00e0 USB 2.0
- 0ee4 3383 Sitecom IEEE 1394 / USB2.0 Combo Card
- 12ee 7001 Root hub
- 1799 0002 Root Hub
- 807d 1043 PCI-USB2 (EHCI subsystem)
- 00e7 IEEE 1394 Host Controller
- 00f2 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr
- 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2]
- 010c VR7701
-1034 Framatome Connectors USA Inc.
-1035 Comp. & Comm. Research Lab
-1036 Future Domain Corp.
- 0000 TMC-18C30 [36C70]
-1037 Hitachi Micro Systems
-1038 AMP, Inc
-1039 Silicon Integrated Systems [SiS]
- 0001 Virtual PCI-to-PCI bridge (AGP)
- 0002 SG86C202
- 0006 85C501/2/3
- 0008 SiS85C503/5513 (LPC Bridge)
- 0009 ACPI
-# source: http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
- 0016 SiS961/2 SMBus Controller
- 0018 SiS85C503/5513 (LPC Bridge)
-# Controller for 2 PATA and 2 SATA channels
- 0180 RAID bus controller 180 SATA/PATA [SiS]
- 0181 SiS SATA
- 0200 5597/5598/6326 VGA
- 1039 0000 SiS5597 SVGA (Shared RAM)
- 0204 82C204
- 0205 SG86C205
- 0300 300/305 PCI/AGP VGA Display Adapter
- 107d 2720 Leadtek WinFast VR300
- 0310 315H PCI/AGP VGA Display Adapter
- 0315 315 PCI/AGP VGA Display Adapter
- 0325 315PRO PCI/AGP VGA Display Adapter
- 0330 330 [Xabre] PCI/AGP VGA Display Adapter
- 0406 85C501/2
- 0496 85C496
- 0530 530 Host
- 0540 540 Host
- 0550 550 Host
- 0597 5513C
- 0601 85C601
- 0620 620 Host
- 0630 630 Host
- 0633 633 Host
- 0635 635 Host
- 0645 SiS645 Host & Memory & AGP Controller
- 0646 SiS645DX Host & Memory & AGP Controller
- 0648 SiS 645xx
- 0650 650/M650 Host
- 0651 651 Host
- 0655 655 Host
- 0660 660 Host
- 0661 661FX/M661FX/M661MX Host
- 0730 730 Host
- 0733 733 Host
- 0735 735 Host
- 0740 740 Host
- 0741 741/741GX/M741 Host
- 0745 745 Host
- 0746 746 Host
- 0755 755 Host
- 0760 760/M760 Host
- 0900 SiS900 PCI Fast Ethernet
- 1019 0a14 K7S5A motherboard
- 1039 0900 SiS900 10/100 Ethernet Adapter
- 1043 8035 CUSI-FX motherboard
- 0961 SiS961 [MuTIOL Media IO]
- 0962 SiS962 [MuTIOL Media IO]
- 0963 SiS963 [MuTIOL Media IO]
- 0964 SiS964 [MuTIOL Media IO]
- 0965 SiS965 [MuTIOL Media IO]
- 3602 83C602
- 5107 5107
- 5300 SiS540 PCI Display Adapter
- 5315 550 PCI/AGP VGA Display Adapter
- 5401 486 PCI Chipset
- 5511 5511/5512
- 5513 5513 [IDE]
- 1019 0970 P6STP-FL motherboard
- 1039 5513 SiS5513 EIDE Controller (A,B step)
- 1043 8035 CUSI-FX motherboard
- 5517 5517
- 5571 5571
- 5581 5581 Pentium Chipset
- 5582 5582
- 5591 5591/5592 Host
- 5596 5596 Pentium Chipset
- 5597 5597 [SiS5582]
- 5600 5600 Host
- 6204 Video decoder & MPEG interface
- 6205 VGA Controller
- 6236 6236 3D-AGP
- 6300 630/730 PCI/AGP VGA Display Adapter
- 1019 0970 P6STP-FL motherboard
- 1043 8035 CUSI-FX motherboard
- 6306 530/620 PCI/AGP VGA Display Adapter
- 1039 6306 SiS530,620 GUI Accelerator+3D
- 6325 65x/M650/740 PCI/AGP VGA Display Adapter
- 6326 86C326 5598/6326
- 1039 6326 SiS6326 GUI Accelerator
- 1092 0a50 SpeedStar A50
- 1092 0a70 SpeedStar A70
- 1092 4910 SpeedStar A70
- 1092 4920 SpeedStar A70
- 1569 6326 SiS6326 GUI Accelerator
- 6330 661/741/760 PCI/AGP VGA Display Adapter
- 1039 6330 [M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter
- 7001 USB 1.0 Controller
- 1019 0a14 K7S5A motherboard
- 1039 7000 Onboard USB Controller
- 7002 USB 2.0 Controller
- 1509 7002 Onboard USB Controller
- 7007 FireWire Controller
- 7012 Sound Controller
-# There are may be different modem codecs here (Intel537 compatible and incompatible)
- 7013 AC'97 Modem Controller
- 7016 SiS7016 PCI Fast Ethernet Adapter
- 1039 7016 SiS7016 10/100 Ethernet Adapter
- 7018 SiS PCI Audio Accelerator
- 1014 01b6 SiS PCI Audio Accelerator
- 1014 01b7 SiS PCI Audio Accelerator
- 1019 7018 SiS PCI Audio Accelerator
- 1025 000e SiS PCI Audio Accelerator
- 1025 0018 SiS PCI Audio Accelerator
- 1039 7018 SiS PCI Audio Accelerator
- 1043 800b SiS PCI Audio Accelerator
- 1054 7018 SiS PCI Audio Accelerator
- 107d 5330 SiS PCI Audio Accelerator
- 107d 5350 SiS PCI Audio Accelerator
- 1170 3209 SiS PCI Audio Accelerator
- 1462 400a SiS PCI Audio Accelerator
- 14a4 2089 SiS PCI Audio Accelerator
- 14cd 2194 SiS PCI Audio Accelerator
- 14ff 1100 SiS PCI Audio Accelerator
- 152d 8808 SiS PCI Audio Accelerator
- 1558 1103 SiS PCI Audio Accelerator
- 1558 2200 SiS PCI Audio Accelerator
- 1563 7018 SiS PCI Audio Accelerator
- 15c5 0111 SiS PCI Audio Accelerator
- 270f a171 SiS PCI Audio Accelerator
- a0a0 0022 SiS PCI Audio Accelerator
- 7019 SiS7019 Audio Accelerator
-103a Seiko Epson Corporation
-103b Tatung Co. of America
-103c Hewlett-Packard Company
- 1005 A4977A Visualize EG
- 1006 Visualize FX6
- 1008 Visualize FX4
- 100a Visualize FX2
- 1028 Tach TL Fibre Channel Host Adapter
- 1029 Tach XL2 Fibre Channel Host Adapter
- 107e 000f Interphase 5560 Fibre Channel Adapter
- 9004 9210 1Gb/2Gb Family Fibre Channel Controller
- 9004 9211 1Gb/2Gb Family Fibre Channel Controller
- 102a Tach TS Fibre Channel Host Adapter
- 107e 000e Interphase 5540/5541 Fibre Channel Adapter
- 9004 9110 1Gb/2Gb Family Fibre Channel Controller
- 9004 9111 1Gb/2Gb Family Fibre Channel Controller
- 1030 J2585A DeskDirect 10/100VG NIC
- 1031 J2585B HP 10/100VG PCI LAN Adapter
- 103c 1040 J2973A DeskDirect 10BaseT NIC
- 103c 1041 J2585B DeskDirect 10/100VG NIC
- 103c 1042 J2970A DeskDirect 10BaseT/2 NIC
- 1040 J2973A DeskDirect 10BaseT NIC
- 1041 J2585B DeskDirect 10/100 NIC
- 1042 J2970A DeskDirect 10BaseT/2 NIC
- 1048 Diva Serial [GSP] Multiport UART
- 103c 1049 Tosca Console
- 103c 104a Tosca Secondary
- 103c 104b Maestro SP2
- 103c 1223 Superdome Console
- 103c 1226 Keystone SP2
- 103c 1227 Powerbar SP2
- 103c 1282 Everest SP2
- 103c 1301 Diva RMP3
- 1054 PCI Local Bus Adapter
- 1064 79C970 PCnet Ethernet Controller
- 108b Visualize FXe
- 10c1 NetServer Smart IRQ Router
- 10ed TopTools Remote Control
- 10f0 rio System Bus Adapter
- 10f1 rio I/O Controller
- 1200 82557B 10/100 NIC
- 1219 NetServer PCI Hot-Plug Controller
- 121a NetServer SMIC Controller
- 121b NetServer Legacy COM Port Decoder
- 121c NetServer PCI COM Port Decoder
- 1229 zx1 System Bus Adapter
- 122a zx1 I/O Controller
- 122e zx1 Local Bus Adapter
- 127c sx1000 I/O Controller
- 1290 Auxiliary Diva Serial Port
- 12b4 zx1 QuickSilver AGP8x Local Bus Adapter
- 2910 E2910A PCIBus Exerciser
- 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer
-103e Solliday Engineering
-103f Synopsys/Logic Modeling Group
-1040 Accelgraphics Inc.
-1041 Computrend
-1042 Micron
- 1000 PC Tech RZ1000
- 1001 PC Tech RZ1001
- 3000 Samurai_0
- 3010 Samurai_1
- 3020 Samurai_IDE
-1043 ASUSTeK Computer Inc.
- 0675 ISDNLink P-IN100-ST-D
- 4015 v7100 SDRAM [GeForce2 MX]
- 4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner]
- 4057 v8200 GeForce 3
- 8043 v8240 PAL 128M [P4T] Motherboard
- 807b v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
- 80bb v9180 Magic/T [GeForce4 MX440 AGP 8x 64MB TV-out]
- 80c5 nForce3 chipset motherboard [SK8N]
- 80df v9520 Magic/T
-1044 Adaptec (formerly DPT)
- 1012 Domino RAID Engine
- a400 SmartCache/Raid I-IV Controller
- a500 PCI Bridge
- a501 SmartRAID V Controller
- 1044 c001 PM1554U2 Ultra2 Single Channel
- 1044 c002 PM1654U2 Ultra2 Single Channel
- 1044 c003 PM1564U3 Ultra3 Single Channel
- 1044 c004 PM1564U3 Ultra3 Dual Channel
- 1044 c005 PM1554U2 Ultra2 Single Channel (NON ACPI)
- 1044 c00a PM2554U2 Ultra2 Single Channel
- 1044 c00b PM2654U2 Ultra2 Single Channel
- 1044 c00c PM2664U3 Ultra3 Single Channel
- 1044 c00d PM2664U3 Ultra3 Dual Channel
- 1044 c00e PM2554U2 Ultra2 Single Channel (NON ACPI)
- 1044 c00f PM2654U2 Ultra2 Single Channel (NON ACPI)
- 1044 c014 PM3754U2 Ultra2 Single Channel (NON ACPI)
- 1044 c015 PM3755U2B Ultra2 Single Channel (NON ACPI)
- 1044 c016 PM3755F Fibre Channel (NON ACPI)
- 1044 c01e PM3757U2 Ultra2 Single Channel
- 1044 c01f PM3757U2 Ultra2 Dual Channel
- 1044 c020 PM3767U3 Ultra3 Dual Channel
- 1044 c021 PM3767U3 Ultra3 Quad Channel
- 1044 c028 PM2865U3 Ultra3 Single Channel
- 1044 c029 PM2865U3 Ultra3 Dual Channel
- 1044 c02a PM2865F Fibre Channel
- 1044 c03c 2000S Ultra3 Single Channel
- 1044 c03d 2000S Ultra3 Dual Channel
- 1044 c03e 2000F Fibre Channel
- 1044 c046 3000S Ultra3 Single Channel
- 1044 c047 3000S Ultra3 Dual Channel
- 1044 c048 3000F Fibre Channel
- 1044 c050 5000S Ultra3 Single Channel
- 1044 c051 5000S Ultra3 Dual Channel
- 1044 c052 5000F Fibre Channel
- 1044 c05a 2400A UDMA Four Channel
- 1044 c05b 2400A UDMA Four Channel DAC
- 1044 c064 3010S Ultra3 Dual Channel
- 1044 c065 3410S Ultra160 Four Channel
- 1044 c066 3010S Fibre Channel
- a511 SmartRAID V Controller
- 1044 c032 ASR-2005S I2O Zero Channel
-1045 OPTi Inc.
- a0f8 82C750 [Vendetta] USB Controller
- c101 92C264
- c178 92C178
- c556 82X556 [Viper]
- c557 82C557 [Viper-M]
- c558 82C558 [Viper-M ISA+IDE]
- c567 82C750 [Vendetta], device 0
- c568 82C750 [Vendetta], device 1
- c569 82C579 [Viper XPress+ Chipset]
- c621 82C621 [Viper-M/N+]
- c700 82C700 [FireStar]
- c701 82C701 [FireStar Plus]
- c814 82C814 [Firebridge 1]
- c822 82C822
- c824 82C824
- c825 82C825 [Firebridge 2]
- c832 82C832
- c861 82C861
- c895 82C895
- c935 EV1935 ECTIVA MachOne PCIAudio
- d568 82C825 [Firebridge 2]
- d721 IDE [FireStar]
-1046 IPC Corporation, Ltd.
-1047 Genoa Systems Corp
-1048 Elsa AG
- 0c60 Gladiac MX
- 0d22 Quadro4 900XGL [ELSA GLoria4 900XGL]
- 1000 QuickStep 1000
- 3000 QuickStep 3000
- 8901 Gloria XL
-1049 Fountain Technologies, Inc.
-# # nee SGS Thomson Microelectronics
-104a STMicroelectronics
- 0008 STG 2000X
- 0009 STG 1764X
- 0010 STG4000 [3D Prophet Kyro Series]
- 0209 STPC Consumer/Industrial North- and Southbridge
- 020a STPC Atlas/ConsumerS/Consumer IIA Northbridge
-# From <http://gatekeeper.dec.com/pub/BSD/FreeBSD/FreeBSD-stable/src/share/misc/pci_vendors>
- 0210 STPC Atlas ISA Bridge
- 021a STPC Consumer S Southbridge
- 021b STPC Consumer IIA Southbridge
- 0500 ST70137 [Unicorn] ADSL DMT Transceiver
- 0564 STPC Client Northbridge
- 0981 21x4x DEC-Tulip compatible 10/100 Ethernet
- 1746 STG 1764X
- 2774 21x4x DEC-Tulip compatible 10/100 Ethernet
- 3520 MPEG-II decoder card
- 55cc STPC Client Southbridge
-104b BusLogic
- 0140 BT-946C (old) [multimaster 01]
- 1040 BT-946C (BA80C30) [MultiMaster 10]
- 8130 Flashpoint LT
-104c Texas Instruments
- 0500 100 MBit LAN Controller
- 0508 TMS380C2X Compressor Interface
- 1000 Eagle i/f AS
- 104c PCI1510 PC card Cardbus Controller
- 3d04 TVP4010 [Permedia]
- 3d07 TVP4020 [Permedia 2]
- 1011 4d10 Comet
- 1040 000f AccelStar II
- 1040 0011 AccelStar II
- 1048 0a31 WINNER 2000
- 1048 0a32 GLoria Synergy
- 1048 0a35 GLoria Synergy
- 107d 2633 WinFast 3D L2300
- 1092 0127 FIRE GL 1000 PRO
- 1092 0136 FIRE GL 1000 PRO
- 1092 0141 FIRE GL 1000 PRO
- 1092 0146 FIRE GL 1000 PRO
- 1092 0148 FIRE GL 1000 PRO
- 1092 0149 FIRE GL 1000 PRO
- 1092 0152 FIRE GL 1000 PRO
- 1092 0154 FIRE GL 1000 PRO
- 1092 0155 FIRE GL 1000 PRO
- 1092 0156 FIRE GL 1000 PRO
- 1092 0157 FIRE GL 1000 PRO
- 1097 3d01 Jeronimo Pro
- 1102 100f Graphics Blaster Extreme
- 3d3d 0100 Reference Permedia 2 3D
- 8000 PCILynx/PCILynx2 IEEE 1394 Link Layer Controller
- e4bf 1010 CF1-1-SNARE
- e4bf 1020 CF1-2-SNARE
- 8009 FireWire Controller
- 104d 8032 8032 OHCI i.LINK (IEEE 1394) Controller
- 8017 PCI4410 FireWire Controller
- 8019 TSB12LV23 IEEE-1394 Controller
- 11bd 000a Studio DV500-1394
- 11bd 000e Studio DV
- e4bf 1010 CF2-1-CYMBAL
- 8020 TSB12LV26 IEEE-1394 Controller (Link)
- 11bd 000f Studio DV500-1394
- 8021 TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated)
- 104d 80df Vaio PCG-FX403
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 8022 TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link)
- 8023 TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)
- 103c 088c nc8000 laptop
- 8024 TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link)
- 8025 TSB82AA2 IEEE-1394b Link Layer Controller
- 55aa 55aa FireWire 800 PCI Card
- 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link)
- 8027 PCI4451 IEEE-1394 Controller
- 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
- 8029 PCI4510 IEEE-1394 Controller
- 1028 0163 Latitude D505
- 1071 8160 MIM2900
- 802b PCI7410,7510,7610 OHCI-Lynx Controller
- 1028 014e PCI7410,7510,7610 OHCI-Lynx Controller (Dell Latitude D800)
- 802e PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
- 8031 Texas Instruments PCIxx21/x515 Cardbus Controller
- 8032 Texas Instruments OHCI Compliant IEEE 1394 Host Controller
- 8033 Texas Instruments PCIxx21 Integrated FlashMedia Controller
- 8034 Texas Instruments PCI6411, PCI6421, PCI6611, PCI6621, PCI7411, PCI7421, PCI7611, PCI7621 Secure Digital (SD) Controller
- 8035 Texas Instruments PCI6411, PCI6421, PCI6611, PCI6621, PCI7411, PCI7421, PCI7611, PCI7621 Smart Card Controller (SMC)
- 8201 PCI1620 Firmware Loading Function
- 8204 PCI7410,7510,7610 PCI Firmware Loading Function
- 1028 014e Latitude D800
- 8400 ACX 100 22Mbps Wireless Interface
- 00fc 16ec U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
- 00fd 16ec U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
- 1186 3b00 DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]
- 1186 3b01 DWL-520+ 22Mbps PCI Wireless Adapter
- 8401 ACX 100 22Mbps Wireless Interface
-# OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi
- 9000 Wireless Interface (of unknown type)
- 9066 ACX 111 54Mbps Wireless Interface
- a001 TDC1570
- a100 TDC1561
- a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f
- a106 TMS320C6205 Fixed Point DSP
- 175c 5000 ASI50xx Audio Adapter
- 175c 8700 ASI87xx Radio Tuner card
- ac10 PCI1050
- ac11 PCI1053
- ac12 PCI1130
- ac13 PCI1031
- ac15 PCI1131
- ac16 PCI1250
- 1014 0092 ThinkPad 600
- ac17 PCI1220
- ac18 PCI1260
- ac19 PCI1221
- ac1a PCI1210
- ac1b PCI1450
- 0e11 b113 Armada M700
- ac1c PCI1225
- 0e11 b121 Armada E500
- 1028 0088 Dell Computer Corporation Latitude CPi A400XT
- ac1d PCI1251A
- ac1e PCI1211
- ac1f PCI1251B
- ac20 TI 2030
- ac21 PCI2031
- ac22 PCI2032 PCI Docking Bridge
- ac23 PCI2250 PCI-to-PCI Bridge
- ac28 PCI2050 PCI-to-PCI Bridge
- ac30 PCI1260 PC card Cardbus Controller
- ac40 PCI4450 PC card Cardbus Controller
- ac41 PCI4410 PC card Cardbus Controller
- ac42 PCI4451 PC card Cardbus Controller
- 1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100)
- ac44 PCI4510 PC card Cardbus Controller
- 1028 0163 Latitude D505
- 1071 8160 MIM2000
- ac46 PCI4520 PC card Cardbus Controller
- ac47 PCI7510 PC card Cardbus Controller
- 1028 014e Latitude D800
- ac4a PCI7510,7610 PC card Cardbus Controller
- 1028 014e Latitude D800
- ac50 PCI1410 PC card Cardbus Controller
- ac51 PCI1420
- 1014 023b ThinkPad T23 (2647-4MG)
- 1028 00b1 Latitude C600
- 1028 012a Latitude C640
- 1033 80cd Versa Note VXi
- 10cf 1095 Lifebook C6155
- e4bf 1000 CP2-2-HIPHOP
- ac52 PCI1451 PC card Cardbus Controller
- ac53 PCI1421 PC card Cardbus Controller
- ac54 PCI1620 PC Card Controller
- ac55 PCI1520 PC card Cardbus Controller
- 1014 0512 ThinkPad T30/T40
- ac56 PCI1510 PC card Cardbus Controller
- 1014 0528 ThinkPad R40e (2684-HVG) Cardbus Controller
- ac60 PCI2040 PCI to DSP Bridge Controller
- 175c 5100 ASI51xx Audio Adapter
- 175c 6100 ASI61xx Audio Adapter
- 175c 6200 ASI62xx Audio Adapter
- ac8d PCI 7620
- ac8e PCI7420 CardBus Controller
- ac8f PCI7420/PCI7620 Dual Socket CardBus and Smart Card Cont. w/ 1394a-2000 OHCI Two-Port PHY/Link-Layer Cont. and SD/MS-Pro Sockets
- fe00 FireWire Host Controller
- fe03 12C01A FireWire Host Controller
-104d Sony Corporation
- 8004 DTL-H2500 [Playstation development board]
- 8009 CXD1947Q i.LINK Controller
- 8039 CXD3222 i.LINK Controller
- 8056 Rockwell HCF 56K modem
- 808a Memory Stick Controller
-104e Oak Technology, Inc
- 0017 OTI-64017
- 0107 OTI-107 [Spitfire]
- 0109 Video Adapter
- 0111 OTI-64111 [Spitfire]
- 0217 OTI-64217
- 0317 OTI-64317
-104f Co-time Computer Ltd
-1050 Winbond Electronics Corp
- 0000 NE2000
- 0001 W83769F
- 0105 W82C105
- 0840 W89C840
- 1050 0001 W89C840 Ethernet Adapter
- 1050 0840 W89C840 Ethernet Adapter
- 0940 W89C940
- 5a5a W89C940F
- 6692 W6692
- 9921 W99200F MPEG-1 Video Encoder
- 9922 W99200F/W9922PF MPEG-1/2 Video Encoder
- 9970 W9970CF
-1051 Anigma, Inc.
-1052 ?Young Micro Systems
-1053 Young Micro Systems
-1054 Hitachi, Ltd
-1055 Efar Microsystems
- 9130 SLC90E66 [Victory66] IDE
- 9460 SLC90E66 [Victory66] ISA
- 9462 SLC90E66 [Victory66] USB
- 9463 SLC90E66 [Victory66] ACPI
-1056 ICL
-# Motorola made a mistake and used 1507 instead of 1057 in some chips. Please look at the 1507 entry as well when updating this.
-1057 Motorola
- 0001 MPC105 [Eagle]
- 0002 MPC106 [Grackle]
- 0003 MPC8240 [Kahlua]
- 0004 MPC107
- 0006 MPC8245 [Unity]
- 0008 MPC8540
- 0009 MPC8560
- 0100 MC145575 [HFC-PCI]
- 0431 KTI829c 100VG
- 1801 DSP56301 Digital Signal Processor
- 14fb 0101 Transas Radar Imitator Board [RIM]
- 14fb 0102 Transas Radar Imitator Board [RIM-2]
- 14fb 0202 Transas Radar Integrator Board [RIB-2]
- 14fb 0611 1 channel CAN bus Controller [CanPci-1]
- 14fb 0612 2 channels CAN bus Controller [CanPci-2]
- 14fb 0613 3 channels CAN bus Controller [CanPci-3]
- 14fb 0614 4 channels CAN bus Controller [CanPci-4]
- 14fb 0621 1 channel CAN bus Controller [CanPci2-1]
- 14fb 0622 2 channels CAN bus Controller [CanPci2-2]
- 14fb 0810 Transas VTS Radar Integrator Board [RIB-4]
- 175c 4200 ASI4215 Audio Adapter
- 175c 4300 ASI43xx Audio Adapter
- 175c 4400 ASI4401 Audio Adapter
- ecc0 0010 Darla
- ecc0 0020 Gina
- ecc0 0030 Layla rev.0
- ecc0 0031 Layla rev.1
- ecc0 0040 Darla24 rev.0
- ecc0 0041 Darla24 rev.1
- ecc0 0050 Gina24 rev.0
- ecc0 0051 Gina24 rev.1
- ecc0 0070 Mona rev.0
- ecc0 0071 Mona rev.1
- ecc0 0072 Mona rev.2
- 18c0 MPC8265A/MPC8266
- 18c1 MPC8271/MPC8272
- 3410 DSP56361 Digital Signal Processor
- ecc0 0050 Gina24 rev.0
- ecc0 0051 Gina24 rev.1
- ecc0 0060 Layla24
- ecc0 0070 Mona rev.0
- ecc0 0071 Mona rev.1
- ecc0 0072 Mona rev.2
- ecc0 0080 Mia rev.0
- ecc0 0081 Mia rev.1
- ecc0 0090 Indigo
- ecc0 00a0 Indigo IO
- ecc0 00b0 Indigo DJ
- ecc0 0100 3G
- 4801 Raven
- 4802 Falcon
- 4803 Hawk
- 4806 CPX8216
- 4d68 20268
- 5600 SM56 PCI Modem
- 1057 0300 SM56 PCI Speakerphone Modem
- 1057 0301 SM56 PCI Voice Modem
- 1057 0302 SM56 PCI Fax Modem
- 1057 5600 SM56 PCI Voice modem
- 13d2 0300 SM56 PCI Speakerphone Modem
- 13d2 0301 SM56 PCI Voice modem
- 13d2 0302 SM56 PCI Fax Modem
- 1436 0300 SM56 PCI Speakerphone Modem
- 1436 0301 SM56 PCI Voice modem
- 1436 0302 SM56 PCI Fax Modem
- 144f 100c SM56 PCI Fax Modem
- 1494 0300 SM56 PCI Speakerphone Modem
- 1494 0301 SM56 PCI Voice modem
- 14c8 0300 SM56 PCI Speakerphone Modem
- 14c8 0302 SM56 PCI Fax Modem
- 1668 0300 SM56 PCI Speakerphone Modem
- 1668 0302 SM56 PCI Fax Modem
- 5803 MPC5200
- 6400 MPC190 Security Processor (S1 family, encryption)
- 6405 MPC184 Security Processor (S1 family)
-1058 Electronics & Telecommunications RSH
-1059 Teknor Industrial Computers Inc
-105a Promise Technology, Inc.
-# more correct description from promise linux sources
- 0d30 PDC20265 (FastTrak100 Lite/Ultra100)
- 105a 4d33 Ultra100
- 0d38 20263
- 105a 4d39 Fasttrak66
- 1275 20275
- 3318 PDC20318 (SATA150 TX4)
- 3319 PDC20319 (FastTrak S150 TX4)
- 8086 3427 S875WP1-E mainboard
- 3371 PDC20371 (FastTrak S150 TX2plus)
- 3373 PDC20378 (FastTrak 378/SATA 378)
- 1043 80f5 K8V Deluxe/PC-DL Deluxe motherboard
- 1462 702e K8T NEO FIS2R motherboard
- 3375 PDC20375 (SATA150 TX2plus)
- 3376 PDC20376 (FastTrak 376)
- 1043 809e A7V8X motherboard
- 3574 PDC20579 SATAII 150 IDE Controller
- 3d18 PDC20518/PDC40518 (SATAII 150 TX4)
- 3d75 PDC20575 (SATAII150 TX2plus)
- 4d30 PDC20267 (FastTrak100/Ultra100)
- 105a 4d33 Ultra100
- 105a 4d39 FastTrak100
- 4d33 20246
- 105a 4d33 20246 IDE Controller
- 4d38 PDC20262 (FastTrak66/Ultra66)
- 105a 4d30 Ultra Device on SuperTrak
- 105a 4d33 Ultra66
- 105a 4d39 FastTrak66
- 4d68 PDC20268 (Ultra100 TX2)
- 105a 4d68 Ultra100TX2
- 4d69 20269
- 105a 4d68 Ultra133TX2
- 5275 PDC20276 (MBFastTrak133 Lite)
- 105a 0275 SuperTrak SX6000 IDE
- 105a 1275 MBFastTrak133 Lite (tm) Controller (RAID mode)
- 1458 b001 MBUltra 133
- 5300 DC5300
- 6268 PDC20270 (FastTrak100 LP/TX2/TX4)
- 105a 4d68 FastTrak100 TX2
- 6269 PDC20271 (FastTrak TX2000)
- 105a 6269 FastTrak TX2/TX2000
- 6621 PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite)
- 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller
- 6626 PDC20618 (Ultra 618)
- 6629 PDC20619 (FastTrak TX4000)
- 7275 PDC20277 (SBFastTrak133 Lite)
-105b Foxconn International, Inc.
-105c Wipro Infotech Limited
-105d Number 9 Computer Company
- 2309 Imagine 128
- 2339 Imagine 128-II
- 105d 0000 Imagine 128 series 2 4Mb VRAM
- 105d 0001 Imagine 128 series 2 4Mb VRAM
- 105d 0002 Imagine 128 series 2 4Mb VRAM
- 105d 0003 Imagine 128 series 2 4Mb VRAM
- 105d 0004 Imagine 128 series 2 4Mb VRAM
- 105d 0005 Imagine 128 series 2 4Mb VRAM
- 105d 0006 Imagine 128 series 2 4Mb VRAM
- 105d 0007 Imagine 128 series 2 4Mb VRAM
- 105d 0008 Imagine 128 series 2e 4Mb DRAM
- 105d 0009 Imagine 128 series 2e 4Mb DRAM
- 105d 000a Imagine 128 series 2 8Mb VRAM
- 105d 000b Imagine 128 series 2 8Mb H-VRAM
- 11a4 000a Barco Metheus 5 Megapixel
- 13cc 0000 Barco Metheus 5 Megapixel
- 13cc 0004 Barco Metheus 5 Megapixel
- 13cc 0005 Barco Metheus 5 Megapixel
- 13cc 0006 Barco Metheus 5 Megapixel
- 13cc 0008 Barco Metheus 5 Megapixel
- 13cc 0009 Barco Metheus 5 Megapixel
- 13cc 000a Barco Metheus 5 Megapixel
- 13cc 000c Barco Metheus 5 Megapixel
- 493d Imagine 128 T2R [Ticket to Ride]
- 11a4 000a Barco Metheus 5 Megapixel, Dual Head
- 11a4 000b Barco Metheus 5 Megapixel, Dual Head
- 13cc 0002 Barco Metheus 4 Megapixel, Dual Head
- 13cc 0003 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0007 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0008 Barco Metheus 5 Megapixel, Dual Head
- 13cc 0009 Barco Metheus 5 Megapixel, Dual Head
- 13cc 000a Barco Metheus 5 Megapixel, Dual Head
- 5348 Revolution 4
- 105d 0037 Revolution IV-FP AGP (For SGI 1600SW)
-105e Vtech Computers Ltd
-105f Infotronic America Inc
-1060 United Microelectronics [UMC]
- 0001 UM82C881
- 0002 UM82C886
- 0101 UM8673F
- 0881 UM8881
- 0886 UM8886F
- 0891 UM8891A
- 1001 UM886A
- 673a UM8886BF
- 673b EIDE Master/DMA
- 8710 UM8710
- 886a UM8886A
- 8881 UM8881F
- 8886 UM8886F
- 888a UM8886A
- 8891 UM8891A
- 9017 UM9017F
- 9018 UM9018
- 9026 UM9026
- e881 UM8881N
- e886 UM8886N
- e88a UM8886N
- e891 UM8891N
-1061 I.I.T.
- 0001 AGX016
- 0002 IIT3204/3501
-1062 Maspar Computer Corp
-1063 Ocean Office Automation
-1064 Alcatel
-1065 Texas Microsystems
-1066 PicoPower Technology
- 0000 PT80C826
- 0001 PT86C521 [Vesuvius v1] Host Bridge
- 0002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Master
- 0003 PT86C524 [Nile] PCI-to-PCI Bridge
- 0004 PT86C525 [Nile-II] PCI-to-PCI Bridge
- 0005 National PC87550 System Controller
- 8002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave
-1067 Mitsubishi Electric
- 0301 AccelGraphics AccelECLIPSE
- 0304 AccelGALAXY A2100 [OEM Evans & Sutherland]
- 0308 Tornado 3000 [OEM Evans & Sutherland]
- 1002 VG500 [VolumePro Volume Rendering Accelerator]
-1068 Diversified Technology
-1069 Mylex Corporation
- 0001 DAC960P
- 0002 DAC960PD
- 0010 DAC960PG
- 0020 DAC960LA
- 0050 AcceleRAID 352/170/160 support Device
- b166 Gemstone chipset SCSI controller
- 1014 0242 iSeries 2872 DASD IOA
- 1014 0266 Dual Channel PCI-X U320 SCSI Adapter
- 1014 0278 Dual Channel PCI-X U320 SCSI RAID Adapter
- 1014 02d3 Dual Channel PCI-X U320 SCSI Adapter
- 1014 02d4 Dual Channel PCI-X U320 SCSI RAID Adapter
- ba55 eXtremeRAID 1100 support Device
- ba56 eXtremeRAID 2000/3000 support Device
-106a Aten Research Inc
-106b Apple Computer Inc.
- 0001 Bandit PowerPC host bridge
- 0002 Grand Central I/O
- 0003 Control Video
- 0004 PlanB Video-In
- 0007 O'Hare I/O
- 000c DOS on Mac
- 000e Hydra Mac I/O
- 0010 Heathrow Mac I/O
- 0017 Paddington Mac I/O
- 0018 UniNorth FireWire
- 0019 KeyLargo USB
- 001e UniNorth Internal PCI
- 001f UniNorth PCI
- 0020 UniNorth AGP
- 0021 UniNorth GMAC (Sun GEM)
- 0022 KeyLargo Mac I/O
- 0024 UniNorth/Pangea GMAC (Sun GEM)
- 0025 KeyLargo/Pangea Mac I/O
- 0026 KeyLargo/Pangea USB
- 0027 UniNorth/Pangea AGP
- 0028 UniNorth/Pangea PCI
- 0029 UniNorth/Pangea Internal PCI
- 002d UniNorth 1.5 AGP
- 002e UniNorth 1.5 PCI
- 002f UniNorth 1.5 Internal PCI
- 0030 UniNorth/Pangea FireWire
- 0031 UniNorth 2 FireWire
- 0032 UniNorth 2 GMAC (Sun GEM)
- 0033 UniNorth 2 ATA/100
- 0034 UniNorth 2 AGP
- 0035 UniNorth 2 PCI
- 0036 UniNorth 2 Internal PCI
- 003b UniNorth/Intrepid ATA/100
- 003e KeyLargo/Intrepid Mac I/O
- 003f KeyLargo/Intrepid USB
- 0040 K2 KeyLargo USB
- 0041 K2 KeyLargo Mac/IO
- 0042 K2 FireWire
- 0043 K2 ATA/100
- 0045 K2 HT-PCI Bridge
- 0046 K2 HT-PCI Bridge
- 0047 K2 HT-PCI Bridge
- 0048 K2 HT-PCI Bridge
- 0049 K2 HT-PCI Bridge
- 004b U3 AGP
- 004c K2 GMAC (Sun GEM)
- 004f Shasta Mac I/O
- 0050 Shasta IDE
- 0051 Shasta (Sun GEM)
- 0052 Shasta Firewire
- 0053 Shasta PCI Bridge
- 0054 Shasta PCI Bridge
- 0055 Shasta PCI Bridge
- 0058 U3L AGP Bridge
- 1645 Tigon3 Gigabit Ethernet NIC (BCM5701)
-106c Hynix Semiconductor
- 8801 Dual Pentium ISA/PCI Motherboard
- 8802 PowerPC ISA/PCI Motherboard
- 8803 Dual Window Graphics Accelerator
- 8804 LAN Controller
- 8805 100-BaseT LAN
-106d Sequent Computer Systems
-106e DFI, Inc
-106f City Gate Development Ltd
-1070 Daewoo Telecom Ltd
-1071 Mitac
- 8160 Mitac 8060B Mobile Platform
-1072 GIT Co Ltd
-1073 Yamaha Corporation
- 0001 3D GUI Accelerator
- 0002 YGV615 [RPA3 3D-Graphics Controller]
- 0003 YMF-740
- 0004 YMF-724
- 1073 0004 YMF724-Based PCI Audio Adapter
- 0005 DS1 Audio
- 1073 0005 DS-XG PCI Audio CODEC
- 0006 DS1 Audio
- 0008 DS1 Audio
- 1073 0008 DS-XG PCI Audio CODEC
- 000a DS1L Audio
- 1073 0004 DS-XG PCI Audio CODEC
- 1073 000a DS-XG PCI Audio CODEC
- 000c YMF-740C [DS-1L Audio Controller]
- 107a 000c DS-XG PCI Audio CODEC
- 000d YMF-724F [DS-1 Audio Controller]
- 1073 000d DS-XG PCI Audio CODEC
- 0010 YMF-744B [DS-1S Audio Controller]
- 1073 0006 DS-XG PCI Audio CODEC
- 1073 0010 DS-XG PCI Audio CODEC
- 0012 YMF-754 [DS-1E Audio Controller]
- 1073 0012 DS-XG PCI Audio Codec
- 0020 DS-1 Audio
- 2000 DS2416 Digital Mixing Card
- 1073 2000 DS2416 Digital Mixing Card
-1074 NexGen Microsystems
- 4e78 82c500/1
-1075 Advanced Integrations Research
-1076 Chaintech Computer Co. Ltd
-1077 QLogic Corp.
- 1016 ISP10160 Single Channel Ultra3 SCSI Processor
- 1020 ISP1020 Fast-wide SCSI
- 1022 ISP1022 Fast-wide SCSI
- 1080 ISP1080 SCSI Host Adapter
- 1216 ISP12160 Dual Channel Ultra3 SCSI Processor
- 101e 8471 QLA12160 on AMI MegaRAID
- 101e 8493 QLA12160 on AMI MegaRAID
- 1240 ISP1240 SCSI Host Adapter
- 1280 ISP1280 SCSI Host Adapter
- 2020 ISP2020A Fast!SCSI Basic Adapter
- 2100 QLA2100 64-bit Fibre Channel Adapter
- 1077 0001 QLA2100 64-bit Fibre Channel Adapter
- 2200 QLA2200 64-bit Fibre Channel Adapter
- 1077 0002 QLA2200
- 2300 QLA2300 64-bit Fibre Channel Adapter
- 2312 QLA2312 Fibre Channel Adapter
-1078 Cyrix Corporation
- 0000 5510 [Grappa]
- 0001 PCI Master
- 0002 5520 [Cognac]
- 0100 5530 Legacy [Kahlua]
- 0101 5530 SMI [Kahlua]
- 0102 5530 IDE [Kahlua]
- 0103 5530 Audio [Kahlua]
- 0104 5530 Video [Kahlua]
- 0400 ZFMicro PCI Bridge
- 0401 ZFMicro Chipset SMI
- 0402 ZFMicro Chipset IDE
- 0403 ZFMicro Expansion Bus
-1079 I-Bus
-107a NetWorth
-107b Gateway 2000
-107c LG Electronics [Lucky Goldstar Co. Ltd]
-107d LeadTek Research Inc.
- 0000 P86C850
- 2134 WinFast 3D S320 II
- 2971 [GeForce FX 5900] WinFast A350 TDH MyViVo
-107e Interphase Corporation
- 0001 5515 ATM Adapter [Flipper]
- 0002 100 VG AnyLan Controller
- 0004 5526 Fibre Channel Host Adapter
- 0005 x526 Fibre Channel Host Adapter
- 0008 5525/5575 ATM Adapter (155 Mbit) [Atlantic]
- 9003 5535-4P-BRI-ST
- 9007 5535-4P-BRI-U
- 9008 5535-1P-SR
- 900c 5535-1P-SR-ST
- 900e 5535-1P-SR-U
- 9011 5535-1P-PRI
- 9013 5535-2P-PRI
- 9023 5536-4P-BRI-ST
- 9027 5536-4P-BRI-U
- 9031 5536-1P-PRI
- 9033 5536-2P-PRI
-107f Data Technology Corporation
- 0802 SL82C105
-1080 Contaq Microsystems
- 0600 82C599
- c691 Cypress CY82C691
- c693 82c693
-1081 Supermac Technology
- 0d47 Radius PCI to NuBUS Bridge
-1082 EFA Corporation of America
-1083 Forex Computer Corporation
- 0001 FR710
-1084 Parador
-1085 Tulip Computers Int.B.V.
-1086 J. Bond Computer Systems
-1087 Cache Computer
-1088 Microcomputer Systems (M) Son
-1089 Data General Corporation
-# Formerly Bit3 Computer Corp.
-108a SBS Technologies
- 0001 VME Bridge Model 617
- 0010 VME Bridge Model 618
- 0040 dataBLIZZARD
- 3000 VME Bridge Model 2706
-108c Oakleigh Systems Inc.
-108d Olicom
- 0001 Token-Ring 16/4 PCI Adapter (3136/3137)
- 0002 16/4 Token Ring
- 0004 RapidFire 3139 Token-Ring 16/4 PCI Adapter
- 108d 0004 OC-3139/3140 RapidFire Token-Ring 16/4 Adapter
- 0005 GoCard 3250 Token-Ring 16/4 CardBus PC Card
- 0006 OC-3530 RapidFire Token-Ring 100
- 0007 RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter
- 108d 0007 OC-3141 RapidFire Token-Ring 16/4 Adapter
- 0008 RapidFire 3540 HSTR 100/16/4 PCI Adapter
- 108d 0008 OC-3540 RapidFire HSTR 100/16/4 Adapter
- 0011 OC-2315
- 0012 OC-2325
- 0013 OC-2183/2185
- 0014 OC-2326
- 0019 OC-2327/2250 10/100 Ethernet Adapter
- 108d 0016 OC-2327 Rapidfire 10/100 Ethernet Adapter
- 108d 0017 OC-2250 GoCard 10/100 Ethernet Adapter
- 0021 OC-6151/6152 [RapidFire ATM 155]
- 0022 ATM Adapter
-108e Sun Microsystems Computer Corp.
- 0001 EBUS
- 1000 EBUS
- 1001 Happy Meal
- 1100 RIO EBUS
- 1101 RIO GEM
- 1102 RIO 1394
- 1103 RIO USB
- 1648 [bge] Gigabit Ethernet
- 2bad GEM
- 5000 Simba Advanced PCI Bridge
- 5043 SunPCI Co-processor
- 8000 Psycho PCI Bus Module
- 8001 Schizo PCI Bus Module
- 8002 Schizo+ PCI Bus Module
- a000 Ultra IIi
- a001 Ultra IIe
- a801 Tomatillo PCI Bus Module
- abba Cassini 10/100/1000
-108f Systemsoft
-1090 Encore Computer Corporation
-1091 Intergraph Corporation
- 0020 3D graphics processor
- 0021 3D graphics processor w/Texturing
- 0040 3D graphics frame buffer
- 0041 3D graphics frame buffer
- 0060 Proprietary bus bridge
- 00e4 Powerstorm 4D50T
- 0720 Motion JPEG codec
- 07a0 Sun Expert3D-Lite Graphics Accelerator
- 1091 Sun Expert3D Graphics Accelerator
-1092 Diamond Multimedia Systems
- 00a0 Speedstar Pro SE
- 00a8 Speedstar 64
- 0550 Viper V550
- 08d4 Supra 2260 Modem
- 094c SupraExpress 56i Pro
- 1092 Viper V330
- 6120 Maximum DVD
- 8810 Stealth SE
- 8811 Stealth 64/SE
- 8880 Stealth
- 8881 Stealth
- 88b0 Stealth 64
- 88b1 Stealth 64
- 88c0 Stealth 64
- 88c1 Stealth 64
- 88d0 Stealth 64
- 88d1 Stealth 64
- 88f0 Stealth 64
- 88f1 Stealth 64
- 9999 DMD-I0928-1 "Monster sound" sound chip
-1093 National Instruments
- 0160 PCI-DIO-96
- 0162 PCI-MIO-16XE-50
- 1170 PCI-MIO-16XE-10
- 1180 PCI-MIO-16E-1
- 1190 PCI-MIO-16E-4
- 1310 PCI-6602
- 1330 PCI-6031E
- 1350 PCI-6071E
- 14e0 PCI-6110
- 14f0 PCI-6111
- 17d0 PCI-6503
- 1870 PCI-6713
- 1880 PCI-6711
- 18b0 PCI-6052E
- 2410 PCI-6733
- 2890 PCI-6036E
- 2a60 PCI-6023E
- 2a70 PCI-6024E
- 2a80 PCI-6025E
- 2c80 PCI-6035E
- 2ca0 PCI-6034E
- 70b8 PCI-6251 [M Series - High Speed Multifunction DAQ]
- b001 IMAQ-PCI-1408
- b011 IMAQ-PXI-1408
- b021 IMAQ-PCI-1424
- b031 IMAQ-PCI-1413
- b041 IMAQ-PCI-1407
- b051 IMAQ-PXI-1407
- b061 IMAQ-PCI-1411
- b071 IMAQ-PCI-1422
- b081 IMAQ-PXI-1422
- b091 IMAQ-PXI-1411
- c801 PCI-GPIB
- c831 PCI-GPIB bridge
-1094 First International Computers [FIC]
-1095 Silicon Image, Inc. (formerly CMD Technology Inc)
- 0240 Adaptec AAR-1210SA SATA HostRAID Controller
- 0640 PCI0640
- 0643 PCI0643
- 0646 PCI0646
- 0647 PCI0647
- 0648 PCI0648
- 0649 SiI 0649 Ultra ATA/100 PCI to ATA Host Controller
- 0e11 005d Integrated Ultra ATA-100 Dual Channel Controller
- 0e11 007e Integrated Ultra ATA-100 IDE RAID Controller
- 101e 0649 AMI MegaRAID IDE 100 Controller
- 0650 PBC0650A
- 0670 USB0670
- 1095 0670 USB0670
- 0673 USB0673
- 0680 PCI0680 Ultra ATA-133 Host Controller
- 1095 3680 Winic W-680 (Silicon Image 680 based)
- 3112 SiI 3112 [SATALink/SATARaid] Serial ATA Controller
- 1095 3112 SiI 3112 SATALink Controller
- 1095 6112 SiI 3112 SATARaid Controller
- 3114 SiI 3114 [SATALink/SATARaid] Serial ATA Controller
- 1095 3114 SiI 3114 SATALink Controller
- 1095 6114 SiI 3114 SATARaid Controller
- 3124 SiI 3124 PCI-X Serial ATA Controller
- 1095 3124 SiI 3124 PCI-X Serial ATA Controller
- 3512 SiI 3512 [SATALink/SATARaid] Serial ATA Controller
- 1095 3512 SiI 3512 SATALink Controller
- 1095 6512 SiI 3512 SATARaid Controller
-1096 Alacron
-1097 Appian Technology
-1098 Quantum Designs (H.K.) Ltd
- 0001 QD-8500
- 0002 QD-8580
-1099 Samsung Electronics Co., Ltd
-109a Packard Bell
-109b Gemlight Computer Ltd.
-109c Megachips Corporation
-109d Zida Technologies Ltd.
-109e Brooktree Corporation
- 0350 Bt848 Video Capture
- 0351 Bt849A Video capture
- 0369 Bt878 Video Capture
- 1002 0001 TV-Wonder
- 1002 0003 TV-Wonder/VE
- 036c Bt879(??) Video Capture
- 13e9 0070 Win/TV (Video Section)
- 036e Bt878 Video Capture
- 0070 13eb WinTV Series
- 0070 ff01 Viewcast Osprey 200
- 0071 0101 DigiTV PCI
- 107d 6606 WinFast TV 2000
- 11bd 0012 PCTV pro (TV + FM stereo receiver)
- 11bd 001c PCTV Sat (DBC receiver)
- 127a 0001 Bt878 Mediastream Controller NTSC
- 127a 0002 Bt878 Mediastream Controller PAL BG
- 127a 0003 Bt878a Mediastream Controller PAL BG
- 127a 0048 Bt878/832 Mediastream Controller
- 144f 3000 MagicTView CPH060 - Video
- 1461 0002 TV98 Series (TV/No FM/Remote)
- 1461 0003 AverMedia UltraTV PCI 350
- 1461 0004 AVerTV WDM Video Capture
- 1461 0761 AverTV DVB-T
- 14f1 0001 Bt878 Mediastream Controller NTSC
- 14f1 0002 Bt878 Mediastream Controller PAL BG
- 14f1 0003 Bt878a Mediastream Controller PAL BG
- 14f1 0048 Bt878/832 Mediastream Controller
- 1822 0001 VisionPlus DVB card
- 1851 1850 FlyVideo'98 - Video
- 1851 1851 FlyVideo II
- 1852 1852 FlyVideo'98 - Video (with FM Tuner)
- 270f fc00 Digitop DTT-1000
- bd11 1200 PCTV pro (TV + FM stereo receiver)
- 036f Bt879 Video Capture
- 127a 0044 Bt879 Video Capture NTSC
- 127a 0122 Bt879 Video Capture PAL I
- 127a 0144 Bt879 Video Capture NTSC
- 127a 0222 Bt879 Video Capture PAL BG
- 127a 0244 Bt879a Video Capture NTSC
- 127a 0322 Bt879 Video Capture NTSC
- 127a 0422 Bt879 Video Capture NTSC
- 127a 1122 Bt879 Video Capture PAL I
- 127a 1222 Bt879 Video Capture PAL BG
- 127a 1322 Bt879 Video Capture NTSC
- 127a 1522 Bt879a Video Capture PAL I
- 127a 1622 Bt879a Video Capture PAL BG
- 127a 1722 Bt879a Video Capture NTSC
- 14f1 0044 Bt879 Video Capture NTSC
- 14f1 0122 Bt879 Video Capture PAL I
- 14f1 0144 Bt879 Video Capture NTSC
- 14f1 0222 Bt879 Video Capture PAL BG
- 14f1 0244 Bt879a Video Capture NTSC
- 14f1 0322 Bt879 Video Capture NTSC
- 14f1 0422 Bt879 Video Capture NTSC
- 14f1 1122 Bt879 Video Capture PAL I
- 14f1 1222 Bt879 Video Capture PAL BG
- 14f1 1322 Bt879 Video Capture NTSC
- 14f1 1522 Bt879a Video Capture PAL I
- 14f1 1622 Bt879a Video Capture PAL BG
- 14f1 1722 Bt879a Video Capture NTSC
- 1851 1850 FlyVideo'98 - Video
- 1851 1851 FlyVideo II
- 1852 1852 FlyVideo'98 - Video (with FM Tuner)
- 0370 Bt880 Video Capture
- 1851 1850 FlyVideo'98
- 1851 1851 FlyVideo'98 EZ - video
- 1852 1852 FlyVideo'98 (with FM Tuner)
- 0878 Bt878 Audio Capture
- 0070 13eb WinTV Series
- 0070 ff01 Viewcast Osprey 200
- 0071 0101 DigiTV PCI
- 1002 0001 TV-Wonder
- 1002 0003 TV-Wonder/VE
- 11bd 0012 PCTV pro (TV + FM stereo receiver, audio section)
- 11bd 001c PCTV Sat (DBC receiver)
- 127a 0001 Bt878 Video Capture (Audio Section)
- 127a 0002 Bt878 Video Capture (Audio Section)
- 127a 0003 Bt878 Video Capture (Audio Section)
- 127a 0048 Bt878 Video Capture (Audio Section)
- 13e9 0070 Win/TV (Audio Section)
- 144f 3000 MagicTView CPH060 - Audio
- 1461 0004 AVerTV WDM Audio Capture
- 1461 0761 AVerTV DVB-T
- 14f1 0001 Bt878 Video Capture (Audio Section)
- 14f1 0002 Bt878 Video Capture (Audio Section)
- 14f1 0003 Bt878 Video Capture (Audio Section)
- 14f1 0048 Bt878 Video Capture (Audio Section)
- 1822 0001 VisionPlus DVB Card
- 270f fc00 Digitop DTT-1000
- bd11 1200 PCTV pro (TV + FM stereo receiver, audio section)
- 0879 Bt879 Audio Capture
- 127a 0044 Bt879 Video Capture (Audio Section)
- 127a 0122 Bt879 Video Capture (Audio Section)
- 127a 0144 Bt879 Video Capture (Audio Section)
- 127a 0222 Bt879 Video Capture (Audio Section)
- 127a 0244 Bt879 Video Capture (Audio Section)
- 127a 0322 Bt879 Video Capture (Audio Section)
- 127a 0422 Bt879 Video Capture (Audio Section)
- 127a 1122 Bt879 Video Capture (Audio Section)
- 127a 1222 Bt879 Video Capture (Audio Section)
- 127a 1322 Bt879 Video Capture (Audio Section)
- 127a 1522 Bt879 Video Capture (Audio Section)
- 127a 1622 Bt879 Video Capture (Audio Section)
- 127a 1722 Bt879 Video Capture (Audio Section)
- 14f1 0044 Bt879 Video Capture (Audio Section)
- 14f1 0122 Bt879 Video Capture (Audio Section)
- 14f1 0144 Bt879 Video Capture (Audio Section)
- 14f1 0222 Bt879 Video Capture (Audio Section)
- 14f1 0244 Bt879 Video Capture (Audio Section)
- 14f1 0322 Bt879 Video Capture (Audio Section)
- 14f1 0422 Bt879 Video Capture (Audio Section)
- 14f1 1122 Bt879 Video Capture (Audio Section)
- 14f1 1222 Bt879 Video Capture (Audio Section)
- 14f1 1322 Bt879 Video Capture (Audio Section)
- 14f1 1522 Bt879 Video Capture (Audio Section)
- 14f1 1622 Bt879 Video Capture (Audio Section)
- 14f1 1722 Bt879 Video Capture (Audio Section)
- 0880 Bt880 Audio Capture
- 2115 BtV 2115 Mediastream controller
- 2125 BtV 2125 Mediastream controller
- 2164 BtV 2164
- 2165 BtV 2165
- 8230 Bt8230 ATM Segment/Reassembly Ctrlr (SRC)
- 8472 Bt8472
- 8474 Bt8474
-109f Trigem Computer Inc.
-10a0 Meidensha Corporation
-10a1 Juko Electronics Ind. Co. Ltd
-10a2 Quantum Corporation
-10a3 Everex Systems Inc
-10a4 Globe Manufacturing Sales
-10a5 Smart Link Ltd.
- 3052 SmartPCI562 56K Modem
- 5449 SmartPCI561 modem
-10a6 Informtech Industrial Ltd.
-10a7 Benchmarq Microelectronics
-10a8 Sierra Semiconductor
- 0000 STB Horizon 64
-10a9 Silicon Graphics, Inc.
- 0001 Crosstalk to PCI Bridge
- 0002 Linc I/O controller
- 0003 IOC3 I/O controller
- 0004 O2 MACE
- 0005 RAD Audio
- 0006 HPCEX
- 0007 RPCEX
- 0008 DiVO VIP
- 0009 AceNIC Gigabit Ethernet
- 10a9 8002 AceNIC Gigabit Ethernet
- 0010 AMP Video I/O
- 0011 GRIP
- 0012 SGH PSHAC GSN
- 1001 Magic Carpet
- 1002 Lithium
- 1003 Dual JPEG 1
- 1004 Dual JPEG 2
- 1005 Dual JPEG 3
- 1006 Dual JPEG 4
- 1007 Dual JPEG 5
- 1008 Cesium
- 100a IOC4 I/O controller
- 2001 Fibre Channel
- 2002 ASDE
- 8001 O2 1394
- 8002 G-net NT
-10aa ACC Microelectronics
- 0000 ACCM 2188
-10ab Digicom
-10ac Honeywell IAC
-10ad Symphony Labs
- 0001 W83769F
- 0003 SL82C103
- 0005 SL82C105
- 0103 SL82c103
- 0105 SL82c105
- 0565 W83C553
-10ae Cornerstone Technology
-10af Micro Computer Systems Inc
-10b0 CardExpert Technology
-10b1 Cabletron Systems Inc
-10b2 Raytheon Company
-10b3 Databook Inc
- 3106 DB87144
- b106 DB87144
-10b4 STB Systems Inc
- 1b1d Velocity 128 3D
- 10b4 237e Velocity 4400
-10b5 PLX Technology, Inc.
- 0001 i960 PCI bus interface
- 1076 VScom 800 8 port serial adaptor
- 1077 VScom 400 4 port serial adaptor
- 1078 VScom 210 2 port serial and 1 port parallel adaptor
- 1103 VScom 200 2 port serial adaptor
- 1146 VScom 010 1 port parallel adaptor
- 1147 VScom 020 2 port parallel adaptor
- 2724 Thales PCSM Security Card
- 8516 PEX 8516 Versatile PCI Express Switch
- 8532 PEX 8532 Versatile PCI Express Switch
- 9030 PCI <-> IOBus Bridge Hot Swap
- 10b5 2862 Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board
- 10b5 2906 Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board
- 10b5 2940 Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board
- 10b5 3025 Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board
- 10b5 3068 Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board
- 15ed 1002 MCCS 8-port Serial Hot Swap
- 15ed 1003 MCCS 16-port Serial Hot Swap
- 9036 9036
- 9050 PCI <-> IOBus Bridge
- 10b5 1067 IXXAT CAN i165
- 10b5 1172 IK220 (Heidenhain)
- 10b5 2036 SatPak GPS
- 10b5 2221 Alpermann+Velte PCL PCI LV: Timecode Reader Board
- 10b5 2273 SH-ARC SoHard ARCnet card
- 10b5 2431 Alpermann+Velte PCL PCI D: Timecode Reader Board
- 10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board
- 10b5 9050 MP9050
- 1498 0362 TPMC866 8 Channel Serial Card
- 1522 0001 RockForce 4 Port V.90 Data/Fax/Voice Modem
- 1522 0002 RockForce 2 Port V.90 Data/Fax/Voice Modem
- 1522 0003 RockForce 6 Port V.90 Data/Fax/Voice Modem
- 1522 0004 RockForce 8 Port V.90 Data/Fax/Voice Modem
- 1522 0010 RockForce2000 4 Port V.90 Data/Fax/Voice Modem
- 1522 0020 RockForce2000 2 Port V.90 Data/Fax/Voice Modem
- 15ed 1000 Macrolink MCCS 8-port Serial
- 15ed 1001 Macrolink MCCS 16-port Serial
- 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap
- 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap
-# Sorry, there was a typo
- 5654 2036 OpenSwitch 6 Telephony card
-# Sorry, there was a typo
- 5654 3132 OpenSwitch 12 Telephony card
- 5654 5634 OpenLine4 Telephony Card
- d531 c002 PCIntelliCAN 2xSJA1000 CAN bus
- d84d 4006 EX-4006 1P
- d84d 4008 EX-4008 1P EPP/ECP
- d84d 4014 EX-4014 2P
- d84d 4018 EX-4018 3P EPP/ECP
- d84d 4025 EX-4025 1S(16C550) RS-232
- d84d 4027 EX-4027 1S(16C650) RS-232
- d84d 4028 EX-4028 1S(16C850) RS-232
- d84d 4036 EX-4036 2S(16C650) RS-232
- d84d 4037 EX-4037 2S(16C650) RS-232
- d84d 4038 EX-4038 2S(16C850) RS-232
- d84d 4052 EX-4052 1S(16C550) RS-422/485
- d84d 4053 EX-4053 2S(16C550) RS-422/485
- d84d 4055 EX-4055 4S(16C550) RS-232
- d84d 4058 EX-4055 4S(16C650) RS-232
- d84d 4065 EX-4065 8S(16C550) RS-232
- d84d 4068 EX-4068 8S(16C650) RS-232
- d84d 4078 EX-4078 2S(16C552) RS-232+1P
- 9054 PCI <-> IOBus Bridge
- 10b5 2455 Wessex Techology PHIL-PCI
- 10b5 2696 Innes Corp AM Radcap card
- 10b5 2717 Innes Corp Auricon card
- 10b5 2844 Innes Corp TVS Encoder card
- 12d9 0002 PCI Prosody Card rev 1.5
- 16df 0011 PIKA PrimeNet MM PCI
- 16df 0012 PIKA PrimeNet MM cPCI 8
- 16df 0013 PIKA PrimeNet MM cPCI 8 (without CAS Signaling Option)
- 16df 0014 PIKA PrimeNet MM cPCI 4
- 16df 0015 PIKA Daytona MM
- 16df 0016 PIKA InLine MM
- 9056 Francois
- 10b5 2979 CellinkBlade 11 - CPCI board VoATM AAL1
- 9060 9060
- 906d 9060SD
- 125c 0640 Aries 16000P
- 906e 9060ES
- 9080 9080
- 103c 10eb (Agilent) E2777B 83K Series PCI based Optical Communication Interface
- 103c 10ec (Agilent) E6978-66442 PCI CIC
- 10b5 9080 9080 [real subsystem ID not set]
- 129d 0002 Aculab PCI Prosidy card
- 12d9 0002 PCI Prosody Card
- 12df 4422 4422PCI ["Do-All" Telemetry Data Aquisition System]
- bb04 B&B 3PCIOSD1A Isolated PCI Serial
-10b6 Madge Networks
- 0001 Smart 16/4 PCI Ringnode
- 0002 Smart 16/4 PCI Ringnode Mk2
- 10b6 0002 Smart 16/4 PCI Ringnode Mk2
- 10b6 0006 16/4 CardBus Adapter
- 0003 Smart 16/4 PCI Ringnode Mk3
- 0e11 b0fd Compaq NC4621 PCI, 4/16, WOL
- 10b6 0003 Smart 16/4 PCI Ringnode Mk3
- 10b6 0007 Presto PCI Plus Adapter
- 0004 Smart 16/4 PCI Ringnode Mk1
- 0006 16/4 Cardbus Adapter
- 10b6 0006 16/4 CardBus Adapter
- 0007 Presto PCI Adapter
- 10b6 0007 Presto PCI
- 0009 Smart 100/16/4 PCI-HS Ringnode
- 10b6 0009 Smart 100/16/4 PCI-HS Ringnode
- 000a Smart 100/16/4 PCI Ringnode
- 10b6 000a Smart 100/16/4 PCI Ringnode
- 000b 16/4 CardBus Adapter Mk2
- 10b6 0008 16/4 CardBus Adapter Mk2
- 10b6 000b 16/4 Cardbus Adapter Mk2
- 000c RapidFire 3140V2 16/4 TR Adapter
- 10b6 000c RapidFire 3140V2 16/4 TR Adapter
- 1000 Collage 25/155 ATM Client Adapter
- 1001 Collage 155 ATM Server Adapter
-10b7 3Com Corporation
- 0001 3c985 1000BaseSX (SX/TX)
- 0013 AR5212 802.11abg NIC (3CRDAG675)
- 10b7 2031 3CRDAG675 11a/b/g Wireless PCI Adapter
- 0910 3C910-A01
- 1006 MINI PCI type 3B Data Fax Modem
- 1007 Mini PCI 56k Winmodem
- 10b7 615c Mini PCI 56K Modem
- 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra]
- 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra]
- 1700 3c940 10/100/1000Base-T [Marvell]
- 1043 80eb P4P800/K8V Deluxe motherboard
- 10b7 0010 3C940 Gigabit LOM Ethernet Adapter
- 10b7 0020 3C941 Gigabit LOM Ethernet Adapter
- 147b 1407 KV8-MAX3 motherboard
- 3390 3c339 TokenLink Velocity
- 3590 3c359 TokenLink Velocity XL
- 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B)
- 4500 3c450 HomePNA [Tornado]
- 5055 3c555 Laptop Hurricane
- 5057 3c575 Megahertz 10/100 LAN CardBus [Boomerang]
- 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5157 3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone]
- 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5257 3cCFE575CT CardBus [Cyclone]
- 10b7 5c57 FE575C-3Com 10/100 LAN CardBus-Fast Ethernet
- 5900 3c590 10BaseT [Vortex]
- 5920 3c592 EISA 10mbps Demon/Vortex
- 5950 3c595 100BaseTX [Vortex]
- 5951 3c595 100BaseT4 [Vortex]
- 5952 3c595 100Base-MII [Vortex]
- 5970 3c597 EISA Fast Demon/Vortex
- 5b57 3c595 Megahertz 10/100 LAN CardBus [Boomerang]
- 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 6000 3CRSHPW796 [OfficeConnect Wireless CardBus]
- 6001 3com 3CRWE154G72 [Office Connect Wireless LAN Adapter]
- 6055 3c556 Hurricane CardBus [Cyclone]
- 6056 3c556B CardBus [Tornado]
- 10b7 6556 10/100 Mini PCI Ethernet Adapter
- 6560 3cCFE656 CardBus [Cyclone]
- 10b7 656a 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6561 3cCFEM656 10/100 LAN+56K Modem CardBus
- 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6562 3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone]
- 10b7 656b 3CCFEM656B 10/100 LAN+56K Modem CardBus
- 6563 3cCFEM656B 10/100 LAN+56K Modem CardBus
- 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus
- 6564 3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado]
- 7646 3cSOHO100-TX Hurricane
- 7770 3CRWE777 PCI(PLX) Wireless Adaptor [Airconnect]
- 7940 3c803 FDDILink UTP Controller
- 7980 3c804 FDDILink SAS Controller
- 7990 3c805 FDDILink DAS Controller
- 80eb 3c940B 10/100/1000Base-T
- 8811 Token ring
- 9000 3c900 10BaseT [Boomerang]
- 9001 3c900 10Mbps Combo [Boomerang]
- 9004 3c900B-TPO Etherlink XL [Cyclone]
- 10b7 9004 3C900B-TPO Etherlink XL TPO 10Mb
- 9005 3c900B-Combo Etherlink XL [Cyclone]
- 10b7 9005 3C900B-Combo Etherlink XL Combo
- 9006 3c900B-TPC Etherlink XL [Cyclone]
- 900a 3c900B-FL 10base-FL [Cyclone]
- 9050 3c905 100BaseTX [Boomerang]
- 9051 3c905 100BaseT4 [Boomerang]
- 9055 3c905B 100BaseTX [Cyclone]
- 1028 0080 3C905B Fast Etherlink XL 10/100
- 1028 0081 3C905B Fast Etherlink XL 10/100
- 1028 0082 3C905B Fast Etherlink XL 10/100
- 1028 0083 3C905B Fast Etherlink XL 10/100
- 1028 0084 3C905B Fast Etherlink XL 10/100
- 1028 0085 3C905B Fast Etherlink XL 10/100
- 1028 0086 3C905B Fast Etherlink XL 10/100
- 1028 0087 3C905B Fast Etherlink XL 10/100
- 1028 0088 3C905B Fast Etherlink XL 10/100
- 1028 0089 3C905B Fast Etherlink XL 10/100
- 1028 0090 3C905B Fast Etherlink XL 10/100
- 1028 0091 3C905B Fast Etherlink XL 10/100
- 1028 0092 3C905B Fast Etherlink XL 10/100
- 1028 0093 3C905B Fast Etherlink XL 10/100
- 1028 0094 3C905B Fast Etherlink XL 10/100
- 1028 0095 3C905B Fast Etherlink XL 10/100
- 1028 0096 3C905B Fast Etherlink XL 10/100
- 1028 0097 3C905B Fast Etherlink XL 10/100
- 1028 0098 3C905B Fast Etherlink XL 10/100
- 1028 0099 3C905B Fast Etherlink XL 10/100
- 10b7 9055 3C905B Fast Etherlink XL 10/100
- 9056 3c905B-T4 Fast EtherLink XL [Cyclone]
- 9058 3c905B Deluxe Etherlink 10/100/BNC [Cyclone]
- 905a 3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone]
- 9200 3c905C-TX/TX-M [Tornado]
- 1028 0095 3C920 Integrated Fast Ethernet Controller
- 1028 0097 3C920 Integrated Fast Ethernet Controller
- 1028 00fe Optiplex GX240
- 1028 012a 3C920 Integrated Fast Ethernet Controller [Latitude C640]
- 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC
- 10b7 7000 10/100 Mini PCI Ethernet Adapter
- 10f1 2466 Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)
- 9201 3C920B-EMB Integrated Fast Ethernet Controller [Tornado]
- 1043 80ab A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller
- 9202 3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller
- 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller
- 9300 3CSOHO100B-TX 910-A01 [tulip]
- 9800 3c980-TX Fast Etherlink XL Server Adapter [Cyclone]
- 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter
- 9805 3c980-C 10/100baseTX NIC [Python-T]
- 10b7 1201 EtherLink Server 10/100 Dual Port A
- 10b7 1202 EtherLink Server 10/100 Dual Port B
- 10b7 9805 3c980 10/100baseTX NIC [Python-T]
- 10f1 2462 Thunder K7 S2462
- 9900 3C990-TX [Typhoon]
- 9902 3CR990-TX-95 [Typhoon 56-bit]
- 9903 3CR990-TX-97 [Typhoon 168-bit]
- 9904 3C990B-TX-M/3C990BSVR [Typhoon2]
- 10b7 1000 3CR990B-TX-M [Typhoon2]
- 10b7 2000 3CR990BSVR [Typhoon2 Server]
- 9905 3CR990-FX-95/97/95 [Typhon Fiber]
- 10b7 1101 3CR990-FX-95 [Typhoon Fiber 56-bit]
- 10b7 1102 3CR990-FX-97 [Typhoon Fiber 168-bit]
- 10b7 2101 3CR990-FX-95 Server [Typhoon Fiber 56-bit]
- 10b7 2102 3CR990-FX-97 Server [Typhoon Fiber 168-bit]
- 9908 3CR990SVR95 [Typhoon Server 56-bit]
- 9909 3CR990SVR97 [Typhoon Server 168-bit]
- 990a 3C990SVR [Typhoon Server]
- 990b 3C990SVR [Typhoon Server]
-10b8 Standard Microsystems Corp [SMC]
- 0005 83c170 EPIC/100 Fast Ethernet Adapter
- 1055 e000 LANEPIC 10/100 [EVB171Q-PCI]
- 1055 e002 LANEPIC 10/100 [EVB171G-PCI]
- 10b8 a011 EtherPower II 10/100
- 10b8 a014 EtherPower II 10/100
- 10b8 a015 EtherPower II 10/100
- 10b8 a016 EtherPower II 10/100
- 10b8 a017 EtherPower II 10/100
- 0006 83c175 EPIC/100 Fast Ethernet Adapter
- 1055 e100 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e102 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e300 LANEPIC Cardbus Fast Ethernet Adapter
- 1055 e302 LANEPIC Cardbus Fast Ethernet Adapter
- 10b8 a012 LANEPIC Cardbus Fast Ethernet Adapter
- 13a2 8002 LANEPIC Cardbus Fast Ethernet Adapter
- 13a2 8006 LANEPIC Cardbus Fast Ethernet Adapter
- 1000 FDC 37c665
- 1001 FDC 37C922
-# 802.11g card
- 2802 SMC2802W [EZ Connect g]
- a011 83C170QF
- b106 SMC34C90
-10b9 ALi Corporation
- 0101 CMI8338/C3DX PCI Audio Device
- 0111 C-Media CMI8738/C3DX Audio Device (OEM)
- 10b9 0111 C-Media CMI8738/C3DX Audio Device (OEM)
- 0780 Multi-IO Card
- 0782 Multi-IO Card
- 1435 M1435
- 1445 M1445
- 1449 M1449
- 1451 M1451
- 1461 M1461
- 1489 M1489
- 1511 M1511 [Aladdin]
- 1512 M1512 [Aladdin]
- 1513 M1513 [Aladdin]
- 1521 M1521 [Aladdin III]
- 10b9 1521 ALI M1521 Aladdin III CPU Bridge
- 1523 M1523
- 10b9 1523 ALI M1523 ISA Bridge
- 1531 M1531 [Aladdin IV]
- 1533 M1533 PCI to ISA Bridge [Aladdin IV]
- 1014 053b ThinkPad R40e (2684-HVG) PCI to ISA Bridge
- 10b9 1533 ALI M1533 Aladdin IV ISA Bridge
- 1541 M1541
- 10b9 1541 ALI M1541 Aladdin V/V+ AGP System Controller
- 1543 M1543
- 1563 M1563 HyperTransport South Bridge
- 1621 M1621
- 1631 ALI M1631 PCI North Bridge Aladdin Pro III
- 1632 M1632M Northbridge+Trident
- 1641 ALI M1641 PCI North Bridge Aladdin Pro IV
- 1644 M1644/M1644T Northbridge+Trident
- 1646 M1646 Northbridge+Trident
- 1647 M1647 Northbridge [MAGiK 1 / MobileMAGiK 1]
- 1651 M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM]
- 1671 M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR]
- 1672 M1672 Northbridge [CyberALADDiN-P4]
- 1681 M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR]
- 1687 M1687 K8 Northbridge [AGP8X and HyperTransport]
- 1689 M1689 K8 Northbridge [Super K8 Single Chip]
- 3141 M3141
- 3143 M3143
- 3145 M3145
- 3147 M3147
- 3149 M3149
- 3151 M3151
- 3307 M3307
- 3309 M3309
- 3323 M3325 Video/Audio Decoder
- 5212 M4803
- 5215 MS4803
- 5217 M5217H
- 5219 M5219
- 5225 M5225
- 5228 M5228 ALi ATA/RAID Controller
- 5229 M5229 IDE
- 1014 050f ThinkPad R30
- 1014 053d ThinkPad R40e (2684-HVG) builtin IDE
- 103c 0024 Pavilion ze4400 builtin IDE
- 1043 8053 A7A266 Motherboard IDE
- 5235 M5225
- 5237 USB 1.1 Controller
- 1014 0540 ThinkPad R40e (2684-HVG) builtin USB
- 103c 0024 Pavilion ze4400 builtin USB
- 5239 USB 2.0 Controller
- 5243 M1541 PCI to AGP Controller
- 5246 AGP8X Controller
- 5247 PCI to AGP Controller
- 5249 M5249 HTT to PCI Bridge
- 5251 M5251 P1394 OHCI 1.0 Controller
- 5253 M5253 P1394 OHCI 1.1 Controller
- 5261 M5261 Ethernet Controller
- 5263 M5263 Ethernet Controller
- 5281 ALi M5281 Serial ATA / RAID Host Controller
- 5287 ULi 5287 SATA
- 5289 ULi 5289 SATA
- 5450 Lucent Technologies Soft Modem AMR
- 5451 M5451 PCI AC-Link Controller Audio Device
- 1014 0506 ThinkPad R30
- 1014 053e ThinkPad R40e (2684-HVG) builtin Audio
- 103c 0024 Pavilion ze4400 builtin Audio
- 10b9 5451 HP Compaq nc4010 (DY885AA#ABN)
- 5453 M5453 PCI AC-Link Controller Modem Device
- 5455 M5455 PCI AC-Link Controller Audio Device
- 5457 M5457 AC'97 Modem Controller
- 1014 0535 ThinkPad R40e (2684-HVG) builtin modem
- 103c 0024 Pavilion ze4400 builtin Modem Device
-# Same but more usefull for driver's lookup
- 5459 SmartLink SmartPCI561 56K Modem
-# SmartLink PCI SoftModem
- 545a SmartLink SmartPCI563 56K Modem
- 5471 M5471 Memory Stick Controller
- 5473 M5473 SD-MMC Controller
- 7101 M7101 Power Management Controller [PMU]
- 1014 0510 ThinkPad R30
- 1014 053c ThinkPad R40e (2684-HVG) Power Management Controller
- 103c 0024 Pavilion ze4400
-10ba Mitsubishi Electric Corp.
- 0301 AccelGraphics AccelECLIPSE
- 0304 AccelGALAXY A2100 [OEM Evans & Sutherland]
- 0308 Tornado 3000 [OEM Evans & Sutherland]
- 1002 VG500 [VolumePro Volume Rendering Accelerator]
-10bb Dapha Electronics Corporation
-10bc Advanced Logic Research
-10bd Surecom Technology
- 0e34 NE-34
-10be Tseng Labs International Co.
-10bf Most Inc
-10c0 Boca Research Inc.
-10c1 ICM Co., Ltd.
-10c2 Auspex Systems Inc.
-10c3 Samsung Semiconductors, Inc.
- 1100 Smartether100 SC1100 LAN Adapter (i82557B)
-10c4 Award Software International Inc.
-10c5 Xerox Corporation
-10c6 Rambus Inc.
-10c7 Media Vision
-10c8 Neomagic Corporation
- 0001 NM2070 [MagicGraph 128]
- 0002 NM2090 [MagicGraph 128V]
- 0003 NM2093 [MagicGraph 128ZV]
- 0004 NM2160 [MagicGraph 128XD]
- 1014 00ba MagicGraph 128XD
- 1025 1007 MagicGraph 128XD
- 1028 0074 MagicGraph 128XD
- 1028 0075 MagicGraph 128XD
- 1028 007d MagicGraph 128XD
- 1028 007e MagicGraph 128XD
- 1033 802f MagicGraph 128XD
- 104d 801b MagicGraph 128XD
- 104d 802f MagicGraph 128XD
- 104d 830b MagicGraph 128XD
- 10ba 0e00 MagicGraph 128XD
- 10c8 0004 MagicGraph 128XD
- 10cf 1029 MagicGraph 128XD
- 10f7 8308 MagicGraph 128XD
- 10f7 8309 MagicGraph 128XD
- 10f7 830b MagicGraph 128XD
- 10f7 830d MagicGraph 128XD
- 10f7 8312 MagicGraph 128XD
- 0005 NM2200 [MagicGraph 256AV]
- 1014 00dd ThinkPad 570
- 1028 0088 Latitude CPi A
- 0006 NM2360 [MagicMedia 256ZX]
- 0016 NM2380 [MagicMedia 256XL+]
- 10c8 0016 MagicMedia 256XL+
- 0025 NM2230 [MagicGraph 256AV+]
- 0083 NM2093 [MagicGraph 128ZV+]
- 8005 NM2200 [MagicMedia 256AV Audio]
- 0e11 b0d1 MagicMedia 256AV Audio Device on Discovery
- 0e11 b126 MagicMedia 256AV Audio Device on Durango
- 1014 00dd MagicMedia 256AV Audio Device on BlackTip Thinkpad
- 1025 1003 MagicMedia 256AV Audio Device on TravelMate 720
- 1028 0088 Latitude CPi A
- 1028 008f MagicMedia 256AV Audio Device on Colorado Inspiron
- 103c 0007 MagicMedia 256AV Audio Device on Voyager II
- 103c 0008 MagicMedia 256AV Audio Device on Voyager III
- 103c 000d MagicMedia 256AV Audio Device on Omnibook 900
- 10c8 8005 MagicMedia 256AV Audio Device on FireAnt
- 110a 8005 MagicMedia 256AV Audio Device
- 14c0 0004 MagicMedia 256AV Audio Device
- 8006 NM2360 [MagicMedia 256ZX Audio]
- 8016 NM2380 [MagicMedia 256XL+ Audio]
-10c9 Dataexpert Corporation
-10ca Fujitsu Microelectr., Inc.
-10cb Omron Corporation
-# nee Mentor ARC Inc
-10cc Mai Logic Incorporated
- 0660 Articia S Host Bridge
- 0661 Articia S PCI Bridge
-10cd Advanced System Products, Inc
- 1100 ASC1100
- 1200 ASC1200 [(abp940) Fast SCSI-II]
- 1300 ABP940-U / ABP960-U
- 10cd 1310 ASC1300 SCSI Adapter
- 2300 ABP940-UW
- 2500 ABP940-U2W
-10ce Radius
-# nee Citicorp TTI
-10cf Fujitsu Limited.
- 2001 mb86605
-10d1 FuturePlus Systems Corp.
-10d2 Molex Incorporated
-10d3 Jabil Circuit Inc
-10d4 Hualon Microelectronics
-10d5 Autologic Inc.
-10d6 Cetia
-10d7 BCM Advanced Research
-10d8 Advanced Peripherals Labs
-10d9 Macronix, Inc. [MXIC]
- 0431 MX98715
- 0512 MX98713
- 0531 MX987x5
- 1186 1200 DFE-540TX ProFAST 10/100 Adapter
- 8625 MX86250
- 8888 MX86200
-10da Compaq IPG-Austin
- 0508 TC4048 Token Ring 4/16
- 3390 Tl3c3x9
-10db Rohm LSI Systems, Inc.
-10dc CERN/ECP/EDU
- 0001 STAR/RD24 SCI-PCI (PMC)
- 0002 TAR/RD24 SCI-PCI (PMC)
- 0021 HIPPI destination
- 0022 HIPPI source
- 10dc ATT2C15-3 FPGA
-10dd Evans & Sutherland
-10de nVidia Corporation
- 0008 NV1 [EDGE 3D]
- 0009 NV1 [EDGE 3D]
- 0010 NV2 [Mutara V08]
- 0020 NV4 [RIVA TNT]
- 1043 0200 V3400 TNT
- 1048 0c18 Erazor II SGRAM
- 1048 0c1b Erazor II
- 1092 0550 Viper V550
- 1092 0552 Viper V550
- 1092 4804 Viper V550
- 1092 4808 Viper V550
- 1092 4810 Viper V550
- 1092 4812 Viper V550
- 1092 4815 Viper V550
- 1092 4820 Viper V550 with TV out
- 1092 4822 Viper V550
- 1092 4904 Viper V550
- 1092 4914 Viper V550
- 1092 8225 Viper V550
- 10b4 273d Velocity 4400
- 10b4 273e Velocity 4400
- 10b4 2740 Velocity 4400
- 10de 0020 Riva TNT
- 1102 1015 Graphics Blaster CT6710
- 1102 1016 Graphics Blaster RIVA TNT
- 0028 NV5 [RIVA TNT2/TNT2 Pro]
- 1043 0200 AGP-V3800 SGRAM
- 1043 0201 AGP-V3800 SDRAM
- 1043 0205 PCI-V3800
- 1043 4000 AGP-V3800PRO
- 1048 0c21 Synergy II
- 1048 0c31 Erazor III
- 107d 2134 WinFast 3D S320 II + TV-Out
- 1092 4804 Viper V770
- 1092 4a00 Viper V770
- 1092 4a02 Viper V770 Ultra
- 1092 5a00 RIVA TNT2/TNT2 Pro
- 1092 6a02 Viper V770 Ultra
- 1092 7a02 Viper V770 Ultra
- 10de 0005 RIVA TNT2 Pro
- 10de 000f Compaq NVIDIA TNT2 Pro
- 1102 1020 3D Blaster RIVA TNT2
- 1102 1026 3D Blaster RIVA TNT2 Digital
- 14af 5810 Maxi Gamer Xentor
- 0029 NV5 [RIVA TNT2 Ultra]
- 1043 0200 AGP-V3800 Deluxe
- 1043 0201 AGP-V3800 Ultra SDRAM
- 1043 0205 PCI-V3800 Ultra
- 1102 1021 3D Blaster RIVA TNT2 Ultra
- 1102 1029 3D Blaster RIVA TNT2 Ultra
- 1102 102f 3D Blaster RIVA TNT2 Ultra
- 14af 5820 Maxi Gamer Xentor 32
- 002a NV5 [Riva TnT2]
- 002b NV5 [Riva TnT2]
- 002c NV6 [Vanta/Vanta LT]
- 1043 0200 AGP-V3800 Combat SDRAM
- 1043 0201 AGP-V3800 Combat
- 1092 6820 Viper V730
- 1102 1031 CT6938 VANTA 8MB
- 1102 1034 CT6894 VANTA 16MB
- 14af 5008 Maxi Gamer Phoenix 2
- 002d NV5M64 [RIVA TNT2 Model 64/Model 64 Pro]
- 1043 0200 AGP-V3800M
- 1043 0201 AGP-V3800M
- 1048 0c3a Erazor III LT
- 10de 001e M64 AGP4x
- 1102 1023 CT6892 RIVA TNT2 Value
- 1102 1024 CT6932 RIVA TNT2 Value 32Mb
- 1102 102c CT6931 RIVA TNT2 Value [Jumper]
- 1462 8808 MSI-8808
- 1554 1041 Pixelview RIVA TNT2 M64
- 1569 002d Palit Microsystems Daytona TNT2 M64
- 002e NV6 [Vanta]
- 002f NV6 [Vanta]
- 0034 MCP04 SMBus
- 0035 MCP04 IDE
- 0036 MCP04 Serial ATA Controller
- 0037 MCP04 Ethernet Controller
- 0038 MCP04 Ethernet Controller
- 003a MCP04 AC'97 Audio Controller
- 003b MCP04 USB Controller
- 003c MCP04 USB Controller
- 003d MCP04 PCI Bridge
- 003e MCP04 Serial ATA Controller
- 0040 nv40 [GeForce 6800 Ultra]
- 0041 NV40 [GeForce 6800]
- 0042 NV40.2
- 0043 NV40.3
- 0045 NV40 [GeForce 6800 GT]
- 0049 NV40GL
- 004e NV40GL [Quadro FX 4000]
- 0051 CK804 ISA Bridge
- 0052 CK804 SMBus
- 0053 CK804 IDE
- 0054 CK804 Serial ATA Controller
- 0055 CK804 Serial ATA Controller
- 0056 CK804 Ethernet Controller
- 0057 CK804 Ethernet Controller
- 0059 CK804 AC'97 Audio Controller
- 005a CK804 USB Controller
- 005b CK804 USB Controller
- 005c CK804 PCI Bridge
- 005d CK804 PCIE Bridge
- 005e CK804 Memory Controller
- 0060 nForce2 ISA Bridge
- 1043 80ad A7N8X Mainboard
- 0064 nForce2 SMBus (MCP)
- 0065 nForce2 IDE
- 0066 nForce2 Ethernet Controller
- 1043 80a7 A7N8X Mainboard onboard nForce2 Ethernet
- 0067 nForce2 USB Controller
- 1043 0c11 A7N8X Mainboard
- 0068 nForce2 USB Controller
- 1043 0c11 A7N8X Mainboard
- 006a nForce2 AC97 Audio Controler (MCP)
- 006b nForce Audio Processing Unit
- 10de 006b nForce2 MCP Audio Processing Unit
- 006c nForce2 External PCI Bridge
- 006d nForce2 PCI Bridge
- 006e nForce2 FireWire (IEEE 1394) Controller
- 0084 MCP2A SMBus
- 0085 MCP2A IDE
- 0086 MCP2A Ethernet Controller
- 0087 MCP2A USB Controller
- 0088 MCP2A USB Controller
- 008a MCP2S AC'97 Audio Controller
- 008b MCP2A PCI Bridge
- 008c MCP2A Ethernet Controller
- 008e nForce2 Serial ATA Controller
- 00a0 NV5 [Aladdin TNT2]
- 14af 5810 Maxi Gamer Xentor
- 00c0 NV41.0
- 00c1 NV41.1
- 00c2 NV41.2
- 00c8 NV41.8
- 00ce NV41GL
- 00d0 nForce3 LPC Bridge
- 00d1 nForce3 Host Bridge
- 00d2 nForce3 AGP Bridge
- 00d3 CK804 Memory Controller
- 00d4 nForce3 SMBus
- 00d5 nForce3 IDE
- 00d6 nForce3 Ethernet
- 00d7 nForce3 USB 1.1
- 00d8 nForce3 USB 2.0
- 00da nForce3 Audio
- 00dd nForce3 PCI Bridge
- 00df CK8S Ethernet Controller
- 00e0 nForce3 250Gb LPC Bridge
- 00e1 nForce3 250Gb Host Bridge
- 00e2 nForce3 250Gb AGP Host to PCI Bridge
- 00e3 CK8S Serial ATA Controller (v2.5)
- 00e4 nForce 250Gb PCI System Management
- 00e5 CK8S Parallel ATA Controller (v2.5)
- 00e6 CK8S Ethernet Controller
- 00e7 CK8S USB Controller
- 00e8 nForce3 EHCI USB 2.0 Controller
- 00ea nForce3 250Gb AC'97 Audio Controller
- 00ed nForce3 250Gb PCI-to-PCI Bridge
- 00ee CK8S Serial ATA Controller (v2.5)
- 00f0 NV40 [GeForce 6800/GeForce 6800 Ultra]
- 00f1 NV43 [GeForce 6600/GeForce 6600 GT]
- 00f2 NV43 [GeForce 6600 GT]
- 00f8 NV45GL [Quadro FX 3400]
- 00f9 NV40 [GeForce 6800 Ultra/GeForce 6800 GT]
- 1682 2120 GEFORCE 6800 GT PCI-E
- 00fa NV36 [GeForce PCX 5750]
- 00fb NV35 [GeForce PCX 5900]
- 00fc NV37GL [Quadro FX 330/GeForce PCX 5300]
- 00fd NV37GL [Quadro FX 330]
- 00fe NV38GL [Quadro FX 1300]
- 00ff NV18 [GeForce PCX 4300]
- 0100 NV10 [GeForce 256 SDR]
- 1043 0200 AGP-V6600 SGRAM
- 1043 0201 AGP-V6600 SDRAM
- 1043 4008 AGP-V6600 SGRAM
- 1043 4009 AGP-V6600 SDRAM
- 1102 102d CT6941 GeForce 256
- 14af 5022 3D Prophet SE
- 0101 NV10DDR [GeForce 256 DDR]
- 1043 0202 AGP-V6800 DDR
- 1043 400a AGP-V6800 DDR SGRAM
- 1043 400b AGP-V6800 DDR SDRAM
- 107d 2822 WinFast GeForce 256
- 1102 102e CT6971 GeForce 256 DDR
- 14af 5021 3D Prophet DDR-DVI
- 0103 NV10GL [Quadro]
- 0110 NV11 [GeForce2 MX/MX 400]
- 1043 4015 AGP-V7100 Pro
- 1043 4031 V7100 Pro with TV output
- 10de 0091 Dell OEM GeForce 2 MX 400
- 1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817]
- 14af 7102 3D Prophet II MX
- 14af 7103 3D Prophet II MX Dual-Display
- 0111 NV11DDR [GeForce2 MX 100 DDR/200 DDR]
- 0112 NV11 [GeForce2 Go]
- 0113 NV11GL [Quadro2 MXR/EX]
- 0140 NV43 [MSI NX6600GT-TD128E]
- 014f NV43 [GeForce 6200]
- 0150 NV15 [GeForce2 GTS/Pro]
- 1043 4016 V7700 AGP Video Card
- 107d 2840 WinFast GeForce2 GTS with TV output
- 107d 2842 WinFast GeForce 2 Pro
- 1462 8831 Creative GeForce2 Pro
- 0151 NV15DDR [GeForce2 Ti]
- 1043 405f V7700Ti
- 1462 5506 Creative 3D Blaster Geforce2 Titanium
- 0152 NV15BR [GeForce2 Ultra, Bladerunner]
- 1048 0c56 GLADIAC Ultra
- 0153 NV15GL [Quadro2 Pro]
- 0170 NV17 [GeForce4 MX 460]
- 0171 NV17 [GeForce4 MX 440]
- 10b0 0002 Gainward Pro/600 TV
- 1462 8661 G4MX440-VTP
- 1462 8730 MX440SES-T (MS-8873)
- 147b 8f00 Abit Siluro GeForce4MX440
- 0172 NV17 [GeForce4 MX 420]
- 0173 NV17 [GeForce4 MX 440-SE]
- 0174 NV17 [GeForce4 440 Go]
- 0175 NV17 [GeForce4 420 Go]
- 0176 NV17 [GeForce4 420 Go 32M]
- 4c53 1090 Cx9 / Vx9 mainboard
- 0177 NV17 [GeForce4 460 Go]
- 0178 NV17GL [Quadro4 550 XGL]
- 0179 NV17 [GeForce4 440 Go 64M]
- 10de 0179 GeForce4 MX (Mac)
- 017a NV17GL [Quadro4 200/400 NVS]
- 017b NV17GL [Quadro4 550 XGL]
- 017c NV17GL [Quadro4 550 GoGL]
- 017d NV17 [GeForce4 410 Go 16M]
- 0181 NV18 [GeForce4 MX 440 AGP 8x]
- 1043 806f V9180 Magic
- 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X
- 1462 8900 MS-8890 GeForce 4 MX440 AGP8X
- 1462 9350 MSI Geforce4 MX T8X with AGP8X
- 147b 8f0d Siluro GF4 MX-8X
- 0182 NV18 [GeForce4 MX 440SE AGP 8x]
- 0183 NV18 [GeForce4 MX 420 AGP 8x]
- 0185 NV18 [GeForce4 MX 4000 AGP 8x]
- 0186 NV18M [GeForce4 448 Go]
- 0187 NV18M [GeForce4 488 Go]
- 0188 NV18GL [Quadro4 580 XGL]
- 018a NV18GL [Quadro4 NVS AGP 8x]
- 018b NV18GL [Quadro4 380 XGL]
- 018d NV18M [GeForce4 448 Go]
- 01a0 NVCrush11 [GeForce2 MX Integrated Graphics]
- 01a4 nForce CPU bridge
- 01ab nForce 420 Memory Controller (DDR)
- 01ac nForce 220/420 Memory Controller
- 01ad nForce 220/420 Memory Controller
- 01b0 nForce Audio
- 01b1 nForce Audio
- 01b2 nForce ISA Bridge
- 01b4 nForce PCI System Management
- 01b7 nForce AGP to PCI Bridge
- 01b8 nForce PCI-to-PCI bridge
- 01bc nForce IDE
- 01c1 nForce AC'97 Modem Controller
- 01c2 nForce USB Controller
- 01c3 nForce Ethernet Controller
- 01e0 nForce2 AGP (different version?)
- 01e8 nForce2 AGP
- 01ea nForce2 Memory Controller 0
- 01eb nForce2 Memory Controller 1
- 01ec nForce2 Memory Controller 2
- 01ed nForce2 Memory Controller 3
- 01ee nForce2 Memory Controller 4
- 01ef nForce2 Memory Controller 5
- 01f0 NV18 [GeForce4 MX - nForce GPU]
- 0200 NV20 [GeForce3]
- 1043 402f AGP-V8200 DDR
- 0201 NV20 [GeForce3 Ti 200]
- 0202 NV20 [GeForce3 Ti 500]
- 1043 405b V8200 T5
- 1545 002f Xtasy 6964
- 0203 NV20DCC [Quadro DCC]
- 0240 C51 PCI Express Bridge
- 0241 C51 PCI Express Bridge
- 0242 C51 PCI Express Bridge
- 0243 C51 PCI Express Bridge
- 0244 C51 PCI Express Bridge
- 0245 C51 PCI Express Bridge
- 0246 C51 PCI Express Bridge
- 0247 C51 PCI Express Bridge
- 0248 C51 PCI Express Bridge
- 0249 C51 PCI Express Bridge
- 024a C51 PCI Express Bridge
- 024b C51 PCI Express Bridge
- 024c C51 PCI Express Bridge
- 024d C51 PCI Express Bridge
- 024e C51 PCI Express Bridge
- 024f C51 PCI Express Bridge
- 0250 NV25 [GeForce4 Ti 4600]
- 0251 NV25 [GeForce4 Ti 4400]
- 1043 8023 v8440 GeForce 4 Ti4400
- 0252 NV25 [GeForce4 Ti]
- 0253 NV25 [GeForce4 Ti 4200]
- 107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI)
- 147b 8f09 Siluro (Dual VGA/TV-out/DVI)
- 0258 NV25GL [Quadro4 900 XGL]
- 0259 NV25GL [Quadro4 750 XGL]
- 025b NV25GL [Quadro4 700 XGL]
- 0260 MCP51 LPC Bridge
- 0261 MCP51 LPC Bridge
- 0262 MCP51 LPC Bridge
- 0263 MCP51 LPC Bridge
- 0264 MCP51 SMBus
- 0265 MCP51 IDE
- 0266 MCP51 Serial ATA Controller
- 0267 MCP51 Serial ATA Controller
- 0268 MCP51 Ethernet Controller
- 0269 MCP51 Ethernet Controller
- 026a MCP51 MCI
- 026b MCP51 AC97 Audio Controller
- 026c MCP51 High Definition Audio
- 026d MCP51 USB Controller
- 026e MCP51 USB Controller
- 026f MCP51 PCI Bridge
- 0270 MCP51 Host Bridge
- 0271 MCP51 PMU
- 0272 MCP51 Memory Controller 0
- 027e C51 Memory Controller 2
- 027f C51 Memory Controller 3
- 0280 NV28 [GeForce4 Ti 4800]
- 0281 NV28 [GeForce4 Ti 4200 AGP 8x]
- 0282 NV28 [GeForce4 Ti 4800 SE]
- 0286 NV28 [GeForce4 Ti 4200 Go AGP 8x]
- 0288 NV28GL [Quadro4 980 XGL]
- 0289 NV28GL [Quadro4 780 XGL]
- 028c NV28GLM [Quadro4 700 GoGL]
- 02f0 C51 Host Bridge
- 02f1 C51 Host Bridge
- 02f2 C51 Host Bridge
- 02f3 C51 Host Bridge
- 02f4 C51 Host Bridge
- 02f5 C51 Host Bridge
- 02f6 C51 Host Bridge
- 02f7 C51 Host Bridge
- 02f8 C51 Memory Controller 5
- 02f9 C51 Memory Controller 4
- 02fa C51 Memory Controller 0
- 02fb C51 PCI Express Bridge
- 02fc C51 PCI Express Bridge
- 02fd C51 PCI Express Bridge
- 02fe C51 Memory Controller 1
- 02ff C51 Host Bridge
- 0300 NV30 [GeForce FX]
- 0301 NV30 [GeForce FX 5800 Ultra]
- 0302 NV30 [GeForce FX 5800]
- 0308 NV30GL [Quadro FX 2000]
- 0309 NV30GL [Quadro FX 1000]
- 0311 NV31 [GeForce FX 5600 Ultra]
- 0312 NV31 [GeForce FX 5600]
- 0313 NV31
- 0314 NV31 [GeForce FX 5600XT]
- 1043 814a V9560XT/TD
- 0316 NV31
- 0317 NV31
- 031a NV31M [GeForce FX Go 5600]
- 031b NV31M [GeForce FX Go5650]
- 031c NVIDIA Quadro FX 700 Go
- 031d NV31
- 031e NV31
- 031f NV31
- 0320 NV34 [GeForce FX 5200]
- 0321 NV34 [GeForce FX 5200 Ultra]
- 0322 NV34 [GeForce FX 5200]
- 1462 9171 MS-8917 (FX5200-T128)
- 0323 NV34 [GeForce FX 5200LE]
- 0324 NV34M [GeForce FX Go 5200]
- 1071 8160 MIM2000
- 0325 NV34M [GeForce FX Go5250]
- 0326 NV34 [GeForce FX 5500]
- 0327 NV34 [GeForce FX 5100]
- 0328 NV34M [GeForce FX Go 5200]
- 0329 NV34M [GeForce FX Go5200]
- 032a NV34GL [Quadro NVS 280 PCI]
- 032b NV34GL [Quadro FX 500/600 PCI]
- 032c NV34GLM [GeForce FX Go 5300]
- 032d NV34 [GeForce FX Go5100]
- 032f NV34
- 0330 NV35 [GeForce FX 5900 Ultra]
- 0331 NV35 [GeForce FX 5900]
- 1043 8145 V9950GE
- 0332 NV35 [GeForce FX 5900XT]
- 0333 NV38 [GeForce FX 5950 Ultra]
- 0334 NV35 [GeForce FX 5900ZT]
- 0338 NV35GL [Quadro FX 3000]
- 033f NV35GL [Quadro FX 700]
- 0341 NV36.1 [GeForce FX 5700 Ultra]
- 0342 NV36.2 [GeForce FX 5700]
- 0343 NV36 [GeForce FX 5700LE]
- 0344 NV36.4 [GeForce FX 5700VE]
- 0345 NV36.5
- 0347 NV36 [GeForce FX Go5700]
- 0348 NV36 [GeForce FX Go5700]
- 0349 NV36
- 034b NV36
- 034c NV36 [Quadro FX Go1000]
- 034e NV36GL [Quadro FX 1100]
- 034f NV36GL
-10df Emulex Corporation
- 1ae5 LP6000 Fibre Channel Host Adapter
- 1ae6 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- 1ae7 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:2-3)
- f005 LP1150e Fibre Channel Host Adapter
- f085 LP850 Fibre Channel Host Adapter
- f095 LP952 Fibre Channel Host Adapter
- f098 LP982 Fibre Channel Host Adapter
- f0a5 LP1050 Fibre Channel Host Adapter
- f0d5 LP1150 Fibre Channel Host Adapter
- f100 LP11000e Fibre Channel Host Adapter
- f700 LP7000 Fibre Channel Host Adapter
- f701 LP 7000EFibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f800 LP8000 Fibre Channel Host Adapter
- f801 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f900 LP9000 Fibre Channel Host Adapter
- f901 LP 9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
- f980 LP9802 Fibre Channel Host Adapter
- f981 LP 9802 Fibre Channel Host Adapter Alternate ID
- f982 LP 9802 Fibre Channel Host Adapter Alternate ID
- fa00 LP10000 Fibre Channel Host Adapter
- fa01 LP101 Fibre Channel Host Adapter
- fd00 LP11000 Fibre Channel Host Adapter
-10e0 Integrated Micro Solutions Inc.
- 5026 IMS5026/27/28
- 5027 IMS5027
- 5028 IMS5028
- 8849 IMS8849
- 8853 IMS8853
- 9128 IMS9128 [Twin turbo 128]
-10e1 Tekram Technology Co.,Ltd.
- 0391 TRM-S1040
- 10e1 0391 DC-315U SCSI-3 Host Adapter
- 690c DC-690c
- dc29 DC-290
-10e2 Aptix Corporation
-10e3 Tundra Semiconductor Corp.
- 0000 CA91C042 [Universe]
- 0860 CA91C860 [QSpan]
- 0862 CA91C862A [QSpan-II]
- 8260 CA91L8200B [Dual PCI PowerSpan II]
- 8261 CA91L8260B [Single PCI PowerSpan II]
-10e4 Tandem Computers
-10e5 Micro Industries Corporation
-10e6 Gainbery Computer Products Inc.
-10e7 Vadem
-10e8 Applied Micro Circuits Corp.
- 1072 INES GPIB-PCI (AMCC5920 based)
- 2011 Q-Motion Video Capture/Edit board
- 4750 S5930 [Matchmaker]
- 5920 S5920
- 8043 LANai4.x [Myrinet LANai interface chip]
- 8062 S5933_PARASTATION
- 807d S5933 [Matchmaker]
- 8088 Kongsberg Spacetec Format Synchronizer
- 8089 Kongsberg Spacetec Serial Output Board
- 809c S5933_HEPC3
- 80d7 PCI-9112
- 80d9 PCI-9118
- 80da PCI-9812
- 811a PCI-IEEE1355-DS-DE Interface
- 814c Fastcom ESCC-PCI (Commtech, Inc.)
- 8170 S5933 [Matchmaker] (Chipset Development Tool)
-# sold with Roper Scientifc(Photometrics) CoolSnap HQ camera
- 81e6 Multimedia video controller
- 8291 Fastcom 232/8-PCI (Commtech, Inc.)
- 82c4 Fastcom 422/4-PCI (Commtech, Inc.)
- 82c5 Fastcom 422/2-PCI (Commtech, Inc.)
- 82c6 Fastcom IG422/1-PCI (Commtech, Inc.)
- 82c7 Fastcom IG232/2-PCI (Commtech, Inc.)
- 82ca Fastcom 232/4-PCI (Commtech, Inc.)
- 82db AJA HDNTV HD SDI Framestore
- 82e2 Fastcom DIO24H-PCI (Commtech, Inc.)
- 8851 S5933 on Innes Corp FM Radio Capture card
-10e9 Alps Electric Co., Ltd.
-10ea Intergraphics Systems
- 1680 IGA-1680
- 1682 IGA-1682
- 1683 IGA-1683
- 2000 CyberPro 2000
- 2010 CyberPro 2000A
- 5000 CyberPro 5000
- 5050 CyberPro 5050
- 5202 CyberPro 5202
-# CyberPro5202 Audio Function
- 5252 CyberPro5252
-10eb Artists Graphics
- 0101 3GA
- 8111 Twist3 Frame Grabber
-10ec Realtek Semiconductor Co., Ltd.
- 8029 RTL-8029(AS)
- 10b8 2011 EZ-Card (SMC1208)
- 10ec 8029 RTL-8029(AS)
- 1113 1208 EN1208
- 1186 0300 DE-528
- 1259 2400 AT-2400
- 8129 RTL-8129
- 10ec 8129 RT8129 Fast Ethernet Adapter
- 8138 RT8139 (B/C) Cardbus Fast Ethernet Adapter
- 10ec 8138 RT8139 (B/C) Fast Ethernet Adapter
- 8139 RTL-8139/8139C/8139C+
- 0357 000a TTP-Monitoring Card V2.0
- 1025 005a TravelMate 290
- 1025 8920 ALN-325
- 1025 8921 ALN-325
- 1071 8160 MIM2000
- 10bd 0320 EP-320X-R
- 10ec 8139 RT8139
- 1113 ec01 FNC-0107TX
- 1186 1300 DFE-538TX
- 1186 1320 SN5200
- 1186 8139 DRN-32TX
- 11f6 8139 FN22-3(A) LinxPRO Ethernet Adapter
- 1259 2500 AT-2500TX
- 1259 2503 AT-2500TX/ACPI
- 1429 d010 ND010
- 1432 9130 EN-9130TX
- 1436 8139 RT8139
- 1458 e000 GA-7VM400M/7VT600 Motherboard
- 146c 1439 FE-1439TX
- 1489 6001 GF100TXRII
- 1489 6002 GF100TXRA
- 149c 139a LFE-8139ATX
- 149c 8139 LFE-8139TX
- 14cb 0200 LNR-100 Family 10/100 Base-TX Ethernet
- 1799 5000 F5D5000 PCI Card/Desktop Network PCI Card
- 2646 0001 EtheRx
- 8e2e 7000 KF-230TX
- 8e2e 7100 KF-230TX/2
- a0a0 0007 ALN-325C
- 8169 RTL-8169 Gigabit Ethernet
- 1259 c107 CG-LAPCIGT
- 1371 434e ProG-2000L
- 1458 e000 GA-K8VT800 Pro Motherboard
- 1462 702c K8T NEO 2 motherboard
- 8180 RTL8180L 802.11b MAC
- 8197 SmartLAN56 56K Modem
-10ed Ascii Corporation
- 7310 V7310
-10ee Xilinx Corporation
- 3fc0 RME Digi96
- 3fc1 RME Digi96/8
- 3fc2 RME Digi96/8 Pro
- 3fc3 RME Digi96/8 Pad
- 3fc4 RME Digi9652 (Hammerfall)
- 3fc5 RME Hammerfall DSP
- 3fc6 RME Hammerfall DSP MADI
- 8381 Ellips Santos Frame Grabber
-10ef Racore Computer Products, Inc.
- 8154 M815x Token Ring Adapter
-10f0 Peritek Corporation
-10f1 Tyan Computer
-10f2 Achme Computer, Inc.
-10f3 Alaris, Inc.
-10f4 S-MOS Systems, Inc.
-10f5 NKK Corporation
- a001 NDR4000 [NR4600 Bridge]
-10f6 Creative Electronic Systems SA
-10f7 Matsushita Electric Industrial Co., Ltd.
-10f8 Altos India Ltd
-10f9 PC Direct
-10fa Truevision
- 000c TARGA 1000
-10fb Thesys Gesellschaft für Mikroelektronik mbH
- 186f TH 6255
-10fc I-O Data Device, Inc.
-# What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives
- 0003 Cardbus IDE Controller
- 0005 Cardbus SCSI CBSC II
-10fd Soyo Computer, Inc
-10fe Fast Multimedia AG
-10ff NCube
-1100 Jazz Multimedia
-1101 Initio Corporation
- 1060 INI-A100U2W
- 9100 INI-9100/9100W
- 9400 INI-940
- 9401 INI-950
- 9500 360P
- 9502 Initio INI-9100UW Ultra Wide SCSI Controller INIC-950P chip
-1102 Creative Labs
- 0002 SB Live! EMU10k1
- 1102 0020 CT4850 SBLive! Value
- 1102 0021 CT4620 SBLive!
- 1102 002f SBLive! mainboard implementation
- 1102 4001 E-mu APS
- 1102 8022 CT4780 SBLive! Value
- 1102 8023 CT4790 SoundBlaster PCI512
- 1102 8024 CT4760 SBLive!
- 1102 8025 SBLive! Mainboard Implementation
- 1102 8026 CT4830 SBLive! Value
- 1102 8027 CT4832 SBLive! Value
- 1102 8028 CT4760 SBLive! OEM version
- 1102 8031 CT4831 SBLive! Value
- 1102 8040 CT4760 SBLive!
- 1102 8051 CT4850 SBLive! Value
- 1102 8061 SBLive! Player 5.1
- 1102 8064 SB Live! 5.1 Model SB0100
- 1102 8065 SBLive! 5.1 Digital Model SB0220
- 1102 8067 SBLive! 5.1 eMicro 28028
- 0004 SB Audigy
- 1102 0051 SB0090 Audigy Player
- 1102 0053 SB0090 Audigy Player/OEM
- 1102 0058 SB0090 Audigy Player/OEM
- 1102 1007 SB0240 Audigy 2 Platinum 6.1
- 1102 2002 SB Audigy 2 ZS (SB0350)
- 0006 [SB Live! Value] EMU10k1X
- 0007 SB Audigy LS
- 1102 1001 SB0310 Audigy LS
- 1102 1002 SB0312 Audigy LS
- 1102 1006 SB0410 SBLive! 24-bit
- 0008 SB0400 Audigy2 Value
- 4001 SB Audigy FireWire Port
- 1102 0010 SB Audigy FireWire Port
- 7002 SB Live! MIDI/Game Port
- 1102 0020 Gameport Joystick
- 7003 SB Audigy MIDI/Game port
- 1102 0040 SB Audigy MIDI/Game Port
- 7004 [SB Live! Value] Input device controller
- 7005 SB Audigy LS MIDI/Game port
- 1102 1001 SB0310 Audigy LS MIDI/Game port
- 1102 1002 SB0312 Audigy LS MIDI/Game port
- 8064 SB0100 [SBLive! 5.1 OEM]
- 8938 Ectiva EV1938
- 1033 80e5 SlimTower-Jim (NEC)
- 1071 7150 Mitac 7150
- 110a 5938 Siemens Scenic Mobile 510PIII
- 13bd 100c Ceres-C (Sharp, Intel BX)
- 13bd 100d Sharp, Intel Banister
- 13bd 100e TwinHead P09S/P09S3 (Sharp)
- 13bd f6f1 Marlin (Sharp)
- 14ff 0e70 P88TE (TWINHEAD INTERNATIONAL Corp)
- 14ff c401 Notebook 9100/9200/2000 (TWINHEAD INTERNATIONAL Corp)
- 156d b400 G400 - Geo (AlphaTop (Taiwan))
- 156d b550 G560 (AlphaTop (Taiwan))
- 156d b560 G560 (AlphaTop (Taiwan))
- 156d b700 G700/U700 (AlphaTop (Taiwan))
- 156d b795 G795 (AlphaTop (Taiwan))
- 156d b797 G797 (AlphaTop (Taiwan))
-1103 Triones Technologies, Inc.
- 0003 HPT343
- 0004 HPT366/368/370/370A/372/372N
- 1103 0001 HPT370A
- 1103 0003 HPT343 / HPT345 / HPT363 UDMA33
- 1103 0004 HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)
- 1103 0005 HPT370 UDMA100
- 1103 0006 HPT302
- 1103 0007 HPT371 UDMA133
- 1103 0008 HPT374 UDMA/ATA133 RAID Controller
- 0005 HPT372A/372N
- 0006 HPT302
- 0007 HPT371/371N
- 0008 HPT374
- 0009 HPT372N
-1104 RasterOps Corp.
-1105 Sigma Designs, Inc.
- 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder
- 8300 REALmagic Hollywood Plus DVD Decoder
- 8400 EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder
- 8401 EM8401 REALmagic DVD/MPEG-2 A/V Decoder
- 8470 EM8470 REALmagic DVD/MPEG-4 A/V Decoder
- 8471 EM8471 REALmagic DVD/MPEG-4 A/V Decoder
- 8475 EM8475 REALmagic DVD/MPEG-4 A/V Decoder
- 8476 EM8476 REALmagic DVD/MPEG-4 A/V Decoder
- 8485 EM8485 REALmagic DVD/MPEG-4 A/V Decoder
- 8486 EM8486 REALmagic DVD/MPEG-4 A/V Decoder
-1106 VIA Technologies, Inc.
- 0102 Embedded VIA Ethernet Controller
- 0130 VT6305 1394.A Controller
- 0305 VT8363/8365 [KT133/KM133]
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 147b a401 KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard
- 0391 VT8371 [KX133]
- 0501 VT8501 [Apollo MVP4]
- 0505 VT82C505
-# Shares chip with :0576. The VT82C576M has :1571 instead of :0561.
- 0561 VT82C576MV
- 0571 VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE
- 1019 0985 P6VXA Motherboard
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 8052 VT8233A Bus Master ATA100/66/33 IDE
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard rev. 1.01
- 1043 80ed A7V600 motherboard
- 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE
- 1179 0001 Magnia Z310
- 1297 f641 FX41 motherboard
- 1458 5002 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 1849 0571 K7VT2 motherboard
- 0576 VT82C576 3V [Apollo Master]
- 0585 VT82C585VP [Apollo VP1/VPX]
- 0586 VT82C586/A/B PCI-to-ISA [Apollo VP]
- 1106 0000 MVP3 ISA Bridge
- 0595 VT82C595 [Apollo VP2]
- 0596 VT82C596 ISA [Mobile South]
- 1106 0000 VT82C596/A/B PCI to ISA Bridge
- 1458 0596 VT82C596/A/B PCI to ISA Bridge
- 0597 VT82C597 [Apollo VP3]
- 0598 VT82C598 [Apollo MVP3]
- 0601 VT8601 [Apollo ProMedia]
- 0605 VT8605 [ProSavage PM133]
- 1043 802c CUV4X mainboard
- 0680 VT82C680 [Apollo P6]
- 0686 VT82C686 [Apollo Super South]
- 1019 0985 P6VXA Motherboard
- 1043 802c CUV4X mainboard
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8040 A7M266 Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 1106 0000 VT82C686/A PCI to ISA Bridge
- 1106 0686 VT82C686/A PCI to ISA Bridge
- 1179 0001 Magnia Z310
- 147b a702 KG7-Lite Mainboard
- 0691 VT82C693A/694x [Apollo PRO133x]
- 1019 0985 P6VXA Motherboard
- 1179 0001 Magnia Z310
- 1458 0691 VT82C691 Apollo Pro System Controller
- 0693 VT82C693 [Apollo Pro Plus]
- 0698 VT82C693A [Apollo Pro133 AGP]
- 0926 VT82C926 [Amazon]
- 1000 VT82C570MV
- 1106 VT82C570MV
- 1571 VT82C576M/VT82C586
- 1595 VT82C595/97 [Apollo VP2/97]
- 3022 CLE266
-# This is *not* USB 2.0 as the existing entry suggests
- 3038 VT82xxxxx UHCI USB 1.1 Controller
- 0925 1234 USB Controller
- 1019 0985 P6VXA Motherboard
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c VT6202 USB2.0 4 port controller
- 1043 80a1 A7V8X-X motherboard
- 1043 80ed A7V600 motherboard
- 1179 0001 Magnia Z310
- 1458 5004 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 182d 201d CN-029 USB2.0 4 port PCI Card
- 3040 VT82C586B ACPI
- 3043 VT86C100A [Rhine]
- 10bd 0000 VT86C100A Fast Ethernet Adapter
- 1106 0100 VT86C100A Fast Ethernet Adapter
- 1186 1400 DFE-530TX rev A
- 3044 IEEE 1394 Host Controller
- 1025 005a TravelMate 290
- 1458 1000 GA-7VT600-1394 Motherboard
- 1462 702d K8T NEO 2 motherboard
- 3050 VT82C596 Power Management
- 3051 VT82C596 Power Management
- 3053 VT6105M [Rhine-III]
- 3057 VT82C686 [Apollo Super ACPI]
- 1019 0985 P6VXA Motherboard
- 1043 8033 A7V Mainboard
- 1043 803e A7V-E Mainboard
- 1043 8040 A7M266 Mainboard
- 1043 8042 A7V133/A7V133-C Mainboard
- 1179 0001 Magnia Z310
- 3058 VT82C686 AC97 Audio Controller
- 0e11 0097 SoundMax Digital Integrated Audio
- 0e11 b194 Soundmax integrated digital audio
- 1019 0985 P6VXA Motherboard
- 1043 1106 A7V133/A7V133-C Mainboard
- 1106 4511 Onboard Audio on EP7KXA
- 1458 7600 Onboard Audio
- 1462 3091 MS-6309 Onboard Audio
- 1462 3300 MS-6330 Onboard Audio
- 15dd 7609 Onboard Audio
- 3059 VT8233/A/8235/8237 AC97 Audio Controller
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 8095 A7V8X Motherboard (Realtek ALC650 codec)
- 1043 80a1 A7V8X-X Motherboard
- 1043 80b0 A7V600/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX])
- 1106 3059 L7VMM2 Motherboard
- 1106 4161 K7VT2 motherboard
- 1297 c160 FX41 motherboard (Realtek ALC650 codec)
- 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650)
- 1462 0080 K8T NEO 2 motherboard
- 1462 3800 KT266 onboard audio
- 147b 1407 KV8-MAX3 motherboard
- 3065 VT6102 [Rhine-II]
- 1043 80a1 A7V8X-X Motherboard
- 1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235
- 1186 1400 DFE-530TX rev A
- 1186 1401 DFE-530TX rev B
- 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
-# This hosts more than just the Intel 537 codec, it also hosts PCtel (SIL33) and SmartLink (SIL34) codecs
- 3068 AC'97 Modem Controller
- 1462 309e MS-6309 Saturn Motherboard
- 3074 VT8233 PCI to ISA Bridge
- 1043 8052 VT8233A
- 3091 VT8633 [Apollo Pro266]
- 3099 VT8366/A/7 [Apollo KT266/A/333]
- 1043 8064 A7V266-E Mainboard
- 1043 807f A7V333 Mainboard
- 1849 3099 K7VT2 motherboard
- 3101 VT8653 Host Bridge
- 3102 VT8662 Host Bridge
- 3103 VT8615 Host Bridge
- 3104 USB 2.0
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard rev 1.01
- 1043 80ed A7V600 motherboard
- 1297 f641 FX41 motherboard
- 1458 5004 GA-7VAX Mainboard
- 1462 7020 K8T NEO 2 motherboard
- 147b 1407 KV8-MAX3 motherboard
- 182d 201d CN-029 USB 2.0 4 port PCI Card
- 3106 VT6105 [Rhine-III]
- 1186 1403 DFE-530TX rev C
- 3108 S3 Unichrome Pro VGA Adapter
- 3109 VT8233C PCI to ISA Bridge
- 3112 VT8361 [KLE133] Host Bridge
- 3116 VT8375 [KM266/KL266] Host Bridge
- 1297 f641 FX41 motherboard
- 3118 S3 Unichrome Pro VGA Adapter
- 3119 VT6120/VT6121/VT6122 Gigabit Ethernet Adapter
-# found on EPIA M6000/9000 mainboard
- 3122 VT8623 [Apollo CLE266] integrated CastleRock graphics
-# found on EPIA M6000/9000 mainboard
- 3123 VT8623 [Apollo CLE266]
- 3128 VT8753 [P4X266 AGP]
- 3133 VT3133 Host Bridge
- 3147 VT8233A ISA Bridge
- 3148 P4M266 Host Bridge
- 3149 VIA VT6420 SATA RAID Controller
- 1043 80ed A7V600/K8V Deluxe motherboard
- 1458 b003 GA-7VM400AM(F) Motherboard
- 1462 7020 K8T Neo 2 Motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3156 P/KN266 Host Bridge
-# on ASUS P4P800
- 3164 VT6410 ATA133 RAID controller
- 3168 VT8374 P4X400 Host Controller/AGP Bridge
- 3177 VT8235 ISA Bridge
- 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235)
- 1043 808c A7V8X motherboard
- 1043 80a1 A7V8X-X motherboard
- 1297 f641 FX41 motherboard
- 1458 5001 GA-7VAX Mainboard
- 1849 3177 K7VT2 motherboard
- 3178 ProSavageDDR P4N333 Host Bridge
- 3188 VT8385 [K8T800 AGP] Host Bridge
- 1043 80a3 K8V Deluxe motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3189 VT8377 [KT400/KT600 AGP] Host Bridge
- 1043 807f A7V8X motherboard
- 1458 5000 GA-7VAX Mainboard
- 3204 K8M800
- 3205 VT8378 [KM400/A] Chipset Host Bridge
- 1458 5000 GA-7VM400M Motherboard
- 3218 K8T800M Host Bridge
- 3227 VT8237 ISA bridge [KT600/K8T800 South]
- 1043 80ed A7V600 motherboard
- 1106 3227 DFI KT600-AL Motherboard
- 1458 5001 GA-7VT600 Motherboard
- 147b 1407 KV8-MAX3 motherboard
- 3249 VT6421 IDE RAID Controller
- 4149 VIA VT6420 (ATA133) Controller
- 5030 VT82C596 ACPI [Apollo PRO]
- 6100 VT85C100A [Rhine II]
- 7204 K8M800
-# S3 Graphics UniChromeâ„¢ 2D/3D Graphics with motion compensation
- 7205 VT8378 [S3 UniChrome] Integrated Video
- 1458 d000 Gigabyte GA-7VM400(A)M(F) Motherboard
- 8231 VT8231 [PCI-to-ISA Bridge]
- 8235 VT8235 ACPI
- 8305 VT8363/8365 [KT133/KM133 AGP]
- 8391 VT8371 [KX133 AGP]
- 8501 VT8501 [Apollo MVP4 AGP]
- 8596 VT82C596 [Apollo PRO AGP]
- 8597 VT82C597 [Apollo VP3 AGP]
- 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP]
- 1019 0985 P6VXA Motherboard
- 8601 VT8601 [Apollo ProMedia AGP]
- 8605 VT8605 [PM133 AGP]
- 8691 VT82C691 [Apollo Pro]
- 8693 VT82C693 [Apollo Pro Plus] PCI Bridge
- b091 VT8633 [Apollo Pro266 AGP]
- b099 VT8366/A/7 [Apollo KT266/A/333 AGP]
- b101 VT8653 AGP Bridge
- b102 VT8362 AGP Bridge
- b103 VT8615 AGP Bridge
- b112 VT8361 [KLE133] AGP Bridge
- b168 VT8235 PCI Bridge
- b188 VT8237 PCI bridge [K8T800 South]
- 147b 1407 KV8-MAX3 motherboard
- b198 VT8237 PCI Bridge
-# 32-Bit PCI bus master Ethernet MAC with standard MII interface
- d104 VT8237 Integrated Fast Ethernet Controller
-1107 Stratus Computers
- 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!)
-1108 Proteon, Inc.
- 0100 p1690plus_AA
- 0101 p1690plus_AB
- 0105 P1690Plus
- 0108 P1690Plus
- 0138 P1690Plus
- 0139 P1690Plus
- 013c P1690Plus
- 013d P1690Plus
-1109 Cogent Data Technologies, Inc.
- 1400 EM110TX [EX110TX]
-110a Siemens Nixdorf AG
- 0002 Pirahna 2-port
- 0005 Tulip controller, power management, switch extender
- 0006 FSC PINC (I/O-APIC)
- 0015 FSC Multiprocessor Interrupt Controller
- 001d FSC Copernicus Management Controller
- 007b FSC Remote Service Controller, mailbox device
- 007c FSC Remote Service Controller, shared memory device
- 007d FSC Remote Service Controller, SMIC device
-# Superfastcom-PCI (Commtech, Inc.) or DSCC4 WAN Adapter
- 2102 DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Controller with 4 Channels
- 2104 Eicon Diva 2.02 compatible passive ISDN card
- 3142 SIMATIC NET CP 5613A1 (Profibus Adapter)
- 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter)
- 4029 SIMATIC NET CP 5613A2 (Profibus Adapter)
- 4942 FPGA I-Bus Tracer for MBD
- 6120 SZB6120
-110b Chromatic Research Inc.
- 0001 Mpact Media Processor
- 0004 Mpact 2
-110c Mini-Max Technology, Inc.
-110d Znyx Advanced Systems
-110e CPU Technology
-110f Ross Technology
-1110 Powerhouse Systems
- 6037 Firepower Powerized SMP I/O ASIC
- 6073 Firepower Powerized SMP I/O ASIC
-1111 Santa Cruz Operation
-# Also claimed to be RNS or Rockwell International, current PCISIG records list Osicom
-1112 Osicom Technologies Inc
- 2200 FDDI Adapter
- 2300 Fast Ethernet Adapter
- 2340 4 Port Fast Ethernet Adapter
- 2400 ATM Adapter
-1113 Accton Technology Corporation
- 1211 SMC2-1211TX
- 103c 1207 EN-1207D Fast Ethernet Adapter
- 1113 1211 EN-1207D Fast Ethernet Adapter
- 1216 EN-1216 Ethernet Adapter
- 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card
- 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]
- 1217 EN-1217 Ethernet Adapter
- 5105 10Mbps Network card
- 9211 EN-1207D Fast Ethernet Adapter
- 1113 9211 EN-1207D Fast Ethernet Adapter
- 9511 21x4x DEC-Tulip compatible Fast Ethernet
- d301 CPWNA100 (Philips wireless PCMCIA)
- ec02 SMC 1244TX v3
-1114 Atmel Corporation
- 0506 802.11b Wireless Network Adaptor (at76c506)
-1115 3D Labs
-1116 Data Translation
- 0022 DT3001
- 0023 DT3002
- 0024 DT3003
- 0025 DT3004
- 0026 DT3005
- 0027 DT3001-PGL
- 0028 DT3003-PGL
-1117 Datacube, Inc
- 9500 Max-1C SVGA card
- 9501 Max-1C image processing
-1118 Berg Electronics
-1119 ICP Vortex Computersysteme GmbH
- 0000 GDT 6000/6020/6050
- 0001 GDT 6000B/6010
- 0002 GDT 6110/6510
- 0003 GDT 6120/6520
- 0004 GDT 6530
- 0005 GDT 6550
- 0006 GDT 6117/6517
- 0007 GDT 6127/6527
- 0008 GDT 6537
- 0009 GDT 6557/6557-ECC
- 000a GDT 6115/6515
- 000b GDT 6125/6525
- 000c GDT 6535
- 000d GDT 6555
- 0010 GDT 6115/6515
- 0011 GDT 6125/6525
- 0012 GDT 6535
- 0013 GDT 6555/6555-ECC
- 0100 GDT 6117RP/6517RP
- 0101 GDT 6127RP/6527RP
- 0102 GDT 6537RP
- 0103 GDT 6557RP
- 0104 GDT 6111RP/6511RP
- 0105 GDT 6121RP/6521RP
- 0110 GDT 6117RD/6517RD
- 0111 GDT 6127RD/6527RD
- 0112 GDT 6537RD
- 0113 GDT 6557RD
- 0114 GDT 6111RD/6511RD
- 0115 GDT 6121RD/6521RD
- 0118 GDT 6118RD/6518RD/6618RD
- 0119 GDT 6128RD/6528RD/6628RD
- 011a GDT 6538RD/6638RD
- 011b GDT 6558RD/6658RD
- 0120 GDT 6117RP2/6517RP2
- 0121 GDT 6127RP2/6527RP2
- 0122 GDT 6537RP2
- 0123 GDT 6557RP2
- 0124 GDT 6111RP2/6511RP2
- 0125 GDT 6121RP2/6521RP2
- 0136 GDT 6113RS/6513RS
- 0137 GDT 6123RS/6523RS
- 0138 GDT 6118RS/6518RS/6618RS
- 0139 GDT 6128RS/6528RS/6628RS
- 013a GDT 6538RS/6638RS
- 013b GDT 6558RS/6658RS
- 013c GDT 6533RS/6633RS
- 013d GDT 6543RS/6643RS
- 013e GDT 6553RS/6653RS
- 013f GDT 6563RS/6663RS
- 0166 GDT 7113RN/7513RN/7613RN
- 0167 GDT 7123RN/7523RN/7623RN
- 0168 GDT 7118RN/7518RN/7518RN
- 0169 GDT 7128RN/7528RN/7628RN
- 016a GDT 7538RN/7638RN
- 016b GDT 7558RN/7658RN
- 016c GDT 7533RN/7633RN
- 016d GDT 7543RN/7643RN
- 016e GDT 7553RN/7653RN
- 016f GDT 7563RN/7663RN
- 01d6 GDT 4x13RZ
- 01d7 GDT 4x23RZ
- 01f6 GDT 8x13RZ
- 01f7 GDT 8x23RZ
- 01fc GDT 8x33RZ
- 01fd GDT 8x43RZ
- 01fe GDT 8x53RZ
- 01ff GDT 8x63RZ
- 0210 GDT 6519RD/6619RD
- 0211 GDT 6529RD/6629RD
- 0260 GDT 7519RN/7619RN
- 0261 GDT 7529RN/7629RN
- 02ff GDT MAXRP
- 0300 GDT NEWRX
-111a Efficient Networks, Inc
- 0000 155P-MF1 (FPGA)
- 0002 155P-MF1 (ASIC)
- 0003 ENI-25P ATM
- 111a 0000 ENI-25p Miniport ATM Adapter
- 0005 SpeedStream (LANAI)
- 111a 0001 ENI-3010 ATM
- 111a 0009 ENI-3060 ADSL (VPI=0)
- 111a 0101 ENI-3010 ATM
- 111a 0109 ENI-3060CO ADSL (VPI=0)
- 111a 0809 ENI-3060 ADSL (VPI=0 or 8)
- 111a 0909 ENI-3060CO ADSL (VPI=0 or 8)
- 111a 0a09 ENI-3060 ADSL (VPI=<0..15>)
- 0007 SpeedStream ADSL
- 111a 1001 ENI-3061 ADSL [ASIC]
- 1203 SpeedStream 1023 Wireless PCI Adapter
-111b Teledyne Electronic Systems
-111c Tricord Systems Inc.
- 0001 Powerbis Bridge
-111d Integrated Device Technology, Inc.
- 0001 IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
- 0003 IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller
- 0004 IDT77V252 155Mbps ATM MICRO ABR SAR Controller
- 0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller
-111e Eldec
-111f Precision Digital Images
- 4a47 Precision MX Video engine interface
- 5243 Frame capture bus interface
-1120 EMC Corporation
-1121 Zilog
-1122 Multi-tech Systems, Inc.
-1123 Excellent Design, Inc.
-1124 Leutron Vision AG
-1125 Eurocore
-1126 Vigra
-1127 FORE Systems Inc
- 0200 ForeRunner PCA-200 ATM
- 0210 PCA-200PC
- 0250 ATM
- 0300 ForeRunner PCA-200EPC ATM
- 0310 ATM
- 0400 ForeRunnerHE ATM Adapter
- 1127 0400 ForeRunnerHE ATM
-1129 Firmworks
-112a Hermes Electronics Company, Ltd.
-112b Linotype - Hell AG
-112c Zenith Data Systems
-112d Ravicad
-112e Infomedia Microelectronics Inc.
-112f Imaging Technology Inc
- 0000 MVC IC-PCI
- 0001 MVC IM-PCI Video frame grabber/processor
-1130 Computervision
-1131 Philips Semiconductors
- 1561 USB 1.1 Host Controller
- 1562 USB 2.0 Host Controller
- 3400 SmartPCI56(UCB1500) 56K Modem
- 5400 TriMedia TM1000/1100
- 5402 TriMedia TM-1300
- 1244 0f00 Fritz!Card DSL
- 7130 SAA7130 Video Broadcast Decoder
- 5168 0138 LiveView FlyVideo 2000
- 7133 SAA713X Audio+video broadcast decoder
- 5168 0138 LifeView FlyVideo 3000
- 5168 0212 LifeView FlyTV Platinum mini
- 5168 0502 LifeView FlyDVB-T Duo CardBus
-# PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl)
- 7134 SAA7134
- 1043 4842 TV-FM Card 7134
- 7135 SAA7135 Audio+video broadcast decoder
- 7145 SAA7145
- 7146 SAA7146
- 110a 0000 Fujitsu/Siemens DVB-C card rev1.5
- 110a ffff Fujitsu/Siemens DVB-C card rev1.5
- 1131 4f56 KNC1 DVB-S Budget
- 1131 4f61 Fujitsu-Siemens Activy DVB-S Budget
- 114b 2003 DVRaptor Video Edit/Capture Card
- 11bd 0006 DV500 Overlay
- 11bd 000a DV500 Overlay
- 11bd 000f DV500 Overlay
- 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5
- 13c2 0001 Technotrend/Hauppauge DVB card rev1.3 or rev1.6
- 13c2 0002 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0003 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0004 Technotrend/Hauppauge DVB card rev2.1
- 13c2 0006 Technotrend/Hauppauge DVB card rev1.3 or rev1.6
- 13c2 0008 Technotrend/Hauppauge DVB-T
- 13c2 000a Octal/Technotrend DVB-C for iTV
- 13c2 1003 Technotrend-Budget / Hauppauge WinTV-NOVA-S DVB card
- 13c2 1004 Technotrend-Budget / Hauppauge WinTV-NOVA-C DVB card
- 13c2 1005 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card
- 13c2 100c Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card
- 13c2 100f Technotrend-Budget / Hauppauge WinTV-NOVA-CI DVB card
- 13c2 1011 Technotrend-Budget / Hauppauge WinTV-NOVA-T DVB card
- 13c2 1013 SATELCO Multimedia DVB
- 13c2 1102 Technotrend/Hauppauge DVB card rev2.1
-1132 Mitel Corp.
-# This is the new official company name. See disclaimer on www.eicon.com for details!
-1133 Eicon Networks Corporation
- 7901 EiconCard S90
- 7902 EiconCard S90
- 7911 EiconCard S91
- 7912 EiconCard S91
- 7941 EiconCard S94
- 7942 EiconCard S94
- 7943 EiconCard S94
- 7944 EiconCard S94
- b921 EiconCard P92
- b922 EiconCard P92
- b923 EiconCard P92
- e001 Diva Pro 2.0 S/T
- e002 Diva 2.0 S/T PCI
- e003 Diva Pro 2.0 U
- e004 Diva 2.0 U PCI
- e005 Diva 2.01 S/T PCI
- e006 Diva CT S/T PCI
- e007 Diva CT U PCI
- e008 Diva CT Lite S/T PCI
- e009 Diva CT Lite U PCI
- e00a Diva ISDN+V.90 PCI
- e00b Diva 2.02 PCI S/T
- e00c Diva 2.02 PCI U
- e00d Diva ISDN Pro 3.0 PCI
- e00e Diva ISDN+CT S/T PCI Rev 2
- e010 Diva Server BRI-2M PCI
- 110a 0021 Fujitsu Siemens ISDN S0
- 8001 0014 Diva Server BRI-2M PCI Cornet NQ
- e011 Diva Server BRI S/T Rev 2
- e012 Diva Server 4BRI-8M PCI
- 8001 0014 Diva Server 4BRI-8M PCI Cornet NQ
- e013 Diva Server 4BRI Rev 2
- 1133 1300 Diva Server V-4BRI-8
- 1133 e013 Diva Server 4BRI-8M 2.0 PCI
- 8001 0014 Diva Server 4BRI-8M 2.0 PCI Cornet NQ
- e014 Diva Server PRI-30M PCI
- 0008 0100 Diva Server PRI-30M PCI
- 8001 0014 Diva Server PRI-30M PCI Cornet NQ
- e015 DIVA Server PRI Rev 2
- 1133 e015 Diva Server PRI 2.0 PCI
- 8001 0014 Diva Server PRI 2.0 PCI Cornet NQ
- e016 Diva Server Voice 4BRI PCI
- 8001 0014 Diva Server PRI Cornet NQ
- e017 Diva Server Voice 4BRI Rev 2
- 1133 e017 Diva Server Voice 4BRI-8M 2.0 PCI
- 8001 0014 Diva Server Voice 4BRI-8M 2.0 PCI Cornet NQ
- e018 Diva Server BRI-2M 2.0 PCI
- 1133 1800 Diva Server V-BRI-2
- 1133 e018 Diva Server BRI-2M 2.0 PCI
- 8001 0014 Diva Server BRI-2M 2.0 PCI Cornet NQ
- e019 Diva Server Voice PRI Rev 2
- 1133 e019 Diva Server Voice PRI 2.0 PCI
- 8001 0014 Diva Server Voice PRI 2.0 PCI Cornet NQ
- e01a Diva Server 2FX
- e01b Diva Server Voice BRI-2M 2.0 PCI
- 1133 e01b Diva Server Voice BRI-2M 2.0 PCI
- 8001 0014 Diva Server Voice BRI-2M 2.0 PCI Cornet NQ
- e01c Diva Server PRI Rev 3
- 1133 1c01 Diva Server PRI/E1/T1-8
- 1133 1c02 Diva Server PRI/T1-24
- 1133 1c03 Diva Server PRI/E1-30
- 1133 1c04 Diva Server PRI/E1/T1
- 1133 1c05 Diva Server V-PRI/T1-24
- 1133 1c06 Diva Server V-PRI/E1-30
- 1133 1c07 Diva Server PRI/E1/T1-8 Cornet NQ
- 1133 1c08 Diva Server PRI/T1-24 Cornet NQ
- 1133 1c09 Diva Server PRI/E1-30 Cornet NQ
- 1133 1c0a Diva Server PRI/E1/T1 Cornet NQ
- 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ
- 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ
- e01e Diva Server 2PRI
- 1133 1e00 Diva Server V-2PRI/E1-60
- 1133 1e01 Diva Server V-2PRI/T1-48
- 1133 1e02 Diva Server 2PRI/E1-60
- 1133 1e03 Diva Server 2PRI/T1-48
- e020 Diva Server 4PRI
- 1133 2000 Diva Server V-4PRI/E1-120
- 1133 2001 Diva Server V-4PRI/T1-96
- 1133 2002 Diva Server 4PRI/E1-120
- 1133 2003 Diva Server 4PRI/T1-96
- e024 Diva Server Analog-4P
- 1133 2400 Diva Server V-Analog-4P
- 1133 e024 Diva Server Analog-4P
- e028 Diva Server Analog-8P
- 1133 2800 Diva Server V-Analog-8P
- 1133 e028 Diva Server Analog-8P
-1134 Mercury Computer Systems
- 0001 Raceway Bridge
- 0002 Dual PCI to RapidIO Bridge
-1135 Fuji Xerox Co Ltd
- 0001 Printer controller
-1136 Momentum Data Systems
-1137 Cisco Systems Inc
-1138 Ziatech Corporation
- 8905 8905 [STD 32 Bridge]
-1139 Dynamic Pictures, Inc
- 0001 VGA Compatable 3D Graphics
-113a FWB Inc
-113b Network Computing Devices
-113c Cyclone Microsystems, Inc.
- 0000 PCI-9060 i960 Bridge
- 0001 PCI-SDK [PCI i960 Evaluation Platform]
- 0911 PCI-911 [i960Jx-based Intelligent I/O Controller]
- 0912 PCI-912 [i960CF-based Intelligent I/O Controller]
- 0913 PCI-913
- 0914 PCI-914 [I/O Controller w/ secondary PCI bus]
-113d Leading Edge Products Inc
-113e Sanyo Electric Co - Computer Engineering Dept
-113f Equinox Systems, Inc.
- 0808 SST-64P Adapter
- 1010 SST-128P Adapter
- 80c0 SST-16P DB Adapter
- 80c4 SST-16P RJ Adapter
- 80c8 SST-16P Adapter
- 8888 SST-4P Adapter
- 9090 SST-8P Adapter
-1140 Intervoice Inc
-1141 Crest Microsystem Inc
-1142 Alliance Semiconductor Corporation
- 3210 AP6410
- 6422 ProVideo 6422
- 6424 ProVideo 6424
- 6425 ProMotion AT25
- 643d ProMotion AT3D
-1143 NetPower, Inc
-1144 Cincinnati Milacron
- 0001 Noservo controller
-1145 Workbit Corporation
- 8007 NinjaSCSI-32 Workbit
- f007 NinjaSCSI-32 KME
- f010 NinjaSCSI-32 Workbit
- f012 NinjaSCSI-32 Logitec
- f013 NinjaSCSI-32 Logitec
- f015 NinjaSCSI-32 Melco
-1146 Force Computers
-1147 Interface Corp
-# Formerly (Schneider & Koch)
-1148 SysKonnect
- 4000 FDDI Adapter
- 0e11 b03b Netelligent 100 FDDI DAS Fibre SC
- 0e11 b03c Netelligent 100 FDDI SAS Fibre SC
- 0e11 b03d Netelligent 100 FDDI DAS UTP
- 0e11 b03e Netelligent 100 FDDI SAS UTP
- 0e11 b03f Netelligent 100 FDDI SAS Fibre MIC
- 1148 5521 FDDI SK-5521 (SK-NET FDDI-UP)
- 1148 5522 FDDI SK-5522 (SK-NET FDDI-UP DAS)
- 1148 5541 FDDI SK-5541 (SK-NET FDDI-FP)
- 1148 5543 FDDI SK-5543 (SK-NET FDDI-LP)
- 1148 5544 FDDI SK-5544 (SK-NET FDDI-LP DAS)
- 1148 5821 FDDI SK-5821 (SK-NET FDDI-UP64)
- 1148 5822 FDDI SK-5822 (SK-NET FDDI-UP64 DAS)
- 1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64)
- 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64)
- 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
- 4200 Token Ring adapter
- 4300 SK-98xx Gigabit Ethernet Server Adapter
- 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
- 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
- 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
- 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
- 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
- 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
- 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
- 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
- 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
- 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
- 1259 2970 AT-2970SX Gigabit Ethernet Adapter
- 1259 2971 AT-2970LX Gigabit Ethernet Adapter
- 1259 2972 AT-2970TX Gigabit Ethernet Adapter
- 1259 2973 AT-2971SX Gigabit Ethernet Adapter
- 1259 2974 AT-2971T Gigabit Ethernet Adapter
- 1259 2975 AT-2970SX/2SC Gigabit Ethernet Adapter
- 1259 2976 AT-2970LX/2SC Gigabit Ethernet Adapter
- 1259 2977 AT-2970TX/2TX Gigabit Ethernet Adapter
- 4320 SK-98xx V2.0 Gigabit Ethernet Adapter
- 1148 0121 Marvell RDK-8001 Adapter
- 1148 0221 Marvell RDK-8002 Adapter
- 1148 0321 Marvell RDK-8003 Adapter
- 1148 0421 Marvell RDK-8004 Adapter
- 1148 0621 Marvell RDK-8006 Adapter
- 1148 0721 Marvell RDK-8007 Adapter
- 1148 0821 Marvell RDK-8008 Adapter
- 1148 0921 Marvell RDK-8009 Adapter
- 1148 1121 Marvell RDK-8011 Adapter
- 1148 1221 Marvell RDK-8012 Adapter
- 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter
- 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
- 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
- 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5051 SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
- 1148 9521 SK-9521 10/100/1000Base-T Adapter
- 4400 SK-9Dxx Gigabit Ethernet Adapter
- 4500 SK-9Mxx Gigabit Ethernet Adapter
- 9000 SK-9Sxx Gigabit Ethernet Server Adapter PCI-X
- 9843 [Fujitsu] Gigabit Ethernet
- 9e00 SK-9Exx 10/100/1000Base-T Adapter
- 1148 2100 SK-9E21 Server Adapter
- 1148 21d0 SK-9E21D 10/100/1000Base-T Adapter
- 1148 2200 SK-9E22 Server Adapter
- 1148 8100 SK-9E81 Server Adapter
- 1148 8200 SK-9E82 Server Adapter
- 1148 9100 SK-9E91 Server Adapter
- 1148 9200 SK-9E92 Server Adapter
-1149 Win System Corporation
-114a VMIC
- 5579 VMIPCI-5579 (Reflective Memory Card)
- 5587 VMIPCI-5587 (Reflective Memory Card)
- 6504 VMIC PCI 7755 FPGA
- 7587 VMIVME-7587
-114b Canopus Co., Ltd
-114c Annabooks
-114d IC Corporation
-114e Nikon Systems Inc
-114f Digi International
- 0002 AccelePort EPC
- 0003 RightSwitch SE-6
- 0004 AccelePort Xem
- 0005 AccelePort Xr
- 0006 AccelePort Xr,C/X
- 0009 AccelePort Xr/J
- 000a AccelePort EPC/J
- 000c DataFirePRIme T1 (1-port)
- 000d SyncPort 2-Port (x.25/FR)
- 0011 AccelePort 8r EIA-232 (IBM)
- 0012 AccelePort 8r EIA-422
- 0013 AccelePort Xr
- 0014 AccelePort 8r EIA-422
- 0015 AccelePort Xem
- 0016 AccelePort EPC/X
- 0017 AccelePort C/X
- 001a DataFirePRIme E1 (1-port)
- 001b AccelePort C/X (IBM)
- 001d DataFire RAS T1/E1/PRI
- 114f 0050 DataFire RAS E1 Adapter
- 114f 0051 DataFire RAS Dual E1 Adapter
- 114f 0052 DataFire RAS T1 Adapter
- 114f 0053 DataFire RAS Dual T1 Adapter
- 0023 AccelePort RAS
- 0024 DataFire RAS B4 ST/U
- 114f 0030 DataFire RAS BRI U Adapter
- 114f 0031 DataFire RAS BRI S/T Adapter
- 0026 AccelePort 4r 920
- 0027 AccelePort Xr 920
- 0028 ClassicBoard 4
- 0029 ClassicBoard 8
- 0034 AccelePort 2r 920
- 0035 DataFire DSP T1/E1/PRI cPCI
- 0040 AccelePort Xp
- 0042 AccelePort 2p
- 0043 AccelePort 4p
- 0044 AccelePort 8p
- 0045 AccelePort 16p
- 004e AccelePort 32p
- 0070 Datafire Micro V IOM2 (Europe)
- 0071 Datafire Micro V (Europe)
- 0072 Datafire Micro V IOM2 (North America)
- 0073 Datafire Micro V (North America)
- 00b0 Digi Neo 4
- 00b1 Digi Neo 8
- 00c8 Digi Neo 2 DB9
- 00c9 Digi Neo 2 DB9 PRI
- 00ca Digi Neo 2 RJ45
- 00cb Digi Neo 2 RJ45 PRI
- 00d0 ClassicBoard 4 422
- 00d1 ClassicBoard 8 422
- 6001 Avanstar
-1150 Thinking Machines Corp
-1151 JAE Electronics Inc.
-1152 Megatek
-1153 Land Win Electronic Corp
-1154 Melco Inc
-1155 Pine Technology Ltd
-1156 Periscope Engineering
-1157 Avsys Corporation
-1158 Voarx R & D Inc
- 3011 Tokenet/vg 1001/10m anylan
- 9050 Lanfleet/Truevalue
- 9051 Lanfleet/Truevalue
-1159 Mutech Corp
- 0001 MV-1000
-115a Harlequin Ltd
-115b Parallax Graphics
-115c Photron Ltd.
-115d Xircom
- 0003 Cardbus Ethernet 10/100
- 1014 0181 10/100 EtherJet Cardbus Adapter
- 1014 1181 10/100 EtherJet Cardbus Adapter
- 1014 8181 10/100 EtherJet Cardbus Adapter
- 1014 9181 10/100 EtherJet Cardbus Adapter
- 115d 0181 Cardbus Ethernet 10/100
- 115d 1181 Cardbus Ethernet 10/100
- 1179 0181 Cardbus Ethernet 10/100
- 8086 8181 EtherExpress PRO/100 Mobile CardBus 32 Adapter
- 8086 9181 EtherExpress PRO/100 Mobile CardBus 32 Adapter
- 0005 Cardbus Ethernet 10/100
- 1014 0182 10/100 EtherJet Cardbus Adapter
- 1014 1182 10/100 EtherJet Cardbus Adapter
- 115d 0182 Cardbus Ethernet 10/100
- 115d 1182 Cardbus Ethernet 10/100
- 0007 Cardbus Ethernet 10/100
- 1014 0182 10/100 EtherJet Cardbus Adapter
- 1014 1182 10/100 EtherJet Cardbus Adapter
- 115d 0182 Cardbus Ethernet 10/100
- 115d 1182 Cardbus Ethernet 10/100
- 000b Cardbus Ethernet 10/100
- 1014 0183 10/100 EtherJet Cardbus Adapter
- 115d 0183 Cardbus Ethernet 10/100
- 000c Mini-PCI V.90 56k Modem
- 000f Cardbus Ethernet 10/100
- 1014 0183 10/100 EtherJet Cardbus Adapter
- 115d 0183 Cardbus Ethernet 10/100
- 00d4 Mini-PCI K56Flex Modem
- 0101 Cardbus 56k modem
- 115d 1081 Cardbus 56k Modem
- 0103 Cardbus Ethernet + 56k Modem
- 1014 9181 Cardbus 56k Modem
- 1115 1181 Cardbus Ethernet 100 + 56k Modem
- 115d 1181 CBEM56G-100 Ethernet + 56k Modem
- 8086 9181 PRO/100 LAN + Modem56 CardBus
-115e Peer Protocols Inc
-115f Maxtor Corporation
-1160 Megasoft Inc
-1161 PFU Limited
-1162 OA Laboratory Co Ltd
-1163 Rendition
- 0001 Verite 1000
- 2000 Verite V2000/V2100/V2200
- 1092 2000 Stealth II S220
-1164 Advanced Peripherals Technologies
-1165 Imagraph Corporation
- 0001 Motion TPEG Recorder/Player with audio
-1166 ServerWorks
- 0000 CMIC-LE
- 0005 CNB20-LE Host Bridge
- 0006 CNB20HE Host Bridge
- 0007 CNB20-LE Host Bridge
- 0008 CNB20HE Host Bridge
- 0009 CNB20LE Host Bridge
- 0010 CIOB30
- 0011 CMIC-HE
- 0012 CMIC-WS Host Bridge (GC-LE chipset)
- 0013 CNB20-HE Host Bridge
- 0014 CMIC-LE Host Bridge (GC-LE chipset)
- 0015 CMIC-GC Host Bridge
- 0016 CMIC-GC Host Bridge
- 0017 GCNB-LE Host Bridge
- 0101 CIOB-X2 PCI-X I/O Bridge
- 0110 CIOB-E I/O Bridge with Gigabit Ethernet
- 0200 OSB4 South Bridge
- 0201 CSB5 South Bridge
- 4c53 1080 CT8 mainboard
- 0203 CSB6 South Bridge
- 0211 OSB4 IDE Controller
- 0212 CSB5 IDE Controller
- 4c53 1080 CT8 mainboard
- 0213 CSB6 RAID/IDE Controller
- 0217 CSB6 IDE Controller
- 0220 OSB4/CSB5 OHCI USB Controller
- 4c53 1080 CT8 mainboard
- 0221 CSB6 OHCI USB Controller
- 0225 CSB5 LPC bridge
-# cancelled
- 4c53 1080 CT8 mainboard
- 0227 GCLE-2 Host Bridge
- 0230 CSB5 LPC bridge
- 4c53 1080 CT8 mainboard
- 0240 K2 SATA
- 0241 K2 SATA
- 0242 K2 SATA
-1167 Mutoh Industries Inc
-1168 Thine Electronics Inc
-1169 Centre for Development of Advanced Computing
-116a Polaris Communications
- 6100 Bus/Tag Channel
- 6800 Escon Channel
- 7100 Bus/Tag Channel
- 7800 Escon Channel
-116b Connectware Inc
-116c Intelligent Resources Integrated Systems
-116d Martin-Marietta
-116e Electronics for Imaging
-116f Workstation Technology
-1170 Inventec Corporation
-1171 Loughborough Sound Images Plc
-1172 Altera Corporation
-1173 Adobe Systems, Inc
-1174 Bridgeport Machines
-1175 Mitron Computer Inc.
-1176 SBE Incorporated
-1177 Silicon Engineering
-1178 Alfa, Inc.
- afa1 Fast Ethernet Adapter
-1179 Toshiba America Info Systems
- 0103 EX-IDE Type-B
- 0404 DVD Decoder card
- 0406 Tecra Video Capture device
- 0407 DVD Decoder card (Version 2)
- 0601 CPU to PCI bridge
- 0603 ToPIC95 PCI to CardBus Bridge for Notebooks
- 060a ToPIC95
- 060f ToPIC97
- 0617 ToPIC100 PCI to Cardbus Bridge with ZV Support
- 0618 CPU to PCI and PCI to ISA bridge
-# Claimed to be Lucent DSP1645 [Mars], but that's apparently incorrect. Does anyone know the correct ID?
- 0701 FIR Port
- 0804 TC6371AF SmartMedia Controller
- 0805 SD TypA Controller
- 0d01 FIR Port Type-DO
- 1179 0001 FIR Port Type-DO
-117a A-Trend Technology
-117b L G Electronics, Inc.
-117c Atto Technology
-117d Becton & Dickinson
-117e T/R Systems
-117f Integrated Circuit Systems
-1180 Ricoh Co Ltd
- 0465 RL5c465
- 0466 RL5c466
- 0475 RL5c475
- 144d c006 vpr Matrix 170B4 CardBus bridge
- 0476 RL5c476 II
- 1014 0185 ThinkPad A/T/X Series
- 104d 80df Vaio PCG-FX403
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 14ef 0220 PCD-RP-220S
- 0477 RL5c477
- 0478 RL5c478
- 1014 0184 ThinkPad A30p (2653-64G)
- 0522 R5C522 IEEE 1394 Controller
- 1014 01cf ThinkPad A30p (2653-64G)
- 0551 R5C551 IEEE 1394 Controller
- 144d c006 vpr Matrix 170B4
- 0552 R5C552 IEEE 1394 Controller
- 1014 0511 ThinkPad A/T/X Series
- 0576 R5C576 SD Bus Host Adapter
- 0592 R5C592 Memory Stick Bus Host Adapter
-1181 Telmatics International
-1183 Fujikura Ltd
-1184 Forks Inc
-1185 Dataworld International Ltd
-1186 D-Link System Inc
- 0100 DC21041
- 1002 DL10050 Sundance Ethernet
- 1186 1002 DFE-550TX
- 1186 1012 DFE-580TX
- 1025 AirPlus Xtreme G DWL-G650 Adapter
- 1026 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 1043 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 1300 RTL8139 Ethernet
- 1186 1300 DFE-538TX 10/100 Ethernet Adapter
- 1186 1301 DFE-530TX+ 10/100 Ethernet Adapter
- 1340 DFE-690TXD CardBus PC Card
- 1541 DFE-680TXD CardBus PC Card
- 1561 DRP-32TXD Cardbus PC Card
- 2027 AirPlus Xtreme G DWL-G520 Adapter
- 3203 AirPlus Xtreme G DWL-G520 Adapter
- 3300 DWL-510 2.4GHz Wireless PCI Adapter
- 3a03 AirPro DWL-A650 Wireless Cardbus Adapter(rev.B)
- 3a04 AirPro DWL-AB650 Multimode Wireless Cardbus Adapter
- 3a05 AirPro DWL-AB520 Multimode Wireless PCI Adapter
- 3a07 AirXpert DWL-AG650 Wireless Cardbus Adapter
- 3a08 AirXpert DWL-AG520 Wireless PCI Adapter
- 3a10 AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B)
- 3a11 AirXpert DWL-AG520 Wireless PCI Adapter(rev.B)
- 3a12 AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)
- 3a13 AirPlus DWL-G520 Wireless PCI Adapter(rev.B)
- 3a14 AirPremier DWL-AG530 Wireless PCI Adapter
- 3a63 AirXpert DWL-AG660 Wireless Cardbus Adapter
- 3b05 DWL-G650+ CardBus PC Card
- 4000 DL2000-based Gigabit Ethernet
- 4300 DGE-528T Gigabit Ethernet Adapter
- 4c00 Gigabit Ethernet Adapter
- 1186 4c00 DGE-530T Gigabit Ethernet Adapter
- 8400 D-Link DWL-650+ CardBus PC Card
-1187 Advanced Technology Laboratories, Inc.
-1188 Shima Seiki Manufacturing Ltd.
-1189 Matsushita Electronics Co Ltd
-118a Hilevel Technology
-118b Hypertec Pty Limited
-118c Corollary, Inc
- 0014 PCIB [C-bus II to PCI bus host bridge chip]
- 1117 Intel 8-way XEON Profusion Chipset [Cache Coherency Filter]
-118d BitFlow Inc
- 0001 Raptor-PCI framegrabber
- 0012 Model 12 Road Runner Frame Grabber
- 0014 Model 14 Road Runner Frame Grabber
- 0024 Model 24 Road Runner Frame Grabber
- 0044 Model 44 Road Runner Frame Grabber
- 0112 Model 12 Road Runner Frame Grabber
- 0114 Model 14 Road Runner Frame Grabber
- 0124 Model 24 Road Runner Frame Grabber
- 0144 Model 44 Road Runner Frame Grabber
- 0212 Model 12 Road Runner Frame Grabber
- 0214 Model 14 Road Runner Frame Grabber
- 0224 Model 24 Road Runner Frame Grabber
- 0244 Model 44 Road Runner Frame Grabber
- 0312 Model 12 Road Runner Frame Grabber
- 0314 Model 14 Road Runner Frame Grabber
- 0324 Model 24 Road Runner Frame Grabber
- 0344 Model 44 Road Runner Frame Grabber
-118e Hermstedt GmbH
-118f Green Logic
-1190 Tripace
- c731 TP-910/920/940 PCI Ultra(Wide) SCSI Adapter
-1191 Artop Electronic Corp
- 0003 SCSI Cache Host Adapter
- 0004 ATP8400
- 0005 ATP850UF
- 0006 ATP860 NO-BIOS
- 0007 ATP860
- 0008 ATP865 NO-ROM
- 0009 ATP865
- 8002 AEC6710 SCSI-2 Host Adapter
- 8010 AEC6712UW SCSI
- 8020 AEC6712U SCSI
- 8030 AEC6712S SCSI
- 8040 AEC6712D SCSI
- 8050 AEC6712SUW SCSI
- 8060 AEC6712 SCSI
- 8080 AEC67160 SCSI
- 8081 AEC67160S SCSI
- 808a AEC67162 2-ch. LVD SCSI
-1192 Densan Company Ltd
-1193 Zeitnet Inc.
- 0001 1221
- 0002 1225
-1194 Toucan Technology
-1195 Ratoc System Inc
-1196 Hytec Electronics Ltd
-1197 Gage Applied Sciences, Inc.
- 010c CompuScope 82G 8bit 2GS/s Analog Input Card
-1198 Lambda Systems Inc
-1199 Attachmate Corporation
-119a Mind Share, Inc.
-119b Omega Micro Inc.
- 1221 82C092G
-119c Information Technology Inst.
-119d Bug, Inc. Sapporo Japan
-119e Fujitsu Microelectronics Ltd.
- 0001 FireStream 155
- 0003 FireStream 50
-119f Bull HN Information Systems
-11a0 Convex Computer Corporation
-11a1 Hamamatsu Photonics K.K.
-11a2 Sierra Research and Technology
-11a3 Deuretzbacher GmbH & Co. Eng. KG
-11a4 Barco Graphics NV
-11a5 Microunity Systems Eng. Inc
-11a6 Pure Data Ltd.
-11a7 Power Computing Corp.
-11a8 Systech Corp.
-11a9 InnoSys Inc.
- 4240 AMCC S933Q Intelligent Serial Card
-11aa Actel
-# Formerly Galileo Technology, Inc.
-11ab Marvell Technology Group Ltd.
- 0146 GT-64010/64010A System Controller
- 138f W8300 802.11 Adapter (rev 07)
- 1fa6 Marvell W8300 802.11 Adapter
- 1fa7 88W8310 and 88W8000G [Libertas] 802.11g client chipset
- 4320 Gigabit Ethernet Controller
- 1019 0f38 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
- 1019 8001 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
- 1043 173c Marvell 88E8001 Gigabit Ethernet Controller (Asus)
- 1043 811a Marvell 88E8001 Gigabit Ethernet Controller (Asus)
- 105b 0c19 Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)
- 10b8 b452 SMC EZ Card 1000 (SMC9452TXV.2)
- 11ab 0121 Marvell RDK-8001
- 11ab 0321 Marvell RDK-8003
- 11ab 1021 Marvell RDK-8010
- 11ab 5021 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)
- 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)
- 1458 e000 Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)
- 147b 1406 Marvell 88E8001 Gigabit Ethernet Controller (Abit)
- 15d4 0047 Marvell 88E8001 Gigabit Ethernet Controller (Iwill)
- 1695 9025 Marvell 88E8001 Gigabit Ethernet Controller (Epox)
- 17f2 1c03 Marvell 88E8001 Gigabit Ethernet Controller (Albatron)
- 270f 2803 Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)
- 4350 Fast Ethernet Controller
- 1179 0001 Marvell 88E8035 Fast Ethernet Controller (Toshiba)
- 11ab 3521 Marvell RDK-8035
- 1854 000d Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 000e Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 000f Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0011 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0012 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0016 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0017 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0018 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0019 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 001c Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 001e Marvell 88E8035 Fast Ethernet Controller (LGE)
- 1854 0020 Marvell 88E8035 Fast Ethernet Controller (LGE)
- 4351 Fast Ethernet Controller
- 107b 4009 Marvell 88E8036 Fast Ethernet Controller (Wistron)
- 10f7 8338 Marvell 88E8036 Fast Ethernet Controller (Panasonic)
- 1179 0001 Marvell 88E8036 Fast Ethernet Controller (Toshiba)
- 1179 ff00 Marvell 88E8036 Fast Ethernet Controller (Compal)
- 1179 ff10 Marvell 88E8036 Fast Ethernet Controller (Inventec)
- 11ab 3621 Marvell RDK-8036
- 13d1 ac12 Abocom EFE3K - 10/100 Ethernet Expresscard
- 161f 203d Marvell 88E8036 Fast Ethernet Controller (Arima)
- 1854 000d Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 000e Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 000f Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0011 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0012 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0016 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0017 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0018 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0019 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 001c Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 001e Marvell 88E8036 Fast Ethernet Controller (LGE)
- 1854 0020 Marvell 88E8036 Fast Ethernet Controller (LGE)
- 4360 Gigabit Ethernet Controller
- 1043 8134 Marvell 88E8052 Gigabit Ethernet Controller (Asus)
- 107b 4009 Marvell 88E8052 Gigabit Ethernet Controller (Wistron)
- 11ab 5221 Marvell RDK-8052
- 1458 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
- 1462 052c Marvell 88E8052 Gigabit Ethernet Controller (MSI)
- 1849 8052 Marvell 88E8052 Gigabit Ethernet Controller (ASRock)
- 1940 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
- a0a0 0509 Marvell 88E8052 Gigabit Ethernet Controller (Aopen)
- 4361 Gigabit Ethernet Controller
- 107b 3015 Marvell 88E8050 Gigabit Ethernet Controller (Gateway)
- 11ab 5021 Marvell 88E8050 Gigabit Ethernet Controller (Intel)
- 8086 3063 D925XCVLK mainboard
- 4362 Gigabit Ethernet Controller
- 103c 2a0d Marvell 88E8053 Gigabit Ethernet Controller (Asus)
- 1043 8142 Marvell 88E8053 Gigabit Ethernet Controller (Asus)
- 109f 3197 Marvell 88E8053 Gigabit Ethernet Controller (Trigem)
- 10f7 8338 Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)
- 10fd a430 Marvell 88E8053 Gigabit Ethernet Controller (SOYO)
- 1179 0001 Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)
- 1179 ff00 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
- 1179 ff10 Marvell 88E8053 Gigabit Ethernet Controller (Inventec)
- 11ab 5321 Marvell RDK-8053
- 1297 c240 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c241 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c242 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c243 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 1297 c244 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
- 13d1 ac11 Abocom EGE5K - Giga Ethernet Expresscard
- 1458 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
- 1462 058c Marvell 88E8053 Gigabit Ethernet Controller (MSI)
- 14c0 0012 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
- 1558 04a0 Marvell 88E8053 Gigabit Ethernet Controller (Clevo)
- 15bd 1003 Marvell 88E8053 Gigabit Ethernet Controller (DFI)
- 161f 203c Marvell 88E8053 Gigabit Ethernet Controller (Arima)
- 161f 203d Marvell 88E8053 Gigabit Ethernet Controller (Arima)
- 1695 9029 Marvell 88E8053 Gigabit Ethernet Controller (Epox)
- 17f2 2c08 Marvell 88E8053 Gigabit Ethernet Controller (Albatron)
- 17ff 0585 Marvell 88E8053 Gigabit Ethernet Controller (Quanta)
- 1849 8053 Marvell 88E8053 Gigabit Ethernet Controller (ASRock)
- 1854 000b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 000c Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0010 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0013 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0014 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0015 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001a Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001d Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 001f Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0021 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1854 0022 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
- 1940 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
- 270f 2801 Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)
- a0a0 0506 Marvell 88E8053 Gigabit Ethernet Controller (Aopen)
- 4611 GT-64115 System Controller
- 4620 GT-64120/64120A/64121A System Controller
- 4801 GT-48001
- 5005 Belkin F5D5005 Gigabit Desktop Network PCI Card
- 5040 MV88SX5040 4-port SATA I PCI-X Controller
- 5041 MV88SX5041 4-port SATA I PCI-X Controller
- 5080 MV88SX5080 8-port SATA I PCI-X Controller
- 5081 MV88SX5081 8-port SATA I PCI-X Controller
- 6041 MV88SX6041 4-port SATA II PCI-X Controller
- 6081 MV88SX6081 8-port SATA II PCI-X Controller
- 6460 MV64360/64361/64362 System Controller
- f003 GT-64010 Primary Image Piranha Image Generator
-11ac Canon Information Systems Research Aust.
-11ad Lite-On Communications Inc
- 0002 LNE100TX
- 11ad 0002 LNE100TX
- 11ad 0003 LNE100TX
- 11ad f003 LNE100TX
- 11ad ffff LNE100TX
- 1385 f004 FA310TX
- c115 LNE100TX [Linksys EtherFast 10/100]
- 11ad c001 LNE100TX [ver 2.0]
-11ae Aztech System Ltd
-11af Avid Technology Inc.
- 0001 [Cinema]
-11b0 V3 Semiconductor Inc.
- 0002 V300PSC
- 0292 V292PBC [Am29030/40 Bridge]
- 0960 V96xPBC
- c960 V96DPC
-11b1 Apricot Computers
-11b2 Eastman Kodak
-11b3 Barr Systems Inc.
-11b4 Leitch Technology International
-11b5 Radstone Technology Plc
-11b6 United Video Corp
-11b7 Motorola
-11b8 XPoint Technologies, Inc
- 0001 Quad PeerMaster
-11b9 Pathlight Technology Inc.
- c0ed SSA Controller
-11ba Videotron Corp
-11bb Pyramid Technology
-11bc Network Peripherals Inc
- 0001 NP-PCI
-11bd Pinnacle Systems Inc.
-11be International Microcircuits Inc
-11bf Astrodesign, Inc.
-11c0 Hewlett Packard
-11c1 Agere Systems (former Lucent Microelectronics)
- 0440 56k WinModem
- 1033 8015 LT WinModem 56k Data+Fax+Voice+Dsvd
- 1033 8047 LT WinModem 56k Data+Fax+Voice+Dsvd
- 1033 804f LT WinModem 56k Data+Fax+Voice+Dsvd
- 10cf 102c LB LT Modem V.90 56k
- 10cf 104a BIBLO LT Modem 56k
- 10cf 105f LB2 LT Modem V.90 56k
- 1179 0001 Internal V.90 Modem
- 11c1 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 122d 4101 MDP7800-U Modem
- 122d 4102 MDP7800SP-U Modem
- 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0441 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0450 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 f100 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 f101 LT WinModem 56k Data+Fax+Voice+Dsvd
- 144d 2101 LT56PV Modem
- 149f 0440 LT WinModem 56k Data+Fax+Voice+Dsvd
- 0441 56k WinModem
- 1033 804d LT WinModem 56k Data+Fax
- 1033 8065 LT WinModem 56k Data+Fax
- 1092 0440 Supra 56i
- 1179 0001 Internal V.90 Modem
- 11c1 0440 LT WinModem 56k Data+Fax
- 11c1 0441 LT WinModem 56k Data+Fax
- 122d 4100 MDP7800-U Modem
- 13e0 0040 LT WinModem 56k Data+Fax
- 13e0 0100 LT WinModem 56k Data+Fax
- 13e0 0410 LT WinModem 56k Data+Fax
- 13e0 0420 TelePath Internet 56k WinModem
- 13e0 0440 LT WinModem 56k Data+Fax
- 13e0 0443 LT WinModem 56k Data+Fax
- 13e0 f102 LT WinModem 56k Data+Fax
- 1416 9804 CommWave 56k Modem
- 141d 0440 LT WinModem 56k Data+Fax
- 144f 0441 Lucent 56k V.90 DF Modem
- 144f 0449 Lucent 56k V.90 DF Modem
- 144f 110d Lucent Win Modem
- 1468 0441 Presario 56k V.90 DF Modem
- 1668 0440 Lucent Win Modem
- 0442 56k WinModem
- 11c1 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 11c1 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0412 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13fc 2471 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 144d 2104 LT56PT Modem
- 144f 1104 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 149f 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 1668 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 0443 LT WinModem
- 0444 LT WinModem
- 0445 LT WinModem
- 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card)
- 8086 2204 PRO/100+ MiniPCI on Armada E500
- 0446 LT WinModem
- 0447 LT WinModem
- 0448 WinModem 56k
- 1014 0131 Lucent Win Modem
- 1033 8066 LT WinModem 56k Data+Fax+Voice+Dsvd
- 13e0 0030 56k Voice Modem
- 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd
-# Actiontech eth+modem card as used by Dell &c.
- 1668 2400 LT WinModem 56k (MiniPCI Ethernet+Modem)
- 0449 WinModem 56k
- 0e11 b14d 56k V.90 Modem
- 13e0 0020 LT WinModem 56k Data+Fax
- 13e0 0041 TelePath Internet 56k WinModem
- 1436 0440 Lucent Win Modem
- 144f 0449 Lucent 56k V.90 DFi Modem
- 1468 0410 IBM ThinkPad T23 (2647-4MG)
- 1468 0440 Lucent Win Modem
- 1468 0449 Presario 56k V.90 DFi Modem
- 044a F-1156IV WinModem (V90, 56KFlex)
- 10cf 1072 LB Global LT Modem
- 13e0 0012 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 13e0 0042 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 144f 1005 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
- 044b LT WinModem
- 044c LT WinModem
- 044d LT WinModem
- 044e LT WinModem
- 044f V90 WildWire Modem
- 0450 LT WinModem
- 1033 80a8 Versa Note Vxi
- 144f 4005 Magnia SG20
- 0451 LT WinModem
- 0452 LT WinModem
- 0453 LT WinModem
- 0454 LT WinModem
- 0455 LT WinModem
- 0456 LT WinModem
- 0457 LT WinModem
- 0458 LT WinModem
- 0459 LT WinModem
- 045a LT WinModem
- 045c LT WinModem
- 0461 V90 WildWire Modem
- 0462 V90 WildWire Modem
- 0480 Venus Modem (V90, 56KFlex)
- 048c V.92 56K WinModem
-# InPorte Home Internal 56k Modem/fax/answering machine/SMS Features
- 048f V.92 56k WinModem
- 5801 USB
- 5802 USS-312 USB Controller
-# 4 port PCI USB Controller made by Agere (formely Lucent)
- 5803 USS-344S USB Controller
- 5811 FW323
- 8086 524c D865PERL mainboard
- dead 0800 FireWire Host Bus Adapter
- ab10 WL60010 Wireless LAN MAC
- ab11 WL60040 Multimode Wireles LAN MAC
- 11c1 ab12 WaveLAN 11abg Cardbus card (Model 1102)
- 11c1 ab13 WaveLAN 11abg MiniPCI card (Model 0512)
- 11c1 ab15 WaveLAN 11abg Cardbus card (Model 1106)
- 11c1 ab16 WaveLAN 11abg MiniPCI card (Model 0516)
- ab20 ORiNOCO PCI Adapter
- ab21 Agere Wireless PCI Adapter
- ab30 Hermes2 Mini-PCI WaveLAN a/b/g
- 14cd 2012 Hermes2 Mini-PCI WaveLAN a/b/g
-11c2 Sand Microelectronics
-11c3 NEC Corporation
-11c4 Document Technologies, Inc
-11c5 Shiva Corporation
-11c6 Dainippon Screen Mfg. Co. Ltd
-11c7 D.C.M. Data Systems
-11c8 Dolphin Interconnect Solutions AS
- 0658 PSB32 SCI-Adapter D31x
- d665 PSB64 SCI-Adapter D32x
- d667 PSB66 SCI-Adapter D33x
-11c9 Magma
- 0010 16-line serial port w/- DMA
- 0011 4-line serial port w/- DMA
-11ca LSI Systems, Inc
-11cb Specialix Research Ltd.
- 2000 PCI_9050
- 11cb 0200 SX
- 11cb b008 I/O8+
- 4000 SUPI_1
- 8000 T225
-11cc Michels & Kleberhoff Computer GmbH
-11cd HAL Computer Systems, Inc.
-11ce Netaccess
-11cf Pioneer Electronic Corporation
-11d0 Lockheed Martin Federal Systems-Manassas
-11d1 Auravision
- 01f7 VxP524
-11d2 Intercom Inc.
-11d3 Trancell Systems Inc
-11d4 Analog Devices
- 1535 Blackfin BF535 processor
- 1805 SM56 PCI modem
- 1889 AD1889 sound chip
-11d5 Ikon Corporation
- 0115 10115
- 0117 10117
-11d6 Tekelec Telecom
-11d7 Trenton Technology, Inc.
-11d8 Image Technologies Development
-11d9 TEC Corporation
-11da Novell
-11db Sega Enterprises Ltd
-11dc Questra Corporation
-11dd Crosfield Electronics Limited
-11de Zoran Corporation
- 6057 ZR36057PQC Video cutting chipset
- 1031 7efe DC10 Plus
- 1031 fc00 MiroVIDEO DC50, Motion JPEG Capture/CODEC Board
- 13ca 4231 JPEG/TV Card
- 6120 ZR36120
- 1328 f001 Cinemaster C DVD Decoder
-11df New Wave PDG
-11e0 Cray Communications A/S
-11e1 GEC Plessey Semi Inc.
-11e2 Samsung Information Systems America
-11e3 Quicklogic Corporation
- 5030 PC Watchdog
-11e4 Second Wave Inc
-11e5 IIX Consulting
-11e6 Mitsui-Zosen System Research
-11e7 Toshiba America, Elec. Company
-11e8 Digital Processing Systems Inc.
-11e9 Highwater Designs Ltd.
-11ea Elsag Bailey
-11eb Formation Inc.
-11ec Coreco Inc
-11ed Mediamatics
-11ee Dome Imaging Systems Inc
-11ef Nicolet Technologies B.V.
-11f0 Compu-Shack
- 4231 FDDI
- 4232 FASTline UTP Quattro
- 4233 FASTline FO
- 4234 FASTline UTP
- 4235 FASTline-II UTP
- 4236 FASTline-II FO
- 4731 GIGAline
-11f1 Symbios Logic Inc
-11f2 Picture Tel Japan K.K.
-11f3 Keithley Metrabyte
-11f4 Kinetic Systems Corporation
- 2915 CAMAC controller
-11f5 Computing Devices International
-11f6 Compex
- 0112 ENet100VG4
- 0113 FreedomLine 100
- 1401 ReadyLink 2000
- 2011 RL100-ATX 10/100
- 11f6 2011 RL100-ATX
- 2201 ReadyLink 100TX (Winbond W89C840)
- 11f6 2011 ReadyLink 100TX
- 9881 RL100TX Fast Ethernet
-11f7 Scientific Atlanta
-11f8 PMC-Sierra Inc.
- 7375 PM7375 [LASAR-155 ATM SAR]
-11f9 I-Cube Inc
-11fa Kasan Electronics Company, Ltd.
-11fb Datel Inc
-11fc Silicon Magic
-11fd High Street Consultants
-11fe Comtrol Corporation
- 0001 RocketPort 32 port w/external I/F
- 0002 RocketPort 8 port w/external I/F
- 0003 RocketPort 16 port w/external I/F
- 0004 RocketPort 4 port w/quad cable
- 0005 RocketPort 8 port w/octa cable
- 0006 RocketPort 8 port w/RJ11 connectors
- 0007 RocketPort 4 port w/RJ11 connectors
- 0008 RocketPort 8 port w/ DB78 SNI (Siemens) connector
- 0009 RocketPort 16 port w/ DB78 SNI (Siemens) connector
- 000a RocketPort Plus 4 port
- 000b RocketPort Plus 8 port
- 000c RocketModem 6 port
- 000d RocketModem 4-port
- 000e RocketPort Plus 2 port RS232
- 000f RocketPort Plus 2 port RS422
- 0801 RocketPort UPCI 32 port w/external I/F
- 0802 RocketPort UPCI 8 port w/external I/F
- 0803 RocketPort UPCI 16 port w/external I/F
- 0805 RocketPort UPCI 8 port w/octa cable
- 080c RocketModem III 8 port
- 080d RocketModem III 4 port
- 0903 RocketPort Compact PCI 16 port w/external I/F
- 8015 RocketPort 4-port UART 16954
-11ff Scion Corporation
- 0003 AG-5
-1200 CSS Corporation
-1201 Vista Controls Corp
-1202 Network General Corp.
- 4300 Gigabit Ethernet Adapter
- 1202 9841 SK-9841 LX
- 1202 9842 SK-9841 LX dual link
- 1202 9843 SK-9843 SX
- 1202 9844 SK-9843 SX dual link
-1203 Bayer Corporation, Agfa Division
-1204 Lattice Semiconductor Corporation
-1205 Array Corporation
-1206 Amdahl Corporation
-1208 Parsytec GmbH
- 4853 HS-Link Device
-1209 SCI Systems Inc
-120a Synaptel
-120b Adaptive Solutions
-120c Technical Corp.
-120d Compression Labs, Inc.
-120e Cyclades Corporation
- 0100 Cyclom-Y below first megabyte
- 0101 Cyclom-Y above first megabyte
- 0102 Cyclom-4Y below first megabyte
- 0103 Cyclom-4Y above first megabyte
- 0104 Cyclom-8Y below first megabyte
- 0105 Cyclom-8Y above first megabyte
- 0200 Cyclades-Z below first megabyte
- 0201 Cyclades-Z above first megabyte
- 0300 PC300/RSV or /X21 (2 ports)
- 0301 PC300/RSV or /X21 (1 port)
- 0310 PC300/TE (2 ports)
- 0311 PC300/TE (1 port)
- 0320 PC300/TE-M (2 ports)
- 0321 PC300/TE-M (1 port)
- 0400 PC400
-120f Essential Communications
- 0001 Roadrunner serial HIPPI
-1210 Hyperparallel Technologies
-1211 Braintech Inc
-1212 Kingston Technology Corp.
-1213 Applied Intelligent Systems, Inc.
-1214 Performance Technologies, Inc.
-1215 Interware Co., Ltd
-1216 Purup Prepress A/S
-1217 O2 Micro, Inc.
- 6729 OZ6729
- 673a OZ6730
- 6832 OZ6832/6833 CardBus Controller
- 6836 OZ6836/6860 CardBus Controller
- 6872 OZ6812 CardBus Controller
- 6925 OZ6922 CardBus Controller
- 6933 OZ6933/711E1 CardBus/SmartCardBus Controller
- 1025 1016 Travelmate 612 TX
- 6972 OZ601/6912/711E0 CardBus/SmartCardBus Controller
- 1014 020c ThinkPad R30
- 1179 0001 Magnia Z310
- 7110 OZ711Mx 4-in-1 MemoryCardBus Accelerator
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 7112 OZ711EC1/M1 SmartCardBus/MemoryCardBus Controller
- 7113 OZ711EC1 SmartCardBus Controller
- 7114 OZ711M1/MC1 4-in-1 MemoryCardBus Controller
- 7134 OZ711MP1/MS1 MemoryCardBus Controller
- 71e2 OZ711E2 SmartCardBus Controller
- 7212 OZ711M2 4-in-1 MemoryCardBus Controller
- 7213 OZ6933E CardBus Controller
- 7223 OZ711M3/MC3 4-in-1 MemoryCardBus Controller
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 7233 OZ711MP3/MS3 4-in-1 MemoryCardBus Controller
-1218 Hybricon Corp.
-1219 First Virtual Corporation
-121a 3Dfx Interactive, Inc.
- 0001 Voodoo
- 0002 Voodoo 2
- 0003 Voodoo Banshee
- 1092 0003 Monster Fusion
- 1092 4000 Monster Fusion
- 1092 4002 Monster Fusion
- 1092 4801 Monster Fusion AGP
- 1092 4803 Monster Fusion AGP
- 1092 8030 Monster Fusion
- 1092 8035 Monster Fusion AGP
- 10b0 0001 Dragon 4000
- 1102 1018 3D Blaster Banshee VE
- 121a 0001 Voodoo Banshee AGP
- 121a 0003 Voodoo Banshee AGP SGRAM
- 121a 0004 Voodoo Banshee
- 139c 0016 Raven
- 139c 0017 Raven
- 14af 0002 Maxi Gamer Phoenix
- 0004 Voodoo Banshee [Velocity 100]
- 0005 Voodoo 3
- 121a 0004 Voodoo3 AGP
- 121a 0030 Voodoo3 AGP
- 121a 0031 Voodoo3 AGP
- 121a 0034 Voodoo3 AGP
- 121a 0036 Voodoo3 2000 PCI
- 121a 0037 Voodoo3 AGP
- 121a 0038 Voodoo3 AGP
- 121a 003a Voodoo3 AGP
- 121a 0044 Voodoo3
- 121a 004b Velocity 100
- 121a 004c Velocity 200
- 121a 004d Voodoo3 AGP
- 121a 004e Voodoo3 AGP
- 121a 0051 Voodoo3 AGP
- 121a 0052 Voodoo3 AGP
- 121a 0060 Voodoo3 3500 TV (NTSC)
- 121a 0061 Voodoo3 3500 TV (PAL)
- 121a 0062 Voodoo3 3500 TV (SECAM)
- 0009 Voodoo 4 / Voodoo 5
- 121a 0003 Voodoo5 PCI 5500
- 121a 0009 Voodoo5 AGP 5500/6000
- 0057 Voodoo 3/3000 [Avenger]
-121b Advanced Telecommunications Modules
-121c Nippon Texaco., Ltd
-121d Lippert Automationstechnik GmbH
-121e CSPI
-121f Arcus Technology, Inc.
-1220 Ariel Corporation
- 1220 AMCC 5933 TMS320C80 DSP/Imaging board
-1221 Contec Co., Ltd
-1222 Ancor Communications, Inc.
-1223 Artesyn Communication Products
- 0003 PM/Link
- 0004 PM/T1
- 0005 PM/E1
- 0008 PM/SLS
- 0009 BajaSpan Resource Target
- 000a BajaSpan Section 0
- 000b BajaSpan Section 1
- 000c BajaSpan Section 2
- 000d BajaSpan Section 3
- 000e PM/PPC
-1224 Interactive Images
-1225 Power I/O, Inc.
-1227 Tech-Source
- 0006 Raptor GFX 8P
-1228 Norsk Elektro Optikk A/S
-1229 Data Kinesis Inc.
-122a Integrated Telecom
-122b LG Industrial Systems Co., Ltd
-122c Sican GmbH
-122d Aztech System Ltd
- 1206 368DSP
- 1400 Trident PCI288-Q3DII (NX)
- 50dc 3328 Audio
- 122d 0001 3328 Audio
- 80da 3328 Audio
- 122d 0001 3328 Audio
-122e Xyratex
-122f Andrew Corporation
-1230 Fishcamp Engineering
-1231 Woodward McCoach, Inc.
-1232 GPT Limited
-1233 Bus-Tech, Inc.
-1234 Technical Corp.
-1235 Risq Modular Systems, Inc.
-1236 Sigma Designs Corporation
- 0000 RealMagic64/GX
- 6401 REALmagic 64/GX (SD 6425)
-1237 Alta Technology Corporation
-1238 Adtran
-1239 3DO Company
-123a Visicom Laboratories, Inc.
-123b Seeq Technology, Inc.
-123c Century Systems, Inc.
-123d Engineering Design Team, Inc.
- 0000 EasyConnect 8/32
- 0002 EasyConnect 8/64
- 0003 EasyIO
-123e Simutech, Inc.
-123f C-Cube Microsystems
- 00e4 MPEG
- 8120 E4?
- 11bd 0006 DV500 E4
- 11bd 000a DV500 E4
- 11bd 000f DV500 E4
- 8888 Cinemaster C 3.0 DVD Decoder
- 1002 0001 Cinemaster C 3.0 DVD Decoder
- 1002 0002 Cinemaster C 3.0 DVD Decoder
- 1328 0001 Cinemaster C 3.0 DVD Decoder
-1240 Marathon Technologies Corp.
-1241 DSC Communications
-# Formerly Jaycor Networks, Inc.
-1242 JNI Corporation
- 1560 JNIC-1560 PCI-X Fibre Channel Controller
- 1242 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter
- 1242 656a FCX-6562 PCI-X Fibre Channel Adapter
- 4643 FCI-1063 Fibre Channel Adapter
- 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter
- 656a FCX-6562 PCI-X Fibre Channel Adapter
-1243 Delphax
-1244 AVM Audiovisuelles MKTG & Computer System GmbH
- 0700 B1 ISDN
- 0800 C4 ISDN
- 0a00 A1 ISDN [Fritz]
- 1244 0a00 FRITZ!Card ISDN Controller
- 0e00 Fritz!PCI v2.0 ISDN
- 1100 C2 ISDN
- 1200 T1 ISDN
- 2700 Fritz!Card DSL SL
- 2900 Fritz!Card DSL v2.0
-1245 A.P.D., S.A.
-1246 Dipix Technologies, Inc.
-1247 Xylon Research, Inc.
-1248 Central Data Corporation
-1249 Samsung Electronics Co., Ltd.
-124a AEG Electrocom GmbH
-124b SBS/Greenspring Modular I/O
- 0040 PCI-40A or cPCI-200 Quad IndustryPack carrier
- 124b 9080 PCI9080 Bridge
-124c Solitron Technologies, Inc.
-124d Stallion Technologies, Inc.
- 0000 EasyConnection 8/32
- 0002 EasyConnection 8/64
- 0003 EasyIO
- 0004 EasyConnection/RA
-124e Cylink
-124f Infortrend Technology, Inc.
- 0041 IFT-2000 Series RAID Controller
-1250 Hitachi Microcomputer System Ltd
-1251 VLSI Solutions Oy
-1253 Guzik Technical Enterprises
-1254 Linear Systems Ltd.
-1255 Optibase Ltd
- 1110 MPEG Forge
- 1210 MPEG Fusion
- 2110 VideoPlex
- 2120 VideoPlex CC
- 2130 VideoQuest
-1256 Perceptive Solutions, Inc.
- 4201 PCI-2220I
- 4401 PCI-2240I
- 5201 PCI-2000
-1257 Vertex Networks, Inc.
-1258 Gilbarco, Inc.
-1259 Allied Telesyn International
- 2560 AT-2560 Fast Ethernet Adapter (i82557B)
- a117 RTL81xx Fast Ethernet
- a120 21x4x DEC-Tulip compatible 10/100 Ethernet
-125a ABB Power Systems
-125b Asix Electronics Corporation
- 1400 ALFA GFC2204 Fast Ethernet
-125c Aurora Technologies, Inc.
- 0101 Saturn 4520P
- 0640 Aries 16000P
-125d ESS Technology
- 0000 ES336H Fax Modem (Early Model)
- 1948 Solo?
- 1968 ES1968 Maestro 2
- 1028 0085 ES1968 Maestro-2 PCI
- 1033 8051 ES1968 Maestro-2 Audiodrive
- 1969 ES1969 Solo-1 Audiodrive
- 1014 0166 ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard
- 125d 8888 Solo-1 Audio Adapter
- 153b 111b Terratec 128i PCI
- 1978 ES1978 Maestro 2E
- 0e11 b112 Armada M700/E500
- 1033 803c ES1978 Maestro-2E Audiodrive
- 1033 8058 ES1978 Maestro-2E Audiodrive
- 1092 4000 Monster Sound MX400
- 1179 0001 ES1978 Maestro-2E Audiodrive
- 1988 ES1988 Allegro-1
- 1092 4100 Sonic Impact S100
- 125d 1988 ESS Allegro-1 Audiodrive
- 1989 ESS Modem
- 125d 1989 ESS Modem
- 1998 ES1983S Maestro-3i PCI Audio Accelerator
- 1028 00b1 Latitude C600
- 1028 00e6 ES1983S Maestro-3i (Dell Inspiron 8100)
- 1999 ES1983S Maestro-3i PCI Modem Accelerator
- 199a ES1983S Maestro-3i PCI Audio Accelerator
- 199b ES1983S Maestro-3i PCI Modem Accelerator
- 2808 ES336H Fax Modem (Later Model)
- 2838 ES2838/2839 SuperLink Modem
- 2898 ES2898 Modem
- 125d 0424 ES56-PI Data Fax Modem
- 125d 0425 ES56T-PI Data Fax Modem
- 125d 0426 ES56V-PI Data Fax Modem
- 125d 0427 VW-PI Data Fax Modem
- 125d 0428 ES56ST-PI Data Fax Modem
- 125d 0429 ES56SV-PI Data Fax Modem
- 147a c001 ES56-PI Data Fax Modem
- 14fe 0428 ES56-PI Data Fax Modem
- 14fe 0429 ES56-PI Data Fax Modem
-125e Specialvideo Engineering SRL
-125f Concurrent Technologies, Inc.
-1260 Intersil Corporation
- 3872 Prism 2.5 Wavelan chipset
- 1468 0202 LAN-Express IEEE 802.11b Wireless LAN
- 3873 Prism 2.5 Wavelan chipset
- 1186 3501 DWL-520 Wireless PCI Adapter
- 1186 3700 DWL-520 Wireless PCI Adapter, Rev E1
- 1385 4105 MA311 802.11b wireless adapter
- 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter
- 16a5 1601 AIR.mate PC-400 PCI Wireless LAN Adapter
- 1737 3874 WMP11 Wireless 802.11b PCI Adapter
- 8086 2513 Wireless 802.11b MiniPCI Adapter
- 3886 ISL3886 [Prism Javelin/Prism Xbow]
- 17cf 0037 Z-Com XG-901 and clones Wireless Adapter
- 3890 Intersil ISL3890 [Prism GT/Prism Duette]
- 10b8 2802 SMC2802W Wireless PCI Adapter
- 10b8 2835 SMC2835W Wireless Cardbus Adapter
- 10b8 a835 SMC2835W V2 Wireless Cardbus Adapter
- 1113 ee03 SMC2802W V2 Wireless PCI Adapter
- 1113 ee08 SMC2835W V3 EU Wireless Cardbus Adapter
- 1186 3202 DWL-G650 A1 Wireless Adapter
- 1259 c104 CG-WLCB54GT Wireless Adapter
- 1385 4800 WG511 Wireless Adapter
- 16a5 1605 ALLNET ALL0271 Wireless PCI Adapter
- 17cf 0014 Z-Com XG-600 and clones Wireless Adapter
- 17cf 0020 Z-Com XG-900 and clones Wireless Adapter
- 8130 HMP8130 NTSC/PAL Video Decoder
- 8131 HMP8131 NTSC/PAL Video Decoder
-1261 Matsushita-Kotobuki Electronics Industries, Ltd.
-1262 ES Computer Company, Ltd.
-1263 Sonic Solutions
-1264 Aval Nagasaki Corporation
-1265 Casio Computer Co., Ltd.
-1266 Microdyne Corporation
- 0001 NE10/100 Adapter (i82557B)
- 1910 NE2000Plus (RT8029) Ethernet Adapter
- 1266 1910 NE2000Plus Ethernet Adapter
-1267 S. A. Telecommunications
- 5352 PCR2101
- 5a4b Telsat Turbo
-1268 Tektronix
-1269 Thomson-CSF/TTM
-126a Lexmark International, Inc.
-126b Adax, Inc.
-126c Northern Telecom
- 1211 10/100BaseTX [RTL81xx]
- 126c 802.11b Wireless Ethernet Adapter
-126d Splash Technology, Inc.
-126e Sumitomo Metal Industries, Ltd.
-126f Silicon Motion, Inc.
- 0501 SM501 VoyagerGX
- 0710 SM710 LynxEM
- 0712 SM712 LynxEM+
- 0720 SM720 Lynx3DM
- 0730 SM731 Cougar3DR
- 0810 SM810 LynxE
- 0811 SM811 LynxE
- 0820 SM820 Lynx3D
- 0910 SM910
-1270 Olympus Optical Co., Ltd.
-1271 GW Instruments
-1272 Telematics International
-1273 Hughes Network Systems
- 0002 DirecPC
-1274 Ensoniq
- 1171 ES1373 [AudioPCI] (also Creative Labs CT5803)
- 1371 ES1371 [AudioPCI-97]
- 0e11 0024 AudioPCI on Motherboard Compaq Deskpro
- 0e11 b1a7 ES1371, ES1373 AudioPCI
- 1033 80ac ES1371, ES1373 AudioPCI
- 1042 1854 Tazer
- 107b 8054 Tabor2
- 1274 1371 Creative Sound Blaster AudioPCI64V, AudioPCI128
- 1462 6470 ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A
- 1462 6560 ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10
- 1462 6630 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 1.0A
- 1462 6631 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 1.0A
- 1462 6632 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 2.0A
- 1462 6633 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 2.0A
- 1462 6820 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00
- 1462 6822 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00A
- 1462 6830 ES1371, ES1373 AudioPCI On Motherboard MS-6183 1.00
- 1462 6880 ES1371, ES1373 AudioPCI On Motherboard MS-6188 1.00
- 1462 6900 ES1371, ES1373 AudioPCI On Motherboard MS-6190 1.00
- 1462 6910 ES1371, ES1373 AudioPCI On Motherboard MS-6191
- 1462 6930 ES1371, ES1373 AudioPCI On Motherboard MS-6193
- 1462 6990 ES1371, ES1373 AudioPCI On Motherboard MS-6199BX 2.0A
- 1462 6991 ES1371, ES1373 AudioPCI On Motherboard MS-6199VIA 2.0A
- 14a4 2077 ES1371, ES1373 AudioPCI On Motherboard KR639
- 14a4 2105 ES1371, ES1373 AudioPCI On Motherboard MR800
- 14a4 2107 ES1371, ES1373 AudioPCI On Motherboard MR801
- 14a4 2172 ES1371, ES1373 AudioPCI On Motherboard DR739
- 1509 9902 ES1371, ES1373 AudioPCI On Motherboard KW11
- 1509 9903 ES1371, ES1373 AudioPCI On Motherboard KW31
- 1509 9904 ES1371, ES1373 AudioPCI On Motherboard KA11
- 1509 9905 ES1371, ES1373 AudioPCI On Motherboard KC13
- 152d 8801 ES1371, ES1373 AudioPCI On Motherboard CP810E
- 152d 8802 ES1371, ES1373 AudioPCI On Motherboard CP810
- 152d 8803 ES1371, ES1373 AudioPCI On Motherboard P3810E
- 152d 8804 ES1371, ES1373 AudioPCI On Motherboard P3810-S
- 152d 8805 ES1371, ES1373 AudioPCI On Motherboard P3820-S
- 270f 2001 ES1371, ES1373 AudioPCI On Motherboard 6CTR
- 270f 2200 ES1371, ES1373 AudioPCI On Motherboard 6WTX
- 270f 3000 ES1371, ES1373 AudioPCI On Motherboard 6WSV
- 270f 3100 ES1371, ES1373 AudioPCI On Motherboard 6WIV2
- 270f 3102 ES1371, ES1373 AudioPCI On Motherboard 6WIV
- 270f 7060 ES1371, ES1373 AudioPCI On Motherboard 6ASA2
- 8086 4249 ES1371, ES1373 AudioPCI On Motherboard BI440ZX
- 8086 424c ES1371, ES1373 AudioPCI On Motherboard BL440ZX
- 8086 425a ES1371, ES1373 AudioPCI On Motherboard BZ440ZX
- 8086 4341 ES1371, ES1373 AudioPCI On Motherboard Cayman
- 8086 4343 ES1371, ES1373 AudioPCI On Motherboard Cape Cod
- 8086 4649 ES1371, ES1373 AudioPCI On Motherboard Fire Island
- 8086 464a ES1371, ES1373 AudioPCI On Motherboard FJ440ZX
- 8086 4d4f ES1371, ES1373 AudioPCI On Motherboard Montreal
- 8086 4f43 ES1371, ES1373 AudioPCI On Motherboard OC440LX
- 8086 5243 ES1371, ES1373 AudioPCI On Motherboard RC440BX
- 8086 5352 ES1371, ES1373 AudioPCI On Motherboard SunRiver
- 8086 5643 ES1371, ES1373 AudioPCI On Motherboard Vancouver
- 8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX
- 5000 ES1370 [AudioPCI]
- 5880 5880 AudioPCI
- 1274 2000 Creative Sound Blaster AudioPCI128
- 1274 2003 Creative SoundBlaster AudioPCI 128
- 1274 5880 Creative Sound Blaster AudioPCI128
- 1274 8001 Sound Blaster 16PCI 4.1ch
- 1458 a000 5880 AudioPCI On Motherboard 6OXET
- 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00
- 270f 2001 5880 AudioPCI On Motherboard 6CTR
- 270f 2200 5880 AudioPCI On Motherboard 6WTX
- 270f 7040 5880 AudioPCI On Motherboard 6ATA4
-1275 Network Appliance Corporation
-1276 Switched Network Technologies, Inc.
-1277 Comstream
-1278 Transtech Parallel Systems Ltd.
- 0701 TPE3/TM3 PowerPC Node
- 0710 TPE5 PowerPC PCI board
-1279 Transmeta Corporation
- 0295 Northbridge
- 0395 LongRun Northbridge
- 0396 SDRAM controller
- 0397 BIOS scratchpad
-127a Rockwell International
- 1002 HCF 56k Data/Fax Modem
- 1092 094c SupraExpress 56i PRO [Diamond SUP2380]
- 122d 4002 HPG / MDP3858-U
- 122d 4005 MDP3858-E
- 122d 4007 MDP3858-A/-NZ
- 122d 4012 MDP3858-SA
- 122d 4017 MDP3858-W
- 122d 4018 MDP3858-W
- 127a 1002 Rockwell 56K D/F HCF Modem
- 1003 HCF 56k Data/Fax Modem
- 0e11 b0bc 229-DF Zephyr
- 0e11 b114 229-DF Cheetah
- 1033 802b 229-DF
- 13df 1003 PCI56RX Modem
- 13e0 0117 IBM
- 13e0 0147 IBM F-1156IV+/R3 Spain V.90 Modem
- 13e0 0197 IBM
- 13e0 01c7 IBM F-1156IV+/R3 WW V.90 Modem
- 13e0 01f7 IBM
- 1436 1003 IBM
- 1436 1103 IBM 5614PM3G V.90 Modem
- 1436 1602 Compaq 229-DF Ducati
- 1004 HCF 56k Data/Fax/Voice Modem
- 1048 1500 MicroLink 56k Modem
- 10cf 1059 Fujitsu 229-DFRT
- 1005 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1005 127a AOpen FM56-P
- 1033 8029 229-DFSV
- 1033 8054 Modem
- 10cf 103c Fujitsu
- 10cf 1055 Fujitsu 229-DFSV
- 10cf 1056 Fujitsu 229-DFSV
- 122d 4003 MDP3858SP-U
- 122d 4006 Packard Bell MDP3858V-E
- 122d 4008 MDP3858SP-A/SP-NZ
- 122d 4009 MDP3858SP-E
- 122d 4010 MDP3858V-U
- 122d 4011 MDP3858SP-SA
- 122d 4013 MDP3858V-A/V-NZ
- 122d 4015 MDP3858SP-W
- 122d 4016 MDP3858V-W
- 122d 4019 MDP3858V-SA
- 13df 1005 PCI56RVP Modem
- 13e0 0187 IBM
- 13e0 01a7 IBM
- 13e0 01b7 IBM DF-1156IV+/R3 Spain V.90 Modem
- 13e0 01d7 IBM DF-1156IV+/R3 WW V.90 Modem
- 1436 1005 IBM
- 1436 1105 IBM
- 1437 1105 IBM 5614PS3G V.90 Modem
- 1022 HCF 56k Modem
- 1436 1303 M3-5614PM3G V.90 Modem
- 1023 HCF 56k Data/Fax Modem
- 122d 4020 Packard Bell MDP3858-WE
- 122d 4023 MDP3858-UE
- 13e0 0247 IBM F-1156IV+/R6 Spain V.90 Modem
- 13e0 0297 IBM
- 13e0 02c7 IBM F-1156IV+/R6 WW V.90 Modem
- 1436 1203 IBM
- 1436 1303 IBM
- 1024 HCF 56k Data/Fax/Voice Modem
- 1025 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 106a Fujitsu 235-DFSV
- 122d 4021 Packard Bell MDP3858V-WE
- 122d 4022 MDP3858SP-WE
- 122d 4024 MDP3858V-UE
- 122d 4025 MDP3858SP-UE
- 1026 HCF 56k PCI Speakerphone Modem
- 1032 HCF 56k Modem
- 1033 HCF 56k Modem
- 1034 HCF 56k Modem
- 1035 HCF 56k PCI Speakerphone Modem
- 1036 HCF 56k Modem
- 1085 HCF 56k Volcano PCI Modem
- 2005 HCF 56k Data/Fax Modem
- 104d 8044 229-DFSV
- 104d 8045 229-DFSV
- 104d 8055 PBE/Aztech 235W-DFSV
- 104d 8056 235-DFSV
- 104d 805a Modem
- 104d 805f Modem
- 104d 8074 Modem
- 2013 HSF 56k Data/Fax Modem
- 1179 0001 Modem
- 1179 ff00 Modem
- 2014 HSF 56k Data/Fax/Voice Modem
- 10cf 1057 Fujitsu Citicorp III
- 122d 4050 MSP3880-U
- 122d 4055 MSP3880-W
- 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 1063 Fujitsu
- 10cf 1064 Fujitsu
- 1468 2015 Fujitsu
- 2016 HSF 56k Data/Fax/Voice/Spkp Modem
- 122d 4051 MSP3880V-W
- 122d 4052 MSP3880SP-W
- 122d 4054 MSP3880V-U
- 122d 4056 MSP3880SP-U
- 122d 4057 MSP3880SP-A
- 4311 Riptide HSF 56k PCI Modem
- 127a 4311 Ring Modular? Riptide HSF RT HP Dom
- 13e0 0210 HP-GVC
- 4320 Riptide PCI Audio Controller
- 1235 4320 Riptide PCI Audio Controller
- 4321 Riptide HCF 56k PCI Modem
- 1235 4321 Hewlett Packard DF
- 1235 4324 Hewlett Packard DF
- 13e0 0210 Hewlett Packard DF
- 144d 2321 Riptide
- 4322 Riptide PCI Game Controller
- 1235 4322 Riptide PCI Game Controller
- 8234 RapidFire 616X ATM155 Adapter
- 108d 0022 RapidFire 616X ATM155 Adapter
- 108d 0027 RapidFire 616X ATM155 Adapter
-127b Pixera Corporation
-127c Crosspoint Solutions, Inc.
-127d Vela Research
-127e Winnov, L.P.
-127f Fujifilm
-1280 Photoscript Group Ltd.
-1281 Yokogawa Electric Corporation
-1282 Davicom Semiconductor, Inc.
- 9009 Ethernet 100/10 MBit
- 9100 21x4x DEC-Tulip compatible 10/100 Ethernet
- 9102 21x4x DEC-Tulip compatible 10/100 Ethernet
- 9132 Ethernet 100/10 MBit
-1283 Integrated Technology Express, Inc.
- 673a IT8330G
- 8212 IT/ITE8212 Dual channel ATA RAID controller (PCI version seems to be IT8212, embedded seems to be ITE8212)
- 1283 0001 IT/ITE8212 Dual channel ATA RAID controller
- 8330 IT8330G
- 8872 IT8874F PCI Dual Serial Port Controller
- 8888 IT8888F PCI to ISA Bridge with SMB
- 8889 IT8889F PCI to ISA Bridge
- e886 IT8330G
-1284 Sahara Networks, Inc.
-1285 Platform Technologies, Inc.
- 0100 AGOGO sound chip (aka ESS Maestro 1)
-1286 Mazet GmbH
-1287 M-Pact, Inc.
- 001e LS220D DVD Decoder
- 001f LS220C DVD Decoder
-1288 Timestep Corporation
-1289 AVC Technology, Inc.
-128a Asante Technologies, Inc.
-128b Transwitch Corporation
-128c Retix Corporation
-128d G2 Networks, Inc.
- 0021 ATM155 Adapter
-128e Hoontech Corporation/Samho Multi Tech Ltd.
- 0008 ST128 WSS/SB
- 0009 ST128 SAM9407
- 000a ST128 Game Port
- 000b ST128 MPU Port
- 000c ST128 Ctrl Port
-128f Tateno Dennou, Inc.
-1290 Sord Computer Corporation
-1291 NCS Computer Italia
-1292 Tritech Microelectronics Inc
-1293 Media Reality Technology
-1294 Rhetorex, Inc.
-1295 Imagenation Corporation
-1296 Kofax Image Products
-1297 Holco Enterprise Co, Ltd/Shuttle Computer
-1298 Spellcaster Telecommunications Inc.
-1299 Knowledge Technology Lab.
-129a VMetro, inc.
- 0615 PBT-615 PCI-X Bus Analyzer
-129b Image Access
-129c Jaycor
-129d Compcore Multimedia, Inc.
-129e Victor Company of Japan, Ltd.
-129f OEC Medical Systems, Inc.
-12a0 Allen-Bradley Company
-12a1 Simpact Associates, Inc.
-12a2 Newgen Systems Corporation
-12a3 Lucent Technologies
- 8105 T8105 H100 Digital Switch
-12a4 NTT Electronics Technology Company
-12a5 Vision Dynamics Ltd.
-12a6 Scalable Networks, Inc.
-12a7 AMO GmbH
-12a8 News Datacom
-12a9 Xiotech Corporation
-12aa SDL Communications, Inc.
-12ab Yuan Yuan Enterprise Co., Ltd.
- 0002 AU8830 [Vortex2] Based Sound Card With A3D Support
- 3000 MPG-200C PCI DVD Decoder Card
-12ac Measurex Corporation
-12ad Multidata GmbH
-12ae Alteon Networks Inc.
- 0001 AceNIC Gigabit Ethernet
- 1014 0104 Gigabit Ethernet-SX PCI Adapter
- 12ae 0001 Gigabit Ethernet-SX (Universal)
- 1410 0104 Gigabit Ethernet-SX PCI Adapter
- 0002 AceNIC Gigabit Ethernet (Copper)
- 10a9 8002 Acenic Gigabit Ethernet
- 12ae 0002 Gigabit Ethernet-T (3C986-T)
- 00fa Farallon PN9100-T Gigabit Ethernet
-12af TDK USA Corp
-12b0 Jorge Scientific Corp
-12b1 GammaLink
-12b2 General Signal Networks
-12b3 Inter-Face Co Ltd
-12b4 FutureTel Inc
-12b5 Granite Systems Inc.
-12b6 Natural Microsystems
-12b7 Cognex Modular Vision Systems Div. - Acumen Inc.
-12b8 Korg
-12b9 3Com Corp, Modem Division (formerly US Robotics)
- 1006 WinModem
- 12b9 005c USR 56k Internal Voice WinModem (Model 3472)
- 12b9 005e USR 56k Internal WinModem (Models 662975)
- 12b9 0062 USR 56k Internal Voice WinModem (Model 662978)
- 12b9 0068 USR 56k Internal Voice WinModem (Model 5690)
- 12b9 007a USR 56k Internal Voice WinModem (Model 662974)
- 12b9 007f USR 56k Internal WinModem (Models 5698, 5699)
- 12b9 0080 USR 56k Internal WinModem (Models 2975, 3528)
- 12b9 0081 USR 56k Internal Voice WinModem (Models 2974, 3529)
- 12b9 0091 USR 56k Internal Voice WinModem (Model 2978)
- 1007 USR 56k Internal WinModem
- 12b9 00a3 USR 56k Internal WinModem (Model 3595)
- 1008 56K FaxModem Model 5610
- 12b9 00a2 USR 56k Internal FAX Modem (Model 2977)
- 12b9 00aa USR 56k Internal Voice Modem (Model 2976)
- 12b9 00ab USR 56k Internal Voice Modem (Model 5609)
- 12b9 00ac USR 56k Internal Voice Modem (Model 3298)
- 12b9 00ad USR 56k Internal FAX Modem (Model 5610)
-12ba BittWare, Inc.
-12bb Nippon Unisoft Corporation
-12bc Array Microsystems
-12bd Computerm Corp.
-12be Anchor Chips Inc.
- 3041 AN3041Q CO-MEM
- 3042 AN3042Q CO-MEM Lite
- 12be 3042 Anchor Chips Lite Evaluation Board
-12bf Fujifilm Microdevices
-12c0 Infimed
-12c1 GMM Research Corp
-12c2 Mentec Limited
-12c3 Holtek Microelectronics Inc
- 0058 PCI NE2K Ethernet
- 5598 PCI NE2K Ethernet
-12c4 Connect Tech Inc
- 0001 Blue HEAT/PCI 8 (RS232/CL/RJ11)
- 0002 Blue HEAT/PCI 4 (RS232)
- 0003 Blue HEAT/PCI 2 (RS232)
- 0004 Blue HEAT/PCI 8 (UNIV, RS485)
- 0005 Blue HEAT/PCI 4+4/6+2 (UNIV, RS232/485)
- 0006 Blue HEAT/PCI 4 (OPTO, RS485)
- 0007 Blue HEAT/PCI 2+2 (RS232/485)
- 0008 Blue HEAT/PCI 2 (OPTO, Tx, RS485)
- 0009 Blue HEAT/PCI 2+6 (RS232/485)
- 000a Blue HEAT/PCI 8 (Tx, RS485)
- 000b Blue HEAT/PCI 4 (Tx, RS485)
- 000c Blue HEAT/PCI 2 (20 MHz, RS485)
- 000d Blue HEAT/PCI 2 PTM
- 0100 NT960/PCI
- 0201 cPCI Titan - 2 Port
- 0202 cPCI Titan - 4 Port
- 0300 CTI PCI UART 2 (RS232)
- 0301 CTI PCI UART 4 (RS232)
- 0302 CTI PCI UART 8 (RS232)
- 0310 CTI PCI UART 1+1 (RS232/485)
- 0311 CTI PCI UART 2+2 (RS232/485)
- 0312 CTI PCI UART 4+4 (RS232/485)
- 0320 CTI PCI UART 2
- 0321 CTI PCI UART 4
- 0322 CTI PCI UART 8
- 0330 CTI PCI UART 2 (RS485)
- 0331 CTI PCI UART 4 (RS485)
- 0332 CTI PCI UART 8 (RS485)
-12c5 Picture Elements Incorporated
- 007e Imaging/Scanning Subsystem Engine
- 007f Imaging/Scanning Subsystem Engine
- 0081 PCIVST [Grayscale Thresholding Engine]
- 0085 Video Simulator/Sender
- 0086 THR2 Multi-scale Thresholder
-12c6 Mitani Corporation
-12c7 Dialogic Corp
-12c8 G Force Co, Ltd
-12c9 Gigi Operations
-12ca Integrated Computing Engines
-12cb Antex Electronics Corporation
-12cc Pluto Technologies International
-12cd Aims Lab
-12ce Netspeed Inc.
-12cf Prophet Systems, Inc.
-12d0 GDE Systems, Inc.
-12d1 PSITech
-12d2 NVidia / SGS Thomson (Joint Venture)
- 0008 NV1
- 0009 DAC64
- 0018 Riva128
- 1048 0c10 VICTORY Erazor
- 107b 8030 STB Velocity 128
- 1092 0350 Viper V330
- 1092 1092 Viper V330
- 10b4 1b1b STB Velocity 128
- 10b4 1b1d STB Velocity 128
- 10b4 1b1e STB Velocity 128, PAL TV-Out
- 10b4 1b20 STB Velocity 128 Sapphire
- 10b4 1b21 STB Velocity 128
- 10b4 1b22 STB Velocity 128 AGP, NTSC TV-Out
- 10b4 1b23 STB Velocity 128 AGP, PAL TV-Out
- 10b4 1b27 STB Velocity 128 DVD
- 10b4 1b88 MVP Pro 128
- 10b4 222a STB Velocity 128 AGP
- 10b4 2230 STB Velocity 128
- 10b4 2232 STB Velocity 128
- 10b4 2235 STB Velocity 128 AGP
- 2a15 54a3 3DVision-SAGP / 3DexPlorer 3000
- 0019 Riva128ZX
- 0020 TNT
- 0028 TNT2
- 0029 UTNT2
- 002c VTNT2
- 00a0 ITNT2
-12d3 Vingmed Sound A/S
-12d4 Ulticom (Formerly DGM&S)
- 0200 T1 Card
-12d5 Equator Technologies Inc
- 0003 BSP16
- 1000 BSP15
-12d6 Analogic Corp
-12d7 Biotronic SRL
-12d8 Pericom Semiconductor
-12d9 Aculab PLC
- 0002 PCI Prosody
- 0004 cPCI Prosody
- 0005 Aculab E1/T1 PCI card
-12da True Time Inc.
-12db Annapolis Micro Systems, Inc
-12dc Symicron Computer Communication Ltd.
-12dd Management Graphics
-12de Rainbow Technologies
- 0200 CryptoSwift CS200
-12df SBS Technologies Inc
-12e0 Chase Research
- 0010 ST16C654 Quad UART
- 0020 ST16C654 Quad UART
- 0030 ST16C654 Quad UART
-12e1 Nintendo Co, Ltd
-12e2 Datum Inc. Bancomm-Timing Division
-12e3 Imation Corp - Medical Imaging Systems
-12e4 Brooktrout Technology Inc
-12e5 Apex Semiconductor Inc
-12e6 Cirel Systems
-12e7 Sunsgroup Corporation
-12e8 Crisc Corp
-12e9 GE Spacenet
-12ea Zuken
-12eb Aureal Semiconductor
- 0001 Vortex 1
- 104d 8036 AU8820 Vortex Digital Audio Processor
- 1092 2000 Sonic Impact A3D
- 1092 2100 Sonic Impact A3D
- 1092 2110 Sonic Impact A3D
- 1092 2200 Sonic Impact A3D
- 122d 1002 AU8820 Vortex Digital Audio Processor
- 12eb 0001 AU8820 Vortex Digital Audio Processor
- 5053 3355 Montego
- 0002 Vortex 2
- 104d 8049 AU8830 Vortex 3D Digital Audio Processor
- 104d 807b AU8830 Vortex 3D Digital Audio Processor
- 1092 3000 Monster Sound II
- 1092 3001 Monster Sound II
- 1092 3002 Monster Sound II
- 1092 3003 Monster Sound II
- 1092 3004 Monster Sound II
- 12eb 0001 AU8830 Vortex 3D Digital Audio Processor
- 12eb 0002 AU8830 Vortex 3D Digital Audio Processor
- 12eb 0088 AU8830 Vortex 3D Digital Audio Processor
- 144d 3510 AU8830 Vortex 3D Digital Audio Processor
- 5053 3356 Montego II
- 0003 AU8810 Vortex Digital Audio Processor
- 104d 8049 AU8810 Vortex Digital Audio Processor
- 104d 8077 AU8810 Vortex Digital Audio Processor
- 109f 1000 AU8810 Vortex Digital Audio Processor
- 12eb 0003 AU8810 Vortex Digital Audio Processor
- 1462 6780 AU8810 Vortex Digital Audio Processor
- 14a4 2073 AU8810 Vortex Digital Audio Processor
- 14a4 2091 AU8810 Vortex Digital Audio Processor
- 14a4 2104 AU8810 Vortex Digital Audio Processor
- 14a4 2106 AU8810 Vortex Digital Audio Processor
- 8803 Vortex 56k Software Modem
- 12eb 8803 Vortex 56k Software Modem
-12ec 3A International, Inc.
-12ed Optivision Inc.
-12ee Orange Micro
-12ef Vienna Systems
-12f0 Pentek
-12f1 Sorenson Vision Inc
-12f2 Gammagraphx, Inc.
-12f3 Radstone Technology
-12f4 Megatel
-12f5 Forks
-12f6 Dawson France
-12f7 Cognex
-12f8 Electronic Design GmbH
- 0002 VideoMaker
-12f9 Four Fold Ltd
-12fb Spectrum Signal Processing
-12fc Capital Equipment Corp
-12fd I2S
-12fe ESD Electronic System Design GmbH
-12ff Lexicon
-1300 Harman International Industries Inc
-1302 Computer Sciences Corp
-1303 Innovative Integration
-1304 Juniper Networks
-1305 Netphone, Inc
-1306 Duet Technologies
-# Formerly ComputerBoards
-1307 Measurement Computing
- 0001 PCI-DAS1602/16
- 000b PCI-DIO48H
- 000c PCI-PDISO8
- 000d PCI-PDISO16
- 000f PCI-DAS1200
- 0010 PCI-DAS1602/12
- 0014 PCI-DIO24H
- 0015 PCI-DIO24H/CTR3
- 0016 PCI-DIO48H/CTR15
- 0017 PCI-DIO96H
- 0018 PCI-CTR05
- 0019 PCI-DAS1200/JR
- 001a PCI-DAS1001
- 001b PCI-DAS1002
- 001c PCI-DAS1602JR/16
- 001d PCI-DAS6402/16
- 001e PCI-DAS6402/12
- 001f PCI-DAS16/M1
- 0020 PCI-DDA02/12
- 0021 PCI-DDA04/12
- 0022 PCI-DDA08/12
- 0023 PCI-DDA02/16
- 0024 PCI-DDA04/16
- 0025 PCI-DDA08/16
- 0026 PCI-DAC04/12-HS
- 0027 PCI-DAC04/16-HS
- 0028 PCI-DIO24
- 0029 PCI-DAS08
- 002c PCI-INT32
- 0033 PCI-DUAL-AC5
- 0034 PCI-DAS-TC
- 0035 PCI-DAS64/M1/16
- 0036 PCI-DAS64/M2/16
- 0037 PCI-DAS64/M3/16
- 004c PCI-DAS1000
- 004d PCI-QUAD04
- 0052 PCI-DAS4020/12
- 005e PCI-DAS6025
-1308 Jato Technologies Inc.
- 0001 NetCelerator Adapter
- 1308 0001 NetCelerator Adapter
-1309 AB Semiconductor Ltd
-130a Mitsubishi Electric Microcomputer
-130b Colorgraphic Communications Corp
-130c Ambex Technologies, Inc
-130d Accelerix Inc
-130e Yamatake-Honeywell Co. Ltd
-130f Advanet Inc
-1310 Gespac
-1311 Videoserver, Inc
-1312 Acuity Imaging, Inc
-1313 Yaskawa Electric Co.
-1316 Teradyne Inc
-1317 Linksys
- 0981 21x4x DEC-Tulip compatible 10/100 Ethernet
- 0985 NC100 Network Everywhere Fast Ethernet 10/100
- 1985 21x4x DEC-Tulip compatible 10/100 Ethernet
- 2850 HSP MicroModem 56
- 8201 ADMtek ADM8211 802.11b Wireless Interface
- 10b8 2635 SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
- 1317 8201 SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
- 8211 ADMtek ADM8211 802.11b Wireless Interface
- 9511 21x4x DEC-Tulip compatible 10/100 Ethernet
-1318 Packet Engines Inc.
- 0911 GNIC-II PCI Gigabit Ethernet [Hamachi]
-1319 Fortemedia, Inc
- 0801 Xwave QS3000A [FM801]
- 0802 Xwave QS3000A [FM801 game port]
- 1000 FM801 PCI Audio
- 1001 FM801 PCI Joystick
-131a Finisar Corp.
-131c Nippon Electro-Sensory Devices Corp
-131d Sysmic, Inc.
-131e Xinex Networks Inc
-131f Siig Inc
- 1000 CyberSerial (1-port) 16550
- 1001 CyberSerial (1-port) 16650
- 1002 CyberSerial (1-port) 16850
- 1010 Duet 1S(16550)+1P
- 1011 Duet 1S(16650)+1P
- 1012 Duet 1S(16850)+1P
- 1020 CyberParallel (1-port)
- 1021 CyberParallel (2-port)
- 1030 CyberSerial (2-port) 16550
- 1031 CyberSerial (2-port) 16650
- 1032 CyberSerial (2-port) 16850
- 1034 Trio 2S(16550)+1P
- 1035 Trio 2S(16650)+1P
- 1036 Trio 2S(16850)+1P
- 1050 CyberSerial (4-port) 16550
- 1051 CyberSerial (4-port) 16650
- 1052 CyberSerial (4-port) 16850
- 2000 CyberSerial (1-port) 16550
- 2001 CyberSerial (1-port) 16650
- 2002 CyberSerial (1-port) 16850
- 2010 Duet 1S(16550)+1P
- 2011 Duet 1S(16650)+1P
- 2012 Duet 1S(16850)+1P
- 2020 CyberParallel (1-port)
- 2021 CyberParallel (2-port)
- 2030 CyberSerial (2-port) 16550
- 131f 2030 PCI Serial Card
- 2031 CyberSerial (2-port) 16650
- 2032 CyberSerial (2-port) 16850
- 2040 Trio 1S(16550)+2P
- 2041 Trio 1S(16650)+2P
- 2042 Trio 1S(16850)+2P
- 2050 CyberSerial (4-port) 16550
- 2051 CyberSerial (4-port) 16650
- 2052 CyberSerial (4-port) 16850
- 2060 Trio 2S(16550)+1P
- 2061 Trio 2S(16650)+1P
- 2062 Trio 2S(16850)+1P
- 2081 CyberSerial (8-port) ST16654
-1320 Crypto AG
-1321 Arcobel Graphics BV
-1322 MTT Co., Ltd
-1323 Dome Inc
-1324 Sphere Communications
-1325 Salix Technologies, Inc
-1326 Seachange international
-1327 Voss scientific
-1328 quadrant international
-1329 Productivity Enhancement
-132a Microcom Inc.
-132b Broadband Technologies
-132c Micrel Inc
-132d Integrated Silicon Solution, Inc.
-1330 MMC Networks
-1331 Radisys Corp.
- 0030 ENP-2611
- 8200 82600 Host Bridge
- 8201 82600 IDE
- 8202 82600 USB
- 8210 82600 PCI Bridge
-1332 Micro Memory
- 5415 MM-5415CN PCI Memory Module with Battery Backup
- 5425 MM-5425CN PCI 64/66 Memory Module with Battery Backup
-1334 Redcreek Communications, Inc
-1335 Videomail, Inc
-1337 Third Planet Publishing
-1338 BT Electronics
-133a Vtel Corp
-133b Softcom Microsystems
-133c Holontech Corp
-133d SS Technologies
-133e Virtual Computer Corp
-133f SCM Microsystems
-1340 Atalla Corp
-1341 Kyoto Microcomputer Co
-1342 Promax Systems Inc
-1343 Phylon Communications Inc
-1344 Crucial Technology
-1345 Arescom Inc
-1347 Odetics
-1349 Sumitomo Electric Industries, Ltd.
-134a DTC Technology Corp.
- 0001 Domex 536
- 0002 Domex DMX3194UP SCSI Adapter
-134b ARK Research Corp.
-134c Chori Joho System Co. Ltd
-134d PCTel Inc
- 2189 HSP56 MicroModem
- 2486 2304WT V.92 MDC Modem
- 7890 HSP MicroModem 56
- 134d 0001 PCT789 adapter
- 7891 HSP MicroModem 56
- 134d 0001 HSP MicroModem 56
- 7892 HSP MicroModem 56
- 7893 HSP MicroModem 56
- 7894 HSP MicroModem 56
- 7895 HSP MicroModem 56
- 7896 HSP MicroModem 56
- 7897 HSP MicroModem 56
-134e CSTI
-134f Algo System Co Ltd
-1350 Systec Co. Ltd
-1351 Sonix Inc
-1353 Thales Idatys
- 0002 Proserver
- 0003 PCI-FUT
- 0004 PCI-S0
- 0005 PCI-FUT-S0
-1354 Dwave System Inc
-1355 Kratos Analytical Ltd
-1356 The Logical Co
-1359 Prisa Networks
-135a Brain Boxes
-135b Giganet Inc
-135c Quatech Inc
- 0010 QSC-100
- 0020 DSC-100
- 0030 DSC-200/300
- 0040 QSC-200/300
- 0050 ESC-100D
- 0060 ESC-100M
- 00f0 MPAC-100 Syncronous Serial Card (Zilog 85230)
- 0170 QSCLP-100
- 0180 DSCLP-100
- 0190 SSCLP-100
- 01a0 QSCLP-200/300
- 01b0 DSCLP-200/300
- 01c0 SSCLP-200/300
-135d ABB Network Partner AB
-135e Sealevel Systems Inc
- 5101 Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32)
- 7101 Single Port RS-232/422/485/530
- 7201 Dual Port RS-232/422/485 Interface
- 7202 Dual Port RS-232 Interface
- 7401 Four Port RS-232 Interface
- 7402 Four Port RS-422/485 Interface
- 7801 Eight Port RS-232 Interface
- 7804 Eight Port RS-232/422/485 Interface
- 8001 8001 Digital I/O Adapter
-135f I-Data International A-S
-1360 Meinberg Funkuhren
- 0101 PCI32 DCF77 Radio Clock
- 0102 PCI509 DCF77 Radio Clock
- 0103 PCI510 DCF77 Radio Clock
- 0201 GPS167PCI GPS Receiver
- 0202 GPS168PCI GPS Receiver
- 0203 GPS169PCI GPS Receiver
- 0301 TCR510PCI IRIG Receiver
-1361 Soliton Systems K.K.
-1362 Fujifacom Corporation
-1363 Phoenix Technology Ltd
-1364 ATM Communications Inc
-1365 Hypercope GmbH
-1366 Teijin Seiki Co. Ltd
-1367 Hitachi Zosen Corporation
-1368 Skyware Corporation
-1369 Digigram
-136a High Soft Tech
-136b Kawasaki Steel Corporation
- ff01 KL5A72002 Motion JPEG
-136c Adtek System Science Co Ltd
-136d Gigalabs Inc
-136f Applied Magic Inc
-1370 ATL Products
-1371 CNet Technology Inc
- 434e GigaCard Network Adapter
- 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
-1373 Silicon Vision Inc
-1374 Silicom Ltd
-1375 Argosystems Inc
-1376 LMC
-1377 Electronic Equipment Production & Distribution GmbH
-1378 Telemann Co. Ltd
-1379 Asahi Kasei Microsystems Co Ltd
-137a Mark of the Unicorn Inc
- 0001 PCI-324 Audiowire Interface
-137b PPT Vision
-137c Iwatsu Electric Co Ltd
-137d Dynachip Corporation
-137e Patriot Scientific Corporation
-137f Japan Satellite Systems Inc
-1380 Sanritz Automation Co Ltd
-1381 Brains Co. Ltd
-1382 Marian - Electronic & Software
- 0001 ARC88 audio recording card
- 2008 Prodif 96 Pro sound system
- 2088 Marc 8 Midi sound system
- 20c8 Marc A sound system
- 4008 Marc 2 sound system
- 4010 Marc 2 Pro sound system
- 4048 Marc 4 MIDI sound system
- 4088 Marc 4 Digi sound system
- 4248 Marc X sound system
-1383 Controlnet Inc
-1384 Reality Simulation Systems Inc
-1385 Netgear
-# Note: This lists as Atheros Communications, Inc. AR5212 802.11abg NIC because of Madwifi
- 0013 WG311T
- 311a GA511 Gigabit Ethernet
- 4100 802.11b Wireless Adapter (MA301)
- 4105 MA311 802.11b wireless adapter
- 4400 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4600 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4601 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4610 WAG511 802.11a/b/g Dual Band Wireless PC Card
- 4a00 WAG311 802.11a/g Wireless PCI Adapter
- 4c00 WG311v2 54 Mbps Wireless PCI Adapter
- 620a GA620 Gigabit Ethernet
- 622a GA622
- 630a GA630 Gigabit Ethernet
- f004 FA310TX
-1386 Video Domain Technologies
-1387 Systran Corp
-1388 Hitachi Information Technology Co Ltd
-1389 Applicom International
- 0001 PCI1500PFB [Intelligent fieldbus adaptor]
-138a Fusion Micromedia Corp
-138b Tokimec Inc
-138c Silicon Reality
-138d Future Techno Designs pte Ltd
-138e Basler GmbH
-138f Patapsco Designs Inc
-1390 Concept Development Inc
-1391 Development Concepts Inc
-1392 Medialight Inc
-1393 Moxa Technologies Co Ltd
- 1040 Smartio C104H/PCI
- 1141 Industrio CP-114
- 1680 Smartio C168H/PCI
- 2040 Intellio CP-204J
- 2180 Intellio C218 Turbo PCI
- 3200 Intellio C320 Turbo PCI
-1394 Level One Communications
- 0001 LXT1001 Gigabit Ethernet
- 1394 0001 NetCelerator Adapter
-1395 Ambicom Inc
-1396 Cipher Systems Inc
-1397 Cologne Chip Designs GmbH
- 2bd0 ISDN network controller [HFC-PCI]
- 1397 2bd0 ISDN Board
- e4bf 1000 CI1-1-Harp
-1398 Clarion co. Ltd
-1399 Rios systems Co Ltd
-139a Alacritech Inc
- 0001 Quad Port 10/100 Server Accelerator
- 0003 Single Port 10/100 Server Accelerator
- 0005 Single Port Gigabit Server Accelerator
-139b Mediasonic Multimedia Systems Ltd
-139c Quantum 3d Inc
-139d EPL limited
-139e Media4
-139f Aethra s.r.l.
-13a0 Crystal Group Inc
-13a1 Kawasaki Heavy Industries Ltd
-13a2 Ositech Communications Inc
-13a3 Hifn Inc.
- 0005 7751 Security Processor
- 0006 6500 Public Key Processor
- 0007 7811 Security Processor
- 0012 7951 Security Processor
- 0014 78XX Security Processor
- 0016 8065 Security Processor
- 0017 8165 Security Processor
- 0018 8154 Security Processor
- 001d 7956 Security Processor
- 0020 7955 Security Processor
-13a4 Rascom Inc
-13a5 Audio Digital Imaging Inc
-13a6 Videonics Inc
-13a7 Teles AG
-13a8 Exar Corp.
- 0154 XR17C154 Quad UART
- 0158 XR17C158 Octal UART
-13a9 Siemens Medical Systems, Ultrasound Group
-13aa Broadband Networks Inc
-13ab Arcom Control Systems Ltd
-13ac Motion Media Technology Ltd
-13ad Nexus Inc
-13ae ALD Technology Ltd
-13af T.Sqware
-13b0 Maxspeed Corp
-13b1 Tamura corporation
-13b2 Techno Chips Co. Ltd
-13b3 Lanart Corporation
-13b4 Wellbean Co Inc
-13b5 ARM
-13b6 Dlog GmbH
-13b7 Logic Devices Inc
-13b8 Nokia Telecommunications oy
-13b9 Elecom Co Ltd
-13ba Oxford Instruments
-13bb Sanyo Technosound Co Ltd
-13bc Bitran Corporation
-13bd Sharp corporation
-13be Miroku Jyoho Service Co. Ltd
-13bf Sharewave Inc
-13c0 Microgate Corporation
- 0010 SyncLink Adapter v1
- 0020 SyncLink SCC Adapter
- 0030 SyncLink Multiport Adapter
- 0210 SyncLink Adapter v2
-13c1 3ware Inc
- 1000 3ware Inc 3ware 5xxx/6xxx-series PATA-RAID
- 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
- 13c1 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
- 1002 3ware Inc 3ware 9xxx-series SATA-RAID
-13c2 Technotrend Systemtechnik GmbH
-13c3 Janz Computer AG
-13c4 Phase Metrics
-13c5 Alphi Technology Corp
-13c6 Condor Engineering Inc
- 0520 CEI-520 A429 Card
- 0620 CEI-620 A429 Card
- 0820 CEI-820 A429 Card
-13c7 Blue Chip Technology Ltd
-13c8 Apptech Inc
-13c9 Eaton Corporation
-13ca Iomega Corporation
-13cb Yano Electric Co Ltd
-13cc Metheus Corporation
-13cd Compatible Systems Corporation
-13ce Cocom A/S
-13cf Studio Audio & Video Ltd
-13d0 Techsan Electronics Co Ltd
- 2103 B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card
- 2200 B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card
-13d1 Abocom Systems Inc
- ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter
- ab03 21x4x DEC-Tulip compatible 10/100 Ethernet
- ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter
- ab08 21x4x DEC-Tulip compatible 10/100 Ethernet
-13d2 Shark Multimedia Inc
-13d3 IMC Networks
-13d4 Graphics Microsystems Inc
-13d5 Media 100 Inc
-13d6 K.I. Technology Co Ltd
-13d7 Toshiba Engineering Corporation
-13d8 Phobos corporation
-13d9 Apex PC Solutions Inc
-13da Intresource Systems pte Ltd
-13db Janich & Klass Computertechnik GmbH
-13dc Netboost Corporation
-13dd Multimedia Bundle Inc
-13de ABB Robotics Products AB
-13df E-Tech Inc
- 0001 PCI56RVP Modem
- 13df 0001 PCI56RVP Modem
-13e0 GVC Corporation
-13e1 Silicom Multimedia Systems Inc
-13e2 Dynamics Research Corporation
-13e3 Nest Inc
-13e4 Calculex Inc
-13e5 Telesoft Design Ltd
-13e6 Argosy research Inc
-13e7 NAC Incorporated
-13e8 Chip Express Corporation
-13e9 Intraserver Technology Inc
-13ea Dallas Semiconductor
-13eb Hauppauge Computer Works Inc
-13ec Zydacron Inc
-13ed Raytheion E-Systems
-13ee Hayes Microcomputer Products Inc
-13ef Coppercom Inc
-13f0 Sundance Technology Inc
- 0201 ST201 Sundance Ethernet
-13f1 Oce' - Technologies B.V.
-13f2 Ford Microelectronics Inc
-13f3 Mcdata Corporation
-13f4 Troika Networks, Inc.
- 1401 Zentai Fibre Channel Adapter
-13f5 Kansai Electric Co. Ltd
-13f6 C-Media Electronics Inc
- 0011 CMI8738
- 0100 CM8338A
- 13f6 ffff CMI8338/C3DX PCI Audio Device
- 0101 CM8338B
- 13f6 0101 CMI8338-031 PCI Audio Device
- 0111 CM8738
- 1019 0970 P6STP-FL motherboard
- 1043 8035 CUSI-FX motherboard
- 1043 8077 CMI8738 6-channel audio controller
- 1043 80e2 CMI8738 6ch-MX
- 13f6 0111 CMI8738/C3DX PCI Audio Device
- 1681 a000 Gamesurround MUSE XL
- 0211 CM8738
-13f7 Wildfire Communications
-13f8 Ad Lib Multimedia Inc
-13f9 NTT Advanced Technology Corp.
-13fa Pentland Systems Ltd
-13fb Aydin Corp
-13fc Computer Peripherals International
-13fd Micro Science Inc
-13fe Advantech Co. Ltd
- 1240 PCI-1240 4-channel stepper motor controller card w. Nova Electronics MCX314
- 1600 PCI-1612 4-port RS-232/422/485 PCI Communication Card
- 1752 PCI-1752
- 1754 PCI-1754
- 1756 PCI-1756
-13ff Silicon Spice Inc
-1400 Artx Inc
- 1401 9432 TX
-1401 CR-Systems A/S
-1402 Meilhaus Electronic GmbH
-1403 Ascor Inc
-1404 Fundamental Software Inc
-1405 Excalibur Systems Inc
-1406 Oce' Printing Systems GmbH
-1407 Lava Computer mfg Inc
- 0100 Lava Dual Serial
- 0101 Lava Quatro A
- 0102 Lava Quatro B
- 0110 Lava DSerial-PCI Port A
- 0111 Lava DSerial-PCI Port B
- 0120 Quattro-PCI A
- 0121 Quattro-PCI B
- 0180 Lava Octo A
- 0181 Lava Octo B
- 0200 Lava Port Plus
- 0201 Lava Quad A
- 0202 Lava Quad B
- 0220 Lava Quattro PCI Ports A/B
- 0221 Lava Quattro PCI Ports C/D
- 0500 Lava Single Serial
- 0600 Lava Port 650
- 8000 Lava Parallel
- 8001 Dual parallel port controller A
- 8002 Lava Dual Parallel port A
- 8003 Lava Dual Parallel port B
- 8800 BOCA Research IOPPAR
-1408 Aloka Co. Ltd
-1409 Timedia Technology Co Ltd
- 7168 PCI2S550 (Dual 16550 UART)
-140a DSP Research Inc
-140b Ramix Inc
-140c Elmic Systems Inc
-140d Matsushita Electric Works Ltd
-140e Goepel Electronic GmbH
-140f Salient Systems Corp
-1410 Midas lab Inc
-1411 Ikos Systems Inc
-# formerly IC Ensemble Inc.
-1412 VIA Technologies Inc.
- 1712 ICE1712 [Envy24] PCI Multi-Channel I/O Controller
- 1412 1712 Hoontech ST Audio DSP 24
- 1412 d630 M-Audio Delta 1010
- 1412 d631 M-Audio Delta DiO
- 1412 d632 M-Audio Delta 66
- 1412 d633 M-Audio Delta 44
- 1412 d634 M-Audio Delta Audiophile
- 1412 d635 M-Audio Delta TDIF
- 1412 d637 M-Audio Delta RBUS
- 1412 d638 M-Audio Delta 410
- 1412 d63b M-Audio Delta 1010LT
- 1412 d63c Digigram VX442
- 1416 1712 Hoontech ST Audio DSP 24 Media 7.1
- 153b 1115 EWS88 MT
- 153b 1125 EWS88 MT (Master)
- 153b 112b EWS88 D
- 153b 112c EWS88 D (Master)
- 153b 1130 EWX 24/96
- 153b 1138 DMX 6fire 24/96
- 153b 1151 PHASE88
- 16ce 1040 Edirol DA-2496
- 1724 VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller
- 1412 1724 AMP Ltd AUDIO2000
- 1412 3630 M-Audio Revolution 7.1
- 153b 1145 Aureon 7.1 Space
- 153b 1147 Aureon 5.1 Sky
- 153b 1153 Aureon 7.1 Universe
- 270f f641 ZNF3-150
- 270f f645 ZNF3-250
-1413 Addonics
-1414 Microsoft Corporation
-1415 Oxford Semiconductor Ltd
- 8403 VScom 011H-EP1 1 port parallel adaptor
- 9501 OX16PCI954 (Quad 16950 UART) function 0
- 131f 2050 CyberPro (4-port)
-# Model IO1085, Part No: JJ-P46012
- 131f 2051 CyberSerial 4S Plus
- 15ed 2000 MCCR Serial p0-3 of 8
- 15ed 2001 MCCR Serial p0-3 of 16
- 950a EXSYS EX-41092 Dual 16950 Serial adapter
- 950b OXCB950 Cardbus 16950 UART
- 9510 OX16PCI954 (Quad 16950 UART) function 1 (Disabled)
- 9511 OX16PCI954 (Quad 16950 UART) function 1
- 15ed 2000 MCCR Serial p4-7 of 8
- 15ed 2001 MCCR Serial p4-15 of 16
- 9521 OX16PCI952 (Dual 16950 UART)
-1416 Multiwave Innovation pte Ltd
-1417 Convergenet Technologies Inc
-1418 Kyushu electronics systems Inc
-1419 Excel Switching Corp
-141a Apache Micro Peripherals Inc
-141b Zoom Telephonics Inc
-141d Digitan Systems Inc
-141e Fanuc Ltd
-141f Visiontech Ltd
-1420 Psion Dacom plc
- 8002 Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part)
- 8003 Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part)
-1421 Ads Technologies Inc
-1422 Ygrec Systems Co Ltd
-1423 Custom Technology Corp.
-1424 Videoserver Connections
-1425 Chelsio Communications Inc
-1426 Storage Technology Corp.
-1427 Better On-Line Solutions
-1428 Edec Co Ltd
-1429 Unex Technology Corp.
-142a Kingmax Technology Inc
-142b Radiolan
-142c Minton Optic Industry Co Ltd
-142d Pix stream Inc
-142e Vitec Multimedia
- 4020 VM2-2 [Video Maker 2] MPEG1/2 Encoder
-142f Radicom Research Inc
-1430 ITT Aerospace/Communications Division
-1431 Gilat Satellite Networks
-1432 Edimax Computer Co.
- 9130 RTL81xx Fast Ethernet
-1433 Eltec Elektronik GmbH
-1435 Real Time Devices US Inc.
-1436 CIS Technology Inc
-1437 Nissin Inc Co
-1438 Atmel-dream
-1439 Outsource Engineering & Mfg. Inc
-143a Stargate Solutions Inc
-143b Canon Research Center, America
-143c Amlogic Inc
-143d Tamarack Microelectronics Inc
-143e Jones Futurex Inc
-143f Lightwell Co Ltd - Zax Division
-1440 ALGOL Corp.
-1441 AGIE Ltd
-1442 Phoenix Contact GmbH & Co.
-1443 Unibrain S.A.
-1444 TRW
-1445 Logical DO Ltd
-1446 Graphin Co Ltd
-1447 AIM GmBH
-1448 Alesis Studio Electronics
-1449 TUT Systems Inc
-144a Adlink Technology
- 7296 PCI-7296
- 7432 PCI-7432
- 7433 PCI-7433
- 7434 PCI-7434
- 7841 PCI-7841
- 8133 PCI-8133
- 8164 PCI-8164
- 8554 PCI-8554
- 9111 PCI-9111
- 9113 PCI-9113
- 9114 PCI-9114
-144b Loronix Information Systems Inc
-144c Catalina Research Inc
-144d Samsung Electronics Co Ltd
-144e OLITEC
-144f Askey Computer Corp.
-1450 Octave Communications Ind.
-1451 SP3D Chip Design GmBH
-1453 MYCOM Inc
-1454 Altiga Networks
-1455 Logic Plus Plus Inc
-1456 Advanced Hardware Architectures
-1457 Nuera Communications Inc
-1458 Giga-byte Technology
- 0c11 K8NS Pro Mainboard
-1459 DOOIN Electronics
-145a Escalate Networks Inc
-145b PRAIM SRL
-145c Cryptek
-145d Gallant Computer Inc
-145e Aashima Technology B.V.
-145f Baldor Electric Company
- 0001 NextMove PCI
-1460 DYNARC INC
-1461 Avermedia Technologies Inc
-1462 Micro-Star International Co., Ltd.
-# MSI CB54G Wireless PC Card that seems to use the Broadcom 4306 Chipset
- 6819 Broadcom Corporation BCM4306 802.11b/g Wireless LAN Controller [MSI CB54G]
- 6825 PCI Card wireless 11g [PC54G]
- 8725 NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter
-# MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I
- 9000 NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter
- 9110 GeFORCE FX5200
- 9119 NVIDIA NV31 [GeForce FX 5600XT] VGA Adapter
- 9591 nVidia Corporation NV36 [GeForce FX 5700LE]
-1463 Fast Corporation
-1464 Interactive Circuits & Systems Ltd
-1465 GN NETTEST Telecom DIV.
-1466 Designpro Inc.
-1467 DIGICOM SPA
-1468 AMBIT Microsystem Corp.
-1469 Cleveland Motion Controls
-146a IFR
-146b Parascan Technologies Ltd
-146c Ruby Tech Corp.
- 1430 FE-1430TX Fast Ethernet PCI Adapter
-146d Tachyon, INC.
-146e Williams Electronics Games, Inc.
-146f Multi Dimensional Consulting Inc
-1470 Bay Networks
-1471 Integrated Telecom Express Inc
-1472 DAIKIN Industries, Ltd
-1473 ZAPEX Technologies Inc
-1474 Doug Carson & Associates
-1475 PICAZO Communications
-1476 MORTARA Instrument Inc
-1477 Net Insight
-1478 DIATREND Corporation
-1479 TORAY Industries Inc
-147a FORMOSA Industrial Computing
-147b ABIT Computer Corp.
-147c AWARE, Inc.
-147d Interworks Computer Products
-147e Matsushita Graphic Communication Systems, Inc.
-147f NIHON UNISYS, Ltd.
-1480 SCII Telecom
-1481 BIOPAC Systems Inc
-1482 ISYTEC - Integrierte Systemtechnik GmBH
-1483 LABWAY Corporation
-1484 Logic Corporation
-1485 ERMA - Electronic GmBH
-1486 L3 Communications Telemetry & Instrumentation
-1487 MARQUETTE Medical Systems
-1488 KONTRON Electronik GmBH
-1489 KYE Systems Corporation
-148a OPTO
-148b INNOMEDIALOGIC Inc.
-148c C.P. Technology Co. Ltd
-148d DIGICOM Systems, Inc.
- 1003 HCF 56k Data/Fax Modem
-148e OSI Plus Corporation
-148f Plant Equipment, Inc.
-1490 Stone Microsystems PTY Ltd.
-1491 ZEAL Corporation
-1492 Time Logic Corporation
-1493 MAKER Communications
-1494 WINTOP Technology, Inc.
-1495 TOKAI Communications Industry Co. Ltd
-1496 JOYTECH Computer Co., Ltd.
-1497 SMA Regelsysteme GmBH
-1498 TEWS Datentechnik GmBH
- 30c8 TPCI200
-1499 EMTEC CO., Ltd
-149a ANDOR Technology Ltd
-149b SEIKO Instruments Inc
-149c OVISLINK Corp.
-149d NEWTEK Inc
- 0001 Video Toaster for PC
-149e Mapletree Networks Inc.
-149f LECTRON Co Ltd
-14a0 SOFTING GmBH
-14a1 Systembase Co Ltd
-14a2 Millennium Engineering Inc
-14a3 Maverick Networks
-14a4 GVC/BCM Advanced Research
-14a5 XIONICS Document Technologies Inc
-14a6 INOVA Computers GmBH & Co KG
-14a7 MYTHOS Systems Inc
-14a8 FEATRON Technologies Corporation
-14a9 HIVERTEC Inc
-14aa Advanced MOS Technology Inc
-14ab Mentor Graphics Corp.
-14ac Novaweb Technologies Inc
-14ad Time Space Radio AB
-14ae CTI, Inc
-14af Guillemot Corporation
- 7102 3D Prophet II MX
-14b0 BST Communication Technology Ltd
-14b1 Nextcom K.K.
-14b2 ENNOVATE Networks Inc
-14b3 XPEED Inc
- 0000 DSL NIC
-14b4 PHILIPS Business Electronics B.V.
-14b5 Creamware GmBH
- 0200 Scope
- 0300 Pulsar
- 0400 PulsarSRB
- 0600 Pulsar2
- 0800 DSP-Board
- 0900 DSP-Board
- 0a00 DSP-Board
- 0b00 DSP-Board
-14b6 Quantum Data Corp.
-14b7 PROXIM Inc
- 0001 Symphony 4110
-14b8 Techsoft Technology Co Ltd
-14b9 AIRONET Wireless Communications
- 0001 PC4800
- 0340 PC4800
- 0350 PC4800
- 4500 PC4500
- 4800 Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800
- a504 Cisco Aironet Wireless 802.11b
- a505 Cisco Aironet CB20a 802.11a Wireless LAN Adapter
- a506 Cisco Aironet Mini PCI b/g
-14ba INTERNIX Inc.
-14bb SEMTECH Corporation
-14bc Globespan Semiconductor Inc.
-14bd CARDIO Control N.V.
-14be L3 Communications
-14bf SPIDER Communications Inc.
-14c0 COMPAL Electronics Inc
-14c1 MYRICOM Inc.
- 8043 Myrinet 2000 Scalable Cluster Interconnect
-14c2 DTK Computer
-14c3 MEDIATEK Corp.
-14c4 IWASAKI Information Systems Co Ltd
-14c5 Automation Products AB
-14c6 Data Race Inc
-14c7 Modular Technology Holdings Ltd
-14c8 Turbocomm Tech. Inc.
-14c9 ODIN Telesystems Inc
-14ca PE Logic Corp.
-14cb Billionton Systems Inc
-14cc NAKAYO Telecommunications Inc
-14cd Universal Scientific Ind.
-14ce Whistle Communications
-14cf TEK Microsystems Inc.
-14d0 Ericsson Axe R & D
-14d1 Computer Hi-Tech Co Ltd
-14d2 Titan Electronics Inc
- 8001 VScom 010L 1 port parallel adaptor
- 8002 VScom 020L 2 port parallel adaptor
- 8010 VScom 100L 1 port serial adaptor
- 8011 VScom 110L 1 port serial and 1 port parallel adaptor
- 8020 VScom 200L 1 port serial adaptor
- 8021 VScom 210L 2 port serial and 1 port parallel adaptor
- 8040 VScom 400L 4 port serial adaptor
- 8080 VScom 800L 8 port serial adaptor
- a000 VScom 010H 1 port parallel adaptor
- a001 VScom 100H 1 port serial adaptor
- a003 VScom 400H 4 port serial adaptor
- a004 VScom 400HF1 4 port serial adaptor
- a005 VScom 200H 2 port serial adaptor
- e001 VScom 010HV2 1 port parallel adaptor
- e010 VScom 100HV2 1 port serial adaptor
- e020 VScom 200HV2 2 port serial adaptor
-14d3 CIRTECH (UK) Ltd
-14d4 Panacom Technology Corp
-14d5 Nitsuko Corporation
-14d6 Accusys Inc
-14d7 Hirakawa Hewtech Corp
-14d8 HOPF Elektronik GmBH
-# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
-14d9 Alliance Semiconductor Corporation
- 0010 AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
- 9000 AS90L10204/10208 HyperTransport to PCI-X Bridge
-14da National Aerospace Laboratories
-14db AFAVLAB Technology Inc
- 2120 TK9902
-14dc Amplicon Liveline Ltd
- 0000 PCI230
- 0001 PCI242
- 0002 PCI244
- 0003 PCI247
- 0004 PCI248
- 0005 PCI249
- 0006 PCI260
- 0007 PCI224
- 0008 PCI234
- 0009 PCI236
- 000a PCI272
- 000b PCI215
-14dd Boulder Design Labs Inc
-14de Applied Integration Corporation
-14df ASIC Communications Corp
-14e1 INVERTEX
-14e2 INFOLIBRIA
-14e3 AMTELCO
-14e4 Broadcom Corporation
- 0800 Sentry5 Chipcommon I/O Controller
- 0804 Sentry5 PCI Bridge
- 0805 Sentry5 MIPS32 CPU
- 0806 Sentry5 Ethernet Controller
- 080b Sentry5 Crypto Accelerator
- 080f Sentry5 DDR/SDR RAM Controller
- 0811 Sentry5 External Interface Core
- 0816 BCM3302 Sentry5 MIPS32 CPU
- 1600 NetXtreme BCM5752 Gigabit Ethernet PCI Express
- 1644 NetXtreme BCM5700 Gigabit Ethernet
- 1014 0277 Broadcom Vigil B5700 1000Base-T
- 1028 00d1 Broadcom BCM5700
- 1028 0106 Broadcom BCM5700
- 1028 0109 Broadcom BCM5700 1000Base-T
- 1028 010a Broadcom BCM5700 1000BaseTX
- 10b7 1000 3C996-T 1000Base-T
- 10b7 1001 3C996B-T 1000Base-T
- 10b7 1002 3C996C-T 1000Base-T
- 10b7 1003 3C997-T 1000Base-T Dual Port
- 10b7 1004 3C996-SX 1000Base-SX
- 10b7 1005 3C997-SX 1000Base-SX Dual Port
- 10b7 1008 3C942 Gigabit LOM (31X31)
- 14e4 0002 NetXtreme 1000Base-SX
- 14e4 0003 NetXtreme 1000Base-SX
- 14e4 0004 NetXtreme 1000Base-T
- 14e4 1028 NetXtreme 1000BaseTX
- 14e4 1644 BCM5700 1000Base-T
- 1645 NetXtreme BCM5701 Gigabit Ethernet
- 0e11 007c NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 0e11 007d NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)
- 0e11 0085 NC7780 Gigabit Server Adapter (embedded, WOL)
- 0e11 0099 NC7780 Gigabit Server Adapter (embedded, WOL)
- 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)
- 1028 0121 Broadcom BCM5701 1000Base-T
- 103c 128a HP 1000Base-T (PCI) [A7061A]
- 103c 128b HP 1000Base-SX (PCI) [A7073A]
- 103c 12a4 HP Core Lan 1000Base-T
- 103c 12c1 HP IOX Core Lan 1000Base-T [A7109AX]
- 10a9 8010 SGI IO9 Gigabit Ethernet (Copper)
- 10a9 8011 SGI Gigabit Ethernet (Copper)
- 10a9 8012 SGI Gigabit Ethernet (Fiber)
- 10b7 1004 3C996-SX 1000Base-SX
- 10b7 1006 3C996B-T 1000Base-T
- 10b7 1007 3C1000-T 1000Base-T
- 10b7 1008 3C940-BR01 1000Base-T
- 14e4 0001 BCM5701 1000Base-T
- 14e4 0005 BCM5701 1000Base-T
- 14e4 0006 BCM5701 1000Base-T
- 14e4 0007 BCM5701 1000Base-SX
- 14e4 0008 BCM5701 1000Base-T
- 14e4 8008 BCM5701 1000Base-T
- 1646 NetXtreme BCM5702 Gigabit Ethernet
- 0e11 00bb NC7760 1000BaseTX
- 1028 0126 Broadcom BCM5702 1000BaseTX
- 14e4 8009 BCM5702 1000BaseTX
- 1647 NetXtreme BCM5703 Gigabit Ethernet
- 0e11 0099 NC7780 1000BaseTX
- 0e11 009a NC7770 1000BaseTX
- 10a9 8010 SGI IO9 Gigabit Ethernet (Copper)
- 14e4 0009 BCM5703 1000BaseTX
- 14e4 000a BCM5703 1000BaseSX
- 14e4 000b BCM5703 1000BaseTX
- 14e4 8009 BCM5703 1000BaseTX
- 14e4 800a BCM5703 1000BaseTX
- 1648 NetXtreme BCM5704 Gigabit Ethernet
- 0e11 00cf NC7772 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00d0 NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00d1 NC7783 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X
- 10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X
- 1166 1648 NetXtreme CIOB-E 1000Base-T
- 164a NetXtreme II BCM5706 Gigabit Ethernet
- 164d NetXtreme BCM5702FE Gigabit Ethernet
- 1653 NetXtreme BCM5705 Gigabit Ethernet
- 0e11 00e3 NC7761 Gigabit Server Adapter
- 1654 NetXtreme BCM5705_2 Gigabit Ethernet
- 0e11 00e3 NC7761 Gigabit Server Adapter
- 103c 3100 NC1020 HP ProLiant Gigabit Server Adapter 32 PCI
- 1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express
- 165d NetXtreme BCM5705M Gigabit Ethernet
- 165e NetXtreme BCM5705M_2 Gigabit Ethernet
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 166e 570x 10/100 Integrated Controller
- 1677 NetXtreme BCM5751 Gigabit Ethernet PCI Express
- 1028 0179 Optiplex GX280
- 167d NetXtreme BCM5751M Gigabit Ethernet PCI Express
- 167e NetXtreme BCM5751F Fast Ethernet PCI Express
- 1696 NetXtreme BCM5782 Gigabit Ethernet
- 103c 12bc HP d530 CMT (DG746A)
- 14e4 000d NetXtreme BCM5782 1000Base-T
- 169c NetXtreme BCM5788 Gigabit Ethernet
- 169d NetLink BCM5789 Gigabit Ethernet PCI Express
- 16a6 NetXtreme BCM5702X Gigabit Ethernet
- 0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
- 1028 0126 BCM5702 1000Base-T
- 14e4 000c BCM5702 1000Base-T
- 14e4 8009 BCM5702 1000Base-T
- 16a7 NetXtreme BCM5703X Gigabit Ethernet
- 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 14e4 0009 NetXtreme BCM5703 1000Base-T
- 14e4 000a NetXtreme BCM5703 1000Base-SX
- 14e4 000b NetXtreme BCM5703 1000Base-T
- 14e4 800a NetXtreme BCM5703 1000Base-T
- 16a8 NetXtreme BCM5704S Gigabit Ethernet
- 10b7 2001 3C998-SX Dual Port 1000-SX PCI-X
- 16aa NetXtreme II BCM5706S Gigabit Ethernet
- 16c6 NetXtreme BCM5702A3 Gigabit Ethernet
- 10b7 1100 3C1000B-T 10/100/1000 PCI
- 14e4 000c BCM5702 1000Base-T
- 14e4 8009 BCM5702 1000Base-T
- 16c7 NetXtreme BCM5703 Gigabit Ethernet
- 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
- 103c 12c3 HP Combo FC/GigE-SX [A9782A]
- 103c 12ca HP Combo FC/GigE-T [A9784A]
- 14e4 0009 NetXtreme BCM5703 1000Base-T
- 14e4 000a NetXtreme BCM5703 1000Base-SX
- 16dd NetLink BCM5781 Gigabit Ethernet PCI Express
- 16f7 NetXtreme BCM5753 Gigabit Ethernet PCI Express
- 16fd NetXtreme BCM5753M Gigabit Ethernet PCI Express
- 16fe NetXtreme BCM5753F Fast Ethernet PCI Express
- 170c BCM4401-B0 100Base-TX
- 170d NetXtreme BCM5901 100Base-TX
- 1014 0545 ThinkPad R40e (2684-HVG) builtin ethernet controller
- 170e NetXtreme BCM5901 100Base-TX
- 3352 BCM3352
- 3360 BCM3360
- 4210 BCM4210 iLine10 HomePNA 2.0
- 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
- 4212 BCM4212 v.90 56k modem
- 4301 BCM4303 802.11b Wireless LAN Controller
- 1028 0407 TrueMobile 1180 Onboard WLAN
- 1043 0120 WL-103b Wireless LAN PC Card
- 4305 BCM4307 V.90 56k Modem
- 4306 BCM4307 Ethernet Controller
- 4307 BCM4307 802.11b Wireless LAN Controller
- 4310 BCM4310 Chipcommon I/OController
- 4312 BCM4310 UART
- 4313 BCM4310 Ethernet Controller
- 4315 BCM4310 USB Controller
- 4320 BCM4306 802.11b/g Wireless LAN Controller
- 1028 0001 TrueMobile 1300 WLAN Mini-PCI Card
- 1028 0003 Wireless 1350 WLAN Mini-PCI Card
- 1043 100f WL-100G
- 14e4 4320 Linksys WMP54G PCI
- 1737 4320 WPC54G
- 1799 7010 Belkin F5D7010 54g Wireless Network card
- 4321 BCM4306 802.11a Wireless LAN Controller
- 4322 BCM4306 UART
- 4324 BCM4309 802.11a/b/g
- 1028 0001 Truemobile 1400
- 1028 0003 Truemobile 1450 MiniPCI
- 4325 BCM43xG 802.11b/g
- 1414 0003 Wireless Notebook Adapter MN-720
- 1414 0004 Wireless PCI Adapter MN-730
-# probably this is a correct ID...
- 4326 BCM4307 Chipcommon I/O Controller?
- 4401 BCM4401 100Base-T
- 1043 80a8 A7V8X motherboard
- 4402 BCM4402 Integrated 10/100BaseT
- 4403 BCM4402 V.90 56k Modem
- 4410 BCM4413 iLine32 HomePNA 2.0
- 4411 BCM4413 V.90 56k modem
- 4412 BCM4412 10/100BaseT
- 4430 BCM44xx CardBus iLine32 HomePNA 2.0
- 4432 BCM4432 CardBus 10/100BaseT
- 4610 BCM4610 Sentry5 PCI to SB Bridge
- 4611 BCM4610 Sentry5 iLine32 HomePNA 1.0
- 4612 BCM4610 Sentry5 V.90 56k Modem
- 4613 BCM4610 Sentry5 Ethernet Controller
- 4614 BCM4610 Sentry5 External Interface
- 4615 BCM4610 Sentry5 USB Controller
- 4704 BCM4704 PCI to SB Bridge
- 4705 BCM4704 Sentry5 802.11b Wireless LAN Controller
- 4706 BCM4704 Sentry5 Ethernet Controller
- 4707 BCM4704 Sentry5 USB Controller
- 4708 BCM4704 Crypto Accelerator
- 4710 BCM4710 Sentry5 PCI to SB Bridge
- 4711 BCM47xx Sentry5 iLine32 HomePNA 2.0
- 4712 BCM47xx V.92 56k modem
- 4713 Sentry5 Ethernet Controller
- 4714 BCM47xx Sentry5 External Interface
- 4715 Sentry5 USB Controller
- 4716 BCM47xx Sentry5 USB Host Controller
- 4717 BCM47xx Sentry5 USB Device Controller
- 4718 Sentry5 Crypto Accelerator
- 4720 BCM4712 MIPS CPU
- 5365 BCM5365P Sentry5 Host Bridge
- 5600 BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
- 5605 BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
- 5615 BCM5615 StrataSwitch 24+2 Ethernet Switch Controller
- 5625 BCM5625 StrataSwitch 24+2 Ethernet Switch Controller
- 5645 BCM5645 StrataSwitch 24+2 Ethernet Switch Controller
- 5670 BCM5670 8-Port 10GE Ethernet Switch Fabric
- 5680 BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller
- 5690 BCM5690 12-port Multi-Layer Gigabit Ethernet Switch
- 5691 BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller
- 5820 BCM5820 Crypto Accelerator
- 5821 BCM5821 Crypto Accelerator
- 5822 BCM5822 Crypto Accelerator
- 5823 BCM5823 Crypto Accelerator
- 5824 BCM5824 Crypto Accelerator
- 5840 BCM5840 Crypto Accelerator
- 5841 BCM5841 Crypto Accelerator
- 5850 BCM5850 Crypto Accelerator
-14e5 Pixelfusion Ltd
-14e6 SHINING Technology Inc
-14e7 3CX
-14e8 RAYCER Inc
-14e9 GARNETS System CO Ltd
-14ea Planex Communications, Inc
- ab06 FNW-3603-TX CardBus Fast Ethernet
- ab07 RTL81xx RealTek Ethernet
-14eb SEIKO EPSON Corp
-14ec ACQIRIS
-14ed DATAKINETICS Ltd
-14ee MASPRO KENKOH Corp
-14ef CARRY Computer ENG. CO Ltd
-14f0 CANON RESEACH CENTRE FRANCE
-14f1 Conexant
- 1002 HCF 56k Modem
- 1003 HCF 56k Modem
- 1004 HCF 56k Modem
- 1005 HCF 56k Modem
- 1006 HCF 56k Modem
- 1022 HCF 56k Modem
- 1023 HCF 56k Modem
- 1024 HCF 56k Modem
- 1025 HCF 56k Modem
- 1026 HCF 56k Modem
- 1032 HCF 56k Modem
- 1033 HCF 56k Data/Fax Modem
- 1033 8077 NEC
- 122d 4027 Dell Zeus - MDP3880-W(B) Data Fax Modem
- 122d 4030 Dell Mercury - MDP3880-U(B) Data Fax Modem
- 122d 4034 Dell Thor - MDP3880-W(U) Data Fax Modem
- 13e0 020d Dell Copper
- 13e0 020e Dell Silver
- 13e0 0261 IBM
- 13e0 0290 Compaq Goldwing
- 13e0 02a0 IBM
- 13e0 02b0 IBM
- 13e0 02c0 Compaq Scooter
- 13e0 02d0 IBM
- 144f 1500 IBM P85-DF (1)
- 144f 1501 IBM P85-DF (2)
- 144f 150a IBM P85-DF (3)
- 144f 150b IBM P85-DF Low Profile (1)
- 144f 1510 IBM P85-DF Low Profile (2)
- 1034 HCF 56k Data/Fax/Voice Modem
- 1035 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 10cf 1098 Fujitsu P85-DFSV
- 1036 HCF 56k Data/Fax/Voice/Spkp Modem
- 104d 8067 HCF 56k Modem
- 122d 4029 MDP3880SP-W
- 122d 4031 MDP3880SP-U
- 13e0 0209 Dell Titanium
- 13e0 020a Dell Graphite
- 13e0 0260 Gateway Red Owl
- 13e0 0270 Gateway White Horse
- 1052 HCF 56k Data/Fax Modem (Worldwide)
- 1053 HCF 56k Data/Fax Modem (Worldwide)
- 1054 HCF 56k Data/Fax/Voice Modem (Worldwide)
- 1055 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide)
- 1056 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
- 1057 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
- 1059 HCF 56k Data/Fax/Voice Modem (Worldwide)
- 1063 HCF 56k Data/Fax Modem
- 1064 HCF 56k Data/Fax/Voice Modem
- 1065 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1066 HCF 56k Data/Fax/Voice/Spkp Modem
- 122d 4033 Dell Athena - MDP3900V-U
- 1433 HCF 56k Data/Fax Modem
- 1434 HCF 56k Data/Fax/Voice Modem
- 1435 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1436 HCF 56k Data/Fax Modem
- 1453 HCF 56k Data/Fax Modem
- 13e0 0240 IBM
- 13e0 0250 IBM
- 144f 1502 IBM P95-DF (1)
- 144f 1503 IBM P95-DF (2)
- 1454 HCF 56k Data/Fax/Voice Modem
- 1455 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 1456 HCF 56k Data/Fax/Voice/Spkp Modem
- 122d 4035 Dell Europa - MDP3900V-W
- 122d 4302 Dell MP3930V-W(C) MiniPCI
- 1610 ADSL AccessRunner PCI Arbitration Device
- 1611 AccessRunner PCI ADSL Interface Device
- 1620 ADSL AccessRunner V2 PCI Arbitration Device
- 1621 AccessRunner V2 PCI ADSL Interface Device
- 1622 AccessRunner V2 PCI ADSL Yukon WAN Adapter
- 1803 HCF 56k Modem
- 0e11 0023 623-LAN Grizzly
- 0e11 0043 623-LAN Yogi
- 1815 HCF 56k Modem
- 0e11 0022 Grizzly
- 0e11 0042 Yogi
- 2003 HSF 56k Data/Fax Modem
- 2004 HSF 56k Data/Fax/Voice Modem
- 2005 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 2006 HSF 56k Data/Fax/Voice/Spkp Modem
- 2013 HSF 56k Data/Fax Modem
- 0e11 b195 Bear
- 0e11 b196 Seminole 1
- 0e11 b1be Seminole 2
- 1025 8013 Acer
- 1033 809d NEC
- 1033 80bc NEC
- 155d 6793 HP
- 155d 8850 E Machines
- 2014 HSF 56k Data/Fax/Voice Modem
- 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
- 2016 HSF 56k Data/Fax/Voice/Spkp Modem
- 2043 HSF 56k Data/Fax Modem (WorldW SmartDAA)
- 2044 HSF 56k Data/Fax/Voice Modem (WorldW SmartDAA)
- 2045 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA)
- 2046 HSF 56k Data/Fax/Voice/Spkp Modem (WorldW SmartDAA)
- 2063 HSF 56k Data/Fax Modem (SmartDAA)
- 2064 HSF 56k Data/Fax/Voice Modem (SmartDAA)
- 2065 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA)
- 2066 HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA)
- 2093 HSF 56k Modem
- 155d 2f07 Legend
- 2143 HSF 56k Data/Fax/Cell Modem (Mob WorldW SmartDAA)
- 2144 HSF 56k Data/Fax/Voice/Cell Modem (Mob WorldW SmartDAA)
- 2145 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WorldW SmartDAA)
- 2146 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob WorldW SmartDAA)
- 2163 HSF 56k Data/Fax/Cell Modem (Mob SmartDAA)
- 2164 HSF 56k Data/Fax/Voice/Cell Modem (Mob SmartDAA)
- 2165 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob SmartDAA)
- 2166 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob SmartDAA)
- 2343 HSF 56k Data/Fax CardBus Modem (Mob WorldW SmartDAA)
- 2344 HSF 56k Data/Fax/Voice CardBus Modem (Mob WorldW SmartDAA)
- 2345 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WorldW SmartDAA)
- 2346 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob WorldW SmartDAA)
- 2363 HSF 56k Data/Fax CardBus Modem (Mob SmartDAA)
- 2364 HSF 56k Data/Fax/Voice CardBus Modem (Mob SmartDAA)
- 2365 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA)
- 2366 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob SmartDAA)
- 2443 HSF 56k Data/Fax Modem (Mob WorldW SmartDAA)
- 104d 8075 Modem
- 104d 8083 Modem
- 104d 8097 Modem
- 2444 HSF 56k Data/Fax/Voice Modem (Mob WorldW SmartDAA)
- 2445 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob WorldW SmartDAA)
- 2446 HSF 56k Data/Fax/Voice/Spkp Modem (Mob WorldW SmartDAA)
- 2463 HSF 56k Data/Fax Modem (Mob SmartDAA)
- 2464 HSF 56k Data/Fax/Voice Modem (Mob SmartDAA)
- 2465 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA)
- 2466 HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA)
- 2f00 HSF 56k HSFi Modem
- 13e0 8d84 IBM HSFi V.90
- 13e0 8d85 Compaq Stinger
- 14f1 2004 Dynalink 56PMi
- 2f02 HSF 56k HSFi Data/Fax
- 2f11 HSF 56k HSFi Modem
- 8234 RS8234 ATM SAR Controller [ServiceSAR Plus]
- 8800 CX22702 DVB-T 2k/8k
- 17de 08a1 XPert DVB-T PCI BDA DVBT 23880 Video Capture
- 8802 CX23883 Broadcast Decoder
- 17de 08a1 Xpert DVB-T PCI 2388x Transport Stream Capture
-14f2 MOBILITY Electronics
- 0120 EV1000 bridge
- 0121 EV1000 Parallel port
- 0122 EV1000 Serial port
- 0123 EV1000 Keyboard controller
- 0124 EV1000 Mouse controller
-14f3 BroadLogic
- 2030 2030 DVB-S Satellite Reciever
- 2050 2050 DVB-T Terrestrial (Cable) Reciever
- 2060 2060 ATSC Terrestrial (Cable) Reciever
-14f4 TOKYO Electronic Industry CO Ltd
-14f5 SOPAC Ltd
-14f6 COYOTE Technologies LLC
-14f7 WOLF Technology Inc
-14f8 AUDIOCODES Inc
- 2077 TP-240 dual span E1 VoIP PCI card
-14f9 AG COMMUNICATIONS
-14fa WANDEL & GOCHERMANN
-14fb TRANSAS MARINE (UK) Ltd
-14fc Quadrics Ltd
- 0000 QsNet Elan3 Network Adapter
- 0001 QsNetII Elan4 Network Adapter
-14fd JAPAN Computer Industry Inc
-14fe ARCHTEK TELECOM Corp
-14ff TWINHEAD INTERNATIONAL Corp
-1500 DELTA Electronics, Inc
- 1360 RTL81xx RealTek Ethernet
-1501 BANKSOFT CANADA Ltd
-1502 MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd
-1503 KAWASAKI LSI USA Inc
-1504 KAISER Electronics
-1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH
-1506 CHAMELEON Systems Inc
-# Should be HTEC Ltd, but there are no known HTEC chips and 1507 is already used by mistake by Motorola (see vendor ID 1057).
-1507 Motorola ?? / HTEC
- 0001 MPC105 [Eagle]
- 0002 MPC106 [Grackle]
- 0003 MPC8240 [Kahlua]
- 0100 MC145575 [HFC-PCI]
- 0431 KTI829c 100VG
- 4801 Raven
- 4802 Falcon
- 4803 Hawk
- 4806 CPX8216
-1508 HONDA CONNECTORS/MHOTRONICS Inc
-1509 FIRST INTERNATIONAL Computer Inc
-150a FORVUS RESEARCH Inc
-150b YAMASHITA Systems Corp
-150c KYOPAL CO Ltd
-150d WARPSPPED Inc
-150e C-PORT Corp
-150f INTEC GmbH
-1510 BEHAVIOR TECH Computer Corp
-1511 CENTILLIUM Technology Corp
-1512 ROSUN Technologies Inc
-1513 Raychem
-1514 TFL LAN Inc
-1515 Advent design
-1516 MYSON Technology Inc
- 0800 MTD-8xx 100/10M Ethernet PCI Adapter
- 0803 SURECOM EP-320X-S 100/10M Ethernet PCI Adapter
- 1320 10bd SURECOM EP-320X-S 100/10M Ethernet PCI Adapter
- 0891 MTD-8xx 100/10M Ethernet PCI Adapter
-1517 ECHOTEK Corp
-1518 PEP MODULAR Computers GmbH
-1519 TELEFON AKTIEBOLAGET LM Ericsson
-151a Globetek
- 1002 PCI-1002
- 1004 PCI-1004
- 1008 PCI-1008
-151b COMBOX Ltd
-151c DIGITAL AUDIO LABS Inc
- 0003 Prodif T 2496
- 4000 Prodif 88
-151d Fujitsu Computer Products Of America
-151e MATRIX Corp
-151f TOPIC SEMICONDUCTOR Corp
- 0000 TP560 Data/Fax/Voice 56k modem
-1520 CHAPLET System Inc
-1521 BELL Corp
-1522 MainPine Ltd
- 0100 PCI <-> IOBus Bridge
- 1522 0200 RockForceDUO 2 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0300 RockForceQUATRO 4 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0400 RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0500 RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem
- 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem
- 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem
- 1522 0c00 RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
- 1522 0d00 RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
-# this is a correction to a recent entry. 1522:0E00 should be 1522:1D00
- 1522 1d00 RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem
-1523 MUSIC Semiconductors
-1524 ENE Technology Inc
- 0510 CB710 Memory Card Reader Controller
- 0610 PCI Smart Card Reader Controller
- 1211 CB1211 Cardbus Controller
- 1225 CB1225 Cardbus Controller
- 1410 CB1410 Cardbus Controller
- 1025 005a TravelMate 290
- 1411 CB-710/2/4 Cardbus Controller
- 1412 CB-712/4 Cardbus Controller
- 1420 CB1420 Cardbus Controller
- 1421 CB-720/2/4 Cardbus Controller
- 1422 CB-722/4 Cardbus Controller
-1525 IMPACT Technologies
-1526 ISS, Inc
-1527 SOLECTRON
-1528 ACKSYS
-1529 AMERICAN MICROSystems Inc
-152a QUICKTURN DESIGN Systems
-152b FLYTECH Technology CO Ltd
-152c MACRAIGOR Systems LLC
-152d QUANTA Computer Inc
-152e MELEC Inc
-152f PHILIPS - CRYPTO
-1530 ACQIS Technology Inc
-1531 CHRYON Corp
-1532 ECHELON Corp
-1533 BALTIMORE
-1534 ROAD Corp
-1535 EVERGREEN Technologies Inc
-1537 DATALEX COMMUNCATIONS
-1538 ARALION Inc
- 0303 ARS106S Ultra ATA 133/100/66 Host Controller
-1539 ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A.
-153a ONO SOKKI
-153b TERRATEC Electronic GmbH
- 1144 Aureon 5.1
-# Terratec seems to use several IDs for the same card.
- 1147 Aureon 5.1 Sky
- 1158 Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV]
-153c ANTAL Electronic
-153d FILANET Corp
-153e TECHWELL Inc
-153f MIPS DENMARK
-1540 PROVIDEO MULTIMEDIA Co Ltd
-1541 MACHONE Communications
-1542 VIVID Technology Inc
-1543 SILICON Laboratories
- 3052 Intel 537 [Winmodem]
- 4c22 Si3036 MC'97 DAA
-1544 DCM DATA Systems
-1545 VISIONTEK
-1546 IOI Technology Corp
-1547 MITUTOYO Corp
-1548 JET PROPULSION Laboratory
-1549 INTERCONNECT Systems Solutions
-154a MAX Technologies Inc
-154b COMPUTEX Co Ltd
-154c VISUAL Technology Inc
-154d PAN INTERNATIONAL Industrial Corp
-154e SERVOTEST Ltd
-154f STRATABEAM Technology
-1550 OPEN NETWORK Co Ltd
-1551 SMART Electronic DEVELOPMENT GmBH
-1552 RACAL AIRTECH Ltd
-1553 CHICONY Electronics Co Ltd
-1554 PROLINK Microsystems Corp
-1555 GESYTEC GmBH
-1556 PLD APPLICATIONS
-1557 MEDIASTAR Co Ltd
-1558 CLEVO/KAPOK Computer
-1559 SI LOGIC Ltd
-155a INNOMEDIA Inc
-155b PROTAC INTERNATIONAL Corp
-155c Cemax-Icon Inc
-155d Mac System Co Ltd
-155e LP Elektronik GmbH
-155f Perle Systems Ltd
-1560 Terayon Communications Systems
-1561 Viewgraphics Inc
-1562 Symbol Technologies
-1563 A-Trend Technology Co Ltd
-1564 Yamakatsu Electronics Industry Co Ltd
-1565 Biostar Microtech Int'l Corp
-1566 Ardent Technologies Inc
-1567 Jungsoft
-1568 DDK Electronics Inc
-1569 Palit Microsystems Inc.
-156a Avtec Systems
-156b 2wire Inc
-156c Vidac Electronics GmbH
-156d Alpha-Top Corp
-156e Alfa Inc
-156f M-Systems Flash Disk Pioneers Ltd
-1570 Lecroy Corp
-1571 Contemporary Controls
- a001 CCSI PCI20-485 ARCnet
- a002 CCSI PCI20-485D ARCnet
- a003 CCSI PCI20-485X ARCnet
- a004 CCSI PCI20-CXB ARCnet
- a005 CCSI PCI20-CXS ARCnet
- a006 CCSI PCI20-FOG-SMA ARCnet
- a007 CCSI PCI20-FOG-ST ARCnet
- a008 CCSI PCI20-TB5 ARCnet
- a009 CCSI PCI20-5-485 5Mbit ARCnet
- a00a CCSI PCI20-5-485D 5Mbit ARCnet
- a00b CCSI PCI20-5-485X 5Mbit ARCnet
- a00c CCSI PCI20-5-FOG-ST 5Mbit ARCnet
- a00d CCSI PCI20-5-FOG-SMA 5Mbit ARCnet
- a201 CCSI PCI22-485 10Mbit ARCnet
- a202 CCSI PCI22-485D 10Mbit ARCnet
- a203 CCSI PCI22-485X 10Mbit ARCnet
- a204 CCSI PCI22-CHB 10Mbit ARCnet
- a205 CCSI PCI22-FOG_ST 10Mbit ARCnet
- a206 CCSI PCI22-THB 10Mbit ARCnet
-1572 Otis Elevator Company
-1573 Lattice - Vantis
-1574 Fairchild Semiconductor
-1575 Voltaire Advanced Data Security Ltd
-1576 Viewcast COM
-1578 HITT
- 5615 VPMK3 [Video Processor Mk III]
-1579 Dual Technology Corp
-157a Japan Elecronics Ind Inc
-157b Star Multimedia Corp
-157c Eurosoft (UK)
- 8001 Fix2000 PCI Y2K Compliance Card
-157d Gemflex Networks
-157e Transition Networks
-157f PX Instruments Technology Ltd
-1580 Primex Aerospace Co
-1581 SEH Computertechnik GmbH
-1582 Cytec Corp
-1583 Inet Technologies Inc
-1584 Uniwill Computer Corp
-1585 Logitron
-1586 Lancast Inc
-1587 Konica Corp
-1588 Solidum Systems Corp
-1589 Atlantek Microsystems Pty Ltd
-158a Digalog Systems Inc
-158b Allied Data Technologies
-158c Hitachi Semiconductor & Devices Sales Co Ltd
-158d Point Multimedia Systems
-158e Lara Technology Inc
-158f Ditect Coop
-1590 3pardata Inc
-1591 ARN
-1592 Syba Tech Ltd
- 0781 Multi-IO Card
- 0782 Parallel Port Card 2xEPP
- 0783 Multi-IO Card
- 0785 Multi-IO Card
- 0786 Multi-IO Card
- 0787 Multi-IO Card
- 0788 Multi-IO Card
- 078a Multi-IO Card
-1593 Bops Inc
-1594 Netgame Ltd
-1595 Diva Systems Corp
-1596 Folsom Research Inc
-1597 Memec Design Services
-1598 Granite Microsystems
-1599 Delta Electronics Inc
-159a General Instrument
-159b Faraday Technology Corp
-159c Stratus Computer Systems
-159d Ningbo Harrison Electronics Co Ltd
-159e A-Max Technology Co Ltd
-159f Galea Network Security
-15a0 Compumaster SRL
-15a1 Geocast Network Systems
-15a2 Catalyst Enterprises Inc
- 0001 TA700 PCI Bus Analyzer/Exerciser
-15a3 Italtel
-15a4 X-Net OY
-15a5 Toyota Macs Inc
-15a6 Sunlight Ultrasound Technologies Ltd
-15a7 SSE Telecom Inc
-15a8 Shanghai Communications Technologies Center
-15aa Moreton Bay
-15ab Bluesteel Networks Inc
-15ac North Atlantic Instruments
-15ad VMware Inc
- 0405 [VMware SVGA II] PCI Display Adapter
- 0710 Virtual SVGA
- 0720 VMware High-Speed Virtual NIC [vmxnet]
-15ae Amersham Pharmacia Biotech
-15b0 Zoltrix International Ltd
-15b1 Source Technology Inc
-15b2 Mosaid Technologies Inc
-15b3 Mellanox Technologies
- 5274 MT21108 InfiniBridge
- 5a44 MT23108 InfiniHost
- 5a45 MT23108 [Infinihost HCA Flash Recovery]
- 5a46 MT23108 PCI Bridge
- 5e8c MT24204 [InfiniHost III Lx HCA]
- 5e8d MT24204 [InfiniHost III Lx HCA Flash Recovery]
- 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
- 6279 MT25208 [InfiniHost III Ex HCA Flash Recovery]
- 6282 MT25208 InfiniHost III Ex
-15b4 CCI/TRIAD
-15b5 Cimetrics Inc
-15b6 Texas Memory Systems Inc
-15b7 Sandisk Corp
-15b8 ADDI-DATA GmbH
-15b9 Maestro Digital Communications
-15ba Impacct Technology Corp
-15bb Portwell Inc
-15bc Agilent Technologies
- 2922 64 Bit, 133MHz PCI-X Exerciser & Protocol Checker
- 2928 64 Bit, 66MHz PCI Exerciser & Analyzer
- 2929 64 Bit, 133MHz PCI-X Analyzer & Exerciser
-15bd DFI Inc
-15be Sola Electronics
-15bf High Tech Computer Corp (HTC)
-15c0 BVM Ltd
-15c1 Quantel
-15c2 Newer Technology Inc
-15c3 Taiwan Mycomp Co Ltd
-15c4 EVSX Inc
-15c5 Procomp Informatics Ltd
- 8010 1394b - 1394 Firewire 3-Port Host Adapter Card
-15c6 Technical University of Budapest
-15c7 Tateyama System Laboratory Co Ltd
- 0349 Tateyama C-PCI PLC/NC card Rev.01A
-15c8 Penta Media Co Ltd
-15c9 Serome Technology Inc
-15ca Bitboys OY
-15cb AG Electronics Ltd
-15cc Hotrail Inc
-15cd Dreamtech Co Ltd
-15ce Genrad Inc
-15cf Hilscher GmbH
-15d1 Infineon Technologies AG
-15d2 FIC (First International Computer Inc)
-15d3 NDS Technologies Israel Ltd
-15d4 Iwill Corp
-15d5 Tatung Co
-15d6 Entridia Corp
-15d7 Rockwell-Collins Inc
-15d8 Cybernetics Technology Co Ltd
-15d9 Super Micro Computer Inc
-15da Cyberfirm Inc
-15db Applied Computing Systems Inc
-15dc Litronic Inc
- 0001 Argus 300 PCI Cryptography Module
-15dd Sigmatel Inc
-15de Malleable Technologies Inc
-15df Infinilink Corp
-15e0 Cacheflow Inc
-15e1 Voice Technologies Group Inc
-15e2 Quicknet Technologies Inc
-15e3 Networth Technologies Inc
-15e4 VSN Systemen BV
-15e5 Valley technologies Inc
-15e6 Agere Inc
-15e7 Get Engineering Corp
-15e8 National Datacomm Corp
- 0130 Wireless PCI Card
-15e9 Pacific Digital Corp
- 1841 ADMA-100 DiscStaQ ATA Controller
-15ea Tokyo Denshi Sekei K.K.
-15eb Drsearch GmbH
-15ec Beckhoff GmbH
- 3101 FC3101 Profibus DP 1 Channel PCI
- 5102 FC5102
-15ed Macrolink Inc
-15ee In Win Development Inc
-15ef Intelligent Paradigm Inc
-15f0 B-Tree Systems Inc
-15f1 Times N Systems Inc
-15f2 Diagnostic Instruments Inc
-15f3 Digitmedia Corp
-15f4 Valuesoft
-15f5 Power Micro Research
-15f6 Extreme Packet Device Inc
-15f7 Banctec
-15f8 Koga Electronics Co
-15f9 Zenith Electronics Corp
-15fa J.P. Axzam Corp
-15fb Zilog Inc
-15fc Techsan Electronics Co Ltd
-15fd N-CUBED.NET
-15fe Kinpo Electronics Inc
-15ff Fastpoint Technologies Inc
-1600 Northrop Grumman - Canada Ltd
-1601 Tenta Technology
-1602 Prosys-tec Inc
-1603 Nokia Wireless Communications
-1604 Central System Research Co Ltd
-1605 Pairgain Technologies
-1606 Europop AG
-1607 Lava Semiconductor Manufacturing Inc
-1608 Automated Wagering International
-1609 Scimetric Instruments Inc
-1612 Telesynergy Research Inc.
-1619 FarSite Communications Ltd
- 0400 FarSync T2P (2 port X.21/V.35/V.24)
- 0440 FarSync T4P (4 port X.21/V.35/V.24)
-# www.rioworks.com
-161f Rioworks
-1626 TDK Semiconductor Corp.
- 8410 RTL81xx Fast Ethernet
-1629 Kongsberg Spacetec AS
- 1003 Format synchronizer v3.0
- 2002 Fast Universal Data Output
-# This seems to occur on their 802.11b Wireless card WMP-11
-1637 Linksys
- 3874 Linksys 802.11b WMP11 PCI Wireless card
-1638 Standard Microsystems Corp [SMC]
- 1100 SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000
-163c Smart Link Ltd.
- 3052 SmartLink SmartPCI562 56K Modem
- 5449 SmartPCI561 Modem
-1657 Brocade Communications Systems, Inc.
-165a Epix Inc
- c100 PIXCI(R) CL1 Camera Link Video Capture Board [custom QL5232]
- d200 PIXCI(R) D2X Digital Video Capture Board [custom QL5232]
- d300 PIXCI(R) D3X Digital Video Capture Board [custom QL5232]
-165d Hsing Tech. Enterprise Co., Ltd.
-1661 Worldspace Corp.
-1668 Actiontec Electronics Inc
- 0100 Mini-PCI bridge
-# Formerly SiByte, Inc.
-166d Broadcom Corporation
- 0001 SiByte BCM1125/1125H/1250 System-on-a-Chip PCI
- 0002 SiByte BCM1125H/1250 System-on-a-Chip HyperTransport
-1677 Bernecker + Rainer
- 104e 5LS172.6 B&R Dual CAN Interface Card
- 12d7 5LS172.61 B&R Dual CAN Interface Card
-167b ZyDAS Technology Corp.
- 2102 ZyDAS ZD1202
- 187e 3406 ZyAIR B-122 CardBus 11Mbs Wireless LAN Card
-1681 Hercules
-# More specs, more accurate desc.
- 0010 Hercules 3d Prophet II Ultra 64MB [ 350 MHz NV15BR core, 128-bit DDR @ 460 MHz, 1.5v AGP4x ]
-1682 XFX Pine Group Inc.
-1688 CastleNet Technology Inc.
- 1170 WLAN 802.11b card
-168c Atheros Communications, Inc.
- 0007 AR5000 802.11a Wireless Adapter
- 0011 AR5210 802.11a NIC
- 0012 AR5211 802.11ab NIC
- 0013 AR5212 802.11abg NIC
- 1113 d301 Philips CPWNA100 Wireless CardBus adapter
- 1186 3202 D-link DWL-G650 B3 Wireless cardbus adapter
- 1186 3203 DWL-G520 Wireless PCI Adapter
- 1186 3a13 DWL-G520 Wireless PCI Adapter rev. B
- 1186 3a94 C54C Wireless 801.11g cardbus
- 1385 4d00 Netgear WG311T Wireless PCI Adapter
- 14b7 0a60 8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter
- 168c 0013 WG511T Wireless CardBus Adapter
- 168c 1025 DWL-G650B2 Wireless CardBus Adapter
- 168c 1027 Netgate NL-3054CB ARIES b/g CardBus Adapter
- 168c 2026 Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter
- 168c 2041 Netgate 5354MP Plus ARIES2 b/g MiniPCI Adapter
- 168c 2042 Netgate 5354MP Plus ARIES2 a/b/g MiniPCI Adapter
- 1014 AR5212 802.11abg NIC
-169c Netcell Corporation
- 0044 SyncRAID SR3000/5000 Series SATA RAID Controllers
-16a5 Tekram Technology Co.,Ltd.
-16ab Global Sun Technology Inc
- 1100 GL24110P
- 1101 PLX9052 PCMCIA-to-PCI Wireless LAN
- 1102 PCMCIA-to-PCI Wireless Network Bridge
- 8501 WL-8305 Wireless LAN PCI Adapter
-16ae Safenet Inc
- 1141 SafeXcel-1141
-16b4 Aspex Semiconductor Ltd
-16be Creatix Polymedia GmbH
-16ca CENATEK Inc
- 0001 Rocket Drive DL
-16cd Densitron Technologies
-16ce Roland Corp.
-# www.pikatechnologies.com
-16df PIKA Technologies Inc.
-16e3 European Space Agency
- 1e0f LEON2FT Processor
-16ec U.S. Robotics
- 00ff USR997900 10/100 Mbps PCI Network Card
- 0116 USR997902 10/100/1000 Mbps PCI Network Card
- 3685 Wireless Access PCI Adapter Model 022415
-16ed Sycron N. V.
- 1001 UMIO communication card
-16f3 Jetway Information Co., Ltd.
-16f4 Vweb Corp
- 8000 VW2010
-16f6 VideoTele.com, Inc.
-# www.internetmachines.com
-1702 Internet Machines Corporation (IMC)
-1705 Digital First, Inc.
-170b NetOctave
- 0100 NSP2000-SSL crypto accelerator
-170c YottaYotta Inc.
-# Seems to be a 2nd ID for Vitesse Semiconductor
-1725 Vitesse Semiconductor
- 7174 VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
-172a Accelerated Encryption
-1734 Fujitsu Siemens Computer GmbH
-1737 Linksys
- 0013 WMP54G Wireless Pci Card
- 0015 WMP54GS Wireless Pci Card
- 1032 Gigabit Network Adapter
- 1737 0015 EG1032 v2 Instant Gigabit Network Adapter
- 1064 Gigabit Network Adapter
- 1737 0016 EG1064 v2 Instant Gigabit Network Adapter
- ab08 21x4x DEC-Tulip compatible 10/100 Ethernet
- ab09 21x4x DEC-Tulip compatible 10/100 Ethernet
-173b Altima (nee Broadcom)
- 03e8 AC1000 Gigabit Ethernet
- 03e9 AC1001 Gigabit Ethernet
- 03ea AC9100 Gigabit Ethernet
- 173b 0001 AC1002
- 03eb AC1003 Gigabit Ethernet
-1743 Peppercon AG
- 8139 ROL/F-100 Fast Ethernet Adapter with ROL
-1749 RLX Technologies
-174b PC Partner Limited
-174d WellX Telecom SA
-175c AudioScience Inc
-175e Sanera Systems, Inc.
-1787 Hightech Information System Ltd.
-# also used by Struck Innovative Systeme for joint developments
-1796 Research Centre Juelich
- 0001 SIS1100 [Gigabit link]
- 0002 HOTlink
- 0003 Counter Timer
- 0004 CAMAC Controller
- 0005 PROFIBUS
- 0006 AMCC HOTlink
-1797 JumpTec h, GMBH
-1799 Belkin
- 6001 Wireless PCI Card - F5D6001
- 6020 Wireless PCMCIA Card - F5D6020
- 6060 Wireless PDA Card - F5D6060
- 7000 Wireless PCI Card - F5D7000
-17a0 Genesys Logic, Inc
- 8033 GL880S USB 1.1 controller
- 8034 GL880S USB 2.0 controller
-17af Hightech Information System Ltd.
-17b3 Hawking Technologies
- ab08 PN672TX 10/100 Ethernet
-17b4 Indra Networks, Inc.
- 0011 WebEnhance 100 GZIP Compression Card
-17c0 Wistron Corp.
-17c2 Newisys, Inc.
-17cc NetChip Technology, Inc
- 2280 USB 2.0
-17d3 Areca Technology Corp.
- 1110 ARC-1110 4-Port PCI-X to SATA RAID Controller
- 1120 ARC-1120 8-Port PCI-X to SATA RAID Controller
- 1130 ARC-1130 12-Port PCI-X to SATA RAID Controller
- 1160 ARC-1160 16-Port PCI-X to SATA RAID Controller
- 1210 ARC-1210 4-Port PCI-Express to SATA RAID Controller
- 1220 ARC-1220 8-Port PCI-Express to SATA RAID Controller
- 1230 ARC-1230 12-Port PCI-Express to SATA RAID Controller
- 1260 ARC-1260 16-Port PCI-Express to SATA RAID Controller
-# S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
-17d5 S2io Inc.
- 5831 Xframe 10 Gigabit Ethernet PCI-X
- 103c 12d5 HP PCI-X 133MHz 10GbE SR Fiber [AB287A]
-17de KWorld Computer Co. Ltd.
-# http://www.connect3d.com
-17ee Connect Components Ltd
-17fe Linksys, A Division of Cisco Systems
- 2120 WMP11v4 802.11b PCI card
- 2220 [AirConn] INPROCOMM IPN 2220 Wireless LAN Adapter (rev 01)
-1813 Ambient Technologies Inc
- 4000 HaM controllerless modem
- 16be 0001 V9x HAM Data Fax Modem
- 4100 HaM plus Data Fax Modem
- 16be 0002 V9x HAM 1394
-1814 RaLink
- 0101 Wireless PCI Adpator RT2400 / RT2460
- 3306 1113 Quidway WL100M
- 0201 Ralink RT2500 802.11 Cardbus Reference Card
- 1371 001e CWC-854 Wireless-G CardBus Adapter
- 1371 001f CWM-854 Wireless-G Mini PCI Adapter
- 1371 0020 CWP-854 Wireless-G PCI Adapter
- 1458 e381 GN-WMKG 802.11b/g Wireless CardBus Adapter
-1820 InfiniCon Systems Inc.
-1822 Twinhan Technology Co. Ltd
-182d SiteCom Europe BV
-# HFC-based ISDN card
- 3069 ISDN PCI DC-105V2
- 9790 WL-121 Wireless Network Adapter 100g+ [Ver.3]
-1830 Credence Systems Corporation
-183b MikroM GmbH
- 08a7 MVC100 DVI
- 08a8 MVC101 SDI
- 08a9 MVC102 DVI+Audio
-1849 ASRock Incorporation
-1851 Microtune, Inc.
-1852 Anritsu Corp.
-185f Wistron NeWeb Corp.
-1867 Topspin Communications
- 5a44 MT23108 PCI-X HCA
- 5a45 MT23108 PCI-X HCA flash recovery
- 5a46 MT23108 PCI-X HCA bridge
- 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
- 6282 MT25208 InfiniHost III Ex
-187e ZyXEL Communication Corporation
-1888 Varisys Ltd
- 0301 VMFX1 FPGA PMC module
- 0601 VSM2 dual PMC carrier
- 0710 VS14x series PowerPC PCI board
- 0720 VS24x series PowerPC PCI board
-# found e.g. on KNC DVB-S card
-1894 KNC One
-1896 B&B Electronics Manufacturing Company, Inc.
-18a1 Astute Networks Inc.
-18ac DViCO Corporation
- d810 FusionHDTV 3 Gold
-18b8 Ammasso
- b001 AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor
-18bc Info-Tek Corp.
-# assigned to Octigabay System, which has been acquired by Cray
-18c8 Cray Inc
-18c9 ARVOO Engineering BV
-18ca XGI - Xabre Graphics Inc
- 0040 Volari V8
-18e6 MPL AG
- 0001 OSCI [Octal Serial Communication Interface]
-18f7 Commtech, Inc.
- 0001 Fastcom ESCC-PCI-335
- 0002 Fastcom 422/4-PCI-335
- 0004 Fastcom 422/2-PCI-335
- 0005 Fastcom IGESCC-PCI-ISO/1
- 000a Fastcom 232/4-PCI-335
-18fb Resilience Corporation
-1924 Level 5 Networks Inc.
-1966 Orad Hi-Tec Systems
- 1975 DVG64 family
-1993 Innominate Security Technologies AG
-# http://www.progeny.net
-19ae Progeny Systems Corporation
-1a08 Sierra semiconductor
- 0000 SC15064
-1b13 Jaton Corp
-1c1c Symphony
- 0001 82C101
-1d44 DPT
- a400 PM2x24/PM3224
-1de1 Tekram Technology Co.,Ltd.
- 0391 TRM-S1040
- 2020 DC-390
- 690c 690c
- dc29 DC290
-1fc0 Tumsan Oy
- 0300 E2200 Dual E1/Rawpipe Card
-2000 Smart Link Ltd.
-2001 Temporal Research Ltd
-2003 Smart Link Ltd.
-2004 Smart Link Ltd.
-21c3 21st Century Computer Corp.
-2348 Racore
- 2010 8142 100VG/AnyLAN
-2646 Kingston Technologies
-270b Xantel Corporation
-270f Chaintech Computer Co. Ltd
-2711 AVID Technology Inc.
-2a15 3D Vision(???)
-3000 Hansol Electronics Inc.
-3142 Post Impression Systems.
-3388 Hint Corp
- 0013 HiNT HC4 PCI to ISDN bridge, Multimedia audio controller
- 0014 HiNT HC4 PCI to ISDN bridge, Network controller
- 0020 HB6 Universal PCI-PCI bridge (transparent mode)
- 0021 HB6 Universal PCI-PCI bridge (non-transparent mode)
- 4c53 1050 CT7 mainboard
- 4c53 1080 CT8 mainboard
- 4c53 10a0 CA3/CR3 mainboard
- 4c53 3010 PPCI mezzanine (32-bit PMC)
- 4c53 3011 PPCI mezzanine (64-bit PMC)
- 0022 HiNT HB4 PCI-PCI Bridge (PCI6150)
- 0026 HB2 PCI-PCI Bridge
- 101a E.Band [AudioTrak Inca88]
- 101b E.Band [AudioTrak Inca88]
- 8011 VXPro II Chipset
- 3388 8011 VXPro II Chipset CPU to PCI Bridge
- 8012 VXPro II Chipset
- 3388 8012 VXPro II Chipset PCI to ISA Bridge
- 8013 VXPro II IDE
- 3388 8013 VXPro II Chipset EIDE Controller
-3411 Quantum Designs (H.K.) Inc
-3513 ARCOM Control Systems Ltd
-3842 eVga.com. Corp.
-38ef 4Links
-3d3d 3DLabs
- 0001 GLINT 300SX
- 0002 GLINT 500TX
- 0003 GLINT Delta
- 0004 Permedia
- 0005 Permedia
- 0006 GLINT MX
- 0007 3D Extreme
- 0008 GLINT Gamma G1
- 0009 Permedia II 2D+3D
- 1040 0011 AccelStar II
- 13e9 1000 6221L-4U
- 3d3d 0100 AccelStar II 3D Accelerator
- 3d3d 0111 Permedia 3:16
- 3d3d 0114 Santa Ana
- 3d3d 0116 Oxygen GVX1
- 3d3d 0119 Scirocco
- 3d3d 0120 Santa Ana PCL
- 3d3d 0125 Oxygen VX1
- 3d3d 0127 Permedia3 Create!
- 000a GLINT R3
- 3d3d 0121 Oxygen VX1
- 000c GLINT R3 [Oxygen VX1]
- 3d3d 0144 Oxygen VX1-4X AGP [Permedia 4]
- 000d GLint R4 rev A
- 0011 GLint R4 rev B
- 0012 GLint R5 rev A
- 0013 GLint R5 rev B
- 0020 VP10 visual processor
-# P10 generic II
- 0022 VP10 visual processor
- 0024 VP9 visual processor
- 0100 Permedia II 2D+3D
- 07a1 Wildcat III 6210
- 07a2 Sun XVR-500 Graphics Accelerator
- 07a3 Wildcat IV 7210
- 1004 Permedia
- 3d04 Permedia
- ffff Glint VGA
-4005 Avance Logic Inc.
- 0300 ALS300 PCI Audio Device
- 0308 ALS300+ PCI Audio Device
- 0309 PCI Input Controller
- 1064 ALG-2064
- 2064 ALG-2064i
- 2128 ALG-2364A GUI Accelerator
- 2301 ALG-2301
- 2302 ALG-2302
- 2303 AVG-2302 GUI Accelerator
- 2364 ALG-2364A
- 2464 ALG-2464
- 2501 ALG-2564A/25128A
- 4000 ALS4000 Audio Chipset
- 4005 4000 ALS4000 Audio Chipset
- 4710 ALC200/200P
-4033 Addtron Technology Co, Inc.
- 1360 RTL8139 Ethernet
-4143 Digital Equipment Corp
-4144 Alpha Data
- 0044 ADM-XRCIIPro
-416c Aladdin Knowledge Systems
- 0100 AladdinCARD
- 0200 CPC
-4444 Internext Compression Inc
- 0016 iTVC16 (CX23416) MPEG-2 Encoder
- 0070 4009 WinTV PVR 250
- 0070 8003 WinTV PVR 150
- 0803 iTVC15 MPEG-2 Encoder
- 0070 4000 WinTV PVR-350
- 0070 4001 WinTV PVR-250
-# video capture card
- 1461 a3cf M179
-4468 Bridgeport machines
-4594 Cogetec Informatique Inc
-45fb Baldor Electric Company
-4680 Umax Computer Corp
-4843 Hercules Computer Technology Inc
-4916 RedCreek Communications Inc
- 1960 RedCreek PCI adapter
-4943 Growth Networks
-494f ACCES I/O Products, Inc.
- 10e8 LPCI-COM-8SM
-4978 Axil Computer Inc
-4a14 NetVin
- 5000 NV5000SC
- 4a14 5000 RT8029-Based Ethernet Adapter
-4b10 Buslogic Inc.
-4c48 LUNG HWA Electronics
-4c53 SBS Technologies
- 0000 PLUSTEST device
- 4c53 3000 PLUSTEST card (PC104+)
- 4c53 3001 PLUSTEST card (PMC)
- 0001 PLUSTEST-MM device
- 4c53 3002 PLUSTEST-MM card (PMC)
-4ca1 Seanix Technology Inc
-4d51 MediaQ Inc.
- 0200 MQ-200
-4d54 Microtechnica Co Ltd
-4ddc ILC Data Device Corp
- 0100 DD-42924I5-300 (ARINC 429 Data Bus)
- 0801 BU-65570I1 MIL-STD-1553 Test and Simulation
- 0802 BU-65570I2 MIL-STD-1553 Test and Simulation
- 0811 BU-65572I1 MIL-STD-1553 Test and Simulation
- 0812 BU-65572I2 MIL-STD-1553 Test and Simulation
- 0881 BU-65570T1 MIL-STD-1553 Test and Simulation
- 0882 BU-65570T2 MIL-STD-1553 Test and Simulation
- 0891 BU-65572T1 MIL-STD-1553 Test and Simulation
- 0892 BU-65572T2 MIL-STD-1553 Test and Simulation
- 0901 BU-65565C1 MIL-STD-1553 Data Bus
- 0902 BU-65565C2 MIL-STD-1553 Data Bus
- 0903 BU-65565C3 MIL-STD-1553 Data Bus
- 0904 BU-65565C4 MIL-STD-1553 Data Bus
- 0b01 BU-65569I1 MIL-STD-1553 Data Bus
- 0b02 BU-65569I2 MIL-STD-1553 Data Bus
- 0b03 BU-65569I3 MIL-STD-1553 Data Bus
- 0b04 BU-65569I4 MIL-STD-1553 Data Bus
-5046 GemTek Technology Corporation
- 1001 PCI Radio
-5053 Voyetra Technologies
- 2010 Daytona Audio Adapter
-5136 S S Technologies
-5143 Qualcomm Inc
-5145 Ensoniq (Old)
- 3031 Concert AudioPCI
-5168 Animation Technologies Inc.
-5301 Alliance Semiconductor Corp.
- 0001 ProMotion aT3D
-5333 S3 Inc.
- 0551 Plato/PX (system)
- 5631 86c325 [ViRGE]
- 8800 86c866 [Vision 866]
- 8801 86c964 [Vision 964]
- 8810 86c764_0 [Trio 32 vers 0]
- 8811 86c764/765 [Trio32/64/64V+]
- 8812 86cM65 [Aurora64V+]
- 8813 86c764_3 [Trio 32/64 vers 3]
- 8814 86c767 [Trio 64UV+]
- 8815 86cM65 [Aurora 128]
- 883d 86c988 [ViRGE/VX]
- 8870 FireGL
- 8880 86c868 [Vision 868 VRAM] vers 0
- 8881 86c868 [Vision 868 VRAM] vers 1
- 8882 86c868 [Vision 868 VRAM] vers 2
- 8883 86c868 [Vision 868 VRAM] vers 3
- 88b0 86c928 [Vision 928 VRAM] vers 0
- 88b1 86c928 [Vision 928 VRAM] vers 1
- 88b2 86c928 [Vision 928 VRAM] vers 2
- 88b3 86c928 [Vision 928 VRAM] vers 3
- 88c0 86c864 [Vision 864 DRAM] vers 0
- 88c1 86c864 [Vision 864 DRAM] vers 1
- 88c2 86c864 [Vision 864-P DRAM] vers 2
- 88c3 86c864 [Vision 864-P DRAM] vers 3
- 88d0 86c964 [Vision 964 VRAM] vers 0
- 88d1 86c964 [Vision 964 VRAM] vers 1
- 88d2 86c964 [Vision 964-P VRAM] vers 2
- 88d3 86c964 [Vision 964-P VRAM] vers 3
- 88f0 86c968 [Vision 968 VRAM] rev 0
- 88f1 86c968 [Vision 968 VRAM] rev 1
- 88f2 86c968 [Vision 968 VRAM] rev 2
- 88f3 86c968 [Vision 968 VRAM] rev 3
- 8900 86c755 [Trio 64V2/DX]
- 5333 8900 86C775 Trio64V2/DX
- 8901 86c775/86c785 [Trio 64V2/DX or /GX]
- 5333 8901 86C775 Trio64V2/DX, 86C785 Trio64V2/GX
- 8902 Plato/PX
- 8903 Trio 3D business multimedia
- 8904 Trio 64 3D
- 1014 00db Integrated Trio3D
- 5333 8904 86C365 Trio3D AGP
- 8905 Trio 64V+ family
- 8906 Trio 64V+ family
- 8907 Trio 64V+ family
- 8908 Trio 64V+ family
- 8909 Trio 64V+ family
- 890a Trio 64V+ family
- 890b Trio 64V+ family
- 890c Trio 64V+ family
- 890d Trio 64V+ family
- 890e Trio 64V+ family
- 890f Trio 64V+ family
- 8a01 ViRGE/DX or /GX
- 0e11 b032 ViRGE/GX
- 10b4 1617 Nitro 3D
- 10b4 1717 Nitro 3D
- 5333 8a01 ViRGE/DX
- 8a10 ViRGE/GX2
- 1092 8a10 Stealth 3D 4000
- 8a13 86c368 [Trio 3D/2X]
- 5333 8a13 Trio3D/2X
- 8a20 86c794 [Savage 3D]
- 5333 8a20 86C391 Savage3D
- 8a21 86c390 [Savage 3D/MV]
- 5333 8a21 86C390 Savage3D/MV
- 8a22 Savage 4
- 1033 8068 Savage 4
- 1033 8069 Savage 4
- 1033 8110 Savage4 LT
- 105d 0018 SR9 8Mb SDRAM
- 105d 002a SR9 Pro 16Mb SDRAM
- 105d 003a SR9 Pro 32Mb SDRAM
- 105d 092f SR9 Pro+ 16Mb SGRAM
- 1092 4207 Stealth III S540
- 1092 4800 Stealth III S540
- 1092 4807 SpeedStar A90
- 1092 4808 Stealth III S540
- 1092 4809 Stealth III S540
- 1092 480e Stealth III S540
- 1092 4904 Stealth III S520
- 1092 4905 SpeedStar A200
- 1092 4a09 Stealth III S540
- 1092 4a0b Stealth III S540 Xtreme
- 1092 4a0f Stealth III S540
- 1092 4e01 Stealth III S540
- 1102 101d 3d Blaster Savage 4
- 1102 101e 3d Blaster Savage 4
- 5333 8100 86C394-397 Savage4 SDRAM 100
- 5333 8110 86C394-397 Savage4 SDRAM 110
- 5333 8125 86C394-397 Savage4 SDRAM 125
- 5333 8143 86C394-397 Savage4 SDRAM 143
- 5333 8a22 86C394-397 Savage4
- 5333 8a2e 86C394-397 Savage4 32bit
- 5333 9125 86C394-397 Savage4 SGRAM 125
- 5333 9143 86C394-397 Savage4 SGRAM 143
- 8a23 Savage 4
- 8a25 ProSavage PM133
- 8a26 ProSavage KM133
- 8c00 ViRGE/M3
- 8c01 ViRGE/MX
- 1179 0001 ViRGE/MX
- 8c02 ViRGE/MX+
- 8c03 ViRGE/MX+MV
- 8c10 86C270-294 Savage/MX-MV
- 8c11 82C270-294 Savage/MX
- 8c12 86C270-294 Savage/IX-MV
- 1014 017f ThinkPad T20
- 1179 0001 86C584 SuperSavage/IXC Toshiba
- 8c13 86C270-294 Savage/IX
- 1179 0001 Magnia Z310
- 8c22 SuperSavage MX/128
- 8c24 SuperSavage MX/64
- 8c26 SuperSavage MX/64C
- 8c2a SuperSavage IX/128 SDR
- 8c2b SuperSavage IX/128 DDR
- 8c2c SuperSavage IX/64 SDR
- 8c2d SuperSavage IX/64 DDR
- 8c2e SuperSavage IX/C SDR
- 1014 01fc ThinkPad T23 (2647-4MG)
- 8c2f SuperSavage IX/C DDR
- 8d01 86C380 [ProSavageDDR K4M266]
- 8d02 VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK)
- 8d03 VT8751 [ProSavageDDR P4M266]
- 8d04 VT8375 [ProSavage8 KM266/KL266]
- 9102 86C410 Savage 2000
- 1092 5932 Viper II Z200
- 1092 5934 Viper II Z200
- 1092 5952 Viper II Z200
- 1092 5954 Viper II Z200
- 1092 5a35 Viper II Z200
- 1092 5a37 Viper II Z200
- 1092 5a55 Viper II Z200
- 1092 5a57 Viper II Z200
- ca00 SonicVibes
-544c Teralogic Inc
- 0350 TL880-based HDTV/ATSC tuner
-5455 Technische University Berlin
- 4458 S5933
-5519 Cnet Technologies, Inc.
-5544 Dunord Technologies
- 0001 I-30xx Scanner Interface
-5555 Genroco, Inc
- 0003 TURBOstor HFP-832 [HiPPI NIC]
-5654 VoiceTronix Pty Ltd
- 3132 OpenSwitch12
-5700 Netpower
-5851 Exacq Technologies
-6356 UltraStor
-6374 c't Magazin für Computertechnik
- 6773 GPPCI
-6409 Logitec Corp.
-6666 Decision Computer International Co.
- 0001 PCCOM4
- 0002 PCCOM8
-7604 O.N. Electronic Co Ltd.
-7bde MIDAC Corporation
-7fed PowerTV
-8008 Quancom Electronic GmbH
- 0010 WDOG1 [PCI-Watchdog 1]
- 0011 PWDOG2 [PCI-Watchdog 2]
-# Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card.
-807d Asustek Computer, Inc.
-8086 Intel Corporation
- 0007 82379AB
- 0008 Extended Express System Support Controller
- 0008 1000 WorldMark 4300 INCA ASIC
- 0039 21145 Fast Ethernet
- 0122 82437FX
- 0309 80303 I/O Processor PCI-to-PCI Bridge
- 030d 80312 I/O Companion Chip PCI-to-PCI Bridge
- 0326 6700/6702PXH I/OxAPIC Interrupt Controller A
- 0327 6700PXH I/OxAPIC Interrupt Controller B
- 0329 6700PXH PCI Express-to-PCI Bridge A
- 032a 6700PXH PCI Express-to-PCI Bridge B
- 032c 6702PXH PCI Express-to-PCI Bridge A
-# A-segment bridge
- 0330 80332 [Dobson] I/O processor
-# A-segment IOAPIC
- 0331 80332 [Dobson] I/O processor
-# B-segment bridge
- 0332 80332 [Dobson] I/O processor
-# B-segment IOAPIC
- 0333 80332 [Dobson] I/O processor
-# Address Translation Unit (ATU)
- 0334 80332 [Dobson] I/O processor
-# PCI-X bridge
- 0335 80331 [Lindsay] I/O processor
-# Address Translation Unit (ATU)
- 0336 80331 [Lindsay] I/O processor
-# A-segment bridge
- 0340 41210 [Lanai] Serial to Parallel PCI Bridge
-# B-segment bridge
- 0341 41210 [Lanai] Serial to Parallel PCI Bridge
- 0482 82375EB/SB PCI to EISA Bridge
- 0483 82424TX/ZX [Saturn] CPU to PCI bridge
- 0484 82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge
- 0486 82425EX/ZX [Aries] PCIset with ISA bridge
- 04a3 82434LX/NX [Mercury/Neptune] Processor to PCI bridge
- 04d0 82437FX [Triton FX]
- 0500 E8870 Processor bus control
- 0501 E8870 Memory controller
-# and registers common to both SPs
- 0502 E8870 Scalability Port 0
-# and global performance monitoring
- 0503 E8870 Scalability Port 1
- 0510 E8870IO Hub Interface Port 0 registers (8-bit compatibility port)
- 0511 E8870IO Hub Interface Port 1 registers
- 0512 E8870IO Hub Interface Port 2 registers
- 0513 E8870IO Hub Interface Port 3 registers
- 0514 E8870IO Hub Interface Port 4 registers
- 0515 E8870IO General SIOH registers
- 0516 E8870IO RAS registers
- 0530 E8870SP Scalability Port 0 registers
- 0531 E8870SP Scalability Port 1 registers
- 0532 E8870SP Scalability Port 2 registers
- 0533 E8870SP Scalability Port 3 registers
- 0534 E8870SP Scalability Port 4 registers
- 0535 E8870SP Scalability Port 5 registers
-# (bi-interleave 0) and global registers that are neither per-port nor per-interleave
- 0536 E8870SP Interleave registers 0 and 1
-# (bi-interleave 1)
- 0537 E8870SP Interleave registers 2 and 3
- 0600 RAID Controller
- 8086 01c1 ICP Vortex GDT8546RZ
- 8086 01f7 SCRU32
-# uninitialized SRCU32 RAID Controller
- 061f 80303 I/O Processor
- 0960 80960RP [i960 RP Microprocessor/Bridge]
- 0962 80960RM [i960RM Bridge]
- 0964 80960RP [i960 RP Microprocessor/Bridge]
- 1000 82542 Gigabit Ethernet Controller
- 0e11 b0df NC1632 Gigabit Ethernet Adapter (1000-SX)
- 0e11 b0e0 NC1633 Gigabit Ethernet Adapter (1000-LX)
- 0e11 b123 NC1634 Gigabit Ethernet Adapter (1000-SX)
- 1014 0119 Netfinity Gigabit Ethernet SX Adapter
- 8086 1000 PRO/1000 Gigabit Server Adapter
- 1001 82543GC Gigabit Ethernet Controller (Fiber)
- 0e11 004a NC6136 Gigabit Server Adapter
- 1014 01ea Netfinity Gigabit Ethernet SX Adapter
- 8086 1002 PRO/1000 F Server Adapter
- 8086 1003 PRO/1000 F Server Adapter
- 1002 Pro 100 LAN+Modem 56 Cardbus II
- 8086 200e Pro 100 LAN+Modem 56 Cardbus II
- 8086 2013 Pro 100 SR Mobile Combo Adapter
- 8086 2017 Pro 100 S Combo Mobile Adapter
- 1004 82543GC Gigabit Ethernet Controller (Copper)
- 0e11 0049 NC7132 Gigabit Upgrade Module
- 0e11 b1a4 NC7131 Gigabit Server Adapter
- 1014 10f2 Gigabit Ethernet Server Adapter
- 8086 1004 PRO/1000 T Server Adapter
- 8086 2004 PRO/1000 T Server Adapter
- 1008 82544EI Gigabit Ethernet Controller (Copper)
- 1014 0269 iSeries 1000/100/10 Ethernet Adapter
- 1028 011c PRO/1000 XT Network Connection
- 8086 1107 PRO/1000 XT Server Adapter
- 8086 2107 PRO/1000 XT Server Adapter
- 8086 2110 PRO/1000 XT Server Adapter
- 8086 3108 PRO/1000 XT Network Connection
- 1009 82544EI Gigabit Ethernet Controller (Fiber)
- 1014 0268 iSeries Gigabit Ethernet Adapter
- 8086 1109 PRO/1000 XF Server Adapter
- 8086 2109 PRO/1000 XF Server Adapter
- 100c 82544GC Gigabit Ethernet Controller (Copper)
- 8086 1112 PRO/1000 T Desktop Adapter
- 8086 2112 PRO/1000 T Desktop Adapter
- 100d 82544GC Gigabit Ethernet Controller (LOM)
- 1028 0123 PRO/1000 XT Network Connection
- 1079 891f 82544GC Based Network Connection
- 4c53 1080 CT8 mainboard
- 8086 110d 82544GC Based Network Connection
- 100e 82540EM Gigabit Ethernet Controller
- 1014 0265 PRO/1000 MT Network Connection
- 1014 0267 PRO/1000 MT Network Connection
- 1014 026a PRO/1000 MT Network Connection
- 1028 002e Optiplex GX260
- 1028 0151 PRO/1000 MT Network Connection
- 107b 8920 PRO/1000 MT Desktop Adapter
- 8086 001e PRO/1000 MT Desktop Adapter
- 8086 002e PRO/1000 MT Desktop Adapter
- 100f 82545EM Gigabit Ethernet Controller (Copper)
- 1014 0269 iSeries 1000/100/10 Ethernet Adapter
- 1014 028e PRO/1000 MT Network Connection
- 8086 1000 PRO/1000 MT Network Connection
- 8086 1001 PRO/1000 MT Server Adapter
- 1010 82546EB Gigabit Ethernet Controller (Copper)
- 1014 027c PRO/1000 MT Dual Port Network Adapter
- 18fb 7872 RESlink-X
- 4c53 1080 CT8 mainboard
- 4c53 10a0 CA3/CR3 mainboard
- 8086 1011 PRO/1000 MT Dual Port Server Adapter
- 8086 101a PRO/1000 MT Dual Port Network Adapter
- 8086 3424 SE7501HG2 Mainboard
- 1011 82545EM Gigabit Ethernet Controller (Fiber)
- 1014 0268 iSeries Gigabit Ethernet Adapter
- 8086 1002 PRO/1000 MF Server Adapter
- 8086 1003 PRO/1000 MF Server Adapter (LX)
- 1012 82546EB Gigabit Ethernet Controller (Fiber)
- 8086 1012 PRO/1000 MF Dual Port Server Adapter
- 1013 82541EI Gigabit Ethernet Controller (Copper)
- 8086 0013 PRO/1000 MT Network Connection
- 8086 1013 IBM ThinkCentre Network Card
- 8086 1113 PRO/1000 MT Desktop Adapter
- 1014 82541ER Gigabit Ethernet Controller
- 1015 82540EM Gigabit Ethernet Controller (LOM)
- 1016 82540EP Gigabit Ethernet Controller (LOM)
- 1014 052c PRO/1000 MT Mobile Connection
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 1016 PRO/1000 MT Mobile Connection
- 1017 82540EP Gigabit Ethernet Controller (LOM)
- 8086 1017 PR0/1000 MT Desktop Connection
-# Update controller name from 82541EP to 82541EI
- 1018 82541EI Gigabit Ethernet Controller
- 8086 1018 PRO/1000 MT Desktop Adapter
- 1019 82547EI Gigabit Ethernet Controller (LOM)
- 1458 1019 GA-8IPE1000 Pro2 motherboard (865PE)
- 1458 e000 Intel Gigabit Ethernet (Kenai II)
- 8086 1019 PRO/1000 CT Desktop Connection
- 8086 301f D865PERL mainboard
- 8086 3427 S875WP1-E mainboard
- 101d 82546EB Gigabit Ethernet Controller
- 8086 1000 PRO/1000 MT Quad Port Server Adapter
- 101e 82540EP Gigabit Ethernet Controller (Mobile)
- 1014 0549 PRO/1000 MT Mobile Connection
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 101e PRO/1000 MT Mobile Connection
- 1026 82545GM Gigabit Ethernet Controller
- 8086 1000 PRO/1000 MT Server Connection
- 8086 1001 PRO/1000 MT Server Adapter
- 8086 1002 PRO/1000 MT Server Adapter
- 8086 1026 PRO/1000 MT Server Connection
- 1027 82545GM Gigabit Ethernet Controller
- 8086 1001 PRO/1000 MF Server Adapter(LX)
- 8086 1002 PRO/1000 MF Server Adapter(LX)
- 8086 1003 PRO/1000 MF Server Adapter(LX)
- 8086 1027 PRO/1000 MF Server Adapter
- 1028 82545GM Gigabit Ethernet Controller
- 8086 1028 PRO/1000 MB Server Adapter
- 1029 82559 Ethernet Controller
- 1030 82559 InBusiness 10/100
- 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller
- 1014 0209 ThinkPad A/T/X Series
- 104d 80e7 Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 107b 5350 EtherExpress PRO/100 VE
- 1179 0001 EtherExpress PRO/100 VE
- 144d c000 EtherExpress PRO/100 VE
- 144d c001 EtherExpress PRO/100 VE
- 144d c003 EtherExpress PRO/100 VE
- 144d c006 vpr Matrix 170B4
- 1032 82801CAM (ICH3) PRO/100 VE Ethernet Controller
- 1033 82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller
- 1034 82801CAM (ICH3) PRO/100 VM Ethernet Controller
- 1035 82801CAM (ICH3)/82562EH (LOM) Ethernet Controller
- 1036 82801CAM (ICH3) 82562EH Ethernet Controller
- 1037 82801CAM (ICH3) Chipset Ethernet Controller
- 1038 82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller
- 1039 82801DB PRO/100 VE (LOM) Ethernet Controller
- 1014 0267 NetVista A30p
- 103a 82801DB PRO/100 VE (CNR) Ethernet Controller
- 103b 82801DB PRO/100 VM (LOM) Ethernet Controller
- 103c 82801DB PRO/100 VM (CNR) Ethernet Controller
- 103d 82801DB PRO/100 VE (MOB) Ethernet Controller
- 103e 82801DB PRO/100 VM (MOB) Ethernet Controller
- 1040 536EP Data Fax Modem
- 16be 1040 V.9X DSP Data Fax Modem
- 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter
- 8086 2527 MIM2000/Centrino
- 1048 PRO/10GbE LR Server Adapter
- 8086 a01f PRO/10GbE LR Server Adapter
- 8086 a11f PRO/10GbE LR Server Adapter
- 1050 82562EZ 10/100 Ethernet Controller
- 1462 728c 865PE Neo2 (MS-6728)
- 1462 758c MS-6758 (875P Neo)
- 8086 3020 D865PERL mainboard
- 8086 3427 S875WP1-E mainboard
- 1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller
- 1059 82551QM Ethernet Controller
-# ICH-6 Component
- 1064 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
-# ICH-6 Component
- 1065 82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller
-# ICH-6 Component
- 1066 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller
-# ICH-6 Component
- 1067 82562 EM/EX/GX - PRO/100 VM Ethernet Controller
-# ICH-6 Component
- 1068 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile
-# ICH-6 Component
- 1069 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile
-# ICH-6 Component
- 106a 82562G \t- PRO/100 VE (LOM) Ethernet Controller
-# ICH-6 Component
- 106b 82562G \t- PRO/100 VE Ethernet Controller Mobile
- 1075 82547GI Gigabit Ethernet Controller
- 1028 0165 PowerEdge 750
- 8086 0075 PRO/1000 CT Network Connection
- 8086 1075 PRO/1000 CT Network Connection
- 1076 82541GI/PI Gigabit Ethernet Controller
- 1028 0165 PowerEdge 750
- 8086 0076 PRO/1000 MT Network Connection
- 8086 1076 PRO/1000 MT Network Connection
- 8086 1176 PRO/1000 MT Desktop Adapter
- 8086 1276 PRO/1000 MT Desktop Adapter
- 1077 82541GI Gigabit Ethernet Controller
- 1179 0001 PRO/1000 MT Mobile Connection
- 8086 0077 PRO/1000 MT Mobile Connection
- 8086 1077 PRO/1000 MT Mobile Connection
- 1078 82541EI Gigabit Ethernet Controller
- 8086 1078 PRO/1000 MT Network Connection
- 1079 82546GB Gigabit Ethernet Controller
- 103c 12a6 HP Dual Port 1000Base-T [A9900A]
- 103c 12cf HP Core Dual Port 1000Base-T [AB352A]
- 4c53 1090 Cx9 / Vx9 mainboard
- 4c53 10b0 CL9 mainboard
- 8086 0079 PRO/1000 MT Dual Port Network Connection
- 8086 1079 PRO/1000 MT Dual Port Network Connection
- 8086 1179 PRO/1000 MT Dual Port Network Connection
- 8086 117a PRO/1000 MT Dual Port Server Adapter
- 107a 82546GB Gigabit Ethernet Controller
- 103c 12a8 HP Dual Port 1000base-SX [A9899A]
- 8086 107a PRO/1000 MF Dual Port Server Adapter
- 8086 127a PRO/1000 MF Dual Port Server Adapter
- 107b 82546GB Gigabit Ethernet Controller
- 8086 007b PRO/1000 MB Dual Port Server Connection
- 8086 107b PRO/1000 MB Dual Port Server Connection
- 1107 PRO/1000 MF Server Adapter (LX)
- 1130 82815 815 Chipset Host Bridge and Memory Controller Hub
- 1025 1016 Travelmate 612 TX
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 1131 82815 815 Chipset AGP Bridge
- 1132 82815 CGC [Chipset Graphics Controller]
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 Mainboard
- 8086 4557 D815EGEW Mainboard
- 1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller
- 8086 1161 82806AA PCI64 Hub APIC
- 1162 Xscale 80200 Big Endian Companion Chip
- 1200 Intel IXP1200 Network Processor
- 172a 0000 AEP SSL Accelerator
- 1209 8255xER/82551IT Fast Ethernet Controller
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 4c53 1070 PC6 mainboard
- 1221 82092AA PCI to PCMCIA Bridge
- 1222 82092AA IDE Controller
- 1223 SAA7116
- 1225 82452KX/GX [Orion]
- 1226 82596 PRO/10 PCI
- 1227 82865 EtherExpress PRO/100A
- 1228 82556 EtherExpress PRO/100 Smart
-# the revision field differentiates between them (1-3 is 82557, 4-5 is 82558, 6-8 is 82559, 9 is 82559ER)
- 1229 82557/8/9 [Ethernet Pro 100]
- 0e11 3001 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3002 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3003 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3004 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3005 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3006 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 3007 82559 Fast Ethernet LOM with Alert on LAN*
- 0e11 b01e NC3120 Fast Ethernet NIC
- 0e11 b01f NC3122 Fast Ethernet NIC (dual port)
- 0e11 b02f NC1120 Ethernet NIC
- 0e11 b04a Netelligent 10/100TX NIC with Wake on LAN
- 0e11 b0c6 NC3161 Fast Ethernet NIC (embedded, WOL)
- 0e11 b0c7 NC3160 Fast Ethernet NIC (embedded)
- 0e11 b0d7 NC3121 Fast Ethernet NIC (WOL)
- 0e11 b0dd NC3131 Fast Ethernet NIC (dual port)
- 0e11 b0de NC3132 Fast Ethernet Module (dual port)
- 0e11 b0e1 NC3133 Fast Ethernet Module (100-FX)
- 0e11 b134 NC3163 Fast Ethernet NIC (embedded, WOL)
- 0e11 b13c NC3162 Fast Ethernet NIC (embedded)
- 0e11 b144 NC3123 Fast Ethernet NIC (WOL)
- 0e11 b163 NC3134 Fast Ethernet NIC (dual port)
- 0e11 b164 NC3135 Fast Ethernet Upgrade Module (dual port)
- 0e11 b1a4 NC7131 Gigabit Server Adapter
- 1014 005c 82558B Ethernet Pro 10/100
- 1014 01bc 82559 Fast Ethernet LAN On Motherboard
- 1014 01f1 10/100 Ethernet Server Adapter
- 1014 01f2 10/100 Ethernet Server Adapter
- 1014 0207 Ethernet Pro/100 S
- 1014 0232 10/100 Dual Port Server Adapter
- 1014 023a ThinkPad R30
- 1014 105c Netfinity 10/100
- 1014 2205 ThinkPad A22p
- 1014 305c 10/100 EtherJet Management Adapter
- 1014 405c 10/100 EtherJet Adapter with Alert on LAN
- 1014 505c 10/100 EtherJet Secure Management Adapter
- 1014 605c 10/100 EtherJet Secure Management Adapter
- 1014 705c 10/100 Netfinity 10/100 Ethernet Security Adapter
- 1014 805c 10/100 Netfinity 10/100 Ethernet Security Adapter
- 1028 009b PowerEdge 2500/2550
- 1028 00ce PowerEdge 1400
- 1033 8000 PC-9821X-B06
- 1033 8016 PK-UG-X006
- 1033 801f PK-UG-X006
- 1033 8026 PK-UG-X006
- 1033 8063 82559-based Fast Ethernet Adapter
- 1033 8064 82559-based Fast Ethernet Adapter
- 103c 10c0 NetServer 10/100TX
- 103c 10c3 NetServer 10/100TX
- 103c 10ca NetServer 10/100TX
- 103c 10cb NetServer 10/100TX
- 103c 10e3 NetServer 10/100TX
- 103c 10e4 NetServer 10/100TX
- 103c 1200 NetServer 10/100TX
- 10c3 1100 SmartEther100 SC1100
- 10cf 1115 8255x-based Ethernet Adapter (10/100)
- 10cf 1143 8255x-based Ethernet Adapter (10/100)
- 1179 0001 8255x-based Ethernet Adapter (10/100)
- 1179 0002 PCI FastEther LAN on Docker
- 1179 0003 8255x-based Fast Ethernet
- 1259 2560 AT-2560 100
- 1259 2561 AT-2560 100 FX Ethernet Adapter
- 1266 0001 NE10/100 Adapter
- 13e9 1000 6221L-4U
- 144d 2501 SEM-2000 MiniPCI LAN Adapter
- 144d 2502 SEM-2100IL MiniPCI LAN Adapter
- 1668 1100 EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)
- 4c53 1080 CT8 mainboard
- 8086 0001 EtherExpress PRO/100B (TX)
- 8086 0002 EtherExpress PRO/100B (T4)
- 8086 0003 EtherExpress PRO/10+
- 8086 0004 EtherExpress PRO/100 WfM
- 8086 0005 82557 10/100
- 8086 0006 82557 10/100 with Wake on LAN
- 8086 0007 82558 10/100 Adapter
- 8086 0008 82558 10/100 with Wake on LAN
- 8086 0009 EtherExpress PRO/100+
- 8086 000a EtherExpress PRO/100+ Management Adapter
- 8086 000b EtherExpress PRO/100+
- 8086 000c EtherExpress PRO/100+ Management Adapter
- 8086 000d EtherExpress PRO/100+ Alert On LAN II* Adapter
- 8086 000e EtherExpress PRO/100+ Management Adapter with Alert On LAN*
- 8086 000f EtherExpress PRO/100 Desktop Adapter
- 8086 0010 EtherExpress PRO/100 S Management Adapter
- 8086 0011 EtherExpress PRO/100 S Management Adapter
- 8086 0012 EtherExpress PRO/100 S Advanced Management Adapter (D)
- 8086 0013 EtherExpress PRO/100 S Advanced Management Adapter (E)
- 8086 0030 EtherExpress PRO/100 Management Adapter with Alert On LAN* GC
- 8086 0031 EtherExpress PRO/100 Desktop Adapter
- 8086 0040 EtherExpress PRO/100 S Desktop Adapter
- 8086 0041 EtherExpress PRO/100 S Desktop Adapter
- 8086 0042 EtherExpress PRO/100 Desktop Adapter
- 8086 0050 EtherExpress PRO/100 S Desktop Adapter
- 8086 1009 EtherExpress PRO/100+ Server Adapter
- 8086 100c EtherExpress PRO/100+ Server Adapter (PILA8470B)
- 8086 1012 EtherExpress PRO/100 S Server Adapter (D)
- 8086 1013 EtherExpress PRO/100 S Server Adapter (E)
- 8086 1015 EtherExpress PRO/100 S Dual Port Server Adapter
- 8086 1017 EtherExpress PRO/100+ Dual Port Server Adapter
- 8086 1030 EtherExpress PRO/100+ Management Adapter with Alert On LAN* G Server
- 8086 1040 EtherExpress PRO/100 S Server Adapter
- 8086 1041 EtherExpress PRO/100 S Server Adapter
- 8086 1042 EtherExpress PRO/100 Server Adapter
- 8086 1050 EtherExpress PRO/100 S Server Adapter
- 8086 1051 EtherExpress PRO/100 Server Adapter
- 8086 1052 EtherExpress PRO/100 Server Adapter
- 8086 10f0 EtherExpress PRO/100+ Dual Port Adapter
- 8086 2009 EtherExpress PRO/100 S Mobile Adapter
- 8086 200d EtherExpress PRO/100 Cardbus
- 8086 200e EtherExpress PRO/100 LAN+V90 Cardbus Modem
- 8086 200f EtherExpress PRO/100 SR Mobile Adapter
- 8086 2010 EtherExpress PRO/100 S Mobile Combo Adapter
- 8086 2013 EtherExpress PRO/100 SR Mobile Combo Adapter
- 8086 2016 EtherExpress PRO/100 S Mobile Adapter
- 8086 2017 EtherExpress PRO/100 S Combo Mobile Adapter
- 8086 2018 EtherExpress PRO/100 SR Mobile Adapter
- 8086 2019 EtherExpress PRO/100 SR Combo Mobile Adapter
- 8086 2101 EtherExpress PRO/100 P Mobile Adapter
- 8086 2102 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2103 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2104 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2105 EtherExpress PRO/100 SP Mobile Adapter
- 8086 2106 EtherExpress PRO/100 P Mobile Adapter
- 8086 2107 EtherExpress PRO/100 Network Connection
- 8086 2108 EtherExpress PRO/100 Network Connection
- 8086 2200 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2201 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2202 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2203 EtherExpress PRO/100+ MiniPCI
- 8086 2204 EtherExpress PRO/100+ MiniPCI
- 8086 2205 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2206 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2207 EtherExpress PRO/100 SP Mobile Combo Adapter
- 8086 2208 EtherExpress PRO/100 P Mobile Combo Adapter
- 8086 2402 EtherExpress PRO/100+ MiniPCI
- 8086 2407 EtherExpress PRO/100+ MiniPCI
- 8086 2408 EtherExpress PRO/100+ MiniPCI
- 8086 2409 EtherExpress PRO/100+ MiniPCI
- 8086 240f EtherExpress PRO/100+ MiniPCI
- 8086 2410 EtherExpress PRO/100+ MiniPCI
- 8086 2411 EtherExpress PRO/100+ MiniPCI
- 8086 2412 EtherExpress PRO/100+ MiniPCI
- 8086 2413 EtherExpress PRO/100+ MiniPCI
- 8086 3000 82559 Fast Ethernet LAN on Motherboard
- 8086 3001 82559 Fast Ethernet LOM with Basic Alert on LAN*
- 8086 3002 82559 Fast Ethernet LOM with Alert on LAN II*
- 8086 3006 EtherExpress PRO/100 S Network Connection
- 8086 3007 EtherExpress PRO/100 S Network Connection
- 8086 3008 EtherExpress PRO/100 Network Connection
- 8086 3010 EtherExpress PRO/100 S Network Connection
- 8086 3011 EtherExpress PRO/100 S Network Connection
- 8086 3012 EtherExpress PRO/100 Network Connection
- 8086 3411 SDS2 Mainboard
- 122d 430FX - 82437FX TSC [Triton I]
- 122e 82371FB PIIX ISA [Triton I]
- 1230 82371FB PIIX IDE [Triton I]
- 1231 DSVD Modem
- 1234 430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)
- 1235 430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP)
- 1237 440FX - 82441FX PMC [Natoma]
- 1239 82371FB PIIX IDE Interface
- 123b 82380PB PCI to PCI Docking Bridge
- 123c 82380AB (MISA) Mobile PCI-to-ISA Bridge
- 123d 683053 Programmable Interrupt Device
-# in" hidden" mode
- 123e 82466GX (IHPC) Integrated Hot-Plug Controller
- 123f 82466GX Integrated Hot-Plug Controller (IHPC)
- 1240 82752 (752) AGP Graphics Accelerator
- 124b 82380FB (MPCI2) Mobile Docking Controller
- 1250 430HX - 82439HX TXC [Triton II]
- 1360 82806AA PCI64 Hub PCI Bridge
- 1361 82806AA PCI64 Hub Controller (HRes)
- 8086 1361 82806AA PCI64 Hub Controller (HRes)
- 8086 8000 82806AA PCI64 Hub Controller (HRes)
- 1460 82870P2 P64H2 Hub PCI Bridge
- 1461 82870P2 P64H2 I/OxAPIC
- 15d9 3480 P4DP6
- 4c53 1090 Cx9 / Vx9 mainboard
- 1462 82870P2 P64H2 Hot Plug Controller
- 1960 80960RP [i960RP Microprocessor]
- 101e 0431 MegaRAID 431 RAID Controller
- 101e 0438 MegaRAID 438 Ultra2 LVD RAID Controller
- 101e 0466 MegaRAID 466 Express Plus RAID Controller
- 101e 0467 MegaRAID 467 Enterprise 1500 RAID Controller
- 101e 0490 MegaRAID 490 Express 300 RAID Controller
- 101e 0762 MegaRAID 762 Express RAID Controller
- 101e 09a0 PowerEdge Expandable RAID Controller 2/SC
- 1028 0467 PowerEdge Expandable RAID Controller 2/DC
- 1028 1111 PowerEdge Expandable RAID Controller 2/SC
- 103c 03a2 MegaRAID
- 103c 10c6 MegaRAID 438, HP NetRAID-3Si
- 103c 10c7 MegaRAID T5, Integrated HP NetRAID
- 103c 10cc MegaRAID, Integrated HP NetRAID
- 103c 10cd HP NetRAID-1Si
- 105a 0000 SuperTrak
- 105a 2168 SuperTrak Pro
- 105a 5168 SuperTrak66/100
- 1111 1111 MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC
- 1111 1112 PowerEdge Expandable RAID Controller 2/SC
- 113c 03a2 MegaRAID
- e4bf 1010 CG1-RADIO
- e4bf 1020 CU2-QUARTET
- e4bf 1040 CU1-CHORUS
- e4bf 3100 CX1-BAND
- 1962 80960RM [i960RM Microprocessor]
- 105a 0000 SuperTrak SX6000 I2O CPU
- 1a21 82840 840 (Carmel) Chipset Host Bridge (Hub A)
- 1a23 82840 840 (Carmel) Chipset AGP Bridge
- 1a24 82840 840 (Carmel) Chipset PCI Bridge (Hub B)
- 1a30 82845 845 (Brookdale) Chipset Host Bridge
- 1028 010e Optiplex GX240
- 1a31 82845 845 (Brookdale) Chipset AGP Bridge
- 2410 82801AA ISA Bridge (LPC)
- 2411 82801AA IDE
- 2412 82801AA USB
- 2413 82801AA SMBus
- 2415 82801AA AC'97 Audio
- 1028 0095 Precision Workstation 220 Integrated Digital Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 11d4 5340 SoundMAX Integrated Digital Audio
- 2416 82801AA AC'97 Modem
- 2418 82801AA PCI Bridge
- 2420 82801AB ISA Bridge (LPC)
- 2421 82801AB IDE
- 2422 82801AB USB
- 2423 82801AB SMBus
- 2425 82801AB AC'97 Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 2426 82801AB AC'97 Modem
- 2428 82801AB PCI Bridge
- 2440 82801BA ISA Bridge (LPC)
- 2442 82801BA/BAM USB (Hub #1)
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 2443 82801BA/BAM SMBus
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 2444 82801BA/BAM USB (Hub #2)
- 1025 1016 Travelmate 612 TX
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 104d 80df Vaio PCG-FX403
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 2445 82801BA/BAM AC'97 Audio
- 1014 01c6 Netvista A40/A40p
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 1462 3370 STAC9721 AC
- 147b 0507 TH7II-RAID
- 8086 4557 D815EGEW Mainboard
- 2446 82801BA/BAM AC'97 Modem
- 1025 1016 Travelmate 612 TX
- 104d 80df Vaio PCG-FX403
- 2448 82801 Mobile PCI Bridge
- 2449 82801BA/BAM/CA/CAM Ethernet Controller
- 0e11 0012 EtherExpress PRO/100 VM
- 0e11 0091 EtherExpress PRO/100 VE
- 1014 01ce EtherExpress PRO/100 VE
- 1014 01dc EtherExpress PRO/100 VE
- 1014 01eb EtherExpress PRO/100 VE
- 1014 01ec EtherExpress PRO/100 VE
- 1014 0202 EtherExpress PRO/100 VE
- 1014 0205 EtherExpress PRO/100 VE
- 1014 0217 EtherExpress PRO/100 VE
- 1014 0234 EtherExpress PRO/100 VE
- 1014 023d EtherExpress PRO/100 VE
- 1014 0244 EtherExpress PRO/100 VE
- 1014 0245 EtherExpress PRO/100 VE
- 1014 0265 PRO/100 VE Desktop Connection
- 1014 0267 PRO/100 VE Desktop Connection
- 1014 026a PRO/100 VE Desktop Connection
- 109f 315d EtherExpress PRO/100 VE
- 109f 3181 EtherExpress PRO/100 VE
- 1179 ff01 PRO/100 VE Network Connection
- 1186 7801 EtherExpress PRO/100 VE
- 144d 2602 HomePNA 1M CNR
- 8086 3010 EtherExpress PRO/100 VE
- 8086 3011 EtherExpress PRO/100 VM
- 8086 3012 82562EH based Phoneline
- 8086 3013 EtherExpress PRO/100 VE
- 8086 3014 EtherExpress PRO/100 VM
- 8086 3015 82562EH based Phoneline
- 8086 3016 EtherExpress PRO/100 P Mobile Combo
- 8086 3017 EtherExpress PRO/100 P Mobile
- 8086 3018 EtherExpress PRO/100
- 244a 82801BAM IDE U100
- 1025 1016 Travelmate 612TX
- 104d 80df Vaio PCG-FX403
- 244b 82801BA IDE U100
- 1014 01c6 Netvista A40/A40p
- 1028 010e Optiplex GX240
- 1043 8027 TUSL2-C Mainboard
- 147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
- 8086 4557 D815EGEW Mainboard
- 244c 82801BAM ISA Bridge (LPC)
- 244e 82801 PCI Bridge
- 1014 0267 NetVista A30p
- 2450 82801E ISA Bridge (LPC)
- 2452 82801E USB
- 2453 82801E SMBus
- 2459 82801E Ethernet Controller 0
- 245b 82801E IDE U100
- 245d 82801E Ethernet Controller 1
- 245e 82801E PCI Bridge
- 2480 82801CA LPC Interface Controller
- 2482 82801CA/CAM USB (Hub #1)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 8086 3424 SE7501HG2 Mainboard
- 8086 4541 Latitude C640
- 2483 82801CA/CAM SMBus Controller
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 2484 82801CA/CAM USB (Hub #2)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 2485 82801CA/CAM AC'97 Audio Controller
- 1013 5959 Crystal WMD Audio Codec
- 1014 0222 ThinkPad T23 (2647-4MG) or A30/A30p (2652/2653)
- 1014 0508 ThinkPad T30
- 1014 051c ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 144d c006 vpr Matrix 170B4
- 2486 82801CA/CAM AC'97 Modem Controller
- 1014 0223 ThinkPad A/T/X Series
- 1014 0503 ThinkPad R31 2656BBG
- 1014 051a ThinkPad A/T/X Series
- 101f 1025 Acer 620 Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 1179 0001 Toshiba Satellite 1110 Z15 internal Modem
- 134d 4c21 Dell Inspiron 2100 internal modem
- 144d 2115 vpr Matrix 170B4 internal modem
- 14f1 5421 MD56ORD V.92 MDC Modem
- 2487 82801CA/CAM USB (Hub #3)
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 15d9 3480 P4DP6
- 8086 1958 vpr Matrix 170B4
- 248a 82801CAM IDE U100
- 1014 0220 ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 8086 1958 vpr Matrix 170B4
- 8086 4541 Latitude C640
- 248b 82801CA Ultra ATA Storage Controller
- 15d9 3480 P4DP6
- 248c 82801CAM ISA Bridge (LPC)
- 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge
- 1014 0267 NetVista A30p
- 1462 5800 845PE Max (MS-6580)
- 24c1 82801DBL (ICH4-L) IDE Controller
- 24c2 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H laptop
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c3 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1458 24c2 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c4 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24c5 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
- 0e11 00b8 Analog Devices Inc. codec [SoundMAX]
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1458 a002 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 24c7 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 5800 845PE Max (MS-6580)
- 1509 2990 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24ca 82801DBM (ICH4-M) IDE Controller
- 1025 005a TravelMate 290
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 24cb 82801DB (ICH4) IDE Controller
- 1014 0267 NetVista A30p
- 1028 0126 Optiplex GX260
- 1458 24c2 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 4c53 1090 Cx9 / Vx9 mainboard
- 24cc 82801DBM (ICH4-M) LPC Interface Bridge
- 24cd 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller
- 1014 0267 NetVista A30p
- 1025 005a TravelMate 290
- 1028 0126 Optiplex GX260
- 1028 0163 Latitude D505
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 1071 8160 MIM2000
- 1462 3981 845PE Max (MS-6580)
- 1509 1968 Averatec 5110H
- 4c53 1090 Cx9 / Vx9 mainboard
- 24d0 82801EB/ER (ICH5/ICH5R) LPC Interface Bridge
- 24d1 82801EB (ICH5) SATA Controller
- 103c 12bc d530 CMT (DG746A)
- 1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000/8KNXP motherboard
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
- 103c 12bc Analog Devices codec [SoundMAX Integrated Digital Audio]
- 1043 80f3 P4P800 Mainboard
-# Again, I suppose they use the same in different subsystems
- 1458 a002 GA-8IPE1000/8KNXP motherboard
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 a000 D865PERL mainboard
- 8086 e000 D865PERL mainboard
- 24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller
- 24d7 82801EB/ER (ICH5/ICH5R) USB UHCI #3
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24db 82801EB/ER (ICH5/ICH5R) IDE Controller
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 1462 7580 MSI 875P
- 8086 24db P4C800 Mainboard
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24dc 82801EB (ICH5) LPC Interface Bridge
- 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
- 1028 0183 PowerEdge 1800
- 103c 12bc d530 CMT (DG746A)
- 1043 80a6 P4P800 Mainboard
- 1458 5006 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24de 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4
- 1043 80a6 P4P800 Mainboard
- 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
- 1462 7280 865PE Neo2 (MS-6728)
- 8086 3427 S875WP1-E mainboard
- 8086 524c D865PERL mainboard
- 24df 82801ER (ICH5R) SATA Controller
- 2500 82820 820 (Camino) Chipset Host Bridge (MCH)
- 1028 0095 Precision Workstation 220 Chipset
- 1043 801c P3C-2000 system chipset
- 2501 82820 820 (Camino) Chipset Host Bridge (MCH)
- 1043 801c P3C-2000 system chipset
- 250b 82820 820 (Camino) Chipset Host Bridge
- 250f 82820 820 (Camino) Chipset AGP Bridge
- 2520 82805AA MTH Memory Translator Hub
- 2521 82804AA MRH-S Memory Repeater Hub for SDRAM
- 2530 82850 850 (Tehama) Chipset Host Bridge (MCH)
- 147b 0507 TH7II-RAID
- 2531 82860 860 (Wombat) Chipset Host Bridge (MCH)
- 2532 82850 850 (Tehama) Chipset AGP Bridge
- 2533 82860 860 (Wombat) Chipset AGP Bridge
- 2534 82860 860 (Wombat) Chipset PCI Bridge
- 2540 E7500 Memory Controller Hub
- 15d9 3480 P4DP6
- 2541 E7500/E7501 Host RASUM Controller
- 15d9 3480 P4DP6
- 4c53 1090 Cx9 / Vx9 mainboard
- 8086 3424 SE7501HG2 Mainboard
- 2543 E7500/E7501 Hub Interface B PCI-to-PCI Bridge
- 2544 E7500/E7501 Hub Interface B RASUM Controller
- 4c53 1090 Cx9 / Vx9 mainboard
- 2545 E7500/E7501 Hub Interface C PCI-to-PCI Bridge
- 2546 E7500/E7501 Hub Interface C RASUM Controller
- 2547 E7500/E7501 Hub Interface D PCI-to-PCI Bridge
- 2548 E7500/E7501 Hub Interface D RASUM Controller
- 254c E7501 Memory Controller Hub
- 4c53 1090 Cx9 / Vx9 mainboard
- 8086 3424 SE7501HG2 Mainboard
- 2550 E7505 Memory Controller Hub
- 2551 E7505/E7205 Series RAS Controller
- 2552 E7505/E7205 PCI-to-AGP Bridge
- 2553 E7505 Hub Interface B PCI-to-PCI Bridge
- 2554 E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
- 255d E7205 Memory Controller Hub
- 2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
- 1028 0126 Optiplex GX260
- 1458 2560 GA-8PE667 Ultra
- 1462 5800 845PE Max (MS-6580)
- 2561 82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge
- 2562 82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device
- 1014 0267 NetVista A30p
- 2570 82865G/PE/P DRAM Controller/Host-Hub Interface
- 1043 80f2 P4P800 Mainboard
- 1458 2570 GA-8IPE1000 Pro2 motherboard (865PE)
- 2571 82865G/PE/P PCI to AGP Controller
- 2572 82865G Integrated Graphics Controller
- 2573 82865G/PE/P PCI to CSA Bridge
- 2576 82865G/PE/P Processor to I/O Memory Interface
- 2578 82875P/E7210 Memory Controller Hub
- 1458 2578 GA-8KNXP motherboard (875P)
- 1462 7580 MS-6758 (875P Neo)
-# Motherboard P4SCE
- 15d9 4580 Super Micro Computer Inc. P4SCE
- 2579 82875P Processor to AGP Controller
- 257b 82875P/E7210 Processor to PCI to CSA Bridge
- 257e 82875P/E7210 Processor to I/O Memory Interface
- 2580 915G/P/GV/GL/PL/910GL Processor to I/O Controller
- 2581 915G/P/GV/GL/PL/910GL PCI Express Root Port
- 2582 82915G/GV/910GL Express Chipset Family Graphics Controller
- 1028 1079 Optiplex GX280
- 2584 925X/XE Memory Controller Hub
- 2585 925X/XE PCI Express Root Port
- 2588 E7220/E7221 Memory Controller Hub
- 2589 E7220/E7221 PCI Express Root Port
- 258a E7221 Integrated Graphics Controller
- 2590 Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller
- 2591 Mobile 915GM/PM Express PCI Express Root Port
- 2592 Mobile 915GM/GMS/910GML Express Graphics Controller
- 25a1 6300ESB LPC Interface Controller
- 25a2 6300ESB PATA Storage Controller
- 4c53 10b0 CL9 mainboard
- 25a3 6300ESB SATA Storage Controller
- 4c53 10b0 CL9 mainboard
- 25a4 6300ESB SMBus Controller
- 4c53 10b0 CL9 mainboard
- 25a6 6300ESB AC'97 Audio Controller
- 4c53 10b0 CL9 mainboard
- 25a7 6300ESB AC'97 Modem Controller
- 25a9 6300ESB USB Universal Host Controller
- 4c53 10b0 CL9 mainboard
- 25aa 6300ESB USB Universal Host Controller
- 4c53 10b0 CL9 mainboard
- 25ab 6300ESB Watchdog Timer
- 4c53 10b0 CL9 mainboard
- 25ac 6300ESB I/O Advanced Programmable Interrupt Controller
- 4c53 10b0 CL9 mainboard
- 25ad 6300ESB USB2 Enhanced Host Controller
- 25ae 6300ESB 64-bit PCI-X Bridge
- 25b0 6300ESB SATA RAID Controller
- 2600 E8500 Hub Interface
- 2601 E8500 PCI Express x4 Port D
- 2602 E8500 PCI Express x4 Port C0
- 2603 E8500 PCI Express x4 Port C1
- 2604 E8500 PCI Express x4 Port B0
- 2605 E8500 PCI Express x4 Port B1
- 2606 E8500 PCI Express x4 Port A0
- 2607 E8500 PCI Express x4 Port A1
- 2608 E8500 PCI Express x8 Port C
- 2609 E8500 PCI Express x8 Port B
- 260a E8500 PCI Express x8 Port A
- 260c E8500 IMI Registers
- 2610 E8500 System Bus, Boot, and Interrupt Registers
- 2611 E8500 Address Mapping Registers
- 2612 E8500 RAS Registers
- 2613 E8500 Reserved Registers
- 2614 E8500 Reserved Registers
- 2615 E8500 Miscellaneous Registers
- 2617 E8500 Reserved Registers
- 2618 E8500 Reserved Registers
- 2619 E8500 Reserved Registers
- 261a E8500 Reserved Registers
- 261b E8500 Reserved Registers
- 261c E8500 Reserved Registers
- 261d E8500 Reserved Registers
- 261e E8500 Reserved Registers
- 2620 E8500 eXternal Memory Bridge
- 2621 E8500 XMB Miscellaneous Registers
- 2622 E8500 XMB Memory Interleaving Registers
- 2623 E8500 XMB DDR Initialization and Calibration
- 2624 E8500 XMB Reserved Registers
- 2625 E8500 XMB Reserved Registers
- 2626 E8500 XMB Reserved Registers
- 2627 E8500 XMB Reserved Registers
- 2640 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge
- 2641 82801FBM (ICH6M) LPC Interface Bridge
- 2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
- 2651 82801FB/FW (ICH6/ICH6W) SATA Controller
- 1028 0179 Optiplex GX280
- 2652 82801FR/FRW (ICH6R/ICH6RW) SATA Controller
- 2653 82801FBM (ICH6M) SATA Controller
- 2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
- 1028 0179 Optiplex GX280
- 2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
- 1028 0179 Optiplex GX280
- 265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
- 1028 0179 Optiplex GX280
- 265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
- 1028 0179 Optiplex GX280
- 265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
- 1028 0179 Optiplex GX280
- 2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
- 2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
- 2664 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
- 2666 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
- 2668 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
- 266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
- 1028 0179 Optiplex GX280
- 266c 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
- 266d 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
- 266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
- 1028 0179 Optiplex GX280
- 266f 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
- 2770 Memory Controller Hub
- 2771 PCI Express Graphics Port
- 2772 Integrated Graphics Controller
- 2774 Workstation Memory Controller Hub
- 2775 PCI Express Graphics Port
- 2776 Integrated Graphics Controller
- 2778 Server Memory Controller Hub
- 2779 PCI Express Root Port
- 2782 82915G Express Chipset Family Graphics Controller
- 2792 Mobile 915GM/GMS/910GML Express Graphics Controller
- 27b8 I/O Controller Hub LPC
- 27b9 Mobile I/O Controller Hub LPC
- 27c0 I/O Controller Hub SATA cc=IDE
- 27c1 I/O Controller Hub SATA cc=AHCI
- 27c3 I/O Controller Hub SATA cc=RAID
- 27c4 Mobile I/O Controller Hub SATA cc=IDE
- 27c5 Mobile I/O Controller Hub SATA cc=AHCI
- 27c8 I/O Controller Hub UHCI USB #1
- 27c9 I/O Controller Hub UHCI USB #2
- 27ca I/O Controller Hub UHCI USB #3
- 27cb I/O Controller Hub UHCI USB #4
- 27cc I/O Controller Hub EHCI USB
- 27d0 I/O Controller Hub PCI Express Port 1
- 27d2 I/O Controller Hub PCI Express Port 2
- 27d4 I/O Controller Hub PCI Express Port 3
- 27d6 I/O Controller Hub PCI Express Port 4
- 27d8 I/O Controller Hub High Definition Audio
- 27da I/O Controller Hub SMBus
- 27dc I/O Controller Hub LAN
- 27dd I/O Controller Hub AC'97 Modem
- 27de I/O Controller Hub AC'97 Audio
- 27df I/O Controller Hub PATA
- 27e0 I/O Controller Hub PCI Express Port 5
- 27e2 I/O Controller Hub PCI Express Port 6
- 3092 Integrated RAID
- 3200 GD31244 PCI-X SATA HBA
- 3340 82855PM Processor to I/O Controller
- 1025 005a TravelMate 290
- 103c 088c nc8000 laptop
- 103c 0890 nc6000 laptop
- 3341 82855PM Processor to AGP Controller
- 3575 82830 830 Chipset Host Bridge
- 1014 021d ThinkPad A/T/X Series
- 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
- 3576 82830 830 Chipset AGP Bridge
- 3577 82830 CGC [Chipset Graphics Controller]
- 1014 0513 ThinkPad A/T/X Series
- 3578 82830 830 Chipset Host Bridge
- 3580 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3581 82852/82855 GM/GME/PM/GMV Processor to AGP Controller
- 3582 82852/855GM Integrated Graphics Device
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3584 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3585 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
- 1028 0163 Latitude D505
- 4c53 10b0 CL9 mainboard
- 3590 E7520 Memory Controller Hub
- 3591 E7525/E7520 Error Reporting Registers
- 3592 E7320 Memory Controller Hub
- 3593 E7320 Error Reporting Registers
- 3594 E7520 DMA Controller
- 3595 E7525/E7520/E7320 PCI Express Port A
- 3596 E7525/E7520/E7320 PCI Express Port A1
- 3597 E7525/E7520 PCI Express Port B
- 3598 E7520 PCI Express Port B1
- 3599 E7520 PCI Express Port C
- 359a E7520 PCI Express Port C1
- 359b E7525/E7520/E7320 Extended Configuration Registers
- 359e E7525 Memory Controller Hub
- 4220 PRO/Wireless 2200BG
- 4223 PRO/Wireless 2915ABG MiniPCI Adapter
- 5200 EtherExpress PRO/100 Intelligent Server
- 5201 EtherExpress PRO/100 Intelligent Server
- 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter
- 530d 80310 IOP [IO Processor]
- 7000 82371SB PIIX3 ISA [Natoma/Triton II]
- 7010 82371SB PIIX3 IDE [Natoma/Triton II]
- 7020 82371SB PIIX3 USB [Natoma/Triton II]
- 7030 430VX - 82437VX TVX [Triton VX]
- 7050 Intel Intercast Video Capture Card
- 7100 430TX - 82439TX MTXC
- 7110 82371AB/EB/MB PIIX4 ISA
- 15ad 1976 virtualHW v3
- 7111 82371AB/EB/MB PIIX4 IDE
- 15ad 1976 virtualHW v3
- 7112 82371AB/EB/MB PIIX4 USB
- 15ad 1976 virtualHW v3
- 7113 82371AB/EB/MB PIIX4 ACPI
- 15ad 1976 virtualHW v3
- 7120 82810 GMCH [Graphics Memory Controller Hub]
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 7121 82810 CGC [Chipset Graphics Controller]
- 4c53 1040 CL7 mainboard
- 4c53 1060 PC7 mainboard
- 8086 4341 Cayman (CA810) Mainboard
- 7122 82810 DC-100 GMCH [Graphics Memory Controller Hub]
- 7123 82810 DC-100 CGC [Chipset Graphics Controller]
- 7124 82810E DC-133 GMCH [Graphics Memory Controller Hub]
- 7125 82810E DC-133 CGC [Chipset Graphics Controller]
- 7126 82810 DC-133 System and Graphics Controller
- 7128 82810-M DC-100 System and Graphics Controller
- 712a 82810-M DC-133 System and Graphics Controller
- 7180 440LX/EX - 82443LX/EX Host bridge
- 7181 440LX/EX - 82443LX/EX AGP bridge
- 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge
- 0e11 0500 Armada 1750 Laptop System Chipset
- 0e11 b110 Armada M700/E500
- 1179 0001 Toshiba Tecra 8100 Laptop System Chipset
- 15ad 1976 virtualHW v3
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge
- 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled)
- 0e11 0460 Armada 1700 Laptop System Chipset
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 7194 82440MX Host Bridge
- 1033 0000 Versa Note Vxi
- 4c53 10a0 CA3/CR3 mainboard
- 7195 82440MX AC'97 Audio Controller
- 1033 80cc Versa Note VXi
- 10cf 1099 QSound_SigmaTel Stac97 PCI Audio
- 11d4 0040 SoundMAX Integrated Digital Audio
- 11d4 0048 SoundMAX Integrated Digital Audio
- 7196 82440MX AC'97 Modem Controller
- 7198 82440MX ISA Bridge
- 7199 82440MX EIDE Controller
- 719a 82440MX USB Universal Host Controller
- 719b 82440MX Power Management Controller
- 71a0 440GX - 82443GX Host bridge
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- 71a1 440GX - 82443GX AGP bridge
- 71a2 440GX - 82443GX Host bridge (AGP disabled)
- 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard
- 7600 82372FB PIIX5 ISA
- 7601 82372FB PIIX5 IDE
- 7602 82372FB PIIX5 USB
- 7603 82372FB PIIX5 SMBus
- 7800 82740 (i740) AGP Graphics Accelerator
- 003d 0008 Starfighter AGP
- 003d 000b Starfighter AGP
- 1092 0100 Stealth II G460
- 10b4 201a Lightspeed 740
- 10b4 202f Lightspeed 740
- 8086 0000 Terminator 2x/i
- 8086 0100 Intel740 Graphics Accelerator
- 84c4 450KX/GX [Orion] - 82454KX/GX PCI bridge
- 84c5 450KX/GX [Orion] - 82453KX/GX Memory controller
- 84ca 450NX - 82451NX Memory & I/O Controller
- 84cb 450NX - 82454NX/84460GX PCI Expander Bridge
- 84e0 460GX - 84460GX System Address Controller (SAC)
- 84e1 460GX - 84460GX System Data Controller (SDC)
- 84e2 460GX - 84460GX AGP Bridge (GXB function 2)
- 84e3 460GX - 84460GX Memory Address Controller (MAC)
- 84e4 460GX - 84460GX Memory Data Controller (MDC)
- 84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
- 84ea 460GX - 84460GX AGP Bridge (GXB function 1)
- 8500 IXP4XX - Intel Network Processor family. IXP420, IXP421, IXP422, IXP425 and IXC1100
- 1993 0dee mGuard-PCI AV#1
- 1993 0def mGuard-PCI AV#0
- 9000 IXP2000 Family Network Processor
- 9001 IXP2400 Network Processor
- 9004 IXP2800 Network Processor
- 9621 Integrated RAID
- 9622 Integrated RAID
- 9641 Integrated RAID
- 96a1 Integrated RAID
-# retail verson
- a01f PRO/10GbE LR Server Adapter
-# OEM version
- a11f PRO/10GbE LR Server Adapter
- b152 21152 PCI-to-PCI Bridge
-# observed, and documented in Intel revision note; new mask of 1011:0026
- b154 21154 PCI-to-PCI Bridge
- b555 21555 Non transparent PCI-to-PCI Bridge
- 12d9 000a PCI VoIP Gateway
- 4c53 1050 CT7 mainboard
- 4c53 1051 CE7 mainboard
- e4bf 1000 CC8-1-BLUES
- ffff 450NX/GX [Orion] - 82453KX/GX Memory controller [BUG]
-8401 TRENDware International Inc.
-8800 Trigem Computer Inc.
- 2008 Video assistent component
-8866 T-Square Design Inc.
-8888 Silicon Magic
-# 8c4a is not Winbond but there is a board misprogrammed
-8c4a Winbond
- 1980 W89C940 misprogrammed [ne2k]
-8e0e Computone Corporation
-8e2e KTI
- 3000 ET32P2
-9004 Adaptec
- 0078 AHA-2940U_CN
- 1078 AIC-7810
- 1160 AIC-1160 [Family Fibre Channel Adapter]
- 2178 AIC-7821
- 3860 AHA-2930CU
- 3b78 AHA-4844W/4844UW
- 5075 AIC-755x
- 5078 AHA-7850
- 9004 7850 AHA-2904/Integrated AIC-7850
- 5175 AIC-755x
- 5178 AIC-7851
- 5275 AIC-755x
- 5278 AIC-7852
- 5375 AIC-755x
- 5378 AIC-7850
- 5475 AIC-755x
- 5478 AIC-7850
- 5575 AVA-2930
- 5578 AIC-7855
- 5647 ANA-7711 TCP Offload Engine
- 9004 7710 ANA-7711F TCP Offload Engine - Optical
- 9004 7711 ANA-7711LP TCP Offload Engine - Copper
- 5675 AIC-755x
- 5678 AIC-7856
- 5775 AIC-755x
- 5778 AIC-7850
- 5800 AIC-5800
- 5900 ANA-5910/5930/5940 ATM155 & 25 LAN Adapter
- 5905 ANA-5910A/5930A/5940A ATM Adapter
- 6038 AIC-3860
- 6075 AIC-1480 / APA-1480
- 9004 7560 AIC-1480 / APA-1480 Cardbus
- 6078 AIC-7860
- 6178 AIC-7861
- 9004 7861 AHA-2940AU Single
- 6278 AIC-7860
- 6378 AIC-7860
- 6478 AIC-786x
- 6578 AIC-786x
- 6678 AIC-786x
- 6778 AIC-786x
- 6915 ANA620xx/ANA69011A
- 9004 0008 ANA69011A/TX 10/100
- 9004 0009 ANA69011A/TX 10/100
- 9004 0010 ANA62022 2-port 10/100
- 9004 0018 ANA62044 4-port 10/100
- 9004 0019 ANA62044 4-port 10/100
- 9004 0020 ANA62022 2-port 10/100
- 9004 0028 ANA69011A/TX 10/100
- 9004 8008 ANA69011A/TX 64 bit 10/100
- 9004 8009 ANA69011A/TX 64 bit 10/100
- 9004 8010 ANA62022 2-port 64 bit 10/100
- 9004 8018 ANA62044 4-port 64 bit 10/100
- 9004 8019 ANA62044 4-port 64 bit 10/100
- 9004 8020 ANA62022 2-port 64 bit 10/100
- 9004 8028 ANA69011A/TX 64 bit 10/100
- 7078 AHA-294x / AIC-7870
- 7178 AHA-2940/2940W / AIC-7871
- 7278 AHA-3940/3940W / AIC-7872
- 7378 AHA-3985 / AIC-7873
- 7478 AHA-2944/2944W / AIC-7874
- 7578 AHA-3944/3944W / AIC-7875
- 7678 AHA-4944W/UW / AIC-7876
- 7710 ANA-7711F Network Accelerator Card (NAC) - Optical
- 7711 ANA-7711C Network Accelerator Card (NAC) - Copper
- 7778 AIC-787x
- 7810 AIC-7810
- 7815 AIC-7815 RAID+Memory Controller IC
- 9004 7815 ARO-1130U2 RAID Controller
- 9004 7840 AIC-7815 RAID+Memory Controller IC
- 7850 AIC-7850
- 7855 AHA-2930
- 7860 AIC-7860
- 7870 AIC-7870
- 7871 AHA-2940
- 7872 AHA-3940
- 7873 AHA-3980
- 7874 AHA-2944
- 7880 AIC-7880P
- 7890 AIC-7890
- 7891 AIC-789x
- 7892 AIC-789x
- 7893 AIC-789x
- 7894 AIC-789x
- 7895 AHA-2940U/UW / AHA-39xx / AIC-7895
- 9004 7890 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7891 AHA-2940U/2940UW Dual
- 9004 7892 AHA-3940AU/AUW/AUWD/UWD
- 9004 7894 AHA-3944AUWD
- 9004 7895 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7896 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 9004 7897 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B
- 7896 AIC-789x
- 7897 AIC-789x
- 8078 AIC-7880U
- 9004 7880 AIC-7880P Ultra/Ultra Wide SCSI Chipset
- 8178 AHA-2940U/UW/D / AIC-7881U
- 9004 7881 AHA-2940UW SCSI Host Adapter
- 8278 AHA-3940U/UW/UWD / AIC-7882U
- 8378 AHA-3940U/UW / AIC-7883U
- 8478 AHA-2944UW / AIC-7884U
- 8578 AHA-3944U/UWD / AIC-7885
- 8678 AHA-4944UW / AIC-7886
- 8778 AHA-2940UW Pro / AIC-788x
- 9004 7887 2940UW Pro Ultra-Wide SCSI Controller
- 8878 AHA-2930UW / AIC-7888
- 9004 7888 AHA-2930UW SCSI Controller
- 8b78 ABA-1030
- ec78 AHA-4944W/UW
-9005 Adaptec
- 0010 AHA-2940U2/U2W
- 9005 2180 AHA-2940U2 SCSI Controller
- 9005 8100 AHA-2940U2B SCSI Controller
- 9005 a100 AHA-2940U2B SCSI Controller
- 9005 a180 AHA-2940U2W SCSI Controller
- 9005 e100 AHA-2950U2B SCSI Controller
- 0011 AHA-2930U2
- 0013 78902
- 9005 0003 AAA-131U2 Array1000 1 Channel RAID Controller
- 9005 000f AIC7890_ARO
- 001f AHA-2940U2/U2W / 7890/7891
- 9005 000f 2940U2W SCSI Controller
- 9005 a180 2940U2W SCSI Controller
- 0020 AIC-7890
- 002f AIC-7890
- 0030 AIC-7890
- 003f AIC-7890
- 0050 AHA-3940U2x/395U2x
- 9005 f500 AHA-3950U2B
- 9005 ffff AHA-3950U2B
- 0051 AHA-3950U2D
- 9005 b500 AHA-3950U2D
- 0053 AIC-7896 SCSI Controller
- 9005 ffff AIC-7896 SCSI Controller mainboard implementation
- 005f AIC-7896U2/7897U2
- 0080 AIC-7892A U160/m
- 0e11 e2a0 Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter
- 9005 6220 AHA-29160C
- 9005 62a0 29160N Ultra160 SCSI Controller
- 9005 e220 29160LP Low Profile Ultra160 SCSI Controller
- 9005 e2a0 29160 Ultra160 SCSI Controller
- 0081 AIC-7892B U160/m
- 9005 62a1 19160 Ultra160 SCSI Controller
- 0083 AIC-7892D U160/m
- 008f AIC-7892P U160/m
- 1179 0001 Magnia Z310
- 15d9 9005 Onboard SCSI Host Adapter
- 00c0 AHA-3960D / AIC-7899A U160/m
- 0e11 f620 Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter
- 9005 f620 AHA-3960D U160/m
- 00c1 AIC-7899B U160/m
- 00c3 AIC-7899D U160/m
- 00c5 RAID subsystem HBA
- 1028 00c5 PowerEdge 2400,2500,2550,4400
- 00cf AIC-7899P U160/m
- 1028 00ce PowerEdge 1400
- 1028 00d1 PowerEdge 2550
- 1028 00d9 PowerEdge 2500
- 10f1 2462 Thunder K7 S2462
- 15d9 9005 Onboard SCSI Host Adapter
- 8086 3411 SDS2 Mainboard
- 0250 ServeRAID Controller
- 1014 0279 ServeRAID-xx
- 1014 028c ServeRAID-xx
-# from kernel sources
- 0279 ServeRAID 6M
- 0283 AAC-RAID
- 9005 0283 Catapult
- 0284 AAC-RAID
- 9005 0284 Tomcat
- 0285 AAC-RAID
- 0e11 0295 SATA 6Ch (Bearcat)
- 1014 02f2 ServeRAID 8i
- 1028 0287 PowerEdge Expandable RAID Controller 320/DC
- 1028 0291 CERC SATA RAID 2 PCI SATA 6ch (DellCorsair)
- 103c 3227 AAR-2610SA
- 17aa 0286 Legend S220 (Legend Crusader)
- 17aa 0287 Legend S230 (Legend Vulcan)
- 9005 0285 2200S (Vulcan)
- 9005 0286 2120S (Crusader)
- 9005 0287 2200S (Vulcan-2m)
- 9005 0288 3230S (Harrier)
- 9005 0289 3240S (Tornado)
- 9005 028a ASR-2020S PCI-X ZCR (Skyhawk)
- 9005 028b ASR-2020S SO-DIMM PCI-X ZCR (Terminator)
- 9005 0290 AAR-2410SA PCI SATA 4ch (Jaguar II)
- 9005 0292 AAR-2810SA PCI SATA 8ch (Corsair-8)
- 9005 0293 AAR-21610SA PCI SATA 16ch (Corsair-16)
- 9005 0294 ESD SO-DIMM PCI-X SATA ZCR (Prowler)
- 0286 AAC-RAID (Rocket)
- 9005 028c ASR-2230S + ASR-2230SLP PCI-X (Lancer)
- 0503 Scamp chipset SCSI controller
- 1014 02BF Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E)
- 8000 ASC-29320A U320
- 800f AIC-7901 U320
- 8010 ASC-39320 U320
- 8011 ASC-32320D U320
- 0e11 00ac ASC-39320D U320
- 9005 0041 ASC-39320D U320
- 8012 ASC-29320 U320
- 8013 ASC-29320B U320
- 8014 ASC-29320LP U320
- 8015 ASC-39320B U320
- 8016 ASC-39320A U320
- 8017 ASC-29320ALP U320
- 801c ASC-39320D U320
- 801d AIC-7902B U320
- 801e AIC-7901A U320
- 801f AIC-7902 U320
- 8080 ASC-29320A U320 w/HostRAID
- 808f AIC-7901 U320 w/HostRAID
- 8090 ASC-39320 U320 w/HostRAID
- 8091 ASC-39320D U320 w/HostRAID
- 8092 ASC-29320 U320 w/HostRAID
- 8093 ASC-29320B U320 w/HostRAID
- 8094 ASC-29320LP U320 w/HostRAID
- 8095 ASC-39320(B) U320 w/HostRAID
- 8096 ASC-39320A U320 w/HostRAID
- 8097 ASC-29320ALP U320 w/HostRAID
- 809c ASC-39320D(B) U320 w/HostRAID
- 809d AIC-7902(B) U320 w/HostRAID
- 809e AIC-7901A U320 w/HostRAID
- 809f AIC-7902 U320 w/HostRAID
-907f Atronics
- 2015 IDE-2015PL
-919a Gigapixel Corp
-9412 Holtek
- 6565 6565
-9699 Omni Media Technology Inc
- 6565 6565
-9710 NetMos Technology
- 7780 USB IRDA-port
- 9705 PCI 9705 Parallel Port
- 9715 PCI 9715 Dual Parallel Port
- 9735 PCI 9735 Multi-I/O Controller
- 1000 0002 0P2S (2 serial)
- 1000 0012 1P2S (1 parallel + 2 serial)
- 9745 PCI 9745 Multi-I/O Controller
- 1000 0002 0P2S (2 serial)
- 1000 0012 1P2S (1 parallel + 2 serial)
- 9755 PCI 9755 Parallel Port and ISA Bridge
- 9805 PCI 9805 Parallel Port
- 9815 PCI 9815 Dual Parallel Port
- 1000 0020 2P0S (2 port parallel adaptor)
- 9835 PCI 9835 Multi-I/O Controller
- 1000 0002 0P2S (16C550 UART)
- 1000 0012 1P2S
- 9845 PCI 9845 Multi-I/O Controller
- 1000 0004 0P4S (4 port 16550A serial card)
- 1000 0006 0P6S (6 port 16550A serial card)
- 1000 0014 1P4S (4 port 16550A serial card + parallel)
- 9855 PCI 9855 Multi-I/O Controller
- 1000 0014 1P4S
-9902 Stargen Inc.
- 0001 SG2010 PCI over Starfabric Bridge
- 0002 SG2010 PCI to Starfabric Gateway
- 0003 SG1010 Starfabric Switch and PCI Bridge
-a0a0 AOPEN Inc.
-a0f1 UNISYS Corporation
-a200 NEC Corporation
-a259 Hewlett Packard
-a25b Hewlett Packard GmbH PL24-MKT
-a304 Sony
-a727 3Com Corporation
- 0013 3CRPAG175 Wireless PC Card
-aa42 Scitex Digital Video
-ac1e Digital Receiver Technology Inc
-ac3d Actuality Systems
-aecb Adrienne Electronics Corporation
-b1b3 Shiva Europe Limited
-# Pinnacle should be 11bd, but they got it wrong several times --mj
-bd11 Pinnacle Systems, Inc. (Wrong ID)
-c001 TSI Telsys
-c0a9 Micron/Crucial Technology
-c0de Motorola
-c0fe Motion Engineering, Inc.
-ca50 Varian Australia Pty Ltd
-cafe Chrysalis-ITS
-cccc Catapult Communications
-cddd Tyzx, Inc.
- 0101 DeepSea 1 High Speed Stereo Vision Frame Grabber
- 0200 DeepSea 2 High Speed Stereo Vision Frame Grabber
-d4d4 Dy4 Systems Inc
- 0601 PCI Mezzanine Card
-d531 I+ME ACTIA GmbH
-d84d Exsys
-dead Indigita Corporation
-deaf Middle Digital Inc.
- 9050 PC Weasel Virtual VGA
- 9051 PC Weasel Serial Port
- 9052 PC Weasel Watchdog Timer
-e000 Winbond
- e000 W89C940
-# see also : http://www.schoenfeld.de/inside/Inside_CWMK3.txt maybe a misuse of TJN id or it use the TJN 3XX chip for other applic
-e159 Tiger Jet Network Inc.
- 0001 Tiger3XX Modem/ISDN interface
- 0059 0001 128k ISDN-S/T Adapter
- 0059 0003 128k ISDN-U Adapter
- 0002 Tiger100APC ISDN chipset
-e4bf EKF Elektronik GmbH
-# Innovative and scalable network IC vendor
-e55e Essence Technology, Inc.
-ea01 Eagle Technology
-# The main chip of all these devices is by Xilinx -> It could also be a Xilinx ID.
-ea60 RME
- 9896 Digi32
- 9897 Digi32 Pro
- 9898 Digi32/8
-eabb Aashima Technology B.V.
-eace Endace Measurement Systems, Ltd
- 3100 DAG 3.10 OC-3/OC-12
- 3200 DAG 3.2x OC-3/OC-12
- 320e DAG 3.2E Fast Ethernet
- 340e DAG 3.4E Fast Ethernet
- 341e DAG 3.41E Fast Ethernet
- 3500 DAG 3.5 OC-3/OC-12
- 351c DAG 3.5ECM Fast Ethernet
- 4100 DAG 4.10 OC-48
- 4110 DAG 4.11 OC-48
- 4220 DAG 4.2 OC-48
- 422e DAG 4.2E Dual Gigabit Ethernet
-ec80 Belkin Corporation
- ec00 F5D6000
-ecc0 Echo Digital Audio Corporation
-edd8 ARK Logic Inc
- a091 1000PV [Stingray]
- a099 2000PV [Stingray]
- a0a1 2000MT
- a0a9 2000MI
-f1d0 AJA Video
-# All boards I have seen have this ID not efac, though all docs say efac...
- cafe KONA SD SMPTE 259M I/O
- efac KONA SD SMPTE 259M I/O
- facd KONA HD SMPTE 292M I/O
-fa57 Interagon AS
- 0001 PMC [Pattern Matching Chip]
-febd Ultraview Corp.
-feda Broadcom Inc (nee Epigram)
- a0fa BCM4210 iLine10 HomePNA 2.0
- a10e BCM4230 iLine10 HomePNA 2.0
-# IT & Telecom company, develops PCI Trunk cards <www.fedetec.es>
-fede Fedetec Inc.
- 0003 TABIC PCI v3
-fffe VMWare Inc
- 0405 Virtual SVGA 4.0
- 0710 Virtual SVGA
-ffff Illegal Vendor ID
-
-
-# List of known device classes, subclasses and programming interfaces
-
-# Syntax:
-# C class class_name
-# subclass subclass_name <-- single tab
-# prog-if prog-if_name <-- two tabs
-
-C 00 Unclassified device
- 00 Non-VGA unclassified device
- 01 VGA compatible unclassified device
-C 01 Mass storage controller
- 00 SCSI storage controller
- 01 IDE interface
- 02 Floppy disk controller
- 03 IPI bus controller
- 04 RAID bus controller
- 80 Unknown mass storage controller
-C 02 Network controller
- 00 Ethernet controller
- 01 Token ring network controller
- 02 FDDI network controller
- 03 ATM network controller
- 04 ISDN controller
- 80 Network controller
-C 03 Display controller
- 00 VGA compatible controller
- 00 VGA
- 01 8514
- 01 XGA compatible controller
- 02 3D controller
- 80 Display controller
-C 04 Multimedia controller
- 00 Multimedia video controller
- 01 Multimedia audio controller
- 02 Computer telephony device
- 80 Multimedia controller
-C 05 Memory controller
- 00 RAM memory
- 01 FLASH memory
- 80 Memory controller
-C 06 Bridge
- 00 Host bridge
- 01 ISA bridge
- 02 EISA bridge
- 03 MicroChannel bridge
- 04 PCI bridge
- 00 Normal decode
- 01 Subtractive decode
- 05 PCMCIA bridge
- 06 NuBus bridge
- 07 CardBus bridge
- 08 RACEway bridge
- 00 Transparent mode
- 01 Endpoint mode
- 09 Semi-transparent PCI-to-PCI bridge
- 40 Primary bus towards host CPU
- 80 Secondary bus towards host CPU
- 0a InfiniBand to PCI host bridge
- 80 Bridge
-C 07 Communication controller
- 00 Serial controller
- 00 8250
- 01 16450
- 02 16550
- 03 16650
- 04 16750
- 05 16850
- 06 16950
- 01 Parallel controller
- 00 SPP
- 01 BiDir
- 02 ECP
- 03 IEEE1284
- fe IEEE1284 Target
- 02 Multiport serial controller
- 03 Modem
- 00 Generic
- 01 Hayes/16450
- 02 Hayes/16550
- 03 Hayes/16650
- 04 Hayes/16750
- 80 Communication controller
-C 08 Generic system peripheral
- 00 PIC
- 00 8259
- 01 ISA PIC
- 02 EISA PIC
- 10 IO-APIC
- 20 IO(X)-APIC
- 01 DMA controller
- 00 8237
- 01 ISA DMA
- 02 EISA DMA
- 02 Timer
- 00 8254
- 01 ISA Timer
- 02 EISA Timers
- 03 RTC
- 00 Generic
- 01 ISA RTC
- 04 PCI Hot-plug controller
- 80 System peripheral
-C 09 Input device controller
- 00 Keyboard controller
- 01 Digitizer Pen
- 02 Mouse controller
- 03 Scanner controller
- 04 Gameport controller
- 00 Generic
- 10 Extended
- 80 Input device controller
-C 0a Docking station
- 00 Generic Docking Station
- 80 Docking Station
-C 0b Processor
- 00 386
- 01 486
- 02 Pentium
- 10 Alpha
- 20 Power PC
- 30 MIPS
- 40 Co-processor
-C 0c Serial bus controller
- 00 FireWire (IEEE 1394)
- 00 Generic
- 10 OHCI
- 01 ACCESS Bus
- 02 SSA
- 03 USB Controller
- 00 UHCI
- 10 OHCI
- 20 EHCI
- 80 Unspecified
- fe USB Device
- 04 Fibre Channel
- 05 SMBus
- 06 InfiniBand
-C 0d Wireless controller
- 00 IRDA controller
- 01 Consumer IR controller
- 10 RF controller
- 80 Wireless controller
-C 0e Intelligent controller
- 00 I2O
-C 0f Satellite communications controller
- 00 Satellite TV controller
- 01 Satellite audio communication controller
- 03 Satellite voice communication controller
- 04 Satellite data communication controller
-C 10 Encryption controller
- 00 Network and computing encryption device
- 10 Entertainment encryption device
- 80 Encryption controller
-C 11 Signal processing controller
- 00 DPIO module
- 01 Performance counters
- 10 Communication synchronizer
- 80 Signal processing controller
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 393e0cee91a9..467a4ceccf10 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -11,6 +11,8 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/pcieport_if.h>
#include "portdrv.h"
@@ -61,7 +63,7 @@ static int pcie_port_remove_service(struct device *dev)
static void pcie_port_shutdown_service(struct device *dev) {}
-static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32 level)
+static int pcie_port_suspend_service(struct device *dev, pm_message_t state)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
@@ -76,7 +78,7 @@ static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32
return 0;
}
-static int pcie_port_resume_service(struct device *dev, u32 level)
+static int pcie_port_resume_service(struct device *dev)
{
struct pcie_device *pciedev;
struct pcie_port_service_driver *driver;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 30bac7ed7c16..02260141dc81 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/pcieport_if.h>
#include "portdrv.h"
@@ -90,15 +91,19 @@ static void pcie_portdrv_save_config(struct pci_dev *dev)
pci_save_msi_state(dev);
}
-static void pcie_portdrv_restore_config(struct pci_dev *dev)
+static int pcie_portdrv_restore_config(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
+ int retval;
pci_restore_state(dev);
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
pci_restore_msi_state(dev);
- pci_enable_device(dev);
+ retval = pci_enable_device(dev);
+ if (retval)
+ return retval;
pci_set_master(dev);
+ return 0;
}
/*
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 93e8a878ea95..fce2cb2112d8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -72,11 +72,13 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/*
* PCI Bus Class Devices
*/
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf)
+static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+ char *buf)
{
- cpumask_t cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
int ret;
+ cpumask_t cpumask;
+ cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
if (ret < PAGE_SIZE)
buf[ret++] = '\n';
@@ -163,7 +165,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
if (l == 0xffffffff)
l = 0;
if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
- sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
+ sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
if (!sz)
continue;
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
@@ -213,7 +215,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
if (l == 0xffffffff)
l = 0;
if (sz && sz != 0xffffffff) {
- sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK);
+ sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
if (sz) {
res->flags = (l & IORESOURCE_ROM_ENABLE) |
IORESOURCE_MEM | IORESOURCE_PREFETCH |
@@ -400,6 +402,12 @@ static void pci_enable_crs(struct pci_dev *dev)
static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
{
struct pci_bus *parent = child->parent;
+
+ /* Attempts to fix that up are really dangerous unless
+ we're going to re-assign all bus numbers. */
+ if (!pcibios_assign_all_busses())
+ return;
+
while (parent->parent && parent->subordinate < max) {
parent->subordinate = max;
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
@@ -476,8 +484,18 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
* We need to assign a number to this bus which we always
* do in the second pass.
*/
- if (!pass)
+ if (!pass) {
+ if (pcibios_assign_all_busses())
+ /* Temporarily disable forwarding of the
+ configuration cycles on all bridges in
+ this bus segment to avoid possible
+ conflicts in the second pass between two
+ bridges programmed with overlapping
+ bus ranges. */
+ pci_write_config_dword(dev, PCI_PRIMARY_BUS,
+ buses & ~0xffffff);
return max;
+ }
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
@@ -584,7 +602,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */
- dev->current_state = 4;
+ dev->current_state = PCI_UNKNOWN;
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
@@ -651,6 +669,7 @@ static void pci_release_dev(struct device *dev)
/**
* pci_cfg_space_size - get the configuration space size of the PCI device.
+ * @dev: PCI device
*
* Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
* have 4096 bytes. Even if the device is capable, that doesn't mean we can
@@ -753,29 +772,19 @@ pci_scan_device(struct pci_bus *bus, int devfn)
kfree(dev);
return NULL;
}
- device_initialize(&dev->dev);
- dev->dev.release = pci_release_dev;
- pci_dev_get(dev);
-
- pci_name_device(dev);
-
- dev->dev.dma_mask = &dev->dma_mask;
- dev->dev.coherent_dma_mask = 0xffffffffull;
return dev;
}
-struct pci_dev * __devinit
-pci_scan_single_device(struct pci_bus *bus, int devfn)
+void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
- struct pci_dev *dev;
+ device_initialize(&dev->dev);
+ dev->dev.release = pci_release_dev;
+ pci_dev_get(dev);
- dev = pci_scan_device(bus, devfn);
- pci_scan_msi_device(dev);
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.coherent_dma_mask = 0xffffffffull;
- if (!dev)
- return NULL;
-
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);
@@ -787,6 +796,19 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
spin_lock(&pci_bus_lock);
list_add_tail(&dev->bus_list, &bus->devices);
spin_unlock(&pci_bus_lock);
+}
+
+struct pci_dev * __devinit
+pci_scan_single_device(struct pci_bus *bus, int devfn)
+{
+ struct pci_dev *dev;
+
+ dev = pci_scan_device(bus, devfn);
+ if (!dev)
+ return NULL;
+
+ pci_device_add(dev, bus);
+ pci_scan_msi_device(dev);
return dev;
}
@@ -883,7 +905,8 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
return max;
}
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus * __devinit pci_create_bus(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata)
{
int error;
struct pci_bus *b;
@@ -940,8 +963,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
- b->subordinate = pci_scan_child_bus(b);
-
return b;
sys_create_link_err:
@@ -959,6 +980,18 @@ err_out:
kfree(b);
return NULL;
}
+EXPORT_SYMBOL_GPL(pci_create_bus);
+
+struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+ int bus, struct pci_ops *ops, void *sysdata)
+{
+ struct pci_bus *b;
+
+ b = pci_create_bus(parent, bus, ops, sysdata);
+ if (b)
+ b->subordinate = pci_scan_child_bus(b);
+ return b;
+}
EXPORT_SYMBOL(pci_scan_bus_parented);
#ifdef CONFIG_HOTPLUG
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 7988fc8df3fd..9eb465727fce 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 1) && cnt) {
unsigned char val;
- pci_read_config_byte(dev, pos, &val);
+ pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
@@ -89,7 +89,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 3) && cnt > 2) {
unsigned short val;
- pci_read_config_word(dev, pos, &val);
+ pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
@@ -98,7 +98,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
while (cnt >= 4) {
unsigned int val;
- pci_read_config_dword(dev, pos, &val);
+ pci_user_read_config_dword(dev, pos, &val);
__put_user(cpu_to_le32(val), (unsigned int __user *) buf);
buf += 4;
pos += 4;
@@ -107,7 +107,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt >= 2) {
unsigned short val;
- pci_read_config_word(dev, pos, &val);
+ pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
@@ -116,7 +116,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt) {
unsigned char val;
- pci_read_config_byte(dev, pos, &val);
+ pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
@@ -151,7 +151,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 1) && cnt) {
unsigned char val;
__get_user(val, buf);
- pci_write_config_byte(dev, pos, val);
+ pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
@@ -160,7 +160,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 3) && cnt > 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
- pci_write_config_word(dev, pos, le16_to_cpu(val));
+ pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
@@ -169,7 +169,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
while (cnt >= 4) {
unsigned int val;
__get_user(val, (unsigned int __user *) buf);
- pci_write_config_dword(dev, pos, le32_to_cpu(val));
+ pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
buf += 4;
pos += 4;
cnt -= 4;
@@ -178,7 +178,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt >= 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
- pci_write_config_word(dev, pos, le16_to_cpu(val));
+ pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
@@ -187,7 +187,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt) {
unsigned char val;
__get_user(val, buf);
- pci_write_config_byte(dev, pos, val);
+ pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
@@ -474,7 +474,7 @@ static int show_dev_config(struct seq_file *m, void *v)
struct pci_dev *first_dev;
struct pci_driver *drv;
u32 class_rev;
- unsigned char latency, min_gnt, max_lat, *class;
+ unsigned char latency, min_gnt, max_lat;
int reg;
first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
@@ -484,22 +484,14 @@ static int show_dev_config(struct seq_file *m, void *v)
drv = pci_dev_driver(dev);
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
- pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
- pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
+ pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+ pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
+ pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- class = pci_class_name(class_rev >> 16);
- if (class)
- seq_printf(m, " %s", class);
- else
- seq_printf(m, " Class %04x", class_rev >> 16);
-#ifdef CONFIG_PCI_NAMES
- seq_printf(m, ": %s", dev->pretty_name);
-#else
+ seq_printf(m, " Class %04x", class_rev >> 16);
seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device);
-#endif
seq_printf(m, " (rev %d).\n", class_rev & 0xff);
if (dev->irq)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8d0968bd527e..5627ce1d2b32 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -7,6 +7,9 @@
*
* Copyright (c) 1999 Martin Mares <mj@ucw.cz>
*
+ * Init/reset quirks for USB host controllers should be in the
+ * USB quirks file, where their drivers can access reuse it.
+ *
* The bridge optimization stuff has been removed. If you really
* have a silly BIOS which is unable to set your host bridge right,
* use the PowerTweak utility (see http://powertweak.sourceforge.net).
@@ -241,17 +244,26 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M );
-static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
+static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
+ unsigned size, int nr, const char *name)
{
region &= ~(size-1);
if (region) {
+ struct pci_bus_region bus_region;
struct resource *res = dev->resource + nr;
res->name = pci_name(dev);
res->start = region;
res->end = region + size - 1;
res->flags = IORESOURCE_IO;
+
+ /* Convert from PCI bus to resource space. */
+ bus_region.start = res->start;
+ bus_region.end = res->end;
+ pcibios_bus_to_resource(dev, res, &bus_region);
+
pci_claim_resource(dev, nr);
+ printk("PCI quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
}
}
@@ -284,25 +296,98 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
u16 region;
pci_read_config_word(dev, 0xE0, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
pci_read_config_word(dev, 0xE2, &region);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi );
+static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
+{
+ u32 devres;
+ u32 mask, size, base;
+
+ pci_read_config_dword(dev, port, &devres);
+ if ((devres & enable) != enable)
+ return;
+ mask = (devres >> 16) & 15;
+ base = devres & 0xffff;
+ size = 16;
+ for (;;) {
+ unsigned bit = size >> 1;
+ if ((bit & mask) == bit)
+ break;
+ size = bit;
+ }
+ /*
+ * For now we only print it out. Eventually we'll want to
+ * reserve it (at least if it's in the 0x1000+ range), but
+ * let's get enough confirmation reports first.
+ */
+ base &= -size;
+ printk("%s PIO at %04x-%04x\n", name, base, base + size - 1);
+}
+
+static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
+{
+ u32 devres;
+ u32 mask, size, base;
+
+ pci_read_config_dword(dev, port, &devres);
+ if ((devres & enable) != enable)
+ return;
+ base = devres & 0xffff0000;
+ mask = (devres & 0x3f) << 16;
+ size = 128 << 16;
+ for (;;) {
+ unsigned bit = size >> 1;
+ if ((bit & mask) == bit)
+ break;
+ size = bit;
+ }
+ /*
+ * For now we only print it out. Eventually we'll want to
+ * reserve it, but let's get enough confirmation reports first.
+ */
+ base &= -size;
+ printk("%s MMIO at %04x-%04x\n", name, base, base + size - 1);
+}
+
/*
* PIIX4 ACPI: Two IO regions pointed to by longwords at
* 0x40 (64 bytes of ACPI registers)
- * 0x90 (32 bytes of SMB registers)
+ * 0x90 (16 bytes of SMB registers)
+ * and a few strange programmable PIIX4 device resources.
*/
static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
{
- u32 region;
+ u32 region, res_a;
pci_read_config_dword(dev, 0x40, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
pci_read_config_dword(dev, 0x90, &region);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+
+ /* Device resource A has enables for some of the other ones */
+ pci_read_config_dword(dev, 0x5c, &res_a);
+
+ piix4_io_quirk(dev, "PIIX4 devres B", 0x60, 3 << 21);
+ piix4_io_quirk(dev, "PIIX4 devres C", 0x64, 3 << 21);
+
+ /* Device resource D is just bitfields for static resources */
+
+ /* Device 12 enabled? */
+ if (res_a & (1 << 29)) {
+ piix4_io_quirk(dev, "PIIX4 devres E", 0x68, 1 << 20);
+ piix4_mem_quirk(dev, "PIIX4 devres F", 0x6c, 1 << 7);
+ }
+ /* Device 13 enabled? */
+ if (res_a & (1 << 30)) {
+ piix4_io_quirk(dev, "PIIX4 devres G", 0x70, 1 << 20);
+ piix4_mem_quirk(dev, "PIIX4 devres H", 0x74, 1 << 7);
+ }
+ piix4_io_quirk(dev, "PIIX4 devres I", 0x78, 1 << 20);
+ piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi );
@@ -316,10 +401,10 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
u32 region;
pci_read_config_dword(dev, 0x40, &region);
- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
pci_read_config_dword(dev, 0x58, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi );
@@ -332,6 +417,18 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi );
+static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
+{
+ u32 region;
+
+ pci_read_config_dword(dev, 0x40, &region);
+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+
+ pci_read_config_dword(dev, 0x48, &region);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
+
/*
* VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers)
@@ -345,7 +442,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
if (rev & 0x10) {
pci_read_config_dword(dev, 0x48, &region);
region &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES);
+ quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi );
@@ -365,14 +462,33 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0x70, &hm);
hm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1);
+ quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon");
pci_read_config_dword(dev, 0x90, &smb);
smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
+/*
+ * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
+ * 0x88 (128 bytes of power management registers)
+ * 0xd0 (16 bytes of SMB registers)
+ */
+static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
+{
+ u16 pm, smb;
+
+ pci_read_config_word(dev, 0x88, &pm);
+ pm &= PCI_BASE_ADDRESS_IO_MASK;
+ quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
+
+ pci_read_config_word(dev, 0xd0, &smb);
+ smb &= PCI_BASE_ADDRESS_IO_MASK;
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
+
#ifdef CONFIG_X86_IO_APIC
@@ -403,6 +519,25 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
/*
+ * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
+ * This leads to doubled level interrupt rates.
+ * Set this bit to get rid of cycle wastage.
+ * Otherwise uncritical.
+ */
+static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
+{
+ u8 misc_control2;
+#define BYPASS_APIC_DEASSERT 8
+
+ pci_read_config_byte(dev, 0x5B, &misc_control2);
+ if (!(misc_control2 & BYPASS_APIC_DEASSERT)) {
+ printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n");
+ pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT);
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
+
+/*
* The AMD io apic can hang the box when an apic irq is masked.
* We check all revs >= B0 (yet not in the pre production!) as the bug
* is currently marked NoFix
@@ -513,28 +648,6 @@ static void quirk_via_irq(struct pci_dev *dev)
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
/*
- * PIIX3 USB: We have to disable USB interrupts that are
- * hardwired to PIRQD# and may be shared with an
- * external device.
- *
- * Legacy Support Register (LEGSUP):
- * bit13: USB PIRQ Enable (USBPIRQDEN),
- * bit4: Trap/SMI On IRQ Enable (USBSMIEN).
- *
- * We mask out all r/wc bits, too.
- */
-static void __devinit quirk_piix3_usb(struct pci_dev *dev)
-{
- u16 legsup;
-
- pci_read_config_word(dev, 0xc0, &legsup);
- legsup &= 0x50ef;
- pci_write_config_word(dev, 0xc0, legsup);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb );
-
-/*
* VIA VT82C598 has its device ID settable and many BIOSes
* set it to the ID of VT82C597 for backward compatibility.
* We need to switch it off to be able to recognize the real
@@ -802,6 +915,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x186a: /* M6Ne notebook */
asus_hides_smbus = 1;
}
+ if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
+ switch (dev->subsystem_device) {
+ case 0x1882: /* M6V notebook */
+ asus_hides_smbus = 1;
+ }
+ }
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
switch(dev->subsystem_device) {
@@ -812,6 +931,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
switch (dev->subsystem_device) {
case 0x12bc: /* HP D330L */
+ case 0x12bd: /* HP D530 */
asus_hides_smbus = 1;
}
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
@@ -831,6 +951,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0xC00C: /* Samsung P35 notebook */
asus_hides_smbus = 1;
}
+ } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {
+ if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
+ switch(dev->subsystem_device) {
+ case 0x0058: /* Compaq Evo N620c */
+ asus_hides_smbus = 1;
+ }
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge );
@@ -840,6 +966,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
{
@@ -864,6 +991,23 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, as
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
+{
+ u32 val, rcba;
+ void __iomem *base;
+
+ if (likely(!asus_hides_smbus))
+ return;
+ pci_read_config_dword(dev, 0xF0, &rcba);
+ base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */
+ if (base == NULL) return;
+ val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
+ writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
+ iounmap(base);
+ printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
@@ -876,234 +1020,6 @@ static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
pci_read_config_byte(dev, 0x77, &val);
}
-
-#define UHCI_USBLEGSUP 0xc0 /* legacy support */
-#define UHCI_USBCMD 0 /* command register */
-#define UHCI_USBSTS 2 /* status register */
-#define UHCI_USBINTR 4 /* interrupt register */
-#define UHCI_USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
-#define UHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
-#define UHCI_USBCMD_GRESET (1 << 2) /* Global reset */
-#define UHCI_USBCMD_CONFIGURE (1 << 6) /* config semaphore */
-#define UHCI_USBSTS_HALTED (1 << 5) /* HCHalted bit */
-
-#define OHCI_CONTROL 0x04
-#define OHCI_CMDSTATUS 0x08
-#define OHCI_INTRSTATUS 0x0c
-#define OHCI_INTRENABLE 0x10
-#define OHCI_INTRDISABLE 0x14
-#define OHCI_OCR (1 << 3) /* ownership change request */
-#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
-#define OHCI_INTR_OC (1 << 30) /* ownership change */
-
-#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */
-#define EHCI_USBCMD 0 /* command register */
-#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
-#define EHCI_USBSTS 4 /* status register */
-#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */
-#define EHCI_USBINTR 8 /* interrupt register */
-#define EHCI_USBLEGSUP 0 /* legacy support register */
-#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
-#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */
-#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
-#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
-
-int usb_early_handoff __devinitdata = 0;
-static int __init usb_handoff_early(char *str)
-{
- usb_early_handoff = 1;
- return 0;
-}
-__setup("usb-handoff", usb_handoff_early);
-
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
-{
- unsigned long base = 0;
- int wait_time, delta;
- u16 val, sts;
- int i;
-
- for (i = 0; i < PCI_ROM_RESOURCE; i++)
- if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
- base = pci_resource_start(pdev, i);
- break;
- }
-
- if (!base)
- return;
-
- /*
- * stop controller
- */
- sts = inw(base + UHCI_USBSTS);
- val = inw(base + UHCI_USBCMD);
- val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
- outw(val, base + UHCI_USBCMD);
-
- /*
- * wait while it stops if it was running
- */
- if ((sts & UHCI_USBSTS_HALTED) == 0)
- {
- wait_time = 1000;
- delta = 100;
-
- do {
- outw(0x1f, base + UHCI_USBSTS);
- udelay(delta);
- wait_time -= delta;
- val = inw(base + UHCI_USBSTS);
- if (val & UHCI_USBSTS_HALTED)
- break;
- } while (wait_time > 0);
- }
-
- /*
- * disable interrupts & legacy support
- */
- outw(0, base + UHCI_USBINTR);
- outw(0x1f, base + UHCI_USBSTS);
- pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
- if (val & 0xbf)
- pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
-
-}
-
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
-{
- void __iomem *base;
- int wait_time;
-
- base = ioremap_nocache(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (base == NULL) return;
-
- if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
- wait_time = 500; /* 0.5 seconds */
- writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
- writel(OHCI_OCR, base + OHCI_CMDSTATUS);
- while (wait_time > 0 &&
- readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
- wait_time -= 10;
- msleep(10);
- }
- }
-
- /*
- * disable interrupts
- */
- writel(~(u32)0, base + OHCI_INTRDISABLE);
- writel(~(u32)0, base + OHCI_INTRSTATUS);
-
- iounmap(base);
-}
-
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
-{
- int wait_time, delta;
- void __iomem *base, *op_reg_base;
- u32 hcc_params, val, temp;
- u8 cap_length;
-
- base = ioremap_nocache(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (base == NULL) return;
-
- cap_length = readb(base);
- op_reg_base = base + cap_length;
- hcc_params = readl(base + EHCI_HCC_PARAMS);
- hcc_params = (hcc_params >> 8) & 0xff;
- if (hcc_params) {
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
- /*
- * Ok, BIOS is in smm mode, try to hand off...
- */
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- &temp);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- temp | EHCI_USBLEGCTLSTS_SOOE);
- val |= EHCI_USBLEGSUP_OS;
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- val);
-
- wait_time = 500;
- do {
- msleep(10);
- wait_time -= 10;
- pci_read_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- &val);
- } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
- if (!wait_time) {
- /*
- * well, possibly buggy BIOS...
- */
- printk(KERN_WARNING "EHCI early BIOS handoff "
- "failed (BIOS bug ?)\n");
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGSUP,
- EHCI_USBLEGSUP_OS);
- pci_write_config_dword(pdev,
- hcc_params + EHCI_USBLEGCTLSTS,
- 0);
- }
- }
- }
-
- /*
- * halt EHCI & disable its interrupts in any case
- */
- val = readl(op_reg_base + EHCI_USBSTS);
- if ((val & EHCI_USBSTS_HALTED) == 0) {
- val = readl(op_reg_base + EHCI_USBCMD);
- val &= ~EHCI_USBCMD_RUN;
- writel(val, op_reg_base + EHCI_USBCMD);
-
- wait_time = 2000;
- delta = 100;
- do {
- writel(0x3f, op_reg_base + EHCI_USBSTS);
- udelay(delta);
- wait_time -= delta;
- val = readl(op_reg_base + EHCI_USBSTS);
- if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
- break;
- }
- } while (wait_time > 0);
- }
- writel(0, op_reg_base + EHCI_USBINTR);
- writel(0x3f, op_reg_base + EHCI_USBSTS);
-
- iounmap(base);
-
- return;
-}
-
-
-
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
-{
- if (!usb_early_handoff)
- return;
-
- if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
- quirk_usb_handoff_uhci(pdev);
- } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
- quirk_usb_handoff_ohci(pdev);
- } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
- quirk_usb_disable_ehci(pdev);
- }
-
- return;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
-
/*
* ... This is further complicated by the fact that some SiS96x south
* bridges pretend to be 85C503/5513 instead. In that case see if we
@@ -1182,7 +1098,7 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic );
#endif
-#ifdef CONFIG_SCSI_SATA
+#ifdef CONFIG_SCSI_SATA_INTEL_COMBINED
static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
{
u8 prog, comb, tmp;
@@ -1259,7 +1175,7 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
request_region(0x170, 8, "libata"); /* port 1 */
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_combined );
-#endif /* CONFIG_SCSI_SATA */
+#endif /* CONFIG_SCSI_SATA_INTEL_COMBINED */
int pcie_mch_quirk;
@@ -1272,6 +1188,27 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quir
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch );
+
+/*
+ * It's possible for the MSI to get corrupted if shpc and acpi
+ * are used together on certain PXH-based systems.
+ */
+static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
+{
+ disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
+ PCI_CAP_ID_MSI);
+ dev->no_msi = 1;
+
+ printk(KERN_WARNING "PCI: PXH quirk detected, "
+ "disabling MSI for SHPC device\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_0, quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_1, quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pcie_pxh);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh);
+
+
static void __devinit quirk_netmos(struct pci_dev *dev)
{
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 713c78f3a65d..598a115cd00e 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/slab.h>
#include "pci.h"
@@ -21,13 +22,21 @@
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
-static void pci_enable_rom(struct pci_dev *pdev)
+static int pci_enable_rom(struct pci_dev *pdev)
{
+ struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
+ struct pci_bus_region region;
u32 rom_addr;
+ if (!res->flags)
+ return -1;
+
+ pcibios_resource_to_bus(pdev, &region, res);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
- rom_addr |= PCI_ROM_ADDRESS_ENABLE;
+ rom_addr &= ~PCI_ROM_ADDRESS_MASK;
+ rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
+ return 0;
}
/**
@@ -71,19 +80,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
} else {
if (res->flags & IORESOURCE_ROM_COPY) {
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE);
+ return (void __iomem *)pci_resource_start(pdev,
+ PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
- if (res->parent == NULL)
- pci_assign_resource(pdev, PCI_ROM_RESOURCE);
-
+ if (res->parent == NULL &&
+ pci_assign_resource(pdev,PCI_ROM_RESOURCE))
+ return NULL;
start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (*size == 0)
return NULL;
/* Enable ROM space decodes */
- pci_enable_rom(pdev);
+ if (pci_enable_rom(pdev))
+ return NULL;
}
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index a2eebc6eaacc..28ce3a7ee434 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -40,7 +40,7 @@
* FIXME: IO should be max 256 bytes. However, since we may
* have a P2P bridge below a cardbus bridge, we need 4K.
*/
-#define CARDBUS_IO_SIZE (4096)
+#define CARDBUS_IO_SIZE (256)
#define CARDBUS_MEM_SIZE (32*1024*1024)
static void __devinit
@@ -77,8 +77,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
}
}
-static void __devinit
-pci_setup_cardbus(struct pci_bus *bus)
+void pci_setup_cardbus(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
struct pci_bus_region region;
@@ -130,6 +129,7 @@ pci_setup_cardbus(struct pci_bus *bus)
region.end);
}
}
+EXPORT_SYMBOL(pci_setup_cardbus);
/* Initialize bridges with base/limit values we have collected.
PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 1ca21d2ba11c..50d6685dcbcc 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -26,13 +26,18 @@
#include "pci.h"
-static void
+void
pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
{
struct pci_bus_region region;
u32 new, check, mask;
int reg;
+ /* Ignore resources for unimplemented BARs and unused resource slots
+ for 64 bit BARs. */
+ if (!res->flags)
+ return;
+
pcibios_resource_to_bus(dev, &region, res);
pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for "
@@ -48,7 +53,9 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
if (resno < 6) {
reg = PCI_BASE_ADDRESS_0 + 4 * resno;
} else if (resno == PCI_ROM_RESOURCE) {
- new |= res->flags & IORESOURCE_ROM_ENABLE;
+ if (!(res->flags & IORESOURCE_ROM_ENABLE))
+ return;
+ new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
/* Hmm, non-standard resource. */
@@ -67,7 +74,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
(PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
- new = 0; /* currently everyone zeros the high address */
+ new = region.start >> 16 >> 16;
pci_write_config_dword(dev, reg + 4, new);
pci_read_config_dword(dev, reg + 4, &check);
if (check != new) {
@@ -90,10 +97,7 @@ pci_claim_resource(struct pci_dev *dev, int resource)
char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
int err;
- if (res->flags & IORESOURCE_IO)
- root = &ioport_resource;
- if (res->flags & IORESOURCE_MEM)
- root = &iomem_resource;
+ root = pcibios_select_root(dev, res);
err = -EINVAL;
if (root != NULL)
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index c071790cc983..87fafc08cb9d 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -13,7 +13,7 @@
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
-
+#include "pci.h"
asmlinkage long
sys_pciconfig_read(unsigned long bus, unsigned long dfn,
@@ -38,13 +38,13 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
lock_kernel();
switch (len) {
case 1:
- cfg_ret = pci_read_config_byte(dev, off, &byte);
+ cfg_ret = pci_user_read_config_byte(dev, off, &byte);
break;
case 2:
- cfg_ret = pci_read_config_word(dev, off, &word);
+ cfg_ret = pci_user_read_config_word(dev, off, &word);
break;
case 4:
- cfg_ret = pci_read_config_dword(dev, off, &dword);
+ cfg_ret = pci_user_read_config_dword(dev, off, &dword);
break;
default:
err = -EINVAL;
@@ -112,7 +112,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(byte, (u8 __user *)buf);
if (err)
break;
- err = pci_write_config_byte(dev, off, byte);
+ err = pci_user_write_config_byte(dev, off, byte);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
@@ -121,7 +121,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(word, (u16 __user *)buf);
if (err)
break;
- err = pci_write_config_word(dev, off, word);
+ err = pci_user_write_config_word(dev, off, word);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
@@ -130,7 +130,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(dword, (u32 __user *)buf);
if (err)
break;
- err = pci_write_config_dword(dev, off, dword);
+ err = pci_user_write_config_dword(dev, off, dword);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6485f75d2fb3..ccf20039e909 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -146,7 +146,7 @@ config I82365
config TCIC
tristate "Databook TCIC host bridge support"
- depends on PCMCIA
+ depends on PCMCIA && ISA
select PCCARD_NONSTATIC
help
Say Y here to include support for the Databook TCIC family of PCMCIA
@@ -154,6 +154,16 @@ config TCIC
"Bridge" is the name used for the hardware inside your computer that
PCMCIA cards are plugged into. If unsure, say N.
+config PCMCIA_M8XX
+ tristate "MPC8xx PCMCIA support"
+ depends on PCMCIA && PPC
+ select PCCARD_NONSTATIC
+ help
+ Say Y here to include support for PowerPC 8xx series PCMCIA
+ controller.
+
+ This driver is also available as a module called m8xx_pcmcia.
+
config HD64465_PCMCIA
tristate "HD64465 host bridge support"
depends on HD64465 && PCMCIA
@@ -221,6 +231,13 @@ config PCMCIA_VRC4173
tristate "NEC VRC4173 CARDU support"
depends on CPU_VR41XX && PCI && PCMCIA
+config OMAP_CF
+ tristate "OMAP CompactFlash Controller"
+ depends on PCMCIA && ARCH_OMAP16XX
+ help
+ Say Y here to support the CompactFlash controller on OMAP.
+ Note that this doesn't support "True IDE" mode.
+
config PCCARD_NONSTATIC
tristate
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index ef694c74dfb7..fe37541abbfe 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_PD6729) += pd6729.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
+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
@@ -34,6 +35,7 @@ obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
+obj-$(CONFIG_OMAP_CF) += omap_cf.o
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
@@ -41,9 +43,11 @@ pxa2xx_core-y += soc_common.o pxa2xx_base.o
au1x00_ss-y += au1000_generic.o
au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
au1x00_ss-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o
+au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o
+au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o
@@ -56,6 +60,7 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
sa1100_cs-y += sa1100_generic.o
sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c
index 42cf8bfbcc98..24cfee1a412c 100644
--- a/drivers/pcmcia/au1000_db1x00.c
+++ b/drivers/pcmcia/au1000_db1x00.c
@@ -40,7 +40,15 @@
#include <asm/irq.h>
#include <asm/signal.h>
#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-db1x00/db1x00.h>
+
+#if defined(CONFIG_MIPS_DB1200)
+ #include <db1200.h>
+#elif defined(CONFIG_MIPS_PB1200)
+ #include <pb1200.h>
+#else
+ #include <asm/mach-db1x00/db1x00.h>
+ static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+#endif
#include "au1000_generic.h"
@@ -50,7 +58,6 @@
#define debug(x,args...)
#endif
-static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS];
extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int);
@@ -59,6 +66,8 @@ static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt)
{
#ifdef CONFIG_MIPS_DB1550
skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3;
+#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+ skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT;
#else
skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2;
#endif
@@ -85,11 +94,19 @@ db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state
switch (skt->nr) {
case 0:
vs = bcsr->status & 0x3;
+#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+ inserted = BOARD_CARD_INSERTED(0);
+#else
inserted = !(bcsr->status & (1<<4));
+#endif
break;
case 1:
vs = (bcsr->status & 0xC)>>2;
+#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+ inserted = BOARD_CARD_INSERTED(1);
+#else
inserted = !(bcsr->status & (1<<5));
+#endif
break;
default:/* should never happen */
return;
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 470ef756252e..87302c548c24 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -42,7 +42,7 @@
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -490,7 +490,7 @@ int au1x00_drv_pcmcia_remove(struct device *dev)
flush_scheduled_work();
skt->ops->hw_shutdown(skt);
au1x00_pcmcia_config_skt(skt, &dead_socket);
- iounmap(skt->virt_io);
+ iounmap(skt->virt_io + (u32)mips_io_port_base);
skt->virt_io = NULL;
}
@@ -519,36 +519,15 @@ static int au1x00_drv_pcmcia_probe(struct device *dev)
}
-static int au1x00_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int au1x00_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver au1x00_pcmcia_driver = {
.probe = au1x00_drv_pcmcia_probe,
.remove = au1x00_drv_pcmcia_remove,
.name = "au1x00-pcmcia",
.bus = &platform_bus_type,
- .suspend = au1x00_drv_pcmcia_suspend,
- .resume = au1x00_drv_pcmcia_resume
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
-static struct platform_device au1x00_device = {
- .name = "au1x00-pcmcia",
- .id = 0,
-};
/* au1x00_pcmcia_init()
*
@@ -562,7 +541,6 @@ static int __init au1x00_pcmcia_init(void)
int error = 0;
if ((error = driver_register(&au1x00_pcmcia_driver)))
return error;
- platform_device_register(&au1x00_device);
return error;
}
@@ -573,7 +551,6 @@ static int __init au1x00_pcmcia_init(void)
static void __exit au1x00_pcmcia_exit(void)
{
driver_unregister(&au1x00_pcmcia_driver);
- platform_device_unregister(&au1x00_device);
}
module_init(au1x00_pcmcia_init);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index d5122b1ea94b..b0e7908392a7 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -44,13 +44,13 @@
/* pcmcia socket 1 needs external glue logic so the memory map
* differs from board to board.
*/
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550)
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_PB1200)
#define AU1X_SOCK1_IO 0xF08000000
#define AU1X_SOCK1_PHYS_ATTR 0xF48000000
#define AU1X_SOCK1_PHYS_MEM 0xF88000000
#define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000
#define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8800000
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550)
+#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || defined(CONFIG_MIPS_DB1200)
#define AU1X_SOCK1_IO 0xF04000000
#define AU1X_SOCK1_PHYS_ATTR 0xF44000000
#define AU1X_SOCK1_PHYS_MEM 0xF84000000
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 1d755e20880c..3f6d51d11374 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
cardbus_assign_irqs(bus, s->pci_irq);
+
+ /* socket specific tune function */
+ if (s->tune_bridge)
+ s->tune_bridge(s, bus);
+
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index e39178fc59d0..d5e76423a0ee 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -654,9 +654,10 @@ static int pccardd(void *__skt)
skt->thread = NULL;
complete_and_exit(&skt->thread_done, 0);
}
- complete(&skt->thread_done);
add_wait_queue(&skt->thread_wait, &wait);
+ complete(&skt->thread_done);
+
for (;;) {
unsigned long flags;
unsigned int events;
@@ -682,12 +683,15 @@ static int pccardd(void *__skt)
continue;
}
- schedule();
- try_to_freeze();
-
if (!skt->thread)
break;
+
+ schedule();
+ try_to_freeze();
}
+ /* make sure we are running before we exit */
+ set_current_state(TASK_RUNNING);
+
remove_wait_queue(&skt->thread_wait, &wait);
/* remove from the device core */
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 6bbfbd0e02a5..55867bc7f199 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -17,9 +17,6 @@
#include <linux/config.h>
-#define CLIENT_MAGIC 0x51E6
-typedef struct client_t client_t;
-
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
#define CLIENT_IRQ_REQ 0x0002
@@ -45,7 +42,6 @@ typedef struct region_t {
typedef struct config_t {
u_int state;
u_int Attributes;
- u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 43da2e92d50f..39d096b52926 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -354,6 +354,7 @@ static void pcmcia_release_dev(struct device *dev)
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
ds_dbg(1, "releasing dev %p\n", p_dev);
pcmcia_put_socket(p_dev->socket);
+ kfree(p_dev->devname);
kfree(p_dev);
}
@@ -424,9 +425,13 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
{
cistpl_manfid_t manf_id;
cistpl_funcid_t func_id;
- cistpl_vers_1_t vers1;
+ cistpl_vers_1_t *vers1;
unsigned int i;
+ vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
+ if (!vers1)
+ return -ENOMEM;
+
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
CISTPL_MANFID, &manf_id)) {
p_dev->manf_id = manf_id.manf;
@@ -443,23 +448,30 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
/* rule of thumb: cards with no FUNCID, but with
* common memory device geometry information, are
* probably memory cards (from pcmcia-cs) */
- cistpl_device_geo_t devgeo;
+ cistpl_device_geo_t *devgeo;
+
+ devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
+ if (!devgeo) {
+ kfree(vers1);
+ return -ENOMEM;
+ }
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
- CISTPL_DEVICE_GEO, &devgeo)) {
+ CISTPL_DEVICE_GEO, devgeo)) {
ds_dbg(0, "mem device geometry probably means "
"FUNCID_MEMORY\n");
p_dev->func_id = CISTPL_FUNCID_MEMORY;
p_dev->has_func_id = 1;
}
+ kfree(devgeo);
}
if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
- &vers1)) {
- for (i=0; i < vers1.ns; i++) {
+ vers1)) {
+ for (i=0; i < vers1->ns; i++) {
char *tmp;
unsigned int length;
- tmp = vers1.str + vers1.ofs[i];
+ tmp = vers1->str + vers1->ofs[i];
length = strlen(tmp) + 1;
if ((length < 3) || (length > 255))
@@ -475,6 +487,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
}
}
+ kfree(vers1);
return 0;
}
@@ -492,6 +505,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
{
struct pcmcia_device *p_dev;
unsigned long flags;
+ int bus_id_len;
s = pcmcia_get_socket(s);
if (!s)
@@ -515,7 +529,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.dev;
p_dev->dev.release = pcmcia_release_dev;
- sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+
+ p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+ if (!p_dev->devname)
+ goto err_free;
+ sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
/* compat */
p_dev->state = CLIENT_UNBOUND;
@@ -540,6 +559,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
return p_dev;
err_free:
+ kfree(p_dev->devname);
kfree(p_dev);
s->device_count--;
err_put:
@@ -1137,7 +1157,8 @@ static struct pcmcia_callback pcmcia_bus_callback = {
.requery = pcmcia_bus_rescan,
};
-static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
+static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
int ret;
@@ -1172,7 +1193,8 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
return 0;
}
-static void pcmcia_bus_remove_socket(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 316f8bcc878b..561706ba4499 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -37,7 +37,7 @@
#include <asm/errno.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/hd64465/hd64465.h>
@@ -844,27 +844,11 @@ static void hs_exit_socket(hs_socket_t *sp)
local_irq_restore(flags);
}
-static int hd64465_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int hd64465_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver hd64465_driver = {
.name = "hd64465-pcmcia",
.bus = &platform_bus_type,
- .suspend = hd64465_suspend,
- .resume = hd64465_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device hd64465_device = {
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index a713015e8228..7ce455d01cc9 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -47,7 +47,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -1332,27 +1332,11 @@ static struct pccard_operations pcic_operations = {
/*====================================================================*/
-static int i82365_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int i82365_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver i82365_driver = {
.name = "i82365",
.bus = &platform_bus_type,
- .suspend = i82365_suspend,
- .resume = i82365_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device i82365_device = {
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 65f3ee3d4d3c..2c22b4b3619d 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -23,7 +23,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -731,28 +731,11 @@ static struct pccard_operations pcc_operations = {
/*====================================================================*/
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver pcc_driver = {
.name = "cfc",
.bus = &platform_bus_type,
- .suspend = m32r_pcc_suspend,
- .resume = m32r_pcc_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 7b14d7efd68c..356a6fb416a1 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -23,7 +23,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/bitops.h>
@@ -695,28 +695,11 @@ static struct pccard_operations pcc_operations = {
/*====================================================================*/
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
-
static struct device_driver pcc_driver = {
.name = "pcc",
.bus = &platform_bus_type,
- .suspend = m32r_pcc_suspend,
- .resume = m32r_pcc_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
new file mode 100644
index 000000000000..f8bed87cf2f1
--- /dev/null
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -0,0 +1,1290 @@
+/*
+ * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
+ *
+ * (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
+ * (C) 2001-2002 Montavista Software, Inc.
+ * <mlocke@mvista.com>
+ *
+ * Support for two slots by Cyclades Corporation
+ * <oliver.kurth@cyclades.de>
+ * Further fixes, v2.6 kernel port
+ * <marcelo.tosatti@cyclades.com>
+ *
+ * "The ExCA standard specifies that socket controllers should provide
+ * two IO and five memory windows per socket, which can be independently
+ * configured and positioned in the host address space and mapped to
+ * arbitrary segments of card address space. " - David A Hinds. 1999
+ *
+ * This controller does _not_ meet the ExCA standard.
+ *
+ * m8xx pcmcia controller brief info:
+ * + 8 windows (attrib, mem, i/o)
+ * + up to two slots (SLOT_A and SLOT_B)
+ * + inputpins, outputpins, event and mask registers.
+ * - no offset register. sigh.
+ *
+ * Because of the lacking offset register we must map the whole card.
+ * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
+ * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
+ * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
+ * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
+ * They are maximum 64KByte each...
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <asm/irq.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+module_param(pc_debug, int, 0);
+#define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);
+#else
+#define dprintk(args...)
+#endif
+
+#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
+#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
+
+static const char *version = "Version 0.06, Aug 2005";
+MODULE_LICENSE("Dual MPL/GPL");
+
+#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
+
+/* The RPX series use SLOT_B */
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+#define CONFIG_PCMCIA_SLOT_B
+#define CONFIG_BD_IS_MHZ
+#endif
+
+/* The ADS board use SLOT_A */
+#ifdef CONFIG_ADS
+#define CONFIG_PCMCIA_SLOT_A
+#define CONFIG_BD_IS_MHZ
+#endif
+
+/* The FADS series are a mess */
+#ifdef CONFIG_FADS
+#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
+#define CONFIG_PCMCIA_SLOT_A
+#else
+#define CONFIG_PCMCIA_SLOT_B
+#endif
+#endif
+
+/* Cyclades ACS uses both slots */
+#ifdef CONFIG_PRxK
+#define CONFIG_PCMCIA_SLOT_A
+#define CONFIG_PCMCIA_SLOT_B
+#endif
+
+#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+
+#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
+
+#define PCMCIA_SOCKETS_NO 2
+/* We have only 8 windows, dualsocket support will be limited. */
+#define PCMCIA_MEM_WIN_NO 2
+#define PCMCIA_IO_WIN_NO 2
+#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
+
+#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
+
+#define PCMCIA_SOCKETS_NO 1
+/* full support for one slot */
+#define PCMCIA_MEM_WIN_NO 5
+#define PCMCIA_IO_WIN_NO 2
+
+/* define _slot_ to be able to optimize macros */
+
+#ifdef CONFIG_PCMCIA_SLOT_A
+#define _slot_ 0
+#define PCMCIA_SLOT_MSG "SLOT_A"
+#else
+#define _slot_ 1
+#define PCMCIA_SLOT_MSG "SLOT_B"
+#endif
+
+#else
+#error m8xx_pcmcia: Bad configuration!
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
+#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
+#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
+
+#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */
+
+/* ------------------------------------------------------------------------- */
+
+/* 2.4.x and newer has this always in HZ */
+#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
+
+static int pcmcia_schlvl = PCMCIA_SCHLVL;
+
+static spinlock_t events_lock = SPIN_LOCK_UNLOCKED;
+
+
+#define PCMCIA_SOCKET_KEY_5V 1
+#define PCMCIA_SOCKET_KEY_LV 2
+
+/* look up table for pgcrx registers */
+static u32 *m8xx_pgcrx[2] = {
+ &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
+ &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
+};
+
+/*
+ * This structure is used to address each window in the PCMCIA controller.
+ *
+ * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
+ * after pcmcia_win[n]...
+ */
+
+struct pcmcia_win {
+ u32 br;
+ u32 or;
+};
+
+/*
+ * For some reason the hardware guys decided to make both slots share
+ * some registers.
+ *
+ * Could someone invent object oriented hardware ?
+ *
+ * The macros are used to get the right bit from the registers.
+ * SLOT_A : slot = 0
+ * SLOT_B : slot = 1
+ */
+
+#define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
+
+#define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4))
+#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
+#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
+#define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4))
+#define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4))
+#define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4))
+
+#define M8XX_PCMCIA_POR_VALID 0x00000001
+#define M8XX_PCMCIA_POR_WRPROT 0x00000002
+#define M8XX_PCMCIA_POR_ATTRMEM 0x00000010
+#define M8XX_PCMCIA_POR_IO 0x00000018
+#define M8XX_PCMCIA_POR_16BIT 0x00000040
+
+#define M8XX_PGCRX(slot) m8xx_pgcrx[slot]
+
+#define M8XX_PGCRX_CXOE 0x00000080
+#define M8XX_PGCRX_CXRESET 0x00000040
+
+/* we keep one lookup table per socket to check flags */
+
+#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
+
+struct event_table {
+ u32 regbit;
+ u32 eventbit;
+};
+
+struct socket_info {
+ void (*handler)(void *info, u32 events);
+ void *info;
+
+ u32 slot;
+
+ socket_state_t state;
+ struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
+ struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
+ struct event_table events[PCMCIA_EVENTS_MAX];
+ struct pcmcia_socket socket;
+};
+
+static struct socket_info socket[PCMCIA_SOCKETS_NO];
+
+/*
+ * Search this table to see if the windowsize is
+ * supported...
+ */
+
+#define M8XX_SIZES_NO 32
+
+static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
+{
+ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
+ 0x00000080, 0x00000040, 0x00000010, 0x00000020,
+ 0x00008000, 0x00004000, 0x00001000, 0x00002000,
+ 0x00000100, 0x00000200, 0x00000800, 0x00000400,
+
+ 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
+ 0x00010000, 0x00020000, 0x00080000, 0x00040000,
+ 0x00800000, 0x00400000, 0x00100000, 0x00200000
+};
+
+/* ------------------------------------------------------------------------- */
+
+static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);
+
+#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
+
+/* ------------------------------------------------------------------------- */
+/* board specific stuff: */
+/* voltage_set(), hardware_enable() and hardware_disable() */
+/* ------------------------------------------------------------------------- */
+/* RPX Boards from Embedded Planet */
+
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+
+/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
+ * SYPCR is write once only, therefore must the slowest memory be faster
+ * than the bus monitor or we will get a machine check due to the bus timeout.
+ */
+
+#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
+
+#undef PCMCIA_BMT_LIMIT
+#define PCMCIA_BMT_LIMIT (6*8)
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ u32 reg = 0;
+
+ switch(vcc) {
+ case 0: break;
+ case 33:
+ reg |= BCSR1_PCVCTL4;
+ break;
+ case 50:
+ reg |= BCSR1_PCVCTL5;
+ break;
+ default:
+ return 1;
+ }
+
+ switch(vpp) {
+ case 0: break;
+ case 33:
+ case 50:
+ if(vcc == vpp)
+ reg |= BCSR1_PCVCTL6;
+ else
+ return 1;
+ break;
+ case 120:
+ reg |= BCSR1_PCVCTL7;
+ default:
+ return 1;
+ }
+
+ if(!((vcc == 50) || (vcc == 0)))
+ return 1;
+
+ /* first, turn off all power */
+
+ out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7));
+
+ /* enable new powersettings */
+
+ out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) | reg);
+
+ return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_RPXCLASSIC */
+
+/* FADS Boards from Motorola */
+
+#if defined(CONFIG_FADS)
+
+#define PCMCIA_BOARD_MSG "FADS"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ u32 reg = 0;
+
+ switch(vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= BCSR1_PCCVCC0;
+ break;
+ case 50:
+ reg |= BCSR1_PCCVCC1;
+ break;
+ default:
+ return 1;
+ }
+
+ switch(vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if(vcc == vpp)
+ reg |= BCSR1_PCCVPP1;
+ else
+ return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= BCSR1_PCCVPP0;
+ else
+ return 1;
+ default:
+ return 1;
+ }
+
+ /* first, turn off all power */
+ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+
+ /* enable new powersettings */
+ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | reg);
+
+ return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static void hardware_enable(int slot)
+{
+ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~BCSR1_PCCEN);
+}
+
+static void hardware_disable(int slot)
+{
+ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | BCSR1_PCCEN);
+}
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Motorola MBX860 */
+
+#if defined(CONFIG_MBX)
+
+#define PCMCIA_BOARD_MSG "MBX"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ u8 reg = 0;
+
+ switch(vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= CSR2_VCC_33;
+ break;
+ case 50:
+ reg |= CSR2_VCC_50;
+ break;
+ default:
+ return 1;
+ }
+
+ switch(vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if(vcc == vpp)
+ reg |= CSR2_VPP_VCC;
+ else
+ return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= CSR2_VPP_12;
+ else
+ return 1;
+ default:
+ return 1;
+ }
+
+ /* first, turn off all power */
+ out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
+
+ /* enable new powersettings */
+ out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) | reg);
+
+ return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_MBX */
+
+#if defined(CONFIG_PRxK)
+#include <asm/cpld.h>
+extern volatile fpga_pc_regs *fpga_pc;
+
+#define PCMCIA_BOARD_MSG "MPC855T"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ u8 reg = 0;
+ u8 regread;
+ cpld_regs *ccpld = get_cpld();
+
+ switch(vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= PCMCIA_VCC_33;
+ break;
+ case 50:
+ reg |= PCMCIA_VCC_50;
+ break;
+ default:
+ return 1;
+ }
+
+ switch(vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if(vcc == vpp)
+ reg |= PCMCIA_VPP_VCC;
+ else
+ return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= PCMCIA_VPP_12;
+ else
+ return 1;
+ default:
+ return 1;
+ }
+
+ reg = reg >> (slot << 2);
+ regread = in_8(&ccpld->fpga_pc_ctl);
+ if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
+ /* enable new powersettings */
+ regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+ out_8(&ccpld->fpga_pc_ctl, reg | regread);
+ msleep(100);
+ }
+
+ return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_PRxK */
+
+static void m8xx_shutdown(void)
+{
+ u32 m, i;
+ struct pcmcia_win *w;
+
+ for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
+ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i));
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i));
+
+ /* turn off interrupt and disable CxOE */
+ out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
+
+ /* turn off memory windows */
+ for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+ out_be32(&w->or, 0); /* set to not valid */
+ w++;
+ }
+
+ /* turn off voltage */
+ voltage_set(i, 0, 0);
+
+ /* disable external hardware */
+ hardware_disable(i);
+ }
+
+ free_irq(pcmcia_schlvl, NULL);
+}
+
+/* copied from tcic.c */
+
+static int m8xx_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+ int ret = 0;
+ if (level == SUSPEND_SAVE_STATE)
+ ret = pcmcia_socket_dev_suspend(dev, state);
+ return ret;
+}
+
+static int m8xx_drv_resume(struct device *dev, u32 level)
+{
+ int ret = 0;
+ if (level == RESUME_RESTORE_STATE)
+ ret = pcmcia_socket_dev_resume(dev);
+ return ret;
+}
+
+static struct device_driver m8xx_driver = {
+ .name = "m8xx-pcmcia",
+ .bus = &platform_bus_type,
+ .suspend = m8xx_drv_suspend,
+ .resume = m8xx_drv_resume,
+};
+
+static struct platform_device m8xx_device = {
+ .name = "m8xx-pcmcia",
+ .id = 0,
+};
+
+static u32 pending_events[PCMCIA_SOCKETS_NO];
+static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
+
+static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ struct socket_info *s;
+ struct event_table *e;
+ unsigned int i, events, pscr, pipr, per;
+
+ dprintk("Interrupt!\n");
+ /* get interrupt sources */
+
+ pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr);
+ pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+ per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per);
+
+ for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+ s = &socket[i];
+ e = &s->events[0];
+ events = 0;
+
+ while(e->regbit) {
+ if(pscr & e->regbit)
+ events |= e->eventbit;
+
+ e++;
+ }
+
+ /*
+ * report only if both card detect signals are the same
+ * not too nice done,
+ * we depend on that CD2 is the bit to the left of CD1...
+ */
+ if(events & SS_DETECT)
+ if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
+ (pipr & M8XX_PCMCIA_CD1(i)))
+ {
+ events &= ~SS_DETECT;
+ }
+
+#ifdef PCMCIA_GLITCHY_CD
+ /*
+ * I've experienced CD problems with my ADS board.
+ * We make an extra check to see if there was a
+ * real change of Card detection.
+ */
+
+ if((events & SS_DETECT) &&
+ ((pipr &
+ (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
+ (s->state.Vcc | s->state.Vpp)) {
+ events &= ~SS_DETECT;
+ /*printk( "CD glitch workaround - CD = 0x%08x!\n",
+ (pipr & (M8XX_PCMCIA_CD2(i)
+ | M8XX_PCMCIA_CD1(i))));*/
+ }
+#endif
+
+ /* call the handler */
+
+ dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
+ "pipr = 0x%08x\n",
+ i, events, pscr, pipr);
+
+ if(events) {
+ spin_lock(&pending_event_lock);
+ pending_events[i] |= events;
+ spin_unlock(&pending_event_lock);
+ /*
+ * Turn off RDY_L bits in the PER mask on
+ * CD interrupt receival.
+ *
+ * They can generate bad interrupts on the
+ * ACS4,8,16,32. - marcelo
+ */
+ per &= ~M8XX_PCMCIA_RDY_L(0);
+ per &= ~M8XX_PCMCIA_RDY_L(1);
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
+
+ if (events)
+ pcmcia_parse_events(&socket[i].socket, events);
+ }
+ }
+
+ /* clear the interrupt sources */
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
+
+ dprintk("Interrupt done.\n");
+
+ return IRQ_HANDLED;
+}
+
+static u32 m8xx_get_graycode(u32 size)
+{
+ u32 k;
+
+ for(k = 0; k < M8XX_SIZES_NO; k++)
+ if(m8xx_size_to_gray[k] == size)
+ break;
+
+ if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
+ k = -1;
+
+ return k;
+}
+
+static u32 m8xx_get_speed(u32 ns, u32 is_io)
+{
+ u32 reg, clocks, psst, psl, psht;
+
+ if(!ns) {
+
+ /*
+ * We get called with IO maps setup to 0ns
+ * if not specified by the user.
+ * They should be 255ns.
+ */
+
+ if(is_io)
+ ns = 255;
+ else
+ ns = 100; /* fast memory if 0 */
+ }
+
+ /*
+ * In PSST, PSL, PSHT fields we tell the controller
+ * timing parameters in CLKOUT clock cycles.
+ * CLKOUT is the same as GCLK2_50.
+ */
+
+/* how we want to adjust the timing - in percent */
+
+#define ADJ 180 /* 80 % longer accesstime - to be sure */
+
+ clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
+ clocks = (clocks * ADJ) / (100*1000);
+ if(clocks >= PCMCIA_BMT_LIMIT) {
+ printk( "Max access time limit reached\n");
+ clocks = PCMCIA_BMT_LIMIT-1;
+ }
+
+ psst = clocks / 7; /* setup time */
+ psht = clocks / 7; /* hold time */
+ psl = (clocks * 5) / 7; /* strobe length */
+
+ psst += clocks - (psst + psht + psl);
+
+ reg = psst << 12;
+ reg |= psl << 7;
+ reg |= psht << 16;
+
+ return reg;
+}
+
+static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
+{
+ int lsock = container_of(sock, struct socket_info, socket)->slot;
+ struct socket_info *s = &socket[lsock];
+ unsigned int pipr, reg;
+
+ pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+
+ *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
+ | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
+ *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
+
+ if (s->state.flags & SS_IOCARD)
+ *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
+ else {
+ *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
+ *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
+ *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
+ }
+
+ if (s->state.Vcc | s->state.Vpp)
+ *value |= SS_POWERON;
+
+ /*
+ * Voltage detection:
+ * This driver only supports 16-Bit pc-cards.
+ * Cardbus is not handled here.
+ *
+ * To determine what voltage to use we must read the VS1 and VS2 pin.
+ * Depending on what socket type is present,
+ * different combinations mean different things.
+ *
+ * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse
+ *
+ * 5V 5V, LV* NC NC 5V only 5V (if available)
+ *
+ * 5V 5V, LV* GND NC 5 or 3.3V as low as possible
+ *
+ * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible
+ *
+ * LV* 5V - - shall not fit into socket
+ *
+ * LV* LV* GND NC 3.3V only 3.3V
+ *
+ * LV* LV* NC GND x.xV x.xV (if avail.)
+ *
+ * LV* LV* GND GND 3.3 or x.xV as low as possible
+ *
+ * *LV means Low Voltage
+ *
+ *
+ * That gives us the following table:
+ *
+ * Socket VS1 VS2 Voltage
+ *
+ * 5V NC NC 5V
+ * 5V NC GND none (should not be possible)
+ * 5V GND NC >= 3.3V
+ * 5V GND GND >= x.xV
+ *
+ * LV NC NC 5V (if available)
+ * LV NC GND x.xV (if available)
+ * LV GND NC 3.3V
+ * LV GND GND >= x.xV
+ *
+ * So, how do I determine if I have a 5V or a LV
+ * socket on my board? Look at the socket!
+ *
+ *
+ * Socket with 5V key:
+ * ++--------------------------------------------+
+ * || |
+ * || ||
+ * || ||
+ * | |
+ * +---------------------------------------------+
+ *
+ * Socket with LV key:
+ * ++--------------------------------------------+
+ * || |
+ * | ||
+ * | ||
+ * | |
+ * +---------------------------------------------+
+ *
+ *
+ * With other words - LV only cards does not fit
+ * into the 5V socket!
+ */
+
+ /* read out VS1 and VS2 */
+
+ reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
+ >> M8XX_PCMCIA_VS_SHIFT(lsock);
+
+ if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
+ switch(reg) {
+ case 1:
+ *value |= SS_3VCARD;
+ break; /* GND, NC - 3.3V only */
+ case 2:
+ *value |= SS_XVCARD;
+ break; /* NC. GND - x.xV only */
+ };
+ }
+
+ dprintk("GetStatus(%d) = %#2.2x\n", lsock, *value);
+ return 0;
+}
+
+static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+ int lsock = container_of(sock, struct socket_info, socket)->slot;
+ *state = socket[lsock].state; /* copy the whole structure */
+
+ dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
+ "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
+ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+ return 0;
+}
+
+static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+ int lsock = container_of(sock, struct socket_info, socket)->slot;
+ struct socket_info *s = &socket[lsock];
+ struct event_table *e;
+ unsigned int reg;
+ unsigned long flags;
+
+ dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+ "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
+ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+
+ /* First, set voltage - bail out if invalid */
+ if(voltage_set(lsock, state->Vcc, state->Vpp))
+ return -EINVAL;
+
+ /* Take care of reset... */
+ if(state->flags & SS_RESET)
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
+ else
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
+
+ /* ... and output enable. */
+
+ /* The CxOE signal is connected to a 74541 on the ADS.
+ I guess most other boards used the ADS as a reference.
+ I tried to control the CxOE signal with SS_OUTPUT_ENA,
+ but the reset signal seems connected via the 541.
+ If the CxOE is left high are some signals tristated and
+ no pullups are present -> the cards act wierd.
+ So right now the buffers are enabled if the power is on. */
+
+ if(state->Vcc || state->Vpp)
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
+ else
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
+
+ /*
+ * We'd better turn off interrupts before
+ * we mess with the events-table..
+ */
+
+ spin_lock_irqsave(&events_lock, flags);
+
+ /*
+ * Play around with the interrupt mask to be able to
+ * give the events the generic pcmcia driver wants us to.
+ */
+
+ e = &s->events[0];
+ reg = 0;
+
+ if(state->csc_mask & SS_DETECT) {
+ e->eventbit = SS_DETECT;
+ reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
+ | M8XX_PCMCIA_CD1(lsock));
+ e++;
+ }
+ if(state->flags & SS_IOCARD) {
+ /*
+ * I/O card
+ */
+ if(state->csc_mask & SS_STSCHG) {
+ e->eventbit = SS_STSCHG;
+ reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
+ e++;
+ }
+ /*
+ * If io_irq is non-zero we should enable irq.
+ */
+ if(state->io_irq) {
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24);
+ /*
+ * Strange thing here:
+ * The manual does not tell us which interrupt
+ * the sources generate.
+ * Anyhow, I found out that RDY_L generates IREQLVL.
+ *
+ * We use level triggerd interrupts, and they don't
+ * have to be cleared in PSCR in the interrupt handler.
+ */
+ reg |= M8XX_PCMCIA_RDY_L(lsock);
+ }
+ else
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
+ }
+ else {
+ /*
+ * Memory card
+ */
+ if(state->csc_mask & SS_BATDEAD) {
+ e->eventbit = SS_BATDEAD;
+ reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
+ e++;
+ }
+ if(state->csc_mask & SS_BATWARN) {
+ e->eventbit = SS_BATWARN;
+ reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
+ e++;
+ }
+ /* What should I trigger on - low/high,raise,fall? */
+ if(state->csc_mask & SS_READY) {
+ e->eventbit = SS_READY;
+ reg |= e->regbit = 0; //??
+ e++;
+ }
+ }
+
+ e->regbit = 0; /* terminate list */
+
+ /*
+ * Clear the status changed .
+ * Port A and Port B share the same port.
+ * Writing ones will clear the bits.
+ */
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
+
+ /*
+ * Write the mask.
+ * Port A and Port B share the same port.
+ * Need for read-modify-write.
+ * Ones will enable the interrupt.
+ */
+
+ /*
+ reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per
+ & M8XX_PCMCIA_MASK(lsock);
+ */
+
+ reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
+ (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg);
+
+ spin_unlock_irqrestore(&events_lock, flags);
+
+ /* copy the struct and modify the copy */
+
+ s->state = *state;
+
+ return 0;
+}
+
+static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+{
+ int lsock = container_of(sock, struct socket_info, socket)->slot;
+
+ struct socket_info *s = &socket[lsock];
+ struct pcmcia_win *w;
+ unsigned int reg, winnr;
+
+#define M8XX_SIZE (io->stop - io->start + 1)
+#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
+
+ dprintk( "SetIOMap(%d, %d, %#2.2x, %d ns, "
+ "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
+ io->speed, io->start, io->stop);
+
+ if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
+ || (io->stop > 0xffff) || (io->stop < io->start))
+ return -EINVAL;
+
+ if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
+ return -EINVAL;
+
+ if(io->flags & MAP_ACTIVE) {
+
+ dprintk( "io->flags & MAP_ACTIVE\n");
+
+ winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
+ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
+
+ /* setup registers */
+
+ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w += winnr;
+
+ out_be32(&w->or, 0); /* turn off window first */
+ out_be32(&w->br, M8XX_BASE);
+
+ reg <<= 27;
+ reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
+
+ reg |= m8xx_get_speed(io->speed, 1);
+
+ if(io->flags & MAP_WRPROT)
+ reg |= M8XX_PCMCIA_POR_WRPROT;
+
+ /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
+ if(io->flags & MAP_16BIT)
+ reg |= M8XX_PCMCIA_POR_16BIT;
+
+ if(io->flags & MAP_ACTIVE)
+ reg |= M8XX_PCMCIA_POR_VALID;
+
+ out_be32(&w->or, reg);
+
+ dprintk("Socket %u: Mapped io window %u at %#8.8x, "
+ "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+ } else {
+ /* shutdown IO window */
+ winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
+ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
+
+ /* setup registers */
+
+ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w += winnr;
+
+ out_be32(&w->or, 0); /* turn off window */
+ out_be32(&w->br, 0); /* turn off base address */
+
+ dprintk("Socket %u: Unmapped io window %u at %#8.8x, "
+ "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+ }
+
+ /* copy the struct and modify the copy */
+ s->io_win[io->map] = *io;
+ s->io_win[io->map].flags &= (MAP_WRPROT
+ | MAP_16BIT
+ | MAP_ACTIVE);
+ dprintk("SetIOMap exit\n");
+
+ return 0;
+}
+
+static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+{
+ int lsock = container_of(sock, struct socket_info, socket)->slot;
+ struct socket_info *s = &socket[lsock];
+ struct pcmcia_win *w;
+ struct pccard_mem_map *old;
+ unsigned int reg, winnr;
+
+ dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
+ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, mem->static_start, mem->card_start);
+
+ if ((mem->map >= PCMCIA_MEM_WIN_NO)
+// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
+ || (mem->card_start >= 0x04000000)
+ || (mem->static_start & 0xfff) /* 4KByte resolution */
+ || (mem->card_start & 0xfff))
+ return -EINVAL;
+
+ if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
+ printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
+ return -EINVAL;
+ }
+ reg <<= 27;
+
+ winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
+
+ /* Setup the window in the pcmcia controller */
+
+ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w += winnr;
+
+ reg |= lsock << 2;
+
+ reg |= m8xx_get_speed(mem->speed, 0);
+
+ if(mem->flags & MAP_ATTRIB)
+ reg |= M8XX_PCMCIA_POR_ATTRMEM;
+
+ if(mem->flags & MAP_WRPROT)
+ reg |= M8XX_PCMCIA_POR_WRPROT;
+
+ if(mem->flags & MAP_16BIT)
+ reg |= M8XX_PCMCIA_POR_16BIT;
+
+ if(mem->flags & MAP_ACTIVE)
+ reg |= M8XX_PCMCIA_POR_VALID;
+
+ out_be32(&w->or, reg);
+
+ dprintk("Socket %u: Mapped memory window %u at %#8.8x, "
+ "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
+
+ if(mem->flags & MAP_ACTIVE) {
+ /* get the new base address */
+ mem->static_start = PCMCIA_MEM_WIN_BASE +
+ (PCMCIA_MEM_WIN_SIZE * winnr)
+ + mem->card_start;
+ }
+
+ dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
+ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, mem->static_start, mem->card_start);
+
+ /* copy the struct and modify the copy */
+
+ old = &s->mem_win[mem->map];
+
+ *old = *mem;
+ old->flags &= (MAP_ATTRIB
+ | MAP_WRPROT
+ | MAP_16BIT
+ | MAP_ACTIVE);
+
+ return 0;
+}
+
+static int m8xx_sock_init(struct pcmcia_socket *sock)
+{
+ int i;
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
+ pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+
+ dprintk( "sock_init(%d)\n", s);
+
+ m8xx_set_socket(sock, &dead_socket);
+ for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
+ io.map = i;
+ m8xx_set_io_map(sock, &io);
+ }
+ for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
+ mem.map = i;
+ m8xx_set_mem_map(sock, &mem);
+ }
+
+ return 0;
+
+}
+
+static int m8xx_suspend(struct pcmcia_socket *sock)
+{
+ return m8xx_set_socket(sock, &dead_socket);
+}
+
+static struct pccard_operations m8xx_services = {
+ .init = m8xx_sock_init,
+ .suspend = m8xx_suspend,
+ .get_status = m8xx_get_status,
+ .get_socket = m8xx_get_socket,
+ .set_socket = m8xx_set_socket,
+ .set_io_map = m8xx_set_io_map,
+ .set_mem_map = m8xx_set_mem_map,
+};
+
+static int __init m8xx_init(void)
+{
+ struct pcmcia_win *w;
+ unsigned int i,m;
+
+ pcmcia_info("%s\n", version);
+
+ if (driver_register(&m8xx_driver))
+ return -1;
+
+ pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
+ " with IRQ %u.\n", pcmcia_schlvl);
+
+ /* Configure Status change interrupt */
+
+ if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
+ "m8xx_pcmcia", NULL)) {
+ pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
+ pcmcia_schlvl);
+ return -1;
+ }
+
+ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
+ M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+
+ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per,
+ in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
+ ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)));
+
+/* connect interrupt and disable CxOE */
+
+ out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
+ out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
+
+/* intialize the fixed memory windows */
+
+ for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
+ for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+ out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
+ (PCMCIA_MEM_WIN_SIZE
+ * (m + i * PCMCIA_MEM_WIN_NO)));
+
+ out_be32(&w->or, 0); /* set to not valid */
+
+ w++;
+ }
+ }
+
+/* turn off voltage */
+ voltage_set(0, 0, 0);
+ voltage_set(1, 0, 0);
+
+/* Enable external hardware */
+ hardware_enable(0);
+ hardware_enable(1);
+
+ platform_device_register(&m8xx_device);
+
+ for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
+ socket[i].slot = i;
+ socket[i].socket.owner = THIS_MODULE;
+ socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
+ socket[i].socket.irq_mask = 0x000;
+ socket[i].socket.map_size = 0x1000;
+ socket[i].socket.io_offset = 0;
+ socket[i].socket.pci_irq = i ? 7 : 9;
+ socket[i].socket.ops = &m8xx_services;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+ socket[i].socket.cb_dev = NULL;
+ socket[i].socket.dev.dev = &m8xx_device.dev;
+ }
+
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
+ pcmcia_register_socket(&socket[i].socket);
+
+ return 0;
+}
+
+static void __exit m8xx_exit(void)
+{
+ int i;
+
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
+ pcmcia_unregister_socket(&socket[i].socket);
+
+ m8xx_shutdown();
+
+ platform_device_unregister(&m8xx_device);
+ driver_unregister(&m8xx_driver);
+}
+
+module_init(m8xx_init);
+module_exit(m8xx_exit);
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
new file mode 100644
index 000000000000..47b5ade95bde
--- /dev/null
+++ b/drivers/pcmcia/omap_cf.c
@@ -0,0 +1,358 @@
+/*
+ * omap_cf.c -- OMAP 16xx CompactFlash controller driver
+ *
+ * Copyright (c) 2005 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
+
+
+/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
+ * hard-wired timings to support Compact Flash memory cards; they won't work
+ * with various other devices (like WLAN adapters) without some external
+ * logic to help out.
+ *
+ * NOTE: CF controller docs disagree with address space docs as to where
+ * CF_BASE really lives; this is a doc erratum.
+ */
+#define CF_BASE 0xfffe2800
+
+/* status; read after IRQ */
+#define CF_STATUS_REG __REG16(CF_BASE + 0x00)
+# define CF_STATUS_BAD_READ (1 << 2)
+# define CF_STATUS_BAD_WRITE (1 << 1)
+# define CF_STATUS_CARD_DETECT (1 << 0)
+
+/* which chipselect (CS0..CS3) is used for CF (active low) */
+#define CF_CFG_REG __REG16(CF_BASE + 0x02)
+
+/* card reset */
+#define CF_CONTROL_REG __REG16(CF_BASE + 0x04)
+# define CF_CONTROL_RESET (1 << 0)
+
+#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT))
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "omap_cf";
+
+struct omap_cf_socket {
+ struct pcmcia_socket socket;
+
+ struct timer_list timer;
+ unsigned present:1;
+ unsigned active:1;
+
+ struct platform_device *pdev;
+ unsigned long phys_cf;
+ u_int irq;
+};
+
+#define POLL_INTERVAL (2 * HZ)
+
+#define SZ_2K (2 * SZ_1K)
+
+/*--------------------------------------------------------------------------*/
+
+static int omap_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void omap_cf_timer(unsigned long _cf)
+{
+ struct omap_cf_socket *cf = (void *) _cf;
+ unsigned present = omap_cf_present();
+
+ if (present != cf->present) {
+ cf->present = present;
+ pr_debug("%s: card %s\n", driver_name,
+ present ? "present" : "gone");
+ pcmcia_parse_events(&cf->socket, SS_DETECT);
+ }
+
+ if (cf->active)
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+/* This irq handler prevents "irqNNN: nobody cared" messages as drivers
+ * claim the card's IRQ. It may also detect some card insertions, but
+ * not removals; it can't always eliminate timer irqs.
+ */
+static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+ omap_cf_timer((unsigned long)_cf);
+ return IRQ_HANDLED;
+}
+
+static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ if (!sp)
+ return -EINVAL;
+
+ /* FIXME power management should probably be board-specific:
+ * - 3VCARD vs XVCARD (OSK only handles 3VCARD)
+ * - POWERON (switched on/off by set_socket)
+ */
+ if (omap_cf_present()) {
+ struct omap_cf_socket *cf;
+
+ *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+ cf = container_of(s, struct omap_cf_socket, socket);
+ s->irq.AssignedIRQ = cf->irq;
+ } else
+ *sp = 0;
+ return 0;
+}
+
+static int
+omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+ u16 control;
+
+ /* FIXME some non-OSK boards will support power switching */
+ switch (s->Vcc) {
+ case 0:
+ case 33:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ control = CF_CONTROL_REG;
+ if (s->flags & SS_RESET)
+ CF_CONTROL_REG = CF_CONTROL_RESET;
+ else
+ CF_CONTROL_REG = 0;
+
+ pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+ return 0;
+}
+
+static int omap_cf_ss_suspend(struct pcmcia_socket *s)
+{
+ pr_debug("%s: %s\n", driver_name, __FUNCTION__);
+ return omap_cf_set_socket(s, &dead_socket);
+}
+
+/* regions are 2K each: mem, attrib, io (and reserved-for-ide) */
+
+static int
+omap_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+ struct omap_cf_socket *cf;
+
+ cf = container_of(s, struct omap_cf_socket, socket);
+ io->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ io->start = cf->phys_cf + SZ_4K;
+ io->stop = io->start + SZ_2K - 1;
+ return 0;
+}
+
+static int
+omap_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+ struct omap_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+ cf = container_of(s, struct omap_cf_socket, socket);
+ map->static_start = cf->phys_cf;
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ if (map->flags & MAP_ATTRIB)
+ map->static_start += SZ_2K;
+ return 0;
+}
+
+static struct pccard_operations omap_cf_ops = {
+ .init = omap_cf_ss_init,
+ .suspend = omap_cf_ss_suspend,
+ .get_status = omap_cf_get_status,
+ .set_socket = omap_cf_set_socket,
+ .set_io_map = omap_cf_set_io_map,
+ .set_mem_map = omap_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * NOTE: right now the only board-specific platform_data is
+ * "what chipselect is used". Boards could want more.
+ */
+
+static int __init omap_cf_probe(struct device *dev)
+{
+ unsigned seg;
+ struct omap_cf_socket *cf;
+ struct platform_device *pdev = to_platform_device(dev);
+ int irq;
+ int status;
+
+ seg = (int) dev->platform_data;
+ if (seg == 0 || seg > 3)
+ return -ENODEV;
+
+ /* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
+ irq = platform_get_irq(pdev, 0);
+ if (!irq)
+ return -EINVAL;
+
+ cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+ init_timer(&cf->timer);
+ cf->timer.function = omap_cf_timer;
+ cf->timer.data = (unsigned long) cf;
+
+ cf->pdev = pdev;
+ dev_set_drvdata(dev, cf);
+
+ /* this primarily just shuts up irq handling noise */
+ status = request_irq(irq, omap_cf_irq, SA_SHIRQ,
+ driver_name, cf);
+ if (status < 0)
+ goto fail0;
+ cf->irq = irq;
+ cf->socket.pci_irq = irq;
+
+ switch (seg) {
+ /* NOTE: CS0 could be configured too ... */
+ case 1:
+ cf->phys_cf = OMAP_CS1_PHYS;
+ break;
+ case 2:
+ cf->phys_cf = OMAP_CS2_PHYS;
+ break;
+ case 3:
+ cf->phys_cf = omap_cs3_phys();
+ break;
+ default:
+ goto fail1;
+ }
+
+ /* pcmcia layer only remaps "real" memory */
+ cf->socket.io_offset = (unsigned long)
+ ioremap(cf->phys_cf + SZ_4K, SZ_2K);
+ if (!cf->socket.io_offset)
+ goto fail1;
+
+ if (!request_mem_region(cf->phys_cf, SZ_8K, driver_name))
+ goto fail1;
+
+ /* NOTE: CF conflicts with MMC1 */
+ omap_cfg_reg(W11_1610_CF_CD1);
+ omap_cfg_reg(P11_1610_CF_CD2);
+ omap_cfg_reg(R11_1610_CF_IOIS16);
+ omap_cfg_reg(V10_1610_CF_IREQ);
+ omap_cfg_reg(W10_1610_CF_RESET);
+
+ CF_CFG_REG = ~(1 << seg);
+
+ pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq);
+
+ /* NOTE: better EMIFS setup might support more cards; but the
+ * TRM only shows how to affect regular flash signals, not their
+ * CF/PCMCIA variants...
+ */
+ pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name,
+ seg, EMIFS_CCS(seg), EMIFS_ACS(seg));
+ EMIFS_CCS(seg) = 0x0004a1b3; /* synch mode 4 etc */
+ EMIFS_ACS(seg) = 0x00000000; /* OE hold/setup */
+
+ /* CF uses armxor_ck, which is "always" available */
+
+ pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name,
+ CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG,
+ omap_cf_present() ? "present" : "(not present)");
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.dev = dev;
+ cf->socket.ops = &omap_cf_ops;
+ cf->socket.resource_ops = &pccard_static_ops;
+ cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+ | SS_CAP_MEM_ALIGN;
+ cf->socket.map_size = SZ_2K;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0)
+ goto fail2;
+
+ cf->active = 1;
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+ return 0;
+
+fail2:
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(cf->phys_cf, SZ_8K);
+fail1:
+ free_irq(irq, cf);
+fail0:
+ kfree(cf);
+ return status;
+}
+
+static int __devexit omap_cf_remove(struct device *dev)
+{
+ struct omap_cf_socket *cf = dev_get_drvdata(dev);
+
+ cf->active = 0;
+ pcmcia_unregister_socket(&cf->socket);
+ del_timer_sync(&cf->timer);
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(cf->phys_cf, SZ_8K);
+ free_irq(cf->irq, cf);
+ kfree(cf);
+ return 0;
+}
+
+static struct device_driver omap_cf_driver = {
+ .name = (char *) driver_name,
+ .bus = &platform_bus_type,
+ .probe = omap_cf_probe,
+ .remove = __devexit_p(omap_cf_remove),
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
+};
+
+static int __init omap_cf_init(void)
+{
+ if (cpu_is_omap16xx())
+ driver_register(&omap_cf_driver);
+ return 0;
+}
+
+static void __exit omap_cf_exit(void)
+{
+ if (cpu_is_omap16xx())
+ driver_unregister(&omap_cf_driver);
+}
+
+module_init(omap_cf_init);
+module_exit(omap_cf_exit);
+
+MODULE_DESCRIPTION("OMAP CF Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 39ba6406fd54..80969f7e7a0b 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -376,6 +376,7 @@ static int ds_open(struct inode *inode, struct file *file)
socket_t i = iminor(inode);
struct pcmcia_socket *s;
user_info_t *user;
+ static int warning_printed = 0;
ds_dbg(0, "ds_open(socket %d)\n", i);
@@ -407,6 +408,17 @@ static int ds_open(struct inode *inode, struct file *file)
s->user = user;
file->private_data = user;
+ if (!warning_printed) {
+ printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
+ "usage.\n");
+ printk(KERN_INFO "pcmcia: This interface will soon be removed from "
+ "the kernel; please expect breakage unless you upgrade "
+ "to new tools.\n");
+ printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
+ "utils/kernel/pcmcia/pcmcia.html for details.\n");
+ warning_printed = 1;
+ }
+
if (s->pcmcia_state.present)
queue_event(user, CS_EVENT_CARD_INSERTION);
return 0;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 6f9fdb276402..89022ad5b520 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -41,6 +41,7 @@ module_param(io_speed, int, 0444);
#ifdef CONFIG_PCMCIA_PROBE
+#include <asm/irq.h>
/* mask of IRQs already reserved by other cards, we should avoid using them */
static u8 pcmcia_used_irq[NR_IRQS];
#endif
@@ -446,7 +447,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
if (mod->Vpp1 != mod->Vpp2)
return CS_BAD_VPP;
- c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
+ s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
@@ -622,8 +623,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
- c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
-
/* Pick memory or I/O card, DMA mode, interrupt */
c->IntType = req->IntType;
c->Attributes = req->Attributes;
@@ -821,7 +820,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- p_dev->dev.bus_id,
+ p_dev->devname,
(req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
if (!ret) {
if (!(req->Attributes & IRQ_HANDLE_PRESENT))
@@ -831,7 +830,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
}
}
#endif
- if (ret) {
+ /* only assign PCI irq if no IRQ already assigned */
+ if (ret && !s->irq.AssignedIRQ) {
if (!s->pci_irq)
return ret;
irq = s->pci_irq;
@@ -842,7 +842,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- p_dev->dev.bus_id, req->Instance))
+ p_dev->devname, req->Instance))
return CS_IN_USE;
}
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 3e23cd461fb1..7fa18fb814bc 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -23,6 +23,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -205,32 +206,20 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
}
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe);
-static int pxa2xx_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxa2xx_drv_pcmcia_resume(struct device *dev)
{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
+ struct pcmcia_low_level *ops = dev->platform_data;
+ int nr = ops ? ops->nr : 0;
-static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- {
- struct pcmcia_low_level *ops = dev->platform_data;
- int nr = ops ? ops->nr : 0;
-
- MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
- ret = pcmcia_socket_dev_resume(dev);
- }
- return ret;
+ MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
+
+ return pcmcia_socket_dev_resume(dev);
}
static struct device_driver pxa2xx_pcmcia_driver = {
.probe = pxa2xx_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove,
- .suspend = pxa2xx_drv_pcmcia_suspend,
+ .suspend = pcmcia_socket_dev_suspend,
.resume = pxa2xx_drv_pcmcia_resume,
.name = "pxa2xx-pcmcia",
.bus = &platform_bus_type,
@@ -246,7 +235,7 @@ static void __exit pxa2xx_pcmcia_exit(void)
driver_unregister(&pxa2xx_pcmcia_driver);
}
-module_init(pxa2xx_pcmcia_init);
+fs_initcall(pxa2xx_pcmcia_init);
module_exit(pxa2xx_pcmcia_exit);
MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5309734e1687..5209d8c7764f 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -17,7 +17,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <pcmcia/ss.h>
@@ -196,7 +196,7 @@ static void __exit mst_pcmcia_exit(void)
platform_device_unregister(mst_pcmcia_device);
}
-module_init(mst_pcmcia_init);
+fs_initcall(mst_pcmcia_init);
module_exit(mst_pcmcia_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 42efe218867a..fe5ea36e7de3 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -16,37 +16,34 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-
#include <asm/hardware/scoop.h>
-#include <asm/arch/corgi.h>
-#include <asm/arch/pxa-regs.h>
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch-sa1100/collie.h>
+#else
+#include <asm/arch-pxa/pxa-regs.h>
+#endif
#include "soc_common.h"
#define NO_KEEP_VS 0x0001
-static unsigned char keep_vs;
-static unsigned char keep_rd;
-
-static struct pcmcia_irqs irqs[] = {
- { 0, CORGI_IRQ_GPIO_CF_CD, "PCMCIA0 CD"},
-};
-
-static void sharpsl_pcmcia_init_reset(void)
+static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
{
- reset_scoop(&corgiscoop_device.dev);
- keep_vs = NO_KEEP_VS;
- keep_rd = 0;
+ reset_scoop(scoopdev->dev);
+ scoopdev->keep_vs = NO_KEEP_VS;
+ scoopdev->keep_rd = 0;
}
static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
+#ifndef CONFIG_SA1100_COLLIE
/*
* Setup default state of GPIO outputs
* before we enable them as outputs.
@@ -69,31 +66,38 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
pxa_gpio_mode(GPIO55_nPREG_MD);
pxa_gpio_mode(GPIO56_nPWAIT_MD);
pxa_gpio_mode(GPIO57_nIOIS16_MD);
+#endif
/* Register interrupts */
- ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
-
- if (ret) {
- printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
- return ret;
+ if (scoop_devs[skt->nr].cd_irq >= 0) {
+ struct pcmcia_irqs cd_irq;
+
+ cd_irq.sock = skt->nr;
+ cd_irq.irq = scoop_devs[skt->nr].cd_irq;
+ cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
+ ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1);
+
+ if (ret) {
+ printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
+ return ret;
+ }
}
- /* Enable interrupt */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
- keep_vs = NO_KEEP_VS;
-
- skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
+ skt->irq = scoop_devs[skt->nr].irq;
return 0;
}
static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ if (scoop_devs[skt->nr].cd_irq >= 0) {
+ struct pcmcia_irqs cd_irq;
- /* CF_BUS_OFF */
- sharpsl_pcmcia_init_reset();
+ cd_irq.sock = skt->nr;
+ cd_irq.irq = scoop_devs[skt->nr].cd_irq;
+ cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
+ soc_pcmcia_free_irqs(skt, &cd_irq, 1);
+ }
}
@@ -101,31 +105,32 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
unsigned short cpr, csr;
+ struct device *scoop = scoop_devs[skt->nr].dev;
- cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
+ cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
- csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
+ write_scoop_reg(scoop, SCOOP_IRM, 0x00FF);
+ write_scoop_reg(scoop, SCOOP_ISR, 0x0000);
+ write_scoop_reg(scoop, SCOOP_IRM, 0x0000);
+ csr = read_scoop_reg(scoop, SCOOP_CSR);
if (csr & 0x0004) {
/* card eject */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- keep_vs = NO_KEEP_VS;
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
}
- else if (!(keep_vs & NO_KEEP_VS)) {
+ else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) {
/* keep vs1,vs2 */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- csr |= keep_vs;
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ csr |= scoop_devs[skt->nr].keep_vs;
}
else if (cpr & 0x0003) {
/* power on */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
- keep_vs = (csr & 0x00C0);
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+ scoop_devs[skt->nr].keep_vs = (csr & 0x00C0);
}
else {
/* card detect */
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
+ write_scoop_reg(scoop, SCOOP_CDR, 0x0002);
}
state->detect = (csr & 0x0004) ? 0 : 1;
@@ -147,6 +152,7 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long flags;
+ struct device *scoop = scoop_devs[skt->nr].dev;
unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
@@ -166,10 +172,10 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
local_irq_save(flags);
- nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
- ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
- nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
- nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
+ nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010;
+ ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083;
+ nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080;
+ nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E;
ncpr |= (state->Vcc == 33) ? 0x0001 :
(state->Vcc == 50) ? 0x0002 : 0;
@@ -184,22 +190,22 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
((skt->status&SS_WRPROT) ? 0x0008 : 0);
if (!(ncpr & 0x0003)) {
- keep_rd = 0;
- } else if (!keep_rd) {
+ scoop_devs[skt->nr].keep_rd = 0;
+ } else if (!scoop_devs[skt->nr].keep_rd) {
if (nccr & 0x0080)
- keep_rd = 1;
+ scoop_devs[skt->nr].keep_rd = 1;
else
nccr |= 0x0080;
}
if (mcr != nmcr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
+ write_scoop_reg(scoop, SCOOP_MCR, nmcr);
if (cpr != ncpr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
+ write_scoop_reg(scoop, SCOOP_CPR, ncpr);
if (ccr != nccr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
+ write_scoop_reg(scoop, SCOOP_CCR, nccr);
if (imr != nimr)
- write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
+ write_scoop_reg(scoop, SCOOP_IMR, nimr);
local_irq_restore(flags);
@@ -208,10 +214,26 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
{
+ sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
+
+ /* Enable interrupt */
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0);
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101);
+ scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
+
+ if (machine_is_collie())
+ /* We need to disable SS_OUTPUT_ENA here. */
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080);
}
static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
+ /* CF_BUS_OFF */
+ sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
+
+ if (machine_is_collie())
+ /* We need to disable SS_OUTPUT_ENA here. */
+ write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080);
}
static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -223,21 +245,37 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
.socket_init = sharpsl_pcmcia_socket_init,
.socket_suspend = sharpsl_pcmcia_socket_suspend,
.first = 0,
- .nr = 1,
+ .nr = 0,
};
static struct platform_device *sharpsl_pcmcia_device;
+#ifdef CONFIG_SA1100_COLLIE
+int __init pcmcia_collie_init(struct device *dev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_collie())
+ ret = sa11xx_drv_pcmcia_probe(dev, &sharpsl_pcmcia_ops, 0, 1);
+
+ return ret;
+}
+
+#else
+
static int __init sharpsl_pcmcia_init(void)
{
int ret;
+ sharpsl_pcmcia_ops.nr=scoop_num;
sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
if (!sharpsl_pcmcia_device)
return -ENOMEM;
+
memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
+ sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev;
ret = platform_device_register(sharpsl_pcmcia_device);
if (ret)
@@ -257,8 +295,9 @@ static void __exit sharpsl_pcmcia_exit(void)
platform_device_unregister(sharpsl_pcmcia_device);
}
-module_init(sharpsl_pcmcia_init);
+fs_initcall(sharpsl_pcmcia_init);
module_exit(sharpsl_pcmcia_exit);
+#endif
MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index c42455d20eb6..00960a379b9c 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -691,7 +691,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
unsigned long size = end - start + 1;
int ret = 0;
- if (end <= start)
+ if (end < start)
return -EINVAL;
down(&rsrc_sem);
@@ -724,7 +724,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
unsigned long size = end - start + 1;
int ret = 0;
- if (end <= start)
+ if (end < start)
return -EINVAL;
if (end > IO_SPACE_LIMIT)
@@ -779,7 +779,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
if (!s->cb_dev || !s->cb_dev->bus)
return -ENODEV;
-#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+#if defined(CONFIG_X86)
/* If this is the root bus, the risk of hitting
* some strange system devices which aren't protected
* by either ACPI resource tables or properly requested
@@ -817,7 +817,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
/* if we got at least one of IO, and one of MEM, we can be glad and
* activate the PCMCIA subsystem */
- if (done & (IORESOURCE_MEM | IORESOURCE_IO))
+ if (done == (IORESOURCE_MEM | IORESOURCE_IO))
s->resource_setup_done = 1;
return 0;
@@ -925,7 +925,7 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
return -EINVAL;
}
}
- if (end_addr <= start_addr)
+ if (end_addr < start_addr)
return -EINVAL;
ret = adjust_io(s, add, start_addr, end_addr);
@@ -977,7 +977,7 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
return -EINVAL;
}
}
- if (end_addr <= start_addr)
+ if (end_addr < start_addr)
return -EINVAL;
ret = adjust_memory(s, add, start_addr, end_addr);
@@ -994,7 +994,8 @@ static struct class_device_attribute *pccard_rsrc_attributes[] = {
NULL,
};
-static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *s = class_get_devdata(class_dev);
struct class_device_attribute **attr;
@@ -1011,7 +1012,8 @@ static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
return ret;
}
-static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct pcmcia_socket *s = class_get_devdata(class_dev);
struct class_device_attribute **attr;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index e98bb3d80e7c..6d441ec75c6a 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -33,13 +33,18 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/config.h>
+#include <linux/platform_device.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
+#include <asm/hardware/scoop.h>
+
#include "sa1100_generic.h"
+int __init pcmcia_collie_init(struct device *dev);
+
static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_init,
@@ -56,6 +61,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#ifdef CONFIG_SA1100_SIMPAD
pcmcia_simpad_init,
#endif
+#ifdef CONFIG_SA1100_COLLIE
+ pcmcia_collie_init,
+#endif
};
static int sa11x0_drv_pcmcia_probe(struct device *dev)
@@ -74,29 +82,13 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev)
return ret;
}
-static int sa11x0_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int sa11x0_drv_pcmcia_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver sa11x0_pcmcia_driver = {
.probe = sa11x0_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove,
.name = "sa11x0-pcmcia",
.bus = &platform_bus_type,
- .suspend = sa11x0_drv_pcmcia_suspend,
- .resume = sa11x0_drv_pcmcia_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
/* sa11x0_pcmcia_init()
@@ -126,5 +118,5 @@ MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller");
MODULE_LICENSE("Dual MPL/GPL");
-module_init(sa11x0_pcmcia_init);
+fs_initcall(sa11x0_pcmcia_init);
module_exit(sa11x0_pcmcia_exit);
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index b441f43a6a55..81ded52c8959 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -122,7 +122,7 @@ void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
static int pcmcia_probe(struct sa1111_dev *dev)
{
- char *base;
+ void __iomem *base;
if (!request_mem_region(dev->res.start, 512,
SA1111_DRIVER_NAME(dev)))
@@ -189,7 +189,7 @@ static void __exit sa1111_drv_pcmcia_exit(void)
sa1111_driver_unregister(&pcmcia_driver);
}
-module_init(sa1111_drv_pcmcia_init);
+fs_initcall(sa1111_drv_pcmcia_init);
module_exit(sa1111_drv_pcmcia_exit);
MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c
index db04ffb6f68c..59c5d968e9f6 100644
--- a/drivers/pcmcia/sa11xx_base.c
+++ b/drivers/pcmcia/sa11xx_base.c
@@ -189,7 +189,7 @@ static int __init sa11xx_pcmcia_init(void)
{
return 0;
}
-module_init(sa11xx_pcmcia_init);
+fs_initcall(sa11xx_pcmcia_init);
static void __exit sa11xx_pcmcia_exit(void) {}
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 888b70e6a484..9e7ccd8a4321 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -66,7 +66,7 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
if (pc_debug > lvl) {
printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func);
va_start(args, fmt);
- printk(fmt, args);
+ vprintk(fmt, args);
va_end(args);
}
}
@@ -321,8 +321,6 @@ soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
* less punt all of this work and let the kernel handle the details
* of power configuration, reset, &c. We also record the value of
* `state' in order to regurgitate it to the PCMCIA core later.
- *
- * Returns: 0
*/
static int
soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
@@ -407,7 +405,7 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
* the map speed as requested, but override the address ranges
* supplied by Card Services.
*
- * Returns: 0 on success, -1 on error
+ * Returns: 0 on success, -ERRNO on error
*/
static int
soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
@@ -655,8 +653,8 @@ static void soc_pcmcia_cpufreq_unregister(void)
}
#else
-#define soc_pcmcia_cpufreq_register()
-#define soc_pcmcia_cpufreq_unregister()
+static int soc_pcmcia_cpufreq_register(void) { return 0; }
+static void soc_pcmcia_cpufreq_unregister(void) {}
#endif
int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
@@ -738,7 +736,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
goto out_err_5;
}
- if ( list_empty(&soc_pcmcia_sockets) )
+ if (list_empty(&soc_pcmcia_sockets))
soc_pcmcia_cpufreq_register();
list_add(&skt->node, &soc_pcmcia_sockets);
@@ -839,7 +837,7 @@ int soc_common_drv_pcmcia_remove(struct device *dev)
release_resource(&skt->res_io);
release_resource(&skt->res_skt);
}
- if ( list_empty(&soc_pcmcia_sockets) )
+ if (list_empty(&soc_pcmcia_sockets))
soc_pcmcia_cpufreq_unregister();
up(&soc_pcmcia_sockets_lock);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 1040a6c1a8a4..4a3150a7854c 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -341,7 +341,8 @@ static struct bin_attribute pccard_cis_attr = {
.write = pccard_store_cis,
};
-static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct class_device_attribute **attr;
int ret = 0;
@@ -357,7 +358,8 @@ static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
return ret;
}
-static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev,
+ struct class_interface *class_intf)
{
struct class_device_attribute **attr;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index d5a61eae6119..e31263864377 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -44,7 +44,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <asm/io.h>
@@ -372,27 +372,11 @@ static int __init get_tcic_id(void)
/*====================================================================*/
-static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int tcic_drv_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver tcic_driver = {
.name = "tcic-pcmcia",
.bus = &platform_bus_type,
- .suspend = tcic_drv_suspend,
- .resume = tcic_drv_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device tcic_device = {
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index fbe233e19ceb..539b5cd1a598 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -59,6 +59,7 @@
#define TI122X_SCR_SER_STEP 0xc0000000
#define TI122X_SCR_INTRTIE 0x20000000
+#define TIXX21_SCR_TIEALL 0x10000000
#define TI122X_SCR_CBRSVD 0x00400000
#define TI122X_SCR_MRBURSTDN 0x00008000
#define TI122X_SCR_MRBURSTUP 0x00004000
@@ -153,6 +154,12 @@
/* EnE test register */
#define ENE_TEST_C9 0xc9 /* 8bit */
#define ENE_TEST_C9_TLTENABLE 0x02
+#define ENE_TEST_C9_PFENABLE_F0 0x04
+#define ENE_TEST_C9_PFENABLE_F1 0x08
+#define ENE_TEST_C9_PFENABLE (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0)
+#define ENE_TEST_C9_WPDISALBLE_F0 0x40
+#define ENE_TEST_C9_WPDISALBLE_F1 0x80
+#define ENE_TEST_C9_WPDISALBLE (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1)
/*
* Texas Instruments CardBus controller overrides.
@@ -618,6 +625,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
int devfn;
unsigned int state;
int ret = 1;
+ u32 sysctl;
/* catch the two-slot controllers */
switch (socket->dev->device) {
@@ -640,6 +648,24 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
*/
break;
+ case PCI_DEVICE_ID_TI_X515:
+ case PCI_DEVICE_ID_TI_X420:
+ case PCI_DEVICE_ID_TI_X620:
+ case PCI_DEVICE_ID_TI_XX21_XX11:
+ case PCI_DEVICE_ID_TI_7410:
+ case PCI_DEVICE_ID_TI_7610:
+ /*
+ * those are either single or dual slot CB with additional functions
+ * like 1394, smartcard reader, etc. check the TIEALL flag for them
+ * the TIEALL flag binds the IRQ of all functions toghether.
+ * we catch the single slot variants later.
+ */
+ sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ if (sysctl & TIXX21_SCR_TIEALL)
+ return 0;
+
+ break;
+
/* single-slot controllers have the 2nd slot empty always :) */
default:
return 1;
@@ -652,6 +678,15 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
if (!func)
return 1;
+ /*
+ * check that the device id of both slots match. this is needed for the
+ * XX21 and the XX11 controller that share the same device id for single
+ * and dual slot controllers. return '2nd slot empty'. we already checked
+ * if the interrupt is tied to another function.
+ */
+ if (socket->dev->device != func->device)
+ goto out;
+
slot2 = pci_get_drvdata(func);
if (!slot2)
goto out;
@@ -791,16 +826,6 @@ static int ti12xx_override(struct yenta_socket *socket)
config_writel(socket, TI113X_SYSTEM_CONTROL, val);
/*
- * for EnE bridges only: clear testbit TLTEnable. this makes the
- * RME Hammerfall DSP sound card working.
- */
- if (socket->dev->vendor == PCI_VENDOR_ID_ENE) {
- u8 test_c9 = config_readb(socket, ENE_TEST_C9);
- test_c9 &= ~ENE_TEST_C9_TLTENABLE;
- config_writeb(socket, ENE_TEST_C9, test_c9);
- }
-
- /*
* Yenta expects controllers to use CSCINT to route
* CSC interrupts to PCI rather than INTVAL.
*/
@@ -841,5 +866,78 @@ static int ti1250_override(struct yenta_socket *socket)
return ti12xx_override(socket);
}
+
+/**
+ * EnE specific part. EnE bridges are register compatible with TI bridges but
+ * have their own test registers and more important their own little problems.
+ * Some fixup code to make everybody happy (TM).
+ */
+
+#ifdef CONFIG_CARDBUS
+/**
+ * set/clear various test bits:
+ * Defaults to clear the bit.
+ * - mask (u8) defines what bits to change
+ * - bits (u8) is the values to change them to
+ * -> it's
+ * current = (current & ~mask) | bits
+ */
+/* pci ids of devices that wants to have the bit set */
+#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) { \
+ .vendor = _vend, \
+ .device = _dev, \
+ .subvendor = _subvend, \
+ .subdevice = _subdev, \
+ .driver_data = ((mask) << 8 | (bits)), \
+ }
+static struct pci_device_id ene_tune_tbl[] = {
+ /* Echo Audio products based on motorola DSP56301 and DSP56361 */
+ DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID,
+ ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+ DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,
+ ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+
+ {}
+};
+
+static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ struct pci_dev *dev;
+ struct pci_device_id *id = NULL;
+ u8 test_c9, old_c9, mask, bits;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev);
+ if (id)
+ break;
+ }
+
+ test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9);
+ if (id) {
+ mask = (id->driver_data >> 8) & 0xFF;
+ bits = id->driver_data & 0xFF;
+
+ test_c9 = (test_c9 & ~mask) | bits;
+ }
+ else
+ /* 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);
+ config_writeb(socket, ENE_TEST_C9, test_c9);
+}
+
+static int ene_override(struct yenta_socket *socket)
+{
+ /* install tune_bridge() function */
+ socket->socket.tune_bridge = ene_tune_bridge;
+
+ return ti1250_override(socket);
+}
+#else
+# define ene_override ti1250_override
+#endif
+
#endif /* _LINUX_TI113X_H */
diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h
index be420bb29113..edccfa5bb400 100644
--- a/drivers/pcmcia/topic.h
+++ b/drivers/pcmcia/topic.h
@@ -101,6 +101,8 @@
#define TOPIC97_AVS_AUDIO_CONTROL 0x02
#define TOPIC97_AVS_VIDEO_CONTROL 0x01
+#define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */
+#define TOPIC_EXCA_IFC_33V_ENA 0x01
static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
{
@@ -137,4 +139,19 @@ static int topic97_override(struct yenta_socket *socket)
return 0;
}
+
+static int topic95_override(struct yenta_socket *socket)
+{
+ u8 fctrl;
+
+ /* enable 3.3V support for 16bit cards */
+ fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
+ exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA);
+
+ /* tell yenta to use exca registers to power 16bit cards */
+ socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
+
+ return 0;
+}
+
#endif /* _LINUX_TOPIC_H */
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 17bb2da6752b..38a028c725d4 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/types.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
@@ -774,31 +775,11 @@ static int __devinit vrc4171_card_setup(char *options)
__setup("vrc4171_card=", vrc4171_card_setup);
-static int vrc4171_card_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int retval = 0;
-
- if (level == SUSPEND_SAVE_STATE)
- retval = pcmcia_socket_dev_suspend(dev, state);
-
- return retval;
-}
-
-static int vrc4171_card_resume(struct device *dev, u32 level)
-{
- int retval = 0;
-
- if (level == RESUME_RESTORE_STATE)
- retval = pcmcia_socket_dev_resume(dev);
-
- return retval;
-}
-
static struct device_driver vrc4171_card_driver = {
.name = vrc4171_card_name,
.bus = &platform_bus_type,
- .suspend = vrc4171_card_suspend,
- .resume = vrc4171_card_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static int __devinit vrc4171_card_init(void)
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 91e7457d5b04..ec6ab65f0872 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
{
debug("%p %04x %08x\n", socket, reg, val);
writel(val, socket->base + reg);
+ readl(socket->base + reg); /* avoid problems with PCI write posting */
}
static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
{
debug("%p %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)
@@ -143,8 +145,46 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
debug("%p %04x %04x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
writeb(val >> 8, socket->base + 0x800 + reg + 1);
+
+ /* PCI write posting... */
+ readb(socket->base + 0x800 + reg);
+ readb(socket->base + 0x800 + reg + 1);
+}
+
+static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *dev = to_pci_dev(yentadev);
+ struct yenta_socket *socket = pci_get_drvdata(dev);
+ int offset = 0, i;
+
+ offset = snprintf(buf, PAGE_SIZE, "CB registers:");
+ for (i = 0; i < 0x24; i += 4) {
+ unsigned val;
+ if (!(i & 15))
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ val = cb_readl(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val);
+ }
+
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:");
+ for (i = 0; i < 0x45; i++) {
+ unsigned char val;
+ if (!(i & 7)) {
+ if (i & 8) {
+ memcpy(buf + offset, " -", 2);
+ offset += 2;
+ } else
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ }
+ val = exca_readb(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val);
+ }
+ buf[offset++] = '\n';
+ return offset;
}
+static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL);
+
/*
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
@@ -184,22 +224,52 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0;
}
-static int yenta_Vcc_power(u32 control)
+static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
{
- switch (control & CB_SC_VCC_MASK) {
- case CB_SC_VCC_5V: return 50;
- case CB_SC_VCC_3V: return 33;
- default: return 0;
- }
-}
+ if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+ (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+ u8 reg, vcc, vpp;
+
+ reg = exca_readb(socket, I365_POWER);
+ vcc = reg & I365_VCC_MASK;
+ vpp = reg & I365_VPP1_MASK;
+ state->Vcc = state->Vpp = 0;
+
+ if (socket->flags & YENTA_16BIT_POWER_DF) {
+ if (vcc == I365_VCC_3V)
+ state->Vcc = 33;
+ if (vcc == I365_VCC_5V)
+ state->Vcc = 50;
+ if (vpp == I365_VPP1_5V)
+ state->Vpp = state->Vcc;
+ if (vpp == I365_VPP1_12V)
+ state->Vpp = 120;
+ } else {
+ if (reg & I365_VCC_5V) {
+ state->Vcc = 50;
+ if (vpp == I365_VPP1_5V)
+ state->Vpp = 50;
+ if (vpp == I365_VPP1_12V)
+ state->Vpp = 120;
+ }
+ }
+ } else {
+ u32 control;
-static int yenta_Vpp_power(u32 control)
-{
- switch (control & CB_SC_VPP_MASK) {
- case CB_SC_VPP_12V: return 120;
- case CB_SC_VPP_5V: return 50;
- case CB_SC_VPP_3V: return 33;
- default: return 0;
+ control = cb_readl(socket, CB_SOCKET_CONTROL);
+
+ switch (control & CB_SC_VCC_MASK) {
+ case CB_SC_VCC_5V: state->Vcc = 50; break;
+ case CB_SC_VCC_3V: state->Vcc = 33; break;
+ default: state->Vcc = 0;
+ }
+
+ switch (control & CB_SC_VPP_MASK) {
+ case CB_SC_VPP_12V: state->Vpp = 120; break;
+ case CB_SC_VPP_5V: state->Vpp = 50; break;
+ case CB_SC_VPP_3V: state->Vpp = 33; break;
+ default: state->Vpp = 0;
+ }
}
}
@@ -211,8 +281,7 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
control = cb_readl(socket, CB_SOCKET_CONTROL);
- state->Vcc = yenta_Vcc_power(control);
- state->Vpp = yenta_Vpp_power(control);
+ yenta_get_power(socket, state);
state->io_irq = socket->io_irq;
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
@@ -246,19 +315,54 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
{
- u32 reg = 0; /* CB_SC_STPCLK? */
- switch (state->Vcc) {
- case 33: reg = CB_SC_VCC_3V; break;
- case 50: reg = CB_SC_VCC_5V; break;
- default: reg = 0; break;
- }
- switch (state->Vpp) {
- case 33: reg |= CB_SC_VPP_3V; break;
- case 50: reg |= CB_SC_VPP_5V; break;
- case 120: reg |= CB_SC_VPP_12V; break;
+ /* some birdges require to use the ExCA registers to power 16bit cards */
+ if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+ (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+ u8 reg, old;
+ reg = old = exca_readb(socket, I365_POWER);
+ reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK);
+
+ /* i82365SL-DF style */
+ if (socket->flags & YENTA_16BIT_POWER_DF) {
+ switch (state->Vcc) {
+ case 33: reg |= I365_VCC_3V; break;
+ case 50: reg |= I365_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 33:
+ case 50: reg |= I365_VPP1_5V; break;
+ case 120: reg |= I365_VPP1_12V; break;
+ }
+ } else {
+ /* i82365SL-B style */
+ switch (state->Vcc) {
+ case 50: reg |= I365_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
+ case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
+ }
+ }
+
+ if (reg != old)
+ exca_writeb(socket, I365_POWER, reg);
+ } else {
+ u32 reg = 0; /* CB_SC_STPCLK? */
+ switch (state->Vcc) {
+ case 33: reg = CB_SC_VCC_3V; break;
+ case 50: reg = CB_SC_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 33: reg |= CB_SC_VPP_3V; break;
+ case 50: reg |= CB_SC_VPP_5V; break;
+ case 120: reg |= CB_SC_VPP_12V; break;
+ }
+ if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
+ cb_writel(socket, CB_SOCKET_CONTROL, reg);
}
- if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
- cb_writel(socket, CB_SOCKET_CONTROL, reg);
}
static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
@@ -489,12 +593,6 @@ static void yenta_interrogate(struct yenta_socket *socket)
static int yenta_sock_init(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
- u16 bridge;
-
- bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
- if (!socket->cb_irq)
- bridge |= CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge);
exca_writeb(socket, I365_GBLCTL, 0x00);
exca_writeb(socket, I365_GENCTL, 0x00);
@@ -603,35 +701,32 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
return 0;
}
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
+static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
{
- struct pci_bus *bus;
struct resource *root, *res;
- u32 start, end;
+ struct pci_bus_region region;
unsigned mask;
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
/* Already allocated? */
if (res->parent)
- return;
+ return 0;
/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
mask = ~0xfff;
if (type & IORESOURCE_IO)
mask = ~3;
- bus = socket->dev->subordinate;
- res->name = bus->name;
+ res->name = socket->dev->subordinate->name;
res->flags = type;
- start = config_readl(socket, addr_start) & mask;
- end = config_readl(socket, addr_end) | ~mask;
- if (start && end > start && !override_bios) {
- res->start = start;
- res->end = end;
+ region.start = config_readl(socket, addr_start) & mask;
+ region.end = config_readl(socket, addr_end) | ~mask;
+ if (region.start && region.end > region.start && !override_bios) {
+ pcibios_bus_to_resource(socket->dev, res, &region);
root = pci_find_parent_resource(socket->dev, res);
if (root && (request_resource(root, res) == 0))
- return;
+ return 0;
printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
pci_name(socket->dev), nr);
}
@@ -639,35 +734,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
if (type & IORESOURCE_IO) {
if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
+ return 1;
} else {
if (type & IORESOURCE_PREFETCH) {
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
/* Approximating prefetchable by non-prefetchable */
res->flags = IORESOURCE_MEM;
}
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
}
printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
pci_name(socket->dev), type);
res->start = res->end = res->flags = 0;
+ return 0;
}
/*
@@ -675,14 +762,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
*/
static void yenta_allocate_resources(struct yenta_socket *socket)
{
- yenta_allocate_res(socket, 0, IORESOURCE_IO,
+ int program = 0;
+ program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
- yenta_allocate_res(socket, 1, IORESOURCE_IO,
+ program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
- yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
+ program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
- yenta_allocate_res(socket, 3, IORESOURCE_MEM,
+ program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
+ if (program)
+ pci_setup_cardbus(socket->dev->subordinate);
}
@@ -697,7 +787,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
if (res->start != 0 && res->end != 0)
release_resource(res);
- res->start = res->end = 0;
+ res->start = res->end = res->flags = 0;
}
}
@@ -709,6 +799,9 @@ static void yenta_close(struct pci_dev *dev)
{
struct yenta_socket *sock = pci_get_drvdata(dev);
+ /* Remove the register attributes */
+ device_remove_file(&dev->dev, &dev_attr_yenta_registers);
+
/* we don't want a dying socket registered */
pcmcia_unregister_socket(&sock->socket);
@@ -754,8 +847,10 @@ enum {
CARDBUS_TYPE_TI12XX,
CARDBUS_TYPE_TI1250,
CARDBUS_TYPE_RICOH,
+ CARDBUS_TYPE_TOPIC95,
CARDBUS_TYPE_TOPIC97,
CARDBUS_TYPE_O2MICRO,
+ CARDBUS_TYPE_ENE,
};
/*
@@ -792,6 +887,9 @@ static struct cardbus_type cardbus_type[] = {
.save_state = ricoh_save_state,
.restore_state = ricoh_restore_state,
},
+ [CARDBUS_TYPE_TOPIC95] = {
+ .override = topic95_override,
+ },
[CARDBUS_TYPE_TOPIC97] = {
.override = topic97_override,
},
@@ -799,6 +897,12 @@ static struct cardbus_type cardbus_type[] = {
.override = o2micro_override,
.restore_state = o2micro_restore_state,
},
+ [CARDBUS_TYPE_ENE] = {
+ .override = ene_override,
+ .save_state = ti_save_state,
+ .restore_state = ti_restore_state,
+ .sock_init = ti_init,
+ },
};
@@ -817,16 +921,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
{
int i;
unsigned long val;
- u16 bridge_ctrl;
u32 mask;
- /* Set up ISA irq routing to probe the ISA irqs.. */
- bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
- bridge_ctrl |= CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
- }
-
/*
* Probe for usable interrupts using the force
* register to generate bogus card status events.
@@ -848,9 +944,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
mask = probe_irq_mask(val) & 0xffff;
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
return mask;
}
@@ -878,18 +971,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re
/* probes the PCI interrupt, use only on override functions */
static int yenta_probe_cb_irq(struct yenta_socket *socket)
{
- u16 bridge_ctrl;
-
if (!socket->cb_irq)
return -1;
socket->probe_status = 0;
- /* disable ISA interrupts */
- bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) {
printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
return -1;
@@ -900,7 +986,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
-
+
msleep(100);
/* disable interrupts */
@@ -938,11 +1024,12 @@ static void yenta_config_init(struct yenta_socket *socket)
{
u16 bridge;
struct pci_dev *dev = socket->dev;
+ struct pci_bus_region region;
- pci_set_power_state(socket->dev, 0);
+ pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
config_writel(socket, CB_LEGACY_MODE_BASE, 0);
- config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+ config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
config_writew(socket, PCI_COMMAND,
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
@@ -965,8 +1052,8 @@ static void yenta_config_init(struct yenta_socket *socket)
* - PCI interrupts enabled if a PCI interrupt exists..
*/
bridge = config_readw(socket, CB_BRIDGE_CONTROL);
- bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
- bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR;
+ bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+ bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
config_writew(socket, CB_BRIDGE_CONTROL, bridge);
}
@@ -979,7 +1066,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
{
struct yenta_socket *socket;
int ret;
-
+
+ /*
+ * If we failed to assign proper bus numbers for this cardbus
+ * controller during PCI probe, its subordinate pci_bus is NULL.
+ * Bail out if so.
+ */
+ if (!dev->subordinate) {
+ printk(KERN_ERR "Yenta: no bus associated with %s! "
+ "(try 'pci=assign-busses')\n", pci_name(dev));
+ return -ENODEV;
+ }
+
socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket)
return -ENOMEM;
@@ -1077,8 +1175,11 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* Register it with the pcmcia layer.. */
ret = pcmcia_register_socket(&socket->socket);
- if (ret == 0)
+ if (ret == 0) {
+ /* Add the yenta register attributes */
+ device_create_file(&dev->dev, &dev_attr_yenta_registers);
goto out;
+ }
unmap:
iounmap(socket->base);
@@ -1188,10 +1289,22 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
+
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
@@ -1199,6 +1312,7 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
+ CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h
index 4e637eef2076..4e75e9e258cd 100644
--- a/drivers/pcmcia/yenta_socket.h
+++ b/drivers/pcmcia/yenta_socket.h
@@ -95,6 +95,12 @@
*/
#define CB_MEM_PAGE(map) (0x40 + (map))
+
+/* control how 16bit cards are powered */
+#define YENTA_16BIT_POWER_EXCA 0x00000001
+#define YENTA_16BIT_POWER_DF 0x00000002
+
+
struct yenta_socket;
struct cardbus_type {
@@ -113,6 +119,8 @@ struct yenta_socket {
struct pcmcia_socket socket;
struct cardbus_type *type;
+ u32 flags;
+
/* for PCI interrupt probing */
unsigned int probe_status;
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 6776308a1fe5..c5143201419a 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -6,7 +6,7 @@ menu "Plug and Play support"
config PNP
bool "Plug and Play support"
- depends on ISA || ACPI_BUS
+ depends on ISA || ACPI
---help---
Plug and Play (PnP) is a standard for peripherals which allows those
peripherals to be configured by software, e.g. assign IRQ's or other
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index add12f7c489a..e95ed67d4f05 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -8,13 +8,6 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
@@ -312,6 +305,8 @@ found:
if (drv->link.driver.probe) {
if (drv->link.driver.probe(&dev->dev)) {
dev->dev.driver = NULL;
+ dev->card_link = NULL;
+ up_write(&dev->dev.bus->subsys.rwsem);
return NULL;
}
}
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 1d037c2a82ac..33da25f3213f 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -11,13 +11,6 @@
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 82c5edd5b9ee..beedd86800f4 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -142,17 +142,6 @@ static void isapnp_write_word(unsigned char idx, unsigned short val)
isapnp_write_byte(idx+1, val);
}
-static void *isapnp_alloc(long size)
-{
- void *result;
-
- result = kmalloc(size, GFP_KERNEL);
- if (!result)
- return NULL;
- memset(result, 0, size);
- return result;
-}
-
static void isapnp_key(void)
{
unsigned char code = 0x6a, msb;
@@ -406,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne
struct pnp_id * id;
if (!dev)
return;
- id = isapnp_alloc(sizeof(struct pnp_id));
+ id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -430,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
struct pnp_dev *dev;
isapnp_peek(tmp, size);
- dev = isapnp_alloc(sizeof(struct pnp_dev));
+ dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->number = number;
@@ -461,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
unsigned long bits;
isapnp_peek(tmp, size);
- irq = isapnp_alloc(sizeof(struct pnp_irq));
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (tmp[1] << 8) | tmp[0];
@@ -485,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
struct pnp_dma *dma;
isapnp_peek(tmp, size);
- dma = isapnp_alloc(sizeof(struct pnp_dma));
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = tmp[0];
@@ -505,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = isapnp_alloc(sizeof(struct pnp_port));
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (tmp[2] << 8) | tmp[1];
@@ -528,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = isapnp_alloc(sizeof(struct pnp_port));
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (tmp[1] << 8) | tmp[0];
@@ -550,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
@@ -573,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -595,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = isapnp_alloc(sizeof(struct pnp_mem));
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -838,7 +827,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
{
- struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
+ struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -874,7 +863,7 @@ static int __init isapnp_build_device_list(void)
header[4], header[5], header[6], header[7], header[8]);
printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
#endif
- if ((card = isapnp_alloc(sizeof(struct pnp_card))) == NULL)
+ if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
continue;
card->number = csn;
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 6c510c19ad7d..cbb2749db178 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -11,14 +11,9 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
+#include <linux/slab.h>
+#include <linux/bitmap.h>
#include "base.h"
DECLARE_MUTEX(pnp_res_mutex);
diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig
index 0782cdc5009f..b1854171b963 100644
--- a/drivers/pnp/pnpacpi/Kconfig
+++ b/drivers/pnp/pnpacpi/Kconfig
@@ -3,7 +3,7 @@
#
config PNPACPI
bool "Plug and Play ACPI support (EXPERIMENTAL)"
- depends on PNP && ACPI_BUS && EXPERIMENTAL
+ depends on PNP && ACPI && EXPERIMENTAL
default y
---help---
Linux uses the PNPACPI to autodetect built-in
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 8655dd2e5b83..1a8915e74160 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/config.h>
#include <linux/acpi.h>
#include <linux/pnp.h>
#include <acpi/acpi_bus.h>
@@ -41,14 +42,6 @@ static inline int is_exclusive_device(struct acpi_device *dev)
return (!acpi_match_ids(dev, excluded_id_list));
}
-void *pnpacpi_kmalloc(size_t size, int f)
-{
- void *p = kmalloc(size, f);
- if (p)
- memset(p, 0, size);
- return p;
-}
-
/*
* Compatible Device IDs
*/
@@ -143,7 +136,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
return 0;
pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
- dev = pnpacpi_kmalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev) {
pnp_err("Out of memory");
return -ENOMEM;
@@ -173,7 +166,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
dev->number = num;
/* set the initial values for the PnP device */
- dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
goto err;
pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
@@ -205,8 +198,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
for (i = 0; i < cid_list->count; i++) {
if (!ispnpidacpi(cid_list->id[i].value))
continue;
- dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id),
- GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
continue;
diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h
index 76f907e09ee6..f28e2ed66fa3 100644
--- a/drivers/pnp/pnpacpi/pnpacpi.h
+++ b/drivers/pnp/pnpacpi/pnpacpi.h
@@ -5,7 +5,6 @@
#include <linux/acpi.h>
#include <linux/pnp.h>
-void *pnpacpi_kmalloc(size_t size, int f);
acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*);
acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*);
int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 75575f6c349c..416d30debe6c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -73,25 +73,35 @@ static void decode_irq_flags(int flag, int *edge_level, int *active_high_low)
}
static void
-pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
+ int edge_level, int active_high_low)
{
int i = 0;
+ int irq;
+
+ if (!valid_IRQ(gsi))
+ return;
+
while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
i < PNP_MAX_IRQ)
i++;
- if (i < PNP_MAX_IRQ) {
- res->irq_resource[i].flags = IORESOURCE_IRQ; //Also clears _UNSET flag
- if (irq == -1) {
- res->irq_resource[i].flags |= IORESOURCE_DISABLED;
- return;
- }
- res->irq_resource[i].start =(unsigned long) irq;
- res->irq_resource[i].end = (unsigned long) irq;
+ if (i >= PNP_MAX_IRQ)
+ return;
+
+ res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+ irq = acpi_register_gsi(gsi, edge_level, active_high_low);
+ if (irq < 0) {
+ res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
}
+
+ res->irq_resource[i].start = irq;
+ res->irq_resource[i].end = irq;
+ pcibios_penalize_isa_irq(irq, 1);
}
static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
{
int i = 0;
while (i < PNP_MAX_DMA &&
@@ -103,14 +113,14 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
res->dma_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->dma_resource[i].start =(unsigned long) dma;
- res->dma_resource[i].end = (unsigned long) dma;
+ res->dma_resource[i].start = dma;
+ res->dma_resource[i].end = dma;
}
}
static void
pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
- int io, int len)
+ u32 io, u32 len)
{
int i = 0;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -122,14 +132,14 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
res->port_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->port_resource[i].start = (unsigned long) io;
- res->port_resource[i].end = (unsigned long)(io + len - 1);
+ res->port_resource[i].start = io;
+ res->port_resource[i].end = io + len - 1;
}
}
static void
pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
- int mem, int len)
+ u64 mem, u64 len)
{
int i = 0;
while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
@@ -141,8 +151,8 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
res->mem_resource[i].flags |= IORESOURCE_DISABLED;
return;
}
- res->mem_resource[i].start = (unsigned long) mem;
- res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+ res->mem_resource[i].start = mem;
+ res->mem_resource[i].end = mem + len - 1;
}
}
@@ -151,27 +161,28 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data)
{
struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
+ int i;
switch (res->id) {
case ACPI_RSTYPE_IRQ:
- if ((res->data.irq.number_of_interrupts > 0) &&
- valid_IRQ(res->data.irq.interrupts[0])) {
- pnpacpi_parse_allocated_irqresource(res_table,
- acpi_register_gsi(res->data.irq.interrupts[0],
- res->data.irq.edge_level,
- res->data.irq.active_high_low));
- pcibios_penalize_isa_irq(res->data.irq.interrupts[0], 1);
+ /*
+ * Per spec, only one interrupt per descriptor is allowed in
+ * _CRS, but some firmware violates this, so parse them all.
+ */
+ for (i = 0; i < res->data.irq.number_of_interrupts; i++) {
+ pnpacpi_parse_allocated_irqresource(res_table,
+ res->data.irq.interrupts[i],
+ res->data.irq.edge_level,
+ res->data.irq.active_high_low);
}
break;
case ACPI_RSTYPE_EXT_IRQ:
- if ((res->data.extended_irq.number_of_interrupts > 0) &&
- valid_IRQ(res->data.extended_irq.interrupts[0])) {
- pnpacpi_parse_allocated_irqresource(res_table,
- acpi_register_gsi(res->data.extended_irq.interrupts[0],
- res->data.extended_irq.edge_level,
- res->data.extended_irq.active_high_low));
- pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0], 1);
+ for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) {
+ pnpacpi_parse_allocated_irqresource(res_table,
+ res->data.extended_irq.interrupts[i],
+ res->data.extended_irq.edge_level,
+ res->data.extended_irq.active_high_low);
}
break;
case ACPI_RSTYPE_DMA:
@@ -244,7 +255,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
if (p->number_of_channels == 0)
return;
- dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
@@ -300,7 +311,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option,
if (p->number_of_interrupts == 0)
return;
- irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -321,7 +332,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
if (p->number_of_interrupts == 0)
return;
- irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -342,7 +353,7 @@ pnpacpi_parse_port_option(struct pnp_option *option,
if (io->range_length == 0)
return;
- port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = io->min_base_address;
@@ -363,7 +374,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
if (io->range_length == 0)
return;
- port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = io->base_address;
@@ -382,7 +393,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->min_base_address;
@@ -405,7 +416,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->min_base_address;
@@ -428,7 +439,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
if (p->range_length == 0)
return;
- mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->range_base_address;
@@ -612,7 +623,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
if (!res_cnt)
return -EINVAL;
buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
- buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL);
+ buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
if (!buffer->pointer)
return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 778a324028f4..f49674f07949 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -86,16 +86,6 @@ int pnp_bios_present(void)
struct pnp_dev_node_info node_info;
-void *pnpbios_kmalloc(size_t size, int f)
-{
- void *p = kmalloc( size, f );
- if ( p == NULL )
- printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
- else
- memset(p, 0, size);
- return p;
-}
-
/*
*
* DOCKING FUNCTIONS
@@ -121,10 +111,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
if (!current->fs->root) {
return -EAGAIN;
}
- if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+ if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
return -ENOMEM;
}
- if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
+ if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
kfree (envp);
return -ENOMEM;
}
@@ -231,7 +221,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table
if(!pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -254,7 +244,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -305,7 +295,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev)
if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
return -EPERM;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
@@ -347,7 +337,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
}
/* set the initial values for the PnP device */
- dev_id = pnpbios_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return -1;
pnpid32_to_pnpid(node->eisa_id,id);
@@ -385,7 +375,7 @@ static void __init build_devlist(void)
struct pnp_bios_node *node;
struct pnp_dev *dev;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return;
@@ -402,7 +392,7 @@ static void __init build_devlist(void)
break;
}
nodes_got++;
- dev = pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL);
+ dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
if (!dev)
break;
if(insert_device(dev,node)<0)
diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h
index 01896e705ed4..d8cb2fd1f127 100644
--- a/drivers/pnp/pnpbios/pnpbios.h
+++ b/drivers/pnp/pnpbios/pnpbios.h
@@ -26,7 +26,6 @@ union pnp_bios_install_struct {
extern int pnp_bios_present(void);
extern int pnpbios_dont_use_current_config;
-extern void *pnpbios_kmalloc(size_t size, int f);
extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 6bb8e1973fd4..5a3dfc97f5e9 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
return -EFBIG;
}
- tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
+ tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
if (!tmpbuf) return -ENOMEM;
if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
@@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos,
if (pos >= 0xff)
return 0;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
for (nodenum=pos; nodenum<0xff; ) {
@@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos,
u8 nodenum = (long)data;
int len;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
kfree(node);
@@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf,
u8 nodenum = (long)data;
int ret = count;
- node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+ node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index e305bb132c24..5e38cd7335f7 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -7,6 +7,8 @@
#include <linux/ctype.h>
#include <linux/pnp.h>
#include <linux/pnpbios.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
@@ -247,7 +249,7 @@ static void
pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((p[5] << 8) | p[4]) << 8;
@@ -263,7 +265,7 @@ static void
pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -279,7 +281,7 @@ static void
pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -296,7 +298,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option)
struct pnp_irq * irq;
unsigned long bits;
- irq = pnpbios_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (p[2] << 8) | p[1];
@@ -313,7 +315,7 @@ static void
pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_dma * dma;
- dma = pnpbios_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = p[1];
@@ -326,7 +328,7 @@ static void
pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (p[3] << 8) | p[2];
@@ -342,7 +344,7 @@ static void
pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+ port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (p[2] << 8) | p[1];
@@ -530,7 +532,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de
case SMALL_TAG_COMPATDEVID: /* compatible ID */
if (len != 4)
goto len_err;
- dev_id = pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL);
+ dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
memset(dev_id, 0, sizeof(struct pnp_id));
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 596a02d7e03d..8936b0cb2ec3 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -16,13 +16,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/slab.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index b952aec49189..61fe998944bd 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -8,13 +8,6 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ctype.h>
-
-#ifdef CONFIG_PNP_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/pnp.h>
#include "base.h"
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index dc1c89dbdb8f..6e7d7b06421d 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -49,7 +49,7 @@ config DASD_FBA
config DASD_DIAG
tristate "Support for DIAG access to Disks"
- depends on DASD && ARCH_S390X = 'n'
+ depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
help
Select this option if you want to use Diagnose250 command to access
Disks under VM. If you are not running under VM or unsure what it is,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d5f53980749b..8fc891a9d47f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.165 $
+ * $Revision: 1.167 $
*/
#include <linux/config.h>
@@ -1131,17 +1131,13 @@ __dasd_process_blk_queue(struct dasd_device * device)
request_queue_t *queue;
struct request *req;
struct dasd_ccw_req *cqr;
- int nr_queued, feature_ro;
+ int nr_queued;
queue = device->request_queue;
/* No queue ? Then there is nothing to do. */
if (queue == NULL)
return;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0) /* no devmap */
- return;
-
/*
* We requeue request from the block device queue to the ccw
* queue only in two states. In state DASD_STATE_READY the
@@ -1162,7 +1158,8 @@ __dasd_process_blk_queue(struct dasd_device * device)
nr_queued < DASD_CHANQ_MAX_SIZE) {
req = elv_next_request(queue);
- if (feature_ro && rq_data_dir(req) == WRITE) {
+ if (device->features & DASD_FEATURE_READONLY &&
+ rq_data_dir(req) == WRITE) {
DBF_DEV_EVENT(DBF_ERR, device,
"Rejecting write request %p",
req);
@@ -1814,17 +1811,13 @@ dasd_generic_set_online (struct ccw_device *cdev,
{
struct dasd_device *device;
- int feature_diag, rc;
+ int rc;
device = dasd_create_device(cdev);
if (IS_ERR(device))
return PTR_ERR(device);
- feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
- if (feature_diag < 0)
- return feature_diag;
-
- if (feature_diag) {
+ if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
"dasd_generic couldn't online device %s "
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d948566bb24a..bda896d9d788 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,7 @@
* functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context.
*
- * $Revision: 1.40 $
+ * $Revision: 1.43 $
*/
#include <linux/config.h>
@@ -513,6 +513,7 @@ dasd_create_device(struct ccw_device *cdev)
if (!devmap->device) {
devmap->device = device;
device->devindex = devmap->devindex;
+ device->features = devmap->features;
get_device(&cdev->dev);
device->cdev = cdev;
rc = 0;
@@ -643,6 +644,8 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
+ if (devmap->device)
+ devmap->device->features = devmap->features;
if (devmap->device && devmap->device->gdp)
set_disk_ro(devmap->device->gdp, ro_flag);
spin_unlock(&dasd_devmap_lock);
@@ -758,7 +761,8 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
devmap->features |= feature;
else
devmap->features &= ~feature;
-
+ if (devmap->device)
+ devmap->device->features = devmap->features;
spin_unlock(&dasd_devmap_lock);
return 0;
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 127699830fa1..7478423b53bb 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,17 +6,18 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.42 $
+ * $Revision: 1.49 $
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/hdreg.h> /* HDIO_GETGEO */
+#include <linux/hdreg.h>
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <asm/dasd.h>
#include <asm/debug.h>
@@ -28,58 +29,89 @@
#include "dasd_int.h"
#include "dasd_diag.h"
-#ifdef PRINTK_HEADER
-#undef PRINTK_HEADER
-#endif /* PRINTK_HEADER */
#define PRINTK_HEADER "dasd(diag):"
MODULE_LICENSE("GPL");
+/* The maximum number of blocks per request (max_blocks) is dependent on the
+ * amount of storage that is available in the static I/O buffer for each
+ * device. Currently each device gets 2 pages. We want to fit two requests
+ * into the available memory so that we can immediately start the next if one
+ * finishes. */
+#define DIAG_MAX_BLOCKS (((2 * PAGE_SIZE - sizeof(struct dasd_ccw_req) - \
+ sizeof(struct dasd_diag_req)) / \
+ sizeof(struct dasd_diag_bio)) / 2)
+#define DIAG_MAX_RETRIES 32
+#define DIAG_TIMEOUT 50 * HZ
+
struct dasd_discipline dasd_diag_discipline;
struct dasd_diag_private {
struct dasd_diag_characteristics rdc_data;
struct dasd_diag_rw_io iob;
struct dasd_diag_init_io iib;
- unsigned int pt_block;
+ blocknum_t pt_block;
};
struct dasd_diag_req {
- int block_count;
+ unsigned int block_count;
struct dasd_diag_bio bio[0];
};
+static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
+
+/* Perform DIAG250 call with block I/O parameter list iob (input and output)
+ * and function code cmd.
+ * In case of an exception return 3. Otherwise return result of bitwise OR of
+ * resulting condition code and DIAG return code. */
static __inline__ int
dia250(void *iob, int cmd)
{
+ typedef struct {
+ char _[max(sizeof (struct dasd_diag_init_io),
+ sizeof (struct dasd_diag_rw_io))];
+ } addr_type;
int rc;
- __asm__ __volatile__(" lhi %0,3\n"
- " lr 0,%2\n"
- " diag 0,%1,0x250\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- " or %0,1\n"
- "1:\n"
-#ifndef CONFIG_ARCH_S390X
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous\n"
+ __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ " lghi %0,3\n"
+ " lgr 0,%3\n"
+ " diag 0,%2,0x250\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ " or %0,1\n"
+ "1:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous\n"
#else
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous\n"
+ " lhi %0,3\n"
+ " lr 0,%3\n"
+ " diag 0,%2,0x250\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ " or %0,1\n"
+ "1:\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous\n"
#endif
- : "=&d" (rc)
- : "d" (cmd), "d" ((void *) __pa(iob))
- : "0", "1", "cc");
+ : "=&d" (rc), "=m" (*(addr_type *) iob)
+ : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
+ : "0", "1", "cc");
return rc;
}
+/* Initialize block I/O to DIAG device using the specified blocksize and
+ * block offset. On success, return zero and set end_block to contain the
+ * number of blocks on the device minus the specified offset. Return non-zero
+ * otherwise. */
static __inline__ int
-mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size)
+mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
+ blocknum_t offset, blocknum_t *end_block)
{
struct dasd_diag_private *private;
struct dasd_diag_init_io *iib;
@@ -92,14 +124,18 @@ mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size)
iib->dev_nr = _ccw_device_get_device_number(device->cdev);
iib->block_size = blocksize;
iib->offset = offset;
- iib->start_block = 0;
- iib->end_block = size;
+ iib->flaga = DASD_DIAG_FLAGA_DEFAULT;
rc = dia250(iib, INIT_BIO);
- return rc & 3;
+ if ((rc & 3) == 0 && end_block)
+ *end_block = iib->end_block;
+
+ return rc;
}
+/* Remove block I/O environment for device. Return zero on success, non-zero
+ * otherwise. */
static __inline__ int
mdsk_term_io(struct dasd_device * device)
{
@@ -112,9 +148,25 @@ mdsk_term_io(struct dasd_device * device)
memset(iib, 0, sizeof (struct dasd_diag_init_io));
iib->dev_nr = _ccw_device_get_device_number(device->cdev);
rc = dia250(iib, TERM_BIO);
- return rc & 3;
+ return rc;
+}
+
+/* Error recovery for failed DIAG requests - try to reestablish the DIAG
+ * environment. */
+static void
+dasd_diag_erp(struct dasd_device *device)
+{
+ int rc;
+
+ mdsk_term_io(device);
+ rc = mdsk_init_io(device, device->bp_block, 0, NULL);
+ if (rc)
+ DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, "
+ "rc=%d", rc);
}
+/* Start a given request at the device. Return zero on success, non-zero
+ * otherwise. */
static int
dasd_start_diag(struct dasd_ccw_req * cqr)
{
@@ -124,32 +176,66 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
int rc;
device = cqr->device;
+ if (cqr->retries < 0) {
+ DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p "
+ "- no retry left)", cqr);
+ cqr->status = DASD_CQR_FAILED;
+ return -EIO;
+ }
private = (struct dasd_diag_private *) device->private;
dreq = (struct dasd_diag_req *) cqr->data;
private->iob.dev_nr = _ccw_device_get_device_number(device->cdev);
private->iob.key = 0;
- private->iob.flags = 2; /* do asynchronous io */
+ private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
private->iob.block_count = dreq->block_count;
- private->iob.interrupt_params = (u32)(addr_t) cqr;
+ private->iob.interrupt_params = (addr_t) cqr;
private->iob.bio_list = __pa(dreq->bio);
+ private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
cqr->startclk = get_clock();
+ cqr->starttime = jiffies;
+ cqr->retries--;
rc = dia250(&private->iob, RW_BIO);
- if (rc > 8) {
- DEV_MESSAGE(KERN_WARNING, device, "dia250 returned CC %d", rc);
- cqr->status = DASD_CQR_ERROR;
- } else if (rc == 0) {
+ switch (rc) {
+ case 0: /* Synchronous I/O finished successfully */
+ cqr->stopclk = get_clock();
cqr->status = DASD_CQR_DONE;
- dasd_schedule_bh(device);
- } else {
+ /* Indicate to calling function that only a dasd_schedule_bh()
+ and no timer is needed */
+ rc = -EACCES;
+ break;
+ case 8: /* Asynchronous I/O was started */
cqr->status = DASD_CQR_IN_IO;
rc = 0;
+ break;
+ default: /* Error condition */
+ cqr->status = DASD_CQR_QUEUED;
+ DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc);
+ dasd_diag_erp(device);
+ rc = -EIO;
+ break;
}
return rc;
}
+/* Terminate given request at the device. */
+static int
+dasd_diag_term_IO(struct dasd_ccw_req * cqr)
+{
+ struct dasd_device *device;
+
+ device = cqr->device;
+ mdsk_term_io(device);
+ mdsk_init_io(device, device->bp_block, 0, NULL);
+ cqr->status = DASD_CQR_CLEAR;
+ cqr->stopclk = get_clock();
+ dasd_schedule_bh(device);
+ return 0;
+}
+
+/* Handle external interruption. */
static void
dasd_ext_handler(struct pt_regs *regs, __u16 code)
{
@@ -157,25 +243,27 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
struct dasd_device *device;
unsigned long long expires;
unsigned long flags;
- char status;
- int ip;
-
- /*
- * Get the external interruption subcode. VM stores
- * this in the 'cpu address' field associated with
- * the external interrupt. For diag 250 the subcode
- * needs to be 3.
- */
- if ((S390_lowcore.cpu_addr & 0xff00) != 0x0300)
- return;
- status = *((char *) &S390_lowcore.ext_params + 5);
- ip = S390_lowcore.ext_params;
+ u8 int_code, status;
+ addr_t ip;
+ int rc;
+ int_code = *((u8 *) DASD_DIAG_LC_INT_CODE);
+ status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
+ switch (int_code) {
+ case DASD_DIAG_CODE_31BIT:
+ ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT);
+ break;
+ case DASD_DIAG_CODE_64BIT:
+ ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT);
+ break;
+ default:
+ return;
+ }
if (!ip) { /* no intparm: unsolicited interrupt */
MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
return;
}
- cqr = (struct dasd_ccw_req *)(addr_t) ip;
+ cqr = (struct dasd_ccw_req *) ip;
device = (struct dasd_device *) cqr->device;
if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
DEV_MESSAGE(KERN_WARNING, device,
@@ -188,6 +276,15 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
/* get irq lock to modify request queue */
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+ /* Check for a pending clear operation */
+ if (cqr->status == DASD_CQR_CLEAR) {
+ cqr->status = DASD_CQR_QUEUED;
+ dasd_clear_timer(device);
+ dasd_schedule_bh(device);
+ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+ return;
+ }
+
cqr->stopclk = get_clock();
expires = 0;
@@ -198,16 +295,22 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
next = list_entry(device->ccw_queue.next,
struct dasd_ccw_req, list);
if (next->status == DASD_CQR_QUEUED) {
- if (dasd_start_diag(next) == 0)
+ rc = dasd_start_diag(next);
+ if (rc == 0)
expires = next->expires;
- else
+ else if (rc != -EACCES)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"Interrupt fastpath "
"failed!");
}
}
- } else
- cqr->status = DASD_CQR_FAILED;
+ } else {
+ cqr->status = DASD_CQR_QUEUED;
+ DEV_MESSAGE(KERN_WARNING, device, "interrupt status for "
+ "request %p was %d (%d retries left)", cqr, status,
+ cqr->retries);
+ dasd_diag_erp(device);
+ }
if (expires != 0)
dasd_set_timer(device, expires);
@@ -218,14 +321,17 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
}
+/* Check whether device can be controlled by DIAG discipline. Return zero on
+ * success, non-zero otherwise. */
static int
dasd_diag_check_device(struct dasd_device *device)
{
struct dasd_diag_private *private;
struct dasd_diag_characteristics *rdc_data;
struct dasd_diag_bio bio;
- long *label;
- int sb, bsize;
+ struct dasd_diag_cms_label *label;
+ blocknum_t end_block;
+ unsigned int sb, bsize;
int rc;
private = (struct dasd_diag_private *) device->private;
@@ -244,8 +350,11 @@ dasd_diag_check_device(struct dasd_device *device)
rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);
rc = diag210((struct diag210 *) rdc_data);
- if (rc)
+ if (rc) {
+ DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "
+ "information (rc=%d)", rc);
return -ENOTSUPP;
+ }
/* Figure out position of label block */
switch (private->rdc_data.vdev_class) {
@@ -256,6 +365,8 @@ dasd_diag_check_device(struct dasd_device *device)
private->pt_block = 2;
break;
default:
+ DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "
+ "(class=%d)", private->rdc_data.vdev_class);
return -ENOTSUPP;
}
@@ -269,15 +380,17 @@ dasd_diag_check_device(struct dasd_device *device)
mdsk_term_io(device);
/* figure out blocksize of device */
- label = (long *) get_zeroed_page(GFP_KERNEL);
+ label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
}
+ rc = 0;
+ end_block = 0;
/* try all sizes - needed for ECKD devices */
for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
- mdsk_init_io(device, bsize, 0, 64);
+ mdsk_init_io(device, bsize, 0, &end_block);
memset(&bio, 0, sizeof (struct dasd_diag_bio));
bio.type = MDSK_READ_REQ;
bio.block_number = private->pt_block + 1;
@@ -289,37 +402,45 @@ dasd_diag_check_device(struct dasd_device *device)
private->iob.block_count = 1;
private->iob.interrupt_params = 0;
private->iob.bio_list = __pa(&bio);
- if (dia250(&private->iob, RW_BIO) == 0)
+ private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
+ rc = dia250(&private->iob, RW_BIO);
+ if (rc == 0 || rc == 3)
break;
mdsk_term_io(device);
}
- if (bsize <= PAGE_SIZE && label[0] == 0xc3d4e2f1) {
- /* get formatted blocksize from label block */
- bsize = (int) label[3];
- device->blocks = label[7];
+ if (rc == 3) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
+ rc = -EOPNOTSUPP;
+ } else if (rc != 0) {
+ DEV_MESSAGE(KERN_WARNING, device, "device access failed "
+ "(rc=%d)", rc);
+ rc = -EIO;
+ } else {
+ if (memcmp(label->label_id, DASD_DIAG_CMS1,
+ sizeof(DASD_DIAG_CMS1)) == 0) {
+ /* get formatted blocksize from label block */
+ bsize = (unsigned int) label->block_size;
+ device->blocks = (unsigned long) label->block_count;
+ } else
+ device->blocks = end_block;
device->bp_block = bsize;
device->s2b_shift = 0; /* bits to shift 512 to get a block */
for (sb = 512; sb < bsize; sb = sb << 1)
device->s2b_shift++;
DEV_MESSAGE(KERN_INFO, device,
- "capacity (%dkB blks): %ldkB",
- (device->bp_block >> 10),
- (device->blocks << device->s2b_shift) >> 1);
+ "(%ld B/blk): %ldkB",
+ (unsigned long) device->bp_block,
+ (unsigned long) (device->blocks <<
+ device->s2b_shift) >> 1);
rc = 0;
- } else {
- if (bsize > PAGE_SIZE)
- DEV_MESSAGE(KERN_WARNING, device, "%s",
- "DIAG access failed");
- else
- DEV_MESSAGE(KERN_WARNING, device, "%s",
- "volume is not CMS formatted");
- rc = -EMEDIUMTYPE;
}
free_page((long) label);
return rc;
}
+/* Fill in virtual disk geometry for device. Return zero on success, non-zero
+ * otherwise. */
static int
dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo)
{
@@ -349,6 +470,8 @@ dasd_diag_erp_postaction(struct dasd_ccw_req * cqr)
return dasd_default_erp_postaction;
}
+/* Create DASD request from block device request. Return pointer to new
+ * request on success, ERR_PTR otherwise. */
static struct dasd_ccw_req *
dasd_diag_build_cp(struct dasd_device * device, struct request *req)
{
@@ -358,9 +481,9 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
struct bio *bio;
struct bio_vec *bv;
char *dst;
- int count, datasize;
+ unsigned int count, datasize;
sector_t recid, first_rec, last_rec;
- unsigned blksize, off;
+ unsigned int blksize, off;
unsigned char rw_cmd;
int i;
@@ -413,13 +536,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
}
}
}
+ cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
cqr->device = device;
- cqr->expires = 50 * HZ; /* 50 seconds */
+ cqr->expires = DIAG_TIMEOUT;
cqr->status = DASD_CQR_FILLED;
return cqr;
}
+/* Release DASD request. Return non-zero if request was successful, zero
+ * otherwise. */
static int
dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
{
@@ -430,6 +556,7 @@ dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
return status;
}
+/* Fill in IOCTL data for device. */
static int
dasd_diag_fill_info(struct dasd_device * device,
struct dasd_information2_t * info)
@@ -437,7 +564,7 @@ dasd_diag_fill_info(struct dasd_device * device,
struct dasd_diag_private *private;
private = (struct dasd_diag_private *) device->private;
- info->label_block = private->pt_block;
+ info->label_block = (unsigned int) private->pt_block;
info->FBA_layout = 1;
info->format = DASD_FORMAT_LDL;
info->characteristics_size = sizeof (struct dasd_diag_characteristics);
@@ -456,26 +583,15 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
"dump sense not available for DIAG data");
}
-/*
- * max_blocks is dependent on the amount of storage that is available
- * in the static io buffer for each device. Currently each device has
- * 8192 bytes (=2 pages). dasd diag is only relevant for 31 bit.
- * The struct dasd_ccw_req has 96 bytes, the struct dasd_diag_req has
- * 8 bytes and the struct dasd_diag_bio for each block has 16 bytes.
- * That makes:
- * (8192 - 96 - 8) / 16 = 505.5 blocks at maximum.
- * We want to fit two into the available memory so that we can immediately
- * start the next request if one finishes off. That makes 252.75 blocks
- * for one request. Give a little safety and the result is 240.
- */
struct dasd_discipline dasd_diag_discipline = {
.owner = THIS_MODULE,
.name = "DIAG",
.ebcname = "DIAG",
- .max_blocks = 240,
+ .max_blocks = DIAG_MAX_BLOCKS,
.check_device = dasd_diag_check_device,
.fill_geometry = dasd_diag_fill_geometry,
.start_IO = dasd_start_diag,
+ .term_IO = dasd_diag_term_IO,
.examine_error = dasd_diag_examine_error,
.erp_action = dasd_diag_erp_action,
.erp_postaction = dasd_diag_erp_postaction,
@@ -493,7 +609,7 @@ dasd_diag_init(void)
"Machine is not VM: %s "
"discipline not initializing",
dasd_diag_discipline.name);
- return -EINVAL;
+ return -ENODEV;
}
ASCEBC(dasd_diag_discipline.ebcname, 4);
@@ -506,13 +622,6 @@ dasd_diag_init(void)
static void __exit
dasd_diag_cleanup(void)
{
- if (!MACHINE_IS_VM) {
- MESSAGE_LOG(KERN_INFO,
- "Machine is not VM: %s "
- "discipline not cleaned",
- dasd_diag_discipline.name);
- return;
- }
unregister_external_interrupt(0x2603, dasd_ext_handler);
ctl_clear_bit(0, 9);
dasd_diag_discipline_pointer = NULL;
@@ -520,22 +629,3 @@ dasd_diag_cleanup(void)
module_init(dasd_diag_init);
module_exit(dasd_diag_cleanup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: 1
- * tab-width: 8
- * End:
- */
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index a0c38e303979..b26eb28df4bf 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
*/
#define MDSK_WRITE_REQ 0x01
@@ -19,6 +19,18 @@
#define DEV_CLASS_FBA 0x01
#define DEV_CLASS_ECKD 0x04
+#define DASD_DIAG_LC_INT_CODE 132
+#define DASD_DIAG_LC_INT_STATUS 133
+#define DASD_DIAG_LC_INT_PARM_31BIT 128
+#define DASD_DIAG_LC_INT_PARM_64BIT 4536
+#define DASD_DIAG_CODE_31BIT 0x03
+#define DASD_DIAG_CODE_64BIT 0x07
+
+#define DASD_DIAG_RWFLAG_ASYNC 0x02
+#define DASD_DIAG_RWFLAG_NOCACHE 0x01
+
+#define DASD_DIAG_FLAGA_FORMAT_64BIT 0x80
+
struct dasd_diag_characteristics {
u16 dev_nr;
u16 rdc_len;
@@ -32,35 +44,106 @@ struct dasd_diag_characteristics {
u8 rdev_features;
} __attribute__ ((packed, aligned(4)));
+struct dasd_diag_cms_label {
+ u8 label_id[4];
+ u8 vol_id[6];
+ u16 version_id;
+ u32 block_size;
+ u32 origin_ptr;
+ u32 usable_count;
+ u32 formatted_count;
+ u32 block_count;
+ u32 used_count;
+ u32 fst_size;
+ u32 fst_count;
+ u8 format_date[6];
+ u8 reserved1[2];
+ u32 disk_offset;
+ u32 map_block;
+ u32 hblk_disp;
+ u32 user_disp;
+ u8 reserved2[4];
+ u8 segment_name[8];
+} __attribute__ ((packed));
+
+#ifdef CONFIG_ARCH_S390X
+#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT
+
+typedef u64 blocknum_t;
+typedef s64 sblocknum_t;
+
+struct dasd_diag_bio {
+ u8 type;
+ u8 status;
+ u8 spare1[2];
+ u32 alet;
+ blocknum_t block_number;
+ u64 buffer;
+} __attribute__ ((packed, aligned(8)));
+
+struct dasd_diag_init_io {
+ u16 dev_nr;
+ u8 flaga;
+ u8 spare1[21];
+ u32 block_size;
+ u8 spare2[4];
+ blocknum_t offset;
+ sblocknum_t start_block;
+ blocknum_t end_block;
+ u8 spare3[8];
+} __attribute__ ((packed, aligned(8)));
+
+struct dasd_diag_rw_io {
+ u16 dev_nr;
+ u8 flaga;
+ u8 spare1[21];
+ u8 key;
+ u8 flags;
+ u8 spare2[2];
+ u32 block_count;
+ u32 alet;
+ u8 spare3[4];
+ u64 interrupt_params;
+ u64 bio_list;
+ u8 spare4[8];
+} __attribute__ ((packed, aligned(8)));
+#else /* CONFIG_ARCH_S390X */
+#define DASD_DIAG_FLAGA_DEFAULT 0x0
+
+typedef u32 blocknum_t;
+typedef s32 sblocknum_t;
+
struct dasd_diag_bio {
u8 type;
u8 status;
u16 spare1;
- u32 block_number;
+ blocknum_t block_number;
u32 alet;
u32 buffer;
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_init_io {
u16 dev_nr;
- u16 spare1[11];
+ u8 flaga;
+ u8 spare1[21];
u32 block_size;
- u32 offset;
- u32 start_block;
- u32 end_block;
- u32 spare2[6];
+ blocknum_t offset;
+ sblocknum_t start_block;
+ blocknum_t end_block;
+ u8 spare2[24];
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_rw_io {
u16 dev_nr;
- u16 spare1[11];
+ u8 flaga;
+ u8 spare1[21];
u8 key;
u8 flags;
- u16 spare2;
+ u8 spare2[2];
u32 block_count;
u32 alet;
u32 bio_list;
u32 interrupt_params;
- u32 spare3[5];
+ u8 spare3[20];
} __attribute__ ((packed, aligned(8)));
-
+#endif /* CONFIG_ARCH_S390X */
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 96c49349701f..a601c9a33541 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,7 @@
*
* gendisk related functions for the dasd driver.
*
- * $Revision: 1.50 $
+ * $Revision: 1.51 $
*/
#include <linux/config.h>
@@ -31,16 +31,12 @@ int
dasd_gendisk_alloc(struct dasd_device *device)
{
struct gendisk *gdp;
- int len, feature_ro;
+ int len;
/* Make sure the minor for this device exists. */
if (device->devindex >= DASD_PER_MAJOR)
return -EBUSY;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
-
gdp = alloc_disk(1 << DASD_PARTN_BITS);
if (!gdp)
return -ENOMEM;
@@ -75,7 +71,7 @@ dasd_gendisk_alloc(struct dasd_device *device)
sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
- if (feature_ro)
+ if (device->features & DASD_FEATURE_READONLY)
set_disk_ro(gdp, 1);
gdp->private_data = device;
gdp->queue = device->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a9f38b235981..9fab04f3056d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.64 $
+ * $Revision: 1.65 $
*/
#ifndef DASD_INT_H
@@ -286,6 +286,7 @@ struct dasd_device {
unsigned int bp_block; /* bytes per block */
unsigned int s2b_shift; /* log2 (bp_block/512) */
unsigned long flags; /* per device flags */
+ unsigned short features; /* copy of devmap-features (read-only!) */
/* Device discipline stuff. */
struct dasd_discipline *discipline;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 980c555aa538..789595b3fa09 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.45 $
+ * $Revision: 1.47 $
*
* i/o controls for the dasd driver.
*/
@@ -296,7 +296,6 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
{
struct dasd_device *device;
struct format_data_t fdata;
- int feature_ro;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -308,10 +307,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
if (device == NULL)
return -ENODEV;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
- if (feature_ro)
+ if (device->features & DASD_FEATURE_READONLY)
return -EROFS;
if (copy_from_user(&fdata, (void __user *) args,
sizeof (struct format_data_t)))
@@ -384,7 +380,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
struct dasd_device *device;
struct dasd_information2_t *dasd_info;
unsigned long flags;
- int rc, feature_ro;
+ int rc;
struct ccw_device *cdev;
device = bdev->bd_disk->private_data;
@@ -394,10 +390,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
if (!device->discipline->fill_info)
return -EINVAL;
- feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature_ro < 0)
- return feature_ro;
-
dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
if (dasd_info == NULL)
return -ENOMEM;
@@ -427,7 +419,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
(dasd_check_blocksize(device->bp_block)))
dasd_info->format = DASD_FORMAT_NONE;
- dasd_info->features |= feature_ro;
+ dasd_info->features |=
+ ((device->features & DASD_FEATURE_READONLY) != 0);
if (device->discipline)
memcpy(dasd_info->type, device->discipline->name, 4);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 43c34f8c5e68..fff9020d4886 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,7 @@
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.32 $
+ * $Revision: 1.33 $
*/
#include <linux/config.h>
@@ -55,7 +55,6 @@ dasd_devices_show(struct seq_file *m, void *v)
{
struct dasd_device *device;
char *substr;
- int feature;
device = dasd_device_from_devindex((unsigned long) v - 1);
if (IS_ERR(device))
@@ -79,10 +78,7 @@ dasd_devices_show(struct seq_file *m, void *v)
else
seq_printf(m, " is ????????");
/* Print devices features. */
- feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
- if (feature < 0)
- return 0;
- substr = feature ? "(ro)" : " ";
+ substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
seq_printf(m, "%4s: ", substr);
/* Print device status information. */
switch ((device != NULL) ? device->state : -1) {
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index fc7a213e591f..c570a9f6ce9c 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -213,6 +213,9 @@ con3270_update(struct con3270 *cp)
struct string *s, *n;
int rc;
+ if (cp->view.dev)
+ raw3270_activate_view(&cp->view);
+
wrq = xchg(&cp->write, 0);
if (!wrq) {
con3270_set_timer(cp, 1);
@@ -489,8 +492,6 @@ con3270_write(struct console *co, const char *str, unsigned int count)
unsigned char c;
cp = condev;
- if (cp->view.dev)
- raw3270_activate_view(&cp->view);
spin_lock_irqsave(&cp->view.lock, flags);
while (count-- > 0) {
c = *str++;
@@ -620,7 +621,7 @@ con3270_init(void)
(void (*)(unsigned long)) con3270_read_tasklet,
(unsigned long) condev->read);
- raw3270_add_view(&condev->view, &con3270_fn, 0);
+ raw3270_add_view(&condev->view, &con3270_fn, 1);
INIT_LIST_HEAD(&condev->freemem);
for (i = 0; i < CON3270_STRING_PAGES; i++) {
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 60afcdcf91c2..735a7fcdeff5 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -33,8 +33,11 @@ struct fs3270 {
int read_command; /* ccw command to use for reads. */
int write_command; /* ccw command to use for writes. */
int attention; /* Got attention. */
- struct raw3270_request *clear; /* single clear request. */
- wait_queue_head_t attn_wait; /* Attention wait queue. */
+ int active; /* Fullscreen view is active. */
+ struct raw3270_request *init; /* single init request. */
+ wait_queue_head_t wait; /* Init & attention wait queue. */
+ struct idal_buffer *rdbuf; /* full-screen-deactivate buffer */
+ size_t rdbuf_size; /* size of data returned by RDBUF */
};
static void
@@ -43,58 +46,172 @@ fs3270_wake_up(struct raw3270_request *rq, void *data)
wake_up((wait_queue_head_t *) data);
}
+static inline int
+fs3270_working(struct fs3270 *fp)
+{
+ /*
+ * The fullscreen view is in working order if the view
+ * has been activated AND the initial request is finished.
+ */
+ return fp->active && raw3270_request_final(fp->init);
+}
+
static int
fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq)
{
- wait_queue_head_t wq;
+ struct fs3270 *fp;
int rc;
- init_waitqueue_head(&wq);
+ fp = (struct fs3270 *) view;
rq->callback = fs3270_wake_up;
- rq->callback_data = &wq;
- rc = raw3270_start(view, rq);
- if (rc)
- return rc;
- /* Started sucessfully. Now wait for completion. */
- wait_event(wq, raw3270_request_final(rq));
- return rq->rc;
+ rq->callback_data = &fp->wait;
+
+ do {
+ if (!fs3270_working(fp)) {
+ /* Fullscreen view isn't ready yet. */
+ rc = wait_event_interruptible(fp->wait,
+ fs3270_working(fp));
+ if (rc != 0)
+ break;
+ }
+ rc = raw3270_start(view, rq);
+ if (rc == 0) {
+ /* Started sucessfully. Now wait for completion. */
+ wait_event(fp->wait, raw3270_request_final(rq));
+ }
+ } while (rc == -EACCES);
+ return rc;
}
+/*
+ * Switch to the fullscreen view.
+ */
static void
fs3270_reset_callback(struct raw3270_request *rq, void *data)
{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
raw3270_request_reset(rq);
+ wake_up(&fp->wait);
+}
+
+static void
+fs3270_restore_callback(struct raw3270_request *rq, void *data)
+{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
+ if (rq->rc != 0 || rq->rescnt != 0) {
+ if (fp->fs_pid)
+ kill_proc(fp->fs_pid, SIGHUP, 1);
+ }
+ fp->rdbuf_size = 0;
+ raw3270_request_reset(rq);
+ wake_up(&fp->wait);
}
-/*
- * Switch to the fullscreen view.
- */
static int
fs3270_activate(struct raw3270_view *view)
{
struct fs3270 *fp;
+ char *cp;
+ int rc;
fp = (struct fs3270 *) view;
- raw3270_request_set_cmd(fp->clear, TC_EWRITEA);
- fp->clear->callback = fs3270_reset_callback;
- return raw3270_start(view, fp->clear);
+
+ /* If an old init command is still running just return. */
+ if (!raw3270_request_final(fp->init))
+ return 0;
+
+ if (fp->rdbuf_size == 0) {
+ /* No saved buffer. Just clear the screen. */
+ raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+ fp->init->callback = fs3270_reset_callback;
+ } else {
+ /* Restore fullscreen buffer saved by fs3270_deactivate. */
+ raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+ raw3270_request_set_idal(fp->init, fp->rdbuf);
+ fp->init->ccw.count = fp->rdbuf_size;
+ cp = fp->rdbuf->data[0];
+ cp[0] = TW_KR;
+ cp[1] = TO_SBA;
+ cp[2] = cp[6];
+ cp[3] = cp[7];
+ cp[4] = TO_IC;
+ cp[5] = TO_SBA;
+ cp[6] = 0x40;
+ cp[7] = 0x40;
+ fp->init->rescnt = 0;
+ fp->init->callback = fs3270_restore_callback;
+ }
+ rc = fp->init->rc = raw3270_start_locked(view, fp->init);
+ if (rc)
+ fp->init->callback(fp->init, NULL);
+ else
+ fp->active = 1;
+ return rc;
}
/*
* Shutdown fullscreen view.
*/
static void
+fs3270_save_callback(struct raw3270_request *rq, void *data)
+{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
+
+ /* Correct idal buffer element 0 address. */
+ fp->rdbuf->data[0] -= 5;
+ fp->rdbuf->size += 5;
+
+ /*
+ * If the rdbuf command failed or the idal buffer is
+ * to small for the amount of data returned by the
+ * rdbuf command, then we have no choice but to send
+ * a SIGHUP to the application.
+ */
+ if (rq->rc != 0 || rq->rescnt == 0) {
+ if (fp->fs_pid)
+ kill_proc(fp->fs_pid, SIGHUP, 1);
+ fp->rdbuf_size = 0;
+ } else
+ fp->rdbuf_size = fp->rdbuf->size - rq->rescnt;
+ raw3270_request_reset(rq);
+ wake_up(&fp->wait);
+}
+
+static void
fs3270_deactivate(struct raw3270_view *view)
{
- // FIXME: is this a good idea? The user program using fullscreen 3270
- // will die just because a console message appeared. On the other
- // hand the fullscreen device is unoperational now.
struct fs3270 *fp;
fp = (struct fs3270 *) view;
- if (fp->fs_pid != 0)
- kill_proc(fp->fs_pid, SIGHUP, 1);
- fp->fs_pid = 0;
+ fp->active = 0;
+
+ /* If an old init command is still running just return. */
+ if (!raw3270_request_final(fp->init))
+ return;
+
+ /* Prepare read-buffer request. */
+ raw3270_request_set_cmd(fp->init, TC_RDBUF);
+ /*
+ * Hackish: skip first 5 bytes of the idal buffer to make
+ * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
+ * in the activation command.
+ */
+ fp->rdbuf->data[0] += 5;
+ fp->rdbuf->size -= 5;
+ raw3270_request_set_idal(fp->init, fp->rdbuf);
+ fp->init->rescnt = 0;
+ fp->init->callback = fs3270_save_callback;
+
+ /* Start I/O to read in the 3270 buffer. */
+ fp->init->rc = raw3270_start_locked(view, fp->init);
+ if (fp->init->rc)
+ fp->init->callback(fp->init, NULL);
}
static int
@@ -103,7 +220,7 @@ fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
/* Handle ATTN. Set indication and wake waiters for attention. */
if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
fp->attention = 1;
- wake_up(&fp->attn_wait);
+ wake_up(&fp->wait);
}
if (rq) {
@@ -125,7 +242,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
struct fs3270 *fp;
struct raw3270_request *rq;
struct idal_buffer *ib;
- int rc;
+ ssize_t rc;
if (count == 0 || count > 65535)
return -EINVAL;
@@ -133,7 +250,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
if (!fp)
return -ENODEV;
ib = idal_buffer_alloc(count, 0);
- if (!ib)
+ if (IS_ERR(ib))
return -ENOMEM;
rq = raw3270_request_alloc(0);
if (!IS_ERR(rq)) {
@@ -141,10 +258,19 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
fp->read_command = 6;
raw3270_request_set_cmd(rq, fp->read_command ? : 2);
raw3270_request_set_idal(rq, ib);
- wait_event(fp->attn_wait, fp->attention);
- rc = fs3270_do_io(&fp->view, rq);
- if (rc == 0 && idal_buffer_to_user(ib, data, count))
- rc = -EFAULT;
+ rc = wait_event_interruptible(fp->wait, fp->attention);
+ fp->attention = 0;
+ if (rc == 0) {
+ rc = fs3270_do_io(&fp->view, rq);
+ if (rc == 0) {
+ count -= rq->rescnt;
+ if (idal_buffer_to_user(ib, data, count) != 0)
+ rc = -EFAULT;
+ else
+ rc = count;
+
+ }
+ }
raw3270_request_free(rq);
} else
rc = PTR_ERR(rq);
@@ -162,13 +288,13 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
struct raw3270_request *rq;
struct idal_buffer *ib;
int write_command;
- int rc;
+ ssize_t rc;
fp = filp->private_data;
if (!fp)
return -ENODEV;
ib = idal_buffer_alloc(count, 0);
- if (!ib)
+ if (IS_ERR(ib))
return -ENOMEM;
rq = raw3270_request_alloc(0);
if (!IS_ERR(rq)) {
@@ -179,6 +305,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
raw3270_request_set_cmd(rq, write_command);
raw3270_request_set_idal(rq, ib);
rc = fs3270_do_io(&fp->view, rq);
+ if (rc == 0)
+ rc = count - rq->rescnt;
} else
rc = -EFAULT;
raw3270_request_free(rq);
@@ -232,7 +360,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
}
/*
- * Allocate tty3270 structure.
+ * Allocate fs3270 structure.
*/
static struct fs3270 *
fs3270_alloc_view(void)
@@ -243,8 +371,8 @@ fs3270_alloc_view(void)
if (!fp)
return ERR_PTR(-ENOMEM);
memset(fp, 0, sizeof(struct fs3270));
- fp->clear = raw3270_request_alloc(0);
- if (!IS_ERR(fp->clear)) {
+ fp->init = raw3270_request_alloc(0);
+ if (IS_ERR(fp->init)) {
kfree(fp);
return ERR_PTR(-ENOMEM);
}
@@ -252,12 +380,17 @@ fs3270_alloc_view(void)
}
/*
- * Free tty3270 structure.
+ * Free fs3270 structure.
*/
static void
fs3270_free_view(struct raw3270_view *view)
{
- raw3270_request_free(((struct fs3270 *) view)->clear);
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) view;
+ if (fp->rdbuf)
+ idal_buffer_free(fp->rdbuf);
+ raw3270_request_free(((struct fs3270 *) view)->init);
kfree(view);
}
@@ -285,11 +418,20 @@ static int
fs3270_open(struct inode *inode, struct file *filp)
{
struct fs3270 *fp;
+ struct idal_buffer *ib;
int minor, rc;
if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
return -ENODEV;
minor = iminor(filp->f_dentry->d_inode);
+ /* Check for minor 0 multiplexer. */
+ if (minor == 0) {
+ if (!current->signal->tty)
+ return -ENODEV;
+ if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
+ return -ENODEV;
+ minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+ }
/* Check if some other program is already using fullscreen mode. */
fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
if (!IS_ERR(fp)) {
@@ -301,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp)
if (IS_ERR(fp))
return PTR_ERR(fp);
- init_waitqueue_head(&fp->attn_wait);
+ init_waitqueue_head(&fp->wait);
fp->fs_pid = current->pid;
rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
if (rc) {
@@ -309,8 +451,18 @@ fs3270_open(struct inode *inode, struct file *filp)
return rc;
}
+ /* Allocate idal-buffer. */
+ ib = idal_buffer_alloc(2*fp->view.rows*fp->view.cols + 5, 0);
+ if (IS_ERR(ib)) {
+ raw3270_put_view(&fp->view);
+ raw3270_del_view(&fp->view);
+ return PTR_ERR(fp);
+ }
+ fp->rdbuf = ib;
+
rc = raw3270_activate_view(&fp->view);
if (rc) {
+ raw3270_put_view(&fp->view);
raw3270_del_view(&fp->view);
return rc;
}
@@ -329,8 +481,12 @@ fs3270_close(struct inode *inode, struct file *filp)
fp = filp->private_data;
filp->private_data = 0;
- if (fp)
+ if (fp) {
+ fp->fs_pid = 0;
+ raw3270_reset(&fp->view);
+ raw3270_put_view(&fp->view);
raw3270_del_view(&fp->view);
+ }
return 0;
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index d5eefeaba50c..d66946443dfc 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -25,6 +25,12 @@
#include "raw3270.h"
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/device.h>
+
+struct class *class3270;
+
/* The main 3270 data structure. */
struct raw3270 {
struct list_head list;
@@ -41,6 +47,8 @@ struct raw3270 {
struct timer_list timer; /* Device timer. */
unsigned char *ascebc; /* ascii -> ebcdic table */
+ struct class_device *clttydev; /* 3270-class tty device ptr */
+ struct class_device *cltubdev; /* 3270-class tub device ptr */
};
/* raw3270->flags */
@@ -317,6 +325,22 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
}
int
+raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
+{
+ struct raw3270 *rp;
+ int rc;
+
+ rp = view->dev;
+ if (!rp || rp->view != view)
+ rc = -EACCES;
+ else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+ rc = -ENODEV;
+ else
+ rc = __raw3270_start(rp, view, rq);
+ return rc;
+}
+
+int
raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
{
struct raw3270 *rp;
@@ -632,12 +656,9 @@ __raw3270_size_device(struct raw3270 *rp)
raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
- if (rc) {
+ if (rc)
/* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */
- if (rc == -EOPNOTSUPP && MACHINE_IS_VM)
- return __raw3270_size_device_vm(rp);
return rc;
- }
/* Wait for attention interrupt. */
#ifdef CONFIG_TN3270_CONSOLE
@@ -695,7 +716,10 @@ raw3270_size_device(struct raw3270 *rp)
down(&raw3270_init_sem);
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
- rc = __raw3270_size_device(rp);
+ if (MACHINE_IS_VM)
+ rc = __raw3270_size_device_vm(rp);
+ else
+ rc = __raw3270_size_device(rp);
raw3270_init_view.dev = 0;
rp->view = 0;
up(&raw3270_init_sem);
@@ -710,6 +734,12 @@ raw3270_size_device(struct raw3270 *rp)
rp->model = 4;
if (rp->rows == 27 && rp->cols == 132)
rp->model = 5;
+ } else {
+ /* Couldn't detect size. Use default model 2. */
+ rp->model = 2;
+ rp->rows = 24;
+ rp->cols = 80;
+ return 0;
}
return rc;
}
@@ -738,6 +768,22 @@ raw3270_reset_device(struct raw3270 *rp)
return rc;
}
+int
+raw3270_reset(struct raw3270_view *view)
+{
+ struct raw3270 *rp;
+ int rc;
+
+ rp = view->dev;
+ if (!rp || rp->view != view)
+ rc = -EACCES;
+ else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+ rc = -ENODEV;
+ else
+ rc = raw3270_reset_device(view->dev);
+ return rc;
+}
+
/*
* Setup new 3270 device.
*/
@@ -768,11 +814,12 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
/*
* Add device to list and find the smallest unused minor
- * number for it.
+ * number for it. Note: there is no device with minor 0,
+ * see special case for fs3270.c:fs3270_open().
*/
down(&raw3270_sem);
/* Keep the list sorted. */
- minor = 0;
+ minor = RAW3270_FIRSTMINOR;
rp->minor = -1;
list_for_each(l, &raw3270_devices) {
tmp = list_entry(l, struct raw3270, list);
@@ -783,7 +830,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
}
minor++;
}
- if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {
+ if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
rp->minor = minor;
list_add_tail(&rp->list, &raw3270_devices);
}
@@ -935,11 +982,12 @@ raw3270_deactivate_view(struct raw3270_view *view)
list_add_tail(&view->list, &rp->view_list);
/* Try to activate another view. */
if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
- list_for_each_entry(view, &rp->view_list, list)
- if (view->fn->activate(view) == 0) {
- rp->view = view;
+ list_for_each_entry(view, &rp->view_list, list) {
+ rp->view = view;
+ if (view->fn->activate(view) == 0)
break;
- }
+ rp->view = 0;
+ }
}
}
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -955,6 +1003,8 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
struct raw3270 *rp;
int rc;
+ if (minor <= 0)
+ return -ENODEV;
down(&raw3270_sem);
rc = -ENODEV;
list_for_each_entry(rp, &raw3270_devices, list) {
@@ -970,7 +1020,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
view->cols = rp->cols;
view->ascebc = rp->ascebc;
spin_lock_init(&view->lock);
- list_add_tail(&view->list, &rp->view_list);
+ list_add(&view->list, &rp->view_list);
rc = 0;
}
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -1033,7 +1083,7 @@ raw3270_del_view(struct raw3270_view *view)
if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
/* Try to activate another view. */
list_for_each_entry(nv, &rp->view_list, list) {
- if (nv->fn->activate(view) == 0) {
+ if (nv->fn->activate(nv) == 0) {
rp->view = nv;
break;
}
@@ -1057,6 +1107,12 @@ raw3270_delete_device(struct raw3270 *rp)
/* Remove from device chain. */
down(&raw3270_sem);
+ if (rp->clttydev)
+ class_device_destroy(class3270,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+ if (rp->cltubdev)
+ class_device_destroy(class3270,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor));
list_del_init(&rp->list);
up(&raw3270_sem);
@@ -1123,6 +1179,16 @@ raw3270_create_attributes(struct raw3270 *rp)
{
//FIXME: check return code
sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
+ rp->clttydev =
+ class_device_create(class3270,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tty%s",
+ rp->cdev->dev.bus_id);
+ rp->cltubdev =
+ class_device_create(class3270,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tub%s",
+ rp->cdev->dev.bus_id);
}
/*
@@ -1183,13 +1249,13 @@ raw3270_set_online (struct ccw_device *cdev)
return PTR_ERR(rp);
rc = raw3270_reset_device(rp);
if (rc)
- return rc;
+ goto failure;
rc = raw3270_size_device(rp);
if (rc)
- return rc;
+ goto failure;
rc = raw3270_reset_device(rp);
if (rc)
- return rc;
+ goto failure;
raw3270_create_attributes(rp);
set_bit(RAW3270_FLAGS_READY, &rp->flags);
down(&raw3270_sem);
@@ -1197,6 +1263,10 @@ raw3270_set_online (struct ccw_device *cdev)
np->notifier(rp->minor, 1);
up(&raw3270_sem);
return 0;
+
+failure:
+ raw3270_delete_device(rp);
+ return rc;
}
/*
@@ -1211,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev)
struct raw3270_notifier *np;
rp = cdev->dev.driver_data;
+ /*
+ * _remove is the opposite of _probe; it's probe that
+ * should set up rp. raw3270_remove gets entered for
+ * devices even if they haven't been varied online.
+ * Thus, rp may validly be NULL here.
+ */
+ if (rp == NULL)
+ return;
clear_bit(RAW3270_FLAGS_READY, &rp->flags);
sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
@@ -1295,6 +1373,7 @@ raw3270_init(void)
if (rc == 0) {
/* Create attributes for early (= console) device. */
down(&raw3270_sem);
+ class3270 = class_create(THIS_MODULE, "3270");
list_for_each_entry(rp, &raw3270_devices, list) {
get_device(&rp->cdev->dev);
raw3270_create_attributes(rp);
@@ -1308,6 +1387,7 @@ static void
raw3270_exit(void)
{
ccw_driver_unregister(&raw3270_ccw_driver);
+ class_destroy(class3270);
}
MODULE_LICENSE("GPL");
@@ -1329,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view);
EXPORT_SYMBOL(raw3270_activate_view);
EXPORT_SYMBOL(raw3270_deactivate_view);
EXPORT_SYMBOL(raw3270_start);
+EXPORT_SYMBOL(raw3270_start_locked);
EXPORT_SYMBOL(raw3270_start_irq);
+EXPORT_SYMBOL(raw3270_reset);
EXPORT_SYMBOL(raw3270_register_notifier);
EXPORT_SYMBOL(raw3270_unregister_notifier);
EXPORT_SYMBOL(raw3270_wait_queue);
diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h
index ed5d4eb9f623..b635bf8e7775 100644
--- a/drivers/s390/char/raw3270.h
+++ b/drivers/s390/char/raw3270.h
@@ -21,6 +21,7 @@
/* Local Channel Commands */
#define TC_WRITE 0x01 /* Write */
+#define TC_RDBUF 0x02 /* Read Buffer */
#define TC_EWRITE 0x05 /* Erase write */
#define TC_READMOD 0x06 /* Read modified */
#define TC_EWRITEA 0x0d /* Erase write alternate */
@@ -76,7 +77,8 @@
#define TW_KR 0xc2 /* Keyboard restore */
#define TW_PLUSALARM 0x04 /* Add this bit for alarm */
-#define RAW3270_MAXDEVS 256
+#define RAW3270_FIRSTMINOR 1 /* First minor number */
+#define RAW3270_MAXDEVS 255 /* Max number of 3270 devices */
/* For TUBGETMOD and TUBSETMOD. Should include. */
struct raw3270_iocb {
@@ -166,7 +168,10 @@ void raw3270_del_view(struct raw3270_view *);
void raw3270_deactivate_view(struct raw3270_view *);
struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int);
int raw3270_start(struct raw3270_view *, struct raw3270_request *);
+int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
+int raw3270_reset(struct raw3270_view *);
+struct raw3270_view *raw3270_view(struct raw3270_view *);
/* Reference count inliner for view structures. */
static inline void
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index ed0cb1f15b4c..fcaee447d6fe 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -72,6 +72,7 @@ struct tape_class_device *register_tape_dev(
tcd->class_device = class_device_create(
tape_class,
+ NULL,
tcd->char_device->dev,
device,
"%s", tcd->device_name
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 7db5ebce7f0f..4b9069370388 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -653,18 +653,12 @@ tty3270_activate(struct raw3270_view *view)
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
spin_unlock_irqrestore(&tp->view.lock, flags);
- start_tty(tp->tty);
return 0;
}
static void
tty3270_deactivate(struct raw3270_view *view)
{
- struct tty3270 *tp;
-
- tp = (struct tty3270 *) view;
- if (tp && tp->tty)
- stop_tty(tp->tty);
}
static int
@@ -716,13 +710,13 @@ tty3270_alloc_view(void)
tp->freemem_pages[pages], PAGE_SIZE);
}
tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);
- if (!tp->write)
+ if (IS_ERR(tp->write))
goto out_pages;
tp->read = raw3270_request_alloc(0);
- if (!tp->read)
+ if (IS_ERR(tp->read))
goto out_write;
tp->kreset = raw3270_request_alloc(1);
- if (!tp->kreset)
+ if (IS_ERR(tp->kreset))
goto out_read;
tp->kbd = kbd_alloc();
if (!tp->kbd)
@@ -845,7 +839,8 @@ tty3270_del_views(void)
int i;
for (i = 0; i < tty3270_max_index; i++) {
- tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, i);
+ tp = (struct tty3270 *)
+ raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
if (!IS_ERR(tp))
raw3270_del_view(&tp->view);
}
@@ -871,7 +866,9 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
if (tty->count > 1)
return 0;
/* Check if the tty3270 is already there. */
- tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, tty->index);
+ tp = (struct tty3270 *)
+ raw3270_find_view(&tty3270_fn,
+ tty->index + RAW3270_FIRSTMINOR);
if (!IS_ERR(tp)) {
tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2;
@@ -903,7 +900,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
(void (*)(unsigned long)) tty3270_read_tasklet,
(unsigned long) tp->read);
- rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+ rc = raw3270_add_view(&tp->view, &tty3270_fn,
+ tty->index + RAW3270_FIRSTMINOR);
if (rc) {
tty3270_free_view(tp);
return rc;
@@ -911,8 +909,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
rc = tty3270_alloc_screen(tp);
if (rc) {
- raw3270_del_view(&tp->view);
raw3270_put_view(&tp->view);
+ raw3270_del_view(&tp->view);
return rc;
}
@@ -1780,7 +1778,7 @@ tty3270_init(void)
struct tty_driver *driver;
int ret;
- driver = alloc_tty_driver(256);
+ driver = alloc_tty_driver(RAW3270_MAXDEVS);
if (!driver)
return -ENOMEM;
@@ -1794,6 +1792,7 @@ tty3270_init(void)
driver->driver_name = "ttyTUB";
driver->name = "ttyTUB";
driver->major = IBM_TTY3270_MAJOR;
+ driver->minor_start = RAW3270_FIRSTMINOR;
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 491f00c032e8..b2d75de144c6 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -788,6 +788,7 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
}
priv->class_device = class_device_create(
vmlogrdr_class,
+ NULL,
MKDEV(vmlogrdr_major, priv->minor_num),
dev,
"%s", dev->bus_id );
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aac83ce6469c..a1c52a682191 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.34 $
+ * $Revision: 1.35 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -35,7 +35,7 @@
*/
/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
(8*sizeof(long)))
static unsigned long bl_dev[__BL_DEV_WORDS];
typedef enum {add, free} range_action;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 91ea8e4777f3..dbb3eb0e330b 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -437,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
if (cdev->dev.driver_data) {
gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
if (get_device(&gdev->dev)) {
- if (klist_node_attached(&gdev->dev.knode_bus))
+ if (device_is_registered(&gdev->dev))
return gdev;
put_device(&gdev->dev);
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index ea813bdce1d6..185bc73c3ecd 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.134 $
+ * $Revision: 1.135 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -815,8 +815,9 @@ __clear_subchannel_easy(unsigned int schid)
struct tpi_info ti;
if (tpi(&ti)) {
- tsch(schid, (struct irb *)__LC_IRB);
- return 0;
+ tsch(ti.irq, (struct irb *)__LC_IRB);
+ if (ti.irq == schid)
+ return 0;
}
udelay(100);
}
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 8cc4f1a940dc..c05b069c2996 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -30,10 +30,13 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/timex.h> /* get_clock() */
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/cmb.h>
+#include <asm/div64.h>
#include "cio.h"
#include "css.h"
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 14c76f5e4177..811c9d150637 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -22,6 +22,7 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
+#include <asm/param.h> /* HZ */
#include "cio.h"
#include "css.h"
@@ -252,6 +253,23 @@ cutype_show (struct device *dev, struct device_attribute *attr, char *buf)
}
static ssize_t
+modalias_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ccw_device *cdev = to_ccwdev(dev);
+ struct ccw_device_id *id = &(cdev->id);
+ int ret;
+
+ ret = sprintf(buf, "ccw:t%04Xm%02x",
+ id->cu_type, id->cu_model);
+ if (id->dev_type != 0)
+ ret += sprintf(buf + ret, "dt%04Xdm%02X\n",
+ id->dev_type, id->dev_model);
+ else
+ ret += sprintf(buf + ret, "dtdm\n");
+ return ret;
+}
+
+static ssize_t
online_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
@@ -448,6 +466,7 @@ static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
+static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
static DEVICE_ATTR(online, 0644, online_show, online_store);
extern struct device_attribute dev_attr_cmb_enable;
static DEVICE_ATTR(availability, 0444, available_show, NULL);
@@ -471,6 +490,7 @@ subchannel_add_files (struct device *dev)
static struct attribute * ccwdev_attrs[] = {
&dev_attr_devtype.attr,
&dev_attr_cutype.attr,
+ &dev_attr_modalias.attr,
&dev_attr_online.attr,
&dev_attr_cmb_enable.attr,
&dev_attr_availability.attr,
@@ -544,7 +564,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
.sibling = sibling,
};
- dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
+ dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
return dev ? to_ccwdev(dev) : NULL;
}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index ee7a05e0c3ba..c1c89f4fd4e3 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -11,9 +11,11 @@
#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
#include <asm/ccwdev.h>
-#include <asm/qdio.h>
+#include <asm/cio.h>
#include "cio.h"
#include "cio_debug.h"
@@ -21,7 +23,6 @@
#include "device.h"
#include "chsc.h"
#include "ioasm.h"
-#include "qdio.h"
int
device_is_online(struct subchannel *sch)
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 02d01a0de16c..ad3fe5aeb663 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.56 $
+ * $Revision: 1.57 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -19,14 +19,12 @@
#include <asm/ccwdev.h>
#include <asm/idals.h>
-#include <asm/qdio.h>
#include "cio.h"
#include "cio_debug.h"
#include "css.h"
#include "chsc.h"
#include "device.h"
-#include "qdio.h"
int
ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index c874607d9a80..45480a2bc4c0 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -21,7 +21,7 @@ struct tpi_info {
* Some S390 specific IO instructions as inline
*/
-extern __inline__ int stsch(int irq, volatile struct schib *addr)
+static inline int stsch(int irq, volatile struct schib *addr)
{
int ccode;
@@ -36,7 +36,7 @@ extern __inline__ int stsch(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int msch(int irq, volatile struct schib *addr)
+static inline int msch(int irq, volatile struct schib *addr)
{
int ccode;
@@ -51,7 +51,7 @@ extern __inline__ int msch(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int msch_err(int irq, volatile struct schib *addr)
+static inline int msch_err(int irq, volatile struct schib *addr)
{
int ccode;
@@ -79,7 +79,7 @@ extern __inline__ int msch_err(int irq, volatile struct schib *addr)
return ccode;
}
-extern __inline__ int tsch(int irq, volatile struct irb *addr)
+static inline int tsch(int irq, volatile struct irb *addr)
{
int ccode;
@@ -94,7 +94,7 @@ extern __inline__ int tsch(int irq, volatile struct irb *addr)
return ccode;
}
-extern __inline__ int tpi( volatile struct tpi_info *addr)
+static inline int tpi( volatile struct tpi_info *addr)
{
int ccode;
@@ -108,7 +108,7 @@ extern __inline__ int tpi( volatile struct tpi_info *addr)
return ccode;
}
-extern __inline__ int ssch(int irq, volatile struct orb *addr)
+static inline int ssch(int irq, volatile struct orb *addr)
{
int ccode;
@@ -123,7 +123,7 @@ extern __inline__ int ssch(int irq, volatile struct orb *addr)
return ccode;
}
-extern __inline__ int rsch(int irq)
+static inline int rsch(int irq)
{
int ccode;
@@ -138,7 +138,7 @@ extern __inline__ int rsch(int irq)
return ccode;
}
-extern __inline__ int csch(int irq)
+static inline int csch(int irq)
{
int ccode;
@@ -153,7 +153,7 @@ extern __inline__ int csch(int irq)
return ccode;
}
-extern __inline__ int hsch(int irq)
+static inline int hsch(int irq)
{
int ccode;
@@ -168,7 +168,7 @@ extern __inline__ int hsch(int irq)
return ccode;
}
-extern __inline__ int xsch(int irq)
+static inline int xsch(int irq)
{
int ccode;
@@ -183,7 +183,7 @@ extern __inline__ int xsch(int irq)
return ccode;
}
-extern __inline__ int chsc(void *chsc_area)
+static inline int chsc(void *chsc_area)
{
int cc;
@@ -198,7 +198,7 @@ extern __inline__ int chsc(void *chsc_area)
return cc;
}
-extern __inline__ int iac( void)
+static inline int iac( void)
{
int ccode;
@@ -210,7 +210,7 @@ extern __inline__ int iac( void)
return ccode;
}
-extern __inline__ int rchp(int chpid)
+static inline int rchp(int chpid)
{
int ccode;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index d36258d6665f..381f339e3200 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -112,7 +112,7 @@ qdio_min(int a,int b)
/***************** SCRUBBER HELPER ROUTINES **********************/
-static inline volatile __u64
+static inline __u64
qdio_get_micros(void)
{
return (get_clock() >> 10); /* time>>12 is microseconds */
@@ -230,7 +230,7 @@ qdio_siga_input(struct qdio_q *q)
}
/* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 * volatile
+static __u32 volatile *
qdio_get_indicator(void)
{
int i;
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index bcabac7a7c46..e319e78b5ea2 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -27,7 +27,7 @@
#ifndef _Z90COMMON_H_
#define _Z90COMMON_H_
-#define VERSION_Z90COMMON_H "$Revision: 1.16 $"
+#define VERSION_Z90COMMON_H "$Revision: 1.17 $"
#define RESPBUFFSIZE 256
@@ -164,5 +164,4 @@ struct CPRBX {
#define UMIN(a,b) ((a) < (b) ? (a) : (b))
#define IS_EVEN(x) ((x) == (2 * ((x) / 2)))
-
#endif
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 82a1d97001d7..0a3bb5a10dd4 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -36,15 +36,6 @@
#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
/**
- * If we are not using the sparse checker, __user has no use.
- */
-#ifdef __CHECKER__
-# define __user __attribute__((noderef, address_space(1)))
-#else
-# define __user
-#endif
-
-/**
* struct ica_rsa_modexpo
*
* Requirements:
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index beb6a5e0da22..c215e0889736 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -32,7 +32,7 @@
#include "z90crypt.h"
#include "z90common.h"
-#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $"
+#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
char z90hardware_version[] __initdata =
"z90hardware.o (" VERSION_Z90HARDWARE_C "/"
@@ -283,48 +283,6 @@ struct type6_msg {
struct CPRB CPRB;
};
-union request_msg {
- union type4_msg t4msg;
- struct type6_msg t6msg;
-};
-
-struct request_msg_ext {
- int q_nr;
- unsigned char *psmid;
- union request_msg reqMsg;
-};
-
-struct type82_hdr {
- unsigned char reserved1;
- unsigned char type;
- unsigned char reserved2[2];
- unsigned char reply_code;
- unsigned char reserved3[3];
-};
-
-#define TYPE82_RSP_CODE 0x82
-
-#define REPLY_ERROR_MACHINE_FAILURE 0x10
-#define REPLY_ERROR_PREEMPT_FAILURE 0x12
-#define REPLY_ERROR_CHECKPT_FAILURE 0x14
-#define REPLY_ERROR_MESSAGE_TYPE 0x20
-#define REPLY_ERROR_INVALID_COMM_CD 0x21
-#define REPLY_ERROR_INVALID_MSG_LEN 0x23
-#define REPLY_ERROR_RESERVD_FIELD 0x24
-#define REPLY_ERROR_FORMAT_FIELD 0x29
-#define REPLY_ERROR_INVALID_COMMAND 0x30
-#define REPLY_ERROR_MALFORMED_MSG 0x40
-#define REPLY_ERROR_RESERVED_FIELDO 0x50
-#define REPLY_ERROR_WORD_ALIGNMENT 0x60
-#define REPLY_ERROR_MESSAGE_LENGTH 0x80
-#define REPLY_ERROR_OPERAND_INVALID 0x82
-#define REPLY_ERROR_OPERAND_SIZE 0x84
-#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85
-#define REPLY_ERROR_RESERVED_FIELD 0x88
-#define REPLY_ERROR_TRANSPORT_FAIL 0x90
-#define REPLY_ERROR_PACKET_TRUNCATED 0xA0
-#define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0
-
struct type86_hdr {
unsigned char reserved1;
unsigned char type;
@@ -338,7 +296,7 @@ struct type86_hdr {
#define TYPE86_FMT2 0x02
struct type86_fmt2_msg {
- struct type86_hdr hdr;
+ struct type86_hdr header;
unsigned char reserved[4];
unsigned char apfs[4];
unsigned int count1;
@@ -538,6 +496,8 @@ static struct function_and_rules_block static_pke_function_and_rulesX = {
{'M','R','P',' ',' ',' ',' ',' '}
};
+static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+
struct T6_keyBlock_hdrX {
unsigned short blen;
unsigned short ulen;
@@ -688,9 +648,38 @@ static struct cca_public_sec static_cca_pub_sec = {
#define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724
-#define CALLER_HEADER 12
+struct error_hdr {
+ unsigned char reserved1;
+ unsigned char type;
+ unsigned char reserved2[2];
+ unsigned char reply_code;
+ unsigned char reserved3[3];
+};
-static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+#define TYPE82_RSP_CODE 0x82
+
+#define REP82_ERROR_MACHINE_FAILURE 0x10
+#define REP82_ERROR_PREEMPT_FAILURE 0x12
+#define REP82_ERROR_CHECKPT_FAILURE 0x14
+#define REP82_ERROR_MESSAGE_TYPE 0x20
+#define REP82_ERROR_INVALID_COMM_CD 0x21
+#define REP82_ERROR_INVALID_MSG_LEN 0x23
+#define REP82_ERROR_RESERVD_FIELD 0x24
+#define REP82_ERROR_FORMAT_FIELD 0x29
+#define REP82_ERROR_INVALID_COMMAND 0x30
+#define REP82_ERROR_MALFORMED_MSG 0x40
+#define REP82_ERROR_RESERVED_FIELDO 0x50
+#define REP82_ERROR_WORD_ALIGNMENT 0x60
+#define REP82_ERROR_MESSAGE_LENGTH 0x80
+#define REP82_ERROR_OPERAND_INVALID 0x82
+#define REP82_ERROR_OPERAND_SIZE 0x84
+#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
+#define REP82_ERROR_RESERVED_FIELD 0x88
+#define REP82_ERROR_TRANSPORT_FAIL 0x90
+#define REP82_ERROR_PACKET_TRUNCATED 0xA0
+#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
+
+#define CALLER_HEADER 12
static inline int
testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
@@ -1212,9 +1201,9 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
struct ap_status_word stat_word;
enum devstat stat;
int ccode;
+ u32 *q_nr_p = (u32 *)msg_ext;
- ((struct request_msg_ext *) msg_ext)->q_nr =
- (dev_nr << SKIP_BITL) + cdx;
+ *q_nr_p = (dev_nr << SKIP_BITL) + cdx;
PDEBUG("msg_len passed to sen: %d\n", msg_len);
PDEBUG("q number passed to sen: %02x%02x%02x%02x\n",
msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]);
@@ -2104,7 +2093,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
int *respbufflen_p, unsigned char *resp_buff)
{
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
- struct type82_hdr *t82h_p = (struct type82_hdr *) response;
+ struct error_hdr *errh_p = (struct error_hdr *) response;
struct type84_hdr *t84h_p = (struct type84_hdr *) response;
struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
int reply_code, service_rc, service_rs, src_l;
@@ -2117,12 +2106,13 @@ convert_response(unsigned char *response, unsigned char *buffer,
service_rc = 0;
service_rs = 0;
src_l = 0;
- switch (t82h_p->type) {
+ switch (errh_p->type) {
case TYPE82_RSP_CODE:
- reply_code = t82h_p->reply_code;
- src_p = (unsigned char *)t82h_p;
- PRINTK("Hardware error: Type 82 Message Header: "
+ reply_code = errh_p->reply_code;
+ src_p = (unsigned char *)errh_p;
+ PRINTK("Hardware error: Type %02X Message Header: "
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ errh_p->type,
src_p[0], src_p[1], src_p[2], src_p[3],
src_p[4], src_p[5], src_p[6], src_p[7]);
break;
@@ -2131,7 +2121,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_p = response + (int)t84h_p->len - src_l;
break;
case TYPE86_RSP_CODE:
- reply_code = t86m_p->hdr.reply_code;
+ reply_code = t86m_p->header.reply_code;
if (reply_code != 0)
break;
cprb_p = (struct CPRB *)
@@ -2143,6 +2133,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
le2toI(cprb_p->ccp_rscode, &service_rs);
if ((service_rc == 8) && (service_rs == 66))
PDEBUG("Bad block format on PCICC\n");
+ else if ((service_rc == 8) && (service_rs == 65))
+ PDEBUG("Probably an even modulus on "
+ "PCICC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCICC\n");
unset_ext_bitlens();
@@ -2155,7 +2148,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
return REC_USE_PCICA;
}
else
- PRINTK("service rc/rs: %d/%d\n",
+ PRINTK("service rc/rs (PCICC): %d/%d\n",
service_rc, service_rs);
return REC_OPERAND_INV;
}
@@ -2169,7 +2162,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (service_rc != 0) {
service_rs = (int) cprbx_p->ccp_rscode;
if ((service_rc == 8) && (service_rs == 66))
- PDEBUG("Bad block format on PCXICC\n");
+ PDEBUG("Bad block format on PCIXCC\n");
+ else if ((service_rc == 8) && (service_rs == 65))
+ PDEBUG("Probably an even modulus on "
+ "PCIXCC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCIXCC\n");
unset_ext_bitlens();
@@ -2182,7 +2178,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
return REC_USE_PCICA;
}
else
- PRINTK("service rc/rs: %d/%d\n",
+ PRINTK("service rc/rs (PCIXCC): %d/%d\n",
service_rc, service_rs);
return REC_OPERAND_INV;
}
@@ -2195,20 +2191,25 @@ convert_response(unsigned char *response, unsigned char *buffer,
}
break;
default:
+ src_p = (unsigned char *)errh_p;
+ PRINTK("Unrecognized Message Header: "
+ "%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ src_p[0], src_p[1], src_p[2], src_p[3],
+ src_p[4], src_p[5], src_p[6], src_p[7]);
return REC_BAD_MESSAGE;
}
if (reply_code)
switch (reply_code) {
- case REPLY_ERROR_OPERAND_INVALID:
+ case REP82_ERROR_OPERAND_INVALID:
return REC_OPERAND_INV;
- case REPLY_ERROR_OPERAND_SIZE:
+ case REP82_ERROR_OPERAND_SIZE:
return REC_OPERAND_SIZE;
- case REPLY_ERROR_EVEN_MOD_IN_OPND:
+ case REP82_ERROR_EVEN_MOD_IN_OPND:
return REC_EVEN_MOD;
- case REPLY_ERROR_MESSAGE_TYPE:
+ case REP82_ERROR_MESSAGE_TYPE:
return WRONG_DEVICE_TYPE;
- case REPLY_ERROR_TRANSPORT_FAIL:
+ case REP82_ERROR_TRANSPORT_FAIL:
PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
t86m_p->apfs[0], t86m_p->apfs[1],
t86m_p->apfs[2], t86m_p->apfs[3]);
@@ -2229,7 +2230,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
PDEBUG("Length returned = %d\n", src_l);
tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l;
memcpy(tgt_p, src_p, src_l);
- if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
+ if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
return REC_INVALID_PAD;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 9ec29bb41b28..0cb47eca91f3 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/interrupt.h> // for tasklets
#include <linux/ioctl32.h>
+#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kobject_uevent.h>
@@ -39,19 +40,8 @@
#include <linux/version.h>
#include "z90crypt.h"
#include "z90common.h"
-#ifndef Z90CRYPT_USE_HOTPLUG
-#include <linux/miscdevice.h>
-#endif
-
-#define VERSION_CODE(vers, rel, seq) (((vers)<<16) | ((rel)<<8) | (seq))
-#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0) /* version < 2.4 */
-# error "This kernel is too old: not supported"
-#endif
-#if LINUX_VERSION_CODE > VERSION_CODE(2,7,0) /* version > 2.6 */
-# error "This kernel is too recent: not supported by this file"
-#endif
-#define VERSION_Z90MAIN_C "$Revision: 1.57 $"
+#define VERSION_Z90MAIN_C "$Revision: 1.62 $"
static char z90main_version[] __initdata =
"z90main.o (" VERSION_Z90MAIN_C "/"
@@ -63,21 +53,12 @@ extern char z90hardware_version[];
* Defaults that may be modified.
*/
-#ifndef Z90CRYPT_USE_HOTPLUG
/**
* You can specify a different minor at compile time.
*/
#ifndef Z90CRYPT_MINOR
#define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR
#endif
-#else
-/**
- * You can specify a different major at compile time.
- */
-#ifndef Z90CRYPT_MAJOR
-#define Z90CRYPT_MAJOR 0
-#endif
-#endif
/**
* You can specify a different domain at compile time or on the insmod
@@ -97,7 +78,7 @@ extern char z90hardware_version[];
* older than CLEANUPTIME seconds in the past.
*/
#ifndef CLEANUPTIME
-#define CLEANUPTIME 20
+#define CLEANUPTIME 15
#endif
/**
@@ -298,6 +279,10 @@ struct z90crypt {
* it contains the request; at READ, the response. The function
* send_to_crypto_device converts the request to device-dependent
* form and use the caller's OPEN-allocated buffer for the response.
+ *
+ * For the contents of caller_dev_dep_req and caller_dev_dep_req_p
+ * because that points to it, see the discussion in z90hardware.c.
+ * Search for "extended request message block".
*/
struct caller {
int caller_buf_l; // length of original request
@@ -398,24 +383,9 @@ static int z90crypt_status_write(struct file *, const char __user *,
unsigned long, void *);
/**
- * Hotplug support
- */
-
-#ifdef Z90CRYPT_USE_HOTPLUG
-#define Z90CRYPT_HOTPLUG_ADD 1
-#define Z90CRYPT_HOTPLUG_REMOVE 2
-
-static void z90crypt_hotplug_event(int, int, int);
-#endif
-
-/**
* Storage allocated at initialization and used throughout the life of
* this insmod
*/
-#ifdef Z90CRYPT_USE_HOTPLUG
-static int z90crypt_major = Z90CRYPT_MAJOR;
-#endif
-
static int domain = DOMAIN_INDEX;
static struct z90crypt z90crypt;
static int quiesce_z90crypt;
@@ -444,14 +414,12 @@ static struct file_operations z90crypt_fops = {
.release = z90crypt_release
};
-#ifndef Z90CRYPT_USE_HOTPLUG
static struct miscdevice z90crypt_misc_device = {
.minor = Z90CRYPT_MINOR,
.name = DEV_NAME,
.fops = &z90crypt_fops,
.devfs_name = DEV_NAME
};
-#endif
/**
* Documentation values.
@@ -603,7 +571,6 @@ z90crypt_init_module(void)
return -EINVAL;
}
-#ifndef Z90CRYPT_USE_HOTPLUG
/* Register as misc device with given minor (or get a dynamic one). */
result = misc_register(&z90crypt_misc_device);
if (result < 0) {
@@ -611,18 +578,6 @@ z90crypt_init_module(void)
z90crypt_misc_device.minor, result);
return result;
}
-#else
- /* Register the major (or get a dynamic one). */
- result = register_chrdev(z90crypt_major, REG_NAME, &z90crypt_fops);
- if (result < 0) {
- PRINTKW("register_chrdev (major %d) failed with %d.\n",
- z90crypt_major, result);
- return result;
- }
-
- if (z90crypt_major == 0)
- z90crypt_major = result;
-#endif
PDEBUG("Registered " DEV_NAME " with result %d\n", result);
@@ -645,11 +600,6 @@ z90crypt_init_module(void)
} else
PRINTK("No devices at startup\n");
-#ifdef Z90CRYPT_USE_HOTPLUG
- /* generate hotplug event for device node generation */
- z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_ADD);
-#endif
-
/* Initialize globals. */
spin_lock_init(&queuespinlock);
@@ -701,17 +651,10 @@ z90crypt_init_module(void)
return 0; // success
init_module_cleanup:
-#ifndef Z90CRYPT_USE_HOTPLUG
if ((nresult = misc_deregister(&z90crypt_misc_device)))
PRINTK("misc_deregister failed with %d.\n", nresult);
else
PDEBUG("misc_deregister successful.\n");
-#else
- if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
- PRINTK("unregister_chrdev failed with %d.\n", nresult);
- else
- PDEBUG("unregister_chrdev successful.\n");
-#endif
return result; // failure
}
@@ -728,19 +671,10 @@ z90crypt_cleanup_module(void)
remove_proc_entry("driver/z90crypt", 0);
-#ifndef Z90CRYPT_USE_HOTPLUG
if ((nresult = misc_deregister(&z90crypt_misc_device)))
PRINTK("misc_deregister failed with %d.\n", nresult);
else
PDEBUG("misc_deregister successful.\n");
-#else
- z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_REMOVE);
-
- if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
- PRINTK("unregister_chrdev failed with %d.\n", nresult);
- else
- PDEBUG("unregister_chrdev successful.\n");
-#endif
/* Remove the tasks */
tasklet_kill(&reader_tasklet);
@@ -766,8 +700,6 @@ z90crypt_cleanup_module(void)
* z90crypt_status_write
* disable_card
* enable_card
- * scan_char
- * scan_string
*
* Helper functions:
* z90crypt_rsa
@@ -1057,9 +989,10 @@ remove_device(struct device *device_p)
* The MCL must be applied and the newer bitlengths enabled for these to work.
*
* Card Type Old limit New limit
+ * PCICA ??-2048 same (the lower limit is less than 128 bit...)
* PCICC 512-1024 512-2048
- * PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+)
- * PCIXCC_MCL3 512-2048 128-2048
+ * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card)
+ * PCIXCC_MCL3 ----- 128-2048
* CEX2C 512-2048 128-2048
*
* ext_bitlens (extended bitlengths) is a global, since you should not apply an
@@ -1104,7 +1037,7 @@ select_device_type(int *dev_type_p, int bytelength)
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
/**
* bitlength is a factor, PCICA is the most capable, even with
- * the new MCL.
+ * the new MCL for PCIXCC.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
@@ -2144,73 +2077,15 @@ enable_card(int card_index)
z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--;
}
-static inline int
-scan_char(unsigned char *bf, unsigned int len,
- unsigned int *offs, unsigned int *p_eof, unsigned char c)
-{
- unsigned int i, found;
-
- found = 0;
- for (i = 0; i < len; i++) {
- if (bf[i] == c) {
- found = 1;
- break;
- }
- if (bf[i] == '\0') {
- *p_eof = 1;
- break;
- }
- if (bf[i] == '\n') {
- break;
- }
- }
- *offs = i+1;
- return found;
-}
-
-static inline int
-scan_string(unsigned char *bf, unsigned int len,
- unsigned int *offs, unsigned int *p_eof, unsigned char *s)
-{
- unsigned int temp_len, temp_offs, found, eof;
-
- temp_len = temp_offs = found = eof = 0;
- while (!eof && !found) {
- found = scan_char(bf+temp_len, len-temp_len,
- &temp_offs, &eof, *s);
-
- temp_len += temp_offs;
- if (eof) {
- found = 0;
- break;
- }
-
- if (found) {
- if (len >= temp_offs+strlen(s)) {
- found = !strncmp(bf+temp_len-1, s, strlen(s));
- if (found) {
- *offs = temp_len+strlen(s)-1;
- break;
- }
- } else {
- found = 0;
- *p_eof = 1;
- break;
- }
- }
- }
- return found;
-}
-
static int
z90crypt_status_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
- int i, j, len, offs, found, eof;
- unsigned char *lbuf;
+ int j, eol;
+ unsigned char *lbuf, *ptr;
unsigned int local_count;
-#define LBUFSIZE 600
+#define LBUFSIZE 1200
lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
if (!lbuf) {
PRINTK("kmalloc failed!\n");
@@ -2227,49 +2102,46 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
return -EFAULT;
}
- lbuf[local_count-1] = '\0';
+ lbuf[local_count] = '\0';
- len = 0;
- eof = 0;
- found = 0;
- while (!eof) {
- found = scan_string(lbuf+len, local_count-len, &offs, &eof,
- "Online devices");
- len += offs;
- if (found == 1)
- break;
+ ptr = strstr(lbuf, "Online devices");
+ if (ptr == 0) {
+ PRINTK("Unable to parse data (missing \"Online devices\")\n");
+ kfree(lbuf);
+ return count;
}
- if (eof) {
+ ptr = strstr(ptr, "\n");
+ if (ptr == 0) {
+ PRINTK("Unable to parse data (missing newline after \"Online devices\")\n");
kfree(lbuf);
return count;
}
+ ptr++;
- if (found)
- found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n');
-
- if (!found || eof) {
+ if (strstr(ptr, "Waiting work element counts") == NULL) {
+ PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n");
kfree(lbuf);
return count;
}
- len += offs;
j = 0;
- for (i = 0; i < 80; i++) {
- switch (*(lbuf+len+i)) {
+ eol = 0;
+ while ((j < 64) && (*ptr != '\0')) {
+ switch (*ptr) {
case '\t':
case ' ':
break;
case '\n':
default:
- eof = 1;
+ eol = 1;
break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
+ case '0': // no device
+ case '1': // PCICA
+ case '2': // PCICC
+ case '3': // PCIXCC_MCL2
+ case '4': // PCIXCC_MCL3
+ case '5': // CEX2C
j++;
break;
case 'd':
@@ -2283,8 +2155,9 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
j++;
break;
}
- if (eof)
+ if (eol)
break;
+ ptr++;
}
kfree(lbuf);
@@ -3479,45 +3352,5 @@ probe_PCIXCC_type(struct device *devPtr)
return rv;
}
-#ifdef Z90CRYPT_USE_HOTPLUG
-static void
-z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
-{
-#ifdef CONFIG_HOTPLUG
- char *argv[3];
- char *envp[6];
- char major[20];
- char minor[20];
-
- sprintf(major, "MAJOR=%d", dev_major);
- sprintf(minor, "MINOR=%d", dev_minor);
-
- argv[0] = hotplug_path;
- argv[1] = "z90crypt";
- argv[2] = 0;
-
- envp[0] = "HOME=/";
- envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
- switch (action) {
- case Z90CRYPT_HOTPLUG_ADD:
- envp[2] = "ACTION=add";
- break;
- case Z90CRYPT_HOTPLUG_REMOVE:
- envp[2] = "ACTION=remove";
- break;
- default:
- BUG();
- break;
- }
- envp[3] = major;
- envp[4] = minor;
- envp[5] = 0;
-
- call_usermodehelper(argv[0], argv, envp, 0);
-#endif
-}
-#endif
-
module_init(z90crypt_init_module);
module_exit(z90crypt_cleanup_module);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 24c0af49c25c..3092473991a7 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2,9 +2,9 @@
* drivers/s390/net/claw.c
* ESCON CLAW network driver
*
- * $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $
+ * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $
*
- * Linux fo zSeries version
+ * Linux for zSeries version
* Copyright (C) 2002,2005 IBM Corporation
* Author(s) Original code written by:
* Kazuo Iimura (iimura@jp.ibm.com)
@@ -431,12 +431,12 @@ claw_pack_skb(struct claw_privbk *privptr)
if (!skb_queue_empty(&p_ch->collect_queue)) {
/* some data */
held_skb = skb_dequeue(&p_ch->collect_queue);
- if (p_env->packing != DO_PACKED)
- return held_skb;
if (held_skb)
- atomic_dec(&held_skb->users);
+ dev_kfree_skb_any(held_skb);
else
return NULL;
+ if (p_env->packing != DO_PACKED)
+ return held_skb;
/* get a new SKB we will pack at least one */
new_skb = dev_alloc_skb(p_env->write_size);
if (new_skb == NULL) {
@@ -455,7 +455,7 @@ claw_pack_skb(struct claw_privbk *privptr)
privptr->stats.tx_packets++;
so_far += held_skb->len;
pkt_cnt++;
- dev_kfree_skb_irq(held_skb);
+ dev_kfree_skb_any(held_skb);
held_skb = skb_dequeue(&p_ch->collect_queue);
if (held_skb)
atomic_dec(&held_skb->users);
@@ -1092,7 +1092,7 @@ claw_release(struct net_device *dev)
}
}
if (privptr->pk_skb != NULL) {
- dev_kfree_skb(privptr->pk_skb);
+ dev_kfree_skb_any(privptr->pk_skb);
privptr->pk_skb = NULL;
}
if(privptr->buffs_alloc != 1) {
@@ -2016,7 +2016,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
p_buf=(struct ccwbk*)privptr->p_end_ccw;
dumpit((char *)p_buf, sizeof(struct endccw));
#endif
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
if (linkid==0) {
lock=LOCK_NO;
}
@@ -4061,7 +4061,7 @@ claw_purge_skb_queue(struct sk_buff_head *q)
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb_any(skb);
}
}
@@ -4410,7 +4410,7 @@ claw_init(void)
#else
"compiled into kernel "
#endif
- " $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ \n");
+ " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n");
#ifdef FUNCTRACE
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 96ca863eaff2..0db4f57a6a95 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
+ * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
*
* CTC / ESCON network driver
*
@@ -37,10 +37,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
*
*/
-
#undef DEBUG
#include <linux/module.h>
#include <linux/init.h>
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
"TX down",
"Restart",
};
-
+
/**
* Events of the channel statemachine
*/
@@ -249,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.74 $";
+ char vbuf[] = "$Revision: 1.78 $";
char *version = vbuf;
if (printed)
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
"Restarting",
"Not operational",
};
-
+
#ifdef DEBUG
/**
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
@@ -671,7 +670,7 @@ static void
fsm_action_nop(fsm_instance * fi, int event, void *arg)
{
}
-
+
/**
* Actions for channel - statemachines.
*****************************************************************************/
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg)
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
}
-
/**
* The statemachine for a channel.
*/
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
};
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-
+
/**
* Functions related to setup and device detection.
*****************************************************************************/
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
}
-
+
/**
* Actions for interface - statemachine.
*****************************************************************************/
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int rc = 0;
DBF_TEXT(trace, 5, __FUNCTION__);
+ /* we need to acquire the lock for testing the state
+ * otherwise we can have an IRQ changing the state to
+ * TXIDLE after the test but before acquiring the lock.
+ */
+ spin_lock_irqsave(&ch->collect_lock, saveflags);
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
int l = skb->len + LL_HEADER_LENGTH;
- spin_lock_irqsave(&ch->collect_lock, saveflags);
- if (ch->collect_len + l > ch->max_bufsize - 2)
- rc = -EBUSY;
- else {
+ if (ch->collect_len + l > ch->max_bufsize - 2) {
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+ return -EBUSY;
+ } else {
atomic_inc(&skb->users);
header.length = l;
header.type = skb->protocol;
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int ccw_idx;
struct sk_buff *nskb;
unsigned long hi;
-
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
/**
* Protect skb against beeing free'd by upper
* layers.
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
if (!nskb) {
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -ENOMEM;
} else {
memcpy(skb_put(nskb, skb->len),
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
*/
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -EBUSY;
}
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
}
}
+ ctc_clear_busy(ch->netdev);
return rc;
}
-
+
/**
* Interface API for upper network layers
*****************************************************************************/
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
dev->trans_start = jiffies;
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
rc = 1;
- ctc_clear_busy(dev);
return rc;
}
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf,
return count;
}
-
static void
ctc_netdev_unregister(struct net_device * dev)
{
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
return count;
}
-
static ssize_t
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index fa09440d82e5..38f50b7129a2 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -16,7 +16,7 @@ MODULE_LICENSE("GPL");
fsm_instance *
init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
- int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+ int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
{
int i;
fsm_instance *this;
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index f9a011001eb6..1b8a7e7c34f3 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -110,7 +110,7 @@ extern fsm_instance *
init_fsm(char *name, const char **state_names,
const char **event_names,
int nr_states, int nr_events, const fsm_node *tmpl,
- int tmpl_len, int order);
+ int tmpl_len, gfp_t order);
/**
* Releases an FSM
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 3a0285669adf..38a2441564d7 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.139 $"
+#define VERSION_QETH_H "$Revision: 1.142 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
QETH_MAX_QUEUES,0x103}, \
+ {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+ QETH_MAX_QUEUES,0}, \
{0,0,0,0,0,0,0,0,0}}
#define QETH_REAL_CARD 1
@@ -363,10 +367,22 @@ struct qeth_hdr_layer2 {
__u8 reserved2[16];
} __attribute__ ((packed));
+struct qeth_hdr_osn {
+ __u8 id;
+ __u8 reserved;
+ __u16 seq_no;
+ __u16 reserved2;
+ __u16 control_flags;
+ __u16 pdu_length;
+ __u8 reserved3[18];
+ __u32 ccid;
+} __attribute__ ((packed));
+
struct qeth_hdr {
union {
struct qeth_hdr_layer2 l2;
struct qeth_hdr_layer3 l3;
+ struct qeth_hdr_osn osn;
} hdr;
} __attribute__ ((packed));
@@ -413,6 +429,7 @@ enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER3 = 0x01,
QETH_HEADER_TYPE_LAYER2 = 0x02,
QETH_HEADER_TYPE_TSO = 0x03,
+ QETH_HEADER_TYPE_OSN = 0x04,
};
/* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01
@@ -582,7 +599,6 @@ enum qeth_card_states {
* Protocol versions
*/
enum qeth_prot_versions {
- QETH_PROT_SNA = 0x0001,
QETH_PROT_IPV4 = 0x0004,
QETH_PROT_IPV6 = 0x0006,
};
@@ -686,6 +702,7 @@ struct qeth_seqno {
__u32 pdu_hdr;
__u32 pdu_hdr_ack;
__u16 ipa;
+ __u32 pkt_seqno;
};
struct qeth_reply {
@@ -760,6 +777,11 @@ enum qeth_threads {
QETH_RECOVER_THREAD = 2,
};
+struct qeth_osn_info {
+ int (*assist_cb)(struct net_device *dev, void *data);
+ int (*data_cb)(struct sk_buff *skb);
+};
+
struct qeth_card {
struct list_head list;
enum qeth_card_states state;
@@ -802,6 +824,7 @@ struct qeth_card {
int use_hard_stop;
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
unsigned short,void *,void *,unsigned);
+ struct qeth_osn_info osn_info;
};
struct qeth_card_list_struct {
@@ -848,6 +871,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
"on interface %s", QETH_CARD_IFNAME(card));
return -ENOMEM;
}
+ kfree_skb(*skb);
*skb = new_skb;
}
return 0;
@@ -914,10 +938,12 @@ qeth_get_hlen(__u8 link_type)
static inline unsigned short
qeth_get_netdev_flags(struct qeth_card *card)
{
- if (card->options.layer2)
+ if (card->options.layer2 &&
+ (card->info.type == QETH_CARD_TYPE_OSAE))
return 0;
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
+ case QETH_CARD_TYPE_OSN:
return IFF_NOARP;
#ifdef CONFIG_QETH_IPV6
default:
@@ -954,9 +980,10 @@ static inline int
qeth_get_max_mtu_for_card(int cardtype)
{
switch (cardtype) {
+
case QETH_CARD_TYPE_UNKNOWN:
- return 61440;
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
return 61440;
case QETH_CARD_TYPE_IQD:
return 57344;
@@ -1002,6 +1029,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu)
case QETH_CARD_TYPE_IQD:
return ((mtu >= 576) &&
(mtu <= card->info.max_mtu + 4096 - 32));
+ case QETH_CARD_TYPE_OSN:
case QETH_CARD_TYPE_UNKNOWN:
default:
return 1;
@@ -1013,6 +1041,7 @@ qeth_get_arphdr_type(int cardtype, int linktype)
{
switch (cardtype) {
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
switch (linktype) {
case QETH_LINK_TYPE_LANE_TR:
case QETH_LINK_TYPE_HSTR:
@@ -1172,7 +1201,7 @@ extern int
qeth_realloc_buffer_pool(struct qeth_card *, int);
extern int
-qeth_set_large_send(struct qeth_card *);
+qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
extern void
qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
@@ -1180,4 +1209,16 @@ qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
extern void
qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+extern int
+qeth_osn_assist(struct net_device *, void *, int);
+
+extern int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *));
+
+extern void
+qeth_osn_deregister(struct net_device *);
+
#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index 5c9a51ce91b6..c0b4c8d82c45 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,7 +12,7 @@
#ifndef __QETH_FS_H__
#define __QETH_FS_H__
-#define VERSION_QETH_FS_H "$Revision: 1.9 $"
+#define VERSION_QETH_FS_H "$Revision: 1.10 $"
extern const char *VERSION_QETH_PROC_C;
extern const char *VERSION_QETH_SYS_C;
@@ -43,6 +43,12 @@ extern void
qeth_remove_device_attributes(struct device *dev);
extern int
+qeth_create_device_attributes_osn(struct device *dev);
+
+extern void
+qeth_remove_device_attributes_osn(struct device *dev);
+
+extern int
qeth_create_driver_attributes(void);
extern void
@@ -108,6 +114,8 @@ qeth_get_cardname(struct qeth_card *card)
return " OSD Express";
case QETH_CARD_TYPE_IQD:
return " HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return " OSN QDIO";
default:
return " unknown";
}
@@ -153,6 +161,8 @@ qeth_get_cardname_short(struct qeth_card *card)
}
case QETH_CARD_TYPE_IQD:
return "HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return "OSN";
default:
return "unknown";
}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 8f4d2999af8e..692003c9f896 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
+ * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $
*
* 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,14 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
- return;
-}
#include <linux/config.h>
#include <linux/module.h>
@@ -80,7 +72,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -204,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum)
{
struct qeth_notify_list_struct *n_entry;
-
/*check first if entry already exists*/
spin_lock(&qeth_notify_lock);
list_for_each_entry(n_entry, &qeth_notify_list, list) {
@@ -519,7 +510,7 @@ static int
__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
{
struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
- int rc = 0;
+ int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag;
QETH_DBF_TEXT(setup, 3, "setoffl");
@@ -531,11 +522,13 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
CARD_BUS_ID(card));
return -ERESTARTSYS;
}
- if ((rc = ccw_device_set_offline(CARD_DDEV(card))) ||
- (rc = ccw_device_set_offline(CARD_WDEV(card))) ||
- (rc = ccw_device_set_offline(CARD_RDEV(card)))) {
+ rc = ccw_device_set_offline(CARD_DDEV(card));
+ rc2 = ccw_device_set_offline(CARD_WDEV(card));
+ rc3 = ccw_device_set_offline(CARD_RDEV(card));
+ if (!rc)
+ rc = (rc2) ? rc2 : rc3;
+ if (rc)
QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
- }
if (recover_flag == CARD_STATE_UP)
card->state = CARD_STATE_RECOVER;
qeth_notify_processes();
@@ -1030,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card)
card->options.fake_broadcast = 0;
card->options.add_hhlen = DEFAULT_ADD_HHLEN;
card->options.fake_ll = 0;
- card->options.layer2 = 0;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ card->options.layer2 = 1;
+ else
+ card->options.layer2 = 0;
}
/**
@@ -1054,6 +1050,7 @@ qeth_setup_card(struct qeth_card *card)
spin_lock_init(&card->vlanlock);
card->vlangrp = NULL;
#endif
+ spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock);
card->thread_start_mask = 0;
@@ -1118,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "detcdtyp");
+ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+ card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
while (known_devices[i][4]) {
if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
(CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
card->info.type = known_devices[i][4];
+ card->qdio.no_out_queues = known_devices[i][8];
+ card->info.is_multicast_different = known_devices[i][9];
if (is_1920_device(card)) {
PRINT_INFO("Priority Queueing not able "
"due to hardware limitations!\n");
card->qdio.no_out_queues = 1;
card->qdio.default_out_queue = 0;
- } else {
- card->qdio.no_out_queues = known_devices[i][8];
- }
- card->info.is_multicast_different = known_devices[i][9];
+ }
return 0;
}
i++;
@@ -1154,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev)
if (!get_device(dev))
return -ENODEV;
+ QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+
card = qeth_alloc_card();
if (!card) {
put_device(dev);
@@ -1163,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev)
card->read.ccwdev = gdev->cdev[0];
card->write.ccwdev = gdev->cdev[1];
card->data.ccwdev = gdev->cdev[2];
-
- if ((rc = qeth_setup_card(card))){
- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- put_device(dev);
- qeth_free_card(card);
- return rc;
- }
gdev->dev.driver_data = card;
card->gdev = gdev;
gdev->cdev[0]->handler = qeth_irq;
gdev->cdev[1]->handler = qeth_irq;
gdev->cdev[2]->handler = qeth_irq;
- rc = qeth_create_device_attributes(dev);
- if (rc) {
+ if ((rc = qeth_determine_card_type(card))){
+ PRINT_WARN("%s: not a valid card type\n", __func__);
+ QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ put_device(dev);
+ qeth_free_card(card);
+ return rc;
+ }
+ if ((rc = qeth_setup_card(card))){
+ QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
put_device(dev);
qeth_free_card(card);
return rc;
}
- if ((rc = qeth_determine_card_type(card))){
- PRINT_WARN("%s: not a valid card type\n", __func__);
- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ rc = qeth_create_device_attributes(dev);
+ if (rc) {
put_device(dev);
qeth_free_card(card);
return rc;
@@ -1634,16 +1633,6 @@ qeth_cmd_timeout(unsigned long data)
spin_unlock_irqrestore(&reply->card->lock, flags);
}
-static void
-qeth_reset_ip_addresses(struct qeth_card *card)
-{
- QETH_DBF_TEXT(trace, 2, "rstipadd");
-
- qeth_clear_ip_list(card, 0, 1);
- /* this function will also schedule the SET_IP_THREAD */
- qeth_set_multicast_list(card->dev);
-}
-
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
@@ -1672,10 +1661,11 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
"IP address reset.\n",
QETH_CARD_IFNAME(card),
card->info.chpid);
- card->lan_online = 1;
netif_carrier_on(card->dev);
- qeth_reset_ip_addresses(card);
+ qeth_schedule_recovery(card);
return NULL;
+ case IPA_CMD_MODCCID:
+ return cmd;
case IPA_CMD_REGISTER_LOCAL_ADDR:
QETH_DBF_TEXT(trace,3, "irla");
break;
@@ -1737,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
cmd = qeth_check_ipa_data(card, iob);
if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
goto out;
+ /*in case of OSN : check if cmd is set */
+ if (card->info.type == QETH_CARD_TYPE_OSN &&
+ cmd &&
+ cmd->hdr.command != IPA_CMD_STARTLAN &&
+ card->osn_info.assist_cb != NULL) {
+ card->osn_info.assist_cb(card->dev, cmd);
+ goto out;
+ }
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
@@ -1753,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
keep_reply = reply->callback(card,
reply,
(unsigned long)cmd);
- }
- else
+ } else
keep_reply = reply->callback(card,
reply,
(unsigned long)iob);
@@ -1784,6 +1781,24 @@ out:
qeth_release_buffer(channel,iob);
}
+static inline void
+qeth_prepare_control_data(struct qeth_card *card, int len,
+struct qeth_cmd_buffer *iob)
+{
+ qeth_setup_ccw(&card->write,iob->data,len);
+ iob->callback = qeth_release_buffer;
+
+ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.trans_hdr++;
+ memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.pdu_hdr++;
+ memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+ QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+
static int
qeth_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob,
@@ -1794,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
{
int rc;
unsigned long flags;
- struct qeth_reply *reply;
+ struct qeth_reply *reply = NULL;
struct timer_list timer;
QETH_DBF_TEXT(trace, 2, "sendctl");
- qeth_setup_ccw(&card->write,iob->data,len);
-
- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.trans_hdr++;
-
- memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.pdu_hdr++;
- memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
- iob->callback = qeth_release_buffer;
-
reply = qeth_alloc_reply(card);
if (!reply) {
PRINT_WARN("Could no alloc qeth_reply!\n");
@@ -1826,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len,
init_timer(&timer);
timer.function = qeth_cmd_timeout;
timer.data = (unsigned long) reply;
- if (IS_IPA(iob->data))
- timer.expires = jiffies + QETH_IPA_TIMEOUT;
- else
- timer.expires = jiffies + QETH_TIMEOUT;
init_waitqueue_head(&reply->wait_q);
spin_lock_irqsave(&card->lock, flags);
list_add_tail(&reply->list, &card->cmd_waiter_list);
@@ -1837,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
wait_event(card->wait_q,
atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ if (IS_IPA(iob->data))
+ timer.expires = jiffies + QETH_IPA_TIMEOUT;
+ else
+ timer.expires = jiffies + QETH_TIMEOUT;
QETH_DBF_TEXT(trace, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1864,6 +1867,62 @@ qeth_send_control_data(struct qeth_card *card, int len,
}
static int
+qeth_osn_send_control_data(struct qeth_card *card, int len,
+ struct qeth_cmd_buffer *iob)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+ wait_event(card->wait_q,
+ atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ QETH_DBF_TEXT(trace, 6, "osnoirqp");
+ spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+ rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+ (addr_t) iob, 0, 0);
+ spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+ if (rc){
+ PRINT_WARN("qeth_osn_send_control_data: "
+ "ccw_device_start rc = %i\n", rc);
+ QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ qeth_release_buffer(iob->channel, iob);
+ atomic_set(&card->write.irq_pending, 0);
+ wake_up(&card->wait_q);
+ }
+ return rc;
+}
+
+static inline void
+qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ char prot_type)
+{
+ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+ memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+
+static int
+qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ int data_len)
+{
+ u16 s1, s2;
+
+QETH_DBF_TEXT(trace,4,"osndipa");
+
+ qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+ s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+ s2 = (u16)data_len;
+ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+ return qeth_osn_send_control_data(card, s1, iob);
+}
+
+static int
qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int (*reply_cb)
(struct qeth_card *,struct qeth_reply*, unsigned long),
@@ -1874,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
QETH_DBF_TEXT(trace,4,"sendipa");
- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
-
- memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-
+ qeth_prepare_ipa_cmd(card,iob,prot_type);
rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
reply_cb, reply_param);
return rc;
@@ -2026,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card)
*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
(__u8) card->info.portno;
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
@@ -2116,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
}
static inline struct sk_buff *
-qeth_get_skb(unsigned int length)
+qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
{
struct sk_buff* skb;
+ int add_len;
+
+ add_len = 0;
+ if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+ add_len = sizeof(struct qeth_hdr);
#ifdef CONFIG_QETH_VLAN
- if ((skb = dev_alloc_skb(length + VLAN_HLEN)))
- skb_reserve(skb, VLAN_HLEN);
-#else
- skb = dev_alloc_skb(length);
+ else
+ add_len = VLAN_HLEN;
#endif
+ skb = dev_alloc_skb(length + add_len);
+ if (skb && add_len)
+ skb_reserve(skb, add_len);
return skb;
}
@@ -2154,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
offset += sizeof(struct qeth_hdr);
if (card->options.layer2)
- skb_len = (*hdr)->hdr.l2.pkt_length;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ skb_len = (*hdr)->hdr.osn.pdu_length;
+ else
+ skb_len = (*hdr)->hdr.l2.pkt_length;
else
skb_len = (*hdr)->hdr.l3.length;
@@ -2162,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
return NULL;
if (card->options.fake_ll){
if(card->dev->type == ARPHRD_IEEE802_TR){
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
} else {
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
}
- } else if (!(skb = qeth_get_skb(skb_len)))
+ } else if (!(skb = qeth_get_skb(skb_len, *hdr)))
goto no_mem;
data_ptr = element->addr + offset;
while (skb_len) {
@@ -2395,6 +2463,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
skb_pull(skb, VLAN_HLEN);
}
#endif
+ *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
return vlan_id;
}
@@ -2468,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
- else
+ else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
qeth_rebuild_skb(card, skb, hdr);
+ else { /*in case of OSN*/
+ skb_push(skb, sizeof(struct qeth_hdr));
+ memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+ }
/* is device UP ? */
if (!(card->dev->flags & IFF_UP)){
dev_kfree_skb_any(skb);
@@ -2480,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card,
vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
else
#endif
- rxrc = netif_rx(skb);
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ rxrc = card->osn_info.data_cb(skb);
+ else
+ rxrc = netif_rx(skb);
card->dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += skb->len;
@@ -2759,11 +2835,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
queue->card->perf_stats.outbound_do_qdio_start_time;
#endif
if (rc){
- QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
- "returned error (%i) on device %s.",
- rc, CARD_DDEV_ID(queue->card));
QETH_DBF_TEXT(trace, 2, "flushbuf");
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
queue->card->stats.tx_errors += count;
/* this must not happen under normal circumstances. if it
* happens something is really wrong -> recover */
@@ -2909,11 +2983,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
QETH_DBF_TEXT(trace, 6, "qdouhdl");
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
- QETH_DBF_SPRINTF(trace, 2, "On device %s: "
- "received active check "
- "condition (0x%08x).",
- CARD_BUS_ID(card), status);
- QETH_DBF_TEXT(trace, 2, "chkcond");
+ QETH_DBF_TEXT(trace, 2, "achkcond");
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "%08x", status);
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -3027,7 +3098,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card)
return -ENOMEM;
}
for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
- ptr = (void *) __get_free_page(GFP_KERNEL);
+ ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
if (!ptr) {
while (j > 0)
free_page((unsigned long)
@@ -3071,7 +3142,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
if (card->qdio.state == QETH_QDIO_ALLOCATED)
return 0;
- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL);
+ card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+ GFP_KERNEL|GFP_DMA);
if (!card->qdio.in_q)
return - ENOMEM;
QETH_DBF_TEXT(setup, 2, "inq");
@@ -3096,7 +3168,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
}
for (i = 0; i < card->qdio.no_out_queues; ++i){
card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
- GFP_KERNEL);
+ GFP_KERNEL|GFP_DMA);
if (!card->qdio.out_qs[i]){
while (i > 0)
kfree(card->qdio.out_qs[--i]);
@@ -3169,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card)
INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
/* outbound */
- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
}
static int
@@ -3356,26 +3426,32 @@ qeth_halt_channel(struct qeth_channel *channel)
static int
qeth_halt_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"haltchs");
- if ((rc = qeth_halt_channel(&card->read)))
- return rc;
- if ((rc = qeth_halt_channel(&card->write)))
- return rc;
- return qeth_halt_channel(&card->data);
+ rc1 = qeth_halt_channel(&card->read);
+ rc2 = qeth_halt_channel(&card->write);
+ rc3 = qeth_halt_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
qeth_clear_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"clearchs");
- if ((rc = qeth_clear_channel(&card->read)))
- return rc;
- if ((rc = qeth_clear_channel(&card->write)))
- return rc;
- return qeth_clear_channel(&card->data);
+ rc1 = qeth_clear_channel(&card->read);
+ rc2 = qeth_clear_channel(&card->write);
+ rc3 = qeth_clear_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
@@ -3445,23 +3521,23 @@ qeth_mpc_initialize(struct qeth_card *card)
}
if ((rc = qeth_cm_enable(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_cm_setup(card))){
QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_enable(card))){
QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_setup(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_alloc_qdio_buffers(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_qdio_establish(card))){
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -3479,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card)
return 0;
out_qdio:
- qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
return rc;
}
@@ -3504,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
case QETH_CARD_TYPE_IQD:
dev = alloc_netdev(0, "hsi%d", ether_setup);
break;
+ case QETH_CARD_TYPE_OSN:
+ dev = alloc_netdev(0, "osn%d", ether_setup);
+ break;
default:
dev = alloc_etherdev(0);
}
@@ -3668,7 +3747,8 @@ qeth_open(struct net_device *dev)
if (card->state != CARD_STATE_SOFTSETUP)
return -ENODEV;
- if ( (card->options.layer2) &&
+ if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+ (card->options.layer2) &&
(!card->info.layer2_mac_registered)) {
QETH_DBF_TEXT(trace,4,"nomacadr");
return -EPERM;
@@ -3706,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return cast_type;
+
if (skb->dst && skb->dst->neighbour){
cast_type = skb->dst->neighbour->type;
if ((cast_type == RTN_BROADCAST) ||
@@ -3795,12 +3878,19 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
+ int rc = 0;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
-
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ *hdr = (struct qeth_hdr *)(*skb)->data;
+ return rc;
+ }
+ rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+ if (rc)
+ return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -4251,7 +4341,8 @@ out:
}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
+ struct sk_buff *skb, int elems)
{
int elements_needed = 0;
@@ -4261,9 +4352,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
if (elements_needed == 0 )
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
+ "IP packet (Number=%d / Length=%d). Discarded.\n",
+ (elements_needed+elems), skb->len);
return 0;
}
return elements_needed;
@@ -4275,7 +4367,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
int ipv = 0;
int cast_type;
struct qeth_qdio_out_q *queue;
- struct qeth_hdr *hdr;
+ struct qeth_hdr *hdr = NULL;
int elements_needed = 0;
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
@@ -4298,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
}
}
}
+ if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+ (skb->protocol == htons(ETH_P_IPV6))) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
cast_type = qeth_get_cast_type(card, skb);
- if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+ if ((cast_type == RTN_BROADCAST) &&
+ (card->info.broadcast_capable == 0)){
card->stats.tx_dropped++;
card->stats.tx_errors++;
dev_kfree_skb_any(skb);
@@ -4327,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
return rc;
}
- qeth_fill_header(card, hdr, skb, ipv, cast_type);
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ qeth_fill_header(card, hdr, skb, ipv, cast_type);
}
if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -4337,9 +4436,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
return -EINVAL;
}
} else {
- elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
- if (!elements_needed)
+ int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+ elements_needed);
+ if (!elems)
return -EINVAL;
+ elements_needed += elems;
}
if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -4386,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
case MII_BMCR: /* Basic mode control register */
rc = BMCR_FULLDPLX;
if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+ (card->info.link_type != QETH_LINK_TYPE_OSN) &&
(card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
rc |= BMCR_SPEED100;
break;
@@ -4504,7 +4606,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
QETH_DBF_TEXT(trace,3,"arpstnoe");
- /* TODO: really not supported by GuestLAN? */
+ /*
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan)
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4681,14 +4787,6 @@ qeth_arp_query(struct qeth_card *card, char *udata)
QETH_DBF_TEXT(trace,3,"arpquery");
- /*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
- /*if (card->info.guestlan)
- return -EOPNOTSUPP; */
if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
IPA_ARP_PROCESSING)) {
PRINT_WARN("ARP processing not supported "
@@ -4894,10 +4992,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
QETH_DBF_TEXT(trace,3,"arpadent");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4937,10 +5034,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry
QETH_DBF_TEXT(trace,3,"arprment");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4978,11 +5074,10 @@ qeth_arp_flush_cache(struct qeth_card *card)
QETH_DBF_TEXT(trace,3,"arpflush");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -5016,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
(card->state != CARD_STATE_SOFTSETUP))
return -ENODEV;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return -EPERM;
+
switch (cmd){
case SIOC_QETH_ARP_SET_NO_ENTRIES:
if ( !capable(CAP_NET_ADMIN) ||
@@ -5206,7 +5304,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
if (!card->vlangrp)
return;
rcu_read_lock();
- in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
+ in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
if (!in_dev)
goto out;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -5341,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev)
{
struct qeth_card *card = (struct qeth_card *) dev->priv;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return ;
+
QETH_DBF_TEXT(trace,3,"setmulti");
qeth_delete_mc_addresses(card);
qeth_add_multicast_ipv4(card);
@@ -5382,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot)
return addr;
}
+int
+qeth_osn_assist(struct net_device *dev,
+ void *data,
+ int data_len)
+{
+ struct qeth_cmd_buffer *iob;
+ struct qeth_card *card;
+ int rc;
+
+ QETH_DBF_TEXT(trace, 2, "osnsdmc");
+ if (!dev)
+ return -ENODEV;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return -ENODEV;
+ if ((card->state != CARD_STATE_UP) &&
+ (card->state != CARD_STATE_SOFTSETUP))
+ return -ENODEV;
+ iob = qeth_wait_for_buffer(&card->write);
+ memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+ rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+ return rc;
+}
+
+static struct net_device *
+qeth_netdev_by_devno(unsigned char *read_dev_no)
+{
+ struct qeth_card *card;
+ struct net_device *ndev;
+ unsigned char *readno;
+ __u16 temp_dev_no, card_dev_no;
+ char *endp;
+ unsigned long flags;
+
+ ndev = NULL;
+ memcpy(&temp_dev_no, read_dev_no, 2);
+ read_lock_irqsave(&qeth_card_list.rwlock, flags);
+ list_for_each_entry(card, &qeth_card_list.list, list) {
+ readno = CARD_RDEV_ID(card);
+ readno += (strlen(readno) - 4);
+ card_dev_no = simple_strtoul(readno, &endp, 16);
+ if (card_dev_no == temp_dev_no) {
+ ndev = card->dev;
+ break;
+ }
+ }
+ read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+ return ndev;
+}
+
+int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **dev,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *))
+{
+ struct qeth_card * card;
+
+ QETH_DBF_TEXT(trace, 2, "osnreg");
+ *dev = qeth_netdev_by_devno(read_dev_no);
+ if (*dev == NULL)
+ return -ENODEV;
+ card = (struct qeth_card *)(*dev)->priv;
+ if (!card)
+ return -ENODEV;
+ if ((assist_cb == NULL) || (data_cb == NULL))
+ return -EINVAL;
+ card->osn_info.assist_cb = assist_cb;
+ card->osn_info.data_cb = data_cb;
+ return 0;
+}
+
+void
+qeth_osn_deregister(struct net_device * dev)
+{
+ struct qeth_card *card;
+
+ QETH_DBF_TEXT(trace, 2, "osndereg");
+ if (!dev)
+ return;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return;
+ card->osn_info.assist_cb = NULL;
+ card->osn_info.data_cb = NULL;
+ return;
+}
+
static void
qeth_delete_mc_addresses(struct qeth_card *card)
{
@@ -5712,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
QETH_DBF_TEXT(trace, 3, "setmcLY3");
return -EOPNOTSUPP;
}
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ PRINT_WARN("Setting MAC address on %s is not supported.\n",
+ dev->name);
+ QETH_DBF_TEXT(trace, 3, "setmcOSN");
+ return -EOPNOTSUPP;
+ }
QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
@@ -6088,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev)
qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
dev->addr_len = OSA_ADDR_LEN;
dev->mtu = card->info.initial_mtu;
-
- SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
SET_MODULE_OWNER(dev);
return 0;
}
@@ -6107,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card)
QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
} else {
if (card->info.type == QETH_CARD_TYPE_IQD)
+ /*FIXME:why do we have same values for dis and ena for osae??? */
card->info.func_level =
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
else
@@ -6136,7 +6331,7 @@ retry:
ccw_device_set_online(CARD_WDEV(card));
ccw_device_set_online(CARD_DDEV(card));
}
- rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE);
+ rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
if (rc == -ERESTARTSYS) {
QETH_DBF_TEXT(setup, 2, "break1");
return rc;
@@ -6188,8 +6383,8 @@ retry:
card->dev = qeth_get_netdevice(card->info.type,
card->info.link_type);
if (!card->dev){
- qeth_qdio_clear_card(card, card->info.type ==
- QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type !=
+ QETH_CARD_TYPE_IQD);
rc = -ENODEV;
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
goto out;
@@ -6476,6 +6671,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+ /* Disable IPV6 support hard coded for Hipersockets */
+ if(card->info.type == QETH_CARD_TYPE_IQD)
+ card->options.ipa4.supported_funcs &= ~IPA_IPV6;
} else {
#ifdef CONFIG_QETH_IPV6
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
@@ -7038,14 +7236,16 @@ qeth_setrouting_v6(struct qeth_card *card)
}
int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
{
int rc = 0;
- if (card->dev == NULL)
+ if (card->dev == NULL) {
+ card->options.large_send = type;
return 0;
-
+ }
netif_stop_queue(card->dev);
+ card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,7 +7266,6 @@ qeth_set_large_send(struct qeth_card *card)
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
break;
}
-
netif_wake_queue(card->dev);
return rc;
}
@@ -7092,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card)
return rc;
} else
card->lan_online = 1;
+ if (card->info.type==QETH_CARD_TYPE_OSN)
+ goto out;
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7263,7 +7464,8 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_stop(card->dev);
} else {
rtnl_lock();
@@ -7445,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(setup ,2, "startag");
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_open(card->dev);
} else {
rtnl_lock();
@@ -7477,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
static void qeth_make_parameters_consistent(struct qeth_card *card)
{
- if (card->options.layer2) {
- if (card->info.type == QETH_CARD_TYPE_IQD) {
- PRINT_ERR("Device %s does not support " \
- "layer 2 functionality. " \
- "Ignoring layer2 option.\n",CARD_BUS_ID(card));
- }
- IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ if (card->options.layer2 == 0)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_ERR("Device %s does not support layer 2 functionality." \
+ " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+ card->options.layer2 = 0;
+ return;
+ }
+ IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#ifdef CONFIG_QETH_IPV6
- IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#endif
- IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
- QETH_CHECKSUM_DEFAULT,
- "Checksumming options are");
- IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
- QETH_TR_BROADCAST_ALLRINGS,
- "Broadcast mode options are");
- IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
- QETH_TR_MACADDR_NONCANONICAL,
- "Canonical MAC addr options are");
- IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
- "Broadcast faking options are");
- IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
- DEFAULT_ADD_HHLEN,"Option add_hhlen is");
- IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
- }
+ IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+ QETH_CHECKSUM_DEFAULT,
+ "Checksumming options are");
+ IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+ QETH_TR_BROADCAST_ALLRINGS,
+ "Broadcast mode options are");
+ IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+ QETH_TR_MACADDR_NONCANONICAL,
+ "Canonical MAC addr options are");
+ IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+ "Broadcast faking options are");
+ IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+ DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+ IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
}
@@ -7533,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
return -EIO;
}
- if (card->options.layer2)
- qeth_make_parameters_consistent(card);
+ qeth_make_parameters_consistent(card);
if ((rc = qeth_hardsetup_card(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
@@ -7593,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev)
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+ {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
{},
};
MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -7730,7 +7936,7 @@ qeth_arp_constructor(struct neighbour *neigh)
goto out;
rcu_read_lock();
- in_dev = rcu_dereference(__in_dev_get(dev));
+ in_dev = __in_dev_get_rcu(dev);
if (in_dev == NULL) {
rcu_read_unlock();
return -EINVAL;
@@ -8120,20 +8326,22 @@ static struct notifier_block qeth_ip6_notifier = {
#endif
static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+__qeth_reboot_event_card(struct device *dev, void *data)
{
-
- struct device *entry;
struct qeth_card *card;
- down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices,
- driver_list) {
- card = (struct qeth_card *) entry->driver_data;
- qeth_clear_ip_list(card, 0, 0);
- qeth_qdio_clear_card(card, 0);
- }
- up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
+ card = (struct qeth_card *) dev->driver_data;
+ qeth_clear_ip_list(card, 0, 0);
+ qeth_qdio_clear_card(card, 0);
+ return 0;
+}
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+
+ driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ __qeth_reboot_event_card);
return NOTIFY_DONE;
}
@@ -8255,7 +8463,6 @@ qeth_init(void)
{
int rc=0;
- qeth_eyecatcher();
PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
version, VERSION_QETH_C, VERSION_QETH_H,
VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
@@ -8336,7 +8543,9 @@ again:
printk("qeth: removed\n");
}
-EXPORT_SYMBOL(qeth_eyecatcher);
+EXPORT_SYMBOL(qeth_osn_register);
+EXPORT_SYMBOL(qeth_osn_deregister);
+EXPORT_SYMBOL(qeth_osn_assist);
module_init(qeth_init);
module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index f685ecc7da99..30e053d3cac2 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,7 +11,7 @@
#include <asm/cio.h>
#include "qeth_mpc.h"
-const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
+const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $";
unsigned char IDX_ACTIVATE_READ[]={
0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
@@ -138,7 +138,9 @@ unsigned char IPA_PDU_HEADER[]={
sizeof(struct qeth_ipa_cmd)%256,
0x00,
sizeof(struct qeth_ipa_cmd)/256,
- sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+ sizeof(struct qeth_ipa_cmd)%256,
+ 0x05,
+ 0x77,0x77,0x77,0x77,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x01,0x00,
sizeof(struct qeth_ipa_cmd)/256,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 3d916b5c5d09..7edc5f1fc0d2 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[];
/* IP Assist related definitions */
/*****************************************************************************/
#define IPA_CMD_INITIATOR_HOST 0x00
-#define IPA_CMD_INITIATOR_HYDRA 0x01
+#define IPA_CMD_INITIATOR_OSA 0x01
+#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
+#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
#define IPA_CMD_PRIM_VERSION_NO 0x01
enum qeth_card_types {
QETH_CARD_TYPE_UNKNOWN = 0,
QETH_CARD_TYPE_OSAE = 10,
QETH_CARD_TYPE_IQD = 1234,
+ QETH_CARD_TYPE_OSN = 11,
};
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -61,6 +64,7 @@ enum qeth_link_types {
QETH_LINK_TYPE_FAST_ETH = 0x01,
QETH_LINK_TYPE_HSTR = 0x02,
QETH_LINK_TYPE_GBIT_ETH = 0x03,
+ QETH_LINK_TYPE_OSN = 0x04,
QETH_LINK_TYPE_10GBIT_ETH = 0x10,
QETH_LINK_TYPE_LANE_ETH100 = 0x81,
QETH_LINK_TYPE_LANE_TR = 0x82,
@@ -111,6 +115,9 @@ enum qeth_ipa_cmds {
IPA_CMD_DELGMAC = 0x24,
IPA_CMD_SETVLAN = 0x25,
IPA_CMD_DELVLAN = 0x26,
+ IPA_CMD_SETCCID = 0x41,
+ IPA_CMD_DELCCID = 0x42,
+ IPA_CMD_MODCCID = 0x43,
IPA_CMD_SETIP = 0xb1,
IPA_CMD_DELIP = 0xb7,
IPA_CMD_QIPASSIST = 0xb2,
@@ -437,8 +444,9 @@ enum qeth_ipa_arp_return_codes {
#define QETH_ARP_DATA_SIZE 3968
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
-#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
-
+#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+ (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+
/*****************************************************************************/
/* END OF IP Assist related definitions */
/*****************************************************************************/
@@ -483,6 +491,7 @@ extern unsigned char ULP_ENABLE[];
/* Layer 2 defintions */
#define QETH_PROT_LAYER2 0x08
#define QETH_PROT_TCPIP 0x03
+#define QETH_PROT_OSN2 0x0a
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 04719196fd20..f2ccfea8fdb8 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
#define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry *qeth_procfile;
+static int
+qeth_procfile_seq_match(struct device *dev, void *data)
+{
+ return 1;
+}
+
static void *
qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- if (*offset == 0)
+ nr = *offset;
+ if (nr == 0)
return SEQ_START_TOKEN;
- /* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
- if (++i == *offset)
- return next_card;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL,
+ NULL, qeth_procfile_seq_match);
- return NULL;
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *next_card = NULL;
- struct list_head *current_card;
+ struct device *prev, *next;
if (it == SEQ_START_TOKEN) {
- next_card = qeth_ccwgroup_driver.driver.devices.next;
- if (next_card->next == next_card) /* list empty */
- return NULL;
- (*offset)++;
- } else {
- current_card = (struct list_head *)it;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- next_card = current_card->next;
- (*offset)++;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ NULL, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
-
- return next_card;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ prev, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static inline const char *
@@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it)
"-------------- ---- ------ ---------- ---- "
"---- ----- -----\n");
} else {
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
CARD_RDEV_ID(card),
@@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile;
static void *
qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev = NULL;
+ int nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
struct device *device;
struct qeth_card *card;
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
CARD_RDEV_ID(card),
@@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile;
static void *
qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* TODO: finish this */
@@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
* output driver settings then;
* else output setting for respective card
*/
+
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- /* TODO: finish this */
- /*
- * maybe SEQ_SATRT_TOKEN can be returned for offset 0
- * output driver settings then;
- * else output setting for respective card
- */
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
* output driver settings then;
* else output setting for respective card
*/
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
return 0;
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 98bedb0cb387..f91a02db5743 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
/*****************************************************************************/
/* */
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c
if (!card)
return -EINVAL;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+ return -EPERM;
+ }
if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) ||
- (card->info.type != QETH_CARD_TYPE_OSAE))
+ (card->state != CARD_STATE_RECOVER)))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
@@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
if (!card)
return -EINVAL;
-
tmp = strsep((char **) &buf, "\n");
-
if (!strcmp(tmp, "no")){
type = QETH_LARGE_SEND_NO;
} else if (!strcmp(tmp, "EDDP")) {
@@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
}
if (card->options.large_send == type)
return count;
- card->options.large_send = type;
- if ((rc = qeth_set_large_send(card)))
+ if ((rc = qeth_set_large_send(card, type)))
return rc;
-
return count;
}
@@ -938,6 +937,19 @@ static struct attribute_group qeth_device_attr_group = {
.attrs = (struct attribute **)qeth_device_attrs,
};
+static struct device_attribute * qeth_osn_device_attrs[] = {
+ &dev_attr_state,
+ &dev_attr_chpid,
+ &dev_attr_if_name,
+ &dev_attr_card_type,
+ &dev_attr_buffer_count,
+ &dev_attr_recover,
+ NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+ .attrs = (struct attribute **)qeth_osn_device_attrs,
+};
#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_id = { \
@@ -1668,7 +1680,12 @@ int
qeth_create_device_attributes(struct device *dev)
{
int ret;
+ struct qeth_card *card = dev->driver_data;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_create_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
return ret;
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1694,6 +1711,12 @@ qeth_create_device_attributes(struct device *dev)
void
qeth_remove_device_attributes(struct device *dev)
{
+ struct qeth_card *card = dev->driver_data;
+
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_remove_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 5bb255e02acc..4191fd9d4d11 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -240,7 +240,7 @@ s390_revalidate_registers(struct mci *mci)
* Floating point control register can't be restored.
* Task will be terminated.
*/
- asm volatile ("lfpc 0(%0)" : : "a" (&zero));
+ asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
kill_task = 1;
}
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile
index fc145307a7d4..d6a78f1a2f16 100644
--- a/drivers/s390/scsi/Makefile
+++ b/drivers/s390/scsi/Makefile
@@ -3,7 +3,7 @@
#
zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
- zfcp_fsf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
+ zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
zfcp_sysfs_unit.o zfcp_sysfs_driver.o
obj-$(CONFIG_ZFCP) += zfcp.o
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index e17b4d58a9f6..cab098556b44 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -122,95 +122,6 @@ _zfcp_hex_dump(char *addr, int count)
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
-static inline int
-zfcp_fsf_req_is_scsi_cmnd(struct zfcp_fsf_req *fsf_req)
-{
- return ((fsf_req->fsf_command == FSF_QTCB_FCP_CMND) &&
- !(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT));
-}
-
-void
-zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req,
- void *add_data, int add_length)
-{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- struct scsi_cmnd *scsi_cmnd;
- int level = 3;
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->dbf_lock, flags);
- if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) {
- scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd;
- debug_text_event(adapter->cmd_dbf, level, "fsferror");
- debug_text_event(adapter->cmd_dbf, level, text);
- debug_event(adapter->cmd_dbf, level, &fsf_req,
- sizeof (unsigned long));
- debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no,
- sizeof (u32));
- debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
- sizeof (unsigned long));
- debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
- min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
- for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH)
- debug_event(adapter->cmd_dbf,
- level,
- (char *) add_data + i,
- min(ZFCP_CMD_DBF_LENGTH, add_length - i));
- }
- spin_unlock_irqrestore(&adapter->dbf_lock, flags);
-}
-
-/* XXX additionally log unit if available */
-/* ---> introduce new parameter for unit, see 2.4 code */
-void
-zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd)
-{
- struct zfcp_adapter *adapter;
- union zfcp_req_data *req_data;
- struct zfcp_fsf_req *fsf_req;
- int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5);
- unsigned long flags;
-
- adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0];
- req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble;
- fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL);
- spin_lock_irqsave(&adapter->dbf_lock, flags);
- debug_text_event(adapter->cmd_dbf, level, "hostbyte");
- debug_text_event(adapter->cmd_dbf, level, text);
- debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32));
- debug_event(adapter->cmd_dbf, level, &scsi_cmnd,
- sizeof (unsigned long));
- debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd,
- min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len));
- if (likely(fsf_req)) {
- debug_event(adapter->cmd_dbf, level, &fsf_req,
- sizeof (unsigned long));
- debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no,
- sizeof (u32));
- } else {
- debug_text_event(adapter->cmd_dbf, level, "");
- debug_text_event(adapter->cmd_dbf, level, "");
- }
- spin_unlock_irqrestore(&adapter->dbf_lock, flags);
-}
-
-void
-zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
- struct fsf_status_read_buffer *status_buffer, int length)
-{
- int level = 1;
- int i;
-
- debug_text_event(adapter->in_els_dbf, level, text);
- debug_event(adapter->in_els_dbf, level, &status_buffer->d_id, 8);
- for (i = 0; i < length; i += ZFCP_IN_ELS_DBF_LENGTH)
- debug_event(adapter->in_els_dbf,
- level,
- (char *) status_buffer->payload + i,
- min(ZFCP_IN_ELS_DBF_LENGTH, length - i));
-}
-
/**
* zfcp_device_setup - setup function
* @str: pointer to parameter string
@@ -922,7 +833,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit)
}
static void *
-zfcp_mempool_alloc(unsigned int __nocast gfp_mask, void *size)
+zfcp_mempool_alloc(gfp_t gfp_mask, void *size)
{
return kmalloc((size_t) size, gfp_mask);
}
@@ -1017,81 +928,6 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
mempool_destroy(adapter->pool.data_gid_pn);
}
-/**
- * zfcp_adapter_debug_register - registers debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be registered
- * return: -ENOMEM on error, 0 otherwise
- */
-int
-zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
-{
- char dbf_name[20];
-
- /* debug feature area which records SCSI command failures (hostbyte) */
- spin_lock_init(&adapter->dbf_lock);
-
- sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s",
- zfcp_get_busid_by_adapter(adapter));
- adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX,
- ZFCP_CMD_DBF_AREAS,
- ZFCP_CMD_DBF_LENGTH);
- debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view);
- debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL);
-
- /* debug feature area which records SCSI command aborts */
- sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s",
- zfcp_get_busid_by_adapter(adapter));
- adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX,
- ZFCP_ABORT_DBF_AREAS,
- ZFCP_ABORT_DBF_LENGTH);
- debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view);
- debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL);
-
- /* debug feature area which records incoming ELS commands */
- sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s",
- zfcp_get_busid_by_adapter(adapter));
- adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX,
- ZFCP_IN_ELS_DBF_AREAS,
- ZFCP_IN_ELS_DBF_LENGTH);
- debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view);
- debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL);
-
- /* debug feature area which records erp events */
- sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s",
- zfcp_get_busid_by_adapter(adapter));
- adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX,
- ZFCP_ERP_DBF_AREAS,
- ZFCP_ERP_DBF_LENGTH);
- debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
- debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL);
-
- if (!(adapter->cmd_dbf && adapter->abort_dbf &&
- adapter->in_els_dbf && adapter->erp_dbf)) {
- zfcp_adapter_debug_unregister(adapter);
- return -ENOMEM;
- }
-
- return 0;
-
-}
-
-/**
- * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be unregistered
- */
-void
-zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
-{
- debug_unregister(adapter->abort_dbf);
- debug_unregister(adapter->cmd_dbf);
- debug_unregister(adapter->erp_dbf);
- debug_unregister(adapter->in_els_dbf);
- adapter->abort_dbf = NULL;
- adapter->cmd_dbf = NULL;
- adapter->erp_dbf = NULL;
- adapter->in_els_dbf = NULL;
-}
-
void
zfcp_dummy_release(struct device *dev)
{
@@ -1299,13 +1135,10 @@ struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
u32 d_id)
{
- struct zfcp_port *port, *tmp_port;
+ struct zfcp_port *port;
int check_wwpn;
- scsi_id_t scsi_id;
- int found;
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
-
/*
* check that there is no port with this WWPN already in list
*/
@@ -1368,7 +1201,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
} else {
snprintf(port->sysfs_device.bus_id,
BUS_ID_SIZE, "0x%016llx", wwpn);
- port->sysfs_device.parent = &adapter->ccw_device->dev;
+ port->sysfs_device.parent = &adapter->ccw_device->dev;
}
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
@@ -1388,24 +1221,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
zfcp_port_get(port);
- scsi_id = 1;
- found = 0;
write_lock_irq(&zfcp_data.config_lock);
- list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
- if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
- &tmp_port->status))
- continue;
- if (tmp_port->scsi_id != scsi_id) {
- found = 1;
- break;
- }
- scsi_id++;
- }
- port->scsi_id = scsi_id;
- if (found)
- list_add_tail(&port->list, &tmp_port->list);
- else
- list_add_tail(&port->list, &adapter->port_list_head);
+ 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)
@@ -1427,6 +1244,9 @@ zfcp_port_dequeue(struct zfcp_port *port)
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);
zfcp_sysfs_port_remove_files(&port->sysfs_device,
atomic_read(&port->status));
@@ -1478,10 +1298,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
/* see FC-FS */
no_entries = (fcp_rscn_head->payload_len / 4);
- zfcp_in_els_dbf_event(adapter, "##rscn", status_buffer,
- fcp_rscn_head->payload_len);
-
- debug_text_event(adapter->erp_dbf, 1, "unsol_els_rscn:");
for (i = 1; i < no_entries; i++) {
/* skip head and start with 1st element */
fcp_rscn_element++;
@@ -1513,8 +1329,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
(ZFCP_STATUS_PORT_DID_DID, &port->status)) {
ZFCP_LOG_INFO("incoming RSCN, trying to open "
"port 0x%016Lx\n", port->wwpn);
- debug_text_event(adapter->erp_dbf, 1,
- "unsol_els_rscnu:");
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED);
continue;
@@ -1540,8 +1354,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
*/
ZFCP_LOG_INFO("incoming RSCN, trying to open "
"port 0x%016Lx\n", port->wwpn);
- debug_text_event(adapter->erp_dbf, 1,
- "unsol_els_rscnk:");
zfcp_test_link(port);
}
}
@@ -1557,8 +1369,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
struct zfcp_port *port;
unsigned long flags;
- zfcp_in_els_dbf_event(adapter, "##plogi", status_buffer, 28);
-
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &adapter->port_list_head, list) {
if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn))
@@ -1572,8 +1382,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
status_buffer->d_id,
zfcp_get_busid_by_adapter(adapter));
} else {
- debug_text_event(adapter->erp_dbf, 1, "unsol_els_plogi:");
- debug_event(adapter->erp_dbf, 1, &els_logi->nport_wwn, 8);
zfcp_erp_port_forced_reopen(port, 0);
}
}
@@ -1586,8 +1394,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
struct zfcp_port *port;
unsigned long flags;
- zfcp_in_els_dbf_event(adapter, "##logo", status_buffer, 16);
-
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &adapter->port_list_head, list) {
if (port->wwpn == els_logo->nport_wwpn)
@@ -1601,8 +1407,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
status_buffer->d_id,
zfcp_get_busid_by_adapter(adapter));
} else {
- debug_text_event(adapter->erp_dbf, 1, "unsol_els_logo:");
- debug_event(adapter->erp_dbf, 1, &els_logo->nport_wwpn, 8);
zfcp_erp_port_forced_reopen(port, 0);
}
}
@@ -1611,7 +1415,6 @@ static void
zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter,
struct fsf_status_read_buffer *status_buffer)
{
- zfcp_in_els_dbf_event(adapter, "##undef", status_buffer, 24);
ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x "
"for adapter %s\n", *(u32 *) (status_buffer->payload),
zfcp_get_busid_by_adapter(adapter));
@@ -1625,10 +1428,11 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
u32 els_type;
struct zfcp_adapter *adapter;
- status_buffer = fsf_req->data.status_read.buffer;
+ status_buffer = (struct fsf_status_read_buffer *) fsf_req->data;
els_type = *(u32 *) (status_buffer->payload);
adapter = fsf_req->adapter;
+ zfcp_san_dbf_event_incoming_els(fsf_req);
if (els_type == LS_PLOGI)
zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
else if (els_type == LS_LOGO)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
new file mode 100644
index 000000000000..826fb3b00605
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -0,0 +1,995 @@
+/*
+ *
+ * linux/drivers/s390/scsi/zfcp_dbf.c
+ *
+ * FCP adapter driver for IBM eServer zSeries
+ *
+ * Debugging facilities
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define ZFCP_DBF_REVISION "$Revision$"
+
+#include <asm/debug.h>
+#include <linux/ctype.h>
+#include "zfcp_ext.h"
+
+static u32 dbfsize = 4;
+
+module_param(dbfsize, uint, 0400);
+MODULE_PARM_DESC(dbfsize,
+ "number of pages for each debug feature area (default 4)");
+
+#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
+
+static inline int
+zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
+{
+ unsigned long long sec;
+ struct timespec xtime;
+ int len = 0;
+
+ stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+ sec = stck >> 12;
+ do_div(sec, 1000000);
+ xtime.tv_sec = sec;
+ stck -= (sec * 1000000) << 12;
+ xtime.tv_nsec = ((stck * 1000) >> 12);
+ len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
+ label, xtime.tv_sec, xtime.tv_nsec);
+
+ return len;
+}
+
+static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
+{
+ int len = 0, i;
+
+ len += sprintf(out_buf + len, "%-24s", label);
+ for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
+ len += sprintf(out_buf + len, "%c", tag[i]);
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+static int
+zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
+{
+ va_list arg;
+ int len = 0;
+
+ len += sprintf(out_buf + len, "%-24s", label);
+ va_start(arg, format);
+ len += vsprintf(out_buf + len, format, arg);
+ va_end(arg);
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+static int
+zfcp_dbf_view_dump(char *out_buf, const char *label,
+ char *buffer, int buflen, int offset, int total_size)
+{
+ int len = 0;
+
+ if (offset == 0)
+ len += sprintf(out_buf + len, "%-24s ", label);
+
+ while (buflen--) {
+ if (offset > 0) {
+ if ((offset % 32) == 0)
+ len += sprintf(out_buf + len, "\n%-24c ", ' ');
+ else if ((offset % 4) == 0)
+ len += sprintf(out_buf + len, " ");
+ }
+ len += sprintf(out_buf + len, "%02x", *buffer++);
+ if (++offset == total_size) {
+ len += sprintf(out_buf + len, "\n");
+ break;
+ }
+ }
+
+ if (total_size == 0)
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+static inline int
+zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
+ debug_entry_t * entry, char *out_buf)
+{
+ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
+ int len = 0;
+
+ if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
+ len += zfcp_dbf_stck(out_buf + len, "timestamp",
+ entry->id.stck);
+ len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
+ entry->id.fields.cpuid);
+ } else {
+ len += zfcp_dbf_view_dump(out_buf + len, NULL,
+ dump->data,
+ dump->size,
+ dump->offset, dump->total_size);
+ if ((dump->offset + dump->size) == dump->total_size)
+ len += sprintf(out_buf + len, "\n");
+ }
+
+ return len;
+}
+
+inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+{
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_qtcb *qtcb = fsf_req->qtcb;
+ union fsf_prot_status_qual *prot_status_qual =
+ &qtcb->prefix.prot_status_qual;
+ union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
+ struct scsi_cmnd *scsi_cmnd;
+ struct zfcp_port *port;
+ struct zfcp_unit *unit;
+ struct zfcp_send_els *send_els;
+ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ struct zfcp_hba_dbf_record_response *response = &rec->type.response;
+ int level;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+ strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
+
+ if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+ (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+ strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE);
+ level = 1;
+ } else if (qtcb->header.fsf_status != FSF_GOOD) {
+ strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE);
+ level = 1;
+ } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
+ (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+ strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
+ level = 4;
+ } else if ((prot_status_qual->doubleword[0] != 0) ||
+ (prot_status_qual->doubleword[1] != 0) ||
+ (fsf_status_qual->doubleword[0] != 0) ||
+ (fsf_status_qual->doubleword[1] != 0)) {
+ strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE);
+ level = 3;
+ } else {
+ strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
+ level = 6;
+ }
+
+ response->fsf_command = fsf_req->fsf_command;
+ response->fsf_reqid = (unsigned long)fsf_req;
+ response->fsf_seqno = fsf_req->seq_no;
+ response->fsf_issued = fsf_req->issued;
+ response->fsf_prot_status = qtcb->prefix.prot_status;
+ response->fsf_status = qtcb->header.fsf_status;
+ memcpy(response->fsf_prot_status_qual,
+ prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE);
+ memcpy(response->fsf_status_qual,
+ fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
+ response->fsf_req_status = fsf_req->status;
+ response->sbal_first = fsf_req->sbal_first;
+ response->sbal_curr = fsf_req->sbal_curr;
+ response->sbal_last = fsf_req->sbal_last;
+ response->pool = fsf_req->pool != NULL;
+ response->erp_action = (unsigned long)fsf_req->erp_action;
+
+ switch (fsf_req->fsf_command) {
+ case FSF_QTCB_FCP_CMND:
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ break;
+ scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+ if (scsi_cmnd != NULL) {
+ response->data.send_fcp.scsi_cmnd
+ = (unsigned long)scsi_cmnd;
+ response->data.send_fcp.scsi_serial
+ = scsi_cmnd->serial_number;
+ }
+ break;
+
+ case FSF_QTCB_OPEN_PORT_WITH_DID:
+ case FSF_QTCB_CLOSE_PORT:
+ case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+ port = (struct zfcp_port *)fsf_req->data;
+ response->data.port.wwpn = port->wwpn;
+ response->data.port.d_id = port->d_id;
+ response->data.port.port_handle = qtcb->header.port_handle;
+ break;
+
+ case FSF_QTCB_OPEN_LUN:
+ case FSF_QTCB_CLOSE_LUN:
+ unit = (struct zfcp_unit *)fsf_req->data;
+ port = unit->port;
+ response->data.unit.wwpn = port->wwpn;
+ response->data.unit.fcp_lun = unit->fcp_lun;
+ response->data.unit.port_handle = qtcb->header.port_handle;
+ response->data.unit.lun_handle = qtcb->header.lun_handle;
+ break;
+
+ case FSF_QTCB_SEND_ELS:
+ send_els = (struct zfcp_send_els *)fsf_req->data;
+ response->data.send_els.d_id = qtcb->bottom.support.d_id;
+ response->data.send_els.ls_code = send_els->ls_code >> 24;
+ break;
+
+ case FSF_QTCB_ABORT_FCP_CMND:
+ case FSF_QTCB_SEND_GENERIC:
+ case FSF_QTCB_EXCHANGE_CONFIG_DATA:
+ case FSF_QTCB_EXCHANGE_PORT_DATA:
+ case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+ case FSF_QTCB_UPLOAD_CONTROL_FILE:
+ break;
+ }
+
+ debug_event(adapter->hba_dbf, level,
+ rec, sizeof(struct zfcp_hba_dbf_record));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+inline void
+zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+ struct fsf_status_read_buffer *status_buffer)
+{
+ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+ strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
+ strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
+
+ rec->type.status.failed = adapter->status_read_failed;
+ if (status_buffer != NULL) {
+ rec->type.status.status_type = status_buffer->status_type;
+ rec->type.status.status_subtype = status_buffer->status_subtype;
+ memcpy(&rec->type.status.queue_designator,
+ &status_buffer->queue_designator,
+ sizeof(struct fsf_queue_designator));
+
+ switch (status_buffer->status_type) {
+ case FSF_STATUS_READ_SENSE_DATA_AVAIL:
+ rec->type.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
+ break;
+
+ case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
+ rec->type.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
+ break;
+
+ case FSF_STATUS_READ_LINK_DOWN:
+ switch (status_buffer->status_subtype) {
+ case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ case FSF_STATUS_READ_SUB_FDISC_FAILED:
+ rec->type.status.payload_size =
+ sizeof(struct fsf_link_down_info);
+ }
+ break;
+
+ case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+ rec->type.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
+ break;
+ }
+ memcpy(&rec->type.status.payload,
+ &status_buffer->payload, rec->type.status.payload_size);
+ }
+
+ debug_event(adapter->hba_dbf, 2,
+ rec, sizeof(struct zfcp_hba_dbf_record));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+inline void
+zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
+ unsigned int qdio_error, unsigned int siga_error,
+ int sbal_index, int sbal_count)
+{
+ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+ strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
+ rec->type.qdio.status = status;
+ rec->type.qdio.qdio_error = qdio_error;
+ rec->type.qdio.siga_error = siga_error;
+ rec->type.qdio.sbal_index = sbal_index;
+ rec->type.qdio.sbal_count = sbal_count;
+ debug_event(adapter->hba_dbf, 0,
+ rec, sizeof(struct zfcp_hba_dbf_record));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
+
+static inline int
+zfcp_hba_dbf_view_response(char *out_buf,
+ struct zfcp_hba_dbf_record_response *rec)
+{
+ int len = 0;
+
+ len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
+ rec->fsf_command);
+ len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+ rec->fsf_reqid);
+ len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+ rec->fsf_seqno);
+ len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+ len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
+ rec->fsf_prot_status);
+ len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
+ rec->fsf_status);
+ len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
+ rec->fsf_prot_status_qual,
+ FSF_PROT_STATUS_QUAL_SIZE,
+ 0, FSF_PROT_STATUS_QUAL_SIZE);
+ len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
+ rec->fsf_status_qual,
+ FSF_STATUS_QUALIFIER_SIZE,
+ 0, FSF_STATUS_QUALIFIER_SIZE);
+ len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
+ rec->fsf_req_status);
+ len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
+ rec->sbal_first);
+ len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
+ rec->sbal_curr);
+ len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
+ rec->sbal_last);
+ len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
+
+ switch (rec->fsf_command) {
+ case FSF_QTCB_FCP_CMND:
+ if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ break;
+ len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+ rec->data.send_fcp.scsi_cmnd);
+ len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+ rec->data.send_fcp.scsi_serial);
+ break;
+
+ case FSF_QTCB_OPEN_PORT_WITH_DID:
+ case FSF_QTCB_CLOSE_PORT:
+ case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+ len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+ rec->data.port.wwpn);
+ len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+ rec->data.port.d_id);
+ len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+ rec->data.port.port_handle);
+ break;
+
+ case FSF_QTCB_OPEN_LUN:
+ case FSF_QTCB_CLOSE_LUN:
+ len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+ rec->data.unit.wwpn);
+ len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
+ rec->data.unit.fcp_lun);
+ len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+ rec->data.unit.port_handle);
+ len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
+ rec->data.unit.lun_handle);
+ break;
+
+ case FSF_QTCB_SEND_ELS:
+ len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+ rec->data.send_els.d_id);
+ len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+ rec->data.send_els.ls_code);
+ break;
+
+ case FSF_QTCB_ABORT_FCP_CMND:
+ case FSF_QTCB_SEND_GENERIC:
+ case FSF_QTCB_EXCHANGE_CONFIG_DATA:
+ case FSF_QTCB_EXCHANGE_PORT_DATA:
+ case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
+ case FSF_QTCB_UPLOAD_CONTROL_FILE:
+ break;
+ }
+
+ return len;
+}
+
+static inline int
+zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
+{
+ int len = 0;
+
+ len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
+ len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
+ rec->status_type);
+ len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
+ rec->status_subtype);
+ len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
+ (char *)&rec->queue_designator,
+ sizeof(struct fsf_queue_designator),
+ 0, sizeof(struct fsf_queue_designator));
+ len += zfcp_dbf_view_dump(out_buf + len, "payload",
+ (char *)&rec->payload,
+ rec->payload_size, 0, rec->payload_size);
+
+ return len;
+}
+
+static inline int
+zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
+{
+ int len = 0;
+
+ len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
+ len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
+ rec->qdio_error);
+ len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
+ rec->siga_error);
+ len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
+ rec->sbal_index);
+ len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
+ rec->sbal_count);
+
+ return len;
+}
+
+static int
+zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
+ char *out_buf, const char *in_buf)
+{
+ struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
+ int len = 0;
+
+ if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+ len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+ if (isalpha(rec->tag2[0]))
+ len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+ if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
+ len += zfcp_hba_dbf_view_response(out_buf + len,
+ &rec->type.response);
+ else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
+ len += zfcp_hba_dbf_view_status(out_buf + len,
+ &rec->type.status);
+ else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
+ len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
+
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+struct debug_view zfcp_hba_dbf_view = {
+ "structured",
+ NULL,
+ &zfcp_dbf_view_header,
+ &zfcp_hba_dbf_view_format,
+ NULL,
+ NULL
+};
+
+inline void
+_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
+ u32 s_id, u32 d_id, void *buffer, int buflen)
+{
+ struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
+ struct zfcp_port *port = send_ct->port;
+ struct zfcp_adapter *adapter = port->adapter;
+ struct ct_hdr *header = (struct ct_hdr *)buffer;
+ struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+ struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+ memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+ strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+ rec->fsf_reqid = (unsigned long)fsf_req;
+ rec->fsf_seqno = fsf_req->seq_no;
+ rec->s_id = s_id;
+ rec->d_id = d_id;
+ if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+ ct->type.request.cmd_req_code = header->cmd_rsp_code;
+ ct->type.request.revision = header->revision;
+ ct->type.request.gs_type = header->gs_type;
+ ct->type.request.gs_subtype = header->gs_subtype;
+ ct->type.request.options = header->options;
+ ct->type.request.max_res_size = header->max_res_size;
+ } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+ ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
+ ct->type.response.revision = header->revision;
+ ct->type.response.reason_code = header->reason_code;
+ ct->type.response.reason_code_expl = header->reason_code_expl;
+ ct->type.response.vendor_unique = header->vendor_unique;
+ }
+ ct->payload_size =
+ min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
+ memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
+ debug_event(adapter->san_dbf, 3,
+ rec, sizeof(struct zfcp_san_dbf_record));
+ spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+}
+
+inline 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;
+
+ _zfcp_san_dbf_event_common_ct("octc", fsf_req,
+ fc_host_port_id(adapter->scsi_host),
+ port->d_id, zfcp_sg_to_address(ct->req),
+ ct->req->length);
+}
+
+inline 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;
+
+ _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
+ fc_host_port_id(adapter->scsi_host),
+ zfcp_sg_to_address(ct->resp),
+ ct->resp->length);
+}
+
+static inline void
+_zfcp_san_dbf_event_common_els(const char *tag, int level,
+ struct zfcp_fsf_req *fsf_req, u32 s_id,
+ u32 d_id, u8 ls_code, void *buffer, int buflen)
+{
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+ unsigned long flags;
+ int offset = 0;
+
+ spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+ do {
+ memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+ if (offset == 0) {
+ strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+ rec->fsf_reqid = (unsigned long)fsf_req;
+ rec->fsf_seqno = fsf_req->seq_no;
+ rec->s_id = s_id;
+ rec->d_id = d_id;
+ rec->type.els.ls_code = ls_code;
+ buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
+ rec->type.els.payload_size = buflen;
+ memcpy(rec->type.els.payload,
+ buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
+ offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
+ } else {
+ strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+ dump->total_size = buflen;
+ dump->offset = offset;
+ dump->size = min(buflen - offset,
+ (int)sizeof(struct zfcp_san_dbf_record)
+ - (int)sizeof(struct zfcp_dbf_dump));
+ memcpy(dump->data, buffer + offset, dump->size);
+ offset += dump->size;
+ }
+ debug_event(adapter->san_dbf, level,
+ rec, sizeof(struct zfcp_san_dbf_record));
+ } while (offset < buflen);
+ spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+}
+
+inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+{
+ struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+ _zfcp_san_dbf_event_common_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);
+}
+
+inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+{
+ struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+ _zfcp_san_dbf_event_common_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),
+ els->resp->length);
+}
+
+inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+{
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_status_read_buffer *status_buffer =
+ (struct fsf_status_read_buffer *)fsf_req->data;
+ int length = (int)status_buffer->length -
+ (int)((void *)&status_buffer->payload - (void *)status_buffer);
+
+ _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
+ fc_host_port_id(adapter->scsi_host),
+ *(u8 *) status_buffer->payload,
+ (void *)status_buffer->payload, length);
+}
+
+static int
+zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
+ char *out_buf, const char *in_buf)
+{
+ struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
+ char *buffer = NULL;
+ int buflen = 0, total = 0;
+ int len = 0;
+
+ if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+ len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+ len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+ rec->fsf_reqid);
+ len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+ rec->fsf_seqno);
+ len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
+ len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
+
+ if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
+ rec->type.ct.type.request.cmd_req_code);
+ len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+ rec->type.ct.type.request.revision);
+ len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
+ rec->type.ct.type.request.gs_type);
+ len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
+ rec->type.ct.type.request.gs_subtype);
+ len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
+ rec->type.ct.type.request.options);
+ len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
+ rec->type.ct.type.request.max_res_size);
+ total = rec->type.ct.payload_size;
+ buffer = rec->type.ct.payload;
+ buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+ } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
+ rec->type.ct.type.response.cmd_rsp_code);
+ len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+ rec->type.ct.type.response.revision);
+ len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
+ rec->type.ct.type.response.reason_code);
+ len +=
+ zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
+ rec->type.ct.type.response.reason_code_expl);
+ len +=
+ zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
+ rec->type.ct.type.response.vendor_unique);
+ total = rec->type.ct.payload_size;
+ buffer = rec->type.ct.payload;
+ buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+ } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
+ strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
+ strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+ rec->type.els.ls_code);
+ total = rec->type.els.payload_size;
+ buffer = rec->type.els.payload;
+ buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
+ }
+
+ len += zfcp_dbf_view_dump(out_buf + len, "payload",
+ buffer, buflen, 0, total);
+
+ if (buflen == total)
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+struct debug_view zfcp_san_dbf_view = {
+ "structured",
+ NULL,
+ &zfcp_dbf_view_header,
+ &zfcp_san_dbf_view_format,
+ NULL,
+ NULL
+};
+
+static inline void
+_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ struct zfcp_adapter *adapter,
+ struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *new_fsf_req)
+{
+ struct zfcp_fsf_req *fsf_req =
+ (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
+ struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
+ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+ unsigned long flags;
+ struct fcp_rsp_iu *fcp_rsp;
+ char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
+ int offset = 0, buflen = 0;
+
+ spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+ do {
+ memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
+ if (offset == 0) {
+ strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+ strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
+ if (scsi_cmnd->device) {
+ rec->scsi_id = scsi_cmnd->device->id;
+ rec->scsi_lun = scsi_cmnd->device->lun;
+ }
+ rec->scsi_result = scsi_cmnd->result;
+ rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+ rec->scsi_serial = scsi_cmnd->serial_number;
+ memcpy(rec->scsi_opcode,
+ &scsi_cmnd->cmnd,
+ min((int)scsi_cmnd->cmd_len,
+ ZFCP_DBF_SCSI_OPCODE));
+ rec->scsi_retries = scsi_cmnd->retries;
+ rec->scsi_allowed = scsi_cmnd->allowed;
+ if (fsf_req != NULL) {
+ fcp_rsp = (struct fcp_rsp_iu *)
+ &(fsf_req->qtcb->bottom.io.fcp_rsp);
+ fcp_rsp_info =
+ zfcp_get_fcp_rsp_info_ptr(fcp_rsp);
+ fcp_sns_info =
+ zfcp_get_fcp_sns_info_ptr(fcp_rsp);
+
+ rec->type.fcp.rsp_validity =
+ fcp_rsp->validity.value;
+ rec->type.fcp.rsp_scsi_status =
+ fcp_rsp->scsi_status;
+ rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
+ if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
+ rec->type.fcp.rsp_code =
+ *(fcp_rsp_info + 3);
+ if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
+ buflen = min((int)fcp_rsp->fcp_sns_len,
+ ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+ rec->type.fcp.sns_info_len = buflen;
+ memcpy(rec->type.fcp.sns_info,
+ fcp_sns_info,
+ min(buflen,
+ ZFCP_DBF_SCSI_FCP_SNS_INFO));
+ offset += min(buflen,
+ ZFCP_DBF_SCSI_FCP_SNS_INFO);
+ }
+
+ rec->fsf_reqid = (unsigned long)fsf_req;
+ rec->fsf_seqno = fsf_req->seq_no;
+ rec->fsf_issued = fsf_req->issued;
+ }
+ if (new_fsf_req != NULL) {
+ rec->type.new_fsf_req.fsf_reqid =
+ (unsigned long)
+ new_fsf_req;
+ rec->type.new_fsf_req.fsf_seqno =
+ new_fsf_req->seq_no;
+ rec->type.new_fsf_req.fsf_issued =
+ new_fsf_req->issued;
+ }
+ } else {
+ strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+ dump->total_size = buflen;
+ dump->offset = offset;
+ dump->size = min(buflen - offset,
+ (int)sizeof(struct
+ zfcp_scsi_dbf_record) -
+ (int)sizeof(struct zfcp_dbf_dump));
+ memcpy(dump->data, fcp_sns_info + offset, dump->size);
+ offset += dump->size;
+ }
+ debug_event(adapter->scsi_dbf, level,
+ rec, sizeof(struct zfcp_scsi_dbf_record));
+ } while (offset < buflen);
+ spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
+}
+
+inline void
+zfcp_scsi_dbf_event_result(const char *tag, int level,
+ struct zfcp_adapter *adapter,
+ struct scsi_cmnd *scsi_cmnd)
+{
+ _zfcp_scsi_dbf_event_common("rslt",
+ tag, level, adapter, scsi_cmnd, NULL);
+}
+
+inline void
+zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
+ struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *new_fsf_req)
+{
+ _zfcp_scsi_dbf_event_common("abrt",
+ tag, 1, adapter, scsi_cmnd, new_fsf_req);
+}
+
+inline void
+zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+ struct scsi_cmnd *scsi_cmnd)
+{
+ struct zfcp_adapter *adapter = unit->port->adapter;
+
+ _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
+ tag, 1, adapter, scsi_cmnd, NULL);
+}
+
+static int
+zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
+ char *out_buf, const char *in_buf)
+{
+ struct zfcp_scsi_dbf_record *rec =
+ (struct zfcp_scsi_dbf_record *)in_buf;
+ int len = 0;
+
+ if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+ len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+ len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+ len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
+ len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
+ rec->scsi_lun);
+ len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
+ rec->scsi_result);
+ len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+ rec->scsi_cmnd);
+ len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+ rec->scsi_serial);
+ len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
+ rec->scsi_opcode,
+ ZFCP_DBF_SCSI_OPCODE,
+ 0, ZFCP_DBF_SCSI_OPCODE);
+ len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
+ rec->scsi_retries);
+ len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
+ rec->scsi_allowed);
+ len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+ rec->fsf_reqid);
+ len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+ rec->fsf_seqno);
+ len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+ if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
+ len +=
+ zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
+ rec->type.fcp.rsp_validity);
+ len +=
+ zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
+ "0x%02x", rec->type.fcp.rsp_scsi_status);
+ len +=
+ zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
+ rec->type.fcp.rsp_resid);
+ len +=
+ zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
+ rec->type.fcp.rsp_code);
+ len +=
+ zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
+ rec->type.fcp.sns_info_len);
+ len +=
+ zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
+ rec->type.fcp.sns_info,
+ min((int)rec->type.fcp.sns_info_len,
+ ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
+ rec->type.fcp.sns_info_len);
+ } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
+ rec->type.new_fsf_req.fsf_reqid);
+ len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
+ rec->type.new_fsf_req.fsf_seqno);
+ len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
+ rec->type.new_fsf_req.fsf_issued);
+ } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
+ (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
+ len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
+ rec->type.new_fsf_req.fsf_reqid);
+ len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
+ rec->type.new_fsf_req.fsf_seqno);
+ len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
+ rec->type.new_fsf_req.fsf_issued);
+ }
+
+ len += sprintf(out_buf + len, "\n");
+
+ return len;
+}
+
+struct debug_view zfcp_scsi_dbf_view = {
+ "structured",
+ NULL,
+ &zfcp_dbf_view_header,
+ &zfcp_scsi_dbf_view_format,
+ NULL,
+ NULL
+};
+
+/**
+ * zfcp_adapter_debug_register - registers debug feature for an adapter
+ * @adapter: pointer to adapter for which debug features should be registered
+ * return: -ENOMEM on error, 0 otherwise
+ */
+int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+{
+ char dbf_name[DEBUG_MAX_NAME_LEN];
+
+ /* debug feature area which records recovery activity */
+ spin_lock_init(&adapter->erp_dbf_lock);
+ sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
+ adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
+ sizeof(struct zfcp_erp_dbf_record));
+ if (!adapter->erp_dbf)
+ goto failed;
+ debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
+ debug_set_level(adapter->erp_dbf, 3);
+
+ /* debug feature area which records HBA (FSF and QDIO) conditions */
+ spin_lock_init(&adapter->hba_dbf_lock);
+ sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
+ adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
+ sizeof(struct zfcp_hba_dbf_record));
+ if (!adapter->hba_dbf)
+ goto failed;
+ debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
+ debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
+ debug_set_level(adapter->hba_dbf, 3);
+
+ /* debug feature area which records SAN command failures and recovery */
+ spin_lock_init(&adapter->san_dbf_lock);
+ sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
+ adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
+ sizeof(struct zfcp_san_dbf_record));
+ if (!adapter->san_dbf)
+ goto failed;
+ debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
+ debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
+ debug_set_level(adapter->san_dbf, 6);
+
+ /* debug feature area which records SCSI command failures and recovery */
+ spin_lock_init(&adapter->scsi_dbf_lock);
+ sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
+ adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
+ sizeof(struct zfcp_scsi_dbf_record));
+ if (!adapter->scsi_dbf)
+ goto failed;
+ debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
+ debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
+ debug_set_level(adapter->scsi_dbf, 3);
+
+ return 0;
+
+ failed:
+ zfcp_adapter_debug_unregister(adapter);
+
+ return -ENOMEM;
+}
+
+/**
+ * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
+ * @adapter: pointer to adapter for which debug features should be unregistered
+ */
+void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+{
+ debug_unregister(adapter->scsi_dbf);
+ debug_unregister(adapter->san_dbf);
+ debug_unregister(adapter->hba_dbf);
+ debug_unregister(adapter->erp_dbf);
+ adapter->scsi_dbf = NULL;
+ adapter->san_dbf = NULL;
+ adapter->hba_dbf = NULL;
+ adapter->erp_dbf = NULL;
+}
+
+#undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 4103b5be7683..d81b737d68cc 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -66,7 +66,7 @@
/********************* GENERAL DEFINES *********************************/
/* zfcp version number, it consists of major, minor, and patch-level number */
-#define ZFCP_VERSION "4.3.0"
+#define ZFCP_VERSION "4.5.0"
/**
* zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -154,13 +154,17 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
+/* Retry 5 times every 2 second, then every minute */
+#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
+#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
+#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
+
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
typedef unsigned long long wwn_t;
-typedef unsigned int fc_id_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;
@@ -281,6 +285,171 @@ struct fcp_logo {
} __attribute__((packed));
/*
+ * DBF stuff
+ */
+#define ZFCP_DBF_TAG_SIZE 4
+
+struct zfcp_dbf_dump {
+ u8 tag[ZFCP_DBF_TAG_SIZE];
+ u32 total_size; /* size of total dump data */
+ u32 offset; /* how much data has being already dumped */
+ u32 size; /* how much data comes with this record */
+ u8 data[]; /* dump data */
+} __attribute__ ((packed));
+
+/* FIXME: to be inflated when reworking the erp dbf */
+struct zfcp_erp_dbf_record {
+ u8 dummy[16];
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_response {
+ u32 fsf_command;
+ u64 fsf_reqid;
+ u32 fsf_seqno;
+ u64 fsf_issued;
+ u32 fsf_prot_status;
+ u32 fsf_status;
+ u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
+ u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+ u32 fsf_req_status;
+ u8 sbal_first;
+ u8 sbal_curr;
+ u8 sbal_last;
+ u8 pool;
+ u64 erp_action;
+ union {
+ struct {
+ u64 scsi_cmnd;
+ u64 scsi_serial;
+ } send_fcp;
+ struct {
+ u64 wwpn;
+ u32 d_id;
+ u32 port_handle;
+ } port;
+ struct {
+ u64 wwpn;
+ u64 fcp_lun;
+ u32 port_handle;
+ u32 lun_handle;
+ } unit;
+ struct {
+ u32 d_id;
+ u8 ls_code;
+ } send_els;
+ } data;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_status {
+ u8 failed;
+ u32 status_type;
+ u32 status_subtype;
+ struct fsf_queue_designator
+ queue_designator;
+ u32 payload_size;
+#define ZFCP_DBF_UNSOL_PAYLOAD 80
+#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32
+#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56
+#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32)
+ u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_qdio {
+ u32 status;
+ u32 qdio_error;
+ u32 siga_error;
+ u8 sbal_index;
+ u8 sbal_count;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record {
+ u8 tag[ZFCP_DBF_TAG_SIZE];
+ u8 tag2[ZFCP_DBF_TAG_SIZE];
+ union {
+ struct zfcp_hba_dbf_record_response response;
+ struct zfcp_hba_dbf_record_status status;
+ struct zfcp_hba_dbf_record_qdio qdio;
+ } type;
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_ct {
+ union {
+ struct {
+ u16 cmd_req_code;
+ u8 revision;
+ u8 gs_type;
+ u8 gs_subtype;
+ u8 options;
+ u16 max_res_size;
+ } request;
+ struct {
+ u16 cmd_rsp_code;
+ u8 revision;
+ u8 reason_code;
+ u8 reason_code_expl;
+ u8 vendor_unique;
+ } response;
+ } type;
+ u32 payload_size;
+#define ZFCP_DBF_CT_PAYLOAD 24
+ u8 payload[ZFCP_DBF_CT_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_els {
+ u8 ls_code;
+ u32 payload_size;
+#define ZFCP_DBF_ELS_PAYLOAD 32
+#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
+ u8 payload[ZFCP_DBF_ELS_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record {
+ u8 tag[ZFCP_DBF_TAG_SIZE];
+ u64 fsf_reqid;
+ u32 fsf_seqno;
+ u32 s_id;
+ u32 d_id;
+ union {
+ struct zfcp_san_dbf_record_ct ct;
+ struct zfcp_san_dbf_record_els els;
+ } type;
+} __attribute__ ((packed));
+
+struct zfcp_scsi_dbf_record {
+ u8 tag[ZFCP_DBF_TAG_SIZE];
+ u8 tag2[ZFCP_DBF_TAG_SIZE];
+ u32 scsi_id;
+ u32 scsi_lun;
+ u32 scsi_result;
+ u64 scsi_cmnd;
+ u64 scsi_serial;
+#define ZFCP_DBF_SCSI_OPCODE 16
+ u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
+ u8 scsi_retries;
+ u8 scsi_allowed;
+ u64 fsf_reqid;
+ u32 fsf_seqno;
+ u64 fsf_issued;
+ union {
+ struct {
+ u64 fsf_reqid;
+ u32 fsf_seqno;
+ u64 fsf_issued;
+ } new_fsf_req;
+ struct {
+ u8 rsp_validity;
+ u8 rsp_scsi_status;
+ u32 rsp_resid;
+ u8 rsp_code;
+#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16
+#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
+ u32 sns_info_len;
+ u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
+ } fcp;
+ } type;
+} __attribute__ ((packed));
+
+/*
* FC-FS stuff
*/
#define R_A_TOV 10 /* seconds */
@@ -339,34 +508,6 @@ struct zfcp_rc_entry {
*/
#define ZFCP_CT_TIMEOUT (3 * R_A_TOV)
-
-/***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/
-
-/* debug feature entries per adapter */
-#define ZFCP_ERP_DBF_INDEX 1
-#define ZFCP_ERP_DBF_AREAS 2
-#define ZFCP_ERP_DBF_LENGTH 16
-#define ZFCP_ERP_DBF_LEVEL 3
-#define ZFCP_ERP_DBF_NAME "zfcperp"
-
-#define ZFCP_CMD_DBF_INDEX 2
-#define ZFCP_CMD_DBF_AREAS 1
-#define ZFCP_CMD_DBF_LENGTH 8
-#define ZFCP_CMD_DBF_LEVEL 3
-#define ZFCP_CMD_DBF_NAME "zfcpcmd"
-
-#define ZFCP_ABORT_DBF_INDEX 2
-#define ZFCP_ABORT_DBF_AREAS 1
-#define ZFCP_ABORT_DBF_LENGTH 8
-#define ZFCP_ABORT_DBF_LEVEL 6
-#define ZFCP_ABORT_DBF_NAME "zfcpabt"
-
-#define ZFCP_IN_ELS_DBF_INDEX 2
-#define ZFCP_IN_ELS_DBF_AREAS 1
-#define ZFCP_IN_ELS_DBF_LENGTH 8
-#define ZFCP_IN_ELS_DBF_LEVEL 6
-#define ZFCP_IN_ELS_DBF_NAME "zfcpels"
-
/******************** LOGGING MACROS AND DEFINES *****************************/
/*
@@ -501,6 +642,7 @@ do { \
#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
#define ZFCP_STATUS_ADAPTER_SCSI_UP \
(ZFCP_STATUS_COMMON_UNBLOCKED | \
@@ -635,45 +777,6 @@ struct zfcp_adapter_mempool {
mempool_t *data_gid_pn;
};
-struct zfcp_exchange_config_data{
-};
-
-struct zfcp_open_port {
- struct zfcp_port *port;
-};
-
-struct zfcp_close_port {
- struct zfcp_port *port;
-};
-
-struct zfcp_open_unit {
- struct zfcp_unit *unit;
-};
-
-struct zfcp_close_unit {
- struct zfcp_unit *unit;
-};
-
-struct zfcp_close_physical_port {
- struct zfcp_port *port;
-};
-
-struct zfcp_send_fcp_command_task {
- struct zfcp_fsf_req *fsf_req;
- struct zfcp_unit *unit;
- struct scsi_cmnd *scsi_cmnd;
- unsigned long start_jiffies;
-};
-
-struct zfcp_send_fcp_command_task_management {
- struct zfcp_unit *unit;
-};
-
-struct zfcp_abort_fcp_command {
- struct zfcp_fsf_req *fsf_req;
- struct zfcp_unit *unit;
-};
-
/*
* header for CT_IU
*/
@@ -702,7 +805,7 @@ struct ct_iu_gid_pn_req {
/* FS_ACC IU and data unit for GID_PN nameserver request */
struct ct_iu_gid_pn_resp {
struct ct_hdr header;
- fc_id_t d_id;
+ u32 d_id;
} __attribute__ ((packed));
typedef void (*zfcp_send_ct_handler_t)(unsigned long);
@@ -768,7 +871,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
struct zfcp_send_els {
struct zfcp_adapter *adapter;
struct zfcp_port *port;
- fc_id_t d_id;
+ u32 d_id;
struct scatterlist *req;
struct scatterlist *resp;
unsigned int req_count;
@@ -781,33 +884,6 @@ struct zfcp_send_els {
int status;
};
-struct zfcp_status_read {
- struct fsf_status_read_buffer *buffer;
-};
-
-struct zfcp_fsf_done {
- struct completion *complete;
- int status;
-};
-
-/* request specific data */
-union zfcp_req_data {
- struct zfcp_exchange_config_data exchange_config_data;
- struct zfcp_open_port open_port;
- struct zfcp_close_port close_port;
- struct zfcp_open_unit open_unit;
- struct zfcp_close_unit close_unit;
- struct zfcp_close_physical_port close_physical_port;
- struct zfcp_send_fcp_command_task send_fcp_command_task;
- struct zfcp_send_fcp_command_task_management
- send_fcp_command_task_management;
- struct zfcp_abort_fcp_command abort_fcp_command;
- struct zfcp_send_ct *send_ct;
- struct zfcp_send_els *send_els;
- struct zfcp_status_read status_read;
- struct fsf_qtcb_bottom_port *port_data;
-};
-
struct zfcp_qdio_queue {
struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
u8 free_index; /* index of next free bfr
@@ -838,21 +914,19 @@ 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 wwnn; /* WWNN */
- wwn_t wwpn; /* WWPN */
- fc_id_t s_id; /* N_Port ID */
wwn_t peer_wwnn; /* P2P peer WWNN */
wwn_t peer_wwpn; /* P2P peer WWPN */
- fc_id_t peer_d_id; /* P2P peer D_ID */
+ u32 peer_d_id; /* P2P peer D_ID */
+ wwn_t physical_wwpn; /* WWPN of physical port */
+ u32 physical_s_id; /* local FC port ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u8 fc_service_class;
u32 fc_topology; /* FC topology */
- u32 fc_link_speed; /* FC interface speed */
u32 hydra_version; /* Hydra version */
u32 fsf_lic_version;
- u32 supported_features;/* of FCP channel */
+ u32 adapter_features; /* FCP channel features */
+ u32 connection_features; /* host connection features */
u32 hardware_version; /* of FCP channel */
- u8 serial_number[32]; /* of hardware */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
unsigned short scsi_host_no; /* Assigned host number */
unsigned char name[9];
@@ -889,11 +963,18 @@ struct zfcp_adapter {
u32 erp_low_mem_count; /* nr of erp actions waiting
for memory */
struct zfcp_port *nameserver_port; /* adapter's nameserver */
- debug_info_t *erp_dbf; /* S/390 debug features */
- debug_info_t *abort_dbf;
- debug_info_t *in_els_dbf;
- debug_info_t *cmd_dbf;
- spinlock_t dbf_lock;
+ debug_info_t *erp_dbf;
+ debug_info_t *hba_dbf;
+ debug_info_t *san_dbf; /* debug feature areas */
+ debug_info_t *scsi_dbf;
+ spinlock_t erp_dbf_lock;
+ spinlock_t hba_dbf_lock;
+ spinlock_t san_dbf_lock;
+ spinlock_t scsi_dbf_lock;
+ struct zfcp_erp_dbf_record erp_dbf_buf;
+ struct zfcp_hba_dbf_record hba_dbf_buf;
+ struct zfcp_san_dbf_record san_dbf_buf;
+ 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 */
@@ -906,6 +987,7 @@ struct zfcp_adapter {
*/
struct zfcp_port {
struct device sysfs_device; /* sysfs device */
+ struct fc_rport *rport; /* rport of fc transport class */
struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -916,10 +998,9 @@ struct zfcp_port {
list */
u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */
- scsi_id_t scsi_id; /* own SCSI ID */
wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */
- fc_id_t d_id; /* D_ID */
+ u32 d_id; /* D_ID */
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
@@ -963,11 +1044,13 @@ struct zfcp_fsf_req {
u32 fsf_command; /* FSF Command copy */
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
- union zfcp_req_data data; /* Info fields of request */
+ unsigned long data; /* private data of request */
struct zfcp_erp_action *erp_action; /* used if this request is
issued on behalf of erp */
mempool_t *pool; /* used if request was alloacted
from emergency pool */
+ unsigned long long issued; /* request sent time (STCK) */
+ struct zfcp_unit *unit;
};
typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 0cf31f7d1c0f..023f4e558ae4 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);
+static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf_statusread(
struct zfcp_erp_action *);
@@ -345,13 +346,13 @@ zfcp_erp_adisc(struct zfcp_port *port)
/* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
without FC-AL-2 capability, so we don't set it */
- adisc->wwpn = adapter->wwpn;
- adisc->wwnn = adapter->wwnn;
- adisc->nport_id = adapter->s_id;
+ adisc->wwpn = fc_host_port_name(adapter->scsi_host);
+ adisc->wwnn = fc_host_node_name(adapter->scsi_host);
+ adisc->nport_id = fc_host_port_id(adapter->scsi_host);
ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
"(wwpn=0x%016Lx, wwnn=0x%016Lx, "
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
- adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
+ adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id);
@@ -404,7 +405,7 @@ zfcp_erp_adisc_handler(unsigned long data)
struct zfcp_send_els *send_els;
struct zfcp_port *port;
struct zfcp_adapter *adapter;
- fc_id_t d_id;
+ u32 d_id;
struct zfcp_ls_adisc_acc *adisc;
send_els = (struct zfcp_send_els *) data;
@@ -435,9 +436,9 @@ zfcp_erp_adisc_handler(unsigned long data)
ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
"0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
- d_id, adapter->s_id, (wwn_t) adisc->wwpn,
- (wwn_t) adisc->wwnn, adisc->hard_nport_id,
- adisc->nport_id);
+ d_id, fc_host_port_id(adapter->scsi_host),
+ (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
+ adisc->hard_nport_id, adisc->nport_id);
/* set wwnn for port */
if (port->wwnn == 0)
@@ -886,7 +887,7 @@ static int
zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
{
int retval = 0;
- struct zfcp_fsf_req *fsf_req;
+ struct zfcp_fsf_req *fsf_req = NULL;
struct zfcp_adapter *adapter = erp_action->adapter;
if (erp_action->fsf_req) {
@@ -896,7 +897,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
if (fsf_req == erp_action->fsf_req)
break;
- if (fsf_req == erp_action->fsf_req) {
+ if (fsf_req && (fsf_req->erp_action == erp_action)) {
/* fsf_req still exists */
debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
debug_event(adapter->erp_dbf, 3, &fsf_req,
@@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
- int retval;
+ int xconfig, xport;
+
+ if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &erp_action->adapter->status)) {
+ zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+ atomic_set(&erp_action->adapter->erp_counter, 0);
+ return ZFCP_ERP_FAILED;
+ }
- /* do 'exchange configuration data' */
- retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
- if (retval == ZFCP_ERP_FAILED)
- return retval;
+ xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
+ xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+ if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
+ return ZFCP_ERP_FAILED;
- /* start the desired number of Status Reads */
- retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
- return retval;
+ return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}
/*
@@ -2291,7 +2297,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status);
ZFCP_LOG_DEBUG("Doing exchange config data\n");
+ write_lock(&adapter->erp_lock);
zfcp_erp_action_to_running(erp_action);
+ write_unlock(&adapter->erp_lock);
zfcp_erp_timeout_init(erp_action);
if (zfcp_fsf_exchange_config_data(erp_action)) {
retval = ZFCP_ERP_FAILED;
@@ -2348,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
return retval;
}
+static int
+zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
+{
+ int retval = ZFCP_ERP_SUCCEEDED;
+ int retries;
+ int sleep;
+ struct zfcp_adapter *adapter = erp_action->adapter;
+
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+ for (retries = 0; ; retries++) {
+ ZFCP_LOG_DEBUG("Doing exchange port data\n");
+ zfcp_erp_action_to_running(erp_action);
+ zfcp_erp_timeout_init(erp_action);
+ if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
+ retval = ZFCP_ERP_FAILED;
+ debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
+ ZFCP_LOG_INFO("error: initiation of exchange of "
+ "port data failed for adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ }
+ debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
+ ZFCP_LOG_DEBUG("Xchange underway\n");
+
+ /*
+ * Why this works:
+ * Both the normal completion handler as well as the timeout
+ * handler will do an 'up' when the 'exchange port data'
+ * request completes or times out. Thus, the signal to go on
+ * won't be lost utilizing this semaphore.
+ * Furthermore, this 'adapter_reopen' action is
+ * guaranteed to be the only action being there (highest action
+ * which prevents other actions from being created).
+ * Resulting from that, the wake signal recognized here
+ * _must_ be the one belonging to the 'exchange port
+ * data' request.
+ */
+ down(&adapter->erp_ready_sem);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange of port data "
+ "for adapter %s timed out\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ }
+
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status))
+ break;
+
+ ZFCP_LOG_DEBUG("host connection still initialising... "
+ "waiting and retrying...\n");
+ /* sleep a little bit before retry */
+ sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
+ ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
+ ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
+ msleep(jiffies_to_msecs(sleep));
+ }
+
+ if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status)) {
+ ZFCP_LOG_INFO("error: exchange of port data for "
+ "adapter %s failed\n",
+ zfcp_get_busid_by_adapter(adapter));
+ retval = ZFCP_ERP_FAILED;
+ }
+
+ return retval;
+}
+
/*
* function:
*
@@ -3194,11 +3272,19 @@ zfcp_erp_action_enqueue(int action,
/* fall through !!! */
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
- if (atomic_test_mask
- (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)
- && port->erp_action.action ==
- ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
- debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp");
+ if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+ &port->status)) {
+ if (port->erp_action.action !=
+ ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
+ ZFCP_LOG_INFO("dropped erp action %i (port "
+ "0x%016Lx, action in use: %i)\n",
+ action, port->wwpn,
+ port->erp_action.action);
+ debug_text_event(adapter->erp_dbf, 4,
+ "pf_actenq_drp");
+ } else
+ debug_text_event(adapter->erp_dbf, 4,
+ "pf_actenq_drpcp");
debug_event(adapter->erp_dbf, 4, &port->wwpn,
sizeof (wwn_t));
goto out;
@@ -3360,13 +3446,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
if ((result == ZFCP_ERP_SUCCEEDED)
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status))
- && (!unit->device))
- scsi_add_device(unit->port->adapter->scsi_host, 0,
- unit->port->scsi_id, unit->scsi_lun);
+ && !unit->device
+ && port->rport)
+ scsi_add_device(port->adapter->scsi_host, 0,
+ port->rport->scsi_target_id,
+ unit->scsi_lun);
zfcp_unit_put(unit);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if ((result == ZFCP_ERP_SUCCEEDED)
+ && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+ &port->status)
+ && !port->rport) {
+ struct fc_rport_identifiers ids;
+ ids.node_name = port->wwnn;
+ ids.port_name = port->wwpn;
+ ids.port_id = port->d_id;
+ ids.roles = FC_RPORT_ROLE_FCP_TARGET;
+ port->rport =
+ fc_remote_port_add(adapter->scsi_host, 0, &ids);
+ if (!port->rport)
+ ZFCP_LOG_NORMAL("failed registration of rport"
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+ port->wwpn);
+ }
zfcp_port_put(port);
break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
@@ -3570,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
struct zfcp_port *port;
unsigned long flags;
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ return;
+
debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 42df7e57eeae..c3782261cb5c 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -96,7 +96,8 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
-extern int zfcp_fsf_exchange_port_data(struct zfcp_adapter *,
+extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
+ struct zfcp_adapter *,
struct fsf_qtcb_bottom_port *);
extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
u32, u32, struct zfcp_sg_list *);
@@ -109,7 +110,6 @@ extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
struct zfcp_erp_action *);
extern int zfcp_fsf_send_els(struct zfcp_send_els *);
-extern int zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *);
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
struct zfcp_unit *,
struct scsi_cmnd *,
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
struct timer_list *);
+extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
+extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;
@@ -180,9 +182,25 @@ extern void zfcp_erp_port_access_changed(struct zfcp_port *);
extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
/******************************** AUX ****************************************/
-extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *,
- void *, int);
-extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *);
-extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *,
- struct fsf_status_read_buffer *, int);
+extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
+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, unsigned int, unsigned int,
+ int, int);
+
+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 *);
+extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
+extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
+
+extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
+ struct scsi_cmnd *);
+extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
+ struct scsi_cmnd *,
+ struct zfcp_fsf_req *);
+extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
+ struct scsi_cmnd *);
+
#endif /* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0d9f20edc490..3b0fc1163f5f 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -59,6 +59,8 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *);
static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
+static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
+ struct fsf_link_down_info *);
static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
@@ -285,51 +287,51 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
{
int retval = 0;
struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_qtcb *qtcb = fsf_req->qtcb;
+ union fsf_prot_status_qual *prot_status_qual =
+ &qtcb->prefix.prot_status_qual;
- ZFCP_LOG_DEBUG("QTCB is at %p\n", fsf_req->qtcb);
+ zfcp_hba_dbf_event_fsf_response(fsf_req);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n",
(unsigned long) fsf_req);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
- zfcp_cmd_dbf_event_fsf("dismiss", fsf_req, NULL, 0);
goto skip_protstatus;
}
/* log additional information provided by FSF (if any) */
- if (unlikely(fsf_req->qtcb->header.log_length)) {
+ if (unlikely(qtcb->header.log_length)) {
/* do not trust them ;-) */
- if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
+ if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
ZFCP_LOG_NORMAL
("bug: ULP (FSF logging) log data starts "
"beyond end of packet header. Ignored. "
"(start=%i, size=%li)\n",
- fsf_req->qtcb->header.log_start,
+ qtcb->header.log_start,
sizeof(struct fsf_qtcb));
goto forget_log;
}
- if ((size_t) (fsf_req->qtcb->header.log_start +
- fsf_req->qtcb->header.log_length)
+ if ((size_t) (qtcb->header.log_start + qtcb->header.log_length)
> sizeof(struct fsf_qtcb)) {
ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
"beyond end of packet header. Ignored. "
"(start=%i, length=%i, size=%li)\n",
- fsf_req->qtcb->header.log_start,
- fsf_req->qtcb->header.log_length,
+ qtcb->header.log_start,
+ qtcb->header.log_length,
sizeof(struct fsf_qtcb));
goto forget_log;
}
ZFCP_LOG_TRACE("ULP log data: \n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (char *) fsf_req->qtcb +
- fsf_req->qtcb->header.log_start,
- fsf_req->qtcb->header.log_length);
+ (char *) qtcb + qtcb->header.log_start,
+ qtcb->header.log_length);
}
forget_log:
/* evaluate FSF Protocol Status */
- switch (fsf_req->qtcb->prefix.prot_status) {
+ switch (qtcb->prefix.prot_status) {
case FSF_PROT_GOOD:
case FSF_PROT_FSF_STATUS_PRESENTED:
@@ -340,14 +342,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
"microcode of version 0x%x, the device driver "
"only supports 0x%x. Aborting.\n",
zfcp_get_busid_by_adapter(adapter),
- fsf_req->qtcb->prefix.prot_status_qual.
- version_error.fsf_version, ZFCP_QTCB_VERSION);
- /* stop operation for this adapter */
- debug_text_exception(adapter->erp_dbf, 0, "prot_ver_err");
+ prot_status_qual->version_error.fsf_version,
+ ZFCP_QTCB_VERSION);
zfcp_erp_adapter_shutdown(adapter, 0);
- zfcp_cmd_dbf_event_fsf("qverserr", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -355,16 +352,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_NORMAL("bug: Sequence number mismatch between "
"driver (0x%x) and adapter %s (0x%x). "
"Restarting all operations on this adapter.\n",
- fsf_req->qtcb->prefix.req_seq_no,
+ qtcb->prefix.req_seq_no,
zfcp_get_busid_by_adapter(adapter),
- fsf_req->qtcb->prefix.prot_status_qual.
- sequence_error.exp_req_seq_no);
- debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err");
- /* restart operation on this adapter */
+ prot_status_qual->sequence_error.exp_req_seq_no);
zfcp_erp_adapter_reopen(adapter, 0);
- zfcp_cmd_dbf_event_fsf("seqnoerr", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -375,116 +366,35 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
"that used on adapter %s. "
"Stopping all operations on this adapter.\n",
zfcp_get_busid_by_adapter(adapter));
- debug_text_exception(adapter->erp_dbf, 0, "prot_unsup_qtcb");
zfcp_erp_adapter_shutdown(adapter, 0);
- zfcp_cmd_dbf_event_fsf("unsqtcbt", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PROT_HOST_CONNECTION_INITIALIZING:
- zfcp_cmd_dbf_event_fsf("hconinit", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&(adapter->status));
- debug_text_event(adapter->erp_dbf, 3, "prot_con_init");
break;
case FSF_PROT_DUPLICATE_REQUEST_ID:
- if (fsf_req->qtcb) {
ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx "
"to the adapter %s is ambiguous. "
- "Stopping all operations on this "
- "adapter.\n",
- *(unsigned long long *)
- (&fsf_req->qtcb->bottom.support.
- req_handle),
- zfcp_get_busid_by_adapter(adapter));
- } else {
- ZFCP_LOG_NORMAL("bug: The request identifier %p "
- "to the adapter %s is ambiguous. "
- "Stopping all operations on this "
- "adapter. "
- "(bug: got this for an unsolicited "
- "status read request)\n",
- fsf_req,
+ "Stopping all operations on this adapter.\n",
+ *(unsigned long long*)
+ (&qtcb->bottom.support.req_handle),
zfcp_get_busid_by_adapter(adapter));
- }
- debug_text_exception(adapter->erp_dbf, 0, "prot_dup_id");
zfcp_erp_adapter_shutdown(adapter, 0);
- zfcp_cmd_dbf_event_fsf("dupreqid", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PROT_LINK_DOWN:
- /*
- * 'test and set' is not atomic here -
- * it's ok as long as calls to our response queue handler
- * (and thus execution of this code here) are serialized
- * by the qdio module
- */
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status)) {
- switch (fsf_req->qtcb->prefix.prot_status_qual.
- locallink_error.code) {
- case FSF_PSQ_LINK_NOLIGHT:
- ZFCP_LOG_INFO("The local link to adapter %s "
- "is down (no light detected).\n",
- zfcp_get_busid_by_adapter(
- adapter));
- break;
- case FSF_PSQ_LINK_WRAPPLUG:
- ZFCP_LOG_INFO("The local link to adapter %s "
- "is down (wrap plug detected).\n",
- zfcp_get_busid_by_adapter(
- adapter));
- break;
- case FSF_PSQ_LINK_NOFCP:
- ZFCP_LOG_INFO("The local link to adapter %s "
- "is down (adjacent node on "
- "link does not support FCP).\n",
- zfcp_get_busid_by_adapter(
- adapter));
- break;
- default:
- ZFCP_LOG_INFO("The local link to adapter %s "
- "is down "
- "(warning: unknown reason "
- "code).\n",
- zfcp_get_busid_by_adapter(
- adapter));
- break;
-
- }
- /*
- * Due to the 'erp failed' flag the adapter won't
- * be recovered but will be just set to 'blocked'
- * state. All subordinary devices will have state
- * 'blocked' and 'erp failed', too.
- * Thus the adapter is still able to provide
- * 'link up' status without being flooded with
- * requests.
- * (note: even 'close port' is not permitted)
- */
- ZFCP_LOG_INFO("Stopping all operations for adapter "
- "%s.\n",
- zfcp_get_busid_by_adapter(adapter));
- atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
- ZFCP_STATUS_COMMON_ERP_FAILED,
- &adapter->status);
- zfcp_erp_adapter_reopen(adapter, 0);
- }
+ zfcp_fsf_link_down_info_eval(adapter,
+ &prot_status_qual->link_down_info);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PROT_REEST_QUEUE:
- debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue");
- ZFCP_LOG_INFO("The local link to adapter with "
+ ZFCP_LOG_NORMAL("The local link to adapter with "
"%s was re-plugged. "
"Re-starting operations on this adapter.\n",
zfcp_get_busid_by_adapter(adapter));
@@ -495,9 +405,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
| ZFCP_STATUS_COMMON_ERP_FAILED);
- zfcp_cmd_dbf_event_fsf("reestque", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -507,12 +414,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
"Restarting all operations on this "
"adapter.\n",
zfcp_get_busid_by_adapter(adapter));
- debug_text_event(adapter->erp_dbf, 0, "prot_err_sta");
- /* restart operation on this adapter */
zfcp_erp_adapter_reopen(adapter, 0);
- zfcp_cmd_dbf_event_fsf("proterrs", fsf_req,
- &fsf_req->qtcb->prefix.prot_status_qual,
- sizeof (union fsf_prot_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -524,11 +426,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
"Stopping all operations on this adapter. "
"(debug info 0x%x).\n",
zfcp_get_busid_by_adapter(adapter),
- fsf_req->qtcb->prefix.prot_status);
- debug_text_event(adapter->erp_dbf, 0, "prot_inval:");
- debug_exception(adapter->erp_dbf, 0,
- &fsf_req->qtcb->prefix.prot_status,
- sizeof (u32));
+ qtcb->prefix.prot_status);
zfcp_erp_adapter_shutdown(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
@@ -568,28 +466,18 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
"(debug info 0x%x).\n",
zfcp_get_busid_by_adapter(fsf_req->adapter),
fsf_req->qtcb->header.fsf_command);
- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
- "fsf_s_unknown");
zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
- zfcp_cmd_dbf_event_fsf("unknownc", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_FCP_RSP_AVAILABLE:
ZFCP_LOG_DEBUG("FCP Sense data will be presented to the "
"SCSI stack.\n");
- debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp");
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus");
zfcp_fsf_fsfstatus_qual_eval(fsf_req);
break;
-
- default:
- break;
}
skip_fsfstatus:
@@ -617,44 +505,28 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_FCP_RSP_AVAILABLE:
- debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp");
break;
case FSF_SQ_RETRY_IF_POSSIBLE:
/* The SCSI-stack may now issue retries or escalate */
- debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry");
- zfcp_cmd_dbf_event_fsf("sqretry", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_COMMAND_ABORTED:
/* Carry the aborted state on to upper layer */
- debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort");
- zfcp_cmd_dbf_event_fsf("sqabort", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_NO_RECOM:
- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
- "fsf_sq_no_rec");
ZFCP_LOG_NORMAL("bug: No recommendation could be given for a"
"problem on the adapter %s "
"Stopping all operations on this adapter. ",
zfcp_get_busid_by_adapter(fsf_req->adapter));
zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
- zfcp_cmd_dbf_event_fsf("sqnrecom", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_PROGRAMMING_ERROR:
ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
"(adapter %s)\n",
zfcp_get_busid_by_adapter(fsf_req->adapter));
- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
- "fsf_sq_ulp_err");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
@@ -668,13 +540,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
(char *) &fsf_req->qtcb->header.fsf_status_qual,
sizeof (union fsf_status_qual));
- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:");
- debug_exception(fsf_req->adapter->erp_dbf, 0,
- &fsf_req->qtcb->header.fsf_status_qual.word[0],
- sizeof (u32));
- zfcp_cmd_dbf_event_fsf("squndef", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
@@ -682,6 +547,110 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
return retval;
}
+/**
+ * zfcp_fsf_link_down_info_eval - evaluate link down information block
+ */
+static void
+zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
+ struct fsf_link_down_info *link_down)
+{
+ switch (link_down->error_code) {
+ case FSF_PSQ_LINK_NO_LIGHT:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(no light detected)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_WRAP_PLUG:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(wrap plug detected)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_NO_FCP:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(adjacent node on link does not support FCP)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(firmware update in progress)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_INVALID_WWPN:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(duplicate or invalid WWPN detected)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(no support for NPIV by Fabric)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_NO_FCP_RESOURCES:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(out of resource in FCP daughtercard)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(out of resource in Fabric)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(unable to Fabric login)\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
+ ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
+ ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
+ ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ default:
+ ZFCP_LOG_NORMAL("The local link to adapter %s is down "
+ "(warning: unknown reason code %d)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ link_down->error_code);
+ }
+
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ ZFCP_LOG_DEBUG("Debug information to link down: "
+ "primary_status=0x%02x "
+ "ioerr_code=0x%02x "
+ "action_code=0x%02x "
+ "reason_code=0x%02x "
+ "explanation_code=0x%02x "
+ "vendor_specific_code=0x%02x\n",
+ link_down->primary_status,
+ link_down->ioerr_code,
+ link_down->action_code,
+ link_down->reason_code,
+ link_down->explanation_code,
+ link_down->vendor_specific_code);
+
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status)) {
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status);
+ switch (link_down->error_code) {
+ case FSF_PSQ_LINK_NO_LIGHT:
+ case FSF_PSQ_LINK_WRAP_PLUG:
+ case FSF_PSQ_LINK_NO_FCP:
+ case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+ zfcp_erp_adapter_reopen(adapter, 0);
+ break;
+ default:
+ zfcp_erp_adapter_failed(adapter);
+ }
+ }
+}
+
/*
* function: zfcp_fsf_req_dispatch
*
@@ -696,11 +665,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
struct zfcp_adapter *adapter = fsf_req->adapter;
int retval = 0;
- if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
- ZFCP_LOG_TRACE("fsf_req=%p, QTCB=%p\n", fsf_req, fsf_req->qtcb);
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb));
- }
switch (fsf_req->fsf_command) {
@@ -760,13 +724,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
"not supported by the adapter %s\n",
- zfcp_get_busid_by_adapter(fsf_req->adapter));
+ zfcp_get_busid_by_adapter(adapter));
if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command)
ZFCP_LOG_NORMAL
("bug: Command issued by the device driver differs "
"from the command returned by the adapter %s "
"(debug info 0x%x, 0x%x).\n",
- zfcp_get_busid_by_adapter(fsf_req->adapter),
+ zfcp_get_busid_by_adapter(adapter),
fsf_req->fsf_command,
fsf_req->qtcb->header.fsf_command);
}
@@ -774,8 +738,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
if (!erp_action)
return retval;
- debug_text_event(adapter->erp_dbf, 3, "a_frh");
- debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
zfcp_erp_async_handler(erp_action, 0);
return retval;
@@ -821,7 +783,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
goto failed_buf;
}
memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer));
- fsf_req->data.status_read.buffer = status_buffer;
+ fsf_req->data = (unsigned long) status_buffer;
/* insert pointer to respective buffer */
sbale = zfcp_qdio_sbale_curr(fsf_req);
@@ -846,6 +808,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
failed_buf:
zfcp_fsf_req_free(fsf_req);
failed_req_create:
+ zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
out:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
return retval;
@@ -859,7 +822,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
struct zfcp_port *port;
unsigned long flags;
- status_buffer = fsf_req->data.status_read.buffer;
+ status_buffer = (struct fsf_status_read_buffer *) fsf_req->data;
adapter = fsf_req->adapter;
read_lock_irqsave(&zfcp_data.config_lock, flags);
@@ -918,38 +881,33 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
int retval = 0;
struct zfcp_adapter *adapter = fsf_req->adapter;
struct fsf_status_read_buffer *status_buffer =
- fsf_req->data.status_read.buffer;
+ (struct fsf_status_read_buffer *) fsf_req->data;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
+ zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer);
mempool_free(status_buffer, adapter->pool.data_status_read);
zfcp_fsf_req_free(fsf_req);
goto out;
}
+ zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer);
+
switch (status_buffer->status_type) {
case FSF_STATUS_READ_PORT_CLOSED:
- debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:");
- debug_event(adapter->erp_dbf, 3,
- &status_buffer->d_id, sizeof (u32));
zfcp_fsf_status_read_port_closed(fsf_req);
break;
case FSF_STATUS_READ_INCOMING_ELS:
- debug_text_event(adapter->erp_dbf, 3, "unsol_els:");
zfcp_fsf_incoming_els(fsf_req);
break;
case FSF_STATUS_READ_SENSE_DATA_AVAIL:
- debug_text_event(adapter->erp_dbf, 3, "unsol_sense:");
ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n",
zfcp_get_busid_by_adapter(adapter));
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer,
- sizeof(struct fsf_status_read_buffer));
break;
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
- debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:");
ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
(char *) status_buffer,
@@ -957,17 +915,32 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_LINK_DOWN:
- debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:");
- ZFCP_LOG_INFO("Local link to adapter %s is down\n",
+ switch (status_buffer->status_subtype) {
+ case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ case FSF_STATUS_READ_SUB_FDISC_FAILED:
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to failed FDISC login\n",
zfcp_get_busid_by_adapter(adapter));
- atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status);
- zfcp_erp_adapter_failed(adapter);
+ break;
+ case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to firmware update on adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ default:
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to unknown reason\n",
+ zfcp_get_busid_by_adapter(adapter));
+ };
+ zfcp_fsf_link_down_info_eval(adapter,
+ (struct fsf_link_down_info *) &status_buffer->payload);
break;
case FSF_STATUS_READ_LINK_UP:
- debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:");
- ZFCP_LOG_INFO("Local link to adapter %s was replugged. "
+ ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. "
"Restarting operations on this adapter\n",
zfcp_get_busid_by_adapter(adapter));
/* All ports should be marked as ready to run again */
@@ -980,35 +953,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_CFDC_UPDATED:
- debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
- ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
+ ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
zfcp_erp_adapter_access_changed(adapter);
break;
case FSF_STATUS_READ_CFDC_HARDENED:
- debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:");
switch (status_buffer->status_subtype) {
case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE:
- ZFCP_LOG_INFO("CFDC of adapter %s saved on SE\n",
+ ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n",
zfcp_get_busid_by_adapter(adapter));
break;
case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2:
- ZFCP_LOG_INFO("CFDC of adapter %s has been copied "
+ ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied "
"to the secondary SE\n",
zfcp_get_busid_by_adapter(adapter));
break;
default:
- ZFCP_LOG_INFO("CFDC of adapter %s has been hardened\n",
+ ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n",
zfcp_get_busid_by_adapter(adapter));
}
break;
+ case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+ debug_text_event(adapter->erp_dbf, 2, "unsol_features:");
+ ZFCP_LOG_INFO("List of supported features on adapter %s has "
+ "been changed from 0x%08X to 0x%08X\n",
+ zfcp_get_busid_by_adapter(adapter),
+ *(u32*) (status_buffer->payload + 4),
+ *(u32*) (status_buffer->payload));
+ adapter->adapter_features = *(u32*) status_buffer->payload;
+ break;
+
default:
- debug_text_event(adapter->erp_dbf, 0, "unsol_unknown:");
- debug_exception(adapter->erp_dbf, 0,
- &status_buffer->status_type, sizeof (u32));
- ZFCP_LOG_NORMAL("bug: An unsolicited status packet of unknown "
+ ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown "
"type was received (debug info 0x%x)\n",
status_buffer->status_type);
ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n",
@@ -1093,7 +1071,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- fsf_req->data.abort_fcp_command.unit = unit;
+ fsf_req->data = (unsigned long) unit;
/* set handles of unit and its parent port in QTCB */
fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -1139,7 +1117,7 @@ static int
zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
{
int retval = -EINVAL;
- struct zfcp_unit *unit = new_fsf_req->data.abort_fcp_command.unit;
+ struct zfcp_unit *unit;
unsigned char status_qual =
new_fsf_req->qtcb->header.fsf_status_qual.word[0];
@@ -1150,6 +1128,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
goto skip_fsfstatus;
}
+ unit = (struct zfcp_unit *) new_fsf_req->data;
+
/* evaluate FSF status in QTCB */
switch (new_fsf_req->qtcb->header.fsf_status) {
@@ -1364,7 +1344,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]);
sbale[3].length = ct->resp[0].length;
sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
- } else if (adapter->supported_features &
+ } else if (adapter->adapter_features &
FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
/* try to use chained SBALs */
bytes = zfcp_qdio_sbals_from_sg(fsf_req,
@@ -1414,7 +1394,9 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
fsf_req->qtcb->header.port_handle = port->handle;
fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
fsf_req->qtcb->bottom.support.timeout = ct->timeout;
- fsf_req->data.send_ct = ct;
+ fsf_req->data = (unsigned long) ct;
+
+ zfcp_san_dbf_event_ct_request(fsf_req);
/* start QDIO request for this FSF request */
ret = zfcp_fsf_req_send(fsf_req, ct->timer);
@@ -1445,10 +1427,10 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
* zfcp_fsf_send_ct_handler - handler for Generic Service requests
* @fsf_req: pointer to struct zfcp_fsf_req
*
- * Data specific for the Generic Service request is passed by
- * fsf_req->data.send_ct
- * Usually a specific handler for the request is called via
- * fsf_req->data.send_ct->handler at end of this function.
+ * Data specific for the Generic Service request is passed using
+ * fsf_req->data. There we find the pointer to struct zfcp_send_ct.
+ * Usually a specific handler for the CT request is called which is
+ * found in this structure.
*/
static int
zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
@@ -1462,7 +1444,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
u16 subtable, rule, counter;
adapter = fsf_req->adapter;
- send_ct = fsf_req->data.send_ct;
+ send_ct = (struct zfcp_send_ct *) fsf_req->data;
port = send_ct->port;
header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
@@ -1474,6 +1456,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_GOOD:
+ zfcp_san_dbf_event_ct_response(fsf_req);
retval = 0;
break;
@@ -1634,7 +1617,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
{
volatile struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req;
- fc_id_t d_id;
+ u32 d_id;
struct zfcp_adapter *adapter;
unsigned long lock_flags;
int bytes;
@@ -1664,7 +1647,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
sbale[3].addr = zfcp_sg_to_address(&els->resp[0]);
sbale[3].length = els->resp[0].length;
sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
- } else if (adapter->supported_features &
+ } else if (adapter->adapter_features &
FSF_FEATURE_ELS_CT_CHAINED_SBALS) {
/* try to use chained SBALs */
bytes = zfcp_qdio_sbals_from_sg(fsf_req,
@@ -1714,10 +1697,12 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
fsf_req->qtcb->bottom.support.d_id = d_id;
fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
- fsf_req->data.send_els = els;
+ fsf_req->data = (unsigned long) els;
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+ zfcp_san_dbf_event_els_request(fsf_req);
+
/* start QDIO request for this FSF request */
ret = zfcp_fsf_req_send(fsf_req, els->timer);
if (ret) {
@@ -1746,23 +1731,23 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
* zfcp_fsf_send_els_handler - handler for ELS commands
* @fsf_req: pointer to struct zfcp_fsf_req
*
- * Data specific for the ELS command is passed by
- * fsf_req->data.send_els
- * Usually a specific handler for the command is called via
- * fsf_req->data.send_els->handler at end of this function.
+ * Data specific for the ELS command is passed using
+ * fsf_req->data. There we find the pointer to struct zfcp_send_els.
+ * Usually a specific handler for the ELS command is called which is
+ * found in this structure.
*/
static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter;
struct zfcp_port *port;
- fc_id_t d_id;
+ u32 d_id;
struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom;
struct zfcp_send_els *send_els;
int retval = -EINVAL;
u16 subtable, rule, counter;
- send_els = fsf_req->data.send_els;
+ send_els = (struct zfcp_send_els *) fsf_req->data;
adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id;
@@ -1775,6 +1760,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_GOOD:
+ zfcp_san_dbf_event_els_response(fsf_req);
retval = 0;
break;
@@ -1954,7 +1940,9 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->erp_action = erp_action;
erp_action->fsf_req->qtcb->bottom.config.feature_selection =
- (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING);
+ FSF_FEATURE_CFDC |
+ FSF_FEATURE_LUN_SHARING |
+ FSF_FEATURE_UPDATE_ALERT;
/* start QDIO request for this FSF request */
retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
@@ -1990,29 +1978,36 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
{
struct fsf_qtcb_bottom_config *bottom;
struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct Scsi_Host *shost = adapter->scsi_host;
bottom = &fsf_req->qtcb->bottom.config;
ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n",
bottom->low_qtcb_version, bottom->high_qtcb_version);
adapter->fsf_lic_version = bottom->lic_version;
- adapter->supported_features = bottom->supported_features;
+ adapter->adapter_features = bottom->adapter_features;
+ adapter->connection_features = bottom->connection_features;
adapter->peer_wwpn = 0;
adapter->peer_wwnn = 0;
adapter->peer_d_id = 0;
if (xchg_ok) {
- adapter->wwnn = bottom->nport_serv_param.wwnn;
- adapter->wwpn = bottom->nport_serv_param.wwpn;
- adapter->s_id = bottom->s_id & ZFCP_DID_MASK;
+ fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
+ fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
+ fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
+ fc_host_speed(shost) = bottom->fc_link_speed;
+ fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
adapter->fc_topology = bottom->fc_topology;
- adapter->fc_link_speed = bottom->fc_link_speed;
adapter->hydra_version = bottom->adapter_type;
+ if (adapter->physical_wwpn == 0)
+ adapter->physical_wwpn = fc_host_port_name(shost);
+ if (adapter->physical_s_id == 0)
+ adapter->physical_s_id = fc_host_port_id(shost);
} else {
- adapter->wwnn = 0;
- adapter->wwpn = 0;
- adapter->s_id = 0;
+ fc_host_node_name(shost) = 0;
+ fc_host_port_name(shost) = 0;
+ fc_host_port_id(shost) = 0;
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
adapter->fc_topology = 0;
- adapter->fc_link_speed = 0;
adapter->hydra_version = 0;
}
@@ -2022,26 +2017,28 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
adapter->peer_wwnn = bottom->plogi_payload.wwnn;
}
- if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){
+ if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
adapter->hardware_version = bottom->hardware_version;
- memcpy(adapter->serial_number, bottom->serial_number, 17);
- EBCASC(adapter->serial_number, sizeof(adapter->serial_number));
+ memcpy(fc_host_serial_number(shost), bottom->serial_number,
+ min(FC_SERIAL_NUMBER_SIZE, 17));
+ EBCASC(fc_host_serial_number(shost),
+ min(FC_SERIAL_NUMBER_SIZE, 17));
}
ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n"
- "WWNN 0x%016Lx, "
- "WWPN 0x%016Lx, "
- "S_ID 0x%08x,\n"
- "adapter version 0x%x, "
- "LIC version 0x%x, "
- "FC link speed %d Gb/s\n",
- zfcp_get_busid_by_adapter(adapter),
- adapter->wwnn,
- adapter->wwpn,
- (unsigned int) adapter->s_id,
- adapter->hydra_version,
- adapter->fsf_lic_version,
- adapter->fc_link_speed);
+ "WWNN 0x%016Lx, "
+ "WWPN 0x%016Lx, "
+ "S_ID 0x%08x,\n"
+ "adapter version 0x%x, "
+ "LIC version 0x%x, "
+ "FC link speed %d Gb/s\n",
+ zfcp_get_busid_by_adapter(adapter),
+ (wwn_t) fc_host_node_name(shost),
+ (wwn_t) fc_host_port_name(shost),
+ fc_host_port_id(shost),
+ adapter->hydra_version,
+ adapter->fsf_lic_version,
+ fc_host_speed(shost));
if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
ZFCP_LOG_NORMAL("error: the adapter %s "
"only supports newer control block "
@@ -2077,11 +2074,12 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
{
struct fsf_qtcb_bottom_config *bottom;
struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_qtcb *qtcb = fsf_req->qtcb;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return -EIO;
- switch (fsf_req->qtcb->header.fsf_status) {
+ switch (qtcb->header.fsf_status) {
case FSF_GOOD:
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
@@ -2111,7 +2109,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
case FSF_TOPO_FABRIC:
- ZFCP_LOG_INFO("Switched fabric fibrechannel "
+ ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
zfcp_get_busid_by_adapter(adapter));
break;
@@ -2129,7 +2127,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
}
- bottom = &fsf_req->qtcb->bottom.config;
+ bottom = &qtcb->bottom.config;
if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) "
"allowed by the adapter %s "
@@ -2154,12 +2152,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
return -EIO;
- ZFCP_LOG_INFO("Local link to adapter %s is down\n",
- zfcp_get_busid_by_adapter(adapter));
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
- ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status);
- zfcp_erp_adapter_failed(adapter);
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
+
+ zfcp_fsf_link_down_info_eval(adapter,
+ &qtcb->header.fsf_status_qual.link_down_info);
break;
default:
debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
@@ -2173,11 +2169,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
/**
* zfcp_fsf_exchange_port_data - request information about local port
+ * @erp_action: ERP action for the adapter for which port data is requested
* @adapter: for which port data is requested
* @data: response to exchange port data request
*/
int
-zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
+zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
+ struct zfcp_adapter *adapter,
struct fsf_qtcb_bottom_port *data)
{
volatile struct qdio_buffer_element *sbale;
@@ -2186,7 +2184,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *fsf_req;
struct timer_list *timer;
- if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){
+ if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
ZFCP_LOG_INFO("error: exchange port data "
"command not supported by adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
@@ -2210,12 +2208,18 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
goto out;
}
+ if (erp_action) {
+ erp_action->fsf_req = fsf_req;
+ fsf_req->erp_action = erp_action;
+ }
+
+ if (data)
+ fsf_req->data = (unsigned long) data;
+
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- fsf_req->data.port_data = data;
-
init_timer(timer);
timer->function = zfcp_fsf_request_timeout_handler;
timer->data = (unsigned long) adapter;
@@ -2227,6 +2231,8 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
"command on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
zfcp_fsf_req_free(fsf_req);
+ if (erp_action)
+ erp_action->fsf_req = NULL;
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
goto out;
@@ -2255,21 +2261,42 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
static void
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
{
- struct fsf_qtcb_bottom_port *bottom;
- struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data;
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct Scsi_Host *shost = adapter->scsi_host;
+ struct fsf_qtcb *qtcb = fsf_req->qtcb;
+ struct fsf_qtcb_bottom_port *bottom, *data;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
- switch (fsf_req->qtcb->header.fsf_status) {
+ switch (qtcb->header.fsf_status) {
case FSF_GOOD:
- bottom = &fsf_req->qtcb->bottom.port;
- memcpy(data, bottom, sizeof(*data));
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+ bottom = &qtcb->bottom.port;
+ data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
+ if (data)
+ memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
+ adapter->physical_wwpn = bottom->wwpn;
+ adapter->physical_s_id = bottom->fc_port_id;
+ } else {
+ adapter->physical_wwpn = fc_host_port_name(shost);
+ adapter->physical_s_id = fc_host_port_id(shost);
+ }
+ fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ break;
+
+ case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+ zfcp_fsf_link_down_info_eval(adapter,
+ &qtcb->header.fsf_status_qual.link_down_info);
break;
default:
- debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng");
- debug_event(fsf_req->adapter->erp_dbf, 0,
+ debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
+ debug_event(adapter->erp_dbf, 0,
&fsf_req->qtcb->header.fsf_status, sizeof(u32));
}
}
@@ -2311,7 +2338,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
- erp_action->fsf_req->data.open_port.port = erp_action->port;
+ erp_action->fsf_req->data = (unsigned long) erp_action->port;
erp_action->fsf_req->erp_action = erp_action;
/* start QDIO request for this FSF request */
@@ -2352,7 +2379,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
struct fsf_qtcb_header *header;
u16 subtable, rule, counter;
- port = fsf_req->data.open_port.port;
+ port = (struct zfcp_port *) fsf_req->data;
header = &fsf_req->qtcb->header;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -2565,7 +2592,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
- erp_action->fsf_req->data.close_port.port = erp_action->port;
+ erp_action->fsf_req->data = (unsigned long) erp_action->port;
erp_action->fsf_req->erp_action = erp_action;
erp_action->fsf_req->qtcb->header.port_handle =
erp_action->port->handle;
@@ -2605,7 +2632,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
int retval = -EINVAL;
struct zfcp_port *port;
- port = fsf_req->data.close_port.port;
+ port = (struct zfcp_port *) fsf_req->data;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change port status in our bookkeeping */
@@ -2702,8 +2729,8 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING,
&erp_action->port->status);
/* save a pointer to this port */
- erp_action->fsf_req->data.close_physical_port.port = erp_action->port;
- /* port to be closeed */
+ erp_action->fsf_req->data = (unsigned long) erp_action->port;
+ /* port to be closed */
erp_action->fsf_req->qtcb->header.port_handle =
erp_action->port->handle;
erp_action->fsf_req->erp_action = erp_action;
@@ -2746,7 +2773,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
struct fsf_qtcb_header *header;
u16 subtable, rule, counter;
- port = fsf_req->data.close_physical_port.port;
+ port = (struct zfcp_port *) fsf_req->data;
header = &fsf_req->qtcb->header;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -2907,10 +2934,11 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->port->handle;
erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
erp_action->unit->fcp_lun;
+ if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
erp_action->fsf_req->qtcb->bottom.support.option =
FSF_OPEN_LUN_SUPPRESS_BOXING;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
- erp_action->fsf_req->data.open_unit.unit = erp_action->unit;
+ erp_action->fsf_req->data = (unsigned long) erp_action->unit;
erp_action->fsf_req->erp_action = erp_action;
/* start QDIO request for this FSF request */
@@ -2954,9 +2982,9 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
struct fsf_qtcb_bottom_support *bottom;
struct fsf_queue_designator *queue_designator;
u16 subtable, rule, counter;
- u32 allowed, exclusive, readwrite;
+ int exclusive, readwrite;
- unit = fsf_req->data.open_unit.unit;
+ unit = (struct zfcp_unit *) fsf_req->data;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change unit status in our bookkeeping */
@@ -2968,10 +2996,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
bottom = &fsf_req->qtcb->bottom.support;
queue_designator = &header->fsf_status_qual.fsf_queue_designator;
- allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED;
- exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE;
- readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER;
-
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_UNIT_SHARED |
ZFCP_STATUS_UNIT_READONLY,
@@ -3145,10 +3169,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
unit->handle);
/* mark unit as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
- atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_COMMON_ACCESS_BOXED,
- &unit->status);
- if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
+
+ if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
+ (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
+ (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) {
+ exclusive = (bottom->lun_access_info &
+ FSF_UNIT_ACCESS_EXCLUSIVE);
+ readwrite = (bottom->lun_access_info &
+ FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
+
if (!exclusive)
atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
&unit->status);
@@ -3241,7 +3270,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
erp_action->port->handle;
erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
- erp_action->fsf_req->data.close_unit.unit = erp_action->unit;
+ erp_action->fsf_req->data = (unsigned long) erp_action->unit;
erp_action->fsf_req->erp_action = erp_action;
/* start QDIO request for this FSF request */
@@ -3280,7 +3309,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
int retval = -EINVAL;
struct zfcp_unit *unit;
- unit = fsf_req->data.close_unit.unit; /* restore unit */
+ unit = (struct zfcp_unit *) fsf_req->data;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* don't change unit status in our bookkeeping */
@@ -3304,9 +3333,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_s_phand_nv");
zfcp_erp_adapter_reopen(unit->port->adapter, 0);
- zfcp_cmd_dbf_event_fsf("porthinv", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3325,9 +3351,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_s_lhand_nv");
zfcp_erp_port_reopen(unit->port, 0);
- zfcp_cmd_dbf_event_fsf("lunhinv", fsf_req,
- &fsf_req->qtcb->header.fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3435,21 +3458,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
goto failed_req_create;
}
- /*
- * associate FSF request with SCSI request
- * (need this for look up on abort)
- */
- fsf_req->data.send_fcp_command_task.fsf_req = fsf_req;
- scsi_cmnd->host_scribble = (char *) &(fsf_req->data);
+ zfcp_unit_get(unit);
+ fsf_req->unit = unit;
- /*
- * associate SCSI command with FSF request
- * (need this for look up on normal command completion)
- */
- fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd;
- fsf_req->data.send_fcp_command_task.start_jiffies = jiffies;
- fsf_req->data.send_fcp_command_task.unit = unit;
- ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun);
+ /* associate FSF request with SCSI request (for look up on abort) */
+ scsi_cmnd->host_scribble = (char *) fsf_req;
+
+ /* associate SCSI command with FSF request */
+ fsf_req->data = (unsigned long) scsi_cmnd;
/* set handles of unit and its parent port in QTCB */
fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -3583,6 +3599,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
send_failed:
no_fit:
failed_scsi_cmnd:
+ zfcp_unit_put(unit);
zfcp_fsf_req_free(fsf_req);
fsf_req = NULL;
scsi_cmnd->host_scribble = NULL;
@@ -3639,7 +3656,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
* hold a pointer to the unit being target of this
* task management request
*/
- fsf_req->data.send_fcp_command_task_management.unit = unit;
+ fsf_req->data = (unsigned long) unit;
/* set FSF related fields in QTCB */
fsf_req->qtcb->header.lun_handle = unit->handle;
@@ -3705,9 +3722,9 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
header = &fsf_req->qtcb->header;
if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
- unit = fsf_req->data.send_fcp_command_task_management.unit;
+ unit = (struct zfcp_unit *) fsf_req->data;
else
- unit = fsf_req->data.send_fcp_command_task.unit;
+ unit = fsf_req->unit;
if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
/* go directly to calls of special handlers */
@@ -3764,10 +3781,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_s_hand_mis");
zfcp_erp_adapter_reopen(unit->port->adapter, 0);
- zfcp_cmd_dbf_event_fsf("handmism",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3788,10 +3801,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"fsf_s_class_nsup");
zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
- zfcp_cmd_dbf_event_fsf("unsclass",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3810,10 +3819,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_s_fcp_lun_nv");
zfcp_erp_port_reopen(unit->port, 0);
- zfcp_cmd_dbf_event_fsf("fluninv",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3852,10 +3857,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"fsf_s_dir_ind_nv");
zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
- zfcp_cmd_dbf_event_fsf("dirinv",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3871,10 +3872,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"fsf_s_cmd_len_nv");
zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
- zfcp_cmd_dbf_event_fsf("cleninv",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -3946,6 +3943,8 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
zfcp_fsf_send_fcp_command_task_management_handler(fsf_req);
} else {
retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req);
+ fsf_req->unit = NULL;
+ zfcp_unit_put(unit);
}
return retval;
}
@@ -3969,10 +3968,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
u32 sns_len;
char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
unsigned long flags;
- struct zfcp_unit *unit = fsf_req->data.send_fcp_command_task.unit;
+ struct zfcp_unit *unit = fsf_req->unit;
read_lock_irqsave(&fsf_req->adapter->abort_lock, flags);
- scpnt = fsf_req->data.send_fcp_command_task.scsi_cmnd;
+ scpnt = (struct scsi_cmnd *) fsf_req->data;
if (unlikely(!scpnt)) {
ZFCP_LOG_DEBUG
("Command with fsf_req %p is not associated to "
@@ -4042,7 +4041,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &fsf_req->qtcb->
bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
- zfcp_cmd_dbf_event_fsf("clenmis", fsf_req, NULL, 0);
set_host_byte(&scpnt->result, DID_ERROR);
goto skip_fsfstatus;
case RSP_CODE_FIELD_INVALID:
@@ -4061,7 +4059,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
(char *) &fsf_req->qtcb->
bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
set_host_byte(&scpnt->result, DID_ERROR);
- zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0);
goto skip_fsfstatus;
case RSP_CODE_RO_MISMATCH:
/* hardware bug */
@@ -4078,7 +4075,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &fsf_req->qtcb->
bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
- zfcp_cmd_dbf_event_fsf("codemism", fsf_req, NULL, 0);
set_host_byte(&scpnt->result, DID_ERROR);
goto skip_fsfstatus;
default:
@@ -4095,7 +4091,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) &fsf_req->qtcb->
bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE);
- zfcp_cmd_dbf_event_fsf("undeffcp", fsf_req, NULL, 0);
set_host_byte(&scpnt->result, DID_ERROR);
goto skip_fsfstatus;
}
@@ -4157,19 +4152,17 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
skip_fsfstatus:
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
- zfcp_cmd_dbf_event_scsi("response", scpnt);
+ if (scpnt->result != 0)
+ zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+ else if (scpnt->retries > 0)
+ zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+ else
+ zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
/* cleanup pointer (need this especially for abort) */
scpnt->host_scribble = NULL;
- /*
- * NOTE:
- * according to the outcome of a discussion on linux-scsi we
- * don't need to grab the io_request_lock here since we use
- * the new eh
- */
/* always call back */
-
(scpnt->scsi_done) (scpnt);
/*
@@ -4197,8 +4190,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
&(fsf_req->qtcb->bottom.io.fcp_rsp);
char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
- struct zfcp_unit *unit =
- fsf_req->data.send_fcp_command_task_management.unit;
+ struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data;
del_timer(&fsf_req->adapter->scsi_er_timer);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
@@ -4275,7 +4267,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
int direction;
int retval = 0;
- if (!(adapter->supported_features & FSF_FEATURE_CFDC)) {
+ if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) {
ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n",
zfcp_get_busid_by_adapter(adapter));
retval = -EOPNOTSUPP;
@@ -4548,52 +4540,6 @@ skip_fsfstatus:
return retval;
}
-
-/*
- * function: zfcp_fsf_req_wait_and_cleanup
- *
- * purpose:
- *
- * FIXME(design): signal seems to be <0 !!!
- * returns: 0 - request completed (*status is valid), cleanup succ.
- * <0 - request completed (*status is valid), cleanup failed
- * >0 - signal which interrupted waiting (*status invalid),
- * request not completed, no cleanup
- *
- * *status is a copy of status of completed fsf_req
- */
-int
-zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
- int interruptible, u32 * status)
-{
- int retval = 0;
- int signal = 0;
-
- if (interruptible) {
- __wait_event_interruptible(fsf_req->completion_wq,
- fsf_req->status &
- ZFCP_STATUS_FSFREQ_COMPLETED,
- signal);
- if (signal) {
- ZFCP_LOG_DEBUG("Caught signal %i while waiting for the "
- "completion of the request at %p\n",
- signal, fsf_req);
- retval = signal;
- goto out;
- }
- } else {
- __wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- }
-
- *status = fsf_req->status;
-
- /* cleanup request */
- zfcp_fsf_req_free(fsf_req);
- out:
- return retval;
-}
-
static inline int
zfcp_fsf_req_sbal_check(unsigned long *flags,
struct zfcp_qdio_queue *queue, int needed)
@@ -4609,15 +4555,16 @@ zfcp_fsf_req_sbal_check(unsigned long *flags,
* set qtcb pointer in fsf_req and initialize QTCB
*/
static inline void
-zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd)
+zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
{
if (likely(fsf_req->qtcb != NULL)) {
+ fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no;
fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req;
fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
- fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd];
+ fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command];
fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req;
- fsf_req->qtcb->header.fsf_command = fsf_cmd;
+ fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command;
}
}
@@ -4685,7 +4632,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
goto failed_fsf_req;
}
- zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd);
+ fsf_req->adapter = adapter;
+ fsf_req->fsf_command = fsf_cmd;
+
+ zfcp_fsf_req_qtcb_init(fsf_req);
/* initialize waitqueue which may be used to wait on
this request completion */
@@ -4707,8 +4657,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
goto failed_sbals;
}
- fsf_req->adapter = adapter; /* pointer to "parent" adapter */
- fsf_req->fsf_command = fsf_cmd;
+ if (fsf_req->qtcb) {
+ fsf_req->seq_no = adapter->fsf_req_seq_no;
+ fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
+ }
fsf_req->sbal_number = 1;
fsf_req->sbal_first = req_queue->free_index;
fsf_req->sbal_curr = req_queue->free_index;
@@ -4759,9 +4711,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
struct zfcp_adapter *adapter;
struct zfcp_qdio_queue *req_queue;
volatile struct qdio_buffer_element *sbale;
+ int inc_seq_no;
int new_distance_from_int;
unsigned long flags;
- int inc_seq_no = 1;
int retval = 0;
adapter = fsf_req->adapter;
@@ -4775,23 +4727,13 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr,
sbale[1].length);
- /* set sequence counter in QTCB */
- if (likely(fsf_req->qtcb)) {
- fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
- fsf_req->seq_no = adapter->fsf_req_seq_no;
- ZFCP_LOG_TRACE("FSF request %p of adapter %s gets "
- "FSF sequence counter value of %i\n",
- fsf_req,
- zfcp_get_busid_by_adapter(adapter),
- fsf_req->qtcb->prefix.req_seq_no);
- } else
- inc_seq_no = 0;
-
/* put allocated FSF request at list tail */
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+ inc_seq_no = (fsf_req->qtcb != NULL);
+
/* figure out expiration time of timeout and start timeout */
if (unlikely(timer)) {
timer->expires += jiffies;
@@ -4821,6 +4763,8 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */
new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req);
+ fsf_req->issued = get_clock();
+
retval = do_QDIO(adapter->ccw_device,
QDIO_FLAG_SYNC_OUTPUT,
0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
@@ -4859,15 +4803,11 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
* routines resulting in missing sequence counter values
* otherwise,
*/
+
/* Don't increase for unsolicited status */
- if (likely(inc_seq_no)) {
+ if (inc_seq_no)
adapter->fsf_req_seq_no++;
- ZFCP_LOG_TRACE
- ("FSF sequence counter value of adapter %s "
- "increased to %i\n",
- zfcp_get_busid_by_adapter(adapter),
- adapter->fsf_req_seq_no);
- }
+
/* count FSF requests pending */
atomic_inc(&adapter->fsf_reqs_active);
}
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 07140dfda2a7..48719f055952 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -116,6 +116,7 @@
#define FSF_INVALID_COMMAND_OPTION 0x000000E5
/* #define FSF_ERROR 0x000000FF */
+#define FSF_PROT_STATUS_QUAL_SIZE 16
#define FSF_STATUS_QUALIFIER_SIZE 16
/* FSF status qualifier, recommendations */
@@ -139,9 +140,18 @@
#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004
/* FSF status qualifier (most significant 4 bytes), local link down */
-#define FSF_PSQ_LINK_NOLIGHT 0x00000004
-#define FSF_PSQ_LINK_WRAPPLUG 0x00000008
-#define FSF_PSQ_LINK_NOFCP 0x00000010
+#define FSF_PSQ_LINK_NO_LIGHT 0x00000004
+#define FSF_PSQ_LINK_WRAP_PLUG 0x00000008
+#define FSF_PSQ_LINK_NO_FCP 0x00000010
+#define FSF_PSQ_LINK_FIRMWARE_UPDATE 0x00000020
+#define FSF_PSQ_LINK_INVALID_WWPN 0x00000100
+#define FSF_PSQ_LINK_NO_NPIV_SUPPORT 0x00000200
+#define FSF_PSQ_LINK_NO_FCP_RESOURCES 0x00000400
+#define FSF_PSQ_LINK_NO_FABRIC_RESOURCES 0x00000800
+#define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE 0x00001000
+#define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000
+#define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000
+#define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000
/* payload size in status read buffer */
#define FSF_STATUS_READ_PAYLOAD_SIZE 4032
@@ -154,15 +164,21 @@
#define FSF_STATUS_READ_INCOMING_ELS 0x00000002
#define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003
#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
-#define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */
+#define FSF_STATUS_READ_LINK_DOWN 0x00000005
#define FSF_STATUS_READ_LINK_UP 0x00000006
#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 */
#define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001
#define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002
+/* status subtypes for link down */
+#define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000
+#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
+#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002
+
/* status subtypes for CFDC */
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
@@ -193,11 +209,15 @@
#define FSF_QTCB_LOG_SIZE 1024
/* channel features */
-#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001
#define FSF_FEATURE_CFDC 0x00000002
#define FSF_FEATURE_LUN_SHARING 0x00000004
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
+#define FSF_FEATURE_UPDATE_ALERT 0x00000100
+
+/* host connection features */
+#define FSF_FEATURE_NPIV_MODE 0x00000001
+#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002
/* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
@@ -305,15 +325,23 @@ struct fsf_qual_sequence_error {
u32 res1[3];
} __attribute__ ((packed));
-struct fsf_qual_locallink_error {
- u32 code;
- u32 res1[3];
+struct fsf_link_down_info {
+ u32 error_code;
+ u32 res1;
+ u8 res2[2];
+ u8 primary_status;
+ u8 ioerr_code;
+ u8 action_code;
+ u8 reason_code;
+ u8 explanation_code;
+ u8 vendor_specific_code;
} __attribute__ ((packed));
union fsf_prot_status_qual {
+ u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
struct fsf_qual_version_error version_error;
struct fsf_qual_sequence_error sequence_error;
- struct fsf_qual_locallink_error locallink_error;
+ struct fsf_link_down_info link_down_info;
} __attribute__ ((packed));
struct fsf_qtcb_prefix {
@@ -331,7 +359,9 @@ union fsf_status_qual {
u8 byte[FSF_STATUS_QUALIFIER_SIZE];
u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)];
+ u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)];
struct fsf_queue_designator fsf_queue_designator;
+ struct fsf_link_down_info link_down_info;
} __attribute__ ((packed));
struct fsf_qtcb_header {
@@ -406,8 +436,8 @@ struct fsf_qtcb_bottom_config {
u32 low_qtcb_version;
u32 max_qtcb_size;
u32 max_data_transfer_size;
- u32 supported_features;
- u8 res1[4];
+ u32 adapter_features;
+ u32 connection_features;
u32 fc_topology;
u32 fc_link_speed;
u32 adapter_type;
@@ -425,7 +455,7 @@ struct fsf_qtcb_bottom_config {
} __attribute__ ((packed));
struct fsf_qtcb_bottom_port {
- u8 res1[8];
+ u64 wwpn;
u32 fc_port_id;
u32 port_type;
u32 port_state;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 24e16ec331d9..d719f66a29a4 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -54,8 +54,7 @@ static inline int zfcp_qdio_sbals_from_buffer
static qdio_handler_t zfcp_qdio_request_handler;
static qdio_handler_t zfcp_qdio_response_handler;
static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
- unsigned int,
- unsigned int, unsigned int);
+ unsigned int, unsigned int, unsigned int, int, int);
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO
@@ -214,22 +213,12 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
*
*/
static inline int
-zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
- unsigned int status,
- unsigned int qdio_error, unsigned int siga_error)
+zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
+ unsigned int qdio_error, unsigned int siga_error,
+ int first_element, int elements_processed)
{
int retval = 0;
- if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE)) {
- if (status & QDIO_STATUS_INBOUND_INT) {
- ZFCP_LOG_TRACE("status is"
- " QDIO_STATUS_INBOUND_INT \n");
- }
- if (status & QDIO_STATUS_OUTBOUND_INT) {
- ZFCP_LOG_TRACE("status is"
- " QDIO_STATUS_OUTBOUND_INT \n");
- }
- }
if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
retval = -EIO;
@@ -237,9 +226,10 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
"qdio_error=0x%x, siga_error=0x%x)\n",
status, qdio_error, siga_error);
- /* Restarting IO on the failed adapter from scratch */
- debug_text_event(adapter->erp_dbf, 1, "qdio_err");
+ zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error,
+ first_element, elements_processed);
/*
+ * Restarting IO on the failed adapter from scratch.
* Since we have been using this adapter, it is save to assume
* that it is not failed but recoverable. The card seems to
* report link-up events by self-initiated queue shutdown.
@@ -282,7 +272,8 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
first_element, elements_processed);
if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
- siga_error)))
+ siga_error, first_element,
+ elements_processed)))
goto out;
/*
* we stored address of struct zfcp_adapter data structure
@@ -334,7 +325,8 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
queue = &adapter->response_queue;
if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
- siga_error)))
+ siga_error, first_element,
+ elements_processed)))
goto out;
/*
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b61d309352c3..3dcd1bfba3b4 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -44,7 +44,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *);
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
-static int zfcp_task_management_function(struct zfcp_unit *, u8);
+static int zfcp_task_management_function(struct zfcp_unit *, u8,
+ struct scsi_cmnd *);
static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
scsi_lun_t);
@@ -242,7 +243,10 @@ static void
zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
{
set_host_byte(&scpnt->result, result);
- zfcp_cmd_dbf_event_scsi("failing", scpnt);
+ if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
+ zfcp_scsi_dbf_event_result("fail", 4,
+ (struct zfcp_adapter*) scpnt->device->host->hostdata[0],
+ scpnt);
/* return directly */
scpnt->scsi_done(scpnt);
}
@@ -389,7 +393,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
struct zfcp_unit *unit, *retval = NULL;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id != port->scsi_id)
+ 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) {
@@ -408,73 +412,44 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id == port->scsi_id)
+ if (port->rport && (id == port->rport->scsi_target_id))
return port;
}
return (struct zfcp_port *) NULL;
}
-/*
- * function: zfcp_scsi_eh_abort_handler
- *
- * purpose: tries to abort the specified (timed out) SCSI command
- *
- * note: We do not need to care for a SCSI command which completes
- * normally but late during this abort routine runs.
- * We are allowed to return late commands to the SCSI stack.
- * It tracks the state of commands and will handle late commands.
- * (Usually, the normal completion of late commands is ignored with
- * respect to the running abort operation. Grep for 'done_late'
- * in the SCSI stacks sources.)
+/**
+ * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
+ * @scpnt: pointer to scsi_cmnd to be aborted
+ * Return: SUCCESS - command has been aborted and cleaned up in internal
+ * bookkeeping, SCSI stack won't be called for aborted command
+ * FAILED - otherwise
*
- * returns: SUCCESS - command has been aborted and cleaned up in internal
- * bookkeeping,
- * SCSI stack won't be called for aborted command
- * FAILED - otherwise
+ * We do not need to care for a SCSI command which completes normally
+ * but late during this abort routine runs. We are allowed to return
+ * late commands to the SCSI stack. It tracks the state of commands and
+ * will handle late commands. (Usually, the normal completion of late
+ * commands is ignored with respect to the running abort operation.)
*/
int
-__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
+ struct Scsi_Host *scsi_host;
+ struct zfcp_adapter *adapter;
+ struct zfcp_unit *unit;
int retval = SUCCESS;
- struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
- struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
- struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
- struct zfcp_port *port = unit->port;
- struct Scsi_Host *scsi_host = scpnt->device->host;
- union zfcp_req_data *req_data = NULL;
+ struct zfcp_fsf_req *new_fsf_req = NULL;
+ struct zfcp_fsf_req *old_fsf_req;
unsigned long flags;
- u32 status = 0;
-
- /* the components of a abort_dbf record (fixed size record) */
- u64 dbf_scsi_cmnd = (unsigned long) scpnt;
- char dbf_opcode[ZFCP_ABORT_DBF_LENGTH];
- wwn_t dbf_wwn = port->wwpn;
- fcp_lun_t dbf_fcp_lun = unit->fcp_lun;
- u64 dbf_retries = scpnt->retries;
- u64 dbf_allowed = scpnt->allowed;
- u64 dbf_timeout = 0;
- u64 dbf_fsf_req = 0;
- u64 dbf_fsf_status = 0;
- u64 dbf_fsf_qual[2] = { 0, 0 };
- char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef";
-
- memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH);
- memcpy(dbf_opcode,
- scpnt->cmnd,
- min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH));
+
+ scsi_host = scpnt->device->host;
+ adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
+ unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n",
scpnt, zfcp_get_busid_by_adapter(adapter));
- spin_unlock_irq(scsi_host->host_lock);
-
- /*
- * Race condition between normal (late) completion and abort has
- * to be avoided.
- * The entirity of all accesses to scsi_req have to be atomic.
- * scsi_req is usually part of the fsf_req and thus we block the
- * release of fsf_req as long as we need to access scsi_req.
- */
+ /* avoid race condition between late normal completion and abort */
write_lock_irqsave(&adapter->abort_lock, flags);
/*
@@ -484,144 +459,47 @@ __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
* this routine returns. (scpnt is parameter passed to this routine
* and must not disappear during abort even on late completion.)
*/
- req_data = (union zfcp_req_data *) scpnt->host_scribble;
- /* DEBUG */
- ZFCP_LOG_DEBUG("req_data=%p\n", req_data);
- if (!req_data) {
- ZFCP_LOG_DEBUG("late command completion overtook abort\n");
- /*
- * That's it.
- * Do not initiate abort but return SUCCESS.
- */
- write_unlock_irqrestore(&adapter->abort_lock, flags);
- retval = SUCCESS;
- strncpy(dbf_result, "##late1", ZFCP_ABORT_DBF_LENGTH);
- goto out;
- }
-
- /* Figure out which fsf_req needs to be aborted. */
- old_fsf_req = req_data->send_fcp_command_task.fsf_req;
-
- dbf_fsf_req = (unsigned long) old_fsf_req;
- dbf_timeout =
- (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ;
-
- ZFCP_LOG_DEBUG("old_fsf_req=%p\n", old_fsf_req);
+ old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
if (!old_fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- ZFCP_LOG_NORMAL("bug: no old fsf request found\n");
- ZFCP_LOG_NORMAL("req_data:\n");
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
- (char *) req_data, sizeof (union zfcp_req_data));
- ZFCP_LOG_NORMAL("scsi_cmnd:\n");
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
- (char *) scpnt, sizeof (struct scsi_cmnd));
- retval = FAILED;
- strncpy(dbf_result, "##bug:r", ZFCP_ABORT_DBF_LENGTH);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+ retval = SUCCESS;
goto out;
}
- old_fsf_req->data.send_fcp_command_task.scsi_cmnd = NULL;
- /* mark old request as being aborted */
+ old_fsf_req->data = 0;
old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
- /*
- * We have to collect all information (e.g. unit) needed by
- * zfcp_fsf_abort_fcp_command before calling that routine
- * since that routine is not allowed to access
- * fsf_req which it is going to abort.
- * This is because of we need to release fsf_req_list_lock
- * before calling zfcp_fsf_abort_fcp_command.
- * Since this lock will not be held, fsf_req may complete
- * late and may be released meanwhile.
- */
- ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit);
- /*
- * We block (call schedule)
- * That's why we must release the lock and enable the
- * interrupts before.
- * On the other hand we do not need the lock anymore since
- * all critical accesses to scsi_req are done.
- */
+ /* don't access old_fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
/* call FSF routine which does the abort */
new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req,
adapter, unit, 0);
- ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req);
if (!new_fsf_req) {
+ ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
retval = FAILED;
- ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd "
- "failed\n");
- strncpy(dbf_result, "##nores", ZFCP_ABORT_DBF_LENGTH);
goto out;
}
/* wait for completion of abort */
- ZFCP_LOG_DEBUG("waiting for cleanup...\n");
-#if 1
- /*
- * FIXME:
- * copying zfcp_fsf_req_wait_and_cleanup code is not really nice
- */
__wait_event(new_fsf_req->completion_wq,
new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- status = new_fsf_req->status;
- dbf_fsf_status = new_fsf_req->qtcb->header.fsf_status;
- /*
- * Ralphs special debug load provides timestamps in the FSF
- * status qualifier. This might be specified later if being
- * useful for debugging aborts.
- */
- dbf_fsf_qual[0] =
- *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
- dbf_fsf_qual[1] =
- *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
- zfcp_fsf_req_free(new_fsf_req);
-#else
- retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
- ZFCP_UNINTERRUPTIBLE, &status);
-#endif
- ZFCP_LOG_DEBUG("Waiting for cleanup complete, status=0x%x\n", status);
+
/* status should be valid since signals were not permitted */
- if (status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+ if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
retval = SUCCESS;
- strncpy(dbf_result, "##succ", ZFCP_ABORT_DBF_LENGTH);
- } else if (status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+ } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
retval = SUCCESS;
- strncpy(dbf_result, "##late2", ZFCP_ABORT_DBF_LENGTH);
} else {
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
retval = FAILED;
- strncpy(dbf_result, "##fail", ZFCP_ABORT_DBF_LENGTH);
}
-
+ zfcp_fsf_req_free(new_fsf_req);
out:
- debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH);
- debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t));
- debug_event(adapter->abort_dbf, 1, &dbf_fcp_lun, sizeof (fcp_lun_t));
- debug_event(adapter->abort_dbf, 1, &dbf_retries, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_allowed, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_timeout, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_fsf_req, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_fsf_status, sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64));
- debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64));
- debug_text_event(adapter->abort_dbf, 1, dbf_result);
-
- spin_lock_irq(scsi_host->host_lock);
return retval;
}
-int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
-{
- int rc;
- struct Scsi_Host *scsi_host = scpnt->device->host;
- spin_lock_irq(scsi_host->host_lock);
- rc = __zfcp_scsi_eh_abort_handler(scpnt);
- spin_unlock_irq(scsi_host->host_lock);
- return rc;
-}
-
/*
* function: zfcp_scsi_eh_device_reset_handler
*
@@ -634,7 +512,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
int retval;
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
- struct Scsi_Host *scsi_host = scpnt->device->host;
if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
@@ -652,8 +529,9 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
*/
if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
&unit->status)) {
- retval =
- zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET);
+ retval = zfcp_task_management_function(unit,
+ FCP_LOGICAL_UNIT_RESET,
+ scpnt);
if (retval) {
ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
if (retval == -ENOTSUPP)
@@ -669,7 +547,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
goto out;
}
}
- retval = zfcp_task_management_function(unit, FCP_TARGET_RESET);
+ retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
if (retval) {
ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
retval = FAILED;
@@ -682,12 +560,12 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
}
static int
-zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags)
+zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
+ struct scsi_cmnd *scpnt)
{
struct zfcp_adapter *adapter = unit->port->adapter;
- int retval;
- int status;
struct zfcp_fsf_req *fsf_req;
+ int retval = 0;
/* issue task management function */
fsf_req = zfcp_fsf_send_fcp_command_task_management
@@ -697,72 +575,63 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags)
"failed for unit 0x%016Lx on port 0x%016Lx on "
"adapter %s\n", unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_adapter(adapter));
+ zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt);
retval = -ENOMEM;
goto out;
}
- retval = zfcp_fsf_req_wait_and_cleanup(fsf_req,
- ZFCP_UNINTERRUPTIBLE, &status);
+ __wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+
/*
* check completion status of task management function
- * (status should always be valid since no signals permitted)
*/
- if (status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED)
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
+ zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
retval = -EIO;
- else if (status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP)
+ } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {
+ zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt);
retval = -ENOTSUPP;
- else
- retval = 0;
+ } else
+ zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
+
+ zfcp_fsf_req_free(fsf_req);
out:
return retval;
}
-/*
- * function: zfcp_scsi_eh_bus_reset_handler
- *
- * purpose:
- *
- * returns:
+/**
+ * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter)
*/
int
zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
{
- int retval = 0;
- struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
+ struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
+ struct zfcp_adapter *adapter = unit->port->adapter;
- unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
- zfcp_erp_wait(unit->port->adapter);
- retval = SUCCESS;
+ zfcp_erp_adapter_reopen(adapter, 0);
+ zfcp_erp_wait(adapter);
- return retval;
+ return SUCCESS;
}
-/*
- * function: zfcp_scsi_eh_host_reset_handler
- *
- * purpose:
- *
- * returns:
+/**
+ * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter)
*/
int
zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
- int retval = 0;
- struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
+ struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
+ struct zfcp_adapter *adapter = unit->port->adapter;
- unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
- zfcp_erp_wait(unit->port->adapter);
- retval = SUCCESS;
+ zfcp_erp_adapter_reopen(adapter, 0);
+ zfcp_erp_wait(adapter);
- return retval;
+ return SUCCESS;
}
/*
@@ -829,10 +698,17 @@ void
zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
{
struct Scsi_Host *shost;
+ struct zfcp_port *port;
shost = adapter->scsi_host;
if (!shost)
return;
+ read_lock_irq(&zfcp_data.config_lock);
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (port->rport)
+ port->rport = NULL;
+ read_unlock_irq(&zfcp_data.config_lock);
+ fc_remove_host(shost);
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
@@ -913,6 +789,14 @@ struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
.show_starget_node_name = 1,
+ .show_rport_supported_classes = 1,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_maxframe_size = 1,
+ .show_host_serial_number = 1,
+ .show_host_speed = 1,
+ .show_host_port_id = 1,
};
/**
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index e7345a74800a..0cd435280e7d 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -62,21 +62,18 @@ static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct devi
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL);
ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
-ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn);
-ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn);
-ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
+ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
+ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed);
ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
fc_topologies[adapter->fc_topology]);
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
adapter->hardware_version);
-ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
@@ -255,21 +252,18 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_in_recovery.attr,
&dev_attr_port_remove.attr,
&dev_attr_port_add.attr,
- &dev_attr_wwnn.attr,
- &dev_attr_wwpn.attr,
- &dev_attr_s_id.attr,
&dev_attr_peer_wwnn.attr,
&dev_attr_peer_wwpn.attr,
&dev_attr_peer_d_id.attr,
+ &dev_attr_physical_wwpn.attr,
+ &dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
- &dev_attr_fc_link_speed.attr,
&dev_attr_fc_service_class.attr,
&dev_attr_fc_topology.attr,
&dev_attr_scsi_host_no.attr,
&dev_attr_status.attr,
&dev_attr_hardware_version.attr,
- &dev_attr_serial_number.attr,
NULL
};
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 7a84c7d474d9..c55e82d91deb 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -67,7 +67,6 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
-ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -263,7 +262,6 @@ static struct attribute_group zfcp_port_common_attr_group = {
static struct attribute *zfcp_port_no_ns_attrs[] = {
&dev_attr_unit_add.attr,
&dev_attr_unit_remove.attr,
- &dev_attr_scsi_id.attr,
NULL
};
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig
index a41778a490d6..3a8152906bf6 100644
--- a/drivers/sbus/char/Kconfig
+++ b/drivers/sbus/char/Kconfig
@@ -69,11 +69,40 @@ config SUN_JSFLASH
If you say Y here, you will be able to boot from your JavaStation's
Flash memory.
-# XXX Why don't we do "source drivers/char/Config.in" somewhere?
-# no shit
-config RTC
- tristate "PC-style Real Time Clock Support"
- depends on PCI && EXPERIMENTAL && SPARC32
+config BBC_I2C
+ tristate "UltraSPARC-III bootbus i2c controller driver"
+ depends on PCI && SPARC64
+ help
+ The BBC devices on the UltraSPARC III have two I2C controllers. The
+ first I2C controller connects mainly to configuration PROMs (NVRAM,
+ CPU configuration, DIMM types, etc.). The second I2C controller
+ connects to environmental control devices such as fans and
+ temperature sensors. The second controller also connects to the
+ smartcard reader, if present. Say Y to enable support for these.
+
+config ENVCTRL
+ tristate "SUNW, envctrl support"
+ depends on PCI && SPARC64
+ help
+ Kernel support for temperature and fan monitoring on Sun SME
+ machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called envctrl.
+
+config DISPLAY7SEG
+ tristate "7-Segment Display support"
+ depends on PCI && SPARC64
+ ---help---
+ This is the driver for the 7-segment display and LED present on
+ Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+ To compile this driver as a module, choose M here: the
+ module will be called display7seg.
+
+ If you do not have a CompactPCI model CP1400 or CP1500, or
+ another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
+ you should say N to this option.
endmenu
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index d96cc47de566..672f9f2b2163 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -871,8 +871,7 @@ static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * reg
#ifdef AURORA_INT_DEBUG
static void aurora_timer (unsigned long ignored);
-static struct timer_list aurora_poll_timer =
- TIMER_INITIALIZER(aurora_timer, 0, 0);
+static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0);
static void
aurora_timer (unsigned long ignored)
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index b8a2c7353b0a..d89f83f769f5 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -5,15 +5,15 @@
*/
#define __KERNEL_SYSCALLS__
+static int errno;
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/oplib.h>
#include <asm/ebus.h>
-static int errno;
-#include <asm/unistd.h>
#include "bbc_i2c.h"
#include "max1617.h"
@@ -459,10 +459,6 @@ static struct task_struct *kenvctrld_task;
static int kenvctrld(void *__unused)
{
- daemonize("kenvctrld");
- allow_signal(SIGKILL);
- kenvctrld_task = current;
-
printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n");
last_warning_jiffies = jiffies - WARN_INTERVAL;
for (;;) {
@@ -470,7 +466,7 @@ static int kenvctrld(void *__unused)
struct bbc_fan_control *fp;
msleep_interruptible(POLL_INTERVAL);
- if (signal_pending(current))
+ if (kthread_should_stop())
break;
for (tp = all_bbc_temps; tp; tp = tp->next) {
@@ -577,7 +573,6 @@ int bbc_envctrl_init(void)
int temp_index = 0;
int fan_index = 0;
int devidx = 0;
- int err = 0;
while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
if (!strcmp(echild->prom_name, "temperature"))
@@ -585,9 +580,13 @@ int bbc_envctrl_init(void)
if (!strcmp(echild->prom_name, "fan-control"))
attach_one_fan(echild, fan_index++);
}
- if (temp_index != 0 && fan_index != 0)
- err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
- return err;
+ if (temp_index != 0 && fan_index != 0) {
+ kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+ if (IS_ERR(kenvctrld_task))
+ return PTR_ERR(kenvctrld_task);
+ }
+
+ return 0;
}
static void destroy_one_temp(struct bbc_cpu_temperature *tp)
@@ -607,26 +606,7 @@ void bbc_envctrl_cleanup(void)
struct bbc_cpu_temperature *tp;
struct bbc_fan_control *fp;
- if (kenvctrld_task != NULL) {
- force_sig(SIGKILL, kenvctrld_task);
- for (;;) {
- struct task_struct *p;
- int found = 0;
-
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p == kenvctrld_task) {
- found = 1;
- break;
- }
- }
- read_unlock(&tasklist_lock);
- if (!found)
- break;
- msleep(1000);
- }
- kenvctrld_task = NULL;
- }
+ kthread_stop(kenvctrld_task);
tp = all_bbc_temps;
while (tp != NULL) {
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index 87302fb14885..ccb20a6f5f36 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -295,8 +295,7 @@ static unsigned short get_pins(unsigned minor)
static void snooze(unsigned long snooze_time, unsigned minor)
{
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(snooze_time + 1);
+ schedule_timeout_uninterruptible(snooze_time + 1);
}
static int wait_for(unsigned short set, unsigned short clr,
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index dbad7f35eb0a..24ed5893b4f0 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -14,7 +14,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
-#include <linux/ioport.h> /* request_region, check_region */
+#include <linux/ioport.h> /* request_region */
#include <asm/atomic.h>
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 9a8c572554f5..b0cc3c2588fd 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -20,10 +20,12 @@
*/
#define __KERNEL_SYSCALLS__
+static int errno;
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/kthread.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/ioport.h>
@@ -37,9 +39,6 @@
#include <asm/uaccess.h>
#include <asm/envctrl.h>
-static int errno;
-#include <asm/unistd.h>
-
#define ENVCTRL_MINOR 162
#define PCF8584_ADDRESS 0x55
@@ -1010,16 +1009,13 @@ static int kenvctrld(void *__unused)
poll_interval = 5000; /* TODO env_mon_interval */
- daemonize("kenvctrld");
- allow_signal(SIGKILL);
-
- kenvctrld_task = current;
-
printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
for (;;) {
- if(msleep_interruptible(poll_interval))
- break;
+ msleep_interruptible(poll_interval);
+ if (kthread_should_stop())
+ break;
+
for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) {
if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
ENVCTRL_CPUTEMP_MON,
@@ -1041,7 +1037,6 @@ static int kenvctrld(void *__unused)
static int __init envctrl_init(void)
{
-#ifdef CONFIG_PCI
struct linux_ebus *ebus = NULL;
struct linux_ebus_device *edev = NULL;
struct linux_ebus_child *edev_child = NULL;
@@ -1118,9 +1113,11 @@ done:
i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
}
- err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
- if (err < 0)
+ kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+ if (IS_ERR(kenvctrld_task)) {
+ err = PTR_ERR(kenvctrld_task);
goto out_deregister;
+ }
return 0;
@@ -1133,37 +1130,13 @@ out_iounmap:
kfree(i2c_childlist[i].tables);
}
return err;
-#else
- return -ENODEV;
-#endif
}
static void __exit envctrl_cleanup(void)
{
int i;
- if (NULL != kenvctrld_task) {
- force_sig(SIGKILL, kenvctrld_task);
- for (;;) {
- struct task_struct *p;
- int found = 0;
-
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p == kenvctrld_task) {
- found = 1;
- break;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (!found)
- break;
-
- msleep(1000);
- }
- kenvctrld_task = NULL;
- }
+ kthread_stop(kenvctrld_task);
iounmap(i2c);
misc_deregister(&envctrl_dev);
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
index e56a43af0f62..a7782e7da42e 100644
--- a/drivers/sbus/char/vfc.h
+++ b/drivers/sbus/char/vfc.h
@@ -129,8 +129,6 @@ struct vfc_dev {
struct vfc_regs *phys_regs;
unsigned int control_reg;
struct semaphore device_lock_sem;
- struct timer_list poll_timer;
- wait_queue_head_t poll_wait;
int instance;
int busy;
unsigned long which_io;
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 86ce54130954..7a103698fa3c 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -137,7 +137,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance)
dev->instance=instance;
init_MUTEX(&dev->device_lock_sem);
dev->control_reg=0;
- init_waitqueue_head(&dev->poll_wait);
dev->busy=0;
return 0;
}
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 1faf1e75f71f..ceec30648f4f 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -79,25 +79,9 @@ int vfc_pcf8584_init(struct vfc_dev *dev)
return 0;
}
-void vfc_i2c_delay_wakeup(struct vfc_dev *dev)
-{
- /* Used to profile code and eliminate too many delays */
- VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance));
- wake_up(&dev->poll_wait);
-}
-
void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs)
{
- DEFINE_WAIT(wait);
- init_timer(&dev->poll_timer);
- dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs);
- dev->poll_timer.data=(unsigned long)dev;
- dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup;
- add_timer(&dev->poll_timer);
- prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE);
- schedule();
- del_timer(&dev->poll_timer);
- finish_wait(&dev->poll_wait, &wait);
+ schedule_timeout_uninterruptible(usecs_to_jiffies(usecs));
}
void inline vfc_i2c_delay(struct vfc_dev *dev)
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index bc6e4627c7a1..a748fbfb6692 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -59,6 +59,8 @@
Fix 'handled=1' ISR usage, remove bogus IRQ check.
Remove un-needed eh_abort handler.
Add support for embedded firmware error strings.
+ 2.26.02.003 - Correctly handle single sgl's with use_sg=1.
+ 2.26.02.004 - Add support for 9550SX controllers.
*/
#include <linux/module.h>
@@ -81,7 +83,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.002"
+#define TW_DRIVER_VERSION "2.26.02.004"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -891,11 +893,6 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
}
- if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing");
- writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
- }
-
if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
if (tw_dev->reset_print == 0) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing");
@@ -929,6 +926,36 @@ out:
return retval;
} /* End twa_empty_response_queue() */
+/* This function will clear the pchip/response queue on 9550SX */
+static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
+{
+ u32 status_reg_value, response_que_value;
+ int count = 0, retval = 1;
+
+ if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+
+ while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
+ response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
+ if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) {
+ /* P-chip settle time */
+ msleep(500);
+ retval = 0;
+ goto out;
+ }
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ count++;
+ }
+ if (count == TW_MAX_RESPONSE_DRAIN)
+ goto out;
+
+ retval = 0;
+ } else
+ retval = 0;
+out:
+ return retval;
+} /* End twa_empty_response_queue_large() */
+
/* This function passes sense keys from firmware to scsi layer */
static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host)
{
@@ -1612,8 +1639,16 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset;
while (tries < TW_MAX_RESET_TRIES) {
- if (do_soft_reset)
+ if (do_soft_reset) {
TW_SOFT_RESET(tw_dev);
+ /* Clear pchip/response queue on 9550SX */
+ if (twa_empty_response_queue_large(tw_dev)) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x36, "Response queue (large) empty failed during reset sequence");
+ do_soft_reset = 1;
+ tries++;
+ continue;
+ }
+ }
/* Make sure controller is in a good state */
if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) {
@@ -1805,6 +1840,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
+ memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
} else {
buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
if (buffaddr == 0)
@@ -1823,6 +1860,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
if (tw_dev->srb[request_id]->use_sg > 0) {
if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
+ struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+ char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
} else {
@@ -1888,11 +1931,20 @@ out:
/* This function completes an execute scsi operation */
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
{
- /* Copy the response if too small */
- if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
- memcpy(tw_dev->srb[request_id]->request_buffer,
- tw_dev->generic_buffer_virt[request_id],
- tw_dev->srb[request_id]->request_bufflen);
+ if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
+ (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
+ tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
+ if (tw_dev->srb[request_id]->use_sg == 0) {
+ memcpy(tw_dev->srb[request_id]->request_buffer,
+ tw_dev->generic_buffer_virt[request_id],
+ tw_dev->srb[request_id]->request_bufflen);
+ }
+ if (tw_dev->srb[request_id]->use_sg == 1) {
+ struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+ char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
}
} /* End twa_scsiop_execute_scsi_complete() */
@@ -2016,7 +2068,10 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
goto out_free_device_extension;
}
- mem_addr = pci_resource_start(pdev, 1);
+ if (pdev->device == PCI_DEVICE_ID_3WARE_9000)
+ mem_addr = pci_resource_start(pdev, 1);
+ else
+ mem_addr = pci_resource_start(pdev, 2);
/* Save base address */
tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE);
@@ -2130,6 +2185,8 @@ static void twa_remove(struct pci_dev *pdev)
static struct pci_device_id twa_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ }
};
MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 8c8ecbed3b58..46f22cdc8298 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -267,7 +267,6 @@ static twa_message_type twa_error_table[] = {
#define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000
#define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000
#define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000
-#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008
/* Status register bit definitions */
#define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000
@@ -285,9 +284,8 @@ static twa_message_type twa_error_table[] = {
#define TW_STATUS_MICROCONTROLLER_READY 0x00002000
#define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000
#define TW_STATUS_EXPECTED_BITS 0x00002000
-#define TW_STATUS_UNEXPECTED_BITS 0x00F00008
-#define TW_STATUS_SBUF_WRITE_ERROR 0x00000008
-#define TW_STATUS_VALID_INTERRUPT 0x00DF0008
+#define TW_STATUS_UNEXPECTED_BITS 0x00F00000
+#define TW_STATUS_VALID_INTERRUPT 0x00DF0000
/* RESPONSE QUEUE BIT DEFINITIONS */
#define TW_RESPONSE_ID_MASK 0x00000FF0
@@ -324,9 +322,9 @@ static twa_message_type twa_error_table[] = {
/* Compatibility defines */
#define TW_9000_ARCH_ID 0x5
-#define TW_CURRENT_DRIVER_SRL 28
-#define TW_CURRENT_DRIVER_BUILD 9
-#define TW_CURRENT_DRIVER_BRANCH 4
+#define TW_CURRENT_DRIVER_SRL 30
+#define TW_CURRENT_DRIVER_BUILD 80
+#define TW_CURRENT_DRIVER_BRANCH 0
/* Phase defines */
#define TW_PHASE_INITIAL 0
@@ -334,6 +332,7 @@ static twa_message_type twa_error_table[] = {
#define TW_PHASE_SGLIST 2
/* Misc defines */
+#define TW_9550SX_DRAIN_COMPLETED 0xFFFF
#define TW_SECTOR_SIZE 512
#define TW_ALIGNMENT_9000 4 /* 4 bytes */
#define TW_ALIGNMENT_9000_SGL 0x3
@@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = {
#ifndef PCI_DEVICE_ID_3WARE_9000
#define PCI_DEVICE_ID_3WARE_9000 0x1002
#endif
+#ifndef PCI_DEVICE_ID_3WARE_9550SX
+#define PCI_DEVICE_ID_3WARE_9550SX 0x1003
+#endif
/* Bitmask macros to eliminate bitfields */
@@ -443,6 +445,7 @@ static twa_message_type twa_error_table[] = {
#define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4)
#define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8))
#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
+#define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30)
#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 973c51fb0fe2..ae9e0203e9de 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
return 0;
} /* End tw_scsiop_inquiry() */
+static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
+ void *data, unsigned int len)
+{
+ struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+ void *buf;
+ unsigned int transfer_len;
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg =
+ (struct scatterlist *)cmd->request_buffer;
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ transfer_len = min(sg->length, len);
+ } else {
+ buf = cmd->request_buffer;
+ transfer_len = min(cmd->request_bufflen, len);
+ }
+
+ memcpy(buf, data, transfer_len);
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *)cmd->request_buffer;
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
+}
+
/* This function is called by the isr to complete an inquiry command */
static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
{
unsigned char *is_unit_present;
- unsigned char *request_buffer;
+ unsigned char request_buffer[36];
TW_Param *param;
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
- /* Fill request buffer */
- if (tw_dev->srb[request_id]->request_buffer == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
- return 1;
- }
- request_buffer = tw_dev->srb[request_id]->request_buffer;
- memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(request_buffer, 0, sizeof(request_buffer));
request_buffer[0] = TYPE_DISK; /* Peripheral device type */
request_buffer[1] = 0; /* Device type modifier */
request_buffer[2] = 0; /* No ansi/iso compliance */
@@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_i
memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */
sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);
+ tw_transfer_internal(tw_dev, request_id, request_buffer,
+ sizeof(request_buffer));
param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
if (param == NULL) {
@@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
{
TW_Param *param;
unsigned char *flags;
- unsigned char *request_buffer;
+ unsigned char request_buffer[8];
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
@@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
return 1;
}
flags = (char *)&(param->data[0]);
- request_buffer = tw_dev->srb[request_id]->buffer;
- memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(request_buffer, 0, sizeof(request_buffer));
request_buffer[0] = 0xf; /* mode data length */
request_buffer[1] = 0; /* default medium type */
@@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
request_buffer[6] = 0x4; /* WCE on */
else
request_buffer[6] = 0x0; /* WCE off */
+ tw_transfer_internal(tw_dev, request_id, request_buffer,
+ sizeof(request_buffer));
return 0;
} /* End tw_scsiop_mode_sense_complete() */
@@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req
{
unsigned char *param_data;
u32 capacity;
- char *buff;
+ char buff[8];
TW_Param *param;
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
- buff = tw_dev->srb[request_id]->request_buffer;
- if (buff == NULL) {
- printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
- return 1;
- }
- memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+ memset(buff, 0, sizeof(buff));
param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
if (param == NULL) {
printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
@@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req
buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
buff[7] = TW_BLOCK_SIZE & 0xff;
+ tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));
+
return 0;
} /* End tw_scsiop_read_capacity_complete() */
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 2341d27ceed7..7a33c708f5b3 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -6090,8 +6090,8 @@ NCR53c7x0_release(struct Scsi_Host *host) {
if (hostdata->num_cmds)
printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
host->host_no, hostdata->num_cmds);
- if (hostdata->events)
- vfree ((void *)hostdata->events);
+
+ vfree(hostdata->events);
/* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
* XXX may be invalid (CONFIG_060_WRITETHROUGH)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index f1e8c4223ed1..9c9f162bd6ed 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1,5 +1,11 @@
menu "SCSI device support"
+config RAID_ATTRS
+ tristate "RAID Transport Class"
+ default n
+ ---help---
+ Provides RAID
+
config SCSI
tristate "SCSI device support"
---help---
@@ -229,6 +235,13 @@ config SCSI_ISCSI_ATTRS
each attached iSCSI device to sysfs, say Y.
Otherwise, say N.
+config SCSI_SAS_ATTRS
+ tristate "SAS Transport Attributes"
+ depends on SCSI
+ help
+ If you wish to export transport-specific information about
+ each attached SAS device to sysfs, say Y.
+
endmenu
menu "SCSI low-level drivers"
@@ -250,7 +263,7 @@ config SCSI_DECNCR
config SCSI_DECSII
tristate "DEC SII Scsi Driver"
- depends on MACH_DECSTATION && SCSI && MIPS32
+ depends on MACH_DECSTATION && SCSI && 32BIT
config BLK_DEV_3W_XXXX_RAID
tristate "3ware 5/6/7/8xxx ATA-RAID support"
@@ -459,6 +472,15 @@ config SCSI_ATA_PIIX
If unsure, say N.
+config SCSI_SATA_MV
+ tristate "Marvell SATA support"
+ depends on SCSI_SATA && PCI && EXPERIMENTAL
+ help
+ This option enables support for the Marvell Serial ATA family.
+ Currently supports 88SX[56]0[48][01] chips.
+
+ If unsure, say N.
+
config SCSI_SATA_NV
tristate "NVIDIA SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -467,11 +489,11 @@ config SCSI_SATA_NV
If unsure, say N.
-config SCSI_SATA_PROMISE
- tristate "Promise SATA TX2/TX4 support"
+config SCSI_PDC_ADMA
+ tristate "Pacific Digital ADMA support"
depends on SCSI_SATA && PCI
help
- This option enables support for Promise Serial ATA TX2/TX4.
+ This option enables support for Pacific Digital ADMA controllers
If unsure, say N.
@@ -483,6 +505,14 @@ config SCSI_SATA_QSTOR
If unsure, say N.
+config SCSI_SATA_PROMISE
+ tristate "Promise SATA TX2/TX4 support"
+ depends on SCSI_SATA && PCI
+ help
+ This option enables support for Promise Serial ATA TX2/TX4.
+
+ If unsure, say N.
+
config SCSI_SATA_SX4
tristate "Promise SATA SX4 support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -499,6 +529,14 @@ config SCSI_SATA_SIL
If unsure, say N.
+config SCSI_SATA_SIL24
+ tristate "Silicon Image 3124/3132 SATA support"
+ depends on SCSI_SATA && PCI && EXPERIMENTAL
+ help
+ This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+ If unsure, say N.
+
config SCSI_SATA_SIS
tristate "SiS 964/180 SATA support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -531,6 +569,11 @@ config SCSI_SATA_VITESSE
If unsure, say N.
+config SCSI_SATA_INTEL_COMBINED
+ bool
+ depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX)
+ default y
+
config SCSI_BUSLOGIC
tristate "BusLogic SCSI support"
depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
@@ -1696,7 +1739,7 @@ config TT_DMA_EMUL
config MAC_SCSI
bool "Macintosh NCR5380 SCSI"
- depends on MAC && SCSI
+ depends on MAC && SCSI=y
help
This is the NCR 5380 SCSI controller included on most of the 68030
based Macintoshes. If you have one of these say Y and read the
@@ -1717,7 +1760,7 @@ config SCSI_MAC_ESP
config MVME147_SCSI
bool "WD33C93 SCSI driver for MVME147"
- depends on MVME147 && SCSI
+ depends on MVME147 && SCSI=y
help
Support for the on-board SCSI controller on the Motorola MVME147
single-board computer.
@@ -1758,7 +1801,7 @@ config SUN3_SCSI
config SUN3X_ESP
bool "Sun3x ESP SCSI"
- depends on SUN3X && SCSI
+ depends on SUN3X && SCSI=y
help
The ESP was an on-board SCSI controller used on Sun 3/80
machines. Say Y here to compile in support for it.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 3746fb9fa2f5..2d4439826c08 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -22,6 +22,8 @@ subdir-$(CONFIG_PCMCIA) += pcmcia
obj-$(CONFIG_SCSI) += scsi_mod.o
+obj-$(CONFIG_RAID_ATTRS) += raid_class.o
+
# --- NOTE ORDERING HERE ---
# For kernel non-modular link, transport attributes need to
# be initialised before drivers
@@ -29,6 +31,7 @@ obj-$(CONFIG_SCSI) += scsi_mod.o
obj-$(CONFIG_SCSI_SPI_ATTRS) += scsi_transport_spi.o
obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o
obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
+obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o
obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
@@ -96,6 +99,7 @@ obj-$(CONFIG_SCSI_DC395x) += dc395x.o
obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
+obj-$(CONFIG_MEGARAID_SAS) += megaraid/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
obj-$(CONFIG_SCSI_SUNESP) += esp.o
obj-$(CONFIG_SCSI_GDTH) += gdth.o
@@ -126,12 +130,15 @@ obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_SIL24) += libata.o sata_sil24.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o
obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o
obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o
obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o
+obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o
+obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o
obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index f8ec6fe7d858..23392ae7df8b 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -88,6 +88,13 @@
*/
#include <scsi/scsi_dbg.h>
+#ifndef NDEBUG
+#define NDEBUG 0
+#endif
+#ifndef NDEBUG_ABORT
+#define NDEBUG_ABORT 0
+#endif
+
#if (NDEBUG & NDEBUG_LISTS)
#define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }
#define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }
@@ -359,7 +366,7 @@ static struct {
{PHASE_UNKNOWN, "UNKNOWN"}
};
-#ifdef NDEBUG
+#if NDEBUG
static struct {
unsigned char mask;
const char *name;
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 79ae73b23680..e1f2246ee7cd 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -62,7 +62,7 @@
#define SYNC_MODE 0 /* Synchronous transfer mode */
-#if DEBUG
+#ifdef DEBUG
#undef NCR53C406A_DEBUG
#define NCR53C406A_DEBUG 1
#endif
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index ccdf440021fb..93416f760e5a 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -133,6 +133,7 @@ struct inquiry_data {
static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
#ifdef AAC_DETAILED_STATUS_INFO
static char *aac_get_status_string(u32 status);
@@ -312,18 +313,37 @@ int aac_get_containers(struct aac_dev *dev)
}
dresp = (struct aac_mount *)fib_data(fibptr);
+ if ((le32_to_cpu(dresp->status) == ST_OK) &&
+ (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
+ dinfo->command = cpu_to_le32(VM_NameServe64);
+ dinfo->count = cpu_to_le32(index);
+ dinfo->type = cpu_to_le32(FT_FILESYS);
+
+ if (fib_send(ContainerCommand,
+ fibptr,
+ sizeof(struct aac_query_mount),
+ FsaNormal,
+ 1, 1,
+ NULL, NULL) < 0)
+ continue;
+ } else
+ dresp->mnt[0].capacityhigh = 0;
+
dprintk ((KERN_DEBUG
- "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%u\n",
+ "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
(int)index, (int)le32_to_cpu(dresp->status),
(int)le32_to_cpu(dresp->mnt[0].vol),
(int)le32_to_cpu(dresp->mnt[0].state),
- (unsigned)le32_to_cpu(dresp->mnt[0].capacity)));
+ ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+ (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
if ((le32_to_cpu(dresp->status) == ST_OK) &&
(le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
(le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
fsa_dev_ptr[index].valid = 1;
fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr[index].size = le32_to_cpu(dresp->mnt[0].capacity);
+ fsa_dev_ptr[index].size
+ = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+ (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
fsa_dev_ptr[index].ro = 1;
}
@@ -348,6 +368,27 @@ static void aac_io_done(struct scsi_cmnd * scsicmd)
spin_unlock_irqrestore(host->host_lock, cpu_flags);
}
+static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
+{
+ void *buf;
+ unsigned int transfer_len;
+ struct scatterlist *sg = scsicmd->request_buffer;
+
+ if (scsicmd->use_sg) {
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ transfer_len = min(sg->length, len + offset);
+ } else {
+ buf = scsicmd->request_buffer;
+ transfer_len = min(scsicmd->request_bufflen, len + offset);
+ }
+
+ memcpy(buf + offset, data, transfer_len - offset);
+
+ if (scsicmd->use_sg)
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+
+}
+
static void get_container_name_callback(void *context, struct fib * fibptr)
{
struct aac_get_name_resp * get_name_reply;
@@ -363,18 +404,22 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
/* Failure is irrelevant, using default value instead */
if ((le32_to_cpu(get_name_reply->status) == CT_OK)
&& (get_name_reply->data[0] != '\0')) {
- int count;
- char * dp;
- char * sp = get_name_reply->data;
+ char *sp = get_name_reply->data;
sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
while (*sp == ' ')
++sp;
- count = sizeof(((struct inquiry_data *)NULL)->inqd_pid);
- dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid;
- if (*sp) do {
- *dp++ = (*sp) ? *sp++ : ' ';
- } while (--count > 0);
+ if (*sp) {
+ char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+ int count = sizeof(d);
+ char *dp = d;
+ do {
+ *dp++ = (*sp) ? *sp++ : ' ';
+ } while (--count > 0);
+ aac_internal_transfer(scsicmd, d,
+ offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+ }
}
+
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
fib_complete(fibptr);
@@ -434,7 +479,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
* is updated in the struct fsa_dev_info structure rather than returned.
*/
-static int probe_container(struct aac_dev *dev, int cid)
+int probe_container(struct aac_dev *dev, int cid)
{
struct fsa_dev_info *fsa_dev_ptr;
int status;
@@ -471,11 +516,29 @@ static int probe_container(struct aac_dev *dev, int cid)
dresp = (struct aac_mount *) fib_data(fibptr);
if ((le32_to_cpu(dresp->status) == ST_OK) &&
+ (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
+ dinfo->command = cpu_to_le32(VM_NameServe64);
+ dinfo->count = cpu_to_le32(cid);
+ dinfo->type = cpu_to_le32(FT_FILESYS);
+
+ if (fib_send(ContainerCommand,
+ fibptr,
+ sizeof(struct aac_query_mount),
+ FsaNormal,
+ 1, 1,
+ NULL, NULL) < 0)
+ goto error;
+ } else
+ dresp->mnt[0].capacityhigh = 0;
+
+ if ((le32_to_cpu(dresp->status) == ST_OK) &&
(le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
(le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
fsa_dev_ptr[cid].valid = 1;
fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr[cid].size = le32_to_cpu(dresp->mnt[0].capacity);
+ fsa_dev_ptr[cid].size
+ = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+ (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
fsa_dev_ptr[cid].ro = 1;
}
@@ -629,7 +692,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
fibptr,
sizeof(*info),
FsaNormal,
- 1, 1,
+ -1, 1, /* First `interrupt' command uses special wait */
NULL,
NULL);
@@ -777,34 +840,36 @@ int aac_get_adapter_info(struct aac_dev* dev)
/*
* 57 scatter gather elements
*/
- dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
- sizeof(struct aac_fibhdr) -
- sizeof(struct aac_write) + sizeof(struct sgmap)) /
- sizeof(struct sgmap);
- if (dev->dac_support) {
- /*
- * 38 scatter gather elements
- */
- dev->scsi_host_ptr->sg_tablesize =
- (dev->max_fib_size -
+ if (!(dev->raw_io_interface)) {
+ dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
sizeof(struct aac_fibhdr) -
- sizeof(struct aac_write64) +
- sizeof(struct sgmap64)) /
- sizeof(struct sgmap64);
- }
- dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
- if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
- /*
- * Worst case size that could cause sg overflow when
- * we break up SG elements that are larger than 64KB.
- * Would be nice if we could tell the SCSI layer what
- * the maximum SG element size can be. Worst case is
- * (sg_tablesize-1) 4KB elements with one 64KB
- * element.
- * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
- */
- dev->scsi_host_ptr->max_sectors =
- (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ sizeof(struct aac_write) + sizeof(struct sgentry)) /
+ sizeof(struct sgentry);
+ if (dev->dac_support) {
+ /*
+ * 38 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize =
+ (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write64) +
+ sizeof(struct sgentry64)) /
+ sizeof(struct sgentry64);
+ }
+ dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+ /*
+ * Worst case size that could cause sg overflow when
+ * we break up SG elements that are larger than 64KB.
+ * Would be nice if we could tell the SCSI layer what
+ * the maximum SG element size can be. Worst case is
+ * (sg_tablesize-1) 4KB elements with one 64KB
+ * element.
+ * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
+ */
+ dev->scsi_host_ptr->max_sectors =
+ (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
}
fib_complete(fibptr);
@@ -814,12 +879,11 @@ int aac_get_adapter_info(struct aac_dev* dev)
}
-static void read_callback(void *context, struct fib * fibptr)
+static void io_callback(void *context, struct fib * fibptr)
{
struct aac_dev *dev;
struct aac_read_reply *readreply;
struct scsi_cmnd *scsicmd;
- u32 lba;
u32 cid;
scsicmd = (struct scsi_cmnd *) context;
@@ -827,8 +891,40 @@ static void read_callback(void *context, struct fib * fibptr)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
- lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
- dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ if (nblank(dprintk(x))) {
+ u64 lba;
+ switch (scsicmd->cmnd[0]) {
+ case WRITE_6:
+ case READ_6:
+ lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
+ (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
+ break;
+ case WRITE_16:
+ case READ_16:
+ lba = ((u64)scsicmd->cmnd[2] << 56) |
+ ((u64)scsicmd->cmnd[3] << 48) |
+ ((u64)scsicmd->cmnd[4] << 40) |
+ ((u64)scsicmd->cmnd[5] << 32) |
+ ((u64)scsicmd->cmnd[6] << 24) |
+ (scsicmd->cmnd[7] << 16) |
+ (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+ break;
+ case WRITE_12:
+ case READ_12:
+ lba = ((u64)scsicmd->cmnd[2] << 24) |
+ (scsicmd->cmnd[3] << 16) |
+ (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ break;
+ default:
+ lba = ((u64)scsicmd->cmnd[2] << 24) |
+ (scsicmd->cmnd[3] << 16) |
+ (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ break;
+ }
+ printk(KERN_DEBUG
+ "io_callback[cpu %d]: lba = %llu, t = %ld.\n",
+ smp_processor_id(), (unsigned long long)lba, jiffies);
+ }
if (fibptr == NULL)
BUG();
@@ -847,7 +943,7 @@ static void read_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
#ifdef AAC_DETAILED_STATUS_INFO
- printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+ printk(KERN_WARNING "io_callback: io failed, status = %d\n",
le32_to_cpu(readreply->status));
#endif
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
@@ -867,56 +963,9 @@ static void read_callback(void *context, struct fib * fibptr)
aac_io_done(scsicmd);
}
-static void write_callback(void *context, struct fib * fibptr)
-{
- struct aac_dev *dev;
- struct aac_write_reply *writereply;
- struct scsi_cmnd *scsicmd;
- u32 lba;
- u32 cid;
-
- scsicmd = (struct scsi_cmnd *) context;
- dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
-
- lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
- dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
- if (fibptr == NULL)
- BUG();
-
- if(scsicmd->use_sg)
- pci_unmap_sg(dev->pdev,
- (struct scatterlist *)scsicmd->buffer,
- scsicmd->use_sg,
- scsicmd->sc_data_direction);
- else if(scsicmd->request_bufflen)
- pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
- scsicmd->request_bufflen,
- scsicmd->sc_data_direction);
-
- writereply = (struct aac_write_reply *) fib_data(fibptr);
- if (le32_to_cpu(writereply->status) == ST_OK)
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
- else {
- printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
- set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
- HARDWARE_ERROR,
- SENCODE_INTERNAL_TARGET_FAILURE,
- ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
- 0, 0);
- memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
- sizeof(struct sense_data));
- }
-
- fib_complete(fibptr);
- fib_free(fibptr);
- aac_io_done(scsicmd);
-}
-
static int aac_read(struct scsi_cmnd * scsicmd, int cid)
{
- u32 lba;
+ u64 lba;
u32 count;
int status;
@@ -928,23 +977,69 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Get block address and transfer length
*/
- if (scsicmd->cmnd[0] == READ_6) /* 6 byte command */
- {
+ switch (scsicmd->cmnd[0]) {
+ case READ_6:
dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
- lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
+ lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
+ (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
count = scsicmd->cmnd[4];
if (count == 0)
count = 256;
- } else {
+ break;
+ case READ_16:
+ dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid));
+
+ lba = ((u64)scsicmd->cmnd[2] << 56) |
+ ((u64)scsicmd->cmnd[3] << 48) |
+ ((u64)scsicmd->cmnd[4] << 40) |
+ ((u64)scsicmd->cmnd[5] << 32) |
+ ((u64)scsicmd->cmnd[6] << 24) |
+ (scsicmd->cmnd[7] << 16) |
+ (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+ count = (scsicmd->cmnd[10] << 24) |
+ (scsicmd->cmnd[11] << 16) |
+ (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+ break;
+ case READ_12:
+ dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid));
+
+ lba = ((u64)scsicmd->cmnd[2] << 24) |
+ (scsicmd->cmnd[3] << 16) |
+ (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ count = (scsicmd->cmnd[6] << 24) |
+ (scsicmd->cmnd[7] << 16) |
+ (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+ break;
+ default:
dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
- lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ lba = ((u64)scsicmd->cmnd[2] << 24) |
+ (scsicmd->cmnd[3] << 16) |
+ (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
+ break;
}
- dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n",
+ dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
smp_processor_id(), (unsigned long long)lba, jiffies));
+ if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) &&
+ (lba & 0xffffffff00000000LL)) {
+ dprintk((KERN_DEBUG "aac_read: Illegal lba\n"));
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+ SAM_STAT_CHECK_CONDITION;
+ set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+ HARDWARE_ERROR,
+ SENCODE_INTERNAL_TARGET_FAILURE,
+ ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+ 0, 0);
+ memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+ (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
+ ? sizeof(scsicmd->sense_buffer)
+ : sizeof(dev->fsa_dev[cid].sense_data));
+ scsicmd->scsi_done(scsicmd);
+ return 0;
+ }
/*
* Alocate and initialize a Fib
*/
@@ -954,13 +1049,38 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fib_init(cmd_fibcontext);
- if (dev->dac_support == 1) {
+ if (dev->raw_io_interface) {
+ struct aac_raw_io *readcmd;
+ readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+ readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+ readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+ readcmd->count = cpu_to_le32(count<<9);
+ readcmd->cid = cpu_to_le16(cid);
+ readcmd->flags = cpu_to_le16(1);
+ readcmd->bpTotal = 0;
+ readcmd->bpComplete = 0;
+
+ aac_build_sgraw(scsicmd, &readcmd->sg);
+ fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+ BUG();
+ /*
+ * Now send the Fib to the adapter
+ */
+ status = fib_send(ContainerRawIo,
+ cmd_fibcontext,
+ fibsize,
+ FsaNormal,
+ 0, 1,
+ (fib_callback) io_callback,
+ (void *) scsicmd);
+ } else if (dev->dac_support == 1) {
struct aac_read64 *readcmd;
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtHostRead64);
readcmd->cid = cpu_to_le16(cid);
readcmd->sector_count = cpu_to_le16(count);
- readcmd->block = cpu_to_le32(lba);
+ readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
readcmd->pad = 0;
readcmd->flags = 0;
@@ -968,7 +1088,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize = sizeof(struct aac_read64) +
((le32_to_cpu(readcmd->sg.count) - 1) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -978,14 +1098,14 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) read_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
} else {
struct aac_read *readcmd;
readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtBlockRead);
readcmd->cid = cpu_to_le32(cid);
- readcmd->block = cpu_to_le32(lba);
+ readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
readcmd->count = cpu_to_le32(count * 512);
aac_build_sg(scsicmd, &readcmd->sg);
@@ -1002,7 +1122,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) read_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
}
@@ -1027,7 +1147,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
static int aac_write(struct scsi_cmnd * scsicmd, int cid)
{
- u32 lba;
+ u64 lba;
u32 count;
int status;
u16 fibsize;
@@ -1044,13 +1164,48 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
count = scsicmd->cmnd[4];
if (count == 0)
count = 256;
+ } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
+ dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid));
+
+ lba = ((u64)scsicmd->cmnd[2] << 56) |
+ ((u64)scsicmd->cmnd[3] << 48) |
+ ((u64)scsicmd->cmnd[4] << 40) |
+ ((u64)scsicmd->cmnd[5] << 32) |
+ ((u64)scsicmd->cmnd[6] << 24) |
+ (scsicmd->cmnd[7] << 16) |
+ (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+ count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
+ (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+ } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
+ dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid));
+
+ lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
+ | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
+ | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
} else {
dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
- lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+ lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
- dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n",
+ dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
smp_processor_id(), (unsigned long long)lba, jiffies));
+ if ((!(dev->raw_io_interface) || !(dev->raw_io_64))
+ && (lba & 0xffffffff00000000LL)) {
+ dprintk((KERN_DEBUG "aac_write: Illegal lba\n"));
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
+ set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+ HARDWARE_ERROR,
+ SENCODE_INTERNAL_TARGET_FAILURE,
+ ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+ 0, 0);
+ memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+ (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
+ ? sizeof(scsicmd->sense_buffer)
+ : sizeof(dev->fsa_dev[cid].sense_data));
+ scsicmd->scsi_done(scsicmd);
+ return 0;
+ }
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
@@ -1061,13 +1216,38 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
}
fib_init(cmd_fibcontext);
- if(dev->dac_support == 1) {
+ if (dev->raw_io_interface) {
+ struct aac_raw_io *writecmd;
+ writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+ writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+ writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+ writecmd->count = cpu_to_le32(count<<9);
+ writecmd->cid = cpu_to_le16(cid);
+ writecmd->flags = 0;
+ writecmd->bpTotal = 0;
+ writecmd->bpComplete = 0;
+
+ aac_build_sgraw(scsicmd, &writecmd->sg);
+ fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+ BUG();
+ /*
+ * Now send the Fib to the adapter
+ */
+ status = fib_send(ContainerRawIo,
+ cmd_fibcontext,
+ fibsize,
+ FsaNormal,
+ 0, 1,
+ (fib_callback) io_callback,
+ (void *) scsicmd);
+ } else if (dev->dac_support == 1) {
struct aac_write64 *writecmd;
writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
writecmd->command = cpu_to_le32(VM_CtHostWrite64);
writecmd->cid = cpu_to_le16(cid);
writecmd->sector_count = cpu_to_le16(count);
- writecmd->block = cpu_to_le32(lba);
+ writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
writecmd->pad = 0;
writecmd->flags = 0;
@@ -1085,14 +1265,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) write_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
} else {
struct aac_write *writecmd;
writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
writecmd->command = cpu_to_le32(VM_CtBlockWrite);
writecmd->cid = cpu_to_le32(cid);
- writecmd->block = cpu_to_le32(lba);
+ writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
writecmd->count = cpu_to_le32(count * 512);
writecmd->sg.count = cpu_to_le32(1);
/* ->stable is not used - it did mean which type of write */
@@ -1111,7 +1291,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize,
FsaNormal,
0, 1,
- (fib_callback) write_callback,
+ (fib_callback) io_callback,
(void *) scsicmd);
}
@@ -1281,11 +1461,18 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
*/
if ((fsa_dev_ptr[cid].valid & 1) == 0) {
switch (scsicmd->cmnd[0]) {
+ case SERVICE_ACTION_IN:
+ if (!(dev->raw_io_interface) ||
+ !(dev->raw_io_64) ||
+ ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+ break;
case INQUIRY:
case READ_CAPACITY:
case TEST_UNIT_READY:
spin_unlock_irq(host->host_lock);
probe_container(dev, cid);
+ if ((fsa_dev_ptr[cid].valid & 1) == 0)
+ fsa_dev_ptr[cid].valid = 0;
spin_lock_irq(host->host_lock);
if (fsa_dev_ptr[cid].valid == 0) {
scsicmd->result = DID_NO_CONNECT << 16;
@@ -1340,44 +1527,86 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
switch (scsicmd->cmnd[0]) {
case INQUIRY:
{
- struct inquiry_data *inq_data_ptr;
+ struct inquiry_data inq_data;
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
- inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
- memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
+ memset(&inq_data, 0, sizeof (struct inquiry_data));
- inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */
- inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */
- inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
- inq_data_ptr->inqd_len = 31;
+ inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
+ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
+ inq_data.inqd_len = 31;
/*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
- inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
+ inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */
/*
* Set the Vendor, Product, and Revision Level
* see: <vendor>.c i.e. aac.c
*/
if (scsicmd->device->id == host->this_id) {
- setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));
- inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */
+ setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+ inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
+ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
return 0;
}
- setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);
- inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+ setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+ inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
return aac_get_container_name(scsicmd, cid);
}
+ case SERVICE_ACTION_IN:
+ if (!(dev->raw_io_interface) ||
+ !(dev->raw_io_64) ||
+ ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+ break;
+ {
+ u64 capacity;
+ char cp[12];
+ unsigned int offset = 0;
+
+ dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
+ capacity = fsa_dev_ptr[cid].size - 1;
+ if (scsicmd->cmnd[13] > 12) {
+ offset = scsicmd->cmnd[13] - 12;
+ if (offset > sizeof(cp))
+ break;
+ memset(cp, 0, offset);
+ aac_internal_transfer(scsicmd, cp, 0, offset);
+ }
+ cp[0] = (capacity >> 56) & 0xff;
+ cp[1] = (capacity >> 48) & 0xff;
+ cp[2] = (capacity >> 40) & 0xff;
+ cp[3] = (capacity >> 32) & 0xff;
+ cp[4] = (capacity >> 24) & 0xff;
+ cp[5] = (capacity >> 16) & 0xff;
+ cp[6] = (capacity >> 8) & 0xff;
+ cp[7] = (capacity >> 0) & 0xff;
+ cp[8] = 0;
+ cp[9] = 0;
+ cp[10] = 2;
+ cp[11] = 0;
+ aac_internal_transfer(scsicmd, cp, offset, sizeof(cp));
+
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
+
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+
+ return 0;
+ }
+
case READ_CAPACITY:
{
u32 capacity;
- char *cp;
+ char cp[8];
dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
- if (fsa_dev_ptr[cid].size <= 0x100000000LL)
+ if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
capacity = fsa_dev_ptr[cid].size - 1;
else
capacity = (u32)-1;
- cp = scsicmd->request_buffer;
+
cp[0] = (capacity >> 24) & 0xff;
cp[1] = (capacity >> 16) & 0xff;
cp[2] = (capacity >> 8) & 0xff;
@@ -1386,6 +1615,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
cp[5] = 0;
cp[6] = 2;
cp[7] = 0;
+ aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1395,15 +1627,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case MODE_SENSE:
{
- char *mode_buf;
+ char mode_buf[4];
dprintk((KERN_DEBUG "MODE SENSE command.\n"));
- mode_buf = scsicmd->request_buffer;
mode_buf[0] = 3; /* Mode data length */
mode_buf[1] = 0; /* Medium type - default */
mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */
mode_buf[3] = 0; /* Block descriptor length */
+ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1411,10 +1643,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
}
case MODE_SENSE_10:
{
- char *mode_buf;
+ char mode_buf[8];
dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
- mode_buf = scsicmd->request_buffer;
mode_buf[0] = 0; /* Mode data length (MSB) */
mode_buf[1] = 6; /* Mode data length (LSB) */
mode_buf[2] = 0; /* Medium type - default */
@@ -1423,6 +1654,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
mode_buf[5] = 0; /* reserved */
mode_buf[6] = 0; /* Block descriptor length (MSB) */
mode_buf[7] = 0; /* Block descriptor length (LSB) */
+ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
scsicmd->scsi_done(scsicmd);
@@ -1466,6 +1698,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
{
case READ_6:
case READ_10:
+ case READ_12:
+ case READ_16:
/*
* Hack to keep track of ordinal number of the device that
* corresponds to a container. Needed to convert
@@ -1473,17 +1707,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
*/
spin_unlock_irq(host->host_lock);
- if (scsicmd->request->rq_disk)
- memcpy(fsa_dev_ptr[cid].devname,
- scsicmd->request->rq_disk->disk_name,
- 8);
-
+ if (scsicmd->request->rq_disk)
+ strlcpy(fsa_dev_ptr[cid].devname,
+ scsicmd->request->rq_disk->disk_name,
+ min(sizeof(fsa_dev_ptr[cid].devname),
+ sizeof(scsicmd->request->rq_disk->disk_name) + 1));
ret = aac_read(scsicmd, cid);
spin_lock_irq(host->host_lock);
return ret;
case WRITE_6:
case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
spin_unlock_irq(host->host_lock);
ret = aac_write(scsicmd, cid);
spin_lock_irq(host->host_lock);
@@ -1714,6 +1950,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
case WRITE_10:
case READ_12:
case WRITE_12:
+ case READ_16:
+ case WRITE_16:
if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) {
printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
} else {
@@ -1819,8 +2057,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
sizeof(scsicmd->sense_buffer) :
le32_to_cpu(srbreply->sense_data_size);
#ifdef AAC_DETAILED_STATUS_INFO
- dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
- le32_to_cpu(srbreply->status), len));
+ printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
+ le32_to_cpu(srbreply->status), len);
#endif
memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
@@ -1894,7 +2132,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
srbcmd->id = cpu_to_le32(scsicmd->device->id);
srbcmd->lun = cpu_to_le32(scsicmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
- timeout = (scsicmd->timeout-jiffies)/HZ;
+ timeout = scsicmd->timeout_per_command/HZ;
if(timeout == 0){
timeout = 1;
}
@@ -2077,6 +2315,76 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
return byte_count;
}
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+{
+ struct Scsi_Host *host = scsicmd->device->host;
+ struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+ unsigned long byte_count = 0;
+
+ // Get rid of old data
+ psg->count = 0;
+ psg->sg[0].next = 0;
+ psg->sg[0].prev = 0;
+ psg->sg[0].addr[0] = 0;
+ psg->sg[0].addr[1] = 0;
+ psg->sg[0].count = 0;
+ psg->sg[0].flags = 0;
+ if (scsicmd->use_sg) {
+ struct scatterlist *sg;
+ int i;
+ int sg_count;
+ sg = (struct scatterlist *) scsicmd->request_buffer;
+
+ sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
+ scsicmd->sc_data_direction);
+
+ for (i = 0; i < sg_count; i++) {
+ int count = sg_dma_len(sg);
+ u64 addr = sg_dma_address(sg);
+ psg->sg[i].next = 0;
+ psg->sg[i].prev = 0;
+ psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
+ psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+ psg->sg[i].count = cpu_to_le32(count);
+ psg->sg[i].flags = 0;
+ byte_count += count;
+ sg++;
+ }
+ psg->count = cpu_to_le32(sg_count);
+ /* hba wants the size to be exact */
+ if(byte_count > scsicmd->request_bufflen){
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
+ byte_count = scsicmd->request_bufflen;
+ }
+ /* Check for command underflow */
+ if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
+ }
+ }
+ else if(scsicmd->request_bufflen) {
+ int count;
+ u64 addr;
+ scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
+ scsicmd->request_buffer,
+ scsicmd->request_bufflen,
+ scsicmd->sc_data_direction);
+ addr = scsicmd->SCp.dma_handle;
+ count = scsicmd->request_bufflen;
+ psg->count = cpu_to_le32(1);
+ psg->sg[0].next = 0;
+ psg->sg[0].prev = 0;
+ psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
+ psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+ psg->sg[0].count = cpu_to_le32(count);
+ psg->sg[0].flags = 0;
+ byte_count = scsicmd->request_bufflen;
+ }
+ return byte_count;
+}
+
#ifdef AAC_DETAILED_STATUS_INFO
struct aac_srb_status_info {
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 4ab07861b457..d54b1cc88d0d 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1,6 +1,10 @@
#if (!defined(dprintk))
# define dprintk(x)
#endif
+/* eg: if (nblank(dprintk(x))) */
+#define _nblank(x) #x
+#define nblank(x) _nblank(x)[0]
+
/*------------------------------------------------------------------------------
* D E F I N E S
@@ -15,7 +19,7 @@
#define AAC_MAX_LUN (8)
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
-#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512)
+#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256)
/*
* These macros convert from physical channels to virtual channels
@@ -110,6 +114,22 @@ struct user_sgentry64 {
u32 count; /* Length. */
};
+struct sgentryraw {
+ __le32 next; /* reserved for F/W use */
+ __le32 prev; /* reserved for F/W use */
+ __le32 addr[2];
+ __le32 count;
+ __le32 flags; /* reserved for F/W use */
+};
+
+struct user_sgentryraw {
+ u32 next; /* reserved for F/W use */
+ u32 prev; /* reserved for F/W use */
+ u32 addr[2];
+ u32 count;
+ u32 flags; /* reserved for F/W use */
+};
+
/*
* SGMAP
*
@@ -137,6 +157,16 @@ struct user_sgmap64 {
struct user_sgentry64 sg[1];
};
+struct sgmapraw {
+ __le32 count;
+ struct sgentryraw sg[1];
+};
+
+struct user_sgmapraw {
+ u32 count;
+ struct user_sgentryraw sg[1];
+};
+
struct creation_info
{
u8 buildnum; /* e.g., 588 */
@@ -276,7 +306,6 @@ enum aac_queue_types {
*/
#define FsaNormal 1
-#define FsaHigh 2
/*
* Define the FIB. The FIB is the where all the requested data and
@@ -351,6 +380,7 @@ struct hw_fib {
*/
#define ContainerCommand 500
#define ContainerCommand64 501
+#define ContainerRawIo 502
/*
* Cluster Commands
*/
@@ -456,6 +486,7 @@ struct adapter_ops
{
void (*adapter_interrupt)(struct aac_dev *dev);
void (*adapter_notify)(struct aac_dev *dev, u32 event);
+ void (*adapter_disable_int)(struct aac_dev *dev);
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
};
@@ -518,8 +549,6 @@ struct aac_queue {
/* This is only valid for adapter to host command queues. */
spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */
spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */
- unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */
- u32 padding; /* Padding - FIXME - can remove I believe */
struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */
/* only valid for command queues which receive entries from the adapter. */
struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */
@@ -748,7 +777,9 @@ struct fsa_dev_info {
u64 last;
u64 size;
u32 type;
+ u32 config_waiting_on;
u16 queue_depth;
+ u8 config_needed;
u8 valid;
u8 ro;
u8 locked;
@@ -981,6 +1012,10 @@ struct aac_dev
u8 nondasd_support;
u8 dac_support;
u8 raid_scsi_mode;
+ /* macro side-effects BEWARE */
+# define raw_io_interface \
+ init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
+ u8 raw_io_64;
u8 printf_enabled;
};
@@ -990,6 +1025,9 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \
(dev)->a_ops.adapter_notify(dev, event)
+#define aac_adapter_disable_int(dev) \
+ (dev)->a_ops.adapter_disable_int(dev)
+
#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
@@ -1156,6 +1194,17 @@ struct aac_write_reply
__le32 committed;
};
+struct aac_raw_io
+{
+ __le32 block[2];
+ __le32 count;
+ __le16 cid;
+ __le16 flags; /* 00 W, 01 R */
+ __le16 bpTotal; /* reserved for F/W use */
+ __le16 bpComplete; /* reserved for F/W use */
+ struct sgmapraw sg;
+};
+
#define CT_FLUSH_CACHE 129
struct aac_synchronize {
__le32 command; /* VM_ContainerConfig */
@@ -1196,7 +1245,7 @@ struct aac_srb
};
/*
- * This and assocated data structs are used by the
+ * This and associated data structs are used by the
* ioctl caller and are in cpu order.
*/
struct user_aac_srb
@@ -1317,8 +1366,10 @@ struct aac_srb_reply
#define VM_CtBlockVerify64 18
#define VM_CtHostRead64 19
#define VM_CtHostWrite64 20
+#define VM_DrvErrTblLog 21
+#define VM_NameServe64 22
-#define MAX_VMCOMMAND_NUM 21 /* used for sizing stats array - leave last */
+#define MAX_VMCOMMAND_NUM 23 /* used for sizing stats array - leave last */
/*
* Descriptive information (eg, vital stats)
@@ -1427,6 +1478,7 @@ struct aac_mntent {
manager (eg, filesystem) */
__le32 altoid; /* != oid <==> snapshot or
broken mirror exists */
+ __le32 capacityhigh;
};
#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */
@@ -1508,11 +1560,12 @@ struct fib_ioctl
struct revision
{
- u32 compat;
- u32 version;
- u32 build;
+ __le32 compat;
+ __le32 version;
+ __le32 build;
};
+
/*
* Ugly - non Linux like ioctl coding for back compat.
*/
@@ -1661,6 +1714,7 @@ extern struct aac_common aac_config;
#define AifCmdJobProgress 2 /* Progress report */
#define AifJobCtrZero 101 /* Array Zero progress */
#define AifJobStsSuccess 1 /* Job completes */
+#define AifJobStsRunning 102 /* Job running */
#define AifCmdAPIReport 3 /* Report from other user of API */
#define AifCmdDriverNotify 4 /* Notify host driver of event */
#define AifDenMorphComplete 200 /* A morph operation completed */
@@ -1731,5 +1785,7 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
+int probe_container(struct aac_dev *dev, int cid);
extern int numacb;
extern int acbsize;
+extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 85387099aab2..71f1cad9b5f0 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -287,7 +287,6 @@ return_fib:
kfree(fib->hw_fib);
kfree(fib);
status = 0;
- fibctx->jiffies = jiffies/HZ;
} else {
spin_unlock_irqrestore(&dev->fib_lock, flags);
if (f.wait) {
@@ -302,6 +301,7 @@ return_fib:
status = -EAGAIN;
}
}
+ fibctx->jiffies = jiffies/HZ;
return status;
}
@@ -405,10 +405,20 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
static int check_revision(struct aac_dev *dev, void __user *arg)
{
struct revision response;
-
- response.compat = 1;
- response.version = le32_to_cpu(dev->adapter_info.kernelrev);
- response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
+ char *driver_version = aac_driver_version;
+ u32 version;
+
+ response.compat = cpu_to_le32(1);
+ version = (simple_strtol(driver_version,
+ &driver_version, 10) << 24) | 0x00000400;
+ version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
+ version += simple_strtol(driver_version + 1, NULL, 10);
+ response.version = cpu_to_le32(version);
+# if (defined(AAC_DRIVER_BUILD))
+ response.build = cpu_to_le32(AAC_DRIVER_BUILD);
+# else
+ response.build = cpu_to_le32(9999);
+# endif
if (copy_to_user(arg, &response, sizeof(response)))
return -EFAULT;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 43557bf661f6..59a341b2aedc 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -44,7 +44,9 @@
#include "aacraid.h"
-struct aac_common aac_config;
+struct aac_common aac_config = {
+ .irq_mod = 1
+};
static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
{
@@ -193,7 +195,7 @@ int aac_send_shutdown(struct aac_dev * dev)
fibctx,
sizeof(struct aac_close),
FsaNormal,
- 1, 1,
+ -2 /* Timeout silently */, 1,
NULL, NULL);
if (status == 0)
@@ -311,8 +313,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->max_fib_size = sizeof(struct hw_fib);
dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
- sizeof(struct aac_fibhdr)
- - sizeof(struct aac_write) + sizeof(struct sgmap))
- / sizeof(struct sgmap);
+ - sizeof(struct aac_write) + sizeof(struct sgentry))
+ / sizeof(struct sgentry);
+ dev->raw_io_64 = 0;
+ if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
+ 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
+ (status[0] == 0x00000001)) {
+ if (status[1] & AAC_OPT_NEW_COMM_64)
+ dev->raw_io_64 = 1;
+ }
if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
0, 0, 0, 0, 0, 0,
status+0, status+1, status+2, status+3, status+4))
@@ -340,8 +349,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->max_fib_size = 512;
dev->sg_tablesize = host->sg_tablesize
= (512 - sizeof(struct aac_fibhdr)
- - sizeof(struct aac_write) + sizeof(struct sgmap))
- / sizeof(struct sgmap);
+ - sizeof(struct aac_write) + sizeof(struct sgentry))
+ / sizeof(struct sgentry);
host->can_queue = AAC_NUM_IO_FIB;
} else if (acbsize == 2048) {
host->max_sectors = 512;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 5322865942e2..e4d543a474ae 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -39,7 +39,9 @@
#include <linux/completion.h>
#include <linux/blkdev.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
#include <asm/semaphore.h>
+#include <asm/delay.h>
#include "aacraid.h"
@@ -254,6 +256,7 @@ static void fib_dealloc(struct fib * fibptr)
static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
{
struct aac_queue * q;
+ unsigned long idx;
/*
* All of the queues wrap when they reach the end, so we check
@@ -263,32 +266,27 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
*/
q = &dev->queues->queue[qid];
-
- *index = le32_to_cpu(*(q->headers.producer));
- if ((*index - 2) == le32_to_cpu(*(q->headers.consumer)))
+
+ idx = *index = le32_to_cpu(*(q->headers.producer));
+ /* Interrupt Moderation, only interrupt for first two entries */
+ if (idx != le32_to_cpu(*(q->headers.consumer))) {
+ if (--idx == 0) {
+ if (qid == AdapNormCmdQueue)
+ idx = ADAP_NORM_CMD_ENTRIES;
+ else
+ idx = ADAP_NORM_RESP_ENTRIES;
+ }
+ if (idx != le32_to_cpu(*(q->headers.consumer)))
*nonotify = 1;
+ }
- if (qid == AdapHighCmdQueue) {
- if (*index >= ADAP_HIGH_CMD_ENTRIES)
- *index = 0;
- } else if (qid == AdapNormCmdQueue) {
+ if (qid == AdapNormCmdQueue) {
if (*index >= ADAP_NORM_CMD_ENTRIES)
*index = 0; /* Wrap to front of the Producer Queue. */
- }
- else if (qid == AdapHighRespQueue)
- {
- if (*index >= ADAP_HIGH_RESP_ENTRIES)
- *index = 0;
- }
- else if (qid == AdapNormRespQueue)
- {
+ } else {
if (*index >= ADAP_NORM_RESP_ENTRIES)
*index = 0; /* Wrap to front of the Producer Queue. */
}
- else {
- printk("aacraid: invalid qid\n");
- BUG();
- }
if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */
printk(KERN_WARNING "Queue %d full, %u outstanding.\n",
@@ -320,12 +318,8 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
{
struct aac_entry * entry = NULL;
int map = 0;
- struct aac_queue * q = &dev->queues->queue[qid];
-
- spin_lock_irqsave(q->lock, q->SavedIrql);
- if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue)
- {
+ if (qid == AdapNormCmdQueue) {
/* if no entries wait for some if caller wants to */
while (!aac_get_entry(dev, qid, &entry, index, nonotify))
{
@@ -336,9 +330,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
*/
entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size));
map = 1;
- }
- else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue)
- {
+ } else {
while(!aac_get_entry(dev, qid, &entry, index, nonotify))
{
/* if no entries wait for some if caller wants to */
@@ -361,42 +353,6 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
return 0;
}
-
-/**
- * aac_insert_entry - insert a queue entry
- * @dev: Adapter
- * @index: Index of entry to insert
- * @qid: Queue number
- * @nonotify: Suppress adapter notification
- *
- * Gets the next free QE off the requested priorty adapter command
- * queue and associates the Fib with the QE. The QE represented by
- * index is ready to insert on the queue when this routine returns
- * success.
- */
-
-static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify)
-{
- struct aac_queue * q = &dev->queues->queue[qid];
-
- if(q == NULL)
- BUG();
- *(q->headers.producer) = cpu_to_le32(index + 1);
- spin_unlock_irqrestore(q->lock, q->SavedIrql);
-
- if (qid == AdapHighCmdQueue ||
- qid == AdapNormCmdQueue ||
- qid == AdapHighRespQueue ||
- qid == AdapNormRespQueue)
- {
- if (!nonotify)
- aac_adapter_notify(dev, qid);
- }
- else
- printk("Suprise insert!\n");
- return 0;
-}
-
/*
* Define the highest level of host to adapter communication routines.
* These routines will support host to adapter FS commuication. These
@@ -425,12 +381,13 @@ static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned l
int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
{
u32 index;
- u32 qid;
struct aac_dev * dev = fibptr->dev;
unsigned long nointr = 0;
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q;
unsigned long flags = 0;
+ unsigned long qflags;
+
if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
return -EBUSY;
/*
@@ -483,26 +440,8 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
* Get a queue entry connect the FIB to it and send an notify
* the adapter a command is ready.
*/
- if (priority == FsaHigh) {
- hw_fib->header.XferState |= cpu_to_le32(HighPriority);
- qid = AdapHighCmdQueue;
- } else {
- hw_fib->header.XferState |= cpu_to_le32(NormalPriority);
- qid = AdapNormCmdQueue;
- }
- q = &dev->queues->queue[qid];
+ hw_fib->header.XferState |= cpu_to_le32(NormalPriority);
- if(wait)
- spin_lock_irqsave(&fibptr->event_lock, flags);
- if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0)
- return -EWOULDBLOCK;
- dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
- dprintk((KERN_DEBUG "Fib contents:.\n"));
- dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command));
- dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState));
- dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
- dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
- dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
/*
* Fill in the Callback and CallbackContext if we are not
* going to wait.
@@ -511,22 +450,67 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
fibptr->callback = callback;
fibptr->callback_data = callback_data;
}
- FIB_COUNTER_INCREMENT(aac_config.FibsSent);
- list_add_tail(&fibptr->queue, &q->pendingq);
- q->numpending++;
fibptr->done = 0;
fibptr->flags = 0;
- if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0)
- return -EWOULDBLOCK;
+ FIB_COUNTER_INCREMENT(aac_config.FibsSent);
+
+ dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
+ dprintk((KERN_DEBUG "Fib contents:.\n"));
+ dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command));
+ dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState));
+ dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
+ dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
+ dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
+
+ q = &dev->queues->queue[AdapNormCmdQueue];
+
+ if(wait)
+ spin_lock_irqsave(&fibptr->event_lock, flags);
+ spin_lock_irqsave(q->lock, qflags);
+ aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
+
+ list_add_tail(&fibptr->queue, &q->pendingq);
+ q->numpending++;
+ *(q->headers.producer) = cpu_to_le32(index + 1);
+ spin_unlock_irqrestore(q->lock, qflags);
+ if (!(nointr & aac_config.irq_mod))
+ aac_adapter_notify(dev, AdapNormCmdQueue);
/*
* If the caller wanted us to wait for response wait now.
*/
if (wait) {
spin_unlock_irqrestore(&fibptr->event_lock, flags);
- down(&fibptr->event_wait);
+ /* Only set for first known interruptable command */
+ if (wait < 0) {
+ /*
+ * *VERY* Dangerous to time out a command, the
+ * assumption is made that we have no hope of
+ * functioning because an interrupt routing or other
+ * hardware failure has occurred.
+ */
+ unsigned long count = 36000000L; /* 3 minutes */
+ unsigned long qflags;
+ while (down_trylock(&fibptr->event_wait)) {
+ if (--count == 0) {
+ spin_lock_irqsave(q->lock, qflags);
+ q->numpending--;
+ list_del(&fibptr->queue);
+ spin_unlock_irqrestore(q->lock, qflags);
+ if (wait == -1) {
+ printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n"
+ "Usually a result of a PCI interrupt routing problem;\n"
+ "update mother board BIOS or consider utilizing one of\n"
+ "the SAFE mode kernel options (acpi, apic etc)\n");
+ }
+ return -ETIMEDOUT;
+ }
+ udelay(5);
+ }
+ } else
+ down(&fibptr->event_wait);
if(fibptr->done == 0)
BUG();
@@ -608,15 +592,9 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
case HostNormCmdQueue:
notify = HostNormCmdNotFull;
break;
- case HostHighCmdQueue:
- notify = HostHighCmdNotFull;
- break;
case HostNormRespQueue:
notify = HostNormRespNotFull;
break;
- case HostHighRespQueue:
- notify = HostHighRespNotFull;
- break;
default:
BUG();
return;
@@ -638,9 +616,13 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
+ struct aac_queue * q;
unsigned long nointr = 0;
- if (hw_fib->header.XferState == 0)
+ unsigned long qflags;
+
+ if (hw_fib->header.XferState == 0) {
return 0;
+ }
/*
* If we plan to do anything check the structure type first.
*/
@@ -655,37 +637,21 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
* send the completed cdb to the adapter.
*/
if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
+ u32 index;
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
- if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) {
- u32 index;
- if (size)
- {
- size += sizeof(struct aac_fibhdr);
- if (size > le16_to_cpu(hw_fib->header.SenderSize))
- return -EMSGSIZE;
- hw_fib->header.Size = cpu_to_le16(size);
- }
- if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) {
- return -EWOULDBLOCK;
- }
- if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) {
- }
- } else if (hw_fib->header.XferState &
- cpu_to_le32(NormalPriority)) {
- u32 index;
-
- if (size) {
- size += sizeof(struct aac_fibhdr);
- if (size > le16_to_cpu(hw_fib->header.SenderSize))
- return -EMSGSIZE;
- hw_fib->header.Size = cpu_to_le16(size);
- }
- if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0)
- return -EWOULDBLOCK;
- if (aac_insert_entry(dev, index, AdapNormRespQueue, (nointr & (int)aac_config.irq_mod)) != 0)
- {
- }
+ if (size) {
+ size += sizeof(struct aac_fibhdr);
+ if (size > le16_to_cpu(hw_fib->header.SenderSize))
+ return -EMSGSIZE;
+ hw_fib->header.Size = cpu_to_le16(size);
}
+ q = &dev->queues->queue[AdapNormRespQueue];
+ spin_lock_irqsave(q->lock, qflags);
+ aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);
+ *(q->headers.producer) = cpu_to_le32(index + 1);
+ spin_unlock_irqrestore(q->lock, qflags);
+ if (!(nointr & (int)aac_config.irq_mod))
+ aac_adapter_notify(dev, AdapNormRespQueue);
}
else
{
@@ -777,6 +743,268 @@ void aac_printf(struct aac_dev *dev, u32 val)
memset(cp, 0, 256);
}
+
+/**
+ * aac_handle_aif - Handle a message from the firmware
+ * @dev: Which adapter this fib is from
+ * @fibptr: Pointer to fibptr from adapter
+ *
+ * This routine handles a driver notify fib from the adapter and
+ * dispatches it to the appropriate routine for handling.
+ */
+
+static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
+{
+ struct hw_fib * hw_fib = fibptr->hw_fib;
+ struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
+ int busy;
+ u32 container;
+ struct scsi_device *device;
+ enum {
+ NOTHING,
+ DELETE,
+ ADD,
+ CHANGE
+ } device_config_needed;
+
+ /* Sniff for container changes */
+
+ if (!dev)
+ return;
+ container = (u32)-1;
+
+ /*
+ * We have set this up to try and minimize the number of
+ * re-configures that take place. As a result of this when
+ * certain AIF's come in we will set a flag waiting for another
+ * type of AIF before setting the re-config flag.
+ */
+ switch (le32_to_cpu(aifcmd->command)) {
+ case AifCmdDriverNotify:
+ switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
+ /*
+ * Morph or Expand complete
+ */
+ case AifDenMorphComplete:
+ case AifDenVolumeExtendComplete:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= dev->maximum_num_containers)
+ break;
+
+ /*
+ * Find the Scsi_Device associated with the SCSI
+ * address. Make sure we have the right array, and if
+ * so set the flag to initiate a new re-config once we
+ * see an AifEnConfigChange AIF come through.
+ */
+
+ if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) {
+ device = scsi_device_lookup(dev->scsi_host_ptr,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ if (device) {
+ dev->fsa_dev[container].config_needed = CHANGE;
+ dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;
+ scsi_device_put(device);
+ }
+ }
+ }
+
+ /*
+ * If we are waiting on something and this happens to be
+ * that thing then set the re-configure flag.
+ */
+ if (container != (u32)-1) {
+ if (container >= dev->maximum_num_containers)
+ break;
+ if (dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data))
+ dev->fsa_dev[container].config_waiting_on = 0;
+ } else for (container = 0;
+ container < dev->maximum_num_containers; ++container) {
+ if (dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data))
+ dev->fsa_dev[container].config_waiting_on = 0;
+ }
+ break;
+
+ case AifCmdEventNotify:
+ switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
+ /*
+ * Add an Array.
+ */
+ case AifEnAddContainer:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= dev->maximum_num_containers)
+ break;
+ dev->fsa_dev[container].config_needed = ADD;
+ dev->fsa_dev[container].config_waiting_on =
+ AifEnConfigChange;
+ break;
+
+ /*
+ * Delete an Array.
+ */
+ case AifEnDeleteContainer:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= dev->maximum_num_containers)
+ break;
+ dev->fsa_dev[container].config_needed = DELETE;
+ dev->fsa_dev[container].config_waiting_on =
+ AifEnConfigChange;
+ break;
+
+ /*
+ * Container change detected. If we currently are not
+ * waiting on something else, setup to wait on a Config Change.
+ */
+ case AifEnContainerChange:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= dev->maximum_num_containers)
+ break;
+ if (dev->fsa_dev[container].config_waiting_on)
+ break;
+ dev->fsa_dev[container].config_needed = CHANGE;
+ dev->fsa_dev[container].config_waiting_on =
+ AifEnConfigChange;
+ break;
+
+ case AifEnConfigChange:
+ break;
+
+ }
+
+ /*
+ * If we are waiting on something and this happens to be
+ * that thing then set the re-configure flag.
+ */
+ if (container != (u32)-1) {
+ if (container >= dev->maximum_num_containers)
+ break;
+ if (dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data))
+ dev->fsa_dev[container].config_waiting_on = 0;
+ } else for (container = 0;
+ container < dev->maximum_num_containers; ++container) {
+ if (dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data))
+ dev->fsa_dev[container].config_waiting_on = 0;
+ }
+ break;
+
+ case AifCmdJobProgress:
+ /*
+ * These are job progress AIF's. When a Clear is being
+ * done on a container it is initially created then hidden from
+ * the OS. When the clear completes we don't get a config
+ * change so we monitor the job status complete on a clear then
+ * wait for a container change.
+ */
+
+ if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
+ && ((((u32 *)aifcmd->data)[6] == ((u32 *)aifcmd->data)[5])
+ || (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess)))) {
+ for (container = 0;
+ container < dev->maximum_num_containers;
+ ++container) {
+ /*
+ * Stomp on all config sequencing for all
+ * containers?
+ */
+ dev->fsa_dev[container].config_waiting_on =
+ AifEnContainerChange;
+ dev->fsa_dev[container].config_needed = ADD;
+ }
+ }
+ if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
+ && (((u32 *)aifcmd->data)[6] == 0)
+ && (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsRunning))) {
+ for (container = 0;
+ container < dev->maximum_num_containers;
+ ++container) {
+ /*
+ * Stomp on all config sequencing for all
+ * containers?
+ */
+ dev->fsa_dev[container].config_waiting_on =
+ AifEnContainerChange;
+ dev->fsa_dev[container].config_needed = DELETE;
+ }
+ }
+ break;
+ }
+
+ device_config_needed = NOTHING;
+ for (container = 0; container < dev->maximum_num_containers;
+ ++container) {
+ if ((dev->fsa_dev[container].config_waiting_on == 0)
+ && (dev->fsa_dev[container].config_needed != NOTHING)) {
+ device_config_needed =
+ dev->fsa_dev[container].config_needed;
+ dev->fsa_dev[container].config_needed = NOTHING;
+ break;
+ }
+ }
+ if (device_config_needed == NOTHING)
+ return;
+
+ /*
+ * If we decided that a re-configuration needs to be done,
+ * schedule it here on the way out the door, please close the door
+ * behind you.
+ */
+
+ busy = 0;
+
+
+ /*
+ * Find the Scsi_Device associated with the SCSI address,
+ * and mark it as changed, invalidating the cache. This deals
+ * with changes to existing device IDs.
+ */
+
+ if (!dev || !dev->scsi_host_ptr)
+ return;
+ /*
+ * force reload of disk info via probe_container
+ */
+ if ((device_config_needed == CHANGE)
+ && (dev->fsa_dev[container].valid == 1))
+ dev->fsa_dev[container].valid = 2;
+ if ((device_config_needed == CHANGE) ||
+ (device_config_needed == ADD))
+ probe_container(dev, container);
+ device = scsi_device_lookup(dev->scsi_host_ptr,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ if (device) {
+ switch (device_config_needed) {
+ case DELETE:
+ scsi_remove_device(device);
+ break;
+ case CHANGE:
+ if (!dev->fsa_dev[container].valid) {
+ scsi_remove_device(device);
+ break;
+ }
+ scsi_rescan_device(&device->sdev_gendev);
+
+ default:
+ break;
+ }
+ scsi_device_put(device);
+ }
+ if (device_config_needed == ADD) {
+ scsi_add_device(dev->scsi_host_ptr,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ }
+
+}
+
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
@@ -791,7 +1019,6 @@ int aac_command_thread(struct aac_dev * dev)
{
struct hw_fib *hw_fib, *hw_newfib;
struct fib *fib, *newfib;
- struct aac_queue_block *queues = dev->queues;
struct aac_fib_context *fibctx;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
@@ -811,21 +1038,22 @@ int aac_command_thread(struct aac_dev * dev)
* Let the DPC know it has a place to send the AIF's to.
*/
dev->aif_thread = 1;
- add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
+ add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
set_current_state(TASK_INTERRUPTIBLE);
+ dprintk ((KERN_INFO "aac_command_thread start\n"));
while(1)
{
- spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
- while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {
+ spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
+ while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) {
struct list_head *entry;
struct aac_aifcmd * aifcmd;
set_current_state(TASK_RUNNING);
-
- entry = queues->queue[HostNormCmdQueue].cmdq.next;
+
+ entry = dev->queues->queue[HostNormCmdQueue].cmdq.next;
list_del(entry);
-
- spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);
+
+ spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
fib = list_entry(entry, struct fib, fiblink);
/*
* We will process the FIB here or pass it to a
@@ -846,6 +1074,7 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
+ aac_handle_aif(dev, fib);
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
@@ -855,9 +1084,62 @@ int aac_command_thread(struct aac_dev * dev)
u32 time_now, time_last;
unsigned long flagv;
-
+ unsigned num;
+ struct hw_fib ** hw_fib_pool, ** hw_fib_p;
+ struct fib ** fib_pool, ** fib_p;
+
+ /* Sniff events */
+ if ((aifcmd->command ==
+ cpu_to_le32(AifCmdEventNotify)) ||
+ (aifcmd->command ==
+ cpu_to_le32(AifCmdJobProgress))) {
+ aac_handle_aif(dev, fib);
+ }
+
time_now = jiffies/HZ;
+ /*
+ * Warning: no sleep allowed while
+ * holding spinlock. We take the estimate
+ * and pre-allocate a set of fibs outside the
+ * lock.
+ */
+ num = le32_to_cpu(dev->init->AdapterFibsSize)
+ / sizeof(struct hw_fib); /* some extra */
+ spin_lock_irqsave(&dev->fib_lock, flagv);
+ entry = dev->fib_list.next;
+ while (entry != &dev->fib_list) {
+ entry = entry->next;
+ ++num;
+ }
+ spin_unlock_irqrestore(&dev->fib_lock, flagv);
+ hw_fib_pool = NULL;
+ fib_pool = NULL;
+ if (num
+ && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL)))
+ && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) {
+ hw_fib_p = hw_fib_pool;
+ fib_p = fib_pool;
+ while (hw_fib_p < &hw_fib_pool[num]) {
+ if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) {
+ --hw_fib_p;
+ break;
+ }
+ if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) {
+ kfree(*(--hw_fib_p));
+ break;
+ }
+ }
+ if ((num = hw_fib_p - hw_fib_pool) == 0) {
+ kfree(fib_pool);
+ fib_pool = NULL;
+ kfree(hw_fib_pool);
+ hw_fib_pool = NULL;
+ }
+ } else if (hw_fib_pool) {
+ kfree(hw_fib_pool);
+ hw_fib_pool = NULL;
+ }
spin_lock_irqsave(&dev->fib_lock, flagv);
entry = dev->fib_list.next;
/*
@@ -866,6 +1148,8 @@ int aac_command_thread(struct aac_dev * dev)
* fib, and then set the event to wake up the
* thread that is waiting for it.
*/
+ hw_fib_p = hw_fib_pool;
+ fib_p = fib_pool;
while (entry != &dev->fib_list) {
/*
* Extract the fibctx
@@ -898,9 +1182,11 @@ int aac_command_thread(struct aac_dev * dev)
* Warning: no sleep allowed while
* holding spinlock
*/
- hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
- newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC);
- if (newfib && hw_newfib) {
+ if (hw_fib_p < &hw_fib_pool[num]) {
+ hw_newfib = *hw_fib_p;
+ *(hw_fib_p++) = NULL;
+ newfib = *fib_p;
+ *(fib_p++) = NULL;
/*
* Make the copy of the FIB
*/
@@ -915,15 +1201,11 @@ int aac_command_thread(struct aac_dev * dev)
fibctx->count++;
/*
* Set the event to wake up the
- * thread that will waiting.
+ * thread that is waiting.
*/
up(&fibctx->wait_sem);
} else {
printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
- if(newfib)
- kfree(newfib);
- if(hw_newfib)
- kfree(hw_newfib);
}
entry = entry->next;
}
@@ -933,21 +1215,38 @@ int aac_command_thread(struct aac_dev * dev)
*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
+ /* Free up the remaining resources */
+ hw_fib_p = hw_fib_pool;
+ fib_p = fib_pool;
+ while (hw_fib_p < &hw_fib_pool[num]) {
+ if (*hw_fib_p)
+ kfree(*hw_fib_p);
+ if (*fib_p)
+ kfree(*fib_p);
+ ++fib_p;
+ ++hw_fib_p;
+ }
+ if (hw_fib_pool)
+ kfree(hw_fib_pool);
+ if (fib_pool)
+ kfree(fib_pool);
}
- spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
kfree(fib);
+ spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
}
/*
* There are no more AIF's
*/
- spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);
+ spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
schedule();
if(signal_pending(current))
break;
set_current_state(TASK_INTERRUPTIBLE);
}
- remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
+ if (dev->queues)
+ remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
dev->aif_thread = 0;
complete_and_exit(&dev->aif_completion, 0);
+ return 0;
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 562da90480a1..a1f9ceef0ac9 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,8 +27,11 @@
* Abstract: Linux Driver entry module for Adaptec RAID Array Controller
*/
-#define AAC_DRIVER_VERSION "1.1.2-lk2"
-#define AAC_DRIVER_BUILD_DATE __DATE__
+#define AAC_DRIVER_VERSION "1.1-4"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH ""
+#endif
+#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
#define AAC_DRIVERNAME "aacraid"
#include <linux/compat.h>
@@ -58,16 +61,24 @@
#include "aacraid.h"
+#ifdef AAC_DRIVER_BUILD
+#define _str(x) #x
+#define str(x) _str(x)
+#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH
+#else
+#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE
+#endif
MODULE_AUTHOR("Red Hat Inc and Adaptec");
MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
"Adaptec Advanced Raid Products, "
"and HP NetRAID-4M SCSI driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(AAC_DRIVER_VERSION);
+MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
+char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
/*
* Because of the way Linux names scsi devices, the order in this table has
@@ -109,36 +120,39 @@ static struct pci_device_id aac_pci_tbl[] = {
{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
- { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 32 }, /* Themisto Jupiter Platform */
- { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 32 }, /* Themisto Jupiter Platform */
- { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 33 }, /* Callisto Jupiter Platform */
- { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 34 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
- { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 35 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
- { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 36 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
- { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 37 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
- { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 38 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
- { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 39 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
- { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 40 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
- { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 41 }, /* AAR-2610SA PCI SATA 6ch */
- { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 42 }, /* ASR-2240S (SabreExpress) */
- { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 43 }, /* ASR-4005SAS */
- { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 44 }, /* IBM 8i (AvonPark) */
- { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 44 }, /* IBM 8i (AvonPark Lite) */
- { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 45 }, /* ASR-4000SAS (BlackBird) */
- { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 46 }, /* ASR-4800SAS (Marauder-X) */
- { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 47 }, /* ASR-4805SAS (Marauder-E) */
- { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 48 }, /* ASR-4810SAS (Hurricane */
-
- { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 49 }, /* Perc 320/DC*/
- { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 50 }, /* Adaptec 5400S (Mustang)*/
- { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 51 }, /* Adaptec 5400S (Mustang)*/
- { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 52 }, /* Dell PERC2/QC */
- { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 53 }, /* HP NetRAID-4M */
-
- { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 54 }, /* Dell Catchall */
- { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 55 }, /* Legend Catchall */
- { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 56 }, /* Adaptec Catch All */
- { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 57 }, /* Adaptec Rocket Catch All */
+ { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
+ { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */
+ { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */
+ { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */
+ { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+ { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+ { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+ { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+ { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+ { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+ { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
+ { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
+ { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
+ { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
+ { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
+ { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
+ { 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
+ { 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
+ { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
+ { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
+ { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
+ { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
+
+ { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
+ { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
+ { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/
+ { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */
+ { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */
+
+ { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */
+ { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
+ { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
+ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
{ 0,}
};
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -180,8 +194,9 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
+ { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */
+ { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */
+ { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */
{ NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
@@ -195,10 +210,12 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */
{ aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
+ { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
+ { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
+ { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */
{ aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
{ aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@@ -436,9 +453,9 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
/*
* We can exit If all the commands are complete
*/
+ spin_unlock_irq(host->host_lock);
if (active == 0)
return SUCCESS;
- spin_unlock_irq(host->host_lock);
ssleep(1);
spin_lock_irq(host->host_lock);
}
@@ -731,7 +748,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
unique_id++;
}
- if (pci_enable_device(pdev))
+ error = pci_enable_device(pdev);
+ if (error)
goto out;
if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL) ||
@@ -755,6 +773,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
shost->irq = pdev->irq;
shost->base = pci_resource_start(pdev, 0);
shost->unique_id = unique_id;
+ shost->max_cmd_len = 16;
aac = (struct aac_dev *)shost->hostdata;
aac->scsi_host_ptr = shost;
@@ -782,7 +801,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
goto out_free_fibs;
aac->maximum_num_channels = aac_drivers[index].channels;
- aac_get_adapter_info(aac);
+ error = aac_get_adapter_info(aac);
+ if (error < 0)
+ goto out_deinit;
/*
* Lets override negotiations and drop the maximum SG limit to 34
@@ -839,11 +860,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
return 0;
-out_deinit:
+ out_deinit:
kill_proc(aac->thread_pid, SIGKILL, 0);
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac);
+ aac_adapter_disable_int(aac);
fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
@@ -860,6 +882,13 @@ out_deinit:
return error;
}
+static void aac_shutdown(struct pci_dev *dev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(dev);
+ struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+ aac_send_shutdown(aac);
+}
+
static void __devexit aac_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -871,6 +900,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
wait_for_completion(&aac->aif_completion);
aac_send_shutdown(aac);
+ aac_adapter_disable_int(aac);
fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
@@ -891,17 +921,18 @@ static struct pci_driver aac_pci_driver = {
.id_table = aac_pci_tbl,
.probe = aac_probe_one,
.remove = __devexit_p(aac_remove_one),
+ .shutdown = aac_shutdown,
};
static int __init aac_init(void)
{
int error;
- printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n",
- AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE);
+ printk(KERN_INFO "Adaptec %s driver (%s)\n",
+ AAC_DRIVERNAME, aac_driver_version);
- error = pci_module_init(&aac_pci_driver);
- if (error)
+ error = pci_register_driver(&aac_pci_driver);
+ if (error < 0)
return error;
aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops);
@@ -909,6 +940,7 @@ static int __init aac_init(void)
printk(KERN_WARNING
"aacraid: unable to register \"aac\" device.\n");
}
+
return 0;
}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 7d68b7825137..557287a0b80b 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_rkt_disable_interrupt - Disable interrupts
+ * @dev: Adapter
+ */
+
+static void aac_rkt_disable_interrupt(struct aac_dev *dev)
+{
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
* rkt_sync_cmd - send a command and wait
* @dev: Adapter
* @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
dev->a_ops.adapter_check_health = aac_rkt_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that we
+ * can handle.
+ */
+ rkt_writeb(dev, MUnit.OIMR, 0xff);
+ rkt_writel(dev, MUnit.ODR, 0xffffffff);
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
@@ -438,6 +457,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 1ff25f49fada..a8459faf87ca 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_rx_disable_interrupt - Disable interrupts
+ * @dev: Adapter
+ */
+
+static void aac_rx_disable_interrupt(struct aac_dev *dev)
+{
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
+}
+
+/**
* rx_sync_cmd - send a command and wait
* @dev: Adapter
* @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
dev->a_ops.adapter_notify = aac_rx_notify_adapter;
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that we
+ * can handle.
+ */
+ rx_writeb(dev, MUnit.OIMR, 0xff);
+ rx_writel(dev, MUnit.ODR, 0xffffffff);
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+
if (aac_init_adapter(dev) == NULL)
goto error_irq;
/*
@@ -438,6 +457,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 0680249ab861..3900abc5850d 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/**
+ * aac_sa_disable_interrupt - disable interrupt
+ * @dev: Which adapter to enable.
+ */
+
+static void aac_sa_disable_interrupt (struct aac_dev *dev)
+{
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+}
+
+/**
* aac_sa_notify_adapter - handle adapter notification
* @dev: Adapter that notification is for
* @event: Event to notidy
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
static void aac_sa_interrupt_adapter (struct aac_dev *dev)
{
- u32 ret;
sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
- &ret, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
*/
dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
+ dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
+ /*
+ * First clear out all interrupts. Then enable the one's that
+ * we can handle.
+ */
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+ sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
+ DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
if(aac_init_adapter(dev) == NULL)
goto error_irq;
@@ -381,6 +398,7 @@ error_kfree:
kfree(dev->queues);
error_irq:
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 0fb93363eb22..37ec5411e325 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -9200,8 +9200,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
(unsigned) s->serial_number, s->retries, s->allowed);
printk(
-" timeout_per_command %d, timeout_total %d, timeout %d\n",
- s->timeout_per_command, s->timeout_total, s->timeout);
+" timeout_per_command %d\n",
+ s->timeout_per_command);
printk(
" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index c5623694d10f..e2a5657d5fdb 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -1,26 +1,34 @@
/*
* ahci.c - AHCI SATA support
*
- * Copyright 2004 Red Hat, Inc.
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
+ * Copyright 2004-2005 Red Hat, Inc.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
*
- * Version 1.0 of the AHCI specification:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * AHCI hardware documentation:
* http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
*
*/
@@ -33,6 +41,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -181,11 +190,9 @@ static void ahci_irq_clear(struct ata_port *ap);
static void ahci_eng_timeout(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
-static void ahci_host_stop(struct ata_host_set *host_set);
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
-static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
static void ahci_remove_one (struct pci_dev *pdev);
@@ -209,12 +216,11 @@ static Scsi_Host_Template ahci_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations ahci_ops = {
+static const struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status,
.check_altstatus = ahci_check_status,
- .check_err = ahci_check_err,
.dev_select = ata_noop_dev_select,
.tf_read = ahci_tf_read,
@@ -234,7 +240,6 @@ static struct ata_port_operations ahci_ops = {
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
- .host_stop = ahci_host_stop,
};
static struct ata_port_info ahci_port_info[] = {
@@ -244,7 +249,7 @@ static struct ata_port_info ahci_port_info[] = {
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_PIO_DMA,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
},
@@ -269,6 +274,8 @@ static struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ESB2 */
{ PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ESB2 */
+ { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH7-M DH */
{ } /* terminate list */
};
@@ -286,17 +293,9 @@ static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int
return base + 0x100 + (port * 0x80);
}
-static inline void *ahci_port_base (void *base, unsigned int port)
-{
- return (void *) ahci_port_base_ul((unsigned long)base, port);
-}
-
-static void ahci_host_stop(struct ata_host_set *host_set)
+static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
{
- struct ahci_host_priv *hpriv = host_set->private_data;
- kfree(hpriv);
-
- ata_host_stop(host_set);
+ return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
}
static int ahci_port_start(struct ata_port *ap)
@@ -304,8 +303,9 @@ static int ahci_port_start(struct ata_port *ap)
struct device *dev = ap->host_set->dev;
struct ahci_host_priv *hpriv = ap->host_set->private_data;
struct ahci_port_priv *pp;
- void *mem, *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void *mem;
dma_addr_t mem_dma;
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
@@ -373,8 +373,8 @@ static void ahci_port_stop(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct ahci_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
tmp = readl(port_mmio + PORT_CMD);
@@ -406,7 +406,7 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
return 0xffffffffU;
}
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -424,7 +424,7 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
return;
}
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void ahci_phy_reset(struct ata_port *ap)
@@ -452,18 +452,11 @@ static void ahci_phy_reset(struct ata_port *ap)
static u8 ahci_check_status(struct ata_port *ap)
{
- void *mmio = (void *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
return readl(mmio + PORT_TFDATA) & 0xFF;
}
-static u8 ahci_check_err(struct ata_port *ap)
-{
- void *mmio = (void *) ap->ioaddr.cmd_addr;
-
- return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
-}
-
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ahci_port_priv *pp = ap->private_data;
@@ -536,8 +529,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
int work;
@@ -584,12 +577,16 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
static void ahci_eng_timeout(struct ata_port *ap)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ struct ata_host_set *host_set = ap->host_set;
+ void __iomem *mmio = host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -604,15 +601,16 @@ static void ahci_eng_timeout(struct ata_port *ap)
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
- ata_qc_complete(qc, ATA_ERR);
+ ata_qc_complete(qc, AC_ERR_OTHER);
}
+ spin_unlock_irqrestore(&host_set->lock, flags);
}
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
{
- void *mmio = ap->host_set->mmio_base;
- void *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 status, serr, ci;
serr = readl(port_mmio + PORT_SCR_ERR);
@@ -632,7 +630,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
if (status & PORT_IRQ_FATAL) {
ahci_intr_error(ap, status);
if (qc)
- ata_qc_complete(qc, ATA_ERR);
+ ata_qc_complete(qc, AC_ERR_OTHER);
}
return 1;
@@ -648,7 +646,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
struct ata_host_set *host_set = dev_instance;
struct ahci_host_priv *hpriv;
unsigned int i, handled = 0;
- void *mmio;
+ void __iomem *mmio;
u32 irq_stat, irq_ack = 0;
VPRINTK("ENTER\n");
@@ -666,17 +664,35 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap;
- u32 tmp;
- VPRINTK("port %u\n", i);
+ if (!(irq_stat & (1 << i)))
+ continue;
+
ap = host_set->ports[i];
- tmp = irq_stat & (1 << i);
- if (tmp && ap) {
+ if (ap) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (ahci_host_intr(ap, qc))
- irq_ack |= (1 << i);
+ if (!ahci_host_intr(ap, qc))
+ if (ata_ratelimit()) {
+ struct pci_dev *pdev =
+ to_pci_dev(ap->host_set->dev);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "unhandled interrupt on port %u\n",
+ i);
+ }
+
+ VPRINTK("port %u\n", i);
+ } else {
+ VPRINTK("port %u (no irq)\n", i);
+ if (ata_ratelimit()) {
+ struct pci_dev *pdev =
+ to_pci_dev(ap->host_set->dev);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "interrupt on disabled port %u\n", i);
+ }
}
+
+ irq_ack |= (1 << i);
}
if (irq_ack) {
@@ -694,10 +710,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
static int ahci_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void *port_mmio = (void *) ap->ioaddr.cmd_addr;
-
- writel(1, port_mmio + PORT_SCR_ACT);
- readl(port_mmio + PORT_SCR_ACT); /* flush */
+ void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
writel(1, port_mmio + PORT_CMD_ISSUE);
readl(port_mmio + PORT_CMD_ISSUE); /* flush */
@@ -747,8 +760,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
tmp = readl(mmio + HOST_CTL);
if (tmp & HOST_RESET) {
- printk(KERN_ERR DRV_NAME "(%s): controller reset failed (0x%x)\n",
- pci_name(pdev), tmp);
+ dev_printk(KERN_ERR, &pdev->dev,
+ "controller reset failed (0x%x)\n", tmp);
return -EIO;
}
@@ -776,22 +789,22 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -862,27 +875,11 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
return 0;
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_intx(struct pci_dev *pdev, int enable)
-{
- u16 pci_command, new;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-
- if (enable)
- new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
- else
- new = pci_command | PCI_COMMAND_INTX_DISABLE;
-
- if (new != pci_command)
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
-}
-
static void ahci_print_info(struct ata_probe_ent *probe_ent)
{
struct ahci_host_priv *hpriv = probe_ent->private_data;
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- void *mmio = probe_ent->mmio_base;
+ void __iomem *mmio = probe_ent->mmio_base;
u32 vers, cap, impl, speed;
const char *speed_s;
u16 cc;
@@ -910,10 +907,10 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent)
else
scc_s = "unknown";
- printk(KERN_INFO DRV_NAME "(%s) AHCI %02x%02x.%02x%02x "
+ dev_printk(KERN_INFO, &pdev->dev,
+ "AHCI %02x%02x.%02x%02x "
"%u slots %u ports %s Gbps 0x%x impl %s mode\n"
,
- pci_name(pdev),
(vers >> 24) & 0xff,
(vers >> 16) & 0xff,
@@ -926,11 +923,11 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent)
impl,
scc_s);
- printk(KERN_INFO DRV_NAME "(%s) flags: "
+ dev_printk(KERN_INFO, &pdev->dev,
+ "flags: "
"%s%s%s%s%s%s"
"%s%s%s%s%s%s%s\n"
,
- pci_name(pdev),
cap & (1 << 31) ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "",
@@ -955,7 +952,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_probe_ent *probe_ent = NULL;
struct ahci_host_priv *hpriv;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int have_msi, pci_dev_busy = 0;
int rc;
@@ -963,7 +960,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
VPRINTK("ENTER\n");
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -992,8 +989,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, AHCI_PCI_BAR),
- pci_resource_len(pdev, AHCI_PCI_BAR));
+ mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -1037,7 +1033,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_hpriv:
kfree(hpriv);
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_free_ent:
kfree(probe_ent);
err_out_msi:
@@ -1077,7 +1073,8 @@ static void ahci_remove_one (struct pci_dev *pdev)
scsi_host_put(ap->host);
}
- host_set->ops->host_stop(host_set);
+ kfree(hpriv);
+ pci_iounmap(pdev, host_set->mmio_base);
kfree(host_set);
if (have_msi)
@@ -1094,7 +1091,6 @@ static int __init ahci_init(void)
return pci_module_init(&ahci_pci_driver);
}
-
static void __exit ahci_exit(void)
{
pci_unregister_driver(&ahci_pci_driver);
@@ -1105,6 +1101,7 @@ MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("AHCI SATA low-level driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
module_init(ahci_init);
module_exit(ahci_exit);
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index c2523a30a7f5..69ed77fcb71f 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,6 +5,7 @@
config SCSI_AIC79XX
tristate "Adaptec AIC79xx U320 support"
depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
help
This driver supports all of Adaptec's Ultra 320 PCI-X
based SCSI controllers.
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index 00f3bd1e181e..527efd36f5c1 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
int
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{
- u_long l;
int error;
int have_seeprom;
u_int hostconf;
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index 70c5fb59c9ea..d754b3267863 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -112,6 +112,9 @@ aic7770_remove(struct device *dev)
struct ahc_softc *ahc = dev_get_drvdata(dev);
u_long s;
+ if (ahc->platform_data && ahc->platform_data->host)
+ scsi_remove_host(ahc->platform_data->host);
+
ahc_lock(ahc, &s);
ahc_intr_enable(ahc, FALSE);
ahc_unlock(ahc, &s);
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index fd4b2f3eb0c2..653fb0b42aea 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
uint16_t user_tagenable;/* Tagged Queuing allowed */
};
-TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
-extern struct ahd_softc_tailq ahd_tailq;
-
/*************************** IO Cell Configuration ****************************/
#define AHD_PRECOMP_SLEW_INDEX \
(AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
void ahd_pause_and_flushwork(struct ahd_softc *ahd);
int ahd_suspend(struct ahd_softc *ahd);
int ahd_resume(struct ahd_softc *ahd);
-void ahd_softc_insert(struct ahd_softc *);
-struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
void ahd_set_unit(struct ahd_softc *, int);
void ahd_set_name(struct ahd_softc *, char *);
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
void ahd_print_devinfo(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
void ahd_dump_sglist(struct scb *scb);
-void ahd_dump_all_cards_state(void);
void ahd_dump_card_state(struct ahd_softc *ahd);
int ahd_print_register(ahd_reg_parse_entry_t *table,
u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 137fb1a37dd1..4e8f00df978d 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
#endif
-/******************************** Globals *************************************/
-struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
/***************************** Lookup Tables **********************************/
char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
}
void
-ahd_softc_insert(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
-#if AHD_PCI_CONFIG > 0
- /*
- * Second Function PCI devices need to inherit some
- * settings from function 0.
- */
- if ((ahd->features & AHD_MULTI_FUNC) != 0) {
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dev_softc_t list_pci;
- ahd_dev_softc_t pci;
-
- list_pci = list_ahd->dev_softc;
- pci = ahd->dev_softc;
- if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
- && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
- struct ahd_softc *master;
- struct ahd_softc *slave;
-
- if (ahd_get_pci_function(list_pci) == 0) {
- master = list_ahd;
- slave = ahd;
- } else {
- master = ahd;
- slave = list_ahd;
- }
- slave->flags &= ~AHD_BIOS_ENABLED;
- slave->flags |=
- master->flags & AHD_BIOS_ENABLED;
- break;
- }
- }
- }
-#endif
-
- /*
- * Insertion sort into our list of softcs.
- */
- list_ahd = TAILQ_FIRST(&ahd_tailq);
- while (list_ahd != NULL
- && ahd_softc_comp(ahd, list_ahd) <= 0)
- list_ahd = TAILQ_NEXT(list_ahd, links);
- if (list_ahd != NULL)
- TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
- else
- TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
- ahd->init_level++;
-}
-
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahd_softc *
-ahd_find_softc(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- if (list_ahd == ahd)
- return (ahd);
- }
- return (NULL);
-}
-
-void
ahd_set_unit(struct ahd_softc *ahd, int unit)
{
ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
static void
ahd_reset_poll(void *arg)
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd = arg;
u_int scsiseq1;
- u_long l;
u_long s;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
ahd_pause(ahd);
ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
ahd_reset_poll, ahd);
ahd_unpause(ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
return;
}
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
ahd_unlock(ahd, &s);
ahd_release_simq(ahd);
- ahd_list_unlock(&l);
}
/**************************** Statistics Processing ***************************/
static void
ahd_stat_timer(void *arg)
{
- struct ahd_softc *ahd;
- u_long l;
+ struct ahd_softc *ahd = arg;
u_long s;
int enint_coal;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
ahd_stat_timer, ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
}
/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
return (last_probe);
}
-void
-ahd_dump_all_cards_state(void)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dump_card_state(list_ahd);
- }
-}
-
int
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
}
printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
- ahd_platform_dump_card_state(ahd);
ahd_restore_modes(ahd, saved_modes);
if (paused == 0)
ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 329cb2331339..95c285cc83e4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -46,32 +46,14 @@
#include "aic79xx_inline.h"
#include <scsi/scsicam.h>
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
+static struct scsi_transport_template *ahd_linux_transport_template = NULL;
#include <linux/init.h> /* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h" /* For geometry detection */
-#endif
-
#include <linux/mm.h> /* For fetching system memory size */
+#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
/*
- * Lock protecting manipulation of the ahd softc list.
- */
-spinlock_t ahd_list_spinlock;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahd_linux_nseg;
-#endif
-
-/*
* Bucket size for counting good commands in between bad ones.
*/
#define AHD_LINUX_ERR_THRESH 1000
@@ -188,71 +170,6 @@ static adapter_tag_info_t aic79xx_tag_info[] =
};
/*
- * By default, read streaming is disabled. In theory,
- * read streaming should enhance performance, but early
- * U320 drive firmware actually performs slower with
- * read streaming enabled.
- */
-#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM
-#define AIC79XX_CONFIGED_RD_STRM 0xFFFF
-#else
-#define AIC79XX_CONFIGED_RD_STRM 0
-#endif
-
-static uint16_t aic79xx_rd_strm_info[] =
-{
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM
-};
-
-/*
- * DV option:
- *
- * positive value = DV Enabled
- * zero = DV Disabled
- * negative value = DV Default for adapter type/seeprom
- */
-#ifdef CONFIG_AIC79XX_DV_SETTING
-#define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING
-#else
-#define AIC79XX_CONFIGED_DV -1
-#endif
-
-static int8_t aic79xx_dv_settings[] =
-{
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV
-};
-
-/*
* The I/O cell on the chip is very configurable in respect to its analog
* characteristics. Set the defaults here; they can be overriden with
* the proper insmod parameters.
@@ -375,13 +292,6 @@ static uint32_t aic79xx_pci_parity = ~0;
uint32_t aic79xx_allow_memio = ~0;
/*
- * aic79xx_detect() has been run, so register all device arrivals
- * immediately with the system rather than deferring to the sorted
- * attachment performed by aic79xx_detect().
- */
-int aic79xx_detect_complete;
-
-/*
* So that we can set how long each device is given as a selection timeout.
* The table of values goes like this:
* 0 - 256ms
@@ -412,7 +322,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC79XX_DRIVER_VERSION);
-module_param(aic79xx, charp, 0);
+module_param(aic79xx, charp, 0444);
MODULE_PARM_DESC(aic79xx,
"period delimited, options string.\n"
" verbose Enable verbose/diagnostic logging\n"
@@ -427,8 +337,6 @@ MODULE_PARM_DESC(aic79xx,
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
-" rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n"
-" dv:<dv_settings> Set per-controller Domain Validation Setting.\n"
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
" precomp:<pcomp_list> Set the signal precompensation (0-7).\n"
" amplitude:<int> Set the signal amplitude (0-7).\n"
@@ -441,249 +349,35 @@ MODULE_PARM_DESC(aic79xx,
" Shorten the selection timeout to 128ms\n"
"\n"
" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
-"\n"
-" Sample /etc/modprobe.conf line:\n"
-" Change Read Streaming for Controller's 2 and 3\n"
-"\n"
-" options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
+"\n");
static void ahd_linux_handle_scsi_status(struct ahd_softc *,
- struct ahd_linux_device *,
+ struct scsi_device *,
struct scb *);
static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
- Scsi_Cmnd *cmd);
-static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dev_timed_unfreeze(u_long arg);
+ struct scsi_cmnd *cmd);
static void ahd_linux_sem_timeout(u_long arg);
+static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
-static void ahd_linux_size_nseg(void);
-static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
-static void ahd_linux_start_dv(struct ahd_softc *ahd);
-static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
-static int ahd_linux_dv_thread(void *data);
-static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
-static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
-static void ahd_linux_dv_transition(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_inq(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ,
- u_int request_length);
-static void ahd_linux_dv_tur(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_web(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_reb(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_su(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static int ahd_linux_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
-static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd);
-static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd);
-static void ahd_linux_device_queue_depth(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*,
- u_int, u_int);
-static void ahd_linux_free_target(struct ahd_softc*,
- struct ahd_linux_target*);
-static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*,
- struct ahd_linux_target*,
- u_int);
-static void ahd_linux_free_device(struct ahd_softc*,
- struct ahd_linux_device*);
-static void ahd_linux_run_device_queue(struct ahd_softc*,
- struct ahd_linux_device*);
+static void ahd_linux_device_queue_depth(struct scsi_device *);
+static int ahd_linux_run_command(struct ahd_softc*,
+ struct ahd_linux_device *,
+ struct scsi_cmnd *);
static void ahd_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahd_linux_setup_tag_info;
-static aic_option_callback_t ahd_linux_setup_rd_strm_info;
-static aic_option_callback_t ahd_linux_setup_dv;
-static aic_option_callback_t ahd_linux_setup_iocell_info;
-static int ahd_linux_next_unit(void);
-static void ahd_runq_tasklet(unsigned long data);
-static int aic79xx_setup(char *c);
-
-/****************************** Inlines ***************************************/
-static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
-static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
-static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
-static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
-static __inline struct ahd_linux_device*
- ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
- u_int target, u_int lun, int alloc);
-static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
-static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static __inline struct ahd_linux_device *
- ahd_linux_next_device_to_run(struct ahd_softc *ahd);
-static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
-
-static __inline void
-ahd_schedule_completeq(struct ahd_softc *ahd)
-{
- if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
- ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
- ahd->platform_data->completeq_timer.expires = jiffies;
- add_timer(&ahd->platform_data->completeq_timer);
- }
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahd_schedule_runq(struct ahd_softc *ahd)
-{
- tasklet_schedule(&ahd->platform_data->runq_tasklet);
-}
-
-static __inline
-void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
- (unsigned long)ahd);
-}
+static int aic79xx_setup(char *c);
-static __inline void
-ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_kill(&ahd->platform_data->runq_tasklet);
-}
+static int ahd_linux_unit;
-static __inline struct ahd_linux_device*
-ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
- u_int lun, int alloc)
-{
- struct ahd_linux_target *targ;
- struct ahd_linux_device *dev;
- u_int target_offset;
- target_offset = target;
- if (channel != 0)
- target_offset += 8;
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL) {
- if (alloc != 0) {
- targ = ahd_linux_alloc_target(ahd, channel, target);
- if (targ == NULL)
- return (NULL);
- } else
- return (NULL);
- }
- dev = targ->devices[lun];
- if (dev == NULL && alloc != 0)
- dev = ahd_linux_alloc_device(ahd, targ, lun);
- return (dev);
-}
-
-#define AHD_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahd_cmd *
-ahd_linux_run_complete_queue(struct ahd_softc *ahd)
-{
- struct ahd_cmd *acmd;
- u_long done_flags;
- int with_errors;
-
- with_errors = 0;
- ahd_done_lock(ahd, &done_flags);
- while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
- /*
- * Linux uses stack recursion to requeue
- * commands that need to be retried. Avoid
- * blowing out the stack by "spoon feeding"
- * commands that completed with error back
- * the operating system in case they are going
- * to be retried. "ick"
- */
- ahd_schedule_completeq(ahd);
- break;
- }
- TAILQ_REMOVE(&ahd->platform_data->completeq,
- acmd, acmd_links.tqe);
- cmd = &acmd_scsi_cmd(acmd);
- cmd->host_scribble = NULL;
- if (ahd_cmd_get_transaction_status(cmd) != DID_OK
- || (cmd->result & 0xFF) != SCSI_STATUS_OK)
- with_errors++;
-
- cmd->scsi_done(cmd);
- }
- ahd_done_unlock(ahd, &done_flags);
- return (acmd);
-}
-
-static __inline void
-ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev)
-{
- if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
- && dev->active == 0) {
- dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
- dev->qfrozen--;
- }
-
- if (TAILQ_FIRST(&dev->busyq) == NULL
- || dev->openings == 0 || dev->qfrozen != 0)
- return;
-
- ahd_linux_run_device_queue(ahd, dev);
-}
-
-static __inline struct ahd_linux_device *
-ahd_linux_next_device_to_run(struct ahd_softc *ahd)
-{
-
- if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
- || (ahd->platform_data->qfrozen != 0
- && AHD_DV_SIMQ_FROZEN(ahd) == 0))
- return (NULL);
- return (TAILQ_FIRST(&ahd->platform_data->device_runq));
-}
-
-static __inline void
-ahd_linux_run_device_queues(struct ahd_softc *ahd)
-{
- struct ahd_linux_device *dev;
-
- while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
- TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
- dev->flags &= ~AHD_DEV_ON_RUN_LIST;
- ahd_linux_check_device_queue(ahd, dev);
- }
-}
+/****************************** Inlines ***************************************/
+static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
static __inline void
ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
int direction;
cmd = scb->io_ctx;
@@ -705,197 +399,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
#define BUILD_SCSIID(ahd, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
-/************************ Host template entry points *************************/
-static int ahd_linux_detect(Scsi_Host_Template *);
-static const char *ahd_linux_info(struct Scsi_Host *);
-static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int ahd_linux_slave_alloc(Scsi_Device *);
-static int ahd_linux_slave_configure(Scsi_Device *);
-static void ahd_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int ahd_linux_biosparam(struct scsi_device*,
- struct block_device*, sector_t, int[]);
-#endif
-#else
-static int ahd_linux_release(struct Scsi_Host *);
-static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
- Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int ahd_linux_bus_reset(Scsi_Cmnd *);
-static int ahd_linux_dev_reset(Scsi_Cmnd *);
-static int ahd_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc. This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer. Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem. We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahd_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- u_int cur_size;
- u_int best_size;
-
- /*
- * The SCSI allocator rounds to the nearest 512 bytes
- * an cannot allocate across a page boundary. Our algorithm
- * is to start at 1K of scsi malloc space per-command and
- * loop through all factors of the PAGE_SIZE and pick the best.
- */
- best_size = 0;
- for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
- u_int nseg;
-
- nseg = cur_size / sizeof(struct scatterlist);
- if (nseg < AHD_LINUX_MIN_NSEG)
- continue;
-
- if (best_size == 0) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- } else {
- u_int best_rem;
- u_int cur_rem;
-
- /*
- * Compare the traits of the current "best_size"
- * with the current size to determine if the
- * current size is a better size.
- */
- best_rem = best_size % sizeof(struct scatterlist);
- cur_rem = cur_size % sizeof(struct scatterlist);
- if (cur_rem < best_rem) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- }
- }
- }
-#endif
-}
-
-/*
- * Try to detect an Adaptec 79XX controller.
- */
-static int
-ahd_linux_detect(Scsi_Host_Template *template)
-{
- struct ahd_softc *ahd;
- int found;
- int error = 0;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * It is a bug that the upper layer takes
- * this lock just prior to calling us.
- */
- spin_unlock_irq(&io_request_lock);
-#endif
-
- /*
- * Sanity checking of Linux SCSI data structures so
- * that some of our hacks^H^H^H^H^Hassumptions aren't
- * violated.
- */
- if (offsetof(struct ahd_cmd_internal, end)
- > offsetof(struct scsi_cmnd, host_scribble)) {
- printf("ahd_linux_detect: SCSI data structures changed.\n");
- printf("ahd_linux_detect: Unable to attach\n");
- return (0);
- }
- /*
- * Determine an appropriate size for our Scatter Gatther lists.
- */
- ahd_linux_size_nseg();
-#ifdef MODULE
- /*
- * If we've been passed any parameters, process them now.
- */
- if (aic79xx)
- aic79xx_setup(aic79xx);
-#endif
-
- template->proc_name = "aic79xx";
-
- /*
- * Initialize our softc list lock prior to
- * probing for any adapters.
- */
- ahd_list_lockinit();
-
-#ifdef CONFIG_PCI
- error = ahd_linux_pci_init();
- if (error)
- return error;
-#endif
-
- /*
- * Register with the SCSI layer all
- * controllers we've found.
- */
- found = 0;
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-
- if (ahd_linux_register_host(ahd, template) == 0)
- found++;
- }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- spin_lock_irq(&io_request_lock);
-#endif
- aic79xx_detect_complete++;
- return 0;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-static int
-ahd_linux_release(struct Scsi_Host * host)
-{
- struct ahd_softc *ahd;
- u_long l;
-
- ahd_list_lock(&l);
- if (host != NULL) {
-
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
- if (ahd != NULL) {
- u_long s;
-
- ahd_lock(ahd, &s);
- ahd_intr_enable(ahd, FALSE);
- ahd_unlock(ahd, &s);
- ahd_free(ahd);
- }
- }
- ahd_list_unlock(&l);
- return (0);
-}
-#endif
-
/*
* Return a string describing the driver.
*/
@@ -928,220 +431,177 @@ ahd_linux_info(struct Scsi_Host *host)
* Queue an SCB to the controller.
*/
static int
-ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
{
struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
+ struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
/*
- * Save the callback on completion function.
- */
- cmd->scsi_done = scsi_done;
-
- ahd_midlayer_entrypoint_lock(ahd, &flags);
-
- /*
* Close the race of a command that was in the process of
* being queued to us just as our simq was frozen. Let
* DV commands through so long as we are only frozen to
* perform DV.
*/
- if (ahd->platform_data->qfrozen != 0
- && AHD_DV_CMD(cmd) == 0) {
-
- ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- return (0);
- }
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id, cmd->device->lun,
- /*alloc*/TRUE);
- if (dev == NULL) {
- ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
- ahd_name(ahd));
- return (0);
+ if (ahd->platform_data->qfrozen != 0) {
+ printf("%s: queue frozen\n", ahd_name(ahd));
+
+ return SCSI_MLQUEUE_HOST_BUSY;
}
- if (cmd->cmd_len > MAX_CDB_LEN)
- return (-EINVAL);
+
+ /*
+ * Save the callback on completion function.
+ */
+ cmd->scsi_done = scsi_done;
+
cmd->result = CAM_REQ_INPROG << 16;
- TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);
- if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- ahd_linux_run_device_queues(ahd);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- return (0);
+
+ return ahd_linux_run_command(ahd, dev, cmd);
+}
+
+static inline struct scsi_target **
+ahd_linux_target_in_softc(struct scsi_target *starget)
+{
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+ unsigned int target_offset;
+
+ target_offset = starget->id;
+ if (starget->channel != 0)
+ target_offset += 8;
+
+ return &ahd->platform_data->starget[target_offset];
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static int
-ahd_linux_slave_alloc(Scsi_Device *device)
+ahd_linux_target_alloc(struct scsi_target *starget)
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
+ unsigned long flags;
+ struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+ struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+ struct ahd_devinfo devinfo;
+ struct ahd_initiator_tinfo *tinfo;
+ struct ahd_tmode_tstate *tstate;
+ char channel = starget->channel + 'A';
- ahd = *((struct ahd_softc **)device->host->hostdata);
- if (bootverbose)
- printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id);
- return (0);
+ ahd_lock(ahd, &flags);
+
+ BUG_ON(*ahd_targp != NULL);
+
+ *ahd_targp = starget;
+ memset(targ, 0, sizeof(*targ));
+
+ tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
+ starget->id, &tstate);
+ ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
+ CAM_LUN_WILDCARD, channel,
+ ROLE_INITIATOR);
+ spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */
+ if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
+ spi_max_offset(starget) = MAX_OFFSET_PACED_BUG;
+ else
+ spi_max_offset(starget) = MAX_OFFSET_PACED;
+ spi_max_width(starget) = ahd->features & AHD_WIDE;
+
+ ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
+ AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+ AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_unlock(ahd, &flags);
+
+ return 0;
+}
+
+static void
+ahd_linux_target_destroy(struct scsi_target *starget)
+{
+ struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
+
+ *ahd_targp = NULL;
}
static int
-ahd_linux_slave_configure(Scsi_Device *device)
+ahd_linux_slave_alloc(struct scsi_device *sdev)
{
- struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
+ struct ahd_softc *ahd =
+ *((struct ahd_softc **)sdev->host->hostdata);
+ struct scsi_target *starget = sdev->sdev_target;
+ struct ahd_linux_target *targ = scsi_transport_target_data(starget);
+ struct ahd_linux_device *dev;
- ahd = *((struct ahd_softc **)device->host->hostdata);
if (bootverbose)
- printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id);
- ahd_midlayer_entrypoint_lock(ahd, &flags);
+ printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
+
+ BUG_ON(targ->sdev[sdev->lun] != NULL);
+
+ dev = scsi_transport_device_data(sdev);
+ memset(dev, 0, sizeof(*dev));
+
/*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
+ * We start out life using untagged
+ * transactions of which we allow one.
*/
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- dev->flags |= AHD_DEV_SLAVE_CONFIGURED;
- dev->scsi_device = device;
- ahd_linux_device_queue_depth(ahd, dev);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ dev->openings = 1;
+
+ /*
+ * Set maxtags to 0. This will be changed if we
+ * later determine that we are dealing with
+ * a tagged queuing capable device.
+ */
+ dev->maxtags = 0;
+
+ targ->sdev[sdev->lun] = sdev;
+
return (0);
}
-static void
-ahd_linux_slave_destroy(Scsi_Device *device)
+static int
+ahd_linux_slave_configure(struct scsi_device *sdev)
{
struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
- ahd = *((struct ahd_softc **)device->host->hostdata);
+ ahd = *((struct ahd_softc **)sdev->host->hostdata);
if (bootverbose)
- printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id);
- ahd_midlayer_entrypoint_lock(ahd, &flags);
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/FALSE);
+ printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id);
- /*
- * Filter out "silly" deletions of real devices by only
- * deleting devices that have had slave_configure()
- * called on them. All other devices that have not
- * been configured will automatically be deleted by
- * the refcounting process.
- */
- if (dev != NULL
- && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- if (TAILQ_EMPTY(&dev->busyq)
- && dev->active == 0
- && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
- ahd_linux_free_device(ahd, dev);
- }
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
+ ahd_linux_device_queue_depth(sdev);
+
+ /* Initial Domain Validation */
+ if (!spi_initial_dv(sdev->sdev_target))
+ spi_dv_device(sdev);
+
+ return 0;
}
-#else
-/*
- * Sets the queue depth for each SCSI device hanging
- * off the input host adapter.
- */
+
static void
-ahd_linux_select_queue_depth(struct Scsi_Host * host,
- Scsi_Device * scsi_devs)
+ahd_linux_slave_destroy(struct scsi_device *sdev)
{
- Scsi_Device *device;
- Scsi_Device *ldev;
struct ahd_softc *ahd;
- u_long flags;
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+ struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
- ahd = *((struct ahd_softc **)host->hostdata);
- ahd_lock(ahd, &flags);
- for (device = scsi_devs; device != NULL; device = device->next) {
+ ahd = *((struct ahd_softc **)sdev->host->hostdata);
+ if (bootverbose)
+ printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
- /*
- * Watch out for duplicate devices. This works around
- * some quirks in how the SCSI scanning code does its
- * device management.
- */
- for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
- if (ldev->host == device->host
- && ldev->channel == device->channel
- && ldev->id == device->id
- && ldev->lun == device->lun)
- break;
- }
- /* Skip duplicate. */
- if (ldev != device)
- continue;
+ BUG_ON(dev->active);
- if (device->host == host) {
- struct ahd_linux_device *dev;
+ targ->sdev[sdev->lun] = NULL;
- /*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
- */
- dev = ahd_linux_get_device(ahd, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- dev->scsi_device = device;
- ahd_linux_device_queue_depth(ahd, dev);
- device->queue_depth = dev->openings
- + dev->active;
- if ((dev->flags & (AHD_DEV_Q_BASIC
- | AHD_DEV_Q_TAGGED)) == 0) {
- /*
- * We allow the OS to queue 2 untagged
- * transactions to us at any time even
- * though we can only execute them
- * serially on the controller/device.
- * This should remove some latency.
- */
- device->queue_depth = 2;
- }
- }
- }
- }
- ahd_unlock(ahd, &flags);
}
-#endif
#if defined(__i386__)
/*
* Return the disk geometry for the given SCSI device.
*/
static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
uint8_t *bh;
-#else
-ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
-{
- struct scsi_device *sdev = disk->device;
- u_long capacity = disk->capacity;
- struct buffer_head *bh;
-#endif
int heads;
int sectors;
int cylinders;
@@ -1151,22 +611,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
ahd = *((struct ahd_softc **)sdev->host->hostdata);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
bh = scsi_bios_ptable(bdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
-#else
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
-#endif
-
if (bh) {
ret = scsi_partsize(bh, capacity,
&geom[2], &geom[0], &geom[1]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
kfree(bh);
-#else
- brelse(bh);
-#endif
if (ret != -1)
return (ret);
}
@@ -1194,392 +643,35 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
* Abort the current SCSI command(s).
*/
static int
-ahd_linux_abort(Scsi_Cmnd *cmd)
+ahd_linux_abort(struct scsi_cmnd *cmd)
{
- struct ahd_softc *ahd;
- struct ahd_cmd *acmd;
- struct ahd_cmd *list_acmd;
- struct ahd_linux_device *dev;
- struct scb *pending_scb;
- u_long s;
- u_int saved_scbptr;
- u_int active_scbptr;
- u_int last_phase;
- u_int cdb_byte;
- int retval;
- int was_paused;
- int paused;
- int wait;
- int disconnected;
- ahd_mode_state saved_modes;
-
- pending_scb = NULL;
- paused = FALSE;
- wait = FALSE;
- ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
- acmd = (struct ahd_cmd *)cmd;
-
- printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun, cmd);
- for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
- printf(" 0x%x", cmd->cmnd[cdb_byte]);
- printf("\n");
-
- /*
- * In all versions of Linux, we have to work around
- * a major flaw in how the mid-layer is locked down
- * if we are to sleep successfully in our error handler
- * while allowing our interrupt handler to run. Since
- * the midlayer acquires either the io_request_lock or
- * our lock prior to calling us, we must use the
- * spin_unlock_irq() method for unlocking our lock.
- * This will force interrupts to be enabled on the
- * current CPU. Since the EH thread should not have
- * been running with CPU interrupts disabled other than
- * by acquiring either the io_request_lock or our own
- * lock, this *should* be safe.
- */
- ahd_midlayer_entrypoint_lock(ahd, &s);
-
- /*
- * First determine if we currently own this command.
- * Start by searching the device queue. If not found
- * there, check the pending_scb list. If not found
- * at all, and the system wanted us to just abort the
- * command, return success.
- */
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id, cmd->device->lun,
- /*alloc*/FALSE);
-
- if (dev == NULL) {
- /*
- * No target device for this command exists,
- * so we must not still own the command.
- */
- printf("%s:%d:%d:%d: Is not an active device\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- retval = SUCCESS;
- goto no_cmd;
- }
-
- TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
- if (list_acmd == acmd)
- break;
- }
-
- if (list_acmd != NULL) {
- printf("%s:%d:%d:%d: Command found on device queue\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
- cmd->result = DID_ABORT << 16;
- ahd_linux_queue_cmd_complete(ahd, cmd);
- retval = SUCCESS;
- goto done;
- }
-
- /*
- * See if we can find a matching cmd in the pending list.
- */
- LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
- if (pending_scb->io_ctx == cmd)
- break;
- }
-
- if (pending_scb == NULL) {
- printf("%s:%d:%d:%d: Command not found\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- goto no_cmd;
- }
-
- if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
- /*
- * We can't queue two recovery actions using the same SCB
- */
- retval = FAILED;
- goto done;
- }
-
- /*
- * Ensure that the card doesn't do anything
- * behind our back. Also make sure that we
- * didn't "just" miss an interrupt that would
- * affect this cmd.
- */
- was_paused = ahd_is_paused(ahd);
- ahd_pause_and_flushwork(ahd);
- paused = TRUE;
-
- if ((pending_scb->flags & SCB_ACTIVE) == 0) {
- printf("%s:%d:%d:%d: Command already completed\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- goto no_cmd;
- }
-
- printf("%s: At time of recovery, card was %spaused\n",
- ahd_name(ahd), was_paused ? "" : "not ");
- ahd_dump_card_state(ahd);
-
- disconnected = TRUE;
- if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
- cmd->device->lun, SCB_GET_TAG(pending_scb),
- ROLE_INITIATOR, CAM_REQ_ABORTED,
- SEARCH_COMPLETE) > 0) {
- printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- retval = SUCCESS;
- goto done;
- }
-
- saved_modes = ahd_save_modes(ahd);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- last_phase = ahd_inb(ahd, LASTPHASE);
- saved_scbptr = ahd_get_scbptr(ahd);
- active_scbptr = saved_scbptr;
- if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
- struct scb *bus_scb;
-
- bus_scb = ahd_lookup_scb(ahd, active_scbptr);
- if (bus_scb == pending_scb)
- disconnected = FALSE;
- }
-
- /*
- * At this point, pending_scb is the scb associated with the
- * passed in command. That command is currently active on the
- * bus or is in the disconnected state.
- */
- if (last_phase != P_BUSFREE
- && SCB_GET_TAG(pending_scb) == active_scbptr) {
-
- /*
- * We're active on the bus, so assert ATN
- * and hope that the target responds.
- */
- pending_scb = ahd_lookup_scb(ahd, active_scbptr);
- pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
- ahd_outb(ahd, MSG_OUT, HOST_MSG);
- ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
- printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
- ahd_name(ahd), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
- wait = TRUE;
- } else if (disconnected) {
-
- /*
- * Actually re-queue this SCB in an attempt
- * to select the device before it reconnects.
- */
- pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
- ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
- pending_scb->hscb->cdb_len = 0;
- pending_scb->hscb->task_attribute = 0;
- pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
-
- if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
- /*
- * Mark the SCB has having an outstanding
- * task management function. Should the command
- * complete normally before the task management
- * function can be sent, the host will be notified
- * to abort our requeued SCB.
- */
- ahd_outb(ahd, SCB_TASK_MANAGEMENT,
- pending_scb->hscb->task_management);
- } else {
- /*
- * If non-packetized, set the MK_MESSAGE control
- * bit indicating that we desire to send a message.
- * We also set the disconnected flag since there is
- * no guarantee that our SCB control byte matches
- * the version on the card. We don't want the
- * sequencer to abort the command thinking an
- * unsolicited reselection occurred.
- */
- pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+ int error;
- /*
- * The sequencer will never re-reference the
- * in-core SCB. To make sure we are notified
- * during reslection, set the MK_MESSAGE flag in
- * the card's copy of the SCB.
- */
- ahd_outb(ahd, SCB_CONTROL,
- ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
- }
-
- /*
- * Clear out any entries in the QINFIFO first
- * so we are the next SCB for this target
- * to run.
- */
- ahd_search_qinfifo(ahd, cmd->device->id,
- cmd->device->channel + 'A', cmd->device->lun,
- SCB_LIST_NULL, ROLE_INITIATOR,
- CAM_REQUEUE_REQ, SEARCH_COMPLETE);
- ahd_qinfifo_requeue_tail(ahd, pending_scb);
- ahd_set_scbptr(ahd, saved_scbptr);
- ahd_print_path(ahd, pending_scb);
- printf("Device is disconnected, re-queuing SCB\n");
- wait = TRUE;
- } else {
- printf("%s:%d:%d:%d: Unable to deliver message\n",
- ahd_name(ahd), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
- retval = FAILED;
- goto done;
- }
-
-no_cmd:
- /*
- * Our assumption is that if we don't have the command, no
- * recovery action was required, so we return success. Again,
- * the semantics of the mid-layer recovery engine are not
- * well defined, so this may change in time.
- */
- retval = SUCCESS;
-done:
- if (paused)
- ahd_unpause(ahd);
- if (wait) {
- struct timer_list timer;
- int ret;
-
- pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
- spin_unlock_irq(&ahd->platform_data->spin_lock);
- init_timer(&timer);
- timer.data = (u_long)pending_scb;
- timer.expires = jiffies + (5 * HZ);
- timer.function = ahd_linux_sem_timeout;
- add_timer(&timer);
- printf("Recovery code sleeping\n");
- down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
- ret = del_timer_sync(&timer);
- if (ret == 0) {
- printf("Timer Expired\n");
- retval = FAILED;
- }
- spin_lock_irq(&ahd->platform_data->spin_lock);
- }
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &s);
- return (retval);
-}
-
-
-static void
-ahd_linux_dev_reset_complete(Scsi_Cmnd *cmd)
-{
- free(cmd, M_DEVBUF);
+ error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT);
+ if (error != 0)
+ printf("aic79xx_abort returns 0x%x\n", error);
+ return error;
}
/*
* Attempt to send a target reset message to the device that timed out.
*/
static int
-ahd_linux_dev_reset(Scsi_Cmnd *cmd)
+ahd_linux_dev_reset(struct scsi_cmnd *cmd)
{
- struct ahd_softc *ahd;
- struct scsi_cmnd *recovery_cmd;
- struct ahd_linux_device *dev;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
- struct scb *scb;
- struct hardware_scb *hscb;
- u_long s;
- struct timer_list timer;
- int retval;
-
- ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
- recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
- if (!recovery_cmd)
- return (FAILED);
- memset(recovery_cmd, 0, sizeof(struct scsi_cmnd));
- recovery_cmd->device = cmd->device;
- recovery_cmd->scsi_done = ahd_linux_dev_reset_complete;
-#ifdef AHD_DEBUG
- if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
- printf("%s:%d:%d:%d: Device reset called for cmd %p\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->device->lun, cmd);
-#endif
- ahd_lock(ahd, &s);
-
- dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
- cmd->device->lun, /*alloc*/FALSE);
- if (dev == NULL) {
- ahd_unlock(ahd, &s);
- kfree(recovery_cmd);
- return (FAILED);
- }
- if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
- ahd_unlock(ahd, &s);
- kfree(recovery_cmd);
- return (FAILED);
- }
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- cmd->device->id, &tstate);
- recovery_cmd->result = CAM_REQ_INPROG << 16;
- recovery_cmd->host_scribble = (char *)scb;
- scb->io_ctx = recovery_cmd;
- scb->platform_data->dev = dev;
- scb->sg_count = 0;
- ahd_set_residual(scb, 0);
- ahd_set_sense_residual(scb, 0);
- hscb = scb->hscb;
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahd, cmd);
- hscb->lun = cmd->device->lun;
- hscb->cdb_len = 0;
- hscb->task_management = SIU_TASKMGMT_LUN_RESET;
- scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
- if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- scb->flags |= SCB_PACKETIZED;
- } else {
- hscb->control |= MK_MESSAGE;
- }
- dev->openings--;
- dev->active++;
- dev->commands_issued++;
- LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
- ahd_queue_scb(ahd, scb);
+ int error;
- scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
- ahd_unlock(ahd, &s);
- init_timer(&timer);
- timer.data = (u_long)scb;
- timer.expires = jiffies + (5 * HZ);
- timer.function = ahd_linux_sem_timeout;
- add_timer(&timer);
- printf("Recovery code sleeping\n");
- down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
- retval = SUCCESS;
- if (del_timer_sync(&timer) == 0) {
- printf("Timer Expired\n");
- retval = FAILED;
- }
- ahd_lock(ahd, &s);
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &s);
- printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
- return (retval);
+ error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
+ if (error != 0)
+ printf("aic79xx_dev_reset returns 0x%x\n", error);
+ return error;
}
/*
* Reset the SCSI bus.
*/
static int
-ahd_linux_bus_reset(Scsi_Cmnd *cmd)
+ahd_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahd_softc *ahd;
u_long s;
@@ -1594,7 +686,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
- ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &s);
if (bootverbose)
@@ -1604,9 +695,10 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
return (SUCCESS);
}
-Scsi_Host_Template aic79xx_driver_template = {
+struct scsi_host_template aic79xx_driver_template = {
.module = THIS_MODULE,
.name = "aic79xx",
+ .proc_name = "aic79xx",
.proc_info = ahd_linux_proc_info,
.info = ahd_linux_info,
.queuecommand = ahd_linux_queue,
@@ -1623,37 +715,10 @@ Scsi_Host_Template aic79xx_driver_template = {
.slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure,
.slave_destroy = ahd_linux_slave_destroy,
+ .target_alloc = ahd_linux_target_alloc,
+ .target_destroy = ahd_linux_target_destroy,
};
-/**************************** Tasklet Handler *********************************/
-
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahd_schedule_runq() calls this routine
- * directly and ahd_schedule_runq() is called with our lock held.
- */
-static void
-ahd_runq_tasklet(unsigned long data)
-{
- struct ahd_softc* ahd;
- struct ahd_linux_device *dev;
- u_long flags;
-
- ahd = (struct ahd_softc *)data;
- ahd_lock(ahd, &flags);
- while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-
- TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
- dev->flags &= ~AHD_DEV_ON_RUN_LIST;
- ahd_linux_check_device_queue(ahd, dev);
- /* Yeild to our interrupt handler */
- ahd_unlock(ahd, &flags);
- ahd_lock(ahd, &flags);
- }
- ahd_unlock(ahd, &flags);
-}
-
/******************************** Bus DMA *************************************/
int
ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
@@ -1693,36 +758,10 @@ int
ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
int flags, bus_dmamap_t *mapp)
{
- bus_dmamap_t map;
-
- map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
- if (map == NULL)
- return (ENOMEM);
- /*
- * Although we can dma data above 4GB, our
- * "consistent" memory is below 4GB for
- * space efficiency reasons (only need a 4byte
- * address). For this reason, we have to reset
- * our dma mask when doing allocations.
- */
- if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
- printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
*vaddr = pci_alloc_consistent(ahd->dev_softc,
- dmat->maxsize, &map->bus_addr);
- if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc,
- ahd->platform_data->hw_dma_mask)) {
- printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
+ dmat->maxsize, mapp);
if (*vaddr == NULL)
return (ENOMEM);
- *mapp = map;
return(0);
}
@@ -1731,7 +770,7 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
void* vaddr, bus_dmamap_t map)
{
pci_free_consistent(ahd->dev_softc, dmat->maxsize,
- vaddr, map->bus_addr);
+ vaddr, map);
}
int
@@ -1745,7 +784,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
*/
bus_dma_segment_t stack_sg;
- stack_sg.ds_addr = map->bus_addr;
+ stack_sg.ds_addr = map;
stack_sg.ds_len = dmat->maxsize;
cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
return (0);
@@ -1754,11 +793,6 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
void
ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
{
- /*
- * The map may is NULL in our < 2.3.X implementation.
- */
- if (map != NULL)
- free(map, M_DEVBUF);
}
int
@@ -1823,41 +857,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
}
static void
-ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
-{
-
- if ((instance >= 0) && (targ >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_tag_info))
- && (targ < AHD_NUM_TARGETS)) {
- aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
- if (bootverbose)
- printf("tag_info[%d:%d] = %d\n", instance, targ, value);
- }
-}
-
-static void
-ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value)
-{
- if ((instance >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {
- aic79xx_rd_strm_info[instance] = value & 0xFFFF;
- if (bootverbose)
- printf("rd_strm[%d] = 0x%x\n", instance, value);
- }
-}
-
-static void
-ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
-{
- if ((instance >= 0)
- && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {
- aic79xx_dv_settings[instance] = value;
- if (bootverbose)
- printf("dv[%d] = %d\n", instance, value);
- }
-}
-
-static void
ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
{
@@ -1887,6 +886,99 @@ ahd_linux_setup_tag_info_global(char *p)
}
}
+static void
+ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
+{
+
+ if ((instance >= 0) && (targ >= 0)
+ && (instance < NUM_ELEMENTS(aic79xx_tag_info))
+ && (targ < AHD_NUM_TARGETS)) {
+ aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
+ if (bootverbose)
+ printf("tag_info[%d:%d] = %d\n", instance, targ, value);
+ }
+}
+
+static char *
+ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+ void (*callback)(u_long, int, int, int32_t),
+ u_long callback_arg)
+{
+ char *tok_end;
+ char *tok_end2;
+ int i;
+ int instance;
+ int targ;
+ int done;
+ char tok_list[] = {'.', ',', '{', '}', '\0'};
+
+ /* All options use a ':' name/arg separator */
+ if (*opt_arg != ':')
+ return (opt_arg);
+ opt_arg++;
+ instance = -1;
+ targ = -1;
+ done = FALSE;
+ /*
+ * Restore separator that may be in
+ * the middle of our option argument.
+ */
+ tok_end = strchr(opt_arg, '\0');
+ if (tok_end < end)
+ *tok_end = ',';
+ while (!done) {
+ switch (*opt_arg) {
+ case '{':
+ if (instance == -1) {
+ instance = 0;
+ } else {
+ if (depth > 1) {
+ if (targ == -1)
+ targ = 0;
+ } else {
+ printf("Malformed Option %s\n",
+ opt_name);
+ done = TRUE;
+ }
+ }
+ opt_arg++;
+ break;
+ case '}':
+ if (targ != -1)
+ targ = -1;
+ else if (instance != -1)
+ instance = -1;
+ opt_arg++;
+ break;
+ case ',':
+ case '.':
+ if (instance == -1)
+ done = TRUE;
+ else if (targ >= 0)
+ targ++;
+ else if (instance >= 0)
+ instance++;
+ opt_arg++;
+ break;
+ case '\0':
+ done = TRUE;
+ break;
+ default:
+ tok_end = end;
+ for (i = 0; tok_list[i]; i++) {
+ tok_end2 = strchr(opt_arg, tok_list[i]);
+ if ((tok_end2) && (tok_end2 < tok_end))
+ tok_end = tok_end2;
+ }
+ callback(callback_arg, instance, targ,
+ simple_strtol(opt_arg, NULL, 0));
+ opt_arg = tok_end;
+ break;
+ }
+ }
+ return (opt_arg);
+}
+
/*
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
@@ -1916,8 +1008,6 @@ aic79xx_setup(char *s)
{ "seltime", &aic79xx_seltime },
{ "tag_info", NULL },
{ "global_tag_depth", NULL},
- { "rd_strm", NULL },
- { "dv", NULL },
{ "slewrate", NULL },
{ "precomp", NULL },
{ "amplitude", NULL },
@@ -1946,24 +1036,18 @@ aic79xx_setup(char *s)
if (strncmp(p, "global_tag_depth", n) == 0) {
ahd_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
- s = aic_parse_brace_option("tag_info", p + n, end,
+ s = ahd_parse_brace_option("tag_info", p + n, end,
2, ahd_linux_setup_tag_info, 0);
- } else if (strncmp(p, "rd_strm", n) == 0) {
- s = aic_parse_brace_option("rd_strm", p + n, end,
- 1, ahd_linux_setup_rd_strm_info, 0);
- } else if (strncmp(p, "dv", n) == 0) {
- s = aic_parse_brace_option("dv", p + n, end, 1,
- ahd_linux_setup_dv, 0);
} else if (strncmp(p, "slewrate", n) == 0) {
- s = aic_parse_brace_option("slewrate",
+ s = ahd_parse_brace_option("slewrate",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_SLEWRATE_INDEX);
} else if (strncmp(p, "precomp", n) == 0) {
- s = aic_parse_brace_option("precomp",
+ s = ahd_parse_brace_option("precomp",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_PRECOMP_INDEX);
} else if (strncmp(p, "amplitude", n) == 0) {
- s = aic_parse_brace_option("amplitude",
+ s = ahd_parse_brace_option("amplitude",
p + n, end, 1, ahd_linux_setup_iocell_info,
AIC79XX_AMPLITUDE_INDEX);
} else if (p[n] == ':') {
@@ -1982,13 +1066,12 @@ __setup("aic79xx=", aic79xx_setup);
uint32_t aic79xx_verbose;
int
-ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
+ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
{
char buf[80];
struct Scsi_Host *host;
char *new_name;
u_long s;
- u_long target;
template->name = ahd->description;
host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
@@ -1997,11 +1080,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
*((struct ahd_softc **)host->hostdata) = ahd;
ahd_lock(ahd, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_assign_lock(host, &ahd->platform_data->spin_lock);
-#elif AHD_SCSI_HAS_HOST_LOCK != 0
- host->lock = &ahd->platform_data->spin_lock;
-#endif
ahd->platform_data->host = host;
host->can_queue = AHD_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -2012,7 +1091,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
host->max_lun = AHD_NUM_LUNS;
host->max_channel = 0;
host->sg_tablesize = AHD_NSEG;
- ahd_set_unit(ahd, ahd_linux_next_unit());
+ ahd_set_unit(ahd, ahd_linux_unit++);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@@ -2020,54 +1099,14 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
ahd_set_name(ahd, new_name);
}
host->unique_id = ahd->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- scsi_set_pci_device(host, ahd->dev_softc);
-#endif
- ahd_linux_setup_user_rd_strm_settings(ahd);
ahd_linux_initialize_scsi_bus(ahd);
- ahd_unlock(ahd, &s);
- ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);
- ahd_lock(ahd, &s);
- if (ahd->platform_data->dv_pid < 0) {
- printf("%s: Failed to create DV thread, error= %d\n",
- ahd_name(ahd), ahd->platform_data->dv_pid);
- return (-ahd->platform_data->dv_pid);
- }
- /*
- * Initially allocate *all* of our linux target objects
- * so that the DV thread will scan them all in parallel
- * just after driver initialization. Any device that
- * does not exist will have its target object destroyed
- * by the selection timeout handler. In the case of a
- * device that appears after the initial DV scan, async
- * negotiation will occur for the first command, and DV
- * will comence should that first command be successful.
- */
- for (target = 0; target < host->max_id; target++) {
-
- /*
- * Skip our own ID. Some Compaq/HP storage devices
- * have enclosure management devices that respond to
- * single bit selection (i.e. selecting ourselves).
- * It is expected that either an external application
- * or a modified kernel will be used to probe this
- * ID if it is appropriate. To accommodate these
- * installations, ahc_linux_alloc_target() will allocate
- * for our ID if asked to do so.
- */
- if (target == ahd->our_id)
- continue;
-
- ahd_linux_alloc_target(ahd, 0, target);
- }
ahd_intr_enable(ahd, TRUE);
- ahd_linux_start_dv(ahd);
ahd_unlock(ahd, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ host->transportt = ahd_linux_transport_template;
+
scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
scsi_scan_host(host);
-#endif
return (0);
}
@@ -2081,29 +1120,6 @@ ahd_linux_get_memsize(void)
}
/*
- * Find the smallest available unit number to use
- * for a new device. We don't just use a static
- * count to handle the "repeated hot-(un)plug"
- * scenario.
- */
-static int
-ahd_linux_next_unit(void)
-{
- struct ahd_softc *ahd;
- int unit;
-
- unit = 0;
-retry:
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- if (ahd->unit == unit) {
- unit++;
- goto retry;
- }
- }
- return (unit);
-}
-
-/*
* Place the SCSI bus into a known state by either resetting it,
* or forcing transfer negotiations on the next command to any
* target.
@@ -2162,20 +1178,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
if (ahd->platform_data == NULL)
return (ENOMEM);
memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
- TAILQ_INIT(&ahd->platform_data->completeq);
- TAILQ_INIT(&ahd->platform_data->device_runq);
ahd->platform_data->irq = AHD_LINUX_NOIRQ;
- ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
ahd_lockinit(ahd);
- ahd_done_lockinit(ahd);
- init_timer(&ahd->platform_data->completeq_timer);
- ahd->platform_data->completeq_timer.data = (u_long)ahd;
- ahd->platform_data->completeq_timer.function =
- (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
- init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
- init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
- ahd_setup_runq_tasklet(ahd);
ahd->seltime = (aic79xx_seltime & 0x3) << 4;
return (0);
}
@@ -2183,39 +1188,22 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
void
ahd_platform_free(struct ahd_softc *ahd)
{
- struct ahd_linux_target *targ;
- struct ahd_linux_device *dev;
+ struct scsi_target *starget;
int i, j;
if (ahd->platform_data != NULL) {
- del_timer_sync(&ahd->platform_data->completeq_timer);
- ahd_linux_kill_dv_thread(ahd);
- ahd_teardown_runq_tasklet(ahd);
- if (ahd->platform_data->host != NULL) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- scsi_remove_host(ahd->platform_data->host);
-#endif
- scsi_host_put(ahd->platform_data->host);
- }
-
/* destroy all of the device and target objects */
for (i = 0; i < AHD_NUM_TARGETS; i++) {
- targ = ahd->platform_data->targets[i];
- if (targ != NULL) {
- /* Keep target around through the loop. */
- targ->refcount++;
+ starget = ahd->platform_data->starget[i];
+ if (starget != NULL) {
for (j = 0; j < AHD_NUM_LUNS; j++) {
-
- if (targ->devices[j] == NULL)
+ struct ahd_linux_target *targ =
+ scsi_transport_target_data(starget);
+ if (targ->sdev[j] == NULL)
continue;
- dev = targ->devices[j];
- ahd_linux_free_device(ahd, dev);
+ targ->sdev[j] = NULL;
}
- /*
- * Forcibly free the target now that
- * all devices are gone.
- */
- ahd_linux_free_target(ahd, targ);
+ ahd->platform_data->starget[i] = NULL;
}
}
@@ -2233,16 +1221,9 @@ ahd_platform_free(struct ahd_softc *ahd)
release_mem_region(ahd->platform_data->mem_busaddr,
0x1000);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * In 2.4 we detach from the scsi midlayer before the PCI
- * layer invokes our remove callback. No per-instance
- * detach is provided, so we must reach inside the PCI
- * subsystem's internals and detach our driver manually.
- */
- if (ahd->dev_softc != NULL)
- ahd->dev_softc->driver = NULL;
-#endif
+ if (ahd->platform_data->host)
+ scsi_host_put(ahd->platform_data->host);
+
free(ahd->platform_data, M_DEVBUF);
}
}
@@ -2280,13 +1261,22 @@ void
ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_queue_alg alg)
{
+ struct scsi_target *starget;
+ struct ahd_linux_target *targ;
struct ahd_linux_device *dev;
+ struct scsi_device *sdev;
int was_queuing;
int now_queuing;
- dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
- devinfo->target,
- devinfo->lun, /*alloc*/FALSE);
+ starget = ahd->platform_data->starget[devinfo->target];
+ targ = scsi_transport_target_data(starget);
+ BUG_ON(targ == NULL);
+ sdev = targ->sdev[devinfo->lun];
+ if (sdev == NULL)
+ return;
+
+ dev = scsi_transport_device_data(sdev);
+
if (dev == NULL)
return;
was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
@@ -2339,1434 +1329,37 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
dev->maxtags = 0;
dev->openings = 1 - dev->active;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if (dev->scsi_device != NULL) {
- switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
- case AHD_DEV_Q_BASIC:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_SIMPLE_TASK,
- dev->openings + dev->active);
- break;
- case AHD_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_ORDERED_TASK,
- dev->openings + dev->active);
- break;
- default:
- /*
- * We allow the OS to queue 2 untagged transactions to
- * us at any time even though we can only execute them
- * serially on the controller/device. This should
- * remove some latency.
- */
- scsi_adjust_queue_depth(dev->scsi_device,
- /*NON-TAGGED*/0,
- /*queue depth*/2);
- break;
- }
- }
-#endif
-}
-
-int
-ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
- int lun, u_int tag, role_t role, uint32_t status)
-{
- int targ;
- int maxtarg;
- int maxlun;
- int clun;
- int count;
-
- if (tag != SCB_LIST_NULL)
- return (0);
-
- targ = 0;
- if (target != CAM_TARGET_WILDCARD) {
- targ = target;
- maxtarg = targ + 1;
- } else {
- maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
- }
- clun = 0;
- if (lun != CAM_LUN_WILDCARD) {
- clun = lun;
- maxlun = clun + 1;
- } else {
- maxlun = AHD_NUM_LUNS;
- }
-
- count = 0;
- for (; targ < maxtarg; targ++) {
-
- for (; clun < maxlun; clun++) {
- struct ahd_linux_device *dev;
- struct ahd_busyq *busyq;
- struct ahd_cmd *acmd;
-
- dev = ahd_linux_get_device(ahd, /*chan*/0, targ,
- clun, /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- busyq = &dev->busyq;
- while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- cmd = &acmd_scsi_cmd(acmd);
- TAILQ_REMOVE(busyq, acmd,
- acmd_links.tqe);
- count++;
- cmd->result = status << 16;
- ahd_linux_queue_cmd_complete(ahd, cmd);
- }
- }
- }
-
- return (count);
-}
-
-static void
-ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
-{
- u_long flags;
-
- ahd_lock(ahd, &flags);
- del_timer(&ahd->platform_data->completeq_timer);
- ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &flags);
-}
-
-static void
-ahd_linux_start_dv(struct ahd_softc *ahd)
-{
-
- /*
- * Freeze the simq and signal ahd_linux_queue to not let any
- * more commands through
- */
- if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s: Starting DV\n", ahd_name(ahd));
-#endif
-
- ahd->platform_data->flags |= AHD_DV_ACTIVE;
- ahd_freeze_simq(ahd);
-
- /* Wake up the DV kthread */
- up(&ahd->platform_data->dv_sem);
- }
-}
-
-static int
-ahd_linux_dv_thread(void *data)
-{
- struct ahd_softc *ahd;
- int target;
- u_long s;
-
- ahd = (struct ahd_softc *)data;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("In DV Thread\n");
-#endif
-
- /*
- * Complete thread creation.
- */
- lock_kernel();
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
- /*
- * Don't care about any signals.
- */
- siginitsetinv(&current->blocked, 0);
-
- daemonize();
- sprintf(current->comm, "ahd_dv_%d", ahd->unit);
-#else
- daemonize("ahd_dv_%d", ahd->unit);
- current->flags |= PF_NOFREEZE;
-#endif
- unlock_kernel();
-
- while (1) {
- /*
- * Use down_interruptible() rather than down() to
- * avoid inclusion in the load average.
- */
- down_interruptible(&ahd->platform_data->dv_sem);
-
- /* Check to see if we've been signaled to exit */
- ahd_lock(ahd, &s);
- if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) {
- ahd_unlock(ahd, &s);
- break;
- }
- ahd_unlock(ahd, &s);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s: Beginning Domain Validation\n",
- ahd_name(ahd));
-#endif
-
- /*
- * Wait for any pending commands to drain before proceeding.
- */
- ahd_lock(ahd, &s);
- while (LIST_FIRST(&ahd->pending_scbs) != NULL) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
-
- /*
- * Wait for the SIMQ to be released so that DV is the
- * only reason the queue is frozen.
- */
- while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
- ahd_unlock(ahd, &s);
-
- for (target = 0; target < AHD_NUM_TARGETS; target++)
- ahd_linux_dv_target(ahd, target);
-
- ahd_lock(ahd, &s);
- ahd->platform_data->flags &= ~AHD_DV_ACTIVE;
- ahd_unlock(ahd, &s);
-
- /*
- * Release the SIMQ so that normal commands are
- * allowed to continue on the bus.
- */
- ahd_release_simq(ahd);
- }
- up(&ahd->platform_data->eh_sem);
- return (0);
-}
-
-static void
-ahd_linux_kill_dv_thread(struct ahd_softc *ahd)
-{
- u_long s;
-
- ahd_lock(ahd, &s);
- if (ahd->platform_data->dv_pid != 0) {
- ahd->platform_data->flags |= AHD_DV_SHUTDOWN;
- ahd_unlock(ahd, &s);
- up(&ahd->platform_data->dv_sem);
-
- /*
- * Use the eh_sem as an indicator that the
- * dv thread is exiting. Note that the dv
- * thread must still return after performing
- * the up on our semaphore before it has
- * completely exited this module. Unfortunately,
- * there seems to be no easy way to wait for the
- * exit of a thread for which you are not the
- * parent (dv threads are parented by init).
- * Cross your fingers...
- */
- down(&ahd->platform_data->eh_sem);
-
- /*
- * Mark the dv thread as already dead. This
- * avoids attempting to kill it a second time.
- * This is necessary because we must kill the
- * DV thread before calling ahd_free() in the
- * module shutdown case to avoid bogus locking
- * in the SCSI mid-layer, but we ahd_free() is
- * called without killing the DV thread in the
- * instance detach case, so ahd_platform_free()
- * calls us again to verify that the DV thread
- * is dead.
- */
- ahd->platform_data->dv_pid = 0;
- } else {
- ahd_unlock(ahd, &s);
- }
-}
-
-#define AHD_LINUX_DV_INQ_SHORT_LEN 36
-#define AHD_LINUX_DV_INQ_LEN 256
-#define AHD_LINUX_DV_TIMEOUT (HZ / 4)
-
-#define AHD_SET_DV_STATE(ahd, targ, newstate) \
- ahd_set_dv_state(ahd, targ, newstate, __LINE__)
-
-static __inline void
-ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ,
- ahd_dv_state newstate, u_int line)
-{
- ahd_dv_state oldstate;
- oldstate = targ->dv_state;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s:%d: Going from state %d to state %d\n",
- ahd_name(ahd), line, oldstate, newstate);
-#endif
-
- if (oldstate == newstate)
- targ->dv_state_retry++;
- else
- targ->dv_state_retry = 0;
- targ->dv_state = newstate;
-}
-
-static void
-ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
-{
- struct ahd_devinfo devinfo;
- struct ahd_linux_target *targ;
- struct scsi_cmnd *cmd;
- struct scsi_device *scsi_dev;
- struct scsi_sense_data *sense;
- uint8_t *buffer;
- u_long s;
- u_int timeout;
- int echo_size;
-
- sense = NULL;
- buffer = NULL;
- echo_size = 0;
- ahd_lock(ahd, &s);
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) {
- ahd_unlock(ahd, &s);
- return;
- }
- ahd_compile_devinfo(&devinfo, ahd->our_id, targ->target, /*lun*/0,
- targ->channel + 'A', ROLE_INITIATOR);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, &devinfo);
- printf("Performing DV\n");
- }
-#endif
-
- ahd_unlock(ahd, &s);
-
- cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
- scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK);
- scsi_dev->host = ahd->platform_data->host;
- scsi_dev->id = devinfo.target;
- scsi_dev->lun = devinfo.lun;
- scsi_dev->channel = devinfo.channel - 'A';
- ahd->platform_data->dv_scsi_dev = scsi_dev;
-
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC);
-
- while (targ->dv_state != AHD_DV_STATE_EXIT) {
- timeout = AHD_LINUX_DV_TIMEOUT;
- switch (targ->dv_state) {
- case AHD_DV_STATE_INQ_SHORT_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC_VERIFY:
- /*
- * Set things to async narrow to reduce the
- * chance that the INQ will fail.
- */
- ahd_lock(ahd, &s);
- ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_unlock(ahd, &s);
- timeout = 10 * HZ;
- targ->flags &= ~AHD_INQ_VALID;
- /* FALLTHROUGH */
- case AHD_DV_STATE_INQ_VERIFY:
- {
- u_int inq_len;
-
- if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC)
- inq_len = AHD_LINUX_DV_INQ_SHORT_LEN;
- else
- inq_len = targ->inq_data->additional_length + 5;
- ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len);
- break;
- }
- case AHD_DV_STATE_TUR:
- case AHD_DV_STATE_BUSY:
- timeout = 5 * HZ;
- ahd_linux_dv_tur(ahd, cmd, &devinfo);
- break;
- case AHD_DV_STATE_REBD:
- ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ);
- break;
- case AHD_DV_STATE_WEB:
- ahd_linux_dv_web(ahd, cmd, &devinfo, targ);
- break;
-
- case AHD_DV_STATE_REB:
- ahd_linux_dv_reb(ahd, cmd, &devinfo, targ);
- break;
-
- case AHD_DV_STATE_SU:
- ahd_linux_dv_su(ahd, cmd, &devinfo, targ);
- timeout = 50 * HZ;
- break;
-
- default:
- ahd_print_devinfo(ahd, &devinfo);
- printf("Unknown DV state %d\n", targ->dv_state);
- goto out;
- }
-
- /* Queue the command and wait for it to complete */
- /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
- init_timer(&cmd->eh_timeout);
-#ifdef AHD_DEBUG
- if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
- /*
- * All of the printfs during negotiation
- * really slow down the negotiation.
- * Add a bit of time just to be safe.
- */
- timeout += HZ;
-#endif
- scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout);
- /*
- * In 2.5.X, it is assumed that all calls from the
- * "midlayer" (which we are emulating) will have the
- * ahd host lock held. For other kernels, the
- * io_request_lock must be held.
- */
-#if AHD_SCSI_HAS_HOST_LOCK != 0
- ahd_lock(ahd, &s);
-#else
- spin_lock_irqsave(&io_request_lock, s);
-#endif
- ahd_linux_queue(cmd, ahd_linux_dv_complete);
-#if AHD_SCSI_HAS_HOST_LOCK != 0
- ahd_unlock(ahd, &s);
-#else
- spin_unlock_irqrestore(&io_request_lock, s);
-#endif
- down_interruptible(&ahd->platform_data->dv_cmd_sem);
- /*
- * Wait for the SIMQ to be released so that DV is the
- * only reason the queue is frozen.
- */
- ahd_lock(ahd, &s);
- while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
- ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
- ahd_unlock(ahd, &s);
- down_interruptible(&ahd->platform_data->dv_sem);
- ahd_lock(ahd, &s);
- }
- ahd_unlock(ahd, &s);
-
- ahd_linux_dv_transition(ahd, cmd, &devinfo, targ);
- }
-
-out:
- if ((targ->flags & AHD_INQ_VALID) != 0
- && ahd_linux_get_device(ahd, devinfo.channel - 'A',
- devinfo.target, devinfo.lun,
- /*alloc*/FALSE) == NULL) {
- /*
- * The DV state machine failed to configure this device.
- * This is normal if DV is disabled. Since we have inquiry
- * data, filter it and use the "optimistic" negotiation
- * parameters found in the inquiry string.
- */
- ahd_linux_filter_inquiry(ahd, &devinfo);
- if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
- ahd_print_devinfo(ahd, &devinfo);
- printf("DV failed to configure device. "
- "Please file a bug report against "
- "this driver.\n");
- }
- }
-
- if (cmd != NULL)
- free(cmd, M_DEVBUF);
-
- if (ahd->platform_data->dv_scsi_dev != NULL) {
- free(ahd->platform_data->dv_scsi_dev, M_DEVBUF);
- ahd->platform_data->dv_scsi_dev = NULL;
- }
-
- ahd_lock(ahd, &s);
- if (targ->dv_buffer != NULL) {
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = NULL;
- }
- if (targ->dv_buffer1 != NULL) {
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = NULL;
- }
- targ->flags &= ~AHD_DV_REQUIRED;
- if (targ->refcount == 0)
- ahd_linux_free_target(ahd, targ);
- ahd_unlock(ahd, &s);
-}
-
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
- u_long s;
- int retval;
-
- ahd_lock(ahd, &s);
- retval = ahd_linux_fallback(ahd, devinfo);
- ahd_unlock(ahd, &s);
-
- return (retval);
-}
-
-static void
-ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ)
-{
- u_int32_t status;
-
- status = aic_error_action(cmd, targ->inq_data,
- ahd_cmd_get_transaction_status(cmd),
- ahd_cmd_get_scsi_status(cmd));
-
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Entering ahd_linux_dv_transition, state= %d, "
- "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
- status, cmd->result);
- }
-#endif
-
- switch (targ->dv_state) {
- case AHD_DV_STATE_INQ_SHORT_ASYNC:
- case AHD_DV_STATE_INQ_ASYNC:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
- if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
+ switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
+ case AHD_DEV_Q_BASIC:
+ scsi_adjust_queue_depth(sdev,
+ MSG_SIMPLE_TASK,
+ dev->openings + dev->active);
break;
- case AHD_DV_STATE_INQ_ASYNC_VERIFY:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- u_int xportflags;
- u_int spi3data;
-
- if (memcmp(targ->inq_data, targ->dv_buffer,
- AHD_LINUX_DV_INQ_LEN) != 0) {
- /*
- * Inquiry data must have changed.
- * Try from the top again.
- */
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- }
-
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
- targ->flags |= AHD_INQ_VALID;
- if (ahd_linux_user_dv_setting(ahd) == 0)
- break;
-
- xportflags = targ->inq_data->flags;
- if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
- break;
-
- spi3data = targ->inq_data->spi3data;
- switch (spi3data & SID_SPI_CLOCK_DT_ST) {
- default:
- case SID_SPI_CLOCK_ST:
- /* Assume only basic DV is supported. */
- targ->flags |= AHD_BASIC_DV;
- break;
- case SID_SPI_CLOCK_DT:
- case SID_SPI_CLOCK_DT_ST:
- targ->flags |= AHD_ENHANCED_DV;
- break;
- }
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
-
- if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
- break;
- case AHD_DV_STATE_INQ_VERIFY:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
-
- if (memcmp(targ->inq_data, targ->dv_buffer,
- AHD_LINUX_DV_INQ_LEN) == 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- int i;
-
- ahd_print_devinfo(ahd, devinfo);
- printf("Inquiry buffer mismatch:");
- for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
- if ((i & 0xF) == 0)
- printf("\n ");
- printf("0x%x:0x0%x ",
- ((uint8_t *)targ->inq_data)[i],
- targ->dv_buffer[i]);
- }
- printf("\n");
- }
-#endif
-
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- } else if ((status & SS_ERRMASK) == EBUSY)
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- if (targ->dv_state_retry < 10)
- break;
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Failed DV inquiry, skipping\n");
- }
-#endif
- break;
- }
- break;
-
- case AHD_DV_STATE_TUR:
- switch (status & SS_MASK) {
- case SS_NOP:
- if ((targ->flags & AHD_BASIC_DV) != 0) {
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_VERIFY);
- } else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
- } else {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- }
- break;
- case SS_RETRY:
- case SS_TUR:
- if ((status & SS_ERRMASK) == EBUSY) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
- break;
- }
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- }
- if (targ->dv_state_retry >= 10) {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV TUR reties exhausted\n");
- }
-#endif
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- if (status & SSQ_DELAY)
- ssleep(1);
-
- break;
- case SS_START:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_REBD:
- switch (status & SS_MASK) {
- case SS_NOP:
- {
- uint32_t echo_size;
-
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
- echo_size = scsi_3btoul(&targ->dv_buffer[1]);
- echo_size &= 0x1FFF;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Echo buffer size= %d\n", echo_size);
- }
-#endif
- if (echo_size == 0) {
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-
- /* Generate the buffer pattern */
- targ->dv_echo_size = echo_size;
- ahd_linux_generate_dv_pattern(targ);
- /*
- * Setup initial negotiation values.
- */
- ahd_linux_filter_inquiry(ahd, devinfo);
- break;
- }
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ)
- targ->dv_state_retry--;
- if (targ->dv_state_retry <= 10)
- break;
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV REBD reties exhausted\n");
- }
-#endif
- /* FALLTHROUGH */
- case SS_FATAL:
- default:
- /*
- * Setup initial negotiation values
- * and try level 1 DV.
- */
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY);
- targ->dv_echo_size = 0;
- break;
- }
- break;
-
- case AHD_DV_STATE_WEB:
- switch (status & SS_MASK) {
- case SS_NOP:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- /*
- * Do not count "falling back"
- * against our retries.
- */
- targ->dv_state_retry = 0;
- }
- if (targ->dv_state_retry <= 10)
- break;
- /* FALLTHROUGH */
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV WEB reties exhausted\n");
- }
-#endif
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_REB:
- switch (status & SS_MASK) {
- case SS_NOP:
- if (memcmp(targ->dv_buffer, targ->dv_buffer1,
- targ->dv_echo_size) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0)
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- else
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_WEB);
- break;
- }
-
- if (targ->dv_buffer != NULL) {
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = NULL;
- }
- if (targ->dv_buffer1 != NULL) {
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = NULL;
- }
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if ((status & SSQ_FALLBACK) != 0) {
- if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_EXIT);
- break;
- }
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
- }
- if (targ->dv_state_retry <= 10) {
- if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
- msleep(ahd->our_id*1000/10);
- break;
- }
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV REB reties exhausted\n");
- }
-#endif
- /* FALLTHROUGH */
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_SU:
- switch (status & SS_MASK) {
- case SS_NOP:
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
- break;
-
- case AHD_DV_STATE_BUSY:
- switch (status & SS_MASK) {
- case SS_NOP:
- case SS_INQ_REFRESH:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_SHORT_ASYNC);
- break;
- case SS_TUR:
- case SS_RETRY:
- AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
- if (ahd_cmd_get_transaction_status(cmd)
- == CAM_REQUEUE_REQ) {
- targ->dv_state_retry--;
- } else if (targ->dv_state_retry < 60) {
- if ((status & SSQ_DELAY) != 0)
- ssleep(1);
- } else {
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("DV BUSY reties exhausted\n");
- }
-#endif
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- }
- break;
- default:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
+ case AHD_DEV_Q_TAGGED:
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TASK,
+ dev->openings + dev->active);
break;
-
default:
- printf("%s: Invalid DV completion state %d\n", ahd_name(ahd),
- targ->dv_state);
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
- break;
- }
-}
-
-static void
-ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo)
-{
- memset(cmd, 0, sizeof(struct scsi_cmnd));
- cmd->device = ahd->platform_data->dv_scsi_dev;
- cmd->scsi_done = ahd_linux_dv_complete;
-}
-
-/*
- * Synthesize an inquiry command. On the return trip, it'll be
- * sniffed and the device transfer settings set for us.
- */
-static void
-ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ,
- u_int request_length)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending INQ\n");
- }
-#endif
- if (targ->inq_data == NULL)
- targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN,
- M_DEVBUF, M_WAITOK);
- if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) {
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN,
- M_DEVBUF, M_WAITOK);
- }
-
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = INQUIRY;
- cmd->cmnd[4] = request_length;
- cmd->request_bufflen = request_length;
- if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC)
- cmd->request_buffer = targ->dv_buffer;
- else
- cmd->request_buffer = targ->inq_data;
- memset(cmd->request_buffer, 0, AHD_LINUX_DV_INQ_LEN);
-}
-
-static void
-ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending TUR\n");
- }
-#endif
- /* Do a TUR to clear out any non-fatal transitional state */
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_NONE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = TEST_UNIT_READY;
-}
-
-#define AHD_REBD_LEN 4
-
-static void
-ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending REBD\n");
- }
-#endif
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(AHD_REBD_LEN, M_DEVBUF, M_WAITOK);
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = READ_BUFFER;
- cmd->cmnd[1] = 0x0b;
- scsi_ulto3b(AHD_REBD_LEN, &cmd->cmnd[6]);
- cmd->request_bufflen = AHD_REBD_LEN;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer;
-}
-
-static void
-ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending WEB\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_TO_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = WRITE_BUFFER;
- cmd->cmnd[1] = 0x0a;
- scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
- cmd->request_bufflen = targ->dv_echo_size;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer;
-}
-
-static void
-ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
-{
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending REB\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_FROM_DEVICE;
- cmd->cmd_len = 10;
- cmd->cmnd[0] = READ_BUFFER;
- cmd->cmnd[1] = 0x0a;
- scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
- cmd->request_bufflen = targ->dv_echo_size;
- cmd->underflow = cmd->request_bufflen;
- cmd->request_buffer = targ->dv_buffer1;
-}
-
-static void
-ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ)
-{
- u_int le;
-
- le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Sending SU\n");
- }
-#endif
- ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
- cmd->sc_data_direction = DMA_NONE;
- cmd->cmd_len = 6;
- cmd->cmnd[0] = START_STOP_UNIT;
- cmd->cmnd[4] = le | SSS_START;
-}
-
-static int
-ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
- struct ahd_linux_target *targ;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_transinfo *goal;
- struct ahd_tmode_tstate *tstate;
- u_int width;
- u_int period;
- u_int offset;
- u_int ppr_options;
- u_int cur_speed;
- u_int wide_speed;
- u_int narrow_speed;
- u_int fallback_speed;
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- ahd_print_devinfo(ahd, devinfo);
- printf("Trying to fallback\n");
- }
-#endif
- targ = ahd->platform_data->targets[devinfo->target_offset];
- tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
- devinfo->our_scsiid,
- devinfo->target, &tstate);
- goal = &tinfo->goal;
- width = goal->width;
- period = goal->period;
- offset = goal->offset;
- ppr_options = goal->ppr_options;
- if (offset == 0)
- period = AHD_ASYNC_XFER_PERIOD;
- if (targ->dv_next_narrow_period == 0)
- targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
- if (targ->dv_next_wide_period == 0)
- targ->dv_next_wide_period = period;
- if (targ->dv_max_width == 0)
- targ->dv_max_width = width;
- if (targ->dv_max_ppr_options == 0)
- targ->dv_max_ppr_options = ppr_options;
- if (targ->dv_last_ppr_options == 0)
- targ->dv_last_ppr_options = ppr_options;
-
- cur_speed = aic_calc_speed(width, period, offset, AHD_SYNCRATE_MIN);
- wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
- targ->dv_next_wide_period,
- MAX_OFFSET, AHD_SYNCRATE_MIN);
- narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
- targ->dv_next_narrow_period,
- MAX_OFFSET, AHD_SYNCRATE_MIN);
- fallback_speed = aic_calc_speed(width, period+1, offset,
- AHD_SYNCRATE_MIN);
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
- "fallback_speed= %d\n", cur_speed, wide_speed,
- narrow_speed, fallback_speed);
- }
-#endif
-
- if (cur_speed > 160000) {
- /*
- * Paced/DT/IU_REQ only transfer speeds. All we
- * can do is fallback in terms of syncrate.
- */
- period++;
- } else if (cur_speed > 80000) {
- if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- /*
- * Try without IU_REQ as it may be confusing
- * an expander.
- */
- ppr_options &= ~MSG_EXT_PPR_IU_REQ;
- } else {
- /*
- * Paced/DT only transfer speeds. All we
- * can do is fallback in terms of syncrate.
- */
- period++;
- ppr_options = targ->dv_max_ppr_options;
- }
- } else if (cur_speed > 3300) {
-
/*
- * In this range we the following
- * options ordered from highest to
- * lowest desireability:
- *
- * o Wide/DT
- * o Wide/non-DT
- * o Narrow at a potentally higher sync rate.
- *
- * All modes are tested with and without IU_REQ
- * set since using IUs may confuse an expander.
+ * We allow the OS to queue 2 untagged transactions to
+ * us at any time even though we can only execute them
+ * serially on the controller/device. This should
+ * remove some latency.
*/
- if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
-
- ppr_options &= ~MSG_EXT_PPR_IU_REQ;
- } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
- /*
- * Try going non-DT.
- */
- ppr_options = targ->dv_max_ppr_options;
- ppr_options &= ~MSG_EXT_PPR_DT_REQ;
- } else if (targ->dv_last_ppr_options != 0) {
- /*
- * Try without QAS or any other PPR options.
- * We may need a non-PPR message to work with
- * an expander. We look at the "last PPR options"
- * so we will perform this fallback even if the
- * target responded to our PPR negotiation with
- * no option bits set.
- */
- ppr_options = 0;
- } else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
- /*
- * If the next narrow speed is greater than
- * the next wide speed, fallback to narrow.
- * Otherwise fallback to the next DT/Wide setting.
- * The narrow async speed will always be smaller
- * than the wide async speed, so handle this case
- * specifically.
- */
- ppr_options = targ->dv_max_ppr_options;
- if (narrow_speed > fallback_speed
- || period >= AHD_ASYNC_XFER_PERIOD) {
- targ->dv_next_wide_period = period+1;
- width = MSG_EXT_WDTR_BUS_8_BIT;
- period = targ->dv_next_narrow_period;
- } else {
- period++;
- }
- } else if ((ahd->features & AHD_WIDE) != 0
- && targ->dv_max_width != 0
- && wide_speed >= fallback_speed
- && (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
- || period >= AHD_ASYNC_XFER_PERIOD)) {
-
- /*
- * We are narrow. Try falling back
- * to the next wide speed with
- * all supported ppr options set.
- */
- targ->dv_next_narrow_period = period+1;
- width = MSG_EXT_WDTR_BUS_16_BIT;
- period = targ->dv_next_wide_period;
- ppr_options = targ->dv_max_ppr_options;
- } else {
- /* Only narrow fallback is allowed. */
- period++;
- ppr_options = targ->dv_max_ppr_options;
- }
- } else {
- return (-1);
- }
- offset = MAX_OFFSET;
- ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_PACED);
- ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, FALSE);
- if (period == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
- if (width == MSG_EXT_WDTR_BUS_8_BIT)
- targ->dv_next_narrow_period = AHD_ASYNC_XFER_PERIOD;
- else
- targ->dv_next_wide_period = AHD_ASYNC_XFER_PERIOD;
+ scsi_adjust_queue_depth(sdev,
+ /*NON-TAGGED*/0,
+ /*queue depth*/2);
+ break;
}
- ahd_set_syncrate(ahd, devinfo, period, offset,
- ppr_options, AHD_TRANS_GOAL, FALSE);
- targ->dv_last_ppr_options = ppr_options;
- return (0);
}
-static void
-ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
-{
- struct ahd_softc *ahd;
- struct scb *scb;
- u_long flags;
-
- ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
- ahd_lock(ahd, &flags);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV) {
- printf("%s: Timeout while doing DV command %x.\n",
- ahd_name(ahd), cmd->cmnd[0]);
- ahd_dump_card_state(ahd);
- }
-#endif
-
- /*
- * Guard against "done race". No action is
- * required if we just completed.
- */
- if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
- ahd_unlock(ahd, &flags);
- return;
- }
-
- /*
- * Command has not completed. Mark this
- * SCB as having failing status prior to
- * resetting the bus, so we get the correct
- * error code.
- */
- if ((scb->flags & SCB_SENSE) != 0)
- ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
- else
- ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);
-
- /*
- * Add a minimal bus settle delay for devices that are slow to
- * respond after bus resets.
- */
- ahd_freeze_simq(ahd);
- init_timer(&ahd->platform_data->reset_timer);
- ahd->platform_data->reset_timer.data = (u_long)ahd;
- ahd->platform_data->reset_timer.expires = jiffies + HZ / 2;
- ahd->platform_data->reset_timer.function =
- (ahd_linux_callback_t *)ahd_release_simq;
- add_timer(&ahd->platform_data->reset_timer);
- if (ahd_linux_next_device_to_run(ahd) != NULL)
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
- ahd_unlock(ahd, &flags);
-}
-
-static void
-ahd_linux_dv_complete(struct scsi_cmnd *cmd)
-{
- struct ahd_softc *ahd;
-
- ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
-
- /* Delete the DV timer before it goes off! */
- scsi_delete_timer(cmd);
-
-#ifdef AHD_DEBUG
- if (ahd_debug & AHD_SHOW_DV)
- printf("%s:%c:%d: Command completed, status= 0x%x\n",
- ahd_name(ahd), cmd->device->channel, cmd->device->id,
- cmd->result);
-#endif
-
- /* Wake up the state machine */
- up(&ahd->platform_data->dv_cmd_sem);
-}
-
-static void
-ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ)
+int
+ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
+ int lun, u_int tag, role_t role, uint32_t status)
{
- uint16_t b;
- u_int i;
- u_int j;
-
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
- if (targ->dv_buffer1 != NULL)
- free(targ->dv_buffer1, M_DEVBUF);
- targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
-
- i = 0;
-
- b = 0x0001;
- for (j = 0 ; i < targ->dv_echo_size; j++) {
- if (j < 32) {
- /*
- * 32bytes of sequential numbers.
- */
- targ->dv_buffer[i++] = j & 0xff;
- } else if (j < 48) {
- /*
- * 32bytes of repeating 0x0000, 0xffff.
- */
- targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00;
- } else if (j < 64) {
- /*
- * 32bytes of repeating 0x5555, 0xaaaa.
- */
- targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55;
- } else {
- /*
- * Remaining buffer is filled with a repeating
- * patter of:
- *
- * 0xffff
- * ~0x0001 << shifted once in each loop.
- */
- if (j & 0x02) {
- if (j & 0x01) {
- targ->dv_buffer[i++] = ~(b >> 8) & 0xff;
- b <<= 1;
- if (b == 0x0000)
- b = 0x0001;
- } else {
- targ->dv_buffer[i++] = (~b & 0xff);
- }
- } else {
- targ->dv_buffer[i++] = 0xff;
- }
- }
- }
+ return 0;
}
static u_int
@@ -3800,100 +1393,23 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
return (tags);
}
-static u_int
-ahd_linux_user_dv_setting(struct ahd_softc *ahd)
-{
- static int warned_user;
- int dv;
-
- if (ahd->unit >= NUM_ELEMENTS(aic79xx_dv_settings)) {
-
- if (warned_user == 0) {
- printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient dv settings instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_dv_settings array in"
-"aic79xx: the aic79xx_osm.c source file.\n");
- warned_user++;
- }
- dv = -1;
- } else {
-
- dv = aic79xx_dv_settings[ahd->unit];
- }
-
- if (dv < 0) {
- /*
- * Apply the default.
- */
- dv = 1;
- if (ahd->seep_config != 0)
- dv = (ahd->seep_config->bios_control & CFENABLEDV);
- }
- return (dv);
-}
-
-static void
-ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd)
-{
- static int warned_user;
- u_int rd_strm_mask;
- u_int target_id;
-
- /*
- * If we have specific read streaming info for this controller,
- * apply it. Otherwise use the defaults.
- */
- if (ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) {
-
- if (warned_user == 0) {
-
- printf(KERN_WARNING
-"aic79xx: WARNING: Insufficient rd_strm instances\n"
-"aic79xx: for installed controllers. Using defaults\n"
-"aic79xx: Please update the aic79xx_rd_strm_info array\n"
-"aic79xx: in the aic79xx_osm.c source file.\n");
- warned_user++;
- }
- rd_strm_mask = AIC79XX_CONFIGED_RD_STRM;
- } else {
-
- rd_strm_mask = aic79xx_rd_strm_info[ahd->unit];
- }
- for (target_id = 0; target_id < 16; target_id++) {
- struct ahd_devinfo devinfo;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
-
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- target_id, &tstate);
- ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
- CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
- tinfo->user.ppr_options &= ~MSG_EXT_PPR_RD_STRM;
- if ((rd_strm_mask & devinfo.target_mask) != 0)
- tinfo->user.ppr_options |= MSG_EXT_PPR_RD_STRM;
- }
-}
-
/*
* Determines the queue depth for a given device.
*/
static void
-ahd_linux_device_queue_depth(struct ahd_softc *ahd,
- struct ahd_linux_device *dev)
+ahd_linux_device_queue_depth(struct scsi_device *sdev)
{
struct ahd_devinfo devinfo;
u_int tags;
+ struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
ahd_compile_devinfo(&devinfo,
ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
tags = ahd_linux_user_tagdepth(ahd, &devinfo);
- if (tags != 0
- && dev->scsi_device != NULL
- && dev->scsi_device->tagged_supported != 0) {
+ if (tags != 0 && sdev->tagged_supported != 0) {
ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
ahd_print_devinfo(ahd, &devinfo);
@@ -3903,11 +1419,10 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd,
}
}
-static void
-ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
+static int
+ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ struct scsi_cmnd *cmd)
{
- struct ahd_cmd *acmd;
- struct scsi_cmnd *cmd;
struct scb *scb;
struct hardware_scb *hscb;
struct ahd_initiator_tinfo *tinfo;
@@ -3915,157 +1430,122 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
u_int col_idx;
uint16_t mask;
- if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0)
- panic("running device on run list");
-
- while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
- && dev->openings > 0 && dev->qfrozen == 0) {
-
- /*
- * Schedule us to run later. The only reason we are not
- * running is because the whole controller Q is frozen.
- */
- if (ahd->platform_data->qfrozen != 0
- && AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
- dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- return;
- }
-
- cmd = &acmd_scsi_cmd(acmd);
+ /*
+ * Get an scb to use.
+ */
+ tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
+ cmd->device->id, &tstate);
+ if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
+ || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
+ col_idx = AHD_NEVER_COL_IDX;
+ } else {
+ col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
+ cmd->device->lun);
+ }
+ if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
+ ahd->flags |= AHD_RESOURCE_SHORTAGE;
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
- /*
- * Get an scb to use.
- */
- tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
- cmd->device->id, &tstate);
- if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
- || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
- col_idx = AHD_NEVER_COL_IDX;
- } else {
- col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
- cmd->device->lun);
- }
- if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
- dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- ahd->flags |= AHD_RESOURCE_SHORTAGE;
- return;
- }
- TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
- scb->io_ctx = cmd;
- scb->platform_data->dev = dev;
- hscb = scb->hscb;
- cmd->host_scribble = (char *)scb;
+ scb->io_ctx = cmd;
+ scb->platform_data->dev = dev;
+ hscb = scb->hscb;
+ cmd->host_scribble = (char *)scb;
- /*
- * Fill out basics of the HSCB.
- */
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahd, cmd);
- hscb->lun = cmd->device->lun;
- scb->hscb->task_management = 0;
- mask = SCB_GET_TARGET_MASK(ahd, scb);
+ /*
+ * Fill out basics of the HSCB.
+ */
+ hscb->control = 0;
+ hscb->scsiid = BUILD_SCSIID(ahd, cmd);
+ hscb->lun = cmd->device->lun;
+ scb->hscb->task_management = 0;
+ mask = SCB_GET_TARGET_MASK(ahd, scb);
- if ((ahd->user_discenable & mask) != 0)
- hscb->control |= DISCENB;
+ if ((ahd->user_discenable & mask) != 0)
+ hscb->control |= DISCENB;
- if (AHD_DV_CMD(cmd) != 0)
- scb->flags |= SCB_SILENT;
+ if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
+ scb->flags |= SCB_PACKETIZED;
- if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
- scb->flags |= SCB_PACKETIZED;
+ if ((tstate->auto_negotiate & mask) != 0) {
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
+ }
- if ((tstate->auto_negotiate & mask) != 0) {
- scb->flags |= SCB_AUTO_NEGOTIATE;
- scb->hscb->control |= MK_MESSAGE;
- }
+ if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
+ int msg_bytes;
+ uint8_t tag_msgs[2];
- if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- int msg_bytes;
- uint8_t tag_msgs[2];
-
- msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
- if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
- hscb->control |= tag_msgs[0];
- if (tag_msgs[0] == MSG_ORDERED_TASK)
- dev->commands_since_idle_or_otag = 0;
- } else
-#endif
- if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
- && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
- hscb->control |= MSG_ORDERED_TASK;
+ msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
+ if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
+ hscb->control |= tag_msgs[0];
+ if (tag_msgs[0] == MSG_ORDERED_TASK)
dev->commands_since_idle_or_otag = 0;
- } else {
- hscb->control |= MSG_SIMPLE_TASK;
- }
+ } else
+ if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
+ && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
+ hscb->control |= MSG_ORDERED_TASK;
+ dev->commands_since_idle_or_otag = 0;
+ } else {
+ hscb->control |= MSG_SIMPLE_TASK;
}
+ }
- hscb->cdb_len = cmd->cmd_len;
- memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
-
- scb->sg_count = 0;
- ahd_set_residual(scb, 0);
- ahd_set_sense_residual(scb, 0);
- if (cmd->use_sg != 0) {
- void *sg;
- struct scatterlist *cur_seg;
- u_int nseg;
- int dir;
-
- cur_seg = (struct scatterlist *)cmd->request_buffer;
- dir = cmd->sc_data_direction;
- nseg = pci_map_sg(ahd->dev_softc, cur_seg,
- cmd->use_sg, dir);
- scb->platform_data->xfer_len = 0;
- for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
- dma_addr_t addr;
- bus_size_t len;
-
- addr = sg_dma_address(cur_seg);
- len = sg_dma_len(cur_seg);
- scb->platform_data->xfer_len += len;
- sg = ahd_sg_setup(ahd, scb, sg, addr, len,
- /*last*/nseg == 1);
- }
- } else if (cmd->request_bufflen != 0) {
- void *sg;
+ hscb->cdb_len = cmd->cmd_len;
+ memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
+
+ scb->platform_data->xfer_len = 0;
+ ahd_set_residual(scb, 0);
+ ahd_set_sense_residual(scb, 0);
+ scb->sg_count = 0;
+ if (cmd->use_sg != 0) {
+ void *sg;
+ struct scatterlist *cur_seg;
+ u_int nseg;
+ int dir;
+
+ cur_seg = (struct scatterlist *)cmd->request_buffer;
+ dir = cmd->sc_data_direction;
+ nseg = pci_map_sg(ahd->dev_softc, cur_seg,
+ cmd->use_sg, dir);
+ scb->platform_data->xfer_len = 0;
+ for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
dma_addr_t addr;
- int dir;
-
- sg = scb->sg_list;
- dir = cmd->sc_data_direction;
- addr = pci_map_single(ahd->dev_softc,
- cmd->request_buffer,
- cmd->request_bufflen, dir);
- scb->platform_data->xfer_len = cmd->request_bufflen;
- scb->platform_data->buf_busaddr = addr;
- sg = ahd_sg_setup(ahd, scb, sg, addr,
- cmd->request_bufflen, /*last*/TRUE);
- }
+ bus_size_t len;
- LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
- dev->openings--;
- dev->active++;
- dev->commands_issued++;
-
- /* Update the error counting bucket and dump if needed */
- if (dev->target->cmds_since_error) {
- dev->target->cmds_since_error++;
- if (dev->target->cmds_since_error >
- AHD_LINUX_ERR_THRESH)
- dev->target->cmds_since_error = 0;
+ addr = sg_dma_address(cur_seg);
+ len = sg_dma_len(cur_seg);
+ scb->platform_data->xfer_len += len;
+ sg = ahd_sg_setup(ahd, scb, sg, addr, len,
+ /*last*/nseg == 1);
}
+ } else if (cmd->request_bufflen != 0) {
+ void *sg;
+ dma_addr_t addr;
+ int dir;
- if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
- dev->commands_since_idle_or_otag++;
- scb->flags |= SCB_ACTIVE;
- ahd_queue_scb(ahd, scb);
+ sg = scb->sg_list;
+ dir = cmd->sc_data_direction;
+ addr = pci_map_single(ahd->dev_softc,
+ cmd->request_buffer,
+ cmd->request_bufflen, dir);
+ scb->platform_data->xfer_len = cmd->request_bufflen;
+ scb->platform_data->buf_busaddr = addr;
+ sg = ahd_sg_setup(ahd, scb, sg, addr,
+ cmd->request_bufflen, /*last*/TRUE);
}
+
+ LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
+ dev->openings--;
+ dev->active++;
+ dev->commands_issued++;
+
+ if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
+ dev->commands_since_idle_or_otag++;
+ scb->flags |= SCB_ACTIVE;
+ ahd_queue_scb(ahd, scb);
+
+ return 0;
}
/*
@@ -4081,9 +1561,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
ahd = (struct ahd_softc *) dev_id;
ahd_lock(ahd, &flags);
ours = ahd_intr(ahd);
- if (ahd_linux_next_device_to_run(ahd) != NULL)
- ahd_schedule_runq(ahd);
- ahd_linux_run_complete_queue(ahd);
ahd_unlock(ahd, &flags);
return IRQ_RETVAL(ours);
}
@@ -4092,111 +1569,6 @@ void
ahd_platform_flushwork(struct ahd_softc *ahd)
{
- while (ahd_linux_run_complete_queue(ahd) != NULL)
- ;
-}
-
-static struct ahd_linux_target*
-ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
-{
- struct ahd_linux_target *targ;
-
- targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
- if (targ == NULL)
- return (NULL);
- memset(targ, 0, sizeof(*targ));
- targ->channel = channel;
- targ->target = target;
- targ->ahd = ahd;
- targ->flags = AHD_DV_REQUIRED;
- ahd->platform_data->targets[target] = targ;
- return (targ);
-}
-
-static void
-ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ)
-{
- struct ahd_devinfo devinfo;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_tmode_tstate *tstate;
- u_int our_id;
- u_int target_offset;
- char channel;
-
- /*
- * Force a negotiation to async/narrow on any
- * future command to this device unless a bus
- * reset occurs between now and that command.
- */
- channel = 'A' + targ->channel;
- our_id = ahd->our_id;
- target_offset = targ->target;
- tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
- targ->target, &tstate);
- ahd_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
- channel, ROLE_INITIATOR);
- ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS);
- ahd->platform_data->targets[target_offset] = NULL;
- if (targ->inq_data != NULL)
- free(targ->inq_data, M_DEVBUF);
- if (targ->dv_buffer != NULL)
- free(targ->dv_buffer, M_DEVBUF);
- if (targ->dv_buffer1 != NULL)
- free(targ->dv_buffer1, M_DEVBUF);
- free(targ, M_DEVBUF);
-}
-
-static struct ahd_linux_device*
-ahd_linux_alloc_device(struct ahd_softc *ahd,
- struct ahd_linux_target *targ, u_int lun)
-{
- struct ahd_linux_device *dev;
-
- dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
- if (dev == NULL)
- return (NULL);
- memset(dev, 0, sizeof(*dev));
- init_timer(&dev->timer);
- TAILQ_INIT(&dev->busyq);
- dev->flags = AHD_DEV_UNCONFIGURED;
- dev->lun = lun;
- dev->target = targ;
-
- /*
- * We start out life using untagged
- * transactions of which we allow one.
- */
- dev->openings = 1;
-
- /*
- * Set maxtags to 0. This will be changed if we
- * later determine that we are dealing with
- * a tagged queuing capable device.
- */
- dev->maxtags = 0;
-
- targ->refcount++;
- targ->devices[lun] = dev;
- return (dev);
-}
-
-static void
-ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev)
-{
- struct ahd_linux_target *targ;
-
- del_timer(&dev->timer);
- targ = dev->target;
- targ->devices[dev->lun] = NULL;
- free(dev, M_DEVBUF);
- targ->refcount--;
- if (targ->refcount == 0
- && (targ->flags & AHD_DV_REQUIRED) == 0)
- ahd_linux_free_target(ahd, targ);
}
void
@@ -4207,10 +1579,14 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
case AC_TRANSFER_NEG:
{
char buf[80];
+ struct scsi_target *starget;
struct ahd_linux_target *targ;
struct info_str info;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
+ unsigned int target_ppr_options;
+
+ BUG_ON(target == CAM_TARGET_WILDCARD);
info.buffer = buf;
info.length = sizeof(buf);
@@ -4234,58 +1610,47 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
* Don't bother reporting results that
* are identical to those last reported.
*/
- targ = ahd->platform_data->targets[target];
- if (targ == NULL)
+ starget = ahd->platform_data->starget[target];
+ if (starget == NULL)
break;
- if (tinfo->curr.period == targ->last_tinfo.period
- && tinfo->curr.width == targ->last_tinfo.width
- && tinfo->curr.offset == targ->last_tinfo.offset
- && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
+ targ = scsi_transport_target_data(starget);
+
+ target_ppr_options =
+ (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
+ + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
+ + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0)
+ + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
+ + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
+ + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
+ + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
+ + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
+
+ if (tinfo->curr.period == spi_period(starget)
+ && tinfo->curr.width == spi_width(starget)
+ && tinfo->curr.offset == spi_offset(starget)
+ && tinfo->curr.ppr_options == target_ppr_options)
if (bootverbose == 0)
break;
- targ->last_tinfo.period = tinfo->curr.period;
- targ->last_tinfo.width = tinfo->curr.width;
- targ->last_tinfo.offset = tinfo->curr.offset;
- targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
-
- printf("(%s:%c:", ahd_name(ahd), channel);
- if (target == CAM_TARGET_WILDCARD)
- printf("*): ");
- else
- printf("%d): ", target);
- ahd_format_transinfo(&info, &tinfo->curr);
- if (info.pos < info.length)
- *info.buffer = '\0';
- else
- buf[info.length - 1] = '\0';
- printf("%s", buf);
+ spi_period(starget) = tinfo->curr.period;
+ spi_width(starget) = tinfo->curr.width;
+ spi_offset(starget) = tinfo->curr.offset;
+ spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+ spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+ spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
+ spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
+ spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
+ spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0;
+ spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
+ spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
+ spi_display_xfer_agreement(starget);
break;
}
case AC_SENT_BDR:
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahd->platform_data->host,
channel - 'A', target);
-#else
- Scsi_Device *scsi_dev;
-
- /*
- * Find the SCSI device associated with this
- * request and indicate that a UA is expected.
- */
- for (scsi_dev = ahd->platform_data->host->host_queue;
- scsi_dev != NULL; scsi_dev = scsi_dev->next) {
- if (channel - 'A' == scsi_dev->channel
- && target == scsi_dev->id
- && (lun == CAM_LUN_WILDCARD
- || lun == scsi_dev->lun)) {
- scsi_dev->was_reset = 1;
- scsi_dev->expecting_cc_ua = 1;
- }
- }
-#endif
break;
}
case AC_BUS_RESET:
@@ -4305,7 +1670,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
void
ahd_done(struct ahd_softc *ahd, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
struct ahd_linux_device *dev;
if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -4373,19 +1738,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
ahd_set_transaction_status(scb, CAM_REQ_CMP);
}
} else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
- ahd_linux_handle_scsi_status(ahd, dev, scb);
- } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- if (AHD_DV_CMD(cmd) == FALSE)
- dev->target->flags &= ~AHD_DV_REQUIRED;
+ ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
}
- /*
- * Start DV for devices that require it assuming the first command
- * sent does not result in a selection timeout.
- */
- if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT
- && (dev->target->flags & AHD_DV_REQUIRED) != 0)
- ahd_linux_start_dv(ahd);
if (dev->openings == 1
&& ahd_get_transaction_status(scb) == CAM_REQ_CMP
@@ -4406,47 +1760,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if (dev->active == 0)
dev->commands_since_idle_or_otag = 0;
- if (TAILQ_EMPTY(&dev->busyq)) {
- if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
- && dev->active == 0
- && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
- ahd_linux_free_device(ahd, dev);
- } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
- dev->flags |= AHD_DEV_ON_RUN_LIST;
- }
-
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
printf("Recovery SCB completes\n");
if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
|| ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
- scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+ if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+ ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
up(&ahd->platform_data->eh_sem);
}
}
ahd_free_scb(ahd, scb);
ahd_linux_queue_cmd_complete(ahd, cmd);
-
- if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0
- && LIST_FIRST(&ahd->pending_scbs) == NULL) {
- ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY;
- up(&ahd->platform_data->dv_sem);
- }
}
static void
ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
- struct ahd_linux_device *dev, struct scb *scb)
+ struct scsi_device *sdev, struct scb *scb)
{
struct ahd_devinfo devinfo;
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
ahd_compile_devinfo(&devinfo,
ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
/*
@@ -4465,7 +1804,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
case SCSI_STATUS_CHECK_COND:
case SCSI_STATUS_CMD_TERMINATED:
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
/*
* Copy sense information to the OS's cmd
@@ -4518,7 +1857,6 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
break;
}
case SCSI_STATUS_QUEUE_FULL:
- {
/*
* By the time the core driver has returned this
* command, all other commands that were queued
@@ -4579,98 +1917,23 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
(dev->flags & AHD_DEV_Q_BASIC)
? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
- /* FALLTHROUGH */
- }
- case SCSI_STATUS_BUSY:
- /*
- * Set a short timer to defer sending commands for
- * a bit since Linux will not delay in this case.
- */
- if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) {
- printf("%s:%c:%d: Device Timer still active during "
- "busy processing\n", ahd_name(ahd),
- dev->target->channel, dev->target->target);
- break;
- }
- dev->flags |= AHD_DEV_TIMER_ACTIVE;
- dev->qfrozen++;
- init_timer(&dev->timer);
- dev->timer.data = (u_long)dev;
- dev->timer.expires = jiffies + (HZ/2);
- dev->timer.function = ahd_linux_dev_timed_unfreeze;
- add_timer(&dev->timer);
- break;
}
}
static void
-ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd)
+ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
{
/*
- * Typically, the complete queue has very few entries
- * queued to it before the queue is emptied by
- * ahd_linux_run_complete_queue, so sorting the entries
- * by generation number should be inexpensive.
- * We perform the sort so that commands that complete
- * with an error are retuned in the order origionally
- * queued to the controller so that any subsequent retries
- * are performed in order. The underlying ahd routines do
- * not guarantee the order that aborted commands will be
- * returned to us.
- */
- struct ahd_completeq *completeq;
- struct ahd_cmd *list_cmd;
- struct ahd_cmd *acmd;
-
- /*
* Map CAM error codes into Linux Error codes. We
* avoid the conversion so that the DV code has the
* full error information available when making
* state change decisions.
*/
- if (AHD_DV_CMD(cmd) == FALSE) {
+ {
uint32_t status;
u_int new_status;
status = ahd_cmd_get_transaction_status(cmd);
- if (status != CAM_REQ_CMP) {
- struct ahd_linux_device *dev;
- struct ahd_devinfo devinfo;
- cam_status cam_status;
- uint32_t action;
- u_int scsi_status;
-
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id,
- cmd->device->lun,
- /*alloc*/FALSE);
-
- if (dev == NULL)
- goto no_fallback;
-
- ahd_compile_devinfo(&devinfo,
- ahd->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A':'B',
- ROLE_INITIATOR);
-
- scsi_status = ahd_cmd_get_scsi_status(cmd);
- cam_status = ahd_cmd_get_transaction_status(cmd);
- action = aic_error_action(cmd, dev->target->inq_data,
- cam_status, scsi_status);
- if ((action & SSQ_FALLBACK) != 0) {
-
- /* Update stats */
- dev->target->errors_detected++;
- if (dev->target->cmds_since_error == 0)
- dev->target->cmds_since_error++;
- else {
- dev->target->cmds_since_error = 0;
- ahd_linux_fallback(ahd, &devinfo);
- }
- }
- }
-no_fallback:
switch (status) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
@@ -4715,26 +1978,7 @@ no_fallback:
new_status = DID_ERROR;
break;
case CAM_REQUEUE_REQ:
- /*
- * If we want the request requeued, make sure there
- * are sufficent retries. In the old scsi error code,
- * we used to be able to specify a result code that
- * bypassed the retry count. Now we must use this
- * hack. We also "fake" a check condition with
- * a sense code of ABORTED COMMAND. This seems to
- * evoke a retry even if this command is being sent
- * via the eh thread. Ick! Ick! Ick!
- */
- if (cmd->retries > 0)
- cmd->retries--;
- new_status = DID_OK;
- ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
- cmd->result |= (DRIVER_SENSE << 24);
- memset(cmd->sense_buffer, 0,
- sizeof(cmd->sense_buffer));
- cmd->sense_buffer[0] = SSD_ERRCODE_VALID
- | SSD_CURRENT_ERROR;
- cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
+ new_status = DID_REQUEUE;
break;
default:
/* We should never get here */
@@ -4745,116 +1989,23 @@ no_fallback:
ahd_cmd_set_transaction_status(cmd, new_status);
}
- completeq = &ahd->platform_data->completeq;
- list_cmd = TAILQ_FIRST(completeq);
- acmd = (struct ahd_cmd *)cmd;
- while (list_cmd != NULL
- && acmd_scsi_cmd(list_cmd).serial_number
- < acmd_scsi_cmd(acmd).serial_number)
- list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
- if (list_cmd != NULL)
- TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
- else
- TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
+ cmd->scsi_done(cmd);
}
static void
-ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+ahd_linux_sem_timeout(u_long arg)
{
- struct scsi_inquiry_data *sid;
- struct ahd_initiator_tinfo *tinfo;
- struct ahd_transinfo *user;
- struct ahd_transinfo *goal;
- struct ahd_transinfo *curr;
- struct ahd_tmode_tstate *tstate;
- struct ahd_linux_device *dev;
- u_int width;
- u_int period;
- u_int offset;
- u_int ppr_options;
- u_int trans_version;
- u_int prot_version;
-
- /*
- * Determine if this lun actually exists. If so,
- * hold on to its corresponding device structure.
- * If not, make sure we release the device and
- * don't bother processing the rest of this inquiry
- * command.
- */
- dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
- devinfo->target, devinfo->lun,
- /*alloc*/TRUE);
-
- sid = (struct scsi_inquiry_data *)dev->target->inq_data;
- if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
-
- dev->flags &= ~AHD_DEV_UNCONFIGURED;
- } else {
- dev->flags |= AHD_DEV_UNCONFIGURED;
- return;
- }
+ struct ahd_softc *ahd;
+ u_long s;
- /*
- * Update our notion of this device's transfer
- * negotiation capabilities.
- */
- tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
- devinfo->our_scsiid,
- devinfo->target, &tstate);
- user = &tinfo->user;
- goal = &tinfo->goal;
- curr = &tinfo->curr;
- width = user->width;
- period = user->period;
- offset = user->offset;
- ppr_options = user->ppr_options;
- trans_version = user->transport_version;
- prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid));
+ ahd = (struct ahd_softc *)arg;
- /*
- * Only attempt SPI3/4 once we've verified that
- * the device claims to support SPI3/4 features.
- */
- if (prot_version < SCSI_REV_2)
- trans_version = SID_ANSI_REV(sid);
- else
- trans_version = SCSI_REV_2;
-
- if ((sid->flags & SID_WBus16) == 0)
- width = MSG_EXT_WDTR_BUS_8_BIT;
- if ((sid->flags & SID_Sync) == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
- }
- if ((sid->spi3data & SID_SPI_QAS) == 0)
- ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
- if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
- ppr_options &= MSG_EXT_PPR_QAS_REQ;
- if ((sid->spi3data & SID_SPI_IUS) == 0)
- ppr_options &= (MSG_EXT_PPR_DT_REQ
- | MSG_EXT_PPR_QAS_REQ);
-
- if (prot_version > SCSI_REV_2
- && ppr_options != 0)
- trans_version = user->transport_version;
-
- ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN);
- ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
- ahd_validate_offset(ahd, /*tinfo limit*/NULL, period,
- &offset, width, ROLE_UNKNOWN);
- if (offset == 0 || period == 0) {
- period = 0;
- offset = 0;
- ppr_options = 0;
+ ahd_lock(ahd, &s);
+ if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
+ ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+ up(&ahd->platform_data->eh_sem);
}
- /* Apply our filtered user settings. */
- curr->transport_version = trans_version;
- curr->protocol_version = prot_version;
- ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, /*paused*/FALSE);
- ahd_set_syncrate(ahd, devinfo, period, offset, ppr_options,
- AHD_TRANS_GOAL, /*paused*/FALSE);
+ ahd_unlock(ahd, &s);
}
void
@@ -4882,12 +2033,6 @@ ahd_release_simq(struct ahd_softc *ahd)
if (ahd->platform_data->qfrozen == 0) {
unblock_reqs = 1;
}
- if (AHD_DV_SIMQ_FROZEN(ahd)
- && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) {
- ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE;
- up(&ahd->platform_data->dv_sem);
- }
- ahd_schedule_runq(ahd);
ahd_unlock(ahd, &s);
/*
* There is still a race here. The mid-layer
@@ -4899,118 +2044,743 @@ ahd_release_simq(struct ahd_softc *ahd)
scsi_unblock_requests(ahd->platform_data->host);
}
-static void
-ahd_linux_sem_timeout(u_long arg)
+static int
+ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
{
- struct scb *scb;
- struct ahd_softc *ahd;
- u_long s;
+ struct ahd_softc *ahd;
+ struct ahd_linux_device *dev;
+ struct scb *pending_scb;
+ u_int saved_scbptr;
+ u_int active_scbptr;
+ u_int last_phase;
+ u_int saved_scsiid;
+ u_int cdb_byte;
+ int retval;
+ int was_paused;
+ int paused;
+ int wait;
+ int disconnected;
+ ahd_mode_state saved_modes;
- scb = (struct scb *)arg;
- ahd = scb->ahd_softc;
- ahd_lock(ahd, &s);
- if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
- scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
- up(&ahd->platform_data->eh_sem);
+ pending_scb = NULL;
+ paused = FALSE;
+ wait = FALSE;
+ ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
+
+ printf("%s:%d:%d:%d: Attempting to queue a%s message:",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun,
+ flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
+
+ printf("CDB:");
+ for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
+ printf(" 0x%x", cmd->cmnd[cdb_byte]);
+ printf("\n");
+
+ spin_lock_irq(&ahd->platform_data->spin_lock);
+
+ /*
+ * First determine if we currently own this command.
+ * Start by searching the device queue. If not found
+ * there, check the pending_scb list. If not found
+ * at all, and the system wanted us to just abort the
+ * command, return success.
+ */
+ dev = scsi_transport_device_data(cmd->device);
+
+ if (dev == NULL) {
+ /*
+ * No target device for this command exists,
+ * so we must not still own the command.
+ */
+ printf("%s:%d:%d:%d: Is not an active device\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ retval = SUCCESS;
+ goto no_cmd;
}
- ahd_unlock(ahd, &s);
+
+ /*
+ * See if we can find a matching cmd in the pending list.
+ */
+ LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+ if (pending_scb->io_ctx == cmd)
+ break;
+ }
+
+ if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
+
+ /* Any SCB for this device will do for a target reset */
+ LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
+ if (ahd_match_scb(ahd, pending_scb, cmd->device->id,
+ cmd->device->channel + 'A',
+ CAM_LUN_WILDCARD,
+ SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+ break;
+ }
+ }
+
+ if (pending_scb == NULL) {
+ printf("%s:%d:%d:%d: Command not found\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ goto no_cmd;
+ }
+
+ if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
+ /*
+ * We can't queue two recovery actions using the same SCB
+ */
+ retval = FAILED;
+ goto done;
+ }
+
+ /*
+ * Ensure that the card doesn't do anything
+ * behind our back. Also make sure that we
+ * didn't "just" miss an interrupt that would
+ * affect this cmd.
+ */
+ was_paused = ahd_is_paused(ahd);
+ ahd_pause_and_flushwork(ahd);
+ paused = TRUE;
+
+ if ((pending_scb->flags & SCB_ACTIVE) == 0) {
+ printf("%s:%d:%d:%d: Command already completed\n",
+ ahd_name(ahd), cmd->device->channel, cmd->device->id,
+ cmd->device->lun);
+ goto no_cmd;
+ }
+
+ printf("%s: At time of recovery, card was %spaused\n",
+ ahd_name(ahd), was_paused ? "" : "not ");
+ ahd_dump_card_state(ahd);
+
+ disconnected = TRUE;
+ if (flag == SCB_ABORT) {
+ if (ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A',
+ cmd->device->lun,
+ pending_scb->hscb->tag,
+ ROLE_INITIATOR, CAM_REQ_ABORTED,
+ SEARCH_COMPLETE) > 0) {
+ printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ retval = SUCCESS;
+ goto done;
+ }
+ } else if (ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A',
+ cmd->device->lun, pending_scb->hscb->tag,
+ ROLE_INITIATOR, /*status*/0,
+ SEARCH_COUNT) > 0) {
+ disconnected = FALSE;
+ }
+
+ saved_modes = ahd_save_modes(ahd);
+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+ last_phase = ahd_inb(ahd, LASTPHASE);
+ saved_scbptr = ahd_get_scbptr(ahd);
+ active_scbptr = saved_scbptr;
+ if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
+ struct scb *bus_scb;
+
+ bus_scb = ahd_lookup_scb(ahd, active_scbptr);
+ if (bus_scb == pending_scb)
+ disconnected = FALSE;
+ else if (flag != SCB_ABORT
+ && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid
+ && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))
+ disconnected = FALSE;
+ }
+
+ /*
+ * At this point, pending_scb is the scb associated with the
+ * passed in command. That command is currently active on the
+ * bus or is in the disconnected state.
+ */
+ saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
+ if (last_phase != P_BUSFREE
+ && (SCB_GET_TAG(pending_scb) == active_scbptr
+ || (flag == SCB_DEVICE_RESET
+ && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) {
+
+ /*
+ * We're active on the bus, so assert ATN
+ * and hope that the target responds.
+ */
+ pending_scb = ahd_lookup_scb(ahd, active_scbptr);
+ pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+ ahd_outb(ahd, MSG_OUT, HOST_MSG);
+ ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
+ printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ wait = TRUE;
+ } else if (disconnected) {
+
+ /*
+ * Actually re-queue this SCB in an attempt
+ * to select the device before it reconnects.
+ */
+ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
+ ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
+ pending_scb->hscb->cdb_len = 0;
+ pending_scb->hscb->task_attribute = 0;
+ pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
+
+ if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
+ /*
+ * Mark the SCB has having an outstanding
+ * task management function. Should the command
+ * complete normally before the task management
+ * function can be sent, the host will be notified
+ * to abort our requeued SCB.
+ */
+ ahd_outb(ahd, SCB_TASK_MANAGEMENT,
+ pending_scb->hscb->task_management);
+ } else {
+ /*
+ * If non-packetized, set the MK_MESSAGE control
+ * bit indicating that we desire to send a message.
+ * We also set the disconnected flag since there is
+ * no guarantee that our SCB control byte matches
+ * the version on the card. We don't want the
+ * sequencer to abort the command thinking an
+ * unsolicited reselection occurred.
+ */
+ pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+
+ /*
+ * The sequencer will never re-reference the
+ * in-core SCB. To make sure we are notified
+ * during reslection, set the MK_MESSAGE flag in
+ * the card's copy of the SCB.
+ */
+ ahd_outb(ahd, SCB_CONTROL,
+ ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
+ }
+
+ /*
+ * Clear out any entries in the QINFIFO first
+ * so we are the next SCB for this target
+ * to run.
+ */
+ ahd_search_qinfifo(ahd, cmd->device->id,
+ cmd->device->channel + 'A', cmd->device->lun,
+ SCB_LIST_NULL, ROLE_INITIATOR,
+ CAM_REQUEUE_REQ, SEARCH_COMPLETE);
+ ahd_qinfifo_requeue_tail(ahd, pending_scb);
+ ahd_set_scbptr(ahd, saved_scbptr);
+ ahd_print_path(ahd, pending_scb);
+ printf("Device is disconnected, re-queuing SCB\n");
+ wait = TRUE;
+ } else {
+ printf("%s:%d:%d:%d: Unable to deliver message\n",
+ ahd_name(ahd), cmd->device->channel,
+ cmd->device->id, cmd->device->lun);
+ retval = FAILED;
+ goto done;
+ }
+
+no_cmd:
+ /*
+ * Our assumption is that if we don't have the command, no
+ * recovery action was required, so we return success. Again,
+ * the semantics of the mid-layer recovery engine are not
+ * well defined, so this may change in time.
+ */
+ retval = SUCCESS;
+done:
+ if (paused)
+ ahd_unpause(ahd);
+ if (wait) {
+ struct timer_list timer;
+ int ret;
+
+ ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;
+ spin_unlock_irq(&ahd->platform_data->spin_lock);
+ init_timer(&timer);
+ timer.data = (u_long)ahd;
+ timer.expires = jiffies + (5 * HZ);
+ timer.function = ahd_linux_sem_timeout;
+ add_timer(&timer);
+ printf("Recovery code sleeping\n");
+ down(&ahd->platform_data->eh_sem);
+ printf("Recovery code awake\n");
+ ret = del_timer_sync(&timer);
+ if (ret == 0) {
+ printf("Timer Expired\n");
+ retval = FAILED;
+ }
+ spin_lock_irq(&ahd->platform_data->spin_lock);
+ }
+ spin_unlock_irq(&ahd->platform_data->spin_lock);
+ return (retval);
}
-static void
-ahd_linux_dev_timed_unfreeze(u_long arg)
+static void ahd_linux_set_width(struct scsi_target *starget, int width)
{
- struct ahd_linux_device *dev;
- struct ahd_softc *ahd;
- u_long s;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_devinfo devinfo;
+ unsigned long flags;
- dev = (struct ahd_linux_device *)arg;
- ahd = dev->target->ahd;
- ahd_lock(ahd, &s);
- dev->flags &= ~AHD_DEV_TIMER_ACTIVE;
- if (dev->qfrozen > 0)
- dev->qfrozen--;
- if (dev->qfrozen == 0
- && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
- ahd_linux_run_device_queue(ahd, dev);
- if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
- && dev->active == 0)
- ahd_linux_free_device(ahd, dev);
- ahd_unlock(ahd, &s);
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_lock(ahd, &flags);
+ ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-void
-ahd_platform_dump_card_state(struct ahd_softc *ahd)
+static void ahd_linux_set_period(struct scsi_target *starget, int period)
{
- struct ahd_linux_device *dev;
- int target;
- int maxtarget;
- int lun;
- int i;
-
- maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7;
- for (target = 0; target <=maxtarget; target++) {
-
- for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
- struct ahd_cmd *acmd;
-
- dev = ahd_linux_get_device(ahd, 0, target,
- lun, /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- printf("DevQ(%d:%d:%d): ", 0, target, lun);
- i = 0;
- TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) {
- if (i++ > AHD_SCB_MAX)
- break;
- }
- printf("%d waiting\n", i);
- }
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options;
+ unsigned int dt;
+ unsigned long flags;
+ unsigned long offset = tinfo->goal.offset;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: set period to %d\n", ahd_name(ahd), period);
+#endif
+ if (offset == 0)
+ offset = MAX_OFFSET;
+
+ if (period < 8)
+ period = 8;
+ if (period < 10) {
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (period == 8)
+ ppr_options |= MSG_EXT_PPR_IU_REQ;
}
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+
+ /* all PPR requests apart from QAS require wide transfers */
+ if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
+ if (spi_width(starget) == 0)
+ ppr_options &= MSG_EXT_PPR_QAS_REQ;
+ }
+
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-static int __init
-ahd_linux_init(void)
+static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- return ahd_linux_detect(&aic79xx_driver_template);
-#else
- scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template);
- if (aic79xx_driver_template.present == 0) {
- scsi_unregister_module(MODULE_SCSI_HA,
- &aic79xx_driver_template);
- return (-ENODEV);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = 0;
+ unsigned int period = 0;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: set offset to %d\n", ahd_name(ahd), offset);
+#endif
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ if (offset != 0) {
+ period = tinfo->goal.period;
+ ppr_options = tinfo->goal.ppr_options;
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
}
- return (0);
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
+ AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_DT_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int width = tinfo->goal.width;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s DT\n", ahd_name(ahd),
+ dt ? "enabling" : "disabling");
+#endif
+ if (dt) {
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (!width)
+ ahd_linux_set_width(starget, 1);
+ } else {
+ if (period <= 9)
+ period = 10; /* If resetting DT, period must be >= 25ns */
+ /* IU is invalid without DT set */
+ ppr_options &= ~MSG_EXT_PPR_IU_REQ;
+ }
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_QAS_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s QAS\n", ahd_name(ahd),
+ qas ? "enabling" : "disabling");
#endif
+
+ if (qas) {
+ ppr_options |= MSG_EXT_PPR_QAS_REQ;
+ }
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
}
-static void __exit
-ahd_linux_exit(void)
+static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
{
- struct ahd_softc *ahd;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_IU_REQ;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt;
+ unsigned long flags;
- /*
- * Shutdown DV threads before going into the SCSI mid-layer.
- * This avoids situations where the mid-layer locks the entire
- * kernel so that waiting for our DV threads to exit leads
- * to deadlock.
- */
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s IU\n", ahd_name(ahd),
+ iu ? "enabling" : "disabling");
+#endif
+
+ if (iu) {
+ ppr_options |= MSG_EXT_PPR_IU_REQ;
+ ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */
+ }
+
+ dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_RD_STRM;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Read Streaming\n", ahd_name(ahd),
+ rdstrm ? "enabling" : "disabling");
+#endif
+
+ if (rdstrm)
+ ppr_options |= MSG_EXT_PPR_RD_STRM;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
- ahd_linux_kill_dv_thread(ahd);
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_WR_FLOW;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Write Flow Control\n", ahd_name(ahd),
+ wrflow ? "enabling" : "disabling");
+#endif
+
+ if (wrflow)
+ ppr_options |= MSG_EXT_PPR_WR_FLOW;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_RTI;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+ if ((ahd->features & AHD_RTI) == 0) {
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: RTI not available\n", ahd_name(ahd));
+#endif
+ return;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s RTI\n", ahd_name(ahd),
+ rti ? "enabling" : "disabling");
+#endif
+
+ if (rti)
+ ppr_options |= MSG_EXT_PPR_RTI;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_PCOMP_EN;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+#ifdef AHD_DEBUG
+ if ((ahd_debug & AHD_SHOW_DV) != 0)
+ printf("%s: %s Precompensation\n", ahd_name(ahd),
+ pcomp ? "Enable" : "Disable");
+#endif
+
+ if (pcomp)
+ ppr_options |= MSG_EXT_PPR_PCOMP_EN;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
+ struct ahd_tmode_tstate *tstate;
+ struct ahd_initiator_tinfo *tinfo
+ = ahd_fetch_transinfo(ahd,
+ starget->channel + 'A',
+ shost->this_id, starget->id, &tstate);
+ struct ahd_devinfo devinfo;
+ unsigned int ppr_options = tinfo->goal.ppr_options
+ & ~MSG_EXT_PPR_HOLD_MCS;
+ unsigned int period = tinfo->goal.period;
+ unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned long flags;
+
+ if (hold)
+ ppr_options |= MSG_EXT_PPR_HOLD_MCS;
+
+ ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahd_find_syncrate(ahd, &period, &ppr_options,
+ dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
+
+ ahd_lock(ahd, &flags);
+ ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
+ ppr_options, AHD_TRANS_GOAL, FALSE);
+ ahd_unlock(ahd, &flags);
+}
+
+
+
+static struct spi_function_template ahd_linux_transport_functions = {
+ .set_offset = ahd_linux_set_offset,
+ .show_offset = 1,
+ .set_period = ahd_linux_set_period,
+ .show_period = 1,
+ .set_width = ahd_linux_set_width,
+ .show_width = 1,
+ .set_dt = ahd_linux_set_dt,
+ .show_dt = 1,
+ .set_iu = ahd_linux_set_iu,
+ .show_iu = 1,
+ .set_qas = ahd_linux_set_qas,
+ .show_qas = 1,
+ .set_rd_strm = ahd_linux_set_rd_strm,
+ .show_rd_strm = 1,
+ .set_wr_flow = ahd_linux_set_wr_flow,
+ .show_wr_flow = 1,
+ .set_rti = ahd_linux_set_rti,
+ .show_rti = 1,
+ .set_pcomp_en = ahd_linux_set_pcomp_en,
+ .show_pcomp_en = 1,
+ .set_hold_mcs = ahd_linux_set_hold_mcs,
+ .show_hold_mcs = 1,
+};
+
+static int __init
+ahd_linux_init(void)
+{
+ int error = 0;
+
/*
- * In 2.4 we have to unregister from the PCI core _after_
- * unregistering from the scsi midlayer to avoid dangling
- * references.
+ * If we've been passed any parameters, process them now.
*/
- scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
-#endif
+ if (aic79xx)
+ aic79xx_setup(aic79xx);
+
+ ahd_linux_transport_template =
+ spi_attach_transport(&ahd_linux_transport_functions);
+ if (!ahd_linux_transport_template)
+ return -ENODEV;
+
+ scsi_transport_reserve_target(ahd_linux_transport_template,
+ sizeof(struct ahd_linux_target));
+ scsi_transport_reserve_device(ahd_linux_transport_template,
+ sizeof(struct ahd_linux_device));
+
+ error = ahd_linux_pci_init();
+ if (error)
+ spi_release_transport(ahd_linux_transport_template);
+ return error;
+}
+
+static void __exit
+ahd_linux_exit(void)
+{
ahd_linux_pci_exit();
+ spi_release_transport(ahd_linux_transport_template);
}
module_init(ahd_linux_init);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 7823e52e99ab..052c6619accc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -42,6 +42,7 @@
#ifndef _AIC79XX_LINUX_H_
#define _AIC79XX_LINUX_H_
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -49,18 +50,23 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/io.h>
-#include <linux/interrupt.h> /* For tasklet support. */
-#include <linux/config.h>
-#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
/* Core SCSI definitions */
#define AIC_LIB_PREFIX ahd
-#include "scsi.h"
-#include <scsi/scsi_host.h>
/* Name space conflict with BSD queue macros */
#ifdef LIST_HEAD
@@ -95,7 +101,7 @@
/************************* Forward Declarations *******************************/
struct ahd_softc;
typedef struct pci_dev *ahd_dev_softc_t;
-typedef Scsi_Cmnd *ahd_io_ctx_t;
+typedef struct scsi_cmnd *ahd_io_ctx_t;
/******************************* Byte Order ***********************************/
#define ahd_htobe16(x) cpu_to_be16(x)
@@ -114,8 +120,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
/************************* Configuration Data *********************************/
extern uint32_t aic79xx_allow_memio;
-extern int aic79xx_detect_complete;
-extern Scsi_Host_Template aic79xx_driver_template;
+extern struct scsi_host_template aic79xx_driver_template;
/***************************** Bus Space/DMA **********************************/
@@ -145,11 +150,7 @@ struct ahd_linux_dma_tag
};
typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
-struct ahd_linux_dmamap
-{
- dma_addr_t bus_addr;
-};
-typedef struct ahd_linux_dmamap* bus_dmamap_t;
+typedef dma_addr_t bus_dmamap_t;
typedef int bus_dma_filter_t(void*, dma_addr_t);
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t;
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);
-static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
+static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
ahd_callback_t *func, void *arg);
static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
static __inline void
-ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
+ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
{
struct ahd_softc *ahd;
@@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
-#define AHD_SCSI_HAS_HOST_LOCK 1
-#else
-#define AHD_SCSI_HAS_HOST_LOCK 0
-#endif
-
#define AIC79XX_DRIVER_VERSION "1.3.11"
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros. The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahd_cmd_internal {
- /* Area owned by the Linux scsi layer. */
- uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
- union {
- STAILQ_ENTRY(ahd_cmd) ste;
- LIST_ENTRY(ahd_cmd) le;
- TAILQ_ENTRY(ahd_cmd) tqe;
- } links;
- uint32_t end;
-};
-
-struct ahd_cmd {
- union {
- struct ahd_cmd_internal icmd;
- struct scsi_cmnd scsi_cmd;
- } un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
/*************************** Device Data Structures ***************************/
/*
* A per probed device structure used to deal with some error recovery
@@ -297,22 +263,17 @@ struct ahd_cmd {
* after a successfully completed inquiry command to the target when
* that inquiry data indicates a lun is present.
*/
-TAILQ_HEAD(ahd_busyq, ahd_cmd);
+
typedef enum {
- AHD_DEV_UNCONFIGURED = 0x01,
AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
- AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
- AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */
AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
- AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
} ahd_linux_dev_flags;
struct ahd_linux_target;
struct ahd_linux_device {
TAILQ_ENTRY(ahd_linux_device) links;
- struct ahd_busyq busyq;
/*
* The number of transactions currently
@@ -388,62 +349,12 @@ struct ahd_linux_device {
*/
u_int commands_since_idle_or_otag;
#define AHD_OTAG_THRESH 500
-
- int lun;
- Scsi_Device *scsi_device;
- struct ahd_linux_target *target;
};
-typedef enum {
- AHD_DV_REQUIRED = 0x01,
- AHD_INQ_VALID = 0x02,
- AHD_BASIC_DV = 0x04,
- AHD_ENHANCED_DV = 0x08
-} ahd_linux_targ_flags;
-
-/* DV States */
-typedef enum {
- AHD_DV_STATE_EXIT = 0,
- AHD_DV_STATE_INQ_SHORT_ASYNC,
- AHD_DV_STATE_INQ_ASYNC,
- AHD_DV_STATE_INQ_ASYNC_VERIFY,
- AHD_DV_STATE_TUR,
- AHD_DV_STATE_REBD,
- AHD_DV_STATE_INQ_VERIFY,
- AHD_DV_STATE_WEB,
- AHD_DV_STATE_REB,
- AHD_DV_STATE_SU,
- AHD_DV_STATE_BUSY
-} ahd_dv_state;
-
struct ahd_linux_target {
- struct ahd_linux_device *devices[AHD_NUM_LUNS];
- int channel;
- int target;
- int refcount;
+ struct scsi_device *sdev[AHD_NUM_LUNS];
struct ahd_transinfo last_tinfo;
struct ahd_softc *ahd;
- ahd_linux_targ_flags flags;
- struct scsi_inquiry_data *inq_data;
- /*
- * The next "fallback" period to use for narrow/wide transfers.
- */
- uint8_t dv_next_narrow_period;
- uint8_t dv_next_wide_period;
- uint8_t dv_max_width;
- uint8_t dv_max_ppr_options;
- uint8_t dv_last_ppr_options;
- u_int dv_echo_size;
- ahd_dv_state dv_state;
- u_int dv_state_retry;
- uint8_t *dv_buffer;
- uint8_t *dv_buffer1;
-
- /*
- * Cumulative counter of errors.
- */
- u_long errors_detected;
- u_long cmds_since_error;
};
/********************* Definitions Required by the Core ***********************/
@@ -453,32 +364,16 @@ struct ahd_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * We dynamically adjust the number of segments in pre-2.5 kernels to
- * avoid fragmentation issues in the SCSI mid-layer's private memory
- * allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
- */
-extern u_int ahd_linux_nseg;
-#define AHD_NSEG ahd_linux_nseg
-#define AHD_LINUX_MIN_NSEG 64
-#else
#define AHD_NSEG 128
-#endif
/*
* Per-SCB OSM storage.
*/
-typedef enum {
- AHD_SCB_UP_EH_SEM = 0x1
-} ahd_linux_scb_flags;
-
struct scb_platform_data {
struct ahd_linux_device *dev;
dma_addr_t buf_busaddr;
uint32_t xfer_len;
uint32_t sense_resid; /* Auto-Sense residual */
- ahd_linux_scb_flags flags;
};
/*
@@ -487,44 +382,23 @@ struct scb_platform_data {
* alignment restrictions of the various platforms supported by
* this driver.
*/
-typedef enum {
- AHD_DV_WAIT_SIMQ_EMPTY = 0x01,
- AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
- AHD_DV_ACTIVE = 0x04,
- AHD_DV_SHUTDOWN = 0x08,
- AHD_RUN_CMPLT_Q_TIMER = 0x10
-} ahd_linux_softc_flags;
-
-TAILQ_HEAD(ahd_completeq, ahd_cmd);
-
struct ahd_platform_data {
/*
* Fields accessed from interrupt context.
*/
- struct ahd_linux_target *targets[AHD_NUM_TARGETS];
- TAILQ_HEAD(, ahd_linux_device) device_runq;
- struct ahd_completeq completeq;
+ struct scsi_target *starget[AHD_NUM_TARGETS];
spinlock_t spin_lock;
- struct tasklet_struct runq_tasklet;
u_int qfrozen;
- pid_t dv_pid;
- struct timer_list completeq_timer;
struct timer_list reset_timer;
- struct timer_list stats_timer;
struct semaphore eh_sem;
- struct semaphore dv_sem;
- struct semaphore dv_cmd_sem; /* XXX This needs to be in
- * the target struct
- */
- struct scsi_device *dv_scsi_dev;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */
- uint64_t hw_dma_mask;
- ahd_linux_softc_flags flags;
+#define AHD_SCB_UP_EH_SEM 0x1
+ uint32_t flags;
};
/************************** OS Utility Wrappers *******************************/
@@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
/**************************** Initialization **********************************/
int ahd_linux_register_host(struct ahd_softc *,
- Scsi_Host_Template *);
+ struct scsi_host_template *);
uint64_t ahd_linux_get_memsize(void);
@@ -657,28 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
struct ahd_transinfo *tinfo);
/******************************** Locking *************************************/
-/* Lock protecting internal data structures */
-static __inline void ahd_lockinit(struct ahd_softc *);
-static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock acquisition and release of the above lock in midlayer entry points. */
-static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
- unsigned long *flags);
-static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
- unsigned long *flags);
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void ahd_done_lockinit(struct ahd_softc *);
-static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
-static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
-
-/* Lock held during ahd_list manipulation and ahd softc frees */
-extern spinlock_t ahd_list_spinlock;
-static __inline void ahd_list_lockinit(void);
-static __inline void ahd_list_lock(unsigned long *flags);
-static __inline void ahd_list_unlock(unsigned long *flags);
-
static __inline void
ahd_lockinit(struct ahd_softc *ahd)
{
@@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
}
-static __inline void
-ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
- /*
- * In 2.5.X and some 2.4.X versions, the midlayer takes our
- * lock just before calling us, so we avoid locking again.
- * For other kernel versions, the io_request_lock is taken
- * just before our entry point is called. In this case, we
- * trade the io_request_lock for our per-softc lock.
- */
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&io_request_lock);
- spin_lock(&ahd->platform_data->spin_lock);
-#endif
-}
-
-static __inline void
-ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&ahd->platform_data->spin_lock);
- spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_lockinit(struct ahd_softc *ahd)
-{
- /*
- * In 2.5.X, our own lock is held during completions.
- * In previous versions, the io_request_lock is used.
- * In either case, we can't initialize this lock again.
- */
-}
-
-static __inline void
-ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
-{
-#if AHD_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahd_list_lockinit(void)
-{
- spin_lock_init(&ahd_list_spinlock);
-}
-
-static __inline void
-ahd_list_lock(unsigned long *flags)
-{
- spin_lock_irqsave(&ahd_list_spinlock, *flags);
-}
-
-static __inline void
-ahd_list_unlock(unsigned long *flags)
-{
- spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
-}
-
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
@@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
}
/**************************** Proc FS Support *********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int ahd_linux_proc_info(char *, char **, off_t, int, int, int);
-#else
int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
off_t, int, int);
-#endif
-
-/*************************** Domain Validation ********************************/
-#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
-#define AHD_DV_SIMQ_FROZEN(ahd) \
- ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \
- && (ahd)->platform_data->qfrozen == 1)
/*********************** Transaction Access Wrappers **************************/
-static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_scsi_status(struct scb *);
static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahd_get_transfer_length(struct scb *);
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
static __inline void ahd_freeze_scb(struct scb *scb);
static __inline
-void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
@@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status)
}
static __inline
-void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
@@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status)
}
static __inline
-uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
@@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb)
}
static __inline
-uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
@@ -1117,7 +890,6 @@ void ahd_done(struct ahd_softc*, struct scb*);
void ahd_send_async(struct ahd_softc *, char channel,
u_int target, u_int lun, ac_code, void *);
void ahd_print_path(struct ahd_softc *, struct scb *);
-void ahd_platform_dump_card_state(struct ahd_softc *ahd);
#ifdef CONFIG_PCI
#define AHD_PCI_CONFIG 1
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 91daf0c7fb10..bf360ae021ab 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,34 @@ struct pci_driver aic79xx_pci_driver = {
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
- struct ahd_softc *ahd;
- u_long l;
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ u_long s;
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev));
- if (ahd != NULL) {
- u_long s;
-
- TAILQ_REMOVE(&ahd_tailq, ahd, links);
- ahd_list_unlock(&l);
- ahd_lock(ahd, &s);
- ahd_intr_enable(ahd, FALSE);
- ahd_unlock(ahd, &s);
- ahd_free(ahd);
- } else
- ahd_list_unlock(&l);
+ if (ahd->platform_data && ahd->platform_data->host)
+ scsi_remove_host(ahd->platform_data->host);
+
+ ahd_lock(ahd, &s);
+ ahd_intr_enable(ahd, FALSE);
+ ahd_unlock(ahd, &s);
+ ahd_free(ahd);
+}
+
+static void
+ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
+{
+ struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
+ unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+ master_pdev = pci_get_slot(pdev->bus, master_devfn);
+ if (master_pdev) {
+ struct ahd_softc *master = pci_get_drvdata(master_pdev);
+ if (master) {
+ ahd->flags &= ~AHD_BIOS_ENABLED;
+ ahd->flags |= master->flags & AHD_BIOS_ENABLED;
+ } else
+ printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
+ pci_dev_put(master_pdev);
+ }
}
static int
@@ -125,22 +132,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
char *name;
int error;
- /*
- * Some BIOSen report the same device multiple times.
- */
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- struct pci_dev *probed_pdev;
-
- probed_pdev = ahd->dev_softc;
- if (probed_pdev->bus->number == pdev->bus->number
- && probed_pdev->devfn == pdev->devfn)
- break;
- }
- if (ahd != NULL) {
- /* Skip duplicate. */
- return (-ENODEV);
- }
-
pci = pdev;
entry = ahd_find_pci_device(pci);
if (entry == NULL)
@@ -177,15 +168,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (memsize >= 0x8000000000ULL
&& pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
ahd->flags |= AHD_64BIT_ADDRESSING;
- ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK;
} else if (memsize > 0x80000000
&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
ahd->flags |= AHD_39BIT_ADDRESSING;
- ahd->platform_data->hw_dma_mask = mask_39bit;
}
} else {
pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
ahd->dev_softc = pci;
error = ahd_pci_config(ahd, entry);
@@ -193,16 +181,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahd_free(ahd);
return (-error);
}
+
+ /*
+ * Second Function PCI devices need to inherit some
+ * * settings from function 0.
+ */
+ if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+ ahd_linux_pci_inherit_flags(ahd);
+
pci_set_drvdata(pdev, ahd);
- if (aic79xx_detect_complete) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- ahd_linux_register_host(ahd, &aic79xx_driver_template);
-#else
- printf("aic79xx: ignoring PCI device found after "
- "initialization\n");
- return (-ENODEV);
-#endif
- }
+
+ ahd_linux_register_host(ahd, &aic79xx_driver_template);
return (0);
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 703f6e44889d..2131db60018a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -283,7 +283,6 @@ int
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
{
struct scb_data *shared_scb_data;
- u_long l;
u_int command;
uint32_t devconfig;
uint16_t subvendor;
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
* Allow interrupts now that we are completely setup.
*/
error = ahd_pci_map_int(ahd);
- if (error != 0)
- return (error);
-
- ahd_list_lock(&l);
- /*
- * Link this softc in with all other ahd instances.
- */
- ahd_softc_insert(ahd);
- ahd_list_unlock(&l);
- return (0);
+ if (!error)
+ ahd->init_level++;
+ return error;
}
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index e01cd6175e34..39a27840fce6 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -49,10 +49,53 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
u_int our_id, char channel,
u_int target_id, u_int target_offset);
static void ahd_dump_device_state(struct info_str *info,
- struct ahd_linux_device *dev);
+ struct scsi_device *sdev);
static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
char *buffer, int length);
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+} scsi_syncrates[] = {
+ { 0x08, 625 }, /* FAST-160 */
+ { 0x09, 1250 }, /* FAST-80 */
+ { 0x0a, 2500 }, /* FAST-40 40MHz */
+ { 0x0b, 3030 }, /* FAST-40 33MHz */
+ { 0x0c, 5000 } /* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahd_calc_syncsrate(u_int period_factor)
+{
+ int i;
+ int num_syncrates;
+
+ num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+ /* See if the period is in the "exception" table */
+ for (i = 0; i < num_syncrates; i++) {
+
+ if (period_factor == scsi_syncrates[i].period_factor) {
+ /* Period in kHz */
+ return (100000000 / scsi_syncrates[i].period);
+ }
+ }
+
+ /*
+ * Wasn't in the table, so use the standard
+ * 4 times conversion.
+ */
+ return (10000000 / (period_factor * 4 * 10));
+}
+
+
static void
copy_mem_info(struct info_str *info, char *data, int len)
{
@@ -109,7 +152,7 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
speed = 3300;
freq = 0;
if (tinfo->offset != 0) {
- freq = aic_calc_syncsrate(tinfo->period);
+ freq = ahd_calc_syncsrate(tinfo->period);
speed = freq;
}
speed *= (0x01 << tinfo->width);
@@ -167,6 +210,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
u_int target_offset)
{
struct ahd_linux_target *targ;
+ struct scsi_target *starget;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
int lun;
@@ -176,20 +220,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahd_format_transinfo(info, &tinfo->user);
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL)
+ starget = ahd->platform_data->starget[target_offset];
+ if (starget == NULL)
return;
+ targ = scsi_transport_target_data(starget);
copy_info(info, "\tGoal: ");
ahd_format_transinfo(info, &tinfo->goal);
copy_info(info, "\tCurr: ");
ahd_format_transinfo(info, &tinfo->curr);
- copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
- struct ahd_linux_device *dev;
+ struct scsi_device *dev;
- dev = targ->devices[lun];
+ dev = targ->sdev[lun];
if (dev == NULL)
continue;
@@ -199,10 +243,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
}
static void
-ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
+ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
{
+ struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+
copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
- dev->target->channel + 'A', dev->target->target, dev->lun);
+ sdev->sdev_target->channel + 'A',
+ sdev->sdev_target->id, sdev->lun);
copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -278,36 +325,16 @@ done:
* Return information to handle /proc support for the driver.
*/
int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ahd_linux_proc_info(char *buffer, char **start, off_t offset,
- int length, int hostno, int inout)
-#else
ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
off_t offset, int length, int inout)
-#endif
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
struct info_str info;
char ahd_info[256];
- u_long l;
u_int max_targ;
u_int i;
int retval;
- retval = -EINVAL;
- ahd_list_lock(&l);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
- if (ahd->platform_data->host->host_no == hostno)
- break;
- }
-#else
- ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
-#endif
-
- if (ahd == NULL)
- goto done;
-
/* Has data been written to the file? */
if (inout == TRUE) {
retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -357,6 +384,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
}
retval = info.pos > info.offset ? info.pos - info.offset : 0;
done:
- ahd_list_unlock(&l);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 088cbc23743d..91d294c6334e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
*
* $FreeBSD$
*/
@@ -243,7 +243,7 @@ typedef enum {
*/
AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
AHC_AIC7860_FE = AHC_AIC7850_FE,
- AHC_AIC7870_FE = AHC_TARGETMODE,
+ AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE,
AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA,
/*
* Although we have space for both the initiator and
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 810ec700d9fc..e196d83b93c7 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1306,7 +1306,6 @@ scratch_ram {
*/
MWI_RESIDUAL {
size 1
- alias TARG_IMMEDIATE_SCB
}
/*
* SCBID of the next SCB to be started by the controller.
@@ -1461,6 +1460,7 @@ scratch_ram {
*/
LAST_MSG {
size 1
+ alias TARG_IMMEDIATE_SCB
}
/*
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
index d84b741fbab5..15196390e28d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
PATCH_ARG_LIST = "struct ahc_softc *ahc"
PREFIX = "ahc_"
@@ -679,6 +679,7 @@ await_busfree:
clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
}
and SXFRCTL0, ~SPIOEN;
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
test SSTAT1,REQINIT|BUSFREE jz .;
test SSTAT1, BUSFREE jnz poll_for_work;
mvi MISSED_BUSFREE call set_seqint;
@@ -1097,7 +1098,7 @@ ultra2_dmahalt:
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SSTAT0, TARGET jz dma_last_sg;
- if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+ if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
test DMAPARAMS, DIRECTION jz dma_mid_sg;
}
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
index 468d612a44f6..3cb07e114e89 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
@@ -28,9 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
*/
/*
@@ -64,7 +62,6 @@
* is preceded by an initial zero (leading 0, followed by 16-bits, MSB
* first). The clock cycling from low to high initiates the next data
* bit to be sent from the chip.
- *
*/
#ifdef __linux__
@@ -81,14 +78,22 @@
* Right now, we only have to read the SEEPROM. But we make it easier to
* add other 93Cx6 functions.
*/
-static struct seeprom_cmd {
+struct seeprom_cmd {
uint8_t len;
- uint8_t bits[9];
-} seeprom_read = {3, {1, 1, 0}};
+ uint8_t bits[11];
+};
+/* Short opcodes for the c46 */
static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Long opcodes for the C56/C66 */
+static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Common opcodes */
static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
/*
* Wait for the SEERDY to go high; about 800 ns.
@@ -222,12 +227,25 @@ int
ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
u_int start_addr, u_int count)
{
+ struct seeprom_cmd *ewen, *ewds;
uint16_t v;
uint8_t temp;
int i, k;
/* Place the chip into write-enable mode */
- send_seeprom_cmd(sd, &seeprom_ewen);
+ if (sd->sd_chip == C46) {
+ ewen = &seeprom_ewen;
+ ewds = &seeprom_ewds;
+ } else if (sd->sd_chip == C56_66) {
+ ewen = &seeprom_long_ewen;
+ ewds = &seeprom_long_ewds;
+ } else {
+ printf("ahc_write_seeprom: unsupported seeprom type %d\n",
+ sd->sd_chip);
+ return (0);
+ }
+
+ send_seeprom_cmd(sd, ewen);
reset_seeprom(sd);
/* Write all requested data out to the seeprom. */
@@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
}
/* Put the chip back into write-protect mode */
- send_seeprom_cmd(sd, &seeprom_ewds);
+ send_seeprom_cmd(sd, ewds);
reset_seeprom(sd);
return (1);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 7bc01e41bcce..58ac46103eb6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -37,9 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $
*/
#ifdef __linux__
@@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc)
ahc_outb(ahc, SEQ_FLAGS2,
ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
}
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahc_outb(ahc, CLRINT, CLRSEQINT);
+
ahc_outb(ahc, MWI_RESIDUAL, 0);
ahc_outb(ahc, SEQCTL, ahc->seqctl);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
+
ahc_unpause(ahc);
}
@@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb_index);
}
#endif
- /*
- * Force a renegotiation with this target just in
- * case the cable was pulled and will later be
- * re-attached. The target may forget its negotiation
- * settings with us should it attempt to reselect
- * during the interruption. The target will not issue
- * a unit attention in this case, so we must always
- * renegotiate.
- */
ahc_scb_devinfo(ahc, &devinfo, scb);
- ahc_force_renegotiation(ahc, &devinfo);
ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahc_freeze_devq(ahc, scb);
+
+ /*
+ * Cancel any pending transactions on the device
+ * now that it seems to be missing. This will
+ * also revert us to async/narrow transfers until
+ * we can renegotiate with the device.
+ */
+ ahc_handle_devreset(ahc, &devinfo,
+ CAM_SEL_TIMEOUT,
+ "Selection Timeout",
+ /*verbose_level*/1);
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_restart(ahc);
@@ -3763,8 +3771,9 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
/*period*/0, /*offset*/0, /*ppr_options*/0,
AHC_TRANS_CUR, /*paused*/TRUE);
- ahc_send_async(ahc, devinfo->channel, devinfo->target,
- CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+ if (status != CAM_SEL_TIMEOUT)
+ ahc_send_async(ahc, devinfo->channel, devinfo->target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
if (message != NULL
&& (verbose_level <= bootverbose))
@@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
* to disturb the integrity of the bus.
*/
ahc_pause(ahc);
- if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
- /*
- * The chip has not been initialized since
- * PCI/EISA/VLB bus reset. Don't trust
- * "left over BIOS data".
- */
- ahc->flags |= AHC_NO_BIOS_INIT;
- }
sxfrctl1_b = 0;
if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
u_int sblkctl;
@@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
ahc->flags |= AHC_ALL_INTERRUPTS;
paused = FALSE;
do {
- if (paused)
+ if (paused) {
ahc_unpause(ahc);
+ /*
+ * Give the sequencer some time to service
+ * any active selections.
+ */
+ ahc_delay(500);
+ }
ahc_intr(ahc);
ahc_pause(ahc);
paused = TRUE;
ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
- ahc_clear_critical_section(ahc);
intstat = ahc_inb(ahc, INTSTAT);
+ if ((intstat & INT_PEND) == 0) {
+ ahc_clear_critical_section(ahc);
+ intstat = ahc_inb(ahc, INTSTAT);
+ }
} while (--maxloops
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 116d0f51ca2c..6ee1435d37fa 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -125,12 +125,6 @@
static struct scsi_transport_template *ahc_linux_transport_template = NULL;
-/*
- * Include aiclib.c as part of our
- * "module dependencies are hard" work around.
- */
-#include "aiclib.c"
-
#include <linux/init.h> /* __setup */
#include <linux/mm.h> /* For fetching system memory size */
#include <linux/blkdev.h> /* For block_size() */
@@ -391,7 +385,6 @@ static int ahc_linux_run_command(struct ahc_softc*,
struct ahc_linux_device *,
struct scsi_cmnd *);
static void ahc_linux_setup_tag_info_global(char *p);
-static aic_option_callback_t ahc_linux_setup_tag_info;
static int aic7xxx_setup(char *s);
static int ahc_linux_unit;
@@ -635,6 +628,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev)
targ->sdev[sdev->lun] = sdev;
+ spi_period(starget) = 0;
+
return 0;
}
@@ -918,6 +913,86 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
}
}
+static char *
+ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
+ void (*callback)(u_long, int, int, int32_t),
+ u_long callback_arg)
+{
+ char *tok_end;
+ char *tok_end2;
+ int i;
+ int instance;
+ int targ;
+ int done;
+ char tok_list[] = {'.', ',', '{', '}', '\0'};
+
+ /* All options use a ':' name/arg separator */
+ if (*opt_arg != ':')
+ return (opt_arg);
+ opt_arg++;
+ instance = -1;
+ targ = -1;
+ done = FALSE;
+ /*
+ * Restore separator that may be in
+ * the middle of our option argument.
+ */
+ tok_end = strchr(opt_arg, '\0');
+ if (tok_end < end)
+ *tok_end = ',';
+ while (!done) {
+ switch (*opt_arg) {
+ case '{':
+ if (instance == -1) {
+ instance = 0;
+ } else {
+ if (depth > 1) {
+ if (targ == -1)
+ targ = 0;
+ } else {
+ printf("Malformed Option %s\n",
+ opt_name);
+ done = TRUE;
+ }
+ }
+ opt_arg++;
+ break;
+ case '}':
+ if (targ != -1)
+ targ = -1;
+ else if (instance != -1)
+ instance = -1;
+ opt_arg++;
+ break;
+ case ',':
+ case '.':
+ if (instance == -1)
+ done = TRUE;
+ else if (targ >= 0)
+ targ++;
+ else if (instance >= 0)
+ instance++;
+ opt_arg++;
+ break;
+ case '\0':
+ done = TRUE;
+ break;
+ default:
+ tok_end = end;
+ for (i = 0; tok_list[i]; i++) {
+ tok_end2 = strchr(opt_arg, tok_list[i]);
+ if ((tok_end2) && (tok_end2 < tok_end))
+ tok_end = tok_end2;
+ }
+ callback(callback_arg, instance, targ,
+ simple_strtol(opt_arg, NULL, 0));
+ opt_arg = tok_end;
+ break;
+ }
+ }
+ return (opt_arg);
+}
+
/*
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
@@ -972,7 +1047,7 @@ aic7xxx_setup(char *s)
if (strncmp(p, "global_tag_depth", n) == 0) {
ahc_linux_setup_tag_info_global(p + n);
} else if (strncmp(p, "tag_info", n) == 0) {
- s = aic_parse_brace_option("tag_info", p + n, end,
+ s = ahc_parse_brace_option("tag_info", p + n, end,
2, ahc_linux_setup_tag_info, 0);
} else if (p[n] == ':') {
*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
@@ -1034,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
return (0);
}
-uint64_t
-ahc_linux_get_memsize(void)
-{
- struct sysinfo si;
-
- si_meminfo(&si);
- return ((uint64_t)si.totalram << PAGE_SHIFT);
-}
-
/*
* Place the SCSI bus into a known state by either resetting it,
* or forcing transfer negotiations on the next command to any
@@ -1143,11 +1209,6 @@ ahc_platform_free(struct ahc_softc *ahc)
int i, j;
if (ahc->platform_data != NULL) {
- if (ahc->platform_data->host != NULL) {
- scsi_remove_host(ahc->platform_data->host);
- scsi_host_put(ahc->platform_data->host);
- }
-
/* destroy all of the device and target objects */
for (i = 0; i < AHC_NUM_TARGETS; i++) {
starget = ahc->platform_data->starget[i];
@@ -1176,6 +1237,9 @@ ahc_platform_free(struct ahc_softc *ahc)
0x1000);
}
+ if (ahc->platform_data->host)
+ scsi_host_put(ahc->platform_data->host);
+
free(ahc->platform_data, M_DEVBUF);
}
}
@@ -1264,14 +1328,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
case AHC_DEV_Q_BASIC:
- scsi_adjust_queue_depth(sdev,
- MSG_SIMPLE_TASK,
- dev->openings + dev->active);
+ scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
+ scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
case AHC_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(sdev,
- MSG_ORDERED_TASK,
- dev->openings + dev->active);
+ scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
+ scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
default:
/*
@@ -1280,9 +1342,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
* serially on the controller/device. This should
* remove some latency.
*/
- scsi_adjust_queue_depth(sdev,
- /*NON-TAGGED*/0,
- /*queue depth*/2);
+ scsi_deactivate_tcq(sdev, 2);
break;
}
}
@@ -1616,9 +1676,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
if (channel == 'B')
target_offset += 8;
starget = ahc->platform_data->starget[target_offset];
- targ = scsi_transport_target_data(starget);
- if (targ == NULL)
+ if (starget == NULL)
break;
+ targ = scsi_transport_target_data(starget);
target_ppr_options =
(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -1635,9 +1695,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
spi_period(starget) = tinfo->curr.period;
spi_width(starget) = tinfo->curr.width;
spi_offset(starget) = tinfo->curr.offset;
- spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
- spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
- spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
+ spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+ spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+ spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
spi_display_xfer_agreement(starget);
break;
}
@@ -2333,8 +2393,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
{
}
-static void ahc_linux_exit(void);
-
static void ahc_linux_set_width(struct scsi_target *starget, int width)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2429,12 +2487,14 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
unsigned int ppr_options = tinfo->goal.ppr_options
& ~MSG_EXT_PPR_DT_REQ;
unsigned int period = tinfo->goal.period;
+ unsigned int width = tinfo->goal.width;
unsigned long flags;
struct ahc_syncrate *syncrate;
if (dt) {
- period = 9; /* 12.5ns is the only period valid for DT */
ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (!width)
+ ahc_linux_set_width(starget, 1);
} else if (period == 9)
period = 10; /* if resetting DT, period must be >= 25ns */
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 0e47ac217549..be9edbe26dbe 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#define AIC7XXX_DRIVER_VERSION "6.2.36"
+#define AIC7XXX_DRIVER_VERSION "7.0"
/*************************** Device Data Structures ***************************/
/*
@@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
int ahc_linux_register_host(struct ahc_softc *,
struct scsi_host_template *);
-uint64_t ahc_linux_get_memsize(void);
-
/*************************** Pretty Printing **********************************/
struct info_str {
char *buffer;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 9d318ce2c993..cb30d9c1153d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -143,12 +143,36 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
struct ahc_softc *ahc = pci_get_drvdata(pdev);
u_long s;
+ if (ahc->platform_data && ahc->platform_data->host)
+ scsi_remove_host(ahc->platform_data->host);
+
ahc_lock(ahc, &s);
ahc_intr_enable(ahc, FALSE);
ahc_unlock(ahc, &s);
ahc_free(ahc);
}
+static void
+ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
+{
+ struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
+ unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+
+ master_pdev = pci_get_slot(pdev->bus, master_devfn);
+ if (master_pdev) {
+ struct ahc_softc *master = pci_get_drvdata(master_pdev);
+ if (master) {
+ ahc->flags &= ~AHC_BIOS_ENABLED;
+ ahc->flags |= master->flags & AHC_BIOS_ENABLED;
+
+ ahc->flags &= ~AHC_PRIMARY_CHANNEL;
+ ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
+ } else
+ printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
+ pci_dev_put(master_pdev);
+ }
+}
+
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -159,6 +183,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ahc_pci_identity *entry;
char *name;
int error;
+ struct device *dev = &pdev->dev;
pci = pdev;
entry = ahc_find_pci_device(pci);
@@ -188,11 +213,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
if (sizeof(dma_addr_t) > 4
- && ahc_linux_get_memsize() > 0x80000000
- && pci_set_dma_mask(pdev, mask_39bit) == 0) {
+ && ahc->features & AHC_LARGE_SCBS
+ && dma_set_mask(dev, mask_39bit) == 0
+ && dma_get_required_mask(dev) > DMA_32BIT_MASK) {
ahc->flags |= AHC_39BIT_ADDRESSING;
} else {
- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ if (dma_set_mask(dev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
return (-ENODEV);
}
@@ -203,6 +229,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc_free(ahc);
return (-error);
}
+
+ /*
+ * Second Function PCI devices need to inherit some
+ * settings from function 0.
+ */
+ if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
+ ahc_linux_pci_inherit_flags(ahc);
+
pci_set_drvdata(pdev, ahc);
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 3802c91f0b07..04a3506cf340 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -54,6 +54,49 @@ static void ahc_dump_device_state(struct info_str *info,
static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
char *buffer, int length);
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+ u_int period_factor;
+ u_int period; /* in 100ths of ns */
+} scsi_syncrates[] = {
+ { 0x08, 625 }, /* FAST-160 */
+ { 0x09, 1250 }, /* FAST-80 */
+ { 0x0a, 2500 }, /* FAST-40 40MHz */
+ { 0x0b, 3030 }, /* FAST-40 33MHz */
+ { 0x0c, 5000 } /* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahc_calc_syncsrate(u_int period_factor)
+{
+ int i;
+ int num_syncrates;
+
+ num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
+ /* See if the period is in the "exception" table */
+ for (i = 0; i < num_syncrates; i++) {
+
+ if (period_factor == scsi_syncrates[i].period_factor) {
+ /* Period in kHz */
+ return (100000000 / scsi_syncrates[i].period);
+ }
+ }
+
+ /*
+ * Wasn't in the table, so use the standard
+ * 4 times conversion.
+ */
+ return (10000000 / (period_factor * 4 * 10));
+}
+
+
static void
copy_mem_info(struct info_str *info, char *data, int len)
{
@@ -106,7 +149,7 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
speed = 3300;
freq = 0;
if (tinfo->offset != 0) {
- freq = aic_calc_syncsrate(tinfo->period);
+ freq = ahc_calc_syncsrate(tinfo->period);
speed = freq;
}
speed *= (0x01 << tinfo->width);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
index 7c1390ed1179..2ce1febca207 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahc_reg_parse_entry {
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
#define CMDSIZE_TABLE_TAIL 0x34
#define MWI_RESIDUAL 0x38
-#define TARG_IMMEDIATE_SCB 0x38
#define NEXT_QUEUED_SCB 0x39
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
#define RETURN_2 0x52
#define LAST_MSG 0x53
+#define TARG_IMMEDIATE_SCB 0x53
#define SCSISEQ_TEMPLATE 0x54
#define ENSELO 0x40
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
index 9c713775d44a..88bfd767c51c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
#include "aic7xxx_osm.h"
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
index cf411368a871..4cee08521e75 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
@@ -2,13 +2,13 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
static uint8_t seqprog[] = {
0xb2, 0x00, 0x00, 0x08,
0xf7, 0x11, 0x22, 0x08,
- 0x00, 0x65, 0xec, 0x59,
+ 0x00, 0x65, 0xee, 0x59,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x6a, 0x24, 0x08,
0x40, 0x00, 0x40, 0x68,
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = {
0x01, 0x4d, 0xc8, 0x30,
0x00, 0x4c, 0x12, 0x70,
0x01, 0x39, 0xa2, 0x30,
- 0x00, 0x6a, 0xc0, 0x5e,
+ 0x00, 0x6a, 0xc2, 0x5e,
0x01, 0x51, 0x20, 0x31,
0x01, 0x57, 0xae, 0x00,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x51, 0x12, 0x5e,
+ 0x00, 0x51, 0x14, 0x5e,
0x01, 0x51, 0xc8, 0x30,
0x00, 0x39, 0xc8, 0x60,
0x00, 0xbb, 0x30, 0x70,
- 0xc1, 0x6a, 0xd8, 0x5e,
+ 0xc1, 0x6a, 0xda, 0x5e,
0x01, 0xbf, 0x72, 0x30,
0x01, 0x40, 0x7e, 0x31,
0x01, 0x90, 0x80, 0x30,
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = {
0x08, 0x6a, 0x78, 0x00,
0x01, 0x50, 0xc8, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0xfc, 0x5d,
+ 0x48, 0x6a, 0xfe, 0x5d,
0x01, 0x6a, 0xdc, 0x01,
0x88, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0xfc, 0x5d,
+ 0x48, 0x6a, 0xfe, 0x5d,
0x01, 0x6a, 0x26, 0x01,
0xf0, 0x19, 0x7a, 0x08,
0x0f, 0x18, 0xc8, 0x08,
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = {
0x00, 0x65, 0x20, 0x41,
0x02, 0x57, 0xae, 0x00,
0x00, 0x65, 0x9e, 0x40,
- 0x61, 0x6a, 0xd8, 0x5e,
+ 0x61, 0x6a, 0xda, 0x5e,
0x08, 0x51, 0x20, 0x71,
0x02, 0x0b, 0xb2, 0x78,
0x00, 0x65, 0xae, 0x40,
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = {
0x80, 0x3d, 0x7a, 0x00,
0x20, 0x6a, 0x16, 0x00,
0x00, 0x65, 0xcc, 0x41,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0x65, 0xb4, 0x5e,
0x00, 0x65, 0x12, 0x40,
0x20, 0x11, 0xd2, 0x68,
0x20, 0x6a, 0x18, 0x00,
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = {
0x80, 0x0b, 0xc4, 0x79,
0x12, 0x01, 0x02, 0x00,
0x01, 0xab, 0xac, 0x30,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x40, 0x6a, 0x16, 0x00,
- 0x80, 0x3e, 0x84, 0x5d,
+ 0x80, 0x3e, 0x86, 0x5d,
0x20, 0xb8, 0x18, 0x79,
- 0x20, 0x6a, 0x84, 0x5d,
- 0x00, 0xab, 0x84, 0x5d,
+ 0x20, 0x6a, 0x86, 0x5d,
+ 0x00, 0xab, 0x86, 0x5d,
0x01, 0xa9, 0x78, 0x30,
0x10, 0xb8, 0x20, 0x79,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x00, 0x65, 0xae, 0x40,
0x10, 0x03, 0x3c, 0x69,
0x08, 0x3c, 0x5a, 0x69,
0x04, 0x3c, 0x92, 0x69,
0x02, 0x3c, 0x98, 0x69,
0x01, 0x3c, 0x44, 0x79,
- 0xff, 0x6a, 0x70, 0x00,
+ 0xff, 0x6a, 0xa6, 0x00,
0x00, 0x65, 0xa4, 0x59,
- 0x00, 0x6a, 0xc0, 0x5e,
- 0xff, 0x38, 0x30, 0x71,
+ 0x00, 0x6a, 0xc2, 0x5e,
+ 0xff, 0x53, 0x30, 0x71,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x38, 0x12, 0x5e,
+ 0x00, 0x53, 0x14, 0x5e,
0x00, 0x65, 0xea, 0x58,
0x12, 0x01, 0x02, 0x00,
0x00, 0x65, 0x18, 0x41,
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = {
0x00, 0x65, 0xf2, 0x58,
0xfd, 0x57, 0xae, 0x08,
0x00, 0x65, 0xae, 0x40,
- 0xe4, 0x6a, 0x6e, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
0x20, 0x3c, 0x4a, 0x79,
- 0x02, 0x6a, 0x84, 0x5d,
- 0x04, 0x6a, 0x84, 0x5d,
+ 0x02, 0x6a, 0x86, 0x5d,
+ 0x04, 0x6a, 0x86, 0x5d,
0x01, 0x03, 0x4c, 0x69,
0xf7, 0x11, 0x22, 0x08,
0xff, 0x6a, 0x24, 0x08,
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = {
0x80, 0x86, 0xc8, 0x08,
0x01, 0x4f, 0xc8, 0x30,
0x00, 0x50, 0x6c, 0x61,
- 0xc4, 0x6a, 0x6e, 0x5d,
+ 0xc4, 0x6a, 0x70, 0x5d,
0x40, 0x3c, 0x68, 0x79,
- 0x28, 0x6a, 0x84, 0x5d,
+ 0x28, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
- 0x08, 0x6a, 0x84, 0x5d,
+ 0x08, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
- 0x84, 0x6a, 0x6e, 0x5d,
+ 0x84, 0x6a, 0x70, 0x5d,
0x00, 0x65, 0xf2, 0x58,
0x01, 0x66, 0xc8, 0x30,
0x01, 0x64, 0xd8, 0x31,
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = {
0xf7, 0x3c, 0x78, 0x08,
0x00, 0x65, 0x20, 0x41,
0x40, 0xaa, 0x7e, 0x10,
- 0x04, 0xaa, 0x6e, 0x5d,
- 0x00, 0x65, 0x56, 0x42,
- 0xc4, 0x6a, 0x6e, 0x5d,
+ 0x04, 0xaa, 0x70, 0x5d,
+ 0x00, 0x65, 0x58, 0x42,
+ 0xc4, 0x6a, 0x70, 0x5d,
0xc0, 0x6a, 0x7e, 0x00,
- 0x00, 0xa8, 0x84, 0x5d,
+ 0x00, 0xa8, 0x86, 0x5d,
0xe4, 0x6a, 0x06, 0x00,
- 0x00, 0x6a, 0x84, 0x5d,
+ 0x00, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x4c, 0x41,
0x10, 0x3c, 0xa8, 0x69,
- 0x00, 0xbb, 0x8a, 0x44,
+ 0x00, 0xbb, 0x8c, 0x44,
0x18, 0x6a, 0xda, 0x01,
0x01, 0x69, 0xd8, 0x31,
0x1c, 0x6a, 0xd0, 0x01,
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = {
0x01, 0x93, 0x26, 0x01,
0x03, 0x6a, 0x2a, 0x01,
0x01, 0x69, 0x32, 0x31,
- 0x1c, 0x6a, 0xe0, 0x5d,
+ 0x1c, 0x6a, 0xe2, 0x5d,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
0x01, 0x50, 0xa0, 0x18,
0x02, 0x6a, 0x22, 0x05,
0x1a, 0x01, 0x02, 0x00,
0x80, 0x6a, 0x74, 0x00,
0x40, 0x6a, 0x78, 0x00,
0x40, 0x6a, 0x16, 0x00,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x00, 0x65, 0xda, 0x5d,
0x01, 0x3f, 0xc8, 0x30,
- 0xbf, 0x64, 0x56, 0x7a,
- 0x80, 0x64, 0x9e, 0x73,
- 0xa0, 0x64, 0x00, 0x74,
- 0xc0, 0x64, 0xf4, 0x73,
- 0xe0, 0x64, 0x30, 0x74,
- 0x01, 0x6a, 0xd8, 0x5e,
+ 0xbf, 0x64, 0x58, 0x7a,
+ 0x80, 0x64, 0xa0, 0x73,
+ 0xa0, 0x64, 0x02, 0x74,
+ 0xc0, 0x64, 0xf6, 0x73,
+ 0xe0, 0x64, 0x32, 0x74,
+ 0x01, 0x6a, 0xda, 0x5e,
0x00, 0x65, 0xcc, 0x41,
0xf7, 0x11, 0x22, 0x08,
0x01, 0x06, 0xd4, 0x30,
0xff, 0x6a, 0x24, 0x08,
0xf7, 0x01, 0x02, 0x08,
- 0x09, 0x0c, 0xe6, 0x79,
+ 0xc0, 0x6a, 0x78, 0x00,
+ 0x09, 0x0c, 0xe8, 0x79,
0x08, 0x0c, 0x04, 0x68,
- 0xb1, 0x6a, 0xd8, 0x5e,
+ 0xb1, 0x6a, 0xda, 0x5e,
0xff, 0x6a, 0x26, 0x09,
0x12, 0x01, 0x02, 0x00,
0x02, 0x6a, 0x08, 0x30,
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = {
0x00, 0xa5, 0x4a, 0x21,
0x00, 0xa6, 0x4c, 0x21,
0x00, 0xa7, 0x4e, 0x25,
- 0x08, 0xeb, 0xdc, 0x7e,
- 0x80, 0xeb, 0x06, 0x7a,
+ 0x08, 0xeb, 0xde, 0x7e,
+ 0x80, 0xeb, 0x08, 0x7a,
0xff, 0x6a, 0xd6, 0x09,
- 0x08, 0xeb, 0x0a, 0x6a,
+ 0x08, 0xeb, 0x0c, 0x6a,
0xff, 0x6a, 0xd4, 0x0c,
- 0x80, 0xa3, 0xdc, 0x6e,
- 0x88, 0xeb, 0x20, 0x72,
- 0x08, 0xeb, 0xdc, 0x6e,
- 0x04, 0xea, 0x24, 0xe2,
- 0x08, 0xee, 0xdc, 0x6e,
+ 0x80, 0xa3, 0xde, 0x6e,
+ 0x88, 0xeb, 0x22, 0x72,
+ 0x08, 0xeb, 0xde, 0x6e,
+ 0x04, 0xea, 0x26, 0xe2,
+ 0x08, 0xee, 0xde, 0x6e,
0x04, 0x6a, 0xd0, 0x81,
0x05, 0xa4, 0xc0, 0x89,
0x03, 0xa5, 0xc2, 0x31,
0x09, 0x6a, 0xd6, 0x05,
- 0x00, 0x65, 0x08, 0x5a,
+ 0x00, 0x65, 0x0a, 0x5a,
0x06, 0xa4, 0xd4, 0x89,
- 0x80, 0x94, 0xdc, 0x7e,
+ 0x80, 0x94, 0xde, 0x7e,
0x07, 0xe9, 0x10, 0x31,
0x01, 0xe9, 0x46, 0x31,
- 0x00, 0xa3, 0xba, 0x5e,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x00, 0xa3, 0xbc, 0x5e,
+ 0x00, 0x65, 0xfc, 0x59,
0x01, 0xa4, 0xca, 0x30,
- 0x80, 0xa3, 0x34, 0x7a,
+ 0x80, 0xa3, 0x36, 0x7a,
0x02, 0x65, 0xca, 0x00,
0x01, 0x65, 0xf8, 0x31,
0x80, 0x93, 0x26, 0x01,
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = {
0x01, 0x8c, 0xc8, 0x30,
0x00, 0x88, 0xc8, 0x18,
0x02, 0x64, 0xc8, 0x88,
- 0xff, 0x64, 0xdc, 0x7e,
- 0xff, 0x8d, 0x4a, 0x6a,
- 0xff, 0x8e, 0x4a, 0x6a,
+ 0xff, 0x64, 0xde, 0x7e,
+ 0xff, 0x8d, 0x4c, 0x6a,
+ 0xff, 0x8e, 0x4c, 0x6a,
0x03, 0x8c, 0xd4, 0x98,
- 0x00, 0x65, 0xdc, 0x56,
+ 0x00, 0x65, 0xde, 0x56,
0x01, 0x64, 0x70, 0x30,
0xff, 0x64, 0xc8, 0x10,
0x01, 0x64, 0xc8, 0x18,
0x00, 0x8c, 0x18, 0x19,
0xff, 0x8d, 0x1a, 0x21,
0xff, 0x8e, 0x1c, 0x25,
- 0xc0, 0x3c, 0x5a, 0x7a,
- 0x21, 0x6a, 0xd8, 0x5e,
+ 0xc0, 0x3c, 0x5c, 0x7a,
+ 0x21, 0x6a, 0xda, 0x5e,
0xa8, 0x6a, 0x76, 0x00,
0x79, 0x6a, 0x76, 0x00,
- 0x40, 0x3f, 0x62, 0x6a,
+ 0x40, 0x3f, 0x64, 0x6a,
0x04, 0x3b, 0x76, 0x00,
0x04, 0x6a, 0xd4, 0x81,
- 0x20, 0x3c, 0x6a, 0x7a,
- 0x51, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x82, 0x42,
+ 0x20, 0x3c, 0x6c, 0x7a,
+ 0x51, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x84, 0x42,
0x20, 0x3c, 0x78, 0x00,
- 0x00, 0xb3, 0xba, 0x5e,
+ 0x00, 0xb3, 0xbc, 0x5e,
0x07, 0xac, 0x10, 0x31,
0x05, 0xb3, 0x46, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0xac, 0x6a, 0xee, 0x5d,
+ 0xac, 0x6a, 0xf0, 0x5d,
0xa3, 0x6a, 0xcc, 0x00,
- 0xb3, 0x6a, 0xf2, 0x5d,
- 0x00, 0x65, 0x3a, 0x5a,
+ 0xb3, 0x6a, 0xf4, 0x5d,
+ 0x00, 0x65, 0x3c, 0x5a,
0xfd, 0xa4, 0x48, 0x09,
0x03, 0x8c, 0x10, 0x30,
- 0x00, 0x65, 0xe6, 0x5d,
- 0x01, 0xa4, 0x94, 0x7a,
+ 0x00, 0x65, 0xe8, 0x5d,
+ 0x01, 0xa4, 0x96, 0x7a,
0x04, 0x3b, 0x76, 0x08,
0x01, 0x3b, 0x26, 0x31,
0x80, 0x02, 0x04, 0x00,
- 0x10, 0x0c, 0x8a, 0x7a,
- 0x03, 0x9e, 0x8c, 0x6a,
+ 0x10, 0x0c, 0x8c, 0x7a,
+ 0x03, 0x9e, 0x8e, 0x6a,
0x7f, 0x02, 0x04, 0x08,
- 0x91, 0x6a, 0xd8, 0x5e,
+ 0x91, 0x6a, 0xda, 0x5e,
0x00, 0x65, 0xcc, 0x41,
0x01, 0xa4, 0xca, 0x30,
- 0x80, 0xa3, 0x9a, 0x7a,
+ 0x80, 0xa3, 0x9c, 0x7a,
0x02, 0x65, 0xca, 0x00,
0x01, 0x65, 0xf8, 0x31,
0x01, 0x3b, 0x26, 0x31,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x01, 0xfc, 0xa8, 0x6a,
- 0x80, 0x0b, 0x9e, 0x6a,
- 0x10, 0x0c, 0x9e, 0x7a,
- 0x20, 0x93, 0x9e, 0x6a,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x01, 0xfc, 0xaa, 0x6a,
+ 0x80, 0x0b, 0xa0, 0x6a,
+ 0x10, 0x0c, 0xa0, 0x7a,
+ 0x20, 0x93, 0xa0, 0x6a,
0x02, 0x93, 0x26, 0x01,
- 0x02, 0xfc, 0xb2, 0x7a,
- 0x40, 0x0d, 0xc6, 0x6a,
+ 0x02, 0xfc, 0xb4, 0x7a,
+ 0x40, 0x0d, 0xc8, 0x6a,
0x01, 0xa4, 0x48, 0x01,
- 0x00, 0x65, 0xc6, 0x42,
- 0x40, 0x0d, 0xb8, 0x6a,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x00, 0x65, 0xaa, 0x42,
- 0x80, 0xfc, 0xc2, 0x7a,
- 0x80, 0xa4, 0xc2, 0x6a,
+ 0x00, 0x65, 0xc8, 0x42,
+ 0x40, 0x0d, 0xba, 0x6a,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x00, 0x65, 0xac, 0x42,
+ 0x80, 0xfc, 0xc4, 0x7a,
+ 0x80, 0xa4, 0xc4, 0x6a,
0xff, 0xa5, 0x4a, 0x19,
0xff, 0xa6, 0x4c, 0x21,
0xff, 0xa7, 0x4e, 0x21,
0xf8, 0xfc, 0x48, 0x09,
0x7f, 0xa3, 0x46, 0x09,
- 0x04, 0x3b, 0xe2, 0x6a,
+ 0x04, 0x3b, 0xe4, 0x6a,
0x02, 0x93, 0x26, 0x01,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0x94, 0xc8, 0x7a,
- 0x01, 0xa4, 0xe0, 0x7a,
- 0x01, 0xfc, 0xd6, 0x7a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x01, 0x94, 0xe2, 0x6a,
- 0x00, 0x65, 0x82, 0x42,
- 0x01, 0x94, 0xe0, 0x7a,
- 0x10, 0x94, 0xe2, 0x6a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0x94, 0xca, 0x7a,
+ 0x01, 0xa4, 0xe2, 0x7a,
+ 0x01, 0xfc, 0xd8, 0x7a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x01, 0x94, 0xe4, 0x6a,
+ 0x00, 0x65, 0x84, 0x42,
+ 0x01, 0x94, 0xe2, 0x7a,
+ 0x10, 0x94, 0xe4, 0x6a,
0xd7, 0x93, 0x26, 0x09,
- 0x28, 0x93, 0xe6, 0x6a,
+ 0x28, 0x93, 0xe8, 0x6a,
0x01, 0x85, 0x0a, 0x01,
- 0x02, 0xfc, 0xee, 0x6a,
+ 0x02, 0xfc, 0xf0, 0x6a,
0x01, 0x14, 0x46, 0x31,
0xff, 0x6a, 0x10, 0x09,
0xfe, 0x85, 0x0a, 0x09,
- 0xff, 0x38, 0xfc, 0x6a,
- 0x80, 0xa3, 0xfc, 0x7a,
- 0x80, 0x0b, 0xfa, 0x7a,
- 0x04, 0x3b, 0xfc, 0x7a,
+ 0xff, 0x38, 0xfe, 0x6a,
+ 0x80, 0xa3, 0xfe, 0x7a,
+ 0x80, 0x0b, 0xfc, 0x7a,
+ 0x04, 0x3b, 0xfe, 0x7a,
0xbf, 0x3b, 0x76, 0x08,
0x01, 0x3b, 0x26, 0x31,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x01, 0x0b, 0x0a, 0x6b,
- 0x10, 0x0c, 0xfe, 0x7a,
- 0x04, 0x93, 0x08, 0x6b,
- 0x01, 0x94, 0x06, 0x7b,
- 0x10, 0x94, 0x08, 0x6b,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x01, 0x0b, 0x0c, 0x6b,
+ 0x10, 0x0c, 0x00, 0x7b,
+ 0x04, 0x93, 0x0a, 0x6b,
+ 0x01, 0x94, 0x08, 0x7b,
+ 0x10, 0x94, 0x0a, 0x6b,
0xc7, 0x93, 0x26, 0x09,
0x01, 0x99, 0xd4, 0x30,
- 0x38, 0x93, 0x0c, 0x6b,
- 0xff, 0x08, 0x5a, 0x6b,
- 0xff, 0x09, 0x5a, 0x6b,
- 0xff, 0x0a, 0x5a, 0x6b,
- 0xff, 0x38, 0x28, 0x7b,
+ 0x38, 0x93, 0x0e, 0x6b,
+ 0xff, 0x08, 0x5c, 0x6b,
+ 0xff, 0x09, 0x5c, 0x6b,
+ 0xff, 0x0a, 0x5c, 0x6b,
+ 0xff, 0x38, 0x2a, 0x7b,
0x04, 0x14, 0x10, 0x31,
0x01, 0x38, 0x18, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0xf4, 0x5d,
- 0x00, 0x38, 0xe0, 0x5d,
+ 0x14, 0x6a, 0xf6, 0x5d,
+ 0x00, 0x38, 0xe2, 0x5d,
0xff, 0x6a, 0x70, 0x08,
- 0x00, 0x65, 0x54, 0x43,
- 0x80, 0xa3, 0x2e, 0x7b,
+ 0x00, 0x65, 0x56, 0x43,
+ 0x80, 0xa3, 0x30, 0x7b,
0x01, 0xa4, 0x48, 0x01,
- 0x00, 0x65, 0x5a, 0x43,
- 0x08, 0xeb, 0x34, 0x7b,
- 0x00, 0x65, 0x0e, 0x5a,
- 0x08, 0xeb, 0x30, 0x6b,
+ 0x00, 0x65, 0x5c, 0x43,
+ 0x08, 0xeb, 0x36, 0x7b,
+ 0x00, 0x65, 0x10, 0x5a,
+ 0x08, 0xeb, 0x32, 0x6b,
0x07, 0xe9, 0x10, 0x31,
0x01, 0xe9, 0xca, 0x30,
0x01, 0x65, 0x46, 0x31,
- 0x00, 0x6a, 0xba, 0x5e,
+ 0x00, 0x6a, 0xbc, 0x5e,
0x88, 0x6a, 0xcc, 0x00,
- 0xa4, 0x6a, 0xf4, 0x5d,
- 0x08, 0x6a, 0xe0, 0x5d,
+ 0xa4, 0x6a, 0xf6, 0x5d,
+ 0x08, 0x6a, 0xe2, 0x5d,
0x0d, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
0x88, 0x6a, 0xcc, 0x00,
- 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8c, 0x5e,
0x01, 0x99, 0x46, 0x31,
- 0x00, 0xa3, 0xba, 0x5e,
+ 0x00, 0xa3, 0xbc, 0x5e,
0x01, 0x88, 0x10, 0x31,
- 0x00, 0x65, 0x3a, 0x5a,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x00, 0x65, 0x3c, 0x5a,
+ 0x00, 0x65, 0xfc, 0x59,
0x03, 0x8c, 0x10, 0x30,
- 0x00, 0x65, 0xe6, 0x5d,
- 0x80, 0x0b, 0x82, 0x6a,
- 0x80, 0x0b, 0x62, 0x6b,
- 0x01, 0x0c, 0x5c, 0x7b,
- 0x10, 0x0c, 0x82, 0x7a,
- 0x03, 0x9e, 0x82, 0x6a,
- 0x00, 0x65, 0x04, 0x5a,
- 0x00, 0x6a, 0xba, 0x5e,
- 0x01, 0xa4, 0x82, 0x6b,
- 0xff, 0x38, 0x78, 0x7b,
+ 0x00, 0x65, 0xe8, 0x5d,
+ 0x80, 0x0b, 0x84, 0x6a,
+ 0x80, 0x0b, 0x64, 0x6b,
+ 0x01, 0x0c, 0x5e, 0x7b,
+ 0x10, 0x0c, 0x84, 0x7a,
+ 0x03, 0x9e, 0x84, 0x6a,
+ 0x00, 0x65, 0x06, 0x5a,
+ 0x00, 0x6a, 0xbc, 0x5e,
+ 0x01, 0xa4, 0x84, 0x6b,
+ 0xff, 0x38, 0x7a, 0x7b,
0x01, 0x38, 0xc8, 0x30,
0x00, 0x08, 0x40, 0x19,
0xff, 0x6a, 0xc8, 0x08,
0x00, 0x09, 0x42, 0x21,
0x00, 0x0a, 0x44, 0x21,
0xff, 0x6a, 0x70, 0x08,
- 0x00, 0x65, 0x7a, 0x43,
+ 0x00, 0x65, 0x7c, 0x43,
0x03, 0x08, 0x40, 0x31,
0x03, 0x08, 0x40, 0x31,
0x01, 0x08, 0x40, 0x31,
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = {
0x04, 0x3c, 0xcc, 0x79,
0xfb, 0x3c, 0x78, 0x08,
0x04, 0x93, 0x20, 0x79,
- 0x01, 0x0c, 0x8e, 0x6b,
+ 0x01, 0x0c, 0x90, 0x6b,
0x80, 0xba, 0x20, 0x79,
0x80, 0x04, 0x20, 0x79,
- 0xe4, 0x6a, 0x6e, 0x5d,
- 0x23, 0x6a, 0x84, 0x5d,
- 0x01, 0x6a, 0x84, 0x5d,
+ 0xe4, 0x6a, 0x70, 0x5d,
+ 0x23, 0x6a, 0x86, 0x5d,
+ 0x01, 0x6a, 0x86, 0x5d,
0x00, 0x65, 0x20, 0x41,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0x3c, 0xa2, 0x7b,
- 0x21, 0x6a, 0xd8, 0x5e,
+ 0x80, 0x3c, 0xa4, 0x7b,
+ 0x21, 0x6a, 0xda, 0x5e,
0x01, 0xbc, 0x18, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x02, 0x6a, 0xf8, 0x01,
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = {
0xff, 0x6a, 0x12, 0x08,
0xff, 0x6a, 0x14, 0x08,
0xf3, 0xbc, 0xd4, 0x18,
- 0xa0, 0x6a, 0xc8, 0x53,
+ 0xa0, 0x6a, 0xca, 0x53,
0x04, 0xa0, 0x10, 0x31,
0xac, 0x6a, 0x26, 0x01,
0x04, 0xa0, 0x10, 0x31,
0x03, 0x08, 0x18, 0x31,
0x88, 0x6a, 0xcc, 0x00,
- 0xa0, 0x6a, 0xf4, 0x5d,
- 0x00, 0xbc, 0xe0, 0x5d,
+ 0xa0, 0x6a, 0xf6, 0x5d,
+ 0x00, 0xbc, 0xe2, 0x5d,
0x3d, 0x6a, 0x26, 0x01,
- 0x00, 0x65, 0xe0, 0x43,
+ 0x00, 0x65, 0xe2, 0x43,
0xff, 0x6a, 0x10, 0x09,
0xa4, 0x6a, 0x26, 0x01,
0x0c, 0xa0, 0x32, 0x31,
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = {
0x36, 0x6a, 0x26, 0x01,
0x02, 0x93, 0x26, 0x01,
0x35, 0x6a, 0x26, 0x01,
- 0x00, 0x65, 0x9c, 0x5e,
- 0x00, 0x65, 0x9c, 0x5e,
+ 0x00, 0x65, 0x9e, 0x5e,
+ 0x00, 0x65, 0x9e, 0x5e,
0x02, 0x93, 0x26, 0x01,
0xbf, 0x3c, 0x78, 0x08,
- 0x04, 0x0b, 0xe6, 0x6b,
- 0x10, 0x0c, 0xe2, 0x7b,
- 0x01, 0x03, 0xe6, 0x6b,
- 0x20, 0x93, 0xe8, 0x6b,
- 0x04, 0x0b, 0xee, 0x6b,
+ 0x04, 0x0b, 0xe8, 0x6b,
+ 0x10, 0x0c, 0xe4, 0x7b,
+ 0x01, 0x03, 0xe8, 0x6b,
+ 0x20, 0x93, 0xea, 0x6b,
+ 0x04, 0x0b, 0xf0, 0x6b,
0x40, 0x3c, 0x78, 0x00,
0xc7, 0x93, 0x26, 0x09,
- 0x38, 0x93, 0xf0, 0x6b,
+ 0x38, 0x93, 0xf2, 0x6b,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0x3c, 0x56, 0x6c,
+ 0x80, 0x3c, 0x58, 0x6c,
0x01, 0x06, 0x50, 0x31,
0x80, 0xb8, 0x70, 0x01,
0x00, 0x65, 0xcc, 0x41,
0x10, 0x3f, 0x06, 0x00,
0x10, 0x6a, 0x06, 0x00,
0x01, 0x3a, 0xca, 0x30,
- 0x80, 0x65, 0x1c, 0x64,
- 0x10, 0xb8, 0x40, 0x6c,
+ 0x80, 0x65, 0x1e, 0x64,
+ 0x10, 0xb8, 0x42, 0x6c,
0xc0, 0x3e, 0xca, 0x00,
- 0x40, 0xb8, 0x0c, 0x6c,
+ 0x40, 0xb8, 0x0e, 0x6c,
0xbf, 0x65, 0xca, 0x08,
- 0x20, 0xb8, 0x20, 0x7c,
+ 0x20, 0xb8, 0x22, 0x7c,
0x01, 0x65, 0x0c, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0x28, 0x64,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0x2a, 0x64,
0x23, 0xb8, 0x0c, 0x08,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0x28, 0x64,
- 0x00, 0xbb, 0x20, 0x44,
- 0xff, 0x65, 0x20, 0x64,
- 0x00, 0x65, 0x40, 0x44,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0x2a, 0x64,
+ 0x00, 0xbb, 0x22, 0x44,
+ 0xff, 0x65, 0x22, 0x64,
+ 0x00, 0x65, 0x42, 0x44,
0x40, 0x6a, 0x18, 0x00,
0x01, 0x65, 0x0c, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
- 0xa0, 0x3f, 0xfc, 0x73,
+ 0x00, 0x65, 0xda, 0x5d,
+ 0xa0, 0x3f, 0xfe, 0x73,
0x40, 0x6a, 0x18, 0x00,
0x01, 0x3a, 0xa6, 0x30,
0x08, 0x6a, 0x74, 0x00,
0x00, 0x65, 0xcc, 0x41,
- 0x64, 0x6a, 0x68, 0x5d,
- 0x80, 0x64, 0xd8, 0x6c,
- 0x04, 0x64, 0x9a, 0x74,
- 0x02, 0x64, 0xaa, 0x74,
- 0x00, 0x6a, 0x60, 0x74,
- 0x03, 0x64, 0xc8, 0x74,
- 0x23, 0x64, 0x48, 0x74,
- 0x08, 0x64, 0x5c, 0x74,
- 0x61, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x64, 0x6a, 0x6a, 0x5d,
+ 0x80, 0x64, 0xda, 0x6c,
+ 0x04, 0x64, 0x9c, 0x74,
+ 0x02, 0x64, 0xac, 0x74,
+ 0x00, 0x6a, 0x62, 0x74,
+ 0x03, 0x64, 0xca, 0x74,
+ 0x23, 0x64, 0x4a, 0x74,
+ 0x08, 0x64, 0x5e, 0x74,
+ 0x61, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0xda, 0x5d,
0x08, 0x51, 0xce, 0x71,
- 0x00, 0x65, 0x40, 0x44,
- 0x80, 0x04, 0x5a, 0x7c,
- 0x51, 0x6a, 0x5e, 0x5d,
- 0x01, 0x51, 0x5a, 0x64,
- 0x01, 0xa4, 0x52, 0x7c,
- 0x80, 0xba, 0x5c, 0x6c,
- 0x41, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
- 0x21, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
- 0x07, 0x6a, 0x54, 0x5d,
+ 0x00, 0x65, 0x42, 0x44,
+ 0x80, 0x04, 0x5c, 0x7c,
+ 0x51, 0x6a, 0x60, 0x5d,
+ 0x01, 0x51, 0x5c, 0x64,
+ 0x01, 0xa4, 0x54, 0x7c,
+ 0x80, 0xba, 0x5e, 0x6c,
+ 0x41, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x21, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x07, 0x6a, 0x56, 0x5d,
0x01, 0x06, 0xd4, 0x30,
0x00, 0x65, 0xcc, 0x41,
- 0x80, 0xb8, 0x56, 0x7c,
- 0xc0, 0x3c, 0x6a, 0x7c,
- 0x80, 0x3c, 0x56, 0x6c,
- 0xff, 0xa8, 0x6a, 0x6c,
- 0x40, 0x3c, 0x56, 0x6c,
- 0x10, 0xb8, 0x6e, 0x7c,
- 0xa1, 0x6a, 0xd8, 0x5e,
- 0x01, 0xb4, 0x74, 0x6c,
- 0x02, 0xb4, 0x76, 0x6c,
- 0x01, 0xa4, 0x76, 0x7c,
- 0xff, 0xa8, 0x86, 0x7c,
+ 0x80, 0xb8, 0x58, 0x7c,
+ 0xc0, 0x3c, 0x6c, 0x7c,
+ 0x80, 0x3c, 0x58, 0x6c,
+ 0xff, 0xa8, 0x6c, 0x6c,
+ 0x40, 0x3c, 0x58, 0x6c,
+ 0x10, 0xb8, 0x70, 0x7c,
+ 0xa1, 0x6a, 0xda, 0x5e,
+ 0x01, 0xb4, 0x76, 0x6c,
+ 0x02, 0xb4, 0x78, 0x6c,
+ 0x01, 0xa4, 0x78, 0x7c,
+ 0xff, 0xa8, 0x88, 0x7c,
0x04, 0xb4, 0x68, 0x01,
0x01, 0x6a, 0x76, 0x00,
- 0x00, 0xbb, 0x12, 0x5e,
- 0xff, 0xa8, 0x86, 0x7c,
- 0x71, 0x6a, 0xd8, 0x5e,
- 0x40, 0x51, 0x86, 0x64,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0xbb, 0x14, 0x5e,
+ 0xff, 0xa8, 0x88, 0x7c,
+ 0x71, 0x6a, 0xda, 0x5e,
+ 0x40, 0x51, 0x88, 0x64,
+ 0x00, 0x65, 0xb4, 0x5e,
0x00, 0x65, 0xde, 0x41,
- 0x00, 0xbb, 0x8a, 0x5c,
+ 0x00, 0xbb, 0x8c, 0x5c,
0x00, 0x65, 0xde, 0x41,
- 0x00, 0x65, 0xb2, 0x5e,
+ 0x00, 0x65, 0xb4, 0x5e,
0x01, 0x65, 0xa2, 0x30,
0x01, 0xf8, 0xc8, 0x30,
0x01, 0x4e, 0xc8, 0x30,
- 0x00, 0x6a, 0xb6, 0xdd,
- 0x00, 0x51, 0xc8, 0x5d,
+ 0x00, 0x6a, 0xb8, 0xdd,
+ 0x00, 0x51, 0xca, 0x5d,
0x01, 0x4e, 0x9c, 0x18,
0x02, 0x6a, 0x22, 0x05,
- 0xc0, 0x3c, 0x56, 0x6c,
+ 0xc0, 0x3c, 0x58, 0x6c,
0x04, 0xb8, 0x70, 0x01,
- 0x00, 0x65, 0xd4, 0x5e,
+ 0x00, 0x65, 0xd6, 0x5e,
0x20, 0xb8, 0xde, 0x69,
0x01, 0xbb, 0xa2, 0x30,
0x3f, 0xba, 0x7c, 0x08,
- 0x00, 0xb9, 0xce, 0x5c,
+ 0x00, 0xb9, 0xd0, 0x5c,
0x00, 0x65, 0xde, 0x41,
0x01, 0x06, 0xd4, 0x30,
0x20, 0x3c, 0xcc, 0x79,
- 0x20, 0x3c, 0x5c, 0x7c,
- 0x01, 0xa4, 0xb8, 0x7c,
+ 0x20, 0x3c, 0x5e, 0x7c,
+ 0x01, 0xa4, 0xba, 0x7c,
0x01, 0xb4, 0x68, 0x01,
0x00, 0x65, 0xcc, 0x41,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x00, 0x65, 0x5e, 0x44,
0x04, 0x14, 0x58, 0x31,
0x01, 0x06, 0xd4, 0x30,
0x08, 0xa0, 0x60, 0x31,
0xac, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0xf4, 0x5d,
+ 0x14, 0x6a, 0xf6, 0x5d,
0x01, 0x06, 0xd4, 0x30,
- 0xa0, 0x6a, 0xec, 0x5d,
+ 0xa0, 0x6a, 0xee, 0x5d,
0x00, 0x65, 0xcc, 0x41,
0xdf, 0x3c, 0x78, 0x08,
0x12, 0x01, 0x02, 0x00,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x00, 0x65, 0x5e, 0x44,
0x4c, 0x65, 0xcc, 0x28,
0x01, 0x3e, 0x20, 0x31,
0xd0, 0x66, 0xcc, 0x18,
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = {
0xd0, 0x65, 0xca, 0x18,
0x01, 0x3e, 0x20, 0x31,
0x30, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xe6, 0x4c,
+ 0x00, 0x65, 0xe8, 0x4c,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x20, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xee, 0x54,
+ 0x00, 0x65, 0xf0, 0x54,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x20, 0x65, 0xca, 0x18,
0xe0, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0xf8, 0x4c,
+ 0x00, 0x65, 0xfa, 0x4c,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0xd0, 0x65, 0xd4, 0x18,
- 0x00, 0x65, 0x00, 0x55,
+ 0x00, 0x65, 0x02, 0x55,
0xe1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x01, 0x6c, 0xa2, 0x30,
- 0xff, 0x51, 0x12, 0x75,
- 0x00, 0x51, 0x8e, 0x5d,
+ 0xff, 0x51, 0x14, 0x75,
+ 0x00, 0x51, 0x90, 0x5d,
0x01, 0x51, 0x20, 0x31,
- 0x00, 0x65, 0x34, 0x45,
+ 0x00, 0x65, 0x36, 0x45,
0x3f, 0xba, 0xc8, 0x08,
- 0x00, 0x3e, 0x34, 0x75,
- 0x00, 0x65, 0xb0, 0x5e,
+ 0x00, 0x3e, 0x36, 0x75,
+ 0x00, 0x65, 0xb2, 0x5e,
0x80, 0x3c, 0x78, 0x00,
0x01, 0x06, 0xd4, 0x30,
- 0x00, 0x65, 0xd8, 0x5d,
+ 0x00, 0x65, 0xda, 0x5d,
0x01, 0x3c, 0x78, 0x00,
- 0xe0, 0x3f, 0x50, 0x65,
+ 0xe0, 0x3f, 0x52, 0x65,
0x02, 0x3c, 0x78, 0x00,
- 0x20, 0x12, 0x50, 0x65,
- 0x51, 0x6a, 0x5e, 0x5d,
- 0x00, 0x51, 0x8e, 0x5d,
- 0x51, 0x6a, 0x5e, 0x5d,
+ 0x20, 0x12, 0x52, 0x65,
+ 0x51, 0x6a, 0x60, 0x5d,
+ 0x00, 0x51, 0x90, 0x5d,
+ 0x51, 0x6a, 0x60, 0x5d,
0x01, 0x51, 0x20, 0x31,
0x04, 0x3c, 0x78, 0x00,
0x01, 0xb9, 0xc8, 0x30,
- 0x00, 0x3d, 0x4e, 0x65,
+ 0x00, 0x3d, 0x50, 0x65,
0x08, 0x3c, 0x78, 0x00,
0x3f, 0xba, 0xc8, 0x08,
- 0x00, 0x3e, 0x4e, 0x65,
+ 0x00, 0x3e, 0x50, 0x65,
0x10, 0x3c, 0x78, 0x00,
- 0x04, 0xb8, 0x4e, 0x7d,
+ 0x04, 0xb8, 0x50, 0x7d,
0xfb, 0xb8, 0x70, 0x09,
- 0x20, 0xb8, 0x44, 0x6d,
+ 0x20, 0xb8, 0x46, 0x6d,
0x01, 0x90, 0xc8, 0x30,
0xff, 0x6a, 0xa2, 0x00,
- 0x00, 0x3d, 0xce, 0x5c,
+ 0x00, 0x3d, 0xd0, 0x5c,
0x01, 0x64, 0x20, 0x31,
0xff, 0x6a, 0x78, 0x08,
0x00, 0x65, 0xea, 0x58,
- 0x10, 0xb8, 0x5c, 0x7c,
- 0xff, 0x6a, 0x54, 0x5d,
- 0x00, 0x65, 0x5c, 0x44,
- 0x00, 0x65, 0xb0, 0x5e,
- 0x31, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x5c, 0x44,
+ 0x10, 0xb8, 0x5e, 0x7c,
+ 0xff, 0x6a, 0x56, 0x5d,
+ 0x00, 0x65, 0x5e, 0x44,
+ 0x00, 0x65, 0xb2, 0x5e,
+ 0x31, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x5e, 0x44,
0x10, 0x3f, 0x06, 0x00,
0x10, 0x6a, 0x06, 0x00,
0x01, 0x65, 0x74, 0x34,
- 0x81, 0x6a, 0xd8, 0x5e,
- 0x00, 0x65, 0x60, 0x45,
+ 0x81, 0x6a, 0xda, 0x5e,
+ 0x00, 0x65, 0x62, 0x45,
0x01, 0x06, 0xd4, 0x30,
- 0x01, 0x0c, 0x60, 0x7d,
- 0x04, 0x0c, 0x5a, 0x6d,
+ 0x01, 0x0c, 0x62, 0x7d,
+ 0x04, 0x0c, 0x5c, 0x6d,
0xe0, 0x03, 0x7e, 0x08,
0xe0, 0x3f, 0xcc, 0x61,
0x01, 0x65, 0xcc, 0x30,
0x01, 0x12, 0xda, 0x34,
0x01, 0x06, 0xd4, 0x34,
- 0x01, 0x03, 0x6e, 0x6d,
+ 0x01, 0x03, 0x70, 0x6d,
0x40, 0x03, 0xcc, 0x08,
0x01, 0x65, 0x06, 0x30,
0x40, 0x65, 0xc8, 0x08,
- 0x00, 0x66, 0x7c, 0x75,
- 0x40, 0x65, 0x7c, 0x7d,
- 0x00, 0x65, 0x7c, 0x5d,
+ 0x00, 0x66, 0x7e, 0x75,
+ 0x40, 0x65, 0x7e, 0x7d,
+ 0x00, 0x65, 0x7e, 0x5d,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x08,
0xff, 0x6a, 0xd4, 0x0c,
0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0x86, 0x7d,
+ 0x02, 0x0b, 0x88, 0x7d,
0x01, 0x65, 0x0c, 0x30,
- 0x02, 0x0b, 0x8a, 0x7d,
+ 0x02, 0x0b, 0x8c, 0x7d,
0xf7, 0x01, 0x02, 0x0c,
0x01, 0x65, 0xc8, 0x30,
- 0xff, 0x41, 0xae, 0x75,
+ 0xff, 0x41, 0xb0, 0x75,
0x01, 0x41, 0x20, 0x31,
0xff, 0x6a, 0xa4, 0x00,
- 0x00, 0x65, 0x9e, 0x45,
- 0xff, 0xbf, 0xae, 0x75,
+ 0x00, 0x65, 0xa0, 0x45,
+ 0xff, 0xbf, 0xb0, 0x75,
0x01, 0x90, 0xa4, 0x30,
0x01, 0xbf, 0x20, 0x31,
- 0x00, 0xbb, 0x98, 0x65,
- 0xff, 0x52, 0xac, 0x75,
+ 0x00, 0xbb, 0x9a, 0x65,
+ 0xff, 0x52, 0xae, 0x75,
0x01, 0xbf, 0xcc, 0x30,
0x01, 0x90, 0xca, 0x30,
0x01, 0x52, 0x20, 0x31,
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = {
0x01, 0x65, 0x20, 0x35,
0x01, 0xbf, 0x82, 0x34,
0x01, 0x64, 0xa2, 0x30,
- 0x00, 0x6a, 0xc0, 0x5e,
+ 0x00, 0x6a, 0xc2, 0x5e,
0x0d, 0x6a, 0x76, 0x00,
- 0x00, 0x51, 0x12, 0x46,
+ 0x00, 0x51, 0x14, 0x46,
0x01, 0x65, 0xa4, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0x06, 0x5e,
+ 0x48, 0x6a, 0x08, 0x5e,
0x01, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x05,
0x88, 0x6a, 0xcc, 0x00,
- 0x48, 0x6a, 0x06, 0x5e,
- 0x01, 0x6a, 0xe0, 0x5d,
+ 0x48, 0x6a, 0x08, 0x5e,
+ 0x01, 0x6a, 0xe2, 0x5d,
0x01, 0x6a, 0x26, 0x05,
0x01, 0x65, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0xcc, 0x7d,
+ 0x80, 0xee, 0xce, 0x7d,
0xff, 0x6a, 0xdc, 0x0d,
0x01, 0x65, 0x32, 0x31,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x46,
- 0x81, 0x6a, 0xd8, 0x5e,
- 0x01, 0x0c, 0xd8, 0x7d,
- 0x04, 0x0c, 0xd6, 0x6d,
+ 0x00, 0x65, 0xaa, 0x46,
+ 0x81, 0x6a, 0xda, 0x5e,
+ 0x01, 0x0c, 0xda, 0x7d,
+ 0x04, 0x0c, 0xd8, 0x6d,
0xe0, 0x03, 0x06, 0x08,
0xe0, 0x03, 0x7e, 0x0c,
0x01, 0x65, 0x18, 0x31,
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = {
0x01, 0x6c, 0xda, 0x34,
0x3d, 0x64, 0xa4, 0x28,
0x55, 0x64, 0xc8, 0x28,
- 0x00, 0x65, 0x06, 0x46,
+ 0x00, 0x65, 0x08, 0x46,
0x2e, 0x64, 0xa4, 0x28,
0x66, 0x64, 0xc8, 0x28,
0x00, 0x6c, 0xda, 0x18,
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = {
0x00, 0x6c, 0xda, 0x24,
0x01, 0x65, 0xc8, 0x30,
0xe0, 0x6a, 0xcc, 0x00,
- 0x44, 0x6a, 0x02, 0x5e,
+ 0x44, 0x6a, 0x04, 0x5e,
0x01, 0x90, 0xe2, 0x31,
- 0x04, 0x3b, 0x26, 0x7e,
+ 0x04, 0x3b, 0x28, 0x7e,
0x30, 0x6a, 0xd0, 0x01,
0x20, 0x6a, 0xd0, 0x01,
0x1d, 0x6a, 0xdc, 0x01,
- 0xdc, 0xee, 0x22, 0x66,
- 0x00, 0x65, 0x3e, 0x46,
+ 0xdc, 0xee, 0x24, 0x66,
+ 0x00, 0x65, 0x40, 0x46,
0x20, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x01,
0x20, 0xa0, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0x2e, 0x7e,
+ 0x80, 0xee, 0x30, 0x7e,
0x11, 0x6a, 0xdc, 0x01,
- 0x50, 0xee, 0x32, 0x66,
+ 0x50, 0xee, 0x34, 0x66,
0x20, 0x6a, 0xd0, 0x01,
0x09, 0x6a, 0xdc, 0x01,
- 0x88, 0xee, 0x38, 0x66,
+ 0x88, 0xee, 0x3a, 0x66,
0x19, 0x6a, 0xdc, 0x01,
- 0xd8, 0xee, 0x3c, 0x66,
+ 0xd8, 0xee, 0x3e, 0x66,
0xff, 0x6a, 0xdc, 0x09,
- 0x18, 0xee, 0x40, 0x6e,
+ 0x18, 0xee, 0x42, 0x6e,
0xff, 0x6a, 0xd4, 0x0c,
0x88, 0x6a, 0xcc, 0x00,
- 0x44, 0x6a, 0x02, 0x5e,
- 0x20, 0x6a, 0xe0, 0x5d,
+ 0x44, 0x6a, 0x04, 0x5e,
+ 0x20, 0x6a, 0xe2, 0x5d,
0x01, 0x3b, 0x26, 0x31,
- 0x04, 0x3b, 0x5a, 0x6e,
+ 0x04, 0x3b, 0x5c, 0x6e,
0xa0, 0x6a, 0xca, 0x00,
0x20, 0x65, 0xc8, 0x18,
- 0x00, 0x65, 0x98, 0x5e,
- 0x00, 0x65, 0x52, 0x66,
+ 0x00, 0x65, 0x9a, 0x5e,
+ 0x00, 0x65, 0x54, 0x66,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0xa8, 0x46,
+ 0x00, 0x65, 0xaa, 0x46,
0xa0, 0x6a, 0xcc, 0x00,
0xff, 0x6a, 0xc8, 0x08,
- 0x20, 0x94, 0x5e, 0x6e,
- 0x10, 0x94, 0x60, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
- 0x08, 0x94, 0x7a, 0x6e,
+ 0x20, 0x94, 0x60, 0x6e,
+ 0x10, 0x94, 0x62, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
+ 0x08, 0x94, 0x7c, 0x6e,
0xff, 0x8c, 0xc8, 0x10,
0xc1, 0x64, 0xc8, 0x18,
0xf8, 0x64, 0xc8, 0x08,
0x01, 0x99, 0xda, 0x30,
- 0x00, 0x66, 0x6e, 0x66,
- 0xc0, 0x66, 0xaa, 0x76,
+ 0x00, 0x66, 0x70, 0x66,
+ 0xc0, 0x66, 0xac, 0x76,
0x60, 0x66, 0xc8, 0x18,
0x3d, 0x64, 0xc8, 0x28,
- 0x00, 0x65, 0x5e, 0x46,
+ 0x00, 0x65, 0x60, 0x46,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0x7c, 0x6e,
+ 0x08, 0x93, 0x7e, 0x6e,
0x00, 0x62, 0xc4, 0x18,
- 0x00, 0x65, 0xa8, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
- 0x00, 0x65, 0x88, 0x5e,
+ 0x00, 0x65, 0xaa, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
+ 0x00, 0x65, 0x8a, 0x5e,
0x01, 0x99, 0xda, 0x30,
0x01, 0x99, 0xda, 0x30,
0x01, 0x99, 0xda, 0x30,
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = {
0x01, 0x6c, 0x32, 0x31,
0x01, 0x6c, 0x32, 0x31,
0x01, 0x6c, 0x32, 0x35,
- 0x08, 0x94, 0xa8, 0x7e,
+ 0x08, 0x94, 0xaa, 0x7e,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0xac, 0x6e,
+ 0x08, 0x93, 0xae, 0x6e,
0xff, 0x6a, 0xd4, 0x0c,
- 0x04, 0xb8, 0xd4, 0x6e,
+ 0x04, 0xb8, 0xd6, 0x6e,
0x01, 0x42, 0x7e, 0x31,
0xff, 0x6a, 0x76, 0x01,
0x01, 0x90, 0x84, 0x34,
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = {
0x01, 0x85, 0x0a, 0x01,
0x7f, 0x65, 0x10, 0x09,
0xfe, 0x85, 0x0a, 0x0d,
- 0xff, 0x42, 0xd0, 0x66,
- 0xff, 0x41, 0xc8, 0x66,
- 0xd1, 0x6a, 0xd8, 0x5e,
+ 0xff, 0x42, 0xd2, 0x66,
+ 0xff, 0x41, 0xca, 0x66,
+ 0xd1, 0x6a, 0xda, 0x5e,
0xff, 0x6a, 0xca, 0x04,
0x01, 0x41, 0x20, 0x31,
0x01, 0xbf, 0x82, 0x30,
0x01, 0x6a, 0x76, 0x00,
- 0x00, 0xbb, 0x12, 0x46,
+ 0x00, 0xbb, 0x14, 0x46,
0x01, 0x42, 0x20, 0x31,
0x01, 0xbf, 0x84, 0x34,
0x01, 0x41, 0x7e, 0x31,
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func;
static int
ahc_patch17_func(struct ahc_softc *ahc)
{
- return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0);
+ return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0);
}
static ahc_patch_func_t ahc_patch16_func;
@@ -1142,152 +1143,152 @@ static struct patch {
{ ahc_patch0_func, 196, 1, 1 },
{ ahc_patch9_func, 212, 6, 2 },
{ ahc_patch0_func, 218, 6, 1 },
- { ahc_patch8_func, 226, 20, 2 },
+ { ahc_patch8_func, 226, 21, 2 },
{ ahc_patch1_func, 241, 1, 1 },
- { ahc_patch1_func, 248, 1, 2 },
- { ahc_patch0_func, 249, 2, 2 },
- { ahc_patch11_func, 250, 1, 1 },
- { ahc_patch9_func, 258, 27, 3 },
- { ahc_patch1_func, 274, 10, 2 },
- { ahc_patch13_func, 277, 1, 1 },
- { ahc_patch14_func, 285, 14, 1 },
- { ahc_patch1_func, 301, 1, 2 },
- { ahc_patch0_func, 302, 1, 1 },
- { ahc_patch9_func, 305, 1, 1 },
- { ahc_patch13_func, 310, 1, 1 },
- { ahc_patch9_func, 311, 2, 2 },
- { ahc_patch0_func, 313, 4, 1 },
- { ahc_patch14_func, 317, 1, 1 },
- { ahc_patch15_func, 319, 2, 3 },
- { ahc_patch9_func, 319, 1, 2 },
- { ahc_patch0_func, 320, 1, 1 },
- { ahc_patch6_func, 325, 1, 2 },
- { ahc_patch0_func, 326, 1, 1 },
- { ahc_patch1_func, 330, 47, 11 },
- { ahc_patch6_func, 337, 2, 4 },
- { ahc_patch7_func, 337, 1, 1 },
- { ahc_patch8_func, 338, 1, 1 },
- { ahc_patch0_func, 339, 1, 1 },
- { ahc_patch16_func, 340, 1, 1 },
- { ahc_patch6_func, 356, 6, 3 },
- { ahc_patch16_func, 356, 5, 1 },
- { ahc_patch0_func, 362, 7, 1 },
- { ahc_patch13_func, 372, 5, 1 },
- { ahc_patch0_func, 377, 52, 17 },
- { ahc_patch14_func, 377, 1, 1 },
- { ahc_patch7_func, 379, 2, 2 },
- { ahc_patch17_func, 380, 1, 1 },
- { ahc_patch9_func, 383, 1, 1 },
- { ahc_patch18_func, 390, 1, 1 },
- { ahc_patch14_func, 395, 9, 3 },
- { ahc_patch9_func, 396, 3, 2 },
- { ahc_patch0_func, 399, 3, 1 },
- { ahc_patch9_func, 407, 6, 2 },
- { ahc_patch0_func, 413, 9, 2 },
- { ahc_patch13_func, 413, 1, 1 },
- { ahc_patch13_func, 422, 2, 1 },
- { ahc_patch14_func, 424, 1, 1 },
- { ahc_patch9_func, 426, 1, 2 },
- { ahc_patch0_func, 427, 1, 1 },
- { ahc_patch7_func, 428, 1, 1 },
+ { ahc_patch1_func, 249, 1, 2 },
+ { ahc_patch0_func, 250, 2, 2 },
+ { ahc_patch11_func, 251, 1, 1 },
+ { ahc_patch9_func, 259, 27, 3 },
+ { ahc_patch1_func, 275, 10, 2 },
+ { ahc_patch13_func, 278, 1, 1 },
+ { ahc_patch14_func, 286, 14, 1 },
+ { ahc_patch1_func, 302, 1, 2 },
+ { ahc_patch0_func, 303, 1, 1 },
+ { ahc_patch9_func, 306, 1, 1 },
+ { ahc_patch13_func, 311, 1, 1 },
+ { ahc_patch9_func, 312, 2, 2 },
+ { ahc_patch0_func, 314, 4, 1 },
+ { ahc_patch14_func, 318, 1, 1 },
+ { ahc_patch15_func, 320, 2, 3 },
+ { ahc_patch9_func, 320, 1, 2 },
+ { ahc_patch0_func, 321, 1, 1 },
+ { ahc_patch6_func, 326, 1, 2 },
+ { ahc_patch0_func, 327, 1, 1 },
+ { ahc_patch1_func, 331, 47, 11 },
+ { ahc_patch6_func, 338, 2, 4 },
+ { ahc_patch7_func, 338, 1, 1 },
+ { ahc_patch8_func, 339, 1, 1 },
+ { ahc_patch0_func, 340, 1, 1 },
+ { ahc_patch16_func, 341, 1, 1 },
+ { ahc_patch6_func, 357, 6, 3 },
+ { ahc_patch16_func, 357, 5, 1 },
+ { ahc_patch0_func, 363, 7, 1 },
+ { ahc_patch13_func, 373, 5, 1 },
+ { ahc_patch0_func, 378, 52, 17 },
+ { ahc_patch14_func, 378, 1, 1 },
+ { ahc_patch7_func, 380, 2, 2 },
+ { ahc_patch17_func, 381, 1, 1 },
+ { ahc_patch9_func, 384, 1, 1 },
+ { ahc_patch18_func, 391, 1, 1 },
+ { ahc_patch14_func, 396, 9, 3 },
+ { ahc_patch9_func, 397, 3, 2 },
+ { ahc_patch0_func, 400, 3, 1 },
+ { ahc_patch9_func, 408, 6, 2 },
+ { ahc_patch0_func, 414, 9, 2 },
+ { ahc_patch13_func, 414, 1, 1 },
+ { ahc_patch13_func, 423, 2, 1 },
+ { ahc_patch14_func, 425, 1, 1 },
+ { ahc_patch9_func, 427, 1, 2 },
+ { ahc_patch0_func, 428, 1, 1 },
{ ahc_patch7_func, 429, 1, 1 },
- { ahc_patch8_func, 430, 3, 3 },
- { ahc_patch6_func, 431, 1, 2 },
- { ahc_patch0_func, 432, 1, 1 },
- { ahc_patch9_func, 433, 1, 1 },
- { ahc_patch15_func, 434, 1, 2 },
- { ahc_patch13_func, 434, 1, 1 },
- { ahc_patch14_func, 436, 9, 4 },
- { ahc_patch9_func, 436, 1, 1 },
- { ahc_patch9_func, 443, 2, 1 },
- { ahc_patch0_func, 445, 4, 3 },
- { ahc_patch9_func, 445, 1, 2 },
- { ahc_patch0_func, 446, 3, 1 },
- { ahc_patch1_func, 450, 2, 1 },
- { ahc_patch7_func, 452, 10, 2 },
- { ahc_patch0_func, 462, 1, 1 },
- { ahc_patch8_func, 463, 118, 22 },
- { ahc_patch1_func, 465, 3, 2 },
- { ahc_patch0_func, 468, 5, 3 },
- { ahc_patch9_func, 468, 2, 2 },
- { ahc_patch0_func, 470, 3, 1 },
- { ahc_patch1_func, 475, 2, 2 },
- { ahc_patch0_func, 477, 6, 3 },
- { ahc_patch9_func, 477, 2, 2 },
- { ahc_patch0_func, 479, 3, 1 },
- { ahc_patch1_func, 485, 2, 2 },
- { ahc_patch0_func, 487, 9, 7 },
- { ahc_patch9_func, 487, 5, 6 },
- { ahc_patch19_func, 487, 1, 2 },
- { ahc_patch0_func, 488, 1, 1 },
- { ahc_patch19_func, 490, 1, 2 },
- { ahc_patch0_func, 491, 1, 1 },
- { ahc_patch0_func, 492, 4, 1 },
- { ahc_patch6_func, 497, 3, 2 },
- { ahc_patch0_func, 500, 1, 1 },
- { ahc_patch6_func, 510, 1, 2 },
- { ahc_patch0_func, 511, 1, 1 },
- { ahc_patch20_func, 548, 7, 1 },
- { ahc_patch3_func, 583, 1, 2 },
- { ahc_patch0_func, 584, 1, 1 },
- { ahc_patch21_func, 587, 1, 1 },
- { ahc_patch8_func, 589, 106, 33 },
- { ahc_patch4_func, 591, 1, 1 },
- { ahc_patch1_func, 597, 2, 2 },
- { ahc_patch0_func, 599, 1, 1 },
- { ahc_patch1_func, 602, 1, 2 },
- { ahc_patch0_func, 603, 1, 1 },
- { ahc_patch9_func, 604, 3, 3 },
- { ahc_patch15_func, 605, 1, 1 },
- { ahc_patch0_func, 607, 4, 1 },
- { ahc_patch19_func, 616, 2, 2 },
- { ahc_patch0_func, 618, 1, 1 },
- { ahc_patch19_func, 622, 10, 3 },
- { ahc_patch5_func, 624, 8, 1 },
- { ahc_patch0_func, 632, 9, 2 },
- { ahc_patch5_func, 633, 8, 1 },
- { ahc_patch4_func, 643, 1, 2 },
- { ahc_patch0_func, 644, 1, 1 },
- { ahc_patch19_func, 645, 1, 2 },
- { ahc_patch0_func, 646, 3, 2 },
- { ahc_patch4_func, 648, 1, 1 },
- { ahc_patch5_func, 649, 1, 1 },
- { ahc_patch5_func, 652, 1, 1 },
- { ahc_patch5_func, 654, 1, 1 },
- { ahc_patch4_func, 656, 2, 2 },
- { ahc_patch0_func, 658, 2, 1 },
- { ahc_patch5_func, 660, 1, 1 },
- { ahc_patch5_func, 663, 1, 1 },
- { ahc_patch5_func, 666, 1, 1 },
- { ahc_patch19_func, 670, 1, 1 },
- { ahc_patch19_func, 673, 1, 1 },
- { ahc_patch4_func, 679, 1, 1 },
- { ahc_patch6_func, 682, 1, 2 },
- { ahc_patch0_func, 683, 1, 1 },
- { ahc_patch7_func, 695, 16, 1 },
- { ahc_patch4_func, 711, 20, 1 },
- { ahc_patch9_func, 732, 4, 2 },
- { ahc_patch0_func, 736, 4, 1 },
- { ahc_patch9_func, 740, 4, 2 },
- { ahc_patch0_func, 744, 3, 1 },
- { ahc_patch6_func, 750, 1, 1 },
- { ahc_patch22_func, 752, 14, 1 },
- { ahc_patch7_func, 766, 3, 1 },
- { ahc_patch9_func, 778, 24, 8 },
- { ahc_patch19_func, 782, 1, 2 },
- { ahc_patch0_func, 783, 1, 1 },
- { ahc_patch15_func, 788, 4, 2 },
- { ahc_patch0_func, 792, 7, 3 },
- { ahc_patch23_func, 792, 5, 2 },
- { ahc_patch0_func, 797, 2, 1 },
- { ahc_patch0_func, 802, 42, 3 },
- { ahc_patch18_func, 814, 18, 2 },
- { ahc_patch0_func, 832, 1, 1 },
- { ahc_patch4_func, 856, 1, 1 },
- { ahc_patch4_func, 857, 3, 2 },
- { ahc_patch0_func, 860, 1, 1 },
- { ahc_patch13_func, 861, 3, 1 },
- { ahc_patch4_func, 864, 12, 1 }
+ { ahc_patch7_func, 430, 1, 1 },
+ { ahc_patch8_func, 431, 3, 3 },
+ { ahc_patch6_func, 432, 1, 2 },
+ { ahc_patch0_func, 433, 1, 1 },
+ { ahc_patch9_func, 434, 1, 1 },
+ { ahc_patch15_func, 435, 1, 2 },
+ { ahc_patch13_func, 435, 1, 1 },
+ { ahc_patch14_func, 437, 9, 4 },
+ { ahc_patch9_func, 437, 1, 1 },
+ { ahc_patch9_func, 444, 2, 1 },
+ { ahc_patch0_func, 446, 4, 3 },
+ { ahc_patch9_func, 446, 1, 2 },
+ { ahc_patch0_func, 447, 3, 1 },
+ { ahc_patch1_func, 451, 2, 1 },
+ { ahc_patch7_func, 453, 10, 2 },
+ { ahc_patch0_func, 463, 1, 1 },
+ { ahc_patch8_func, 464, 118, 22 },
+ { ahc_patch1_func, 466, 3, 2 },
+ { ahc_patch0_func, 469, 5, 3 },
+ { ahc_patch9_func, 469, 2, 2 },
+ { ahc_patch0_func, 471, 3, 1 },
+ { ahc_patch1_func, 476, 2, 2 },
+ { ahc_patch0_func, 478, 6, 3 },
+ { ahc_patch9_func, 478, 2, 2 },
+ { ahc_patch0_func, 480, 3, 1 },
+ { ahc_patch1_func, 486, 2, 2 },
+ { ahc_patch0_func, 488, 9, 7 },
+ { ahc_patch9_func, 488, 5, 6 },
+ { ahc_patch19_func, 488, 1, 2 },
+ { ahc_patch0_func, 489, 1, 1 },
+ { ahc_patch19_func, 491, 1, 2 },
+ { ahc_patch0_func, 492, 1, 1 },
+ { ahc_patch0_func, 493, 4, 1 },
+ { ahc_patch6_func, 498, 3, 2 },
+ { ahc_patch0_func, 501, 1, 1 },
+ { ahc_patch6_func, 511, 1, 2 },
+ { ahc_patch0_func, 512, 1, 1 },
+ { ahc_patch20_func, 549, 7, 1 },
+ { ahc_patch3_func, 584, 1, 2 },
+ { ahc_patch0_func, 585, 1, 1 },
+ { ahc_patch21_func, 588, 1, 1 },
+ { ahc_patch8_func, 590, 106, 33 },
+ { ahc_patch4_func, 592, 1, 1 },
+ { ahc_patch1_func, 598, 2, 2 },
+ { ahc_patch0_func, 600, 1, 1 },
+ { ahc_patch1_func, 603, 1, 2 },
+ { ahc_patch0_func, 604, 1, 1 },
+ { ahc_patch9_func, 605, 3, 3 },
+ { ahc_patch15_func, 606, 1, 1 },
+ { ahc_patch0_func, 608, 4, 1 },
+ { ahc_patch19_func, 617, 2, 2 },
+ { ahc_patch0_func, 619, 1, 1 },
+ { ahc_patch19_func, 623, 10, 3 },
+ { ahc_patch5_func, 625, 8, 1 },
+ { ahc_patch0_func, 633, 9, 2 },
+ { ahc_patch5_func, 634, 8, 1 },
+ { ahc_patch4_func, 644, 1, 2 },
+ { ahc_patch0_func, 645, 1, 1 },
+ { ahc_patch19_func, 646, 1, 2 },
+ { ahc_patch0_func, 647, 3, 2 },
+ { ahc_patch4_func, 649, 1, 1 },
+ { ahc_patch5_func, 650, 1, 1 },
+ { ahc_patch5_func, 653, 1, 1 },
+ { ahc_patch5_func, 655, 1, 1 },
+ { ahc_patch4_func, 657, 2, 2 },
+ { ahc_patch0_func, 659, 2, 1 },
+ { ahc_patch5_func, 661, 1, 1 },
+ { ahc_patch5_func, 664, 1, 1 },
+ { ahc_patch5_func, 667, 1, 1 },
+ { ahc_patch19_func, 671, 1, 1 },
+ { ahc_patch19_func, 674, 1, 1 },
+ { ahc_patch4_func, 680, 1, 1 },
+ { ahc_patch6_func, 683, 1, 2 },
+ { ahc_patch0_func, 684, 1, 1 },
+ { ahc_patch7_func, 696, 16, 1 },
+ { ahc_patch4_func, 712, 20, 1 },
+ { ahc_patch9_func, 733, 4, 2 },
+ { ahc_patch0_func, 737, 4, 1 },
+ { ahc_patch9_func, 741, 4, 2 },
+ { ahc_patch0_func, 745, 3, 1 },
+ { ahc_patch6_func, 751, 1, 1 },
+ { ahc_patch22_func, 753, 14, 1 },
+ { ahc_patch7_func, 767, 3, 1 },
+ { ahc_patch9_func, 779, 24, 8 },
+ { ahc_patch19_func, 783, 1, 2 },
+ { ahc_patch0_func, 784, 1, 1 },
+ { ahc_patch15_func, 789, 4, 2 },
+ { ahc_patch0_func, 793, 7, 3 },
+ { ahc_patch23_func, 793, 5, 2 },
+ { ahc_patch0_func, 798, 2, 1 },
+ { ahc_patch0_func, 803, 42, 3 },
+ { ahc_patch18_func, 815, 18, 2 },
+ { ahc_patch0_func, 833, 1, 1 },
+ { ahc_patch4_func, 857, 1, 1 },
+ { ahc_patch4_func, 858, 3, 2 },
+ { ahc_patch0_func, 861, 1, 1 },
+ { ahc_patch13_func, 862, 3, 1 },
+ { ahc_patch4_func, 865, 12, 1 }
};
static struct cs {
@@ -1296,11 +1297,11 @@ static struct cs {
} critical_sections[] = {
{ 11, 18 },
{ 21, 30 },
- { 711, 727 },
- { 857, 860 },
- { 864, 870 },
- { 872, 874 },
- { 874, 876 }
+ { 712, 728 },
+ { 858, 861 },
+ { 865, 871 },
+ { 873, 875 },
+ { 875, 877 }
};
static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
index 7c5a6db0e672..828ae3d9a510 100644
--- a/drivers/scsi/aic7xxx/aiclib.c
+++ b/drivers/scsi/aic7xxx/aiclib.c
@@ -30,1382 +30,5 @@
* $Id$
*/
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-
-/* Core SCSI definitions */
-#include <scsi/scsi_host.h>
#include "aiclib.h"
-#include "cam.h"
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* FALSE */
-#ifndef TRUE
-#define TRUE 1
-#endif /* TRUE */
-#ifndef ERESTART
-#define ERESTART -1 /* restart syscall */
-#endif
-#ifndef EJUSTRETURN
-#define EJUSTRETURN -2 /* don't modify regs, just return */
-#endif
-
-static int ascentrycomp(const void *key, const void *member);
-static int senseentrycomp(const void *key, const void *member);
-static void fetchtableentries(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *,
- const struct sense_key_table_entry **,
- const struct asc_table_entry **);
-static void * scsibsearch(const void *key, const void *base, size_t nmemb,
- size_t size,
- int (*compar)(const void *, const void *));
-typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
-static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern,
- int str_len);
-static caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table,
- int num_entries, int entry_size,
- cam_quirkmatch_t *comp_func);
-
-#define SCSI_NO_SENSE_STRINGS 1
-#if !defined(SCSI_NO_SENSE_STRINGS)
-#define SST(asc, ascq, action, desc) \
- asc, ascq, action, desc
-#else
-static const char empty_string[] = "";
-
-#define SST(asc, ascq, action, desc) \
- asc, ascq, action, empty_string
-#endif
-
-static const struct sense_key_table_entry sense_key_table[] =
-{
- { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
- { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
- {
- SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
- "NOT READY"
- },
- { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
- { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
- { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
- { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
- { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
- { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
- { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
- { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
- { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
- { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
- { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
- { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
- { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
-};
-
-static const int sense_key_table_size =
- sizeof(sense_key_table)/sizeof(sense_key_table[0]);
-
-static struct asc_table_entry quantum_fireball_entries[] = {
- {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, initializing cmd. required")}
-};
-
-static struct asc_table_entry sony_mo_entries[] = {
- {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, cause not reportable")}
-};
-
-static struct scsi_sense_quirk_entry sense_quirk_table[] = {
- {
- /*
- * The Quantum Fireball ST and SE like to return 0x04 0x0b when
- * they really should return 0x04 0x02. 0x04,0x0b isn't
- * defined in any SCSI spec, and it isn't mentioned in the
- * hardware manual for these drives.
- */
- {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
- /*num_sense_keys*/0,
- sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
- /*sense key entries*/NULL,
- quantum_fireball_entries
- },
- {
- /*
- * This Sony MO drive likes to return 0x04, 0x00 when it
- * isn't spun up.
- */
- {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
- /*num_sense_keys*/0,
- sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
- /*sense key entries*/NULL,
- sony_mo_entries
- }
-};
-
-static const int sense_quirk_table_size =
- sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
-
-static struct asc_table_entry asc_table[] = {
-/*
- * From File: ASC-NUM.TXT
- * SCSI ASC/ASCQ Assignments
- * Numeric Sorted Listing
- * as of 5/12/97
- *
- * D - DIRECT ACCESS DEVICE (SBC) device column key
- * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
- * . L - PRINTER DEVICE (SSC) blank = reserved
- * . P - PROCESSOR DEVICE (SPC) not blank = allowed
- * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
- * . . R - CD DEVICE (MMC)
- * . . S - SCANNER DEVICE (SGC)
- * . . .O - OPTICAL MEMORY DEVICE (SBC)
- * . . . M - MEDIA CHANGER DEVICE (SMC)
- * . . . C - COMMUNICATION DEVICE (SSC)
- * . . . .A - STORAGE ARRAY DEVICE (SCC)
- * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
- * DTLPWRSOMCAE ASC ASCQ Action Description
- * ------------ ---- ---- ------ -----------------------------------*/
-/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
- "No additional sense information") },
-/* T S */{SST(0x00, 0x01, SS_RDEF,
- "Filemark detected") },
-/* T S */{SST(0x00, 0x02, SS_RDEF,
- "End-of-partition/medium detected") },
-/* T */{SST(0x00, 0x03, SS_RDEF,
- "Setmark detected") },
-/* T S */{SST(0x00, 0x04, SS_RDEF,
- "Beginning-of-partition/medium detected") },
-/* T S */{SST(0x00, 0x05, SS_RDEF,
- "End-of-data detected") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
- "I/O process terminated") },
-/* R */{SST(0x00, 0x11, SS_FATAL|EBUSY,
- "Audio play operation in progress") },
-/* R */{SST(0x00, 0x12, SS_NOP,
- "Audio play operation paused") },
-/* R */{SST(0x00, 0x13, SS_NOP,
- "Audio play operation successfully completed") },
-/* R */{SST(0x00, 0x14, SS_RDEF,
- "Audio play operation stopped due to error") },
-/* R */{SST(0x00, 0x15, SS_NOP,
- "No current audio status to return") },
-/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
- "Operation in progress") },
-/* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
- "Cleaning requested") },
-/* D W O */{SST(0x01, 0x00, SS_RDEF,
- "No index/sector signal") },
-/* D WR OM */{SST(0x02, 0x00, SS_RDEF,
- "No seek complete") },
-/* DTL W SO */{SST(0x03, 0x00, SS_RDEF,
- "Peripheral device write fault") },
-/* T */{SST(0x03, 0x01, SS_RDEF,
- "No write current") },
-/* T */{SST(0x03, 0x02, SS_RDEF,
- "Excessive write errors") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x00,
- SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
- "Logical unit not ready, cause not reportable") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x01,
- SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
- "Logical unit is in process of becoming ready") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
- "Logical unit not ready, initializing cmd. required") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
- "Logical unit not ready, manual intervention required")},
-/* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY,
- "Logical unit not ready, format in progress") },
-/* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY,
- "Logical unit not ready, rebuild in progress") },
-/* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY,
- "Logical unit not ready, recalculation in progress") },
-/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
- "Logical unit not ready, operation in progress") },
-/* R */{SST(0x04, 0x08, SS_FATAL|EBUSY,
- "Logical unit not ready, long write in progress") },
-/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
- "Logical unit does not respond to selection") },
-/* D WR OM */{SST(0x06, 0x00, SS_RDEF,
- "No reference position found") },
-/* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF,
- "Multiple peripheral devices selected") },
-/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
- "Logical unit communication failure") },
-/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
- "Logical unit communication time-out") },
-/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
- "Logical unit communication parity error") },
-/* DT R OM */{SST(0x08, 0x03, SS_RDEF,
- "Logical unit communication crc error (ultra-dma/32)")},
-/* DT WR O */{SST(0x09, 0x00, SS_RDEF,
- "Track following error") },
-/* WR O */{SST(0x09, 0x01, SS_RDEF,
- "Tracking servo failure") },
-/* WR O */{SST(0x09, 0x02, SS_RDEF,
- "Focus servo failure") },
-/* WR O */{SST(0x09, 0x03, SS_RDEF,
- "Spindle servo failure") },
-/* DT WR O */{SST(0x09, 0x04, SS_RDEF,
- "Head select fault") },
-/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
- "Error log overflow") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
- "Warning") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
- "Specified temperature exceeded") },
-/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
- "Enclosure degraded") },
-/* T RS */{SST(0x0C, 0x00, SS_RDEF,
- "Write error") },
-/* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Write error - recovered with auto reallocation") },
-/* D W O */{SST(0x0C, 0x02, SS_RDEF,
- "Write error - auto reallocation failed") },
-/* D W O */{SST(0x0C, 0x03, SS_RDEF,
- "Write error - recommend reassignment") },
-/* DT W O */{SST(0x0C, 0x04, SS_RDEF,
- "Compression check miscompare error") },
-/* DT W O */{SST(0x0C, 0x05, SS_RDEF,
- "Data expansion occurred during compression") },
-/* DT W O */{SST(0x0C, 0x06, SS_RDEF,
- "Block not compressible") },
-/* R */{SST(0x0C, 0x07, SS_RDEF,
- "Write error - recovery needed") },
-/* R */{SST(0x0C, 0x08, SS_RDEF,
- "Write error - recovery failed") },
-/* R */{SST(0x0C, 0x09, SS_RDEF,
- "Write error - loss of streaming") },
-/* R */{SST(0x0C, 0x0A, SS_RDEF,
- "Write error - padding blocks added") },
-/* D W O */{SST(0x10, 0x00, SS_RDEF,
- "ID CRC or ECC error") },
-/* DT WRSO */{SST(0x11, 0x00, SS_RDEF,
- "Unrecovered read error") },
-/* DT W SO */{SST(0x11, 0x01, SS_RDEF,
- "Read retries exhausted") },
-/* DT W SO */{SST(0x11, 0x02, SS_RDEF,
- "Error too long to correct") },
-/* DT W SO */{SST(0x11, 0x03, SS_RDEF,
- "Multiple read errors") },
-/* D W O */{SST(0x11, 0x04, SS_RDEF,
- "Unrecovered read error - auto reallocate failed") },
-/* WR O */{SST(0x11, 0x05, SS_RDEF,
- "L-EC uncorrectable error") },
-/* WR O */{SST(0x11, 0x06, SS_RDEF,
- "CIRC unrecovered error") },
-/* W O */{SST(0x11, 0x07, SS_RDEF,
- "Data re-synchronization error") },
-/* T */{SST(0x11, 0x08, SS_RDEF,
- "Incomplete block read") },
-/* T */{SST(0x11, 0x09, SS_RDEF,
- "No gap found") },
-/* DT O */{SST(0x11, 0x0A, SS_RDEF,
- "Miscorrected error") },
-/* D W O */{SST(0x11, 0x0B, SS_RDEF,
- "Unrecovered read error - recommend reassignment") },
-/* D W O */{SST(0x11, 0x0C, SS_RDEF,
- "Unrecovered read error - recommend rewrite the data")},
-/* DT WR O */{SST(0x11, 0x0D, SS_RDEF,
- "De-compression CRC error") },
-/* DT WR O */{SST(0x11, 0x0E, SS_RDEF,
- "Cannot decompress using declared algorithm") },
-/* R */{SST(0x11, 0x0F, SS_RDEF,
- "Error reading UPC/EAN number") },
-/* R */{SST(0x11, 0x10, SS_RDEF,
- "Error reading ISRC number") },
-/* R */{SST(0x11, 0x11, SS_RDEF,
- "Read error - loss of streaming") },
-/* D W O */{SST(0x12, 0x00, SS_RDEF,
- "Address mark not found for id field") },
-/* D W O */{SST(0x13, 0x00, SS_RDEF,
- "Address mark not found for data field") },
-/* DTL WRSO */{SST(0x14, 0x00, SS_RDEF,
- "Recorded entity not found") },
-/* DT WR O */{SST(0x14, 0x01, SS_RDEF,
- "Record not found") },
-/* T */{SST(0x14, 0x02, SS_RDEF,
- "Filemark or setmark not found") },
-/* T */{SST(0x14, 0x03, SS_RDEF,
- "End-of-data not found") },
-/* T */{SST(0x14, 0x04, SS_RDEF,
- "Block sequence error") },
-/* DT W O */{SST(0x14, 0x05, SS_RDEF,
- "Record not found - recommend reassignment") },
-/* DT W O */{SST(0x14, 0x06, SS_RDEF,
- "Record not found - data auto-reallocated") },
-/* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF,
- "Random positioning error") },
-/* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF,
- "Mechanical positioning error") },
-/* DT WR O */{SST(0x15, 0x02, SS_RDEF,
- "Positioning error detected by read of medium") },
-/* D W O */{SST(0x16, 0x00, SS_RDEF,
- "Data synchronization mark error") },
-/* D W O */{SST(0x16, 0x01, SS_RDEF,
- "Data sync error - data rewritten") },
-/* D W O */{SST(0x16, 0x02, SS_RDEF,
- "Data sync error - recommend rewrite") },
-/* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Data sync error - data auto-reallocated") },
-/* D W O */{SST(0x16, 0x04, SS_RDEF,
- "Data sync error - recommend reassignment") },
-/* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with no error correction applied") },
-/* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with retries") },
-/* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with positive head offset") },
-/* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with negative head offset") },
-/* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with retries and/or CIRC applied") },
-/* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data using previous sector id") },
-/* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - data auto-reallocated") },
-/* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - recommend reassignment")},
-/* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - recommend rewrite") },
-/* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data without ECC - data rewritten") },
-/* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with error correction applied") },
-/* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with error corr. & retries applied") },
-/* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - data auto-reallocated") },
-/* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with CIRC") },
-/* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with L-EC") },
-/* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - recommend reassignment") },
-/* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data - recommend rewrite") },
-/* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered data with ECC - data rewritten") },
-/* D O */{SST(0x19, 0x00, SS_RDEF,
- "Defect list error") },
-/* D O */{SST(0x19, 0x01, SS_RDEF,
- "Defect list not available") },
-/* D O */{SST(0x19, 0x02, SS_RDEF,
- "Defect list error in primary list") },
-/* D O */{SST(0x19, 0x03, SS_RDEF,
- "Defect list error in grown list") },
-/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
- "Parameter list length error") },
-/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
- "Synchronous data transfer error") },
-/* D O */{SST(0x1C, 0x00, SS_RDEF,
- "Defect list not found") },
-/* D O */{SST(0x1C, 0x01, SS_RDEF,
- "Primary defect list not found") },
-/* D O */{SST(0x1C, 0x02, SS_RDEF,
- "Grown defect list not found") },
-/* D W O */{SST(0x1D, 0x00, SS_FATAL,
- "Miscompare during verify operation" )},
-/* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
- "Recovered id with ecc correction") },
-/* D O */{SST(0x1F, 0x00, SS_RDEF,
- "Partial defect list transfer") },
-/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
- "Invalid command operation code") },
-/* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL,
- "Logical block address out of range" )},
-/* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL,
- "Invalid element address") },
-/* D */{SST(0x22, 0x00, SS_FATAL|EINVAL,
- "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
-/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
- "Invalid field in CDB") },
-/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
- "Logical unit not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
- "Invalid field in parameter list") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
- "Parameter not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
- "Parameter value invalid") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
- "Threshold parameters not supported") },
-/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
- "Invalid release of active persistent reservation") },
-/* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES,
- "Write protected") },
-/* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES,
- "Hardware write protected") },
-/* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES,
- "Logical unit software write protected") },
-/* T */{SST(0x27, 0x03, SS_FATAL|EACCES,
- "Associated write protect") },
-/* T */{SST(0x27, 0x04, SS_FATAL|EACCES,
- "Persistent write protect") },
-/* T */{SST(0x27, 0x05, SS_FATAL|EACCES,
- "Permanent write protect") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF,
- "Not ready to ready change, medium may have changed") },
-/* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
- "Import or export element accessed") },
-/*
- * XXX JGibbs - All of these should use the same errno, but I don't think
- * ENXIO is the correct choice. Should we borrow from the networking
- * errnos? ECONNRESET anyone?
- */
-/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF,
- "Power on, reset, or bus device reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
- "Power on occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
- "Scsi bus reset occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
- "Bus device reset function occurred") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
- "Device internal reset") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
- "Transceiver mode changed to single-ended") },
-/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
- "Transceiver mode changed to LVD") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
- "Parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
- "Mode parameters changed") },
-/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
- "Log parameters changed") },
-/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
- "Reservations preempted") },
-/* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF,
- "Copy cannot execute since host cannot disconnect") },
-/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
- "Command sequence error") },
-/* S */{SST(0x2C, 0x01, SS_RDEF,
- "Too many windows specified") },
-/* S */{SST(0x2C, 0x02, SS_RDEF,
- "Invalid combination of windows specified") },
-/* R */{SST(0x2C, 0x03, SS_RDEF,
- "Current program area is not empty") },
-/* R */{SST(0x2C, 0x04, SS_RDEF,
- "Current program area is empty") },
-/* T */{SST(0x2D, 0x00, SS_RDEF,
- "Overwrite error on update in place") },
-/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
- "Commands cleared by another initiator") },
-/* DT WR OM */{SST(0x30, 0x00, SS_RDEF,
- "Incompatible medium installed") },
-/* DT WR O */{SST(0x30, 0x01, SS_RDEF,
- "Cannot read medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x02, SS_RDEF,
- "Cannot read medium - incompatible format") },
-/* DT */{SST(0x30, 0x03, SS_RDEF,
- "Cleaning cartridge installed") },
-/* DT WR O */{SST(0x30, 0x04, SS_RDEF,
- "Cannot write medium - unknown format") },
-/* DT WR O */{SST(0x30, 0x05, SS_RDEF,
- "Cannot write medium - incompatible format") },
-/* DT W O */{SST(0x30, 0x06, SS_RDEF,
- "Cannot format medium - incompatible medium") },
-/* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
- "Cleaning failure") },
-/* R */{SST(0x30, 0x08, SS_RDEF,
- "Cannot write - application code mismatch") },
-/* R */{SST(0x30, 0x09, SS_RDEF,
- "Current session not fixated for append") },
-/* DT WR O */{SST(0x31, 0x00, SS_RDEF,
- "Medium format corrupted") },
-/* D L R O */{SST(0x31, 0x01, SS_RDEF,
- "Format command failed") },
-/* D W O */{SST(0x32, 0x00, SS_RDEF,
- "No defect spare location available") },
-/* D W O */{SST(0x32, 0x01, SS_RDEF,
- "Defect list update failure") },
-/* T */{SST(0x33, 0x00, SS_RDEF,
- "Tape length error") },
-/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
- "Enclosure failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
- "Enclosure services failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
- "Unsupported enclosure function") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
- "Enclosure services unavailable") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
- "Enclosure services transfer failure") },
-/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
- "Enclosure services transfer refused") },
-/* L */{SST(0x36, 0x00, SS_RDEF,
- "Ribbon, ink, or toner failure") },
-/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
- "Rounded parameter") },
-/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
- "Saving parameters not supported") },
-/* DTL WRSOM */{SST(0x3A, 0x00, SS_NOP,
- "Medium not present") },
-/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
- "Medium not present - tray closed") },
-/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
- "Medium not present - tray open") },
-/* DT WR OM */{SST(0x3A, 0x03, SS_NOP,
- "Medium not present - Loadable") },
-/* DT WR OM */{SST(0x3A, 0x04, SS_NOP,
- "Medium not present - medium auxiliary "
- "memory accessible") },
-/* DT WR OM */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */
-/* TL */{SST(0x3B, 0x00, SS_RDEF,
- "Sequential positioning error") },
-/* T */{SST(0x3B, 0x01, SS_RDEF,
- "Tape position error at beginning-of-medium") },
-/* T */{SST(0x3B, 0x02, SS_RDEF,
- "Tape position error at end-of-medium") },
-/* L */{SST(0x3B, 0x03, SS_RDEF,
- "Tape or electronic vertical forms unit not ready") },
-/* L */{SST(0x3B, 0x04, SS_RDEF,
- "Slew failure") },
-/* L */{SST(0x3B, 0x05, SS_RDEF,
- "Paper jam") },
-/* L */{SST(0x3B, 0x06, SS_RDEF,
- "Failed to sense top-of-form") },
-/* L */{SST(0x3B, 0x07, SS_RDEF,
- "Failed to sense bottom-of-form") },
-/* T */{SST(0x3B, 0x08, SS_RDEF,
- "Reposition error") },
-/* S */{SST(0x3B, 0x09, SS_RDEF,
- "Read past end of medium") },
-/* S */{SST(0x3B, 0x0A, SS_RDEF,
- "Read past beginning of medium") },
-/* S */{SST(0x3B, 0x0B, SS_RDEF,
- "Position past end of medium") },
-/* T S */{SST(0x3B, 0x0C, SS_RDEF,
- "Position past beginning of medium") },
-/* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
- "Medium destination element full") },
-/* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF,
- "Medium source element empty") },
-/* R */{SST(0x3B, 0x0F, SS_RDEF,
- "End of medium reached") },
-/* DT WR OM */{SST(0x3B, 0x11, SS_RDEF,
- "Medium magazine not accessible") },
-/* DT WR OM */{SST(0x3B, 0x12, SS_RDEF,
- "Medium magazine removed") },
-/* DT WR OM */{SST(0x3B, 0x13, SS_RDEF,
- "Medium magazine inserted") },
-/* DT WR OM */{SST(0x3B, 0x14, SS_RDEF,
- "Medium magazine locked") },
-/* DT WR OM */{SST(0x3B, 0x15, SS_RDEF,
- "Medium magazine unlocked") },
-/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
- "Invalid bits in identify message") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
- "Logical unit has not self-configured yet") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
- "Logical unit failure") },
-/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
- "Timeout on logical unit") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
- "Target operating conditions have changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
- "Microcode has been changed") },
-/* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF,
- "Changed operating definition") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT,
- "Inquiry data has changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
- "Component device attached") },
-/* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
- "Device identifier changed") },
-/* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
- "Redundancy group created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
- "Redundancy group deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
- "Spare created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
- "Spare deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
- "Volume set created or modified") },
-/* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
- "Volume set deleted") },
-/* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
- "Volume set deassigned") },
-/* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
- "Volume set reassigned") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF,
- "Reported luns data has changed") },
-/* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT
- | SSQ_DELAY_RANDOM|EBUSY,
- "Echo buffer overwritten") },
-/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") },
-/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF,
- "Medium auxiliary memory accessible") },
-/* D */{SST(0x40, 0x00, SS_RDEF,
- "Ram failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
- "Diagnostic failure: ASCQ = Component ID") },
-/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) },/* Range 0x80->0xFF */
-/* D */{SST(0x41, 0x00, SS_RDEF,
- "Data path failure") }, /* deprecated - use 40 NN instead */
-/* D */{SST(0x42, 0x00, SS_RDEF,
- "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
-/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
- "Message error") },
-/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
- "Internal target failure") },
-/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
- "Select or reselect failure") },
-/* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF,
- "Unsuccessful soft reset") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK,
- "SCSI parity error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK,
- "Data Phase CRC error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK,
- "SCSI parity error detected during ST data phase") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK,
- "Information Unit iuCRC error") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK,
- "Asynchronous information protection error detected") },
-/* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK,
- "Protocol server CRC error") },
-/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK,
- "Initiator detected error message received") },
-/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
- "Invalid message error") },
-/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
- "Command phase error") },
-/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
- "Data phase error") },
-/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
- "Logical unit failed self-configuration") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
- "Tagged overlapped commands: ASCQ = Queue tag ID") },
-/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL)}, /* Range 0x00->0xFF */
-/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
- "Overlapped commands attempted") },
-/* T */{SST(0x50, 0x00, SS_RDEF,
- "Write append error") },
-/* T */{SST(0x50, 0x01, SS_RDEF,
- "Write append position error") },
-/* T */{SST(0x50, 0x02, SS_RDEF,
- "Position error related to timing") },
-/* T O */{SST(0x51, 0x00, SS_RDEF,
- "Erase failure") },
-/* T */{SST(0x52, 0x00, SS_RDEF,
- "Cartridge fault") },
-/* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF,
- "Media load or eject failed") },
-/* T */{SST(0x53, 0x01, SS_RDEF,
- "Unload tape failure") },
-/* DT WR OM */{SST(0x53, 0x02, SS_RDEF,
- "Medium removal prevented") },
-/* P */{SST(0x54, 0x00, SS_RDEF,
- "Scsi to host system interface failure") },
-/* P */{SST(0x55, 0x00, SS_RDEF,
- "System resource failure") },
-/* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
- "System buffer full") },
-/* R */{SST(0x57, 0x00, SS_RDEF,
- "Unable to recover table-of-contents") },
-/* O */{SST(0x58, 0x00, SS_RDEF,
- "Generation does not exist") },
-/* O */{SST(0x59, 0x00, SS_RDEF,
- "Updated block read") },
-/* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF,
- "Operator request or state change input") },
-/* DT WR OM */{SST(0x5A, 0x01, SS_RDEF,
- "Operator medium removal request") },
-/* DT W O */{SST(0x5A, 0x02, SS_RDEF,
- "Operator selected write protect") },
-/* DT W O */{SST(0x5A, 0x03, SS_RDEF,
- "Operator selected write permit") },
-/* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF,
- "Log exception") },
-/* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF,
- "Threshold condition met") },
-/* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF,
- "Log counter at maximum") },
-/* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF,
- "Log list codes exhausted") },
-/* D O */{SST(0x5C, 0x00, SS_RDEF,
- "RPL status change") },
-/* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
- "Spindles synchronized") },
-/* D O */{SST(0x5C, 0x02, SS_RDEF,
- "Spindles not synchronized") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
- "Failure prediction threshold exceeded") },
-/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
- "Failure prediction threshold exceeded (false)") },
-/* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF,
- "Low power condition on") },
-/* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF,
- "Idle condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF,
- "Standby condition activated by timer") },
-/* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF,
- "Idle condition activated by command") },
-/* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF,
- "Standby condition activated by command") },
-/* S */{SST(0x60, 0x00, SS_RDEF,
- "Lamp failure") },
-/* S */{SST(0x61, 0x00, SS_RDEF,
- "Video acquisition error") },
-/* S */{SST(0x61, 0x01, SS_RDEF,
- "Unable to acquire video") },
-/* S */{SST(0x61, 0x02, SS_RDEF,
- "Out of focus") },
-/* S */{SST(0x62, 0x00, SS_RDEF,
- "Scan head positioning error") },
-/* R */{SST(0x63, 0x00, SS_RDEF,
- "End of user area encountered on this track") },
-/* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
- "Packet does not fit in available space") },
-/* R */{SST(0x64, 0x00, SS_RDEF,
- "Illegal mode for this track") },
-/* R */{SST(0x64, 0x01, SS_RDEF,
- "Invalid packet size") },
-/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
- "Voltage fault") },
-/* S */{SST(0x66, 0x00, SS_RDEF,
- "Automatic document feeder cover up") },
-/* S */{SST(0x66, 0x01, SS_RDEF,
- "Automatic document feeder lift up") },
-/* S */{SST(0x66, 0x02, SS_RDEF,
- "Document jam in automatic document feeder") },
-/* S */{SST(0x66, 0x03, SS_RDEF,
- "Document miss feed automatic in document feeder") },
-/* A */{SST(0x67, 0x00, SS_RDEF,
- "Configuration failure") },
-/* A */{SST(0x67, 0x01, SS_RDEF,
- "Configuration of incapable logical units failed") },
-/* A */{SST(0x67, 0x02, SS_RDEF,
- "Add logical unit failed") },
-/* A */{SST(0x67, 0x03, SS_RDEF,
- "Modification of logical unit failed") },
-/* A */{SST(0x67, 0x04, SS_RDEF,
- "Exchange of logical unit failed") },
-/* A */{SST(0x67, 0x05, SS_RDEF,
- "Remove of logical unit failed") },
-/* A */{SST(0x67, 0x06, SS_RDEF,
- "Attachment of logical unit failed") },
-/* A */{SST(0x67, 0x07, SS_RDEF,
- "Creation of logical unit failed") },
-/* A */{SST(0x68, 0x00, SS_RDEF,
- "Logical unit not configured") },
-/* A */{SST(0x69, 0x00, SS_RDEF,
- "Data loss on logical unit") },
-/* A */{SST(0x69, 0x01, SS_RDEF,
- "Multiple logical unit failures") },
-/* A */{SST(0x69, 0x02, SS_RDEF,
- "Parity/data mismatch") },
-/* A */{SST(0x6A, 0x00, SS_RDEF,
- "Informational, refer to log") },
-/* A */{SST(0x6B, 0x00, SS_RDEF,
- "State change has occurred") },
-/* A */{SST(0x6B, 0x01, SS_RDEF,
- "Redundancy level got better") },
-/* A */{SST(0x6B, 0x02, SS_RDEF,
- "Redundancy level got worse") },
-/* A */{SST(0x6C, 0x00, SS_RDEF,
- "Rebuild failure occurred") },
-/* A */{SST(0x6D, 0x00, SS_RDEF,
- "Recalculate failure occurred") },
-/* A */{SST(0x6E, 0x00, SS_RDEF,
- "Command to logical unit failed") },
-/* T */{SST(0x70, 0x00, SS_RDEF,
- "Decompression exception short: ASCQ = Algorithm ID") },
-/* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) }, /* Range 0x00 -> 0xFF */
-/* T */{SST(0x71, 0x00, SS_RDEF,
- "Decompression exception long: ASCQ = Algorithm ID") },
-/* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
- NULL) }, /* Range 0x00 -> 0xFF */
-/* R */{SST(0x72, 0x00, SS_RDEF,
- "Session fixation error") },
-/* R */{SST(0x72, 0x01, SS_RDEF,
- "Session fixation error writing lead-in") },
-/* R */{SST(0x72, 0x02, SS_RDEF,
- "Session fixation error writing lead-out") },
-/* R */{SST(0x72, 0x03, SS_RDEF,
- "Session fixation error - incomplete track in session") },
-/* R */{SST(0x72, 0x04, SS_RDEF,
- "Empty or partially written reserved track") },
-/* R */{SST(0x73, 0x00, SS_RDEF,
- "CD control error") },
-/* R */{SST(0x73, 0x01, SS_RDEF,
- "Power calibration area almost full") },
-/* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
- "Power calibration area is full") },
-/* R */{SST(0x73, 0x03, SS_RDEF,
- "Power calibration area error") },
-/* R */{SST(0x73, 0x04, SS_RDEF,
- "Program memory area update failure") },
-/* R */{SST(0x73, 0x05, SS_RDEF,
- "program memory area is full") }
-};
-
-static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
-
-struct asc_key
-{
- int asc;
- int ascq;
-};
-
-static int
-ascentrycomp(const void *key, const void *member)
-{
- int asc;
- int ascq;
- const struct asc_table_entry *table_entry;
-
- asc = ((const struct asc_key *)key)->asc;
- ascq = ((const struct asc_key *)key)->ascq;
- table_entry = (const struct asc_table_entry *)member;
-
- if (asc >= table_entry->asc) {
-
- if (asc > table_entry->asc)
- return (1);
-
- if (ascq <= table_entry->ascq) {
- /* Check for ranges */
- if (ascq == table_entry->ascq
- || ((table_entry->action & SSQ_RANGE) != 0
- && ascq >= (table_entry - 1)->ascq))
- return (0);
- return (-1);
- }
- return (1);
- }
- return (-1);
-}
-
-static int
-senseentrycomp(const void *key, const void *member)
-{
- int sense_key;
- const struct sense_key_table_entry *table_entry;
-
- sense_key = *((const int *)key);
- table_entry = (const struct sense_key_table_entry *)member;
-
- if (sense_key >= table_entry->sense_key) {
- if (sense_key == table_entry->sense_key)
- return (0);
- return (1);
- }
- return (-1);
-}
-
-static void
-fetchtableentries(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *inq_data,
- const struct sense_key_table_entry **sense_entry,
- const struct asc_table_entry **asc_entry)
-{
- void *match;
- const struct asc_table_entry *asc_tables[2];
- const struct sense_key_table_entry *sense_tables[2];
- struct asc_key asc_ascq;
- size_t asc_tables_size[2];
- size_t sense_tables_size[2];
- int num_asc_tables;
- int num_sense_tables;
- int i;
-
- /* Default to failure */
- *sense_entry = NULL;
- *asc_entry = NULL;
- match = NULL;
- if (inq_data != NULL)
- match = cam_quirkmatch((void *)inq_data,
- (void *)sense_quirk_table,
- sense_quirk_table_size,
- sizeof(*sense_quirk_table),
- aic_inquiry_match);
-
- if (match != NULL) {
- struct scsi_sense_quirk_entry *quirk;
-
- quirk = (struct scsi_sense_quirk_entry *)match;
- asc_tables[0] = quirk->asc_info;
- asc_tables_size[0] = quirk->num_ascs;
- asc_tables[1] = asc_table;
- asc_tables_size[1] = asc_table_size;
- num_asc_tables = 2;
- sense_tables[0] = quirk->sense_key_info;
- sense_tables_size[0] = quirk->num_sense_keys;
- sense_tables[1] = sense_key_table;
- sense_tables_size[1] = sense_key_table_size;
- num_sense_tables = 2;
- } else {
- asc_tables[0] = asc_table;
- asc_tables_size[0] = asc_table_size;
- num_asc_tables = 1;
- sense_tables[0] = sense_key_table;
- sense_tables_size[0] = sense_key_table_size;
- num_sense_tables = 1;
- }
-
- asc_ascq.asc = asc;
- asc_ascq.ascq = ascq;
- for (i = 0; i < num_asc_tables; i++) {
- void *found_entry;
-
- found_entry = scsibsearch(&asc_ascq, asc_tables[i],
- asc_tables_size[i],
- sizeof(**asc_tables),
- ascentrycomp);
-
- if (found_entry) {
- *asc_entry = (struct asc_table_entry *)found_entry;
- break;
- }
- }
-
- for (i = 0; i < num_sense_tables; i++) {
- void *found_entry;
-
- found_entry = scsibsearch(&sense_key, sense_tables[i],
- sense_tables_size[i],
- sizeof(**sense_tables),
- senseentrycomp);
-
- if (found_entry) {
- *sense_entry =
- (struct sense_key_table_entry *)found_entry;
- break;
- }
- }
-}
-
-static void *
-scsibsearch(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *))
-{
- const void *entry;
- u_int l;
- u_int u;
- u_int m;
-
- l = -1;
- u = nmemb;
- while (l + 1 != u) {
- m = (l + u) / 2;
- entry = base + m * size;
- if (compar(key, entry) > 0)
- l = m;
- else
- u = m;
- }
-
- entry = base + u * size;
- if (u == nmemb
- || compar(key, entry) != 0)
- return (NULL);
-
- return ((void *)entry);
-}
-
-/*
- * Compare string with pattern, returning 0 on match.
- * Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name,
- * wildcard '?' matches a single non-space character.
- */
-static int
-cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
-{
-
- while (*pattern != '\0'&& str_len > 0) {
-
- if (*pattern == '*') {
- return (0);
- }
- if ((*pattern != *str)
- && (*pattern != '?' || *str == ' ')) {
- return (1);
- }
- pattern++;
- str++;
- str_len--;
- }
- while (str_len > 0 && *str++ == ' ')
- str_len--;
-
- return (str_len);
-}
-
-static caddr_t
-cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
- int entry_size, cam_quirkmatch_t *comp_func)
-{
- for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
- if ((*comp_func)(target, quirk_table) == 0)
- return (quirk_table);
- }
- return (NULL);
-}
-
-void
-aic_sense_desc(int sense_key, int asc, int ascq,
- struct scsi_inquiry_data *inq_data,
- const char **sense_key_desc, const char **asc_desc)
-{
- const struct asc_table_entry *asc_entry;
- const struct sense_key_table_entry *sense_entry;
-
- fetchtableentries(sense_key, asc, ascq,
- inq_data,
- &sense_entry,
- &asc_entry);
-
- *sense_key_desc = sense_entry->desc;
-
- if (asc_entry != NULL)
- *asc_desc = asc_entry->desc;
- else if (asc >= 0x80 && asc <= 0xff)
- *asc_desc = "Vendor Specific ASC";
- else if (ascq >= 0x80 && ascq <= 0xff)
- *asc_desc = "Vendor Specific ASCQ";
- else
- *asc_desc = "Reserved ASC/ASCQ pair";
-}
-
-/*
- * Given sense and device type information, return the appropriate action.
- * If we do not understand the specific error as identified by the ASC/ASCQ
- * pair, fall back on the more generic actions derived from the sense key.
- */
-aic_sense_action
-aic_sense_error_action(struct scsi_sense_data *sense_data,
- struct scsi_inquiry_data *inq_data, uint32_t sense_flags)
-{
- const struct asc_table_entry *asc_entry;
- const struct sense_key_table_entry *sense_entry;
- int error_code, sense_key, asc, ascq;
- aic_sense_action action;
-
- scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);
-
- if (error_code == SSD_DEFERRED_ERROR) {
- /*
- * XXX dufault@FreeBSD.org
- * This error doesn't relate to the command associated
- * with this request sense. A deferred error is an error
- * for a command that has already returned GOOD status
- * (see SCSI2 8.2.14.2).
- *
- * By my reading of that section, it looks like the current
- * command has been cancelled, we should now clean things up
- * (hopefully recovering any lost data) and then retry the
- * current command. There are two easy choices, both wrong:
- *
- * 1. Drop through (like we had been doing), thus treating
- * this as if the error were for the current command and
- * return and stop the current command.
- *
- * 2. Issue a retry (like I made it do) thus hopefully
- * recovering the current transfer, and ignoring the
- * fact that we've dropped a command.
- *
- * These should probably be handled in a device specific
- * sense handler or punted back up to a user mode daemon
- */
- action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
- } else {
- fetchtableentries(sense_key, asc, ascq,
- inq_data,
- &sense_entry,
- &asc_entry);
-
- /*
- * Override the 'No additional Sense' entry (0,0)
- * with the error action of the sense key.
- */
- if (asc_entry != NULL
- && (asc != 0 || ascq != 0))
- action = asc_entry->action;
- else
- action = sense_entry->action;
-
- if (sense_key == SSD_KEY_RECOVERED_ERROR) {
- /*
- * The action succeeded but the device wants
- * the user to know that some recovery action
- * was required.
- */
- action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
- action |= SS_NOP|SSQ_PRINT_SENSE;
- } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
- if ((sense_flags & SF_QUIET_IR) != 0)
- action &= ~SSQ_PRINT_SENSE;
- } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
- if ((sense_flags & SF_RETRY_UA) != 0
- && (action & SS_MASK) == SS_FAIL) {
- action &= ~(SS_MASK|SSQ_MASK);
- action |= SS_RETRY|SSQ_DECREMENT_COUNT|
- SSQ_PRINT_SENSE;
- }
- }
- }
-
- if ((sense_flags & SF_PRINT_ALWAYS) != 0)
- action |= SSQ_PRINT_SENSE;
- else if ((sense_flags & SF_NO_PRINT) != 0)
- action &= ~SSQ_PRINT_SENSE;
-
- return (action);
-}
-
-/*
- * Try make as good a match as possible with
- * available sub drivers
- */
-int
-aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
-{
- struct scsi_inquiry_pattern *entry;
- struct scsi_inquiry_data *inq;
-
- entry = (struct scsi_inquiry_pattern *)table_entry;
- inq = (struct scsi_inquiry_data *)inqbuffer;
-
- if (((SID_TYPE(inq) == entry->type)
- || (entry->type == T_ANY))
- && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
- : entry->media_type & SIP_MEDIA_FIXED)
- && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
- && (cam_strmatch(inq->product, entry->product,
- sizeof(inq->product)) == 0)
- && (cam_strmatch(inq->revision, entry->revision,
- sizeof(inq->revision)) == 0)) {
- return (0);
- }
- return (-1);
-}
-
-/*
- * Table of syncrates that don't follow the "divisible by 4"
- * rule. This table will be expanded in future SCSI specs.
- */
-static struct {
- u_int period_factor;
- u_int period; /* in 100ths of ns */
-} scsi_syncrates[] = {
- { 0x08, 625 }, /* FAST-160 */
- { 0x09, 1250 }, /* FAST-80 */
- { 0x0a, 2500 }, /* FAST-40 40MHz */
- { 0x0b, 3030 }, /* FAST-40 33MHz */
- { 0x0c, 5000 } /* FAST-20 */
-};
-
-/*
- * Return the frequency in kHz corresponding to the given
- * sync period factor.
- */
-u_int
-aic_calc_syncsrate(u_int period_factor)
-{
- int i;
- int num_syncrates;
-
- num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
- /* See if the period is in the "exception" table */
- for (i = 0; i < num_syncrates; i++) {
-
- if (period_factor == scsi_syncrates[i].period_factor) {
- /* Period in kHz */
- return (100000000 / scsi_syncrates[i].period);
- }
- }
-
- /*
- * Wasn't in the table, so use the standard
- * 4 times conversion.
- */
- return (10000000 / (period_factor * 4 * 10));
-}
-
-/*
- * Return speed in KB/s.
- */
-u_int
-aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate)
-{
- u_int freq;
-
- if (offset != 0 && period < min_rate)
- freq = aic_calc_syncsrate(period);
- else
- /* Roughly 3.3MB/s for async */
- freq = 3300;
- freq <<= width;
- return (freq);
-}
-
-uint32_t
-aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
- cam_status status, u_int scsi_status)
-{
- aic_sense_action err_action;
- int sense;
-
- sense = (cmd->result >> 24) == DRIVER_SENSE;
-
- switch (status) {
- case CAM_REQ_CMP:
- err_action = SS_NOP;
- break;
- case CAM_AUTOSENSE_FAIL:
- case CAM_SCSI_STATUS_ERROR:
-
- switch (scsi_status) {
- case SCSI_STATUS_OK:
- case SCSI_STATUS_COND_MET:
- case SCSI_STATUS_INTERMED:
- case SCSI_STATUS_INTERMED_COND_MET:
- err_action = SS_NOP;
- break;
- case SCSI_STATUS_CMD_TERMINATED:
- case SCSI_STATUS_CHECK_COND:
- if (sense != 0) {
- struct scsi_sense_data *sense;
-
- sense = (struct scsi_sense_data *)
- &cmd->sense_buffer;
- err_action =
- aic_sense_error_action(sense, inq_data, 0);
-
- } else {
- err_action = SS_RETRY|SSQ_FALLBACK
- | SSQ_DECREMENT_COUNT|EIO;
- }
- break;
- case SCSI_STATUS_QUEUE_FULL:
- case SCSI_STATUS_BUSY:
- err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY
- | SSQ_DECREMENT_COUNT|EBUSY;
- break;
- case SCSI_STATUS_RESERV_CONFLICT:
- default:
- err_action = SS_FAIL|EBUSY;
- break;
- }
- break;
- case CAM_CMD_TIMEOUT:
- case CAM_REQ_CMP_ERR:
- case CAM_UNEXP_BUSFREE:
- case CAM_UNCOR_PARITY:
- case CAM_DATA_RUN_ERR:
- err_action = SS_RETRY|SSQ_FALLBACK|EIO;
- break;
- case CAM_UA_ABORT:
- case CAM_UA_TERMIO:
- case CAM_MSG_REJECT_REC:
- case CAM_SEL_TIMEOUT:
- err_action = SS_FAIL|EIO;
- break;
- case CAM_REQ_INVALID:
- case CAM_PATH_INVALID:
- case CAM_DEV_NOT_THERE:
- case CAM_NO_HBA:
- case CAM_PROVIDE_FAIL:
- case CAM_REQ_TOO_BIG:
- case CAM_RESRC_UNAVAIL:
- case CAM_BUSY:
- default:
- /* panic?? These should never occur in our application. */
- err_action = SS_FAIL|EIO;
- break;
- case CAM_SCSI_BUS_RESET:
- case CAM_BDR_SENT:
- case CAM_REQUEUE_REQ:
- /* Unconditional requeue */
- err_action = SS_RETRY;
- break;
- }
-
- return (err_action);
-}
-
-char *
-aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
- aic_option_callback_t *callback, u_long callback_arg)
-{
- char *tok_end;
- char *tok_end2;
- int i;
- int instance;
- int targ;
- int done;
- char tok_list[] = {'.', ',', '{', '}', '\0'};
- /* All options use a ':' name/arg separator */
- if (*opt_arg != ':')
- return (opt_arg);
- opt_arg++;
- instance = -1;
- targ = -1;
- done = FALSE;
- /*
- * Restore separator that may be in
- * the middle of our option argument.
- */
- tok_end = strchr(opt_arg, '\0');
- if (tok_end < end)
- *tok_end = ',';
- while (!done) {
- switch (*opt_arg) {
- case '{':
- if (instance == -1) {
- instance = 0;
- } else {
- if (depth > 1) {
- if (targ == -1)
- targ = 0;
- } else {
- printf("Malformed Option %s\n",
- opt_name);
- done = TRUE;
- }
- }
- opt_arg++;
- break;
- case '}':
- if (targ != -1)
- targ = -1;
- else if (instance != -1)
- instance = -1;
- opt_arg++;
- break;
- case ',':
- case '.':
- if (instance == -1)
- done = TRUE;
- else if (targ >= 0)
- targ++;
- else if (instance >= 0)
- instance++;
- opt_arg++;
- break;
- case '\0':
- done = TRUE;
- break;
- default:
- tok_end = end;
- for (i = 0; tok_list[i]; i++) {
- tok_end2 = strchr(opt_arg, tok_list[i]);
- if ((tok_end2) && (tok_end2 < tok_end))
- tok_end = tok_end2;
- }
- callback(callback_arg, instance, targ,
- simple_strtol(opt_arg, NULL, 0));
- opt_arg = tok_end;
- break;
- }
- }
- return (opt_arg);
-}
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h
index bfe6f954d3c4..3bfbf0fe1ec2 100644
--- a/drivers/scsi/aic7xxx/aiclib.h
+++ b/drivers/scsi/aic7xxx/aiclib.h
@@ -57,121 +57,6 @@
#ifndef _AICLIB_H
#define _AICLIB_H
-/*
- * Linux Interrupt Support.
- */
-#ifndef IRQ_RETVAL
-typedef void irqreturn_t;
-#define IRQ_RETVAL(x)
-#endif
-
-/*
- * SCSI command format
- */
-
-/*
- * Define dome bits that are in ALL (or a lot of) scsi commands
- */
-#define SCSI_CTL_LINK 0x01
-#define SCSI_CTL_FLAG 0x02
-#define SCSI_CTL_VENDOR 0xC0
-#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
-#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
-
-#define SCSI_MAX_CDBLEN 16 /*
- * 16 byte commands are in the
- * SCSI-3 spec
- */
-/* 6byte CDBs special case 0 length to be 256 */
-#define SCSI_CDB6_LEN(len) ((len) == 0 ? 256 : len)
-
-/*
- * This type defines actions to be taken when a particular sense code is
- * received. Right now, these flags are only defined to take up 16 bits,
- * but can be expanded in the future if necessary.
- */
-typedef enum {
- SS_NOP = 0x000000, /* Do nothing */
- SS_RETRY = 0x010000, /* Retry the command */
- SS_FAIL = 0x020000, /* Bail out */
- SS_START = 0x030000, /* Send a Start Unit command to the device,
- * then retry the original command.
- */
- SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
- * device, then retry the original command.
- */
- SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
- * device, then retry the original command.
- */
- SS_INQ_REFRESH = 0x060000,
- SS_MASK = 0xff0000
-} aic_sense_action;
-
-typedef enum {
- SSQ_NONE = 0x0000,
- SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */
- SSQ_MANY = 0x0200, /* send lots of recovery commands */
- SSQ_RANGE = 0x0400, /*
- * This table entry represents the
- * end of a range of ASCQs that
- * have identical error actions
- * and text.
- */
- SSQ_PRINT_SENSE = 0x0800,
- SSQ_DELAY = 0x1000, /* Delay before retry. */
- SSQ_DELAY_RANDOM = 0x2000, /* Randomized delay before retry. */
- SSQ_FALLBACK = 0x4000, /* Do a speed fallback to recover */
- SSQ_MASK = 0xff00
-} aic_sense_action_qualifier;
-
-/* Mask for error status values */
-#define SS_ERRMASK 0xff
-
-/* The default, retyable, error action */
-#define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
-
-/* The retyable, error action, with table specified error code */
-#define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
-
-/* Fatal error action, with table specified error code */
-#define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE
-
-struct scsi_generic
-{
- uint8_t opcode;
- uint8_t bytes[11];
-};
-
-struct scsi_request_sense
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_test_unit_ready
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[3];
- uint8_t control;
-};
-
-struct scsi_send_diag
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SSD_UOL 0x01
-#define SSD_DOL 0x02
-#define SSD_SELFTEST 0x04
-#define SSD_PF 0x10
- uint8_t unused[1];
- uint8_t paramlen[2];
- uint8_t control;
-};
-
struct scsi_sense
{
uint8_t opcode;
@@ -181,537 +66,12 @@ struct scsi_sense
uint8_t control;
};
-struct scsi_inquiry
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SI_EVPD 0x01
- uint8_t page_code;
- uint8_t reserved;
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_sense_6
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SMS_DBD 0x08
- uint8_t page;
-#define SMS_PAGE_CODE 0x3F
-#define SMS_VENDOR_SPECIFIC_PAGE 0x00
-#define SMS_DISCONNECT_RECONNECT_PAGE 0x02
-#define SMS_PERIPHERAL_DEVICE_PAGE 0x09
-#define SMS_CONTROL_MODE_PAGE 0x0A
-#define SMS_ALL_PAGES_PAGE 0x3F
-#define SMS_PAGE_CTRL_MASK 0xC0
-#define SMS_PAGE_CTRL_CURRENT 0x00
-#define SMS_PAGE_CTRL_CHANGEABLE 0x40
-#define SMS_PAGE_CTRL_DEFAULT 0x80
-#define SMS_PAGE_CTRL_SAVED 0xC0
- uint8_t unused;
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_sense_10
-{
- uint8_t opcode;
- uint8_t byte2; /* same bits as small version */
- uint8_t page; /* same bits as small version */
- uint8_t unused[4];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_mode_select_6
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SMS_SP 0x01
-#define SMS_PF 0x10
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_mode_select_10
-{
- uint8_t opcode;
- uint8_t byte2; /* same bits as small version */
- uint8_t unused[5];
- uint8_t length[2];
- uint8_t control;
-};
-
-/*
- * When sending a mode select to a tape drive, the medium type must be 0.
- */
-struct scsi_mode_hdr_6
-{
- uint8_t datalen;
- uint8_t medium_type;
- uint8_t dev_specific;
- uint8_t block_descr_len;
-};
-
-struct scsi_mode_hdr_10
-{
- uint8_t datalen[2];
- uint8_t medium_type;
- uint8_t dev_specific;
- uint8_t reserved[2];
- uint8_t block_descr_len[2];
-};
-
-struct scsi_mode_block_descr
-{
- uint8_t density_code;
- uint8_t num_blocks[3];
- uint8_t reserved;
- uint8_t block_len[3];
-};
-
-struct scsi_log_sense
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SLS_SP 0x01
-#define SLS_PPC 0x02
- uint8_t page;
-#define SLS_PAGE_CODE 0x3F
-#define SLS_ALL_PAGES_PAGE 0x00
-#define SLS_OVERRUN_PAGE 0x01
-#define SLS_ERROR_WRITE_PAGE 0x02
-#define SLS_ERROR_READ_PAGE 0x03
-#define SLS_ERROR_READREVERSE_PAGE 0x04
-#define SLS_ERROR_VERIFY_PAGE 0x05
-#define SLS_ERROR_NONMEDIUM_PAGE 0x06
-#define SLS_ERROR_LASTN_PAGE 0x07
-#define SLS_PAGE_CTRL_MASK 0xC0
-#define SLS_PAGE_CTRL_THRESHOLD 0x00
-#define SLS_PAGE_CTRL_CUMULATIVE 0x40
-#define SLS_PAGE_CTRL_THRESH_DEFAULT 0x80
-#define SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0
- uint8_t reserved[2];
- uint8_t paramptr[2];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_log_select
-{
- uint8_t opcode;
- uint8_t byte2;
-/* SLS_SP 0x01 */
-#define SLS_PCR 0x02
- uint8_t page;
-/* SLS_PAGE_CTRL_MASK 0xC0 */
-/* SLS_PAGE_CTRL_THRESHOLD 0x00 */
-/* SLS_PAGE_CTRL_CUMULATIVE 0x40 */
-/* SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 */
-/* SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 */
- uint8_t reserved[4];
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_log_header
-{
- uint8_t page;
- uint8_t reserved;
- uint8_t datalen[2];
-};
-
-struct scsi_log_param_header {
- uint8_t param_code[2];
- uint8_t param_control;
-#define SLP_LP 0x01
-#define SLP_LBIN 0x02
-#define SLP_TMC_MASK 0x0C
-#define SLP_TMC_ALWAYS 0x00
-#define SLP_TMC_EQUAL 0x04
-#define SLP_TMC_NOTEQUAL 0x08
-#define SLP_TMC_GREATER 0x0C
-#define SLP_ETC 0x10
-#define SLP_TSD 0x20
-#define SLP_DS 0x40
-#define SLP_DU 0x80
- uint8_t param_len;
-};
-
-struct scsi_control_page {
- uint8_t page_code;
- uint8_t page_length;
- uint8_t rlec;
-#define SCB_RLEC 0x01 /*Report Log Exception Cond*/
- uint8_t queue_flags;
-#define SCP_QUEUE_ALG_MASK 0xF0
-#define SCP_QUEUE_ALG_RESTRICTED 0x00
-#define SCP_QUEUE_ALG_UNRESTRICTED 0x10
-#define SCP_QUEUE_ERR 0x02 /*Queued I/O aborted for CACs*/
-#define SCP_QUEUE_DQUE 0x01 /*Queued I/O disabled*/
- uint8_t eca_and_aen;
-#define SCP_EECA 0x80 /*Enable Extended CA*/
-#define SCP_RAENP 0x04 /*Ready AEN Permission*/
-#define SCP_UAAENP 0x02 /*UA AEN Permission*/
-#define SCP_EAENP 0x01 /*Error AEN Permission*/
- uint8_t reserved;
- uint8_t aen_holdoff_period[2];
-};
-
-struct scsi_reserve
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_release
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_prevent
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[2];
- uint8_t how;
- uint8_t control;
-};
-#define PR_PREVENT 0x01
-#define PR_ALLOW 0x00
-
-struct scsi_sync_cache
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t begin_lba[4];
- uint8_t reserved;
- uint8_t lb_count[2];
- uint8_t control;
-};
-
-
-struct scsi_changedef
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused1;
- uint8_t how;
- uint8_t unused[4];
- uint8_t datalen;
- uint8_t control;
-};
-
-struct scsi_read_buffer
-{
- uint8_t opcode;
- uint8_t byte2;
-#define RWB_MODE 0x07
-#define RWB_MODE_HDR_DATA 0x00
-#define RWB_MODE_DATA 0x02
-#define RWB_MODE_DOWNLOAD 0x04
-#define RWB_MODE_DOWNLOAD_SAVE 0x05
- uint8_t buffer_id;
- uint8_t offset[3];
- uint8_t length[3];
- uint8_t control;
-};
-
-struct scsi_write_buffer
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t buffer_id;
- uint8_t offset[3];
- uint8_t length[3];
- uint8_t control;
-};
-
-struct scsi_rw_6
-{
- uint8_t opcode;
- uint8_t addr[3];
-/* only 5 bits are valid in the MSB address byte */
-#define SRW_TOPADDR 0x1F
- uint8_t length;
- uint8_t control;
-};
-
-struct scsi_rw_10
-{
- uint8_t opcode;
-#define SRW10_RELADDR 0x01
-#define SRW10_FUA 0x08
-#define SRW10_DPO 0x10
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t reserved;
- uint8_t length[2];
- uint8_t control;
-};
-
-struct scsi_rw_12
-{
- uint8_t opcode;
-#define SRW12_RELADDR 0x01
-#define SRW12_FUA 0x08
-#define SRW12_DPO 0x10
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t length[4];
- uint8_t reserved;
- uint8_t control;
-};
-
-struct scsi_start_stop_unit
-{
- uint8_t opcode;
- uint8_t byte2;
-#define SSS_IMMED 0x01
- uint8_t reserved[2];
- uint8_t how;
-#define SSS_START 0x01
-#define SSS_LOEJ 0x02
- uint8_t control;
-};
-
-#define SC_SCSI_1 0x01
-#define SC_SCSI_2 0x03
-
-/*
- * Opcodes
- */
-
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define READ_6 0x08
-#define WRITE_6 0x0a
-#define INQUIRY 0x12
-#define MODE_SELECT_6 0x15
-#define MODE_SENSE_6 0x1a
-#define START_STOP_UNIT 0x1b
-#define START_STOP 0x1b
-#define RESERVE 0x16
-#define RELEASE 0x17
-#define RECEIVE_DIAGNOSTIC 0x1c
-#define SEND_DIAGNOSTIC 0x1d
-#define PREVENT_ALLOW 0x1e
-#define READ_CAPACITY 0x25
-#define READ_10 0x28
-#define WRITE_10 0x2a
-#define POSITION_TO_ELEMENT 0x2b
-#define SYNCHRONIZE_CACHE 0x35
-#define WRITE_BUFFER 0x3b
-#define READ_BUFFER 0x3c
-#define CHANGE_DEFINITION 0x40
-#define LOG_SELECT 0x4c
-#define LOG_SENSE 0x4d
-#ifdef XXXCAM
-#define MODE_SENSE_10 0x5A
-#endif
-#define MODE_SELECT_10 0x55
-#define MOVE_MEDIUM 0xa5
-#define READ_12 0xa8
-#define WRITE_12 0xaa
-#define READ_ELEMENT_STATUS 0xb8
-
-
-/*
- * Device Types
- */
-#define T_DIRECT 0x00
-#define T_SEQUENTIAL 0x01
-#define T_PRINTER 0x02
-#define T_PROCESSOR 0x03
-#define T_WORM 0x04
-#define T_CDROM 0x05
-#define T_SCANNER 0x06
-#define T_OPTICAL 0x07
-#define T_CHANGER 0x08
-#define T_COMM 0x09
-#define T_ASC0 0x0a
-#define T_ASC1 0x0b
-#define T_STORARRAY 0x0c
-#define T_ENCLOSURE 0x0d
-#define T_RBC 0x0e
-#define T_OCRW 0x0f
-#define T_NODEVICE 0x1F
-#define T_ANY 0xFF /* Used in Quirk table matches */
-
-#define T_REMOV 1
-#define T_FIXED 0
-
-/*
- * This length is the initial inquiry length used by the probe code, as
- * well as the legnth necessary for aic_print_inquiry() to function
- * correctly. If either use requires a different length in the future,
- * the two values should be de-coupled.
- */
-#define SHORT_INQUIRY_LENGTH 36
-
-struct scsi_inquiry_data
-{
- uint8_t device;
-#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
-#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
-#define SID_QUAL_LU_CONNECTED 0x00 /*
- * The specified peripheral device
- * type is currently connected to
- * logical unit. If the target cannot
- * determine whether or not a physical
- * device is currently connected, it
- * shall also use this peripheral
- * qualifier when returning the INQUIRY
- * data. This peripheral qualifier
- * does not mean that the device is
- * ready for access by the initiator.
- */
-#define SID_QUAL_LU_OFFLINE 0x01 /*
- * The target is capable of supporting
- * the specified peripheral device type
- * on this logical unit; however, the
- * physical device is not currently
- * connected to this logical unit.
- */
-#define SID_QUAL_RSVD 0x02
-#define SID_QUAL_BAD_LU 0x03 /*
- * The target is not capable of
- * supporting a physical device on
- * this logical unit. For this
- * peripheral qualifier the peripheral
- * device type shall be set to 1Fh to
- * provide compatibility with previous
- * versions of SCSI. All other
- * peripheral device type values are
- * reserved for this peripheral
- * qualifier.
- */
-#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0)
- uint8_t dev_qual2;
-#define SID_QUAL2 0x7F
-#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0)
- uint8_t version;
-#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07)
#define SCSI_REV_0 0
#define SCSI_REV_CCS 1
#define SCSI_REV_2 2
#define SCSI_REV_SPC 3
#define SCSI_REV_SPC2 4
-#define SID_ECMA 0x38
-#define SID_ISO 0xC0
- uint8_t response_format;
-#define SID_AENC 0x80
-#define SID_TrmIOP 0x40
- uint8_t additional_length;
- uint8_t reserved[2];
- uint8_t flags;
-#define SID_SftRe 0x01
-#define SID_CmdQue 0x02
-#define SID_Linked 0x08
-#define SID_Sync 0x10
-#define SID_WBus16 0x20
-#define SID_WBus32 0x40
-#define SID_RelAdr 0x80
-#define SID_VENDOR_SIZE 8
- char vendor[SID_VENDOR_SIZE];
-#define SID_PRODUCT_SIZE 16
- char product[SID_PRODUCT_SIZE];
-#define SID_REVISION_SIZE 4
- char revision[SID_REVISION_SIZE];
- /*
- * The following fields were taken from SCSI Primary Commands - 2
- * (SPC-2) Revision 14, Dated 11 November 1999
- */
-#define SID_VENDOR_SPECIFIC_0_SIZE 20
- uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE];
- /*
- * An extension of SCSI Parallel Specific Values
- */
-#define SID_SPI_IUS 0x01
-#define SID_SPI_QAS 0x02
-#define SID_SPI_CLOCK_ST 0x00
-#define SID_SPI_CLOCK_DT 0x04
-#define SID_SPI_CLOCK_DT_ST 0x0C
-#define SID_SPI_MASK 0x0F
- uint8_t spi3data;
- uint8_t reserved2;
- /*
- * Version Descriptors, stored 2 byte values.
- */
- uint8_t version1[2];
- uint8_t version2[2];
- uint8_t version3[2];
- uint8_t version4[2];
- uint8_t version5[2];
- uint8_t version6[2];
- uint8_t version7[2];
- uint8_t version8[2];
-
- uint8_t reserved3[22];
-
-#define SID_VENDOR_SPECIFIC_1_SIZE 160
- uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
-};
-
-struct scsi_vpd_unit_serial_number
-{
- uint8_t device;
- uint8_t page_code;
-#define SVPD_UNIT_SERIAL_NUMBER 0x80
- uint8_t reserved;
- uint8_t length; /* serial number length */
-#define SVPD_SERIAL_NUM_SIZE 251
- uint8_t serial_num[SVPD_SERIAL_NUM_SIZE];
-};
-
-struct scsi_read_capacity
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t addr[4];
- uint8_t unused[3];
- uint8_t control;
-};
-
-struct scsi_read_capacity_data
-{
- uint8_t addr[4];
- uint8_t length[4];
-};
-
-struct scsi_report_luns
-{
- uint8_t opcode;
- uint8_t byte2;
- uint8_t unused[3];
- uint8_t addr[4];
- uint8_t control;
-};
-
-struct scsi_report_luns_data {
- uint8_t length[4]; /* length of LUN inventory, in bytes */
- uint8_t reserved[4]; /* unused */
- /*
- * LUN inventory- we only support the type zero form for now.
- */
- struct {
- uint8_t lundata[8];
- } luns[1];
-};
-#define RPL_LUNDATA_ATYP_MASK 0xc0 /* MBZ for type 0 lun */
-#define RPL_LUNDATA_T0LUN 1 /* @ lundata[1] */
-
-
struct scsi_sense_data
{
uint8_t error_code;
@@ -757,41 +117,6 @@ struct scsi_sense_data
#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
};
-struct scsi_mode_header_6
-{
- uint8_t data_length; /* Sense data length */
- uint8_t medium_type;
- uint8_t dev_spec;
- uint8_t blk_desc_len;
-};
-
-struct scsi_mode_header_10
-{
- uint8_t data_length[2];/* Sense data length */
- uint8_t medium_type;
- uint8_t dev_spec;
- uint8_t unused[2];
- uint8_t blk_desc_len[2];
-};
-
-struct scsi_mode_page_header
-{
- uint8_t page_code;
- uint8_t page_length;
-};
-
-struct scsi_mode_blk_desc
-{
- uint8_t density;
- uint8_t nblocks[3];
- uint8_t reserved;
- uint8_t blklen[3];
-};
-
-#define SCSI_DEFAULT_DENSITY 0x00 /* use 'default' density */
-#define SCSI_SAME_DENSITY 0x7f /* use 'same' density- >= SCSI-2 only */
-
-
/*
* Status Byte
*/
@@ -807,76 +132,7 @@ struct scsi_mode_blk_desc
#define SCSI_STATUS_ACA_ACTIVE 0x30
#define SCSI_STATUS_TASK_ABORTED 0x40
-struct scsi_inquiry_pattern {
- uint8_t type;
- uint8_t media_type;
-#define SIP_MEDIA_REMOVABLE 0x01
-#define SIP_MEDIA_FIXED 0x02
- const char *vendor;
- const char *product;
- const char *revision;
-};
-
-struct scsi_static_inquiry_pattern {
- uint8_t type;
- uint8_t media_type;
- char vendor[SID_VENDOR_SIZE+1];
- char product[SID_PRODUCT_SIZE+1];
- char revision[SID_REVISION_SIZE+1];
-};
-
-struct scsi_sense_quirk_entry {
- struct scsi_inquiry_pattern inq_pat;
- int num_sense_keys;
- int num_ascs;
- struct sense_key_table_entry *sense_key_info;
- struct asc_table_entry *asc_info;
-};
-
-struct sense_key_table_entry {
- uint8_t sense_key;
- uint32_t action;
- const char *desc;
-};
-
-struct asc_table_entry {
- uint8_t asc;
- uint8_t ascq;
- uint32_t action;
- const char *desc;
-};
-
-struct op_table_entry {
- uint8_t opcode;
- uint16_t opmask;
- const char *desc;
-};
-
-struct scsi_op_quirk_entry {
- struct scsi_inquiry_pattern inq_pat;
- int num_ops;
- struct op_table_entry *op_table;
-};
-
-typedef enum {
- SSS_FLAG_NONE = 0x00,
- SSS_FLAG_PRINT_COMMAND = 0x01
-} scsi_sense_string_flags;
-
-extern const char *scsi_sense_key_text[];
-
/************************* Large Disk Handling ********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
-
-static __inline int
-aic_sector_div(u_long capacity, int heads, int sectors)
-{
- return (capacity / (heads * sectors));
-}
-#else
-static __inline int aic_sector_div(sector_t capacity, int heads, int sectors);
-
static __inline int
aic_sector_div(sector_t capacity, int heads, int sectors)
{
@@ -884,152 +140,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
sector_div(capacity, (heads * sectors));
return (int)capacity;
}
-#endif
-
-/**************************** Module Library Hack *****************************/
-/*
- * What we'd like to do is have a single "scsi library" module that both the
- * aic7xxx and aic79xx drivers could load and depend on. A cursory examination
- * of implementing module dependencies in Linux (handling the install and
- * initrd cases) does not look promissing. For now, we just duplicate this
- * code in both drivers using a simple symbol renaming scheme that hides this
- * hack from the drivers.
- */
-#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x
-#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
-#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
-
-#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc)
-#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action)
-#define aic_error_action AIC_LIB_ENTRY(_error_action)
-#define aic_op_desc AIC_LIB_ENTRY(_op_desc)
-#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string)
-#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry)
-#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate)
-#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam)
-#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed)
-#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match)
-#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match)
-#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option)
-
-/******************************************************************************/
-
-void aic_sense_desc(int /*sense_key*/, int /*asc*/,
- int /*ascq*/, struct scsi_inquiry_data*,
- const char** /*sense_key_desc*/,
- const char** /*asc_desc*/);
-aic_sense_action aic_sense_error_action(struct scsi_sense_data*,
- struct scsi_inquiry_data*,
- uint32_t /*sense_flags*/);
-uint32_t aic_error_action(struct scsi_cmnd *,
- struct scsi_inquiry_data *,
- cam_status, u_int);
-
-#define SF_RETRY_UA 0x01
-#define SF_NO_PRINT 0x02
-#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
-#define SF_PRINT_ALWAYS 0x08
-
-
-const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*);
-char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/,
- size_t /*len*/);
-void aic_print_inquiry(struct scsi_inquiry_data*);
-
-u_int aic_calc_syncsrate(u_int /*period_factor*/);
-u_int aic_calc_syncparam(u_int /*period*/);
-u_int aic_calc_speed(u_int width, u_int period, u_int offset,
- u_int min_rate);
-
-int aic_inquiry_match(caddr_t /*inqbuffer*/,
- caddr_t /*table_entry*/);
-int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
- caddr_t /*table_entry*/);
-
-typedef void aic_option_callback_t(u_long, int, int, int32_t);
-char * aic_parse_brace_option(char *opt_name, char *opt_arg,
- char *end, int depth,
- aic_option_callback_t *, u_long);
-
-static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
- int *error_code, int *sense_key,
- int *asc, int *ascq);
-static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
-static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
-static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
-static __inline uint32_t scsi_2btoul(uint8_t *bytes);
-static __inline uint32_t scsi_3btoul(uint8_t *bytes);
-static __inline int32_t scsi_3btol(uint8_t *bytes);
-static __inline uint32_t scsi_4btoul(uint8_t *bytes);
-
-static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
- int *error_code, int *sense_key,
- int *asc, int *ascq)
-{
- *error_code = sense->error_code & SSD_ERRCODE;
- *sense_key = sense->flags & SSD_KEY;
- *asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
- *ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
-}
-
-static __inline void
-scsi_ulto2b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 8) & 0xff;
- bytes[1] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto3b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 16) & 0xff;
- bytes[1] = (val >> 8) & 0xff;
- bytes[2] = val & 0xff;
-}
-
-static __inline void
-scsi_ulto4b(uint32_t val, uint8_t *bytes)
-{
-
- bytes[0] = (val >> 24) & 0xff;
- bytes[1] = (val >> 16) & 0xff;
- bytes[2] = (val >> 8) & 0xff;
- bytes[3] = val & 0xff;
-}
-
-static __inline uint32_t
-scsi_2btoul(uint8_t *bytes)
-{
- uint32_t rv;
-
- rv = (bytes[0] << 8) |
- bytes[1];
- return (rv);
-}
-
-static __inline uint32_t
-scsi_3btoul(uint8_t *bytes)
-{
- uint32_t rv;
-
- rv = (bytes[0] << 16) |
- (bytes[1] << 8) |
- bytes[2];
- return (rv);
-}
-
-static __inline int32_t
-scsi_3btol(uint8_t *bytes)
-{
- uint32_t rc = scsi_3btoul(bytes);
-
- if (rc & 0x00800000)
- rc |= 0xff000000;
-
- return (int32_t) rc;
-}
static __inline uint32_t
scsi_4btoul(uint8_t *bytes)
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
index 54b32868aaf7..13f23043c8a3 100644
--- a/drivers/scsi/arm/Kconfig
+++ b/drivers/scsi/arm/Kconfig
@@ -3,7 +3,7 @@
#
config SCSI_ACORNSCSI_3
tristate "Acorn SCSI card (aka30) support"
- depends on ARCH_ACORN && SCSI
+ depends on ARCH_ACORN && SCSI && BROKEN
help
This enables support for the Acorn SCSI card (aka30). If you have an
Acorn system with one of these, say Y. If unsure, say N.
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 48e1c4d9738b..19937640e2e7 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -10,6 +10,8 @@
* Commonly used scsi driver functions.
*/
+#include <linux/scatterlist.h>
+
#define BELT_AND_BRACES
/*
@@ -22,9 +24,7 @@ static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int
BUG_ON(bufs + 1 > max);
- sg->page = virt_to_page(SCp->ptr);
- sg->offset = offset_in_page(SCp->ptr);
- sg->length = SCp->this_residual;
+ sg_set_buf(sg, SCp->ptr, SCp->this_residual);
if (bufs)
memcpy(sg + 1, SCp->buffer + 1,
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index a2cfade2c1c6..7f8aa1b552ce 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -1,24 +1,42 @@
/*
-
- ata_piix.c - Intel PATA/SATA controllers
-
- Maintained by: Jeff Garzik <jgarzik@pobox.com>
- Please ALWAYS copy linux-ide@vger.kernel.org
- on emails.
-
-
- Copyright 2003-2004 Red Hat Inc
- Copyright 2003-2004 Jeff Garzik
-
-
- Copyright header from piix.c:
-
- Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
-
- May be copied or modified under the terms of the GNU General Public License
-
+ * ata_piix.c - Intel PATA/SATA controllers
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ *
+ * Copyright 2003-2005 Red Hat Inc
+ * Copyright 2003-2005 Jeff Garzik
+ *
+ *
+ * Copyright header from piix.c:
+ *
+ * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003 Red Hat Inc <alan@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, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available at http://developer.intel.com/
+ *
*/
#include <linux/kernel.h>
@@ -27,12 +45,13 @@
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#define DRV_NAME "ata_piix"
-#define DRV_VERSION "1.03"
+#define DRV_VERSION "1.04"
enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
@@ -50,8 +69,8 @@ enum {
PIIX_COMB_PATA_P0 = (1 << 1),
PIIX_COMB = (1 << 2), /* combined mode enabled? */
- PIIX_PORT_PRESENT = (1 << 0),
- PIIX_PORT_ENABLED = (1 << 4),
+ PIIX_PORT_ENABLED = (1 << 0),
+ PIIX_PORT_PRESENT = (1 << 4),
PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6),
@@ -129,7 +148,7 @@ static Scsi_Host_Template piix_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations piix_pata_ops = {
+static const struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
@@ -159,7 +178,7 @@ static struct ata_port_operations piix_pata_ops = {
.host_stop = ata_host_stop,
};
-static struct ata_port_operations piix_sata_ops = {
+static const struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@@ -359,7 +378,9 @@ static void piix_pata_phy_reset(struct ata_port *ap)
* None (inherited from caller).
*
* RETURNS:
- * Non-zero if device detected, zero otherwise.
+ * Non-zero if port is enabled, it may or may not have a device
+ * attached in that case (PRESENT bit would only be set if BIOS probe
+ * was done). Zero is returned if port is disabled.
*/
static int piix_sata_probe (struct ata_port *ap)
{
@@ -383,7 +404,7 @@ static int piix_sata_probe (struct ata_port *ap)
*/
for (i = 0; i < 4; i++) {
- mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
+ mask = (PIIX_PORT_ENABLED << i);
if ((orig_mask & mask) == mask)
if (combined || (i == ap->hard_port_no))
@@ -422,7 +443,6 @@ static void piix_sata_phy_reset(struct ata_port *ap)
* piix_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: um
- * @pio: PIO mode, 0 - 4
*
* Set PIO mode for device, in host controller PCI config space.
*
@@ -548,25 +568,12 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
}
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
-}
-
#define AHCI_PCI_BAR 5
#define AHCI_GLOBAL_CTL 0x04
#define AHCI_ENABLE (1 << 31)
static int piix_disable_ahci(struct pci_dev *pdev)
{
- void *mmio;
- unsigned long addr;
+ void __iomem *mmio;
u32 tmp;
int rc = 0;
@@ -574,11 +581,11 @@ static int piix_disable_ahci(struct pci_dev *pdev)
* works because this device is usually set up by BIOS.
*/
- addr = pci_resource_start(pdev, AHCI_PCI_BAR);
- if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+ if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
+ !pci_resource_len(pdev, AHCI_PCI_BAR))
return 0;
- mmio = ioremap(addr, 64);
+ mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
if (!mmio)
return -ENOMEM;
@@ -592,7 +599,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
rc = -EIO;
}
- iounmap(mmio);
+ pci_iounmap(pdev, mmio);
return rc;
}
@@ -615,27 +622,28 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct ata_port_info *port_info[2];
- unsigned int combined = 0, n_ports = 1;
+ unsigned int combined = 0;
unsigned int pata_chan = 0, sata_chan = 0;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
/* no hotplugging support (FIXME) */
if (!in_module_init)
return -ENODEV;
port_info[0] = &piix_port_info[ent->driver_data];
- port_info[1] = NULL;
+ port_info[1] = &piix_port_info[ent->driver_data];
if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
- u8 tmp;
- pci_read_config_byte(pdev, PIIX_SCC, &tmp);
- if (tmp == PIIX_AHCI_DEVICE) {
- int rc = piix_disable_ahci(pdev);
- if (rc)
- return rc;
- }
+ u8 tmp;
+ pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+ if (tmp == PIIX_AHCI_DEVICE) {
+ int rc = piix_disable_ahci(pdev);
+ if (rc)
+ return rc;
+ }
}
if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
@@ -658,18 +666,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
* message-signalled interrupts currently).
*/
if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
if (combined) {
port_info[sata_chan] = &piix_port_info[ent->driver_data];
port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
port_info[pata_chan] = &piix_port_info[ich5_pata];
- n_ports++;
- printk(KERN_WARNING DRV_NAME ": combined mode detected\n");
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "combined mode detected (p=%u, s=%u)\n",
+ pata_chan, sata_chan);
}
- return ata_pci_init_one(pdev, port_info, n_ports);
+ return ata_pci_init_one(pdev, port_info, 2);
}
static int __init piix_init(void)
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index e6153fe5842a..a8cfbef304b5 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -996,6 +996,7 @@ oktosend:
#ifdef ED_DBGP
printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
#endif
+ dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2;
outb(0x06, tmpcip);
@@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host)
for (k = 0; k < 16; k++) {
if (!atp_dev->id[j][k].prd_table)
continue;
- pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
+ pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
atp_dev->id[j][k].prd_table = NULL;
}
}
@@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host)
int c,k;
for(c=0;c < 2;c++) {
for(k=0;k<16;k++) {
- atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
+ atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
if (!atp_dev->id[c][k].prd_table) {
printk("atp870u_init_tables fail\n");
atp870u_free_tables(host);
return -ENOMEM;
}
+ atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
atp_dev->id[c][k].devsp=0x20;
atp_dev->id[c][k].devtype = 0x7f;
atp_dev->id[c][k].curr_req = NULL;
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
index 89f43af39cf2..62bae64a01c1 100644
--- a/drivers/scsi/atp870u.h
+++ b/drivers/scsi/atp870u.h
@@ -54,8 +54,9 @@ struct atp_unit
unsigned long tran_len;
unsigned long last_len;
unsigned char *prd_pos;
- unsigned char *prd_table;
- dma_addr_t prdaddr;
+ unsigned char *prd_table; /* Kernel address of PRD table */
+ dma_addr_t prd_bus; /* Bus address of PRD */
+ dma_addr_t prdaddr; /* Dynamically updated in driver */
struct scsi_cmnd *curr_req;
} id[2][16];
struct Scsi_Host *host;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 3900e28ac7d6..540147cb51ce 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/chio.h> /* here are all the ioctls */
@@ -31,7 +30,7 @@
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_dbg.h>
#define CH_DT_MAX 16
@@ -117,7 +116,7 @@ typedef struct {
} scsi_changer;
static LIST_HEAD(ch_devlist);
-static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ch_devlist_lock);
static int ch_devcount;
static struct scsi_driver ch_template =
@@ -181,17 +180,17 @@ static struct {
/* ------------------------------------------------------------------- */
-static int ch_find_errno(unsigned char *sense_buffer)
+static int ch_find_errno(struct scsi_sense_hdr *sshdr)
{
int i,errno = 0;
/* Check to see if additional sense information is available */
- if (sense_buffer[7] > 5 &&
- sense_buffer[12] != 0) {
+ if (scsi_sense_valid(sshdr) &&
+ sshdr->asc != 0) {
for (i = 0; err[i].errno != 0; i++) {
- if (err[i].sense == sense_buffer[ 2] &&
- err[i].asc == sense_buffer[12] &&
- err[i].ascq == sense_buffer[13]) {
+ if (err[i].sense == sshdr->sense_key &&
+ err[i].asc == sshdr->asc &&
+ err[i].ascq == sshdr->ascq) {
errno = -err[i].errno;
break;
}
@@ -207,13 +206,9 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
void *buffer, unsigned buflength,
enum dma_data_direction direction)
{
- int errno, retries = 0, timeout;
- struct scsi_request *sr;
+ int errno, retries = 0, timeout, result;
+ struct scsi_sense_hdr sshdr;
- sr = scsi_allocate_request(ch->device, GFP_KERNEL);
- if (NULL == sr)
- return -ENOMEM;
-
timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
? timeout_init : timeout_move;
@@ -224,16 +219,17 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
__scsi_print_command(cmd);
}
- scsi_wait_req(sr, cmd, buffer, buflength,
- timeout * HZ, MAX_RETRIES);
+ result = scsi_execute_req(ch->device, cmd, direction, buffer,
+ buflength, &sshdr, timeout * HZ,
+ MAX_RETRIES);
- dprintk("result: 0x%x\n",sr->sr_result);
- if (driver_byte(sr->sr_result) & DRIVER_SENSE) {
+ dprintk("result: 0x%x\n",result);
+ if (driver_byte(result) & DRIVER_SENSE) {
if (debug)
- scsi_print_req_sense(ch->name, sr);
- errno = ch_find_errno(sr->sr_sense_buffer);
+ scsi_print_sense_hdr(ch->name, &sshdr);
+ errno = ch_find_errno(&sshdr);
- switch(sr->sr_sense_buffer[2] & 0xf) {
+ switch(sshdr.sense_key) {
case UNIT_ATTENTION:
ch->unit_attention = 1;
if (retries++ < 3)
@@ -241,7 +237,6 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
break;
}
}
- scsi_release_request(sr);
return errno;
}
@@ -565,7 +560,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
return result;
}
-static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
+static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
{
int retval = 0;
u_char data[16];
@@ -639,6 +634,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
scsi_changer *ch = file->private_data;
int retval;
+ void __user *argp = (void __user *)arg;
switch (cmd) {
case CHIOGPARAMS:
@@ -651,7 +647,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
params.cp_nportals = ch->counts[CHET_IE];
params.cp_ndrives = ch->counts[CHET_DT];
- if (copy_to_user((void *) arg, &params, sizeof(params)))
+ if (copy_to_user(argp, &params, sizeof(params)))
return -EFAULT;
return 0;
}
@@ -676,7 +672,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
vparams.cvp_n4 = ch->counts[CHET_V4];
strncpy(vparams.cvp_label4,vendor_labels[3],16);
}
- if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
+ if (copy_to_user(argp, &vparams, sizeof(vparams)))
return -EFAULT;
return 0;
}
@@ -685,7 +681,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_position pos;
- if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
+ if (copy_from_user(&pos, argp, sizeof (pos)))
return -EFAULT;
if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
@@ -704,7 +700,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_move mv;
- if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ if (copy_from_user(&mv, argp, sizeof (mv)))
return -EFAULT;
if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
@@ -726,7 +722,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_exchange mv;
- if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ if (copy_from_user(&mv, argp, sizeof (mv)))
return -EFAULT;
if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) ||
@@ -751,7 +747,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
{
struct changer_element_status ces;
- if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
+ if (copy_from_user(&ces, argp, sizeof (ces)))
return -EFAULT;
if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
return -EINVAL;
@@ -767,7 +763,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
unsigned int elem;
int result,i;
- if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
+ if (copy_from_user(&cge, argp, sizeof (cge)))
return -EFAULT;
if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
@@ -830,7 +826,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
kfree(buffer);
up(&ch->lock);
- if (copy_to_user((void*)arg, &cge, sizeof (cge)))
+ if (copy_to_user(argp, &cge, sizeof (cge)))
return -EFAULT;
return result;
}
@@ -848,7 +844,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
struct changer_set_voltag csv;
int elem;
- if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
+ if (copy_from_user(&csv, argp, sizeof(csv)))
return -EFAULT;
if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
@@ -866,7 +862,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
}
default:
- return scsi_ioctl(ch->device, cmd, (void*)arg);
+ return scsi_ioctl(ch->device, cmd, argp);
}
}
@@ -899,9 +895,9 @@ static long ch_ioctl_compat(struct file * file,
case CHIOGSTATUS32:
{
struct changer_element_status32 ces32;
- unsigned char *data;
+ unsigned char __user *data;
- if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
+ if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
return -EFAULT;
if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
return -EINVAL;
@@ -940,9 +936,7 @@ static int ch_probe(struct device *dev)
if (init)
ch_init_elem(ch);
- devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
- S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
- class_device_create(ch_sysfs_class,
+ class_device_create(ch_sysfs_class, NULL,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
dev, "s%s", ch->name);
@@ -974,7 +968,6 @@ static int ch_remove(struct device *dev)
class_device_destroy(ch_sysfs_class,
MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
- devfs_remove(ch->name);
kfree(ch->dt);
kfree(ch);
ch_devcount--;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index ec161733a82b..f6be2c1c3942 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -17,6 +17,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_eh.h>
+#include <scsi/scsi_dbg.h>
@@ -1155,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
}
}
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+ const char *sense_txt;
+ /* An example of deferred is when an earlier write to disk cache
+ * succeeded, but now the disk discovers that it cannot write the
+ * data to the magnetic media.
+ */
+ const char *error = scsi_sense_is_deferred(sshdr) ?
+ "<<DEFERRED>>" : "Current";
+ printk(KERN_INFO "%s: %s", name, error);
+ if (sshdr->response_code >= 0x72)
+ printk(" [descriptor]");
+
+ sense_txt = scsi_sense_key_string(sshdr->sense_key);
+ if (sense_txt)
+ printk(": sense key: %s\n", sense_txt);
+ else
+ printk(": sense key=0x%x\n", sshdr->sense_key);
+ printk(KERN_INFO " ");
+ scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+ printk("\n");
+}
+EXPORT_SYMBOL(scsi_print_sense_hdr);
+
/* Print sense information */
void
__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
@@ -1162,8 +1188,6 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
{
int k, num, res;
unsigned int info;
- const char *error;
- const char *sense_txt;
struct scsi_sense_hdr ssh;
res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
@@ -1181,26 +1205,7 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
printk("\n");
return;
}
-
- /* An example of deferred is when an earlier write to disk cache
- * succeeded, but now the disk discovers that it cannot write the
- * data to the magnetic media.
- */
- error = scsi_sense_is_deferred(&ssh) ?
- "<<DEFERRED>>" : "Current";
- printk(KERN_INFO "%s: %s", name, error);
- if (ssh.response_code >= 0x72)
- printk(" [descriptor]");
-
- sense_txt = scsi_sense_key_string(ssh.sense_key);
- if (sense_txt)
- printk(": sense key: %s\n", sense_txt);
- else
- printk(": sense key=0x%x\n", ssh.sense_key);
- printk(KERN_INFO " ");
- scsi_show_extd_sense(ssh.asc, ssh.ascq);
- printk("\n");
-
+ scsi_print_sense_hdr(name, &ssh);
if (ssh.response_code < 0x72) {
/* only decode extras for "fixed" format now */
char buff[80];
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index d72be0ce89c8..3fda8d455c5b 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -691,8 +691,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg)
if( copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
result = -EFAULT;
- if( buf)
- kfree( buf);
+ kfree(buf);
return result;
}
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 929170dcd3cb..600ba1202864 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -183,7 +183,7 @@
* cross a page boundy.
*/
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
+
struct SGentry {
u32 address; /* bus! address */
@@ -235,7 +235,6 @@ struct ScsiReqBlk {
u8 sg_count; /* No of HW sg entries for this request */
u8 sg_index; /* Index of HW sg entry for this request */
u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
- void **virt_map;
unsigned char *virt_addr; /* Virtual address of current transfer position */
/*
@@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
reqlen, cmd->request_buffer, cmd->use_sg,
srb->sg_count);
+ srb->virt_addr = page_address(sl->page);
for (i = 0; i < srb->sg_count; i++) {
- u32 seglen = (u32)sg_dma_len(sl + i);
- sgp[i].address = (u32)sg_dma_address(sl + i);
+ u32 busaddr = (u32)sg_dma_address(&sl[i]);
+ u32 seglen = (u32)sl[i].length;
+ sgp[i].address = busaddr;
sgp[i].length = seglen;
srb->total_xfer_length += seglen;
- srb->virt_map[i] = kmap(sl[i].page);
}
- srb->virt_addr = srb->virt_map[0];
sgp += srb->sg_count - 1;
/*
@@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
- void **virt = srb->virt_map;
dprintkdbg(DBG_0,
"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
/* We have to walk the scatterlist to find it */
sg = (struct scatterlist *)cmd->request_buffer;
- idx = 0;
while (segment--) {
unsigned long mask =
~((unsigned long)sg->length - 1) & PAGE_MASK;
if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
- srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
+ srb->virt_addr = (page_address(sg->page)
+ + psge->address -
+ (psge->address & PAGE_MASK));
return;
}
++sg;
- ++idx;
}
dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
}
/*
- * calculate all the residue data that not yet transfered
+ * calculate all the residue data that not yet tranfered
* SCSI transfer counter + left in SCSI FIFO data
*
* .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
struct scsi_cmnd *cmd = srb->cmd;
enum dma_data_direction dir = cmd->sc_data_direction;
if (cmd->use_sg && dir != PCI_DMA_NONE) {
- int i;
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
cmd->use_sg, cmd->request_buffer);
/* unmap the sg segments */
- for (i = 0; i < srb->sg_count; i++)
- kunmap(virt_to_page(srb->virt_map[i]));
pci_unmap_sg(acb->dev,
(struct scatterlist *)cmd->request_buffer,
cmd->use_sg, dir);
@@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
if (cmd->use_sg) {
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
- ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
+ ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
} else {
ptr = (struct ScsiInqData *)(cmd->request_buffer);
}
@@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
- kfree(acb->srb_array[i].segment_x);
-
- vfree(acb->srb_array[0].virt_map);
+ if (acb->srb_array[i].segment_x)
+ kfree(acb->srb_array[i].segment_x);
}
@@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
int srb_idx = 0;
unsigned i = 0;
struct SGentry *ptr;
- void **virt_array;
- for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
acb->srb_array[i].segment_x = NULL;
- acb->srb_array[i].virt_map = NULL;
- }
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
@@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
ptr + (i * DC395x_MAX_SG_LISTENTRY);
else
dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
-
- virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
-
- if (!virt_array) {
- adapter_sg_tables_free(acb);
- return 1;
- }
-
- for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
- acb->srb_array[i].virt_map = virt_array;
- virt_array += DC395x_MAX_SG_LISTENTRY;
- }
-
return 0;
}
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index 315f95a0d6c0..4f39890b44ac 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -228,7 +228,7 @@ static int dec_esp_detect(Scsi_Host_Template * tpnt)
mem_start = get_tc_base_addr(slot);
/* Store base addr into esp struct */
- esp->slot = PHYSADDR(mem_start);
+ esp->slot = CPHYSADDR(mem_start);
esp->dregs = 0;
esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index e2370529c632..7235f94f1191 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
raptorFlag = TRUE;
}
-
+ if (pci_request_regions(pDev, "dpt_i2o")) {
+ PERROR("dpti: adpt_config_hba: pci request region failed\n");
+ return -EINVAL;
+ }
base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
if (!base_addr_virt) {
+ pci_release_regions(pDev);
PERROR("dpti: adpt_config_hba: io remap failed\n");
return -EINVAL;
}
@@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
if (!msg_addr_virt) {
PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
iounmap(base_addr_virt);
+ pci_release_regions(pDev);
return -EINVAL;
}
} else {
@@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
iounmap(msg_addr_virt);
}
iounmap(base_addr_virt);
+ pci_release_regions(pDev);
return -ENOMEM;
}
memset(pHba, 0, sizeof(adpt_hba));
@@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
up(&adpt_configuration_lock);
iounmap(pHba->base_addr_virt);
+ pci_release_regions(pHba->pDev);
if(pHba->msg_addr_virt != pHba->base_addr_virt){
iounmap(pHba->msg_addr_virt);
}
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index c10e45b94b62..3d13fdee4fc2 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1357,7 +1357,7 @@ static int port_detect(unsigned long port_base, unsigned int j,
for (i = 0; i < shost->can_queue; i++) {
size_t sz = shost->sg_tablesize *sizeof(struct sg_list);
- unsigned int gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
+ gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
ha->cp[i].sglist = kmalloc(sz, gfp_mask);
if (!ha->cp[i].sglist) {
printk
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index fa652f8aa643..d59d449a9e4d 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = {
.use_clustering = DISABLE_CLUSTERING,
};
#include "scsi_module.c"
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5feb886c3392..71dd1ebbe58f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -24,11 +24,13 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/transport_class.h>
+#include <linux/platform_device.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
@@ -52,21 +54,100 @@ static struct class shost_class = {
};
/**
- * scsi_host_cancel - cancel outstanding IO to this host
- * @shost: pointer to struct Scsi_Host
- * recovery: recovery requested to run.
+ * scsi_host_set_state - Take the given host through the host
+ * state model.
+ * @shost: scsi host to change the state of.
+ * @state: state to change to.
+ *
+ * Returns zero if unsuccessful or an error if the requested
+ * transition is illegal.
**/
-static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
+int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
{
- struct scsi_device *sdev;
+ enum scsi_host_state oldstate = shost->shost_state;
+
+ if (state == oldstate)
+ return 0;
+
+ switch (state) {
+ case SHOST_CREATED:
+ /* There are no legal states that come back to
+ * created. This is the manually initialised start
+ * state */
+ goto illegal;
+
+ case SHOST_RUNNING:
+ switch (oldstate) {
+ case SHOST_CREATED:
+ case SHOST_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_RECOVERY:
+ switch (oldstate) {
+ case SHOST_RUNNING:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_CANCEL:
+ switch (oldstate) {
+ case SHOST_CREATED:
+ case SHOST_RUNNING:
+ case SHOST_CANCEL_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_DEL:
+ switch (oldstate) {
+ case SHOST_CANCEL:
+ case SHOST_DEL_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
- set_bit(SHOST_CANCEL, &shost->shost_state);
- shost_for_each_device(sdev, shost) {
- scsi_device_cancel(sdev, recovery);
+ case SHOST_CANCEL_RECOVERY:
+ switch (oldstate) {
+ case SHOST_CANCEL:
+ case SHOST_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case SHOST_DEL_RECOVERY:
+ switch (oldstate) {
+ case SHOST_CANCEL_RECOVERY:
+ break;
+ default:
+ goto illegal;
+ }
+ break;
}
- wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY,
- &shost->shost_state)));
+ shost->shost_state = state;
+ return 0;
+
+ illegal:
+ SCSI_LOG_ERROR_RECOVERY(1,
+ dev_printk(KERN_ERR, &shost->shost_gendev,
+ "Illegal host state transition"
+ "%s->%s\n",
+ scsi_host_state_name(oldstate),
+ scsi_host_state_name(state)));
+ return -EINVAL;
}
+EXPORT_SYMBOL(scsi_host_set_state);
/**
* scsi_remove_host - remove a scsi host
@@ -74,15 +155,29 @@ static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/
void scsi_remove_host(struct Scsi_Host *shost)
{
+ unsigned long flags;
+ down(&shost->scan_mutex);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (scsi_host_set_state(shost, SHOST_CANCEL))
+ if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ up(&shost->scan_mutex);
+ return;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ up(&shost->scan_mutex);
scsi_forget_host(shost);
- scsi_host_cancel(shost, 0);
scsi_proc_host_rm(shost);
- set_bit(SHOST_DEL, &shost->shost_state);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (scsi_host_set_state(shost, SHOST_DEL))
+ BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
+ spin_unlock_irqrestore(shost->host_lock, flags);
transport_unregister_device(&shost->shost_gendev);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
+ scsi_proc_hostdir_rm(shost->hostt);
}
EXPORT_SYMBOL(scsi_remove_host);
@@ -115,7 +210,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (error)
goto out;
- set_bit(SHOST_ADD, &shost->shost_state);
+ scsi_host_set_state(shost, SHOST_RUNNING);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
@@ -164,19 +259,11 @@ static void scsi_host_dev_release(struct device *dev)
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
- if (shost->ehandler) {
- DECLARE_COMPLETION(sem);
- shost->eh_notify = &sem;
- shost->eh_kill = 1;
- up(shost->eh_wait);
- wait_for_completion(&sem);
- shost->eh_notify = NULL;
- }
-
+ if (shost->ehandler)
+ kthread_stop(shost->ehandler);
if (shost->work_q)
destroy_workqueue(shost->work_q);
- scsi_proc_hostdir_rm(shost->hostt);
scsi_destroy_command_freelist(shost);
kfree(shost->shost_data);
@@ -201,8 +288,8 @@ static void scsi_host_dev_release(struct device *dev)
struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
{
struct Scsi_Host *shost;
- int gfp_mask = GFP_KERNEL, rval;
- DECLARE_COMPLETION(complete);
+ gfp_t gfp_mask = GFP_KERNEL;
+ int rval;
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
@@ -226,6 +313,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock);
+ shost->shost_state = SHOST_CREATED;
INIT_LIST_HEAD(&shost->__devices);
INIT_LIST_HEAD(&shost->__targets);
INIT_LIST_HEAD(&shost->eh_cmd_q);
@@ -307,12 +395,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
- shost->eh_notify = &complete;
- rval = kernel_thread(scsi_error_handler, shost, 0);
- if (rval < 0)
+ shost->ehandler = kthread_run(scsi_error_handler, shost,
+ "scsi_eh_%d", shost->host_no);
+ if (IS_ERR(shost->ehandler)) {
+ rval = PTR_ERR(shost->ehandler);
goto fail_destroy_freelist;
- wait_for_completion(&complete);
- shost->eh_notify = NULL;
+ }
scsi_proc_hostdir_add(shost->hostt);
return shost;
@@ -382,7 +470,7 @@ EXPORT_SYMBOL(scsi_host_lookup);
**/
struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
{
- if (test_bit(SHOST_DEL, &shost->shost_state) ||
+ if ((shost->shost_state == SHOST_DEL) ||
!get_device(&shost->shost_gendev))
return NULL;
return shost;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index b5dc35355570..19392f651272 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -36,7 +36,6 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/mca.h>
-#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/mca-legacy.h>
@@ -461,6 +460,8 @@ MODULE_PARM(adisplay, "1i");
MODULE_PARM(normal, "1i");
MODULE_PARM(ansi, "1i");
#endif
+
+MODULE_LICENSE("GPL");
#endif
/*counter of concurrent disk read/writes, to turn on/off disk led */
static int disk_rw_in_progress = 0;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fe09d145542a..822b9fa706f3 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
-#define IBMVSCSI_VERSION "1.5.6"
+#define IBMVSCSI_VERSION "1.5.7"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@@ -145,6 +145,8 @@ static int initialize_event_pool(struct event_pool *pool,
sizeof(*evt->xfer_iu) * i;
evt->xfer_iu = pool->iu_storage + i;
evt->hostdata = hostdata;
+ evt->ext_list = NULL;
+ evt->ext_list_token = 0;
}
return 0;
@@ -161,9 +163,16 @@ static void release_event_pool(struct event_pool *pool,
struct ibmvscsi_host_data *hostdata)
{
int i, in_use = 0;
- for (i = 0; i < pool->size; ++i)
+ for (i = 0; i < pool->size; ++i) {
if (atomic_read(&pool->events[i].free) != 1)
++in_use;
+ if (pool->events[i].ext_list) {
+ dma_free_coherent(hostdata->dev,
+ SG_ALL * sizeof(struct memory_descriptor),
+ pool->events[i].ext_list,
+ pool->events[i].ext_list_token);
+ }
+ }
if (in_use)
printk(KERN_WARNING
"ibmvscsi: releasing event pool with %d "
@@ -286,24 +295,41 @@ static void set_srp_direction(struct scsi_cmnd *cmd,
} else {
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_out_count = numbuf;
+ srp_cmd->data_out_count =
+ numbuf < MAX_INDIRECT_BUFS ?
+ numbuf: MAX_INDIRECT_BUFS;
} else {
srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_in_count = numbuf;
+ srp_cmd->data_in_count =
+ numbuf < MAX_INDIRECT_BUFS ?
+ numbuf: MAX_INDIRECT_BUFS;
}
}
}
+static void unmap_sg_list(int num_entries,
+ struct device *dev,
+ struct memory_descriptor *md)
+{
+ int i;
+
+ for (i = 0; i < num_entries; ++i) {
+ dma_unmap_single(dev,
+ md[i].virtual_address,
+ md[i].length, DMA_BIDIRECTIONAL);
+ }
+}
+
/**
* unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
* @cmd: srp_cmd whose additional_data member will be unmapped
* @dev: device for which the memory is mapped
*
*/
-static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+static void unmap_cmd_data(struct srp_cmd *cmd,
+ struct srp_event_struct *evt_struct,
+ struct device *dev)
{
- int i;
-
if ((cmd->data_out_format == SRP_NO_BUFFER) &&
(cmd->data_in_format == SRP_NO_BUFFER))
return;
@@ -318,15 +344,34 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
(struct indirect_descriptor *)cmd->additional_data;
int num_mapped = indirect->head.length /
sizeof(indirect->list[0]);
- for (i = 0; i < num_mapped; ++i) {
- struct memory_descriptor *data = &indirect->list[i];
- dma_unmap_single(dev,
- data->virtual_address,
- data->length, DMA_BIDIRECTIONAL);
+
+ if (num_mapped <= MAX_INDIRECT_BUFS) {
+ unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+ return;
}
+
+ unmap_sg_list(num_mapped, dev, evt_struct->ext_list);
}
}
+static int map_sg_list(int num_entries,
+ struct scatterlist *sg,
+ struct memory_descriptor *md)
+{
+ int i;
+ u64 total_length = 0;
+
+ for (i = 0; i < num_entries; ++i) {
+ struct memory_descriptor *descr = md + i;
+ struct scatterlist *sg_entry = &sg[i];
+ descr->virtual_address = sg_dma_address(sg_entry);
+ descr->length = sg_dma_len(sg_entry);
+ descr->memory_handle = 0;
+ total_length += sg_dma_len(sg_entry);
+ }
+ return total_length;
+}
+
/**
* map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
* @cmd: Scsi_Cmnd with the scatterlist
@@ -337,10 +382,11 @@ static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
* Returns 1 on success.
*/
static int map_sg_data(struct scsi_cmnd *cmd,
+ struct srp_event_struct *evt_struct,
struct srp_cmd *srp_cmd, struct device *dev)
{
- int i, sg_mapped;
+ int sg_mapped;
u64 total_length = 0;
struct scatterlist *sg = cmd->request_buffer;
struct memory_descriptor *data =
@@ -363,27 +409,46 @@ static int map_sg_data(struct scsi_cmnd *cmd,
return 1;
}
- if (sg_mapped > MAX_INDIRECT_BUFS) {
+ if (sg_mapped > SG_ALL) {
printk(KERN_ERR
"ibmvscsi: More than %d mapped sg entries, got %d\n",
- MAX_INDIRECT_BUFS, sg_mapped);
+ SG_ALL, sg_mapped);
return 0;
}
indirect->head.virtual_address = 0;
indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
indirect->head.memory_handle = 0;
- for (i = 0; i < sg_mapped; ++i) {
- struct memory_descriptor *descr = &indirect->list[i];
- struct scatterlist *sg_entry = &sg[i];
- descr->virtual_address = sg_dma_address(sg_entry);
- descr->length = sg_dma_len(sg_entry);
- descr->memory_handle = 0;
- total_length += sg_dma_len(sg_entry);
+
+ if (sg_mapped <= MAX_INDIRECT_BUFS) {
+ total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
+ indirect->total_length = total_length;
+ return 1;
}
- indirect->total_length = total_length;
- return 1;
+ /* get indirect table */
+ if (!evt_struct->ext_list) {
+ evt_struct->ext_list =(struct memory_descriptor*)
+ dma_alloc_coherent(dev,
+ SG_ALL * sizeof(struct memory_descriptor),
+ &evt_struct->ext_list_token, 0);
+ if (!evt_struct->ext_list) {
+ printk(KERN_ERR
+ "ibmvscsi: Can't allocate memory for indirect table\n");
+ return 0;
+
+ }
+ }
+
+ total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);
+
+ indirect->total_length = total_length;
+ indirect->head.virtual_address = evt_struct->ext_list_token;
+ indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
+ memcpy(indirect->list, evt_struct->ext_list,
+ MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor));
+
+ return 1;
}
/**
@@ -428,6 +493,7 @@ static int map_single_data(struct scsi_cmnd *cmd,
* Returns 1 on success.
*/
static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+ struct srp_event_struct *evt_struct,
struct srp_cmd *srp_cmd, struct device *dev)
{
switch (cmd->sc_data_direction) {
@@ -450,7 +516,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
if (!cmd->request_buffer)
return 1;
if (cmd->use_sg)
- return map_sg_data(cmd, srp_cmd, dev);
+ return map_sg_data(cmd, evt_struct, srp_cmd, dev);
return map_single_data(cmd, srp_cmd, dev);
}
@@ -486,6 +552,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
printk(KERN_WARNING
"ibmvscsi: Warning, request_limit exceeded\n");
unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ evt_struct,
hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -513,7 +580,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
return 0;
send_error:
- unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+ unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
if ((cmnd = evt_struct->cmnd) != NULL) {
cmnd->result = DID_ERROR << 16;
@@ -551,6 +618,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
rsp->sense_and_response_data,
rsp->sense_data_list_length);
unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ evt_struct,
evt_struct->hostdata->dev);
if (rsp->doover)
@@ -583,6 +651,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
{
struct srp_cmd *srp_cmd;
struct srp_event_struct *evt_struct;
+ struct indirect_descriptor *indirect;
struct ibmvscsi_host_data *hostdata =
(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
u16 lun = lun_from_dev(cmnd->device);
@@ -591,14 +660,6 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
if (!evt_struct)
return SCSI_MLQUEUE_HOST_BUSY;
- init_event_struct(evt_struct,
- handle_cmd_rsp,
- VIOSRP_SRP_FORMAT,
- cmnd->timeout);
-
- evt_struct->cmnd = cmnd;
- evt_struct->cmnd_done = done;
-
/* Set up the actual SRP IU */
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, sizeof(*srp_cmd));
@@ -606,17 +667,25 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
srp_cmd->lun = ((u64) lun) << 48;
- if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+ if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
}
+ init_event_struct(evt_struct,
+ handle_cmd_rsp,
+ VIOSRP_SRP_FORMAT,
+ cmnd->timeout_per_command/HZ);
+
+ evt_struct->cmnd = cmnd;
+ evt_struct->cmnd_done = done;
+
/* Fix up dma address of the buffer itself */
- if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
- (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)srp_cmd->additional_data;
+ indirect = (struct indirect_descriptor *)srp_cmd->additional_data;
+ if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
+ (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) &&
+ (indirect->head.virtual_address == 0)) {
indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
offsetof(struct srp_cmd, additional_data) +
offsetof(struct indirect_descriptor, list);
@@ -658,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
if (hostdata->madapter_info.port_max_txu[0])
hostdata->host->max_sectors =
hostdata->madapter_info.port_max_txu[0] >> 9;
+
+ if (hostdata->madapter_info.os_type == 3 &&
+ strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
+ printk("ibmvscsi: host (Ver. %s) doesn't support large"
+ "transfers\n",
+ hostdata->madapter_info.srp_version);
+ printk("ibmvscsi: limiting scatterlists to %d\n",
+ MAX_INDIRECT_BUFS);
+ hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
+ }
}
}
@@ -826,11 +905,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *found_evt;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
* out the correct tag
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -839,11 +920,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
- if (!found_evt)
+ if (!found_evt) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return FAILED;
+ }
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
return FAILED;
}
@@ -867,7 +951,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
return FAILED;
}
@@ -901,6 +987,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -910,6 +997,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
if (found_evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
tsk_mgmt->managed_task_tag);
@@ -922,8 +1010,10 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
- unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+ unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt,
+ found_evt->hostdata->dev);
free_event_struct(&found_evt->hostdata->pool, found_evt);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
atomic_inc(&hostdata->request_limit);
return SUCCESS;
}
@@ -943,10 +1033,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *pos;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
return FAILED;
}
@@ -969,7 +1062,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
return FAILED;
}
@@ -1002,12 +1097,14 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
if (tmp_evt->cmnd)
tmp_evt->cmnd->result = (DID_RESET << 16);
list_del(&tmp_evt->list);
- unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+ unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt,
+ tmp_evt->hostdata->dev);
free_event_struct(&tmp_evt->hostdata->pool,
tmp_evt);
atomic_inc(&hostdata->request_limit);
@@ -1017,6 +1114,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
tmp_evt->done(tmp_evt);
}
}
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return SUCCESS;
}
@@ -1035,6 +1133,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata)
if (tmp_evt->cmnd) {
tmp_evt->cmnd->result = (DID_ERROR << 16);
unmap_cmd_data(&tmp_evt->iu.srp.cmd,
+ tmp_evt,
tmp_evt->hostdata->dev);
if (tmp_evt->cmnd_done)
tmp_evt->cmnd_done(tmp_evt->cmnd);
@@ -1339,7 +1438,7 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 16,
.can_queue = 1, /* Updated after SRP_LOGIN */
.this_id = -1,
- .sg_tablesize = MAX_INDIRECT_BUFS,
+ .sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = ibmvscsi_attrs,
};
@@ -1442,15 +1541,18 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
*/
static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
{"vscsi", "IBM,v-scsi"},
- {0,}
+ { "", "" }
};
-
MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
+
static struct vio_driver ibmvscsi_driver = {
- .name = "ibmvscsi",
.id_table = ibmvscsi_device_table,
.probe = ibmvscsi_probe,
- .remove = ibmvscsi_remove
+ .remove = ibmvscsi_remove,
+ .driver = {
+ .name = "ibmvscsi",
+ .owner = THIS_MODULE,
+ }
};
int __init ibmvscsi_module_init(void)
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 1030b703c30e..8bec0438dc8a 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,6 +68,8 @@ struct srp_event_struct {
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
union viosrp_iu *sync_srp;
+ struct memory_descriptor *ext_list;
+ dma_addr_t ext_list_token;
};
/* a pool of event structs for use */
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index e9202f2a8276..1045872b0175 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -28,10 +28,10 @@
* hypervisor system or a converged hypervisor system.
*/
-#include <asm/iSeries/vio.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpConfig.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/hv_lp_event.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
#include <asm/vio.h>
#include <linux/device.h>
#include "ibmvscsi.h"
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 035f615817d7..8bf5652f1060 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -28,6 +28,7 @@
*/
#include <asm/vio.h>
+#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/hvcall.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
index 2ae5154fd89c..7d8e4c4accb9 100644
--- a/drivers/scsi/ibmvscsi/srp.h
+++ b/drivers/scsi/ibmvscsi/srp.h
@@ -35,7 +35,7 @@
enum srp_types {
SRP_LOGIN_REQ_TYPE = 0x00,
SRP_LOGIN_RSP_TYPE = 0xC0,
- SRP_LOGIN_REJ_TYPE = 0x80,
+ SRP_LOGIN_REJ_TYPE = 0xC2,
SRP_I_LOGOUT_TYPE = 0x03,
SRP_T_LOGOUT_TYPE = 0x80,
SRP_TSK_MGMT_TYPE = 0x01,
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 3d62c9bcbff7..a440ea38efaa 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -184,13 +184,16 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
unsigned long flags;
local_irq_save(flags);
- buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
- drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
+ buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
+ pc->sg->offset;
+ drive->hwif->atapi_input_bytes(drive,
+ buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags);
} else {
buf = page_address(pc->sg->page) + pc->sg->offset;
- drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
+ drive->hwif->atapi_input_bytes(drive,
+ buf + pc->b_count, count);
}
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
@@ -216,13 +219,16 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
unsigned long flags;
local_irq_save(flags);
- buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
- drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
+ buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
+ pc->sg->offset;
+ drive->hwif->atapi_output_bytes(drive,
+ buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags);
} else {
buf = page_address(pc->sg->page) + pc->sg->offset;
- drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
+ drive->hwif->atapi_output_bytes(drive,
+ buf + pc->b_count, count);
}
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index babd48363402..e0039dfae8e5 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4944,6 +4944,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
int rc;
ENTER;
+ pci_unblock_user_cfg_access(ioa_cfg->pdev);
rc = pci_restore_state(ioa_cfg->pdev);
if (rc != PCIBIOS_SUCCESSFUL) {
@@ -4998,6 +4999,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
int rc;
ENTER;
+ pci_block_user_cfg_access(ioa_cfg->pdev);
rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
if (rc != PCIBIOS_SUCCESSFUL) {
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 6dfcb4fbccdd..4cdd891781b1 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -133,10 +133,12 @@
/* 6.10.00 - Remove 1G Addressing Limitations */
/* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */
/* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */
-/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */
+/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */
/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */
/* - Fix sort order of 7k */
/* - Remove 3 unused "inline" functions */
+/* 7.12.xx - Use STATIC functions whereever possible */
+/* - Clean up deprecated MODULE_PARM calls */
/*****************************************************************************/
/*
@@ -207,8 +209,8 @@ module_param(ips, charp, 0);
/*
* DRIVER_VER
*/
-#define IPS_VERSION_HIGH "7.10"
-#define IPS_VERSION_LOW ".18 "
+#define IPS_VERSION_HIGH "7.12"
+#define IPS_VERSION_LOW ".02 "
#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index 480e06f4d6ae..505e967013de 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -87,15 +87,14 @@
#define scsi_set_pci_device(sh,dev) (0)
#endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
- #ifndef irqreturn_t
- typedef void irqreturn_t;
- #endif
-
+ #ifndef IRQ_NONE
+ typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
+ #endif
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT)
#define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT)
#define IPS_ADD_HOST(shost,device)
@@ -123,6 +122,10 @@
#ifndef min
#define min(x,y) ((x) < (y) ? x : y)
#endif
+
+ #ifndef __iomem /* For clean compiles in earlier kernels without __iomem annotations */
+ #define __iomem
+ #endif
#define pci_dma_hi32(a) ((a >> 16) >> 16)
#define pci_dma_lo32(a) (a & 0xffffffff)
@@ -1206,13 +1209,13 @@ typedef struct {
#define IPS_VER_MAJOR 7
#define IPS_VER_MAJOR_STRING "7"
-#define IPS_VER_MINOR 10
-#define IPS_VER_MINOR_STRING "10"
-#define IPS_VER_BUILD 18
-#define IPS_VER_BUILD_STRING "18"
-#define IPS_VER_STRING "7.10.18"
+#define IPS_VER_MINOR 12
+#define IPS_VER_MINOR_STRING "12"
+#define IPS_VER_BUILD 02
+#define IPS_VER_BUILD_STRING "02"
+#define IPS_VER_STRING "7.12.02"
#define IPS_RELEASE_ID 0x00020000
-#define IPS_BUILD_IDENT 731
+#define IPS_BUILD_IDENT 761
#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved."
#define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved."
@@ -1223,12 +1226,12 @@ typedef struct {
#define IPS_VER_SERVERAID2 "2.88.13"
#define IPS_VER_NAVAJO "2.88.13"
#define IPS_VER_SERVERAID3 "6.10.24"
-#define IPS_VER_SERVERAID4H "7.10.11"
-#define IPS_VER_SERVERAID4MLx "7.10.18"
-#define IPS_VER_SARASOTA "7.10.18"
-#define IPS_VER_MARCO "7.10.18"
-#define IPS_VER_SEBRING "7.10.18"
-#define IPS_VER_KEYWEST "7.10.18"
+#define IPS_VER_SERVERAID4H "7.12.02"
+#define IPS_VER_SERVERAID4MLx "7.12.02"
+#define IPS_VER_SARASOTA "7.12.02"
+#define IPS_VER_MARCO "7.12.02"
+#define IPS_VER_SEBRING "7.12.02"
+#define IPS_VER_KEYWEST "7.12.02"
/* Compatability IDs for various adapters */
#define IPS_COMPAT_UNKNOWN ""
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 4cbb6187cc44..459a4daebece 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(parisc, lasi700_ids);
static int __init
lasi700_probe(struct parisc_device *dev)
{
- unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET;
+ unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET;
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
@@ -125,8 +125,6 @@ lasi700_probe(struct parisc_device *dev)
hostdata->dmode_extra = DMODE_FC2;
}
- NCR_700_set_mem_mapped(hostdata);
-
host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
if (!host)
goto out_kfree;
@@ -168,7 +166,7 @@ lasi700_driver_remove(struct parisc_device *dev)
}
static struct parisc_driver lasi700_driver = {
- .name = "Lasi SCSI",
+ .name = "lasi_scsi",
.id_table = lasi700_ids,
.probe = lasi700_probe,
.remove = __devexit_p(lasi700_driver_remove),
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 73b1f72b7e43..ff18fa7044c5 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1,25 +1,35 @@
/*
- libata-core.c - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
-
+ * libata-core.c - helper library for ATA
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 Jeff Garzik
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from http://www.t13.org/ and
+ * http://www.sata-io.org/
+ *
*/
#include <linux/config.h>
@@ -38,6 +48,8 @@
#include <linux/completion.h>
#include <linux/suspend.h>
#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#include "scsi.h"
#include "scsi_priv.h"
@@ -52,26 +64,31 @@
static unsigned int ata_busy_sleep (struct ata_port *ap,
unsigned long tmout_pat,
unsigned long tmout);
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
static void ata_set_mode(struct ata_port *ap);
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift);
static int fgb(u32 bitmap);
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
u8 *xfer_mode_out,
unsigned int *xfer_shift_out);
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
static void __ata_qc_complete(struct ata_queued_cmd *qc);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
+int atapi_enabled = 0;
+module_param(atapi_enabled, int, 0444);
+MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
/**
- * ata_tf_load - send taskfile registers to host controller
+ * ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
@@ -81,7 +98,7 @@ MODULE_VERSION(DRV_VERSION);
* Inherited from caller.
*/
-static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -139,7 +156,7 @@ static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
* Inherited from caller.
*/
-static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -208,7 +225,7 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
* LOCKING:
* Inherited from caller.
*/
-void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_load_mmio(ap, tf);
@@ -228,7 +245,7 @@ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
@@ -249,7 +266,7 @@ static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
@@ -269,7 +286,7 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_exec_command_mmio(ap, tf);
@@ -278,28 +295,6 @@ void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
}
/**
- * ata_exec - issue ATA command to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Issues PIO/MMIO write to ATA command register, with proper
- * synchronization with interrupt handler / other threads.
- *
- * LOCKING:
- * Obtains host_set lock.
- */
-
-static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
-{
- unsigned long flags;
-
- DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->ops->exec_command(ap, tf);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-}
-
-/**
* ata_tf_to_host - issue ATA taskfile to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
@@ -309,30 +304,11 @@ static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
* other threads.
*
* LOCKING:
- * Obtains host_set lock.
- */
-
-static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
-{
- ap->ops->tf_load(ap, tf);
-
- ata_exec(ap, tf);
-}
-
-/**
- * ata_tf_to_host_nolock - issue ATA taskfile to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Issues ATA taskfile register set to ATA host controller,
- * with proper synchronization with interrupt handler and
- * other threads.
- *
- * LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
+static inline void ata_tf_to_host(struct ata_port *ap,
+ const struct ata_taskfile *tf)
{
ap->ops->tf_load(ap, tf);
ap->ops->exec_command(ap, tf);
@@ -354,6 +330,8 @@ static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
+ tf->command = ata_check_status(ap);
+ tf->feature = inb(ioaddr->error_addr);
tf->nsect = inb(ioaddr->nsect_addr);
tf->lbal = inb(ioaddr->lbal_addr);
tf->lbam = inb(ioaddr->lbam_addr);
@@ -386,6 +364,8 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
+ tf->command = ata_check_status(ap);
+ tf->feature = readb((void __iomem *)ioaddr->error_addr);
tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
@@ -506,30 +486,6 @@ u8 ata_altstatus(struct ata_port *ap)
/**
- * ata_chk_err - Read device error reg
- * @ap: port where the device is
- *
- * Reads ATA taskfile error register for
- * currently-selected device and return its value.
- *
- * Note: may NOT be used as the check_err() entry in
- * ata_port_operations.
- *
- * LOCKING:
- * Inherited from caller.
- */
-u8 ata_chk_err(struct ata_port *ap)
-{
- if (ap->ops->check_err)
- return ap->ops->check_err(ap);
-
- if (ap->flags & ATA_FLAG_MMIO) {
- return readb((void __iomem *) ap->ioaddr.error_addr);
- }
- return inb(ap->ioaddr.error_addr);
-}
-
-/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert
* @fis: Buffer into which data will output
@@ -542,7 +498,7 @@ u8 ata_chk_err(struct ata_port *ap)
* Inherited from caller.
*/
-void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
+void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
{
fis[0] = 0x27; /* Register - Host to Device FIS */
fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
@@ -583,7 +539,7 @@ void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
* Inherited from caller.
*/
-void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
+void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf)
{
tf->command = fis[2]; /* status */
tf->feature = fis[3]; /* error */
@@ -601,79 +557,53 @@ void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
tf->hob_nsect = fis[13];
}
-/**
- * ata_prot_to_cmd - determine which read/write opcodes to use
- * @protocol: ATA_PROT_xxx taskfile protocol
- * @lba48: true is lba48 is present
- *
- * Given necessary input, determine which read/write commands
- * to use to transfer data.
- *
- * LOCKING:
- * None.
- */
-static int ata_prot_to_cmd(int protocol, int lba48)
-{
- int rcmd = 0, wcmd = 0;
-
- switch (protocol) {
- case ATA_PROT_PIO:
- if (lba48) {
- rcmd = ATA_CMD_PIO_READ_EXT;
- wcmd = ATA_CMD_PIO_WRITE_EXT;
- } else {
- rcmd = ATA_CMD_PIO_READ;
- wcmd = ATA_CMD_PIO_WRITE;
- }
- break;
-
- case ATA_PROT_DMA:
- if (lba48) {
- rcmd = ATA_CMD_READ_EXT;
- wcmd = ATA_CMD_WRITE_EXT;
- } else {
- rcmd = ATA_CMD_READ;
- wcmd = ATA_CMD_WRITE;
- }
- break;
-
- default:
- return -1;
- }
-
- return rcmd | (wcmd << 8);
-}
+static const u8 ata_rw_cmds[] = {
+ /* pio multi */
+ ATA_CMD_READ_MULTI,
+ ATA_CMD_WRITE_MULTI,
+ ATA_CMD_READ_MULTI_EXT,
+ ATA_CMD_WRITE_MULTI_EXT,
+ /* pio */
+ ATA_CMD_PIO_READ,
+ ATA_CMD_PIO_WRITE,
+ ATA_CMD_PIO_READ_EXT,
+ ATA_CMD_PIO_WRITE_EXT,
+ /* dma */
+ ATA_CMD_READ,
+ ATA_CMD_WRITE,
+ ATA_CMD_READ_EXT,
+ ATA_CMD_WRITE_EXT
+};
/**
- * ata_dev_set_protocol - set taskfile protocol and r/w commands
- * @dev: device to examine and configure
+ * ata_rwcmd_protocol - set taskfile r/w commands and protocol
+ * @qc: command to examine and configure
*
- * Examine the device configuration, after we have
- * read the identify-device page and configured the
- * data transfer mode. Set internal state related to
- * the ATA taskfile protocol (pio, pio mult, dma, etc.)
- * and calculate the proper read/write commands to use.
+ * Examine the device configuration and tf->flags to calculate
+ * the proper read/write commands and protocol to use.
*
* LOCKING:
* caller.
*/
-static void ata_dev_set_protocol(struct ata_device *dev)
+void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
{
- int pio = (dev->flags & ATA_DFLAG_PIO);
- int lba48 = (dev->flags & ATA_DFLAG_LBA48);
- int proto, cmd;
+ struct ata_taskfile *tf = &qc->tf;
+ struct ata_device *dev = qc->dev;
- if (pio)
- proto = dev->xfer_protocol = ATA_PROT_PIO;
- else
- proto = dev->xfer_protocol = ATA_PROT_DMA;
+ int index, lba48, write;
+
+ lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
+ write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
- cmd = ata_prot_to_cmd(proto, lba48);
- if (cmd < 0)
- BUG();
+ if (dev->flags & ATA_DFLAG_PIO) {
+ tf->protocol = ATA_PROT_PIO;
+ index = dev->multi_count ? 0 : 4;
+ } else {
+ tf->protocol = ATA_PROT_DMA;
+ index = 8;
+ }
- dev->read_cmd = cmd & 0xff;
- dev->write_cmd = (cmd >> 8) & 0xff;
+ tf->command = ata_rw_cmds[index + lba48 + write];
}
static const char * xfer_mode_str[] = {
@@ -855,7 +785,7 @@ static unsigned int ata_devchk(struct ata_port *ap,
* the event of failure.
*/
-unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(const struct ata_taskfile *tf)
{
/* Apple's open source Darwin code hints that some devices only
* put a proper signature into the LBA mid/high registers,
@@ -907,8 +837,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
memset(&tf, 0, sizeof(tf));
- err = ata_chk_err(ap);
ap->ops->tf_read(ap, &tf);
+ err = tf.feature;
dev->class = ATA_DEV_NONE;
@@ -947,7 +877,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
* caller.
*/
-void ata_dev_id_string(u16 *id, unsigned char *s,
+void ata_dev_id_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len)
{
unsigned int c;
@@ -1064,7 +994,7 @@ void ata_dev_select(struct ata_port *ap, unsigned int device,
* caller.
*/
-static inline void ata_dump_id(struct ata_device *dev)
+static inline void ata_dump_id(const struct ata_device *dev)
{
DPRINTK("49==0x%04x "
"53==0x%04x "
@@ -1092,6 +1022,31 @@ static inline void ata_dump_id(struct ata_device *dev)
dev->id[93]);
}
+/*
+ * Compute the PIO modes available for this device. This is not as
+ * trivial as it seems if we must consider early devices correctly.
+ *
+ * FIXME: pre IDE drive timing (do we care ?).
+ */
+
+static unsigned int ata_pio_modes(const struct ata_device *adev)
+{
+ u16 modes;
+
+ /* Usual case. Word 53 indicates word 88 is valid */
+ if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+ modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
+ modes <<= 3;
+ modes |= 0x7;
+ return modes;
+ }
+
+ /* If word 88 isn't valid then Word 51 holds the PIO timing number
+ for the maximum. Turn it into a mask and return it */
+ modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+ return modes;
+}
+
/**
* ata_dev_identify - obtain IDENTIFY x DEVICE page
* @ap: port on which device we wish to probe resides
@@ -1117,10 +1072,9 @@ static inline void ata_dump_id(struct ata_device *dev)
static void ata_dev_identify(struct ata_port *ap, unsigned int device)
{
struct ata_device *dev = &ap->device[device];
- unsigned int i;
+ unsigned int major_version;
u16 tmp;
unsigned long xfer_modes;
- u8 status;
unsigned int using_edd;
DECLARE_COMPLETION(wait);
struct ata_queued_cmd *qc;
@@ -1174,8 +1128,11 @@ retry:
else
wait_for_completion(&wait);
- status = ata_chk_status(ap);
- if (status & ATA_ERR) {
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->ops->tf_read(ap, &qc->tf);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (qc->tf.command & ATA_ERR) {
/*
* arg! EDD works for all test cases, but seems to return
* the ATA signature for some ATAPI devices. Until the
@@ -1188,7 +1145,7 @@ retry:
* to have this problem.
*/
if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
- u8 err = ata_chk_err(ap);
+ u8 err = qc->tf.feature;
if (err & ATA_ABORTED) {
dev->class = ATA_DEV_ATAPI;
qc->cursg = 0;
@@ -1215,9 +1172,9 @@ retry:
* common ATA, ATAPI feature tests
*/
- /* we require LBA and DMA support (bits 8 & 9 of word 49) */
- if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
- printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+ /* we require DMA support (bits 8 of word 49) */
+ if (!ata_id_has_dma(dev->id)) {
+ printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
goto err_out_nosup;
}
@@ -1225,10 +1182,8 @@ retry:
xfer_modes = dev->id[ATA_ID_UDMA_MODES];
if (!xfer_modes)
xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
- if (!xfer_modes) {
- xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
- xfer_modes |= (0x7 << ATA_SHIFT_PIO);
- }
+ if (!xfer_modes)
+ xfer_modes = ata_pio_modes(dev);
ata_dump_id(dev);
@@ -1237,32 +1192,75 @@ retry:
if (!ata_id_is_ata(dev->id)) /* sanity check */
goto err_out_nosup;
+ /* get major version */
tmp = dev->id[ATA_ID_MAJOR_VER];
- for (i = 14; i >= 1; i--)
- if (tmp & (1 << i))
+ for (major_version = 14; major_version >= 1; major_version--)
+ if (tmp & (1 << major_version))
break;
- /* we require at least ATA-3 */
- if (i < 3) {
- printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
- goto err_out_nosup;
+ /*
+ * The exact sequence expected by certain pre-ATA4 drives is:
+ * SRST RESET
+ * IDENTIFY
+ * INITIALIZE DEVICE PARAMETERS
+ * anything else..
+ * Some drives were very specific about that exact sequence.
+ */
+ if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
+ ata_dev_init_params(ap, dev);
+
+ /* current CHS translation info (id[53-58]) might be
+ * changed. reread the identify device info.
+ */
+ ata_dev_reread_id(ap, dev);
}
- if (ata_id_has_lba48(dev->id)) {
- dev->flags |= ATA_DFLAG_LBA48;
- dev->n_sectors = ata_id_u64(dev->id, 100);
- } else {
- dev->n_sectors = ata_id_u32(dev->id, 60);
+ if (ata_id_has_lba(dev->id)) {
+ dev->flags |= ATA_DFLAG_LBA;
+
+ if (ata_id_has_lba48(dev->id)) {
+ dev->flags |= ATA_DFLAG_LBA48;
+ dev->n_sectors = ata_id_u64(dev->id, 100);
+ } else {
+ dev->n_sectors = ata_id_u32(dev->id, 60);
+ }
+
+ /* print device info to dmesg */
+ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
+ ap->id, device,
+ major_version,
+ ata_mode_string(xfer_modes),
+ (unsigned long long)dev->n_sectors,
+ dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
+ } else {
+ /* CHS */
+
+ /* Default translation */
+ dev->cylinders = dev->id[1];
+ dev->heads = dev->id[3];
+ dev->sectors = dev->id[6];
+ dev->n_sectors = dev->cylinders * dev->heads * dev->sectors;
+
+ if (ata_id_current_chs_valid(dev->id)) {
+ /* Current CHS translation is valid. */
+ dev->cylinders = dev->id[54];
+ dev->heads = dev->id[55];
+ dev->sectors = dev->id[56];
+
+ dev->n_sectors = ata_id_u32(dev->id, 57);
+ }
+
+ /* print device info to dmesg */
+ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
+ ap->id, device,
+ major_version,
+ ata_mode_string(xfer_modes),
+ (unsigned long long)dev->n_sectors,
+ (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
+
}
ap->host->max_cmd_len = 16;
-
- /* print device info to dmesg */
- printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
- ap->id, device,
- ata_mode_string(xfer_modes),
- (unsigned long long)dev->n_sectors,
- dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
}
/* ATAPI-specific feature tests */
@@ -1296,7 +1294,7 @@ err_out:
}
-static inline u8 ata_dev_knobble(struct ata_port *ap)
+static inline u8 ata_dev_knobble(const struct ata_port *ap)
{
return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
}
@@ -1304,12 +1302,12 @@ static inline u8 ata_dev_knobble(struct ata_port *ap)
/**
* ata_dev_config - Run device specific handlers and check for
* SATA->PATA bridges
- * @ap: Bus
+ * @ap: Bus
* @i: Device
*
* LOCKING:
*/
-
+
void ata_dev_config(struct ata_port *ap, unsigned int i)
{
/* limit bridge transfers to udma5, 200 sectors */
@@ -1482,7 +1480,153 @@ void ata_port_disable(struct ata_port *ap)
ap->flags |= ATA_FLAG_PORT_DISABLED;
}
-static struct {
+/*
+ * This mode timing computation functionality is ported over from
+ * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
+ */
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension and UDMA6, which
+ * is currently supported only by Maxtor drives.
+ */
+
+static const struct ata_timing ata_timing[] = {
+
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
+ { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
+
+ { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
+ { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
+ { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
+
+/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
+
+ { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
+ { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
+ { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
+
+ { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
+ { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
+ { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
+
+/* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */
+ { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
+ { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
+
+ { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
+ { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
+ { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
+
+/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
+
+ { 0xFF }
+};
+
+#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
+#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+
+static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
+{
+ q->setup = EZ(t->setup * 1000, T);
+ q->act8b = EZ(t->act8b * 1000, T);
+ q->rec8b = EZ(t->rec8b * 1000, T);
+ q->cyc8b = EZ(t->cyc8b * 1000, T);
+ q->active = EZ(t->active * 1000, T);
+ q->recover = EZ(t->recover * 1000, T);
+ q->cycle = EZ(t->cycle * 1000, T);
+ q->udma = EZ(t->udma * 1000, UT);
+}
+
+void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
+ struct ata_timing *m, unsigned int what)
+{
+ if (what & ATA_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
+ if (what & ATA_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
+ if (what & ATA_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
+ if (what & ATA_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
+ if (what & ATA_TIMING_ACTIVE ) m->active = max(a->active, b->active);
+ if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & ATA_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
+ if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
+}
+
+static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
+{
+ const struct ata_timing *t;
+
+ for (t = ata_timing; t->mode != speed; t++)
+ if (t->mode == 0xFF)
+ return NULL;
+ return t;
+}
+
+int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+ struct ata_timing *t, int T, int UT)
+{
+ const struct ata_timing *s;
+ struct ata_timing p;
+
+ /*
+ * Find the mode.
+ */
+
+ if (!(s = ata_timing_find_mode(speed)))
+ return -EINVAL;
+
+ /*
+ * If the drive is an EIDE drive, it can tell us it needs extended
+ * PIO/MW_DMA cycle timing.
+ */
+
+ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
+ memset(&p, 0, sizeof(p));
+ if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+ if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
+ else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
+ } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+ p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
+ }
+ ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
+ }
+
+ /*
+ * Convert the timing to bus clock counts.
+ */
+
+ ata_timing_quantize(s, t, T, UT);
+
+ /*
+ * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
+ * and some other commands. We have to ensure that the DMA cycle timing is
+ * slower/equal than the fastest PIO timing.
+ */
+
+ if (speed > XFER_PIO_4) {
+ ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
+ ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
+ }
+
+ /*
+ * Lenghten active & recovery time so that cycle time is correct.
+ */
+
+ if (t->act8b + t->rec8b < t->cyc8b) {
+ t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+ t->rec8b = t->cyc8b - t->act8b;
+ }
+
+ if (t->active + t->recover < t->cycle) {
+ t->active += (t->cycle - (t->active + t->recover)) / 2;
+ t->recover = t->cycle - t->active;
+ }
+
+ return 0;
+}
+
+static const struct {
unsigned int shift;
u8 base;
} xfer_mode_classes[] = {
@@ -1589,7 +1733,7 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
*/
static void ata_set_mode(struct ata_port *ap)
{
- unsigned int i, xfer_shift;
+ unsigned int xfer_shift;
u8 xfer_mode;
int rc;
@@ -1618,11 +1762,6 @@ static void ata_set_mode(struct ata_port *ap)
if (ap->ops->post_set_mode)
ap->ops->post_set_mode(ap);
- for (i = 0; i < 2; i++) {
- struct ata_device *dev = &ap->device[i];
- ata_dev_set_protocol(dev);
- }
-
return;
err_out:
@@ -1732,12 +1871,14 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
*
* LOCKING:
* PCI/etc. bus probe sem.
+ * Obtains host_set lock.
*
*/
static unsigned int ata_bus_edd(struct ata_port *ap)
{
struct ata_taskfile tf;
+ unsigned long flags;
/* set up execute-device-diag (bus reset) taskfile */
/* also, take interrupts to a known state (disabled) */
@@ -1748,7 +1889,9 @@ static unsigned int ata_bus_edd(struct ata_port *ap)
tf.protocol = ATA_PROT_NODATA;
/* do bus reset */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
ata_tf_to_host(ap, &tf);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
/* spec says at least 2ms. but who knows with those
* crazy ATAPI devices...
@@ -1896,7 +2039,8 @@ err_out:
DPRINTK("EXIT\n");
}
-static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static void ata_pr_blacklisted(const struct ata_port *ap,
+ const struct ata_device *dev)
{
printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
ap->id, dev->devno);
@@ -1934,7 +2078,7 @@ static const char * ata_dma_blacklist [] = {
"_NEC DV5800A",
};
-static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static int ata_dma_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[40];
char *s;
@@ -1959,9 +2103,9 @@ static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
return 0;
}
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift)
{
- struct ata_device *master, *slave;
+ const struct ata_device *master, *slave;
unsigned int mask;
master = &ap->device[0];
@@ -1973,14 +2117,14 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
mask = ap->udma_mask;
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, master)) {
+ if (ata_dma_blacklisted(master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dma_blacklisted(ap, slave)) {
+ if (ata_dma_blacklisted(slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
@@ -1990,14 +2134,14 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
mask = ap->mwdma_mask;
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, master)) {
+ if (ata_dma_blacklisted(master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
- if (ata_dma_blacklisted(ap, slave)) {
+ if (ata_dma_blacklisted(slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
@@ -2061,7 +2205,7 @@ static int fgb(u32 bitmap)
* Zero on success, negative on error.
*/
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
u8 *xfer_mode_out,
unsigned int *xfer_shift_out)
{
@@ -2130,6 +2274,110 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
}
/**
+ * ata_dev_reread_id - Reread the device identify device info
+ * @ap: port where the device is
+ * @dev: device to reread the identify device info
+ *
+ * LOCKING:
+ */
+
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int rc;
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+ qc->dma_dir = DMA_FROM_DEVICE;
+
+ if (dev->class == ATA_DEV_ATA) {
+ qc->tf.command = ATA_CMD_ID_ATA;
+ DPRINTK("do ATA identify\n");
+ } else {
+ qc->tf.command = ATA_CMD_ID_ATAPI;
+ DPRINTK("do ATAPI identify\n");
+ }
+
+ qc->tf.flags |= ATA_TFLAG_DEVICE;
+ qc->tf.protocol = ATA_PROT_PIO;
+ qc->nsect = 1;
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ goto err_out;
+
+ wait_for_completion(&wait);
+
+ swap_buf_le16(dev->id, ATA_ID_WORDS);
+
+ ata_dump_id(dev);
+
+ DPRINTK("EXIT\n");
+
+ return;
+err_out:
+ ata_port_disable(ap);
+}
+
+/**
+ * ata_dev_init_params - Issue INIT DEV PARAMS command
+ * @ap: Port associated with device @dev
+ * @dev: Device to which command will be sent
+ *
+ * LOCKING:
+ */
+
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ int rc;
+ unsigned long flags;
+ u16 sectors = dev->id[6];
+ u16 heads = dev->id[3];
+
+ /* Number of sectors per track 1-255. Number of heads 1-16 */
+ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+ return;
+
+ /* set up init dev params taskfile */
+ DPRINTK("init dev params \n");
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
+ qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ qc->tf.protocol = ATA_PROT_NODATA;
+ qc->tf.nsect = sectors;
+ qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ ata_port_disable(ap);
+ else
+ wait_for_completion(&wait);
+
+ DPRINTK("EXIT\n");
+}
+
+/**
* ata_sg_clean - Unmap DMA memory associated with command
* @qc: Command containing DMA memory to be released
*
@@ -2268,34 +2516,14 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
* spin_lock_irqsave(host_set lock)
*/
-
-
-/**
- * ata_sg_init_one - Prepare a one-entry scatter-gather list.
- * @qc: Queued command
- * @buf: transfer buffer
- * @buflen: length of buf
- *
- * Builds a single-entry scatter-gather list to initiate a
- * transfer utilizing the specified buffer.
- *
- * LOCKING:
- */
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
{
- struct scatterlist *sg;
-
qc->flags |= ATA_QCFLAG_SINGLE;
- memset(&qc->sgent, 0, sizeof(qc->sgent));
qc->sg = &qc->sgent;
qc->n_elem = 1;
qc->buf_virt = buf;
-
- sg = qc->sg;
- sg->page = virt_to_page(buf);
- sg->offset = (unsigned long) buf & ~PAGE_MASK;
- sg->length = buflen;
+ sg_init_one(qc->sg, buf, buflen);
}
/**
@@ -2312,18 +2540,6 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
* spin_lock_irqsave(host_set lock)
*/
-
-/**
- * ata_sg_init - Assign a scatter gather list to a queued command
- * @qc: Queued command
- * @sg: Scatter-gather list
- * @n_elem: length of sg list
- *
- * Attaches a scatter-gather list to a queued command.
- *
- * LOCKING:
- */
-
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem)
{
@@ -2402,33 +2618,54 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
}
/**
+ * ata_poll_qc_complete - turn irq back on and finish qc
+ * @qc: Command to complete
+ * @drv_stat: ATA status register content
+ *
+ * LOCKING:
+ * None. (grabs host lock)
+ */
+
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+{
+ struct ata_port *ap = qc->ap;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_irq_on(ap);
+ ata_qc_complete(qc, err_mask);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+}
+
+/**
* ata_pio_poll -
- * @ap:
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
*
* RETURNS:
- *
+ * timeout value to use
*/
static unsigned long ata_pio_poll(struct ata_port *ap)
{
u8 status;
- unsigned int poll_state = PIO_ST_UNKNOWN;
- unsigned int reg_state = PIO_ST_UNKNOWN;
- const unsigned int tmout_state = PIO_ST_TMOUT;
-
- switch (ap->pio_task_state) {
- case PIO_ST:
- case PIO_ST_POLL:
- poll_state = PIO_ST_POLL;
- reg_state = PIO_ST;
+ unsigned int poll_state = HSM_ST_UNKNOWN;
+ unsigned int reg_state = HSM_ST_UNKNOWN;
+ const unsigned int tmout_state = HSM_ST_TMOUT;
+
+ switch (ap->hsm_task_state) {
+ case HSM_ST:
+ case HSM_ST_POLL:
+ poll_state = HSM_ST_POLL;
+ reg_state = HSM_ST;
break;
- case PIO_ST_LAST:
- case PIO_ST_LAST_POLL:
- poll_state = PIO_ST_LAST_POLL;
- reg_state = PIO_ST_LAST;
+ case HSM_ST_LAST:
+ case HSM_ST_LAST_POLL:
+ poll_state = HSM_ST_LAST_POLL;
+ reg_state = HSM_ST_LAST;
break;
default:
BUG();
@@ -2438,68 +2675,72 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
status = ata_chk_status(ap);
if (status & ATA_BUSY) {
if (time_after(jiffies, ap->pio_task_timeout)) {
- ap->pio_task_state = tmout_state;
+ ap->hsm_task_state = tmout_state;
return 0;
}
- ap->pio_task_state = poll_state;
+ ap->hsm_task_state = poll_state;
return ATA_SHORT_PAUSE;
}
- ap->pio_task_state = reg_state;
+ ap->hsm_task_state = reg_state;
return 0;
}
/**
- * ata_pio_complete -
- * @ap:
+ * ata_pio_complete - check if drive is busy or idle
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
+ *
+ * RETURNS:
+ * Non-zero if qc completed, zero otherwise.
*/
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
{
struct ata_queued_cmd *qc;
u8 drv_stat;
/*
- * This is purely hueristic. This is a fast path.
- * Sometimes when we enter, BSY will be cleared in
- * a chk-status or two. If not, the drive is probably seeking
- * or something. Snooze for a couple msecs, then
- * chk-status again. If still busy, fall back to
- * PIO_ST_POLL state.
+ * This is purely heuristic. This is a fast path. Sometimes when
+ * we enter, BSY will be cleared in a chk-status or two. If not,
+ * the drive is probably seeking or something. Snooze for a couple
+ * msecs, then chk-status again. If still busy, fall back to
+ * HSM_ST_POLL state.
*/
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
msleep(2);
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
- ap->pio_task_state = PIO_ST_LAST_POLL;
+ ap->hsm_task_state = HSM_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
- return;
+ return 0;
}
}
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
- ap->pio_task_state = PIO_ST_ERR;
- return;
+ ap->hsm_task_state = HSM_ST_ERR;
+ return 0;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
- ap->pio_task_state = PIO_ST_IDLE;
+ ap->hsm_task_state = HSM_ST_IDLE;
- ata_irq_on(ap);
+ ata_poll_qc_complete(qc, 0);
- ata_qc_complete(qc, drv_stat);
+ /* another command may start at this point */
+
+ return 1;
}
/**
- * swap_buf_le16 -
+ * swap_buf_le16 - swap halves of 16-words in place
* @buf: Buffer to swap
* @buf_words: Number of 16-bit words in buffer.
*
@@ -2508,6 +2749,7 @@ static void ata_pio_complete (struct ata_port *ap)
* vice-versa.
*
* LOCKING:
+ * Inherited from caller.
*/
void swap_buf_le16(u16 *buf, unsigned int buf_words)
{
@@ -2519,6 +2761,19 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
#endif /* __BIG_ENDIAN */
}
+/**
+ * ata_mmio_data_xfer - Transfer data by MMIO
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @write_data: read/write
+ *
+ * Transfer data from/to the device data register by MMIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int write_data)
{
@@ -2527,6 +2782,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
u16 *buf16 = (u16 *) buf;
void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+ /* Transfer multiple of 2 bytes */
if (write_data) {
for (i = 0; i < words; i++)
writew(le16_to_cpu(buf16[i]), mmio);
@@ -2534,19 +2790,74 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
for (i = 0; i < words; i++)
buf16[i] = cpu_to_le16(readw(mmio));
}
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ u16 align_buf[1] = { 0 };
+ unsigned char *trailing_buf = buf + buflen - 1;
+
+ if (write_data) {
+ memcpy(align_buf, trailing_buf, 1);
+ writew(le16_to_cpu(align_buf[0]), mmio);
+ } else {
+ align_buf[0] = cpu_to_le16(readw(mmio));
+ memcpy(trailing_buf, align_buf, 1);
+ }
+ }
}
+/**
+ * ata_pio_data_xfer - Transfer data by PIO
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @write_data: read/write
+ *
+ * Transfer data from/to the device data register by PIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int write_data)
{
- unsigned int dwords = buflen >> 1;
+ unsigned int words = buflen >> 1;
+ /* Transfer multiple of 2 bytes */
if (write_data)
- outsw(ap->ioaddr.data_addr, buf, dwords);
+ outsw(ap->ioaddr.data_addr, buf, words);
else
- insw(ap->ioaddr.data_addr, buf, dwords);
+ insw(ap->ioaddr.data_addr, buf, words);
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ u16 align_buf[1] = { 0 };
+ unsigned char *trailing_buf = buf + buflen - 1;
+
+ if (write_data) {
+ memcpy(align_buf, trailing_buf, 1);
+ outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+ } else {
+ align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+ memcpy(trailing_buf, align_buf, 1);
+ }
+ }
}
+/**
+ * ata_data_xfer - Transfer data from/to the data register.
+ * @ap: port to read/write
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @do_write: read/write
+ *
+ * Transfer data from/to the device data register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int do_write)
{
@@ -2556,6 +2867,16 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
ata_pio_data_xfer(ap, buf, buflen, do_write);
}
+/**
+ * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ * @qc: Command on going
+ *
+ * Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void ata_pio_sector(struct ata_queued_cmd *qc)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2566,7 +2887,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
unsigned char *buf;
if (qc->cursect == (qc->nsect - 1))
- ap->pio_task_state = PIO_ST_LAST;
+ ap->hsm_task_state = HSM_ST_LAST;
page = sg[qc->cursg].page;
offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
@@ -2594,6 +2915,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
kunmap(page);
}
+/**
+ * __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ * @qc: Command on going
+ * @bytes: number of bytes
+ *
+ * Transfer Transfer data from/to the ATAPI device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ */
+
static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
{
int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2603,10 +2936,33 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
unsigned char *buf;
unsigned int offset, count;
- if (qc->curbytes == qc->nbytes - bytes)
- ap->pio_task_state = PIO_ST_LAST;
+ if (qc->curbytes + bytes >= qc->nbytes)
+ ap->hsm_task_state = HSM_ST_LAST;
next_sg:
+ if (unlikely(qc->cursg >= qc->n_elem)) {
+ /*
+ * The end of qc->sg is reached and the device expects
+ * more data to transfer. In order not to overrun qc->sg
+ * and fulfill length specified in the byte count register,
+ * - for read case, discard trailing data from the device
+ * - for write case, padding zero data to the device
+ */
+ u16 pad_buf[1] = { 0 };
+ unsigned int words = bytes >> 1;
+ unsigned int i;
+
+ if (words) /* warning if bytes > 1 */
+ printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
+ ap->id, bytes);
+
+ for (i = 0; i < words; i++)
+ ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+ ap->hsm_task_state = HSM_ST_LAST;
+ return;
+ }
+
sg = &qc->sg[qc->cursg];
page = sg->page;
@@ -2640,11 +2996,20 @@ next_sg:
kunmap(page);
- if (bytes) {
+ if (bytes)
goto next_sg;
- }
}
+/**
+ * atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ * @qc: Command on going
+ *
+ * Transfer Transfer data from/to the ATAPI device.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static void atapi_pio_bytes(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@@ -2674,12 +3039,12 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
err_out:
printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
ap->id, dev->devno);
- ap->pio_task_state = PIO_ST_ERR;
+ ap->hsm_task_state = HSM_ST_ERR;
}
/**
- * ata_pio_sector -
- * @ap:
+ * ata_pio_block - start PIO on a block
+ * @ap: the target ata_port
*
* LOCKING:
* None. (executing in kernel thread context)
@@ -2691,19 +3056,19 @@ static void ata_pio_block(struct ata_port *ap)
u8 status;
/*
- * This is purely hueristic. This is a fast path.
+ * This is purely heuristic. This is a fast path.
* Sometimes when we enter, BSY will be cleared in
* a chk-status or two. If not, the drive is probably seeking
* or something. Snooze for a couple msecs, then
* chk-status again. If still busy, fall back to
- * PIO_ST_POLL state.
+ * HSM_ST_POLL state.
*/
status = ata_busy_wait(ap, ATA_BUSY, 5);
if (status & ATA_BUSY) {
msleep(2);
status = ata_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
- ap->pio_task_state = PIO_ST_POLL;
+ ap->hsm_task_state = HSM_ST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
return;
}
@@ -2715,11 +3080,7 @@ static void ata_pio_block(struct ata_port *ap)
if (is_atapi_taskfile(&qc->tf)) {
/* no more data to transfer or unsupported ATAPI command */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_IDLE;
-
- ata_irq_on(ap);
-
- ata_qc_complete(qc, status);
+ ap->hsm_task_state = HSM_ST_LAST;
return;
}
@@ -2727,7 +3088,7 @@ static void ata_pio_block(struct ata_port *ap)
} else {
/* handle BSY=0, DRQ=0 as error */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_ERR;
+ ap->hsm_task_state = HSM_ST_ERR;
return;
}
@@ -2738,101 +3099,54 @@ static void ata_pio_block(struct ata_port *ap)
static void ata_pio_error(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
- u8 drv_stat;
+
+ printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
- drv_stat = ata_chk_status(ap);
- printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
- ap->id, drv_stat);
-
- ap->pio_task_state = PIO_ST_IDLE;
+ ap->hsm_task_state = HSM_ST_IDLE;
- ata_irq_on(ap);
-
- ata_qc_complete(qc, drv_stat | ATA_ERR);
+ ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
}
static void ata_pio_task(void *_data)
{
struct ata_port *ap = _data;
- unsigned long timeout = 0;
+ unsigned long timeout;
+ int qc_completed;
+
+fsm_start:
+ timeout = 0;
+ qc_completed = 0;
- switch (ap->pio_task_state) {
- case PIO_ST_IDLE:
+ switch (ap->hsm_task_state) {
+ case HSM_ST_IDLE:
return;
- case PIO_ST:
+ case HSM_ST:
ata_pio_block(ap);
break;
- case PIO_ST_LAST:
- ata_pio_complete(ap);
+ case HSM_ST_LAST:
+ qc_completed = ata_pio_complete(ap);
break;
- case PIO_ST_POLL:
- case PIO_ST_LAST_POLL:
+ case HSM_ST_POLL:
+ case HSM_ST_LAST_POLL:
timeout = ata_pio_poll(ap);
break;
- case PIO_ST_TMOUT:
- case PIO_ST_ERR:
+ case HSM_ST_TMOUT:
+ case HSM_ST_ERR:
ata_pio_error(ap);
return;
}
if (timeout)
- queue_delayed_work(ata_wq, &ap->pio_task,
- timeout);
- else
- queue_work(ata_wq, &ap->pio_task);
-}
-
-static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
- struct scsi_cmnd *cmd)
-{
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- unsigned long flags;
- int rc;
-
- DPRINTK("ATAPI request sense\n");
-
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
-
- /* FIXME: is this needed? */
- memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
- ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
- qc->dma_dir = DMA_FROM_DEVICE;
-
- memset(&qc->cdb, 0, ap->cdb_len);
- qc->cdb[0] = REQUEST_SENSE;
- qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
-
- qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- qc->tf.command = ATA_CMD_PACKET;
-
- qc->tf.protocol = ATA_PROT_ATAPI;
- qc->tf.lbam = (8 * 1024) & 0xff;
- qc->tf.lbah = (8 * 1024) >> 8;
- qc->nbytes = SCSI_SENSE_BUFFERSIZE;
-
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- if (rc)
- ata_port_disable(ap);
- else
- wait_for_completion(&wait);
-
- DPRINTK("EXIT\n");
+ queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+ else if (!qc_completed)
+ goto fsm_start;
}
/**
@@ -2857,8 +3171,10 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
static void ata_qc_timeout(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ struct ata_host_set *host_set = ap->host_set;
struct ata_device *dev = qc->dev;
u8 host_stat = 0, drv_stat;
+ unsigned long flags;
DPRINTK("ENTER\n");
@@ -2869,7 +3185,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
/* finish completing original command */
+ spin_lock_irqsave(&host_set->lock, flags);
__ata_qc_complete(qc);
+ spin_unlock_irqrestore(&host_set->lock, flags);
atapi_request_sense(ap, dev, cmd);
@@ -2880,6 +3198,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
}
}
+ spin_lock_irqsave(&host_set->lock, flags);
+
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
@@ -2895,7 +3215,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ap->ops->bmdma_stop(qc);
/* fall through */
@@ -2910,9 +3230,12 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
ap->id, qc->tf.command, drv_stat, host_stat);
/* complete taskfile transaction */
- ata_qc_complete(qc, drv_stat);
+ ata_qc_complete(qc, ac_err_mask(drv_stat));
break;
}
+
+ spin_unlock_irqrestore(&host_set->lock, flags);
+
out:
DPRINTK("EXIT\n");
}
@@ -2943,14 +3266,14 @@ void ata_eng_timeout(struct ata_port *ap)
DPRINTK("ENTER\n");
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (!qc) {
+ if (qc)
+ ata_qc_timeout(qc);
+ else {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
- ata_qc_timeout(qc);
-
out:
DPRINTK("EXIT\n");
}
@@ -3007,15 +3330,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
qc->nbytes = qc->curbytes = 0;
ata_tf_init(ap, &qc->tf, dev->devno);
-
- if (dev->flags & ATA_DFLAG_LBA48)
- qc->tf.flags |= ATA_TFLAG_LBA48;
}
return qc;
}
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
{
return 0;
}
@@ -3053,7 +3373,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
- *
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
@@ -3073,10 +3392,9 @@ void ata_qc_free(struct ata_queued_cmd *qc)
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
- *
*/
-void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
{
int rc;
@@ -3086,10 +3404,15 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
- /* call completion callback */
- rc = qc->complete_fn(qc, drv_stat);
+ /* atapi: mark qc as inactive to prevent the interrupt handler
+ * from completing the command twice later, before the error handler
+ * is called. (when rc != 0 and atapi request sense is needed)
+ */
qc->flags &= ~ATA_QCFLAG_ACTIVE;
+ /* call completion callback */
+ rc = qc->complete_fn(qc, err_mask);
+
/* if callback indicates not to complete command (non-zero),
* return immediately
*/
@@ -3195,7 +3518,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_NODATA:
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
break;
case ATA_PROT_DMA:
@@ -3206,23 +3529,25 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
ata_qc_set_polling(qc);
- ata_tf_to_host_nolock(ap, &qc->tf);
- ap->pio_task_state = PIO_ST;
+ ata_tf_to_host(ap, &qc->tf);
+ ap->hsm_task_state = HSM_ST;
queue_work(ata_wq, &ap->pio_task);
break;
case ATA_PROT_ATAPI:
ata_qc_set_polling(qc);
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ata_tf_to_host(ap, &qc->tf);
queue_work(ata_wq, &ap->packet_task);
break;
case ATA_PROT_ATAPI_NODATA:
- ata_tf_to_host_nolock(ap, &qc->tf);
+ ap->flags |= ATA_FLAG_NOINTR;
+ ata_tf_to_host(ap, &qc->tf);
queue_work(ata_wq, &ap->packet_task);
break;
case ATA_PROT_ATAPI_DMA:
+ ap->flags |= ATA_FLAG_NOINTR;
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
queue_work(ata_wq, &ap->packet_task);
@@ -3267,7 +3592,7 @@ static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
}
/**
- * ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
@@ -3431,14 +3756,14 @@ u8 ata_bmdma_status(struct ata_port *ap)
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
/**
* ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- * @ap: Port associated with this ATA transaction.
+ * @qc: Command we are ending DMA for
*
* Clears the ATA_DMA_START flag in the dma control register
*
@@ -3448,8 +3773,9 @@ u8 ata_bmdma_status(struct ata_port *ap)
* spin_lock_irqsave(host_set lock)
*/
-void ata_bmdma_stop(struct ata_port *ap)
+void ata_bmdma_stop(struct ata_queued_cmd *qc)
{
+ struct ata_port *ap = qc->ap;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
@@ -3501,7 +3827,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(ap);
+ ap->ops->bmdma_stop(qc);
/* fall through */
@@ -3523,7 +3849,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
ap->ops->irq_clear(ap);
/* complete taskfile transaction */
- ata_qc_complete(qc, status);
+ ata_qc_complete(qc, ac_err_mask(status));
break;
default:
@@ -3559,7 +3885,6 @@ idle_irq:
*
* RETURNS:
* IRQ_NONE or IRQ_HANDLED.
- *
*/
irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
@@ -3576,7 +3901,8 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -3618,7 +3944,7 @@ static void atapi_packet_task(void *_data)
/* sleep-wait for BSY to clear */
DPRINTK("busy wait\n");
if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
- goto err_out;
+ goto err_out_status;
/* make sure DRQ is set */
status = ata_chk_status(ap);
@@ -3628,27 +3954,37 @@ static void atapi_packet_task(void *_data)
/* send SCSI cdb */
DPRINTK("send cdb\n");
assert(ap->cdb_len >= 12);
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
- /* if we are DMA'ing, irq handler takes over from here */
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
- ap->ops->bmdma_start(qc); /* initiate bmdma */
+ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+ unsigned long flags;
- /* non-data commands are also handled via irq */
- else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
- /* do nothing */
- }
+ /* Once we're done issuing command and kicking bmdma,
+ * irq handler takes over. To not lose irq, we need
+ * to clear NOINTR flag before sending cdb, but
+ * interrupt handler shouldn't be invoked before we're
+ * finished. Hence, the following locking.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+ ap->ops->bmdma_start(qc); /* initiate bmdma */
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ } else {
+ ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
- /* PIO commands are handled by polling */
- else {
- ap->pio_task_state = PIO_ST;
+ /* PIO commands are handled by polling */
+ ap->hsm_task_state = HSM_ST;
queue_work(ata_wq, &ap->pio_task);
}
return;
+err_out_status:
+ status = ata_chk_status(ap);
err_out:
- ata_qc_complete(qc, ATA_ERR);
+ ata_poll_qc_complete(qc, __ac_err_mask(status));
}
@@ -3662,6 +3998,7 @@ err_out:
* May be used as the port_start() entry in ata_port_operations.
*
* LOCKING:
+ * Inherited from caller.
*/
int ata_port_start (struct ata_port *ap)
@@ -3687,6 +4024,7 @@ int ata_port_start (struct ata_port *ap)
* May be used as the port_stop() entry in ata_port_operations.
*
* LOCKING:
+ * Inherited from caller.
*/
void ata_port_stop (struct ata_port *ap)
@@ -3709,6 +4047,7 @@ void ata_host_stop (struct ata_host_set *host_set)
* @do_unregister: 1 if we fully unregister, 0 to just stop the port
*
* LOCKING:
+ * Inherited from caller.
*/
static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
@@ -3736,12 +4075,11 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
*
* LOCKING:
* Inherited from caller.
- *
*/
static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
struct ata_host_set *host_set,
- struct ata_probe_ent *ent, unsigned int port_no)
+ const struct ata_probe_ent *ent, unsigned int port_no)
{
unsigned int i;
@@ -3751,8 +4089,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
host->unique_id = ata_unique_id++;
host->max_cmd_len = 12;
- scsi_assign_lock(host, &host_set->lock);
-
ap->flags = ATA_FLAG_PORT_DISABLED;
ap->id = host->unique_id;
ap->host = host;
@@ -3797,10 +4133,9 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
*
* RETURNS:
* New ata_port on success, for NULL on error.
- *
*/
-static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
+static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
struct ata_host_set *host_set,
unsigned int port_no)
{
@@ -3845,10 +4180,9 @@ err_out:
*
* RETURNS:
* Number of ports registered. Zero on error (no ports registered).
- *
*/
-int ata_device_add(struct ata_probe_ent *ent)
+int ata_device_add(const struct ata_probe_ent *ent)
{
unsigned int count = 0, i;
struct device *dev = ent->dev;
@@ -3856,11 +4190,10 @@ int ata_device_add(struct ata_probe_ent *ent)
DPRINTK("ENTER\n");
/* alloc a container for our list of ATA ports (buses) */
- host_set = kmalloc(sizeof(struct ata_host_set) +
+ host_set = kzalloc(sizeof(struct ata_host_set) +
(ent->n_ports * sizeof(void *)), GFP_KERNEL);
if (!host_set)
return 0;
- memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *)));
spin_lock_init(&host_set->lock);
host_set->dev = dev;
@@ -3900,10 +4233,8 @@ int ata_device_add(struct ata_probe_ent *ent)
count++;
}
- if (!count) {
- kfree(host_set);
- return 0;
- }
+ if (!count)
+ goto err_free_ret;
/* obtain irq, that is shared between channels */
if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
@@ -3948,7 +4279,7 @@ int ata_device_add(struct ata_probe_ent *ent)
for (i = 0; i < count; i++) {
struct ata_port *ap = host_set->ports[i];
- scsi_scan_host(ap->host);
+ ata_scsi_scan_host(ap);
}
dev_set_drvdata(dev, host_set);
@@ -3961,12 +4292,59 @@ err_out:
ata_host_remove(host_set->ports[i], 1);
scsi_host_put(host_set->ports[i]->host);
}
+err_free_ret:
kfree(host_set);
VPRINTK("EXIT, returning 0\n");
return 0;
}
/**
+ * ata_host_set_remove - PCI layer callback for device removal
+ * @host_set: ATA host set that was removed
+ *
+ * Unregister all objects associated with this host set. Free those
+ * objects.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ */
+
+void ata_host_set_remove(struct ata_host_set *host_set)
+{
+ struct ata_port *ap;
+ unsigned int i;
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+ scsi_remove_host(ap->host);
+ }
+
+ free_irq(host_set->irq, host_set);
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+
+ ata_scsi_release(ap->host);
+
+ if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ if (ioaddr->cmd_addr == 0x1f0)
+ release_region(0x1f0, 8);
+ else if (ioaddr->cmd_addr == 0x170)
+ release_region(0x170, 8);
+ }
+
+ scsi_host_put(ap->host);
+ }
+
+ if (host_set->ops->host_stop)
+ host_set->ops->host_stop(host_set);
+
+ kfree(host_set);
+}
+
+/**
* ata_scsi_release - SCSI layer callback hook for host unload
* @host: libata host to be unloaded
*
@@ -4020,19 +4398,17 @@ void ata_std_ports(struct ata_ioports *ioaddr)
}
static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
{
struct ata_probe_ent *probe_ent;
- probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
kobject_name(&(dev->kobj)));
return NULL;
}
- memset(probe_ent, 0, sizeof(*probe_ent));
-
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->dev = dev;
@@ -4048,90 +4424,99 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+#ifdef CONFIG_PCI
+
+void ata_pci_host_stop (struct ata_host_set *host_set)
+{
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+ pci_iounmap(pdev, host_set->mmio_base);
+}
+
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
+ * @ports: bitmap of ports present
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
+ *
+ * The caller need only pass the address of the primary port, the
+ * secondary will be deduced automatically. If the device has non
+ * standard secondary port mappings this function can be called twice,
+ * once for each interface.
*/
-#ifdef CONFIG_PCI
struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
{
struct ata_probe_ent *probe_ent =
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ int p = 0;
+
if (!probe_ent)
return NULL;
- probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
- probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr =
- pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
- probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
- probe_ent->port[1].altstatus_addr =
- probe_ent->port[1].ctl_addr =
- pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
- probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+ if (ports & ATA_PORT_PRIMARY) {
+ probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+ probe_ent->port[p].altstatus_addr =
+ probe_ent->port[p].ctl_addr =
+ pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+ probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+ ata_std_ports(&probe_ent->port[p]);
+ p++;
+ }
- ata_std_ports(&probe_ent->port[0]);
- ata_std_ports(&probe_ent->port[1]);
+ if (ports & ATA_PORT_SECONDARY) {
+ probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+ probe_ent->port[p].altstatus_addr =
+ probe_ent->port[p].ctl_addr =
+ pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+ probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+ ata_std_ports(&probe_ent->port[p]);
+ p++;
+ }
+ probe_ent->n_ports = p;
return probe_ent;
}
-static struct ata_probe_ent *
-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
- struct ata_probe_ent **ppe2)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num)
{
- struct ata_probe_ent *probe_ent, *probe_ent2;
+ struct ata_probe_ent *probe_ent;
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
if (!probe_ent)
return NULL;
- probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
- if (!probe_ent2) {
- kfree(probe_ent);
- return NULL;
- }
-
- probe_ent->n_ports = 1;
- probe_ent->irq = 14;
- probe_ent->hard_port_no = 0;
probe_ent->legacy_mode = 1;
-
- probe_ent2->n_ports = 1;
- probe_ent2->irq = 15;
-
- probe_ent2->hard_port_no = 1;
- probe_ent2->legacy_mode = 1;
-
- probe_ent->port[0].cmd_addr = 0x1f0;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x3f6;
- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
- probe_ent2->port[0].cmd_addr = 0x170;
- probe_ent2->port[0].altstatus_addr =
- probe_ent2->port[0].ctl_addr = 0x376;
- probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-
+ probe_ent->n_ports = 1;
+ probe_ent->hard_port_no = port_num;
+
+ switch(port_num)
+ {
+ case 0:
+ probe_ent->irq = 14;
+ probe_ent->port[0].cmd_addr = 0x1f0;
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr = 0x3f6;
+ break;
+ case 1:
+ probe_ent->irq = 15;
+ probe_ent->port[0].cmd_addr = 0x170;
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr = 0x376;
+ break;
+ }
+ probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
ata_std_ports(&probe_ent->port[0]);
- ata_std_ports(&probe_ent2->port[0]);
-
- *ppe2 = probe_ent2;
return probe_ent;
}
@@ -4154,13 +4539,12 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
*
* RETURNS:
* Zero on success, negative on errno-based value on error.
- *
*/
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
- struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
+ struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
@@ -4177,7 +4561,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
&& (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- /* TODO: support transitioning to native mode? */
+ /* TODO: What if one channel is in native mode ... */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
if ((tmp8 & mask) != mask)
@@ -4185,11 +4569,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
}
/* FIXME... */
- if ((!legacy_mode) && (n_ports > 1)) {
- printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n");
- return -EINVAL;
+ if ((!legacy_mode) && (n_ports > 2)) {
+ printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
+ n_ports = 2;
+ /* For now */
}
+ /* FIXME: Really for ATA it isn't safe because the device may be
+ multi-purpose and we want to leave it alone if it was already
+ enabled. Secondly for shared use as Arjan says we want refcounting
+
+ Checking dev->is_enabled is insufficient as this is not set at
+ boot for the primary video which is BIOS enabled
+ */
+
rc = pci_enable_device(pdev);
if (rc)
return rc;
@@ -4200,6 +4593,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out;
}
+ /* FIXME: Should use platform specific mappers for legacy port ranges */
if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) {
struct resource *conflict, res;
@@ -4244,10 +4638,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out_regions;
if (legacy_mode) {
- probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
- } else
- probe_ent = ata_pci_init_native_mode(pdev, port);
- if (!probe_ent) {
+ if (legacy_mode & (1 << 0))
+ probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
+ if (legacy_mode & (1 << 1))
+ probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+ } else {
+ if (n_ports == 2)
+ probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+ else
+ probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
+ }
+ if (!probe_ent && !probe_ent2) {
rc = -ENOMEM;
goto err_out_regions;
}
@@ -4285,7 +4686,7 @@ err_out:
* @pdev: PCI device that was removed
*
* PCI layer indicates to libata via this hook that
- * hot-unplug or module unload event has occured.
+ * hot-unplug or module unload event has occurred.
* Handle this by unregistering all objects associated
* with this PCI device. Free those objects. Then finally
* release PCI resources and disable device.
@@ -4298,46 +4699,15 @@ void ata_pci_remove_one (struct pci_dev *pdev)
{
struct device *dev = pci_dev_to_dev(pdev);
struct ata_host_set *host_set = dev_get_drvdata(dev);
- struct ata_port *ap;
- unsigned int i;
-
- for (i = 0; i < host_set->n_ports; i++) {
- ap = host_set->ports[i];
-
- scsi_remove_host(ap->host);
- }
-
- free_irq(host_set->irq, host_set);
-
- for (i = 0; i < host_set->n_ports; i++) {
- ap = host_set->ports[i];
-
- ata_scsi_release(ap->host);
-
- if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
- struct ata_ioports *ioaddr = &ap->ioaddr;
-
- if (ioaddr->cmd_addr == 0x1f0)
- release_region(0x1f0, 8);
- else if (ioaddr->cmd_addr == 0x170)
- release_region(0x170, 8);
- }
-
- scsi_host_put(ap->host);
- }
-
- if (host_set->ops->host_stop)
- host_set->ops->host_stop(host_set);
-
- kfree(host_set);
+ ata_host_set_remove(host_set);
pci_release_regions(pdev);
pci_disable_device(pdev);
dev_set_drvdata(dev, NULL);
}
/* move to PCI subsystem */
-int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
+int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
{
unsigned long tmp = 0;
@@ -4390,6 +4760,27 @@ static void __exit ata_exit(void)
module_init(ata_init);
module_exit(ata_exit);
+static unsigned long ratelimit_time;
+static spinlock_t ata_ratelimit_lock = SPIN_LOCK_UNLOCKED;
+
+int ata_ratelimit(void)
+{
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ata_ratelimit_lock, flags);
+
+ if (time_after(jiffies, ratelimit_time)) {
+ rc = 1;
+ ratelimit_time = jiffies + (HZ/5);
+ } else
+ rc = 0;
+
+ spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
+
+ return rc;
+}
+
/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
@@ -4400,6 +4791,7 @@ module_exit(ata_exit);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_host_set_remove);
EXPORT_SYMBOL_GPL(ata_sg_init);
EXPORT_SYMBOL_GPL(ata_sg_init_one);
EXPORT_SYMBOL_GPL(ata_qc_complete);
@@ -4413,7 +4805,6 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
-EXPORT_SYMBOL_GPL(ata_chk_err);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
@@ -4430,6 +4821,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset);
EXPORT_SYMBOL_GPL(ata_bus_reset);
EXPORT_SYMBOL_GPL(ata_port_disable);
+EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_error);
@@ -4441,8 +4833,12 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_timing_compute);
+EXPORT_SYMBOL_GPL(ata_timing_merge);
+
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_host_stop);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 794fb559efb0..248baae96486 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1,25 +1,36 @@
/*
- libata-scsi.c - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
-
+ * libata-scsi.c - helper library for ATA
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 Jeff Garzik
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from
+ * - http://www.t10.org/
+ * - http://www.t13.org/
+ *
*/
#include <linux/kernel.h>
@@ -28,15 +39,66 @@
#include <scsi/scsi.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
#include <linux/libata.h>
+#include <linux/hdreg.h>
#include <asm/uaccess.h>
#include "libata.h"
-typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
-static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
+#define SECTOR_SIZE 512
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+
+#define RW_RECOVERY_MPAGE 0x1
+#define RW_RECOVERY_MPAGE_LEN 12
+#define CACHE_MPAGE 0x8
+#define CACHE_MPAGE_LEN 20
+#define CONTROL_MPAGE 0xa
+#define CONTROL_MPAGE_LEN 12
+#define ALL_MPAGES 0x3f
+#define ALL_SUB_MPAGES 0xff
+
+
+static const u8 def_rw_recovery_mpage[] = {
+ RW_RECOVERY_MPAGE,
+ RW_RECOVERY_MPAGE_LEN - 2,
+ (1 << 7) | /* AWRE, sat-r06 say it shall be 0 */
+ (1 << 6), /* ARRE (auto read reallocation) */
+ 0, /* read retry count */
+ 0, 0, 0, 0,
+ 0, /* write retry count */
+ 0, 0, 0
+};
+
+static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
+ CACHE_MPAGE,
+ CACHE_MPAGE_LEN - 2,
+ 0, /* contains WCE, needs to be 0 for logic */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, /* contains DRA, needs to be 0 for logic */
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
+ CONTROL_MPAGE,
+ CONTROL_MPAGE_LEN - 2,
+ 2, /* DSENSE=0, GLTSD=1 */
+ 0, /* [QAM+QERR may be 1, see 05-359r1] */
+ 0, 0, 0, 0, 0xff, 0xff,
+ 0, 30 /* extended self test time, see 05-359r1 */
+};
+
+
+static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *))
+{
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ done(cmd);
+}
/**
* ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
@@ -67,6 +129,150 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
return 0;
}
+/**
+ * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
+ * @dev: Device to whom we are issuing command
+ * @arg: User provided data for issuing command
+ *
+ * LOCKING:
+ * Defined by the SCSI layer. We don't really care.
+ *
+ * RETURNS:
+ * Zero on success, negative errno on error.
+ */
+
+int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+ int rc = 0;
+ u8 scsi_cmd[MAX_COMMAND_SIZE];
+ u8 args[4], *argbuf = NULL;
+ int argsize = 0;
+ struct scsi_request *sreq;
+
+ if (NULL == (void *)arg)
+ return -EINVAL;
+
+ if (copy_from_user(args, arg, sizeof(args)))
+ return -EFAULT;
+
+ sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+ if (!sreq)
+ return -EINTR;
+
+ memset(scsi_cmd, 0, sizeof(scsi_cmd));
+
+ if (args[3]) {
+ argsize = SECTOR_SIZE * args[3];
+ argbuf = kmalloc(argsize, GFP_KERNEL);
+ if (argbuf == NULL) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ scsi_cmd[1] = (4 << 1); /* PIO Data-in */
+ scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev,
+ block count in sector count field */
+ sreq->sr_data_direction = DMA_FROM_DEVICE;
+ } else {
+ scsi_cmd[1] = (3 << 1); /* Non-data */
+ /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+ sreq->sr_data_direction = DMA_NONE;
+ }
+
+ scsi_cmd[0] = ATA_16;
+
+ scsi_cmd[4] = args[2];
+ if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+ scsi_cmd[6] = args[3];
+ scsi_cmd[8] = args[1];
+ scsi_cmd[10] = 0x4f;
+ scsi_cmd[12] = 0xc2;
+ } else {
+ scsi_cmd[6] = args[1];
+ }
+ scsi_cmd[14] = args[0];
+
+ /* Good values for timeout and retries? Values below
+ from scsi_ioctl_send_command() for default case... */
+ scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);
+
+ if (sreq->sr_result) {
+ rc = -EIO;
+ goto error;
+ }
+
+ /* Need code to retrieve data from check condition? */
+
+ if ((argbuf)
+ && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
+ rc = -EFAULT;
+error:
+ scsi_release_request(sreq);
+
+ if (argbuf)
+ kfree(argbuf);
+
+ return rc;
+}
+
+/**
+ * ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
+ * @dev: Device to whom we are issuing command
+ * @arg: User provided data for issuing command
+ *
+ * LOCKING:
+ * Defined by the SCSI layer. We don't really care.
+ *
+ * RETURNS:
+ * Zero on success, negative errno on error.
+ */
+int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+ int rc = 0;
+ u8 scsi_cmd[MAX_COMMAND_SIZE];
+ u8 args[7];
+ struct scsi_request *sreq;
+
+ if (NULL == (void *)arg)
+ return -EINVAL;
+
+ if (copy_from_user(args, arg, sizeof(args)))
+ return -EFAULT;
+
+ memset(scsi_cmd, 0, sizeof(scsi_cmd));
+ scsi_cmd[0] = ATA_16;
+ scsi_cmd[1] = (3 << 1); /* Non-data */
+ /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+ scsi_cmd[4] = args[1];
+ scsi_cmd[6] = args[2];
+ scsi_cmd[8] = args[3];
+ scsi_cmd[10] = args[4];
+ scsi_cmd[12] = args[5];
+ scsi_cmd[14] = args[0];
+
+ sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+ if (!sreq) {
+ rc = -EINTR;
+ goto error;
+ }
+
+ sreq->sr_data_direction = DMA_NONE;
+ /* Good values for timeout and retries? Values below
+ from scsi_ioctl_send_command() for default case... */
+ scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
+
+ if (sreq->sr_result) {
+ rc = -EIO;
+ goto error;
+ }
+
+ /* Need code to retrieve data from check condition? */
+
+error:
+ scsi_release_request(sreq);
+ return rc;
+}
+
int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
{
struct ata_port *ap;
@@ -96,6 +302,16 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
return -EINVAL;
return 0;
+ case HDIO_DRIVE_CMD:
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ata_cmd_ioctl(scsidev, arg);
+
+ case HDIO_DRIVE_TASK:
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ata_task_ioctl(scsidev, arg);
+
default:
rc = -ENOTTY;
break;
@@ -154,24 +370,70 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
}
/**
+ * ata_dump_status - user friendly display of error info
+ * @id: id of the port in question
+ * @tf: ptr to filled out taskfile
+ *
+ * Decode and dump the ATA error/status registers for the user so
+ * that they have some idea what really happened at the non
+ * make-believe layer.
+ *
+ * LOCKING:
+ * inherited from caller
+ */
+void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+{
+ u8 stat = tf->command, err = tf->feature;
+
+ printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
+ if (stat & ATA_BUSY) {
+ printk("Busy }\n"); /* Data is not valid in this case */
+ } else {
+ if (stat & 0x40) printk("DriveReady ");
+ if (stat & 0x20) printk("DeviceFault ");
+ if (stat & 0x10) printk("SeekComplete ");
+ if (stat & 0x08) printk("DataRequest ");
+ if (stat & 0x04) printk("CorrectedError ");
+ if (stat & 0x02) printk("Index ");
+ if (stat & 0x01) printk("Error ");
+ printk("}\n");
+
+ if (err) {
+ printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
+ if (err & 0x04) printk("DriveStatusError ");
+ if (err & 0x80) {
+ if (err & 0x04) printk("BadCRC ");
+ else printk("Sector ");
+ }
+ if (err & 0x40) printk("UncorrectableError ");
+ if (err & 0x10) printk("SectorIdNotFound ");
+ if (err & 0x02) printk("TrackZeroNotFound ");
+ if (err & 0x01) printk("AddrMarkNotFound ");
+ printk("}\n");
+ }
+ }
+}
+
+/**
* ata_to_sense_error - convert ATA error to SCSI error
- * @qc: Command that we are erroring out
* @drv_stat: value contained in ATA status register
+ * @drv_err: value contained in ATA error register
+ * @sk: the sense key we'll fill out
+ * @asc: the additional sense code we'll fill out
+ * @ascq: the additional sense code qualifier we'll fill out
*
- * Converts an ATA error into a SCSI error. While we are at it
- * we decode and dump the ATA error for the user so that they
- * have some idea what really happened at the non make-believe
- * layer.
+ * Converts an ATA error into a SCSI error. Fill out pointers to
+ * SK, ASC, and ASCQ bytes for later use in fixed or descriptor
+ * format sense blocks.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
-
-void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
+ u8 *ascq)
{
- struct scsi_cmnd *cmd = qc->scsicmd;
- u8 err = 0;
- unsigned char *sb = cmd->sense_buffer;
+ int i;
+
/* Based on the 3ware driver translation table */
static unsigned char sense_table[][4] = {
/* BBD|ECC|ID|MAR */
@@ -212,105 +474,192 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
{0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
- int i = 0;
-
- cmd->result = SAM_STAT_CHECK_CONDITION;
/*
* Is this an error we can process/parse
*/
+ if (drv_stat & ATA_BUSY) {
+ drv_err = 0; /* Ignore the err bits, they're invalid */
+ }
- if(drv_stat & ATA_ERR)
- /* Read the err bits */
- err = ata_chk_err(qc->ap);
+ if (drv_err) {
+ /* Look for drv_err */
+ for (i = 0; sense_table[i][0] != 0xFF; i++) {
+ /* Look for best matches first */
+ if ((sense_table[i][0] & drv_err) ==
+ sense_table[i][0]) {
+ *sk = sense_table[i][1];
+ *asc = sense_table[i][2];
+ *ascq = sense_table[i][3];
+ goto translate_done;
+ }
+ }
+ /* No immediate match */
+ printk(KERN_WARNING "ata%u: no sense translation for "
+ "error 0x%02x\n", id, drv_err);
+ }
- /* Display the ATA level error info */
+ /* Fall back to interpreting status bits */
+ for (i = 0; stat_table[i][0] != 0xFF; i++) {
+ if (stat_table[i][0] & drv_stat) {
+ *sk = stat_table[i][1];
+ *asc = stat_table[i][2];
+ *ascq = stat_table[i][3];
+ goto translate_done;
+ }
+ }
+ /* No error? Undecoded? */
+ printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
+ id, drv_stat);
+
+ /* For our last chance pick, use medium read error because
+ * it's much more common than an ATA drive telling you a write
+ * has failed.
+ */
+ *sk = MEDIUM_ERROR;
+ *asc = 0x11; /* "unrecovered read error" */
+ *ascq = 0x04; /* "auto-reallocation failed" */
+
+ translate_done:
+ printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
+ "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
+ *sk, *asc, *ascq);
+ return;
+}
+
+/*
+ * ata_gen_ata_desc_sense - Generate check condition sense block.
+ * @qc: Command that completed.
+ *
+ * This function is specific to the ATA descriptor format sense
+ * block specified for the ATA pass through commands. Regardless
+ * of whether the command errored or not, return a sense
+ * block. Copy all controller registers into the sense
+ * block. Clear sense key, ASC & ASCQ if there is no error.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->tf;
+ unsigned char *sb = cmd->sense_buffer;
+ unsigned char *desc = sb + 8;
+
+ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+ /*
+ * Read the controller registers.
+ */
+ assert(NULL != qc->ap->ops->tf_read);
+ qc->ap->ops->tf_read(qc->ap, tf);
- printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
- if(drv_stat & 0x80)
- {
- printk("Busy ");
- err = 0; /* Data is not valid in this case */
+ /*
+ * Use ata_to_sense_error() to map status register bits
+ * onto sense key, asc & ascq.
+ */
+ if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+ ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+ &sb[1], &sb[2], &sb[3]);
+ sb[1] &= 0x0f;
}
- else {
- if(drv_stat & 0x40) printk("DriveReady ");
- if(drv_stat & 0x20) printk("DeviceFault ");
- if(drv_stat & 0x10) printk("SeekComplete ");
- if(drv_stat & 0x08) printk("DataRequest ");
- if(drv_stat & 0x04) printk("CorrectedError ");
- if(drv_stat & 0x02) printk("Index ");
- if(drv_stat & 0x01) printk("Error ");
+
+ /*
+ * Sense data is current and format is descriptor.
+ */
+ sb[0] = 0x72;
+
+ desc[0] = 0x09;
+
+ /*
+ * Set length of additional sense data.
+ * Since we only populate descriptor 0, the total
+ * length is the same (fixed) length as descriptor 0.
+ */
+ desc[1] = sb[7] = 14;
+
+ /*
+ * Copy registers into sense buffer.
+ */
+ desc[2] = 0x00;
+ desc[3] = tf->feature; /* == error reg */
+ desc[5] = tf->nsect;
+ desc[7] = tf->lbal;
+ desc[9] = tf->lbam;
+ desc[11] = tf->lbah;
+ desc[12] = tf->device;
+ desc[13] = tf->command; /* == status reg */
+
+ /*
+ * Fill in Extend bit, and the high order bytes
+ * if applicable.
+ */
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ desc[2] |= 0x01;
+ desc[4] = tf->hob_nsect;
+ desc[6] = tf->hob_lbal;
+ desc[8] = tf->hob_lbam;
+ desc[10] = tf->hob_lbah;
}
- printk("}\n");
-
- if(err)
- {
- printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
- if(err & 0x04) printk("DriveStatusError ");
- if(err & 0x80)
- {
- if(err & 0x04)
- printk("BadCRC ");
- else
- printk("Sector ");
- }
- if(err & 0x40) printk("UncorrectableError ");
- if(err & 0x10) printk("SectorIdNotFound ");
- if(err & 0x02) printk("TrackZeroNotFound ");
- if(err & 0x01) printk("AddrMarkNotFound ");
- printk("}\n");
+}
+
+/**
+ * ata_gen_fixed_sense - generate a SCSI fixed sense block
+ * @qc: Command that we are erroring out
+ *
+ * Leverage ata_to_sense_error() to give us the codes. Fit our
+ * LBA in here if there's room.
+ *
+ * LOCKING:
+ * inherited from caller
+ */
+void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->tf;
+ unsigned char *sb = cmd->sense_buffer;
+
+ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+ /*
+ * Read the controller registers.
+ */
+ assert(NULL != qc->ap->ops->tf_read);
+ qc->ap->ops->tf_read(qc->ap, tf);
- /* Should we dump sector info here too ?? */
+ /*
+ * Use ata_to_sense_error() to map status register bits
+ * onto sense key, asc & ascq.
+ */
+ if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+ ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+ &sb[2], &sb[12], &sb[13]);
+ sb[2] &= 0x0f;
}
+ sb[0] = 0x70;
+ sb[7] = 0x0a;
- /* Look for err */
- while(sense_table[i][0] != 0xFF)
- {
- /* Look for best matches first */
- if((sense_table[i][0] & err) == sense_table[i][0])
- {
- sb[0] = 0x70;
- sb[2] = sense_table[i][1];
- sb[7] = 0x0a;
- sb[12] = sense_table[i][2];
- sb[13] = sense_table[i][3];
- return;
- }
- i++;
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ /* TODO: find solution for LBA48 descriptors */
}
- /* No immediate match */
- if(err)
- printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
- i = 0;
- /* Fall back to interpreting status bits */
- while(stat_table[i][0] != 0xFF)
- {
- if(stat_table[i][0] & drv_stat)
- {
- sb[0] = 0x70;
- sb[2] = stat_table[i][1];
- sb[7] = 0x0a;
- sb[12] = stat_table[i][2];
- sb[13] = stat_table[i][3];
- return;
- }
- i++;
+ else if (tf->flags & ATA_TFLAG_LBA) {
+ /* A small (28b) LBA will fit in the 32b info field */
+ sb[0] |= 0x80; /* set valid bit */
+ sb[3] = tf->device & 0x0f;
+ sb[4] = tf->lbah;
+ sb[5] = tf->lbam;
+ sb[6] = tf->lbal;
}
- /* No error ?? */
- printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
- /* additional-sense-code[-qualifier] */
- sb[0] = 0x70;
- sb[2] = MEDIUM_ERROR;
- sb[7] = 0x0A;
- if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
- sb[12] = 0x11; /* "unrecovered read error" */
- sb[13] = 0x04;
- } else {
- sb[12] = 0x0C; /* "write error - */
- sb[13] = 0x02; /* auto-reallocation failed" */
+ else {
+ /* TODO: C/H/S */
}
}
@@ -385,12 +734,83 @@ int ata_scsi_error(struct Scsi_Host *host)
* appropriate place
*/
host->host_failed--;
+ INIT_LIST_HEAD(&host->eh_cmd_q);
DPRINTK("EXIT\n");
return 0;
}
/**
+ * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ * @qc: Storage for translated ATA taskfile
+ * @scsicmd: SCSI command to translate
+ *
+ * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ * (to start). Perhaps these commands should be preceded by
+ * CHECK POWER MODE to see what power mode the device is already in.
+ * [See SAT revision 5 at www.t10.org]
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+ const u8 *scsicmd)
+{
+ struct ata_taskfile *tf = &qc->tf;
+
+ tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+ tf->protocol = ATA_PROT_NODATA;
+ if (scsicmd[1] & 0x1) {
+ ; /* ignore IMMED bit, violates sat-r05 */
+ }
+ if (scsicmd[4] & 0x2)
+ goto invalid_fld; /* LOEJ bit set not supported */
+ if (((scsicmd[4] >> 4) & 0xf) != 0)
+ goto invalid_fld; /* power conditions not supported */
+ if (scsicmd[4] & 0x1) {
+ tf->nsect = 1; /* 1 sector, lba=0 */
+
+ if (qc->dev->flags & ATA_DFLAG_LBA) {
+ qc->tf.flags |= ATA_TFLAG_LBA;
+
+ tf->lbah = 0x0;
+ tf->lbam = 0x0;
+ tf->lbal = 0x0;
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ tf->lbal = 0x1; /* sect */
+ tf->lbam = 0x0; /* cyl low */
+ tf->lbah = 0x0; /* cyl high */
+ }
+
+ tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
+ } else {
+ tf->nsect = 0; /* time period value (0 implies now) */
+ tf->command = ATA_CMD_STANDBY;
+ /* Consider: ATA STANDBY IMMEDIATE command */
+ }
+ /*
+ * Standby and Idle condition timers could be implemented but that
+ * would require libata to implement the Power condition mode page
+ * and allow the user to change it. Changing mode pages requires
+ * MODE SELECT to be implemented.
+ */
+
+ return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
+}
+
+
+/**
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
* @qc: Storage for translated ATA taskfile
* @scsicmd: SCSI command to translate (ignored)
@@ -405,14 +825,14 @@ int ata_scsi_error(struct Scsi_Host *host)
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
tf->flags |= ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;
- if ((tf->flags & ATA_TFLAG_LBA48) &&
+ if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
(ata_id_has_flush_ext(qc->dev->id)))
tf->command = ATA_CMD_FLUSH_EXT;
else
@@ -422,6 +842,99 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
}
/**
+ * scsi_6_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 6-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("six-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 8;
+ lba |= ((u64)scsicmd[3]);
+
+ len |= ((u32)scsicmd[4]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
+ * scsi_10_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 10-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("ten-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 24;
+ lba |= ((u64)scsicmd[3]) << 16;
+ lba |= ((u64)scsicmd[4]) << 8;
+ lba |= ((u64)scsicmd[5]);
+
+ len |= ((u32)scsicmd[7]) << 8;
+ len |= ((u32)scsicmd[8]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
+ * scsi_16_lba_len - Get LBA and transfer length
+ * @scsicmd: SCSI command to translate
+ *
+ * Calculate LBA and transfer length for 16-byte commands.
+ *
+ * RETURNS:
+ * @plba: the LBA
+ * @plen: the transfer length
+ */
+
+static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+ u64 lba = 0;
+ u32 len = 0;
+
+ VPRINTK("sixteen-byte command\n");
+
+ lba |= ((u64)scsicmd[2]) << 56;
+ lba |= ((u64)scsicmd[3]) << 48;
+ lba |= ((u64)scsicmd[4]) << 40;
+ lba |= ((u64)scsicmd[5]) << 32;
+ lba |= ((u64)scsicmd[6]) << 24;
+ lba |= ((u64)scsicmd[7]) << 16;
+ lba |= ((u64)scsicmd[8]) << 8;
+ lba |= ((u64)scsicmd[9]);
+
+ len |= ((u32)scsicmd[10]) << 24;
+ len |= ((u32)scsicmd[11]) << 16;
+ len |= ((u32)scsicmd[12]) << 8;
+ len |= ((u32)scsicmd[13]);
+
+ *plba = lba;
+ *plen = len;
+}
+
+/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
* @scsicmd: SCSI command to translate
@@ -435,82 +948,110 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
- unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+ struct ata_device *dev = qc->dev;
u64 dev_sectors = qc->dev->n_sectors;
- u64 sect = 0;
- u32 n_sect = 0;
+ u64 block;
+ u32 n_block;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;
- tf->device |= ATA_LBA;
- if (scsicmd[0] == VERIFY) {
- sect |= ((u64)scsicmd[2]) << 24;
- sect |= ((u64)scsicmd[3]) << 16;
- sect |= ((u64)scsicmd[4]) << 8;
- sect |= ((u64)scsicmd[5]);
+ if (scsicmd[0] == VERIFY)
+ scsi_10_lba_len(scsicmd, &block, &n_block);
+ else if (scsicmd[0] == VERIFY_16)
+ scsi_16_lba_len(scsicmd, &block, &n_block);
+ else
+ goto invalid_fld;
- n_sect |= ((u32)scsicmd[7]) << 8;
- n_sect |= ((u32)scsicmd[8]);
- }
+ if (!n_block)
+ goto nothing_to_do;
+ if (block >= dev_sectors)
+ goto out_of_range;
+ if ((block + n_block) > dev_sectors)
+ goto out_of_range;
- else if (scsicmd[0] == VERIFY_16) {
- sect |= ((u64)scsicmd[2]) << 56;
- sect |= ((u64)scsicmd[3]) << 48;
- sect |= ((u64)scsicmd[4]) << 40;
- sect |= ((u64)scsicmd[5]) << 32;
- sect |= ((u64)scsicmd[6]) << 24;
- sect |= ((u64)scsicmd[7]) << 16;
- sect |= ((u64)scsicmd[8]) << 8;
- sect |= ((u64)scsicmd[9]);
-
- n_sect |= ((u32)scsicmd[10]) << 24;
- n_sect |= ((u32)scsicmd[11]) << 16;
- n_sect |= ((u32)scsicmd[12]) << 8;
- n_sect |= ((u32)scsicmd[13]);
- }
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf->flags |= ATA_TFLAG_LBA;
- else
- return 1;
+ if (dev->flags & ATA_DFLAG_LBA48) {
+ if (n_block > (64 * 1024))
+ goto invalid_fld;
- if (!n_sect)
- return 1;
- if (sect >= dev_sectors)
- return 1;
- if ((sect + n_sect) > dev_sectors)
- return 1;
- if (lba48) {
- if (n_sect > (64 * 1024))
- return 1;
- } else {
- if (n_sect > 256)
- return 1;
- }
+ /* use LBA48 */
+ tf->flags |= ATA_TFLAG_LBA48;
+ tf->command = ATA_CMD_VERIFY_EXT;
+
+ tf->hob_nsect = (n_block >> 8) & 0xff;
- if (lba48) {
- tf->command = ATA_CMD_VERIFY_EXT;
+ tf->hob_lbah = (block >> 40) & 0xff;
+ tf->hob_lbam = (block >> 32) & 0xff;
+ tf->hob_lbal = (block >> 24) & 0xff;
+ } else {
+ if (n_block > 256)
+ goto invalid_fld;
+
+ /* use LBA28 */
+ tf->command = ATA_CMD_VERIFY;
+
+ tf->device |= (block >> 24) & 0xf;
+ }
- tf->hob_nsect = (n_sect >> 8) & 0xff;
+ tf->nsect = n_block & 0xff;
- tf->hob_lbah = (sect >> 40) & 0xff;
- tf->hob_lbam = (sect >> 32) & 0xff;
- tf->hob_lbal = (sect >> 24) & 0xff;
+ tf->lbah = (block >> 16) & 0xff;
+ tf->lbam = (block >> 8) & 0xff;
+ tf->lbal = block & 0xff;
+
+ tf->device |= ATA_LBA;
} else {
+ /* CHS */
+ u32 sect, head, cyl, track;
+
+ if (n_block > 256)
+ goto invalid_fld;
+
+ /* Convert LBA to CHS */
+ track = (u32)block / dev->sectors;
+ cyl = track / dev->heads;
+ head = track % dev->heads;
+ sect = (u32)block % dev->sectors + 1;
+
+ DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+ (u32)block, track, cyl, head, sect);
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
+ Head: 0-15
+ Sector: 1-255*/
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ goto out_of_range;
+
tf->command = ATA_CMD_VERIFY;
-
- tf->device |= (sect >> 24) & 0xf;
+ tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device |= head;
}
- tf->nsect = n_sect & 0xff;
+ return 0;
- tf->lbah = (sect >> 16) & 0xff;
- tf->lbam = (sect >> 8) & 0xff;
- tf->lbal = sect & 0xff;
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
- return 0;
+out_of_range:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ /* "Logical Block Address out of range" */
+ return 1;
+
+nothing_to_do:
+ qc->scsicmd->result = SAM_STAT_GOOD;
+ return 1;
}
/**
@@ -533,107 +1074,175 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
* Zero on success, non-zero on error.
*/
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct ata_taskfile *tf = &qc->tf;
- unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+ struct ata_device *dev = qc->dev;
+ u64 block;
+ u32 n_block;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- tf->protocol = qc->dev->xfer_protocol;
- tf->device |= ATA_LBA;
- if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
- scsicmd[0] == READ_16) {
- tf->command = qc->dev->read_cmd;
- } else {
- tf->command = qc->dev->write_cmd;
+ if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
+ scsicmd[0] == WRITE_16)
tf->flags |= ATA_TFLAG_WRITE;
+
+ /* Calculate the SCSI LBA and transfer length. */
+ switch (scsicmd[0]) {
+ case READ_10:
+ case WRITE_10:
+ scsi_10_lba_len(scsicmd, &block, &n_block);
+ break;
+ case READ_6:
+ case WRITE_6:
+ scsi_6_lba_len(scsicmd, &block, &n_block);
+
+ /* for 6-byte r/w commands, transfer length 0
+ * means 256 blocks of data, not 0 block.
+ */
+ if (!n_block)
+ n_block = 256;
+ break;
+ case READ_16:
+ case WRITE_16:
+ scsi_16_lba_len(scsicmd, &block, &n_block);
+ break;
+ default:
+ DPRINTK("no-byte command\n");
+ goto invalid_fld;
}
- if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
- if (lba48) {
- tf->hob_nsect = scsicmd[7];
- tf->hob_lbal = scsicmd[2];
+ /* Check and compose ATA command */
+ if (!n_block)
+ /* For 10-byte and 16-byte SCSI R/W commands, transfer
+ * length 0 means transfer 0 block of data.
+ * However, for ATA R/W commands, sector count 0 means
+ * 256 or 65536 sectors, not 0 sectors as in SCSI.
+ */
+ goto nothing_to_do;
- qc->nsect = ((unsigned int)scsicmd[7] << 8) |
- scsicmd[8];
- } else {
- /* if we don't support LBA48 addressing, the request
- * -may- be too large. */
- if ((scsicmd[2] & 0xf0) || scsicmd[7])
- return 1;
+ if (dev->flags & ATA_DFLAG_LBA) {
+ tf->flags |= ATA_TFLAG_LBA;
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[2];
+ if (dev->flags & ATA_DFLAG_LBA48) {
+ /* The request -may- be too large for LBA48. */
+ if ((block >> 48) || (n_block > 65536))
+ goto out_of_range;
- qc->nsect = scsicmd[8];
- }
+ /* use LBA48 */
+ tf->flags |= ATA_TFLAG_LBA48;
- tf->nsect = scsicmd[8];
- tf->lbal = scsicmd[5];
- tf->lbam = scsicmd[4];
- tf->lbah = scsicmd[3];
+ tf->hob_nsect = (n_block >> 8) & 0xff;
- VPRINTK("ten-byte command\n");
- return 0;
- }
+ tf->hob_lbah = (block >> 40) & 0xff;
+ tf->hob_lbam = (block >> 32) & 0xff;
+ tf->hob_lbal = (block >> 24) & 0xff;
+ } else {
+ /* use LBA28 */
- if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
- qc->nsect = tf->nsect = scsicmd[4];
- tf->lbal = scsicmd[3];
- tf->lbam = scsicmd[2];
- tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
+ /* The request -may- be too large for LBA28. */
+ if ((block >> 28) || (n_block > 256))
+ goto out_of_range;
- VPRINTK("six-byte command\n");
- return 0;
- }
+ tf->device |= (block >> 24) & 0xf;
+ }
- if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
- /* rule out impossible LBAs and sector counts */
- if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
- return 1;
+ ata_rwcmd_protocol(qc);
- if (lba48) {
- tf->hob_nsect = scsicmd[12];
- tf->hob_lbal = scsicmd[6];
- tf->hob_lbam = scsicmd[5];
- tf->hob_lbah = scsicmd[4];
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff;
- qc->nsect = ((unsigned int)scsicmd[12] << 8) |
- scsicmd[13];
- } else {
- /* once again, filter out impossible non-zero values */
- if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
- (scsicmd[6] & 0xf0))
- return 1;
+ tf->lbah = (block >> 16) & 0xff;
+ tf->lbam = (block >> 8) & 0xff;
+ tf->lbal = block & 0xff;
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[6];
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ u32 sect, head, cyl, track;
- qc->nsect = scsicmd[13];
- }
+ /* The request -may- be too large for CHS addressing. */
+ if ((block >> 28) || (n_block > 256))
+ goto out_of_range;
- tf->nsect = scsicmd[13];
- tf->lbal = scsicmd[9];
- tf->lbam = scsicmd[8];
- tf->lbah = scsicmd[7];
+ ata_rwcmd_protocol(qc);
- VPRINTK("sixteen-byte command\n");
- return 0;
+ /* Convert LBA to CHS */
+ track = (u32)block / dev->sectors;
+ cyl = track / dev->heads;
+ head = track % dev->heads;
+ sect = (u32)block % dev->sectors + 1;
+
+ DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+ (u32)block, track, cyl, head, sect);
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
+ Head: 0-15
+ Sector: 1-255*/
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ goto out_of_range;
+
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device |= head;
}
- DPRINTK("no-byte command\n");
+ return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
+
+out_of_range:
+ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ /* "Logical Block Address out of range" */
+ return 1;
+
+nothing_to_do:
+ qc->scsicmd->result = SAM_STAT_GOOD;
return 1;
}
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
+ unsigned int err_mask)
{
struct scsi_cmnd *cmd = qc->scsicmd;
+ u8 *cdb = cmd->cmnd;
+ int need_sense = (err_mask != 0);
+
+ /* For ATA pass thru (SAT) commands, generate a sense block if
+ * user mandated it or if there's an error. Note that if we
+ * generate because the user forced us to, a check condition
+ * is generated and the ATA register values are returned
+ * whether the command completed successfully or not. If there
+ * was no error, SK, ASC and ASCQ will all be zero.
+ */
+ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
+ ((cdb[2] & 0x20) || need_sense)) {
+ ata_gen_ata_desc_sense(qc);
+ } else {
+ if (!need_sense) {
+ cmd->result = SAM_STAT_GOOD;
+ } else {
+ /* TODO: decide which descriptor format to use
+ * for 48b LBA devices and call that here
+ * instead of the fixed desc, which is only
+ * good for smaller LBA (and maybe CHS?)
+ * devices.
+ */
+ ata_gen_fixed_sense(qc);
+ }
+ }
- if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
- ata_to_sense_error(qc, drv_stat);
- else
- cmd->result = SAM_STAT_GOOD;
+ if (need_sense) {
+ /* The ata_gen_..._sense routines fill in tf */
+ ata_dump_status(qc->ap->id, &qc->tf);
+ }
qc->scsidone(cmd);
@@ -655,6 +1264,12 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
* This function sets up an ata_queued_cmd structure for the
* SCSI command, and sends that ata_queued_cmd to the hardware.
*
+ * The xlat_func argument (actor) returns 0 if ready to execute
+ * ATA command, else 1 to finish translation. If 1 is returned
+ * then cmd->result (and possibly cmd->sense_buffer) are assumed
+ * to be set reflecting an error condition or clean (early)
+ * termination.
+ *
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
@@ -671,7 +1286,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
qc = ata_scsi_qc_new(ap, dev, cmd, done);
if (!qc)
- return;
+ goto err_mem;
/* data is present; dma-map it */
if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
@@ -679,7 +1294,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
if (unlikely(cmd->request_bufflen < 1)) {
printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
ap->id, dev->devno);
- goto err_out;
+ goto err_did;
}
if (cmd->use_sg)
@@ -694,19 +1309,28 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
qc->complete_fn = ata_scsi_qc_complete;
if (xlat_func(qc, scsicmd))
- goto err_out;
+ goto early_finish;
/* select device, send command to hardware */
if (ata_qc_issue(qc))
- goto err_out;
+ goto err_did;
VPRINTK("EXIT\n");
return;
-err_out:
+early_finish:
+ ata_qc_free(qc);
+ done(cmd);
+ DPRINTK("EXIT - early finish (good or error)\n");
+ return;
+
+err_did:
ata_qc_free(qc);
- ata_bad_cdb(cmd, done);
- DPRINTK("EXIT - badcmd\n");
+err_mem:
+ cmd->result = (DID_ERROR << 16);
+ done(cmd);
+ DPRINTK("EXIT - internal\n");
+ return;
}
/**
@@ -773,7 +1397,8 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* Mapping the response buffer, calling the command's handler,
* and handling the handler's return value. This return value
* indicates whether the handler wishes the SCSI command to be
- * completed successfully, or not.
+ * completed successfully (0), or not (in which case cmd->result
+ * and sense buffer are assumed to be set).
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -792,12 +1417,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
rc = actor(args, rbuf, buflen);
ata_scsi_rbuf_put(cmd, rbuf);
- if (rc)
- ata_bad_cdb(cmd, args->done);
- else {
+ if (rc == 0)
cmd->result = SAM_STAT_GOOD;
- args->done(cmd);
- }
+ args->done(cmd);
}
/**
@@ -1011,13 +1633,9 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
const u8 *last)
{
- u8 page[] = {
- 0x8, /* page code */
- 0x12, /* page length */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 zeroes */
- 0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */
- };
+ u8 page[CACHE_MPAGE_LEN];
+ memcpy(page, def_cache_mpage, sizeof(page));
if (ata_id_wcache_enabled(id))
page[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id))
@@ -1041,15 +1659,9 @@ static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
{
- const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
-
- /* byte 2: set the descriptor format sense data bit (bit 2)
- * since we need to support returning this format for SAT
- * commands and any SCSI commands against a 48b LBA device.
- */
-
- ata_msense_push(ptr_io, last, page, sizeof(page));
- return sizeof(page);
+ ata_msense_push(ptr_io, last, def_control_mpage,
+ sizeof(def_control_mpage));
+ return sizeof(def_control_mpage);
}
/**
@@ -1066,15 +1678,10 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
{
- const u8 page[] = {
- 0x1, /* page code */
- 0xa, /* page length */
- (1 << 7) | (1 << 6), /* note auto r/w reallocation */
- 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
- };
- ata_msense_push(ptr_io, last, page, sizeof(page));
- return sizeof(page);
+ ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
+ sizeof(def_rw_recovery_mpage));
+ return sizeof(def_rw_recovery_mpage);
}
/**
@@ -1083,7 +1690,9 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
- * Simulate MODE SENSE commands.
+ * Simulate MODE SENSE commands. Assume this is invoked for direct
+ * access devices (e.g. disks) only. There should be no block
+ * descriptor for other device types.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
@@ -1093,61 +1702,115 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
u8 *scsicmd = args->cmd->cmnd, *p, *last;
- unsigned int page_control, six_byte, output_len;
+ const u8 sat_blk_desc[] = {
+ 0, 0, 0, 0, /* number of blocks: sat unspecified */
+ 0,
+ 0, 0x2, 0x0 /* block length: 512 bytes */
+ };
+ u8 pg, spg;
+ unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
VPRINTK("ENTER\n");
six_byte = (scsicmd[0] == MODE_SENSE);
-
- /* we only support saved and current values (which we treat
- * in the same manner)
+ ebd = !(scsicmd[1] & 0x8); /* dbd bit inverted == edb */
+ /*
+ * LLBA bit in msense(10) ignored (compliant)
*/
+
page_control = scsicmd[2] >> 6;
- if ((page_control != 0) && (page_control != 3))
- return 1;
+ switch (page_control) {
+ case 0: /* current */
+ break; /* supported */
+ case 3: /* saved */
+ goto saving_not_supp;
+ case 1: /* changeable */
+ case 2: /* defaults */
+ default:
+ goto invalid_fld;
+ }
- if (six_byte)
- output_len = 4;
- else
- output_len = 8;
+ if (six_byte) {
+ output_len = 4 + (ebd ? 8 : 0);
+ alloc_len = scsicmd[4];
+ } else {
+ output_len = 8 + (ebd ? 8 : 0);
+ alloc_len = (scsicmd[7] << 8) + scsicmd[8];
+ }
+ minlen = (alloc_len < buflen) ? alloc_len : buflen;
p = rbuf + output_len;
- last = rbuf + buflen - 1;
+ last = rbuf + minlen - 1;
+
+ pg = scsicmd[2] & 0x3f;
+ spg = scsicmd[3];
+ /*
+ * No mode subpages supported (yet) but asking for _all_
+ * subpages may be valid
+ */
+ if (spg && (spg != ALL_SUB_MPAGES))
+ goto invalid_fld;
- switch(scsicmd[2] & 0x3f) {
- case 0x01: /* r/w error recovery */
+ switch(pg) {
+ case RW_RECOVERY_MPAGE:
output_len += ata_msense_rw_recovery(&p, last);
break;
- case 0x08: /* caching */
+ case CACHE_MPAGE:
output_len += ata_msense_caching(args->id, &p, last);
break;
- case 0x0a: { /* control mode */
+ case CONTROL_MPAGE: {
output_len += ata_msense_ctl_mode(&p, last);
break;
}
- case 0x3f: /* all pages */
+ case ALL_MPAGES:
output_len += ata_msense_rw_recovery(&p, last);
output_len += ata_msense_caching(args->id, &p, last);
output_len += ata_msense_ctl_mode(&p, last);
break;
default: /* invalid page code */
- return 1;
+ goto invalid_fld;
}
+ if (minlen < 1)
+ return 0;
if (six_byte) {
output_len--;
rbuf[0] = output_len;
+ if (ebd) {
+ if (minlen > 3)
+ rbuf[3] = sizeof(sat_blk_desc);
+ if (minlen > 11)
+ memcpy(rbuf + 4, sat_blk_desc,
+ sizeof(sat_blk_desc));
+ }
} else {
output_len -= 2;
rbuf[0] = output_len >> 8;
- rbuf[1] = output_len;
+ if (minlen > 1)
+ rbuf[1] = output_len;
+ if (ebd) {
+ if (minlen > 7)
+ rbuf[7] = sizeof(sat_blk_desc);
+ if (minlen > 15)
+ memcpy(rbuf + 8, sat_blk_desc,
+ sizeof(sat_blk_desc));
+ }
}
-
return 0;
+
+invalid_fld:
+ ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ /* "Invalid field in cbd" */
+ return 1;
+
+saving_not_supp:
+ ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+ /* "Saving parameters not supported" */
+ return 1;
}
/**
@@ -1170,10 +1833,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
VPRINTK("ENTER\n");
- if (ata_id_has_lba48(args->id))
- n_sectors = ata_id_u64(args->id, 100);
- else
- n_sectors = ata_id_u32(args->id, 60);
+ if (ata_id_has_lba(args->id)) {
+ if (ata_id_has_lba48(args->id))
+ n_sectors = ata_id_u64(args->id, 100);
+ else
+ n_sectors = ata_id_u32(args->id, 60);
+ } else {
+ /* CHS default translation */
+ n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+ if (ata_id_current_chs_valid(args->id))
+ /* CHS current translation */
+ n_sectors = ata_id_u32(args->id, 57);
+ }
+
n_sectors--; /* ATA TotalUserSectors - 1 */
if (args->cmd->cmnd[0] == READ_CAPACITY) {
@@ -1237,6 +1910,34 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
}
/**
+ * ata_scsi_set_sense - Set SCSI sense data and status
+ * @cmd: SCSI request to be handled
+ * @sk: SCSI-defined sense key
+ * @asc: SCSI-defined additional sense code
+ * @ascq: SCSI-defined additional sense code qualifier
+ *
+ * Helper function that builds a valid fixed format, current
+ * response code and the given sense key (sk), additional sense
+ * code (asc) and additional sense code qualifier (ascq) with
+ * a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+ * DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+ *
+ * LOCKING:
+ * Not required
+ */
+
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+ cmd->sense_buffer[0] = 0x70; /* fixed format, current */
+ cmd->sense_buffer[2] = sk;
+ cmd->sense_buffer[7] = 18 - 8; /* additional sense length */
+ cmd->sense_buffer[12] = asc;
+ cmd->sense_buffer[13] = ascq;
+}
+
+/**
* ata_scsi_badcmd - End a SCSI request with an error
* @cmd: SCSI request to be handled
* @done: SCSI command completion function
@@ -1254,30 +1955,89 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{
DPRINTK("ENTER\n");
- cmd->result = SAM_STAT_CHECK_CONDITION;
-
- cmd->sense_buffer[0] = 0x70;
- cmd->sense_buffer[2] = ILLEGAL_REQUEST;
- cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */
- cmd->sense_buffer[12] = asc;
- cmd->sense_buffer[13] = ascq;
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
done(cmd);
}
-static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+ struct scsi_cmnd *cmd)
+{
+ DECLARE_COMPLETION(wait);
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int rc;
+
+ DPRINTK("ATAPI request sense\n");
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ /* FIXME: is this needed? */
+ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+ ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+ qc->dma_dir = DMA_FROM_DEVICE;
+
+ memset(&qc->cdb, 0, ap->cdb_len);
+ qc->cdb[0] = REQUEST_SENSE;
+ qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+ qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ qc->tf.command = ATA_CMD_PACKET;
+
+ qc->tf.protocol = ATA_PROT_ATAPI;
+ qc->tf.lbam = (8 * 1024) & 0xff;
+ qc->tf.lbah = (8 * 1024) >> 8;
+ qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+
+ qc->waiting = &wait;
+ qc->complete_fn = ata_qc_complete_noop;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ rc = ata_qc_issue(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (rc)
+ ata_port_disable(ap);
+ else
+ wait_for_completion(&wait);
+
+ DPRINTK("EXIT\n");
+}
+
+static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
{
struct scsi_cmnd *cmd = qc->scsicmd;
- if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+ VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
+
+ if (unlikely(err_mask & AC_ERR_DEV)) {
DPRINTK("request check condition\n");
+ /* FIXME: command completion with check condition
+ * but no sense causes the error handler to run,
+ * which then issues REQUEST SENSE, fills in the sense
+ * buffer, and completes the command (for the second
+ * time). We need to issue REQUEST SENSE some other
+ * way, to avoid completing the command twice.
+ */
cmd->result = SAM_STAT_CHECK_CONDITION;
qc->scsidone(cmd);
return 1;
- } else {
+ }
+
+ else if (unlikely(err_mask))
+ /* FIXME: not quite right; we don't want the
+ * translation of taskfile registers into
+ * a sense descriptors, since that's only
+ * correct for ATA, not ATAPI
+ */
+ ata_gen_ata_desc_sense(qc);
+
+ else {
u8 *scsicmd = cmd->cmnd;
if (scsicmd[0] == INQUIRY) {
@@ -1285,15 +2045,30 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
unsigned int buflen;
buflen = ata_scsi_rbuf_get(cmd, &buf);
- buf[2] = 0x5;
- buf[3] = (buf[3] & 0xf0) | 2;
+
+ /* ATAPI devices typically report zero for their SCSI version,
+ * and sometimes deviate from the spec WRT response data
+ * format. If SCSI version is reported as zero like normal,
+ * then we make the following fixups: 1) Fake MMC-5 version,
+ * to indicate to the Linux scsi midlayer this is a modern
+ * device. 2) Ensure response data format / ATAPI information
+ * are always correct.
+ */
+ /* FIXME: do we ever override EVPD pages and the like, with
+ * this code?
+ */
+ if (buf[2] == 0) {
+ buf[2] = 0x5;
+ buf[3] = 0x32;
+ }
+
ata_scsi_rbuf_put(cmd, buf);
}
+
cmd->result = SAM_STAT_GOOD;
}
qc->scsidone(cmd);
-
return 0;
}
/**
@@ -1308,7 +2083,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
* Zero on success, non-zero on failure.
*/
-static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
{
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
@@ -1377,7 +2152,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
*/
static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
{
struct ata_device *dev;
@@ -1394,14 +2169,151 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
if (unlikely(!ata_dev_present(dev)))
return NULL;
-#ifndef ATA_ENABLE_ATAPI
- if (unlikely(dev->class == ATA_DEV_ATAPI))
- return NULL;
-#endif
+ if (!atapi_enabled) {
+ if (unlikely(dev->class == ATA_DEV_ATAPI))
+ return NULL;
+ }
return dev;
}
+/*
+ * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ * @byte1: Byte 1 from pass-thru CDB.
+ *
+ * RETURNS:
+ * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
+ */
+static u8
+ata_scsi_map_proto(u8 byte1)
+{
+ switch((byte1 & 0x1e) >> 1) {
+ case 3: /* Non-data */
+ return ATA_PROT_NODATA;
+
+ case 6: /* DMA */
+ return ATA_PROT_DMA;
+
+ case 4: /* PIO Data-in */
+ case 5: /* PIO Data-out */
+ if (byte1 & 0xe0) {
+ return ATA_PROT_PIO_MULT;
+ }
+ return ATA_PROT_PIO;
+
+ case 10: /* Device Reset */
+ case 0: /* Hard Reset */
+ case 1: /* SRST */
+ case 2: /* Bus Idle */
+ case 7: /* Packet */
+ case 8: /* DMA Queued */
+ case 9: /* Device Diagnostic */
+ case 11: /* UDMA Data-in */
+ case 12: /* UDMA Data-Out */
+ case 13: /* FPDMA */
+ default: /* Reserved */
+ break;
+ }
+
+ return ATA_PROT_UNKNOWN;
+}
+
+/**
+ * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ * @qc: command structure to be initialized
+ * @cmd: SCSI command to convert
+ *
+ * Handles either 12 or 16-byte versions of the CDB.
+ *
+ * RETURNS:
+ * Zero on success, non-zero on failure.
+ */
+static unsigned int
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+ struct ata_taskfile *tf = &(qc->tf);
+ struct scsi_cmnd *cmd = qc->scsicmd;
+
+ if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
+ return 1;
+
+ /*
+ * 12 and 16 byte CDBs use different offsets to
+ * provide the various register values.
+ */
+ if (scsicmd[0] == ATA_16) {
+ /*
+ * 16-byte CDB - may contain extended commands.
+ *
+ * If that is the case, copy the upper byte register values.
+ */
+ if (scsicmd[1] & 0x01) {
+ tf->hob_feature = scsicmd[3];
+ tf->hob_nsect = scsicmd[5];
+ tf->hob_lbal = scsicmd[7];
+ tf->hob_lbam = scsicmd[9];
+ tf->hob_lbah = scsicmd[11];
+ tf->flags |= ATA_TFLAG_LBA48;
+ } else
+ tf->flags &= ~ATA_TFLAG_LBA48;
+
+ /*
+ * Always copy low byte, device and command registers.
+ */
+ tf->feature = scsicmd[4];
+ tf->nsect = scsicmd[6];
+ tf->lbal = scsicmd[8];
+ tf->lbam = scsicmd[10];
+ tf->lbah = scsicmd[12];
+ tf->device = scsicmd[13];
+ tf->command = scsicmd[14];
+ } else {
+ /*
+ * 12-byte CDB - incapable of extended commands.
+ */
+ tf->flags &= ~ATA_TFLAG_LBA48;
+
+ tf->feature = scsicmd[3];
+ tf->nsect = scsicmd[4];
+ tf->lbal = scsicmd[5];
+ tf->lbam = scsicmd[6];
+ tf->lbah = scsicmd[7];
+ tf->device = scsicmd[8];
+ tf->command = scsicmd[9];
+ }
+
+ /*
+ * Filter SET_FEATURES - XFER MODE command -- otherwise,
+ * SET_FEATURES - XFER MODE must be preceded/succeeded
+ * by an update to hardware-specific registers for each
+ * controller (i.e. the reason for ->set_piomode(),
+ * ->set_dmamode(), and ->post_set_mode() hooks).
+ */
+ if ((tf->command == ATA_CMD_SET_FEATURES)
+ && (tf->feature == SETFEATURES_XFER))
+ return 1;
+
+ /*
+ * Set flags so that all registers will be written,
+ * and pass on write indication (used for PIO/DMA
+ * setup.)
+ */
+ tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
+
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ tf->flags |= ATA_TFLAG_WRITE;
+
+ /*
+ * Set transfer length.
+ *
+ * TODO: find out if we need to do more here to
+ * cover scatter/gather case.
+ */
+ qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
+
+ return 0;
+}
+
/**
* ata_get_xlat_func - check if SCSI to ATA translation is possible
* @dev: ATA device
@@ -1434,6 +2346,13 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case VERIFY:
case VERIFY_16:
return ata_scsi_verify_xlat;
+
+ case ATA_12:
+ case ATA_16:
+ return ata_scsi_pass_thru;
+
+ case START_STOP:
+ return ata_scsi_start_stop_xlat;
}
return NULL;
@@ -1487,8 +2406,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
struct ata_port *ap;
struct ata_device *dev;
struct scsi_device *scsidev = cmd->device;
+ struct Scsi_Host *shost = scsidev->host;
- ap = (struct ata_port *) &scsidev->host->hostdata[0];
+ ap = (struct ata_port *) &shost->hostdata[0];
+
+ spin_unlock(shost->host_lock);
+ spin_lock(&ap->host_set->lock);
ata_scsi_dump_cdb(ap, cmd);
@@ -1511,6 +2434,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
out_unlock:
+ spin_unlock(&ap->host_set->lock);
+ spin_lock(shost->host_lock);
return 0;
}
@@ -1532,7 +2457,7 @@ void ata_scsi_simulate(u16 *id,
void (*done)(struct scsi_cmnd *))
{
struct ata_scsi_args args;
- u8 *scsicmd = cmd->cmnd;
+ const u8 *scsicmd = cmd->cmnd;
args.id = id;
args.cmd = cmd;
@@ -1552,7 +2477,7 @@ void ata_scsi_simulate(u16 *id,
case INQUIRY:
if (scsicmd[1] & 2) /* is CmdDt set? */
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
else if (scsicmd[2] == 0x00)
@@ -1562,7 +2487,7 @@ void ata_scsi_simulate(u16 *id,
else if (scsicmd[2] == 0x83)
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
else
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case MODE_SENSE:
@@ -1572,7 +2497,7 @@ void ata_scsi_simulate(u16 *id,
case MODE_SELECT: /* unconditionally return */
case MODE_SELECT_10: /* bad-field-in-cdb */
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case READ_CAPACITY:
@@ -1583,20 +2508,38 @@ void ata_scsi_simulate(u16 *id,
if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
else
- ata_bad_cdb(cmd, done);
+ ata_scsi_invalid_field(cmd, done);
break;
case REPORT_LUNS:
ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
break;
- /* mandantory commands we haven't implemented yet */
+ /* mandatory commands we haven't implemented yet */
case REQUEST_SENSE:
/* all other commands */
default:
- ata_bad_scsiop(cmd, done);
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ /* "Invalid command operation code" */
+ done(cmd);
break;
}
}
+void ata_scsi_scan_host(struct ata_port *ap)
+{
+ struct ata_device *dev;
+ unsigned int i;
+
+ if (ap->flags & ATA_FLAG_PORT_DISABLED)
+ return;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ dev = &ap->device[i];
+
+ if (ata_dev_present(dev))
+ scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
+ }
+}
+
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index d90430bbb0de..fad051ca4672 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -1,32 +1,35 @@
/*
- libata.h - helper library for ATA
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
-
+ * libata.h - helper library for ATA
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 Jeff Garzik
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
*/
#ifndef __LIBATA_H__
#define __LIBATA_H__
#define DRV_NAME "libata"
-#define DRV_VERSION "1.11" /* must be exactly four chars */
+#define DRV_VERSION "1.12" /* must be exactly four chars */
struct ata_scsi_args {
u16 *id;
@@ -35,19 +38,25 @@ struct ata_scsi_args {
};
/* libata-core.c */
+extern int atapi_enabled;
+extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
+extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep);
-extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
/* libata-scsi.c */
-extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
+extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+ struct scsi_cmnd *cmd);
+extern void ata_scsi_scan_host(struct ata_port *ap);
extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
@@ -72,18 +81,10 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+ u8 sk, u8 asc, u8 ascq);
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
-static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
- ata_scsi_badcmd(cmd, done, 0x20, 0x00);
-}
-
-static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
- ata_scsi_badcmd(cmd, done, 0x24, 0x00);
-}
-
#endif /* __LIBATA_H__ */
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3bb82aae432e..adb95674823f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -342,9 +342,6 @@ struct lpfc_hba {
#define VPD_MASK 0xf /* mask for any vpd data */
struct timer_list els_tmofunc;
-
- void *link_stats;
-
/*
* stat counters
*/
@@ -370,6 +367,8 @@ struct lpfc_hba {
struct list_head freebufList;
struct list_head ctrspbuflist;
struct list_head rnidrspbuflist;
+
+ struct fc_host_statistics link_stats;
};
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3cea92883019..acae7c48ef7d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
@@ -965,21 +966,21 @@ static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
- u64 nodename;
+ u64 node_name;
spin_lock_irq(shost->host_lock);
if ((phba->fc_flag & FC_FABRIC) ||
((phba->fc_topology == TOPOLOGY_LOOP) &&
(phba->fc_flag & FC_PUBLIC_LOOP)))
- memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64));
+ node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
/* fabric is local port if there is no F/FL_Port */
- memcpy(&nodename, &phba->fc_nodename, sizeof(u64));
+ node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
spin_unlock_irq(shost->host_lock);
- fc_host_fabric_name(shost) = be64_to_cpu(nodename);
+ fc_host_fabric_name(shost) = node_name;
}
@@ -988,8 +989,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
{
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
struct lpfc_sli *psli = &phba->sli;
- struct fc_host_statistics *hs =
- (struct fc_host_statistics *)phba->link_stats;
+ struct fc_host_statistics *hs = &phba->link_stats;
LPFC_MBOXQ_t *pmboxq;
MAILBOX_t *pmb;
int rc=0;
@@ -1020,6 +1020,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
return NULL;
}
+ memset(hs, 0, sizeof (struct fc_host_statistics));
+
hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
@@ -1101,21 +1103,20 @@ lpfc_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
- uint64_t node_name = 0;
+ u64 node_name = 0;
struct lpfc_nodelist *ndlp = NULL;
spin_lock_irq(shost->host_lock);
/* Search the mapped list for this target ID */
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
if (starget->id == ndlp->nlp_sid) {
- memcpy(&node_name, &ndlp->nlp_nodename,
- sizeof(struct lpfc_name));
+ node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
break;
}
}
spin_unlock_irq(shost->host_lock);
- fc_starget_node_name(starget) = be64_to_cpu(node_name);
+ fc_starget_node_name(starget) = node_name;
}
static void
@@ -1123,21 +1124,20 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
- uint64_t port_name = 0;
+ u64 port_name = 0;
struct lpfc_nodelist *ndlp = NULL;
spin_lock_irq(shost->host_lock);
/* Search the mapped list for this target ID */
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
if (starget->id == ndlp->nlp_sid) {
- memcpy(&port_name, &ndlp->nlp_portname,
- sizeof(struct lpfc_name));
+ port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
break;
}
}
spin_unlock_irq(shost->host_lock);
- fc_starget_port_name(starget) = be64_to_cpu(port_name);
+ fc_starget_port_name(starget) = port_name;
}
static void
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 78adee4699af..1280f0e54636 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -27,8 +27,10 @@
#include <linux/interrupt.h>
#include <linux/utsname.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
#include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 2b1c9572dae7..63caf7fe9725 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 233901e9dfde..56052f4510c3 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -24,6 +24,7 @@
#include <linux/kthread.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
@@ -1016,13 +1017,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
struct fc_rport *rport;
struct lpfc_rport_data *rdata;
struct fc_rport_identifiers rport_ids;
- uint64_t wwn;
/* Remote port has reappeared. Re-register w/ FC transport */
- memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t));
- rport_ids.node_name = be64_to_cpu(wwn);
- memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t));
- rport_ids.port_name = be64_to_cpu(wwn);
+ rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+ rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rport_ids.port_id = ndlp->nlp_DID;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
if (ndlp->nlp_type & NLP_FCP_TARGET)
@@ -1135,6 +1133,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
switch(list) {
case NLP_NO_LIST: /* No list, just remove it */
lpfc_nlp_remove(phba, nlp);
+ /* as node removed - stop further transport calls */
+ rport_del = none;
break;
case NLP_UNUSED_LIST:
spin_lock_irq(phba->host->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 21591cb9f551..86c41981188b 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -262,12 +262,14 @@ struct lpfc_sli_ct_request {
#define FF_FRAME_SIZE 2048
struct lpfc_name {
+ union {
+ struct {
#ifdef __BIG_ENDIAN_BITFIELD
- uint8_t nameType:4; /* FC Word 0, bit 28:31 */
- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */
+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
#else /* __LITTLE_ENDIAN_BITFIELD */
- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
- uint8_t nameType:4; /* FC Word 0, bit 28:31 */
+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */
#endif
#define NAME_IEEE 0x1 /* IEEE name - nameType */
@@ -276,8 +278,11 @@ struct lpfc_name {
#define NAME_IP_TYPE 0x4 /* IP address */
#define NAME_CCITT_TYPE 0xC
#define NAME_CCITT_GR_TYPE 0xE
- uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */
- uint8_t IEEE[6]; /* FC IEEE address */
+ uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */
+ uint8_t IEEE[6]; /* FC IEEE address */
+ } s;
+ uint8_t wwn[8];
+ } u;
};
struct csp {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 34d416d2b007..0856ff7d3b33 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
@@ -284,7 +285,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
if (phba->SerialNumber[0] == 0) {
uint8_t *outptr;
- outptr = (uint8_t *) & phba->fc_nodename.IEEE[0];
+ outptr = &phba->fc_nodename.u.s.IEEE[0];
for (i = 0; i < 12; i++) {
status = *outptr++;
j = ((status & 0xf0) >> 4);
@@ -1332,21 +1333,18 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
unsigned long bar0map_len, bar2map_len;
int error = -ENODEV, retval;
int i;
- u64 wwname;
if (pci_enable_device(pdev))
goto out;
if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
goto out_disable_device;
- host = scsi_host_alloc(&lpfc_template,
- sizeof (struct lpfc_hba) + sizeof (unsigned long));
+ host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
if (!host)
goto out_release_regions;
phba = (struct lpfc_hba*)host->hostdata;
memset(phba, 0, sizeof (struct lpfc_hba));
- phba->link_stats = (void *)&phba[1];
phba->host = host;
phba->fc_flag |= FC_LOADING;
@@ -1525,10 +1523,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
* Must done after lpfc_sli_hba_setup()
*/
- memcpy(&wwname, &phba->fc_nodename, sizeof(u64));
- fc_host_node_name(host) = be64_to_cpu(wwname);
- memcpy(&wwname, &phba->fc_portname, sizeof(u64));
- fc_host_port_name(host) = be64_to_cpu(wwname);
+ fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn);
+ fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn);
fc_host_supported_classes(host) = FC_COS_CLASS3;
memset(fc_host_supported_fc4s(host), 0,
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index c27cf94795db..73eb89f91593 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -23,6 +23,11 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
#include "lpfc_hw.h"
#include "lpfc_sli.h"
#include "lpfc_disc.h"
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index a5cfb6421fa9..352df47bcaca 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -23,6 +23,11 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include <scsi/scsi.h>
+
#include "lpfc_hw.h"
#include "lpfc_sli.h"
#include "lpfc_disc.h"
@@ -34,7 +39,7 @@
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
static void *
-lpfc_pool_kmalloc(unsigned int gfp_flags, void *data)
+lpfc_pool_kmalloc(gfp_t gfp_flags, void *data)
{
return kmalloc((unsigned long)data, gfp_flags);
}
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 45dc0210fc49..9b35eaac781d 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 17e4974d4445..b5ad1871d34b 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -40,11 +40,6 @@
#define LPFC_RESET_WAIT 2
#define LPFC_ABORT_WAIT 2
-static inline void lpfc_put_lun(struct fcp_cmnd *fcmd, unsigned int lun)
-{
- fcmd->fcpLunLsl = 0;
- fcmd->fcpLunMsl = swab16((uint16_t)lun);
-}
/*
* This routine allocates a scsi buffer, which contains all the necessary
@@ -238,6 +233,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
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);
num_bde = 1;
bpl++;
@@ -245,8 +242,11 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
/*
* Finish initializing those IOCB fields that are dependent on the
- * scsi_cmnd request_buffer
+ * 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.
*/
+ 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;
@@ -445,8 +445,11 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
int datadir = scsi_cmnd->sc_data_direction;
lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+ /* clear task management bits */
+ lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
- lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+ int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+ &lpfc_cmd->fcp_cmnd->fcp_lun);
memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16);
@@ -545,7 +548,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
piocb = &piocbq->iocb;
fcp_cmnd = lpfc_cmd->fcp_cmnd;
- lpfc_put_lun(lpfc_cmd->fcp_cmnd, lpfc_cmd->pCmd->device->lun);
+ int_to_scsilun(lpfc_cmd->pCmd->device->lun,
+ &lpfc_cmd->fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
@@ -746,6 +750,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
goto out_fail_command;
}
+ else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+ cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ goto out_fail_command;
+ }
/*
* The device is most likely recovered and the driver
* needs a bit more time to finish. Ask the midlayer
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 0fd9ba14e1b5..acd64c49e849 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -78,18 +78,7 @@ struct fcp_rsp {
};
struct fcp_cmnd {
- uint32_t fcpLunMsl; /* most significant lun word (32 bits) */
- uint32_t fcpLunLsl; /* least significant lun word (32 bits) */
- /* # of bits to shift lun id to end up in right
- * payload word, little endian = 8, big = 16.
- */
-#ifdef __BIG_ENDIAN
-#define FC_LUN_SHIFT 16
-#define FC_ADDR_MODE_SHIFT 24
-#else /* __LITTLE_ENDIAN */
-#define FC_LUN_SHIFT 8
-#define FC_ADDR_MODE_SHIFT 0
-#endif
+ struct scsi_lun fcp_lun;
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1775508ed276..e74e224fd77c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -24,9 +24,11 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
#include "lpfc_hw.h"
#include "lpfc_sli.h"
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 47dea48ee0ec..7e6747b06f90 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.0.29"
+#define LPFC_DRIVER_VERSION "8.0.30"
#define LPFC_DRIVER_NAME "lpfc"
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 6f308ebe3e79..61a6fd810bb4 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -621,8 +621,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
if(islogical) {
switch (cmd->cmnd[0]) {
case TEST_UNIT_READY:
- memset(cmd->request_buffer, 0, cmd->request_bufflen);
-
#if MEGA_HAVE_CLUSTERING
/*
* Do we support clustering and is the support enabled
@@ -652,11 +650,28 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
return NULL;
#endif
- case MODE_SENSE:
+ case MODE_SENSE: {
+ char *buf;
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *)cmd->request_buffer;
+ buf = kmap_atomic(sg->page, KM_IRQ0) +
+ sg->offset;
+ } else
+ buf = cmd->request_buffer;
memset(cmd->request_buffer, 0, cmd->cmnd[4]);
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *)cmd->request_buffer;
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
cmd->result = (DID_OK << 16);
cmd->scsi_done(cmd);
return NULL;
+ }
case READ_CAPACITY:
case INQUIRY:
@@ -1685,14 +1700,23 @@ mega_rundoneq (adapter_t *adapter)
static void
mega_free_scb(adapter_t *adapter, scb_t *scb)
{
+ unsigned long length;
+
switch( scb->dma_type ) {
case MEGA_DMA_TYPE_NONE:
break;
case MEGA_BULK_DATA:
+ if (scb->cmd->use_sg == 0)
+ length = scb->cmd->request_bufflen;
+ else {
+ struct scatterlist *sgl =
+ (struct scatterlist *)scb->cmd->request_buffer;
+ length = sgl->length;
+ }
pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
- scb->cmd->request_bufflen, scb->dma_direction);
+ length, scb->dma_direction);
break;
case MEGA_SGLIST:
@@ -1741,6 +1765,7 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
struct scatterlist *sgl;
struct page *page;
unsigned long offset;
+ unsigned int length;
Scsi_Cmnd *cmd;
int sgcnt;
int idx;
@@ -1748,14 +1773,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
cmd = scb->cmd;
/* Scatter-gather not used */
- if( !cmd->use_sg ) {
-
- page = virt_to_page(cmd->request_buffer);
- offset = offset_in_page(cmd->request_buffer);
+ if( cmd->use_sg == 0 || (cmd->use_sg == 1 &&
+ !adapter->has_64bit_addr)) {
+
+ if (cmd->use_sg == 0) {
+ page = virt_to_page(cmd->request_buffer);
+ offset = offset_in_page(cmd->request_buffer);
+ length = cmd->request_bufflen;
+ } else {
+ sgl = (struct scatterlist *)cmd->request_buffer;
+ page = sgl->page;
+ offset = sgl->offset;
+ length = sgl->length;
+ }
scb->dma_h_bulkdata = pci_map_page(adapter->dev,
page, offset,
- cmd->request_bufflen,
+ length,
scb->dma_direction);
scb->dma_type = MEGA_BULK_DATA;
@@ -1765,14 +1799,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
*/
if( adapter->has_64bit_addr ) {
scb->sgl64[0].address = scb->dma_h_bulkdata;
- scb->sgl64[0].length = cmd->request_bufflen;
+ scb->sgl64[0].length = length;
*buf = (u32)scb->sgl_dma_addr;
- *len = (u32)cmd->request_bufflen;
+ *len = (u32)length;
return 1;
}
else {
*buf = (u32)scb->dma_h_bulkdata;
- *len = (u32)cmd->request_bufflen;
+ *len = (u32)length;
}
return 0;
}
@@ -1791,27 +1825,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
if( sgcnt > adapter->sglen ) BUG();
+ *len = 0;
+
for( idx = 0; idx < sgcnt; idx++, sgl++ ) {
if( adapter->has_64bit_addr ) {
scb->sgl64[idx].address = sg_dma_address(sgl);
- scb->sgl64[idx].length = sg_dma_len(sgl);
+ *len += scb->sgl64[idx].length = sg_dma_len(sgl);
}
else {
scb->sgl[idx].address = sg_dma_address(sgl);
- scb->sgl[idx].length = sg_dma_len(sgl);
+ *len += scb->sgl[idx].length = sg_dma_len(sgl);
}
}
/* Reset pointer and length fields */
*buf = scb->sgl_dma_addr;
- /*
- * For passthru command, dataxferlen must be set, even for commands
- * with a sg list
- */
- *len = (u32)cmd->request_bufflen;
-
/* Return count of SG requests */
return sgcnt;
}
diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
index 917d591d90b2..7363e12663ac 100644
--- a/drivers/scsi/megaraid/Kconfig.megaraid
+++ b/drivers/scsi/megaraid/Kconfig.megaraid
@@ -76,3 +76,12 @@ config MEGARAID_LEGACY
To compile this driver as a module, choose M here: the
module will be called megaraid
endif
+
+config MEGARAID_SAS
+ tristate "LSI Logic MegaRAID SAS RAID Module"
+ depends on PCI && SCSI
+ help
+ Module for LSI Logic's SAS based RAID controllers.
+ To compile this driver as a module, choose 'm' here.
+ Module will be called megaraid_sas
+
diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
index 6dd99f275722..f469915b97c3 100644
--- a/drivers/scsi/megaraid/Makefile
+++ b/drivers/scsi/megaraid/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o
obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o
+obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index d47be8e0ea3a..c9e743ba09ec 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -76,7 +76,7 @@ static void megaraid_exit(void);
static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
static void megaraid_detach_one(struct pci_dev *);
-static void megaraid_mbox_shutdown(struct device *);
+static void megaraid_mbox_shutdown(struct pci_dev *);
static int megaraid_io_attach(adapter_t *);
static void megaraid_io_detach(adapter_t *);
@@ -369,9 +369,7 @@ static struct pci_driver megaraid_pci_driver_g = {
.id_table = pci_id_table_g,
.probe = megaraid_probe_one,
.remove = __devexit_p(megaraid_detach_one),
- .driver = {
- .shutdown = megaraid_mbox_shutdown,
- }
+ .shutdown = megaraid_mbox_shutdown,
};
@@ -673,9 +671,9 @@ megaraid_detach_one(struct pci_dev *pdev)
* Shutdown notification, perform flush cache
*/
static void
-megaraid_mbox_shutdown(struct device *device)
+megaraid_mbox_shutdown(struct pci_dev *pdev)
{
- adapter_t *adapter = pci_get_drvdata(to_pci_dev(device));
+ adapter_t *adapter = pci_get_drvdata(pdev);
static int counter;
if (!adapter) {
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
new file mode 100644
index 000000000000..c3f637395734
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -0,0 +1,2806 @@
+/*
+ *
+ * Linux MegaRAID driver for SAS based RAID controllers
+ *
+ * Copyright (c) 2003-2005 LSI Logic Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * FILE : megaraid_sas.c
+ * Version : v00.00.02.00-rc4
+ *
+ * Authors:
+ * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
+ * Sumant Patro <Sumant.Patro@lsil.com>
+ *
+ * List of supported controllers
+ *
+ * OEM Product Name VID DID SSVID SSID
+ * --- ------------ --- --- ---- ----
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/uio.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include "megaraid_sas.h"
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MEGASAS_VERSION);
+MODULE_AUTHOR("sreenivas.bagalkote@lsil.com");
+MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver");
+
+/*
+ * PCI ID table for all supported controllers
+ */
+static struct pci_device_id megasas_pci_table[] = {
+
+ {
+ PCI_VENDOR_ID_LSI_LOGIC,
+ PCI_DEVICE_ID_LSI_SAS1064R,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ },
+ {
+ PCI_VENDOR_ID_DELL,
+ PCI_DEVICE_ID_DELL_PERC5,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ },
+ {0} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(pci, megasas_pci_table);
+
+static int megasas_mgmt_majorno;
+static struct megasas_mgmt_info megasas_mgmt_info;
+static struct fasync_struct *megasas_async_queue;
+static DECLARE_MUTEX(megasas_async_queue_mutex);
+
+/**
+ * megasas_get_cmd - Get a command from the free pool
+ * @instance: Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+ *instance)
+{
+ unsigned long flags;
+ struct megasas_cmd *cmd = NULL;
+
+ spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+
+ if (!list_empty(&instance->cmd_pool)) {
+ cmd = list_entry((&instance->cmd_pool)->next,
+ struct megasas_cmd, list);
+ list_del_init(&cmd->list);
+ } else {
+ printk(KERN_ERR "megasas: Command pool empty!\n");
+ }
+
+ spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+ return cmd;
+}
+
+/**
+ * megasas_return_cmd - Return a cmd to free command pool
+ * @instance: Adapter soft state
+ * @cmd: Command packet to be returned to free command pool
+ */
+static inline void
+megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+
+ cmd->scmd = NULL;
+ list_add_tail(&cmd->list, &instance->cmd_pool);
+
+ spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+/**
+ * megasas_enable_intr - Enables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_enable_intr(struct megasas_register_set __iomem * regs)
+{
+ writel(1, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr - Disables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_disable_intr(struct megasas_register_set __iomem * regs)
+{
+ u32 mask = readl(&regs->outbound_intr_mask) & (~0x00000001);
+ writel(mask, &regs->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_issue_polled - Issues a polling command
+ * @instance: Adapter soft state
+ * @cmd: Command packet to be issued
+ *
+ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+ */
+static int
+megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ int i;
+ u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
+
+ struct megasas_header *frame_hdr = &cmd->frame->hdr;
+
+ frame_hdr->cmd_status = 0xFF;
+ frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+ /*
+ * Issue the frame using inbound queue port
+ */
+ writel(cmd->frame_phys_addr >> 3,
+ &instance->reg_set->inbound_queue_port);
+
+ /*
+ * Wait for cmd_status to change
+ */
+ for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
+ rmb();
+ msleep(1);
+ }
+
+ if (frame_hdr->cmd_status == 0xff)
+ return -ETIME;
+
+ return 0;
+}
+
+/**
+ * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds
+ * @instance: Adapter soft state
+ * @cmd: Command to be issued
+ *
+ * This function waits on an event for the command to be returned from ISR.
+ * Used to issue ioctl commands.
+ */
+static int
+megasas_issue_blocked_cmd(struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ cmd->cmd_status = ENODATA;
+
+ writel(cmd->frame_phys_addr >> 3,
+ &instance->reg_set->inbound_queue_port);
+
+ wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA));
+
+ return 0;
+}
+
+/**
+ * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd
+ * @instance: Adapter soft state
+ * @cmd_to_abort: Previously issued cmd to be aborted
+ *
+ * MFI firmware can abort previously issued AEN comamnd (automatic event
+ * notification). The megasas_issue_blocked_abort_cmd() issues such abort
+ * cmd and blocks till it is completed.
+ */
+static int
+megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
+ struct megasas_cmd *cmd_to_abort)
+{
+ struct megasas_cmd *cmd;
+ struct megasas_abort_frame *abort_fr;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd)
+ return -1;
+
+ abort_fr = &cmd->frame->abort;
+
+ /*
+ * Prepare and issue the abort frame
+ */
+ abort_fr->cmd = MFI_CMD_ABORT;
+ abort_fr->cmd_status = 0xFF;
+ abort_fr->flags = 0;
+ abort_fr->abort_context = cmd_to_abort->index;
+ abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
+ abort_fr->abort_mfi_phys_addr_hi = 0;
+
+ cmd->sync_cmd = 1;
+ cmd->cmd_status = 0xFF;
+
+ writel(cmd->frame_phys_addr >> 3,
+ &instance->reg_set->inbound_queue_port);
+
+ /*
+ * Wait for this cmd to complete
+ */
+ wait_event(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF));
+
+ megasas_return_cmd(instance, cmd);
+ return 0;
+}
+
+/**
+ * megasas_make_sgl32 - Prepares 32-bit SGL
+ * @instance: Adapter soft state
+ * @scp: SCSI command from the mid-layer
+ * @mfi_sgl: SGL to be filled in
+ *
+ * If successful, this function returns the number of SG elements. Otherwise,
+ * it returnes -1.
+ */
+static inline int
+megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ union megasas_sgl *mfi_sgl)
+{
+ int i;
+ int sge_count;
+ struct scatterlist *os_sgl;
+
+ /*
+ * Return 0 if there is no data transfer
+ */
+ if (!scp->request_buffer || !scp->request_bufflen)
+ return 0;
+
+ if (!scp->use_sg) {
+ mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev,
+ scp->
+ request_buffer,
+ scp->
+ request_bufflen,
+ scp->
+ sc_data_direction);
+ mfi_sgl->sge32[0].length = scp->request_bufflen;
+
+ return 1;
+ }
+
+ os_sgl = (struct scatterlist *)scp->request_buffer;
+ sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
+ scp->sc_data_direction);
+
+ for (i = 0; i < sge_count; i++, os_sgl++) {
+ mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
+ mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
+ }
+
+ return sge_count;
+}
+
+/**
+ * megasas_make_sgl64 - Prepares 64-bit SGL
+ * @instance: Adapter soft state
+ * @scp: SCSI command from the mid-layer
+ * @mfi_sgl: SGL to be filled in
+ *
+ * If successful, this function returns the number of SG elements. Otherwise,
+ * it returnes -1.
+ */
+static inline int
+megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ union megasas_sgl *mfi_sgl)
+{
+ int i;
+ int sge_count;
+ struct scatterlist *os_sgl;
+
+ /*
+ * Return 0 if there is no data transfer
+ */
+ if (!scp->request_buffer || !scp->request_bufflen)
+ return 0;
+
+ if (!scp->use_sg) {
+ mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev,
+ scp->
+ request_buffer,
+ scp->
+ request_bufflen,
+ scp->
+ sc_data_direction);
+
+ mfi_sgl->sge64[0].length = scp->request_bufflen;
+
+ return 1;
+ }
+
+ os_sgl = (struct scatterlist *)scp->request_buffer;
+ sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
+ scp->sc_data_direction);
+
+ for (i = 0; i < sge_count; i++, os_sgl++) {
+ mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
+ mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
+ }
+
+ return sge_count;
+}
+
+/**
+ * megasas_build_dcdb - Prepares a direct cdb (DCDB) command
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @cmd: Command to be prepared in
+ *
+ * This function prepares CDB commands. These are typcially pass-through
+ * commands to the devices.
+ */
+static inline int
+megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ struct megasas_cmd *cmd)
+{
+ u32 sge_sz;
+ int sge_bytes;
+ u32 is_logical;
+ u32 device_id;
+ u16 flags = 0;
+ struct megasas_pthru_frame *pthru;
+
+ is_logical = MEGASAS_IS_LOGICAL(scp);
+ device_id = MEGASAS_DEV_INDEX(instance, scp);
+ pthru = (struct megasas_pthru_frame *)cmd->frame;
+
+ if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+ flags = MFI_FRAME_DIR_WRITE;
+ else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ flags = MFI_FRAME_DIR_READ;
+ else if (scp->sc_data_direction == PCI_DMA_NONE)
+ flags = MFI_FRAME_DIR_NONE;
+
+ /*
+ * Prepare the DCDB frame
+ */
+ pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO;
+ pthru->cmd_status = 0x0;
+ pthru->scsi_status = 0x0;
+ pthru->target_id = device_id;
+ pthru->lun = scp->device->lun;
+ pthru->cdb_len = scp->cmd_len;
+ pthru->timeout = 0;
+ pthru->flags = flags;
+ pthru->data_xfer_len = scp->request_bufflen;
+
+ memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+ /*
+ * Construct SGL
+ */
+ sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+ sizeof(struct megasas_sge32);
+
+ if (IS_DMA64) {
+ pthru->flags |= MFI_FRAME_SGL64;
+ pthru->sge_count = megasas_make_sgl64(instance, scp,
+ &pthru->sgl);
+ } else
+ pthru->sge_count = megasas_make_sgl32(instance, scp,
+ &pthru->sgl);
+
+ /*
+ * Sense info specific
+ */
+ pthru->sense_len = SCSI_SENSE_BUFFERSIZE;
+ pthru->sense_buf_phys_addr_hi = 0;
+ pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+
+ sge_bytes = sge_sz * pthru->sge_count;
+
+ /*
+ * Compute the total number of frames this command consumes. FW uses
+ * this number to pull sufficient number of frames from host memory.
+ */
+ cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
+ ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1;
+
+ if (cmd->frame_count > 7)
+ cmd->frame_count = 8;
+
+ return cmd->frame_count;
+}
+
+/**
+ * megasas_build_ldio - Prepares IOs to logical devices
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @cmd: Command to to be prepared
+ *
+ * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
+ */
+static inline int
+megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ struct megasas_cmd *cmd)
+{
+ u32 sge_sz;
+ int sge_bytes;
+ u32 device_id;
+ u8 sc = scp->cmnd[0];
+ u16 flags = 0;
+ struct megasas_io_frame *ldio;
+
+ device_id = MEGASAS_DEV_INDEX(instance, scp);
+ ldio = (struct megasas_io_frame *)cmd->frame;
+
+ if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+ flags = MFI_FRAME_DIR_WRITE;
+ else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ flags = MFI_FRAME_DIR_READ;
+
+ /*
+ * Preare the Logical IO frame: 2nd bit is zero for all read cmds
+ */
+ ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
+ ldio->cmd_status = 0x0;
+ ldio->scsi_status = 0x0;
+ ldio->target_id = device_id;
+ ldio->timeout = 0;
+ ldio->reserved_0 = 0;
+ ldio->pad_0 = 0;
+ ldio->flags = flags;
+ ldio->start_lba_hi = 0;
+ ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0;
+
+ /*
+ * 6-byte READ(0x08) or WRITE(0x0A) cdb
+ */
+ if (scp->cmd_len == 6) {
+ ldio->lba_count = (u32) scp->cmnd[4];
+ ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) |
+ ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
+
+ ldio->start_lba_lo &= 0x1FFFFF;
+ }
+
+ /*
+ * 10-byte READ(0x28) or WRITE(0x2A) cdb
+ */
+ else if (scp->cmd_len == 10) {
+ ldio->lba_count = (u32) scp->cmnd[8] |
+ ((u32) scp->cmnd[7] << 8);
+ ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+ }
+
+ /*
+ * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+ */
+ else if (scp->cmd_len == 12) {
+ ldio->lba_count = ((u32) scp->cmnd[6] << 24) |
+ ((u32) scp->cmnd[7] << 16) |
+ ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+ ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+ }
+
+ /*
+ * 16-byte READ(0x88) or WRITE(0x8A) cdb
+ */
+ else if (scp->cmd_len == 16) {
+ ldio->lba_count = ((u32) scp->cmnd[10] << 24) |
+ ((u32) scp->cmnd[11] << 16) |
+ ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
+
+ ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) |
+ ((u32) scp->cmnd[7] << 16) |
+ ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+ ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+
+ }
+
+ /*
+ * Construct SGL
+ */
+ sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+ sizeof(struct megasas_sge32);
+
+ if (IS_DMA64) {
+ ldio->flags |= MFI_FRAME_SGL64;
+ ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
+ } else
+ ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
+
+ /*
+ * Sense info specific
+ */
+ ldio->sense_len = SCSI_SENSE_BUFFERSIZE;
+ ldio->sense_buf_phys_addr_hi = 0;
+ ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+
+ sge_bytes = sge_sz * ldio->sge_count;
+
+ cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
+ ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1;
+
+ if (cmd->frame_count > 7)
+ cmd->frame_count = 8;
+
+ return cmd->frame_count;
+}
+
+/**
+ * megasas_build_cmd - Prepares a command packet
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @frame_count: [OUT] Number of frames used to prepare this command
+ */
+static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance
+ *instance,
+ struct scsi_cmnd *scp,
+ int *frame_count)
+{
+ u32 logical_cmd;
+ struct megasas_cmd *cmd;
+
+ /*
+ * Find out if this is logical or physical drive command.
+ */
+ logical_cmd = MEGASAS_IS_LOGICAL(scp);
+
+ /*
+ * Logical drive command
+ */
+ if (logical_cmd) {
+
+ if (scp->device->id >= MEGASAS_MAX_LD) {
+ scp->result = DID_BAD_TARGET << 16;
+ return NULL;
+ }
+
+ switch (scp->cmnd[0]) {
+
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ case READ_6:
+ case WRITE_6:
+ case READ_16:
+ case WRITE_16:
+ /*
+ * Fail for LUN > 0
+ */
+ if (scp->device->lun) {
+ scp->result = DID_BAD_TARGET << 16;
+ return NULL;
+ }
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ scp->result = DID_IMM_RETRY << 16;
+ return NULL;
+ }
+
+ *frame_count = megasas_build_ldio(instance, scp, cmd);
+
+ if (!(*frame_count)) {
+ megasas_return_cmd(instance, cmd);
+ return NULL;
+ }
+
+ return cmd;
+
+ default:
+ /*
+ * Fail for LUN > 0
+ */
+ if (scp->device->lun) {
+ scp->result = DID_BAD_TARGET << 16;
+ return NULL;
+ }
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ scp->result = DID_IMM_RETRY << 16;
+ return NULL;
+ }
+
+ *frame_count = megasas_build_dcdb(instance, scp, cmd);
+
+ if (!(*frame_count)) {
+ megasas_return_cmd(instance, cmd);
+ return NULL;
+ }
+
+ return cmd;
+ }
+ } else {
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ scp->result = DID_IMM_RETRY << 16;
+ return NULL;
+ }
+
+ *frame_count = megasas_build_dcdb(instance, scp, cmd);
+
+ if (!(*frame_count)) {
+ megasas_return_cmd(instance, cmd);
+ return NULL;
+ }
+
+ return cmd;
+ }
+
+ return NULL;
+}
+
+/**
+ * megasas_queue_command - Queue entry point
+ * @scmd: SCSI command to be queued
+ * @done: Callback entry point
+ */
+static int
+megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
+{
+ u32 frame_count;
+ unsigned long flags;
+ struct megasas_cmd *cmd;
+ struct megasas_instance *instance;
+
+ instance = (struct megasas_instance *)
+ scmd->device->host->hostdata;
+ scmd->scsi_done = done;
+ scmd->result = 0;
+
+ cmd = megasas_build_cmd(instance, scmd, &frame_count);
+
+ if (!cmd) {
+ done(scmd);
+ return 0;
+ }
+
+ cmd->scmd = scmd;
+ scmd->SCp.ptr = (char *)cmd;
+ scmd->SCp.sent_command = jiffies;
+
+ /*
+ * Issue the command to the FW
+ */
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding++;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
+
+ writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)),
+ &instance->reg_set->inbound_queue_port);
+
+ return 0;
+}
+
+/**
+ * megasas_wait_for_outstanding - Wait for all outstanding cmds
+ * @instance: Adapter soft state
+ *
+ * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
+ * complete all its outstanding commands. Returns error if one or more IOs
+ * are pending after this time period. It also marks the controller dead.
+ */
+static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+{
+ int i;
+ u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+
+ for (i = 0; i < wait_time; i++) {
+
+ if (!instance->fw_outstanding)
+ break;
+
+ if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+ printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
+ "commands to complete\n", i,
+ instance->fw_outstanding);
+ }
+
+ msleep(1000);
+ }
+
+ if (instance->fw_outstanding) {
+ instance->hw_crit_error = 1;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * megasas_generic_reset - Generic reset routine
+ * @scmd: Mid-layer SCSI command
+ *
+ * This routine implements a generic reset handler for device, bus and host
+ * reset requests. Device, bus and host specific reset handlers can use this
+ * function after they do their specific tasks.
+ */
+static int megasas_generic_reset(struct scsi_cmnd *scmd)
+{
+ int ret_val;
+ struct megasas_instance *instance;
+
+ instance = (struct megasas_instance *)scmd->device->host->hostdata;
+
+ printk(KERN_NOTICE "megasas: RESET -%ld cmd=%x <c=%d t=%d l=%d>\n",
+ scmd->serial_number, scmd->cmnd[0], scmd->device->channel,
+ scmd->device->id, scmd->device->lun);
+
+ if (instance->hw_crit_error) {
+ printk(KERN_ERR "megasas: cannot recover from previous reset "
+ "failures\n");
+ return FAILED;
+ }
+
+ spin_unlock(scmd->device->host->host_lock);
+
+ ret_val = megasas_wait_for_outstanding(instance);
+
+ if (ret_val == SUCCESS)
+ printk(KERN_NOTICE "megasas: reset successful \n");
+ else
+ printk(KERN_ERR "megasas: failed to do reset\n");
+
+ spin_lock(scmd->device->host->host_lock);
+
+ return ret_val;
+}
+
+static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+{
+ unsigned long seconds;
+
+ if (scmd->SCp.ptr) {
+ seconds = (jiffies - scmd->SCp.sent_command) / HZ;
+
+ if (seconds < 90) {
+ return EH_RESET_TIMER;
+ } else {
+ return EH_NOT_HANDLED;
+ }
+ }
+
+ return EH_HANDLED;
+}
+
+/**
+ * megasas_reset_device - Device reset handler entry point
+ */
+static int megasas_reset_device(struct scsi_cmnd *scmd)
+{
+ int ret;
+
+ /*
+ * First wait for all commands to complete
+ */
+ ret = megasas_generic_reset(scmd);
+
+ return ret;
+}
+
+/**
+ * megasas_reset_bus_host - Bus & host reset handler entry point
+ */
+static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
+{
+ int ret;
+
+ /*
+ * Frist wait for all commands to complete
+ */
+ ret = megasas_generic_reset(scmd);
+
+ return ret;
+}
+
+/**
+ * megasas_service_aen - Processes an event notification
+ * @instance: Adapter soft state
+ * @cmd: AEN command completed by the ISR
+ *
+ * For AEN, driver sends a command down to FW that is held by the FW till an
+ * event occurs. When an event of interest occurs, FW completes the command
+ * that it was previously holding.
+ *
+ * This routines sends SIGIO signal to processes that have registered with the
+ * driver for AEN.
+ */
+static void
+megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ /*
+ * Don't signal app if it is just an aborted previously registered aen
+ */
+ if (!cmd->abort_aen)
+ kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
+ else
+ cmd->abort_aen = 0;
+
+ instance->aen_cmd = NULL;
+ megasas_return_cmd(instance, cmd);
+}
+
+/*
+ * Scsi host template for megaraid_sas driver
+ */
+static struct scsi_host_template megasas_template = {
+
+ .module = THIS_MODULE,
+ .name = "LSI Logic SAS based MegaRAID driver",
+ .proc_name = "megaraid_sas",
+ .queuecommand = megasas_queue_command,
+ .eh_device_reset_handler = megasas_reset_device,
+ .eh_bus_reset_handler = megasas_reset_bus_host,
+ .eh_host_reset_handler = megasas_reset_bus_host,
+ .eh_timed_out = megasas_reset_timer,
+ .use_clustering = ENABLE_CLUSTERING,
+};
+
+/**
+ * megasas_complete_int_cmd - Completes an internal command
+ * @instance: Adapter soft state
+ * @cmd: Command to be completed
+ *
+ * The megasas_issue_blocked_cmd() function waits for a command to complete
+ * after it issues a command. This function wakes up that waiting routine by
+ * calling wake_up() on the wait queue.
+ */
+static void
+megasas_complete_int_cmd(struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ cmd->cmd_status = cmd->frame->io.cmd_status;
+
+ if (cmd->cmd_status == ENODATA) {
+ cmd->cmd_status = 0;
+ }
+ wake_up(&instance->int_cmd_wait_q);
+}
+
+/**
+ * megasas_complete_abort - Completes aborting a command
+ * @instance: Adapter soft state
+ * @cmd: Cmd that was issued to abort another cmd
+ *
+ * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q
+ * after it issues an abort on a previously issued command. This function
+ * wakes up all functions waiting on the same wait queue.
+ */
+static void
+megasas_complete_abort(struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ if (cmd->sync_cmd) {
+ cmd->sync_cmd = 0;
+ cmd->cmd_status = 0;
+ wake_up(&instance->abort_cmd_wait_q);
+ }
+
+ return;
+}
+
+/**
+ * megasas_unmap_sgbuf - Unmap SG buffers
+ * @instance: Adapter soft state
+ * @cmd: Completed command
+ */
+static inline void
+megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ dma_addr_t buf_h;
+ u8 opcode;
+
+ if (cmd->scmd->use_sg) {
+ pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer,
+ cmd->scmd->use_sg, cmd->scmd->sc_data_direction);
+ return;
+ }
+
+ if (!cmd->scmd->request_bufflen)
+ return;
+
+ opcode = cmd->frame->hdr.cmd;
+
+ if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
+ if (IS_DMA64)
+ buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
+ else
+ buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
+ } else {
+ if (IS_DMA64)
+ buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
+ else
+ buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
+ }
+
+ pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen,
+ cmd->scmd->sc_data_direction);
+ return;
+}
+
+/**
+ * megasas_complete_cmd - Completes a command
+ * @instance: Adapter soft state
+ * @cmd: Command to be completed
+ * @alt_status: If non-zero, use this value as status to
+ * SCSI mid-layer instead of the value returned
+ * by the FW. This should be used if caller wants
+ * an alternate status (as in the case of aborted
+ * commands)
+ */
+static inline void
+megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+ u8 alt_status)
+{
+ int exception = 0;
+ struct megasas_header *hdr = &cmd->frame->hdr;
+ unsigned long flags;
+
+ if (cmd->scmd) {
+ cmd->scmd->SCp.ptr = (char *)0;
+ }
+
+ switch (hdr->cmd) {
+
+ case MFI_CMD_PD_SCSI_IO:
+ case MFI_CMD_LD_SCSI_IO:
+
+ /*
+ * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
+ * issued either through an IO path or an IOCTL path. If it
+ * was via IOCTL, we will send it to internal completion.
+ */
+ if (cmd->sync_cmd) {
+ cmd->sync_cmd = 0;
+ megasas_complete_int_cmd(instance, cmd);
+ break;
+ }
+
+ /*
+ * Don't export physical disk devices to mid-layer.
+ */
+ if (!MEGASAS_IS_LOGICAL(cmd->scmd) &&
+ (hdr->cmd_status == MFI_STAT_OK) &&
+ (cmd->scmd->cmnd[0] == INQUIRY)) {
+
+ if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) ==
+ TYPE_DISK) {
+ cmd->scmd->result = DID_BAD_TARGET << 16;
+ exception = 1;
+ }
+ }
+
+ case MFI_CMD_LD_READ:
+ case MFI_CMD_LD_WRITE:
+
+ if (alt_status) {
+ cmd->scmd->result = alt_status << 16;
+ exception = 1;
+ }
+
+ if (exception) {
+
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding--;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
+
+ megasas_unmap_sgbuf(instance, cmd);
+ cmd->scmd->scsi_done(cmd->scmd);
+ megasas_return_cmd(instance, cmd);
+
+ break;
+ }
+
+ switch (hdr->cmd_status) {
+
+ case MFI_STAT_OK:
+ cmd->scmd->result = DID_OK << 16;
+ break;
+
+ case MFI_STAT_SCSI_IO_FAILED:
+ case MFI_STAT_LD_INIT_IN_PROGRESS:
+ cmd->scmd->result =
+ (DID_ERROR << 16) | hdr->scsi_status;
+ break;
+
+ case MFI_STAT_SCSI_DONE_WITH_ERROR:
+
+ cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status;
+
+ if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) {
+ memset(cmd->scmd->sense_buffer, 0,
+ SCSI_SENSE_BUFFERSIZE);
+ memcpy(cmd->scmd->sense_buffer, cmd->sense,
+ hdr->sense_len);
+
+ cmd->scmd->result |= DRIVER_SENSE << 24;
+ }
+
+ break;
+
+ case MFI_STAT_LD_OFFLINE:
+ case MFI_STAT_DEVICE_NOT_FOUND:
+ cmd->scmd->result = DID_BAD_TARGET << 16;
+ break;
+
+ default:
+ printk(KERN_DEBUG "megasas: MFI FW status %#x\n",
+ hdr->cmd_status);
+ cmd->scmd->result = DID_ERROR << 16;
+ break;
+ }
+
+ spin_lock_irqsave(&instance->instance_lock, flags);
+ instance->fw_outstanding--;
+ spin_unlock_irqrestore(&instance->instance_lock, flags);
+
+ megasas_unmap_sgbuf(instance, cmd);
+ cmd->scmd->scsi_done(cmd->scmd);
+ megasas_return_cmd(instance, cmd);
+
+ break;
+
+ case MFI_CMD_SMP:
+ case MFI_CMD_STP:
+ case MFI_CMD_DCMD:
+
+ /*
+ * See if got an event notification
+ */
+ if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
+ megasas_service_aen(instance, cmd);
+ else
+ megasas_complete_int_cmd(instance, cmd);
+
+ break;
+
+ case MFI_CMD_ABORT:
+ /*
+ * Cmd issued to abort another cmd returned
+ */
+ megasas_complete_abort(instance, cmd);
+ break;
+
+ default:
+ printk("megasas: Unknown command completed! [0x%X]\n",
+ hdr->cmd);
+ break;
+ }
+}
+
+/**
+ * megasas_deplete_reply_queue - Processes all completed commands
+ * @instance: Adapter soft state
+ * @alt_status: Alternate status to be returned to
+ * SCSI mid-layer instead of the status
+ * returned by the FW
+ */
+static inline int
+megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
+{
+ u32 status;
+ u32 producer;
+ u32 consumer;
+ u32 context;
+ struct megasas_cmd *cmd;
+
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&instance->reg_set->outbound_intr_status);
+
+ if (!(status & MFI_OB_INTR_STATUS_MASK)) {
+ return IRQ_NONE;
+ }
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, &instance->reg_set->outbound_intr_status);
+
+ producer = *instance->producer;
+ consumer = *instance->consumer;
+
+ while (consumer != producer) {
+ context = instance->reply_queue[consumer];
+
+ cmd = instance->cmd_list[context];
+
+ megasas_complete_cmd(instance, cmd, alt_status);
+
+ consumer++;
+ if (consumer == (instance->max_fw_cmds + 1)) {
+ consumer = 0;
+ }
+ }
+
+ *instance->consumer = producer;
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * megasas_isr - isr entry point
+ */
+static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs)
+{
+ return megasas_deplete_reply_queue((struct megasas_instance *)devp,
+ DID_OK);
+}
+
+/**
+ * megasas_transition_to_ready - Move the FW to READY state
+ * @reg_set: MFI register set
+ *
+ * During the initialization, FW passes can potentially be in any one of
+ * several possible states. If the FW in operational, waiting-for-handshake
+ * states, driver must take steps to bring it to ready state. Otherwise, it
+ * has to wait for the ready state.
+ */
+static int
+megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set)
+{
+ int i;
+ u8 max_wait;
+ u32 fw_state;
+ u32 cur_state;
+
+ fw_state = readl(&reg_set->outbound_msg_0) & MFI_STATE_MASK;
+
+ while (fw_state != MFI_STATE_READY) {
+
+ printk(KERN_INFO "megasas: Waiting for FW to come to ready"
+ " state\n");
+ switch (fw_state) {
+
+ case MFI_STATE_FAULT:
+
+ printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
+ return -ENODEV;
+
+ case MFI_STATE_WAIT_HANDSHAKE:
+ /*
+ * Set the CLR bit in inbound doorbell
+ */
+ writel(MFI_INIT_CLEAR_HANDSHAKE,
+ &reg_set->inbound_doorbell);
+
+ max_wait = 2;
+ cur_state = MFI_STATE_WAIT_HANDSHAKE;
+ break;
+
+ case MFI_STATE_OPERATIONAL:
+ /*
+ * Bring it to READY state; assuming max wait 2 secs
+ */
+ megasas_disable_intr(reg_set);
+ writel(MFI_INIT_READY, &reg_set->inbound_doorbell);
+
+ max_wait = 10;
+ cur_state = MFI_STATE_OPERATIONAL;
+ break;
+
+ case MFI_STATE_UNDEFINED:
+ /*
+ * This state should not last for more than 2 seconds
+ */
+ max_wait = 2;
+ cur_state = MFI_STATE_UNDEFINED;
+ break;
+
+ case MFI_STATE_BB_INIT:
+ max_wait = 2;
+ cur_state = MFI_STATE_BB_INIT;
+ break;
+
+ case MFI_STATE_FW_INIT:
+ max_wait = 20;
+ cur_state = MFI_STATE_FW_INIT;
+ break;
+
+ case MFI_STATE_FW_INIT_2:
+ max_wait = 20;
+ cur_state = MFI_STATE_FW_INIT_2;
+ break;
+
+ case MFI_STATE_DEVICE_SCAN:
+ max_wait = 20;
+ cur_state = MFI_STATE_DEVICE_SCAN;
+ break;
+
+ case MFI_STATE_FLUSH_CACHE:
+ max_wait = 20;
+ cur_state = MFI_STATE_FLUSH_CACHE;
+ break;
+
+ default:
+ printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",
+ fw_state);
+ return -ENODEV;
+ }
+
+ /*
+ * The cur_state should not last for more than max_wait secs
+ */
+ for (i = 0; i < (max_wait * 1000); i++) {
+ fw_state = MFI_STATE_MASK &
+ readl(&reg_set->outbound_msg_0);
+
+ if (fw_state == cur_state) {
+ msleep(1);
+ } else
+ break;
+ }
+
+ /*
+ * Return error if fw_state hasn't changed after max_wait
+ */
+ if (fw_state == cur_state) {
+ printk(KERN_DEBUG "FW state [%d] hasn't changed "
+ "in %d secs\n", fw_state, max_wait);
+ return -ENODEV;
+ }
+ };
+
+ return 0;
+}
+
+/**
+ * megasas_teardown_frame_pool - Destroy the cmd frame DMA pool
+ * @instance: Adapter soft state
+ */
+static void megasas_teardown_frame_pool(struct megasas_instance *instance)
+{
+ int i;
+ u32 max_cmd = instance->max_fw_cmds;
+ struct megasas_cmd *cmd;
+
+ if (!instance->frame_dma_pool)
+ return;
+
+ /*
+ * Return all frames to pool
+ */
+ for (i = 0; i < max_cmd; i++) {
+
+ cmd = instance->cmd_list[i];
+
+ if (cmd->frame)
+ pci_pool_free(instance->frame_dma_pool, cmd->frame,
+ cmd->frame_phys_addr);
+
+ if (cmd->sense)
+ pci_pool_free(instance->sense_dma_pool, cmd->frame,
+ cmd->sense_phys_addr);
+ }
+
+ /*
+ * Now destroy the pool itself
+ */
+ pci_pool_destroy(instance->frame_dma_pool);
+ pci_pool_destroy(instance->sense_dma_pool);
+
+ instance->frame_dma_pool = NULL;
+ instance->sense_dma_pool = NULL;
+}
+
+/**
+ * megasas_create_frame_pool - Creates DMA pool for cmd frames
+ * @instance: Adapter soft state
+ *
+ * Each command packet has an embedded DMA memory buffer that is used for
+ * filling MFI frame and the SG list that immediately follows the frame. This
+ * function creates those DMA memory buffers for each command packet by using
+ * PCI pool facility.
+ */
+static int megasas_create_frame_pool(struct megasas_instance *instance)
+{
+ int i;
+ u32 max_cmd;
+ u32 sge_sz;
+ u32 sgl_sz;
+ u32 total_sz;
+ u32 frame_count;
+ struct megasas_cmd *cmd;
+
+ max_cmd = instance->max_fw_cmds;
+
+ /*
+ * Size of our frame is 64 bytes for MFI frame, followed by max SG
+ * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer
+ */
+ sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+ sizeof(struct megasas_sge32);
+
+ /*
+ * Calculated the number of 64byte frames required for SGL
+ */
+ sgl_sz = sge_sz * instance->max_num_sge;
+ frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+
+ /*
+ * We need one extra frame for the MFI command
+ */
+ frame_count++;
+
+ total_sz = MEGAMFI_FRAME_SIZE * frame_count;
+ /*
+ * Use DMA pool facility provided by PCI layer
+ */
+ instance->frame_dma_pool = pci_pool_create("megasas frame pool",
+ instance->pdev, total_sz, 64,
+ 0);
+
+ if (!instance->frame_dma_pool) {
+ printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
+ return -ENOMEM;
+ }
+
+ instance->sense_dma_pool = pci_pool_create("megasas sense pool",
+ instance->pdev, 128, 4, 0);
+
+ if (!instance->sense_dma_pool) {
+ printk(KERN_DEBUG "megasas: failed to setup sense pool\n");
+
+ pci_pool_destroy(instance->frame_dma_pool);
+ instance->frame_dma_pool = NULL;
+
+ return -ENOMEM;
+ }
+
+ /*
+ * Allocate and attach a frame to each of the commands in cmd_list.
+ * By making cmd->index as the context instead of the &cmd, we can
+ * always use 32bit context regardless of the architecture
+ */
+ for (i = 0; i < max_cmd; i++) {
+
+ cmd = instance->cmd_list[i];
+
+ cmd->frame = pci_pool_alloc(instance->frame_dma_pool,
+ GFP_KERNEL, &cmd->frame_phys_addr);
+
+ cmd->sense = pci_pool_alloc(instance->sense_dma_pool,
+ GFP_KERNEL, &cmd->sense_phys_addr);
+
+ /*
+ * megasas_teardown_frame_pool() takes care of freeing
+ * whatever has been allocated
+ */
+ if (!cmd->frame || !cmd->sense) {
+ printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");
+ megasas_teardown_frame_pool(instance);
+ return -ENOMEM;
+ }
+
+ cmd->frame->io.context = cmd->index;
+ }
+
+ return 0;
+}
+
+/**
+ * megasas_free_cmds - Free all the cmds in the free cmd pool
+ * @instance: Adapter soft state
+ */
+static void megasas_free_cmds(struct megasas_instance *instance)
+{
+ int i;
+ /* First free the MFI frame pool */
+ megasas_teardown_frame_pool(instance);
+
+ /* Free all the commands in the cmd_list */
+ for (i = 0; i < instance->max_fw_cmds; i++)
+ kfree(instance->cmd_list[i]);
+
+ /* Free the cmd_list buffer itself */
+ kfree(instance->cmd_list);
+ instance->cmd_list = NULL;
+
+ INIT_LIST_HEAD(&instance->cmd_pool);
+}
+
+/**
+ * megasas_alloc_cmds - Allocates the command packets
+ * @instance: Adapter soft state
+ *
+ * Each command that is issued to the FW, whether IO commands from the OS or
+ * internal commands like IOCTLs, are wrapped in local data structure called
+ * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to
+ * the FW.
+ *
+ * Each frame has a 32-bit field called context (tag). This context is used
+ * to get back the megasas_cmd from the frame when a frame gets completed in
+ * the ISR. Typically the address of the megasas_cmd itself would be used as
+ * the context. But we wanted to keep the differences between 32 and 64 bit
+ * systems to the mininum. We always use 32 bit integers for the context. In
+ * this driver, the 32 bit values are the indices into an array cmd_list.
+ * This array is used only to look up the megasas_cmd given the context. The
+ * free commands themselves are maintained in a linked list called cmd_pool.
+ */
+static int megasas_alloc_cmds(struct megasas_instance *instance)
+{
+ int i;
+ int j;
+ u32 max_cmd;
+ struct megasas_cmd *cmd;
+
+ max_cmd = instance->max_fw_cmds;
+
+ /*
+ * instance->cmd_list is an array of struct megasas_cmd pointers.
+ * Allocate the dynamic array first and then allocate individual
+ * commands.
+ */
+ instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd,
+ GFP_KERNEL);
+
+ if (!instance->cmd_list) {
+ printk(KERN_DEBUG "megasas: out of memory\n");
+ return -ENOMEM;
+ }
+
+ memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) * max_cmd);
+
+ for (i = 0; i < max_cmd; i++) {
+ instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
+ GFP_KERNEL);
+
+ if (!instance->cmd_list[i]) {
+
+ for (j = 0; j < i; j++)
+ kfree(instance->cmd_list[j]);
+
+ kfree(instance->cmd_list);
+ instance->cmd_list = NULL;
+
+ return -ENOMEM;
+ }
+ }
+
+ /*
+ * Add all the commands to command pool (instance->cmd_pool)
+ */
+ for (i = 0; i < max_cmd; i++) {
+ cmd = instance->cmd_list[i];
+ memset(cmd, 0, sizeof(struct megasas_cmd));
+ cmd->index = i;
+ cmd->instance = instance;
+
+ list_add_tail(&cmd->list, &instance->cmd_pool);
+ }
+
+ /*
+ * Create a frame pool and assign one frame to each cmd
+ */
+ if (megasas_create_frame_pool(instance)) {
+ printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
+ megasas_free_cmds(instance);
+ }
+
+ return 0;
+}
+
+/**
+ * megasas_get_controller_info - Returns FW's controller structure
+ * @instance: Adapter soft state
+ * @ctrl_info: Controller information structure
+ *
+ * Issues an internal command (DCMD) to get the FW's controller structure.
+ * This information is mainly used to find out the maximum IO transfer per
+ * command supported by the FW.
+ */
+static int
+megasas_get_ctrl_info(struct megasas_instance *instance,
+ struct megasas_ctrl_info *ctrl_info)
+{
+ int ret = 0;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ struct megasas_ctrl_info *ci;
+ dma_addr_t ci_h = 0;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
+ return -ENOMEM;
+ }
+
+ dcmd = &cmd->frame->dcmd;
+
+ ci = pci_alloc_consistent(instance->pdev,
+ sizeof(struct megasas_ctrl_info), &ci_h);
+
+ if (!ci) {
+ printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");
+ megasas_return_cmd(instance, cmd);
+ return -ENOMEM;
+ }
+
+ memset(ci, 0, sizeof(*ci));
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
+ dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = ci_h;
+ dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);
+
+ if (!megasas_issue_polled(instance, cmd)) {
+ ret = 0;
+ memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+ } else {
+ ret = -1;
+ }
+
+ pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
+ ci, ci_h);
+
+ megasas_return_cmd(instance, cmd);
+ return ret;
+}
+
+/**
+ * megasas_init_mfi - Initializes the FW
+ * @instance: Adapter soft state
+ *
+ * This is the main function for initializing MFI firmware.
+ */
+static int megasas_init_mfi(struct megasas_instance *instance)
+{
+ u32 context_sz;
+ u32 reply_q_sz;
+ u32 max_sectors_1;
+ u32 max_sectors_2;
+ struct megasas_register_set __iomem *reg_set;
+
+ struct megasas_cmd *cmd;
+ struct megasas_ctrl_info *ctrl_info;
+
+ struct megasas_init_frame *init_frame;
+ struct megasas_init_queue_info *initq_info;
+ dma_addr_t init_frame_h;
+ dma_addr_t initq_info_h;
+
+ /*
+ * Map the message registers
+ */
+ instance->base_addr = pci_resource_start(instance->pdev, 0);
+
+ if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) {
+ printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+ return -EBUSY;
+ }
+
+ instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+
+ if (!instance->reg_set) {
+ printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+ goto fail_ioremap;
+ }
+
+ reg_set = instance->reg_set;
+
+ /*
+ * We expect the FW state to be READY
+ */
+ if (megasas_transition_to_ready(instance->reg_set))
+ goto fail_ready_state;
+
+ /*
+ * Get various operational parameters from status register
+ */
+ instance->max_fw_cmds = readl(&reg_set->outbound_msg_0) & 0x00FFFF;
+ instance->max_num_sge = (readl(&reg_set->outbound_msg_0) & 0xFF0000) >>
+ 0x10;
+ /*
+ * Create a pool of commands
+ */
+ if (megasas_alloc_cmds(instance))
+ goto fail_alloc_cmds;
+
+ /*
+ * Allocate memory for reply queue. Length of reply queue should
+ * be _one_ more than the maximum commands handled by the firmware.
+ *
+ * Note: When FW completes commands, it places corresponding contex
+ * values in this circular reply queue. This circular queue is a fairly
+ * typical producer-consumer queue. FW is the producer (of completed
+ * commands) and the driver is the consumer.
+ */
+ context_sz = sizeof(u32);
+ reply_q_sz = context_sz * (instance->max_fw_cmds + 1);
+
+ instance->reply_queue = pci_alloc_consistent(instance->pdev,
+ reply_q_sz,
+ &instance->reply_queue_h);
+
+ if (!instance->reply_queue) {
+ printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
+ goto fail_reply_queue;
+ }
+
+ /*
+ * Prepare a init frame. Note the init frame points to queue info
+ * structure. Each frame has SGL allocated after first 64 bytes. For
+ * this frame - since we don't need any SGL - we use SGL's space as
+ * queue info structure
+ *
+ * We will not get a NULL command below. We just created the pool.
+ */
+ cmd = megasas_get_cmd(instance);
+
+ init_frame = (struct megasas_init_frame *)cmd->frame;
+ initq_info = (struct megasas_init_queue_info *)
+ ((unsigned long)init_frame + 64);
+
+ init_frame_h = cmd->frame_phys_addr;
+ initq_info_h = init_frame_h + 64;
+
+ memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
+ memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
+
+ initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
+ initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
+
+ initq_info->producer_index_phys_addr_lo = instance->producer_h;
+ initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
+
+ init_frame->cmd = MFI_CMD_INIT;
+ init_frame->cmd_status = 0xFF;
+ init_frame->queue_info_new_phys_addr_lo = initq_info_h;
+
+ init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
+
+ /*
+ * Issue the init frame in polled mode
+ */
+ if (megasas_issue_polled(instance, cmd)) {
+ printk(KERN_DEBUG "megasas: Failed to init firmware\n");
+ goto fail_fw_init;
+ }
+
+ megasas_return_cmd(instance, cmd);
+
+ ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
+
+ /*
+ * Compute the max allowed sectors per IO: The controller info has two
+ * limits on max sectors. Driver should use the minimum of these two.
+ *
+ * 1 << stripe_sz_ops.min = max sectors per strip
+ *
+ * Note that older firmwares ( < FW ver 30) didn't report information
+ * to calculate max_sectors_1. So the number ended up as zero always.
+ */
+ if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
+
+ max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
+ ctrl_info->max_strips_per_io;
+ max_sectors_2 = ctrl_info->max_request_size;
+
+ instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2)
+ ? max_sectors_1 : max_sectors_2;
+ } else
+ instance->max_sectors_per_req = instance->max_num_sge *
+ PAGE_SIZE / 512;
+
+ kfree(ctrl_info);
+
+ return 0;
+
+ fail_fw_init:
+ megasas_return_cmd(instance, cmd);
+
+ pci_free_consistent(instance->pdev, reply_q_sz,
+ instance->reply_queue, instance->reply_queue_h);
+ fail_reply_queue:
+ megasas_free_cmds(instance);
+
+ fail_alloc_cmds:
+ fail_ready_state:
+ iounmap(instance->reg_set);
+
+ fail_ioremap:
+ pci_release_regions(instance->pdev);
+
+ return -EINVAL;
+}
+
+/**
+ * megasas_release_mfi - Reverses the FW initialization
+ * @intance: Adapter soft state
+ */
+static void megasas_release_mfi(struct megasas_instance *instance)
+{
+ u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
+
+ pci_free_consistent(instance->pdev, reply_q_sz,
+ instance->reply_queue, instance->reply_queue_h);
+
+ megasas_free_cmds(instance);
+
+ iounmap(instance->reg_set);
+
+ pci_release_regions(instance->pdev);
+}
+
+/**
+ * megasas_get_seq_num - Gets latest event sequence numbers
+ * @instance: Adapter soft state
+ * @eli: FW event log sequence numbers information
+ *
+ * FW maintains a log of all events in a non-volatile area. Upper layers would
+ * usually find out the latest sequence number of the events, the seq number at
+ * the boot etc. They would "read" all the events below the latest seq number
+ * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq
+ * number), they would subsribe to AEN (asynchronous event notification) and
+ * wait for the events to happen.
+ */
+static int
+megasas_get_seq_num(struct megasas_instance *instance,
+ struct megasas_evt_log_info *eli)
+{
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ struct megasas_evt_log_info *el_info;
+ dma_addr_t el_info_h = 0;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ return -ENOMEM;
+ }
+
+ dcmd = &cmd->frame->dcmd;
+ el_info = pci_alloc_consistent(instance->pdev,
+ sizeof(struct megasas_evt_log_info),
+ &el_info_h);
+
+ if (!el_info) {
+ megasas_return_cmd(instance, cmd);
+ return -ENOMEM;
+ }
+
+ memset(el_info, 0, sizeof(*el_info));
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
+ dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = el_info_h;
+ dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info);
+
+ megasas_issue_blocked_cmd(instance, cmd);
+
+ /*
+ * Copy the data back into callers buffer
+ */
+ memcpy(eli, el_info, sizeof(struct megasas_evt_log_info));
+
+ pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
+ el_info, el_info_h);
+
+ megasas_return_cmd(instance, cmd);
+
+ return 0;
+}
+
+/**
+ * megasas_register_aen - Registers for asynchronous event notification
+ * @instance: Adapter soft state
+ * @seq_num: The starting sequence number
+ * @class_locale: Class of the event
+ *
+ * This function subscribes for AEN for events beyond the @seq_num. It requests
+ * to be notified if and only if the event is of type @class_locale
+ */
+static int
+megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+ u32 class_locale_word)
+{
+ int ret_val;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ union megasas_evt_class_locale curr_aen;
+ union megasas_evt_class_locale prev_aen;
+
+ /*
+ * If there an AEN pending already (aen_cmd), check if the
+ * class_locale of that pending AEN is inclusive of the new
+ * AEN request we currently have. If it is, then we don't have
+ * to do anything. In other words, whichever events the current
+ * AEN request is subscribing to, have already been subscribed
+ * to.
+ *
+ * If the old_cmd is _not_ inclusive, then we have to abort
+ * that command, form a class_locale that is superset of both
+ * old and current and re-issue to the FW
+ */
+
+ curr_aen.word = class_locale_word;
+
+ if (instance->aen_cmd) {
+
+ prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
+
+ /*
+ * A class whose enum value is smaller is inclusive of all
+ * higher values. If a PROGRESS (= -1) was previously
+ * registered, then a new registration requests for higher
+ * classes need not be sent to FW. They are automatically
+ * included.
+ *
+ * Locale numbers don't have such hierarchy. They are bitmap
+ * values
+ */
+ if ((prev_aen.members.class <= curr_aen.members.class) &&
+ !((prev_aen.members.locale & curr_aen.members.locale) ^
+ curr_aen.members.locale)) {
+ /*
+ * Previously issued event registration includes
+ * current request. Nothing to do.
+ */
+ return 0;
+ } else {
+ curr_aen.members.locale |= prev_aen.members.locale;
+
+ if (prev_aen.members.class < curr_aen.members.class)
+ curr_aen.members.class = prev_aen.members.class;
+
+ instance->aen_cmd->abort_aen = 1;
+ ret_val = megasas_issue_blocked_abort_cmd(instance,
+ instance->
+ aen_cmd);
+
+ if (ret_val) {
+ printk(KERN_DEBUG "megasas: Failed to abort "
+ "previous AEN command\n");
+ return ret_val;
+ }
+ }
+ }
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd)
+ return -ENOMEM;
+
+ dcmd = &cmd->frame->dcmd;
+
+ memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail));
+
+ /*
+ * Prepare DCMD for aen registration
+ */
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
+ dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
+ dcmd->mbox.w[0] = seq_num;
+ dcmd->mbox.w[1] = curr_aen.word;
+ dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
+ dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
+
+ /*
+ * Store reference to the cmd used to register for AEN. When an
+ * application wants us to register for AEN, we have to abort this
+ * cmd and re-register with a new EVENT LOCALE supplied by that app
+ */
+ instance->aen_cmd = cmd;
+
+ /*
+ * Issue the aen registration frame
+ */
+ writel(cmd->frame_phys_addr >> 3,
+ &instance->reg_set->inbound_queue_port);
+
+ return 0;
+}
+
+/**
+ * megasas_start_aen - Subscribes to AEN during driver load time
+ * @instance: Adapter soft state
+ */
+static int megasas_start_aen(struct megasas_instance *instance)
+{
+ struct megasas_evt_log_info eli;
+ union megasas_evt_class_locale class_locale;
+
+ /*
+ * Get the latest sequence number from FW
+ */
+ memset(&eli, 0, sizeof(eli));
+
+ if (megasas_get_seq_num(instance, &eli))
+ return -1;
+
+ /*
+ * Register AEN with FW for latest sequence number plus 1
+ */
+ class_locale.members.reserved = 0;
+ class_locale.members.locale = MR_EVT_LOCALE_ALL;
+ class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+ return megasas_register_aen(instance, eli.newest_seq_num + 1,
+ class_locale.word);
+}
+
+/**
+ * megasas_io_attach - Attaches this driver to SCSI mid-layer
+ * @instance: Adapter soft state
+ */
+static int megasas_io_attach(struct megasas_instance *instance)
+{
+ struct Scsi_Host *host = instance->host;
+
+ /*
+ * Export parameters required by SCSI mid-layer
+ */
+ host->irq = instance->pdev->irq;
+ host->unique_id = instance->unique_id;
+ host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
+ host->this_id = instance->init_id;
+ host->sg_tablesize = instance->max_num_sge;
+ host->max_sectors = instance->max_sectors_per_req;
+ host->cmd_per_lun = 128;
+ host->max_channel = MEGASAS_MAX_CHANNELS - 1;
+ host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
+ host->max_lun = MEGASAS_MAX_LUN;
+
+ /*
+ * Notify the mid-layer about the new controller
+ */
+ if (scsi_add_host(host, &instance->pdev->dev)) {
+ printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Trigger SCSI to scan our drives
+ */
+ scsi_scan_host(host);
+ return 0;
+}
+
+/**
+ * megasas_probe_one - PCI hotplug entry point
+ * @pdev: PCI device structure
+ * @id: PCI ids of supported hotplugged adapter
+ */
+static int __devinit
+megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int rval;
+ struct Scsi_Host *host;
+ struct megasas_instance *instance;
+
+ /*
+ * Announce PCI information
+ */
+ printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+
+ printk("bus %d:slot %d:func %d\n",
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+ /*
+ * PCI prepping: enable device set bus mastering and dma mask
+ */
+ rval = pci_enable_device(pdev);
+
+ if (rval) {
+ return rval;
+ }
+
+ pci_set_master(pdev);
+
+ /*
+ * All our contollers are capable of performing 64-bit DMA
+ */
+ if (IS_DMA64) {
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
+
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
+ goto fail_set_dma_mask;
+ }
+ } else {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
+ goto fail_set_dma_mask;
+ }
+
+ host = scsi_host_alloc(&megasas_template,
+ sizeof(struct megasas_instance));
+
+ if (!host) {
+ printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n");
+ goto fail_alloc_instance;
+ }
+
+ instance = (struct megasas_instance *)host->hostdata;
+ memset(instance, 0, sizeof(*instance));
+
+ instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
+ &instance->producer_h);
+ instance->consumer = pci_alloc_consistent(pdev, sizeof(u32),
+ &instance->consumer_h);
+
+ if (!instance->producer || !instance->consumer) {
+ printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+ "producer, consumer\n");
+ goto fail_alloc_dma_buf;
+ }
+
+ *instance->producer = 0;
+ *instance->consumer = 0;
+
+ instance->evt_detail = pci_alloc_consistent(pdev,
+ sizeof(struct
+ megasas_evt_detail),
+ &instance->evt_detail_h);
+
+ if (!instance->evt_detail) {
+ printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+ "event detail structure\n");
+ goto fail_alloc_dma_buf;
+ }
+
+ /*
+ * Initialize locks and queues
+ */
+ INIT_LIST_HEAD(&instance->cmd_pool);
+
+ init_waitqueue_head(&instance->int_cmd_wait_q);
+ init_waitqueue_head(&instance->abort_cmd_wait_q);
+
+ spin_lock_init(&instance->cmd_pool_lock);
+ spin_lock_init(&instance->instance_lock);
+
+ sema_init(&instance->aen_mutex, 1);
+ sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
+
+ /*
+ * Initialize PCI related and misc parameters
+ */
+ instance->pdev = pdev;
+ instance->host = host;
+ instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
+ instance->init_id = MEGASAS_DEFAULT_INIT_ID;
+
+ /*
+ * Initialize MFI Firmware
+ */
+ if (megasas_init_mfi(instance))
+ goto fail_init_mfi;
+
+ /*
+ * Register IRQ
+ */
+ if (request_irq(pdev->irq, megasas_isr, SA_SHIRQ, "megasas", instance)) {
+ printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ goto fail_irq;
+ }
+
+ megasas_enable_intr(instance->reg_set);
+
+ /*
+ * Store instance in PCI softstate
+ */
+ pci_set_drvdata(pdev, instance);
+
+ /*
+ * Add this controller to megasas_mgmt_info structure so that it
+ * can be exported to management applications
+ */
+ megasas_mgmt_info.count++;
+ megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance;
+ megasas_mgmt_info.max_index++;
+
+ /*
+ * Initiate AEN (Asynchronous Event Notification)
+ */
+ if (megasas_start_aen(instance)) {
+ printk(KERN_DEBUG "megasas: start aen failed\n");
+ goto fail_start_aen;
+ }
+
+ /*
+ * Register with SCSI mid-layer
+ */
+ if (megasas_io_attach(instance))
+ goto fail_io_attach;
+
+ return 0;
+
+ fail_start_aen:
+ fail_io_attach:
+ megasas_mgmt_info.count--;
+ megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
+ megasas_mgmt_info.max_index--;
+
+ pci_set_drvdata(pdev, NULL);
+ megasas_disable_intr(instance->reg_set);
+ free_irq(instance->pdev->irq, instance);
+
+ megasas_release_mfi(instance);
+
+ fail_irq:
+ fail_init_mfi:
+ fail_alloc_dma_buf:
+ if (instance->evt_detail)
+ pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+ instance->evt_detail,
+ instance->evt_detail_h);
+
+ if (instance->producer)
+ pci_free_consistent(pdev, sizeof(u32), instance->producer,
+ instance->producer_h);
+ if (instance->consumer)
+ pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+ instance->consumer_h);
+ scsi_host_put(host);
+
+ fail_alloc_instance:
+ fail_set_dma_mask:
+ pci_disable_device(pdev);
+
+ return -ENODEV;
+}
+
+/**
+ * megasas_flush_cache - Requests FW to flush all its caches
+ * @instance: Adapter soft state
+ */
+static void megasas_flush_cache(struct megasas_instance *instance)
+{
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd)
+ return;
+
+ dcmd = &cmd->frame->dcmd;
+
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 0;
+ dcmd->flags = MFI_FRAME_DIR_NONE;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = 0;
+ dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
+ dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
+
+ megasas_issue_blocked_cmd(instance, cmd);
+
+ megasas_return_cmd(instance, cmd);
+
+ return;
+}
+
+/**
+ * megasas_shutdown_controller - Instructs FW to shutdown the controller
+ * @instance: Adapter soft state
+ */
+static void megasas_shutdown_controller(struct megasas_instance *instance)
+{
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd)
+ return;
+
+ if (instance->aen_cmd)
+ megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
+
+ dcmd = &cmd->frame->dcmd;
+
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 0;
+ dcmd->flags = MFI_FRAME_DIR_NONE;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = 0;
+ dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN;
+
+ megasas_issue_blocked_cmd(instance, cmd);
+
+ megasas_return_cmd(instance, cmd);
+
+ return;
+}
+
+/**
+ * megasas_detach_one - PCI hot"un"plug entry point
+ * @pdev: PCI device structure
+ */
+static void megasas_detach_one(struct pci_dev *pdev)
+{
+ int i;
+ struct Scsi_Host *host;
+ struct megasas_instance *instance;
+
+ instance = pci_get_drvdata(pdev);
+ host = instance->host;
+
+ scsi_remove_host(instance->host);
+ megasas_flush_cache(instance);
+ megasas_shutdown_controller(instance);
+
+ /*
+ * Take the instance off the instance array. Note that we will not
+ * decrement the max_index. We let this array be sparse array
+ */
+ for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+ if (megasas_mgmt_info.instance[i] == instance) {
+ megasas_mgmt_info.count--;
+ megasas_mgmt_info.instance[i] = NULL;
+
+ break;
+ }
+ }
+
+ pci_set_drvdata(instance->pdev, NULL);
+
+ megasas_disable_intr(instance->reg_set);
+
+ free_irq(instance->pdev->irq, instance);
+
+ megasas_release_mfi(instance);
+
+ pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+ instance->evt_detail, instance->evt_detail_h);
+
+ pci_free_consistent(pdev, sizeof(u32), instance->producer,
+ instance->producer_h);
+
+ pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+ instance->consumer_h);
+
+ scsi_host_put(host);
+
+ pci_set_drvdata(pdev, NULL);
+
+ pci_disable_device(pdev);
+
+ return;
+}
+
+/**
+ * megasas_shutdown - Shutdown entry point
+ * @device: Generic device structure
+ */
+static void megasas_shutdown(struct pci_dev *pdev)
+{
+ struct megasas_instance *instance = pci_get_drvdata(pdev);
+ megasas_flush_cache(instance);
+}
+
+/**
+ * megasas_mgmt_open - char node "open" entry point
+ */
+static int megasas_mgmt_open(struct inode *inode, struct file *filep)
+{
+ /*
+ * Allow only those users with admin rights
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ return 0;
+}
+
+/**
+ * megasas_mgmt_release - char node "release" entry point
+ */
+static int megasas_mgmt_release(struct inode *inode, struct file *filep)
+{
+ filep->private_data = NULL;
+ fasync_helper(-1, filep, 0, &megasas_async_queue);
+
+ return 0;
+}
+
+/**
+ * megasas_mgmt_fasync - Async notifier registration from applications
+ *
+ * This function adds the calling process to a driver global queue. When an
+ * event occurs, SIGIO will be sent to all processes in this queue.
+ */
+static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
+{
+ int rc;
+
+ down(&megasas_async_queue_mutex);
+
+ rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
+
+ up(&megasas_async_queue_mutex);
+
+ if (rc >= 0) {
+ /* For sanity check when we get ioctl */
+ filep->private_data = filep;
+ return 0;
+ }
+
+ printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc);
+
+ return rc;
+}
+
+/**
+ * megasas_mgmt_fw_ioctl - Issues management ioctls to FW
+ * @instance: Adapter soft state
+ * @argp: User's ioctl packet
+ */
+static int
+megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ struct megasas_iocpacket __user * user_ioc,
+ struct megasas_iocpacket *ioc)
+{
+ struct megasas_sge32 *kern_sge32;
+ struct megasas_cmd *cmd;
+ void *kbuff_arr[MAX_IOCTL_SGE];
+ dma_addr_t buf_handle = 0;
+ int error = 0, i;
+ void *sense = NULL;
+ dma_addr_t sense_handle;
+ u32 *sense_ptr;
+
+ memset(kbuff_arr, 0, sizeof(kbuff_arr));
+
+ if (ioc->sge_count > MAX_IOCTL_SGE) {
+ printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n",
+ ioc->sge_count, MAX_IOCTL_SGE);
+ return -EINVAL;
+ }
+
+ cmd = megasas_get_cmd(instance);
+ if (!cmd) {
+ printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * User's IOCTL packet has 2 frames (maximum). Copy those two
+ * frames into our cmd's frames. cmd->frame's context will get
+ * overwritten when we copy from user's frames. So set that value
+ * alone separately
+ */
+ memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
+ cmd->frame->hdr.context = cmd->index;
+
+ /*
+ * The management interface between applications and the fw uses
+ * MFI frames. E.g, RAID configuration changes, LD property changes
+ * etc are accomplishes through different kinds of MFI frames. The
+ * driver needs to care only about substituting user buffers with
+ * kernel buffers in SGLs. The location of SGL is embedded in the
+ * struct iocpacket itself.
+ */
+ kern_sge32 = (struct megasas_sge32 *)
+ ((unsigned long)cmd->frame + ioc->sgl_off);
+
+ /*
+ * For each user buffer, create a mirror buffer and copy in
+ */
+ for (i = 0; i < ioc->sge_count; i++) {
+ kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
+ ioc->sgl[i].iov_len,
+ &buf_handle);
+ if (!kbuff_arr[i]) {
+ printk(KERN_DEBUG "megasas: Failed to alloc "
+ "kernel SGL buffer for IOCTL \n");
+ error = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * We don't change the dma_coherent_mask, so
+ * pci_alloc_consistent only returns 32bit addresses
+ */
+ kern_sge32[i].phys_addr = (u32) buf_handle;
+ kern_sge32[i].length = ioc->sgl[i].iov_len;
+
+ /*
+ * We created a kernel buffer corresponding to the
+ * user buffer. Now copy in from the user buffer
+ */
+ if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base,
+ (u32) (ioc->sgl[i].iov_len))) {
+ error = -EFAULT;
+ goto out;
+ }
+ }
+
+ if (ioc->sense_len) {
+ sense = pci_alloc_consistent(instance->pdev, ioc->sense_len,
+ &sense_handle);
+ if (!sense) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ sense_ptr =
+ (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
+ *sense_ptr = sense_handle;
+ }
+
+ /*
+ * Set the sync_cmd flag so that the ISR knows not to complete this
+ * cmd to the SCSI mid-layer
+ */
+ cmd->sync_cmd = 1;
+ megasas_issue_blocked_cmd(instance, cmd);
+ cmd->sync_cmd = 0;
+
+ /*
+ * copy out the kernel buffers to user buffers
+ */
+ for (i = 0; i < ioc->sge_count; i++) {
+ if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i],
+ ioc->sgl[i].iov_len)) {
+ error = -EFAULT;
+ goto out;
+ }
+ }
+
+ /*
+ * copy out the sense
+ */
+ if (ioc->sense_len) {
+ /*
+ * sense_ptr points to the location that has the user
+ * sense buffer address
+ */
+ sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
+ ioc->sense_off);
+
+ if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
+ sense, ioc->sense_len)) {
+ error = -EFAULT;
+ goto out;
+ }
+ }
+
+ /*
+ * copy the status codes returned by the fw
+ */
+ if (copy_to_user(&user_ioc->frame.hdr.cmd_status,
+ &cmd->frame->hdr.cmd_status, sizeof(u8))) {
+ printk(KERN_DEBUG "megasas: Error copying out cmd_status\n");
+ error = -EFAULT;
+ }
+
+ out:
+ if (sense) {
+ pci_free_consistent(instance->pdev, ioc->sense_len,
+ sense, sense_handle);
+ }
+
+ for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
+ pci_free_consistent(instance->pdev,
+ kern_sge32[i].length,
+ kbuff_arr[i], kern_sge32[i].phys_addr);
+ }
+
+ megasas_return_cmd(instance, cmd);
+ return error;
+}
+
+static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+{
+ int i;
+
+ for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+
+ if ((megasas_mgmt_info.instance[i]) &&
+ (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+ return megasas_mgmt_info.instance[i];
+ }
+
+ return NULL;
+}
+
+static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+{
+ struct megasas_iocpacket __user *user_ioc =
+ (struct megasas_iocpacket __user *)arg;
+ struct megasas_iocpacket *ioc;
+ struct megasas_instance *instance;
+ int error;
+
+ ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
+ if (!ioc)
+ return -ENOMEM;
+
+ if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
+ error = -EFAULT;
+ goto out_kfree_ioc;
+ }
+
+ instance = megasas_lookup_instance(ioc->host_no);
+ if (!instance) {
+ error = -ENODEV;
+ goto out_kfree_ioc;
+ }
+
+ /*
+ * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
+ */
+ if (down_interruptible(&instance->ioctl_sem)) {
+ error = -ERESTARTSYS;
+ goto out_kfree_ioc;
+ }
+ error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
+ up(&instance->ioctl_sem);
+
+ out_kfree_ioc:
+ kfree(ioc);
+ return error;
+}
+
+static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
+{
+ struct megasas_instance *instance;
+ struct megasas_aen aen;
+ int error;
+
+ if (file->private_data != file) {
+ printk(KERN_DEBUG "megasas: fasync_helper was not "
+ "called first\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&aen, (void __user *)arg, sizeof(aen)))
+ return -EFAULT;
+
+ instance = megasas_lookup_instance(aen.host_no);
+
+ if (!instance)
+ return -ENODEV;
+
+ down(&instance->aen_mutex);
+ error = megasas_register_aen(instance, aen.seq_num,
+ aen.class_locale_word);
+ up(&instance->aen_mutex);
+ return error;
+}
+
+/**
+ * megasas_mgmt_ioctl - char node ioctl entry point
+ */
+static long
+megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case MEGASAS_IOC_FIRMWARE:
+ return megasas_mgmt_ioctl_fw(file, arg);
+
+ case MEGASAS_IOC_GET_AEN:
+ return megasas_mgmt_ioctl_aen(file, arg);
+ }
+
+ return -ENOTTY;
+}
+
+#ifdef CONFIG_COMPAT
+static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
+{
+ struct compat_megasas_iocpacket __user *cioc =
+ (struct compat_megasas_iocpacket __user *)arg;
+ struct megasas_iocpacket __user *ioc =
+ compat_alloc_user_space(sizeof(struct megasas_iocpacket));
+ int i;
+ int error = 0;
+
+ clear_user(ioc, sizeof(*ioc));
+
+ if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
+ copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
+ copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
+ copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
+ copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
+ copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
+ return -EFAULT;
+
+ for (i = 0; i < MAX_IOCTL_SGE; i++) {
+ compat_uptr_t ptr;
+
+ if (get_user(ptr, &cioc->sgl[i].iov_base) ||
+ put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
+ copy_in_user(&ioc->sgl[i].iov_len,
+ &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
+ return -EFAULT;
+ }
+
+ error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
+
+ if (copy_in_user(&cioc->frame.hdr.cmd_status,
+ &ioc->frame.hdr.cmd_status, sizeof(u8))) {
+ printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
+ return -EFAULT;
+ }
+ return error;
+}
+
+static long
+megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case MEGASAS_IOC_FIRMWARE:{
+ return megasas_mgmt_compat_ioctl_fw(file, arg);
+ }
+ case MEGASAS_IOC_GET_AEN:
+ return megasas_mgmt_ioctl_aen(file, arg);
+ }
+
+ return -ENOTTY;
+}
+#endif
+
+/*
+ * File operations structure for management interface
+ */
+static struct file_operations megasas_mgmt_fops = {
+ .owner = THIS_MODULE,
+ .open = megasas_mgmt_open,
+ .release = megasas_mgmt_release,
+ .fasync = megasas_mgmt_fasync,
+ .unlocked_ioctl = megasas_mgmt_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = megasas_mgmt_compat_ioctl,
+#endif
+};
+
+/*
+ * PCI hotplug support registration structure
+ */
+static struct pci_driver megasas_pci_driver = {
+
+ .name = "megaraid_sas",
+ .id_table = megasas_pci_table,
+ .probe = megasas_probe_one,
+ .remove = __devexit_p(megasas_detach_one),
+ .shutdown = megasas_shutdown,
+};
+
+/*
+ * Sysfs driver attributes
+ */
+static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
+{
+ return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n",
+ MEGASAS_VERSION);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
+
+static ssize_t
+megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
+{
+ return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
+ MEGASAS_RELDATE);
+}
+
+static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
+ NULL);
+
+/**
+ * megasas_init - Driver load entry point
+ */
+static int __init megasas_init(void)
+{
+ int rval;
+
+ /*
+ * Announce driver version and other information
+ */
+ printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
+ MEGASAS_EXT_VERSION);
+
+ memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
+
+ /*
+ * Register character device node
+ */
+ rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);
+
+ if (rval < 0) {
+ printk(KERN_DEBUG "megasas: failed to open device node\n");
+ return rval;
+ }
+
+ megasas_mgmt_majorno = rval;
+
+ /*
+ * Register ourselves as PCI hotplug module
+ */
+ rval = pci_module_init(&megasas_pci_driver);
+
+ if (rval) {
+ printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
+ unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+ }
+
+ driver_create_file(&megasas_pci_driver.driver, &driver_attr_version);
+ driver_create_file(&megasas_pci_driver.driver,
+ &driver_attr_release_date);
+
+ return rval;
+}
+
+/**
+ * megasas_exit - Driver unload entry point
+ */
+static void __exit megasas_exit(void)
+{
+ driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+ driver_remove_file(&megasas_pci_driver.driver,
+ &driver_attr_release_date);
+
+ pci_unregister_driver(&megasas_pci_driver);
+ unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+}
+
+module_init(megasas_init);
+module_exit(megasas_exit);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
new file mode 100644
index 000000000000..eaec9d531424
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -0,0 +1,1142 @@
+/*
+ *
+ * Linux MegaRAID driver for SAS based RAID controllers
+ *
+ * Copyright (c) 2003-2005 LSI Logic Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * FILE : megaraid_sas.h
+ */
+
+#ifndef LSI_MEGARAID_SAS_H
+#define LSI_MEGARAID_SAS_H
+
+/**
+ * MegaRAID SAS Driver meta data
+ */
+#define MEGASAS_VERSION "00.00.02.00-rc4"
+#define MEGASAS_RELDATE "Sep 16, 2005"
+#define MEGASAS_EXT_VERSION "Fri Sep 16 12:37:08 EDT 2005"
+
+/*
+ * =====================================
+ * MegaRAID SAS MFI firmware definitions
+ * =====================================
+ */
+
+/*
+ * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for
+ * protocol between the software and firmware. Commands are issued using
+ * "message frames"
+ */
+
+/**
+ * FW posts its state in upper 4 bits of outbound_msg_0 register
+ */
+#define MFI_STATE_MASK 0xF0000000
+#define MFI_STATE_UNDEFINED 0x00000000
+#define MFI_STATE_BB_INIT 0x10000000
+#define MFI_STATE_FW_INIT 0x40000000
+#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
+#define MFI_STATE_FW_INIT_2 0x70000000
+#define MFI_STATE_DEVICE_SCAN 0x80000000
+#define MFI_STATE_FLUSH_CACHE 0xA0000000
+#define MFI_STATE_READY 0xB0000000
+#define MFI_STATE_OPERATIONAL 0xC0000000
+#define MFI_STATE_FAULT 0xF0000000
+
+#define MEGAMFI_FRAME_SIZE 64
+
+/**
+ * During FW init, clear pending cmds & reset state using inbound_msg_0
+ *
+ * ABORT : Abort all pending cmds
+ * READY : Move from OPERATIONAL to READY state; discard queue info
+ * MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??)
+ * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
+ */
+#define MFI_INIT_ABORT 0x00000000
+#define MFI_INIT_READY 0x00000002
+#define MFI_INIT_MFIMODE 0x00000004
+#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008
+#define MFI_RESET_FLAGS MFI_INIT_READY|MFI_INIT_MFIMODE
+
+/**
+ * MFI frame flags
+ */
+#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000
+#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001
+#define MFI_FRAME_SGL32 0x0000
+#define MFI_FRAME_SGL64 0x0002
+#define MFI_FRAME_SENSE32 0x0000
+#define MFI_FRAME_SENSE64 0x0004
+#define MFI_FRAME_DIR_NONE 0x0000
+#define MFI_FRAME_DIR_WRITE 0x0008
+#define MFI_FRAME_DIR_READ 0x0010
+#define MFI_FRAME_DIR_BOTH 0x0018
+
+/**
+ * Definition for cmd_status
+ */
+#define MFI_CMD_STATUS_POLL_MODE 0xFF
+
+/**
+ * MFI command opcodes
+ */
+#define MFI_CMD_INIT 0x00
+#define MFI_CMD_LD_READ 0x01
+#define MFI_CMD_LD_WRITE 0x02
+#define MFI_CMD_LD_SCSI_IO 0x03
+#define MFI_CMD_PD_SCSI_IO 0x04
+#define MFI_CMD_DCMD 0x05
+#define MFI_CMD_ABORT 0x06
+#define MFI_CMD_SMP 0x07
+#define MFI_CMD_STP 0x08
+
+#define MR_DCMD_CTRL_GET_INFO 0x01010000
+
+#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
+#define MR_FLUSH_CTRL_CACHE 0x01
+#define MR_FLUSH_DISK_CACHE 0x02
+
+#define MR_DCMD_CTRL_SHUTDOWN 0x01050000
+#define MR_ENABLE_DRIVE_SPINDOWN 0x01
+
+#define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100
+#define MR_DCMD_CTRL_EVENT_GET 0x01040300
+#define MR_DCMD_CTRL_EVENT_WAIT 0x01040500
+#define MR_DCMD_LD_GET_PROPERTIES 0x03030000
+
+#define MR_DCMD_CLUSTER 0x08000000
+#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100
+#define MR_DCMD_CLUSTER_RESET_LD 0x08010200
+
+/**
+ * MFI command completion codes
+ */
+enum MFI_STAT {
+ MFI_STAT_OK = 0x00,
+ MFI_STAT_INVALID_CMD = 0x01,
+ MFI_STAT_INVALID_DCMD = 0x02,
+ MFI_STAT_INVALID_PARAMETER = 0x03,
+ MFI_STAT_INVALID_SEQUENCE_NUMBER = 0x04,
+ MFI_STAT_ABORT_NOT_POSSIBLE = 0x05,
+ MFI_STAT_APP_HOST_CODE_NOT_FOUND = 0x06,
+ MFI_STAT_APP_IN_USE = 0x07,
+ MFI_STAT_APP_NOT_INITIALIZED = 0x08,
+ MFI_STAT_ARRAY_INDEX_INVALID = 0x09,
+ MFI_STAT_ARRAY_ROW_NOT_EMPTY = 0x0a,
+ MFI_STAT_CONFIG_RESOURCE_CONFLICT = 0x0b,
+ MFI_STAT_DEVICE_NOT_FOUND = 0x0c,
+ MFI_STAT_DRIVE_TOO_SMALL = 0x0d,
+ MFI_STAT_FLASH_ALLOC_FAIL = 0x0e,
+ MFI_STAT_FLASH_BUSY = 0x0f,
+ MFI_STAT_FLASH_ERROR = 0x10,
+ MFI_STAT_FLASH_IMAGE_BAD = 0x11,
+ MFI_STAT_FLASH_IMAGE_INCOMPLETE = 0x12,
+ MFI_STAT_FLASH_NOT_OPEN = 0x13,
+ MFI_STAT_FLASH_NOT_STARTED = 0x14,
+ MFI_STAT_FLUSH_FAILED = 0x15,
+ MFI_STAT_HOST_CODE_NOT_FOUNT = 0x16,
+ MFI_STAT_LD_CC_IN_PROGRESS = 0x17,
+ MFI_STAT_LD_INIT_IN_PROGRESS = 0x18,
+ MFI_STAT_LD_LBA_OUT_OF_RANGE = 0x19,
+ MFI_STAT_LD_MAX_CONFIGURED = 0x1a,
+ MFI_STAT_LD_NOT_OPTIMAL = 0x1b,
+ MFI_STAT_LD_RBLD_IN_PROGRESS = 0x1c,
+ MFI_STAT_LD_RECON_IN_PROGRESS = 0x1d,
+ MFI_STAT_LD_WRONG_RAID_LEVEL = 0x1e,
+ MFI_STAT_MAX_SPARES_EXCEEDED = 0x1f,
+ MFI_STAT_MEMORY_NOT_AVAILABLE = 0x20,
+ MFI_STAT_MFC_HW_ERROR = 0x21,
+ MFI_STAT_NO_HW_PRESENT = 0x22,
+ MFI_STAT_NOT_FOUND = 0x23,
+ MFI_STAT_NOT_IN_ENCL = 0x24,
+ MFI_STAT_PD_CLEAR_IN_PROGRESS = 0x25,
+ MFI_STAT_PD_TYPE_WRONG = 0x26,
+ MFI_STAT_PR_DISABLED = 0x27,
+ MFI_STAT_ROW_INDEX_INVALID = 0x28,
+ MFI_STAT_SAS_CONFIG_INVALID_ACTION = 0x29,
+ MFI_STAT_SAS_CONFIG_INVALID_DATA = 0x2a,
+ MFI_STAT_SAS_CONFIG_INVALID_PAGE = 0x2b,
+ MFI_STAT_SAS_CONFIG_INVALID_TYPE = 0x2c,
+ MFI_STAT_SCSI_DONE_WITH_ERROR = 0x2d,
+ MFI_STAT_SCSI_IO_FAILED = 0x2e,
+ MFI_STAT_SCSI_RESERVATION_CONFLICT = 0x2f,
+ MFI_STAT_SHUTDOWN_FAILED = 0x30,
+ MFI_STAT_TIME_NOT_SET = 0x31,
+ MFI_STAT_WRONG_STATE = 0x32,
+ MFI_STAT_LD_OFFLINE = 0x33,
+ MFI_STAT_PEER_NOTIFICATION_REJECTED = 0x34,
+ MFI_STAT_PEER_NOTIFICATION_FAILED = 0x35,
+ MFI_STAT_RESERVATION_IN_PROGRESS = 0x36,
+ MFI_STAT_I2C_ERRORS_DETECTED = 0x37,
+ MFI_STAT_PCI_ERRORS_DETECTED = 0x38,
+
+ MFI_STAT_INVALID_STATUS = 0xFF
+};
+
+/*
+ * Number of mailbox bytes in DCMD message frame
+ */
+#define MFI_MBOX_SIZE 12
+
+enum MR_EVT_CLASS {
+
+ MR_EVT_CLASS_DEBUG = -2,
+ MR_EVT_CLASS_PROGRESS = -1,
+ MR_EVT_CLASS_INFO = 0,
+ MR_EVT_CLASS_WARNING = 1,
+ MR_EVT_CLASS_CRITICAL = 2,
+ MR_EVT_CLASS_FATAL = 3,
+ MR_EVT_CLASS_DEAD = 4,
+
+};
+
+enum MR_EVT_LOCALE {
+
+ MR_EVT_LOCALE_LD = 0x0001,
+ MR_EVT_LOCALE_PD = 0x0002,
+ MR_EVT_LOCALE_ENCL = 0x0004,
+ MR_EVT_LOCALE_BBU = 0x0008,
+ MR_EVT_LOCALE_SAS = 0x0010,
+ MR_EVT_LOCALE_CTRL = 0x0020,
+ MR_EVT_LOCALE_CONFIG = 0x0040,
+ MR_EVT_LOCALE_CLUSTER = 0x0080,
+ MR_EVT_LOCALE_ALL = 0xffff,
+
+};
+
+enum MR_EVT_ARGS {
+
+ MR_EVT_ARGS_NONE,
+ MR_EVT_ARGS_CDB_SENSE,
+ MR_EVT_ARGS_LD,
+ MR_EVT_ARGS_LD_COUNT,
+ MR_EVT_ARGS_LD_LBA,
+ MR_EVT_ARGS_LD_OWNER,
+ MR_EVT_ARGS_LD_LBA_PD_LBA,
+ MR_EVT_ARGS_LD_PROG,
+ MR_EVT_ARGS_LD_STATE,
+ MR_EVT_ARGS_LD_STRIP,
+ MR_EVT_ARGS_PD,
+ MR_EVT_ARGS_PD_ERR,
+ MR_EVT_ARGS_PD_LBA,
+ MR_EVT_ARGS_PD_LBA_LD,
+ MR_EVT_ARGS_PD_PROG,
+ MR_EVT_ARGS_PD_STATE,
+ MR_EVT_ARGS_PCI,
+ MR_EVT_ARGS_RATE,
+ MR_EVT_ARGS_STR,
+ MR_EVT_ARGS_TIME,
+ MR_EVT_ARGS_ECC,
+
+};
+
+/*
+ * SAS controller properties
+ */
+struct megasas_ctrl_prop {
+
+ u16 seq_num;
+ u16 pred_fail_poll_interval;
+ u16 intr_throttle_count;
+ u16 intr_throttle_timeouts;
+ u8 rebuild_rate;
+ u8 patrol_read_rate;
+ u8 bgi_rate;
+ u8 cc_rate;
+ u8 recon_rate;
+ u8 cache_flush_interval;
+ u8 spinup_drv_count;
+ u8 spinup_delay;
+ u8 cluster_enable;
+ u8 coercion_mode;
+ u8 alarm_enable;
+ u8 disable_auto_rebuild;
+ u8 disable_battery_warn;
+ u8 ecc_bucket_size;
+ u16 ecc_bucket_leak_rate;
+ u8 restore_hotspare_on_insertion;
+ u8 expose_encl_devices;
+ u8 reserved[38];
+
+} __attribute__ ((packed));
+
+/*
+ * SAS controller information
+ */
+struct megasas_ctrl_info {
+
+ /*
+ * PCI device information
+ */
+ struct {
+
+ u16 vendor_id;
+ u16 device_id;
+ u16 sub_vendor_id;
+ u16 sub_device_id;
+ u8 reserved[24];
+
+ } __attribute__ ((packed)) pci;
+
+ /*
+ * Host interface information
+ */
+ struct {
+
+ u8 PCIX:1;
+ u8 PCIE:1;
+ u8 iSCSI:1;
+ u8 SAS_3G:1;
+ u8 reserved_0:4;
+ u8 reserved_1[6];
+ u8 port_count;
+ u64 port_addr[8];
+
+ } __attribute__ ((packed)) host_interface;
+
+ /*
+ * Device (backend) interface information
+ */
+ struct {
+
+ u8 SPI:1;
+ u8 SAS_3G:1;
+ u8 SATA_1_5G:1;
+ u8 SATA_3G:1;
+ u8 reserved_0:4;
+ u8 reserved_1[6];
+ u8 port_count;
+ u64 port_addr[8];
+
+ } __attribute__ ((packed)) device_interface;
+
+ /*
+ * List of components residing in flash. All str are null terminated
+ */
+ u32 image_check_word;
+ u32 image_component_count;
+
+ struct {
+
+ char name[8];
+ char version[32];
+ char build_date[16];
+ char built_time[16];
+
+ } __attribute__ ((packed)) image_component[8];
+
+ /*
+ * List of flash components that have been flashed on the card, but
+ * are not in use, pending reset of the adapter. This list will be
+ * empty if a flash operation has not occurred. All stings are null
+ * terminated
+ */
+ u32 pending_image_component_count;
+
+ struct {
+
+ char name[8];
+ char version[32];
+ char build_date[16];
+ char build_time[16];
+
+ } __attribute__ ((packed)) pending_image_component[8];
+
+ u8 max_arms;
+ u8 max_spans;
+ u8 max_arrays;
+ u8 max_lds;
+
+ char product_name[80];
+ char serial_no[32];
+
+ /*
+ * Other physical/controller/operation information. Indicates the
+ * presence of the hardware
+ */
+ struct {
+
+ u32 bbu:1;
+ u32 alarm:1;
+ u32 nvram:1;
+ u32 uart:1;
+ u32 reserved:28;
+
+ } __attribute__ ((packed)) hw_present;
+
+ u32 current_fw_time;
+
+ /*
+ * Maximum data transfer sizes
+ */
+ u16 max_concurrent_cmds;
+ u16 max_sge_count;
+ u32 max_request_size;
+
+ /*
+ * Logical and physical device counts
+ */
+ u16 ld_present_count;
+ u16 ld_degraded_count;
+ u16 ld_offline_count;
+
+ u16 pd_present_count;
+ u16 pd_disk_present_count;
+ u16 pd_disk_pred_failure_count;
+ u16 pd_disk_failed_count;
+
+ /*
+ * Memory size information
+ */
+ u16 nvram_size;
+ u16 memory_size;
+ u16 flash_size;
+
+ /*
+ * Error counters
+ */
+ u16 mem_correctable_error_count;
+ u16 mem_uncorrectable_error_count;
+
+ /*
+ * Cluster information
+ */
+ u8 cluster_permitted;
+ u8 cluster_active;
+
+ /*
+ * Additional max data transfer sizes
+ */
+ u16 max_strips_per_io;
+
+ /*
+ * Controller capabilities structures
+ */
+ struct {
+
+ u32 raid_level_0:1;
+ u32 raid_level_1:1;
+ u32 raid_level_5:1;
+ u32 raid_level_1E:1;
+ u32 raid_level_6:1;
+ u32 reserved:27;
+
+ } __attribute__ ((packed)) raid_levels;
+
+ struct {
+
+ u32 rbld_rate:1;
+ u32 cc_rate:1;
+ u32 bgi_rate:1;
+ u32 recon_rate:1;
+ u32 patrol_rate:1;
+ u32 alarm_control:1;
+ u32 cluster_supported:1;
+ u32 bbu:1;
+ u32 spanning_allowed:1;
+ u32 dedicated_hotspares:1;
+ u32 revertible_hotspares:1;
+ u32 foreign_config_import:1;
+ u32 self_diagnostic:1;
+ u32 mixed_redundancy_arr:1;
+ u32 global_hot_spares:1;
+ u32 reserved:17;
+
+ } __attribute__ ((packed)) adapter_operations;
+
+ struct {
+
+ u32 read_policy:1;
+ u32 write_policy:1;
+ u32 io_policy:1;
+ u32 access_policy:1;
+ u32 disk_cache_policy:1;
+ u32 reserved:27;
+
+ } __attribute__ ((packed)) ld_operations;
+
+ struct {
+
+ u8 min;
+ u8 max;
+ u8 reserved[2];
+
+ } __attribute__ ((packed)) stripe_sz_ops;
+
+ struct {
+
+ u32 force_online:1;
+ u32 force_offline:1;
+ u32 force_rebuild:1;
+ u32 reserved:29;
+
+ } __attribute__ ((packed)) pd_operations;
+
+ struct {
+
+ u32 ctrl_supports_sas:1;
+ u32 ctrl_supports_sata:1;
+ u32 allow_mix_in_encl:1;
+ u32 allow_mix_in_ld:1;
+ u32 allow_sata_in_cluster:1;
+ u32 reserved:27;
+
+ } __attribute__ ((packed)) pd_mix_support;
+
+ /*
+ * Define ECC single-bit-error bucket information
+ */
+ u8 ecc_bucket_count;
+ u8 reserved_2[11];
+
+ /*
+ * Include the controller properties (changeable items)
+ */
+ struct megasas_ctrl_prop properties;
+
+ /*
+ * Define FW pkg version (set in envt v'bles on OEM basis)
+ */
+ char package_version[0x60];
+
+ u8 pad[0x800 - 0x6a0];
+
+} __attribute__ ((packed));
+
+/*
+ * ===============================
+ * MegaRAID SAS driver definitions
+ * ===============================
+ */
+#define MEGASAS_MAX_PD_CHANNELS 2
+#define MEGASAS_MAX_LD_CHANNELS 2
+#define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \
+ MEGASAS_MAX_LD_CHANNELS)
+#define MEGASAS_MAX_DEV_PER_CHANNEL 128
+#define MEGASAS_DEFAULT_INIT_ID -1
+#define MEGASAS_MAX_LUN 8
+#define MEGASAS_MAX_LD 64
+
+/*
+ * When SCSI mid-layer calls driver's reset routine, driver waits for
+ * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
+ * that the driver cannot _actually_ abort or reset pending commands. While
+ * it is waiting for the commands to complete, it prints a diagnostic message
+ * every MEGASAS_RESET_NOTICE_INTERVAL seconds
+ */
+#define MEGASAS_RESET_WAIT_TIME 180
+#define MEGASAS_RESET_NOTICE_INTERVAL 5
+
+#define MEGASAS_IOCTL_CMD 0
+
+/*
+ * FW reports the maximum of number of commands that it can accept (maximum
+ * commands that can be outstanding) at any time. The driver must report a
+ * lower number to the mid layer because it can issue a few internal commands
+ * itself (E.g, AEN, abort cmd, IOCTLs etc). The number of commands it needs
+ * is shown below
+ */
+#define MEGASAS_INT_CMDS 32
+
+/*
+ * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
+ * SGLs based on the size of dma_addr_t
+ */
+#define IS_DMA64 (sizeof(dma_addr_t) == 8)
+
+#define MFI_OB_INTR_STATUS_MASK 0x00000002
+#define MFI_POLL_TIMEOUT_SECS 10
+
+struct megasas_register_set {
+
+ u32 reserved_0[4]; /*0000h */
+
+ u32 inbound_msg_0; /*0010h */
+ u32 inbound_msg_1; /*0014h */
+ u32 outbound_msg_0; /*0018h */
+ u32 outbound_msg_1; /*001Ch */
+
+ u32 inbound_doorbell; /*0020h */
+ u32 inbound_intr_status; /*0024h */
+ u32 inbound_intr_mask; /*0028h */
+
+ u32 outbound_doorbell; /*002Ch */
+ u32 outbound_intr_status; /*0030h */
+ u32 outbound_intr_mask; /*0034h */
+
+ u32 reserved_1[2]; /*0038h */
+
+ u32 inbound_queue_port; /*0040h */
+ u32 outbound_queue_port; /*0044h */
+
+ u32 reserved_2; /*004Ch */
+
+ u32 index_registers[1004]; /*0050h */
+
+} __attribute__ ((packed));
+
+struct megasas_sge32 {
+
+ u32 phys_addr;
+ u32 length;
+
+} __attribute__ ((packed));
+
+struct megasas_sge64 {
+
+ u64 phys_addr;
+ u32 length;
+
+} __attribute__ ((packed));
+
+union megasas_sgl {
+
+ struct megasas_sge32 sge32[1];
+ struct megasas_sge64 sge64[1];
+
+} __attribute__ ((packed));
+
+struct megasas_header {
+
+ u8 cmd; /*00h */
+ u8 sense_len; /*01h */
+ u8 cmd_status; /*02h */
+ u8 scsi_status; /*03h */
+
+ u8 target_id; /*04h */
+ u8 lun; /*05h */
+ u8 cdb_len; /*06h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+ u32 data_xferlen; /*14h */
+
+} __attribute__ ((packed));
+
+union megasas_sgl_frame {
+
+ struct megasas_sge32 sge32[8];
+ struct megasas_sge64 sge64[5];
+
+} __attribute__ ((packed));
+
+struct megasas_init_frame {
+
+ u8 cmd; /*00h */
+ u8 reserved_0; /*01h */
+ u8 cmd_status; /*02h */
+
+ u8 reserved_1; /*03h */
+ u32 reserved_2; /*04h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 reserved_3; /*12h */
+ u32 data_xfer_len; /*14h */
+
+ u32 queue_info_new_phys_addr_lo; /*18h */
+ u32 queue_info_new_phys_addr_hi; /*1Ch */
+ u32 queue_info_old_phys_addr_lo; /*20h */
+ u32 queue_info_old_phys_addr_hi; /*24h */
+
+ u32 reserved_4[6]; /*28h */
+
+} __attribute__ ((packed));
+
+struct megasas_init_queue_info {
+
+ u32 init_flags; /*00h */
+ u32 reply_queue_entries; /*04h */
+
+ u32 reply_queue_start_phys_addr_lo; /*08h */
+ u32 reply_queue_start_phys_addr_hi; /*0Ch */
+ u32 producer_index_phys_addr_lo; /*10h */
+ u32 producer_index_phys_addr_hi; /*14h */
+ u32 consumer_index_phys_addr_lo; /*18h */
+ u32 consumer_index_phys_addr_hi; /*1Ch */
+
+} __attribute__ ((packed));
+
+struct megasas_io_frame {
+
+ u8 cmd; /*00h */
+ u8 sense_len; /*01h */
+ u8 cmd_status; /*02h */
+ u8 scsi_status; /*03h */
+
+ u8 target_id; /*04h */
+ u8 access_byte; /*05h */
+ u8 reserved_0; /*06h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+ u32 lba_count; /*14h */
+
+ u32 sense_buf_phys_addr_lo; /*18h */
+ u32 sense_buf_phys_addr_hi; /*1Ch */
+
+ u32 start_lba_lo; /*20h */
+ u32 start_lba_hi; /*24h */
+
+ union megasas_sgl sgl; /*28h */
+
+} __attribute__ ((packed));
+
+struct megasas_pthru_frame {
+
+ u8 cmd; /*00h */
+ u8 sense_len; /*01h */
+ u8 cmd_status; /*02h */
+ u8 scsi_status; /*03h */
+
+ u8 target_id; /*04h */
+ u8 lun; /*05h */
+ u8 cdb_len; /*06h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+ u32 data_xfer_len; /*14h */
+
+ u32 sense_buf_phys_addr_lo; /*18h */
+ u32 sense_buf_phys_addr_hi; /*1Ch */
+
+ u8 cdb[16]; /*20h */
+ union megasas_sgl sgl; /*30h */
+
+} __attribute__ ((packed));
+
+struct megasas_dcmd_frame {
+
+ u8 cmd; /*00h */
+ u8 reserved_0; /*01h */
+ u8 cmd_status; /*02h */
+ u8 reserved_1[4]; /*03h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+
+ u32 data_xfer_len; /*14h */
+ u32 opcode; /*18h */
+
+ union { /*1Ch */
+ u8 b[12];
+ u16 s[6];
+ u32 w[3];
+ } mbox;
+
+ union megasas_sgl sgl; /*28h */
+
+} __attribute__ ((packed));
+
+struct megasas_abort_frame {
+
+ u8 cmd; /*00h */
+ u8 reserved_0; /*01h */
+ u8 cmd_status; /*02h */
+
+ u8 reserved_1; /*03h */
+ u32 reserved_2; /*04h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 reserved_3; /*12h */
+ u32 reserved_4; /*14h */
+
+ u32 abort_context; /*18h */
+ u32 pad_1; /*1Ch */
+
+ u32 abort_mfi_phys_addr_lo; /*20h */
+ u32 abort_mfi_phys_addr_hi; /*24h */
+
+ u32 reserved_5[6]; /*28h */
+
+} __attribute__ ((packed));
+
+struct megasas_smp_frame {
+
+ u8 cmd; /*00h */
+ u8 reserved_1; /*01h */
+ u8 cmd_status; /*02h */
+ u8 connection_status; /*03h */
+
+ u8 reserved_2[3]; /*04h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+
+ u32 data_xfer_len; /*14h */
+ u64 sas_addr; /*18h */
+
+ union {
+ struct megasas_sge32 sge32[2]; /* [0]: resp [1]: req */
+ struct megasas_sge64 sge64[2]; /* [0]: resp [1]: req */
+ } sgl;
+
+} __attribute__ ((packed));
+
+struct megasas_stp_frame {
+
+ u8 cmd; /*00h */
+ u8 reserved_1; /*01h */
+ u8 cmd_status; /*02h */
+ u8 reserved_2; /*03h */
+
+ u8 target_id; /*04h */
+ u8 reserved_3[2]; /*05h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 pad_0; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+
+ u32 data_xfer_len; /*14h */
+
+ u16 fis[10]; /*18h */
+ u32 stp_flags;
+
+ union {
+ struct megasas_sge32 sge32[2]; /* [0]: resp [1]: data */
+ struct megasas_sge64 sge64[2]; /* [0]: resp [1]: data */
+ } sgl;
+
+} __attribute__ ((packed));
+
+union megasas_frame {
+
+ struct megasas_header hdr;
+ struct megasas_init_frame init;
+ struct megasas_io_frame io;
+ struct megasas_pthru_frame pthru;
+ struct megasas_dcmd_frame dcmd;
+ struct megasas_abort_frame abort;
+ struct megasas_smp_frame smp;
+ struct megasas_stp_frame stp;
+
+ u8 raw_bytes[64];
+};
+
+struct megasas_cmd;
+
+union megasas_evt_class_locale {
+
+ struct {
+ u16 locale;
+ u8 reserved;
+ s8 class;
+ } __attribute__ ((packed)) members;
+
+ u32 word;
+
+} __attribute__ ((packed));
+
+struct megasas_evt_log_info {
+ u32 newest_seq_num;
+ u32 oldest_seq_num;
+ u32 clear_seq_num;
+ u32 shutdown_seq_num;
+ u32 boot_seq_num;
+
+} __attribute__ ((packed));
+
+struct megasas_progress {
+
+ u16 progress;
+ u16 elapsed_seconds;
+
+} __attribute__ ((packed));
+
+struct megasas_evtarg_ld {
+
+ u16 target_id;
+ u8 ld_index;
+ u8 reserved;
+
+} __attribute__ ((packed));
+
+struct megasas_evtarg_pd {
+ u16 device_id;
+ u8 encl_index;
+ u8 slot_number;
+
+} __attribute__ ((packed));
+
+struct megasas_evt_detail {
+
+ u32 seq_num;
+ u32 time_stamp;
+ u32 code;
+ union megasas_evt_class_locale cl;
+ u8 arg_type;
+ u8 reserved1[15];
+
+ union {
+ struct {
+ struct megasas_evtarg_pd pd;
+ u8 cdb_length;
+ u8 sense_length;
+ u8 reserved[2];
+ u8 cdb[16];
+ u8 sense[64];
+ } __attribute__ ((packed)) cdbSense;
+
+ struct megasas_evtarg_ld ld;
+
+ struct {
+ struct megasas_evtarg_ld ld;
+ u64 count;
+ } __attribute__ ((packed)) ld_count;
+
+ struct {
+ u64 lba;
+ struct megasas_evtarg_ld ld;
+ } __attribute__ ((packed)) ld_lba;
+
+ struct {
+ struct megasas_evtarg_ld ld;
+ u32 prevOwner;
+ u32 newOwner;
+ } __attribute__ ((packed)) ld_owner;
+
+ struct {
+ u64 ld_lba;
+ u64 pd_lba;
+ struct megasas_evtarg_ld ld;
+ struct megasas_evtarg_pd pd;
+ } __attribute__ ((packed)) ld_lba_pd_lba;
+
+ struct {
+ struct megasas_evtarg_ld ld;
+ struct megasas_progress prog;
+ } __attribute__ ((packed)) ld_prog;
+
+ struct {
+ struct megasas_evtarg_ld ld;
+ u32 prev_state;
+ u32 new_state;
+ } __attribute__ ((packed)) ld_state;
+
+ struct {
+ u64 strip;
+ struct megasas_evtarg_ld ld;
+ } __attribute__ ((packed)) ld_strip;
+
+ struct megasas_evtarg_pd pd;
+
+ struct {
+ struct megasas_evtarg_pd pd;
+ u32 err;
+ } __attribute__ ((packed)) pd_err;
+
+ struct {
+ u64 lba;
+ struct megasas_evtarg_pd pd;
+ } __attribute__ ((packed)) pd_lba;
+
+ struct {
+ u64 lba;
+ struct megasas_evtarg_pd pd;
+ struct megasas_evtarg_ld ld;
+ } __attribute__ ((packed)) pd_lba_ld;
+
+ struct {
+ struct megasas_evtarg_pd pd;
+ struct megasas_progress prog;
+ } __attribute__ ((packed)) pd_prog;
+
+ struct {
+ struct megasas_evtarg_pd pd;
+ u32 prevState;
+ u32 newState;
+ } __attribute__ ((packed)) pd_state;
+
+ struct {
+ u16 vendorId;
+ u16 deviceId;
+ u16 subVendorId;
+ u16 subDeviceId;
+ } __attribute__ ((packed)) pci;
+
+ u32 rate;
+ char str[96];
+
+ struct {
+ u32 rtc;
+ u32 elapsedSeconds;
+ } __attribute__ ((packed)) time;
+
+ struct {
+ u32 ecar;
+ u32 elog;
+ char str[64];
+ } __attribute__ ((packed)) ecc;
+
+ u8 b[96];
+ u16 s[48];
+ u32 w[24];
+ u64 d[12];
+ } args;
+
+ char description[128];
+
+} __attribute__ ((packed));
+
+struct megasas_instance {
+
+ u32 *producer;
+ dma_addr_t producer_h;
+ u32 *consumer;
+ dma_addr_t consumer_h;
+
+ u32 *reply_queue;
+ dma_addr_t reply_queue_h;
+
+ unsigned long base_addr;
+ struct megasas_register_set __iomem *reg_set;
+
+ s8 init_id;
+ u8 reserved[3];
+
+ u16 max_num_sge;
+ u16 max_fw_cmds;
+ u32 max_sectors_per_req;
+
+ struct megasas_cmd **cmd_list;
+ struct list_head cmd_pool;
+ spinlock_t cmd_pool_lock;
+ struct dma_pool *frame_dma_pool;
+ struct dma_pool *sense_dma_pool;
+
+ struct megasas_evt_detail *evt_detail;
+ dma_addr_t evt_detail_h;
+ struct megasas_cmd *aen_cmd;
+ struct semaphore aen_mutex;
+ struct semaphore ioctl_sem;
+
+ struct Scsi_Host *host;
+
+ wait_queue_head_t int_cmd_wait_q;
+ wait_queue_head_t abort_cmd_wait_q;
+
+ struct pci_dev *pdev;
+ u32 unique_id;
+
+ u32 fw_outstanding;
+ u32 hw_crit_error;
+ spinlock_t instance_lock;
+};
+
+#define MEGASAS_IS_LOGICAL(scp) \
+ (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
+
+#define MEGASAS_DEV_INDEX(inst, scp) \
+ ((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
+ scp->device->id
+
+struct megasas_cmd {
+
+ union megasas_frame *frame;
+ dma_addr_t frame_phys_addr;
+ u8 *sense;
+ dma_addr_t sense_phys_addr;
+
+ u32 index;
+ u8 sync_cmd;
+ u8 cmd_status;
+ u16 abort_aen;
+
+ struct list_head list;
+ struct scsi_cmnd *scmd;
+ struct megasas_instance *instance;
+ u32 frame_count;
+};
+
+#define MAX_MGMT_ADAPTERS 1024
+#define MAX_IOCTL_SGE 16
+
+struct megasas_iocpacket {
+
+ u16 host_no;
+ u16 __pad1;
+ u32 sgl_off;
+ u32 sge_count;
+ u32 sense_off;
+ u32 sense_len;
+ union {
+ u8 raw[128];
+ struct megasas_header hdr;
+ } frame;
+
+ struct iovec sgl[MAX_IOCTL_SGE];
+
+} __attribute__ ((packed));
+
+struct megasas_aen {
+ u16 host_no;
+ u16 __pad1;
+ u32 seq_num;
+ u32 class_locale_word;
+} __attribute__ ((packed));
+
+#ifdef CONFIG_COMPAT
+struct compat_megasas_iocpacket {
+ u16 host_no;
+ u16 __pad1;
+ u32 sgl_off;
+ u32 sge_count;
+ u32 sense_off;
+ u32 sense_len;
+ union {
+ u8 raw[128];
+ struct megasas_header hdr;
+ } frame;
+ struct compat_iovec sgl[MAX_IOCTL_SGE];
+} __attribute__ ((packed));
+
+#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct compat_megasas_iocpacket)
+#else
+#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket)
+#endif
+
+#define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen)
+
+struct megasas_mgmt_info {
+
+ u16 count;
+ struct megasas_instance *instance[MAX_MGMT_ADAPTERS];
+ int max_index;
+};
+
+#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index ff1933298da6..bdccf73cf9fe 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -730,7 +730,7 @@ static void start_phase(struct mesh_state *ms)
* issue a SEQ_MSGOUT to get the mesh to drop ACK.
*/
if ((in_8(&mr->bus_status0) & BS0_ATN) == 0) {
- dlog(ms, "bus0 was %.2x explictly asserting ATN", mr->bus_status0);
+ dlog(ms, "bus0 was %.2x explicitly asserting ATN", mr->bus_status0);
out_8(&mr->bus_status0, BS0_ATN); /* explicit ATN */
mesh_flush_io(mr);
udelay(1);
@@ -1766,7 +1766,7 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t state)
struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
unsigned long flags;
- if (state == mdev->ofdev.dev.power.power_state || state < 2)
+ if (state.event == mdev->ofdev.dev.power.power_state.event || state.event < 2)
return 0;
scsi_block_requests(ms->host);
@@ -1791,7 +1791,7 @@ static int mesh_resume(struct macio_dev *mdev)
struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
unsigned long flags;
- if (mdev->ofdev.dev.power.power_state == 0)
+ if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
return 0;
set_mesh_power(ms, 1);
@@ -1802,7 +1802,7 @@ static int mesh_resume(struct macio_dev *mdev)
enable_irq(ms->meshintr);
scsi_unblock_requests(ms->host);
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
return 0;
}
@@ -1959,22 +1959,35 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
/* Set it up */
mesh_init(ms);
- /* XXX FIXME: error should be fatal */
- if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms))
+ /* Request interrupt */
+ if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms)) {
printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr);
+ goto out_shutdown;
+ }
- /* XXX FIXME: handle failure */
- scsi_add_host(mesh_host, &mdev->ofdev.dev);
+ /* Add scsi host & scan */
+ if (scsi_add_host(mesh_host, &mdev->ofdev.dev))
+ goto out_release_irq;
scsi_scan_host(mesh_host);
return 0;
-out_unmap:
+ out_release_irq:
+ free_irq(ms->meshintr, ms);
+ out_shutdown:
+ /* shutdown & reset bus in case of error or macos can be confused
+ * at reboot if the bus was set to synchronous mode already
+ */
+ mesh_shutdown(mdev);
+ set_mesh_power(ms, 0);
+ pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size,
+ ms->dma_cmd_space, ms->dma_cmd_bus);
+ out_unmap:
iounmap(ms->dma);
iounmap(ms->mesh);
-out_free:
+ out_free:
scsi_host_put(mesh_host);
-out_release:
+ out_release:
macio_release_resources(mdev);
return -ENODEV;
@@ -2001,7 +2014,7 @@ static int mesh_remove(struct macio_dev *mdev)
/* Free DMA commands memory */
pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size,
- ms->dma_cmd_space, ms->dma_cmd_bus);
+ ms->dma_cmd_space, ms->dma_cmd_bus);
/* Release memory resources */
macio_release_resources(mdev);
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 89a4a0615c22..172839fce0eb 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -1377,7 +1377,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
*aSRpnt = SRpnt;
return (-EIO);
}
@@ -1419,7 +1419,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
if (new_frame > frame + 1000) {
printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO);
}
if ( i >= nframes + pending ) break;
@@ -1500,7 +1500,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
SRpnt->sr_sense_buffer[12] == 0 &&
SRpnt->sr_sense_buffer[13] == 2) {
printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
- vfree((void *)buffer);
+ vfree(buffer);
return (-EIO); /* hit end of tape = fail */
}
i = ((SRpnt->sr_sense_buffer[3] << 24) |
@@ -1525,7 +1525,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
}
if (!pending)
osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
- vfree((void *)buffer);
+ vfree(buffer);
return 0;
}
@@ -5146,7 +5146,8 @@ static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned
/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
{
- int i, priority;
+ int i;
+ gfp_t priority;
struct osst_buffer *tb;
if (from_initialization)
@@ -5178,7 +5179,8 @@ static struct osst_buffer * new_tape_buffer( int from_initialization, int need_d
/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
{
- int segs, nbr, max_segs, b_size, priority, order, got;
+ int segs, nbr, max_segs, b_size, order, got;
+ gfp_t priority;
if (STbuffer->buffer_size >= OS_FRAME_SIZE)
return 1;
@@ -5627,7 +5629,7 @@ static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape *
if (!osst_sysfs_valid) return;
- osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
+ osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
if (IS_ERR(osst_class_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return;
@@ -5852,7 +5854,7 @@ static int osst_remove(struct device *dev)
os_scsi_tapes[i] = NULL;
osst_nr_dev--;
write_unlock(&os_scsi_tapes_lock);
- if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
+ vfree(tpnt->header_cache);
if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
@@ -5896,8 +5898,7 @@ static void __exit exit_osst (void)
for (i=0; i < osst_max_dev; ++i) {
if (!(STp = os_scsi_tapes[i])) continue;
/* This is defensive, supposed to happen during detach */
- if (STp->header_cache)
- vfree(STp->header_cache);
+ vfree(STp->header_cache);
if (STp->buffer) {
normalize_buffer(STp->buffer);
kfree(STp->buffer);
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
new file mode 100644
index 000000000000..665017eda8a6
--- /dev/null
+++ b/drivers/scsi/pdc_adma.c
@@ -0,0 +1,741 @@
+/*
+ * pdc_adma.c - Pacific Digital Corporation ADMA
+ *
+ * Maintained by: Mark Lord <mlord@pobox.com>
+ *
+ * Copyright 2005 Mark Lord
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ *
+ * Supports ATA disks in single-packet ADMA mode.
+ * Uses PIO for everything else.
+ *
+ * TODO: Use ADMA transfers for ATAPI devices, when possible.
+ * This requires careful attention to a number of quirks of the chip.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME "pdc_adma"
+#define DRV_VERSION "0.03"
+
+/* macro to calculate base address for ATA regs */
+#define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40))
+
+/* macro to calculate base address for ADMA regs */
+#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20))
+
+enum {
+ ADMA_PORTS = 2,
+ ADMA_CPB_BYTES = 40,
+ ADMA_PRD_BYTES = LIBATA_MAX_PRD * 16,
+ ADMA_PKT_BYTES = ADMA_CPB_BYTES + ADMA_PRD_BYTES,
+
+ ADMA_DMA_BOUNDARY = 0xffffffff,
+
+ /* global register offsets */
+ ADMA_MODE_LOCK = 0x00c7,
+
+ /* per-channel register offsets */
+ ADMA_CONTROL = 0x0000, /* ADMA control */
+ ADMA_STATUS = 0x0002, /* ADMA status */
+ ADMA_CPB_COUNT = 0x0004, /* CPB count */
+ ADMA_CPB_CURRENT = 0x000c, /* current CPB address */
+ ADMA_CPB_NEXT = 0x000c, /* next CPB address */
+ ADMA_CPB_LOOKUP = 0x0010, /* CPB lookup table */
+ ADMA_FIFO_IN = 0x0014, /* input FIFO threshold */
+ ADMA_FIFO_OUT = 0x0016, /* output FIFO threshold */
+
+ /* ADMA_CONTROL register bits */
+ aNIEN = (1 << 8), /* irq mask: 1==masked */
+ aGO = (1 << 7), /* packet trigger ("Go!") */
+ aRSTADM = (1 << 5), /* ADMA logic reset */
+ aPIOMD4 = 0x0003, /* PIO mode 4 */
+
+ /* ADMA_STATUS register bits */
+ aPSD = (1 << 6),
+ aUIRQ = (1 << 4),
+ aPERR = (1 << 0),
+
+ /* CPB bits */
+ cDONE = (1 << 0),
+ cVLD = (1 << 0),
+ cDAT = (1 << 2),
+ cIEN = (1 << 3),
+
+ /* PRD bits */
+ pORD = (1 << 4),
+ pDIRO = (1 << 5),
+ pEND = (1 << 7),
+
+ /* ATA register flags */
+ rIGN = (1 << 5),
+ rEND = (1 << 7),
+
+ /* ATA register addresses */
+ ADMA_REGS_CONTROL = 0x0e,
+ ADMA_REGS_SECTOR_COUNT = 0x12,
+ ADMA_REGS_LBA_LOW = 0x13,
+ ADMA_REGS_LBA_MID = 0x14,
+ ADMA_REGS_LBA_HIGH = 0x15,
+ ADMA_REGS_DEVICE = 0x16,
+ ADMA_REGS_COMMAND = 0x17,
+
+ /* PCI device IDs */
+ board_1841_idx = 0, /* ADMA 2-port controller */
+};
+
+typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
+
+struct adma_port_priv {
+ u8 *pkt;
+ dma_addr_t pkt_dma;
+ adma_state_t state;
+};
+
+static int adma_ata_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+static irqreturn_t adma_intr (int irq, void *dev_instance,
+ struct pt_regs *regs);
+static int adma_port_start(struct ata_port *ap);
+static void adma_host_stop(struct ata_host_set *host_set);
+static void adma_port_stop(struct ata_port *ap);
+static void adma_phy_reset(struct ata_port *ap);
+static void adma_qc_prep(struct ata_queued_cmd *qc);
+static int adma_qc_issue(struct ata_queued_cmd *qc);
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+static u8 adma_bmdma_status(struct ata_port *ap);
+static void adma_irq_clear(struct ata_port *ap);
+static void adma_eng_timeout(struct ata_port *ap);
+
+static Scsi_Host_Template adma_ata_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ENABLE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ADMA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+};
+
+static const struct ata_port_operations adma_ata_ops = {
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .check_atapi_dma = adma_check_atapi_dma,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+ .phy_reset = adma_phy_reset,
+ .qc_prep = adma_qc_prep,
+ .qc_issue = adma_qc_issue,
+ .eng_timeout = adma_eng_timeout,
+ .irq_handler = adma_intr,
+ .irq_clear = adma_irq_clear,
+ .port_start = adma_port_start,
+ .port_stop = adma_port_stop,
+ .host_stop = adma_host_stop,
+ .bmdma_stop = adma_bmdma_stop,
+ .bmdma_status = adma_bmdma_status,
+};
+
+static struct ata_port_info adma_port_info[] = {
+ /* board_1841_idx */
+ {
+ .sht = &adma_ata_sht,
+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+ ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
+ .pio_mask = 0x10, /* pio4 */
+ .udma_mask = 0x1f, /* udma0-4 */
+ .port_ops = &adma_ata_ops,
+ },
+};
+
+static struct pci_device_id adma_ata_pci_tbl[] = {
+ { PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_1841_idx },
+
+ { } /* terminate list */
+};
+
+static struct pci_driver adma_ata_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = adma_ata_pci_tbl,
+ .probe = adma_ata_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 1; /* ATAPI DMA not yet supported */
+}
+
+static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ /* nothing */
+}
+
+static u8 adma_bmdma_status(struct ata_port *ap)
+{
+ return 0;
+}
+
+static void adma_irq_clear(struct ata_port *ap)
+{
+ /* nothing */
+}
+
+static void adma_reset_engine(void __iomem *chan)
+{
+ /* reset ADMA to idle state */
+ writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+ udelay(2);
+ writew(aPIOMD4, chan + ADMA_CONTROL);
+ udelay(2);
+}
+
+static void adma_reinit_engine(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+ void __iomem *mmio_base = ap->host_set->mmio_base;
+ void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+
+ /* mask/clear ATA interrupts */
+ writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+ ata_check_status(ap);
+
+ /* reset the ADMA engine */
+ adma_reset_engine(chan);
+
+ /* set in-FIFO threshold to 0x100 */
+ writew(0x100, chan + ADMA_FIFO_IN);
+
+ /* set CPB pointer */
+ writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
+
+ /* set out-FIFO threshold to 0x100 */
+ writew(0x100, chan + ADMA_FIFO_OUT);
+
+ /* set CPB count */
+ writew(1, chan + ADMA_CPB_COUNT);
+
+ /* read/discard ADMA status */
+ readb(chan + ADMA_STATUS);
+}
+
+static inline void adma_enter_reg_mode(struct ata_port *ap)
+{
+ void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+ writew(aPIOMD4, chan + ADMA_CONTROL);
+ readb(chan + ADMA_STATUS); /* flush */
+}
+
+static void adma_phy_reset(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+
+ pp->state = adma_state_idle;
+ adma_reinit_engine(ap);
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
+}
+
+static void adma_eng_timeout(struct ata_port *ap)
+{
+ struct adma_port_priv *pp = ap->private_data;
+
+ if (pp->state != adma_state_idle) /* healthy paranoia */
+ pp->state = adma_state_mmio;
+ adma_reinit_engine(ap);
+ ata_eng_timeout(ap);
+}
+
+static int adma_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct scatterlist *sg = qc->sg;
+ struct ata_port *ap = qc->ap;
+ struct adma_port_priv *pp = ap->private_data;
+ u8 *buf = pp->pkt;
+ int nelem, i = (2 + buf[3]) * 8;
+ u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
+
+ for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
+ u32 addr;
+ u32 len;
+
+ addr = (u32)sg_dma_address(sg);
+ *(__le32 *)(buf + i) = cpu_to_le32(addr);
+ i += 4;
+
+ len = sg_dma_len(sg) >> 3;
+ *(__le32 *)(buf + i) = cpu_to_le32(len);
+ i += 4;
+
+ if ((nelem + 1) == qc->n_elem)
+ pFLAGS |= pEND;
+ buf[i++] = pFLAGS;
+ buf[i++] = qc->dev->dma_mode & 0xf;
+ buf[i++] = 0; /* pPKLW */
+ buf[i++] = 0; /* reserved */
+
+ *(__le32 *)(buf + i)
+ = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+ i += 4;
+
+ VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem,
+ (unsigned long)addr, len);
+ }
+ return i;
+}
+
+static void adma_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct adma_port_priv *pp = qc->ap->private_data;
+ u8 *buf = pp->pkt;
+ u32 pkt_dma = (u32)pp->pkt_dma;
+ int i = 0;
+
+ VPRINTK("ENTER\n");
+
+ adma_enter_reg_mode(qc->ap);
+ if (qc->tf.protocol != ATA_PROT_DMA) {
+ ata_qc_prep(qc);
+ return;
+ }
+
+ buf[i++] = 0; /* Response flags */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = cVLD | cDAT | cIEN;
+ i++; /* cLEN, gets filled in below */
+
+ *(__le32 *)(buf+i) = cpu_to_le32(pkt_dma); /* cNCPB */
+ i += 4; /* cNCPB */
+ i += 4; /* cPRD, gets filled in below */
+
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+ buf[i++] = 0; /* reserved */
+
+ /* ATA registers; must be a multiple of 4 */
+ buf[i++] = qc->tf.device;
+ buf[i++] = ADMA_REGS_DEVICE;
+ if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
+ buf[i++] = qc->tf.hob_nsect;
+ buf[i++] = ADMA_REGS_SECTOR_COUNT;
+ buf[i++] = qc->tf.hob_lbal;
+ buf[i++] = ADMA_REGS_LBA_LOW;
+ buf[i++] = qc->tf.hob_lbam;
+ buf[i++] = ADMA_REGS_LBA_MID;
+ buf[i++] = qc->tf.hob_lbah;
+ buf[i++] = ADMA_REGS_LBA_HIGH;
+ }
+ buf[i++] = qc->tf.nsect;
+ buf[i++] = ADMA_REGS_SECTOR_COUNT;
+ buf[i++] = qc->tf.lbal;
+ buf[i++] = ADMA_REGS_LBA_LOW;
+ buf[i++] = qc->tf.lbam;
+ buf[i++] = ADMA_REGS_LBA_MID;
+ buf[i++] = qc->tf.lbah;
+ buf[i++] = ADMA_REGS_LBA_HIGH;
+ buf[i++] = 0;
+ buf[i++] = ADMA_REGS_CONTROL;
+ buf[i++] = rIGN;
+ buf[i++] = 0;
+ buf[i++] = qc->tf.command;
+ buf[i++] = ADMA_REGS_COMMAND | rEND;
+
+ buf[3] = (i >> 3) - 2; /* cLEN */
+ *(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i); /* cPRD */
+
+ i = adma_fill_sg(qc);
+ wmb(); /* flush PRDs and pkt to memory */
+#if 0
+ /* dump out CPB + PRDs for debug */
+ {
+ int j, len = 0;
+ static char obuf[2048];
+ for (j = 0; j < i; ++j) {
+ len += sprintf(obuf+len, "%02x ", buf[j]);
+ if ((j & 7) == 7) {
+ printk("%s\n", obuf);
+ len = 0;
+ }
+ }
+ if (len)
+ printk("%s\n", obuf);
+ }
+#endif
+}
+
+static inline void adma_packet_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+ VPRINTK("ENTER, ap %p\n", ap);
+
+ /* fire up the ADMA engine */
+ writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
+}
+
+static int adma_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct adma_port_priv *pp = qc->ap->private_data;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ pp->state = adma_state_pkt;
+ adma_packet_start(qc);
+ return 0;
+
+ case ATA_PROT_ATAPI_DMA:
+ BUG();
+ break;
+
+ default:
+ break;
+ }
+
+ pp->state = adma_state_mmio;
+ return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0, port_no;
+ u8 __iomem *mmio_base = host_set->mmio_base;
+
+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+ struct ata_port *ap = host_set->ports[port_no];
+ struct adma_port_priv *pp;
+ struct ata_queued_cmd *qc;
+ void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+ u8 status = readb(chan + ADMA_STATUS);
+
+ if (status == 0)
+ continue;
+ handled = 1;
+ adma_enter_reg_mode(ap);
+ if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+ continue;
+ pp = ap->private_data;
+ if (!pp || pp->state != adma_state_pkt)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+ unsigned int err_mask = 0;
+
+ if ((status & (aPERR | aPSD | aUIRQ)))
+ err_mask = AC_ERR_OTHER;
+ else if (pp->pkt[0] != cDONE)
+ err_mask = AC_ERR_OTHER;
+
+ ata_qc_complete(qc, err_mask);
+ }
+ }
+ return handled;
+}
+
+static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0, port_no;
+
+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+ struct ata_port *ap;
+ ap = host_set->ports[port_no];
+ if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+ struct ata_queued_cmd *qc;
+ struct adma_port_priv *pp = ap->private_data;
+ if (!pp || pp->state != adma_state_mmio)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+
+ /* check main status, clearing INTRQ */
+ u8 status = ata_check_status(ap);
+ if ((status & ATA_BUSY))
+ continue;
+ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+ ap->id, qc->tf.protocol, status);
+
+ /* complete taskfile transaction */
+ pp->state = adma_state_idle;
+ ata_qc_complete(qc, ac_err_mask(status));
+ handled = 1;
+ }
+ }
+ }
+ return handled;
+}
+
+static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ unsigned int handled = 0;
+
+ VPRINTK("ENTER\n");
+
+ spin_lock(&host_set->lock);
+ handled = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
+ spin_unlock(&host_set->lock);
+
+ VPRINTK("EXIT\n");
+
+ return IRQ_RETVAL(handled);
+}
+
+static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+ port->cmd_addr =
+ port->data_addr = base + 0x000;
+ port->error_addr =
+ port->feature_addr = base + 0x004;
+ port->nsect_addr = base + 0x008;
+ port->lbal_addr = base + 0x00c;
+ port->lbam_addr = base + 0x010;
+ port->lbah_addr = base + 0x014;
+ port->device_addr = base + 0x018;
+ port->status_addr =
+ port->command_addr = base + 0x01c;
+ port->altstatus_addr =
+ port->ctl_addr = base + 0x038;
+}
+
+static int adma_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct adma_port_priv *pp;
+ int rc;
+
+ rc = ata_port_start(ap);
+ if (rc)
+ return rc;
+ adma_enter_reg_mode(ap);
+ rc = -ENOMEM;
+ pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ goto err_out;
+ pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+ GFP_KERNEL);
+ if (!pp->pkt)
+ goto err_out_kfree;
+ /* paranoia? */
+ if ((pp->pkt_dma & 7) != 0) {
+ printk("bad alignment for pp->pkt_dma: %08x\n",
+ (u32)pp->pkt_dma);
+ dma_free_coherent(dev, ADMA_PKT_BYTES,
+ pp->pkt, pp->pkt_dma);
+ goto err_out_kfree;
+ }
+ memset(pp->pkt, 0, ADMA_PKT_BYTES);
+ ap->private_data = pp;
+ adma_reinit_engine(ap);
+ return 0;
+
+err_out_kfree:
+ kfree(pp);
+err_out:
+ ata_port_stop(ap);
+ return rc;
+}
+
+static void adma_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct adma_port_priv *pp = ap->private_data;
+
+ adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
+ if (pp != NULL) {
+ ap->private_data = NULL;
+ if (pp->pkt != NULL)
+ dma_free_coherent(dev, ADMA_PKT_BYTES,
+ pp->pkt, pp->pkt_dma);
+ kfree(pp);
+ }
+ ata_port_stop(ap);
+}
+
+static void adma_host_stop(struct ata_host_set *host_set)
+{
+ unsigned int port_no;
+
+ for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+ adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
+
+ ata_pci_host_stop(host_set);
+}
+
+static void adma_host_init(unsigned int chip_id,
+ struct ata_probe_ent *probe_ent)
+{
+ unsigned int port_no;
+ void __iomem *mmio_base = probe_ent->mmio_base;
+
+ /* enable/lock aGO operation */
+ writeb(7, mmio_base + ADMA_MODE_LOCK);
+
+ /* reset the ADMA logic */
+ for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+ adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+}
+
+static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+ int rc;
+
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
+ return rc;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
+ return rc;
+ }
+ return 0;
+}
+
+static int adma_ata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int printed_version;
+ struct ata_probe_ent *probe_ent = NULL;
+ void __iomem *mmio_base;
+ unsigned int board_idx = (unsigned int) ent->driver_data;
+ int rc, port_no;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+
+ if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+ rc = -ENODEV;
+ goto err_out_regions;
+ }
+
+ mmio_base = pci_iomap(pdev, 4, 0);
+ if (mmio_base == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ rc = adma_set_dma_masks(pdev, mmio_base);
+ if (rc)
+ goto err_out_iounmap;
+
+ probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = adma_port_info[board_idx].sht;
+ probe_ent->host_flags = adma_port_info[board_idx].host_flags;
+ probe_ent->pio_mask = adma_port_info[board_idx].pio_mask;
+ probe_ent->mwdma_mask = adma_port_info[board_idx].mwdma_mask;
+ probe_ent->udma_mask = adma_port_info[board_idx].udma_mask;
+ probe_ent->port_ops = adma_port_info[board_idx].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = mmio_base;
+ probe_ent->n_ports = ADMA_PORTS;
+
+ for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+ adma_ata_setup_port(&probe_ent->port[port_no],
+ ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+ }
+
+ pci_set_master(pdev);
+
+ /* initialize adapter */
+ adma_host_init(board_idx, probe_ent);
+
+ rc = ata_device_add(probe_ent);
+ kfree(probe_ent);
+ if (rc != ADMA_PORTS)
+ goto err_out_iounmap;
+ return 0;
+
+err_out_iounmap:
+ pci_iounmap(pdev, mmio_base);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static int __init adma_ata_init(void)
+{
+ return pci_module_init(&adma_ata_pci_driver);
+}
+
+static void __exit adma_ata_exit(void)
+{
+ pci_unregister_driver(&adma_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(adma_ata_init);
+module_exit(adma_ata_exit);
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 623082d3a83f..c89da7d5b6df 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -95,8 +95,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
int i, retry, nplutos;
fc_channel *fc;
Scsi_Device dev;
- struct timer_list fc_timer =
- TIMER_INITIALIZER(pluto_detect_timeout, 0, 0);
+ DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
tpnt->proc_name = "pluto";
fcscount = 0;
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index b993652bfa25..637fb6565d28 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -996,7 +996,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
break;
case ABORT_DEVICE:
- ha->flags.in_reset = 1;
if (qla1280_verbose)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing abort device "
@@ -1010,7 +1009,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing device reset "
"command.\n", ha->host_no, bus, target, lun);
- ha->flags.in_reset = 1;
if (qla1280_device_reset(ha, bus, target) == 0)
result = SUCCESS;
break;
@@ -1019,7 +1017,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
if (qla1280_verbose)
printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS "
"DEVICE RESET\n", ha->host_no, bus);
- ha->flags.in_reset = 1;
if (qla1280_bus_reset(ha, bus == 0))
result = SUCCESS;
@@ -1047,7 +1044,6 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
if (!list_empty(&ha->done_q))
qla1280_done(ha);
- ha->flags.in_reset = 0;
/* If we didn't manage to issue the action, or we have no
* command to wait for, exit here */
@@ -1269,6 +1265,22 @@ qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
}
#endif
+
+/* disable risc and host interrupts */
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+ WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
+}
+
+/* enable risc and host interrupts */
+static inline void
+qla1280_enable_intrs(struct scsi_qla_host *ha)
+{
+ WRT_REG_WORD(&ha->iobase->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+ RD_REG_WORD(&ha->iobase->ictrl); /* PCI Posted Write flush */
+}
/**************************************************************************
* qla1280_intr_handler
@@ -1290,7 +1302,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
ha->isr_count++;
reg = ha->iobase;
- WRT_REG_WORD(&reg->ictrl, 0); /* disable our interrupt. */
+ qla1280_disable_intrs(ha);
data = qla1280_debounce_register(&reg->istatus);
/* Check for pending interrupts. */
@@ -1303,8 +1315,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(HOST_LOCK);
- /* enable our interrupt. */
- WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+ qla1280_enable_intrs(ha);
LEAVE_INTR("qla1280_intr_handler");
return IRQ_RETVAL(handled);
@@ -1317,7 +1328,7 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
uint8_t mr;
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct nvram *nv;
- int status;
+ int status, lun;
nv = &ha->nvram;
@@ -1325,24 +1336,38 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
/* Set Target Parameters. */
mb[0] = MBC_SET_TARGET_PARAMETERS;
- mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
- mb[1] <<= 8;
-
- mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[2] = nv->bus[bus].target[target].parameter.renegotiate_on_error << 8;
+ mb[2] |= nv->bus[bus].target[target].parameter.stop_queue_on_check << 9;
+ mb[2] |= nv->bus[bus].target[target].parameter.auto_request_sense << 10;
+ mb[2] |= nv->bus[bus].target[target].parameter.tag_queuing << 11;
+ mb[2] |= nv->bus[bus].target[target].parameter.enable_sync << 12;
+ mb[2] |= nv->bus[bus].target[target].parameter.enable_wide << 13;
+ mb[2] |= nv->bus[bus].target[target].parameter.parity_checking << 14;
+ mb[2] |= nv->bus[bus].target[target].parameter.disconnect_allowed << 15;
if (IS_ISP1x160(ha)) {
mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
- mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
- nv->bus[bus].target[target].sync_period;
+ mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8);
mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
mr |= BIT_6;
} else {
- mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
- nv->bus[bus].target[target].sync_period;
+ mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8);
}
+ mb[3] |= nv->bus[bus].target[target].sync_period;
- status = qla1280_mailbox_command(ha, mr, &mb[0]);
+ status = qla1280_mailbox_command(ha, mr, mb);
+
+ /* Set Device Queue Parameters. */
+ for (lun = 0; lun < MAX_LUNS; lun++) {
+ mb[0] = MBC_SET_DEVICE_QUEUE;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[1] |= lun;
+ mb[2] = nv->bus[bus].max_queue_depth;
+ mb[3] = nv->bus[bus].target[target].execution_throttle;
+ status |= qla1280_mailbox_command(ha, 0x0f, mb);
+ }
if (status)
printk(KERN_WARNING "scsi(%ld:%i:%i): "
@@ -1389,19 +1414,19 @@ qla1280_slave_configure(struct scsi_device *device)
}
#if LINUX_VERSION_CODE > 0x020500
- nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr;
- nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr;
+ nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
+ nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;
nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;
#endif
if (driver_setup.no_sync ||
(driver_setup.sync_mask &&
(~driver_setup.sync_mask & (1 << target))))
- nv->bus[bus].target[target].parameter.f.enable_sync = 0;
+ nv->bus[bus].target[target].parameter.enable_sync = 0;
if (driver_setup.no_wide ||
(driver_setup.wide_mask &&
(~driver_setup.wide_mask & (1 << target))))
- nv->bus[bus].target[target].parameter.f.enable_wide = 0;
+ nv->bus[bus].target[target].parameter.enable_wide = 0;
if (IS_ISP1x160(ha)) {
if (driver_setup.no_ppr ||
(driver_setup.ppr_mask &&
@@ -1410,7 +1435,7 @@ qla1280_slave_configure(struct scsi_device *device)
}
spin_lock_irqsave(HOST_LOCK, flags);
- if (nv->bus[bus].target[target].parameter.f.enable_sync)
+ if (nv->bus[bus].target[target].parameter.enable_sync)
status = qla1280_set_target_parameters(ha, bus, target);
qla1280_get_target_parameters(ha, device);
spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1448,7 +1473,6 @@ qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q)
*
* Input:
* ha = adapter block pointer.
- * done_q = done queue.
*/
static void
qla1280_done(struct scsi_qla_host *ha)
@@ -1522,7 +1546,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
int host_status = DID_ERROR;
uint16_t comp_status = le16_to_cpu(sts->comp_status);
uint16_t state_flags = le16_to_cpu(sts->state_flags);
- uint16_t residual_length = le16_to_cpu(sts->residual_length);
+ uint16_t residual_length = le32_to_cpu(sts->residual_length);
uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
#if DEBUG_QLA1280_INTR
static char *reason[] = {
@@ -1582,7 +1606,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
case CS_DATA_OVERRUN:
dprintk(2, "Data overrun 0x%x\n", residual_length);
- dprintk(2, "qla1280_isr: response packet data\n");
+ dprintk(2, "qla1280_return_status: response packet data\n");
qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
host_status = DID_ERROR;
break;
@@ -1617,40 +1641,6 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
/* QLogic ISP1280 Hardware Support Functions. */
/****************************************************************************/
- /*
- * qla2100_enable_intrs
- * qla2100_disable_intrs
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * None
- */
-static inline void
-qla1280_enable_intrs(struct scsi_qla_host *ha)
-{
- struct device_reg __iomem *reg;
-
- reg = ha->iobase;
- /* enable risc and host interrupts */
- WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
- RD_REG_WORD(&reg->ictrl); /* PCI Posted Write flush */
- ha->flags.ints_enabled = 1;
-}
-
-static inline void
-qla1280_disable_intrs(struct scsi_qla_host *ha)
-{
- struct device_reg __iomem *reg;
-
- reg = ha->iobase;
- /* disable risc and host interrupts */
- WRT_REG_WORD(&reg->ictrl, 0);
- RD_REG_WORD(&reg->ictrl); /* PCI Posted Write flush */
- ha->flags.ints_enabled = 0;
-}
-
/*
* qla1280_initialize_adapter
* Initialize board.
@@ -1679,7 +1669,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
ha->flags.reset_active = 0;
ha->flags.abort_isp_active = 0;
- ha->flags.ints_enabled = 0;
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ia64_platform_is("sn2")) {
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
@@ -1758,69 +1747,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
return status;
}
-
-/*
- * ISP Firmware Test
- * Checks if present version of RISC firmware is older than
- * driver firmware.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * 0 = firmware does not need to be loaded.
- */
-static int
-qla1280_isp_firmware(struct scsi_qla_host *ha)
-{
- struct nvram *nv = (struct nvram *) ha->response_ring;
- int status = 0; /* dg 2/27 always loads RISC */
- uint16_t mb[MAILBOX_REGISTER_COUNT];
-
- ENTER("qla1280_isp_firmware");
-
- dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no);
-
- /* Bad NVRAM data, load RISC code. */
- if (!ha->nvram_valid) {
- ha->flags.disable_risc_code_load = 0;
- } else
- ha->flags.disable_risc_code_load =
- nv->cntr_flags_1.disable_loading_risc_code;
-
- if (ha->flags.disable_risc_code_load) {
- dprintk(3, "qla1280_isp_firmware: Telling RISC to verify "
- "checksum of loaded BIOS code.\n");
-
- /* Verify checksum of loaded RISC code. */
- mb[0] = MBC_VERIFY_CHECKSUM;
- /* mb[1] = ql12_risc_code_addr01; */
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-
- if (!(status =
- qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
- /* Start firmware execution. */
- dprintk(3, "qla1280_isp_firmware: Startng F/W "
- "execution.\n");
-
- mb[0] = MBC_EXECUTE_FIRMWARE;
- /* mb[1] = ql12_risc_code_addr01; */
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
- qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
- } else
- printk(KERN_INFO "qla1280: RISC checksum failed.\n");
- } else {
- dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
- status = 1;
- }
-
- if (status)
- dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
-
- LEAVE("qla1280_isp_firmware");
- return status;
-}
-
/*
* Chip diagnostics
* Test chip for proper operation.
@@ -2006,7 +1932,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
"%d,%d(0x%x)\n",
risc_code_address, cnt, num, risc_address);
for(i = 0; i < cnt; i++)
- ((uint16_t *)ha->request_ring)[i] =
+ ((__le16 *)ha->request_ring)[i] =
cpu_to_le16(risc_code_address[i]);
mb[0] = MBC_LOAD_RAM;
@@ -2085,7 +2011,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
if (err) {
- printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+ printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
return err;
}
@@ -2105,14 +2031,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
static int
qla1280_load_firmware(struct scsi_qla_host *ha)
{
- int err = -ENODEV;
-
- /* If firmware needs to be loaded */
- if (!qla1280_isp_firmware(ha)) {
- printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
- ha->host_no);
- goto out;
- }
+ int err;
err = qla1280_chip_diag(ha);
if (err)
@@ -2246,17 +2165,17 @@ qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
{
struct nvram *nv = &ha->nvram;
- nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
- nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
- nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
- nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+ nv->bus[bus].target[target].parameter.renegotiate_on_error = 1;
+ nv->bus[bus].target[target].parameter.auto_request_sense = 1;
+ nv->bus[bus].target[target].parameter.tag_queuing = 1;
+ nv->bus[bus].target[target].parameter.enable_sync = 1;
#if 1 /* Some SCSI Processors do not seem to like this */
- nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+ nv->bus[bus].target[target].parameter.enable_wide = 1;
#endif
- nv->bus[bus].target[target].parameter.f.parity_checking = 1;
- nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
nv->bus[bus].target[target].execution_throttle =
nv->bus[bus].max_queue_depth - 1;
+ nv->bus[bus].target[target].parameter.parity_checking = 1;
+ nv->bus[bus].target[target].parameter.disconnect_allowed = 1;
if (IS_ISP1x160(ha)) {
nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
@@ -2284,9 +2203,9 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
nv->firmware_feature.f.enable_fast_posting = 1;
nv->firmware_feature.f.disable_synchronous_backoff = 1;
- nv->termination.f.scsi_bus_0_control = 3;
- nv->termination.f.scsi_bus_1_control = 3;
- nv->termination.f.auto_term_support = 1;
+ nv->termination.scsi_bus_0_control = 3;
+ nv->termination.scsi_bus_1_control = 3;
+ nv->termination.auto_term_support = 1;
/*
* Set default FIFO magic - What appropriate values would be here
@@ -2296,7 +2215,12 @@ qla1280_set_defaults(struct scsi_qla_host *ha)
* header file provided by QLogic seems to be bogus or incomplete
* at best.
*/
- nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+ nv->isp_config.burst_enable = 1;
+ if (IS_ISP1040(ha))
+ nv->isp_config.fifo_threshold |= 3;
+ else
+ nv->isp_config.fifo_threshold |= 4;
+
if (IS_ISP1x160(ha))
nv->isp_parameter = 0x01; /* fast memory enable */
@@ -2327,66 +2251,53 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
struct nvram *nv = &ha->nvram;
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status, lun;
+ uint16_t flag;
/* Set Target Parameters. */
mb[0] = MBC_SET_TARGET_PARAMETERS;
- mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
- mb[1] <<= 8;
-
- /*
- * Do not enable wide, sync, and ppr for the initial
- * INQUIRY run. We enable this later if we determine
- * the target actually supports it.
- */
- nv->bus[bus].target[target].parameter.f.
- auto_request_sense = 1;
- nv->bus[bus].target[target].parameter.f.
- stop_queue_on_check = 0;
-
- if (IS_ISP1x160(ha))
- nv->bus[bus].target[target].ppr_1x160.
- flags.enable_ppr = 0;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
/*
- * No sync, wide, etc. while probing
+ * Do not enable sync and ppr for the initial INQUIRY run. We
+ * enable this later if we determine the target actually
+ * supports it.
*/
- mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
- ~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+ mb[2] = (TP_RENEGOTIATE | TP_AUTO_REQUEST_SENSE | TP_TAGGED_QUEUE
+ | TP_WIDE | TP_PARITY | TP_DISCONNECT);
if (IS_ISP1x160(ha))
mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
else
mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
mb[3] |= nv->bus[bus].target[target].sync_period;
-
- status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status = qla1280_mailbox_command(ha, 0x0f, mb);
/* Save Tag queuing enable flag. */
- mb[0] = BIT_0 << target;
- if (nv->bus[bus].target[target].parameter.f.tag_queuing)
- ha->bus_settings[bus].qtag_enables |= mb[0];
+ flag = (BIT_0 << target) & mb[0];
+ if (nv->bus[bus].target[target].parameter.tag_queuing)
+ ha->bus_settings[bus].qtag_enables |= flag;
/* Save Device enable flag. */
if (IS_ISP1x160(ha)) {
if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
- ha->bus_settings[bus].device_enables |= mb[0];
+ ha->bus_settings[bus].device_enables |= flag;
ha->bus_settings[bus].lun_disables |= 0;
} else {
if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
- ha->bus_settings[bus].device_enables |= mb[0];
+ ha->bus_settings[bus].device_enables |= flag;
/* Save LUN disable flag. */
if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
- ha->bus_settings[bus].lun_disables |= mb[0];
+ ha->bus_settings[bus].lun_disables |= flag;
}
/* Set Device Queue Parameters. */
for (lun = 0; lun < MAX_LUNS; lun++) {
mb[0] = MBC_SET_DEVICE_QUEUE;
- mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
- mb[1] = mb[1] << 8 | lun;
+ mb[1] = (uint16_t)((bus ? target | BIT_7 : target) << 8);
+ mb[1] |= lun;
mb[2] = nv->bus[bus].max_queue_depth;
mb[3] = nv->bus[bus].target[target].execution_throttle;
- status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+ status |= qla1280_mailbox_command(ha, 0x0f, mb);
}
return status;
@@ -2431,7 +2342,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
struct nvram *nv = &ha->nvram;
int bus, target, status = 0;
uint16_t mb[MAILBOX_REGISTER_COUNT];
- uint16_t mask;
ENTER("qla1280_nvram_config");
@@ -2439,7 +2349,7 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
/* Always force AUTO sense for LINUX SCSI */
for (bus = 0; bus < MAX_BUSES; bus++)
for (target = 0; target < MAX_TARGETS; target++) {
- nv->bus[bus].target[target].parameter.f.
+ nv->bus[bus].target[target].parameter.
auto_request_sense = 1;
}
} else {
@@ -2457,31 +2367,40 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
- cfg1 = RD_REG_WORD(&reg->cfg_1);
+ cfg1 = RD_REG_WORD(&reg->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6);
cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
/* Busted fifo, says mjacob. */
- if (hwrev == ISP_CFG0_1040A)
- WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
- else
- WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+ if (hwrev != ISP_CFG0_1040A)
+ cfg1 |= nv->isp_config.fifo_threshold << 4;
+
+ cfg1 |= nv->isp_config.burst_enable << 2;
+ WRT_REG_WORD(&reg->cfg_1, cfg1);
WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
} else {
+ uint16_t cfg1, term;
+
/* Set ISP hardware DMA burst */
- mb[0] = nv->isp_config.c;
+ cfg1 = nv->isp_config.fifo_threshold << 4;
+ cfg1 |= nv->isp_config.burst_enable << 2;
/* Enable DMA arbitration on dual channel controllers */
if (ha->ports > 1)
- mb[0] |= BIT_13;
- WRT_REG_WORD(&reg->cfg_1, mb[0]);
+ cfg1 |= BIT_13;
+ WRT_REG_WORD(&reg->cfg_1, cfg1);
/* Set SCSI termination. */
- WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
- mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
- WRT_REG_WORD(&reg->gpio_data, mb[0]);
+ WRT_REG_WORD(&reg->gpio_enable,
+ BIT_7 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
+ term = nv->termination.scsi_bus_1_control;
+ term |= nv->termination.scsi_bus_0_control << 2;
+ term |= nv->termination.auto_term_support << 7;
+ RD_REG_WORD(&reg->id_l); /* Flush PCI write */
+ WRT_REG_WORD(&reg->gpio_data, term);
}
+ RD_REG_WORD(&reg->id_l); /* Flush PCI write */
/* ISP parameter word. */
mb[0] = MBC_SET_SYSTEM_PARAMETER;
@@ -2497,16 +2416,17 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
/* Firmware feature word. */
mb[0] = MBC_SET_FIRMWARE_FEATURES;
- mask = BIT_5 | BIT_1 | BIT_0;
- mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask);
+ mb[1] = nv->firmware_feature.f.enable_fast_posting;
+ mb[1] |= nv->firmware_feature.f.report_lvd_bus_transition << 1;
+ mb[1] |= nv->firmware_feature.f.disable_synchronous_backoff << 5;
#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2)
if (ia64_platform_is("sn2")) {
printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "
"workaround\n", ha->host_no);
- mb[1] |= BIT_9;
+ mb[1] |= nv->firmware_feature.f.unused_9 << 9; /* XXX */
}
#endif
- status |= qla1280_mailbox_command(ha, mask, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* Retry count and delay. */
mb[0] = MBC_SET_RETRY_COUNT;
@@ -2535,27 +2455,27 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
mb[2] |= BIT_5;
if (nv->bus[1].config_2.data_line_active_negation)
mb[2] |= BIT_4;
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY;
mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */
- status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* thingy */
mb[0] = MBC_SET_PCI_CONTROL;
- mb[1] = 2; /* Data DMA Channel Burst Enable */
- mb[2] = 2; /* Command DMA Channel Burst Enable */
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ mb[1] = BIT_1; /* Data DMA Channel Burst Enable */
+ mb[2] = BIT_1; /* Command DMA Channel Burst Enable */
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
mb[0] = MBC_SET_TAG_AGE_LIMIT;
mb[1] = 8;
- status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
/* Selection timeout. */
mb[0] = MBC_SET_SELECTION_TIMEOUT;
mb[1] = nv->bus[0].selection_timeout;
mb[2] = nv->bus[1].selection_timeout;
- status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, mb);
for (bus = 0; bus < ha->ports; bus++)
status |= qla1280_config_bus(ha, bus);
@@ -3066,7 +2986,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct scsi_cmnd *cmd = sp->cmd;
cmd_a64_entry_t *pkt;
struct scatterlist *sg = NULL;
- u32 *dword_ptr;
+ __le32 *dword_ptr;
dma_addr_t dma_handle;
int status = 0;
int cnt;
@@ -3104,10 +3024,13 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
}
+ dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n",
+ ha->req_q_cnt, seg_cnt);
+
/* If room for request in request ring. */
if ((req_cnt + 2) >= ha->req_q_cnt) {
status = 1;
- dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt="
+ dprintk(2, "qla1280_start_scsi: in-ptr=0x%x req_q_cnt="
"0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
req_cnt);
goto out;
@@ -3119,7 +3042,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
if (cnt >= MAX_OUTSTANDING_COMMANDS) {
status = 1;
- dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
+ dprintk(2, "qla1280_start_scsi: NO ROOM IN "
"OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt);
goto out;
}
@@ -3128,7 +3051,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
ha->req_q_cnt -= req_cnt;
CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1);
- dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
+ dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd));
dprintk(2, " bus %i, target %i, lun %i\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
@@ -3350,7 +3273,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
struct scsi_cmnd *cmd = sp->cmd;
struct cmd_entry *pkt;
struct scatterlist *sg = NULL;
- uint32_t *dword_ptr;
+ __le32 *dword_ptr;
int status = 0;
int cnt;
int req_cnt;
@@ -3993,21 +3916,21 @@ qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha)
result = cmd->request_buffer;
n = &ha->nvram;
- n->bus[bus].target[target].parameter.f.enable_wide = 0;
- n->bus[bus].target[target].parameter.f.enable_sync = 0;
+ n->bus[bus].target[target].parameter.enable_wide = 0;
+ n->bus[bus].target[target].parameter.enable_sync = 0;
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
if (result[7] & 0x60)
- n->bus[bus].target[target].parameter.f.enable_wide = 1;
+ n->bus[bus].target[target].parameter.enable_wide = 1;
if (result[7] & 0x10)
- n->bus[bus].target[target].parameter.f.enable_sync = 1;
+ n->bus[bus].target[target].parameter.enable_sync = 1;
if ((result[2] >= 3) && (result[4] + 5 > 56) &&
(result[56] & 0x4))
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n",
- n->bus[bus].target[target].parameter.f.enable_wide,
- n->bus[bus].target[target].parameter.f.enable_sync,
+ n->bus[bus].target[target].parameter.enable_wide,
+ n->bus[bus].target[target].parameter.enable_sync,
n->bus[bus].target[target].ppr_1x160.flags.enable_ppr);
}
#endif
@@ -4071,7 +3994,7 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
/* Save ISP completion status */
CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
- if (scsi_status & SS_CHECK_CONDITION) {
+ if (scsi_status & SAM_STAT_CHECK_CONDITION) {
if (comp_status != CS_ARS_FAILED) {
uint16_t req_sense_length =
le16_to_cpu(pkt->req_sense_length);
@@ -4650,7 +4573,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
- " suitable DMA mask - aboring\n", ha->host_no);
+ "suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
goto error_free_irq;
}
@@ -4660,14 +4583,14 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#else
if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
- " suitable DMA mask - aboring\n", ha->host_no);
+ "suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
goto error_free_irq;
}
#endif
ha->request_ring = pci_alloc_consistent(ha->pdev,
- ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+ ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
&ha->request_dma);
if (!ha->request_ring) {
printk(KERN_INFO "qla1280: Failed to get request memory\n");
@@ -4675,7 +4598,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
ha->response_ring = pci_alloc_consistent(ha->pdev,
- ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+ ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
&ha->response_dma);
if (!ha->response_ring) {
printk(KERN_INFO "qla1280: Failed to get response memory\n");
@@ -4758,7 +4681,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#if LINUX_VERSION_CODE >= 0x020600
error_disable_adapter:
- WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ qla1280_disable_intrs(ha);
#endif
error_free_irq:
free_irq(pdev->irq, ha);
@@ -4770,11 +4693,11 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#endif
error_free_response_ring:
pci_free_consistent(ha->pdev,
- ((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),
+ ((RESPONSE_ENTRY_CNT + 1) * sizeof(struct response)),
ha->response_ring, ha->response_dma);
error_free_request_ring:
pci_free_consistent(ha->pdev,
- ((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
+ ((REQUEST_ENTRY_CNT + 1) * sizeof(request_t)),
ha->request_ring, ha->request_dma);
error_put_host:
scsi_host_put(host);
@@ -4795,7 +4718,7 @@ qla1280_remove_one(struct pci_dev *pdev)
scsi_remove_host(host);
#endif
- WRT_REG_WORD(&ha->iobase->ictrl, 0);
+ qla1280_disable_intrs(ha);
free_irq(pdev->irq, ha);
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index d245ae07518e..59915fb70301 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -94,9 +94,6 @@
#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */
-/* Number of segments 1 - 65535 */
-#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */
-
/*
* SCSI Request Block structure (sp) that is placed
* on cmd->SCp location of every I/O
@@ -378,29 +375,23 @@ struct nvram {
uint16_t unused_12; /* 12, 13 */
uint16_t unused_14; /* 14, 15 */
- union {
- uint8_t c;
- struct {
- uint8_t reserved:2;
- uint8_t burst_enable:1;
- uint8_t reserved_1:1;
- uint8_t fifo_threshold:4;
- } f;
+ struct {
+ uint8_t reserved:2;
+ uint8_t burst_enable:1;
+ uint8_t reserved_1:1;
+ uint8_t fifo_threshold:4;
} isp_config; /* 16 */
/* Termination
* 0 = Disable, 1 = high only, 3 = Auto term
*/
- union {
- uint8_t c;
- struct {
- uint8_t scsi_bus_1_control:2;
- uint8_t scsi_bus_0_control:2;
- uint8_t unused_0:1;
- uint8_t unused_1:1;
- uint8_t unused_2:1;
- uint8_t auto_term_support:1;
- } f;
+ struct {
+ uint8_t scsi_bus_1_control:2;
+ uint8_t scsi_bus_0_control:2;
+ uint8_t unused_0:1;
+ uint8_t unused_1:1;
+ uint8_t unused_2:1;
+ uint8_t auto_term_support:1;
} termination; /* 17 */
uint16_t isp_parameter; /* 18, 19 */
@@ -460,18 +451,15 @@ struct nvram {
uint16_t unused_38; /* 38, 39 */
struct {
- union {
- uint8_t c;
- struct {
- uint8_t renegotiate_on_error:1;
- uint8_t stop_queue_on_check:1;
- uint8_t auto_request_sense:1;
- uint8_t tag_queuing:1;
- uint8_t enable_sync:1;
- uint8_t enable_wide:1;
- uint8_t parity_checking:1;
- uint8_t disconnect_allowed:1;
- } f;
+ struct {
+ uint8_t renegotiate_on_error:1;
+ uint8_t stop_queue_on_check:1;
+ uint8_t auto_request_sense:1;
+ uint8_t tag_queuing:1;
+ uint8_t enable_sync:1;
+ uint8_t enable_wide:1;
+ uint8_t parity_checking:1;
+ uint8_t disconnect_allowed:1;
} parameter; /* 40 */
uint8_t execution_throttle; /* 41 */
@@ -528,23 +516,23 @@ struct cmd_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t handle; /* System handle. */
+ __le32 handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
};
/*
@@ -556,21 +544,21 @@ struct cont_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved; /* Reserved */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
- uint32_t dseg_5_address; /* Data segment 5 address. */
- uint32_t dseg_5_length; /* Data segment 5 length. */
- uint32_t dseg_6_address; /* Data segment 6 address. */
- uint32_t dseg_6_length; /* Data segment 6 length. */
+ __le32 reserved; /* Reserved */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_4_address; /* Data segment 4 address. */
+ __le32 dseg_4_length; /* Data segment 4 length. */
+ __le32 dseg_5_address; /* Data segment 5 address. */
+ __le32 dseg_5_length; /* Data segment 5 length. */
+ __le32 dseg_6_address; /* Data segment 6 address. */
+ __le32 dseg_6_length; /* Data segment 6 length. */
};
/*
@@ -586,22 +574,22 @@ struct response {
#define RF_FULL BIT_1 /* Full */
#define RF_BAD_HEADER BIT_2 /* Bad header. */
#define RF_BAD_PAYLOAD BIT_3 /* Bad payload. */
- uint32_t handle; /* System handle. */
- uint16_t scsi_status; /* SCSI status. */
- uint16_t comp_status; /* Completion status. */
- uint16_t state_flags; /* State flags. */
-#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */
-#define SF_GOT_SENSE BIT_13 /* Got Sense */
-#define SF_GOT_STATUS BIT_12 /* Got Status */
-#define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */
-#define SF_SENT_CDB BIT_10 /* Send CDB */
-#define SF_GOT_TARGET BIT_9 /* */
-#define SF_GOT_BUS BIT_8 /* */
- uint16_t status_flags; /* Status flags. */
- uint16_t time; /* Time. */
- uint16_t req_sense_length; /* Request sense data length. */
- uint32_t residual_length; /* Residual transfer length. */
- uint16_t reserved[4];
+ __le32 handle; /* System handle. */
+ __le16 scsi_status; /* SCSI status. */
+ __le16 comp_status; /* Completion status. */
+ __le16 state_flags; /* State flags. */
+#define SF_TRANSFER_CMPL BIT_14 /* Transfer Complete. */
+#define SF_GOT_SENSE BIT_13 /* Got Sense */
+#define SF_GOT_STATUS BIT_12 /* Got Status */
+#define SF_TRANSFERRED_DATA BIT_11 /* Transferred data */
+#define SF_SENT_CDB BIT_10 /* Send CDB */
+#define SF_GOT_TARGET BIT_9 /* */
+#define SF_GOT_BUS BIT_8 /* */
+ __le16 status_flags; /* Status flags. */
+ __le16 time; /* Time. */
+ __le16 req_sense_length;/* Request sense data length. */
+ __le32 residual_length; /* Residual transfer length. */
+ __le16 reserved[4];
uint8_t req_sense_data[32]; /* Request sense data. */
};
@@ -614,7 +602,7 @@ struct mrk_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved;
+ __le32 reserved;
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
uint8_t modifier; /* Modifier (7-0). */
@@ -638,11 +626,11 @@ struct ecmd_entry {
uint32_t handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[88]; /* SCSI command words. */
};
@@ -655,20 +643,20 @@ typedef struct {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t handle; /* System handle. */
+ __le32 handle; /* System handle. */
uint8_t lun; /* SCSI LUN */
uint8_t target; /* SCSI ID */
- uint16_t cdb_len; /* SCSI command length. */
- uint16_t control_flags; /* Control flags. */
- uint16_t reserved;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 cdb_len; /* SCSI command length. */
+ __le16 control_flags; /* Control flags. */
+ __le16 reserved;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t reserved_1[2]; /* unused */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
+ __le32 reserved_1[2]; /* unused */
+ __le32 dseg_0_address[2]; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2]; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
} cmd_a64_entry_t, request_t;
/*
@@ -680,16 +668,16 @@ struct cont_a64_entry {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address[2]; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address[2]; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address[2]; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
+ __le32 dseg_0_address[2]; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2]; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address[2]; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address[2]; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
+ __le32 dseg_4_address[2]; /* Data segment 4 address. */
+ __le32 dseg_4_length; /* Data segment 4 length. */
};
/*
@@ -701,10 +689,10 @@ struct elun_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status not used. */
- uint32_t reserved_2;
- uint16_t lun; /* Bit 15 is bus number. */
- uint16_t reserved_4;
- uint32_t option_flags;
+ __le32 reserved_2;
+ __le16 lun; /* Bit 15 is bus number. */
+ __le16 reserved_4;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_5;
uint8_t command_count; /* Number of ATIOs allocated. */
@@ -714,8 +702,8 @@ struct elun_entry {
/* commands (2-26). */
uint8_t group_7_length; /* SCSI CDB length for group 7 */
/* commands (2-26). */
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t reserved_6[20];
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 reserved_6[20];
};
/*
@@ -729,20 +717,20 @@ struct modify_lun_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t reserved_3;
uint8_t operators;
uint8_t reserved_4;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_5;
uint8_t command_count; /* Number of ATIOs allocated. */
uint8_t immed_notify_count; /* Number of Immediate Notify */
/* entries allocated. */
- uint16_t reserved_6;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t reserved_7[20];
+ __le16 reserved_6;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 reserved_7[20];
};
/*
@@ -754,20 +742,20 @@ struct notify_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t reserved_4;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
/* entries allocated. */
- uint16_t seq_id;
+ __le16 seq_id;
uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */
- uint16_t reserved_5[8];
+ __le16 reserved_5[8];
uint8_t sense_data[18];
};
@@ -780,16 +768,16 @@ struct nack_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t event;
- uint16_t seq_id;
- uint16_t reserved_4[22];
+ __le16 seq_id;
+ __le16 reserved_4[22];
};
/*
@@ -801,12 +789,12 @@ struct atio_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun;
uint8_t initiator_id;
uint8_t cdb_len;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
@@ -824,28 +812,28 @@ struct ctio_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
+ __le32 dseg_2_address; /* Data segment 2 address. */
+ __le32 dseg_2_length; /* Data segment 2 length. */
+ __le32 dseg_3_address; /* Data segment 3 address. */
+ __le32 dseg_3_length; /* Data segment 3 length. */
};
/*
@@ -857,24 +845,24 @@ struct ctio_ret_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint16_t dseg_1_length; /* Data segment 1 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 dseg_0_address; /* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address; /* Data segment 1 address. */
+ __le16 dseg_1_length; /* Data segment 1 length. */
uint8_t sense_data[18];
};
@@ -887,25 +875,25 @@ struct ctio_a64_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t reserved_4[2];
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 reserved_4[2];
+ __le32 dseg_0_address[2];/* Data segment 0 address. */
+ __le32 dseg_0_length; /* Data segment 0 length. */
+ __le32 dseg_1_address[2];/* Data segment 1 address. */
+ __le32 dseg_1_length; /* Data segment 1 length. */
};
/*
@@ -917,21 +905,21 @@ struct ctio_a64_ret_entry {
uint8_t entry_count; /* Entry count. */
uint8_t reserved_1;
uint8_t entry_status; /* Entry Status. */
- uint32_t reserved_2;
+ __le32 reserved_2;
uint8_t lun; /* SCSI LUN */
uint8_t initiator_id;
uint8_t reserved_3;
uint8_t target_id;
- uint32_t option_flags;
+ __le32 option_flags;
uint8_t status;
uint8_t scsi_status;
uint8_t tag_value; /* Received queue tag message value */
uint8_t tag_type; /* Received queue tag message type */
- uint32_t transfer_length;
- uint32_t residual;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint16_t reserved_4[7];
+ __le32 transfer_length;
+ __le32 residual;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le16 reserved_4[7];
uint8_t sense_data[18];
};
@@ -979,14 +967,6 @@ struct ctio_a64_ret_entry {
#define CS_RETRY 0x82 /* Driver defined */
/*
- * ISP status entry - SCSI status byte bit definitions.
- */
-#define SS_CHECK_CONDITION BIT_1
-#define SS_CONDITION_MET BIT_2
-#define SS_BUSY_CONDITION BIT_3
-#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
-
-/*
* ISP target entries - Option flags bit definitions.
*/
#define OF_ENABLE_TAG BIT_1 /* Tagged queue action enable */
@@ -1082,10 +1062,6 @@ struct scsi_qla_host {
uint32_t reset_active:1; /* 3 */
uint32_t abort_isp_active:1; /* 4 */
uint32_t disable_risc_code_load:1; /* 5 */
- uint32_t enable_64bit_addressing:1; /* 6 */
- uint32_t in_reset:1; /* 7 */
- uint32_t ints_enabled:1;
- uint32_t ignore_nvram:1;
#ifdef __ia64__
uint32_t use_pci_vchannel:1;
#endif
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 659a5d63467d..fc25cd834668 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -211,6 +211,138 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
}
+/* Scsi_Host attributes. */
+
+static ssize_t
+qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
+}
+
+static ssize_t
+qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ char fw_str[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->isp_ops.fw_version_str(ha, fw_str));
+}
+
+static ssize_t
+qla2x00_serial_num_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ uint32_t sn;
+
+ sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+ return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
+ sn % 100000);
+}
+
+static ssize_t
+qla2x00_isp_name_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name);
+}
+
+static ssize_t
+qla2x00_isp_id_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+ ha->product_id[0], ha->product_id[1], ha->product_id[2],
+ ha->product_id[3]);
+}
+
+static ssize_t
+qla2x00_model_name_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
+}
+
+static ssize_t
+qla2x00_model_desc_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->model_desc ? ha->model_desc: "");
+}
+
+static ssize_t
+qla2x00_pci_info_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ char pci_info[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->isp_ops.pci_info_str(ha, pci_info));
+}
+
+static ssize_t
+qla2x00_state_show(struct class_device *cdev, char *buf)
+{
+ scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+ int len = 0;
+
+ if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+ atomic_read(&ha->loop_state) == LOOP_DEAD)
+ len = snprintf(buf, PAGE_SIZE, "Link Down\n");
+ else if (atomic_read(&ha->loop_state) != LOOP_READY ||
+ test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
+ test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))
+ len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
+ else {
+ len = snprintf(buf, PAGE_SIZE, "Link Up - ");
+
+ switch (ha->current_topology) {
+ case ISP_CFG_NL:
+ len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+ break;
+ case ISP_CFG_FL:
+ len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
+ break;
+ case ISP_CFG_N:
+ len += snprintf(buf + len, PAGE_SIZE-len,
+ "N_Port to N_Port\n");
+ break;
+ case ISP_CFG_F:
+ len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
+ break;
+ default:
+ len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
+ break;
+ }
+ }
+ return len;
+}
+
+static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
+ NULL);
+static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
+static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
+static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
+static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
+static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
+static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
+static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
+static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+
+struct class_device_attribute *qla2x00_host_attrs[] = {
+ &class_device_attr_driver_version,
+ &class_device_attr_fw_version,
+ &class_device_attr_serial_num,
+ &class_device_attr_isp_name,
+ &class_device_attr_isp_id,
+ &class_device_attr_model_name,
+ &class_device_attr_model_desc,
+ &class_device_attr_pci_info,
+ &class_device_attr_state,
+ NULL,
+};
+
/* Host attributes. */
static void
@@ -228,16 +360,16 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
scsi_qla_host_t *ha = to_qla_host(host);
fc_port_t *fcport;
- uint64_t node_name = 0;
+ u64 node_name = 0;
list_for_each_entry(fcport, &ha->fcports, list) {
if (starget->id == fcport->os_target_id) {
- node_name = *(uint64_t *)fcport->node_name;
+ node_name = wwn_to_u64(fcport->node_name);
break;
}
}
- fc_starget_node_name(starget) = be64_to_cpu(node_name);
+ fc_starget_node_name(starget) = node_name;
}
static void
@@ -246,16 +378,16 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
scsi_qla_host_t *ha = to_qla_host(host);
fc_port_t *fcport;
- uint64_t port_name = 0;
+ u64 port_name = 0;
list_for_each_entry(fcport, &ha->fcports, list) {
if (starget->id == fcport->os_target_id) {
- port_name = *(uint64_t *)fcport->port_name;
+ port_name = wwn_to_u64(fcport->port_name);
break;
}
}
- fc_starget_port_name(starget) = be64_to_cpu(port_name);
+ fc_starget_port_name(starget) = port_name;
}
static void
@@ -304,10 +436,13 @@ struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
.dd_fcrport_size = sizeof(struct fc_port *),
+ .show_rport_supported_classes = 1,
.get_starget_node_name = qla2x00_get_starget_node_name,
.show_starget_node_name = 1,
@@ -325,8 +460,7 @@ struct fc_function_template qla2xxx_transport_functions = {
void
qla2x00_init_host_attr(scsi_qla_host_t *ha)
{
- fc_host_node_name(ha->host) =
- be64_to_cpu(*(uint64_t *)ha->init_cb->node_name);
- fc_host_port_name(ha->host) =
- be64_to_cpu(*(uint64_t *)ha->init_cb->port_name);
+ fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name);
+ fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name);
+ fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 72bbaa91dc77..9791496fa788 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1334,7 +1334,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
WRT_REG_DWORD(dmp_reg, 0xB0200000);
- dmp_reg = (uint32_t *)((uint8_t *)reg + 0xFC);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index b8d90e97e017..9684e7a91fa9 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -81,6 +81,7 @@
#define DEBUG2_3_11(x) do {x;} while (0);
#define DEBUG2_9_10(x) do {x;} while (0);
#define DEBUG2_11(x) do {x;} while (0);
+#define DEBUG2_13(x) do {x;} while (0);
#else
#define DEBUG2(x) do {} while (0);
#endif
@@ -169,8 +170,14 @@
#if defined(QL_DEBUG_LEVEL_13)
#define DEBUG13(x) do {x;} while (0)
+#if !defined(DEBUG2_13)
+#define DEBUG2_13(x) do {x;} while(0)
+#endif
#else
#define DEBUG13(x) do {} while (0)
+#if !defined(QL_DEBUG_LEVEL_2)
+#define DEBUG2_13(x) do {} while(0)
+#endif
#endif
#if defined(QL_DEBUG_LEVEL_14)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 1c6d366f4fad..b455c31405e4 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -214,6 +214,7 @@
* valid range of an N-PORT id is 0 through 0x7ef.
*/
#define NPH_LAST_HANDLE 0x7ef
+#define NPH_MGMT_SERVER 0x7fa /* FFFFFA */
#define NPH_SNS 0x7fc /* FFFFFC */
#define NPH_FABRIC_CONTROLLER 0x7fd /* FFFFFD */
#define NPH_F_PORT 0x7fe /* FFFFFE */
@@ -630,6 +631,7 @@ typedef struct {
#define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */
#define MBC_READ_RAM_EXTENDED 0xf /* Read RAM extended. */
#define MBC_IOCB_COMMAND 0x12 /* Execute IOCB command. */
+#define MBC_STOP_FIRMWARE 0x14 /* Stop firmware. */
#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */
#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */
#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */
@@ -913,7 +915,7 @@ typedef struct {
* MSB BIT 1 =
* MSB BIT 2 =
* MSB BIT 3 =
- * MSB BIT 4 =
+ * MSB BIT 4 = LED mode
* MSB BIT 5 = enable 50 ohm termination
* MSB BIT 6 = Data Rate (2300 only)
* MSB BIT 7 = Data Rate (2300 only)
@@ -1035,7 +1037,7 @@ typedef struct {
* MSB BIT 1 =
* MSB BIT 2 =
* MSB BIT 3 =
- * MSB BIT 4 =
+ * MSB BIT 4 = LED mode
* MSB BIT 5 = enable 50 ohm termination
* MSB BIT 6 = Data Rate (2300 only)
* MSB BIT 7 = Data Rate (2300 only)
@@ -1131,10 +1133,7 @@ typedef struct {
uint8_t link_down_timeout;
- uint8_t adapter_id_0[4];
- uint8_t adapter_id_1[4];
- uint8_t adapter_id_2[4];
- uint8_t adapter_id_3[4];
+ uint8_t adapter_id[16];
uint8_t alt1_boot_node_name[WWN_SIZE];
uint16_t alt1_boot_lun_number;
@@ -1673,6 +1672,7 @@ typedef struct fc_port {
uint8_t cur_path; /* current path id */
struct fc_rport *rport;
+ u32 supported_classes;
} fc_port_t;
/*
@@ -1727,6 +1727,8 @@ typedef struct fc_port {
#define CT_REJECT_RESPONSE 0x8001
#define CT_ACCEPT_RESPONSE 0x8002
+#define CT_REASON_CANNOT_PERFORM 0x09
+#define CT_EXPL_ALREADY_REGISTERED 0x10
#define NS_N_PORT_TYPE 0x01
#define NS_NL_PORT_TYPE 0x02
@@ -1768,6 +1770,100 @@ typedef struct fc_port {
#define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255)
#define RSNN_NN_RSP_SIZE 16
+/*
+ * HBA attribute types.
+ */
+#define FDMI_HBA_ATTR_COUNT 9
+#define FDMI_HBA_NODE_NAME 1
+#define FDMI_HBA_MANUFACTURER 2
+#define FDMI_HBA_SERIAL_NUMBER 3
+#define FDMI_HBA_MODEL 4
+#define FDMI_HBA_MODEL_DESCRIPTION 5
+#define FDMI_HBA_HARDWARE_VERSION 6
+#define FDMI_HBA_DRIVER_VERSION 7
+#define FDMI_HBA_OPTION_ROM_VERSION 8
+#define FDMI_HBA_FIRMWARE_VERSION 9
+#define FDMI_HBA_OS_NAME_AND_VERSION 0xa
+#define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb
+
+struct ct_fdmi_hba_attr {
+ uint16_t type;
+ uint16_t len;
+ union {
+ uint8_t node_name[WWN_SIZE];
+ uint8_t manufacturer[32];
+ uint8_t serial_num[8];
+ uint8_t model[16];
+ uint8_t model_desc[80];
+ uint8_t hw_version[16];
+ uint8_t driver_version[32];
+ uint8_t orom_version[16];
+ uint8_t fw_version[16];
+ uint8_t os_version[128];
+ uint8_t max_ct_len[4];
+ } a;
+};
+
+struct ct_fdmi_hba_attributes {
+ uint32_t count;
+ struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT];
+};
+
+/*
+ * Port attribute types.
+ */
+#define FDMI_PORT_ATTR_COUNT 5
+#define FDMI_PORT_FC4_TYPES 1
+#define FDMI_PORT_SUPPORT_SPEED 2
+#define FDMI_PORT_CURRENT_SPEED 3
+#define FDMI_PORT_MAX_FRAME_SIZE 4
+#define FDMI_PORT_OS_DEVICE_NAME 5
+#define FDMI_PORT_HOST_NAME 6
+
+struct ct_fdmi_port_attr {
+ uint16_t type;
+ uint16_t len;
+ union {
+ uint8_t fc4_types[32];
+ uint32_t sup_speed;
+ uint32_t cur_speed;
+ uint32_t max_frame_size;
+ uint8_t os_dev_name[32];
+ uint8_t host_name[32];
+ } a;
+};
+
+/*
+ * Port Attribute Block.
+ */
+struct ct_fdmi_port_attributes {
+ uint32_t count;
+ struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT];
+};
+
+/* FDMI definitions. */
+#define GRHL_CMD 0x100
+#define GHAT_CMD 0x101
+#define GRPL_CMD 0x102
+#define GPAT_CMD 0x110
+
+#define RHBA_CMD 0x200
+#define RHBA_RSP_SIZE 16
+
+#define RHAT_CMD 0x201
+#define RPRT_CMD 0x210
+
+#define RPA_CMD 0x211
+#define RPA_RSP_SIZE 16
+
+#define DHBA_CMD 0x300
+#define DHBA_REQ_SIZE (16 + 8)
+#define DHBA_RSP_SIZE 16
+
+#define DHAT_CMD 0x301
+#define DPRT_CMD 0x310
+#define DPA_CMD 0x311
+
/* CT command header -- request/response common fields */
struct ct_cmd_hdr {
uint8_t revision;
@@ -1825,6 +1921,43 @@ struct ct_sns_req {
uint8_t name_len;
uint8_t sym_node_name[255];
} rsnn_nn;
+
+ struct {
+ uint8_t hba_indentifier[8];
+ } ghat;
+
+ struct {
+ uint8_t hba_identifier[8];
+ uint32_t entry_count;
+ uint8_t port_name[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } rhba;
+
+ struct {
+ uint8_t hba_identifier[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } rhat;
+
+ struct {
+ uint8_t port_name[8];
+ struct ct_fdmi_port_attributes attrs;
+ } rpa;
+
+ struct {
+ uint8_t port_name[8];
+ } dhba;
+
+ struct {
+ uint8_t port_name[8];
+ } dhat;
+
+ struct {
+ uint8_t port_name[8];
+ } dprt;
+
+ struct {
+ uint8_t port_name[8];
+ } dpa;
} req;
};
@@ -1882,6 +2015,12 @@ struct ct_sns_rsp {
struct {
uint8_t fc4_types[32];
} gft_id;
+
+ struct {
+ uint32_t entry_count;
+ uint8_t port_name[8];
+ struct ct_fdmi_hba_attributes attrs;
+ } ghat;
} rsp;
};
@@ -2032,6 +2171,8 @@ struct isp_operations {
uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
+ void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
+ uint32_t);
uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
@@ -2111,6 +2252,7 @@ typedef struct scsi_qla_host {
#define IOCTL_ERROR_RECOVERY 23
#define LOOP_RESET_NEEDED 24
#define BEACON_BLINK_NEEDED 25
+#define REGISTER_FDMI_NEEDED 26
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@@ -2204,6 +2346,7 @@ typedef struct scsi_qla_host {
int port_down_retry_count;
uint8_t mbx_count;
uint16_t last_loop_id;
+ uint16_t mgmt_svr_loop_id;
uint32_t login_retry_count;
@@ -2318,6 +2461,7 @@ typedef struct scsi_qla_host {
uint8_t model_number[16+1];
#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
char *model_desc;
+ uint8_t adapter_id[16+1];
uint8_t *node_name;
uint8_t *port_name;
@@ -2377,6 +2521,7 @@ typedef struct scsi_qla_host {
#define QLA_SUSPENDED 0x106
#define QLA_BUSY 0x107
#define QLA_RSCNS_HANDLED 0x108
+#define QLA_ALREADY_REGISTERED 0x109
/*
* Stat info for all adpaters
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 665c203e0675..e451941ad81d 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -52,7 +52,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
-extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
@@ -79,6 +79,7 @@ extern int ql2xplogiabsentdevice;
extern int ql2xenablezio;
extern int ql2xintrdelaytimer;
extern int ql2xloginretrycount;
+extern int ql2xfdmienable;
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
@@ -147,9 +148,6 @@ qla2x00_abort_target(fc_port_t *);
#endif
extern int
-qla2x00_target_reset(scsi_qla_host_t *, struct fc_port *);
-
-extern int
qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
uint8_t *, uint16_t *);
@@ -215,6 +213,9 @@ qla2x00_get_serdes_params(scsi_qla_host_t *, uint16_t *, uint16_t *,
extern int
qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+extern int
+qla2x00_stop_firmware(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
@@ -269,11 +270,14 @@ extern int qla2x00_rft_id(scsi_qla_host_t *);
extern int qla2x00_rff_id(scsi_qla_host_t *);
extern int qla2x00_rnn_id(scsi_qla_host_t *);
extern int qla2x00_rsnn_nn(scsi_qla_host_t *);
+extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern int qla2x00_fdmi_register(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_rscn.c source file.
*/
-extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
int);
extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
@@ -289,6 +293,8 @@ extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_attr.c source file.
*/
+struct class_device_attribute;
+extern struct class_device_attribute *qla2x00_host_attrs[];
struct fc_function_template;
extern struct fc_function_template qla2xxx_transport_functions;
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 31ce4f62da13..e7b138c2e339 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1099,3 +1099,567 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
return (rval);
}
+
+/**
+ * qla2x00_mgmt_svr_login() - Login to fabric Managment Service.
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_mgmt_svr_login(scsi_qla_host_t *ha)
+{
+ int ret;
+ uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+ ret = QLA_SUCCESS;
+ if (ha->flags.management_server_logged_in)
+ return ret;
+
+ ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
+ mb, BIT_1);
+ if (mb[0] != MBS_COMMAND_COMPLETE) {
+ DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
+ "loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x\n",
+ __func__, ha->host_no, ha->mgmt_svr_loop_id, mb[0], mb[1],
+ mb[2], mb[6], mb[7]));
+ ret = QLA_FUNCTION_FAILED;
+ } else
+ ha->flags.management_server_logged_in = 1;
+
+ return ret;
+}
+
+/**
+ * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+ uint32_t rsp_size)
+{
+ ms_iocb_entry_t *ms_pkt;
+
+ ms_pkt = ha->ms_iocb;
+ memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
+
+ ms_pkt->entry_type = MS_IOCB_TYPE;
+ ms_pkt->entry_count = 1;
+ SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id);
+ ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
+ ms_pkt->timeout = __constant_cpu_to_le16(59);
+ ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+ ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
+ ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
+ ms_pkt->req_bytecount = cpu_to_le32(req_size);
+
+ ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+
+ ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
+
+ return ms_pkt;
+}
+
+/**
+ * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
+ * @ha: HA context
+ * @req_size: request size in bytes
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the @ha's ms_iocb.
+ */
+void *
+qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
+ uint32_t rsp_size)
+{
+ struct ct_entry_24xx *ct_pkt;
+
+ ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+ memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
+
+ ct_pkt->entry_type = CT_IOCB_TYPE;
+ ct_pkt->entry_count = 1;
+ ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
+ ct_pkt->timeout = __constant_cpu_to_le16(59);
+ ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
+ ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
+ ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
+ ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+
+ ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+
+ ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
+ ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+
+ return ct_pkt;
+}
+
+static inline ms_iocb_entry_t *
+qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size)
+{
+ ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
+ struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+ ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+ } else {
+ ms_pkt->req_bytecount = cpu_to_le32(req_size);
+ ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+ }
+
+ return ms_pkt;
+}
+
+/**
+ * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
+ * @ct_req: CT request buffer
+ * @cmd: GS command
+ * @rsp_size: response size in bytes
+ *
+ * Returns a pointer to the intitialized @ct_req.
+ */
+static inline struct ct_sns_req *
+qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
+ uint16_t rsp_size)
+{
+ memset(ct_req, 0, sizeof(struct ct_sns_pkt));
+
+ ct_req->header.revision = 0x01;
+ ct_req->header.gs_type = 0xFA;
+ ct_req->header.gs_subtype = 0x10;
+ ct_req->command = cpu_to_be16(cmd);
+ ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
+
+ return ct_req;
+}
+
+/**
+ * qla2x00_fdmi_rhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rhba(scsi_qla_host_t *ha)
+{
+ int rval, alen;
+ uint32_t size, sn;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ uint8_t *entries;
+ struct ct_fdmi_hba_attr *eiter;
+
+ /* Issue RHBA */
+ /* Prepare common MS IOCB */
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
+ RHBA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- attribute block, attributes. */
+ memcpy(ct_req->req.rhba.hba_identifier, ha->port_name, WWN_SIZE);
+ ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
+ memcpy(ct_req->req.rhba.port_name, ha->port_name, WWN_SIZE);
+ size = 2 * WWN_SIZE + 4 + 4;
+
+ /* Attributes */
+ ct_req->req.rhba.attrs.count =
+ __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
+ entries = ct_req->req.rhba.hba_identifier;
+
+ /* Nodename. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
+ eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
+ memcpy(eiter->a.node_name, ha->node_name, WWN_SIZE);
+ size += 4 + WWN_SIZE;
+
+ DEBUG13(printk("%s(%ld): NODENAME=%02x%02x%02x%02x%02x%02x%02x%02x.\n",
+ __func__, ha->host_no,
+ eiter->a.node_name[0], eiter->a.node_name[1], eiter->a.node_name[2],
+ eiter->a.node_name[3], eiter->a.node_name[4], eiter->a.node_name[5],
+ eiter->a.node_name[6], eiter->a.node_name[7]));
+
+ /* Manufacturer. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
+ strcpy(eiter->a.manufacturer, "QLogic Corporation");
+ alen = strlen(eiter->a.manufacturer);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MANUFACTURER=%s.\n", __func__, ha->host_no,
+ eiter->a.manufacturer));
+
+ /* Serial number. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
+ sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
+ sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
+ alen = strlen(eiter->a.serial_num);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): SERIALNO=%s.\n", __func__, ha->host_no,
+ eiter->a.serial_num));
+
+ /* Model name. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
+ strcpy(eiter->a.model, ha->model_number);
+ alen = strlen(eiter->a.model);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MODEL_NAME=%s.\n", __func__, ha->host_no,
+ eiter->a.model));
+
+ /* Model description. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
+ if (ha->model_desc)
+ strncpy(eiter->a.model_desc, ha->model_desc, 80);
+ alen = strlen(eiter->a.model_desc);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): MODEL_DESC=%s.\n", __func__, ha->host_no,
+ eiter->a.model_desc));
+
+ /* Hardware version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
+ strcpy(eiter->a.hw_version, ha->adapter_id);
+ alen = strlen(eiter->a.hw_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): HARDWAREVER=%s.\n", __func__, ha->host_no,
+ eiter->a.hw_version));
+
+ /* Driver version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
+ strcpy(eiter->a.driver_version, qla2x00_version_str);
+ alen = strlen(eiter->a.driver_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): DRIVERVER=%s.\n", __func__, ha->host_no,
+ eiter->a.driver_version));
+
+ /* Option ROM version. */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
+ strcpy(eiter->a.orom_version, "0.00");
+ alen = strlen(eiter->a.orom_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): OPTROMVER=%s.\n", __func__, ha->host_no,
+ eiter->a.orom_version));
+
+ /* Firmware version */
+ eiter = (struct ct_fdmi_hba_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
+ ha->isp_ops.fw_version_str(ha, eiter->a.fw_version);
+ alen = strlen(eiter->a.fw_version);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): FIRMWAREVER=%s.\n", __func__, ha->host_no,
+ eiter->a.fw_version));
+
+ /* Update MS request size. */
+ qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+ DEBUG13(printk("%s(%ld): RHBA identifier="
+ "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+ ha->host_no, ct_req->req.rhba.hba_identifier[0],
+ ct_req->req.rhba.hba_identifier[1],
+ ct_req->req.rhba.hba_identifier[2],
+ ct_req->req.rhba.hba_identifier[3],
+ ct_req->req.rhba.hba_identifier[4],
+ ct_req->req.rhba.hba_identifier[5],
+ ct_req->req.rhba.hba_identifier[6],
+ ct_req->req.rhba.hba_identifier[7], size));
+ DEBUG13(qla2x00_dump_buffer(entries, size));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): RHBA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RHBA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+ ct_rsp->header.explanation_code ==
+ CT_EXPL_ALREADY_REGISTERED) {
+ DEBUG2_13(printk("%s(%ld): HBA already registered.\n",
+ __func__, ha->host_no));
+ rval = QLA_ALREADY_REGISTERED;
+ }
+ } else {
+ DEBUG2(printk("scsi(%ld): RHBA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_dhba() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_dhba(scsi_qla_host_t *ha)
+{
+ int rval;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+
+ /* Issue RPA */
+ /* Prepare common MS IOCB */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE,
+ DHBA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
+ DHBA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- portname. */
+ memcpy(ct_req->req.dhba.port_name, ha->port_name, WWN_SIZE);
+
+ DEBUG13(printk("%s(%ld): DHBA portname="
+ "%02x%02x%02x%02x%02x%02x%02x%02x.\n", __func__, ha->host_no,
+ ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
+ ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
+ ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
+ ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): DHBA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "DHBA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ DEBUG2(printk("scsi(%ld): DHBA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_rpa() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+{
+ int rval, alen;
+ uint32_t size, max_frame_size;
+
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ uint8_t *entries;
+ struct ct_fdmi_port_attr *eiter;
+ struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
+
+ /* Issue RPA */
+ /* Prepare common MS IOCB */
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
+ RPA_RSP_SIZE);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command arguments -- attribute block, attributes. */
+ memcpy(ct_req->req.rpa.port_name, ha->port_name, WWN_SIZE);
+ size = WWN_SIZE + 4;
+
+ /* Attributes */
+ ct_req->req.rpa.attrs.count =
+ __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
+ entries = ct_req->req.rpa.port_name;
+
+ /* FC4 types. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
+ eiter->len = __constant_cpu_to_be16(4 + 32);
+ eiter->a.fc4_types[2] = 0x01;
+ size += 4 + 32;
+
+ DEBUG13(printk("%s(%ld): FC4_TYPES=%02x %02x.\n", __func__, ha->host_no,
+ eiter->a.fc4_types[2], eiter->a.fc4_types[1]));
+
+ /* Supported speed. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ if (IS_QLA25XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(4);
+ else if (IS_QLA24XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(8);
+ else if (IS_QLA23XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(2);
+ else
+ eiter->a.sup_speed = __constant_cpu_to_be32(1);
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no,
+ eiter->a.sup_speed));
+
+ /* Current speed. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ switch (ha->link_data_rate) {
+ case 0:
+ eiter->a.cur_speed = __constant_cpu_to_be32(1);
+ break;
+ case 1:
+ eiter->a.cur_speed = __constant_cpu_to_be32(2);
+ break;
+ case 3:
+ eiter->a.cur_speed = __constant_cpu_to_be32(8);
+ break;
+ case 4:
+ eiter->a.cur_speed = __constant_cpu_to_be32(4);
+ break;
+ }
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): CURRENT_SPEED=%x.\n", __func__, ha->host_no,
+ eiter->a.cur_speed));
+
+ /* Max frame size. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+ eiter->len = __constant_cpu_to_be16(4 + 4);
+ max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ?
+ (uint32_t) icb24->frame_payload_size:
+ (uint32_t) ha->init_cb->frame_payload_size;
+ eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
+ size += 4 + 4;
+
+ DEBUG13(printk("%s(%ld): MAX_FRAME_SIZE=%x.\n", __func__, ha->host_no,
+ eiter->a.max_frame_size));
+
+ /* OS device name. */
+ eiter = (struct ct_fdmi_port_attr *) (entries + size);
+ eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+ sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no);
+ alen = strlen(eiter->a.os_dev_name);
+ alen += (alen & 3) ? (4 - (alen & 3)) : 4;
+ eiter->len = cpu_to_be16(4 + alen);
+ size += 4 + alen;
+
+ DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no,
+ eiter->a.os_dev_name));
+
+ /* Update MS request size. */
+ qla2x00_update_ms_fdmi_iocb(ha, size + 16);
+
+ DEBUG13(printk("%s(%ld): RPA portname="
+ "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n", __func__,
+ ha->host_no, ct_req->req.rpa.port_name[0],
+ ct_req->req.rpa.port_name[1], ct_req->req.rpa.port_name[2],
+ ct_req->req.rpa.port_name[3], ct_req->req.rpa.port_name[4],
+ ct_req->req.rpa.port_name[5], ct_req->req.rpa.port_name[6],
+ ct_req->req.rpa.port_name[7], size));
+ DEBUG13(qla2x00_dump_buffer(entries, size));
+
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(ms_iocb_entry_t));
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+ DEBUG2_3(printk("scsi(%ld): RPA issue IOCB failed (%d).\n",
+ ha->host_no, rval));
+ } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RPA") !=
+ QLA_SUCCESS) {
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ DEBUG2(printk("scsi(%ld): RPA exiting normally.\n",
+ ha->host_no));
+ }
+
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_register() -
+ * @ha: HA context
+ *
+ * Returns 0 on success.
+ */
+int
+qla2x00_fdmi_register(scsi_qla_host_t *ha)
+{
+ int rval;
+
+ rval = qla2x00_mgmt_svr_login(ha);
+ if (rval)
+ return rval;
+
+ rval = qla2x00_fdmi_rhba(ha);
+ if (rval) {
+ if (rval != QLA_ALREADY_REGISTERED)
+ return rval;
+
+ rval = qla2x00_fdmi_dhba(ha);
+ if (rval)
+ return rval;
+
+ rval = qla2x00_fdmi_rhba(ha);
+ if (rval)
+ return rval;
+ }
+ rval = qla2x00_fdmi_rpa(ha);
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a6d2559217cd..fbb6feee40cf 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -88,6 +88,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
ha->mbx_flags = 0;
ha->isp_abort_cnt = 0;
ha->beacon_blink_led = 0;
+ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
rval = ha->isp_ops.pci_config(ha);
@@ -200,6 +201,7 @@ int
qla2100_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -214,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha)
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -236,6 +238,7 @@ int
qla2300_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
uint32_t cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -301,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha)
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -323,6 +326,7 @@ int
qla24xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
int pcix_cmd_reg, pcie_dctl_reg;
@@ -365,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
}
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1563,7 +1567,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
- ha->flags.enable_led_scheme = ((nv->efi_parameters & BIT_3) ? 1 : 0);
+ ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
ha->operating_mode =
(icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -1681,7 +1685,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
* Returns a pointer to the allocated fcport, or NULL, if none available.
*/
fc_port_t *
-qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
{
fc_port_t *fcport;
@@ -1697,6 +1701,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
+ fcport->supported_classes = FC_COS_UNSPECIFIED;
return (fcport);
}
@@ -1898,7 +1903,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
continue;
/* Bypass if not same domain and area of adapter. */
- if (area != ha->d_id.b.area || domain != ha->d_id.b.domain)
+ if (area && domain &&
+ (area != ha->d_id.b.area || domain != ha->d_id.b.domain))
continue;
/* Bypass invalid local loop ID. */
@@ -2063,8 +2069,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
return;
}
- rport_ids.node_name = be64_to_cpu(*(uint64_t *)fcport->node_name);
- rport_ids.port_name = be64_to_cpu(*(uint64_t *)fcport->port_name);
+ rport_ids.node_name = wwn_to_u64(fcport->node_name);
+ rport_ids.port_name = wwn_to_u64(fcport->port_name);
rport_ids.port_id = fcport->d_id.b.domain << 16 |
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2075,6 +2081,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
return;
}
rport->dd_data = fcport;
+ rport->supported_classes = fcport->supported_classes;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
if (fcport->port_type == FCT_INITIATOR)
@@ -2130,6 +2137,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
return (QLA_SUCCESS);
}
do {
+ /* FDMI support. */
+ if (ql2xfdmienable &&
+ test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags))
+ qla2x00_fdmi_register(ha);
+
/* Ensure we are logged into the SNS. */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
loop_id = NPH_SNS;
@@ -2392,6 +2404,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
if (new_fcport->d_id.b24 == ha->d_id.b24)
continue;
+ /* Bypass if same domain and area of adapter. */
+ if (((new_fcport->d_id.b24 & 0xffff00) ==
+ (ha->d_id.b24 & 0xffff00)) && ha->current_topology ==
+ ISP_CFG_FL)
+ continue;
+
/* Bypass reserved domain fields. */
if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
continue;
@@ -2794,6 +2812,11 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
}
}
+ if (mb[10] & BIT_0)
+ fcport->supported_classes |= FC_COS_CLASS2;
+ if (mb[10] & BIT_1)
+ fcport->supported_classes |= FC_COS_CLASS3;
+
rval = QLA_SUCCESS;
break;
} else if (mb[0] == MBS_LOOP_ID_USED) {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index ebdc3c54d155..37f82e2cd7fb 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -810,12 +810,8 @@ qla24xx_start_scsi(srb_t *sp)
ha->req_q_cnt = ha->request_q_length -
(ha->req_ring_index - cnt);
}
- if (ha->req_q_cnt < (req_cnt + 2)) {
- if (cmd->use_sg)
- pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
- cmd->sc_data_direction);
+ if (ha->req_q_cnt < (req_cnt + 2))
goto queuing_error;
- }
/* Build command packet. */
ha->current_outstanding_cmd = handle;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f910de6dd437..c255bb0268a9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -451,6 +451,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->flags.management_server_logged_in = 0;
ha->link_data_rate = 0;
+ if (ql2xfdmienable)
+ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
/* Update AEN queue. */
qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 409ea0ac4032..13e1c9047079 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -19,6 +19,7 @@
#include "qla_def.h"
#include <linux/delay.h>
+#include <scsi/scsi_transport_fc.h>
static void
qla2x00_mbx_sem_timeout(unsigned long data)
@@ -251,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
} else {
- mb0 = RD_MAILBOX_REG(ha, reg->isp, 0);
+ mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
ictrl = RD_REG_WORD(&reg->isp.ictrl);
}
printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
@@ -983,58 +984,6 @@ qla2x00_abort_target(fc_port_t *fcport)
#endif
/*
- * qla2x00_target_reset
- * Issue target reset mailbox command.
- *
- * Input:
- * ha = adapter block pointer.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);)
-
- if (atomic_read(&fcport->state) != FCS_ONLINE)
- return 0;
-
- mcp->mb[0] = MBC_TARGET_RESET;
- if (HAS_EXTENDED_IDS(ha))
- mcp->mb[1] = fcport->loop_id;
- else
- mcp->mb[1] = fcport->loop_id << 8;
- mcp->mb[2] = ha->loop_reset_delay;
- mcp->out_mb = MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n",
- ha->host_no, rval);)
- } else {
- /*EMPTY*/
- DEBUG11(printk("qla2x00_target_reset(%ld): done.\n",
- ha->host_no);)
- }
-
- return rval;
-}
-
-/*
* qla2x00_get_adapter_id
* Get adapter ID and topology.
*
@@ -1326,6 +1275,10 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
fcport->port_type = FCT_INITIATOR;
else
fcport->port_type = FCT_TARGET;
+
+ /* Passback COS information. */
+ fcport->supported_classes = (pd->options & BIT_4) ?
+ FC_COS_CLASS2: FC_COS_CLASS3;
}
gpd_error_out:
@@ -1661,6 +1614,13 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
mb[1] |= BIT_1;
} else
mb[1] = BIT_0;
+
+ /* Passback COS information. */
+ mb[10] = 0;
+ if (lg->io_parameter[7] || lg->io_parameter[8])
+ mb[10] |= BIT_0; /* Class 2. */
+ if (lg->io_parameter[9] || lg->io_parameter[10])
+ mb[10] |= BIT_1; /* Class 3. */
}
dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1723,6 +1683,8 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
mb[2] = mcp->mb[2];
mb[6] = mcp->mb[6];
mb[7] = mcp->mb[7];
+ /* COS retrieved from Get-Port-Database mailbox command. */
+ mb[10] = 0;
}
if (rval != QLA_SUCCESS) {
@@ -2465,3 +2427,32 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
return rval;
}
+
+int
+qla2x00_stop_firmware(scsi_qla_host_t *ha)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+ mcp->mb[0] = MBC_STOP_FIRMWARE;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = 5;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 9000659bfbcf..7aec93f9d423 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -79,7 +79,7 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
-int ql2xfwloadbin;
+int ql2xfwloadbin=1;
module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
"Load ISP2xxx firmware image via hotplug.");
@@ -88,6 +88,12 @@ static void qla2x00_free_device(scsi_qla_host_t *);
static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
+int ql2xfdmienable;
+module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfdmienable,
+ "Enables FDMI registratons "
+ "Default is 0 - no FDMI. 1 - perfom FDMI.");
+
/*
* SCSI host template entry points
*/
@@ -105,6 +111,9 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
static int qla2x00_loop_reset(scsi_qla_host_t *ha);
static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
+static int qla2x00_change_queue_depth(struct scsi_device *, int);
+static int qla2x00_change_queue_type(struct scsi_device *, int);
+
static struct scsi_host_template qla2x00_driver_template = {
.module = THIS_MODULE,
.name = "qla2xxx",
@@ -119,6 +128,8 @@ static struct scsi_host_template qla2x00_driver_template = {
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .change_queue_depth = qla2x00_change_queue_depth,
+ .change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
@@ -129,6 +140,7 @@ static struct scsi_host_template qla2x00_driver_template = {
* which equates to 0x800000 sectors.
*/
.max_sectors = 0xFFFF,
+ .shost_attrs = qla2x00_host_attrs,
};
static struct scsi_host_template qla24xx_driver_template = {
@@ -145,12 +157,15 @@ static struct scsi_host_template qla24xx_driver_template = {
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .change_queue_depth = qla2x00_change_queue_depth,
+ .change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
+ .shost_attrs = qla2x00_host_attrs,
};
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@ -487,14 +502,13 @@ qc24_fail_command:
static int
qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
{
-#define ABORT_POLLING_PERIOD HZ
-#define ABORT_WAIT_ITER ((10 * HZ) / (ABORT_POLLING_PERIOD))
+#define ABORT_POLLING_PERIOD 1000
+#define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD))
unsigned long wait_iter = ABORT_WAIT_ITER;
int ret = QLA_SUCCESS;
while (CMD_SP(cmd)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(ABORT_POLLING_PERIOD);
+ msleep(ABORT_POLLING_PERIOD);
if (--wait_iter)
break;
@@ -1016,7 +1030,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
if (fcport->port_type != FCT_TARGET)
continue;
- status = qla2x00_target_reset(ha, fcport);
+ status = qla2x00_device_reset(ha, fcport);
if (status != QLA_SUCCESS)
break;
}
@@ -1103,6 +1117,28 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
sdev->hostdata = NULL;
}
+static int
+qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ return sdev->queue_depth;
+}
+
+static int
+qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+ if (sdev->tagged_supported) {
+ scsi_set_tag_type(sdev, tag_type);
+ if (tag_type)
+ scsi_activate_tcq(sdev, sdev->queue_depth);
+ else
+ scsi_deactivate_tcq(sdev, sdev->queue_depth);
+ } else
+ tag_type = 0;
+
+ return tag_type;
+}
+
/**
* qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
* @ha: HA context
@@ -1113,36 +1149,23 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
static void
qla2x00_config_dma_addressing(scsi_qla_host_t *ha)
{
- /* Assume 32bit DMA address */
+ /* Assume a 32bit DMA mask. */
ha->flags.enable_64bit_addressing = 0;
- /*
- * Given the two variants pci_set_dma_mask(), allow the compiler to
- * assist in setting the proper dma mask.
- */
- if (sizeof(dma_addr_t) > 4) {
- if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
+ if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) {
+ /* Any upper-dword bits set? */
+ if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
+ !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
+ /* Ok, a 64bit DMA mask is applicable. */
ha->flags.enable_64bit_addressing = 1;
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64;
-
- if (pci_set_consistent_dma_mask(ha->pdev,
- DMA_64BIT_MASK)) {
- qla_printk(KERN_DEBUG, ha,
- "Failed to set 64 bit PCI consistent mask; "
- "using 32 bit.\n");
- pci_set_consistent_dma_mask(ha->pdev,
- DMA_32BIT_MASK);
- }
- } else {
- qla_printk(KERN_DEBUG, ha,
- "Failed to set 64 bit PCI DMA mask, falling back "
- "to 32 bit MASK.\n");
- pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
+ return;
}
- } else {
- pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
+
+ dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK);
+ pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
static int
@@ -1302,6 +1325,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->brd_info = brd_info;
sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no);
+ ha->dpc_pid = -1;
+
/* Configure PCI I/O space */
ret = qla2x00_iospace_config(ha);
if (ret)
@@ -1316,6 +1341,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->prev_topology = 0;
ha->ports = MAX_BUSES;
ha->init_cb_size = sizeof(init_cb_t);
+ ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
/* Assign ISP specific operations. */
ha->isp_ops.pci_config = qla2100_pci_config;
@@ -1338,6 +1364,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32;
ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32;
ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb;
+ ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb;
ha->isp_ops.read_nvram = qla2x00_read_nvram_data;
ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
ha->isp_ops.fw_dump = qla2100_fw_dump;
@@ -1375,6 +1402,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct init_cb_24xx);
+ ha->mgmt_svr_loop_id = 10;
ha->isp_ops.pci_config = qla24xx_pci_config;
ha->isp_ops.reset_chip = qla24xx_reset_chip;
ha->isp_ops.chip_diag = qla24xx_chip_diag;
@@ -1395,6 +1423,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.fabric_login = qla24xx_login_fabric;
ha->isp_ops.fabric_logout = qla24xx_fabric_logout;
ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb;
+ ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb;
ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
ha->isp_ops.fw_dump = qla24xx_fw_dump;
@@ -1421,7 +1450,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
*/
spin_lock_init(&ha->mbx_reg_lock);
- ha->dpc_pid = -1;
init_completion(&ha->dpc_inited);
init_completion(&ha->dpc_exited);
@@ -1558,8 +1586,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
return 0;
probe_failed:
- fc_remove_host(ha->host);
-
qla2x00_free_device(ha);
scsi_host_put(host);
@@ -1601,10 +1627,6 @@ qla2x00_free_device(scsi_qla_host_t *ha)
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
qla2x00_cancel_io_descriptors(ha);
- /* turn-off interrupts on the card */
- if (ha->interrupts_on)
- ha->isp_ops.disable_intrs(ha);
-
/* Disable timer */
if (ha->timer_active)
qla2x00_stop_timer(ha);
@@ -1624,8 +1646,14 @@ qla2x00_free_device(scsi_qla_host_t *ha)
}
}
- qla2x00_mem_free(ha);
+ /* Stop currently executing firmware. */
+ qla2x00_stop_firmware(ha);
+
+ /* turn-off interrupts on the card */
+ if (ha->interrupts_on)
+ ha->isp_ops.disable_intrs(ha);
+ qla2x00_mem_free(ha);
ha->flags.online = 0;
@@ -1934,7 +1962,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
{
struct list_head *fcpl, *fcptemp;
fc_port_t *fcport;
- unsigned long wtime;/* max wait time if mbx cmd is busy. */
+ unsigned int wtime;/* max wait time if mbx cmd is busy. */
if (ha == NULL) {
/* error */
@@ -1943,11 +1971,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
}
/* Make sure all other threads are stopped. */
- wtime = 60 * HZ;
- while (ha->dpc_wait && wtime) {
- set_current_state(TASK_INTERRUPTIBLE);
- wtime = schedule_timeout(wtime);
- }
+ wtime = 60 * 1000;
+ while (ha->dpc_wait && wtime)
+ wtime = msleep_interruptible(wtime);
/* free ioctl memory */
qla2x00_free_ioctl_mem(ha);
@@ -2478,15 +2504,15 @@ qla2x00_timer(scsi_qla_host_t *ha)
int
qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
{
- const unsigned int step = HZ/10;
+ const unsigned int step = 100; /* msecs */
+ unsigned int iterations = jiffies_to_msecs(timeout)/100;
do {
if (!down_trylock(sema))
return 0;
- set_current_state(TASK_INTERRUPTIBLE);
- if (schedule_timeout(step))
+ if (msleep_interruptible(step))
break;
- } while ((timeout -= step) > 0);
+ } while (--iterations >= 0);
return -ETIMEDOUT;
}
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index bdc3bc74bbe1..7534efcc8918 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -330,6 +330,8 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
fcport->flags &= ~FCF_FAILOVER_NEEDED;
fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
atomic_set(&fcport->state, FCS_ONLINE);
+ if (fcport->rport)
+ fc_remote_port_unblock(fcport->rport);
}
@@ -1064,7 +1066,7 @@ qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
* Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
*/
fc_port_t *
-qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
{
fc_port_t *fcport;
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d7f5c608009c..c14abf743b7c 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -468,21 +468,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
uint32_t i;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
for (i = 0; i < dwords; i++, faddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
flash_data_to_access_addr(faddr)));
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return dwptr;
}
@@ -532,10 +523,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
ret = QLA_SUCCESS;
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
ha->host_no, man_id, flash_id));
@@ -599,10 +586,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return ret;
}
@@ -630,11 +613,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
{
uint32_t i;
uint32_t *dwptr;
- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
/* Dword reads to flash. */
dwptr = (uint32_t *)buf;
@@ -642,10 +620,6 @@ qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
nvram_data_to_access_addr(naddr)));
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return buf;
}
@@ -690,10 +664,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
ret = QLA_SUCCESS;
- /* Pause RISC. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -728,9 +698,5 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
- /* Release RISC pause. */
- WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
-
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index e3cd3618bc54..eae7d6edd531 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -19,9 +19,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.00b5-k"
+#define QLA2XXX_VERSION "8.01.00-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
#define QLA_DRIVER_PATCH_VER 0
-#define QLA_DRIVER_BETA_VER 5
+#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index a917ab7475ac..1fd5fc6d0fe3 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1119,6 +1119,36 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int
host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
}
+static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out)
+{
+ unsigned char *buf;
+ unsigned int buflen;
+
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *) cmd->request_buffer;
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ buflen = sg->length;
+ } else {
+ buf = cmd->request_buffer;
+ buflen = cmd->request_bufflen;
+ }
+
+ *buf_out = buf;
+ return buflen;
+}
+
+static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf)
+{
+ if (cmd->use_sg) {
+ struct scatterlist *sg;
+
+ sg = (struct scatterlist *) cmd->request_buffer;
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ }
+}
+
/*
* Until we scan the entire bus with inquiries, go throught this fella...
*/
@@ -1145,11 +1175,9 @@ static void ourdone(struct scsi_cmnd *Cmnd)
int ok = host_byte(Cmnd->result) == DID_OK;
if (Cmnd->cmnd[0] == 0x12 && ok) {
unsigned char *iqd;
+ unsigned int iqd_len;
- if (Cmnd->use_sg != 0)
- BUG();
-
- iqd = ((unsigned char *)Cmnd->buffer);
+ iqd_len = scsi_rbuf_get(Cmnd, &iqd);
/* tags handled in midlayer */
/* enable sync mode? */
@@ -1163,6 +1191,9 @@ static void ourdone(struct scsi_cmnd *Cmnd)
if (iqd[7] & 0x20) {
qpti->dev_param[tgt].device_flags |= 0x20;
}
+
+ scsi_rbuf_put(Cmnd, iqd);
+
qpti->sbits |= (1 << tgt);
} else if (!ok) {
qpti->sbits |= (1 << tgt);
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
new file mode 100644
index 000000000000..f1ea5027865f
--- /dev/null
+++ b/drivers/scsi/raid_class.c
@@ -0,0 +1,250 @@
+/*
+ * RAID Attributes
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/raid_class.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#define RAID_NUM_ATTRS 3
+
+struct raid_internal {
+ struct raid_template r;
+ struct raid_function_template *f;
+ /* The actual attributes */
+ struct class_device_attribute private_attrs[RAID_NUM_ATTRS];
+ /* The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c */
+ struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1];
+};
+
+struct raid_component {
+ struct list_head node;
+ struct device *dev;
+ int num;
+};
+
+#define to_raid_internal(tmpl) container_of(tmpl, struct raid_internal, r)
+
+#define tc_to_raid_internal(tcont) ({ \
+ struct raid_template *r = \
+ container_of(tcont, struct raid_template, raid_attrs); \
+ to_raid_internal(r); \
+})
+
+#define ac_to_raid_internal(acont) ({ \
+ struct transport_container *tc = \
+ container_of(acont, struct transport_container, ac); \
+ tc_to_raid_internal(tc); \
+})
+
+#define class_device_to_raid_internal(cdev) ({ \
+ struct attribute_container *ac = \
+ attribute_container_classdev_to_container(cdev); \
+ ac_to_raid_internal(ac); \
+})
+
+
+static int raid_match(struct attribute_container *cont, struct device *dev)
+{
+ /* We have to look for every subsystem that could house
+ * emulated RAID devices, so start with SCSI */
+ struct raid_internal *i = ac_to_raid_internal(cont);
+
+ if (scsi_is_sdev_device(dev)) {
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (i->f->cookie != sdev->host->hostt)
+ return 0;
+
+ return i->f->is_raid(dev);
+ }
+ /* FIXME: look at other subsystems too */
+ return 0;
+}
+
+static int raid_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct raid_data *rd;
+
+ BUG_ON(class_get_devdata(cdev));
+
+ rd = kmalloc(sizeof(*rd), GFP_KERNEL);
+ if (!rd)
+ return -ENOMEM;
+
+ memset(rd, 0, sizeof(*rd));
+ INIT_LIST_HEAD(&rd->component_list);
+ class_set_devdata(cdev, rd);
+
+ return 0;
+}
+
+static int raid_remove(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct raid_data *rd = class_get_devdata(cdev);
+ struct raid_component *rc, *next;
+ class_set_devdata(cdev, NULL);
+ list_for_each_entry_safe(rc, next, &rd->component_list, node) {
+ char buf[40];
+ snprintf(buf, sizeof(buf), "component-%d", rc->num);
+ list_del(&rc->node);
+ sysfs_remove_link(&cdev->kobj, buf);
+ kfree(rc);
+ }
+ kfree(class_get_devdata(cdev));
+ return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(raid_class,
+ "raid_devices",
+ raid_setup,
+ raid_remove,
+ NULL);
+
+static struct {
+ enum raid_state value;
+ char *name;
+} raid_states[] = {
+ { RAID_ACTIVE, "active" },
+ { RAID_DEGRADED, "degraded" },
+ { RAID_RESYNCING, "resyncing" },
+ { RAID_OFFLINE, "offline" },
+};
+
+static const char *raid_state_name(enum raid_state state)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) {
+ if (raid_states[i].value == state) {
+ name = raid_states[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
+
+#define raid_attr_show_internal(attr, fmt, var, code) \
+static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \
+{ \
+ struct raid_data *rd = class_get_devdata(cdev); \
+ code \
+ return snprintf(buf, 20, #fmt "\n", var); \
+}
+
+#define raid_attr_ro_states(attr, states, code) \
+raid_attr_show_internal(attr, %s, name, \
+ const char *name; \
+ code \
+ name = raid_##states##_name(rd->attr); \
+) \
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+
+#define raid_attr_ro_internal(attr, code) \
+raid_attr_show_internal(attr, %d, rd->attr, code) \
+static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+#define ATTR_CODE(attr) \
+ struct raid_internal *i = class_device_to_raid_internal(cdev); \
+ if (i->f->get_##attr) \
+ i->f->get_##attr(cdev->dev);
+
+#define raid_attr_ro(attr) raid_attr_ro_internal(attr, )
+#define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr))
+#define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
+
+raid_attr_ro(level);
+raid_attr_ro_fn(resync);
+raid_attr_ro_state(state);
+
+void raid_component_add(struct raid_template *r,struct device *raid_dev,
+ struct device *component_dev)
+{
+ struct class_device *cdev =
+ attribute_container_find_class_device(&r->raid_attrs.ac,
+ raid_dev);
+ struct raid_component *rc;
+ struct raid_data *rd = class_get_devdata(cdev);
+ char buf[40];
+
+ rc = kmalloc(sizeof(*rc), GFP_KERNEL);
+ if (!rc)
+ return;
+
+ INIT_LIST_HEAD(&rc->node);
+ rc->dev = component_dev;
+ rc->num = rd->component_count++;
+
+ snprintf(buf, sizeof(buf), "component-%d", rc->num);
+ list_add_tail(&rc->node, &rd->component_list);
+ sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf);
+}
+EXPORT_SYMBOL(raid_component_add);
+
+struct raid_template *
+raid_class_attach(struct raid_function_template *ft)
+{
+ struct raid_internal *i = kmalloc(sizeof(struct raid_internal),
+ GFP_KERNEL);
+ int count = 0;
+
+ if (unlikely(!i))
+ return NULL;
+
+ memset(i, 0, sizeof(*i));
+
+ i->f = ft;
+
+ i->r.raid_attrs.ac.class = &raid_class.class;
+ i->r.raid_attrs.ac.match = raid_match;
+ i->r.raid_attrs.ac.attrs = &i->attrs[0];
+
+ attribute_container_register(&i->r.raid_attrs.ac);
+
+ i->attrs[count++] = &class_device_attr_level;
+ i->attrs[count++] = &class_device_attr_resync;
+ i->attrs[count++] = &class_device_attr_state;
+
+ i->attrs[count] = NULL;
+ BUG_ON(count > RAID_NUM_ATTRS);
+
+ return &i->r;
+}
+EXPORT_SYMBOL(raid_class_attach);
+
+void
+raid_class_release(struct raid_template *r)
+{
+ struct raid_internal *i = to_raid_internal(r);
+
+ attribute_container_unregister(&i->r.raid_attrs.ac);
+
+ kfree(i);
+}
+EXPORT_SYMBOL(raid_class_release);
+
+static __init int raid_init(void)
+{
+ return transport_class_register(&raid_class);
+}
+
+static __exit void raid_exit(void)
+{
+ transport_class_unregister(&raid_class);
+}
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("RAID device class");
+MODULE_LICENSE("GPL");
+
+module_init(raid_init);
+module_exit(raid_exit);
+
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
new file mode 100644
index 000000000000..46dbdee79f77
--- /dev/null
+++ b/drivers/scsi/sata_mv.c
@@ -0,0 +1,1575 @@
+/*
+ * sata_mv.c - Marvell SATA support
+ *
+ * Copyright 2005: EMC Corporation, all rights reserved.
+ *
+ * Please ALWAYS copy linux-ide@vger.kernel.org on emails.
+ *
+ * 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME "sata_mv"
+#define DRV_VERSION "0.25"
+
+enum {
+ /* BAR's are enumerated in terms of pci_resource_start() terms */
+ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */
+ MV_IO_BAR = 2, /* offset 0x18: IO space */
+ MV_MISC_BAR = 3, /* offset 0x1c: FLASH, NVRAM, SRAM */
+
+ MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */
+ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */
+
+ MV_PCI_REG_BASE = 0,
+ MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
+ MV_SATAHC0_REG_BASE = 0x20000,
+
+ MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ,
+ MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ,
+ MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */
+ MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ,
+
+ MV_USE_Q_DEPTH = ATA_DEF_QUEUE,
+
+ MV_MAX_Q_DEPTH = 32,
+ MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1,
+
+ /* CRQB needs alignment on a 1KB boundary. Size == 1KB
+ * CRPB needs alignment on a 256B boundary. Size == 256B
+ * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
+ * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
+ */
+ MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH),
+ MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH),
+ MV_MAX_SG_CT = 176,
+ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
+ MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
+
+ /* Our DMA boundary is determined by an ePRD being unable to handle
+ * anything larger than 64KB
+ */
+ MV_DMA_BOUNDARY = 0xffffU,
+
+ MV_PORTS_PER_HC = 4,
+ /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
+ MV_PORT_HC_SHIFT = 2,
+ /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
+ MV_PORT_MASK = 3,
+
+ /* Host Flags */
+ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
+ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
+ MV_FLAG_GLBL_SFT_RST = (1 << 28), /* Global Soft Reset support */
+ MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+ MV_6XXX_FLAGS = (MV_FLAG_IRQ_COALESCE |
+ MV_FLAG_GLBL_SFT_RST),
+
+ chip_504x = 0,
+ chip_508x = 1,
+ chip_604x = 2,
+ chip_608x = 3,
+
+ CRQB_FLAG_READ = (1 << 0),
+ CRQB_TAG_SHIFT = 1,
+ CRQB_CMD_ADDR_SHIFT = 8,
+ CRQB_CMD_CS = (0x2 << 11),
+ CRQB_CMD_LAST = (1 << 15),
+
+ CRPB_FLAG_STATUS_SHIFT = 8,
+
+ EPRD_FLAG_END_OF_TBL = (1 << 31),
+
+ /* PCI interface registers */
+
+ PCI_COMMAND_OFS = 0xc00,
+
+ PCI_MAIN_CMD_STS_OFS = 0xd30,
+ STOP_PCI_MASTER = (1 << 2),
+ PCI_MASTER_EMPTY = (1 << 3),
+ GLOB_SFT_RST = (1 << 4),
+
+ PCI_IRQ_CAUSE_OFS = 0x1d58,
+ PCI_IRQ_MASK_OFS = 0x1d5c,
+ PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */
+
+ HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
+ HC_MAIN_IRQ_MASK_OFS = 0x1d64,
+ PORT0_ERR = (1 << 0), /* shift by port # */
+ PORT0_DONE = (1 << 1), /* shift by port # */
+ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
+ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */
+ PCI_ERR = (1 << 18),
+ TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */
+ TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */
+ PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */
+ GPIO_INT = (1 << 22),
+ SELF_INT = (1 << 23),
+ TWSI_INT = (1 << 24),
+ HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
+ HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
+ PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
+ HC_MAIN_RSVD),
+
+ /* SATAHC registers */
+ HC_CFG_OFS = 0,
+
+ HC_IRQ_CAUSE_OFS = 0x14,
+ CRPB_DMA_DONE = (1 << 0), /* shift by port # */
+ HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */
+ DEV_IRQ = (1 << 8), /* shift by port # */
+
+ /* Shadow block registers */
+ SHD_BLK_OFS = 0x100,
+ SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */
+
+ /* SATA registers */
+ SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
+ SATA_ACTIVE_OFS = 0x350,
+
+ /* Port registers */
+ EDMA_CFG_OFS = 0,
+ EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */
+ EDMA_CFG_NCQ = (1 << 5),
+ EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
+ EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
+ EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
+
+ EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
+ EDMA_ERR_IRQ_MASK_OFS = 0xc,
+ EDMA_ERR_D_PAR = (1 << 0),
+ EDMA_ERR_PRD_PAR = (1 << 1),
+ EDMA_ERR_DEV = (1 << 2),
+ EDMA_ERR_DEV_DCON = (1 << 3),
+ EDMA_ERR_DEV_CON = (1 << 4),
+ EDMA_ERR_SERR = (1 << 5),
+ EDMA_ERR_SELF_DIS = (1 << 7),
+ EDMA_ERR_BIST_ASYNC = (1 << 8),
+ EDMA_ERR_CRBQ_PAR = (1 << 9),
+ EDMA_ERR_CRPB_PAR = (1 << 10),
+ EDMA_ERR_INTRL_PAR = (1 << 11),
+ EDMA_ERR_IORDY = (1 << 12),
+ EDMA_ERR_LNK_CTRL_RX = (0xf << 13),
+ EDMA_ERR_LNK_CTRL_RX_2 = (1 << 15),
+ EDMA_ERR_LNK_DATA_RX = (0xf << 17),
+ EDMA_ERR_LNK_CTRL_TX = (0x1f << 21),
+ EDMA_ERR_LNK_DATA_TX = (0x1f << 26),
+ EDMA_ERR_TRANS_PROTO = (1 << 31),
+ EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+ EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
+ EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
+ EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
+ EDMA_ERR_LNK_DATA_RX |
+ EDMA_ERR_LNK_DATA_TX |
+ EDMA_ERR_TRANS_PROTO),
+
+ EDMA_REQ_Q_BASE_HI_OFS = 0x10,
+ EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */
+ EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
+
+ EDMA_REQ_Q_OUT_PTR_OFS = 0x18,
+ EDMA_REQ_Q_PTR_SHIFT = 5,
+
+ EDMA_RSP_Q_BASE_HI_OFS = 0x1c,
+ EDMA_RSP_Q_IN_PTR_OFS = 0x20,
+ EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */
+ EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
+ EDMA_RSP_Q_PTR_SHIFT = 3,
+
+ EDMA_CMD_OFS = 0x28,
+ EDMA_EN = (1 << 0),
+ EDMA_DS = (1 << 1),
+ ATA_RST = (1 << 2),
+
+ /* Host private flags (hp_flags) */
+ MV_HP_FLAG_MSI = (1 << 0),
+
+ /* Port private flags (pp_flags) */
+ MV_PP_FLAG_EDMA_EN = (1 << 0),
+ MV_PP_FLAG_EDMA_DS_ACT = (1 << 1),
+};
+
+/* Command ReQuest Block: 32B */
+struct mv_crqb {
+ u32 sg_addr;
+ u32 sg_addr_hi;
+ u16 ctrl_flags;
+ u16 ata_cmd[11];
+};
+
+/* Command ResPonse Block: 8B */
+struct mv_crpb {
+ u16 id;
+ u16 flags;
+ u32 tmstmp;
+};
+
+/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
+struct mv_sg {
+ u32 addr;
+ u32 flags_size;
+ u32 addr_hi;
+ u32 reserved;
+};
+
+struct mv_port_priv {
+ struct mv_crqb *crqb;
+ dma_addr_t crqb_dma;
+ struct mv_crpb *crpb;
+ dma_addr_t crpb_dma;
+ struct mv_sg *sg_tbl;
+ dma_addr_t sg_tbl_dma;
+
+ unsigned req_producer; /* cp of req_in_ptr */
+ unsigned rsp_consumer; /* cp of rsp_out_ptr */
+ u32 pp_flags;
+};
+
+struct mv_host_priv {
+ u32 hp_flags;
+};
+
+static void mv_irq_clear(struct ata_port *ap);
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static void mv_phy_reset(struct ata_port *ap);
+static void mv_host_stop(struct ata_host_set *host_set);
+static int mv_port_start(struct ata_port *ap);
+static void mv_port_stop(struct ata_port *ap);
+static void mv_qc_prep(struct ata_queued_cmd *qc);
+static int mv_qc_issue(struct ata_queued_cmd *qc);
+static irqreturn_t mv_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs);
+static void mv_eng_timeout(struct ata_port *ap);
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static Scsi_Host_Template mv_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = MV_USE_Q_DEPTH,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = MV_MAX_SG_CT,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = MV_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+ .ordered_flush = 1,
+};
+
+static const struct ata_port_operations mv_ops = {
+ .port_disable = ata_port_disable,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+
+ .phy_reset = mv_phy_reset,
+
+ .qc_prep = mv_qc_prep,
+ .qc_issue = mv_qc_issue,
+
+ .eng_timeout = mv_eng_timeout,
+
+ .irq_handler = mv_interrupt,
+ .irq_clear = mv_irq_clear,
+
+ .scr_read = mv_scr_read,
+ .scr_write = mv_scr_write,
+
+ .port_start = mv_port_start,
+ .port_stop = mv_port_stop,
+ .host_stop = mv_host_stop,
+};
+
+static struct ata_port_info mv_port_info[] = {
+ { /* chip_504x */
+ .sht = &mv_sht,
+ .host_flags = MV_COMMON_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_508x */
+ .sht = &mv_sht,
+ .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_604x */
+ .sht = &mv_sht,
+ .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
+ .port_ops = &mv_ops,
+ },
+ { /* chip_608x */
+ .sht = &mv_sht,
+ .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+ MV_FLAG_DUAL_HC),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
+ .port_ops = &mv_ops,
+ },
+};
+
+static struct pci_device_id mv_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
+
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
+ {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
+ {} /* terminate list */
+};
+
+static struct pci_driver mv_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = mv_pci_tbl,
+ .probe = mv_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+/*
+ * Functions
+ */
+
+static inline void writelfl(unsigned long data, void __iomem *addr)
+{
+ writel(data, addr);
+ (void) readl(addr); /* flush to avoid PCI posted write */
+}
+
+static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+{
+ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+}
+
+static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
+{
+ return (mv_hc_base(base, port >> MV_PORT_HC_SHIFT) +
+ MV_SATAHC_ARBTR_REG_SZ +
+ ((port & MV_PORT_MASK) * MV_PORT_REG_SZ));
+}
+
+static inline void __iomem *mv_ap_base(struct ata_port *ap)
+{
+ return mv_port_base(ap->host_set->mmio_base, ap->port_no);
+}
+
+static inline int mv_get_hc_count(unsigned long hp_flags)
+{
+ return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+}
+
+static void mv_irq_clear(struct ata_port *ap)
+{
+}
+
+/**
+ * mv_start_dma - Enable eDMA engine
+ * @base: port base address
+ * @pp: port private data
+ *
+ * Verify the local cache of the eDMA state is accurate with an
+ * assert.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+{
+ if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+ writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+ pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+ }
+ assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
+}
+
+/**
+ * mv_stop_dma - Disable eDMA engine
+ * @ap: ATA channel to manipulate
+ *
+ * Verify the local cache of the eDMA state is accurate with an
+ * assert.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_stop_dma(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+ u32 reg;
+ int i;
+
+ if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+ /* Disable EDMA if active. The disable bit auto clears.
+ */
+ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ } else {
+ assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+ }
+
+ /* now properly wait for the eDMA to stop */
+ for (i = 1000; i > 0; i--) {
+ reg = readl(port_mmio + EDMA_CMD_OFS);
+ if (!(EDMA_EN & reg)) {
+ break;
+ }
+ udelay(100);
+ }
+
+ if (EDMA_EN & reg) {
+ printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+ /* FIXME: Consider doing a reset here to recover */
+ }
+}
+
+#ifdef ATA_DEBUG
+static void mv_dump_mem(void __iomem *start, unsigned bytes)
+{
+ int b, w;
+ for (b = 0; b < bytes; ) {
+ DPRINTK("%p: ", start + b);
+ for (w = 0; b < bytes && w < 4; w++) {
+ printk("%08x ",readl(start + b));
+ b += sizeof(u32);
+ }
+ printk("\n");
+ }
+}
+#endif
+
+static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
+{
+#ifdef ATA_DEBUG
+ int b, w;
+ u32 dw;
+ for (b = 0; b < bytes; ) {
+ DPRINTK("%02x: ", b);
+ for (w = 0; b < bytes && w < 4; w++) {
+ (void) pci_read_config_dword(pdev,b,&dw);
+ printk("%08x ",dw);
+ b += sizeof(u32);
+ }
+ printk("\n");
+ }
+#endif
+}
+static void mv_dump_all_regs(void __iomem *mmio_base, int port,
+ struct pci_dev *pdev)
+{
+#ifdef ATA_DEBUG
+ void __iomem *hc_base = mv_hc_base(mmio_base,
+ port >> MV_PORT_HC_SHIFT);
+ void __iomem *port_base;
+ int start_port, num_ports, p, start_hc, num_hcs, hc;
+
+ if (0 > port) {
+ start_hc = start_port = 0;
+ num_ports = 8; /* shld be benign for 4 port devs */
+ num_hcs = 2;
+ } else {
+ start_hc = port >> MV_PORT_HC_SHIFT;
+ start_port = port;
+ num_ports = num_hcs = 1;
+ }
+ DPRINTK("All registers for port(s) %u-%u:\n", start_port,
+ num_ports > 1 ? num_ports - 1 : start_port);
+
+ if (NULL != pdev) {
+ DPRINTK("PCI config space regs:\n");
+ mv_dump_pci_cfg(pdev, 0x68);
+ }
+ DPRINTK("PCI regs:\n");
+ mv_dump_mem(mmio_base+0xc00, 0x3c);
+ mv_dump_mem(mmio_base+0xd00, 0x34);
+ mv_dump_mem(mmio_base+0xf00, 0x4);
+ mv_dump_mem(mmio_base+0x1d00, 0x6c);
+ for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
+ hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+ DPRINTK("HC regs (HC %i):\n", hc);
+ mv_dump_mem(hc_base, 0x1c);
+ }
+ for (p = start_port; p < start_port + num_ports; p++) {
+ port_base = mv_port_base(mmio_base, p);
+ DPRINTK("EDMA regs (port %i):\n",p);
+ mv_dump_mem(port_base, 0x54);
+ DPRINTK("SATA regs (port %i):\n",p);
+ mv_dump_mem(port_base+0x300, 0x60);
+ }
+#endif
+}
+
+static unsigned int mv_scr_offset(unsigned int sc_reg_in)
+{
+ unsigned int ofs;
+
+ switch (sc_reg_in) {
+ case SCR_STATUS:
+ case SCR_CONTROL:
+ case SCR_ERROR:
+ ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32));
+ break;
+ case SCR_ACTIVE:
+ ofs = SATA_ACTIVE_OFS; /* active is not with the others */
+ break;
+ default:
+ ofs = 0xffffffffU;
+ break;
+ }
+ return ofs;
+}
+
+static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
+{
+ unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+ if (0xffffffffU != ofs) {
+ return readl(mv_ap_base(ap) + ofs);
+ } else {
+ return (u32) ofs;
+ }
+}
+
+static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+{
+ unsigned int ofs = mv_scr_offset(sc_reg_in);
+
+ if (0xffffffffU != ofs) {
+ writelfl(val, mv_ap_base(ap) + ofs);
+ }
+}
+
+/**
+ * mv_global_soft_reset - Perform the 6xxx global soft reset
+ * @mmio_base: base address of the HBA
+ *
+ * This routine only applies to 6xxx parts.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_global_soft_reset(void __iomem *mmio_base)
+{
+ void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS;
+ int i, rc = 0;
+ u32 t;
+
+ /* Following procedure defined in PCI "main command and status
+ * register" table.
+ */
+ t = readl(reg);
+ writel(t | STOP_PCI_MASTER, reg);
+
+ for (i = 0; i < 1000; i++) {
+ udelay(1);
+ t = readl(reg);
+ if (PCI_MASTER_EMPTY & t) {
+ break;
+ }
+ }
+ if (!(PCI_MASTER_EMPTY & t)) {
+ printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
+ rc = 1;
+ goto done;
+ }
+
+ /* set reset */
+ i = 5;
+ do {
+ writel(t | GLOB_SFT_RST, reg);
+ t = readl(reg);
+ udelay(1);
+ } while (!(GLOB_SFT_RST & t) && (i-- > 0));
+
+ if (!(GLOB_SFT_RST & t)) {
+ printk(KERN_ERR DRV_NAME ": can't set global reset\n");
+ rc = 1;
+ goto done;
+ }
+
+ /* clear reset and *reenable the PCI master* (not mentioned in spec) */
+ i = 5;
+ do {
+ writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
+ t = readl(reg);
+ udelay(1);
+ } while ((GLOB_SFT_RST & t) && (i-- > 0));
+
+ if (GLOB_SFT_RST & t) {
+ printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
+ rc = 1;
+ }
+done:
+ return rc;
+}
+
+/**
+ * mv_host_stop - Host specific cleanup/stop routine.
+ * @host_set: host data structure
+ *
+ * Disable ints, cleanup host memory, call general purpose
+ * host_stop.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_host_stop(struct ata_host_set *host_set)
+{
+ struct mv_host_priv *hpriv = host_set->private_data;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+ if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
+ pci_disable_msi(pdev);
+ } else {
+ pci_intx(pdev, 0);
+ }
+ kfree(hpriv);
+ ata_host_stop(host_set);
+}
+
+/**
+ * mv_port_start - Port specific init/start routine.
+ * @ap: ATA channel to manipulate
+ *
+ * Allocate and point to DMA memory, init port private memory,
+ * zero indices.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct mv_port_priv *pp;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ void *mem;
+ dma_addr_t mem_dma;
+
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp) {
+ return -ENOMEM;
+ }
+ memset(pp, 0, sizeof(*pp));
+
+ mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
+ GFP_KERNEL);
+ if (!mem) {
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+
+ /* First item in chunk of DMA memory:
+ * 32-slot command request table (CRQB), 32 bytes each in size
+ */
+ pp->crqb = mem;
+ pp->crqb_dma = mem_dma;
+ mem += MV_CRQB_Q_SZ;
+ mem_dma += MV_CRQB_Q_SZ;
+
+ /* Second item:
+ * 32-slot command response table (CRPB), 8 bytes each in size
+ */
+ pp->crpb = mem;
+ pp->crpb_dma = mem_dma;
+ mem += MV_CRPB_Q_SZ;
+ mem_dma += MV_CRPB_Q_SZ;
+
+ /* Third item:
+ * Table of scatter-gather descriptors (ePRD), 16 bytes each
+ */
+ pp->sg_tbl = mem;
+ pp->sg_tbl_dma = mem_dma;
+
+ writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT |
+ EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
+
+ writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+ writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+ writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+ writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+ writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
+ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ pp->req_producer = pp->rsp_consumer = 0;
+
+ /* Don't turn on EDMA here...do it before DMA commands only. Else
+ * we'll be unable to send non-data, PIO, etc due to restricted access
+ * to shadow regs.
+ */
+ ap->private_data = pp;
+ return 0;
+}
+
+/**
+ * mv_port_stop - Port specific cleanup/stop routine.
+ * @ap: ATA channel to manipulate
+ *
+ * Stop DMA, cleanup port memory.
+ *
+ * LOCKING:
+ * This routine uses the host_set lock to protect the DMA stop.
+ */
+static void mv_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct mv_port_priv *pp = ap->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ mv_stop_dma(ap);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ ap->private_data = NULL;
+ dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
+ kfree(pp);
+}
+
+/**
+ * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
+ * @qc: queued command whose SG list to source from
+ *
+ * Populate the SG list and mark the last entry.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct mv_port_priv *pp = qc->ap->private_data;
+ unsigned int i;
+
+ for (i = 0; i < qc->n_elem; i++) {
+ u32 sg_len;
+ dma_addr_t addr;
+
+ addr = sg_dma_address(&qc->sg[i]);
+ sg_len = sg_dma_len(&qc->sg[i]);
+
+ pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
+ pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+ assert(0 == (sg_len & ~MV_DMA_BOUNDARY));
+ pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len);
+ }
+ if (0 < qc->n_elem) {
+ pp->sg_tbl[qc->n_elem - 1].flags_size |=
+ cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+ }
+}
+
+static inline unsigned mv_inc_q_index(unsigned *index)
+{
+ *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
+ return *index;
+}
+
+static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+{
+ *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+ (last ? CRQB_CMD_LAST : 0);
+}
+
+/**
+ * mv_qc_prep - Host specific command preparation.
+ * @qc: queued command to prepare
+ *
+ * This routine simply redirects to the general purpose routine
+ * if command is not DMA. Else, it handles prep of the CRQB
+ * (command request block), does some sanity checking, and calls
+ * the SG load routine.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct mv_port_priv *pp = ap->private_data;
+ u16 *cw;
+ struct ata_taskfile *tf;
+ u16 flags = 0;
+
+ if (ATA_PROT_DMA != qc->tf.protocol) {
+ return;
+ }
+
+ /* the req producer index should be the same as we remember it */
+ assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
+ EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->req_producer);
+
+ /* Fill in command request block
+ */
+ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+ flags |= CRQB_FLAG_READ;
+ }
+ assert(MV_MAX_Q_DEPTH > qc->tag);
+ flags |= qc->tag << CRQB_TAG_SHIFT;
+
+ pp->crqb[pp->req_producer].sg_addr =
+ cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+ pp->crqb[pp->req_producer].sg_addr_hi =
+ cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+ pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+
+ cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+ tf = &qc->tf;
+
+ /* Sadly, the CRQB cannot accomodate all registers--there are
+ * only 11 bytes...so we must pick and choose required
+ * registers based on the command. So, we drop feature and
+ * hob_feature for [RW] DMA commands, but they are needed for
+ * NCQ. NCQ will drop hob_nsect.
+ */
+ switch (tf->command) {
+ case ATA_CMD_READ:
+ case ATA_CMD_READ_EXT:
+ case ATA_CMD_WRITE:
+ case ATA_CMD_WRITE_EXT:
+ mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
+ break;
+#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */
+ case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_FPDMA_WRITE:
+ mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
+ mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
+ break;
+#endif /* FIXME: remove this line when NCQ added */
+ default:
+ /* The only other commands EDMA supports in non-queued and
+ * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
+ * of which are defined/used by Linux. If we get here, this
+ * driver needs work.
+ *
+ * FIXME: modify libata to give qc_prep a return value and
+ * return error here.
+ */
+ BUG_ON(tf->command);
+ break;
+ }
+ mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
+ mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
+ mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
+ mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
+ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */
+
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
+ return;
+ }
+ mv_fill_sg(qc);
+}
+
+/**
+ * mv_qc_issue - Initiate a command to the host
+ * @qc: queued command to start
+ *
+ * This routine simply redirects to the general purpose routine
+ * if command is not DMA. Else, it sanity checks our local
+ * caches of the request producer/consumer indices then enables
+ * DMA and bumps the request producer index.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_qc_issue(struct ata_queued_cmd *qc)
+{
+ void __iomem *port_mmio = mv_ap_base(qc->ap);
+ struct mv_port_priv *pp = qc->ap->private_data;
+ u32 in_ptr;
+
+ if (ATA_PROT_DMA != qc->tf.protocol) {
+ /* We're about to send a non-EDMA capable command to the
+ * port. Turn off EDMA so there won't be problems accessing
+ * shadow block, etc registers.
+ */
+ mv_stop_dma(qc->ap);
+ return ata_qc_issue_prot(qc);
+ }
+
+ in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ /* the req producer index should be the same as we remember it */
+ assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->req_producer);
+ /* until we do queuing, the queue should be empty at this point */
+ assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
+ EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+ mv_inc_q_index(&pp->req_producer); /* now incr producer index */
+
+ mv_start_dma(port_mmio, pp);
+
+ /* and write the request in pointer to kick the EDMA to life */
+ in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
+ in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+ writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ return 0;
+}
+
+/**
+ * mv_get_crpb_status - get status from most recently completed cmd
+ * @ap: ATA channel to manipulate
+ *
+ * This routine is for use when the port is in DMA mode, when it
+ * will be using the CRPB (command response block) method of
+ * returning command completion information. We assert indices
+ * are good, grab status, and bump the response consumer index to
+ * prove that we're up to date.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static u8 mv_get_crpb_status(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+ u32 out_ptr;
+
+ out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ /* the response consumer index should be the same as we remember it */
+ assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->rsp_consumer);
+
+ /* increment our consumer index... */
+ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+
+ /* and, until we do NCQ, there should only be 1 CRPB waiting */
+ assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
+ EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ pp->rsp_consumer);
+
+ /* write out our inc'd consumer index so EDMA knows we're caught up */
+ out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
+ out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+ writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+ /* Return ATA status register for completed CRPB */
+ return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
+}
+
+/**
+ * mv_err_intr - Handle error interrupts on the port
+ * @ap: ATA channel to manipulate
+ *
+ * In most cases, just clear the interrupt and move on. However,
+ * some cases require an eDMA reset, which is done right before
+ * the COMRESET in mv_phy_reset(). The SERR case requires a
+ * clear of pending errors in the SATA SERROR register. Finally,
+ * if the port disabled DMA, update our cached copy to match.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_err_intr(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 edma_err_cause, serr = 0;
+
+ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ if (EDMA_ERR_SERR & edma_err_cause) {
+ serr = scr_read(ap, SCR_ERROR);
+ scr_write_flush(ap, SCR_ERROR, serr);
+ }
+ if (EDMA_ERR_SELF_DIS & edma_err_cause) {
+ struct mv_port_priv *pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ }
+ DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
+ "SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
+
+ /* Clear EDMA now that SERR cleanup done */
+ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* check for fatal here and recover if needed */
+ if (EDMA_ERR_FATAL & edma_err_cause) {
+ mv_phy_reset(ap);
+ }
+}
+
+/**
+ * mv_host_intr - Handle all interrupts on the given host controller
+ * @host_set: host specific structure
+ * @relevant: port error bits relevant to this host controller
+ * @hc: which host controller we're to look at
+ *
+ * Read then write clear the HC interrupt status then walk each
+ * port connected to the HC and see if it needs servicing. Port
+ * success ints are reported in the HC interrupt status reg, the
+ * port error ints are reported in the higher level main
+ * interrupt status register and thus are passed in via the
+ * 'relevant' argument.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
+ unsigned int hc)
+{
+ void __iomem *mmio = host_set->mmio_base;
+ void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+ struct ata_port *ap;
+ struct ata_queued_cmd *qc;
+ u32 hc_irq_cause;
+ int shift, port, port0, hard_port, handled;
+ unsigned int err_mask;
+ u8 ata_status = 0;
+
+ if (hc == 0) {
+ port0 = 0;
+ } else {
+ port0 = MV_PORTS_PER_HC;
+ }
+
+ /* we'll need the HC success int register in most cases */
+ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+ if (hc_irq_cause) {
+ writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+ }
+
+ VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
+ hc,relevant,hc_irq_cause);
+
+ for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
+ ap = host_set->ports[port];
+ hard_port = port & MV_PORT_MASK; /* range 0-3 */
+ handled = 0; /* ensure ata_status is set if handled++ */
+
+ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+ /* new CRPB on the queue; just one at a time until NCQ
+ */
+ ata_status = mv_get_crpb_status(ap);
+ handled++;
+ } else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+ /* received ATA IRQ; read the status reg to clear INTRQ
+ */
+ ata_status = readb((void __iomem *)
+ ap->ioaddr.status_addr);
+ handled++;
+ }
+
+ err_mask = ac_err_mask(ata_status);
+
+ shift = port << 1; /* (port * 2) */
+ if (port >= MV_PORTS_PER_HC) {
+ shift++; /* skip bit 8 in the HC Main IRQ reg */
+ }
+ if ((PORT0_ERR << shift) & relevant) {
+ mv_err_intr(ap);
+ err_mask |= AC_ERR_OTHER;
+ handled++;
+ }
+
+ if (handled && ap) {
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (NULL != qc) {
+ VPRINTK("port %u IRQ found for qc, "
+ "ata_status 0x%x\n", port,ata_status);
+ /* mark qc status appropriately */
+ ata_qc_complete(qc, err_mask);
+ }
+ }
+ }
+ VPRINTK("EXIT\n");
+}
+
+/**
+ * mv_interrupt -
+ * @irq: unused
+ * @dev_instance: private data; in this case the host structure
+ * @regs: unused
+ *
+ * Read the read only register to determine if any host
+ * controllers have pending interrupts. If so, call lower level
+ * routine to handle. Also check for PCI errors which are only
+ * reported here.
+ *
+ * LOCKING:
+ * This routine holds the host_set lock while processing pending
+ * interrupts.
+ */
+static irqreturn_t mv_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ unsigned int hc, handled = 0, n_hcs;
+ void __iomem *mmio = host_set->mmio_base;
+ u32 irq_stat;
+
+ irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
+
+ /* check the cases where we either have nothing pending or have read
+ * a bogus register value which can indicate HW removal or PCI fault
+ */
+ if (!irq_stat || (0xffffffffU == irq_stat)) {
+ return IRQ_NONE;
+ }
+
+ n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
+ spin_lock(&host_set->lock);
+
+ for (hc = 0; hc < n_hcs; hc++) {
+ u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
+ if (relevant) {
+ mv_host_intr(host_set, relevant, hc);
+ handled++;
+ }
+ }
+ if (PCI_ERR & irq_stat) {
+ printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
+ readl(mmio + PCI_IRQ_CAUSE_OFS));
+
+ DPRINTK("All regs @ PCI error\n");
+ mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
+
+ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+ handled++;
+ }
+ spin_unlock(&host_set->lock);
+
+ return IRQ_RETVAL(handled);
+}
+
+/**
+ * mv_phy_reset - Perform eDMA reset followed by COMRESET
+ * @ap: ATA channel to manipulate
+ *
+ * Part of this is taken from __sata_phy_reset and modified to
+ * not sleep since this routine gets called from interrupt level.
+ *
+ * LOCKING:
+ * Inherited from caller. This is coded to safe to call at
+ * interrupt level, i.e. it does not sleep.
+ */
+static void mv_phy_reset(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct ata_taskfile tf;
+ struct ata_device *dev = &ap->device[0];
+ unsigned long timeout;
+
+ VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
+
+ mv_stop_dma(ap);
+
+ writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+ udelay(25); /* allow reset propagation */
+
+ /* Spec never mentions clearing the bit. Marvell's driver does
+ * clear the bit, however.
+ */
+ writelfl(0, port_mmio + EDMA_CMD_OFS);
+
+ VPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+ /* proceed to init communications via the scr_control reg */
+ scr_write_flush(ap, SCR_CONTROL, 0x301);
+ mdelay(1);
+ scr_write_flush(ap, SCR_CONTROL, 0x300);
+ timeout = jiffies + (HZ * 1);
+ do {
+ mdelay(10);
+ if ((scr_read(ap, SCR_STATUS) & 0xf) != 1)
+ break;
+ } while (time_before(jiffies, timeout));
+
+ VPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+ "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+ mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+ if (sata_dev_present(ap)) {
+ ata_port_probe(ap);
+ } else {
+ printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+ ap->id, scr_read(ap, SCR_STATUS));
+ ata_port_disable(ap);
+ return;
+ }
+ ap->cbl = ATA_CBL_SATA;
+
+ tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
+ tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
+ tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr);
+ tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
+
+ dev->class = ata_dev_classify(&tf);
+ if (!ata_dev_present(dev)) {
+ VPRINTK("Port disabled post-sig: No device present.\n");
+ ata_port_disable(ap);
+ }
+ VPRINTK("EXIT\n");
+}
+
+/**
+ * mv_eng_timeout - Routine called by libata when SCSI times out I/O
+ * @ap: ATA channel to manipulate
+ *
+ * Intent is to clear all pending error conditions, reset the
+ * chip/bus, fail the command, and move on.
+ *
+ * LOCKING:
+ * This routine holds the host_set lock while failing the command.
+ */
+static void mv_eng_timeout(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+
+ printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+ DPRINTK("All regs @ start of eng_timeout\n");
+ mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
+ to_pci_dev(ap->host_set->dev));
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
+ ap->host_set->mmio_base, ap, qc, qc->scsicmd,
+ &qc->scsicmd->cmnd);
+
+ mv_err_intr(ap);
+ mv_phy_reset(ap);
+
+ if (!qc) {
+ printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+ ap->id);
+ } else {
+ /* hack alert! We cannot use the supplied completion
+ * function from inside the ->eh_strategy_handler() thread.
+ * libata is the only user of ->eh_strategy_handler() in
+ * any kernel, so the default scsi_done() assumes it is
+ * not being called from the SCSI EH.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ qc->scsidone = scsi_finish_command;
+ ata_qc_complete(qc, AC_ERR_OTHER);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ }
+}
+
+/**
+ * mv_port_init - Perform some early initialization on a single port.
+ * @port: libata data structure storing shadow register addresses
+ * @port_mmio: base address of the port
+ *
+ * Initialize shadow register mmio addresses, clear outstanding
+ * interrupts on the port, and unmask interrupts for the future
+ * start of the port.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
+{
+ unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+ unsigned serr_ofs;
+
+ /* PIO related setup
+ */
+ port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
+ port->error_addr =
+ port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
+ port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
+ port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
+ port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
+ port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
+ port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
+ port->status_addr =
+ port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
+ /* special case: control/altstatus doesn't have ATA_REG_ address */
+ port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
+
+ /* unused: */
+ port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+
+ /* Clear any currently outstanding port interrupt conditions */
+ serr_ofs = mv_scr_offset(SCR_ERROR);
+ writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
+ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* unmask all EDMA error interrupts */
+ writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
+
+ VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
+ readl(port_mmio + EDMA_CFG_OFS),
+ readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
+ readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
+}
+
+/**
+ * mv_host_init - Perform some early initialization of the host.
+ * @probe_ent: early data struct representing the host
+ *
+ * If possible, do an early global reset of the host. Then do
+ * our port init and clear/unmask all/relevant host interrupts.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_host_init(struct ata_probe_ent *probe_ent)
+{
+ int rc = 0, n_hc, port, hc;
+ void __iomem *mmio = probe_ent->mmio_base;
+ void __iomem *port_mmio;
+
+ if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) &&
+ mv_global_soft_reset(probe_ent->mmio_base)) {
+ rc = 1;
+ goto done;
+ }
+
+ n_hc = mv_get_hc_count(probe_ent->host_flags);
+ probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
+
+ for (port = 0; port < probe_ent->n_ports; port++) {
+ port_mmio = mv_port_base(mmio, port);
+ mv_port_init(&probe_ent->port[port], port_mmio);
+ }
+
+ for (hc = 0; hc < n_hc; hc++) {
+ void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+
+ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
+ "(before clear)=0x%08x\n", hc,
+ readl(hc_mmio + HC_CFG_OFS),
+ readl(hc_mmio + HC_IRQ_CAUSE_OFS));
+
+ /* Clear any currently outstanding hc interrupt conditions */
+ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+ }
+
+ /* Clear any currently outstanding host interrupt conditions */
+ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+ /* and unmask interrupt generation for host regs */
+ writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+ writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
+
+ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
+ "PCI int cause/mask=0x%08x/0x%08x\n",
+ readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
+ readl(mmio + HC_MAIN_IRQ_MASK_OFS),
+ readl(mmio + PCI_IRQ_CAUSE_OFS),
+ readl(mmio + PCI_IRQ_MASK_OFS));
+done:
+ return rc;
+}
+
+/**
+ * mv_print_info - Dump key info to kernel log for perusal.
+ * @probe_ent: early data struct representing the host
+ *
+ * FIXME: complete this.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void mv_print_info(struct ata_probe_ent *probe_ent)
+{
+ struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ struct mv_host_priv *hpriv = probe_ent->private_data;
+ u8 rev_id, scc;
+ const char *scc_s;
+
+ /* Use this to determine the HW stepping of the chip so we know
+ * what errata to workaround
+ */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
+ if (scc == 0)
+ scc_s = "SCSI";
+ else if (scc == 0x01)
+ scc_s = "RAID";
+ else
+ scc_s = "unknown";
+
+ dev_printk(KERN_INFO, &pdev->dev,
+ "%u slots %u ports %s mode IRQ via %s\n",
+ (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
+ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+}
+
+/**
+ * mv_init_one - handle a positive probe of a Marvell host
+ * @pdev: PCI device found
+ * @ent: PCI device ID entry for the matched host
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ struct ata_probe_ent *probe_ent = NULL;
+ struct mv_host_priv *hpriv;
+ unsigned int board_idx = (unsigned int)ent->driver_data;
+ void __iomem *mmio_base;
+ int pci_dev_busy = 0, rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc) {
+ pci_dev_busy = 1;
+ goto err_out;
+ }
+
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
+ if (mmio_base == NULL) {
+ rc = -ENOMEM;
+ goto err_out_free_ent;
+ }
+
+ hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv) {
+ rc = -ENOMEM;
+ goto err_out_iounmap;
+ }
+ memset(hpriv, 0, sizeof(*hpriv));
+
+ probe_ent->sht = mv_port_info[board_idx].sht;
+ probe_ent->host_flags = mv_port_info[board_idx].host_flags;
+ probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
+ probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
+ probe_ent->port_ops = mv_port_info[board_idx].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = mmio_base;
+ probe_ent->private_data = hpriv;
+
+ /* initialize adapter */
+ rc = mv_host_init(probe_ent);
+ if (rc) {
+ goto err_out_hpriv;
+ }
+
+ /* Enable interrupts */
+ if (pci_enable_msi(pdev) == 0) {
+ hpriv->hp_flags |= MV_HP_FLAG_MSI;
+ } else {
+ pci_intx(pdev, 1);
+ }
+
+ mv_dump_pci_cfg(pdev, 0x68);
+ mv_print_info(probe_ent);
+
+ if (ata_device_add(probe_ent) == 0) {
+ rc = -ENODEV; /* No devices discovered */
+ goto err_out_dev_add;
+ }
+
+ kfree(probe_ent);
+ return 0;
+
+err_out_dev_add:
+ if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
+ pci_disable_msi(pdev);
+ } else {
+ pci_intx(pdev, 0);
+ }
+err_out_hpriv:
+ kfree(hpriv);
+err_out_iounmap:
+ pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
+ kfree(probe_ent);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out:
+ if (!pci_dev_busy) {
+ pci_disable_device(pdev);
+ }
+
+ return rc;
+}
+
+static int __init mv_init(void)
+{
+ return pci_module_init(&mv_pci_driver);
+}
+
+static void __exit mv_exit(void)
+{
+ pci_unregister_driver(&mv_pci_driver);
+}
+
+MODULE_AUTHOR("Brett Russ");
+MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(mv_init);
+module_exit(mv_exit);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index b0403ccd8a25..d573888eda76 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -4,21 +4,39 @@
* Copyright 2004 NVIDIA Corp. All rights reserved.
* Copyright 2004 Andrew Chew
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * No hardware documentation available outside of NVIDIA.
+ * This driver programs the NVIDIA SATA controller in a similar
+ * fashion as with other PCI IDE BMDMA controllers, with a few
+ * NV-specific details such as register offsets, SATA phy location,
+ * hotplug info, etc.
+ *
+ * 0.09
+ * - Fixed bug introduced by 0.08's MCP51 and MCP55 support.
+ *
+ * 0.08
+ * - Added support for MCP51 and MCP55.
+ *
+ * 0.07
+ * - Added support for RAID class code.
*
* 0.06
* - Added generic SATA support by using a pci_device_id that filters on
@@ -43,12 +61,13 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#define DRV_NAME "sata_nv"
-#define DRV_VERSION "0.6"
+#define DRV_VERSION "0.8"
#define NV_PORTS 2
#define NV_PIO_MASK 0x1f
@@ -134,9 +153,20 @@ static struct pci_device_id nv_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
{ 0, } /* terminate list */
};
@@ -209,7 +239,7 @@ static Scsi_Host_Template nv_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations nv_ops = {
+static const struct ata_port_operations nv_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -274,7 +304,8 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -301,7 +332,7 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
return 0xffffffffU;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -315,7 +346,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
return;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
else
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -323,6 +354,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static void nv_host_stop (struct ata_host_set *host_set)
{
struct nv_host *host = host_set->private_data;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
// Disable hotplug event interrupts.
if (host->host_desc->disable_hotplug)
@@ -330,7 +362,8 @@ static void nv_host_stop (struct ata_host_set *host_set)
kfree(host);
- ata_host_stop(host_set);
+ if (host_set->mmio_base)
+ pci_iounmap(pdev, host_set->mmio_base);
}
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -351,7 +384,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -373,7 +406,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = -ENOMEM;
ppi = &nv_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
goto err_out_regions;
@@ -392,8 +425,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
unsigned long base;
- probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
if (probe_ent->mmio_base == NULL) {
rc = -EIO;
goto err_out_free_host;
@@ -429,7 +461,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_iounmap:
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
- iounmap(probe_ent->mmio_base);
+ pci_iounmap(pdev, probe_ent->mmio_base);
err_out_free_host:
kfree(host);
err_out_free_ent:
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 5c1d4411457a..b41c977d6fab 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -7,21 +7,26 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware information only available under NDA.
*
*/
@@ -33,6 +38,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -40,7 +46,7 @@
#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "1.01"
+#define DRV_VERSION "1.02"
enum {
@@ -79,13 +85,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
static void pdc_eng_timeout(struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
-static void pdc_phy_reset(struct ata_port *ap);
+static void pdc_pata_phy_reset(struct ata_port *ap);
+static void pdc_sata_phy_reset(struct ata_port *ap);
static void pdc_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_irq_clear(struct ata_port *ap);
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
+
static Scsi_Host_Template pdc_ata_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -106,24 +114,48 @@ static Scsi_Host_Template pdc_ata_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations pdc_ata_ops = {
+static const struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
.dev_select = ata_std_dev_select,
- .phy_reset = pdc_phy_reset,
+
+ .phy_reset = pdc_sata_phy_reset,
+
.qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot,
.eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear,
+
.scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write,
.port_start = pdc_port_start,
.port_stop = pdc_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
+};
+
+static const struct ata_port_operations pdc_pata_ops = {
+ .port_disable = ata_port_disable,
+ .tf_load = pdc_tf_load_mmio,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = pdc_exec_command_mmio,
+ .dev_select = ata_std_dev_select,
+
+ .phy_reset = pdc_pata_phy_reset,
+
+ .qc_prep = pdc_qc_prep,
+ .qc_issue = pdc_qc_issue_prot,
+ .eng_timeout = pdc_eng_timeout,
+ .irq_handler = pdc_interrupt,
+ .irq_clear = pdc_irq_clear,
+
+ .port_start = pdc_port_start,
+ .port_stop = pdc_port_stop,
+ .host_stop = ata_pci_host_stop,
};
static struct ata_port_info pdc_port_info[] = {
@@ -135,7 +167,7 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_sata_ops,
},
/* board_20319 */
@@ -146,7 +178,7 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_sata_ops,
},
/* board_20619 */
@@ -157,13 +189,15 @@ static struct ata_port_info pdc_port_info[] = {
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
- .port_ops = &pdc_ata_ops,
+ .port_ops = &pdc_pata_ops,
},
};
static struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
+ { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -176,11 +210,17 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
+ { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
@@ -248,7 +288,7 @@ static void pdc_port_stop(struct ata_port *ap)
static void pdc_reset_port(struct ata_port *ap)
{
- void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
unsigned int i;
u32 tmp;
@@ -268,17 +308,28 @@ static void pdc_reset_port(struct ata_port *ap)
readl(mmio); /* flush */
}
-static void pdc_phy_reset(struct ata_port *ap)
+static void pdc_sata_phy_reset(struct ata_port *ap)
{
pdc_reset_port(ap);
sata_phy_reset(ap);
}
+static void pdc_pata_phy_reset(struct ata_port *ap)
+{
+ /* FIXME: add cable detect. Don't assume 40-pin cable */
+ ap->cbl = ATA_CBL_PATA40;
+ ap->udma_mask &= ATA_UDMA_MASK_40C;
+
+ pdc_reset_port(ap);
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
+}
+
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -287,7 +338,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -321,11 +372,15 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
static void pdc_eng_timeout(struct ata_port *ap)
{
+ struct ata_host_set *host_set = ap->host_set;
u8 drv_stat;
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -345,7 +400,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
- ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+ drv_stat = ata_wait_idle(ap);
+ ata_qc_complete(qc, __ac_err_mask(drv_stat));
break;
default:
@@ -354,50 +410,48 @@ static void pdc_eng_timeout(struct ata_port *ap)
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
ap->id, qc->tf.command, drv_stat);
- ata_qc_complete(qc, drv_stat);
+ ata_qc_complete(qc, ac_err_mask(drv_stat));
break;
}
out:
+ spin_unlock_irqrestore(&host_set->lock, flags);
DPRINTK("EXIT\n");
}
static inline unsigned int pdc_host_intr( struct ata_port *ap,
struct ata_queued_cmd *qc)
{
- u8 status;
- unsigned int handled = 0, have_err = 0;
+ unsigned int handled = 0, err_mask = 0;
u32 tmp;
- void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
tmp = readl(mmio);
if (tmp & PDC_ERR_MASK) {
- have_err = 1;
+ err_mask = AC_ERR_DEV;
pdc_reset_port(ap);
}
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
- status = ata_wait_idle(ap);
- if (have_err)
- status |= ATA_ERR;
- ata_qc_complete(qc, status);
+ err_mask |= ac_err_mask(ata_wait_idle(ap));
+ ata_qc_complete(qc, err_mask);
handled = 1;
break;
default:
- ap->stats.idle_irq++;
- break;
+ ap->stats.idle_irq++;
+ break;
}
- return handled;
+ return handled;
}
static void pdc_irq_clear(struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
readl(mmio + PDC_INT_SEQMASK);
}
@@ -409,7 +463,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
u32 mask = 0;
unsigned int i, tmp;
unsigned int handled = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
VPRINTK("ENTER\n");
@@ -441,7 +495,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
VPRINTK("port %u\n", i);
ap = host_set->ports[i];
tmp = mask & (1 << (i + 1));
- if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (tmp && ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -471,8 +526,8 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
pp->pkt[2] = seq;
wmb(); /* flush PRD, pkt writes */
- writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+ writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
}
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
@@ -494,7 +549,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -502,7 +557,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -530,7 +585,7 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
{
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
u32 tmp;
/*
@@ -573,13 +628,13 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
@@ -612,8 +667,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 3),
- pci_resource_len(pdev, 3));
+ mmio_base = pci_iomap(pdev, 3, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
diff --git a/drivers/scsi/sata_promise.h b/drivers/scsi/sata_promise.h
index 6e7e96b9ee13..6ee5e190262d 100644
--- a/drivers/scsi/sata_promise.h
+++ b/drivers/scsi/sata_promise.h
@@ -3,21 +3,24 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
*
*/
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 1383e8a28d72..9938dae782b6 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -6,21 +6,24 @@
* Copyright 2005 Pacific Digital Corporation.
* (OSL/GPL code release authorized by Jalil Fadavi).
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
*
*/
@@ -32,6 +35,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <asm/io.h>
@@ -48,8 +52,6 @@ enum {
QS_PRD_BYTES = QS_MAX_PRD * 16,
QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES,
- QS_DMA_BOUNDARY = ~0UL,
-
/* global register offsets */
QS_HCF_CNFG3 = 0x0003, /* host configuration offset */
QS_HID_HPHY = 0x0004, /* host physical interface info */
@@ -98,6 +100,10 @@ enum {
board_2068_idx = 0, /* QStor 4-port SATA/RAID */
};
+enum {
+ QS_DMA_BOUNDARY = ~0UL
+};
+
typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
struct qs_port_priv {
@@ -117,7 +123,7 @@ static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc);
static int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-static void qs_bmdma_stop(struct ata_port *ap);
+static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap);
static void qs_irq_clear(struct ata_port *ap);
static void qs_eng_timeout(struct ata_port *ap);
@@ -142,7 +148,7 @@ static Scsi_Host_Template qs_ata_sht = {
.bios_param = ata_std_bios_param,
};
-static struct ata_port_operations qs_ata_ops = {
+static const struct ata_port_operations qs_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -198,7 +204,7 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
return 1; /* ATAPI DMA not supported */
}
-static void qs_bmdma_stop(struct ata_port *ap)
+static void qs_bmdma_stop(struct ata_queued_cmd *qc)
{
/* nothing */
}
@@ -386,7 +392,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
sff1, sff0, port_no, sHST, sDST);
handled = 1;
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap && !(ap->flags &
+ (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_pkt)
@@ -394,11 +401,12 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
switch (sHST) {
- case 0: /* sucessful CPB */
+ case 0: /* successful CPB */
case 3: /* device error */
pp->state = qs_state_idle;
qs_enter_reg_mode(qc->ap);
- ata_qc_complete(qc, sDST);
+ ata_qc_complete(qc,
+ ac_err_mask(sDST));
break;
default:
break;
@@ -417,7 +425,8 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
struct ata_port *ap;
ap = host_set->ports[port_no];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio)
@@ -426,15 +435,15 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
/* check main status, clearing INTRQ */
- u8 status = ata_chk_status(ap);
+ u8 status = ata_check_status(ap);
if ((status & ATA_BUSY))
continue;
DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
ap->id, qc->tf.protocol, status);
-
+
/* complete taskfile transaction */
pp->state = qs_state_idle;
- ata_qc_complete(qc, status);
+ ata_qc_complete(qc, ac_err_mask(status));
handled = 1;
}
}
@@ -489,7 +498,7 @@ static int qs_port_start(struct ata_port *ap)
if (rc)
return rc;
qs_enter_reg_mode(ap);
- pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) {
rc = -ENOMEM;
goto err_out;
@@ -533,11 +542,12 @@ static void qs_port_stop(struct ata_port *ap)
static void qs_host_stop(struct ata_host_set *host_set)
{
void __iomem *mmio_base = host_set->mmio_base;
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
- ata_host_stop(host_set);
+ pci_iounmap(pdev, mmio_base);
}
static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
@@ -591,25 +601,22 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME
- "(%s): 64-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME
- "(%s): 32-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME
- "(%s): 32-bit consistent DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
@@ -626,7 +633,7 @@ static int qs_ata_init_one(struct pci_dev *pdev,
int rc, port_no;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -641,8 +648,7 @@ static int qs_ata_init_one(struct pci_dev *pdev,
goto err_out_regions;
}
- mmio_base = ioremap(pci_resource_start(pdev, 4),
- pci_resource_len(pdev, 4));
+ mmio_base = pci_iomap(pdev, 4, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_regions;
@@ -692,7 +698,7 @@ static int qs_ata_init_one(struct pci_dev *pdev,
return 0;
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_regions:
pci_release_regions(pdev);
err_out:
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 49ed557a4b66..435f7e0085ec 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -5,24 +5,32 @@
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
- * Copyright 2003 Red Hat, Inc.
+ * Copyright 2003-2005 Red Hat, Inc.
* Copyright 2003 Benjamin Herrenschmidt
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Documentation for SiI 3112:
+ * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ * Other errata and documentation available under NDA.
*
*/
@@ -33,6 +41,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -41,8 +50,11 @@
#define DRV_VERSION "0.9"
enum {
+ SIL_FLAG_MOD15WRITE = (1 << 30),
+
sil_3112 = 0,
- sil_3114 = 1,
+ sil_3112_m15w = 1,
+ sil_3114 = 2,
SIL_FIFO_R0 = 0x40,
SIL_FIFO_W0 = 0x41,
@@ -75,14 +87,15 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void sil_post_set_mode (struct ata_port *ap);
+
static struct pci_device_id sil_pci_tbl[] = {
- { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
- { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
- { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+ { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
{ } /* terminate list */
};
@@ -138,7 +151,7 @@ static Scsi_Host_Template sil_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations sil_ops = {
+static const struct ata_port_operations sil_ops = {
.port_disable = ata_port_disable,
.dev_config = sil_dev_config,
.tf_load = ata_tf_load,
@@ -161,7 +174,7 @@ static struct ata_port_operations sil_ops = {
.scr_write = sil_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static struct ata_port_info sil_port_info[] = {
@@ -174,6 +187,16 @@ static struct ata_port_info sil_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
+ }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+ {
+ .sht = &sil_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SRST | ATA_FLAG_MMIO |
+ SIL_FLAG_MOD15WRITE,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil_ops,
}, /* sil_3114 */
{
.sht = &sil_sht,
@@ -210,6 +233,7 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
u8 cache_line = 0;
@@ -221,7 +245,8 @@ static void sil_post_set_mode (struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
struct ata_device *dev;
- void *addr = host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+ void __iomem *addr =
+ host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
u32 tmp, dev_mode[2];
unsigned int i;
@@ -265,7 +290,7 @@ static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_re
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
- void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+ void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
return readl(mmio);
return 0xffffffffU;
@@ -273,7 +298,7 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
{
- void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+ void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
if (mmio)
writel(val, mmio);
}
@@ -323,15 +348,15 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
while ((len > 0) && (s[len - 1] == ' '))
len--;
- for (n = 0; sil_blacklist[n].product; n++)
+ for (n = 0; sil_blacklist[n].product; n++)
if (!memcmp(sil_blacklist[n].product, s,
strlen(sil_blacklist[n].product))) {
quirks = sil_blacklist[n].quirk;
break;
}
-
+
/* limit requests to 15 sectors */
- if (quirks & SIL_QUIRK_MOD15WRITE) {
+ if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
ap->id, dev->devno);
ap->host->max_sectors = 15;
@@ -354,7 +379,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
int rc;
unsigned int i;
int pci_dev_busy = 0;
@@ -362,7 +387,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
u8 cls;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
@@ -404,8 +429,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
- mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ mmio_base = pci_iomap(pdev, 5, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -440,8 +464,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
writeb(cls, mmio_base + SIL_FIFO_W3);
}
} else
- printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n",
- pci_name(pdev));
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "cache line size not set. Driver may not function\n");
if (ent->driver_data == sil_3114) {
irq_mask = SIL_MASK_4PORT;
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
new file mode 100644
index 000000000000..c66548025657
--- /dev/null
+++ b/drivers/scsi/sata_sil24.c
@@ -0,0 +1,871 @@
+/*
+ * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
+ *
+ * Copyright 2005 Tejun Heo
+ *
+ * Based on preview driver from Silicon Image.
+ *
+ * NOTE: No NCQ/ATAPI support yet. The preview driver didn't support
+ * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
+ * those work. Enabling those shouldn't be difficult. Basic
+ * structure is all there (in libata-dev tree). If you have any
+ * information about this hardware, please contact me or linux-ide.
+ * Info is needed on...
+ *
+ * - How to issue tagged commands and turn on sactive on issue accordingly.
+ * - Where to put an ATAPI command and how to tell the device to send it.
+ * - How to enable/use 64bit.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME "sata_sil24"
+#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */
+
+/*
+ * Port request block (PRB) 32 bytes
+ */
+struct sil24_prb {
+ u16 ctrl;
+ u16 prot;
+ u32 rx_cnt;
+ u8 fis[6 * 4];
+};
+
+/*
+ * Scatter gather entry (SGE) 16 bytes
+ */
+struct sil24_sge {
+ u64 addr;
+ u32 cnt;
+ u32 flags;
+};
+
+/*
+ * Port multiplier
+ */
+struct sil24_port_multiplier {
+ u32 diag;
+ u32 sactive;
+};
+
+enum {
+ /*
+ * Global controller registers (128 bytes @ BAR0)
+ */
+ /* 32 bit regs */
+ HOST_SLOT_STAT = 0x00, /* 32 bit slot stat * 4 */
+ HOST_CTRL = 0x40,
+ HOST_IRQ_STAT = 0x44,
+ HOST_PHY_CFG = 0x48,
+ HOST_BIST_CTRL = 0x50,
+ HOST_BIST_PTRN = 0x54,
+ HOST_BIST_STAT = 0x58,
+ HOST_MEM_BIST_STAT = 0x5c,
+ HOST_FLASH_CMD = 0x70,
+ /* 8 bit regs */
+ HOST_FLASH_DATA = 0x74,
+ HOST_TRANSITION_DETECT = 0x75,
+ HOST_GPIO_CTRL = 0x76,
+ HOST_I2C_ADDR = 0x78, /* 32 bit */
+ HOST_I2C_DATA = 0x7c,
+ HOST_I2C_XFER_CNT = 0x7e,
+ HOST_I2C_CTRL = 0x7f,
+
+ /* HOST_SLOT_STAT bits */
+ HOST_SSTAT_ATTN = (1 << 31),
+
+ /*
+ * Port registers
+ * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
+ */
+ PORT_REGS_SIZE = 0x2000,
+ PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+ PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
+ /* 32 bit regs */
+ PORT_CTRL_STAT = 0x1000, /* write: ctrl-set, read: stat */
+ PORT_CTRL_CLR = 0x1004, /* write: ctrl-clear */
+ PORT_IRQ_STAT = 0x1008, /* high: status, low: interrupt */
+ PORT_IRQ_ENABLE_SET = 0x1010, /* write: enable-set */
+ PORT_IRQ_ENABLE_CLR = 0x1014, /* write: enable-clear */
+ PORT_ACTIVATE_UPPER_ADDR= 0x101c,
+ PORT_EXEC_FIFO = 0x1020, /* command execution fifo */
+ PORT_CMD_ERR = 0x1024, /* command error number */
+ PORT_FIS_CFG = 0x1028,
+ PORT_FIFO_THRES = 0x102c,
+ /* 16 bit regs */
+ PORT_DECODE_ERR_CNT = 0x1040,
+ PORT_DECODE_ERR_THRESH = 0x1042,
+ PORT_CRC_ERR_CNT = 0x1044,
+ PORT_CRC_ERR_THRESH = 0x1046,
+ PORT_HSHK_ERR_CNT = 0x1048,
+ PORT_HSHK_ERR_THRESH = 0x104a,
+ /* 32 bit regs */
+ PORT_PHY_CFG = 0x1050,
+ PORT_SLOT_STAT = 0x1800,
+ PORT_CMD_ACTIVATE = 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
+ PORT_EXEC_DIAG = 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
+ PORT_PSD_DIAG = 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
+ PORT_SCONTROL = 0x1f00,
+ PORT_SSTATUS = 0x1f04,
+ PORT_SERROR = 0x1f08,
+ PORT_SACTIVE = 0x1f0c,
+
+ /* PORT_CTRL_STAT bits */
+ PORT_CS_PORT_RST = (1 << 0), /* port reset */
+ PORT_CS_DEV_RST = (1 << 1), /* device reset */
+ PORT_CS_INIT = (1 << 2), /* port initialize */
+ PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */
+ PORT_CS_RESUME = (1 << 6), /* port resume */
+ PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */
+ PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */
+ PORT_CS_RDY = (1 << 31), /* port ready to accept commands */
+
+ /* PORT_IRQ_STAT/ENABLE_SET/CLR */
+ /* bits[11:0] are masked */
+ PORT_IRQ_COMPLETE = (1 << 0), /* command(s) completed */
+ PORT_IRQ_ERROR = (1 << 1), /* command execution error */
+ PORT_IRQ_PORTRDY_CHG = (1 << 2), /* port ready change */
+ PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */
+ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */
+ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */
+ PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */
+ PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */
+
+ /* bits[27:16] are unmasked (raw) */
+ PORT_IRQ_RAW_SHIFT = 16,
+ PORT_IRQ_MASKED_MASK = 0x7ff,
+ PORT_IRQ_RAW_MASK = (0x7ff << PORT_IRQ_RAW_SHIFT),
+
+ /* ENABLE_SET/CLR specific, intr steering - 2 bit field */
+ PORT_IRQ_STEER_SHIFT = 30,
+ PORT_IRQ_STEER_MASK = (3 << PORT_IRQ_STEER_SHIFT),
+
+ /* PORT_CMD_ERR constants */
+ PORT_CERR_DEV = 1, /* Error bit in D2H Register FIS */
+ PORT_CERR_SDB = 2, /* Error bit in SDB FIS */
+ PORT_CERR_DATA = 3, /* Error in data FIS not detected by dev */
+ PORT_CERR_SEND = 4, /* Initial cmd FIS transmission failure */
+ PORT_CERR_INCONSISTENT = 5, /* Protocol mismatch */
+ PORT_CERR_DIRECTION = 6, /* Data direction mismatch */
+ PORT_CERR_UNDERRUN = 7, /* Ran out of SGEs while writing */
+ PORT_CERR_OVERRUN = 8, /* Ran out of SGEs while reading */
+ PORT_CERR_PKT_PROT = 11, /* DIR invalid in 1st PIO setup of ATAPI */
+ PORT_CERR_SGT_BOUNDARY = 16, /* PLD ecode 00 - SGT not on qword boundary */
+ PORT_CERR_SGT_TGTABRT = 17, /* PLD ecode 01 - target abort */
+ PORT_CERR_SGT_MSTABRT = 18, /* PLD ecode 10 - master abort */
+ PORT_CERR_SGT_PCIPERR = 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
+ PORT_CERR_CMD_BOUNDARY = 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
+ PORT_CERR_CMD_TGTABRT = 25, /* ctrl[15:13] 010 - target abort */
+ PORT_CERR_CMD_MSTABRT = 26, /* ctrl[15:13] 100 - master abort */
+ PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
+ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */
+ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */
+ PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */
+ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */
+ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */
+
+ /*
+ * Other constants
+ */
+ SGE_TRM = (1 << 31), /* Last SGE in chain */
+ PRB_SOFT_RST = (1 << 7), /* Soft reset request (ign BSY?) */
+
+ /* board id */
+ BID_SIL3124 = 0,
+ BID_SIL3132 = 1,
+ BID_SIL3131 = 2,
+
+ IRQ_STAT_4PORTS = 0xf,
+};
+
+struct sil24_cmd_block {
+ struct sil24_prb prb;
+ struct sil24_sge sge[LIBATA_MAX_PRD];
+};
+
+/*
+ * ap->private_data
+ *
+ * The preview driver always returned 0 for status. We emulate it
+ * here from the previous interrupt.
+ */
+struct sil24_port_priv {
+ struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */
+ dma_addr_t cmd_block_dma; /* DMA base addr for them */
+ struct ata_taskfile tf; /* Cached taskfile registers */
+};
+
+/* ap->host_set->private_data */
+struct sil24_host_priv {
+ void __iomem *host_base; /* global controller control (128 bytes @BAR0) */
+ void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */
+};
+
+static u8 sil24_check_status(struct ata_port *ap);
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void sil24_phy_reset(struct ata_port *ap);
+static void sil24_qc_prep(struct ata_queued_cmd *qc);
+static int sil24_qc_issue(struct ata_queued_cmd *qc);
+static void sil24_irq_clear(struct ata_port *ap);
+static void sil24_eng_timeout(struct ata_port *ap);
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int sil24_port_start(struct ata_port *ap);
+static void sil24_port_stop(struct ata_port *ap);
+static void sil24_host_stop(struct ata_host_set *host_set);
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static struct pci_device_id sil24_pci_tbl[] = {
+ { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+ { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
+ { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+ { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+ { } /* terminate list */
+};
+
+static struct pci_driver sil24_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = sil24_pci_tbl,
+ .probe = sil24_init_one,
+ .remove = ata_pci_remove_one, /* safe? */
+};
+
+static Scsi_Host_Template sil24_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+ .ordered_flush = 1, /* NCQ not supported yet */
+};
+
+static const struct ata_port_operations sil24_ops = {
+ .port_disable = ata_port_disable,
+
+ .check_status = sil24_check_status,
+ .check_altstatus = sil24_check_status,
+ .dev_select = ata_noop_dev_select,
+
+ .tf_read = sil24_tf_read,
+
+ .phy_reset = sil24_phy_reset,
+
+ .qc_prep = sil24_qc_prep,
+ .qc_issue = sil24_qc_issue,
+
+ .eng_timeout = sil24_eng_timeout,
+
+ .irq_handler = sil24_interrupt,
+ .irq_clear = sil24_irq_clear,
+
+ .scr_read = sil24_scr_read,
+ .scr_write = sil24_scr_write,
+
+ .port_start = sil24_port_start,
+ .port_stop = sil24_port_stop,
+ .host_stop = sil24_host_stop,
+};
+
+/*
+ * Use bits 30-31 of host_flags to encode available port numbers.
+ * Current maxium is 4.
+ */
+#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30)
+#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1)
+
+static struct ata_port_info sil24_port_info[] = {
+ /* sil_3124 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+ /* sil_3132 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+ /* sil_3131/sil_3531 */
+ {
+ .sht = &sil24_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+ ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x3f, /* udma0-5 */
+ .port_ops = &sil24_ops,
+ },
+};
+
+static inline void sil24_update_tf(struct ata_port *ap)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+ struct sil24_prb __iomem *prb = port;
+ u8 fis[6 * 4];
+
+ memcpy_fromio(fis, prb->fis, 6 * 4);
+ ata_tf_from_fis(fis, &pp->tf);
+}
+
+static u8 sil24_check_status(struct ata_port *ap)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ return pp->tf.command;
+}
+
+static int sil24_scr_map[] = {
+ [SCR_CONTROL] = 0,
+ [SCR_STATUS] = 1,
+ [SCR_ERROR] = 2,
+ [SCR_ACTIVE] = 3,
+};
+
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+ void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void __iomem *addr;
+ addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+ return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
+ }
+ return 0xffffffffU;
+}
+
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+ void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void __iomem *addr;
+ addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+ writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
+ }
+}
+
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct sil24_port_priv *pp = ap->private_data;
+ *tf = pp->tf;
+}
+
+static void sil24_phy_reset(struct ata_port *ap)
+{
+ __sata_phy_reset(ap);
+ /*
+ * No ATAPI yet. Just unconditionally indicate ATA device.
+ * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
+ * and libata core will ignore the device.
+ */
+ if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+ ap->device[0].class = ATA_DEV_ATA;
+}
+
+static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+ struct sil24_cmd_block *cb)
+{
+ struct scatterlist *sg = qc->sg;
+ struct sil24_sge *sge = cb->sge;
+ unsigned i;
+
+ for (i = 0; i < qc->n_elem; i++, sg++, sge++) {
+ sge->addr = cpu_to_le64(sg_dma_address(sg));
+ sge->cnt = cpu_to_le32(sg_dma_len(sg));
+ sge->flags = 0;
+ sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM);
+ }
+}
+
+static void sil24_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct sil24_port_priv *pp = ap->private_data;
+ struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+ struct sil24_prb *prb = &cb->prb;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_PIO:
+ case ATA_PROT_DMA:
+ case ATA_PROT_NODATA:
+ break;
+ default:
+ /* ATAPI isn't supported yet */
+ BUG();
+ }
+
+ ata_tf_to_fis(&qc->tf, prb->fis, 0);
+
+ if (qc->flags & ATA_QCFLAG_DMAMAP)
+ sil24_fill_sg(qc, cb);
+}
+
+static int sil24_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+ struct sil24_port_priv *pp = ap->private_data;
+ dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+
+ writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+ return 0;
+}
+
+static void sil24_irq_clear(struct ata_port *ap)
+{
+ /* unused */
+}
+
+static int __sil24_reset_controller(void __iomem *port)
+{
+ int cnt;
+ u32 tmp;
+
+ /* Reset controller state. Is this correct? */
+ writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+ readl(port + PORT_CTRL_STAT); /* sync */
+
+ /* Max ~100ms */
+ for (cnt = 0; cnt < 1000; cnt++) {
+ udelay(100);
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (!(tmp & PORT_CS_DEV_RST))
+ break;
+ }
+
+ if (tmp & PORT_CS_DEV_RST)
+ return -1;
+ return 0;
+}
+
+static void sil24_reset_controller(struct ata_port *ap)
+{
+ printk(KERN_NOTICE DRV_NAME
+ " ata%u: resetting controller...\n", ap->id);
+ if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
+ printk(KERN_ERR DRV_NAME
+ " ata%u: failed to reset controller\n", ap->id);
+}
+
+static void sil24_eng_timeout(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (!qc) {
+ printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+ ap->id);
+ return;
+ }
+
+ /*
+ * hack alert! We cannot use the supplied completion
+ * function from inside the ->eh_strategy_handler() thread.
+ * libata is the only user of ->eh_strategy_handler() in
+ * any kernel, so the default scsi_done() assumes it is
+ * not being called from the SCSI EH.
+ */
+ printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+ qc->scsidone = scsi_finish_command;
+ ata_qc_complete(qc, AC_ERR_OTHER);
+
+ sil24_reset_controller(ap);
+}
+
+static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
+{
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ struct sil24_port_priv *pp = ap->private_data;
+ void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+ u32 irq_stat, cmd_err, sstatus, serror;
+ unsigned int err_mask;
+
+ irq_stat = readl(port + PORT_IRQ_STAT);
+ writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
+
+ if (!(irq_stat & PORT_IRQ_ERROR)) {
+ /* ignore non-completion, non-error irqs for now */
+ printk(KERN_WARNING DRV_NAME
+ "ata%u: non-error exception irq (irq_stat %x)\n",
+ ap->id, irq_stat);
+ return;
+ }
+
+ cmd_err = readl(port + PORT_CMD_ERR);
+ sstatus = readl(port + PORT_SSTATUS);
+ serror = readl(port + PORT_SERROR);
+ if (serror)
+ writel(serror, port + PORT_SERROR);
+
+ printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
+ " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
+ ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
+
+ if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
+ /*
+ * Device is reporting error, tf registers are valid.
+ */
+ sil24_update_tf(ap);
+ err_mask = ac_err_mask(pp->tf.command);
+ } else {
+ /*
+ * Other errors. libata currently doesn't have any
+ * mechanism to report these errors. Just turn on
+ * ATA_ERR.
+ */
+ err_mask = AC_ERR_OTHER;
+ }
+
+ if (qc)
+ ata_qc_complete(qc, err_mask);
+
+ sil24_reset_controller(ap);
+}
+
+static inline void sil24_host_intr(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+ u32 slot_stat;
+
+ slot_stat = readl(port + PORT_SLOT_STAT);
+ if (!(slot_stat & HOST_SSTAT_ATTN)) {
+ struct sil24_port_priv *pp = ap->private_data;
+ /*
+ * !HOST_SSAT_ATTN guarantees successful completion,
+ * so reading back tf registers is unnecessary for
+ * most commands. TODO: read tf registers for
+ * commands which require these values on successful
+ * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
+ * DEVICE RESET and READ PORT MULTIPLIER (any more?).
+ */
+ sil24_update_tf(ap);
+
+ if (qc)
+ ata_qc_complete(qc, ac_err_mask(pp->tf.command));
+ } else
+ sil24_error_intr(ap, slot_stat);
+}
+
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ struct sil24_host_priv *hpriv = host_set->private_data;
+ unsigned handled = 0;
+ u32 status;
+ int i;
+
+ status = readl(hpriv->host_base + HOST_IRQ_STAT);
+
+ if (status == 0xffffffff) {
+ printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
+ "PCI fault or device removal?\n");
+ goto out;
+ }
+
+ if (!(status & IRQ_STAT_4PORTS))
+ goto out;
+
+ spin_lock(&host_set->lock);
+
+ for (i = 0; i < host_set->n_ports; i++)
+ if (status & (1 << i)) {
+ struct ata_port *ap = host_set->ports[i];
+ if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+ sil24_host_intr(host_set->ports[i]);
+ handled++;
+ } else
+ printk(KERN_ERR DRV_NAME
+ ": interrupt from disabled port %d\n", i);
+ }
+
+ spin_unlock(&host_set->lock);
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+static int sil24_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct sil24_port_priv *pp;
+ struct sil24_cmd_block *cb;
+ size_t cb_size = sizeof(*cb);
+ dma_addr_t cb_dma;
+
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+ memset(pp, 0, sizeof(*pp));
+
+ pp->tf.command = ATA_DRDY;
+
+ cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+ if (!cb) {
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(cb, 0, cb_size);
+
+ pp->cmd_block = cb;
+ pp->cmd_block_dma = cb_dma;
+
+ ap->private_data = pp;
+
+ return 0;
+}
+
+static void sil24_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct sil24_port_priv *pp = ap->private_data;
+ size_t cb_size = sizeof(*pp->cmd_block);
+
+ dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
+ kfree(pp);
+}
+
+static void sil24_host_stop(struct ata_host_set *host_set)
+{
+ struct sil24_host_priv *hpriv = host_set->private_data;
+
+ iounmap(hpriv->host_base);
+ iounmap(hpriv->port_base);
+ kfree(hpriv);
+}
+
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int printed_version = 0;
+ unsigned int board_id = (unsigned int)ent->driver_data;
+ struct ata_port_info *pinfo = &sil24_port_info[board_id];
+ struct ata_probe_ent *probe_ent = NULL;
+ struct sil24_host_priv *hpriv = NULL;
+ void __iomem *host_base = NULL;
+ void __iomem *port_base = NULL;
+ int i, rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto out_disable;
+
+ rc = -ENOMEM;
+ /* ioremap mmio registers */
+ host_base = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!host_base)
+ goto out_free;
+ port_base = ioremap(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ if (!port_base)
+ goto out_free;
+
+ /* allocate & init probe_ent and hpriv */
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (!probe_ent)
+ goto out_free;
+
+ hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv)
+ goto out_free;
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = pinfo->sht;
+ probe_ent->host_flags = pinfo->host_flags;
+ probe_ent->pio_mask = pinfo->pio_mask;
+ probe_ent->udma_mask = pinfo->udma_mask;
+ probe_ent->port_ops = pinfo->port_ops;
+ probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags);
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = port_base;
+ probe_ent->private_data = hpriv;
+
+ memset(hpriv, 0, sizeof(*hpriv));
+ hpriv->host_base = host_base;
+ hpriv->port_base = port_base;
+
+ /*
+ * Configure the device
+ */
+ /*
+ * FIXME: This device is certainly 64-bit capable. We just
+ * don't know how to use it. After fixing 32bit activation in
+ * this function, enable 64bit masks here.
+ */
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
+ goto out_free;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
+ goto out_free;
+ }
+
+ /* GPIO off */
+ writel(0, host_base + HOST_FLASH_CMD);
+
+ /* Mask interrupts during initialization */
+ writel(0, host_base + HOST_CTRL);
+
+ for (i = 0; i < probe_ent->n_ports; i++) {
+ void __iomem *port = port_base + i * PORT_REGS_SIZE;
+ unsigned long portu = (unsigned long)port;
+ u32 tmp;
+ int cnt;
+
+ probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+ probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+
+ ata_std_ports(&probe_ent->port[i]);
+
+ /* Initial PHY setting */
+ writel(0x20c, port + PORT_PHY_CFG);
+
+ /* Clear port RST */
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (tmp & PORT_CS_PORT_RST) {
+ writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+ readl(port + PORT_CTRL_STAT); /* sync */
+ for (cnt = 0; cnt < 10; cnt++) {
+ msleep(10);
+ tmp = readl(port + PORT_CTRL_STAT);
+ if (!(tmp & PORT_CS_PORT_RST))
+ break;
+ }
+ if (tmp & PORT_CS_PORT_RST)
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to clear port RST\n");
+ }
+
+ /* Zero error counters. */
+ writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+ writel(0x8000, port + PORT_CRC_ERR_THRESH);
+ writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+ writel(0x0000, port + PORT_DECODE_ERR_CNT);
+ writel(0x0000, port + PORT_CRC_ERR_CNT);
+ writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+ /* FIXME: 32bit activation? */
+ writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
+ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
+
+ /* Configure interrupts */
+ writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+ writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
+ port + PORT_IRQ_ENABLE_SET);
+
+ /* Clear interrupts */
+ writel(0x0fff0fff, port + PORT_IRQ_STAT);
+ writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+ /* Clear port multiplier enable and resume bits */
+ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+
+ /* Reset itself */
+ if (__sil24_reset_controller(port))
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to reset controller\n");
+ }
+
+ /* Turn on interrupts */
+ writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+
+ pci_set_master(pdev);
+
+ /* FIXME: check ata_device_add return value */
+ ata_device_add(probe_ent);
+
+ kfree(probe_ent);
+ return 0;
+
+ out_free:
+ if (host_base)
+ iounmap(host_base);
+ if (port_base)
+ iounmap(port_base);
+ kfree(probe_ent);
+ kfree(hpriv);
+ pci_release_regions(pdev);
+ out_disable:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static int __init sil24_init(void)
+{
+ return pci_module_init(&sil24_pci_driver);
+}
+
+static void __exit sil24_exit(void)
+{
+ pci_unregister_driver(&sil24_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
+
+module_init(sil24_init);
+module_exit(sil24_exit);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index e418b89c6b9d..42288be0e561 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -7,21 +7,26 @@
*
* Copyright 2004 Uwe Koziolek
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -33,6 +38,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -47,7 +53,10 @@ enum {
/* PCI configuration registers */
SIS_GENCTL = 0x54, /* IDE General Control register */
SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */
- SIS_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
+ SIS180_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
+ SIS182_SATA1_OFS = 0x20, /* offset from sata0->sata1 phy regs */
+ SIS_PMR = 0x90, /* port mapping register */
+ SIS_PMR_COMBINED = 0x30,
/* random bits */
SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */
@@ -62,6 +71,7 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static struct pci_device_id sis_pci_tbl[] = {
{ PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
{ PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+ { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
{ } /* terminate list */
};
@@ -93,7 +103,7 @@ static Scsi_Host_Template sis_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations sis_ops = {
+static const struct ata_port_operations sis_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
@@ -134,77 +144,111 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg)
+static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
{
unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
- if (port_no)
- addr += SIS_SATA1_OFS;
+ if (port_no) {
+ if (device == 0x182)
+ addr += SIS182_SATA1_OFS;
+ else
+ addr += SIS180_SATA1_OFS;
+ }
+
return addr;
}
static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg);
- u32 val;
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
+ u32 val, val2 = 0;
+ u8 pmr;
if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
return 0xffffffff;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
pci_read_config_dword(pdev, cfg_addr, &val);
- return val;
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
+
+ return val|val2;
}
static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
- unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr);
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
+ u8 pmr;
if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
return;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
pci_write_config_dword(pdev, cfg_addr, val);
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ pci_write_config_dword(pdev, cfg_addr+0x10, val);
}
static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+ u32 val, val2 = 0;
+ u8 pmr;
+
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
if (ap->flags & SIS_FLAG_CFGSCR)
return sis_scr_cfg_read(ap, sc_reg);
- return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+ val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
+
+ return val | val2;
}
static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
{
+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
+ u8 pmr;
+
if (sc_reg > SCR_CONTROL)
return;
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
if (ap->flags & SIS_FLAG_CFGSCR)
sis_scr_cfg_write(ap, sc_reg, val);
- else
+ else {
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
-}
-
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+ if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
+ outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
}
}
static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
int rc;
u32 genctl;
struct ata_port_info *ppi;
int pci_dev_busy = 0;
+ u8 pmr;
+ u8 port2_start;
+
+ if (!printed_version++)
+ dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -224,7 +268,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &sis_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
@@ -234,7 +278,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-
+
/* if hardware thinks SCRs are in IO space, but there are
* no IO resources assigned, change to PCI cfg space.
*/
@@ -246,15 +290,33 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
}
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ if (ent->device != 0x182) {
+ if ((pmr & SIS_PMR_COMBINED) == 0) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 180/181 chipset in SATA mode\n");
+ port2_start = 64;
+ }
+ else {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "Detected SiS 180/181 chipset in combined mode\n");
+ port2_start=0;
+ }
+ }
+ else {
+ dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n");
+ port2_start = 0x20;
+ }
+
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
probe_ent->port[0].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR);
probe_ent->port[1].scr_addr =
- pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
+ pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
}
pci_set_master(pdev);
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 858e07185dbd..db615ff794d8 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -13,21 +13,26 @@
* This driver probably works with non-Apple versions of the
* Broadcom chipset...
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -39,6 +44,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -79,6 +85,8 @@
/* Port stride */
#define K2_SATA_PORT_OFFSET 0x100
+static u8 k2_stat_check_status(struct ata_port *ap);
+
static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
@@ -97,7 +105,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
}
-static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -131,16 +139,24 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- u16 nsect, lbal, lbam, lbah;
+ u16 nsect, lbal, lbam, lbah, feature;
- nsect = tf->nsect = readw(ioaddr->nsect_addr);
- lbal = tf->lbal = readw(ioaddr->lbal_addr);
- lbam = tf->lbam = readw(ioaddr->lbam_addr);
- lbah = tf->lbah = readw(ioaddr->lbah_addr);
+ tf->command = k2_stat_check_status(ap);
tf->device = readw(ioaddr->device_addr);
+ feature = readw(ioaddr->error_addr);
+ nsect = readw(ioaddr->nsect_addr);
+ lbal = readw(ioaddr->lbal_addr);
+ lbam = readw(ioaddr->lbam_addr);
+ lbah = readw(ioaddr->lbah_addr);
+
+ tf->feature = feature;
+ tf->nsect = nsect;
+ tf->lbal = lbal;
+ tf->lbam = lbam;
+ tf->lbah = lbah;
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readw(ioaddr->error_addr) >> 8;
+ tf->hob_feature = feature >> 8;
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
@@ -195,18 +211,18 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
/* start host DMA transaction */
dmactl = readb(mmio + ATA_DMA_CMD);
writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
- /* There is a race condition in certain SATA controllers that can
- be seen when the r/w command is given to the controller before the
+ /* There is a race condition in certain SATA controllers that can
+ be seen when the r/w command is given to the controller before the
host DMA is started. On a Read command, the controller would initiate
the command to the drive even before it sees the DMA start. When there
- are very fast drives connected to the controller, or when the data request
+ are very fast drives connected to the controller, or when the data request
hits in the drive cache, there is the possibility that the drive returns a part
or all of the requested data to the controller before the DMA start is issued.
In this case, the controller would become confused as to what to do with the data.
In the worst case when all the data is returned back to the controller, the
controller could hang. In other cases it could return partial data returning
in data corruption. This problem has been seen in PPC systems and can also appear
- on an system with very fast disks, where the SATA controller is sitting behind a
+ on an system with very fast disks, where the SATA controller is sitting behind a
number of bridges, and hence there is significant latency between the r/w command
and the start command. */
/* issue r/w command if the access is to ATA*/
@@ -214,7 +230,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
ap->ops->exec_command(ap, &qc->tf);
}
-
+
static u8 k2_stat_check_status(struct ata_port *ap)
{
return readl((void *) ap->ioaddr.status_addr);
@@ -292,7 +308,7 @@ static Scsi_Host_Template k2_sata_sht = {
};
-static struct ata_port_operations k2_sata_ops = {
+static const struct ata_port_operations k2_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = k2_sata_tf_load,
.tf_read = k2_sata_tf_read,
@@ -313,7 +329,7 @@ static struct ata_port_operations k2_sata_ops = {
.scr_write = k2_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -341,13 +357,13 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base;
+ void __iomem *mmio_base;
int pci_dev_busy = 0;
int rc;
int i;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
@@ -387,8 +403,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
+ mmio_base = pci_iomap(pdev, 5, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 140cea05de3f..0ec21e09f5d8 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -7,21 +7,26 @@
*
* Copyright 2003-2004 Red Hat, Inc.
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -33,6 +38,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -94,7 +100,7 @@ enum {
PDC_DIMM1_CONTROL_OFFSET = 0x84,
PDC_SDRAM_CONTROL_OFFSET = 0x88,
PDC_I2C_WRITE = 0x00000000,
- PDC_I2C_READ = 0x00000040,
+ PDC_I2C_READ = 0x00000040,
PDC_I2C_START = 0x00000080,
PDC_I2C_MASK_INT = 0x00000020,
PDC_I2C_COMPLETE = 0x00010000,
@@ -105,16 +111,16 @@ enum {
PDC_DIMM_SPD_COLUMN_NUM = 4,
PDC_DIMM_SPD_MODULE_ROW = 5,
PDC_DIMM_SPD_TYPE = 11,
- PDC_DIMM_SPD_FRESH_RATE = 12,
- PDC_DIMM_SPD_BANK_NUM = 17,
+ PDC_DIMM_SPD_FRESH_RATE = 12,
+ PDC_DIMM_SPD_BANK_NUM = 17,
PDC_DIMM_SPD_CAS_LATENCY = 18,
- PDC_DIMM_SPD_ATTRIBUTE = 21,
+ PDC_DIMM_SPD_ATTRIBUTE = 21,
PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
- PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
+ PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
PDC_DIMM_SPD_SYSTEM_FREQ = 126,
- PDC_CTL_STATUS = 0x08,
+ PDC_CTL_STATUS = 0x08,
PDC_DIMM_WINDOW_CTLR = 0x0C,
PDC_TIME_CONTROL = 0x3C,
PDC_TIME_PERIOD = 0x40,
@@ -132,7 +138,7 @@ struct pdc_port_priv {
};
struct pdc_host_priv {
- void *dimm_mmio;
+ void __iomem *dimm_mmio;
unsigned int doing_hdma;
unsigned int hdma_prod;
@@ -152,20 +158,20 @@ static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set);
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
u32 device, u32 subaddr, u32 *pdata);
static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size);
static void pdc20621_irq_clear(struct ata_port *ap);
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -191,7 +197,7 @@ static Scsi_Host_Template pdc_sata_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations pdc_20621_ops = {
+static const struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read,
@@ -240,13 +246,14 @@ static struct pci_driver pdc_sata_pci_driver = {
static void pdc20621_host_stop(struct ata_host_set *host_set)
{
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
struct pdc_host_priv *hpriv = host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
- iounmap(dimm_mmio);
+ pci_iounmap(pdev, dimm_mmio);
kfree(hpriv);
- ata_host_stop(host_set);
+ pci_iounmap(pdev, host_set->mmio_base);
}
static int pdc_port_start(struct ata_port *ap)
@@ -446,9 +453,9 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
struct scatterlist *sg = qc->sg;
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host_set->mmio_base;
struct pdc_host_priv *hpriv = ap->host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
unsigned int portno = ap->port_no;
unsigned int i, last, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
@@ -468,7 +475,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
- total_len += sg[i].length;
+ total_len += sg_dma_len(&sg[i]);
}
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
sgt_len = idx * 4;
@@ -508,9 +515,9 @@ static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
- void *mmio = ap->host_set->mmio_base;
+ void __iomem *mmio = ap->host_set->mmio_base;
struct pdc_host_priv *hpriv = ap->host_set->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
unsigned int portno = ap->port_no;
unsigned int i;
@@ -560,7 +567,7 @@ static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
{
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -634,7 +641,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 seq = (u8) (port_no + 1);
unsigned int port_ofs;
@@ -663,8 +670,8 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
writel(port_ofs + PDC_DIMM_ATA_PKT,
- (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_ATA_PKT,
port_ofs + PDC_DIMM_ATA_PKT,
@@ -694,7 +701,7 @@ static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
struct ata_queued_cmd *qc,
unsigned int doing_hdma,
- void *mmio)
+ void __iomem *mmio)
{
unsigned int port_no = ap->port_no;
unsigned int port_ofs =
@@ -712,7 +719,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* get drive status; clear intr; complete txn */
- ata_qc_complete(qc, ata_wait_idle(ap));
+ ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
pdc20621_pop_hdma(qc);
}
@@ -741,8 +748,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4));
writel(port_ofs + PDC_DIMM_ATA_PKT,
- (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
- readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
}
/* step two - execute ATA command */
@@ -750,7 +757,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* get drive status; clear intr; complete txn */
- ata_qc_complete(qc, ata_wait_idle(ap));
+ ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
pdc20621_pop_hdma(qc);
}
handled = 1;
@@ -760,7 +767,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
- ata_qc_complete(qc, status);
+ ata_qc_complete(qc, ac_err_mask(status));
handled = 1;
} else {
@@ -773,7 +780,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
static void pdc20621_irq_clear(struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
- void *mmio = host_set->mmio_base;
+ void __iomem *mmio = host_set->mmio_base;
mmio += PDC_CHIP0_OFS;
@@ -787,7 +794,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
u32 mask = 0;
unsigned int i, tmp, port_no;
unsigned int handled = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
VPRINTK("ENTER\n");
@@ -825,7 +832,8 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
ap = host_set->ports[port_no];
tmp = mask & (1 << i);
VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
- if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (tmp && ap &&
+ !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -847,10 +855,14 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
static void pdc_eng_timeout(struct ata_port *ap)
{
u8 drv_stat;
+ struct ata_host_set *host_set = ap->host_set;
struct ata_queued_cmd *qc;
+ unsigned long flags;
DPRINTK("ENTER\n");
+ spin_lock_irqsave(&host_set->lock, flags);
+
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -870,7 +882,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
- ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+ ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
break;
default:
@@ -879,15 +891,16 @@ static void pdc_eng_timeout(struct ata_port *ap)
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
ap->id, qc->tf.command, drv_stat);
- ata_qc_complete(qc, drv_stat);
+ ata_qc_complete(qc, ac_err_mask(drv_stat));
break;
}
out:
+ spin_unlock_irqrestore(&host_set->lock, flags);
DPRINTK("EXIT\n");
}
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -895,7 +908,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
@@ -922,23 +935,23 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
- page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
- idx = (u16) (offset / window_size);
+ page_mask = 0x00;
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
+ idx = (u16) (offset / window_size);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
@@ -947,19 +960,19 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
offset -= (idx * window_size);
idx++;
- dist = ((long) (window_size - (offset + size))) >= 0 ? size :
+ dist = ((long) (window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
dist);
- psource += dist;
+ psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio),
window_size / 4);
psource += window_size;
size -= window_size;
@@ -971,71 +984,70 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
readl(mmio + PDC_GENERAL_CTLR);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_fromio((char *) psource, (char *) (dimm_mmio),
+ memcpy_fromio((char *) psource, (char *) (dimm_mmio),
size / 4);
}
}
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
struct pdc_host_priv *hpriv = pe->private_data;
- void *dimm_mmio = hpriv->dimm_mmio;
+ void __iomem *dimm_mmio = hpriv->dimm_mmio;
- /* hard-code chip #0 */
+ /* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
- page_mask = 0x00;
- window_size = 0x2000 * 4; /* 32K byte uchar size */
+ page_mask = 0x00;
+ window_size = 0x2000 * 4; /* 32K byte uchar size */
idx = (u16) (offset / window_size);
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- offset -= (idx * window_size);
+ offset -= (idx * window_size);
idx++;
dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
(long) (window_size - offset);
- memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+ memcpy_toio(dimm_mmio + offset / 4, psource, dist);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
- psource += dist;
+ psource += dist;
size -= dist;
for (; (long) size >= (long) window_size ;) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_toio((char *) (dimm_mmio), (char *) psource,
- window_size / 4);
+ memcpy_toio(dimm_mmio, psource, window_size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
psource += window_size;
size -= window_size;
idx ++;
}
-
+
if (size) {
writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
readl(mmio + PDC_DIMM_WINDOW_CTLR);
- memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+ memcpy_toio(dimm_mmio, psource, size / 4);
writel(0x01, mmio + PDC_GENERAL_CTLR);
readl(mmio + PDC_GENERAL_CTLR);
}
}
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
u32 subaddr, u32 *pdata)
{
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
u32 i2creg = 0;
- u32 status;
+ u32 status;
u32 count =0;
/* hard-code chip #0 */
@@ -1049,7 +1061,7 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
/* Write Control to perform read operation, mask int */
- writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
+ writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
mmio + PDC_I2C_CONTROL_OFFSET);
for (count = 0; count <= 1000; count ++) {
@@ -1062,26 +1074,26 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
}
*pdata = (status >> 8) & 0x000000ff;
- return 1;
+ return 1;
}
static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
{
u32 data=0 ;
- if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
if (data == 100)
return 100;
} else
return 0;
-
+
if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
- if(data <= 0x75)
+ if(data <= 0x75)
return 133;
} else
return 0;
-
+
return 0;
}
@@ -1091,15 +1103,15 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
u32 spd0[50];
u32 data = 0;
int size, i;
- u8 bdimmsize;
- void *mmio = pe->mmio_base;
+ u8 bdimmsize;
+ void __iomem *mmio = pe->mmio_base;
static const struct {
unsigned int reg;
unsigned int ofs;
} pdc_i2c_read_data [] = {
- { PDC_DIMM_SPD_TYPE, 11 },
+ { PDC_DIMM_SPD_TYPE, 11 },
{ PDC_DIMM_SPD_FRESH_RATE, 12 },
- { PDC_DIMM_SPD_COLUMN_NUM, 4 },
+ { PDC_DIMM_SPD_COLUMN_NUM, 4 },
{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
{ PDC_DIMM_SPD_ROW_NUM, 3 },
{ PDC_DIMM_SPD_BANK_NUM, 17 },
@@ -1108,7 +1120,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
- { PDC_DIMM_SPD_CAS_LATENCY, 18 },
+ { PDC_DIMM_SPD_CAS_LATENCY, 18 },
};
/* hard-code chip #0 */
@@ -1116,17 +1128,17 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
- pdc_i2c_read_data[i].reg,
+ pdc_i2c_read_data[i].reg,
&spd0[pdc_i2c_read_data[i].ofs]);
-
+
data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
- data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
+ data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
((((spd0[27] + 9) / 10) - 1) << 8) ;
- data |= (((((spd0[29] > spd0[28])
- ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
+ data |= (((((spd0[29] > spd0[28])
+ ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
-
- if (spd0[18] & 0x08)
+
+ if (spd0[18] & 0x08)
data |= ((0x03) << 14);
else if (spd0[18] & 0x04)
data |= ((0x02) << 14);
@@ -1135,7 +1147,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
else
data |= (0 << 14);
- /*
+ /*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
@@ -1145,9 +1157,9 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
data |= (((size / 16) - 1) << 16);
data |= (0 << 23);
data |= 8;
- writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
+ writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
- return size;
+ return size;
}
@@ -1155,7 +1167,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
{
u32 data, spd0;
int error, i;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1167,12 +1179,12 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
Refresh Enable (bit 17)
*/
- data = 0x022259F1;
+ data = 0x022259F1;
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
/* Turn on for ECC */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
@@ -1186,22 +1198,22 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
data |= (1<<19);
writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- error = 1;
+ error = 1;
for (i = 1; i <= 10; i++) { /* polling ~5 secs */
data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
if (!(data & (1<<19))) {
error = 0;
- break;
+ break;
}
msleep(i*100);
}
return error;
}
-
+
static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
{
- int speed, size, length;
+ int speed, size, length;
u32 addr,spd0,pci_status;
u32 tmp=0;
u32 time_period=0;
@@ -1209,7 +1221,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
u32 ticks=0;
u32 clock=0;
u32 fparam=0;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1228,7 +1240,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
/* Wait 3 seconds */
msleep(3000);
- /*
+ /*
When timer is enabled, counter is decreased every internal
clock cycle.
*/
@@ -1236,24 +1248,24 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
tcount = readl(mmio + PDC_TIME_COUNTER);
VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
- /*
+ /*
If SX4 is on PCI-X bus, after 3 seconds, the timer counter
register should be >= (0xffffffff - 3x10^8).
*/
if(tcount >= PCI_X_TCOUNT) {
ticks = (time_period - tcount);
VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
-
+
clock = (ticks / 300000);
VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
-
+
clock = (clock * 33);
VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
/* PLL F Param (bit 22:16) */
fparam = (1400000 / clock) - 2;
VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
-
+
/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
pci_status = (0x8a001824 | (fparam << 16));
} else
@@ -1264,21 +1276,21 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
writel(pci_status, mmio + PDC_CTL_STATUS);
readl(mmio + PDC_CTL_STATUS);
- /*
+ /*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if (!(speed = pdc20621_detect_dimm(pe))) {
- printk(KERN_ERR "Detect Local DIMM Fail\n");
+ printk(KERN_ERR "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
}
VPRINTK("Local DIMM Speed = %d\n", speed);
- /* Programming DIMM0 Module Control Register (index_CID0:80h) */
+ /* Programming DIMM0 Module Control Register (index_CID0:80h) */
size = pdc20621_prog_dimm0(pe);
VPRINTK("Local DIMM Size = %dMB\n",size);
- /* Programming DIMM Module Global Control Register (index_CID0:88h) */
+ /* Programming DIMM Module Global Control Register (index_CID0:88h) */
if (pdc20621_prog_dimm_global(pe)) {
printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
return 1;
@@ -1297,30 +1309,30 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
+ pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
- printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
+ printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
#endif
/* ECC initiliazation. */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
VPRINTK("Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
while (addr < length) {
- pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
+ pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
sizeof(u32));
addr += sizeof(u32);
}
@@ -1333,7 +1345,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
static void pdc_20621_init(struct ata_probe_ent *pe)
{
u32 tmp;
- void *mmio = pe->mmio_base;
+ void __iomem *mmio = pe->mmio_base;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1366,14 +1378,15 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
- void *mmio_base, *dimm_mmio = NULL;
+ void __iomem *mmio_base;
+ void __iomem *dimm_mmio = NULL;
struct pdc_host_priv *hpriv = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/*
* If this driver happens to only be useful on Apple's K2, then
@@ -1406,8 +1419,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 3),
- pci_resource_len(pdev, 3));
+ mmio_base = pci_iomap(pdev, 3, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -1421,8 +1433,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
}
memset(hpriv, 0, sizeof(*hpriv));
- dimm_mmio = ioremap(pci_resource_start(pdev, 4),
- pci_resource_len(pdev, 4));
+ dimm_mmio = pci_iomap(pdev, 4, 0);
if (!dimm_mmio) {
kfree(hpriv);
rc = -ENOMEM;
@@ -1469,9 +1480,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
err_out_iounmap_dimm: /* only get to this label if 20621 */
kfree(hpriv);
- iounmap(dimm_mmio);
+ pci_iounmap(pdev, dimm_mmio);
err_out_iounmap:
- iounmap(mmio_base);
+ pci_iounmap(pdev, mmio_base);
err_out_free_ent:
kfree(probe_ent);
err_out_regions:
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index a71fb54eebd3..a5e245c098e1 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -1,21 +1,26 @@
/*
* sata_uli.c - ULi Electronics SATA
*
- * The contents of this file are subject to the Open
- * Software License version 1.1 that can be found at
- * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- * by reference.
*
- * Alternatively, the contents of this file may be used under the terms
- * of the GNU General Public License version 2 (the "GPL") as distributed
- * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
*
*/
@@ -27,6 +32,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -85,7 +91,7 @@ static Scsi_Host_Template uli_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations uli_ops = {
+static const struct ata_port_operations uli_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@@ -120,8 +126,8 @@ static struct ata_port_info uli_port_info = {
.sht = &uli_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x03, //support pio mode 4 (FIXME)
- .udma_mask = 0x7f, //support udma mode 6
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &uli_ops,
};
@@ -171,26 +177,18 @@ static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
uli_scr_cfg_write(ap, sc_reg, val);
}
-/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
-{
- u16 pci_command;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
-}
-
static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ static int printed_version;
struct ata_probe_ent *probe_ent;
struct ata_port_info *ppi;
int rc;
unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
+ if (!printed_version++)
+ dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
rc = pci_enable_device(pdev);
if (rc)
return rc;
@@ -209,12 +207,12 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
ppi = &uli_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
-
+
switch (board_idx) {
case uli_5287:
probe_ent->port[0].scr_addr = ULI5287_BASE;
@@ -255,7 +253,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
}
pci_set_master(pdev);
- pci_enable_intx(pdev);
+ pci_intx(pdev, 1);
/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index f43183c19a12..b3ecdbe400e9 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -1,34 +1,38 @@
/*
- sata_via.c - VIA Serial ATA controllers
-
- Maintained by: Jeff Garzik <jgarzik@pobox.com>
- Please ALWAYS copy linux-ide@vger.kernel.org
+ * sata_via.c - VIA Serial ATA controllers
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
on emails.
-
- Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- Copyright 2003-2004 Jeff Garzik
-
- The contents of this file are subject to the Open
- Software License version 1.1 that can be found at
- http://www.opensource.org/licenses/osl-1.1.txt and is included herein
- by reference.
-
- Alternatively, the contents of this file may be used under the terms
- of the GNU General Public License version 2 (the "GPL") as distributed
- in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL.
-
- ----------------------------------------------------------------------
-
- To-do list:
- * VT6421 PATA support
-
+ *
+ * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
+ * Copyright 2003-2004 Jeff Garzik
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available under NDA.
+ *
+ *
+ * To-do list:
+ * - VT6421 PATA support
+ *
*/
#include <linux/kernel.h>
@@ -37,6 +41,7 @@
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -105,7 +110,7 @@ static Scsi_Host_Template svia_sht = {
.ordered_flush = 1,
};
-static struct ata_port_operations svia_sata_ops = {
+static const struct ata_port_operations svia_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
@@ -208,7 +213,7 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
struct ata_probe_ent *probe_ent;
struct ata_port_info *ppi = &svia_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
if (!probe_ent)
return NULL;
@@ -255,15 +260,15 @@ static void svia_configure(struct pci_dev *pdev)
u8 tmp8;
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
- printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
- pci_name(pdev),
+ dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
(int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
/* make sure SATA channels are enabled */
pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
- pci_name(pdev), (int) tmp8);
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "enabling SATA channels (0x%x)\n",
+ (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
}
@@ -271,8 +276,9 @@ static void svia_configure(struct pci_dev *pdev)
/* make sure interrupts for each channel sent to us */
pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
- pci_name(pdev), (int) tmp8);
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "enabling SATA channel interrupts (0x%x)\n",
+ (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
}
@@ -280,8 +286,9 @@ static void svia_configure(struct pci_dev *pdev)
/* make sure native mode is enabled */
pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
- pci_name(pdev), (int) tmp8);
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "enabling SATA channel native mode (0x%x)\n",
+ (int) tmp8);
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
@@ -299,7 +306,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
u8 tmp8;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -314,8 +321,9 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == vt6420) {
pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
if (tmp8 & SATA_2DEV) {
- printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
- pci_name(pdev), (int) tmp8);
+ dev_printk(KERN_ERR, &pdev->dev,
+ "SATA master/slave not supported (0x%x)\n",
+ (int) tmp8);
rc = -EIO;
goto err_out_regions;
}
@@ -328,10 +336,11 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) ||
(pci_resource_len(pdev, i) < bar_sizes[i])) {
- printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
- pci_name(pdev), i,
- pci_resource_start(pdev, i),
- pci_resource_len(pdev, i));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
+ i,
+ pci_resource_start(pdev, i),
+ pci_resource_len(pdev, i));
rc = -ENODEV;
goto err_out_regions;
}
@@ -347,10 +356,9 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent = vt6420_init_probe_ent(pdev);
else
probe_ent = vt6421_init_probe_ent(pdev);
-
+
if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
rc = -ENOMEM;
goto err_out_regions;
}
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index c5e09dc6f3de..bb84ba0c7e83 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -9,9 +9,29 @@
*
* Bits from Jeff Garzik, Copyright RedHat, Inc.
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Vitesse hardware documentation presumably available under NDA.
+ * Intel 31244 (same hardware interface) documentation presumably
+ * available from http://developer.intel.com/
+ *
*/
#include <linux/kernel.h>
@@ -22,6 +42,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/device.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -66,7 +87,7 @@ static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -75,16 +96,16 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
{
- unsigned long mask_addr;
+ void __iomem *mask_addr;
u8 mask;
- mask_addr = (unsigned long) ap->host_set->mmio_base +
+ mask_addr = ap->host_set->mmio_base +
VSC_SATA_INT_MASK_OFFSET + ap->port_no;
mask = readb(mask_addr);
if (ctl & ATA_NIEN)
@@ -95,7 +116,7 @@ static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
}
-static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -133,16 +154,24 @@ static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
- u16 nsect, lbal, lbam, lbah;
+ u16 nsect, lbal, lbam, lbah, feature;
- nsect = tf->nsect = readw(ioaddr->nsect_addr);
- lbal = tf->lbal = readw(ioaddr->lbal_addr);
- lbam = tf->lbam = readw(ioaddr->lbam_addr);
- lbah = tf->lbah = readw(ioaddr->lbah_addr);
+ tf->command = ata_check_status(ap);
tf->device = readw(ioaddr->device_addr);
+ feature = readw(ioaddr->error_addr);
+ nsect = readw(ioaddr->nsect_addr);
+ lbal = readw(ioaddr->lbal_addr);
+ lbam = readw(ioaddr->lbam_addr);
+ lbah = readw(ioaddr->lbah_addr);
+
+ tf->feature = feature;
+ tf->nsect = nsect;
+ tf->lbal = lbal;
+ tf->lbam = lbam;
+ tf->lbah = lbah;
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readb(ioaddr->error_addr);
+ tf->hob_feature = feature >> 8;
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
@@ -173,7 +202,8 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
struct ata_port *ap;
ap = host_set->ports[i];
- if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ if (ap && !(ap->flags &
+ (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -210,7 +240,7 @@ static Scsi_Host_Template vsc_sata_sht = {
};
-static struct ata_port_operations vsc_sata_ops = {
+static const struct ata_port_operations vsc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = vsc_sata_tf_load,
.tf_read = vsc_sata_tf_read,
@@ -231,7 +261,7 @@ static struct ata_port_operations vsc_sata_ops = {
.scr_write = vsc_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = ata_pci_host_stop,
};
static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -262,11 +292,11 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
int pci_dev_busy = 0;
- void *mmio_base;
+ void __iomem *mmio_base;
int rc;
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)
@@ -305,8 +335,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
- mmio_base = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ mmio_base = pci_iomap(pdev, 0, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
@@ -342,7 +371,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
pci_set_master(pdev);
- /*
+ /*
* Config offset 0x98 is "Extended Control and Status Register 0"
* Default value is (1 << 28). All bits except bit 28 are reserved in
* DPA mode. If bit 28 is set, LED 0 reflects all ports' activity.
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d14523d7e449..a5711d545d71 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -130,7 +130,7 @@ EXPORT_SYMBOL(scsi_device_types);
* Returns: Pointer to request block.
*/
struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
- int gfp_mask)
+ gfp_t gfp_mask)
{
const int offset = ALIGN(sizeof(struct scsi_request), 4);
const int size = offset + sizeof(struct request);
@@ -196,7 +196,7 @@ struct scsi_host_cmd_pool {
unsigned int users;
char *name;
unsigned int slab_flags;
- unsigned int gfp_mask;
+ gfp_t gfp_mask;
};
static struct scsi_host_cmd_pool scsi_cmd_pool = {
@@ -213,7 +213,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
static DECLARE_MUTEX(host_cmd_pool_mutex);
static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
@@ -245,7 +245,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
*
* Returns: The allocated scsi command structure.
*/
-struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
+struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
@@ -268,6 +268,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
} else
put_device(&dev->sdev_gendev);
+ cmd->jiffies_at_alloc = jiffies;
return cmd;
}
EXPORT_SYMBOL(scsi_get_command);
@@ -627,7 +628,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
spin_lock_irqsave(host->host_lock, flags);
scsi_cmd_get_serial(host, cmd);
- if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
+ if (unlikely(host->shost_state == SHOST_DEL)) {
cmd->result = (DID_NO_CONNECT << 16);
scsi_done(cmd);
} else {
@@ -798,9 +799,23 @@ static void scsi_softirq(struct softirq_action *h)
while (!list_empty(&local_q)) {
struct scsi_cmnd *cmd = list_entry(local_q.next,
struct scsi_cmnd, eh_entry);
+ /* The longest time any command should be outstanding is the
+ * per command timeout multiplied by the number of retries.
+ *
+ * For a typical command, this is 2.5 minutes */
+ unsigned long wait_for
+ = cmd->allowed * cmd->timeout_per_command;
list_del_init(&cmd->eh_entry);
disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ dev_printk(KERN_ERR, &cmd->device->sdev_gendev,
+ "timing out command, waited %lus\n",
+ wait_for/HZ);
+ disposition = SUCCESS;
+ }
+
scsi_log_completion(cmd, disposition);
switch (disposition) {
case SUCCESS:
@@ -1250,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
list_for_each_safe(lh, lh_sf, &active_list) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_del_init(lh);
- if (recovery) {
- scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD);
- } else {
+ if (recovery &&
+ !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
scmd->result = (DID_ABORT << 16);
scsi_finish_command(scmd);
}
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 6121dc1bfada..e69477d1889b 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -110,10 +110,12 @@ static struct {
{"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */
{"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */
{"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN},
+ {"transtec", "T5008", "0001", BLIST_NOREPORTLUN },
{"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */
+ {"", "Scanner", "1.80", BLIST_NOLUN}, /* responds to all lun */
/*
* Other types of devices that have special flags.
@@ -135,7 +137,7 @@ static struct {
{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
{"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
- {"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
+ {"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
{"DELL", "PV660F", NULL, BLIST_SPARSELUN},
{"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN},
{"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */
@@ -183,6 +185,7 @@ static struct {
{"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
{"SEAGATE", "ST34555N", "0930", BLIST_NOTQ}, /* Chokes on tagged INQUIRY */
@@ -191,6 +194,7 @@ static struct {
{"SGI", "RAID5", "*", BLIST_SPARSELUN},
{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
{"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+ {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
{"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 0fc8b48f052b..52b348c36d56 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -49,7 +50,7 @@
void scsi_eh_wakeup(struct Scsi_Host *shost)
{
if (shost->host_busy == shost->host_failed) {
- up(shost->eh_wait);
+ wake_up_process(shost->ehandler);
SCSI_LOG_ERROR_RECOVERY(5,
printk("Waking error handler thread\n"));
}
@@ -67,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
{
struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
+ int ret = 0;
- if (shost->eh_wait == NULL)
+ if (!shost->ehandler)
return 0;
spin_lock_irqsave(shost->host_lock, flags);
+ if (scsi_host_set_state(shost, SHOST_RECOVERY))
+ if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
+ goto out_unlock;
+ ret = 1;
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
- set_bit(SHOST_RECOVERY, &shost->shost_state);
shost->host_failed++;
scsi_eh_wakeup(shost);
+ out_unlock:
spin_unlock_irqrestore(shost->host_lock, flags);
- return 1;
+ return ret;
}
/**
@@ -115,7 +121,6 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
add_timer(&scmd->eh_timeout);
}
-EXPORT_SYMBOL(scsi_add_timer);
/**
* scsi_delete_timer - Delete/cancel timer for a given function.
@@ -143,7 +148,6 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
return rtn;
}
-EXPORT_SYMBOL(scsi_delete_timer);
/**
* scsi_times_out - Timeout function for normal scsi commands.
@@ -177,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd)
}
if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
- panic("Error handler thread not present at %p %p %s %d",
- scmd, scmd->device->host, __FILE__, __LINE__);
+ scmd->result |= DID_TIME_OUT << 16;
+ __scsi_done(scmd);
}
}
@@ -197,7 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
{
int online;
- wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state)));
+ wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
online = scsi_device_online(sdev);
@@ -775,9 +779,11 @@ retry_tur:
__FUNCTION__, scmd, rtn));
if (rtn == SUCCESS)
return 0;
- else if (rtn == NEEDS_RETRY)
+ else if (rtn == NEEDS_RETRY) {
if (retry_cnt--)
goto retry_tur;
+ return 0;
+ }
return 1;
}
@@ -1439,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
static void scsi_restart_operations(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
+ unsigned long flags;
/*
* If the door was locked, we need to insert a door lock request
@@ -1458,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
__FUNCTION__));
- clear_bit(SHOST_RECOVERY, &shost->shost_state);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (scsi_host_set_state(shost, SHOST_RUNNING))
+ if (scsi_host_set_state(shost, SHOST_CANCEL))
+ BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
+ spin_unlock_irqrestore(shost->host_lock, flags);
wake_up(&shost->host_wait);
@@ -1580,50 +1591,31 @@ int scsi_error_handler(void *data)
{
struct Scsi_Host *shost = (struct Scsi_Host *) data;
int rtn;
- DECLARE_MUTEX_LOCKED(sem);
-
- /*
- * Flush resources
- */
-
- daemonize("scsi_eh_%d", shost->host_no);
current->flags |= PF_NOFREEZE;
- shost->eh_wait = &sem;
- shost->ehandler = current;
-
+
/*
- * Wake up the thread that created us.
+ * Note - we always use TASK_INTERRUPTIBLE even if the module
+ * was loaded as part of the kernel. The reason is that
+ * UNINTERRUPTIBLE would cause this thread to be counted in
+ * the load average as a running process, and an interruptible
+ * wait doesn't.
*/
- SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
- " scsi_eh_%d\n",shost->host_no));
-
- complete(shost->eh_notify);
-
- while (1) {
- /*
- * If we get a signal, it means we are supposed to go
- * away and die. This typically happens if the user is
- * trying to unload a module.
- */
- SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
- " scsi_eh_%d"
- " sleeping\n",shost->host_no));
-
- /*
- * Note - we always use down_interruptible with the semaphore
- * even if the module was loaded as part of the kernel. The
- * reason is that down() will cause this thread to be counted
- * in the load average as a running process, and down
- * interruptible doesn't. Given that we need to allow this
- * thread to die if the driver was loaded as a module, using
- * semaphores isn't unreasonable.
- */
- down_interruptible(&sem);
- if (shost->eh_kill)
- break;
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (!kthread_should_stop()) {
+ if (shost->host_failed == 0 ||
+ shost->host_failed != shost->host_busy) {
+ SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
+ " scsi_eh_%d"
+ " sleeping\n",
+ shost->host_no));
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ continue;
+ }
+ __set_current_state(TASK_RUNNING);
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d waking"
" up\n",shost->host_no));
@@ -1650,32 +1642,18 @@ int scsi_error_handler(void *data)
* which are still online.
*/
scsi_restart_operations(shost);
-
+ set_current_state(TASK_INTERRUPTIBLE);
}
+ __set_current_state(TASK_RUNNING);
+
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
" exiting\n",shost->host_no));
/*
* Make sure that nobody tries to wake us up again.
*/
- shost->eh_wait = NULL;
-
- /*
- * Knock this down too. From this point on, the host is flying
- * without a pilot. If this is because the module is being unloaded,
- * that's fine. If the user sent a signal to this thing, we are
- * potentially in real danger.
- */
- shost->eh_active = 0;
shost->ehandler = NULL;
-
- /*
- * If anyone is waiting for us to exit (i.e. someone trying to unload
- * a driver), then wake up that process to let them know we are on
- * the way out the door.
- */
- complete_and_exit(shost->eh_notify, 0);
return 0;
}
@@ -1846,12 +1824,16 @@ EXPORT_SYMBOL(scsi_reset_provider);
int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
struct scsi_sense_hdr *sshdr)
{
- if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70)
+ if (!sense_buffer || !sb_len)
return 0;
memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
sshdr->response_code = (sense_buffer[0] & 0x7f);
+
+ if (!scsi_sense_valid(sshdr))
+ return 0;
+
if (sshdr->response_code >= 0x72) {
/*
* descriptor format
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 7a6b530115ac..6a3f6aae8a97 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -30,20 +30,20 @@
#define MAX_BUF PAGE_SIZE
-/*
- * If we are told to probe a host, we will return 0 if the host is not
- * present, 1 if the host is present, and will return an identifying
- * string at *arg, if arg is non null, filling to the length stored at
- * (int *) arg
+/**
+ * ioctl_probe -- return host identification
+ * @host: host to identify
+ * @buffer: userspace buffer for identification
+ *
+ * Return an identifying string at @buffer, if @buffer is non-NULL, filling
+ * to the length stored at * (int *) @buffer.
*/
-
static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
{
unsigned int len, slen;
const char *string;
- int temp = host->hostt->present;
- if (temp && buffer) {
+ if (buffer) {
if (get_user(len, (unsigned int __user *) buffer))
return -EFAULT;
@@ -59,7 +59,7 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
return -EFAULT;
}
}
- return temp;
+ return 1;
}
/*
@@ -88,25 +88,18 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
int timeout, int retries)
{
- struct scsi_request *sreq;
int result;
struct scsi_sense_hdr sshdr;
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n");
- return -ENOMEM;
- }
-
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0,
+ &sshdr, timeout, retries);
- SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result));
+ SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result));
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
- (scsi_request_normalize_sense(sreq, &sshdr))) {
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ (scsi_sense_valid(&sshdr))) {
switch (sshdr.sense_key) {
case ILLEGAL_REQUEST:
if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
@@ -125,7 +118,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
case UNIT_ATTENTION:
if (sdev->removable) {
sdev->changed = 1;
- sreq->sr_result = 0; /* This is no longer considered an error */
+ result = 0; /* This is no longer considered an error */
break;
}
default: /* Fall through for non-removable media */
@@ -135,15 +128,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
sdev->channel,
sdev->id,
sdev->lun,
- sreq->sr_result);
- scsi_print_req_sense(" ", sreq);
+ result);
+ scsi_print_sense_hdr(" ", &sshdr);
break;
}
}
- result = sreq->sr_result;
SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n"));
- scsi_release_request(sreq);
return result;
}
@@ -208,13 +199,14 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
{
char *buf;
unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
char __user *cmd_in;
- struct scsi_request *sreq;
unsigned char opcode;
unsigned int inlen, outlen, cmdlen;
unsigned int needed, buf_needed;
int timeout, retries, result;
- int data_direction, gfp_mask = GFP_KERNEL;
+ int data_direction;
+ gfp_t gfp_mask = GFP_KERNEL;
if (!sic)
return -EINVAL;
@@ -321,31 +313,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
break;
}
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- result = -EINTR;
- goto error;
- }
-
- sreq->sr_data_direction = data_direction;
- scsi_wait_req(sreq, cmd, buf, needed, timeout, retries);
+ result = scsi_execute(sdev, cmd, data_direction, buf, needed,
+ sense, timeout, retries, 0);
/*
* If there was an error condition, pass the info back to the user.
*/
- result = sreq->sr_result;
if (result) {
- int sb_len = sizeof(sreq->sr_sense_buffer);
+ int sb_len = sizeof(*sense);
sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
- if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len))
+ if (copy_to_user(cmd_in, sense, sb_len))
result = -EFAULT;
} else {
if (copy_to_user(cmd_in, buf, outlen))
result = -EFAULT;
}
- scsi_release_request(sreq);
error:
kfree(buf);
return result;
@@ -475,8 +459,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
* error processing, as long as the device was opened
* non-blocking */
if (filp && filp->f_flags & O_NONBLOCK) {
- if (test_bit(SHOST_RECOVERY,
- &sdev->host->shost_state))
+ if (scsi_host_in_recovery(sdev->host))
return -ENODEV;
} else if (!scsi_block_when_processing_errors(sdev))
return -ENODEV;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7a91ca3d32a6..3ff538809786 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -99,6 +99,28 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
static void scsi_run_queue(struct request_queue *q);
/*
+ * Function: scsi_unprep_request()
+ *
+ * Purpose: Remove all preparation done for a request, including its
+ * associated scsi_cmnd, so that it can be requeued.
+ *
+ * Arguments: req - request to unprepare
+ *
+ * Lock status: Assumed that no locks are held upon entry.
+ *
+ * Returns: Nothing.
+ */
+static void scsi_unprep_request(struct request *req)
+{
+ struct scsi_cmnd *cmd = req->special;
+
+ req->flags &= ~REQ_DONTPREP;
+ req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+
+ scsi_put_command(cmd);
+}
+
+/*
* Function: scsi_queue_insert()
*
* Purpose: Insert a command in the midlevel queue.
@@ -232,23 +254,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
}
EXPORT_SYMBOL(scsi_do_req);
-static void scsi_wait_done(struct scsi_cmnd *cmd)
-{
- struct request *req = cmd->request;
- struct request_queue *q = cmd->device->request_queue;
- unsigned long flags;
-
- req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
-
- spin_lock_irqsave(q->queue_lock, flags);
- if (blk_rq_tagged(req))
- blk_queue_end_tag(q, req);
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- if (req->waiting)
- complete(req->waiting);
-}
-
/* This is the end routine we get to if a command was never attached
* to the request. Simply complete the request without changing
* rq_status; this will cause a DRIVER_ERROR. */
@@ -263,21 +268,114 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
unsigned bufflen, int timeout, int retries)
{
DECLARE_COMPLETION(wait);
-
- sreq->sr_request->waiting = &wait;
- sreq->sr_request->rq_status = RQ_SCSI_BUSY;
- sreq->sr_request->end_io = scsi_wait_req_end_io;
- scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
- timeout, retries);
+ int write = (sreq->sr_data_direction == DMA_TO_DEVICE);
+ struct request *req;
+
+ req = blk_get_request(sreq->sr_device->request_queue, write,
+ __GFP_WAIT);
+ if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req,
+ buffer, bufflen, __GFP_WAIT)) {
+ sreq->sr_result = DRIVER_ERROR << 24;
+ blk_put_request(req);
+ return;
+ }
+
+ req->flags |= REQ_NOMERGE;
+ req->waiting = &wait;
+ req->end_io = scsi_wait_req_end_io;
+ req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]);
+ req->sense = sreq->sr_sense_buffer;
+ req->sense_len = 0;
+ memcpy(req->cmd, cmnd, req->cmd_len);
+ req->timeout = timeout;
+ req->flags |= REQ_BLOCK_PC;
+ req->rq_disk = NULL;
+ blk_insert_request(sreq->sr_device->request_queue, req,
+ sreq->sr_data_direction == DMA_TO_DEVICE, NULL);
wait_for_completion(&wait);
sreq->sr_request->waiting = NULL;
- if (sreq->sr_request->rq_status != RQ_SCSI_DONE)
+ sreq->sr_result = req->errors;
+ if (req->errors)
sreq->sr_result |= (DRIVER_ERROR << 24);
- __scsi_release_request(sreq);
+ blk_put_request(req);
}
+
EXPORT_SYMBOL(scsi_wait_req);
+/**
+ * scsi_execute - insert request and wait for the result
+ * @sdev: scsi device
+ * @cmd: scsi command
+ * @data_direction: data direction
+ * @buffer: data buffer
+ * @bufflen: len of buffer
+ * @sense: optional sense buffer
+ * @timeout: request timeout in seconds
+ * @retries: number of times to retry request
+ * @flags: or into request flags;
+ *
+ * returns the req->errors value which is the the scsi_cmnd result
+ * field.
+ **/
+int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ unsigned char *sense, int timeout, int retries, int flags)
+{
+ struct request *req;
+ int write = (data_direction == DMA_TO_DEVICE);
+ int ret = DRIVER_ERROR << 24;
+
+ req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+
+ if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
+ buffer, bufflen, __GFP_WAIT))
+ goto out;
+
+ req->cmd_len = COMMAND_SIZE(cmd[0]);
+ memcpy(req->cmd, cmd, req->cmd_len);
+ req->sense = sense;
+ req->sense_len = 0;
+ req->timeout = timeout;
+ req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+
+ /*
+ * head injection *required* here otherwise quiesce won't work
+ */
+ blk_execute_rq(req->q, NULL, req, 1);
+
+ ret = req->errors;
+ out:
+ blk_put_request(req);
+
+ return ret;
+}
+EXPORT_SYMBOL(scsi_execute);
+
+
+int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ struct scsi_sense_hdr *sshdr, int timeout, int retries)
+{
+ char *sense = NULL;
+ int result;
+
+ if (sshdr) {
+ sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+ if (!sense)
+ return DRIVER_ERROR << 24;
+ memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
+ }
+ result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
+ sense, timeout, retries, 0);
+ if (sshdr)
+ scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
+
+ kfree(sense);
+ return result;
+}
+EXPORT_SYMBOL(scsi_execute_req);
+
/*
* Function: scsi_init_cmd_errh()
*
@@ -348,7 +446,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
- if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) &&
+ if (unlikely(scsi_host_in_recovery(shost) &&
shost->host_failed))
scsi_eh_wakeup(shost);
spin_unlock(shost->host_lock);
@@ -476,15 +574,16 @@ static void scsi_run_queue(struct request_queue *q)
* I/O errors in the middle of the request, in which case
* we need to request the blocks that come after the bad
* sector.
+ * Notes: Upon return, cmd is a stale pointer.
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
+ struct request *req = cmd->request;
unsigned long flags;
- cmd->request->flags &= ~REQ_DONTPREP;
-
+ scsi_unprep_request(req);
spin_lock_irqsave(q->queue_lock, flags);
- blk_requeue_request(q, cmd->request);
+ blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
@@ -519,13 +618,14 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
*
* Lock status: Assumed that lock is not held upon entry.
*
- * Returns: cmd if requeue done or required, NULL otherwise
+ * Returns: cmd if requeue required, NULL otherwise.
*
* Notes: This is called for block device requests in order to
* mark some number of sectors as complete.
*
* We are guaranteeing that the request queue will be goosed
* at some point during this call.
+ * Notes: If cmd was requeued, upon return it will be a stale pointer.
*/
static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
int bytes, int requeue)
@@ -548,14 +648,15 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
if (!uptodate && blk_noretry_request(req))
end_that_request_chunk(req, 0, leftover);
else {
- if (requeue)
+ if (requeue) {
/*
* Bleah. Leftovers again. Stick the
* leftovers in the front of the
* queue, and goose the queue again.
*/
scsi_requeue_command(q, cmd);
-
+ cmd = NULL;
+ }
return cmd;
}
}
@@ -576,7 +677,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
return NULL;
}
-static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mask)
+static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
@@ -781,15 +882,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
* requeueing right here - we will requeue down below
* when we handle the bad sectors.
*/
- cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);
/*
- * If the command completed without error, then either finish off the
- * rest of the command, or start a new one.
+ * If the command completed without error, then either
+ * finish off the rest of the command, or start a new one.
*/
- if (result == 0 || cmd == NULL ) {
+ if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)
return;
- }
}
/*
* Now, if we were good little boys and girls, Santa left us a request
@@ -804,7 +903,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
* and quietly refuse further access.
*/
cmd->device->changed = 1;
- cmd = scsi_end_request(cmd, 0,
+ scsi_end_request(cmd, 0,
this_count, 1);
return;
} else {
@@ -838,7 +937,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
scsi_requeue_command(q, cmd);
result = 0;
} else {
- cmd = scsi_end_request(cmd, 0, this_count, 1);
+ scsi_end_request(cmd, 0, this_count, 1);
return;
}
break;
@@ -851,18 +950,21 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
scsi_requeue_command(q, cmd);
return;
}
- printk(KERN_INFO "Device %s not ready.\n",
- req->rq_disk ? req->rq_disk->disk_name : "");
- cmd = scsi_end_request(cmd, 0, this_count, 1);
+ if (!(req->flags & REQ_QUIET))
+ dev_printk(KERN_INFO,
+ &cmd->device->sdev_gendev,
+ "Device not ready.\n");
+ scsi_end_request(cmd, 0, this_count, 1);
return;
case VOLUME_OVERFLOW:
- printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ",
- cmd->device->host->host_no,
- (int)cmd->device->channel,
- (int)cmd->device->id, (int)cmd->device->lun);
- __scsi_print_command(cmd->data_cmnd);
- scsi_print_sense("", cmd);
- cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+ if (!(req->flags & REQ_QUIET)) {
+ dev_printk(KERN_INFO,
+ &cmd->device->sdev_gendev,
+ "Volume overflow, CDB: ");
+ __scsi_print_command(cmd->data_cmnd);
+ scsi_print_sense("", cmd);
+ }
+ scsi_end_request(cmd, 0, block_bytes, 1);
return;
default:
break;
@@ -878,14 +980,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
return;
}
if (result) {
- printk(KERN_INFO "SCSI error : <%d %d %d %d> return code "
- "= 0x%x\n", cmd->device->host->host_no,
- cmd->device->channel,
- cmd->device->id,
- cmd->device->lun, result);
-
- if (driver_byte(result) & DRIVER_SENSE)
- scsi_print_sense("", cmd);
+ if (!(req->flags & REQ_QUIET)) {
+ dev_printk(KERN_INFO, &cmd->device->sdev_gendev,
+ "SCSI error: return code = 0x%x\n", result);
+
+ if (driver_byte(result) & DRIVER_SENSE)
+ scsi_print_sense("", cmd);
+ }
/*
* Mark a single buffer as not uptodate. Queue the remainder.
* We sometimes get this cruft in the event that a medium error
@@ -894,7 +995,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
block_bytes = req->hard_cur_sectors << 9;
if (!block_bytes)
block_bytes = req->data_len;
- cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+ scsi_end_request(cmd, 0, block_bytes, 1);
}
}
EXPORT_SYMBOL(scsi_io_completion);
@@ -938,8 +1039,10 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
- if (unlikely(!sgpnt))
+ if (unlikely(!sgpnt)) {
+ scsi_unprep_request(req);
return BLKPREP_DEFER;
+ }
cmd->request_buffer = (char *) sgpnt;
cmd->request_bufflen = req->nr_sectors << 9;
@@ -1020,6 +1123,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
return -EOPNOTSUPP;
}
+static void scsi_generic_done(struct scsi_cmnd *cmd)
+{
+ BUG_ON(!blk_pc_request(cmd->request));
+ scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
+}
+
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
struct scsi_device *sdev = q->queuedata;
@@ -1034,7 +1143,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
if (unlikely(!scsi_device_online(sdev))) {
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
/* OK, we're not in a running state don't prep
@@ -1044,7 +1153,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* at all allowed down */
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
/* OK, we only allow special commands (i.e. not
* user initiated ones */
@@ -1061,7 +1170,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* these two cases differently. We differentiate by looking
* at request->cmd, as this tells us the real story.
*/
- if (req->flags & REQ_SPECIAL) {
+ if (req->flags & REQ_SPECIAL && req->special) {
struct scsi_request *sreq = req->special;
if (sreq->sr_magic == SCSI_REQ_MAGIC) {
@@ -1073,14 +1182,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
cmd = req->special;
} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
- if(unlikely(specials_only)) {
+ if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
if(specials_only == SDEV_QUIESCE ||
specials_only == SDEV_BLOCK)
- return BLKPREP_DEFER;
+ goto defer;
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
sdev->host->host_no, sdev->id, sdev->lun);
- return BLKPREP_KILL;
+ goto kill;
}
@@ -1098,7 +1207,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
cmd->tag = req->tag;
} else {
blk_dump_rq_flags(req, "SCSI bad req");
- return BLKPREP_KILL;
+ goto kill;
}
/* note the overloading of req->special. When the tag
@@ -1136,17 +1245,38 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* required).
*/
ret = scsi_init_io(cmd);
- if (ret) /* BLKPREP_KILL return also releases the command */
- return ret;
+ switch(ret) {
+ /* For BLKPREP_KILL/DEFER the cmd was released */
+ case BLKPREP_KILL:
+ goto kill;
+ case BLKPREP_DEFER:
+ goto defer;
+ }
/*
* Initialize the actual SCSI command for this request.
*/
- drv = *(struct scsi_driver **)req->rq_disk->private_data;
- if (unlikely(!drv->init_command(cmd))) {
- scsi_release_buffers(cmd);
- scsi_put_command(cmd);
- return BLKPREP_KILL;
+ if (req->rq_disk) {
+ drv = *(struct scsi_driver **)req->rq_disk->private_data;
+ if (unlikely(!drv->init_command(cmd))) {
+ scsi_release_buffers(cmd);
+ scsi_put_command(cmd);
+ goto kill;
+ }
+ } else {
+ memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+ cmd->cmd_len = req->cmd_len;
+ if (rq_data_dir(req) == WRITE)
+ cmd->sc_data_direction = DMA_TO_DEVICE;
+ else if (req->data_len)
+ cmd->sc_data_direction = DMA_FROM_DEVICE;
+ else
+ cmd->sc_data_direction = DMA_NONE;
+
+ cmd->transfersize = req->data_len;
+ cmd->allowed = 3;
+ cmd->timeout_per_command = req->timeout;
+ cmd->done = scsi_generic_done;
}
}
@@ -1163,6 +1293,9 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
if (sdev->device_busy == 0)
blk_plug_device(q);
return BLKPREP_DEFER;
+ kill:
+ req->errors = DID_NO_CONNECT << 16;
+ return BLKPREP_KILL;
}
/*
@@ -1207,7 +1340,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
struct Scsi_Host *shost,
struct scsi_device *sdev)
{
- if (test_bit(SHOST_RECOVERY, &shost->shost_state))
+ if (scsi_host_in_recovery(shost))
return 0;
if (shost->host_busy == 0 && shost->host_blocked) {
/*
@@ -1237,19 +1370,24 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
}
/*
- * Kill requests for a dead device
+ * Kill a request for a dead device
*/
-static void scsi_kill_requests(request_queue_t *q)
+static void scsi_kill_request(struct request *req, request_queue_t *q)
{
- struct request *req;
+ struct scsi_cmnd *cmd = req->special;
+
+ blkdev_dequeue_request(req);
- while ((req = elv_next_request(q)) != NULL) {
- blkdev_dequeue_request(req);
- req->flags |= REQ_QUIET;
- while (end_that_request_first(req, 0, req->nr_sectors))
- ;
- end_that_request_last(req);
+ if (unlikely(cmd == NULL)) {
+ printk(KERN_CRIT "impossible request in %s.\n",
+ __FUNCTION__);
+ BUG();
}
+
+ scsi_init_cmd_errh(cmd);
+ cmd->result = DID_NO_CONNECT << 16;
+ atomic_inc(&cmd->device->iorequest_cnt);
+ __scsi_done(cmd);
}
/*
@@ -1272,7 +1410,8 @@ static void scsi_request_fn(struct request_queue *q)
if (!sdev) {
printk("scsi: killing requests for dead queue\n");
- scsi_kill_requests(q);
+ while ((req = elv_next_request(q)) != NULL)
+ scsi_kill_request(req, q);
return;
}
@@ -1299,11 +1438,7 @@ static void scsi_request_fn(struct request_queue *q)
if (unlikely(!scsi_device_online(sdev))) {
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
sdev->host->host_no, sdev->id, sdev->lun);
- blkdev_dequeue_request(req);
- req->flags |= REQ_QUIET;
- while (end_that_request_first(req, 0, req->nr_sectors))
- ;
- end_that_request_last(req);
+ scsi_kill_request(req, q);
continue;
}
@@ -1316,6 +1451,14 @@ static void scsi_request_fn(struct request_queue *q)
sdev->device_busy++;
spin_unlock(q->queue_lock);
+ cmd = req->special;
+ if (unlikely(cmd == NULL)) {
+ printk(KERN_CRIT "impossible request in %s.\n"
+ "please mail a stack trace to "
+ "linux-scsi@vger.kernel.org",
+ __FUNCTION__);
+ BUG();
+ }
spin_lock(shost->host_lock);
if (!scsi_host_queue_ready(q, shost, sdev))
@@ -1334,15 +1477,6 @@ static void scsi_request_fn(struct request_queue *q)
*/
spin_unlock_irq(shost->host_lock);
- cmd = req->special;
- if (unlikely(cmd == NULL)) {
- printk(KERN_CRIT "impossible request in %s.\n"
- "please mail a stack trace to "
- "linux-scsi@vger.kernel.org",
- __FUNCTION__);
- BUG();
- }
-
/*
* Finally, initialize any error handling parameters, and set up
* the timers for timeouts.
@@ -1539,9 +1673,9 @@ void scsi_exit_queue(void)
}
}
/**
- * __scsi_mode_sense - issue a mode sense, falling back from 10 to
+ * scsi_mode_sense - issue a mode sense, falling back from 10 to
* six bytes if necessary.
- * @sreq: SCSI request to fill in with the MODE_SENSE
+ * @sdev: SCSI device to be queried
* @dbd: set if mode sense will allow block descriptors to be returned
* @modepage: mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
@@ -1549,26 +1683,34 @@ void scsi_exit_queue(void)
* @timeout: command timeout
* @retries: number of retries before failing
* @data: returns a structure abstracting the mode header data
+ * @sense: place to put sense data (or NULL if no sense to be collected).
+ * must be SCSI_SENSE_BUFFERSIZE big.
*
* Returns zero if unsuccessful, or the header offset (either 4
* or 8 depending on whether a six or ten byte command was
* issued) if successful.
**/
int
-__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data) {
+ struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) {
unsigned char cmd[12];
int use_10_for_ms;
int header_length;
+ int result;
+ struct scsi_sense_hdr my_sshdr;
memset(data, 0, sizeof(*data));
memset(&cmd[0], 0, 12);
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
+ /* caller might not be interested in sense, but we need it */
+ if (!sshdr)
+ sshdr = &my_sshdr;
+
retry:
- use_10_for_ms = sreq->sr_device->use_10_for_ms;
+ use_10_for_ms = sdev->use_10_for_ms;
if (use_10_for_ms) {
if (len < 8)
@@ -1586,36 +1728,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
header_length = 4;
}
- sreq->sr_cmd_len = 0;
- memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
memset(buffer, 0, len);
- scsi_wait_req(sreq, cmd, buffer, len, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+ sshdr, timeout, retries);
/* This code looks awful: what it's doing is making sure an
* ILLEGAL REQUEST sense return identifies the actual command
* byte as the problem. MODE_SENSE commands can return
* ILLEGAL REQUEST if the code page isn't supported */
- if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) &&
- (driver_byte(sreq->sr_result) & DRIVER_SENSE)) {
- struct scsi_sense_hdr sshdr;
-
- if (scsi_request_normalize_sense(sreq, &sshdr)) {
- if ((sshdr.sense_key == ILLEGAL_REQUEST) &&
- (sshdr.asc == 0x20) && (sshdr.ascq == 0)) {
+ if (use_10_for_ms && !scsi_status_is_good(result) &&
+ (driver_byte(result) & DRIVER_SENSE)) {
+ if (scsi_sense_valid(sshdr)) {
+ if ((sshdr->sense_key == ILLEGAL_REQUEST) &&
+ (sshdr->asc == 0x20) && (sshdr->ascq == 0)) {
/*
* Invalid command operation code
*/
- sreq->sr_device->use_10_for_ms = 0;
+ sdev->use_10_for_ms = 0;
goto retry;
}
}
}
- if(scsi_status_is_good(sreq->sr_result)) {
+ if(scsi_status_is_good(result)) {
data->header_length = header_length;
if(use_10_for_ms) {
data->length = buffer[0]*256 + buffer[1] + 2;
@@ -1632,73 +1769,31 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
}
}
- return sreq->sr_result;
-}
-EXPORT_SYMBOL(__scsi_mode_sense);
-
-/**
- * scsi_mode_sense - issue a mode sense, falling back from 10 to
- * six bytes if necessary.
- * @sdev: scsi device to send command to.
- * @dbd: set if mode sense will disable block descriptors in the return
- * @modepage: mode page being requested
- * @buffer: request buffer (may not be smaller than eight bytes)
- * @len: length of request buffer.
- * @timeout: command timeout
- * @retries: number of retries before failing
- *
- * Returns zero if unsuccessful, or the header offset (either 4
- * or 8 depending on whether a six or ten byte command was
- * issued) if successful.
- **/
-int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
- unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data)
-{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- int ret;
-
- if (!sreq)
- return -1;
-
- ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len,
- timeout, retries, data);
-
- scsi_release_request(sreq);
-
- return ret;
+ return result;
}
EXPORT_SYMBOL(scsi_mode_sense);
int
scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
{
- struct scsi_request *sreq;
char cmd[] = {
TEST_UNIT_READY, 0, 0, 0, 0, 0,
};
+ struct scsi_sense_hdr sshdr;
int result;
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq)
- return -ENOMEM;
-
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr,
+ timeout, retries);
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) {
- struct scsi_sense_hdr sshdr;
+ if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
- if ((scsi_request_normalize_sense(sreq, &sshdr)) &&
+ if ((scsi_sense_valid(&sshdr)) &&
((sshdr.sense_key == UNIT_ATTENTION) ||
(sshdr.sense_key == NOT_READY))) {
sdev->changed = 1;
- sreq->sr_result = 0;
+ result = 0;
}
}
- result = sreq->sr_result;
- scsi_release_request(sreq);
return result;
}
EXPORT_SYMBOL(scsi_test_unit_ready);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index d30d7f4e63ec..d05f778d31a8 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -63,6 +63,9 @@ 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 int scsi_error_handler(void *host);
extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
@@ -121,6 +124,7 @@ extern void scsi_sysfs_unregister(void);
extern void scsi_sysfs_device_initialize(struct scsi_device *);
extern int scsi_sysfs_target_initialize(struct scsi_device *);
extern struct scsi_transport_template blank_transport_template;
+extern void __scsi_remove_device(struct scsi_device *);
extern struct bus_type scsi_bus_type;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 2d3c4ac475f2..327c5d7e5bd2 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout,
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
- * @sreq: used to send the command
+ * @sdev: scsi device to send command to
* @result: area to store the result of the MODE SENSE
*
* Description:
- * Send a vendor specific MODE SENSE (not a MODE SELECT) command using
- * @sreq to unlock a device, storing the (unused) results into result.
+ * Send a vendor specific MODE SENSE (not a MODE SELECT) command.
* Called for BLIST_KEY devices.
**/
-static void scsi_unlock_floptical(struct scsi_request *sreq,
+static void scsi_unlock_floptical(struct scsi_device *sdev,
unsigned char *result)
{
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
@@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq,
scsi_cmd[1] = 0;
scsi_cmd[2] = 0x2e;
scsi_cmd[3] = 0;
- scsi_cmd[4] = 0x2a; /* size */
+ scsi_cmd[4] = 0x2a; /* size */
scsi_cmd[5] = 0;
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
- scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3);
+ scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL,
+ SCSI_TIMEOUT, 3);
}
/**
@@ -336,9 +334,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
unsigned long flags;
const int size = sizeof(struct scsi_target)
+ shost->transportt->target_size;
- struct scsi_target *starget = kmalloc(size, GFP_ATOMIC);
+ struct scsi_target *starget;
struct scsi_target *found_target;
+ /*
+ * Obtain the real parent from the transport. The transport
+ * is allowed to fail (no error) if there is nothing at that
+ * target id.
+ */
+ if (shost->transportt->target_parent) {
+ spin_lock_irqsave(shost->host_lock, flags);
+ parent = shost->transportt->target_parent(shost, channel, id);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ if (!parent)
+ return NULL;
+ }
+
+ starget = kmalloc(size, GFP_KERNEL);
if (!starget) {
printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
return NULL;
@@ -419,26 +431,25 @@ void scsi_target_reap(struct scsi_target *starget)
/**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
- * @sreq: used to send the INQUIRY
+ * @sdev: scsi_device to probe
* @inq_result: area to store the INQUIRY result
+ * @result_len: len of inq_result
* @bflags: store any bflags found here
*
* Description:
- * Probe the lun associated with @sreq using a standard SCSI INQUIRY;
+ * Probe the lun associated with @req using a standard SCSI INQUIRY;
*
- * If the INQUIRY is successful, sreq->sr_result is zero and: the
+ * If the INQUIRY is successful, zero is returned and the
* INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
- * are copied to the Scsi_Device at @sreq->sr_device (sdev);
- * any flags value is stored in *@bflags.
+ * are copied to the Scsi_Device any flags value is stored in *@bflags.
**/
-static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
- int *bflags)
+static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
+ int result_len, int *bflags)
{
- struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
int first_inquiry_len, try_inquiry_len, next_inquiry_len;
int response_len = 0;
- int pass, count;
+ int pass, count, result;
struct scsi_sense_hdr sshdr;
*bflags = 0;
@@ -461,28 +472,26 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
memset(scsi_cmd, 0, 6);
scsi_cmd[0] = INQUIRY;
scsi_cmd[4] = (unsigned char) try_inquiry_len;
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
memset(inq_result, 0, try_inquiry_len);
- scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result,
- try_inquiry_len,
- HZ/2 + HZ*scsi_inq_timeout, 3);
+
+ result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
+ inq_result, try_inquiry_len, &sshdr,
+ HZ / 2 + HZ * scsi_inq_timeout, 3);
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s "
"with code 0x%x\n",
- sreq->sr_result ? "failed" : "successful",
- sreq->sr_result));
+ result ? "failed" : "successful", result));
- if (sreq->sr_result) {
+ if (result) {
/*
* not-ready to ready transition [asc/ascq=0x28/0x0]
* or power-on, reset [asc/ascq=0x29/0x0], continue.
* INQUIRY should not yield UNIT_ATTENTION
* but many buggy devices do so anyway.
*/
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
- scsi_request_normalize_sense(sreq, &sshdr)) {
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ scsi_sense_valid(&sshdr)) {
if ((sshdr.sense_key == UNIT_ATTENTION) &&
((sshdr.asc == 0x28) ||
(sshdr.asc == 0x29)) &&
@@ -493,7 +502,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
break;
}
- if (sreq->sr_result == 0) {
+ if (result == 0) {
response_len = (unsigned char) inq_result[4] + 5;
if (response_len > 255)
response_len = first_inquiry_len; /* sanity */
@@ -542,8 +551,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
/* If the last transfer attempt got an error, assume the
* peripheral doesn't exist or is dead. */
- if (sreq->sr_result)
- return;
+ if (result)
+ return -EIO;
/* Don't report any more data than the device says is valid */
sdev->inquiry_len = min(try_inquiry_len, response_len);
@@ -578,8 +587,9 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
if (sdev->scsi_level >= 2 ||
(sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1))
sdev->scsi_level++;
+ sdev->sdev_target->scsi_level = sdev->scsi_level;
- return;
+ return 0;
}
/**
@@ -762,6 +772,15 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
return SCSI_SCAN_LUN_PRESENT;
}
+static inline void scsi_destroy_sdev(struct scsi_device *sdev)
+{
+ if (sdev->host->hostt->slave_destroy)
+ sdev->host->hostt->slave_destroy(sdev);
+ transport_destroy_device(&sdev->sdev_gendev);
+ put_device(&sdev->sdev_gendev);
+}
+
+
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
* @starget: pointer to target device structure
@@ -786,18 +805,17 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
void *hostdata)
{
struct scsi_device *sdev;
- struct scsi_request *sreq;
unsigned char *result;
- int bflags, res = SCSI_SCAN_NO_RESPONSE;
+ int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
/*
* The rescan flag is used as an optimization, the first scan of a
* host adapter calls into here with rescan == 0.
*/
- if (rescan) {
- sdev = scsi_device_lookup_by_target(starget, lun);
- if (sdev) {
+ sdev = scsi_device_lookup_by_target(starget, lun);
+ if (sdev) {
+ if (rescan || sdev->sdev_state != SDEV_CREATED) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: device exists on %s\n",
sdev->sdev_gendev.bus_id));
@@ -812,21 +830,18 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
sdev->model);
return SCSI_SCAN_LUN_PRESENT;
}
- }
-
- sdev = scsi_alloc_sdev(starget, lun, hostdata);
+ scsi_device_put(sdev);
+ } else
+ sdev = scsi_alloc_sdev(starget, lun, hostdata);
if (!sdev)
goto out;
- sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
- if (!sreq)
- goto out_free_sdev;
- result = kmalloc(256, GFP_ATOMIC |
+
+ result = kmalloc(result_len, GFP_ATOMIC |
((shost->unchecked_isa_dma) ? __GFP_DMA : 0));
if (!result)
- goto out_free_sreq;
+ goto out_free_sdev;
- scsi_probe_lun(sreq, result, &bflags);
- if (sreq->sr_result)
+ if (scsi_probe_lun(sdev, result, result_len, &bflags))
goto out_free_result;
/*
@@ -854,7 +869,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
if (res == SCSI_SCAN_LUN_PRESENT) {
if (bflags & BLIST_KEY) {
sdev->lockable = 0;
- scsi_unlock_floptical(sreq, result);
+ scsi_unlock_floptical(sdev, result);
}
if (bflagsp)
*bflagsp = bflags;
@@ -862,20 +877,18 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
out_free_result:
kfree(result);
- out_free_sreq:
- scsi_release_request(sreq);
out_free_sdev:
if (res == SCSI_SCAN_LUN_PRESENT) {
if (sdevp) {
- scsi_device_get(sdev);
- *sdevp = sdev;
+ if (scsi_device_get(sdev) == 0) {
+ *sdevp = sdev;
+ } else {
+ __scsi_remove_device(sdev);
+ res = SCSI_SCAN_NO_RESPONSE;
+ }
}
- } else {
- if (sdev->host->hostt->slave_destroy)
- sdev->host->hostt->slave_destroy(sdev);
- transport_destroy_device(&sdev->sdev_gendev);
- put_device(&sdev->sdev_gendev);
- }
+ } else
+ scsi_destroy_sdev(sdev);
out:
return res;
}
@@ -1047,7 +1060,7 @@ EXPORT_SYMBOL(int_to_scsilun);
* 0: scan completed (or no memory, so further scanning is futile)
* 1: no report lun scan, or not configured
**/
-static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
+static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
int rescan)
{
char devname[64];
@@ -1056,11 +1069,12 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
unsigned int lun;
unsigned int num_luns;
unsigned int retries;
+ int result;
struct scsi_lun *lunp, *lun_data;
- struct scsi_request *sreq;
u8 *data;
struct scsi_sense_hdr sshdr;
- struct scsi_target *starget = scsi_target(sdev);
+ struct scsi_device *sdev;
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
/*
* Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
@@ -1068,19 +1082,23 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
* support more than 8 LUNs.
*/
if ((bflags & BLIST_NOREPORTLUN) ||
- sdev->scsi_level < SCSI_2 ||
- (sdev->scsi_level < SCSI_3 &&
- (!(bflags & BLIST_REPORTLUN2) || sdev->host->max_lun <= 8)) )
+ starget->scsi_level < SCSI_2 ||
+ (starget->scsi_level < SCSI_3 &&
+ (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
return 1;
if (bflags & BLIST_NOLUN)
return 0;
- sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
- if (!sreq)
- goto out;
+ if (!(sdev = scsi_device_lookup_by_target(starget, 0))) {
+ sdev = scsi_alloc_sdev(starget, 0, NULL);
+ if (!sdev)
+ return 0;
+ if (scsi_device_get(sdev))
+ return 0;
+ }
sprintf(devname, "host %d channel %d id %d",
- sdev->host->host_no, sdev->channel, sdev->id);
+ shost->host_no, sdev->channel, sdev->id);
/*
* Allocate enough to hold the header (the same size as one scsi_lun)
@@ -1095,8 +1113,10 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun);
lun_data = kmalloc(length, GFP_ATOMIC |
(sdev->host->unchecked_isa_dma ? __GFP_DMA : 0));
- if (!lun_data)
- goto out_release_request;
+ if (!lun_data) {
+ printk(ALLOC_FAILURE_MSG, __FUNCTION__);
+ goto out;
+ }
scsi_cmd[0] = REPORT_LUNS;
@@ -1115,8 +1135,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
scsi_cmd[10] = 0; /* reserved */
scsi_cmd[11] = 0; /* control */
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
/*
* We can get a UNIT ATTENTION, for example a power on/reset, so
@@ -1132,29 +1150,29 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending"
" REPORT LUNS to %s (try %d)\n", devname,
retries));
- scsi_wait_req(sreq, scsi_cmd, lun_data, length,
- SCSI_TIMEOUT + 4*HZ, 3);
+
+ result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
+ lun_data, length, &sshdr,
+ SCSI_TIMEOUT + 4 * HZ, 3);
+
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS"
- " %s (try %d) result 0x%x\n", sreq->sr_result
- ? "failed" : "successful", retries,
- sreq->sr_result));
- if (sreq->sr_result == 0)
+ " %s (try %d) result 0x%x\n", result
+ ? "failed" : "successful", retries, result));
+ if (result == 0)
break;
- else if (scsi_request_normalize_sense(sreq, &sshdr)) {
+ else if (scsi_sense_valid(&sshdr)) {
if (sshdr.sense_key != UNIT_ATTENTION)
break;
}
}
- if (sreq->sr_result) {
+ if (result) {
/*
* The device probably does not support a REPORT LUN command
*/
kfree(lun_data);
- scsi_release_request(sreq);
return 1;
}
- scsi_release_request(sreq);
/*
* Get the length from the first four bytes of lun_data.
@@ -1200,10 +1218,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
for (i = 0; i < sizeof(struct scsi_lun); i++)
printk("%02x", data[i]);
printk(" has a LUN larger than currently supported.\n");
- } else if (lun == 0) {
- /*
- * LUN 0 has already been scanned.
- */
} else if (lun > sdev->host->max_lun) {
printk(KERN_WARNING "scsi: %s lun%d has a LUN larger"
" than allowed by the host adapter\n",
@@ -1226,15 +1240,13 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
}
kfree(lun_data);
- return 0;
-
- out_release_request:
- scsi_release_request(sreq);
out:
- /*
- * We are out of memory, don't try scanning any further.
- */
- printk(ALLOC_FAILURE_MSG, __FUNCTION__);
+ scsi_device_put(sdev);
+ if (sdev->sdev_state == SDEV_CREATED)
+ /*
+ * the sdev we used didn't appear in the report luns scan
+ */
+ scsi_destroy_sdev(sdev);
return 0;
}
@@ -1251,9 +1263,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
get_device(&starget->dev);
down(&shost->scan_mutex);
- res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
- if (res != SCSI_SCAN_LUN_PRESENT)
- sdev = ERR_PTR(-ENODEV);
+ if (scsi_host_scan_allowed(shost)) {
+ res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
+ hostdata);
+ if (res != SCSI_SCAN_LUN_PRESENT)
+ sdev = ERR_PTR(-ENODEV);
+ }
up(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
@@ -1262,6 +1277,19 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
}
EXPORT_SYMBOL(__scsi_add_device);
+int scsi_add_device(struct Scsi_Host *host, uint channel,
+ uint target, uint lun)
+{
+ struct scsi_device *sdev =
+ __scsi_add_device(host, channel, target, lun, NULL);
+ if (IS_ERR(sdev))
+ return PTR_ERR(sdev);
+
+ scsi_device_put(sdev);
+ return 0;
+}
+EXPORT_SYMBOL(scsi_add_device);
+
void scsi_rescan_device(struct device *dev)
{
struct scsi_driver *drv;
@@ -1278,32 +1306,12 @@ void scsi_rescan_device(struct device *dev)
}
EXPORT_SYMBOL(scsi_rescan_device);
-/**
- * scsi_scan_target - scan a target id, possibly including all LUNs on the
- * target.
- * @sdevsca: Scsi_Device handle for scanning
- * @shost: host to scan
- * @channel: channel to scan
- * @id: target id to scan
- *
- * Description:
- * Scan the target id on @shost, @channel, and @id. Scan at least LUN
- * 0, and possibly all LUNs on the target id.
- *
- * Use the pre-allocated @sdevscan as a handle for the scanning. This
- * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the
- * scanning functions modify sdevscan->lun.
- *
- * First try a REPORT LUN scan, if that does not scan the target, do a
- * sequential scan of LUNs on the target id.
- **/
-void scsi_scan_target(struct device *parent, unsigned int channel,
- unsigned int id, unsigned int lun, int rescan)
+static void __scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan)
{
struct Scsi_Host *shost = dev_to_shost(parent);
int bflags = 0;
int res;
- struct scsi_device *sdev = NULL;
struct scsi_target *starget;
if (shost->this_id == id)
@@ -1312,9 +1320,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
*/
return;
-
starget = scsi_alloc_target(parent, channel, id);
-
if (!starget)
return;
@@ -1331,27 +1337,16 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
* Scan LUN 0, if there is some response, scan further. Ideally, we
* would not configure LUN 0 until all LUNs are scanned.
*/
- res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, NULL);
- if (res == SCSI_SCAN_LUN_PRESENT) {
- if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
+ res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL);
+ if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) {
+ if (scsi_report_lun_scan(starget, bflags, rescan) != 0)
/*
* The REPORT LUN did not scan the target,
* do a sequential scan.
*/
scsi_sequential_lun_scan(starget, bflags,
- res, sdev->scsi_level, rescan);
- } else if (res == SCSI_SCAN_TARGET_PRESENT) {
- /*
- * There's a target here, but lun 0 is offline so we
- * can't use the report_lun scan. Fall back to a
- * sequential lun scan with a bflags of SPARSELUN and
- * a default scsi level of SCSI_2
- */
- scsi_sequential_lun_scan(starget, BLIST_SPARSELUN,
- SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan);
+ res, starget->scsi_level, rescan);
}
- if (sdev)
- scsi_device_put(sdev);
out_reap:
/* now determine if the target has any children at all
@@ -1360,6 +1355,33 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
put_device(&starget->dev);
}
+
+/**
+ * scsi_scan_target - scan a target id, possibly including all LUNs on the
+ * target.
+ * @parent: host to scan
+ * @channel: channel to scan
+ * @id: target id to scan
+ * @lun: Specific LUN to scan or SCAN_WILD_CARD
+ * @rescan: passed to LUN scanning routines
+ *
+ * Description:
+ * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0,
+ * and possibly all LUNs on the target id.
+ *
+ * First try a REPORT LUN scan, if that does not scan the target, do a
+ * sequential scan of LUNs on the target id.
+ **/
+void scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan)
+{
+ struct Scsi_Host *shost = dev_to_shost(parent);
+
+ down(&shost->scan_mutex);
+ if (scsi_host_scan_allowed(shost))
+ __scsi_scan_target(parent, channel, id, lun, rescan);
+ up(&shost->scan_mutex);
+}
EXPORT_SYMBOL(scsi_scan_target);
static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
@@ -1385,10 +1407,12 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
order_id = shost->max_id - id - 1;
else
order_id = id;
- scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
+ __scsi_scan_target(&shost->shost_gendev, channel,
+ order_id, lun, rescan);
}
else
- scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
+ __scsi_scan_target(&shost->shost_gendev, channel,
+ id, lun, rescan);
}
int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1403,11 +1427,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
return -EINVAL;
down(&shost->scan_mutex);
- if (channel == SCAN_WILD_CARD)
- for (channel = 0; channel <= shost->max_channel; channel++)
+ if (scsi_host_scan_allowed(shost)) {
+ if (channel == SCAN_WILD_CARD)
+ for (channel = 0; channel <= shost->max_channel;
+ channel++)
+ scsi_scan_channel(shost, channel, id, lun,
+ rescan);
+ else
scsi_scan_channel(shost, channel, id, lun, rescan);
- else
- scsi_scan_channel(shost, channel, id, lun, rescan);
+ }
up(&shost->scan_mutex);
return 0;
@@ -1439,23 +1467,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
void scsi_forget_host(struct Scsi_Host *shost)
{
- struct scsi_target *starget, *tmp;
+ struct scsi_device *sdev;
unsigned long flags;
- /*
- * Ok, this look a bit strange. We always look for the first device
- * on the list as scsi_remove_device removes them from it - thus we
- * also have to release the lock.
- * We don't need to get another reference to the device before
- * releasing the lock as we already own the reference from
- * scsi_register_device that's release in scsi_remove_device. And
- * after that we don't look at sdev anymore.
- */
+ restart:
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
+ list_for_each_entry(sdev, &shost->__devices, siblings) {
+ if (sdev->sdev_state == SDEV_DEL)
+ continue;
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_remove_target(&starget->dev);
- spin_lock_irqsave(shost->host_lock, flags);
+ __scsi_remove_device(sdev);
+ goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1482,12 +1504,15 @@ void scsi_forget_host(struct Scsi_Host *shost)
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
- struct scsi_device *sdev;
+ struct scsi_device *sdev = NULL;
struct scsi_target *starget;
+ down(&shost->scan_mutex);
+ if (!scsi_host_scan_allowed(shost))
+ goto out;
starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
if (!starget)
- return NULL;
+ goto out;
sdev = scsi_alloc_sdev(starget, 0, NULL);
if (sdev) {
@@ -1495,6 +1520,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
sdev->borken = 0;
}
put_device(&starget->dev);
+ out:
+ up(&shost->scan_mutex);
return sdev;
}
EXPORT_SYMBOL(scsi_get_host_dev);
@@ -1516,10 +1543,7 @@ void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
- if (sdev->host->hostt->slave_destroy)
- sdev->host->hostt->slave_destroy(sdev);
- transport_destroy_device(&sdev->sdev_gendev);
- put_device(&sdev->sdev_gendev);
+ scsi_destroy_sdev(sdev);
}
EXPORT_SYMBOL(scsi_free_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index beed7fbe1cbe..72a6550a056c 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -48,6 +48,32 @@ const char *scsi_device_state_name(enum scsi_device_state state)
return name;
}
+static struct {
+ enum scsi_host_state value;
+ char *name;
+} shost_states[] = {
+ { SHOST_CREATED, "created" },
+ { SHOST_RUNNING, "running" },
+ { SHOST_CANCEL, "cancel" },
+ { SHOST_DEL, "deleted" },
+ { SHOST_RECOVERY, "recovery" },
+ { SHOST_CANCEL_RECOVERY, "cancel/recovery" },
+ { SHOST_DEL_RECOVERY, "deleted/recovery", },
+};
+const char *scsi_host_state_name(enum scsi_host_state state)
+{
+ int i;
+ char *name = NULL;
+
+ for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+ if (shost_states[i].value == state) {
+ name = shost_states[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
static int check_set(unsigned int *val, char *src)
{
char *last;
@@ -124,6 +150,43 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf,
};
static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+static ssize_t
+store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+{
+ int i;
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ enum scsi_host_state state = 0;
+
+ for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+ const int len = strlen(shost_states[i].name);
+ if (strncmp(shost_states[i].name, buf, len) == 0 &&
+ buf[len] == '\n') {
+ state = shost_states[i].value;
+ break;
+ }
+ }
+ if (!state)
+ return -EINVAL;
+
+ if (scsi_host_set_state(shost, state))
+ return -EINVAL;
+ return count;
+}
+
+static ssize_t
+show_shost_state(struct class_device *class_dev, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(class_dev);
+ const char *name = scsi_host_state_name(shost->shost_state);
+
+ if (!name)
+ return -EINVAL;
+
+ return snprintf(buf, 20, "%s\n", name);
+}
+
+static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+
shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -139,6 +202,7 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
&class_device_attr_unchecked_isa_dma,
&class_device_attr_proc_name,
&class_device_attr_scan,
+ &class_device_attr_state,
NULL
};
@@ -591,7 +655,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
error = attr_add(&sdev->sdev_gendev,
sdev->host->hostt->sdev_attrs[i]);
if (error) {
- scsi_remove_device(sdev);
+ __scsi_remove_device(sdev);
goto out;
}
}
@@ -605,7 +669,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
scsi_sysfs_sdev_attrs[i]);
error = device_create_file(&sdev->sdev_gendev, attr);
if (error) {
- scsi_remove_device(sdev);
+ __scsi_remove_device(sdev);
goto out;
}
}
@@ -625,17 +689,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
return error;
}
-/**
- * scsi_remove_device - unregister a device from the scsi bus
- * @sdev: scsi_device to unregister
- **/
-void scsi_remove_device(struct scsi_device *sdev)
+void __scsi_remove_device(struct scsi_device *sdev)
{
- struct Scsi_Host *shost = sdev->host;
-
- down(&shost->scan_mutex);
if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
- goto out;
+ return;
class_device_unregister(&sdev->sdev_classdev);
device_del(&sdev->sdev_gendev);
@@ -644,7 +701,18 @@ void scsi_remove_device(struct scsi_device *sdev)
sdev->host->hostt->slave_destroy(sdev);
transport_unregister_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev);
-out:
+}
+
+/**
+ * scsi_remove_device - unregister a device from the scsi bus
+ * @sdev: scsi_device to unregister
+ **/
+void scsi_remove_device(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = sdev->host;
+
+ down(&shost->scan_mutex);
+ __scsi_remove_device(sdev);
up(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
@@ -653,17 +721,20 @@ void __scsi_remove_target(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
- struct scsi_device *sdev, *tmp;
+ struct scsi_device *sdev;
spin_lock_irqsave(shost->host_lock, flags);
starget->reap_ref++;
- list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+ restart:
+ list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->channel != starget->channel ||
- sdev->id != starget->id)
+ sdev->id != starget->id ||
+ sdev->sdev_state == SDEV_DEL)
continue;
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_device(sdev);
spin_lock_irqsave(shost->host_lock, flags);
+ goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_target_reap(starget);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 35d1c1e8e345..b856e140e65f 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -26,6 +26,7 @@
*/
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/sched.h> /* workqueue stuff, HZ */
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@@ -252,7 +253,8 @@ struct fc_internal {
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
-static int fc_target_setup(struct device *dev)
+static int fc_target_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct scsi_target *starget = to_scsi_target(dev);
struct fc_rport *rport = starget_to_rport(starget);
@@ -281,7 +283,8 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
NULL,
NULL);
-static int fc_host_setup(struct device *dev)
+static int fc_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
@@ -817,12 +820,15 @@ show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name);
}
+#define get_list_head_entry(pos, head, member) \
+ pos = list_entry((head)->next, typeof(*pos), member)
+
static ssize_t
store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
const char *buf, size_t count)
{
struct Scsi_Host *shost = transport_class_to_shost(cdev);
- struct fc_rport *rport, *next_rport;
+ struct fc_rport *rport;
enum fc_tgtid_binding_type val;
unsigned long flags;
@@ -832,9 +838,13 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
/* if changing bind type, purge all unused consistent bindings */
if (val != fc_host_tgtid_bind_type(shost)) {
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry_safe(rport, next_rport,
- &fc_host_rport_bindings(shost), peers)
+ while (!list_empty(&fc_host_rport_bindings(shost))) {
+ get_list_head_entry(rport,
+ &fc_host_rport_bindings(shost), peers);
+ spin_unlock_irqrestore(shost->host_lock, flags);
fc_rport_terminate(rport);
+ spin_lock_irqsave(shost->host_lock, flags);
+ }
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1022,6 +1032,23 @@ static int fc_rport_match(struct attribute_container *cont,
return &i->rport_attr_cont.ac == cont;
}
+
+/*
+ * Must be called with shost->host_lock held
+ */
+static struct device *fc_target_parent(struct Scsi_Host *shost,
+ int channel, uint id)
+{
+ struct fc_rport *rport;
+
+ list_for_each_entry(rport, &fc_host_rports(shost), peers)
+ if ((rport->channel == channel) &&
+ (rport->scsi_target_id == id))
+ return &rport->dev;
+
+ return NULL;
+}
+
struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft)
{
@@ -1057,6 +1084,8 @@ fc_attach_transport(struct fc_function_template *ft)
/* Transport uses the shost workq for scsi scanning */
i->t.create_work_queue = 1;
+
+ i->t.target_parent = fc_target_parent;
/*
* Setup SCSI Target Attributes.
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 8bb8222ea589..d2caa35059d9 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -19,6 +19,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
new file mode 100644
index 000000000000..1d145d2f9a38
--- /dev/null
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -0,0 +1,819 @@
+/*
+ * Copyright (C) 2005 Dell Inc.
+ * Released under GPL v2.
+ *
+ * Serial Attached SCSI (SAS) transport class.
+ *
+ * The SAS transport class contains common code to deal with SAS HBAs,
+ * an aproximated representation of SAS topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and managment
+ * interfaces to userspace.
+ *
+ * In addition to the basic SCSI core objects this transport class
+ * introduces two additional intermediate objects: The SAS PHY
+ * as represented by struct sas_phy defines an "outgoing" PHY on
+ * a SAS HBA or Expander, and the SAS remote PHY represented by
+ * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
+ * end device. Note that this is purely a software concept, the
+ * underlying hardware for a PHY and a remote PHY is the exactly
+ * the same.
+ *
+ * There is no concept of a SAS port in this code, users can see
+ * what PHYs form a wide port based on the port_identifier attribute,
+ * which is the same for all PHYs in a port.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_sas.h>
+
+
+#define SAS_HOST_ATTRS 0
+#define SAS_PORT_ATTRS 11
+#define SAS_RPORT_ATTRS 5
+
+struct sas_internal {
+ struct scsi_transport_template t;
+ struct sas_function_template *f;
+
+ struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+ struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+ struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+
+ struct transport_container phy_attr_cont;
+ struct transport_container rphy_attr_cont;
+
+ /*
+ * The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c
+ */
+ struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+ struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+ struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+};
+#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
+
+struct sas_host_attrs {
+ struct list_head rphy_list;
+ spinlock_t lock;
+ u32 next_target_id;
+};
+#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+ struct class_device_attribute class_device_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * Pretty printing helpers
+ */
+
+#define sas_bitfield_name_match(title, table) \
+static ssize_t \
+get_sas_##title##_names(u32 table_key, char *buf) \
+{ \
+ char *prefix = ""; \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \
+ if (table[i].value & table_key) { \
+ len += sprintf(buf + len, "%s%s", \
+ prefix, table[i].name); \
+ prefix = ", "; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+#define sas_bitfield_name_search(title, table) \
+static ssize_t \
+get_sas_##title##_names(u32 table_key, char *buf) \
+{ \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \
+ if (table[i].value == table_key) { \
+ len += sprintf(buf + len, "%s", \
+ table[i].name); \
+ break; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+static struct {
+ u32 value;
+ char *name;
+} sas_device_type_names[] = {
+ { SAS_PHY_UNUSED, "unused" },
+ { SAS_END_DEVICE, "end device" },
+ { SAS_EDGE_EXPANDER_DEVICE, "edge expander" },
+ { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" },
+};
+sas_bitfield_name_search(device_type, sas_device_type_names)
+
+
+static struct {
+ u32 value;
+ char *name;
+} sas_protocol_names[] = {
+ { SAS_PROTOCOL_SATA, "sata" },
+ { SAS_PROTOCOL_SMP, "smp" },
+ { SAS_PROTOCOL_STP, "stp" },
+ { SAS_PROTOCOL_SSP, "ssp" },
+};
+sas_bitfield_name_match(protocol, sas_protocol_names)
+
+static struct {
+ u32 value;
+ char *name;
+} sas_linkspeed_names[] = {
+ { SAS_LINK_RATE_UNKNOWN, "Unknown" },
+ { SAS_PHY_DISABLED, "Phy disabled" },
+ { SAS_LINK_RATE_FAILED, "Link Rate failed" },
+ { SAS_SATA_SPINUP_HOLD, "Spin-up hold" },
+ { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" },
+ { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" },
+};
+sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
+
+
+/*
+ * SAS host attributes
+ */
+
+static int sas_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
+{
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ INIT_LIST_HEAD(&sas_host->rphy_list);
+ spin_lock_init(&sas_host->lock);
+ sas_host->next_target_id = 0;
+ return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(sas_host_class,
+ "sas_host", sas_host_setup, NULL, NULL);
+
+static int sas_host_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_host_device(dev))
+ return 0;
+ shost = dev_to_shost(dev);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->t.host_attrs.ac == cont;
+}
+
+static int do_sas_phy_delete(struct device *dev, void *data)
+{
+ if (scsi_is_sas_phy(dev))
+ sas_phy_delete(dev_to_phy(dev));
+ return 0;
+}
+
+/**
+ * sas_remove_host -- tear down a Scsi_Host's SAS data structures
+ * @shost: Scsi Host that is torn down
+ *
+ * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
+ * Must be called just before scsi_remove_host for SAS HBAs.
+ */
+void sas_remove_host(struct Scsi_Host *shost)
+{
+ device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete);
+}
+EXPORT_SYMBOL(sas_remove_host);
+
+
+/*
+ * SAS Port attributes
+ */
+
+#define sas_phy_show_simple(field, name, format_string, cast) \
+static ssize_t \
+show_sas_phy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ return snprintf(buf, 20, format_string, cast phy->field); \
+}
+
+#define sas_phy_simple_attr(field, name, format_string, type) \
+ sas_phy_show_simple(field, name, format_string, (type)) \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_protocol(field, name) \
+static ssize_t \
+show_sas_phy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ if (!phy->field) \
+ return snprintf(buf, 20, "none\n"); \
+ return get_sas_protocol_names(phy->field, buf); \
+}
+
+#define sas_phy_protocol_attr(field, name) \
+ sas_phy_show_protocol(field, name) \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_linkspeed(field) \
+static ssize_t \
+show_sas_phy_##field(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_phy *phy = transport_class_to_phy(cdev); \
+ \
+ return get_sas_linkspeed_names(phy->field, buf); \
+}
+
+#define sas_phy_linkspeed_attr(field) \
+ sas_phy_show_linkspeed(field) \
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+
+static ssize_t
+show_sas_device_type(struct class_device *cdev, char *buf)
+{
+ struct sas_phy *phy = transport_class_to_phy(cdev);
+
+ if (!phy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+ return get_sas_device_type_names(phy->identify.device_type, buf);
+}
+
+static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+
+sas_phy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+sas_phy_protocol_attr(identify.target_port_protocols,
+ target_port_protocols);
+sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+ unsigned long long);
+sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
+sas_phy_linkspeed_attr(negotiated_linkrate);
+sas_phy_linkspeed_attr(minimum_linkrate_hw);
+sas_phy_linkspeed_attr(minimum_linkrate);
+sas_phy_linkspeed_attr(maximum_linkrate_hw);
+sas_phy_linkspeed_attr(maximum_linkrate);
+
+
+static DECLARE_TRANSPORT_CLASS(sas_phy_class,
+ "sas_phy", NULL, NULL, NULL);
+
+static int sas_phy_match(struct attribute_container *cont, struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_sas_phy(dev))
+ return 0;
+ shost = dev_to_shost(dev->parent);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->phy_attr_cont.ac == cont;
+}
+
+static void sas_phy_release(struct device *dev)
+{
+ struct sas_phy *phy = dev_to_phy(dev);
+
+ put_device(dev->parent);
+ kfree(phy);
+}
+
+/**
+ * sas_phy_alloc -- allocates and initialize a SAS PHY structure
+ * @parent: Parent device
+ * @number: Port number
+ *
+ * Allocates an SAS PHY structure. It will be added in the device tree
+ * below the device specified by @parent, which has to be either a Scsi_Host
+ * or sas_rphy.
+ *
+ * Returns:
+ * SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_phy *sas_phy_alloc(struct device *parent, int number)
+{
+ struct Scsi_Host *shost = dev_to_shost(parent);
+ struct sas_phy *phy;
+
+ phy = kmalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return NULL;
+ memset(phy, 0, sizeof(*phy));
+
+ get_device(parent);
+
+ phy->number = number;
+
+ device_initialize(&phy->dev);
+ phy->dev.parent = get_device(parent);
+ phy->dev.release = sas_phy_release;
+ sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
+
+ transport_setup_device(&phy->dev);
+
+ return phy;
+}
+EXPORT_SYMBOL(sas_phy_alloc);
+
+/**
+ * sas_phy_add -- add a SAS PHY to the device hierachy
+ * @phy: The PHY to be added
+ *
+ * Publishes a SAS PHY to the rest of the system.
+ */
+int sas_phy_add(struct sas_phy *phy)
+{
+ int error;
+
+ error = device_add(&phy->dev);
+ if (!error) {
+ transport_add_device(&phy->dev);
+ transport_configure_device(&phy->dev);
+ }
+
+ return error;
+}
+EXPORT_SYMBOL(sas_phy_add);
+
+/**
+ * sas_phy_free -- free a SAS PHY
+ * @phy: SAS PHY to free
+ *
+ * Frees the specified SAS PHY.
+ *
+ * Note:
+ * This function must only be called on a PHY that has not
+ * sucessfully been added using sas_phy_add().
+ */
+void sas_phy_free(struct sas_phy *phy)
+{
+ transport_destroy_device(&phy->dev);
+ put_device(phy->dev.parent);
+ put_device(phy->dev.parent);
+ put_device(phy->dev.parent);
+ kfree(phy);
+}
+EXPORT_SYMBOL(sas_phy_free);
+
+/**
+ * sas_phy_delete -- remove SAS PHY
+ * @phy: SAS PHY to remove
+ *
+ * Removes the specified SAS PHY. If the SAS PHY has an
+ * associated remote PHY it is removed before.
+ */
+void
+sas_phy_delete(struct sas_phy *phy)
+{
+ struct device *dev = &phy->dev;
+
+ if (phy->rphy)
+ sas_rphy_delete(phy->rphy);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(dev->parent);
+}
+EXPORT_SYMBOL(sas_phy_delete);
+
+/**
+ * scsi_is_sas_phy -- check if a struct device represents a SAS PHY
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a SAS PHY, %0 else
+ */
+int scsi_is_sas_phy(const struct device *dev)
+{
+ return dev->release == sas_phy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_phy);
+
+/*
+ * SAS remote PHY attributes.
+ */
+
+#define sas_rphy_show_simple(field, name, format_string, cast) \
+static ssize_t \
+show_sas_rphy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
+ \
+ return snprintf(buf, 20, format_string, cast rphy->field); \
+}
+
+#define sas_rphy_simple_attr(field, name, format_string, type) \
+ sas_rphy_show_simple(field, name, format_string, (type)) \
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+#define sas_rphy_show_protocol(field, name) \
+static ssize_t \
+show_sas_rphy_##name(struct class_device *cdev, char *buf) \
+{ \
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
+ \
+ if (!rphy->field) \
+ return snprintf(buf, 20, "none\n"); \
+ return get_sas_protocol_names(rphy->field, buf); \
+}
+
+#define sas_rphy_protocol_attr(field, name) \
+ sas_rphy_show_protocol(field, name) \
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+static ssize_t
+show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+{
+ struct sas_rphy *rphy = transport_class_to_rphy(cdev);
+
+ if (!rphy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+ return get_sas_device_type_names(
+ rphy->identify.device_type, buf);
+}
+
+static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
+ show_sas_rphy_device_type, NULL);
+
+sas_rphy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
+sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+ unsigned long long);
+sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+
+static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
+ "sas_rphy", NULL, NULL, NULL);
+
+static int sas_rphy_match(struct attribute_container *cont, struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct sas_internal *i;
+
+ if (!scsi_is_sas_rphy(dev))
+ return 0;
+ shost = dev_to_shost(dev->parent->parent);
+
+ if (!shost->transportt)
+ return 0;
+ if (shost->transportt->host_attrs.ac.class !=
+ &sas_host_class.class)
+ return 0;
+
+ i = to_sas_internal(shost->transportt);
+ return &i->rphy_attr_cont.ac == cont;
+}
+
+static void sas_rphy_release(struct device *dev)
+{
+ struct sas_rphy *rphy = dev_to_rphy(dev);
+
+ put_device(dev->parent);
+ kfree(rphy);
+}
+
+/**
+ * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure
+ * @parent: SAS PHY this remote PHY is conneted to
+ *
+ * Allocates an SAS remote PHY structure, connected to @parent.
+ *
+ * Returns:
+ * SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent)
+{
+ struct Scsi_Host *shost = dev_to_shost(&parent->dev);
+ struct sas_rphy *rphy;
+
+ rphy = kmalloc(sizeof(*rphy), GFP_KERNEL);
+ if (!rphy) {
+ put_device(&parent->dev);
+ return NULL;
+ }
+ memset(rphy, 0, sizeof(*rphy));
+
+ device_initialize(&rphy->dev);
+ rphy->dev.parent = get_device(&parent->dev);
+ rphy->dev.release = sas_rphy_release;
+ sprintf(rphy->dev.bus_id, "rphy-%d:%d",
+ shost->host_no, parent->number);
+ transport_setup_device(&rphy->dev);
+
+ return rphy;
+}
+EXPORT_SYMBOL(sas_rphy_alloc);
+
+/**
+ * sas_rphy_add -- add a SAS remote PHY to the device hierachy
+ * @rphy: The remote PHY to be added
+ *
+ * Publishes a SAS remote PHY to the rest of the system.
+ */
+int sas_rphy_add(struct sas_rphy *rphy)
+{
+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+ struct sas_identify *identify = &rphy->identify;
+ int error;
+
+ if (parent->rphy)
+ return -ENXIO;
+ parent->rphy = rphy;
+
+ error = device_add(&rphy->dev);
+ if (error)
+ return error;
+ transport_add_device(&rphy->dev);
+ transport_configure_device(&rphy->dev);
+
+ spin_lock(&sas_host->lock);
+ list_add_tail(&rphy->list, &sas_host->rphy_list);
+ if (identify->device_type == SAS_END_DEVICE &&
+ (identify->target_port_protocols &
+ (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
+ rphy->scsi_target_id = sas_host->next_target_id++;
+ else
+ rphy->scsi_target_id = -1;
+ spin_unlock(&sas_host->lock);
+
+ if (rphy->scsi_target_id != -1) {
+ scsi_scan_target(&rphy->dev, parent->number,
+ rphy->scsi_target_id, ~0, 0);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sas_rphy_add);
+
+/**
+ * sas_rphy_free -- free a SAS remote PHY
+ * @rphy SAS remote PHY to free
+ *
+ * Frees the specified SAS remote PHY.
+ *
+ * Note:
+ * This function must only be called on a remote
+ * PHY that has not sucessfully been added using
+ * sas_rphy_add().
+ */
+void sas_rphy_free(struct sas_rphy *rphy)
+{
+ struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ spin_lock(&sas_host->lock);
+ list_del(&rphy->list);
+ spin_unlock(&sas_host->lock);
+
+ transport_destroy_device(&rphy->dev);
+ put_device(rphy->dev.parent);
+ put_device(rphy->dev.parent);
+ put_device(rphy->dev.parent);
+ kfree(rphy);
+}
+EXPORT_SYMBOL(sas_rphy_free);
+
+/**
+ * sas_rphy_delete -- remove SAS remote PHY
+ * @rphy: SAS remote PHY to remove
+ *
+ * Removes the specified SAS remote PHY.
+ */
+void
+sas_rphy_delete(struct sas_rphy *rphy)
+{
+ struct device *dev = &rphy->dev;
+ struct sas_phy *parent = dev_to_phy(dev->parent);
+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ scsi_remove_target(dev);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+
+ spin_lock(&sas_host->lock);
+ list_del(&rphy->list);
+ spin_unlock(&sas_host->lock);
+
+ put_device(&parent->dev);
+}
+EXPORT_SYMBOL(sas_rphy_delete);
+
+/**
+ * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a SAS remote PHY, %0 else
+ */
+int scsi_is_sas_rphy(const struct device *dev)
+{
+ return dev->release == sas_rphy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_rphy);
+
+
+/*
+ * SCSI scan helper
+ */
+
+static struct device *sas_target_parent(struct Scsi_Host *shost,
+ int channel, uint id)
+{
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+ struct sas_rphy *rphy;
+ struct device *dev = NULL;
+
+ spin_lock(&sas_host->lock);
+ list_for_each_entry(rphy, &sas_host->rphy_list, list) {
+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+ if (parent->number == channel &&
+ rphy->scsi_target_id == id)
+ dev = &rphy->dev;
+ }
+ spin_unlock(&sas_host->lock);
+
+ return dev;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_RPORT_ATTRIBUTE(field) \
+ i->private_rphy_attrs[count] = class_device_attr_##field; \
+ i->private_rphy_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rphy_attrs[count].store = NULL; \
+ i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \
+ count++
+
+#define SETUP_PORT_ATTRIBUTE(field) \
+ i->private_phy_attrs[count] = class_device_attr_##field; \
+ i->private_phy_attrs[count].attr.mode = S_IRUGO; \
+ i->private_phy_attrs[count].store = NULL; \
+ i->phy_attrs[count] = &i->private_phy_attrs[count]; \
+ count++
+
+
+/**
+ * sas_attach_transport -- instantiate SAS transport template
+ * @ft: SAS transport class function template
+ */
+struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *ft)
+{
+ struct sas_internal *i;
+ int count;
+
+ i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL);
+ if (!i)
+ return NULL;
+ memset(i, 0, sizeof(struct sas_internal));
+
+ i->t.target_parent = sas_target_parent;
+
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &sas_host_class.class;
+ i->t.host_attrs.ac.match = sas_host_match;
+ transport_container_register(&i->t.host_attrs);
+ i->t.host_size = sizeof(struct sas_host_attrs);
+
+ i->phy_attr_cont.ac.class = &sas_phy_class.class;
+ i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
+ i->phy_attr_cont.ac.match = sas_phy_match;
+ transport_container_register(&i->phy_attr_cont);
+
+ i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
+ i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
+ i->rphy_attr_cont.ac.match = sas_rphy_match;
+ transport_container_register(&i->rphy_attr_cont);
+
+ i->f = ft;
+
+ count = 0;
+ i->host_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_PORT_ATTRIBUTE(initiator_port_protocols);
+ SETUP_PORT_ATTRIBUTE(target_port_protocols);
+ SETUP_PORT_ATTRIBUTE(device_type);
+ SETUP_PORT_ATTRIBUTE(sas_address);
+ SETUP_PORT_ATTRIBUTE(phy_identifier);
+ SETUP_PORT_ATTRIBUTE(port_identifier);
+ SETUP_PORT_ATTRIBUTE(negotiated_linkrate);
+ SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);
+ SETUP_PORT_ATTRIBUTE(minimum_linkrate);
+ SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);
+ SETUP_PORT_ATTRIBUTE(maximum_linkrate);
+ i->phy_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
+ SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
+ SETUP_RPORT_ATTRIBUTE(rphy_device_type);
+ SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
+ SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
+ i->rphy_attrs[count] = NULL;
+
+ return &i->t;
+}
+EXPORT_SYMBOL(sas_attach_transport);
+
+/**
+ * sas_release_transport -- release SAS transport template instance
+ * @t: transport template instance
+ */
+void sas_release_transport(struct scsi_transport_template *t)
+{
+ struct sas_internal *i = to_sas_internal(t);
+
+ transport_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->phy_attr_cont);
+ transport_container_unregister(&i->rphy_attr_cont);
+
+ kfree(i);
+}
+EXPORT_SYMBOL(sas_release_transport);
+
+static __init int sas_transport_init(void)
+{
+ int error;
+
+ error = transport_class_register(&sas_host_class);
+ if (error)
+ goto out;
+ error = transport_class_register(&sas_phy_class);
+ if (error)
+ goto out_unregister_transport;
+ error = transport_class_register(&sas_rphy_class);
+ if (error)
+ goto out_unregister_phy;
+
+ return 0;
+
+ out_unregister_phy:
+ transport_class_unregister(&sas_phy_class);
+ out_unregister_transport:
+ transport_class_unregister(&sas_host_class);
+ out:
+ return error;
+
+}
+
+static void __exit sas_transport_exit(void)
+{
+ transport_class_unregister(&sas_host_class);
+ transport_class_unregister(&sas_phy_class);
+ transport_class_unregister(&sas_rphy_class);
+}
+
+MODULE_AUTHOR("Christoph Hellwig");
+MODULE_DESCRIPTION("SAS Transphy Attributes");
+MODULE_LICENSE("GPL");
+
+module_init(sas_transport_init);
+module_exit(sas_transport_exit);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 7670919a087a..ef577c8c2182 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -28,14 +28,14 @@
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
-#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */
+#define SPI_NUM_ATTRS 14 /* increase this if you add attributes */
#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always
* on" attributes */
#define SPI_HOST_ATTRS 1
@@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int value, int denom)
return result;
}
-/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions
- * resulting from (likely) bus and device resets */
-static void spi_wait_req(struct scsi_request *sreq, const void *cmd,
- void *buffer, unsigned bufflen)
+static int spi_execute(struct scsi_device *sdev, const void *cmd,
+ enum dma_data_direction dir,
+ void *buffer, unsigned bufflen,
+ struct scsi_sense_hdr *sshdr)
{
- int i;
+ int i, result;
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
for(i = 0; i < DV_RETRIES; i++) {
- sreq->sr_request->flags |= REQ_FAILFAST;
-
- scsi_wait_req(sreq, cmd, buffer, bufflen,
- DV_TIMEOUT, /* retries */ 1);
- if (sreq->sr_result & DRIVER_SENSE) {
- struct scsi_sense_hdr sshdr;
-
- if (scsi_request_normalize_sense(sreq, &sshdr)
- && sshdr.sense_key == UNIT_ATTENTION)
+ result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
+ sense, DV_TIMEOUT, /* retries */ 1,
+ REQ_FAILFAST);
+ if (result & DRIVER_SENSE) {
+ struct scsi_sense_hdr sshdr_tmp;
+ if (!sshdr)
+ sshdr = &sshdr_tmp;
+
+ if (scsi_normalize_sense(sense, sizeof(*sense),
+ sshdr)
+ && sshdr->sense_key == UNIT_ATTENTION)
continue;
}
break;
}
+ return result;
}
static struct {
@@ -162,7 +166,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
return SPI_SIGNAL_UNKNOWN;
}
-static int spi_host_setup(struct device *dev)
+static int spi_host_setup(struct transport_container *tc, struct device *dev,
+ struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
@@ -196,7 +201,9 @@ static int spi_host_match(struct attribute_container *cont,
return &i->t.host_attrs.ac == cont;
}
-static int spi_device_configure(struct device *dev)
+static int spi_device_configure(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_target *starget = sdev->sdev_target;
@@ -214,7 +221,9 @@ static int spi_device_configure(struct device *dev)
return 0;
}
-static int spi_setup_transport_attrs(struct device *dev)
+static int spi_setup_transport_attrs(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
{
struct scsi_target *starget = to_scsi_target(dev);
@@ -231,6 +240,7 @@ static int spi_setup_transport_attrs(struct device *dev)
spi_rd_strm(starget) = 0;
spi_rti(starget) = 0;
spi_pcomp_en(starget) = 0;
+ spi_hold_mcs(starget) = 0;
spi_dv_pending(starget) = 0;
spi_initial_dv(starget) = 0;
init_MUTEX(&spi_dv_sem(starget));
@@ -347,6 +357,7 @@ spi_transport_rd_attr(wr_flow, "%d\n");
spi_transport_rd_attr(rd_strm, "%d\n");
spi_transport_rd_attr(rti, "%d\n");
spi_transport_rd_attr(pcomp_en, "%d\n");
+spi_transport_rd_attr(hold_mcs, "%d\n");
/* we only care about the first child device so we return 1 */
static int child_iter(struct device *dev, void *data)
@@ -539,13 +550,13 @@ enum spi_compare_returns {
/* This is for read/write Domain Validation: If the device supports
* an echo buffer, we do read/write tests to it */
static enum spi_compare_returns
-spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
u8 *ptr, const int retries)
{
- struct scsi_device *sdev = sreq->sr_device;
int len = ptr - buffer;
- int j, k, r;
+ int j, k, r, result;
unsigned int pattern = 0x0000ffff;
+ struct scsi_sense_hdr sshdr;
const char spi_write_buffer[] = {
WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0
@@ -590,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
}
for (r = 0; r < retries; r++) {
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_TO_DEVICE;
- spi_wait_req(sreq, spi_write_buffer, buffer, len);
- if(sreq->sr_result || !scsi_device_online(sdev)) {
- struct scsi_sense_hdr sshdr;
+ result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE,
+ buffer, len, &sshdr);
+ if(result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
- if (scsi_request_normalize_sense(sreq, &sshdr)
+ if (scsi_sense_valid(&sshdr)
&& sshdr.sense_key == ILLEGAL_REQUEST
/* INVALID FIELD IN CDB */
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00)
@@ -609,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
return SPI_COMPARE_SKIP_TEST;
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
+ SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result);
return SPI_COMPARE_FAILURE;
}
memset(ptr, 0, len);
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_FROM_DEVICE;
- spi_wait_req(sreq, spi_read_buffer, ptr, len);
+ spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE,
+ ptr, len, NULL);
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (memcmp(buffer, ptr, len) != 0)
@@ -628,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
/* This is for the simplest form of Domain Validation: a read test
* on the inquiry data from the device */
static enum spi_compare_returns
-spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
+spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer,
u8 *ptr, const int retries)
{
- int r;
- const int len = sreq->sr_device->inquiry_len;
- struct scsi_device *sdev = sreq->sr_device;
+ int r, result;
+ const int len = sdev->inquiry_len;
const char spi_inquiry[] = {
INQUIRY, 0, 0, 0, len, 0
};
for (r = 0; r < retries; r++) {
- sreq->sr_cmd_len = 0; /* wait_req to fill in */
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
memset(ptr, 0, len);
- spi_wait_req(sreq, spi_inquiry, ptr, len);
+ result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE,
+ ptr, len, NULL);
- if(sreq->sr_result || !scsi_device_online(sdev)) {
+ if(result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
return SPI_COMPARE_FAILURE;
}
@@ -667,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
}
static enum spi_compare_returns
-spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
+spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr,
enum spi_compare_returns
- (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+ (*compare_fn)(struct scsi_device *, u8 *, u8 *, int))
{
- struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
- struct scsi_device *sdev = sreq->sr_device;
+ struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct scsi_target *starget = sdev->sdev_target;
int period = 0, prevperiod = 0;
enum spi_compare_returns retval;
@@ -680,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
for (;;) {
int newperiod;
- retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+ retval = compare_fn(sdev, buffer, ptr, DV_LOOPS);
if (retval == SPI_COMPARE_SUCCESS
|| retval == SPI_COMPARE_SKIP_TEST)
@@ -726,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
}
static int
-spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer)
{
- int l;
+ int l, result;
/* first off do a test unit ready. This can error out
* because of reservations or some other reason. If it
@@ -744,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
};
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_NONE;
-
/* We send a set of three TURs to clear any outstanding
* unit attention conditions if they exist (Otherwise the
* buffer tests won't be happy). If the TUR still fails
* (reservation conflict, device not ready, etc) just
* skip the write tests */
for (l = 0; ; l++) {
- spi_wait_req(sreq, spi_test_unit_ready, NULL, 0);
+ result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE,
+ NULL, 0, NULL);
- if(sreq->sr_result) {
+ if(result) {
if(l >= 3)
return 0;
} else {
@@ -764,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
}
}
- sreq->sr_cmd_len = 0;
- sreq->sr_data_direction = DMA_FROM_DEVICE;
-
- spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4);
+ result = spi_execute(sdev, spi_read_buffer_descriptor,
+ DMA_FROM_DEVICE, buffer, 4, NULL);
- if (sreq->sr_result)
+ if (result)
/* Device has no echo buffer */
return 0;
@@ -777,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
}
static void
-spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
+spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
{
- struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
- struct scsi_device *sdev = sreq->sr_device;
+ struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct scsi_target *starget = sdev->sdev_target;
int len = sdev->inquiry_len;
/* first set us up for narrow async */
DV_SET(offset, 0);
DV_SET(width, 0);
- if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+ if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
@@ -799,7 +798,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
scsi_device_wide(sdev)) {
i->f->set_width(starget, 1);
- if (spi_dv_device_compare_inquiry(sreq, buffer,
+ if (spi_dv_device_compare_inquiry(sdev, buffer,
buffer + len,
DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
@@ -820,7 +819,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
len = 0;
if (scsi_device_dt(sdev))
- len = spi_dv_device_get_echo_buffer(sreq, buffer);
+ len = spi_dv_device_get_echo_buffer(sdev, buffer);
retry:
@@ -846,7 +845,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (len == 0) {
SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
- spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_retrain(sdev, buffer, buffer + len,
spi_dv_device_compare_inquiry);
return;
}
@@ -856,7 +855,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
- if (spi_dv_retrain(sreq, buffer, buffer + len,
+ if (spi_dv_retrain(sdev, buffer, buffer + len,
spi_dv_device_echo_buffer)
== SPI_COMPARE_SKIP_TEST) {
/* OK, the stupid drive can't do a write echo buffer
@@ -879,16 +878,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
void
spi_dv_device(struct scsi_device *sdev)
{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
struct scsi_target *starget = sdev->sdev_target;
u8 *buffer;
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
- if (unlikely(!sreq))
- return;
-
if (unlikely(scsi_device_get(sdev)))
- goto out_free_req;
+ return;
buffer = kmalloc(len, GFP_KERNEL);
@@ -909,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev)
SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n");
- spi_dv_device_internal(sreq, buffer);
+ spi_dv_device_internal(sdev, buffer);
SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n");
@@ -924,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev)
kfree(buffer);
out_put:
scsi_device_put(sdev);
- out_free_req:
- scsi_release_request(sreq);
}
EXPORT_SYMBOL(spi_dv_device);
@@ -1028,10 +1021,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
sprint_frac(tmp, picosec, 1000);
dev_info(&starget->dev,
- "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
- scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
- tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
- tp->qas ? " QAS" : "", tmp, tp->offset);
+ "%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n",
+ scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
+ tp->dt ? "DT" : "ST",
+ tp->iu ? " IU" : "",
+ tp->qas ? " QAS" : "",
+ tp->rd_strm ? " RDSTRM" : "",
+ tp->rti ? " RTI" : "",
+ tp->wr_flow ? " WRFLOW" : "",
+ tp->pcomp_en ? " PCOMP" : "",
+ tp->hold_mcs ? " HMCS" : "",
+ tmp, tp->offset);
} else {
dev_info(&starget->dev, "%sasynchronous.\n",
tp->width ? "wide " : "");
@@ -1073,6 +1073,7 @@ static int spi_device_match(struct attribute_container *cont,
{
struct scsi_device *sdev;
struct Scsi_Host *shost;
+ struct spi_internal *i;
if (!scsi_is_sdev_device(dev))
return 0;
@@ -1085,6 +1086,9 @@ static int spi_device_match(struct attribute_container *cont,
/* Note: this class has no device attributes, so it has
* no per-HBA allocation and thus we don't need to distinguish
* the attribute containers for the device */
+ i = to_spi_internal(shost->transportt);
+ if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target))
+ return 0;
return 1;
}
@@ -1092,6 +1096,7 @@ static int spi_target_match(struct attribute_container *cont,
struct device *dev)
{
struct Scsi_Host *shost;
+ struct scsi_target *starget;
struct spi_internal *i;
if (!scsi_is_target_device(dev))
@@ -1103,7 +1108,11 @@ static int spi_target_match(struct attribute_container *cont,
return 0;
i = to_spi_internal(shost->transportt);
-
+ starget = to_scsi_target(dev);
+
+ if (i->f->deny_binding && i->f->deny_binding(starget))
+ return 0;
+
return &i->t.target_attrs.ac == cont;
}
@@ -1154,6 +1163,7 @@ spi_attach_transport(struct spi_function_template *ft)
SETUP_ATTRIBUTE(rd_strm);
SETUP_ATTRIBUTE(rti);
SETUP_ATTRIBUTE(pcomp_en);
+ SETUP_ATTRIBUTE(hold_mcs);
/* if you add an attribute but forget to increase SPI_NUM_ATTRS
* this bug will trigger */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0410e1bf109a..9a1dc0cea03c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -59,7 +59,6 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
#include <scsi/scsicam.h>
#include "scsi_logging.h"
@@ -125,7 +124,7 @@ static int sd_issue_flush(struct device *, sector_t *);
static void sd_end_flush(request_queue_t *, struct request *);
static int sd_prepare_flush(request_queue_t *, struct request *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer);
+ unsigned char *buffer);
static struct scsi_driver sd_template = {
.owner = THIS_MODULE,
@@ -236,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+ SCpnt->cmd_len = rq->cmd_len;
if (rq_data_dir(rq) == WRITE)
SCpnt->sc_data_direction = DMA_TO_DEVICE;
else if (rq->data_len)
@@ -682,19 +682,13 @@ not_present:
static int sd_sync_cache(struct scsi_device *sdp)
{
- struct scsi_request *sreq;
int retries, res;
+ struct scsi_sense_hdr sshdr;
if (!scsi_device_online(sdp))
return -ENODEV;
- sreq = scsi_allocate_request(sdp, GFP_KERNEL);
- if (!sreq) {
- printk("FAILED\n No memory for request\n");
- return -ENOMEM;
- }
- sreq->sr_data_direction = DMA_NONE;
for (retries = 3; retries > 0; --retries) {
unsigned char cmd[10] = { 0 };
@@ -703,22 +697,20 @@ static int sd_sync_cache(struct scsi_device *sdp)
* Leave the rest of the command zero to indicate
* flush everything.
*/
- scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
- if (sreq->sr_result == 0)
+ res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
+ if (res == 0)
break;
}
- res = sreq->sr_result;
- if (res) {
- printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
+ if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
"host = %d, driver = %02x\n ",
status_byte(res), msg_byte(res),
host_byte(res), driver_byte(res));
if (driver_byte(res) & DRIVER_SENSE)
- scsi_print_req_sense("sd", sreq);
+ scsi_print_sense_hdr("sd", &sshdr);
}
- scsi_release_request(sreq);
return res;
}
@@ -957,22 +949,19 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
}
-static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)
+static int media_not_present(struct scsi_disk *sdkp,
+ struct scsi_sense_hdr *sshdr)
{
- struct scsi_sense_hdr sshdr;
- if (!srp->sr_result)
- return 0;
- if (!(driver_byte(srp->sr_result) & DRIVER_SENSE))
+ if (!scsi_sense_valid(sshdr))
return 0;
/* not invoked for commands that could return deferred errors */
- if (scsi_request_normalize_sense(srp, &sshdr)) {
- if (sshdr.sense_key != NOT_READY &&
- sshdr.sense_key != UNIT_ATTENTION)
- return 0;
- if (sshdr.asc != 0x3A) /* medium not present */
- return 0;
- }
+ if (sshdr->sense_key != NOT_READY &&
+ sshdr->sense_key != UNIT_ATTENTION)
+ return 0;
+ if (sshdr->asc != 0x3A) /* medium not present */
+ return 0;
+
set_media_not_present(sdkp);
return 1;
}
@@ -981,10 +970,10 @@ static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp)
* spinup disk - called only in sd_revalidate_disk()
*/
static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+{
unsigned char cmd[10];
- unsigned long spintime_value = 0;
+ unsigned long spintime_expire = 0;
int retries, spintime;
unsigned int the_result;
struct scsi_sense_hdr sshdr;
@@ -1001,18 +990,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
cmd[0] = TEST_UNIT_READY;
memset((void *) &cmd[1], 0, 9);
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0,
- SCSI_SENSE_BUFFERSIZE);
- SRpnt->sr_data_direction = DMA_NONE;
+ the_result = scsi_execute_req(sdkp->device, cmd,
+ DMA_NONE, NULL, 0,
+ &sshdr, SD_TIMEOUT,
+ SD_MAX_RETRIES);
- scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,
- 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES);
-
- the_result = SRpnt->sr_result;
if (the_result)
- sense_valid = scsi_request_normalize_sense(
- SRpnt, &sshdr);
+ sense_valid = scsi_sense_valid(&sshdr);
retries++;
} while (retries < 3 &&
(!scsi_status_is_good(the_result) ||
@@ -1024,7 +1008,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
* any media in it, don't bother with any of the rest of
* this crap.
*/
- if (media_not_present(sdkp, SRpnt))
+ if (media_not_present(sdkp, &sshdr))
return;
if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
@@ -1063,33 +1047,42 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
cmd[1] = 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0,
- SCSI_SENSE_BUFFERSIZE);
-
- SRpnt->sr_data_direction = DMA_NONE;
- scsi_wait_req(SRpnt, (void *)cmd,
- (void *) buffer, 0/*512*/,
- SD_TIMEOUT, SD_MAX_RETRIES);
- spintime_value = jiffies;
+ scsi_execute_req(sdkp->device, cmd, DMA_NONE,
+ NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
+ spintime_expire = jiffies + 100 * HZ;
+ spintime = 1;
}
- spintime = 1;
/* Wait 1 second for next try */
msleep(1000);
printk(".");
+
+ /*
+ * Wait for USB flash devices with slow firmware.
+ * Yes, this sense key/ASC combination shouldn't
+ * occur here. It's characteristic of these devices.
+ */
+ } else if (sense_valid &&
+ sshdr.sense_key == UNIT_ATTENTION &&
+ sshdr.asc == 0x28) {
+ if (!spintime) {
+ spintime_expire = jiffies + 5 * HZ;
+ spintime = 1;
+ }
+ /* Wait 1 second for next try */
+ msleep(1000);
} else {
/* we don't understand the sense code, so it's
* probably pointless to loop */
if(!spintime) {
printk(KERN_NOTICE "%s: Unit Not Ready, "
"sense:\n", diskname);
- scsi_print_req_sense("", SRpnt);
+ scsi_print_sense_hdr("", &sshdr);
}
break;
}
- } while (spintime &&
- time_after(spintime_value + 100 * HZ, jiffies));
+ } while (spintime && time_before_eq(jiffies, spintime_expire));
if (spintime) {
if (scsi_status_is_good(the_result))
@@ -1104,14 +1097,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
*/
static void
sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+ unsigned char *buffer)
+{
unsigned char cmd[16];
- struct scsi_device *sdp = sdkp->device;
int the_result, retries;
int sector_size = 0;
int longrc = 0;
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
+ struct scsi_device *sdp = sdkp->device;
repeat:
retries = 3;
@@ -1128,20 +1122,15 @@ repeat:
memset((void *) buffer, 0, 8);
}
- SRpnt->sr_cmd_len = 0;
- memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
- SRpnt->sr_data_direction = DMA_FROM_DEVICE;
-
- scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
- longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
+ the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ buffer, longrc ? 12 : 8, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
- if (media_not_present(sdkp, SRpnt))
+ if (media_not_present(sdkp, &sshdr))
return;
- the_result = SRpnt->sr_result;
if (the_result)
- sense_valid = scsi_request_normalize_sense(SRpnt,
- &sshdr);
+ sense_valid = scsi_sense_valid(&sshdr);
retries--;
} while (the_result && retries);
@@ -1156,7 +1145,7 @@ repeat:
driver_byte(the_result));
if (driver_byte(the_result) & DRIVER_SENSE)
- scsi_print_req_sense("sd", SRpnt);
+ scsi_print_sense_hdr("sd", &sshdr);
else
printk("%s : sense not available. \n", diskname);
@@ -1296,11 +1285,13 @@ got_data:
/* called with buffer of length 512 */
static inline int
-sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
- unsigned char *buffer, int len, struct scsi_mode_data *data)
+sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
+ unsigned char *buffer, int len, struct scsi_mode_data *data,
+ struct scsi_sense_hdr *sshdr)
{
- return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len,
- SD_TIMEOUT, SD_MAX_RETRIES, data);
+ return scsi_mode_sense(sdp, dbd, modepage, buffer, len,
+ SD_TIMEOUT, SD_MAX_RETRIES, data,
+ sshdr);
}
/*
@@ -1309,25 +1300,27 @@ sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
*/
static void
sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+ unsigned char *buffer)
+{
int res;
+ struct scsi_device *sdp = sdkp->device;
struct scsi_mode_data data;
set_disk_ro(sdkp->disk, 0);
- if (sdkp->device->skip_ms_page_3f) {
+ if (sdp->skip_ms_page_3f) {
printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
return;
}
- if (sdkp->device->use_192_bytes_for_3f) {
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data);
+ if (sdp->use_192_bytes_for_3f) {
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL);
} else {
/*
* First attempt: ask for all pages (0x3F), but only 4 bytes.
* We have to start carefully: some devices hang if we ask
* for more than is available.
*/
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL);
/*
* Second attempt: ask for page 0 When only page 0 is
@@ -1336,14 +1329,14 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
* CDB.
*/
if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL);
/*
* Third attempt: ask 255 bytes, as we did earlier.
*/
if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255,
- &data);
+ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255,
+ &data, NULL);
}
if (!scsi_status_is_good(res)) {
@@ -1365,19 +1358,20 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
*/
static void
sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer)
+ unsigned char *buffer)
{
int len = 0, res;
+ struct scsi_device *sdp = sdkp->device;
int dbd;
int modepage;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
- if (sdkp->device->skip_ms_page_8)
+ if (sdp->skip_ms_page_8)
goto defaults;
- if (sdkp->device->type == TYPE_RBC) {
+ if (sdp->type == TYPE_RBC) {
modepage = 6;
dbd = 8;
} else {
@@ -1386,7 +1380,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
}
/* cautiously ask */
- res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
+ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr);
if (!scsi_status_is_good(res))
goto bad_sense;
@@ -1407,7 +1401,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
len += data.header_length + data.block_descriptor_length;
/* Get the data */
- res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data);
+ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
if (scsi_status_is_good(res)) {
const char *types[] = {
@@ -1439,7 +1433,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
}
bad_sense:
- if (scsi_request_normalize_sense(SRpnt, &sshdr) &&
+ if (scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST &&
sshdr.asc == 0x24 && sshdr.ascq == 0x0)
printk(KERN_NOTICE "%s: cache data unavailable\n",
@@ -1464,7 +1458,6 @@ static int sd_revalidate_disk(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
- struct scsi_request *sreq;
unsigned char *buffer;
SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
@@ -1476,18 +1469,11 @@ static int sd_revalidate_disk(struct gendisk *disk)
if (!scsi_device_online(sdp))
goto out;
- sreq = scsi_allocate_request(sdp, GFP_KERNEL);
- if (!sreq) {
- printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation "
- "failure.\n");
- goto out;
- }
-
buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA);
if (!buffer) {
printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
"failure.\n");
- goto out_release_request;
+ goto out;
}
/* defaults, until the device tells us otherwise */
@@ -1498,25 +1484,23 @@ static int sd_revalidate_disk(struct gendisk *disk)
sdkp->WCE = 0;
sdkp->RCD = 0;
- sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer);
+ sd_spinup_disk(sdkp, disk->disk_name);
/*
* Without media there is no reason to ask; moreover, some devices
* react badly if we do.
*/
if (sdkp->media_present) {
- sd_read_capacity(sdkp, disk->disk_name, sreq, buffer);
+ sd_read_capacity(sdkp, disk->disk_name, buffer);
if (sdp->removable)
sd_read_write_protect_flag(sdkp, disk->disk_name,
- sreq, buffer);
- sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer);
+ buffer);
+ sd_read_cache_type(sdkp, disk->disk_name, buffer);
}
set_capacity(disk, sdkp->capacity);
kfree(buffer);
- out_release_request:
- scsi_release_request(sreq);
out:
return 0;
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 51292f269ce5..d86d5c26061d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,6 +49,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
+#include <linux/scatterlist.h>
#include "scsi.h"
#include <scsi/scsi_dbg.h>
@@ -61,7 +62,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */
#ifdef CONFIG_SCSI_PROC_FS
#include <linux/proc_fs.h>
-static char *sg_version_date = "20050328";
+static char *sg_version_date = "20050908";
static int sg_proc_init(void);
static void sg_proc_cleanup(void);
@@ -104,8 +105,8 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
#define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */
-static int sg_add(struct class_device *);
-static void sg_remove(struct class_device *);
+static int sg_add(struct class_device *, struct class_interface *);
+static void sg_remove(struct class_device *, struct class_interface *);
static Scsi_Request *dummy_cmdp; /* only used for sizeof */
@@ -1027,8 +1028,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (sdp->detached)
return -ENODEV;
if (filp->f_flags & O_NONBLOCK) {
- if (test_bit(SHOST_RECOVERY,
- &sdp->device->host->shost_state))
+ if (scsi_host_in_recovery(sdp->device->host))
return -EBUSY;
} else if (!scsi_block_when_processing_errors(sdp->device))
return -EBUSY;
@@ -1300,7 +1300,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */
sfp->mmap_called = 1;
}
- vma->vm_flags |= (VM_RESERVED | VM_IO);
+ vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = sfp;
vma->vm_ops = &sg_mmap_vm_ops;
return 0;
@@ -1507,7 +1507,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
}
static int
-sg_add(struct class_device *cl_dev)
+sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
{
struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
struct gendisk *disk;
@@ -1551,7 +1551,7 @@ sg_add(struct class_device *cl_dev)
if (sg_sysfs_valid) {
struct class_device * sg_class_member;
- sg_class_member = class_device_create(sg_sysfs_class,
+ sg_class_member = class_device_create(sg_sysfs_class, NULL,
MKDEV(SCSI_GENERIC_MAJOR, k),
cl_dev->dev, "%s",
disk->disk_name);
@@ -1583,7 +1583,7 @@ out:
}
static void
-sg_remove(struct class_device *cl_dev)
+sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
{
struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
Sg_device *sdp = NULL;
@@ -1795,12 +1795,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unsigned long uaddr, size_t count, int rw,
unsigned long max_pfn)
{
+ unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned long start = uaddr >> PAGE_SHIFT;
+ const int nr_pages = end - start;
int res, i, j;
- unsigned int nr_pages;
struct page **pages;
- nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
/* User attempted Overflow! */
if ((uaddr + count) < uaddr)
return -EINVAL;
@@ -1887,13 +1887,17 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
int i;
for (i=0; i < nr_pages; i++) {
- if (dirtied && !PageReserved(sgl[i].page))
- SetPageDirty(sgl[i].page);
- /* unlock_page(sgl[i].page); */
+ struct page *page = sgl[i].page;
+
+ /* XXX: just for debug. Remove when PageReserved is removed */
+ BUG_ON(PageReserved(page));
+ if (dirtied)
+ SetPageDirty(page);
+ /* unlock_page(page); */
/* FIXME: cache flush missing for rw==READ
* FIXME: call the correct reference counting function
*/
- page_cache_release(sgl[i].page);
+ page_cache_release(page);
}
return 0;
@@ -1993,9 +1997,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
if (!p)
break;
}
- sclp->page = virt_to_page(p);
- sclp->offset = offset_in_page(p);
- sclp->length = ret_sz;
+ sg_set_buf(sclp, p, ret_sz);
SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
k, sg_scatg2virt(sclp), ret_sz));
@@ -2645,7 +2647,7 @@ static char *
sg_page_malloc(int rqSz, int lowDma, int *retSzp)
{
char *resp = NULL;
- int page_mask;
+ gfp_t page_mask;
int order, a_size;
int resSz = rqSz;
@@ -2850,8 +2852,7 @@ sg_proc_init(void)
struct proc_dir_entry *pdep;
struct sg_proc_leaf * leaf;
- sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname,
- S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+ sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL);
if (!sg_proc_sgp)
return 1;
for (k = 0; k < num_leaves; ++k) {
@@ -2971,23 +2972,22 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos)
{
struct sg_proc_deviter * it = kmalloc(sizeof(*it), GFP_KERNEL);
+ s->private = it;
if (! it)
return NULL;
+
if (NULL == sg_dev_arr)
- goto err1;
+ return NULL;
it->index = *pos;
it->max = sg_last_dev();
if (it->index >= it->max)
- goto err1;
+ return NULL;
return it;
-err1:
- kfree(it);
- return NULL;
}
static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
+ struct sg_proc_deviter * it = s->private;
*pos = ++it->index;
return (it->index < it->max) ? it : NULL;
@@ -2995,7 +2995,7 @@ static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void dev_seq_stop(struct seq_file *s, void *v)
{
- kfree (v);
+ kfree(s->private);
}
static int sg_proc_open_dev(struct inode *inode, struct file *file)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2f259f249522..561901b1cf11 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -50,10 +50,10 @@
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */
-#include <scsi/scsi_request.h>
#include "scsi_logging.h"
#include "sr.h"
@@ -199,15 +199,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
/* check multisession offset etc */
sr_cd_check(cdi);
- /*
- * If the disk changed, the capacity will now be different,
- * so we force a re-read of this information
- * Force 2048 for the sector size so that filesystems won't
- * be trying to use something that is too small if the disc
- * has changed.
- */
- cd->needs_sector_size = 1;
- cd->device->sector_size = 2048;
+ get_sectorsize(cd);
}
return retval;
}
@@ -334,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+ SCpnt->cmd_len = rq->cmd_len;
if (!rq->data_len)
SCpnt->sc_data_direction = DMA_NONE;
else if (rq_data_dir(rq) == WRITE)
@@ -538,13 +531,6 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
- /*
- * If this device did not have media in the drive at boot time, then
- * we would have been unable to get the sector size. Check to see if
- * this is the case, and try again.
- */
- if (cd->needs_sector_size)
- get_sectorsize(cd);
return 0;
error_out:
@@ -604,7 +590,6 @@ static int sr_probe(struct device *dev)
cd->driver = &sr_template;
cd->disk = disk;
cd->capacity = 0x1fffff;
- cd->needs_sector_size = 1;
cd->device->changed = 1; /* force recheck CD type */
cd->use = 1;
cd->readcd_known = 0;
@@ -658,43 +643,30 @@ static void get_sectorsize(struct scsi_cd *cd)
unsigned char *buffer;
int the_result, retries = 3;
int sector_size;
- struct scsi_request *SRpnt = NULL;
request_queue_t *queue;
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
goto Enomem;
- SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
- if (!SRpnt)
- goto Enomem;
do {
cmd[0] = READ_CAPACITY;
memset((void *) &cmd[1], 0, 9);
- /* Mark as really busy */
- SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
- SRpnt->sr_cmd_len = 0;
-
memset(buffer, 0, 8);
/* Do the command and wait.. */
- SRpnt->sr_data_direction = DMA_FROM_DEVICE;
- scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
- 8, SR_TIMEOUT, MAX_RETRIES);
+ the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
+ buffer, 8, NULL, SR_TIMEOUT,
+ MAX_RETRIES);
- the_result = SRpnt->sr_result;
retries--;
} while (the_result && retries);
- scsi_release_request(SRpnt);
- SRpnt = NULL;
-
if (the_result) {
cd->capacity = 0x1fffff;
sector_size = 2048; /* A guess, just in case */
- cd->needs_sector_size = 1;
} else {
#if 0
if (cdrom_get_last_written(&cd->cdi,
@@ -727,7 +699,6 @@ static void get_sectorsize(struct scsi_cd *cd)
printk("%s: unsupported sector size %d.\n",
cd->cdi.name, sector_size);
cd->capacity = 0;
- cd->needs_sector_size = 1;
}
cd->device->sector_size = sector_size;
@@ -736,7 +707,6 @@ static void get_sectorsize(struct scsi_cd *cd)
* Add this so that we have the ability to correctly gauge
* what the device is capable of.
*/
- cd->needs_sector_size = 0;
set_capacity(cd->disk, cd->capacity);
}
@@ -748,10 +718,7 @@ out:
Enomem:
cd->capacity = 0x1fffff;
- sector_size = 2048; /* A guess, just in case */
- cd->needs_sector_size = 1;
- if (SRpnt)
- scsi_release_request(SRpnt);
+ cd->device->sector_size = 2048; /* A guess, just in case */
goto out;
}
@@ -759,8 +726,8 @@ static void get_capabilities(struct scsi_cd *cd)
{
unsigned char *buffer;
struct scsi_mode_data data;
- struct scsi_request *SRpnt;
unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_sense_hdr sshdr;
unsigned int the_result;
int retries, rc, n;
@@ -776,19 +743,11 @@ static void get_capabilities(struct scsi_cd *cd)
""
};
- /* allocate a request for the TEST_UNIT_READY */
- SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
- if (!SRpnt) {
- printk(KERN_WARNING "(get_capabilities:) Request allocation "
- "failure.\n");
- return;
- }
/* allocate transfer buffer */
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer) {
printk(KERN_ERR "sr: out of memory.\n");
- scsi_release_request(SRpnt);
return;
}
@@ -800,24 +759,19 @@ static void get_capabilities(struct scsi_cd *cd)
memset((void *)cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt->sr_cmd_len = 0;
- SRpnt->sr_sense_buffer[0] = 0;
- SRpnt->sr_sense_buffer[2] = 0;
- SRpnt->sr_data_direction = DMA_NONE;
-
- scsi_wait_req (SRpnt, (void *) cmd, buffer,
- 0, SR_TIMEOUT, MAX_RETRIES);
+ the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
+ 0, &sshdr, SR_TIMEOUT,
+ MAX_RETRIES);
- the_result = SRpnt->sr_result;
retries++;
} while (retries < 5 &&
(!scsi_status_is_good(the_result) ||
- ((driver_byte(the_result) & DRIVER_SENSE) &&
- SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
+ (scsi_sense_valid(&sshdr) &&
+ sshdr.sense_key == UNIT_ATTENTION)));
/* ask for mode page 0x2a */
rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
- SR_TIMEOUT, 3, &data);
+ SR_TIMEOUT, 3, &data, NULL);
if (!scsi_status_is_good(rc)) {
/* failed, drive doesn't have capabilities mode page */
@@ -825,7 +779,6 @@ static void get_capabilities(struct scsi_cd *cd)
cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
CDC_DVD | CDC_DVD_RAM |
CDC_SELECT_DISC | CDC_SELECT_SPEED);
- scsi_release_request(SRpnt);
kfree(buffer);
printk("%s: scsi-1 drive\n", cd->cdi.name);
return;
@@ -885,7 +838,6 @@ static void get_capabilities(struct scsi_cd *cd)
cd->device->writeable = 1;
}
- scsi_release_request(SRpnt);
kfree(buffer);
}
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index 0b3178007203..d2bcd99c272f 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -33,7 +33,6 @@ typedef struct scsi_cd {
struct scsi_device *device;
unsigned int vendor; /* vendor code, see sr_vendor.c */
unsigned long ms_offset; /* for reading multisession-CD's */
- unsigned needs_sector_size:1; /* needs to get sector size */
unsigned use:1; /* is this device still supportable */
unsigned xa_flag:1; /* CD has XA sectors ? */
unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 82d68fdb1548..6e45ac3c43c5 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -17,7 +17,7 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_cmnd.h>
#include "sr.h"
@@ -84,41 +84,37 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
{
- struct scsi_request *SRpnt;
struct scsi_device *SDev;
- struct request *req;
+ struct scsi_sense_hdr sshdr;
int result, err = 0, retries = 0;
+ struct request_sense *sense = cgc->sense;
SDev = cd->device;
- SRpnt = scsi_allocate_request(SDev, GFP_KERNEL);
- if (!SRpnt) {
- printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl");
- err = -ENOMEM;
- goto out;
- }
- SRpnt->sr_data_direction = cgc->data_direction;
+
+ if (!sense) {
+ sense = kmalloc(sizeof(*sense), GFP_KERNEL);
+ if (!sense) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
retry:
if (!scsi_block_when_processing_errors(SDev)) {
err = -ENODEV;
- goto out_free;
+ goto out;
}
- scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen,
- cgc->timeout, IOCTL_RETRIES);
-
- req = SRpnt->sr_request;
- if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) {
- memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen);
- kfree(SRpnt->sr_buffer);
- SRpnt->sr_buffer = req->buffer;
- }
+ memset(sense, 0, sizeof(*sense));
+ result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
+ cgc->buffer, cgc->buflen, (char *)sense,
+ cgc->timeout, IOCTL_RETRIES, 0);
- result = SRpnt->sr_result;
+ scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
/* Minimal error checking. Ignore cases we know about, and report the rest. */
if (driver_byte(result) != 0) {
- switch (SRpnt->sr_sense_buffer[2] & 0xf) {
+ switch (sshdr.sense_key) {
case UNIT_ATTENTION:
SDev->changed = 1;
if (!cgc->quiet)
@@ -128,8 +124,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
err = -ENOMEDIUM;
break;
case NOT_READY: /* This happens if there is no disc in drive */
- if (SRpnt->sr_sense_buffer[12] == 0x04 &&
- SRpnt->sr_sense_buffer[13] == 0x01) {
+ if (sshdr.asc == 0x04 &&
+ sshdr.ascq == 0x01) {
/* sense: Logical unit is in process of becoming ready */
if (!cgc->quiet)
printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
@@ -146,37 +142,33 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
if (!cgc->quiet)
printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name);
#ifdef DEBUG
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
#endif
err = -ENOMEDIUM;
break;
case ILLEGAL_REQUEST:
err = -EIO;
- if (SRpnt->sr_sense_buffer[12] == 0x20 &&
- SRpnt->sr_sense_buffer[13] == 0x00)
+ if (sshdr.asc == 0x20 &&
+ sshdr.ascq == 0x00)
/* sense: Invalid command operation code */
err = -EDRIVE_CANT_DO_THIS;
#ifdef DEBUG
__scsi_print_command(cgc->cmd);
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
#endif
break;
default:
printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
__scsi_print_command(cgc->cmd);
- scsi_print_req_sense("sr", SRpnt);
+ scsi_print_sense_hdr("sr", &sshdr);
err = -EIO;
}
}
- if (cgc->sense)
- memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense));
-
/* Wake up a process waiting for device */
- out_free:
- scsi_release_request(SRpnt);
- SRpnt = NULL;
out:
+ if (!cgc->sense)
+ kfree(sense);
cgc->stat = err;
return err;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 0291a8fb654d..da9766283bd7 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20050501";
+static char *verstr = "20050830";
#include <linux/module.h>
@@ -219,6 +219,12 @@ static int switch_partition(struct scsi_tape *);
static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
+static void scsi_tape_release(struct kref *);
+
+#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
+
+static DECLARE_MUTEX(st_ref_sem);
+
#include "osst_detect.h"
#ifndef SIGS_FROM_OSST
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
{"OnStream", "FW-", "", "osst"}
#endif
+static struct scsi_tape *scsi_tape_get(int dev)
+{
+ struct scsi_tape *STp = NULL;
+
+ down(&st_ref_sem);
+ write_lock(&st_dev_arr_lock);
+
+ if (dev < st_dev_max && scsi_tapes != NULL)
+ STp = scsi_tapes[dev];
+ if (!STp) goto out;
+
+ kref_get(&STp->kref);
+
+ if (!STp->device)
+ goto out_put;
+
+ if (scsi_device_get(STp->device))
+ goto out_put;
+
+ goto out;
+
+out_put:
+ kref_put(&STp->kref, scsi_tape_release);
+ STp = NULL;
+out:
+ write_unlock(&st_dev_arr_lock);
+ up(&st_ref_sem);
+ return STp;
+}
+
+static void scsi_tape_put(struct scsi_tape *STp)
+{
+ struct scsi_device *sdev = STp->device;
+
+ down(&st_ref_sem);
+ kref_put(&STp->kref, scsi_tape_release);
+ scsi_device_put(sdev);
+ up(&st_ref_sem);
+}
+
struct st_reject_data {
char *vendor;
char *model;
@@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
return 0;
cmdstatp = &STp->buffer->cmdstat;
- st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
+ st_analyze_sense(SRpnt, cmdstatp);
if (cmdstatp->have_sense)
scode = STp->buffer->cmdstat.sense_hdr.sense_key;
@@ -399,10 +445,10 @@ static void st_sleep_done(struct scsi_cmnd * SCpnt)
(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
SCpnt->request->rq_status = RQ_SCSI_DONE;
- (STp->buffer)->last_SRpnt = SCpnt->sc_request;
DEB( STp->write_pending = 0; )
- complete(SCpnt->request->waiting);
+ if (SCpnt->request->waiting)
+ complete(SCpnt->request->waiting);
}
/* Do the scsi command. Waits until command performed if do_wait is true.
@@ -412,8 +458,20 @@ static struct scsi_request *
st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
int bytes, int direction, int timeout, int retries, int do_wait)
{
+ struct completion *waiting;
unsigned char *bp;
+ /* if async, make sure there's no command outstanding */
+ if (!do_wait && ((STp->buffer)->last_SRpnt)) {
+ printk(KERN_ERR "%s: Async command already active.\n",
+ tape_name(STp));
+ if (signal_pending(current))
+ (STp->buffer)->syscall_result = (-EINTR);
+ else
+ (STp->buffer)->syscall_result = (-EBUSY);
+ return NULL;
+ }
+
if (SRpnt == NULL) {
SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
if (SRpnt == NULL) {
@@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
}
}
- init_completion(&STp->wait);
+ /* If async IO, set last_SRpnt. This ptr tells write_behind_check
+ which IO is outstanding. It's nulled out when the IO completes. */
+ if (!do_wait)
+ (STp->buffer)->last_SRpnt = SRpnt;
+
+ waiting = &STp->wait;
+ init_completion(waiting);
SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
if (SRpnt->sr_use_sg) {
if (!STp->buffer->do_dio)
@@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
bp = (STp->buffer)->b_data;
SRpnt->sr_data_direction = direction;
SRpnt->sr_cmd_len = 0;
- SRpnt->sr_request->waiting = &(STp->wait);
+ SRpnt->sr_request->waiting = waiting;
SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
SRpnt->sr_request->rq_disk = STp->disk;
+ SRpnt->sr_request->end_io = blk_end_sync_rq;
STp->buffer->cmdstat.have_sense = 0;
scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
st_sleep_done, timeout, retries);
if (do_wait) {
- wait_for_completion(SRpnt->sr_request->waiting);
+ wait_for_completion(waiting);
SRpnt->sr_request->waiting = NULL;
+ if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+ SRpnt->sr_result |= (DRIVER_ERROR << 24);
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
}
return SRpnt;
@@ -465,6 +532,7 @@ static int write_behind_check(struct scsi_tape * STp)
struct st_buffer *STbuffer;
struct st_partstat *STps;
struct st_cmdstatus *cmdstatp;
+ struct scsi_request *SRpnt;
STbuffer = STp->buffer;
if (!STbuffer->writing)
@@ -478,10 +546,14 @@ static int write_behind_check(struct scsi_tape * STp)
) /* end DEB */
wait_for_completion(&(STp->wait));
- (STp->buffer)->last_SRpnt->sr_request->waiting = NULL;
+ SRpnt = STbuffer->last_SRpnt;
+ STbuffer->last_SRpnt = NULL;
+ SRpnt->sr_request->waiting = NULL;
+ if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+ SRpnt->sr_result |= (DRIVER_ERROR << 24);
- (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt);
- scsi_release_request((STp->buffer)->last_SRpnt);
+ (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+ scsi_release_request(SRpnt);
STbuffer->buffer_bytes -= STbuffer->writing;
STps = &(STp->ps[STp->partition]);
@@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, struct file *filp)
*/
filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+ if (!(STp = scsi_tape_get(dev)))
+ return -ENXIO;
+
write_lock(&st_dev_arr_lock);
- if (dev >= st_dev_max || scsi_tapes == NULL ||
- ((STp = scsi_tapes[dev]) == NULL)) {
- write_unlock(&st_dev_arr_lock);
- return (-ENXIO);
- }
filp->private_data = STp;
name = tape_name(STp);
if (STp->in_use) {
write_unlock(&st_dev_arr_lock);
+ scsi_tape_put(STp);
DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
return (-EBUSY);
}
- if(scsi_device_get(STp->device)) {
- write_unlock(&st_dev_arr_lock);
- return (-ENXIO);
- }
STp->in_use = 1;
write_unlock(&st_dev_arr_lock);
STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
@@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, struct file *filp)
err_out:
normalize_buffer(STp->buffer);
STp->in_use = 0;
- scsi_device_put(STp->device);
+ scsi_tape_put(STp);
return retval;
}
@@ -1250,7 +1317,7 @@ static int st_release(struct inode *inode, struct file *filp)
write_lock(&st_dev_arr_lock);
STp->in_use = 0;
write_unlock(&st_dev_arr_lock);
- scsi_device_put(STp->device);
+ scsi_tape_put(STp);
return result;
}
@@ -3510,7 +3577,8 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
static struct st_buffer *
new_tape_buffer(int from_initialization, int need_dma, int max_sg)
{
- int i, priority, got = 0, segs = 0;
+ int i, got = 0, segs = 0;
+ gfp_t priority;
struct st_buffer *tb;
if (from_initialization)
@@ -3543,7 +3611,8 @@ static struct st_buffer *
/* Try to allocate enough space in the tape buffer */
static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
{
- int segs, nbr, max_segs, b_size, priority, order, got;
+ int segs, nbr, max_segs, b_size, order, got;
+ gfp_t priority;
if (new_size <= STbuffer->buffer_size)
return 1;
@@ -3887,6 +3956,7 @@ static int st_probe(struct device *dev)
goto out_put_disk;
}
memset(tpnt, 0, sizeof(struct scsi_tape));
+ kref_init(&tpnt->kref);
tpnt->disk = disk;
sprintf(disk->disk_name, "st%d", i);
disk->private_data = &tpnt->driver;
@@ -3902,6 +3972,7 @@ static int st_probe(struct device *dev)
tpnt->tape_type = MT_ISSCSI2;
tpnt->buffer = buffer;
+ tpnt->buffer->last_SRpnt = NULL;
tpnt->inited = 0;
tpnt->dirty = 0;
@@ -4076,15 +4147,10 @@ static int st_remove(struct device *dev)
tpnt->modes[mode].cdevs[j] = NULL;
}
}
- tpnt->device = NULL;
- if (tpnt->buffer) {
- tpnt->buffer->orig_frp_segs = 0;
- normalize_buffer(tpnt->buffer);
- kfree(tpnt->buffer);
- }
- put_disk(tpnt->disk);
- kfree(tpnt);
+ down(&st_ref_sem);
+ kref_put(&tpnt->kref, scsi_tape_release);
+ up(&st_ref_sem);
return 0;
}
}
@@ -4093,6 +4159,34 @@ static int st_remove(struct device *dev)
return 0;
}
+/**
+ * scsi_tape_release - Called to free the Scsi_Tape structure
+ * @kref: pointer to embedded kref
+ *
+ * st_ref_sem must be held entering this routine. Because it is
+ * called on last put, you should always use the scsi_tape_get()
+ * scsi_tape_put() helpers which manipulate the semaphore directly
+ * and never do a direct kref_put().
+ **/
+static void scsi_tape_release(struct kref *kref)
+{
+ struct scsi_tape *tpnt = to_scsi_tape(kref);
+ struct gendisk *disk = tpnt->disk;
+
+ tpnt->device = NULL;
+
+ if (tpnt->buffer) {
+ tpnt->buffer->orig_frp_segs = 0;
+ normalize_buffer(tpnt->buffer);
+ kfree(tpnt->buffer);
+ }
+
+ disk->private_data = NULL;
+ put_disk(disk);
+ kfree(tpnt);
+ return;
+}
+
static void st_intr(struct scsi_cmnd *SCpnt)
{
scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
@@ -4114,6 +4208,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+ SCpnt->cmd_len = rq->cmd_len;
if (rq_data_dir(rq) == WRITE)
SCpnt->sc_data_direction = DMA_TO_DEVICE;
@@ -4149,12 +4244,10 @@ static int __init init_st(void)
do_create_driverfs_files();
return 0;
}
- if (st_sysfs_class)
- class_destroy(st_sysfs_class);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
-
ST_MAX_TAPE_ENTRIES);
}
+ class_destroy(st_sysfs_class);
printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
return 1;
@@ -4162,13 +4255,11 @@ static int __init init_st(void)
static void __exit exit_st(void)
{
- if (st_sysfs_class)
- class_destroy(st_sysfs_class);
- st_sysfs_class = NULL;
do_remove_driverfs_files();
scsi_unregister_driver(&st_template.gendrv);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
ST_MAX_TAPE_ENTRIES);
+ class_destroy(st_sysfs_class);
kfree(scsi_tapes);
printk(KERN_INFO "st: Unloaded.\n");
}
@@ -4286,7 +4377,7 @@ static void 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 =
- class_device_create(st_sysfs_class,
+ class_device_create(st_sysfs_class, NULL,
MKDEV(SCSI_TAPE_MAJOR,
TAPE_MINOR(dev_num, mode, rew)),
&STp->device->sdev_gendev, "%s", name);
@@ -4352,12 +4443,12 @@ static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pag
static int sgl_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;
- unsigned int nr_pages;
struct page **pages;
- nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
-
/* User attempted Overflow! */
if ((uaddr + count) < uaddr)
return -EINVAL;
@@ -4435,12 +4526,16 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p
int i;
for (i=0; i < nr_pages; i++) {
- if (dirtied && !PageReserved(sgl[i].page))
- SetPageDirty(sgl[i].page);
+ struct page *page = sgl[i].page;
+
+ /* XXX: just for debug. Remove when PageReserved is removed */
+ BUG_ON(PageReserved(page));
+ if (dirtied)
+ SetPageDirty(page);
/* FIXME: cache flush missing for rw==READ
* FIXME: call the correct reference counting function
*/
- page_cache_release(sgl[i].page);
+ page_cache_release(page);
}
return 0;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 061da111398e..790acac160bc 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -3,7 +3,7 @@
#define _ST_H
#include <linux/completion.h>
-
+#include <linux/kref.h>
/* Descriptor for analyzed sense data */
struct st_cmdstatus {
@@ -156,6 +156,7 @@ struct scsi_tape {
unsigned char last_sense[16];
#endif
struct gendisk *disk;
+ struct kref kref;
};
/* Bit masks for use_pf */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index e753ba27dc59..a1a58e1d5ad3 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -37,6 +37,9 @@
* 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/slab.h>
+
#include "sym_glue.h"
#include "sym_nvram.h"
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 3131a6bf7ab7..3a264a408216 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -37,6 +37,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/gfp.h>
+
#ifndef SYM_HIPD_H
#define SYM_HIPD_H
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 5a51051e31f0..b131432c677d 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev)
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- void __iomem *zalon = ioremap(dev->hpa, 4096);
+ void __iomem *zalon = ioremap(dev->hpa.start, 4096);
void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
@@ -127,7 +127,7 @@ zalon_probe(struct parisc_device *dev)
device.chip = zalon720_chip;
device.host_id = 7;
device.dev = &dev->dev;
- device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET;
+ device.slot.base = dev->hpa.start + GSC_SCSI_ZALON_OFFSET;
device.slot.base_v = io_port;
device.slot.irq = dev->irq;
device.differential = 2;
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 0b10169961eb..b5cf39468d18 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -58,8 +58,7 @@ static const char serial21285_name[] = "Footbridge UART";
* int((BAUD_BASE - (baud >> 1)) / baud)
*/
-static void
-serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial21285_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(IRQ_CONTX);
@@ -67,8 +66,7 @@ serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial21285_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(IRQ_CONTX);
@@ -148,7 +146,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- serial21285_stop_tx(port, 0);
+ serial21285_stop_tx(port);
goto out;
}
@@ -164,7 +162,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- serial21285_stop_tx(port, 0);
+ serial21285_stop_tx(port);
out:
return IRQ_HANDLED;
@@ -465,7 +463,7 @@ static int __init serial21285_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver serial21285_reg;
+static struct uart_driver serial21285_reg;
static struct console serial21285_console =
{
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 9097f2f7b12a..2efb317153ce 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -40,7 +40,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index b116122e569a..170c9d2a749c 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -2474,8 +2474,7 @@ static struct tty_operations rs_360_ops = {
.tiocmset = rs_360_tiocmset,
};
-/* int __init rs_360_init(void) */
-int rs_360_init(void)
+static int __init rs_360_init(void)
{
struct serial_state * state;
ser_info_t *info;
@@ -2827,10 +2826,7 @@ int rs_360_init(void)
return 0;
}
-
-
-
-
+module_init(rs_360_init);
/* This must always be called before the rs_360_init() function, otherwise
* it blows away the port control information.
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 7e8fc7c1d4cc..f47d2c454e33 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -33,7 +33,7 @@
#include <linux/sysrq.h>
#include <linux/mca.h>
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
@@ -864,7 +864,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
/*
* We're pretty sure there's a port here. Lets find out what
* type of port it is. The IIR top two bits allows us to find
- * out if its 8250 or 16450, 16550, 16550A or later. This
+ * out if it's 8250 or 16450, 16550, 16550A or later. This
* determines what we test for next.
*
* We also initialise the EFR (if any) to zero for later. The
@@ -1001,7 +1001,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
}
}
-static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1018,7 +1018,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
static void transmit_chars(struct uart_8250_port *up);
-static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1158,7 +1158,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
up->port.x_char = 0;
return;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ if (uart_tx_stopped(&up->port)) {
+ serial8250_stop_tx(&up->port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
__stop_tx(up);
return;
}
@@ -2354,13 +2358,10 @@ static int __devexit serial8250_remove(struct device *dev)
return 0;
}
-static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
+static int serial8250_suspend(struct device *dev, pm_message_t state)
{
int i;
- if (level != SUSPEND_DISABLE)
- return 0;
-
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
@@ -2371,13 +2372,10 @@ static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int serial8250_resume(struct device *dev, u32 level)
+static int serial8250_resume(struct device *dev)
{
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
@@ -2532,7 +2530,7 @@ static int __init serial8250_init(void)
goto out;
serial8250_isa_devs = platform_device_register_simple("serial8250",
- -1, NULL, 0);
+ PLAT8250_DEV_LEGACY, NULL, 0);
if (IS_ERR(serial8250_isa_devs)) {
ret = PTR_ERR(serial8250_isa_devs);
goto unreg;
@@ -2586,82 +2584,3 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
#endif
MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
-
-/**
- * register_serial - configure a 16x50 serial port at runtime
- * @req: request structure
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use an error is returned. If the port
- * is not currently in the table it is added.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- *
- * Note: this function is deprecated - use serial8250_register_port
- * instead.
- */
-int register_serial(struct serial_struct *req)
-{
- struct uart_port port;
-
- port.iobase = req->port;
- port.membase = req->iomem_base;
- port.irq = req->irq;
- port.uartclk = req->baud_base * 16;
- port.fifosize = req->xmit_fifo_size;
- port.regshift = req->iomem_reg_shift;
- port.iotype = req->io_type;
- port.flags = req->flags | UPF_BOOT_AUTOCONF;
- port.mapbase = req->iomap_base;
- port.dev = NULL;
-
- if (share_irqs)
- port.flags |= UPF_SHARE_IRQ;
-
- if (HIGH_BITS_OFFSET)
- port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-
- /*
- * If a clock rate wasn't specified by the low level driver, then
- * default to the standard clock rate. This should be 115200 (*16)
- * and should not depend on the architecture's BASE_BAUD definition.
- * However, since this API will be deprecated, it's probably a
- * better idea to convert the drivers to use the new API
- * (serial8250_register_port and serial8250_unregister_port).
- */
- if (port.uartclk == 0) {
- printk(KERN_WARNING
- "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n",
- port.iobase, port.mapbase, port.membase, port.irq);
- printk(KERN_WARNING "Serial: see %s:%d for more information\n",
- __FILE__, __LINE__);
- dump_stack();
-
- /*
- * Fix it up for now, but this is only a temporary measure.
- */
- port.uartclk = BASE_BAUD * 16;
- }
-
- return serial8250_register_port(&port);
-}
-EXPORT_SYMBOL(register_serial);
-
-/**
- * unregister_serial - remove a 16x50 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may not be called from interrupt
- * context. We hand the port back to our local PM control.
- *
- * Note: this function is deprecated - use serial8250_unregister_port
- * instead.
- */
-void unregister_serial(int line)
-{
- serial8250_unregister_port(line);
-}
-EXPORT_SYMBOL(unregister_serial);
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 9225c82faeb8..b1b459efda52 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -16,11 +16,7 @@
*/
#include <linux/config.h>
-
-int serial8250_register_port(struct uart_port *);
-void serial8250_unregister_port(int line);
-void serial8250_suspend_port(int line);
-void serial8250_resume_port(int line);
+#include <linux/serial_8250.h>
struct old_serial_port {
unsigned int uart;
diff --git a/drivers/serial/8250_accent.c b/drivers/serial/8250_accent.c
index 1f2c276063ef..9c10262f2469 100644
--- a/drivers/serial/8250_accent.c
+++ b/drivers/serial/8250_accent.c
@@ -29,7 +29,7 @@ static struct plat_serial8250_port accent_data[] = {
static struct platform_device accent_device = {
.name = "serial8250",
- .id = 2,
+ .id = PLAT8250_DEV_ACCENT,
.dev = {
.platform_data = accent_data,
},
diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
index 6b9ead288517..a802bdce6e5d 100644
--- a/drivers/serial/8250_acpi.c
+++ b/drivers/serial/8250_acpi.c
@@ -47,18 +47,30 @@ static acpi_status acpi_serial_port(struct uart_port *port,
static acpi_status acpi_serial_ext_irq(struct uart_port *port,
struct acpi_resource_ext_irq *ext_irq)
{
- if (ext_irq->number_of_interrupts > 0)
- port->irq = acpi_register_gsi(ext_irq->interrupts[0],
+ int rc;
+
+ if (ext_irq->number_of_interrupts > 0) {
+ rc = acpi_register_gsi(ext_irq->interrupts[0],
ext_irq->edge_level, ext_irq->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ port->irq = rc;
+ }
return AE_OK;
}
static acpi_status acpi_serial_irq(struct uart_port *port,
struct acpi_resource_irq *irq)
{
- if (irq->number_of_interrupts > 0)
- port->irq = acpi_register_gsi(irq->interrupts[0],
+ int rc;
+
+ if (irq->number_of_interrupts > 0) {
+ rc = acpi_register_gsi(irq->interrupts[0],
irq->edge_level, irq->active_high_low);
+ if (rc < 0)
+ return AE_ERROR;
+ port->irq = rc;
+ }
return AE_OK;
}
diff --git a/drivers/serial/8250_boca.c b/drivers/serial/8250_boca.c
index 465c9ea1e7a3..3bfe0f7b26fb 100644
--- a/drivers/serial/8250_boca.c
+++ b/drivers/serial/8250_boca.c
@@ -43,7 +43,7 @@ static struct plat_serial8250_port boca_data[] = {
static struct platform_device boca_device = {
.name = "serial8250",
- .id = 3,
+ .id = PLAT8250_DEV_BOCA,
.dev = {
.platform_data = boca_data,
},
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index b7a5dd710228..59ba5d993b4b 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -164,7 +164,7 @@ static int __init parse_options(struct early_uart_device *device, char *options)
if ((options = strchr(options, ','))) {
options++;
- device->baud = simple_strtoul(options, 0, 0);
+ device->baud = simple_strtoul(options, NULL, 0);
length = min(strcspn(options, " "), sizeof(device->options));
strncpy(device->options, options, length);
} else {
diff --git a/drivers/serial/8250_fourport.c b/drivers/serial/8250_fourport.c
index e9b4d908ef42..6375d68b7913 100644
--- a/drivers/serial/8250_fourport.c
+++ b/drivers/serial/8250_fourport.c
@@ -35,7 +35,7 @@ static struct plat_serial8250_port fourport_data[] = {
static struct platform_device fourport_device = {
.name = "serial8250",
- .id = 1,
+ .id = PLAT8250_DEV_FOURPORT,
.dev = {
.platform_data = fourport_data,
},
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 431aa5761a7a..8b4947933d9b 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -29,7 +29,6 @@
static int __init
serial_init_chip(struct parisc_device *dev)
{
- static int serial_line_nr;
struct uart_port port;
unsigned long address;
int err;
@@ -42,12 +41,13 @@ serial_init_chip(struct parisc_device *dev)
*/
if (parisc_parent(dev)->id.hw_type != HPHW_IOA) {
printk(KERN_INFO "Serial: device 0x%lx not configured.\n"
- "Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa);
+ "Enable support for Wax, Lasi, Asp or Dino.\n",
+ dev->hpa.start);
}
return -ENODEV;
}
- address = dev->hpa;
+ address = dev->hpa.start;
if (dev->id.sversion != 0x8d) {
address += 0x800;
}
diff --git a/drivers/serial/8250_hub6.c b/drivers/serial/8250_hub6.c
index 77f396f84b4c..daf569cd3c8f 100644
--- a/drivers/serial/8250_hub6.c
+++ b/drivers/serial/8250_hub6.c
@@ -40,7 +40,7 @@ static struct plat_serial8250_port hub6_data[] = {
static struct platform_device hub6_device = {
.name = "serial8250",
- .id = 4,
+ .id = PLAT8250_DEV_HUB6,
.dev = {
.platform_data = hub6_data,
},
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c
index f0c40d68b8c1..ac205256d5f3 100644
--- a/drivers/serial/8250_mca.c
+++ b/drivers/serial/8250_mca.c
@@ -44,7 +44,7 @@ static struct plat_serial8250_port mca_data[] = {
static struct platform_device mca_device = {
.name = "serial8250",
- .id = 5,
+ .id = PLAT8250_DEV_MCA,
.dev = {
.platform_data = mca_data,
},
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 07f05e9d0955..5c3c03932d6d 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -34,36 +34,6 @@
#undef SERIAL_DEBUG_PCI
/*
- * Definitions for PCI support.
- */
-#define FL_BASE_MASK 0x0007
-#define FL_BASE0 0x0000
-#define FL_BASE1 0x0001
-#define FL_BASE2 0x0002
-#define FL_BASE3 0x0003
-#define FL_BASE4 0x0004
-#define FL_GET_BASE(x) (x & FL_BASE_MASK)
-
-/* Use successive BARs (PCI base address registers),
- else use offset into some specified BAR */
-#define FL_BASE_BARS 0x0008
-
-/* do not assign an irq */
-#define FL_NOIRQ 0x0080
-
-/* Use the Base address register size to cap number of ports */
-#define FL_REGION_SZ_CAP 0x0100
-
-struct pci_board {
- unsigned int flags;
- unsigned int num_ports;
- unsigned int base_baud;
- unsigned int uart_offset;
- unsigned int reg_shift;
- unsigned int first_offset;
-};
-
-/*
* init function returns:
* > 0 - number of ports
* = 0 - use board->num_ports
@@ -75,14 +45,15 @@ struct pci_serial_quirk {
u32 subvendor;
u32 subdevice;
int (*init)(struct pci_dev *dev);
- int (*setup)(struct pci_dev *dev, struct pci_board *board,
- struct uart_port *port, int idx);
+ int (*setup)(struct serial_private *, struct pciserial_board *,
+ struct uart_port *, int);
void (*exit)(struct pci_dev *dev);
};
#define PCI_NUM_BAR_RESOURCES 6
struct serial_private {
+ struct pci_dev *dev;
unsigned int nr;
void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];
struct pci_serial_quirk *quirk;
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev)
}
static int
-setup_port(struct pci_dev *dev, struct uart_port *port,
+setup_port(struct serial_private *priv, struct uart_port *port,
int bar, int offset, int regshift)
{
- struct serial_private *priv = pci_get_drvdata(dev);
+ struct pci_dev *dev = priv->dev;
unsigned long base, len;
if (bar >= PCI_NUM_BAR_RESOURCES)
return -EINVAL;
+ base = pci_resource_start(dev, bar);
+
if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
- base = pci_resource_start(dev, bar);
len = pci_resource_len(dev, bar);
if (!priv->remapped_bar[bar])
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
return -ENOMEM;
port->iotype = UPIO_MEM;
+ port->iobase = 0;
port->mapbase = base + offset;
port->membase = priv->remapped_bar[bar] + offset;
port->regshift = regshift;
} else {
- base = pci_resource_start(dev, bar) + offset;
port->iotype = UPIO_PORT;
- port->iobase = base;
+ port->iobase = base + offset;
+ port->mapbase = 0;
+ port->membase = NULL;
+ port->regshift = 0;
}
return 0;
}
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
* Not that ugly ;) -- HW
*/
static int
-afavlab_setup(struct pci_dev *dev, struct pci_board *board,
+afavlab_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
offset += (idx - 4) * board->uart_offset;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -177,6 +152,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
rc = 4;
break;
case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+ case PCI_DEVICE_ID_HP_DIVA_HURRICANE:
rc = 1;
break;
}
@@ -189,13 +165,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
* some serial ports are supposed to be hidden on certain models.
*/
static int
-pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
+pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
- switch (dev->subsystem_device) {
+ switch (priv->dev->subsystem_device) {
case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
if (idx == 3)
idx++;
@@ -212,7 +188,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
offset += idx * board->uart_offset;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -251,8 +227,10 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev)
}
irq_config = 0x41;
- if (dev->vendor == PCI_VENDOR_ID_PANACOM)
+ if (dev->vendor == PCI_VENDOR_ID_PANACOM ||
+ dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS) {
irq_config = 0x43;
+ }
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
(dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
/*
@@ -307,7 +285,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
-sbs_setup(struct pci_dev *dev, struct pci_board *board,
+sbs_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -323,7 +301,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
} else /* we have only 8 ports on PMC-OCTALPRO */
return 1;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
@@ -389,6 +367,9 @@ static void __devexit sbs_exit(struct pci_dev *dev)
* - 10x cards have control registers in IO and/or memory space;
* - 20x cards have control registers in standard PCI configuration space.
*
+ * Note: all 10x cards have PCI device ids 0x10..
+ * all 20x cards have PCI device ids 0x20..
+ *
* There are also Quartet Serial cards which use Oxford Semiconductor
* 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
*
@@ -445,24 +426,18 @@ static int pci_siig20x_init(struct pci_dev *dev)
return 0;
}
-int pci_siig10x_fn(struct pci_dev *dev, int enable)
+static int pci_siig_init(struct pci_dev *dev)
{
- int ret = 0;
- if (enable)
- ret = pci_siig10x_init(dev);
- return ret;
-}
+ unsigned int type = dev->device & 0xff00;
-int pci_siig20x_fn(struct pci_dev *dev, int enable)
-{
- int ret = 0;
- if (enable)
- ret = pci_siig20x_init(dev);
- return ret;
-}
+ if (type == 0x1000)
+ return pci_siig10x_init(dev);
+ else if (type == 0x2000)
+ return pci_siig20x_init(dev);
-EXPORT_SYMBOL(pci_siig10x_fn);
-EXPORT_SYMBOL(pci_siig20x_fn);
+ moan_device("Unknown SIIG card", dev);
+ return -ENODEV;
+}
/*
* Timedia has an explosion of boards, and to avoid the PCI table from
@@ -523,7 +498,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
* Ugh, this is ugly as all hell --- TYT
*/
static int
-pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
+pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -549,14 +524,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
bar = idx - 2;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/*
* Some Titan cards are also a little weird
*/
static int
-titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
+titan_400l_800l_setup(struct serial_private *priv,
+ struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -573,7 +549,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
offset = (idx - 2) * board->uart_offset;
}
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
static int __devinit pci_xircom_init(struct pci_dev *dev)
@@ -593,7 +569,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev)
}
static int
-pci_default_setup(struct pci_dev *dev, struct pci_board *board,
+pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -604,13 +580,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
else
offset += idx * board->uart_offset;
- maxnr = (pci_resource_len(dev, bar) - board->first_offset) /
+ maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) /
(8 << board->reg_shift);
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
return 1;
- return setup_port(dev, port, bar, offset, board->reg_shift);
+ return setup_port(priv, port, bar, offset, board->reg_shift);
}
/* This should be in linux/pci_ids.h */
@@ -691,6 +667,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_SUBVENDOR_ID_EXSYS,
+ .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
.subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
.subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
.init = pci_plx9050_init,
@@ -754,152 +739,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = sbs_setup,
.exit = __devexit_p(sbs_exit),
},
-
/*
* SIIG cards.
- * It is not clear whether these could be collapsed.
*/
{
.vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_10x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig10x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_1S_20x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- { .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_2S_20x_850,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_550,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_650,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
- .setup = pci_default_setup,
- },
- {
- .vendor = PCI_VENDOR_ID_SIIG,
- .device = PCI_DEVICE_ID_SIIG_4S_20x_850,
+ .device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .init = pci_siig20x_init,
+ .init = pci_siig_init,
.setup = pci_default_setup,
},
/*
@@ -990,7 +838,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
}
static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
+get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
{
if (board->flags & FL_NOIRQ)
return 0;
@@ -1091,6 +939,7 @@ enum pci_board_num_t {
pbn_panacom,
pbn_panacom2,
pbn_panacom4,
+ pbn_exsys_4055,
pbn_plx_romulus,
pbn_oxsemi,
pbn_intel_i960,
@@ -1115,7 +964,7 @@ enum pci_board_num_t {
* see first lines of serial_in() and serial_out() in 8250.c
*/
-static struct pci_board pci_boards[] __devinitdata = {
+static struct pciserial_board pci_boards[] __devinitdata = {
[pbn_default] = {
.flags = FL_BASE0,
.num_ports = 1,
@@ -1456,6 +1305,13 @@ static struct pci_board pci_boards[] __devinitdata = {
.reg_shift = 7,
},
+ [pbn_exsys_4055] = {
+ .flags = FL_BASE2,
+ .num_ports = 4,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+
/* I think this entry is broken - the first_offset looks wrong --rmk */
[pbn_plx_romulus] = {
.flags = FL_BASE2,
@@ -1575,7 +1431,7 @@ static struct pci_board pci_boards[] __devinitdata = {
* serial specs. Returns 0 on success, 1 on failure.
*/
static int __devinit
-serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
int num_iomem, num_port, first_port = -1, i;
@@ -1640,7 +1496,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
}
static inline int
-serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
+serial_pci_matches(struct pciserial_board *board,
+ struct pciserial_board *guessed)
{
return
board->num_ports == guessed->num_ports &&
@@ -1650,58 +1507,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
board->first_offset == guessed->first_offset;
}
-/*
- * Probe one serial board. Unfortunately, there is no rhyme nor reason
- * to the arrangement of serial ports on a PCI card.
- */
-static int __devinit
-pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+struct serial_private *
+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
{
+ struct uart_port serial_port;
struct serial_private *priv;
- struct pci_board *board, tmp;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
- if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
- printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
- ent->driver_data);
- return -EINVAL;
- }
-
- board = &pci_boards[ent->driver_data];
-
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
-
- if (ent->driver_data == pbn_default) {
- /*
- * Use a copy of the pci_board entry for this;
- * avoid changing entries in the table.
- */
- memcpy(&tmp, board, sizeof(struct pci_board));
- board = &tmp;
-
- /*
- * We matched one of our class entries. Try to
- * determine the parameters of this board.
- */
- rc = serial_pci_guess_board(dev, board);
- if (rc)
- goto disable;
- } else {
- /*
- * We matched an explicit entry. If we are able to
- * detect this boards settings with our heuristic,
- * then we no longer need this entry.
- */
- memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));
- rc = serial_pci_guess_board(dev, &tmp);
- if (rc == 0 && serial_pci_matches(board, &tmp))
- moan_device("Redundant entry in serial pci_table.",
- dev);
- }
-
nr_ports = board->num_ports;
/*
@@ -1718,8 +1531,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
*/
if (quirk->init) {
rc = quirk->init(dev);
- if (rc < 0)
- goto disable;
+ if (rc < 0) {
+ priv = ERR_PTR(rc);
+ goto err_out;
+ }
if (rc)
nr_ports = rc;
}
@@ -1728,27 +1543,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
sizeof(unsigned int) * nr_ports,
GFP_KERNEL);
if (!priv) {
- rc = -ENOMEM;
- goto deinit;
+ priv = ERR_PTR(-ENOMEM);
+ goto err_deinit;
}
memset(priv, 0, sizeof(struct serial_private) +
sizeof(unsigned int) * nr_ports);
+ priv->dev = dev;
priv->quirk = quirk;
- pci_set_drvdata(dev, priv);
+
+ memset(&serial_port, 0, sizeof(struct uart_port));
+ serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ serial_port.uartclk = board->base_baud * 16;
+ serial_port.irq = get_pci_irq(dev, board);
+ serial_port.dev = &dev->dev;
for (i = 0; i < nr_ports; i++) {
- struct uart_port serial_port;
- memset(&serial_port, 0, sizeof(struct uart_port));
-
- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF |
- UPF_SHARE_IRQ;
- serial_port.uartclk = board->base_baud * 16;
- serial_port.irq = get_pci_irq(dev, board, i);
- serial_port.dev = &dev->dev;
- if (quirk->setup(dev, board, &serial_port, i))
+ if (quirk->setup(priv, board, &serial_port, i))
break;
+
#ifdef SERIAL_DEBUG_PCI
printk("Setup PCI port: port %x, irq %d, type %d\n",
serial_port.iobase, serial_port.irq, serial_port.iotype);
@@ -1763,24 +1577,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
priv->nr = i;
- return 0;
+ return priv;
- deinit:
+ err_deinit:
if (quirk->exit)
quirk->exit(dev);
- disable:
- pci_disable_device(dev);
- return rc;
+ err_out:
+ return priv;
}
+EXPORT_SYMBOL_GPL(pciserial_init_ports);
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
+void pciserial_remove_ports(struct serial_private *priv)
{
- struct serial_private *priv = pci_get_drvdata(dev);
struct pci_serial_quirk *quirk;
int i;
- pci_set_drvdata(dev, NULL);
-
for (i = 0; i < priv->nr; i++)
serial8250_unregister_port(priv->line[i]);
@@ -1793,25 +1604,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
/*
* Find the exit quirks.
*/
- quirk = find_quirk(dev);
+ quirk = find_quirk(priv->dev);
if (quirk->exit)
- quirk->exit(dev);
+ quirk->exit(priv->dev);
+
+ kfree(priv);
+}
+EXPORT_SYMBOL_GPL(pciserial_remove_ports);
+
+void pciserial_suspend_ports(struct serial_private *priv)
+{
+ int i;
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_suspend_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
+
+void pciserial_resume_ports(struct serial_private *priv)
+{
+ int i;
+
+ /*
+ * Ensure that the board is correctly configured.
+ */
+ if (priv->quirk->init)
+ priv->quirk->init(priv->dev);
+
+ for (i = 0; i < priv->nr; i++)
+ if (priv->line[i] >= 0)
+ serial8250_resume_port(priv->line[i]);
+}
+EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+
+/*
+ * Probe one serial board. Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ struct serial_private *priv;
+ struct pciserial_board *board, tmp;
+ int rc;
+
+ if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+ printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+ ent->driver_data);
+ return -EINVAL;
+ }
+
+ board = &pci_boards[ent->driver_data];
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ if (ent->driver_data == pbn_default) {
+ /*
+ * Use a copy of the pci_board entry for this;
+ * avoid changing entries in the table.
+ */
+ memcpy(&tmp, board, sizeof(struct pciserial_board));
+ board = &tmp;
+
+ /*
+ * We matched one of our class entries. Try to
+ * determine the parameters of this board.
+ */
+ rc = serial_pci_guess_board(dev, board);
+ if (rc)
+ goto disable;
+ } else {
+ /*
+ * We matched an explicit entry. If we are able to
+ * detect this boards settings with our heuristic,
+ * then we no longer need this entry.
+ */
+ memcpy(&tmp, &pci_boards[pbn_default],
+ sizeof(struct pciserial_board));
+ rc = serial_pci_guess_board(dev, &tmp);
+ if (rc == 0 && serial_pci_matches(board, &tmp))
+ moan_device("Redundant entry in serial pci_table.",
+ dev);
+ }
+
+ priv = pciserial_init_ports(dev, board);
+ if (!IS_ERR(priv)) {
+ pci_set_drvdata(dev, priv);
+ return 0;
+ }
+
+ rc = PTR_ERR(priv);
+
+ disable:
pci_disable_device(dev);
+ return rc;
+}
- kfree(priv);
+static void __devexit pciserial_remove_one(struct pci_dev *dev)
+{
+ struct serial_private *priv = pci_get_drvdata(dev);
+
+ pci_set_drvdata(dev, NULL);
+
+ pciserial_remove_ports(priv);
+
+ pci_disable_device(dev);
}
static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
{
struct serial_private *priv = pci_get_drvdata(dev);
- if (priv) {
- int i;
+ if (priv)
+ pciserial_suspend_ports(priv);
- for (i = 0; i < priv->nr; i++)
- serial8250_suspend_port(priv->line[i]);
- }
pci_save_state(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
@@ -1825,21 +1734,12 @@ static int pciserial_resume_one(struct pci_dev *dev)
pci_restore_state(dev);
if (priv) {
- int i;
-
/*
* The device may have been disabled. Re-enable it.
*/
pci_enable_device(dev);
- /*
- * Ensure that the board is correctly configured.
- */
- if (priv->quirk->init)
- priv->quirk->init(dev);
-
- for (i = 0; i < priv->nr; i++)
- serial8250_resume_port(priv->line[i]);
+ pciserial_resume_ports(priv);
}
return 0;
}
@@ -1973,6 +1873,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CHASE_PCIRAS,
PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
pbn_b2_8_460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_EXSYS,
+ PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0,
+ pbn_exsys_4055 },
/*
* Megawolf Romulus PCI Serial Card, from Mike Hudson
* (Exoray@isys.ca)
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index 6b321e82cafb..5d8660a42b77 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -272,8 +272,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "SUP1421", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
{ "SUP1590", 0 },
+ /* SupraExpress 336i Sp ASVD */
+ { "SUP1620", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
{ "SUP1760", 0 },
+ /* SupraExpress 56i Sp Intl */
+ { "SUP2171", 0 },
/* Phoebe Micro */
/* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
{ "TEX0011", 0 },
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 97034d3937fd..b745a1b9e835 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -80,7 +80,7 @@ config SERIAL_8250_CS
config SERIAL_8250_ACPI
bool "8250/16550 device discovery via ACPI namespace"
default y if IA64
- depends on ACPI_BUS && SERIAL_8250
+ depends on ACPI && SERIAL_8250
---help---
If you wish to enable serial port discovery via the ACPI
namespace, say Y here. If unsure, say N.
@@ -211,7 +211,7 @@ comment "Non-8250 serial port support"
config SERIAL_AMBA_PL010
tristate "ARM AMBA PL010 serial port support"
- depends on ARM_AMBA
+ depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
@@ -308,7 +308,7 @@ config SERIAL_S3C2410_CONSOLE
config SERIAL_DZ
bool "DECstation DZ serial driver"
- depends on MACH_DECSTATION && MIPS32
+ depends on MACH_DECSTATION && 32BIT
select SERIAL_CORE
help
DZ11-family serial controllers for VAXstations, including the
@@ -819,7 +819,7 @@ config SERIAL_M32R_SIO_CONSOLE
config SERIAL_M32R_PLDSIO
bool "M32R SIO I/F on a PLD"
- depends on SERIAL_M32R_SIO=y
+ depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT)
default n
help
Say Y here if you want to use the M32R serial controller
@@ -830,7 +830,7 @@ config SERIAL_M32R_PLDSIO
config SERIAL_TXX9
bool "TMPTX39XX/49XX SIO support"
- depends HAS_TXX9_SERIAL
+ depends HAS_TXX9_SERIAL && BROKEN
select SERIAL_CORE
default y
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 2884b310e54d..ddd0307fece2 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -50,6 +50,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/hardware.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_serial.h>
@@ -105,7 +106,7 @@ struct uart_amba_port {
unsigned int old_status;
};
-static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pl010_stop_tx(struct uart_port *port)
{
unsigned int cr;
@@ -114,7 +115,7 @@ static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
UART_PUT_CR(port, cr);
}
-static void pl010_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pl010_start_tx(struct uart_port *port)
{
unsigned int cr;
@@ -219,7 +220,7 @@ static void pl010_tx_chars(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- pl010_stop_tx(port, 0);
+ pl010_stop_tx(port);
return;
}
@@ -236,7 +237,7 @@ static void pl010_tx_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- pl010_stop_tx(port, 0);
+ pl010_stop_tx(port);
}
static void pl010_modem_status(struct uart_port *port)
@@ -689,7 +690,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAM",
.write = pl010_console_write,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 7db88ee18f75..938d185841c9 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -50,6 +50,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#include <asm/hardware/amba_serial.h>
@@ -74,7 +75,7 @@ struct uart_amba_port {
unsigned int old_status;
};
-static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -82,7 +83,7 @@ static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
writew(uap->im, uap->port.membase + UART011_IMSC);
}
-static void pl011_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pl011_start_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -184,7 +185,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
- pl011_stop_tx(&uap->port, 0);
+ pl011_stop_tx(&uap->port);
return;
}
@@ -201,7 +202,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
uart_write_wakeup(&uap->port);
if (uart_circ_empty(xmit))
- pl011_stop_tx(&uap->port, 0);
+ pl011_stop_tx(&uap->port);
}
static void pl011_modem_status(struct uart_amba_port *uap)
@@ -701,7 +702,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAMA",
.write = pl011_console_write,
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index 6104aeef1243..a274ebf256a1 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -200,7 +200,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
}
-static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -210,7 +210,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -337,7 +337,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port, 0);
+ serial8250_stop_tx(&up->port);
return;
}
@@ -356,7 +356,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
DEBUG_INTR("THRE...");
if (uart_circ_empty(xmit))
- serial8250_stop_tx(&up->port, 0);
+ serial8250_stop_tx(&up->port);
}
static _INLINE_ void check_modem_status(struct uart_8250_port *up)
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index e92522b33c48..87ef368384fb 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -69,8 +69,7 @@
#define tx_enabled(port) ((port)->unused[0])
-static void
-clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void clps711xuart_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
@@ -78,8 +77,7 @@ clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
+static void clps711xuart_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
enable_irq(TX_IRQ(port));
@@ -100,7 +98,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
{
struct uart_port *port = dev_id;
struct tty_struct *tty = port->info->tty;
- unsigned int status, ch, flg, ignored = 0;
+ unsigned int status, ch, flg;
status = clps_readl(SYSFLG(port));
while (!(status & SYSFLG_URXFE)) {
@@ -165,7 +163,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port, 0);
+ clps711xuart_stop_tx(port);
return IRQ_HANDLED;
}
@@ -182,7 +180,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port, 0);
+ clps711xuart_stop_tx(port);
return IRQ_HANDLED;
}
@@ -527,7 +525,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver clps711x_reg;
+static struct uart_driver clps711x_reg;
static struct console clps711x_console = {
.name = "ttyCL",
.write = clps711xuart_console_write,
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 5f6187baad86..73c8a088c160 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -40,13 +40,15 @@
#define TX_NUM_FIFO 4
#define TX_BUF_SIZE 32
+#define SCC_WAIT_CLOSING 100
+
struct uart_cpm_port {
struct uart_port port;
- u16 rx_nrfifos;
+ u16 rx_nrfifos;
u16 rx_fifosize;
- u16 tx_nrfifos;
+ u16 tx_nrfifos;
u16 tx_fifosize;
- smc_t *smcp;
+ smc_t *smcp;
smc_uart_t *smcup;
scc_t *sccp;
scc_uart_t *sccup;
@@ -67,6 +69,8 @@ struct uart_cpm_port {
int bits;
/* Keep track of 'odd' SMC2 wirings */
int is_portb;
+ /* wait on close if needed */
+ int wait_closing;
};
extern int cpm_uart_port_map[UART_NR];
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 29db677d4284..25825f2aba22 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -9,9 +9,10 @@
*
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
+ *
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@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
@@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/
+static inline unsigned long cpu2cpm_addr(void *addr)
+{
+ if ((unsigned long)addr >= CPM_ADDR)
+ return (unsigned long)addr;
+ return virt_to_bus(addr);
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr)
+{
+ if (addr >= CPM_ADDR)
+ return (void *)addr;
+ return bus_to_virt(addr);
+}
+
/*
- * Check, if transmit buffers are processed
+ * Check, if transmit buffers are processed
*/
static unsigned int cpm_uart_tx_empty(struct uart_port *port)
{
@@ -109,7 +124,7 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
/*
* Stop transmitter
*/
-static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void cpm_uart_stop_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
@@ -126,7 +141,7 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
/*
* Start transmitter
*/
-static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+static void cpm_uart_start_tx(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile smc_t *smcp = pinfo->smcp;
@@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
}
if (cpm_uart_tx_pump(port) != 0) {
- if (IS_SMC(pinfo))
+ if (IS_SMC(pinfo)) {
smcp->smc_smcm |= SMCM_TX;
- else
+ smcp->smc_smcmr |= SMCMR_TEN;
+ } else {
sccp->scc_sccm |= UART_SCCM_TX;
+ pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT;
+ }
}
}
/*
- * Stop receiver
+ * Stop receiver
*/
static void cpm_uart_stop_rx(struct uart_port *port)
{
@@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port)
}
/*
- * Generate a break.
+ * Generate a break.
*/
static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
{
@@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
/* get number of characters, and check spce in flip-buffer */
i = bdp->cbd_datlen;
- /* If we have not enough room in tty flip buffer, then we try
+ /* If we have not enough room in tty flip buffer, then we try
* later, which will be the next rx-interrupt or a timeout
*/
if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
@@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
}
/* get pointer */
- cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
/* loop through the buffer */
while (i-- > 0) {
@@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
} /* End while (i--) */
/* This BD is ready to be used again. Clear status. get next */
- bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
bdp->cbd_sc |= BD_SC_EMPTY;
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->rx_bd_base;
else
bdp++;
+
} /* End for (;;) */
/* Write back buffer pointer */
@@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
if (IS_SMC(pinfo)) {
events = smcp->smc_smce;
+ smcp->smc_smce = events;
if (events & SMCM_BRKE)
uart_handle_break(port);
if (events & SMCM_RX)
cpm_uart_int_rx(port, regs);
if (events & SMCM_TX)
cpm_uart_int_tx(port, regs);
- smcp->smc_smce = events;
} else {
events = sccp->scc_scce;
+ sccp->scc_scce = events;
if (events & UART_SCCM_BRKE)
uart_handle_break(port);
if (events & UART_SCCM_RX)
cpm_uart_int_rx(port, regs);
if (events & UART_SCCM_TX)
cpm_uart_int_tx(port, regs);
- sccp->scc_scce = events;
}
return (events) ? IRQ_HANDLED : IRQ_NONE;
}
@@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port)
{
int retval;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+ int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:startup\n", port->line);
@@ -376,9 +396,17 @@ static int cpm_uart_startup(struct uart_port *port)
pinfo->sccp->scc_sccm |= UART_SCCM_RX;
}
+ if (!(pinfo->flags & FLAG_CONSOLE))
+ cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
return 0;
}
+inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
+{
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(pinfo->wait_closing);
+}
+
/*
* Shutdown the uart
*/
@@ -394,6 +422,15 @@ static void cpm_uart_shutdown(struct uart_port *port)
/* If the port is not the console, disable Rx and Tx. */
if (!(pinfo->flags & FLAG_CONSOLE)) {
+ /* Wait for all the BDs marked sent */
+ while(!cpm_uart_tx_empty(port)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ if (pinfo->wait_closing)
+ cpm_uart_wait_until_send(pinfo);
+
/* Stop uarts */
if (IS_SMC(pinfo)) {
volatile smc_t *smcp = pinfo->smcp;
@@ -502,7 +539,7 @@ static void cpm_uart_set_termios(struct uart_port *port,
*/
if ((termios->c_cflag & CREAD) == 0)
port->read_status_mask &= ~BD_SC_EMPTY;
-
+
spin_lock_irqsave(&port->lock, flags);
/* Start bit has not been added (so don't, because we would just
@@ -569,7 +606,8 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- p = bus_to_virt(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr);
+
*p++ = xmit->buf[xmit->tail];
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
@@ -586,7 +624,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- cpm_uart_stop_tx(port, 0);
+ cpm_uart_stop_tx(port);
return 0;
}
@@ -595,7 +633,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
- p = bus_to_virt(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -606,6 +644,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}
bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
@@ -618,7 +657,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
- cpm_uart_stop_tx(port, 0);
+ cpm_uart_stop_tx(port);
return 0;
}
@@ -643,12 +682,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
mem_addr += pinfo->rx_fifosize;
}
-
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
/* Set the physical address of the host memory
@@ -658,12 +697,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_INTRPT;
mem_addr += pinfo->tx_fifosize;
}
-
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
}
@@ -763,6 +802,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
/* Using idle charater time requires some additional tuning. */
up->smc_mrblr = pinfo->rx_fifosize;
up->smc_maxidl = pinfo->rx_fifosize;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
up->smc_brkcr = 1;
cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
@@ -796,7 +837,7 @@ static int cpm_uart_request_port(struct uart_port *port)
/*
* Setup any port IO, connect any baud rate generators,
* etc. This is expected to be handled by board
- * dependant code
+ * dependant code
*/
if (pinfo->set_lineif)
pinfo->set_lineif(pinfo);
@@ -815,6 +856,10 @@ static int cpm_uart_request_port(struct uart_port *port)
return ret;
cpm_uart_initbd(pinfo);
+ if (IS_SMC(pinfo))
+ cpm_uart_init_smc(pinfo);
+ else
+ cpm_uart_init_scc(pinfo);
return 0;
}
@@ -869,7 +914,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = smc1_lineif,
},
@@ -883,7 +928,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = smc2_lineif,
#ifdef CONFIG_SERIAL_CPM_ALT_SMC2
@@ -899,9 +944,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc1_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC2] = {
.port = {
@@ -912,9 +958,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc2_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC3] = {
.port = {
@@ -925,9 +972,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc3_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC4] = {
.port = {
@@ -938,9 +986,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc4_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
};
@@ -983,11 +1032,8 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* If the buffer address is in the CPM DPRAM, don't
* convert it.
*/
- if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
- cp = (unsigned char *) (bdp->cbd_bufaddr);
- else
- cp = bus_to_virt(bdp->cbd_bufaddr);
-
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+
*cp = *s;
bdp->cbd_datlen = 1;
@@ -1003,10 +1049,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
while ((bdp->cbd_sc & BD_SC_READY) != 0)
;
- if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
- cp = (unsigned char *) (bdp->cbd_bufaddr);
- else
- cp = bus_to_virt(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
*cp = 13;
bdp->cbd_datlen = 1;
@@ -1045,7 +1088,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
port =
(struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
pinfo = (struct uart_cpm_port *)port;
-
+
pinfo->flags |= FLAG_CONSOLE;
if (options) {
@@ -1062,7 +1105,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
/*
* Setup any port IO, connect any baud rate generators,
* etc. This is expected to be handled by board
- * dependant code
+ * dependant code
*/
if (pinfo->set_lineif)
pinfo->set_lineif(pinfo);
@@ -1092,14 +1135,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
return 0;
}
-extern struct uart_driver cpm_reg;
+static struct uart_driver cpm_reg;
static struct console cpm_scc_uart_console = {
- .name "ttyCPM",
- .write cpm_uart_console_write,
- .device uart_console_device,
- .setup cpm_uart_console_setup,
- .flags CON_PRINTBUFFER,
- .index -1,
+ .name = "ttyCPM",
+ .write = cpm_uart_console_write,
+ .device = uart_console_device,
+ .setup = cpm_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
.data = &cpm_reg,
};
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 8efbd6d1d6a4..4b0786e7eb7f 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -5,7 +5,7 @@
*
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
+ *
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
*
@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo)
{
volatile cpm8xx_t *cp = cpmp;
+
+ (void)cp; /* fix warning */
+#if defined (CONFIG_MPC885ADS)
+ /* Enable SMC1 transceivers */
+ {
+ cp->cp_pepar |= 0x000000c0;
+ cp->cp_pedir &= ~0x000000c0;
+ cp->cp_peso &= ~0x00000040;
+ cp->cp_peso |= 0x00000080;
+ }
+#elif defined (CONFIG_MPC86XADS)
unsigned int iobits = 0x000000c0;
if (!pinfo->is_portb) {
@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
}
-
-#ifdef CONFIG_MPC885ADS
- /* Enable SMC1 transceivers */
- {
- volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4);
- uint tmp;
-
- tmp = in_be32(bcsr1);
- tmp &= ~BCSR1_RS232EN_1;
- out_be32(bcsr1, tmp);
- iounmap(bcsr1);
- }
#endif
-
pinfo->brg = 1;
}
void smc2_lineif(struct uart_cpm_port *pinfo)
{
-#ifdef CONFIG_MPC885ADS
volatile cpm8xx_t *cp = cpmp;
- volatile uint __iomem *bcsr1;
- uint tmp;
+ (void)cp; /* fix warning */
+#if defined (CONFIG_MPC885ADS)
cp->cp_pepar |= 0x00000c00;
cp->cp_pedir &= ~0x00000c00;
cp->cp_peso &= ~0x00000400;
cp->cp_peso |= 0x00000800;
+#elif defined (CONFIG_MPC86XADS)
+ unsigned int iobits = 0x00000c00;
+
+ if (!pinfo->is_portb) {
+ cp->cp_pbpar |= iobits;
+ cp->cp_pbdir &= ~iobits;
+ cp->cp_pbodr &= ~iobits;
+ } else {
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
+ }
- /* Enable SMC2 transceivers */
- bcsr1 = ioremap(BCSR1, 4);
- tmp = in_be32(bcsr1);
- tmp &= ~BCSR1_RS232EN_2;
- out_be32(bcsr1, tmp);
- iounmap(bcsr1);
#endif
pinfo->brg = 2;
@@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
}
/*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
* receive buffer descriptors from dual port ram, and a character
* buffer area from host mem. If we are allocating for the console we need
* to do it from bootmem
@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
if (is_con) {
+ /* was hostalloc but changed cause it blows away the */
+ /* large tlb mapping when pinning the kernel area */
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = 0;
} else
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index c4c8f4b44f53..15ad58d94889 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -142,6 +142,14 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
* be supported in a sane fashion.
*/
#ifndef CONFIG_STX_GP3
+#ifdef CONFIG_MPC8560_ADS
+ volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+ io->iop_ppard |= 0x00000018;
+ io->iop_psord &= ~0x00000008; /* Rx */
+ io->iop_psord &= ~0x00000010; /* Tx */
+ io->iop_pdird &= ~0x00000008; /* Rx */
+ io->iop_pdird |= 0x00000010; /* Tx */
+#else
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
@@ -149,6 +157,7 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
#endif
+#endif
cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
pinfo->brg = 2;
@@ -257,6 +266,7 @@ int cpm_uart_init_portdesc(void)
cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
cpm_uart_ports[UART_SMC1].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
+ *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
cpm_uart_ports[UART_SMC1].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[0];
cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
@@ -269,6 +279,7 @@ int cpm_uart_init_portdesc(void)
cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
cpm_uart_ports[UART_SMC2].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
+ *(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
cpm_uart_ports[UART_SMC2].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[1];
cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 23b8871e74cc..40d3e7139cfe 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -446,7 +446,6 @@ static char *serial_version = "$Revision: 1.25 $";
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <linux/delay.h>
@@ -5041,17 +5040,3 @@ rs_init(void)
/* this makes sure that rs_init is called during kernel boot */
module_init(rs_init);
-
-/*
- * register_serial and unregister_serial allows for serial ports to be
- * configured at run-time, to support PCMCIA modems.
- */
-int
-register_serial(struct serial_struct *req)
-{
- return -1;
-}
-
-void unregister_serial(int line)
-{
-}
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 97824eeeafae..e63b9dffc8d7 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -112,7 +112,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset,
* ------------------------------------------------------------
*/
-static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
+static void dz_stop_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
@@ -125,7 +125,7 @@ static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
spin_unlock_irqrestore(&dport->port.lock, flags);
}
-static void dz_start_tx(struct uart_port *uport, unsigned int tty_start)
+static void dz_start_tx(struct uart_port *uport)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned short tmp, mask = 1 << dport->port.line;
@@ -290,7 +290,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)
}
/* if nothing to do or stopped or hardware stopped */
if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
- dz_stop_tx(&dport->port, 0);
+ dz_stop_tx(&dport->port);
return;
}
@@ -308,7 +308,7 @@ static inline void dz_transmit_chars(struct dz_port *dport)
/* Are we done */
if (uart_circ_empty(xmit))
- dz_stop_tx(&dport->port, 0);
+ dz_stop_tx(&dport->port);
}
/*
@@ -440,7 +440,7 @@ static int dz_startup(struct uart_port *uport)
*/
static void dz_shutdown(struct uart_port *uport)
{
- dz_stop_tx(uport, 0);
+ dz_stop_tx(uport);
}
/*
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index c112b32764e8..eb31125c6a30 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -56,7 +56,6 @@
#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -989,18 +988,16 @@ static unsigned int icom_get_mctrl(struct uart_port *port)
return result;
}
-static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void icom_stop_tx(struct uart_port *port)
{
unsigned char cmdReg;
- if (tty_stop) {
- trace(ICOM_PORT, "STOP", 0);
- cmdReg = readb(&ICOM_PORT->dram->CmdReg);
- writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
- }
+ trace(ICOM_PORT, "STOP", 0);
+ cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+ writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
}
-static void icom_start_tx(struct uart_port *port, unsigned int tty_start)
+static void icom_start_tx(struct uart_port *port)
{
unsigned char cmdReg;
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 01a8726a3f97..4a54ff584700 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -36,7 +36,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
@@ -73,7 +73,7 @@ struct imx_port {
struct uart_port port;
struct timer_list timer;
unsigned int old_status;
- int txirq,rxirq;
+ int txirq,rxirq,rtsirq;
};
/*
@@ -124,7 +124,7 @@ static void imx_timeout(unsigned long data)
/*
* interrupts disabled on entry
*/
-static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void imx_stop_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
@@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
} while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
if (uart_circ_empty(xmit))
- imx_stop_tx(&sport->port, 0);
+ imx_stop_tx(&sport->port);
}
/*
* interrupts disabled on entry
*/
-static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
+static void imx_start_tx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
@@ -181,6 +181,22 @@ static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
imx_transmit_buffer(sport);
}
+static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct imx_port *sport = (struct imx_port *)dev_id;
+ unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ USR1((u32)sport->port.membase) = USR1_RTSD;
+ uart_handle_cts_change(&sport->port, !!val);
+ wake_up_interruptible(&sport->port.info->delta_msr_wait);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+ return IRQ_HANDLED;
+}
+
static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
{
struct imx_port *sport = (struct imx_port *)dev_id;
@@ -196,7 +212,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- imx_stop_tx(&sport->port, 0);
+ imx_stop_tx(&sport->port);
goto out;
}
@@ -291,13 +307,31 @@ static unsigned int imx_tx_empty(struct uart_port *port)
return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0;
}
+/*
+ * We have a modem side uart, so the meanings of RTS and CTS are inverted.
+ */
static unsigned int imx_get_mctrl(struct uart_port *port)
{
- return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+ struct imx_port *sport = (struct imx_port *)port;
+ unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
+
+ if (USR1((u32)sport->port.membase) & USR1_RTSS)
+ tmp |= TIOCM_CTS;
+
+ if (UCR2((u32)sport->port.membase) & UCR2_CTS)
+ tmp |= TIOCM_RTS;
+
+ return tmp;
}
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ struct imx_port *sport = (struct imx_port *)port;
+
+ if (mctrl & TIOCM_RTS)
+ UCR2((u32)sport->port.membase) |= UCR2_CTS;
+ else
+ UCR2((u32)sport->port.membase) &= ~UCR2_CTS;
}
/*
@@ -365,18 +399,24 @@ static int imx_startup(struct uart_port *port)
*/
retval = request_irq(sport->rxirq, imx_rxint, 0,
DRIVER_NAME, sport);
- if (retval) goto error_out2;
+ if (retval) goto error_out1;
retval = request_irq(sport->txirq, imx_txint, 0,
- "imx-uart", sport);
- if (retval) goto error_out1;
+ DRIVER_NAME, sport);
+ if (retval) goto error_out2;
+
+ retval = request_irq(sport->rtsirq, imx_rtsint, 0,
+ DRIVER_NAME, sport);
+ if (retval) goto error_out3;
+ set_irq_type(sport->rtsirq, IRQT_BOTHEDGE);
/*
* Finally, clear and enable interrupts
*/
+ USR1((u32)sport->port.membase) = USR1_RTSD;
UCR1((u32)sport->port.membase) |=
- (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+ (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
/*
@@ -388,10 +428,11 @@ static int imx_startup(struct uart_port *port)
return 0;
-error_out1:
- free_irq(sport->rxirq, sport);
-error_out2:
+error_out3:
free_irq(sport->txirq, sport);
+error_out2:
+ free_irq(sport->rxirq, sport);
+error_out1:
return retval;
}
@@ -407,6 +448,7 @@ static void imx_shutdown(struct uart_port *port)
/*
* Free the interrupts
*/
+ free_irq(sport->rtsirq, sport);
free_irq(sport->txirq, sport);
free_irq(sport->rxirq, sport);
@@ -415,7 +457,7 @@ static void imx_shutdown(struct uart_port *port)
*/
UCR1((u32)sport->port.membase) &=
- ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+ ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
}
static void
@@ -505,7 +547,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
* disable interrupts and drain transmitter
*/
old_ucr1 = UCR1((u32)sport->port.membase);
- UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
+ UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
barrier();
@@ -626,6 +668,7 @@ static struct imx_port imx_ports[] = {
{
.txirq = UART1_MINT_TX,
.rxirq = UART1_MINT_RX,
+ .rtsirq = UART1_MINT_RTS,
.port = {
.type = PORT_IMX,
.iotype = SERIAL_IO_MEM,
@@ -641,6 +684,7 @@ static struct imx_port imx_ports[] = {
}, {
.txirq = UART2_MINT_TX,
.rxirq = UART2_MINT_RX,
+ .rtsirq = UART2_MINT_RTS,
.port = {
.type = PORT_IMX,
.iotype = SERIAL_IO_MEM,
@@ -720,7 +764,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
UCR1((u32)sport->port.membase) =
(old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
- & ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
+ & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
/*
@@ -842,7 +886,7 @@ imx_console_setup(struct console *co, char *options)
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver imx_reg;
+static struct uart_driver imx_reg;
static struct console imx_console = {
.name = "ttySMX",
.write = imx_console_write,
@@ -877,21 +921,21 @@ static struct uart_driver imx_reg = {
.cons = IMX_CONSOLE,
};
-static int serial_imx_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_imx_suspend(struct device *_dev, pm_message_t state)
{
struct imx_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&imx_reg, &sport->port);
return 0;
}
-static int serial_imx_resume(struct device *_dev, u32 level)
+static int serial_imx_resume(struct device *_dev)
{
struct imx_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&imx_reg, &sport->port);
return 0;
@@ -951,6 +995,7 @@ static int __init imx_serial_init(void)
static void __exit imx_serial_exit(void)
{
uart_unregister_driver(&imx_reg);
+ driver_unregister(&serial_imx_driver);
}
module_init(imx_serial_init);
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 793c3a7cbe47..771676abee60 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -308,6 +308,8 @@ struct ioc4_serial {
typedef void ioc4_intr_func_f(void *, uint32_t);
typedef ioc4_intr_func_f *ioc4_intr_func_t;
+static unsigned int Num_of_ioc4_cards;
+
/* defining this will get you LOTS of great debug info */
//#define DEBUG_INTERRUPTS
#define DPRINT_CONFIG(_x...) ;
@@ -317,7 +319,8 @@ typedef ioc4_intr_func_f *ioc4_intr_func_t;
#define WAKEUP_CHARS 256
/* number of characters we want to transmit to the lower level at a time */
-#define IOC4_MAX_CHARS 128
+#define IOC4_MAX_CHARS 256
+#define IOC4_FIFO_CHARS 255
/* Device name we're using */
#define DEVICE_NAME "ttyIOC"
@@ -973,18 +976,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
this_ir &= ~this_mir;
}
}
- if (this_ir) {
- printk(KERN_ERR
- "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x,"
- " sio_ies = 0x%x, other_ir = 0x%x :"
- "other_ies = 0x%x\n",
- (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
- "other", this_ir,
- readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
- readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
- readl(&soft->is_ioc4_misc_addr->other_ir.raw),
- readl(&soft->is_ioc4_misc_addr->other_ies.raw));
- }
}
#ifdef DEBUG_INTERRUPTS
{
@@ -1050,6 +1041,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
return -ENOMEM;
}
memset(port, 0, sizeof(struct ioc4_port));
+ spin_lock_init(&port->ip_lock);
/* we need to remember the previous ones, to point back to
* them farther down - setting up the ring buffers.
@@ -1703,12 +1695,14 @@ ioc4_change_speed(struct uart_port *the_port,
baud = 9600;
if (!the_port->fifosize)
- the_port->fifosize = IOC4_MAX_CHARS;
+ the_port->fifosize = IOC4_FIFO_CHARS;
the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
the_port->timeout += HZ / 50; /* Add .02 seconds of slop */
the_port->ignore_status_mask = N_ALL_INPUT;
+ info->tty->low_latency = 1;
+
if (I_IGNPAR(info->tty))
the_port->ignore_status_mask &= ~(N_PARITY_ERROR
| N_FRAMING_ERROR);
@@ -1754,7 +1748,6 @@ ioc4_change_speed(struct uart_port *the_port,
*/
static inline int ic4_startup_local(struct uart_port *the_port)
{
- int retval = 0;
struct ioc4_port *port;
struct uart_info *info;
@@ -1766,9 +1759,6 @@ static inline int ic4_startup_local(struct uart_port *the_port)
return -1;
info = the_port->info;
- if (info->flags & UIF_INITIALIZED) {
- return retval;
- }
if (info->tty) {
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1787,7 +1777,6 @@ static inline int ic4_startup_local(struct uart_port *the_port)
/* set the speed of the serial port */
ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
- info->flags |= UIF_INITIALIZED;
return 0;
}
@@ -1797,9 +1786,13 @@ static inline int ic4_startup_local(struct uart_port *the_port)
*/
static void ioc4_cb_output_lowat(struct ioc4_port *port)
{
+ unsigned long pflags;
+
/* ip_lock is set on the call here */
if (port->ip_port) {
+ spin_lock_irqsave(&port->ip_port->lock, pflags);
transmit_chars(port->ip_port);
+ spin_unlock_irqrestore(&port->ip_port->lock, pflags);
}
}
@@ -2076,8 +2069,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf,
* available data as long as it returns some.
*/
/* Re-arm the timer */
- writel(port->ip_rx_cons | IOC4_SRCIR_ARM,
- &port->ip_serial_regs->srcir);
+ writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
cons_ptr = port->ip_rx_cons;
@@ -2311,6 +2303,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf,
}
return total;
}
+
/**
* receive_chars - upper level read. Called with ip_lock.
* @the_port: port to read from
@@ -2319,9 +2312,11 @@ static void receive_chars(struct uart_port *the_port)
{
struct tty_struct *tty;
unsigned char ch[IOC4_MAX_CHARS];
- int read_count, request_count;
+ int read_count, request_count = IOC4_MAX_CHARS;
struct uart_icount *icount;
struct uart_info *info = the_port->info;
+ int flip = 0;
+ unsigned long pflags;
/* Make sure all the pointers are "good" ones */
if (!info)
@@ -2329,16 +2324,17 @@ static void receive_chars(struct uart_port *the_port)
if (!info->tty)
return;
+ spin_lock_irqsave(&the_port->lock, pflags);
tty = info->tty;
- request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
+ if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count)
+ request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
if (request_count > 0) {
- if (request_count > IOC4_MAX_CHARS - 2)
- request_count = IOC4_MAX_CHARS - 2;
icount = &the_port->icount;
read_count = do_read(the_port, ch, request_count);
if (read_count > 0) {
+ flip = 1;
memcpy(tty->flip.char_buf_ptr, ch, read_count);
memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
tty->flip.char_buf_ptr += read_count;
@@ -2347,7 +2343,11 @@ static void receive_chars(struct uart_port *the_port)
icount->rx += read_count;
}
}
- tty_flip_buffer_push(tty);
+
+ spin_unlock_irqrestore(&the_port->lock, pflags);
+
+ if (flip)
+ tty_flip_buffer_push(tty);
}
/**
@@ -2373,10 +2373,9 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port)
/**
* ic4_stop_tx - stop the transmitter
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_stop
*
*/
-static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop)
+static void ic4_stop_tx(struct uart_port *the_port)
{
}
@@ -2406,18 +2405,14 @@ static void ic4_shutdown(struct uart_port *the_port)
info = the_port->info;
- if (!(info->flags & UIF_INITIALIZED))
- return;
-
wake_up_interruptible(&info->delta_msr_wait);
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
- spin_lock_irqsave(&port->ip_lock, port_flags);
+ spin_lock_irqsave(&the_port->lock, port_flags);
set_notification(port, N_ALL, 0);
- info->flags &= ~UIF_INITIALIZED;
- spin_unlock_irqrestore(&port->ip_lock, port_flags);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
}
/**
@@ -2471,18 +2466,15 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port)
/**
* ic4_start_tx - Start transmitter, flush any output
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_start
*
*/
-static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop)
+static void ic4_start_tx(struct uart_port *the_port)
{
struct ioc4_port *port = get_ioc4_port(the_port);
- unsigned long flags;
if (port) {
- spin_lock_irqsave(&port->ip_lock, flags);
- transmit_chars(the_port);
- spin_unlock_irqrestore(&port->ip_lock, flags);
+ set_notification(port, N_OUTPUT_LOWAT, 1);
+ enable_intrs(port, port->ip_hooks->intr_tx_mt);
}
}
@@ -2524,9 +2516,9 @@ static int ic4_startup(struct uart_port *the_port)
}
/* Start up the serial port */
- spin_lock_irqsave(&port->ip_lock, port_flags);
+ spin_lock_irqsave(&the_port->lock, port_flags);
retval = ic4_startup_local(the_port);
- spin_unlock_irqrestore(&port->ip_lock, port_flags);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
return retval;
}
@@ -2541,12 +2533,11 @@ static void
ic4_set_termios(struct uart_port *the_port,
struct termios *termios, struct termios *old_termios)
{
- struct ioc4_port *port = get_ioc4_port(the_port);
unsigned long port_flags;
- spin_lock_irqsave(&port->ip_lock, port_flags);
+ spin_lock_irqsave(&the_port->lock, port_flags);
ioc4_change_speed(the_port, termios, old_termios);
- spin_unlock_irqrestore(&port->ip_lock, port_flags);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
}
/**
@@ -2621,24 +2612,25 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
__FUNCTION__, (void *)the_port,
(void *)port));
- spin_lock_init(&the_port->lock);
/* membase, iobase and mapbase just need to be non-0 */
the_port->membase = (unsigned char __iomem *)1;
- the_port->line = the_port->iobase = ii;
+ the_port->iobase = (pdev->bus->number << 16) | ii;
+ the_port->line = (Num_of_ioc4_cards << 2) | ii;
the_port->mapbase = 1;
the_port->type = PORT_16550A;
- the_port->fifosize = IOC4_MAX_CHARS;
+ the_port->fifosize = IOC4_FIFO_CHARS;
the_port->ops = &ioc4_ops;
the_port->irq = control->ic_irq;
the_port->dev = &pdev->dev;
+ spin_lock_init(&the_port->lock);
if (uart_add_one_port(&ioc4_uart, the_port) < 0) {
printk(KERN_WARNING
- "%s: unable to add port %d\n",
- __FUNCTION__, the_port->line);
+ "%s: unable to add port %d bus %d\n",
+ __FUNCTION__, the_port->line, pdev->bus->number);
} else {
DPRINT_CONFIG(
- ("IOC4 serial driver port %d irq = %d\n",
- the_port->line, the_port->irq));
+ ("IOC4 serial port %d irq = %d, bus %d\n",
+ the_port->line, the_port->irq, pdev->bus->number));
}
/* all ports are rs232 for now */
ioc4_set_proto(port, PROTO_RS232);
@@ -2748,6 +2740,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
goto out4;
+ Num_of_ioc4_cards++;
+
return ret;
/* error exits that give back resources */
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ea5bf4d4daa3..ef132349f310 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -592,7 +592,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
}
/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void ip22zilog_stop_tx(struct uart_port *port)
{
struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
@@ -600,7 +600,7 @@ static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
/* The port lock is held and interrupts are disabled. */
-static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start)
+static void ip22zilog_start_tx(struct uart_port *port)
{
struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 98de2258fd06..6fa0d62d6f68 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -113,7 +113,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
udelay(10);
}
-static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
+static void jsm_tty_start_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
@@ -125,7 +125,7 @@ static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
}
-static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void jsm_tty_stop_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 0301feacbde4..b0ecc7537ce5 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -275,7 +275,7 @@ serial_out(struct uart_sio_port *up, int offset, int value)
__sio_out(value, offset);
}
-static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void m32r_sio_stop_tx(struct uart_port *port)
{
struct uart_sio_port *up = (struct uart_sio_port *)port;
@@ -285,7 +285,7 @@ static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void m32r_sio_start_tx(struct uart_port *port, unsigned int tty_start)
+static void m32r_sio_start_tx(struct uart_port *port)
{
#ifdef CONFIG_SERIAL_M32R_PLDSIO
struct uart_sio_port *up = (struct uart_sio_port *)port;
@@ -425,7 +425,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- m32r_sio_stop_tx(&up->port, 0);
+ m32r_sio_stop_tx(&up->port);
return;
}
@@ -446,7 +446,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up)
DEBUG_INTR("THRE...");
if (uart_circ_empty(xmit))
- m32r_sio_stop_tx(&up->port, 0);
+ m32r_sio_stop_tx(&up->port);
}
/*
@@ -1123,7 +1123,7 @@ static int __init m32r_sio_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver m32r_sio_reg;
+static struct uart_driver m32r_sio_reg;
static struct console m32r_sio_console = {
.name = "ttyS",
.write = m32r_sio_console_write,
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 8c40167778de..e2ebdcad553c 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -40,7 +40,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/semaphore.h>
#include <asm/delay.h>
#include <asm/coldfire.h>
@@ -64,8 +63,13 @@ struct timer_list mcfrs_timer_struct;
#endif
#if defined(CONFIG_HW_FEITH)
- #define CONSOLE_BAUD_RATE 38400
- #define DEFAULT_CBAUD B38400
+#define CONSOLE_BAUD_RATE 38400
+#define DEFAULT_CBAUD B38400
+#endif
+
+#if defined(CONFIG_MOD5272)
+#define CONSOLE_BAUD_RATE 115200
+#define DEFAULT_CBAUD B115200
#endif
#ifndef CONSOLE_BAUD_RATE
@@ -91,7 +95,7 @@ static struct tty_driver *mcfrs_serial_driver;
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
@@ -1511,7 +1515,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
*portp = (*portp & ~0x000000ff) | 0x00000055;
portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
*portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
volatile unsigned char *icrp, *uartp;
volatile unsigned long *imrp;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 2a5cf174ca30..0dd08a09e7e6 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -45,7 +45,7 @@
*/
#include <linux/config.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -119,7 +119,7 @@ mpc52xx_uart_get_mctrl(struct uart_port *port)
}
static void
-mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+mpc52xx_uart_stop_tx(struct uart_port *port)
{
/* port->lock taken by caller */
port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
@@ -127,7 +127,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
static void
-mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+mpc52xx_uart_start_tx(struct uart_port *port)
{
/* port->lock taken by caller */
port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
@@ -485,7 +485,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
/* Nothing to do ? */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mpc52xx_uart_stop_tx(port,0);
+ mpc52xx_uart_stop_tx(port);
return 0;
}
@@ -504,7 +504,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port)
/* Maybe we're done after all */
if (uart_circ_empty(xmit)) {
- mpc52xx_uart_stop_tx(port,0);
+ mpc52xx_uart_stop_tx(port);
return 0;
}
@@ -781,22 +781,22 @@ mpc52xx_uart_remove(struct device *dev)
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct device *dev, u32 level)
+mpc52xx_uart_resume(struct device *dev)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- if (port && level == RESUME_ENABLE)
+ if (port)
uart_resume_port(&mpc52xx_uart_driver, port);
return 0;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index e43276c6a954..ba8838b234da 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -52,6 +52,8 @@
* 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
*/
+#include <linux/platform_device.h>
+
#include "mpsc.h"
/*
@@ -1072,18 +1074,18 @@ mpsc_get_mctrl(struct uart_port *port)
}
static void
-mpsc_stop_tx(struct uart_port *port, uint tty_start)
+mpsc_stop_tx(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- pr_debug("mpsc_stop_tx[%d]: tty_start: %d\n", port->line, tty_start);
+ pr_debug("mpsc_stop_tx[%d]\n", port->line);
mpsc_freeze(pi);
return;
}
static void
-mpsc_start_tx(struct uart_port *port, uint tty_start)
+mpsc_start_tx(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
@@ -1091,7 +1093,7 @@ mpsc_start_tx(struct uart_port *port, uint tty_start)
mpsc_copy_tx_data(pi);
mpsc_sdma_start_tx(pi);
- pr_debug("mpsc_start_tx[%d]: tty_start: %d\n", port->line, tty_start);
+ pr_debug("mpsc_start_tx[%d]\n", port->line);
return;
}
@@ -1100,6 +1102,8 @@ mpsc_start_rx(struct mpsc_port_info *pi)
{
pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line);
+ /* Issue a Receive Abort to clear any receive errors */
+ writel(MPSC_CHR_2_RA, pi->mpsc_base + MPSC_CHR_2);
if (pi->rcv_data) {
mpsc_enter_hunt(pi);
mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index dadd7e19714e..660bae5ba179 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -27,6 +27,7 @@
#include <linux/delay.h> /* for udelay */
#include <linux/device.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/parisc-device.h>
#ifdef CONFIG_MAGIC_SYSRQ
@@ -111,22 +112,20 @@ static unsigned int mux_get_mctrl(struct uart_port *port)
/**
* mux_stop_tx - Stop transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_stop: tty layer issue this command?
*
* The Serial MUX does not support this function.
*/
-static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void mux_stop_tx(struct uart_port *port)
{
}
/**
* mux_start_tx - Start transmitting characters.
* @port: Ptr to the uart_port.
- * @tty_start: tty layer issue this command?
*
* The Serial Mux does not support this function.
*/
-static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
+static void mux_start_tx(struct uart_port *port)
{
}
@@ -181,7 +180,7 @@ static void mux_write(struct uart_port *port)
}
if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
return;
}
@@ -202,7 +201,7 @@ static void mux_write(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- mux_stop_tx(port, 0);
+ mux_stop_tx(port);
}
/**
@@ -446,7 +445,7 @@ static int __init mux_probe(struct parisc_device *dev)
unsigned long bytecnt;
struct uart_port *port;
- status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
+ status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
if(status != PDC_OK) {
printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
return 1;
@@ -471,16 +470,18 @@ static int __init mux_probe(struct parisc_device *dev)
for(i = 0; i < ports; ++i, ++port_cnt) {
port = &mux_ports[port_cnt];
port->iobase = 0;
- port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
+ port->mapbase = dev->hpa.start + MUX_OFFSET +
+ (i * MUX_LINE_OFFSET);
port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
port->iotype = SERIAL_IO_MEM;
port->type = PORT_MUX;
- port->irq = SERIAL_IRQ_NONE;
+ port->irq = NO_IRQ;
port->uartclk = 0;
port->fifosize = MUX_FIFO_SIZE;
port->ops = &mux_pops;
port->flags = UPF_BOOT_AUTOCONF;
port->line = port_cnt;
+ spin_lock_init(&port->lock);
status = uart_add_one_port(&mux_driver, port);
BUG_ON(status);
}
@@ -499,7 +500,7 @@ static struct parisc_device_id mux_tbl[] = {
MODULE_DEVICE_TABLE(parisc, mux_tbl);
static struct parisc_driver serial_mux_driver = {
- .name = "Serial MUX",
+ .name = "serial_mux",
.id_table = mux_tbl,
.probe = mux_probe,
};
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 7db2f37532cf..5ddd8ab1f108 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -630,11 +630,10 @@ static unsigned int pmz_get_mctrl(struct uart_port *port)
/*
* Stop TX side. Dealt like sunzilog at next Tx interrupt,
- * though for DMA, we will have to do a bit more. What is
- * the meaning of the tty_stop bit ? XXX
+ * though for DMA, we will have to do a bit more.
* The port lock is held and interrupts are disabled.
*/
-static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void pmz_stop_tx(struct uart_port *port)
{
to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED;
}
@@ -643,7 +642,7 @@ static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop)
* Kick the Tx side.
* The port lock is held and interrupts are disabled.
*/
-static void pmz_start_tx(struct uart_port *port, unsigned int tty_start)
+static void pmz_start_tx(struct uart_port *port)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned char status;
@@ -1601,7 +1600,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
return 0;
}
- if (pm_state == mdev->ofdev.dev.power.power_state || pm_state < 2)
+ if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
return 0;
pmz_debug("suspend, switching to state %d\n", pm_state);
@@ -1661,7 +1660,7 @@ static int pmz_resume(struct macio_dev *mdev)
if (uap == NULL)
return 0;
- if (mdev->ofdev.dev.power.power_state == 0)
+ if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
return 0;
pmz_debug("resume, switching to state 0\n");
@@ -1714,7 +1713,7 @@ static int pmz_resume(struct macio_dev *mdev)
pmz_debug("resume, switching complete\n");
- mdev->ofdev.dev.power.power_state = 0;
+ mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
return 0;
}
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 461c81c93207..16b2f9417af9 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -39,7 +39,7 @@
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
@@ -80,7 +80,7 @@ static void serial_pxa_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
-static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial_pxa_stop_tx(struct uart_port *port)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
@@ -185,7 +185,7 @@ static void transmit_chars(struct uart_pxa_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_pxa_stop_tx(&up->port, 0);
+ serial_pxa_stop_tx(&up->port);
return;
}
@@ -203,10 +203,10 @@ static void transmit_chars(struct uart_pxa_port *up)
if (uart_circ_empty(xmit))
- serial_pxa_stop_tx(&up->port, 0);
+ serial_pxa_stop_tx(&up->port);
}
-static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial_pxa_start_tx(struct uart_port *port)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
@@ -358,6 +358,9 @@ static int serial_pxa_startup(struct uart_port *port)
unsigned long flags;
int retval;
+ if (port->line == 3) /* HWUART */
+ up->mcr |= UART_MCR_AFE;
+ else
up->mcr = 0;
/*
@@ -481,8 +484,10 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
if ((up->port.uartclk / quot) < (2400 * 16))
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
- else
+ else if ((up->port.uartclk / quot) < (230400 * 16))
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
+ else
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
/*
* Ok, we're now changing the port state. Do it with
@@ -499,7 +504,7 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
/*
* Update the per-port timeout.
*/
- uart_update_timeout(port, termios->c_cflag, quot);
+ uart_update_timeout(port, termios->c_cflag, baud);
up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
if (termios->c_iflag & INPCK)
@@ -589,8 +594,8 @@ serial_pxa_type(struct uart_port *port)
#ifdef CONFIG_SERIAL_PXA_CONSOLE
-extern struct uart_pxa_port serial_pxa_ports[];
-extern struct uart_driver serial_pxa_reg;
+static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_driver serial_pxa_reg;
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -772,6 +777,20 @@ static struct uart_pxa_port serial_pxa_ports[] = {
.ops = &serial_pxa_pops,
.line = 2,
},
+ }, { /* HWUART */
+ .name = "HWUART",
+ .cken = CKEN4_HWUART,
+ .port = {
+ .type = PORT_PXA,
+ .iotype = UPIO_MEM,
+ .membase = (void *)&HWUART,
+ .mapbase = __PREG(HWUART),
+ .irq = IRQ_HWUART,
+ .uartclk = 921600 * 16,
+ .fifosize = 64,
+ .ops = &serial_pxa_pops,
+ .line = 3,
+ },
}
};
@@ -786,21 +805,21 @@ static struct uart_driver serial_pxa_reg = {
.cons = PXA_CONSOLE,
};
-static int serial_pxa_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_pxa_suspend(struct device *_dev, pm_message_t state)
{
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&serial_pxa_reg, &sport->port);
return 0;
}
-static int serial_pxa_resume(struct device *_dev, u32 level)
+static int serial_pxa_resume(struct device *_dev)
{
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&serial_pxa_reg, &sport->port);
return 0;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 7365d4b50b95..036792328d49 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -63,7 +63,7 @@
#include <linux/module.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/sysrq.h>
#include <linux/console.h>
@@ -82,8 +82,6 @@
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
-#include <asm/mach-types.h>
-
/* structures */
struct s3c24xx_uart_info {
@@ -246,8 +244,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
}
-static void
-s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void s3c24xx_serial_stop_tx(struct uart_port *port)
{
if (tx_enabled(port)) {
disable_irq(TX_IRQ(port));
@@ -257,8 +254,7 @@ s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
-static void
-s3c24xx_serial_start_tx(struct uart_port *port, unsigned int tty_start)
+static void s3c24xx_serial_start_tx(struct uart_port *port)
{
if (!tx_enabled(port)) {
if (port->flags & UPF_CONS_FLOW)
@@ -424,7 +420,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re
*/
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- s3c24xx_serial_stop_tx(port, 0);
+ s3c24xx_serial_stop_tx(port);
goto out;
}
@@ -443,7 +439,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- s3c24xx_serial_stop_tx(port, 0);
+ s3c24xx_serial_stop_tx(port);
out:
return IRQ_HANDLED;
@@ -755,8 +751,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct s3c24xx_uart_clksrc *clksrc;
- struct clk *clk;
+ struct s3c24xx_uart_clksrc *clksrc = NULL;
+ struct clk *clk = NULL;
unsigned long flags;
unsigned int baud, quot;
unsigned int ulcon;
@@ -1096,8 +1092,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
static int probe_index = 0;
-int s3c24xx_serial_probe(struct device *_dev,
- struct s3c24xx_uart_info *info)
+static int s3c24xx_serial_probe(struct device *_dev,
+ struct s3c24xx_uart_info *info)
{
struct s3c24xx_uart_port *ourport;
struct platform_device *dev = to_platform_device(_dev);
@@ -1124,7 +1120,7 @@ int s3c24xx_serial_probe(struct device *_dev,
return ret;
}
-int s3c24xx_serial_remove(struct device *_dev)
+static int s3c24xx_serial_remove(struct device *_dev)
{
struct uart_port *port = s3c24xx_dev_to_port(_dev);
@@ -1138,22 +1134,22 @@ int s3c24xx_serial_remove(struct device *_dev)
#ifdef CONFIG_PM
-int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
- if (port && level == SUSPEND_DISABLE)
+ if (port)
uart_suspend_port(&s3c24xx_uart_drv, port);
return 0;
}
-int s3c24xx_serial_resume(struct device *dev, u32 level)
+static int s3c24xx_serial_resume(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- if (port && level == RESUME_ENABLE) {
+ if (port) {
clk_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
clk_disable(ourport->clk);
@@ -1169,8 +1165,8 @@ int s3c24xx_serial_resume(struct device *dev, u32 level)
#define s3c24xx_serial_resume NULL
#endif
-int s3c24xx_serial_init(struct device_driver *drv,
- struct s3c24xx_uart_info *info)
+static int s3c24xx_serial_init(struct device_driver *drv,
+ struct s3c24xx_uart_info *info)
{
dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
return driver_register(drv);
@@ -1239,6 +1235,7 @@ static int s3c2400_serial_probe(struct device *dev)
static struct device_driver s3c2400_serial_drv = {
.name = "s3c2400-uart",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = s3c2400_serial_probe,
.remove = s3c24xx_serial_remove,
@@ -1342,6 +1339,7 @@ static int s3c2410_serial_probe(struct device *dev)
static struct device_driver s3c2410_serial_drv = {
.name = "s3c2410-uart",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = s3c2410_serial_probe,
.remove = s3c24xx_serial_remove,
@@ -1503,6 +1501,7 @@ static int s3c2440_serial_probe(struct device *dev)
static struct device_driver s3c2440_serial_drv = {
.name = "s3c2440-uart",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = s3c2440_serial_probe,
.remove = s3c24xx_serial_remove,
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 98641c3f5ab9..ed618cc7ae96 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -35,7 +35,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
@@ -145,7 +145,7 @@ static void sa1100_timeout(unsigned long data)
/*
* interrupts disabled on entry
*/
-static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sa1100_stop_tx(struct uart_port *port)
{
struct sa1100_port *sport = (struct sa1100_port *)port;
u32 utcr3;
@@ -158,7 +158,7 @@ static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
/*
* interrupts may not be disabled on entry
*/
-static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sa1100_start_tx(struct uart_port *port)
{
struct sa1100_port *sport = (struct sa1100_port *)port;
unsigned long flags;
@@ -264,7 +264,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
sa1100_mctrl_check(sport);
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
- sa1100_stop_tx(&sport->port, 0);
+ sa1100_stop_tx(&sport->port);
return;
}
@@ -284,7 +284,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit))
- sa1100_stop_tx(&sport->port, 0);
+ sa1100_stop_tx(&sport->port);
}
static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
@@ -799,7 +799,7 @@ sa1100_console_setup(struct console *co, char *options)
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver sa1100_reg;
+static struct uart_driver sa1100_reg;
static struct console sa1100_console = {
.name = "ttySA",
.write = sa1100_console_write,
@@ -834,21 +834,21 @@ static struct uart_driver sa1100_reg = {
.cons = SA1100_CONSOLE,
};
-static int sa1100_serial_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_serial_suspend(struct device *_dev, pm_message_t state)
{
struct sa1100_port *sport = dev_get_drvdata(_dev);
- if (sport && level == SUSPEND_DISABLE)
+ if (sport)
uart_suspend_port(&sa1100_reg, &sport->port);
return 0;
}
-static int sa1100_serial_resume(struct device *_dev, u32 level)
+static int sa1100_serial_resume(struct device *_dev)
{
struct sa1100_port *sport = dev_get_drvdata(_dev);
- if (sport && level == RESUME_ENABLE)
+ if (sport)
uart_resume_port(&sa1100_reg, &sport->port);
return 0;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 54699c3a00ab..0745ce782974 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -80,7 +80,7 @@ static void uart_stop(struct tty_struct *tty)
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- port->ops->stop_tx(port, 1);
+ port->ops->stop_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -91,7 +91,7 @@ static void __uart_start(struct tty_struct *tty)
if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
!tty->stopped && !tty->hw_stopped)
- port->ops->start_tx(port, 1);
+ port->ops->start_tx(port);
}
static void uart_start(struct tty_struct *tty)
@@ -147,8 +147,7 @@ static int uart_startup(struct uart_state *state, int init_hw)
* once we have successfully opened the port. Also set
* up the tty->alt_speed kludge
*/
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
if (port->type == PORT_UNKNOWN)
return 0;
@@ -542,7 +541,7 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
port->x_char = ch;
if (ch) {
spin_lock_irqsave(&port->lock, flags);
- port->ops->start_tx(port, 0);
+ port->ops->start_tx(port);
spin_unlock_irqrestore(&port->lock, flags);
}
}
@@ -1146,7 +1145,7 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios
spin_lock_irqsave(&state->port->lock, flags);
if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
tty->hw_stopped = 1;
- state->port->ops->stop_tx(state->port, 0);
+ state->port->ops->stop_tx(state->port);
}
spin_unlock_irqrestore(&state->port->lock, flags);
}
@@ -1869,7 +1868,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
struct uart_ops *ops = port->ops;
spin_lock_irq(&port->lock);
- ops->stop_tx(port, 0);
+ ops->stop_tx(port);
ops->set_mctrl(port, 0);
ops->stop_rx(port);
spin_unlock_irq(&port->lock);
@@ -1935,7 +1934,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
uart_change_speed(state, NULL);
spin_lock_irq(&port->lock);
ops->set_mctrl(port, port->mctrl);
- ops->start_tx(port, 0);
+ ops->start_tx(port);
spin_unlock_irq(&port->lock);
}
@@ -1947,21 +1946,31 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
static inline void
uart_report_port(struct uart_driver *drv, struct uart_port *port)
{
- printk("%s%d", drv->dev_name, port->line);
- printk(" at ");
+ char address[64];
+
switch (port->iotype) {
case UPIO_PORT:
- printk("I/O 0x%x", port->iobase);
+ snprintf(address, sizeof(address),
+ "I/O 0x%x", port->iobase);
break;
case UPIO_HUB6:
- printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+ snprintf(address, sizeof(address),
+ "I/O 0x%x offset 0x%x", port->iobase, port->hub6);
break;
case UPIO_MEM:
case UPIO_MEM32:
- printk("MMIO 0x%lx", port->mapbase);
+ snprintf(address, sizeof(address),
+ "MMIO 0x%lx", port->mapbase);
+ break;
+ default:
+ strlcpy(address, "*unknown*", sizeof(address));
break;
}
- printk(" (irq = %d) is a %s\n", port->irq, uart_type(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));
}
static void
@@ -2289,143 +2298,11 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
}
EXPORT_SYMBOL(uart_match_port);
-/*
- * Try to find an unused uart_state slot for a port.
- */
-static struct uart_state *
-uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
-{
- int i;
-
- /*
- * First, find a port entry which matches. Note: if we do
- * find a matching entry, and it has a non-zero use count,
- * then we can't register the port.
- */
- for (i = 0; i < drv->nr; i++)
- if (uart_match_port(drv->state[i].port, port))
- return &drv->state[i];
-
- /*
- * We didn't find a matching entry, so look for the first
- * free entry. We look for one which hasn't been previously
- * used (indicated by zero iobase).
- */
- for (i = 0; i < drv->nr; i++)
- if (drv->state[i].port->type == PORT_UNKNOWN &&
- drv->state[i].port->iobase == 0 &&
- drv->state[i].count == 0)
- return &drv->state[i];
-
- /*
- * That also failed. Last resort is to find any currently
- * entry which doesn't have a real port associated with it.
- */
- for (i = 0; i < drv->nr; i++)
- if (drv->state[i].port->type == PORT_UNKNOWN &&
- drv->state[i].count == 0)
- return &drv->state[i];
-
- return NULL;
-}
-
-/**
- * uart_register_port: register uart settings with a port
- * @drv: pointer to the uart low level driver structure for this port
- * @port: uart port structure describing the port
- *
- * Register UART settings with the specified low level driver. Detect
- * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
- * IRQ if UPF_AUTO_IRQ is set.
- *
- * We try to pick the same port for the same IO base address, so that
- * when a modem is plugged in, unplugged and plugged back in, it gets
- * allocated the same port.
- *
- * Returns negative error, or positive line number.
- */
-int uart_register_port(struct uart_driver *drv, struct uart_port *port)
-{
- struct uart_state *state;
- int ret;
-
- down(&port_sem);
-
- state = uart_find_match_or_unused(drv, port);
-
- if (state) {
- /*
- * Ok, we've found a line that we can use.
- *
- * If we find a port that matches this one, and it appears
- * to be in-use (even if it doesn't have a type) we shouldn't
- * alter it underneath itself - the port may be open and
- * trying to do useful work.
- */
- if (uart_users(state) != 0) {
- ret = -EBUSY;
- goto out;
- }
-
- /*
- * If the port is already initialised, don't touch it.
- */
- if (state->port->type == PORT_UNKNOWN) {
- state->port->iobase = port->iobase;
- state->port->membase = port->membase;
- state->port->irq = port->irq;
- state->port->uartclk = port->uartclk;
- state->port->fifosize = port->fifosize;
- state->port->regshift = port->regshift;
- state->port->iotype = port->iotype;
- state->port->flags = port->flags;
- state->port->line = state - drv->state;
- state->port->mapbase = port->mapbase;
-
- uart_configure_port(drv, state, state->port);
- }
-
- ret = state->port->line;
- } else
- ret = -ENOSPC;
- out:
- up(&port_sem);
- return ret;
-}
-
-/**
- * uart_unregister_port - de-allocate a port
- * @drv: pointer to the uart low level driver structure for this port
- * @line: line index previously returned from uart_register_port()
- *
- * Hang up the specified line associated with the low level driver,
- * and mark the port as unused.
- */
-void uart_unregister_port(struct uart_driver *drv, int line)
-{
- struct uart_state *state;
-
- if (line < 0 || line >= drv->nr) {
- printk(KERN_ERR "Attempt to unregister ");
- printk("%s%d", drv->dev_name, line);
- printk("\n");
- return;
- }
-
- state = drv->state + line;
-
- down(&port_sem);
- uart_unconfigure_port(drv, state);
- up(&port_sem);
-}
-
EXPORT_SYMBOL(uart_write_wakeup);
EXPORT_SYMBOL(uart_register_driver);
EXPORT_SYMBOL(uart_unregister_driver);
EXPORT_SYMBOL(uart_suspend_port);
EXPORT_SYMBOL(uart_resume_port);
-EXPORT_SYMBOL(uart_register_port);
-EXPORT_SYMBOL(uart_unregister_port);
EXPORT_SYMBOL(uart_add_one_port);
EXPORT_SYMBOL(uart_remove_one_port);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 1ae0b381c162..2c7d3ef76e8e 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 56f269b6bfb1..d01dbe5da3b9 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -112,13 +112,12 @@ struct uart_port_lh7a40x {
unsigned int statusPrev; /* Most recently read modem status */
};
-static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop)
+static void lh7a40xuart_stop_tx (struct uart_port* port)
{
BIT_CLR (port, UART_R_INTEN, TxInt);
}
-static void lh7a40xuart_start_tx (struct uart_port* port,
- unsigned int tty_start)
+static void lh7a40xuart_start_tx (struct uart_port* port)
{
BIT_SET (port, UART_R_INTEN, TxInt);
@@ -208,7 +207,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
return;
}
if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
- lh7a40xuart_stop_tx (port, 0);
+ lh7a40xuart_stop_tx (port);
return;
}
@@ -230,7 +229,7 @@ static void lh7a40xuart_tx_chars (struct uart_port* port)
uart_write_wakeup (port);
if (uart_circ_empty (xmit))
- lh7a40xuart_stop_tx (port, 0);
+ lh7a40xuart_stop_tx (port);
}
static void lh7a40xuart_modem_status (struct uart_port* port)
@@ -633,7 +632,7 @@ static int __init lh7a40xuart_console_setup (struct console* co, char* options)
return uart_set_options (port, co, baud, parity, bits, flow);
}
-extern struct uart_driver lh7a40x_reg;
+static struct uart_driver lh7a40x_reg;
static struct console lh7a40x_console = {
.name = "ttyAM",
.write = lh7a40xuart_console_write,
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index d085030df70b..f10c86d60b64 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -31,6 +31,8 @@
* 1.01 Set fifosize to make tx_empry called properly.
* Use standard uart_get_divisor.
* 1.02 Cleanup. (import 8250.c changes)
+ * 1.03 Fix low-latency mode. (import 8250.c changes)
+ * 1.04 Remove usage of deprecated functions, cleanup.
*/
#include <linux/config.h>
@@ -54,7 +56,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-static char *serial_version = "1.02";
+static char *serial_version = "1.04";
static char *serial_name = "TX39/49 Serial driver";
#define PASS_LIMIT 256
@@ -86,9 +88,9 @@ static char *serial_name = "TX39/49 Serial driver";
*/
#ifdef ENABLE_SERIAL_TXX9_PCI
#define NR_PCI_BOARDS 4
-#define UART_NR (2 + NR_PCI_BOARDS)
+#define UART_NR (4 + NR_PCI_BOARDS)
#else
-#define UART_NR 2
+#define UART_NR 4
#endif
struct uart_txx9_port {
@@ -253,7 +255,7 @@ sio_quot_set(struct uart_txx9_port *up, int quot)
sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
}
-static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void serial_txx9_stop_tx(struct uart_port *port)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
unsigned long flags;
@@ -263,7 +265,7 @@ static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop)
spin_unlock_irqrestore(&up->port.lock, flags);
}
-static void serial_txx9_start_tx(struct uart_port *port, unsigned int tty_start)
+static void serial_txx9_start_tx(struct uart_port *port)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
unsigned long flags;
@@ -304,8 +306,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
/* The following is not allowed by the tty layer and
unsafe. It should be fixed ASAP */
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if(tty->low_latency)
+ if (tty->low_latency) {
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ }
/* If this failed then we will throw away the
bytes but must do so to clear interrupts */
}
@@ -356,7 +361,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
ignore_char:
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
*status = disr;
}
@@ -372,7 +379,7 @@ static inline void transmit_chars(struct uart_txx9_port *up)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial_txx9_stop_tx(&up->port, 0);
+ serial_txx9_stop_tx(&up->port);
return;
}
@@ -389,7 +396,7 @@ static inline void transmit_chars(struct uart_txx9_port *up)
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- serial_txx9_stop_tx(&up->port, 0);
+ serial_txx9_stop_tx(&up->port);
}
static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -667,17 +674,8 @@ serial_txx9_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
- if (state) {
- /* sleep */
-
- if (up->pm)
- up->pm(port, state, oldstate);
- } else {
- /* wake */
-
- if (up->pm)
- up->pm(port, state, oldstate);
- }
+ if (up->pm)
+ up->pm(port, state, oldstate);
}
static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -979,14 +977,6 @@ static int __init serial_txx9_console_init(void)
}
console_initcall(serial_txx9_console_init);
-static int __init serial_txx9_late_console_init(void)
-{
- if (!(serial_txx9_console.flags & CON_ENABLED))
- register_console(&serial_txx9_console);
- return 0;
-}
-late_initcall(serial_txx9_late_console_init);
-
#define SERIAL_TXX9_CONSOLE &serial_txx9_console
#else
#define SERIAL_TXX9_CONSOLE NULL
@@ -1039,6 +1029,73 @@ static void serial_txx9_resume_port(int line)
uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
}
+static DECLARE_MUTEX(serial_txx9_sem);
+
+/**
+ * serial_txx9_register_port - register a serial port
+ * @port: serial port template
+ *
+ * Configure the serial port specified by the request.
+ *
+ * The port is then probed and if necessary the IRQ is autodetected
+ * If this fails an error is returned.
+ *
+ * On success the port is ready to use and the line number is returned.
+ */
+static int __devinit serial_txx9_register_port(struct uart_port *port)
+{
+ int i;
+ struct uart_txx9_port *uart;
+ int ret = -ENOSPC;
+
+ down(&serial_txx9_sem);
+ for (i = 0; i < UART_NR; i++) {
+ uart = &serial_txx9_ports[i];
+ if (uart->port.type == PORT_UNKNOWN)
+ break;
+ }
+ if (i < UART_NR) {
+ uart_remove_one_port(&serial_txx9_reg, &uart->port);
+ uart->port.iobase = port->iobase;
+ uart->port.membase = port->membase;
+ uart->port.irq = port->irq;
+ uart->port.uartclk = port->uartclk;
+ uart->port.iotype = port->iotype;
+ uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
+ uart->port.mapbase = port->mapbase;
+ if (port->dev)
+ uart->port.dev = port->dev;
+ ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
+ if (ret == 0)
+ ret = uart->port.line;
+ }
+ up(&serial_txx9_sem);
+ return ret;
+}
+
+/**
+ * serial_txx9_unregister_port - remove a txx9 serial port at runtime
+ * @line: serial line number
+ *
+ * Remove one serial port. This may not be called from interrupt
+ * context. We hand the port back to the our control.
+ */
+static void __devexit serial_txx9_unregister_port(int line)
+{
+ struct uart_txx9_port *uart = &serial_txx9_ports[line];
+
+ down(&serial_txx9_sem);
+ uart_remove_one_port(&serial_txx9_reg, &uart->port);
+ uart->port.flags = 0;
+ uart->port.type = PORT_UNKNOWN;
+ uart->port.iobase = 0;
+ uart->port.mapbase = 0;
+ uart->port.membase = 0;
+ uart->port.dev = NULL;
+ uart_add_one_port(&serial_txx9_reg, &uart->port);
+ up(&serial_txx9_sem);
+}
+
/*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
@@ -1056,13 +1113,13 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
memset(&port, 0, sizeof(port));
port.ops = &serial_txx9_pops;
- port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called */
port.flags |= UPF_TXX9_HAVE_CTS_LINE;
port.uartclk = 66670000;
port.irq = dev->irq;
port.iotype = UPIO_PORT;
port.iobase = pci_resource_start(dev, 1);
- line = uart_register_port(&serial_txx9_reg, &port);
+ port.dev = &dev->dev;
+ line = serial_txx9_register_port(&port);
if (line < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
}
@@ -1078,7 +1135,7 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
if (line) {
- uart_unregister_port(&serial_txx9_reg, line);
+ serial_txx9_unregister_port(line);
pci_disable_device(dev);
}
}
@@ -1089,6 +1146,8 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
if (line)
serial_txx9_suspend_port(line);
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@@ -1096,8 +1155,13 @@ static int pciserial_txx9_resume_one(struct pci_dev *dev)
{
int line = (int)(long)pci_get_drvdata(dev);
- if (line)
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ if (line) {
+ pci_enable_device(dev);
serial_txx9_resume_port(line);
+ }
return 0;
}
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index ad5b776d779b..430754ebac8a 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -79,8 +79,8 @@ static struct sci_port *serial_console_port = 0;
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
/* Function prototypes */
-static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop);
-static void sci_start_tx(struct uart_port *port, unsigned int tty_start);
+static void sci_stop_tx(struct uart_port *port);
+static void sci_start_tx(struct uart_port *port);
static void sci_start_rx(struct uart_port *port, unsigned int tty_start);
static void sci_stop_rx(struct uart_port *port);
static int sci_request_irq(struct sci_port *port);
@@ -455,7 +455,7 @@ static void sci_transmit_chars(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
- sci_stop_tx(port, 0);
+ sci_stop_tx(port);
} else {
local_irq_save(flags);
ctrl = sci_in(port, SCSCR);
@@ -900,7 +900,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
}
-static void sci_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sci_start_tx(struct uart_port *port)
{
struct sci_port *s = &sci_ports[port->line];
@@ -909,7 +909,7 @@ static void sci_start_tx(struct uart_port *port, unsigned int tty_start)
enable_irq(s->irqs[SCIx_TXI_IRQ]);
}
-static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sci_stop_tx(struct uart_port *port)
{
unsigned long flags;
unsigned short ctrl;
@@ -967,7 +967,7 @@ static int sci_startup(struct uart_port *port)
#endif
sci_request_irq(s);
- sci_start_tx(port, 1);
+ sci_start_tx(port);
sci_start_rx(port, 1);
return 0;
@@ -978,7 +978,7 @@ static void sci_shutdown(struct uart_port *port)
struct sci_port *s = &sci_ports[port->line];
sci_stop_rx(port);
- sci_stop_tx(port, 1);
+ sci_stop_tx(port);
sci_free_irq(s);
#if defined(__H8300S__)
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 840815fde49b..313f9df24a2d 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -259,10 +259,9 @@ static unsigned int snp_tx_empty(struct uart_port *port)
/**
* snp_stop_tx - stop the transmitter - no-op for us
* @port: Port to operat eon - we ignore - no-op function
- * @tty_stop: Set to 1 if called via uart_stop
*
*/
-static void snp_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void snp_stop_tx(struct uart_port *port)
{
}
@@ -325,10 +324,9 @@ static void snp_stop_rx(struct uart_port *port)
/**
* snp_start_tx - Start transmitter
* @port: Port to operate on
- * @tty_stop: Set to 1 if called via uart_start
*
*/
-static void snp_start_tx(struct uart_port *port, unsigned int tty_stop)
+static void snp_start_tx(struct uart_port *port)
{
if (sal_console_port.sc_ops->sal_wakeup_transmit)
sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port,
@@ -615,7 +613,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw)
uart_write_wakeup(&port->sc_port);
if (uart_circ_empty(xmit))
- snp_stop_tx(&port->sc_port, 0); /* no-op for us */
+ snp_stop_tx(&port->sc_port); /* no-op for us */
}
/**
@@ -1093,6 +1091,7 @@ int __init sn_serial_console_early_setup(void)
return -1;
sal_console_port.sc_ops = &poll_ops;
+ spin_lock_init(&sal_console_port.sc_port.lock);
early_sn_setup(); /* Find SAL entry points */
register_console(&sal_console_early);
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 8d198880756a..ba9381fd3f2d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -245,7 +245,7 @@ receive_chars(struct uart_sunsab_port *up,
return tty;
}
-static void sunsab_stop_tx(struct uart_port *, unsigned int);
+static void sunsab_stop_tx(struct uart_port *);
static void sunsab_tx_idle(struct uart_sunsab_port *);
static void transmit_chars(struct uart_sunsab_port *up,
@@ -274,7 +274,6 @@ static void transmit_chars(struct uart_sunsab_port *up,
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
up->interrupt_mask1 |= SAB82532_IMR1_XPR;
writeb(up->interrupt_mask1, &up->regs->w.imr1);
- uart_write_wakeup(&up->port);
return;
}
@@ -301,7 +300,7 @@ static void transmit_chars(struct uart_sunsab_port *up,
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- sunsab_stop_tx(&up->port, 0);
+ sunsab_stop_tx(&up->port);
}
static void check_status(struct uart_sunsab_port *up,
@@ -448,7 +447,7 @@ static unsigned int sunsab_get_mctrl(struct uart_port *port)
}
/* port->lock held by caller. */
-static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sunsab_stop_tx(struct uart_port *port)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
@@ -476,7 +475,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *up)
}
/* port->lock held by caller. */
-static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunsab_start_tx(struct uart_port *port)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
struct circ_buf *xmit = &up->port.info->xmit;
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index d57a3553aea3..656c0e8d160e 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -255,21 +255,30 @@ static void disable_rsa(struct uart_sunsu_port *up)
}
#endif /* CONFIG_SERIAL_8250_RSA */
-static void sunsu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static inline void __stop_tx(struct uart_sunsu_port *p)
+{
+ if (p->ier & UART_IER_THRI) {
+ p->ier &= ~UART_IER_THRI;
+ serial_out(p, UART_IER, p->ier);
+ }
+}
+
+static void sunsu_stop_tx(struct uart_port *port)
{
struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
- if (up->port.type == PORT_16C950 && tty_stop) {
+ __stop_tx(up);
+
+ /*
+ * We really want to stop the transmitter from sending.
+ */
+ if (up->port.type == PORT_16C950) {
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
}
-static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunsu_start_tx(struct uart_port *port)
{
struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
@@ -277,10 +286,11 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
up->ier |= UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
+
/*
- * We only do this from uart_start
+ * Re-enable the transmitter if we disabled it.
*/
- if (tty_start && up->port.type == PORT_16C950) {
+ if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
up->acr &= ~UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
@@ -413,8 +423,12 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
up->port.x_char = 0;
return;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- sunsu_stop_tx(&up->port, 0);
+ if (uart_tx_stopped(&up->port)) {
+ sunsu_stop_tx(&up->port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
+ __stop_tx(up);
return;
}
@@ -431,7 +445,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
uart_write_wakeup(&up->port);
if (uart_circ_empty(xmit))
- sunsu_stop_tx(&up->port, 0);
+ __stop_tx(up);
}
static _INLINE_ void check_modem_status(struct uart_sunsu_port *up)
@@ -504,11 +518,7 @@ static void sunsu_change_mouse_baud(struct uart_sunsu_port *up)
quot = up->port.uartclk / (16 * new_baud);
- spin_unlock(&up->port.lock);
-
sunsu_change_speed(&up->port, up->cflag, 0, quot);
-
- spin_lock(&up->port.lock);
}
static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *regs, int is_break)
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index bff42a7b89d0..7653d6cf05af 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -517,10 +517,9 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if (up->port.info == NULL)
goto ack_tx_int;
xmit = &up->port.info->xmit;
- if (uart_circ_empty(xmit)) {
- uart_write_wakeup(&up->port);
+ if (uart_circ_empty(xmit))
goto ack_tx_int;
- }
+
if (uart_tx_stopped(&up->port))
goto ack_tx_int;
@@ -684,7 +683,7 @@ static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void sunzilog_stop_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
@@ -692,7 +691,7 @@ static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
/* The port lock is held and interrupts are disabled. */
-static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunzilog_start_tx(struct uart_port *port)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
index 186f1300cead..47b504ff38b2 100644
--- a/drivers/serial/uart00.c
+++ b/drivers/serial/uart00.c
@@ -87,7 +87,7 @@
#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
-static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void uart00_stop_tx(struct uart_port *port)
{
UART_PUT_IEC(port, UART_IEC_TIE_MSK);
}
@@ -199,7 +199,7 @@ static void uart00_tx_chars(struct uart_port *port)
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- uart00_stop_tx(port, 0);
+ uart00_stop_tx(port);
return;
}
@@ -218,10 +218,10 @@ static void uart00_tx_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- uart00_stop_tx(port, 0);
+ uart00_stop_tx(port);
}
-static void uart00_start_tx(struct uart_port *port, unsigned int tty_start)
+static void uart00_start_tx(struct uart_port *port)
{
UART_PUT_IES(port, UART_IES_TIE_MSK);
uart00_tx_chars(port);
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index bb482780a41d..9378895a8d56 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -240,7 +240,7 @@ console_initcall(v850e_uart_console_init);
/* TX/RX interrupt handlers. */
-static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
+static void v850e_uart_stop_tx (struct uart_port *port);
void v850e_uart_tx (struct uart_port *port)
{
@@ -339,14 +339,14 @@ static unsigned v850e_uart_get_mctrl (struct uart_port *port)
return mctrl;
}
-static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start)
+static void v850e_uart_start_tx (struct uart_port *port)
{
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
v850e_uart_tx (port);
v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));
}
-static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
+static void v850e_uart_stop_tx (struct uart_port *port)
{
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
}
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 1f985327b0d4..01696b3e3f61 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -26,7 +26,7 @@
#endif
#include <linux/console.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/ioport.h>
#include <linux/init.h>
@@ -284,7 +284,7 @@ static unsigned int siu_get_mctrl(struct uart_port *port)
return mctrl;
}
-static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static void siu_stop_tx(struct uart_port *port)
{
unsigned long flags;
uint8_t ier;
@@ -298,7 +298,7 @@ static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
spin_unlock_irqrestore(&port->lock, flags);
}
-static void siu_start_tx(struct uart_port *port, unsigned int tty_start)
+static void siu_start_tx(struct uart_port *port)
{
unsigned long flags;
uint8_t ier;
@@ -458,7 +458,7 @@ static inline void transmit_chars(struct uart_port *port)
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- siu_stop_tx(port, 0);
+ siu_stop_tx(port);
return;
}
@@ -474,7 +474,7 @@ static inline void transmit_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- siu_stop_tx(port, 0);
+ siu_stop_tx(port);
}
static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -976,14 +976,11 @@ static int siu_remove(struct device *dev)
return 0;
}
-static int siu_suspend(struct device *dev, pm_message_t state, u32 level)
+static int siu_suspend(struct device *dev, pm_message_t state)
{
struct uart_port *port;
int i;
- if (level != SUSPEND_DISABLE)
- return 0;
-
for (i = 0; i < siu_uart_driver.nr; i++) {
port = &siu_uart_ports[i];
if ((port->type == PORT_VR41XX_SIU ||
@@ -995,14 +992,11 @@ static int siu_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
-static int siu_resume(struct device *dev, u32 level)
+static int siu_resume(struct device *dev)
{
struct uart_port *port;
int i;
- if (level != RESUME_ENABLE)
- return 0;
-
for (i = 0; i < siu_uart_driver.nr; i++) {
port = &siu_uart_ports[i];
if ((port->type == PORT_VR41XX_SIU ||
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index f056276b08a1..28757cb9d246 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -16,6 +16,8 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/superhyway.h>
+#include <linux/string.h>
+#include <linux/slab.h>
static int superhyway_devices;
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index a89ef4df80c3..a0e5af638e0e 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -8,33 +8,31 @@
* for more details.
*
* Copyright (c) Harald Koerfgen, 1998
- * Copyright (c) 2001, 2003 Maciej W. Rozycki
+ * Copyright (c) 2001, 2003, 2005 Maciej W. Rozycki
*/
-#include <linux/string.h>
#include <linux/init.h>
-#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
#include <asm/addrspace.h>
+#include <asm/bug.h>
#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/paccess.h>
+
#include <asm/dec/machtype.h>
#include <asm/dec/prom.h>
#include <asm/dec/tcinfo.h>
#include <asm/dec/tcmodule.h>
#include <asm/dec/interrupts.h>
-#include <asm/paccess.h>
-#include <asm/ptrace.h>
-
-#define TC_DEBUG
MODULE_LICENSE("GPL");
slot_info tc_bus[MAX_SLOT];
static int num_tcslots;
static tcinfo *info;
-unsigned long system_base;
-
/*
* Interface to the world. Read comment in include/asm-mips/tc.h.
*/
@@ -97,13 +95,16 @@ unsigned long get_tc_speed(void)
static void __init tc_probe(unsigned long startaddr, unsigned long size,
int slots)
{
+ unsigned long slotaddr;
int i, slot, err;
long offset;
- unsigned char pattern[4];
- unsigned char *module;
+ u8 pattern[4];
+ volatile u8 *module;
for (slot = 0; slot < slots; slot++) {
- module = (char *)(startaddr + slot * size);
+ slotaddr = startaddr + slot * size;
+ module = ioremap_nocache(slotaddr, size);
+ BUG_ON(!module);
offset = OLDCARD;
@@ -112,8 +113,10 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size,
err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1);
err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2);
err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3);
- if (err)
+ if (err) {
+ iounmap(module);
continue;
+ }
if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
pattern[2] != 0xaa || pattern[3] != 0xff) {
@@ -124,16 +127,20 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size,
err |= get_dbe(pattern[1], module + TC_PATTERN1);
err |= get_dbe(pattern[2], module + TC_PATTERN2);
err |= get_dbe(pattern[3], module + TC_PATTERN3);
- if (err)
+ if (err) {
+ iounmap(module);
continue;
+ }
}
if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
- pattern[2] != 0xaa || pattern[3] != 0xff)
+ pattern[2] != 0xaa || pattern[3] != 0xff) {
+ iounmap(module);
continue;
+ }
- tc_bus[slot].base_addr = (unsigned long)module;
- for(i = 0; i < 8; i++) {
+ tc_bus[slot].base_addr = slotaddr;
+ for (i = 0; i < 8; i++) {
tc_bus[slot].firmware[i] =
module[TC_FIRM_VER + offset + 4 * i];
tc_bus[slot].vendor[i] =
@@ -171,13 +178,15 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size,
tc_bus[slot].interrupt = -1;
break;
}
+
+ iounmap(module);
}
}
/*
* the main entry
*/
-void __init tc_init(void)
+static int __init tc_init(void)
{
int tc_clock;
int i;
@@ -185,7 +194,7 @@ void __init tc_init(void)
unsigned long slot_size;
if (!TURBOCHANNEL)
- return;
+ return 0;
for (i = 0; i < MAX_SLOT; i++) {
tc_bus[i].base_addr = 0;
@@ -196,8 +205,8 @@ void __init tc_init(void)
tc_bus[i].flags = FREE;
}
- info = (tcinfo *) rex_gettcinfo();
- slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
+ info = rex_gettcinfo();
+ slot0addr = CPHYSADDR((long)rex_slot_address(0));
switch (mips_machtype) {
case MACH_DS5000_200:
@@ -216,37 +225,24 @@ void __init tc_init(void)
tc_clock = 10000 / info->clk_period;
- if (TURBOCHANNEL && info->slot_size && slot0addr) {
- printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
- tc_clock / 10, tc_clock % 10);
- printk("(with%s parity)\n", info->parity ? "" : "out");
+ if (info->slot_size && slot0addr) {
+ pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n",
+ info->revision, tc_clock / 10, tc_clock % 10,
+ info->parity ? "" : "out");
slot_size = info->slot_size << 20;
tc_probe(slot0addr, slot_size, num_tcslots);
- /*
- * All TURBOchannel DECstations have the onboard devices
- * where the (num_tcslots + 0 or 1 on DS5k/xx) Option Module
- * would be.
- */
- if(mips_machtype == MACH_DS5000_XX)
- i = 1;
- else
- i = 0;
-
- system_base = slot0addr + slot_size * (num_tcslots + i);
-
-#ifdef TC_DEBUG
- for (i = 0; i < num_tcslots; i++)
- if (tc_bus[i].base_addr) {
- printk(" slot %d: ", i);
- printk("%s %s %s\n", tc_bus[i].vendor,
- tc_bus[i].name, tc_bus[i].firmware);
- }
-#endif
- ioport_resource.end = KSEG2 - 1;
+ for (i = 0; i < num_tcslots; i++) {
+ if (!tc_bus[i].base_addr)
+ continue;
+ pr_info(" slot %d: %s %s %s\n", i, tc_bus[i].vendor,
+ tc_bus[i].name, tc_bus[i].firmware);
+ }
}
+
+ return 0;
}
subsys_initcall(tc_init);
@@ -257,4 +253,3 @@ EXPORT_SYMBOL(release_tc_card);
EXPORT_SYMBOL(get_tc_base_addr);
EXPORT_SYMBOL(get_tc_irq_nr);
EXPORT_SYMBOL(get_tc_speed);
-EXPORT_SYMBOL(system_base);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 4382ee60b6a8..c52af73a251b 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -65,14 +65,14 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
-#include <asm/dec/serial.h>
-#ifdef CONFIG_MACH_DECSTATION
#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/machtype.h>
+#include <asm/dec/serial.h>
+#include <asm/dec/system.h>
#include <asm/dec/tc.h>
-#include <asm/dec/ioasic_addrs.h>
-#endif
+
#ifdef CONFIG_KGDB
#include <asm/kgdb.h>
#endif
@@ -192,18 +192,6 @@ static void probe_sccs(void);
static void change_speed(struct dec_serial *info);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static DECLARE_MUTEX(tmp_buf_sem);
-
static inline int serial_paranoia_check(struct dec_serial *info,
char *name, const char *routine)
{
@@ -1628,30 +1616,22 @@ static void __init probe_sccs(void)
return;
}
- /*
- * When serial console is activated, tc_init has not been called yet
- * and system_base is undefined. Unfortunately we have to hardcode
- * system_base for this case :-(. HK
- */
switch(mips_machtype) {
#ifdef CONFIG_MACH_DECSTATION
case MACH_DS5000_2X0:
case MACH_DS5900:
- system_base = KSEG1ADDR(0x1f800000);
n_chips = 2;
zs_parms = &ds_parms;
zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
break;
case MACH_DS5000_1XX:
- system_base = KSEG1ADDR(0x1c000000);
n_chips = 2;
zs_parms = &ds_parms;
zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
break;
case MACH_DS5000_XX:
- system_base = KSEG1ADDR(0x1c000000);
n_chips = 1;
zs_parms = &ds_parms;
zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
@@ -1673,17 +1653,17 @@ static void __init probe_sccs(void)
* The sccs reside on the high byte of the 16 bit IOBUS
*/
zs_channels[n_channels].control =
- (volatile unsigned char *)system_base +
+ (volatile void *)CKSEG1ADDR(dec_kn_slot_base +
(0 == chip ? zs_parms->scc0 : zs_parms->scc1) +
(0 == channel ? zs_parms->channel_a_offset :
- zs_parms->channel_b_offset);
+ zs_parms->channel_b_offset));
zs_channels[n_channels].data =
zs_channels[n_channels].control + 4;
#ifndef CONFIG_SERIAL_DEC_CONSOLE
/*
* We're called early and memory managment isn't up, yet.
- * Thus check_region would fail.
+ * Thus request_region would fail.
*/
if (!request_region((unsigned long)
zs_channels[n_channels].control,
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index f2c9fa423d40..f6704688ee8c 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -774,10 +774,7 @@ static int ixj_wink(IXJ *j)
j->pots_winkstart = jiffies;
SLIC_SetState(PLD_SLIC_STATE_OC, j);
- while (time_before(jiffies, j->pots_winkstart + j->winktime)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(jiffies_to_msecs(j->winktime));
SLIC_SetState(slicnow, j);
return 0;
@@ -1912,7 +1909,6 @@ static int ixj_pcmcia_cable_check(IXJ *j)
static int ixj_hookstate(IXJ *j)
{
- unsigned long det;
int fOffHook = 0;
switch (j->cardtype) {
@@ -1943,11 +1939,7 @@ static int ixj_hookstate(IXJ *j)
j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
if (j->flags.ringing || j->flags.cringing) {
if (!in_interrupt()) {
- det = jiffies + (hertz / 50);
- while (time_before(jiffies, det)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(20);
}
SLIC_GetState(j);
if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
@@ -2062,7 +2054,7 @@ static void ixj_ring_start(IXJ *j)
static int ixj_ring(IXJ *j)
{
char cntr;
- unsigned long jif, det;
+ unsigned long jif;
j->flags.ringing = 1;
if (ixj_hookstate(j) & 1) {
@@ -2070,7 +2062,6 @@ static int ixj_ring(IXJ *j)
j->flags.ringing = 0;
return 1;
}
- det = 0;
for (cntr = 0; cntr < j->maxrings; cntr++) {
jif = jiffies + (1 * hertz);
ixj_ring_on(j);
@@ -2080,8 +2071,7 @@ static int ixj_ring(IXJ *j)
j->flags.ringing = 0;
return 1;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (signal_pending(current))
break;
}
@@ -2089,20 +2079,13 @@ static int ixj_ring(IXJ *j)
ixj_ring_off(j);
while (time_before(jiffies, jif)) {
if (ixj_hookstate(j) & 1) {
- det = jiffies + (hertz / 100);
- while (time_before(jiffies, det)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- }
+ msleep(10);
if (ixj_hookstate(j) & 1) {
j->flags.ringing = 0;
return 1;
}
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (signal_pending(current))
break;
}
@@ -2168,10 +2151,8 @@ static int ixj_release(struct inode *inode, struct file *file_p)
* Set up locks to ensure that only one process is talking to the DSP at a time.
* This is necessary to keep the DSP from locking up.
*/
- while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if (ixjdebug & 0x0002)
printk(KERN_INFO "Closing board %d\n", NUM(inode));
@@ -3301,14 +3282,10 @@ static void ixj_write_cidcw(IXJ *j)
ixj_play_tone(j, 23);
clear_bit(j->board, &j->busyflags);
- while(j->tone_state) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(j->tone_state)
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if(ixjdebug & 0x0200) {
printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies);
}
@@ -3328,14 +3305,10 @@ static void ixj_write_cidcw(IXJ *j)
ixj_play_tone(j, 24);
clear_bit(j->board, &j->busyflags);
- while(j->tone_state) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(j->tone_state)
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if(ixjdebug & 0x0200) {
printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies);
}
@@ -3343,14 +3316,10 @@ static void ixj_write_cidcw(IXJ *j)
j->cidcw_wait = jiffies + ((50 * hertz) / 100);
clear_bit(j->board, &j->busyflags);
- while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
- while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait))
+ schedule_timeout_interruptible(1);
+ while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
j->cidcw_wait = 0;
if(!j->flags.cidcw_ack) {
if(ixjdebug & 0x0200) {
@@ -6125,10 +6094,8 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
* Set up locks to ensure that only one process is talking to the DSP at a time.
* This is necessary to keep the DSP from locking up.
*/
- while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+ schedule_timeout_interruptible(1);
if (ixjdebug & 0x0040)
printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
if (minor >= IXJMAX) {
@@ -6694,8 +6661,6 @@ static struct file_operations ixj_fops =
static int ixj_linetest(IXJ *j)
{
- unsigned long jifwait;
-
j->flags.pstncheck = 1; /* Testing */
j->flags.pstn_present = 0; /* Assume the line is not there */
@@ -6726,11 +6691,7 @@ static int ixj_linetest(IXJ *j)
outb_p(j->pld_scrw.byte, j->XILINXbase);
daa_set_mode(j, SOP_PU_CONVERSATION);
- jifwait = jiffies + hertz;
- while (time_before(jiffies, jifwait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(1000);
daa_int_read(j);
daa_set_mode(j, SOP_PU_RESET);
if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6750,11 +6711,7 @@ static int ixj_linetest(IXJ *j)
j->pld_slicw.bits.rly3 = 0;
outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
daa_set_mode(j, SOP_PU_CONVERSATION);
- jifwait = jiffies + hertz;
- while (time_before(jiffies, jifwait)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(1000);
daa_int_read(j);
daa_set_mode(j, SOP_PU_RESET);
if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6783,7 +6740,6 @@ static int ixj_linetest(IXJ *j)
static int ixj_selfprobe(IXJ *j)
{
unsigned short cmd;
- unsigned long jif;
int cnt;
BYTES bytes;
@@ -6933,29 +6889,13 @@ static int ixj_selfprobe(IXJ *j)
} else {
if (j->cardtype == QTI_LINEJACK) {
LED_SetState(0x1, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x2, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x4, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x8, j);
- jif = jiffies + (hertz / 10);
- while (time_before(jiffies, jif)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ msleep(100);
LED_SetState(0x0, j);
daa_get_version(j);
if (ixjdebug & 0x0002)
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index df014c2a7c54..a50c2bc506f2 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_MON) += mon/
+obj-$(CONFIG_PCI) += host/
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_ISP116X_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
@@ -17,7 +18,6 @@ obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_AUDIO) += class/
-obj-$(CONFIG_USB_BLUETOOTH_TTY) += class/
obj-$(CONFIG_USB_MIDI) += class/
obj-$(CONFIG_USB_PRINTER) += class/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 8e184e2641cb..79861ee12a29 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE,
cxacru_blocking_completion, &instance->rcv_done, 1);
- instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_fill_int_urb(instance->snd_urb,
usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
instance->snd_buf, PAGE_SIZE,
cxacru_blocking_completion, &instance->snd_done, 4);
- instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;
init_MUTEX(&instance->cm_serialize);
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index bb1db1959854..c466739428b2 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -960,7 +960,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
intf->altsetting->desc.bInterfaceNumber);
/* instance init */
- instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
+ instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
if (!instance) {
dev_dbg(dev, "%s: no memory for instance data!\n", __func__);
return -ENOMEM;
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 0561d0234f23..ef105a92a7bd 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -4,9 +4,22 @@
comment "USB Device Class drivers"
depends on USB
+config OBSOLETE_OSS_USB_DRIVER
+ bool "Obsolete OSS USB drivers"
+ depends on USB && SOUND
+ help
+ This option enables support for the obsolete USB Audio and Midi
+ drivers that are scheduled for removal in the near future since
+ there are ALSA drivers for the same hardware.
+
+ Please contact Adrian Bunk <bunk@stusta.de> if you had to
+ say Y here because of missing support in the ALSA drivers.
+
+ If unsure, say N.
+
config USB_AUDIO
tristate "USB Audio support"
- depends on USB && SOUND
+ depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
help
Say Y here if you want to connect USB audio equipment such as
speakers to your computer's USB port. You only need this if you use
@@ -15,35 +28,14 @@ config USB_AUDIO
To compile this driver as a module, choose M here: the
module will be called audio.
-comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem"
- depends on USB && BT
-
-config USB_BLUETOOTH_TTY
- tristate "USB Bluetooth TTY support"
- depends on USB && BT=n
- ---help---
- This driver implements a nonstandard tty interface to a Bluetooth
- device that can be used only by specialized Bluetooth HCI software.
-
- Say Y here if you want to use OpenBT Bluetooth stack (available
- at <http://developer.axis.com/software>), or other TTY based
- Bluetooth stacks, and want to connect a USB Bluetooth device
- to your computer's USB port.
-
- Do *not* enable this driver if you want to use generic Linux
- Bluetooth support.
-
- If in doubt, say N here.
-
- To compile this driver as a module, choose M here: the
- module will be called bluetty.
-
config USB_MIDI
tristate "USB MIDI support"
- depends on USB && SOUND
+ depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
---help---
Say Y here if you want to connect a USB MIDI device to your
- computer's USB port. This driver is for devices that comply with
+ computer's USB port. You only need this if you use the OSS
+ sound system; USB MIDI devices are supported by ALSA's USB
+ audio driver. This driver is for devices that comply with
'Universal Serial Bus Device Class Definition for MIDI Device'.
The following devices are known to work:
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index 971e5497a3fd..229471247751 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -5,6 +5,5 @@
obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_AUDIO) += audio.o
-obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o
obj-$(CONFIG_USB_MIDI) += usb-midi.o
obj-$(CONFIG_USB_PRINTER) += usblp.o
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index f8f21567cc22..50858273f8d3 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -631,8 +631,10 @@ static void usbin_stop(struct usb_audiodev *as)
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ if (notkilled)
+ schedule_timeout_interruptible(1);
+ else
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&as->lock, flags);
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
@@ -1102,8 +1104,10 @@ static void usbout_stop(struct usb_audiodev *as)
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ if (notkilled)
+ schedule_timeout_interruptible(1);
+ else
+ schedule_timeout_uninterruptible(1);
spin_lock_irqsave(&as->lock, flags);
i = u->flags;
spin_unlock_irqrestore(&as->lock, flags);
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
deleted file mode 100644
index 524023327c49..000000000000
--- a/drivers/usb/class/bluetty.c
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * bluetty.c Version 0.13
- *
- * Copyright (C) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2000 Mark Douglas Corner <mcorner@umich.edu>
- *
- * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
- *
- * (2001/11/30) Version 0.13 gkh
- * - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
- * - removed active variable, as open_count will do.
- *
- * (2001/07/09) Version 0.12 gkh
- * - removed in_interrupt() call, as it doesn't make sense to do
- * that anymore.
- *
- * (2001/06/05) Version 0.11 gkh
- * - Fixed problem with read urb status saying that we have shutdown,
- * and that we shouldn't resubmit the urb. Patch from unknown.
- *
- * (2001/05/28) Version 0.10 gkh
- * - Fixed problem with using data from userspace in the bluetooth_write
- * function as found by the CHECKER project.
- * - Added a buffer to the write_urb_pool which reduces the number of
- * buffers being created and destroyed for ever write. Also cleans
- * up the logic a bit.
- * - Added a buffer to the control_urb_pool which fixes a memory leak
- * when the device is removed from the system.
- *
- * (2001/05/28) Version 0.9 gkh
- * Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback
- * which was found by both the CHECKER project and Mikko Rahkonen.
- *
- * (08/04/2001) gb
- * Identify version on module load.
- *
- * (2001/03/10) Version 0.8 gkh
- * Fixed problem with not unlinking interrupt urb on device close
- * and resubmitting the read urb on error with bluetooth struct.
- * Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the
- * fixes.
- *
- * (11/29/2000) Version 0.7 gkh
- * Fixed problem with overrunning the tty flip buffer.
- * Removed unneeded NULL pointer initialization.
- *
- * (10/05/2000) Version 0.6 gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- * Got a real major id number and name.
- *
- * (08/06/2000) Version 0.5 gkh
- * Fixed problem of not resubmitting the bulk read urb if there is
- * an error in the callback. Ericsson devices seem to need this.
- *
- * (07/11/2000) Version 0.4 gkh
- * Fixed bug in disconnect for when we call tty_hangup
- * Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
- * getting attached to the control urb properly.
- * Fixed bug in bluetooth_write where we pay attention to the result
- * of bluetooth_ctrl_msg.
- *
- * (08/03/2000) Version 0.3 gkh mdc
- * Merged in Mark's changes to make the driver play nice with the Axis
- * stack.
- * Made the write bulk use an urb pool to enable larger transfers with
- * fewer calls to the driver.
- * Fixed off by one bug in acl pkt receive
- * Made packet counters specific to each bluetooth device
- * Added checks for zero length callbacks
- * Added buffers for int and bulk packets. Had to do this otherwise
- * packet types could intermingle.
- * Made a control urb pool for the control messages.
- *
- * (07/11/2000) Version 0.2 gkh
- * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe
- * function.
- *
- * (07/09/2000) Version 0.1 gkh
- * Initial release. Has support for sending ACL data (which is really just
- * a HCI frame.) Raw HCI commands and HCI events are not supported.
- * A ioctl will probably be needed for the HCI commands and events in the
- * future. All isoch endpoints are ignored at this time also.
- * This driver should work for all currently shipping USB Bluetooth
- * devices at this time :)
- *
- */
-
-/*
- * 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-#define DEBUG
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.13"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
-#define DRIVER_DESC "USB Bluetooth tty driver"
-
-/* define this if you have hardware that is not good */
-/*#define BTBUGGYHARDWARE */
-
-/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
-#define WIRELESS_CLASS_CODE 0xe0
-#define RF_SUBCLASS_CODE 0x01
-#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE 0x01
-
-
-#define BLUETOOTH_TTY_MAJOR 216 /* real device node major id */
-#define BLUETOOTH_TTY_MINORS 256 /* whole lotta bluetooth devices */
-
-#define USB_BLUETOOTH_MAGIC 0x6d02 /* magic number for bluetooth struct */
-
-#define BLUETOOTH_CONTROL_REQUEST_TYPE 0x20
-
-/* Bluetooth packet types */
-#define CMD_PKT 0x01
-#define ACL_PKT 0x02
-#define SCO_PKT 0x03
-#define EVENT_PKT 0x04
-#define ERROR_PKT 0x05
-#define NEG_PKT 0x06
-
-/* Message sizes */
-#define MAX_EVENT_SIZE 0xFF
-#define EVENT_HDR_SIZE 3 /* 2 for the header + 1 for the type indicator */
-#define EVENT_BUFFER_SIZE (MAX_EVENT_SIZE + EVENT_HDR_SIZE)
-
-#define MAX_ACL_SIZE 0xFFFF
-#define ACL_HDR_SIZE 5 /* 4 for the header + 1 for the type indicator */
-#define ACL_BUFFER_SIZE (MAX_ACL_SIZE + ACL_HDR_SIZE)
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
-
-#define NUM_BULK_URBS 24
-#define NUM_CONTROL_URBS 16
-
-struct usb_bluetooth {
- int magic;
- struct usb_device * dev;
- struct tty_driver * tty_driver; /* the tty_driver for this device */
- struct tty_struct * tty; /* the corresponding tty for this port */
-
- unsigned char minor; /* the starting minor number for this device */
- int throttle; /* throttled by tty layer */
- int open_count;
-
- __u8 control_out_bInterfaceNum;
- struct urb * control_urb_pool[NUM_CONTROL_URBS];
- struct usb_ctrlrequest dr[NUM_CONTROL_URBS];
-
- unsigned char * interrupt_in_buffer;
- struct urb * interrupt_in_urb;
- __u8 interrupt_in_endpointAddress;
- __u8 interrupt_in_interval;
- int interrupt_in_buffer_size;
-
- unsigned char * bulk_in_buffer;
- struct urb * read_urb;
- __u8 bulk_in_endpointAddress;
- int bulk_in_buffer_size;
-
- int bulk_out_buffer_size;
- __u8 bulk_out_endpointAddress;
-
- wait_queue_head_t write_wait;
-
- struct work_struct work; /* work queue entry for line discipline waking up */
-
- unsigned int int_packet_pos;
- unsigned char int_buffer[EVENT_BUFFER_SIZE];
- unsigned int bulk_packet_pos;
- unsigned char bulk_buffer[ACL_BUFFER_SIZE]; /* 64k preallocated, fix? */
- struct semaphore lock;
-};
-
-
-/* local function prototypes */
-static int bluetooth_open (struct tty_struct *tty, struct file *filp);
-static void bluetooth_close (struct tty_struct *tty, struct file *filp);
-static int bluetooth_write (struct tty_struct *tty, const unsigned char *buf, int count);
-static int bluetooth_write_room (struct tty_struct *tty);
-static int bluetooth_chars_in_buffer (struct tty_struct *tty);
-static void bluetooth_throttle (struct tty_struct *tty);
-static void bluetooth_unthrottle (struct tty_struct *tty);
-static int bluetooth_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void bluetooth_set_termios (struct tty_struct *tty, struct termios *old);
-
-static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-
-static int usb_bluetooth_probe (struct usb_interface *intf,
- const struct usb_device_id *id);
-static void usb_bluetooth_disconnect (struct usb_interface *intf);
-
-
-static struct usb_device_id usb_bluetooth_ids [] = {
- { USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
-
-static struct usb_driver usb_bluetooth_driver = {
- .owner = THIS_MODULE,
- .name = "bluetty",
- .probe = usb_bluetooth_probe,
- .disconnect = usb_bluetooth_disconnect,
- .id_table = usb_bluetooth_ids,
-};
-
-static struct tty_driver *bluetooth_tty_driver;
-static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS];
-
-
-static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
-{
- if (!bluetooth) {
- dbg("%s - bluetooth == NULL", function);
- return -1;
- }
- if (bluetooth->magic != USB_BLUETOOTH_MAGIC) {
- dbg("%s - bad magic number for bluetooth", function);
- return -1;
- }
-
- return 0;
-}
-
-
-static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function)
-{
- if (!bluetooth ||
- bluetooth_paranoia_check (bluetooth, function)) {
- /* then say that we don't have a valid usb_bluetooth thing, which will
- * end up generating -ENODEV return values */
- return NULL;
- }
-
- return bluetooth;
-}
-
-
-static inline struct usb_bluetooth *get_bluetooth_by_index (int index)
-{
- return bluetooth_table[index];
-}
-
-
-static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
-{
- struct urb *urb = NULL;
- struct usb_ctrlrequest *dr = NULL;
- int i;
- int status;
-
- dbg ("%s", __FUNCTION__);
-
- /* try to find a free urb in our list */
- for (i = 0; i < NUM_CONTROL_URBS; ++i) {
- if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) {
- urb = bluetooth->control_urb_pool[i];
- dr = &bluetooth->dr[i];
- break;
- }
- }
- if (urb == NULL) {
- dbg ("%s - no free urbs", __FUNCTION__);
- return -ENOMEM;
- }
-
- /* keep increasing the urb transfer buffer to fit the size of the message */
- if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
- if (urb->transfer_buffer == NULL) {
- err ("%s - out of memory", __FUNCTION__);
- return -ENOMEM;
- }
- }
- if (urb->transfer_buffer_length < len) {
- kfree(urb->transfer_buffer);
- urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
- if (urb->transfer_buffer == NULL) {
- err ("%s - out of memory", __FUNCTION__);
- return -ENOMEM;
- }
- }
- memcpy (urb->transfer_buffer, buf, len);
-
- dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
- dr->bRequest = request;
- dr->wValue = cpu_to_le16((u16) value);
- dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
- dr->wLength = cpu_to_le16((u16) len);
-
- usb_fill_control_urb (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
- (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
-
- /* send it down the pipe */
- status = usb_submit_urb(urb, GFP_KERNEL);
- if (status)
- dbg("%s - usb_submit_urb(control) failed with status = %d", __FUNCTION__, status);
-
- return status;
-}
-
-
-
-
-
-/*****************************************************************************
- * Driver tty interface functions
- *****************************************************************************/
-static int bluetooth_open (struct tty_struct *tty, struct file * filp)
-{
- struct usb_bluetooth *bluetooth;
- int result;
-
- dbg("%s", __FUNCTION__);
-
- /* initialize the pointer incase something fails */
- tty->driver_data = NULL;
-
- /* get the bluetooth object associated with this tty pointer */
- bluetooth = get_bluetooth_by_index (tty->index);
-
- if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
- return -ENODEV;
- }
-
- down (&bluetooth->lock);
-
- ++bluetooth->open_count;
- if (bluetooth->open_count == 1) {
- /* set up our structure making the tty driver remember our object, and us it */
- tty->driver_data = bluetooth;
- bluetooth->tty = tty;
-
- /* force low_latency on so that our tty_push actually forces the data through,
- * otherwise it is scheduled, and with high data rates (like with OHCI) data
- * can get lost. */
- bluetooth->tty->low_latency = 1;
-
- /* Reset the packet position counters */
- bluetooth->int_packet_pos = 0;
- bluetooth->bulk_packet_pos = 0;
-
-#ifndef BTBUGGYHARDWARE
- /* Start reading from the device */
- usb_fill_bulk_urb (bluetooth->read_urb, bluetooth->dev,
- usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
- bluetooth->bulk_in_buffer,
- bluetooth->bulk_in_buffer_size,
- bluetooth_read_bulk_callback, bluetooth);
- result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
- if (result)
- dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
-#endif
- usb_fill_int_urb (bluetooth->interrupt_in_urb, bluetooth->dev,
- usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
- bluetooth->interrupt_in_buffer,
- bluetooth->interrupt_in_buffer_size,
- bluetooth_int_callback, bluetooth,
- bluetooth->interrupt_in_interval);
- result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
- if (result)
- dbg("%s - usb_submit_urb(interrupt in) failed with status %d", __FUNCTION__, result);
- }
-
- up(&bluetooth->lock);
-
- return 0;
-}
-
-
-static void bluetooth_close (struct tty_struct *tty, struct file * filp)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not opened", __FUNCTION__);
- return;
- }
-
- down (&bluetooth->lock);
-
- --bluetooth->open_count;
- if (bluetooth->open_count <= 0) {
- bluetooth->open_count = 0;
-
- /* shutdown any in-flight urbs that we know about */
- usb_kill_urb (bluetooth->read_urb);
- usb_kill_urb (bluetooth->interrupt_in_urb);
- }
- up(&bluetooth->lock);
-}
-
-
-static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
- struct urb *urb = NULL;
- unsigned char *temp_buffer = NULL;
- const unsigned char *current_buffer;
- unsigned char *urb_buffer;
- int i;
- int retval = 0;
-
- if (!bluetooth) {
- return -ENODEV;
- }
-
- dbg("%s - %d byte(s)", __FUNCTION__, count);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not opened", __FUNCTION__);
- return -EINVAL;
- }
-
- if (count == 0) {
- dbg("%s - write request of 0 bytes", __FUNCTION__);
- return 0;
- }
- if (count == 1) {
- dbg("%s - write request only included type %d", __FUNCTION__, buf[0]);
- return 1;
- }
-
-#ifdef DEBUG
- printk (KERN_DEBUG __FILE__ ": %s - length = %d, data = ", __FUNCTION__, count);
- for (i = 0; i < count; ++i) {
- printk ("%.2x ", buf[i]);
- }
- printk ("\n");
-#endif
-
- current_buffer = buf;
-
- switch (*current_buffer) {
- /* First byte indicates the type of packet */
- case CMD_PKT:
- /* dbg("%s- Send cmd_pkt len:%d", __FUNCTION__, count);*/
-
- retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
- if (retval) {
- goto exit;
- }
- retval = count;
- break;
-
- case ACL_PKT:
- ++current_buffer;
- --count;
-
- urb_buffer = kmalloc (count, GFP_ATOMIC);
- if (!urb_buffer) {
- dev_err(&bluetooth->dev->dev, "out of memory\n");
- retval = -ENOMEM;
- goto exit;
- }
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- dev_err(&bluetooth->dev->dev, "no more free urbs\n");
- kfree(urb_buffer);
- retval = -ENOMEM;
- goto exit;
- }
- memcpy (urb_buffer, current_buffer, count);
-
- /* build up our urb */
- usb_fill_bulk_urb(urb, bluetooth->dev,
- usb_sndbulkpipe(bluetooth->dev,
- bluetooth->bulk_out_endpointAddress),
- urb_buffer,
- count,
- bluetooth_write_bulk_callback,
- bluetooth);
-
-
- /* send it down the pipe */
- retval = usb_submit_urb(urb, GFP_KERNEL);
- if (retval) {
- dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
- goto exit;
- }
-
- /* we are done with this urb, so let the host driver
- * really free it when it is finished with it */
- usb_free_urb (urb);
- retval = count + 1;
- break;
-
- default :
- dbg("%s - unsupported (at this time) write type", __FUNCTION__);
- retval = -EINVAL;
- break;
- }
-
-exit:
- kfree(temp_buffer);
-
- return retval;
-}
-
-
-static int bluetooth_write_room (struct tty_struct *tty)
-{
- dbg("%s", __FUNCTION__);
-
- /*
- * We really can take anything the user throws at us
- * but let's pick a nice big number to tell the tty
- * layer that we have lots of free space
- */
- return 2048;
-}
-
-
-static int bluetooth_chars_in_buffer (struct tty_struct *tty)
-{
- dbg("%s", __FUNCTION__);
-
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device, so just tell the tty layer that everything
- * is flushed.
- */
- return 0;
-}
-
-
-static void bluetooth_throttle (struct tty_struct * tty)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return;
- }
-
- dbg("%s unsupported (at this time)", __FUNCTION__);
-
- return;
-}
-
-
-static void bluetooth_unthrottle (struct tty_struct * tty)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return;
- }
-
- dbg("%s unsupported (at this time)", __FUNCTION__);
-}
-
-
-static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return -ENODEV;
- }
-
- dbg("%s - cmd 0x%.4x", __FUNCTION__, cmd);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return -ENODEV;
- }
-
- /* FIXME!!! */
- return -ENOIOCTLCMD;
-}
-
-
-static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return;
- }
-
- /* FIXME!!! */
-
- return;
-}
-
-
-#ifdef BTBUGGYHARDWARE
-void btusb_enable_bulk_read(struct tty_struct *tty){
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
- int result;
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return;
- }
-
- if (bluetooth->read_urb) {
- usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev,
- usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
- bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
- bluetooth_read_bulk_callback, bluetooth);
- result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
- if (result)
- err ("%s - failed submitting read urb, error %d", __FUNCTION__, result);
- }
-}
-
-void btusb_disable_bulk_read(struct tty_struct *tty){
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
- if (!bluetooth) {
- return;
- }
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth->open_count) {
- dbg ("%s - device not open", __FUNCTION__);
- return;
- }
-
- if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
- usb_kill_urb(bluetooth->read_urb);
-}
-#endif
-
-
-/*****************************************************************************
- * urb callback functions
- *****************************************************************************/
-
-
-static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
- unsigned char *data = urb->transfer_buffer;
- unsigned int i;
- unsigned int count = urb->actual_length;
- unsigned int packet_size;
- int status;
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth) {
- dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
- return;
- }
-
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
- goto exit;
- }
-
- if (!count) {
- dbg("%s - zero length int", __FUNCTION__);
- goto exit;
- }
-
-
-#ifdef DEBUG
- if (count) {
- printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
- for (i = 0; i < count; ++i) {
- printk ("%.2x ", data[i]);
- }
- printk ("\n");
- }
-#endif
-
-#ifdef BTBUGGYHARDWARE
- if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
- data += 2;
- count -= 2;
- }
- if (count == 0) {
- urb->actual_length = 0;
- goto exit;
- }
-#endif
- /* We add a packet type identifier to the beginning of each
- HCI frame. This makes the data in the tty look like a
- serial USB devices. Each HCI frame can be broken across
- multiple URBs so we buffer them until we have a full hci
- packet */
-
- if (!bluetooth->int_packet_pos) {
- bluetooth->int_buffer[0] = EVENT_PKT;
- bluetooth->int_packet_pos++;
- }
-
- if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
- err("%s - exceeded EVENT_BUFFER_SIZE", __FUNCTION__);
- bluetooth->int_packet_pos = 0;
- goto exit;
- }
-
- memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
- urb->transfer_buffer, count);
- bluetooth->int_packet_pos += count;
- urb->actual_length = 0;
-
- if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
- packet_size = bluetooth->int_buffer[2];
- else
- goto exit;
-
- if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
- err("%s - packet was too long", __FUNCTION__);
- bluetooth->int_packet_pos = 0;
- goto exit;
- }
-
- if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
- for (i = 0; i < bluetooth->int_packet_pos; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
- if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(bluetooth->tty);
- }
- tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
- }
- tty_flip_buffer_push(bluetooth->tty);
-
- bluetooth->int_packet_pos = 0;
- }
-
-exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
-}
-
-
-static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth) {
- dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
- return;
- }
-
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
- return;
- }
-}
-
-
-static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
- unsigned char *data = urb->transfer_buffer;
- unsigned int count = urb->actual_length;
- unsigned int i;
- unsigned int packet_size;
- int result;
-
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth) {
- dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
- return;
- }
-
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
- if (urb->status == -ENOENT) {
- dbg("%s - URB canceled, won't reschedule", __FUNCTION__);
- return;
- }
- goto exit;
- }
-
- if (!count) {
- dbg("%s - zero length read bulk", __FUNCTION__);
- goto exit;
- }
-
-#ifdef DEBUG
- if (count) {
- printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
- for (i = 0; i < count; ++i) {
- printk ("%.2x ", data[i]);
- }
- printk ("\n");
- }
-#endif
-#ifdef BTBUGGYHARDWARE
- if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00)
- && (data[2] == 0x00) && (data[3] == 0x00)) {
- urb->actual_length = 0;
- usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev,
- usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
- bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
- bluetooth_read_bulk_callback, bluetooth);
- result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
- if (result)
- err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
- return;
- }
-#endif
- /* We add a packet type identifier to the beginning of each
- HCI frame. This makes the data in the tty look like a
- serial USB devices. Each HCI frame can be broken across
- multiple URBs so we buffer them until we have a full hci
- packet */
-
- if (!bluetooth->bulk_packet_pos) {
- bluetooth->bulk_buffer[0] = ACL_PKT;
- bluetooth->bulk_packet_pos++;
- }
-
- if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
- err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__);
- bluetooth->bulk_packet_pos = 0;
- goto exit;
- }
-
- memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
- urb->transfer_buffer, count);
- bluetooth->bulk_packet_pos += count;
- urb->actual_length = 0;
-
- if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
- packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
- } else {
- goto exit;
- }
-
- if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
- err("%s - packet was too long", __FUNCTION__);
- bluetooth->bulk_packet_pos = 0;
- goto exit;
- }
-
- if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
- for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(bluetooth->tty);
- }
- tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
- }
- tty_flip_buffer_push(bluetooth->tty);
- bluetooth->bulk_packet_pos = 0;
- }
-
-exit:
- if (!bluetooth || !bluetooth->open_count)
- return;
-
- usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev,
- usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
- bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
- bluetooth_read_bulk_callback, bluetooth);
- result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
- if (result)
- err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
- return;
-}
-
-
-static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
- dbg("%s", __FUNCTION__);
-
- /* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree(urb->transfer_buffer);
-
- if (!bluetooth) {
- dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
- return;
- }
-
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
- return;
- }
-
- /* wake up our little function to let the tty layer know that something happened */
- schedule_work(&bluetooth->work);
-}
-
-
-static void bluetooth_softint(void *private)
-{
- struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-
- dbg("%s", __FUNCTION__);
-
- if (!bluetooth)
- return;
-
- tty_wakeup(bluetooth->tty);
-}
-
-
-static int usb_bluetooth_probe (struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev (intf);
- struct usb_bluetooth *bluetooth = NULL;
- struct usb_host_interface *interface;
- struct usb_endpoint_descriptor *endpoint;
- struct usb_endpoint_descriptor *interrupt_in_endpoint[8];
- struct usb_endpoint_descriptor *bulk_in_endpoint[8];
- struct usb_endpoint_descriptor *bulk_out_endpoint[8];
- int control_out_endpoint;
-
- int minor;
- int buffer_size;
- int i;
- int num_interrupt_in = 0;
- int num_bulk_in = 0;
- int num_bulk_out = 0;
-
- interface = intf->cur_altsetting;
- control_out_endpoint = interface->desc.bInterfaceNumber;
-
- /* find the endpoints that we need */
- for (i = 0; i < interface->desc.bNumEndpoints; ++i) {
- endpoint = &interface->endpoint[i].desc;
-
- if ((endpoint->bEndpointAddress & 0x80) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk in endpoint */
- dbg("found bulk in");
- bulk_in_endpoint[num_bulk_in] = endpoint;
- ++num_bulk_in;
- }
-
- if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found a bulk out endpoint */
- dbg("found bulk out");
- bulk_out_endpoint[num_bulk_out] = endpoint;
- ++num_bulk_out;
- }
-
- if ((endpoint->bEndpointAddress & 0x80) &&
- ((endpoint->bmAttributes & 3) == 0x03)) {
- /* we found a interrupt in endpoint */
- dbg("found interrupt in");
- interrupt_in_endpoint[num_interrupt_in] = endpoint;
- ++num_interrupt_in;
- }
- }
-
- /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */
- if ((num_bulk_in != 1) ||
- (num_bulk_out != 1) ||
- (num_interrupt_in != 1)) {
- dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__);
- return -EIO;
- }
-
- info("USB Bluetooth converter detected");
-
- for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor)
- ;
- if (bluetooth_table[minor]) {
- err("No more free Bluetooth devices");
- return -ENODEV;
- }
-
- if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
- err("Out of memory");
- return -ENOMEM;
- }
-
- memset(bluetooth, 0, sizeof(struct usb_bluetooth));
-
- bluetooth->magic = USB_BLUETOOTH_MAGIC;
- bluetooth->dev = dev;
- bluetooth->minor = minor;
- INIT_WORK(&bluetooth->work, bluetooth_softint, bluetooth);
- init_MUTEX(&bluetooth->lock);
-
- /* record the interface number for the control out */
- bluetooth->control_out_bInterfaceNum = control_out_endpoint;
-
- /* create our control out urb pool */
- for (i = 0; i < NUM_CONTROL_URBS; ++i) {
- struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
- if (urb == NULL) {
- err("No free urbs available");
- goto probe_error;
- }
- urb->transfer_buffer = NULL;
- bluetooth->control_urb_pool[i] = urb;
- }
-
- /* set up the endpoint information */
- endpoint = bulk_in_endpoint[0];
- bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL);
- if (!bluetooth->read_urb) {
- err("No free urbs available");
- goto probe_error;
- }
- bluetooth->bulk_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
- bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
- bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!bluetooth->bulk_in_buffer) {
- err("Couldn't allocate bulk_in_buffer");
- goto probe_error;
- }
- usb_fill_bulk_urb(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
- bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth);
-
- endpoint = bulk_out_endpoint[0];
- bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
- bluetooth->bulk_out_buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
-
- endpoint = interrupt_in_endpoint[0];
- bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!bluetooth->interrupt_in_urb) {
- err("No free urbs available");
- goto probe_error;
- }
- bluetooth->interrupt_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
- bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
- bluetooth->interrupt_in_interval = endpoint->bInterval;
- bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!bluetooth->interrupt_in_buffer) {
- err("Couldn't allocate interrupt_in_buffer");
- goto probe_error;
- }
- usb_fill_int_urb(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback,
- bluetooth, endpoint->bInterval);
-
- /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
- tty_register_device (bluetooth_tty_driver, minor, &intf->dev);
- info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
-
- bluetooth_table[minor] = bluetooth;
-
- /* success */
- usb_set_intfdata (intf, bluetooth);
- return 0;
-
-probe_error:
- if (bluetooth->read_urb)
- usb_free_urb (bluetooth->read_urb);
- if (bluetooth->bulk_in_buffer)
- kfree (bluetooth->bulk_in_buffer);
- if (bluetooth->interrupt_in_urb)
- usb_free_urb (bluetooth->interrupt_in_urb);
- if (bluetooth->interrupt_in_buffer)
- kfree (bluetooth->interrupt_in_buffer);
- for (i = 0; i < NUM_CONTROL_URBS; ++i)
- if (bluetooth->control_urb_pool[i]) {
- if (bluetooth->control_urb_pool[i]->transfer_buffer)
- kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
- usb_free_urb (bluetooth->control_urb_pool[i]);
- }
-
- bluetooth_table[minor] = NULL;
-
- /* free up any memory that we allocated */
- kfree (bluetooth);
- return -EIO;
-}
-
-
-static void usb_bluetooth_disconnect(struct usb_interface *intf)
-{
- struct usb_bluetooth *bluetooth = usb_get_intfdata (intf);
- int i;
-
- usb_set_intfdata (intf, NULL);
- if (bluetooth) {
- if ((bluetooth->open_count) && (bluetooth->tty))
- tty_hangup(bluetooth->tty);
-
- bluetooth->open_count = 0;
-
- if (bluetooth->read_urb) {
- usb_kill_urb (bluetooth->read_urb);
- usb_free_urb (bluetooth->read_urb);
- }
- if (bluetooth->bulk_in_buffer)
- kfree (bluetooth->bulk_in_buffer);
-
- if (bluetooth->interrupt_in_urb) {
- usb_kill_urb (bluetooth->interrupt_in_urb);
- usb_free_urb (bluetooth->interrupt_in_urb);
- }
- if (bluetooth->interrupt_in_buffer)
- kfree (bluetooth->interrupt_in_buffer);
-
- tty_unregister_device (bluetooth_tty_driver, bluetooth->minor);
-
- for (i = 0; i < NUM_CONTROL_URBS; ++i) {
- if (bluetooth->control_urb_pool[i]) {
- usb_kill_urb (bluetooth->control_urb_pool[i]);
- if (bluetooth->control_urb_pool[i]->transfer_buffer)
- kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
- usb_free_urb (bluetooth->control_urb_pool[i]);
- }
- }
-
- info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor);
-
- bluetooth_table[bluetooth->minor] = NULL;
-
- /* free up any memory that we allocated */
- kfree (bluetooth);
- } else {
- info("device disconnected");
- }
-}
-
-static struct tty_operations bluetooth_ops = {
- .open = bluetooth_open,
- .close = bluetooth_close,
- .write = bluetooth_write,
- .write_room = bluetooth_write_room,
- .ioctl = bluetooth_ioctl,
- .set_termios = bluetooth_set_termios,
- .throttle = bluetooth_throttle,
- .unthrottle = bluetooth_unthrottle,
- .chars_in_buffer = bluetooth_chars_in_buffer,
-};
-
-static int usb_bluetooth_init(void)
-{
- int i;
- int result;
-
- /* Initialize our global data */
- for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) {
- bluetooth_table[i] = NULL;
- }
-
- info ("USB Bluetooth support registered");
-
- bluetooth_tty_driver = alloc_tty_driver(BLUETOOTH_TTY_MINORS);
- if (!bluetooth_tty_driver)
- return -ENOMEM;
-
- bluetooth_tty_driver->owner = THIS_MODULE;
- bluetooth_tty_driver->driver_name = "usb-bluetooth";
- bluetooth_tty_driver->name = "ttyUB";
- bluetooth_tty_driver->devfs_name = "usb/ttub/";
- bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
- bluetooth_tty_driver->minor_start = 0;
- bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- bluetooth_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- bluetooth_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
- bluetooth_tty_driver->init_termios = tty_std_termios;
- bluetooth_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- tty_set_operations(bluetooth_tty_driver, &bluetooth_ops);
- if (tty_register_driver (bluetooth_tty_driver)) {
- err("%s - failed to register tty driver", __FUNCTION__);
- put_tty_driver(bluetooth_tty_driver);
- return -1;
- }
-
- /* register the USB driver */
- result = usb_register(&usb_bluetooth_driver);
- if (result < 0) {
- tty_unregister_driver(bluetooth_tty_driver);
- put_tty_driver(bluetooth_tty_driver);
- err("usb_register failed for the USB bluetooth driver. Error number %d", result);
- return -1;
- }
-
- info(DRIVER_DESC " " DRIVER_VERSION);
-
- return 0;
-}
-
-
-static void usb_bluetooth_exit(void)
-{
- usb_deregister(&usb_bluetooth_driver);
- tty_unregister_driver(bluetooth_tty_driver);
- put_tty_driver(bluetooth_tty_driver);
-}
-
-
-module_init(usb_bluetooth_init);
-module_exit(usb_bluetooth_exit);
-
-/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 16ecad30e29c..1b4751412970 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -827,11 +827,10 @@ skip_normal_probe:
return -ENODEV;
}
- if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
- dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
+ if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
+ dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
goto alloc_fail;
}
- memset(acm, 0, sizeof(struct acm));
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
readsize = le16_to_cpu(epread->wMaxPacketSize);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 7ce43fb8118a..357e75335f17 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -310,8 +310,9 @@ static int usblp_check_status(struct usblp *usblp, int err)
error = usblp_read_status (usblp, usblp->statusbuf);
if (error < 0) {
- err("usblp%d: error %d reading printer status",
- usblp->minor, error);
+ if (printk_ratelimit())
+ err("usblp%d: error %d reading printer status",
+ usblp->minor, error);
return 0;
}
@@ -604,7 +605,9 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case LPGETSTATUS:
if (usblp_read_status(usblp, usblp->statusbuf)) {
- err("usblp%d: failed reading printer status", usblp->minor);
+ if (printk_ratelimit())
+ err("usblp%d: failed reading printer status",
+ usblp->minor);
retval = -EIO;
goto done;
}
@@ -841,9 +844,8 @@ static struct file_operations usblp_fops = {
};
static struct usb_class_driver usblp_class = {
- .name = "usb/lp%d",
+ .name = "lp%d",
.fops = &usblp_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = USBLP_MINOR_BASE,
};
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 1a9ff6184943..ff03184da403 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS
If you are unsure about this, say N here.
config USB_SUSPEND
- bool "USB suspend/resume (EXPERIMENTAL)"
+ bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
depends on USB && PM && EXPERIMENTAL
help
If you say Y here, you can use driver calls or the sysfs
"power/state" file to suspend or resume individual USB
- peripherals. There are many related features, such as
- remote wakeup and driver-specific suspend processing, that
- may not yet work as expected.
+ peripherals.
+
+ Also, USB "remote wakeup" signaling is supported, whereby some
+ USB devices (like keyboards and network adapters) can wake up
+ their parent hub. That wakeup cascades up the USB tree, and
+ could wake the system from states like suspend-to-RAM.
If you are unsure about this, say N here.
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 9e8c377b8161..dd1c4d2a0c31 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -3,14 +3,14 @@
#
usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
- config.o file.o buffer.o sysfs.o
+ config.o file.o buffer.o sysfs.o devio.o notify.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
endif
ifeq ($(CONFIG_USB_DEVICEFS),y)
- usbcore-objs += devio.o inode.o devices.o
+ usbcore-objs += inode.o devices.o
endif
obj-$(CONFIG_USB) += usbcore.o
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index fc15b4acc8af..57e800ac3cee 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -106,7 +106,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
void *hcd_buffer_alloc (
struct usb_bus *bus,
size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma
)
{
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 99595e07b653..993019500cc3 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref)
struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
int j;
- for (j = 0; j < intfc->num_altsetting; j++)
- kfree(intfc->altsetting[j].endpoint);
+ for (j = 0; j < intfc->num_altsetting; j++) {
+ struct usb_host_interface *alt = &intfc->altsetting[j];
+
+ kfree(alt->endpoint);
+ kfree(alt->string);
+ }
kfree(intfc);
}
@@ -188,10 +192,9 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
}
len = sizeof(struct usb_host_endpoint) * num_ep;
- alt->endpoint = kmalloc(len, GFP_KERNEL);
+ alt->endpoint = kzalloc(len, GFP_KERNEL);
if (!alt->endpoint)
return -ENOMEM;
- memset(alt->endpoint, 0, len);
/* Parse all the endpoint descriptors */
n = 0;
@@ -353,10 +356,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
}
len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
- config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
+ config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
if (!intfc)
return -ENOMEM;
- memset(intfc, 0, len);
kref_init(&intfc->ref);
}
@@ -422,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev)
struct usb_host_config *cf = &dev->config[c];
kfree(cf->string);
- cf->string = NULL;
-
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
if (cf->intf_cache[i])
kref_put(&cf->intf_cache[i]->ref,
@@ -459,16 +459,14 @@ int usb_get_configuration(struct usb_device *dev)
}
length = ncfg * sizeof(struct usb_host_config);
- dev->config = kmalloc(length, GFP_KERNEL);
+ dev->config = kzalloc(length, GFP_KERNEL);
if (!dev->config)
goto err2;
- memset(dev->config, 0, length);
length = ncfg * sizeof(char *);
- dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
+ dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
if (!dev->rawdescriptors)
goto err2;
- memset(dev->rawdescriptors, 0, length);
buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!buffer)
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f86bf1454e21..942cd437dc48 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -30,6 +30,8 @@
* Revision history
* 22.12.1999 0.1 Initial release (split from proc_usb.c)
* 04.01.2000 0.2 Turned into its own filesystem
+ * 30.09.2005 0.3 Fix user-triggerable oops in async URB delivery
+ * (CAN-2005-3055)
*/
/*****************************************************************************/
@@ -43,6 +45,8 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
+#include <linux/cdev.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
@@ -50,10 +54,15 @@
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
+#define USB_MAXBUS 64
+#define USB_DEVICE_MAX USB_MAXBUS * 128
+static struct class *usb_device_class;
+
struct async {
struct list_head asynclist;
struct dev_state *ps;
- struct task_struct *task;
+ pid_t pid;
+ uid_t uid, euid;
unsigned int signr;
unsigned int ifnum;
void __user *userbuffer;
@@ -71,6 +80,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
dev_info( dev , format , ## arg); \
} while (0)
+#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
+
#define MAX_USBFS_BUFFER_SIZE 16384
@@ -199,10 +210,10 @@ err:
static struct async *alloc_async(unsigned int numisoframes)
{
unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
- struct async *as = kmalloc(assize, GFP_KERNEL);
+ struct async *as = kzalloc(assize, GFP_KERNEL);
+
if (!as)
return NULL;
- memset(as, 0, assize);
as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
if (!as->urb) {
kfree(as);
@@ -269,6 +280,28 @@ static inline struct async *async_getpending(struct dev_state *ps, void __user *
return NULL;
}
+static void snoop_urb(struct urb *urb, void __user *userurb)
+{
+ int j;
+ unsigned char *data = urb->transfer_buffer;
+
+ if (!usbfs_snoop)
+ return;
+
+ if (urb->pipe & USB_DIR_IN)
+ dev_info(&urb->dev->dev, "direction=IN\n");
+ else
+ dev_info(&urb->dev->dev, "direction=OUT\n");
+ dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
+ dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
+ urb->transfer_buffer_length);
+ dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
+ dev_info(&urb->dev->dev, "data: ");
+ for (j = 0; j < urb->transfer_buffer_length; ++j)
+ printk ("%02x ", data[j]);
+ printk("\n");
+}
+
static void async_completed(struct urb *urb, struct pt_regs *regs)
{
struct async *as = (struct async *)urb->context;
@@ -283,9 +316,12 @@ static void async_completed(struct urb *urb, struct pt_regs *regs)
sinfo.si_errno = as->urb->status;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = as->userurb;
- send_sig_info(as->signr, &sinfo, as->task);
+ kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
+ as->euid);
}
- wake_up(&ps->wait);
+ snoop(&urb->dev->dev, "urb complete\n");
+ snoop_urb(urb, as->userurb);
+ wake_up(&ps->wait);
}
static void destroy_async (struct dev_state *ps, struct list_head *list)
@@ -482,12 +518,29 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
return ret;
}
+static struct usb_device *usbdev_lookup_minor(int minor)
+{
+ struct class_device *class_dev;
+ struct usb_device *dev = NULL;
+
+ down(&usb_device_class->sem);
+ list_for_each_entry(class_dev, &usb_device_class->children, node) {
+ if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+ dev = class_dev->class_data;
+ break;
+ }
+ }
+ up(&usb_device_class->sem);
+
+ return dev;
+};
+
/*
* file operations
*/
static int usbdev_open(struct inode *inode, struct file *file)
{
- struct usb_device *dev;
+ struct usb_device *dev = NULL;
struct dev_state *ps;
int ret;
@@ -501,11 +554,16 @@ static int usbdev_open(struct inode *inode, struct file *file)
lock_kernel();
ret = -ENOENT;
- dev = usb_get_dev(inode->u.generic_ip);
+ /* check if we are called from a real node or usbfs */
+ if (imajor(inode) == USB_DEVICE_MAJOR)
+ dev = usbdev_lookup_minor(iminor(inode));
+ if (!dev)
+ dev = inode->u.generic_ip;
if (!dev) {
kfree(ps);
goto out;
}
+ usb_get_dev(dev);
ret = 0;
ps->dev = dev;
ps->file = file;
@@ -514,7 +572,9 @@ static int usbdev_open(struct inode *inode, struct file *file)
INIT_LIST_HEAD(&ps->async_completed);
init_waitqueue_head(&ps->wait);
ps->discsignr = 0;
- ps->disctask = current;
+ ps->disc_pid = current->pid;
+ ps->disc_uid = current->uid;
+ ps->disc_euid = current->euid;
ps->disccontext = NULL;
ps->ifclaimed = 0;
wmb();
@@ -583,7 +643,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) {
dev_info(&dev->dev, "control read: data ");
for (j = 0; j < i; ++j)
- printk ("%02x ", (unsigned char)(tbuf)[j]);
+ printk("%02x ", (unsigned char)(tbuf)[j]);
printk("\n");
}
if (copy_to_user(ctrl.data, tbuf, i)) {
@@ -606,7 +666,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) {
dev_info(&dev->dev, "control write: data: ");
for (j = 0; j < ctrl.wLength; ++j)
- printk ("%02x ", (unsigned char)(tbuf)[j]);
+ printk("%02x ", (unsigned char)(tbuf)[j]);
printk("\n");
}
usb_unlock_device(dev);
@@ -631,7 +691,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
unsigned int tmo, len1, pipe;
int len2;
unsigned char *tbuf;
- int i, ret;
+ int i, j, ret;
if (copy_from_user(&bulk, arg, sizeof(bulk)))
return -EFAULT;
@@ -656,10 +716,18 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
kfree(tbuf);
return -EINVAL;
}
+ snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
+ bulk.len, bulk.timeout);
usb_unlock_device(dev);
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
usb_lock_device(dev);
if (!i && len2) {
+ if (usbfs_snoop) {
+ dev_info(&dev->dev, "bulk read: data ");
+ for (j = 0; j < len2; ++j)
+ printk("%02x ", (unsigned char)(tbuf)[j]);
+ printk("\n");
+ }
if (copy_to_user(bulk.data, tbuf, len2)) {
kfree(tbuf);
return -EFAULT;
@@ -672,6 +740,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
return -EFAULT;
}
}
+ snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
+ bulk.len, bulk.timeout);
+ if (usbfs_snoop) {
+ dev_info(&dev->dev, "bulk write: data: ");
+ for (j = 0; j < len1; ++j)
+ printk("%02x ", (unsigned char)(tbuf)[j]);
+ printk("\n");
+ }
usb_unlock_device(dev);
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
usb_lock_device(dev);
@@ -817,7 +893,6 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
return status;
}
-
static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
void __user *arg)
@@ -878,6 +953,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
kfree(dr);
return -EFAULT;
}
+ snoop(&ps->dev->dev, "control urb\n");
break;
case USBDEVFS_URB_TYPE_BULK:
@@ -892,6 +968,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
return -EFAULT;
+ snoop(&ps->dev->dev, "bulk urb\n");
break;
case USBDEVFS_URB_TYPE_ISO:
@@ -921,6 +998,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
}
uurb->buffer_length = totlen;
+ snoop(&ps->dev->dev, "iso urb\n");
break;
case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -936,6 +1014,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
return -EFAULT;
+ snoop(&ps->dev->dev, "interrupt urb\n");
break;
default:
@@ -976,13 +1055,17 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
as->userbuffer = NULL;
as->signr = uurb->signr;
as->ifnum = ifnum;
- as->task = current;
+ as->pid = current->pid;
+ as->uid = current->uid;
+ as->euid = current->euid;
if (!(uurb->endpoint & USB_DIR_IN)) {
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
free_async(as);
return -EFAULT;
}
}
+ snoop(&as->urb->dev->dev, "submit urb\n");
+ snoop_urb(as->urb, as->userurb);
async_newpending(as);
if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
@@ -1218,24 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg)
return 0;
}
-static int proc_ioctl (struct dev_state *ps, void __user *arg)
+static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
{
- struct usbdevfs_ioctl ctrl;
int size;
void *buf = NULL;
int retval = 0;
struct usb_interface *intf = NULL;
struct usb_driver *driver = NULL;
- int i;
- /* get input parameters and alloc buffer */
- if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
- return -EFAULT;
- if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
+ /* alloc buffer */
+ if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
return -ENOMEM;
- if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
- if (copy_from_user (buf, ctrl.data, size)) {
+ if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
+ if (copy_from_user (buf, ctl->data, size)) {
kfree(buf);
return -EFAULT;
}
@@ -1251,22 +1330,13 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
if (ps->dev->state != USB_STATE_CONFIGURED)
retval = -EHOSTUNREACH;
- else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
+ else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
retval = -EINVAL;
- else switch (ctrl.ioctl_code) {
+ else switch (ctl->ioctl_code) {
/* disconnect kernel driver from interface */
case USBDEVFS_DISCONNECT:
- /* don't allow the user to unbind the hub driver from
- * a hub with children to manage */
- for (i = 0; i < ps->dev->maxchild; ++i) {
- if (ps->dev->children[i])
- retval = -EBUSY;
- }
- if (retval)
- break;
-
down_write(&usb_bus_type.subsys.rwsem);
if (intf->dev.driver) {
driver = to_usb_driver(intf->dev.driver);
@@ -1294,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
if (driver == NULL || driver->ioctl == NULL) {
retval = -ENOTTY;
} else {
- retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
+ retval = driver->ioctl (intf, ctl->ioctl_code, buf);
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
}
@@ -1303,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
/* cleanup and return */
if (retval >= 0
- && (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
+ && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
&& size > 0
- && copy_to_user (ctrl.data, buf, size) != 0)
+ && copy_to_user (ctl->data, buf, size) != 0)
retval = -EFAULT;
kfree(buf);
return retval;
}
+static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
+{
+ struct usbdevfs_ioctl ctrl;
+
+ if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+ return -EFAULT;
+ return proc_ioctl(ps, &ctrl);
+}
+
+#ifdef CONFIG_COMPAT
+static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
+{
+ struct usbdevfs_ioctl32 __user *uioc;
+ struct usbdevfs_ioctl ctrl;
+ u32 udata;
+
+ uioc = compat_ptr(arg);
+ if (get_user(ctrl.ifno, &uioc->ifno) ||
+ get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
+ __get_user(udata, &uioc->data))
+ return -EFAULT;
+ ctrl.data = compat_ptr(udata);
+
+ return proc_ioctl(ps, &ctrl);
+}
+#endif
+
/*
* NOTE: All requests here that have interface numbers as parameters
* are assuming that somehow the configuration has been prevented from
@@ -1412,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
ret = proc_reapurbnonblock_compat(ps, p);
break;
+ case USBDEVFS_IOCTL32:
+ snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
+ ret = proc_ioctl_compat(ps, p);
+ break;
#endif
case USBDEVFS_DISCARDURB:
@@ -1446,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
case USBDEVFS_IOCTL:
snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
- ret = proc_ioctl(ps, p);
+ ret = proc_ioctl_default(ps, p);
break;
}
usb_unlock_device(dev);
@@ -1477,3 +1578,88 @@ struct file_operations usbfs_device_file_operations = {
.open = usbdev_open,
.release = usbdev_release,
};
+
+static void usbdev_add(struct usb_device *dev)
+{
+ int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
+
+ dev->class_dev = class_device_create(usb_device_class, NULL,
+ MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
+ "usbdev%d.%d", dev->bus->busnum, dev->devnum);
+
+ dev->class_dev->class_data = dev;
+}
+
+static void usbdev_remove(struct usb_device *dev)
+{
+ class_device_unregister(dev->class_dev);
+}
+
+static int usbdev_notify(struct notifier_block *self, unsigned long action,
+ void *dev)
+{
+ switch (action) {
+ case USB_DEVICE_ADD:
+ usbdev_add(dev);
+ break;
+ case USB_DEVICE_REMOVE:
+ usbdev_remove(dev);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block usbdev_nb = {
+ .notifier_call = usbdev_notify,
+};
+
+static struct cdev usb_device_cdev = {
+ .kobj = {.name = "usb_device", },
+ .owner = THIS_MODULE,
+};
+
+int __init usbdev_init(void)
+{
+ int retval;
+
+ retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
+ "usb_device");
+ if (retval) {
+ err("unable to register minors for usb_device");
+ goto out;
+ }
+ cdev_init(&usb_device_cdev, &usbfs_device_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);
+ goto error_cdev;
+ }
+ usb_device_class = class_create(THIS_MODULE, "usb_device");
+ if (IS_ERR(usb_device_class)) {
+ err("unable to register usb_device class");
+ retval = PTR_ERR(usb_device_class);
+ goto error_class;
+ }
+
+ usb_register_notify(&usbdev_nb);
+
+out:
+ return retval;
+
+error_class:
+ usb_device_class = NULL;
+ cdev_del(&usb_device_cdev);
+
+error_cdev:
+ unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ goto out;
+}
+
+void usbdev_cleanup(void)
+{
+ usb_unregister_notify(&usbdev_nb);
+ class_destroy(usb_device_class);
+ cdev_del(&usb_device_cdev);
+ unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+}
+
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 65ca131cc44c..e695308095ae 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -17,7 +17,6 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
@@ -88,8 +87,6 @@ int usb_major_init(void)
goto out;
}
- devfs_mk_dir("usb");
-
out:
return error;
}
@@ -97,7 +94,6 @@ out:
void usb_major_cleanup(void)
{
class_destroy(usb_class);
- devfs_remove("usb");
unregister_chrdev(USB_MAJOR, "usb");
}
@@ -112,8 +108,7 @@ void usb_major_cleanup(void)
* enabled, the minor number will be based on the next available free minor,
* starting at the class_driver->minor_base.
*
- * This function also creates the devfs file for the usb device, if devfs
- * is enabled, and creates a usb class device in the sysfs tree.
+ * This function also creates a usb class device in the sysfs tree.
*
* usb_deregister_dev() must be called when the driver is done with
* the minor numbers given out by this function.
@@ -162,22 +157,20 @@ int usb_register_dev(struct usb_interface *intf,
intf->minor = minor;
- /* handle the devfs registration */
- snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
- devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
-
/* create a usb class device for this usb interface */
+ snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
temp = strrchr(name, '/');
if (temp && (temp[1] != 0x00))
++temp;
else
temp = name;
- intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+ intf->class_dev = class_device_create(usb_class, NULL,
+ MKDEV(USB_MAJOR, minor),
+ &intf->dev, "%s", temp);
if (IS_ERR(intf->class_dev)) {
spin_lock (&minor_lock);
usb_minors[intf->minor] = NULL;
spin_unlock (&minor_lock);
- devfs_remove (name);
retval = PTR_ERR(intf->class_dev);
}
exit:
@@ -195,9 +188,8 @@ EXPORT_SYMBOL(usb_register_dev);
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
- * This function also cleans up the devfs file for the usb device, if devfs
- * is enabled, and removes the usb class device from the sysfs tree.
- *
+ * This function also removes the usb class device from the sysfs tree.
+ *
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev(struct usb_interface *intf,
@@ -220,7 +212,6 @@ void usb_deregister_dev(struct usb_interface *intf,
spin_unlock (&minor_lock);
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
- devfs_remove (name);
class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
intf->class_dev = NULL;
intf->minor = -1;
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index fc056062c960..84d9e69329bb 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -30,6 +30,8 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/usb.h>
+
+#include "usb.h"
#include "hcd.h"
@@ -121,10 +123,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
}
}
-#ifdef CONFIG_PCI_NAMES
- hcd->product_desc = dev->pretty_name;
-#endif
-
pci_set_master (dev);
retval = usb_add_hcd (hcd, dev->irq, SA_SHIRQ);
@@ -201,6 +199,26 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
hcd = pci_get_drvdata(dev);
+ /* Root hub suspend should have stopped all downstream traffic,
+ * and all bus master traffic. And done so for both the interface
+ * and the stub usb_device (which we check here). But maybe it
+ * didn't; writing sysfs power/state files ignores such rules...
+ *
+ * We must ignore the FREEZE vs SUSPEND distinction here, because
+ * otherwise the swsusp will save (and restore) garbage state.
+ */
+ if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+ return -EBUSY;
+
+ if (hcd->driver->suspend) {
+ retval = hcd->driver->suspend(hcd, message);
+ if (retval) {
+ dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
+ retval);
+ goto done;
+ }
+ }
+
/* FIXME until the generic PM interfaces change a lot more, this
* can't use PCI D1 and D2 states. For example, the confusion
* between messages and states will need to vanish, and messages
@@ -219,41 +237,22 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
*/
has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
- switch (hcd->state) {
-
- /* entry if root hub wasn't yet suspended ... from sysfs,
- * without autosuspend, or if USB_SUSPEND isn't configured.
+ /* Downstream ports from this root hub should already be quiesced, so
+ * there will be no DMA activity. Now we can shut down the upstream
+ * link (except maybe for PME# resume signaling) and enter some PCI
+ * low power state, if the hardware allows.
*/
- case HC_STATE_RUNNING:
- hcd->state = HC_STATE_QUIESCING;
- retval = hcd->driver->suspend (hcd, message);
- if (retval) {
- dev_dbg (hcd->self.controller,
- "suspend fail, retval %d\n",
- retval);
- break;
- }
- hcd->state = HC_STATE_SUSPENDED;
- /* FALLTHROUGH */
+ if (hcd->state == HC_STATE_SUSPENDED) {
- /* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
- * controller and/or root hub will already have been suspended,
- * but it won't be ready for a PCI resume call.
- *
- * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
- * have been called, otherwise root hub timers still run ...
- */
- case HC_STATE_SUSPENDED:
/* no DMA or IRQs except when HC is active */
if (dev->current_state == PCI_D0) {
- free_irq (hcd->irq, hcd);
pci_save_state (dev);
pci_disable_device (dev);
}
if (!has_pci_pm) {
dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
- break;
+ goto done;
}
/* NOTE: dev->current_state becomes nonzero only here, and
@@ -264,26 +263,29 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
retval = pci_set_power_state (dev, PCI_D3hot);
if (retval == 0) {
dev_dbg (hcd->self.controller, "--> PCI D3\n");
- pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
- pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
- } else if (retval < 0) {
+
+ /* Ignore these return values. We rely on pci code to
+ * reject requests the hardware can't implement, rather
+ * than coding the same thing.
+ */
+ (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+ (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
+ } else {
dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
retval);
(void) usb_hcd_pci_resume (dev);
- break;
}
- break;
- default:
+
+ } else {
dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
hcd->state);
WARN_ON(1);
retval = -EINVAL;
- break;
}
- /* update power_state **ONLY** to make sysfs happier */
+done:
if (retval == 0)
- dev->dev.power.power_state = message;
+ dev->dev.power.power_state = PMSG_SUSPEND;
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -339,8 +341,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
dev->current_state);
}
#endif
- pci_enable_wake (dev, dev->current_state, 0);
- pci_enable_wake (dev, PCI_D3cold, 0);
+ /* yes, ignore these results too... */
+ (void) pci_enable_wake (dev, dev->current_state, 0);
+ (void) pci_enable_wake (dev, PCI_D3cold, 0);
} else {
/* Same basic cases: clean (powered/not), dirty */
dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -362,25 +365,17 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
dev->dev.power.power_state = PMSG_ON;
- hcd->state = HC_STATE_RESUMING;
hcd->saw_irq = 0;
- retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
- hcd->irq_descr, hcd);
- if (retval < 0) {
- dev_err (hcd->self.controller,
- "can't restore IRQ after resume!\n");
- usb_hc_died (hcd);
- return retval;
- }
- retval = hcd->driver->resume (hcd);
- if (!HC_IS_RUNNING (hcd->state)) {
- dev_dbg (hcd->self.controller,
- "resume fail, retval %d\n", retval);
- usb_hc_died (hcd);
+ if (hcd->driver->resume) {
+ retval = hcd->driver->resume(hcd);
+ if (retval) {
+ dev_err (hcd->self.controller,
+ "PCI post-resume error %d!\n", retval);
+ usb_hc_died (hcd);
+ }
}
- pci_enable_device(dev);
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_resume);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 79422a3b07bc..6c7ca5b08cd6 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -130,7 +130,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
0x00, 0x00, /* __le16 idVendor; */
0x00, 0x00, /* __le16 idProduct; */
@@ -153,7 +153,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
0x00, 0x00, /* __le16 idVendor; */
0x00, 0x00, /* __le16 idProduct; */
@@ -458,22 +458,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
default:
/* non-generic request */
- if (HC_IS_SUSPENDED (hcd->state))
- status = -EAGAIN;
- else {
- switch (typeReq) {
- case GetHubStatus:
- case GetPortStatus:
- len = 4;
- break;
- case GetHubDescriptor:
- len = sizeof (struct usb_hub_descriptor);
- break;
- }
- status = hcd->driver->hub_control (hcd,
- typeReq, wValue, wIndex,
- tbuf, wLength);
+ switch (typeReq) {
+ case GetHubStatus:
+ case GetPortStatus:
+ len = 4;
+ break;
+ case GetHubDescriptor:
+ len = sizeof (struct usb_hub_descriptor);
+ break;
}
+ status = hcd->driver->hub_control (hcd,
+ typeReq, wValue, wIndex,
+ tbuf, wLength);
break;
error:
/* "protocol stall" on error */
@@ -487,7 +483,7 @@ error:
"CTRL: TypeReq=0x%x val=0x%x "
"idx=0x%x len=%d ==> %d\n",
typeReq, wValue, wIndex,
- wLength, urb->status);
+ wLength, status);
}
}
if (len) {
@@ -748,10 +744,9 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{
struct usb_bus *bus;
- bus = kmalloc (sizeof *bus, GFP_KERNEL);
+ bus = kzalloc (sizeof *bus, GFP_KERNEL);
if (!bus)
return NULL;
- memset(bus, 0, sizeof(struct usb_bus));
usb_bus_init (bus);
bus->op = op;
return bus;
@@ -782,7 +777,8 @@ static int usb_register_bus(struct usb_bus *bus)
return -E2BIG;
}
- bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
+ bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
+ bus->controller, "usb_host%d", busnum);
if (IS_ERR(bus->class_dev)) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
@@ -795,8 +791,7 @@ static int usb_register_bus(struct usb_bus *bus)
list_add (&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock);
- usbfs_add_bus (bus);
- usbmon_notify_bus_add (bus);
+ usb_notify_add_bus(bus);
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
@@ -823,8 +818,7 @@ static void usb_deregister_bus (struct usb_bus *bus)
list_del (&bus->bus_list);
up (&usb_bus_list_lock);
- usbmon_notify_bus_remove (bus);
- usbfs_remove_bus (bus);
+ usb_notify_remove_bus(bus);
clear_bit (bus->busnum, busmap.busmap);
@@ -1112,7 +1106,7 @@ static void urb_unlink (struct urb *urb)
* expects usb_submit_urb() to have sanity checked and conditioned all
* inputs in the urb
*/
-static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
+static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
{
int status;
struct usb_hcd *hcd = urb->dev->bus->hcpriv;
@@ -1142,10 +1136,20 @@ static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
else switch (hcd->state) {
case HC_STATE_RUNNING:
case HC_STATE_RESUMING:
+doit:
usb_get_dev (urb->dev);
list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
break;
+ case HC_STATE_SUSPENDED:
+ /* HC upstream links (register access, wakeup signaling) can work
+ * even when the downstream links (and DMA etc) are quiesced; let
+ * usbcore talk to the root hub.
+ */
+ if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
+ && urb->dev->parent == NULL)
+ goto doit;
+ /* FALL THROUGH */
default:
status = -ESHUTDOWN;
break;
@@ -1293,12 +1297,6 @@ static int hcd_unlink_urb (struct urb *urb, int status)
goto done;
}
- /* running ~= hc unlink handshake works (irq, timer, etc)
- * halted ~= no unlink handshake is needed
- * suspended, resuming == should never happen
- */
- WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
-
/* insist the urb is still queued */
list_for_each(tmp, &ep->urb_list) {
if (tmp == &urb->urb_list)
@@ -1430,28 +1428,92 @@ rescan:
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM
-static int hcd_hub_suspend (struct usb_bus *bus)
+int hcd_bus_suspend (struct usb_bus *bus)
{
struct usb_hcd *hcd;
+ int status;
hcd = container_of (bus, struct usb_hcd, self);
- if (hcd->driver->hub_suspend)
- return hcd->driver->hub_suspend (hcd);
- return 0;
+ if (!hcd->driver->bus_suspend)
+ return -ENOENT;
+ hcd->state = HC_STATE_QUIESCING;
+ status = hcd->driver->bus_suspend (hcd);
+ if (status == 0)
+ hcd->state = HC_STATE_SUSPENDED;
+ else
+ dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+ "suspend", status);
+ return status;
}
-static int hcd_hub_resume (struct usb_bus *bus)
+int hcd_bus_resume (struct usb_bus *bus)
{
struct usb_hcd *hcd;
+ int status;
hcd = container_of (bus, struct usb_hcd, self);
- if (hcd->driver->hub_resume)
- return hcd->driver->hub_resume (hcd);
- return 0;
+ if (!hcd->driver->bus_resume)
+ return -ENOENT;
+ if (hcd->state == HC_STATE_RUNNING)
+ return 0;
+ hcd->state = HC_STATE_RESUMING;
+ status = hcd->driver->bus_resume (hcd);
+ if (status == 0)
+ hcd->state = HC_STATE_RUNNING;
+ else {
+ dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+ "resume", status);
+ usb_hc_died(hcd);
+ }
+ return status;
}
+/*
+ * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
+ * @hcd: host controller for this root hub
+ *
+ * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
+ * that the HCD's root hub polling is deactivated; and that the root's hub
+ * driver is suspended. HCDs may call this to autosuspend when their root
+ * hub's downstream ports are all inactive: unpowered, disconnected,
+ * disabled, or suspended.
+ *
+ * The HCD will autoresume on device connect change detection (using SRP
+ * or a D+/D- pullup). The HCD also autoresumes on remote wakeup signaling
+ * from any ports that are suspended (if that is enabled). In most cases,
+ * overcurrent signaling (on powered ports) will also start autoresume.
+ *
+ * Always called with IRQs blocked.
+ */
+void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
+{
+ struct urb *urb;
+
+ spin_lock (&hcd_root_hub_lock);
+ usb_suspend_root_hub (hcd->self.root_hub);
+
+ /* force status urb to complete/unlink while suspended */
+ if (hcd->status_urb) {
+ urb = hcd->status_urb;
+ urb->status = -ECONNRESET;
+ urb->hcpriv = NULL;
+ urb->actual_length = 0;
+
+ del_timer (&hcd->rh_timer);
+ hcd->poll_pending = 0;
+ hcd->status_urb = NULL;
+ } else
+ urb = NULL;
+ spin_unlock (&hcd_root_hub_lock);
+ hcd->state = HC_STATE_SUSPENDED;
+
+ if (urb)
+ usb_hcd_giveback_urb (hcd, urb, NULL);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
+
/**
* usb_hcd_resume_root_hub - called by HCD to resume its root hub
* @hcd: host controller for this root hub
@@ -1459,7 +1521,7 @@ static int hcd_hub_resume (struct usb_bus *bus)
* The USB host controller calls this function when its root hub is
* suspended (with the remote wakeup feature enabled) and a remote
* wakeup request is received. It queues a request for khubd to
- * resume the root hub.
+ * resume the root hub (that is, manage its downstream ports again).
*/
void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
{
@@ -1470,13 +1532,9 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
usb_resume_root_hub (hcd->self.root_hub);
spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
}
+EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
-#else
-void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
-{
-}
#endif
-EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
/*-------------------------------------------------------------------------*/
@@ -1529,10 +1587,6 @@ static struct usb_operations usb_hcd_operations = {
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
.disable = hcd_endpoint_disable,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = hcd_hub_suspend,
- .hub_resume = hcd_hub_resume,
-#endif
};
/*-------------------------------------------------------------------------*/
@@ -1606,7 +1660,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
return IRQ_NONE;
hcd->saw_irq = 1;
- if (hcd->state != start && hcd->state == HC_STATE_HALT)
+ if (hcd->state == HC_STATE_HALT)
usb_hc_died (hcd);
return IRQ_HANDLED;
}
@@ -1630,7 +1684,6 @@ void usb_hc_died (struct usb_hcd *hcd)
spin_lock_irqsave (&hcd_root_hub_lock, flags);
if (hcd->rh_registered) {
hcd->poll_rh = 0;
- del_timer(&hcd->rh_timer);
/* make khubd clean up old urbs and devices */
usb_set_device_state (hcd->self.root_hub,
@@ -1669,7 +1722,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
{
struct usb_hcd *hcd;
- hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
+ hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
if (!hcd) {
dev_dbg (dev, "hcd alloc failed\n");
return NULL;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 28055f95645b..24a62a2ff86d 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -142,22 +142,18 @@ struct hcd_timeout { /* timeouts we allocate */
struct usb_operations {
int (*get_frame_number) (struct usb_device *usb_dev);
- int (*submit_urb) (struct urb *urb, unsigned mem_flags);
+ int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
int (*unlink_urb) (struct urb *urb, int status);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
void (*disable)(struct usb_device *udev,
struct usb_host_endpoint *ep);
-
- /* global suspend/resume of bus */
- int (*hub_suspend)(struct usb_bus *);
- int (*hub_resume)(struct usb_bus *);
};
/* each driver provides one of these, and hardware init support */
@@ -182,12 +178,12 @@ struct hc_driver {
int (*start) (struct usb_hcd *hcd);
/* NOTE: these suspend/resume calls relate to the HC as
- * a whole, not just the root hub; they're for bus glue.
+ * a whole, not just the root hub; they're for PCI bus glue.
*/
- /* called after all devices were suspended */
+ /* called after suspending the hub, before entering D3 etc */
int (*suspend) (struct usb_hcd *hcd, pm_message_t message);
- /* called before any devices get resumed */
+ /* called after entering D0 (etc), before resuming the hub */
int (*resume) (struct usb_hcd *hcd);
/* cleanly make HCD stop writing memory and doing I/O */
@@ -200,7 +196,7 @@ struct hc_driver {
int (*urb_enqueue) (struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags);
+ gfp_t mem_flags);
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
@@ -212,8 +208,8 @@ struct hc_driver {
int (*hub_control) (struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
- int (*hub_suspend)(struct usb_hcd *);
- int (*hub_resume)(struct usb_hcd *);
+ int (*bus_suspend)(struct usb_hcd *);
+ int (*bus_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
void (*hub_irq_enable)(struct usb_hcd *);
/* Needed only if port-change IRQs are level-triggered */
@@ -247,7 +243,7 @@ int hcd_buffer_create (struct usb_hcd *hcd);
void hcd_buffer_destroy (struct usb_hcd *hcd);
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
- unsigned mem_flags, dma_addr_t *dma);
+ gfp_t mem_flags, dma_addr_t *dma);
void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
@@ -339,11 +335,11 @@ extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
* to preallocate bandwidth)
*/
#define USB2_HOST_DELAY 5 /* nsec, guess */
-#define HS_NSECS(bytes) ( ((55 * 8 * 2083)/1000) \
- + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+#define HS_NSECS(bytes) ( ((55 * 8 * 2083) \
+ + (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
-#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083)/1000) \
- + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
+ + (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
@@ -355,8 +351,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
-
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
@@ -378,6 +372,33 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
+#ifdef CONFIG_PM
+extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern int hcd_bus_suspend (struct usb_bus *bus);
+extern int hcd_bus_resume (struct usb_bus *bus);
+#else
+static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
+{
+ return;
+}
+
+static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+{
+ return;
+}
+
+static inline int hcd_bus_suspend(struct usb_bus *bus)
+{
+ return 0;
+}
+
+static inline int hcd_bus_resume (struct usb_bus *bus)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
/*
* USB device fs stuff
*/
@@ -388,23 +409,13 @@ extern int usb_find_interface_driver (struct usb_device *dev,
* these are expected to be called from the USB core/hub thread
* with the kernel lock held
*/
-extern void usbfs_add_bus(struct usb_bus *bus);
-extern void usbfs_remove_bus(struct usb_bus *bus);
-extern void usbfs_add_device(struct usb_device *dev);
-extern void usbfs_remove_device(struct usb_device *dev);
extern void usbfs_update_special (void);
-
extern int usbfs_init(void);
extern void usbfs_cleanup(void);
#else /* CONFIG_USB_DEVICEFS */
-static inline void usbfs_add_bus(struct usb_bus *bus) {}
-static inline void usbfs_remove_bus(struct usb_bus *bus) {}
-static inline void usbfs_add_device(struct usb_device *dev) {}
-static inline void usbfs_remove_device(struct usb_device *dev) {}
static inline void usbfs_update_special (void) {}
-
static inline int usbfs_init(void) { return 0; }
static inline void usbfs_cleanup(void) { }
@@ -419,8 +430,6 @@ struct usb_mon_operations {
void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
- void (*bus_add)(struct usb_bus *bus);
- void (*bus_remove)(struct usb_bus *bus);
};
extern struct usb_mon_operations *mon_ops;
@@ -443,18 +452,6 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
if (bus->monitored)
(*mon_ops->urb_complete)(bus, urb);
}
-
-static inline void usbmon_notify_bus_add(struct usb_bus *bus)
-{
- if (mon_ops)
- (*mon_ops->bus_add)(bus);
-}
-
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
-{
- if (mon_ops)
- (*mon_ops->bus_remove)(bus);
-}
int usb_mon_register(struct usb_mon_operations *ops);
void usb_mon_deregister(void);
@@ -465,8 +462,6 @@ static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
int error) {}
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
-static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
#endif /* CONFIG_USB_MON */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c3e46d24a37e..256d9f698715 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -435,23 +435,33 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
static void hub_power_on(struct usb_hub *hub)
{
int port1;
+ unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
+ u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
/* if hub supports power switching, enable power on each port */
- if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
+ if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
dev_dbg(hub->intfdev, "enabling power on all ports\n");
for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
set_port_feature(hub->hdev, port1,
USB_PORT_FEAT_POWER);
}
- /* Wait for power to be enabled */
- msleep(hub->descriptor->bPwrOn2PwrGood * 2);
+ /* Wait at least 100 msec for power to become stable */
+ msleep(max(pgood_delay, (unsigned) 100));
}
-static void hub_quiesce(struct usb_hub *hub)
+static inline void __hub_quiesce(struct usb_hub *hub)
{
- /* stop khubd and related activity */
+ /* (nonblocking) khubd and related activity won't re-trigger */
hub->quiescing = 1;
+ hub->activating = 0;
+ hub->resume_root_hub = 0;
+}
+
+static void hub_quiesce(struct usb_hub *hub)
+{
+ /* (blocking) stop khubd and related activity */
+ __hub_quiesce(hub);
usb_kill_urb(hub->urb);
if (hub->has_indicators)
cancel_delayed_work(&hub->leds);
@@ -465,6 +475,7 @@ static void hub_activate(struct usb_hub *hub)
hub->quiescing = 0;
hub->activating = 1;
+ hub->resume_root_hub = 0;
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -492,12 +503,30 @@ static int hub_hub_status(struct usb_hub *hub,
return ret;
}
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+{
+ struct usb_device *hdev = hub->hdev;
+ int ret;
+
+ if (hdev->children[port1-1] && set_state) {
+ usb_set_device_state(hdev->children[port1-1],
+ USB_STATE_NOTATTACHED);
+ }
+ ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+ if (ret)
+ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+ port1, ret);
+
+ return ret;
+}
+
static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *hdev = hub->hdev;
struct device *hub_dev = hub->intfdev;
u16 hubstatus, hubchange;
+ u16 wHubCharacteristics;
unsigned int pipe;
int maxp, ret;
char *message;
@@ -543,9 +572,9 @@ static int hub_configure(struct usb_hub *hub,
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
(hdev->maxchild == 1) ? "" : "s");
- le16_to_cpus(&hub->descriptor->wHubCharacteristics);
+ wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
- if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) {
+ if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
int i;
char portstr [USB_MAXCHILDREN + 1];
@@ -558,7 +587,7 @@ static int hub_configure(struct usb_hub *hub,
} else
dev_dbg(hub_dev, "standalone hub\n");
- switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
+ switch (wHubCharacteristics & HUB_CHAR_LPSM) {
case 0x00:
dev_dbg(hub_dev, "ganged power switching\n");
break;
@@ -571,7 +600,7 @@ static int hub_configure(struct usb_hub *hub,
break;
}
- switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
+ switch (wHubCharacteristics & HUB_CHAR_OCPM) {
case 0x00:
dev_dbg(hub_dev, "global over-current protection\n");
break;
@@ -610,24 +639,38 @@ static int hub_configure(struct usb_hub *hub,
break;
}
- switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
- case 0x00:
- if (hdev->descriptor.bDeviceProtocol != 0)
- dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n");
+ /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
+ switch (wHubCharacteristics & HUB_CHAR_TTTT) {
+ case HUB_TTTT_8_BITS:
+ if (hdev->descriptor.bDeviceProtocol != 0) {
+ hub->tt.think_time = 666;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 8, hub->tt.think_time);
+ }
break;
- case 0x20:
- dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n");
+ case HUB_TTTT_16_BITS:
+ hub->tt.think_time = 666 * 2;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 16, hub->tt.think_time);
break;
- case 0x40:
- dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n");
+ case HUB_TTTT_24_BITS:
+ hub->tt.think_time = 666 * 3;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 24, hub->tt.think_time);
break;
- case 0x60:
- dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n");
+ case HUB_TTTT_32_BITS:
+ hub->tt.think_time = 666 * 4;
+ dev_dbg(hub_dev, "TT requires at most %d "
+ "FS bit times (%d ns)\n",
+ 32, hub->tt.think_time);
break;
}
/* probe() zeroes hub->indicator[] */
- if (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) {
+ if (wHubCharacteristics & HUB_CHAR_PORTIND) {
hub->has_indicators = 1;
dev_dbg(hub_dev, "Port indicators are supported\n");
}
@@ -672,7 +715,7 @@ static int hub_configure(struct usb_hub *hub,
(hubstatus & HUB_STATUS_LOCAL_POWER)
? "lost (inactive)" : "good");
- if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0)
+ if ((wHubCharacteristics & HUB_CHAR_OCPM) == 0)
dev_dbg(hub_dev, "%sover-current condition exists\n",
(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
@@ -712,20 +755,36 @@ fail:
static unsigned highspeed_hubs;
+/* Called after the hub driver is unbound from a hub with children */
+static void hub_remove_children_work(void *__hub)
+{
+ struct usb_hub *hub = __hub;
+ struct usb_device *hdev = hub->hdev;
+ int i;
+
+ kfree(hub);
+
+ usb_lock_device(hdev);
+ for (i = 0; i < hdev->maxchild; ++i) {
+ if (hdev->children[i])
+ usb_disconnect(&hdev->children[i]);
+ }
+ usb_unlock_device(hdev);
+ usb_put_dev(hdev);
+}
+
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev;
+ int n, port1;
- if (!hub)
- return;
+ usb_set_intfdata (intf, NULL);
hdev = hub->hdev;
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
- usb_set_intfdata (intf, NULL);
-
hub_quiesce(hub);
usb_free_urb(hub->urb);
hub->urb = NULL;
@@ -746,8 +805,27 @@ static void hub_disconnect(struct usb_interface *intf)
hub->buffer = NULL;
}
- /* Free the memory */
- kfree(hub);
+ /* If there are any children then this is an unbind only, not a
+ * physical disconnection. The active ports must be disabled
+ * and later on we must call usb_disconnect(). We can't call
+ * it now because we may not hold the hub's device lock.
+ */
+ n = 0;
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ if (hdev->children[port1 - 1]) {
+ ++n;
+ hub_port_disable(hub, port1, 1);
+ }
+ }
+
+ if (n == 0)
+ kfree(hub);
+ else {
+ /* Reuse the hub->leds work_struct for our own purposes */
+ INIT_WORK(&hub->leds, hub_remove_children_work, hub);
+ schedule_work(&hub->leds);
+ usb_get_dev(hdev);
+ }
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -787,14 +865,12 @@ descriptor_error:
/* We found a hub */
dev_info (&intf->dev, "USB hub found\n");
- hub = kmalloc(sizeof(*hub), GFP_KERNEL);
+ hub = kzalloc(sizeof(*hub), GFP_KERNEL);
if (!hub) {
dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
return -ENOMEM;
}
- memset(hub, 0, sizeof(*hub));
-
INIT_LIST_HEAD(&hub->event_list);
hub->intfdev = &intf->dev;
hub->hdev = hdev;
@@ -953,9 +1029,15 @@ void usb_set_device_state(struct usb_device *udev,
spin_lock_irqsave(&device_state_lock, flags);
if (udev->state == USB_STATE_NOTATTACHED)
; /* do nothing */
- else if (new_state != USB_STATE_NOTATTACHED)
+ else if (new_state != USB_STATE_NOTATTACHED) {
udev->state = new_state;
- else
+ if (new_state == USB_STATE_CONFIGURED)
+ device_init_wakeup(&udev->dev,
+ (udev->actconfig->desc.bmAttributes
+ & USB_CONFIG_ATT_WAKEUP));
+ else if (new_state != USB_STATE_SUSPENDED)
+ device_init_wakeup(&udev->dev, 0);
+ } else
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
}
@@ -1044,13 +1126,14 @@ void usb_disconnect(struct usb_device **pdev)
*/
usb_disable_device(udev, 0);
+ usb_notify_remove_device(udev);
+
/* Free the device number, remove the /proc/bus/usb entry and
* the sysfs attributes, and delete the parent's children[]
* (or root_hub) pointer.
*/
dev_dbg (&udev->dev, "unregistering device\n");
release_address(udev);
- usbfs_remove_device(udev);
usb_remove_sysfs_dev_files(udev);
/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1121,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
{}
#endif
-static void get_string(struct usb_device *udev, char **string, int index)
-{
- char *buf;
-
- if (!index)
- return;
- buf = kmalloc(256, GFP_KERNEL);
- if (!buf)
- return;
- if (usb_string(udev, index, buf, 256) > 0)
- *string = buf;
- else
- kfree(buf);
-}
-
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
@@ -1174,9 +1242,10 @@ int usb_new_device(struct usb_device *udev)
}
/* read the standard strings and cache them if present */
- get_string(udev, &udev->product, udev->descriptor.iProduct);
- get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
- get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
+ udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
+ udev->manufacturer = usb_cache_string(udev,
+ udev->descriptor.iManufacturer);
+ udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
/* Tell the world! */
dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
@@ -1248,11 +1317,9 @@ int usb_new_device(struct usb_device *udev)
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
- static int __usb_suspend_device (struct usb_device *,
- int port1, pm_message_t state);
- err = __usb_suspend_device(udev,
- udev->bus->otg_port,
- PMSG_SUSPEND);
+ static int __usb_suspend_device(struct usb_device *,
+ int port1);
+ err = __usb_suspend_device(udev, udev->bus->otg_port);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
@@ -1288,9 +1355,8 @@ int usb_new_device(struct usb_device *udev)
}
/* USB device state == configured ... usable */
+ usb_notify_add_device(udev);
- /* add a /proc/bus/usb entry */
- usbfs_add_device(udev);
return 0;
fail:
@@ -1392,7 +1458,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
port1, status);
else {
status = hub_port_wait_reset(hub, port1, udev, delay);
- if (status)
+ if (status && status != -ENOTCONN)
dev_dbg(hub->intfdev,
"port_wait_reset: err = %d\n",
status);
@@ -1401,8 +1467,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
/* return on disconnect or reset */
switch (status) {
case 0:
- /* TRSTRCY = 10 ms */
- msleep(10);
+ /* TRSTRCY = 10 ms; plus some extra */
+ msleep(10 + 40);
/* FALL THROUGH */
case -ENOTCONN:
case -ENODEV:
@@ -1428,23 +1494,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status;
}
-static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
-{
- struct usb_device *hdev = hub->hdev;
- int ret;
-
- if (hdev->children[port1-1] && set_state) {
- usb_set_device_state(hdev->children[port1-1],
- USB_STATE_NOTATTACHED);
- }
- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
- if (ret)
- dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
- port1, ret);
-
- return ret;
-}
-
/*
* Disable a port and mark a logical connnect-change event, so that some
* time later khubd will disconnect() any existing usb_device on the port
@@ -1458,7 +1507,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
/* FIXME let caller ask to power down the port:
* - some devices won't enumerate without a VBUS power cycle
* - SRP saves power that way
- * - usb_suspend_device(dev, PMSG_SUSPEND)
+ * - ... new call, TBD ...
* That's easy if this hub can switch power per-port, and
* khubd reactivates the port later (timer, SRP, etc).
* Powerdown must be optional, because of reset/DFU.
@@ -1494,11 +1543,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* NOTE: OTG devices may issue remote wakeup (or SRP) even when
* we don't explicitly enable it here.
*/
- if (udev->actconfig
- // && FIXME (remote wakeup enabled on this bus)
- // ... currently assuming it's always appropriate
- && (udev->actconfig->desc.bmAttributes
- & USB_CONFIG_ATT_WAKEUP) != 0) {
+ if (device_may_wakeup(&udev->dev)) {
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
USB_DEVICE_REMOTE_WAKEUP, 0,
@@ -1544,11 +1589,14 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* Other than re-initializing the hub (plug/unplug, except for root hubs),
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
*/
-static int __usb_suspend_device (struct usb_device *udev, int port1,
- pm_message_t state)
+static int __usb_suspend_device (struct usb_device *udev, int port1)
{
- int status;
+ int status = 0;
/* caller owns the udev device lock */
if (port1 < 0)
@@ -1559,95 +1607,39 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
return 0;
}
- /* suspend interface drivers; if this is a hub, it
- * suspends the child devices
- */
+ /* all interfaces must already be suspended */
if (udev->actconfig) {
int i;
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *intf;
- struct usb_driver *driver;
intf = udev->actconfig->interface[i];
- if (state <= intf->dev.power.power_state)
- continue;
- if (!intf->dev.driver)
- continue;
- driver = to_usb_driver(intf->dev.driver);
-
- if (driver->suspend) {
- status = driver->suspend(intf, state);
- if (intf->dev.power.power_state != state
- || status)
- dev_err(&intf->dev,
- "suspend %d fail, code %d\n",
- state, status);
- }
-
- /* only drivers with suspend() can ever resume();
- * and after power loss, even they won't.
- * bus_rescan_devices() can rebind drivers later.
- *
- * FIXME the PM core self-deadlocks when unbinding
- * drivers during suspend/resume ... everything grabs
- * dpm_sem (not a spinlock, ugh). we want to unbind,
- * since we know every driver's probe/disconnect works
- * even for drivers that can't suspend.
- */
- if (!driver->suspend || state > PM_SUSPEND_MEM) {
-#if 1
- dev_warn(&intf->dev, "resume is unsafe!\n");
-#else
- down_write(&usb_bus_type.rwsem);
- device_release_driver(&intf->dev);
- up_write(&usb_bus_type.rwsem);
-#endif
+ if (is_active(intf)) {
+ dev_dbg(&intf->dev, "nyet suspended\n");
+ return -EBUSY;
}
}
}
- /*
- * FIXME this needs port power off call paths too, to help force
- * USB into the "generic" PM model. At least for devices on
- * ports that aren't using ganged switching (usually root hubs).
- *
- * NOTE: SRP-capable links should adopt more aggressive poweroff
- * policies (when HNP doesn't apply) once we have mechanisms to
- * turn power back on! (Likely not before 2.7...)
+ /* we only change a device's upstream USB link.
+ * root hubs have no upstream USB link.
*/
- if (state > PM_SUSPEND_MEM) {
- dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
- }
-
- /* "global suspend" of the HC-to-USB interface (root hub), or
- * "selective suspend" of just one hub-device link.
- */
- if (!udev->parent) {
- struct usb_bus *bus = udev->bus;
- if (bus && bus->op->hub_suspend) {
- status = bus->op->hub_suspend (bus);
- if (status == 0) {
- dev_dbg(&udev->dev, "usb suspend\n");
- usb_set_device_state(udev,
- USB_STATE_SUSPENDED);
- }
- } else
- status = -EOPNOTSUPP;
- } else
+ if (udev->parent)
status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
udev);
if (status == 0)
- udev->dev.power.power_state = state;
+ udev->dev.power.power_state = PMSG_SUSPEND;
return status;
}
-/**
+#endif
+
+/*
* usb_suspend_device - suspend a usb device
* @udev: device that's no longer in active use
- * @state: PMSG_SUSPEND to suspend
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
*
* Suspends a USB device that isn't in active use, conserving power.
* Devices may wake out of a suspend, if anything important happens,
@@ -1655,37 +1647,50 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
* suspend by the host, using usb_resume_device(). It's also routine
* to disconnect devices while they are suspended.
*
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
* Suspending OTG devices may trigger HNP, if that's been enabled
* between a pair of dual-role devices. That will change roles, such
* as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
*
* Returns 0 on success, else negative errno.
*/
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
+int usb_suspend_device(struct usb_device *udev)
{
+#ifdef CONFIG_USB_SUSPEND
int port1, status;
port1 = locktree(udev);
if (port1 < 0)
return port1;
- status = __usb_suspend_device(udev, port1, state);
+ status = __usb_suspend_device(udev, port1);
usb_unlock_device(udev);
return status;
+#else
+ /* NOTE: udev->state unchanged, it's not lying ... */
+ udev->dev.power.power_state = PMSG_SUSPEND;
+ return 0;
+#endif
}
+EXPORT_SYMBOL_GPL(usb_suspend_device);
/*
+ * If the USB "suspend" state is in use (rather than "global suspend"),
+ * many devices will be individually taken out of suspend state using
+ * special" resume" signaling. These routines kick in shortly after
* hardware resume signaling is finished, either because of selective
* resume (by host) or remote wakeup (by device) ... now see what changed
* in the tree that's rooted at this device.
*/
-static int finish_port_resume(struct usb_device *udev)
+static int finish_device_resume(struct usb_device *udev)
{
int status;
u16 devstatus;
/* caller owns the udev device lock */
- dev_dbg(&udev->dev, "usb resume\n");
+ dev_dbg(&udev->dev, "finish resume\n");
/* usb ch9 identifies four variants of SUSPENDED, based on what
* state the device resumes to. Linux currently won't see the
@@ -1695,7 +1700,6 @@ static int finish_port_resume(struct usb_device *udev)
usb_set_device_state(udev, udev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
- udev->dev.power.power_state = PMSG_ON;
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
@@ -1708,9 +1712,11 @@ static int finish_port_resume(struct usb_device *udev)
status);
else if (udev->actconfig) {
unsigned i;
+ int (*resume)(struct device *);
le16_to_cpus(&devstatus);
- if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+ if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+ && udev->parent) {
status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE,
@@ -1726,33 +1732,11 @@ static int finish_port_resume(struct usb_device *udev)
}
/* resume interface drivers; if this is a hub, it
- * resumes the child devices
+ * may have a child resume event to deal with soon
*/
- for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *intf;
- struct usb_driver *driver;
-
- intf = udev->actconfig->interface[i];
- if (intf->dev.power.power_state == PMSG_ON)
- continue;
- if (!intf->dev.driver) {
- /* FIXME maybe force to alt 0 */
- continue;
- }
- driver = to_usb_driver(intf->dev.driver);
-
- /* bus_rescan_devices() may rebind drivers */
- if (!driver->resume)
- continue;
-
- /* can we do better than just logging errors? */
- status = driver->resume(intf);
- if (intf->dev.power.power_state != PMSG_ON
- || status)
- dev_dbg(&intf->dev,
- "resume fail, state %d code %d\n",
- intf->dev.power.power_state, status);
- }
+ resume = udev->dev.bus->resume;
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
+ (void) resume(&udev->actconfig->interface[i]->dev);
status = 0;
} else if (udev->devnum <= 0) {
@@ -1762,6 +1746,8 @@ static int finish_port_resume(struct usb_device *udev)
return status;
}
+#ifdef CONFIG_USB_SUSPEND
+
static int
hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
{
@@ -1807,7 +1793,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
/* TRSMRCY = 10 msec */
msleep(10);
if (udev)
- status = finish_port_resume(udev);
+ status = finish_device_resume(udev);
}
}
if (status < 0)
@@ -1816,12 +1802,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
return status;
}
-static int hub_resume (struct usb_interface *intf);
+#endif
-/**
+/*
* usb_resume_device - re-activate a suspended usb device
* @udev: device to re-activate
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
*
* This will re-activate the suspended device, increasing power usage
* while letting drivers communicate again with its endpoints.
@@ -1839,35 +1825,22 @@ int usb_resume_device(struct usb_device *udev)
if (port1 < 0)
return port1;
- /* "global resume" of the HC-to-USB interface (root hub), or
- * selective resume of one hub-to-device port
- */
- if (!udev->parent) {
- struct usb_bus *bus = udev->bus;
- if (bus && bus->op->hub_resume) {
- status = bus->op->hub_resume (bus);
+#ifdef CONFIG_USB_SUSPEND
+ /* selective resume of one downstream hub-to-device port */
+ if (udev->parent) {
+ if (udev->state == USB_STATE_SUSPENDED) {
+ // NOTE swsusp may bork us, device state being wrong...
+ // NOTE this fails if parent is also suspended...
+ status = hub_port_resume(hdev_to_hub(udev->parent),
+ port1, udev);
} else
- status = -EOPNOTSUPP;
- if (status == 0) {
- dev_dbg(&udev->dev, "usb resume\n");
- /* TRSMRCY = 10 msec */
- msleep(10);
- usb_set_device_state (udev, USB_STATE_CONFIGURED);
- udev->dev.power.power_state = PMSG_ON;
- status = hub_resume (udev
- ->actconfig->interface[0]);
- }
- } else if (udev->state == USB_STATE_SUSPENDED) {
- // NOTE this fails if parent is also suspended...
- status = hub_port_resume(hdev_to_hub(udev->parent),
- port1, udev);
- } else {
- status = 0;
- }
- if (status < 0) {
+ status = 0;
+ } else
+#endif
+ status = finish_device_resume(udev);
+ if (status < 0)
dev_dbg(&udev->dev, "can't resume, status %d\n",
status);
- }
usb_unlock_device(udev);
@@ -1884,6 +1857,8 @@ static int remote_wakeup(struct usb_device *udev)
{
int status = 0;
+#ifdef CONFIG_USB_SUSPEND
+
/* don't repeat RESUME sequence if this device
* was already woken up by some other task
*/
@@ -1892,38 +1867,52 @@ static int remote_wakeup(struct usb_device *udev)
dev_dbg(&udev->dev, "RESUME (wakeup)\n");
/* TRSMRCY = 10 msec */
msleep(10);
- status = finish_port_resume(udev);
+ status = finish_device_resume(udev);
}
up(&udev->serialize);
+#endif
return status;
}
-static int hub_suspend(struct usb_interface *intf, pm_message_t state)
+static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
- int status;
-
- /* stop khubd and related activity */
- hub_quiesce(hub);
- /* then suspend every port */
+ /* fail if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
udev = hdev->children [port1-1];
- if (!udev)
- continue;
- down(&udev->serialize);
- status = __usb_suspend_device(udev, port1, state);
- up(&udev->serialize);
- if (status < 0)
- dev_dbg(&intf->dev, "suspend port %d --> %d\n",
- port1, status);
+ if (udev && (udev->dev.power.power_state.event
+ == PM_EVENT_ON
+#ifdef CONFIG_USB_SUSPEND
+ || udev->state != USB_STATE_SUSPENDED
+#endif
+ )) {
+ dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+ return -EBUSY;
+ }
}
- intf->dev.power.power_state = state;
+ /* "global suspend" of the downstream HC-to-USB interface */
+ if (!hdev->parent) {
+ struct usb_bus *bus = hdev->bus;
+ if (bus) {
+ int status = hcd_bus_suspend (bus);
+
+ if (status != 0) {
+ dev_dbg(&hdev->dev, "'global' suspend %d\n",
+ status);
+ return status;
+ }
+ } else
+ return -EOPNOTSUPP;
+ }
+
+ /* stop khubd and related activity */
+ hub_quiesce(hub);
return 0;
}
@@ -1931,11 +1920,35 @@ static int hub_resume(struct usb_interface *intf)
{
struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_get_intfdata (intf);
- unsigned port1;
int status;
- if (intf->dev.power.power_state == PM_SUSPEND_ON)
- return 0;
+ /* "global resume" of the downstream HC-to-USB interface */
+ if (!hdev->parent) {
+ struct usb_bus *bus = hdev->bus;
+ if (bus) {
+ status = hcd_bus_resume (bus);
+ if (status) {
+ dev_dbg(&intf->dev, "'global' resume %d\n",
+ status);
+ return status;
+ }
+ } else
+ return -EOPNOTSUPP;
+ if (status == 0) {
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+ }
+ }
+
+ hub_activate(hub);
+
+ /* REVISIT: this recursion probably shouldn't exist. Remove
+ * this code sometime, after retesting with different root and
+ * external hubs.
+ */
+#ifdef CONFIG_USB_SUSPEND
+ {
+ unsigned port1;
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
@@ -1961,7 +1974,7 @@ static int hub_resume(struct usb_interface *intf)
if (portstat & USB_PORT_STAT_SUSPEND)
status = hub_port_resume(hub, port1, udev);
else {
- status = finish_port_resume(udev);
+ status = finish_device_resume(udev);
if (status < 0) {
dev_dbg(&intf->dev, "resume port %d --> %d\n",
port1, status);
@@ -1970,43 +1983,31 @@ static int hub_resume(struct usb_interface *intf)
}
up(&udev->serialize);
}
- intf->dev.power.power_state = PMSG_ON;
-
- hub->resume_root_hub = 0;
- hub_activate(hub);
+ }
+#endif
return 0;
}
-void usb_resume_root_hub(struct usb_device *hdev)
+void usb_suspend_root_hub(struct usb_device *hdev)
{
struct usb_hub *hub = hdev_to_hub(hdev);
- hub->resume_root_hub = 1;
- kick_khubd(hub);
+ /* This also makes any led blinker stop retriggering. We're called
+ * from irq, so the blinker might still be scheduled. Caller promises
+ * that the root hub status URB will be canceled.
+ */
+ __hub_quiesce(hub);
+ mark_quiesced(to_usb_interface(hub->intfdev));
}
-#else /* !CONFIG_USB_SUSPEND */
-
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
+void usb_resume_root_hub(struct usb_device *hdev)
{
- return 0;
-}
+ struct usb_hub *hub = hdev_to_hub(hdev);
-int usb_resume_device(struct usb_device *udev)
-{
- return 0;
+ hub->resume_root_hub = 1;
+ kick_khubd(hub);
}
-#define hub_suspend NULL
-#define hub_resume NULL
-#define remote_wakeup(x) 0
-
-#endif /* CONFIG_USB_SUSPEND */
-
-EXPORT_SYMBOL(usb_suspend_device);
-EXPORT_SYMBOL(usb_resume_device);
-
-
/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
*
@@ -2415,6 +2416,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
{
struct usb_device *hdev = hub->hdev;
struct device *hub_dev = hub->intfdev;
+ u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
int status, i;
dev_dbg (hub_dev,
@@ -2452,8 +2454,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
/* maybe switch power back on (e.g. root hub was reset) */
- if ((hub->descriptor->wHubCharacteristics
- & HUB_CHAR_LPSM) < 2
+ if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
@@ -2632,21 +2633,28 @@ static void hub_events(void)
intf = to_usb_interface(hub->intfdev);
hub_dev = &intf->dev;
- dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
+ i = hub->resume_root_hub;
+
+ dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
hdev->state, hub->descriptor
? hub->descriptor->bNbrPorts
: 0,
/* NOTE: expects max 15 ports... */
(u16) hub->change_bits[0],
- (u16) hub->event_bits[0]);
+ (u16) hub->event_bits[0],
+ i ? ", resume root" : "");
usb_get_intf(intf);
- i = hub->resume_root_hub;
spin_unlock_irq(&hub_event_lock);
- /* Is this is a root hub wanting to be resumed? */
- if (i)
- usb_resume_device(hdev);
+ /* Is this is a root hub wanting to reactivate the downstream
+ * ports? If so, be sure the interface resumes even if its
+ * stub "device" node was never suspended.
+ */
+ if (i) {
+ dpm_runtime_resume(&hdev->dev);
+ dpm_runtime_resume(&intf->dev);
+ }
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 53bf5649621e..bf23f8978024 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -131,7 +131,7 @@ struct usb_hub_descriptor {
__u8 bDescLength;
__u8 bDescriptorType;
__u8 bNbrPorts;
- __u16 wHubCharacteristics;
+ __le16 wHubCharacteristics;
__u8 bPwrOn2PwrGood;
__u8 bHubContrCurrent;
/* add 1 bit for hub status change; round to bytes */
@@ -157,6 +157,12 @@ enum hub_led_mode {
struct usb_device;
+/* Transaction Translator Think Times, in bits */
+#define HUB_TTTT_8_BITS 0x00
+#define HUB_TTTT_16_BITS 0x20
+#define HUB_TTTT_24_BITS 0x40
+#define HUB_TTTT_32_BITS 0x60
+
/*
* As of USB 2.0, full/low speed devices are segregated into trees.
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
@@ -170,6 +176,7 @@ struct usb_device;
struct usb_tt {
struct usb_device *hub; /* upstream highspeed hub */
int multi; /* true means one TT per port */
+ unsigned think_time; /* think time in ns */
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
spinlock_t lock;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index c3e3a95d3804..12f490fdee8f 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -39,6 +39,7 @@
#include <linux/usbdevice_fs.h>
#include <linux/smp_lock.h>
#include <linux/parser.h>
+#include <linux/notifier.h>
#include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h"
@@ -619,7 +620,7 @@ void usbfs_update_special (void)
}
}
-void usbfs_add_bus(struct usb_bus *bus)
+static void usbfs_add_bus(struct usb_bus *bus)
{
struct dentry *parent;
char name[8];
@@ -642,12 +643,9 @@ void usbfs_add_bus(struct usb_bus *bus)
err ("error creating usbfs bus entry");
return;
}
-
- usbfs_update_special();
- usbfs_conn_disc_event();
}
-void usbfs_remove_bus(struct usb_bus *bus)
+static void usbfs_remove_bus(struct usb_bus *bus)
{
if (bus->usbfs_dentry) {
fs_remove_file (bus->usbfs_dentry);
@@ -659,12 +657,9 @@ void usbfs_remove_bus(struct usb_bus *bus)
remove_special_files();
num_buses = 0;
}
-
- usbfs_update_special();
- usbfs_conn_disc_event();
}
-void usbfs_add_device(struct usb_device *dev)
+static void usbfs_add_device(struct usb_device *dev)
{
char name[8];
int i;
@@ -690,12 +685,9 @@ void usbfs_add_device(struct usb_device *dev)
}
if (dev->usbfs_dentry->d_inode)
dev->usbfs_dentry->d_inode->i_size = i_size;
-
- usbfs_update_special();
- usbfs_conn_disc_event();
}
-void usbfs_remove_device(struct usb_device *dev)
+static void usbfs_remove_device(struct usb_device *dev)
{
struct dev_state *ds;
struct siginfo sinfo;
@@ -713,13 +705,36 @@ void usbfs_remove_device(struct usb_device *dev)
sinfo.si_errno = EPIPE;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = ds->disccontext;
- send_sig_info(ds->discsignr, &sinfo, ds->disctask);
+ kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid);
}
}
+}
+
+static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
+{
+ switch (action) {
+ case USB_DEVICE_ADD:
+ usbfs_add_device(dev);
+ break;
+ case USB_DEVICE_REMOVE:
+ usbfs_remove_device(dev);
+ break;
+ case USB_BUS_ADD:
+ usbfs_add_bus(dev);
+ break;
+ case USB_BUS_REMOVE:
+ usbfs_remove_bus(dev);
+ }
+
usbfs_update_special();
usbfs_conn_disc_event();
+ return NOTIFY_OK;
}
+static struct notifier_block usbfs_nb = {
+ .notifier_call = usbfs_notify,
+};
+
/* --------------------------------------------------------------------- */
static struct proc_dir_entry *usbdir = NULL;
@@ -728,15 +743,11 @@ int __init usbfs_init(void)
{
int retval;
- retval = usb_register(&usbfs_driver);
+ retval = register_filesystem(&usb_fs_type);
if (retval)
return retval;
- retval = register_filesystem(&usb_fs_type);
- if (retval) {
- usb_deregister(&usbfs_driver);
- return retval;
- }
+ usb_register_notify(&usbfs_nb);
/* create mount point for usbfs */
usbdir = proc_mkdir("usb", proc_bus);
@@ -746,7 +757,7 @@ int __init usbfs_init(void)
void usbfs_cleanup(void)
{
- usb_deregister(&usbfs_driver);
+ usb_unregister_notify(&usbfs_nb);
unregister_filesystem(&usb_fs_type);
if (usbdir)
remove_proc_entry("usb", proc_bus);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 88d1b376f67c..644a3d4f12aa 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -48,7 +48,6 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
init_completion(&done);
urb->context = &done;
- urb->transfer_flags |= URB_ASYNC_UNLINK;
urb->actual_length = 0;
status = usb_submit_urb(urb, GFP_NOIO);
@@ -188,21 +187,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
* If a thread in your driver uses this call, make sure your disconnect()
* method can wait for it to complete. Since you don't have a handle on
* the URB used, you can't cancel the request.
+ *
+ * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
+ * ioctl, users are forced to abuse this routine by using it to submit
+ * URBs for interrupt endpoints. We will take the liberty of creating
+ * an interrupt URB (with the default interval) if the target is an
+ * interrupt endpoint.
*/
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout)
{
struct urb *urb;
+ struct usb_host_endpoint *ep;
- if (len < 0)
+ ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
+ [usb_pipeendpoint(pipe)];
+ if (!ep || len < 0)
return -EINVAL;
- urb=usb_alloc_urb(0, GFP_KERNEL);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
- usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, NULL);
+ 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_api_blocking_completion, NULL,
+ ep->desc.bInterval);
+ } else
+ usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+ usb_api_blocking_completion, NULL);
return usb_start_wait_urb(urb, timeout, actual_length);
}
@@ -266,7 +281,9 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
continue;
if (found) {
status = usb_unlink_urb (io->urbs [i]);
- if (status != -EINPROGRESS && status != -EBUSY)
+ if (status != -EINPROGRESS
+ && status != -ENODEV
+ && status != -EBUSY)
dev_err (&io->dev->dev,
"%s, unlink --> %d\n",
__FUNCTION__, status);
@@ -320,7 +337,7 @@ int usb_sg_init (
struct scatterlist *sg,
int nents,
size_t length,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
int i;
@@ -357,8 +374,7 @@ int usb_sg_init (
if (!io->urbs)
goto nomem;
- urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
- | URB_NO_INTERRUPT;
+ urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
if (usb_pipein (pipe))
urb_flags |= URB_SHORT_NOT_OK;
@@ -771,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
return err;
}
+/**
+ * usb_cache_string - read a string descriptor and cache it for later use
+ * @udev: the device whose string descriptor is being read
+ * @index: the descriptor index
+ *
+ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or NULL if the index is 0 or the string could not be read.
+ */
+char *usb_cache_string(struct usb_device *udev, int index)
+{
+ char *buf;
+ char *smallbuf = NULL;
+ int len;
+
+ if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
+ if ((len = usb_string(udev, index, buf, 256)) > 0) {
+ if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+ return buf;
+ memcpy(smallbuf, buf, len);
+ }
+ kfree(buf);
+ }
+ return smallbuf;
+}
+
/*
* usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
* @dev: the device whose device descriptor is being updated
@@ -987,13 +1028,11 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
/* remove this interface if it has been registered */
interface = dev->actconfig->interface[i];
- if (!klist_node_attached(&interface->dev.knode_bus))
+ if (!device_is_registered(&interface->dev))
continue;
dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id);
usb_remove_sysfs_intf_files(interface);
- kfree(interface->cur_altsetting->string);
- interface->cur_altsetting->string = NULL;
device_del (&interface->dev);
}
@@ -1133,6 +1172,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
*/
/* prevent submissions using previous endpoint settings */
+ if (device_is_registered(&iface->dev))
+ usb_remove_sysfs_intf_files(iface);
usb_disable_interface(dev, iface);
iface->cur_altsetting = alt;
@@ -1168,6 +1209,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* (Likewise, EP0 never "halts" on well designed devices.)
*/
usb_enable_interface(dev, iface);
+ if (device_is_registered(&iface->dev))
+ usb_create_sysfs_intf_files(iface);
return 0;
}
@@ -1217,10 +1260,8 @@ int usb_reset_configuration(struct usb_device *dev)
USB_REQ_SET_CONFIGURATION, 0,
config->desc.bConfigurationValue, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT);
- if (retval < 0) {
- usb_set_device_state(dev, USB_STATE_ADDRESS);
+ if (retval < 0)
return retval;
- }
dev->toggle[0] = dev->toggle[1] = 0;
@@ -1229,6 +1270,8 @@ int usb_reset_configuration(struct usb_device *dev)
struct usb_interface *intf = config->interface[i];
struct usb_host_interface *alt;
+ if (device_is_registered(&intf->dev))
+ usb_remove_sysfs_intf_files(intf);
alt = usb_altnum_to_altsetting(intf, 0);
/* No altsetting 0? We'll assume the first altsetting.
@@ -1241,6 +1284,8 @@ int usb_reset_configuration(struct usb_device *dev)
intf->cur_altsetting = alt;
usb_enable_interface(dev, intf);
+ if (device_is_registered(&intf->dev))
+ usb_create_sysfs_intf_files(intf);
}
return 0;
}
@@ -1328,7 +1373,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
}
for (; n < nintf; ++n) {
- new_interfaces[n] = kmalloc(
+ new_interfaces[n] = kzalloc(
sizeof(struct usb_interface),
GFP_KERNEL);
if (!new_interfaces[n]) {
@@ -1369,7 +1414,6 @@ free_interfaces:
struct usb_host_interface *alt;
cp->interface[i] = intf = new_interfaces[i];
- memset(intf, 0, sizeof(*intf));
intfc = cp->intf_cache[i];
intf->altsetting = intfc->altsetting;
intf->num_altsetting = intfc->num_altsetting;
@@ -1393,6 +1437,7 @@ free_interfaces:
intf->dev.dma_mask = dev->dev.dma_mask;
intf->dev.release = release_interface;
device_initialize (&intf->dev);
+ mark_quiesced(intf);
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration,
@@ -1400,12 +1445,9 @@ free_interfaces:
}
kfree(new_interfaces);
- if ((cp->desc.iConfiguration) &&
- (cp->string == NULL)) {
- cp->string = kmalloc(256, GFP_KERNEL);
- if (cp->string)
- usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
- }
+ if (cp->string == NULL)
+ cp->string = usb_cache_string(dev,
+ cp->desc.iConfiguration);
/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
@@ -1415,13 +1457,12 @@ free_interfaces:
*/
for (i = 0; i < nintf; ++i) {
struct usb_interface *intf = cp->interface[i];
- struct usb_interface_descriptor *desc;
+ struct usb_host_interface *alt = intf->cur_altsetting;
- desc = &intf->altsetting [0].desc;
dev_dbg (&dev->dev,
"adding %s (config #%d, interface %d)\n",
intf->dev.bus_id, configuration,
- desc->bInterfaceNumber);
+ alt->desc.bInterfaceNumber);
ret = device_add (&intf->dev);
if (ret != 0) {
dev_err(&dev->dev,
@@ -1430,13 +1471,6 @@ free_interfaces:
ret);
continue;
}
- if ((intf->cur_altsetting->desc.iInterface) &&
- (intf->cur_altsetting->string == NULL)) {
- intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
- if (intf->cur_altsetting->string)
- usb_string(dev, intf->cur_altsetting->desc.iInterface,
- intf->cur_altsetting->string, 256);
- }
usb_create_sysfs_intf_files (intf);
}
}
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
new file mode 100644
index 000000000000..37da059eced7
--- /dev/null
+++ b/drivers/usb/core/notify.c
@@ -0,0 +1,120 @@
+/*
+ * All the USB notify logic
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * notifier functions originally based on those in kernel/sys.c
+ * but fixed up to not be so broken.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb.h"
+
+
+static struct notifier_block *usb_notifier_list;
+static DECLARE_MUTEX(usb_notifier_lock);
+
+static void usb_notifier_chain_register(struct notifier_block **list,
+ struct notifier_block *n)
+{
+ down(&usb_notifier_lock);
+ while (*list) {
+ if (n->priority > (*list)->priority)
+ break;
+ list = &((*list)->next);
+ }
+ n->next = *list;
+ *list = n;
+ up(&usb_notifier_lock);
+}
+
+static void usb_notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ down(&usb_notifier_lock);
+ while ((*nl)!=NULL) {
+ if ((*nl)==n) {
+ *nl = n->next;
+ goto exit;
+ }
+ nl=&((*nl)->next);
+ }
+exit:
+ up(&usb_notifier_lock);
+}
+
+static int usb_notifier_call_chain(struct notifier_block **n,
+ unsigned long val, void *v)
+{
+ int ret=NOTIFY_DONE;
+ struct notifier_block *nb = *n;
+
+ down(&usb_notifier_lock);
+ while (nb) {
+ ret = nb->notifier_call(nb,val,v);
+ if (ret&NOTIFY_STOP_MASK) {
+ goto exit;
+ }
+ nb = nb->next;
+ }
+exit:
+ up(&usb_notifier_lock);
+ return ret;
+}
+
+/**
+ * usb_register_notify - register a notifier callback whenever a usb change happens
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * These changes are either USB devices or busses being added or removed.
+ */
+void usb_register_notify(struct notifier_block *nb)
+{
+ usb_notifier_chain_register(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_register_notify);
+
+/**
+ * usb_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * usb_register_notifier() must have been previously called for this function
+ * to work properly.
+ */
+void usb_unregister_notify(struct notifier_block *nb)
+{
+ usb_notifier_chain_unregister(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_unregister_notify);
+
+
+void usb_notify_add_device(struct usb_device *udev)
+{
+ usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+}
+
+void usb_notify_remove_device(struct usb_device *udev)
+{
+ usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+}
+
+void usb_notify_add_bus(struct usb_bus *ubus)
+{
+ usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+}
+
+void usb_notify_remove_bus(struct usb_bus *ubus)
+{
+ usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 00297f113849..edd83e014452 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -22,9 +22,207 @@
#include "usb.h"
+/* endpoint stuff */
+struct ep_object {
+ struct usb_endpoint_descriptor *desc;
+ struct usb_device *udev;
+ struct kobject kobj;
+};
+#define to_ep_object(_kobj) \
+ container_of(_kobj, struct ep_object, kobj)
+
+struct ep_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct usb_device *,
+ struct usb_endpoint_descriptor *, char *);
+};
+#define to_ep_attribute(_attr) \
+ container_of(_attr, struct ep_attribute, attr)
+
+#define EP_ATTR(_name) \
+struct ep_attribute ep_##_name = { \
+ .attr = {.name = #_name, .owner = THIS_MODULE, \
+ .mode = S_IRUGO}, \
+ .show = show_ep_##_name}
+
+#define usb_ep_attr(field, format_string) \
+static ssize_t show_ep_##field(struct usb_device *udev, \
+ struct usb_endpoint_descriptor *desc, \
+ char *buf) \
+{ \
+ return sprintf(buf, format_string, desc->field); \
+} \
+static EP_ATTR(field);
+
+usb_ep_attr(bLength, "%02x\n")
+usb_ep_attr(bEndpointAddress, "%02x\n")
+usb_ep_attr(bmAttributes, "%02x\n")
+usb_ep_attr(bInterval, "%02x\n")
+
+static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc, char *buf)
+{
+ return sprintf(buf, "%04x\n",
+ le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
+}
+static EP_ATTR(wMaxPacketSize);
+
+static ssize_t show_ep_type(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc, char *buf)
+{
+ char *type = "unknown";
+
+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ type = "Control";
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ type = "Isoc";
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ type = "Bulk";
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ type = "Interrupt";
+ break;
+ }
+ return sprintf(buf, "%s\n", type);
+}
+static EP_ATTR(type);
+
+static ssize_t show_ep_interval(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc, char *buf)
+{
+ char unit;
+ unsigned interval = 0;
+ unsigned in;
+
+ in = (desc->bEndpointAddress & USB_DIR_IN);
+
+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
+ interval = desc->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ interval = 1 << (desc->bInterval - 1);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+ interval = desc->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (udev->speed == USB_SPEED_HIGH)
+ interval = 1 << (desc->bInterval - 1);
+ else
+ interval = desc->bInterval;
+ break;
+ }
+ interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+ if (interval % 1000)
+ unit = 'u';
+ else {
+ unit = 'm';
+ interval /= 1000;
+ }
+
+ return sprintf(buf, "%d%cs\n", interval, unit);
+}
+static EP_ATTR(interval);
+
+static ssize_t show_ep_direction(struct usb_device *udev,
+ struct usb_endpoint_descriptor *desc, char *buf)
+{
+ char *direction;
+
+ if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_CONTROL)
+ direction = "both";
+ else if (desc->bEndpointAddress & USB_DIR_IN)
+ direction = "in";
+ else
+ direction = "out";
+ return sprintf(buf, "%s\n", direction);
+}
+static EP_ATTR(direction);
+
+static struct attribute *ep_attrs[] = {
+ &ep_bLength.attr,
+ &ep_bEndpointAddress.attr,
+ &ep_bmAttributes.attr,
+ &ep_bInterval.attr,
+ &ep_wMaxPacketSize.attr,
+ &ep_type.attr,
+ &ep_interval.attr,
+ &ep_direction.attr,
+ NULL,
+};
+
+static void ep_object_release(struct kobject *kobj)
+{
+ kfree(to_ep_object(kobj));
+}
+
+static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct ep_object *ep_obj = to_ep_object(kobj);
+ struct ep_attribute *ep_attr = to_ep_attribute(attr);
+
+ return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
+}
+
+static struct sysfs_ops ep_object_sysfs_ops = {
+ .show = ep_object_show,
+};
+
+static struct kobj_type ep_object_ktype = {
+ .release = ep_object_release,
+ .sysfs_ops = &ep_object_sysfs_ops,
+ .default_attrs = ep_attrs,
+};
+
+static void usb_create_ep_files(struct kobject *parent,
+ struct usb_host_endpoint *endpoint,
+ struct usb_device *udev)
+{
+ struct ep_object *ep_obj;
+ struct kobject *kobj;
+
+ ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
+ if (!ep_obj)
+ return;
+
+ ep_obj->desc = &endpoint->desc;
+ ep_obj->udev = udev;
+
+ kobj = &ep_obj->kobj;
+ kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
+ kobj->parent = parent;
+ kobj->ktype = &ep_object_ktype;
+
+ /* Don't use kobject_register, because it generates a hotplug event */
+ kobject_init(kobj);
+ if (kobject_add(kobj) == 0)
+ endpoint->kobj = kobj;
+ else
+ kobject_put(kobj);
+}
+
+static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+{
+
+ if (endpoint->kobj) {
+ kobject_del(endpoint->kobj);
+ kobject_put(endpoint->kobj);
+ endpoint->kobj = NULL;
+ }
+}
+
/* Active configuration fields */
#define usb_actconfig_show(field, multiplier, format_string) \
-static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_##field (struct device *dev, \
+ struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
struct usb_host_config *actconfig; \
@@ -46,22 +244,17 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
usb_actconfig_attr (bmAttributes, 1, "%2x\n")
usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
-static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_configuration_string(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
struct usb_host_config *actconfig;
- int len;
udev = to_usb_device (dev);
actconfig = udev->actconfig;
if ((!actconfig) || (!actconfig->string))
return 0;
- len = sprintf(buf, actconfig->string, PAGE_SIZE);
- if (len < 0)
- return 0;
- buf[len] = '\n';
- buf[len+1] = 0;
- return len+1;
+ return sprintf(buf, "%s\n", actconfig->string);
}
static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
@@ -69,7 +262,8 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
usb_actconfig_show(bConfigurationValue, 1, "%u\n");
static ssize_t
-set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct usb_device *udev = udev = to_usb_device (dev);
int config, value;
@@ -87,18 +281,13 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
/* String fields */
#define usb_string_attr(name) \
-static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
- int len; \
\
udev = to_usb_device (dev); \
- len = snprintf(buf, 256, "%s", udev->name); \
- if (len < 0) \
- return 0; \
- buf[len] = '\n'; \
- buf[len+1] = 0; \
- return len+1; \
+ return sprintf(buf, "%s\n", udev->name); \
} \
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
@@ -167,7 +356,8 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
/* Descriptor fields */
#define usb_descriptor_attr_le16(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
{ \
struct usb_device *udev; \
\
@@ -183,7 +373,8 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n")
#define usb_descriptor_attr(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
{ \
struct usb_device *udev; \
\
@@ -236,19 +427,21 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
if (udev->serial)
device_create_file (dev, &dev_attr_serial);
device_create_file (dev, &dev_attr_configuration);
+ usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
}
void usb_remove_sysfs_dev_files (struct usb_device *udev)
{
struct device *dev = &udev->dev;
+ usb_remove_ep_files(&udev->ep0);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
- if (udev->descriptor.iManufacturer)
+ if (udev->manufacturer)
device_remove_file(dev, &dev_attr_manufacturer);
- if (udev->descriptor.iProduct)
+ if (udev->product)
device_remove_file(dev, &dev_attr_product);
- if (udev->descriptor.iSerialNumber)
+ if (udev->serial)
device_remove_file(dev, &dev_attr_serial);
device_remove_file (dev, &dev_attr_configuration);
}
@@ -256,11 +449,13 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
/* Interface fields */
#define usb_intf_attr(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
{ \
struct usb_interface *intf = to_usb_interface (dev); \
\
- return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
+ return sprintf (buf, format_string, \
+ intf->cur_altsetting->desc.field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
@@ -271,7 +466,8 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
-static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_interface_string(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_interface *intf;
struct usb_device *udev;
@@ -288,34 +484,28 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_modalias(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_interface *intf;
struct usb_device *udev;
- int len;
+ struct usb_host_interface *alt;
intf = to_usb_interface(dev);
udev = interface_to_usbdev(intf);
-
- len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct),
- le16_to_cpu(udev->descriptor.bcdDevice),
- udev->descriptor.bDeviceClass,
- udev->descriptor.bDeviceSubClass,
- udev->descriptor.bDeviceProtocol);
- buf += len;
-
- if (udev->descriptor.bDeviceClass == 0) {
- struct usb_host_interface *alt = intf->cur_altsetting;
-
- return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol);
- } else {
- return len + sprintf(buf, "*isc*ip*\n");
- }
+ alt = intf->cur_altsetting;
+
+ return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
+ "ic%02Xisc%02Xip%02X\n",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ le16_to_cpu(udev->descriptor.bcdDevice),
+ udev->descriptor.bDeviceClass,
+ udev->descriptor.bDeviceSubClass,
+ udev->descriptor.bDeviceProtocol,
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol);
}
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
@@ -333,20 +523,47 @@ static struct attribute_group intf_attr_grp = {
.attrs = intf_attrs,
};
+static inline void usb_create_intf_ep_files(struct usb_interface *intf,
+ struct usb_device *udev)
+{
+ struct usb_host_interface *iface_desc;
+ int i;
+
+ iface_desc = intf->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+ usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+ udev);
+}
+
+static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+{
+ struct usb_host_interface *iface_desc;
+ int i;
+
+ iface_desc = intf->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+ usb_remove_ep_files(&iface_desc->endpoint[i]);
+}
+
void usb_create_sysfs_intf_files (struct usb_interface *intf)
{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_host_interface *alt = intf->cur_altsetting;
+
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
- if (intf->cur_altsetting->string)
+ if (alt->string == NULL)
+ alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ if (alt->string)
device_create_file(&intf->dev, &dev_attr_interface);
-
+ usb_create_intf_ep_files(intf, udev);
}
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
{
+ usb_remove_intf_ep_files(intf);
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
if (intf->cur_altsetting->string)
device_remove_file(&intf->dev, &dev_attr_interface);
-
}
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c0feee25ff0a..f2a1fed2a802 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -60,7 +60,7 @@ void usb_init_urb(struct urb *urb)
*
* The driver must call usb_free_urb() when it is finished with the urb.
*/
-struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags)
+struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb;
@@ -224,7 +224,7 @@ struct urb * usb_get_urb(struct urb *urb)
* GFP_NOIO, unless b) or c) apply
*
*/
-int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
int pipe, temp, max;
struct usb_device *dev;
@@ -237,7 +237,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
(dev->state < USB_STATE_DEFAULT) ||
(!dev->bus) || (dev->devnum <= 0))
return -ENODEV;
- if (dev->state == USB_STATE_SUSPENDED)
+ if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+ || dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
if (!(op = dev->bus->op) || !op->submit_urb)
return -ENODEV;
@@ -309,9 +310,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
unsigned int allowed;
/* enforce simple/standard policy */
- allowed = URB_ASYNC_UNLINK; // affects later unlinks
- allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- allowed |= URB_NO_INTERRUPT;
+ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+ URB_NO_INTERRUPT);
switch (temp) {
case PIPE_BULK:
if (is_out)
@@ -400,14 +400,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
* canceled (rather than any other code) and will quickly be removed
* from host controller data structures.
*
- * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the
- * URB indicated that the request was synchronous. This usage is now
- * deprecated; if the flag is clear the call will be forwarded to
- * usb_kill_urb() and the return value will be 0. In the future, drivers
- * should call usb_kill_urb() directly for synchronous unlinking.
- *
- * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
- * request is asynchronous. Success is indicated by returning -EINPROGRESS,
+ * This request is always asynchronous.
+ * Success is indicated by returning -EINPROGRESS,
* at which time the URB will normally have been unlinked but not yet
* given back to the device driver. When it is called, the completion
* function will see urb->status == -ECONNRESET. Failure is indicated
@@ -453,17 +447,6 @@ int usb_unlink_urb(struct urb *urb)
{
if (!urb)
return -EINVAL;
- if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
-#ifdef CONFIG_DEBUG_KERNEL
- if (printk_ratelimit()) {
- printk(KERN_NOTICE "usb_unlink_urb() is deprecated for "
- "synchronous unlinks. Use usb_kill_urb() instead.\n");
- WARN_ON(1);
- }
-#endif
- usb_kill_urb(urb);
- return 0;
- }
if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
return -ENODEV;
return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 99c85d2f92da..0eefff7bcb3c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -65,6 +65,16 @@ static int generic_probe (struct device *dev)
}
static int generic_remove (struct device *dev)
{
+ struct usb_device *udev = to_usb_device(dev);
+
+ /* if this is only an unbind, not a physical disconnect, then
+ * unconfigure the device */
+ if (udev->state == USB_STATE_CONFIGURED)
+ usb_set_configuration(udev, 0);
+
+ /* in case the call failed or the device was suspended */
+ if (udev->state >= USB_STATE_CONFIGURED)
+ usb_disable_device(udev, 0);
return 0;
}
@@ -97,10 +107,19 @@ static int usb_probe_interface(struct device *dev)
id = usb_match_id (intf, driver->id_table);
if (id) {
dev_dbg (dev, "%s - got id\n", __FUNCTION__);
+
+ /* Interface "power state" doesn't correspond to any hardware
+ * state whatsoever. We use it to record when it's bound to
+ * a driver that may start I/0: it's not frozen/quiesced.
+ */
+ mark_active(intf);
intf->condition = USB_INTERFACE_BINDING;
error = driver->probe (intf, id);
- intf->condition = error ? USB_INTERFACE_UNBOUND :
- USB_INTERFACE_BOUND;
+ if (error) {
+ mark_quiesced(intf);
+ intf->condition = USB_INTERFACE_UNBOUND;
+ } else
+ intf->condition = USB_INTERFACE_BOUND;
}
return error;
@@ -126,6 +145,7 @@ static int usb_unbind_interface(struct device *dev)
0);
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
+ mark_quiesced(intf);
return 0;
}
@@ -289,11 +309,12 @@ int usb_driver_claim_interface(struct usb_driver *driver,
dev->driver = &driver->driver;
usb_set_intfdata(iface, priv);
iface->condition = USB_INTERFACE_BOUND;
+ mark_active(iface);
/* if interface was already added, bind now; else let
* the future device_add() bind it, bypassing probe()
*/
- if (klist_node_attached(&dev->knode_bus))
+ if (device_is_registered(dev))
device_bind_driver(dev);
return 0;
@@ -326,8 +347,8 @@ void usb_driver_release_interface(struct usb_driver *driver,
if (iface->condition != USB_INTERFACE_BOUND)
return;
- /* release only after device_add() */
- if (klist_node_attached(&dev->knode_bus)) {
+ /* don't release if the interface hasn't been added yet */
+ if (device_is_registered(dev)) {
iface->condition = USB_INTERFACE_UNBINDING;
device_release_driver(dev);
}
@@ -335,6 +356,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
dev->driver = NULL;
usb_set_intfdata(iface, NULL);
iface->condition = USB_INTERFACE_UNBOUND;
+ mark_quiesced(iface);
}
/**
@@ -547,6 +569,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
{
struct usb_interface *intf;
struct usb_device *usb_dev;
+ struct usb_host_interface *alt;
int i = 0;
int length = 0;
@@ -563,7 +586,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
intf = to_usb_interface(dev);
usb_dev = interface_to_usbdev (intf);
-
+ alt = intf->cur_altsetting;
+
if (usb_dev->devnum < 0) {
pr_debug ("usb %s: already deleted?\n", dev->bus_id);
return -ENODEV;
@@ -605,46 +629,27 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
- if (usb_dev->descriptor.bDeviceClass == 0) {
- struct usb_host_interface *alt = intf->cur_altsetting;
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "INTERFACE=%d/%d/%d",
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
+ return -ENOMEM;
- /* 2.4 only exposed interface zero. in 2.5, hotplug
- * agents are called for all interfaces, and can use
- * $DEVPATH/bInterfaceNumber if necessary.
- */
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "INTERFACE=%d/%d/%d",
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
- return -ENOMEM;
-
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice),
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol,
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
- return -ENOMEM;
- } else {
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice),
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol))
- return -ENOMEM;
- }
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol,
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
+ return -ENOMEM;
envp[i] = NULL;
@@ -699,12 +704,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
struct usb_device *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
-
bus = usb_bus_get(bus);
if (!bus) {
kfree(dev);
@@ -912,7 +915,7 @@ int usb_trylock_device(struct usb_device *udev)
* is neither BINDING nor BOUND. Rather than sleeping to wait for the
* lock, the routine polls repeatedly. This is to prevent deadlock with
* disconnect; in some drivers (such as usb-storage) the disconnect()
- * callback will block waiting for a device reset to complete.
+ * or suspend() method will block waiting for a device reset to complete.
*
* Returns a negative error code for failure, otherwise 1 or 0 to indicate
* that the device will or will not have to be unlocked. (0 can be
@@ -922,6 +925,8 @@ int usb_trylock_device(struct usb_device *udev)
int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface)
{
+ unsigned long jiffies_expire = jiffies + HZ;
+
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
if (udev->state == USB_STATE_SUSPENDED)
@@ -938,6 +943,12 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
while (!usb_trylock_device(udev)) {
+
+ /* If we can't acquire the lock after waiting one second,
+ * we're probably deadlocked */
+ if (time_after(jiffies, jiffies_expire))
+ return -EBUSY;
+
msleep(15);
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
@@ -1129,7 +1140,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
void *usb_buffer_alloc (
struct usb_device *dev,
size_t size,
- unsigned mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma
)
{
@@ -1384,13 +1395,30 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
+static int verify_suspended(struct device *dev, void *unused)
+{
+ return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+}
+
static int usb_generic_suspend(struct device *dev, pm_message_t message)
{
- struct usb_interface *intf;
- struct usb_driver *driver;
+ struct usb_interface *intf;
+ struct usb_driver *driver;
+ int status;
- if (dev->driver == &usb_generic_driver)
- return usb_suspend_device (to_usb_device(dev), message);
+ /* USB devices enter SUSPEND state through their hubs, but can be
+ * marked for FREEZE as soon as their children are already idled.
+ * But those semantics are useless, so we equate the two (sigh).
+ */
+ if (dev->driver == &usb_generic_driver) {
+ if (dev->power.power_state.event == message.event)
+ return 0;
+ /* we need to rule out bogus requests through sysfs */
+ status = device_for_each_child(dev, NULL, verify_suspended);
+ if (status)
+ return status;
+ return usb_suspend_device (to_usb_device(dev));
+ }
if ((dev->driver == NULL) ||
(dev->driver_data == &usb_generic_driver_data))
@@ -1399,23 +1427,44 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
intf = to_usb_interface(dev);
driver = to_usb_driver(dev->driver);
- /* there's only one USB suspend state */
- if (intf->dev.power.power_state)
+ /* with no hardware, USB interfaces only use FREEZE and ON states */
+ if (!is_active(intf))
return 0;
- if (driver->suspend)
- return driver->suspend(intf, message);
- return 0;
+ if (driver->suspend && driver->resume) {
+ status = driver->suspend(intf, message);
+ if (status)
+ dev_err(dev, "%s error %d\n", "suspend", status);
+ else
+ mark_quiesced(intf);
+ } else {
+ // FIXME else if there's no suspend method, disconnect...
+ dev_warn(dev, "no %s?\n", "suspend");
+ status = 0;
+ }
+ return status;
}
static int usb_generic_resume(struct device *dev)
{
- struct usb_interface *intf;
- struct usb_driver *driver;
+ struct usb_interface *intf;
+ struct usb_driver *driver;
+ struct usb_device *udev;
+ int status;
- /* devices resume through their hub */
- if (dev->driver == &usb_generic_driver)
+ if (dev->power.power_state.event == PM_EVENT_ON)
+ return 0;
+
+ /* mark things as "on" immediately, no matter what errors crop up */
+ dev->power.power_state.event = PM_EVENT_ON;
+
+ /* devices resume through their hubs */
+ if (dev->driver == &usb_generic_driver) {
+ udev = to_usb_device(dev);
+ if (udev->state == USB_STATE_NOTATTACHED)
+ return 0;
return usb_resume_device (to_usb_device(dev));
+ }
if ((dev->driver == NULL) ||
(dev->driver_data == &usb_generic_driver_data))
@@ -1424,8 +1473,22 @@ static int usb_generic_resume(struct device *dev)
intf = to_usb_interface(dev);
driver = to_usb_driver(dev->driver);
- if (driver->resume)
- return driver->resume(intf);
+ udev = interface_to_usbdev(intf);
+ if (udev->state == USB_STATE_NOTATTACHED)
+ return 0;
+
+ /* if driver was suspended, it has a resume method;
+ * however, sysfs can wrongly mark things as suspended
+ * (on the "no suspend method" FIXME path above)
+ */
+ if (driver->resume) {
+ status = driver->resume(intf);
+ if (status) {
+ dev_err(dev, "%s error %d\n", "resume", status);
+ mark_quiesced(intf);
+ }
+ } else
+ dev_warn(dev, "no %s?\n", "resume");
return 0;
}
@@ -1478,13 +1541,18 @@ static int __init usb_init(void)
retval = usb_major_init();
if (retval)
goto major_init_failed;
+ retval = usb_register(&usbfs_driver);
+ if (retval)
+ goto driver_register_failed;
+ retval = usbdev_init();
+ if (retval)
+ goto usbdevice_init_failed;
retval = usbfs_init();
if (retval)
goto fs_init_failed;
retval = usb_hub_init();
if (retval)
goto hub_init_failed;
-
retval = driver_register(&usb_generic_driver);
if (!retval)
goto out;
@@ -1493,7 +1561,11 @@ static int __init usb_init(void)
hub_init_failed:
usbfs_cleanup();
fs_init_failed:
- usb_major_cleanup();
+ usbdev_cleanup();
+usbdevice_init_failed:
+ usb_deregister(&usbfs_driver);
+driver_register_failed:
+ usb_major_cleanup();
major_init_failed:
usb_host_cleanup();
host_init_failed:
@@ -1514,6 +1586,8 @@ static void __exit usb_exit(void)
driver_unregister(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
+ usb_deregister(&usbfs_driver);
+ usbdev_cleanup();
usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 2c690f6d4c18..1c4a68499dce 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -13,12 +13,14 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
+extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_lock_all_devices(void);
extern void usb_unlock_all_devices(void);
extern void usb_kick_khubd(struct usb_device *dev);
+extern void usb_suspend_root_hub(struct usb_device *hdev);
extern void usb_resume_root_hub(struct usb_device *dev);
extern int usb_hub_init(void);
@@ -28,6 +30,28 @@ extern void usb_major_cleanup(void);
extern int usb_host_init(void);
extern void usb_host_cleanup(void);
+extern int usb_suspend_device(struct usb_device *dev);
+extern int usb_resume_device(struct usb_device *dev);
+
+
+/* Interfaces and their "power state" are owned by usbcore */
+
+static inline void mark_active(struct usb_interface *f)
+{
+ f->dev.power.power_state.event = PM_EVENT_ON;
+}
+
+static inline void mark_quiesced(struct usb_interface *f)
+{
+ f->dev.power.power_state.event = PM_EVENT_FREEZE;
+}
+
+static inline int is_active(struct usb_interface *f)
+{
+ return f->dev.power.power_state.event == PM_EVENT_ON;
+}
+
+
/* for labeling diagnostics */
extern const char *usbcore_name;
@@ -37,6 +61,8 @@ extern struct file_operations usbfs_devices_fops;
extern struct file_operations usbfs_device_file_operations;
extern void usbfs_conn_disc_event(void);
+extern int usbdev_init(void);
+extern void usbdev_cleanup(void);
struct dev_state {
struct list_head list; /* state list */
@@ -47,8 +73,15 @@ struct dev_state {
struct list_head async_completed;
wait_queue_head_t wait; /* wake up if a request completed */
unsigned int discsignr;
- struct task_struct *disctask;
+ pid_t disc_pid;
+ uid_t disc_uid, disc_euid;
void __user *disccontext;
unsigned long ifclaimed;
};
+/* internal notify stuff */
+extern void usb_notify_add_device(struct usb_device *udev);
+extern void usb_notify_remove_device(struct usb_device *udev);
+extern void usb_notify_add_bus(struct usb_bus *ubus);
+extern void usb_notify_remove_bus(struct usb_bus *ubus);
+
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 583db7c38cf1..975ace3f5b1e 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -50,7 +50,7 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/version.h>
-
+#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb_gadget.h>
@@ -470,7 +470,7 @@ static int dummy_disable (struct usb_ep *_ep)
}
static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags)
+dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
{
struct dummy_ep *ep;
struct dummy_request *req;
@@ -507,7 +507,7 @@ dummy_alloc_buffer (
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned mem_flags
+ gfp_t mem_flags
) {
char *retval;
struct dummy_ep *ep;
@@ -541,7 +541,7 @@ fifo_complete (struct usb_ep *ep, struct usb_request *req)
static int
dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
struct dummy_ep *ep;
struct dummy_request *req;
@@ -935,14 +935,10 @@ static int dummy_udc_remove (struct device *dev)
return 0;
}
-static int dummy_udc_suspend (struct device *dev, pm_message_t state,
- u32 level)
+static int dummy_udc_suspend (struct device *dev, pm_message_t state)
{
struct dummy *dum = dev_get_drvdata(dev);
- if (level != SUSPEND_DISABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 1;
@@ -954,13 +950,10 @@ static int dummy_udc_suspend (struct device *dev, pm_message_t state,
return 0;
}
-static int dummy_udc_resume (struct device *dev, u32 level)
+static int dummy_udc_resume (struct device *dev)
{
struct dummy *dum = dev_get_drvdata(dev);
- if (level != RESUME_ENABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 0;
@@ -974,6 +967,7 @@ static int dummy_udc_resume (struct device *dev, u32 level)
static struct device_driver dummy_udc_driver = {
.name = (char *) gadget_name,
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = dummy_udc_probe,
.remove = dummy_udc_remove,
@@ -999,7 +993,7 @@ static int dummy_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct dummy *dum;
struct urbp *urbp;
@@ -1758,7 +1752,7 @@ static int dummy_hub_control (
return retval;
}
-static int dummy_hub_suspend (struct usb_hcd *hcd)
+static int dummy_bus_suspend (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
@@ -1769,7 +1763,7 @@ static int dummy_hub_suspend (struct usb_hcd *hcd)
return 0;
}
-static int dummy_hub_resume (struct usb_hcd *hcd)
+static int dummy_bus_resume (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
@@ -1901,8 +1895,8 @@ static const struct hc_driver dummy_hcd = {
.hub_status_data = dummy_hub_status,
.hub_control = dummy_hub_control,
- .hub_suspend = dummy_hub_suspend,
- .hub_resume = dummy_hub_resume,
+ .bus_suspend = dummy_bus_suspend,
+ .bus_resume = dummy_bus_resume,
};
static int dummy_hcd_probe (struct device *dev)
@@ -1936,52 +1930,32 @@ static int dummy_hcd_remove (struct device *dev)
return 0;
}
-static int dummy_hcd_suspend (struct device *dev, pm_message_t state,
- u32 level)
+static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
{
struct usb_hcd *hcd;
- if (level != SUSPEND_DISABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
hcd = dev_get_drvdata (dev);
-#ifndef CONFIG_USB_SUSPEND
- /* Otherwise this would never happen */
- usb_lock_device (hcd->self.root_hub);
- dummy_hub_suspend (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
hcd->state = HC_STATE_SUSPENDED;
return 0;
}
-static int dummy_hcd_resume (struct device *dev, u32 level)
+static int dummy_hcd_resume (struct device *dev)
{
struct usb_hcd *hcd;
- if (level != RESUME_ENABLE)
- return 0;
-
dev_dbg (dev, "%s\n", __FUNCTION__);
hcd = dev_get_drvdata (dev);
hcd->state = HC_STATE_RUNNING;
-#ifndef CONFIG_USB_SUSPEND
- /* Otherwise this would never happen */
- usb_lock_device (hcd->self.root_hub);
- dummy_hub_resume (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
usb_hcd_poll_rh_status (hcd);
return 0;
}
static struct device_driver dummy_hcd_driver = {
.name = (char *) driver_name,
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = dummy_hcd_probe,
.remove = dummy_hcd_remove,
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8509e955007d..8f402f85e1ca 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -945,11 +945,11 @@ config_buf (enum usb_device_speed speed,
/*-------------------------------------------------------------------------*/
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags);
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
static int
-set_ether_config (struct eth_dev *dev, unsigned gfp_flags)
+set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
@@ -1081,7 +1081,7 @@ static void eth_reset_config (struct eth_dev *dev)
* that returns config descriptors, and altsetting code.
*/
static int
-eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags)
+eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
@@ -1598,7 +1598,7 @@ static void defer_kevent (struct eth_dev *dev, int flag)
static void rx_complete (struct usb_ep *ep, struct usb_request *req);
static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags)
+rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
{
struct sk_buff *skb;
int retval = -ENOMEM;
@@ -1724,7 +1724,7 @@ clean:
}
static int prealloc (struct list_head *list, struct usb_ep *ep,
- unsigned n, unsigned gfp_flags)
+ unsigned n, gfp_t gfp_flags)
{
unsigned i;
struct usb_request *req;
@@ -1763,7 +1763,7 @@ extra:
return 0;
}
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags)
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
{
int status;
@@ -1779,7 +1779,7 @@ fail:
return status;
}
-static void rx_fill (struct eth_dev *dev, unsigned gfp_flags)
+static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
{
struct usb_request *req;
unsigned long flags;
@@ -1962,7 +1962,7 @@ drop:
* normally just one notification will be queued.
*/
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned);
+static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
static void
@@ -2024,7 +2024,7 @@ static int rndis_control_ack (struct net_device *net)
#endif /* RNDIS */
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags)
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
{
DEBUG (dev, "%s\n", __FUNCTION__);
@@ -2092,7 +2092,7 @@ static int eth_stop (struct net_device *net)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags)
+eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
{
struct usb_request *req;
@@ -2181,6 +2181,7 @@ eth_bind (struct usb_gadget *gadget)
u8 cdc = 1, zlp = 1, rndis = 1;
struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
int status = -ENOMEM;
+ int gcnum;
/* these flags are only ever cleared; compiler take note */
#ifndef DEV_CONFIG_CDC
@@ -2194,44 +2195,26 @@ eth_bind (struct usb_gadget *gadget)
* standard protocol is _strongly_ preferred for interop purposes.
* (By everyone except Microsoft.)
*/
- if (gadget_is_net2280 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
- } else if (gadget_is_dummy (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0202);
- } else if (gadget_is_pxa (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
+ if (gadget_is_pxa (gadget)) {
/* pxa doesn't support altsettings */
cdc = 0;
} else if (gadget_is_sh(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
/* sh doesn't support multiple interfaces or configs */
cdc = 0;
rndis = 0;
} else if (gadget_is_sa1100 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
/* hardware can't write zlps */
zlp = 0;
/* sa1100 CAN do CDC, without status endpoint ... we use
* non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
*/
cdc = 0;
- } else if (gadget_is_goku (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
- } else if (gadget_is_mq11xx (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
- } else if (gadget_is_omap (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
- } else if (gadget_is_lh7a40x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
- } else if (gadget_is_n9604(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
- } else if (gadget_is_pxa27x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
- } else if (gadget_is_s3c2410(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
- } else if (gadget_is_at91(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
- } else {
+ }
+
+ gcnum = usb_gadget_controller_number (gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+ else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
* so we fail in this case.
@@ -2550,6 +2533,7 @@ static struct usb_gadget_driver eth_driver = {
.driver = {
.name = (char *) shortname,
+ .owner = THIS_MODULE,
// .shutdown = ...
// .suspend = ...
// .resume = ...
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 4f57085619b4..ea09aaa3cab6 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/limits.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -669,7 +670,6 @@ struct fsg_dev {
wait_queue_head_t thread_wqh;
int thread_wakeup_needed;
struct completion thread_notifier;
- int thread_pid;
struct task_struct *thread_task;
sigset_t thread_signal_mask;
@@ -1084,7 +1084,6 @@ static void wakeup_thread(struct fsg_dev *fsg)
static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
{
unsigned long flags;
- struct task_struct *thread_task;
/* Do nothing if a higher-priority exception is already in progress.
* If a lower-or-equal priority exception is in progress, preempt it
@@ -1093,9 +1092,9 @@ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
if (fsg->state <= new_state) {
fsg->exception_req_tag = fsg->ep0_req_tag;
fsg->state = new_state;
- thread_task = fsg->thread_task;
- if (thread_task)
- send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task);
+ if (fsg->thread_task)
+ send_sig_info(SIGUSR1, SEND_SIG_FORCED,
+ fsg->thread_task);
}
spin_unlock_irqrestore(&fsg->lock, flags);
}
@@ -3383,11 +3382,6 @@ static int fsg_main_thread(void *fsg_)
{
struct fsg_dev *fsg = (struct fsg_dev *) fsg_;
- fsg->thread_task = current;
-
- /* Release all our userspace resources */
- daemonize("file-storage-gadget");
-
/* Allow the thread to be killed by a signal, but set the signal mask
* to block everything but INT, TERM, KILL, and USR1. */
siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
@@ -3400,9 +3394,6 @@ static int fsg_main_thread(void *fsg_)
* that expects a __user pointer and it will work okay. */
set_fs(get_ds());
- /* Wait for the gadget registration to finish up */
- wait_for_completion(&fsg->thread_notifier);
-
/* The main loop */
while (fsg->state != FSG_STATE_TERMINATED) {
if (exception_in_progress(fsg) || signal_pending(current)) {
@@ -3440,8 +3431,9 @@ static int fsg_main_thread(void *fsg_)
spin_unlock_irq(&fsg->lock);
}
+ spin_lock_irq(&fsg->lock);
fsg->thread_task = NULL;
- flush_signals(current);
+ spin_unlock_irq(&fsg->lock);
/* In case we are exiting because of a signal, unregister the
* gadget driver and close the backing file. */
@@ -3713,6 +3705,7 @@ static void fsg_unbind(struct usb_gadget *gadget)
static int __init check_parameters(struct fsg_dev *fsg)
{
int prot;
+ int gcnum;
/* Store the default values */
mod_data.transport_type = USB_PR_BULK;
@@ -3724,33 +3717,13 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.can_stall = 0;
if (mod_data.release == 0xffff) { // Parameter wasn't set
- if (gadget_is_net2280(fsg->gadget))
- mod_data.release = 0x0301;
- else if (gadget_is_dummy(fsg->gadget))
- mod_data.release = 0x0302;
- else if (gadget_is_pxa(fsg->gadget))
- mod_data.release = 0x0303;
- else if (gadget_is_sh(fsg->gadget))
- mod_data.release = 0x0304;
-
/* The sa1100 controller is not supported */
-
- else if (gadget_is_goku(fsg->gadget))
- mod_data.release = 0x0306;
- else if (gadget_is_mq11xx(fsg->gadget))
- mod_data.release = 0x0307;
- else if (gadget_is_omap(fsg->gadget))
- mod_data.release = 0x0308;
- else if (gadget_is_lh7a40x(fsg->gadget))
- mod_data.release = 0x0309;
- else if (gadget_is_n9604(fsg->gadget))
- mod_data.release = 0x0310;
- else if (gadget_is_pxa27x(fsg->gadget))
- mod_data.release = 0x0311;
- else if (gadget_is_s3c2410(gadget))
- mod_data.release = 0x0312;
- else if (gadget_is_at91(fsg->gadget))
- mod_data.release = 0x0313;
+ if (gadget_is_sa1100(fsg->gadget))
+ gcnum = -1;
+ else
+ gcnum = usb_gadget_controller_number(fsg->gadget);
+ if (gcnum >= 0)
+ mod_data.release = 0x0300 + gcnum;
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
@@ -3850,12 +3823,11 @@ static int __init fsg_bind(struct usb_gadget *gadget)
/* Create the LUNs, open their backing files, and register the
* LUN devices in sysfs. */
- fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
+ fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);
if (!fsg->luns) {
rc = -ENOMEM;
goto out;
}
- memset(fsg->luns, 0, i * sizeof(struct lun));
fsg->nluns = i;
for (i = 0; i < fsg->nluns; ++i) {
@@ -3978,10 +3950,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
sprintf(&serial[i], "%02X", c);
}
- if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS |
- CLONE_FILES))) < 0)
+ fsg->thread_task = kthread_create(fsg_main_thread, fsg,
+ "file-storage-gadget");
+ if (IS_ERR(fsg->thread_task)) {
+ rc = PTR_ERR(fsg->thread_task);
goto out;
- fsg->thread_pid = rc;
+ }
INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
@@ -4013,7 +3987,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
mod_data.removable, mod_data.can_stall,
mod_data.buflen);
- DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
+ DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
+
+ set_bit(REGISTERED, &fsg->atomic_bitflags);
+
+ /* Tell the thread to start working */
+ wake_up_process(fsg->thread_task);
return 0;
autoconf_fail:
@@ -4065,6 +4044,7 @@ static struct usb_gadget_driver fsg_driver = {
.driver = {
.name = (char *) shortname,
+ .owner = THIS_MODULE,
// .release = ...
// .suspend = ...
// .resume = ...
@@ -4076,10 +4056,9 @@ static int __init fsg_alloc(void)
{
struct fsg_dev *fsg;
- fsg = kmalloc(sizeof *fsg, GFP_KERNEL);
+ fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
if (!fsg)
return -ENOMEM;
- memset(fsg, 0, sizeof *fsg);
spin_lock_init(&fsg->lock);
init_rwsem(&fsg->filesem);
init_waitqueue_head(&fsg->thread_wqh);
@@ -4105,15 +4084,9 @@ static int __init fsg_init(void)
if ((rc = fsg_alloc()) != 0)
return rc;
fsg = the_fsg;
- if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) {
+ if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
fsg_free(fsg);
- return rc;
- }
- set_bit(REGISTERED, &fsg->atomic_bitflags);
-
- /* Tell the thread to start working */
- complete(&fsg->thread_notifier);
- return 0;
+ return rc;
}
module_init(fsg_init);
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index ea2eb52c766d..8cbae21d84b9 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -5,6 +5,7 @@
*
* This could eventually work like the ARM mach_is_*() stuff, driven by
* some config file that gets updated as new hardware is supported.
+ * (And avoiding the runtime comparisons in typical one-choice cases.)
*
* NOTE: some of these controller drivers may not be available yet.
*/
@@ -86,7 +87,61 @@
#define gadget_is_at91(g) 0
#endif
+#ifdef CONFIG_USB_GADGET_IMX
+#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
+#else
+#define gadget_is_imx(g) 0
+#endif
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
+
+/**
+ * usb_gadget_controller_number - support bcdDevice id convention
+ * @gadget: the controller being driven
+ *
+ * Return a 2-digit BCD value associated with the peripheral controller,
+ * suitable for use as part of a bcdDevice value, or a negative error code.
+ *
+ * NOTE: this convention is purely optional, and has no meaning in terms of
+ * any USB specification. If you want to use a different convention in your
+ * gadget driver firmware -- maybe a more formal revision ID -- feel free.
+ *
+ * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
+ * to change their behavior accordingly. For example it might help avoiding
+ * some chip bug.
+ */
+static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
+{
+ if (gadget_is_net2280(gadget))
+ return 0x01;
+ else if (gadget_is_dummy(gadget))
+ return 0x02;
+ else if (gadget_is_pxa(gadget))
+ return 0x03;
+ else if (gadget_is_sh(gadget))
+ return 0x04;
+ else if (gadget_is_sa1100(gadget))
+ return 0x05;
+ else if (gadget_is_goku(gadget))
+ return 0x06;
+ else if (gadget_is_mq11xx(gadget))
+ return 0x07;
+ else if (gadget_is_omap(gadget))
+ return 0x08;
+ else if (gadget_is_lh7a40x(gadget))
+ return 0x09;
+ else if (gadget_is_n9604(gadget))
+ return 0x10;
+ else if (gadget_is_pxa27x(gadget))
+ return 0x11;
+ else if (gadget_is_s3c2410(gadget))
+ return 0x12;
+ else if (gadget_is_at91(gadget))
+ return 0x13;
+ else if (gadget_is_imx(gadget))
+ return 0x14;
+ return -ENOENT;
+}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index eaab26f4ed37..654469778ab5 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -269,7 +269,7 @@ static int goku_ep_disable(struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
{
struct goku_request *req;
@@ -327,7 +327,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
*/
static void *
goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, unsigned gfp_flags)
+ dma_addr_t *dma, gfp_t gfp_flags)
{
void *retval;
struct goku_ep *ep;
@@ -789,7 +789,7 @@ finished:
/*-------------------------------------------------------------------------*/
static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct goku_request *req;
struct goku_ep *ep;
@@ -1970,6 +1970,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver goku_pci_driver = {
.name = (char *) driver_name,
.id_table = pci_ids,
+ .owner = THIS_MODULE,
.probe = goku_probe,
.remove = goku_remove,
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 020815397a49..5c40980a5bd9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -483,6 +483,7 @@ ep_release (struct inode *inode, struct file *fd)
data->state = STATE_EP_DISABLED;
data->desc.bDescriptorType = 0;
data->hs_desc.bDescriptorType = 0;
+ usb_ep_disable(data->ep);
}
put_ep (data);
return 0;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 4842577789c9..bc6269f10cbb 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -21,6 +21,8 @@
*
*/
+#include <linux/platform_device.h>
+
#include "lh7a40x_udc.h"
//#define DEBUG printk
@@ -71,13 +73,13 @@ static char *state_names[] = {
static int lh7a40x_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *);
static int lh7a40x_ep_disable(struct usb_ep *ep);
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
- int);
+ gfp_t);
static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
unsigned);
-static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int);
static int lh7a40x_fifo_status(struct usb_ep *ep);
@@ -1106,7 +1108,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
}
static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
- unsigned gfp_flags)
+ gfp_t gfp_flags)
{
struct lh7a40x_request *req;
@@ -1134,7 +1136,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
}
static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
- dma_addr_t * dma, unsigned gfp_flags)
+ dma_addr_t * dma, gfp_t gfp_flags)
{
char *retval;
@@ -1158,7 +1160,7 @@ static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
* NOTE: Sets INDEX register
*/
static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
- unsigned gfp_flags)
+ gfp_t gfp_flags)
{
struct lh7a40x_request *req;
struct lh7a40x_ep *ep;
@@ -2140,6 +2142,7 @@ static int lh7a40x_udc_remove(struct device *_dev)
static struct device_driver udc_driver = {
.name = (char *)driver_name,
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = lh7a40x_udc_probe,
.remove = lh7a40x_udc_remove
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 477fab2e74d1..0dc6bb00bf72 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -376,7 +376,7 @@ static int net2280_disable (struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
{
struct net2280_ep *ep;
struct net2280_request *req;
@@ -463,7 +463,7 @@ net2280_alloc_buffer (
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned gfp_flags
+ gfp_t gfp_flags
)
{
void *retval;
@@ -897,7 +897,7 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
/*-------------------------------------------------------------------------*/
static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct net2280_request *req;
struct net2280_ep *ep;
@@ -2948,6 +2948,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver net2280_pci_driver = {
.name = (char *) driver_name,
.id_table = pci_ids,
+ .owner = THIS_MODULE,
.probe = net2280_probe,
.remove = net2280_remove,
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index ff5533e69560..387692a3611e 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -38,7 +38,7 @@
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/moduleparam.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb_otg.h>
@@ -269,7 +269,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
/*-------------------------------------------------------------------------*/
static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags)
+omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
{
struct omap_req *req;
@@ -298,7 +298,7 @@ omap_alloc_buffer(
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- unsigned gfp_flags
+ gfp_t gfp_flags
)
{
void *retval;
@@ -691,7 +691,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
}
static void
-finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
{
u16 count;
@@ -699,6 +699,8 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
ep->dma_counter = (u16) (req->req.dma + req->req.actual);
count = dma_dest_len(ep, req->req.dma + req->req.actual);
count += req->req.actual;
+ if (one)
+ count--;
if (count <= req->req.length)
req->req.actual = count;
@@ -747,7 +749,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
if (!list_empty(&ep->queue)) {
req = container_of(ep->queue.next,
struct omap_req, queue);
- finish_out_dma(ep, req, 0);
+ finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
}
UDC_IRQ_SRC_REG = UDC_RXN_EOT;
@@ -925,7 +927,7 @@ static void dma_channel_release(struct omap_ep *ep)
while (UDC_RXDMA_CFG_REG & mask)
udelay(10);
if (req)
- finish_out_dma(ep, req, -ECONNRESET);
+ finish_out_dma(ep, req, -ECONNRESET, 0);
}
omap_free_dma(ep->lch);
ep->dma_channel = 0;
@@ -937,7 +939,7 @@ static void dma_channel_release(struct omap_ep *ep)
/*-------------------------------------------------------------------------*/
static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct omap_ep *ep = container_of(_ep, struct omap_ep, ep);
struct omap_req *req = container_of(_req, struct omap_req, req);
@@ -1786,8 +1788,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
udc->driver->suspend(&udc->gadget);
spin_lock(&udc->lock);
}
+ if (udc->transceiver)
+ otg_set_suspend(udc->transceiver, 1);
} else {
VDBG("resume\n");
+ if (udc->transceiver)
+ otg_set_suspend(udc->transceiver, 0);
if (udc->gadget.speed == USB_SPEED_FULL
&& udc->driver->resume) {
spin_unlock(&udc->lock);
@@ -2909,12 +2915,10 @@ static int __exit omap_udc_remove(struct device *dev)
* may involve talking to an external transceiver (e.g. isp1301).
*/
-static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_udc_suspend(struct device *dev, pm_message_t message)
{
u32 devstat;
- if (level != SUSPEND_POWER_DOWN)
- return 0;
devstat = UDC_DEVSTAT_REG;
/* we're requesting 48 MHz clock if the pullup is enabled
@@ -2931,11 +2935,8 @@ static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
return 0;
}
-static int omap_udc_resume(struct device *dev, u32 level)
+static int omap_udc_resume(struct device *dev)
{
- if (level != RESUME_POWER_ON)
- return 0;
-
DBG("resume + wakeup/SRP\n");
omap_pullup(&udc->gadget, 1);
@@ -2948,6 +2949,7 @@ static int omap_udc_resume(struct device *dev, u32 level)
static struct device_driver udc_driver = {
.name = (char *) driver_name,
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = omap_udc_probe,
.remove = __exit_p(omap_udc_remove),
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 1507738337c4..ee9cd7869d92 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -43,7 +43,7 @@
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
@@ -332,7 +332,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
* pxa2xx_ep_alloc_request - allocate a request data structure
*/
static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
{
struct pxa2xx_request *req;
@@ -367,7 +367,7 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
*/
static void *
pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, unsigned gfp_flags)
+ dma_addr_t *dma, gfp_t gfp_flags)
{
char *retval;
@@ -874,7 +874,7 @@ done:
/*-------------------------------------------------------------------------*/
static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct pxa2xx_request *req;
struct pxa2xx_ep *ep;
@@ -2602,24 +2602,23 @@ static int __exit pxa2xx_udc_remove(struct device *_dev)
* VBUS IRQs should probably be ignored so that the PXA device just acts
* "dead" to USB hosts until system resume.
*/
-static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level)
+static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state)
{
struct pxa2xx_udc *udc = dev_get_drvdata(dev);
- if (level == SUSPEND_POWER_DOWN) {
- if (!udc->mach->udc_command)
- WARN("USB host won't detect disconnect!\n");
- pullup(udc, 0);
- }
+ if (!udc->mach->udc_command)
+ WARN("USB host won't detect disconnect!\n");
+ pullup(udc, 0);
+
return 0;
}
-static int pxa2xx_udc_resume(struct device *dev, u32 level)
+static int pxa2xx_udc_resume(struct device *dev)
{
struct pxa2xx_udc *udc = dev_get_drvdata(dev);
- if (level == RESUME_POWER_ON)
- pullup(udc, 1);
+ pullup(udc, 1);
+
return 0;
}
@@ -2632,6 +2631,7 @@ static int pxa2xx_udc_resume(struct device *dev, u32 level)
static struct device_driver udc_driver = {
.name = "pxa2xx-udc",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = pxa2xx_udc_probe,
.shutdown = pxa2xx_udc_shutdown,
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index d0bc396a85d5..19a883f7d1b8 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -73,7 +73,7 @@ struct pxa2xx_ep {
volatile u32 *reg_ubcr;
volatile u32 *reg_uddr;
#ifdef USE_DMA
- volatile u32 *reg_drcmr;
+ volatile u32 *reg_drcmr;
#define drcmr(n) .reg_drcmr = & DRCMR ## n ,
#else
#define drcmr(n)
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 9e4f1c6935a5..b35ac6d334f8 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
u8 type, unsigned int index, int is_otg);
static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
- unsigned kmalloc_flags);
+ gfp_t kmalloc_flags);
static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
- unsigned kmalloc_flags);
+ gfp_t kmalloc_flags);
static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags);
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
static void gs_free_ports(struct gs_dev *dev);
/* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags);
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
static void gs_buf_free(struct gs_buf *gb);
static void gs_buf_clear(struct gs_buf *gb);
static unsigned int gs_buf_data_avail(struct gs_buf *gb);
@@ -1422,49 +1422,20 @@ static int gs_bind(struct usb_gadget *gadget)
int ret;
struct usb_ep *ep;
struct gs_dev *dev;
+ int gcnum;
- /* device specific */
- if (gadget_is_net2280(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
- } else if (gadget_is_pxa(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
- } else if (gadget_is_sh(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
- /* sh doesn't support multiple interfaces or configs */
+ /* Some controllers can't support CDC ACM:
+ * - sh doesn't support multiple interfaces or configs;
+ * - sa1100 doesn't have a third interrupt endpoint
+ */
+ if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
use_acm = 0;
- } else if (gadget_is_sa1100(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
- /* sa1100 doesn't support necessary endpoints */
- use_acm = 0;
- } else if (gadget_is_goku(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
- } else if (gadget_is_mq11xx(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
- } else if (gadget_is_omap(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
- } else if (gadget_is_lh7a40x(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
- } else if (gadget_is_n9604(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0009);
- } else if (gadget_is_pxa27x(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0011);
- } else if (gadget_is_s3c2410(gadget)) {
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
- } else if (gadget_is_at91(gadget)) {
+
+ gcnum = usb_gadget_controller_number(gadget);
+ if (gcnum >= 0)
gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
- } else {
+ cpu_to_le16(GS_VERSION_NUM | gcnum);
+ else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name);
/* unrecognized, but safe unless bulk is REALLY quirky */
@@ -2120,7 +2091,7 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
* usb_request or NULL if there is an error.
*/
static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)
+gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
{
struct usb_request *req;
@@ -2161,7 +2132,7 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
* endpoint, buffer len, and kmalloc flags.
*/
static struct gs_req_entry *
-gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)
+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
struct gs_req_entry *req;
@@ -2202,7 +2173,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
*
* The device lock is normally held when calling this function.
*/
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
{
int i;
struct gs_port *port;
@@ -2284,7 +2255,7 @@ static void gs_free_ports(struct gs_dev *dev)
*
* Allocate a circular buffer and all associated memory.
*/
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
{
struct gs_buf *gb;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index bb9b2d94eed5..6c58636e914b 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -612,7 +612,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
}
static struct usb_request *
-source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
+source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
{
struct usb_request *req;
int status;
@@ -640,7 +640,7 @@ source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
}
static int
-set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags)
+set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_ep *ep;
@@ -744,7 +744,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
}
static int
-set_loopback_config (struct zero_dev *dev, unsigned gfp_flags)
+set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
{
int result = 0;
struct usb_ep *ep;
@@ -845,7 +845,7 @@ static void zero_reset_config (struct zero_dev *dev)
* by limiting configuration choices (like the pxa2xx).
*/
static int
-zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags)
+zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
{
int result = 0;
struct usb_gadget *gadget = dev->gadget;
@@ -1139,6 +1139,13 @@ zero_bind (struct usb_gadget *gadget)
{
struct zero_dev *dev;
struct usb_ep *ep;
+ int gcnum;
+
+ /* FIXME this can't yet work right with SH ... it has only
+ * one configuration, numbered one.
+ */
+ if (gadget_is_sh(gadget))
+ return -ENODEV;
/* Bulk-only drivers like this one SHOULD be able to
* autoconfigure on any sane usb controller driver,
@@ -1161,43 +1168,10 @@ autoconf_fail:
EP_OUT_NAME = ep->name;
ep->driver_data = ep; /* claim */
-
- /*
- * DRIVER POLICY CHOICE: you may want to do this differently.
- * One thing to avoid is reusing a bcdDevice revision code
- * with different host-visible configurations or behavior
- * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
- */
- if (gadget_is_net2280 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
- } else if (gadget_is_pxa (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
-#if 0
- } else if (gadget_is_sh(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
- /* SH has only one configuration; see "loopdefault" */
- device_desc.bNumConfigurations = 1;
- /* FIXME make 1 == default.bConfigurationValue */
-#endif
- } else if (gadget_is_sa1100 (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
- } else if (gadget_is_goku (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
- } else if (gadget_is_mq11xx (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
- } else if (gadget_is_omap (gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
- } else if (gadget_is_lh7a40x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
- } else if (gadget_is_n9604(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
- } else if (gadget_is_pxa27x(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
- } else if (gadget_is_s3c2410(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
- } else if (gadget_is_at91(gadget)) {
- device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
- } else {
+ gcnum = usb_gadget_controller_number (gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+ else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
* so warn about unrcognized controllers, don't panic.
@@ -1328,6 +1302,7 @@ static struct usb_gadget_driver zero_driver = {
.driver = {
.name = (char *) shortname,
+ .owner = THIS_MODULE,
// .shutdown = ...
// .suspend = ...
// .resume = ...
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 350d14fc1cc9..58321d3f314c 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -1,8 +1,9 @@
#
-# Makefile for USB Host Controller Driver
-# framework and drivers
+# Makefile for USB Host Controller Drivers
#
+obj-$(CONFIG_PCI) += pci-quirks.o
+
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 50cb01831075..65ac9fef3a7c 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -527,7 +527,7 @@ show_periodic (struct class_device *class_dev, char *buf)
p.qh->period,
le32_to_cpup (&p.qh->hw_info2)
/* uframe masks */
- & 0xffff,
+ & (QH_CMASK | QH_SMASK),
p.qh);
size -= temp;
next += temp;
@@ -641,7 +641,7 @@ show_registers (struct class_device *class_dev, char *buf)
spin_lock_irqsave (&ehci->lock, flags);
- if (bus->controller->power.power_state) {
+ if (bus->controller->power.power_state.event) {
size = scnprintf (next, size,
"bus %s, device %s (driver " DRIVER_VERSION ")\n"
"%s\n"
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 149b13fc0a71..af3c05eb86fc 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -182,6 +182,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
{
u32 temp = readl (&ehci->regs->status);
+ /* disable any irqs left enabled by previous code */
+ writel (0, &ehci->regs->intr_enable);
+
if ((temp & STS_HALT) != 0)
return 0;
@@ -297,50 +300,17 @@ static void ehci_watchdog (unsigned long param)
spin_unlock_irqrestore (&ehci->lock, flags);
}
-#ifdef CONFIG_PCI
-
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
+/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+ * This forcibly disables dma and IRQs, helping kexec and other cases
+ * where the next system software may expect clean state.
*/
-static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
-{
- struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
- /* always say Linux will own the hardware */
- pci_write_config_byte(pdev, where + 3, 1);
-
- /* maybe wait a while for BIOS to respond */
- if (cap & (1 << 16)) {
- int msec = 5000;
-
- do {
- msleep(10);
- msec -= 10;
- pci_read_config_dword(pdev, where, &cap);
- } while ((cap & (1 << 16)) && msec);
- if (cap & (1 << 16)) {
- ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
- where, cap);
- // some BIOS versions seem buggy...
- // return 1;
- ehci_warn (ehci, "continuing after BIOS bug...\n");
- /* disable all SMIs, and clear "BIOS owns" flag */
- pci_write_config_dword(pdev, where + 4, 0);
- pci_write_config_byte(pdev, where + 2, 0);
- } else
- ehci_dbg(ehci, "BIOS handoff succeeded\n");
- }
- return 0;
-}
-
-#endif
-
static int
ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
{
struct ehci_hcd *ehci;
ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+ (void) ehci_halt (ehci);
/* make BIOS/etc use companion controller during reboot */
writel (0, &ehci->regs->configured_flag);
@@ -363,139 +333,90 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
msleep(20);
}
+/*-------------------------------------------------------------------------*/
+
+/*
+ * ehci_work is called from some interrupts, timers, and so on.
+ * it calls driver completion functions, after dropping ehci->lock.
+ */
+static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
+{
+ timer_action_done (ehci, TIMER_IO_WATCHDOG);
+ if (ehci->reclaim_ready)
+ end_unlink_async (ehci, regs);
+
+ /* another CPU may drop ehci->lock during a schedule scan while
+ * it reports urb completions. this flag guards against bogus
+ * attempts at re-entrant schedule scanning.
+ */
+ if (ehci->scanning)
+ return;
+ ehci->scanning = 1;
+ scan_async (ehci, regs);
+ if (ehci->next_uframe != -1)
+ scan_periodic (ehci, regs);
+ ehci->scanning = 0;
-/* called by khubd or root hub init threads */
+ /* the IO watchdog guards against hardware or driver bugs that
+ * misplace IRQs, and should let us run completely without IRQs.
+ * such lossage has been observed on both VT6202 and VT8235.
+ */
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+ (ehci->async->qh_next.ptr != NULL ||
+ ehci->periodic_sched != 0))
+ timer_action (ehci, TIMER_IO_WATCHDOG);
+}
-static int ehci_hc_reset (struct usb_hcd *hcd)
+static void ehci_stop (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 temp;
- unsigned count = 256/4;
- spin_lock_init (&ehci->lock);
+ ehci_dbg (ehci, "stop\n");
- ehci->caps = hcd->regs;
- ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
- dbg_hcs_params (ehci, "reset");
- dbg_hcc_params (ehci, "reset");
+ /* Turn off port power on all root hub ports. */
+ ehci_port_power (ehci, 0);
- /* cache this readonly data; minimize chip reads */
- ehci->hcs_params = readl (&ehci->caps->hcs_params);
+ /* no more interrupts ... */
+ del_timer_sync (&ehci->watchdog);
-#ifdef CONFIG_PCI
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ spin_lock_irq(&ehci->lock);
+ if (HC_IS_RUNNING (hcd->state))
+ ehci_quiesce (ehci);
- switch (pdev->vendor) {
- case PCI_VENDOR_ID_TDI:
- if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
- ehci->is_tdi_rh_tt = 1;
- tdi_reset (ehci);
- }
- break;
- case PCI_VENDOR_ID_AMD:
- /* AMD8111 EHCI doesn't work, according to AMD errata */
- if (pdev->device == 0x7463) {
- ehci_info (ehci, "ignoring AMD8111 (errata)\n");
- return -EIO;
- }
- break;
- }
+ ehci_reset (ehci);
+ writel (0, &ehci->regs->intr_enable);
+ spin_unlock_irq(&ehci->lock);
- /* optional debug port, normally in the first BAR */
- temp = pci_find_capability (pdev, 0x0a);
- if (temp) {
- pci_read_config_dword(pdev, temp, &temp);
- temp >>= 16;
- if ((temp & (3 << 13)) == (1 << 13)) {
- temp &= 0x1fff;
- ehci->debug = hcd->regs + temp;
- temp = readl (&ehci->debug->control);
- ehci_info (ehci, "debug port %d%s\n",
- HCS_DEBUG_PORT(ehci->hcs_params),
- (temp & DBGP_ENABLED)
- ? " IN USE"
- : "");
- if (!(temp & DBGP_ENABLED))
- ehci->debug = NULL;
- }
- }
+ /* let companion controllers work when we aren't */
+ writel (0, &ehci->regs->configured_flag);
+ unregister_reboot_notifier (&ehci->reboot_notifier);
- temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
- } else
- temp = 0;
-
- /* EHCI 0.96 and later may have "extended capabilities" */
- while (temp && count--) {
- u32 cap;
-
- pci_read_config_dword (to_pci_dev(hcd->self.controller),
- temp, &cap);
- ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
- switch (cap & 0xff) {
- case 1: /* BIOS/SMM/... handoff */
- if (bios_handoff (ehci, temp, cap) != 0)
- return -EOPNOTSUPP;
- break;
- case 0: /* illegal reserved capability */
- ehci_warn (ehci, "illegal capability!\n");
- cap = 0;
- /* FALLTHROUGH */
- default: /* unknown */
- break;
- }
- temp = (cap >> 8) & 0xff;
- }
- if (!count) {
- ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
- return -EIO;
- }
- if (ehci_is_TDI(ehci))
- ehci_reset (ehci);
-#endif
+ remove_debug_files (ehci);
- ehci_port_power (ehci, 0);
+ /* root hub is shut down separately (first, when possible) */
+ spin_lock_irq (&ehci->lock);
+ if (ehci->async)
+ ehci_work (ehci, NULL);
+ spin_unlock_irq (&ehci->lock);
+ ehci_mem_cleanup (ehci);
- /* at least the Genesys GL880S needs fixup here */
- temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
- temp &= 0x0f;
- if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
- ehci_dbg (ehci, "bogus port configuration: "
- "cc=%d x pcc=%d < ports=%d\n",
- HCS_N_CC(ehci->hcs_params),
- HCS_N_PCC(ehci->hcs_params),
- HCS_N_PORTS(ehci->hcs_params));
-
-#ifdef CONFIG_PCI
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev;
-
- pdev = to_pci_dev(hcd->self.controller);
- switch (pdev->vendor) {
- case 0x17a0: /* GENESYS */
- /* GL880S: should be PORTS=2 */
- temp |= (ehci->hcs_params & ~0xf);
- ehci->hcs_params = temp;
- break;
- case PCI_VENDOR_ID_NVIDIA:
- /* NF4: should be PCC=10 */
- break;
- }
- }
+#ifdef EHCI_STATS
+ ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+ ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+ ehci->stats.lost_iaa);
+ ehci_dbg (ehci, "complete %ld unlink %ld\n",
+ ehci->stats.complete, ehci->stats.unlink);
#endif
- }
- /* force HC to halt state */
- return ehci_halt (ehci);
+ dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
}
-static int ehci_start (struct usb_hcd *hcd)
+static int ehci_run (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
int retval;
u32 hcc_params;
- u8 sbrn = 0;
int first;
/* skip some things on restart paths */
@@ -534,25 +455,6 @@ static int ehci_start (struct usb_hcd *hcd)
}
writel (ehci->periodic_dma, &ehci->regs->frame_list);
-#ifdef CONFIG_PCI
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev;
- u16 port_wake;
-
- pdev = to_pci_dev(hcd->self.controller);
-
- /* Serial Bus Release Number is at PCI 0x60 offset */
- pci_read_config_byte(pdev, 0x60, &sbrn);
-
- /* port wake capability, reported by boot firmware */
- pci_read_config_word(pdev, 0x62, &port_wake);
- hcd->can_wakeup = (port_wake & 1) != 0;
-
- /* help hc dma work well with cachelines */
- pci_set_mwi (pdev);
- }
-#endif
-
/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
@@ -648,7 +550,7 @@ static int ehci_start (struct usb_hcd *hcd)
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci,
"USB %x.%x %s, EHCI %x.%02x, driver %s\n",
- ((sbrn & 0xf0)>>4), (sbrn & 0x0f),
+ ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
first ? "initialized" : "restarted",
temp >> 8, temp & 0xff, DRIVER_VERSION);
@@ -660,184 +562,6 @@ static int ehci_start (struct usb_hcd *hcd)
return 0;
}
-/* always called by thread; normally rmmod */
-
-static void ehci_stop (struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
-
- ehci_dbg (ehci, "stop\n");
-
- /* Turn off port power on all root hub ports. */
- ehci_port_power (ehci, 0);
-
- /* no more interrupts ... */
- del_timer_sync (&ehci->watchdog);
-
- spin_lock_irq(&ehci->lock);
- if (HC_IS_RUNNING (hcd->state))
- ehci_quiesce (ehci);
-
- ehci_reset (ehci);
- writel (0, &ehci->regs->intr_enable);
- spin_unlock_irq(&ehci->lock);
-
- /* let companion controllers work when we aren't */
- writel (0, &ehci->regs->configured_flag);
- unregister_reboot_notifier (&ehci->reboot_notifier);
-
- remove_debug_files (ehci);
-
- /* root hub is shut down separately (first, when possible) */
- spin_lock_irq (&ehci->lock);
- if (ehci->async)
- ehci_work (ehci, NULL);
- spin_unlock_irq (&ehci->lock);
- ehci_mem_cleanup (ehci);
-
-#ifdef EHCI_STATS
- ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
- ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
- ehci->stats.lost_iaa);
- ehci_dbg (ehci, "complete %ld unlink %ld\n",
- ehci->stats.complete, ehci->stats.unlink);
-#endif
-
- dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
-}
-
-static int ehci_get_frame (struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PM
-
-/* suspend/resume, section 4.3 */
-
-/* These routines rely on the bus (pci, platform, etc)
- * to handle powerdown and wakeup, and currently also on
- * transceivers that don't need any software attention to set up
- * the right sort of wakeup.
- */
-
-static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message)
-{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
-
- if (time_before (jiffies, ehci->next_statechange))
- msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
- (void) usb_suspend_device (hcd->self.root_hub, message);
-#else
- usb_lock_device (hcd->self.root_hub);
- (void) ehci_hub_suspend (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
- // save (PCI) FLADJ in case of Vaux power loss
- // ... we'd only use it to handle clock skew
-
- return 0;
-}
-
-static int ehci_resume (struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- unsigned port;
- struct usb_device *root = hcd->self.root_hub;
- int retval = -EINVAL;
-
- // maybe restore (PCI) FLADJ
-
- if (time_before (jiffies, ehci->next_statechange))
- msleep (100);
-
- /* If any port is suspended, we know we can/must resume the HC. */
- for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
- u32 status;
- port--;
- status = readl (&ehci->regs->port_status [port]);
- if (status & PORT_SUSPEND) {
- down (&hcd->self.root_hub->serialize);
- retval = ehci_hub_resume (hcd);
- up (&hcd->self.root_hub->serialize);
- break;
- }
- if (!root->children [port])
- continue;
- dbg_port (ehci, __FUNCTION__, port + 1, status);
- usb_set_device_state (root->children[port],
- USB_STATE_NOTATTACHED);
- }
-
- /* Else reset, to cope with power loss or flush-to-storage
- * style "resume" having activated BIOS during reboot.
- */
- if (port == 0) {
- (void) ehci_halt (ehci);
- (void) ehci_reset (ehci);
- (void) ehci_hc_reset (hcd);
-
- /* emptying the schedule aborts any urbs */
- spin_lock_irq (&ehci->lock);
- if (ehci->reclaim)
- ehci->reclaim_ready = 1;
- ehci_work (ehci, NULL);
- spin_unlock_irq (&ehci->lock);
-
- /* restart; khubd will disconnect devices */
- retval = ehci_start (hcd);
-
- /* here we "know" root ports should always stay powered;
- * but some controllers may lose all power.
- */
- ehci_port_power (ehci, 1);
- }
-
- return retval;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * ehci_work is called from some interrupts, timers, and so on.
- * it calls driver completion functions, after dropping ehci->lock.
- */
-static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
-{
- timer_action_done (ehci, TIMER_IO_WATCHDOG);
- if (ehci->reclaim_ready)
- end_unlink_async (ehci, regs);
-
- /* another CPU may drop ehci->lock during a schedule scan while
- * it reports urb completions. this flag guards against bogus
- * attempts at re-entrant schedule scanning.
- */
- if (ehci->scanning)
- return;
- ehci->scanning = 1;
- scan_async (ehci, regs);
- if (ehci->next_uframe != -1)
- scan_periodic (ehci, regs);
- ehci->scanning = 0;
-
- /* the IO watchdog guards against hardware or driver bugs that
- * misplace IRQs, and should let us run completely without IRQs.
- * such lossage has been observed on both VT6202 and VT8235.
- */
- if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
- (ehci->async->qh_next.ptr != NULL ||
- ehci->periodic_sched != 0))
- timer_action (ehci, TIMER_IO_WATCHDOG);
-}
-
/*-------------------------------------------------------------------------*/
static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
@@ -960,7 +684,7 @@ static int ehci_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
struct list_head qtd_list;
@@ -1124,8 +848,7 @@ rescan:
case QH_STATE_UNLINK: /* wait for hw to finish? */
idle_timeout:
spin_unlock_irqrestore (&ehci->lock, flags);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (1);
+ schedule_timeout_uninterruptible(1);
goto rescan;
case QH_STATE_IDLE: /* fully unlinked */
if (list_empty (&qh->qtd_list)) {
@@ -1149,106 +872,24 @@ done:
return;
}
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_driver = {
- .description = hcd_name,
- .product_desc = "EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_hc_reset,
- .start = ehci_start,
-#ifdef CONFIG_PM
- .suspend = ehci_suspend,
- .resume = ehci_resume,
-#endif
- .stop = ehci_stop,
-
- /*
- * 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,
- .hub_suspend = ehci_hub_suspend,
- .hub_resume = ehci_hub_resume,
-};
+static int ehci_get_frame (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+}
/*-------------------------------------------------------------------------*/
-/* EHCI 1.0 doesn't require PCI */
-
-#ifdef CONFIG_PCI
-
-/* PCI driver selection metadata; PCI hotplugging uses this */
-static const struct pci_device_id pci_ids [] = { {
- /* handle any USB 2.0 EHCI controller */
- PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
- .driver_data = (unsigned long) &ehci_driver,
- },
- { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver ehci_pci_driver = {
- .name = (char *) hcd_name,
- .id_table = pci_ids,
-
- .probe = usb_hcd_pci_probe,
- .remove = usb_hcd_pci_remove,
-
-#ifdef CONFIG_PM
- .suspend = usb_hcd_pci_suspend,
- .resume = usb_hcd_pci_resume,
-#endif
-};
-
-#endif /* PCI */
-
-
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
MODULE_DESCRIPTION (DRIVER_INFO);
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_LICENSE ("GPL");
-static int __init init (void)
-{
- if (usb_disabled())
- return -ENODEV;
-
- pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
- hcd_name,
- sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
- sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
-
- return pci_register_driver (&ehci_pci_driver);
-}
-module_init (init);
+#ifdef CONFIG_PCI
+#include "ehci-pci.c"
+#endif
-static void __exit cleanup (void)
-{
- pci_unregister_driver (&ehci_pci_driver);
-}
-module_exit (cleanup);
+#if !defined(CONFIG_PCI)
+#error "missing bus glue for ehci-hcd"
+#endif
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 36cc1f2218d5..88cb4ada686e 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -30,7 +30,7 @@
#ifdef CONFIG_PM
-static int ehci_hub_suspend (struct usb_hcd *hcd)
+static int ehci_bus_suspend (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int port;
@@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* suspend any active/unsuspended ports, maybe allow wakeup */
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
- u32 t1 = readl (reg);
+ u32 t1 = readl (reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -83,7 +83,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* caller has locked the root hub, and should reset/reinit on error */
-static int ehci_hub_resume (struct usb_hcd *hcd)
+static int ehci_bus_resume (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
@@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
- temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
+ temp &= ~(PORT_RWC_BITS
+ | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
if (temp & PORT_SUSPEND) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME;
@@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
temp = readl (&ehci->regs->port_status [i]);
if ((temp & PORT_SUSPEND) == 0)
continue;
- temp &= ~PORT_RESUME;
+ temp &= ~(PORT_RWC_BITS | PORT_RESUME);
writel (temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
@@ -158,8 +159,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
#else
-#define ehci_hub_suspend NULL
-#define ehci_hub_resume NULL
+#define ehci_bus_suspend NULL
+#define ehci_bus_resume NULL
#endif /* CONFIG_PM */
@@ -191,6 +192,7 @@ static int check_reset_complete (
// what happens if HCS_N_CC(params) == 0 ?
port_status |= PORT_OWNER;
+ port_status &= ~PORT_RWC_BITS;
writel (port_status, &ehci->regs->port_status [index]);
} else
@@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (temp & PORT_OWNER) {
/* don't report this in GetPortStatus */
if (temp & PORT_CSC) {
- temp &= ~PORT_CSC;
+ temp &= ~PORT_RWC_BITS;
+ temp |= PORT_CSC;
writel (temp, &ehci->regs->port_status [i]);
}
continue;
@@ -343,7 +346,7 @@ static int ehci_hub_control (
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_ENABLE:
- writel (temp | PORT_PEC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_SUSPEND:
@@ -353,7 +356,8 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0)
goto error;
/* resume signaling for 20 msec */
- writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
+ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ writel (temp | PORT_RESUME,
&ehci->regs->port_status [wIndex]);
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (20);
@@ -364,15 +368,15 @@ static int ehci_hub_control (
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
- writel (temp & ~PORT_POWER,
+ writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_CONNECTION:
- writel (temp | PORT_CSC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- writel (temp | PORT_OCC,
+ writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_RESET:
@@ -416,7 +420,7 @@ static int ehci_hub_control (
/* stop resume signaling */
temp = readl (&ehci->regs->port_status [wIndex]);
- writel (temp & ~PORT_RESUME,
+ writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
&ehci->regs->port_status [wIndex]);
retval = handshake (
&ehci->regs->port_status [wIndex],
@@ -437,7 +441,7 @@ static int ehci_hub_control (
ehci->reset_done [wIndex] = 0;
/* force reset to complete */
- writel (temp & ~PORT_RESET,
+ writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
&ehci->regs->port_status [wIndex]);
/* REVISIT: some hardware needs 550+ usec to clear
* this bit; seems too long to spin routinely...
@@ -500,6 +504,7 @@ static int ehci_hub_control (
if (temp & PORT_OWNER)
break;
+ temp &= ~PORT_RWC_BITS;
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
if ((temp & PORT_PE) == 0
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 5c38ad869485..91c2ab43cbcc 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -45,7 +45,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
INIT_LIST_HEAD (&qtd->qtd_list);
}
-static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
{
struct ehci_qtd *qtd;
dma_addr_t dma;
@@ -79,7 +79,7 @@ static void qh_destroy (struct kref *kref)
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
}
-static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
{
struct ehci_qh *qh;
dma_addr_t dma;
@@ -161,7 +161,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
}
/* remember to add cleanup code (above) if you add anything here */
-static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
{
int i;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
new file mode 100644
index 000000000000..145008853966
--- /dev/null
+++ b/drivers/usb/host/ehci-pci.c
@@ -0,0 +1,415 @@
+/*
+ * EHCI HCD (Host Controller Driver) PCI Bus Glue.
+ *
+ * Copyright (c) 2000-2004 by 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CONFIG_PCI
+#error "This file is PCI bus glue. CONFIG_PCI must be defined."
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
+ * off the controller (maybe it can boot from highspeed USB disks).
+ */
+static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
+{
+ struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
+
+ /* always say Linux will own the hardware */
+ pci_write_config_byte(pdev, where + 3, 1);
+
+ /* maybe wait a while for BIOS to respond */
+ if (cap & (1 << 16)) {
+ int msec = 5000;
+
+ do {
+ msleep(10);
+ msec -= 10;
+ pci_read_config_dword(pdev, where, &cap);
+ } while ((cap & (1 << 16)) && msec);
+ if (cap & (1 << 16)) {
+ ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
+ where, cap);
+ // some BIOS versions seem buggy...
+ // return 1;
+ ehci_warn (ehci, "continuing after BIOS bug...\n");
+ /* disable all SMIs, and clear "BIOS owns" flag */
+ pci_write_config_dword(pdev, where + 4, 0);
+ pci_write_config_byte(pdev, where + 2, 0);
+ } else
+ ehci_dbg(ehci, "BIOS handoff succeeded\n");
+ }
+ return 0;
+}
+
+/* called by khubd or root hub init threads */
+static int ehci_pci_reset (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 temp;
+ unsigned count = 256/4;
+
+ spin_lock_init (&ehci->lock);
+
+ ehci->caps = hcd->regs;
+ ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
+ dbg_hcs_params (ehci, "reset");
+ dbg_hcc_params (ehci, "reset");
+
+ /* cache this readonly data; minimize chip reads */
+ ehci->hcs_params = readl (&ehci->caps->hcs_params);
+
+ if (hcd->self.controller->bus == &pci_bus_type) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_TDI:
+ if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ ehci->is_tdi_rh_tt = 1;
+ tdi_reset (ehci);
+ }
+ break;
+ case PCI_VENDOR_ID_AMD:
+ /* AMD8111 EHCI doesn't work, according to AMD errata */
+ if (pdev->device == 0x7463) {
+ ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+ return -EIO;
+ }
+ break;
+ case PCI_VENDOR_ID_NVIDIA:
+ /* NVidia reports that certain chips don't handle
+ * QH, ITD, or SITD addresses above 2GB. (But TD,
+ * data buffer, and periodic schedule are normal.)
+ */
+ switch (pdev->device) {
+ case 0x003c: /* MCP04 */
+ case 0x005b: /* CK804 */
+ case 0x00d8: /* CK8 */
+ case 0x00e8: /* CK8S */
+ if (pci_set_consistent_dma_mask(pdev,
+ DMA_31BIT_MASK) < 0)
+ ehci_warn (ehci, "can't enable NVidia "
+ "workaround for >2GB RAM\n");
+ break;
+ }
+ break;
+ }
+
+ /* optional debug port, normally in the first BAR */
+ temp = pci_find_capability (pdev, 0x0a);
+ if (temp) {
+ pci_read_config_dword(pdev, temp, &temp);
+ temp >>= 16;
+ if ((temp & (3 << 13)) == (1 << 13)) {
+ temp &= 0x1fff;
+ ehci->debug = hcd->regs + temp;
+ temp = readl (&ehci->debug->control);
+ ehci_info (ehci, "debug port %d%s\n",
+ HCS_DEBUG_PORT(ehci->hcs_params),
+ (temp & DBGP_ENABLED)
+ ? " IN USE"
+ : "");
+ if (!(temp & DBGP_ENABLED))
+ ehci->debug = NULL;
+ }
+ }
+
+ temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+ } else
+ temp = 0;
+
+ /* EHCI 0.96 and later may have "extended capabilities" */
+ while (temp && count--) {
+ u32 cap;
+
+ pci_read_config_dword (to_pci_dev(hcd->self.controller),
+ temp, &cap);
+ ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
+ switch (cap & 0xff) {
+ case 1: /* BIOS/SMM/... handoff */
+ if (bios_handoff (ehci, temp, cap) != 0)
+ return -EOPNOTSUPP;
+ break;
+ case 0: /* illegal reserved capability */
+ ehci_warn (ehci, "illegal capability!\n");
+ cap = 0;
+ /* FALLTHROUGH */
+ default: /* unknown */
+ break;
+ }
+ temp = (cap >> 8) & 0xff;
+ }
+ if (!count) {
+ ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
+ return -EIO;
+ }
+ if (ehci_is_TDI(ehci))
+ ehci_reset (ehci);
+
+ ehci_port_power (ehci, 0);
+
+ /* at least the Genesys GL880S needs fixup here */
+ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
+ temp &= 0x0f;
+ if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
+ ehci_dbg (ehci, "bogus port configuration: "
+ "cc=%d x pcc=%d < ports=%d\n",
+ HCS_N_CC(ehci->hcs_params),
+ HCS_N_PCC(ehci->hcs_params),
+ HCS_N_PORTS(ehci->hcs_params));
+
+ if (hcd->self.controller->bus == &pci_bus_type) {
+ struct pci_dev *pdev;
+
+ pdev = to_pci_dev(hcd->self.controller);
+ switch (pdev->vendor) {
+ case 0x17a0: /* GENESYS */
+ /* GL880S: should be PORTS=2 */
+ temp |= (ehci->hcs_params & ~0xf);
+ ehci->hcs_params = temp;
+ break;
+ case PCI_VENDOR_ID_NVIDIA:
+ /* NF4: should be PCC=10 */
+ break;
+ }
+ }
+ }
+
+ /* force HC to halt state */
+ return ehci_halt (ehci);
+}
+
+static int ehci_pci_start (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ int result = 0;
+
+ if (hcd->self.controller->bus == &pci_bus_type) {
+ struct pci_dev *pdev;
+ u16 port_wake;
+
+ pdev = to_pci_dev(hcd->self.controller);
+
+ /* Serial Bus Release Number is at PCI 0x60 offset */
+ pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+
+ /* port wake capability, reported by boot firmware */
+ pci_read_config_word(pdev, 0x62, &port_wake);
+ hcd->can_wakeup = (port_wake & 1) != 0;
+
+ /* help hc dma work well with cachelines */
+ result = pci_set_mwi(pdev);
+ if (result)
+ ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
+ }
+
+ return ehci_run (hcd);
+}
+
+/* always called by thread; normally rmmod */
+
+static void ehci_pci_stop (struct usb_hcd *hcd)
+{
+ ehci_stop (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+/* These routines rely on the bus (pci, platform, etc)
+ * to handle powerdown and wakeup, and currently also on
+ * transceivers that don't need any software attention to set up
+ * the right sort of wakeup.
+ */
+
+static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+
+ if (time_before (jiffies, ehci->next_statechange))
+ msleep (100);
+
+#ifdef CONFIG_USB_SUSPEND
+ (void) usb_suspend_device (hcd->self.root_hub);
+#else
+ usb_lock_device (hcd->self.root_hub);
+ (void) ehci_bus_suspend (hcd);
+ usb_unlock_device (hcd->self.root_hub);
+#endif
+
+ // save (PCI) FLADJ in case of Vaux power loss
+ // ... we'd only use it to handle clock skew
+
+ return 0;
+}
+
+static int ehci_pci_resume (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ unsigned port;
+ struct usb_device *root = hcd->self.root_hub;
+ int retval = -EINVAL;
+
+ // maybe restore (PCI) FLADJ
+
+ if (time_before (jiffies, ehci->next_statechange))
+ msleep (100);
+
+ /* If any port is suspended (or owned by the companion),
+ * we know we can/must resume the HC (and mustn't reset it).
+ */
+ for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+ u32 status;
+ port--;
+ status = readl (&ehci->regs->port_status [port]);
+ if (!(status & PORT_POWER))
+ continue;
+ if (status & (PORT_SUSPEND | PORT_OWNER)) {
+ down (&hcd->self.root_hub->serialize);
+ retval = ehci_bus_resume (hcd);
+ up (&hcd->self.root_hub->serialize);
+ break;
+ }
+ if (!root->children [port])
+ continue;
+ dbg_port (ehci, __FUNCTION__, port + 1, status);
+ usb_set_device_state (root->children[port],
+ USB_STATE_NOTATTACHED);
+ }
+
+ /* Else reset, to cope with power loss or flush-to-storage
+ * style "resume" having activated BIOS during reboot.
+ */
+ if (port == 0) {
+ (void) ehci_halt (ehci);
+ (void) ehci_reset (ehci);
+ (void) ehci_pci_reset (hcd);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq (&ehci->lock);
+ if (ehci->reclaim)
+ ehci->reclaim_ready = 1;
+ ehci_work (ehci, NULL);
+ spin_unlock_irq (&ehci->lock);
+
+ /* restart; khubd will disconnect devices */
+ retval = ehci_run (hcd);
+
+ /* here we "know" root ports should always stay powered;
+ * but some controllers may lose all power.
+ */
+ ehci_port_power (ehci, 1);
+ }
+
+ return retval;
+}
+#endif
+
+static const struct hc_driver ehci_pci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_pci_reset,
+ .start = ehci_pci_start,
+#ifdef CONFIG_PM
+ .suspend = ehci_pci_suspend,
+ .resume = ehci_pci_resume,
+#endif
+ .stop = ehci_pci_stop,
+
+ /*
+ * 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,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* PCI driver selection metadata; PCI hotplugging uses this */
+static const struct pci_device_id pci_ids [] = { {
+ /* handle any USB 2.0 EHCI controller */
+ PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+ .driver_data = (unsigned long) &ehci_pci_hc_driver,
+ },
+ { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ehci_pci_driver = {
+ .name = (char *) hcd_name,
+ .id_table = pci_ids,
+ .owner = THIS_MODULE,
+
+ .probe = usb_hcd_pci_probe,
+ .remove = usb_hcd_pci_remove,
+
+#ifdef CONFIG_PM
+ .suspend = usb_hcd_pci_suspend,
+ .resume = usb_hcd_pci_resume,
+#endif
+};
+
+static int __init ehci_hcd_pci_init (void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+ hcd_name,
+ sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
+ sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+
+ return pci_register_driver (&ehci_pci_driver);
+}
+module_init (ehci_hcd_pci_init);
+
+static void __exit ehci_hcd_pci_cleanup (void)
+{
+ pci_unregister_driver (&ehci_pci_driver);
+}
+module_exit (ehci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4f97a4ad1ed3..5bb872c3496d 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -222,7 +222,7 @@ __acquires(ehci->lock)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
/* S-mask in a QH means it's an interrupt urb */
- if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
+ if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
/* ... update hc-wide periodic stats (for usbfs) */
ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -428,7 +428,8 @@ halt:
/* should be rare for periodic transfers,
* except maybe high bandwidth ...
*/
- if (qh->period) {
+ if ((__constant_cpu_to_le32 (QH_SMASK)
+ & qh->hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else
@@ -476,7 +477,7 @@ qh_urb_transaction (
struct ehci_hcd *ehci,
struct urb *urb,
struct list_head *head,
- int flags
+ gfp_t flags
) {
struct ehci_qtd *qtd, *qtd_prev;
dma_addr_t buf;
@@ -628,7 +629,7 @@ static struct ehci_qh *
qh_make (
struct ehci_hcd *ehci,
struct urb *urb,
- int flags
+ gfp_t flags
) {
struct ehci_qh *qh = ehci_qh_alloc (ehci, flags);
u32 info1 = 0, info2 = 0;
@@ -676,6 +677,9 @@ qh_make (
goto done;
}
} else {
+ struct usb_tt *tt = urb->dev->tt;
+ int think_time;
+
/* gap is f(FS/LS transfer times) */
qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
is_input, 0, maxp) / (125 * 1000);
@@ -689,6 +693,10 @@ qh_make (
qh->c_usecs = HS_USECS (0);
}
+ think_time = tt ? tt->think_time : 0;
+ qh->tt_usecs = NS_TO_US (think_time +
+ usb_calc_bus_time (urb->dev->speed,
+ is_input, 0, max_packet (maxp)));
qh->period = urb->interval;
}
}
@@ -898,7 +906,7 @@ submit_async (
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ehci_qtd *qtd;
int epnum;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 9af4f64532a9..f0c8aa1ccd5d 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -301,7 +301,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* high bandwidth, or otherwise every microframe */
@@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
- qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ qh->period,
+ le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* qh->qh_next still "live" to HC */
@@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
* active high speed queues may need bigger delays...
*/
if (list_empty (&qh->qtd_list)
- || (__constant_cpu_to_le32 (0x0ff << 8)
+ || (__constant_cpu_to_le32 (QH_CMASK)
& qh->hw_info2) != 0)
wait = 2;
else
@@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
- uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff);
+ uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
@@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
- qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff);
+ qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
qh->hw_info2 |= qh->period
? cpu_to_le32 (1 << uframe)
- : __constant_cpu_to_le32 (0xff);
+ : __constant_cpu_to_le32 (QH_SMASK);
qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@ -588,7 +589,7 @@ static int intr_submit (
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
- unsigned mem_flags
+ gfp_t mem_flags
) {
unsigned epnum;
unsigned long flags;
@@ -633,11 +634,11 @@ done:
/* ehci_iso_stream ops work with both ITD and SITD */
static struct ehci_iso_stream *
-iso_stream_alloc (unsigned mem_flags)
+iso_stream_alloc (gfp_t mem_flags)
{
struct ehci_iso_stream *stream;
- stream = kcalloc(1, sizeof *stream, mem_flags);
+ stream = kzalloc(sizeof *stream, mem_flags);
if (likely (stream != NULL)) {
INIT_LIST_HEAD(&stream->td_list);
INIT_LIST_HEAD(&stream->free_list);
@@ -699,6 +700,7 @@ iso_stream_init (
} else {
u32 addr;
+ int think_time;
addr = dev->ttport << 24;
if (!ehci_is_TDI(ehci)
@@ -708,6 +710,9 @@ iso_stream_init (
addr |= epnum << 8;
addr |= dev->devnum;
stream->usecs = HS_USECS_ISO (maxp);
+ think_time = dev->tt ? dev->tt->think_time : 0;
+ stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
+ dev->speed, is_input, 1, maxp));
if (is_input) {
u32 tmp;
@@ -846,7 +851,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/* ehci_iso_sched ops can be ITD-only or SITD-only */
static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets, unsigned mem_flags)
+iso_sched_alloc (unsigned packets, gfp_t mem_flags)
{
struct ehci_iso_sched *iso_sched;
int size = sizeof *iso_sched;
@@ -919,7 +924,7 @@ itd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
struct ehci_itd *itd;
@@ -1413,7 +1418,7 @@ itd_complete (
/*-------------------------------------------------------------------------*/
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
@@ -1524,7 +1529,7 @@ sitd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
)
{
struct ehci_sitd *sitd;
@@ -1774,7 +1779,7 @@ sitd_complete (
static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 4df498231752..18e257c2bdb5 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -97,6 +97,7 @@ struct ehci_hcd { /* one per controller */
#else
# define COUNT(x) do {} while (0)
#endif
+ u8 sbrn; /* packed release number */
};
/* convert between an HCD pointer and the corresponding EHCI_HCD */
@@ -263,6 +264,7 @@ struct ehci_regs {
#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));
/* Appendix C, Debug port ... intended for use with special "debug devices"
@@ -385,6 +387,11 @@ struct ehci_qh {
__le32 hw_info1; /* see EHCI 3.6.2 */
#define QH_HEAD 0x00008000
__le32 hw_info2; /* see EHCI 3.6.2 */
+#define QH_SMASK 0x000000ff
+#define QH_CMASK 0x0000ff00
+#define QH_HUBADDR 0x007f0000
+#define QH_HUBPORT 0x3f800000
+#define QH_MULT 0xc0000000
__le32 hw_current; /* qtd list - see EHCI 3.6.4 */
/* qtd overlay (hardware parts of a struct ehci_qtd) */
@@ -416,6 +423,7 @@ struct ehci_qh {
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */
u8 c_usecs; /* ... split completion bw */
+ u16 tt_usecs; /* tt downstream bandwidth */
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
@@ -474,6 +482,7 @@ struct ehci_iso_stream {
*/
u8 interval;
u8 usecs, c_usecs;
+ u16 tt_usecs;
u16 maxp;
u16 raw_mask;
unsigned bandwidth;
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 81f8f6b7fdce..a8267cf17db4 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -178,8 +178,8 @@ static __u8 root_hub_hub_des[] =
0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
};
-static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0);
+static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
/* We want the start timer to expire before the eot timer, because the former might start
traffic, thus making it unnecessary for the latter to time out. */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 50b1970fe6b6..f9c3f5b8dd1c 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -70,6 +70,7 @@
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb_isp116x.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -83,7 +84,7 @@
#include "../core/hcd.h"
#include "isp116x.h"
-#define DRIVER_VERSION "08 Apr 2005"
+#define DRIVER_VERSION "05 Aug 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -229,9 +230,11 @@ static void preproc_atl_queue(struct isp116x *isp116x)
struct isp116x_ep *ep;
struct urb *urb;
struct ptd *ptd;
- u16 toggle = 0, dir = PTD_DIR_SETUP, len;
+ u16 len;
for (ep = isp116x->atl_active; ep; ep = ep->active) {
+ u16 toggle = 0, dir = PTD_DIR_SETUP;
+
BUG_ON(list_empty(&ep->hep->urb_list));
urb = container_of(ep->hep->urb_list.next,
struct urb, urb_list);
@@ -324,7 +327,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
usb_settoggle(udev, ep->epnum,
ep->nextpid ==
USB_PID_OUT,
- PTD_GET_TOGGLE(ptd) ^ 1);
+ PTD_GET_TOGGLE(ptd));
+ urb->actual_length += PTD_GET_COUNT(ptd);
urb->status = cc_to_error[TD_DATAUNDERRUN];
spin_unlock(&urb->lock);
continue;
@@ -627,17 +631,15 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
ERR("Unrecoverable error\n");
/* What should we do here? Reset? */
}
- if (intstat & HCINT_RHSC) {
- isp116x->rhstatus =
- isp116x_read_reg32(isp116x, HCRHSTATUS);
- isp116x->rhport[0] =
- isp116x_read_reg32(isp116x, HCRHPORT1);
- isp116x->rhport[1] =
- isp116x_read_reg32(isp116x, HCRHPORT2);
- }
+ if (intstat & HCINT_RHSC)
+ /* When root hub or any of its ports is going
+ to come out of suspend, it may take more
+ than 10ms for status bits to stabilize. */
+ mod_timer(&hcd->rh_timer, jiffies
+ + msecs_to_jiffies(20) + 1);
if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n");
- schedule_work(&isp116x->rh_resume);
+ usb_hcd_resume_root_hub(hcd);
ret = IRQ_HANDLED;
}
irqstat &= ~HCuPINT_OPR;
@@ -693,7 +695,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
static int isp116x_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *hep, struct urb *urb,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
struct usb_device *udev = urb->dev;
@@ -715,7 +717,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
}
/* avoid all allocations within spinlocks: request or endpoint */
if (!hep->hcpriv) {
- ep = kcalloc(1, sizeof *ep, mem_flags);
+ ep = kzalloc(sizeof *ep, mem_flags);
if (!ep)
return -ENOMEM;
}
@@ -923,20 +925,27 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
int ports, i, changed = 0;
+ unsigned long flags;
if (!HC_IS_RUNNING(hcd->state))
return -ESHUTDOWN;
- ports = isp116x->rhdesca & RH_A_NDP;
+ /* Report no status change now, if we are scheduled to be
+ called later */
+ if (timer_pending(&hcd->rh_timer))
+ return 0;
- /* init status */
+ ports = isp116x->rhdesca & RH_A_NDP;
+ spin_lock_irqsave(&isp116x->lock, flags);
+ isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))
buf[0] = changed = 1;
else
buf[0] = 0;
for (i = 0; i < ports; i++) {
- u32 status = isp116x->rhport[i];
+ u32 status = isp116x->rhport[i] =
+ isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
| RH_PS_OCIC | RH_PS_PRSC)) {
@@ -945,6 +954,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
continue;
}
}
+ spin_unlock_irqrestore(&isp116x->lock, flags);
return changed;
}
@@ -1151,7 +1161,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
#ifdef CONFIG_PM
-static int isp116x_hub_suspend(struct usb_hcd *hcd)
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long flags;
@@ -1191,7 +1201,7 @@ static int isp116x_hub_suspend(struct usb_hcd *hcd)
return ret;
}
-static int isp116x_hub_resume(struct usb_hcd *hcd)
+static int isp116x_bus_resume(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
u32 val;
@@ -1254,21 +1264,11 @@ static int isp116x_hub_resume(struct usb_hcd *hcd)
return 0;
}
-static void isp116x_rh_resume(void *_hcd)
-{
- struct usb_hcd *hcd = _hcd;
-
- usb_resume_device(hcd->self.root_hub);
-}
#else
-#define isp116x_hub_suspend NULL
-#define isp116x_hub_resume NULL
-
-static void isp116x_rh_resume(void *_hcd)
-{
-}
+#define isp116x_bus_suspend NULL
+#define isp116x_bus_resume NULL
#endif
@@ -1461,10 +1461,6 @@ static int isp116x_sw_reset(struct isp116x *isp116x)
return ret;
}
-/*
- Reset. Tries to perform platform-specific hardware
- reset first; falls back to software reset.
-*/
static int isp116x_reset(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
@@ -1472,17 +1468,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
u16 clkrdy = 0;
int ret = 0, timeout = 15 /* ms */ ;
- if (isp116x->board && isp116x->board->reset) {
- /* Hardware reset */
- isp116x->board->reset(hcd->self.controller, 1);
- msleep(10);
- if (isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 1);
- msleep(1);
- isp116x->board->reset(hcd->self.controller, 0);
- } else
- ret = isp116x_sw_reset(isp116x);
-
+ ret = isp116x_sw_reset(isp116x);
if (ret)
return ret;
@@ -1499,10 +1485,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
ERR("Clock not ready after 20ms\n");
/* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */
- if (!isp116x->board || !isp116x->board->reset)
- ERR("The driver does not support hardware wakeup.\n");
- ERR("Please make sure that the H_WAKEUP pin "
- "is pulled low!\n");
+ ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
ret = -ENODEV;
}
return ret;
@@ -1525,15 +1508,7 @@ static void isp116x_stop(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
spin_unlock_irqrestore(&isp116x->lock, flags);
- /* Put the chip into reset state */
- if (isp116x->board && isp116x->board->reset)
- isp116x->board->reset(hcd->self.controller, 0);
- else
- isp116x_sw_reset(isp116x);
-
- /* Stop the clock */
- if (isp116x->board && isp116x->board->clock)
- isp116x->board->clock(hcd->self.controller, 0);
+ isp116x_sw_reset(isp116x);
}
/*
@@ -1559,6 +1534,9 @@ static int isp116x_start(struct usb_hcd *hcd)
return -ENODEV;
}
+ /* To be removed in future */
+ hcd->uses_new_polling = 1;
+
isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
@@ -1567,7 +1545,7 @@ static int isp116x_start(struct usb_hcd *hcd)
if (board->sel15Kres)
val |= HCHWCFG_15KRSEL;
/* Remote wakeup won't work without working clock */
- if (board->clknotstop || board->remote_wakeup_enable)
+ if (board->remote_wakeup_enable)
val |= HCHWCFG_CLKNOTSTOP;
if (board->oc_enable)
val |= HCHWCFG_ANALOG_OC;
@@ -1578,16 +1556,13 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg16(isp116x, HCHWCFG, val);
/* ----- Root hub conf */
- val = 0;
- /* AN10003_1.pdf recommends NPS to be always 1 */
- if (board->no_power_switching)
- val |= RH_A_NPS;
- if (board->power_switching_mode)
- val |= RH_A_PSM;
- if (board->potpg)
- val |= (board->potpg << 24) & RH_A_POTPGT;
- else
- val |= (25 << 24) & RH_A_POTPGT;
+ val = (25 << 24) & RH_A_POTPGT;
+ /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+ be always set. Yet, instead, we request individual port
+ power switching. */
+ val |= RH_A_PSM;
+ /* Report overcurrent per port */
+ val |= RH_A_OCPM;
isp116x_write_reg32(isp116x, HCRHDESCA, val);
isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
@@ -1617,9 +1592,6 @@ static int isp116x_start(struct usb_hcd *hcd)
/* Go operational */
val = HCCONTROL_USB_OPER;
- /* Remote wakeup connected - NOT SUPPORTED */
- /* if (board->remote_wakeup_connected)
- val |= HCCONTROL_RWC; */
if (board->remote_wakeup_enable)
val |= HCCONTROL_RWE;
isp116x_write_reg32(isp116x, HCCONTROL, val);
@@ -1655,8 +1627,8 @@ static struct hc_driver isp116x_hc_driver = {
.hub_status_data = isp116x_hub_status_data,
.hub_control = isp116x_hub_control,
- .hub_suspend = isp116x_hub_suspend,
- .hub_resume = isp116x_hub_resume,
+ .bus_suspend = isp116x_bus_suspend,
+ .bus_resume = isp116x_bus_resume,
};
/*----------------------------------------------------------------*/
@@ -1668,7 +1640,7 @@ static int __init_or_module isp116x_remove(struct device *dev)
struct platform_device *pdev;
struct resource *res;
- if(!hcd)
+ if (!hcd)
return 0;
isp116x = hcd_to_isp116x(hcd);
pdev = container_of(dev, struct platform_device, dev);
@@ -1751,7 +1723,6 @@ static int __init isp116x_probe(struct device *dev)
isp116x->addr_reg = addr_reg;
spin_lock_init(&isp116x->lock);
INIT_LIST_HEAD(&isp116x->async);
- INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd);
isp116x->board = dev->platform_data;
if (!isp116x->board) {
@@ -1793,22 +1764,13 @@ static int __init isp116x_probe(struct device *dev)
/*
Suspend of platform device
*/
-static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
+static int isp116x_suspend(struct device *dev, pm_message_t state)
{
int ret = 0;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- VDBG("%s: state %x, phase %x\n", __func__, state, phase);
-
- if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN)
- return 0;
+ VDBG("%s: state %x\n", __func__, state);
- ret = usb_suspend_device(hcd->self.root_hub, state);
- if (!ret) {
- dev->power.power_state = state;
- INFO("%s suspended\n", hcd_name);
- } else
- ERR("%s suspend failed\n", hcd_name);
+ dev->power.power_state = state;
return ret;
}
@@ -1816,21 +1778,14 @@ static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
/*
Resume platform device
*/
-static int isp116x_resume(struct device *dev, u32 phase)
+static int isp116x_resume(struct device *dev)
{
int ret = 0;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state,
- phase);
- if (phase != RESUME_POWER_ON)
- return 0;
+ VDBG("%s: state %x\n", __func__, dev->power.power_state);
+
+ dev->power.power_state = PMSG_ON;
- ret = usb_resume_device(hcd->self.root_hub);
- if (!ret) {
- dev->power.power_state = PMSG_ON;
- VDBG("%s resumed\n", (char *)hcd_name);
- }
return ret;
}
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index 58873470dcf5..c6fec96785fe 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -253,7 +253,6 @@ static const int cc_to_error[16] = {
struct isp116x {
spinlock_t lock;
- struct work_struct rh_resume;
void __iomem *addr_reg;
void __iomem *data_reg;
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 3981bf15c8c7..f0c78cf14b6c 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -18,6 +18,8 @@
* This file is licenced under the GPL.
*/
+#include <linux/platform_device.h>
+
#include <asm/mach-au1x00/au1000.h>
#define USBH_ENABLE_BE (1<<0)
@@ -214,6 +216,11 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
@@ -259,6 +266,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
static struct device_driver ohci_hcd_au1xxx_driver = {
.name = "au1xxx-ohci",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = ohci_hcd_au1xxx_drv_probe,
.remove = ohci_hcd_au1xxx_drv_remove,
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index c58408c95c3d..7bfffcbbd226 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -193,10 +193,6 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
maybe_print_eds (controller, "donehead",
ohci_readl (controller, &regs->donehead), next, size);
-
- /* broken fminterval means traffic won't flow! */
- ohci_dbg (controller, "fminterval %08x\n",
- ohci_readl (controller, &regs->fminterval));
}
#define dbg_port_sw(hc,num,value,next,size) \
@@ -228,23 +224,22 @@ ohci_dump_roothub (
char **next,
unsigned *size)
{
- u32 temp, ndp, i;
+ u32 temp, i;
temp = roothub_a (controller);
if (temp == ~(u32)0)
return;
- ndp = (temp & RH_A_NDP);
if (verbose) {
ohci_dbg_sw (controller, next, size,
- "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+ "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
((temp & RH_A_POTPGT) >> 24) & 0xff,
(temp & RH_A_NOCP) ? " NOCP" : "",
(temp & RH_A_OCPM) ? " OCPM" : "",
(temp & RH_A_DT) ? " DT" : "",
(temp & RH_A_NPS) ? " NPS" : "",
(temp & RH_A_PSM) ? " PSM" : "",
- ndp
+ (temp & RH_A_NDP), controller->num_ports
);
temp = roothub_b (controller);
ohci_dbg_sw (controller, next, size,
@@ -266,7 +261,7 @@ ohci_dump_roothub (
);
}
- for (i = 0; i < ndp; i++) {
+ for (i = 0; i < controller->num_ports; i++) {
temp = roothub_portstatus (controller, i);
dbg_port_sw (controller, i, temp, next, size);
}
@@ -631,7 +626,7 @@ show_registers (struct class_device *class_dev, char *buf)
hcd->product_desc,
hcd_name);
- if (bus->controller->power.power_state) {
+ if (bus->controller->power.power_state.event) {
size -= scnprintf (next, size,
"SUSPENDED (no register access)\n");
goto done;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 56b43f2a0e52..5c0c6c8a7a82 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -180,7 +180,7 @@ static int ohci_urb_enqueue (
struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
struct ed *ed;
@@ -382,8 +382,7 @@ sanitize:
goto sanitize;
}
spin_unlock_irqrestore (&ohci->lock, flags);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (1);
+ schedule_timeout_uninterruptible(1);
goto rescan;
case ED_IDLE: /* fully unlinked */
if (list_empty (&ed->td_list)) {
@@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
// flush the writes
(void) ohci_readl (ohci, &ohci->regs->control);
+ /* Read the number of ports unless overridden */
+ if (ohci->num_ports == 0)
+ ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
if (ohci->hcca)
return 0;
@@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
msleep(temp);
temp = roothub_a (ohci);
if (!(temp & RH_A_NPS)) {
- unsigned ports = temp & RH_A_NDP;
-
/* power down each port */
- for (temp = 0; temp < ports; temp++)
+ for (temp = 0; temp < ohci->num_ports; temp++)
ohci_writel (ohci, RH_PS_LSDA,
&ohci->regs->roothub.portstatus [temp]);
}
@@ -720,8 +721,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_RD) {
ohci_vdbg (ohci, "resume detect\n");
+ ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
if (hcd->state != HC_STATE_QUIESCING)
- schedule_work(&ohci->rh_resume);
+ usb_hcd_resume_root_hub(hcd);
}
if (ints & OHCI_INTR_WDH) {
@@ -789,7 +791,7 @@ static void ohci_stop (struct usb_hcd *hcd)
/* must not be called from interrupt context */
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
static int ohci_restart (struct ohci_hcd *ohci)
{
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* and that if we try to turn them back on the root hub
* will respond to CSC processing.
*/
- i = roothub_a (ohci) & RH_A_NDP;
+ i = ohci->num_ports;
while (i--)
ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [temp]);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 83ca4549a50e..e01e77bc324b 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -36,7 +36,7 @@
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
#define OHCI_SCHED_ENABLES \
(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
@@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
static int ohci_restart (struct ohci_hcd *ohci);
-static int ohci_hub_suspend (struct usb_hcd *hcd)
+static int ohci_bus_suspend (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int status = 0;
@@ -73,7 +73,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci_dbg (ohci, "suspend root hub\n");
/* First stop any processing */
- hcd->state = HC_STATE_QUIESCING;
if (ohci->hc_control & OHCI_SCHED_ENABLES) {
int limit;
@@ -108,7 +107,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
else
ohci->hc_control &= ~OHCI_CTRL_RWE;
- /* Suspend hub */
+ /* Suspend hub ... this is the "global (to this bus) suspend" mode,
+ * which doesn't imply ports will first be individually suspended.
+ */
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
@@ -118,8 +119,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci->next_statechange = jiffies + msecs_to_jiffies (5);
done:
+ /* external suspend vs self autosuspend ... same effect */
if (status == 0)
- hcd->state = HC_STATE_SUSPENDED;
+ usb_hcd_suspend_root_hub(hcd);
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
@@ -133,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed)
}
/* caller has locked the root hub */
-static int ohci_hub_resume (struct usb_hcd *hcd)
+static int ohci_bus_resume (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
u32 temp, enables;
@@ -146,7 +148,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
- /* this can happen after suspend-to-disk */
+ /* this can happen after resuming a swsusp snapshot */
if (hcd->state == HC_STATE_RESUMING) {
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
@@ -169,11 +171,12 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci_info (ohci, "wakeup\n");
break;
case OHCI_USB_OPER:
- ohci_dbg (ohci, "already resumed\n");
- status = 0;
+ /* this can happen after resuming a swsusp snapshot */
+ ohci_dbg (ohci, "snapshot resume? reinit\n");
+ status = -EBUSY;
break;
default: /* RESET, we lost power */
- ohci_dbg (ohci, "root hub hardware reset\n");
+ ohci_dbg (ohci, "lost power\n");
status = -EBUSY;
}
spin_unlock_irq (&ohci->lock);
@@ -184,7 +187,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (status != -EINPROGRESS)
return status;
- temp = roothub_a (ohci) & RH_A_NDP;
+ temp = ohci->num_ports;
enables = 0;
while (temp--) {
u32 stat = ohci_readl (ohci,
@@ -198,8 +201,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
}
/* Some controllers (lucent erratum) need extra-long delays */
- hcd->state = HC_STATE_RESUMING;
- mdelay (20 /* usb 11.5.1.10 */ + 15);
+ msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
temp = ohci_readl (ohci, &ohci->regs->control);
temp &= OHCI_CTRL_HCFS;
@@ -273,28 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
(void) ohci_readl (ohci, &ohci->regs->control);
}
- hcd->state = HC_STATE_RUNNING;
return 0;
}
-static void ohci_rh_resume (void *_hcd)
-{
- struct usb_hcd *hcd = _hcd;
-
- usb_lock_device (hcd->self.root_hub);
- (void) ohci_hub_resume (hcd);
- usb_unlock_device (hcd->self.root_hub);
-}
-
-#else
-
-static void ohci_rh_resume (void *_hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (_hcd);
- ohci_dbg(ohci, "rh_resume ??\n");
-}
-
-#endif /* CONFIG_USB_SUSPEND || CONFIG_PM */
+#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
@@ -304,7 +288,7 @@ static int
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ports, i, changed = 0, length = 1;
+ int i, changed = 0, length = 1;
int can_suspend = hcd->can_wakeup;
unsigned long flags;
@@ -319,9 +303,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
goto done;
}
- ports = roothub_a (ohci) & RH_A_NDP;
- if (ports > MAX_ROOT_PORTS) {
- ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+ /* undocumented erratum seen on at least rev D */
+ if ((ohci->flags & OHCI_QUIRK_AMD756)
+ && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+ ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
goto done;
@@ -332,13 +317,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
buf [0] = changed = 1;
else
buf [0] = 0;
- if (ports > 7) {
+ if (ohci->num_ports > 7) {
buf [1] = 0;
length++;
}
/* look at each port */
- for (i = 0; i < ports; i++) {
+ for (i = 0; i < ohci->num_ports; i++) {
u32 status = roothub_portstatus (ohci, i);
if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -366,7 +351,6 @@ done:
#ifdef CONFIG_PM
/* save power by suspending idle root hubs;
* INTR_RD wakes us when there's work
- * NOTE: if we can do this, we don't need a root hub timer!
*/
if (can_suspend
&& !changed
@@ -378,8 +362,7 @@ done:
&& usb_trylock_device (hcd->self.root_hub)
) {
ohci_vdbg (ohci, "autosuspend\n");
- (void) ohci_hub_suspend (hcd);
- hcd->state = HC_STATE_RUNNING;
+ (void) ohci_bus_suspend (hcd);
usb_unlock_device (hcd->self.root_hub);
}
#endif
@@ -395,15 +378,14 @@ ohci_hub_descriptor (
struct usb_hub_descriptor *desc
) {
u32 rh = roothub_a (ohci);
- int ports = rh & RH_A_NDP;
u16 temp;
desc->bDescriptorType = 0x29;
desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
desc->bHubContrCurrent = 0;
- desc->bNbrPorts = ports;
- temp = 1 + (ports / 8);
+ desc->bNbrPorts = ohci->num_ports;
+ temp = 1 + (ohci->num_ports / 8);
desc->bDescLength = 7 + 2 * temp;
temp = 0;
@@ -421,7 +403,7 @@ ohci_hub_descriptor (
rh = roothub_b (ohci);
memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
desc->bitmap [0] = rh & RH_B_DR;
- if (ports > 7) {
+ if (ohci->num_ports > 7) {
desc->bitmap [1] = (rh & RH_B_DR) >> 8;
desc->bitmap [2] = 0xff;
} else
@@ -554,7 +536,7 @@ static int ohci_hub_control (
temp = RH_PS_POCI;
if ((ohci->hc_control & OHCI_CTRL_HCFS)
!= OHCI_USB_OPER)
- schedule_work (&ohci->rh_resume);
+ usb_hcd_resume_root_hub(hcd);
break;
case USB_PORT_FEAT_C_SUSPEND:
temp = RH_PS_PSSC;
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 817620d73841..336c766c6e29 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -16,9 +16,9 @@
* This file is licenced under the GPL.
*/
+#include <linux/platform_device.h>
+
#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
extern int usb_disabled(void);
@@ -195,6 +195,11 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
@@ -241,6 +246,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct device *dev)
static struct device_driver ohci_hcd_lh7a404_driver = {
.name = "lh7a404-ohci",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = ohci_hcd_lh7a404_drv_probe,
.remove = ohci_hcd_lh7a404_drv_remove,
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index fd3c4d3714bd..bfbe328a4788 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
ohci->next_statechange = jiffies;
spin_lock_init (&ohci->lock);
INIT_LIST_HEAD (&ohci->pending);
- INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
ohci->reboot_notifier.notifier_call = ohci_reboot;
}
@@ -84,7 +83,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
/* TDs ... */
static struct td *
-td_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct td *td;
@@ -118,7 +117,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
/* EDs ... */
static struct ed *
-ed_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
{
dma_addr_t dma;
struct ed *ed;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 5cde76faab93..e46cc540cf4d 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -14,11 +14,14 @@
* This file is licenced under the GPL.
*/
+#include <linux/signal.h> /* SA_INTERRUPT */
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
@@ -421,9 +424,9 @@ static const struct hc_driver ohci_omap_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
@@ -456,50 +459,32 @@ static int ohci_hcd_omap_drv_remove(struct device *dev)
#ifdef CONFIG_PM
-static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level)
+static int ohci_omap_suspend(struct device *dev, pm_message_t message)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
- int status = -EINVAL;
-
- if (level != SUSPEND_POWER_DOWN)
- return 0;
-
- down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- status = ohci_hub_suspend(ohci_to_hcd(ohci));
- if (status == 0) {
- omap_ohci_clock_power(0);
- ohci_to_hcd(ohci)->self.root_hub->state =
- USB_STATE_SUSPENDED;
- ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
- dev->power.power_state = PMSG_SUSPEND;
- }
- up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- return status;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ omap_ohci_clock_power(0);
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+ dev->power.power_state = PMSG_SUSPEND;
+ return 0;
}
-static int ohci_omap_resume(struct device *dev, u32 level)
+static int ohci_omap_resume(struct device *dev)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
- int status = 0;
-
- if (level != RESUME_POWER_ON)
- return 0;
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
+
omap_ohci_clock_power(1);
-#ifdef CONFIG_USB_SUSPEND
- /* get extra cleanup even if remote wakeup isn't in use */
- status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
-#else
- down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- status = ohci_hub_resume(ohci_to_hcd(ohci));
- up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-#endif
- if (status == 0)
- dev->power.power_state = PMSG_ON;
- return status;
+ dev->power.power_state = PMSG_ON;
+ usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+ return 0;
}
#endif
@@ -511,6 +496,7 @@ static int ohci_omap_resume(struct device *dev, u32 level)
*/
static struct device_driver ohci_hcd_omap_driver = {
.name = "ohci",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index eede6be098d2..7ce1d9ef0289 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -14,6 +14,8 @@
* This file is licenced under the GPL.
*/
+#include <linux/jiffies.h>
+
#ifdef CONFIG_PPC_PMAC
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
@@ -112,23 +114,13 @@ ohci_pci_start (struct usb_hcd *hcd)
static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-
- /* suspend root hub, hoping it keeps power during suspend */
- if (time_before (jiffies, ohci->next_statechange))
- msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
- (void) usb_suspend_device (hcd->self.root_hub, message);
-#else
- usb_lock_device (hcd->self.root_hub);
- (void) ohci_hub_suspend (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
+ /* root hub was already suspended */
- /* let things settle down a bit */
- msleep (100);
-
+ /* FIXME these PMAC things get called in the wrong places. ASIC
+ * clocks should be turned off AFTER entering D3, and on BEFORE
+ * trying to enter D0. Evidently the PCI layer doesn't currently
+ * provide the right sort of platform hooks for this ...
+ */
#ifdef CONFIG_PPC_PMAC
if (_machine == _MACH_Pmac) {
struct device_node *of_node;
@@ -145,9 +137,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
static int ohci_pci_resume (struct usb_hcd *hcd)
{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int retval = 0;
-
#ifdef CONFIG_PPC_PMAC
if (_machine == _MACH_Pmac) {
struct device_node *of_node;
@@ -159,19 +148,8 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
}
#endif /* CONFIG_PPC_PMAC */
- /* resume root hub */
- if (time_before (jiffies, ohci->next_statechange))
- msleep (100);
-#ifdef CONFIG_USB_SUSPEND
- /* get extra cleanup even if remote wakeup isn't in use */
- retval = usb_resume_device (hcd->self.root_hub);
-#else
- usb_lock_device (hcd->self.root_hub);
- retval = ohci_hub_resume (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
- return retval;
+ usb_hcd_resume_root_hub(hcd);
+ return 0;
}
#endif /* CONFIG_PM */
@@ -218,9 +196,9 @@ static const struct hc_driver ohci_pci_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
@@ -240,6 +218,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver ohci_pci_driver = {
.name = (char *) hcd_name,
.id_table = pci_ids,
+ .owner = THIS_MODULE,
.probe = usb_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 17964c39d06a..92cf6f4a1374 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -14,7 +14,7 @@
* This file is licenced under the GPL.
*/
-#include <asm/usb.h>
+#include <linux/platform_device.h>
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -23,9 +23,7 @@
* usb_hcd_ppc_soc_probe - initialize On-Chip 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.
+ * Allocates basic resources for this USB host controller.
*
* Store this function in the HCD's struct pci_driver as probe().
*/
@@ -37,7 +35,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
struct ohci_hcd *ohci;
struct resource *res;
int irq;
- struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
pr_debug("initializing PPC-SOC USB Controller\n");
@@ -73,9 +70,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
goto err2;
}
- if (pd->start && (retval = pd->start(pdev)))
- goto err3;
-
ohci = hcd_to_ohci(hcd);
ohci->flags |= OHCI_BIG_ENDIAN;
ohci_hcd_init(ohci);
@@ -85,9 +79,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
return retval;
pr_debug("Removing PPC-SOC USB Controller\n");
- if (pd && pd->stop)
- pd->stop(pdev);
- err3:
+
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -105,25 +97,21 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
* @pdev: USB Host Controller being removed
* Context: !in_interrupt()
*
- * Reverses the effect of usb_hcd_ppc_soc_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
+ * Reverses the effect of usb_hcd_ppc_soc_probe().
+ * It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
- struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
-
usb_remove_hcd(hcd);
pr_debug("stopping PPC-SOC USB Controller\n");
- if (pd && pd->stop)
- pd->stop(pdev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_hcd_put(hcd);
+ usb_put_hcd(hcd);
}
static int __devinit
@@ -177,9 +165,9 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
@@ -207,10 +195,11 @@ static int ohci_hcd_ppc_soc_drv_remove(struct device *dev)
static struct device_driver ohci_hcd_ppc_soc_driver = {
.name = "ppc-soc-ohci",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = ohci_hcd_ppc_soc_drv_probe,
.remove = ohci_hcd_ppc_soc_drv_remove,
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
/*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
/*.resume = ohci_hcd_ppc_soc_drv_resume,*/
#endif
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e5bc1789d18a..59e20568e8f9 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -20,6 +20,9 @@
*/
#include <linux/device.h>
+#include <linux/signal.h>
+#include <linux/platform_device.h>
+
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -75,33 +78,6 @@ static int pxa27x_ohci_select_pmm( int mode )
return 0;
}
-/*
- If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_set_port_power( int port )
-{
- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
- UHCRHPS(port) |= 0x100;
- return 0;
- }
- return -1;
-}
-
-/*
- If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_clear_port_power( int port )
-{
- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
- UHCRHPS(port) |= 0x200;
- return 0;
- }
-
- return -1;
-}
-
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
@@ -130,11 +106,17 @@ static void pxa27x_start_hc(struct platform_device *dev)
Polarity Low to active low. Supply power to USB ports. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
}
UHCHR &= ~UHCHR_SSE;
UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
+
+ /* Clear any OTG Pin Hold */
+ if (PSSR & PSSR_OTGPH)
+ PSSR |= PSSR_OTGPH;
}
static void pxa27x_stop_hc(struct platform_device *dev)
@@ -198,17 +180,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
pxa27x_start_hc(dev);
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );
-
- /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
- if (pxa27x_ohci_set_port_power(1) < 0)
- printk(KERN_ERR "Setting port 1 power failed.\n");
-
- if (pxa27x_ohci_clear_port_power(2) < 0)
- printk(KERN_ERR "Setting port 2 power failed.\n");
-
- if (pxa27x_ohci_clear_port_power(3) < 0)
- printk(KERN_ERR "Setting port 3 power failed.\n");
+ pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
ohci_hcd_init(hcd_to_ohci(hcd));
@@ -258,6 +230,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
+ /* The value of NDP in roothub_a is incorrect on this hardware */
+ ohci->num_ports = 3;
+
if ((ret = ohci_init(ohci)) < 0)
return ret;
@@ -306,10 +281,11 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
+ .start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
@@ -337,7 +313,7 @@ static int ohci_hcd_pxa27x_drv_remove(struct device *dev)
return 0;
}
-static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state)
{
// struct platform_device *pdev = to_platform_device(dev);
// struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -346,7 +322,7 @@ static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u
return 0;
}
-static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level)
+static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
{
// struct platform_device *pdev = to_platform_device(dev);
// struct usb_hcd *hcd = dev_get_drvdata(dev);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index e9401662503c..ee1fc605b402 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -19,8 +19,9 @@
* This file is licenced under the GPL.
*/
+#include <linux/platform_device.h>
+
#include <asm/hardware.h>
-#include <asm/mach-types.h>
#include <asm/hardware/clock.h>
#include <asm/arch/usb-control.h>
@@ -129,7 +130,7 @@ static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info,
if (info->power_control != NULL) {
info->port[port-1].power = to;
- (info->power_control)(port, to);
+ (info->power_control)(port-1, to);
}
}
@@ -339,8 +340,8 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
struct usb_hcd *hcd = NULL;
int retval;
- s3c2410_usb_set_power(dev->dev.platform_data, 0, 1);
s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);
+ s3c2410_usb_set_power(dev->dev.platform_data, 2, 1);
hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");
if (hcd == NULL)
@@ -449,11 +450,11 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.hub_status_data = ohci_s3c2410_hub_status_data,
.hub_control = ohci_s3c2410_hub_control,
-
-#if defined(CONFIG_USB_SUSPEND) && 0
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
+ .start_port_reset = ohci_start_port_reset,
};
/* device driver */
@@ -475,6 +476,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct device *dev)
static struct device_driver ohci_hcd_s3c2410_driver = {
.name = "s3c2410-ohci",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = ohci_hcd_s3c2410_drv_remove,
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 814d2be4ee7b..fb3221ebbb29 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -235,10 +235,11 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
-#ifdef CONFIG_USB_SUSPEND
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
+ .start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 71cdd2262860..caacf14371f5 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -383,12 +383,12 @@ struct ohci_hcd {
/*
* driver state
*/
+ int num_ports;
int load [NUM_INTS];
u32 hc_control; /* copy of hc control reg */
unsigned long next_statechange; /* suspend/resume */
u32 fminterval; /* saved register */
- struct work_struct rh_resume;
struct notifier_block reboot_notifier;
unsigned long flags; /* for HC bugs */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
new file mode 100644
index 000000000000..e46528c825bf
--- /dev/null
+++ b/drivers/usb/host/pci-quirks.c
@@ -0,0 +1,319 @@
+/*
+ * This file contains code to reset and initialize USB host controllers.
+ * Some of it includes work-arounds for PCI hardware and BIOS quirks.
+ * It may need to run early during booting -- before USB would normally
+ * initialize -- to ensure that Linux doesn't use any legacy modes.
+ *
+ * Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ * (and others)
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+
+#define UHCI_USBLEGSUP 0xc0 /* legacy support */
+#define UHCI_USBCMD 0 /* command register */
+#define UHCI_USBINTR 4 /* interrupt register */
+#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
+#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
+#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */
+#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */
+#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */
+#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */
+#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */
+
+#define OHCI_CONTROL 0x04
+#define OHCI_CMDSTATUS 0x08
+#define OHCI_INTRSTATUS 0x0c
+#define OHCI_INTRENABLE 0x10
+#define OHCI_INTRDISABLE 0x14
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
+#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
+#define OHCI_INTR_OC (1 << 30) /* ownership change */
+
+#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */
+#define EHCI_USBCMD 0 /* command register */
+#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
+#define EHCI_USBSTS 4 /* status register */
+#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */
+#define EHCI_USBINTR 8 /* interrupt register */
+#define EHCI_USBLEGSUP 0 /* legacy support register */
+#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
+#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */
+#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
+#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
+
+
+/*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+ */
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+ /* Turn off PIRQ enable and SMI enable. (This also turns off the
+ * BIOS's USB Legacy Support.) Turn off all the R/WC bits too.
+ */
+ pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
+
+ /* Reset the HC - this will force us to get a
+ * new notification of any already connected
+ * ports due to the virtual disconnect that it
+ * implies.
+ */
+ outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD);
+ mb();
+ udelay(5);
+ if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
+ dev_warn(&pdev->dev, "HCRESET not completed yet!\n");
+
+ /* Just to be safe, disable interrupt requests and
+ * make sure the controller is stopped.
+ */
+ outw(0, base + UHCI_USBINTR);
+ outw(0, base + UHCI_USBCMD);
+}
+EXPORT_SYMBOL_GPL(uhci_reset_hc);
+
+/*
+ * Initialize a controller that was newly discovered or has just been
+ * resumed. In either case we can't be sure of its previous state.
+ *
+ * Returns: 1 if the controller was reset, 0 otherwise.
+ */
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+ u16 legsup;
+ unsigned int cmd, intr;
+
+ /*
+ * When restarting a suspended controller, we expect all the
+ * settings to be the same as we left them:
+ *
+ * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
+ * Controller is stopped and configured with EGSM set;
+ * No interrupts enabled except possibly Resume Detect.
+ *
+ * If any of these conditions are violated we do a complete reset.
+ */
+ pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
+ if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
+ dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
+ __FUNCTION__, legsup);
+ goto reset_needed;
+ }
+
+ cmd = inw(base + UHCI_USBCMD);
+ if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
+ !(cmd & UHCI_USBCMD_EGSM)) {
+ dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
+ __FUNCTION__, cmd);
+ goto reset_needed;
+ }
+
+ intr = inw(base + UHCI_USBINTR);
+ if (intr & (~UHCI_USBINTR_RESUME)) {
+ dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
+ __FUNCTION__, intr);
+ goto reset_needed;
+ }
+ return 0;
+
+reset_needed:
+ dev_dbg(&pdev->dev, "Performing full reset\n");
+ uhci_reset_hc(pdev, base);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
+
+static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
+{
+ u16 cmd;
+ return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
+}
+
+#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
+#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
+
+static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+{
+ unsigned long base = 0;
+ int i;
+
+ if (!pio_enabled(pdev))
+ return;
+
+ for (i = 0; i < PCI_ROM_RESOURCE; i++)
+ if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+ base = pci_resource_start(pdev, i);
+ break;
+ }
+
+ if (base)
+ uhci_check_and_reset_hc(pdev, base);
+}
+
+static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
+{
+ return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
+}
+
+static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+{
+ void __iomem *base;
+ int wait_time;
+ u32 control;
+
+ if (!mmio_resource_enabled(pdev, 0))
+ return;
+
+ base = ioremap_nocache(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (base == NULL) return;
+
+/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
+#ifndef __hppa__
+ control = readl(base + OHCI_CONTROL);
+ if (control & OHCI_CTRL_IR) {
+ wait_time = 500; /* arbitrary; 5 seconds */
+ writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
+ writel(OHCI_OCR, base + OHCI_CMDSTATUS);
+ while (wait_time > 0 &&
+ readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
+ wait_time -= 10;
+ msleep(10);
+ }
+ if (wait_time <= 0)
+ printk(KERN_WARNING "%s %s: early BIOS handoff "
+ "failed (BIOS bug ?)\n",
+ pdev->dev.bus_id, "OHCI");
+
+ /* reset controller, preserving RWC */
+ writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
+ }
+#endif
+
+ /*
+ * disable interrupts
+ */
+ writel(~(u32)0, base + OHCI_INTRDISABLE);
+ writel(~(u32)0, base + OHCI_INTRSTATUS);
+
+ iounmap(base);
+}
+
+static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+{
+ int wait_time, delta;
+ void __iomem *base, *op_reg_base;
+ u32 hcc_params, val, temp;
+ u8 cap_length;
+
+ if (!mmio_resource_enabled(pdev, 0))
+ return;
+
+ base = ioremap_nocache(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (base == NULL) return;
+
+ cap_length = readb(base);
+ op_reg_base = base + cap_length;
+ hcc_params = readl(base + EHCI_HCC_PARAMS);
+ hcc_params = (hcc_params >> 8) & 0xff;
+ if (hcc_params) {
+ pci_read_config_dword(pdev,
+ hcc_params + EHCI_USBLEGSUP,
+ &val);
+ if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
+ /*
+ * Ok, BIOS is in smm mode, try to hand off...
+ */
+ pci_read_config_dword(pdev,
+ hcc_params + EHCI_USBLEGCTLSTS,
+ &temp);
+ pci_write_config_dword(pdev,
+ hcc_params + EHCI_USBLEGCTLSTS,
+ temp | EHCI_USBLEGCTLSTS_SOOE);
+ val |= EHCI_USBLEGSUP_OS;
+ pci_write_config_dword(pdev,
+ hcc_params + EHCI_USBLEGSUP,
+ val);
+
+ wait_time = 500;
+ do {
+ msleep(10);
+ wait_time -= 10;
+ pci_read_config_dword(pdev,
+ hcc_params + EHCI_USBLEGSUP,
+ &val);
+ } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
+ if (!wait_time) {
+ /*
+ * well, possibly buggy BIOS...
+ */
+ printk(KERN_WARNING "%s %s: early BIOS handoff "
+ "failed (BIOS bug ?)\n",
+ pdev->dev.bus_id, "EHCI");
+ pci_write_config_dword(pdev,
+ hcc_params + EHCI_USBLEGSUP,
+ EHCI_USBLEGSUP_OS);
+ pci_write_config_dword(pdev,
+ hcc_params + EHCI_USBLEGCTLSTS,
+ 0);
+ }
+ }
+ }
+
+ /*
+ * halt EHCI & disable its interrupts in any case
+ */
+ val = readl(op_reg_base + EHCI_USBSTS);
+ if ((val & EHCI_USBSTS_HALTED) == 0) {
+ val = readl(op_reg_base + EHCI_USBCMD);
+ val &= ~EHCI_USBCMD_RUN;
+ writel(val, op_reg_base + EHCI_USBCMD);
+
+ wait_time = 2000;
+ delta = 100;
+ do {
+ writel(0x3f, op_reg_base + EHCI_USBSTS);
+ udelay(delta);
+ wait_time -= delta;
+ val = readl(op_reg_base + EHCI_USBSTS);
+ if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
+ break;
+ }
+ } while (wait_time > 0);
+ }
+ writel(0, op_reg_base + EHCI_USBINTR);
+ writel(0x3f, op_reg_base + EHCI_USBSTS);
+
+ iounmap(base);
+
+ return;
+}
+
+
+
+static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+{
+ if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
+ quirk_usb_handoff_uhci(pdev);
+ else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
+ quirk_usb_handoff_ohci(pdev);
+ else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ quirk_usb_disable_ehci(pdev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 7a890a65f55d..5607c0ae6835 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -54,6 +54,7 @@
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb_sl811.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -782,6 +783,9 @@ retry:
/* usb 1.1 says max 90% of a frame is available for periodic transfers.
* this driver doesn't promise that much since it's got to handle an
* IRQ per packet; irq handling latencies also use up that time.
+ *
+ * NOTE: the periodic schedule is a sparse tree, with the load for
+ * each branch minimized. see fig 3.5 in the OHCI spec for example.
*/
#define MAX_PERIODIC_LOAD 500 /* out of 1000 usec */
@@ -815,7 +819,7 @@ static int sl811h_urb_enqueue(
struct usb_hcd *hcd,
struct usb_host_endpoint *hep,
struct urb *urb,
- unsigned mem_flags
+ gfp_t mem_flags
) {
struct sl811 *sl811 = hcd_to_sl811(hcd);
struct usb_device *udev = urb->dev;
@@ -835,7 +839,7 @@ static int sl811h_urb_enqueue(
/* avoid all allocations within spinlocks */
if (!hep->hcpriv)
- ep = kcalloc(1, sizeof *ep, mem_flags);
+ ep = kzalloc(sizeof *ep, mem_flags);
spin_lock_irqsave(&sl811->lock, flags);
@@ -843,6 +847,7 @@ static int sl811h_urb_enqueue(
if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
|| !HC_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
+ kfree(ep);
goto fail;
}
@@ -911,8 +916,16 @@ static int sl811h_urb_enqueue(
case PIPE_ISOCHRONOUS:
case PIPE_INTERRUPT:
urb->interval = ep->period;
- if (ep->branch < PERIODIC_SIZE)
+ if (ep->branch < PERIODIC_SIZE) {
+ /* NOTE: the phase is correct here, but the value
+ * needs offsetting by the transfer queue depth.
+ * All current drivers ignore start_frame, so this
+ * is unlikely to ever matter...
+ */
+ urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1))
+ + ep->branch;
break;
+ }
retval = balance(sl811, ep->period, ep->load);
if (retval < 0)
@@ -1122,7 +1135,7 @@ sl811h_hub_descriptor (
desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp);
/* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
- desc->bitmap[0] = 1 << 1;
+ desc->bitmap[0] = 0 << 1;
desc->bitmap[1] = ~0;
}
@@ -1351,7 +1364,7 @@ error:
#ifdef CONFIG_PM
static int
-sl811h_hub_suspend(struct usb_hcd *hcd)
+sl811h_bus_suspend(struct usb_hcd *hcd)
{
// SOFs off
DBG("%s\n", __FUNCTION__);
@@ -1359,7 +1372,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd)
}
static int
-sl811h_hub_resume(struct usb_hcd *hcd)
+sl811h_bus_resume(struct usb_hcd *hcd)
{
// SOFs on
DBG("%s\n", __FUNCTION__);
@@ -1368,8 +1381,8 @@ sl811h_hub_resume(struct usb_hcd *hcd)
#else
-#define sl811h_hub_suspend NULL
-#define sl811h_hub_resume NULL
+#define sl811h_bus_suspend NULL
+#define sl811h_bus_resume NULL
#endif
@@ -1611,8 +1624,8 @@ static struct hc_driver sl811h_hc_driver = {
*/
.hub_status_data = sl811h_hub_status_data,
.hub_control = sl811h_hub_control,
- .hub_suspend = sl811h_hub_suspend,
- .hub_resume = sl811h_hub_resume,
+ .bus_suspend = sl811h_bus_suspend,
+ .bus_resume = sl811h_bus_resume,
};
/*-------------------------------------------------------------------------*/
@@ -1772,18 +1785,15 @@ sl811h_probe(struct device *dev)
*/
static int
-sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct sl811 *sl811 = hcd_to_sl811(hcd);
int retval = 0;
- if (phase != SUSPEND_POWER_DOWN)
- return retval;
-
- if (state <= PM_SUSPEND_MEM)
- retval = sl811h_hub_suspend(hcd);
- else
+ if (state.event == PM_EVENT_FREEZE)
+ retval = sl811h_bus_suspend(hcd);
+ else if (state.event == PM_EVENT_SUSPEND)
port_power(sl811, 0);
if (retval == 0)
dev->power.power_state = state;
@@ -1791,18 +1801,15 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
}
static int
-sl811h_resume(struct device *dev, u32 phase)
+sl811h_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct sl811 *sl811 = hcd_to_sl811(hcd);
- if (phase != RESUME_POWER_ON)
- return 0;
-
/* with no "check to see if VBUS is still powered" board hook,
* let's assume it'd only be powered to enable remote wakeup.
*/
- if (dev->power.power_state > PM_SUSPEND_MEM
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND
|| !hcd->can_wakeup) {
sl811->port1 = 0;
port_power(sl811, 1);
@@ -1810,7 +1817,7 @@ sl811h_resume(struct device *dev, u32 phase)
}
dev->power.power_state = PMSG_ON;
- return sl811h_hub_resume(hcd);
+ return sl811h_bus_resume(hcd);
}
#else
@@ -1825,6 +1832,7 @@ sl811h_resume(struct device *dev, u32 phase)
struct device_driver sl811h_driver = {
.name = (char *) hcd_name,
.bus = &platform_bus_type,
+ .owner = THIS_MODULE,
.probe = sl811h_probe,
.remove = __devexit_p(sl811h_remove),
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 38aebe361ca1..e73faf831b24 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 4538a98b6f9d..151154df37fa 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu
if (urbp->urb->status != -EINPROGRESS)
out += sprintf(out, "Status=%d ", urbp->urb->status);
- //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
count = 0;
@@ -446,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
out += sprintf(out, "Frame List\n");
for (i = 0; i < UHCI_NUMFRAMES; ++i) {
int shown = 0;
- td = uhci->fl->frame_cpu[i];
+ td = uhci->frame_cpu[i];
if (!td)
continue;
- if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+ if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
show_frame_num();
out += sprintf(out, " frame list does not match td->dma_handle!\n");
}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 0d5d2545bf07..15e0a511069b 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -97,46 +97,20 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
-static inline void restart_timer(struct uhci_hcd *uhci)
-{
- mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
-}
-
-#include "uhci-hub.c"
#include "uhci-debug.c"
#include "uhci-q.c"
+#include "uhci-hub.c"
+
+extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
/*
- * Make sure the controller is completely inactive, unable to
- * generate interrupts or do DMA.
+ * Finish up a host controller reset and update the recorded state.
*/
-static void reset_hc(struct uhci_hcd *uhci)
+static void finish_reset(struct uhci_hcd *uhci)
{
int port;
- /* Turn off PIRQ enable and SMI enable. (This also turns off the
- * BIOS's USB Legacy Support.) Turn off all the R/WC bits too.
- */
- pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
- USBLEGSUP_RWC);
-
- /* Reset the HC - this will force us to get a
- * new notification of any already connected
- * ports due to the virtual disconnect that it
- * implies.
- */
- outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
- mb();
- udelay(5);
- if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
- dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
-
- /* Just to be safe, disable interrupt requests and
- * make sure the controller is stopped.
- */
- outw(0, uhci->io_addr + USBINTR);
- outw(0, uhci->io_addr + USBCMD);
-
/* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
* bits in the port status and control registers.
* We have to clear them by hand.
@@ -158,9 +132,9 @@ static void reset_hc(struct uhci_hcd *uhci)
*/
static void hc_died(struct uhci_hcd *uhci)
{
- reset_hc(uhci);
+ uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
+ finish_reset(uhci);
uhci->hc_inaccessible = 1;
- del_timer(&uhci->stall_timer);
}
/*
@@ -169,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci)
*/
static void check_and_reset_hc(struct uhci_hcd *uhci)
{
- u16 legsup;
- unsigned int cmd, intr;
-
- /*
- * When restarting a suspended controller, we expect all the
- * settings to be the same as we left them:
- *
- * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
- * Controller is stopped and configured with EGSM set;
- * No interrupts enabled except possibly Resume Detect.
- *
- * If any of these conditions are violated we do a complete reset.
- */
- pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
- if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
- dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
- __FUNCTION__, legsup);
- goto reset_needed;
- }
-
- cmd = inw(uhci->io_addr + USBCMD);
- if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
- dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
- __FUNCTION__, cmd);
- goto reset_needed;
- }
-
- intr = inw(uhci->io_addr + USBINTR);
- if (intr & (~USBINTR_RESUME)) {
- dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
- __FUNCTION__, intr);
- goto reset_needed;
- }
- return;
-
-reset_needed:
- dev_dbg(uhci_dev(uhci), "Performing full reset\n");
- reset_hc(uhci);
+ if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
+ finish_reset(uhci);
}
/*
@@ -218,13 +156,13 @@ static void configure_hc(struct uhci_hcd *uhci)
outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
/* Store the frame list base address */
- outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+ outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
/* Set the current frame number */
outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
- /* Mark controller as running before we enable interrupts */
- uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+ /* Mark controller as not halted before we enable interrupts */
+ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
mb();
/* Enable PIRQ */
@@ -287,8 +225,11 @@ __acquires(uhci->lock)
/* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode, still configured.
*/
- int_enable = (resume_detect_interrupts_are_broken(uhci) ?
- 0 : USBINTR_RESUME);
+ uhci->working_RD = 1;
+ int_enable = USBINTR_RESUME;
+ if (resume_detect_interrupts_are_broken(uhci)) {
+ uhci->working_RD = int_enable = 0;
+ }
outw(int_enable, uhci->io_addr + USBINTR);
outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
mb();
@@ -315,7 +256,6 @@ __acquires(uhci->lock)
uhci->rh_state = new_state;
uhci->is_stopped = UHCI_IS_STOPPED;
- del_timer(&uhci->stall_timer);
uhci_to_hcd(uhci)->poll_rh = !int_enable;
uhci_scan_schedule(uhci, NULL);
@@ -323,6 +263,7 @@ __acquires(uhci->lock)
static void start_rh(struct uhci_hcd *uhci)
{
+ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
uhci->is_stopped = 0;
smp_wmb();
@@ -335,7 +276,6 @@ static void start_rh(struct uhci_hcd *uhci)
mb();
uhci->rh_state = UHCI_RH_RUNNING;
uhci_to_hcd(uhci)->poll_rh = 1;
- restart_timer(uhci);
}
static void wakeup_rh(struct uhci_hcd *uhci)
@@ -374,20 +314,6 @@ __acquires(uhci->lock)
mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
}
-static void stall_callback(unsigned long _uhci)
-{
- struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
- unsigned long flags;
-
- spin_lock_irqsave(&uhci->lock, flags);
- uhci_scan_schedule(uhci, NULL);
- check_fsbr(uhci);
-
- if (!uhci->is_stopped)
- restart_timer(uhci);
- spin_unlock_irqrestore(&uhci->lock, flags);
-}
-
static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -418,8 +344,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
"host controller halted, "
"very bad!\n");
hc_died(uhci);
- spin_unlock_irqrestore(&uhci->lock, flags);
- return IRQ_HANDLED;
+
+ /* Force a callback in case there are
+ * pending unlinks */
+ mod_timer(&hcd->rh_timer, jiffies);
}
spin_unlock_irqrestore(&uhci->lock, flags);
}
@@ -427,10 +355,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (status & USBSTS_RD)
usb_hcd_poll_rh_status(hcd);
-
- spin_lock_irqsave(&uhci->lock, flags);
- uhci_scan_schedule(uhci, regs);
- spin_unlock_irqrestore(&uhci->lock, flags);
+ else {
+ spin_lock_irqsave(&uhci->lock, flags);
+ uhci_scan_schedule(uhci, regs);
+ spin_unlock_irqrestore(&uhci->lock, flags);
+ }
return IRQ_HANDLED;
}
@@ -453,36 +382,21 @@ static void release_uhci(struct uhci_hcd *uhci)
int i;
for (i = 0; i < UHCI_NUM_SKELQH; i++)
- if (uhci->skelqh[i]) {
- uhci_free_qh(uhci, uhci->skelqh[i]);
- uhci->skelqh[i] = NULL;
- }
+ uhci_free_qh(uhci, uhci->skelqh[i]);
- if (uhci->term_td) {
- uhci_free_td(uhci, uhci->term_td);
- uhci->term_td = NULL;
- }
+ uhci_free_td(uhci, uhci->term_td);
- if (uhci->qh_pool) {
- dma_pool_destroy(uhci->qh_pool);
- uhci->qh_pool = NULL;
- }
+ dma_pool_destroy(uhci->qh_pool);
- if (uhci->td_pool) {
- dma_pool_destroy(uhci->td_pool);
- uhci->td_pool = NULL;
- }
+ dma_pool_destroy(uhci->td_pool);
- if (uhci->fl) {
- dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
- uhci->fl, uhci->fl->dma_handle);
- uhci->fl = NULL;
- }
+ kfree(uhci->frame_cpu);
- if (uhci->dentry) {
- debugfs_remove(uhci->dentry);
- uhci->dentry = NULL;
- }
+ dma_free_coherent(uhci_dev(uhci),
+ UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ uhci->frame, uhci->frame_dma_handle);
+
+ debugfs_remove(uhci->dentry);
}
static int uhci_reset(struct usb_hcd *hcd)
@@ -561,7 +475,6 @@ static int uhci_start(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
int retval = -EBUSY;
int i;
- dma_addr_t dma_handle;
struct dentry *dentry;
hcd->uses_new_polling = 1;
@@ -595,21 +508,23 @@ static int uhci_start(struct usb_hcd *hcd)
init_waitqueue_head(&uhci->waitqh);
- init_timer(&uhci->stall_timer);
- uhci->stall_timer.function = stall_callback;
- uhci->stall_timer.data = (unsigned long) uhci;
-
- uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
- &dma_handle, 0);
- if (!uhci->fl) {
+ uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+ UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ &uhci->frame_dma_handle, 0);
+ if (!uhci->frame) {
dev_err(uhci_dev(uhci), "unable to allocate "
"consistent memory for frame list\n");
- goto err_alloc_fl;
+ goto err_alloc_frame;
}
+ memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
- memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
- uhci->fl->dma_handle = dma_handle;
+ uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
+ GFP_KERNEL);
+ if (!uhci->frame_cpu) {
+ dev_err(uhci_dev(uhci), "unable to allocate "
+ "memory for frame pointers\n");
+ goto err_alloc_frame_cpu;
+ }
uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
sizeof(struct uhci_td), 16, 0);
@@ -692,7 +607,7 @@ static int uhci_start(struct usb_hcd *hcd)
irq = 7;
/* Only place we don't use the frame list routines */
- uhci->fl->frame[i] = UHCI_PTR_QH |
+ uhci->frame[i] = UHCI_PTR_QH |
cpu_to_le32(uhci->skelqh[irq]->dma_handle);
}
@@ -710,31 +625,29 @@ static int uhci_start(struct usb_hcd *hcd)
* error exits:
*/
err_alloc_skelqh:
- for (i = 0; i < UHCI_NUM_SKELQH; i++)
- if (uhci->skelqh[i]) {
+ for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+ if (uhci->skelqh[i])
uhci_free_qh(uhci, uhci->skelqh[i]);
- uhci->skelqh[i] = NULL;
- }
+ }
uhci_free_td(uhci, uhci->term_td);
- uhci->term_td = NULL;
err_alloc_term_td:
dma_pool_destroy(uhci->qh_pool);
- uhci->qh_pool = NULL;
err_create_qh_pool:
dma_pool_destroy(uhci->td_pool);
- uhci->td_pool = NULL;
err_create_td_pool:
- dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
- uhci->fl, uhci->fl->dma_handle);
- uhci->fl = NULL;
+ kfree(uhci->frame_cpu);
+
+err_alloc_frame_cpu:
+ dma_free_coherent(uhci_dev(uhci),
+ UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ uhci->frame, uhci->frame_dma_handle);
-err_alloc_fl:
+err_alloc_frame:
debugfs_remove(uhci->dentry);
- uhci->dentry = NULL;
err_create_debug_entry:
return retval;
@@ -745,11 +658,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
spin_lock_irq(&uhci->lock);
- reset_hc(uhci);
+ if (!uhci->hc_inaccessible)
+ hc_died(uhci);
uhci_scan_schedule(uhci, NULL);
spin_unlock_irq(&uhci->lock);
- del_timer_sync(&uhci->stall_timer);
release_uhci(uhci);
}
@@ -794,14 +707,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
if (uhci->hc_inaccessible) /* Dead or already suspended */
goto done;
-#ifndef CONFIG_USB_SUSPEND
- /* Otherwise this would never happen */
- suspend_rh(uhci, UHCI_RH_SUSPENDED);
-#endif
-
if (uhci->rh_state > UHCI_RH_SUSPENDED) {
dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
- hcd->state = HC_STATE_RUNNING;
rc = -EBUSY;
goto done;
};
@@ -811,13 +718,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
*/
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
uhci->hc_inaccessible = 1;
+ hcd->poll_rh = 0;
/* FIXME: Enable non-PME# remote wakeup? */
done:
spin_unlock_irq(&uhci->lock);
- if (rc == 0)
- del_timer_sync(&hcd->rh_timer);
return rc;
}
@@ -841,17 +747,16 @@ static int uhci_resume(struct usb_hcd *hcd)
check_and_reset_hc(uhci);
configure_hc(uhci);
-#ifndef CONFIG_USB_SUSPEND
- /* Otherwise this would never happen */
- wakeup_rh(uhci);
-#endif
if (uhci->rh_state == UHCI_RH_RESET)
suspend_rh(uhci, UHCI_RH_SUSPENDED);
spin_unlock_irq(&uhci->lock);
- if (hcd->poll_rh)
+ if (!uhci->working_RD) {
+ /* Suspended root hub needs to be polled */
+ hcd->poll_rh = 1;
usb_hcd_poll_rh_status(hcd);
+ }
return 0;
}
#endif
@@ -899,8 +804,8 @@ static const struct hc_driver uhci_driver = {
#ifdef CONFIG_PM
.suspend = uhci_suspend,
.resume = uhci_resume,
- .hub_suspend = uhci_rh_suspend,
- .hub_resume = uhci_rh_resume,
+ .bus_suspend = uhci_rh_suspend,
+ .bus_resume = uhci_rh_resume,
#endif
.stop = uhci_stop,
@@ -926,6 +831,7 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
static struct pci_driver uhci_pci_driver = {
.name = (char *)hcd_name,
.id_table = uhci_pci_ids,
+ .owner = THIS_MODULE,
.probe = usb_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index bf9c5f9b508b..e576db57a926 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -7,6 +7,7 @@
#define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
#define PIPE_DEVEP_MASK 0x0007ff00
+
/*
* Universal Host Controller Interface data structures and defines
*/
@@ -82,15 +83,10 @@
#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */
#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */
-struct uhci_frame_list {
- __le32 frame[UHCI_NUMFRAMES];
-
- void *frame_cpu[UHCI_NUMFRAMES];
-
- dma_addr_t dma_handle;
-};
-struct urb_priv;
+/*
+ * Queue Headers
+ */
/*
* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is
@@ -116,13 +112,13 @@ struct uhci_qh {
struct urb_priv *urbp;
- struct list_head list; /* P: uhci->frame_list_lock */
- struct list_head remove_list; /* P: uhci->remove_list_lock */
+ struct list_head list;
+ struct list_head remove_list;
} __attribute__((aligned(16)));
/*
* We need a special accessor for the element pointer because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
*/
static __le32 inline qh_element(struct uhci_qh *qh) {
__le32 element = qh->element;
@@ -131,6 +127,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
return element;
}
+
+/*
+ * Transfer Descriptors
+ */
+
/*
* for TD <status>:
*/
@@ -183,17 +184,10 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
*
* That's silly, the hardware doesn't care. The hardware only cares that
* the hardware words are 16-byte aligned, and we can have any amount of
- * sw space after the TD entry as far as I can tell.
- *
- * But let's just go with the documentation, at least for 32-bit machines.
- * On 64-bit machines we probably want to take advantage of the fact that
- * hw doesn't really care about the size of the sw-only area.
- *
- * Alas, not anymore, we have more than 4 words for software, woops.
- * Everything still works tho, surprise! -jerdfelt
+ * sw space after the TD entry.
*
* td->link points to either another TD (not necessarily for the same urb or
- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs)
+ * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs).
*/
struct uhci_td {
/* Hardware fields */
@@ -205,18 +199,16 @@ struct uhci_td {
/* Software fields */
dma_addr_t dma_handle;
- struct urb *urb;
-
- struct list_head list; /* P: urb->lock */
- struct list_head remove_list; /* P: uhci->td_remove_list_lock */
+ struct list_head list;
+ struct list_head remove_list;
int frame; /* for iso: what frame? */
- struct list_head fl_list; /* P: uhci->frame_list_lock */
+ struct list_head fl_list;
} __attribute__((aligned(16)));
/*
* We need a special accessor for the control/status word because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
*/
static u32 inline td_status(struct uhci_td *td) {
__le32 status = td->status;
@@ -227,6 +219,10 @@ static u32 inline td_status(struct uhci_td *td) {
/*
+ * Skeleton Queue Headers
+ */
+
+/*
* The UHCI driver places Interrupt, Control and Bulk into QH's both
* to group together TD's for one transfer, and also to faciliate queuing
* of URB's. To make it easy to insert entries into the schedule, we have
@@ -256,15 +252,15 @@ static u32 inline td_status(struct uhci_td *td) {
*
* The terminating QH is used for 2 reasons:
* - To place a terminating TD which is used to workaround a PIIX bug
- * (see Intel errata for explanation)
+ * (see Intel errata for explanation), and
* - To loop back to the full-speed control queue for full-speed bandwidth
- * reclamation
+ * reclamation.
*
* Isochronous transfers are stored before the start of the skeleton
* schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. Since we don't
- * need to use them either, we follow the spec diagrams in hope that it'll
- * be more compatible with future UHCI implementations.
+ * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * says that queues never advance on an error completion status, which
+ * makes them totally unsuitable for Isochronous transfers.
*/
#define UHCI_NUM_SKELQH 12
@@ -314,8 +310,13 @@ static inline int __interval_to_skel(int interval)
return 0; /* int128 for 128-255 ms (Max.) */
}
+
+/*
+ * The UHCI controller and root hub
+ */
+
/*
- * States for the root hub.
+ * States for the root hub:
*
* To prevent "bouncing" in the presence of electrical noise,
* when there are no devices attached we delay for 1 second in the
@@ -326,7 +327,7 @@ static inline int __interval_to_skel(int interval)
*/
enum uhci_rh_state {
/* In the following states the HC must be halted.
- * These two must come first */
+ * These two must come first. */
UHCI_RH_RESET,
UHCI_RH_SUSPENDED,
@@ -338,16 +339,13 @@ enum uhci_rh_state {
UHCI_RH_SUSPENDING,
/* In the following states it's an error if the HC is halted.
- * These two must come last */
+ * These two must come last. */
UHCI_RH_RUNNING, /* The normal state */
UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
};
/*
- * This describes the full uhci information.
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs.
+ * The full UHCI controller information:
*/
struct uhci_hcd {
@@ -360,13 +358,15 @@ struct uhci_hcd {
struct dma_pool *qh_pool;
struct dma_pool *td_pool;
- struct usb_bus *bus;
-
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
spinlock_t lock;
- struct uhci_frame_list *fl; /* P: uhci->lock */
+
+ dma_addr_t frame_dma_handle; /* Hardware frame list */
+ __le32 *frame;
+ void **frame_cpu; /* CPU's frame list */
+
int fsbr; /* Full-speed bandwidth reclamation */
unsigned long fsbrtimeout; /* FSBR delay */
@@ -380,6 +380,8 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int hc_inaccessible:1; /* HC is suspended or dead */
+ unsigned int working_RD:1; /* Suspended root hub doesn't
+ need to be polled */
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
@@ -388,26 +390,24 @@ struct uhci_hcd {
unsigned long ports_timeout; /* Time to stop signalling */
/* Main list of URB's currently controlled by this HC */
- struct list_head urb_list; /* P: uhci->lock */
+ struct list_head urb_list;
/* List of QH's that are done, but waiting to be unlinked (race) */
- struct list_head qh_remove_list; /* P: uhci->lock */
+ struct list_head qh_remove_list;
unsigned int qh_remove_age; /* Age in frames */
/* List of TD's that are done, but waiting to be freed (race) */
- struct list_head td_remove_list; /* P: uhci->lock */
+ struct list_head td_remove_list;
unsigned int td_remove_age; /* Age in frames */
/* List of asynchronously unlinked URB's */
- struct list_head urb_remove_list; /* P: uhci->lock */
+ struct list_head urb_remove_list;
unsigned int urb_remove_age; /* Age in frames */
/* List of URB's awaiting completion callback */
- struct list_head complete_list; /* P: uhci->lock */
-
- int rh_numports;
+ struct list_head complete_list;
- struct timer_list stall_timer;
+ int rh_numports; /* Number of root-hub ports */
wait_queue_head_t waitqh; /* endpoint_disable waiters */
};
@@ -424,13 +424,17 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
#define uhci_dev(u) (uhci_to_hcd(u)->self.controller)
+
+/*
+ * Private per-URB data
+ */
struct urb_priv {
struct list_head urb_list;
struct urb *urb;
struct uhci_qh *qh; /* QH for this URB */
- struct list_head td_list; /* P: urb->lock */
+ struct list_head td_list;
unsigned fsbr : 1; /* URB turned on FSBR */
unsigned fsbr_timeout : 1; /* URB timed out on FSBR */
@@ -439,12 +443,12 @@ struct urb_priv {
/* a control transfer, retrigger */
/* the status phase */
- unsigned long inserttime; /* In jiffies */
unsigned long fsbrtime; /* In jiffies */
- struct list_head queue_list; /* P: uhci->frame_list_lock */
+ struct list_head queue_list;
};
+
/*
* Locking in uhci.c
*
@@ -464,6 +468,5 @@ struct urb_priv {
#define PCI_VENDOR_ID_GENESYS 0x17a0
#define PCI_DEVICE_ID_GL880S_UHCI 0x8083
-#define PCI_DEVICE_ID_GL880S_EHCI 0x8084
#endif
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 4eace2b19ddb..a71e48a66805 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags;
- int status;
+ int status = 0;
spin_lock_irqsave(&uhci->lock, flags);
- if (uhci->hc_inaccessible) {
- status = 0;
- goto done;
- }
+ uhci_scan_schedule(uhci, NULL);
+ if (uhci->hc_inaccessible)
+ goto done;
+ check_fsbr(uhci);
uhci_check_ports(uhci);
+
status = get_hub_status_data(uhci, buf);
switch (uhci->rh_state) {
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index bbb36cd6ed61..7e46887d9e12 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
{
if (uhci->is_stopped)
- mod_timer(&uhci->stall_timer, jiffies);
+ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
}
@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
td->frame = framenum;
/* Is there a TD already mapped there? */
- if (uhci->fl->frame_cpu[framenum]) {
+ if (uhci->frame_cpu[framenum]) {
struct uhci_td *ftd, *ltd;
- ftd = uhci->fl->frame_cpu[framenum];
+ ftd = uhci->frame_cpu[framenum];
ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
list_add_tail(&td->fl_list, &ftd->fl_list);
@@ -101,29 +101,32 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
wmb();
ltd->link = cpu_to_le32(td->dma_handle);
} else {
- td->link = uhci->fl->frame[framenum];
+ td->link = uhci->frame[framenum];
wmb();
- uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
- uhci->fl->frame_cpu[framenum] = td;
+ uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+ uhci->frame_cpu[framenum] = td;
}
}
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
+ struct uhci_td *td)
{
/* If it's not inserted, don't remove it */
- if (td->frame == -1 && list_empty(&td->fl_list))
+ if (td->frame == -1) {
+ WARN_ON(!list_empty(&td->fl_list));
return;
+ }
- if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+ if (uhci->frame_cpu[td->frame] == td) {
if (list_empty(&td->fl_list)) {
- uhci->fl->frame[td->frame] = td->link;
- uhci->fl->frame_cpu[td->frame] = NULL;
+ uhci->frame[td->frame] = td->link;
+ uhci->frame_cpu[td->frame] = NULL;
} else {
struct uhci_td *ntd;
ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
- uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
- uhci->fl->frame_cpu[td->frame] = ntd;
+ uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+ uhci->frame_cpu[td->frame] = ntd;
}
} else {
struct uhci_td *ptd;
@@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
ptd->link = td->link;
}
- wmb();
- td->link = UHCI_PTR_TERM;
-
list_del_init(&td->fl_list);
td->frame = -1;
}
+static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ struct uhci_td *td;
+
+ list_for_each_entry(td, &urbp->td_list, list)
+ uhci_remove_td_frame_list(uhci, td);
+ wmb();
+}
+
/*
* Inserts a td list into qh.
*/
@@ -443,7 +453,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
memset((void *)urbp, 0, sizeof(*urbp));
- urbp->inserttime = jiffies;
urbp->fsbrtime = jiffies;
urbp->urb = urb;
@@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
{
struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- td->urb = urb;
-
list_add_tail(&td->list, &urbp->td_list);
}
@@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
return;
list_del_init(&td->list);
-
- td->urb = NULL;
}
static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
@@ -503,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
uhci_remove_td_from_urb(td);
- uhci_remove_td(uhci, td);
list_add(&td->remove_list, &uhci->td_remove_list);
}
@@ -1073,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
struct uhci_td *td;
int i, ret, frame;
int status, destination;
+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1081,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
if (ret)
return ret;
- frame = urb->start_frame;
- for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
- if (!urb->iso_frame_desc[i].length)
- continue;
-
+ for (i = 0; i < urb->number_of_packets; i++) {
td = uhci_alloc_td(uhci);
if (!td)
return -ENOMEM;
@@ -1096,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
if (i + 1 >= urb->number_of_packets)
td->status |= cpu_to_le32(TD_CTRL_IOC);
+ }
+ frame = urb->start_frame;
+ list_for_each_entry(td, &urbp->td_list, list) {
uhci_insert_td_frame_list(uhci, td, frame);
+ frame += urb->interval;
}
return -EINPROGRESS;
@@ -1110,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
int status;
int i, ret = 0;
- urb->actual_length = 0;
+ urb->actual_length = urb->error_count = 0;
i = 0;
list_for_each_entry(td, &urbp->td_list, list) {
@@ -1134,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
i++;
}
+ unlink_isochronous_tds(uhci, urb);
return ret;
}
@@ -1164,7 +1170,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
static int uhci_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *ep,
- struct urb *urb, unsigned mem_flags)
+ struct urb *urb, gfp_t mem_flags)
{
int ret;
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -1366,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
goto done;
list_del_init(&urbp->urb_list);
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+ unlink_isochronous_tds(uhci, urb);
uhci_unlink_generic(uhci, urb);
uhci_get_current_frame_number(uhci);
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index a330a4b50e16..1d973bcf56aa 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -425,9 +425,8 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
static struct usb_driver mdc800_usb_driver;
static struct file_operations mdc800_device_ops;
static struct usb_class_driver mdc800_class = {
- .name = "usb/mdc800%d",
+ .name = "mdc800%d",
.fops = &mdc800_device_ops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = MDC800_DEVICE_MINOR_BASE,
};
@@ -976,13 +975,13 @@ static struct usb_driver mdc800_usb_driver =
Init and Cleanup this driver (Main Functions)
*************************************************************************/
-#define try(A) if (!(A)) goto cleanup_on_fail;
-
static int __init usb_mdc800_init (void)
{
int retval = -ENODEV;
/* Allocate Memory */
- try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+ mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL);
+ if (!mdc800)
+ goto cleanup_on_fail;
memset(mdc800, 0, sizeof(struct mdc800_data));
mdc800->dev = NULL;
@@ -998,13 +997,25 @@ static int __init usb_mdc800_init (void)
mdc800->downloaded = 0;
mdc800->written = 0;
- try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
- try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
- try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+ mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+ if (!mdc800->irq_urb_buffer)
+ goto cleanup_on_fail;
+ mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
+ if (!mdc800->write_urb_buffer)
+ goto cleanup_on_fail;
+ mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+ if (!mdc800->download_urb_buffer)
+ goto cleanup_on_fail;
- try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
- try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
- try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+ mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->irq_urb)
+ goto cleanup_on_fail;
+ mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->download_urb)
+ goto cleanup_on_fail;
+ mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->write_urb)
+ goto cleanup_on_fail;
/* Register the driver */
retval = usb_register(&mdc800_usb_driver);
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index c84e1486054f..c89d0769b3da 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -773,11 +773,10 @@ static int mts_usb_probe(struct usb_interface *intf,
}
- new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+ new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL);
if (!new_desc)
goto out;
- memset(new_desc, 0, sizeof(*new_desc));
new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!new_desc->urb)
goto out_kfree;
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 298e4a25e3d3..1e53934907c0 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -230,6 +230,20 @@ config USB_EGALAX
To compile this driver as a module, choose M here: the
module will be called touchkitusb.
+config USB_YEALINK
+ tristate "Yealink usb-p1k voip phone"
+ depends on USB && INPUT && EXPERIMENTAL
+ ---help---
+ Say Y here if you want to enable keyboard and LCD functions of the
+ Yealink usb-p1k usb phones. The audio part is enabled by the generic
+ usb sound driver, so you might want to enable that as well.
+
+ For information about how to use these additional functions, see
+ <file:Documentation/input/yealink.txt>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called yealink.
+
config USB_XPAD
tristate "X-Box gamepad support"
depends on USB && INPUT
@@ -272,3 +286,23 @@ config USB_KEYSPAN_REMOTE
To compile this driver as a module, choose M here: the module will
be called keyspan_remote.
+
+config USB_APPLETOUCH
+ tristate "Apple USB Touchpad support"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an Apple USB Touchpad.
+
+ These are the touchpads that can be found on post-February 2005
+ Apple Powerbooks (prior models have a Synaptics touchpad connected
+ to the ADB bus).
+
+ This driver provides a basic mouse driver but can be interfaced
+ with the synaptics X11 driver to provide acceleration and
+ scrolling in X11.
+
+ For further information, see
+ <file:Documentation/input/appletouch.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called appletouch.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index f1547be632d4..5e03b93f29f6 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -39,4 +39,6 @@ obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
+obj-$(CONFIG_USB_YEALINK) += yealink.o
obj-$(CONFIG_USB_XPAD) += xpad.o
+obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 13532f3e3efc..a32558b4048e 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -53,7 +53,7 @@ struct usb_acecad {
char name[128];
char phys[64];
struct usb_device *usbdev;
- struct input_dev dev;
+ struct input_dev *input;
struct urb *irq;
signed char *data;
@@ -64,7 +64,7 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_acecad *acecad = urb->context;
unsigned char *data = acecad->data;
- struct input_dev *dev = &acecad->dev;
+ struct input_dev *dev = acecad->input;
int prox, status;
switch (urb->status) {
@@ -135,8 +135,8 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
struct usb_acecad *acecad;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
@@ -152,9 +152,10 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL);
- if (!acecad)
- return -ENOMEM;
+ acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!acecad || !input_dev)
+ goto fail1;
acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
if (!acecad->data)
@@ -164,6 +165,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
if (!acecad->irq)
goto fail2;
+ acecad->usbdev = dev;
+ acecad->input = input_dev;
+
if (dev->manufacturer)
strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
@@ -173,48 +177,48 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
strlcat(acecad->name, dev->product, sizeof(acecad->name));
}
- usb_make_path(dev, path, sizeof(path));
- snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path);
+ usb_make_path(dev, acecad->phys, sizeof(acecad->phys));
+ strlcat(acecad->phys, "/input0", sizeof(acecad->phys));
- acecad->usbdev = dev;
+ input_dev->name = acecad->name;
+ input_dev->phys = acecad->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = acecad;
- acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+ input_dev->open = usb_acecad_open;
+ input_dev->close = usb_acecad_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
switch (id->driver_info) {
case 0:
- acecad->dev.absmax[ABS_X] = 5000;
- acecad->dev.absmax[ABS_Y] = 3750;
- acecad->dev.absmax[ABS_PRESSURE] = 512;
+ input_dev->absmax[ABS_X] = 5000;
+ input_dev->absmax[ABS_Y] = 3750;
+ input_dev->absmax[ABS_PRESSURE] = 512;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad Flair Tablet %04x:%04x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
break;
case 1:
- acecad->dev.absmax[ABS_X] = 3000;
- acecad->dev.absmax[ABS_Y] = 2250;
- acecad->dev.absmax[ABS_PRESSURE] = 1024;
+ input_dev->absmax[ABS_X] = 3000;
+ input_dev->absmax[ABS_Y] = 2250;
+ input_dev->absmax[ABS_PRESSURE] = 1024;
if (!strlen(acecad->name))
snprintf(acecad->name, sizeof(acecad->name),
"USB Acecad 302 Tablet %04x:%04x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
break;
}
- acecad->dev.absfuzz[ABS_X] = 4;
- acecad->dev.absfuzz[ABS_Y] = 4;
-
- acecad->dev.private = acecad;
- acecad->dev.open = usb_acecad_open;
- acecad->dev.close = usb_acecad_close;
-
- acecad->dev.name = acecad->name;
- acecad->dev.phys = acecad->phys;
- usb_to_input_id(dev, &acecad->dev.id);
- acecad->dev.dev = &intf->dev;
+ input_dev->absfuzz[ABS_X] = 4;
+ input_dev->absfuzz[ABS_Y] = 4;
usb_fill_int_urb(acecad->irq, dev, pipe,
acecad->data, maxp > 8 ? 8 : maxp,
@@ -222,17 +226,15 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
acecad->irq->transfer_dma = acecad->data_dma;
acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&acecad->dev);
-
- printk(KERN_INFO "input: %s with packet size %d on %s\n",
- acecad->name, maxp, path);
+ input_register_device(acecad->input);
usb_set_intfdata(intf, acecad);
return 0;
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
- fail1: kfree(acecad);
+ fail1: input_free_device(input_dev);
+ kfree(acecad);
return -ENOMEM;
}
@@ -243,7 +245,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (acecad) {
usb_kill_urb(acecad->irq);
- input_unregister_device(&acecad->dev);
+ input_unregister_device(acecad->input);
usb_free_urb(acecad->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma);
kfree(acecad);
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index cd0cbfe20723..1c3b472a3bca 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -317,7 +317,7 @@ struct aiptek_settings {
};
struct aiptek {
- struct input_dev inputdev; /* input device struct */
+ struct input_dev *inputdev; /* input device struct */
struct usb_device *usbdev; /* usb device struct */
struct urb *urb; /* urb for incoming reports */
dma_addr_t data_dma; /* our dma stuffage */
@@ -402,7 +402,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
{
struct aiptek *aiptek = urb->context;
unsigned char *data = aiptek->data;
- struct input_dev *inputdev = &aiptek->inputdev;
+ struct input_dev *inputdev = aiptek->inputdev;
int jitterable = 0;
int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck;
@@ -955,20 +955,20 @@ static int aiptek_program_tablet(struct aiptek *aiptek)
/* Query getXextension */
if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_X] = 0;
- aiptek->inputdev.absmax[ABS_X] = ret - 1;
+ aiptek->inputdev->absmin[ABS_X] = 0;
+ aiptek->inputdev->absmax[ABS_X] = ret - 1;
/* Query getYextension */
if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_Y] = 0;
- aiptek->inputdev.absmax[ABS_Y] = ret - 1;
+ aiptek->inputdev->absmin[ABS_Y] = 0;
+ aiptek->inputdev->absmax[ABS_Y] = ret - 1;
/* Query getPressureLevels */
if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0)
return ret;
- aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
- aiptek->inputdev.absmax[ABS_PRESSURE] = ret - 1;
+ aiptek->inputdev->absmin[ABS_PRESSURE] = 0;
+ aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1;
/* Depending on whether we are in absolute or relative mode, we will
* do a switchToTablet(absolute) or switchToMouse(relative) command.
@@ -1025,8 +1025,8 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
return 0;
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
- aiptek->inputdev.absmax[ABS_X] + 1,
- aiptek->inputdev.absmax[ABS_Y] + 1);
+ aiptek->inputdev->absmax[ABS_X] + 1,
+ aiptek->inputdev->absmax[ABS_Y] + 1);
}
/* These structs define the sysfs files, param #1 is the name of the
@@ -1048,7 +1048,7 @@ static ssize_t show_tabletProductId(struct device *dev, struct device_attribute
return 0;
return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev.id.product);
+ aiptek->inputdev->id.product);
}
static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
@@ -1063,7 +1063,7 @@ static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev.id.vendor);
+ return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
}
static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
@@ -1977,7 +1977,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct input_dev *inputdev;
struct input_handle *inputhandle;
struct list_head *node, *next;
- char path[64 + 1];
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1996,24 +1995,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
*/
speeds[0] = programmableDelay;
- if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL)
- return -ENOMEM;
- memset(aiptek, 0, sizeof(struct aiptek));
+ aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
+ inputdev = input_allocate_device();
+ if (!aiptek || !inputdev)
+ goto fail1;
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
SLAB_ATOMIC, &aiptek->data_dma);
- if (aiptek->data == NULL) {
- kfree(aiptek);
- return -ENOMEM;
- }
+ if (!aiptek->data)
+ goto fail1;
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (aiptek->urb == NULL) {
- usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
- aiptek->data_dma);
- kfree(aiptek);
- return -ENOMEM;
- }
+ if (!aiptek->urb)
+ goto fail2;
+
+ aiptek->inputdev = inputdev;
+ aiptek->usbdev = usbdev;
+ aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
+ aiptek->inDelay = 0;
+ aiptek->endDelay = 0;
+ aiptek->previousJitterable = 0;
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2036,31 +2037,48 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Both structs should have equivalent settings
*/
- memcpy(&aiptek->newSetting, &aiptek->curSetting,
- sizeof(struct aiptek_settings));
+ aiptek->newSetting = aiptek->curSetting;
+
+ /* Determine the usb devices' physical path.
+ * Asketh not why we always pretend we're using "../input0",
+ * but I suspect this will have to be refactored one
+ * day if a single USB device can be a keyboard & a mouse
+ * & a tablet, and the inputX number actually will tell
+ * us something...
+ */
+ usb_make_path(usbdev, aiptek->features.usbPath,
+ sizeof(aiptek->features.usbPath));
+ strlcat(aiptek->features.usbPath, "/input0",
+ sizeof(aiptek->features.usbPath));
+
+ /* Set up client data, pointers to open and close routines
+ * for the input device.
+ */
+ inputdev->name = "Aiptek";
+ inputdev->phys = aiptek->features.usbPath;
+ usb_to_input_id(usbdev, &inputdev->id);
+ inputdev->cdev.dev = &intf->dev;
+ inputdev->private = aiptek;
+ inputdev->open = aiptek_open;
+ inputdev->close = aiptek_close;
/* Now program the capacities of the tablet, in terms of being
* an input device.
*/
- aiptek->inputdev.evbit[0] |= BIT(EV_KEY)
+ inputdev->evbit[0] |= BIT(EV_KEY)
| BIT(EV_ABS)
| BIT(EV_REL)
| BIT(EV_MSC);
- aiptek->inputdev.absbit[0] |=
- (BIT(ABS_X) |
- BIT(ABS_Y) |
- BIT(ABS_PRESSURE) |
- BIT(ABS_TILT_X) |
- BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC));
+ inputdev->absbit[0] |= BIT(ABS_MISC);
- aiptek->inputdev.relbit[0] |=
+ inputdev->relbit[0] |=
(BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
- aiptek->inputdev.keybit[LONG(BTN_LEFT)] |=
+ inputdev->keybit[LONG(BTN_LEFT)] |=
(BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
- aiptek->inputdev.keybit[LONG(BTN_DIGI)] |=
+ inputdev->keybit[LONG(BTN_DIGI)] |=
(BIT(BTN_TOOL_PEN) |
BIT(BTN_TOOL_RUBBER) |
BIT(BTN_TOOL_PENCIL) |
@@ -2070,70 +2088,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
BIT(BTN_TOOL_LENS) |
BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
- aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL);
+ inputdev->mscbit[0] = BIT(MSC_SERIAL);
/* Programming the tablet macro keys needs to be done with a for loop
* as the keycodes are discontiguous.
*/
for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
- set_bit(macroKeyEvents[i], aiptek->inputdev.keybit);
-
- /* Set up client data, pointers to open and close routines
- * for the input device.
- */
- aiptek->inputdev.private = aiptek;
- aiptek->inputdev.open = aiptek_open;
- aiptek->inputdev.close = aiptek_close;
+ set_bit(macroKeyEvents[i], inputdev->keybit);
- /* Determine the usb devices' physical path.
- * Asketh not why we always pretend we're using "../input0",
- * but I suspect this will have to be refactored one
- * day if a single USB device can be a keyboard & a mouse
- * & a tablet, and the inputX number actually will tell
- * us something...
- */
- if (usb_make_path(usbdev, path, 64) > 0)
- sprintf(aiptek->features.usbPath, "%s/input0", path);
-
- /* Program the input device coordinate capacities. We do not yet
+ /*
+ * Program the input device coordinate capacities. We do not yet
* know what maximum X, Y, and Z values are, so we're putting fake
* values in. Later, we'll ask the tablet to put in the correct
* values.
*/
- aiptek->inputdev.absmin[ABS_X] = 0;
- aiptek->inputdev.absmax[ABS_X] = 2999;
- aiptek->inputdev.absmin[ABS_Y] = 0;
- aiptek->inputdev.absmax[ABS_Y] = 2249;
- aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
- aiptek->inputdev.absmax[ABS_PRESSURE] = 511;
- aiptek->inputdev.absmin[ABS_TILT_X] = AIPTEK_TILT_MIN;
- aiptek->inputdev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX;
- aiptek->inputdev.absmin[ABS_TILT_Y] = AIPTEK_TILT_MIN;
- aiptek->inputdev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX;
- aiptek->inputdev.absmin[ABS_WHEEL] = AIPTEK_WHEEL_MIN;
- aiptek->inputdev.absmax[ABS_WHEEL] = AIPTEK_WHEEL_MAX - 1;
- aiptek->inputdev.absfuzz[ABS_X] = 0;
- aiptek->inputdev.absfuzz[ABS_Y] = 0;
- aiptek->inputdev.absfuzz[ABS_PRESSURE] = 0;
- aiptek->inputdev.absfuzz[ABS_TILT_X] = 0;
- aiptek->inputdev.absfuzz[ABS_TILT_Y] = 0;
- aiptek->inputdev.absfuzz[ABS_WHEEL] = 0;
- aiptek->inputdev.absflat[ABS_X] = 0;
- aiptek->inputdev.absflat[ABS_Y] = 0;
- aiptek->inputdev.absflat[ABS_PRESSURE] = 0;
- aiptek->inputdev.absflat[ABS_TILT_X] = 0;
- aiptek->inputdev.absflat[ABS_TILT_Y] = 0;
- aiptek->inputdev.absflat[ABS_WHEEL] = 0;
- aiptek->inputdev.name = "Aiptek";
- aiptek->inputdev.phys = aiptek->features.usbPath;
- usb_to_input_id(usbdev, &aiptek->inputdev.id);
- aiptek->inputdev.dev = &intf->dev;
-
- aiptek->usbdev = usbdev;
- aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
- aiptek->inDelay = 0;
- aiptek->endDelay = 0;
- aiptek->previousJitterable = 0;
+ input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0);
+ input_set_abs_params(inputdev, ABS_X, 0, 2249, 0, 0);
+ input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0);
+ input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+ input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+ input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
endpoint = &intf->altsetting[0].endpoint[0].desc;
@@ -2150,28 +2124,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->urb->transfer_dma = aiptek->data_dma;
aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- /* Register the tablet as an Input Device
- */
- input_register_device(&aiptek->inputdev);
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to /{devfs}/input/eventN.
- */
- inputdev = &aiptek->inputdev;
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
- }
-
- info("input: Aiptek on %s (%s)\n", path, aiptek->features.inputPath);
-
/* Program the tablet. This sets the tablet up in the mode
* specified in newSetting, and also queries the tablet's
* physical capacities.
@@ -2186,13 +2138,32 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
aiptek->curSetting.programmableDelay = speeds[i];
(void)aiptek_program_tablet(aiptek);
- if (aiptek->inputdev.absmax[ABS_X] > 0) {
+ if (aiptek->inputdev->absmax[ABS_X] > 0) {
info("input: Aiptek using %d ms programming speed\n",
aiptek->curSetting.programmableDelay);
break;
}
}
+ /* Register the tablet as an Input Device
+ */
+ input_register_device(aiptek->inputdev);
+
+ /* We now will look for the evdev device which is mapped to
+ * the tablet. The partial name is kept in the link list of
+ * input_handles associated with this input device.
+ * What identifies an evdev input_handler is that it begins
+ * with 'event', continues with a digit, and that in turn
+ * is mapped to input/eventN.
+ */
+ list_for_each_safe(node, next, &inputdev->h_list) {
+ inputhandle = to_handle(node);
+ if (strncmp(inputhandle->name, "event", 5) == 0) {
+ strcpy(aiptek->features.inputPath, inputhandle->name);
+ break;
+ }
+ }
+
/* Associate this driver's struct with the usb interface.
*/
usb_set_intfdata(intf, aiptek);
@@ -2207,6 +2178,12 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
info("aiptek: error loading 'evdev' module");
return 0;
+
+fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+ aiptek->data_dma);
+fail1: input_free_device(inputdev);
+ kfree(aiptek);
+ return -ENOMEM;
}
/* Forward declaration */
@@ -2234,7 +2211,7 @@ static void aiptek_disconnect(struct usb_interface *intf)
/* Free & unhook everything from the system.
*/
usb_kill_urb(aiptek->urb);
- input_unregister_device(&aiptek->inputdev);
+ input_unregister_device(aiptek->inputdev);
aiptek_delete_files(&intf->dev);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644
index 000000000000..15840db092a5
--- /dev/null
+++ b/drivers/usb/input/appletouch.c
@@ -0,0 +1,475 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
+ * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ *
+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/usb_input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID 0x05AC
+
+#define ATP_DEVICE(prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = APPLE_VENDOR_ID, \
+ .idProduct = (prod), \
+ .bInterfaceClass = 0x03, \
+ .bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+ { ATP_DEVICE(0x020E) },
+ { ATP_DEVICE(0x020F) },
+ { ATP_DEVICE(0x030A) },
+ { ATP_DEVICE(0x030B) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/* size of a USB urb transfer */
+#define ATP_DATASIZE 81
+
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) sensors.
+ */
+#define ATP_XSENSORS 26
+#define ATP_YSENSORS 16
+
+/* amount of fuzz this touchpad generates */
+#define ATP_FUZZ 16
+
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE 300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks
+ * 0 <= y < 646
+ */
+#define ATP_XFACT 64
+#define ATP_YFACT 43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD 5
+
+/* 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 */
+ int open; /* non-zero if opened */
+ struct input_dev *input; /* input dev */
+ int valid; /* are the sensors valid ? */
+ int x_old; /* last reported x/y, */
+ int y_old; /* used for smoothing */
+ /* current value of the sensors */
+ signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+ /* last value of the sensors */
+ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
+ /* accumulated sensors */
+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+};
+
+#define dbg_dump(msg, tab) \
+ if (debug > 1) { \
+ int i; \
+ printk("appletouch: %s %lld", msg, (long long)jiffies); \
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
+ printk(" %02x", tab[i]); \
+ printk("\n"); \
+ }
+
+#define dprintk(format, a...) \
+ do { \
+ if (debug) printk(format, ##a); \
+ } while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+ int *z, int *fingers)
+{
+ int i;
+ /* values to calculate mean */
+ int pcum = 0, psum = 0;
+
+ *fingers = 0;
+
+ for (i = 0; i < nb_sensors; i++) {
+ if (xy_sensors[i] < ATP_THRESHOLD)
+ continue;
+ if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+ (*fingers)++;
+ pcum += xy_sensors[i] * i;
+ psum += xy_sensors[i];
+ }
+
+ if (psum > 0) {
+ *z = psum;
+ return pcum * fact / psum;
+ }
+
+ return 0;
+}
+
+static inline void atp_report_fingers(struct input_dev *input, int fingers)
+{
+ input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i;
+ struct atp *dev = urb->context;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ /* drop incomplete datasets */
+ if (dev->urb->actual_length != ATP_DATASIZE) {
+ dprintk("appletouch: incomplete data package.\n");
+ goto exit;
+ }
+
+ /* reorder the sensors values */
+ for (i = 0; i < 8; i++) {
+ /* X values */
+ dev->xy_cur[i ] = dev->data[5 * i + 2];
+ dev->xy_cur[i + 8] = dev->data[5 * i + 4];
+ dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+ if (i < 2)
+ dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+ /* Y values */
+ dev->xy_cur[i + 26] = dev->data[5 * i + 1];
+ dev->xy_cur[i + 34] = dev->data[5 * i + 3];
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ if (!dev->valid) {
+ /* first sample */
+ dev->valid = 1;
+ dev->x_old = dev->y_old = -1;
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ /* 17" Powerbooks have 10 extra X sensors */
+ for (i = 16; i < ATP_XSENSORS; i++)
+ if (dev->xy_cur[i]) {
+ printk("appletouch: 17\" model detected.\n");
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (ATP_XSENSORS - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ break;
+ }
+
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+ /* accumulate the change */
+ signed char change = dev->xy_old[i] - dev->xy_cur[i];
+ dev->xy_acc[i] -= change;
+
+ /* prevent down drifting */
+ if (dev->xy_acc[i] < 0)
+ dev->xy_acc[i] = 0;
+ }
+
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+ 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);
+
+ 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("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, !!dev->data[80]);
+
+ input_sync(dev->input);
+
+exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+ }
+}
+
+static int atp_open(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ if (usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
+
+ dev->open = 1;
+ return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+ struct atp *dev = input->private;
+
+ usb_kill_urb(dev->urb);
+ dev->open = 0;
+}
+
+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+ struct atp *dev;
+ struct input_dev *input_dev;
+ struct usb_device *udev = interface_to_usbdev(iface);
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int int_in_endpointAddr = 0;
+ int i, retval = -ENOMEM;
+
+
+ /* set up the endpoint information */
+ /* use only the first interrupt-in endpoint */
+ iface_desc = iface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if (!int_in_endpointAddr &&
+ (endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT)) {
+ /* we found an interrupt in endpoint */
+ int_in_endpointAddr = endpoint->bEndpointAddress;
+ break;
+ }
+ }
+ if (!int_in_endpointAddr) {
+ err("Could not find int-in endpoint");
+ return -EIO;
+ }
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!dev || !input_dev) {
+ err("Out of memory");
+ goto err_free_devs;
+ }
+
+ dev->udev = udev;
+ dev->input = input_dev;
+
+ dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb) {
+ retval = -ENOMEM;
+ goto err_free_devs;
+ }
+
+ dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+ &dev->urb->transfer_dma);
+ if (!dev->data) {
+ retval = -ENOMEM;
+ goto err_free_urb;
+ }
+
+ usb_fill_int_urb(dev->urb, udev,
+ usb_rcvintpipe(udev, int_in_endpointAddr),
+ dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+
+ usb_make_path(udev, dev->phys, sizeof(dev->phys));
+ strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+ input_dev->name = "appletouch";
+ input_dev->phys = dev->phys;
+ usb_to_input_id(dev->udev, &input_dev->id);
+ input_dev->cdev.dev = &iface->dev;
+
+ input_dev->private = dev;
+ input_dev->open = atp_open;
+ input_dev->close = atp_close;
+
+ set_bit(EV_ABS, input_dev->evbit);
+
+ /*
+ * 12" and 15" Powerbooks only have 16 x sensors,
+ * 17" models are detected later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 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);
+ set_bit(BTN_LEFT, input_dev->keybit);
+
+ input_register_device(dev->input);
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(iface, dev);
+
+ return 0;
+
+ err_free_urb:
+ usb_free_urb(dev->urb);
+ err_free_devs:
+ usb_set_intfdata(iface, NULL);
+ kfree(dev);
+ input_free_device(input_dev);
+ return retval;
+}
+
+static void atp_disconnect(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+
+ usb_set_intfdata(iface, NULL);
+ if (dev) {
+ usb_kill_urb(dev->urb);
+ input_unregister_device(dev->input);
+ usb_free_urb(dev->urb);
+ usb_buffer_free(dev->udev, ATP_DATASIZE,
+ dev->data, dev->urb->transfer_dma);
+ kfree(dev);
+ }
+ printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+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 = 0;
+ return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+ struct atp *dev = usb_get_intfdata(iface);
+ if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+ return -EIO;
+
+ return 0;
+}
+
+static struct usb_driver atp_driver = {
+ .owner = THIS_MODULE,
+ .name = "appletouch",
+ .probe = atp_probe,
+ .disconnect = atp_disconnect,
+ .suspend = atp_suspend,
+ .resume = atp_resume,
+ .id_table = atp_table,
+};
+
+static int __init atp_init(void)
+{
+ return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+ usb_deregister(&atp_driver);
+}
+
+module_init(atp_init);
+module_exit(atp_exit);
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index fd99681ee483..9a2a47db9494 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -112,7 +112,6 @@
#define NAME_BUFSIZE 80 /* size of product name, path buffers */
#define DATA_BUFSIZE 63 /* size of URB data buffers */
-#define ATI_INPUTNUM 1 /* Which input device to register as */
static unsigned long channel_mask;
module_param(channel_mask, ulong, 0444);
@@ -162,7 +161,7 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
static DECLARE_MUTEX(disconnect_sem);
struct ati_remote {
- struct input_dev idev;
+ struct input_dev *idev;
struct usb_device *udev;
struct usb_interface *interface;
@@ -198,15 +197,13 @@ struct ati_remote {
#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
/* Translation table from hardware messages to input events. */
-static struct
-{
+static struct {
short kind;
unsigned char data1, data2;
int type;
unsigned int code;
int value;
-} ati_remote_tbl[] =
-{
+} ati_remote_tbl[] = {
/* Directional control pad axes */
{KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */
{KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */
@@ -286,7 +283,6 @@ static struct
/* Local function prototypes */
static void ati_remote_dump (unsigned char *data, unsigned int actual_length);
-static void ati_remote_delete (struct ati_remote *dev);
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);
@@ -428,7 +424,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
{
struct ati_remote *ati_remote = urb->context;
unsigned char *data= ati_remote->inbuf;
- struct input_dev *dev = &ati_remote->idev;
+ struct input_dev *dev = ati_remote->idev;
int index, acc;
int remote_num;
@@ -587,38 +583,55 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs)
}
/*
- * ati_remote_delete
+ * ati_remote_alloc_buffers
*/
-static void ati_remote_delete(struct ati_remote *ati_remote)
+static int ati_remote_alloc_buffers(struct usb_device *udev,
+ struct ati_remote *ati_remote)
{
- if (ati_remote->irq_urb)
- usb_kill_urb(ati_remote->irq_urb);
+ ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ &ati_remote->inbuf_dma);
+ if (!ati_remote->inbuf)
+ return -1;
- if (ati_remote->out_urb)
- usb_kill_urb(ati_remote->out_urb);
+ ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ &ati_remote->outbuf_dma);
+ if (!ati_remote->outbuf)
+ return -1;
- input_unregister_device(&ati_remote->idev);
+ ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ati_remote->irq_urb)
+ return -1;
- if (ati_remote->inbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->inbuf, ati_remote->inbuf_dma);
+ ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ati_remote->out_urb)
+ return -1;
- if (ati_remote->outbuf)
- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
- ati_remote->outbuf, ati_remote->outbuf_dma);
+ return 0;
+}
+/*
+ * ati_remote_free_buffers
+ */
+static void ati_remote_free_buffers(struct ati_remote *ati_remote)
+{
if (ati_remote->irq_urb)
usb_free_urb(ati_remote->irq_urb);
if (ati_remote->out_urb)
usb_free_urb(ati_remote->out_urb);
- kfree(ati_remote);
+ if (ati_remote->inbuf)
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->inbuf, ati_remote->inbuf_dma);
+
+ if (ati_remote->outbuf)
+ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+ ati_remote->inbuf, ati_remote->outbuf_dma);
}
static void ati_remote_input_init(struct ati_remote *ati_remote)
{
- struct input_dev *idev = &(ati_remote->idev);
+ struct input_dev *idev = ati_remote->idev;
int i;
idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
@@ -637,7 +650,7 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
idev->phys = ati_remote->phys;
usb_to_input_id(ati_remote->udev, &idev->id);
- idev->dev = &ati_remote->udev->dev;
+ idev->cdev.dev = &ati_remote->udev->dev;
}
static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -674,7 +687,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
(ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
dev_err(&ati_remote->interface->dev,
"Initializing ati_remote hardware failed.\n");
- return 1;
+ return -EIO;
}
return 0;
@@ -686,95 +699,83 @@ static int ati_remote_initialize(struct ati_remote *ati_remote)
static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct ati_remote *ati_remote = NULL;
- struct usb_host_interface *iface_host;
- int retval = -ENOMEM;
- char path[64];
-
- /* Allocate and clear an ati_remote struct */
- if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
- return -ENOMEM;
- memset(ati_remote, 0x00, sizeof (struct ati_remote));
+ struct usb_host_interface *iface_host = interface->cur_altsetting;
+ struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
+ struct ati_remote *ati_remote;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
- iface_host = interface->cur_altsetting;
if (iface_host->desc.bNumEndpoints != 2) {
err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- ati_remote->endpoint_in = &(iface_host->endpoint[0].desc);
- ati_remote->endpoint_out = &(iface_host->endpoint[1].desc);
- ati_remote->udev = udev;
- ati_remote->interface = interface;
+ endpoint_in = &iface_host->endpoint[0].desc;
+ endpoint_out = &iface_host->endpoint[1].desc;
- if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) {
+ if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) {
+ if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) {
+ if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
err("%s: endpoint_in message size==0? \n", __FUNCTION__);
- retval = -ENODEV;
- goto error;
+ return -ENODEV;
}
- /* Allocate URB buffers, URBs */
- ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
- &ati_remote->inbuf_dma);
- if (!ati_remote->inbuf)
- goto error;
+ ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ati_remote || !input_dev)
+ goto fail1;
- ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
- &ati_remote->outbuf_dma);
- if (!ati_remote->outbuf)
- goto error;
+ /* Allocate URB buffers, URBs */
+ if (ati_remote_alloc_buffers(udev, ati_remote))
+ goto fail2;
- ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ati_remote->irq_urb)
- goto error;
+ ati_remote->endpoint_in = endpoint_in;
+ ati_remote->endpoint_out = endpoint_out;
+ ati_remote->udev = udev;
+ ati_remote->idev = input_dev;
+ ati_remote->interface = interface;
- ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ati_remote->out_urb)
- goto error;
+ usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
+ strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
- usb_make_path(udev, path, NAME_BUFSIZE);
- sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
if (udev->manufacturer)
- strcat(ati_remote->name, udev->manufacturer);
+ strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
if (udev->product)
- sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product);
+ snprintf(ati_remote->name, sizeof(ati_remote->name),
+ "%s %s", ati_remote->name, udev->product);
if (!strlen(ati_remote->name))
- sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
+ snprintf(ati_remote->name, sizeof(ati_remote->name),
+ DRIVER_DESC "(%04x,%04x)",
le16_to_cpu(ati_remote->udev->descriptor.idVendor),
le16_to_cpu(ati_remote->udev->descriptor.idProduct));
+ ati_remote_input_init(ati_remote);
+
/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
- retval = ati_remote_initialize(ati_remote);
- if (retval)
- goto error;
+ err = ati_remote_initialize(ati_remote);
+ if (err)
+ goto fail3;
/* Set up and register input device */
- ati_remote_input_init(ati_remote);
- input_register_device(&ati_remote->idev);
-
- dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n",
- ati_remote->name, path);
+ input_register_device(ati_remote->idev);
usb_set_intfdata(interface, ati_remote);
+ return 0;
-error:
- if (retval)
- ati_remote_delete(ati_remote);
-
- return retval;
+fail3: usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+fail2: ati_remote_free_buffers(ati_remote);
+fail1: input_free_device(input_dev);
+ kfree(ati_remote);
+ return err;
}
/*
@@ -791,7 +792,11 @@ static void ati_remote_disconnect(struct usb_interface *interface)
return;
}
- ati_remote_delete(ati_remote);
+ usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+ input_unregister_device(ati_remote->idev);
+ ati_remote_free_buffers(ati_remote);
+ kfree(ati_remote);
}
/*
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index b2cb2b35892e..79ddce4555ab 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -2,7 +2,8 @@
* USB HID support for Linux
*
* Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
*/
/*
@@ -38,7 +39,7 @@
* Version Information
*/
-#define DRIVER_VERSION "v2.01"
+#define DRIVER_VERSION "v2.6"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
if (maxpacket > 0) {
padlen = (len + maxpacket - 1) / maxpacket;
padlen *= maxpacket;
- if (padlen > HID_BUFFER_SIZE)
- padlen = HID_BUFFER_SIZE;
+ if (padlen > hid->bufsize)
+ padlen = hid->bufsize;
} else
padlen = 0;
hid->urbctrl->transfer_buffer_length = padlen;
@@ -1096,6 +1097,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
switch (urb->status) {
case 0: /* success */
+ break;
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timeout on uhci */
unplug = 1;
@@ -1143,6 +1145,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
case 0: /* success */
if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+ break;
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timectrl on uhci */
unplug = 1;
@@ -1284,13 +1287,8 @@ void hid_init_reports(struct hid_device *hid)
struct hid_report *report;
int err, ret;
- list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
- int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
- if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
- if (size > hid->urbin->transfer_buffer_length)
- hid->urbin->transfer_buffer_length = size;
+ list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
- }
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
@@ -1372,12 +1370,14 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_A4TECH 0x09da
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
-#define USB_VENDOR_ID_AASHIMA 0x06D6
+#define USB_VENDOR_ID_AASHIMA 0x06d6
#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
#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_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@@ -1432,7 +1432,7 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_VENDOR_ID_LD 0x0f11
-#define USB_DEVICE_ID_CASSY 0x1000
+#define USB_DEVICE_ID_CASSY 0x1000
#define USB_DEVICE_ID_POCKETCASSY 0x1010
#define USB_DEVICE_ID_MOBILECASSY 0x1020
#define USB_DEVICE_ID_JWM 0x1080
@@ -1444,6 +1444,8 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_NETWORKANALYSER 0x2020
#define USB_DEVICE_ID_POWERCONTROL 0x2030
+#define USB_VENDOR_ID_APPLE 0x05ac
+#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
/*
* Alphabetically sorted blacklist by quirk type.
@@ -1468,6 +1470,7 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, 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 },
@@ -1548,10 +1551,12 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
{ 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_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -1564,15 +1569,32 @@ static struct hid_blacklist {
{ 0, 0 }
};
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
+{
+ struct hid_report *report;
+ int size;
+
+ list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+ size = ((report->size - 1) >> 3) + 1;
+ if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
+ size++;
+ if (*max < size)
+ *max = size;
+ }
+}
+
static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
+ if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
return -1;
- if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
+ if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
return -1;
if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
return -1;
- if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+ if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
return -1;
return 0;
@@ -1581,13 +1603,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
if (hid->inbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
if (hid->outbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
if (hid->cr)
usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
if (hid->ctrlbuf)
- usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
+ usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
@@ -1597,8 +1619,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
struct hid_descriptor *hdesc;
struct hid_device *hid;
unsigned quirks = 0, rsize = 0;
- char *buf, *rdesc;
- int n;
+ char *rdesc;
+ int n, len, insize = 0;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1608,10 +1630,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (quirks & HID_QUIRK_IGNORE)
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("class descriptor not present\n");
- 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("class descriptor not present\n");
+ return NULL;
}
for (n = 0; n < hdesc->bNumDescriptors; n++)
@@ -1652,6 +1675,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
kfree(rdesc);
hid->quirks = quirks;
+ hid->bufsize = HID_MIN_BUFFER_SIZE;
+ hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
+ hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
+ hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+
+ if (hid->bufsize > HID_MAX_BUFFER_SIZE)
+ hid->bufsize = HID_MAX_BUFFER_SIZE;
+
+ hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
+
+ if (insize > HID_MAX_BUFFER_SIZE)
+ insize = HID_MAX_BUFFER_SIZE;
+
if (hid_alloc_buffers(dev, hid)) {
hid_free_buffers(dev, hid);
goto fail;
@@ -1667,10 +1703,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
continue;
- /* handle potential highspeed HID correctly */
interval = endpoint->bInterval;
- if (dev->speed == USB_SPEED_HIGH)
- interval = 1 << (interval - 1);
/* Change the polling interval of mice. */
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
@@ -1682,10 +1715,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
+ usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
hid_irq_in, hid, interval);
hid->urbin->transfer_dma = hid->inbuf_dma;
- hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
} else {
if (hid->urbout)
continue;
@@ -1695,7 +1728,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
hid_irq_out, hid, interval);
hid->urbout->transfer_dma = hid->outbuf_dma;
- hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
}
@@ -1717,37 +1750,42 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->name[0] = 0;
- if (!(buf = kmalloc(64, GFP_KERNEL)))
- goto fail;
+ if (dev->manufacturer)
+ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
- if (dev->manufacturer) {
- strcat(hid->name, dev->manufacturer);
- if (dev->product)
- snprintf(hid->name, 64, "%s %s", hid->name, dev->product);
- } else if (dev->product) {
- snprintf(hid->name, 128, "%s", dev->product);
- } else
- snprintf(hid->name, 128, "%04x:%04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
-
- usb_make_path(dev, buf, 64);
- snprintf(hid->phys, 64, "%s/input%d", buf,
- intf->altsetting[0].desc.bInterfaceNumber);
+ 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));
+
+ 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;
- kfree(buf);
-
hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
if (!hid->urbctrl)
goto fail;
+
usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
hid->ctrlbuf, 1, hid_ctrl, hid);
hid->urbctrl->setup_dma = hid->cr_dma;
hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
- hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
+ hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+
+ /* May be needed for some devices */
+ usb_clear_halt(hid->dev, hid->urbin->pipe);
return hid;
@@ -1852,7 +1890,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
struct hid_device *hid = usb_get_intfdata (intf);
usb_kill_urb(hid->urbin);
- intf->dev.power.power_state = PMSG_SUSPEND;
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
@@ -1862,7 +1899,6 @@ static int hid_resume(struct usb_interface *intf)
struct hid_device *hid = usb_get_intfdata (intf);
int status;
- intf->dev.power.power_state = PMSG_ON;
if (hid->open)
status = usb_submit_urb(hid->urbin, GFP_NOIO);
else
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index 52437e5e2e78..ceebab99eff2 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -85,6 +85,23 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x91, "D-PadDown"},
{0, 0x92, "D-PadRight"},
{0, 0x93, "D-PadLeft"},
+ { 2, 0, "Simulation" },
+ {0, 0xb0, "Aileron"},
+ {0, 0xb1, "AileronTrim"},
+ {0, 0xb2, "Anti-Torque"},
+ {0, 0xb3, "Autopilot"},
+ {0, 0xb4, "Chaff"},
+ {0, 0xb5, "Collective"},
+ {0, 0xb6, "DiveBrake"},
+ {0, 0xb7, "ElectronicCountermeasures"},
+ {0, 0xb8, "Elevator"},
+ {0, 0xb9, "ElevatorTrim"},
+ {0, 0xba, "Rudder"},
+ {0, 0xbb, "Throttle"},
+ {0, 0xbc, "FlightCommunications"},
+ {0, 0xbd, "FlareRelease"},
+ {0, 0xbe, "LandingGear"},
+ {0, 0xbf, "ToeBrake"},
{ 7, 0, "Keyboard" },
{ 8, 0, "LED" },
{0, 0x01, "NumLock"},
@@ -92,6 +109,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x03, "ScrollLock"},
{0, 0x04, "Compose"},
{0, 0x05, "Kana"},
+ {0, 0x4b, "GenericIndicator"},
{ 9, 0, "Button" },
{ 10, 0, "Ordinal" },
{ 12, 0, "Consumer" },
@@ -574,7 +592,8 @@ static char *keys[KEY_MAX + 1] = {
[KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
[KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
[KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
- [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13",
+ [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
+ [KEY_REDO] = "Redo", [KEY_F13] = "F13",
[KEY_F14] = "F14", [KEY_F15] = "F15",
[KEY_F16] = "F16", [KEY_F17] = "F17",
[KEY_F18] = "F18", [KEY_F19] = "F19",
@@ -584,15 +603,15 @@ static char *keys[KEY_MAX + 1] = {
[KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
[KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
[KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
- [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost",
+ [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost",
[KEY_PRINT] = "Print", [KEY_HP] = "HP",
[KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
[KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
[KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
[KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
[KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
- [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel",
- [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up",
+ [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
+ [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
[KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
@@ -622,8 +641,8 @@ static char *keys[KEY_MAX + 1] = {
[BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
- [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
- [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
+ [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
+ [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
@@ -659,6 +678,9 @@ static char *keys[KEY_MAX + 1] = {
[KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL",
[KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine",
[KEY_DEL_LINE] = "DeleteLine",
+ [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
+ [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
+ [KEY_DOCUMENTS] = "Documents",
};
static char *relatives[REL_MAX + 1] = {
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 63a4db721f7e..9ff25eb520a6 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -76,10 +76,10 @@ static struct {
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
- struct input_dev *input = &hidinput->input;
- struct hid_device *device = hidinput->input.private;
- int max, code;
- unsigned long *bit;
+ struct input_dev *input = hidinput->input;
+ struct hid_device *device = input->private;
+ int max = 0, code;
+ unsigned long *bit = NULL;
field->hidinput = hidinput;
@@ -131,6 +131,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
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;
+ }
+ break;
+
case HID_UP_GENDESK:
if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
@@ -238,8 +247,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x000: goto ignore;
case 0x034: map_key_clear(KEY_SLEEP); break;
case 0x036: map_key_clear(BTN_MISC); break;
+ case 0x045: map_key_clear(KEY_RADIO); break;
case 0x08a: map_key_clear(KEY_WWW); break;
+ case 0x08d: map_key_clear(KEY_PROGRAM); break;
case 0x095: map_key_clear(KEY_HELP); break;
+ case 0x09c: map_key_clear(KEY_CHANNELUP); break;
+ case 0x09d: map_key_clear(KEY_CHANNELDOWN); 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;
@@ -259,6 +272,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x18a: map_key_clear(KEY_MAIL); break;
case 0x192: map_key_clear(KEY_CALC); break;
case 0x194: map_key_clear(KEY_FILE); break;
+ case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
+ case 0x201: map_key_clear(KEY_NEW); 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;
@@ -271,7 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
case 0x238: map_rel(REL_HWHEEL); break;
- default: goto unknown;
+ 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;
@@ -296,9 +318,42 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_MSVENDOR:
-
goto ignore;
+ case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0x003: map_key_clear(KEY_FN); break;
+ default: goto ignore;
+ }
+ break;
+
+ case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ 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_SUBTITLE); 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: goto ignore;
+ }
+ break;
+
case HID_UP_PID:
set_bit(EV_FF, input->evbit);
@@ -349,6 +404,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (usage->code > max)
goto ignore;
+ if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
+ map_rel(REL_HWHEEL);
+
if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
(usage->type == EV_REL) && (usage->code == REL_WHEEL))
set_bit(REL_HWHEEL, bit);
@@ -403,7 +461,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
if (!field->hidinput)
return;
- input = &field->hidinput->input;
+
+ input = field->hidinput->input;
input_regs(input, regs);
@@ -475,13 +534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
{
- struct list_head *lh;
struct hid_input *hidinput;
- list_for_each (lh, &hid->inputs) {
- hidinput = list_entry(lh, struct hid_input, list);
- input_sync(&hidinput->input);
- }
+ list_for_each_entry(hidinput, &hid->inputs, list)
+ input_sync(hidinput->input);
}
static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
@@ -546,6 +602,7 @@ int hidinput_connect(struct hid_device *hid)
struct usb_device *dev = hid->dev;
struct hid_report *report;
struct hid_input *hidinput = NULL;
+ struct input_dev *input_dev;
int i, j, k;
INIT_LIST_HEAD(&hid->inputs);
@@ -566,25 +623,28 @@ int hidinput_connect(struct hid_device *hid)
continue;
if (!hidinput) {
- hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
- if (!hidinput) {
+ hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!hidinput || !input_dev) {
+ kfree(hidinput);
+ input_free_device(input_dev);
err("Out of memory during hid input probe");
return -1;
}
- memset(hidinput, 0, sizeof(*hidinput));
- list_add_tail(&hidinput->list, &hid->inputs);
+ input_dev->private = hid;
+ input_dev->event = hidinput_input_event;
+ input_dev->open = hidinput_open;
+ input_dev->close = hidinput_close;
- hidinput->input.private = hid;
- hidinput->input.event = hidinput_input_event;
- hidinput->input.open = hidinput_open;
- hidinput->input.close = hidinput_close;
+ input_dev->name = hid->name;
+ input_dev->phys = hid->phys;
+ input_dev->uniq = hid->uniq;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &hid->intf->dev;
- hidinput->input.name = hid->name;
- hidinput->input.phys = hid->phys;
- hidinput->input.uniq = hid->uniq;
- usb_to_input_id(dev, &hidinput->input.id);
- hidinput->input.dev = &hid->intf->dev;
+ hidinput->input = input_dev;
+ list_add_tail(&hidinput->list, &hid->inputs);
}
for (i = 0; i < report->maxfield; i++)
@@ -599,7 +659,7 @@ int hidinput_connect(struct hid_device *hid)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- input_register_device(&hidinput->input);
+ input_register_device(hidinput->input);
hidinput = NULL;
}
}
@@ -609,7 +669,7 @@ int hidinput_connect(struct hid_device *hid)
* only useful in this case, and not for multi-input quirks. */
if (hidinput) {
hid_ff_init(hid);
- input_register_device(&hidinput->input);
+ input_register_device(hidinput->input);
}
return 0;
@@ -617,13 +677,11 @@ int hidinput_connect(struct hid_device *hid)
void hidinput_disconnect(struct hid_device *hid)
{
- struct list_head *lh, *next;
- struct hid_input *hidinput;
+ struct hid_input *hidinput, *next;
- list_for_each_safe(lh, next, &hid->inputs) {
- hidinput = list_entry(lh, struct hid_input, list);
- input_unregister_device(&hidinput->input);
+ list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
list_del(&hidinput->list);
+ input_unregister_device(hidinput->input);
kfree(hidinput);
}
}
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 0c4c77aa31ea..f82c9c9e5d51 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -255,22 +255,19 @@ static void hid_lgff_input_init(struct hid_device* hid)
u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor);
u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct);
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct))
dev++;
- ff = dev->ff;
+ for (ff = dev->ff; *ff >= 0; ff++)
+ set_bit(*ff, input_dev->ffbit);
- while (*ff >= 0) {
- set_bit(*ff, hidinput->input.ffbit);
- ++ff;
- }
-
- hidinput->input.upload_effect = hid_lgff_upload_effect;
- hidinput->input.flush = hid_lgff_flush;
+ input_dev->upload_effect = hid_lgff_upload_effect;
+ input_dev->flush = hid_lgff_flush;
- set_bit(EV_FF, hidinput->input.evbit);
- hidinput->input.ff_effects_max = LGFF_EFFECTS;
+ set_bit(EV_FF, input_dev->evbit);
+ input_dev->ff_effects_max = LGFF_EFFECTS;
}
static void hid_lgff_exit(struct hid_device* hid)
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
index 8f6a0a6f94a9..023fd5ac31c8 100644
--- a/drivers/usb/input/hid-tmff.c
+++ b/drivers/usb/input/hid-tmff.c
@@ -111,6 +111,7 @@ int hid_tmff_init(struct hid_device *hid)
struct tmff_device *private;
struct list_head *pos;
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL);
if (!private)
@@ -155,7 +156,7 @@ int hid_tmff_init(struct hid_device *hid)
private->report = report;
private->rumble = field;
- set_bit(FF_RUMBLE, hidinput->input.ffbit);
+ set_bit(FF_RUMBLE, input_dev->ffbit);
break;
default:
@@ -164,11 +165,11 @@ int hid_tmff_init(struct hid_device *hid)
}
/* Fallthrough to here only when a valid usage is found */
- hidinput->input.upload_effect = hid_tmff_upload_effect;
- hidinput->input.flush = hid_tmff_flush;
+ input_dev->upload_effect = hid_tmff_upload_effect;
+ input_dev->flush = hid_tmff_flush;
- set_bit(EV_FF, hidinput->input.evbit);
- hidinput->input.ff_effects_max = TMFF_EFFECTS;
+ set_bit(EV_FF, input_dev->evbit);
+ input_dev->ff_effects_max = TMFF_EFFECTS;
}
}
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index c1b6b69bc4a4..ee48a2276104 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -173,6 +173,7 @@ struct hid_item {
#define HID_UP_UNDEFINED 0x00000000
#define HID_UP_GENDESK 0x00010000
+#define HID_UP_SIMULATION 0x00020000
#define HID_UP_KEYBOARD 0x00070000
#define HID_UP_LED 0x00080000
#define HID_UP_BUTTON 0x00090000
@@ -182,6 +183,8 @@ struct hid_item {
#define HID_UP_PID 0x000f0000
#define HID_UP_HPVENDOR 0xff7f0000
#define HID_UP_MSVENDOR 0xff000000
+#define HID_UP_CUSTOM 0x00ff0000
+#define HID_UP_LOGIVENDOR 0xffbc0000
#define HID_USAGE 0x0000ffff
@@ -242,6 +245,7 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200
+#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400
/*
* This is the global environment of the parser. This information is
@@ -348,7 +352,8 @@ struct hid_report_enum {
#define HID_REPORT_TYPES 3
-#define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */
+#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
+#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
#define HID_OUTPUT_FIFO_SIZE 64
@@ -366,7 +371,7 @@ struct hid_control_fifo {
struct hid_input {
struct list_head list;
struct hid_report *report;
- struct input_dev input;
+ struct input_dev *input;
};
struct hid_device { /* device report descriptor */
@@ -386,6 +391,8 @@ struct hid_device { /* device report descriptor */
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ unsigned int bufsize; /* URB buffer size */
+
struct urb *urbin; /* Input URB */
char *inbuf; /* Input buffer */
dma_addr_t inbuf_dma; /* Input buffer dma */
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 4c13331b5f41..440377c7a0da 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -507,6 +507,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL;
hid_submit_report(hid, report, USB_DIR_OUT);
+ hid_wait_io(hid);
return 0;
@@ -731,9 +732,8 @@ static struct file_operations hiddev_fops = {
};
static struct usb_class_driver hiddev_class = {
- .name = "usb/hid/hiddev%d",
+ .name = "hiddev%d",
.fops = &hiddev_fops,
- .mode = S_IFCHR | S_IRUGO | S_IWUSR,
.minor_base = HIDDEV_MINOR_BASE,
};
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 0dc439f10823..3b581853cf10 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -73,7 +73,7 @@ MODULE_LICENSE( DRIVER_LICENSE );
struct itmtouch_dev {
struct usb_device *usbdev; /* usb device */
- struct input_dev inputdev; /* input device */
+ struct input_dev *inputdev; /* input device */
struct urb *readurb; /* urb */
char rbuf[ITM_BUFSIZE]; /* data */
int users;
@@ -88,9 +88,9 @@ static struct usb_device_id itmtouch_ids [] = {
static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
{
- struct itmtouch_dev * itmtouch = urb->context;
+ struct itmtouch_dev *itmtouch = urb->context;
unsigned char *data = urb->transfer_buffer;
- struct input_dev *dev = &itmtouch->inputdev;
+ struct input_dev *dev = itmtouch->inputdev;
int retval;
switch (urb->status) {
@@ -156,49 +156,62 @@ static void itmtouch_close(struct input_dev *input)
static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct itmtouch_dev *itmtouch;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
unsigned int pipe;
unsigned int maxp;
- char path[PATH_SIZE];
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) {
+ itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!itmtouch || !input_dev) {
err("%s - Out of memory.", __FUNCTION__);
- return -ENOMEM;
+ goto fail;
}
itmtouch->usbdev = udev;
+ itmtouch->inputdev = input_dev;
- itmtouch->inputdev.private = itmtouch;
- itmtouch->inputdev.open = itmtouch_open;
- itmtouch->inputdev.close = itmtouch_close;
+ if (udev->manufacturer)
+ strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
- usb_make_path(udev, path, PATH_SIZE);
-
- itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- itmtouch->inputdev.name = itmtouch->name;
- itmtouch->inputdev.phys = itmtouch->phys;
- usb_to_input_id(udev, &itmtouch->inputdev.id);
- itmtouch->inputdev.dev = &intf->dev;
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
+ strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
+ }
if (!strlen(itmtouch->name))
sprintf(itmtouch->name, "USB ITM touchscreen");
+ usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
+ strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
+
+ input_dev->name = itmtouch->name;
+ input_dev->phys = itmtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = itmtouch;
+
+ input_dev->open = itmtouch_open;
+ input_dev->close = itmtouch_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
/* device limits */
/* as specified by the ITM datasheet, X and Y are 12bit,
* Z (pressure) is 8 bit. However, the fields are defined up
* to 14 bits for future possible expansion.
*/
- input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0);
- input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0);
- input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
/* initialise the URB so we can read from the transport stream */
pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
@@ -208,22 +221,23 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id
maxp = ITM_BUFSIZE;
itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-
if (!itmtouch->readurb) {
dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
- kfree(itmtouch);
- return -ENOMEM;
+ goto fail;
}
usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
- input_register_device(&itmtouch->inputdev);
+ input_register_device(itmtouch->inputdev);
- printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path);
usb_set_intfdata(intf, itmtouch);
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(itmtouch);
+ return -ENOMEM;
}
static void itmtouch_disconnect(struct usb_interface *intf)
@@ -233,7 +247,7 @@ static void itmtouch_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (itmtouch) {
- input_unregister_device(&itmtouch->inputdev);
+ input_unregister_device(itmtouch->inputdev);
usb_kill_urb(itmtouch->readurb);
usb_free_urb(itmtouch->readurb);
kfree(itmtouch);
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index b6f6ac8d9c2f..a248664b5d1d 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -34,7 +34,7 @@ MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
struct kbtab {
signed char *data;
dma_addr_t data_dma;
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
struct urb *irq;
int x, y;
@@ -48,7 +48,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
{
struct kbtab *kbtab = urb->context;
unsigned char *data = kbtab->data;
- struct input_dev *dev = &kbtab->dev;
+ struct input_dev *dev = kbtab->dev;
int retval;
switch (urb->status) {
@@ -124,53 +124,43 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct kbtab *kbtab;
- char path[64];
+ struct input_dev *input_dev;
- if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL)))
- return -ENOMEM;
- memset(kbtab, 0, sizeof(struct kbtab));
+ kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbtab || !input_dev)
+ goto fail1;
kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
- if (!kbtab->data) {
- kfree(kbtab);
- return -ENOMEM;
- }
+ if (!kbtab->data)
+ goto fail1;
kbtab->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!kbtab->irq) {
- usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
- kfree(kbtab);
- return -ENOMEM;
- }
-
- kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
- kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-
- kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-
- kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
+ if (!kbtab->irq)
+ goto fail2;
- kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL);
-
- kbtab->dev.absmax[ABS_X] = 0x2000;
- kbtab->dev.absmax[ABS_Y] = 0x1750;
- kbtab->dev.absmax[ABS_PRESSURE] = 0xff;
+ kbtab->usbdev = dev;
+ kbtab->dev = input_dev;
- kbtab->dev.absfuzz[ABS_X] = 4;
- kbtab->dev.absfuzz[ABS_Y] = 4;
+ usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys));
+ strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys));
- kbtab->dev.private = kbtab;
- kbtab->dev.open = kbtab_open;
- kbtab->dev.close = kbtab_close;
+ input_dev->name = "KB Gear Tablet";
+ input_dev->phys = kbtab->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = kbtab;
- usb_make_path(dev, path, 64);
- sprintf(kbtab->phys, "%s/input0", path);
+ input_dev->open = kbtab_open;
+ input_dev->close = kbtab_close;
- kbtab->dev.name = "KB Gear Tablet";
- kbtab->dev.phys = kbtab->phys;
- usb_to_input_id(dev, &kbtab->dev.id);
- kbtab->dev.dev = &intf->dev;
- kbtab->usbdev = dev;
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
+ input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, 0x1750, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
endpoint = &intf->cur_altsetting->endpoint[0].desc;
@@ -181,23 +171,25 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
kbtab->irq->transfer_dma = kbtab->data_dma;
kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&kbtab->dev);
-
- printk(KERN_INFO "input: KB Gear Tablet on %s\n", path);
+ input_register_device(kbtab->dev);
usb_set_intfdata(intf, kbtab);
-
return 0;
+
+fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(kbtab);
+ return -ENOMEM;
}
static void kbtab_disconnect(struct usb_interface *intf)
{
- struct kbtab *kbtab = usb_get_intfdata (intf);
+ struct kbtab *kbtab = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
if (kbtab) {
usb_kill_urb(kbtab->irq);
- input_unregister_device(&kbtab->dev);
+ input_unregister_device(kbtab->dev);
usb_free_urb(kbtab->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma);
kfree(kbtab);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 67dc93685203..5b8d65f62abf 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -20,6 +20,7 @@
#include <linux/moduleparam.h>
#include <linux/input.h>
#include <linux/usb.h>
+#include <linux/usb_input.h>
#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>"
@@ -75,7 +76,7 @@ struct usb_keyspan {
char name[128];
char phys[64];
struct usb_device* udev;
- struct input_dev input;
+ struct input_dev *input;
struct usb_interface* interface;
struct usb_endpoint_descriptor* in_endpoint;
struct urb* irq_urb;
@@ -136,12 +137,11 @@ static struct usb_driver keyspan_driver;
*/
static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
{
- char codes[4*RECV_SIZE];
+ char codes[4 * RECV_SIZE];
int i;
- for (i = 0; i < RECV_SIZE; i++) {
- snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]);
- }
+ for (i = 0; i < RECV_SIZE; i++)
+ snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]);
dev_info(&dev->udev->dev, "%s\n", codes);
}
@@ -153,7 +153,7 @@ static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
{
if (dev->data.bits_left >= bits_needed)
- return(0);
+ return 0;
/*
* Somehow we've missed the last message. The message will be repeated
@@ -162,7 +162,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
if (dev->data.pos >= dev->data.len) {
dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n",
__FUNCTION__, dev->data.pos, dev->data.len);
- return(-1);
+ return -1;
}
/* Load as much as we can into the tester. */
@@ -172,7 +172,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
dev->data.bits_left += 8;
}
- return(0);
+ return 0;
}
/*
@@ -311,10 +311,10 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
__FUNCTION__, message.system, message.button, message.toggle);
if (message.toggle != remote->toggle) {
- input_regs(&remote->input, regs);
- input_report_key(&remote->input, keyspan_key_table[message.button], 1);
- input_report_key(&remote->input, keyspan_key_table[message.button], 0);
- input_sync(&remote->input);
+ input_regs(remote->input, regs);
+ input_report_key(remote->input, keyspan_key_table[message.button], 1);
+ input_report_key(remote->input, keyspan_key_table[message.button], 0);
+ input_sync(remote->input);
remote->toggle = message.toggle;
}
@@ -397,14 +397,9 @@ static int keyspan_open(struct input_dev *dev)
{
struct usb_keyspan *remote = dev->private;
- if (remote->open++)
- return 0;
-
remote->irq_urb->dev = remote->udev;
- if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) {
- remote->open--;
+ if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
return -EIO;
- }
return 0;
}
@@ -413,8 +408,26 @@ static void keyspan_close(struct input_dev *dev)
{
struct usb_keyspan *remote = dev->private;
- if (!--remote->open)
- usb_kill_urb(remote->irq_urb);
+ usb_kill_urb(remote->irq_urb);
+}
+
+static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface)
+{
+
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+
+ for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
+ endpoint = &iface->endpoint[i].desc;
+
+ if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ /* we found our interrupt in endpoint */
+ return endpoint;
+ }
+ }
+
+ return NULL;
}
/*
@@ -422,115 +435,78 @@ static void keyspan_close(struct input_dev *dev)
*/
static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
- int i;
- int retval = -ENOMEM;
- char path[64];
- char *buf;
- struct usb_keyspan *remote = NULL;
- struct usb_host_interface *iface_desc;
+ struct usb_device *udev = interface_to_usbdev(interface);
struct usb_endpoint_descriptor *endpoint;
- struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
+ struct usb_keyspan *remote;
+ struct input_dev *input_dev;
+ int i, retval;
- /* See if the offered device matches what we can accept */
- if ((udev->descriptor.idVendor != USB_KEYSPAN_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_KEYSPAN_PRODUCT_UIA11) )
+ endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
+ if (!endpoint)
return -ENODEV;
- /* allocate memory for our device state and initialize it */
- remote = kmalloc(sizeof(*remote), GFP_KERNEL);
- if (remote == NULL) {
- err("Out of memory\n");
- goto error;
+ remote = kzalloc(sizeof(*remote), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!remote || !input_dev) {
+ retval = -ENOMEM;
+ goto fail1;
}
- memset(remote, 0x00, sizeof(*remote));
remote->udev = udev;
+ remote->input = input_dev;
remote->interface = interface;
+ remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
- /* set up the endpoint information */
- /* use only the first in interrupt endpoint */
- iface_desc = interface->cur_altsetting;
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
-
- if (!remote->in_endpoint &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- /* we found our interrupt in endpoint */
- remote->in_endpoint = endpoint;
-
- remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
- if (!remote->in_buffer) {
- retval = -ENOMEM;
- goto error;
- }
- }
- }
-
- if (!remote->in_endpoint) {
- err("Could not find interrupt input endpoint.\n");
- retval = -ENODEV;
- goto error;
+ remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+ if (!remote->in_buffer) {
+ retval = -ENOMEM;
+ goto fail1;
}
remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!remote->irq_urb) {
- err("Failed to allocate urb.\n");
retval = -ENOMEM;
- goto error;
+ goto fail2;
}
- retval = keyspan_setup(remote->udev);
+ retval = keyspan_setup(udev);
if (retval) {
- err("Failed to setup device.\n");
retval = -ENODEV;
- goto error;
- }
-
- /*
- * Setup the input system with the bits we are going to be reporting
- */
- remote->input.evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */
- for (i = 0; i < 32; ++i) {
- if (keyspan_key_table[i] != KEY_RESERVED) {
- set_bit(keyspan_key_table[i], remote->input.keybit);
- }
+ goto fail3;
}
- remote->input.private = remote;
- remote->input.open = keyspan_open;
- remote->input.close = keyspan_close;
-
- usb_make_path(remote->udev, path, 64);
- sprintf(remote->phys, "%s/input0", path);
+ if (udev->manufacturer)
+ strlcpy(remote->name, udev->manufacturer, sizeof(remote->name));
- remote->input.name = remote->name;
- remote->input.phys = remote->phys;
- remote->input.id.bustype = BUS_USB;
- remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor);
- remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct);
- remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice);
-
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
- kfree(remote);
- return -ENOMEM;
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(remote->name, " ", sizeof(remote->name));
+ strlcat(remote->name, udev->product, sizeof(remote->name));
}
- if (remote->udev->descriptor.iManufacturer &&
- usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(remote->name, buf);
+ if (!strlen(remote->name))
+ snprintf(remote->name, sizeof(remote->name),
+ "USB Keyspan Remote %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
- if (remote->udev->descriptor.iProduct &&
- usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0)
- sprintf(remote->name, "%s %s", remote->name, buf);
+ usb_make_path(udev, remote->phys, sizeof(remote->phys));
+ strlcat(remote->phys, "/input0", sizeof(remote->phys));
- if (!strlen(remote->name))
- sprintf(remote->name, "USB Keyspan Remote %04x:%04x",
- remote->input.id.vendor, remote->input.id.product);
+ input_dev->name = remote->name;
+ input_dev->phys = remote->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &interface->dev;
- kfree(buf);
+ input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */
+ for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
+ if (keyspan_key_table[i] != KEY_RESERVED)
+ set_bit(keyspan_key_table[i], input_dev->keybit);
+
+ input_dev->private = remote;
+ input_dev->open = keyspan_open;
+ input_dev->close = keyspan_close;
/*
* Initialize the URB to access the device. The urb gets sent to the device in keyspan_open()
@@ -543,27 +519,17 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* we can register the device now, as it is ready */
- input_register_device(&remote->input);
+ input_register_device(remote->input);
/* save our data pointer in this interface device */
usb_set_intfdata(interface, remote);
- /* let the user know what node this device is now attached to */
- info("connected: %s on %s", remote->name, path);
return 0;
-error:
- /*
- * In case of error we need to clean up any allocated buffers
- */
- if (remote->irq_urb)
- usb_free_urb(remote->irq_urb);
-
- if (remote->in_buffer)
- usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
-
- if (remote)
- kfree(remote);
+ fail3: usb_free_urb(remote->irq_urb);
+ fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
+ fail1: kfree(remote);
+ input_free_device(input_dev);
return retval;
}
@@ -575,23 +541,16 @@ static void keyspan_disconnect(struct usb_interface *interface)
{
struct usb_keyspan *remote;
- /* prevent keyspan_open() from racing keyspan_disconnect() */
- lock_kernel();
-
remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (remote) { /* We have a valid driver structure so clean up everything we allocated. */
- input_unregister_device(&remote->input);
+ input_unregister_device(remote->input);
usb_kill_urb(remote->irq_urb);
usb_free_urb(remote->irq_urb);
- usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma);
+ usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
kfree(remote);
}
-
- unlock_kernel();
-
- info("USB Keyspan now disconnected");
}
/*
diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h
new file mode 100644
index 000000000000..a424094d9fe2
--- /dev/null
+++ b/drivers/usb/input/map_to_7segment.h
@@ -0,0 +1,189 @@
+/*
+ * 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/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index ff9275057a18..7fce526560ca 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -98,7 +98,7 @@ struct mtouch_usb {
dma_addr_t data_dma;
struct urb *irq;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
char name[128];
char phys[64];
};
@@ -135,14 +135,14 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- input_regs(&mtouch->input, regs);
- input_report_key(&mtouch->input, BTN_TOUCH,
+ input_regs(mtouch->input, regs);
+ input_report_key(mtouch->input, BTN_TOUCH,
MTOUCHUSB_GET_TOUCHED(mtouch->data));
- input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
- input_report_abs(&mtouch->input, ABS_Y,
+ input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
+ input_report_abs(mtouch->input, ABS_Y,
(raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
- MTOUCHUSB_GET_YC(mtouch->data));
- input_sync(&mtouch->input);
+ input_sync(mtouch->input);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -195,10 +195,10 @@ static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *m
static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct mtouch_usb *mtouch;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
- char path[64];
int nRet;
dbg("%s - called", __FUNCTION__);
@@ -209,57 +209,55 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
dbg("%s - setting endpoint", __FUNCTION__);
endpoint = &interface->endpoint[0].desc;
- if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) {
+ mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mtouch || !input_dev) {
err("%s - Out of memory.", __FUNCTION__);
- return -ENOMEM;
+ goto fail1;
}
- memset(mtouch, 0, sizeof(struct mtouch_usb));
- mtouch->udev = udev;
-
dbg("%s - allocating buffers", __FUNCTION__);
- if (mtouchusb_alloc_buffers(udev, mtouch)) {
- mtouchusb_free_buffers(udev, mtouch);
- kfree(mtouch);
- return -ENOMEM;
- }
+ if (mtouchusb_alloc_buffers(udev, mtouch))
+ goto fail2;
- mtouch->input.private = mtouch;
- mtouch->input.open = mtouchusb_open;
- mtouch->input.close = mtouchusb_close;
-
- usb_make_path(udev, path, 64);
- sprintf(mtouch->phys, "%s/input0", path);
-
- mtouch->input.name = mtouch->name;
- mtouch->input.phys = mtouch->phys;
- usb_to_input_id(udev, &mtouch->input.id);
- mtouch->input.dev = &intf->dev;
-
- mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- /* Used to Scale Compensated Data and Flip Y */
- mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC;
- mtouch->input.absmax[ABS_X] = raw_coordinates ?
- MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
- mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
- mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
- mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC;
- mtouch->input.absmax[ABS_Y] = raw_coordinates ?
- MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
- mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
- mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
+ mtouch->udev = udev;
+ mtouch->input = input_dev;
if (udev->manufacturer)
- strcat(mtouch->name, udev->manufacturer);
- if (udev->product)
- sprintf(mtouch->name, "%s %s", mtouch->name, udev->product);
+ strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(mtouch->name, " ", sizeof(mtouch->name));
+ strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
+ }
if (!strlen(mtouch->name))
- sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
- mtouch->input.id.vendor, mtouch->input.id.product);
+ snprintf(mtouch->name, sizeof(mtouch->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
+ strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
+
+ input_dev->name = mtouch->name;
+ input_dev->phys = mtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = mtouch;
+
+ input_dev->open = mtouchusb_open;
+ input_dev->close = mtouchusb_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
+ raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
+ MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
+ input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
+ raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
+ MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_RESET,
@@ -272,9 +270,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!mtouch->irq) {
dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
- mtouchusb_free_buffers(udev, mtouch);
- kfree(mtouch);
- return -ENOMEM;
+ goto fail2;
}
dbg("%s - usb_fill_int_urb", __FUNCTION__);
@@ -284,7 +280,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
mtouchusb_irq, mtouch, endpoint->bInterval);
dbg("%s - input_register_device", __FUNCTION__);
- input_register_device(&mtouch->input);
+ input_register_device(mtouch->input);
nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
@@ -293,10 +289,13 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
__FUNCTION__, nRet);
- printk(KERN_INFO "input: %s on %s\n", mtouch->name, path);
usb_set_intfdata(intf, mtouch);
-
return 0;
+
+fail2: mtouchusb_free_buffers(udev, mtouch);
+fail1: input_free_device(input_dev);
+ kfree(mtouch);
+ return -ENOMEM;
}
static void mtouchusb_disconnect(struct usb_interface *intf)
@@ -308,7 +307,7 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
if (mtouch) {
dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
usb_kill_urb(mtouch->irq);
- input_unregister_device(&mtouch->input);
+ input_unregister_device(mtouch->input);
usb_free_urb(mtouch->irq);
mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
kfree(mtouch);
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index 256963863478..dca5ee93a4ef 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -198,7 +198,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
}
effect->id = id;
- dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id);
+ dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id);
pid_private->effects[id].owner = current->pid;
pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED);
spin_unlock_irqrestore(&pid_private->lock, flags);
@@ -262,8 +262,9 @@ int hid_pid_init(struct hid_device *hid)
{
struct hid_ff_pid *private;
struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
- private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+ private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
if (!private)
return -ENOMEM;
@@ -281,11 +282,12 @@ int hid_pid_init(struct hid_device *hid)
usb_fill_control_urb(private->urbffout, hid->dev, 0,
(void *)&private->ffcr, private->ctrl_buffer, 8,
hid_pid_ctrl_out, hid);
- hidinput->input.upload_effect = hid_pid_upload_effect;
- hidinput->input.flush = hid_pid_flush;
- hidinput->input.ff_effects_max = 8; // A random default
- set_bit(EV_FF, hidinput->input.evbit);
- set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+ input_dev->upload_effect = hid_pid_upload_effect;
+ input_dev->flush = hid_pid_flush;
+ input_dev->ff_effects_max = 8; // A random default
+ set_bit(EV_FF, input_dev->evbit);
+ set_bit(EV_FF_STATUS, input_dev->evbit);
spin_lock_init(&private->lock);
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index ad4afe7e5897..b7476233ef5d 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -68,7 +68,7 @@ struct powermate_device {
struct usb_ctrlrequest *configcr;
dma_addr_t configcr_dma;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
spinlock_t lock;
int static_brightness;
int pulse_speed;
@@ -106,10 +106,10 @@ static void powermate_irq(struct urb *urb, struct pt_regs *regs)
}
/* handle updates to device state */
- input_regs(&pm->input, regs);
- input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01);
- input_report_rel(&pm->input, REL_DIAL, pm->data[1]);
- input_sync(&pm->input);
+ input_regs(pm->input, regs);
+ input_report_key(pm->input, BTN_0, pm->data[0] & 0x01);
+ input_report_rel(pm->input, REL_DIAL, pm->data[1]);
+ input_sync(pm->input);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -153,10 +153,10 @@ static void powermate_sync_state(struct powermate_device *pm)
Only values of 'arg' quite close to 255 are particularly useful/spectacular.
*/
- if (pm->pulse_speed < 255){
+ if (pm->pulse_speed < 255) {
op = 0; // divide
arg = 255 - pm->pulse_speed;
- } else if (pm->pulse_speed > 255){
+ } else if (pm->pulse_speed > 255) {
op = 2; // multiply
arg = pm->pulse_speed - 255;
} else {
@@ -166,11 +166,11 @@ static void powermate_sync_state(struct powermate_device *pm)
pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE );
pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op );
pm->requires_update &= ~UPDATE_PULSE_MODE;
- }else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){
+ } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) {
pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS );
pm->configcr->wIndex = cpu_to_le16( pm->static_brightness );
pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS;
- }else{
+ } else {
printk(KERN_ERR "powermate: unknown update required");
pm->requires_update = 0; /* fudge the bug */
return;
@@ -228,19 +228,19 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
spin_lock_irqsave(&pm->lock, flags);
/* mark state updates which are required */
- if (static_brightness != pm->static_brightness){
+ if (static_brightness != pm->static_brightness) {
pm->static_brightness = static_brightness;
pm->requires_update |= UPDATE_STATIC_BRIGHTNESS;
}
- if (pulse_asleep != pm->pulse_asleep){
+ if (pulse_asleep != pm->pulse_asleep) {
pm->pulse_asleep = pulse_asleep;
pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS);
}
- if (pulse_awake != pm->pulse_awake){
+ if (pulse_awake != pm->pulse_awake) {
pm->pulse_awake = pulse_awake;
pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS);
}
- if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){
+ if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) {
pm->pulse_speed = pulse_speed;
pm->pulse_table = pulse_table;
pm->requires_update |= UPDATE_PULSE_MODE;
@@ -283,6 +283,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
SLAB_ATOMIC, &pm->data_dma);
if (!pm->data)
return -1;
+
pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
SLAB_ATOMIC, &pm->configcr_dma);
if (!pm->configcr)
@@ -308,8 +309,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct powermate_device *pm;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
+ int err = -ENOMEM;
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
@@ -323,42 +325,61 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
0, interface->desc.bInterfaceNumber, NULL, 0,
USB_CTRL_SET_TIMEOUT);
- if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
- return -ENOMEM;
-
- memset(pm, 0, sizeof(struct powermate_device));
- pm->udev = udev;
+ pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!pm || !input_dev)
+ goto fail1;
- if (powermate_alloc_buffers(udev, pm)) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (powermate_alloc_buffers(udev, pm))
+ goto fail2;
pm->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!pm->irq) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (!pm->irq)
+ goto fail2;
pm->config = usb_alloc_urb(0, GFP_KERNEL);
- if (!pm->config) {
- usb_free_urb(pm->irq);
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -ENOMEM;
- }
+ if (!pm->config)
+ goto fail3;
+
+ pm->udev = udev;
+ pm->input = input_dev;
+
+ usb_make_path(udev, pm->phys, sizeof(pm->phys));
+ strlcpy(pm->phys, "/input0", sizeof(pm->phys));
spin_lock_init(&pm->lock);
- init_input_dev(&pm->input);
+
+ switch (le16_to_cpu(udev->descriptor.idProduct)) {
+ case POWERMATE_PRODUCT_NEW:
+ input_dev->name = pm_name_powermate;
+ break;
+ case POWERMATE_PRODUCT_OLD:
+ input_dev->name = pm_name_soundknob;
+ break;
+ default:
+ input_dev->name = pm_name_soundknob;
+ printk(KERN_WARNING "powermate: unknown product id %04x\n",
+ le16_to_cpu(udev->descriptor.idProduct));
+ }
+
+ input_dev->phys = pm->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = pm;
+
+ input_dev->event = powermate_input_event;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
+ input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+ input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
+ input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
/* get a handle to the interrupt data pipe */
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
- if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){
- printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
+ if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) {
+ printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp);
maxp = POWERMATE_PAYLOAD_SIZE_MAX;
}
@@ -371,35 +392,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
/* register our interrupt URB with the USB system */
if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
- powermate_free_buffers(udev, pm);
- kfree(pm);
- return -EIO; /* failure */
+ err = -EIO;
+ goto fail4;
}
- switch (le16_to_cpu(udev->descriptor.idProduct)) {
- case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break;
- case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break;
- default:
- pm->input.name = pm_name_soundknob;
- printk(KERN_WARNING "powermate: unknown product id %04x\n",
- le16_to_cpu(udev->descriptor.idProduct));
- }
-
- pm->input.private = pm;
- pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
- pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
- pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
- pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
- usb_to_input_id(udev, &pm->input.id);
- pm->input.event = powermate_input_event;
- pm->input.dev = &intf->dev;
- pm->input.phys = pm->phys;
-
- input_register_device(&pm->input);
-
- usb_make_path(udev, path, 64);
- snprintf(pm->phys, 64, "%s/input0", path);
- printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys);
+ input_register_device(pm->input);
/* force an update of everything */
pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -407,6 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
usb_set_intfdata(intf, pm);
return 0;
+
+fail4: usb_free_urb(pm->config);
+fail3: usb_free_urb(pm->irq);
+fail2: powermate_free_buffers(udev, pm);
+fail1: input_free_device(input_dev);
+ kfree(pm);
+ return err;
}
/* Called when a USB device we've accepted ownership of is removed */
@@ -418,7 +422,7 @@ static void powermate_disconnect(struct usb_interface *intf)
if (pm) {
pm->requires_update = 0;
usb_kill_urb(pm->irq);
- input_unregister_device(&pm->input);
+ input_unregister_device(pm->input);
usb_free_urb(pm->irq);
usb_free_urb(pm->config);
powermate_free_buffers(interface_to_usbdev(intf), pm);
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 4276c24a5080..0043e6ebcd1f 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -68,14 +68,16 @@ struct touchkit_usb {
dma_addr_t data_dma;
struct urb *irq;
struct usb_device *udev;
- struct input_dev input;
+ struct input_dev *input;
char name[128];
char phys[64];
};
static struct usb_device_id touchkit_devices[] = {
{USB_DEVICE(0x3823, 0x0001)},
+ {USB_DEVICE(0x0123, 0x0001)},
{USB_DEVICE(0x0eef, 0x0001)},
+ {USB_DEVICE(0x0eef, 0x0002)},
{}
};
@@ -115,12 +117,12 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
y = TOUCHKIT_GET_Y(touchkit->data);
}
- input_regs(&touchkit->input, regs);
- input_report_key(&touchkit->input, BTN_TOUCH,
+ input_regs(touchkit->input, regs);
+ input_report_key(touchkit->input, BTN_TOUCH,
TOUCHKIT_GET_TOUCHED(touchkit->data));
- input_report_abs(&touchkit->input, ABS_X, x);
- input_report_abs(&touchkit->input, ABS_Y, y);
- input_sync(&touchkit->input);
+ input_report_abs(touchkit->input, ABS_X, x);
+ input_report_abs(touchkit->input, ABS_Y, y);
+ input_sync(touchkit->input);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -171,87 +173,81 @@ static void touchkit_free_buffers(struct usb_device *udev,
static int touchkit_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- int ret;
struct touchkit_usb *touchkit;
+ struct input_dev *input_dev;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
- char path[64];
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
- if (!touchkit)
- return -ENOMEM;
-
- memset(touchkit, 0, sizeof(struct touchkit_usb));
- touchkit->udev = udev;
-
- if (touchkit_alloc_buffers(udev, touchkit)) {
- ret = -ENOMEM;
+ touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!touchkit || !input_dev)
goto out_free;
- }
-
- touchkit->input.private = touchkit;
- touchkit->input.open = touchkit_open;
- touchkit->input.close = touchkit_close;
-
- usb_make_path(udev, path, 64);
- sprintf(touchkit->phys, "%s/input0", path);
-
- touchkit->input.name = touchkit->name;
- touchkit->input.phys = touchkit->phys;
- usb_to_input_id(udev, &touchkit->input.id);
- touchkit->input.dev = &intf->dev;
-
- touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
- touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
- /* Used to Scale Compensated Data */
- touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC;
- touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC;
- touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ;
- touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT;
- touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC;
- touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC;
- touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ;
- touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT;
-
- if (udev->manufacturer)
- strcat(touchkit->name, udev->manufacturer);
- if (udev->product)
- sprintf(touchkit->name, "%s %s", touchkit->name, udev->product);
- if (!strlen(touchkit->name))
- sprintf(touchkit->name, "USB Touchscreen %04x:%04x",
- touchkit->input.id.vendor, touchkit->input.id.product);
+ if (touchkit_alloc_buffers(udev, touchkit))
+ goto out_free;
touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!touchkit->irq) {
dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
- ret = -ENOMEM;
goto out_free_buffers;
}
+ touchkit->udev = udev;
+ touchkit->input = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(touchkit->name, " ", sizeof(touchkit->name));
+ strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
+ }
+
+ if (!strlen(touchkit->name))
+ snprintf(touchkit->name, sizeof(touchkit->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
+ strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
+
+ input_dev->name = touchkit->name;
+ input_dev->phys = touchkit->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = touchkit;
+ input_dev->open = touchkit_open;
+ input_dev->close = touchkit_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
+ TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
+ input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
+ TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
+
usb_fill_int_urb(touchkit->irq, touchkit->udev,
- usb_rcvintpipe(touchkit->udev, 0x81),
- touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
- touchkit_irq, touchkit, endpoint->bInterval);
+ usb_rcvintpipe(touchkit->udev, 0x81),
+ touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
+ touchkit_irq, touchkit, endpoint->bInterval);
- input_register_device(&touchkit->input);
+ input_register_device(touchkit->input);
- printk(KERN_INFO "input: %s on %s\n", touchkit->name, path);
usb_set_intfdata(intf, touchkit);
-
return 0;
out_free_buffers:
touchkit_free_buffers(udev, touchkit);
out_free:
+ input_free_device(input_dev);
kfree(touchkit);
- return ret;
+ return -ENOMEM;
}
static void touchkit_disconnect(struct usb_interface *intf)
@@ -265,8 +261,8 @@ static void touchkit_disconnect(struct usb_interface *intf)
dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
usb_set_intfdata(intf, NULL);
- input_unregister_device(&touchkit->input);
usb_kill_urb(touchkit->irq);
+ input_unregister_device(touchkit->input);
usb_free_urb(touchkit->irq);
touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
kfree(touchkit);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 28987f15eeee..226b6f90a907 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -66,7 +66,7 @@ static unsigned char usb_kbd_keycode[256] = {
};
struct usb_kbd {
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
unsigned char old[8];
struct urb *irq, *led;
@@ -99,29 +99,29 @@ static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
- input_regs(&kbd->dev, regs);
+ input_regs(kbd->dev, regs);
for (i = 0; i < 8; i++)
- input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
+ input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
for (i = 2; i < 8; i++) {
if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
if (usb_kbd_keycode[kbd->old[i]])
- input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
+ input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
else
info("Unknown key (scancode %#x) released.", 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);
+ input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
}
}
- input_sync(&kbd->dev);
+ input_sync(kbd->dev);
memcpy(kbd->old, kbd->new, 8);
@@ -227,12 +227,12 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
static int usb_kbd_probe(struct usb_interface *iface,
const struct usb_device_id *id)
{
- struct usb_device * dev = interface_to_usbdev(iface);
+ struct usb_device *dev = interface_to_usbdev(iface);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_kbd *kbd;
+ struct input_dev *input_dev;
int i, pipe, maxp;
- char path[64];
interface = iface->cur_altsetting;
@@ -240,37 +240,59 @@ static int usb_kbd_probe(struct usb_interface *iface,
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -ENODEV;
- if ((endpoint->bmAttributes & 3) != 3)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL)))
- return -ENOMEM;
- memset(kbd, 0, sizeof(struct usb_kbd));
+ kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!kbd || !input_dev)
+ goto fail1;
- if (usb_kbd_alloc_mem(dev, kbd)) {
- usb_kbd_free_mem(dev, kbd);
- kfree(kbd);
- return -ENOMEM;
- }
+ if (usb_kbd_alloc_mem(dev, kbd))
+ goto fail2;
kbd->usbdev = dev;
+ kbd->dev = input_dev;
+
+ if (dev->manufacturer)
+ strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
+
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(kbd->name, " ", sizeof(kbd->name));
+ strlcat(kbd->name, dev->product, sizeof(kbd->name));
+ }
+
+ if (!strlen(kbd->name))
+ snprintf(kbd->name, sizeof(kbd->name),
+ "USB HIDBP Keyboard %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
+ strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
- kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
+ input_dev->name = kbd->name;
+ input_dev->phys = kbd->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &iface->dev;
+ input_dev->private = kbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+ input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
for (i = 0; i < 255; i++)
- set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
- clear_bit(0, kbd->dev.keybit);
+ set_bit(usb_kbd_keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
- kbd->dev.private = kbd;
- kbd->dev.event = usb_kbd_event;
- kbd->dev.open = usb_kbd_open;
- kbd->dev.close = usb_kbd_close;
+ input_dev->event = usb_kbd_event;
+ input_dev->open = usb_kbd_open;
+ input_dev->close = usb_kbd_close;
usb_fill_int_urb(kbd->irq, dev, pipe,
kbd->new, (maxp > 8 ? 8 : maxp),
@@ -284,37 +306,22 @@ static int usb_kbd_probe(struct usb_interface *iface,
kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
kbd->cr->wLength = cpu_to_le16(1);
- usb_make_path(dev, path, 64);
- sprintf(kbd->phys, "%s/input0", path);
-
- kbd->dev.name = kbd->name;
- kbd->dev.phys = kbd->phys;
- usb_to_input_id(dev, &kbd->dev.id);
- kbd->dev.dev = &iface->dev;
-
- if (dev->manufacturer)
- strcat(kbd->name, dev->manufacturer);
- if (dev->product)
- sprintf(kbd->name, "%s %s", kbd->name, dev->product);
-
- if (!strlen(kbd->name))
- sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
- kbd->dev.id.vendor, kbd->dev.id.product);
-
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void *) kbd->cr, kbd->leds, 1,
usb_kbd_led, kbd);
kbd->led->setup_dma = kbd->cr_dma;
kbd->led->transfer_dma = kbd->leds_dma;
- kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
- | URB_NO_SETUP_DMA_MAP);
+ kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- input_register_device(&kbd->dev);
-
- printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
+ input_register_device(kbd->dev);
usb_set_intfdata(iface, kbd);
return 0;
+
+fail2: usb_kbd_free_mem(dev, kbd);
+fail1: input_free_device(input_dev);
+ kfree(kbd);
+ return -ENOMEM;
}
static void usb_kbd_disconnect(struct usb_interface *intf)
@@ -324,7 +331,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (kbd) {
usb_kill_urb(kbd->irq);
- input_unregister_device(&kbd->dev);
+ input_unregister_device(kbd->dev);
usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
kfree(kbd);
}
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 4104dec847fb..230f6b1b314a 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -50,7 +50,7 @@ struct usb_mouse {
char name[128];
char phys[64];
struct usb_device *usbdev;
- struct input_dev dev;
+ struct input_dev *dev;
struct urb *irq;
signed char *data;
@@ -61,7 +61,7 @@ static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_mouse *mouse = urb->context;
signed char *data = mouse->data;
- struct input_dev *dev = &mouse->dev;
+ struct input_dev *dev = mouse->dev;
int status;
switch (urb->status) {
@@ -115,14 +115,14 @@ static void usb_mouse_close(struct input_dev *dev)
usb_kill_urb(mouse->irq);
}
-static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
+static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- struct usb_device * dev = interface_to_usbdev(intf);
+ struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_mouse *mouse;
+ struct input_dev *input_dev;
int pipe, maxp;
- char path[64];
interface = intf->cur_altsetting;
@@ -130,59 +130,62 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
return -ENODEV;
- if ((endpoint->bmAttributes & 3) != 3)
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
- return -ENOMEM;
- memset(mouse, 0, sizeof(struct usb_mouse));
+ mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mouse || !input_dev)
+ goto fail1;
mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
- if (!mouse->data) {
- kfree(mouse);
- return -ENOMEM;
- }
+ if (!mouse->data)
+ goto fail1;
mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!mouse->irq) {
- usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
- kfree(mouse);
- return -ENODEV;
- }
+ if (!mouse->irq)
+ goto fail2;
mouse->usbdev = dev;
+ mouse->dev = input_dev;
+
+ if (dev->manufacturer)
+ strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
- mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- mouse->dev.relbit[0] |= BIT(REL_WHEEL);
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(mouse->name, " ", sizeof(mouse->name));
+ strlcat(mouse->name, dev->product, sizeof(mouse->name));
+ }
- mouse->dev.private = mouse;
- mouse->dev.open = usb_mouse_open;
- mouse->dev.close = usb_mouse_close;
+ if (!strlen(mouse->name))
+ snprintf(mouse->name, sizeof(mouse->name),
+ "USB HIDBP Mouse %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
- usb_make_path(dev, path, 64);
- sprintf(mouse->phys, "%s/input0", path);
+ usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
+ strlcat(mouse->phys, "/input0", sizeof(mouse->phys));
- mouse->dev.name = mouse->name;
- mouse->dev.phys = mouse->phys;
- usb_to_input_id(dev, &mouse->dev.id);
- mouse->dev.dev = &intf->dev;
+ input_dev->name = mouse->name;
+ input_dev->phys = mouse->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
- if (dev->manufacturer)
- strcat(mouse->name, dev->manufacturer);
- if (dev->product)
- sprintf(mouse->name, "%s %s", mouse->name, dev->product);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
- if (!strlen(mouse->name))
- sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
- mouse->dev.id.vendor, mouse->dev.id.product);
+ input_dev->private = mouse;
+ input_dev->open = usb_mouse_open;
+ input_dev->close = usb_mouse_close;
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
(maxp > 8 ? 8 : maxp),
@@ -190,11 +193,15 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
mouse->irq->transfer_dma = mouse->data_dma;
mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&mouse->dev);
- printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
+ input_register_device(mouse->dev);
usb_set_intfdata(intf, mouse);
return 0;
+
+fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(mouse);
+ return -ENOMEM;
}
static void usb_mouse_disconnect(struct usb_interface *intf)
@@ -204,7 +211,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (mouse) {
usb_kill_urb(mouse->irq);
- input_unregister_device(&mouse->dev);
+ input_unregister_device(mouse->dev);
usb_free_urb(mouse->irq);
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
kfree(mouse);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 02412e31a46b..ea0f75773ae1 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -111,7 +111,7 @@ struct wacom_features {
struct wacom {
signed char *data;
dma_addr_t data_dma;
- struct input_dev dev;
+ struct input_dev *dev;
struct usb_device *usbdev;
struct urb *irq;
struct wacom_features *features;
@@ -135,7 +135,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int prox, pressure;
int retval;
@@ -225,7 +225,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int retval;
switch (urb->status) {
@@ -275,7 +275,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int retval;
switch (urb->status) {
@@ -318,7 +318,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int x, y;
int retval;
@@ -342,9 +342,6 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- x = le16_to_cpu(*(__le16 *) &data[2]);
- y = le16_to_cpu(*(__le16 *) &data[4]);
-
input_regs(dev, regs);
if (data[1] & 0x10) { /* in prox */
@@ -373,15 +370,17 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
}
}
- if (data[1] & 0x80) {
+ if (data[1] & 0x90) {
+ x = le16_to_cpu(*(__le16 *) &data[2]);
+ y = le16_to_cpu(*(__le16 *) &data[4]);
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
- }
- if (wacom->tool[0] != BTN_TOOL_MOUSE) {
- input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
- input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
- input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
- input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+ if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+ input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
+ input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+ input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
+ input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+ }
}
input_report_key(dev, wacom->tool[0], data[1] & 0x10);
@@ -398,7 +397,7 @@ static int wacom_intuos_inout(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
int idx;
/* tool number */
@@ -480,7 +479,7 @@ static void wacom_intuos_general(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
unsigned int t;
/* general pen packet */
@@ -510,7 +509,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
- struct input_dev *dev = &wacom->dev;
+ struct input_dev *dev = wacom->dev;
unsigned int t;
int idx;
int retval;
@@ -568,7 +567,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
/* Cintiq doesn't send data when RDY bit isn't set */
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
- return;
+ goto exit;
if (wacom->features->type >= INTUOS3) {
input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
@@ -739,95 +738,83 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
- char rep_data[2] = {0x02, 0x02};
struct wacom *wacom;
- char path[64];
+ struct input_dev *input_dev;
+ char rep_data[2] = {0x02, 0x02};
- if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL)))
- return -ENOMEM;
- memset(wacom, 0, sizeof(struct wacom));
+ wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!wacom || !input_dev)
+ goto fail1;
wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
- if (!wacom->data) {
- kfree(wacom);
- return -ENOMEM;
- }
+ if (!wacom->data)
+ goto fail1;
wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!wacom->irq) {
- usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
- kfree(wacom);
- return -ENOMEM;
- }
+ if (!wacom->irq)
+ goto fail2;
+
+ wacom->usbdev = dev;
+ wacom->dev = input_dev;
+ usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+ strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
wacom->features = wacom_features + (id - wacom_ids);
+ if (wacom->features->pktlen > 10)
+ BUG();
+
+ input_dev->name = wacom->features->name;
+ usb_to_input_id(dev, &input_dev->id);
+
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = wacom;
+ input_dev->open = wacom_open;
+ input_dev->close = wacom_close;
- wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
- wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+ input_set_abs_params(input_dev, ABS_X, 0, wacom->features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
switch (wacom->features->type) {
case GRAPHIRE:
- wacom->dev.evbit[0] |= BIT(EV_REL);
- wacom->dev.relbit[0] |= BIT(REL_WHEEL);
- wacom->dev.absbit[0] |= BIT(ABS_DISTANCE);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+ input_dev->evbit[0] |= BIT(EV_REL);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
break;
case INTUOS3:
case CINTIQ:
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
- wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+ input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
/* fall through */
case INTUOS:
- wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
- wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
- wacom->dev.relbit[0] |= BIT(REL_WHEEL);
- wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
+ input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+ input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+ input_dev->relbit[0] |= BIT(REL_WHEEL);
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
| BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
- wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+ input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+ input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
break;
case PL:
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+ input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
break;
}
- wacom->dev.absmax[ABS_X] = wacom->features->x_max;
- wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
- wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
- wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
- wacom->dev.absmax[ABS_TILT_X] = 127;
- wacom->dev.absmax[ABS_TILT_Y] = 127;
- wacom->dev.absmax[ABS_WHEEL] = 1023;
-
- wacom->dev.absmax[ABS_RX] = 4097;
- wacom->dev.absmax[ABS_RY] = 4097;
- wacom->dev.absmin[ABS_RZ] = -900;
- wacom->dev.absmax[ABS_RZ] = 899;
- wacom->dev.absmin[ABS_THROTTLE] = -1023;
- wacom->dev.absmax[ABS_THROTTLE] = 1023;
-
- wacom->dev.absfuzz[ABS_X] = 4;
- wacom->dev.absfuzz[ABS_Y] = 4;
-
- wacom->dev.private = wacom;
- wacom->dev.open = wacom_open;
- wacom->dev.close = wacom_close;
-
- usb_make_path(dev, path, 64);
- sprintf(wacom->phys, "%s/input0", path);
-
- wacom->dev.name = wacom->features->name;
- wacom->dev.phys = wacom->phys;
- usb_to_input_id(dev, &wacom->dev.id);
- wacom->dev.dev = &intf->dev;
- wacom->usbdev = dev;
-
endpoint = &intf->cur_altsetting->endpoint[0].desc;
if (wacom->features->pktlen > 10)
@@ -840,18 +827,20 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->irq->transfer_dma = wacom->data_dma;
wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- input_register_device(&wacom->dev);
+ input_register_device(wacom->dev);
/* ask the tablet to report tablet data */
usb_set_report(intf, 3, 2, rep_data, 2);
/* repeat once (not sure why the first call often fails) */
usb_set_report(intf, 3, 2, rep_data, 2);
- printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
-
usb_set_intfdata(intf, wacom);
-
return 0;
+
+fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
+fail1: input_free_device(input_dev);
+ kfree(wacom);
+ return -ENOMEM;
}
static void wacom_disconnect(struct usb_interface *intf)
@@ -861,7 +850,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (wacom) {
usb_kill_urb(wacom->irq);
- input_unregister_device(&wacom->dev);
+ input_unregister_device(wacom->dev);
usb_free_urb(wacom->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
kfree(wacom);
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 18125e0bffa2..43112f040b6d 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -103,7 +103,7 @@ static struct usb_device_id xpad_table [] = {
MODULE_DEVICE_TABLE (usb, xpad_table);
struct usb_xpad {
- struct input_dev dev; /* input device interface */
+ struct input_dev *dev; /* input device interface */
struct usb_device *udev; /* usb device */
struct urb *irq_in; /* urb for interrupt in report */
@@ -125,7 +125,7 @@ struct usb_xpad {
static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs)
{
- struct input_dev *dev = &xpad->dev;
+ struct input_dev *dev = xpad->dev;
input_regs(dev, regs);
@@ -214,9 +214,9 @@ static void xpad_close (struct input_dev *dev)
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev (intf);
- struct usb_xpad *xpad = NULL;
+ struct usb_xpad *xpad;
+ struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
- char path[64];
int i;
for (i = 0; xpad_device[i].idVendor; i++) {
@@ -225,89 +225,80 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
break;
}
- if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) {
- err("cannot allocate memory for new pad");
- return -ENOMEM;
- }
- memset(xpad, 0, sizeof(struct usb_xpad));
+ xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!xpad || !input_dev)
+ goto fail1;
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
SLAB_ATOMIC, &xpad->idata_dma);
- if (!xpad->idata) {
- kfree(xpad);
- return -ENOMEM;
- }
+ if (!xpad->idata)
+ goto fail1;
xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
- if (!xpad->irq_in) {
- err("cannot allocate memory for new pad irq urb");
- usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
- kfree(xpad);
- return -ENOMEM;
- }
-
- ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
-
- usb_fill_int_urb(xpad->irq_in, udev,
- usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
- xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
- xpad, ep_irq_in->bInterval);
- xpad->irq_in->transfer_dma = xpad->idata_dma;
- xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ if (!xpad->irq_in)
+ goto fail2;
xpad->udev = udev;
+ xpad->dev = input_dev;
+ usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+ strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
- usb_to_input_id(udev, &xpad->dev.id);
- xpad->dev.dev = &intf->dev;
- xpad->dev.private = xpad;
- xpad->dev.name = xpad_device[i].name;
- xpad->dev.phys = xpad->phys;
- xpad->dev.open = xpad_open;
- xpad->dev.close = xpad_close;
-
- usb_make_path(udev, path, 64);
- snprintf(xpad->phys, 64, "%s/input0", path);
+ input_dev->name = xpad_device[i].name;
+ input_dev->phys = xpad->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = xpad;
+ input_dev->open = xpad_open;
+ input_dev->close = xpad_close;
- xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; xpad_btn[i] >= 0; i++)
- set_bit(xpad_btn[i], xpad->dev.keybit);
+ set_bit(xpad_btn[i], input_dev->keybit);
for (i = 0; xpad_abs[i] >= 0; i++) {
signed short t = xpad_abs[i];
- set_bit(t, xpad->dev.absbit);
+ set_bit(t, input_dev->absbit);
switch (t) {
case ABS_X:
case ABS_Y:
case ABS_RX:
case ABS_RY: /* the two sticks */
- xpad->dev.absmax[t] = 32767;
- xpad->dev.absmin[t] = -32768;
- xpad->dev.absflat[t] = 128;
- xpad->dev.absfuzz[t] = 16;
+ input_set_abs_params(input_dev, t, -32768, 32767, 16, 128);
break;
case ABS_Z:
case ABS_RZ: /* the triggers */
- xpad->dev.absmax[t] = 255;
- xpad->dev.absmin[t] = 0;
+ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y: /* the d-pad */
- xpad->dev.absmax[t] = 1;
- xpad->dev.absmin[t] = -1;
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
break;
}
}
- input_register_device(&xpad->dev);
+ ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
+ usb_fill_int_urb(xpad->irq_in, udev,
+ usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
+ xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
+ xpad, ep_irq_in->bInterval);
+ xpad->irq_in->transfer_dma = xpad->idata_dma;
+ xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- printk(KERN_INFO "input: %s on %s", xpad->dev.name, path);
+ input_register_device(xpad->dev);
usb_set_intfdata(intf, xpad);
return 0;
+
+fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+fail1: input_free_device(input_dev);
+ kfree(xpad);
+ return -ENOMEM;
+
}
static void xpad_disconnect(struct usb_interface *intf)
@@ -317,7 +308,7 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (xpad) {
usb_kill_urb(xpad->irq_in);
- input_unregister_device(&xpad->dev);
+ input_unregister_device(xpad->dev);
usb_free_urb(xpad->irq_in);
usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
kfree(xpad);
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
new file mode 100644
index 000000000000..f526aebea502
--- /dev/null
+++ b/drivers/usb/input/yealink.c
@@ -0,0 +1,1017 @@
+/*
+ * drivers/usb/input/yealink.c
+ *
+ * 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
+ */
+/*
+ * Description:
+ * Driver for the USB-P1K voip usb phone.
+ * This device is produced by Yealink Network Technology Co Ltd
+ * but may be branded under several names:
+ * - Yealink usb-p1k
+ * - Tiptel 115
+ * - ...
+ *
+ * This driver is based on:
+ * - the usbb2k-api http://savannah.nongnu.org/projects/usbb2k-api/
+ * - information from http://memeteau.free.fr/usbb2k
+ * - the xpad-driver drivers/usb/input/xpad.c
+ *
+ * Thanks to:
+ * - Olivier Vandorpe, for providing the usbb2k-api.
+ * - Martin Diehl, for spotting my memory allocation bug.
+ *
+ * History:
+ * 20050527 henk First version, functional keyboard. Keyboard events
+ * will pop-up on the ../input/eventX bus.
+ * 20050531 henk Added led, LCD, dialtone and sysfs interface.
+ * 20050610 henk Cleanups, make it ready for public consumption.
+ * 20050630 henk Cleanups, fixes in response to comments.
+ * 20050701 henk sysfs write serialisation, fix potential unload races
+ * 20050801 henk Added ringtone, restructure USB
+ * 20050816 henk Merge 2.6.13-rc6
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/usb.h>
+#include <linux/usb_input.h>
+
+#include "map_to_7segment.h"
+#include "yealink.h"
+
+#define DRIVER_VERSION "yld-20050816"
+#define DRIVER_AUTHOR "Henk Vergonet"
+#define DRIVER_DESC "Yealink phone driver"
+
+#define YEALINK_POLLING_FREQUENCY 10 /* in [Hz] */
+
+struct yld_status {
+ u8 lcd[24];
+ u8 led;
+ u8 dialtone;
+ u8 ringtone;
+ u8 keynum;
+} __attribute__ ((packed));
+
+/*
+ * Register the LCD segment and icon map
+ */
+#define _LOC(k,l) { .a = (k), .m = (l) }
+#define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm) \
+ { .type = (t), \
+ .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm), \
+ _LOC(d, dm), _LOC(e, em), _LOC(g, gm), \
+ _LOC(f, fm) } } }
+#define _PIC(t, h, hm, n) \
+ { .type = (t), \
+ .u = { .p = { .name = (n), .a = (h), .m = (hm) } } }
+
+static const struct lcd_segment_map {
+ char type;
+ union {
+ struct pictogram_map {
+ u8 a,m;
+ char name[10];
+ } p;
+ struct segment_map {
+ u8 a,m;
+ } s[7];
+ } u;
+} lcdMap[] = {
+#include "yealink.h"
+};
+
+struct yealink_dev {
+ struct input_dev *idev; /* input device */
+ struct usb_device *udev; /* usb device */
+
+ /* irq input channel */
+ struct yld_ctl_packet *irq_data;
+ dma_addr_t irq_dma;
+ struct urb *urb_irq;
+
+ /* control output channel */
+ struct yld_ctl_packet *ctl_data;
+ dma_addr_t ctl_dma;
+ struct usb_ctrlrequest *ctl_req;
+ dma_addr_t ctl_req_dma;
+ struct urb *urb_ctl;
+
+ char phys[64]; /* physical device path */
+
+ u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
+ int key_code; /* last reported key */
+
+ int stat_ix;
+ union {
+ struct yld_status s;
+ u8 b[sizeof(struct yld_status)];
+ } master, copy;
+};
+
+
+/*******************************************************************************
+ * Yealink lcd interface
+ ******************************************************************************/
+
+/*
+ * Register a default 7 segment character set
+ */
+static SEG7_DEFAULT_MAP(map_seg7);
+
+ /* Display a char,
+ * char '\9' and '\n' are placeholders and do not overwrite the original text.
+ * A space will always hide an icon.
+ */
+static int setChar(struct yealink_dev *yld, int el, int chr)
+{
+ int i, a, m, val;
+
+ if (el >= ARRAY_SIZE(lcdMap))
+ return -EINVAL;
+
+ if (chr == '\t' || chr == '\n')
+ return 0;
+
+ yld->lcdMap[el] = chr;
+
+ if (lcdMap[el].type == '.') {
+ a = lcdMap[el].u.p.a;
+ m = lcdMap[el].u.p.m;
+ if (chr != ' ')
+ yld->master.b[a] |= m;
+ else
+ yld->master.b[a] &= ~m;
+ return 0;
+ }
+
+ val = map_to_seg7(&map_seg7, chr);
+ for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) {
+ m = lcdMap[el].u.s[i].m;
+
+ if (m == 0)
+ continue;
+
+ a = lcdMap[el].u.s[i].a;
+ if (val & 1)
+ yld->master.b[a] |= m;
+ else
+ yld->master.b[a] &= ~m;
+ val = val >> 1;
+ }
+ return 0;
+};
+
+/*******************************************************************************
+ * Yealink key interface
+ ******************************************************************************/
+
+/* Map device buttons to internal key events.
+ *
+ * USB-P1K button layout:
+ *
+ * up
+ * IN OUT
+ * down
+ *
+ * pickup C hangup
+ * 1 2 3
+ * 4 5 6
+ * 7 8 9
+ * * 0 #
+ *
+ * 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.
+ */
+static int map_p1k_to_key(int scancode)
+{
+ switch(scancode) { /* phone key: */
+ case 0x23: return KEY_LEFT; /* IN */
+ case 0x33: return KEY_UP; /* up */
+ case 0x04: return KEY_RIGHT; /* OUT */
+ case 0x24: return KEY_DOWN; /* down */
+ case 0x03: return KEY_ENTER; /* pickup */
+ case 0x14: return KEY_BACKSPACE; /* C */
+ case 0x13: return KEY_ESC; /* hangup */
+ case 0x00: return KEY_1; /* 1 */
+ case 0x01: return KEY_2; /* 2 */
+ case 0x02: return KEY_3; /* 3 */
+ case 0x10: return KEY_4; /* 4 */
+ case 0x11: return KEY_5; /* 5 */
+ case 0x12: return KEY_6; /* 6 */
+ case 0x20: return KEY_7; /* 7 */
+ case 0x21: return KEY_8; /* 8 */
+ case 0x22: return KEY_9; /* 9 */
+ case 0x30: return KEY_KPASTERISK; /* * */
+ case 0x31: return KEY_0; /* 0 */
+ case 0x32: return KEY_LEFTSHIFT |
+ KEY_3 << 8; /* # */
+ }
+ return -EINVAL;
+}
+
+/* Completes a request by converting the data into events for the
+ * input subsystem.
+ *
+ * The key parameter can be cascaded: key2 << 8 | key1
+ */
+static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs)
+{
+ struct input_dev *idev = yld->idev;
+
+ input_regs(idev, regs);
+ if (yld->key_code >= 0) {
+ /* old key up */
+ input_report_key(idev, yld->key_code & 0xff, 0);
+ if (yld->key_code >> 8)
+ input_report_key(idev, yld->key_code >> 8, 0);
+ }
+
+ yld->key_code = key;
+ if (key >= 0) {
+ /* new valid key */
+ input_report_key(idev, key & 0xff, 1);
+ if (key >> 8)
+ input_report_key(idev, key >> 8, 1);
+ }
+ input_sync(idev);
+}
+
+/*******************************************************************************
+ * Yealink usb communication interface
+ ******************************************************************************/
+
+static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p)
+{
+ u8 *buf = (u8 *)p;
+ int i;
+ u8 sum = 0;
+
+ for(i=0; i<USB_PKT_LEN-1; i++)
+ sum -= buf[i];
+ p->sum = sum;
+ return usb_control_msg(yld->udev,
+ usb_sndctrlpipe(yld->udev, 0),
+ USB_REQ_SET_CONFIGURATION,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x200, 3,
+ p, sizeof(*p),
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static u8 default_ringtone[] = {
+ 0xEF, /* volume [0-255] */
+ 0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */
+ 0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFB, 0x1E, 0x00, 0x0C,
+ 0xFC, 0x18, 0x00, 0x0C,
+ 0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */
+ 0x00, 0x00 /* end of sequence */
+};
+
+static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size)
+{
+ struct yld_ctl_packet *p = yld->ctl_data;
+ int ix, len;
+
+ if (size <= 0)
+ return -EINVAL;
+
+ /* Set the ringtone volume */
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_RING_VOLUME;
+ yld->ctl_data->size = 1;
+ yld->ctl_data->data[0] = buf[0];
+ yealink_cmd(yld, p);
+
+ buf++;
+ size--;
+
+ p->cmd = CMD_RING_NOTE;
+ ix = 0;
+ while (size != ix) {
+ len = size - ix;
+ if (len > sizeof(p->data))
+ len = sizeof(p->data);
+ p->size = len;
+ p->offset = cpu_to_be16(ix);
+ memcpy(p->data, &buf[ix], len);
+ yealink_cmd(yld, p);
+ ix += len;
+ }
+ return 0;
+}
+
+/* keep stat_master & stat_copy in sync.
+ */
+static int yealink_do_idle_tasks(struct yealink_dev *yld)
+{
+ u8 val;
+ int i, ix, len;
+
+ ix = yld->stat_ix;
+
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_KEYPRESS;
+ yld->ctl_data->size = 1;
+ yld->ctl_data->sum = 0xff - CMD_KEYPRESS;
+
+ /* If state update pointer wraps do a KEYPRESS first. */
+ if (ix >= sizeof(yld->master)) {
+ yld->stat_ix = 0;
+ return 0;
+ }
+
+ /* find update candidates: copy != master */
+ do {
+ val = yld->master.b[ix];
+ if (val != yld->copy.b[ix])
+ goto send_update;
+ } while (++ix < sizeof(yld->master));
+
+ /* nothing todo, wait a bit and poll for a KEYPRESS */
+ yld->stat_ix = 0;
+ /* TODO how can we wait abit. ??
+ * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY);
+ */
+ return 0;
+
+send_update:
+
+ /* Setup an appropriate update request */
+ yld->copy.b[ix] = val;
+ yld->ctl_data->data[0] = val;
+
+ switch(ix) {
+ case offsetof(struct yld_status, led):
+ yld->ctl_data->cmd = CMD_LED;
+ yld->ctl_data->sum = -1 - CMD_LED - val;
+ break;
+ case offsetof(struct yld_status, dialtone):
+ yld->ctl_data->cmd = CMD_DIALTONE;
+ yld->ctl_data->sum = -1 - CMD_DIALTONE - val;
+ break;
+ case offsetof(struct yld_status, ringtone):
+ yld->ctl_data->cmd = CMD_RINGTONE;
+ yld->ctl_data->sum = -1 - CMD_RINGTONE - val;
+ break;
+ case offsetof(struct yld_status, keynum):
+ val--;
+ val &= 0x1f;
+ yld->ctl_data->cmd = CMD_SCANCODE;
+ yld->ctl_data->offset = cpu_to_be16(val);
+ yld->ctl_data->data[0] = 0;
+ yld->ctl_data->sum = -1 - CMD_SCANCODE - val;
+ break;
+ default:
+ len = sizeof(yld->master.s.lcd) - ix;
+ if (len > sizeof(yld->ctl_data->data))
+ len = sizeof(yld->ctl_data->data);
+
+ /* Combine up to <len> consecutive LCD bytes in a singe request
+ */
+ yld->ctl_data->cmd = CMD_LCD;
+ yld->ctl_data->offset = cpu_to_be16(ix);
+ yld->ctl_data->size = len;
+ yld->ctl_data->sum = -CMD_LCD - ix - val - len;
+ for(i=1; i<len; i++) {
+ ix++;
+ val = yld->master.b[ix];
+ yld->copy.b[ix] = val;
+ yld->ctl_data->data[i] = val;
+ yld->ctl_data->sum -= val;
+ }
+ }
+ yld->stat_ix = ix + 1;
+ return 1;
+}
+
+/* Decide on how to handle responses
+ *
+ * The state transition diagram is somethhing like:
+ *
+ * syncState<--+
+ * | |
+ * | idle
+ * \|/ |
+ * init --ok--> waitForKey --ok--> getKey
+ * ^ ^ |
+ * | +-------ok-------+
+ * error,start
+ *
+ */
+static void urb_irq_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct yealink_dev *yld = urb->context;
+ int ret;
+
+ if (urb->status)
+ err("%s - urb status %d", __FUNCTION__, urb->status);
+
+ switch (yld->irq_data->cmd) {
+ case CMD_KEYPRESS:
+
+ yld->master.s.keynum = yld->irq_data->data[0];
+ break;
+
+ case CMD_SCANCODE:
+ dbg("get scancode %x", yld->irq_data->data[0]);
+
+ report_key(yld, map_p1k_to_key(yld->irq_data->data[0]), regs);
+ break;
+
+ default:
+ err("unexpected response %x", yld->irq_data->cmd);
+ }
+
+ yealink_do_idle_tasks(yld);
+
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (ret)
+ err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+}
+
+static void urb_ctl_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct yealink_dev *yld = urb->context;
+ int ret;
+
+ if (urb->status)
+ err("%s - urb status %d", __FUNCTION__, urb->status);
+
+ switch (yld->ctl_data->cmd) {
+ case CMD_KEYPRESS:
+ case CMD_SCANCODE:
+ /* ask for a response */
+ ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+ break;
+ default:
+ /* send new command */
+ yealink_do_idle_tasks(yld);
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ }
+
+ if (ret)
+ err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+}
+
+/*******************************************************************************
+ * input event interface
+ ******************************************************************************/
+
+/* TODO should we issue a ringtone on a SND_BELL event?
+static int input_ev(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
+{
+
+ if (type != EV_SND)
+ return -EINVAL;
+
+ switch (code) {
+ case SND_BELL:
+ case SND_TONE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+*/
+
+static int input_open(struct input_dev *dev)
+{
+ struct yealink_dev *yld = dev->private;
+ int i, ret;
+
+ dbg("%s", __FUNCTION__);
+
+ /* force updates to device */
+ for (i = 0; i<sizeof(yld->master); i++)
+ yld->copy.b[i] = ~yld->master.b[i];
+ yld->key_code = -1; /* no keys pressed */
+
+ yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone));
+
+ /* issue INIT */
+ memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
+ yld->ctl_data->cmd = CMD_INIT;
+ yld->ctl_data->size = 10;
+ yld->ctl_data->sum = 0x100-CMD_INIT-10;
+ if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
+ dbg("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static void input_close(struct input_dev *dev)
+{
+ struct yealink_dev *yld = dev->private;
+
+ usb_kill_urb(yld->urb_ctl);
+ usb_kill_urb(yld->urb_irq);
+}
+
+/*******************************************************************************
+ * sysfs interface
+ ******************************************************************************/
+
+static DECLARE_RWSEM(sysfs_rwsema);
+
+/* Interface to the 7-segments translation table aka. char set.
+ */
+static ssize_t show_map(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ memcpy(buf, &map_seg7, sizeof(map_seg7));
+ return sizeof(map_seg7);
+}
+
+static ssize_t store_map(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t cnt)
+{
+ if (cnt != sizeof(map_seg7))
+ return -EINVAL;
+ memcpy(&map_seg7, buf, sizeof(map_seg7));
+ return sizeof(map_seg7);
+}
+
+/* Interface to the LCD.
+ */
+
+/* Reading /sys/../lineX will return the format string with its settings:
+ *
+ * Example:
+ * cat ./line3
+ * 888888888888
+ * Linux Rocks!
+ */
+static ssize_t show_line(struct device *dev, char *buf, int a, int b)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_read(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_read(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = a; i < b; i++)
+ *buf++ = lcdMap[i].type;
+ *buf++ = '\n';
+ for (i = a; i < b; i++)
+ *buf++ = yld->lcdMap[i];
+ *buf++ = '\n';
+ *buf = 0;
+
+ up_read(&sysfs_rwsema);
+ return 3 + ((b - a) << 1);
+}
+
+static ssize_t show_line1(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET);
+}
+
+static ssize_t show_line2(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET);
+}
+
+static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET);
+}
+
+/* Writing to /sys/../lineX will set the coresponding LCD line.
+ * - Excess characters are ignored.
+ * - If less characters are written than allowed, the remaining digits are
+ * unchanged.
+ * - The '\n' or '\t' char is a placeholder, it does not overwrite the
+ * original content.
+ */
+static ssize_t store_line(struct device *dev, const char *buf, size_t count,
+ int el, size_t len)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ if (len > count)
+ len = count;
+ for (i = 0; i < len; i++)
+ setChar(yld, el++, buf[i]);
+
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+static ssize_t store_line1(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE);
+}
+
+static ssize_t store_line2(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE);
+}
+
+static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE);
+}
+
+/* Interface to visible and audible "icons", these include:
+ * pictures on the LCD, the LED, and the dialtone signal.
+ */
+
+/* Get a list of "switchable elements" with their current state. */
+static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct yealink_dev *yld;
+ int i, ret = 1;
+
+ down_read(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_read(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
+ if (lcdMap[i].type != '.')
+ continue;
+ ret += sprintf(&buf[ret], "%s %s\n",
+ yld->lcdMap[i] == ' ' ? " " : "on",
+ lcdMap[i].u.p.name);
+ }
+ up_read(&sysfs_rwsema);
+ return ret;
+}
+
+/* Change the visibility of a particular element. */
+static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
+ int chr)
+{
+ struct yealink_dev *yld;
+ int i;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
+ if (lcdMap[i].type != '.')
+ continue;
+ if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) {
+ setChar(yld, i, chr);
+ break;
+ }
+ }
+
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+static ssize_t show_icon(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return set_icon(dev, buf, count, buf[0]);
+}
+
+static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return set_icon(dev, buf, count, ' ');
+}
+
+/* Upload a ringtone to the device.
+ */
+
+/* Stores raw ringtone data in the phone */
+static ssize_t store_ringtone(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct yealink_dev *yld;
+
+ down_write(&sysfs_rwsema);
+ yld = dev_get_drvdata(dev);
+ if (yld == NULL) {
+ up_write(&sysfs_rwsema);
+ return -ENODEV;
+ }
+
+ /* TODO locking with async usb control interface??? */
+ yealink_set_ringtone(yld, (char *)buf, count);
+ up_write(&sysfs_rwsema);
+ return count;
+}
+
+#define _M444 S_IRUGO
+#define _M664 S_IRUGO|S_IWUSR|S_IWGRP
+#define _M220 S_IWUSR|S_IWGRP
+
+static DEVICE_ATTR(map_seg7 , _M664, show_map , store_map );
+static DEVICE_ATTR(line1 , _M664, show_line1 , store_line1 );
+static DEVICE_ATTR(line2 , _M664, show_line2 , store_line2 );
+static DEVICE_ATTR(line3 , _M664, show_line3 , store_line3 );
+static DEVICE_ATTR(get_icons , _M444, get_icons , NULL );
+static DEVICE_ATTR(show_icon , _M220, NULL , show_icon );
+static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon );
+static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone);
+
+static struct attribute *yld_attributes[] = {
+ &dev_attr_line1.attr,
+ &dev_attr_line2.attr,
+ &dev_attr_line3.attr,
+ &dev_attr_get_icons.attr,
+ &dev_attr_show_icon.attr,
+ &dev_attr_hide_icon.attr,
+ &dev_attr_map_seg7.attr,
+ &dev_attr_ringtone.attr,
+ NULL
+};
+
+static struct attribute_group yld_attr_group = {
+ .attrs = yld_attributes
+};
+
+/*******************************************************************************
+ * Linux interface and usb initialisation
+ ******************************************************************************/
+
+static const struct yld_device {
+ u16 idVendor;
+ u16 idProduct;
+ char *name;
+} yld_device[] = {
+ { 0x6993, 0xb001, "Yealink usb-p1k" },
+};
+
+static struct usb_device_id usb_table [] = {
+ { USB_INTERFACE_INFO(USB_CLASS_HID, 0, 0) },
+ { }
+};
+
+static int usb_cleanup(struct yealink_dev *yld, int err)
+{
+ if (yld == NULL)
+ return err;
+
+ if (yld->urb_irq) {
+ usb_kill_urb(yld->urb_irq);
+ usb_free_urb(yld->urb_irq);
+ }
+ if (yld->urb_ctl)
+ usb_free_urb(yld->urb_ctl);
+ if (yld->idev) {
+ if (err)
+ input_free_device(yld->idev);
+ else
+ input_unregister_device(yld->idev);
+ }
+ if (yld->ctl_req)
+ usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
+ yld->ctl_req, yld->ctl_req_dma);
+ if (yld->ctl_data)
+ usb_buffer_free(yld->udev, USB_PKT_LEN,
+ yld->ctl_data, yld->ctl_dma);
+ if (yld->irq_data)
+ usb_buffer_free(yld->udev, USB_PKT_LEN,
+ yld->irq_data, yld->irq_dma);
+ kfree(yld);
+ return err;
+}
+
+static void usb_disconnect(struct usb_interface *intf)
+{
+ struct yealink_dev *yld;
+
+ down_write(&sysfs_rwsema);
+ yld = usb_get_intfdata(intf);
+ sysfs_remove_group(&intf->dev.kobj, &yld_attr_group);
+ usb_set_intfdata(intf, NULL);
+ up_write(&sysfs_rwsema);
+
+ usb_cleanup(yld, 0);
+}
+
+static int usb_match(struct usb_device *udev)
+{
+ int i;
+ u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
+ u16 idProduct = le16_to_cpu(udev->descriptor.idProduct);
+
+ for (i = 0; i < ARRAY_SIZE(yld_device); i++) {
+ if ((idVendor == yld_device[i].idVendor) &&
+ (idProduct == yld_device[i].idProduct))
+ return i;
+ }
+ return -ENODEV;
+}
+
+static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev (intf);
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct yealink_dev *yld;
+ struct input_dev *input_dev;
+ int ret, pipe, i;
+
+ i = usb_match(udev);
+ if (i < 0)
+ return -ENODEV;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
+ return -EIO;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ return -EIO;
+
+ yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
+ if (!yld)
+ return -ENOMEM;
+
+ yld->udev = udev;
+
+ yld->idev = input_dev = input_allocate_device();
+ if (!input_dev)
+ return usb_cleanup(yld, -ENOMEM);
+
+ /* allocate usb buffers */
+ yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ SLAB_ATOMIC, &yld->irq_dma);
+ if (yld->irq_data == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+ SLAB_ATOMIC, &yld->ctl_dma);
+ if (!yld->ctl_data)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
+ SLAB_ATOMIC, &yld->ctl_req_dma);
+ if (yld->ctl_req == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ /* allocate urb structures */
+ yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (yld->urb_irq == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
+ if (yld->urb_ctl == NULL)
+ return usb_cleanup(yld, -ENOMEM);
+
+ /* 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(yld->urb_irq, udev, pipe, yld->irq_data,
+ USB_PKT_LEN,
+ urb_irq_callback,
+ yld, endpoint->bInterval);
+ yld->urb_irq->transfer_dma = yld->irq_dma;
+ yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ yld->urb_irq->dev = udev;
+
+ /* initialise ctl urb */
+ yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
+ USB_DIR_OUT;
+ yld->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION;
+ yld->ctl_req->wValue = cpu_to_le16(0x200);
+ yld->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
+ yld->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN);
+
+ usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+ (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
+ urb_ctl_callback, yld);
+ yld->urb_ctl->setup_dma = yld->ctl_req_dma;
+ yld->urb_ctl->transfer_dma = yld->ctl_dma;
+ yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
+ URB_NO_TRANSFER_DMA_MAP;
+ yld->urb_ctl->dev = udev;
+
+ /* find out the physical bus location */
+ usb_make_path(udev, yld->phys, sizeof(yld->phys));
+ strlcat(yld->phys, "/input0", sizeof(yld->phys));
+
+ /* register settings for the input device */
+ input_dev->name = yld_device[i].name;
+ input_dev->phys = yld->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+
+ input_dev->private = yld;
+ input_dev->open = input_open;
+ input_dev->close = input_close;
+ /* input_dev->event = input_ev; TODO */
+
+ /* register available key events */
+ input_dev->evbit[0] = BIT(EV_KEY);
+ for (i = 0; i < 256; i++) {
+ int k = map_p1k_to_key(i);
+ if (k >= 0) {
+ set_bit(k & 0xff, input_dev->keybit);
+ if (k >> 8)
+ set_bit(k >> 8, input_dev->keybit);
+ }
+ }
+
+ input_register_device(yld->idev);
+
+ usb_set_intfdata(intf, yld);
+
+ /* clear visible elements */
+ for (i = 0; i < ARRAY_SIZE(lcdMap); i++)
+ setChar(yld, i, ' ');
+
+ /* display driver version on LCD line 3 */
+ store_line3(&intf->dev, NULL,
+ DRIVER_VERSION, sizeof(DRIVER_VERSION));
+
+ /* Register sysfs hooks (don't care about failure) */
+ sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
+ return 0;
+}
+
+static struct usb_driver yealink_driver = {
+ .owner = THIS_MODULE,
+ .name = "yealink",
+ .probe = usb_probe,
+ .disconnect = usb_disconnect,
+ .id_table = usb_table,
+};
+
+static int __init yealink_dev_init(void)
+{
+ int ret = usb_register(&yealink_driver);
+ if (ret == 0)
+ info(DRIVER_DESC ":" DRIVER_VERSION);
+ return ret;
+}
+
+static void __exit yealink_dev_exit(void)
+{
+ usb_deregister(&yealink_driver);
+}
+
+module_init(yealink_dev_init);
+module_exit(yealink_dev_exit);
+
+MODULE_DEVICE_TABLE (usb, usb_table);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/yealink.h b/drivers/usb/input/yealink.h
new file mode 100644
index 000000000000..48af0be9cbdf
--- /dev/null
+++ b/drivers/usb/input/yealink.h
@@ -0,0 +1,220 @@
+/*
+ * drivers/usb/input/yealink.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 INPUT_YEALINK_H
+#define INPUT_YEALINK_H
+
+/* Using the control channel on interface 3 various aspects of the phone
+ * can be controlled like LCD, LED, dialtone and the ringtone.
+ */
+
+struct yld_ctl_packet {
+ u8 cmd; /* command code, see below */
+ u8 size; /* 1-11, size of used data bytes. */
+ u16 offset; /* internal packet offset */
+ u8 data[11];
+ s8 sum; /* negative sum of 15 preceding bytes */
+} __attribute__ ((packed));
+
+#define USB_PKT_LEN sizeof(struct yld_ctl_packet)
+
+/* The following yld_ctl_packet's are available: */
+
+/* Init registers
+ *
+ * cmd 0x8e
+ * size 10
+ * offset 0
+ * data 0,0,0,0....
+ */
+#define CMD_INIT 0x8e
+
+/* Request key scan
+ *
+ * cmd 0x80
+ * size 1
+ * offset 0
+ * data[0] on return returns the key number, if it changes there's a new
+ * key pressed.
+ */
+#define CMD_KEYPRESS 0x80
+
+/* Request scancode
+ *
+ * cmd 0x81
+ * size 1
+ * offset key number [0-1f]
+ * data[0] on return returns the scancode
+ */
+#define CMD_SCANCODE 0x81
+
+/* Set LCD
+ *
+ * cmd 0x04
+ * size 1-11
+ * offset 0-23
+ * data segment bits
+ */
+#define CMD_LCD 0x04
+
+/* Set led
+ *
+ * cmd 0x05
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 1 ON
+ */
+#define CMD_LED 0x05
+
+/* Set ringtone volume
+ *
+ * cmd 0x11
+ * size 1
+ * offset 0
+ * data[0] 0-0xff volume
+ */
+#define CMD_RING_VOLUME 0x11
+
+/* Set ringtone notes
+ *
+ * cmd 0x02
+ * size 1-11
+ * offset 0->
+ * data binary representation LE16(-freq), LE16(duration) ....
+ */
+#define CMD_RING_NOTE 0x02
+
+/* Sound ringtone via the speaker on the back
+ *
+ * cmd 0x03
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 0x24 ON
+ */
+#define CMD_RINGTONE 0x03
+
+/* Sound dial tone via the ear speaker
+ *
+ * cmd 0x09
+ * size 1
+ * offset 0
+ * data[0] 0 OFF / 1 ON
+ */
+#define CMD_DIALTONE 0x09
+
+#endif /* INPUT_YEALINK_H */
+
+
+#if defined(_SEG) && defined(_PIC)
+/* This table maps the LCD segments onto individual bit positions in the
+ * yld_status struct.
+ */
+
+/* LCD, each segment must be driven seperately.
+ *
+ * Layout:
+ *
+ * |[] [][] [][] [][] in |[][]
+ * |[] M [][] D [][] : [][] out |[][]
+ * store
+ *
+ * NEW REP SU MO TU WE TH FR SA
+ *
+ * [] [] [] [] [] [] [] [] [] [] [] []
+ * [] [] [] [] [] [] [] [] [] [] [] []
+ */
+
+/* Line 1
+ * Format : 18.e8.M8.88...188
+ * Icon names : M D : IN OUT STORE
+ */
+#define LCD_LINE1_OFFSET 0
+#define LCD_LINE1_SIZE 17
+
+/* Note: first g then f => ! ! */
+/* _SEG( type a b c d e g f ) */
+ _SEG('1', 0,0 , 22,2 , 22,2 , 0,0 , 0,0 , 0,0 , 0,0 ),
+ _SEG('8', 20,1 , 20,2 , 20,4 , 20,8 , 21,4 , 21,2 , 21,1 ),
+ _PIC('.', 22,1 , "M" ),
+ _SEG('e', 18,1 , 18,2 , 18,4 , 18,1 , 19,2 , 18,1 , 19,1 ),
+ _SEG('8', 16,1 , 16,2 , 16,4 , 16,8 , 17,4 , 17,2 , 17,1 ),
+ _PIC('.', 15,8 , "D" ),
+ _SEG('M', 14,1 , 14,2 , 14,4 , 14,1 , 15,4 , 15,2 , 15,1 ),
+ _SEG('8', 12,1 , 12,2 , 12,4 , 12,8 , 13,4 , 13,2 , 13,1 ),
+ _PIC('.', 11,8 , ":" ),
+ _SEG('8', 10,1 , 10,2 , 10,4 , 10,8 , 11,4 , 11,2 , 11,1 ),
+ _SEG('8', 8,1 , 8,2 , 8,4 , 8,8 , 9,4 , 9,2 , 9,1 ),
+ _PIC('.', 7,1 , "IN" ),
+ _PIC('.', 7,2 , "OUT" ),
+ _PIC('.', 7,4 , "STORE" ),
+ _SEG('1', 0,0 , 5,1 , 5,1 , 0,0 , 0,0 , 0,0 , 0,0 ),
+ _SEG('8', 4,1 , 4,2 , 4,4 , 4,8 , 5,8 , 5,4 , 5,2 ),
+ _SEG('8', 2,1 , 2,2 , 2,4 , 2,8 , 3,4 , 3,2 , 3,1 ),
+
+/* Line 2
+ * Format : .........
+ * Pict. name : NEW REP SU MO TU WE TH FR SA
+ */
+#define LCD_LINE2_OFFSET LCD_LINE1_OFFSET + LCD_LINE1_SIZE
+#define LCD_LINE2_SIZE 9
+
+ _PIC('.', 23,2 , "NEW" ),
+ _PIC('.', 23,4 , "REP" ),
+ _PIC('.', 1,8 , "SU" ),
+ _PIC('.', 1,4 , "MO" ),
+ _PIC('.', 1,2 , "TU" ),
+ _PIC('.', 1,1 , "WE" ),
+ _PIC('.', 0,1 , "TH" ),
+ _PIC('.', 0,2 , "FR" ),
+ _PIC('.', 0,4 , "SA" ),
+
+/* Line 3
+ * Format : 888888888888
+ */
+#define LCD_LINE3_OFFSET LCD_LINE2_OFFSET + LCD_LINE2_SIZE
+#define LCD_LINE3_SIZE 12
+
+ _SEG('8', 22,16, 22,32, 22,64, 22,128, 23,128, 23,64, 23,32 ),
+ _SEG('8', 20,16, 20,32, 20,64, 20,128, 21,128, 21,64, 21,32 ),
+ _SEG('8', 18,16, 18,32, 18,64, 18,128, 19,128, 19,64, 19,32 ),
+ _SEG('8', 16,16, 16,32, 16,64, 16,128, 17,128, 17,64, 17,32 ),
+ _SEG('8', 14,16, 14,32, 14,64, 14,128, 15,128, 15,64, 15,32 ),
+ _SEG('8', 12,16, 12,32, 12,64, 12,128, 13,128, 13,64, 13,32 ),
+ _SEG('8', 10,16, 10,32, 10,64, 10,128, 11,128, 11,64, 11,32 ),
+ _SEG('8', 8,16, 8,32, 8,64, 8,128, 9,128, 9,64, 9,32 ),
+ _SEG('8', 6,16, 6,32, 6,64, 6,128, 7,128, 7,64, 7,32 ),
+ _SEG('8', 4,16, 4,32, 4,64, 4,128, 5,128, 5,64, 5,32 ),
+ _SEG('8', 2,16, 2,32, 2,64, 2,128, 3,128, 3,64, 3,32 ),
+ _SEG('8', 0,16, 0,32, 0,64, 0,128, 1,128, 1,64, 1,32 ),
+
+/* Line 4
+ *
+ * The LED, DIALTONE and RINGTONE are implemented as icons and use the same
+ * sysfs interface.
+ */
+#define LCD_LINE4_OFFSET LCD_LINE3_OFFSET + LCD_LINE3_SIZE
+
+ _PIC('.', offsetof(struct yld_status, led) , 0x01, "LED" ),
+ _PIC('.', offsetof(struct yld_status, dialtone) , 0x01, "DIALTONE" ),
+ _PIC('.', offsetof(struct yld_status, ringtone) , 0x24, "RINGTONE" ),
+
+#undef _SEG
+#undef _PIC
+#endif /* _SEG && _PIC */
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 6ca2fae99d2d..27b23c55bbc7 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -707,9 +707,8 @@ static struct file_operations dabusb_fops =
};
static struct usb_class_driver dabusb_class = {
- .name = "usb/dabusb%d",
+ .name = "dabusb%d",
.fops = &dabusb_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = DABUSB_MINOR,
};
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 20ac9e1069d4..9fe2c2710d13 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -119,7 +119,7 @@ struct konicawc {
int yplanesz; /* Number of bytes in the Y plane */
unsigned int buttonsts:1;
#ifdef CONFIG_INPUT
- struct input_dev input;
+ struct input_dev *input;
char input_physname[64];
#endif
};
@@ -218,6 +218,57 @@ static void konicawc_adjust_picture(struct uvd *uvd)
konicawc_camera_on(uvd);
}
+#ifdef CONFIG_INPUT
+
+static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
+{
+ struct input_dev *input_dev;
+
+ usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+ strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+ cam->input = input_dev = input_allocate_device();
+ if (!input_dev) {
+ warn("Not enough memory for camera's input device\n");
+ return;
+ }
+
+ input_dev->name = "Konicawc snapshot button";
+ input_dev->phys = cam->input_physname;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->cdev.dev = &dev->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+ input_dev->private = cam;
+
+ input_register_device(cam->input);
+}
+
+static void konicawc_unregister_input(struct konicawc *cam)
+{
+ if (cam->input) {
+ input_unregister_device(cam->input);
+ cam->input = NULL;
+ }
+}
+
+static void konicawc_report_buttonstat(struct konicawc *cam)
+{
+ if (cam->input) {
+ input_report_key(cam->input, BTN_0, cam->buttonsts);
+ input_sync(cam->input);
+ }
+}
+
+#else
+
+static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }
+static inline void konicawc_unregister_input(struct konicawc *cam) { }
+static inline void konicawc_report_buttonstat(struct konicawc *cam) { }
+
+#endif /* CONFIG_INPUT */
static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb)
{
@@ -273,10 +324,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
if(button != cam->buttonsts) {
DEBUG(2, "button: %sclicked", button ? "" : "un");
cam->buttonsts = button;
-#ifdef CONFIG_INPUT
- input_report_key(&cam->input, BTN_0, cam->buttonsts);
- input_sync(&cam->input);
-#endif
+ konicawc_report_buttonstat(cam);
}
if(sts == 0x01) { /* drop frame */
@@ -645,9 +693,9 @@ static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw)
RingQueue_Flush(&uvd->dp);
cam->lastframe = -2;
if(uvd->curframe != -1) {
- uvd->frame[uvd->curframe].curline = 0;
- uvd->frame[uvd->curframe].seqRead_Length = 0;
- uvd->frame[uvd->curframe].seqRead_Index = 0;
+ uvd->frame[uvd->curframe].curline = 0;
+ uvd->frame[uvd->curframe].seqRead_Length = 0;
+ uvd->frame[uvd->curframe].seqRead_Index = 0;
}
konicawc_start_data(uvd);
@@ -718,7 +766,6 @@ static void konicawc_configure_video(struct uvd *uvd)
DEBUG(1, "setting initial values");
}
-
static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -839,21 +886,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
err("usbvideo_RegisterVideoDevice() failed.");
uvd = NULL;
}
-#ifdef CONFIG_INPUT
- /* Register input device for button */
- memset(&cam->input, 0, sizeof(struct input_dev));
- cam->input.name = "Konicawc snapshot button";
- cam->input.private = cam;
- cam->input.evbit[0] = BIT(EV_KEY);
- cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
- usb_to_input_id(dev, &cam->input.id);
- input_register_device(&cam->input);
-
- usb_make_path(dev, cam->input_physname, 56);
- strcat(cam->input_physname, "/input0");
- cam->input.phys = cam->input_physname;
- info("konicawc: %s on %s\n", cam->input.name, cam->input.phys);
-#endif
+
+ konicawc_register_input(cam, dev);
}
if (uvd) {
@@ -869,10 +903,9 @@ static void konicawc_free_uvd(struct uvd *uvd)
int i;
struct konicawc *cam = (struct konicawc *)uvd->user_data;
-#ifdef CONFIG_INPUT
- input_unregister_device(&cam->input);
-#endif
- for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ konicawc_unregister_input(cam);
+
+ for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
usb_free_urb(cam->sts_urb[i]);
cam->sts_urb[i] = NULL;
}
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 7398a7f19c1e..0fd0fa9fec21 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -260,7 +260,7 @@ static int stv_stop_video (struct usb_stv *dev)
PDEBUG (0, "STV(i): Camera set to original resolution");
}
/* origMode */
- kfree (buf);
+ kfree(buf);
return i;
}
@@ -276,7 +276,7 @@ static int stv_set_video_mode (struct usb_stv *dev)
}
if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
- kfree (buf);
+ kfree(buf);
return i;
}
@@ -301,13 +301,13 @@ static int stv_set_video_mode (struct usb_stv *dev)
goto exit;
error:
- kfree (buf);
+ kfree(buf);
if (stop_video == 1)
stv_stop_video (dev);
return -1;
exit:
- kfree (buf);
+ kfree(buf);
return 0;
}
@@ -327,7 +327,7 @@ static int stv_init (struct usb_stv *stv680)
/* set config 1, interface 0, alternate 0 */
if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
- kfree (buffer);
+ kfree(buffer);
PDEBUG (0, "STV(e): set config 1,0,0 failed");
return -1;
}
@@ -435,11 +435,11 @@ static int stv_init (struct usb_stv *stv680)
error:
i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */
PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]);
- kfree (buffer);
+ kfree(buffer);
return -1;
exit:
- kfree (buffer);
+ kfree(buffer);
/* video = 320x240, 352x288 */
if (stv680->CIF == 1) {
@@ -708,10 +708,10 @@ static int stv680_stop_stream (struct usb_stv *stv680)
usb_kill_urb (stv680->urb[i]);
usb_free_urb (stv680->urb[i]);
stv680->urb[i] = NULL;
- kfree (stv680->sbuf[i].data);
+ kfree(stv680->sbuf[i].data);
}
for (i = 0; i < STV680_NUMSCRATCH; i++) {
- kfree (stv680->scratch[i].data);
+ kfree(stv680->scratch[i].data);
stv680->scratch[i].data = NULL;
}
@@ -1068,7 +1068,7 @@ static int stv_close (struct inode *inode, struct file *file)
stv680->user = 0;
if (stv680->removed) {
- kfree (stv680);
+ kfree(stv680);
stv680 = NULL;
PDEBUG (0, "STV(i): device unregistered");
}
@@ -1445,14 +1445,14 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
usb_kill_urb (stv680->urb[i]);
usb_free_urb (stv680->urb[i]);
stv680->urb[i] = NULL;
- kfree (stv680->sbuf[i].data);
+ kfree(stv680->sbuf[i].data);
}
for (i = 0; i < STV680_NUMSCRATCH; i++)
- kfree (stv680->scratch[i].data);
+ kfree(stv680->scratch[i].data);
PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
/* Free the memory */
- kfree (stv680);
+ kfree(stv680);
}
static void stv680_disconnect (struct usb_interface *intf)
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 4a5857c53f11..0bc0b1247a6b 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1148,7 +1148,7 @@ vicam_write_proc_gain(struct file *file, const char *buffer,
static void
vicam_create_proc_root(void)
{
- vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
+ vicam_proc_root = proc_mkdir("video/vicam", NULL);
if (vicam_proc_root)
vicam_proc_root->owner = THIS_MODULE;
@@ -1181,7 +1181,7 @@ vicam_create_proc_entry(struct vicam_camera *cam)
sprintf(name, "video%d", cam->vdev.minor);
- cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
+ cam->proc_dir = proc_mkdir(name, vicam_proc_root);
if ( !cam->proc_dir )
return; // FIXME: We should probably return an error here
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index ca9f3a30634f..f36c0b6c6e36 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1523,7 +1523,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap)
static int w9968cf_i2c_attach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
int id = client->driver->id, err = 0;
if (id == I2C_DRIVERID_OVCAMCHIP) {
@@ -1535,12 +1534,12 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
}
} else {
DBG(4, "Rejected client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->name)
return -EINVAL;
}
DBG(5, "I2C attach client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->name)
return 0;
}
@@ -1549,12 +1548,11 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
static int w9968cf_i2c_detach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
if (cam->sensor_client == client)
cam->sensor_client = NULL;
- DBG(5, "I2C detach client [%s]", clientname)
+ DBG(5, "I2C detach client [%s]", client->name)
return 0;
}
@@ -1573,15 +1571,13 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
int err = 0;
static struct i2c_algorithm algo = {
- .name = "W996[87]CF algorithm",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = w9968cf_i2c_smbus_xfer,
.algo_control = w9968cf_i2c_control,
.functionality = w9968cf_i2c_func,
};
static struct i2c_adapter adap = {
- .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
+ .id = I2C_HW_SMBUS_W9968CF,
.class = I2C_CLASS_CAM_DIGITAL,
.owner = THIS_MODULE,
.client_register = w9968cf_i2c_attach_inform,
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 6f7994f5a714..5f33f7c64885 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -426,7 +426,7 @@ static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
/* cancel an urb which is submitted to the chain
the result is 0 if the urb is cancelled, or -EINPROGRESS if
- URB_ASYNC_UNLINK is set and the function is successfully started.
+ the function is successfully started.
*/
static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
{
@@ -515,7 +515,6 @@ static void auerchain_unlink_all (pauerchain_t acp)
acep = acp->active;
if (acep) {
urbp = acep->urbp;
- urbp->transfer_flags &= ~URB_ASYNC_UNLINK;
dbg ("unlink active urb");
usb_kill_urb (urbp);
}
@@ -1874,9 +1873,8 @@ static struct file_operations auerswald_fops =
};
static struct usb_class_driver auerswald_class = {
- .name = "usb/auer%d",
+ .name = "auer%d",
.fops = &auerswald_fops,
- .mode = S_IFCHR | S_IRUGO | S_IWUGO,
.minor_base = AUER_MINOR_BASE,
};
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 733acc213726..1dc3e0f73014 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -105,11 +105,10 @@ static struct file_operations idmouse_fops = {
.release = idmouse_release,
};
-/* class driver information for devfs */
+/* class driver information */
static struct usb_class_driver idmouse_class = {
- .name = "usb/idmouse%d",
+ .name = "idmouse%d",
.fops = &idmouse_fops,
- .mode = S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, /* filemode (char, 444) */
.minor_base = USB_IDMOUSE_MINOR_BASE,
};
@@ -320,20 +319,8 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
return -ENODEV;
}
- if (*ppos >= IMGSIZE) {
- up (&dev->sem);
- return 0;
- }
-
- count = min ((loff_t)count, IMGSIZE - (*ppos));
-
- if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) {
- result = -EFAULT;
- } else {
- result = count;
- *ppos += count;
- }
-
+ result = simple_read_from_buffer(buffer, count, ppos,
+ dev->bulk_in_buffer, IMGSIZE);
/* unlock the device */
up(&dev->sem);
return result;
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index ad17892aac9e..7e93ac96490f 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -464,7 +464,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
bytes_to_read = min(count, *actual_buffer);
if (bytes_to_read < *actual_buffer)
- dev_warn(&dev->intf->dev, "Read buffer overflow, %d bytes dropped\n",
+ dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
*actual_buffer-bytes_to_read);
/* copy one interrupt_in_buffer from ring_buffer into userspace */
@@ -528,8 +528,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
/* write the data into interrupt_out_buffer from userspace */
bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
if (bytes_to_write < count)
- dev_warn(&dev->intf->dev, "Write buffer overflow, %d bytes dropped\n",count-bytes_to_write);
- dbg_info(&dev->intf->dev, "%s: count = %d, bytes_to_write = %d\n", __FUNCTION__, count, bytes_to_write);
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
retval = -EFAULT;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 7d06105763d4..2703e205bc8f 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -271,12 +271,11 @@ static struct file_operations tower_fops = {
/*
* usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
*/
static struct usb_class_driver tower_class = {
- .name = "usb/legousbtower%d",
+ .name = "legousbtower%d",
.fops = &tower_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
.minor_base = LEGO_USB_TOWER_MINOR_BASE,
};
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 26f77e29c7a6..7d02d8ec6b1a 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -443,9 +443,8 @@ file_operations usb_rio_fops = {
};
static struct usb_class_driver usb_rio_class = {
- .name = "usb/rio500%d",
+ .name = "rio500%d",
.fops = &usb_rio_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = RIO_MINOR,
};
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e144caf7..7603cbe0865d 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -4,11 +4,43 @@ config USB_SISUSBVGA
depends on USB && USB_EHCI_HCD
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
- Net2280 and a SiS315 chip.
-
- Note that this device requires a USB 2.0 host controller. It will not
+ Net2280 and a SiS315 chip.
+
+ Note that this device requires a USB 2.0 host controller. It will not
work with USB 1.x controllers.
- To compile this driver as a module, choose M here: the module will be
- called sisusb. If unsure, say N.
+ To compile this driver as a module, choose M here; the module will be
+ called sisusbvga. If unsure, say N.
+
+config USB_SISUSBVGA_CON
+ bool "Text console and mode switching support" if USB_SISUSBVGA
+ depends on VT
+ select FONT_8x16
+ ---help---
+ Say Y here if you want a VGA text console via the USB dongle or
+ want to support userland applications that utilize the driver's
+ display mode switching capabilities.
+
+ Note that this console supports VGA/EGA text mode only.
+
+ By default, the console part of the driver will not kick in when
+ the driver is initialized. If you want the driver to take over
+ one or more of the consoles, you need to specify the number of
+ the first and last consoles (starting at 1) as driver parameters.
+
+ For example, if the driver is compiled as a module:
+
+ modprobe sisusbvga first=1 last=5
+
+ If you use hotplug, add this to your modutils config files with
+ the "options" keyword, such as eg.
+
+ options sisusbvga first=1 last=5
+
+ If the driver is compiled into the kernel image, the parameters
+ must be given in the kernel command like, such as
+
+ sisusbvga.first=1 sisusbvga.last=5
+
+
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643ceaf8..7f934cfc906c 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,7 @@
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
+
+sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 2fd12264fd53..c946c9a538a0 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
+ * Main part
+ *
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
#include <linux/kref.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
#include "sisusb.h"
+#ifdef INCL_SISUSB_CON
+#include <linux/font.h>
+#endif
+
#define SISUSB_DONTSYNC
/* Forward declarations / clean-up routines */
+#ifdef INCL_SISUSB_CON
+int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
+int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
+int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
+int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
+int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
+
+int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written);
+
+int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern void sisusb_init_concode(void);
+extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+
+extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+
+extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ u8 *arg, int cmapsz, int ch512, int dorecalc,
+ struct vc_data *c, int fh, int uplock);
+
+static int sisusb_first_vc = 0;
+static int sisusb_last_vc = 0;
+module_param_named(first, sisusb_first_vc, int, 0);
+module_param_named(last, sisusb_last_vc, int, 0);
+MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
+MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
+#endif
+
static struct usb_driver sisusb_driver;
-static DECLARE_MUTEX(disconnect_sem);
+DECLARE_MUTEX(disconnect_sem);
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -229,7 +275,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completeout, &sisusb->urbout_context[index]);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
if ((urb->transfer_dma = transfer_dma))
@@ -295,7 +341,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
sisusb_bulk_completein, sisusb);
- urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->transfer_flags |= tflags;
urb->actual_length = 0;
if ((urb->transfer_dma = transfer_dma))
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
/* The following routines assume being used to transfer byte, word,
* long etc.
- * This means that they assume "data" in machine endianness format.
+ * This means that
+ * - the write routines expect "data" in machine endianness format.
+ * The data will be converted to leXX in sisusb_xxx_packet.
+ * - the read routines can expect read data in machine-endianess.
*/
static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap16, (u16 __user *)userbuffer))
return -EFAULT;
} else
- swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+ swap16 = *((u16 *)kernbuffer);
ret = sisusb_write_memio_word(sisusb,
SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (userbuffer) {
if (copy_from_user(&buf, userbuffer, 3))
return -EFAULT;
-
+#ifdef __BIG_ENDIAN
swap32 = (buf[0] << 16) |
(buf[1] << 8) |
buf[2];
+#else
+ swap32 = (buf[2] << 16) |
+ (buf[1] << 8) |
+ buf[0];
+#endif
} else
+#ifdef __BIG_ENDIAN
swap32 = (kernbuffer[0] << 16) |
(kernbuffer[1] << 8) |
kernbuffer[2];
+#else
+ swap32 = (kernbuffer[2] << 16) |
+ (kernbuffer[1] << 8) |
+ kernbuffer[0];
+#endif
ret = sisusb_write_memio_24bit(sisusb,
SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if (get_user(swap32, (u32 __user *)userbuffer))
return -EFAULT;
} else
- swap32 = (kernbuffer[0] << 24) |
- (kernbuffer[1] << 16) |
- (kernbuffer[2] << 8) |
- kernbuffer[3];
+ swap32 = *((u32 *)kernbuffer);
ret = sisusb_write_memio_long(sisusb,
SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
return ret ? -EIO : 0;
}
+/* Remember: Read data in packet is in machine-endianess! So for
+ * byte, word, 24bit, long no endian correction is necessary.
+ */
+
static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
u32 addr, u8 *data)
{
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
(u16 __user *)userbuffer))
return -EFAULT;
} else {
- kernbuffer[0] = swap16 >> 8;
- kernbuffer[1] = swap16 & 0xff;
+ *((u16 *)kernbuffer) = swap16;
}
}
return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
addr, &swap32);
if (!ret) {
(*bytes_read) += 3;
+#ifdef __BIG_ENDIAN
buf[0] = (swap32 >> 16) & 0xff;
buf[1] = (swap32 >> 8) & 0xff;
buf[2] = swap32 & 0xff;
+#else
+ buf[2] = (swap32 >> 16) & 0xff;
+ buf[1] = (swap32 >> 8) & 0xff;
+ buf[0] = swap32 & 0xff;
+#endif
if (userbuffer) {
if (copy_to_user(userbuffer, &buf[0], 3))
return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
userbuffer += 4;
} else {
- kernbuffer[0] = (swap32 >> 24) & 0xff;
- kernbuffer[1] = (swap32 >> 16) & 0xff;
- kernbuffer[2] = (swap32 >> 8) & 0xff;
- kernbuffer[3] = swap32 & 0xff;
+ *((u32 *)kernbuffer) = swap32;
kernbuffer += 4;
}
addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
/* High level: Gfx (indexed) register access */
-static int
+#ifdef INCL_SISUSB_CON
+int
+sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
+{
+ return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+
+int
+sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
+{
+ return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+#endif
+
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
{
int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
{
int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
u8 myand, u8 myor)
{
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
return ret;
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
{
return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
}
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
{
return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
}
+/* Write/read video ram */
+
+#ifdef INCL_SISUSB_CON
+int
+sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
+{
+ return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
+{
+ return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
+{
+ return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
+{
+ return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written)
+{
+ return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
+}
+
+#ifdef SISUSBENDIANTEST
+int
+sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
+ u32 src, int length, size_t *bytes_written)
+{
+ return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
+}
+#endif
+#endif
+
+#ifdef SISUSBENDIANTEST
+static void
+sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
+{
+ static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+ char destbuffer[10];
+ size_t dummy;
+ int i,j;
+
+ sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
+
+ for(i = 1; i <= 7; i++) {
+ printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
+ sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
+ for(j = 0; j < i; j++) {
+ printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
+ }
+ }
+}
+#endif
+
/* access pci config registers (reg numbers 0, 4, 8, etc) */
static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
return ret;
}
+
+#ifdef INCL_SISUSB_CON
+
+/* Set up default text mode:
+ - Set text mode (0x03)
+ - Upload default font
+ - Upload user font (if available)
+*/
+
+int
+sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
+{
+ int ret = 0, slot = sisusb->font_slot, i;
+ const struct font_desc *myfont;
+ u8 *tempbuf;
+ u16 *tempbufb;
+ size_t written;
+ static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+ static char bootlogo[] = "(o_ //\\ V_/_";
+
+ /* sisusb->lock is down */
+
+ if (!sisusb->SiS_Pr)
+ return 1;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ /* Set mode 0x03 */
+ SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
+
+ if (!(myfont = find_font("VGA8x16")))
+ return 1;
+
+ if (!(tempbuf = vmalloc(8192)))
+ return 1;
+
+ for (i = 0; i < 256; i++)
+ memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
+
+ /* Upload default font */
+ ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
+
+ vfree(tempbuf);
+
+ /* Upload user font (and reset current slot) */
+ if (sisusb->font_backup) {
+ ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
+ 8192, sisusb->font_backup_512, 1, NULL,
+ sisusb->font_backup_height, 0);
+ if (slot != 2)
+ sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
+ NULL, 16, 0);
+ }
+
+ if (init && !sisusb->scrbuf) {
+
+ if ((tempbuf = vmalloc(8192))) {
+
+ i = 4096;
+ tempbufb = (u16 *)tempbuf;
+ while (i--)
+ *(tempbufb++) = 0x0720;
+
+ i = 0;
+ tempbufb = (u16 *)tempbuf;
+ while (bootlogo[i]) {
+ *(tempbufb++) = 0x0700 | bootlogo[i++];
+ if (!(i % 4))
+ tempbufb += 76;
+ }
+
+ i = 0;
+ tempbufb = (u16 *)tempbuf + 6;
+ while (bootstring[i])
+ *(tempbufb++) = 0x0700 | bootstring[i++];
+
+ ret |= sisusb_copy_memory(sisusb, tempbuf,
+ sisusb->vrambase, 8192, &written);
+
+ vfree(tempbuf);
+
+ }
+
+ } else if (sisusb->scrbuf) {
+
+ ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
+ sisusb->vrambase, sisusb->scrbuf_size, &written);
+
+ }
+
+ if (sisusb->sisusb_cursor_size_from >= 0 &&
+ sisusb->sisusb_cursor_size_to >= 0) {
+ sisusb_setidxreg(sisusb, SISCR, 0x0a,
+ sisusb->sisusb_cursor_size_from);
+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
+ sisusb->sisusb_cursor_size_to);
+ } else {
+ sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
+ sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
+ sisusb->sisusb_cursor_size_to = -1;
+ }
+
+ slot = sisusb->sisusb_cursor_loc;
+ if(slot < 0) slot = 0;
+
+ sisusb->sisusb_cursor_loc = -1;
+ sisusb->bad_cursor_pos = 1;
+
+ sisusb_set_cursor(sisusb, slot);
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+
+ sisusb->textmodedestroyed = 0;
+
+ /* sisusb->lock is down */
+
+ return ret;
+}
+
+#endif
+
/* fops */
static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
}
}
- /* increment usage count for the device */
+ /* Increment usage count for our sisusb */
kref_get(&sisusb->kref);
sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
up(&disconnect_sem);
- printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
-
return 0;
}
-static void
+void
sisusb_delete(struct kref *kref)
{
struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
sisusb->sisusb_dev = NULL;
sisusb_free_buffers(sisusb);
sisusb_free_urbs(sisusb);
+#ifdef INCL_SISUSB_CON
+ kfree(sisusb->SiS_Pr);
+#endif
kfree(sisusb);
}
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
up(&disconnect_sem);
- printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
-
return 0;
}
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
int retval, port, length;
u32 address;
+ /* All our commands require the device
+ * to be initialized.
+ */
+ if (!sisusb->devinit)
+ return -ENODEV;
+
port = y->data3 -
SISUSB_PCI_PSEUDO_IOPORTBASE +
SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
break;
case SUCMD_CLRSCR:
+ /* Gfx core must be initialized */
+ if (!sisusb->gfxinit)
+ return -ENODEV;
+
length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
address = y->data3 -
SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
retval = sisusb_clear_vram(sisusb, address, length);
break;
+ case SUCMD_HANDLETEXTMODE:
+ retval = 0;
+#ifdef INCL_SISUSB_CON
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ switch (y->data0) {
+ case 0:
+ retval = sisusb_reset_text_mode(sisusb, 0);
+ break;
+ case 1:
+ sisusb->textmodedestroyed = 1;
+ break;
+ }
+#endif
+ break;
+
+#ifdef INCL_SISUSB_CON
+ case SUCMD_SETMODE:
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ retval = 0;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
+ retval = -EINVAL;
+
+ break;
+
+ case SUCMD_SETVESAMODE:
+ /* Gfx core must be initialized, SiS_Pr must exist */
+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+ return -ENODEV;
+
+ retval = 0;
+
+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+ sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+ if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
+ retval = -EINVAL;
+
+ break;
+#endif
+
default:
retval = -EINVAL;
}
- if(retval > 0)
+ if (retval > 0)
retval = -EIO;
return retval;
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
x.sisusb_vramsize = sisusb->vramsize;
x.sisusb_minor = sisusb->minor;
x.sisusb_fbdevactive= 0;
+#ifdef INCL_SISUSB_CON
+ x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
+#else
+ x.sisusb_conactive = 0;
+#endif
if (copy_to_user((void __user *)arg, &x, sizeof(x)))
retval = -EFAULT;
@@ -2895,9 +3239,8 @@ static struct file_operations usb_sisusb_fops = {
};
static struct usb_class_driver usb_sisusb_class = {
- .name = "usb/sisusbvga%d",
+ .name = "sisusbvga%d",
.fops = &usb_sisusb_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = SISUSB_MINOR
};
@@ -2994,12 +3337,25 @@ static int sisusb_probe(struct usb_interface *intf,
printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
sisusb->minor, sisusb->numobufs);
+#ifdef INCL_SISUSB_CON
+ /* Allocate our SiS_Pr */
+ if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
+ sisusb->minor);
+ }
+#endif
+
/* Do remaining init stuff */
init_waitqueue_head(&sisusb->wait_q);
usb_set_intfdata(intf, sisusb);
+ usb_get_dev(sisusb->sisusb_dev);
+
+ sisusb->present = 1;
+
#ifdef SISUSB_OLD_CONFIG_COMPAT
{
int ret;
@@ -3014,14 +3370,19 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->minor);
else
sisusb->ioctl32registered = 1;
-
}
#endif
- sisusb->present = 1;
-
if (dev->speed == USB_SPEED_HIGH) {
- if (sisusb_init_gfxdevice(sisusb, 1))
+ int initscreen = 1;
+#ifdef INCL_SISUSB_CON
+ if (sisusb_first_vc > 0 &&
+ sisusb_last_vc > 0 &&
+ sisusb_first_vc <= sisusb_last_vc &&
+ sisusb_last_vc <= MAX_NR_CONSOLES)
+ initscreen = 0;
+#endif
+ if (sisusb_init_gfxdevice(sisusb, initscreen))
printk(KERN_ERR
"sisusbvga[%d]: Failed to early "
"initialize device\n",
@@ -3035,6 +3396,16 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb->ready = 1;
+#ifdef SISUSBENDIANTEST
+ printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
+ sisusb_testreadwrite(sisusb);
+ printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
+#endif
+
+#ifdef INCL_SISUSB_CON
+ sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
+#endif
+
return 0;
error_4:
@@ -3053,13 +3424,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
struct sisusb_usb_data *sisusb;
int minor;
- down(&disconnect_sem);
-
/* This should *not* happen */
- if (!(sisusb = usb_get_intfdata(intf))) {
- up(&disconnect_sem);
+ if (!(sisusb = usb_get_intfdata(intf)))
return;
- }
+
+#ifdef INCL_SISUSB_CON
+ sisusb_console_exit(sisusb);
+#endif
+
+ /* The above code doesn't need the disconnect
+ * semaphore to be down; its meaning is to
+ * protect all other routines from the disconnect
+ * case, not the other way round.
+ */
+ down(&disconnect_sem);
down(&sisusb->lock);
@@ -3123,11 +3501,17 @@ static int __init usb_sisusb_init(void)
{
int retval;
+#ifdef INCL_SISUSB_CON
+ sisusb_init_concode();
+#endif
+
if (!(retval = usb_register(&sisusb_driver))) {
+
printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
printk(KERN_INFO
"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+
}
return retval;
@@ -3142,6 +3526,6 @@ module_init(usb_sisusb_init);
module_exit(usb_sisusb_exit);
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
-MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d006a25a..401ff21d7881 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -46,15 +46,36 @@
#endif
#endif
+/* For older kernels, support for text consoles is by default
+ * off. To ensable text console support, change the following:
+ */
+#if 0
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+#define CONFIG_USB_SISUSBVGA_CON
+#endif
+#endif
+
/* Version Information */
#define SISUSB_VERSION 0
#define SISUSB_REVISION 0
-#define SISUSB_PATCHLEVEL 7
+#define SISUSB_PATCHLEVEL 8
+
+/* Include console and mode switching code? */
+
+#ifdef CONFIG_USB_SISUSBVGA_CON
+#define INCL_SISUSB_CON 1
+#endif
+
+#ifdef INCL_SISUSB_CON
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include "sisusb_struct.h"
+#endif
/* USB related */
-#define SISUSB_MINOR 133 /* FIXME */
+#define SISUSB_MINOR 133 /* official */
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE 0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
unsigned char gfxinit; /* graphics core initialized? */
unsigned short chipid, chipvendor;
unsigned short chiprevision;
+#ifdef INCL_SISUSB_CON
+ struct SiS_Private *SiS_Pr;
+ unsigned long scrbuf;
+ unsigned int scrbuf_size;
+ int haveconsole, con_first, con_last;
+ int havethisconsole[MAX_NR_CONSOLES];
+ int textmodedestroyed;
+ unsigned int sisusb_num_columns; /* real number, not vt's idea */
+ int cur_start_addr, con_rolled_over;
+ int sisusb_cursor_loc, bad_cursor_pos;
+ int sisusb_cursor_size_from;
+ int sisusb_cursor_size_to;
+ int current_font_height, current_font_512;
+ int font_backup_size, font_backup_height, font_backup_512;
+ char *font_backup;
+ int font_slot;
+ struct vc_data *sisusb_display_fg;
+ int is_gfx;
+ int con_blanked;
+#endif
};
#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {
__u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
- __u8 sisusb_reserved[32]; /* for future use */
+ __u32 sisusb_conactive; /* != 0 if console driver active */
+
+ __u8 sisusb_reserved[28]; /* for future use */
};
struct sisusb_command {
@@ -261,18 +304,24 @@ struct sisusb_command {
__u32 data4; /* for future use */
};
-#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
-#define SUCMD_SET 0x02 /* data1 = value */
-#define SUCMD_SETOR 0x03 /* data1 = or */
-#define SUCMD_SETAND 0x04 /* data1 = and */
-#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
-#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
+#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
+#define SUCMD_SET 0x02 /* data1 = value */
+#define SUCMD_SETOR 0x03 /* data1 = or */
+#define SUCMD_SETAND 0x04 /* data1 = and */
+#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
+#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
-#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
+#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
+
+#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
+
+#define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */
+#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */
#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
-#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
-#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+
#endif /* SISUSB_H */
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 000000000000..24584463553d
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1658 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * VGA text mode console part
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Portions based on vgacon.c which are
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * based on code Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ *
+ * A note on using in_atomic() in here: We can't handle console
+ * calls from non-schedulable context due to our USB-dependend
+ * nature. For now, this driver just ignores any calls if it
+ * detects this state.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/smp_lock.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
+extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
+extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
+extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
+
+extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+ u32 dest, int length, size_t *bytes_written);
+
+extern void sisusb_delete(struct kref *kref);
+extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+
+#define sisusbcon_writew(val, addr) (*(addr) = (val))
+#define sisusbcon_readw(addr) (*(addr))
+#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
+#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
+
+/* vc_data -> sisusb conversion table */
+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
+
+/* Forward declaration */
+static const struct consw sisusb_con;
+
+extern struct semaphore disconnect_sem;
+
+static inline void
+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ sisusbcon_writew(c, s++);
+}
+
+static inline void
+sisusb_initialize(struct sisusb_usb_data *sisusb)
+{
+ /* Reset cursor and start address */
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
+ return;
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
+}
+
+static inline void
+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
+{
+ sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+}
+
+void
+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
+{
+ if (sisusb->sisusb_cursor_loc == location)
+ return;
+
+ sisusb->sisusb_cursor_loc = location;
+
+ /* Hardware bug: Text cursor appears twice or not at all
+ * at some positions. Work around it with the cursor skew
+ * bits.
+ */
+
+ if ((location & 0x0007) == 0x0007) {
+ sisusb->bad_cursor_pos = 1;
+ location--;
+ if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
+ return;
+ } else if (sisusb->bad_cursor_pos) {
+ if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
+ return;
+ sisusb->bad_cursor_pos = 0;
+ }
+
+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
+ return;
+ sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
+}
+
+static inline struct sisusb_usb_data *
+sisusb_get_sisusb(unsigned short console)
+{
+ return mysisusbs[console];
+}
+
+static inline int
+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
+{
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
+ return 0;
+
+ return 1;
+}
+
+static struct sisusb_usb_data *
+sisusb_get_sisusb_lock_and_check(unsigned short console)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* We can't handle console calls in non-schedulable
+ * context due to our locks and the USB transport.
+ * So we simply ignore them. This should only affect
+ * some calls to printk.
+ */
+ if (in_atomic())
+ return NULL;
+
+ if (!(sisusb = sisusb_get_sisusb(console)))
+ return NULL;
+
+ down(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb) ||
+ !sisusb->havethisconsole[console]) {
+ up(&sisusb->lock);
+ return NULL;
+ }
+
+ return sisusb;
+}
+
+static int
+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
+{
+ if (sisusb->is_gfx ||
+ sisusb->textmodedestroyed ||
+ c->vc_mode != KD_TEXT)
+ return 1;
+
+ return 0;
+}
+
+/* con_startup console interface routine */
+static const char *
+sisusbcon_startup(void)
+{
+ return "SISUSBCON";
+}
+
+/* con_init console interface routine */
+static void
+sisusbcon_init(struct vc_data *c, int init)
+{
+ struct sisusb_usb_data *sisusb;
+ int cols, rows;
+
+ /* This is called by take_over_console(),
+ * ie by us/under our control. It is
+ * only called after text mode and fonts
+ * are set up/restored.
+ */
+
+ down(&disconnect_sem);
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+ up(&disconnect_sem);
+ return;
+ }
+
+ down(&sisusb->lock);
+
+ if (!sisusb_sisusb_valid(sisusb)) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return;
+ }
+
+ c->vc_can_do_color = 1;
+
+ c->vc_complement_mask = 0x7700;
+
+ c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
+
+ sisusb->haveconsole = 1;
+
+ sisusb->havethisconsole[c->vc_num] = 1;
+
+ /* We only support 640x400 */
+ c->vc_scan_lines = 400;
+
+ c->vc_font.height = sisusb->current_font_height;
+
+ /* We only support width = 8 */
+ cols = 80;
+ rows = c->vc_scan_lines / c->vc_font.height;
+
+ /* Increment usage count for our sisusb.
+ * Doing so saves us from upping/downing
+ * the disconnect semaphore; we can't
+ * lose our sisusb until this is undone
+ * in con_deinit. For all other console
+ * interface functions, it suffices to
+ * use sisusb->lock and do a quick check
+ * of sisusb for device disconnection.
+ */
+ kref_get(&sisusb->kref);
+
+ if (!*c->vc_uni_pagedir_loc)
+ con_set_default_unimap(c);
+
+ up(&sisusb->lock);
+
+ up(&disconnect_sem);
+
+ if (init) {
+ c->vc_cols = cols;
+ c->vc_rows = rows;
+ } else
+ vc_resize(c, cols, rows);
+}
+
+/* con_deinit console interface routine */
+static void
+sisusbcon_deinit(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int i;
+
+ /* This is called by take_over_console()
+ * and others, ie not under our control.
+ */
+
+ down(&disconnect_sem);
+
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+ up(&disconnect_sem);
+ return;
+ }
+
+ down(&sisusb->lock);
+
+ /* Clear ourselves in mysisusbs */
+ mysisusbs[c->vc_num] = NULL;
+
+ sisusb->havethisconsole[c->vc_num] = 0;
+
+ /* Free our font buffer if all consoles are gone */
+ if (sisusb->font_backup) {
+ for(i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (sisusb->havethisconsole[c->vc_num])
+ break;
+ }
+ if (i == MAX_NR_CONSOLES) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ up(&sisusb->lock);
+
+ /* decrement the usage count on our sisusb */
+ kref_put(&sisusb->kref, sisusb_delete);
+
+ up(&disconnect_sem);
+}
+
+/* interface routine */
+static u8
+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+ u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = color;
+
+ if (underline)
+ attr = (attr & 0xf0) | c->vc_ulcolor;
+ else if (intensity == 0)
+ attr = (attr & 0xf0) | c->vc_halfcolor;
+
+ if (reverse)
+ attr = ((attr) & 0x88) |
+ ((((attr) >> 4) |
+ ((attr) << 4)) & 0x77);
+
+ if (blink)
+ attr ^= 0x80;
+
+ if (intensity == 2)
+ attr ^= 0x08;
+
+ return attr;
+}
+
+/* Interface routine */
+static void
+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
+{
+ /* Invert a region. This is called with a pointer
+ * to the console's internal screen buffer. So we
+ * simply do the inversion there and rely on
+ * a call to putc(s) to update the real screen.
+ */
+
+ while (count--) {
+ u16 a = sisusbcon_readw(p);
+
+ a = ((a) & 0x88ff) |
+ (((a) & 0x7000) >> 4) |
+ (((a) & 0x0700) << 4);
+
+ sisusbcon_writew(a, p++);
+ }
+}
+
+#define SISUSB_VADDR(x,y) \
+ ((u16 *)c->vc_origin + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+#define SISUSB_HADDR(x,y) \
+ ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
+ (y) * sisusb->sisusb_num_columns + \
+ (x))
+
+/* Interface routine */
+static void
+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Don't need to put the character into buffer ourselves,
+ * because the vt does this BEFORE calling us.
+ */
+#if 0
+ sisusbcon_writew(ch, SISUSB_VADDR(x, y));
+#endif
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), 2, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
+ int count, int y, int x)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ u16 *dest;
+ int i;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to put the characters into the buffer ourselves,
+ * because the vt does this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ for (i = count; i > 0; i--)
+ sisusbcon_writew(sisusbcon_readw(s++), dest++);
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), count * 2, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int i, length, cols;
+ u16 *dest;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ /* Need to clear buffer ourselves, because the vt does
+ * this AFTER calling us.
+ */
+
+ dest = SISUSB_VADDR(x, y);
+
+ cols = sisusb->sisusb_num_columns;
+
+ if (width > cols)
+ width = cols;
+
+ if (x == 0 && width >= c->vc_cols) {
+
+ sisusbcon_memsetw(dest, eattr, height * cols * 2);
+
+ } else {
+
+ for (i = height; i > 0; i--, dest += cols)
+ sisusbcon_memsetw(dest, eattr, width * 2);
+
+ }
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - x - (cols - width - x)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
+ (u32)SISUSB_HADDR(x, y), length, &written);
+
+ up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_bmove(struct vc_data *c, int sy, int sx,
+ int dy, int dx, int height, int width)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int cols, length;
+#if 0
+ u16 *src, *dest;
+ int i;
+#endif
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ cols = sisusb->sisusb_num_columns;
+
+ /* Don't need to move data outselves, because
+ * vt does this BEFORE calling us.
+ * This is only used by vt's insert/deletechar.
+ */
+#if 0
+ if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
+
+ sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
+ height * width * 2);
+
+ } else if (dy < sy || (dy == sy && dx < sx)) {
+
+ src = SISUSB_VADDR(sx, sy);
+ dest = SISUSB_VADDR(dx, dy);
+
+ for (i = height; i > 0; i--) {
+ sisusbcon_memmovew(dest, src, width * 2);
+ src += cols;
+ dest += cols;
+ }
+
+ } else {
+
+ src = SISUSB_VADDR(sx, sy + height - 1);
+ dest = SISUSB_VADDR(dx, dy + height - 1);
+
+ for (i = height; i > 0; i--) {
+ sisusbcon_memmovew(dest, src, width * 2);
+ src -= cols;
+ dest -= cols;
+ }
+
+ }
+#endif
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ length = ((height * cols) - dx - (cols - width - dx)) * 2;
+
+
+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
+ (u32)SISUSB_HADDR(dx, dy), length, &written);
+
+ up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_switch(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t written;
+ int length;
+
+ /* Returnvalue 0 means we have fully restored screen,
+ * and vt doesn't need to call do_update_region().
+ * Returnvalue != 0 naturally means the opposite.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ /* Don't write to screen if in gfx mode */
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ /* That really should not happen. It would mean we are
+ * being called while the vc is using its private buffer
+ * as origin.
+ */
+ if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
+ up(&sisusb->lock);
+ printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
+ return 0;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Restore the screen contents */
+ sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
+ length);
+
+ sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
+ (u32)SISUSB_HADDR(0, 0),
+ length, &written);
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static void
+sisusbcon_save_screen(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+ int length;
+
+ /* Save the current screen contents to vc's private
+ * buffer.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ /* Check that we don't copy too much */
+ length = min((int)c->vc_screenbuf_size,
+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+ /* Save the screen contents to vc's private buffer */
+ sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
+ length);
+
+ up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ struct sisusb_usb_data *sisusb;
+ int i, j;
+
+ /* Return value not used by vt */
+
+ if (!CON_IS_VISIBLE(c))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -EINVAL;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ for (i = j = 0; i < 16; i++) {
+ if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+ break;
+ }
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/* interface routine */
+static int
+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
+{
+ struct sisusb_usb_data *sisusb;
+ u8 sr1, cr17, pmreg, cr63;
+ ssize_t written;
+ int ret = 0;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (mode_switch)
+ sisusb->is_gfx = blank ? 1 : 0;
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ switch (blank) {
+
+ case 1: /* Normal blanking: Clear screen */
+ case -1:
+ sisusbcon_memsetw((u16 *)c->vc_origin,
+ c->vc_video_erase_char,
+ c->vc_screenbuf_size);
+ sisusb_copy_memory(sisusb,
+ (unsigned char *)c->vc_origin,
+ (u32)(sisusb->vrambase +
+ (c->vc_origin - sisusb->scrbuf)),
+ c->vc_screenbuf_size, &written);
+ sisusb->con_blanked = 1;
+ ret = 1;
+ break;
+
+ default: /* VESA blanking */
+ switch (blank) {
+ case 0: /* Unblank */
+ sr1 = 0x00;
+ cr17 = 0x80;
+ pmreg = 0x00;
+ cr63 = 0x00;
+ ret = 1;
+ sisusb->con_blanked = 0;
+ break;
+ case VESA_VSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x80;
+ cr63 = 0x40;
+ break;
+ case VESA_HSYNC_SUSPEND + 1:
+ sr1 = 0x20;
+ cr17 = 0x80;
+ pmreg = 0x40;
+ cr63 = 0x40;
+ break;
+ case VESA_POWERDOWN + 1:
+ sr1 = 0x20;
+ cr17 = 0x00;
+ pmreg = 0xc0;
+ cr63 = 0x40;
+ break;
+ default:
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
+ sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
+ sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
+ sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
+
+ }
+
+ up(&sisusb->lock);
+
+ return ret;
+}
+
+/* interface routine */
+static int
+sisusbcon_scrolldelta(struct vc_data *c, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ /* The return value does not seem to be used */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+
+ if (sisusb->con_rolled_over >
+ (c->vc_scr_end - sisusb->scrbuf) + margin) {
+
+ ul = c->vc_scr_end - sisusb->scrbuf;
+ we = sisusb->con_rolled_over + c->vc_size_row;
+
+ } else {
+
+ ul = 0;
+ we = sisusb->scrbuf_size;
+
+ }
+
+ p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
+ lines * c->vc_size_row;
+
+ st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
+
+ if (st < 2 * margin)
+ margin = 0;
+
+ if (p < margin)
+ p = 0;
+
+ if (p > st - margin)
+ p = st;
+
+ c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
+ }
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static void
+sisusbcon_cursor(struct vc_data *c, int mode)
+{
+ struct sisusb_usb_data *sisusb;
+ int from, to, baseline;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return;
+ }
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ if (mode == CM_ERASE) {
+ sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
+ sisusb->sisusb_cursor_size_to = -1;
+ up(&sisusb->lock);
+ return;
+ }
+
+ sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
+
+ baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
+
+ switch (c->vc_cursor_type & 0x0f) {
+ case CUR_BLOCK: from = 1;
+ to = c->vc_font.height;
+ break;
+ case CUR_TWO_THIRDS: from = c->vc_font.height / 3;
+ to = baseline;
+ break;
+ case CUR_LOWER_HALF: from = c->vc_font.height / 2;
+ to = baseline;
+ break;
+ case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;
+ to = baseline;
+ break;
+ case CUR_NONE: from = 31;
+ to = 30;
+ break;
+ default:
+ case CUR_UNDERLINE: from = baseline - 1;
+ to = baseline;
+ break;
+ }
+
+ if (sisusb->sisusb_cursor_size_from != from ||
+ sisusb->sisusb_cursor_size_to != to) {
+
+ sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
+
+ sisusb->sisusb_cursor_size_from = from;
+ sisusb->sisusb_cursor_size_to = to;
+ }
+
+ up(&sisusb->lock);
+}
+
+static int
+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
+ int t, int b, int dir, int lines)
+{
+ int cols = sisusb->sisusb_num_columns;
+ int length = ((b - t) * cols) * 2;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+
+ /* sisusb->lock is down */
+
+ /* Scroll an area which does not match the
+ * visible screen's dimensions. This needs
+ * to be done separately, as it does not
+ * use hardware panning.
+ */
+
+ switch (dir) {
+
+ case SM_UP:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t),
+ SISUSB_VADDR(0, t + lines),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
+ lines * cols * 2);
+ break;
+
+ case SM_DOWN:
+ sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
+ SISUSB_VADDR(0, t),
+ (b - t - lines) * cols * 2);
+ sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+ lines * cols * 2);
+ break;
+ }
+
+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
+ (u32)SISUSB_HADDR(0, t), length, &written);
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+ struct sisusb_usb_data *sisusb;
+ u16 eattr = c->vc_video_erase_char;
+ ssize_t written;
+ int copyall = 0;
+ unsigned long oldorigin;
+ unsigned int delta = lines * c->vc_size_row;
+ u32 originoffset;
+
+ /* Returning != 0 means we have done the scrolling successfully.
+ * Returning 0 makes vt do the scrolling on its own.
+ * Note that con_scroll is only called if the console is
+ * visible. In that case, the origin should be our buffer,
+ * not the vt's private one.
+ */
+
+ if (!lines)
+ return 1;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb)) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ /* Special case */
+ if (t || b != c->vc_rows)
+ return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
+
+ if (c->vc_origin != c->vc_visible_origin) {
+ c->vc_visible_origin = c->vc_origin;
+ sisusbcon_set_start_address(sisusb, c);
+ }
+
+ /* limit amount to maximum realistic size */
+ if (lines > c->vc_rows)
+ lines = c->vc_rows;
+
+ oldorigin = c->vc_origin;
+
+ switch (dir) {
+
+ case SM_UP:
+
+ if (c->vc_scr_end + delta >=
+ sisusb->scrbuf + sisusb->scrbuf_size) {
+ sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+ (u16 *)(oldorigin + delta),
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf;
+ sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
+ copyall = 1;
+ } else
+ c->vc_origin += delta;
+
+ sisusbcon_memsetw(
+ (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
+ eattr, delta);
+
+ break;
+
+ case SM_DOWN:
+
+ if (oldorigin - delta < sisusb->scrbuf) {
+ sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size +
+ delta),
+ (u16 *)oldorigin,
+ c->vc_screenbuf_size - delta);
+ c->vc_origin = sisusb->scrbuf +
+ sisusb->scrbuf_size -
+ c->vc_screenbuf_size;
+ sisusb->con_rolled_over = 0;
+ copyall = 1;
+ } else
+ c->vc_origin -= delta;
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+
+ scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
+
+ break;
+ }
+
+ originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
+
+ if (copyall)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ c->vc_screenbuf_size, &written);
+ else if (dir == SM_UP)
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin + c->vc_screenbuf_size - delta,
+ (u32)sisusb->vrambase + originoffset +
+ c->vc_screenbuf_size - delta,
+ delta, &written);
+ else
+ sisusb_copy_memory(sisusb,
+ (char *)c->vc_origin,
+ (u32)(sisusb->vrambase + originoffset),
+ delta, &written);
+
+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+ c->vc_visible_origin = c->vc_origin;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_set_origin(struct vc_data *c)
+{
+ struct sisusb_usb_data *sisusb;
+
+ /* Returning != 0 means we were successful.
+ * Returning 0 will vt make to use its own
+ * screenbuffer as the origin.
+ */
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return 0;
+
+ /* sisusb->lock is down */
+
+ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
+
+ sisusbcon_set_start_address(sisusb, c);
+
+ sisusb->con_rolled_over = 0;
+
+ up(&sisusb->lock);
+
+ return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
+{
+ struct sisusb_usb_data *sisusb;
+ int fh;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ fh = sisusb->current_font_height;
+
+ up(&sisusb->lock);
+
+ /* We are quite unflexible as regards resizing. The vt code
+ * handles sizes where the line length isn't equal the pitch
+ * quite badly. As regards the rows, our panning tricks only
+ * work well if the number of rows equals the visible number
+ * of rows.
+ */
+
+ if (newcols != 80 || c->vc_scan_lines / fh != newrows)
+ return -EINVAL;
+
+ return 0;
+}
+
+int
+sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ u8 *arg, int cmapsz, int ch512, int dorecalc,
+ struct vc_data *c, int fh, int uplock)
+{
+ int font_select = 0x00, i, err = 0;
+ u32 offset = 0;
+ u8 dummy;
+
+ /* sisusb->lock is down */
+
+ /*
+ * The default font is kept in slot 0.
+ * A user font is loaded in slot 2 (256 ch)
+ * or 2+3 (512 ch).
+ */
+
+ if ((slot != 0 && slot != 2) || !fh) {
+ if (uplock)
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ if (set)
+ sisusb->font_slot = slot;
+
+ /* Default font is always 256 */
+ if (slot == 0)
+ ch512 = 0;
+ else
+ offset = 4 * cmapsz;
+
+ font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if (arg) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset + i,
+ arg[i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset + i,
+ &arg[i]);
+ if (err)
+ break;
+ }
+
+ /*
+ * In 512-character mode, the character map is not contiguous if
+ * we want to remain EGA compatible -- which we do
+ */
+
+ if (ch512) {
+ if (set)
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_writeb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ else
+ for (i = 0; i < cmapsz; i++) {
+ err |= sisusb_readb(sisusb,
+ sisusb->vrambase + offset +
+ (2 * cmapsz) + i,
+ &arg[cmapsz + i]);
+ if (err)
+ break;
+ }
+ }
+ }
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
+ if (set)
+ sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
+
+ if (err)
+ goto font_op_error;
+
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
+
+ if (err)
+ goto font_op_error;
+
+ if ((set) && (ch512 != sisusb->current_font_512)) {
+
+ /* Font is shared among all our consoles.
+ * And so is the hi_font_mask.
+ */
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *c = vc_cons[i].d;
+ if (c && c->vc_sw == &sisusb_con)
+ c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ }
+
+ sisusb->current_font_512 = ch512;
+
+ /* color plane enable register:
+ 256-char: enable intensity bit
+ 512-char: disable intensity bit */
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x12);
+ sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
+
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ sisusb_setreg(sisusb, SISAR, 0x20);
+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+ }
+
+ if (dorecalc) {
+
+ /*
+ * Adjust the screen to fit a font of a certain height
+ */
+
+ unsigned char ovr, vde, fsr;
+ int rows = 0, maxscan = 0;
+
+ if (c) {
+
+ /* Number of video rows */
+ rows = c->vc_scan_lines / fh;
+ /* Scan lines to actually display-1 */
+ maxscan = rows * fh - 1;
+
+ /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
+ rows, maxscan, fh, c->vc_scan_lines);*/
+
+ sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
+ vde = maxscan & 0xff;
+ ovr = (ovr & 0xbd) |
+ ((maxscan & 0x100) >> 7) |
+ ((maxscan & 0x200) >> 3);
+ sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
+ sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
+
+ }
+
+ sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
+ fsr = (fsr & 0xe0) | (fh - 1);
+ sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
+ sisusb->current_font_height = fh;
+
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ }
+
+ if (uplock)
+ up(&sisusb->lock);
+
+ if (dorecalc && c) {
+ int i, rows = c->vc_scan_lines / fh;
+
+ /* Now adjust our consoles' size */
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *vc = vc_cons[i].d;
+
+ if (vc && vc->vc_sw == &sisusb_con) {
+ if (CON_IS_VISIBLE(vc)) {
+ vc->vc_sw->con_cursor(vc, CM_DRAW);
+ }
+ vc->vc_font.height = fh;
+ vc_resize(vc, 0, rows);
+ }
+ }
+ }
+
+ return 0;
+
+font_op_error:
+ if (uplock)
+ up(&sisusb->lock);
+
+ return -EIO;
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_set(struct vc_data *c, struct console_font *font,
+ unsigned flags)
+{
+ struct sisusb_usb_data *sisusb;
+ unsigned charcount = font->charcount;
+
+ if (font->width != 8 || (charcount != 256 && charcount != 512))
+ return -EINVAL;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ /* Save the user-provided font into a buffer. This
+ * is used for restoring text mode after quitting
+ * from X and for the con_getfont routine.
+ */
+ if (sisusb->font_backup) {
+ if (sisusb->font_backup_size < charcount) {
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+ }
+ }
+
+ if (!sisusb->font_backup)
+ sisusb->font_backup = vmalloc(charcount * 32);
+
+ if (sisusb->font_backup) {
+ memcpy(sisusb->font_backup, font->data, charcount * 32);
+ sisusb->font_backup_size = charcount;
+ sisusb->font_backup_height = font->height;
+ sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
+ }
+
+ /* do_font_op ups sisusb->lock */
+
+ return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
+ 8192, (charcount == 512),
+ (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
+ c, font->height, 1);
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_get(struct vc_data *c, struct console_font *font)
+{
+ struct sisusb_usb_data *sisusb;
+
+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+ return -ENODEV;
+
+ /* sisusb->lock is down */
+
+ font->width = 8;
+ font->height = c->vc_font.height;
+ font->charcount = 256;
+
+ if (!font->data) {
+ up(&sisusb->lock);
+ return 0;
+ }
+
+ if (!sisusb->font_backup) {
+ up(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ /* Copy 256 chars only, like vgacon */
+ memcpy(font->data, sisusb->font_backup, 256 * 32);
+
+ up(&sisusb->lock);
+
+ return 0;
+}
+
+/*
+ * The console `switch' structure for the sisusb console
+ */
+
+static const struct consw sisusb_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbcon_startup,
+ .con_init = sisusbcon_init,
+ .con_deinit = sisusbcon_deinit,
+ .con_clear = sisusbcon_clear,
+ .con_putc = sisusbcon_putc,
+ .con_putcs = sisusbcon_putcs,
+ .con_cursor = sisusbcon_cursor,
+ .con_scroll = sisusbcon_scroll,
+ .con_bmove = sisusbcon_bmove,
+ .con_switch = sisusbcon_switch,
+ .con_blank = sisusbcon_blank,
+ .con_font_set = sisusbcon_font_set,
+ .con_font_get = sisusbcon_font_get,
+ .con_set_palette = sisusbcon_set_palette,
+ .con_scrolldelta = sisusbcon_scrolldelta,
+ .con_build_attr = sisusbcon_build_attr,
+ .con_invert_region = sisusbcon_invert_region,
+ .con_set_origin = sisusbcon_set_origin,
+ .con_save_screen = sisusbcon_save_screen,
+ .con_resize = sisusbcon_resize,
+};
+
+/* Our very own dummy console driver */
+
+static const char *sisusbdummycon_startup(void)
+{
+ return "SISUSBVGADUMMY";
+}
+
+static void sisusbdummycon_init(struct vc_data *vc, int init)
+{
+ vc->vc_can_do_color = 1;
+ if (init) {
+ vc->vc_cols = 80;
+ vc->vc_rows = 25;
+ } else
+ vc_resize(vc, 80, 25);
+}
+
+static int sisusbdummycon_dummy(void)
+{
+ return 0;
+}
+
+#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
+
+const struct consw sisusb_dummy_con = {
+ .owner = THIS_MODULE,
+ .con_startup = sisusbdummycon_startup,
+ .con_init = sisusbdummycon_init,
+ .con_deinit = SISUSBCONDUMMY,
+ .con_clear = SISUSBCONDUMMY,
+ .con_putc = SISUSBCONDUMMY,
+ .con_putcs = SISUSBCONDUMMY,
+ .con_cursor = SISUSBCONDUMMY,
+ .con_scroll = SISUSBCONDUMMY,
+ .con_bmove = SISUSBCONDUMMY,
+ .con_switch = SISUSBCONDUMMY,
+ .con_blank = SISUSBCONDUMMY,
+ .con_font_set = SISUSBCONDUMMY,
+ .con_font_get = SISUSBCONDUMMY,
+ .con_font_default = SISUSBCONDUMMY,
+ .con_font_copy = SISUSBCONDUMMY,
+ .con_set_palette = SISUSBCONDUMMY,
+ .con_scrolldelta = SISUSBCONDUMMY,
+};
+
+int
+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+{
+ int i, ret, minor = sisusb->minor;
+
+ down(&disconnect_sem);
+
+ down(&sisusb->lock);
+
+ /* Erm.. that should not happen */
+ if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 1;
+ }
+
+ sisusb->con_first = first;
+ sisusb->con_last = last;
+
+ if (first > last ||
+ first > MAX_NR_CONSOLES ||
+ last > MAX_NR_CONSOLES) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 1;
+ }
+
+ /* If gfxcore not initialized or no consoles given, quit graciously */
+ if (!sisusb->gfxinit || first < 1 || last < 1) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return 0;
+ }
+
+ sisusb->sisusb_cursor_loc = -1;
+ sisusb->sisusb_cursor_size_from = -1;
+ sisusb->sisusb_cursor_size_to = -1;
+
+ /* Set up text mode (and upload default font) */
+ if (sisusb_reset_text_mode(sisusb, 1)) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to set up text mode\n",
+ minor);
+ return 1;
+ }
+
+ /* Initialize some gfx registers */
+ sisusb_initialize(sisusb);
+
+ for (i = first - 1; i <= last - 1; i++) {
+ /* Save sisusb for our interface routines */
+ mysisusbs[i] = sisusb;
+ }
+
+ /* Initial console setup */
+ sisusb->sisusb_num_columns = 80;
+
+ /* Use a 32K buffer (matches b8000-bffff area) */
+ sisusb->scrbuf_size = 32 * 1024;
+
+ /* Allocate screen buffer */
+ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate screen buffer\n",
+ minor);
+ return 1;
+ }
+
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+
+ /* Now grab the desired console(s) */
+ ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
+
+ if (!ret)
+ sisusb->haveconsole = 1;
+ else {
+ for (i = first - 1; i <= last - 1; i++)
+ mysisusbs[i] = NULL;
+ }
+
+ return ret;
+}
+
+void
+sisusb_console_exit(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ /* This is called if the device is disconnected
+ * and while disconnect and lock semaphores
+ * are up. This should be save because we
+ * can't lose our sisusb any other way but by
+ * disconnection (and hence, the disconnect
+ * sema is for protecting all other access
+ * functions from disconnection, not the
+ * other way round).
+ */
+
+ /* Now what do we do in case of disconnection:
+ * One alternative would be to simply call
+ * give_up_console(). Nah, not a good idea.
+ * give_up_console() is obviously buggy as it
+ * only discards the consw pointer from the
+ * driver_map, but doesn't adapt vc->vc_sw
+ * of the affected consoles. Hence, the next
+ * call to any of the console functions will
+ * eventually take a trip to oops county.
+ * Also, give_up_console for some reason
+ * doesn't decrement our module refcount.
+ * Instead, we switch our consoles to a private
+ * dummy console. This, of course, keeps our
+ * refcount up as well, but it works perfectly.
+ */
+
+ if (sisusb->haveconsole) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ if (sisusb->havethisconsole[i])
+ take_over_console(&sisusb_dummy_con, i, i, 0);
+ /* At this point, con_deinit for all our
+ * consoles is executed by take_over_console().
+ */
+ sisusb->haveconsole = 0;
+ }
+
+ vfree((void *)sisusb->scrbuf);
+ sisusb->scrbuf = 0;
+
+ vfree(sisusb->font_backup);
+ sisusb->font_backup = NULL;
+}
+
+void __init sisusb_init_concode(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ mysisusbs[i] = NULL;
+}
+
+#endif /* INCL_CON */
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 000000000000..f28bc240f9b6
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,1047 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Display mode initializing code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+
+#include "sisusb_init.h"
+
+/*********************************************/
+/* POINTER INITIALIZATION */
+/*********************************************/
+
+static void
+SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
+ SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
+
+ SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
+ SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
+ SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
+ SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
+
+ SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
+}
+
+/*********************************************/
+/* HELPER: Get ModeID */
+/*********************************************/
+
+unsigned short
+SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
+{
+ unsigned short ModeIndex = 0;
+
+ switch (HDisplay)
+ {
+ case 320:
+ if (VDisplay == 200)
+ ModeIndex = ModeIndex_320x200[Depth];
+ else if (VDisplay == 240)
+ ModeIndex = ModeIndex_320x240[Depth];
+ break;
+ case 400:
+ if (VDisplay == 300)
+ ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 512:
+ if (VDisplay == 384)
+ ModeIndex = ModeIndex_512x384[Depth];
+ break;
+ case 640:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_640x480[Depth];
+ else if (VDisplay == 400)
+ ModeIndex = ModeIndex_640x400[Depth];
+ break;
+ case 720:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_720x480[Depth];
+ else if (VDisplay == 576)
+ ModeIndex = ModeIndex_720x576[Depth];
+ break;
+ case 768:
+ if (VDisplay == 576)
+ ModeIndex = ModeIndex_768x576[Depth];
+ break;
+ case 800:
+ if (VDisplay == 600)
+ ModeIndex = ModeIndex_800x600[Depth];
+ else if (VDisplay == 480)
+ ModeIndex = ModeIndex_800x480[Depth];
+ break;
+ case 848:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_848x480[Depth];
+ break;
+ case 856:
+ if (VDisplay == 480)
+ ModeIndex = ModeIndex_856x480[Depth];
+ break;
+ case 960:
+ if (VDisplay == 540)
+ ModeIndex = ModeIndex_960x540[Depth];
+ else if (VDisplay == 600)
+ ModeIndex = ModeIndex_960x600[Depth];
+ break;
+ case 1024:
+ if (VDisplay == 576)
+ ModeIndex = ModeIndex_1024x576[Depth];
+ else if (VDisplay == 768)
+ ModeIndex = ModeIndex_1024x768[Depth];
+ break;
+ case 1152:
+ if (VDisplay == 864)
+ ModeIndex = ModeIndex_1152x864[Depth];
+ break;
+ case 1280:
+ switch (VDisplay) {
+ case 720:
+ ModeIndex = ModeIndex_1280x720[Depth];
+ break;
+ case 768:
+ ModeIndex = ModeIndex_1280x768[Depth];
+ break;
+ case 1024:
+ ModeIndex = ModeIndex_1280x1024[Depth];
+ break;
+ }
+ }
+
+ return ModeIndex;
+}
+
+/*********************************************/
+/* HELPER: SetReg, GetReg */
+/*********************************************/
+
+static void
+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short data)
+{
+ sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
+}
+
+static void
+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short data)
+{
+ sisusb_setreg(SiS_Pr->sisusb, port, data);
+}
+
+static unsigned char
+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index)
+{
+ u8 data;
+
+ sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
+
+ return data;
+}
+
+static unsigned char
+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
+{
+ u8 data;
+
+ sisusb_getreg(SiS_Pr->sisusb, port, &data);
+
+ return data;
+}
+
+static void
+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND,
+ unsigned short DataOR)
+{
+ sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
+}
+
+static void
+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
+ unsigned short index, unsigned short DataAND)
+{
+ sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
+}
+
+static void
+SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
+ unsigned short index, unsigned short DataOR)
+{
+ sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
+}
+
+/*********************************************/
+/* HELPER: DisplayOn, DisplayOff */
+/*********************************************/
+
+static void
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
+}
+
+/*********************************************/
+/* HELPER: Init Port Addresses */
+/*********************************************/
+
+void
+SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
+{
+ SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+ SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+ SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+ SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+ SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+ SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+ SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+ SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+ SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+ SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+ SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+ SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+ SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+}
+
+/*********************************************/
+/* HELPER: GetSysFlags */
+/*********************************************/
+
+static void
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+ SiS_Pr->SiS_MyCR63 = 0x63;
+}
+
+/*********************************************/
+/* HELPER: Init PCI & Engines */
+/*********************************************/
+
+static void
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
+ /* - Enable 2D (0x40)
+ * - Enable 3D (0x02)
+ * - Enable 3D vertex command fetch (0x10)
+ * - Enable 3D command parser (0x08)
+ * - Enable 3D G/L transformation engine (0x80)
+ */
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
+}
+
+/*********************************************/
+/* HELPER: SET SEGMENT REGISTERS */
+/*********************************************/
+
+static void
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
+ temp |= (value >> 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
+ temp |= (value & 0x0f);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp;
+
+ value &= 0x00ff;
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
+ temp |= (value & 0xf0);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
+ temp |= (value << 4);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ SiS_SetSegRegLower(SiS_Pr, value);
+ SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+ unsigned short temp = value >> 8;
+
+ temp &= 0x07;
+ temp |= (temp << 4);
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
+ SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+ SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+ SiS_ResetSegmentReg(SiS_Pr);
+ SiS_ResetSegmentRegOver(SiS_Pr);
+}
+
+/*********************************************/
+/* HELPER: SearchModeID */
+/*********************************************/
+
+static int
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex)
+{
+ if ((*ModeNo) <= 0x13) {
+
+ if ((*ModeNo) != 0x03)
+ return 0;
+
+ (*ModeIdIndex) = 0;
+
+ } else {
+
+ for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
+ break;
+
+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+ return 0;
+ }
+
+ }
+
+ return 1;
+}
+
+/*********************************************/
+/* HELPER: ENABLE CRT1 */
+/*********************************************/
+
+static void
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+ /* Enable CRT1 gating */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
+}
+
+/*********************************************/
+/* HELPER: GetColorDepth */
+/*********************************************/
+
+static unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
+ unsigned short modeflag;
+ short index;
+
+ if (ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ index = (modeflag & ModeTypeMask) - ModeEGA;
+ if (index < 0) index = 0;
+ return ColorDepth[index];
+}
+
+/*********************************************/
+/* HELPER: GetOffset */
+/*********************************************/
+
+static unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short xres, temp, colordepth, infoflag;
+
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
+
+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+ temp = xres / 16;
+
+ if (infoflag & InterlaceMode)
+ temp <<= 1;
+
+ temp *= colordepth;
+
+ if (xres % 16)
+ temp += (colordepth >> 1);
+
+ return temp;
+}
+
+/*********************************************/
+/* SEQ */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char SRdata;
+ int i;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
+
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
+
+ for(i = 2; i <= 4; i++) {
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
+ }
+}
+
+/*********************************************/
+/* MISC */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
+}
+
+/*********************************************/
+/* CRTC */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char CRTCdata;
+ unsigned short i;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+ for(i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
+ }
+}
+
+/*********************************************/
+/* ATT */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char ARdata;
+ unsigned short i;
+
+ for(i = 0; i <= 0x13; i++) {
+ ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
+ }
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
+
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/* GRC */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+ unsigned char GRdata;
+ unsigned short i;
+
+ for(i = 0; i <= 0x08; i++) {
+ GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
+ }
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA) {
+ /* 256 color disable */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
+ }
+}
+
+/*********************************************/
+/* CLEAR EXTENDED REGISTERS */
+/*********************************************/
+
+static void
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ int i;
+
+ for(i = 0x0A; i <= 0x0E; i++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
+ }
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
+}
+
+/*********************************************/
+/* Get rate index */
+/*********************************************/
+
+static unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short rrti, i, index, temp;
+
+ if (ModeNo <= 0x13)
+ return 0xFFFF;
+
+ index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
+ if (index > 0) index--;
+
+ rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
+
+ i = 0;
+ do {
+ if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
+ break;
+
+ temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
+ if (temp < SiS_Pr->SiS_ModeType)
+ break;
+
+ i++;
+ index--;
+ } while(index != 0xFFFF);
+
+ i--;
+
+ return (rrti + i);
+}
+
+/*********************************************/
+/* SYNC */
+/*********************************************/
+
+static void
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
+{
+ unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
+ sync &= 0xC0;
+ sync |= 0x2f;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
+}
+
+/*********************************************/
+/* CRTC/2 */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned char index;
+ unsigned short temp, i, j, modeflag;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
+
+ for(i = 0,j = 0; i <= 7; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x10; i <= 10; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x15; i <= 12; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+ for(j = 0x0A; i <= 15; i++, j++) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
+ SiS_Pr->SiS_CRT1Table[index].CR[i]);
+ }
+
+ temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
+
+ temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+ if (modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
+
+ if (SiS_Pr->SiS_ModeType > ModeVGA)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
+}
+
+/*********************************************/
+/* OFFSET & PITCH */
+/*********************************************/
+/* (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ unsigned short temp;
+
+ temp = (du >> 8) & 0x0f;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
+
+ if (infoflag & InterlaceMode) du >>= 1;
+
+ du <<= 5;
+ temp = (du >> 8) & 0xff;
+ if (du & 0xff) temp++;
+ temp++;
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
+}
+
+/*********************************************/
+/* VCLK */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+ unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
+}
+
+/*********************************************/
+/* FIFO */
+/*********************************************/
+
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short mi)
+{
+ unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ /* disable auto-threshold */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
+
+ if (ModeNo <= 0x13)
+ return;
+
+ if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
+ }
+}
+
+/*********************************************/
+/* MODE REGISTERS */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short rrti)
+{
+ unsigned short data = 0, VCLK = 0, index = 0;
+
+ if (ModeNo > 0x13) {
+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+
+ if (VCLK >= 166) data |= 0x0c;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
+
+ if (VCLK >= 166)
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
+
+ /* DAC speed */
+ data = 0x03;
+ if (VCLK >= 260)
+ data = 0x00;
+ else if (VCLK >= 160)
+ data = 0x01;
+ else if (VCLK >= 135)
+ data = 0x02;
+
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short rrti)
+{
+ unsigned short data, infoflag = 0, modeflag;
+
+ if (ModeNo <= 0x13)
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+ }
+
+ /* Disable DPMS */
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
+
+ data = 0;
+ if (ModeNo > 0x13) {
+ if (SiS_Pr->SiS_ModeType > ModeEGA) {
+ data |= 0x02;
+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+ }
+ if (infoflag & InterlaceMode) data |= 0x20;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
+
+ data = 0;
+ if (infoflag & InterlaceMode) {
+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+ unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
+ unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
+ data = hrs - (hto >> 1) + 3;
+ }
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
+
+ if (modeflag & HalfDCLK)
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
+
+ data = 0;
+ if (modeflag & LineCompareOff)
+ data = 0x08;
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
+
+ if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
+
+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
+
+ data = 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeText) {
+ data ^= 0x60;
+ if (SiS_Pr->SiS_ModeType != ModeEGA)
+ data ^= 0xA0;
+ }
+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
+
+ SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
+
+ if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
+ else
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
+}
+
+/*********************************************/
+/* LOAD DAC */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
+ unsigned short shiftflag, unsigned short dl, unsigned short ah,
+ unsigned short al, unsigned short dh)
+{
+ unsigned short d1, d2, d3;
+
+ switch (dl) {
+ case 0:
+ d1 = dh; d2 = ah; d3 = al;
+ break;
+ case 1:
+ d1 = ah; d2 = al; d3 = dh;
+ break;
+ default:
+ d1 = al; d2 = dh; d3 = ah;
+ }
+ SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
+ SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
+}
+
+static void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
+{
+ unsigned short data, data2, time, i, j, k, m, n, o;
+ unsigned short si, di, bx, sf;
+ unsigned long DACAddr, DACData;
+ const unsigned char *table = NULL;
+
+ if (ModeNo < 0x13)
+ data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
+ else
+ data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+ data &= DACInfoFlag;
+
+ j = time = 64;
+ if (data == 0x00)
+ table = SiS_MDA_DAC;
+ else if (data == 0x08)
+ table = SiS_CGA_DAC;
+ else if (data == 0x10)
+ table = SiS_EGA_DAC;
+ else {
+ j = 16;
+ time = 256;
+ table = SiS_VGA_DAC;
+ }
+
+ DACAddr = SiS_Pr->SiS_P3c8;
+ DACData = SiS_Pr->SiS_P3c9;
+ sf = 0;
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
+
+ for(i = 0; i < j; i++) {
+ data = table[i];
+ for(k = 0; k < 3; k++) {
+ data2 = 0;
+ if (data & 0x01) data2 += 0x2A;
+ if (data & 0x02) data2 += 0x15;
+ SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
+ data >>= 2;
+ }
+ }
+
+ if (time == 256) {
+ for(i = 16; i < 32; i++) {
+ data = table[i] << sf;
+ for(k = 0; k < 3; k++)
+ SiS_SetRegByte(SiS_Pr, DACData, data);
+ }
+ si = 32;
+ for(m = 0; m < 9; m++) {
+ di = si;
+ bx = si + 4;
+ for(n = 0; n < 3; n++) {
+ for(o = 0; o < 5; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[bx], table[si]);
+ si++;
+ }
+ si -= 2;
+ for(o = 0; o < 3; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+ table[di], table[si], table[bx]);
+ si--;
+ }
+ }
+ si += 5;
+ }
+ }
+}
+
+/*********************************************/
+/* SET CRT1 REGISTER GROUP */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ unsigned short StandTableIndex, rrti;
+
+ SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+ if (ModeNo <= 0x13)
+ StandTableIndex = 0;
+ else
+ StandTableIndex = 1;
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+
+ rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if (rrti != 0xFFFF) {
+ SiS_SetCRT1Sync(SiS_Pr, rrti);
+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
+ }
+
+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_DisplayOn(SiS_Pr);
+}
+
+/*********************************************/
+/* SiSSetMode() */
+/*********************************************/
+
+int
+SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+ unsigned short ModeIdIndex;
+ unsigned long BaseAddr = SiS_Pr->IOAddress;
+
+ SiSUSB_InitPtr(SiS_Pr);
+ SiSUSBRegInit(SiS_Pr, BaseAddr);
+ SiS_GetSysFlags(SiS_Pr);
+
+ if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
+ return 0;
+
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
+
+ SiSInitPCIetc(SiS_Pr);
+
+ ModeNo &= 0x7f;
+
+ SiS_Pr->SiS_ModeType =
+ SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
+
+ SiS_Pr->SiS_SetFlag = LowModeTests;
+
+ /* Set mode on CRT1 */
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_HandleCRT1(SiS_Pr);
+
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+ /* Store mode number */
+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
+
+ return 1;
+}
+
+int
+SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
+{
+ unsigned short ModeNo = 0;
+ int i;
+
+ SiSUSB_InitPtr(SiS_Pr);
+
+ if (VModeNo == 0x03) {
+
+ ModeNo = 0x03;
+
+ } else {
+
+ i = 0;
+ do {
+
+ if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
+ ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
+ break;
+ }
+
+ } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
+
+ }
+
+ if (!ModeNo)
+ return 0;
+
+ return SiSUSBSetMode(SiS_Pr, ModeNo);
+}
+
+#endif /* INCL_SISUSB_CON */
+
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 000000000000..5b11577835c8
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,830 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * 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 named 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_INIT_H_
+#define _SISUSB_INIT_H_
+
+/* SiS_ModeType */
+#define ModeText 0x00
+#define ModeCGA 0x01
+#define ModeEGA 0x02
+#define ModeVGA 0x03
+#define Mode15Bpp 0x04
+#define Mode16Bpp 0x05
+#define Mode24Bpp 0x06
+#define Mode32Bpp 0x07
+
+#define ModeTypeMask 0x07
+#define IsTextMode 0x07
+
+#define DACInfoFlag 0x0018
+#define MemoryInfoFlag 0x01E0
+#define MemorySizeShift 5
+
+/* modeflag */
+#define Charx8Dot 0x0200
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode 0x8000
+
+/* Infoflag */
+#define SupportTV 0x0008
+#define SupportTV1024 0x0800
+#define SupportCHTV 0x0800
+#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */
+#define SupportHiVision 0x0010
+#define SupportYPbPr750p 0x1000
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */
+#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */
+#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+#define SyncNN 0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2 0x0001
+#define LowModeTests 0x0002
+#define LCDVESATiming 0x0008
+#define EnableLVDSDDA 0x0010
+#define SetDispDevSwitchFlag 0x0020
+#define CheckWinDos 0x0040
+#define SetDOSMode 0x0080
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200 0
+#define SIS_RI_320x240 1
+#define SIS_RI_320x400 2
+#define SIS_RI_400x300 3
+#define SIS_RI_512x384 4
+#define SIS_RI_640x400 5
+#define SIS_RI_640x480 6
+#define SIS_RI_800x600 7
+#define SIS_RI_1024x768 8
+#define SIS_RI_1280x1024 9
+#define SIS_RI_1600x1200 10
+#define SIS_RI_1920x1440 11
+#define SIS_RI_2048x1536 12
+#define SIS_RI_720x480 13
+#define SIS_RI_720x576 14
+#define SIS_RI_1280x960 15
+#define SIS_RI_800x480 16
+#define SIS_RI_1024x576 17
+#define SIS_RI_1280x720 18
+#define SIS_RI_856x480 19
+#define SIS_RI_1280x768 20
+#define SIS_RI_1400x1050 21
+#define SIS_RI_1152x864 22 /* Up to here SiS conforming */
+#define SIS_RI_848x480 23
+#define SIS_RI_1360x768 24
+#define SIS_RI_1024x600 25
+#define SIS_RI_1152x768 26
+#define SIS_RI_768x576 27
+#define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800 30
+#define SIS_RI_1920x1080 31
+#define SIS_RI_960x540 32
+#define SIS_RI_960x600 33
+
+#define SIS_VIDEO_CAPTURE 0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
+#define SIS_CRT2_PORT_04 0x04 - 0x30
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f};
+static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22};
+static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+
+static const unsigned char SiS_MDA_DAC[] =
+{
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+ 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+ 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+ 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+ 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+ 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+ 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] =
+{
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+ 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+ 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+ 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+ 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+ 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+ 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x0B,0x0C,0x0D,0x0F,0x10
+};
+
+static const struct SiS_St SiSUSB_SModeIDTable[] =
+{
+ {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
+{
+ { 640,400},
+ { 640,350},
+ { 720,400},
+ { 720,350},
+ { 640,480}
+};
+
+static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
+{
+ { 320, 200, 8, 8}, /* 0x00 */
+ { 320, 240, 8, 8}, /* 0x01 */
+ { 320, 400, 8, 8}, /* 0x02 */
+ { 400, 300, 8, 8}, /* 0x03 */
+ { 512, 384, 8, 8}, /* 0x04 */
+ { 640, 400, 8,16}, /* 0x05 */
+ { 640, 480, 8,16}, /* 0x06 */
+ { 800, 600, 8,16}, /* 0x07 */
+ { 1024, 768, 8,16}, /* 0x08 */
+ { 1280,1024, 8,16}, /* 0x09 */
+ { 1600,1200, 8,16}, /* 0x0a */
+ { 1920,1440, 8,16}, /* 0x0b */
+ { 2048,1536, 8,16}, /* 0x0c */
+ { 720, 480, 8,16}, /* 0x0d */
+ { 720, 576, 8,16}, /* 0x0e */
+ { 1280, 960, 8,16}, /* 0x0f */
+ { 800, 480, 8,16}, /* 0x10 */
+ { 1024, 576, 8,16}, /* 0x11 */
+ { 1280, 720, 8,16}, /* 0x12 */
+ { 856, 480, 8,16}, /* 0x13 */
+ { 1280, 768, 8,16}, /* 0x14 */
+ { 1400,1050, 8,16}, /* 0x15 */
+ { 1152, 864, 8,16}, /* 0x16 */
+ { 848, 480, 8,16}, /* 0x17 */
+ { 1360, 768, 8,16}, /* 0x18 */
+ { 1024, 600, 8,16}, /* 0x19 */
+ { 1152, 768, 8,16}, /* 0x1a */
+ { 768, 576, 8,16}, /* 0x1b */
+ { 1360,1024, 8,16}, /* 0x1c */
+ { 1680,1050, 8,16}, /* 0x1d */
+ { 1280, 800, 8,16}, /* 0x1e */
+ { 1920,1080, 8,16}, /* 0x1f */
+ { 960, 540, 8,16}, /* 0x20 */
+ { 960, 600, 8,16} /* 0x21 */
+};
+
+static const struct SiS_StandTable SiSUSB_StandTable[] =
+{
+ /* MD_3_400 - mode 0x03 - 400 */
+ {
+ 0x50,0x18,0x10,0x1000,
+ { 0x00,0x03,0x00,0x02 },
+ 0x67,
+ { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+ 0xff },
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x0c,0x00,0x0f,0x08 },
+ { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
+ },
+ /* Generic for VGA and higher */
+ {
+ 0x00,0x00,0x00,0x0000,
+ { 0x01,0x0f,0x00,0x0e },
+ 0x23,
+ { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+ 0xff },
+ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x01,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
+ }
+};
+
+static const struct SiS_Ext SiSUSB_EModeIDTable[] =
+{
+ {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+ {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+ {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+ {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+ {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+ {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+ {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+ {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+ {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+ {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+ {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
+ {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
+ {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+ {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+ {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+ {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
+ {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */
+ {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */
+ {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */
+ {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
+ {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
+ {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
+ {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */
+ {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
+ {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
+ {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+ {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+ {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+ {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+ {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
+ {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
+ {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
+ {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
+ {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
+ {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
+ {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
+ {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
+ {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
+ {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
+ {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
+ {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
+ {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
+ {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
+ {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
+ {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
+ {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
+ {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
+ {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
+ {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
+ {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
+ {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
+ {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
+ {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
+ {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
+ {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
+ {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
+ {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
+ {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
+ {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
+ {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
+ {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
+ {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+ {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+ {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const struct SiS_Ext2 SiSUSB_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
+ {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
+ {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
+ {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
+ {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
+ {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
+ {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
+ {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
+ {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
+ {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
+ {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
+ {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
+ {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
+ {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
+ {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
+ {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
+ {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
+ {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
+ {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
+ {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
+ {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
+ {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
+ {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
+ {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
+ {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
+ {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
+ {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
+ {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
+ {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
+ {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
+ {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
+ {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
+ {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
+ {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */
+ {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */
+ {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */
+ {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */
+ {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */
+ {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
+ {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
+ {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
+ {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
+ {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
+ {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
+ {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */
+ {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */
+ {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */
+ {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
+ 0x00}}, /* 0x0 */
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}, /* 0x1 */
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
+ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+ 0x01}}, /* 0x2 */
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+ 0x01}}, /* 0x3 */
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+ 0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
+ 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+ 0x00}}, /* 0x6 */
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+ 0x00}}, /* 0x7 */
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+ 0x00}}, /* 0x8 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
+ 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+ 0x61}}, /* 0x9 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
+ 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
+ 0x61}}, /* 0xa */
+ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
+ 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
+ 0x61}}, /* 0xb */
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+ 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
+ 0x00}}, /* 0xc */
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+ 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+ 0x01}}, /* 0xd */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+ 0x01}}, /* 0xe */
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+ 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+ 0x01}}, /* 0xf */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+ 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+ 0x01}}, /* 0x10 */
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+ 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+ 0x01}}, /* 0x11 */
+ {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
+ 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
+ 0x61}}, /* 0x12 */
+ {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
+ 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
+ 0x61}}, /* 0x13 */
+ {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
+ 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
+ 0x61}}, /* 0x14 */
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+ 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+ 0x00}}, /* 0x15 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x16 */
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x17 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+ 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+ 0x01}}, /* 0x18 */
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+ 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+ 0x01}}, /* 0x19 */
+ {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
+ 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
+ 0x62}}, /* 0x1a */
+ {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
+ 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
+ 0x62}}, /* 0x1b */
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+ 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+ 0x00}}, /* 0x1c */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+ 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+ 0x01}}, /* 0x1d */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
+ 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+ 0x01}}, /* 0x1e */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+ 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+ 0x01}}, /* 0x1f */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x20 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x21 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x22 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x23 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x24 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x25 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+ 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+ 0x00}}, /* 0x26 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x27 */
+ {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
+ 0x63}}, /* 0x28 */
+ {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
+ 0x63}}, /* 0x29 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2a */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2b */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+ 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+ 0x00}}, /* 0x2c */
+ {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
+ 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2d */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
+ 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2e */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
+ 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
+ 0x44}}, /* 0x2f */
+ {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
+ 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
+ 0x44}}, /* 0x30 */
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+ 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+ 0x00}}, /* 0x31 */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
+ 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+ 0x01}}, /* 0x32 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+ 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+ 0x01}}, /* 0x33 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+ 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+ 0x01}}, /* 0x34 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+ 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+ 0x01}}, /* 0x35 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+ 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+ 0x01}}, /* 0x36 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
+ 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+ 0x01}}, /* 0x37 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+ 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x38 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+ 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x39 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+ 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+ 0x01}}, /* 0x3a */
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
+ 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+ 0x01}}, /* 0x3b */
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+ 0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x3d */
+ {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
+ 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
+ 0x00}}, /* 0x3e */
+ {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
+ 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
+ 0x00}}, /* 0x3f */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+ 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+ 0x01}}, /* 0x40 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}}, /* 0x41 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
+ 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+ 0x01}}, /* 0x42 */
+ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
+ 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
+ 0x00}}, /* 0x43 */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
+ 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+ 0x01}}, /* 0x44 */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x45 */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
+ 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+ 0x00}}, /* 0x46 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x47 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
+ 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+ 0x00}}, /* 0x48 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
+ 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+ 0x01}}, /* 0x49 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
+ 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+ 0x01}}, /* 0x4a */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
+ 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
+ 0x00}}, /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
+ 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+ 0x01}}, /* 0x4c */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}},
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}, /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
+ 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+ 0x21}}, /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
+ 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+ 0x20}}, /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
+ 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+ 0x61}}, /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
+ 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+ 0x41}}, /* 0x52 */
+ {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
+ 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
+ 0x01}}, /* 0x53 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
+ 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+ 0x41}} /* 0x54 */
+};
+
+static struct SiS_VCLKData SiSUSB_VCLKData[] =
+{
+ { 0x1b,0xe1, 25}, /* 0x00 */
+ { 0x4e,0xe4, 28}, /* 0x01 */
+ { 0x57,0xe4, 31}, /* 0x02 */
+ { 0xc3,0xc8, 36}, /* 0x03 */
+ { 0x42,0xe2, 40}, /* 0x04 */
+ { 0xfe,0xcd, 43}, /* 0x05 */
+ { 0x5d,0xc4, 44}, /* 0x06 */
+ { 0x52,0xe2, 49}, /* 0x07 */
+ { 0x53,0xe2, 50}, /* 0x08 */
+ { 0x74,0x67, 52}, /* 0x09 */
+ { 0x6d,0x66, 56}, /* 0x0a */
+ { 0x5a,0x64, 65}, /* 0x0b */
+ { 0x46,0x44, 67}, /* 0x0c */
+ { 0xb1,0x46, 68}, /* 0x0d */
+ { 0xd3,0x4a, 72}, /* 0x0e */
+ { 0x29,0x61, 75}, /* 0x0f */
+ { 0x6e,0x46, 76}, /* 0x10 */
+ { 0x2b,0x61, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x41,104}, /* 0x17 */
+ { 0x3a,0x23,105}, /* 0x18 */
+ { 0x70,0x44,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0x54,0x42,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x62,0x06,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a 301 TV */
+ { 0x52,0x6a, 27}, /* 0x3b 301 TV */
+ { 0x62,0x24, 70}, /* 0x3c 301 TV */
+ { 0x62,0x64, 70}, /* 0x3d 301 TV */
+ { 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+ { 0x20,0x26, 33}, /* 0x3f 301 TV */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x60,0x36, 30}, /* 0x41 Chrontel */
+ { 0x40,0x4a, 28}, /* 0x42 Chrontel */
+ { 0x9f,0x46, 44}, /* 0x43 Chrontel */
+ { 0x97,0x2c, 26}, /* 0x44 */
+ { 0x44,0xe4, 25}, /* 0x45 Chrontel */
+ { 0x7e,0x32, 47}, /* 0x46 Chrontel */
+ { 0x8a,0x24, 31}, /* 0x47 Chrontel */
+ { 0x97,0x2c, 26}, /* 0x48 Chrontel */
+ { 0xce,0x3c, 39}, /* 0x49 */
+ { 0x52,0x4a, 36}, /* 0x4a Chrontel */
+ { 0x34,0x61, 95}, /* 0x4b */
+ { 0x78,0x27,108}, /* 0x4c - was 102 */
+ { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+ { 0x41,0x4e, 21}, /* 0x4e */
+ { 0xa1,0x4a, 29}, /* 0x4f Chrontel */
+ { 0x19,0x42, 42}, /* 0x50 */
+ { 0x54,0x46, 58}, /* 0x51 Chrontel */
+ { 0x25,0x42, 61}, /* 0x52 */
+ { 0x44,0x44, 66}, /* 0x53 Chrontel */
+ { 0x3a,0x62, 70}, /* 0x54 Chrontel */
+ { 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+ { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+ { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+ { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+ { 0x52,0x07,149}, /* 0x59 1280x960-85 */
+ { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+ { 0x45,0x25, 83}, /* 0x5c 1280x800 */
+ { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+ { 0x70,0x24,162}, /* 0x5e 1600x1200 */
+ { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+ { 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+ { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+ { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */
+ { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+ { 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+ { 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+ { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+ { 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+ { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+ { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+ { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+ { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+ { 0x45,0x25, 83}, /* 0x6c 1280x800 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35} /* 0x71 768@576@60 */
+};
+
+void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
+unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
+int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 data);
+extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 *data);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand, u8 myor);
+extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+ u8 index, u8 myor);
+extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+ u8 idx, u8 myand);
+
+#endif
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 000000000000..94edd4726c42
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,169 @@
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * 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 named 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
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * 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.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_STRUCT_H_
+#define _SISUSB_STRUCT_H_
+
+struct SiS_St {
+ unsigned char St_ModeID;
+ unsigned short St_ModeFlag;
+ unsigned char St_StTableIndex;
+ unsigned char St_CRT2CRTC;
+ unsigned char St_ResInfo;
+ unsigned char VB_StTVFlickerIndex;
+ unsigned char VB_StTVEdgeIndex;
+ unsigned char VB_StTVYFilterIndex;
+ unsigned char St_PDC;
+};
+
+struct SiS_StandTable
+{
+ unsigned char CRT_COLS;
+ unsigned char ROWS;
+ unsigned char CHAR_HEIGHT;
+ unsigned short CRT_LEN;
+ unsigned char SR[4];
+ unsigned char MISC;
+ unsigned char CRTC[0x19];
+ unsigned char ATTR[0x14];
+ unsigned char GRC[9];
+};
+
+struct SiS_StResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+};
+
+struct SiS_Ext
+{
+ unsigned char Ext_ModeID;
+ unsigned short Ext_ModeFlag;
+ unsigned short Ext_VESAID;
+ unsigned char Ext_RESINFO;
+ unsigned char VB_ExtTVFlickerIndex;
+ unsigned char VB_ExtTVEdgeIndex;
+ unsigned char VB_ExtTVYFilterIndex;
+ unsigned char VB_ExtTVYFilterIndexROM661;
+ unsigned char REFindex;
+ char ROMMODEIDX661;
+};
+
+struct SiS_Ext2
+{
+ unsigned short Ext_InfoFlag;
+ unsigned char Ext_CRT1CRTC;
+ unsigned char Ext_CRTVCLK;
+ unsigned char Ext_CRT2CRTC;
+ unsigned char Ext_CRT2CRTC_NS;
+ unsigned char ModeID;
+ unsigned short XRes;
+ unsigned short YRes;
+ unsigned char Ext_PDC;
+ unsigned char Ext_FakeCRT2CRTC;
+ unsigned char Ext_FakeCRT2Clk;
+};
+
+struct SiS_CRT1Table
+{
+ unsigned char CR[17];
+};
+
+struct SiS_VCLKData
+{
+ unsigned char SR2B,SR2C;
+ unsigned short CLOCK;
+};
+
+struct SiS_ModeResInfo
+{
+ unsigned short HTotal;
+ unsigned short VTotal;
+ unsigned char XChar;
+ unsigned char YChar;
+};
+
+struct SiS_Private
+{
+ void *sisusb;
+
+ unsigned long IOAddress;
+
+ unsigned long SiS_P3c4;
+ unsigned long SiS_P3d4;
+ unsigned long SiS_P3c0;
+ unsigned long SiS_P3ce;
+ unsigned long SiS_P3c2;
+ unsigned long SiS_P3ca;
+ unsigned long SiS_P3c6;
+ unsigned long SiS_P3c7;
+ unsigned long SiS_P3c8;
+ unsigned long SiS_P3c9;
+ unsigned long SiS_P3cb;
+ unsigned long SiS_P3cc;
+ unsigned long SiS_P3cd;
+ unsigned long SiS_P3da;
+ unsigned long SiS_Part1Port;
+
+ unsigned char SiS_MyCR63;
+ unsigned short SiS_CRT1Mode;
+ unsigned short SiS_ModeType;
+ unsigned short SiS_SetFlag;
+
+ const struct SiS_StandTable *SiS_StandTable;
+ const struct SiS_St *SiS_SModeIDTable;
+ const struct SiS_Ext *SiS_EModeIDTable;
+ const struct SiS_Ext2 *SiS_RefIndex;
+ const struct SiS_CRT1Table *SiS_CRT1Table;
+ struct SiS_VCLKData *SiS_VCLKData;
+ const struct SiS_ModeResInfo *SiS_ModeResInfo;
+};
+
+#endif
+
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 096ab3029676..85f3725334b0 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -251,13 +251,12 @@ static struct file_operations lcd_fops = {
};
/*
- * * usb class driver info in order to get a minor number from the usb core,
- * * and to have the device registered with devfs and the driver core
- * */
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
static struct usb_class_driver lcd_class = {
- .name = "usb/lcd%d",
+ .name = "lcd%d",
.fops = &lcd_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
.minor_base = USBLCD_MINOR,
};
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index cda7249a90b2..2997f558159b 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -9,7 +9,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/usb.h>
@@ -381,7 +381,6 @@ alloc_sglist (int nents, int max, int vary)
sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL);
if (!sg)
return NULL;
- memset (sg, 0, nents * sizeof *sg);
for (i = 0; i < nents; i++) {
char *buf;
@@ -394,9 +393,7 @@ alloc_sglist (int nents, int max, int vary)
memset (buf, 0, size);
/* kmalloc pages are always physically contiguous! */
- sg [i].page = virt_to_page (buf);
- sg [i].offset = offset_in_page (buf);
- sg [i].length = size;
+ sg_init_one(&sg[i], buf, size);
if (vary) {
size += vary;
@@ -983,10 +980,10 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
reqp->number = i % NUM_SUBCASES;
reqp->expected = expected;
u->setup_packet = (char *) &reqp->setup;
+ u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
u->context = &context;
u->complete = ctrl_complete;
- u->transfer_flags |= URB_ASYNC_UNLINK;
}
/* queue the urbs */
@@ -1052,7 +1049,6 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
if (!urb)
return -ENOMEM;
- urb->transfer_flags |= URB_ASYNC_UNLINK;
urb->context = &completion;
urb->complete = unlink1_callback;
@@ -1533,7 +1529,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (down_interruptible (&dev->sem))
return -ERESTARTSYS;
- if (intf->dev.power.power_state != PMSG_ON) {
+ if (intf->dev.power.power_state.event != PM_EVENT_ON) {
up (&dev->sem);
return -EHOSTUNREACH;
}
@@ -1950,21 +1946,11 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
{
- struct usbtest_dev *dev = usb_get_intfdata (intf);
-
- down (&dev->sem);
- intf->dev.power.power_state = PMSG_SUSPEND;
- up (&dev->sem);
return 0;
}
static int usbtest_resume (struct usb_interface *intf)
{
- struct usbtest_dev *dev = usb_get_intfdata (intf);
-
- down (&dev->sem);
- intf->dev.power.power_state = PMSG_ON;
- up (&dev->sem);
return 0;
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index faa74436de52..0592cb5e6c4d 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -3,8 +3,8 @@
/*
* uss720.c -- USS720 USB Parport Cable.
*
- * Copyright (C) 1999
- * Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1999, 2005
+ * Thomas Sailer (t.sailer@alumni.ethz.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
@@ -23,103 +23,240 @@
* Based on parport_pc.c
*
* History:
- * 0.1 04.08.99 Created
- * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh
- * Interrupt handling currently disabled because
- * usb_request_irq crashes somewhere within ohci.c
- * for no apparent reason (that is for me, anyway)
- * ECP currently untested
- * 0.3 10.08.99 fixing merge errors
- * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable
- * 0.5 20.09.99 usb_control_msg wrapper used
- * Nov01.00 usb_device_table support by Adam J. Richter
- * 08.04.01 Identify version on module load. gb
+ * 0.1 04.08.1999 Created
+ * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh
+ * Interrupt handling currently disabled because
+ * usb_request_irq crashes somewhere within ohci.c
+ * for no apparent reason (that is for me, anyway)
+ * ECP currently untested
+ * 0.3 10.08.1999 fixing merge errors
+ * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable
+ * 0.5 20.09.1999 usb_control_msg wrapper used
+ * Nov01.2000 usb_device_table support by Adam J. Richter
+ * 08.04.2001 Identify version on module load. gb
+ * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore
+ * context asynchronous
*
*/
/*****************************************************************************/
+#define DEBUG
+
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/parport.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5"
-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_VERSION "v0.6"
+#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
/* --------------------------------------------------------------------- */
struct parport_uss720_private {
struct usb_device *usbdev;
- void *irqhandle;
- unsigned int irqpipe;
- unsigned char reg[7]; /* USB registers */
+ struct parport *pp;
+ struct kref ref_count;
+ __u8 reg[7]; /* USB registers */
+ struct list_head asynclist;
+ spinlock_t asynclock;
+};
+
+struct uss720_async_request {
+ struct parport_uss720_private *priv;
+ struct kref ref_count;
+ struct list_head asynclist;
+ struct completion compl;
+ struct urb *urb;
+ struct usb_ctrlrequest dr;
+ __u8 reg[7];
};
/* --------------------------------------------------------------------- */
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+static void destroy_priv(struct kref *kref)
{
- struct parport_uss720_private *priv = pp->private_data;
- struct usb_device *usbdev = priv->usbdev;
- static const unsigned char regindex[9] = {
- 4, 0, 1, 5, 5, 0, 2, 3, 6
- };
- int ret;
+ struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
- if (!usbdev)
- return -1;
- ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
- if (ret != 7) {
- printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
- (unsigned int)reg, ret);
- ret = -1;
- } else {
+ usb_put_dev(priv->usbdev);
+ kfree(priv);
+ dbg("destroying priv datastructure");
+}
+
+static void destroy_async(struct kref *kref)
+{
+ struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
+ struct parport_uss720_private *priv = rq->priv;
+ unsigned long flags;
+
+ if (likely(rq->urb))
+ usb_free_urb(rq->urb);
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_del_init(&rq->asynclist);
+ spin_unlock_irqrestore(&priv->asynclock, flags);
+ kfree(rq);
+ kref_put(&priv->ref_count, destroy_priv);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+ struct uss720_async_request *rq;
+ struct parport *pp;
+ struct parport_uss720_private *priv;
+
+ rq = urb->context;
+ priv = rq->priv;
+ pp = priv->pp;
+ if (urb->status) {
+ err("async_complete: urb error %d", urb->status);
+ } else if (rq->dr.bRequest == 3) {
+ memcpy(priv->reg, rq->reg, sizeof(priv->reg));
#if 0
- printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
- (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
- (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
- (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
+ dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
+ (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
+ (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
+ (unsigned int)priv->reg[6]);
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
- if (priv->reg[2] & priv->reg[1] & 0x10)
+ if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
parport_generic_irq(0, pp, NULL);
- ret = 0;
}
- if (val)
- *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
- return ret;
+ complete(&rq->compl);
+ kref_put(&rq->ref_count, destroy_async);
}
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
+ gfp_t mem_flags)
{
- struct parport_uss720_private *priv = pp->private_data;
- struct usb_device *usbdev = priv->usbdev;
+ struct usb_device *usbdev;
+ struct uss720_async_request *rq;
+ unsigned long flags;
int ret;
+ if (!priv)
+ return NULL;
+ usbdev = priv->usbdev;
if (!usbdev)
- return -1;
- ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
- if (ret) {
- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n",
- (unsigned int)reg, (unsigned int)val, ret);
- } else {
-#if 0
- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n",
- (unsigned int)reg, (unsigned int)val);
-#endif
+ return NULL;
+ rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
+ if (!rq) {
+ err("submit_async_request out of memory");
+ return NULL;
+ }
+ kref_init(&rq->ref_count);
+ INIT_LIST_HEAD(&rq->asynclist);
+ init_completion(&rq->compl);
+ kref_get(&priv->ref_count);
+ rq->priv = priv;
+ rq->urb = usb_alloc_urb(0, mem_flags);
+ if (!rq->urb) {
+ kref_put(&rq->ref_count, destroy_async);
+ err("submit_async_request out of memory");
+ return NULL;
+ }
+ rq->dr.bRequestType = requesttype;
+ rq->dr.bRequest = request;
+ rq->dr.wValue = cpu_to_le16(value);
+ rq->dr.wIndex = cpu_to_le16(index);
+ rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
+ usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
+ (unsigned char *)&rq->dr,
+ (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
+ /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_add_tail(&rq->asynclist, &priv->asynclist);
+ spin_unlock_irqrestore(&priv->asynclock, flags);
+ ret = usb_submit_urb(rq->urb, mem_flags);
+ if (!ret) {
+ kref_get(&rq->ref_count);
+ return rq;
}
+ kref_put(&rq->ref_count, destroy_async);
+ err("submit_async_request submit_urb failed with %d", ret);
+ return NULL;
+}
+
+static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
+{
+ struct uss720_async_request *rq;
+ unsigned long flags;
+ unsigned int ret = 0;
+
+ spin_lock_irqsave(&priv->asynclock, flags);
+ list_for_each_entry(rq, &priv->asynclist, asynclist) {
+ usb_unlink_urb(rq->urb);
+ ret++;
+ }
+ spin_unlock_irqrestore(&priv->asynclock, flags);
return ret;
}
/* --------------------------------------------------------------------- */
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags)
+{
+ struct parport_uss720_private *priv;
+ struct uss720_async_request *rq;
+ static const unsigned char regindex[9] = {
+ 4, 0, 1, 5, 5, 0, 2, 3, 6
+ };
+ int ret;
+
+ if (!pp)
+ return -EIO;
+ priv = pp->private_data;
+ rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
+ if (!rq) {
+ err("get_1284_register(%u) failed", (unsigned int)reg);
+ return -EIO;
+ }
+ if (!val) {
+ kref_put(&rq->ref_count, destroy_async);
+ return 0;
+ }
+ if (wait_for_completion_timeout(&rq->compl, HZ)) {
+ ret = rq->urb->status;
+ *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
+ if (ret)
+ warn("get_1284_register: usb error %d", ret);
+ kref_put(&rq->ref_count, destroy_async);
+ return ret;
+ }
+ warn("get_1284_register timeout");
+ kill_all_async_requests_priv(priv);
+ return -EIO;
+}
+
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags)
+{
+ struct parport_uss720_private *priv;
+ struct uss720_async_request *rq;
+
+ if (!pp)
+ return -EIO;
+ priv = pp->private_data;
+ rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
+ if (!rq) {
+ err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
+ return -EIO;
+ }
+ kref_put(&rq->ref_count, destroy_async);
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
/* ECR modes */
#define ECR_SPP 00
#define ECR_PS2 01
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
{
struct parport_uss720_private *priv = pp->private_data;
int mode;
+ __u8 reg;
- if (get_1284_register(pp, 6, NULL))
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
/* Bits <7:5> contain the mode. */
mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
case ECR_ECP: /* ECP Parallel Port mode */
/* Poll slowly. */
for (;;) {
- if (get_1284_register(pp, 6, NULL))
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
if (priv->reg[2] & 0x01)
break;
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
}
}
/* Set the mode. */
- if (set_1284_register(pp, 6, m << 5))
+ if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
+ return -EIO;
+ if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
return -EIO;
return 0;
}
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
{
unsigned char stat;
- if (get_1284_register(pp, 1, &stat))
+ if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
return 1;
return stat & 1;
}
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
static void parport_uss720_write_data(struct parport *pp, unsigned char d)
{
- set_1284_register(pp, 0, d);
+ set_1284_register(pp, 0, d, GFP_KERNEL);
}
static unsigned char parport_uss720_read_data(struct parport *pp)
{
unsigned char ret;
- if (get_1284_register(pp, 0, &ret))
+ if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
return 0;
return ret;
}
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
struct parport_uss720_private *priv = pp->private_data;
d = (d & 0xf) | (priv->reg[1] & 0xf0);
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
mask &= 0x0f;
val &= 0x0f;
d = (priv->reg[1] & (~mask)) ^ val;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return 0;
priv->reg[1] = d;
return d & 0xf;
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
{
unsigned char ret;
- if (get_1284_register(pp, 1, &ret))
+ if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
return 0;
return ret & 0xf8;
}
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
unsigned char d;
d = priv->reg[1] & ~0x10;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
unsigned char d;
d = priv->reg[1] | 0x10;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
unsigned char d;
d = priv->reg[1] & ~0x20;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
unsigned char d;
d = priv->reg[1] | 0x20;
- if (set_1284_register(pp, 2, d))
+ if (set_1284_register(pp, 2, d, GFP_KERNEL))
return;
priv->reg[1] = d;
}
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
{
struct parport_uss720_private *priv = pp->private_data;
- if (get_1284_register(pp, 2, NULL))
+#if 0
+ if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
return;
+#endif
s->u.pc.ctr = priv->reg[1];
s->u.pc.ecr = priv->reg[2];
}
static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
{
- set_1284_register(pp, 2, s->u.pc.ctr);
- set_1284_register(pp, 6, s->u.pc.ecr);
- get_1284_register(pp, 2, NULL);
+ struct parport_uss720_private *priv = pp->private_data;
+
+ set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
+ set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
+ get_1284_register(pp, 2, NULL, GFP_ATOMIC);
+ priv->reg[1] = s->u.pc.ctr;
+ priv->reg[2] = s->u.pc.ecr;
}
static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
- if (get_1284_register(pp, 4, (char *)buf))
+ if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
break;
buf++;
if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
- if (set_1284_register(pp, 4, (char *)buf))
+ if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
break;
((char*)buf)++;
- if (get_1284_register(pp, 1, NULL))
+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
if (change_mode(pp, ECR_EPP))
return 0;
for (; got < length; got++) {
- if (get_1284_register(pp, 3, (char *)buf))
+ if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
break;
buf++;
if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
- if (set_1284_register(pp, 3, *(char *)buf))
+ if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
break;
buf++;
- if (get_1284_register(pp, 1, NULL))
+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
if (change_mode(pp, ECR_ECP))
return 0;
for (; written < len; written++) {
- if (set_1284_register(pp, 5, *(char *)buffer))
+ if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
break;
buffer++;
}
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
static int uss720_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct usb_device *usbdev = interface_to_usbdev(intf);
+ struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
struct usb_host_interface *interface;
struct usb_host_endpoint *endpoint;
struct parport_uss720_private *priv;
struct parport *pp;
+ unsigned char reg;
int i;
- printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
- le16_to_cpu(usbdev->descriptor.idVendor),
- le16_to_cpu(usbdev->descriptor.idProduct));
+ dbg("probe: vendor id 0x%x, device id 0x%x\n",
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct));
/* our known interfaces have 3 alternate settings */
- if (intf->num_altsetting != 3)
+ if (intf->num_altsetting != 3) {
+ usb_put_dev(usbdev);
return -ENODEV;
-
+ }
i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
- printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+ dbg("set inteface result %d", i);
interface = intf->cur_altsetting;
/*
* Allocate parport interface
*/
- printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
-
- if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+ if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+ usb_put_dev(usbdev);
return -ENOMEM;
+ }
+ priv->pp = NULL;
+ priv->usbdev = usbdev;
+ kref_init(&priv->ref_count);
+ 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))) {
- printk(KERN_WARNING "usb-uss720: could not register parport\n");
+ warn("could not register parport");
goto probe_abort;
}
+ priv->pp = pp;
pp->private_data = priv;
- priv->usbdev = usbdev;
pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
- set_1284_register(pp, 7, 0x00);
- set_1284_register(pp, 6, 0x30); /* PS/2 mode */
- set_1284_register(pp, 2, 0x0c);
+ set_1284_register(pp, 7, 0x00, GFP_KERNEL);
+ set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */
+ set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
/* debugging */
- get_1284_register(pp, 0, NULL);
- printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
- priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+ get_1284_register(pp, 0, &reg, GFP_KERNEL);
+ dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
+ priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
endpoint = &interface->endpoint[2];
- printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
-#if 0
- priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
- i = usb_request_irq(usbdev, priv->irqpipe,
- uss720_irq, endpoint->bInterval,
- pp, &priv->irqhandle);
- if (i) {
- printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
- goto probe_abort_port;
- }
-#endif
+ dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
parport_announce_port(pp);
- usb_set_intfdata (intf, pp);
+ usb_set_intfdata(intf, pp);
return 0;
-#if 0
-probe_abort_port:
- parport_put_port(pp);
-#endif
probe_abort:
- kfree(priv);
+ kill_all_async_requests_priv(priv);
+ kref_put(&priv->ref_count, destroy_priv);
return -ENODEV;
}
static void uss720_disconnect(struct usb_interface *intf)
{
- struct parport *pp = usb_get_intfdata (intf);
+ struct parport *pp = usb_get_intfdata(intf);
struct parport_uss720_private *priv;
+ struct usb_device *usbdev;
- usb_set_intfdata (intf, NULL);
+ dbg("disconnect");
+ usb_set_intfdata(intf, NULL);
if (pp) {
priv = pp->private_data;
- parport_remove_port(pp);
-#if 0
- usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
+ usbdev = priv->usbdev;
priv->usbdev = NULL;
+ priv->pp = NULL;
+ dbg("parport_remove_port");
+ parport_remove_port(pp);
parport_put_port(pp);
- kfree(priv);
+ kill_all_async_requests_priv(priv);
+ kref_put(&priv->ref_count, destroy_priv);
}
+ dbg("disconnect done");
}
/* table of cables that work through this driver */
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
/* --------------------------------------------------------------------- */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static int __init uss720_init(void)
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
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");
out:
return retval;
}
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 777642e26b9a..deb9ddffa402 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -9,9 +9,8 @@ config USB_MON
help
If you say Y here, a component which captures the USB traffic
between peripheral-specific drivers and HC drivers will be built.
- The USB_MON is similar in spirit and may be compatible with Dave
- Harding's USBMon.
+ For more information, see <file:Documentation/usb/usbmon.txt>.
- This is somewhat experimental at this time, but it should be safe,
- as long as you aren't using modular USB and try to remove this
- module.
+ This is somewhat experimental at this time, but it should be safe.
+
+ If unsure, say Y.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index f18d10ce91f9..3cf3ea3a88ed 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -2,6 +2,7 @@
# Makefile for USB Core files and filesystem
#
-usbmon-objs := mon_main.o mon_stat.o mon_text.o
+usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_dma.o
+# This does not use CONFIG_USB_MON because we want this to use a tristate.
obj-$(CONFIG_USB) += usbmon.o
diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c
new file mode 100644
index 000000000000..0a1367b760a0
--- /dev/null
+++ b/drivers/usb/mon/mon_dma.c
@@ -0,0 +1,55 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * mon_dma.c: Library which snoops on DMA areas.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
+ */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+
+#include <linux/usb.h> /* Only needed for declarations in usb_mon.h */
+#include "usb_mon.h"
+
+#ifdef __i386__ /* CONFIG_ARCH_I386 does not exit */
+#define MON_HAS_UNMAP 1
+
+#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
+
+char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+{
+ struct page *pg;
+ unsigned long flags;
+ unsigned char *map;
+ unsigned char *ptr;
+
+ /*
+ * On i386, a DMA handle is the "physical" address of a page.
+ * In other words, the bus address is equal to physical address.
+ * There is no IOMMU.
+ */
+ pg = phys_to_page(dma_addr);
+
+ /*
+ * We are called from hardware IRQs in case of callbacks.
+ * But we can be called from softirq or process context in case
+ * of submissions. In such case, we need to protect KM_IRQ0.
+ */
+ local_irq_save(flags);
+ map = kmap_atomic(pg, KM_IRQ0);
+ ptr = map + (dma_addr & (PAGE_SIZE-1));
+ memcpy(dst, ptr, len);
+ kunmap_atomic(map, KM_IRQ0);
+ local_irq_restore(flags);
+ return 0;
+}
+#endif /* __i386__ */
+
+#ifndef MON_HAS_UNMAP
+char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+{
+ return 'D';
+}
+#endif
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index aa9d00808e4e..c34944c75047 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -2,6 +2,8 @@
* The USB Monitor, inspired by Dave Harding's USBMon.
*
* mon_main.c: Main file, module initiation and exit, registrations, etc.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
*/
#include <linux/kernel.h>
@@ -9,6 +11,7 @@
#include <linux/usb.h>
#include <linux/debugfs.h>
#include <linux/smp_lock.h>
+#include <linux/notifier.h>
#include "usb_mon.h"
#include "../core/hcd.h"
@@ -203,6 +206,23 @@ static void mon_bus_remove(struct usb_bus *ubus)
up(&mon_lock);
}
+static int mon_notify(struct notifier_block *self, unsigned long action,
+ void *dev)
+{
+ switch (action) {
+ case USB_BUS_ADD:
+ mon_bus_add(dev);
+ break;
+ case USB_BUS_REMOVE:
+ mon_bus_remove(dev);
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block mon_nb = {
+ .notifier_call = mon_notify,
+};
+
/*
* Ops
*/
@@ -210,8 +230,6 @@ static struct usb_mon_operations mon_ops_0 = {
.urb_submit = mon_submit,
.urb_submit_error = mon_submit_error,
.urb_complete = mon_complete,
- .bus_add = mon_bus_add,
- .bus_remove = mon_bus_remove,
};
/*
@@ -311,7 +329,7 @@ static int __init mon_init(void)
mondir = debugfs_create_dir("usbmon", NULL);
if (IS_ERR(mondir)) {
- printk(KERN_NOTICE TAG ": debugs is not available\n");
+ printk(KERN_NOTICE TAG ": debugfs is not available\n");
return -ENODEV;
}
if (mondir == NULL) {
@@ -327,6 +345,8 @@ static int __init mon_init(void)
}
// MOD_INC_USE_COUNT(which_module?);
+ usb_register_notify(&mon_nb);
+
down(&usb_bus_list_lock);
list_for_each_entry (ubus, &usb_bus_list, bus_list) {
mon_bus_init(mondir, ubus);
@@ -340,6 +360,7 @@ static void __exit mon_exit(void)
struct mon_bus *mbus;
struct list_head *p;
+ usb_unregister_notify(&mon_nb);
usb_mon_deregister();
down(&mon_lock);
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 26266b30028e..17d0190ef64e 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -79,7 +79,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
return '-';
if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
- return 'D';
+ return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
if (urb->setup_packet == NULL)
return 'Z'; /* '0' would be not as pretty. */
@@ -91,25 +91,11 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
int len, char ev_type)
{
int pipe = urb->pipe;
- unsigned char *data;
-
- /*
- * The check to see if it's safe to poke at data has an enormous
- * number of corner cases, but it seems that the following is
- * more or less safe.
- *
- * We do not even try to look transfer_buffer, because it can
- * contain non-NULL garbage in case the upper level promised to
- * set DMA for the HCD.
- */
- if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
- return 'D';
if (len <= 0)
return 'L';
-
- if ((data = urb->transfer_buffer) == NULL)
- return 'Z'; /* '0' would be not as pretty. */
+ if (len >= DATA_MAX)
+ len = DATA_MAX;
/*
* Bulk is easy to shortcut reliably.
@@ -126,8 +112,21 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
}
}
- if (len >= DATA_MAX)
- len = DATA_MAX;
+ /*
+ * The check to see if it's safe to poke at data has an enormous
+ * number of corner cases, but it seems that the following is
+ * more or less safe.
+ *
+ * We do not even try to look transfer_buffer, because it can
+ * contain non-NULL garbage in case the upper level promised to
+ * set DMA for the HCD.
+ */
+ if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+ return mon_dmapeek(ep->data, urb->transfer_dma, len);
+
+ if (urb->transfer_buffer == NULL)
+ return 'Z'; /* '0' would be not as pretty. */
+
memcpy(ep->data, urb->transfer_buffer, len);
return 0;
}
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index ed35c18a5c44..4be0f9346071 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -1,5 +1,7 @@
/*
* The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
*/
#ifndef __USB_MON_H
@@ -43,6 +45,10 @@ struct mon_reader {
void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r);
void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
+/*
+ */
+extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
+
extern struct semaphore mon_lock;
extern struct file_operations mon_fops_text;
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index b104430e2c6a..efd6ca7e4ac5 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -99,7 +99,7 @@ config USB_USBNET
with "minidrivers" built around a common network driver core
that supports deep queues for efficient transfers. (This gives
better performance with small packets and at high speeds).
-
+
The USB host runs "usbnet", and the other end of the link might be:
- Another USB host, when using USB "network" or "data transfer"
@@ -125,38 +125,63 @@ config USB_USBNET
To compile this driver as a module, choose M here: the
module will be called usbnet.
-comment "USB Host-to-Host Cables"
- depends on USB_USBNET
-
-config USB_ALI_M5632
- boolean "ALi M5632 based 'USB 2.0 Data Link' cables"
- depends on USB_USBNET
+config USB_NET_AX8817X
+ tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
+ depends on USB_USBNET && NET_ETHERNET
+ select CRC32
+ select MII
default y
help
- Choose this option if you're using a host-to-host cable
- based on this design, which supports USB 2.0 high speed.
+ This option adds support for ASIX AX88xxx based USB 2.0
+ 10/100 Ethernet adapters.
-config USB_AN2720
- boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
- depends on USB_USBNET
- default y
- help
- Choose this option if you're using a host-to-host cable
- based on this design. Note that AnchorChips is now a
- Cypress brand.
+ This driver should work with at least the following devices:
+ * Aten UC210T
+ * ASIX AX88172
+ * Billionton Systems, USB2AR
+ * Buffalo LUA-U2-KTX
+ * Corega FEther USB2-TX
+ * D-Link DUB-E100
+ * Hawking UF200
+ * Linksys USB200M
+ * Netgear FA120
+ * Sitecom LN-029
+ * Intellinet USB 2.0 Ethernet
+ * ST Lab USB 2.0 Ethernet
+ * TrendNet TU2-ET100
-config USB_BELKIN
- boolean "eTEK based host-to-host cables (Advance, Belkin, ...)"
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use.
+
+
+config USB_NET_CDCETHER
+ tristate "CDC Ethernet support (smart devices such as cable modems)"
depends on USB_USBNET
default y
help
- Choose this option if you're using a host-to-host cable
- based on this design: two NetChip 2890 chips and an Atmel
- microcontroller, with LEDs that indicate traffic.
+ This option supports devices conforming to the Communication Device
+ Class (CDC) Ethernet Control Model, a specification that's easy to
+ implement in device firmware. The CDC specifications are available
+ from <http://www.usb.org/>.
-config USB_GENESYS
- boolean "GeneSys GL620USB-A based cables"
- default y
+ CDC Ethernet is an implementation option for DOCSIS cable modems
+ that support USB connectivity, used for non-Microsoft USB hosts.
+ The Linux-USB CDC Ethernet Gadget driver is an open implementation.
+ This driver should work with at least the following devices:
+
+ * Ericsson PipeRider (all variants)
+ * Motorola (DM100 and SB4100)
+ * Broadcom Cable Modem (reference design)
+ * Toshiba PCX1100U
+ * ...
+
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use. However, if the
+ IEEE 802 "local assignment" bit is set in the address, a "usbX"
+ name is used instead.
+
+config USB_NET_GL620A
+ tristate "GeneSys GL620USB-A based cables"
depends on USB_USBNET
help
Choose this option if you're using a host-to-host cable,
@@ -164,38 +189,78 @@ config USB_GENESYS
Note that the half-duplex "GL620USB" is not supported.
-config USB_NET1080
- boolean "NetChip 1080 based cables (Laplink, ...)"
+config USB_NET_NET1080
+ tristate "NetChip 1080 based cables (Laplink, ...)"
default y
depends on USB_USBNET
help
Choose this option if you're using a host-to-host cable based
- on this design: one NetChip 1080 chips and supporting logic,
- supporting LEDs that indicate traffic
+ on this design: one NetChip 1080 chip and supporting logic,
+ optionally with LEDs that indicate traffic
-config USB_PL2301
- boolean "Prolific PL-2301/2302 based cables"
- default y
- # handshake/init/reset problems, from original 'plusb' driver
+config USB_NET_PLUSB
+ tristate "Prolific PL-2301/2302 based cables"
+ # if the handshake/init/reset problems, from original 'plusb',
+ # are ever resolved ... then remove "experimental"
depends on USB_USBNET && EXPERIMENTAL
help
Choose this option if you're using a host-to-host cable
with one of these chips.
-config USB_KC2190
- boolean "KT Technology KC2190 based cables (InstaNet)"
- default y
+config USB_NET_RNDIS_HOST
+ tristate "Host for RNDIS devices (EXPERIMENTAL)"
depends on USB_USBNET && EXPERIMENTAL
+ select USB_NET_CDCETHER
help
- Choose this option if you're using a host-to-host cable
- with one of these chips.
+ This option enables hosting "Remote NDIS" USB networking links,
+ as encouraged by Microsoft (instead of CDC Ethernet!) for use in
+ various devices that may only support this protocol.
-comment "Intelligent USB Devices/Gadgets"
+ Avoid using this protocol unless you have no better options.
+ The protocol specification is incomplete, and is controlled by
+ (and for) Microsoft; it isn't an "Open" ecosystem or market.
+
+config USB_NET_CDC_SUBSET
+ tristate "Simple USB Network Links (CDC Ethernet subset)"
depends on USB_USBNET
+ help
+ This driver module supports USB network devices that can work
+ without any device-specific information. Select it if you have
+ one of these drivers.
+
+ Note that while many USB host-to-host cables can work in this mode,
+ that may mean not being able to talk to Win32 systems or more
+ commonly not being able to handle certain events (like replugging
+ the host on the other end) very well. Also, these devices will
+ not generally have permanently assigned Ethernet addresses.
+
+config USB_ALI_M5632
+ boolean "ALi M5632 based 'USB 2.0 Data Link' cables"
+ depends on USB_NET_CDC_SUBSET
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design, which supports USB 2.0 high speed.
+
+config USB_AN2720
+ boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
+ depends on USB_NET_CDC_SUBSET
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design. Note that AnchorChips is now a
+ Cypress brand.
+
+config USB_BELKIN
+ boolean "eTEK based host-to-host cables (Advance, Belkin, ...)"
+ depends on USB_NET_CDC_SUBSET
+ default y
+ help
+ Choose this option if you're using a host-to-host cable
+ based on this design: two NetChip 2890 chips and an Atmel
+ microcontroller, with LEDs that indicate traffic.
config USB_ARMLINUX
boolean "Embedded ARM Linux links (iPaq, ...)"
- depends on USB_USBNET
+ depends on USB_NET_CDC_SUBSET
default y
help
Choose this option to support the "usb-eth" networking driver
@@ -212,15 +277,15 @@ config USB_ARMLINUX
config USB_EPSON2888
boolean "Epson 2888 based firmware (DEVELOPMENT)"
- depends on USB_USBNET
- default y
+ depends on USB_NET_CDC_SUBSET
help
Choose this option to support the usb networking links used
by some sample firmware from Epson.
-config USB_ZAURUS
- boolean "Sharp Zaurus (stock ROMs) and compatible"
+config USB_NET_ZAURUS
+ tristate "Sharp Zaurus (stock ROMs) and compatible"
depends on USB_USBNET
+ select USB_NET_CDCETHER
select CRC32
default y
help
@@ -229,67 +294,12 @@ config USB_ZAURUS
This also supports some related device firmware, as used in some
PDAs from Olympus and some cell phones from Motorola.
- If you install an alternate ROM image, such as the Linux 2.6 based
+ If you install an alternate image, such as the Linux 2.6 based
versions of OpenZaurus, you should no longer need to support this
protocol. Only the "eth-fd" or "net_fd" drivers in these devices
really need this non-conformant variant of CDC Ethernet (or in
some cases CDC MDLM) protocol, not "g_ether".
-config USB_CDCETHER
- boolean "CDC Ethernet support (smart devices such as cable modems)"
- depends on USB_USBNET
- default y
- help
- This option supports devices conforming to the Communication Device
- Class (CDC) Ethernet Control Model, a specification that's easy to
- implement in device firmware. The CDC specifications are available
- from <http://www.usb.org/>.
-
- CDC Ethernet is an implementation option for DOCSIS cable modems
- that support USB connectivity, used for non-Microsoft USB hosts.
- This driver should work with at least the following devices:
-
- * Ericsson PipeRider (all variants)
- * Motorola (DM100 and SB4100)
- * Broadcom Cable Modem (reference design)
- * Toshiba PCX1100U
- * ...
-
- This driver creates an interface named "ethX", where X depends on
- what other networking devices you have in use. However, if the
- IEEE 802 "local assignment" bit is set in the address, a "usbX"
- name is used instead.
-
-comment "USB Network Adapters"
- depends on USB_USBNET
-
-config USB_AX8817X
- boolean "ASIX AX88xxx Based USB 2.0 Ethernet Devices"
- depends on USB_USBNET && NET_ETHERNET
- select CRC32
- select MII
- default y
- help
- This option adds support for ASIX AX88xxx based USB 2.0
- 10/100 Ethernet devices.
-
- This driver should work with at least the following devices:
- * Aten UC210T
- * ASIX AX88172
- * Billionton Systems, USB2AR
- * Buffalo LUA-U2-KTX
- * Corega FEther USB2-TX
- * D-Link DUB-E100
- * Hawking UF200
- * Linksys USB200M
- * Netgear FA120
- * Sitecom LN-029
- * Intellinet USB 2.0 Ethernet
- * ST Lab USB 2.0 Ethernet
- * TrendNet TU2-ET100
-
- This driver creates an interface named "ethX", where X depends on
- what other networking devices you have in use.
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 16f352195512..222c0495f791 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -6,7 +6,13 @@ obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_RTL8150) += rtl8150.o
+obj-$(CONFIG_USB_NET_AX8817X) += asix.o
+obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
+obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
+obj-$(CONFIG_USB_NET_NET1080) += net1080.o
+obj-$(CONFIG_USB_NET_PLUSB) += plusb.o
+obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o
+obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o
+obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
-
-CFLAGS_zd1201.o = -Idrivers/net/wireless/
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
new file mode 100644
index 000000000000..252a34fbb42c
--- /dev/null
+++ b/drivers/usb/net/asix.c
@@ -0,0 +1,948 @@
+/*
+ * ASIX AX8817X based USB 2.0 Ethernet Devices
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (c) 2002-2003 TiVo Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+
+#include "usbnet.h"
+
+
+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
+
+#define AX_CMD_SET_SW_MII 0x06
+#define AX_CMD_READ_MII_REG 0x07
+#define AX_CMD_WRITE_MII_REG 0x08
+#define AX_CMD_SET_HW_MII 0x0a
+#define AX_CMD_READ_EEPROM 0x0b
+#define AX_CMD_WRITE_EEPROM 0x0c
+#define AX_CMD_WRITE_ENABLE 0x0d
+#define AX_CMD_WRITE_DISABLE 0x0e
+#define AX_CMD_WRITE_RX_CTL 0x10
+#define AX_CMD_READ_IPG012 0x11
+#define AX_CMD_WRITE_IPG0 0x12
+#define AX_CMD_WRITE_IPG1 0x13
+#define AX_CMD_WRITE_IPG2 0x14
+#define AX_CMD_WRITE_MULTI_FILTER 0x16
+#define AX_CMD_READ_NODE_ID 0x17
+#define AX_CMD_READ_PHY_ID 0x19
+#define AX_CMD_READ_MEDIUM_STATUS 0x1a
+#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
+#define AX_CMD_READ_MONITOR_MODE 0x1c
+#define AX_CMD_WRITE_MONITOR_MODE 0x1d
+#define AX_CMD_WRITE_GPIOS 0x1f
+#define AX_CMD_SW_RESET 0x20
+#define AX_CMD_SW_PHY_STATUS 0x21
+#define AX_CMD_SW_PHY_SELECT 0x22
+#define AX88772_CMD_READ_NODE_ID 0x13
+
+#define AX_MONITOR_MODE 0x01
+#define AX_MONITOR_LINK 0x02
+#define AX_MONITOR_MAGIC 0x04
+#define AX_MONITOR_HSFS 0x10
+
+/* AX88172 Medium Status Register values */
+#define AX_MEDIUM_FULL_DUPLEX 0x02
+#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
+#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
+
+#define AX_MCAST_FILTER_SIZE 8
+#define AX_MAX_MCAST 64
+
+#define AX_EEPROM_LEN 0x40
+
+#define AX_SWRESET_CLEAR 0x00
+#define AX_SWRESET_RR 0x01
+#define AX_SWRESET_RT 0x02
+#define AX_SWRESET_PRTE 0x04
+#define AX_SWRESET_PRL 0x08
+#define AX_SWRESET_BZ 0x10
+#define AX_SWRESET_IPRL 0x20
+#define AX_SWRESET_IPPD 0x40
+
+#define AX88772_IPG0_DEFAULT 0x15
+#define AX88772_IPG1_DEFAULT 0x0c
+#define AX88772_IPG2_DEFAULT 0x12
+
+#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
+#define AX88772_MEDIUM_RESERVED 0x0004
+#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
+#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
+#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
+#define AX88772_MEDIUM_RX_ENABLE 0x0100
+#define AX88772_MEDIUM_100MB 0x0200
+#define AX88772_MEDIUM_DEFAULT \
+ (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
+ AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
+ AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+
+#define AX_EEPROM_MAGIC 0xdeadbeef
+
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
+struct ax8817x_data {
+ u8 multi_filter[AX_MCAST_FILTER_SIZE];
+};
+
+struct ax88172_int_data {
+ u16 res1;
+ u8 link;
+ u16 res2;
+ u8 status;
+ u16 res3;
+} __attribute__ ((packed));
+
+static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ return usb_control_msg(
+ dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ cmd,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ index,
+ data,
+ size,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ return usb_control_msg(
+ dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ cmd,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ index,
+ data,
+ size,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+
+ if (urb->status < 0)
+ printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
+ urb->status);
+
+ kfree(req);
+ usb_free_urb(urb);
+}
+
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+{
+ struct ax88172_int_data *event;
+ int link;
+
+ if (urb->actual_length < 8)
+ return;
+
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link) {
+ netif_carrier_on(dev->net);
+ usbnet_defer_kevent (dev, EVENT_LINK_RESET );
+ } else
+ netif_carrier_off(dev->net);
+ devdbg(dev, "ax8817x - Link Status is: %d", link);
+ }
+}
+
+static void
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ struct usb_ctrlrequest *req;
+ int status;
+ struct urb *urb;
+
+ if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+ devdbg(dev, "Error allocating URB in write_cmd_async!");
+ return;
+ }
+
+ if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+ deverr(dev, "Failed to allocate memory for control request");
+ usb_free_urb(urb);
+ return;
+ }
+
+ req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+ req->bRequest = cmd;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
+
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (void *)req, data, size,
+ ax8817x_async_cmd_callback, req);
+
+ if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ deverr(dev, "Error submitting the control message: status=%d",
+ status);
+ kfree(req);
+ usb_free_urb(urb);
+ }
+}
+
+static void ax8817x_set_multicast(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ u8 rx_ctl = 0x8c;
+
+ if (net->flags & IFF_PROMISC) {
+ rx_ctl |= 0x01;
+ } else if (net->flags & IFF_ALLMULTI
+ || net->mc_count > AX_MAX_MCAST) {
+ rx_ctl |= 0x02;
+ } else if (net->mc_count == 0) {
+ /* just broadcast and directed */
+ } else {
+ /* We use the 20 byte dev->data
+ * for our 8 byte filter buffer
+ * to avoid allocating memory that
+ * is tricky to free later */
+ struct dev_mc_list *mc_list = net->mc_list;
+ u32 crc_bits;
+ int i;
+
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+ /* Build the multicast hash filter. */
+ for (i = 0; i < net->mc_count; i++) {
+ crc_bits =
+ ether_crc(ETH_ALEN,
+ mc_list->dmi_addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ mc_list = mc_list->next;
+ }
+
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
+
+ rx_ctl |= 0x10;
+ }
+
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u16 res;
+ u8 buf[1];
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+ (__u16)loc, 2, (u16 *)&res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+
+ return res & 0xffff;
+}
+
+/* same as above, but converts resulting value to cpu byte order */
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+{
+ return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+}
+
+static void
+ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u16 res = val;
+ u8 buf[1];
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ (__u16)loc, 2, (u16 *)&res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+}
+
+/* same as above, but converts new value to le16 byte order before writing */
+static void
+ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+ u16 lpa;
+ u16 adv;
+ u16 res;
+ u8 mode;
+
+ mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ res = mii_nway_result(lpa|adv);
+ if (res & LPA_DUPLEX)
+ mode |= AX_MEDIUM_FULL_DUPLEX;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+
+ return 0;
+}
+
+static void
+ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ u8 opt;
+
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
+ return;
+ }
+ wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
+ wolinfo->wolopts = 0;
+ if (opt & AX_MONITOR_MODE) {
+ if (opt & AX_MONITOR_LINK)
+ wolinfo->wolopts |= WAKE_PHY;
+ if (opt & AX_MONITOR_MAGIC)
+ wolinfo->wolopts |= WAKE_MAGIC;
+ }
+}
+
+static int
+ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ u8 opt = 0;
+ u8 buf[1];
+
+ if (wolinfo->wolopts & WAKE_PHY)
+ opt |= AX_MONITOR_LINK;
+ if (wolinfo->wolopts & WAKE_MAGIC)
+ opt |= AX_MONITOR_MAGIC;
+ if (opt != 0)
+ opt |= AX_MONITOR_MODE;
+
+ if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
+ opt, 0, 0, &buf) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ax8817x_get_eeprom_len(struct net_device *net)
+{
+ return AX_EEPROM_LEN;
+}
+
+static int ax8817x_get_eeprom(struct net_device *net,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct usbnet *dev = netdev_priv(net);
+ u16 *ebuf = (u16 *)data;
+ int i;
+
+ /* Crude hack to ensure that we don't overwrite memory
+ * if an odd length is supplied
+ */
+ if (eeprom->len % 2)
+ return -EINVAL;
+
+ eeprom->magic = AX_EEPROM_MAGIC;
+
+ /* ax8817x returns 2 bytes from eeprom on read */
+ for (i=0; i < eeprom->len / 2; i++) {
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+ eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void ax8817x_get_drvinfo (struct net_device *net,
+ struct ethtool_drvinfo *info)
+{
+ /* Inherit standard device info */
+ usbnet_get_drvinfo(net, info);
+ info->eedump_len = 0x3e;
+}
+
+static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return mii_ethtool_gset(&dev->mii,cmd);
+}
+
+static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return mii_ethtool_sset(&dev->mii,cmd);
+}
+
+/* We need to override some ethtool_ops so we require our
+ own structure so we don't interfere with other usbnet
+ devices that may be connected at the same time. */
+static struct ethtool_ops ax8817x_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
+};
+
+static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret = 0;
+ void *buf;
+ int i;
+ unsigned long gpio_bits = dev->driver_info->data;
+
+ usbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Toggle the GPIOs in a manufacturer/model specific way */
+ for (i = 2; i >= 0; i--) {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ (gpio_bits >> (i * 8)) & 0xff, 0, 0,
+ buf)) < 0)
+ goto out2;
+ msleep(5);
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ 0x80, 0, 0, buf)) < 0) {
+ dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID,
+ 0, 0, 6, buf)) < 0) {
+ dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
+ goto out2;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out2;
+ }
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read;
+ dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.phy_id_mask = 0x3f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = *((u8 *)buf + 1);
+ dev->net->do_ioctl = ax8817x_ioctl;
+
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ mii_nway_restart(&dev->mii);
+
+ return 0;
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static struct ethtool_ops ax88772_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ void *buf;
+
+ usbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ dbg ("Cannot allocate memory for buffer");
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ 0x00B0, 0, 0, buf)) < 0)
+ goto out2;
+
+ msleep(5);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ 0x0001, 0, 0, buf)) < 0) {
+ dbg("Select PHY #1 failed: %d", ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
+ 0, 0, buf)) < 0) {
+ dbg("Failed to power down internal PHY: %d", ret);
+ goto out2;
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
+ 0, 0, buf)) < 0) {
+ dbg("Failed to perform software reset: %d", ret);
+ goto out2;
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
+ 0, 0, buf)) < 0) {
+ dbg("Failed to set Internal/External PHY reset control: %d",
+ ret);
+ goto out2;
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ 0x0000, 0, 0, buf)) < 0) {
+ dbg("Failed to reset RX_CTL: %d", ret);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+ 0, 0, ETH_ALEN, buf)) < 0) {
+ dbg("Failed to read MAC address: %d", ret);
+ goto out2;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
+ 0, 0, 0, buf)) < 0) {
+ dbg("Enabling software MII failed: %d", ret);
+ goto out2;
+ }
+
+ if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG,
+ 0x0010, 2, 2, buf)) < 0)
+ || (*((u16 *)buf) != 0x003b)) {
+ dbg("Read PHY register 2 must be 0x3b00: %d", ret);
+ goto out2;
+ }
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read;
+ dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+ dev->net->do_ioctl = ax8817x_ioctl;
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ dbg("Error reading PHY ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out2;
+ }
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
+ 0, 0, buf)) < 0) {
+ dbg("Set external PHY reset pin level: %d", ret);
+ goto out2;
+ }
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
+ 0, 0, buf)) < 0) {
+ dbg("Set Internal/External PHY reset control: %d", ret);
+ goto out2;
+ }
+ msleep(150);
+
+
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA);
+ mii_nway_restart(&dev->mii);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
+ dbg("Write medium mode register: %d", ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
+ AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
+ dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
+ goto out2;
+ }
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
+ dbg("Failed to set hardware MII: %02x", ret);
+ goto out2;
+ }
+
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
+ buf)) < 0) {
+ dbg("Reset RX_CTL failed: %d", ret);
+ goto out2;
+ }
+
+ kfree(buf);
+
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+ /* hard_mtu is still the default - the device does not support
+ jumbo eth frames */
+ dev->rx_urb_size = 2048;
+ }
+
+ return 0;
+
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ u8 *head;
+ u32 header;
+ char *packet;
+ struct sk_buff *ax_skb;
+ u16 size;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
+
+ skb_pull(skb, 4);
+
+ while (skb->len > 0) {
+ if ((short)(header & 0x0000ffff) !=
+ ~((short)((header & 0xffff0000) >> 16))) {
+ devdbg(dev,"header length data is error");
+ }
+ /* get the packet length */
+ size = (u16) (header & 0x0000ffff);
+
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+ return 2;
+ if (size > ETH_FRAME_LEN) {
+ devdbg(dev,"invalid rx length %d", size);
+ return 0;
+ }
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (ax_skb) {
+ ax_skb->len = size;
+ ax_skb->data = packet;
+ ax_skb->tail = packet + size;
+ usbnet_skb_return(dev, ax_skb);
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, (size + 1) & 0xfffe);
+
+ if (skb->len == 0)
+ break;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
+ skb_pull(skb, 4);
+ }
+
+ if (skb->len < 0) {
+ devdbg(dev,"invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ int padlen;
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+ u32 packet_len;
+ u32 padbytes = 0xffff0000;
+
+ padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (4 + padlen))) {
+ if ((headroom < 4) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ skb_push(skb, 4);
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
+
+ if ((skb->len % 512) == 0) {
+ memcpy( skb->tail, &padbytes, sizeof(padbytes));
+ skb_put(skb, sizeof(padbytes));
+ }
+ return skb;
+}
+
+static int ax88772_link_reset(struct usbnet *dev)
+{
+ u16 lpa;
+ u16 adv;
+ u16 res;
+ u16 mode;
+
+ mode = AX88772_MEDIUM_DEFAULT;
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ res = mii_nway_result(lpa|adv);
+
+ if ((res & LPA_DUPLEX) == 0)
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+ if ((res & LPA_100) == 0)
+ mode &= ~AX88772_MEDIUM_100MB;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+
+ return 0;
+}
+
+static const struct driver_info ax8817x_info = {
+ .description = "ASIX AX8817x USB 2.0 Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x00130103,
+};
+
+static const struct driver_info dlink_dub_e100_info = {
+ .description = "DLink DUB-E100 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x009f9d9f,
+};
+
+static const struct driver_info netgear_fa120_info = {
+ .description = "Netgear FA-120 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x00130103,
+};
+
+static const struct driver_info hawking_uf200_info = {
+ .description = "Hawking UF200 USB Ethernet",
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88172_link_reset,
+ .reset = ax88172_link_reset,
+ .flags = FLAG_ETHER,
+ .data = 0x001f1d1f,
+};
+
+static const struct driver_info ax88772_info = {
+ .description = "ASIX AX88772 USB 2.0 Ethernet",
+ .bind = ax88772_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88772_link_reset,
+ .reset = ax88772_link_reset,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .data = 0x00130103,
+};
+
+static const struct usb_device_id products [] = {
+{
+ // Linksys USB200M
+ USB_DEVICE (0x077b, 0x2226),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Netgear FA120
+ USB_DEVICE (0x0846, 0x1040),
+ .driver_info = (unsigned long) &netgear_fa120_info,
+}, {
+ // DLink DUB-E100
+ USB_DEVICE (0x2001, 0x1a00),
+ .driver_info = (unsigned long) &dlink_dub_e100_info,
+}, {
+ // Intellinet, ST Lab USB Ethernet
+ USB_DEVICE (0x0b95, 0x1720),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Hawking UF200, TrendNet TU2-ET100
+ USB_DEVICE (0x07b8, 0x420a),
+ .driver_info = (unsigned long) &hawking_uf200_info,
+}, {
+ // Billionton Systems, USB2AR
+ USB_DEVICE (0x08dd, 0x90ff),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // ATEN UC210T
+ USB_DEVICE (0x0557, 0x2009),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Buffalo LUA-U2-KTX
+ USB_DEVICE (0x0411, 0x003d),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
+ USB_DEVICE (0x6189, 0x182d),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // corega FEther USB2-TX
+ USB_DEVICE (0x07aa, 0x0017),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // Surecom EP-1427X-2
+ USB_DEVICE (0x1189, 0x0893),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // goodway corp usb gwusb2e
+ USB_DEVICE (0x1631, 0x6200),
+ .driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // ASIX AX88772 10/100
+ USB_DEVICE (0x0b95, 0x7720),
+ .driver_info = (unsigned long) &ax88772_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver asix_driver = {
+ .owner = THIS_MODULE,
+ .name = "asix",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disconnect = usbnet_disconnect,
+};
+
+static int __init asix_init(void)
+{
+ return usb_register(&asix_driver);
+}
+module_init(asix_init);
+
+static void __exit asix_exit(void)
+{
+ usb_deregister(&asix_driver);
+}
+module_exit(asix_exit);
+
+MODULE_AUTHOR("David Hollis");
+MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index c8be912f24e1..37ef365a2472 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -383,7 +383,6 @@ static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
if (urb->status == -ECONNRESET) {
dbg("Tx Reset.");
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
urb->status = 0;
catc->netdev->trans_start = jiffies;
catc->stats.tx_errors++;
@@ -445,7 +444,6 @@ static void catc_tx_timeout(struct net_device *netdev)
struct catc *catc = netdev_priv(netdev);
warn("Transmit timed out.");
- catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(catc->tx_urb);
}
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
new file mode 100644
index 000000000000..652b04bbf6af
--- /dev/null
+++ b/drivers/usb/net/cdc_ether.c
@@ -0,0 +1,509 @@
+/*
+ * CDC Ethernet based networking peripherals
+ * Copyright (C) 2003-2005 by 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * probes control interface, claims data interface, collects the bulk
+ * endpoints, activates data interface (if needed), maybe sets MTU.
+ * all pure cdc, except for certain firmware workarounds, and knowing
+ * that rndis uses one different rule.
+ */
+int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ u8 *buf = intf->cur_altsetting->extra;
+ int len = intf->cur_altsetting->extralen;
+ struct usb_interface_descriptor *d;
+ struct cdc_state *info = (void *) &dev->data;
+ int status;
+ int rndis;
+ struct usb_driver *driver = driver_of(intf);
+
+ if (sizeof dev->data < sizeof *info)
+ return -EDOM;
+
+ /* expect strict spec conformance for the descriptors, but
+ * cope with firmware which stores them in the wrong place
+ */
+ if (len == 0 && dev->udev->actconfig->extralen) {
+ /* Motorola SB4100 (and others: Brad Hards says it's
+ * from a Broadcom design) put CDC descriptors here
+ */
+ buf = dev->udev->actconfig->extra;
+ len = dev->udev->actconfig->extralen;
+ if (len)
+ dev_dbg(&intf->dev,
+ "CDC descriptors on config\n");
+ }
+
+ /* this assumes that if there's a non-RNDIS vendor variant
+ * of cdc-acm, it'll fail RNDIS requests cleanly.
+ */
+ rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
+
+ memset(info, 0, sizeof *info);
+ info->control = intf;
+ while (len > 3) {
+ if (buf [1] != USB_DT_CS_INTERFACE)
+ goto next_desc;
+
+ /* use bDescriptorSubType to identify the CDC descriptors.
+ * We expect devices with CDC header and union descriptors.
+ * For CDC Ethernet we need the ethernet descriptor.
+ * For RNDIS, ignore two (pointless) CDC modem descriptors
+ * in favor of a complicated OID-based RPC scheme doing what
+ * CDC Ethernet achieves with a simple descriptor.
+ */
+ switch (buf [2]) {
+ case USB_CDC_HEADER_TYPE:
+ if (info->header) {
+ dev_dbg(&intf->dev, "extra CDC header\n");
+ goto bad_desc;
+ }
+ info->header = (void *) buf;
+ if (info->header->bLength != sizeof *info->header) {
+ dev_dbg(&intf->dev, "CDC header len %u\n",
+ info->header->bLength);
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_UNION_TYPE:
+ if (info->u) {
+ dev_dbg(&intf->dev, "extra CDC union\n");
+ goto bad_desc;
+ }
+ info->u = (void *) buf;
+ if (info->u->bLength != sizeof *info->u) {
+ dev_dbg(&intf->dev, "CDC union len %u\n",
+ info->u->bLength);
+ goto bad_desc;
+ }
+
+ /* we need a master/control interface (what we're
+ * probed with) and a slave/data interface; union
+ * descriptors sort this all out.
+ */
+ info->control = usb_ifnum_to_if(dev->udev,
+ info->u->bMasterInterface0);
+ info->data = usb_ifnum_to_if(dev->udev,
+ info->u->bSlaveInterface0);
+ if (!info->control || !info->data) {
+ dev_dbg(&intf->dev,
+ "master #%u/%p slave #%u/%p\n",
+ info->u->bMasterInterface0,
+ info->control,
+ info->u->bSlaveInterface0,
+ info->data);
+ goto bad_desc;
+ }
+ if (info->control != intf) {
+ dev_dbg(&intf->dev, "bogus CDC Union\n");
+ /* Ambit USB Cable Modem (and maybe others)
+ * interchanges master and slave interface.
+ */
+ if (info->data == intf) {
+ info->data = info->control;
+ info->control = intf;
+ } else
+ goto bad_desc;
+ }
+
+ /* a data interface altsetting does the real i/o */
+ d = &info->data->cur_altsetting->desc;
+ if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
+ dev_dbg(&intf->dev, "slave class %u\n",
+ d->bInterfaceClass);
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_ETHERNET_TYPE:
+ if (info->ether) {
+ dev_dbg(&intf->dev, "extra CDC ether\n");
+ goto bad_desc;
+ }
+ info->ether = (void *) buf;
+ if (info->ether->bLength != sizeof *info->ether) {
+ dev_dbg(&intf->dev, "CDC ether len %u\n",
+ info->ether->bLength);
+ goto bad_desc;
+ }
+ dev->hard_mtu = le16_to_cpu(
+ info->ether->wMaxSegmentSize);
+ /* because of Zaurus, we may be ignoring the host
+ * side link address we were given.
+ */
+ break;
+ }
+next_desc:
+ len -= buf [0]; /* bLength */
+ buf += buf [0];
+ }
+
+ if (!info->header || !info->u || (!rndis && !info->ether)) {
+ dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n",
+ info->header ? "" : "header ",
+ info->u ? "" : "union ",
+ info->ether ? "" : "ether ");
+ goto bad_desc;
+ }
+
+ /* claim data interface and set it up ... with side effects.
+ * network traffic can't flow until an altsetting is enabled.
+ */
+ status = usb_driver_claim_interface(driver, info->data, dev);
+ if (status < 0)
+ return status;
+ status = usbnet_get_endpoints(dev, info->data);
+ if (status < 0) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ return status;
+ }
+
+ /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+ dev->status = NULL;
+ if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+ struct usb_endpoint_descriptor *desc;
+
+ dev->status = &info->control->cur_altsetting->endpoint [0];
+ desc = &dev->status->desc;
+ if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
+ || !(desc->bEndpointAddress & USB_DIR_IN)
+ || (le16_to_cpu(desc->wMaxPacketSize)
+ < sizeof(struct usb_cdc_notification))
+ || !desc->bInterval) {
+ dev_dbg(&intf->dev, "bad notification endpoint\n");
+ dev->status = NULL;
+ }
+ }
+ if (rndis && !dev->status) {
+ dev_dbg(&intf->dev, "missing RNDIS status endpoint\n");
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ return -ENODEV;
+ }
+ return 0;
+
+bad_desc:
+ dev_info(&dev->udev->dev, "bad CDC descriptors\n");
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct cdc_state *info = (void *) &dev->data;
+ struct usb_driver *driver = driver_of(intf);
+
+ /* disconnect master --> disconnect slave */
+ if (intf == info->control && info->data) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ info->data = NULL;
+ }
+
+ /* and vice versa (just in case) */
+ else if (intf == info->data && info->control) {
+ /* ensure immediate exit from usbnet_disconnect */
+ usb_set_intfdata(info->control, NULL);
+ usb_driver_release_interface(driver, info->control);
+ info->control = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Communications Device Class, Ethernet Control model
+ *
+ * Takes two interfaces. The DATA interface is inactive till an altsetting
+ * is selected. Configuration data includes class descriptors. There's
+ * an optional status endpoint on the control interface.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with, with more functionality.
+ *
+ *-------------------------------------------------------------------------*/
+
+static void dumpspeed(struct usbnet *dev, __le32 *speeds)
+{
+ if (netif_msg_timer(dev))
+ devinfo(dev, "link speeds: %u kbps up, %u kbps down",
+ __le32_to_cpu(speeds[0]) / 1000,
+ __le32_to_cpu(speeds[1]) / 1000);
+}
+
+static void cdc_status(struct usbnet *dev, struct urb *urb)
+{
+ struct usb_cdc_notification *event;
+
+ if (urb->actual_length < sizeof *event)
+ return;
+
+ /* SPEED_CHANGE can get split into two 8-byte packets */
+ if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
+ dumpspeed(dev, (__le32 *) urb->transfer_buffer);
+ return;
+ }
+
+ event = urb->transfer_buffer;
+ switch (event->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ if (netif_msg_timer(dev))
+ devdbg(dev, "CDC: carrier %s",
+ event->wValue ? "on" : "off");
+ if (event->wValue)
+ netif_carrier_on(dev->net);
+ else
+ netif_carrier_off(dev->net);
+ break;
+ case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
+ if (netif_msg_timer(dev))
+ devdbg(dev, "CDC: speed change (len %d)",
+ urb->actual_length);
+ if (urb->actual_length != (sizeof *event + 8))
+ set_bit(EVENT_STS_SPLIT, &dev->flags);
+ else
+ dumpspeed(dev, (__le32 *) &event[1]);
+ break;
+ /* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS),
+ * but there are no standard formats for the response data.
+ */
+ default:
+ deverr(dev, "CDC: unexpected notification %02x!",
+ event->bNotificationType);
+ break;
+ }
+}
+
+static u8 nibble(unsigned char c)
+{
+ if (likely(isdigit(c)))
+ return c - '0';
+ c = toupper(c);
+ if (likely(isxdigit(c)))
+ return 10 + c - 'A';
+ return 0;
+}
+
+static inline int
+get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e)
+{
+ int tmp, i;
+ unsigned char buf [13];
+
+ tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf);
+ if (tmp != 12) {
+ dev_dbg(&dev->udev->dev,
+ "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp);
+ if (tmp >= 0)
+ tmp = -EINVAL;
+ return tmp;
+ }
+ for (i = tmp = 0; i < 6; i++, tmp += 2)
+ dev->net->dev_addr [i] =
+ (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]);
+ return 0;
+}
+
+static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int status;
+ struct cdc_state *info = (void *) &dev->data;
+
+ status = usbnet_generic_cdc_bind(dev, intf);
+ if (status < 0)
+ return status;
+
+ status = get_ethernet_addr(dev, info->ether);
+ if (status < 0) {
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver_of(intf), info->data);
+ return status;
+ }
+
+ /* FIXME cdc-ether has some multicast code too, though it complains
+ * in routine cases. info->ether describes the multicast support.
+ * Implement that here, manipulating the cdc filter as needed.
+ */
+ return 0;
+}
+
+static const struct driver_info cdc_info = {
+ .description = "CDC Ethernet Device",
+ .flags = FLAG_ETHER,
+ // .check_connect = cdc_check_connect,
+ .bind = cdc_bind,
+ .unbind = usbnet_cdc_unbind,
+ .status = cdc_status,
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+static const struct usb_device_id products [] = {
+/*
+ * BLACKLIST !!
+ *
+ * First blacklist any products that are egregiously nonconformant
+ * with the CDC Ethernet specs. Minor braindamage we cope with; when
+ * they're not even trying, needing a separate driver is only the first
+ * of the differences to show up.
+ */
+
+#define ZAURUS_MASTER_INTERFACE \
+ .bInterfaceClass = USB_CLASS_COMM, \
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+/* SA-1100 based Sharp Zaurus ("collie"), or compatible;
+ * wire-incompatible with true CDC Ethernet implementations.
+ * (And, it seems, needlessly so...)
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8004,
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+},
+
+/* PXA-25x based Sharp Zaurii. Note that it seems some of these
+ * (later models especially) may have shipped only with firmware
+ * advertising false "CDC MDLM" compatibility ... but we're not
+ * clear which models did that, so for now let's assume the worst.
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9031, /* C-750 C-760 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9032, /* SL-6000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9050, /* C-860 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = 0,
+},
+
+/*
+ * WHITELIST!!!
+ *
+ * CDC Ether uses two interfaces, not necessarily consecutive.
+ * We match the main interface, ignoring the optional device
+ * class so we could handle devices that aren't exclusively
+ * CDC ether.
+ *
+ * NOTE: this match must come AFTER entries blacklisting devices
+ * because of bugs/quirks in a given product (like Zaurus, above).
+ */
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver cdc_driver = {
+ .owner = THIS_MODULE,
+ .name = "cdc_ether",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+
+static int __init cdc_init(void)
+{
+ BUG_ON((sizeof(((struct usbnet *)0)->data)
+ < sizeof(struct cdc_state)));
+
+ return usb_register(&cdc_driver);
+}
+module_init(cdc_init);
+
+static void __exit cdc_exit(void)
+{
+ usb_deregister(&cdc_driver);
+}
+module_exit(cdc_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB CDC Ethernet devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
new file mode 100644
index 000000000000..f1730b685fd2
--- /dev/null
+++ b/drivers/usb/net/cdc_subset.c
@@ -0,0 +1,335 @@
+/*
+ * Simple "CDC Subset" USB Networking Links
+ * Copyright (C) 2000-2005 by 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
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * This supports simple USB network links that don't require any special
+ * framing or hardware control operations. The protocol used here is a
+ * strict subset of CDC Ethernet, with three basic differences reflecting
+ * the goal that almost any hardware should run it:
+ *
+ * - Minimal runtime control: one interface, no altsettings, and
+ * no vendor or class specific control requests. If a device is
+ * configured, it is allowed to exchange packets with the host.
+ * Fancier models would mean not working on some hardware.
+ *
+ * - Minimal manufacturing control: no IEEE "Organizationally
+ * Unique ID" required, or an EEPROMs to store one. Each host uses
+ * one random "locally assigned" Ethernet address instead, which can
+ * of course be overridden using standard tools like "ifconfig".
+ * (With 2^46 such addresses, same-net collisions are quite rare.)
+ *
+ * - There is no additional framing data for USB. Packets are written
+ * exactly as in CDC Ethernet, starting with an Ethernet header and
+ * terminated by a short packet. However, the host will never send a
+ * zero length packet; some systems can't handle those robustly.
+ *
+ * Anything that can transmit and receive USB bulk packets can implement
+ * this protocol. That includes both smart peripherals and quite a lot
+ * of "host-to-host" USB cables (which embed two devices back-to-back).
+ *
+ * Note that although Linux may use many of those host-to-host links
+ * with this "cdc_subset" framing, that doesn't mean there may not be a
+ * better approach. Handling the "other end unplugs/replugs" scenario
+ * well tends to require chip-specific vendor requests. Also, Windows
+ * peers at the other end of host-to-host cables may expect their own
+ * framing to be used rather than this "cdc_subset" model.
+ */
+
+#if defined(CONFIG_USB_EPSON2888) || defined(CONFIG_USB_ARMLINUX)
+/* PDA style devices are always connected if present */
+static int always_connected (struct usbnet *dev)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_USB_ALI_M5632
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * ALi M5632 driver ... does high speed
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info ali_m5632_info = {
+ .description = "ALi M5632",
+};
+
+
+#endif
+
+
+#ifdef CONFIG_USB_AN2720
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * AnchorChips 2720 driver ... http://www.cypress.com
+ *
+ * This doesn't seem to have a way to detect whether the peer is
+ * connected, or need any reset handshaking. It's got pretty big
+ * internal buffers (handles most of a frame's worth of data).
+ * Chip data sheets don't describe any vendor control messages.
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info an2720_info = {
+ .description = "AnchorChips/Cypress 2720",
+ // no reset available!
+ // no check_connect available!
+
+ .in = 2, .out = 2, // direction distinguishes these
+};
+
+#endif /* CONFIG_USB_AN2720 */
+
+
+#ifdef CONFIG_USB_BELKIN
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * Belkin F5U104 ... two NetChip 2280 devices + Atmel AVR microcontroller
+ *
+ * ... also two eTEK designs, including one sold as "Advance USBNET"
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info belkin_info = {
+ .description = "Belkin, eTEK, or compatible",
+};
+
+#endif /* CONFIG_USB_BELKIN */
+
+
+
+#ifdef CONFIG_USB_EPSON2888
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * EPSON USB clients
+ *
+ * This is the same idea as Linux PDAs (below) except the firmware in the
+ * device might not be Tux-powered. Epson provides reference firmware that
+ * implements this interface. Product developers can reuse or modify that
+ * code, such as by using their own product and vendor codes.
+ *
+ * Support was from Juro Bystricky <bystricky.juro@erd.epson.com>
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info epson2888_info = {
+ .description = "Epson USB Device",
+ .check_connect = always_connected,
+
+ .in = 4, .out = 3,
+};
+
+#endif /* CONFIG_USB_EPSON2888 */
+
+
+#ifdef CONFIG_USB_KC2190
+#define HAVE_HARDWARE
+static const struct driver_info kc2190_info = {
+ .description = "KC Technology KC-190",
+};
+#endif /* CONFIG_USB_KC2190 */
+
+
+#ifdef CONFIG_USB_ARMLINUX
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * Intel's SA-1100 chip integrates basic USB support, and is used
+ * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more.
+ * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to
+ * network using minimal USB framing data.
+ *
+ * This describes the driver currently in standard ARM Linux kernels.
+ * The Zaurus uses a different driver (see later).
+ *
+ * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support
+ * and different USB endpoint numbering than the SA1100 devices. The
+ * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100
+ * so we rely on the endpoint descriptors.
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info linuxdev_info = {
+ .description = "Linux Device",
+ .check_connect = always_connected,
+};
+
+static const struct driver_info yopy_info = {
+ .description = "Yopy",
+ .check_connect = always_connected,
+};
+
+static const struct driver_info blob_info = {
+ .description = "Boot Loader OBject",
+ .check_connect = always_connected,
+};
+
+#endif /* CONFIG_USB_ARMLINUX */
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef HAVE_HARDWARE
+#error You need to configure some hardware for this driver
+#endif
+
+/*
+ * chip vendor names won't normally be on the cables, and
+ * may not be on the device.
+ */
+
+static const struct usb_device_id products [] = {
+
+#ifdef CONFIG_USB_ALI_M5632
+{
+ USB_DEVICE (0x0402, 0x5632), // ALi defaults
+ .driver_info = (unsigned long) &ali_m5632_info,
+},
+#endif
+
+#ifdef CONFIG_USB_AN2720
+{
+ USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
+ .driver_info = (unsigned long) &an2720_info,
+}, {
+ USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
+ .driver_info = (unsigned long) &an2720_info,
+},
+#endif
+
+#ifdef CONFIG_USB_BELKIN
+{
+ USB_DEVICE (0x050d, 0x0004), // Belkin
+ .driver_info = (unsigned long) &belkin_info,
+}, {
+ USB_DEVICE (0x056c, 0x8100), // eTEK
+ .driver_info = (unsigned long) &belkin_info,
+}, {
+ USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK)
+ .driver_info = (unsigned long) &belkin_info,
+},
+#endif
+
+#ifdef CONFIG_USB_EPSON2888
+{
+ USB_DEVICE (0x0525, 0x2888), // EPSON USB client
+ .driver_info = (unsigned long) &epson2888_info,
+},
+#endif
+
+#ifdef CONFIG_USB_KC2190
+{
+ USB_DEVICE (0x050f, 0x0190), // KC-190
+ .driver_info = (unsigned long) &kc2190_info,
+},
+#endif
+
+#ifdef CONFIG_USB_ARMLINUX
+/*
+ * SA-1100 using standard ARM Linux kernels, or compatible.
+ * Often used when talking to Linux PDAs (iPaq, Yopy, etc).
+ * The sa-1100 "usb-eth" driver handles the basic framing.
+ *
+ * PXA25x or PXA210 ... these use a "usb-eth" driver much like
+ * the sa1100 one, but hardware uses different endpoint numbers.
+ *
+ * Or the Linux "Ethernet" gadget on hardware that can't talk
+ * CDC Ethernet (e.g., no altsettings), in either of two modes:
+ * - acting just like the old "usb-eth" firmware, though
+ * the implementation is different
+ * - supporting RNDIS as the first/default configuration for
+ * MS-Windows interop; Linux needs to use the other config
+ */
+{
+ // 1183 = 0x049F, both used as hex values?
+ // Compaq "Itsy" vendor/product id
+ USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible
+ .driver_info = (unsigned long) &linuxdev_info,
+}, {
+ USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy"
+ .driver_info = (unsigned long) &yopy_info,
+}, {
+ USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
+ .driver_info = (unsigned long) &blob_info,
+}, {
+ // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
+ // e.g. Gumstix, current OpenZaurus, ...
+ USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
+ .driver_info = (unsigned long) &linuxdev_info,
+},
+#endif
+
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_driver cdc_subset_driver = {
+ .owner = THIS_MODULE,
+ .name = "cdc_subset",
+ .probe = usbnet_probe,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .disconnect = usbnet_disconnect,
+ .id_table = products,
+};
+
+static int __init cdc_subset_init(void)
+{
+ return usb_register(&cdc_subset_driver);
+}
+module_init(cdc_subset_init);
+
+static void __exit cdc_subset_exit(void)
+{
+ usb_deregister(&cdc_subset_driver);
+}
+module_exit(cdc_subset_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("Simple 'CDC Subset' USB networking links");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
new file mode 100644
index 000000000000..c0f263b202a6
--- /dev/null
+++ b/drivers/usb/net/gl620a.c
@@ -0,0 +1,407 @@
+/*
+ * GeneSys GL620USB-A based links
+ * Copyright (C) 2001 by Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
+ * Copyright (C) 2001 by Stanislav Brabec <utx@penguin.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// #define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ * ... should partially interop with the Win32 driver for this hardware.
+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
+ *
+ * Some info from GeneSys:
+ * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk.
+ * (Some cables, like the BAFO-100c, use the half duplex version.)
+ * - For the full duplex model, the low bit of the version code says
+ * which side is which ("left/right").
+ * - For the half duplex type, a control/interrupt handshake settles
+ * the transfer direction. (That's disabled here, partially coded.)
+ * A control URB would block until other side writes an interrupt.
+ *
+ * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
+ * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>.
+ */
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE 0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE 0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE 0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL 0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS 32
+// max packet length
+#define GL_MAX_PACKET_LEN 1514
+// max receive buffer size
+#define GL_RCV_BUF_SIZE \
+ (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_packet {
+ u32 packet_length;
+ char packet_data [1];
+};
+
+struct gl_header {
+ u32 packet_count;
+ struct gl_packet packets;
+};
+
+#ifdef GENELINK_ACK
+
+// FIXME: this code is incomplete, not debugged; it doesn't
+// handle interrupts correctly; it should use the generic
+// status IRQ code (which didn't exist back in 2001).
+
+struct gl_priv {
+ struct urb *irq_urb;
+ char irq_buf [INTERRUPT_BUFSIZE];
+};
+
+static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
+{
+ int retval;
+
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ value,
+ 0, // index
+ 0, // data buffer
+ 0, // size
+ USB_CTRL_SET_TIMEOUT);
+ return retval;
+}
+
+static void gl_interrupt_complete(struct urb *urb, struct pt_regs *regs)
+{
+ int status = urb->status;
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ }
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, status);
+}
+
+static int gl_interrupt_read(struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+ int retval;
+
+ // issue usb interrupt read
+ if (priv && priv->irq_urb) {
+ // submit urb
+ if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0)
+ dbg("gl_interrupt_read: submit fail - %X...", retval);
+ else
+ dbg("gl_interrupt_read: submit success...");
+ }
+
+ return 0;
+}
+
+// check whether another side is connected
+static int genelink_check_connect(struct usbnet *dev)
+{
+ int retval;
+
+ dbg("genelink_check_connect...");
+
+ // detect whether another side is connected
+ if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+ dbg("%s: genelink_check_connect write fail - %X",
+ dev->net->name, retval);
+ return retval;
+ }
+
+ // usb interrupt read to ack another side
+ if ((retval = gl_interrupt_read(dev)) != 0) {
+ dbg("%s: genelink_check_connect read fail - %X",
+ dev->net->name, retval);
+ return retval;
+ }
+
+ dbg("%s: genelink_check_connect read success", dev->net->name);
+ return 0;
+}
+
+// allocate and initialize the private data for genelink
+static int genelink_init(struct usbnet *dev)
+{
+ struct gl_priv *priv;
+
+ // allocate the private data structure
+ if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) {
+ dbg("%s: cannot allocate private data per device",
+ dev->net->name);
+ return -ENOMEM;
+ }
+
+ // allocate irq urb
+ if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) {
+ dbg("%s: cannot allocate private irq urb per device",
+ dev->net->name);
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ // fill irq urb
+ usb_fill_int_urb(priv->irq_urb, dev->udev,
+ usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE),
+ priv->irq_buf, INTERRUPT_BUFSIZE,
+ gl_interrupt_complete, 0,
+ GENELINK_INTERRUPT_INTERVAL);
+
+ // set private data pointer
+ dev->priv_data = priv;
+
+ return 0;
+}
+
+// release the private data
+static int genelink_free(struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+
+ if (!priv)
+ return 0;
+
+// FIXME: can't cancel here; it's synchronous, and
+// should have happened earlier in any case (interrupt
+// handling needs to be generic)
+
+ // cancel irq urb first
+ usb_kill_urb(priv->irq_urb);
+
+ // free irq urb
+ usb_free_urb(priv->irq_urb);
+
+ // free the private data structure
+ kfree(priv);
+
+ return 0;
+}
+
+#endif
+
+static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct gl_header *header;
+ struct gl_packet *packet;
+ struct sk_buff *gl_skb;
+ u32 size;
+
+ header = (struct gl_header *) skb->data;
+
+ // get the packet count of the received skb
+ le32_to_cpus(&header->packet_count);
+ if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
+ || (header->packet_count < 0)) {
+ dbg("genelink: invalid received packet count %d",
+ header->packet_count);
+ return 0;
+ }
+
+ // set the current packet pointer to the first packet
+ packet = &header->packets;
+
+ // decrement the length for the packet count size 4 bytes
+ skb_pull(skb, 4);
+
+ while (header->packet_count > 1) {
+ // get the packet length
+ size = le32_to_cpu(packet->packet_length);
+
+ // this may be a broken packet
+ if (size > GL_MAX_PACKET_LEN) {
+ dbg("genelink: invalid rx length %d", size);
+ return 0;
+ }
+
+ // allocate the skb for the individual packet
+ gl_skb = alloc_skb(size, GFP_ATOMIC);
+ if (gl_skb) {
+
+ // copy the packet data to the new skb
+ memcpy(skb_put(gl_skb, size),
+ packet->packet_data, size);
+ usbnet_skb_return(dev, gl_skb);
+ }
+
+ // advance to the next packet
+ packet = (struct gl_packet *)
+ &packet->packet_data [size];
+ header->packet_count--;
+
+ // shift the data pointer to the next gl_packet
+ skb_pull(skb, size + 4);
+ }
+
+ // skip the packet length field 4 bytes
+ skb_pull(skb, 4);
+
+ if (skb->len > GL_MAX_PACKET_LEN) {
+ dbg("genelink: invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *
+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int padlen;
+ int length = skb->len;
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+ u32 *packet_count;
+ u32 *packet_len;
+
+ // FIXME: magic numbers, bleech
+ padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+ if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + (4 + 4*1),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ // attach the packet count to the header
+ packet_count = (u32 *) skb_push(skb, (4 + 4*1));
+ packet_len = packet_count + 1;
+
+ *packet_count = cpu_to_le32(1);
+ *packet_len = cpu_to_le32(length);
+
+ // add padding byte
+ if ((skb->len % dev->maxpacket) == 0)
+ skb_put(skb, 1);
+
+ return skb;
+}
+
+static int genelink_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ dev->hard_mtu = GL_RCV_BUF_SIZE;
+ dev->net->hard_header_len += 4;
+ dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
+ dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
+ return 0;
+}
+
+static const struct driver_info genelink_info = {
+ .description = "Genesys GeneLink",
+ .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT,
+ .bind = genelink_bind,
+ .rx_fixup = genelink_rx_fixup,
+ .tx_fixup = genelink_tx_fixup,
+
+ .in = 1, .out = 2,
+
+#ifdef GENELINK_ACK
+ .check_connect =genelink_check_connect,
+#endif
+};
+
+static const struct usb_device_id products [] = {
+
+{
+ USB_DEVICE(0x05e3, 0x0502), // GL620USB-A
+ .driver_info = (unsigned long) &genelink_info,
+},
+ /* NOT: USB_DEVICE(0x05e3, 0x0501), // GL620USB
+ * that's half duplex, not currently supported
+ */
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver gl620a_driver = {
+ .owner = THIS_MODULE,
+ .name = "gl620a",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init usbnet_init(void)
+{
+ return usb_register(&gl620a_driver);
+}
+module_init(usbnet_init);
+
+static void __exit usbnet_exit(void)
+{
+ usb_deregister(&gl620a_driver);
+}
+module_exit(usbnet_exit);
+
+MODULE_AUTHOR("Jiun-Jie Huang");
+MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 7ffa99b9760f..6bef1be6b36c 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -469,7 +469,7 @@ static int kaweth_reset(struct kaweth_device *kaweth)
0,
KAWETH_CONTROL_TIMEOUT);
- udelay(10000);
+ mdelay(10);
kaweth_dbg("kaweth_reset() returns %d.",result);
@@ -477,13 +477,13 @@ static int kaweth_reset(struct kaweth_device *kaweth)
}
static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
-static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned);
+static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
/****************************************************************
int_callback
*****************************************************************/
-static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf)
+static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
{
int status;
@@ -550,7 +550,7 @@ static void kaweth_resubmit_tl(void *d)
* kaweth_resubmit_rx_urb
****************************************************************/
static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
- unsigned mem_flags)
+ gfp_t mem_flags)
{
int result;
@@ -787,7 +787,6 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
kaweth_usb_transmit_complete,
kaweth);
kaweth->end = 0;
- kaweth->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
{
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
new file mode 100644
index 000000000000..cee55f8cf64f
--- /dev/null
+++ b/drivers/usb/net/net1080.c
@@ -0,0 +1,622 @@
+/*
+ * Net1080 based USB host-to-host cables
+ * Copyright (C) 2000-2005 by 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include <asm/unaligned.h>
+
+#include "usbnet.h"
+
+
+/*
+ * Netchip 1080 driver ... http://www.netchip.com
+ * (Sept 2004: End-of-life announcement has been sent.)
+ * Used in (some) LapLink cables
+ */
+
+#define frame_errors data[1]
+
+/*
+ * NetChip framing of ethernet packets, supporting additional error
+ * checks for links that may drop bulk packets from inside messages.
+ * Odd USB length == always short read for last usb packet.
+ * - nc_header
+ * - Ethernet header (14 bytes)
+ * - payload
+ * - (optional padding byte, if needed so length becomes odd)
+ * - nc_trailer
+ *
+ * This framing is to be avoided for non-NetChip devices.
+ */
+
+struct nc_header { // packed:
+ __le16 hdr_len; // sizeof nc_header (LE, all)
+ __le16 packet_len; // payload size (including ethhdr)
+ __le16 packet_id; // detects dropped packets
+#define MIN_HEADER 6
+
+ // all else is optional, and must start with:
+ // __le16 vendorId; // from usb-if
+ // __le16 productId;
+} __attribute__((__packed__));
+
+#define PAD_BYTE ((unsigned char)0xAC)
+
+struct nc_trailer {
+ __le16 packet_id;
+} __attribute__((__packed__));
+
+// packets may use FLAG_FRAMING_NC and optional pad
+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+ + sizeof (struct ethhdr) \
+ + (mtu) \
+ + 1 \
+ + sizeof (struct nc_trailer))
+
+#define MIN_FRAMED FRAMED_SIZE(0)
+
+/* packets _could_ be up to 64KB... */
+#define NC_MAX_PACKET 32767
+
+
+/*
+ * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
+ * before the hardware drops it. If that's done, the driver will need to
+ * frame network packets to guard against the dropped USB packets. The win32
+ * driver sets this for both sides of the link.
+ */
+#define NC_READ_TTL_MS ((u8)255) // ms
+
+/*
+ * We ignore most registers and EEPROM contents.
+ */
+#define REG_USBCTL ((u8)0x04)
+#define REG_TTL ((u8)0x10)
+#define REG_STATUS ((u8)0x11)
+
+/*
+ * Vendor specific requests to read/write data
+ */
+#define REQUEST_REGISTER ((u8)0x10)
+#define REQUEST_EEPROM ((u8)0x11)
+
+static int
+nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
+{
+ int status = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, regnum,
+ retval_ptr, sizeof *retval_ptr,
+ USB_CTRL_GET_TIMEOUT);
+ if (status > 0)
+ status = 0;
+ if (!status)
+ le16_to_cpus(retval_ptr);
+ return status;
+}
+
+static inline int
+nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
+{
+ return nc_vendor_read(dev, REQUEST_REGISTER, regnum, retval_ptr);
+}
+
+// no retval ... can become async, usable in_interrupt()
+static void
+nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
+{
+ usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, regnum,
+ NULL, 0, // data is in setup packet
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static inline void
+nc_register_write(struct usbnet *dev, u8 regnum, u16 value)
+{
+ nc_vendor_write(dev, REQUEST_REGISTER, regnum, value);
+}
+
+
+#if 0
+static void nc_dump_registers(struct usbnet *dev)
+{
+ u8 reg;
+ u16 *vp = kmalloc(sizeof (u16));
+
+ if (!vp) {
+ dbg("no memory?");
+ return;
+ }
+
+ dbg("%s registers:", dev->net->name);
+ for (reg = 0; reg < 0x20; reg++) {
+ int retval;
+
+ // reading some registers is trouble
+ if (reg >= 0x08 && reg <= 0xf)
+ continue;
+ if (reg >= 0x12 && reg <= 0x1e)
+ continue;
+
+ retval = nc_register_read(dev, reg, vp);
+ if (retval < 0)
+ dbg("%s reg [0x%x] ==> error %d",
+ dev->net->name, reg, retval);
+ else
+ dbg("%s reg [0x%x] = 0x%x",
+ dev->net->name, reg, *vp);
+ }
+ kfree(vp);
+}
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Control register
+ */
+
+#define USBCTL_WRITABLE_MASK 0x1f0f
+// bits 15-13 reserved, r/o
+#define USBCTL_ENABLE_LANG (1 << 12)
+#define USBCTL_ENABLE_MFGR (1 << 11)
+#define USBCTL_ENABLE_PROD (1 << 10)
+#define USBCTL_ENABLE_SERIAL (1 << 9)
+#define USBCTL_ENABLE_DEFAULTS (1 << 8)
+// bits 7-4 reserved, r/o
+#define USBCTL_FLUSH_OTHER (1 << 3)
+#define USBCTL_FLUSH_THIS (1 << 2)
+#define USBCTL_DISCONN_OTHER (1 << 1)
+#define USBCTL_DISCONN_THIS (1 << 0)
+
+static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
+{
+ if (!netif_msg_link(dev))
+ return;
+ devdbg(dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
+ " this%s%s;"
+ " other%s%s; r/o 0x%x",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ usbctl,
+ (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
+ (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
+ (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
+ (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
+ (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
+
+ (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
+ (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
+ (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
+ (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
+ usbctl & ~USBCTL_WRITABLE_MASK
+ );
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Status register
+ */
+
+#define STATUS_PORT_A (1 << 15)
+
+#define STATUS_CONN_OTHER (1 << 14)
+#define STATUS_SUSPEND_OTHER (1 << 13)
+#define STATUS_MAILBOX_OTHER (1 << 12)
+#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
+
+#define STATUS_CONN_THIS (1 << 6)
+#define STATUS_SUSPEND_THIS (1 << 5)
+#define STATUS_MAILBOX_THIS (1 << 4)
+#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
+
+#define STATUS_UNSPEC_MASK 0x0c8c
+#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
+
+
+static inline void nc_dump_status(struct usbnet *dev, u16 status)
+{
+ if (!netif_msg_link(dev))
+ return;
+ devdbg(dev, "net1080 %s-%s status 0x%x:"
+ " this (%c) PKT=%d%s%s%s;"
+ " other PKT=%d%s%s%s; unspec 0x%x",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ status,
+
+ // XXX the packet counts don't seem right
+ // (1 at reset, not 0); maybe UNSPEC too
+
+ (status & STATUS_PORT_A) ? 'A' : 'B',
+ STATUS_PACKETS_THIS(status),
+ (status & STATUS_CONN_THIS) ? " CON" : "",
+ (status & STATUS_SUSPEND_THIS) ? " SUS" : "",
+ (status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
+
+ STATUS_PACKETS_OTHER(status),
+ (status & STATUS_CONN_OTHER) ? " CON" : "",
+ (status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
+ (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
+
+ status & STATUS_UNSPEC_MASK
+ );
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * TTL register
+ */
+
+#define TTL_THIS(ttl) (0x00ff & ttl)
+#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8))
+#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this))))
+
+static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
+{
+ if (netif_msg_link(dev))
+ devdbg(dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ ttl, TTL_THIS(ttl), TTL_OTHER(ttl));
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int net1080_reset(struct usbnet *dev)
+{
+ u16 usbctl, status, ttl;
+ u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+ int retval;
+
+ if (!vp)
+ return -ENOMEM;
+
+ // nc_dump_registers(dev);
+
+ if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
+ dbg("can't read %s-%s status: %d",
+ dev->udev->bus->bus_name, dev->udev->devpath, retval);
+ goto done;
+ }
+ status = *vp;
+ nc_dump_status(dev, status);
+
+ if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
+ dbg("can't read USBCTL, %d", retval);
+ goto done;
+ }
+ usbctl = *vp;
+ nc_dump_usbctl(dev, usbctl);
+
+ nc_register_write(dev, REG_USBCTL,
+ USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
+
+ if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
+ dbg("can't read TTL, %d", retval);
+ goto done;
+ }
+ ttl = *vp;
+ // nc_dump_ttl(dev, ttl);
+
+ nc_register_write(dev, REG_TTL,
+ MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) );
+ dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
+
+ if (netif_msg_link(dev))
+ devinfo(dev, "port %c, peer %sconnected",
+ (status & STATUS_PORT_A) ? 'A' : 'B',
+ (status & STATUS_CONN_OTHER) ? "" : "dis"
+ );
+ retval = 0;
+
+done:
+ kfree(vp);
+ return retval;
+}
+
+static int net1080_check_connect(struct usbnet *dev)
+{
+ int retval;
+ u16 status;
+ u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+
+ if (!vp)
+ return -ENOMEM;
+ retval = nc_register_read(dev, REG_STATUS, vp);
+ status = *vp;
+ kfree(vp);
+ if (retval != 0) {
+ dbg("%s net1080_check_conn read - %d", dev->net->name, retval);
+ return retval;
+ }
+ if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
+ return -ENOLINK;
+ return 0;
+}
+
+static void nc_flush_complete(struct urb *urb, struct pt_regs *regs)
+{
+ kfree(urb->context);
+ usb_free_urb(urb);
+}
+
+static void nc_ensure_sync(struct usbnet *dev)
+{
+ dev->frame_errors++;
+ if (dev->frame_errors > 5) {
+ struct urb *urb;
+ struct usb_ctrlrequest *req;
+ int status;
+
+ /* Send a flush */
+ urb = usb_alloc_urb(0, SLAB_ATOMIC);
+ if (!urb)
+ return;
+
+ req = kmalloc(sizeof *req, GFP_ATOMIC);
+ if (!req) {
+ usb_free_urb(urb);
+ return;
+ }
+
+ req->bRequestType = USB_DIR_OUT
+ | USB_TYPE_VENDOR
+ | USB_RECIP_DEVICE;
+ req->bRequest = REQUEST_REGISTER;
+ req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS
+ | USBCTL_FLUSH_OTHER);
+ req->wIndex = cpu_to_le16(REG_USBCTL);
+ req->wLength = cpu_to_le16(0);
+
+ /* queue an async control request, we don't need
+ * to do anything when it finishes except clean up.
+ */
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (unsigned char *) req,
+ NULL, 0,
+ nc_flush_complete, req);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ kfree(req);
+ usb_free_urb(urb);
+ return;
+ }
+
+ if (netif_msg_rx_err(dev))
+ devdbg(dev, "flush net1080; too many framing errors");
+ dev->frame_errors = 0;
+ }
+}
+
+static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct nc_header *header;
+ struct nc_trailer *trailer;
+ u16 hdr_len, packet_len;
+
+ if (!(skb->len & 0x01)) {
+#ifdef DEBUG
+ struct net_device *net = dev->net;
+ dbg("rx framesize %d range %d..%d mtu %d", skb->len,
+ net->hard_header_len, dev->hard_mtu, net->mtu);
+#endif
+ dev->stats.rx_frame_errors++;
+ nc_ensure_sync(dev);
+ return 0;
+ }
+
+ header = (struct nc_header *) skb->data;
+ hdr_len = le16_to_cpup(&header->hdr_len);
+ packet_len = le16_to_cpup(&header->packet_len);
+ if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
+ dev->stats.rx_frame_errors++;
+ dbg("packet too big, %d", packet_len);
+ nc_ensure_sync(dev);
+ return 0;
+ } else if (hdr_len < MIN_HEADER) {
+ dev->stats.rx_frame_errors++;
+ dbg("header too short, %d", hdr_len);
+ nc_ensure_sync(dev);
+ return 0;
+ } else if (hdr_len > MIN_HEADER) {
+ // out of band data for us?
+ dbg("header OOB, %d bytes", hdr_len - MIN_HEADER);
+ nc_ensure_sync(dev);
+ // switch (vendor/product ids) { ... }
+ }
+ skb_pull(skb, hdr_len);
+
+ trailer = (struct nc_trailer *)
+ (skb->data + skb->len - sizeof *trailer);
+ skb_trim(skb, skb->len - sizeof *trailer);
+
+ if ((packet_len & 0x01) == 0) {
+ if (skb->data [packet_len] != PAD_BYTE) {
+ dev->stats.rx_frame_errors++;
+ dbg("bad pad");
+ return 0;
+ }
+ skb_trim(skb, skb->len - 1);
+ }
+ if (skb->len != packet_len) {
+ dev->stats.rx_frame_errors++;
+ dbg("bad packet len %d (expected %d)",
+ skb->len, packet_len);
+ nc_ensure_sync(dev);
+ return 0;
+ }
+ if (header->packet_id != get_unaligned(&trailer->packet_id)) {
+ dev->stats.rx_fifo_errors++;
+ dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
+ le16_to_cpu(header->packet_id),
+ le16_to_cpu(trailer->packet_id));
+ return 0;
+ }
+#if 0
+ devdbg(dev, "frame <rx h %d p %d id %d", header->hdr_len,
+ header->packet_len, header->packet_id);
+#endif
+ dev->frame_errors = 0;
+ return 1;
+}
+
+static struct sk_buff *
+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+ struct nc_header *header = NULL;
+ struct nc_trailer *trailer = NULL;
+ int len = skb->len;
+
+ padlen = ((len + sizeof (struct nc_header)
+ + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+ if (!skb_cloned(skb)) {
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+
+ if ((padlen + sizeof (struct nc_trailer)) <= tailroom
+ && sizeof (struct nc_header) <= headroom)
+ /* There's enough head and tail room */
+ goto encapsulate;
+
+ if ((sizeof (struct nc_header) + padlen
+ + sizeof (struct nc_trailer)) <
+ (headroom + tailroom)) {
+ /* There's enough total room, so just readjust */
+ skb->data = memmove(skb->head
+ + sizeof (struct nc_header),
+ skb->data, skb->len);
+ skb->tail = skb->data + len;
+ goto encapsulate;
+ }
+ }
+
+ /* Create a new skb to use with the correct size */
+ skb2 = skb_copy_expand(skb,
+ sizeof (struct nc_header),
+ sizeof (struct nc_trailer) + padlen,
+ flags);
+ dev_kfree_skb_any(skb);
+ if (!skb2)
+ return skb2;
+ skb = skb2;
+
+encapsulate:
+ /* header first */
+ header = (struct nc_header *) skb_push(skb, sizeof *header);
+ header->hdr_len = cpu_to_le16(sizeof (*header));
+ header->packet_len = cpu_to_le16(len);
+ header->packet_id = cpu_to_le16((u16)dev->xid++);
+
+ /* maybe pad; then trailer */
+ if (!((skb->len + sizeof *trailer) & 0x01))
+ *skb_put(skb, 1) = PAD_BYTE;
+ trailer = (struct nc_trailer *) skb_put(skb, sizeof *trailer);
+ put_unaligned(header->packet_id, &trailer->packet_id);
+#if 0
+ devdbg(dev, "frame >tx h %d p %d id %d",
+ header->hdr_len, header->packet_len,
+ header->packet_id);
+#endif
+ return skb;
+}
+
+static int net1080_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ unsigned extra = sizeof (struct nc_header)
+ + 1
+ + sizeof (struct nc_trailer);
+
+ dev->net->hard_header_len += extra;
+ dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
+ dev->hard_mtu = NC_MAX_PACKET;
+ return usbnet_get_endpoints (dev, intf);
+}
+
+static const struct driver_info net1080_info = {
+ .description = "NetChip TurboCONNECT",
+ .flags = FLAG_FRAMING_NC,
+ .bind = net1080_bind,
+ .reset = net1080_reset,
+ .check_connect = net1080_check_connect,
+ .rx_fixup = net1080_rx_fixup,
+ .tx_fixup = net1080_tx_fixup,
+};
+
+static const struct usb_device_id products [] = {
+{
+ USB_DEVICE(0x0525, 0x1080), // NetChip ref design
+ .driver_info = (unsigned long) &net1080_info,
+}, {
+ USB_DEVICE(0x06D0, 0x0622), // Laplink Gold
+ .driver_info = (unsigned long) &net1080_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver net1080_driver = {
+ .owner = THIS_MODULE,
+ .name = "net1080",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init net1080_init(void)
+{
+ return usb_register(&net1080_driver);
+}
+module_init(net1080_init);
+
+static void __exit net1080_exit(void)
+{
+ usb_deregister(&net1080_driver);
+}
+module_exit(net1080_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("NetChip 1080 based USB Host-to-Host Links");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index fcd6d3ccef44..537eb181d985 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -648,6 +648,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
}
/*
+ * If the packet is unreasonably long, quietly drop it rather than
+ * kernel panicing by calling skb_put.
+ */
+ if (pkt_len > PEGASUS_MTU)
+ goto goon;
+
+ /*
* at this point we are sure pegasus->rx_skb != NULL
* so we go ahead and pass up the packet.
*/
@@ -825,7 +832,6 @@ static void pegasus_tx_timeout(struct net_device *net)
pegasus_t *pegasus = netdev_priv(net);
if (netif_msg_timer(pegasus))
printk(KERN_WARNING "%s: tx timeout\n", net->name);
- pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
}
@@ -887,15 +893,17 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
__u8 data[2];
read_eprom_word(pegasus, 4, (__u16 *) data);
- if (data[1] < 0x80) {
- if (netif_msg_timer(pegasus))
- dev_info(&pegasus->intf->dev,
- "intr interval changed from %ums to %ums\n",
- data[1], 0x80);
- data[1] = 0x80;
-#ifdef PEGASUS_WRITE_EEPROM
- write_eprom_word(pegasus, 4, *(__u16 *) data);
+ if (pegasus->usb->speed != USB_SPEED_HIGH) {
+ if (data[1] < 0x80) {
+ if (netif_msg_timer(pegasus))
+ dev_info(&pegasus->intf->dev, "intr interval "
+ "changed from %ums to %ums\n",
+ data[1], 0x80);
+ data[1] = 0x80;
+#ifdef PEGASUS_WRITE_EEPROM
+ write_eprom_word(pegasus, 4, *(__u16 *) data);
#endif
+ }
}
pegasus->intr_interval = data[1];
}
@@ -905,8 +913,9 @@ static void set_carrier(struct net_device *net)
pegasus_t *pegasus = netdev_priv(net);
u16 tmp;
- if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+ if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
return;
+
if (tmp & BMSR_LSTATUS)
netif_carrier_on(net);
else
@@ -1356,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
cancel_delayed_work(&pegasus->carrier_check);
unregister_netdev(pegasus->net);
usb_put_dev(interface_to_usbdev(intf));
+ unlink_all_urbs(pegasus);
free_all_urbs(pegasus);
free_skb_pool(pegasus);
if (pegasus->rx_skb)
@@ -1374,7 +1384,6 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
usb_kill_urb(pegasus->rx_urb);
usb_kill_urb(pegasus->intr_urb);
}
- intf->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
@@ -1382,7 +1391,6 @@ static int pegasus_resume (struct usb_interface *intf)
{
struct pegasus *pegasus = usb_get_intfdata(intf);
- intf->dev.power.power_state = PMSG_ON;
netif_device_attach (pegasus->net);
if (netif_running(pegasus->net)) {
pegasus->rx_urb->status = 0;
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index b98f2a833442..9fbd59b55cb6 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -181,6 +181,8 @@ PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
new file mode 100644
index 000000000000..74c2b3581c76
--- /dev/null
+++ b/drivers/usb/net/plusb.c
@@ -0,0 +1,156 @@
+/*
+ * PL-2301/2302 USB host-to-host link cables
+ * Copyright (C) 2000-2005 by 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+
+#include "usbnet.h"
+
+
+/*
+ * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
+ *
+ * The protocol and handshaking used here should be bug-compatible
+ * with the Linux 2.2 "plusb" driver, by Deti Fliegl.
+ *
+ * HEADS UP: this handshaking isn't all that robust. This driver
+ * gets confused easily if you unplug one end of the cable then
+ * try to connect it again; you'll need to restart both ends. The
+ * "naplink" software (used by some PlayStation/2 deveopers) does
+ * the handshaking much better! Also, sometimes this hardware
+ * seems to get wedged under load. Prolific docs are weak, and
+ * don't identify differences between PL2301 and PL2302, much less
+ * anything to explain the different PL2302 versions observed.
+ */
+
+/*
+ * Bits 0-4 can be used for software handshaking; they're set from
+ * one end, cleared from the other, "read" with the interrupt byte.
+ */
+#define PL_S_EN (1<<7) /* (feature only) suspend enable */
+/* reserved bit -- rx ready (6) ? */
+#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */
+#define PL_RESET_OUT (1<<4) /* reset output pipe */
+#define PL_RESET_IN (1<<3) /* reset input pipe */
+#define PL_TX_C (1<<2) /* transmission complete */
+#define PL_TX_REQ (1<<1) /* transmission received */
+#define PL_PEER_E (1<<0) /* peer exists */
+
+static inline int
+pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
+{
+ return usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ req,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ val, index,
+ NULL, 0,
+ USB_CTRL_GET_TIMEOUT);
+}
+
+static inline int
+pl_clear_QuickLink_features(struct usbnet *dev, int val)
+{
+ return pl_vendor_req(dev, 1, (u8) val, 0);
+}
+
+static inline int
+pl_set_QuickLink_features(struct usbnet *dev, int val)
+{
+ return pl_vendor_req(dev, 3, (u8) val, 0);
+}
+
+static int pl_reset(struct usbnet *dev)
+{
+ /* some units seem to need this reset, others reject it utterly.
+ * FIXME be more like "naplink" or windows drivers.
+ */
+ (void) pl_set_QuickLink_features(dev,
+ PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
+ return 0;
+}
+
+static const struct driver_info prolific_info = {
+ .description = "Prolific PL-2301/PL-2302",
+ .flags = FLAG_NO_SETINT,
+ /* some PL-2302 versions seem to fail usb_set_interface() */
+ .reset = pl_reset,
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Proilific's name won't normally be on the cables, and
+ * may not be on the device.
+ */
+
+static const struct usb_device_id products [] = {
+
+{
+ USB_DEVICE(0x067b, 0x0000), // PL-2301
+ .driver_info = (unsigned long) &prolific_info,
+}, {
+ USB_DEVICE(0x067b, 0x0001), // PL-2302
+ .driver_info = (unsigned long) &prolific_info,
+},
+
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver plusb_driver = {
+ .owner = THIS_MODULE,
+ .name = "plusb",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init plusb_init(void)
+{
+ return usb_register(&plusb_driver);
+}
+module_init(plusb_init);
+
+static void __exit plusb_exit(void)
+{
+ usb_deregister(&plusb_driver);
+}
+module_exit(plusb_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("Prolific PL-2301/2302 USB Host to Host Link Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
new file mode 100644
index 000000000000..b5a925dc1beb
--- /dev/null
+++ b/drivers/usb/net/rndis_host.c
@@ -0,0 +1,615 @@
+/*
+ * Host Side support for RNDIS Networking Links
+ * Copyright (C) 2005 by 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of
+ * course ACM was intended for modems, not Ethernet links! USB's standard
+ * for Ethernet links is "CDC Ethernet", which is significantly simpler.
+ */
+
+/*
+ * CONTROL uses CDC "encapsulated commands" with funky notifications.
+ * - control-out: SEND_ENCAPSULATED
+ * - interrupt-in: RESPONSE_AVAILABLE
+ * - control-in: GET_ENCAPSULATED
+ *
+ * We'll try to ignore the RESPONSE_AVAILABLE notifications.
+ */
+struct rndis_msg_hdr {
+ __le32 msg_type; /* RNDIS_MSG_* */
+ __le32 msg_len;
+ // followed by data that varies between messages
+ __le32 request_id;
+ __le32 status;
+ // ... and more
+} __attribute__ ((packed));
+
+/* RNDIS defines this (absurdly huge) control timeout */
+#define RNDIS_CONTROL_TIMEOUT_MS (10 * 1000)
+
+
+#define ccpu2 __constant_cpu_to_le32
+
+#define RNDIS_MSG_COMPLETION ccpu2(0x80000000)
+
+/* codes for "msg_type" field of rndis messages;
+ * only the data channel uses packet messages (maybe batched);
+ * everything else goes on the control channel.
+ */
+#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */
+#define RNDIS_MSG_INIT ccpu2(0x00000002)
+#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_HALT ccpu2(0x00000003)
+#define RNDIS_MSG_QUERY ccpu2(0x00000004)
+#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_SET ccpu2(0x00000005)
+#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_RESET ccpu2(0x00000006)
+#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_INDICATE ccpu2(0x00000007)
+#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008)
+#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
+
+/* codes for "status" field of completion messages */
+#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
+#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001)
+#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015)
+#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb)
+#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b)
+#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c)
+
+
+struct rndis_data_hdr {
+ __le32 msg_type; /* RNDIS_MSG_PACKET */
+ __le32 msg_len; // rndis_data_hdr + data_len + pad
+ __le32 data_offset; // 36 -- right after header
+ __le32 data_len; // ... real packet size
+
+ __le32 oob_data_offset; // zero
+ __le32 oob_data_len; // zero
+ __le32 num_oob; // zero
+ __le32 packet_data_offset; // zero
+
+ __le32 packet_data_len; // zero
+ __le32 vc_handle; // zero
+ __le32 reserved; // zero
+} __attribute__ ((packed));
+
+struct rndis_init { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INIT */
+ __le32 msg_len; // 24
+ __le32 request_id;
+ __le32 major_version; // of rndis (1.0)
+ __le32 minor_version;
+ __le32 max_transfer_size;
+} __attribute__ ((packed));
+
+struct rndis_init_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INIT_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+ __le32 major_version; // of rndis (1.0)
+ __le32 minor_version;
+ __le32 device_flags;
+ __le32 medium; // zero == 802.3
+ __le32 max_packets_per_message;
+ __le32 max_transfer_size;
+ __le32 packet_alignment; // max 7; (1<<n) bytes
+ __le32 af_list_offset; // zero
+ __le32 af_list_size; // zero
+} __attribute__ ((packed));
+
+struct rndis_halt { /* OUT (no reply) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_HALT */
+ __le32 msg_len;
+ __le32 request_id;
+} __attribute__ ((packed));
+
+struct rndis_query { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_QUERY */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 oid;
+ __le32 len;
+ __le32 offset;
+/*?*/ __le32 handle; // zero
+} __attribute__ ((packed));
+
+struct rndis_query_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_QUERY_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+ __le32 len;
+ __le32 offset;
+} __attribute__ ((packed));
+
+struct rndis_set { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_SET */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 oid;
+ __le32 len;
+ __le32 offset;
+/*?*/ __le32 handle; // zero
+} __attribute__ ((packed));
+
+struct rndis_set_c { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_SET_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+} __attribute__ ((packed));
+
+struct rndis_reset { /* IN */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_RESET */
+ __le32 msg_len;
+ __le32 reserved;
+} __attribute__ ((packed));
+
+struct rndis_reset_c { /* OUT */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_RESET_C */
+ __le32 msg_len;
+ __le32 status;
+ __le32 addressing_lost;
+} __attribute__ ((packed));
+
+struct rndis_indicate { /* IN (unrequested) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_INDICATE */
+ __le32 msg_len;
+ __le32 status;
+ __le32 length;
+ __le32 offset;
+/**/ __le32 diag_status;
+ __le32 error_offset;
+/**/ __le32 message;
+} __attribute__ ((packed));
+
+struct rndis_keepalive { /* OUT (optionally IN) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */
+ __le32 msg_len;
+ __le32 request_id;
+} __attribute__ ((packed));
+
+struct rndis_keepalive_c { /* IN (optionally OUT) */
+ // header and:
+ __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */
+ __le32 msg_len;
+ __le32 request_id;
+ __le32 status;
+} __attribute__ ((packed));
+
+/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and
+ * there are gobs more that may optionally be supported. We'll avoid as much
+ * of that mess as possible.
+ */
+#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101)
+#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e)
+
+/*
+ * RNDIS notifications from device: command completion; "reverse"
+ * keepalives; etc
+ */
+static void rndis_status(struct usbnet *dev, struct urb *urb)
+{
+ devdbg(dev, "rndis status urb, len %d stat %d",
+ urb->actual_length, urb->status);
+ // FIXME for keepalives, respond immediately (asynchronously)
+ // if not an RNDIS status, do like cdc_status(dev,urb) does
+}
+
+/*
+ * RPC done RNDIS-style. Caller guarantees:
+ * - message is properly byteswapped
+ * - there's no other request pending
+ * - buf can hold up to 1KB response (required by RNDIS spec)
+ * On return, the first few entries are already byteswapped.
+ *
+ * Call context is likely probe(), before interface name is known,
+ * which is why we won't try to use it in the diagnostics.
+ */
+static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
+{
+ struct cdc_state *info = (void *) &dev->data;
+ int retval;
+ unsigned count;
+ __le32 rsp;
+ u32 xid = 0, msg_len, request_id;
+
+ /* REVISIT when this gets called from contexts other than probe() or
+ * disconnect(): either serialize, or dispatch responses on xid
+ */
+
+ /* Issue the request; don't bother byteswapping our xid */
+ if (likely(buf->msg_type != RNDIS_MSG_HALT
+ && buf->msg_type != RNDIS_MSG_RESET)) {
+ xid = dev->xid++;
+ if (!xid)
+ xid = dev->xid++;
+ buf->request_id = (__force __le32) xid;
+ }
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ buf, le32_to_cpu(buf->msg_len),
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (unlikely(retval < 0 || xid == 0))
+ return retval;
+
+ // FIXME Seems like some devices discard responses when
+ // we time out and cancel our "get response" requests...
+ // so, this is fragile. Probably need to poll for status.
+
+ /* ignore status endpoint, just poll the control channel;
+ * the request probably completed immediately
+ */
+ rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
+ for (count = 0; count < 10; count++) {
+ memset(buf, 0, 1024);
+ retval = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ USB_CDC_GET_ENCAPSULATED_RESPONSE,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ buf, 1024,
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (likely(retval >= 8)) {
+ msg_len = le32_to_cpu(buf->msg_len);
+ request_id = (__force u32) buf->request_id;
+ if (likely(buf->msg_type == rsp)) {
+ if (likely(request_id == xid)) {
+ if (unlikely(rsp == RNDIS_MSG_RESET_C))
+ return 0;
+ if (likely(RNDIS_STATUS_SUCCESS
+ == buf->status))
+ return 0;
+ dev_dbg(&info->control->dev,
+ "rndis reply status %08x\n",
+ le32_to_cpu(buf->status));
+ return -EL3RST;
+ }
+ dev_dbg(&info->control->dev,
+ "rndis reply id %d expected %d\n",
+ request_id, xid);
+ /* then likely retry */
+ } else switch (buf->msg_type) {
+ case RNDIS_MSG_INDICATE: { /* fault */
+ // struct rndis_indicate *msg = (void *)buf;
+ dev_info(&info->control->dev,
+ "rndis fault indication\n");
+ }
+ break;
+ case RNDIS_MSG_KEEPALIVE: { /* ping */
+ struct rndis_keepalive_c *msg = (void *)buf;
+
+ msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
+ msg->msg_len = ccpu2(sizeof *msg);
+ msg->status = RNDIS_STATUS_SUCCESS;
+ retval = usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, info->u->bMasterInterface0,
+ msg, sizeof *msg,
+ RNDIS_CONTROL_TIMEOUT_MS);
+ if (unlikely(retval < 0))
+ dev_dbg(&info->control->dev,
+ "rndis keepalive err %d\n",
+ retval);
+ }
+ break;
+ default:
+ dev_dbg(&info->control->dev,
+ "unexpected rndis msg %08x len %d\n",
+ le32_to_cpu(buf->msg_type), msg_len);
+ }
+ } else {
+ /* device probably issued a protocol stall; ignore */
+ dev_dbg(&info->control->dev,
+ "rndis response error, code %d\n", retval);
+ }
+ msleep(2);
+ }
+ dev_dbg(&info->control->dev, "rndis response timeout\n");
+ return -ETIMEDOUT;
+}
+
+static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int retval;
+ struct net_device *net = dev->net;
+ union {
+ void *buf;
+ struct rndis_msg_hdr *header;
+ struct rndis_init *init;
+ struct rndis_init_c *init_c;
+ struct rndis_query *get;
+ struct rndis_query_c *get_c;
+ struct rndis_set *set;
+ struct rndis_set_c *set_c;
+ } u;
+ u32 tmp;
+
+ /* we can't rely on i/o from stack working, or stack allocation */
+ u.buf = kmalloc(1024, GFP_KERNEL);
+ if (!u.buf)
+ return -ENOMEM;
+ retval = usbnet_generic_cdc_bind(dev, intf);
+ if (retval < 0)
+ goto done;
+
+ net->hard_header_len += sizeof (struct rndis_data_hdr);
+
+ /* initialize; max transfer is 16KB at full speed */
+ u.init->msg_type = RNDIS_MSG_INIT;
+ u.init->msg_len = ccpu2(sizeof *u.init);
+ u.init->major_version = ccpu2(1);
+ u.init->minor_version = ccpu2(0);
+ u.init->max_transfer_size = ccpu2(net->mtu + net->hard_header_len);
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ /* it might not even be an RNDIS device!! */
+ dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
+fail:
+ usb_driver_release_interface(driver_of(intf),
+ ((struct cdc_state *)&(dev->data))->data);
+ goto done;
+ }
+ dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size);
+ /* REVISIT: peripheral "alignment" request is ignored ... */
+ dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu,
+ 1 << le32_to_cpu(u.init_c->packet_alignment));
+
+ /* get designated host ethernet address */
+ memset(u.get, 0, sizeof *u.get);
+ u.get->msg_type = RNDIS_MSG_QUERY;
+ u.get->msg_len = ccpu2(sizeof *u.get);
+ u.get->oid = OID_802_3_PERMANENT_ADDRESS;
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
+ goto fail;
+ }
+ tmp = le32_to_cpu(u.get_c->offset);
+ if (unlikely((tmp + 8) > (1024 - ETH_ALEN)
+ || u.get_c->len != ccpu2(ETH_ALEN))) {
+ dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
+ tmp, le32_to_cpu(u.get_c->len));
+ retval = -EDOM;
+ goto fail;
+ }
+ memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
+
+ /* set a nonzero filter to enable data transfers */
+ memset(u.set, 0, sizeof *u.set);
+ u.set->msg_type = RNDIS_MSG_SET;
+ u.set->msg_len = ccpu2(4 + sizeof *u.set);
+ u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
+ u.set->len = ccpu2(4);
+ u.set->offset = ccpu2((sizeof *u.set) - 8);
+ *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER);
+
+ retval = rndis_command(dev, u.header);
+ if (unlikely(retval < 0)) {
+ dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
+ goto fail;
+ }
+
+ retval = 0;
+done:
+ kfree(u.buf);
+ return retval;
+}
+
+static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct rndis_halt *halt;
+
+ /* try to clear any rndis state/activity (no i/o from stack!) */
+ halt = kcalloc(1, sizeof *halt, SLAB_KERNEL);
+ if (halt) {
+ halt->msg_type = RNDIS_MSG_HALT;
+ halt->msg_len = ccpu2(sizeof *halt);
+ (void) rndis_command(dev, (void *)halt);
+ kfree(halt);
+ }
+
+ return usbnet_cdc_unbind(dev, intf);
+}
+
+/*
+ * DATA -- host must not write zlps
+ */
+static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ /* peripheral may have batched packets to us... */
+ while (likely(skb->len)) {
+ struct rndis_data_hdr *hdr = (void *)skb->data;
+ struct sk_buff *skb2;
+ u32 msg_len, data_offset, data_len;
+
+ msg_len = le32_to_cpu(hdr->msg_len);
+ data_offset = le32_to_cpu(hdr->data_offset);
+ data_len = le32_to_cpu(hdr->data_len);
+
+ /* don't choke if we see oob, per-packet data, etc */
+ if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
+ || skb->len < msg_len
+ || (data_offset + data_len + 8) > msg_len)) {
+ dev->stats.rx_frame_errors++;
+ devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
+ le32_to_cpu(hdr->msg_type),
+ msg_len, data_offset, data_len, skb->len);
+ return 0;
+ }
+ skb_pull(skb, 8 + data_offset);
+
+ /* at most one packet left? */
+ if (likely((data_len - skb->len) <= sizeof *hdr)) {
+ skb_trim(skb, data_len);
+ break;
+ }
+
+ /* try to return all the packets in the batch */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ break;
+ skb_pull(skb, msg_len - sizeof *hdr);
+ skb_trim(skb2, data_len);
+ usbnet_skb_return(dev, skb2);
+ }
+
+ /* caller will usbnet_skb_return the remaining packet */
+ return 1;
+}
+
+static struct sk_buff *
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ struct rndis_data_hdr *hdr;
+ struct sk_buff *skb2;
+ unsigned len = skb->len;
+
+ if (likely(!skb_cloned(skb))) {
+ int room = skb_headroom(skb);
+
+ /* enough head room as-is? */
+ if (unlikely((sizeof *hdr) <= room))
+ goto fill;
+
+ /* enough room, but needs to be readjusted? */
+ room += skb_tailroom(skb);
+ if (likely((sizeof *hdr) <= room)) {
+ skb->data = memmove(skb->head + sizeof *hdr,
+ skb->data, len);
+ skb->tail = skb->data + len;
+ goto fill;
+ }
+ }
+
+ /* create a new skb, with the correct size (and tailpad) */
+ skb2 = skb_copy_expand(skb, sizeof *hdr, 1, flags);
+ dev_kfree_skb_any(skb);
+ if (unlikely(!skb2))
+ return skb2;
+ skb = skb2;
+
+ /* fill out the RNDIS header. we won't bother trying to batch
+ * packets; Linux minimizes wasted bandwidth through tx queues.
+ */
+fill:
+ hdr = (void *) __skb_push(skb, sizeof *hdr);
+ memset(hdr, 0, sizeof *hdr);
+ hdr->msg_type = RNDIS_MSG_PACKET;
+ hdr->msg_len = cpu_to_le32(skb->len);
+ hdr->data_offset = ccpu2(sizeof(*hdr) - 8);
+ hdr->data_len = cpu_to_le32(len);
+
+ /* FIXME make the last packet always be short ... */
+ return skb;
+}
+
+
+static const struct driver_info rndis_info = {
+ .description = "RNDIS device",
+ .flags = FLAG_ETHER | FLAG_FRAMING_RN,
+ .bind = rndis_bind,
+ .unbind = rndis_unbind,
+ .status = rndis_status,
+ .rx_fixup = rndis_rx_fixup,
+ .tx_fixup = rndis_tx_fixup,
+};
+
+#undef ccpu2
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products [] = {
+{
+ /* RNDIS is MSFT's un-official variant of CDC ACM */
+ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+ .driver_info = (unsigned long) &rndis_info,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver rndis_driver = {
+ .owner = THIS_MODULE,
+ .name = "rndis_host",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init rndis_init(void)
+{
+ return usb_register(&rndis_driver);
+}
+module_init(rndis_init);
+
+static void __exit rndis_exit(void)
+{
+ usb_deregister(&rndis_driver);
+}
+module_exit(rndis_exit);
+
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB Host side RNDIS driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 59ab40ebb394..787dd3591d6a 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -653,7 +653,6 @@ static void rtl8150_tx_timeout(struct net_device *netdev)
{
rtl8150_t *dev = netdev_priv(netdev);
warn("%s: Tx timeout.", netdev->name);
- dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(dev->tx_urb);
dev->stats.tx_errors++;
}
@@ -910,6 +909,7 @@ static void rtl8150_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (dev) {
set_bit(RTL8150_UNPLUG, &dev->flags);
+ tasklet_disable(&dev->tl);
unregister_netdev(dev->netdev);
unlink_all_urbs(dev);
free_all_urbs(dev);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 576f3b852fce..74f05c9c84d5 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -1,10 +1,7 @@
/*
- * USB Networking Links
- * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
- * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
+ * USB Network driver infrastructure
+ * Copyright (C) 2000-2005 by David Brownell
* Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
- * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
- * Copyright (c) 2002-2003 TiVo Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,95 +20,15 @@
/*
* This is a generic "USB networking" framework that works with several
- * kinds of full and high speed networking devices:
- *
- * + USB host-to-host "network cables", used for IP-over-USB links.
- * These are often used for Laplink style connectivity products.
- * - AnchorChip 2720
- * - Belkin, eTEK (interops with Win32 drivers)
- * - GeneSys GL620USB-A
- * - NetChip 1080 (interoperates with NetChip Win32 drivers)
- * - Prolific PL-2301/2302 (replaces "plusb" driver)
- * - KC Technology KC2190
- *
- * + Smart USB devices can support such links directly, using Internet
- * standard protocols instead of proprietary host-to-device links.
- * - Linux PDAs like iPaq, Yopy, and Zaurus
- * - The BLOB boot loader (for diskless booting)
- * - Linux "gadgets", perhaps using PXA-2xx or Net2280 controllers
- * - Devices using EPSON's sample USB firmware
- * - CDC-Ethernet class devices, such as many cable modems
- *
- * + Adapters to networks such as Ethernet.
- * - AX8817X based USB 2.0 products
- *
- * Links to these devices can be bridged using Linux Ethernet bridging.
- * With minor exceptions, these all use similar USB framing for network
- * traffic, but need different protocols for control traffic.
- *
- * USB devices can implement their side of this protocol at the cost
- * of two bulk endpoints; it's not restricted to "cable" applications.
- * See the SA1110, Zaurus, or EPSON device/client support in this driver;
- * slave/target drivers such as "usb-eth" (on most SA-1100 PDAs) or
- * "g_ether" (in the Linux "gadget" framework) implement that behavior
- * within devices.
- *
- *
- * CHANGELOG:
- *
- * 13-sep-2000 experimental, new
- * 10-oct-2000 usb_device_id table created.
- * 28-oct-2000 misc fixes; mostly, discard more TTL-mangled rx packets.
- * 01-nov-2000 usb_device_id table and probing api update by
- * Adam J. Richter <adam@yggdrasil.com>.
- * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info
- * and prolific support, isolate net1080-specific bits, cleanup.
- * fix unlink_urbs oops in D3 PM resume code path.
- *
- * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ...
- * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it;
- * AnchorChips 2720 support (from spec) for testing;
- * fix bit-ordering problem with ethernet multicast addr
- * 19-feb-2001 Support for clearing halt conditions. SA1100 UDC support
- * updates. Oleg Drokin (green@iXcelerator.com)
- * 25-mar-2001 More SA-1100 updates, including workaround for ip problem
- * expecting cleared skb->cb and framing change to match latest
- * handhelds.org version (Oleg). Enable device IDs from the
- * Win32 Belkin driver; other cleanups (db).
- * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various
- * cleanups for problems not yet seen in the field. (db)
- * 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
- * from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
- * rx unlinks somehow weren't async; minor cleanup.
- * 03-nov-2001 Merged GeneSys driver; original code from Jiun-Jie Huang
- * <huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec
- * <utx@penguin.cz>. Made framing options (NetChip/GeneSys)
- * tie mostly to (sub)driver info. Workaround some PL-2302
- * chips that seem to reject SET_INTERFACE requests.
- *
- * 06-apr-2002 Added ethtool support, based on a patch from Brad Hards.
- * Level of diagnostics is more configurable; they use device
- * location (usb_device->devpath) instead of address (2.5).
- * For tx_fixup, memflags can't be NOIO.
- * 07-may-2002 Generalize/cleanup keventd support, handling rx stalls (mostly
- * for USB 2.0 TTs) and memory shortages (potential) too. (db)
- * Use "locally assigned" IEEE802 address space. (Brad Hards)
- * 18-oct-2002 Support for Zaurus (Pavel Machek), related cleanup (db).
- * 14-dec-2002 Remove Zaurus-private crc32 code (Pavel); 2.5 oops fix,
- * cleanups and stubbed PXA-250 support (db), fix for framing
- * issues on Z, net1080, and gl620a (Toby Milne)
- *
- * 31-mar-2003 Use endpoint descriptors: high speed support, simpler sa1100
- * vs pxa25x, and CDC Ethernet. Throttle down log floods on
- * disconnect; other cleanups. (db) Flush net1080 fifos
- * after several sequential framing errors. (Johannes Erdfelt)
- * 22-aug-2003 AX8817X support (Dave Hollis).
- * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan
- * (Neil Bortnak)
- * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
- *
- * 01-feb-2005 AX88772 support (Phil Chang & Dave Hollis)
- *-------------------------------------------------------------------------*/
+ * kinds of full and high speed networking devices: host-to-host cables,
+ * smart usb peripherals, and actual Ethernet adapters.
+ *
+ * These devices usually differ in terms of control protocols (if they
+ * even have one!) and sometimes they define new framing to wrap or batch
+ * Ethernet packets. Otherwise, they talk to USB pretty much the same,
+ * so interface (un)binding, endpoint I/O queues, fault handling, and other
+ * issues can usefully be addressed by this framework.
+ */
// #define DEBUG // error path messages, extra info
// #define VERBOSE // more; success messages
@@ -121,24 +38,18 @@
# define DEBUG
#endif
#include <linux/module.h>
-#include <linux/kmod.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/random.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
#include <linux/usb.h>
-#include <asm/io.h>
-#include <asm/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/dma-mapping.h>
-#define DRIVER_VERSION "03-Nov-2004"
+#include "usbnet.h"
+
+#define DRIVER_VERSION "22-Aug-2005"
/*-------------------------------------------------------------------------*/
@@ -149,15 +60,14 @@
* One maximum size Ethernet packet takes twenty four of them.
* For high speed, each frame comfortably fits almost 36 max size
* Ethernet packets (so queues should be bigger).
+ *
+ * REVISIT qlens should be members of 'struct usbnet'; the goal is to
+ * let the USB host controller be busy for 5msec or more before an irq
+ * is required, under load. Jumbograms change the equation.
*/
#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-// packets are always ethernet inside
-// ... except they can be bigger (limit of 64K with NetChip framing)
-#define MIN_PACKET sizeof(struct ethhdr)
-#define MAX_PACKET 32768
-
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
@@ -165,9 +75,6 @@
// us (it polls at HZ/4 usually) before we report too many false errors.
#define THROTTLE_JIFFIES (HZ/8)
-// for vendor-specific control operations
-#define CONTROL_TIMEOUT_MS 500
-
// between wakeups
#define UNLINK_TIMEOUT_MS 3
@@ -176,109 +83,6 @@
// randomly generated ethernet address
static u8 node_id [ETH_ALEN];
-// state we keep for each device we handle
-struct usbnet {
- // housekeeping
- struct usb_device *udev;
- struct driver_info *driver_info;
- wait_queue_head_t *wait;
-
- // i/o info: pipes etc
- unsigned in, out;
- struct usb_host_endpoint *status;
- unsigned maxpacket;
- struct timer_list delay;
-
- // protocol/interface state
- struct net_device *net;
- struct net_device_stats stats;
- int msg_enable;
- unsigned long data [5];
-
- struct mii_if_info mii;
-
- // various kinds of pending driver work
- struct sk_buff_head rxq;
- struct sk_buff_head txq;
- struct sk_buff_head done;
- struct urb *interrupt;
- struct tasklet_struct bh;
-
- struct work_struct kevent;
- unsigned long flags;
-# define EVENT_TX_HALT 0
-# define EVENT_RX_HALT 1
-# define EVENT_RX_MEMORY 2
-# define EVENT_STS_SPLIT 3
-# define EVENT_LINK_RESET 4
-};
-
-// device-specific info used by the driver
-struct driver_info {
- char *description;
-
- int flags;
-/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
-#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
-#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
-#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
-#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
-
-#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
-#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
-
-#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
-
- /* init device ... can sleep, or cause probe() failure */
- int (*bind)(struct usbnet *, struct usb_interface *);
-
- /* cleanup device ... can sleep, but can't fail */
- void (*unbind)(struct usbnet *, struct usb_interface *);
-
- /* reset device ... can sleep */
- int (*reset)(struct usbnet *);
-
- /* see if peer is connected ... can sleep */
- int (*check_connect)(struct usbnet *);
-
- /* for status polling */
- void (*status)(struct usbnet *, struct urb *);
-
- /* link reset handling, called from defer_kevent */
- int (*link_reset)(struct usbnet *);
-
- /* fixup rx packet (strip framing) */
- int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
-
- /* fixup tx packet (add framing) */
- struct sk_buff *(*tx_fixup)(struct usbnet *dev,
- struct sk_buff *skb, int flags);
-
- // FIXME -- also an interrupt mechanism
- // useful for at least PL2301/2302 and GL620USB-A
- // and CDC use them to report 'is it connected' changes
-
- /* for new devices, use the descriptor-reading code instead */
- int in; /* rx endpoint */
- int out; /* tx endpoint */
-
- unsigned long data; /* Misc driver specific data */
-};
-
-// we record the state for each of our queued skbs
-enum skb_state {
- illegal = 0,
- tx_start, tx_done,
- rx_start, rx_done, rx_cleanup
-};
-
-struct skb_data { // skb->cb is one of these
- struct urb *urb;
- struct usbnet *dev;
- enum skb_state state;
- size_t length;
-};
-
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
@@ -286,39 +90,10 @@ static int msg_level = -1;
module_param (msg_level, int, 0);
MODULE_PARM_DESC (msg_level, "Override default message level");
-
-#ifdef DEBUG
-#define devdbg(usbnet, fmt, arg...) \
- printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-#else
-#define devdbg(usbnet, fmt, arg...) do {} while(0)
-#endif
-
-#define deverr(usbnet, fmt, arg...) \
- printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-#define devwarn(usbnet, fmt, arg...) \
- printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
-
-#define devinfo(usbnet, fmt, arg...) \
- printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
-
/*-------------------------------------------------------------------------*/
-static void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
-static u32 usbnet_get_link (struct net_device *);
-static u32 usbnet_get_msglevel (struct net_device *);
-static void usbnet_set_msglevel (struct net_device *, u32);
-static void defer_kevent (struct usbnet *, int);
-
-/* mostly for PDA style devices, which are always connected if present */
-static int always_connected (struct usbnet *dev)
-{
- return 0;
-}
-
/* handles CDC Ethernet and many other network "bulk data" interfaces */
-static int
-get_endpoints (struct usbnet *dev, struct usb_interface *intf)
+int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
{
int tmp;
struct usb_host_interface *alt = NULL;
@@ -382,6 +157,7 @@ get_endpoints (struct usbnet *dev, struct usb_interface *intf)
dev->status = status;
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_get_endpoints);
static void intr_complete (struct urb *urb, struct pt_regs *regs);
@@ -421,7 +197,11 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
return 0;
}
-static void skb_return (struct usbnet *dev, struct sk_buff *skb)
+/* Passes this packet up the stack, updating its accounting.
+ * Some link protocols batch packets, so their rx_fixup paths
+ * can return clones as well as just modify the original skb.
+ */
+void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
{
int status;
@@ -438,2425 +218,7 @@ static void skb_return (struct usbnet *dev, struct sk_buff *skb)
if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
devdbg (dev, "netif_rx status %d", status);
}
-
-
-#ifdef CONFIG_USB_ALI_M5632
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * ALi M5632 driver ... does high speed
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info ali_m5632_info = {
- .description = "ALi M5632",
-};
-
-
-#endif
-
-
-#ifdef CONFIG_USB_AN2720
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * AnchorChips 2720 driver ... http://www.cypress.com
- *
- * This doesn't seem to have a way to detect whether the peer is
- * connected, or need any reset handshaking. It's got pretty big
- * internal buffers (handles most of a frame's worth of data).
- * Chip data sheets don't describe any vendor control messages.
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info an2720_info = {
- .description = "AnchorChips/Cypress 2720",
- // no reset available!
- // no check_connect available!
-
- .in = 2, .out = 2, // direction distinguishes these
-};
-
-#endif /* CONFIG_USB_AN2720 */
-
-
-#ifdef CONFIG_USB_AX8817X
-/* ASIX AX8817X based USB 2.0 Ethernet Devices */
-
-#define HAVE_HARDWARE
-#define NEED_MII
-
-#include <linux/crc32.h>
-
-#define AX_CMD_SET_SW_MII 0x06
-#define AX_CMD_READ_MII_REG 0x07
-#define AX_CMD_WRITE_MII_REG 0x08
-#define AX_CMD_SET_HW_MII 0x0a
-#define AX_CMD_READ_EEPROM 0x0b
-#define AX_CMD_WRITE_EEPROM 0x0c
-#define AX_CMD_WRITE_ENABLE 0x0d
-#define AX_CMD_WRITE_DISABLE 0x0e
-#define AX_CMD_WRITE_RX_CTL 0x10
-#define AX_CMD_READ_IPG012 0x11
-#define AX_CMD_WRITE_IPG0 0x12
-#define AX_CMD_WRITE_IPG1 0x13
-#define AX_CMD_WRITE_IPG2 0x14
-#define AX_CMD_WRITE_MULTI_FILTER 0x16
-#define AX_CMD_READ_NODE_ID 0x17
-#define AX_CMD_READ_PHY_ID 0x19
-#define AX_CMD_READ_MEDIUM_STATUS 0x1a
-#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
-#define AX_CMD_READ_MONITOR_MODE 0x1c
-#define AX_CMD_WRITE_MONITOR_MODE 0x1d
-#define AX_CMD_WRITE_GPIOS 0x1f
-#define AX_CMD_SW_RESET 0x20
-#define AX_CMD_SW_PHY_STATUS 0x21
-#define AX_CMD_SW_PHY_SELECT 0x22
-#define AX88772_CMD_READ_NODE_ID 0x13
-
-#define AX_MONITOR_MODE 0x01
-#define AX_MONITOR_LINK 0x02
-#define AX_MONITOR_MAGIC 0x04
-#define AX_MONITOR_HSFS 0x10
-
-/* AX88172 Medium Status Register values */
-#define AX_MEDIUM_FULL_DUPLEX 0x02
-#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
-#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
-
-#define AX_MCAST_FILTER_SIZE 8
-#define AX_MAX_MCAST 64
-
-#define AX_EEPROM_LEN 0x40
-
-#define AX_SWRESET_CLEAR 0x00
-#define AX_SWRESET_RR 0x01
-#define AX_SWRESET_RT 0x02
-#define AX_SWRESET_PRTE 0x04
-#define AX_SWRESET_PRL 0x08
-#define AX_SWRESET_BZ 0x10
-#define AX_SWRESET_IPRL 0x20
-#define AX_SWRESET_IPPD 0x40
-
-#define AX88772_IPG0_DEFAULT 0x15
-#define AX88772_IPG1_DEFAULT 0x0c
-#define AX88772_IPG2_DEFAULT 0x12
-
-#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
-#define AX88772_MEDIUM_RESERVED 0x0004
-#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
-#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
-#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
-#define AX88772_MEDIUM_RX_ENABLE 0x0100
-#define AX88772_MEDIUM_100MB 0x0200
-#define AX88772_MEDIUM_DEFAULT \
- (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
- AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
- AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
-
-#define AX_EEPROM_MAGIC 0xdeadbeef
-
-/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct ax8817x_data {
- u8 multi_filter[AX_MCAST_FILTER_SIZE];
-};
-
-struct ax88172_int_data {
- u16 res1;
- u8 link;
- u16 res2;
- u8 status;
- u16 res3;
-} __attribute__ ((packed));
-
-static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- return usb_control_msg(
- dev->udev,
- usb_rcvctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- data,
- size,
- CONTROL_TIMEOUT_MS);
-}
-
-static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- return usb_control_msg(
- dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- cmd,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- data,
- size,
- CONTROL_TIMEOUT_MS);
-}
-
-static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
-{
- struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-
- if (urb->status < 0)
- printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
- urb->status);
-
- kfree(req);
- usb_free_urb(urb);
-}
-
-static void ax8817x_status(struct usbnet *dev, struct urb *urb)
-{
- struct ax88172_int_data *event;
- int link;
-
- if (urb->actual_length < 8)
- return;
-
- event = urb->transfer_buffer;
- link = event->link & 0x01;
- if (netif_carrier_ok(dev->net) != link) {
- if (link) {
- netif_carrier_on(dev->net);
- defer_kevent (dev, EVENT_LINK_RESET );
- } else
- netif_carrier_off(dev->net);
- devdbg(dev, "ax8817x - Link Status is: %d", link);
- }
-}
-
-static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- struct usb_ctrlrequest *req;
- int status;
- struct urb *urb;
-
- if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
- devdbg(dev, "Error allocating URB in write_cmd_async!");
- return;
- }
-
- if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
- deverr(dev, "Failed to allocate memory for control request");
- usb_free_urb(urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- req->bRequest = cmd;
- req->wValue = cpu_to_le16(value);
- req->wIndex = cpu_to_le16(index);
- req->wLength = cpu_to_le16(size);
-
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, size,
- ax8817x_async_cmd_callback, req);
-
- if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- deverr(dev, "Error submitting the control message: status=%d", status);
- kfree(req);
- usb_free_urb(urb);
- }
-}
-
-static void ax8817x_set_multicast(struct net_device *net)
-{
- struct usbnet *dev = netdev_priv(net);
- struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
- u8 rx_ctl = 0x8c;
-
- if (net->flags & IFF_PROMISC) {
- rx_ctl |= 0x01;
- } else if (net->flags & IFF_ALLMULTI
- || net->mc_count > AX_MAX_MCAST) {
- rx_ctl |= 0x02;
- } else if (net->mc_count == 0) {
- /* just broadcast and directed */
- } else {
- /* We use the 20 byte dev->data
- * for our 8 byte filter buffer
- * to avoid allocating memory that
- * is tricky to free later */
- struct dev_mc_list *mc_list = net->mc_list;
- u32 crc_bits;
- int i;
-
- memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
-
- /* Build the multicast hash filter. */
- for (i = 0; i < net->mc_count; i++) {
- crc_bits =
- ether_crc(ETH_ALEN,
- mc_list->dmi_addr) >> 26;
- data->multi_filter[crc_bits >> 3] |=
- 1 << (crc_bits & 7);
- mc_list = mc_list->next;
- }
-
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
- AX_MCAST_FILTER_SIZE, data->multi_filter);
-
- rx_ctl |= 0x10;
- }
-
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
-}
-
-static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
-{
- struct usbnet *dev = netdev_priv(netdev);
- u16 res;
- u8 buf[1];
-
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
-
- return res & 0xffff;
-}
-
-static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
-{
- struct usbnet *dev = netdev_priv(netdev);
- u16 res = val;
- u8 buf[1];
-
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
-}
-
-static int ax88172_link_reset(struct usbnet *dev)
-{
- u16 lpa;
- u8 mode;
-
- mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
- lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
- if (lpa & LPA_DUPLEX)
- mode |= AX_MEDIUM_FULL_DUPLEX;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
-
- return 0;
-}
-
-static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-{
- struct usbnet *dev = netdev_priv(net);
- u8 opt;
-
- if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
- wolinfo->supported = 0;
- wolinfo->wolopts = 0;
- return;
- }
- wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
- wolinfo->wolopts = 0;
- if (opt & AX_MONITOR_MODE) {
- if (opt & AX_MONITOR_LINK)
- wolinfo->wolopts |= WAKE_PHY;
- if (opt & AX_MONITOR_MAGIC)
- wolinfo->wolopts |= WAKE_MAGIC;
- }
-}
-
-static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-{
- struct usbnet *dev = netdev_priv(net);
- u8 opt = 0;
- u8 buf[1];
-
- if (wolinfo->wolopts & WAKE_PHY)
- opt |= AX_MONITOR_LINK;
- if (wolinfo->wolopts & WAKE_MAGIC)
- opt |= AX_MONITOR_MAGIC;
- if (opt != 0)
- opt |= AX_MONITOR_MODE;
-
- if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
- opt, 0, 0, &buf) < 0)
- return -EINVAL;
-
- return 0;
-}
-
-static int ax8817x_get_eeprom_len(struct net_device *net)
-{
- return AX_EEPROM_LEN;
-}
-
-static int ax8817x_get_eeprom(struct net_device *net,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct usbnet *dev = netdev_priv(net);
- u16 *ebuf = (u16 *)data;
- int i;
-
- /* Crude hack to ensure that we don't overwrite memory
- * if an odd length is supplied
- */
- if (eeprom->len % 2)
- return -EINVAL;
-
- eeprom->magic = AX_EEPROM_MAGIC;
-
- /* ax8817x returns 2 bytes from eeprom on read */
- for (i=0; i < eeprom->len / 2; i++) {
- if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
- eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
- return -EINVAL;
- }
- return 0;
-}
-
-static void ax8817x_get_drvinfo (struct net_device *net,
- struct ethtool_drvinfo *info)
-{
- /* Inherit standard device info */
- usbnet_get_drvinfo(net, info);
- info->eedump_len = 0x3e;
-}
-
-static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
-{
- struct usbnet *dev = netdev_priv(net);
-
- return mii_ethtool_gset(&dev->mii,cmd);
-}
-
-static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
-{
- struct usbnet *dev = netdev_priv(net);
-
- return mii_ethtool_sset(&dev->mii,cmd);
-}
-
-/* We need to override some ethtool_ops so we require our
- own structure so we don't interfere with other usbnet
- devices that may be connected at the same time. */
-static struct ethtool_ops ax8817x_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
-};
-
-static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
-{
- int ret = 0;
- void *buf;
- int i;
- unsigned long gpio_bits = dev->driver_info->data;
-
- get_endpoints(dev,intf);
-
- buf = kmalloc(ETH_ALEN, GFP_KERNEL);
- if(!buf) {
- ret = -ENOMEM;
- goto out1;
- }
-
- /* Toggle the GPIOs in a manufacturer/model specific way */
- for (i = 2; i >= 0; i--) {
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
- (gpio_bits >> (i * 8)) & 0xff, 0, 0,
- buf)) < 0)
- goto out2;
- msleep(5);
- }
-
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
- dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
- goto out2;
- }
-
- /* Get the MAC address */
- memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
- dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
- goto out2;
- }
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
-
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
- dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
- goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
- ret = -EIO;
- goto out2;
- }
-
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
- dev->mii.phy_id_mask = 0x3f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = *((u8 *)buf + 1);
-
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax8817x_ethtool_ops;
-
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- mii_nway_restart(&dev->mii);
-
- return 0;
-out2:
- kfree(buf);
-out1:
- return ret;
-}
-
-static struct ethtool_ops ax88772_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
-};
-
-static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
-{
- int ret;
- void *buf;
-
- get_endpoints(dev,intf);
-
- buf = kmalloc(6, GFP_KERNEL);
- if(!buf) {
- dbg ("Cannot allocate memory for buffer");
- ret = -ENOMEM;
- goto out1;
- }
-
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
- 0x00B0, 0, 0, buf)) < 0)
- goto out2;
-
- msleep(5);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
- dbg("Select PHY #1 failed: %d", ret);
- goto out2;
- }
-
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) {
- dbg("Failed to power down internal PHY: %d", ret);
- goto out2;
- }
-
- msleep(150);
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) {
- dbg("Failed to perform software reset: %d", ret);
- goto out2;
- }
-
- msleep(150);
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
- dbg("Failed to set Internal/External PHY reset control: %d", ret);
- goto out2;
- }
-
- msleep(150);
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0,
- buf)) < 0) {
- dbg("Failed to reset RX_CTL: %d", ret);
- goto out2;
- }
-
- /* Get the MAC address */
- memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
- dbg("Failed to read MAC address: %d", ret);
- goto out2;
- }
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
-
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) {
- dbg("Enabling software MII failed: %d", ret);
- goto out2;
- }
-
- if (((ret =
- ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
- || (*((u16 *)buf) != 0x003b)) {
- dbg("Read PHY register 2 must be 0x3b00: %d", ret);
- goto out2;
- }
-
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
- dev->mii.phy_id_mask = 0xff;
- dev->mii.reg_num_mask = 0xff;
-
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
- dbg("Error reading PHY ID: %02x", ret);
- goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
- dev->mii.phy_id = *((u8 *)buf + 1);
-
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
- dbg("Set external PHY reset pin level: %d", ret);
- goto out2;
- }
- msleep(150);
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
- dbg("Set Internal/External PHY reset control: %d", ret);
- goto out2;
- }
- msleep(150);
-
-
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax88772_ethtool_ops;
-
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA);
- mii_nway_restart(&dev->mii);
-
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
- dbg("Write medium mode register: %d", ret);
- goto out2;
- }
-
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
- dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
- goto out2;
- }
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
- dbg("Failed to set hardware MII: %02x", ret);
- goto out2;
- }
-
- /* Set RX_CTL to default values with 2k buffer, and enable cactus */
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
- buf)) < 0) {
- dbg("Reset RX_CTL failed: %d", ret);
- goto out2;
- }
-
- kfree(buf);
-
- return 0;
-
-out2:
- kfree(buf);
-out1:
- return ret;
-}
-
-static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-{
- u32 *header;
- char *packet;
- struct sk_buff *ax_skb;
- u16 size;
-
- header = (u32 *) skb->data;
- le32_to_cpus(header);
- packet = (char *)(header + 1);
-
- skb_pull(skb, 4);
-
- while (skb->len > 0) {
- if ((short)(*header & 0x0000ffff) !=
- ~((short)((*header & 0xffff0000) >> 16))) {
- devdbg(dev,"header length data is error");
- }
- /* get the packet length */
- size = (u16) (*header & 0x0000ffff);
-
- if ((skb->len) - ((size + 1) & 0xfffe) == 0)
- return 2;
- if (size > ETH_FRAME_LEN) {
- devdbg(dev,"invalid rx length %d", size);
- return 0;
- }
- ax_skb = skb_clone(skb, GFP_ATOMIC);
- if (ax_skb) {
- ax_skb->len = size;
- ax_skb->data = packet;
- ax_skb->tail = packet + size;
- skb_return(dev, ax_skb);
- } else {
- return 0;
- }
-
- skb_pull(skb, (size + 1) & 0xfffe);
-
- if (skb->len == 0)
- break;
-
- header = (u32 *) skb->data;
- le32_to_cpus(header);
- packet = (char *)(header + 1);
- skb_pull(skb, 4);
- }
-
- if (skb->len < 0) {
- devdbg(dev,"invalid rx length %d", skb->len);
- return 0;
- }
- return 1;
-}
-
-static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- int flags)
-{
- int padlen;
- int headroom = skb_headroom(skb);
- int tailroom = skb_tailroom(skb);
- u32 *packet_len;
- u32 *padbytes_ptr;
-
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
-
- if ((!skb_cloned(skb))
- && ((headroom + tailroom) >= (4 + padlen))) {
- if ((headroom < 4) || (tailroom < padlen)) {
- skb->data = memmove(skb->head + 4, skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- }
- } else {
- struct sk_buff *skb2;
- skb2 = skb_copy_expand(skb, 4, padlen, flags);
- dev_kfree_skb_any(skb);
- skb = skb2;
- if (!skb)
- return NULL;
- }
-
- packet_len = (u32 *) skb_push(skb, 4);
-
- packet_len = (u32 *) skb->data;
- *packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-
- if ((skb->len % 512) == 0) {
- padbytes_ptr = (u32 *) skb->tail;
- *padbytes_ptr = 0xffff0000;
- skb_put(skb, padlen);
- }
- return skb;
-}
-
-static int ax88772_link_reset(struct usbnet *dev)
-{
- u16 lpa;
- u16 mode;
-
- mode = AX88772_MEDIUM_DEFAULT;
- lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
-
- if ((lpa & LPA_DUPLEX) == 0)
- mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
- if ((lpa & LPA_100) == 0)
- mode &= ~AX88772_MEDIUM_100MB;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
-
- return 0;
-}
-
-static const struct driver_info ax8817x_info = {
- .description = "ASIX AX8817x USB 2.0 Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x00130103,
-};
-
-static const struct driver_info dlink_dub_e100_info = {
- .description = "DLink DUB-E100 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x009f9d9f,
-};
-
-static const struct driver_info netgear_fa120_info = {
- .description = "Netgear FA-120 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x00130103,
-};
-
-static const struct driver_info hawking_uf200_info = {
- .description = "Hawking UF200 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
- .link_reset = ax88172_link_reset,
- .reset = ax88172_link_reset,
- .flags = FLAG_ETHER,
- .data = 0x001f1d1f,
-};
-
-static const struct driver_info ax88772_info = {
- .description = "ASIX AX88772 USB 2.0 Ethernet",
- .bind = ax88772_bind,
- .status = ax8817x_status,
- .link_reset = ax88772_link_reset,
- .reset = ax88772_link_reset,
- .flags = FLAG_ETHER | FLAG_FRAMING_AX,
- .rx_fixup = ax88772_rx_fixup,
- .tx_fixup = ax88772_tx_fixup,
- .data = 0x00130103,
-};
-
-#endif /* CONFIG_USB_AX8817X */
-
-
-
-#ifdef CONFIG_USB_BELKIN
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller
- *
- * ... also two eTEK designs, including one sold as "Advance USBNET"
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info belkin_info = {
- .description = "Belkin, eTEK, or compatible",
-};
-
-#endif /* CONFIG_USB_BELKIN */
-
-
-
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class declarations.
- * Used by CDC Ethernet, and some CDC variants
- *
- *-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_CDCETHER
-#define NEED_GENERIC_CDC
-#endif
-
-#ifdef CONFIG_USB_ZAURUS
-/* Ethernet variant uses funky framing, broken ethernet addressing */
-#define NEED_GENERIC_CDC
-#endif
-
-#ifdef CONFIG_USB_RNDIS
-/* ACM variant uses even funkier framing, complex control RPC scheme */
-#define NEED_GENERIC_CDC
-#endif
-
-
-#ifdef NEED_GENERIC_CDC
-
-#include <linux/usb_cdc.h>
-
-struct cdc_state {
- struct usb_cdc_header_desc *header;
- struct usb_cdc_union_desc *u;
- struct usb_cdc_ether_desc *ether;
- struct usb_interface *control;
- struct usb_interface *data;
-};
-
-static struct usb_driver usbnet_driver;
-
-/*
- * probes control interface, claims data interface, collects the bulk
- * endpoints, activates data interface (if needed), maybe sets MTU.
- * all pure cdc, except for certain firmware workarounds.
- */
-static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- u8 *buf = intf->cur_altsetting->extra;
- int len = intf->cur_altsetting->extralen;
- struct usb_interface_descriptor *d;
- struct cdc_state *info = (void *) &dev->data;
- int status;
- int rndis;
-
- if (sizeof dev->data < sizeof *info)
- return -EDOM;
-
- /* expect strict spec conformance for the descriptors, but
- * cope with firmware which stores them in the wrong place
- */
- if (len == 0 && dev->udev->actconfig->extralen) {
- /* Motorola SB4100 (and others: Brad Hards says it's
- * from a Broadcom design) put CDC descriptors here
- */
- buf = dev->udev->actconfig->extra;
- len = dev->udev->actconfig->extralen;
- if (len)
- dev_dbg (&intf->dev,
- "CDC descriptors on config\n");
- }
-
- /* this assumes that if there's a non-RNDIS vendor variant
- * of cdc-acm, it'll fail RNDIS requests cleanly.
- */
- rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
-
- memset (info, 0, sizeof *info);
- info->control = intf;
- while (len > 3) {
- if (buf [1] != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* use bDescriptorSubType to identify the CDC descriptors.
- * We expect devices with CDC header and union descriptors.
- * For CDC Ethernet we need the ethernet descriptor.
- * For RNDIS, ignore two (pointless) CDC modem descriptors
- * in favor of a complicated OID-based RPC scheme doing what
- * CDC Ethernet achieves with a simple descriptor.
- */
- switch (buf [2]) {
- case USB_CDC_HEADER_TYPE:
- if (info->header) {
- dev_dbg (&intf->dev, "extra CDC header\n");
- goto bad_desc;
- }
- info->header = (void *) buf;
- if (info->header->bLength != sizeof *info->header) {
- dev_dbg (&intf->dev, "CDC header len %u\n",
- info->header->bLength);
- goto bad_desc;
- }
- break;
- case USB_CDC_UNION_TYPE:
- if (info->u) {
- dev_dbg (&intf->dev, "extra CDC union\n");
- goto bad_desc;
- }
- info->u = (void *) buf;
- if (info->u->bLength != sizeof *info->u) {
- dev_dbg (&intf->dev, "CDC union len %u\n",
- info->u->bLength);
- goto bad_desc;
- }
-
- /* we need a master/control interface (what we're
- * probed with) and a slave/data interface; union
- * descriptors sort this all out.
- */
- info->control = usb_ifnum_to_if(dev->udev,
- info->u->bMasterInterface0);
- info->data = usb_ifnum_to_if(dev->udev,
- info->u->bSlaveInterface0);
- if (!info->control || !info->data) {
- dev_dbg (&intf->dev,
- "master #%u/%p slave #%u/%p\n",
- info->u->bMasterInterface0,
- info->control,
- info->u->bSlaveInterface0,
- info->data);
- goto bad_desc;
- }
- if (info->control != intf) {
- dev_dbg (&intf->dev, "bogus CDC Union\n");
- /* Ambit USB Cable Modem (and maybe others)
- * interchanges master and slave interface.
- */
- if (info->data == intf) {
- info->data = info->control;
- info->control = intf;
- } else
- goto bad_desc;
- }
-
- /* a data interface altsetting does the real i/o */
- d = &info->data->cur_altsetting->desc;
- if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
- dev_dbg (&intf->dev, "slave class %u\n",
- d->bInterfaceClass);
- goto bad_desc;
- }
- break;
- case USB_CDC_ETHERNET_TYPE:
- if (info->ether) {
- dev_dbg (&intf->dev, "extra CDC ether\n");
- goto bad_desc;
- }
- info->ether = (void *) buf;
- if (info->ether->bLength != sizeof *info->ether) {
- dev_dbg (&intf->dev, "CDC ether len %u\n",
- info->ether->bLength);
- goto bad_desc;
- }
- dev->net->mtu = le16_to_cpup (
- &info->ether->wMaxSegmentSize)
- - ETH_HLEN;
- /* because of Zaurus, we may be ignoring the host
- * side link address we were given.
- */
- break;
- }
-next_desc:
- len -= buf [0]; /* bLength */
- buf += buf [0];
- }
-
- if (!info->header || !info->u || (!rndis && !info->ether)) {
- dev_dbg (&intf->dev, "missing cdc %s%s%sdescriptor\n",
- info->header ? "" : "header ",
- info->u ? "" : "union ",
- info->ether ? "" : "ether ");
- goto bad_desc;
- }
-
- /* claim data interface and set it up ... with side effects.
- * network traffic can't flow until an altsetting is enabled.
- */
- status = usb_driver_claim_interface (&usbnet_driver, info->data, dev);
- if (status < 0)
- return status;
- status = get_endpoints (dev, info->data);
- if (status < 0) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return status;
- }
-
- /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
- dev->status = NULL;
- if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
- struct usb_endpoint_descriptor *desc;
-
- dev->status = &info->control->cur_altsetting->endpoint [0];
- desc = &dev->status->desc;
- if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
- || !(desc->bEndpointAddress & USB_DIR_IN)
- || (le16_to_cpu(desc->wMaxPacketSize)
- < sizeof (struct usb_cdc_notification))
- || !desc->bInterval) {
- dev_dbg (&intf->dev, "bad notification endpoint\n");
- dev->status = NULL;
- }
- }
- if (rndis && !dev->status) {
- dev_dbg (&intf->dev, "missing RNDIS status endpoint\n");
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return -ENODEV;
- }
- return 0;
-
-bad_desc:
- dev_info (&dev->udev->dev, "bad CDC descriptors\n");
- return -ENODEV;
-}
-
-static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
-{
- struct cdc_state *info = (void *) &dev->data;
-
- /* disconnect master --> disconnect slave */
- if (intf == info->control && info->data) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- info->data = NULL;
- }
-
- /* and vice versa (just in case) */
- else if (intf == info->data && info->control) {
- /* ensure immediate exit from usbnet_disconnect */
- usb_set_intfdata(info->control, NULL);
- usb_driver_release_interface (&usbnet_driver, info->control);
- info->control = NULL;
- }
-}
-
-#endif /* NEED_GENERIC_CDC */
-
-
-#ifdef CONFIG_USB_CDCETHER
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class, Ethernet Control model
- *
- * Takes two interfaces. The DATA interface is inactive till an altsetting
- * is selected. Configuration data includes class descriptors.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with.
- *
- *-------------------------------------------------------------------------*/
-
-#include <linux/ctype.h>
-
-
-static void dumpspeed (struct usbnet *dev, __le32 *speeds)
-{
- if (netif_msg_timer (dev))
- devinfo (dev, "link speeds: %u kbps up, %u kbps down",
- __le32_to_cpu(speeds[0]) / 1000,
- __le32_to_cpu(speeds[1]) / 1000);
-}
-
-static void cdc_status (struct usbnet *dev, struct urb *urb)
-{
- struct usb_cdc_notification *event;
-
- if (urb->actual_length < sizeof *event)
- return;
-
- /* SPEED_CHANGE can get split into two 8-byte packets */
- if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) {
- dumpspeed (dev, (__le32 *) urb->transfer_buffer);
- return;
- }
-
- event = urb->transfer_buffer;
- switch (event->bNotificationType) {
- case USB_CDC_NOTIFY_NETWORK_CONNECTION:
- if (netif_msg_timer (dev))
- devdbg (dev, "CDC: carrier %s",
- event->wValue ? "on" : "off");
- if (event->wValue)
- netif_carrier_on(dev->net);
- else
- netif_carrier_off(dev->net);
- break;
- case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
- if (netif_msg_timer (dev))
- devdbg (dev, "CDC: speed change (len %d)",
- urb->actual_length);
- if (urb->actual_length != (sizeof *event + 8))
- set_bit (EVENT_STS_SPLIT, &dev->flags);
- else
- dumpspeed (dev, (__le32 *) &event[1]);
- break;
- // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */
- default:
- deverr (dev, "CDC: unexpected notification %02x!",
- event->bNotificationType);
- break;
- }
-}
-
-static u8 nibble (unsigned char c)
-{
- if (likely (isdigit (c)))
- return c - '0';
- c = toupper (c);
- if (likely (isxdigit (c)))
- return 10 + c - 'A';
- return 0;
-}
-
-static inline int
-get_ethernet_addr (struct usbnet *dev, struct usb_cdc_ether_desc *e)
-{
- int tmp, i;
- unsigned char buf [13];
-
- tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
- if (tmp != 12) {
- dev_dbg (&dev->udev->dev,
- "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp);
- if (tmp >= 0)
- tmp = -EINVAL;
- return tmp;
- }
- for (i = tmp = 0; i < 6; i++, tmp += 2)
- dev->net->dev_addr [i] =
- (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
- return 0;
-}
-
-static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- int status;
- struct cdc_state *info = (void *) &dev->data;
-
- status = generic_cdc_bind (dev, intf);
- if (status < 0)
- return status;
-
- status = get_ethernet_addr (dev, info->ether);
- if (status < 0) {
- usb_set_intfdata(info->data, NULL);
- usb_driver_release_interface (&usbnet_driver, info->data);
- return status;
- }
-
- /* FIXME cdc-ether has some multicast code too, though it complains
- * in routine cases. info->ether describes the multicast support.
- */
- return 0;
-}
-
-static const struct driver_info cdc_info = {
- .description = "CDC Ethernet Device",
- .flags = FLAG_ETHER,
- // .check_connect = cdc_check_connect,
- .bind = cdc_bind,
- .unbind = cdc_unbind,
- .status = cdc_status,
-};
-
-#endif /* CONFIG_USB_CDCETHER */
-
-
-
-#ifdef CONFIG_USB_EPSON2888
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * EPSON USB clients
- *
- * This is the same idea as Linux PDAs (below) except the firmware in the
- * device might not be Tux-powered. Epson provides reference firmware that
- * implements this interface. Product developers can reuse or modify that
- * code, such as by using their own product and vendor codes.
- *
- * Support was from Juro Bystricky <bystricky.juro@erd.epson.com>
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info epson2888_info = {
- .description = "Epson USB Device",
- .check_connect = always_connected,
-
- .in = 4, .out = 3,
-};
-
-#endif /* CONFIG_USB_EPSON2888 */
-
-
-#ifdef CONFIG_USB_GENESYS
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * GeneSys GL620USB-A (www.genesyslogic.com.tw)
- *
- * ... should partially interop with the Win32 driver for this hardware
- * The GeneSys docs imply there's some NDIS issue motivating this framing.
- *
- * Some info from GeneSys:
- * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk.
- * (Some cables, like the BAFO-100c, use the half duplex version.)
- * - For the full duplex model, the low bit of the version code says
- * which side is which ("left/right").
- * - For the half duplex type, a control/interrupt handshake settles
- * the transfer direction. (That's disabled here, partially coded.)
- * A control URB would block until other side writes an interrupt.
- *
- * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
- * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>.
- *
- *-------------------------------------------------------------------------*/
-
-// control msg write command
-#define GENELINK_CONNECT_WRITE 0xF0
-// interrupt pipe index
-#define GENELINK_INTERRUPT_PIPE 0x03
-// interrupt read buffer size
-#define INTERRUPT_BUFSIZE 0x08
-// interrupt pipe interval value
-#define GENELINK_INTERRUPT_INTERVAL 0x10
-// max transmit packet number per transmit
-#define GL_MAX_TRANSMIT_PACKETS 32
-// max packet length
-#define GL_MAX_PACKET_LEN 1514
-// max receive buffer size
-#define GL_RCV_BUF_SIZE \
- (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
-
-struct gl_packet {
- u32 packet_length;
- char packet_data [1];
-};
-
-struct gl_header {
- u32 packet_count;
- struct gl_packet packets;
-};
-
-#ifdef GENELINK_ACK
-
-// FIXME: this code is incomplete, not debugged; it doesn't
-// handle interrupts correctly. interrupts should be generic
-// code like all other device I/O, anyway.
-
-struct gl_priv {
- struct urb *irq_urb;
- char irq_buf [INTERRUPT_BUFSIZE];
-};
-
-static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
-{
- int retval;
-
- retval = usb_control_msg (dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- request,
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- value,
- 0, // index
- 0, // data buffer
- 0, // size
- CONTROL_TIMEOUT_MS);
- return retval;
-}
-
-static void gl_interrupt_complete (struct urb *urb, struct pt_regs *regs)
-{
- int status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
- }
-
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
-}
-
-static int gl_interrupt_read (struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
- int retval;
-
- // issue usb interrupt read
- if (priv && priv->irq_urb) {
- // submit urb
- if ((retval = usb_submit_urb (priv->irq_urb, GFP_KERNEL)) != 0)
- dbg ("gl_interrupt_read: submit fail - %X...", retval);
- else
- dbg ("gl_interrupt_read: submit success...");
- }
-
- return 0;
-}
-
-// check whether another side is connected
-static int genelink_check_connect (struct usbnet *dev)
-{
- int retval;
-
- dbg ("genelink_check_connect...");
-
- // detect whether another side is connected
- if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
- dbg ("%s: genelink_check_connect write fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- // usb interrupt read to ack another side
- if ((retval = gl_interrupt_read (dev)) != 0) {
- dbg ("%s: genelink_check_connect read fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- dbg ("%s: genelink_check_connect read success", dev->net->name);
- return 0;
-}
-
-// allocate and initialize the private data for genelink
-static int genelink_init (struct usbnet *dev)
-{
- struct gl_priv *priv;
-
- // allocate the private data structure
- if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
- dbg ("%s: cannot allocate private data per device",
- dev->net->name);
- return -ENOMEM;
- }
-
- // allocate irq urb
- if ((priv->irq_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
- dbg ("%s: cannot allocate private irq urb per device",
- dev->net->name);
- kfree (priv);
- return -ENOMEM;
- }
-
- // fill irq urb
- usb_fill_int_urb (priv->irq_urb, dev->udev,
- usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
- priv->irq_buf, INTERRUPT_BUFSIZE,
- gl_interrupt_complete, 0,
- GENELINK_INTERRUPT_INTERVAL);
-
- // set private data pointer
- dev->priv_data = priv;
-
- return 0;
-}
-
-// release the private data
-static int genelink_free (struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
-
- if (!priv)
- return 0;
-
-// FIXME: can't cancel here; it's synchronous, and
-// should have happened earlier in any case (interrupt
-// handling needs to be generic)
-
- // cancel irq urb first
- usb_kill_urb (priv->irq_urb);
-
- // free irq urb
- usb_free_urb (priv->irq_urb);
-
- // free the private data structure
- kfree (priv);
-
- return 0;
-}
-
-#endif
-
-static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
- struct gl_header *header;
- struct gl_packet *packet;
- struct sk_buff *gl_skb;
- u32 size;
-
- header = (struct gl_header *) skb->data;
-
- // get the packet count of the received skb
- le32_to_cpus (&header->packet_count);
- if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
- || (header->packet_count < 0)) {
- dbg ("genelink: invalid received packet count %d",
- header->packet_count);
- return 0;
- }
-
- // set the current packet pointer to the first packet
- packet = &header->packets;
-
- // decrement the length for the packet count size 4 bytes
- skb_pull (skb, 4);
-
- while (header->packet_count > 1) {
- // get the packet length
- size = packet->packet_length;
-
- // this may be a broken packet
- if (size > GL_MAX_PACKET_LEN) {
- dbg ("genelink: invalid rx length %d", size);
- return 0;
- }
-
- // allocate the skb for the individual packet
- gl_skb = alloc_skb (size, GFP_ATOMIC);
- if (gl_skb) {
-
- // copy the packet data to the new skb
- memcpy(skb_put(gl_skb, size), packet->packet_data, size);
- skb_return (dev, skb);
- }
-
- // advance to the next packet
- packet = (struct gl_packet *)
- &packet->packet_data [size];
- header->packet_count--;
-
- // shift the data pointer to the next gl_packet
- skb_pull (skb, size + 4);
- }
-
- // skip the packet length field 4 bytes
- skb_pull (skb, 4);
-
- if (skb->len > GL_MAX_PACKET_LEN) {
- dbg ("genelink: invalid rx length %d", skb->len);
- return 0;
- }
- return 1;
-}
-
-static struct sk_buff *
-genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- int length = skb->len;
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
- u32 *packet_count;
- u32 *packet_len;
-
- // FIXME: magic numbers, bleech
- padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
-
- if ((!skb_cloned (skb))
- && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
- if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
- skb->data = memmove (skb->head + (4 + 4*1),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- }
- } else {
- struct sk_buff *skb2;
- skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
- dev_kfree_skb_any (skb);
- skb = skb2;
- if (!skb)
- return NULL;
- }
-
- // attach the packet count to the header
- packet_count = (u32 *) skb_push (skb, (4 + 4*1));
- packet_len = packet_count + 1;
-
- // FIXME little endian?
- *packet_count = 1;
- *packet_len = length;
-
- // add padding byte
- if ((skb->len % dev->maxpacket) == 0)
- skb_put (skb, 1);
-
- return skb;
-}
-
-static const struct driver_info genelink_info = {
- .description = "Genesys GeneLink",
- .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT,
- .rx_fixup = genelink_rx_fixup,
- .tx_fixup = genelink_tx_fixup,
-
- .in = 1, .out = 2,
-
-#ifdef GENELINK_ACK
- .check_connect =genelink_check_connect,
-#endif
-};
-
-#endif /* CONFIG_USB_GENESYS */
-
-
-
-#ifdef CONFIG_USB_NET1080
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Netchip 1080 driver ... http://www.netchip.com
- * Used in LapLink cables
- *
- *-------------------------------------------------------------------------*/
-
-#define dev_packet_id data[0]
-#define frame_errors data[1]
-
-/*
- * NetChip framing of ethernet packets, supporting additional error
- * checks for links that may drop bulk packets from inside messages.
- * Odd USB length == always short read for last usb packet.
- * - nc_header
- * - Ethernet header (14 bytes)
- * - payload
- * - (optional padding byte, if needed so length becomes odd)
- * - nc_trailer
- *
- * This framing is to be avoided for non-NetChip devices.
- */
-
-struct nc_header { // packed:
- __le16 hdr_len; // sizeof nc_header (LE, all)
- __le16 packet_len; // payload size (including ethhdr)
- __le16 packet_id; // detects dropped packets
-#define MIN_HEADER 6
-
- // all else is optional, and must start with:
- // u16 vendorId; // from usb-if
- // u16 productId;
-} __attribute__((__packed__));
-
-#define PAD_BYTE ((unsigned char)0xAC)
-
-struct nc_trailer {
- __le16 packet_id;
-} __attribute__((__packed__));
-
-// packets may use FLAG_FRAMING_NC and optional pad
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
- + sizeof (struct ethhdr) \
- + (mtu) \
- + 1 \
- + sizeof (struct nc_trailer))
-
-#define MIN_FRAMED FRAMED_SIZE(0)
-
-
-/*
- * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
- * before the hardware drops it. If that's done, the driver will need to
- * frame network packets to guard against the dropped USB packets. The win32
- * driver sets this for both sides of the link.
- */
-#define NC_READ_TTL_MS ((u8)255) // ms
-
-/*
- * We ignore most registers and EEPROM contents.
- */
-#define REG_USBCTL ((u8)0x04)
-#define REG_TTL ((u8)0x10)
-#define REG_STATUS ((u8)0x11)
-
-/*
- * Vendor specific requests to read/write data
- */
-#define REQUEST_REGISTER ((u8)0x10)
-#define REQUEST_EEPROM ((u8)0x11)
-
-static int
-nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
-{
- int status = usb_control_msg (dev->udev,
- usb_rcvctrlpipe (dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, regnum,
- retval_ptr, sizeof *retval_ptr,
- CONTROL_TIMEOUT_MS);
- if (status > 0)
- status = 0;
- if (!status)
- le16_to_cpus (retval_ptr);
- return status;
-}
-
-static inline int
-nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr)
-{
- return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr);
-}
-
-// no retval ... can become async, usable in_interrupt()
-static void
-nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
-{
- usb_control_msg (dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- req,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, regnum,
- NULL, 0, // data is in setup packet
- CONTROL_TIMEOUT_MS);
-}
-
-static inline void
-nc_register_write (struct usbnet *dev, u8 regnum, u16 value)
-{
- nc_vendor_write (dev, REQUEST_REGISTER, regnum, value);
-}
-
-
-#if 0
-static void nc_dump_registers (struct usbnet *dev)
-{
- u8 reg;
- u16 *vp = kmalloc (sizeof (u16));
-
- if (!vp) {
- dbg ("no memory?");
- return;
- }
-
- dbg ("%s registers:", dev->net->name);
- for (reg = 0; reg < 0x20; reg++) {
- int retval;
-
- // reading some registers is trouble
- if (reg >= 0x08 && reg <= 0xf)
- continue;
- if (reg >= 0x12 && reg <= 0x1e)
- continue;
-
- retval = nc_register_read (dev, reg, vp);
- if (retval < 0)
- dbg ("%s reg [0x%x] ==> error %d",
- dev->net->name, reg, retval);
- else
- dbg ("%s reg [0x%x] = 0x%x",
- dev->net->name, reg, *vp);
- }
- kfree (vp);
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Control register
- */
-
-#define USBCTL_WRITABLE_MASK 0x1f0f
-// bits 15-13 reserved, r/o
-#define USBCTL_ENABLE_LANG (1 << 12)
-#define USBCTL_ENABLE_MFGR (1 << 11)
-#define USBCTL_ENABLE_PROD (1 << 10)
-#define USBCTL_ENABLE_SERIAL (1 << 9)
-#define USBCTL_ENABLE_DEFAULTS (1 << 8)
-// bits 7-4 reserved, r/o
-#define USBCTL_FLUSH_OTHER (1 << 3)
-#define USBCTL_FLUSH_THIS (1 << 2)
-#define USBCTL_DISCONN_OTHER (1 << 1)
-#define USBCTL_DISCONN_THIS (1 << 0)
-
-static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
-{
- if (!netif_msg_link (dev))
- return;
- devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
- " this%s%s;"
- " other%s%s; r/o 0x%x",
- dev->udev->bus->bus_name, dev->udev->devpath,
- usbctl,
- (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
- (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
- (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
- (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
- (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
-
- (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
- (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
- (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
- (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
- usbctl & ~USBCTL_WRITABLE_MASK
- );
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Status register
- */
-
-#define STATUS_PORT_A (1 << 15)
-
-#define STATUS_CONN_OTHER (1 << 14)
-#define STATUS_SUSPEND_OTHER (1 << 13)
-#define STATUS_MAILBOX_OTHER (1 << 12)
-#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
-
-#define STATUS_CONN_THIS (1 << 6)
-#define STATUS_SUSPEND_THIS (1 << 5)
-#define STATUS_MAILBOX_THIS (1 << 4)
-#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
-
-#define STATUS_UNSPEC_MASK 0x0c8c
-#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
-
-
-static inline void nc_dump_status (struct usbnet *dev, u16 status)
-{
- if (!netif_msg_link (dev))
- return;
- devdbg (dev, "net1080 %s-%s status 0x%x:"
- " this (%c) PKT=%d%s%s%s;"
- " other PKT=%d%s%s%s; unspec 0x%x",
- dev->udev->bus->bus_name, dev->udev->devpath,
- status,
-
- // XXX the packet counts don't seem right
- // (1 at reset, not 0); maybe UNSPEC too
-
- (status & STATUS_PORT_A) ? 'A' : 'B',
- STATUS_PACKETS_THIS (status),
- (status & STATUS_CONN_THIS) ? " CON" : "",
- (status & STATUS_SUSPEND_THIS) ? " SUS" : "",
- (status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
-
- STATUS_PACKETS_OTHER (status),
- (status & STATUS_CONN_OTHER) ? " CON" : "",
- (status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
- (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
-
- status & STATUS_UNSPEC_MASK
- );
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * TTL register
- */
-
-#define TTL_THIS(ttl) (0x00ff & ttl)
-#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8))
-#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this))))
-
-static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
-{
- if (netif_msg_link (dev))
- devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
- dev->udev->bus->bus_name, dev->udev->devpath,
- ttl, TTL_THIS (ttl), TTL_OTHER (ttl));
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net1080_reset (struct usbnet *dev)
-{
- u16 usbctl, status, ttl;
- u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL);
- int retval;
-
- if (!vp)
- return -ENOMEM;
-
- // nc_dump_registers (dev);
-
- if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) {
- dbg ("can't read %s-%s status: %d",
- dev->udev->bus->bus_name, dev->udev->devpath, retval);
- goto done;
- }
- status = *vp;
- nc_dump_status (dev, status);
-
- if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
- dbg ("can't read USBCTL, %d", retval);
- goto done;
- }
- usbctl = *vp;
- nc_dump_usbctl (dev, usbctl);
-
- nc_register_write (dev, REG_USBCTL,
- USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
-
- if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) {
- dbg ("can't read TTL, %d", retval);
- goto done;
- }
- ttl = *vp;
- // nc_dump_ttl (dev, ttl);
-
- nc_register_write (dev, REG_TTL,
- MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
- dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
-
- if (netif_msg_link (dev))
- devinfo (dev, "port %c, peer %sconnected",
- (status & STATUS_PORT_A) ? 'A' : 'B',
- (status & STATUS_CONN_OTHER) ? "" : "dis"
- );
- retval = 0;
-
-done:
- kfree (vp);
- return retval;
-}
-
-static int net1080_check_connect (struct usbnet *dev)
-{
- int retval;
- u16 status;
- u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL);
-
- if (!vp)
- return -ENOMEM;
- retval = nc_register_read (dev, REG_STATUS, vp);
- status = *vp;
- kfree (vp);
- if (retval != 0) {
- dbg ("%s net1080_check_conn read - %d", dev->net->name, retval);
- return retval;
- }
- if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
- return -ENOLINK;
- return 0;
-}
-
-static void nc_flush_complete (struct urb *urb, struct pt_regs *regs)
-{
- kfree (urb->context);
- usb_free_urb(urb);
-}
-
-static void nc_ensure_sync (struct usbnet *dev)
-{
- dev->frame_errors++;
- if (dev->frame_errors > 5) {
- struct urb *urb;
- struct usb_ctrlrequest *req;
- int status;
-
- /* Send a flush */
- urb = usb_alloc_urb (0, SLAB_ATOMIC);
- if (!urb)
- return;
-
- req = kmalloc (sizeof *req, GFP_ATOMIC);
- if (!req) {
- usb_free_urb (urb);
- return;
- }
-
- req->bRequestType = USB_DIR_OUT
- | USB_TYPE_VENDOR
- | USB_RECIP_DEVICE;
- req->bRequest = REQUEST_REGISTER;
- req->wValue = cpu_to_le16 (USBCTL_FLUSH_THIS
- | USBCTL_FLUSH_OTHER);
- req->wIndex = cpu_to_le16 (REG_USBCTL);
- req->wLength = cpu_to_le16 (0);
-
- /* queue an async control request, we don't need
- * to do anything when it finishes except clean up.
- */
- usb_fill_control_urb (urb, dev->udev,
- usb_sndctrlpipe (dev->udev, 0),
- (unsigned char *) req,
- NULL, 0,
- nc_flush_complete, req);
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status) {
- kfree (req);
- usb_free_urb (urb);
- return;
- }
-
- if (netif_msg_rx_err (dev))
- devdbg (dev, "flush net1080; too many framing errors");
- dev->frame_errors = 0;
- }
-}
-
-static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
- struct nc_header *header;
- struct nc_trailer *trailer;
- u16 hdr_len, packet_len;
-
- if (!(skb->len & 0x01)
- || MIN_FRAMED > skb->len
- || skb->len > FRAMED_SIZE (dev->net->mtu)) {
- dev->stats.rx_frame_errors++;
- dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
- (int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net->mtu),
- dev->net->mtu);
- nc_ensure_sync (dev);
- return 0;
- }
-
- header = (struct nc_header *) skb->data;
- hdr_len = le16_to_cpup (&header->hdr_len);
- packet_len = le16_to_cpup (&header->packet_len);
- if (FRAMED_SIZE (packet_len) > MAX_PACKET) {
- dev->stats.rx_frame_errors++;
- dbg ("packet too big, %d", packet_len);
- nc_ensure_sync (dev);
- return 0;
- } else if (hdr_len < MIN_HEADER) {
- dev->stats.rx_frame_errors++;
- dbg ("header too short, %d", hdr_len);
- nc_ensure_sync (dev);
- return 0;
- } else if (hdr_len > MIN_HEADER) {
- // out of band data for us?
- dbg ("header OOB, %d bytes", hdr_len - MIN_HEADER);
- nc_ensure_sync (dev);
- // switch (vendor/product ids) { ... }
- }
- skb_pull (skb, hdr_len);
-
- trailer = (struct nc_trailer *)
- (skb->data + skb->len - sizeof *trailer);
- skb_trim (skb, skb->len - sizeof *trailer);
-
- if ((packet_len & 0x01) == 0) {
- if (skb->data [packet_len] != PAD_BYTE) {
- dev->stats.rx_frame_errors++;
- dbg ("bad pad");
- return 0;
- }
- skb_trim (skb, skb->len - 1);
- }
- if (skb->len != packet_len) {
- dev->stats.rx_frame_errors++;
- dbg ("bad packet len %d (expected %d)",
- skb->len, packet_len);
- nc_ensure_sync (dev);
- return 0;
- }
- if (header->packet_id != get_unaligned (&trailer->packet_id)) {
- dev->stats.rx_fifo_errors++;
- dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- le16_to_cpu (header->packet_id),
- le16_to_cpu (trailer->packet_id));
- return 0;
- }
-#if 0
- devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
- header->packet_len, header->packet_id);
-#endif
- dev->frame_errors = 0;
- return 1;
-}
-
-static struct sk_buff *
-net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = ((skb->len + sizeof (struct nc_header)
- + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
- if (!skb_cloned (skb)) {
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
-
- if ((padlen + sizeof (struct nc_trailer)) <= tailroom
- && sizeof (struct nc_header) <= headroom)
- /* There's enough head and tail room */
- return skb;
-
- if ((sizeof (struct nc_header) + padlen
- + sizeof (struct nc_trailer)) <
- (headroom + tailroom)) {
- /* There's enough total room, so just readjust */
- skb->data = memmove (skb->head
- + sizeof (struct nc_header),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- return skb;
- }
- }
-
- /* Create a new skb to use with the correct size */
- skb2 = skb_copy_expand (skb,
- sizeof (struct nc_header),
- sizeof (struct nc_trailer) + padlen,
- flags);
- dev_kfree_skb_any (skb);
- return skb2;
-}
-
-static const struct driver_info net1080_info = {
- .description = "NetChip TurboCONNECT",
- .flags = FLAG_FRAMING_NC,
- .reset = net1080_reset,
- .check_connect =net1080_check_connect,
- .rx_fixup = net1080_rx_fixup,
- .tx_fixup = net1080_tx_fixup,
-};
-
-#endif /* CONFIG_USB_NET1080 */
-
-
-
-#ifdef CONFIG_USB_PL2301
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
- *
- * The protocol and handshaking used here should be bug-compatible
- * with the Linux 2.2 "plusb" driver, by Deti Fliegl.
- *
- *-------------------------------------------------------------------------*/
-
-/*
- * Bits 0-4 can be used for software handshaking; they're set from
- * one end, cleared from the other, "read" with the interrupt byte.
- */
-#define PL_S_EN (1<<7) /* (feature only) suspend enable */
-/* reserved bit -- rx ready (6) ? */
-#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */
-#define PL_RESET_OUT (1<<4) /* reset output pipe */
-#define PL_RESET_IN (1<<3) /* reset input pipe */
-#define PL_TX_C (1<<2) /* transmission complete */
-#define PL_TX_REQ (1<<1) /* transmission received */
-#define PL_PEER_E (1<<0) /* peer exists */
-
-static inline int
-pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
-{
- return usb_control_msg (dev->udev,
- usb_rcvctrlpipe (dev->udev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- val, index,
- NULL, 0,
- CONTROL_TIMEOUT_MS);
-}
-
-static inline int
-pl_clear_QuickLink_features (struct usbnet *dev, int val)
-{
- return pl_vendor_req (dev, 1, (u8) val, 0);
-}
-
-static inline int
-pl_set_QuickLink_features (struct usbnet *dev, int val)
-{
- return pl_vendor_req (dev, 3, (u8) val, 0);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pl_reset (struct usbnet *dev)
-{
- /* some units seem to need this reset, others reject it utterly.
- * FIXME be more like "naplink" or windows drivers.
- */
- (void) pl_set_QuickLink_features (dev,
- PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
- return 0;
-}
-
-static const struct driver_info prolific_info = {
- .description = "Prolific PL-2301/PL-2302",
- .flags = FLAG_NO_SETINT,
- /* some PL-2302 versions seem to fail usb_set_interface() */
- .reset = pl_reset,
-};
-
-#endif /* CONFIG_USB_PL2301 */
-
-
-#ifdef CONFIG_USB_KC2190
-#define HAVE_HARDWARE
-static const struct driver_info kc2190_info = {
- .description = "KC Technology KC-190",
-};
-#endif /* CONFIG_USB_KC2190 */
-
-
-#ifdef CONFIG_USB_ARMLINUX
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Intel's SA-1100 chip integrates basic USB support, and is used
- * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more.
- * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to
- * network using minimal USB framing data.
- *
- * This describes the driver currently in standard ARM Linux kernels.
- * The Zaurus uses a different driver (see later).
- *
- * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support
- * and different USB endpoint numbering than the SA1100 devices. The
- * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100
- * so we rely on the endpoint descriptors.
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info linuxdev_info = {
- .description = "Linux Device",
- .check_connect = always_connected,
-};
-
-static const struct driver_info yopy_info = {
- .description = "Yopy",
- .check_connect = always_connected,
-};
-
-static const struct driver_info blob_info = {
- .description = "Boot Loader OBject",
- .check_connect = always_connected,
-};
-
-#endif /* CONFIG_USB_ARMLINUX */
-
-
-#ifdef CONFIG_USB_ZAURUS
-#define HAVE_HARDWARE
-
-#include <linux/crc32.h>
-
-/*-------------------------------------------------------------------------
- *
- * Zaurus is also a SA-1110 based PDA, but one using a different driver
- * (and framing) for its USB slave/gadget controller than the case above.
- *
- * For the current version of that driver, the main way that framing is
- * nonstandard (also from perspective of the CDC ethernet model!) is a
- * crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around. Also, all Zaurii use the same
- * default Ethernet address.
- *
- * PXA based models use the same framing, and also can't implement
- * set_interface properly.
- *
- * All known Zaurii lie about their standards conformance. Most lie by
- * saying they support CDC Ethernet. Some lie and say they support CDC
- * MDLM (as if for access to cell phone modems). Someone, please beat
- * on Sharp (and other such vendors) for a while with a cluestick.
- *
- *-------------------------------------------------------------------------*/
-
-static struct sk_buff *
-zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = 2;
- if (!skb_cloned (skb)) {
- int tailroom = skb_tailroom (skb);
- if ((padlen + 4) <= tailroom)
- goto done;
- }
- skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags);
- dev_kfree_skb_any (skb);
- skb = skb2;
- if (skb) {
- u32 fcs;
-done:
- fcs = crc32_le (~0, skb->data, skb->len);
- fcs = ~fcs;
-
- *skb_put (skb, 1) = fcs & 0xff;
- *skb_put (skb, 1) = (fcs>> 8) & 0xff;
- *skb_put (skb, 1) = (fcs>>16) & 0xff;
- *skb_put (skb, 1) = (fcs>>24) & 0xff;
- }
- return skb;
-}
-
-static const struct driver_info zaurus_sl5x00_info = {
- .description = "Sharp Zaurus SL-5x00",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info)
-
-static const struct driver_info zaurus_pxa_info = {
- .description = "Sharp Zaurus, PXA-2xx based",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
-
-static const struct driver_info olympus_mxl_info = {
- .description = "Olympus R1000",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .bind = generic_cdc_bind,
- .unbind = cdc_unbind,
- .tx_fixup = zaurus_tx_fixup,
-};
-#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info)
-
-
-/* Some more recent products using Lineo/Belcarra code will wrongly claim
- * CDC MDLM conformance. They aren't conformant: data endpoints live
- * in the control interface, there's no data interface, and it's not used
- * to talk to a cell phone radio. But at least we can detect these two
- * pseudo-classes, rather than growing this product list with entries for
- * each new nonconformant product (sigh).
- */
-static const u8 safe_guid[16] = {
- 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
- 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-};
-static const u8 blan_guid[16] = {
- 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
- 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
-};
-
-static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
-{
- u8 *buf = intf->cur_altsetting->extra;
- int len = intf->cur_altsetting->extralen;
- struct usb_cdc_mdlm_desc *desc = NULL;
- struct usb_cdc_mdlm_detail_desc *detail = NULL;
-
- while (len > 3) {
- if (buf [1] != USB_DT_CS_INTERFACE)
- goto next_desc;
-
- /* use bDescriptorSubType, and just verify that we get a
- * "BLAN" (or "SAFE") descriptor.
- */
- switch (buf [2]) {
- case USB_CDC_MDLM_TYPE:
- if (desc) {
- dev_dbg (&intf->dev, "extra MDLM\n");
- goto bad_desc;
- }
- desc = (void *) buf;
- if (desc->bLength != sizeof *desc) {
- dev_dbg (&intf->dev, "MDLM len %u\n",
- desc->bLength);
- goto bad_desc;
- }
- /* expect bcdVersion 1.0, ignore */
- if (memcmp(&desc->bGUID, blan_guid, 16)
- && memcmp(&desc->bGUID, safe_guid, 16) ) {
- /* hey, this one might _really_ be MDLM! */
- dev_dbg (&intf->dev, "MDLM guid\n");
- goto bad_desc;
- }
- break;
- case USB_CDC_MDLM_DETAIL_TYPE:
- if (detail) {
- dev_dbg (&intf->dev, "extra MDLM detail\n");
- goto bad_desc;
- }
- detail = (void *) buf;
- switch (detail->bGuidDescriptorType) {
- case 0: /* "SAFE" */
- if (detail->bLength != (sizeof *detail + 2))
- goto bad_detail;
- break;
- case 1: /* "BLAN" */
- if (detail->bLength != (sizeof *detail + 3))
- goto bad_detail;
- break;
- default:
- goto bad_detail;
- }
-
- /* assuming we either noticed BLAN already, or will
- * find it soon, there are some data bytes here:
- * - bmNetworkCapabilities (unused)
- * - bmDataCapabilities (bits, see below)
- * - bPad (ignored, for PADAFTER -- BLAN-only)
- * bits are:
- * - 0x01 -- Zaurus framing (add CRC)
- * - 0x02 -- PADBEFORE (CRC includes some padding)
- * - 0x04 -- PADAFTER (some padding after CRC)
- * - 0x08 -- "fermat" packet mangling (for hw bugs)
- * the PADBEFORE appears not to matter; we interop
- * with devices that use it and those that don't.
- */
- if ((detail->bDetailData[1] & ~02) != 0x01) {
- /* bmDataCapabilites == 0 would be fine too,
- * but framing is minidriver-coupled for now.
- */
-bad_detail:
- dev_dbg (&intf->dev,
- "bad MDLM detail, %d %d %d\n",
- detail->bLength,
- detail->bDetailData[0],
- detail->bDetailData[2]);
- goto bad_desc;
- }
- break;
- }
-next_desc:
- len -= buf [0]; /* bLength */
- buf += buf [0];
- }
-
- if (!desc || !detail) {
- dev_dbg (&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
- desc ? "" : "func ",
- detail ? "" : "detail ");
- goto bad_desc;
- }
-
- /* There's probably a CDC Ethernet descriptor there, but we can't
- * rely on the Ethernet address it provides since not all vendors
- * bother to make it unique. Likewise there's no point in tracking
- * of the CDC event notifications.
- */
- return get_endpoints (dev, intf);
-
-bad_desc:
- dev_info (&dev->udev->dev, "unsupported MDLM descriptors\n");
- return -ENODEV;
-}
-
-static const struct driver_info bogus_mdlm_info = {
- .description = "pseudo-MDLM (BLAN) device",
- .flags = FLAG_FRAMING_Z,
- .check_connect = always_connected,
- .tx_fixup = zaurus_tx_fixup,
- .bind = blan_mdlm_bind,
-};
-
-#else
-
-/* blacklist all those devices */
-#define ZAURUS_STRONGARM_INFO 0
-#define ZAURUS_PXA_INFO 0
-#define OLYMPUS_MXL_INFO 0
-
-#endif
+EXPORT_SYMBOL_GPL(usbnet_skb_return);
/*-------------------------------------------------------------------------
@@ -2868,22 +230,12 @@ static const struct driver_info bogus_mdlm_info = {
static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
+ int ll_mtu = new_mtu + net->hard_header_len;
- if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
+ if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
return -EINVAL;
-#ifdef CONFIG_USB_NET1080
- if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
- if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
- return -EINVAL;
- }
-#endif
-#ifdef CONFIG_USB_GENESYS
- if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
- && new_mtu > GL_MAX_PACKET_LEN)
- return -EINVAL;
-#endif
// no second zero-length packet read wanted after mtu-sized packets
- if (((new_mtu + sizeof (struct ethhdr)) % dev->maxpacket) == 0)
+ if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
net->mtu = new_mtu;
return 0;
@@ -2903,19 +255,18 @@ static struct net_device_stats *usbnet_get_stats (struct net_device *net)
* completion callbacks. 2.5 should have fixed those bugs...
*/
-static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
+static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
{
- struct sk_buff_head *list = skb->list;
unsigned long flags;
- spin_lock_irqsave (&list->lock, flags);
- __skb_unlink (skb, list);
- spin_unlock (&list->lock);
- spin_lock (&dev->done.lock);
- __skb_queue_tail (&dev->done, skb);
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_unlink(skb, list);
+ spin_unlock(&list->lock);
+ spin_lock(&dev->done.lock);
+ __skb_queue_tail(&dev->done, skb);
if (dev->done.qlen == 1)
- tasklet_schedule (&dev->bh);
- spin_unlock_irqrestore (&dev->done.lock, flags);
+ tasklet_schedule(&dev->bh);
+ spin_unlock_irqrestore(&dev->done.lock, flags);
}
/* some work can't be done in tasklets, so we use keventd
@@ -2923,7 +274,7 @@ static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
* NOTE: annoying asymmetry: if it's active, schedule_work() fails,
* but tasklet_schedule() doesn't. hope the failure is rare.
*/
-static void defer_kevent (struct usbnet *dev, int work)
+void usbnet_defer_kevent (struct usbnet *dev, int work)
{
set_bit (work, &dev->flags);
if (!schedule_work (&dev->kevent))
@@ -2931,50 +282,24 @@ static void defer_kevent (struct usbnet *dev, int work)
else
devdbg (dev, "kevent %d scheduled", work);
}
+EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
/*-------------------------------------------------------------------------*/
static void rx_complete (struct urb *urb, struct pt_regs *regs);
-static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
+static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
{
struct sk_buff *skb;
struct skb_data *entry;
int retval = 0;
unsigned long lockflags;
- size_t size;
-
-#ifdef CONFIG_USB_NET1080
- if (dev->driver_info->flags & FLAG_FRAMING_NC)
- size = FRAMED_SIZE (dev->net->mtu);
- else
-#endif
-#ifdef CONFIG_USB_GENESYS
- if (dev->driver_info->flags & FLAG_FRAMING_GL)
- size = GL_RCV_BUF_SIZE;
- else
-#endif
-#ifdef CONFIG_USB_ZAURUS
- if (dev->driver_info->flags & FLAG_FRAMING_Z)
- size = 6 + (sizeof (struct ethhdr) + dev->net->mtu);
- else
-#endif
-#ifdef CONFIG_USB_RNDIS
- if (dev->driver_info->flags & FLAG_FRAMING_RN)
- size = RNDIS_MAX_TRANSFER;
- else
-#endif
-#ifdef CONFIG_USB_AX8817X
- if (dev->driver_info->flags & FLAG_FRAMING_AX)
- size = 2048;
- else
-#endif
- size = (sizeof (struct ethhdr) + dev->net->mtu);
+ size_t size = dev->rx_urb_size;
if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
if (netif_msg_rx_err (dev))
devdbg (dev, "no rx skb");
- defer_kevent (dev, EVENT_RX_MEMORY);
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return;
}
@@ -2988,7 +313,6 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
usb_fill_bulk_urb (urb, dev->udev, dev->in,
skb->data, size, rx_complete, skb);
- urb->transfer_flags |= URB_ASYNC_UNLINK;
spin_lock_irqsave (&dev->rxq.lock, lockflags);
@@ -2997,10 +321,10 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
case -EPIPE:
- defer_kevent (dev, EVENT_RX_HALT);
+ usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
case -ENOMEM:
- defer_kevent (dev, EVENT_RX_MEMORY);
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
break;
case -ENODEV:
if (netif_msg_ifdown (dev))
@@ -3038,7 +362,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
// else network stack removes extra byte if we forced a short packet
if (skb->len)
- skb_return (dev, skb);
+ usbnet_skb_return (dev, skb);
else {
if (netif_msg_rx_err (dev))
devdbg (dev, "drop");
@@ -3064,7 +388,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
switch (urb_status) {
// success
case 0:
- if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) {
+ if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
@@ -3079,7 +403,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
// storm, recovering as needed.
case -EPIPE:
dev->stats.rx_errors++;
- defer_kevent (dev, EVENT_RX_HALT);
+ usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
// software-driven interface shutdown
@@ -3120,7 +444,7 @@ block:
break;
}
- defer_bh (dev, skb);
+ defer_bh(dev, skb, &dev->rxq);
if (urb) {
if (netif_running (dev->net)
@@ -3321,55 +645,58 @@ done:
/*-------------------------------------------------------------------------*/
-static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
+/* ethtool methods; minidrivers may need to add some more, but
+ * they'll probably want to use this base set.
+ */
+
+void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
{
struct usbnet *dev = netdev_priv(net);
+ /* REVISIT don't always return "usbnet" */
strncpy (info->driver, driver_name, sizeof info->driver);
strncpy (info->version, DRIVER_VERSION, sizeof info->version);
strncpy (info->fw_version, dev->driver_info->description,
sizeof info->fw_version);
usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
}
+EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
static u32 usbnet_get_link (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- /* If a check_connect is defined, return it's results */
+ /* If a check_connect is defined, return its result */
if (dev->driver_info->check_connect)
return dev->driver_info->check_connect (dev) == 0;
- /* Otherwise, we're up to avoid breaking scripts */
+ /* Otherwise, say we're up (to avoid breaking scripts) */
return 1;
}
-static u32 usbnet_get_msglevel (struct net_device *net)
+u32 usbnet_get_msglevel (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
return dev->msg_enable;
}
+EXPORT_SYMBOL_GPL(usbnet_get_msglevel);
-static void usbnet_set_msglevel (struct net_device *net, u32 level)
+void usbnet_set_msglevel (struct net_device *net, u32 level)
{
struct usbnet *dev = netdev_priv(net);
dev->msg_enable = level;
}
+EXPORT_SYMBOL_GPL(usbnet_set_msglevel);
-static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
-{
-#ifdef NEED_MII
- {
- struct usbnet *dev = netdev_priv(net);
-
- if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
- return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
- }
-#endif
- return -EOPNOTSUPP;
-}
+/* drivers may override default ethtool_ops in their bind() routine */
+static struct ethtool_ops usbnet_ethtool_ops = {
+ .get_drvinfo = usbnet_get_drvinfo,
+ .get_link = usbnet_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+};
/*-------------------------------------------------------------------------*/
@@ -3388,19 +715,24 @@ kevent (void *data)
if (test_bit (EVENT_TX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->txq);
status = usb_clear_halt (dev->udev, dev->out);
- if (status < 0 && status != -EPIPE) {
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
if (netif_msg_tx_err (dev))
deverr (dev, "can't clear tx halt, status %d",
status);
} else {
clear_bit (EVENT_TX_HALT, &dev->flags);
- netif_wake_queue (dev->net);
+ if (status != -ESHUTDOWN)
+ netif_wake_queue (dev->net);
}
}
if (test_bit (EVENT_RX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->rxq);
status = usb_clear_halt (dev->udev, dev->in);
- if (status < 0 && status != -EPIPE) {
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
if (netif_msg_rx_err (dev))
deverr (dev, "can't clear rx halt, status %d",
status);
@@ -3459,7 +791,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
switch (urb->status) {
case -EPIPE:
- defer_kevent (dev, EVENT_TX_HALT);
+ usbnet_defer_kevent (dev, EVENT_TX_HALT);
break;
/* software-driven interface shutdown */
@@ -3490,7 +822,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
urb->dev = NULL;
entry->state = tx_done;
- defer_bh (dev, skb);
+ defer_bh(dev, skb, &dev->txq);
}
/*-------------------------------------------------------------------------*/
@@ -3516,10 +848,6 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
struct skb_data *entry;
struct driver_info *info = dev->driver_info;
unsigned long flags;
-#ifdef CONFIG_USB_NET1080
- struct nc_header *header = NULL;
- struct nc_trailer *trailer = NULL;
-#endif /* CONFIG_USB_NET1080 */
// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
@@ -3545,24 +873,8 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
entry->state = tx_start;
entry->length = length;
- // FIXME: reorganize a bit, so that fixup() fills out NetChip
- // framing too. (Packet ID update needs the spinlock...)
- // [ BETTER: we already own net->xmit_lock, that's enough ]
-
-#ifdef CONFIG_USB_NET1080
- if (info->flags & FLAG_FRAMING_NC) {
- header = (struct nc_header *) skb_push (skb, sizeof *header);
- header->hdr_len = cpu_to_le16 (sizeof (*header));
- header->packet_len = cpu_to_le16 (length);
- if (!((skb->len + sizeof *trailer) & 0x01))
- *skb_put (skb, 1) = PAD_BYTE;
- trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
- }
-#endif /* CONFIG_USB_NET1080 */
-
usb_fill_bulk_urb (urb, dev->udev, dev->out,
skb->data, skb->len, tx_complete, skb);
- urb->transfer_flags |= URB_ASYNC_UNLINK;
/* don't assume the hardware handles USB_ZERO_PACKET
* NOTE: strictly conforming cdc-ether devices should expect
@@ -3575,22 +887,10 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
spin_lock_irqsave (&dev->txq.lock, flags);
-#ifdef CONFIG_USB_NET1080
- if (info->flags & FLAG_FRAMING_NC) {
- header->packet_id = cpu_to_le16 ((u16)dev->dev_packet_id++);
- put_unaligned (header->packet_id, &trailer->packet_id);
-#if 0
- devdbg (dev, "frame >tx h %d p %d id %d",
- header->hdr_len, header->packet_len,
- header->packet_id);
-#endif
- }
-#endif /* CONFIG_USB_NET1080 */
-
switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) {
case -EPIPE:
netif_stop_queue (net);
- defer_kevent (dev, EVENT_TX_HALT);
+ usbnet_defer_kevent (dev, EVENT_TX_HALT);
break;
default:
if (netif_msg_tx_err (dev))
@@ -3693,7 +993,7 @@ static void usbnet_bh (unsigned long param)
// precondition: never called in_interrupt
-static void usbnet_disconnect (struct usb_interface *intf)
+void usbnet_disconnect (struct usb_interface *intf)
{
struct usbnet *dev;
struct usb_device *xdev;
@@ -3707,7 +1007,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
xdev = interface_to_usbdev (intf);
if (netif_msg_probe (dev))
- devinfo (dev, "unregister usbnet usb-%s-%s, %s",
+ devinfo (dev, "unregister '%s' usb-%s-%s, %s",
+ intf->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description);
@@ -3723,15 +1024,14 @@ static void usbnet_disconnect (struct usb_interface *intf)
free_netdev(net);
usb_put_dev (xdev);
}
+EXPORT_SYMBOL_GPL(usbnet_disconnect);
/*-------------------------------------------------------------------------*/
-static struct ethtool_ops usbnet_ethtool_ops;
-
// precondition: never called in_interrupt
-static int
+int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
struct usbnet *dev;
@@ -3780,6 +1080,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
strcpy (net->name, "usb%d");
memcpy (net->dev_addr, node_id, sizeof node_id);
+ /* rx and tx sides can use different message sizes;
+ * bind() should set rx_urb_size in that case.
+ */
+ dev->hard_mtu = net->mtu + net->hard_header_len;
#if 0
// dma_supported() is deeply broken on almost all architectures
// possible with some EHCI controllers
@@ -3794,7 +1098,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
net->stop = usbnet_stop;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
net->tx_timeout = usbnet_tx_timeout;
- net->do_ioctl = usbnet_ioctl;
net->ethtool_ops = &usbnet_ethtool_ops;
// allow device-specific bind/init procedures
@@ -3807,8 +1110,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if ((dev->driver_info->flags & FLAG_ETHER) != 0
&& (net->dev_addr [0] & 0x02) == 0)
strcpy (net->name, "eth%d");
- } else if (!info->in || info->out)
- status = get_endpoints (dev, udev);
+
+ /* maybe the remote can't receive an Ethernet MTU */
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
+ net->mtu = dev->hard_mtu - net->hard_header_len;
+ } else if (!info->in || !info->out)
+ status = usbnet_get_endpoints (dev, udev);
else {
dev->in = usb_rcvbulkpipe (xdev, info->in);
dev->out = usb_sndbulkpipe (xdev, info->out);
@@ -3820,12 +1127,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
-
if (status == 0 && dev->status)
status = init_status (dev, udev);
if (status < 0)
goto out1;
+ if (!dev->rx_urb_size)
+ dev->rx_urb_size = dev->hard_mtu;
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
SET_NETDEV_DEV(net, &udev->dev);
@@ -3833,8 +1141,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if (status)
goto out3;
if (netif_msg_probe (dev))
- devinfo (dev, "register usbnet at usb-%s-%s, %s, "
+ devinfo (dev, "register '%s' at usb-%s-%s, %s, "
"%02x:%02x:%02x:%02x:%02x:%02x",
+ udev->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description,
net->dev_addr [0], net->dev_addr [1],
@@ -3858,12 +1167,15 @@ out:
usb_put_dev(xdev);
return status;
}
+EXPORT_SYMBOL_GPL(usbnet_probe);
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_PM
+/* FIXME these suspend/resume methods assume non-CDC style
+ * devices, with only one interface.
+ */
-static int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
+int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -3873,370 +1185,39 @@ static int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
netif_device_detach (dev->net);
(void) unlink_urbs (dev, &dev->rxq);
(void) unlink_urbs (dev, &dev->txq);
- intf->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_suspend);
-static int usbnet_resume (struct usb_interface *intf)
+int usbnet_resume (struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
- intf->dev.power.power_state = PMSG_ON;
netif_device_attach (dev->net);
tasklet_schedule (&dev->bh);
return 0;
}
+EXPORT_SYMBOL_GPL(usbnet_resume);
-#else /* !CONFIG_PM */
-
-#define usbnet_suspend NULL
-#define usbnet_resume NULL
-
-#endif /* CONFIG_PM */
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef HAVE_HARDWARE
-#error You need to configure some hardware for this driver
-#endif
-
-/*
- * chip vendor names won't normally be on the cables, and
- * may not be on the device.
- */
-
-static const struct usb_device_id products [] = {
-
-#ifdef CONFIG_USB_ALI_M5632
-{
- USB_DEVICE (0x0402, 0x5632), // ALi defaults
- .driver_info = (unsigned long) &ali_m5632_info,
-},
-#endif
-
-#ifdef CONFIG_USB_AN2720
-{
- USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
- .driver_info = (unsigned long) &an2720_info,
-}, {
- USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
- .driver_info = (unsigned long) &an2720_info,
-},
-#endif
-
-#ifdef CONFIG_USB_BELKIN
-{
- USB_DEVICE (0x050d, 0x0004), // Belkin
- .driver_info = (unsigned long) &belkin_info,
-}, {
- USB_DEVICE (0x056c, 0x8100), // eTEK
- .driver_info = (unsigned long) &belkin_info,
-}, {
- USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK)
- .driver_info = (unsigned long) &belkin_info,
-},
-#endif
-
-#ifdef CONFIG_USB_AX8817X
-{
- // Linksys USB200M
- USB_DEVICE (0x077b, 0x2226),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Netgear FA120
- USB_DEVICE (0x0846, 0x1040),
- .driver_info = (unsigned long) &netgear_fa120_info,
-}, {
- // DLink DUB-E100
- USB_DEVICE (0x2001, 0x1a00),
- .driver_info = (unsigned long) &dlink_dub_e100_info,
-}, {
- // Intellinet, ST Lab USB Ethernet
- USB_DEVICE (0x0b95, 0x1720),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Hawking UF200, TrendNet TU2-ET100
- USB_DEVICE (0x07b8, 0x420a),
- .driver_info = (unsigned long) &hawking_uf200_info,
-}, {
- // Billionton Systems, USB2AR
- USB_DEVICE (0x08dd, 0x90ff),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // ATEN UC210T
- USB_DEVICE (0x0557, 0x2009),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Buffalo LUA-U2-KTX
- USB_DEVICE (0x0411, 0x003d),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
- USB_DEVICE (0x6189, 0x182d),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // corega FEther USB2-TX
- USB_DEVICE (0x07aa, 0x0017),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // Surecom EP-1427X-2
- USB_DEVICE (0x1189, 0x0893),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // goodway corp usb gwusb2e
- USB_DEVICE (0x1631, 0x6200),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // ASIX AX88772 10/100
- USB_DEVICE (0x0b95, 0x7720),
- .driver_info = (unsigned long) &ax88772_info,
-},
-#endif
-
-#ifdef CONFIG_USB_EPSON2888
-{
- USB_DEVICE (0x0525, 0x2888), // EPSON USB client
- .driver_info = (unsigned long) &epson2888_info,
-},
-#endif
-
-#ifdef CONFIG_USB_GENESYS
-{
- USB_DEVICE (0x05e3, 0x0502), // GL620USB-A
- .driver_info = (unsigned long) &genelink_info,
-},
- /* NOT: USB_DEVICE (0x05e3, 0x0501), // GL620USB
- * that's half duplex, not currently supported
- */
-#endif
-
-#ifdef CONFIG_USB_NET1080
-{
- USB_DEVICE (0x0525, 0x1080), // NetChip ref design
- .driver_info = (unsigned long) &net1080_info,
-}, {
- USB_DEVICE (0x06D0, 0x0622), // Laplink Gold
- .driver_info = (unsigned long) &net1080_info,
-},
-#endif
-
-#ifdef CONFIG_USB_PL2301
-{
- USB_DEVICE (0x067b, 0x0000), // PL-2301
- .driver_info = (unsigned long) &prolific_info,
-}, {
- USB_DEVICE (0x067b, 0x0001), // PL-2302
- .driver_info = (unsigned long) &prolific_info,
-},
-#endif
-
-#ifdef CONFIG_USB_KC2190
-{
- USB_DEVICE (0x050f, 0x0190), // KC-190
- .driver_info = (unsigned long) &kc2190_info,
-},
-#endif
-
-#ifdef CONFIG_USB_RNDIS
-{
- /* RNDIS is MSFT's un-official variant of CDC ACM */
- USB_INTERFACE_INFO (USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
- .driver_info = (unsigned long) &rndis_info,
-},
-#endif
-
-#ifdef CONFIG_USB_ARMLINUX
-/*
- * SA-1100 using standard ARM Linux kernels, or compatible.
- * Often used when talking to Linux PDAs (iPaq, Yopy, etc).
- * The sa-1100 "usb-eth" driver handles the basic framing.
- *
- * PXA25x or PXA210 ... these use a "usb-eth" driver much like
- * the sa1100 one, but hardware uses different endpoint numbers.
- *
- * Or the Linux "Ethernet" gadget on hardware that can't talk
- * CDC Ethernet (e.g., no altsettings), in either of two modes:
- * - acting just like the old "usb-eth" firmware, though
- * the implementation is different
- * - supporting RNDIS as the first/default configuration for
- * MS-Windows interop; Linux needs to use the other config
- */
-{
- // 1183 = 0x049F, both used as hex values?
- // Compaq "Itsy" vendor/product id
- USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible
- .driver_info = (unsigned long) &linuxdev_info,
-}, {
- USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy"
- .driver_info = (unsigned long) &yopy_info,
-}, {
- USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
- .driver_info = (unsigned long) &blob_info,
-}, {
- // Linux Ethernet/RNDIS gadget on pxa210/25x/26x
- // e.g. Gumstix, current OpenZaurus, ...
- USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
- .driver_info = (unsigned long) &linuxdev_info,
-},
-#endif
-
-#if defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_CDCETHER)
-/*
- * SA-1100 based Sharp Zaurus ("collie"), or compatible.
- * Same idea as above, but different framing.
- *
- * PXA-2xx based models are also lying-about-cdc.
- * Some models don't even tell the same lies ...
- *
- * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
- * unlike the older ones with 2.4 "embedix" kernels.
- *
- * NOTE: These entries do double-duty, serving as blacklist entries
- * whenever Zaurus support isn't enabled, but CDC Ethernet is.
- */
-#define ZAURUS_MASTER_INTERFACE \
- .bInterfaceClass = USB_CLASS_COMM, \
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
- .bInterfaceProtocol = USB_CDC_PROTO_NONE
-{
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8004,
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_STRONGARM_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8005, /* A-300 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8006, /* B-500/SL-5600 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x8007, /* C-700 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x9031, /* C-750 C-760 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- .idProduct = 0x9032, /* SL-6000 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-}, {
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x04DD,
- /* reported with some C860 units */
- .idProduct = 0x9050, /* C-860 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = ZAURUS_PXA_INFO,
-},
-
-#ifdef CONFIG_USB_ZAURUS
- /* At least some (reports vary) PXA units have very different lies
- * about their standards support: they claim to be cell phones with
- * direct access to their radios. (They don't conform to CDC MDLM.)
- */
-{
- USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
- USB_CDC_PROTO_NONE),
- .driver_info = (unsigned long) &bogus_mdlm_info,
-},
-#endif
-
-/* Olympus has some models with a Zaurus-compatible option.
- * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
- */
-{
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
- | USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x07B4,
- .idProduct = 0x0F02, /* R-1000 */
- ZAURUS_MASTER_INTERFACE,
- .driver_info = OLYMPUS_MXL_INFO,
-},
-#endif
-
-#ifdef CONFIG_USB_CDCETHER
-{
- /* CDC Ether uses two interfaces, not necessarily consecutive.
- * We match the main interface, ignoring the optional device
- * class so we could handle devices that aren't exclusively
- * CDC ether.
- *
- * NOTE: this match must come AFTER entries working around
- * bugs/quirks in a given product (like Zaurus, above).
- */
- USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
- USB_CDC_PROTO_NONE),
- .driver_info = (unsigned long) &cdc_info,
-},
-#endif
-
- { }, // END
-};
-MODULE_DEVICE_TABLE (usb, products);
-
-static struct usb_driver usbnet_driver = {
- .owner = THIS_MODULE,
- .name = driver_name,
- .id_table = products,
- .probe = usbnet_probe,
- .disconnect = usbnet_disconnect,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
-};
-
-/* Default ethtool_ops assigned. Devices can override in their bind() routine */
-static struct ethtool_ops usbnet_ethtool_ops = {
- .get_drvinfo = usbnet_get_drvinfo,
- .get_link = usbnet_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
-};
/*-------------------------------------------------------------------------*/
-static int __init usbnet_init (void)
+static int __init usbnet_init(void)
{
- // compiler should optimize these out
+ /* compiler should optimize this out */
BUG_ON (sizeof (((struct sk_buff *)0)->cb)
< sizeof (struct skb_data));
-#ifdef CONFIG_USB_CDCETHER
- BUG_ON ((sizeof (((struct usbnet *)0)->data)
- < sizeof (struct cdc_state)));
-#endif
random_ether_addr(node_id);
-
- return usb_register(&usbnet_driver);
+ return 0;
}
-module_init (usbnet_init);
+module_init(usbnet_init);
-static void __exit usbnet_exit (void)
+static void __exit usbnet_exit(void)
{
- usb_deregister (&usbnet_driver);
}
-module_exit (usbnet_exit);
+module_exit(usbnet_exit);
-MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (numerous vendors)");
-MODULE_LICENSE ("GPL");
+MODULE_AUTHOR("David Brownell");
+MODULE_DESCRIPTION("USB network driver framework");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
new file mode 100644
index 000000000000..89fc4958eecf
--- /dev/null
+++ b/drivers/usb/net/usbnet.h
@@ -0,0 +1,193 @@
+/*
+ * USB Networking Link Interface
+ *
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.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 __USBNET_H
+#define __USBNET_H
+
+
+/* interface from usbnet core to each USB networking link we handle */
+struct usbnet {
+ /* housekeeping */
+ struct usb_device *udev;
+ struct driver_info *driver_info;
+ wait_queue_head_t *wait;
+
+ /* i/o info: pipes etc */
+ unsigned in, out;
+ struct usb_host_endpoint *status;
+ unsigned maxpacket;
+ struct timer_list delay;
+
+ /* protocol/interface state */
+ struct net_device *net;
+ struct net_device_stats stats;
+ int msg_enable;
+ unsigned long data [5];
+ u32 xid;
+ u32 hard_mtu; /* count any extra framing */
+ size_t rx_urb_size; /* size for rx urbs */
+ struct mii_if_info mii;
+
+ /* various kinds of pending driver work */
+ struct sk_buff_head rxq;
+ struct sk_buff_head txq;
+ struct sk_buff_head done;
+ struct urb *interrupt;
+ struct tasklet_struct bh;
+
+ struct work_struct kevent;
+ unsigned long flags;
+# define EVENT_TX_HALT 0
+# define EVENT_RX_HALT 1
+# define EVENT_RX_MEMORY 2
+# define EVENT_STS_SPLIT 3
+# define EVENT_LINK_RESET 4
+};
+
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
+{
+ return to_usb_driver(intf->dev.driver);
+}
+
+/* interface from the device/framing level "minidriver" to core */
+struct driver_info {
+ char *description;
+
+ int flags;
+/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
+#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
+#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
+#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
+
+#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
+#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
+
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+
+ /* init device ... can sleep, or cause probe() failure */
+ int (*bind)(struct usbnet *, struct usb_interface *);
+
+ /* cleanup device ... can sleep, but can't fail */
+ void (*unbind)(struct usbnet *, struct usb_interface *);
+
+ /* reset device ... can sleep */
+ int (*reset)(struct usbnet *);
+
+ /* see if peer is connected ... can sleep */
+ int (*check_connect)(struct usbnet *);
+
+ /* for status polling */
+ void (*status)(struct usbnet *, struct urb *);
+
+ /* link reset handling, called from defer_kevent */
+ int (*link_reset)(struct usbnet *);
+
+ /* fixup rx packet (strip framing) */
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+ /* fixup tx packet (add framing) */
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
+ struct sk_buff *skb, gfp_t flags);
+
+ /* for new devices, use the descriptor-reading code instead */
+ int in; /* rx endpoint */
+ int out; /* tx endpoint */
+
+ unsigned long data; /* Misc driver specific data */
+};
+
+/* Minidrivers are just drivers using the "usbnet" core as a powerful
+ * network-specific subroutine library ... that happens to do pretty
+ * much everything except custom framing and chip-specific stuff.
+ */
+extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
+extern int usbnet_suspend (struct usb_interface *, pm_message_t );
+extern int usbnet_resume (struct usb_interface *);
+extern void usbnet_disconnect(struct usb_interface *);
+
+
+/* Drivers that reuse some of the standard USB CDC infrastructure
+ * (notably, using multiple interfaces according to the the CDC
+ * union descriptor) get some helper code.
+ */
+struct cdc_state {
+ struct usb_cdc_header_desc *header;
+ struct usb_cdc_union_desc *u;
+ struct usb_cdc_ether_desc *ether;
+ struct usb_interface *control;
+ struct usb_interface *data;
+};
+
+extern int usbnet_generic_cdc_bind (struct usbnet *, struct usb_interface *);
+extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
+
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* we record the state for each of our queued skbs */
+enum skb_state {
+ illegal = 0,
+ tx_start, tx_done,
+ rx_start, rx_done, rx_cleanup
+};
+
+struct skb_data { /* skb->cb is one of these */
+ struct urb *urb;
+ struct usbnet *dev;
+ enum skb_state state;
+ size_t length;
+};
+
+
+extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *);
+extern void usbnet_defer_kevent (struct usbnet *, int);
+extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
+
+extern u32 usbnet_get_msglevel (struct net_device *);
+extern void usbnet_set_msglevel (struct net_device *, u32);
+extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
+
+/* messaging support includes the interface name, so it must not be
+ * used before it has one ... notably, in minidriver bind() calls.
+ */
+#ifdef DEBUG
+#define devdbg(usbnet, fmt, arg...) \
+ printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#else
+#define devdbg(usbnet, fmt, arg...) do {} while(0)
+#endif
+
+#define deverr(usbnet, fmt, arg...) \
+ printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#define devwarn(usbnet, fmt, arg...) \
+ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+
+#define devinfo(usbnet, fmt, arg...) \
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
+
+
+#endif /* __USBNET_H */
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
new file mode 100644
index 000000000000..5d4b7d55b097
--- /dev/null
+++ b/drivers/usb/net/zaurus.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
+ * Copyright (C) 2002-2005 by 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 DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * All known Zaurii lie about their standards conformance. At least
+ * the earliest SA-1100 models lie by saying they support CDC Ethernet.
+ * Some later models (especially PXA-25x and PXA-27x based ones) lie
+ * and say they support CDC MDLM (for access to cell phone modems).
+ *
+ * There are non-Zaurus products that use these same protocols too.
+ *
+ * The annoying thing is that at the same time Sharp was developing
+ * that annoying standards-breaking software, the Linux community had
+ * a simple "CDC Subset" working reliably on the same SA-1100 hardware.
+ * That is, the same functionality but not violating standards.
+ *
+ * The CDC Ethernet nonconformance points are troublesome to hosts
+ * with a true CDC Ethernet implementation:
+ * - Framing appends a CRC, which the spec says drivers "must not" do;
+ * - Transfers data in altsetting zero, instead of altsetting 1;
+ * - All these peripherals use the same ethernet address.
+ *
+ * The CDC MDLM nonconformance is less immediately troublesome, since all
+ * MDLM implementations are quasi-proprietary anyway.
+ */
+
+static struct sk_buff *
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+
+ padlen = 2;
+ if (!skb_cloned(skb)) {
+ int tailroom = skb_tailroom(skb);
+ if ((padlen + 4) <= tailroom)
+ goto done;
+ }
+ skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (skb) {
+ u32 fcs;
+done:
+ fcs = crc32_le(~0, skb->data, skb->len);
+ fcs = ~fcs;
+
+ *skb_put (skb, 1) = fcs & 0xff;
+ *skb_put (skb, 1) = (fcs>> 8) & 0xff;
+ *skb_put (skb, 1) = (fcs>>16) & 0xff;
+ *skb_put (skb, 1) = (fcs>>24) & 0xff;
+ }
+ return skb;
+}
+
+static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ /* Belcarra's funky framing has other options; mostly
+ * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
+ */
+ dev->net->hard_header_len += 6;
+ dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
+ return usbnet_generic_cdc_bind(dev, intf);
+}
+
+/* PDA style devices are always connected if present */
+static int always_connected (struct usbnet *dev)
+{
+ return 0;
+}
+
+static const struct driver_info zaurus_sl5x00_info = {
+ .description = "Sharp Zaurus SL-5x00",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info)
+
+static const struct driver_info zaurus_pxa_info = {
+ .description = "Sharp Zaurus, PXA-2xx based",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
+
+static const struct driver_info olympus_mxl_info = {
+ .description = "Olympus R1000",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .bind = zaurus_bind,
+ .unbind = usbnet_cdc_unbind,
+ .tx_fixup = zaurus_tx_fixup,
+};
+#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info)
+
+
+/* Some more recent products using Lineo/Belcarra code will wrongly claim
+ * CDC MDLM conformance. They aren't conformant: data endpoints live
+ * in the control interface, there's no data interface, and it's not used
+ * to talk to a cell phone radio. But at least we can detect these two
+ * pseudo-classes, rather than growing this product list with entries for
+ * each new nonconformant product (sigh).
+ */
+static const u8 safe_guid[16] = {
+ 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+ 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+};
+static const u8 blan_guid[16] = {
+ 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
+ 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
+};
+
+static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ u8 *buf = intf->cur_altsetting->extra;
+ int len = intf->cur_altsetting->extralen;
+ struct usb_cdc_mdlm_desc *desc = NULL;
+ struct usb_cdc_mdlm_detail_desc *detail = NULL;
+
+ while (len > 3) {
+ if (buf [1] != USB_DT_CS_INTERFACE)
+ goto next_desc;
+
+ /* use bDescriptorSubType, and just verify that we get a
+ * "BLAN" (or "SAFE") descriptor.
+ */
+ switch (buf [2]) {
+ case USB_CDC_MDLM_TYPE:
+ if (desc) {
+ dev_dbg(&intf->dev, "extra MDLM\n");
+ goto bad_desc;
+ }
+ desc = (void *) buf;
+ if (desc->bLength != sizeof *desc) {
+ dev_dbg(&intf->dev, "MDLM len %u\n",
+ desc->bLength);
+ goto bad_desc;
+ }
+ /* expect bcdVersion 1.0, ignore */
+ if (memcmp(&desc->bGUID, blan_guid, 16)
+ && memcmp(&desc->bGUID, safe_guid, 16) ) {
+ /* hey, this one might _really_ be MDLM! */
+ dev_dbg(&intf->dev, "MDLM guid\n");
+ goto bad_desc;
+ }
+ break;
+ case USB_CDC_MDLM_DETAIL_TYPE:
+ if (detail) {
+ dev_dbg(&intf->dev, "extra MDLM detail\n");
+ goto bad_desc;
+ }
+ detail = (void *) buf;
+ switch (detail->bGuidDescriptorType) {
+ case 0: /* "SAFE" */
+ if (detail->bLength != (sizeof *detail + 2))
+ goto bad_detail;
+ break;
+ case 1: /* "BLAN" */
+ if (detail->bLength != (sizeof *detail + 3))
+ goto bad_detail;
+ break;
+ default:
+ goto bad_detail;
+ }
+
+ /* assuming we either noticed BLAN already, or will
+ * find it soon, there are some data bytes here:
+ * - bmNetworkCapabilities (unused)
+ * - bmDataCapabilities (bits, see below)
+ * - bPad (ignored, for PADAFTER -- BLAN-only)
+ * bits are:
+ * - 0x01 -- Zaurus framing (add CRC)
+ * - 0x02 -- PADBEFORE (CRC includes some padding)
+ * - 0x04 -- PADAFTER (some padding after CRC)
+ * - 0x08 -- "fermat" packet mangling (for hw bugs)
+ * the PADBEFORE appears not to matter; we interop
+ * with devices that use it and those that don't.
+ */
+ if ((detail->bDetailData[1] & ~0x02) != 0x01) {
+ /* bmDataCapabilites == 0 would be fine too,
+ * but framing is minidriver-coupled for now.
+ */
+bad_detail:
+ dev_dbg(&intf->dev,
+ "bad MDLM detail, %d %d %d\n",
+ detail->bLength,
+ detail->bDetailData[0],
+ detail->bDetailData[2]);
+ goto bad_desc;
+ }
+ break;
+ }
+next_desc:
+ len -= buf [0]; /* bLength */
+ buf += buf [0];
+ }
+
+ if (!desc || !detail) {
+ dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
+ desc ? "" : "func ",
+ detail ? "" : "detail ");
+ goto bad_desc;
+ }
+
+ /* There's probably a CDC Ethernet descriptor there, but we can't
+ * rely on the Ethernet address it provides since not all vendors
+ * bother to make it unique. Likewise there's no point in tracking
+ * of the CDC event notifications.
+ */
+ return usbnet_get_endpoints(dev, intf);
+
+bad_desc:
+ dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n");
+ return -ENODEV;
+}
+
+static const struct driver_info bogus_mdlm_info = {
+ .description = "pseudo-MDLM (BLAN) device",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .tx_fixup = zaurus_tx_fixup,
+ .bind = blan_mdlm_bind,
+};
+
+static const struct usb_device_id products [] = {
+#define ZAURUS_MASTER_INTERFACE \
+ .bInterfaceClass = USB_CLASS_COMM, \
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8004,
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_STRONGARM_INFO,
+},
+
+/* PXA-2xx based models are also lying-about-cdc. If you add any
+ * more devices that claim to be CDC Ethernet, make sure they get
+ * added to the blacklist in cdc_ether too.
+ *
+ * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
+ * unlike the older ones with 2.4 "embedix" kernels.
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9031, /* C-750 C-760 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x9032, /* SL-6000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9050, /* C-860 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = ZAURUS_PXA_INFO,
+},
+
+
+/* At least some of the newest PXA units have very different lies about
+ * their standards support: they claim to be cell phones offering
+ * direct access to their radios! (No, they don't conform to CDC MDLM.)
+ */
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &bogus_mdlm_info,
+},
+
+/* Olympus has some models with a Zaurus-compatible option.
+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x07B4,
+ .idProduct = 0x0F02, /* R-1000 */
+ ZAURUS_MASTER_INTERFACE,
+ .driver_info = OLYMPUS_MXL_INFO,
+},
+ { }, // END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver zaurus_driver = {
+ .owner = THIS_MODULE,
+ .name = "zaurus",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init zaurus_init(void)
+{
+ return usb_register(&zaurus_driver);
+}
+module_init(zaurus_init);
+
+static void __exit zaurus_exit(void)
+{
+ usb_deregister(&zaurus_driver);
+}
+module_exit(zaurus_exit);
+
+MODULE_AUTHOR("Pavel Machek, David Brownell");
+MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index 29cd801eb958..2f52261c7cc1 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -21,7 +21,7 @@
#include <linux/string.h>
#include <linux/if_arp.h>
#include <linux/firmware.h>
-#include <ieee802_11.h>
+#include <net/ieee80211.h>
#include "zd1201.h"
static struct usb_device_id zd1201_table[] = {
@@ -338,25 +338,24 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
- if ((seq & IEEE802_11_SCTL_FRAG) ||
- (fc & IEEE802_11_FCTL_MOREFRAGS)) {
+ if ((seq & IEEE80211_SCTL_FRAG) ||
+ (fc & IEEE80211_FCTL_MOREFRAGS)) {
struct zd1201_frag *frag = NULL;
char *ptr;
if (datalen<14)
goto resubmit;
- if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
- frag = kmalloc(sizeof(struct zd1201_frag*),
- GFP_ATOMIC);
+ if ((seq & IEEE80211_SCTL_FRAG) == 0) {
+ frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
if (!frag)
goto resubmit;
- skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
+ skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
if (!skb) {
kfree(frag);
goto resubmit;
}
frag->skb = skb;
- frag->seq = seq & IEEE802_11_SCTL_SEQ;
+ frag->seq = seq & IEEE80211_SCTL_SEQ;
skb_reserve(skb, 2);
memcpy(skb_put(skb, 12), &data[datalen-14], 12);
memcpy(skb_put(skb, 2), &data[6], 2);
@@ -365,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
- if(frag->seq == (seq&IEEE802_11_SCTL_SEQ))
+ if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
break;
if (!frag)
goto resubmit;
@@ -373,7 +372,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
ptr = skb_put(skb, len);
if (ptr)
memcpy(ptr, data+8, len);
- if (fc & IEEE802_11_FCTL_MOREFRAGS)
+ if (fc & IEEE80211_FCTL_MOREFRAGS)
goto resubmit;
hlist_del_init(&frag->fnode);
kfree(frag);
@@ -522,7 +521,7 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int
int reqlen;
char seq=0;
struct urb *urb;
- unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+ gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
len += 4; /* first 4 are for header */
@@ -848,7 +847,6 @@ static void zd1201_tx_timeout(struct net_device *dev)
return;
dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
dev->name);
- zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(zd->tx_urb);
zd->stats.tx_errors++;
/* Restart the timeout to quiet the watchdog: */
diff --git a/drivers/usb/serial/ChangeLog.old b/drivers/usb/serial/ChangeLog.old
new file mode 100644
index 000000000000..c1b279939bbf
--- /dev/null
+++ b/drivers/usb/serial/ChangeLog.old
@@ -0,0 +1,730 @@
+This is the contents of some of the drivers/usb/serial/ files that had old
+changelog comments. They were quite old, and out of date, and we don't keep
+them anymore, so I've put them here, away from the source files, in case
+people still care to see them.
+
+- Greg Kroah-Hartman <greg@kroah.com> October 20, 2005
+
+-----------------------------------------------------------------------
+usb-serial.h Change Log comments:
+
+ (03/26/2002) gkh
+ removed the port->tty check from port_paranoia_check() due to serial
+ consoles not having a tty device assigned to them.
+
+ (12/03/2001) gkh
+ removed active from the port structure.
+ added documentation to the usb_serial_device_type structure
+
+ (10/10/2001) gkh
+ added vendor and product to serial structure. Needed to determine device
+ owner when the device is disconnected.
+
+ (05/30/2001) gkh
+ added sem to port structure and removed port_lock
+
+ (10/05/2000) gkh
+ Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
+ fix bug with urb->dev not being set properly, now that the usb core
+ needs it.
+
+ (09/11/2000) gkh
+ Added usb_serial_debug_data function to help get rid of #DEBUG in the
+ drivers.
+
+ (08/28/2000) gkh
+ Added port_lock to port structure.
+
+ (08/08/2000) gkh
+ Added open_count to port structure.
+
+ (07/23/2000) gkh
+ Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+ Modifications to allow usb-serial drivers to be modules.
+
+-----------------------------------------------------------------------
+usb-serial.c Change Log comments:
+
+ (12/10/2002) gkh
+ Split the ports off into their own struct device, and added a
+ usb-serial bus driver.
+
+ (11/19/2002) gkh
+ removed a few #ifdefs for the generic code and cleaned up the failure
+ logic in initialization.
+
+ (10/02/2002) gkh
+ moved the console code to console.c and out of this file.
+
+ (06/05/2002) gkh
+ moved location of startup() call in serial_probe() until after all
+ of the port information and endpoints are initialized. This makes
+ things easier for some drivers.
+
+ (04/10/2002) gkh
+ added serial_read_proc function which creates a
+ /proc/tty/driver/usb-serial file.
+
+ (03/27/2002) gkh
+ Got USB serial console code working properly and merged into the main
+ version of the tree. Thanks to Randy Dunlap for the initial version
+ of this code, and for pushing me to finish it up.
+ The USB serial console works with any usb serial driver device.
+
+ (03/21/2002) gkh
+ Moved all manipulation of port->open_count into the core. Now the
+ individual driver's open and close functions are called only when the
+ first open() and last close() is called. Making the drivers a bit
+ smaller and simpler.
+ Fixed a bug if a driver didn't have the owner field set.
+
+ (02/26/2002) gkh
+ Moved all locking into the main serial_* functions, instead of having
+ the individual drivers have to grab the port semaphore. This should
+ reduce races.
+ Reworked the MOD_INC logic a bit to always increment and decrement, even
+ if the generic driver is being used.
+
+ (10/10/2001) gkh
+ usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
+ help prevent child drivers from accessing the device since it is now
+ gone.
+
+ (09/13/2001) gkh
+ Moved generic driver initialize after we have registered with the USB
+ core. Thanks to Randy Dunlap for pointing this problem out.
+
+ (07/03/2001) gkh
+ Fixed module paramater size. Thanks to John Brockmeyer for the pointer.
+ Fixed vendor and product getting defined through the MODULE_PARM macro
+ if the Generic driver wasn't compiled in.
+ Fixed problem with generic_shutdown() not being called for drivers that
+ don't have a shutdown() function.
+
+ (06/06/2001) gkh
+ added evil hack that is needed for the prolific pl2303 device due to the
+ crazy way its endpoints are set up.
+
+ (05/30/2001) gkh
+ switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (04/08/2001) gb
+ Identify version on module load.
+
+ 2001_02_05 gkh
+ Fixed buffer overflows bug with the generic serial driver. Thanks to
+ Todd Squires <squirest@ct0.com> for fixing this.
+
+ (01/10/2001) gkh
+ Fixed bug where the generic serial adaptor grabbed _any_ device that was
+ offered to it.
+
+ (12/12/2000) gkh
+ Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+ moved them to the serial_open and serial_close functions.
+ Also fixed bug with there not being a MOD_DEC for the generic driver
+ (thanks to Gary Brubaker for finding this.)
+
+ (11/29/2000) gkh
+ Small NULL pointer initialization cleanup which saves a bit of disk image
+
+ (11/01/2000) Adam J. Richter
+ instead of using idVendor/idProduct pairs, usb serial drivers
+ now identify their hardware interest with usb_device_id tables,
+ which they usually have anyhow for use with MODULE_DEVICE_TABLE.
+
+ (10/05/2000) gkh
+ Fixed bug with urb->dev not being set properly, now that the usb
+ core needs it.
+
+ (09/11/2000) gkh
+ Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (08/28/2000) gkh
+ Added port_lock to port structure.
+ Added locks for SMP safeness to generic driver
+ Fixed the ability to open a generic device's port more than once.
+
+ (07/23/2000) gkh
+ Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+ Modifications to allow usb-serial drivers to be modules.
+
+ (07/03/2000) gkh
+ Added more debugging to serial_ioctl call
+
+ (06/25/2000) gkh
+ Changed generic_write_bulk_callback to not call wake_up_interruptible
+ directly, but to have port_softint do it at a safer time.
+
+ (06/23/2000) gkh
+ Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (05/22/2000) gkh
+ Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
+ removed from the individual device source files.
+
+ (05/03/2000) gkh
+ Added the Digi Acceleport driver from Al Borchers and Peter Berger.
+
+ (05/02/2000) gkh
+ Changed devfs and tty register code to work properly now. This was based on
+ the ACM driver changes by Vojtech Pavlik.
+
+ (04/27/2000) Ryan VanderBijl
+ Put calls to *_paranoia_checks into one function.
+
+ (04/23/2000) gkh
+ Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
+ Moved when the startup code printed out the devices that are supported.
+
+ (04/19/2000) gkh
+ Added driver for ZyXEL omni.net lcd plus ISDN TA
+ Made startup info message specify which drivers were compiled in.
+
+ (04/03/2000) gkh
+ Changed the probe process to remove the module unload races.
+ Changed where the tty layer gets initialized to have devfs work nicer.
+ Added initial devfs support.
+
+ (03/26/2000) gkh
+ Split driver up into device specific pieces.
+
+ (03/19/2000) gkh
+ Fixed oops that could happen when device was removed while a program
+ was talking to the device.
+ Removed the static urbs and now all urbs are created and destroyed
+ dynamically.
+ Reworked the internal interface. Now everything is based on the
+ usb_serial_port structure instead of the larger usb_serial structure.
+ This fixes the bug that a multiport device could not have more than
+ one port open at one time.
+
+ (03/17/2000) gkh
+ Added config option for debugging messages.
+ Added patch for keyspan pda from Brian Warner.
+
+ (03/06/2000) gkh
+ Added the keyspan pda code from Brian Warner <warner@lothar.com>
+ Moved a bunch of the port specific stuff into its own structure. This
+ is in anticipation of the true multiport devices (there's a bug if you
+ try to access more than one port of any multiport device right now)
+
+ (02/21/2000) gkh
+ Made it so that any serial devices only have to specify which functions
+ they want to overload from the generic function calls (great,
+ inheritance in C, in a driver, just what I wanted...)
+ Added support for set_termios and ioctl function calls. No drivers take
+ advantage of this yet.
+ Removed the #ifdef MODULE, now there is no module specific code.
+ Cleaned up a few comments in usb-serial.h that were wrong (thanks again
+ to Miles Lott).
+ Small fix to get_free_serial.
+
+ (02/14/2000) gkh
+ Removed the Belkin and Peracom functionality from the driver due to
+ the lack of support from the vendor, and me not wanting people to
+ accidenatly buy the device, expecting it to work with Linux.
+ Added read_bulk_callback and write_bulk_callback to the type structure
+ for the needs of the FTDI and WhiteHEAT driver.
+ Changed all reverences to FTDI to FTDI_SIO at the request of Bill
+ Ryder.
+ Changed the output urb size back to the max endpoint size to make
+ the ftdi_sio driver have it easier, and due to the fact that it didn't
+ really increase the speed any.
+
+ (02/11/2000) gkh
+ Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
+ patch from Miles Lott (milos@insync.net).
+ Fixed bug with not restoring the minor range that a device grabs, if
+ the startup function fails (thanks Miles for finding this).
+
+ (02/05/2000) gkh
+ Added initial framework for the Keyspan PDA serial converter so that
+ Brian Warner has a place to put his code.
+ Made the ezusb specific functions generic enough that different
+ devices can use them (whiteheat and keyspan_pda both need them).
+ Split out a whole bunch of structure and other stuff to a separate
+ usb-serial.h file.
+ Made the Visor connection messages a little more understandable, now
+ that Miles Lott (milos@insync.net) has gotten the Generic channel to
+ work. Also made them always show up in the log file.
+
+ (01/25/2000) gkh
+ Added initial framework for FTDI serial converter so that Bill Ryder
+ has a place to put his code.
+ Added the vendor specific info from Handspring. Now we can print out
+ informational debug messages as well as understand what is happening.
+
+ (01/23/2000) gkh
+ Fixed problem of crash when trying to open a port that didn't have a
+ device assigned to it. Made the minor node finding a little smarter,
+ now it looks to find a continuous space for the new device.
+
+ (01/21/2000) gkh
+ Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
+ Fixed get_serial_by_minor which was all messed up for multi port
+ devices. Fixed multi port problem for generic devices. Now the number
+ of ports is determined by the number of bulk out endpoints for the
+ generic device.
+
+ (01/19/2000) gkh
+ Removed lots of cruft that was around from the old (pre urb) driver
+ interface.
+ Made the serial_table dynamic. This should save lots of memory when
+ the number of minor nodes goes up to 256.
+ Added initial support for devices that have more than one port.
+ Added more debugging comments for the Visor, and added a needed
+ set_configuration call.
+
+ (01/17/2000) gkh
+ Fixed the WhiteHEAT firmware (my processing tool had a bug)
+ and added new debug loader firmware for it.
+ Removed the put_char function as it isn't really needed.
+ Added visor startup commands as found by the Win98 dump.
+
+ (01/13/2000) gkh
+ Fixed the vendor id for the generic driver to the one I meant it to be.
+
+ (01/12/2000) gkh
+ Forget the version numbering...that's pretty useless...
+ Made the driver able to be compiled so that the user can select which
+ converter they want to use. This allows people who only want the Visor
+ support to not pay the memory size price of the WhiteHEAT.
+ Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
+ grabbed the root hub. Not good.
+
+ version 0.4.0 (01/10/2000) gkh
+ Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
+ device. Added startup function to allow firmware to be downloaded to
+ a device if it needs to be.
+ Added firmware download logic to the WhiteHEAT device.
+ Started to add #defines to split up the different drivers for potential
+ configuration option.
+
+ version 0.3.1 (12/30/99) gkh
+ Fixed problems with urb for bulk out.
+ Added initial support for multiple sets of endpoints. This enables
+ the Handspring Visor to be attached successfully. Only the first
+ bulk in / bulk out endpoint pair is being used right now.
+
+ version 0.3.0 (12/27/99) gkh
+ Added initial support for the Handspring Visor based on a patch from
+ Miles Lott (milos@sneety.insync.net)
+ Cleaned up the code a bunch and converted over to using urbs only.
+
+ version 0.2.3 (12/21/99) gkh
+ Added initial support for the Connect Tech WhiteHEAT converter.
+ Incremented the number of ports in expectation of getting the
+ WhiteHEAT to work properly (4 ports per connection).
+ Added notification on insertion and removal of what port the
+ device is/was connected to (and what kind of device it was).
+
+ version 0.2.2 (12/16/99) gkh
+ Changed major number to the new allocated number. We're legal now!
+
+ version 0.2.1 (12/14/99) gkh
+ Fixed bug that happens when device node is opened when there isn't a
+ device attached to it. Thanks to marek@webdesign.no for noticing this.
+
+ version 0.2.0 (11/10/99) gkh
+ Split up internals to make it easier to add different types of serial
+ converters to the code.
+ Added a "generic" driver that gets it's vendor and product id
+ from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
+ for the idea and sample code (from the usb scanner driver.)
+ Cleared up any licensing questions by releasing it under the GNU GPL.
+
+ version 0.1.2 (10/25/99) gkh
+ Fixed bug in detecting device.
+
+ version 0.1.1 (10/05/99) gkh
+ Changed the major number to not conflict with anything else.
+
+ version 0.1 (09/28/99) gkh
+ Can recognize the two different devices and start up a read from
+ device when asked to. Writes also work. No control signals yet, this
+ all is vendor specific data (i.e. no spec), also no control for
+ different baud rates or other bit settings.
+ Currently we are using the same devid as the acm driver. This needs
+ to change.
+
+-----------------------------------------------------------------------
+visor.c Change Log comments:
+
+ (06/03/2003) Judd Montgomery <judd at jpilot.org>
+ Added support for module parameter options for untested/unknown
+ devices.
+
+ (03/09/2003) gkh
+ Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl
+ <brachtl@redgrep.cz> for the information.
+
+ (03/05/2003) gkh
+ Think Treo support is now working.
+
+ (04/03/2002) gkh
+ Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI
+ <hiro@zob.ne.jp> for the information.
+
+ (03/27/2002) gkh
+ Removed assumptions that port->tty was always valid (is not true
+ for usb serial console devices.)
+
+ (03/23/2002) gkh
+ Added support for the Palm i705 device, thanks to Thomas Riemer
+ <tom@netmech.com> for the information.
+
+ (03/21/2002) gkh
+ Added support for the Palm m130 device, thanks to Udo Eisenbarth
+ <udo.eisenbarth@web.de> for the information.
+
+ (02/27/2002) gkh
+ Reworked the urb handling logic. We have no more pool, but dynamically
+ allocate the urb and the transfer buffer on the fly. In testing this
+ does not incure any measurable overhead. This also relies on the fact
+ that we have proper reference counting logic for urbs.
+
+ (02/21/2002) SilaS
+ Added initial support for the Palm m515 devices.
+
+ (02/14/2002) gkh
+ Added support for the Clie S-360 device.
+
+ (12/18/2001) gkh
+ Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand
+ for the patch.
+
+ (11/11/2001) gkh
+ Added support for the m125 devices, and added check to prevent oopses
+ for Clié devices that lie about the number of ports they have.
+
+ (08/30/2001) gkh
+ Added support for the Clie devices, both the 3.5 and 4.0 os versions.
+ Many thanks to Daniel Burke, and Bryan Payne for helping with this.
+
+ (08/23/2001) gkh
+ fixed a few potential bugs pointed out by Oliver Neukum.
+
+ (05/30/2001) gkh
+ switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (05/28/2000) gkh
+ Added initial support for the Palm m500 and Palm m505 devices.
+
+ (04/08/2001) gb
+ Identify version on module load.
+
+ (01/21/2000) gkh
+ Added write_room and chars_in_buffer, as they were previously using the
+ generic driver versions which is all wrong now that we are using an urb
+ pool. Thanks to Wolfgang Grandegger for pointing this out to me.
+ Removed count assignment in the write function, which was not needed anymore
+ either. Thanks to Al Borchers for pointing this out.
+
+ (12/12/2000) gkh
+ Moved MOD_DEC to end of visor_close to be nicer, as the final write
+ message can sleep.
+
+ (11/12/2000) gkh
+ Fixed bug with data being dropped on the floor by forcing tty->low_latency
+ to be on. Hopefully this fixes the OHCI issue!
+
+ (11/01/2000) Adam J. Richter
+ usb_device_id table support
+
+ (10/05/2000) gkh
+ Fixed bug with urb->dev not being set properly, now that the usb
+ core needs it.
+
+ (09/11/2000) gkh
+ Got rid of always calling kmalloc for every urb we wrote out to the
+ device.
+ Added visor_read_callback so we can keep track of bytes in and out for
+ those people who like to know the speed of their device.
+ Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (09/06/2000) gkh
+ Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_
+ the host controller drivers set urb->dev = NULL when the urb is finished.
+
+ (08/28/2000) gkh
+ Added locks for SMP safeness.
+
+ (08/08/2000) gkh
+ Fixed endian problem in visor_startup.
+ Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+ than once.
+
+ (07/23/2000) gkh
+ Added pool of write urbs to speed up transfers to the visor.
+
+ (07/19/2000) gkh
+ Added module_init and module_exit functions to handle the fact that this
+ driver is a loadable module now.
+
+ (07/03/2000) gkh
+ Added visor_set_ioctl and visor_set_termios functions (they don't do much
+ of anything, but are good for debugging.)
+
+ (06/25/2000) gkh
+ Fixed bug in visor_unthrottle that should help with the disconnect in PPP
+ bug that people have been reporting.
+
+ (06/23/2000) gkh
+ Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (04/27/2000) Ryan VanderBijl
+ Fixed memory leak in visor_close
+
+ (03/26/2000) gkh
+ Split driver up into device specific pieces.
+
+-----------------------------------------------------------------------
+pl2303.c Change Log comments:
+
+ 2002_Mar_26 gkh
+ allowed driver to work properly if there is no tty assigned to a port
+ (this happens for serial console devices.)
+
+ 2001_Oct_06 gkh
+ Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it.
+
+ 2001_Sep_19 gkh
+ Added break support.
+
+ 2001_Aug_30 gkh
+ fixed oops in write_bulk_callback.
+
+ 2001_Aug_28 gkh
+ reworked buffer logic to be like other usb-serial drivers. Hopefully
+ removing some reported problems.
+
+ 2001_Jun_06 gkh
+ finished porting to 2.4 format.
+
+
+-----------------------------------------------------------------------
+io_edgeport.c Change Log comments:
+
+ 2003_04_03 al borchers
+ - fixed a bug (that shows up with dosemu) where the tty struct is
+ used in a callback after it has been freed
+
+ 2.3 2002_03_08 greg kroah-hartman
+ - fixed bug when multiple devices were attached at the same time.
+
+ 2.2 2001_11_14 greg kroah-hartman
+ - fixed bug in edge_close that kept the port from being used more
+ than once.
+ - fixed memory leak on device removal.
+ - fixed potential double free of memory when command urb submitting
+ failed.
+ - other small cleanups when the device is removed
+
+ 2.1 2001_07_09 greg kroah-hartman
+ - added support for TIOCMBIS and TIOCMBIC.
+
+ (04/08/2001) gb
+ - Identify version on module load.
+
+ 2.0 2001_03_05 greg kroah-hartman
+ - reworked entire driver to fit properly in with the other usb-serial
+ drivers. Occasional oopses still happen, but it's a good start.
+
+ 1.2.3 (02/23/2001) greg kroah-hartman
+ - changed device table to work properly for 2.4.x final format.
+ - fixed problem with dropping data at high data rates.
+
+ 1.2.2 (11/27/2000) greg kroah-hartman
+ - cleaned up more NTisms.
+ - Added device table for 2.4.0-test11
+
+ 1.2.1 (11/08/2000) greg kroah-hartman
+ - Started to clean up NTisms.
+ - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
+
+ 1.2 (10/17/2000) David Iacovelli
+ Remove all EPIC code and GPL source
+ Fix RELEVANT_IFLAG macro to include flow control
+ changes port configuration changes.
+ Fix redefinition of SERIAL_MAGIC
+ Change all timeout values to 5 seconds
+ Tried to fix the UHCI multiple urb submission, but failed miserably.
+ it seems to work fine with OHCI.
+ ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must
+ find a way to work arount this UHCI bug )
+
+ 1.1 (10/11/2000) David Iacovelli
+ Fix XON/XOFF flow control to support both IXON and IXOFF
+
+ 0.9.27 (06/30/2000) David Iacovelli
+ Added transmit queue and now allocate urb for command writes.
+
+ 0.9.26 (06/29/2000) David Iacovelli
+ Add support for 80251 based edgeport
+
+ 0.9.25 (06/27/2000) David Iacovelli
+ Do not close the port if it has multiple opens.
+
+ 0.9.24 (05/26/2000) David Iacovelli
+ Add IOCTLs to support RXTX and JAVA POS
+ and first cut at running BlackBox Demo
+
+ 0.9.23 (05/24/2000) David Iacovelli
+ Add IOCTLs to support RXTX and JAVA POS
+
+ 0.9.22 (05/23/2000) David Iacovelli
+ fixed bug in enumeration. If epconfig turns on mapping by
+ path after a device is already plugged in, we now update
+ the mapping correctly
+
+ 0.9.21 (05/16/2000) David Iacovelli
+ Added BlockUntilChaseResp() to also wait for txcredits
+ Updated the way we allocate and handle write URBs
+ Add debug code to dump buffers
+
+ 0.9.20 (05/01/2000) David Iacovelli
+ change driver to use usb/tts/
+
+ 0.9.19 (05/01/2000) David Iacovelli
+ Update code to compile if DEBUG is off
+
+ 0.9.18 (04/28/2000) David Iacovelli
+ cleanup and test tty_register with devfs
+
+ 0.9.17 (04/27/2000) greg kroah-hartman
+ changed tty_register around to be like the way it
+ was before, but now it works properly with devfs.
+
+ 0.9.16 (04/26/2000) david iacovelli
+ Fixed bug in GetProductInfo()
+
+ 0.9.15 (04/25/2000) david iacovelli
+ Updated enumeration
+
+ 0.9.14 (04/24/2000) david iacovelli
+ Removed all config/status IOCTLS and
+ converted to using /proc/edgeport
+ still playing with devfs
+
+ 0.9.13 (04/24/2000) david iacovelli
+ Removed configuration based on ttyUSB0
+ Added support for configuration using /prod/edgeport
+ first attempt at using devfs (not working yet!)
+ Added IOCTL to GetProductInfo()
+ Added support for custom baud rates
+ Add support for random port numbers
+
+ 0.9.12 (04/18/2000) david iacovelli
+ added additional configuration IOCTLs
+ use ttyUSB0 for configuration
+
+ 0.9.11 (04/17/2000) greg kroah-hartman
+ fixed module initialization race conditions.
+ made all urbs dynamically allocated.
+ made driver devfs compatible. now it only registers the tty device
+ when the device is actually plugged in.
+
+ 0.9.10 (04/13/2000) greg kroah-hartman
+ added proc interface framework.
+
+ 0.9.9 (04/13/2000) david iacovelli
+ added enumeration code and ioctls to configure the device
+
+ 0.9.8 (04/12/2000) david iacovelli
+ Change interrupt read start when device is plugged in
+ and stop when device is removed
+ process interrupt reads when all ports are closed
+ (keep value of rxBytesAvail consistent with the edgeport)
+ set the USB_BULK_QUEUE flag so that we can shove a bunch
+ of urbs at once down the pipe
+
+ 0.9.7 (04/10/2000) david iacovelli
+ start to add enumeration code.
+ generate serial number for epic devices
+ add support for kdb
+
+ 0.9.6 (03/30/2000) david iacovelli
+ add IOCTL to get string, manufacture, and boot descriptors
+
+ 0.9.5 (03/14/2000) greg kroah-hartman
+ more error checking added to SerialOpen to try to fix UHCI open problem
+
+ 0.9.4 (03/09/2000) greg kroah-hartman
+ added more error checking to handle oops when data is hanging
+ around and tty is abruptly closed.
+
+ 0.9.3 (03/09/2000) david iacovelli
+ Add epic support for xon/xoff chars
+ play with performance
+
+ 0.9.2 (03/08/2000) greg kroah-hartman
+ changed most "info" calls to "dbg"
+ implemented flow control properly in the termios call
+
+ 0.9.1 (03/08/2000) david iacovelli
+ added EPIC support
+ enabled bootloader update
+
+ 0.9 (03/08/2000) greg kroah-hartman
+ Release to IO networks.
+ Integrated changes that David made
+ made getting urbs for writing SMP safe
+
+ 0.8 (03/07/2000) greg kroah-hartman
+ Release to IO networks.
+ Fixed problems that were seen in code by David.
+ Now both Edgeport/4 and Edgeport/2 works properly.
+ Changed most of the functions to use port instead of serial.
+
+ 0.7 (02/27/2000) greg kroah-hartman
+ Milestone 3 release.
+ Release to IO Networks
+ ioctl for waiting on line change implemented.
+ ioctl for getting statistics implemented.
+ multiport support working.
+ lsr and msr registers are now handled properly.
+ change break now hooked up and working.
+ support for all known Edgeport devices.
+
+ 0.6 (02/22/2000) greg kroah-hartman
+ Release to IO networks.
+ CHASE is implemented correctly when port is closed.
+ SerialOpen now blocks correctly until port is fully opened.
+
+ 0.5 (02/20/2000) greg kroah-hartman
+ Release to IO networks.
+ Known problems:
+ modem status register changes are not sent on to the user
+ CHASE is not implemented when the port is closed.
+
+ 0.4 (02/16/2000) greg kroah-hartman
+ Second cut at the CeBit demo.
+ Doesn't leak memory on every write to the port
+ Still small leaks on startup.
+ Added support for Edgeport/2 and Edgeport/8
+
+ 0.3 (02/15/2000) greg kroah-hartman
+ CeBit demo release.
+ Force the line settings to 4800, 8, 1, e for the demo.
+ Warning! This version leaks memory like crazy!
+
+ 0.2 (01/30/2000) greg kroah-hartman
+ Milestone 1 release.
+ Device is found by USB subsystem, enumerated, fimware is downloaded
+ and the descriptors are printed to the debug log, config is set, and
+ green light starts to blink. Open port works, and data can be sent
+ and received at the default settings of the UART. Loopback connector
+ and debug log confirms this.
+
+ 0.1 (01/23/2000) greg kroah-hartman
+ Initial release to help IO Networks try to set up their test system.
+ Edgeport4 is recognized, firmware is downloaded, config is set so
+ device blinks green light every 3 sec. Port is bound, but opening,
+ closing, and sending data do not work properly.
+
+
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 9438909e87a5..7b5e8e4ee2bb 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -394,6 +394,15 @@ config USB_SERIAL_MCT_U232
To compile this driver as a module, choose M here: the
module will be called mct_u232.
+config USB_SERIAL_NOKIA_DKU2
+ tristate "USB Nokia DKU2 Driver"
+ depends on USB_SERIAL
+ help
+ Say Y here if you want to use a Nokia DKU2 device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nokia_dku2.
+
config USB_SERIAL_PL2303
tristate "USB Prolific 2303 Single Port Serial Driver"
depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 6c7cdcc99a9e..55fd461793b7 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_NOKIA_DKU2) += nokia_dku2.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index a4ce0008d69b..1f29d8837327 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -16,7 +16,8 @@
#include "usb-serial.h"
static struct usb_device_id id_table [] = {
- { USB_DEVICE(0xf3d, 0x0112) },
+ { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
+ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -29,9 +30,11 @@ static struct usb_driver airprime_driver = {
.id_table = id_table,
};
-static struct usb_serial_device_type airprime_device = {
- .owner = THIS_MODULE,
- .name = "airprime",
+static struct usb_serial_driver airprime_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "airprime",
+ },
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index abb1b2c543bb..84bc0ee4f061 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -121,10 +121,12 @@ static struct usb_driver belkin_driver = {
};
/* All of the device info needed for the serial converters */
-static struct usb_serial_device_type belkin_device = {
- .owner = THIS_MODULE,
- .name = "Belkin / Peracom / GoHubs USB Serial Adapter",
- .short_name = "belkin",
+static struct usb_serial_driver belkin_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "belkin",
+ },
+ .description = "Belkin / Peracom / GoHubs USB Serial Adapter",
.id_table = id_table_combined,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 2f612c2d894b..664139afcfa9 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -18,7 +18,7 @@
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
- struct usb_serial_device_type *driver;
+ struct usb_serial_driver *driver;
const struct usb_serial_port *port;
/*
@@ -44,7 +44,7 @@ struct bus_type usb_serial_bus_type = {
static int usb_serial_device_probe (struct device *dev)
{
- struct usb_serial_device_type *driver;
+ struct usb_serial_driver *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
@@ -57,13 +57,13 @@ static int usb_serial_device_probe (struct device *dev)
driver = port->serial->type;
if (driver->port_probe) {
- if (!try_module_get(driver->owner)) {
+ if (!try_module_get(driver->driver.owner)) {
dev_err(dev, "module get failed, exiting\n");
retval = -EIO;
goto exit;
}
retval = driver->port_probe (port);
- module_put(driver->owner);
+ module_put(driver->driver.owner);
if (retval)
goto exit;
}
@@ -72,7 +72,7 @@ static int usb_serial_device_probe (struct device *dev)
tty_register_device (usb_serial_tty_driver, minor, dev);
dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d\n",
- driver->name, minor);
+ driver->description, minor);
exit:
return retval;
@@ -80,7 +80,7 @@ exit:
static int usb_serial_device_remove (struct device *dev)
{
- struct usb_serial_device_type *driver;
+ struct usb_serial_driver *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
@@ -92,43 +92,38 @@ static int usb_serial_device_remove (struct device *dev)
driver = port->serial->type;
if (driver->port_remove) {
- if (!try_module_get(driver->owner)) {
+ if (!try_module_get(driver->driver.owner)) {
dev_err(dev, "module get failed, exiting\n");
retval = -EIO;
goto exit;
}
retval = driver->port_remove (port);
- module_put(driver->owner);
+ module_put(driver->driver.owner);
}
exit:
minor = port->number;
tty_unregister_device (usb_serial_tty_driver, minor);
dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
- driver->name, minor);
+ driver->description, minor);
return retval;
}
-int usb_serial_bus_register(struct usb_serial_device_type *device)
+int usb_serial_bus_register(struct usb_serial_driver *driver)
{
int retval;
- if (device->short_name)
- device->driver.name = (char *)device->short_name;
- else
- device->driver.name = (char *)device->name;
- device->driver.bus = &usb_serial_bus_type;
- device->driver.probe = usb_serial_device_probe;
- device->driver.remove = usb_serial_device_remove;
- device->driver.owner = device->owner;
+ driver->driver.bus = &usb_serial_bus_type;
+ driver->driver.probe = usb_serial_device_probe;
+ driver->driver.remove = usb_serial_device_remove;
- retval = driver_register(&device->driver);
+ retval = driver_register(&driver->driver);
return retval;
}
-void usb_serial_bus_deregister(struct usb_serial_device_type *device)
+void usb_serial_bus_deregister(struct usb_serial_driver *driver)
{
- driver_unregister (&device->driver);
+ driver_unregister(&driver->driver);
}
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 4ace9964fc6b..c5334dd89b12 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.04"
+#define DRIVER_VERSION "v0.05"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
@@ -54,8 +54,11 @@ static void cp2101_shutdown(struct usb_serial*);
static int debug;
static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ } /* Terminating Entry */
};
@@ -64,15 +67,17 @@ MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver cp2101_driver = {
.owner = THIS_MODULE,
- .name = "CP2101",
+ .name = "cp2101",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
};
-static struct usb_serial_device_type cp2101_device = {
- .owner = THIS_MODULE,
- .name = "CP2101",
+static struct usb_serial_driver cp2101_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "cp2101",
+ },
.id_table = id_table,
.num_interrupt_in = 0,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index b5b431067b08..e581e4ae8483 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -83,10 +83,12 @@ static struct usb_driver cyberjack_driver = {
.id_table = id_table,
};
-static struct usb_serial_device_type cyberjack_device = {
- .owner = THIS_MODULE,
- .name = "Reiner SCT Cyberjack USB card reader",
- .short_name = "cyberjack",
+static struct usb_serial_driver cyberjack_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "cyberjack",
+ },
+ .description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 012e63e05806..af9290ed257b 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -176,10 +176,12 @@ static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, u
static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
-static struct usb_serial_device_type cypress_earthmate_device = {
- .owner = THIS_MODULE,
- .name = "DeLorme Earthmate USB",
- .short_name = "earthmate",
+static struct usb_serial_driver cypress_earthmate_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "earthmate",
+ },
+ .description = "DeLorme Earthmate USB",
.id_table = id_table_earthmate,
.num_interrupt_in = 1,
.num_interrupt_out = 1,
@@ -203,10 +205,12 @@ static struct usb_serial_device_type cypress_earthmate_device = {
.write_int_callback = cypress_write_int_callback,
};
-static struct usb_serial_device_type cypress_hidcom_device = {
- .owner = THIS_MODULE,
- .name = "HID->COM RS232 Adapter",
- .short_name = "cyphidcom",
+static struct usb_serial_driver cypress_hidcom_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "cyphidcom",
+ },
+ .description = "HID->COM RS232 Adapter",
.id_table = id_table_cyphidcomrs232,
.num_interrupt_in = 1,
.num_interrupt_out = 1,
@@ -453,8 +457,8 @@ static int generic_startup (struct usb_serial *serial)
priv->cbr_mask = B300;
usb_set_serial_port_data(serial->port[0], priv);
- return (0);
-}
+ return 0;
+}
static int cypress_earthmate_startup (struct usb_serial *serial)
@@ -464,14 +468,15 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
+ dbg("%s - Failed setting up port %d", __FUNCTION__,
+ serial->port[0]->number);
return 1;
}
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_EARTHMATE;
-
- return (0);
+
+ return 0;
} /* cypress_earthmate_startup */
@@ -482,14 +487,15 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
if (generic_startup(serial)) {
- dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number);
+ dbg("%s - Failed setting up port %d", __FUNCTION__,
+ serial->port[0]->number);
return 1;
}
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_CYPHIDCOM;
- return (0);
+ return 0;
} /* cypress_hidcom_startup */
@@ -608,8 +614,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
timeout = max((HZ*2560)/bps,HZ/10);
else
timeout = 2*HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
+ schedule_timeout_interruptible(timeout);
dbg("%s - stopping urbs", __FUNCTION__);
usb_kill_urb (port->interrupt_in_urb);
@@ -909,7 +914,8 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
} /* cypress_ioctl */
-static void cypress_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void cypress_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
@@ -918,7 +924,7 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
unsigned long flags;
__u8 oldlines;
int linechange = 0;
-
+
dbg("%s - port %d", __FUNCTION__, port->number);
tty = port->tty;
@@ -931,10 +937,12 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
*(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ CLOCAL;
} else if (priv->chiptype == CT_CYPHIDCOM) {
*(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
}
priv->termios_initialized = 1;
}
@@ -946,12 +954,15 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
/* check if there are new settings */
if (old_termios) {
if ((cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - attempting to set new termios settings", __FUNCTION__);
- /* should make a copy of this in case something goes wrong in the function, we can restore it */
+ (RELEVANT_IFLAG(iflag) !=
+ RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg("%s - attempting to set new termios settings",
+ __FUNCTION__);
+ /* should make a copy of this in case something goes
+ * wrong in the function, we can restore it */
spin_lock_irqsave(&priv->lock, flags);
priv->tmp_termios = *(tty->termios);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
} else {
dbg("%s - nothing to do, exiting", __FUNCTION__);
return;
@@ -962,21 +973,34 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
/* set number of data bits, parity, stop bits */
/* when parity is disabled the parity type bit is ignored */
- stop_bits = cflag & CSTOPB ? 1 : 0; /* 1 means 2 stop bits, 0 means 1 stop bit */
-
+ /* 1 means 2 stop bits, 0 means 1 stop bit */
+ stop_bits = cflag & CSTOPB ? 1 : 0;
+
if (cflag & PARENB) {
parity_enable = 1;
- parity_type = cflag & PARODD ? 1 : 0; /* 1 means odd parity, 0 means even parity */
+ /* 1 means odd parity, 0 means even parity */
+ parity_type = cflag & PARODD ? 1 : 0;
} else
parity_enable = parity_type = 0;
if (cflag & CSIZE) {
switch (cflag & CSIZE) {
- case CS5: data_bits = 0; break;
- case CS6: data_bits = 1; break;
- case CS7: data_bits = 2; break;
- case CS8: data_bits = 3; break;
- default: err("%s - CSIZE was set, but not CS5-CS8", __FUNCTION__); data_bits = 3;
+ case CS5:
+ data_bits = 0;
+ break;
+ case CS6:
+ data_bits = 1;
+ break;
+ case CS7:
+ data_bits = 2;
+ break;
+ case CS8:
+ data_bits = 3;
+ break;
+ default:
+ err("%s - CSIZE was set, but not CS5-CS8",
+ __FUNCTION__);
+ data_bits = 3;
}
} else
data_bits = 3;
@@ -991,63 +1015,85 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
} else {
baud_mask = (cflag & CBAUD);
switch(baud_mask) {
- case B300: dbg("%s - setting baud 300bps", __FUNCTION__); break;
- case B600: dbg("%s - setting baud 600bps", __FUNCTION__); break;
- case B1200: dbg("%s - setting baud 1200bps", __FUNCTION__); break;
- case B2400: dbg("%s - setting baud 2400bps", __FUNCTION__); break;
- case B4800: dbg("%s - setting baud 4800bps", __FUNCTION__); break;
- case B9600: dbg("%s - setting baud 9600bps", __FUNCTION__); break;
- case B19200: dbg("%s - setting baud 19200bps", __FUNCTION__); break;
- case B38400: dbg("%s - setting baud 38400bps", __FUNCTION__); break;
- case B57600: dbg("%s - setting baud 57600bps", __FUNCTION__); break;
- case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break;
- default: dbg("%s - unknown masked baud rate", __FUNCTION__);
+ case B300:
+ dbg("%s - setting baud 300bps", __FUNCTION__);
+ break;
+ case B600:
+ dbg("%s - setting baud 600bps", __FUNCTION__);
+ break;
+ case B1200:
+ dbg("%s - setting baud 1200bps", __FUNCTION__);
+ break;
+ case B2400:
+ dbg("%s - setting baud 2400bps", __FUNCTION__);
+ break;
+ case B4800:
+ dbg("%s - setting baud 4800bps", __FUNCTION__);
+ break;
+ case B9600:
+ dbg("%s - setting baud 9600bps", __FUNCTION__);
+ break;
+ case B19200:
+ dbg("%s - setting baud 19200bps", __FUNCTION__);
+ break;
+ case B38400:
+ dbg("%s - setting baud 38400bps", __FUNCTION__);
+ break;
+ case B57600:
+ dbg("%s - setting baud 57600bps", __FUNCTION__);
+ break;
+ case B115200:
+ dbg("%s - setting baud 115200bps", __FUNCTION__);
+ break;
+ default:
+ dbg("%s - unknown masked baud rate", __FUNCTION__);
}
priv->line_control = (CONTROL_DTR | CONTROL_RTS);
}
spin_unlock_irqrestore(&priv->lock, flags);
-
- dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)", __FUNCTION__,
- stop_bits, parity_enable, parity_type, data_bits);
- cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
- parity_type, 0, CYPRESS_SET_CONFIG);
+ dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
+ "%d data_bits (+5)", __FUNCTION__, stop_bits,
+ parity_enable, parity_type, data_bits);
+
+ cypress_serial_control(port, baud_mask, data_bits, stop_bits,
+ parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
- /* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
- * this should confirm that all is working if it returns what we just set */
+ /* we perform a CYPRESS_GET_CONFIG so that the current settings are
+ * filled into the private structure this should confirm that all is
+ * working if it returns what we just set */
cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
- /* Here we can define custom tty settings for devices
- *
- * the main tty termios flag base comes from empeg.c
- */
+ /* Here we can define custom tty settings for devices; the main tty
+ * termios flag base comes from empeg.c */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
-
- dbg("Using custom termios settings for a baud rate of 4800bps.");
+ dbg("Using custom termios settings for a baud rate of "
+ "4800bps.");
/* define custom termios settings for NMEA protocol */
tty->termios->c_iflag /* input modes - */
- &= ~(IGNBRK /* disable ignore break */
- | BRKINT /* disable break causes interrupt */
- | PARMRK /* disable mark parity errors */
- | ISTRIP /* disable clear high bit of input characters */
- | INLCR /* disable translate NL to CR */
- | IGNCR /* disable ignore CR */
- | ICRNL /* disable translate CR to NL */
- | IXON); /* disable enable XON/XOFF flow control */
-
+ &= ~(IGNBRK /* disable ignore break */
+ | BRKINT /* disable break causes interrupt */
+ | PARMRK /* disable mark parity errors */
+ | ISTRIP /* disable clear high bit of input char */
+ | INLCR /* disable translate NL to CR */
+ | IGNCR /* disable ignore CR */
+ | ICRNL /* disable translate CR to NL */
+ | IXON); /* disable enable XON/XOFF flow control */
+
tty->termios->c_oflag /* output modes */
- &= ~OPOST; /* disable postprocess output characters */
-
- tty->termios->c_lflag /* line discipline modes */
- &= ~(ECHO /* disable echo input characters */
- | ECHONL /* disable echo new line */
- | ICANON /* disable erase, kill, werase, and rprnt special characters */
- | ISIG /* disable interrupt, quit, and suspend special characters */
- | IEXTEN); /* disable non-POSIX special characters */
+ &= ~OPOST; /* disable postprocess output char */
+ tty->termios->c_lflag /* line discipline modes */
+ &= ~(ECHO /* disable echo input characters */
+ | ECHONL /* disable echo new line */
+ | ICANON /* disable erase, kill, werase, and rprnt
+ special characters */
+ | ISIG /* disable interrupt, quit, and suspend
+ special characters */
+ | IEXTEN); /* disable non-POSIX special characters */
} /* CT_CYPHIDCOM: Application should handle this for device */
linechange = (priv->line_control != oldlines);
@@ -1060,7 +1106,7 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
}
} /* cypress_set_termios */
-
+
/* returns amount of data still left in soft buffer */
static int cypress_chars_in_buffer(struct usb_serial_port *port)
{
@@ -1088,7 +1134,7 @@ static void cypress_throttle (struct usb_serial_port *port)
spin_lock_irqsave(&priv->lock, flags);
priv->rx_flags = THROTTLED;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1110,7 +1156,8 @@ static void cypress_unthrottle (struct usb_serial_port *port)
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+ dev_err(&port->dev, "%s - failed submitting read urb, "
+ "error %d\n", __FUNCTION__, result);
}
}
@@ -1122,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
- char tty_flag = TTY_NORMAL;
+ char tty_flag = TTY_NORMAL;
int havedata = 0;
int bytes = 0;
int result;
@@ -1131,7 +1178,8 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) {
- dbg("%s - nonzero read status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero read status received: %d", __FUNCTION__,
+ urb->status);
return;
}
@@ -1155,51 +1203,55 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
case 32:
/* This is for the CY7C64013... */
priv->current_status = data[0] & 0xF8;
- bytes = data[1]+2;
- i=2;
+ bytes = data[1] + 2;
+ i = 2;
if (bytes > 2)
havedata = 1;
break;
case 8:
/* This is for the CY7C63743... */
priv->current_status = data[0] & 0xF8;
- bytes = (data[0] & 0x07)+1;
- i=1;
+ bytes = (data[0] & 0x07) + 1;
+ i = 1;
if (bytes > 1)
havedata = 1;
break;
default:
- dbg("%s - wrong packet size - received %d bytes", __FUNCTION__, urb->actual_length);
+ dbg("%s - wrong packet size - received %d bytes",
+ __FUNCTION__, urb->actual_length);
spin_unlock_irqrestore(&priv->lock, flags);
goto continue_read;
}
spin_unlock_irqrestore(&priv->lock, flags);
- usb_serial_debug_data (debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
+ urb->actual_length, data);
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
if (priv != NULL) {
if (priv->current_status != priv->prev_status) {
- priv->diff_status |= priv->current_status ^ priv->prev_status;
+ priv->diff_status |= priv->current_status ^
+ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = priv->current_status;
}
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
- /* hangup, as defined in acm.c... this might be a bad place for it though */
- if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) {
+ /* hangup, as defined in acm.c... this might be a bad place for it
+ * though */
+ if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ !(priv->current_status & UART_CD)) {
dbg("%s - calling hangup", __FUNCTION__);
tty_hangup(tty);
goto continue_read;
}
- /* There is one error bit... I'm assuming it is a parity error indicator
- * as the generic firmware will set this bit to 1 if a parity error occurs.
- * I can not find reference to any other error events.
- *
- */
+ /* There is one error bit... I'm assuming it is a parity error
+ * indicator as the generic firmware will set this bit to 1 if a
+ * parity error occurs.
+ * I can not find reference to any other error events. */
spin_lock_irqsave(&priv->lock, flags);
if (priv->current_status & CYP_ERROR) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1211,7 +1263,8 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
/* process read if there is data other than line status */
if (tty && (bytes > i)) {
for (; i < bytes ; ++i) {
- dbg("pushing byte number %d - %d - %c",i,data[i],data[i]);
+ dbg("pushing byte number %d - %d - %c", i, data[i],
+ data[i]);
if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
@@ -1221,25 +1274,28 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
}
spin_lock_irqsave(&priv->lock, flags);
- priv->bytes_in += bytes; /* control and status byte(s) are also counted */
+ /* control and status byte(s) are also counted */
+ priv->bytes_in += bytes;
spin_unlock_irqrestore(&priv->lock, flags);
continue_read:
-
- /* Continue trying to always read... unless the port has closed. */
+
+ /* Continue trying to always read... unless the port has closed. */
if (port->open_count > 0) {
- usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
- usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
- port->interrupt_in_urb->transfer_buffer,
- port->interrupt_in_urb->transfer_buffer_length,
- cypress_read_int_callback, port,
- interval);
- result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- if (result)
- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
+ usb_rcvintpipe(port->serial->dev,
+ port->interrupt_in_endpointAddress),
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
+ cypress_read_int_callback, port, interval);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting "
+ "read urb, error %d\n", __FUNCTION__,
+ result);
}
-
+
return;
} /* cypress_read_int_callback */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index a19a47f6cf12..dc74644a603d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -503,10 +503,12 @@ static struct usb_driver digi_driver = {
/* device info needed for the Digi serial converter */
-static struct usb_serial_device_type digi_acceleport_2_device = {
- .owner = THIS_MODULE,
- .name = "Digi 2 port USB adapter",
- .short_name = "digi_2",
+static struct usb_serial_driver digi_acceleport_2_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "digi_2",
+ },
+ .description = "Digi 2 port USB adapter",
.id_table = id_table_2,
.num_interrupt_in = 0,
.num_bulk_in = 4,
@@ -530,10 +532,12 @@ static struct usb_serial_device_type digi_acceleport_2_device = {
.shutdown = digi_shutdown,
};
-static struct usb_serial_device_type digi_acceleport_4_device = {
- .owner = THIS_MODULE,
- .name = "Digi 4 port USB adapter",
- .short_name = "digi_4",
+static struct usb_serial_driver digi_acceleport_4_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "digi_4",
+ },
+ .description = "Digi 4 port USB adapter",
.id_table = id_table_4,
.num_interrupt_in = 0,
.num_bulk_in = 5,
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 8d562ab454a8..0b0546dcc7b9 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -112,9 +112,11 @@ static struct usb_driver empeg_driver = {
.id_table = id_table,
};
-static struct usb_serial_device_type empeg_device = {
- .owner = THIS_MODULE,
- .name = "Empeg",
+static struct usb_serial_driver empeg_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "empeg",
+ },
.id_table = id_table,
.num_interrupt_in = 0,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index d1964a0c4168..61204bf7cd78 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -269,6 +269,8 @@
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
static int debug;
+static __u16 vendor = FTDI_VID;
+static __u16 product;
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
@@ -407,6 +409,35 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
+ /*
+ * These will probably use user-space drivers. Uncomment them if
+ * you need them or use the user-specified vendor/product module
+ * parameters (see ftdi_sio.h for the numbers). Make a fuss if
+ * you think the driver should recognize any of them by default.
+ */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
+ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -418,6 +449,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
{ 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_RM_CANVIEW_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
@@ -427,12 +459,24 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
- { } /* Terminating entry */
+ { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
+ { }, /* Optional parameter entry */
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
@@ -518,10 +562,12 @@ static unsigned short int ftdi_232am_baud_to_divisor (int baud);
static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
static __u32 ftdi_232bm_baud_to_divisor (int baud);
-static struct usb_serial_device_type ftdi_sio_device = {
- .owner = THIS_MODULE,
- .name = "FTDI USB Serial Device",
- .short_name = "ftdi_sio",
+static struct usb_serial_driver ftdi_sio_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ftdi_sio",
+ },
+ .description = "FTDI USB Serial Device",
.id_table = id_table_combined,
.num_interrupt_in = 0,
.num_bulk_in = 1,
@@ -874,7 +920,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
unsigned interfaces;
/* Assume it is not the original SIO device for now. */
- priv->baud_base = 48000000 / 16;
+ priv->baud_base = 48000000 / 2;
priv->write_offset = 0;
version = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -1806,10 +1852,12 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
} else {
/* set the baudrate determined before */
if (change_speed(port)) {
- err("%s urb failed to set baurdrate", __FUNCTION__);
+ err("%s urb failed to set baudrate", __FUNCTION__);
+ }
+ /* Ensure RTS and DTR are raised when baudrate changed from 0 */
+ if ((old_termios->c_cflag & CBAUD) == B0) {
+ set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
- /* Ensure RTS and DTR are raised */
- set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
/* Set flow control */
@@ -2030,6 +2078,15 @@ static int __init ftdi_init (void)
int retval;
dbg("%s", __FUNCTION__);
+ if (vendor > 0 && product > 0) {
+ /* Add user specified VID/PID to reserved element of table. */
+ int i;
+ for (i = 0; id_table_combined[i].idVendor; i++)
+ ;
+ id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ id_table_combined[i].idVendor = vendor;
+ id_table_combined[i].idProduct = product;
+ }
retval = usb_serial_register(&ftdi_sio_device);
if (retval)
goto failed_sio_register;
@@ -2066,4 +2123,9 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
+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");
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 9f4342093e8b..ddb63df31ce6 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -142,10 +142,43 @@
/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */
-/* ELV USB Module UO100 (PID sent by Stefan Frings) */
-#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
-/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
-#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */
+/*
+ * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
+ * All of these devices use FTDI's vendor ID (0x0403).
+ *
+ * The previously included PID for the UO 100 module was incorrect.
+ * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
+ *
+ * Armin Laeuger originally sent the PID for the UM 100 module.
+ */
+#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */
+#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */
+#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */
+#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */
+/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
+ * MS Windows, rather than the FTDI Virtual Com Port drivers.
+ * Maybe these will be easier to use with the libftdi/libusb user-space
+ * drivers, or possibly the Comedi drivers in some cases. */
+#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */
+#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */
+#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */
+#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */
+#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */
+#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */
+#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */
+#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */
+#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */
+#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */
+#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */
+#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */
+#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */
+#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
+#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */
+#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */
+#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */
+#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */
+#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */
+#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */
/*
* Definitions for ID TECH (www.idt-net.com) devices
@@ -166,6 +199,19 @@
#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */
/*
+ * Definitions for Artemis astronomical USB based cameras
+ * Check it at http://www.artemisccd.co.uk/
+ */
+#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */
+
+/*
+ * Definitions for ATIK Instruments astronomical USB based cameras
+ * Check it at http://www.atik-instruments.com/
+ */
+#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Camera */
+#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Camera */
+
+/*
* Protego product ids
*/
#define PROTEGO_SPECIAL_1 0xFC70 /* special/unknown device */
@@ -222,6 +268,7 @@
*/
#define FALCOM_VID 0x0F94 /* Vendor Id */
#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */
+#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */
/*
* SUUNTO product ids
@@ -277,12 +324,27 @@
#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */
/*
+ * Xsens Technologies BV products (http://www.xsens.com).
+ */
+#define XSENS_CONVERTER_0_PID 0xD388
+#define XSENS_CONVERTER_1_PID 0xD389
+#define XSENS_CONVERTER_2_PID 0xD38A
+#define XSENS_CONVERTER_3_PID 0xD38B
+#define XSENS_CONVERTER_4_PID 0xD38C
+#define XSENS_CONVERTER_5_PID 0xD38D
+#define XSENS_CONVERTER_6_PID 0xD38E
+#define XSENS_CONVERTER_7_PID 0xD38F
+
+/*
* Evolution Robotics products (http://www.evolution.com/).
* Submitted by Shawn M. Lavelle.
*/
#define EVOLUTION_VID 0xDEEE /* Vendor ID */
#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */
+/* Pyramid Computer GmbH */
+#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
+
/* 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 2ef614d5c8f2..35820bda7ae1 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1468,16 +1468,13 @@ static void garmin_shutdown (struct usb_serial *serial)
}
-
-
-
-
-
/* All of the device info needed */
-static struct usb_serial_device_type garmin_device = {
- .owner = THIS_MODULE,
- .name = "Garmin GPS usb/tty",
- .short_name = "garmin_gps",
+static struct usb_serial_driver garmin_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "garmin_gps",
+ },
+ .description = "Garmin GPS usb/tty",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index ddde5fb13f6b..8909208f506a 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -36,10 +36,11 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
/* All of the device info needed for the Generic Serial Converter */
-struct usb_serial_device_type usb_serial_generic_device = {
- .owner = THIS_MODULE,
- .name = "Generic",
- .short_name = "generic",
+struct usb_serial_driver usb_serial_generic_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "generic",
+ },
.id_table = generic_device_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -223,7 +224,7 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->num_bulk_out) {
- if (port->write_urb_busy)
+ if (!(port->write_urb_busy))
room = port->bulk_out_size;
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 64d55fbd206e..8eadfb705601 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -38,15 +38,17 @@ MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver hp49gp_driver = {
.owner = THIS_MODULE,
- .name = "HP4X",
+ .name = "hp4X",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
};
-static struct usb_serial_device_type hp49gp_device = {
- .owner = THIS_MODULE,
- .name = "HP4X",
+static struct usb_serial_driver hp49gp_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "hp4X",
+ },
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 04bfe279d763..dc4c498bd1ed 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -27,225 +27,6 @@
* Networks technical support, or Peter Berger <pberger@brimson.com>,
* or Al Borchers <alborchers@steinerpoint.com>.
*
- * Version history:
- *
- * 2003_04_03 al borchers
- * - fixed a bug (that shows up with dosemu) where the tty struct is
- * used in a callback after it has been freed
- *
- * 2.3 2002_03_08 greg kroah-hartman
- * - fixed bug when multiple devices were attached at the same time.
- *
- * 2.2 2001_11_14 greg kroah-hartman
- * - fixed bug in edge_close that kept the port from being used more
- * than once.
- * - fixed memory leak on device removal.
- * - fixed potential double free of memory when command urb submitting
- * failed.
- * - other small cleanups when the device is removed
- *
- * 2.1 2001_07_09 greg kroah-hartman
- * - added support for TIOCMBIS and TIOCMBIC.
- *
- * (04/08/2001) gb
- * - Identify version on module load.
- *
- * 2.0 2001_03_05 greg kroah-hartman
- * - reworked entire driver to fit properly in with the other usb-serial
- * drivers. Occasional oopses still happen, but it's a good start.
- *
- * 1.2.3 (02/23/2001) greg kroah-hartman
- * - changed device table to work properly for 2.4.x final format.
- * - fixed problem with dropping data at high data rates.
- *
- * 1.2.2 (11/27/2000) greg kroah-hartman
- * - cleaned up more NTisms.
- * - Added device table for 2.4.0-test11
- *
- * 1.2.1 (11/08/2000) greg kroah-hartman
- * - Started to clean up NTisms.
- * - Fixed problem with dev field of urb for kernels >= 2.4.0-test9
- *
- * 1.2 (10/17/2000) David Iacovelli
- * Remove all EPIC code and GPL source
- * Fix RELEVANT_IFLAG macro to include flow control
- * changes port configuration changes.
- * Fix redefinition of SERIAL_MAGIC
- * Change all timeout values to 5 seconds
- * Tried to fix the UHCI multiple urb submission, but failed miserably.
- * it seems to work fine with OHCI.
- * ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must
- * find a way to work arount this UHCI bug )
- *
- * 1.1 (10/11/2000) David Iacovelli
- * Fix XON/XOFF flow control to support both IXON and IXOFF
- *
- * 0.9.27 (06/30/2000) David Iacovelli
- * Added transmit queue and now allocate urb for command writes.
- *
- * 0.9.26 (06/29/2000) David Iacovelli
- * Add support for 80251 based edgeport
- *
- * 0.9.25 (06/27/2000) David Iacovelli
- * Do not close the port if it has multiple opens.
- *
- * 0.9.24 (05/26/2000) David Iacovelli
- * Add IOCTLs to support RXTX and JAVA POS
- * and first cut at running BlackBox Demo
- *
- * 0.9.23 (05/24/2000) David Iacovelli
- * Add IOCTLs to support RXTX and JAVA POS
- *
- * 0.9.22 (05/23/2000) David Iacovelli
- * fixed bug in enumeration. If epconfig turns on mapping by
- * path after a device is already plugged in, we now update
- * the mapping correctly
- *
- * 0.9.21 (05/16/2000) David Iacovelli
- * Added BlockUntilChaseResp() to also wait for txcredits
- * Updated the way we allocate and handle write URBs
- * Add debug code to dump buffers
- *
- * 0.9.20 (05/01/2000) David Iacovelli
- * change driver to use usb/tts/
- *
- * 0.9.19 (05/01/2000) David Iacovelli
- * Update code to compile if DEBUG is off
- *
- * 0.9.18 (04/28/2000) David Iacovelli
- * cleanup and test tty_register with devfs
- *
- * 0.9.17 (04/27/2000) greg kroah-hartman
- * changed tty_register around to be like the way it
- * was before, but now it works properly with devfs.
- *
- * 0.9.16 (04/26/2000) david iacovelli
- * Fixed bug in GetProductInfo()
- *
- * 0.9.15 (04/25/2000) david iacovelli
- * Updated enumeration
- *
- * 0.9.14 (04/24/2000) david iacovelli
- * Removed all config/status IOCTLS and
- * converted to using /proc/edgeport
- * still playing with devfs
- *
- * 0.9.13 (04/24/2000) david iacovelli
- * Removed configuration based on ttyUSB0
- * Added support for configuration using /prod/edgeport
- * first attempt at using devfs (not working yet!)
- * Added IOCTL to GetProductInfo()
- * Added support for custom baud rates
- * Add support for random port numbers
- *
- * 0.9.12 (04/18/2000) david iacovelli
- * added additional configuration IOCTLs
- * use ttyUSB0 for configuration
- *
- * 0.9.11 (04/17/2000) greg kroah-hartman
- * fixed module initialization race conditions.
- * made all urbs dynamically allocated.
- * made driver devfs compatible. now it only registers the tty device
- * when the device is actually plugged in.
- *
- * 0.9.10 (04/13/2000) greg kroah-hartman
- * added proc interface framework.
- *
- * 0.9.9 (04/13/2000) david iacovelli
- * added enumeration code and ioctls to configure the device
- *
- * 0.9.8 (04/12/2000) david iacovelli
- * Change interrupt read start when device is plugged in
- * and stop when device is removed
- * process interrupt reads when all ports are closed
- * (keep value of rxBytesAvail consistent with the edgeport)
- * set the USB_BULK_QUEUE flag so that we can shove a bunch
- * of urbs at once down the pipe
- *
- * 0.9.7 (04/10/2000) david iacovelli
- * start to add enumeration code.
- * generate serial number for epic devices
- * add support for kdb
- *
- * 0.9.6 (03/30/2000) david iacovelli
- * add IOCTL to get string, manufacture, and boot descriptors
- *
- * 0.9.5 (03/14/2000) greg kroah-hartman
- * more error checking added to SerialOpen to try to fix UHCI open problem
- *
- * 0.9.4 (03/09/2000) greg kroah-hartman
- * added more error checking to handle oops when data is hanging
- * around and tty is abruptly closed.
- *
- * 0.9.3 (03/09/2000) david iacovelli
- * Add epic support for xon/xoff chars
- * play with performance
- *
- * 0.9.2 (03/08/2000) greg kroah-hartman
- * changed most "info" calls to "dbg"
- * implemented flow control properly in the termios call
- *
- * 0.9.1 (03/08/2000) david iacovelli
- * added EPIC support
- * enabled bootloader update
- *
- * 0.9 (03/08/2000) greg kroah-hartman
- * Release to IO networks.
- * Integrated changes that David made
- * made getting urbs for writing SMP safe
- *
- * 0.8 (03/07/2000) greg kroah-hartman
- * Release to IO networks.
- * Fixed problems that were seen in code by David.
- * Now both Edgeport/4 and Edgeport/2 works properly.
- * Changed most of the functions to use port instead of serial.
- *
- * 0.7 (02/27/2000) greg kroah-hartman
- * Milestone 3 release.
- * Release to IO Networks
- * ioctl for waiting on line change implemented.
- * ioctl for getting statistics implemented.
- * multiport support working.
- * lsr and msr registers are now handled properly.
- * change break now hooked up and working.
- * support for all known Edgeport devices.
- *
- * 0.6 (02/22/2000) greg kroah-hartman
- * Release to IO networks.
- * CHASE is implemented correctly when port is closed.
- * SerialOpen now blocks correctly until port is fully opened.
- *
- * 0.5 (02/20/2000) greg kroah-hartman
- * Release to IO networks.
- * Known problems:
- * modem status register changes are not sent on to the user
- * CHASE is not implemented when the port is closed.
- *
- * 0.4 (02/16/2000) greg kroah-hartman
- * Second cut at the CeBit demo.
- * Doesn't leak memory on every write to the port
- * Still small leaks on startup.
- * Added support for Edgeport/2 and Edgeport/8
- *
- * 0.3 (02/15/2000) greg kroah-hartman
- * CeBit demo release.
- * Force the line settings to 4800, 8, 1, e for the demo.
- * Warning! This version leaks memory like crazy!
- *
- * 0.2 (01/30/2000) greg kroah-hartman
- * Milestone 1 release.
- * Device is found by USB subsystem, enumerated, fimware is downloaded
- * and the descriptors are printed to the debug log, config is set, and
- * green light starts to blink. Open port works, and data can be sent
- * and received at the default settings of the UART. Loopback connector
- * and debug log confirms this.
- *
- * 0.1 (01/23/2000) greg kroah-hartman
- * Initial release to help IO Networks try to set up their test system.
- * Edgeport4 is recognized, firmware is downloaded, config is set so
- * device blinks green light every 3 sec. Port is bound, but opening,
- * closing, and sending data do not work properly.
- *
*/
#include <linux/config.h>
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index e7ffe02408bd..fad561c04c76 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -75,10 +75,12 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
-static struct usb_serial_device_type edgeport_2port_device = {
- .owner = THIS_MODULE,
- .name = "Edgeport 2 port adapter",
- .short_name = "edgeport_2",
+static struct usb_serial_driver edgeport_2port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "edgeport_2",
+ },
+ .description = "Edgeport 2 port adapter",
.id_table = edgeport_2port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -103,10 +105,12 @@ static struct usb_serial_device_type edgeport_2port_device = {
.write_bulk_callback = edge_bulk_out_data_callback,
};
-static struct usb_serial_device_type edgeport_4port_device = {
- .owner = THIS_MODULE,
- .name = "Edgeport 4 port adapter",
- .short_name = "edgeport_4",
+static struct usb_serial_driver edgeport_4port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "edgeport_4",
+ },
+ .description = "Edgeport 4 port adapter",
.id_table = edgeport_4port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -131,10 +135,12 @@ static struct usb_serial_device_type edgeport_4port_device = {
.write_bulk_callback = edge_bulk_out_data_callback,
};
-static struct usb_serial_device_type edgeport_8port_device = {
- .owner = THIS_MODULE,
- .name = "Edgeport 8 port adapter",
- .short_name = "edgeport_8",
+static struct usb_serial_driver edgeport_8port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "edgeport_8",
+ },
+ .description = "Edgeport 8 port adapter",
.id_table = edgeport_8port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ebf9967f7c86..832b6d6734c0 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2982,10 +2982,12 @@ static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
}
-static struct usb_serial_device_type edgeport_1port_device = {
- .owner = THIS_MODULE,
- .name = "Edgeport TI 1 port adapter",
- .short_name = "edgeport_ti_1",
+static struct usb_serial_driver edgeport_1port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "edgeport_ti_1",
+ },
+ .description = "Edgeport TI 1 port adapter",
.id_table = edgeport_1port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -3010,10 +3012,12 @@ static struct usb_serial_device_type edgeport_1port_device = {
.write_bulk_callback = edge_bulk_out_callback,
};
-static struct usb_serial_device_type edgeport_2port_device = {
- .owner = THIS_MODULE,
- .name = "Edgeport TI 2 port adapter",
- .short_name = "edgeport_ti_2",
+static struct usb_serial_driver edgeport_2port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "edgeport_ti_2",
+ },
+ .description = "Edgeport TI 2 port adapter",
.id_table = edgeport_2port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 2,
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index c05c2a2a0f31..d5d066488100 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -92,24 +92,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port);
static struct usb_device_id ipaq_id_table [] = {
/* The first entry is a placeholder for the insmod-specified device */
{ USB_DEVICE(0x049F, 0x0003) },
- { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
- { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
- { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
- { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
- { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
- { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
- { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
- { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
- { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
- { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
- { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
{ USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
{ USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
{ USB_DEVICE(0x03F0, 0x1216) }, /* HP USB Sync 1612 */
@@ -125,7 +108,13 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x03F0, 0x5016) }, /* HP USB Sync 1650 */
{ USB_DEVICE(0x03F0, 0x5116) }, /* HP USB Sync 1651 */
{ USB_DEVICE(0x03F0, 0x5216) }, /* HP USB Sync 1652 */
- { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+ { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
+ { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
+ { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
+ { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
+ { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
+ { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
+ { USB_DEVICE(0x045E, 0x00CE) }, /* Microsoft USB Sync */
{ USB_DEVICE(0x045E, 0x0400) }, /* Windows Powered Pocket PC 2002 */
{ USB_DEVICE(0x045E, 0x0401) }, /* Windows Powered Pocket PC 2002 */
{ USB_DEVICE(0x045E, 0x0402) }, /* Windows Powered Pocket PC 2002 */
@@ -251,17 +240,81 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x045E, 0x04E8) }, /* Windows Powered Smartphone 2003 */
{ USB_DEVICE(0x045E, 0x04E9) }, /* Windows Powered Smartphone 2003 */
{ USB_DEVICE(0x045E, 0x04EA) }, /* Windows Powered Smartphone 2003 */
- { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
- { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
- { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
+ { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
+ { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
+ { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
+ { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
+ { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
+ { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+ { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
+ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
+ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
+ { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
+ { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
+ { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
+ { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
+ { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
+ { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
+ { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
+ { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
+ { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
+ { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
+ { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
+ { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
+ { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
+ { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
+ { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
+ { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
+ { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
+ { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
+ { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
+ { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
+ { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
+ { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
+ { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
+ { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
+ { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
+ { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
+ { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
+ { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
+ { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
+ { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
+ { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
+ { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
+ { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
+ { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
+ { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
+ { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
{ USB_DEVICE(0x0930, 0x0700) }, /* TOSHIBA USB Sync 0700 */
{ USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */
+ { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
{ USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */
{ USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */
- { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
{ USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */
{ USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */
{ USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */
+ { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+ { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
+ { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
+ { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
+ { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
+ { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
+ { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
+ { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
{ USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */
{ USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */
{ USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */
@@ -422,116 +475,67 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */
{ USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */
{ USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */
- { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
- { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
- { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
- { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
- { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
- { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
{ USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
- { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
- { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
- { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
- { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
- { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
- { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
- { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
- { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
- { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
- { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
- { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
- { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
+ { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
{ USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
- { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
- { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
- { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+ { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
+ { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
+ { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
+ { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
+ { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */
+ { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */
+ { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */
+ { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
{ USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */
{ USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */
{ USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */
{ USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */
- { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
- { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
- { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
- { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
- { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
- { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
- { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
- { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
- { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
- { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
- { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
- { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
- { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
- { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
- { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
- { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
- { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
+ { USB_DEVICE(0x1114, 0x0001) }, /* Psion Teklogix Sync 753x */
+ { USB_DEVICE(0x1114, 0x0004) }, /* Psion Teklogix Sync netBookPro */
+ { USB_DEVICE(0x1114, 0x0006) }, /* Psion Teklogix Sync 7525 */
+ { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
+ { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
+ { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
+ { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
+ { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+ { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
+ { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */
+ { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */
+ { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */
+ { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */
+ { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */
+ { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
{ USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */
{ USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */
- { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
- { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
{ USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */
- { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
{ USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */
- { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
+ { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
+ { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
+ { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
+ { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
+ { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
+ { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
+ { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
{ USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */
+ { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
+ { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
+ { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
+ { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
{ USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */
{ USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */
{ USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */
{ USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */
- { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
- { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
- { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
- { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
- { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
- { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
- { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
- { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
- { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
+ { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
+ { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
- { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
- { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
- { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
- { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
- { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
- { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
- { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
- { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
- { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
- { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
- { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
- { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
- { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
- { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
- { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
- { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
- { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
- { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
- { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
- { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
- { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
- { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
- { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
- { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
- { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */
- { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */
- { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */
- { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
- { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
- { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */
- { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */
- { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */
- { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */
- { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */
- { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
- { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+ { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
{ } /* Terminating entry */
};
@@ -547,9 +551,12 @@ static struct usb_driver ipaq_driver = {
/* All of the device info needed for the Compaq iPAQ */
-static struct usb_serial_device_type ipaq_device = {
- .owner = THIS_MODULE,
- .name = "PocketPC PDA",
+static struct usb_serial_driver ipaq_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ipaq",
+ },
+ .description = "PocketPC PDA",
.id_table = ipaq_id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 85e242459c27..a02fada85362 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -443,10 +443,12 @@ static int ipw_disconnect(struct usb_serial_port *port)
return 0;
}
-static struct usb_serial_device_type ipw_device = {
- .owner = THIS_MODULE,
- .name = "IPWireless converter",
- .short_name = "ipw",
+static struct usb_serial_driver ipw_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ipw",
+ },
+ .description = "IPWireless converter",
.id_table = usb_ipw_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 937b2fdd7171..19f329e9bdcf 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -133,9 +133,12 @@ static struct usb_driver ir_driver = {
};
-static struct usb_serial_device_type ir_device = {
- .owner = THIS_MODULE,
- .name = "IR Dongle",
+static struct usb_serial_driver ir_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ir-usb",
+ },
+ .description = "IR Dongle",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index fb0926292228..3b958e60f5e8 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -383,11 +383,8 @@ static int keyspan_write(struct usb_serial_port *port,
dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) {
- if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
- break;
if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
break;
- this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb);
break;
}
@@ -402,7 +399,6 @@ static int keyspan_write(struct usb_serial_port *port,
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo + dataOffset;
- this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)", err);
@@ -1119,10 +1115,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
static inline void stop_urb(struct urb *urb)
{
- if (urb && urb->status == -EINPROGRESS) {
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ if (urb && urb->status == -EINPROGRESS)
usb_kill_urb(urb);
- }
}
static void keyspan_close(struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index e9b45b768aca..5cfc13b5e56f 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -570,10 +570,12 @@ static struct usb_device_id keyspan_4port_ids[] = {
};
/* Structs for the devices, pre and post renumeration. */
-static struct usb_serial_device_type keyspan_pre_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan - (without firmware)",
- .short_name = "keyspan_no_firm",
+static struct usb_serial_driver keyspan_pre_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_no_firm",
+ },
+ .description = "Keyspan - (without firmware)",
.id_table = keyspan_pre_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -582,10 +584,12 @@ static struct usb_serial_device_type keyspan_pre_device = {
.attach = keyspan_fake_startup,
};
-static struct usb_serial_device_type keyspan_1port_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan 1 port adapter",
- .short_name = "keyspan_1",
+static struct usb_serial_driver keyspan_1port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_1",
+ },
+ .description = "Keyspan 1 port adapter",
.id_table = keyspan_1port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -607,10 +611,12 @@ static struct usb_serial_device_type keyspan_1port_device = {
.shutdown = keyspan_shutdown,
};
-static struct usb_serial_device_type keyspan_2port_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan 2 port adapter",
- .short_name = "keyspan_2",
+static struct usb_serial_driver keyspan_2port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_2",
+ },
+ .description = "Keyspan 2 port adapter",
.id_table = keyspan_2port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -632,10 +638,12 @@ static struct usb_serial_device_type keyspan_2port_device = {
.shutdown = keyspan_shutdown,
};
-static struct usb_serial_device_type keyspan_4port_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan 4 port adapter",
- .short_name = "keyspan_4",
+static struct usb_serial_driver keyspan_4port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_4",
+ },
+ .description = "Keyspan 4 port adapter",
.id_table = keyspan_4port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 5,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 635c384cb15a..cd4f48bd83b6 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -783,10 +783,12 @@ static void keyspan_pda_shutdown (struct usb_serial *serial)
}
#ifdef KEYSPAN
-static struct usb_serial_device_type keyspan_pda_fake_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan PDA - (prerenumeration)",
- .short_name = "keyspan_pda_pre",
+static struct usb_serial_driver keyspan_pda_fake_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_pda_pre",
+ },
+ .description = "Keyspan PDA - (prerenumeration)",
.id_table = id_table_fake,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -797,10 +799,12 @@ static struct usb_serial_device_type keyspan_pda_fake_device = {
#endif
#ifdef XIRCOM
-static struct usb_serial_device_type xircom_pgs_fake_device = {
- .owner = THIS_MODULE,
- .name = "Xircom / Entregra PGS - (prerenumeration)",
- .short_name = "xircom_no_firm",
+static struct usb_serial_driver xircom_pgs_fake_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "xircom_no_firm",
+ },
+ .description = "Xircom / Entregra PGS - (prerenumeration)",
.id_table = id_table_fake_xircom,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -810,10 +814,12 @@ static struct usb_serial_device_type xircom_pgs_fake_device = {
};
#endif
-static struct usb_serial_device_type keyspan_pda_device = {
- .owner = THIS_MODULE,
- .name = "Keyspan PDA",
- .short_name = "keyspan_pda",
+static struct usb_serial_driver keyspan_pda_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "keyspan_pda",
+ },
+ .description = "Keyspan PDA",
.id_table = id_table_std,
.num_interrupt_in = 1,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index a11e829e38c8..a8951c0fd020 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -123,10 +123,12 @@ static struct usb_driver kl5kusb105d_driver = {
.id_table = id_table,
};
-static struct usb_serial_device_type kl5kusb105d_device = {
- .owner = THIS_MODULE,
- .name = "KL5KUSB105D / PalmConnect",
- .short_name = "kl5kusb105d",
+static struct usb_serial_driver kl5kusb105d_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "kl5kusb105d",
+ },
+ .description = "KL5KUSB105D / PalmConnect",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index fe4c98a75171..9456dd9dd136 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -105,9 +105,12 @@ static struct usb_driver kobil_driver = {
};
-static struct usb_serial_device_type kobil_device = {
- .owner = THIS_MODULE,
- .name = "KOBIL USB smart card terminal",
+static struct usb_serial_driver kobil_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "kobil",
+ },
+ .description = "KOBIL USB smart card terminal",
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 50b6369647d2..ca5dbadb9b7e 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -132,10 +132,12 @@ static struct usb_driver mct_u232_driver = {
.id_table = id_table_combined,
};
-static struct usb_serial_device_type mct_u232_device = {
- .owner = THIS_MODULE,
- .name = "MCT U232",
- .short_name = "mct_u232",
+static struct usb_serial_driver mct_u232_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mct_u232",
+ },
+ .description = "MCT U232",
.id_table = id_table_combined,
.num_interrupt_in = 2,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/nokia_dku2.c b/drivers/usb/serial/nokia_dku2.c
new file mode 100644
index 000000000000..fad01bef3a64
--- /dev/null
+++ b/drivers/usb/serial/nokia_dku2.c
@@ -0,0 +1,142 @@
+/*
+ * Nokia DKU2 USB driver
+ *
+ * Copyright (C) 2004
+ * Author: C Kemp
+ *
+ * This program is largely derived from work by the linux-usb group
+ * and associated source files. Please see the usb/serial files for
+ * individual credits and copyrights.
+ *
+ * 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.
+ *
+ * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ * Added short name to device structure to make driver load into kernel 2.6.13
+ *
+ * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ * Added usb_deregister to exit code - to allow remove and reinsert of module
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+
+#define NOKIA_VENDOR_ID 0x0421
+#define NOKIA7600_PRODUCT_ID 0x0400
+#define NOKIA6230_PRODUCT_ID 0x040f
+#define NOKIA6170_PRODUCT_ID 0x0416
+#define NOKIA6670_PRODUCT_ID 0x041d
+#define NOKIA6680_PRODUCT_ID 0x041e
+#define NOKIA6230i_PRODUCT_ID 0x0428
+
+#define NOKIA_AT_PORT 0x82
+#define NOKIA_FBUS_PORT 0x86
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.2"
+#define DRIVER_AUTHOR "C Kemp"
+#define DRIVER_DESC "Nokia DKU2 Driver"
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA7600_PRODUCT_ID) },
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230_PRODUCT_ID) },
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6170_PRODUCT_ID) },
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6670_PRODUCT_ID) },
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6680_PRODUCT_ID) },
+ { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230i_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* The only thing which makes this device different from a generic
+ * device is that we have to set an alternative configuration to make
+ * the relevant endpoints available. In 2.6 this is really easy... */
+static int nokia_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ int retval = -ENODEV;
+
+ if (serial->interface->altsetting[0].endpoint[0].desc.bEndpointAddress == NOKIA_AT_PORT) {
+ /* the AT port */
+ dev_info(&serial->dev->dev, "Nokia AT Port:\n");
+ retval = 0;
+ } else if (serial->interface->num_altsetting == 2 &&
+ serial->interface->altsetting[1].endpoint[0].desc.bEndpointAddress == NOKIA_FBUS_PORT) {
+ /* the FBUS port */
+ dev_info(&serial->dev->dev, "Nokia FBUS Port:\n");
+ usb_set_interface(serial->dev, 10, 1);
+ retval = 0;
+ }
+
+ return retval;
+}
+
+static struct usb_driver nokia_driver = {
+ .owner = THIS_MODULE,
+ .name = "nokia_dku2",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+};
+
+static struct usb_serial_driver nokia_serial_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "nokia_dku2",
+ },
+ .description = "Nokia 7600/6230(i)/6170/66x0 DKU2 driver",
+ .id_table = id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .probe = nokia_probe,
+};
+
+static int __init nokia_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&nokia_serial_driver);
+ if (retval)
+ return retval;
+
+ retval = usb_register(&nokia_driver);
+ if (retval) {
+ usb_serial_deregister(&nokia_serial_driver);
+ return retval;
+ }
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
+ return retval;
+}
+
+static void __exit nokia_exit(void)
+{
+ usb_deregister(&nokia_driver);
+ usb_serial_deregister(&nokia_serial_driver);
+}
+
+module_init(nokia_init);
+module_exit(nokia_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 6a99ae192df1..3caf97072ac0 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -88,10 +88,12 @@ static struct usb_driver omninet_driver = {
};
-static struct usb_serial_device_type zyxel_omninet_device = {
- .owner = THIS_MODULE,
- .name = "ZyXEL - omni.net lcd plus usb",
- .short_name = "omninet",
+static struct usb_serial_driver zyxel_omninet_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "omninet",
+ },
+ .description = "ZyXEL - omni.net lcd plus usb",
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e9256408757f..7716000045b7 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -25,6 +25,9 @@
2005-06-20 v0.4.1 add missing braces :-/
killed end-of-line whitespace
2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2
+ 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
+ 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
+ wants to send >2000 bytes.
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
@@ -45,42 +48,47 @@
#include "usb-serial.h"
/* Function prototypes */
-static int option_open (struct usb_serial_port *port, struct file *filp);
-static void option_close (struct usb_serial_port *port, struct file *filp);
-static int option_startup (struct usb_serial *serial);
-static void option_shutdown (struct usb_serial *serial);
-static void option_rx_throttle (struct usb_serial_port *port);
-static void option_rx_unthrottle (struct usb_serial_port *port);
-static int option_write_room (struct usb_serial_port *port);
+static int option_open(struct usb_serial_port *port, struct file *filp);
+static void option_close(struct usb_serial_port *port, struct file *filp);
+static int option_startup(struct usb_serial *serial);
+static void option_shutdown(struct usb_serial *serial);
+static void option_rx_throttle(struct usb_serial_port *port);
+static void option_rx_unthrottle(struct usb_serial_port *port);
+static int option_write_room(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
-static int option_write (struct usb_serial_port *port,
- const unsigned char *buf, int count);
+static int option_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
-static int option_chars_in_buffer (struct usb_serial_port *port);
-static int option_ioctl (struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static void option_set_termios (struct usb_serial_port *port,
- struct termios *old);
-static void option_break_ctl (struct usb_serial_port *port, int break_state);
-static int option_tiocmget (struct usb_serial_port *port, struct file *file);
-static int option_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear);
-static int option_send_setup (struct usb_serial_port *port);
+static int option_chars_in_buffer(struct usb_serial_port *port);
+static int option_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void option_set_termios(struct usb_serial_port *port,
+ struct termios *old);
+static void option_break_ctl(struct usb_serial_port *port, int break_state);
+static int option_tiocmget(struct usb_serial_port *port, struct file *file);
+static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
+static int option_send_setup(struct usb_serial_port *port);
/* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0
+#define HUAWEI_VENDOR_ID 0x12D1
+#define AUDIOVOX_VENDOR_ID 0x0F3D
#define OPTION_PRODUCT_OLD 0x5000
#define OPTION_PRODUCT_FUSION 0x6000
#define OPTION_PRODUCT_FUSION2 0x6300
-
+#define HUAWEI_PRODUCT_E600 0x1001
+#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ } /* Terminating entry */
};
@@ -97,10 +105,12 @@ static struct usb_driver option_driver = {
/* The card has three separate interfaces, wich the serial driver
* recognizes separately, thus num_port=1.
*/
-static struct usb_serial_device_type option_3port_device = {
- .owner = THIS_MODULE,
- .name = "Option 3G data card",
- .short_name = "option",
+static struct usb_serial_driver option_3port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "option",
+ },
+ .description = "Option 3G data card",
.id_table = option_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -129,12 +139,11 @@ static int debug;
#define debug 0
#endif
-
/* per port private data */
#define N_IN_URB 4
#define N_OUT_URB 1
-#define IN_BUFLEN 1024
+#define IN_BUFLEN 4096
#define OUT_BUFLEN 128
struct option_port_private {
@@ -156,10 +165,8 @@ struct option_port_private {
unsigned long tx_start_time[N_OUT_URB];
};
-
/* Functions used by new usb-serial code. */
-static int __init
-option_init (void)
+static int __init option_init(void)
{
int retval;
retval = usb_serial_register(&option_3port_device);
@@ -179,8 +186,7 @@ failed_3port_device_register:
return retval;
}
-static void __exit
-option_exit (void)
+static void __exit option_exit(void)
{
usb_deregister (&option_driver);
usb_serial_deregister (&option_3port_device);
@@ -189,39 +195,31 @@ option_exit (void)
module_init(option_init);
module_exit(option_exit);
-static void
-option_rx_throttle (struct usb_serial_port *port)
+static void option_rx_throttle(struct usb_serial_port *port)
{
dbg("%s", __FUNCTION__);
}
-
-static void
-option_rx_unthrottle (struct usb_serial_port *port)
+static void option_rx_unthrottle(struct usb_serial_port *port)
{
dbg("%s", __FUNCTION__);
}
-
-static void
-option_break_ctl (struct usb_serial_port *port, int break_state)
+static void option_break_ctl(struct usb_serial_port *port, int break_state)
{
/* Unfortunately, I don't know how to send a break */
dbg("%s", __FUNCTION__);
}
-
-static void
-option_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+static void option_set_termios(struct usb_serial_port *port,
+ struct termios *old_termios)
{
dbg("%s", __FUNCTION__);
option_send_setup(port);
}
-static int
-option_tiocmget (struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct usb_serial_port *port, struct file *file)
{
unsigned int value;
struct option_port_private *portdata;
@@ -238,9 +236,8 @@ option_tiocmget (struct usb_serial_port *port, struct file *file)
return value;
}
-static int
-option_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear)
+static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
{
struct option_port_private *portdata;
@@ -258,17 +255,15 @@ option_tiocmset (struct usb_serial_port *port, struct file *file,
return option_send_setup(port);
}
-static int
-option_ioctl (struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int option_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
}
/* Write */
-static int
-option_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int option_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct option_port_private *portdata;
int i;
@@ -289,28 +284,29 @@ option_write (struct usb_serial_port *port,
this_urb = portdata->out_urbs[i];
if (this_urb->status == -EINPROGRESS) {
- if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
- continue;
- if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
+ if (time_before(jiffies,
+ portdata->tx_start_time[i] + 10 * HZ))
continue;
- this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb);
continue;
}
if (this_urb->status != 0)
- dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status);
+ dbg("usb_write %p failed (err=%d)",
+ this_urb, this_urb->status);
- dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
+ dbg("%s: endpoint %d buf %d", __FUNCTION__,
+ usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
memcpy (this_urb->transfer_buffer, buf, todo);
this_urb->transfer_buffer_length = todo;
- this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err) {
- dbg("usb_submit_urb %p (write bulk) failed (%d, has %d)", this_urb, err, this_urb->status);
+ dbg("usb_submit_urb %p (write bulk) failed "
+ "(%d, has %d)", this_urb,
+ err, this_urb->status);
continue;
}
portdata->tx_start_time[i] = jiffies;
@@ -323,8 +319,7 @@ option_write (struct usb_serial_port *port,
return count;
}
-static void
-option_indat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
{
int i, err;
int endpoint;
@@ -357,14 +352,14 @@ option_indat_callback (struct urb *urb, struct pt_regs *regs)
if (port->open_count && urb->status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err);
+ printk(KERN_ERR "%s: resubmit read urb failed. "
+ "(%d)", __FUNCTION__, err);
}
}
return;
}
-static void
-option_outdat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port;
@@ -376,8 +371,7 @@ option_outdat_callback (struct urb *urb, struct pt_regs *regs)
schedule_work(&port->work);
}
-static void
-option_instat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
{
int err;
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
@@ -395,10 +389,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
dbg("%s: NULL req_pkt\n", __FUNCTION__);
return;
}
- if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) {
+ if ((req_pkt->bRequestType == 0xA1) &&
+ (req_pkt->bRequest == 0x20)) {
int old_dcd_state;
unsigned char signals = *((unsigned char *)
- urb->transfer_buffer + sizeof(struct usb_ctrlrequest));
+ urb->transfer_buffer +
+ sizeof(struct usb_ctrlrequest));
dbg("%s: signal x%x", __FUNCTION__, signals);
@@ -408,12 +404,13 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
- && old_dcd_state && !portdata->dcd_state) {
+ if (port->tty && !C_CLOCAL(port->tty) &&
+ old_dcd_state && !portdata->dcd_state)
tty_hangup(port->tty);
- }
- } else
- dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest);
+ } else {
+ dbg("%s: type %x req %x", __FUNCTION__,
+ req_pkt->bRequestType,req_pkt->bRequest);
+ }
} else
dbg("%s: error %d", __FUNCTION__, urb->status);
@@ -422,13 +419,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err);
+ dbg("%s: resubmit intr urb failed. (%d)",
+ __FUNCTION__, err);
}
}
-
-static int
-option_write_room (struct usb_serial_port *port)
+static int option_write_room(struct usb_serial_port *port)
{
struct option_port_private *portdata;
int i;
@@ -447,9 +443,7 @@ option_write_room (struct usb_serial_port *port)
return data_len;
}
-
-static int
-option_chars_in_buffer (struct usb_serial_port *port)
+static int option_chars_in_buffer(struct usb_serial_port *port)
{
struct option_port_private *portdata;
int i;
@@ -467,9 +461,7 @@ option_chars_in_buffer (struct usb_serial_port *port)
return data_len;
}
-
-static int
-option_open (struct usb_serial_port *port, struct file *filp)
+static int option_open(struct usb_serial_port *port, struct file *filp)
{
struct option_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -490,17 +482,21 @@ option_open (struct usb_serial_port *port, struct file *filp)
if (! urb)
continue;
if (urb->dev != serial->dev) {
- dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev);
+ dbg("%s: dev %p != %p", __FUNCTION__,
+ urb->dev, serial->dev);
continue;
}
- /* make sure endpoint data toggle is synchronized with the device */
-
+ /*
+ * make sure endpoint data toggle is synchronized with the
+ * device
+ */
usb_clear_halt(urb->dev, urb->pipe);
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
- dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err,
+ dbg("%s: submit urb %d failed (%d) %d",
+ __FUNCTION__, i, err,
urb->transfer_buffer_length);
}
}
@@ -511,7 +507,8 @@ option_open (struct usb_serial_port *port, struct file *filp)
if (! urb)
continue;
urb->dev = serial->dev;
- /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), 0); */
}
port->tty->low_latency = 1;
@@ -521,17 +518,13 @@ option_open (struct usb_serial_port *port, struct file *filp)
return (0);
}
-static inline void
-stop_urb (struct urb *urb)
+static inline void stop_urb(struct urb *urb)
{
- if (urb && urb->status == -EINPROGRESS) {
- urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ if (urb && urb->status == -EINPROGRESS)
usb_kill_urb(urb);
- }
}
-static void
-option_close (struct usb_serial_port *port, struct file *filp)
+static void option_close(struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -555,12 +548,10 @@ option_close (struct usb_serial_port *port, struct file *filp)
port->tty = NULL;
}
-
/* Helper functions used by option_setup_urbs */
-static struct urb *
-option_setup_urb (struct usb_serial *serial, int endpoint,
- int dir, void *ctx, char *buf, int len,
- void (*callback)(struct urb *, struct pt_regs *regs))
+static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+ int dir, void *ctx, char *buf, int len,
+ void (*callback)(struct urb *, struct pt_regs *regs))
{
struct urb *urb;
@@ -582,8 +573,7 @@ option_setup_urb (struct usb_serial *serial, int endpoint,
}
/* Setup urbs */
-static void
-option_setup_urbs (struct usb_serial *serial)
+static void option_setup_urbs(struct usb_serial *serial)
{
int j;
struct usb_serial_port *port;
@@ -609,9 +599,7 @@ option_setup_urbs (struct usb_serial *serial)
}
}
-
-static int
-option_send_setup (struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
@@ -627,16 +615,15 @@ option_send_setup (struct usb_serial_port *port)
if (portdata->rts_state)
val |= 0x02;
- return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
}
return 0;
}
-
-static int
-option_startup (struct usb_serial *serial)
+static int option_startup(struct usb_serial *serial)
{
int i, err;
struct usb_serial_port *port;
@@ -647,9 +634,10 @@ option_startup (struct usb_serial *serial)
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL);
+ portdata = kmalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
- dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i);
+ dbg("%s: kmalloc for option_port_private (%d) failed!.",
+ __FUNCTION__, i);
return (1);
}
memset(portdata, 0, sizeof(struct option_port_private));
@@ -660,7 +648,8 @@ option_startup (struct usb_serial *serial)
continue;
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
- dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err);
+ dbg("%s: submit irq_in urb failed %d",
+ __FUNCTION__, err);
}
option_setup_urbs(serial);
@@ -668,8 +657,7 @@ option_startup (struct usb_serial *serial)
return (0);
}
-static void
-option_shutdown (struct usb_serial *serial)
+static void option_shutdown(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 7eab5d4cf3a8..165c119bf10e 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -8,31 +8,10 @@
*
* 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 Free Software Foundation; either version 2 of the License.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
- * 2002_Mar_26 gkh
- * allowed driver to work properly if there is no tty assigned to a port
- * (this happens for serial console devices.)
- *
- * 2001_Oct_06 gkh
- * Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it.
- *
- * 2001_Sep_19 gkh
- * Added break support.
- *
- * 2001_Aug_30 gkh
- * fixed oops in write_bulk_callback.
- *
- * 2001_Aug_28 gkh
- * reworked buffer logic to be like other usb-serial drivers. Hopefully
- * removing some reported problems.
- *
- * 2001_Jun_06 gkh
- * finished porting to 2.4 format.
- *
*/
#include <linux/config.h>
@@ -55,7 +34,6 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.12"
#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
static int debug;
@@ -95,6 +73,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
+ { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
{ } /* Terminating entry */
};
@@ -174,9 +153,11 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
/* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_device_type pl2303_device = {
- .owner = THIS_MODULE,
- .name = "PL-2303",
+static struct usb_serial_driver pl2303_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "pl2303",
+ },
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
@@ -538,8 +519,10 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- usb_clear_halt(serial->dev, port->write_urb->pipe);
- usb_clear_halt(serial->dev, port->read_urb->pipe);
+ if (priv->type != HX) {
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+ }
buf = kmalloc(10, GFP_KERNEL);
if (buf==NULL)
@@ -650,8 +633,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
timeout = max((HZ*2560)/bps,HZ/10);
else
timeout = 2*HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout);
+ schedule_timeout_interruptible(timeout);
/* shutdown our urbs */
dbg("%s - shutting down urbs", __FUNCTION__);
@@ -1193,7 +1175,7 @@ static int __init pl2303_init (void)
retval = usb_register(&pl2303_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ info(DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&pl2303_device);
@@ -1213,7 +1195,6 @@ module_init(pl2303_init);
module_exit(pl2303_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index b734c4003c5a..7be9644f5a03 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -58,3 +58,7 @@
#define SYNTECH_VENDOR_ID 0x0745
#define SYNTECH_PRODUCT_ID 0x0001
+
+/* Nokia CA-42 Cable */
+#define NOKIA_CA42_VENDOR_ID 0x078b
+#define NOKIA_CA42_PRODUCT_ID 0x1234
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 96a17568cbf1..c22bdc0c4dfd 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -92,7 +92,7 @@ MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE("GPL");
#if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT)
-#abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
+#error "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
#endif
#if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR)
@@ -397,9 +397,11 @@ static int safe_startup (struct usb_serial *serial)
return 0;
}
-static struct usb_serial_device_type safe_device = {
- .owner = THIS_MODULE,
- .name = "Safe",
+static struct usb_serial_driver safe_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "safe_serial",
+ },
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 59c88de3e7ae..205dbf7201da 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -255,9 +255,12 @@ static struct usb_driver ti_usb_driver = {
.id_table = ti_id_table_combined,
};
-static struct usb_serial_device_type ti_1port_device = {
- .owner = THIS_MODULE,
- .name = "TI USB 3410 1 port adapter",
+static struct usb_serial_driver ti_1port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ti_usb_3410_5052_1",
+ },
+ .description = "TI USB 3410 1 port adapter",
.id_table = ti_id_table_3410,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -282,9 +285,12 @@ static struct usb_serial_device_type ti_1port_device = {
.write_bulk_callback = ti_bulk_out_callback,
};
-static struct usb_serial_device_type ti_2port_device = {
- .owner = THIS_MODULE,
- .name = "TI USB 5052 2 port adapter",
+static struct usb_serial_driver ti_2port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ti_usb_3410_5052_2",
+ },
+ .description = "TI USB 5052 2 port adapter",
.id_table = ti_id_table_5052,
.num_interrupt_in = 1,
.num_bulk_in = 2,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0267b26dde18..0c4881d18cd5 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,7 +1,7 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999 - 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2000 Peter Berger (pberger@brimson.com)
* Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
*
@@ -9,316 +9,11 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * This driver was originally based on the ACM driver by Armin Fuerst (which was
+ * This driver was originally based on the ACM driver by Armin Fuerst (which was
* based on a driver by Brad Keryan)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
- * (12/10/2002) gkh
- * Split the ports off into their own struct device, and added a
- * usb-serial bus driver.
- *
- * (11/19/2002) gkh
- * removed a few #ifdefs for the generic code and cleaned up the failure
- * logic in initialization.
- *
- * (10/02/2002) gkh
- * moved the console code to console.c and out of this file.
- *
- * (06/05/2002) gkh
- * moved location of startup() call in serial_probe() until after all
- * of the port information and endpoints are initialized. This makes
- * things easier for some drivers.
- *
- * (04/10/2002) gkh
- * added serial_read_proc function which creates a
- * /proc/tty/driver/usb-serial file.
- *
- * (03/27/2002) gkh
- * Got USB serial console code working properly and merged into the main
- * version of the tree. Thanks to Randy Dunlap for the initial version
- * of this code, and for pushing me to finish it up.
- * The USB serial console works with any usb serial driver device.
- *
- * (03/21/2002) gkh
- * Moved all manipulation of port->open_count into the core. Now the
- * individual driver's open and close functions are called only when the
- * first open() and last close() is called. Making the drivers a bit
- * smaller and simpler.
- * Fixed a bug if a driver didn't have the owner field set.
- *
- * (02/26/2002) gkh
- * Moved all locking into the main serial_* functions, instead of having
- * the individual drivers have to grab the port semaphore. This should
- * reduce races.
- * Reworked the MOD_INC logic a bit to always increment and decrement, even
- * if the generic driver is being used.
- *
- * (10/10/2001) gkh
- * usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
- * help prevent child drivers from accessing the device since it is now
- * gone.
- *
- * (09/13/2001) gkh
- * Moved generic driver initialize after we have registered with the USB
- * core. Thanks to Randy Dunlap for pointing this problem out.
- *
- * (07/03/2001) gkh
- * Fixed module paramater size. Thanks to John Brockmeyer for the pointer.
- * Fixed vendor and product getting defined through the MODULE_PARM macro
- * if the Generic driver wasn't compiled in.
- * Fixed problem with generic_shutdown() not being called for drivers that
- * don't have a shutdown() function.
- *
- * (06/06/2001) gkh
- * added evil hack that is needed for the prolific pl2303 device due to the
- * crazy way its endpoints are set up.
- *
- * (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * 2001_02_05 gkh
- * Fixed buffer overflows bug with the generic serial driver. Thanks to
- * Todd Squires <squirest@ct0.com> for fixing this.
- *
- * (01/10/2001) gkh
- * Fixed bug where the generic serial adaptor grabbed _any_ device that was
- * offered to it.
- *
- * (12/12/2000) gkh
- * Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
- * moved them to the serial_open and serial_close functions.
- * Also fixed bug with there not being a MOD_DEC for the generic driver
- * (thanks to Gary Brubaker for finding this.)
- *
- * (11/29/2000) gkh
- * Small NULL pointer initialization cleanup which saves a bit of disk image
- *
- * (11/01/2000) Adam J. Richter
- * instead of using idVendor/idProduct pairs, usb serial drivers
- * now identify their hardware interest with usb_device_id tables,
- * which they usually have anyhow for use with MODULE_DEVICE_TABLE.
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (09/11/2000) gkh
- * Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (08/28/2000) gkh
- * Added port_lock to port structure.
- * Added locks for SMP safeness to generic driver
- * Fixed the ability to open a generic device's port more than once.
- *
- * (07/23/2000) gkh
- * Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- * Modifications to allow usb-serial drivers to be modules.
- *
- * (07/03/2000) gkh
- * Added more debugging to serial_ioctl call
- *
- * (06/25/2000) gkh
- * Changed generic_write_bulk_callback to not call wake_up_interruptible
- * directly, but to have port_softint do it at a safer time.
- *
- * (06/23/2000) gkh
- * Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (05/22/2000) gkh
- * Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
- * removed from the individual device source files.
- *
- * (05/03/2000) gkh
- * Added the Digi Acceleport driver from Al Borchers and Peter Berger.
- *
- * (05/02/2000) gkh
- * Changed devfs and tty register code to work properly now. This was based on
- * the ACM driver changes by Vojtech Pavlik.
- *
- * (04/27/2000) Ryan VanderBijl
- * Put calls to *_paranoia_checks into one function.
- *
- * (04/23/2000) gkh
- * Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
- * Moved when the startup code printed out the devices that are supported.
- *
- * (04/19/2000) gkh
- * Added driver for ZyXEL omni.net lcd plus ISDN TA
- * Made startup info message specify which drivers were compiled in.
- *
- * (04/03/2000) gkh
- * Changed the probe process to remove the module unload races.
- * Changed where the tty layer gets initialized to have devfs work nicer.
- * Added initial devfs support.
- *
- * (03/26/2000) gkh
- * Split driver up into device specific pieces.
- *
- * (03/19/2000) gkh
- * Fixed oops that could happen when device was removed while a program
- * was talking to the device.
- * Removed the static urbs and now all urbs are created and destroyed
- * dynamically.
- * Reworked the internal interface. Now everything is based on the
- * usb_serial_port structure instead of the larger usb_serial structure.
- * This fixes the bug that a multiport device could not have more than
- * one port open at one time.
- *
- * (03/17/2000) gkh
- * Added config option for debugging messages.
- * Added patch for keyspan pda from Brian Warner.
- *
- * (03/06/2000) gkh
- * Added the keyspan pda code from Brian Warner <warner@lothar.com>
- * Moved a bunch of the port specific stuff into its own structure. This
- * is in anticipation of the true multiport devices (there's a bug if you
- * try to access more than one port of any multiport device right now)
- *
- * (02/21/2000) gkh
- * Made it so that any serial devices only have to specify which functions
- * they want to overload from the generic function calls (great,
- * inheritance in C, in a driver, just what I wanted...)
- * Added support for set_termios and ioctl function calls. No drivers take
- * advantage of this yet.
- * Removed the #ifdef MODULE, now there is no module specific code.
- * Cleaned up a few comments in usb-serial.h that were wrong (thanks again
- * to Miles Lott).
- * Small fix to get_free_serial.
- *
- * (02/14/2000) gkh
- * Removed the Belkin and Peracom functionality from the driver due to
- * the lack of support from the vendor, and me not wanting people to
- * accidenatly buy the device, expecting it to work with Linux.
- * Added read_bulk_callback and write_bulk_callback to the type structure
- * for the needs of the FTDI and WhiteHEAT driver.
- * Changed all reverences to FTDI to FTDI_SIO at the request of Bill
- * Ryder.
- * Changed the output urb size back to the max endpoint size to make
- * the ftdi_sio driver have it easier, and due to the fact that it didn't
- * really increase the speed any.
- *
- * (02/11/2000) gkh
- * Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
- * patch from Miles Lott (milos@insync.net).
- * Fixed bug with not restoring the minor range that a device grabs, if
- * the startup function fails (thanks Miles for finding this).
- *
- * (02/05/2000) gkh
- * Added initial framework for the Keyspan PDA serial converter so that
- * Brian Warner has a place to put his code.
- * Made the ezusb specific functions generic enough that different
- * devices can use them (whiteheat and keyspan_pda both need them).
- * Split out a whole bunch of structure and other stuff to a separate
- * usb-serial.h file.
- * Made the Visor connection messages a little more understandable, now
- * that Miles Lott (milos@insync.net) has gotten the Generic channel to
- * work. Also made them always show up in the log file.
- *
- * (01/25/2000) gkh
- * Added initial framework for FTDI serial converter so that Bill Ryder
- * has a place to put his code.
- * Added the vendor specific info from Handspring. Now we can print out
- * informational debug messages as well as understand what is happening.
- *
- * (01/23/2000) gkh
- * Fixed problem of crash when trying to open a port that didn't have a
- * device assigned to it. Made the minor node finding a little smarter,
- * now it looks to find a continuous space for the new device.
- *
- * (01/21/2000) gkh
- * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
- * Fixed get_serial_by_minor which was all messed up for multi port
- * devices. Fixed multi port problem for generic devices. Now the number
- * of ports is determined by the number of bulk out endpoints for the
- * generic device.
- *
- * (01/19/2000) gkh
- * Removed lots of cruft that was around from the old (pre urb) driver
- * interface.
- * Made the serial_table dynamic. This should save lots of memory when
- * the number of minor nodes goes up to 256.
- * Added initial support for devices that have more than one port.
- * Added more debugging comments for the Visor, and added a needed
- * set_configuration call.
- *
- * (01/17/2000) gkh
- * Fixed the WhiteHEAT firmware (my processing tool had a bug)
- * and added new debug loader firmware for it.
- * Removed the put_char function as it isn't really needed.
- * Added visor startup commands as found by the Win98 dump.
- *
- * (01/13/2000) gkh
- * Fixed the vendor id for the generic driver to the one I meant it to be.
- *
- * (01/12/2000) gkh
- * Forget the version numbering...that's pretty useless...
- * Made the driver able to be compiled so that the user can select which
- * converter they want to use. This allows people who only want the Visor
- * support to not pay the memory size price of the WhiteHEAT.
- * Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
- * grabbed the root hub. Not good.
- *
- * version 0.4.0 (01/10/2000) gkh
- * Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
- * device. Added startup function to allow firmware to be downloaded to
- * a device if it needs to be.
- * Added firmware download logic to the WhiteHEAT device.
- * Started to add #defines to split up the different drivers for potential
- * configuration option.
- *
- * version 0.3.1 (12/30/99) gkh
- * Fixed problems with urb for bulk out.
- * Added initial support for multiple sets of endpoints. This enables
- * the Handspring Visor to be attached successfully. Only the first
- * bulk in / bulk out endpoint pair is being used right now.
- *
- * version 0.3.0 (12/27/99) gkh
- * Added initial support for the Handspring Visor based on a patch from
- * Miles Lott (milos@sneety.insync.net)
- * Cleaned up the code a bunch and converted over to using urbs only.
- *
- * version 0.2.3 (12/21/99) gkh
- * Added initial support for the Connect Tech WhiteHEAT converter.
- * Incremented the number of ports in expectation of getting the
- * WhiteHEAT to work properly (4 ports per connection).
- * Added notification on insertion and removal of what port the
- * device is/was connected to (and what kind of device it was).
- *
- * version 0.2.2 (12/16/99) gkh
- * Changed major number to the new allocated number. We're legal now!
- *
- * version 0.2.1 (12/14/99) gkh
- * Fixed bug that happens when device node is opened when there isn't a
- * device attached to it. Thanks to marek@webdesign.no for noticing this.
- *
- * version 0.2.0 (11/10/99) gkh
- * Split up internals to make it easier to add different types of serial
- * converters to the code.
- * Added a "generic" driver that gets it's vendor and product id
- * from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
- * for the idea and sample code (from the usb scanner driver.)
- * Cleared up any licensing questions by releasing it under the GNU GPL.
- *
- * version 0.1.2 (10/25/99) gkh
- * Fixed bug in detecting device.
- *
- * version 0.1.1 (10/05/99) gkh
- * Changed the major number to not conflict with anything else.
- *
- * version 0.1 (09/28/99) gkh
- * Can recognize the two different devices and start up a read from
- * device when asked to. Writes also work. No control signals yet, this
- * all is vendor specific data (i.e. no spec), also no control for
- * different baud rates or other bit settings.
- * Currently we are using the same devid as the acm driver. This needs
- * to change.
- *
*/
#include <linux/config.h>
@@ -342,7 +37,6 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
@@ -427,7 +121,7 @@ static void destroy_serial(struct kref *kref)
serial = to_usb_serial(kref);
- dbg ("%s - %s", __FUNCTION__, serial->type->name);
+ dbg("%s - %s", __FUNCTION__, serial->type->description);
serial->type->shutdown(serial);
@@ -507,7 +201,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
/* lock this module before we call it
* this may fail, which means we must bail out,
* safe because we are called with BKL held */
- if (!try_module_get(serial->type->owner)) {
+ if (!try_module_get(serial->type->driver.owner)) {
retval = -ENODEV;
goto bailout_kref_put;
}
@@ -522,7 +216,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
return 0;
bailout_module_put:
- module_put(serial->type->owner);
+ module_put(serial->type->driver.owner);
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
port->open_count = 0;
@@ -531,7 +225,7 @@ bailout_kref_put:
static void serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
if (!port)
return;
@@ -553,7 +247,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
port->tty = NULL;
}
- module_put(port->serial->type->owner);
+ module_put(port->serial->type->driver.owner);
}
kref_put(&port->serial->kref, destroy_serial);
@@ -561,7 +255,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
@@ -580,7 +274,7 @@ exit:
static int serial_write_room (struct tty_struct *tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -599,7 +293,7 @@ exit:
static int serial_chars_in_buffer (struct tty_struct *tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
dbg("%s = port %d", __FUNCTION__, port->number);
@@ -618,7 +312,7 @@ exit:
static void serial_throttle (struct tty_struct * tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -634,7 +328,7 @@ static void serial_throttle (struct tty_struct * tty)
static void serial_unthrottle (struct tty_struct * tty)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -650,7 +344,7 @@ static void serial_unthrottle (struct tty_struct * tty)
static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
@@ -672,7 +366,7 @@ exit:
static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -688,7 +382,7 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
static void serial_break (struct tty_struct *tty, int break_state)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -711,16 +405,16 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
char tmp[40];
dbg("%s", __FUNCTION__);
- length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
+ length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
serial = usb_serial_get_by_index(i);
if (serial == NULL)
continue;
length += sprintf (page+length, "%d:", i);
- if (serial->type->owner)
- length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
- length += sprintf (page+length, " name:\"%s\"", serial->type->name);
+ if (serial->type->driver.owner)
+ length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
+ length += sprintf (page+length, " name:\"%s\"", serial->type->description);
length += sprintf (page+length, " vendor:%04x product:%04x",
le16_to_cpu(serial->dev->descriptor.idVendor),
le16_to_cpu(serial->dev->descriptor.idProduct));
@@ -749,7 +443,7 @@ done:
static int serial_tiocmget (struct tty_struct *tty, struct file *file)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -768,7 +462,7 @@ exit:
static int serial_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -786,7 +480,7 @@ exit:
void usb_serial_port_softint(void *private)
{
- struct usb_serial_port *port = (struct usb_serial_port *)private;
+ struct usb_serial_port *port = private;
struct tty_struct *tty;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -823,7 +517,7 @@ static void port_release(struct device *dev)
static struct usb_serial * create_serial (struct usb_device *dev,
struct usb_interface *interface,
- struct usb_serial_device_type *type)
+ struct usb_serial_driver *driver)
{
struct usb_serial *serial;
@@ -834,22 +528,22 @@ static struct usb_serial * create_serial (struct usb_device *dev,
}
memset (serial, 0, sizeof(*serial));
serial->dev = usb_get_dev(dev);
- serial->type = type;
+ serial->type = driver;
serial->interface = interface;
kref_init(&serial->kref);
return serial;
}
-static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
{
struct list_head *p;
const struct usb_device_id *id;
- struct usb_serial_device_type *t;
+ struct usb_serial_driver *t;
/* List trough know devices and see if the usb id matches */
list_for_each(p, &usb_serial_driver_list) {
- t = list_entry(p, struct usb_serial_device_type, driver_list);
+ t = list_entry(p, struct usb_serial_driver, driver_list);
id = usb_match_id(iface, t->id_table);
if (id != NULL) {
dbg("descriptor matches");
@@ -872,7 +566,7 @@ int usb_serial_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
- struct usb_serial_device_type *type = NULL;
+ struct usb_serial_driver *type = NULL;
int retval;
int minor;
int buffer_size;
@@ -900,7 +594,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (type->probe) {
const struct usb_device_id *id;
- if (!try_module_get(type->owner)) {
+ if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
@@ -908,7 +602,7 @@ int usb_serial_probe(struct usb_interface *interface,
id = usb_match_id(interface, type->id_table);
retval = type->probe(serial, id);
- module_put(type->owner);
+ module_put(type->driver.owner);
if (retval) {
dbg ("sub driver rejected device");
@@ -992,7 +686,7 @@ int usb_serial_probe(struct usb_interface *interface,
#endif
/* found all that we need */
- dev_info(&interface->dev, "%s converter detected\n", type->name);
+ dev_info(&interface->dev, "%s converter detected\n", type->description);
#ifdef CONFIG_USB_SERIAL_GENERIC
if (type == &usb_serial_generic_device) {
@@ -1007,13 +701,13 @@ int usb_serial_probe(struct usb_interface *interface,
if (!num_ports) {
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
- if (!try_module_get(type->owner)) {
+ if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
}
num_ports = type->calc_num_ports (serial);
- module_put(type->owner);
+ module_put(type->driver.owner);
}
if (!num_ports)
num_ports = type->num_ports;
@@ -1158,12 +852,12 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has an attach function, call it */
if (type->attach) {
- if (!try_module_get(type->owner)) {
+ if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev, "module get failed, exiting\n");
goto probe_error;
}
retval = type->attach (serial);
- module_put(type->owner);
+ module_put(type->driver.owner);
if (retval < 0)
goto probe_error;
if (retval > 0) {
@@ -1330,7 +1024,7 @@ static int __init usb_serial_init(void)
goto exit_generic;
}
- info(DRIVER_DESC " " DRIVER_VERSION);
+ info(DRIVER_DESC);
return result;
@@ -1375,7 +1069,7 @@ module_exit(usb_serial_exit);
} \
} while (0)
-static void fixup_generic(struct usb_serial_device_type *device)
+static void fixup_generic(struct usb_serial_driver *device)
{
set_to_generic_if_null(device, open);
set_to_generic_if_null(device, write);
@@ -1387,30 +1081,33 @@ static void fixup_generic(struct usb_serial_device_type *device)
set_to_generic_if_null(device, shutdown);
}
-int usb_serial_register(struct usb_serial_device_type *new_device)
+int usb_serial_register(struct usb_serial_driver *driver)
{
int retval;
- fixup_generic(new_device);
+ fixup_generic(driver);
+
+ if (!driver->description)
+ driver->description = driver->driver.name;
/* Add this device to our list of devices */
- list_add(&new_device->driver_list, &usb_serial_driver_list);
+ list_add(&driver->driver_list, &usb_serial_driver_list);
- retval = usb_serial_bus_register(new_device);
+ retval = usb_serial_bus_register(driver);
if (retval) {
- err("problem %d when registering driver %s", retval, new_device->name);
- list_del(&new_device->driver_list);
+ err("problem %d when registering driver %s", retval, driver->description);
+ list_del(&driver->driver_list);
}
else
- info("USB Serial support registered for %s", new_device->name);
+ info("USB Serial support registered for %s", driver->description);
return retval;
}
-void usb_serial_deregister(struct usb_serial_device_type *device)
+void usb_serial_deregister(struct usb_serial_driver *device)
{
- info("USB Serial deregistering driver %s", device->name);
+ info("USB Serial deregistering driver %s", device->description);
list_del(&device->driver_list);
usb_serial_bus_deregister(device);
}
@@ -1429,7 +1126,6 @@ EXPORT_SYMBOL_GPL(usb_serial_port_softint);
/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 57f92f054c75..238a5a871ed6 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -1,53 +1,13 @@
/*
* USB Serial Converter driver
*
- * Copyright (C) 1999 - 2004
+ * Copyright (C) 1999 - 2005
* 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; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2 of the License.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
- * (03/26/2002) gkh
- * removed the port->tty check from port_paranoia_check() due to serial
- * consoles not having a tty device assigned to them.
- *
- * (12/03/2001) gkh
- * removed active from the port structure.
- * added documentation to the usb_serial_device_type structure
- *
- * (10/10/2001) gkh
- * added vendor and product to serial structure. Needed to determine device
- * owner when the device is disconnected.
- *
- * (05/30/2001) gkh
- * added sem to port structure and removed port_lock
- *
- * (10/05/2000) gkh
- * Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
- * fix bug with urb->dev not being set properly, now that the usb core
- * needs it.
- *
- * (09/11/2000) gkh
- * Added usb_serial_debug_data function to help get rid of #DEBUG in the
- * drivers.
- *
- * (08/28/2000) gkh
- * Added port_lock to port structure.
- *
- * (08/08/2000) gkh
- * Added open_count to port structure.
- *
- * (07/23/2000) gkh
- * Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- * Modifications to allow usb-serial drivers to be modules.
- *
- *
*/
@@ -143,7 +103,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
/**
* usb_serial - structure used by the usb-serial core for a device
* @dev: pointer to the struct usb_device for this device
- * @type: pointer to the struct usb_serial_device_type for this device
+ * @type: pointer to the struct usb_serial_driver for this device
* @interface: pointer to the struct usb_interface for this device
* @minor: the starting minor number for this device
* @num_ports: the number of ports this device has
@@ -159,7 +119,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
*/
struct usb_serial {
struct usb_device * dev;
- struct usb_serial_device_type * type;
+ struct usb_serial_driver * type;
struct usb_interface * interface;
unsigned char minor;
unsigned char num_ports;
@@ -188,13 +148,9 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
}
/**
- * usb_serial_device_type - a structure that defines a usb serial device
- * @owner: pointer to the module that owns this device.
- * @name: pointer to a string that describes this device. This string used
+ * usb_serial_driver - describes a usb serial driver
+ * @description: pointer to a string that describes this driver. This string used
* in the syslog messages when a device is inserted or removed.
- * @short_name: a pointer to a string that describes this device in
- * KOBJ_NAME_LEN characters or less. This is used for the sysfs interface
- * to describe the driver.
* @id_table: pointer to a list of usb_device_id structures that define all
* of the devices this structure can support.
* @num_interrupt_in: the number of interrupt in endpoints this device will
@@ -221,16 +177,19 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
* @shutdown: pointer to the driver's shutdown function. This will be
* called when the device is removed from the system.
*
- * This structure is defines a USB Serial device. It provides all of
+ * This structure is defines a USB Serial driver. It provides all of
* the information that the USB serial core code needs. If the function
* pointers are defined, then the USB serial core code will call them when
* the corresponding tty port functions are called. If they are not
* called, the generic serial function will be used instead.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver (remember
+ * it will show up in sysfs, so it needs to be short and to the point.
+ * Useing the module name is a good idea.)
*/
-struct usb_serial_device_type {
- struct module *owner;
- char *name;
- char *short_name;
+struct usb_serial_driver {
+ const char *description;
const struct usb_device_id *id_table;
char num_interrupt_in;
char num_interrupt_out;
@@ -269,10 +228,10 @@ struct usb_serial_device_type {
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
};
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver)
+#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
-extern int usb_serial_register(struct usb_serial_device_type *new_device);
-extern void usb_serial_deregister(struct usb_serial_device_type *device);
+extern int usb_serial_register(struct usb_serial_driver *driver);
+extern void usb_serial_deregister(struct usb_serial_driver *driver);
extern void usb_serial_port_softint(void *private);
extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
@@ -303,10 +262,10 @@ extern void usb_serial_generic_shutdown (struct usb_serial *serial);
extern int usb_serial_generic_register (int debug);
extern void usb_serial_generic_deregister (void);
-extern int usb_serial_bus_register (struct usb_serial_device_type *device);
-extern void usb_serial_bus_deregister (struct usb_serial_device_type *device);
+extern int usb_serial_bus_register (struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
-extern struct usb_serial_device_type usb_serial_generic_device;
+extern struct usb_serial_driver usb_serial_generic_device;
extern struct bus_type usb_serial_bus_type;
extern struct tty_driver *usb_serial_tty_driver;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 31c57adcb623..a473c1c34559 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -7,139 +7,10 @@
*
* 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 Free Software Foundation; either version 2 of the License.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
- * (06/03/2003) Judd Montgomery <judd at jpilot.org>
- * Added support for module parameter options for untested/unknown
- * devices.
- *
- * (03/09/2003) gkh
- * Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl
- * <brachtl@redgrep.cz> for the information.
- *
- * (03/05/2003) gkh
- * Think Treo support is now working.
- *
- * (04/03/2002) gkh
- * Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI
- * <hiro@zob.ne.jp> for the information.
- *
- * (03/27/2002) gkh
- * Removed assumptions that port->tty was always valid (is not true
- * for usb serial console devices.)
- *
- * (03/23/2002) gkh
- * Added support for the Palm i705 device, thanks to Thomas Riemer
- * <tom@netmech.com> for the information.
- *
- * (03/21/2002) gkh
- * Added support for the Palm m130 device, thanks to Udo Eisenbarth
- * <udo.eisenbarth@web.de> for the information.
- *
- * (02/27/2002) gkh
- * Reworked the urb handling logic. We have no more pool, but dynamically
- * allocate the urb and the transfer buffer on the fly. In testing this
- * does not incure any measurable overhead. This also relies on the fact
- * that we have proper reference counting logic for urbs.
- *
- * (02/21/2002) SilaS
- * Added initial support for the Palm m515 devices.
- *
- * (02/14/2002) gkh
- * Added support for the Clie S-360 device.
- *
- * (12/18/2001) gkh
- * Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand
- * for the patch.
- *
- * (11/11/2001) gkh
- * Added support for the m125 devices, and added check to prevent oopses
- * for Clié devices that lie about the number of ports they have.
- *
- * (08/30/2001) gkh
- * Added support for the Clie devices, both the 3.5 and 4.0 os versions.
- * Many thanks to Daniel Burke, and Bryan Payne for helping with this.
- *
- * (08/23/2001) gkh
- * fixed a few potential bugs pointed out by Oliver Neukum.
- *
- * (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (05/28/2000) gkh
- * Added initial support for the Palm m500 and Palm m505 devices.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * (01/21/2000) gkh
- * Added write_room and chars_in_buffer, as they were previously using the
- * generic driver versions which is all wrong now that we are using an urb
- * pool. Thanks to Wolfgang Grandegger for pointing this out to me.
- * Removed count assignment in the write function, which was not needed anymore
- * either. Thanks to Al Borchers for pointing this out.
- *
- * (12/12/2000) gkh
- * Moved MOD_DEC to end of visor_close to be nicer, as the final write
- * message can sleep.
- *
- * (11/12/2000) gkh
- * Fixed bug with data being dropped on the floor by forcing tty->low_latency
- * to be on. Hopefully this fixes the OHCI issue!
- *
- * (11/01/2000) Adam J. Richter
- * usb_device_id table support
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (09/11/2000) gkh
- * Got rid of always calling kmalloc for every urb we wrote out to the
- * device.
- * Added visor_read_callback so we can keep track of bytes in and out for
- * those people who like to know the speed of their device.
- * Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (09/06/2000) gkh
- * Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_
- * the host controller drivers set urb->dev = NULL when the urb is finished.
- *
- * (08/28/2000) gkh
- * Added locks for SMP safeness.
- *
- * (08/08/2000) gkh
- * Fixed endian problem in visor_startup.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
- * than once.
- *
- * (07/23/2000) gkh
- * Added pool of write urbs to speed up transfers to the visor.
- *
- * (07/19/2000) gkh
- * Added module_init and module_exit functions to handle the fact that this
- * driver is a loadable module now.
- *
- * (07/03/2000) gkh
- * Added visor_set_ioctl and visor_set_termios functions (they don't do much
- * of anything, but are good for debugging.)
- *
- * (06/25/2000) gkh
- * Fixed bug in visor_unthrottle that should help with the disconnect in PPP
- * bug that people have been reporting.
- *
- * (06/23/2000) gkh
- * Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (04/27/2000) Ryan VanderBijl
- * Fixed memory leak in visor_close
- *
- * (03/26/2000) gkh
- * Split driver up into device specific pieces.
- *
*/
#include <linux/config.h>
@@ -161,7 +32,6 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.1"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
@@ -311,10 +181,12 @@ static struct usb_driver visor_driver = {
};
/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
-static struct usb_serial_device_type handspring_device = {
- .owner = THIS_MODULE,
- .name = "Handspring Visor / Palm OS",
- .short_name = "visor",
+static struct usb_serial_driver handspring_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "visor",
+ },
+ .description = "Handspring Visor / Palm OS",
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 2,
@@ -339,10 +211,12 @@ static struct usb_serial_device_type handspring_device = {
};
/* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */
-static struct usb_serial_device_type clie_5_device = {
- .owner = THIS_MODULE,
- .name = "Sony Clie 5.0",
- .short_name = "clie_5",
+static struct usb_serial_driver clie_5_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "clie_5",
+ },
+ .description = "Sony Clie 5.0",
.id_table = clie_id_5_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 2,
@@ -367,10 +241,12 @@ static struct usb_serial_device_type clie_5_device = {
};
/* device info for the Sony Clie OS version 3.5 */
-static struct usb_serial_device_type clie_3_5_device = {
- .owner = THIS_MODULE,
- .name = "Sony Clie 3.5",
- .short_name = "clie_3.5",
+static struct usb_serial_driver clie_3_5_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "clie_3.5",
+ },
+ .description = "Sony Clie 3.5",
.id_table = clie_id_3_5_table,
.num_interrupt_in = 0,
.num_bulk_in = 1,
@@ -782,7 +658,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
break;
}
dev_info(dev, "%s: port %d, is for %s use\n",
- serial->type->name,
+ serial->type->description,
connection_info->connections[i].port, string);
}
}
@@ -791,11 +667,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
*/
if (num_ports == 0 || num_ports > 2) {
dev_warn (dev, "%s: No valid connect info available\n",
- serial->type->name);
+ serial->type->description);
num_ports = 2;
}
- dev_info(dev, "%s: Number of ports: %d\n", serial->type->name,
+ dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
num_ports);
/*
@@ -1125,7 +1001,7 @@ static int __init visor_init (void)
retval = usb_register(&visor_driver);
if (retval)
goto failed_usb_register;
- info(DRIVER_DESC " " DRIVER_VERSION);
+ info(DRIVER_DESC);
return 0;
failed_usb_register:
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index cf3bc30675a1..18c3183be769 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -156,10 +156,12 @@ static void whiteheat_unthrottle (struct usb_serial_port *port);
static void whiteheat_read_callback (struct urb *urb, struct pt_regs *regs);
static void whiteheat_write_callback (struct urb *urb, struct pt_regs *regs);
-static struct usb_serial_device_type whiteheat_fake_device = {
- .owner = THIS_MODULE,
- .name = "Connect Tech - WhiteHEAT - (prerenumeration)",
- .short_name = "whiteheatnofirm",
+static struct usb_serial_driver whiteheat_fake_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "whiteheatnofirm",
+ },
+ .description = "Connect Tech - WhiteHEAT - (prerenumeration)",
.id_table = id_table_prerenumeration,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -169,10 +171,12 @@ static struct usb_serial_device_type whiteheat_fake_device = {
.attach = whiteheat_firmware_attach,
};
-static struct usb_serial_device_type whiteheat_device = {
- .owner = THIS_MODULE,
- .name = "Connect Tech - WhiteHEAT",
- .short_name = "whiteheat",
+static struct usb_serial_driver whiteheat_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "whiteheat",
+ },
+ .description = "Connect Tech - WhiteHEAT",
.id_table = id_table_std,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -382,10 +386,10 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't send command [%d]", serial->type->name, ret);
+ err("%s: Couldn't send command [%d]", serial->type->description, ret);
goto no_firmware;
} else if (alen != sizeof(command)) {
- err("%s: Send command incomplete [%d]", serial->type->name, alen);
+ err("%s: Send command incomplete [%d]", serial->type->description, alen);
goto no_firmware;
}
@@ -394,19 +398,19 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_clear_halt(serial->dev, pipe);
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->name, ret);
+ err("%s: Couldn't get results [%d]", serial->type->description, ret);
goto no_firmware;
} else if (alen != sizeof(result)) {
- err("%s: Get results incomplete [%d]", serial->type->name, alen);
+ err("%s: Get results incomplete [%d]", serial->type->description, alen);
goto no_firmware;
} else if (result[0] != command[0]) {
- err("%s: Command failed [%d]", serial->type->name, result[0]);
+ err("%s: Command failed [%d]", 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->name,
+ info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
for (i = 0; i < serial->num_ports; i++) {
@@ -414,7 +418,7 @@ static int whiteheat_attach (struct usb_serial *serial)
info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->name);
+ err("%s: Out of memory for port structures\n", serial->type->description);
goto no_private;
}
@@ -484,7 +488,7 @@ static int whiteheat_attach (struct usb_serial *serial)
command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
if (command_info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->name);
+ err("%s: Out of memory for port structures\n", serial->type->description);
goto no_command_private;
}
@@ -501,9 +505,9 @@ 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->name);
- err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name);
- err("%s: please contact support@connecttech.com\n", serial->type->name);
+ 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);
return -ENODEV;
no_command_private:
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index f1f1c0608c22..1a9679f76f5a 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -2,7 +2,8 @@
# USB Storage driver configuration
#
-comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'"
+comment "may also be needed; see USB_STORAGE Help for more information"
depends on USB
config USB_STORAGE
@@ -111,3 +112,15 @@ config USB_STORAGE_JUMPSHOT
Say Y here to include additional code to support the Lexar Jumpshot
USB CompactFlash reader.
+
+config USB_STORAGE_ONETOUCH
+ bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
+ depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL
+ help
+ Say Y here to include additional code to support the Maxtor OneTouch
+ USB hard drive's onetouch button.
+
+ This code registers the button on the front of Maxtor OneTouch USB
+ hard drive's as an input device. An action can be associated with
+ this input in any keybinding software. (e.g. gnome's keyboard short-
+ cuts)
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 56652ccc2881..44ab8f9978fe 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -18,6 +18,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o
usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o
usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
initializers.o $(usb-storage-obj-y)
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
new file mode 100644
index 000000000000..89401a59f952
--- /dev/null
+++ b/drivers/usb/storage/onetouch.c
@@ -0,0 +1,211 @@
+/*
+ * Support for the Maxtor OneTouch USB hard drive's button
+ *
+ * Current development and maintenance by:
+ * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
+ *
+ * Initial work by:
+ * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
+ *
+ * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
+ *
+ */
+
+/*
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_input.h>
+#include "usb.h"
+#include "onetouch.h"
+#include "debug.h"
+
+void onetouch_release_input(void *onetouch_);
+
+struct usb_onetouch {
+ char name[128];
+ char phys[64];
+ struct input_dev *dev; /* input device interface */
+ struct usb_device *udev; /* usb device */
+
+ struct urb *irq; /* urb for interrupt in report */
+ unsigned char *data; /* input data */
+ dma_addr_t data_dma;
+};
+
+static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_onetouch *onetouch = urb->context;
+ signed char *data = onetouch->data;
+ struct input_dev *dev = onetouch->dev;
+ int status;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ /* -EPIPE: should clear the halt */
+ default: /* error */
+ goto resubmit;
+ }
+
+ input_regs(dev, regs);
+ input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
+ input_sync(dev);
+
+resubmit:
+ status = usb_submit_urb (urb, SLAB_ATOMIC);
+ if (status)
+ err ("can't resubmit intr, %s-%s/input0, status %d",
+ onetouch->udev->bus->bus_name,
+ onetouch->udev->devpath, status);
+}
+
+static int usb_onetouch_open(struct input_dev *dev)
+{
+ struct usb_onetouch *onetouch = dev->private;
+
+ onetouch->irq->dev = onetouch->udev;
+ if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
+ err("usb_submit_urb failed");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void usb_onetouch_close(struct input_dev *dev)
+{
+ struct usb_onetouch *onetouch = dev->private;
+
+ usb_kill_urb(onetouch->irq);
+}
+
+int onetouch_connect_input(struct us_data *ss)
+{
+ struct usb_device *udev = ss->pusb_dev;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_onetouch *onetouch;
+ struct input_dev *input_dev;
+ int pipe, maxp;
+
+ interface = ss->pusb_intf->cur_altsetting;
+
+ if (interface->desc.bNumEndpoints != 3)
+ return -ENODEV;
+
+ endpoint = &interface->endpoint[2].desc;
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
+ return -ENODEV;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_INT)
+ return -ENODEV;
+
+ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+
+ onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!onetouch || !input_dev)
+ goto fail1;
+
+ onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
+ SLAB_ATOMIC, &onetouch->data_dma);
+ if (!onetouch->data)
+ goto fail1;
+
+ onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!onetouch->irq)
+ goto fail2;
+
+ onetouch->udev = udev;
+ onetouch->dev = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(onetouch->name, udev->manufacturer,
+ sizeof(onetouch->name));
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(onetouch->name, " ", sizeof(onetouch->name));
+ strlcat(onetouch->name, udev->product, sizeof(onetouch->name));
+ }
+
+ if (!strlen(onetouch->name))
+ snprintf(onetouch->name, sizeof(onetouch->name),
+ "Maxtor Onetouch %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys));
+ strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys));
+
+ input_dev->name = onetouch->name;
+ input_dev->phys = onetouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &udev->dev;
+
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(ONETOUCH_BUTTON, input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+
+ input_dev->private = onetouch;
+ input_dev->open = usb_onetouch_open;
+ input_dev->close = usb_onetouch_close;
+
+ usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
+ (maxp > 8 ? 8 : maxp),
+ usb_onetouch_irq, onetouch, endpoint->bInterval);
+ onetouch->irq->transfer_dma = onetouch->data_dma;
+ onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ ss->extra_destructor = onetouch_release_input;
+ ss->extra = onetouch;
+
+ input_register_device(onetouch->dev);
+
+ return 0;
+
+ fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN,
+ onetouch->data, onetouch->data_dma);
+ fail1: kfree(onetouch);
+ input_free_device(input_dev);
+ return -ENOMEM;
+}
+
+void onetouch_release_input(void *onetouch_)
+{
+ struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;
+
+ if (onetouch) {
+ usb_kill_urb(onetouch->irq);
+ input_unregister_device(onetouch->dev);
+ usb_free_urb(onetouch->irq);
+ usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN,
+ onetouch->data, onetouch->data_dma);
+ }
+}
diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h
new file mode 100644
index 000000000000..41c7aa8f0446
--- /dev/null
+++ b/drivers/usb/storage/onetouch.h
@@ -0,0 +1,9 @@
+#ifndef _ONETOUCH_H_
+#define _ONETOUCH_H_
+
+#define ONETOUCH_PKT_LEN 0x02
+#define ONETOUCH_BUTTON KEY_PROG1
+
+int onetouch_connect_input(struct us_data *ss);
+
+#endif
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index af294bb68c35..4837524eada7 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -156,6 +156,14 @@ static int slave_configure(struct scsi_device *sdev)
if (us->flags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
+ /* Some devices report a SCSI revision level above 2 but are
+ * unable to handle the REPORT LUNS command (for which
+ * support is mandatory at level 3). Since we already have
+ * a Get-Max-LUN request, we won't lose much by setting the
+ * revision level down to 2. The only devices that would be
+ * affected are those with sparse LUNs. */
+ sdev->scsi_level = SCSI_2;
+
/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
* Hardware Error) when any low-level error occurs,
* recoverable or not. Setting this flag tells the SCSI
@@ -219,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
-/* This is always called with scsi_lock(host) held */
static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ * bits are protected by the host lock. */
+ scsi_lock(us_to_host(us));
+
/* Is this command still active? */
if (us->srb != srb) {
+ scsi_unlock(us_to_host(us));
US_DEBUGP ("-- nothing to abort\n");
return FAILED;
}
/* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
* a device reset isn't already in progress (to avoid interfering
- * with the reset). To prevent races with auto-reset, we must
- * stop any ongoing USB transfers while still holding the host
- * lock. */
+ * with the reset). Note that we must retain the host lock while
+ * calling usb_stor_stop_transport(); otherwise it might interfere
+ * with an auto-reset that begins as soon as we release the lock. */
set_bit(US_FLIDX_TIMED_OUT, &us->flags);
if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
+ scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
-
- /* Reacquire the lock and allow USB transfers to resume */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
- clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
}
/* This invokes the transport reset mechanism to reset the state of the
* device */
-/* This is always called with scsi_lock(host) held */
static int device_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -271,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
}
/* Simulate a SCSI bus reset by resetting the device's USB port. */
-/* This is always called with scsi_lock(host) held */
static int bus_reset(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
@@ -283,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
result = usb_stor_port_reset(us);
up(&(us->dev_semaphore));
- /* lock the host for the return */
return result < 0 ? FAILED : SUCCESS;
}
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index f3b60288696c..33c55a6261bb 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,4 +1,4 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
+/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
*
* $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
*
@@ -67,10 +67,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
/*
- * Convenience function to produce an ATAPI read/write sectors command
+ * Convenience function to produce an ATA read/write sectors command
* Use cmd=0x20 for read, cmd=0x30 for write
*/
-static void usbat_pack_atapi_sector_cmd(unsigned char *buf,
+static void usbat_pack_ata_sector_cmd(unsigned char *buf,
unsigned char thistime,
u32 sector, unsigned char cmd)
{
@@ -196,10 +196,12 @@ static int usbat_check_status(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_FAILED;
- if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok)
+ /* error/check condition (0x51 is ok) */
+ if (*reply & 0x01 && *reply != 0x51)
return USB_STOR_TRANSPORT_FAILED;
- if (*reply & 0x20) // device fault
+ /* device fault */
+ if (*reply & 0x20)
return USB_STOR_TRANSPORT_FAILED;
return USB_STOR_TRANSPORT_GOOD;
@@ -222,29 +224,39 @@ static int usbat_set_shuttle_features(struct us_data *us,
command[0] = 0x40;
command[1] = USBAT_CMD_SET_FEAT;
- // The only bit relevant to ATA access is bit 6
- // which defines 8 bit data access (set) or 16 bit (unset)
+ /*
+ * The only bit relevant to ATA access is bit 6
+ * which defines 8 bit data access (set) or 16 bit (unset)
+ */
command[2] = epp_control;
- // If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
- // ET1 and ET2 define an external event to be checked for on event of a
- // _read_blocks or _write_blocks operation. The read/write will not take
- // place unless the defined trigger signal is active.
+ /*
+ * If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
+ * ET1 and ET2 define an external event to be checked for on event of a
+ * _read_blocks or _write_blocks operation. The read/write will not take
+ * place unless the defined trigger signal is active.
+ */
command[3] = external_trigger;
- // The resultant byte of the mask operation (see mask_byte) is compared for
- // equivalence with this test pattern. If equal, the read/write will take
- // place.
+ /*
+ * The resultant byte of the mask operation (see mask_byte) is compared for
+ * equivalence with this test pattern. If equal, the read/write will take
+ * place.
+ */
command[4] = test_pattern;
- // This value is logically ANDed with the status register field specified
- // in the read/write command.
+ /*
+ * This value is logically ANDed with the status register field specified
+ * in the read/write command.
+ */
command[5] = mask_byte;
- // If ALQ is set in the qualifier, this field contains the address of the
- // registers where the byte count should be read for transferring the data.
- // If ALQ is not set, then this field contains the number of bytes to be
- // transferred.
+ /*
+ * If ALQ is set in the qualifier, this field contains the address of the
+ * registers where the byte count should be read for transferring the data.
+ * If ALQ is not set, then this field contains the number of bytes to be
+ * transferred.
+ */
command[6] = subcountL;
command[7] = subcountH;
@@ -273,26 +285,26 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
if (result!=USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (*status & 0x01) { // check condition
+ if (*status & 0x01) { /* check condition */
result = usbat_read(us, USBAT_ATA, 0x10, status);
return USB_STOR_TRANSPORT_FAILED;
}
- if (*status & 0x20) // device fault
+ if (*status & 0x20) /* device fault */
return USB_STOR_TRANSPORT_FAILED;
- if ((*status & 0x80)==0x00) { // not busy
+ if ((*status & 0x80)==0x00) { /* not busy */
US_DEBUGP("Waited not busy for %d steps\n", i);
return USB_STOR_TRANSPORT_GOOD;
}
if (i<500)
- msleep(10); // 5 seconds
+ msleep(10); /* 5 seconds */
else if (i<700)
- msleep(50); // 10 seconds
+ msleep(50); /* 10 seconds */
else if (i<1200)
- msleep(100); // 50 seconds
+ msleep(100); /* 50 seconds */
else
- msleep(1000); // X minutes
+ msleep(1000); /* X minutes */
}
US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
@@ -412,9 +424,12 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
if (i==0) {
cmdlen = 16;
- // Write to multiple registers
- // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
- // but that's what came out of the trace every single time.
+ /*
+ * Write to multiple registers
+ * Not really sure the 0x07, 0x17, 0xfc, 0xe7 is
+ * necessary here, but that's what came out of the
+ * trace every single time.
+ */
command[0] = 0x40;
command[1] = access | USBAT_CMD_WRITE_REGS;
command[2] = 0x07;
@@ -426,7 +441,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
} else
cmdlen = 8;
- // Conditionally read or write blocks
+ /* Conditionally read or write blocks */
command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
command[cmdlen-7] = access |
(direction==DMA_TO_DEVICE ?
@@ -456,11 +471,6 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
}
-
- //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
- // direction == DMA_TO_DEVICE ? "out" : "in",
- // len, use_sg);
-
result = usb_stor_bulk_transfer_sg(us,
pipe, content, len, use_sg, NULL);
@@ -508,9 +518,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
if (result!=USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (*status & 0x01) // check condition
+ if (*status & 0x01) /* check condition */
return USB_STOR_TRANSPORT_FAILED;
- if (*status & 0x20) // device fault
+ if (*status & 0x20) /* device fault */
return USB_STOR_TRANSPORT_FAILED;
US_DEBUGP("Redoing %s\n",
@@ -547,32 +557,32 @@ static int usbat_multiple_write(struct us_data *us,
BUG_ON(num_registers > US_IOBUF_SIZE/2);
- // Write to multiple registers, ATA access
+ /* Write to multiple registers, ATA access */
command[0] = 0x40;
command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;
- // No relevance
+ /* No relevance */
command[2] = 0;
command[3] = 0;
command[4] = 0;
command[5] = 0;
- // Number of bytes to be transferred (incl. addresses and data)
+ /* Number of bytes to be transferred (incl. addresses and data) */
command[6] = LSB_of(num_registers*2);
command[7] = MSB_of(num_registers*2);
- // The setup command
+ /* The setup command */
result = usbat_execute_command(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- // Create the reg/data, reg/data sequence
+ /* Create the reg/data, reg/data sequence */
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
- // Send the data
+ /* Send the data */
result = usbat_bulk_write(us, data, num_registers*2);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -606,17 +616,17 @@ static int usbat_read_blocks(struct us_data *us,
command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;
command[2] = USBAT_ATA_DATA;
command[3] = USBAT_ATA_STATUS;
- command[4] = 0xFD; // Timeout (ms);
+ command[4] = 0xFD; /* Timeout (ms); */
command[5] = USBAT_QUAL_FCQ;
command[6] = LSB_of(len);
command[7] = MSB_of(len);
- // Multiple block read setup command
+ /* Multiple block read setup command */
result = usbat_execute_command(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_FAILED;
- // Read the blocks we just asked for
+ /* Read the blocks we just asked for */
result = usbat_bulk_read(us, buffer, len);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_FAILED;
@@ -647,17 +657,17 @@ static int usbat_write_blocks(struct us_data *us,
command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;
command[2] = USBAT_ATA_DATA;
command[3] = USBAT_ATA_STATUS;
- command[4] = 0xFD; // Timeout (ms)
+ command[4] = 0xFD; /* Timeout (ms) */
command[5] = USBAT_QUAL_FCQ;
command[6] = LSB_of(len);
command[7] = MSB_of(len);
- // Multiple block write setup command
+ /* Multiple block write setup command */
result = usbat_execute_command(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_FAILED;
- // Write the data
+ /* Write the data */
result = usbat_bulk_write(us, buffer, len);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_FAILED;
@@ -711,16 +721,20 @@ static int usbat_device_reset(struct us_data *us)
{
int rc;
- // Reset peripheral, enable peripheral control signals
- // (bring reset signal up)
+ /*
+ * Reset peripheral, enable peripheral control signals
+ * (bring reset signal up)
+ */
rc = usbat_write_user_io(us,
USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- // Enable peripheral control signals
- // (bring reset signal down)
+ /*
+ * Enable peripheral control signals
+ * (bring reset signal down)
+ */
rc = usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -737,7 +751,7 @@ static int usbat_device_enable_cdt(struct us_data *us)
{
int rc;
- // Enable peripheral control signals and card detect
+ /* Enable peripheral control signals and card detect */
rc = usbat_write_user_io(us,
USBAT_UIO_ACKD | USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -786,7 +800,7 @@ static int usbat_flash_check_media(struct us_data *us,
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- // Check for media existence
+ /* Check for media existence */
rc = usbat_flash_check_media_present(uio);
if (rc == USBAT_FLASH_MEDIA_NONE) {
info->sense_key = 0x02;
@@ -795,11 +809,11 @@ static int usbat_flash_check_media(struct us_data *us,
return USB_STOR_TRANSPORT_FAILED;
}
- // Check for media change
+ /* Check for media change */
rc = usbat_flash_check_media_changed(uio);
if (rc == USBAT_FLASH_MEDIA_CHANGED) {
- // Reset and re-enable card detect
+ /* Reset and re-enable card detect */
rc = usbat_device_reset(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
@@ -839,32 +853,29 @@ static int usbat_identify_device(struct us_data *us,
rc = usbat_device_reset(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
+ msleep(25);
/*
- * By examining the device signature after a reset, we can identify
- * whether the device supports the ATAPI packet interface.
- * The flash-devices do not support this, whereas the HP CDRW's obviously
- * do.
- *
- * This method is not ideal, but works because no other devices have been
- * produced based on the USBAT/USBAT02.
- *
- * Section 9.1 of the ATAPI-4 spec states (amongst other things) that
- * after a device reset, a Cylinder low of 0x14 indicates that the device
- * does support packet commands.
+ * In attempt to distinguish between HP CDRW's and Flash readers, we now
+ * execute the IDENTIFY PACKET DEVICE command. On ATA devices (i.e. flash
+ * readers), this command should fail with error. On ATAPI devices (i.e.
+ * CDROM drives), it should succeed.
*/
- rc = usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, &status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ rc = usbat_write(us, USBAT_ATA, USBAT_ATA_CMD, 0xA1);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("usbat_identify_device: Cylinder low is %02X\n", status);
+ rc = usbat_get_status(us, &status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if (status == 0x14) {
- // Device is HP 8200
+ /* Check for error bit, or if the command 'fell through' */
+ if (status == 0xA1 || !(status & 0x01)) {
+ /* Device is HP 8200 */
US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
info->devicetype = USBAT_DEV_HP8200;
} else {
- // Device is a CompactFlash reader/writer
+ /* Device is a CompactFlash reader/writer */
US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
info->devicetype = USBAT_DEV_FLASH;
}
@@ -919,7 +930,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
if (!reply)
return USB_STOR_TRANSPORT_ERROR;
- // ATAPI command : IDENTIFY DEVICE
+ /* ATA command : IDENTIFY DEVICE */
rc = usbat_multiple_write(us, registers, command, 3);
if (rc != USB_STOR_XFER_GOOD) {
US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
@@ -927,7 +938,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
goto leave;
}
- // Read device status
+ /* Read device status */
if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
@@ -935,7 +946,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
msleep(100);
- // Read the device identification data
+ /* Read the device identification data */
rc = usbat_read_block(us, reply, 512);
if (rc != USB_STOR_TRANSPORT_GOOD)
goto leave;
@@ -980,19 +991,23 @@ static int usbat_flash_read_data(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Jumpshot
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
+ /*
+ * we're working in LBA mode. according to the ATA spec,
+ * we can support up to 28-bit addressing. I don't know if Jumpshot
+ * supports beyond 24-bit addressing. It's kind of hard to test
+ * since it requires > 8GB CF card.
+ */
if (sector > 0x0FFFFFFF)
return USB_STOR_TRANSPORT_ERROR;
totallen = sectors * info->ssize;
- // Since we don't read more than 64 KB at a time, we have to create
- // a bounce buffer and move the data a piece at a time between the
- // bounce buffer and the actual transfer buffer.
+ /*
+ * Since we don't read more than 64 KB at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ */
alloclen = min(totallen, 65536u);
buffer = kmalloc(alloclen, GFP_NOIO);
@@ -1000,27 +1015,29 @@ static int usbat_flash_read_data(struct us_data *us,
return USB_STOR_TRANSPORT_ERROR;
do {
- // loop, never allocate or transfer more than 64k at once
- // (min(128k, 255*info->ssize) is the real limit)
+ /*
+ * loop, never allocate or transfer more than 64k at once
+ * (min(128k, 255*info->ssize) is the real limit)
+ */
len = min(totallen, alloclen);
thistime = (len / info->ssize) & 0xff;
- // ATAPI command 0x20 (READ SECTORS)
- usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20);
+ /* ATA command 0x20 (READ SECTORS) */
+ usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20);
- // Write/execute ATAPI read command
+ /* Write/execute ATA read command */
result = usbat_multiple_write(us, registers, command, 7);
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
- // Read the data we just requested
+ /* Read the data we just requested */
result = usbat_read_blocks(us, buffer, len);
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
US_DEBUGP("usbat_flash_read_data: %d bytes\n", len);
- // Store the data in the transfer buffer
+ /* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
&sg_idx, &sg_offset, TO_XFER_BUF);
@@ -1064,19 +1081,23 @@ static int usbat_flash_write_data(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- // we're working in LBA mode. according to the ATA spec,
- // we can support up to 28-bit addressing. I don't know if Jumpshot
- // supports beyond 24-bit addressing. It's kind of hard to test
- // since it requires > 8GB CF card.
+ /*
+ * we're working in LBA mode. according to the ATA spec,
+ * we can support up to 28-bit addressing. I don't know if the device
+ * supports beyond 24-bit addressing. It's kind of hard to test
+ * since it requires > 8GB media.
+ */
if (sector > 0x0FFFFFFF)
return USB_STOR_TRANSPORT_ERROR;
totallen = sectors * info->ssize;
- // Since we don't write more than 64 KB at a time, we have to create
- // a bounce buffer and move the data a piece at a time between the
- // bounce buffer and the actual transfer buffer.
+ /*
+ * Since we don't write more than 64 KB at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ */
alloclen = min(totallen, 65536u);
buffer = kmalloc(alloclen, GFP_NOIO);
@@ -1084,24 +1105,26 @@ static int usbat_flash_write_data(struct us_data *us,
return USB_STOR_TRANSPORT_ERROR;
do {
- // loop, never allocate or transfer more than 64k at once
- // (min(128k, 255*info->ssize) is the real limit)
+ /*
+ * loop, never allocate or transfer more than 64k at once
+ * (min(128k, 255*info->ssize) is the real limit)
+ */
len = min(totallen, alloclen);
thistime = (len / info->ssize) & 0xff;
- // Get the data from the transfer buffer
+ /* Get the data from the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
&sg_idx, &sg_offset, FROM_XFER_BUF);
- // ATAPI command 0x30 (WRITE SECTORS)
- usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30);
+ /* ATA command 0x30 (WRITE SECTORS) */
+ usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);
- // Write/execute ATAPI write command
+ /* Write/execute ATA write command */
result = usbat_multiple_write(us, registers, command, 7);
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
- // Write the data
+ /* Write the data */
result = usbat_write_blocks(us, buffer, len);
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
@@ -1172,42 +1195,44 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
srb->transfersize);
}
- // Since we only read in one block at a time, we have to create
- // a bounce buffer and move the data a piece at a time between the
- // bounce buffer and the actual transfer buffer.
+ /*
+ * Since we only read in one block at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ */
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
len = min(len, srb->request_bufflen);
buffer = kmalloc(len, GFP_NOIO);
- if (buffer == NULL) // bloody hell!
+ if (buffer == NULL) /* bloody hell! */
return USB_STOR_TRANSPORT_FAILED;
sector = short_pack(data[7+3], data[7+2]);
sector <<= 16;
sector |= short_pack(data[7+5], data[7+4]);
transferred = 0;
- sg_segment = 0; // for keeping track of where we are in
- sg_offset = 0; // the scatter/gather list
+ sg_segment = 0; /* for keeping track of where we are in */
+ sg_offset = 0; /* the scatter/gather list */
while (transferred != srb->request_bufflen) {
if (len > srb->request_bufflen - transferred)
len = srb->request_bufflen - transferred;
- data[3] = len&0xFF; // (cylL) = expected length (L)
- data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
+ data[3] = len&0xFF; /* (cylL) = expected length (L) */
+ data[4] = (len>>8)&0xFF; /* (cylH) = expected length (H) */
- // Fix up the SCSI command sector and num sectors
+ /* Fix up the SCSI command sector and num sectors */
- data[7+2] = MSB_of(sector>>16); // SCSI command sector
+ data[7+2] = MSB_of(sector>>16); /* SCSI command sector */
data[7+3] = LSB_of(sector>>16);
data[7+4] = MSB_of(sector&0xFFFF);
data[7+5] = LSB_of(sector&0xFFFF);
if (data[7+0] == GPCMD_READ_CD)
data[7+6] = 0;
- data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
- data[7+8] = LSB_of(len / srb->transfersize); // num sectors
+ data[7+7] = MSB_of(len / srb->transfersize); /* SCSI command */
+ data[7+8] = LSB_of(len / srb->transfersize); /* num sectors */
result = usbat_hp8200e_rw_block_test(us, USBAT_ATA,
registers, data, 19,
@@ -1220,16 +1245,16 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
break;
- // Store the data in the transfer buffer
+ /* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, srb,
&sg_segment, &sg_offset, TO_XFER_BUF);
- // Update the amount transferred and the sector number
+ /* Update the amount transferred and the sector number */
transferred += len;
sector += len / srb->transfersize;
- } // while transferred != srb->request_bufflen
+ } /* while transferred != srb->request_bufflen */
kfree(buffer);
return result;
@@ -1239,16 +1264,10 @@ static int usbat_select_and_test_registers(struct us_data *us)
{
int selector;
unsigned char *status = us->iobuf;
- unsigned char max_selector = 0xB0;
- if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
- max_selector = 0xA0;
-
- // try device = master, then device = slave.
- for (selector = 0xA0; selector <= max_selector; selector += 0x10) {
-
- if (usbat_get_device_type(us) == USBAT_DEV_HP8200 &&
- usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
+ /* try device = master, then device = slave. */
+ for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
+ if (usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -1307,7 +1326,7 @@ int init_usbat(struct us_data *us)
memset(us->extra, 0, sizeof(struct usbat_info));
info = (struct usbat_info *) (us->extra);
- // Enable peripheral control signals
+ /* Enable peripheral control signals */
rc = usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -1334,60 +1353,30 @@ int init_usbat(struct us_data *us)
US_DEBUGP("INIT 3\n");
- // At this point, we need to detect which device we are using
- if (usbat_set_transport(us, info))
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 4\n");
-
- if (usbat_get_device_type(us) == USBAT_DEV_HP8200) {
- msleep(250);
-
- // Write 0x80 to ISA port 0x3F
- rc = usbat_write(us, USBAT_ISA, 0x3F, 0x80);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 5\n");
-
- // Read ISA port 0x27
- rc = usbat_read(us, USBAT_ISA, 0x27, status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 6\n");
-
- rc = usbat_read_user_io(us, status);
- if (rc != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 7\n");
- }
-
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 8\n");
+ US_DEBUGP("INIT 4\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 9\n");
+ US_DEBUGP("INIT 5\n");
- // Enable peripheral control signals and card detect
+ /* Enable peripheral control signals and card detect */
rc = usbat_device_enable_cdt(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 10\n");
+ US_DEBUGP("INIT 6\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 11\n");
+ US_DEBUGP("INIT 7\n");
msleep(1400);
@@ -1395,13 +1384,19 @@ int init_usbat(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 12\n");
+ US_DEBUGP("INIT 8\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 13\n");
+ US_DEBUGP("INIT 9\n");
+
+ /* At this point, we need to detect which device we are using */
+ if (usbat_set_transport(us, info))
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUGP("INIT 10\n");
if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {
subcountH = 0x02;
@@ -1412,7 +1407,7 @@ int init_usbat(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 14\n");
+ US_DEBUGP("INIT 11\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -1447,10 +1442,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
- data[3] = len&0xFF; // (cylL) = expected length (L)
- data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
- data[5] = 0xB0; // (device sel) = slave
- data[6] = 0xA0; // (command) = ATA PACKET COMMAND
+ data[3] = len&0xFF; /* (cylL) = expected length (L) */
+ data[4] = (len>>8)&0xFF; /* (cylH) = expected length (H) */
+ data[5] = 0xB0; /* (device sel) = slave */
+ data[6] = 0xA0; /* (command) = ATA PACKET COMMAND */
for (i=7; i<19; i++) {
registers[i] = 0x10;
@@ -1499,13 +1494,15 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
return result;
}
- // Write the 12-byte command header.
-
- // If the command is BLANK then set the timer for 75 minutes.
- // Otherwise set it for 10 minutes.
-
- // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
- // AT SPEED 4 IS UNRELIABLE!!!
+ /*
+ * Write the 12-byte command header.
+ *
+ * If the command is BLANK then set the timer for 75 minutes.
+ * Otherwise set it for 10 minutes.
+ *
+ * NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
+ * AT SPEED 4 IS UNRELIABLE!!!
+ */
if ( (result = usbat_write_block(us,
USBAT_ATA, srb->cmnd, 12,
@@ -1514,19 +1511,18 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
return result;
}
- // If there is response data to be read in
- // then do it here.
+ /* If there is response data to be read in then do it here. */
if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
- // How many bytes to read in? Check cylL register
+ /* How many bytes to read in? Check cylL register */
if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) !=
USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR;
}
- if (len > 0xFF) { // need to read cylH also
+ if (len > 0xFF) { /* need to read cylH also */
len = *status;
if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
USB_STOR_XFER_GOOD) {
@@ -1589,13 +1585,16 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec
+ /* hard coded 512 byte sectors as per ATA spec */
+ info->ssize = 0x200;
US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
info->sectors, info->ssize);
- // build the reply
- // note: must return the sector number of the last sector,
- // *not* the total number of sectors
+ /*
+ * build the reply
+ * note: must return the sector number of the last sector,
+ * *not* the total number of sectors
+ */
((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
usb_stor_set_xfer_buf(ptr, 8, srb);
@@ -1619,7 +1618,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == READ_12) {
- // I don't think we'll ever see a READ_12 but support it anyway...
+ /*
+ * I don't think we'll ever see a READ_12 but support it anyway
+ */
block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
@@ -1641,7 +1642,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == WRITE_12) {
- // I don't think we'll ever see a WRITE_12 but support it anyway...
+ /*
+ * I don't think we'll ever see a WRITE_12 but support it anyway
+ */
block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
@@ -1678,8 +1681,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
- // sure. whatever. not like we can stop the user from popping
- // the media out of the device (no locking doors, etc)
+ /*
+ * sure. whatever. not like we can stop the user from popping
+ * the media out of the device (no locking doors, etc)
+ */
return USB_STOR_TRANSPORT_GOOD;
}
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 5b8e867e2ae5..25e7d8b340b8 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -55,8 +55,8 @@
#define USBAT_UIO_WRITE 0
/* Qualifier bits */
-#define USBAT_QUAL_FCQ 0x20 // full compare
-#define USBAT_QUAL_ALQ 0x10 // auto load subcount
+#define USBAT_QUAL_FCQ 0x20 /* full compare */
+#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */
/* USBAT Flash Media status types */
#define USBAT_FLASH_MEDIA_NONE 0
@@ -67,39 +67,39 @@
#define USBAT_FLASH_MEDIA_CHANGED 1
/* USBAT ATA registers */
-#define USBAT_ATA_DATA 0x10 // read/write data (R/W)
-#define USBAT_ATA_FEATURES 0x11 // set features (W)
-#define USBAT_ATA_ERROR 0x11 // error (R)
-#define USBAT_ATA_SECCNT 0x12 // sector count (R/W)
-#define USBAT_ATA_SECNUM 0x13 // sector number (R/W)
-#define USBAT_ATA_LBA_ME 0x14 // cylinder low (R/W)
-#define USBAT_ATA_LBA_HI 0x15 // cylinder high (R/W)
-#define USBAT_ATA_DEVICE 0x16 // head/device selection (R/W)
-#define USBAT_ATA_STATUS 0x17 // device status (R)
-#define USBAT_ATA_CMD 0x17 // device command (W)
-#define USBAT_ATA_ALTSTATUS 0x0E // status (no clear IRQ) (R)
+#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */
+#define USBAT_ATA_FEATURES 0x11 /* set features (W) */
+#define USBAT_ATA_ERROR 0x11 /* error (R) */
+#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */
+#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */
+#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */
+#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */
+#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */
+#define USBAT_ATA_STATUS 0x17 /* device status (R) */
+#define USBAT_ATA_CMD 0x17 /* device command (W) */
+#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */
/* USBAT User I/O Data registers */
-#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals
-#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only)
- // CDT = ACKD & !UI1 & !UI0
-#define USBAT_UIO_1 0x20 // I/O 1
-#define USBAT_UIO_0 0x10 // I/O 0
-#define USBAT_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode
-#define USBAT_UIO_UI1 0x04 // Input 1
-#define USBAT_UIO_UI0 0x02 // Input 0
-#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
+#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */
+#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */
+ /* CDT = ACKD & !UI1 & !UI0 */
+#define USBAT_UIO_1 0x20 /* I/O 1 */
+#define USBAT_UIO_0 0x10 /* I/O 0 */
+#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */
+#define USBAT_UIO_UI1 0x04 /* Input 1 */
+#define USBAT_UIO_UI0 0x02 /* Input 0 */
+#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
/* USBAT User I/O Enable registers */
-#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral
-#define USBAT_UIO_ACKD 0x40 // Enable Card Detect
-#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input
- // If ACKD=1, set OE1 to 1 also.
-#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input
-#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip
+#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */
+#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */
+#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */
+ /* If ACKD=1, set OE1 to 1 also. */
+#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */
+#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */
/* USBAT Features */
-#define USBAT_FEAT_ETEN 0x80 // External trigger enable
+#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */
#define USBAT_FEAT_U1 0x08
#define USBAT_FEAT_U0 0x04
#define USBAT_FEAT_ET1 0x02
@@ -112,12 +112,12 @@ struct usbat_info {
int devicetype;
/* Used for Flash readers only */
- unsigned long sectors; // total sector count
- unsigned long ssize; // sector size in bytes
+ unsigned long sectors; /* total sector count */
+ unsigned long ssize; /* sector size in bytes */
unsigned char sense_key;
- unsigned long sense_asc; // additional sense code
- unsigned long sense_ascq; // additional sense code qualifier
+ unsigned long sense_asc; /* additional sense code */
+ unsigned long sense_ascq; /* additional sense code qualifier */
};
#endif
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index e6b1c6cf07f2..7ca896a342e3 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -96,8 +96,8 @@
* or before the URB_ACTIVE bit was set. If so, it's essential to cancel
* the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
* is still set). Either way, the function must then wait for the URB to
- * finish. Note that because the URB_ASYNC_UNLINK flag is set, the URB can
- * still be in progress even after a call to usb_unlink_urb() returns.
+ * finish. Note that the URB can still be in progress even after a call to
+ * usb_unlink_urb() returns.
*
* The idea is that (1) once the ABORTING or DISCONNECTING bit is set,
* either the stop_transport() function or the submitting function
@@ -158,8 +158,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
* hasn't been mapped for DMA. Yes, this is clunky, but it's
* easier than always having the caller tell us whether the
* transfer buffer has already been mapped. */
- us->current_urb->transfer_flags =
- URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
+ us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
if (us->current_urb->transfer_buffer == us->iobuf)
us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
us->current_urb->transfer_dma = us->iobuf_dma;
@@ -611,7 +610,6 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned char old_sc_data_direction;
unsigned char old_cmd_len;
unsigned char old_cmnd[MAX_COMMAND_SIZE];
- unsigned long old_serial_number;
int old_resid;
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
@@ -638,31 +636,27 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* use the new buffer we have */
old_request_buffer = srb->request_buffer;
- srb->request_buffer = srb->sense_buffer;
+ srb->request_buffer = us->sensebuf;
/* set the buffer length for transfer */
old_request_bufflen = srb->request_bufflen;
- srb->request_bufflen = 18;
+ srb->request_bufflen = US_SENSE_SIZE;
/* set up for no scatter-gather use */
old_sg = srb->use_sg;
srb->use_sg = 0;
- /* change the serial number -- toggle the high bit*/
- old_serial_number = srb->serial_number;
- srb->serial_number ^= 0x80000000;
-
/* issue the auto-sense command */
old_resid = srb->resid;
srb->resid = 0;
temp_result = us->transport(us->srb, us);
/* let's clean up right away */
+ memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);
srb->resid = old_resid;
srb->request_buffer = old_request_buffer;
srb->request_bufflen = old_request_bufflen;
srb->use_sg = old_sg;
- srb->serial_number = old_serial_number;
srb->sc_data_direction = old_sc_data_direction;
srb->cmd_len = old_cmd_len;
memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
@@ -930,6 +924,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int result;
/* issue the command */
+ us->iobuf[0] = 0;
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
@@ -985,7 +980,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
- bcb->Tag = srb->serial_number;
+ bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG)
bcb->Lun |= srb->device->id << 4;
@@ -1074,7 +1069,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status);
- if (bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) {
+ if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 8d9e0663f8fe..0a362cc781ad 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -50,7 +50,7 @@
#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
#define US_PR_BULK 0x50 /* bulk only */
#ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
+#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index bd0ab3039bdd..9e926a8f2116 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -71,14 +71,31 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
- US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0),
+ US_SC_8070, US_PR_USBAT, init_usbat, 0),
UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
"HP",
"CD-Writer+ CD-4e",
- US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0),
+ US_SC_8070, US_PR_USBAT, init_usbat, 0),
#endif
+/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
+UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
+ "VIA Technologies Inc.",
+ "USB 2.0 Card Reader",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
+ * for USB floppies that need the SINGLE_LUN enforcement.
+ */
+UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,
+ "NEC",
+ "NEC USB UF000x",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
@@ -89,6 +106,20 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Stefan Werner <dustbln@gmx.de> */
+UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100,
+ "TrekStor",
+ "i.Beat Joy 2.0",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
+UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
+ "SMSC",
+ "FDC GOLD-2.30",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
@@ -96,6 +127,24 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+/*
+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
+ * The key does not actually break, but it returns zero sense which
+ * makes our SCSI stack to print confusing messages.
+ */
+UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
+ "USBest Technology", /* sold by Transcend */
+ "USB Mass Storage Device",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
+ "Neuros Audio",
+ "USB 2.0 HD 2.5",
+ US_SC_DEVICE, US_PR_BULK, NULL,
+ US_FL_NEED_OVERRIDE ),
+
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
@@ -202,6 +251,13 @@ UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
+/* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */
+UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999,
+ "LEICA",
+ "D-LUX Camera",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
+
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
*/
@@ -291,9 +347,9 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100,
#ifdef CONFIG_USB_STORAGE_USBAT
UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999,
- "SCM",
- "SCM USBAT-02",
- US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+ "Shuttle/SCM",
+ "USBAT-02",
+ US_SC_SCSI, US_PR_USBAT, init_usbat,
US_FL_SINGLE_LUN),
#endif
@@ -556,6 +612,16 @@ UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/*
+ * Reported by Tyson Vinson <lornoss@gmail.com>
+ * This particular productId is the iPod Nano
+ */
+UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999,
+ "Apple",
+ "iPod",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
@@ -660,6 +726,14 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005,
+ "Sandisk",
+ "ImageMate SDDR-05b",
+ US_SC_SCSI, US_PR_USBAT, init_usbat,
+ US_FL_SINGLE_LUN ),
+#endif
+
UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
"Sandisk",
"ImageMate SDDR-12",
@@ -682,7 +756,7 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
#endif
/* Reported by Eero Volotinen <eero@ping-viini.org> */
-UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0406, 0x0406,
+UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999,
"Freecom Technologies",
"FHD-Classic",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -929,6 +1003,18 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
US_FL_SINGLE_LUN ),
#endif
+/* Submitted by: Nick Sillik <n.sillik@temple.edu>
+ * Needed for OneTouch extension to usb-storage
+ *
+ */
+#ifdef CONFIG_USB_STORAGE_ONETOUCH
+ UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999,
+ "Maxtor",
+ "OneTouch External Harddrive",
+ US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+ 0),
+#endif
+
/* Submitted by Joris Struyve <joris@struyve.be> */
UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
"Medion",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 77e7fc258aa2..3847ebed2aa4 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -54,6 +54,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/kthread.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -90,7 +91,9 @@
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
#include "jumpshot.h"
#endif
-
+#ifdef CONFIG_USB_STORAGE_ONETOUCH
+#include "onetouch.h"
+#endif
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -109,11 +112,6 @@ static atomic_t total_threads = ATOMIC_INIT(0);
static DECLARE_COMPLETION(threads_gone);
-static int storage_probe(struct usb_interface *iface,
- const struct usb_device_id *id);
-
-static void storage_disconnect(struct usb_interface *iface);
-
/* The entries in this table, except for final ones here
* (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
* line for line with the entries of us_unsuaul_dev_list[].
@@ -231,13 +229,40 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
{ NULL }
};
-static struct usb_driver usb_storage_driver = {
- .owner = THIS_MODULE,
- .name = "usb-storage",
- .probe = storage_probe,
- .disconnect = storage_disconnect,
- .id_table = storage_usb_ids,
-};
+
+#ifdef CONFIG_PM /* Minimal support for suspend and resume */
+
+static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+
+ /* Wait until no command is running */
+ down(&us->dev_semaphore);
+
+ US_DEBUGP("%s\n", __FUNCTION__);
+ iface->dev.power.power_state.event = message.event;
+
+ /* When runtime PM is working, we'll set a flag to indicate
+ * whether we should autoresume when a SCSI request arrives. */
+
+ up(&us->dev_semaphore);
+ return 0;
+}
+
+static int storage_resume(struct usb_interface *iface)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+
+ down(&us->dev_semaphore);
+
+ US_DEBUGP("%s\n", __FUNCTION__);
+ iface->dev.power.power_state.event = PM_EVENT_ON;
+
+ up(&us->dev_semaphore);
+ return 0;
+}
+
+#endif /* CONFIG_PM */
/*
* fill_inquiry_response takes an unsigned char array (which must
@@ -286,22 +311,7 @@ static int usb_stor_control_thread(void * __us)
struct us_data *us = (struct us_data *)__us;
struct Scsi_Host *host = us_to_host(us);
- lock_kernel();
-
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources.
- */
- daemonize("usb-storage");
current->flags |= PF_NOFREEZE;
- unlock_kernel();
-
- /* acquire a reference to the host, so it won't be deallocated
- * until we're ready to exit */
- scsi_host_get(host);
-
- /* signal that we've started the thread */
- complete(&(us->notify));
for(;;) {
US_DEBUGP("*** thread sleeping.\n");
@@ -390,11 +400,16 @@ SkipForAbort:
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* the TIMED_OUT flag, not srb->result == DID_ABORT, because
- * a timeout/abort request might be received after all the
- * USB processing was complete. */
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))
+ * the timeout might have occurred after the command had
+ * already completed with a different result code. */
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
complete(&(us->notify));
+ /* Allow USB transfers to resume */
+ clear_bit(US_FLIDX_ABORTING, &us->flags);
+ clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+ }
+
/* finished working on this command */
us->srb = NULL;
scsi_unlock(host);
@@ -460,6 +475,12 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
US_DEBUGP("I/O buffer allocation failed\n");
return -ENOMEM;
}
+
+ us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
+ if (!us->sensebuf) {
+ US_DEBUGP("Sense buffer allocation failed\n");
+ return -ENOMEM;
+ }
return 0;
}
@@ -548,8 +569,8 @@ static int get_transport(struct us_data *us)
break;
#ifdef CONFIG_USB_STORAGE_USBAT
- case US_PR_SCM_ATAPI:
- us->transport_name = "SCM/ATAPI";
+ case US_PR_USBAT:
+ us->transport_name = "Shuttle USBAT";
us->transport = usbat_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 1;
@@ -733,6 +754,7 @@ static int get_pipes(struct us_data *us)
static int usb_stor_acquire_resources(struct us_data *us)
{
int p;
+ struct task_struct *th;
us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) {
@@ -740,38 +762,28 @@ static int usb_stor_acquire_resources(struct us_data *us)
return -ENOMEM;
}
- /* Lock the device while we carry out the next two operations */
- down(&us->dev_semaphore);
-
- /* For bulk-only devices, determine the max LUN value */
- if (us->protocol == US_PR_BULK) {
- p = usb_stor_Bulk_max_lun(us);
- if (p < 0) {
- up(&us->dev_semaphore);
- return p;
- }
- us->max_lun = p;
- }
-
/* Just before we start our control thread, initialize
* the device if it needs initialization */
- if (us->unusual_dev->initFunction)
- us->unusual_dev->initFunction(us);
-
- up(&us->dev_semaphore);
+ if (us->unusual_dev->initFunction) {
+ p = us->unusual_dev->initFunction(us);
+ if (p)
+ return p;
+ }
/* Start up our control thread */
- p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
- if (p < 0) {
+ th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+ if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start control thread\n");
- return p;
+ return PTR_ERR(th);
}
- us->pid = p;
- atomic_inc(&total_threads);
- /* Wait for the thread to start */
- wait_for_completion(&(us->notify));
+ /* Take a reference to the host for the control thread and
+ * count it among all the threads we have launched. Then
+ * start it up. */
+ scsi_host_get(us_to_host(us));
+ atomic_inc(&total_threads);
+ wake_up_process(th);
return 0;
}
@@ -786,6 +798,7 @@ static void usb_stor_release_resources(struct us_data *us)
* any more commands.
*/
US_DEBUGP("-- sending exit command to thread\n");
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
up(&us->sema);
/* Call the destructor routine, if it exists */
@@ -804,6 +817,8 @@ static void dissociate_dev(struct us_data *us)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
+ kfree(us->sensebuf);
+
/* Free the device-related DMA-mapped buffers */
if (us->cr)
usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
@@ -816,25 +831,53 @@ static void dissociate_dev(struct us_data *us)
usb_set_intfdata(us->pusb_intf, NULL);
}
-/* Thread to carry out delayed SCSI-device scanning */
-static int usb_stor_scan_thread(void * __us)
+/* First stage of disconnect processing: stop all commands and remove
+ * the host */
+static void quiesce_and_remove_host(struct us_data *us)
{
- struct us_data *us = (struct us_data *)__us;
+ /* Prevent new USB transfers, stop the current command, and
+ * interrupt a SCSI-scan or device-reset delay */
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
+ usb_stor_stop_transport(us);
+ wake_up(&us->delay_wait);
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources.
- */
- lock_kernel();
- daemonize("usb-stor-scan");
- unlock_kernel();
+ /* It doesn't matter if the SCSI-scanning thread is still running.
+ * The thread will exit when it sees the DISCONNECTING flag. */
- /* Acquire a reference to the host, so it won't be deallocated
- * until we're ready to exit */
- scsi_host_get(us_to_host(us));
+ /* Wait for the current command to finish, then remove the host */
+ down(&us->dev_semaphore);
+ up(&us->dev_semaphore);
+
+ /* queuecommand won't accept any new commands and the control
+ * thread won't execute a previously-queued command. If there
+ * is such a command pending, complete it with an error. */
+ if (us->srb) {
+ us->srb->result = DID_NO_CONNECT << 16;
+ scsi_lock(us_to_host(us));
+ us->srb->scsi_done(us->srb);
+ us->srb = NULL;
+ scsi_unlock(us_to_host(us));
+ }
+
+ /* Now we own no commands so it's safe to remove the SCSI host */
+ scsi_remove_host(us_to_host(us));
+}
+
+/* Second stage of disconnect processing: deallocate all resources */
+static void release_everything(struct us_data *us)
+{
+ usb_stor_release_resources(us);
+ dissociate_dev(us);
- /* Signal that we've started the thread */
- complete(&(us->notify));
+ /* Drop our reference to the host; the SCSI core will free it
+ * (and "us" along with it) when the refcount becomes 0. */
+ scsi_host_put(us_to_host(us));
+}
+
+/* Thread to carry out delayed SCSI-device scanning */
+static int usb_stor_scan_thread(void * __us)
+{
+ struct us_data *us = (struct us_data *)__us;
printk(KERN_DEBUG
"usb-storage: device found at %d\n", us->pusb_dev->devnum);
@@ -853,6 +896,14 @@ retry:
/* If the device is still connected, perform the scanning */
if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+
+ /* For bulk-only devices, determine the max LUN value */
+ if (us->protocol == US_PR_BULK &&
+ !(us->flags & US_FL_SINGLE_LUN)) {
+ down(&us->dev_semaphore);
+ us->max_lun = usb_stor_Bulk_max_lun(us);
+ up(&us->dev_semaphore);
+ }
scsi_scan_host(us_to_host(us));
printk(KERN_DEBUG "usb-storage: device scan complete\n");
@@ -872,6 +923,7 @@ static int storage_probe(struct usb_interface *intf,
struct us_data *us;
const int id_index = id - storage_usb_ids;
int result;
+ struct task_struct *th;
US_DEBUGP("USB Mass Storage device detected\n");
@@ -952,27 +1004,28 @@ static int storage_probe(struct usb_interface *intf,
}
/* Start up the thread for delayed SCSI-device scanning */
- result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM);
- if (result < 0) {
+ th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
+ if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
- scsi_remove_host(host);
+ quiesce_and_remove_host(us);
+ result = PTR_ERR(th);
goto BadDevice;
}
- atomic_inc(&total_threads);
- /* Wait for the thread to start */
- wait_for_completion(&(us->notify));
+ /* Take a reference to the host for the scanning thread and
+ * count it among all the threads we have launched. Then
+ * start it up. */
+ scsi_host_get(us_to_host(us));
+ atomic_inc(&total_threads);
+ wake_up_process(th);
return 0;
/* We come here if there are any problems */
BadDevice:
US_DEBUGP("storage_probe() failed\n");
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- usb_stor_release_resources(us);
- dissociate_dev(us);
- scsi_host_put(host);
+ release_everything(us);
return result;
}
@@ -982,34 +1035,26 @@ static void storage_disconnect(struct usb_interface *intf)
struct us_data *us = usb_get_intfdata(intf);
US_DEBUGP("storage_disconnect() called\n");
-
- /* Prevent new USB transfers, stop the current command, and
- * interrupt a SCSI-scan or device-reset delay */
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- usb_stor_stop_transport(us);
- wake_up(&us->delay_wait);
-
- /* It doesn't matter if the SCSI-scanning thread is still running.
- * The thread will exit when it sees the DISCONNECTING flag. */
-
- /* Wait for the current command to finish, then remove the host */
- down(&us->dev_semaphore);
- up(&us->dev_semaphore);
- scsi_remove_host(us_to_host(us));
-
- /* Wait for everything to become idle and release all our resources */
- usb_stor_release_resources(us);
- dissociate_dev(us);
-
- /* Drop our reference to the host; the SCSI core will free it
- * (and "us" along with it) when the refcount becomes 0. */
- scsi_host_put(us_to_host(us));
+ quiesce_and_remove_host(us);
+ release_everything(us);
}
/***********************************************************************
* Initialization and registration
***********************************************************************/
+static struct usb_driver usb_storage_driver = {
+ .owner = THIS_MODULE,
+ .name = "usb-storage",
+ .probe = storage_probe,
+ .disconnect = storage_disconnect,
+#ifdef CONFIG_PM
+ .suspend = storage_suspend,
+ .resume = storage_resume,
+#endif
+ .id_table = storage_usb_ids,
+};
+
static int __init usb_stor_init(void)
{
int retval;
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 625b7aa98074..98b09711a739 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -117,6 +117,7 @@ enum { US_DO_ALL_FLAGS };
*/
#define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */
+#define US_SENSE_SIZE 18 /* Size of the autosense data buffer */
typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
typedef int (*trans_reset)(struct us_data*);
@@ -158,15 +159,14 @@ struct us_data {
/* SCSI interfaces */
struct scsi_cmnd *srb; /* current srb */
-
- /* thread information */
- int pid; /* control thread */
+ unsigned int tag; /* current dCBWTag */
/* control and bulk communications data */
struct urb *current_urb; /* USB requests */
struct usb_ctrlrequest *cr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather req. */
unsigned char *iobuf; /* I/O buffer */
+ unsigned char *sensebuf; /* sense data buffer */
dma_addr_t cr_dma; /* buffer DMA addresses */
dma_addr_t iobuf_dma;
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 353f24d45bc1..6c3a53f8f26c 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -223,9 +223,8 @@ static struct file_operations skel_fops = {
* and to have the device registered with devfs and the driver core
*/
static struct usb_class_driver skel_class = {
- .name = "usb/skel%d",
+ .name = "skel%d",
.fops = &skel_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
.minor_base = USB_SKEL_MINOR_BASE,
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cde0ed097af6..7192b770bfb6 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -494,7 +494,7 @@ config FB_TGA
config FB_VESA
bool "VESA VGA graphics support"
- depends on (FB = y) && (X86 || X86_64)
+ depends on (FB = y) && X86
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -681,7 +681,6 @@ config FB_RIVA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports graphics boards with the nVidia Riva/Geforce
chips.
@@ -713,14 +712,13 @@ config FB_RIVA_DEBUG
config FB_I810
tristate "Intel 810/815 support (EXPERIMENTAL)"
- depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+ depends on FB && EXPERIMENTAL && PCI && X86_32
select AGP
select AGP_INTEL
select FB_MODE_HELPERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel 810
and 815 chipsets. Say Y if you have and plan to use such a board.
@@ -754,9 +752,16 @@ config FB_I810_GTF
If unsure, say N.
+config FB_I810_I2C
+ bool "Enable DDC Support"
+ depends on FB_I810 && FB_I810_GTF
+ select I2C
+ select I2C_ALGOBIT
+ help
+
config FB_INTEL
tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
- depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+ depends on FB && EXPERIMENTAL && PCI && X86_32
select AGP
select AGP_INTEL
select FB_MODE_HELPERS
@@ -960,8 +965,7 @@ config FB_RADEON
can be build either as modules or built-in.
There is a product page at
- <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
-
+ http://apps.ati.com/ATIcompare/
config FB_RADEON_I2C
bool "DDC/I2C for ATI Radeon support"
depends on FB_RADEON
@@ -1084,15 +1088,16 @@ config FB_SAVAGE_ACCEL
choose N here.
config FB_SIS
- tristate "SiS acceleration"
+ tristate "SiS/XGI display support"
depends on FB && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
help
- This is the frame buffer device driver for the SiS 300, 315 and
- 330 series VGA chipsets. Specs available at <http://www.sis.com>
+ 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.
+ Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
To compile this driver as a module, choose M here; the module
will be called sisfb.
@@ -1104,11 +1109,12 @@ config FB_SIS_300
Say Y here to support use of the SiS 300/305, 540, 630 and 730.
config FB_SIS_315
- bool "SiS 315/330 series support"
+ bool "SiS 315/330/340 series and XGI support"
depends on FB_SIS
help
- Say Y here to support use of the SiS 315 and 330 series
- (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760).
+ Say Y here to support use of the SiS 315, 330 and 340 series
+ (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
+ as XGI V3XT, V5, V8 and Z7.
config FB_NEOMAGIC
tristate "NeoMagic display support"
@@ -1180,6 +1186,32 @@ config FB_VOODOO1
Please read the <file:Documentation/fb/README-sstfb.txt> for supported
options and other important info support.
+config FB_CYBLA
+ tristate "Cyberblade/i1 support"
+ depends on FB && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select VIDEO_SELECT
+ ---help---
+ This driver is supposed to support the Trident Cyberblade/i1
+ graphics core integrated in the VIA VT8601A North Bridge,
+ also known as VIA Apollo PLE133.
+
+ Status:
+ - Developed, tested and working on EPIA 5000 and EPIA 800.
+ - Does work reliable on all systems with CRT/LCD connected to
+ normal VGA ports.
+ - Should work on systems that do use the internal LCD port, but
+ this is absolutely not tested.
+
+ Character imageblit, copyarea and rectangle fill are hw accelerated,
+ ypan scrolling is used by default.
+
+ Please do read <file:Documentation/fb/cyblafb/*>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cyblafb.
+
config FB_TRIDENT
tristate "Trident support"
depends on FB && PCI
@@ -1193,8 +1225,12 @@ config FB_TRIDENT
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.
@@ -1205,7 +1241,6 @@ config FB_TRIDENT_ACCEL
This will compile the Trident frame buffer device with
acceleration functions.
-
config FB_PM3
tristate "Permedia3 support"
depends on FB && PCI && BROKEN
@@ -1341,7 +1376,7 @@ config FB_HIT
config FB_PMAG_AA
bool "PMAG-AA TURBOchannel framebuffer support"
- depends on (FB = y) && MACH_DECSTATION && TC
+ depends on (FB = y) && TC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1352,7 +1387,7 @@ config FB_PMAG_AA
config FB_PMAG_BA
bool "PMAG-BA TURBOchannel framebuffer support"
- depends on (FB = y) && MACH_DECSTATION && TC
+ depends on (FB = y) && TC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1363,7 +1398,7 @@ config FB_PMAG_BA
config FB_PMAGB_B
bool "PMAGB-B TURBOchannel framebuffer support"
- depends on (FB = y) && MACH_DECSTATION && TC
+ depends on (FB = y) && TC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1375,7 +1410,7 @@ config FB_PMAGB_B
config FB_MAXINE
bool "Maxine (Personal DECstation) onboard framebuffer support"
- depends on (FB = y) && MACH_DECSTATION && TC
+ depends on (FB = y) && MACH_DECSTATION
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1484,6 +1519,30 @@ config FB_S1D13XXX
working with S1D13806). Product specs at
<http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+config FB_S3C2410
+ tristate "S3C2410 LCD framebuffer support"
+ depends on FB && ARCH_S3C2410
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Samsung
+ S3C2410 processor.
+
+ 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 s3c2410fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+config FB_S3C2410_DEBUG
+ bool "S3C2410 lcd debug messages"
+ depends on FB_S3C2410
+ help
+ Turn on debugging messages. Note that you can set/unset at run time
+ through sysfs
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b018df4e95c8..97c5d03ac8d9 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,7 +9,8 @@ obj-$(CONFIG_LOGO) += logo/
obj-$(CONFIG_SYSFS) += backlight/
obj-$(CONFIG_FB) += fb.o
-fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o
+fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+ modedb.o fbcvt.o
fb-objs := $(fb-y)
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
@@ -50,7 +51,8 @@ obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o
-obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
+obj-$(CONFIG_FB_CYBLA) += cyblafb.o
+obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_STI) += stifb.o
obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
@@ -84,7 +86,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_AU1100) += au1100fb.o fbgen.o
+obj-$(CONFIG_FB_AU1100) += au1100fb.o
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
@@ -92,6 +94,7 @@ obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
+obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index f02965f39501..9b6a39348f81 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -26,7 +26,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fb.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 321dbe91dc14..4fc93dc2b4d3 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <linux/list.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
@@ -504,14 +505,14 @@ static int clcdfb_remove(struct amba_device *dev)
static struct amba_id clcdfb_id_table[] = {
{
.id = 0x00041110,
- .mask = 0x000fffff,
+ .mask = 0x000ffffe,
},
{ 0, 0 },
};
static struct amba_driver clcd_driver = {
.drv = {
- .name = "clcd-pl110",
+ .name = "clcd-pl11x",
},
.probe = clcdfb_probe,
.remove = clcdfb_remove,
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index d28457e0c063..126daff1c848 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -47,6 +47,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/arcfb.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 7bc1d44d8814..e380ee8b0247 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -806,8 +806,8 @@ static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, stru
/* Very simple test to make sure it appeared */
if (BIOS_IN16(0) != 0xaa55) {
- printk(KERN_ERR "aty128fb: Invalid ROM signature %x should be 0xaa55\n",
- BIOS_IN16(0));
+ printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
+ " be 0xaa55\n", BIOS_IN16(0));
goto failed;
}
@@ -2323,17 +2323,16 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
* can properly take care of D3 ? Also, with swsusp, we
* know we'll be rebooted, ...
*/
-#ifdef CONFIG_PPC_PMAC
+#ifndef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
- if (state >= 3)
- state = 2;
+ return 0;
#endif /* CONFIG_PPC_PMAC */
- if (state != 2 || state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
printk(KERN_DEBUG "aty128fb: suspending...\n");
@@ -2367,7 +2366,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
* used dummy fb ops, 2.5 need proper support for this at the
* fbdev level
*/
- if (state == 2)
+ if (state.event != PM_EVENT_ON)
aty128_set_suspend(par, 1);
release_console_sem();
@@ -2382,12 +2381,11 @@ static int aty128_do_resume(struct pci_dev *pdev)
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
/* Wakeup chip */
- if (pdev->dev.power.power_state == 2)
- aty128_set_suspend(par, 0);
+ aty128_set_suspend(par, 0);
par->asleep = 0;
/* Restore display & engine */
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 8c42538dc8c1..037fe9d32fe3 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -911,20 +911,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
vdisplay = par->lcd_height;
#endif
- if(vdisplay < 400) {
- h_sync_pol = 1;
- v_sync_pol = 0;
- } else if(vdisplay < 480) {
- h_sync_pol = 0;
- v_sync_pol = 1;
- } else if(vdisplay < 768) {
- h_sync_pol = 0;
- v_sync_pol = 0;
- } else {
- h_sync_pol = 1;
- v_sync_pol = 1;
- }
-
v_disp--;
v_sync_strt--;
v_sync_end--;
@@ -2022,17 +2008,16 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef CONFIG_PPC_PMAC
+#ifndef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
- if (state >= 3)
- state = 2;
+ return 0;
#endif /* CONFIG_PPC_PMAC */
- if (state != 2 || state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
acquire_console_sem();
@@ -2071,12 +2056,12 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
acquire_console_sem();
- if (pdev->dev.power.power_state == 2)
+ if (pdev->dev.power.power_state.event == 2)
aty_power_mgmt(0, par);
par->asleep = 0;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index e7e8b52014c3..8a24a66d9ba8 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -329,8 +329,9 @@ static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev
/* Very simple test to make sure it appeared */
if (BIOS_IN16(0) != 0xaa55) {
- printk(KERN_ERR "radeonfb (%s): Invalid ROM signature %x should be"
- "0xaa55\n", pci_name(rinfo->pdev), BIOS_IN16(0));
+ printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
+ "should be 0xaa55\n",
+ pci_name(rinfo->pdev), BIOS_IN16(0));
goto failed;
}
/* Look for the PCI data to check the ROM type */
@@ -474,7 +475,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
*/
/* Flush PCI buffers ? */
- tmp = INREG(DEVICE_ID);
+ tmp = INREG16(DEVICE_ID);
local_irq_disable();
@@ -2312,19 +2313,27 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
/* request the mem regions */
- ret = pci_request_regions(pdev, "radeonfb");
+ ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
if (ret < 0) {
- printk( KERN_ERR "radeonfb (%s): cannot reserve PCI regions."
- " Someone already got them?\n", pci_name(rinfo->pdev));
+ printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
+ pci_name(rinfo->pdev));
goto err_release_fb;
}
+ ret = pci_request_region(pdev, 2, "radeonfb mmio");
+ if (ret < 0) {
+ printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
+ pci_name(rinfo->pdev));
+ goto err_release_pci0;
+ }
+
/* map the regions */
rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
if (!rinfo->mmio_base) {
- printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", pci_name(rinfo->pdev));
+ printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
+ pci_name(rinfo->pdev));
ret = -EIO;
- goto err_release_pci;
+ goto err_release_pci2;
}
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
@@ -2499,10 +2508,12 @@ err_unmap_rom:
if (rinfo->bios_seg)
radeon_unmap_ROM(rinfo, pdev);
iounmap(rinfo->mmio_base);
-err_release_pci:
- pci_release_regions(pdev);
+err_release_pci2:
+ pci_release_region(pdev, 2);
+err_release_pci0:
+ pci_release_region(pdev, 0);
err_release_fb:
- framebuffer_release(info);
+ framebuffer_release(info);
err_disable:
pci_disable_device(pdev);
err_out:
@@ -2548,7 +2559,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
iounmap(rinfo->mmio_base);
iounmap(rinfo->fb_base);
- pci_release_regions(pdev);
+ pci_release_region(pdev, 2);
+ pci_release_region(pdev, 0);
kfree(rinfo->mon1_EDID);
kfree(rinfo->mon2_EDID);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 762244164c81..a9d0414e4655 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -75,7 +75,7 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_ATI;
+ chan->adapter.id = I2C_HW_B_RADEON;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->rinfo->pdev->dev;
chan->algo.setsda = radeon_gpio_setsda;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 98352af39325..097d668c4fe5 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -62,9 +62,9 @@ static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
OUTPLL(pllSCLK_CNTL, tmp);
return;
}
- /* RV350 (M10) */
+ /* RV350 (M10/M11) */
if (rinfo->family == CHIP_FAMILY_RV350) {
- /* for RV350/M10, no delays are required. */
+ /* for RV350/M10/M11, no delays are required. */
tmp = INPLL(pllSCLK_CNTL2);
tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
SCLK_CNTL2__R300_FORCE_GA |
@@ -248,7 +248,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
return;
}
- /* M10 */
+ /* M10/M11 */
if (rinfo->family == CHIP_FAMILY_RV350) {
tmp = INPLL(pllSCLK_CNTL2);
tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
@@ -1155,7 +1155,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
- /* This is the code for the Aluminium PowerBooks M10 */
+ /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
if (rinfo->family == CHIP_FAMILY_RV350) {
u32 sdram_mode_reg = rinfo->save_regs[35];
static u32 default_mrtable[] =
@@ -2526,18 +2526,18 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
struct radeonfb_info *rinfo = info->par;
int i;
- if (state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n",
- pci_name(pdev), state);
+ pci_name(pdev), state.event);
/* For suspend-to-disk, we cheat here. We don't suspend anything and
* let fbcon continue drawing until we are all set. That shouldn't
* really cause any problem at this point, provided that the wakeup
* code knows that any state in memory may not match the HW
*/
- if (state != PM_SUSPEND_MEM)
+ if (state.event == PM_EVENT_FREEZE)
goto done;
acquire_console_sem();
@@ -2616,7 +2616,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
struct radeonfb_info *rinfo = info->par;
int rc = 0;
- if (pdev->dev.power.power_state == 0)
+ if (pdev->dev.power.power_state.event == PM_EVENT_ON)
return 0;
if (rinfo->no_schedule) {
@@ -2626,7 +2626,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
acquire_console_sem();
printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
- pci_name(pdev), pdev->dev.power.power_state);
+ pci_name(pdev), pdev->dev.power.power_state.event);
if (pci_enable_device(pdev)) {
@@ -2637,7 +2637,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
}
pci_set_master(pdev);
- if (pdev->dev.power.power_state == PM_SUSPEND_MEM) {
+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
/* Wakeup chip. Check from config space if we were powered off
* (todo: additionally, check CLK_PIN_CNTL too)
*/
@@ -2741,9 +2741,11 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
rinfo->pm_mode |= radeon_pm_d2;
/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
- * in some desktop G4s), and Via (M9+ chip on iBook G4)
+ * in some desktop G4s), Via (M9+ chip on iBook G4) and
+ * Snowy (M11 chip on iBook G4 manufactured after July 2005)
*/
- if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) {
+ if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") ||
+ !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) {
rinfo->reinit_func = radeon_reinitialize_M10;
rinfo->pm_mode |= radeon_pm_off;
}
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 659bc9f62244..01b8b2f78514 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -395,6 +395,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
#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)
#define INREG(addr) readl((rinfo->mmio_base)+addr)
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c
index 92643af12581..a085cbf74ecb 100644
--- a/drivers/video/aty/xlinit.c
+++ b/drivers/video/aty/xlinit.c
@@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info)
const struct xl_card_cfg_t * card = &card_cfg[xl_card];
struct atyfb_par *par = (struct atyfb_par *) info->par;
union aty_pll pll;
- int i, err;
+ int err;
u32 temp;
aty_st_8(CONFIG_STAT0, 0x85, par);
@@ -252,9 +252,14 @@ int atyfb_xl_init(struct fb_info *info)
aty_st_le32(0xEC, 0x00000000, par);
aty_st_le32(0xFC, 0x00000000, par);
- for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) {
- aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
+#if defined (CONFIG_FB_ATY_GENERIC_LCD)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++)
+ aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
}
+#endif
aty_st_le16(CONFIG_STAT0, 0x00A4, par);
mdelay(10);
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index b6fe30c3ad62..a5129806172f 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -2,6 +2,11 @@
* BRIEF MODULE DESCRIPTION
* Au1100 LCD Driver.
*
+ * Rewritten for 2.6 by Embedded Alley Solutions
+ * <source@embeddedalley.com>, based on submissions by
+ * Karl Lessard <klessard@sunrisetelecom.com>
+ * <c.pellegrin@exadron.com>
+ *
* Copyright 2002 MontaVista Software
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
@@ -33,298 +38,253 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
-#include <asm/au1000.h>
-#include <asm/pb1100.h>
-#include "au1100fb.h"
+#include <asm/mach-au1x00/au1000.h>
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb2.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
+#define DEBUG 0
+
+#include "au1100fb.h"
/*
* Sanity check. If this is a new Au1100 based board, search for
* the PB1100 ifdefs to make sure you modify the code accordingly.
*/
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3)
+#if defined(CONFIG_MIPS_PB1100)
+ #include <asm/mach-pb1x00/pb1100.h>
+#elif defined(CONFIG_MIPS_DB1100)
+ #include <asm/mach-db1x00/db1x00.h>
#else
-error Unknown Au1100 board
+ #error "Unknown Au1100 board, Au1100 FB driver not supported"
#endif
-#define CMAPSIZE 16
-
-static int my_lcd_index; /* default is zero */
-struct known_lcd_panels *p_lcd;
-AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR;
-
-struct au1100fb_info {
- struct fb_info_gen gen;
- unsigned long fb_virt_start;
- unsigned long fb_size;
- unsigned long fb_phys;
- int mmaped;
- int nohwcursor;
+#define DRIVER_NAME "au1100fb"
+#define DRIVER_DESC "LCD controller driver for AU1100 processors"
- struct { unsigned red, green, blue, pad; } palette[256];
+#define to_au1100fb_device(_info) \
+ (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
-#if defined(FBCON_HAS_CFB16)
- u16 fbcon_cmap16[16];
-#endif
+/* Bitfields format supported by the controller. Note that the order of formats
+ * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the
+ * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF]
+ */
+struct fb_bitfield rgb_bitfields[][4] =
+{
+ /* Red, Green, Blue, Transp */
+ { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+ { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+ /* The last is used to describe 12bpp format */
+ { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
};
-
-struct au1100fb_par {
- struct fb_var_screeninfo var;
-
- int line_length; // in bytes
- int cmap_len; // color-map length
+static struct fb_fix_screeninfo au1100fb_fix __initdata = {
+ .id = "AU1100 FB",
+ .xpanstep = 1,
+ .ypanstep = 1,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .accel = FB_ACCEL_NONE,
};
-
-static struct au1100fb_info fb_info;
-static struct au1100fb_par current_par;
-static struct display disp;
-
-int au1100fb_init(void);
-void au1100fb_setup(char *options, int *ints);
-static int au1100fb_mmap(struct fb_info *fb, struct file *file,
- struct vm_area_struct *vma);
-static int au1100_blank(int blank_mode, struct fb_info_gen *info);
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info);
-
-void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
-
-static struct fb_ops au1100fb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = fbgen_get_fix,
- .fb_get_var = fbgen_get_var,
- .fb_set_var = fbgen_set_var,
- .fb_get_cmap = fbgen_get_cmap,
- .fb_set_cmap = fbgen_set_cmap,
- .fb_pan_display = fbgen_pan_display,
- .fb_ioctl = au1100fb_ioctl,
- .fb_mmap = au1100fb_mmap,
+static struct fb_var_screeninfo au1100fb_var __initdata = {
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .vmode = FB_VMODE_NONINTERLACED,
};
-static void au1100_detect(void)
-{
- /*
- * This function should detect the current video mode settings
- * and store it as the default video mode
- */
+static struct au1100fb_drv_info drv_info;
- /*
- * Yeh, well, we're not going to change any settings so we're
- * always stuck with the default ...
+/*
+ * Set hardware with var settings. This will enable the controller with a specific
+ * mode, normally validated with the fb_check_var method
*/
-
-}
-
-static int au1100_encode_fix(struct fb_fix_screeninfo *fix,
- const void *_par, struct fb_info_gen *_info)
+int au1100fb_setmode(struct au1100fb_device *fbdev)
{
- struct au1100fb_info *info = (struct au1100fb_info *) _info;
- struct au1100fb_par *par = (struct au1100fb_par *) _par;
- struct fb_var_screeninfo *var = &par->var;
-
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
- fix->smem_start = info->fb_phys;
- fix->smem_len = info->fb_size;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = (var->bits_per_pixel == 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- fix->ywrapstep = 0;
- fix->xpanstep = 1;
- fix->ypanstep = 1;
- fix->line_length = current_par.line_length;
- return 0;
-}
+ struct fb_info *info = &fbdev->info;
+ u32 words;
+ int index;
-static void set_color_bitfields(struct fb_var_screeninfo *var)
-{
- switch (var->bits_per_pixel) {
- case 8:
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case 16: /* RGB 565 */
- 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;
- break;
+ if (!fbdev)
+ return -EINVAL;
+
+ /* Update var-dependent FB info */
+ if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) {
+ if (info->var.bits_per_pixel <= 8) {
+ /* palettized */
+ info->var.red.offset = 0;
+ info->var.red.length = info->var.bits_per_pixel;
+ info->var.red.msb_right = 0;
+
+ info->var.green.offset = 0;
+ info->var.green.length = info->var.bits_per_pixel;
+ info->var.green.msb_right = 0;
+
+ info->var.blue.offset = 0;
+ info->var.blue.length = info->var.bits_per_pixel;
+ info->var.blue.msb_right = 0;
+
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ info->var.transp.msb_right = 0;
+
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ info->fix.line_length = info->var.xres_virtual /
+ (8/info->var.bits_per_pixel);
+ } else {
+ /* non-palettized */
+ index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT;
+ info->var.red = rgb_bitfields[index][0];
+ info->var.green = rgb_bitfields[index][1];
+ info->var.blue = rgb_bitfields[index][2];
+ info->var.transp = rgb_bitfields[index][3];
+
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */
+ }
+ } else {
+ /* mono */
+ info->fix.visual = FB_VISUAL_MONO10;
+ info->fix.line_length = info->var.xres_virtual / 8;
}
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
-}
+ info->screen_size = info->fix.line_length * info->var.yres_virtual;
-static int au1100_decode_var(const struct fb_var_screeninfo *var,
- void *_par, struct fb_info_gen *_info)
-{
+ /* Determine BPP mode and format */
+ fbdev->regs->lcd_control = fbdev->panel->control_base |
+ ((info->var.rotate/90) << LCD_CONTROL_SM_BIT);
- struct au1100fb_par *par = (struct au1100fb_par *)_par;
+ fbdev->regs->lcd_intenable = 0;
+ fbdev->regs->lcd_intstatus = 0;
- /*
- * Don't allow setting any of these yet: xres and yres don't
- * make sense for LCD panels.
- */
- if (var->xres != p_lcd->xres ||
- var->yres != p_lcd->yres ||
- var->xres != p_lcd->xres ||
- var->yres != p_lcd->yres) {
- return -EINVAL;
- }
- if(var->bits_per_pixel != p_lcd->bpp) {
- return -EINVAL;
- }
+ fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
- memset(par, 0, sizeof(struct au1100fb_par));
- par->var = *var;
-
- /* FIXME */
- switch (var->bits_per_pixel) {
- case 8:
- par->var.bits_per_pixel = 8;
- break;
- case 16:
- par->var.bits_per_pixel = 16;
- break;
- default:
- printk("color depth %d bpp not supported\n",
- var->bits_per_pixel);
- return -EINVAL;
+ fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
+
+ fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
+ fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys);
+
+ if (panel_is_dual(fbdev->panel)) {
+ /* Second panel display seconf half of screen if possible,
+ * otherwise display the same as the first panel */
+ if (info->var.yres_virtual >= (info->var.yres << 1)) {
+ fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys +
+ (info->fix.line_length *
+ (info->var.yres_virtual >> 1)));
+ } else {
+ fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys);
+ }
}
- set_color_bitfields(&par->var);
- par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
- return 0;
-}
-static int au1100_encode_var(struct fb_var_screeninfo *var,
- const void *par, struct fb_info_gen *_info)
-{
+ words = info->fix.line_length / sizeof(u32);
+ if (!info->var.rotate || (info->var.rotate == 180)) {
+ words *= info->var.yres_virtual;
+ if (info->var.rotate /* 180 */) {
+ words -= (words % 8); /* should be divisable by 8 */
+ }
+ }
+ fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words);
- *var = ((struct au1100fb_par *)par)->var;
- return 0;
-}
+ fbdev->regs->lcd_pwmdiv = 0;
+ fbdev->regs->lcd_pwmhi = 0;
-static void
-au1100_get_par(void *_par, struct fb_info_gen *_info)
-{
- *(struct au1100fb_par *)_par = current_par;
-}
+ /* Resume controller */
+ fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-static void au1100_set_par(const void *par, struct fb_info_gen *info)
-{
- /* nothing to do: we don't change any settings */
+ return 0;
}
-static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *info)
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
{
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+ u32 *palette = fbdev->regs->lcd_pallettebase;
+ u32 value;
- struct au1100fb_info* i = (struct au1100fb_info*)info;
-
- if (regno > 255)
- return 1;
+ if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
+ return -EINVAL;
- *red = i->palette[regno].red;
- *green = i->palette[regno].green;
- *blue = i->palette[regno].blue;
- *transp = 0;
+ if (fbi->var.grayscale) {
+ /* Convert color to grayscale */
+ red = green = blue =
+ (19595 * red + 38470 * green + 7471 * blue) >> 16;
+ }
- return 0;
-}
+ if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+ /* Place color in the pseudopalette */
+ if (regno > 16)
+ return -EINVAL;
-static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct au1100fb_info* i = (struct au1100fb_info *)info;
- u32 rgbcol;
-
- if (regno > 255)
- return 1;
-
- i->palette[regno].red = red;
- i->palette[regno].green = green;
- i->palette[regno].blue = blue;
-
- switch(p_lcd->bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- red >>= 10;
- green >>= 10;
- blue >>= 10;
- p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) |
- ((green&0x3f)<<5) | ((red&0x1f)<<11);
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- i->fbcon_cmap16[regno] =
- ((red & 0xf800) >> 0) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11);
- break;
-#endif
- default:
- break;
+ palette = (u32*)fbi->pseudo_palette;
+
+ red >>= (16 - fbi->var.red.length);
+ green >>= (16 - fbi->var.green.length);
+ blue >>= (16 - fbi->var.blue.length);
+
+ value = (red << fbi->var.red.offset) |
+ (green << fbi->var.green.offset)|
+ (blue << fbi->var.blue.offset);
+ value &= 0xFFFF;
+
+ } else if (panel_is_active(fbdev->panel)) {
+ /* COLOR TFT PALLETTIZED (use RGB 565) */
+ value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F);
+ value &= 0xFFFF;
+
+ } else if (panel_is_color(fbdev->panel)) {
+ /* COLOR STN MODE */
+ value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) |
+ ((green >> 8) & 0x00F0) |
+ (((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00);
+ value &= 0xFFF;
+ } else {
+ /* MONOCHROME MODE */
+ value = (green >> 12) & 0x000F;
+ value &= 0xF;
}
+ palette[regno] = value;
+
return 0;
}
-
-static int au1100_blank(int blank_mode, struct fb_info_gen *_info)
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
{
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+ print_dbg("fb_blank %d %p", blank_mode, fbi);
switch (blank_mode) {
+
case VESA_NO_BLANKING:
- /* turn on panel */
- //printk("turn on panel\n");
+ /* Turn on panel */
+ fbdev->regs->lcd_control |= LCD_CONTROL_GO;
#ifdef CONFIG_MIPS_PB1100
- p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
- au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
+ if (drv_info.panel_idx == 1) {
+ au_writew(au_readw(PB1100_G_CONTROL)
+ | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
PB1100_G_CONTROL);
-#endif
-#ifdef CONFIG_MIPS_HYDROGEN3
- /* Turn controller & power supply on, GPIO213 */
- au_writel(0x20002000, 0xB1700008);
- au_writel(0x00040000, 0xB1900108);
- au_writel(0x01000100, 0xB1700008);
+ }
#endif
au_sync();
break;
@@ -332,12 +292,14 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info)
case VESA_VSYNC_SUSPEND:
case VESA_HSYNC_SUSPEND:
case VESA_POWERDOWN:
- /* turn off panel */
- //printk("turn off panel\n");
+ /* Turn off panel */
+ fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
#ifdef CONFIG_MIPS_PB1100
- au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight,
+ if (drv_info.panel_idx == 1) {
+ au_writew(au_readw(PB1100_G_CONTROL)
+ & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
PB1100_G_CONTROL);
- p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO;
+ }
#endif
au_sync();
break;
@@ -348,49 +310,87 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info)
return 0;
}
-static void au1100_set_disp(const void *unused, struct display *disp,
- struct fb_info_gen *info)
+/* fb_pan_display
+ * Pan display in x and/or y as specified
+ */
+int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
{
- disp->screen_base = (char *)fb_info.fb_virt_start;
-
- switch (disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- disp->dispsw = &fbcon_cfb8;
- if (fb_info.nohwcursor)
- fbcon_cfb8.cursor = au1100_nocursor;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = fb_info.fbcon_cmap16;
- if (fb_info.nohwcursor)
- fbcon_cfb16.cursor = au1100_nocursor;
- break;
-#endif
- default:
- disp->dispsw = &fbcon_dummy;
- disp->dispsw_data = NULL;
- break;
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+ int dy;
+
+ print_dbg("fb_pan_display %p %p", var, fbi);
+
+ if (!var || !fbdev) {
+ return -EINVAL;
+ }
+
+ if (var->xoffset - fbi->var.xoffset) {
+ /* No support for X panning for now! */
+ return -EINVAL;
+ }
+
+ print_dbg("fb_pan_display 2 %p %p", var, fbi);
+ dy = var->yoffset - fbi->var.yoffset;
+ if (dy) {
+
+ u32 dmaaddr;
+
+ print_dbg("Panning screen of %d lines", dy);
+
+ dmaaddr = fbdev->regs->lcd_dmaaddr0;
+ dmaaddr += (fbi->fix.line_length * dy);
+
+ /* TODO: Wait for current frame to finished */
+ fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+
+ if (panel_is_dual(fbdev->panel)) {
+ dmaaddr = fbdev->regs->lcd_dmaaddr1;
+ dmaaddr += (fbi->fix.line_length * dy);
+ fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+ }
+ }
+ print_dbg("fb_pan_display 3 %p %p", var, fbi);
+
+ return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
+{
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+ print_dbg("fb_rotate %p %d", fbi, angle);
+
+ if (fbdev && (angle > 0) && !(angle % 90)) {
+
+ fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+
+ fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK);
+ fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT);
+
+ fbdev->regs->lcd_control |= LCD_CONTROL_GO;
}
}
-static int
-au1100fb_mmap(struct fb_info *_fb,
- struct file *file,
- struct vm_area_struct *vma)
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap method mainly
+ * to allow the use of the TLB streaming flag (CCA=6)
+ */
+int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma)
{
+ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
unsigned int len;
unsigned long start=0, off;
- struct au1100fb_info *fb = (struct au1100fb_info *)_fb;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
return -EINVAL;
}
- start = fb_info.fb_phys & PAGE_MASK;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size);
+ start = fbdev->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
off = vma->vm_pgoff << PAGE_SHIFT;
@@ -401,276 +401,309 @@ au1100fb_mmap(struct fb_info *_fb,
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
- pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
- //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
- /* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO;
- if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ if (io_remap_page_range(vma, vma->vm_start, off,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
return -EAGAIN;
}
- fb->mmaped = 1;
return 0;
}
-int au1100_pan_display(const struct fb_var_screeninfo *var,
- struct fb_info_gen *info)
+static struct fb_ops au1100fb_ops =
{
- return 0;
-}
+ .owner = THIS_MODULE,
+ .fb_setcolreg = au1100fb_fb_setcolreg,
+ .fb_blank = au1100fb_fb_blank,
+ .fb_pan_display = au1100fb_fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_rotate = au1100fb_fb_rotate,
+ .fb_mmap = au1100fb_fb_mmap,
+};
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info)
-{
- /* nothing to do yet */
- return -EINVAL;
-}
-static struct fbgen_hwswitch au1100_switch = {
- au1100_detect,
- au1100_encode_fix,
- au1100_decode_var,
- au1100_encode_var,
- au1100_get_par,
- au1100_set_par,
- au1100_getcolreg,
- au1100_setcolreg,
- au1100_pan_display,
- au1100_blank,
- au1100_set_disp
-};
+/*-------------------------------------------------------------------------*/
+/* AU1100 LCD controller device driver */
-int au1100_setmode(void)
+int au1100fb_drv_probe(struct device *dev)
{
- int words;
-
- /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/
- switch (p_lcd->mode_control & LCD_CONTROL_SM)
- {
- case LCD_CONTROL_SM_0:
- case LCD_CONTROL_SM_180:
- words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32;
- break;
- case LCD_CONTROL_SM_90:
- case LCD_CONTROL_SM_270:
- /* is this correct? */
- words = (p_lcd->xres * p_lcd->bpp) / 8;
- break;
- default:
- printk("mode_control reg not initialized\n");
+ struct au1100fb_device *fbdev = NULL;
+ struct resource *regs_res;
+ unsigned long page;
+ u32 sys_clksrc;
+
+ if (!dev)
return -EINVAL;
+
+ /* Allocate new device private */
+ if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
+ print_err("fail to allocate device private record");
+ return -ENOMEM;
}
+ memset((void*)fbdev, 0, sizeof(struct au1100fb_device));
- /*
- * Setup LCD controller
- */
+ fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
- p_lcd_reg->lcd_control = p_lcd->mode_control;
- p_lcd_reg->lcd_intstatus = 0;
- p_lcd_reg->lcd_intenable = 0;
- p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming;
- p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming;
- p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol;
- p_lcd_reg->lcd_words = words - 1;
- p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys;
+ dev_set_drvdata(dev, (void*)fbdev);
- /* turn on panel */
-#ifdef CONFIG_MIPS_PB1100
- au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
- PB1100_G_CONTROL);
-#endif
-#ifdef CONFIG_MIPS_HYDROGEN3
- /* Turn controller & power supply on, GPIO213 */
- au_writel(0x20002000, 0xB1700008);
- au_writel(0x00040000, 0xB1900108);
- au_writel(0x01000100, 0xB1700008);
-#endif
+ /* Allocate region for our registers and map them */
+ if (!(regs_res = platform_get_resource(to_platform_device(dev),
+ IORESOURCE_MEM, 0))) {
+ print_err("fail to retrieve registers resource");
+ return -EFAULT;
+ }
- p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
+ au1100fb_fix.mmio_start = regs_res->start;
+ au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1;
- return 0;
-}
+ if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
+ DRIVER_NAME)) {
+ print_err("fail to lock memory region at 0x%08x",
+ au1100fb_fix.mmio_start);
+ return -EBUSY;
+ }
+ fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start);
-int __init au1100fb_init(void)
-{
- uint32 sys_clksrc;
- unsigned long page;
+ print_dbg("Register memory map at %p", fbdev->regs);
+ print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
- /*
- * Get the panel information/display mode and update the registry
- */
- p_lcd = &panels[my_lcd_index];
-
- switch (p_lcd->mode_control & LCD_CONTROL_SM)
- {
- case LCD_CONTROL_SM_0:
- case LCD_CONTROL_SM_180:
- p_lcd->xres =
- (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
- p_lcd->yres =
- (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
- break;
- case LCD_CONTROL_SM_90:
- case LCD_CONTROL_SM_270:
- p_lcd->yres =
- (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
- p_lcd->xres =
- (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
- break;
- }
- /*
- * Panel dimensions x bpp must be divisible by 32
- */
- if (((p_lcd->yres * p_lcd->bpp) % 32) != 0)
- printk("VERT %% 32\n");
- if (((p_lcd->xres * p_lcd->bpp) % 32) != 0)
- printk("HORZ %% 32\n");
- /*
- * Allocate LCD framebuffer from system memory
- */
- fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8;
-
- current_par.var.xres = p_lcd->xres;
- current_par.var.xres_virtual = p_lcd->xres;
- current_par.var.yres = p_lcd->yres;
- current_par.var.yres_virtual = p_lcd->yres;
- current_par.var.bits_per_pixel = p_lcd->bpp;
-
- /* FIX!!! only works for 8/16 bpp */
- current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */
- fb_info.fb_virt_start = (unsigned long )
- __get_free_pages(GFP_ATOMIC | GFP_DMA,
- get_order(fb_info.fb_size + 0x1000));
- if (!fb_info.fb_virt_start) {
- printk("Unable to allocate fb memory\n");
+ /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
+ fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
+ (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
+
+ fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ &fbdev->fb_phys, GFP_KERNEL);
+ if (!fbdev->fb_mem) {
+ print_err("fail to allocate frambuffer (size: %dK))",
+ fbdev->fb_len / 1024);
return -ENOMEM;
}
- fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start);
+
+ au1100fb_fix.smem_start = fbdev->fb_phys;
+ au1100fb_fix.smem_len = fbdev->fb_len;
/*
* Set page reserved so that mmap will work. This is necessary
* since we'll be remapping normal memory.
*/
- for (page = fb_info.fb_virt_start;
- page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size);
+ for (page = (unsigned long)fbdev->fb_mem;
+ page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
page += PAGE_SIZE) {
+#if CONFIG_DMA_NONCOHERENT
+ SetPageReserved(virt_to_page(CAC_ADDR(page)));
+#else
SetPageReserved(virt_to_page(page));
+#endif
}
- memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
-
- /* set freqctrl now to allow more time to stabilize */
- /* zero-out out LCD bits */
- sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0;
- sys_clksrc |= p_lcd->mode_toyclksrc;
- au_writel(sys_clksrc, SYS_CLKSRC);
-
- /* FIXME add check to make sure auxpll is what is expected! */
- au1100_setmode();
-
- fb_info.gen.parsize = sizeof(struct au1100fb_par);
- fb_info.gen.fbhw = &au1100_switch;
-
- strcpy(fb_info.gen.info.modename, "Au1100 LCD");
- fb_info.gen.info.changevar = NULL;
- fb_info.gen.info.node = -1;
-
- fb_info.gen.info.fbops = &au1100fb_ops;
- fb_info.gen.info.disp = &disp;
- fb_info.gen.info.switch_con = &fbgen_switch;
- fb_info.gen.info.updatevar = &fbgen_update_var;
- fb_info.gen.info.blank = &fbgen_blank;
- fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-
- /* This should give a reasonable default video mode */
- fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
- fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
- fbgen_set_disp(-1, &fb_info.gen);
- fbgen_install_cmap(0, &fb_info.gen);
- if (register_framebuffer(&fb_info.gen.info) < 0)
- return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- GET_FB_IDX(fb_info.gen.info.node),
- fb_info.gen.info.modename);
+ print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+ print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+ /* Setup LCD clock to AUX (48 MHz) */
+ sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
+ au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
+
+ /* load the panel info into the var struct */
+ au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
+ au1100fb_var.xres = fbdev->panel->xres;
+ au1100fb_var.xres_virtual = au1100fb_var.xres;
+ au1100fb_var.yres = fbdev->panel->yres;
+ au1100fb_var.yres_virtual = au1100fb_var.yres;
+
+ fbdev->info.screen_base = fbdev->fb_mem;
+ fbdev->info.fbops = &au1100fb_ops;
+ fbdev->info.fix = au1100fb_fix;
+
+ if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) {
+ return -ENOMEM;
+ }
+ memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16);
+
+ if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+ print_err("Fail to allocate colormap (%d entries)",
+ AU1100_LCD_NBR_PALETTE_ENTRIES);
+ kfree(fbdev->info.pseudo_palette);
+ return -EFAULT;
+ }
+
+ fbdev->info.var = au1100fb_var;
+
+ /* Set h/w registers */
+ au1100fb_setmode(fbdev);
+
+ /* Register new framebuffer */
+ if (register_framebuffer(&fbdev->info) < 0) {
+ print_err("cannot register new framebuffer");
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ if (fbdev->regs) {
+ release_mem_region(fbdev->regs_phys, fbdev->regs_len);
+ }
+ if (fbdev->fb_mem) {
+ dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys);
+ }
+ if (fbdev->info.cmap.len != 0) {
+ fb_dealloc_cmap(&fbdev->info.cmap);
+ }
+ kfree(fbdev);
+ dev_set_drvdata(dev, NULL);
return 0;
}
+int au1100fb_drv_remove(struct device *dev)
+{
+ struct au1100fb_device *fbdev = NULL;
+
+ if (!dev)
+ return -ENODEV;
+
+ fbdev = (struct au1100fb_device*) dev_get_drvdata(dev);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+ au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
+#endif
+ fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-void au1100fb_cleanup(struct fb_info *info)
+ /* Clean up all probe data */
+ unregister_framebuffer(&fbdev->info);
+
+ release_mem_region(fbdev->regs_phys, fbdev->regs_len);
+
+ dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys);
+
+ fb_dealloc_cmap(&fbdev->info.cmap);
+ kfree(fbdev->info.pseudo_palette);
+ kfree((void*)fbdev);
+
+ return 0;
+}
+
+int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+
+int au1100fb_drv_resume(struct device *dev, u32 level)
{
- unregister_framebuffer(info);
+ /* TODO */
+ return 0;
}
+static struct device_driver au1100fb_driver = {
+ .name = "au1100-lcd",
+ .bus = &platform_bus_type,
-void au1100fb_setup(char *options, int *ints)
+ .probe = au1100fb_drv_probe,
+ .remove = au1100fb_drv_remove,
+ .suspend = au1100fb_drv_suspend,
+ .resume = au1100fb_drv_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Kernel driver */
+
+int au1100fb_setup(char *options)
{
char* this_opt;
- int i;
- int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ char* mode = NULL;
+ int panel_idx = 0;
+ if (num_panels <= 0) {
+ print_err("No LCD panels supported by driver!");
+ return -EFAULT;
+ }
- if (!options || !*options)
- return;
-
- for(this_opt=strtok(options, ","); this_opt;
- this_opt=strtok(NULL, ",")) {
+ if (options) {
+ while ((this_opt = strsep(&options,",")) != NULL) {
+ /* Panel option */
if (!strncmp(this_opt, "panel:", 6)) {
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
- /* Read Pb1100 Switch S10 ? */
- if (!strncmp(this_opt+6, "s10", 3))
- {
- int panel;
- panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */
- panel >>= 8;
- panel &= 0x0F;
- if (panel >= num_panels) panel = 0;
- my_lcd_index = panel;
- }
- else
-#endif
- /* Get the panel name, everything else if fixed */
- for (i=0; i<num_panels; i++) {
- if (!strncmp(this_opt+6, panels[i].panel_name,
+ int i;
+ this_opt += 6;
+ for (i = 0; i < num_panels; i++) {
+ if (!strncmp(this_opt,
+ known_lcd_panels[i].name,
strlen(this_opt))) {
- my_lcd_index = i;
+ panel_idx = i;
break;
}
}
+ if (i >= num_panels) {
+ print_warn("Panel %s not supported!", this_opt);
+ }
+ }
+ /* Mode option (only option that start with digit) */
+ else if (isdigit(this_opt[0])) {
+ mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL);
+ strncpy(mode, this_opt, strlen(this_opt) + 1);
+ }
+ /* Unsupported option */
+ else {
+ print_warn("Unsupported option \"%s\"", this_opt);
}
- else if (!strncmp(this_opt, "nohwcursor", 10)) {
- printk("nohwcursor\n");
- fb_info.nohwcursor = 1;
}
}
- printk("au1100fb: Panel %d %s\n", my_lcd_index,
- panels[my_lcd_index].panel_name);
-}
+ drv_info.panel_idx = panel_idx;
+ drv_info.opt_mode = mode;
+ print_info("Panel=%s Mode=%s",
+ known_lcd_panels[drv_info.panel_idx].name,
+ drv_info.opt_mode ? drv_info.opt_mode : "default");
+ return 0;
+}
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-int init_module(void)
+int __init au1100fb_init(void)
{
- return au1100fb_init();
+ char* options;
+ int ret;
+
+ print_info("" DRIVER_DESC "");
+
+ memset(&drv_info, 0, sizeof(drv_info));
+
+ if (fb_get_options(DRIVER_NAME, &options))
+ return -ENODEV;
+
+ /* Setup driver with options */
+ ret = au1100fb_setup(options);
+ if (ret < 0) {
+ print_err("Fail to setup driver");
+ return ret;
+ }
+
+ return driver_register(&au1100fb_driver);
}
-void cleanup_module(void)
+void __exit au1100fb_cleanup(void)
{
- au1100fb_cleanup(void);
+ driver_unregister(&au1100fb_driver);
+
+ if (drv_info.opt_mode)
+ kfree(drv_info.opt_mode);
}
-MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
-MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");
-#endif /* MODULE */
+module_init(au1100fb_init);
+module_exit(au1100fb_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
index 657c560ab73c..2855534dc235 100644
--- a/drivers/video/au1100fb.h
+++ b/drivers/video/au1100fb.h
@@ -30,352 +30,352 @@
#ifndef _AU1100LCD_H
#define _AU1100LCD_H
+#include <asm/mach-au1x00/au1000.h>
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
/********************************************************************/
-#define uint32 unsigned long
-typedef volatile struct
-{
- uint32 lcd_control;
- uint32 lcd_intstatus;
- uint32 lcd_intenable;
- uint32 lcd_horztiming;
- uint32 lcd_verttiming;
- uint32 lcd_clkcontrol;
- uint32 lcd_dmaaddr0;
- uint32 lcd_dmaaddr1;
- uint32 lcd_words;
- uint32 lcd_pwmdiv;
- uint32 lcd_pwmhi;
- uint32 reserved[(0x0400-0x002C)/4];
- uint32 lcd_pallettebase[256];
-
-} AU1100_LCD;
+
+/* LCD controller restrictions */
+#define AU1100_LCD_MAX_XRES 800
+#define AU1100_LCD_MAX_YRES 600
+#define AU1100_LCD_MAX_BPP 16
+#define AU1100_LCD_MAX_CLK 48000000
+#define AU1100_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1100FB_NBR_VIDEO_BUFFERS 4
/********************************************************************/
-#define AU1100_LCD_ADDR 0xB5000000
+struct au1100fb_panel
+{
+ const char name[25]; /* Full name <vendor>_<model> */
-/*
- * Register bit definitions
- */
+ u32 control_base; /* Mode-independent control values */
+ u32 clkcontrol_base; /* Panel pixclock preferences */
-/* lcd_control */
-#define LCD_CONTROL_SBPPF (7<<18)
-#define LCD_CONTROL_SBPPF_655 (0<<18)
-#define LCD_CONTROL_SBPPF_565 (1<<18)
-#define LCD_CONTROL_SBPPF_556 (2<<18)
-#define LCD_CONTROL_SBPPF_1555 (3<<18)
-#define LCD_CONTROL_SBPPF_5551 (4<<18)
-#define LCD_CONTROL_WP (1<<17)
-#define LCD_CONTROL_WD (1<<16)
-#define LCD_CONTROL_C (1<<15)
-#define LCD_CONTROL_SM (3<<13)
-#define LCD_CONTROL_SM_0 (0<<13)
-#define LCD_CONTROL_SM_90 (1<<13)
-#define LCD_CONTROL_SM_180 (2<<13)
-#define LCD_CONTROL_SM_270 (3<<13)
-#define LCD_CONTROL_DB (1<<12)
-#define LCD_CONTROL_CCO (1<<11)
-#define LCD_CONTROL_DP (1<<10)
-#define LCD_CONTROL_PO (3<<8)
-#define LCD_CONTROL_PO_00 (0<<8)
-#define LCD_CONTROL_PO_01 (1<<8)
-#define LCD_CONTROL_PO_10 (2<<8)
-#define LCD_CONTROL_PO_11 (3<<8)
-#define LCD_CONTROL_MPI (1<<7)
-#define LCD_CONTROL_PT (1<<6)
-#define LCD_CONTROL_PC (1<<5)
-#define LCD_CONTROL_BPP (7<<1)
-#define LCD_CONTROL_BPP_1 (0<<1)
-#define LCD_CONTROL_BPP_2 (1<<1)
-#define LCD_CONTROL_BPP_4 (2<<1)
-#define LCD_CONTROL_BPP_8 (3<<1)
-#define LCD_CONTROL_BPP_12 (4<<1)
-#define LCD_CONTROL_BPP_16 (5<<1)
-#define LCD_CONTROL_GO (1<<0)
-
-/* lcd_intstatus, lcd_intenable */
-#define LCD_INT_SD (1<<7)
-#define LCD_INT_OF (1<<6)
-#define LCD_INT_UF (1<<5)
-#define LCD_INT_SA (1<<3)
-#define LCD_INT_SS (1<<2)
-#define LCD_INT_S1 (1<<1)
-#define LCD_INT_S0 (1<<0)
-
-/* lcd_horztiming */
-#define LCD_HORZTIMING_HN2 (255<<24)
-#define LCD_HORZTIMING_HN2_N(N) (((N)-1)<<24)
-#define LCD_HORZTIMING_HN1 (255<<16)
-#define LCD_HORZTIMING_HN1_N(N) (((N)-1)<<16)
-#define LCD_HORZTIMING_HPW (63<<10)
-#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<10)
-#define LCD_HORZTIMING_PPL (1023<<0)
-#define LCD_HORZTIMING_PPL_N(N) (((N)-1)<<0)
-
-/* lcd_verttiming */
-#define LCD_VERTTIMING_VN2 (255<<24)
-#define LCD_VERTTIMING_VN2_N(N) (((N)-1)<<24)
-#define LCD_VERTTIMING_VN1 (255<<16)
-#define LCD_VERTTIMING_VN1_N(N) (((N)-1)<<16)
-#define LCD_VERTTIMING_VPW (63<<10)
-#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<10)
-#define LCD_VERTTIMING_LPP (1023<<0)
-#define LCD_VERTTIMING_LPP_N(N) (((N)-1)<<0)
-
-/* lcd_clkcontrol */
-#define LCD_CLKCONTROL_IB (1<<18)
-#define LCD_CLKCONTROL_IC (1<<17)
-#define LCD_CLKCONTROL_IH (1<<16)
-#define LCD_CLKCONTROL_IV (1<<15)
-#define LCD_CLKCONTROL_BF (31<<10)
-#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
-#define LCD_CLKCONTROL_PCD (1023<<0)
-#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
-
-/* lcd_pwmdiv */
-#define LCD_PWMDIV_EN (1<<12)
-#define LCD_PWMDIV_PWMDIV (2047<<0)
-#define LCD_PWMDIV_PWMDIV_N(N) (((N)-1)<<0)
-
-/* lcd_pwmhi */
-#define LCD_PWMHI_PWMHI1 (2047<<12)
-#define LCD_PWMHI_PWMHI1_N(N) ((N)<<12)
-#define LCD_PWMHI_PWMHI0 (2047<<0)
-#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
-
-/* lcd_pallettebase - MONOCHROME */
-#define LCD_PALLETTE_MONO_MI (15<<0)
-#define LCD_PALLETTE_MONO_MI_N(N) ((N)<<0)
-
-/* lcd_pallettebase - COLOR */
-#define LCD_PALLETTE_COLOR_BI (15<<8)
-#define LCD_PALLETTE_COLOR_BI_N(N) ((N)<<8)
-#define LCD_PALLETTE_COLOR_GI (15<<4)
-#define LCD_PALLETTE_COLOR_GI_N(N) ((N)<<4)
-#define LCD_PALLETTE_COLOR_RI (15<<0)
-#define LCD_PALLETTE_COLOR_RI_N(N) ((N)<<0)
-
-/* lcd_palletebase - COLOR TFT PALLETIZED */
-#define LCD_PALLETTE_TFT_DC (65535<<0)
-#define LCD_PALLETTE_TFT_DC_N(N) ((N)<<0)
+ u32 horztiming;
+ u32 verttiming;
-/********************************************************************/
+ u32 xres; /* Maximum horizontal resolution */
+ u32 yres; /* Maximum vertical resolution */
+ u32 bpp; /* Maximum depth supported */
+};
-struct known_lcd_panels
+struct au1100fb_regs
{
- uint32 xres;
- uint32 yres;
- uint32 bpp;
- unsigned char panel_name[256];
- uint32 mode_control;
- uint32 mode_horztiming;
- uint32 mode_verttiming;
- uint32 mode_clkcontrol;
- uint32 mode_pwmdiv;
- uint32 mode_pwmhi;
- uint32 mode_toyclksrc;
- uint32 mode_backlight;
+ u32 lcd_control;
+ u32 lcd_intstatus;
+ u32 lcd_intenable;
+ u32 lcd_horztiming;
+ u32 lcd_verttiming;
+ u32 lcd_clkcontrol;
+ u32 lcd_dmaaddr0;
+ u32 lcd_dmaaddr1;
+ u32 lcd_words;
+ u32 lcd_pwmdiv;
+ u32 lcd_pwmhi;
+ u32 reserved[(0x0400-0x002C)/4];
+ u32 lcd_pallettebase[256];
+};
+
+struct au1100fb_device {
+
+ struct fb_info info; /* FB driver info record */
+ struct au1100fb_panel *panel; /* Panel connected to this device */
+
+ struct au1100fb_regs* regs; /* Registers memory map */
+ size_t regs_len;
+ unsigned int regs_phys;
+
+ unsigned char* fb_mem; /* FrameBuffer memory map */
+ size_t fb_len;
+ dma_addr_t fb_phys;
};
-#if defined(__BIG_ENDIAN)
-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11
-#else
-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00
-#endif
+/********************************************************************/
-/*
- * The fb driver assumes that AUX PLL is at 48MHz. That can
- * cover up to 800x600 resolution; if you need higher resolution,
- * you should modify the driver as needed, not just this structure.
+#define LCD_CONTROL (AU1100_LCD_BASE + 0x0)
+ #define LCD_CONTROL_SBB_BIT 21
+ #define LCD_CONTROL_SBB_MASK (0x3 << LCD_CONTROL_SBB_BIT)
+ #define LCD_CONTROL_SBB_1 (0 << LCD_CONTROL_SBB_BIT)
+ #define LCD_CONTROL_SBB_2 (1 << LCD_CONTROL_SBB_BIT)
+ #define LCD_CONTROL_SBB_3 (2 << LCD_CONTROL_SBB_BIT)
+ #define LCD_CONTROL_SBB_4 (3 << LCD_CONTROL_SBB_BIT)
+ #define LCD_CONTROL_SBPPF_BIT 18
+ #define LCD_CONTROL_SBPPF_MASK (0x7 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_SBPPF_655 (0 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_SBPPF_565 (1 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_SBPPF_556 (2 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_SBPPF_1555 (3 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_SBPPF_5551 (4 << LCD_CONTROL_SBPPF_BIT)
+ #define LCD_CONTROL_WP (1<<17)
+ #define LCD_CONTROL_WD (1<<16)
+ #define LCD_CONTROL_C (1<<15)
+ #define LCD_CONTROL_SM_BIT 13
+ #define LCD_CONTROL_SM_MASK (0x3 << LCD_CONTROL_SM_BIT)
+ #define LCD_CONTROL_SM_0 (0 << LCD_CONTROL_SM_BIT)
+ #define LCD_CONTROL_SM_90 (1 << LCD_CONTROL_SM_BIT)
+ #define LCD_CONTROL_SM_180 (2 << LCD_CONTROL_SM_BIT)
+ #define LCD_CONTROL_SM_270 (3 << LCD_CONTROL_SM_BIT)
+ #define LCD_CONTROL_DB (1<<12)
+ #define LCD_CONTROL_CCO (1<<11)
+ #define LCD_CONTROL_DP (1<<10)
+ #define LCD_CONTROL_PO_BIT 8
+ #define LCD_CONTROL_PO_MASK (0x3 << LCD_CONTROL_PO_BIT)
+ #define LCD_CONTROL_PO_00 (0 << LCD_CONTROL_PO_BIT)
+ #define LCD_CONTROL_PO_01 (1 << LCD_CONTROL_PO_BIT)
+ #define LCD_CONTROL_PO_10 (2 << LCD_CONTROL_PO_BIT)
+ #define LCD_CONTROL_PO_11 (3 << LCD_CONTROL_PO_BIT)
+ #define LCD_CONTROL_MPI (1<<7)
+ #define LCD_CONTROL_PT (1<<6)
+ #define LCD_CONTROL_PC (1<<5)
+ #define LCD_CONTROL_BPP_BIT 1
+ #define LCD_CONTROL_BPP_MASK (0x7 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_1 (0 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_2 (1 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_4 (2 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_8 (3 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_12 (4 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_BPP_16 (5 << LCD_CONTROL_BPP_BIT)
+ #define LCD_CONTROL_GO (1<<0)
+
+#define LCD_INTSTATUS (AU1100_LCD_BASE + 0x4)
+#define LCD_INTENABLE (AU1100_LCD_BASE + 0x8)
+ #define LCD_INT_SD (1<<7)
+ #define LCD_INT_OF (1<<6)
+ #define LCD_INT_UF (1<<5)
+ #define LCD_INT_SA (1<<3)
+ #define LCD_INT_SS (1<<2)
+ #define LCD_INT_S1 (1<<1)
+ #define LCD_INT_S0 (1<<0)
+
+#define LCD_HORZTIMING (AU1100_LCD_BASE + 0xC)
+ #define LCD_HORZTIMING_HN2_BIT 24
+ #define LCD_HORZTIMING_HN2_MASK (0xFF << LCD_HORZTIMING_HN2_BIT)
+ #define LCD_HORZTIMING_HN2_N(N) ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK)
+ #define LCD_HORZTIMING_HN1_BIT 16
+ #define LCD_HORZTIMING_HN1_MASK (0xFF << LCD_HORZTIMING_HN1_BIT)
+ #define LCD_HORZTIMING_HN1_N(N) ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK)
+ #define LCD_HORZTIMING_HPW_BIT 10
+ #define LCD_HORZTIMING_HPW_MASK (0x3F << LCD_HORZTIMING_HPW_BIT)
+ #define LCD_HORZTIMING_HPW_N(N) ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK)
+ #define LCD_HORZTIMING_PPL_BIT 0
+ #define LCD_HORZTIMING_PPL_MASK (0x3FF << LCD_HORZTIMING_PPL_BIT)
+ #define LCD_HORZTIMING_PPL_N(N) ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK)
+
+#define LCD_VERTTIMING (AU1100_LCD_BASE + 0x10)
+ #define LCD_VERTTIMING_VN2_BIT 24
+ #define LCD_VERTTIMING_VN2_MASK (0xFF << LCD_VERTTIMING_VN2_BIT)
+ #define LCD_VERTTIMING_VN2_N(N) ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK)
+ #define LCD_VERTTIMING_VN1_BIT 16
+ #define LCD_VERTTIMING_VN1_MASK (0xFF << LCD_VERTTIMING_VN1_BIT)
+ #define LCD_VERTTIMING_VN1_N(N) ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK)
+ #define LCD_VERTTIMING_VPW_BIT 10
+ #define LCD_VERTTIMING_VPW_MASK (0x3F << LCD_VERTTIMING_VPW_BIT)
+ #define LCD_VERTTIMING_VPW_N(N) ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK)
+ #define LCD_VERTTIMING_LPP_BIT 0
+ #define LCD_VERTTIMING_LPP_MASK (0x3FF << LCD_VERTTIMING_LPP_BIT)
+ #define LCD_VERTTIMING_LPP_N(N) ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK)
+
+#define LCD_CLKCONTROL (AU1100_LCD_BASE + 0x14)
+ #define LCD_CLKCONTROL_IB (1<<18)
+ #define LCD_CLKCONTROL_IC (1<<17)
+ #define LCD_CLKCONTROL_IH (1<<16)
+ #define LCD_CLKCONTROL_IV (1<<15)
+ #define LCD_CLKCONTROL_BF_BIT 10
+ #define LCD_CLKCONTROL_BF_MASK (0x1F << LCD_CLKCONTROL_BF_BIT)
+ #define LCD_CLKCONTROL_BF_N(N) ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK)
+ #define LCD_CLKCONTROL_PCD_BIT 0
+ #define LCD_CLKCONTROL_PCD_MASK (0x3FF << LCD_CLKCONTROL_PCD_BIT)
+ #define LCD_CLKCONTROL_PCD_N(N) (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK)
+
+#define LCD_DMAADDR0 (AU1100_LCD_BASE + 0x18)
+#define LCD_DMAADDR1 (AU1100_LCD_BASE + 0x1C)
+ #define LCD_DMA_SA_BIT 5
+ #define LCD_DMA_SA_MASK (0x7FFFFFF << LCD_DMA_SA_BIT)
+ #define LCD_DMA_SA_N(N) ((N) & LCD_DMA_SA_MASK)
+
+#define LCD_WORDS (AU1100_LCD_BASE + 0x20)
+ #define LCD_WRD_WRDS_BIT 0
+ #define LCD_WRD_WRDS_MASK (0xFFFFFFFF << LCD_WRD_WRDS_BIT)
+ #define LCD_WRD_WRDS_N(N) ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK)
+
+#define LCD_PWMDIV (AU1100_LCD_BASE + 0x24)
+ #define LCD_PWMDIV_EN (1<<12)
+ #define LCD_PWMDIV_PWMDIV_BIT 0
+ #define LCD_PWMDIV_PWMDIV_MASK (0xFFF << LCD_PWMDIV_PWMDIV_BIT)
+ #define LCD_PWMDIV_PWMDIV_N(N) ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK)
+
+#define LCD_PWMHI (AU1100_LCD_BASE + 0x28)
+ #define LCD_PWMHI_PWMHI1_BIT 12
+ #define LCD_PWMHI_PWMHI1_MASK (0xFFF << LCD_PWMHI_PWMHI1_BIT)
+ #define LCD_PWMHI_PWMHI1_N(N) (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK)
+ #define LCD_PWMHI_PWMHI0_BIT 0
+ #define LCD_PWMHI_PWMHI0_MASK (0xFFF << LCD_PWMHI_PWMHI0_BIT)
+ #define LCD_PWMHI_PWMHI0_N(N) (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK)
+
+#define LCD_PALLETTEBASE (AU1100_LCD_BASE + 0x400)
+ #define LCD_PALLETTE_MONO_MI_BIT 0
+ #define LCD_PALLETTE_MONO_MI_MASK (0xF << LCD_PALLETTE_MONO_MI_BIT)
+ #define LCD_PALLETTE_MONO_MI_N(N) (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK)
+
+ #define LCD_PALLETTE_COLOR_RI_BIT 8
+ #define LCD_PALLETTE_COLOR_RI_MASK (0xF << LCD_PALLETTE_COLOR_RI_BIT)
+ #define LCD_PALLETTE_COLOR_RI_N(N) (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK)
+ #define LCD_PALLETTE_COLOR_GI_BIT 4
+ #define LCD_PALLETTE_COLOR_GI_MASK (0xF << LCD_PALLETTE_COLOR_GI_BIT)
+ #define LCD_PALLETTE_COLOR_GI_N(N) (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK)
+ #define LCD_PALLETTE_COLOR_BI_BIT 0
+ #define LCD_PALLETTE_COLOR_BI_MASK (0xF << LCD_PALLETTE_COLOR_BI_BIT)
+ #define LCD_PALLETTE_COLOR_BI_N(N) (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK)
+
+ #define LCD_PALLETTE_TFT_DC_BIT 0
+ #define LCD_PALLETTE_TFT_DC_MASK (0xFFFF << LCD_PALLETTE_TFT_DC_BIT)
+ #define LCD_PALLETTE_TFT_DC_N(N) (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK)
+
+/********************************************************************/
+
+/* List of panels known to work with the AU1100 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
*/
-struct known_lcd_panels panels[] =
+static struct au1100fb_panel known_lcd_panels[] =
{
- { /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */
- 320, /* xres */
- 240, /* yres */
- 16, /* bpp */
-
- "Sharp_320x240_16",
- /* mode_control */
+ /* 800x600x16bpp CRT */
+ [0] = {
+ .name = "CRT_800x600_16",
+ .xres = 800,
+ .yres = 600,
+ .bpp = 16,
+ .control_base = 0x0004886A |
+ LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
+ LCD_CONTROL_BPP_16,
+ .clkcontrol_base = 0x00020000,
+ .horztiming = 0x005aff1f,
+ .verttiming = 0x16000e57,
+ },
+ /* just the standard LCD */
+ [1] = {
+ .name = "WWPC LCD",
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .control_base = 0x0006806A,
+ .horztiming = 0x0A1010EF,
+ .verttiming = 0x0301013F,
+ .clkcontrol_base = 0x00018001,
+ },
+ /* Sharp 320x240 TFT panel */
+ [2] = {
+ .name = "Sharp_LQ038Q5DR01",
+ .xres = 320,
+ .yres = 240,
+ .bpp = 16,
+ .control_base =
( LCD_CONTROL_SBPPF_565
- /*LCD_CONTROL_WP*/
- /*LCD_CONTROL_WD*/
| LCD_CONTROL_C
| LCD_CONTROL_SM_0
- /*LCD_CONTROL_DB*/
- /*LCD_CONTROL_CCO*/
- /*LCD_CONTROL_DP*/
- | LCD_DEFAULT_PIX_FORMAT
- /*LCD_CONTROL_MPI*/
+ | LCD_CONTROL_DEFAULT_PO
| LCD_CONTROL_PT
| LCD_CONTROL_PC
| LCD_CONTROL_BPP_16 ),
-
- /* mode_horztiming */
+ .horztiming =
( LCD_HORZTIMING_HN2_N(8)
| LCD_HORZTIMING_HN1_N(60)
| LCD_HORZTIMING_HPW_N(12)
| LCD_HORZTIMING_PPL_N(320) ),
-
- /* mode_verttiming */
+ .verttiming =
( LCD_VERTTIMING_VN2_N(5)
| LCD_VERTTIMING_VN1_N(17)
| LCD_VERTTIMING_VPW_N(1)
| LCD_VERTTIMING_LPP_N(240) ),
-
- /* mode_clkcontrol */
- ( 0
- /*LCD_CLKCONTROL_IB*/
- /*LCD_CLKCONTROL_IC*/
- /*LCD_CLKCONTROL_IH*/
- /*LCD_CLKCONTROL_IV*/
- | LCD_CLKCONTROL_PCD_N(1) ),
-
- /* mode_pwmdiv */
- 0,
-
- /* mode_pwmhi */
- 0,
-
- /* mode_toyclksrc */
- ((1<<7) | (1<<6) | (1<<5)),
-
- /* mode_backlight */
- 6
+ .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
},
- { /* 1: Pb1100 LCDC 640x480 TFT panel */
- 640, /* xres */
- 480, /* yres */
- 16, /* bpp */
-
- "Generic_640x480_16",
-
- /* mode_control */
- 0x004806a | LCD_DEFAULT_PIX_FORMAT,
-
- /* mode_horztiming */
- 0x3434d67f,
-
- /* mode_verttiming */
- 0x0e0e39df,
-
- /* mode_clkcontrol */
- ( 0
- /*LCD_CLKCONTROL_IB*/
- /*LCD_CLKCONTROL_IC*/
- /*LCD_CLKCONTROL_IH*/
- /*LCD_CLKCONTROL_IV*/
- | LCD_CLKCONTROL_PCD_N(1) ),
-
- /* mode_pwmdiv */
- 0,
-
- /* mode_pwmhi */
- 0,
-
- /* mode_toyclksrc */
- ((1<<7) | (1<<6) | (0<<5)),
-
- /* mode_backlight */
- 7
+ /* Hitachi SP14Q005 and possibly others */
+ [3] = {
+ .name = "Hitachi_SP14Qxxx",
+ .xres = 320,
+ .yres = 240,
+ .bpp = 4,
+ .control_base =
+ ( LCD_CONTROL_C
+ | LCD_CONTROL_BPP_4 ),
+ .horztiming =
+ ( LCD_HORZTIMING_HN2_N(1)
+ | LCD_HORZTIMING_HN1_N(1)
+ | LCD_HORZTIMING_HPW_N(1)
+ | LCD_HORZTIMING_PPL_N(320) ),
+ .verttiming =
+ ( LCD_VERTTIMING_VN2_N(1)
+ | LCD_VERTTIMING_VN1_N(1)
+ | LCD_VERTTIMING_VPW_N(1)
+ | LCD_VERTTIMING_LPP_N(240) ),
+ .clkcontrol_base = LCD_CLKCONTROL_PCD_N(4),
},
- { /* 2: Pb1100 LCDB 640x480 PrimeView TFT panel */
- 640, /* xres */
- 480, /* yres */
- 16, /* bpp */
-
- "PrimeView_640x480_16",
-
- /* mode_control */
- 0x0004886a | LCD_DEFAULT_PIX_FORMAT,
-
- /* mode_horztiming */
- 0x0e4bfe7f,
-
- /* mode_verttiming */
- 0x210805df,
-
- /* mode_clkcontrol */
- 0x00038001,
-
- /* mode_pwmdiv */
- 0,
-
- /* mode_pwmhi */
- 0,
-
- /* mode_toyclksrc */
- ((1<<7) | (1<<6) | (0<<5)),
-
- /* mode_backlight */
- 7
+ /* Generic 640x480 TFT panel */
+ [4] = {
+ .name = "TFT_640x480_16",
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO,
+ .horztiming = 0x3434d67f,
+ .verttiming = 0x0e0e39df,
+ .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
},
- { /* 3: Pb1100 800x600x16bpp NEON CRT */
- 800, /* xres */
- 600, /* yres */
- 16, /* bpp */
-
- "NEON_800x600_16",
-
- /* mode_control */
- 0x0004886A | LCD_DEFAULT_PIX_FORMAT,
-
- /* mode_horztiming */
- 0x005AFF1F,
-
- /* mode_verttiming */
- 0x16000E57,
-
- /* mode_clkcontrol */
- 0x00020000,
-
- /* mode_pwmdiv */
- 0,
-
- /* mode_pwmhi */
- 0,
-
- /* mode_toyclksrc */
- ((1<<7) | (1<<6) | (0<<5)),
-
- /* mode_backlight */
- 7
+ /* Pb1100 LCDB 640x480 PrimeView TFT panel */
+ [5] = {
+ .name = "PrimeView_640x480_16",
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO,
+ .horztiming = 0x0e4bfe7f,
+ .verttiming = 0x210805df,
+ .clkcontrol_base = 0x00038001,
},
+};
- { /* 4: Pb1100 640x480x16bpp NEON CRT */
- 640, /* xres */
- 480, /* yres */
- 16, /* bpp */
-
- "NEON_640x480_16",
-
- /* mode_control */
- 0x0004886A | LCD_DEFAULT_PIX_FORMAT,
-
- /* mode_horztiming */
- 0x0052E27F,
-
- /* mode_verttiming */
- 0x18000DDF,
-
- /* mode_clkcontrol */
- 0x00020000,
+struct au1100fb_drv_info {
+ int panel_idx;
+ char *opt_mode;
+};
- /* mode_pwmdiv */
- 0,
+/********************************************************************/
- /* mode_pwmhi */
- 0,
+/* Inline helpers */
- /* mode_toyclksrc */
- ((1<<7) | (1<<6) | (0<<5)),
+#define panel_is_dual(panel) (panel->control_base & LCD_CONTROL_DP)
+#define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT)
+#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC)
+#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO)
- /* mode_backlight */
- 7
- },
-};
#endif /* _AU1100LCD_H */
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9aae884475be..4af321fae390 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,3 +3,4 @@
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
+obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 353cb3f73cf2..4867498f68e8 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -14,22 +14,22 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/fb.h>
#include <linux/backlight.h>
-#include <asm/arch-pxa/corgi.h>
-#include <asm/hardware/scoop.h>
+#include <asm/arch/sharpsl.h>
-#define CORGI_MAX_INTENSITY 0x3e
#define CORGI_DEFAULT_INTENSITY 0x1f
-#define CORGI_LIMIT_MASK 0x0b
+#define CORGI_LIMIT_MASK 0x0b
static int corgibl_powermode = FB_BLANK_UNBLANK;
static int current_intensity = 0;
static int corgibl_limit = 0;
+static void (*corgibl_mach_set_intensity)(int intensity);
static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_properties corgibl_data;
static void corgibl_send_intensity(int intensity)
{
@@ -43,18 +43,10 @@ static void corgibl_send_intensity(int intensity)
intensity &= CORGI_LIMIT_MASK;
}
- /* Skip 0x20 as it will blank the display */
- if (intensity >= 0x20)
- intensity++;
-
spin_lock_irqsave(&bl_lock, flags);
- /* Bits 0-4 are accessed via the SSP interface */
- corgi_ssp_blduty_set(intensity & 0x1f);
- /* Bit 5 is via SCOOP */
- if (intensity & 0x0020)
- set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
- else
- reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+
+ corgibl_mach_set_intensity(intensity);
+
spin_unlock_irqrestore(&bl_lock, flags);
}
@@ -81,17 +73,15 @@ static void corgibl_blank(int blank)
}
#ifdef CONFIG_PM
-static int corgibl_suspend(struct device *dev, pm_message_t state, u32 level)
+static int corgibl_suspend(struct device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN)
- corgibl_blank(FB_BLANK_POWERDOWN);
+ corgibl_blank(FB_BLANK_POWERDOWN);
return 0;
}
-static int corgibl_resume(struct device *dev, u32 level)
+static int corgibl_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON)
- corgibl_blank(FB_BLANK_UNBLANK);
+ corgibl_blank(FB_BLANK_UNBLANK);
return 0;
}
#else
@@ -113,8 +103,8 @@ static int corgibl_get_power(struct backlight_device *bd)
static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
{
- if (intensity > CORGI_MAX_INTENSITY)
- intensity = CORGI_MAX_INTENSITY;
+ if (intensity > corgibl_data.max_brightness)
+ intensity = corgibl_data.max_brightness;
corgibl_send_intensity(intensity);
current_intensity=intensity;
return 0;
@@ -141,7 +131,6 @@ static struct backlight_properties corgibl_data = {
.owner = THIS_MODULE,
.get_power = corgibl_get_power,
.set_power = corgibl_set_power,
- .max_brightness = CORGI_MAX_INTENSITY,
.get_brightness = corgibl_get_intensity,
.set_brightness = corgibl_set_intensity,
};
@@ -150,12 +139,18 @@ static struct backlight_device *corgi_backlight_device;
static int __init corgibl_probe(struct device *dev)
{
+ struct corgibl_machinfo *machinfo = dev->platform_data;
+
+ corgibl_data.max_brightness = machinfo->max_intensity;
+ corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+
corgi_backlight_device = backlight_device_register ("corgi-bl",
NULL, &corgibl_data);
if (IS_ERR (corgi_backlight_device))
return PTR_ERR (corgi_backlight_device);
corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
+ corgibl_limit_intensity(0);
printk("Corgi Backlight Driver Initialized.\n");
return 0;
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
new file mode 100644
index 000000000000..ada6e75eb048
--- /dev/null
+++ b/drivers/video/backlight/locomolcd.c
@@ -0,0 +1,157 @@
+/*
+ * Backlight control code for Sharp Zaurus SL-5500
+ *
+ * Copyright 2005 John Lenz <lenz@cs.wisc.edu>
+ * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
+ * GPL v2
+ *
+ * This driver assumes single CPU. That's okay, because collie is
+ * slightly old hardware, and noone is going to retrofit second CPU to
+ * old PDA.
+ */
+
+/* LCD power functions */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware/locomo.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch/collie.h>
+#else
+#include <asm/arch/poodle.h>
+#endif
+
+extern void (*sa1100fb_lcd_power)(int on);
+
+static struct locomo_dev *locomolcd_dev;
+
+static void locomolcd_on(int comadj)
+{
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+ mdelay(2);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+ mdelay(2);
+
+ locomo_m62332_senddata(locomolcd_dev, comadj, 0);
+ mdelay(5);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
+ mdelay(10);
+
+ /* TFTCRST | CPSOUT=0 | CPSEN */
+ locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
+
+ /* Set CPSD */
+ locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
+
+ /* TFTCRST | CPSOUT=0 | CPSEN */
+ locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
+ mdelay(10);
+
+ locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
+}
+
+static void locomolcd_off(int comadj)
+{
+ /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
+ locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
+ mdelay(1);
+
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+ mdelay(110);
+
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+ mdelay(700);
+
+ /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
+ locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
+ locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+}
+
+void locomolcd_power(int on)
+{
+ int comadj = 118;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (!locomolcd_dev) {
+ local_irq_restore(flags);
+ return;
+ }
+
+ /* read comadj */
+#ifdef CONFIG_MACH_POODLE
+ comadj = 118;
+#else
+ comadj = 128;
+#endif
+
+ if (on)
+ locomolcd_on(comadj);
+ else
+ locomolcd_off(comadj);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(locomolcd_power);
+
+static int poodle_lcd_probe(struct locomo_dev *dev)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ locomolcd_dev = dev;
+
+ /* the poodle_lcd_power function is called for the first time
+ * from fs_initcall, which is before locomo is activated.
+ * We need to recall poodle_lcd_power here*/
+#ifdef CONFIG_MACH_POODLE
+ locomolcd_power(1);
+#endif
+ local_irq_restore(flags);
+ return 0;
+}
+
+static int poodle_lcd_remove(struct locomo_dev *dev)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ locomolcd_dev = NULL;
+ local_irq_restore(flags);
+ return 0;
+}
+
+static struct locomo_driver poodle_lcd_driver = {
+ .drv = {
+ .name = "locomo-backlight",
+ },
+ .devid = LOCOMO_DEVID_BACKLIGHT,
+ .probe = poodle_lcd_probe,
+ .remove = poodle_lcd_remove,
+};
+
+static int __init poodle_lcd_init(void)
+{
+ int ret = locomo_driver_register(&poodle_lcd_driver);
+ if (ret) return ret;
+
+#ifdef CONFIG_SA1100_COLLIE
+ sa1100fb_lcd_power = locomolcd_power;
+#endif
+ return 0;
+}
+device_initcall(poodle_lcd_init);
+
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index e75a965ec760..4131243cfdf8 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -462,9 +462,9 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *p = pci_get_drvdata(pdev);
- if (state == pdev->dev.power.power_state)
+ if (state.event == pdev->dev.power.power_state.event)
return 0;
- if (state != PM_SUSPEND_MEM)
+ if (state.event != PM_SUSPEND_MEM)
goto done;
acquire_console_sem();
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index a3040429c27b..3a26f9cc8585 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -275,20 +275,20 @@ static const struct cirrusfb_board_info_rec {
#ifdef CONFIG_PCI
#define CHIP(id, btype) \
- { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
+ { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
static struct pci_device_id cirrusfb_pci_table[] = {
- CHIP( CIRRUS_5436, BT_ALPINE ),
- CHIP( CIRRUS_5434_8, BT_ALPINE ),
- CHIP( CIRRUS_5434_4, BT_ALPINE ),
- CHIP( CIRRUS_5430, BT_ALPINE ), /* GD-5440 has identical id */
- CHIP( CIRRUS_7543, BT_ALPINE ),
- CHIP( CIRRUS_7548, BT_ALPINE ),
- CHIP( CIRRUS_5480, BT_GD5480 ), /* MacPicasso probably */
- CHIP( CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
- CHIP( CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
- CHIP( CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
- CHIP( CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
+ CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
+ CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
+ CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
+ CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
+ CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
+ CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
+ CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
+ CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
+ CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
+ CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
+ CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index cbff98337aa6..6a9ae2b3d1ab 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
config VGA_CONSOLE
bool "VGA text console" if EMBEDDED || !X86
- depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
+ depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC && !ARCH_VERSATILE
default y
help
Saying Y here will allow you to use Linux in text mode through a
@@ -28,7 +28,7 @@ config VGA_CONSOLE
config VIDEO_SELECT
bool "Video mode selection support"
- depends on (X86 || X86_64) && VGA_CONSOLE
+ 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
@@ -110,7 +110,7 @@ config STI_CONSOLE
config FONTS
bool "Select compiled-in fonts"
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
help
Say Y here if you would like to use fonts other than the default
your frame buffer console usually use.
@@ -123,7 +123,7 @@ config FONTS
config FONT_8x8
bool "VGA 8x8 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -137,7 +137,7 @@ config FONT_8x8
config FONT_8x16
bool "VGA 8x16 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
+ depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || STI_CONSOLE || USB_SISUSBVGA_CON
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
@@ -147,7 +147,7 @@ config FONT_8x16
config FONT_6x11
bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
default y if !SPARC32 && !SPARC64 && !FONTS && MAC
help
Small console font with Macintosh-style high-half glyphs. Some Mac
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index b562f6bb9d31..42c7b8dcd220 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -33,6 +33,10 @@ endif
obj-$(CONFIG_FB_STI) += sticore.o font.o
+ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
+obj-$(CONFIG_USB_SISUSBVGA) += font.o
+endif
+
# Targets that kbuild needs to know about
targets := promcon_tbl.c
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 3c731577fed6..9f70e512b88b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c)
{
int attribute = 0;
- if (fb_get_color_depth(&info->var) == 1) {
+ if (fb_get_color_depth(&info->var, &info->fix) == 1) {
if (attr_underline(c))
attribute |= FBCON_ATTRIBUTE_UNDERLINE;
if (attr_reverse(c))
@@ -103,42 +103,104 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
info->fbops->fb_fillrect(info, &region);
}
+static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
+ const u16 *s, u32 attr, u32 cnt,
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst)
+{
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 idx = vc->vc_font.width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = vc->vc_font.data + (scr_readw(s++)&
+ charmask)*cellsize;
+
+ if (attr) {
+ update_attr(buf, src, attr, vc);
+ src = buf;
+ }
+
+ if (likely(idx == 1))
+ __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+ else
+ fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+
+ dst += s_pitch;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+}
+
+static inline void bit_putcs_unaligned(struct vc_data *vc,
+ struct fb_info *info, const u16 *s,
+ u32 attr, u32 cnt, u32 d_pitch,
+ u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf,
+ u8 *dst)
+{
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 shift_low = 0, mod = vc->vc_font.width % 8;
+ u32 shift_high = 8;
+ u32 idx = vc->vc_font.width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = vc->vc_font.data + (scr_readw(s++)&
+ charmask)*cellsize;
+
+ if (attr) {
+ update_attr(buf, src, attr, vc);
+ src = buf;
+ }
+
+ fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
+ image->height, shift_high,
+ shift_low, mod);
+ shift_low += mod;
+ dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
+ shift_low &= 7;
+ shift_high = 8 - shift_low;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+
+}
+
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
const unsigned short *s, int count, int yy, int xx,
int fg, int bg)
{
- unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
- unsigned int width = (vc->vc_font.width + 7) >> 3;
- unsigned int cellsize = vc->vc_font.height * width;
- unsigned int maxcnt = info->pixmap.size/cellsize;
- unsigned int scan_align = info->pixmap.scan_align - 1;
- unsigned int buf_align = info->pixmap.buf_align - 1;
- unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
- unsigned int shift_high = 8, pitch, cnt, size, k;
- unsigned int idx = vc->vc_font.width >> 3;
- unsigned int attribute = get_attribute(info, scr_readw(s));
struct fb_image image;
- u8 *src, *dst, *buf = NULL;
-
- if (attribute) {
- buf = kmalloc(cellsize, GFP_KERNEL);
- if (!buf)
- return;
- }
+ u32 width = (vc->vc_font.width + 7)/8;
+ u32 cellsize = width * vc->vc_font.height;
+ u32 maxcnt = info->pixmap.size/cellsize;
+ u32 scan_align = info->pixmap.scan_align - 1;
+ u32 buf_align = info->pixmap.buf_align - 1;
+ u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
+ u32 attribute = get_attribute(info, scr_readw(s));
+ u8 *dst, *buf = NULL;
image.fg_color = fg;
image.bg_color = bg;
-
image.dx = xx * vc->vc_font.width;
image.dy = yy * vc->vc_font.height;
image.height = vc->vc_font.height;
image.depth = 1;
+ if (attribute) {
+ buf = kmalloc(cellsize, GFP_KERNEL);
+ if (!buf)
+ return;
+ }
+
while (count) {
if (count > maxcnt)
- cnt = k = maxcnt;
+ cnt = maxcnt;
else
- cnt = k = count;
+ cnt = count;
image.width = vc->vc_font.width * cnt;
pitch = ((image.width + 7) >> 3) + scan_align;
@@ -147,41 +209,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
size &= ~buf_align;
dst = fb_get_buffer_offset(info, &info->pixmap, size);
image.data = dst;
- if (mod) {
- while (k--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attribute) {
- update_attr(buf, src, attribute, vc);
- src = buf;
- }
-
- fb_pad_unaligned_buffer(dst, pitch, src, idx,
- image.height, shift_high,
- shift_low, mod);
- shift_low += mod;
- dst += (shift_low >= 8) ? width : width - 1;
- shift_low &= 7;
- shift_high = 8 - shift_low;
- }
- } else {
- while (k--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attribute) {
- update_attr(buf, src, attribute, vc);
- src = buf;
- }
-
- fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
- dst += width;
- }
- }
- info->fbops->fb_imageblit(info, &image);
+
+ if (!mod)
+ bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
+ width, cellsize, &image, buf, dst);
+ else
+ bit_putcs_unaligned(vc, info, s, attribute, cnt,
+ pitch, width, cellsize, &image,
+ buf, dst);
+
image.dx += cnt * vc->vc_font.width;
count -= cnt;
+ s += cnt;
}
/* buf is always NULL except when in monochrome mode, so in this case
@@ -189,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
NULL pointers just fine */
if (unlikely(buf))
kfree(buf);
+
}
static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 35c88bd7ba5e..0fc8bb499c3f 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -214,7 +214,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
static inline int get_color(struct vc_data *vc, struct fb_info *info,
u16 c, int is_fg)
{
- int depth = fb_get_color_depth(&info->var);
+ int depth = fb_get_color_depth(&info->var, &info->fix);
int color = 0;
if (console_blanked) {
@@ -230,9 +230,13 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
switch (depth) {
case 1:
{
+ int col = ~(0xfff << (max(info->var.green.length,
+ max(info->var.red.length,
+ info->var.blue.length)))) & 0xff;
+
/* 0 or 1 */
- int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
- int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
+ int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
+ int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
if (console_blanked)
fg = bg;
@@ -243,9 +247,25 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
case 2:
/*
* Scale down 16-colors to 4 colors. Default 4-color palette
- * is grayscale.
+ * is grayscale. However, simply dividing the values by 4
+ * will not work, as colors 1, 2 and 3 will be scaled-down
+ * to zero rendering them invisible. So empirically convert
+ * colors to a sane 4-level grayscale.
*/
- color /= 4;
+ switch (color) {
+ case 0:
+ color = 0; /* black */
+ break;
+ case 1 ... 6:
+ color = 2; /* white */
+ break;
+ case 7 ... 8:
+ color = 1; /* gray */
+ break;
+ default:
+ color = 3; /* intense white */
+ break;
+ }
break;
case 3:
/*
@@ -311,6 +331,35 @@ static void cursor_timer_handler(unsigned long dev_addr)
mod_timer(&ops->cursor_timer, jiffies + HZ/5);
}
+static void fbcon_add_cursor_timer(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+
+ if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
+ !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+ if (!info->queue.func)
+ INIT_WORK(&info->queue, fb_flashcursor, info);
+
+ init_timer(&ops->cursor_timer);
+ ops->cursor_timer.function = cursor_timer_handler;
+ ops->cursor_timer.expires = jiffies + HZ / 5;
+ ops->cursor_timer.data = (unsigned long ) info;
+ add_timer(&ops->cursor_timer);
+ ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
+ }
+}
+
+static void fbcon_del_cursor_timer(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+
+ if (info->queue.func == fb_flashcursor &&
+ ops->flags & FBCON_FLAGS_CURSOR_TIMER) {
+ del_timer_sync(&ops->cursor_timer);
+ ops->flags &= ~FBCON_FLAGS_CURSOR_TIMER;
+ }
+}
+
#ifndef MODULE
static int __init fb_console_setup(char *this_opt)
{
@@ -426,7 +475,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
* remove underline attribute from erase character
* if black and white framebuffer.
*/
- if (fb_get_color_depth(&info->var) == 1)
+ if (fb_get_color_depth(&info->var, &info->fix) == 1)
erase &= ~0x400;
logo_height = fb_prepare_logo(info);
logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -563,9 +612,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
}
if (!err) {
- if (oldinfo->queue.func == fb_flashcursor)
- del_timer_sync(&ops->cursor_timer);
-
+ fbcon_del_cursor_timer(oldinfo);
kfree(ops->cursor_state.mask);
kfree(ops->cursor_data);
kfree(oldinfo->fbcon_par);
@@ -576,22 +623,6 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
return err;
}
-static void con2fb_init_newinfo(struct fb_info *info)
-{
- if (!info->queue.func || info->queue.func == fb_flashcursor) {
- struct fbcon_ops *ops = info->fbcon_par;
-
- if (!info->queue.func)
- INIT_WORK(&info->queue, fb_flashcursor, info);
-
- init_timer(&ops->cursor_timer);
- ops->cursor_timer.function = cursor_timer_handler;
- ops->cursor_timer.expires = jiffies + HZ / 5;
- ops->cursor_timer.data = (unsigned long ) info;
- add_timer(&ops->cursor_timer);
- }
-}
-
static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
int unit, int show_logo)
{
@@ -675,7 +706,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
logo_shown != FBCON_LOGO_DONTSHOW);
if (!found)
- con2fb_init_newinfo(info);
+ fbcon_add_cursor_timer(info);
con2fb_map_boot[unit] = newidx;
con2fb_init_display(vc, info, unit, show_logo);
}
@@ -736,7 +767,7 @@ static const char *fbcon_startup(void)
const char *display_desc = "frame buffer device";
struct display *p = &fb_display[fg_console];
struct vc_data *vc = vc_cons[fg_console].d;
- struct font_desc *font = NULL;
+ const struct font_desc *font = NULL;
struct module *owner;
struct fb_info *info = NULL;
struct fbcon_ops *ops;
@@ -810,7 +841,7 @@ static const char *fbcon_startup(void)
info->var.yres);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
- vc->vc_font.data = p->fontdata = font->data;
+ vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
}
@@ -878,18 +909,7 @@ static const char *fbcon_startup(void)
}
#endif /* CONFIG_MAC */
- /* Initialize the work queue. If the driver provides its
- * own work queue this means it will use something besides
- * default timer to flash the cursor. */
- if (!info->queue.func) {
- INIT_WORK(&info->queue, fb_flashcursor, info);
-
- init_timer(&ops->cursor_timer);
- ops->cursor_timer.function = cursor_timer_handler;
- ops->cursor_timer.expires = jiffies + HZ / 5;
- ops->cursor_timer.data = (unsigned long ) info;
- add_timer(&ops->cursor_timer);
- }
+ fbcon_add_cursor_timer(info);
return display_desc;
}
@@ -921,7 +941,7 @@ static void fbcon_init(struct vc_data *vc, int init)
fb, copy the font from that console */
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -930,7 +950,7 @@ static void fbcon_init(struct vc_data *vc, int init)
}
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -1168,7 +1188,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
return;
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1178,7 +1198,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(var) != 1);
+ var->activate = FB_ACTIVATE_NOW;
+ info->var.activate = var->activate;
+ info->var.yoffset = info->var.xoffset = 0;
+ fb_set_var(info, var);
+
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -1662,6 +1687,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
+ if (logo_shown >= 0)
+ goto redraw_down;
switch (p->scrollmode) {
case SCROLL_MOVE:
ops->bmove(vc, info, t, 0, t + count, 0,
@@ -1898,7 +1925,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
static int fbcon_switch(struct vc_data *vc)
{
- struct fb_info *info;
+ struct fb_info *info, *old_info = NULL;
struct display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
int i, prev_console;
@@ -1931,7 +1958,8 @@ static int fbcon_switch(struct vc_data *vc)
}
prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon;
-
+ if (prev_console != -1)
+ old_info = registered_fb[con2fb_map[prev_console]];
/*
* FIXME: If we have multiple fbdev's loaded, we need to
* update all info->currcon. Perhaps, we can place this
@@ -1959,15 +1987,17 @@ static int fbcon_switch(struct vc_data *vc)
info->var.yoffset = info->var.xoffset = p->yscroll = 0;
fb_set_var(info, &var);
- if (prev_console != -1 &&
- registered_fb[con2fb_map[prev_console]] != info &&
- info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
+ if (old_info != NULL && old_info != info) {
+ if (info->fbops->fb_set_par)
+ info->fbops->fb_set_par(info);
+ fbcon_del_cursor_timer(old_info);
+ fbcon_add_cursor_timer(info);
+ }
set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
- vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
updatescrollmode(p, info, vc);
@@ -2048,11 +2078,16 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
fbcon_generic_blank(vc, info, blank);
}
- if (!blank)
- update_screen(vc);
- }
+ if (!blank)
+ update_screen(vc);
+ }
+
+ if (!blank)
+ fbcon_add_cursor_timer(info);
+ else
+ fbcon_del_cursor_timer(info);
- return 0;
+ return 0;
}
static void fbcon_free_font(struct display *p)
@@ -2115,7 +2150,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
}
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
- u8 * data, int userfont)
+ const u8 * data, int userfont)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
@@ -2133,7 +2168,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
cnt = FNTCHARCNT(data);
else
cnt = 256;
- vc->vc_font.data = p->fontdata = data;
+ vc->vc_font.data = (void *)(p->fontdata = data);
if ((p->userfont = userfont))
REFCOUNT(data)++;
vc->vc_font.width = w;
@@ -2290,7 +2325,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
- new_data = fb_display[i].fontdata;
+ new_data = (u8 *)fb_display[i].fontdata;
break;
}
}
@@ -2300,7 +2335,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- struct font_desc *f;
+ const struct font_desc *f;
if (!name)
f = get_default_font(info->var.xres, info->var.yres);
@@ -2332,7 +2367,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
if (!CON_IS_VISIBLE(vc))
return 0;
- depth = fb_get_color_depth(&info->var);
+ depth = fb_get_color_depth(&info->var, &info->fix);
if (depth > 3) {
for (i = j = 0; i < 16; i++) {
k = table[i];
@@ -2593,6 +2628,51 @@ static void fbcon_modechanged(struct fb_info *info)
}
}
+static void fbcon_set_all_vcs(struct fb_info *info)
+{
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct vc_data *vc;
+ struct display *p;
+ int i, rows, cols;
+
+ if (!ops || ops->currcon < 0)
+ return;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ vc = vc_cons[i].d;
+ if (!vc || vc->vc_mode != KD_TEXT ||
+ registered_fb[con2fb_map[i]] != info)
+ continue;
+
+ p = &fb_display[vc->vc_num];
+
+ info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+ var_to_display(p, &info->var, info);
+ cols = info->var.xres / vc->vc_font.width;
+ rows = info->var.yres / vc->vc_font.height;
+ vc_resize(vc, cols, rows);
+
+ if (CON_IS_VISIBLE(vc)) {
+ updatescrollmode(p, info, vc);
+ scrollback_max = 0;
+ scrollback_current = 0;
+ update_var(vc->vc_num, info);
+ fbcon_set_palette(vc, color_table);
+ update_screen(vc);
+ if (softback_buf) {
+ int l = fbcon_softback_size / vc->vc_size_row;
+ if (l > 5)
+ softback_end = softback_buf + l * vc->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0
+ would screw the operation totally */
+ softback_top = 0;
+ }
+ }
+ }
+ }
+}
+
static int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
{
@@ -2708,6 +2788,9 @@ static int fbcon_event_notify(struct notifier_block *self,
case FB_EVENT_MODE_CHANGE:
fbcon_modechanged(info);
break;
+ case FB_EVENT_MODE_CHANGE_ALL:
+ fbcon_set_all_vcs(info);
+ break;
case FB_EVENT_MODE_DELETE:
mode = event->data;
ret = fbcon_mode_deleted(info, mode);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 5d377860bce2..0738cd62def2 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,7 +18,8 @@
#include <asm/io.h>
-#define FBCON_FLAGS_INIT 1
+#define FBCON_FLAGS_INIT 1
+#define FBCON_FLAGS_CURSOR_TIMER 2
/*
* This is the interface between the low-level console driver and the
@@ -29,7 +30,7 @@ struct display {
/* Filled in by the frame buffer device */
u_short inverse; /* != 0 text black on white as default */
/* Filled in by the low-level console driver */
- u_char *fontdata;
+ const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
short yscroll; /* Hardware scrolling */
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index ff0af96e4dfc..e6aa0eab5bb6 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 9216
-static unsigned char fontdata_10x18[FONTDATAMAX] = {
+static const unsigned char fontdata_10x18[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 0000000000 */
@@ -5132,7 +5132,7 @@ static unsigned char fontdata_10x18[FONTDATAMAX] = {
};
-struct font_desc font_10x18 = {
+const struct font_desc font_10x18 = {
FONT10x18_IDX,
"10x18",
10,
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index c52f1294044a..89976cd97494 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX (11*256)
-static unsigned char fontdata_6x11[FONTDATAMAX] = {
+static const unsigned char fontdata_6x11[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = {
};
-struct font_desc font_vga_6x11 = {
+const struct font_desc font_vga_6x11 = {
VGA6x11_IDX,
"ProFont6x11",
6,
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index 1fa7fcf2ff72..bbf116647397 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 3584
-static unsigned char fontdata_7x14[FONTDATAMAX] = {
+static const unsigned char fontdata_7x14[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 0000000 */
@@ -4108,7 +4108,7 @@ static unsigned char fontdata_7x14[FONTDATAMAX] = {
};
-struct font_desc font_7x14 = {
+const struct font_desc font_7x14 = {
FONT7x14_IDX,
"7x14",
7,
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index e6f8dbaa122b..74fe86f28ff4 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_8x16[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x16 = {
+const struct font_desc font_vga_8x16 = {
VGA8x16_IDX,
"VGA8x16",
8,
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 57fbe266a6b9..26199f8ee908 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x8 = {
+const struct font_desc font_vga_8x8 = {
VGA8x8_IDX,
"VGA8x8",
8,
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index d565505e3069..2d2e39632e2d 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -3,7 +3,7 @@
#include <linux/config.h>
#include <linux/font.h>
-static unsigned char acorndata_8x8[] = {
+static const unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -262,7 +262,7 @@ static unsigned char acorndata_8x8[] = {
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-struct font_desc font_acorn_8x8 = {
+const struct font_desc font_acorn_8x8 = {
ACORN8x8_IDX,
"Acorn8x8",
8,
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 593b95500a0c..d818234fdf11 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -43,7 +43,7 @@ __END__;
#define FONTDATAMAX 1536
-static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
+static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*{*/
/* Char 0: ' ' */
@@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*}*/
};
-struct font_desc font_mini_4x6 = {
+const struct font_desc font_mini_4x6 = {
MINI4x6_IDX,
"MINI4x6",
4,
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index 5fa95f118818..e646c88f55c7 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -13,7 +13,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
};
-struct font_desc font_pearl_8x8 = {
+const struct font_desc font_pearl_8x8 = {
PEARL8x8_IDX,
"PEARL8x8",
8,
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index c7bd967ea100..ab5eb93407b4 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 11264
-static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
+static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 000000000000 */
@@ -6151,7 +6151,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
};
-struct font_desc font_sun_12x22 = {
+const struct font_desc font_sun_12x22 = {
SUN12x22_IDX,
"SUN12x22",
12,
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 2af3ab354652..41f910f5529c 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
@@ -261,7 +261,7 @@ static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
-struct font_desc font_sun_8x16 = {
+const struct font_desc font_sun_8x16 = {
SUN8x16_IDX,
"SUN8x16",
8,
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index e79b29702649..4fd07d9eca03 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -23,7 +23,7 @@
#define NO_FONTS
-static struct font_desc *fonts[] = {
+static const struct font_desc *fonts[] = {
#ifdef CONFIG_FONT_8x8
#undef NO_FONTS
&font_vga_8x8,
@@ -84,7 +84,7 @@ static struct font_desc *fonts[] = {
*
*/
-struct font_desc *find_font(char *name)
+const struct font_desc *find_font(const char *name)
{
unsigned int i;
@@ -108,10 +108,10 @@ struct font_desc *find_font(char *name)
*
*/
-struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres)
{
int i, c, cc;
- struct font_desc *f, *g;
+ const struct font_desc *f, *g;
g = NULL;
cc = -10000;
@@ -138,7 +138,6 @@ struct font_desc *get_default_font(int xres, int yres)
return g;
}
-EXPORT_SYMBOL(fonts);
EXPORT_SYMBOL(find_font);
EXPORT_SYMBOL(get_default_font);
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index e793ffd39db5..762c7a593141 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -32,7 +32,6 @@
#include <linux/font.h>
-extern struct font_desc font_vga_8x16;
extern unsigned long sgi_gfxaddr;
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index d940f605acb6..a7bcd17112c0 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -511,12 +511,12 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
struct sti_cooked_font *cooked_font;
if (!fbfont_name || !strlen(fbfont_name))
- return NULL;
+ return NULL;
fbfont = find_font(fbfont_name);
if (!fbfont)
- fbfont = get_default_font(1024,768);
+ fbfont = get_default_font(1024,768);
if (!fbfont)
- return NULL;
+ return NULL;
DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n",
fbfont->width, fbfont->height, fbfont->name));
@@ -527,7 +527,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
nf = kmalloc(size, GFP_KERNEL);
if (!nf)
- return NULL;
+ return NULL;
memset(nf, 0, size);
nf->first_char = 0;
@@ -546,8 +546,8 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font) {
- kfree(nf);
- return NULL;
+ kfree(nf);
+ return NULL;
}
cooked_font->raw = nf;
@@ -595,7 +595,7 @@ sti_select_font(struct sti_cooked_rom *rom,
static void __init
sti_dump_rom(struct sti_rom *rom)
{
- printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
+ printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
rom->graphics_id[0],
rom->graphics_id[1],
rom->revno[0] >> 4,
@@ -651,15 +651,16 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width)
struct sti_cooked_font *font;
int i = 0;
- for(font = rom->font_start; font; font = font->next_font, i++) {
- if((font->raw->width == width) && (font->raw->height == height))
+ for (font = rom->font_start; font; font = font->next_font, i++) {
+ if ((font->raw->width == width) &&
+ (font->raw->height == height))
return i;
}
return 0;
}
-#define BMODE_RELOCATE(offset) offset = (offset) / 4;
-#define BMODE_LAST_ADDR_OFFS 0x50
+#define BMODE_RELOCATE(offset) offset = (offset) / 4;
+#define BMODE_LAST_ADDR_OFFS 0x50
static void * __init
sti_bmode_font_raw(struct sti_cooked_font *f)
@@ -700,35 +701,35 @@ sti_get_bmode_rom (unsigned long address)
{
struct sti_rom *raw;
u32 size;
- struct sti_rom_font *raw_font, *font_start;
-
+ struct sti_rom_font *raw_font, *font_start;
+
sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size);
-
- size = (size+3) / 4;
+
+ size = (size+3) / 4;
raw = kmalloc(size, GFP_KERNEL);
if (raw) {
- sti_bmode_rom_copy(address, size, raw);
- memmove (&raw->res004, &raw->type[0], 0x3c);
- raw->type[3] = raw->res004;
+ sti_bmode_rom_copy(address, size, raw);
+ memmove (&raw->res004, &raw->type[0], 0x3c);
+ raw->type[3] = raw->res004;
- BMODE_RELOCATE (raw->region_list);
- BMODE_RELOCATE (raw->font_start);
+ BMODE_RELOCATE (raw->region_list);
+ BMODE_RELOCATE (raw->font_start);
- BMODE_RELOCATE (raw->init_graph);
- BMODE_RELOCATE (raw->state_mgmt);
- BMODE_RELOCATE (raw->font_unpmv);
- BMODE_RELOCATE (raw->block_move);
- BMODE_RELOCATE (raw->inq_conf);
+ BMODE_RELOCATE (raw->init_graph);
+ BMODE_RELOCATE (raw->state_mgmt);
+ BMODE_RELOCATE (raw->font_unpmv);
+ BMODE_RELOCATE (raw->block_move);
+ BMODE_RELOCATE (raw->inq_conf);
- raw_font = ((void *)raw) + raw->font_start;
- font_start = raw_font;
+ raw_font = ((void *)raw) + raw->font_start;
+ font_start = raw_font;
- while (raw_font->next_font) {
- BMODE_RELOCATE (raw_font->next_font);
- raw_font = ((void *)font_start) + raw_font->next_font;
- }
+ while (raw_font->next_font) {
+ BMODE_RELOCATE (raw_font->next_font);
+ raw_font = ((void *)font_start) + raw_font->next_font;
+ }
}
- return raw;
+ return raw;
}
struct sti_rom * __init
@@ -736,15 +737,15 @@ sti_get_wmode_rom (unsigned long address)
{
struct sti_rom *raw;
unsigned long size;
-
+
/* read the ROM size directly from the struct in ROM */
size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
raw = kmalloc(size, GFP_KERNEL);
- if(raw)
- sti_rom_copy(address, size, raw);
+ if (raw)
+ sti_rom_copy(address, size, raw);
- return raw;
+ return raw;
}
int __init
@@ -757,14 +758,14 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
if (!cooked)
goto out_err;
- if (wordmode)
- raw = sti_get_wmode_rom (address);
- else
- raw = sti_get_bmode_rom (address);
+ if (wordmode)
+ raw = sti_get_wmode_rom (address);
+ else
+ raw = sti_get_bmode_rom (address);
+
+ if (!raw)
+ goto out_err;
- if (!raw)
- goto out_err;
-
if (!sti_cook_fonts(cooked, raw)) {
printk(KERN_ERR "No font found for STI at %08lx\n", address);
goto out_err;
@@ -787,7 +788,7 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
sti->font_width = sti->font->raw->width;
sti->font_height = sti->font->raw->height;
if (!wordmode)
- sti->font->raw = sti_bmode_font_raw(sti->font);
+ sti->font->raw = sti_bmode_font_raw(sti->font);
sti->sti_mem_request = raw->sti_mem_req;
sti->graphics_id[0] = raw->graphics_id[0];
@@ -811,16 +812,16 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
u32 sig;
if (num_sti_roms >= MAX_STI_ROMS) {
- printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
- return NULL;
+ printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
+ return NULL;
}
sti = kmalloc(sizeof(*sti), GFP_KERNEL);
if (!sti) {
- printk(KERN_ERR "Not enough memory !\n");
- return NULL;
+ printk(KERN_ERR "Not enough memory !\n");
+ return NULL;
}
-
+
memset(sti, 0, sizeof(*sti));
spin_lock_init(&sti->lock);
@@ -932,28 +933,21 @@ static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *p
*/
static int __init sticore_pa_init(struct parisc_device *dev)
{
- unsigned long rom = 0;
char pa_path[21];
struct sti_struct *sti = NULL;
-
- if(dev->num_addrs) {
- rom = dev->addr[0];
- }
- if (!rom) {
- rom = dev->hpa;
- DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
- sti = sti_try_rom_generic(rom, dev->hpa, NULL);
- rom = PAGE0->proc_sti;
- }
- if (!sti) {
- DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
- sti = sti_try_rom_generic(rom, dev->hpa, NULL);
- }
+ int hpa = dev->hpa.start;
+
+ if (dev->num_addrs && dev->addr[0])
+ sti = sti_try_rom_generic(dev->addr[0], hpa, NULL);
+ if (!sti)
+ sti = sti_try_rom_generic(hpa, hpa, NULL);
+ if (!sti)
+ sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL);
if (!sti)
return 1;
-
+
print_pa_hwpath(dev, pa_path);
- sticore_check_for_default_sti (sti, pa_path);
+ sticore_check_for_default_sti(sti, pa_path);
return 0;
}
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d27fa91e5886..56cd199605f4 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -497,6 +497,57 @@ static void vgacon_cursor(struct vc_data *c, int mode)
}
}
+static int vgacon_doresize(struct vc_data *c,
+ unsigned int width, unsigned int height)
+{
+ unsigned long flags;
+ unsigned int scanlines = height * c->vc_font.height;
+ u8 scanlines_lo, r7, vsync_end, mode;
+
+ spin_lock_irqsave(&vga_lock, flags);
+
+ outb_p(VGA_CRTC_MODE, vga_video_port_reg);
+ mode = inb_p(vga_video_port_val);
+
+ if (mode & 0x04)
+ scanlines >>= 1;
+
+ scanlines -= 1;
+ scanlines_lo = scanlines & 0xff;
+
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ r7 = inb_p(vga_video_port_val) & ~0x42;
+
+ if (scanlines & 0x100)
+ r7 |= 0x02;
+ if (scanlines & 0x200)
+ r7 |= 0x40;
+
+ /* deprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ vsync_end = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end & ~0x80, vga_video_port_val);
+
+ outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
+ outb_p(width - 1, vga_video_port_val);
+ outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
+ outb_p(width >> 1, vga_video_port_val);
+
+ outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
+ outb_p(scanlines_lo, vga_video_port_val);
+ outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+ outb_p(r7,vga_video_port_val);
+
+ /* reprotect registers */
+ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+ outb_p(vsync_end, vga_video_port_val);
+
+ spin_unlock_irqrestore(&vga_lock, flags);
+
+ return 0;
+}
+
static int vgacon_switch(struct vc_data *c)
{
/*
@@ -510,9 +561,17 @@ static int vgacon_switch(struct vc_data *c)
/* We can only copy out the size of the video buffer here,
* otherwise we get into VGA BIOS */
- if (!vga_is_gfx)
+ if (!vga_is_gfx) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
- c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+ if (!(vga_video_num_columns % 2) &&
+ vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_lines <= (ORIG_VIDEO_LINES *
+ vga_default_font_height) / c->vc_font.height)
+ vgacon_doresize(c, c->vc_cols, c->vc_rows);
+ }
+
return 0; /* Redrawing not needed */
}
@@ -520,6 +579,7 @@ static void vga_set_palette(struct vc_data *vc, unsigned char *table)
{
int i, j;
+ vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
for (i = j = 0; i < 16; i++) {
vga_w(state.vgabase, VGA_PEL_IW, table[i]);
vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
@@ -662,6 +722,7 @@ static void vga_pal_blank(struct vgastate *state)
{
int i;
+ vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
for (i = 0; i < 16; i++) {
vga_w(state->vgabase, VGA_PEL_IW, i);
vga_w(state->vgabase, VGA_PEL_D, 0);
@@ -962,6 +1023,20 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
#endif
+static int vgacon_resize(struct vc_data *c, unsigned int width,
+ unsigned int height)
+{
+ if (width % 2 || width > ORIG_VIDEO_COLS ||
+ height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+ c->vc_font.height)
+ /* let svgatextmode tinker with video timings */
+ return 0;
+
+ if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
+ vgacon_doresize(c, width, height);
+ return 0;
+}
+
static int vgacon_scrolldelta(struct vc_data *c, int lines)
{
if (!lines) /* Turn scrollback off */
@@ -1103,6 +1178,7 @@ const struct consw vga_con = {
.con_blank = vgacon_blank,
.con_font_set = vgacon_font_set,
.con_font_get = vgacon_font_get,
+ .con_resize = vgacon_resize,
.con_set_palette = vgacon_set_palette,
.con_scrolldelta = vgacon_scrolldelta,
.con_set_origin = vgacon_set_origin,
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
new file mode 100644
index 000000000000..6992100a508c
--- /dev/null
+++ b/drivers/video/cyblafb.c
@@ -0,0 +1,1457 @@
+/*
+ * Frame buffer driver for Trident Cyberblade/i1 graphics core
+ *
+ * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de>
+ *
+ * CREDITS:
+ * tridentfb.c by Jani Monoses
+ * see files above for further credits
+ *
+ * TODO:
+ *
+ */
+
+#define CYBLAFB_DEBUG 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/types.h>
+#include <video/cyblafb.h>
+
+#define VERSION "0.54"
+
+struct cyblafb_par {
+ u32 pseudo_pal[16];
+ struct fb_ops ops;
+};
+
+static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
+ .id = "CyBla",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .ypanstep = 1,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static char *mode __devinitdata = NULL;
+static int bpp __devinitdata = 8;
+static int ref __devinitdata = 75;
+static int fp __devinitdata;
+static int crt __devinitdata;
+static int memsize __devinitdata;
+static int vesafb __devinitdata;
+
+static int nativex;
+static int center;
+static int stretch;
+static int pciwb = 1;
+static int pcirb = 1;
+static int pciwr = 1;
+static int pcirr = 1;
+static int verbosity;
+static int displaytype;
+
+static void __iomem * io_virt; // iospace virtual memory address
+
+module_param(mode,charp,0);
+module_param(bpp,int,0);
+module_param(ref,int,0);
+module_param(fp,int,0);
+module_param(crt,int,0);
+module_param(nativex,int,0);
+module_param(center,int,0);
+module_param(stretch,int,0);
+module_param(pciwb,int,0);
+module_param(pcirb,int,0);
+module_param(pciwr,int,0);
+module_param(pcirr,int,0);
+module_param(memsize,int,0);
+module_param(verbosity,int,0);
+module_param(vesafb,int,0);
+
+//=========================================
+//
+// Port access macros for memory mapped io
+//
+//=========================================
+
+#define out8(r,v) writeb(v,io_virt+r)
+#define out32(r,v) writel(v,io_virt+r)
+#define in8(r) readb(io_virt+r)
+#define in32(r) readl(io_virt+r)
+
+//======================================
+//
+// Hardware access inline functions
+//
+//======================================
+
+static inline unsigned char read3X4(int reg)
+{
+ out8(0x3D4,reg);
+ return in8(0x3D5);
+}
+
+static inline unsigned char read3C4(int reg)
+{
+ out8(0x3C4,reg);
+ return in8(0x3C5);
+}
+
+static inline unsigned char read3CE(int reg)
+{
+ out8(0x3CE,reg);
+ return in8(0x3CF);
+}
+
+static inline void write3X4(int reg,unsigned char val)
+{
+ out8(0x3D4,reg);
+ out8(0x3D5,val);
+}
+
+static inline void write3C4(int reg,unsigned char val)
+{
+ out8(0x3C4,reg);
+ out8(0x3C5,val);
+}
+
+static inline void write3CE(int reg,unsigned char val)
+{
+ out8(0x3CE,reg);
+ out8(0x3CF,val);
+}
+
+static inline void write3C0(int reg,unsigned char val)
+{
+ in8(0x3DA); // read to reset index
+ out8(0x3C0,reg);
+ out8(0x3C0,val);
+}
+
+//=================================================
+//
+// Enable memory mapped io and unprotect registers
+//
+//=================================================
+
+static inline void enable_mmio(void)
+{
+ int tmp;
+
+ outb(0x0B,0x3C4);
+ inb(0x3C5); // Set NEW mode
+ outb(SR0E,0x3C4); // write enable a lot of extended ports
+ outb(0x80,0x3C5);
+
+ outb(SR11,0x3C4); // write enable those extended ports that
+ outb(0x87,0x3C5); // are not affected by SR0E_New
+
+ outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2
+ tmp=inb(0x3d5) & 0xBF;
+ outb(CR1E,0x3d4);
+ outb(tmp,0x3d5);
+
+ outb(CR39,0x3D4);
+ outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched
+}
+
+//=================================================
+//
+// Set pixel clock VCLK1
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+//=================================================
+
+static void set_vclk(struct cyblafb_par *par, int freq)
+{
+ u32 m,n,k;
+ int f,fi,d,di;
+ u8 lo=0,hi=0;
+
+ d = 2000;
+ k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
+ for(m = 0;m<64;m++)
+ for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 !
+ fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12);
+ if ((di = abs(fi - freq)) < d) {
+ d = di;
+ f = fi;
+ lo = (u8) n;
+ hi = (u8) ((k<<6) | m);
+ }
+ }
+ write3C4(SR19,hi);
+ write3C4(SR18,lo);
+ if(verbosity > 1)
+ output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
+ freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+}
+
+//================================================
+//
+// Cyberblade specific Graphics Engine (GE) setup
+//
+//================================================
+
+static void cyblafb_setup_GE(int pitch,int bpp)
+{
+ int base = (pitch>>3)<<20;
+
+ switch (bpp) {
+ case 8: base |= (0<<29); break;
+ case 15: base |= (5<<29); break;
+ case 16: base |= (1<<29); break;
+ case 24:
+ case 32: base |= (2<<29); break;
+ }
+
+ write3X4(CR36,0x90); // reset GE
+ write3X4(CR36,0x80); // enable GE
+
+ out32(GE24,1<<7); // reset all GE pointers
+ out32(GE24,0);
+
+ write3X4(CR2D,0x00); // GE Timinigs, no delays
+
+ out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
+ out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
+ out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
+ out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
+ out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
+ out32(GECC,base); // Source Stride / Buffer Base 1, p 133
+ out32(GED0,base); // Source Stride / Buffer Base 2, p 133
+ out32(GED4,base); // Source Stride / Buffer Base 3, p 133
+ out32(GE6C,0); // Pattern and Style, p 129, ok
+}
+
+//=====================================================================
+//
+// Although this is a .fb_sync function that could be enabled in
+// cyblafb_ops, we do not include it there. We sync immediately before
+// new GE operations to improve performance.
+//
+//=====================================================================
+
+static int cyblafb_sync(struct fb_info *info)
+{
+ int status, i=100000;
+ while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ i--;
+
+ if (i == 0) {
+ // The timeout might be caused by disabled mmio.
+ // Cause:
+ // - bit CR39 & 1 == 0 upon return, X trident driver bug
+ // - kdm bug (KD_GRAPHICS not set on first switch)
+ // - kernel design flaw (it believes in the correctness
+ // of kdm/X
+ // So we make sure that mmio is enabled first ...
+ enable_mmio();
+// show_trace(NULL,&status);
+ i=1000000;
+ while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ i--;
+ if (i == 0) {
+ output("GE Timeout, status: %x\n",status);
+ if(status & 0x80000000)
+ output("Bresenham Engine : Busy\n");
+ if(status & 0x40000000)
+ output("Setup Engine : Busy\n");
+ if(status & 0x20000000)
+ output("SP / DPE : Busy\n");
+ if(status & 0x10000000)
+ output("Memory Interface : Busy\n");
+ if(status & 0x08000000)
+ output("Com Lst Proc : Busy\n");
+ if(status & 0x04000000)
+ output("Block Write : Busy\n");
+ if(status & 0x02000000)
+ output("Command Buffer : Full\n");
+ if(status & 0x01000000)
+ output("RESERVED : Busy\n");
+ if(status & 0x00800000)
+ output("PCI Write Buffer : Busy\n");
+ cyblafb_setup_GE(info->var.xres,
+ info->var.bits_per_pixel);
+ }
+ }
+
+ return 0;
+}
+
+//==============================
+//
+// Cyberblade specific fillrect
+//
+//==============================
+
+static void cyblafb_fillrect(struct fb_info * info,
+ const struct fb_fillrect *fr)
+{
+ int bpp = info->var.bits_per_pixel;
+ int col;
+
+ switch (bpp) {
+ default:
+ case 8: col = fr->color;
+ col |= col <<8;
+ col |= col <<16;
+ break;
+ case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
+ col |= col <<16;
+ break;
+ case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
+ break;
+ }
+
+ cyblafb_sync(info);
+
+ out32(GE60,col);
+ out32(GE48,fr->rop ? 0x66:ROP_S);
+ out32(GE44,0x20000000|1<<19|1<<4|2<<2);
+ out32(GE08,point(fr->dx,fr->dy));
+ out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1));
+
+}
+
+//==============================
+//
+// Cyberblade specific copyarea
+//
+//==============================
+
+static void cyblafb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *ca)
+{
+ __u32 s1,s2,d1,d2;
+ int direction;
+
+ s1 = point(ca->sx,ca->sy);
+ s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
+ d1 = point(ca->dx,ca->dy);
+ d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
+ if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
+ direction = 0;
+ else
+ direction = 2;
+
+ cyblafb_sync(info);
+
+ out32(GE44,0xa0000000|1<<19|1<<2|direction);
+ out32(GE00,direction?s2:s1);
+ out32(GE04,direction?s1:s2);
+ out32(GE08,direction?d2:d1);
+ out32(GE0C,direction?d1:d2);
+
+}
+
+//=======================================================================
+//
+// Cyberblade specific imageblit
+//
+// Accelerated for the most usual case, blitting 1-bit deep character
+// character images. Everything else is passed to the generic imageblit.
+//
+//=======================================================================
+
+static void cyblafb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+
+ u32 fgcol, bgcol;
+
+ int i;
+ int bpp = info->var.bits_per_pixel;
+ int index = 0;
+ int index_end=image->height * image->width / 8;
+ int width_dds=image->width / 32;
+ int width_dbs=image->width % 32;
+
+ if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 ||
+ image->width % 8 != 0 || image->width == 0 || image->height == 0) {
+ cfb_imageblit(info,image);
+ return;
+ }
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ fgcol = ((u32*)(info->pseudo_palette))[image->fg_color];
+ bgcol = ((u32*)(info->pseudo_palette))[image->bg_color];
+ } else {
+ fgcol = image->fg_color;
+ bgcol = image->bg_color;
+ }
+
+ switch (bpp) {
+ case 8:
+ fgcol |= fgcol <<8; fgcol |= fgcol <<16;
+ bgcol |= bgcol <<8; bgcol |= bgcol <<16;
+ break;
+ case 16:
+ fgcol |= fgcol <<16;
+ bgcol |= bgcol <<16;
+ break;
+ default:
+ break;
+ }
+
+ cyblafb_sync(info);
+
+ out32(GE60,fgcol);
+ out32(GE64,bgcol);
+ out32(GE44,0xa0000000 | 1<<20 | 1<<19);
+ out32(GE08,point(image->dx,image->dy));
+ out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
+
+ while(index < index_end) {
+ const char *p = image->data + index;
+ for(i=0;i<width_dds;i++) {
+ out32(GE9C,*(u32*)p);
+ p+=4;
+ index+=4;
+ }
+ switch(width_dbs) {
+ case 0: break;
+ case 8: out32(GE9C,*(u8*)p);
+ index+=1;
+ break;
+ case 16: out32(GE9C,*(u16*)p);
+ index+=2;
+ break;
+ case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16);
+ index+=3;
+ break;
+ }
+ }
+}
+
+//==========================================================
+//
+// Check if video mode is acceptable. We change var->??? if
+// video mode is slightly off or return error otherwise.
+// info->??? must not be changed!
+//
+//==========================================================
+
+static int cyblafb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int bpp = var->bits_per_pixel;
+ int s,t,maxvyres;
+
+ //
+ // we try to support 8, 16, 24 and 32 bpp modes,
+ // default to 8
+ //
+ // there is a 24 bpp mode, but for now we change requests to 32 bpp
+ // (This is what tridentfb does ... will be changed in the future)
+ //
+ //
+ if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+ bpp = 8;
+ if (bpp == 24 )
+ bpp = var->bits_per_pixel = 32;
+
+ //
+ // interlaced modes are broken, fail if one is requested
+ //
+ if (var->vmode & FB_VMODE_INTERLACED)
+ return -EINVAL;
+
+ //
+ // fail if requested resolution is higher than physical
+ // flatpanel resolution
+ //
+ if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex)
+ return -EINVAL;
+
+ //
+ // xres != xres_virtual is broken, fail if such an
+ // unusual mode is requested
+ //
+ if (var->xres != var->xres_virtual)
+ return -EINVAL;
+
+ //
+ // we do not allow vclk to exceed 230 MHz
+ //
+ if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
+ return -EINVAL;
+
+ //
+ // calc max yres_virtual that would fit in memory
+ // and max yres_virtual that could be used for scrolling
+ // and use minimum of the results as maxvyres
+ //
+ // adjust vyres_virtual to maxvyres if necessary
+ // fail if requested yres is bigger than maxvyres
+ //
+ s = (0x1fffff / (var->xres * bpp/8)) + var->yres;
+ t = info->fix.smem_len / (var->xres * bpp/8);
+ maxvyres = t < s ? t : s;
+ if (maxvyres < var->yres_virtual)
+ var->yres_virtual=maxvyres;
+ if (maxvyres < var->yres)
+ return -EINVAL;
+
+ switch (bpp) {
+ 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:
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
+//=====================================================================
+//
+// Pan the display
+//
+// The datasheets defines crt start address to be 20 bits wide and
+// to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is
+// CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use
+// it, so it is also safe to be used here. BTW: datasheet CR0E on page
+// 90 really is CR1E, the real CRE is documented on page 72.
+//
+//=====================================================================
+
+static int cyblafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ unsigned int offset;
+
+ offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+
+ write3X4(CR0D,offset & 0xFF);
+ write3X4(CR0C,(offset & 0xFF00) >> 8);
+ write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
+ write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
+ write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
+
+ return 0;
+}
+
+//============================================
+//
+// This will really help in case of a bug ...
+// dump most gaphics core registers.
+//
+//============================================
+
+static void regdump(struct cyblafb_par *par)
+{
+ int i;
+
+ if (verbosity < 2)
+ return;
+
+ printk("\n");
+ for(i=0; i<=0xff; i++) {
+ outb(i,0x3d4);
+ printk("CR%02x=%02x ",i,inb(0x3d5));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ outb(0x30,0x3ce);
+ outb(inb(0x3cf) | 0x40,0x3cf);
+ for(i=0; i<=0x1f; i++) {
+ if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) {
+ outb(i,0x3d4);
+ printk("CR%02x=%02x ",i,inb(0x3d5));
+ } else
+ printk("------- ");
+ if (i%16==15)
+ printk("\n");
+ }
+ outb(0x30,0x3ce);
+ outb(inb(0x3cf) & 0xbf,0x3cf);
+
+ printk("\n");
+ for(i=0; i<=0x7f; i++) {
+ outb(i,0x3ce);
+ printk("GR%02x=%02x ",i,inb(0x3cf));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ printk("\n");
+ for(i=0; i<=0xff; i++) {
+ outb(i,0x3c4);
+ printk("SR%02x=%02x ",i,inb(0x3c5));
+ if (i%16==15)
+ printk("\n");
+ }
+
+ printk("\n");
+ for(i=0; i <= 0x1F; i++) {
+ inb(0x3da); // next access is index!
+ outb(i,0x3c0);
+ printk("AR%02x=%02x ",i,inb(0x3c1));
+ if (i%16==15)
+ printk("\n");
+ }
+ printk("\n");
+
+ inb(0x3DA); // reset internal flag to 3c0 index
+ outb(0x20,0x3C0); // enable attr
+
+ return;
+}
+
+//======================================
+//
+// Set hardware to requested video mode
+//
+//======================================
+
+static int cyblafb_set_par(struct fb_info *info)
+{
+ struct cyblafb_par *par = info->par;
+ u32
+ htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch,
+ vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
+ struct fb_var_screeninfo *var = &info->var;
+ int bpp = var->bits_per_pixel;
+ int i;
+
+ if (verbosity > 0)
+ output("Switching to new mode: "
+ "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
+ var->xres,var->yres,var->xres_virtual,
+ var->yres_virtual,var->bits_per_pixel,var->pixclock,
+ var->left_margin,var->right_margin,var->upper_margin,
+ var->lower_margin,var->hsync_len,var->vsync_len);
+
+ htotal = (var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) / 8 - 5;
+ hdispend = var->xres/8 - 1;
+ hsyncstart = (var->xres + var->right_margin)/8;
+ hsyncend = var->hsync_len/8;
+ hblankstart = hdispend + 1;
+ hblankend = htotal + 3; // should be htotal + 5, bios does it this way
+ preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3);
+
+ vtotal = var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len - 2;
+ vdispend = var->yres - 1;
+ vsyncstart = var->yres + var->lower_margin;
+ vblankstart = var->yres;
+ vblankend = vtotal; // should be vtotal + 2, but bios does it this way
+ vsyncend = var->vsync_len;
+
+ enable_mmio(); // necessary! ... check X ...
+
+ write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+
+ write3CE(GR30,8);
+
+ if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
+
+ // stretch or center ?
+
+ out8(0x3C2,0xEB);
+
+ write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+
+ if (center) {
+ write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80);
+ write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80);
+ }
+ else if (stretch) {
+ write3CE(GR5D,0);
+ write3CE(GR52,(read3CE(GR52) & 0x7C) | 1);
+ write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
+ }
+
+ } else {
+ out8(0x3C2,0x2B);
+ write3CE(GR30,8);
+ }
+
+ //
+ // Setup CRxx regs
+ //
+
+ write3X4(CR00,htotal & 0xFF);
+ write3X4(CR01,hdispend & 0xFF);
+ write3X4(CR02,hblankstart & 0xFF);
+ write3X4(CR03,hblankend & 0x1F);
+ write3X4(CR04,hsyncstart & 0xFF);
+ write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
+ write3X4(CR06,vtotal & 0xFF);
+ write3X4(CR07,(vtotal & 0x100) >> 8 |
+ (vdispend & 0x100) >> 7 |
+ (vsyncstart & 0x100) >> 6 |
+ (vblankstart & 0x100) >> 5 |
+ 0x10 |
+ (vtotal & 0x200) >> 4 |
+ (vdispend & 0x200) >> 3 |
+ (vsyncstart & 0x200) >> 2);
+ write3X4(CR08,0);
+ write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 | // FIX !!!
+ ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
+ write3X4(CR0A,0); // Init to some reasonable default
+ write3X4(CR0B,0); // Init to some reasonable default
+ write3X4(CR0C,0); // Offset 0
+ write3X4(CR0D,0); // Offset 0
+ write3X4(CR0E,0); // Init to some reasonable default
+ write3X4(CR0F,0); // Init to some reasonable default
+ write3X4(CR10,vsyncstart & 0xFF);
+ write3X4(CR11,(vsyncend & 0x0F));
+ write3X4(CR12,vdispend & 0xFF);
+ write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF);
+ write3X4(CR14,0x40); // double word mode
+ write3X4(CR15,vblankstart & 0xFF);
+ write3X4(CR16,vblankend & 0xFF);
+ write3X4(CR17,0xC3);
+ write3X4(CR18,0xFF);
+ // CR19: needed for interlaced modes ... ignore it for now
+ write3X4(CR1A,0x07); // Arbitration Control Counter 1
+ write3X4(CR1B,0x07); // Arbitration Control Counter 2
+ write3X4(CR1C,0x07); // Arbitration Control Counter 3
+ write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-)
+ write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
+ // CR1F: do not set, contains BIOS info about memsize
+ write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode
+ write3X4(CR21,0x20); // enable linear memory access
+ // CR22: RO cpu latch readback
+ // CR23: ???
+ // CR24: RO AR flag state
+ // CR25: RAMDAC rw timing, pclk buffer tristate control ????
+ // CR26: ???
+ write3X4(CR27,(vdispend & 0x400) >> 6 |
+ (vsyncstart & 0x400) >> 5 |
+ (vblankstart & 0x400) >> 4 |
+ (vtotal & 0x400) >> 3 |
+ 0x8);
+ // CR28: ???
+ write3X4(CR29,(read3X4(CR29) & 0xCF) |
+ ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4));
+ write3X4(CR2A,read3X4(CR2A) | 0x40);
+ write3X4(CR2B,(htotal & 0x100) >> 8 |
+ (hdispend & 0x100) >> 7 |
+ // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ???
+ (hsyncstart & 0x100) >> 5 |
+ (hblankstart & 0x100) >> 4);
+ // CR2C: ???
+ // CR2D: initialized in cyblafb_setup_GE()
+ write3X4(CR2F,0x92); // conservative, better signal quality
+ // CR30: reserved
+ // CR31: reserved
+ // CR32: reserved
+ // CR33: reserved
+ // CR34: disabled in CR36
+ // CR35: disabled in CR36
+ // CR36: initialized in cyblafb_setup_GE
+ // CR37: i2c, ignore for now
+ write3X4(CR38,(bpp == 8) ? 0x00 : //
+ (bpp == 16) ? 0x05 : // highcolor
+ (bpp == 24) ? 0x29 : // packed 24bit truecolor
+ (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
+ write3X4(CR39,0x01 | // MMIO enable
+ (pcirb ? 0x02 : 0) | // pci read burst enable
+ (pciwb ? 0x04 : 0)); // pci write burst enable
+ write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase
+ (pcirr ? 0x40 : 0) | // pci read retry enable
+ (pciwr ? 0x80 : 0)); // pci write retry enable
+ write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0);
+ write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
+ write3X4(CR58,0x82); // Bios does this .... don't know more
+ //
+ // Setup SRxx regs
+ //
+ write3C4(SR00,3);
+ write3C4(SR01,1); //set char clock 8 dots wide
+ write3C4(SR02,0x0F); //enable 4 maps needed in chain4 mode
+ write3C4(SR03,0); //no character map select
+ write3C4(SR04,0x0E); //memory mode: ext mem, even, chain4
+
+ out8(0x3C4,0x0b);
+ in8(0x3C5); // Set NEW mode
+ write3C4(SR0D,0x00); // test ... check
+
+ set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
+ info->var.pixclock); //SR18,SR19
+
+ //
+ // Setup GRxx regs
+ //
+ write3CE(GR00,0x00); // test ... check
+ write3CE(GR01,0x00); // test ... check
+ write3CE(GR02,0x00); // test ... check
+ write3CE(GR03,0x00); // test ... check
+ write3CE(GR04,0x00); // test ... check
+ write3CE(GR05,0x40); // no CGA compat,allow 256 col
+ write3CE(GR06,0x05); // graphics mode
+ write3CE(GR07,0x0F); // planes?
+ write3CE(GR08,0xFF); // test ... check
+ write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4
+ write3CE(GR20,0xC0); // test ... check
+ write3CE(GR2F,0xA0); // PCLK = VCLK, no skew,
+
+ //
+ // Setup ARxx regs
+ //
+ for(i = 0;i < 0x10;i++) // set AR00 .. AR0f
+ write3C0(i,i);
+ write3C0(AR10,0x41); // graphics mode and support 256 color modes
+ write3C0(AR12,0x0F); // planes
+ write3C0(AR13,0); // horizontal pel panning
+ in8(0x3DA); // reset internal flag to 3c0 index
+ out8(0x3C0,0x20); // enable attr
+
+ //
+ // Setup hidden RAMDAC command register
+ //
+ in8(0x3C8); // these reads are
+ in8(0x3C6); // necessary to
+ in8(0x3C6); // unmask the RAMDAC
+ in8(0x3C6); // command reg, otherwise
+ in8(0x3C6); // we would write the pixelmask reg!
+ out8(0x3C6,(bpp == 8) ? 0x00 : // 256 colors
+ (bpp == 15) ? 0x10 : //
+ (bpp == 16) ? 0x30 : // hicolor
+ (bpp == 24) ? 0xD0 : // truecolor
+ (bpp == 32) ? 0xD0 : 0); // truecolor
+ in8(0x3C8);
+
+ //
+ // GR31 is not mentioned in the datasheet
+ //
+ if (displaytype == DISPLAY_FP)
+ write3CE(GR31,(read3CE(GR31) & 0x8F) |
+ ((info->var.yres > 1024) ? 0x50 :
+ (info->var.yres > 768) ? 0x30 :
+ (info->var.yres > 600) ? 0x20 :
+ (info->var.yres > 480) ? 0x10 : 0));
+
+ info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_TRUECOLOR;
+ info->fix.line_length = info->var.xres * (bpp >> 3);
+ info->cmap.len = (bpp == 8) ? 256: 16;
+
+ //
+ // init acceleration engine
+ //
+ cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+
+ regdump(par);
+
+ return 0;
+}
+
+//========================
+//
+// Set one color register
+//
+//========================
+
+static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ int bpp = info->var.bits_per_pixel;
+
+ if (regno >= info->cmap.len)
+ return 1;
+
+ if (bpp == 8) {
+ out8(0x3C6,0xFF);
+ out8(0x3C8,regno);
+ out8(0x3C9,red>>10);
+ out8(0x3C9,green>>10);
+ out8(0x3C9,blue>>10);
+
+ } else if (bpp == 16) // RGB 565
+ ((u32*)info->pseudo_palette)[regno] =
+ (red & 0xF800) |
+ ((green & 0xFC00) >> 5) |
+ ((blue & 0xF800) >> 11);
+ else if (bpp == 32) // ARGB 8888
+ ((u32*)info->pseudo_palette)[regno] =
+ ((transp & 0xFF00) <<16) |
+ ((red & 0xFF00) << 8) |
+ ((green & 0xFF00)) |
+ ((blue & 0xFF00)>>8);
+
+ return 0;
+}
+
+//==========================================================
+//
+// Try blanking the screen. For flat panels it does nothing
+//
+//==========================================================
+
+static int cyblafb_blank(int blank_mode, struct fb_info *info)
+{
+ unsigned char PMCont,DPMSCont;
+
+ if (displaytype == DISPLAY_FP)
+ return 0;
+
+ out8(0x83C8,0x04); // DPMS Control
+ PMCont = in8(0x83C6) & 0xFC;
+
+ DPMSCont = read3CE(GR23) & 0xFC;
+
+ switch (blank_mode)
+ {
+ case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On
+ case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On
+ PMCont |= 0x03;
+ DPMSCont |= 0x00;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
+ PMCont |= 0x02;
+ DPMSCont |= 0x01;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
+ PMCont |= 0x02;
+ DPMSCont |= 0x02;
+ break;
+ case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
+ PMCont |= 0x00;
+ DPMSCont |= 0x03;
+ break;
+ }
+
+ write3CE(GR23,DPMSCont);
+ out8(0x83C8,4);
+ out8(0x83C6,PMCont);
+ //
+ // let fbcon do a softblank for us
+ //
+ return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops cyblafb_ops __devinitdata = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = cyblafb_setcolreg,
+ .fb_pan_display = cyblafb_pan_display,
+ .fb_blank = cyblafb_blank,
+ .fb_check_var = cyblafb_check_var,
+ .fb_set_par = cyblafb_set_par,
+ .fb_fillrect = cyblafb_fillrect,
+ .fb_copyarea= cyblafb_copyarea,
+ .fb_imageblit = cyblafb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+//==========================================================================
+//
+// getstartupmode() decides about the inital video mode
+//
+// There is no reason to use modedb, a lot of video modes there would
+// need altered timings to display correctly. So I decided that it is much
+// better to provide a limited optimized set of modes plus the option of
+// using the mode in effect at startup time (might be selected using the
+// vga=??? paramter). After that the user might use fbset to select any
+// mode he likes, check_var will not try to alter geometry parameters as
+// it would be necessary otherwise.
+//
+//==========================================================================
+
+static int __devinit getstartupmode(struct fb_info *info)
+{
+ u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
+ vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend,
+ cr00,cr01,cr02,cr03,cr04,cr05,cr2b,
+ cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27,
+ cr38,
+ sr0d,sr18,sr19,
+ gr0f,
+ fi,pxclkdiv,vclkdiv,tmp,i;
+
+ struct modus {
+ int xres; int yres; int vyres; int bpp; int pxclk;
+ int left_margin; int right_margin; int upper_margin;
+ int lower_margin; int hsync_len; int vsync_len;
+ } modedb[5] = {
+ { 0, 0, 8000, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 640, 480, 3756, 0, 0, -40, 24, 17, 0, 216, 3},
+ { 800, 600, 3221, 0, 0, 96, 24, 14, 0, 136, 11},
+ {1024, 768, 2815, 0, 0, 144, 24, 29, 0, 120, 3},
+ {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160, 3}
+ };
+
+ outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5);
+ outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5);
+ outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5);
+ outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5);
+ outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5);
+ outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5);
+ outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5);
+ outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5);
+ outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5);
+ outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5);
+ outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf);
+
+ htotal = cr00 | (cr2b & 0x01) << 8;
+ hdispend = cr01 | (cr2b & 0x02) << 7;
+ hblankstart = cr02 | (cr2b & 0x10) << 4;
+ hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
+ hsyncstart = cr04 | (cr2b & 0x08) << 5;
+ hsyncend = cr05 & 0x1f;
+
+ modedb[0].xres = hblankstart * 8;
+ modedb[0].hsync_len = hsyncend * 8;
+ modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
+ modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
+ modedb[0].right_margin - modedb[0].hsync_len;
+
+ vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
+ | (cr27 & 0x80) << 3;
+ vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
+ | (cr27 & 0x10) << 6;
+ vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
+ | (cr27 & 0x20) << 5;
+ vsyncend = cr11 & 0x0f;
+ vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
+ | (cr27 & 0x40) << 4;
+ vblankend = cr16;
+
+ modedb[0].yres = vdispend + 1;
+ modedb[0].vsync_len = vsyncend;
+ modedb[0].lower_margin = vsyncstart - modedb[0].yres;
+ modedb[0].upper_margin = vtotal - modedb[0].yres -
+ modedb[0].lower_margin - modedb[0].vsync_len + 2;
+
+ tmp = cr38 & 0x3c;
+ modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
+ tmp == 8 ? 32 : 8;
+
+ fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+ pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
+ tmp = sr0d & 0x06;
+ vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
+ modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi;
+
+ if (verbosity > 0)
+ output("detected startup mode: "
+ "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
+ modedb[0].xres,modedb[0].yres,modedb[0].xres,
+ modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin,
+ modedb[0].right_margin,modedb[0].upper_margin,
+ modedb[0].lower_margin,modedb[0].hsync_len,
+ modedb[0].vsync_len);
+
+ //
+ // We use this goto target in case of a failed check_var. No, I really
+ // do not want to do it in another way!
+ //
+
+ tryagain:
+
+ i = (mode == NULL) ? 0 :
+ !strncmp(mode,"640x480",7) ? 1 :
+ !strncmp(mode,"800x600",7) ? 2 :
+ !strncmp(mode,"1024x768",8) ? 3 :
+ !strncmp(mode,"1280x1024",9) ? 4 : 0;
+
+ ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
+
+ if(i==0) {
+ info->var.pixclock = modedb[i].pxclk;
+ info->var.bits_per_pixel = modedb[i].bpp;
+ } else {
+ info->var.pixclock = (100000000 /
+ ((modedb[i].left_margin + modedb[i].xres +
+ modedb[i].right_margin + modedb[i].hsync_len
+ ) * (
+ modedb[i].upper_margin + modedb[i].yres +
+ modedb[i].lower_margin + modedb[i].vsync_len
+ ) *
+ ref / 10000
+ ));
+ info->var.bits_per_pixel = bpp;
+ }
+
+ info->var.left_margin = modedb[i].left_margin;
+ info->var.right_margin = modedb[i].right_margin;
+ info->var.xres = modedb[i].xres;
+ info->var.xres_virtual = modedb[i].xres;
+ info->var.xoffset = 0;
+ info->var.hsync_len = modedb[i].hsync_len;
+ info->var.upper_margin = modedb[i].upper_margin;
+ info->var.yres = modedb[i].yres;
+ info->var.yres_virtual = modedb[i].vyres;
+ info->var.yoffset = 0;
+ info->var.lower_margin = modedb[i].lower_margin;
+ info->var.vsync_len = modedb[i].vsync_len;
+ info->var.sync = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ if(cyblafb_check_var(&info->var,info)) {
+ // 640x480-8@75 should really never fail. One case would
+ // be fp == 1 and nativex < 640 ... give up then
+ if(i==1 && bpp == 8 && ref == 75){
+ output("Can't find a valid mode :-(\n");
+ return -EINVAL;
+ }
+ // Our detected mode is unlikely to fail. If it does,
+ // try 640x480-8@75 ...
+ if(i==0) {
+ mode="640x480";
+ bpp=8;
+ ref=75;
+ output("Detected mode failed check_var! "
+ "Trying 640x480-8@75\n");
+ goto tryagain;
+ }
+ // A specified video mode failed for some reason.
+ // Try the startup mode first
+ output("Specified mode '%s' failed check! "
+ "Falling back to startup mode.\n",mode);
+ mode=NULL;
+ goto tryagain;
+ }
+
+ return 0;
+
+}
+
+//========================================================
+//
+// Detect activated memory size. Undefined values require
+// memsize parameter.
+//
+//========================================================
+
+static unsigned int __devinit get_memsize(void)
+{
+ unsigned char tmp;
+ unsigned int k;
+
+ if (memsize)
+ k = memsize * Kb;
+ else {
+ tmp = read3X4(CR1F) & 0x0F;
+ switch (tmp) {
+ case 0x03: k = 1 * Mb; break;
+ case 0x07: k = 2 * Mb; break;
+ case 0x0F: k = 4 * Mb; break;
+ case 0x04: k = 8 * Mb; break;
+ default:
+ k = 1 * Mb;
+ output("Unknown memory size code %x in CR1F."
+ " We default to 1 Mb for now, please"
+ " do provide a memsize parameter!\n",
+ tmp);
+ }
+ }
+
+ if (verbosity > 0)
+ output("framebuffer size = %d Kb\n",k/Kb);
+ return k;
+}
+
+//=========================================================
+//
+// Detect if a flat panel monitor connected to the special
+// interface is active. Override is possible by fp and crt
+// parameters.
+//
+//=========================================================
+
+static unsigned int __devinit get_displaytype(void)
+{
+ if (fp)
+ return DISPLAY_FP;
+ if (crt)
+ return DISPLAY_CRT;
+ return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+}
+
+//=====================================
+//
+// Get native resolution of flat panel
+//
+//=====================================
+
+static int __devinit get_nativex(void)
+{
+ int x,y,tmp;
+
+ if (nativex)
+ return nativex;
+
+ tmp = (read3CE(GR52) >> 4) & 3;
+
+ switch (tmp) {
+ case 0: x = 1280; y = 1024; break;
+ case 2: x = 1024; y = 768; break;
+ case 3: x = 800; y = 600; break;
+ case 4: x = 1400; y = 1050; break;
+ case 1:
+ default: x = 640; y = 480; break;
+ }
+
+ if (verbosity > 0)
+ output("%dx%d flat panel found\n",x,y);
+ return x;
+}
+
+static int __devinit cybla_pci_probe(struct pci_dev * dev,
+ const struct pci_device_id * id)
+{
+ struct fb_info *info;
+ struct cyblafb_par *par;
+
+ info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev);
+
+ if (!info)
+ goto errout_alloc;
+
+ par = info->par;
+ par->ops = cyblafb_ops;
+
+ info->fix = cyblafb_fix;
+ info->fbops = &par->ops;
+ info->fix = cyblafb_fix;
+
+ if (pci_enable_device(dev)) {
+ output("could not enable device!\n");
+ goto errout_enable;
+ }
+
+ // might already be requested by vga console or vesafb,
+ // so we do care about success
+ request_region(0x3c0,32,"cyblafb");
+
+ //
+ // Graphics Engine Registers
+ //
+ request_region(GEBase,0x100,"cyblafb");
+
+ regdump(par);
+
+ enable_mmio();
+
+ // setup MMIO region
+ info->fix.mmio_start = pci_resource_start(dev,1);
+ info->fix.mmio_len = 0x20000;
+
+ if (!request_mem_region(info->fix.mmio_start,
+ info->fix.mmio_len,"cyblafb")) {
+ output("request_mem_region failed for mmio region!\n");
+ goto errout_mmio_reqmem;
+ }
+
+ io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+
+ if (!io_virt) {
+ output("ioremap failed for mmio region\n");
+ goto errout_mmio_remap;
+ }
+
+ // setup framebuffer memory ... might already be requested
+ // by vesafb. Not to fail in case of an unsuccessful request
+ // is useful for the development cycle
+ info->fix.smem_start = pci_resource_start(dev,0);
+ info->fix.smem_len = get_memsize();
+
+ if (!request_mem_region(info->fix.smem_start,
+ info->fix.smem_len,"cyblafb")) {
+ output("request_mem_region failed for smem region!\n");
+ if (!vesafb)
+ goto errout_smem_req;
+ }
+
+ info->screen_base = ioremap_nocache(info->fix.smem_start,
+ info->fix.smem_len);
+
+ if (!info->screen_base) {
+ output("ioremap failed for smem region\n");
+ goto errout_smem_remap;
+ }
+
+ displaytype = get_displaytype();
+
+ if(displaytype == DISPLAY_FP)
+ nativex = get_nativex();
+
+ //
+ // FBINFO_HWACCEL_YWRAP .... does not work (could be made to work?)
+ // FBINFO_PARTIAL_PAN_OK .... is not ok
+ // FBINFO_READS_FAST .... is necessary for optimal scrolling
+ //
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN
+ | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
+
+ info->pseudo_palette = par->pseudo_pal;
+
+ if(getstartupmode(info))
+ goto errout_findmode;
+
+ fb_alloc_cmap(&info->cmap,256,0);
+
+ if (register_framebuffer(info)) {
+ output("Could not register CyBla framebuffer\n");
+ goto errout_register;
+ }
+
+ pci_set_drvdata(dev,info);
+
+ //
+ // normal exit and error paths
+ //
+
+ return 0;
+
+ errout_register:
+ errout_findmode:
+ iounmap(info->screen_base);
+ errout_smem_remap:
+ release_mem_region(info->fix.smem_start,
+ info->fix.smem_len);
+ errout_smem_req:
+ iounmap(io_virt);
+ errout_mmio_remap:
+ release_mem_region(info->fix.mmio_start,
+ info->fix.mmio_len);
+ errout_mmio_reqmem:
+// release_region(0x3c0,32);
+ errout_enable:
+ framebuffer_release(info);
+ errout_alloc:
+ output("CyblaFB version %s aborting init.\n",VERSION);
+ return -ENODEV;
+}
+
+static void __devexit cybla_pci_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ unregister_framebuffer(info);
+ iounmap(io_virt);
+ iounmap(info->screen_base);
+ release_mem_region(info->fix.smem_start,info->fix.smem_len);
+ release_mem_region(info->fix.mmio_start,info->fix.mmio_len);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ output("CyblaFB version %s normal exit.\n",VERSION);
+}
+
+//
+// List of boards that we are trying to support
+//
+static struct pci_device_id cybla_devices[] = {
+ {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci,cybla_devices);
+
+static struct pci_driver cyblafb_pci_driver = {
+ .name = "cyblafb",
+ .id_table = cybla_devices,
+ .probe = cybla_pci_probe,
+ .remove = __devexit_p(cybla_pci_remove)
+};
+
+//=============================================================
+//
+// kernel command line example:
+//
+// video=cyblafb:1280x1024,bpp=16,ref=50 ...
+//
+// modprobe command line example:
+//
+// modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
+//
+//=============================================================
+
+static int __devinit cyblafb_init(void)
+{
+#ifndef MODULE
+ char *options = NULL;
+ char *opt;
+
+ if (fb_get_options("cyblafb",&options))
+ return -ENODEV;
+
+ if (options && *options)
+ while((opt = strsep(&options,",")) != NULL ) {
+ if (!*opt) continue;
+ else if (!strncmp(opt,"bpp=",4))
+ bpp = simple_strtoul(opt+4,NULL,0);
+ else if (!strncmp(opt,"ref=",4))
+ ref = simple_strtoul(opt+4,NULL,0);
+ else if (!strncmp(opt,"fp",2))
+ displaytype = DISPLAY_FP;
+ else if (!strncmp(opt,"crt",3))
+ displaytype = DISPLAY_CRT;
+ else if (!strncmp(opt,"nativex=",8))
+ nativex = simple_strtoul(opt+8,NULL,0);
+ else if (!strncmp(opt,"center",6))
+ center = 1;
+ else if (!strncmp(opt,"stretch",7))
+ stretch = 1;
+ else if (!strncmp(opt,"pciwb=",6))
+ pciwb = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pcirb=",6))
+ pcirb = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pciwr=",6))
+ pciwr = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"pcirr=",6))
+ pcirr = simple_strtoul(opt+6,NULL,0);
+ else if (!strncmp(opt,"memsize=",8))
+ memsize = simple_strtoul(opt+8,NULL,0);
+ else if (!strncmp(opt,"verbosity=",10))
+ verbosity = simple_strtoul(opt+10,NULL,0);
+ else if (!strncmp(opt,"vesafb",6))
+ vesafb = 1;
+ else
+ mode = opt;
+ }
+#endif
+ output("CyblaFB version %s initializing\n",VERSION);
+ return pci_module_init(&cyblafb_pci_driver);
+}
+
+static void __exit cyblafb_exit(void)
+{
+ pci_unregister_driver(&cyblafb_pci_driver);
+}
+
+module_init(cyblafb_init);
+module_exit(cyblafb_exit);
+
+MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 1dbb82dca40b..1785686a7f11 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -6,6 +6,8 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 116e808d71cd..7363d0b25fdf 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -54,6 +54,8 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
#include <asm/types.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
new file mode 100644
index 000000000000..0b6af00d197e
--- /dev/null
+++ b/drivers/video/fbcvt.c
@@ -0,0 +1,380 @@
+/*
+ * linux/drivers/video/fbcvt.c - VESA(TM) Coordinated Video Timings
+ *
+ * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
+ *
+ * Based from the VESA(TM) Coordinated Video Timing Generator by
+ * Graham Loveridge April 9, 2003 available at
+ * http://www.vesa.org/public/CVT/CVTd6r1.xls
+ *
+ * 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/fb.h>
+
+#define FB_CVT_CELLSIZE 8
+#define FB_CVT_GTF_C 40
+#define FB_CVT_GTF_J 20
+#define FB_CVT_GTF_K 128
+#define FB_CVT_GTF_M 600
+#define FB_CVT_MIN_VSYNC_BP 550
+#define FB_CVT_MIN_VPORCH 3
+#define FB_CVT_MIN_BPORCH 6
+
+#define FB_CVT_RB_MIN_VBLANK 460
+#define FB_CVT_RB_HBLANK 160
+#define FB_CVT_RB_V_FPORCH 3
+
+#define FB_CVT_FLAG_REDUCED_BLANK 1
+#define FB_CVT_FLAG_MARGINS 2
+#define FB_CVT_FLAG_INTERLACED 4
+
+struct fb_cvt_data {
+ u32 xres;
+ u32 yres;
+ u32 refresh;
+ u32 f_refresh;
+ u32 pixclock;
+ u32 hperiod;
+ u32 hblank;
+ u32 hfreq;
+ u32 htotal;
+ u32 vtotal;
+ u32 vsync;
+ u32 hsync;
+ u32 h_front_porch;
+ u32 h_back_porch;
+ u32 v_front_porch;
+ u32 v_back_porch;
+ u32 h_margin;
+ u32 v_margin;
+ u32 interlace;
+ u32 aspect_ratio;
+ u32 active_pixels;
+ u32 flags;
+ u32 status;
+};
+
+static int fb_cvt_vbi_tab[] = {
+ 4, /* 4:3 */
+ 5, /* 16:9 */
+ 6, /* 16:10 */
+ 7, /* 5:4 */
+ 7, /* 15:9 */
+ 8, /* reserved */
+ 9, /* reserved */
+ 10 /* custom */
+};
+
+/* returns hperiod * 1000 */
+static u32 fb_cvt_hperiod(struct fb_cvt_data *cvt)
+{
+ u32 num = 1000000000/cvt->f_refresh;
+ u32 den;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ num -= FB_CVT_RB_MIN_VBLANK * 1000;
+ den = 2 * (cvt->yres/cvt->interlace + 2 * cvt->v_margin);
+ } else {
+ num -= FB_CVT_MIN_VSYNC_BP * 1000;
+ den = 2 * (cvt->yres/cvt->interlace + cvt->v_margin * 2
+ + FB_CVT_MIN_VPORCH + cvt->interlace/2);
+ }
+
+ return 2 * (num/den);
+}
+
+/* returns ideal duty cycle * 1000 */
+static u32 fb_cvt_ideal_duty_cycle(struct fb_cvt_data *cvt)
+{
+ u32 c_prime = (FB_CVT_GTF_C - FB_CVT_GTF_J) *
+ (FB_CVT_GTF_K) + 256 * FB_CVT_GTF_J;
+ u32 m_prime = (FB_CVT_GTF_K * FB_CVT_GTF_M);
+ u32 h_period_est = cvt->hperiod;
+
+ return (1000 * c_prime - ((m_prime * h_period_est)/1000))/256;
+}
+
+static u32 fb_cvt_hblank(struct fb_cvt_data *cvt)
+{
+ u32 hblank = 0;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ hblank = FB_CVT_RB_HBLANK;
+ else {
+ u32 ideal_duty_cycle = fb_cvt_ideal_duty_cycle(cvt);
+ u32 active_pixels = cvt->active_pixels;
+
+ if (ideal_duty_cycle < 20000)
+ hblank = (active_pixels * 20000)/
+ (100000 - 20000);
+ else {
+ hblank = (active_pixels * ideal_duty_cycle)/
+ (100000 - ideal_duty_cycle);
+ }
+ }
+
+ hblank &= ~((2 * FB_CVT_CELLSIZE) - 1);
+
+ return hblank;
+}
+
+static u32 fb_cvt_hsync(struct fb_cvt_data *cvt)
+{
+ u32 hsync;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ hsync = 32;
+ else
+ hsync = (FB_CVT_CELLSIZE * cvt->htotal)/100;
+
+ hsync &= ~(FB_CVT_CELLSIZE - 1);
+ return hsync;
+}
+
+static u32 fb_cvt_vbi_lines(struct fb_cvt_data *cvt)
+{
+ u32 vbi_lines, min_vbi_lines, act_vbi_lines;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ vbi_lines = (1000 * FB_CVT_RB_MIN_VBLANK)/cvt->hperiod + 1;
+ min_vbi_lines = FB_CVT_RB_V_FPORCH + cvt->vsync +
+ FB_CVT_MIN_BPORCH;
+
+ } else {
+ vbi_lines = (FB_CVT_MIN_VSYNC_BP * 1000)/cvt->hperiod + 1 +
+ FB_CVT_MIN_VPORCH;
+ min_vbi_lines = cvt->vsync + FB_CVT_MIN_BPORCH +
+ FB_CVT_MIN_VPORCH;
+ }
+
+ if (vbi_lines < min_vbi_lines)
+ act_vbi_lines = min_vbi_lines;
+ else
+ act_vbi_lines = vbi_lines;
+
+ return act_vbi_lines;
+}
+
+static u32 fb_cvt_vtotal(struct fb_cvt_data *cvt)
+{
+ u32 vtotal = cvt->yres/cvt->interlace;
+
+ vtotal += 2 * cvt->v_margin + cvt->interlace/2 + fb_cvt_vbi_lines(cvt);
+ vtotal |= cvt->interlace/2;
+
+ return vtotal;
+}
+
+static u32 fb_cvt_pixclock(struct fb_cvt_data *cvt)
+{
+ u32 pixclock;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ pixclock = (cvt->f_refresh * cvt->vtotal * cvt->htotal)/1000;
+ else
+ pixclock = (cvt->htotal * 1000000)/cvt->hperiod;
+
+ pixclock /= 250;
+ pixclock *= 250;
+ pixclock *= 1000;
+
+ return pixclock;
+}
+
+static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
+{
+ u32 xres = cvt->xres;
+ u32 yres = cvt->yres;
+ u32 aspect = -1;
+
+ if (xres == (yres * 4)/3 && !((yres * 4) % 3))
+ aspect = 0;
+ else if (xres == (yres * 16)/9 && !((yres * 16) % 9))
+ aspect = 1;
+ else if (xres == (yres * 16)/10 && !((yres * 16) % 10))
+ aspect = 2;
+ else if (xres == (yres * 5)/4 && !((yres * 5) % 4))
+ aspect = 3;
+ else if (xres == (yres * 15)/9 && !((yres * 15) % 9))
+ aspect = 4;
+ else {
+ printk(KERN_INFO "fbcvt: Aspect ratio not CVT "
+ "standard\n");
+ aspect = 7;
+ cvt->status = 1;
+ }
+
+ return aspect;
+}
+
+static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+{
+ u32 pixcount, pixcount_mod;
+ int cnt = 255, offset = 0, read = 0;
+ u8 *buf = kmalloc(256, GFP_KERNEL);
+
+ if (!buf)
+ return;
+
+ memset(buf, 0, 256);
+ pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
+ pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
+ pixcount_mod /= 1000;
+
+ read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
+ cvt->xres, cvt->yres, cvt->refresh);
+ offset += read;
+ cnt -= read;
+
+ if (cvt->status)
+ snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
+ "Pixel Image\n", pixcount, pixcount_mod);
+ else {
+ if (pixcount) {
+ read = snprintf(buf+offset, cnt, "%d", pixcount);
+ cnt -= read;
+ offset += read;
+ }
+
+ read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
+ cnt -= read;
+ offset += read;
+
+ if (cvt->aspect_ratio == 0)
+ read = snprintf(buf+offset, cnt, "3");
+ else if (cvt->aspect_ratio == 3)
+ read = snprintf(buf+offset, cnt, "4");
+ else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
+ read = snprintf(buf+offset, cnt, "9");
+ else if (cvt->aspect_ratio == 2)
+ read = snprintf(buf+offset, cnt, "A");
+ else
+ read = 0;
+ cnt -= read;
+ offset += read;
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ read = snprintf(buf+offset, cnt, "-R");
+ cnt -= read;
+ offset += read;
+ }
+ }
+
+ printk(KERN_INFO "%s\n", buf);
+ kfree(buf);
+}
+
+static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
+ struct fb_videomode *mode)
+{
+ mode->refresh = cvt->f_refresh;
+ mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
+ mode->left_margin = cvt->h_back_porch;
+ mode->right_margin = cvt->h_front_porch;
+ mode->hsync_len = cvt->hsync;
+ mode->upper_margin = cvt->v_back_porch;
+ mode->lower_margin = cvt->v_front_porch;
+ mode->vsync_len = cvt->vsync;
+
+ mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+
+ if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ else
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+/*
+ * fb_find_mode_cvt - calculate mode using VESA(TM) CVT
+ * @mode: pointer to fb_videomode; xres, yres, refresh and vmode must be
+ * pre-filled with the desired values
+ * @margins: add margin to calculation (1.8% of xres and yres)
+ * @rb: compute with reduced blanking (for flatpanels)
+ *
+ * RETURNS:
+ * 0 for success
+ * @mode is filled with computed values. If interlaced, the refresh field
+ * will be filled with the field rate (2x the frame rate)
+ *
+ * DESCRIPTION:
+ * Computes video timings using VESA(TM) Coordinated Video Timings
+ */
+int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb)
+{
+ struct fb_cvt_data cvt;
+
+ memset(&cvt, 0, sizeof(cvt));
+
+ if (margins)
+ cvt.flags |= FB_CVT_FLAG_MARGINS;
+
+ if (rb)
+ cvt.flags |= FB_CVT_FLAG_REDUCED_BLANK;
+
+ if (mode->vmode & FB_VMODE_INTERLACED)
+ cvt.flags |= FB_CVT_FLAG_INTERLACED;
+
+ cvt.xres = mode->xres;
+ cvt.yres = mode->yres;
+ cvt.refresh = mode->refresh;
+ cvt.f_refresh = cvt.refresh;
+ cvt.interlace = 1;
+
+ if (!cvt.xres || !cvt.yres || !cvt.refresh) {
+ printk(KERN_INFO "fbcvt: Invalid input parameters\n");
+ return 1;
+ }
+
+ if (!(cvt.refresh == 50 || cvt.refresh == 60 || cvt.refresh == 70 ||
+ cvt.refresh == 85)) {
+ printk(KERN_INFO "fbcvt: Refresh rate not CVT "
+ "standard\n");
+ cvt.status = 1;
+ }
+
+ cvt.xres &= ~(FB_CVT_CELLSIZE - 1);
+
+ if (cvt.flags & FB_CVT_FLAG_INTERLACED) {
+ cvt.interlace = 2;
+ cvt.f_refresh *= 2;
+ }
+
+ if (cvt.flags & FB_CVT_FLAG_REDUCED_BLANK) {
+ if (cvt.refresh != 60) {
+ printk(KERN_INFO "fbcvt: 60Hz refresh rate "
+ "advised for reduced blanking\n");
+ cvt.status = 1;
+ }
+ }
+
+ if (cvt.flags & FB_CVT_FLAG_MARGINS) {
+ cvt.h_margin = (cvt.xres * 18)/1000;
+ cvt.h_margin &= ~(FB_CVT_CELLSIZE - 1);
+ cvt.v_margin = ((cvt.yres/cvt.interlace)* 18)/1000;
+ }
+
+ cvt.aspect_ratio = fb_cvt_aspect_ratio(&cvt);
+ cvt.active_pixels = cvt.xres + 2 * cvt.h_margin;
+ cvt.hperiod = fb_cvt_hperiod(&cvt);
+ cvt.vsync = fb_cvt_vbi_tab[cvt.aspect_ratio];
+ cvt.vtotal = fb_cvt_vtotal(&cvt);
+ cvt.hblank = fb_cvt_hblank(&cvt);
+ cvt.htotal = cvt.active_pixels + cvt.hblank;
+ cvt.hsync = fb_cvt_hsync(&cvt);
+ cvt.pixclock = fb_cvt_pixclock(&cvt);
+ cvt.hfreq = cvt.pixclock/cvt.htotal;
+ cvt.h_back_porch = cvt.hblank/2 + cvt.h_margin;
+ cvt.h_front_porch = cvt.hblank - cvt.hsync - cvt.h_back_porch +
+ 2 * cvt.h_margin;
+ cvt.v_back_porch = 3 + cvt.v_margin;
+ cvt.v_front_porch = cvt.vtotal - cvt.yres/cvt.interlace -
+ cvt.v_back_porch - cvt.vsync;
+ fb_cvt_print_name(&cvt);
+ fb_cvt_convert_to_mode(&cvt, mode);
+
+ return 0;
+}
+EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d2e19f6dd72c..e2667ddab3f1 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -62,16 +62,26 @@ int num_registered_fb;
* Helpers
*/
-int fb_get_color_depth(struct fb_var_screeninfo *var)
+int fb_get_color_depth(struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix)
{
- if (var->green.length == var->blue.length &&
- var->green.length == var->red.length &&
- !var->green.offset && !var->blue.offset &&
- !var->red.offset)
- return var->green.length;
- else
- return (var->green.length + var->red.length +
- var->blue.length);
+ int depth = 0;
+
+ if (fix->visual == FB_VISUAL_MONO01 ||
+ fix->visual == FB_VISUAL_MONO10)
+ depth = 1;
+ else {
+ if (var->green.length == var->blue.length &&
+ var->green.length == var->red.length &&
+ var->green.offset == var->blue.offset &&
+ var->green.offset == var->red.offset)
+ depth = var->green.length;
+ else
+ depth = var->green.length + var->red.length +
+ var->blue.length;
+ }
+
+ return depth;
}
EXPORT_SYMBOL(fb_get_color_depth);
@@ -80,15 +90,7 @@ EXPORT_SYMBOL(fb_get_color_depth);
*/
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
{
- int i, j;
-
- for (i = height; i--; ) {
- /* s_pitch is a few bytes at the most, memcpy is suboptimal */
- for (j = 0; j < s_pitch; j++)
- dst[j] = src[j];
- src += s_pitch;
- dst += d_pitch;
- }
+ __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
}
EXPORT_SYMBOL(fb_pad_aligned_buffer);
@@ -249,13 +251,18 @@ static void fb_set_logo(struct fb_info *info,
const struct linux_logo *logo, u8 *dst,
int depth)
{
- int i, j, k, fg = 1;
+ int i, j, k;
const u8 *src = logo->data;
- u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+ u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+ u8 fg = 1, d;
- if (fb_get_color_depth(&info->var) == 3)
+ if (fb_get_color_depth(&info->var, &info->fix) == 3)
fg = 7;
+ if (info->fix.visual == FB_VISUAL_MONO01 ||
+ info->fix.visual == FB_VISUAL_MONO10)
+ fg = ~((u8) (0xfff << info->var.green.length));
+
switch (depth) {
case 4:
for (i = 0; i < logo->height; i++)
@@ -318,7 +325,7 @@ static struct logo_data {
int fb_prepare_logo(struct fb_info *info)
{
- int depth = fb_get_color_depth(&info->var);
+ int depth = fb_get_color_depth(&info->var, &info->fix);
memset(&fb_logo, 0, sizeof(struct logo_data));
@@ -628,7 +635,7 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
int
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
{
- int err;
+ int err, flags = info->flags;
if (var->activate & FB_ACTIVATE_INV_MODE) {
struct fb_videomode mode1, mode2;
@@ -682,13 +689,15 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
!list_empty(&info->modelist))
err = fb_add_videomode(&mode, &info->modelist);
- if (!err && info->flags & FBINFO_MISC_USEREVENT) {
+ if (!err && (flags & FBINFO_MISC_USEREVENT)) {
struct fb_event event;
+ int evnt = (var->activate & FB_ACTIVATE_ALL) ?
+ FB_EVENT_MODE_CHANGE_ALL :
+ FB_EVENT_MODE_CHANGE;
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
- notifier_call_chain(&fb_notifier_list,
- FB_EVENT_MODE_CHANGE,
+ notifier_call_chain(&fb_notifier_list, evnt,
&event);
}
}
@@ -909,7 +918,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
}
#endif
#elif defined(__powerpc__)
- vma->vm_page_prot = phys_mem_access_prot(file, off,
+ vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
#elif defined(__alpha__)
@@ -1012,6 +1021,7 @@ register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
+ struct fb_videomode mode;
if (num_registered_fb == FB_MAX)
return -ENXIO;
@@ -1021,7 +1031,7 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
+ fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
fb_info->device, "fb%d", i);
if (IS_ERR(fb_info->class_device)) {
/* Not fatal */
@@ -1042,16 +1052,11 @@ register_framebuffer(struct fb_info *fb_info)
}
fb_info->pixmap.offset = 0;
- if (!fb_info->modelist.prev ||
- !fb_info->modelist.next ||
- list_empty(&fb_info->modelist)) {
- struct fb_videomode mode;
-
+ if (!fb_info->modelist.prev || !fb_info->modelist.next)
INIT_LIST_HEAD(&fb_info->modelist);
- fb_var_to_videomode(&mode, &fb_info->var);
- fb_add_videomode(&mode, &fb_info->modelist);
- }
+ fb_var_to_videomode(&mode, &fb_info->var);
+ fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
devfs_mk_cdev(MKDEV(FB_MAJOR, i),
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index c2718bb94949..713226cdf3c6 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -29,6 +29,7 @@
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
+#include <video/edid.h>
#ifdef CONFIG_PPC_OF
#include <linux/pci.h>
#include <asm/prom.h>
@@ -313,11 +314,13 @@ static int edid_is_monitor_block(unsigned char *block)
return 0;
}
-static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
+static void calc_mode_timings(int xres, int yres, int refresh,
+ struct fb_videomode *mode)
{
struct fb_var_screeninfo var;
struct fb_info info;
+ memset(&var, 0, sizeof(struct fb_var_screeninfo));
var.xres = xres;
var.yres = yres;
fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
@@ -1251,9 +1254,41 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
-EINVAL : 0;
}
+#if defined(__i386__)
+#include <linux/pci.h>
+
+/*
+ * We need to ensure that the EDID block is only returned for
+ * the primary graphics adapter.
+ */
+
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+ struct pci_dev *dev = NULL;
+ struct resource *res = NULL;
+ unsigned char *edid = NULL;
+
+ if (device)
+ dev = to_pci_dev(device);
+
+ if (dev)
+ res = &dev->resource[PCI_ROM_RESOURCE];
+
+ if (res && res->flags & IORESOURCE_ROM_SHADOW)
+ edid = edid_info.dummy;
+
+ return edid;
+}
+#else
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+ return NULL;
+}
+#endif /* _i386_ */
+
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-
+EXPORT_SYMBOL(fb_firmware_edid);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 1147b899f007..007c8e9b2b39 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -242,6 +242,13 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf)
fb_info->var.yres_virtual);
}
+static ssize_t show_stride(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info =
+ (struct fb_info *)class_get_devdata(class_device);
+ return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
+}
+
/* Format for cmap is "%02x%c%4x%4x%4x\n" */
/* %02x entry %c transp %4x red %4x blue %4x green \n */
/* 256 rows at 16 chars equals 4096, the normal page size */
@@ -432,6 +439,7 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
__ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(stride, S_IRUGO, show_stride, NULL),
};
int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index d3c1922cb13a..316bfe994811 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -11,7 +11,7 @@
#include <linux/config.h>
#include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/fb.h>
@@ -1126,7 +1126,7 @@ static int __init gbefb_probe(struct device *dev)
gbefb_setup(options);
#endif
- if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
+ if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
ret = -EBUSY;
goto out_release_framebuffer;
@@ -1152,12 +1152,24 @@ static int __init gbefb_probe(struct device *dev)
if (gbe_mem_phys) {
/* memory was allocated at boot time */
gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
+ if (!gbe_mem) {
+ printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
+ ret = -ENOMEM;
+ goto out_tiles_free;
+ }
+
gbe_dma_addr = 0;
} else {
/* try to allocate memory with the classical allocator
* this has high chance to fail on low memory machines */
gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
GFP_KERNEL);
+ if (!gbe_mem) {
+ printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
+ ret = -ENOMEM;
+ goto out_tiles_free;
+ }
+
gbe_mem_phys = (unsigned long) gbe_dma_addr;
}
@@ -1165,12 +1177,6 @@ static int __init gbefb_probe(struct device *dev)
mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
#endif
- if (!gbe_mem) {
- printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
- ret = -ENXIO;
- goto out_tiles_free;
- }
-
/* map framebuffer memory into tiles table */
for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index b075fd02de31..5a9b89c3831b 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -3,15 +3,13 @@
#
config FB_GEODE
bool "AMD Geode family framebuffer support (EXPERIMENTAL)"
- default n
- depends on FB && EXPERIMENTAL && X86
+ depends on FB && PCI && EXPERIMENTAL && X86
---help---
Say 'Y' here to allow you to select framebuffer drivers for
the AMD Geode family of processors.
config FB_GEODE_GX1
tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
- default n
depends on FB_GEODE && EXPERIMENTAL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
@@ -21,9 +19,7 @@ config FB_GEODE_GX1
Framebuffer driver for the display controller integrated into the
AMD Geode GX1 processor.
- 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 gx1fb. If you want to compile it as a module,
- say M here and read <file:Documentation/modules.txt>.
+ To compile this driver as a module, choose M here: the module will be
+ called gx1fb.
If unsure, say N.
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
index f4983879fcc4..926d53eeb549 100644
--- a/drivers/video/geode/display_gx1.c
+++ b/drivers/video/geode/display_gx1.c
@@ -22,7 +22,7 @@
#include "geodefb.h"
#include "display_gx1.h"
-static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(gx1_conf_reg_lock);
static u8 gx1_read_conf_reg(u8 reg)
{
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
index b7bac0a526b3..ae04820e0c57 100644
--- a/drivers/video/geode/geodefb.h
+++ b/drivers/video/geode/geodefb.h
@@ -29,7 +29,6 @@ struct geodefb_par {
int enable_crt;
int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
int panel_y;
- struct pci_dev *vid_dev;
void __iomem *dc_regs;
void __iomem *vid_regs;
struct geode_dc_ops *dc_ops;
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 83830d24bcda..74a5fca86b8a 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -30,6 +30,62 @@ static char mode_option[32] = "640x480-16@60";
static int crt_option = 1;
static char panel_option[32] = "";
+/* Modes relevant to the GX1 (taken from modedb.c) */
+static const struct fb_videomode __initdata gx1_modedb[] = {
+ /* 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
static int gx1_line_delta(int xres, int bpp)
{
int line_delta = xres * (bpp >> 3);
@@ -47,8 +103,6 @@ static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct geodefb_par *par = info->par;
- printk(KERN_DEBUG "%s()\n", __FUNCTION__);
-
/* Maximum resolution is 1280x1024. */
if (var->xres > 1280 || var->yres > 1024)
return -EINVAL;
@@ -146,40 +200,48 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info)
return par->vid_ops->blank_display(info, blank_mode);
}
-static int __init gx1fb_map_video_memory(struct fb_info *info)
+static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
{
struct geodefb_par *par = info->par;
unsigned gx_base;
int fb_len;
+ int ret;
gx_base = gx1_gx_base();
if (!gx_base)
return -ENODEV;
- par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
- PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
- if (!par->vid_dev)
- return -ENODEV;
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ return ret;
- par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
- pci_resource_len(par->vid_dev, 1));
+ ret = pci_request_region(dev, 1, "gx1fb (video)");
+ if (ret < 0)
+ return ret;
+ par->vid_regs = ioremap(pci_resource_start(dev, 1),
+ pci_resource_len(dev, 1));
if (!par->vid_regs)
return -ENOMEM;
+ if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)"))
+ return -EBUSY;
par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
if (!par->dc_regs)
return -ENOMEM;
- info->fix.smem_start = gx_base + 0x800000;
+ ret = pci_request_region(dev, 0, "gx1fb (frame buffer)");
+ if (ret < 0 )
+ return -EBUSY;
if ((fb_len = gx1_frame_buffer_size()) < 0)
return -ENOMEM;
+ info->fix.smem_start = pci_resource_start(dev, 0);
info->fix.smem_len = fb_len;
info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
if (!info->screen_base)
return -ENOMEM;
- printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
- info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
+ dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
return 0;
}
@@ -216,13 +278,13 @@ static struct fb_ops gx1fb_ops = {
.fb_cursor = soft_cursor,
};
-static struct fb_info * __init gx1fb_init_fbinfo(void)
+static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
{
- struct fb_info *info;
struct geodefb_par *par;
+ struct fb_info *info;
/* Alloc enough space for the pseudo palette. */
- info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL);
+ info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
if (!info)
return NULL;
@@ -255,47 +317,37 @@ static struct fb_info * __init gx1fb_init_fbinfo(void)
/* CRT and panel options */
par->enable_crt = crt_option;
if (parse_panel_option(info) < 0)
- printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n",
- info->fix.id);
+ printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n");
if (!par->panel_x)
par->enable_crt = 1; /* fall back to CRT if no panel is specified */
return info;
}
-
-static struct fb_info *gx1fb_info;
-
-static int __init gx1fb_init(void)
+static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct geodefb_par *par;
struct fb_info *info;
- struct geodefb_par *par;
int ret;
-#ifndef MODULE
- if (fb_get_options("gx1fb", NULL))
- return -ENODEV;
-#endif
-
- info = gx1fb_init_fbinfo();
+ info = gx1fb_init_fbinfo(&pdev->dev);
if (!info)
return -ENOMEM;
- gx1fb_info = info;
-
par = info->par;
/* GX1 display controller and CS5530 video device */
par->dc_ops = &gx1_dc_ops;
par->vid_ops = &cs5530_vid_ops;
- if ((ret = gx1fb_map_video_memory(info)) < 0) {
- printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
+ if ((ret = gx1fb_map_video_memory(info, pdev)) < 0) {
+ dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
goto err;
}
- ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+ ret = fb_find_mode(&info->var, info, mode_option,
+ gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
if (ret == 0 || ret == 4) {
- printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
+ dev_err(&pdev->dev, "could not find valid video mode\n");
ret = -EINVAL;
goto err;
}
@@ -310,39 +362,83 @@ static int __init gx1fb_init(void)
ret = -EINVAL;
goto err;
}
+ pci_set_drvdata(pdev, info);
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
return 0;
err:
- if (info->screen_base)
+ if (info->screen_base) {
iounmap(info->screen_base);
- if (par->vid_regs)
+ pci_release_region(pdev, 0);
+ }
+ if (par->vid_regs) {
iounmap(par->vid_regs);
- if (par->dc_regs)
+ pci_release_region(pdev, 1);
+ }
+ if (par->dc_regs) {
iounmap(par->dc_regs);
- if (par->vid_dev)
- pci_dev_put(par->vid_dev);
+ release_mem_region(gx1_gx_base() + 0x8300, 0x100);
+ }
+
+ pci_disable_device(pdev);
+
if (info)
framebuffer_release(info);
return ret;
}
-static void __exit gx1fb_cleanup(void)
+static void gx1fb_remove(struct pci_dev *pdev)
{
- struct fb_info *info = gx1fb_info;
- struct geodefb_par *par = gx1fb_info->par;
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct geodefb_par *par = info->par;
unregister_framebuffer(info);
iounmap((void __iomem *)info->screen_base);
+ pci_release_region(pdev, 0);
+
iounmap(par->vid_regs);
+ pci_release_region(pdev, 1);
+
iounmap(par->dc_regs);
+ release_mem_region(gx1_gx_base() + 0x8300, 0x100);
- pci_dev_put(par->vid_dev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
+static struct pci_device_id gx1fb_id_table[] = {
+ { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+ 0xff0000, 0 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gx1fb_id_table);
+
+static struct pci_driver gx1fb_driver = {
+ .name = "gx1fb",
+ .id_table = gx1fb_id_table,
+ .probe = gx1fb_probe,
+ .remove = gx1fb_remove,
+};
+
+static int __init gx1fb_init(void)
+{
+#ifndef MODULE
+ if (fb_get_options("gx1fb", NULL))
+ return -ENODEV;
+#endif
+ return pci_register_driver(&gx1fb_driver);
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+ pci_unregister_driver(&gx1fb_driver);
+}
+
module_init(gx1fb_init);
module_exit(gx1fb_cleanup);
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
index d3764acf8443..649c3943d431 100644
--- a/drivers/video/geode/video_cs5530.c
+++ b/drivers/video/geode/video_cs5530.c
@@ -69,8 +69,6 @@ static const struct cs5530_pll_entry cs5530_pll_table[] = {
{ 4310, 0x2FB1B802, }, /* 232.0000 */
};
-#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
-
static void cs5530_set_dclk_frequency(struct fb_info *info)
{
struct geodefb_par *par = info->par;
@@ -82,7 +80,7 @@ static void cs5530_set_dclk_frequency(struct fb_info *info)
value = cs5530_pll_table[0].pll_value;
min = cs5530_pll_table[0].pixclock - info->var.pixclock;
if (min < 0) min = -min;
- for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+ for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
if (diff < 0L) diff = -diff;
if (diff < min) {
diff --git a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile
index 794ae76c7c4b..96e08c8ded97 100644
--- a/drivers/video/i810/Makefile
+++ b/drivers/video/i810/Makefile
@@ -4,7 +4,6 @@
obj-$(CONFIG_FB_I810) += i810fb.o
-
i810fb-objs := i810_main.o i810_accel.o
ifdef CONFIG_FB_I810_GTF
@@ -12,3 +11,7 @@ i810fb-objs += i810_gtf.o
else
i810fb-objs += i810_dvt.o
endif
+
+ifdef CONFIG_FB_I810_I2C
+i810fb-objs += i810-i2c.o
+endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
new file mode 100644
index 000000000000..689d2586366d
--- /dev/null
+++ b/drivers/video/i810/i810-i2c.c
@@ -0,0 +1,257 @@
+ /*-*- linux-c -*-
+ * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
+ *
+ * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include "i810.h"
+#include "i810_regs.h"
+#include "../edid.h"
+
+#define I810_DDC 0x50
+/* bit locations in the registers */
+#define SCL_DIR_MASK 0x0001
+#define SCL_DIR 0x0002
+#define SCL_VAL_MASK 0x0004
+#define SCL_VAL_OUT 0x0008
+#define SCL_VAL_IN 0x0010
+#define SDA_DIR_MASK 0x0100
+#define SDA_DIR 0x0200
+#define SDA_VAL_MASK 0x0400
+#define SDA_VAL_OUT 0x0800
+#define SDA_VAL_IN 0x1000
+
+#define DEBUG /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static void i810i2c_setscl(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+ SCL_DIR_MASK | SCL_VAL_MASK);
+ i810_readl(mmio, GPIOB); /* flush posted write */
+}
+
+static void i810i2c_setsda(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+ SDA_DIR_MASK | SDA_VAL_MASK);
+ i810_readl(mmio, GPIOB); /* flush posted write */
+}
+
+static int i810i2c_getscl(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, SCL_DIR_MASK);
+ i810_writel(mmio, GPIOB, 0);
+ return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN));
+}
+
+static int i810i2c_getsda(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOB, SDA_DIR_MASK);
+ i810_writel(mmio, GPIOB, 0);
+ return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN));
+}
+
+static void i810ddc_setscl(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+ SCL_DIR_MASK | SCL_VAL_MASK);
+ i810_readl(mmio, GPIOA); /* flush posted write */
+}
+
+static void i810ddc_setsda(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+ SDA_DIR_MASK | SDA_VAL_MASK);
+ i810_readl(mmio, GPIOA); /* flush posted write */
+}
+
+static int i810ddc_getscl(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, SCL_DIR_MASK);
+ i810_writel(mmio, GPIOA, 0);
+ return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN));
+}
+
+static int i810ddc_getsda(void *data)
+{
+ struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, GPIOA, SDA_DIR_MASK);
+ i810_writel(mmio, GPIOA, 0);
+ return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN));
+}
+
+#define I2C_ALGO_DDC_I810 0x0e0000
+#define I2C_ALGO_I2C_I810 0x0f0000
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
+ int conn)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->dev->dev;
+ switch (conn) {
+ case 1:
+ chan->adapter.id = I2C_ALGO_DDC_I810;
+ chan->algo.setsda = i810ddc_setsda;
+ chan->algo.setscl = i810ddc_setscl;
+ chan->algo.getsda = i810ddc_getsda;
+ chan->algo.getscl = i810ddc_getscl;
+ break;
+ case 2:
+ chan->adapter.id = I2C_ALGO_I2C_I810;
+ chan->algo.setsda = i810i2c_setsda;
+ chan->algo.setscl = i810i2c_setscl;
+ chan->algo.getsda = i810i2c_getsda;
+ chan->algo.getscl = i810i2c_getscl;
+ break;
+ }
+ chan->algo.udelay = 10;
+ chan->algo.mdelay = 10;
+ chan->algo.timeout = (HZ/2);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ /* Raise SCL and SDA */
+ chan->algo.setsda(chan, 1);
+ chan->algo.setscl(chan, 1);
+ udelay(20);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
+ else
+ dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
+ "%s.\n", name);
+ return rc;
+}
+
+void i810_create_i2c_busses(struct i810fb_par *par)
+{
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+ i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1);
+ i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2);
+}
+
+void i810_delete_i2c_busses(struct i810fb_par *par)
+{
+ if (par->chan[0].par)
+ i2c_bit_del_bus(&par->chan[0].adapter);
+ par->chan[0].par = NULL;
+ if (par->chan[1].par)
+ i2c_bit_del_bus(&par->chan[1].adapter);
+ par->chan[1].par = NULL;
+}
+
+static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan)
+{
+ u8 start = 0x0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = I810_DDC,
+ .len = 1,
+ .buf = &start,
+ }, {
+ .addr = I810_DDC,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ },
+ };
+ u8 *buf;
+
+ buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!buf) {
+ DPRINTK("i810-i2c: Failed to allocate memory\n");
+ return NULL;
+ }
+ msgs[1].buf = buf;
+
+ if (i2c_transfer(&chan->adapter, msgs, 2) == 2) {
+ DPRINTK("i810-i2c: I2C Transfer successful\n");
+ return buf;
+ }
+ DPRINTK("i810-i2c: Unable to read EDID block.\n");
+ kfree(buf);
+ return NULL;
+}
+
+int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
+{
+ struct i810fb_par *par = info->par;
+ u8 *edid = NULL;
+ int i;
+
+ DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
+ if (conn < 3) {
+ for (i = 0; i < 3; i++) {
+ /* Do the real work */
+ edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
+ if (edid)
+ break;
+ }
+ } else {
+ DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, fb_firmware_edid(info->device),
+ EDID_LENGTH);
+ }
+
+ if (out_edid)
+ *out_edid = edid;
+
+ return (edid) ? 0 : 1;
+}
+
+
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index fe3b75794756..d48949ceaacc 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -16,6 +16,9 @@
#include <linux/list.h>
#include <linux/agp_backend.h>
#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
#include <video/vga.h>
/* Fence */
@@ -201,7 +204,6 @@
#define HAS_ACCELERATION 2
#define ALWAYS_SYNC 4
#define LOCKUP 8
-#define USE_HWCUR 16
struct gtt_data {
struct agp_memory *i810_fb_memory;
@@ -241,6 +243,14 @@ struct state_registers {
u8 cr39, cr41, cr70, sr01, msr;
};
+struct i810fb_par;
+
+struct i810fb_i2c_chan {
+ struct i810fb_par *par;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
struct i810fb_par {
struct mode_registers regs;
struct state_registers hw_state;
@@ -252,10 +262,12 @@ struct i810fb_par {
struct heap_data iring;
struct heap_data cursor_heap;
struct vgastate state;
+ struct i810fb_i2c_chan chan[2];
atomic_t use_count;
u32 pseudo_palette[17];
unsigned long mmio_start_phys;
u8 __iomem *mmio_start_virtual;
+ u8 *edid;
u32 pitch;
u32 pixconf;
u32 watermark;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 7513fb9b19cf..0dbc9ddb6766 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -92,20 +92,21 @@ static struct pci_driver i810fb_driver = {
.resume = i810fb_resume,
};
-static int vram __initdata = 4;
-static int bpp __initdata = 8;
-static int mtrr __initdata = 0;
-static int accel __initdata = 0;
-static int hsync1 __initdata = 0;
-static int hsync2 __initdata = 0;
-static int vsync1 __initdata = 0;
-static int vsync2 __initdata = 0;
-static int xres __initdata = 640;
-static int yres __initdata = 480;
-static int vyres __initdata = 0;
-static int sync __initdata = 0;
-static int ext_vga __initdata = 0;
-static int dcolor __initdata = 0;
+static char *mode_option __devinitdata = NULL;
+static int vram __devinitdata = 4;
+static int bpp __devinitdata = 8;
+static int mtrr __devinitdata;
+static int accel __devinitdata;
+static int hsync1 __devinitdata;
+static int hsync2 __devinitdata;
+static int vsync1 __devinitdata;
+static int vsync2 __devinitdata;
+static int xres __devinitdata;
+static int yres __devinitdata;
+static int vyres __devinitdata;
+static int sync __devinitdata;
+static int extvga __devinitdata;
+static int dcolor __devinitdata;
/*------------------------------------------------------------*/
@@ -310,6 +311,8 @@ static void i810_hires(u8 __iomem *mmio)
val = i810_readb(CR_DATA_CGA, mmio);
i810_writeb(CR_INDEX_CGA, mmio, CR80);
i810_writeb(CR_DATA_CGA, mmio, val | 1);
+ /* Stop LCD displays from flickering */
+ i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
}
/**
@@ -947,31 +950,24 @@ static int i810_check_params(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct i810fb_par *par = (struct i810fb_par *) info->par;
- int line_length, vidmem;
- u32 xres, yres, vxres, vyres;
-
- xres = var->xres;
- yres = var->yres;
- vxres = var->xres_virtual;
- vyres = var->yres_virtual;
-
+ int line_length, vidmem, mode_valid = 0, retval = 0;
+ u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
/*
* Memory limit
*/
- line_length = get_line_length(par, vxres,
- var->bits_per_pixel);
-
+ line_length = get_line_length(par, vxres, var->bits_per_pixel);
vidmem = line_length*vyres;
+
if (vidmem > par->fb.size) {
vyres = par->fb.size/line_length;
- if (vyres < yres) {
+ if (vyres < var->yres) {
vyres = yres;
vxres = par->fb.size/vyres;
vxres /= var->bits_per_pixel >> 3;
line_length = get_line_length(par, vxres,
var->bits_per_pixel);
vidmem = line_length * yres;
- if (vxres < xres) {
+ if (vxres < var->xres) {
printk("i810fb: required video memory, "
"%d bytes, for %dx%d-%d (virtual) "
"is out of range\n",
@@ -981,6 +977,10 @@ static int i810_check_params(struct fb_var_screeninfo *var,
}
}
}
+
+ var->xres_virtual = vxres;
+ var->yres_virtual = vyres;
+
/*
* Monitor limit
*/
@@ -996,26 +996,41 @@ static int i810_check_params(struct fb_var_screeninfo *var,
info->monspecs.dclkmax = 204000000;
break;
}
+
info->monspecs.dclkmin = 15000000;
- if (fb_validate_mode(var, info)) {
+ if (!fb_validate_mode(var, info))
+ mode_valid = 1;
+
+#ifdef CONFIG_FB_I810_I2C
+ if (!mode_valid && info->monspecs.gtf &&
+ !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+ mode_valid = 1;
+
+ if (!mode_valid && info->monspecs.modedb_len) {
+ struct fb_videomode *mode;
+
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ fb_videomode_to_var(var, mode);
+ mode_valid = 1;
+ }
+ }
+#endif
+ if (!mode_valid && info->monspecs.modedb_len == 0) {
if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
int default_sync = (info->monspecs.hfmin-HFMIN)
- |(info->monspecs.hfmax-HFMAX)
- |(info->monspecs.vfmin-VFMIN)
- |(info->monspecs.vfmax-VFMAX);
+ |(info->monspecs.hfmax-HFMAX)
+ |(info->monspecs.vfmin-VFMIN)
+ |(info->monspecs.vfmax-VFMAX);
printk("i810fb: invalid video mode%s\n",
- default_sync ? "" :
- ". Specifying vsyncN/hsyncN parameters may help");
- return -EINVAL;
+ default_sync ? "" : ". Specifying "
+ "vsyncN/hsyncN parameters may help");
+ retval = -EINVAL;
}
}
-
- var->xres = xres;
- var->yres = yres;
- var->xres_virtual = vxres;
- var->yres_virtual = vyres;
- return 0;
+
+ return retval;
}
/**
@@ -1375,7 +1390,6 @@ static int i810fb_set_par(struct fb_info *info)
decode_var(&info->var, par);
i810_load_regs(par);
i810_init_cursor(par);
-
encode_fix(&info->fix, info);
if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
@@ -1418,9 +1432,8 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
struct i810fb_par *par = (struct i810fb_par *)info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- if (!(par->dev_flags & USE_HWCUR) || !info->var.accel_flags ||
- par->dev_flags & LOCKUP)
- return soft_cursor(info, cursor);
+ if (!par->dev_flags & LOCKUP)
+ return -ENXIO;
if (cursor->image.width > 64 || cursor->image.height > 64)
return -ENXIO;
@@ -1506,12 +1519,12 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
struct i810fb_par *par = (struct i810fb_par *) info->par;
int blank = 0, prev_state = par->cur_state;
- if (state == prev_state)
+ if (state.event == prev_state)
return 0;
- par->cur_state = state;
+ par->cur_state = state.event;
- switch (state) {
+ switch (state.event) {
case 1:
blank = VESA_VSYNC_SUSPEND;
break;
@@ -1712,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
if (bpp < 8)
bpp = 8;
+ par->i810fb_ops = i810fb_ops;
+
+ if (xres)
+ info->var.xres = xres;
+ else
+ info->var.xres = 640;
+
+ if (yres)
+ info->var.yres = yres;
+ else
+ info->var.yres = 480;
+
if (!vyres)
- vyres = (vram << 20)/(xres*bpp >> 3);
+ vyres = (vram << 20)/(info->var.xres*bpp >> 3);
- par->i810fb_ops = i810fb_ops;
- info->var.xres = xres;
- info->var.yres = yres;
info->var.yres_virtual = vyres;
info->var.bits_per_pixel = bpp;
@@ -1744,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
i810_init_cursor(par);
/* mvo: enable external vga-connector (for laptops) */
- if (ext_vga) {
+ if (extvga) {
i810_writel(HVSYNC, mmio, 0);
i810_writel(PWR_CLKC, mmio, 3);
}
@@ -1814,8 +1836,80 @@ i810_allocate_pci_resource(struct i810fb_par *par,
return 0;
}
+static void __devinit i810fb_find_init_mode(struct fb_info *info)
+{
+ struct fb_videomode mode;
+ struct fb_var_screeninfo var;
+ struct fb_monspecs *specs = &info->monspecs;
+ int found = 0;
+#ifdef CONFIG_FB_I810_I2C
+ int i;
+ int err;
+ struct i810fb_par *par = info->par;
+#endif
+
+ INIT_LIST_HEAD(&info->modelist);
+ memset(&mode, 0, sizeof(struct fb_videomode));
+ var = info->var;
+#ifdef CONFIG_FB_I810_I2C
+ i810_create_i2c_busses(par);
+
+ for (i = 0; i < 3; i++) {
+ err = i810_probe_i2c_connector(info, &par->edid, i+1);
+ if (!err)
+ break;
+ }
+
+ if (!err)
+ printk("i810fb_init_pci: DDC probe successful\n");
+
+ fb_edid_to_monspecs(par->edid, specs);
+
+ if (specs->modedb == NULL)
+ printk("i810fb_init_pci: Unable to get Mode Database\n");
+
+ fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
+ &info->modelist);
+ if (specs->modedb != NULL) {
+ if (xres && yres) {
+ struct fb_videomode *m;
+
+ if ((m = fb_find_best_mode(&var, &info->modelist))) {
+ mode = *m;
+ found = 1;
+ }
+ }
+
+ if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+ mode = specs->modedb[i];
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ mode = specs->modedb[0];
+ found = 1;
+ }
+
+ fb_videomode_to_var(&var, &mode);
+ }
+#endif
+ if (mode_option)
+ fb_find_mode(&var, info, mode_option, specs->modedb,
+ specs->modedb_len, (found) ? &mode : NULL,
+ info->var.bits_per_pixel);
+
+ info->var = var;
+ fb_destroy_modedb(specs->modedb);
+ specs->modedb = NULL;
+}
+
#ifndef MODULE
-static int __init i810fb_setup(char *options)
+static int __devinit i810fb_setup(char *options)
{
char *this_opt, *suffix = NULL;
@@ -1827,8 +1921,8 @@ static int __init i810fb_setup(char *options)
mtrr = 1;
else if (!strncmp(this_opt, "accel", 5))
accel = 1;
- else if (!strncmp(this_opt, "ext_vga", 7))
- ext_vga = 1;
+ else if (!strncmp(this_opt, "extvga", 6))
+ extvga = 1;
else if (!strncmp(this_opt, "sync", 4))
sync = 1;
else if (!strncmp(this_opt, "vram:", 5))
@@ -1857,6 +1951,8 @@ static int __init i810fb_setup(char *options)
vsync2 = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "dcolor", 6))
dcolor = 1;
+ else
+ mode_option = this_opt;
}
return 0;
}
@@ -1867,6 +1963,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
{
struct fb_info *info;
struct i810fb_par *par = NULL;
+ struct fb_videomode mode;
int i, err = -1, vfreq, hfreq, pixclock;
i = 0;
@@ -1875,7 +1972,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
if (!info)
return -ENOMEM;
- par = (struct i810fb_par *) info->par;
+ par = info->par;
par->dev = dev;
if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
@@ -1906,15 +2003,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
info->fbops = &par->i810fb_ops;
info->pseudo_palette = par->pseudo_palette;
fb_alloc_cmap(&info->cmap, 256, 0);
+ i810fb_find_init_mode(info);
if ((err = info->fbops->fb_check_var(&info->var, info))) {
i810fb_release_resource(info, par);
return err;
}
+
+ fb_var_to_videomode(&mode, &info->var);
+ fb_add_videomode(&mode, &info->modelist);
encode_fix(&info->fix, info);
i810fb_init_ringbuffer(info);
err = register_framebuffer(info);
+
if (err < 0) {
i810fb_release_resource(info, par);
printk("i810fb_init: cannot register framebuffer device\n");
@@ -1953,6 +2055,8 @@ static void i810fb_release_resource(struct fb_info *info,
struct gtt_data *gtt = &par->i810_gtt;
unset_mtrr(par);
+ i810_delete_i2c_busses(par);
+
if (par->i810_gtt.i810_cursor_memory)
agp_free_memory(gtt->i810_cursor_memory);
if (par->i810_gtt.i810_fb_memory)
@@ -1962,7 +2066,8 @@ static void i810fb_release_resource(struct fb_info *info,
iounmap(par->mmio_start_virtual);
if (par->aperture.virtual)
iounmap(par->aperture.virtual);
-
+ if (par->edid)
+ kfree(par->edid);
if (par->res_flags & FRAMEBUFFER_REQ)
release_mem_region(par->aperture.physical,
par->aperture.size);
@@ -1988,7 +2093,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
}
#ifndef MODULE
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
char *option = NULL;
@@ -2006,7 +2111,7 @@ static int __init i810fb_init(void)
#ifdef MODULE
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
hsync1 *= 1000;
hsync2 *= 1000;
@@ -2046,14 +2151,16 @@ module_param(accel, bool, 0);
MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
module_param(mtrr, bool, 0);
MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
module_param(sync, bool, 0);
MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
" (default = 0)");
module_param(dcolor, bool, 0);
MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
" (default = 0 = TrueColor)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
MODULE_AUTHOR("Tony A. Daplas");
MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 43b4297b4d48..06072a6466f2 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -83,6 +83,22 @@ extern int i810fb_sync (struct fb_info *p);
extern void i810fb_init_ringbuffer(struct fb_info *info);
extern void i810fb_load_front (u32 offset, struct fb_info *info);
+#ifdef CONFIG_FB_I810_I2C
+/* I2C */
+extern int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+ int conn);
+extern void i810_create_i2c_busses(struct i810fb_par *par);
+extern void i810_delete_i2c_busses(struct i810fb_par *par);
+#else
+static inline int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+ int conn)
+{
+ return 1;
+}
+static inline void i810_create_i2c_busses(struct i810fb_par *par) { }
+static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
+#endif
+
/* Conditionals */
#ifdef CONFIG_X86
inline void flush_cache(void)
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cabd53cec991..64d9bcc38da3 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -31,12 +31,11 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/arch/imxfb.h>
@@ -425,23 +424,21 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int imxfb_suspend(struct device *dev, u32 state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- imxfb_disable_controller(fbi);
+ imxfb_disable_controller(fbi);
return 0;
}
-static int imxfb_resume(struct device *dev, u32 level)
+static int imxfb_resume(struct device *dev)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
- if (level == RESUME_ENABLE)
- imxfb_enable_controller(fbi);
+ imxfb_enable_controller(fbi);
return 0;
}
#else
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 6680ec9ba69e..011e11626558 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -234,7 +234,6 @@ struct intelfb_info {
/* palette */
u32 pseudo_palette[17];
- struct { u8 red, green, blue, pad; } palette[256];
/* chip info */
int pci_chipset;
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 298bc9cd99e7..80a09344f1aa 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -117,14 +117,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
#include <linux/pagemap.h>
#include <linux/version.h>
@@ -230,7 +226,7 @@ MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
static int accel = 1;
static int vram = 4;
-static int hwcursor = 1;
+static int hwcursor = 0;
static int mtrr = 1;
static int fixed = 0;
static int noinit = 0;
@@ -242,7 +238,7 @@ static int voffset = 48;
static char *mode = NULL;
module_param(accel, bool, S_IRUGO);
-MODULE_PARM_DESC(accel, "Enable console acceleration");
+MODULE_PARM_DESC(accel, "Enable hardware acceleration");
module_param(vram, int, S_IRUGO);
MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
module_param(voffset, int, S_IRUGO);
@@ -498,7 +494,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct fb_info *info;
struct intelfb_info *dinfo;
- int i, j, err, dvo;
+ int i, err, dvo;
int aperture_size, stolen_size;
struct agp_kern_info gtt_info;
int agp_memtype;
@@ -583,23 +579,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
- /* Map the fb and MMIO regions */
- dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
- (dinfo->aperture.physical, dinfo->aperture.size);
- if (!dinfo->aperture.virtual) {
- ERR_MSG("Cannot remap FB region.\n");
- cleanup(dinfo);
- return -ENODEV;
- }
- dinfo->mmio_base =
- (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
- INTEL_REG_SIZE);
- if (!dinfo->mmio_base) {
- ERR_MSG("Cannot remap MMIO region.\n");
- cleanup(dinfo);
- return -ENODEV;
- }
-
/* Get the chipset info. */
dinfo->pci_chipset = pdev->device;
@@ -683,6 +662,26 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Allocate memories (which aren't stolen) */
+ /* Map the fb and MMIO regions */
+ /* ioremap only up to the end of used aperture */
+ dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
+ (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
+ + dinfo->fb.size);
+ if (!dinfo->aperture.virtual) {
+ ERR_MSG("Cannot remap FB region.\n");
+ cleanup(dinfo);
+ return -ENODEV;
+ }
+
+ dinfo->mmio_base =
+ (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
+ INTEL_REG_SIZE);
+ if (!dinfo->mmio_base) {
+ ERR_MSG("Cannot remap MMIO region.\n");
+ cleanup(dinfo);
+ return -ENODEV;
+ }
+
if (dinfo->accel) {
if (!(dinfo->gtt_ring_mem =
agp_allocate_memory(bridge, dinfo->ring.size >> 12,
@@ -841,13 +840,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
if (bailearly == 5)
bailout(dinfo);
- for (i = 0; i < 16; i++) {
- j = color_table[i];
- dinfo->palette[i].red = default_red[j];
- dinfo->palette[i].green = default_grn[j];
- dinfo->palette[i].blue = default_blu[j];
- }
-
if (bailearly == 6)
bailout(dinfo);
@@ -1359,10 +1351,6 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
green >>= 8;
blue >>= 8;
- dinfo->palette[regno].red = red;
- dinfo->palette[regno].green = green;
- dinfo->palette[regno].blue = blue;
-
intelfbhw_setcolreg(dinfo, regno, red, green, blue,
transp);
}
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index f5bed581dc45..5bafc3c54db7 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -29,14 +29,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
#include <linux/pagemap.h>
#include <linux/version.h>
diff --git a/drivers/video/logo/.gitignore b/drivers/video/logo/.gitignore
new file mode 100644
index 000000000000..e48355f538fa
--- /dev/null
+++ b/drivers/video/logo/.gitignore
@@ -0,0 +1,7 @@
+#
+# Generated files
+#
+*_mono.c
+*_vga16.c
+*_clut224.c
+*_gray256.c
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 98e00d8601e5..e02da41f1b26 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1285,7 +1285,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
vaddr_t vm;
unsigned int offs;
unsigned int offs2;
- unsigned char store;
+ unsigned char store, orig;
unsigned char bytes[32];
unsigned char* tmp;
@@ -1298,7 +1298,8 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
if (maxSize > 0x2000000) maxSize = 0x2000000;
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+ orig = mga_inb(M_EXTVGA_DATA);
+ mga_outb(M_EXTVGA_DATA, orig | 0x80);
store = mga_readb(vm, 0x1234);
tmp = bytes;
@@ -1323,7 +1324,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+ mga_outb(M_EXTVGA_DATA, orig);
*realSize = offs - 0x100000;
#ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1858,6 +1859,8 @@ static int initMatrox2(WPMINFO struct board* b){
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+ matroxfb_update_fix(PMINFO2);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
@@ -2010,11 +2013,11 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
}
/* not match... */
if (!b->vendor)
- return -1;
+ return -ENODEV;
if (dev > 0) {
/* not requested one... */
dev--;
- return -1;
+ return -ENODEV;
}
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
if (pci_enable_device(pdev)) {
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 67f85344f0cc..ad60bbb16cdf 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1271,7 +1271,7 @@ ERROR0:;
}
static int maven_attach_adapter(struct i2c_adapter* adapter) {
- if (adapter->id == (I2C_ALGO_BIT | I2C_HW_B_G400))
+ if (adapter->id == I2C_HW_B_G400)
return i2c_probe(adapter, &addr_data, &maven_detect_client);
return 0;
}
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index a18dd024fc86..d9d3e9f6c08e 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -68,6 +68,9 @@
* "David C. Hansen" <haveblue@us.ibm.com>
* Fixes
*
+ * "Ian Romanick" <idr@us.ibm.com>
+ * Find PInS data in BIOS on PowerPC systems.
+ *
* (following author is not in any relation with this code, but his code
* is included in this driver)
*
@@ -496,10 +499,35 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
get_bios_version(vbios, bd);
get_bios_output(vbios, bd);
get_bios_tvout(vbios, bd);
+#if defined(__powerpc__)
+ /* On PowerPC cards, the PInS offset isn't stored at the end of the
+ * BIOS image. Instead, you must search the entire BIOS image for
+ * the magic PInS signature.
+ *
+ * This actually applies to all OpenFirmware base cards. Since these
+ * cards could be put in a MIPS or SPARC system, should the condition
+ * be something different?
+ */
+ for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
+ unsigned char header[3];
+
+ header[0] = readb(vbios + pins_offset);
+ header[1] = readb(vbios + pins_offset + 1);
+ header[2] = readb(vbios + pins_offset + 2);
+ if ( (header[0] == 0x2E) && (header[1] == 0x41)
+ && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
+ printk(KERN_INFO "PInS data found at offset %u\n",
+ pins_offset);
+ get_pins(vbios + pins_offset, bd);
+ break;
+ }
+ }
+#else
pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
if (pins_offset <= 0xFF80) {
get_pins(vbios + pins_offset, bd);
}
+#endif
}
#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
@@ -755,6 +783,8 @@ void matroxfb_read_pins(WPMINFO2) {
}
#endif
matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios));
+ printk(KERN_INFO "PInS memtype = %u\n",
+ (ACCESS_FBINFO(values).reg.opt & 0x1C00) >> 10);
}
EXPORT_SYMBOL(matroxfb_DAC_in);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index fbf659b6dab0..47516c44a390 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -246,6 +246,11 @@ static const struct fb_videomode modedb[] = {
/* 480x300 @ 72 Hz, 48.0 kHz hsync */
NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
0, FB_VMODE_DOUBLE
+ }, {
+ /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
+ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
},
};
@@ -451,12 +456,22 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
*
* Valid mode specifiers for @mode_option:
*
- * <xres>x<yres>[-<bpp>][@<refresh>] or
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
* <name>[-<bpp>][@<refresh>]
*
* with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
* <name> a string.
*
+ * If 'M' is present after yres (and before refresh/bpp if present),
+ * the function will compute the timings using VESA(tm) Coordinated
+ * Video Timings (CVT). If 'R' is present after 'M', will compute with
+ * reduced blanking (for flatpanels). If 'i' is present, compute
+ * interlaced mode. If 'm' is present, add margins equal to 1.8%
+ * of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ * 'i' and 'm' must be after 'M' and 'R'. Example:
+ *
+ * 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ *
* NOTE: The passed struct @var is _not_ cleared! This allows you
* to supply values for e.g. the grayscale and accel_flags fields.
*
@@ -490,7 +505,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
- int yres_specified = 0;
+ int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
u32 best, diff;
for (i = namelen-1; i >= 0; i--) {
@@ -501,6 +516,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
!yres_specified) {
refresh = my_atoi(&name[i+1]);
refresh_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
} else
goto done;
break;
@@ -509,6 +526,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
if (!bpp_specified && !yres_specified) {
bpp = my_atoi(&name[i+1]);
bpp_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
} else
goto done;
break;
@@ -521,6 +540,22 @@ int fb_find_mode(struct fb_var_screeninfo *var,
break;
case '0'...'9':
break;
+ case 'M':
+ if (!yres_specified)
+ cvt = 1;
+ break;
+ case 'R':
+ if (!cvt)
+ rb = 1;
+ break;
+ case 'm':
+ if (!cvt)
+ margins = 1;
+ break;
+ case 'i':
+ if (!cvt)
+ interlace = 1;
+ break;
default:
goto done;
}
@@ -530,6 +565,34 @@ int fb_find_mode(struct fb_var_screeninfo *var,
res_specified = 1;
}
done:
+ if (cvt) {
+ struct fb_videomode cvt_mode;
+ int ret;
+
+ DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
+ (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
+ "", (margins) ? " with margins" : "", (interlace) ?
+ " interlaced" : "");
+
+ cvt_mode.xres = xres;
+ cvt_mode.yres = yres;
+ cvt_mode.refresh = (refresh) ? refresh : 60;
+
+ if (interlace)
+ cvt_mode.vmode |= FB_VMODE_INTERLACED;
+ else
+ cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+
+ ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+
+ if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
+ DPRINTK("modedb CVT: CVT mode ok\n");
+ return 1;
+ }
+
+ DPRINTK("CVT mode invalid, getting mode from database\n");
+ }
+
DPRINTK("Trying specified video mode%s %ix%i\n",
refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 3757c1407c19..12f2884d3f0b 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -90,14 +90,13 @@ static int nvidia_gpio_getsda(void *data)
return val;
}
-#define I2C_ALGO_NVIDIA 0x0e0000
static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
{
int rc;
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_NVIDIA;
+ chan->adapter.id = I2C_HW_B_NVIDIA;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pci_dev->dev;
chan->algo.setsda = nvidia_gpio_setsda;
@@ -195,8 +194,9 @@ static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
return NULL;
}
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
{
+ struct nvidia_par *par = info->par;
u8 *edid = NULL;
int i;
@@ -206,10 +206,20 @@ int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
if (edid)
break;
}
+
+ if (!edid && conn == 1) {
+ /* try to get from firmware */
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e != NULL) {
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
+ }
+
if (out_edid)
*out_edid = edid;
- if (!edid)
- return 1;
- return 0;
+ return (edid) ? 0 : 1;
}
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index 9da320986f4c..afee284fc73c 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -95,6 +95,7 @@
#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+#ifdef __LITTLE_ENDIAN
#define reverse_order(l) \
do { \
u8 *a = (u8 *)(l); \
@@ -103,5 +104,8 @@ do { \
*a = byte_rev[*a], a++; \
*a = byte_rev[*a]; \
} while(0)
+#else
+#define reverse_order(l)
+#endif /* __LITTLE_ENDIAN */
#endif /* __NV_LOCAL_H__ */
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 7d12eb85310d..4fa2cf9a8af2 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -30,8 +30,9 @@
void nvidia_create_i2c_busses(struct nvidia_par *par) {}
void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
{
+ struct nvidia_par *par = info->par;
struct device_node *dp;
unsigned char *pedid = NULL;
unsigned char *disptype = NULL;
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 42847ce1b8dd..cac44fc7f587 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -34,7 +34,7 @@ void NVLockUnlock(struct nvidia_par *par, int);
#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
void nvidia_create_i2c_busses(struct nvidia_par *par);
void nvidia_delete_i2c_busses(struct nvidia_par *par);
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
u8 ** out_edid);
#else
#define nvidia_create_i2c_busses(...)
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 0bbdca2e0f91..11c84178f420 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -401,7 +401,7 @@ void NVCommonSetup(struct fb_info *info)
nvidia_create_i2c_busses(par);
if (!par->twoHeads) {
par->CRTCnumber = 0;
- nvidia_probe_i2c_connector(par, 1, &edidA);
+ nvidia_probe_i2c_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
@@ -488,14 +488,14 @@ void NVCommonSetup(struct fb_info *info)
oldhead = NV_RD32(par->PCRTC0, 0x00000860);
NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
- nvidia_probe_i2c_connector(par, 1, &edidA);
+ nvidia_probe_i2c_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
fb_edid_to_monspecs(edidA, monA);
}
- nvidia_probe_i2c_connector(par, 2, &edidB);
+ nvidia_probe_i2c_connector(info, 2, &edidB);
if (edidB && !fb_parse_edid(edidB, &var)) {
printk("nvidiafb: EDID found from BUS2\n");
monB = &monitorB;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index b2e6b2407869..308defc389a2 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -384,6 +384,14 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x021d,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x021e,
@@ -658,7 +666,7 @@ static int nvidia_calc_regs(struct fb_info *info)
{
struct nvidia_par *par = info->par;
struct _riva_hw_state *state = &par->ModeReg;
- int i, depth = fb_get_color_depth(&info->var);
+ int i, depth = fb_get_color_depth(&info->var, &info->fix);
int h_display = info->var.xres / 8 - 1;
int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
int h_end = (info->var.xres + info->var.right_margin +
@@ -978,6 +986,9 @@ static int nvidiafb_set_par(struct fb_info *info)
!par->twoHeads)
par->FPDither = 0;
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
nvidia_init_vga(info);
nvidia_calc_regs(info);
nvidia_write_regs(par);
@@ -992,9 +1003,6 @@ static int nvidiafb_set_par(struct fb_info *info)
NVWriteCrtc(par, 0x11, 0x00);
info->fix.line_length = (info->var.xres_virtual *
info->var.bits_per_pixel) >> 3;
- info->fix.visual = (info->var.bits_per_pixel == 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
if (info->var.accel_flags) {
info->fbops->fb_imageblit = nvidiafb_imageblit;
info->fbops->fb_fillrect = nvidiafb_fillrect;
@@ -1324,6 +1332,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
fb_videomode_to_var(&nvidiafb_default_var, &modedb);
nvidiafb_default_var.bits_per_pixel = 8;
+ } else if (par->fpWidth && par->fpHeight) {
+ char buf[16];
+
+ memset(buf, 0, 16);
+ snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
+ fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
+ specs->modedb_len, &modedb, 8);
}
if (mode_option)
@@ -1350,7 +1365,8 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if (!hwcur)
- info->fbops->fb_cursor = soft_cursor;
+ info->fbops->fb_cursor = soft_cursor;
+
info->var.accel_flags = (!noaccel);
switch (par->Architecture) {
@@ -1466,10 +1482,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
par->Chipset = (pd->vendor << 16) | pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-#ifdef CONFIG_PCI_NAMES
- printk(KERN_INFO PFX "%s\n", pd->pretty_name);
-#endif
-
if (par->Architecture == 0) {
printk(KERN_ERR PFX "unknown NV_ARCH\n");
goto err_out_free_base0;
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 42a6591e863f..611922c0b22f 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -363,7 +363,7 @@ static void __init offb_init_nodriver(struct device_node *dp)
address = (u_long) dp->addrs[i].address;
#ifdef CONFIG_PPC64
- address += dp->phb->pci_mem_offset;
+ address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
#endif
/* kludge for valkyrie */
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 7808a01493ad..b76a5a9a125b 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -288,6 +288,9 @@ static void p9100_init_one(struct sbus_dev *sdev)
all->par.physbase = sdev->reg_addrs[2].phys_addr;
sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ all->info.var.red.length = 8;
+ all->info.var.green.length = 8;
+ all->info.var.blue.length = 8;
linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
all->info.var.xres);
@@ -323,6 +326,7 @@ static void p9100_init_one(struct sbus_dev *sdev)
kfree(all);
return;
}
+ fb_set_cmap(&all->info.cmap, &all->info);
list_add(&all->list, &p9100_list);
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index e0dad948467b..2e11b601c488 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -67,6 +67,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
+#include <linux/ctype.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
@@ -2594,7 +2595,7 @@ static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
{
char *next;
- if (!(CHAR_IS_NUM(options[0]))) {
+ if (!(isdigit(options[0]))) {
(*bn) = 0;
return (options);
}
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 3e00ad7f2e31..28d1fe5fe340 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -413,7 +413,7 @@ static struct fb_ops aafb_ops = {
static int __init init_one(int slot)
{
- unsigned long base_addr = get_tc_base_addr(slot);
+ unsigned long base_addr = CKSEG1ADDR(get_tc_base_addr(slot));
struct aafb_info *ip = &my_fb_info[slot];
memset(ip, 0, sizeof(struct aafb_info));
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index f8095588e99d..c98f1c8d7dc2 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -1,57 +1,55 @@
/*
- * linux/drivers/video/pmag-ba-fb.c
+ * linux/drivers/video/pmag-ba-fb.c
*
- * PMAG-BA TurboChannel framebuffer card support ... derived from:
+ * PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
+ * derived from:
* "HP300 Topcat framebuffer support (derived from macfb of all things)
* Phil Blundell <philb@gnu.org> 1998", the original code can be
- * found in the file hpfb.c in the same directory.
+ * found in the file hpfb.c in the same directory.
*
* Based on digital document:
* "PMAG-BA TURBOchannel Color Frame Buffer
* Functional Specification", Revision 1.2, August 27, 1990
*
- * DECstation related code Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org>,
- * Karsten Merker <merker@linuxtag.org> and
+ * DECstation related code Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org>,
+ * Karsten Merker <merker@linuxtag.org> and
* Harald Koerfgen.
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
+ * Copyright (c) 2005 Maciej W. Rozycki
*
+ * 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/kernel.h>
-#include <linux/sched.h>
+
+#include <linux/compiler.h>
#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/fb.h>
-#include <asm/bootinfo.h>
-#include <asm/dec/machtype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
#include <asm/dec/tc.h>
+
#include <video/pmag-ba-fb.h>
-struct pmag_ba_ramdac_regs {
- unsigned char addr_low;
- unsigned char pad0[3];
- unsigned char addr_hi;
- unsigned char pad1[3];
- unsigned char data;
- unsigned char pad2[3];
- unsigned char cmap;
+
+struct pmagbafb_par {
+ struct fb_info *next;
+ volatile void __iomem *mmio;
+ volatile u32 __iomem *dac;
+ int slot;
};
-/*
- * Max 3 TURBOchannel slots -> max 3 PMAG-BA :)
- */
-static struct fb_info pmagba_fb_info[3];
-static struct fb_var_screeninfo pmagbafb_defined = {
+static struct fb_info *root_pmagbafb_dev;
+
+static struct fb_var_screeninfo pmagbafb_defined __initdata = {
.xres = 1024,
.yres = 864,
.xres_virtual = 1024,
@@ -61,58 +59,71 @@ static struct fb_var_screeninfo pmagbafb_defined = {
.green.length = 8,
.blue.length = 8,
.activate = FB_ACTIVATE_NOW,
- .height = 274,
- .width = 195,
- .accel = FB_ACCEL_NONE,
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 14452,
+ .left_margin = 116,
+ .right_margin = 12,
+ .upper_margin = 34,
+ .lower_margin = 12,
+ .hsync_len = 128,
+ .vsync_len = 3,
+ .sync = FB_SYNC_ON_GREEN,
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbafb_fix = {
+static struct fb_fix_screeninfo pmagbafb_fix __initdata = {
.id = "PMAG-BA",
- .smem_len = (1024 * 864),
+ .smem_len = (1024 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.line_length = 1024,
+ .mmio_len = PMAG_BA_SIZE - PMAG_BA_BT459,
};
-/*
- * Turn hardware cursor off
- */
-void pmagbafb_erase_cursor(struct pmag_ba_ramdac_regs *bt459_regs)
+
+static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
{
- bt459_regs->addr_low = 0;
- bt459_regs->addr_hi = 3;
- bt459_regs->data = 0;
+ writeb(v, par->dac + reg / 4);
}
+static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
+{
+ return readb(par->dac + reg / 4);
+}
+
+
/*
- * Set the palette.
+ * Set the palette.
*/
-static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
{
- struct pmag_ba_ramdac_regs *bt459_regs = (struct pmag_ba_ramdac_regs *) info->par;
+ struct pmagbafb_par *par = info->par;
- if (regno >= info->cmap.len)
- return 1;
+ BUG_ON(regno >= info->cmap.len);
red >>= 8; /* The cmap fields are 16 bits */
- green >>= 8; /* wide, but the harware colormap */
+ green >>= 8; /* wide, but the hardware colormap */
blue >>= 8; /* registers are only 8 bits wide */
- bt459_regs->addr_low = (__u8) regno;
- bt459_regs->addr_hi = 0;
- bt459_regs->cmap = red;
- bt459_regs->cmap = green;
- bt459_regs->cmap = blue;
+ mb();
+ dac_write(par, BT459_ADDR_LO, regno);
+ dac_write(par, BT459_ADDR_HI, 0x00);
+ wmb();
+ dac_write(par, BT459_CMAP, red);
+ wmb();
+ dac_write(par, BT459_CMAP, green);
+ wmb();
+ dac_write(par, BT459_CMAP, blue);
+
return 0;
}
static struct fb_ops pmagbafb_ops = {
.owner = THIS_MODULE,
- .fb_get_fix = gen_get_fix,
- .fb_get_var = gen_get_var,
.fb_setcolreg = pmagbafb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
@@ -120,63 +131,133 @@ static struct fb_ops pmagbafb_ops = {
.fb_cursor = soft_cursor,
};
-int __init pmagbafb_init_one(int slot)
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbafb_erase_cursor(struct fb_info *info)
+{
+ struct pmagbafb_par *par = info->par;
+
+ mb();
+ dac_write(par, BT459_ADDR_LO, 0x00);
+ dac_write(par, BT459_ADDR_HI, 0x03);
+ wmb();
+ dac_write(par, BT459_DATA, 0x00);
+}
+
+
+static int __init pmagbafb_init_one(int slot)
{
- unsigned long base_addr = get_tc_base_addr(slot);
- struct fb_info *info = &pmagba_fb_info[slot];
- struct display *disp = &pmagba_disp[slot];
-
- printk("PMAG-BA framebuffer in slot %d\n", slot);
- /*
- * Framebuffer display memory base address and friends
- */
- pmagbafb_fix.smem_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET;
- info->par = (base_addr + PMAG_BA_BT459_OFFSET);
-
- /*
- * Configure the Bt459 RAM DAC
- */
- pmagbafb_erase_cursor((struct pmag_ba_ramdac_regs *) info->par);
-
- /*
- * Let there be consoles..
- */
+ struct fb_info *info;
+ struct pmagbafb_par *par;
+ unsigned long base_addr;
+
+ info = framebuffer_alloc(sizeof(struct pmagbafb_par), NULL);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->slot = slot;
+ claim_tc_card(par->slot);
+
+ base_addr = get_tc_base_addr(par->slot);
+
+ par->next = root_pmagbafb_dev;
+ root_pmagbafb_dev = info;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ goto err_alloc;
+
info->fbops = &pmagbafb_ops;
+ info->fix = pmagbafb_fix;
info->var = pmagbafb_defined;
- info->fix = pmagbafb_fix;
- info->screen_base = pmagbafb_fix.smem_start;
info->flags = FBINFO_DEFAULT;
- fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ /* MMIO mapping setup. */
+ info->fix.mmio_start = base_addr;
+ par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+ if (!par->mmio)
+ goto err_cmap;
+ par->dac = par->mmio + PMAG_BA_BT459;
+
+ /* Frame buffer mapping setup. */
+ info->fix.smem_start = base_addr + PMAG_BA_FBMEM;
+ info->screen_base = ioremap_nocache(info->fix.smem_start,
+ info->fix.smem_len);
+ if (!info->screen_base)
+ goto err_mmio_map;
+ info->screen_size = info->fix.smem_len;
+
+ pmagbafb_erase_cursor(info);
if (register_framebuffer(info) < 0)
- return 1;
+ goto err_smem_map;
+
+ pr_info("fb%d: %s frame buffer device in slot %d\n",
+ info->node, info->fix.id, par->slot);
+
return 0;
+
+
+err_smem_map:
+ iounmap(info->screen_base);
+
+err_mmio_map:
+ iounmap(par->mmio);
+
+err_cmap:
+ fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+ root_pmagbafb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+ return -ENXIO;
}
-/*
- * Initialise the framebuffer
- */
+static void __exit pmagbafb_exit_one(void)
+{
+ struct fb_info *info = root_pmagbafb_dev;
+ struct pmagbafb_par *par = info->par;
-int __init pmagbafb_init(void)
+ unregister_framebuffer(info);
+ iounmap(info->screen_base);
+ iounmap(par->mmio);
+ fb_dealloc_cmap(&info->cmap);
+ root_pmagbafb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+}
+
+
+/*
+ * Initialise the framebuffer.
+ */
+static int __init pmagbafb_init(void)
{
- int sid;
- int found = 0;
+ int count = 0;
+ int slot;
if (fb_get_options("pmagbafb", NULL))
- return -ENODEV;
-
- if (TURBOCHANNEL) {
- while ((sid = search_tc_card("PMAG-BA")) >= 0) {
- found = 1;
- claim_tc_card(sid);
- pmagbafb_init_one(sid);
- }
- return found ? 0 : -ENODEV;
- } else {
- return -ENODEV;
+ return -ENXIO;
+
+ while ((slot = search_tc_card("PMAG-BA")) >= 0) {
+ if (pmagbafb_init_one(slot) < 0)
+ break;
+ count++;
}
+ return (count > 0) ? 0 : -ENXIO;
}
+static void __exit pmagbafb_exit(void)
+{
+ while (root_pmagbafb_dev)
+ pmagbafb_exit_one();
+}
+
+
module_init(pmagbafb_init);
+module_exit(pmagbafb_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index d14eaee91cff..a483b13e117b 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -1,114 +1,128 @@
/*
- * linux/drivers/video/pmagb-b-fb.c
+ * linux/drivers/video/pmagb-b-fb.c
*
- * PMAGB-B TurboChannel framebuffer card support ... derived from:
+ * PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support,
+ * derived from:
* "HP300 Topcat framebuffer support (derived from macfb of all things)
* Phil Blundell <philb@gnu.org> 1998", the original code can be
- * found in the file hpfb.c in the same directory.
+ * found in the file hpfb.c in the same directory.
*
- * DECstation related code Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org>,
- * Karsten Merker <merker@linuxtag.org> and
+ * DECstation related code Copyright (C) 1999, 2000, 2001 by
+ * Michael Engel <engel@unix-ag.org>,
+ * Karsten Merker <merker@linuxtag.org> and
* Harald Koerfgen.
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
+ * Copyright (c) 2005 Maciej W. Rozycki
*
+ * 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.
*/
-/*
- * We currently only support the PMAGB-B in high resolution mode
- * as I know of no way to detect low resolution mode set via jumper.
- * KM, 2001/01/07
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
+#include <linux/compiler.h>
#include <linux/delay.h>
-#include <linux/init.h>
+#include <linux/errno.h>
#include <linux/fb.h>
-#include <asm/bootinfo.h>
-#include <asm/dec/machtype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
#include <asm/dec/tc.h>
+
#include <video/pmagb-b-fb.h>
-struct pmagb_b_ramdac_regs {
- unsigned char addr_low;
- unsigned char pad0[3];
- unsigned char addr_hi;
- unsigned char pad1[3];
- unsigned char data;
- unsigned char pad2[3];
- unsigned char cmap;
+
+struct pmagbbfb_par {
+ struct fb_info *next;
+ volatile void __iomem *mmio;
+ volatile void __iomem *smem;
+ volatile u32 __iomem *sfb;
+ volatile u32 __iomem *dac;
+ unsigned int osc0;
+ unsigned int osc1;
+ int slot;
};
-/*
- * Max 3 TURBOchannel slots -> max 3 PMAGB-B :)
- */
-static struct fb_info pmagbb_fb_info[3];
-static struct fb_var_screeninfo pmagbbfb_defined = {
- .xres = 1280,
- .yres = 1024,
- .xres_virtual = 1280,
- .yres_virtual = 1024,
+static struct fb_info *root_pmagbbfb_dev;
+
+static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
.bits_per_pixel = 8,
.red.length = 8,
.green.length = 8,
.blue.length = 8,
.activate = FB_ACTIVATE_NOW,
- .height = 274,
- .width = 195,
+ .height = -1,
+ .width = -1,
.accel_flags = FB_ACCEL_NONE,
+ .sync = FB_SYNC_ON_GREEN,
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct fb_fix_screeninfo pmagbafb_fix = {
+static struct fb_fix_screeninfo pmagbbfb_fix __initdata = {
.id = "PMAGB-BA",
- .smem_len = (1280 * 1024),
+ .smem_len = (2048 * 1024),
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
- .line_length = 1280,
+ .mmio_len = PMAGB_B_FBMEM,
+};
+
+
+static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v)
+{
+ writel(v, par->sfb + reg / 4);
}
-/*
- * Turn hardware cursor off
- */
-void pmagbbfb_erase_cursor(struct pmagb_b_ramdac_regs *bt459_regs)
+static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+ return readl(par->sfb + reg / 4);
+}
+
+static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v)
{
- bt459_regs->addr_low = 0;
- bt459_regs->addr_hi = 3;
- bt459_regs->data = 0;
+ writeb(v, par->dac + reg / 4);
}
+static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+ return readb(par->dac + reg / 4);
+}
+
+static inline void gp0_write(struct pmagbbfb_par *par, u32 v)
+{
+ writel(v, par->mmio + PMAGB_B_GP0);
+}
+
+
/*
- * Set the palette.
+ * Set the palette.
*/
-static int pmagbbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
{
- struct pmagb_b_ramdac_regs *bt459_regs = (struct pmagb_b_ramdac_regs *) info->par;
-
- if (regno >= info->cmap.len)
- return 1;
+ struct pmagbbfb_par *par = info->par;
+
+ BUG_ON(regno >= info->cmap.len);
red >>= 8; /* The cmap fields are 16 bits */
- green >>= 8; /* wide, but the harware colormap */
+ green >>= 8; /* wide, but the hardware colormap */
blue >>= 8; /* registers are only 8 bits wide */
- bt459_regs->addr_low = (__u8) regno;
- bt459_regs->addr_hi = 0;
- bt459_regs->cmap = red;
- bt459_regs->cmap = green;
- bt459_regs->cmap = blue;
+ mb();
+ dac_write(par, BT459_ADDR_LO, regno);
+ dac_write(par, BT459_ADDR_HI, 0x00);
+ wmb();
+ dac_write(par, BT459_CMAP, red);
+ wmb();
+ dac_write(par, BT459_CMAP, green);
+ wmb();
+ dac_write(par, BT459_CMAP, blue);
+
return 0;
}
@@ -121,62 +135,247 @@ static struct fb_ops pmagbbfb_ops = {
.fb_cursor = soft_cursor,
};
-int __init pmagbbfb_init_one(int slot)
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbbfb_erase_cursor(struct fb_info *info)
+{
+ struct pmagbbfb_par *par = info->par;
+
+ mb();
+ dac_write(par, BT459_ADDR_LO, 0x00);
+ dac_write(par, BT459_ADDR_HI, 0x03);
+ wmb();
+ dac_write(par, BT459_DATA, 0x00);
+}
+
+/*
+ * Set up screen parameters.
+ */
+static void __init pmagbbfb_screen_setup(struct fb_info *info)
+{
+ struct pmagbbfb_par *par = info->par;
+
+ info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4;
+ info->var.xres_virtual = info->var.xres;
+ info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK;
+ info->var.yres_virtual = info->var.yres;
+ info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_BP_SHIFT) &
+ SFB_VID_HOR_BP_MASK) * 4;
+ info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_FP_SHIFT) &
+ SFB_VID_HOR_FP_MASK) * 4;
+ info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK;
+ info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK;
+ info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >>
+ SFB_VID_HOR_SYN_SHIFT) &
+ SFB_VID_HOR_SYN_MASK) * 4;
+ info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >>
+ SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK;
+
+ info->fix.line_length = info->var.xres;
+};
+
+/*
+ * Determine oscillator configuration.
+ */
+static void __init pmagbbfb_osc_setup(struct fb_info *info)
{
- unsigned long base_addr = get_tc_base_addr(slot);
- struct fb_info *info = &pmagbb_fb_info[slot];
-
- printk("PMAGB-BA framebuffer in slot %d\n", slot);
- /*
- * Framebuffer display memory base address and friends
- */
- pmagbbfb_fix.smem_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET;
- info->par = (base_addr + PMAGB_B_BT459_OFFSET);
-
- /*
- * Configure the Bt459 RAM DAC
- */
- pmagbbfb_erase_cursor((struct pmagb_b_ramdac_regs *) info->par);
-
- /*
- * Let there be consoles..
- */
+ static unsigned int pmagbbfb_freqs[] __initdata = {
+ 130808, 119843, 104000, 92980, 74367, 72800,
+ 69197, 66000, 65000, 50350, 36000, 32000, 25175
+ };
+ struct pmagbbfb_par *par = info->par;
+ u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
+ u32 freq0, freq1, freqtc = get_tc_speed() / 250;
+ int i, j;
+
+ gp0_write(par, 0); /* select Osc0 */
+ for (j = 0; j < 16; j++) {
+ mb();
+ sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+ mb();
+ for (i = 0; i < 100; i++) { /* nominally max. 20.5us */
+ if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+ break;
+ udelay(1);
+ }
+ count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+ }
+
+ gp0_write(par, 1); /* select Osc1 */
+ for (j = 0; j < 16; j++) {
+ mb();
+ sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+
+ for (i = 0; i < 100; i++) { /* nominally max. 20.5us */
+ if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+ break;
+ udelay(1);
+ }
+ count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+ }
+
+ freq0 = (freqtc * count0 + counttc / 2) / counttc;
+ par->osc0 = freq0;
+ if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 &&
+ freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64)
+ par->osc0 = pmagbbfb_freqs[0];
+
+ freq1 = (par->osc0 * count1 + count0 / 2) / count0;
+ par->osc1 = freq1;
+ for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++)
+ if (freq1 >= pmagbbfb_freqs[i] -
+ (pmagbbfb_freqs[i] + 128) / 256 &&
+ freq1 <= pmagbbfb_freqs[i] +
+ (pmagbbfb_freqs[i] + 128) / 256) {
+ par->osc1 = pmagbbfb_freqs[i];
+ break;
+ }
+
+ if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 ||
+ par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512)
+ par->osc1 = 0;
+
+ gp0_write(par, par->osc1 != 0); /* reselect OscX */
+
+ info->var.pixclock = par->osc1 ?
+ (1000000000 + par->osc1 / 2) / par->osc1 :
+ (1000000000 + par->osc0 / 2) / par->osc0;
+};
+
+
+static int __init pmagbbfb_init_one(int slot)
+{
+ char freq0[12], freq1[12];
+ struct fb_info *info;
+ struct pmagbbfb_par *par;
+ unsigned long base_addr;
+ u32 vid_base;
+
+ info = framebuffer_alloc(sizeof(struct pmagbbfb_par), NULL);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->slot = slot;
+ claim_tc_card(par->slot);
+
+ base_addr = get_tc_base_addr(par->slot);
+
+ par->next = root_pmagbbfb_dev;
+ root_pmagbbfb_dev = info;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ goto err_alloc;
+
info->fbops = &pmagbbfb_ops;
- info->var = pmagbbfb_defined;
info->fix = pmagbbfb_fix;
- info->screen_base = pmagbbfb_fix.smem_start;
+ info->var = pmagbbfb_defined;
info->flags = FBINFO_DEFAULT;
- fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ /* MMIO mapping setup. */
+ info->fix.mmio_start = base_addr;
+ par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+ if (!par->mmio)
+ goto err_cmap;
+ par->sfb = par->mmio + PMAGB_B_SFB;
+ par->dac = par->mmio + PMAGB_B_BT459;
+
+ /* Frame buffer mapping setup. */
+ info->fix.smem_start = base_addr + PMAGB_B_FBMEM;
+ par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
+ if (!par->smem)
+ goto err_mmio_map;
+ vid_base = sfb_read(par, SFB_REG_VID_BASE);
+ info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
+ info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
+
+ pmagbbfb_erase_cursor(info);
+ pmagbbfb_screen_setup(info);
+ pmagbbfb_osc_setup(info);
if (register_framebuffer(info) < 0)
- return 1;
+ goto err_smem_map;
+
+ snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
+ par->osc0 / 1000, par->osc0 % 1000);
+ snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
+ par->osc1 / 1000, par->osc1 % 1000);
+
+ pr_info("fb%d: %s frame buffer device in slot %d\n",
+ info->node, info->fix.id, par->slot);
+ pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n",
+ info->node, freq0, par->osc1 ? freq1 : "disabled",
+ par->osc1 != 0);
+
return 0;
+
+
+err_smem_map:
+ iounmap(par->smem);
+
+err_mmio_map:
+ iounmap(par->mmio);
+
+err_cmap:
+ fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+ root_pmagbbfb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+ return -ENXIO;
}
-/*
- * Initialise the framebuffer
- */
+static void __exit pmagbbfb_exit_one(void)
+{
+ struct fb_info *info = root_pmagbbfb_dev;
+ struct pmagbbfb_par *par = info->par;
+
+ unregister_framebuffer(info);
+ iounmap(par->smem);
+ iounmap(par->mmio);
+ fb_dealloc_cmap(&info->cmap);
+ root_pmagbbfb_dev = par->next;
+ release_tc_card(par->slot);
+ framebuffer_release(info);
+}
-int __init pmagbbfb_init(void)
+
+/*
+ * Initialise the framebuffer.
+ */
+static int __init pmagbbfb_init(void)
{
- int sid;
- int found = 0;
+ int count = 0;
+ int slot;
if (fb_get_options("pmagbbfb", NULL))
- return -ENODEV;
+ return -ENXIO;
- if (TURBOCHANNEL) {
- while ((sid = search_tc_card("PMAGB-BA")) >= 0) {
- found = 1;
- claim_tc_card(sid);
- pmagbbfb_init_one(sid);
- }
- return found ? 0 : -ENODEV;
- } else {
- return -ENODEV;
+ while ((slot = search_tc_card("PMAGB-BA")) >= 0) {
+ if (pmagbbfb_init_one(slot) < 0)
+ break;
+ count++;
}
+ return (count > 0) ? 0 : -ENXIO;
+}
+
+static void __exit pmagbbfb_exit(void)
+{
+ while (root_pmagbbfb_dev)
+ pmagbbfb_exit_one();
}
+
module_init(pmagbbfb_init);
+module_exit(pmagbbfb_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 16e37a535d85..efd9333b05c2 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -36,7 +36,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
@@ -260,9 +260,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
#ifdef CONFIG_CPU_FREQ
- DPRINTK("dma period = %d ps, clock = %d kHz\n",
- pxafb_display_dma_period(var),
- get_clk_frequency_khz(0));
+ pr_debug("pxafb: dma period = %d ps, clock = %d kHz\n",
+ pxafb_display_dma_period(var),
+ get_clk_frequency_khz(0));
#endif
return 0;
@@ -270,7 +270,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static inline void pxafb_set_truecolor(u_int is_true_color)
{
- DPRINTK("true_color = %d\n", is_true_color);
+ pr_debug("pxafb: true_color = %d\n", is_true_color);
// do your machine-specific setup if needed
}
@@ -284,7 +284,7 @@ static int pxafb_set_par(struct fb_info *info)
struct fb_var_screeninfo *var = &info->var;
unsigned long palette_mem_size;
- DPRINTK("set_par\n");
+ pr_debug("pxafb: set_par\n");
if (var->bits_per_pixel == 16)
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
@@ -308,7 +308,7 @@ static int pxafb_set_par(struct fb_info *info)
palette_mem_size = fbi->palette_size * sizeof(u16);
- DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+ pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
@@ -369,7 +369,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
struct pxafb_info *fbi = (struct pxafb_info *)info;
int i;
- DPRINTK("pxafb_blank: blank=%d\n", blank);
+ pr_debug("pxafb: blank=%d\n", blank);
switch (blank) {
case FB_BLANK_POWERDOWN:
@@ -468,6 +468,36 @@ static inline unsigned int get_pcd(unsigned int pixclock)
}
/*
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
+ */
+static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+{
+ unsigned long long htime;
+
+ if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+ fbi->hsync_time=0;
+ return;
+ }
+
+ htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000;
+ do_div(htime, pcd * fbi->fb.var.hsync_len);
+ fbi->hsync_time = htime;
+}
+
+unsigned long pxafb_get_hsync_time(struct device *dev)
+{
+ struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+ /* If display is blanked/suspended, hsync isn't active */
+ if (!fbi || (fbi->state != C_ENABLE))
+ return 0;
+
+ return fbi->hsync_time;
+}
+EXPORT_SYMBOL(pxafb_get_hsync_time);
+
+/*
* pxafb_activate_var():
* Configures LCD Controller based on entries in var parameter. Settings are
* only written to the controller if changes were made.
@@ -478,15 +508,15 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
u_long flags;
u_int lines_per_panel, pcd = get_pcd(var->pixclock);
- DPRINTK("Configuring PXA LCD\n");
+ pr_debug("pxafb: Configuring PXA LCD\n");
- DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
- var->xres, var->hsync_len,
- var->left_margin, var->right_margin);
- DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
- var->yres, var->vsync_len,
- var->upper_margin, var->lower_margin);
- DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
+ pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
+ var->xres, var->hsync_len,
+ var->left_margin, var->right_margin);
+ pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+ var->yres, var->vsync_len,
+ var->upper_margin, var->lower_margin);
+ pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
#if DEBUG_VAR
if (var->xres < 16 || var->xres > 1024)
@@ -559,10 +589,10 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
if (pcd)
new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
- DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
- DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
- DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
- DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
+ pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0);
+ pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1);
+ pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2);
+ pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3);
/* Update shadow copy atomically */
local_irq_save(flags);
@@ -607,30 +637,31 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
}
#if 0
- DPRINTK("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
- DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
- DPRINTK("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
- DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
- DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
- DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
-
- DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
- DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
- DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
-
- DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
- DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
- DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
-
- DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
- DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
- DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
+ pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
+ pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
+ pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
+ pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
+ pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
+ pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
+
+ pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
+ pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
+ pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
+
+ pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
+ pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
+ pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
+
+ pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
+ pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
+ pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
#endif
fbi->reg_lccr0 = new_regs.lccr0;
fbi->reg_lccr1 = new_regs.lccr1;
fbi->reg_lccr2 = new_regs.lccr2;
fbi->reg_lccr3 = new_regs.lccr3;
+ set_hsync_time(fbi, pcd);
local_irq_restore(flags);
/*
@@ -653,7 +684,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
*/
static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
{
- DPRINTK("backlight o%s\n", on ? "n" : "ff");
+ pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
if (pxafb_backlight_power)
pxafb_backlight_power(on);
@@ -661,7 +692,7 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
{
- DPRINTK("LCD power o%s\n", on ? "n" : "ff");
+ pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
if (pxafb_lcd_power)
pxafb_lcd_power(on);
@@ -709,13 +740,16 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
static void pxafb_enable_controller(struct pxafb_info *fbi)
{
- DPRINTK("Enabling LCD controller\n");
- DPRINTK("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
- DPRINTK("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
- DPRINTK("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
- DPRINTK("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
- DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
- DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+ pr_debug("pxafb: Enabling LCD controller\n");
+ pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
+ pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
+ pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
+ pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
+ pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
+ pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+
+ /* enable LCD controller clock */
+ pxa_set_cken(CKEN16_LCD, 1);
/* Sequence from 11.7.10 */
LCCR3 = fbi->reg_lccr3;
@@ -727,19 +761,19 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
FDADR1 = fbi->fdadr1;
LCCR0 |= LCCR0_ENB;
- DPRINTK("FDADR0 0x%08x\n", (unsigned int) FDADR0);
- DPRINTK("FDADR1 0x%08x\n", (unsigned int) FDADR1);
- DPRINTK("LCCR0 0x%08x\n", (unsigned int) LCCR0);
- DPRINTK("LCCR1 0x%08x\n", (unsigned int) LCCR1);
- DPRINTK("LCCR2 0x%08x\n", (unsigned int) LCCR2);
- DPRINTK("LCCR3 0x%08x\n", (unsigned int) LCCR3);
+ pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0);
+ pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1);
+ pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0);
+ pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
+ pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
+ pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
}
static void pxafb_disable_controller(struct pxafb_info *fbi)
{
DECLARE_WAITQUEUE(wait, current);
- DPRINTK("Disabling LCD controller\n");
+ pr_debug("pxafb: disabling LCD controller\n");
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&fbi->ctrlr_wait, &wait);
@@ -750,6 +784,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
schedule_timeout(20 * HZ / 1000);
remove_wait_queue(&fbi->ctrlr_wait, &wait);
+
+ /* disable LCD controller clock */
+ pxa_set_cken(CKEN16_LCD, 0);
}
/*
@@ -901,6 +938,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
case CPUFREQ_POSTCHANGE:
pcd = get_pcd(fbi->fb.var.pixclock);
+ set_hsync_time(fbi, pcd);
fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
break;
@@ -943,21 +981,19 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int pxafb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxafb_suspend(struct device *dev, pm_message_t state)
{
struct pxafb_info *fbi = dev_get_drvdata(dev);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- set_ctrlr_state(fbi, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
-static int pxafb_resume(struct device *dev, u32 level)
+static int pxafb_resume(struct device *dev)
{
struct pxafb_info *fbi = dev_get_drvdata(dev);
- if (level == RESUME_ENABLE)
- set_ctrlr_state(fbi, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
#else
@@ -1001,7 +1037,7 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
palette_mem_size = fbi->palette_size * sizeof(u16);
- DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+ pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
@@ -1299,8 +1335,6 @@ int __init pxafb_probe(struct device *dev)
ret = -ENOMEM;
goto failed;
}
- /* enable LCD controller clock */
- pxa_set_cken(CKEN16_LCD, 1);
ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
if (ret) {
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index de15fec5f82f..47f41f70db7a 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -83,6 +83,8 @@ struct pxafb_info {
u_int reg_lccr2;
u_int reg_lccr3;
+ unsigned long hsync_time;
+
volatile u_char state;
volatile u_char task_state;
struct semaphore ctrlr_sem;
@@ -112,15 +114,6 @@ struct pxafb_info {
#define PXA_NAME "PXA"
/*
- * Debug macros
- */
-#if DEBUG
-# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-#else
-# define DPRINTK(fmt, args...)
-#endif
-
-/*
* Minimum X and Y resolutions
*/
#define MIN_XRES 64
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 71b69da0c40d..8416b2e2b501 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -18,10 +18,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/q40_master.h>
#include <linux/fb.h>
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index c46387024b1d..a78b9bd8f897 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -80,7 +80,7 @@
#include <video/radeon.h>
#include <linux/radeonfb.h>
-#define DEBUG 1
+#define DEBUG 0
#if DEBUG
#define RTRACE printk
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index ae297e222681..3e9f96e9237d 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1936,10 +1936,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
default_par->Chipset = (pd->vendor << 16) | pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
-#ifdef CONFIG_PCI_NAMES
- printk(KERN_INFO PFX "%s\n", pd->pretty_name);
-#endif
-
if(default_par->riva.Architecture == 0) {
printk(KERN_ERR PFX "unknown NV_ARCH\n");
ret=-ENODEV;
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index da1334dfd51d..77151d8e0766 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -92,14 +92,13 @@ static int riva_gpio_getsda(void* data)
return val;
}
-#define I2C_ALGO_RIVA 0x0e0000
static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
{
int rc;
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_RIVA;
+ chan->adapter.id = I2C_HW_B_RIVA;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pdev->dev;
chan->algo.setsda = riva_gpio_setsda;
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 3848be2b9d2d..f4437430dc5f 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -30,7 +30,7 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/types.h>
@@ -655,7 +655,7 @@ bail:
}
#ifdef CONFIG_PM
-static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
+static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state)
{
struct fb_info *info = dev_get_drvdata(dev);
struct s1d13xxxfb_par *s1dfb = info->par;
@@ -702,15 +702,12 @@ static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
return 0;
}
-static int s1d13xxxfb_resume(struct device *dev, u32 level)
+static int s1d13xxxfb_resume(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
struct s1d13xxxfb_par *s1dfb = info->par;
struct s1d13xxxfb_pdata *pdata = NULL;
- if (level != RESUME_ENABLE)
- return 0;
-
/* awaken the chip */
s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
new file mode 100644
index 000000000000..3cef90456a4b
--- /dev/null
+++ b/drivers/video/s3c2410fb.c
@@ -0,0 +1,911 @@
+/*
+ * linux/drivers/video/s3c2410fb.c
+ * Copyright (c) Arnaud Patard, Ben Dooks
+ *
+ * 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.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.c and others
+ *
+ * ChangeLog
+ * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - u32 state -> pm_message_t state
+ * - S3C2410_{VA,SZ}_LCD -> S3C24XX
+ *
+ * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the ioctl
+ * - use readl/writel instead of __raw_writel/__raw_readl
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Added the possibility to set on or off the
+ * debugging mesaages
+ * - Replaced 0 and 1 by on or off when reading the
+ * /sys files
+ *
+ * 2005-03-23: Ben Dooks <ben-linux@fluff.org>
+ * - added non 16bpp modes
+ * - updated platform information for range of x/y/bpp
+ * - add code to ensure palette is written correctly
+ * - add pixel clock divisor control
+ *
+ * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Removed the use of currcon as it no more exist
+ * - Added LCD power sysfs interface
+ *
+ * 2004-11-03: Ben Dooks <ben-linux@fluff.org>
+ * - minor cleanups
+ * - add suspend/resume support
+ * - s3c2410fb_setcolreg() not valid in >8bpp modes
+ * - removed last CONFIG_FB_S3C2410_FIXED
+ * - ensure lcd controller stopped before cleanup
+ * - added sysfs interface for backlight power
+ * - added mask for gpio configuration
+ * - ensured IRQs disabled during GPIO configuration
+ * - disable TPAL before enabling video
+ *
+ * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Suppress command line options
+ *
+ * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.c to s3c2410fb.c
+ * - Add support for different devices
+ * - Backlight support
+ *
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ * - added clock (de-)allocation code
+ * - added fixem fbmem option
+ *
+ * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - code cleanup
+ * - added a forgotten return in h1940fb_init
+ *
+ * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
+ * - code cleanup and extended debugging
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/fb.h>
+#include <asm/hardware/clock.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "s3c2410fb.h"
+
+
+static struct s3c2410fb_mach_info *mach_info;
+
+/* Debugging stuff */
+#ifdef CONFIG_FB_S3C2410_DEBUG
+static int debug = 1;
+#else
+static int debug = 0;
+#endif
+
+#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
+
+/* useful functions */
+
+/* s3c2410fb_set_lcdaddr
+ *
+ * initialise lcd controller address pointers
+*/
+
+static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
+{
+ struct fb_var_screeninfo *var = &fbi->fb->var;
+ unsigned long saddr1, saddr2, saddr3;
+
+ saddr1 = fbi->fb->fix.smem_start >> 1;
+ saddr2 = fbi->fb->fix.smem_start;
+ saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
+ saddr2>>= 1;
+
+ saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+
+ dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
+ dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
+ dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
+
+ writel(saddr1, S3C2410_LCDSADDR1);
+ writel(saddr2, S3C2410_LCDSADDR2);
+ writel(saddr3, S3C2410_LCDSADDR3);
+}
+
+/* s3c2410fb_calc_pixclk()
+ *
+ * calculate divisor for clk->pixclk
+*/
+
+static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
+ unsigned long pixclk)
+{
+ unsigned long clk = clk_get_rate(fbi->clk);
+ unsigned long long div;
+
+ /* pixclk is in picoseoncds, our clock is in Hz
+ *
+ * Hz -> picoseconds is / 10^-12
+ */
+
+ div = (unsigned long long)clk * pixclk;
+ do_div(div,1000000UL);
+ do_div(div,1000000UL);
+
+ dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
+ return div;
+}
+
+/*
+ * s3c2410fb_check_var():
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ *
+ */
+static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+
+ dprintk("check_var(var=%p, info=%p)\n", var, info);
+
+ /* validate x/y resolution */
+
+ if (var->yres > fbi->mach_info->yres.max)
+ var->yres = fbi->mach_info->yres.max;
+ else if (var->yres < fbi->mach_info->yres.min)
+ var->yres = fbi->mach_info->yres.min;
+
+ if (var->xres > fbi->mach_info->xres.max)
+ var->yres = fbi->mach_info->xres.max;
+ else if (var->xres < fbi->mach_info->xres.min)
+ var->xres = fbi->mach_info->xres.min;
+
+ /* validate bpp */
+
+ if (var->bits_per_pixel > fbi->mach_info->bpp.max)
+ var->bits_per_pixel = fbi->mach_info->bpp.max;
+ else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
+ var->bits_per_pixel = fbi->mach_info->bpp.min;
+
+ /* set r/g/b positions */
+
+ if (var->bits_per_pixel == 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;
+ var->transp.length = 0;
+ } else {
+ var->red.length = var->bits_per_pixel;
+ var->red.offset = 0;
+ var->green.length = var->bits_per_pixel;
+ var->green.offset = 0;
+ var->blue.length = var->bits_per_pixel;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ }
+
+ return 0;
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+*/
+
+static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
+ struct fb_var_screeninfo *var)
+{
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+
+ dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
+ dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
+ dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
+
+ switch (var->bits_per_pixel) {
+ case 1:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+ break;
+ case 2:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+ break;
+ case 4:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+ break;
+ case 8:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+ break;
+ case 16:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+ break;
+ }
+
+ /* check to see if we need to update sync/borders */
+
+ if (!fbi->mach_info->fixed_syncs) {
+ dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+ var->upper_margin, var->lower_margin,
+ var->vsync_len);
+
+ dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+ var->left_margin, var->right_margin,
+ var->hsync_len);
+
+ fbi->regs.lcdcon2 =
+ S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+ S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+ S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+ fbi->regs.lcdcon3 =
+ S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+ S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+
+ fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
+ fbi->regs.lcdcon4 |= S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+ }
+
+ /* update X/Y info */
+
+ fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+ fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+ fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
+ fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+
+ if (var->pixclock > 0) {
+ int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
+
+ clkdiv = (clkdiv / 2) -1;
+ if (clkdiv < 0)
+ clkdiv = 0;
+
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
+ }
+
+ /* write new registers */
+
+ dprintk("new register set:\n");
+ dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
+ dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
+ dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
+ dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
+ dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
+
+ writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ /* set lcd address pointers */
+ s3c2410fb_set_lcdaddr(fbi);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+}
+
+
+/*
+ * s3c2410fb_set_par - Optional function. Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ */
+static int s3c2410fb_set_par(struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+
+ if (var->bits_per_pixel == 16)
+ fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ else
+ fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8;
+
+ /* activate this new configuration */
+
+ s3c2410fb_activate_var(fbi, var);
+ return 0;
+}
+
+static void schedule_palette_update(struct s3c2410fb_info *fbi,
+ unsigned int regno, unsigned int val)
+{
+ unsigned long flags;
+ unsigned long irqen;
+
+ local_irq_save(flags);
+
+ fbi->palette_buffer[regno] = val;
+
+ if (!fbi->palette_ready) {
+ fbi->palette_ready = 1;
+
+ /* enable IRQ */
+ irqen = readl(S3C2410_LCDINTMSK);
+ irqen &= ~S3C2410_LCDINT_FRSYNC;
+ writel(irqen, S3C2410_LCDINTMSK);
+ }
+
+ local_irq_restore(flags);
+}
+
+/* from pxafb.c */
+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int s3c2410fb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
+{
+ struct s3c2410fb_info *fbi = info->par;
+ unsigned int val;
+
+ /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n", regno, red, green, blue); */
+
+ switch (fbi->fb->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /* true-colour, use pseuo-palette */
+
+ if (regno < 16) {
+ u32 *pal = fbi->fb->pseudo_palette;
+
+ val = chan_to_field(red, &fbi->fb->var.red);
+ val |= chan_to_field(green, &fbi->fb->var.green);
+ val |= chan_to_field(blue, &fbi->fb->var.blue);
+
+ pal[regno] = val;
+ }
+ break;
+
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (regno < 256) {
+ /* currently assume RGB 5-6-5 mode */
+
+ val = ((red >> 0) & 0xf800);
+ val |= ((green >> 5) & 0x07e0);
+ val |= ((blue >> 11) & 0x001f);
+
+ writel(val, S3C2410_TFTPAL(regno));
+ schedule_palette_update(fbi, regno, val);
+ }
+
+ break;
+
+ default:
+ return 1; /* unknown type */
+ }
+
+ return 0;
+}
+
+
+/**
+ * s3c2410fb_blank
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ *
+ */
+static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
+{
+ dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (blank_mode == FB_BLANK_UNBLANK)
+ writel(0x0, S3C2410_TPAL);
+ else {
+ dprintk("setting TPAL to output 0x000000\n");
+ writel(S3C2410_TPAL_EN, S3C2410_TPAL);
+ }
+
+ return 0;
+}
+
+static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
+}
+static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ if (mach_info == NULL)
+ return -EINVAL;
+
+ if (len < 1)
+ return -EINVAL;
+
+ if (strnicmp(buf, "on", 2) == 0 ||
+ strnicmp(buf, "1", 1) == 0) {
+ debug = 1;
+ printk(KERN_DEBUG "s3c2410fb: Debug On");
+ } else if (strnicmp(buf, "off", 3) == 0 ||
+ strnicmp(buf, "0", 1) == 0) {
+ debug = 0;
+ printk(KERN_DEBUG "s3c2410fb: Debug Off");
+ } else {
+ return -EINVAL;
+ }
+
+ return len;
+}
+
+
+static DEVICE_ATTR(debug, 0666,
+ s3c2410fb_debug_show,
+ s3c2410fb_debug_store);
+
+static struct fb_ops s3c2410fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = s3c2410fb_check_var,
+ .fb_set_par = s3c2410fb_set_par,
+ .fb_blank = s3c2410fb_blank,
+ .fb_setcolreg = s3c2410fb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+
+/*
+ * s3c2410fb_map_video_memory():
+ * Allocates the DRAM memory for the frame buffer. This buffer is
+ * remapped into a non-cached, non-buffered, memory region to
+ * allow palette and pixel writes to occur without flushing the
+ * cache. Once this area is remapped, all virtual memory
+ * access to the video memory should occur at the new region.
+ */
+static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi)
+{
+ dprintk("map_video_memory(fbi=%p)\n", fbi);
+
+ fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
+ fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+ &fbi->map_dma, GFP_KERNEL);
+
+ fbi->map_size = fbi->fb->fix.smem_len;
+
+ if (fbi->map_cpu) {
+ /* prevent initial garbage on screen */
+ dprintk("map_video_memory: clear %p:%08x\n",
+ fbi->map_cpu, fbi->map_size);
+ memset(fbi->map_cpu, 0xf0, fbi->map_size);
+
+ fbi->screen_dma = fbi->map_dma;
+ fbi->fb->screen_base = fbi->map_cpu;
+ fbi->fb->fix.smem_start = fbi->screen_dma;
+
+ dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",
+ fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);
+ }
+
+ return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi)
+{
+ dma_free_writecombine(fbi->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma);
+}
+
+static inline void modify_gpio(void __iomem *reg,
+ unsigned long set, unsigned long mask)
+{
+ unsigned long tmp;
+
+ tmp = readl(reg) & ~mask;
+ writel(tmp | set, reg);
+}
+
+
+/*
+ * s3c2410fb_init_registers - Initialise all LCD-related registers
+ */
+
+int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+{
+ unsigned long flags;
+
+ /* Initialise LCD with values from haret */
+
+ local_irq_save(flags);
+
+ /* modify the gpio(s) with interrupts set (bjd) */
+
+ modify_gpio(S3C2410_GPCUP, mach_info->gpcup, mach_info->gpcup_mask);
+ modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
+ modify_gpio(S3C2410_GPDUP, mach_info->gpdup, mach_info->gpdup_mask);
+ modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
+
+ local_irq_restore(flags);
+
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+ writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+ writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+ writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+ s3c2410fb_set_lcdaddr(fbi);
+
+ dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel);
+ writel(mach_info->lpcsel, S3C2410_LPCSEL);
+
+ dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL));
+
+ /* ensure temporary palette disabled */
+ writel(0x00, S3C2410_TPAL);
+
+ /* Enable video by setting the ENVID bit to 1 */
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+ writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+ return 0;
+}
+
+static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
+{
+ unsigned int i;
+ unsigned long ent;
+
+ fbi->palette_ready = 0;
+
+ for (i = 0; i < 256; i++) {
+ if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)
+ continue;
+
+ writel(ent, S3C2410_TFTPAL(i));
+
+ /* it seems the only way to know exactly
+ * if the palette wrote ok, is to check
+ * to see if the value verifies ok
+ */
+
+ if (readw(S3C2410_TFTPAL(i)) == ent)
+ fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+ else
+ fbi->palette_ready = 1; /* retry */
+ }
+}
+
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
+{
+ struct s3c2410fb_info *fbi = dev_id;
+ unsigned long lcdirq = readl(S3C2410_LCDINTPND);
+
+ if (lcdirq & S3C2410_LCDINT_FRSYNC) {
+ if (fbi->palette_ready)
+ s3c2410fb_write_palette(fbi);
+
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND);
+ writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static char driver_name[]="s3c2410fb";
+
+int __init s3c2410fb_probe(struct device *dev)
+{
+ struct s3c2410fb_info *info;
+ struct fb_info *fbinfo;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3c2410fb_hw *mregs;
+ int ret;
+ int irq;
+ int i;
+
+ mach_info = dev->platform_data;
+ if (mach_info == NULL) {
+ dev_err(dev,"no platform data for lcd, cannot attach\n");
+ return -EINVAL;
+ }
+
+ mregs = &mach_info->regs;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq for device\n");
+ return -ENOENT;
+ }
+
+ fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), dev);
+ if (!fbinfo) {
+ return -ENOMEM;
+ }
+
+
+ info = fbinfo->par;
+ info->fb = fbinfo;
+ dev_set_drvdata(dev, fbinfo);
+
+ s3c2410fb_init_registers(info);
+
+ dprintk("devinit\n");
+
+ strcpy(fbinfo->fix.id, driver_name);
+
+ memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
+
+ info->mach_info = dev->platform_data;
+
+ fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbinfo->fix.type_aux = 0;
+ fbinfo->fix.xpanstep = 0;
+ fbinfo->fix.ypanstep = 0;
+ fbinfo->fix.ywrapstep = 0;
+ fbinfo->fix.accel = FB_ACCEL_NONE;
+
+ fbinfo->var.nonstd = 0;
+ fbinfo->var.activate = FB_ACTIVATE_NOW;
+ fbinfo->var.height = mach_info->height;
+ fbinfo->var.width = mach_info->width;
+ fbinfo->var.accel_flags = 0;
+ fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+ fbinfo->fbops = &s3c2410fb_ops;
+ fbinfo->flags = FBINFO_FLAG_DEFAULT;
+ fbinfo->pseudo_palette = &info->pseudo_pal;
+
+ fbinfo->var.xres = mach_info->xres.defval;
+ fbinfo->var.xres_virtual = mach_info->xres.defval;
+ fbinfo->var.yres = mach_info->yres.defval;
+ fbinfo->var.yres_virtual = mach_info->yres.defval;
+ fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
+
+ fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1;
+ fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1;
+ fbinfo->var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
+
+ fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
+ fbinfo->var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
+ fbinfo->var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
+
+ fbinfo->var.red.offset = 11;
+ fbinfo->var.green.offset = 5;
+ fbinfo->var.blue.offset = 0;
+ fbinfo->var.transp.offset = 0;
+ fbinfo->var.red.length = 5;
+ fbinfo->var.green.length = 6;
+ fbinfo->var.blue.length = 5;
+ fbinfo->var.transp.length = 0;
+ fbinfo->fix.smem_len = mach_info->xres.max *
+ mach_info->yres.max *
+ mach_info->bpp.max / 8;
+
+ for (i = 0; i < 256; i++)
+ info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+
+ if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) {
+ ret = -EBUSY;
+ goto dealloc_fb;
+ }
+
+
+ dprintk("got LCD region\n");
+
+ ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, info);
+ if (ret) {
+ dev_err(dev, "cannot get irq %d - err %d\n", irq, ret);
+ ret = -EBUSY;
+ goto release_mem;
+ }
+
+ info->clk = clk_get(NULL, "lcd");
+ if (!info->clk || IS_ERR(info->clk)) {
+ printk(KERN_ERR "failed to get lcd clock source\n");
+ ret = -ENOENT;
+ goto release_irq;
+ }
+
+ clk_use(info->clk);
+ clk_enable(info->clk);
+ dprintk("got and enabled clock\n");
+
+ msleep(1);
+
+ /* Initialize video memory */
+ ret = s3c2410fb_map_video_memory(info);
+ if (ret) {
+ printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+ ret = -ENOMEM;
+ goto release_clock;
+ }
+ dprintk("got video memory\n");
+
+ ret = s3c2410fb_init_registers(info);
+
+ ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
+
+ ret = register_framebuffer(fbinfo);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
+ goto free_video_memory;
+ }
+
+ /* create device files */
+ device_create_file(dev, &dev_attr_debug);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ fbinfo->node, fbinfo->fix.id);
+
+ return 0;
+
+free_video_memory:
+ s3c2410fb_unmap_video_memory(info);
+release_clock:
+ clk_disable(info->clk);
+ clk_unuse(info->clk);
+ clk_put(info->clk);
+release_irq:
+ free_irq(irq,info);
+release_mem:
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+dealloc_fb:
+ framebuffer_release(fbinfo);
+ return ret;
+}
+
+/* s3c2410fb_stop_lcd
+ *
+ * shutdown the lcd controller
+*/
+
+static void s3c2410fb_stop_lcd(void)
+{
+ unsigned long flags;
+ unsigned long tmp;
+
+ local_irq_save(flags);
+
+ tmp = readl(S3C2410_LCDCON1);
+ writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+
+ local_irq_restore(flags);
+}
+
+/*
+ * Cleanup
+ */
+static int s3c2410fb_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+ int irq;
+
+ s3c2410fb_stop_lcd();
+ msleep(1);
+
+ s3c2410fb_unmap_video_memory(info);
+
+ if (info->clk) {
+ clk_disable(info->clk);
+ clk_unuse(info->clk);
+ clk_put(info->clk);
+ info->clk = NULL;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ free_irq(irq,info);
+ release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+ unregister_framebuffer(fbinfo);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* suspend and resume support for the lcd controller */
+
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state)
+{
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+
+ s3c2410fb_stop_lcd();
+
+ /* sleep before disabling the clock, we need to ensure
+ * the LCD DMA engine is not going to get back on the bus
+ * before the clock goes off again (bjd) */
+
+ msleep(1);
+ clk_disable(info->clk);
+
+ return 0;
+}
+
+static int s3c2410fb_resume(struct device *dev)
+{
+ struct fb_info *fbinfo = dev_get_drvdata(dev);
+ struct s3c2410fb_info *info = fbinfo->par;
+
+ clk_enable(info->clk);
+ msleep(1);
+
+ s3c2410fb_init_registers(info);
+
+ return 0;
+}
+
+#else
+#define s3c2410fb_suspend NULL
+#define s3c2410fb_resume NULL
+#endif
+
+static struct device_driver s3c2410fb_driver = {
+ .name = "s3c2410-lcd",
+ .bus = &platform_bus_type,
+ .probe = s3c2410fb_probe,
+ .suspend = s3c2410fb_suspend,
+ .resume = s3c2410fb_resume,
+ .remove = s3c2410fb_remove
+};
+
+int __devinit s3c2410fb_init(void)
+{
+ return driver_register(&s3c2410fb_driver);
+}
+
+static void __exit s3c2410fb_cleanup(void)
+{
+ driver_unregister(&s3c2410fb_driver);
+}
+
+
+module_init(s3c2410fb_init);
+module_exit(s3c2410fb_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
new file mode 100644
index 000000000000..be40968f899e
--- /dev/null
+++ b/drivers/video/s3c2410fb.h
@@ -0,0 +1,56 @@
+/*
+ * linux/drivers/s3c2410fb.h
+ * Copyright (c) Arnaud Patard
+ *
+ * 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.
+ *
+ * S3C2410 LCD Controller Frame Buffer Driver
+ * based on skeletonfb.c, sa1100fb.h
+ *
+ * ChangeLog
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Moved dprintk to s3c2410fb.c
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Renamed from h1940fb.h to s3c2410fb.h
+ * - Chenged h1940 to s3c2410
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - First version
+ */
+
+#ifndef __S3C2410FB_H
+#define __S3C2410FB_H
+
+struct s3c2410fb_info {
+ struct fb_info *fb;
+ struct device *dev;
+ struct clk *clk;
+
+ struct s3c2410fb_mach_info *mach_info;
+
+ /* raw memory addresses */
+ dma_addr_t map_dma; /* physical */
+ u_char * map_cpu; /* virtual */
+ u_int map_size;
+
+ struct s3c2410fb_hw regs;
+
+ /* addresses of pieces placed in raw buffer */
+ u_char * screen_cpu; /* virtual address of buffer */
+ dma_addr_t screen_dma; /* physical address of buffer */
+ unsigned int palette_ready;
+
+ /* keep these registers in case we need to re-write palette */
+ u32 palette_buffer[256];
+ u32 pseudo_pal[16];
+};
+
+#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */
+
+int s3c2410fb_init(void);
+
+#endif
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 2d29db7ef800..3d35b28aaac7 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -173,7 +173,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
@@ -592,13 +592,14 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return ret;
}
+#ifdef CONFIG_CPU_FREQ
/*
* sa1100fb_display_dma_period()
* Calculate the minimum period (in picoseconds) between two DMA
* requests for the LCD controller. If we hit this, it means we're
* doing nothing but LCD DMA.
*/
-static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
{
/*
* Period = pixclock * bits_per_byte * bytes_per_transfer
@@ -606,6 +607,7 @@ static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
*/
return var->pixclock * 8 * 16 / var->bits_per_pixel;
}
+#endif
/*
* sa1100fb_check_var():
@@ -1307,21 +1309,19 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int sa1100fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100fb_suspend(struct device *dev, pm_message_t state)
{
struct sa1100fb_info *fbi = dev_get_drvdata(dev);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- set_ctrlr_state(fbi, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
-static int sa1100fb_resume(struct device *dev, u32 level)
+static int sa1100fb_resume(struct device *dev)
{
struct sa1100fb_info *fbi = dev_get_drvdata(dev);
- if (level == RESUME_ENABLE)
- set_ctrlr_state(fbi, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
#else
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 024a0cecff15..3c98457783c4 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -137,7 +137,6 @@ static int prosavage_gpio_getsda(void* data)
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
}
-#define I2C_ALGO_SAVAGE 0x0f0000
static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
const char *name)
{
@@ -147,7 +146,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
if (add_bus && chan->par) {
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_ALGO_SAVAGE;
+ chan->adapter.id = I2C_HW_B_SAVAGE;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->pcidev->dev;
chan->algo.udelay = 40;
@@ -260,8 +259,9 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
return buf;
}
-int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
+int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
{
+ struct savagefb_par *par = info->par;
u8 *edid = NULL;
int i;
@@ -271,12 +271,22 @@ int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
if (edid)
break;
}
+
+ if (!edid) {
+ /* try to get from firmware */
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e) {
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
+ }
+
if (out_edid)
*out_edid = edid;
- if (!edid)
- return 1;
- return 0;
+ return (edid) ? 0 : 1;
}
MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 8594b1e42d71..ea17f7e0482c 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,7 +60,6 @@
#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
-
/* Chip tags. These are used to group the adapters into
* related families.
*/
@@ -128,6 +127,10 @@ typedef enum {
#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
#define BCI_CMD_SEND_COLOR 0x00008000
+#define DISP_CRT 1
+#define DISP_LCD 2
+#define DISP_DFP 3
+
struct xtimings {
unsigned int Clock;
unsigned int HDisplay;
@@ -166,6 +169,10 @@ struct savagefb_par {
struct savagefb_i2c_chan chan;
unsigned char *edid;
u32 pseudo_palette[16];
+ int pm_state;
+ int display_type;
+ int dvi;
+ int crtonly;
int dacSpeedBpp;
int maxClock;
int minClock;
@@ -338,7 +345,7 @@ do { \
} \
}
-extern int savagefb_probe_i2c_connector(struct savagefb_par *par,
+extern int savagefb_probe_i2c_connector(struct fb_info *info,
u8 **out_edid);
extern void savagefb_create_i2c_busses(struct fb_info *info);
extern void savagefb_delete_i2c_busses(struct fb_info *info);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index f4633d1891f1..7c285455c924 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1400,6 +1400,58 @@ static int savagefb_pan_display (struct fb_var_screeninfo *var,
return 0;
}
+static int savagefb_blank(int blank, struct fb_info *info)
+{
+ struct savagefb_par *par = info->par;
+ u8 sr8 = 0, srd = 0;
+
+ if (par->display_type == DISP_CRT) {
+ vga_out8(0x3c4, 0x08);
+ sr8 = vga_in8(0x3c5);
+ sr8 |= 0x06;
+ vga_out8(0x3c5, sr8);
+ vga_out8(0x3c4, 0x0d);
+ srd = vga_in8(0x3c5);
+ srd &= 0x03;
+
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ srd |= 0x10;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ srd |= 0x40;
+ break;
+ case FB_BLANK_POWERDOWN:
+ srd |= 0x50;
+ break;
+ }
+
+ vga_out8(0x3c4, 0x0d);
+ vga_out8(0x3c5, srd);
+ }
+
+ if (par->display_type == DISP_LCD ||
+ par->display_type == DISP_DFP) {
+ switch(blank) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
+ break;
+ }
+ }
+
+ return (blank == FB_BLANK_NORMAL) ? 1 : 0;
+}
static struct fb_ops savagefb_ops = {
.owner = THIS_MODULE,
@@ -1407,6 +1459,7 @@ static struct fb_ops savagefb_ops = {
.fb_set_par = savagefb_set_par,
.fb_setcolreg = savagefb_setcolreg,
.fb_pan_display = savagefb_pan_display,
+ .fb_blank = savagefb_blank,
#if defined(CONFIG_FB_SAVAGE_ACCEL)
.fb_fillrect = savagefb_fillrect,
.fb_copyarea = savagefb_copyarea,
@@ -1583,8 +1636,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 };
static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-
- int videoRam, videoRambytes;
+ int videoRam, videoRambytes, dvi;
DBG("savage_init_hw");
@@ -1705,9 +1757,32 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
par->MCLK);
+ /* check for DVI/flat panel */
+ dvi = 0;
+
+ if (par->chip == S3_SAVAGE4) {
+ unsigned char sr30 = 0x00;
+
+ vga_out8(0x3c4, 0x30);
+ /* clear bit 1 */
+ vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
+ sr30 = vga_in8(0x3c5);
+ if (sr30 & 0x02 /*0x04 */) {
+ dvi = 1;
+ printk("savagefb: Digital Flat Panel Detected\n");
+ }
+ }
+
+ if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly)
+ par->display_type = DISP_LCD;
+ else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
+ par->display_type = DISP_DFP;
+ else
+ par->display_type = DISP_CRT;
+
/* Check LCD panel parrmation */
- if (par->chip == S3_SAVAGE_MX) {
+ if (par->display_type == DISP_LCD) {
unsigned char cr6b = VGArCR( 0x6b );
int panelX = (VGArSEQ (0x61) +
@@ -1759,7 +1834,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
par->SavagePanelWidth = panelX;
par->SavagePanelHeight = panelY;
- }
+ } else
+ par->display_type = DISP_CRT;
}
savage_get_default_par (par);
@@ -1899,12 +1975,11 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->pixmap.buf_align = 4;
info->pixmap.access_align = 32;
- fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+ err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+ if (!err)
info->flags |= FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
-
- err = 0;
}
#endif
return err;
@@ -1932,14 +2007,14 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
if (err)
goto failed_enable;
- if (pci_request_regions(dev, "savagefb")) {
+ if ((err = pci_request_regions(dev, "savagefb"))) {
printk(KERN_ERR "cannot request PCI regions\n");
goto failed_enable;
}
err = -ENOMEM;
- if (savage_init_fb_info(info, dev, id))
+ if ((err = savage_init_fb_info(info, dev, id)))
goto failed_init;
err = savage_map_mmio(info);
@@ -1947,6 +2022,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
goto failed_mmio;
video_len = savage_init_hw(par);
+ /* FIXME: cant be negative */
if (video_len < 0) {
err = video_len;
goto failed_mmio;
@@ -1959,7 +2035,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
INIT_LIST_HEAD(&info->modelist);
#if defined(CONFIG_FB_SAVAGE_I2C)
savagefb_create_i2c_busses(info);
- savagefb_probe_i2c_connector(par, &par->edid);
+ savagefb_probe_i2c_connector(info, &par->edid);
+ kfree(par->edid);
fb_edid_to_monspecs(par->edid, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
@@ -2110,15 +2187,31 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
struct savagefb_par *par = (struct savagefb_par *)info->par;
DBG("savagefb_suspend");
- printk(KERN_DEBUG "state: %u\n", state);
+
+
+ par->pm_state = state.event;
+
+ /*
+ * For PM_EVENT_FREEZE, do not power down so the console
+ * can remain active.
+ */
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ return 0;
+ }
acquire_console_sem();
- fb_set_suspend(info, pci_choose_state(dev, state));
- savage_disable_mmio(par);
- release_console_sem();
+ fb_set_suspend(info, 1);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+ savagefb_blank(FB_BLANK_POWERDOWN, info);
+ savage_disable_mmio(par);
+ pci_save_state(dev);
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
+ release_console_sem();
return 0;
}
@@ -2128,22 +2221,34 @@ static int savagefb_resume (struct pci_dev* dev)
struct fb_info *info =
(struct fb_info *)pci_get_drvdata(dev);
struct savagefb_par *par = (struct savagefb_par *)info->par;
+ int cur_state = par->pm_state;
DBG("savage_resume");
- pci_set_power_state(dev, 0);
- pci_restore_state(dev);
- if(pci_enable_device(dev))
- DBG("err");
+ par->pm_state = PM_EVENT_ON;
- SavagePrintRegs();
+ /*
+ * The adapter was not powered down coming back from a
+ * PM_EVENT_FREEZE.
+ */
+ if (cur_state == PM_EVENT_FREEZE) {
+ pci_set_power_state(dev, PCI_D0);
+ return 0;
+ }
acquire_console_sem();
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
+ if(pci_enable_device(dev))
+ DBG("err");
+
+ pci_set_master(dev);
savage_enable_mmio(par);
savage_init_hw(par);
savagefb_set_par (info);
-
+ savagefb_blank(FB_BLANK_UNBLANK, info);
fb_set_suspend (info, 0);
release_console_sem();
@@ -2277,3 +2382,6 @@ static int __init savagefb_init(void)
module_init(savagefb_init);
module_exit(savage_done);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 8413907b379a..cf5106eab2d5 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -18,6 +18,8 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
#include <asm/mtrr.h>
diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/sis/300vtbl.h
index b6d5c71b2563..e4b4a2626da4 100644
--- a/drivers/video/sis/300vtbl.h
+++ b/drivers/video/sis/300vtbl.h
@@ -3,7 +3,7 @@
/*
* Register settings for SiS 300 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,31 +50,7 @@
*
*/
-static const SiS_StStruct SiS300_SModeIDTable[] =
-{
- {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
- {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
- {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00, 0},
- {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00, 0},
- {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00, 0},
- {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
- {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00, 0},
- {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00, 0},
- {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00, 0},
- {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00, 0},
- {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00, 0},
- {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00, 0},
- {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00, 0},
- {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00, 0},
- {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00, 0},
- {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00, 0},
- {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00, 0},
- {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
- {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00, 0},
- {0xff, 0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static const SiS_ExtStruct SiS300_EModeIDTable[] =
+static const struct SiS_Ext SiS300_EModeIDTable[] =
{
{0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x? */
{0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1},
@@ -110,7 +86,7 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0x59,0x921b,0x0138,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x8 */
{0x5c,0x921f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26,-1}, /* 512x384x32 */
{0x5d,0x021d,0x0139,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x16 */
- {0x5e,0x021f,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x32 */
+ {0x5e,0x021f,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x32 */
{0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1},
{0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x32 */
{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
@@ -119,8 +95,8 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
- {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x8 - not in BIOS! */
- {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x16 - not in BIOS! */
+ {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x8 */
+ {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x16 */
{0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d,-1}, /* 800x480x8 */
{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x8 */
{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x16 */
@@ -166,77 +142,77 @@ static const SiS_ExtStruct SiS300_EModeIDTable[] =
{0xff,0x0000,0xffff,0, 0x00,0x00,0x00,0x00,0x00}
};
-static const SiS_Ext2Struct SiS300_RefIndex[] =
-{
- {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
- {0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
- {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
- {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0}, /* 03 */
- {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0}, /* 04 */
- {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0}, /* 05 */
- {0x0047,0x11,0x4e,0x00,0x05,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
- {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0}, /* 07 */
- {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
- {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
- {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
- {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
- {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 0c */
- {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0}, /* 0d */
- {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0}, /* 0e */
- {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0}, /* 0f */
- {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
- {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0}, /* 11 */
- {0x006f,0x32,0x03,0x06,0x14,0x32, 720, 576, 0}, /* 12 */
- {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0}, /* 13 */
- {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
- {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
- {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
- {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
- {0x0047,0x1a,0x52,0x00,0x06,0x37,1024, 768, 0}, /* 18 */
- {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
- {0x0387,0x1c,0x4d,0x00,0x07,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
- {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0}, /* 1b */
- {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0}, /* 1c */
- {0x0007,0x1f,0x98,0x00,0x07,0x3a,1280,1024, 0}, /* 1d */
- {0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
- {0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
- {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
- {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
- {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
- {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
- {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
- {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
- {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */ /* was c077 */
- {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
- {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
- {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
- {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
- {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
- {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */ /* VCLK 0x09 */
- {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0}, /* 2d */
- {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0}, /* 2e */
- {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0}, /* 2f */
- {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0}, /* 30 */
- {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0}, /* 31 */
- {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0}, /* 32 */
- {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0}, /* 33 */
- {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0}, /* 34 */
- {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0}, /* 35 */
- {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0}, /* 36 1152x864-60Hz */
- {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0}, /* 37 1152x864-75Hz */
- {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0}, /* 38 1152x864-85Hz */
- {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0}, /* 39 848x480-38Hzi */
- {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0}, /* 3a 848x480-60Hz */
- {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3b 856x480-38Hzi */
- {0xc047,0x42,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3c 856x480-60Hz */
- {0x0067,0x43,0x3e,0x0c,0x1b,0x48,1360, 768, 0}, /* 3d 1360x768-60Hz */
- {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0}, /* 3e 1280x768-60Hz */
- {0x006f,0x47,0x03,0x06,0x15,0x5f, 768, 576, 0}, /* 3f 768x576 */
- {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0}, /* 40 1360x1024-59Hz (BARCO1366 only) */
- {0xffff, 0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
+static const struct SiS_Ext2 SiS300_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 00 */
+ {0x0467,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 01 */
+ {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 02 - CRT1CRTC was 0x4f */
+ {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 03 */
+ {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 04 */
+ {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 05 */
+ {0x0047,0x11,0x0e,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 06 - CRT1CRTC was 0x51 */
+ {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 07 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 08 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 09 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0a */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0b */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0c */
+ {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0d */
+ {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0e */
+ {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0f */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0, 0x4a, 0x49}, /* 10 */
+ {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0, 0x00, 0x00}, /* 11 */
+ {0x006f,0x32,0x4a,0x06,0x14,0x32, 720, 576, 0, 0x00, 0x00}, /* 12 */ /* 4a was 03 */
+ {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 13 */
+ {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 14 */
+ {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 15 - CRT1CRTC was 0x97 */
+ {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 16 */
+ {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 17 - CRT1CRTC was 0x59 */
+ {0x0047,0x1a,0x12,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 18 */
+ {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 19 - CRT1CRTC was 0x5b */
+ {0x0387,0x1c,0x0d,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1a - CRT1CRTC was 0x5c */
+ {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1b */
+ {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1c */
+ {0x0007,0x1f,0x18,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1d */
+ {0x0007,0x20,0x19,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1e - CRT1CRTC was 0x60 */
+ {0x0007,0x21,0x1a,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1f */
+ {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 20 */
+ {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 21 - CRT1CRTC was 0x63 */
+ {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 22 */
+ {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0, 0x4b, 0x4b}, /* 23 */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0, 0x00, 0x00}, /* 24 */
+ {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0, 0x00, 0x00}, /* 25 */
+ {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0, 0x00, 0x00}, /* 26 */ /* was c077 */
+ {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0, 0x00, 0x00}, /* 27 */
+ {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0, 0x00, 0x00}, /* 28 */
+ {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 29 - 1280x960-60 */
+ {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 2a - 1280x960-85 */
+ {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0, 0x00, 0x00}, /* 2b */
+ {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0, 0x00, 0x00}, /* 2c */ /* VCLK 0x09 */
+ {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2d */
+ {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2e */
+ {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2f */
+ {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 30 */
+ {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 31 */
+ {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 32 */
+ {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 33 */
+ {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 34 */
+ {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 35 */
+ {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 36 1152x864-60Hz */
+ {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 37 1152x864-75Hz */
+ {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 38 1152x864-85Hz */
+ {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 39 848x480-38Hzi */
+ {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 3a 848x480-60Hz */
+ {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3b 856x480-38Hzi */
+ {0xc067,0x42,0x28,0x0c,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3c 856x480-60Hz */
+ {0x0067,0x43,0x3e,0x0d,0x1b,0x48,1360, 768, 0, 0x00, 0x00}, /* 3d 1360x768-60Hz */
+ {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0, 0x00, 0x00}, /* 3e 1280x768-60Hz */
+ {0x006f,0x47,0x4c,0x06,0x15,0x5f, 768, 576, 0, 0x00, 0x00}, /* 3f 768x576 */
+ {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0, 0x00, 0x00}, /* 40 1360x1024-59Hz (BARCO1366 only) */
+ {0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_VBMode SiS300_VBModeIDTable[] =
{
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -303,53 +279,26 @@ static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
-static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
+static const struct SiS_CRT1Table SiS300_CRT1Table[] =
{
-#if 1
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 - 320x200 */
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
0x00}},
-#endif
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f, /* 0x00 - corrected 320x200-72 - does not work */
- 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04,
- 0x00}},
-#endif
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* 0x01 */
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
0x00}},
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e, /* 0x01 - corrected 320x240-60 - does not work */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04,
- 0x00}},
-#endif
{{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 */
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
0x01}},
-#if 0
- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 - corrected 400x300-60 */
- 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
- 0x01}},
-#endif
{{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
0x01}},
{{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
0x00}},
-#if 0
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 0x05 */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
-#endif
{{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */
0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
0x00}},
-#if 0
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, /* 0x06 */
- 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
- 0x00}},
-#endif
{{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */
0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
0x00}},
@@ -359,19 +308,9 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
0x00}},
-#if 0
- {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e, /* 0x09 */
- 0xe4,0x87,0xdf,0xdf,0x04,0x00,0x00,0x01,
- 0x00}},
-#endif
{{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x09 - corrected 640x480-100 */
0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
0x00}},
-#if 0
- {{0x6c,0x4f,0x4f,0x83,0x59,0x9e,0x00,0x3e, /* 0x0a */
- 0xe5,0x8d,0xdf,0xdf,0x01,0x00,0x00,0x01,
- 0x00}},
-#endif
{{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x0a - corrected 640x480-120 */
0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
0x00}},
@@ -459,11 +398,6 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
0x00}},
-#if 0
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 0x27: 1280x960-70 - invalid! */
- 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}},
-#endif
{{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 0x27: 1280x960-60 - correct */
0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
0x01}},
@@ -497,9 +431,9 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
0x00}},
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 0x32 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}},
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, /* 0x32: 720x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}},
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* 0x33 - 1024x600 */
0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
0x01}},
@@ -560,18 +494,24 @@ static const SiS_CRT1TableStruct SiS300_CRT1Table[] =
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, /* 1280x768-60 */
0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
0x01}}, /* 0x46 */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x47 */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x47 */
{{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52, /* 1360x1024 (Barco iQ Pro R300) */
0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
0x00}}, /* 0x48 */
{{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
- 0x41}} /* 0x49 */
+ 0x41}}, /* 0x49 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+ 0x40}}, /* 0x4a */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+ 0x00}} /* 0x4b */
};
-static const SiS_MCLKDataStruct SiS300_MCLKData_630[] =
+static const struct SiS_MCLKData SiS300_MCLKData_630[] =
{
{ 0x5a,0x64,0x80, 66},
{ 0xb3,0x45,0x80, 83},
@@ -583,7 +523,7 @@ static const SiS_MCLKDataStruct SiS300_MCLKData_630[] =
{ 0x37,0x61,0x80,100}
};
-static const SiS_MCLKDataStruct SiS300_MCLKData_300[] =
+static const struct SiS_MCLKData SiS300_MCLKData_300[] =
{
{ 0x68,0x43,0x80,125},
{ 0x68,0x43,0x80,125},
@@ -595,7 +535,7 @@ static const SiS_MCLKDataStruct SiS300_MCLKData_300[] =
{ 0x37,0x61,0x80,100}
};
-static SiS_VCLKDataStruct SiS300_VCLKData[] =
+static struct SiS_VCLKData SiS300_VCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -669,53 +609,26 @@ static SiS_VCLKDataStruct SiS300_VCLKData[] =
{ 0xe2,0x46,135}, /* 0x45 */ /* 1280x1024-75, better clock for VGA2 */
{ 0x70,0x29, 81}, /* 0x46 */ /* unused */
{ 0, 0, 0}, /* 0x47 custom (will be filled out) */
- { 0xce,0x25,189} /* 0x48 */ /* Replacement for index 0x1b for 730 (and 540?) */
+ { 0xce,0x25,189}, /* 0x48 */ /* Replacement for index 0x1b for 730 (and 540?) */
+ { 0x15,0xe1, 20}, /* 0x49 */ /* 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x4a */ /* 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x4b */ /* 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35} /* 0x4c */ /* 768@576@60 */
};
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR07 = 0x10;
-#endif
-
-static const DRAM4Type SiS300_SR15[8] =
+static const unsigned char SiS300_SR15[4 * 8] =
{
- {0x01,0x09,0xa3,0x00},
- {0x43,0x43,0x43,0x00},
- {0x1e,0x1e,0x1e,0x00},
- {0x2a,0x2a,0x2a,0x00},
- {0x06,0x06,0x06,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00}
+ 0x01,0x09,0xa3,0x00,
+ 0x43,0x43,0x43,0x00,
+ 0x1e,0x1e,0x1e,0x00,
+ 0x2a,0x2a,0x2a,0x00,
+ 0x06,0x06,0x06,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00
};
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR1F = 0x00;
-static UCHAR SiS300_SR21 = 0x16;
-static UCHAR SiS300_SR22 = 0xb2;
-static UCHAR SiS300_SR23 = 0xf6;
-static UCHAR SiS300_SR24 = 0x0d;
-static UCHAR SiS300_SR25[] = {0x0,0x0};
-static UCHAR SiS300_SR31 = 0x00;
-static UCHAR SiS300_SR32 = 0x11;
-static UCHAR SiS300_SR33 = 0x00;
-static UCHAR SiS300_CRT2Data_1_2 = 0x40;
-static UCHAR SiS300_CRT2Data_4_D = 0x00;
-static UCHAR SiS300_CRT2Data_4_E = 0x00;
-static UCHAR SiS300_CRT2Data_4_10 = 0x80;
-
-static const USHORT SiS300_RGBSenseData = 0xd1;
-static const USHORT SiS300_VideoSenseData = 0xb3;
-static const USHORT SiS300_YCSenseData = 0xb9;
-static const USHORT SiS300_RGBSenseData2 = 0x0190;
-static const USHORT SiS300_VideoSenseData2 = 0x0174;
-static const USHORT SiS300_YCSenseData2 = 0x016b;
-
-static const DRAM4Type SiS300_CR40[5];
-
-static UCHAR SiS300_CR49[2];
-#endif
-
-static const SiS_PanelDelayTblStruct SiS300_PanelDelayTbl[] =
+static const struct SiS_PanelDelayTbl SiS300_PanelDelayTbl[] =
{
{{0x05,0xaa}},
{{0x05,0x14}},
@@ -735,33 +648,11 @@ static const SiS_PanelDelayTblStruct SiS300_PanelDelayTbl[] =
{{0x05,0x60}}
};
-#if 0
-static const SiS_PanelDelayTblStruct SiS300_PanelDelayTblLVDS[] =
-{
- {{0x05,0xaa}},
- {{0x05,0x14}},
- {{0x05,0x36}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x90}},
- {{0x05,0x90}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}},
- {{0x05,0x14}}, /* 2.07a (JVC): 14,96 */
- {{0x05,0x28}}, /* 2.04.5c: 20, 80 - Clevo (2.04.2c): 05, 28 */
- {{0x05,0x14}},
- {{0x05,0x14}}, /* Some BIOSes: 05, 40 */
- {{0x05,0x60}}
-};
-#endif
-
/**************************************************************/
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const SiS_LCDDataStruct SiS300_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1024x768Data[] =
{
{ 62, 25, 800, 546,1344, 806},
{ 32, 15, 930, 546,1344, 806},
@@ -772,7 +663,7 @@ static const SiS_LCDDataStruct SiS300_St2LCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS300_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1024x768Data[] =
{
{ 12, 5, 896, 512,1344, 806},
{ 12, 5, 896, 510,1344, 806},
@@ -789,7 +680,7 @@ static const SiS_LCDDataStruct SiS300_ExtLCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS300_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1280x1024Data[] =
{
{ 22, 5, 800, 510,1650,1088},
{ 22, 5, 800, 510,1650,1088},
@@ -801,7 +692,7 @@ static const SiS_LCDDataStruct SiS300_St2LCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_LCDDataStruct SiS300_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -813,53 +704,116 @@ static const SiS_LCDDataStruct SiS300_ExtLCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_1[] =
{ /* VESA Timing */
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
+ {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+ {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_2[] =
{ /* Non-VESA */
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+ {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
};
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_3[] =
{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
};
/**************************************************************/
/* LVDS/Chrontel -------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS300_CHTVUPALData[] =
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_1[]=
+{
+ { 832, 438,1331, 806},
+ { 832, 388,1331, 806},
+ { 832, 438,1331, 806},
+ { 832, 388,1331, 806},
+ { 832, 518,1331, 806},
+ {1050, 638,1344, 806},
+ {1344, 806,1344, 806},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066} /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066} /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ G series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1024Data_1[]=
+{
+ { 832, 438,1331, 806},
+ { 832, 409,1331, 806},
+ { 832, 438,1331, 806},
+ { 832, 409,1331, 806},
+ { 832, 518,1331, 806}, /* 640x480 */
+ {1050, 638,1344, 806}, /* 800x600 */
+ {1344, 806,1344, 806}, /* 1024x768 */
+};
+
+/* Custom data for 848x480 and 856x480 parallel LVDS panels */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_1[]=
+{
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 640x480 TODO */
+ {1088, 525,1088, 525}, /* 800x600 TODO */
+ {1088, 525,1088, 525}, /* 1024x768 TODO */
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 848x480 */
+ {1088, 525,1088, 525}, /* 856x480 */
+ {1088, 525,1088, 525} /* 1360x768 TODO */
+};
+
+/* Custom data for 848x480 parallel panel */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_2[]=
+{
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 640x480 */
+ {1088, 525,1088, 525}, /* 800x600 */
+ {1088, 525,1088, 525}, /* 1024x768 */
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ { 0, 0, 0, 0},
+ {1088, 525,1088, 525}, /* 848x480 */
+ {1088, 525,1088, 525}, /* 856x480 */
+ {1088, 525,1088, 525} /* 1360x768 TODO */
+};
+
+static const struct SiS_LVDSData SiS300_CHTVUPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -869,7 +823,7 @@ static const SiS_LVDSDataStruct SiS300_CHTVUPALData[] =
{ 936, 836, 936, 836}
};
-static const SiS_LVDSDataStruct SiS300_CHTVOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -879,7 +833,7 @@ static const SiS_LVDSDataStruct SiS300_CHTVOPALData[] =
{ 960, 750, 960, 750}
};
-static const SiS_LVDSDataStruct SiS300_CHTVSOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVSOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -889,486 +843,8 @@ static const SiS_LVDSDataStruct SiS300_CHTVSOPALData[] =
{ 944, 625, 944, 625}
};
-
-static const SiS_LVDSDesStruct SiS300_PanelType00_1[] =
-{
- { 1059, 626 }, /* 2.08 */
- { 1059, 624 },
- { 1059, 626 },
- { 1059, 624 },
- { 1059, 624 },
- { 0, 627 },
- { 0, 627 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {0, 626},
- {0, 624},
- {0, 626},
- {0, 624},
- {0, 624},
- {0, 627},
- {0, 627},
- {0, 0},
- {0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType01_1[] =
-{
- { 0, 0 }, /* 2.08 */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType02_1[] =
-{
- { 1059, 626 }, /* 2.08 */
- { 1059, 624 },
- { 1059, 626 },
- { 1059, 624 },
- { 1059, 624 },
- { 0, 627 },
- { 0, 627 },
- { 0, 0 },
- { 0, 0 }
-#if 0
- {0, 626},
- {0, 624},
- {0, 626},
- {0, 624},
- {0, 624},
- {0, 627},
- {0, 627},
- {0, 0},
- {0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType03_1[] =
-{
- { 8, 436},
- { 8, 440},
- { 8, 436},
- { 8, 440},
- { 8, 512},
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType04_1[] = /* 1280x1024 */
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType05_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType06_1[] = /* Clevo Trumpion 1024x768 */
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType07_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType08_1[] =
-{
- {1059, 626},
- {1059, 624},
- {1059, 626},
- {1059, 624},
- {1059, 624},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType09_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0a_1[] =
-{
- {1059, 626},
- {1059, 624},
- {1059, 626},
- {1059, 624},
- {1059, 624},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0b_1[] =
-{
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- {1343, 0},
- { 0, 799},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0c_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0d_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0e_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0}, /* 640x480 */
- {1343, 0}, /* 800x600 */
- { 0, 805}, /* 1024x768 */
- { 0, 794}, /* 1280x1024 */
- { 0, 0} /* 1280x960 - not applicable */
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0f_1[] =
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType00_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType01_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType02_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType03_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- {1152, 622},
- {1152, 597}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType04_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType05_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType06_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType07_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType08_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType09_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0a_2[] =
-{
- {976, 527},
- {976, 502},
- {976, 527},
- {976, 502},
- {976, 567},
- { 0, 627},
- { 0, 627},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0b_2[] =
-{
- { 1152, 700},
- { 1152, 675},
- { 1152, 700},
- { 1152, 675},
- { 1152, 740},
- { 1232, 799},
- { 0, 799},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0c_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0d_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0e_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelType0f_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelTypeNS_1[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 805},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS300_PanelTypeNS_2[] =
-{
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0}
-};
-
-/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */
+/* Custom des data for Barco iQ R200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */
{
{1330, 798}, /* 320x200 */
{1330, 794},
@@ -1381,7 +857,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x102
{ 0, 0} /* 1360x1024 */
};
-static const SiS_LVDSDesStruct SiS300_PanelType04_2a[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2a[] =
{
{1152, 622},
{1152, 597},
@@ -1394,8 +870,8 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_2a[] =
{ 0, 0}
};
-/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */
+/* Custom des data for Barco iQ G200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1b[] = /* 1024x768 */
{
{1330, 798}, /* 320x200 */
{1330, 794},
@@ -1406,7 +882,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */
{ 0, 805} /* 1024x768 / 512x384 */
};
-static const SiS_LVDSDesStruct SiS300_PanelType04_2b[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2b[] =
{
{1152, 622},
{1152, 597},
@@ -1419,376 +895,7 @@ static const SiS_LVDSDesStruct SiS300_PanelType04_2b[] =
/* CRT1 CRTC for slave modes */
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[] =
-{
- {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] =
-{
- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
- 0x00 }},
- {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04,
- 0x00 }},
- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xE2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-
-#if 0
- {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00 }},
- {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
- 0x00}},
- {{0x37,0x27,0x9B,0x2b,0x94,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x41,0x31,0x85,0x35,0x1d,0x7c,0xf0,
- 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
- 0x02,0x88,0xFf,0x25,0x10,0x00,0x01,
- 0x01 }}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] =
-{
- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00 }},
- {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00 }},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
- 0x00 }},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x04,
- 0x00 }},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[] =
-{
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
- 0x1c,0x80,0xdf,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] =
-{
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e,
- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
- 0x00 }},
- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba,
- 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05,
- 0x00 }},
- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x4f,0x31,0x93,0x3e,0x86,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01 }},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
- 0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UNTSC[] =
{
{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1810,7 +917,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1ONTSC[] =
{
{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1832,7 +939,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1854,7 +961,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1OPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1876,7 +983,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1SOPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1898,7 +1005,7 @@ static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] =
0x01 }}
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UNTSC[] =
{
{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1908,7 +1015,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 24: 800x600 NTSC 7/10 */
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_ONTSC[] =
{
{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1918,7 +1025,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 23: 800x600 NTSC 3/4 */
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1929,7 +1036,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_OPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1940,26 +1047,26 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
};
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_SOPAL[] =
{
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
- {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */
- {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* TW: Mode 19: 800x600 PAL 1/1 */
+ {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 13: 640x480 PAL 5/4 */
+ {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 19: 800x600 PAL 1/1 */
};
-static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e};
+static const unsigned char SiS300_CHTVVCLKUNTSC[] = { 0x29,0x29,0x29,0x29,0x2a,0x2e };
-static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-static const UCHAR SiS300_CHTVVCLKSONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKSONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-static const UCHAR SiS300_CHTVVCLKUPAL[] = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31};
+static const unsigned char SiS300_CHTVVCLKUPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x2f,0x31 };
-static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32};
+static const unsigned char SiS300_CHTVVCLKOPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x30,0x32 };
-static const UCHAR SiS300_CHTVVCLKSOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x36,0x29};
+static const unsigned char SiS300_CHTVVCLKSOPAL[] = { 0x2f,0x2f,0x2f,0x2f,0x36,0x29 };
diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/sis/310vtbl.h
index 2c71d048f7c4..54fcbbf4ef63 100644
--- a/drivers/video/sis/310vtbl.h
+++ b/drivers/video/sis/310vtbl.h
@@ -1,9 +1,9 @@
/* $XFree86$ */
/* $XdotOrg$ */
/*
- * Register settings for SiS 315/330 series
+ * Register settings for SiS 315/330/340 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,37 +50,13 @@
*
*/
-static const SiS_StStruct SiS310_SModeIDTable[]=
-{
- {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
- {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
- {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01, 0x40},
- {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02, 0x40},
- {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02, 0x40},
- {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03, 0x40},
- {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05, 0x40},
- {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03, 0x40},
- {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03, 0x40},
- {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05, 0x40},
- {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05, 0x40},
- {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05, 0x40},
- {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04, 0x40},
- {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05, 0x40},
- {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05, 0x40},
- {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
-};
-
-static const SiS_ExtStruct SiS310_EModeIDTable[]=
+static const struct SiS_Ext SiS310_EModeIDTable[] =
{
{0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
{0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
- {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+ {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
{0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
- {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+ {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
{0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
{0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
{0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
@@ -103,10 +79,10 @@ static const SiS_ExtStruct SiS310_EModeIDTable[]=
{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
{0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8 */
{0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8 */
- {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8 */
+ {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8 */
{0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
{0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
- {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+ {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
{0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8 */
{0x5a,0x021b,0x0138,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8 fstn */
{0x5b,0x0a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
@@ -139,406 +115,335 @@ static const SiS_ExtStruct SiS310_EModeIDTable[]=
{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
- {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
- {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
- {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
- {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
- {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
- {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
- {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1}, /* 848x480 */
- {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1},
- {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1},
- {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1}, /* 856x480 */
- {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1},
- {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1},
- {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 1360x768 */
- {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
- {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x8 */
+ {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x16 */
+ {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x32*/
+ {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1}, /* 1152x864 */
+ {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+ {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+ {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1}, /* 848x480 */
+ {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1},
+ {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x48,-1},
+ {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 856x480 */
+ {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x4a,-1},
+ {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1}, /* 1360x768 */
+ {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
+ {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
{0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
{0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
{0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
- {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1}, /* 768x576 */
- {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1},
- {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1},
- {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, /* 1280x800 */
- {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
- {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
- {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, /* 1680x1050 */
- {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
- {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
- {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, /* 1920x1080(i) */
- {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
- {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
- {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1}, /* 960x540 */
- {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1},
- {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1},
- {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1}, /* 960x600 */
- {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1},
- {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1},
+ {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1}, /* 768x576 */
+ {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1},
+ {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4d,-1},
+ {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7}, /* 1280x800 */
+ {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+ {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+ {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9}, /* 1680x1050 */
+ {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+ {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+ {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1}, /* 1920x1080(i) */
+ {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+ {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+ {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1}, /* 960x540 */
+ {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1},
+ {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x53,-1},
+ {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1}, /* 960x600 */
+ {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1},
+ {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x54,-1},
+ {0x1a,0x0e3b,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8}, /* 1280x854 */
+ {0x1b,0x0e7d,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
+ {0x1c,0x0eff,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
{0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
};
-static const SiS_Ext2Struct SiS310_RefIndex[]=
-{
- {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
- {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
- {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
- {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
- {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
- {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
- {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
- {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
- {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
- {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
- {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
- {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
- {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
- {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
- {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
- {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
- {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
- {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
- {0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
- {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
- {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
- {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
- {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
- {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
- {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
- {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
- {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
- {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
- {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
- {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
- {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
- {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
- {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
- {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
- {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
- {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
- {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
- {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
- {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
- {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
- {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
- {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
- {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
- {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
- {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
- {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
- {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
- {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
- {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
- {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
- {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
- {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
- {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
- {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
- {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
- {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
- {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
- {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
- {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
- {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
- {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
- {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
- {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
- {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */ /* FSTN 320x240 */
- {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */ /* 0x5b was 0x12 */
- {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
- {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
- {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-60Hz */
- {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-75Hz */
- {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x45 1152x864-85Hz */
- {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-38Hzi */
- {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x47 848x480-60Hz */
- {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-38Hzi */
- {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x49 856x480-60Hz */
- {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x4a 1360x768-60Hz */
- {0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4b 768x576-56Hz */
- {0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4c 1280x800-60Hz */
- {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4d 1680x1050-60Hz */
- {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30}, /* 0x4e 1920x1080 60Hzi */
- {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30}, /* 0x4f 960x540 60Hz */
- {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30}, /* 0x50 960x600 60Hz */
- {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0}
-};
-
-#ifdef LINUX_XF86
-static const struct {
- UCHAR Ext_ModeID; /* ModeID in new ROM */
- UCHAR Ext_MyModeID; /* corresponding ModeID in my tables (0 = identical) */
- USHORT Ext_VESAID; /* corresponding VESA ID in new ROM */
-} SiS_EModeIDTable661[] = {
- { 0x6a, 0x00, 0x0102 },
- { 0x1d, 0x20, 0x0000 },
- { 0x1e, 0x21, 0x0000 },
- { 0x1f, 0x22, 0x0000 },
- { 0x20, 0x29, 0x0000 },
- { 0x21, 0x2a, 0x0000 },
- { 0x22, 0x2b, 0x0000 },
- { 0x23, 0x00, 0x011c },
- { 0x24, 0x00, 0x011d },
- { 0x25, 0x00, 0x011e },
- { 0x26, 0x00, 0x011f },
- { 0x27, 0x00, 0x0120 },
- { 0x28, 0x00, 0x0121 },
- { 0x2a, 0x14, 0x013d },
- { 0x2b, 0x15, 0x013e },
- { 0x2c, 0x16, 0x013f },
- { 0x2e, 0x00, 0x0101 },
- { 0x2f, 0x00, 0x0100 },
- { 0x30, 0x00, 0x0103 },
- { 0x37, 0x00, 0x0104 },
- { 0x38, 0x00, 0x0105 },
- { 0x3a, 0x00, 0x0107 },
- { 0x3c, 0x00, 0x0125 },
- { 0x3d, 0x00, 0x0126 },
- { 0x40, 0x00, 0x010d },
- { 0x41, 0x00, 0x010e },
- { 0x43, 0x00, 0x0110 },
- { 0x44, 0x00, 0x0111 },
- { 0x46, 0x00, 0x0113 },
- { 0x47, 0x00, 0x0114 },
- { 0x49, 0x00, 0x0116 },
- { 0x4a, 0x00, 0x0117 },
- { 0x4c, 0x00, 0x0119 },
- { 0x4d, 0x00, 0x011a },
- { 0x50, 0x00, 0x0127 },
- { 0x51, 0x00, 0x0128 },
- { 0x52, 0x00, 0x0129 },
- { 0x56, 0x00, 0x012a },
- { 0x57, 0x00, 0x012b },
- { 0x58, 0x00, 0x012c },
- { 0x59, 0x00, 0x012d },
- { 0x5a, 0x17, 0x012e },
- { 0x5b, 0x18, 0x012f },
- { 0x5c, 0x19, 0x0130 },
- { 0x5d, 0x00, 0x0131 },
- { 0x62, 0x00, 0x0112 },
- { 0x63, 0x00, 0x0115 },
- { 0x64, 0x00, 0x0118 },
- { 0x65, 0x00, 0x011b },
- { 0x66, 0x00, 0x0132 },
- { 0x75, 0x00, 0x013a },
- { 0x78, 0x00, 0x013b },
- { 0x79, 0x00, 0x013c },
- { 0x7b, 0x7c, 0x0136 },
- { 0x7c, 0x7d, 0x0137 },
- { 0x7d, 0x7e, 0x0138 },
- { 0xff, 0xff, 0xffff }
-};
-#endif
-
-static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
+static const struct SiS_Ext2 SiS310_RefIndex[] =
+{
+ {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x0 */
+ {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1 */
+ {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2 */
+ {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3 */
+ {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4 */
+ {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x5 */
+ {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x6 */
+ {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x7 */
+ {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x8 */
+ {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x9 */
+ {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xa */
+ {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xb */
+ {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xc */
+ {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xd */
+ {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xe */
+ {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xf */
+ {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e, 0x00, 0x00, 0x00, 0x00}, /* 0x10 */
+ {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x11 */
+ {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x12 (6f was 03) */
+ {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x13 */
+ {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x14 */
+ {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x15 */
+ {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x16 */
+ {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x17 */
+ {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x18 */
+ {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x19 */
+ {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1a */
+ {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1b */
+ {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1c */
+ {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1d */
+ {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1e */
+ {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1f */
+ {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x20 */
+ {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x21 */
+ {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x22 */
+ {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x23 */
+ {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x24 */
+ {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x00}, /* 0x25 */
+ {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x26 */
+ {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x27 */
+ {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x28 */
+ {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x29 */
+ {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2a */
+ {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2b */
+ {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2c */
+ {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2d */
+ {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2e */
+ {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2f */
+ {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x30 */
+ {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x31 */
+ {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x32 */
+ {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x33 */
+ {0x2077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x32, 0x40, 0x5e, 0x73}, /* 0x34 */
+ {0x2047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x33, 0x07, 0xff, 0xff}, /* 0x35 */
+ {0x2047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x34, 0x0a, 0xff, 0xff}, /* 0x36 */
+ {0x2077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x35, 0x0b, 0x5f, 0x74}, /* 0x37 */
+ {0x2047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x36, 0x11, 0xff, 0xff}, /* 0x38 */
+ {0x2047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x37, 0x16, 0xff, 0xff}, /* 0x39 */
+ {0x3137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x38, 0x19, 0x60, 0x75}, /* 0x3a */
+ {0x3107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x39, 0x1e, 0xff, 0xff}, /* 0x3b */
+ {0x3307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x3a, 0x20, 0xff, 0xff}, /* 0x3c */
+ {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3d */
+ {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3e */
+ {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3f */ /* FSTN 320x240 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x58, 0x19, 0x42, 0x5b}, /* 0x40 */ /* 0x5b was 0x12 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x59, 0x1e, 0xff, 0xff}, /* 0x41 */
+ {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x5a, 0x20, 0xff, 0xff}, /* 0x42 */
+ {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x43 */
+ {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x44 1400x1050-75Hz */
+ {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x45 1152x864-60Hz */
+ {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x46 1152x864-75Hz */
+ {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x47 1152x864-85Hz */
+ {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x48 848x480-38Hzi */
+ {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x49 848x480-60Hz */
+ {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4a 856x480-38Hzi */
+ {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4b 856x480-60Hz */
+ {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4c 1360x768-60Hz */
+ {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4d 768x576-56Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5b, 0x19, 0x4f, 0x5c}, /* 0x4e 1280x800-60Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5c, 0x1e, 0xff, 0xff}, /* 0x4f 1280x800-75Hz */
+ {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5d, 0x20, 0xff, 0xff}, /* 0x50 1280x800-85Hz */
+ {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x51 1680x1050-60Hz */
+ {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x52 1920x1080 60Hzi */
+ {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x53 960x540 60Hz */
+ {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x54 960x600 60Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x62, 0x19, 0x61, 0x76}, /* 0x55 1280x854-60Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x63, 0x1e, 0xff, 0xff}, /* 0x56 1280x854-75Hz */
+ {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x64, 0x20, 0xff, 0xff}, /* 0x57 1280x854-85Hz */
+ {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiS310_CRT1Table[] =
{
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
- 0x00}}, /* 0x0 */
+ 0x00}}, /* 0x0 */
{{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
- 0x00}}, /* 0x1 */
+ 0x00}}, /* 0x1 */
{{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
- 0x01}}, /* 0x2 */
+ 0x01}}, /* 0x2 */
{{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
- 0x01}}, /* 0x3 */
+ 0x01}}, /* 0x3 */
{{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
- 0x00}}, /* 0x4 */
-#if 0
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}}, /* 0x5 */
-#endif
- {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */
+ 0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* corrected 640x480-60 */
0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
- 0x00}},
-#if 0
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e,
- 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
- 0x00}}, /* 0x6 */
-#endif
- {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */
+ 0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* corrected 640x480-72 */
0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
- 0x00}},
+ 0x00}}, /* 0x6 */
{{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
- 0x00}}, /* 0x7 */
+ 0x00}}, /* 0x7 */
{{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
- 0x00}}, /* 0x8 */
+ 0x00}}, /* 0x8 */
{{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, /* Corrected VBE */
- 0x61}}, /* 0x9 */
+ 0x61}}, /* 0x9 */
{{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
- 0x61}}, /* 0xa */
+ 0x61}}, /* 0xa */
{{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, /* Corrected VBE */
- 0x61}}, /* 0xb */
+ 0x61}}, /* 0xb */
{{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* Corrected VDE, VBE */
- 0x00}}, /* 0xc */
+ 0x00}}, /* 0xc */
{{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0xd */
+ 0x01}}, /* 0xd */
{{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
- 0x01}}, /* 0xe */
+ 0x01}}, /* 0xe */
{{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
- 0x01}}, /* 0xf */
+ 0x01}}, /* 0xf */
{{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
- 0x01}}, /* 0x10 */
+ 0x01}}, /* 0x10 */
{{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
- 0x01}}, /* 0x11 */
+ 0x01}}, /* 0x11 */
{{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
- 0x61}}, /* 0x12 */
+ 0x61}}, /* 0x12 */
{{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
- 0x61}}, /* 0x13 */
+ 0x61}}, /* 0x13 */
{{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
- 0x61}}, /* 0x14 */
+ 0x61}}, /* 0x14 */
{{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
- 0x00}}, /* 0x15 */
+ 0x00}}, /* 0x15 */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
- 0x01}}, /* 0x16 */
+ 0x01}}, /* 0x16 */
{{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
- 0x01}}, /* 0x17 */
+ 0x01}}, /* 0x17 */
{{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
- 0x01}}, /* 0x18 */
+ 0x01}}, /* 0x18 */
{{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
- 0x01}}, /* 0x19 */
+ 0x01}}, /* 0x19 */
{{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
- 0x62}}, /* 0x1a */
+ 0x62}}, /* 0x1a */
{{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
- 0x62}}, /* 0x1b */
+ 0x62}}, /* 0x1b */
{{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
- 0x00}}, /* 0x1c */
+ 0x00}}, /* 0x1c */
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
- 0x01}}, /* 0x1d */
+ 0x01}}, /* 0x1d */
{{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
- 0x01}}, /* 0x1e */
+ 0x01}}, /* 0x1e */
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
- 0x01}}, /* 0x1f */
+ 0x01}}, /* 0x1f */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x20 */
+ 0x00}}, /* 0x20 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x21 @ 4084 */
+ 0x00}}, /* 0x21 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x22 */
+ 0x00}}, /* 0x22 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x23 */
+ 0x00}}, /* 0x23 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x24 */
+ 0x00}}, /* 0x24 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x25 */
+ 0x00}}, /* 0x25 */
{{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
- 0x00}}, /* 0x26 */
+ 0x00}}, /* 0x26 */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x27 */
+ 0x00}}, /* 0x27 */
{{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
- 0x63}}, /* 0x28 */
+ 0x63}}, /* 0x28 */
{{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
- 0x63}}, /* 0x29 */
+ 0x63}}, /* 0x29 */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2a */
+ 0x00}}, /* 0x2a */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2b */
+ 0x00}}, /* 0x2b */
{{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
- 0x00}}, /* 0x2c */
+ 0x00}}, /* 0x2c */
{{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
- 0x44}}, /* 0x2d */
+ 0x44}}, /* 0x2d */
{{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
- 0x44}}, /* 0x2e */
+ 0x44}}, /* 0x2e */
{{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
- 0x44}}, /* 0x2f */
+ 0x44}}, /* 0x2f */
{{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
- 0x44}}, /* 0x30 */
+ 0x44}}, /* 0x30 */
{{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
- 0x00}}, /* 0x31 */
+ 0x00}}, /* 0x31 */
{{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
- 0x01}}, /* 0x32 */
+ 0x01}}, /* 0x32 */
{{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
- 0x01}}, /* 0x33 */
+ 0x01}}, /* 0x33 */
{{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
- 0x01}}, /* 0x34 */
+ 0x01}}, /* 0x34 */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
- 0x01}}, /* 0x35 */
+ 0x01}}, /* 0x35 */
{{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
- 0x01}}, /* 0x36 */
+ 0x01}}, /* 0x36 */
{{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */
0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
- 0x01}}, /* 0x37 */
+ 0x01}}, /* 0x37 */
{{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
- 0x01}}, /* 0x38 */
+ 0x01}}, /* 0x38 */
{{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
- 0x01}}, /* 0x39 */
+ 0x01}}, /* 0x39 */
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
- 0x01}}, /* 0x3a */
-#if 0
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 1280x960 - invalid */
- 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}}, /* 0x3b */
-#endif
+ 0x01}}, /* 0x3a */
{{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 1280x960-60 - corrected */
0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
- 0x01}}, /* 0x3b */
+ 0x01}}, /* 0x3b */
{{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
- 0x00}}, /* 0x3c */
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x3d */
+ 0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, /* 720x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x3d */
{{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
- 0x00}}, /* 0x3e */
+ 0x00}}, /* 0x3e */
{{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
- 0x00}}, /* 0x3f */
+ 0x00}}, /* 0x3f */
{{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
0x01}}, /* 0x40 */
@@ -578,11 +483,11 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
{{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
0x01}}, /* 0x4c */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
- 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
- 0x01}}, /* 0x4d */
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+ 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+ 0x41}}, /* 0x4d */
+ {{0x5f,0x27,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* FSTN 320x240 (working) */
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
0x00}}, /* 0x4e */
{{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
@@ -601,10 +506,58 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
0x01}}, /* 0x53 */
{{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
- 0x41}} /* 0x54 */
-};
-
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
+ 0x41}}, /* 0x54 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+ 0x40}}, /* 0x55 */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+ 0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+ 0x00}}, /* 0x56 */
+ {{0xd7,0xc7,0xc7,0x9b,0xd1,0x15,0xd1,0x10, /* 1600x1200 for LCDA */
+ 0xb2,0x86,0xaf,0xb0,0xd2,0x2f,0x00,0x03,
+ 0x00}}, /* 0x57 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 60 Hz */
+ 0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x58 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 75 Hz */
+ 0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+ 0x01}}, /* 0x59 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xdc, /* 1280x768 (1280x1024) 85 Hz */
+ 0x95,0x89,0xff,0x94,0x2f,0x21,0x00,0x07,
+ 0x01}}, /* 0x5a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x800 (1280x1024) 60 Hz */
+ 0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+ 0x01}}, /* 0x5b */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x800 (1280x1024) 75 Hz */
+ 0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+ 0x01}}, /* 0x5c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x800 (1280x1024) 85 Hz */
+ 0xa5,0x89,0x1f,0xa4,0x2f,0x01,0x00,0x07,
+ 0x01}}, /* 0x5d */
+ {{0x7f,0x63,0x63,0x83,0x6d,0x1d,0x0b,0x3e, /* 800x480 (wide) 60 Hz */
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x06,
+ 0x00}}, /* 0x5e */
+ {{0xa0,0x7f,0x7f,0x84,0x85,0x97,0x52,0xf0, /* 1024x576 (wide) 60 Hz */
+ 0x41,0x85,0x3f,0x40,0x53,0x00,0x00,0x02,
+ 0x01}}, /* 0x5f */
+ {{0xc9,0x9f,0x9f,0x8d,0xb0,0x15,0xec,0xf0, /* 1280x720 (wide) 60 Hz */
+ 0xd4,0x89,0xcf,0xd3,0xed,0x20,0x00,0x07,
+ 0x01}}, /* 0x60 */
+ {{0xcb,0x9f,0x9f,0x8f,0xa5,0x13,0x5b,0xff, /* 1280x854-60 wide */
+ 0x56,0x89,0x55,0x55,0x5c,0x30,0x00,0x07,
+ 0x01}}, /* 0x61 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x854 (1280x1024) 60 Hz */
+ 0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+ 0x41}}, /* 0x62 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x854 (1280x1024) 75 Hz */
+ 0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+ 0x41}}, /* 0x63 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x854 (1280x1024) 85 Hz */
+ 0xc0,0x84,0x55,0xbf,0x2f,0x01,0x00,0x07,
+ 0x41}} /* 0x64 */
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_315[] =
{
{ 0x3b,0x22,0x01,143},
{ 0x5c,0x23,0x01,166},
@@ -616,7 +569,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
{ 0x5c,0x23,0x01,166}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_650[] =
{
{ 0x5a,0x64,0x82, 66},
{ 0xb3,0x45,0x82, 83},
@@ -628,7 +581,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
{ 0x37,0x22,0x82,133}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_330[] =
{
{ 0x5c,0x23,0x01,166},
{ 0x5c,0x23,0x01,166},
@@ -640,7 +593,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
{ 0x79,0x06,0x01,250}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_660[] =
{
{ 0x5c,0x23,0x82,166},
{ 0x5c,0x23,0x82,166},
@@ -652,7 +605,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_760[] =
{
{ 0x37,0x22,0x82,133},
{ 0x5c,0x23,0x82,166},
@@ -664,7 +617,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_761[] =
{
{ 0x37,0x22,0x82,133}, /* Preliminary */
{ 0x5c,0x23,0x82,166},
@@ -676,7 +629,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
{ 0x37,0x21,0x82,200}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_340[] =
{
{ 0x79,0x06,0x01,250},
{ 0x7c,0x08,0x01,200},
@@ -688,9 +641,9 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
{ 0x29,0x01,0x81,300}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
+static const struct SiS_MCLKData SiS310_MCLKData_1[] = /* ECLK */
{
- { 0x29,0x21,0x82,150},
+ { 0x29,0x21,0x82,150},
{ 0x5c,0x23,0x82,166},
{ 0x65,0x23,0x82,183},
{ 0x37,0x21,0x82,200},
@@ -700,7 +653,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
{ 0x37,0x22,0x82,133}
};
-static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_1_340[] =
{
{ 0x7c,0x08,0x01,200},
{ 0x7c,0x08,0x01,200},
@@ -712,7 +665,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
{ 0x29,0x01,0x81,300}
};
-static SiS_VCLKDataStruct SiS310_VCLKData[]=
+static struct SiS_VCLKData SiS310_VCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -805,7 +758,7 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
- { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
{ 0x45,0x25, 83}, /* 0x5c 1280x800 */
{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
@@ -823,10 +776,19 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
{ 0x45,0x25, 83}, /* 0x6c 1280x800 */
- { 0x70,0x28, 90} /* 0x6d 1152x864@60 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35}, /* 0x71 768x576@60 */
+ { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+ { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+ { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+ { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+ { 0x75,0x13, 84} /* 0x76 1280x854 60Hz (wide) */
};
-static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static struct SiS_VBVCLKData SiS310_VBVCLKData[] =
{
{ 0x1b,0xe1, 25}, /* 0x00 */
{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -858,12 +820,6 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x5e,0x43,113}, /* 0x1b */
{ 0xbc,0x44,116}, /* 0x1c */
{ 0xe0,0x46,132}, /* 0x1d */
-#if 0
- { 0xd4,0x28,135}, /* 0x1e */
- { 0xea,0x2a,139}, /* 0x1f */
- { 0x41,0x22,157}, /* 0x20 */
- { 0x70,0x24,162}, /* 0x21 */
-#endif
{ 0xe2,0x46,135}, /* 0x1e */ /* 1280x1024-75, better clock for VGA2 */
{ 0xe5,0x46,139}, /* 0x1f */ /* 1024x768-120, better clock for VGA2 */
{ 0x15,0x01,157}, /* 0x20 */ /* 1280x1024-85, better clock for VGA2 */
@@ -912,7 +868,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x34,0x61, 95}, /* 0x4b UNUSED */
{ 0x78,0x27,108}, /* 0x4c UNUSED */
{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
- { 0x41,0x4e, 21}, /* 0x4e UNUSED */
+ { 0x41,0x4e, 21}, /* 0x4e */
{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
{ 0x19,0x42, 42}, /* 0x50 UNUSED */
{ 0x54,0x46, 58}, /* 0x51 UNUSED */
@@ -925,7 +881,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
- { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
+ { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
{ 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */
{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
@@ -943,57 +899,33 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
{ 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */
- { 0x70,0x28, 90} /* 0x6d 1152x864@60 */
+ { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+ { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+ { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+ { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+ { 0x2b,0xc2, 35}, /* 0x71 768@576@60 */
+ { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+ { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+ { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+ { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+ { 0x75,0x13, 84} /* 0x76 1280x854 60Hz (SiS LVDS) LCD */
};
-static const DRAM4Type SiS310_SR15[8] = {
- {0x00,0x04,0x60,0x60},
- {0x0f,0x0f,0x0f,0x0f},
- {0xba,0xba,0xba,0xba},
- {0xa9,0xa9,0xac,0xac},
- {0xa0,0xa0,0xa0,0xa8},
- {0x00,0x00,0x02,0x02},
- {0x30,0x30,0x40,0x40},
- {0x00,0xa5,0xfb,0xf6}
-};
-
-#ifdef LINUX_KERNEL
-
-static UCHAR SiS310_SR07 = 0x18;
-
-static const DRAM4Type SiS310_CR40[5] = {
- {0x77,0x77,0x33,0x33},
- {0x77,0x77,0x33,0x33},
- {0x00,0x00,0x00,0x00},
- {0x5b,0x5b,0x03,0x03},
- {0x00,0x00,0xf0,0xf8}
+static const unsigned char SiS310_SR15[4 * 8] =
+{
+ 0x00,0x04,0x60,0x60,
+ 0x0f,0x0f,0x0f,0x0f,
+ 0xba,0xba,0xba,0xba,
+ 0xa9,0xa9,0xac,0xac,
+ 0xa0,0xa0,0xa0,0xa8,
+ 0x00,0x00,0x02,0x02,
+ 0x30,0x30,0x40,0x40,
+ 0x00,0xa5,0xfb,0xf6
};
-static UCHAR SiS310_CR49[] = {0xaa,0x88};
-static UCHAR SiS310_SR1F = 0x00;
-static UCHAR SiS310_SR21 = 0xa5;
-static UCHAR SiS310_SR22 = 0xfb;
-static UCHAR SiS310_SR23 = 0xf6;
-static UCHAR SiS310_SR24 = 0x0d;
-static UCHAR SiS310_SR25[] = {0x33,0x3};
-static UCHAR SiS310_SR31 = 0x00;
-static UCHAR SiS310_SR32 = 0x11;
-static UCHAR SiS310_SR33 = 0x00;
-static UCHAR SiS310_CRT2Data_1_2 = 0x00;
-static UCHAR SiS310_CRT2Data_4_D = 0x00;
-static UCHAR SiS310_CRT2Data_4_E = 0x00;
-static UCHAR SiS310_CRT2Data_4_10 = 0x80;
-static const USHORT SiS310_RGBSenseData = 0xd1;
-static const USHORT SiS310_VideoSenseData = 0xb9;
-static const USHORT SiS310_YCSenseData = 0xb3;
-static const USHORT SiS310_RGBSenseData2 = 0x0190;
-static const USHORT SiS310_VideoSenseData2 = 0x0174;
-static const USHORT SiS310_YCSenseData2 = 0x016b;
-#endif
-
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTbl[] =
{
- {{0x10,0x40}},
+ {{0x10,0x40}},
{{0x10,0x40}},
{{0x10,0x40}},
{{0x10,0x40}},
@@ -1011,7 +943,7 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
{{0x10,0x40}}
};
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTblLVDS[] =
{
{{0x28,0xc8}},
{{0x28,0xc8}},
@@ -1035,18 +967,18 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const SiS_LCDDataStruct SiS310_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1024x768Data[] =
{
{ 62, 25, 800, 546,1344, 806},
{ 32, 15, 930, 546,1344, 806},
- { 62, 25, 800, 546,1344, 806},
+ { 62, 25, 800, 546,1344, 806},
{ 104, 45, 945, 496,1344, 806},
{ 62, 25, 800, 546,1344, 806},
{ 31, 18,1008, 624,1344, 806},
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1024x768Data[] =
{
{ 42, 25,1536, 419,1344, 806},
{ 48, 25,1536, 369,1344, 806},
@@ -1057,7 +989,7 @@ static const SiS_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
{ 1, 1,1344, 806,1344, 806}
};
-static const SiS_LCDDataStruct SiS310_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1280x1024Data[] =
{
{ 22, 5, 800, 510,1650,1088},
{ 22, 5, 800, 510,1650,1088},
@@ -1069,7 +1001,7 @@ static const SiS_LCDDataStruct SiS310_St2LCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -1081,45 +1013,22 @@ static const SiS_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
{ 1, 1,1688,1066,1688,1066}
};
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_1024x768_1[] =
{
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
};
-/* *** LCDA *** */
-
-#if 0
-static const SiS_LVDSDataStruct SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo, 651+301C */
- {1200, 450, 2048,1250},
- {1200, 400, 2048,1250},
- {1280, 450, 2048,1250},
- {1280, 400, 2048,1250},
- {1200, 530, 2048,1250},
- {1360, 650, 2048,1250},
- {1584, 818, 2048,1250},
- {1688,1066, 2048,1250},
- {1688,1066, 2048,1250},
-#if 0
- {2048,1250, 2048,1250} /* this should be correct */
-#endif
-#if 1
- {2160,1250, 2048,1250} /* ? */
-#endif
-};
-#endif
-
/**************************************************************/
/* LVDS, CHRONTEL ------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS310_CHTVUPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1130,7 +1039,7 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALData[]=
{1400,1000,1400,1000}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1138,10 +1047,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALData[]=
{1008, 625,1008, 625},
{ 840, 625, 840, 625},
{ 944, 625, 944, 625},
- {1400, 875,1400, 875}
+ {1400, 875,1400, 875}
};
-static const SiS_LVDSDataStruct SiS310_CHTVUPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALMData[] =
{
{ 840, 600, 840, 600},
{ 840, 600, 840, 600},
@@ -1149,10 +1058,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALMData[]=
{ 840, 600, 840, 600},
{ 784, 600, 784, 600},
{1064, 750,1064, 750},
- {1160, 945,1160, 945}
+ {1160, 945,1160, 945}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALMData[] =
{
{ 840, 525, 840, 525},
{ 840, 525, 840, 525},
@@ -1160,10 +1069,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALMData[]=
{ 840, 525, 840, 525},
{ 784, 525, 784, 525},
{1040, 700,1040, 700},
- {1160, 840,1160, 840}
+ {1160, 840,1160, 840}
};
-static const SiS_LVDSDataStruct SiS310_CHTVUPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALNData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1174,7 +1083,7 @@ static const SiS_LVDSDataStruct SiS310_CHTVUPALNData[]=
{1400,1000,1400,1000}
};
-static const SiS_LVDSDataStruct SiS310_CHTVOPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALNData[] =
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1182,10 +1091,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVOPALNData[]=
{1008, 625,1008, 625},
{ 840, 625, 840, 625},
{ 944, 625, 944, 625},
- {1400, 875,1400, 875}
+ {1400, 875,1400, 875}
};
-static const SiS_LVDSDataStruct SiS310_CHTVSOPALData[]= /* (super overscan - no effect on 7019) */
+static const struct SiS_LVDSData SiS310_CHTVSOPALData[] = /* (super overscan - no effect on 7019) */
{
{1008, 625,1008, 625},
{1008, 625,1008, 625},
@@ -1196,1333 +1105,10 @@ static const SiS_LVDSDataStruct SiS310_CHTVSOPALData[]= /* (super overscan -
{1400, 875,1400, 875}
};
-
-static const SiS_LVDSDesStruct SiS310_PanelType00_1[]= /* 800x600 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType01_1[]= /* 1024x768 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 805},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType02_1[]= /* 1280x1024 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 1065},
- { 0, 0},
- { 0, 0}
-};
-
-
-static const SiS_LVDSDesStruct SiS310_PanelType03_1[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType04_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType05_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType06_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType07_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType08_1[]= /* 1400x1050 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType09_1[]= /* 1280x768 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0a_1[]= /* 1600x1200 */
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0b_1[]= /* 640x480_2 */
-{
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 8, 524},
- { 0, 524}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0c_1[]= /* 640x480_3 */
-{
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 0, 524},
- { 8, 524},
- { 0, 524}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0d_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0e_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0f_1[]=
-{
- {1343, 798},
- {1343, 794},
- {1343, 798},
- {1343, 794},
- {1343, 0},
- {1343, 0},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType00_2[]=
-{
- {980, 528},
- {980, 503},
- {980, 528},
- {980, 503},
- {980, 568},
- { 0, 628},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType01_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 806},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType02_2[]=
-{
- {1368, 754},
- {1368, 729},
- {1368, 754},
- {1368, 729},
- {1368, 794},
- {1448, 854},
- {1560, 938},
- { 0,1066},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType03_2[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType04_2[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType05_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType06_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType07_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType08_2[]= /* 1400x1050 */
-{
- {1308, 741},
- {1308, 716},
- {1308, 741},
- {1308, 716},
- {1308, 781},
- {1388, 841},
- {1500, 925},
- {1628,1053},
- { 0,1065},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType09_2[]= /* 1280x768 */
-{
- {1083, 622},
- {1083, 597},
- {1083, 622},
- {1083, 597},
- {1083, 662},
- {1163, 722},
- {1286, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0a_2[]= /* 1600x1200 */
-{
- {1568, 920},
- {1568, 895},
- {1568, 920},
- {1568, 895},
- {1568, 960},
- {1648,1020},
- {1760,1104},
- {1888,1232},
- {1948,1245},
- { 0, 0}
-#if 0
- {1568, 850},
- {1568, 825},
- {1568, 850},
- {1568, 825},
- {1568, 890},
- {1648, 950},
- {1760,1034},
- {1888,1162},
- {1948,1175},
- { 0, 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0b_2[]= /* 640x480_2 */
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0c_2[]= /* 640x480_3 */
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0d_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0e_2[]=
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelType0f_2[] =
-{
- {1152, 622},
- {1152, 597},
- {1152, 622},
- {1152, 597},
- {1152, 662},
- {1232, 722},
- { 0, 805},
- { 0, 794},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelTypeNS_1[]=
-{
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 8, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 806},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS310_PanelTypeNS_2[] =
-{
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0},
- { 0 , 0}
-};
-
-/* CRT1 CRTC for SlaveModes and LCDA */
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] =
-{
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] =
-{
- {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
- 0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
- 0x00 }},
- {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0,
- 0x58,0x8d,0x57,0x73,0x20,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]=
-{
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
- 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
- 0x27,0x8c,0xdf,0x73,0x00,0x00,0x06,
- 0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
- 0x58,0x8d,0x57,0x73,0x20,0x00,0x06,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] =
-{
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
- 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba,
- 0x27,0x8c,0xdf,0x73,0x00,0x00,0x01,
- 0x00 }},
- {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0,
- 0x63,0x88,0x57,0x73,0x00,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] =
-{
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
- 0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
- 0x00}},
- {{0x87,0x63,0x8B,0x67,0x18,0x7c,0xf0,
- 0x5A,0x81,0x57,0x7D,0x00,0x00,0x06,
- 0x01}},
- {{0xA3,0x7f,0x87,0x83,0x94,0x24,0xf5,
- 0x02,0x89,0xFf,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] =
-{
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00 }},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
- 0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
- 0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x04,0x3e,
- 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
- 0x00}},
- {{0x55,0x31,0x99,0x35,0x06,0x7c,0xf0,
- 0x5A,0x81,0x57,0x7D,0x00,0x00,0x01,
- 0x01}},
- {{0x63,0x3F,0x87,0x43,0x94,0x24,0xf5,
- 0x02,0x89,0xFf,0x25,0x10,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
- 0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
- 0x01 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x7f,0x86,0xdf,0x25,0x10,0x00,0x06,
- 0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xbb,0x82,0x57,0x25,0x10,0x00,0x02,
- 0x01 }},
- {{0xa3,0x7f,0x87,0x83,0x94,0x24,0xf5,
- 0x02,0x89,0xff,0x25,0x10,0x00,0x02,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] =
-{
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
- 0x7f,0x86,0xdf,0x25,0x10,0x00,0x01,
- 0x00 }},
- {{0x71,0x31,0x95,0x46,0x97,0x24,0xf1,
- 0xbb,0x82,0x57,0x25,0x10,0x00,0x01,
- 0x01 }},
- {{0x63,0x3f,0x87,0x46,0x97,0x24,0xf5,
- 0x0f,0x86,0xff,0x25,0x30,0x00,0x01,
- 0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] =
-{
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
- 0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x08,0x3e,
- 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06,
- 0x00}},
- {{0x92,0x63,0x96,0x6c,0x18,0x80,0xf0,
- 0x58,0x8c,0x57,0x81,0x20,0x00,0x06,
- 0x01}},
- {{0xae,0x7f,0x92,0x88,0x94,0x28,0xf5,
- 0x00,0x84,0xff,0x29,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] =
-{
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
- 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
- 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
- 0x01}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x08,0x3e,
- 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05,
- 0x00}},
- {{0x60,0x31,0x84,0x3a,0x86,0x80,0xf0,
- 0x58,0x8c,0x57,0x81,0x20,0x00,0x01,
- 0x01}},
- {{0x6e,0x3f,0x92,0x48,0x94,0x28,0xf5,
- 0x00,0x84,0xff,0x29,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] =
-{
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
- 0xf0,0x84,0x85,0x84,0x11,0x00,0x02,
- 0x01}},
- {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xaf,0x83,0x44,0x43,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xfa,0x83,0x44,0x43,0x31,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
- 0xf0,0x84,0x85,0x84,0x11,0x00,0x06,
- 0x01}},
- {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x59,0x07,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] =
-{
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x5e,0x81,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
- 0xdf,0x82,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
- 0x57,0x8e,0x57,0x67,0x20,0x00,0x06,
- 0x01}},
- {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf1,
- 0xff,0x86,0xff,0x0f,0x10,0x00,0x02,
- 0x01,}},
- {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0xde,
- 0xff,0x86,0xff,0x0f,0x01,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
- 0x19,0x80,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#if 0
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x06,
- 0x01}},
- {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x02,
- 0x01}},
- {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
- 0x1a,0x80,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] =
-{
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xdf,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x57,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf1,
- 0xff,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
- 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
- 0x00}}
-#if 0
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
- 0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
- 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] =
-{
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
- 0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
- 0xff,0x83,0x85,0x84,0x11,0x00,0x02,
- 0x01}},
- {{0xce,0x63,0x92,0x8e,0x1c,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x7f,0x92,0x9c,0x0a,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xac,0x1a,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x07,
- 0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#if 0
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
- 0x01}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
- 0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
- 0x03,0x87,0xdf,0x29,0x01,0x00,0x03,
- 0x00}},
- {{0xce,0x63,0x92,0x96,0x04,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x07,
- 0x01}},
- {{0xce,0x7f,0x92,0xa4,0x12,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xb4,0x02,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x03,
- 0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
- 0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
- 0xff,0x83,0x85,0x84,0x11,0x00,0x06,
- 0x01}},
- {{0x9c,0x31,0x80,0x5c,0x8a,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x5c,0x0a,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}},
- {{0x7e,0x4f,0x82,0x5c,0x0a,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x06,
- 0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
- 0x00}}
-#if 0
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
- 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9e,
- 0x03,0x87,0xdf,0x29,0x01,0x00,0x06,
- 0x00}},
- {{0x9c,0x31,0x80,0x64,0x92,0x28,0xd4,
- 0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
- 0x01}},
- {{0x8e,0x3f,0x92,0x64,0x12,0x28,0xd4,
- 0x93,0x87,0xff,0x29,0x21,0x00,0x06,
- 0x01}},
- {{0x7e,0x4f,0x82,0x64,0x12,0x28,0x5a,
- 0x13,0x87,0xff,0x29,0x29,0x00,0x06,
- 0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
- 0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] =
-{
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x56,0xBA,
- 0x03,0x86,0xDF,0x57,0x00,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xCE,0xF0,
- 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x02,
- 0x01}},
- {{0xB3,0x7F,0x97,0x8B,0x83,0x76,0xF5,
- 0x23,0x86,0xFF,0x77,0x10,0x00,0x06,
- 0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
- 0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
- 0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
- 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
- 0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
- 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
- 0x00}}
-#if 0
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
- 0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x10,0x3e,
- 0xe0,0x84,0xdf,0x11,0x00,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0x88,0xf0,
- 0x58,0x8c,0x57,0x89,0x20,0x00,0x06,
- 0x01}},
- {{0xb3,0x7f,0x97,0x81,0x99,0x30,0xf5,
- 0x00,0x84,0xff,0x31,0x10,0x00,0x02,
- 0x01}},
- {{0xd3,0x9f,0x97,0xa1,0x19,0x30,0x5a,
- 0x00,0x84,0xff,0x31,0x09,0x00,0x07,
- 0x01}},
- {{0xe2,0xae,0x86,0xb0,0x88,0x4a,0x10,
- 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x03,
- 0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x81,0xe0,0x10,
- 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x07,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] =
-{
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
- 0x00}},
- {{0x5B,0x27,0x9F,0x29,0x01,0x8E,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
- 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
- 0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
- 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
- 0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x56,0xBA,
- 0x03,0x86,0xDF,0x57,0x00,0x00,0x01,
- 0x00}},
- {{0x65,0x31,0x89,0x3D,0x95,0xCE,0xF0,
- 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x01,
- 0x01}},
- {{0x73,0x3F,0x97,0x4B,0x83,0x76,0xF5,
- 0x23,0x86,0xFF,0x77,0x10,0x00,0x05,
- 0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
- 0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
- 0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
- 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
- 0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xE0,0x10,
- 0xB0,0x84,0xAF,0xE1,0x2F,0x00,0x06,
- 0x00}}
-#if 0
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
- 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
- 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x10,0x3e,
- 0xe0,0x84,0xdf,0x11,0x00,0x00,0x01,
- 0x00}},
- {{0x65,0x31,0x89,0x33,0x8b,0x88,0xf0,
- 0x58,0x8c,0x57,0x89,0x20,0x00,0x01,
- 0x01}},
- {{0x73,0x3f,0x97,0x41,0x99,0x30,0xf5,
- 0x00,0x84,0xff,0x31,0x10,0x00,0x01,
- 0x01}},
- {{0x83,0x4f,0x87,0x51,0x09,0x30,0x5a,
- 0x00,0x84,0xff,0x31,0x09,0x00,0x06,
- 0x01}},
- {{0x8a,0x56,0x8e,0x58,0x10,0x4a,0x10,
- 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0xe0,0x10,
- 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x06,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] =
-{
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
- 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
- 0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x9F,
- 0x6B,0x8E,0x03,0x02,0x01,0x00,0x07,
- 0x01}},
- {{0xFB,0x63,0x9F,0xA1,0x99,0x26,0xD5,
- 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x07,
- 0x01}},
- {{0xFB,0x7F,0x9F,0xAF,0x87,0x26,0xDD,
- 0xFB,0x8E,0x13,0x12,0x31,0x00,0x03,
- 0x01}},
- {{0xFB,0x9F,0x9F,0xBF,0x97,0x26,0x5B,
- 0x7B,0x8E,0xFF,0x27,0x39,0x00,0x03,
- 0x01}},
- {{0xFB,0xAE,0x9F,0xC6,0x9E,0x26,0x11,
- 0x88,0x8B,0x19,0x27,0x1F,0x00,0x03,
- 0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
- 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
- 0x00}}
-#if 0
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
- 0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
- 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x07,
- 0x01}},
- {{0xfb,0x63,0x9f,0x9a,0x92,0xe0,0xd4,
- 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x07,
- 0x01}},
- {{0xfb,0x7f,0x9f,0xa8,0x80,0xe0,0xd4,
- 0xef,0x83,0xff,0xe1,0x21,0x00,0x03,
- 0x01}},
- {{0xfb,0x9f,0x9f,0xb8,0x90,0xe0,0x5a,
- 0x6f,0x83,0xff,0xe1,0x29,0x00,0x03,
- 0x01}},
- {{0xfb,0xae,0x9f,0xbf,0x97,0xe0,0x10,
- 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x03,
- 0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x84,0xe0,0x10,
- 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x07,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] =
-{
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
- 0x01}},
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
- 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x07,0x8B,0xA0,0x9F,0x01,0x00,0x02,
- 0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
- 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
- 0x01}},
- {{0xC9,0x31,0x8D,0x6F,0x07,0x26,0xD5,
- 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x03,
- 0x01}},
- {{0xBB,0x3F,0x9F,0x6F,0x87,0x26,0xDD,
- 0xFB,0x8E,0x13,0x12,0x31,0x00,0x02,
- 0x01}},
- {{0xAB,0x4F,0x8F,0x68,0x80,0xE0,0x5A,
- 0x6F,0x83,0xFF,0xE1,0x29,0x00,0x02,
- 0x01}},
- {{0xA3,0x56,0x87,0x67,0x9F,0xE0,0x10,
- 0x7C,0x80,0x19,0xE1,0x0F,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9B,0x68,0x00,0xE0,0x10,
- 0xC7,0x8B,0xAF,0xE1,0x0F,0x00,0x02,
- 0x00}}
-#if 0
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
- 0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
- 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x02,
- 0x01}},
- {{0xc9,0x31,0x8d,0x68,0x00,0xe0,0xd4,
- 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x03,
- 0x01}},
- {{0xbb,0x3f,0x9f,0x68,0x80,0xe0,0xd4,
- 0xef,0x83,0xff,0xe1,0x21,0x00,0x02,
- 0x01}},
- {{0xab,0x4f,0x8f,0x68,0x80,0xe0,0x5a,
- 0x6f,0x83,0xff,0xe1,0x29,0x00,0x02,
- 0x01}},
- {{0xa3,0x56,0x87,0x67,0x9f,0xe0,0x10,
- 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x06,
- 0x00}},
- {{0x97,0x63,0x9b,0x68,0x00,0xe0,0x10,
- 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x02,
- 0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
- 0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
- 0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
- 0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-
/* CRT1 CRTC for Chrontel TV slave modes */
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] =
-{
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UNTSC[] =
+{
{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
0x00 }},
@@ -2546,7 +1132,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] =
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1ONTSC[] =
{
{{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -2571,8 +1157,8 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] =
0x01 }}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] =
-{
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UPAL[] =
+{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
0x00 }},
@@ -2596,7 +1182,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] =
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1OPAL[] =
{
{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2621,8 +1207,7 @@ static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] =
0x01 }}
};
-
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UNTSC[] =
{
{{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2642,7 +1227,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
for PAL-M and PAL-N all above is corrected.
*/
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_ONTSC[] =
{
{{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2653,7 +1238,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
{{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPAL[] =
{
{{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2664,7 +1249,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
{{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPAL[] =
{
{{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2675,7 +1260,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
{{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALM[] =
{
{{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2691,7 +1276,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALM[] =
{
{{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
{{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2707,7 +1292,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALN[] =
{
{{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
{{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2723,7 +1308,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
#endif
};
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALN[] =
{
{{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
{{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2739,16 +1324,16 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
#endif
};
-static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKONTSC[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUNTSC[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKONTSC[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-static const UCHAR SiS310_CHTVVCLKUPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPAL[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPAL[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
-static const UCHAR SiS310_CHTVVCLKUPALM[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKOPALM[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUPALM[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKOPALM[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-static const UCHAR SiS310_CHTVVCLKUPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile
index aaed8c2b4a64..f7c0046e5b1d 100644
--- a/drivers/video/sis/Makefile
+++ b/drivers/video/sis/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_FB_SIS) += sisfb.o
-sisfb-objs := sis_main.o sis_accel.o init.o init301.o
+sisfb-objs := sis_main.o sis_accel.o init.o init301.o initextlfb.o
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index ecfd72178dbb..2ab3868efde3 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -2,11 +2,12 @@
/* $XdotOrg$ */
/*
* Mode initializing code (CRT1 section) for
- * for SiS 300/305/540/630/730 and
- * SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ * for SiS 300/305/540/630/730,
+ * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI Volari V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -53,17 +54,12 @@
*
* Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
* Used by permission.
- *
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if they are marked TW or not.
- *
*/
-
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "init.h"
#ifdef SIS300
@@ -84,24 +80,13 @@
#if defined(SIS300) || defined(SIS315H)
static void
-InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitCommonPointer(struct SiS_Private *SiS_Pr)
{
+ SiS_Pr->SiS_SModeIDTable = SiS_SModeIDTable;
SiS_Pr->SiS_StResInfo = SiS_StResInfo;
SiS_Pr->SiS_ModeResInfo = SiS_ModeResInfo;
SiS_Pr->SiS_StandTable = SiS_StandTable;
- SiS_Pr->SiS_NTSCPhase = SiS_NTSCPhase;
- SiS_Pr->SiS_PALPhase = SiS_PALPhase;
- SiS_Pr->SiS_NTSCPhase2 = SiS_NTSCPhase2;
- SiS_Pr->SiS_PALPhase2 = SiS_PALPhase2;
- SiS_Pr->SiS_PALMPhase = SiS_PALMPhase;
- SiS_Pr->SiS_PALNPhase = SiS_PALNPhase;
- SiS_Pr->SiS_PALMPhase2 = SiS_PALMPhase2;
- SiS_Pr->SiS_PALNPhase2 = SiS_PALNPhase2;
- SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase;
- SiS_Pr->SiS_SpecialPhaseM = SiS_SpecialPhaseM;
- SiS_Pr->SiS_SpecialPhaseJ = SiS_SpecialPhaseJ;
-
SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming;
SiS_Pr->SiS_PALTiming = SiS_PALTiming;
SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing;
@@ -137,6 +122,7 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
SiS_Pr->SiS_LCD1280x800Data = SiS_LCD1280x800Data;
SiS_Pr->SiS_LCD1280x800_2Data = SiS_LCD1280x800_2Data;
+ SiS_Pr->SiS_LCD1280x854Data = SiS_LCD1280x854Data;
SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data;
SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data;
SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data;
@@ -145,67 +131,30 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data;
SiS_Pr->SiS_NoScaleData = SiS_NoScaleData;
- SiS_Pr->SiS_LVDS320x480Data_1 = SiS_LVDS320x480Data_1;
+ SiS_Pr->SiS_LVDS320x240Data_1 = SiS_LVDS320x240Data_1;
+ SiS_Pr->SiS_LVDS320x240Data_2 = SiS_LVDS320x240Data_2;
+ SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1;
- SiS_Pr->SiS_LVDS800x600Data_2 = SiS_LVDS800x600Data_2;
- SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
- SiS_Pr->SiS_LVDS1024x768Data_2 = SiS_LVDS1024x768Data_2;
- SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1;
- SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2;
- SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1;
- SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2;
- SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1;
- SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2;
- SiS_Pr->SiS_LVDS1280x768Data_1 = SiS_LVDS1280x768Data_1;
- SiS_Pr->SiS_LVDS1280x768Data_2 = SiS_LVDS1280x768Data_2;
SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1;
- SiS_Pr->SiS_LVDS1024x600Data_2 = SiS_LVDS1024x600Data_2;
- SiS_Pr->SiS_LVDS1152x768Data_1 = SiS_LVDS1152x768Data_1;
- SiS_Pr->SiS_LVDS1152x768Data_2 = SiS_LVDS1152x768Data_2;
- SiS_Pr->SiS_LVDSXXXxXXXData_1 = SiS_LVDSXXXxXXXData_1;
- SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x960Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x960Data_2;
- SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x1024Data_1;
- SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x1024Data_2;
- SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
- SiS_Pr->SiS_LVDS640x480Data_2 = SiS_LVDS640x480Data_2;
-
- SiS_Pr->SiS_LVDS848x480Data_1 = SiS_LVDS848x480Data_1;
- SiS_Pr->SiS_LVDS848x480Data_2 = SiS_LVDS848x480Data_2;
- SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
- SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
- SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
- SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
+ SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
- SiS_Pr->SiS_LVDSCRT11280x768_1 = SiS_LVDSCRT11280x768_1;
+ SiS_Pr->SiS_LVDSCRT1320x240_1 = SiS_LVDSCRT1320x240_1;
+ SiS_Pr->SiS_LVDSCRT1320x240_2 = SiS_LVDSCRT1320x240_2;
+ SiS_Pr->SiS_LVDSCRT1320x240_2_H = SiS_LVDSCRT1320x240_2_H;
+ SiS_Pr->SiS_LVDSCRT1320x240_3 = SiS_LVDSCRT1320x240_3;
+ SiS_Pr->SiS_LVDSCRT1320x240_3_H = SiS_LVDSCRT1320x240_3_H;
+ SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
+ SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
+#if 0
SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1;
- SiS_Pr->SiS_LVDSCRT11152x768_1 = SiS_LVDSCRT11152x768_1;
- SiS_Pr->SiS_LVDSCRT11280x768_1_H = SiS_LVDSCRT11280x768_1_H;
SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H;
- SiS_Pr->SiS_LVDSCRT11152x768_1_H = SiS_LVDSCRT11152x768_1_H;
- SiS_Pr->SiS_LVDSCRT11280x768_2 = SiS_LVDSCRT11280x768_2;
SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2;
- SiS_Pr->SiS_LVDSCRT11152x768_2 = SiS_LVDSCRT11152x768_2;
- SiS_Pr->SiS_LVDSCRT11280x768_2_H = SiS_LVDSCRT11280x768_2_H;
SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H;
- SiS_Pr->SiS_LVDSCRT11152x768_2_H = SiS_LVDSCRT11152x768_2_H;
- SiS_Pr->SiS_LVDSCRT1320x480_1 = SiS_LVDSCRT1320x480_1;
- SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
- SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
- SiS_Pr->SiS_LVDSCRT1640x480_2 = SiS_LVDSCRT1640x480_2;
- SiS_Pr->SiS_LVDSCRT1640x480_2_H = SiS_LVDSCRT1640x480_2_H;
- SiS_Pr->SiS_LVDSCRT1640x480_3 = SiS_LVDSCRT1640x480_3;
- SiS_Pr->SiS_LVDSCRT1640x480_3_H = SiS_LVDSCRT1640x480_3_H;
+#endif
SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
- SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
- SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
- SiS_Pr->SiS_CHTVUPALDesData = SiS_CHTVUPALDesData;
- SiS_Pr->SiS_CHTVOPALDesData = SiS_CHTVOPALDesData;
-
SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* lowest value LVDS/LCDA */
SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */
}
@@ -213,50 +162,24 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS300
static void
-InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo300Pointer(struct SiS_Private *SiS_Pr)
{
- InitCommonPointer(SiS_Pr, HwInfo);
+ InitCommonPointer(SiS_Pr);
- SiS_Pr->SiS_SModeIDTable = SiS300_SModeIDTable;
SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
SiS_Pr->SiS_EModeIDTable = SiS300_EModeIDTable;
SiS_Pr->SiS_RefIndex = SiS300_RefIndex;
SiS_Pr->SiS_CRT1Table = SiS300_CRT1Table;
- if(HwInfo->jChipType == SIS_300) {
- SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
+ if(SiS_Pr->ChipType == SIS_300) {
+ SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
} else {
- SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
+ SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
}
SiS_Pr->SiS_VCLKData = SiS300_VCLKData;
- SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
+ SiS_Pr->SiS_VBVCLKData = (struct SiS_VBVCLKData *)SiS300_VCLKData;
SiS_Pr->SiS_SR15 = SiS300_SR15;
-#ifdef LINUX_KERNEL
- SiS_Pr->pSiS_SR07 = &SiS300_SR07;
- SiS_Pr->SiS_CR40 = SiS300_CR40;
- SiS_Pr->SiS_CR49 = SiS300_CR49;
- SiS_Pr->pSiS_SR1F = &SiS300_SR1F;
- SiS_Pr->pSiS_SR21 = &SiS300_SR21;
- SiS_Pr->pSiS_SR22 = &SiS300_SR22;
- SiS_Pr->pSiS_SR23 = &SiS300_SR23;
- SiS_Pr->pSiS_SR24 = &SiS300_SR24;
- SiS_Pr->SiS_SR25 = SiS300_SR25;
- SiS_Pr->pSiS_SR31 = &SiS300_SR31;
- SiS_Pr->pSiS_SR32 = &SiS300_SR32;
- SiS_Pr->pSiS_SR33 = &SiS300_SR33;
- SiS_Pr->pSiS_CRT2Data_1_2 = &SiS300_CRT2Data_1_2;
- SiS_Pr->pSiS_CRT2Data_4_D = &SiS300_CRT2Data_4_D;
- SiS_Pr->pSiS_CRT2Data_4_E = &SiS300_CRT2Data_4_E;
- SiS_Pr->pSiS_CRT2Data_4_10 = &SiS300_CRT2Data_4_10;
- SiS_Pr->pSiS_RGBSenseData = &SiS300_RGBSenseData;
- SiS_Pr->pSiS_VideoSenseData = &SiS300_VideoSenseData;
- SiS_Pr->pSiS_YCSenseData = &SiS300_YCSenseData;
- SiS_Pr->pSiS_RGBSenseData2 = &SiS300_RGBSenseData2;
- SiS_Pr->pSiS_VideoSenseData2 = &SiS300_VideoSenseData2;
- SiS_Pr->pSiS_YCSenseData2 = &SiS300_YCSenseData2;
-#endif
-
SiS_Pr->SiS_PanelDelayTbl = SiS300_PanelDelayTbl;
SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
@@ -266,11 +189,8 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_St2LCD1280x1024Data = SiS300_St2LCD1280x1024Data;
SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS300_CRT2Part2_1024x768_1;
- SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
SiS_Pr->SiS_CRT2Part2_1024x768_2 = SiS300_CRT2Part2_1024x768_2;
- SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
SiS_Pr->SiS_CRT2Part2_1024x768_3 = SiS300_CRT2Part2_1024x768_3;
- SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
SiS_Pr->SiS_CHTVUPALData = SiS300_CHTVUPALData;
SiS_Pr->SiS_CHTVOPALData = SiS300_CHTVOPALData;
@@ -280,64 +200,16 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData; /* not supported on 300 series */
SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
- SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
- SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
- SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
- SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
- SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
- SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
- SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
- SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
- SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
- SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
- SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
- SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
- SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
- SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
- SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
- SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
- SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
- SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
- SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
- SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
- SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
- SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
- SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
- SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
- SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
- SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
- SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
- SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
- SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
- SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
- SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
- SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
-
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
- }
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
- SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
- SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
- }
-
- SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS300_LVDSCRT1800x600_1;
- SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS300_LVDSCRT1800x600_1_H;
- SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS300_LVDSCRT1800x600_2;
- SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS300_LVDSCRT1800x600_2_H;
- SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS300_LVDSCRT11024x768_1;
- SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS300_LVDSCRT11024x768_1_H;
- SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS300_LVDSCRT11024x768_2;
- SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS300_LVDSCRT11024x768_2_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS300_LVDSCRT11280x1024_1;
- SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS300_LVDSCRT11280x1024_2;
- SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS300_LVDSCRT1XXXxXXX_1;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS300_LVDSCRT1XXXxXXX_1_H;
+ SiS_Pr->SiS_LVDS848x480Data_1 = SiS300_LVDS848x480Data_1;
+ SiS_Pr->SiS_LVDS848x480Data_2 = SiS300_LVDS848x480Data_2;
+ SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
+ SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
+ SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
+
+ SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
+ SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
+ SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
+ SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
@@ -367,64 +239,38 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H
static void
-InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo310Pointer(struct SiS_Private *SiS_Pr)
{
- InitCommonPointer(SiS_Pr, HwInfo);
+ InitCommonPointer(SiS_Pr);
- SiS_Pr->SiS_SModeIDTable = SiS310_SModeIDTable;
SiS_Pr->SiS_EModeIDTable = SiS310_EModeIDTable;
- SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex;
+ SiS_Pr->SiS_RefIndex = SiS310_RefIndex;
SiS_Pr->SiS_CRT1Table = SiS310_CRT1Table;
- if(HwInfo->jChipType >= SIS_340) {
- SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 */
- } else if(HwInfo->jChipType >= SIS_761) {
+ if(SiS_Pr->ChipType >= SIS_340) {
+ SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 + XGI */
+ } else if(SiS_Pr->ChipType >= SIS_761) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761; /* 761 - preliminary */
- } else if(HwInfo->jChipType >= SIS_760) {
+ } else if(SiS_Pr->ChipType >= SIS_760) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760; /* 760 */
- } else if(HwInfo->jChipType >= SIS_661) {
+ } else if(SiS_Pr->ChipType >= SIS_661) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660; /* 661/741 */
- } else if(HwInfo->jChipType == SIS_330) {
+ } else if(SiS_Pr->ChipType == SIS_330) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330; /* 330 */
- } else if(HwInfo->jChipType > SIS_315PRO) {
+ } else if(SiS_Pr->ChipType > SIS_315PRO) {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650; /* 550, 650, 740 */
} else {
SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315; /* 315 */
}
- if(HwInfo->jChipType >= SIS_340) {
- SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
+ if(SiS_Pr->ChipType >= SIS_340) {
+ SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
} else {
- SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
+ SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
}
SiS_Pr->SiS_VCLKData = SiS310_VCLKData;
SiS_Pr->SiS_VBVCLKData = SiS310_VBVCLKData;
SiS_Pr->SiS_SR15 = SiS310_SR15;
-#ifdef LINUX_KERNEL
- SiS_Pr->pSiS_SR07 = &SiS310_SR07;
- SiS_Pr->SiS_CR40 = SiS310_CR40;
- SiS_Pr->SiS_CR49 = SiS310_CR49;
- SiS_Pr->pSiS_SR1F = &SiS310_SR1F;
- SiS_Pr->pSiS_SR21 = &SiS310_SR21;
- SiS_Pr->pSiS_SR22 = &SiS310_SR22;
- SiS_Pr->pSiS_SR23 = &SiS310_SR23;
- SiS_Pr->pSiS_SR24 = &SiS310_SR24;
- SiS_Pr->SiS_SR25 = SiS310_SR25;
- SiS_Pr->pSiS_SR31 = &SiS310_SR31;
- SiS_Pr->pSiS_SR32 = &SiS310_SR32;
- SiS_Pr->pSiS_SR33 = &SiS310_SR33;
- SiS_Pr->pSiS_CRT2Data_1_2 = &SiS310_CRT2Data_1_2;
- SiS_Pr->pSiS_CRT2Data_4_D = &SiS310_CRT2Data_4_D;
- SiS_Pr->pSiS_CRT2Data_4_E = &SiS310_CRT2Data_4_E;
- SiS_Pr->pSiS_CRT2Data_4_10 = &SiS310_CRT2Data_4_10;
- SiS_Pr->pSiS_RGBSenseData = &SiS310_RGBSenseData;
- SiS_Pr->pSiS_VideoSenseData = &SiS310_VideoSenseData;
- SiS_Pr->pSiS_YCSenseData = &SiS310_YCSenseData;
- SiS_Pr->pSiS_RGBSenseData2 = &SiS310_RGBSenseData2;
- SiS_Pr->pSiS_VideoSenseData2 = &SiS310_VideoSenseData2;
- SiS_Pr->pSiS_YCSenseData2 = &SiS310_YCSenseData2;
-#endif
-
SiS_Pr->SiS_PanelDelayTbl = SiS310_PanelDelayTbl;
SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
@@ -435,41 +281,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS310_CRT2Part2_1024x768_1;
- SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
- SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
- SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
- SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
- SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
- SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
- SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
- SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
- SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
- SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
- SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
- SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
- SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
- SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
- SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
- SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
- SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
- SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
- SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
- SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
- SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
- SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
- SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
- SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
- SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
- SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
- SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
- SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
- SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
- SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
- SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
- SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
- SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
- SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
-
SiS_Pr->SiS_CHTVUPALData = SiS310_CHTVUPALData;
SiS_Pr->SiS_CHTVOPALData = SiS310_CHTVOPALData;
SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
@@ -478,33 +289,11 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
- SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS310_LVDSCRT1800x600_1;
- SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS310_LVDSCRT11024x768_1;
- SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS310_LVDSCRT11280x1024_1;
- SiS_Pr->SiS_LVDSCRT11400x1050_1 = SiS310_LVDSCRT11400x1050_1;
- SiS_Pr->SiS_LVDSCRT11600x1200_1 = SiS310_LVDSCRT11600x1200_1;
- SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS310_LVDSCRT1800x600_1_H;
- SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS310_LVDSCRT11024x768_1_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
- SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
- SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
- SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS310_LVDSCRT1800x600_2;
- SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS310_LVDSCRT11024x768_2;
- SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS310_LVDSCRT11280x1024_2;
- SiS_Pr->SiS_LVDSCRT11400x1050_2 = SiS310_LVDSCRT11400x1050_2;
- SiS_Pr->SiS_LVDSCRT11600x1200_2 = SiS310_LVDSCRT11600x1200_2;
- SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS310_LVDSCRT1800x600_2_H;
- SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS310_LVDSCRT11024x768_2_H;
- SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
- SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
- SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS310_LVDSCRT1XXXxXXX_1;
- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS310_LVDSCRT1XXXxXXX_1_H;
- SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
- SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
- SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL;
- SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL;
- SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
+ SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
+ SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
+ SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL;
+ SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL;
+ SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
@@ -528,208 +317,203 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
#endif
-static void
-SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+BOOLEAN
+SiSInitPtr(struct SiS_Private *SiS_Pr)
{
- switch(HwInfo->jChipType) {
-#ifdef SIS315H
- case SIS_315H:
- case SIS_315:
- case SIS_315PRO:
- case SIS_550:
- case SIS_650:
- case SIS_740:
- case SIS_330:
- case SIS_661:
- case SIS_741:
- case SIS_660:
- case SIS_760:
- case SIS_761:
- case SIS_340:
- InitTo310Pointer(SiS_Pr, HwInfo);
- break;
-#endif
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- case SIS_300:
- case SIS_540:
- case SIS_630:
- case SIS_730:
- InitTo300Pointer(SiS_Pr, HwInfo);
- break;
+ InitTo300Pointer(SiS_Pr);
+#else
+ return FALSE;
+#endif
+ } else {
+#ifdef SIS315H
+ InitTo310Pointer(SiS_Pr);
+#else
+ return FALSE;
#endif
- default:
- break;
}
+ return TRUE;
}
/*********************************************/
/* HELPER: Get ModeID */
/*********************************************/
-#ifdef LINUX_XF86
-USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
switch(HDisplay)
{
- case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) {
- if(FSTN) ModeIndex = ModeIndex_320x240_FSTN[Depth];
- else ModeIndex = ModeIndex_320x240[Depth];
- }
- break;
- case 400:
- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- }
- break;
- case 512:
- if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
- }
- break;
- case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
- else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
- break;
- case 720:
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
- break;
- case 768:
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
- break;
- case 800:
- if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
- else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
- break;
- case 848:
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
- break;
- case 856:
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
- break;
- case 960:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
- else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
- }
- break;
- case 1024:
- if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
- else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
- else if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
- }
- break;
- case 1152:
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
- if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
- }
- break;
- case 1280:
- switch(VDisplay) {
- case 720:
- ModeIndex = ModeIndex_1280x720[Depth];
- break;
- case 768:
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_1280x768[Depth];
- } else {
- ModeIndex = ModeIndex_310_1280x768[Depth];
- }
- break;
- case 800:
- if(VGAEngine == SIS_315_VGA) {
- ModeIndex = ModeIndex_1280x800[Depth];
- }
- break;
- case 960:
- ModeIndex = ModeIndex_1280x960[Depth];
- break;
- case 1024:
- ModeIndex = ModeIndex_1280x1024[Depth];
- break;
- }
- break;
- case 1360:
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
- if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
- }
- break;
- case 1400:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) {
- ModeIndex = ModeIndex_1400x1050[Depth];
- }
- }
- break;
- case 1600:
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
- break;
- case 1680:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
- }
- break;
- case 1920:
- if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
- else if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
- }
- break;
- case 2048:
- if(VDisplay == 1536) {
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_2048x1536[Depth];
- } else {
- ModeIndex = ModeIndex_310_2048x1536[Depth];
- }
- }
- break;
+ case 320:
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ else if(VDisplay == 240) {
+ if((VBFlags & CRT2_LCD) && (FSTN))
+ ModeIndex = ModeIndex_320x240_FSTN[Depth];
+ else
+ ModeIndex = ModeIndex_320x240[Depth];
+ }
+ break;
+ case 400:
+ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ }
+ break;
+ case 512:
+ if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ }
+ break;
+ case 640:
+ if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
+ else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+ break;
+ case 720:
+ if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
+ else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+ break;
+ case 768:
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ break;
+ case 800:
+ if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+ else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+ break;
+ case 848:
+ if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+ break;
+ case 856:
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ break;
+ case 960:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+ else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
+ }
+ break;
+ case 1024:
+ if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+ else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+ else if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
+ }
+ break;
+ case 1152:
+ if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+ if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
+ }
+ break;
+ case 1280:
+ switch(VDisplay) {
+ case 720:
+ ModeIndex = ModeIndex_1280x720[Depth];
+ break;
+ case 768:
+ if(VGAEngine == SIS_300_VGA) {
+ ModeIndex = ModeIndex_300_1280x768[Depth];
+ } else {
+ ModeIndex = ModeIndex_310_1280x768[Depth];
+ }
+ break;
+ case 800:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x800[Depth];
+ }
+ break;
+ case 854:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x854[Depth];
+ }
+ break;
+ case 960:
+ ModeIndex = ModeIndex_1280x960[Depth];
+ break;
+ case 1024:
+ ModeIndex = ModeIndex_1280x1024[Depth];
+ break;
+ }
+ break;
+ case 1360:
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VGAEngine == SIS_300_VGA) {
+ if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
+ }
+ break;
+ case 1400:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1050) {
+ ModeIndex = ModeIndex_1400x1050[Depth];
+ }
+ }
+ break;
+ case 1600:
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ break;
+ case 1680:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ }
+ break;
+ case 1920:
+ if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+ else if(VGAEngine == SIS_315_VGA) {
+ if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
+ }
+ break;
+ case 2048:
+ if(VDisplay == 1536) {
+ if(VGAEngine == SIS_300_VGA) {
+ ModeIndex = ModeIndex_300_2048x1536[Depth];
+ } else {
+ ModeIndex = ModeIndex_310_2048x1536[Depth];
+ }
+ }
+ break;
}
- return(ModeIndex);
+ return ModeIndex;
}
-#endif
-USHORT
-SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, USHORT CustomT, int LCDwidth, int LCDheight)
+unsigned short
+SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
- if(VBFlags & (VB_LVDS | VB_30xBDH)) {
+ if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
switch(HDisplay)
{
case 320:
- if(CustomT != CUT_PANEL848) {
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) {
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(VDisplay == 200) {
+ if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
+ } else if(VDisplay == 240) {
if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
- else if(VGAEngine == SIS_315_VGA) {
- ModeIndex = ModeIndex_320x240_FSTN[Depth];
+ else if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_320x240_FSTN[Depth];
}
}
}
- break;
- case 400:
- if(CustomT != CUT_PANEL848) {
- if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 400:
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
}
}
- break;
+ break;
case 512:
- if(CustomT != CUT_PANEL848) {
- if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+ if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
if(VDisplay == 384) {
ModeIndex = ModeIndex_512x384[Depth];
@@ -739,9 +523,10 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
}
break;
case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
else if(VDisplay == 400) {
- if(CustomT != CUT_PANEL848) ModeIndex = ModeIndex_640x400[Depth];
+ if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
+ ModeIndex = ModeIndex_640x400[Depth];
}
break;
case 800:
@@ -752,6 +537,11 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
}
break;
+ case 856:
+ if(CustomT == CUT_PANEL856) {
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ }
+ break;
case 1024:
if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
else if(VGAEngine == SIS_300_VGA) {
@@ -762,7 +552,7 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
break;
case 1152:
if(VGAEngine == SIS_300_VGA) {
- if((VDisplay == 768) && (LCDheight == 768)) {
+ if((VDisplay == 768) && (LCDheight == 768)) {
ModeIndex = ModeIndex_1152x768[Depth];
}
}
@@ -770,49 +560,49 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
case 1280:
if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
else if(VGAEngine == SIS_315_VGA) {
- if((VDisplay == 768) && (LCDheight == 768)) {
+ if((VDisplay == 768) && (LCDheight == 768)) {
ModeIndex = ModeIndex_310_1280x768[Depth];
}
}
break;
case 1360:
if(VGAEngine == SIS_300_VGA) {
- if(CustomT == CUT_BARCO1366) {
+ if(CustomT == CUT_BARCO1366) {
if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
}
}
if(CustomT == CUT_PANEL848) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
}
break;
case 1400:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
}
break;
case 1600:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
}
break;
}
- } else if(VBFlags & VB_SISBRIDGE) {
+ } else if(VBFlags2 & VB2_SISBRIDGE) {
switch(HDisplay)
{
case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
+ break;
+ case 400:
if(LCDwidth >= 800 && LCDheight >= 600) {
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
}
- break;
+ break;
case 512:
if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
break;
case 640:
@@ -821,96 +611,115 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
break;
case 720:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
}
break;
case 768:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
}
break;
case 800:
if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
}
break;
case 848:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
}
break;
case 856:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+ if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
}
break;
case 960:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
+ if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
}
break;
case 1024:
if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
}
break;
case 1152:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+ if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
}
break;
case 1280:
switch(VDisplay) {
case 720:
- ModeIndex = ModeIndex_1280x720[Depth];
+ ModeIndex = ModeIndex_1280x720[Depth];
case 768:
- if(VGAEngine == SIS_300_VGA) {
+ if(VGAEngine == SIS_300_VGA) {
ModeIndex = ModeIndex_300_1280x768[Depth];
} else {
ModeIndex = ModeIndex_310_1280x768[Depth];
}
break;
case 800:
- if(VGAEngine == SIS_315_VGA) {
+ if(VGAEngine == SIS_315_VGA) {
ModeIndex = ModeIndex_1280x800[Depth];
}
break;
+ case 854:
+ if(VGAEngine == SIS_315_VGA) {
+ ModeIndex = ModeIndex_1280x854[Depth];
+ }
+ break;
case 960:
- ModeIndex = ModeIndex_1280x960[Depth];
+ ModeIndex = ModeIndex_1280x960[Depth];
break;
case 1024:
- ModeIndex = ModeIndex_1280x1024[Depth];
+ ModeIndex = ModeIndex_1280x1024[Depth];
break;
}
break;
case 1360:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+ if(VGAEngine == SIS_315_VGA) { /* OVER1280 only? */
+ if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
}
break;
case 1400:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
}
}
break;
case 1600:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+ if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
}
}
break;
#ifndef VB_FORBID_CRT2LCD_OVER_1600
case 1680:
if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+ if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+ }
+ }
+ break;
+ case 1920:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+ if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+ }
+ }
+ break;
+ case 2048:
+ if(VGAEngine == SIS_315_VGA) {
+ if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+ if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
}
}
break;
@@ -921,16 +730,17 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
return ModeIndex;
}
-USHORT
-SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ unsigned short ModeIndex = 0;
- if(VBFlags & VB_CHRONTEL) {
+ if(VBFlags2 & VB2_CHRONTEL) {
switch(HDisplay)
{
- case 512:
+ case 512:
if(VGAEngine == SIS_315_VGA) {
if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
@@ -944,27 +754,27 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 1024:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+ if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
}
break;
}
- } else if(VBFlags & VB_SISTVBRIDGE) {
+ } else if(VBFlags2 & VB2_SISTVBRIDGE) {
switch(HDisplay)
{
case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+ if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- break;
- case 512:
+ break;
+ case 400:
+ if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+ break;
+ case 512:
if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
- (VBFlags & TV_HIVISION) ||
- ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+ (VBFlags & TV_HIVISION) ||
+ ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
+ if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
}
break;
case 640:
@@ -973,34 +783,34 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 720:
if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
- if(VDisplay == 480) {
- ModeIndex = ModeIndex_720x480[Depth];
- } else if(VDisplay == 576) {
+ if(VDisplay == 480) {
+ ModeIndex = ModeIndex_720x480[Depth];
+ } else if(VDisplay == 576) {
if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
- ModeIndex = ModeIndex_720x576[Depth];
- }
+ ModeIndex = ModeIndex_720x576[Depth];
+ }
}
break;
case 768:
if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
- if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+ if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+ if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
}
}
break;
case 800:
if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
else if(VDisplay == 480) {
- if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+ if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
ModeIndex = ModeIndex_800x480[Depth];
}
}
break;
case 960:
if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 600) {
+ if(VDisplay == 600) {
if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
ModeIndex = ModeIndex_960x600[Depth];
}
@@ -1009,25 +819,28 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
break;
case 1024:
if(VDisplay == 768) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) {
+ if(VBFlags2 & VB2_30xBLV) {
ModeIndex = ModeIndex_1024x768[Depth];
}
} else if(VDisplay == 576) {
- if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+ if( (VBFlags & TV_HIVISION) ||
+ ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
+ ((VBFlags2 & VB2_30xBLV) &&
+ ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
ModeIndex = ModeIndex_1024x576[Depth];
}
}
break;
case 1280:
if(VDisplay == 720) {
- if((VBFlags & TV_HIVISION) ||
+ if((VBFlags & TV_HIVISION) ||
((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
- ModeIndex = ModeIndex_1280x720[Depth];
+ ModeIndex = ModeIndex_1280x720[Depth];
}
} else if(VDisplay == 1024) {
- if((VBFlags & TV_HIVISION) ||
+ if((VBFlags & TV_HIVISION) ||
((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
- ModeIndex = ModeIndex_1280x1024[Depth];
+ ModeIndex = ModeIndex_1280x1024[Depth];
}
}
break;
@@ -1036,99 +849,31 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
return ModeIndex;
}
-USHORT
-SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+ unsigned int VBFlags2)
{
- USHORT ModeIndex = 0;
+ if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
- if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
+ if(HDisplay >= 1920) return 0;
switch(HDisplay)
{
- case 320:
- if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
- else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
- break;
- case 400:
- if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
- break;
- case 512:
- if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
- break;
- case 640:
- if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
- else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
- break;
- case 720:
- if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
- break;
- case 768:
- if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
- break;
- case 800:
- if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
- else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
- break;
- case 848:
- if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
- break;
- case 856:
- if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
- break;
- case 960:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
- else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
- }
- break;
- case 1024:
- if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
- else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
- break;
- case 1152:
- if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
- else if(VGAEngine == SIS_300_VGA) {
- if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
- }
- break;
- case 1280:
- if(VDisplay == 768) {
- if(VGAEngine == SIS_300_VGA) {
- ModeIndex = ModeIndex_300_1280x768[Depth];
- } else {
- ModeIndex = ModeIndex_310_1280x768[Depth];
- }
- } else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
- else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth];
- else if(VDisplay == 800) ModeIndex = ModeIndex_1280x800[Depth];
- else if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth];
- break;
- case 1360:
- if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
- break;
- case 1400:
- if(VGAEngine == SIS_315_VGA) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
- }
- break;
case 1600:
- if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
- if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
- }
+ if(VDisplay == 1200) {
+ if(VGAEngine != SIS_315_VGA) return 0;
+ if(!(VBFlags2 & VB2_30xB)) return 0;
}
break;
case 1680:
- if(VGAEngine == SIS_315_VGA) {
- if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
- if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
- }
+ if(VDisplay == 1050) {
+ if(VGAEngine != SIS_315_VGA) return 0;
+ if(!(VBFlags2 & VB2_30xB)) return 0;
}
break;
}
- return ModeIndex;
+ return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
}
@@ -1137,83 +882,83 @@ SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int
/*********************************************/
void
-SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data)
+SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
{
- OutPortByte(port,index);
- OutPortByte(port + 1,data);
+ OutPortByte(port, index);
+ OutPortByte(port + 1, data);
}
void
-SiS_SetRegByte(SISIOADDRESS port, USHORT data)
+SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
{
- OutPortByte(port,data);
+ OutPortByte(port, data);
}
void
-SiS_SetRegShort(SISIOADDRESS port, USHORT data)
+SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
{
- OutPortWord(port,data);
+ OutPortWord(port, data);
}
void
-SiS_SetRegLong(SISIOADDRESS port, ULONG data)
+SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
{
- OutPortLong(port,data);
+ OutPortLong(port, data);
}
-UCHAR
-SiS_GetReg(SISIOADDRESS port, USHORT index)
+unsigned char
+SiS_GetReg(SISIOADDRESS port, unsigned short index)
{
- OutPortByte(port,index);
+ OutPortByte(port, index);
return(InPortByte(port + 1));
}
-UCHAR
+unsigned char
SiS_GetRegByte(SISIOADDRESS port)
{
return(InPortByte(port));
}
-USHORT
+unsigned short
SiS_GetRegShort(SISIOADDRESS port)
{
return(InPortWord(port));
}
-ULONG
+unsigned int
SiS_GetRegLong(SISIOADDRESS port)
{
return(InPortLong(port));
}
void
-SiS_SetRegANDOR(SISIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR)
+SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp = (temp & (DataAND)) | DataOR;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp = (temp & (DataAND)) | DataOR;
+ SiS_SetReg(Port, Index, temp);
}
void
-SiS_SetRegAND(SISIOADDRESS Port,USHORT Index,USHORT DataAND)
+SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp &= DataAND;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp &= DataAND;
+ SiS_SetReg(Port, Index, temp);
}
void
-SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
+SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
{
- USHORT temp;
+ unsigned short temp;
- temp = SiS_GetReg(Port,Index);
- temp |= DataOR;
- SiS_SetReg(Port,Index,temp);
+ temp = SiS_GetReg(Port, Index);
+ temp |= DataOR;
+ SiS_SetReg(Port, Index, temp);
}
/*********************************************/
@@ -1221,13 +966,13 @@ SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
/*********************************************/
void
-SiS_DisplayOn(SiS_Private *SiS_Pr)
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
{
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
}
void
-SiS_DisplayOff(SiS_Private *SiS_Pr)
+SiS_DisplayOff(struct SiS_Private *SiS_Pr)
{
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
}
@@ -1238,7 +983,7 @@ SiS_DisplayOff(SiS_Private *SiS_Pr)
/*********************************************/
void
-SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
+SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
{
SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
@@ -1251,16 +996,17 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
- SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */
- SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */
- SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */
- SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
- SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */
- SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */
- SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
- SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+ SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+ SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
+ SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
+ SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
+ SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;
+ SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
+ SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
}
/*********************************************/
@@ -1268,7 +1014,7 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
/*********************************************/
static void
-SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
{
unsigned char cr5f, temp1, temp2;
@@ -1276,9 +1022,9 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* (SR11 is used for DDC and in enable/disablebridge) */
SiS_Pr->SiS_SensibleSR11 = FALSE;
SiS_Pr->SiS_MyCR63 = 0x63;
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
SiS_Pr->SiS_MyCR63 = 0x53;
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
SiS_Pr->SiS_SensibleSR11 = TRUE;
}
}
@@ -1286,43 +1032,52 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* You should use the macros, not these flags directly */
SiS_Pr->SiS_SysFlags = 0;
- if(HwInfo->jChipType == SIS_650) {
+ if(SiS_Pr->ChipType == SIS_650) {
cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
if((!temp1) || (temp2)) {
- switch(cr5f) {
+ switch(cr5f) {
case 0x80:
case 0x90:
case 0xc0:
- SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+ SiS_Pr->SiS_SysFlags |= SF_IsM650;
+ break;
case 0xa0:
case 0xb0:
case 0xe0:
- SiS_Pr->SiS_SysFlags |= SF_Is651; break;
+ SiS_Pr->SiS_SysFlags |= SF_Is651;
+ break;
}
} else {
- switch(cr5f) {
+ switch(cr5f) {
case 0x90:
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
switch(temp1) {
- case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
+ case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
}
break;
case 0xb0:
- SiS_Pr->SiS_SysFlags |= SF_Is652; break;
+ SiS_Pr->SiS_SysFlags |= SF_Is652;
+ break;
default:
- SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+ SiS_Pr->SiS_SysFlags |= SF_IsM650;
+ break;
}
}
}
- if(HwInfo->jChipType == SIS_760) {
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
- if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
+
+ if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
+ SiS_Pr->SiS_SysFlags |= SF_760LFB;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
+ SiS_Pr->SiS_SysFlags |= SF_760UMA;
+ }
}
}
@@ -1331,18 +1086,20 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
{
- switch(HwInfo->jChipType) {
+ switch(SiS_Pr->ChipType) {
+#ifdef SIS300
case SIS_300:
case SIS_540:
case SIS_630:
case SIS_730:
/* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
- * - RELOCATED VGA IO (0x20)
- * - MMIO ENABLE (0x1)
+ * - RELOCATED VGA IO ENABLED (0x20)
+ * - MMIO ENABLED (0x01)
+ * Leave other bits untouched.
*/
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
/* - Enable 2D (0x40)
* - Enable 3D (0x02)
* - Enable 3D Vertex command fetch (0x10) ?
@@ -1350,6 +1107,8 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
break;
+#endif
+#ifdef SIS315H
case SIS_315H:
case SIS_315:
case SIS_315PRO:
@@ -1362,21 +1121,30 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
case SIS_760:
case SIS_761:
case SIS_340:
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
- /* - Enable 2D (0x40)
- * - Enable 3D (0x02)
+ case XGI_40:
+ /* See above */
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ /* - Enable 3D G/L transformation engine (0x80)
+ * - Enable 2D (0x40)
* - Enable 3D vertex command fetch (0x10)
* - Enable 3D command parser (0x08)
- * - Enable 3D G/L transformation engine (0x80)
+ * - Enable 3D (0x02)
*/
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
break;
+ case XGI_20:
case SIS_550:
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ /* See above */
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
/* No 3D engine ! */
/* - Enable 2D (0x40)
+ * - disable 3D
*/
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x40);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
+ break;
+#endif
+ default:
+ break;
}
}
@@ -1384,38 +1152,40 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* HELPER: SetLVDSetc */
/*********************************************/
-static void
-SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
SiS_Pr->SiS_IF_DEF_LVDS = 0;
SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
SiS_Pr->SiS_IF_DEF_CH70xx = 0;
- SiS_Pr->SiS_IF_DEF_DSTN = 0;
- SiS_Pr->SiS_IF_DEF_FSTN = 0;
SiS_Pr->SiS_IF_DEF_CONEX = 0;
SiS_Pr->SiS_ChrontelInit = 0;
+ if(SiS_Pr->ChipType == XGI_20) return;
+
/* Check for SiS30x first */
temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
if((temp == 1) || (temp == 2)) return;
- switch(HwInfo->jChipType) {
+ switch(SiS_Pr->ChipType) {
#ifdef SIS300
case SIS_540:
case SIS_630:
case SIS_730:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- temp = (temp & 0x0E) >> 1;
- if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
- if((temp == 4) || (temp == 5)) {
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+ if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+ if((temp == 4) || (temp == 5)) {
/* Save power status (and error check) - UNUSED */
SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
SiS_Pr->SiS_IF_DEF_CH70xx = 1;
- }
+ }
break;
#endif
#ifdef SIS315H
@@ -1423,26 +1193,26 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
case SIS_650:
case SIS_740:
case SIS_330:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- temp = (temp & 0x0E) >> 1;
- if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
- break;
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+ if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+ break;
case SIS_661:
case SIS_741:
case SIS_660:
case SIS_760:
case SIS_761:
case SIS_340:
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- temp = (temp & 0xe0) >> 5;
- if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
- if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
- if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */
- break;
+ case XGI_20:
+ case XGI_40:
+ temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
+ if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+ if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */
+ break;
#endif
default:
- break;
+ break;
}
}
@@ -1451,35 +1221,55 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
{
SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
}
void
-SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
{
SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
}
/*********************************************/
+/* HELPER: Get modeflag */
+/*********************************************/
+
+unsigned short
+SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
+{
+ if(SiS_Pr->UseCustomMode) {
+ return SiS_Pr->CModeFlag;
+ } else if(ModeNo <= 0x13) {
+ return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+}
+
+/*********************************************/
/* HELPER: Determine ROM usage */
/*********************************************/
BOOLEAN
-SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romversoffs, romvmaj = 1, romvmin = 0;
-
- if(HwInfo->jChipType >= SIS_761) {
- /* I very much assume 761 and 340 will use new layout */
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romversoffs, romvmaj = 1, romvmin = 0;
+
+ if(SiS_Pr->ChipType >= XGI_20) {
+ /* XGI ROMs don't qualify */
+ return FALSE;
+ } else if(SiS_Pr->ChipType >= SIS_761) {
+ /* I very much assume 761, 340 and newer will use new layout */
return TRUE;
- } else if(HwInfo->jChipType >= SIS_661) {
+ } else if(SiS_Pr->ChipType >= SIS_661) {
if((ROMAddr[0x1a] == 'N') &&
- (ROMAddr[0x1b] == 'e') &&
- (ROMAddr[0x1c] == 'w') &&
- (ROMAddr[0x1d] == 'V')) {
+ (ROMAddr[0x1b] == 'e') &&
+ (ROMAddr[0x1c] == 'w') &&
+ (ROMAddr[0x1d] == 'V')) {
return TRUE;
}
romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
@@ -1494,9 +1284,9 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
} else if(IS_SIS650740) {
if((ROMAddr[0x1a] == 'N') &&
- (ROMAddr[0x1b] == 'e') &&
- (ROMAddr[0x1c] == 'w') &&
- (ROMAddr[0x1d] == 'V')) {
+ (ROMAddr[0x1b] == 'e') &&
+ (ROMAddr[0x1c] == 'w') &&
+ (ROMAddr[0x1d] == 'V')) {
return TRUE;
}
}
@@ -1504,45 +1294,50 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
static void
-SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = 0;
SiS_Pr->SiS_UseROM = FALSE;
SiS_Pr->SiS_ROMNew = FALSE;
+ SiS_Pr->SiS_PWDOffset = 0;
- if((ROMAddr) && (HwInfo->UseROM)) {
- if(HwInfo->jChipType == SIS_300) {
- /* 300: We check if the code starts below 0x220 by
+ if(SiS_Pr->ChipType >= XGI_20) return;
+
+ if((ROMAddr) && (SiS_Pr->UseROM)) {
+ if(SiS_Pr->ChipType == SIS_300) {
+ /* 300: We check if the code starts below 0x220 by
* checking the jmp instruction at the beginning
* of the BIOS image.
*/
if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
SiS_Pr->SiS_UseROM = TRUE;
- } else if(HwInfo->jChipType < SIS_315H) {
+ } else if(SiS_Pr->ChipType < SIS_315H) {
/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
* the others do as well
*/
SiS_Pr->SiS_UseROM = TRUE;
} else {
- /* 315/330 series stick to the standard(s) */
+ /* 315/330 series stick to the standard(s) */
SiS_Pr->SiS_UseROM = TRUE;
- if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+ if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
SiS_Pr->SiS_EMIOffset = 14;
+ SiS_Pr->SiS_PWDOffset = 17;
SiS_Pr->SiS661LCD2TableSize = 36;
/* Find out about LCD data table entry size */
if((romptr = SISGETROMW(0x0102))) {
if(ROMAddr[romptr + (32 * 16)] == 0xff)
- SiS_Pr->SiS661LCD2TableSize = 32;
+ SiS_Pr->SiS661LCD2TableSize = 32;
else if(ROMAddr[romptr + (34 * 16)] == 0xff)
- SiS_Pr->SiS661LCD2TableSize = 34;
- else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94 */
- SiS_Pr->SiS661LCD2TableSize = 36;
+ SiS_Pr->SiS661LCD2TableSize = 34;
+ else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94, 2.05.00+ */
+ SiS_Pr->SiS661LCD2TableSize = 36;
else if( (ROMAddr[romptr + (38 * 16)] == 0xff) || /* 2.00.00 - 2.02.00 */
- (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00+ */
- SiS_Pr->SiS661LCD2TableSize = 38;
+ (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00 - <2.05.00 */
+ SiS_Pr->SiS661LCD2TableSize = 38; /* UMC data layout abandoned at 2.05.00 */
SiS_Pr->SiS_EMIOffset = 16;
+ SiS_Pr->SiS_PWDOffset = 19;
}
}
}
@@ -1555,9 +1350,9 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp;
+ unsigned short temp;
value &= 0x00ff;
temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
@@ -1569,9 +1364,9 @@ SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp;
+ unsigned short temp;
value &= 0x00ff;
temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
@@ -1583,22 +1378,22 @@ SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_SetSegmentReg(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
{
SiS_SetSegRegLower(SiS_Pr, value);
SiS_SetSegRegUpper(SiS_Pr, value);
}
static void
-SiS_ResetSegmentReg(SiS_Private *SiS_Pr)
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
{
SiS_SetSegmentReg(SiS_Pr, 0);
}
static void
-SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
{
- USHORT temp = value >> 8;
+ unsigned short temp = value >> 8;
temp &= 0x07;
temp |= (temp << 4);
@@ -1607,15 +1402,15 @@ SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
}
static void
-SiS_ResetSegmentRegOver(SiS_Private *SiS_Pr)
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
{
SiS_SetSegmentRegOver(SiS_Pr, 0);
}
static void
-SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
{
- if((IS_SIS65x) || (HwInfo->jChipType >= SIS_661)) {
+ if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
SiS_ResetSegmentReg(SiS_Pr);
SiS_ResetSegmentRegOver(SiS_Pr);
}
@@ -1625,89 +1420,86 @@ SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
/* HELPER: GetVBType */
/*********************************************/
-static void
-SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_GetVBType(struct SiS_Private *SiS_Pr)
{
- USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27;
-
- SiS_Pr->SiS_VBType = 0;
-
- if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
- return;
-
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-
- if(flag > 3) return;
-
- rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-
- if(flag >= 2) {
- SiS_Pr->SiS_VBType = VB_SIS302B;
- } else if(flag == 1) {
- if(rev >= 0xC0) {
- SiS_Pr->SiS_VBType = VB_SIS301C;
- } else if(rev >= 0xB0) {
- SiS_Pr->SiS_VBType = VB_SIS301B;
- /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
- nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
- if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
- } else {
- SiS_Pr->SiS_VBType = VB_SIS301;
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
- if(rev >= 0xE0) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
- if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
- else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */
- } else if(rev >= 0xD0) {
- SiS_Pr->SiS_VBType = VB_SIS301LV;
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
- p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
- p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
- p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
- if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
- SiS_Pr->SiS_VBType |= VB_UMC;
- }
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
- }
+ unsigned short flag = 0, rev = 0, nolcd = 0;
+ unsigned short p4_0f, p4_25, p4_27;
+
+ SiS_Pr->SiS_VBType = 0;
+
+ if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+ return;
+
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+
+ if(flag > 3)
+ return;
+
+ rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+
+ if(flag >= 2) {
+ SiS_Pr->SiS_VBType = VB_SIS302B;
+ } else if(flag == 1) {
+ if(rev >= 0xC0) {
+ SiS_Pr->SiS_VBType = VB_SIS301C;
+ } else if(rev >= 0xB0) {
+ SiS_Pr->SiS_VBType = VB_SIS301B;
+ /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
+ nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
+ if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+ } else {
+ SiS_Pr->SiS_VBType = VB_SIS301;
+ }
+ }
+ if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
+ if(rev >= 0xE0) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+ if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+ else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */
+ } else if(rev >= 0xD0) {
+ SiS_Pr->SiS_VBType = VB_SIS301LV;
+ }
+ }
+ if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
+ p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
+ p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
+ if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
+ SiS_Pr->SiS_VBType |= VB_UMC;
+ }
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
+ }
}
/*********************************************/
/* HELPER: Check RAM size */
/*********************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
static BOOLEAN
-SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
- USHORT memorysize,modeflag;
-
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
- }
-
- memorysize = modeflag & MemoryInfoFlag;
- memorysize >>= MemorySizeShift; /* Get required memory size */
- memorysize++;
-
- if(AdapterMemSize < memorysize) return FALSE;
- return TRUE;
+ unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
+ unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+ unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
+
+ if(!AdapterMemSize) return TRUE;
+
+ if(AdapterMemSize < memorysize) return FALSE;
+ return TRUE;
}
#endif
@@ -1716,63 +1508,65 @@ SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
#ifdef SIS315H
-static UCHAR
-SiS_Get310DRAMType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char
+SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
{
- UCHAR data, temp;
+ unsigned char data;
if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
- data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
+ data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
} else {
- if(HwInfo->jChipType >= SIS_340) {
- /* TODO */
- data = 0;
- } if(HwInfo->jChipType >= SIS_661) {
- data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
- if(SiS_Pr->SiS_ROMNew) {
- data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
- }
- } else if(IS_SIS550650740) {
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
- } else { /* 315, 330 */
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
- if(HwInfo->jChipType == SIS_330) {
- if(data > 1) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30;
- switch(temp) {
- case 0x00: data = 1; break;
- case 0x10: data = 3; break;
- case 0x20: data = 3; break;
- case 0x30: data = 2; break;
- }
- } else {
- data = 0;
- }
- }
- }
+ if(SiS_Pr->ChipType >= XGI_20) {
+ /* Do I need this? SR17 seems to be zero anyway... */
+ data = 0;
+ } else if(SiS_Pr->ChipType >= SIS_340) {
+ /* TODO */
+ data = 0;
+ } if(SiS_Pr->ChipType >= SIS_661) {
+ if(SiS_Pr->SiS_ROMNew) {
+ data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+ } else {
+ data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+ }
+ } else if(IS_SIS550650740) {
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+ } else { /* 315, 330 */
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
+ if(SiS_Pr->ChipType == SIS_330) {
+ if(data > 1) {
+ switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
+ case 0x00: data = 1; break;
+ case 0x10: data = 3; break;
+ case 0x20: data = 3; break;
+ case 0x30: data = 2; break;
+ }
+ } else {
+ data = 0;
+ }
+ }
+ }
}
return data;
}
-static USHORT
-SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+SiS_GetMCLK(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index;
-
- index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- if(HwInfo->jChipType >= SIS_661) {
- if(SiS_Pr->SiS_ROMNew) {
- return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
- }
- return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
- } else if(index >= 4) {
- index -= 4;
- return(SiS_Pr->SiS_MCLKData_1[index].CLOCK);
- } else {
- return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
- }
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index;
+
+ index = SiS_Get310DRAMType(SiS_Pr);
+ if(SiS_Pr->ChipType >= SIS_661) {
+ if(SiS_Pr->SiS_ROMNew) {
+ return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
+ }
+ return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+ } else if(index >= 4) {
+ return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
+ } else {
+ return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+ }
}
#endif
@@ -1780,30 +1574,30 @@ SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* HELPER: ClearBuffer */
/*********************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
static void
-SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- UCHAR SISIOMEMTYPE *VideoMemoryAddress = HwInfo->pjVideoMemoryAddress;
- ULONG AdapterMemorySize = HwInfo->ulVideoMemorySize;
- USHORT SISIOMEMTYPE *pBuffer;
- int i;
-
- if(SiS_Pr->SiS_ModeType >= ModeEGA) {
- if(ModeNo > 0x13) {
- SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
- } else {
- pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
- for(i=0; i<0x4000; i++) writew(0x0000, &pBuffer[i]);
- }
- } else {
- if(SiS_Pr->SiS_ModeType < ModeCGA) {
- pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
- for(i=0; i<0x4000; i++) writew(0x0720, &pBuffer[i]);
- } else {
- SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
- }
- }
+ unsigned char SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
+ unsigned int memsize = SiS_Pr->VideoMemorySize;
+ unsigned short SISIOMEMTYPE *pBuffer;
+ int i;
+
+ if(!memaddr || !memsize) return;
+
+ if(SiS_Pr->SiS_ModeType >= ModeEGA) {
+ if(ModeNo > 0x13) {
+ SiS_SetMemory(memaddr, memsize, 0);
+ } else {
+ pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+ for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
+ }
+ } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
+ pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+ for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
+ } else {
+ SiS_SetMemory(memaddr, 0x8000, 0);
+ }
}
#endif
@@ -1812,35 +1606,36 @@ SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
BOOLEAN
-SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex)
{
- UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+ unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
- if(*ModeNo <= 0x13) {
+ if((*ModeNo) <= 0x13) {
if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
- for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
- if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break;
- if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) return FALSE;
+ for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+ if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
+ if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
}
- if(*ModeNo == 0x07) {
- if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
- /* else 350 lines */
+ if((*ModeNo) == 0x07) {
+ if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
}
- if(*ModeNo <= 0x03) {
- if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
- if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
- /* else 350 lines */
+ if((*ModeNo) <= 0x03) {
+ if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
+ if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
+ /* else 350 lines */
}
/* else 200 lines */
} else {
- for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
- if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break;
- if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return FALSE;
+ for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+ if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
+ if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
}
}
@@ -1851,10 +1646,10 @@ SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
/* HELPER: GetModePtr */
/*********************************************/
-UCHAR
-SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR index;
+ unsigned short index;
if(ModeNo <= 0x13) {
index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
@@ -1866,79 +1661,125 @@ SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
}
/*********************************************/
+/* HELPERS: Get some indices */
+/*********************************************/
+
+unsigned short
+SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+ if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+ if(UseWide == 1) {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
+ }
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
+ }
+}
+
+unsigned short
+SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+ if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+ if(UseWide == 1) {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
+ }
+}
+
+/*********************************************/
/* HELPER: LowModeTests */
/*********************************************/
static BOOLEAN
-SiS_DoLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp,temp1,temp2;
-
- if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
- return(TRUE);
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
- temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
- if((HwInfo->jChipType >= SIS_315H) ||
- (HwInfo->jChipType == SIS_300)) {
- if(temp2 == 0x55) return(FALSE);
- else return(TRUE);
- } else {
- if(temp2 != 0x55) return(TRUE);
- else {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
- return(FALSE);
- }
- }
+ unsigned short temp, temp1, temp2;
+
+ if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
+ return TRUE;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
+ temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
+ if((SiS_Pr->ChipType >= SIS_315H) ||
+ (SiS_Pr->ChipType == SIS_300)) {
+ if(temp2 == 0x55) return FALSE;
+ else return TRUE;
+ } else {
+ if(temp2 != 0x55) return TRUE;
+ else {
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
+ return FALSE;
+ }
+ }
}
static void
-SiS_SetLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- if(SiS_DoLowModeTest(SiS_Pr, ModeNo, HwInfo)) {
- SiS_Pr->SiS_SetFlag |= LowModeTests;
- }
+ if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
+ SiS_Pr->SiS_SetFlag |= LowModeTests;
+ }
}
/*********************************************/
-/* HELPER: ENABLE CRT1 */
+/* HELPER: OPEN/CLOSE CRT1 CRTC */
/*********************************************/
static void
-SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
+{
+ if(IS_SIS650) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+ if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+ } else if(IS_SIS661741660760) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+ if(!SiS_Pr->SiS_ROMNew) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+ }
+ }
+}
+
+static void
+SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
{
- if(IS_SIS650) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
- if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
- }
- } else if(IS_SIS661741660760) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
- if(!SiS_Pr->SiS_ROMNew) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
- }
- }
+#if 0 /* This locks some CRTC registers. We don't want that. */
+ unsigned short temp1 = 0, temp2 = 0;
+
+ if(IS_SIS661741660760) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ temp1 = 0xa0; temp2 = 0x08;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
+ }
+#endif
}
static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
{
- /* Enable CRT1 gating */
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+ /* Enable CRT1 gating */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
#if 0
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
- if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
- (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
- }
- }
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+ if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+ (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+ }
+ }
#endif
}
@@ -1946,57 +1787,54 @@ SiS_HandleCRT1(SiS_Private *SiS_Pr)
/* HELPER: GetColorDepth */
/*********************************************/
-USHORT
-SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
- SHORT index;
- USHORT modeflag;
-
- /* Do NOT check UseCustomMode, will skrew up FIFO */
- if(ModeNo == 0xfe) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- if(ModeNo <= 0x13)
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- else
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- index = (modeflag & ModeTypeMask) - ModeEGA;
- if(index < 0) index = 0;
- return(ColorDepth[index]);
+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+ unsigned short modeflag;
+ short index;
+
+ /* Do NOT check UseCustomMode, will skrew up FIFO */
+ if(ModeNo == 0xfe) {
+ modeflag = SiS_Pr->CModeFlag;
+ } else if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+ index = (modeflag & ModeTypeMask) - ModeEGA;
+ if(index < 0) index = 0;
+ return ColorDepth[index];
}
/*********************************************/
/* HELPER: GetOffset */
/*********************************************/
-USHORT
-SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT xres, temp, colordepth, infoflag;
-
- if(SiS_Pr->UseCustomMode) {
- infoflag = SiS_Pr->CInfoFlag;
- xres = SiS_Pr->CHDisplay;
- } else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
- }
-
- colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
-
- temp = xres / 16;
- if(infoflag & InterlaceMode) temp <<= 1;
- temp *= colordepth;
- if(xres % 16) {
- colordepth >>= 1;
- temp += colordepth;
- }
-
- return(temp);
+ unsigned short xres, temp, colordepth, infoflag;
+
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ xres = SiS_Pr->CHDisplay;
+ } else {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+ xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
+ }
+
+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+ temp = xres / 16;
+ if(infoflag & InterlaceMode) temp <<= 1;
+ temp *= colordepth;
+ if(xres % 16) temp += (colordepth >> 1);
+
+ return temp;
}
/*********************************************/
@@ -2004,55 +1842,29 @@ SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR SRdata;
- USHORT i;
+ unsigned char SRdata;
+ int i;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03); /* Set SR0 */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
- SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0];
+ /* or "display off" */
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SRdata |= 0x01;
- }
- if(HwInfo->jChipType >= SIS_661) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
- }
+ /* determine whether to force x8 dotclock */
+ if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SRdata |= 0x01; /* 8 dot clock */
- }
- }
- }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) SRdata |= 0x01;
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
- SRdata |= 0x20; /* screen off */
+ }
SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
for(i = 2; i <= 4; i++) {
- SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
}
}
@@ -2062,17 +1874,17 @@ SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR Miscdata;
+ unsigned char Miscdata;
Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
- if(HwInfo->jChipType < SIS_661) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- Miscdata |= 0x0C;
- }
+ if(SiS_Pr->ChipType < SIS_661) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ Miscdata |= 0x0C;
+ }
}
}
@@ -2084,33 +1896,34 @@ SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo
/*********************************************/
static void
-SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT StandTableIndex)
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR CRTCdata;
- USHORT i;
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* Unlock CRTC */
-
- for(i = 0; i <= 0x18; i++) {
- CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */
- }
- if(HwInfo->jChipType >= SIS_661) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- for(i = 0x13; i <= 0x14; i++) {
- CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
- }
- } else if( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision >= 0x30) ) { /* for 630S0 */
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
- }
- }
- }
+ unsigned char CRTCdata;
+ unsigned short i;
+
+ /* Unlock CRTC */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0; i <= 0x18; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+ }
+
+ if(SiS_Pr->ChipType >= SIS_661) {
+ SiS_OpenCRTC(SiS_Pr);
+ for(i = 0x13; i <= 0x14; i++) {
+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+ }
+ } else if( ( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
+ }
+ }
+ }
}
/*********************************************/
@@ -2118,64 +1931,58 @@ SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR ARdata;
- USHORT i;
+ unsigned char ARdata;
+ unsigned short i;
for(i = 0; i <= 0x13; i++) {
ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
-#if 0
- if((i <= 0x0f) || (i == 0x11)) {
- if(ds:489 & 0x08) {
- continue;
- }
- }
-#endif
+
if(i == 0x13) {
- /* Pixel shift. If screen on LCD or TV is shifted left or right,
- * this might be the cause.
- */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata=0;
- }
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
- }
- }
- }
- if(HwInfo->jChipType >= SIS_661) {
+ /* Pixel shift. If screen on LCD or TV is shifted left or right,
+ * this might be the cause.
+ */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
+ }
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+ }
+ }
+ }
+ if(SiS_Pr->ChipType >= SIS_661) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(IS_SIS550650740660) {
- /* 315, 330 don't do this */
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
- } else {
- ARdata = 0;
- }
+ /* 315, 330 don't do this */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+ } else {
+ ARdata = 0;
+ }
}
} else {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
}
- }
+ }
}
- SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */
+ SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */
}
- SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */
+
+ SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */
SiS_GetRegByte(SiS_Pr->SiS_P3da);
- SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */
SiS_GetRegByte(SiS_Pr->SiS_P3da);
}
@@ -2184,10 +1991,10 @@ SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
/*********************************************/
static void
-SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
{
- UCHAR GRdata;
- USHORT i;
+ unsigned char GRdata;
+ unsigned short i;
for(i = 0; i <= 0x08; i++) {
GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
@@ -2205,22 +2012,22 @@ SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
/*********************************************/
static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT i;
+ unsigned short i;
- for(i = 0x0A; i <= 0x0E; i++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
- }
+ for(i = 0x0A; i <= 0x0E; i++) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
+ }
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
- if(ModeNo <= 0x13) {
- if(ModeNo == 0x06 || ModeNo >= 0x0e) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+ if(ModeNo <= 0x13) {
+ if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+ }
+ }
+ }
}
/*********************************************/
@@ -2228,32 +2035,24 @@ SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
static void
-SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H) {
- if(HwInfo->jChipType < SIS_661) {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_661) {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
}
} else {
if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
- (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
+ (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
return;
}
}
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
- }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
- }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
@@ -2264,19 +2063,19 @@ SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
{
- USHORT sync;
+ unsigned short sync;
- if(SiS_Pr->UseCustomMode) {
- sync = SiS_Pr->CInfoFlag >> 8;
- } else {
- sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
- }
+ if(SiS_Pr->UseCustomMode) {
+ sync = SiS_Pr->CInfoFlag >> 8;
+ } else {
+ sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
+ }
- sync &= 0xC0;
- sync |= 0x2f;
- SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
+ sync &= 0xC0;
+ sync |= 0x2f;
+ SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
}
/*********************************************/
@@ -2284,72 +2083,67 @@ SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
/*********************************************/
static void
-SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- UCHAR index;
- USHORT temp,i,j,modeflag;
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* unlock cr0-7 */
-
- if(SiS_Pr->UseCustomMode) {
-
- modeflag = SiS_Pr->CModeFlag;
-
- for(i=0,j=0;i<=7;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x10;i<=10;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x15;i<=12;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
- }
- for(j=0x0A;i<=15;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
- }
-
- temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
- temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
- } else {
-
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- for(i=0,j=0;i<=7;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x10;i<=10;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x15;i<=12;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
- for(j=0x0A;i<=15;i++,j++) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
- }
-
- temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
- temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
- }
-
- if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+ unsigned short temp, i, j, modeflag;
+ unsigned char *crt1data = NULL;
+
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->UseCustomMode) {
+
+ crt1data = &SiS_Pr->CCRT1CRTC[0];
+
+ } else {
+
+ temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
+
+ /* Alternate for 1600x1200 LCDA */
+ if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
+
+ crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
+
+ }
+
+ /* unlock cr0-7 */
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0, j = 0; i <= 7; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x10; i <= 10; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x15; i <= 12; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+ }
+ for(j = 0x0A; i <= 15; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
+ }
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
+
+ temp = (crt1data[16] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
+
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+ }
+
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == XGI_20) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
+ if(!(temp = crt1data[5] & 0x1f)) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
+ temp = (crt1data[16] >> 5) + 3;
+ if(temp > 7) temp -= 7;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
+ }
+#endif
}
/*********************************************/
@@ -2359,33 +2153,32 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT temp, DisplayUnit, infoflag;
+ unsigned short temp, DisplayUnit, infoflag;
if(SiS_Pr->UseCustomMode) {
infoflag = SiS_Pr->CInfoFlag;
} else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
}
- DisplayUnit = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
+ DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
temp = (DisplayUnit >> 8) & 0x0f;
SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
- temp = DisplayUnit & 0xFF;
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,temp);
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
if(infoflag & InterlaceMode) DisplayUnit >>= 1;
DisplayUnit <<= 5;
- temp = (DisplayUnit & 0xff00) >> 8;
+ temp = (DisplayUnit >> 8) + 1;
if(DisplayUnit & 0xff) temp++;
- temp++;
+ if(SiS_Pr->ChipType == XGI_20) {
+ if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
+ }
SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
}
@@ -2394,39 +2187,49 @@ SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT index=0, clka, clkb;
-
- if(SiS_Pr->UseCustomMode) {
- clka = SiS_Pr->CSR2B;
- clkb = SiS_Pr->CSR2C;
- } else {
- index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
- clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
- } else {
- clka = SiS_Pr->SiS_VCLKData[index].SR2B;
- clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
- }
- }
-
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
- }
-
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,clka);
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,clkb);
-
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
- }
+ unsigned short index = 0, clka, clkb;
+
+ if(SiS_Pr->UseCustomMode) {
+ clka = SiS_Pr->CSR2B;
+ clkb = SiS_Pr->CSR2C;
+ } else {
+ index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+ (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ /* Alternate for 1600x1200 LCDA */
+ if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
+ clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
+ clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
+ } else {
+ clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+ clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+ }
+ }
+
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+
+ if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
+ if(SiS_Pr->ChipType == XGI_20) {
+ unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+ if(mf & HalfDCLK) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
+ clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
+ clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+ }
+ }
+#endif
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+ }
}
/*********************************************/
@@ -2434,415 +2237,358 @@ SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS300
-static USHORT
-SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key)
+void
+SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+ unsigned short *idx2)
+{
+ unsigned short temp1, temp2;
+ static const unsigned char ThTiming[8] = {
+ 1, 2, 2, 3, 0, 1, 1, 2
+ };
+
+ temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
+ (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
+ (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
+ (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
+ (*idx1) <<= 1;
+}
+
+static unsigned short
+SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
+{
+ static const unsigned char ThLowA[8 * 3] = {
+ 61, 3,52, 5,68, 7,100,11,
+ 43, 3,42, 5,54, 7, 78,11,
+ 34, 3,37, 5,47, 7, 67,11
+ };
+
+ return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
+}
+
+unsigned short
+SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
+{
+ static const unsigned char ThLowB[8 * 3] = {
+ 81, 4,72, 6,88, 8,120,12,
+ 55, 4,54, 6,66, 8, 90,12,
+ 42, 4,45, 6,55, 8, 75,12
+ };
+
+ return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
+}
+
+static unsigned short
+SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
+ unsigned short colordepth, unsigned short key)
{
- const UCHAR ThLowA[] = { 61, 3,52, 5,68, 7,100,11,
- 43, 3,42, 5,54, 7, 78,11,
- 34, 3,37, 5,47, 7, 67,11 };
-
- const UCHAR ThLowB[] = { 81, 4,72, 6,88, 8,120,12,
- 55, 4,54, 6,66, 8, 90,12,
- 42, 4,45, 6,55, 8, 75,12 };
-
- const UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 };
-
- USHORT tempah, tempal, tempcl, tempbx, temp;
- ULONG longtemp;
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempah &= 0x62;
- tempah >>= 1;
- tempal = tempah;
- tempah >>= 3;
- tempal |= tempah;
- tempal &= 0x07;
- tempcl = ThTiming[tempal];
- tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempbx >>= 6;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- tempah >>= 4;
- tempah &= 0x0c;
- tempbx |= tempah;
- tempbx <<= 1;
- if(key == 0) {
- tempal = ThLowA[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowA[tempbx];
- } else {
- tempal = ThLowB[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowB[tempbx];
- }
- longtemp = tempal * VCLK * colordepth;
- temp = longtemp % (MCLK * 16);
- longtemp /= (MCLK * 16);
- if(temp) longtemp++;
- return((USHORT)longtemp);
+ unsigned short idx1, idx2;
+ unsigned int longtemp = VCLK * colordepth;
+
+ SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
+
+ if(key == 0) {
+ longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
+ } else {
+ longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
+ }
+ idx1 = longtemp % (MCLK * 16);
+ longtemp /= (MCLK * 16);
+ if(idx1) longtemp++;
+ return (unsigned short)longtemp;
}
-static USHORT
-SiS_CalcDelay(SiS_Private *SiS_Pr, USHORT VCLK, USHORT colordepth, USHORT MCLK)
+static unsigned short
+SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
+ unsigned short colordepth, unsigned short MCLK)
{
- USHORT tempax, tempbx;
-
- tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
- tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
- if(tempax < 4) tempax = 4;
- tempax -= 4;
- if(tempbx < tempax) tempbx = tempax;
- return(tempbx);
+ unsigned short temp1, temp2;
+
+ temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
+ temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
+ if(temp1 < 4) temp1 = 4;
+ temp1 -= 4;
+ if(temp2 < temp1) temp2 = temp1;
+ return temp2;
}
static void
-SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo,
- USHORT RefreshRateTableIndex)
+SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short ThresholdLow = 0;
+ unsigned short temp, index, VCLK, MCLK, colorth;
+ static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
+
+ if(ModeNo > 0x13) {
+
+ /* Get VCLK */
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+
+ /* Get half colordepth */
+ colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+ /* Get MCLK */
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
+ MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
+
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
+
+ do {
+ ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
+ if(ThresholdLow < 0x13) break;
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
+ ThresholdLow = 0x13;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
+ if(!temp) break;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
+ } while(0);
+
+ } else ThresholdLow = 2;
+
+ /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+ temp = (ThresholdLow << 4) | 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
+
+ temp = (ThresholdLow & 0x10) << 1;
+ if(ModeNo > 0x13) temp |= 0x40;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
+
+ /* What is this? */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+ /* Write CRT/CPU threshold high */
+ temp = ThresholdLow + 3;
+ if(temp > 0x0f) temp = 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+}
+
+unsigned short
+SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
{
- USHORT ThresholdLow = 0;
- USHORT index, VCLK, MCLK, colorth=0;
- USHORT tempah, temp;
-
- if(ModeNo > 0x13) {
-
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
- }
-
- switch (SiS_Pr->SiS_ModeType - ModeEGA) { /* Get half colordepth */
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- }
-
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- tempah &= 0xc3;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah);
-
- do {
- ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK);
- ThresholdLow++;
- if(ThresholdLow < 0x13) break;
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
- ThresholdLow = 0x13;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempah >>= 6;
- if(!(tempah)) break;
- tempah--;
- tempah <<= 6;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah);
- } while(0);
-
- } else ThresholdLow = 2;
-
- /* Write CRT/CPU threshold low, CRT/Engine threshold high */
- temp = (ThresholdLow << 4) | 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
-
- temp = (ThresholdLow & 0x10) << 1;
- if(ModeNo > 0x13) temp |= 0x40;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
-
- /* What is this? */
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
-
- /* Write CRT/CPU threshold high */
- temp = ThresholdLow + 3;
- if(temp > 0x0f) temp = 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+ static const unsigned char LatencyFactor[] = {
+ 97, 88, 86, 79, 77, 0, /* 64 bit BQ=2 */
+ 0, 87, 85, 78, 76, 54, /* 64 bit BQ=1 */
+ 97, 88, 86, 79, 77, 0, /* 128 bit BQ=2 */
+ 0, 79, 77, 70, 68, 48, /* 128 bit BQ=1 */
+ 80, 72, 69, 63, 61, 0, /* 64 bit BQ=2 */
+ 0, 70, 68, 61, 59, 37, /* 64 bit BQ=1 */
+ 86, 77, 75, 68, 66, 0, /* 128 bit BQ=2 */
+ 0, 68, 66, 59, 57, 37 /* 128 bit BQ=1 */
+ };
+ static const unsigned char LatencyFactor730[] = {
+ 69, 63, 61,
+ 86, 79, 77,
+ 103, 96, 94,
+ 120,113,111,
+ 137,130,128
+ };
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ return (unsigned short)LatencyFactor730[index];
+ } else {
+ return (unsigned short)LatencyFactor[index];
+ }
}
-static USHORT
-SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR key, PSIS_HW_INFO HwInfo)
+static unsigned short
+SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
{
- USHORT data,index;
- const UCHAR LatencyFactor[] = {
- 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
- 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
- 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
- 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
- 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
- 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
- 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
- 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */
- };
- const UCHAR LatencyFactor730[] = {
- 69, 63, 61,
- 86, 79, 77,
- 103, 96, 94,
- 120,113,111,
- 137,130,128, /* --- Table ends with this entry, data below */
- 137,130,128, /* to avoid using illegal values */
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- };
-
- if(HwInfo->jChipType == SIS_730) {
- index = ((key & 0x0f) * 3) + ((key & 0xC0) >> 6);
- data = LatencyFactor730[index];
- } else {
- index = (key & 0xE0) >> 5;
- if(key & 0x10) index +=6;
- if(!(key & 0x01)) index += 24;
- data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(data & 0x0080) index += 12;
- data = LatencyFactor[index];
- }
- return(data);
+ unsigned short index;
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
+ } else {
+ index = (key & 0xe0) >> 5;
+ if(key & 0x10) index += 6;
+ if(!(key & 0x01)) index += 24;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
+ }
+ return SiS_GetLatencyFactor630(SiS_Pr, index);
}
static void
-SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, USHORT ModeNo,
- PSIS_HW_INFO HwInfo,
- USHORT RefreshRateTableIndex)
+SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex)
{
- USHORT i,index,data,VCLK,MCLK,colorth=0;
- ULONG B,eax,bl,data2;
- USHORT ThresholdLow=0;
- UCHAR FQBQData[]= {
- 0x01,0x21,0x41,0x61,0x81,
- 0x31,0x51,0x71,0x91,0xb1,
- 0x00,0x20,0x40,0x60,0x80,
- 0x30,0x50,0x70,0x90,0xb0,
- 0xFF
- };
- UCHAR FQBQData730[]= {
- 0x34,0x74,0xb4,
- 0x23,0x63,0xa3,
- 0x12,0x52,0x92,
- 0x01,0x41,0x81,
- 0x00,0x40,0x80,
- 0xff
- };
-
- i=0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
- }
-
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
-
- data2 = SiS_Pr->SiS_ModeType - ModeEGA; /* Get half colordepth */
- switch (data2) {
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- }
-
- if(HwInfo->jChipType == SIS_730) {
-
- do {
- B = SiS_CalcDelay2(SiS_Pr, FQBQData730[i], HwInfo) * VCLK * colorth;
- bl = B / (MCLK * 16);
-
- if(B == bl * 16 * MCLK) {
- bl = bl + 1;
- } else {
- bl = bl + 2;
- }
-
- if(bl > 0x13) {
- if(FQBQData730[i+1] == 0xFF) {
- ThresholdLow = 0x13;
- break;
- }
- i++;
- } else {
- ThresholdLow = bl;
- break;
- }
- } while(FQBQData730[i] != 0xFF);
+ unsigned short ThresholdLow = 0;
+ unsigned short i, data, VCLK, MCLK16, colorth = 0;
+ unsigned int templ, datal;
+ const unsigned char *queuedata = NULL;
+ static const unsigned char FQBQData[21] = {
+ 0x01,0x21,0x41,0x61,0x81,
+ 0x31,0x51,0x71,0x91,0xb1,
+ 0x00,0x20,0x40,0x60,0x80,
+ 0x30,0x50,0x70,0x90,0xb0,
+ 0xff
+ };
+ static const unsigned char FQBQData730[16] = {
+ 0x34,0x74,0xb4,
+ 0x23,0x63,0xa3,
+ 0x12,0x52,0x92,
+ 0x01,0x41,0x81,
+ 0x00,0x40,0x80,
+ 0xff
+ };
+ static const unsigned short colortharray[6] = {
+ 1, 1, 2, 2, 3, 4
+ };
- } else {
+ i = 0;
- do {
- B = SiS_CalcDelay2(SiS_Pr, FQBQData[i], HwInfo) * VCLK * colorth;
- bl = B / (MCLK * 16);
+ if(ModeNo > 0x13) {
- if(B == bl * 16 * MCLK) {
- bl = bl + 1;
- } else {
- bl = bl + 2;
- }
+ /* Get VCLK */
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
+ }
- if(bl > 0x13) {
- if(FQBQData[i+1] == 0xFF) {
- ThresholdLow = 0x13;
- break;
- }
- i++;
- } else {
- ThresholdLow = bl;
- break;
- }
- } while(FQBQData[i] != 0xFF);
- }
- }
- else {
- if(HwInfo->jChipType == SIS_730) {
- } else {
- i = 9;
- }
- ThresholdLow = 0x02;
- }
+ /* Get MCLK * 16 */
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
+ MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
+
+ /* Get half colordepth */
+ colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+ if(SiS_Pr->ChipType == SIS_730) {
+ queuedata = &FQBQData730[0];
+ } else {
+ queuedata = &FQBQData[0];
+ }
+
+ do {
+ templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
+
+ datal = templ % MCLK16;
+ templ = (templ / MCLK16) + 1;
+ if(datal) templ++;
+
+ if(templ > 0x13) {
+ if(queuedata[i + 1] == 0xFF) {
+ ThresholdLow = 0x13;
+ break;
+ }
+ i++;
+ } else {
+ ThresholdLow = templ;
+ break;
+ }
+ } while(queuedata[i] != 0xFF);
+
+ } else {
+
+ if(SiS_Pr->ChipType != SIS_730) i = 9;
+ ThresholdLow = 0x02;
+
+ }
+
+ /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+ data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+
+ data = (ThresholdLow & 0x10) << 1;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+
+ /* What is this? */
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+ /* Write CRT/CPU threshold high (gap = 3) */
+ data = ThresholdLow + 3;
+ if(data > 0x0f) data = 0x0f;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
/* Write foreground and background queue */
- if(HwInfo->jChipType == SIS_730) {
-
- data2 = FQBQData730[i];
- data2 = (data2 & 0xC0) >> 5;
- data2 <<= 8;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xfffff9ff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
+#ifdef SIS_LINUX_KERNEL
+ templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
#else
- /* We use pci functions X offers. We use pcitag 0, because
- * we want to read/write to the host bridge (which is always
- * 00:00.0 on 630, 730 and 540), not the VGA device.
- */
- eax = pciReadLong(0x00000000, 0x50);
- eax &= 0xfffff9ff;
- eax |= data2;
- pciWriteLong(0x00000000, 0x50, eax);
+ templ = pciReadLong(0x00000000, 0x50);
#endif
- /* Write GUI grant timer (PCI config 0xA3) */
- data2 = FQBQData730[i] << 8;
- data2 = (data2 & 0x0f00) | ((data2 & 0x3000) >> 8);
- data2 <<= 20;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0x00ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
-#else
- eax = pciReadLong(0x00000000, 0xA0);
- eax &= 0x00ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0xA0, eax);
-#endif
+ if(SiS_Pr->ChipType == SIS_730) {
- } else {
+ templ &= 0xfffff9ff;
+ templ |= ((queuedata[i] & 0xc0) << 3);
- data2 = FQBQData[i];
- data2 = (data2 & 0xf0) >> 4;
- data2 <<= 24;
+ } else {
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xf0ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
-#else
- eax = pciReadLong(0x00000000, 0x50);
- eax &= 0xf0ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0x50, eax);
-#endif
+ templ &= 0xf0ffffff;
+ if( (ModeNo <= 0x13) &&
+ (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
+ templ |= 0x0b000000;
+ } else {
+ templ |= ((queuedata[i] & 0xf0) << 20);
+ }
+
+ }
- /* Write GUI grant timer (PCI config 0xA3) */
- data2 = FQBQData[i];
- data2 &= 0x0f;
- data2 <<= 24;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
- eax &= 0xf0ffffff;
- eax |= data2;
- SiS_SetRegLong(0xcfc,eax);
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
+ templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
#else
- eax = pciReadLong(0x00000000, 0xA0);
- eax &= 0xf0ffffff;
- eax |= data2;
- pciWriteLong(0x00000000, 0xA0, eax);
+ pciWriteLong(0x00000000, 0x50, templ);
+ templ = pciReadLong(0x00000000, 0xA0);
#endif
- }
+ /* GUI grant timer (PCI config 0xA3) */
+ if(SiS_Pr->ChipType == SIS_730) {
+
+ templ &= 0x00ffffff;
+ datal = queuedata[i] << 8;
+ templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
- /* Write CRT/CPU threshold low, CRT/Engine threshold high */
- data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+ } else {
- data = (ThresholdLow & 0x10) << 1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+ templ &= 0xf0ffffff;
+ templ |= ((queuedata[i] & 0x0f) << 24);
- /* What is this? */
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+ }
- /* Write CRT/CPU threshold high (gap = 3) */
- data = ThresholdLow + 3;
- if(data > 0x0f) data = 0x0f;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
-}
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
+#else
+ pciWriteLong(0x00000000, 0xA0, templ);
#endif
+}
+#endif /* SIS300 */
#ifdef SIS315H
static void
-SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT modeflag;
-
- /* disable auto-threshold */
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
-
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
-
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
- if(ModeNo > 0x13) {
- if(HwInfo->jChipType >= SIS_661) {
- if(!(modeflag & HalfDCLK)) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
- }
- } else {
- if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
- }
- }
- }
+ unsigned short modeflag;
+
+ /* disable auto-threshold */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
+
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->ChipType >= XGI_20) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ } else if(SiS_Pr->ChipType >= SIS_661) {
+ if(!(modeflag & HalfDCLK)) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ }
+ } else {
+ if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+ }
+ }
+ }
}
#endif
@@ -2851,385 +2597,370 @@ SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetVCLKState(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT RefreshRateTableIndex,
- USHORT ModeIdIndex)
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
{
- USHORT data=0, VCLK=0, index=0;
+ unsigned short data = 0, VCLK = 0, index = 0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->UseCustomMode) {
- VCLK = SiS_Pr->CSRClock;
- } else {
- index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- }
- }
-
- if(HwInfo->jChipType < SIS_315H) {
-
- if(VCLK > 150) data |= 0x80;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
-
- data = 0x00;
- if(VCLK >= 150) data |= 0x08;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->UseCustomMode) {
+ VCLK = SiS_Pr->CSRClock;
+ } else {
+ index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+ }
+ }
- } else {
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ if(VCLK > 150) data |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
- if(VCLK >= 166) data |= 0x0c;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+ data = 0x00;
+ if(VCLK >= 150) data |= 0x08;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+#endif
+ } else if(SiS_Pr->ChipType < XGI_20) {
+#ifdef SIS315H
+ if(VCLK >= 166) data |= 0x0c;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
- if(VCLK >= 166) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
- }
- }
+ if(VCLK >= 166) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ if(VCLK >= 200) data |= 0x0c;
+ if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+ if(SiS_Pr->ChipType != XGI_20) {
+ data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
+ if(VCLK < 200) data |= 0x10;
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
+ }
+#endif
+ }
- /* DAC speed */
- if(HwInfo->jChipType >= SIS_661) {
+ /* DAC speed */
+ if(SiS_Pr->ChipType >= SIS_661) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
- } else {
+ } else {
- data = 0x03;
- if((VCLK >= 135) && (VCLK < 160)) data = 0x02;
- else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
- else if(VCLK >= 260) data = 0x00;
+ data = 0x03;
+ if(VCLK >= 260) data = 0x00;
+ else if(VCLK >= 160) data = 0x01;
+ else if(VCLK >= 135) data = 0x02;
- if(HwInfo->jChipType == SIS_540) {
- if((VCLK == 203) || (VCLK < 234)) data = 0x02;
- }
+ if(SiS_Pr->ChipType == SIS_540) {
+ if((VCLK == 203) || (VCLK < 234)) data = 0x02;
+ }
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
- } else {
- if(HwInfo->jChipType > SIS_315PRO) {
- if(ModeNo > 0x13) data &= 0xfc;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
- }
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+ } else {
+ if(SiS_Pr->ChipType > SIS_315PRO) {
+ if(ModeNo > 0x13) data &= 0xfc;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
+ }
- }
+ }
}
static void
-SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
- USHORT data,infoflag=0,modeflag;
- USHORT resindex,xres;
+ unsigned short data, infoflag = 0, modeflag, resindex;
#ifdef SIS315H
- USHORT data2,data3;
- ULONG longdata;
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short data2, data3;
#endif
- if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- infoflag = SiS_Pr->CInfoFlag;
- xres = SiS_Pr->CHDisplay;
- } else {
- resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(ModeNo > 0x13) {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
- } else {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
- }
- }
-
- /* Disable DPMS */
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
-
- data = 0;
- if(ModeNo > 0x13) {
- if(SiS_Pr->SiS_ModeType > ModeEGA) {
- data |= 0x02;
- data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
- }
- if(infoflag & InterlaceMode) data |= 0x20;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
-
- if(HwInfo->jChipType != SIS_300) {
- data = 0;
- if(infoflag & InterlaceMode) {
- if(xres <= 800) data = 0x0020;
- else if(xres <= 1024) data = 0x0035;
- else data = 0x0048;
- }
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
- }
-
- if(modeflag & HalfDCLK) {
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
- }
-
- data = 0;
- if(modeflag & LineCompareOff) data = 0x08;
- if(HwInfo->jChipType == SIS_300) {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
- if(SiS_Pr->SiS_ModeType == ModeEGA) {
- if(ModeNo > 0x13) {
- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
- }
- }
- }
-
- if(HwInfo->jChipType >= SIS_661) {
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ } else {
+ resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ if(ModeNo > 0x13) {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+ }
+ }
+
+ /* Disable DPMS */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
+
+ data = 0;
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->SiS_ModeType > ModeEGA) {
+ data |= 0x02;
+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+ }
+ if(infoflag & InterlaceMode) data |= 0x20;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
+
+ if(SiS_Pr->ChipType != SIS_300) {
+ data = 0;
+ if(infoflag & InterlaceMode) {
+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+ int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
+ ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
+ int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
+ ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
+ data = hrs - (hto >> 1) + 3;
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
+ }
+
+ if(modeflag & HalfDCLK) {
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
+ }
+
+ data = 0;
+ if(modeflag & LineCompareOff) data = 0x08;
+ if(SiS_Pr->ChipType == SIS_300) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
+ } else {
+ if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
+ if(SiS_Pr->SiS_ModeType == ModeEGA) {
+ if(ModeNo > 0x13) {
+ data |= 0x40;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
+ }
#ifdef SIS315H
- if(HwInfo->jChipType == SIS_315PRO) {
-
- data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- data = SiS_Pr->SiS_SR15[2][data];
- if(SiS_Pr->SiS_ModeType == ModeText) {
- data &= 0xc7;
- } else {
- data2 = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- data2 >>= 1;
- if(infoflag & InterlaceMode) data2 >>= 1;
- data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
- if(!data3) data3++;
- data2 /= data3;
- if(data2 >= 0x50) {
- data &= 0x0f;
- data |= 0x50;
- }
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-
- } else if( (HwInfo->jChipType == SIS_330) ||
- ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
-
- data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
- if(HwInfo->jChipType == SIS_330) {
- data = SiS_Pr->SiS_SR15[2][data];
- } else {
- if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6];
- else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
- else data = 0xba;
- }
- if(SiS_Pr->SiS_ModeType <= ModeEGA) {
- data &= 0xc7;
- } else {
- if(SiS_Pr->UseCustomMode) {
- data2 = SiS_Pr->CSRClock;
- } else {
- data2 = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+ }
- data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
- if(data3) data2 *= data3;
-
- longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
-
- data2 = longdata / data2;
-
- if(HwInfo->jChipType == SIS_330) {
- if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
- if (data2 >= 0x19c) data = 0xba;
- else if(data2 >= 0x140) data = 0x7a;
- else if(data2 >= 0x101) data = 0x3a;
- else if(data2 >= 0xf5) data = 0x32;
- else if(data2 >= 0xe2) data = 0x2a;
- else if(data2 >= 0xc4) data = 0x22;
- else if(data2 >= 0xac) data = 0x1a;
- else if(data2 >= 0x9e) data = 0x12;
- else if(data2 >= 0x8e) data = 0x0a;
- else data = 0x02;
- } else {
- if(data2 >= 0x127) data = 0xba;
- else data = 0x7a;
- }
- } else { /* 760+LFB */
- if (data2 >= 0x190) data = 0xba;
- else if(data2 >= 0xff) data = 0x7a;
- else if(data2 >= 0xd3) data = 0x3a;
- else if(data2 >= 0xa9) data = 0x1a;
- else if(data2 >= 0x93) data = 0x0a;
- else data = 0x02;
- }
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
- } else if(HwInfo->jChipType == SIS_340) {
- /* TODO */
- }
+ if(SiS_Pr->ChipType == SIS_315PRO) {
+
+ data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
+ if(SiS_Pr->SiS_ModeType == ModeText) {
+ data &= 0xc7;
+ } else {
+ data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
+ if(infoflag & InterlaceMode) data2 >>= 1;
+ data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+ if(data3) data2 /= data3;
+ if(data2 >= 0x50) {
+ data &= 0x0f;
+ data |= 0x50;
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+ } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
+
+ data = SiS_Get310DRAMType(SiS_Pr);
+ if(SiS_Pr->ChipType == SIS_330) {
+ data = SiS_Pr->SiS_SR15[(2 * 4) + data];
+ } else {
+ if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6];
+ else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+ else data = 0xba;
+ }
+ if(SiS_Pr->SiS_ModeType <= ModeEGA) {
+ data &= 0xc7;
+ } else {
+ if(SiS_Pr->UseCustomMode) {
+ data2 = SiS_Pr->CSRClock;
+ } else {
+ data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+ data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
+ }
+
+ data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+ if(data3) data2 *= data3;
+
+ data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
+
+ if(SiS_Pr->ChipType == SIS_330) {
+ if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+ if (data2 >= 0x19c) data = 0xba;
+ else if(data2 >= 0x140) data = 0x7a;
+ else if(data2 >= 0x101) data = 0x3a;
+ else if(data2 >= 0xf5) data = 0x32;
+ else if(data2 >= 0xe2) data = 0x2a;
+ else if(data2 >= 0xc4) data = 0x22;
+ else if(data2 >= 0xac) data = 0x1a;
+ else if(data2 >= 0x9e) data = 0x12;
+ else if(data2 >= 0x8e) data = 0x0a;
+ else data = 0x02;
+ } else {
+ if(data2 >= 0x127) data = 0xba;
+ else data = 0x7a;
+ }
+ } else { /* 76x+LFB */
+ if (data2 >= 0x190) data = 0xba;
+ else if(data2 >= 0xff) data = 0x7a;
+ else if(data2 >= 0xd3) data = 0x3a;
+ else if(data2 >= 0xa9) data = 0x1a;
+ else if(data2 >= 0x93) data = 0x0a;
+ else data = 0x02;
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+ }
+ /* XGI: Nothing. */
+ /* TODO: Check SiS340 */
#endif
- data = 0x60;
- if(SiS_Pr->SiS_ModeType != ModeText) {
- data ^= 0x60;
- if(SiS_Pr->SiS_ModeType != ModeEGA) {
- data ^= 0xA0;
- }
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
+ data = 0x60;
+ if(SiS_Pr->SiS_ModeType != ModeText) {
+ data ^= 0x60;
+ if(SiS_Pr->SiS_ModeType != ModeEGA) {
+ data ^= 0xA0;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
- SiS_SetVCLKState(SiS_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex);
+ SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
- } else {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
- }
- }
+ if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
+ (SiS_Pr->ChipType == XGI_40)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
+ }
+ } else if(SiS_Pr->ChipType == XGI_20) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
+ } else {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
+ }
#endif
}
-/*********************************************/
-/* LOAD DAC */
-/*********************************************/
-
-#if 0
+#ifdef SIS315H
static void
-SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port)
+SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
{
+#if 0
+ /* TODO: Find out about IOAddress2 */
+ SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
+ SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
+ SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
int i;
- OutPortByte(port, 0);
- port++;
- for (i=0; i < (256 * 3); i++) {
- OutPortByte(port, 0);
+ if((SiS_Pr->ChipRevision != 0) ||
+ (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
+ return;
+
+ for(i = 0; i <= 4; i++) { /* SR00 - SR04 */
+ SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
}
+ for(i = 0; i <= 8; i++) { /* GR00 - GR08 */
+ SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
+ }
+ SiS_SetReg(P2_3c4,0x05,0x86);
+ SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06)); /* SR06 */
+ SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21)); /* SR21 */
+ SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc)); /* MISC */
+ SiS_SetReg(P2_3c4,0x05,0x00);
+#endif
}
#endif
+/*********************************************/
+/* LOAD DAC */
+/*********************************************/
+
static void
-SiS_WriteDAC(SiS_Private *SiS_Pr, SISIOADDRESS DACData, USHORT shiftflag,
- USHORT dl, USHORT ah, USHORT al, USHORT dh)
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
+ unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
{
- USHORT temp,bh,bl;
-
- bh = ah;
- bl = al;
- if(dl != 0) {
- temp = bh;
- bh = dh;
- dh = temp;
- if(dl == 1) {
- temp = bl;
- bl = dh;
- dh = temp;
- } else {
- temp = bl;
- bl = bh;
- bh = temp;
- }
- }
- if(shiftflag) {
- dh <<= 2;
- bh <<= 2;
- bl <<= 2;
- }
- SiS_SetRegByte(DACData,(USHORT)dh);
- SiS_SetRegByte(DACData,(USHORT)bh);
- SiS_SetRegByte(DACData,(USHORT)bl);
+ unsigned short d1, d2, d3;
+
+ switch(dl) {
+ case 0: d1 = dh; d2 = ah; d3 = al; break;
+ case 1: d1 = ah; d2 = al; d3 = dh; break;
+ default: d1 = al; d2 = dh; d3 = ah;
+ }
+ SiS_SetRegByte(DACData, (d1 << shiftflag));
+ SiS_SetRegByte(DACData, (d2 << shiftflag));
+ SiS_SetRegByte(DACData, (d3 << shiftflag));
}
void
-SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT data,data2;
- USHORT time,i,j,k,m,n,o;
- USHORT si,di,bx,dl,al,ah,dh;
- USHORT shiftflag;
+ unsigned short data, data2, time, i, j, k, m, n, o;
+ unsigned short si, di, bx, sf;
SISIOADDRESS DACAddr, DACData;
- const USHORT *table = NULL;
+ const unsigned char *table = NULL;
- if(ModeNo <= 0x13) {
- data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- if(SiS_Pr->UseCustomMode) {
- data = SiS_Pr->CModeFlag;
- } else {
- data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
- }
+ data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
- data &= DACInfoFlag;
- time = 64;
- if(data == 0x00) table = SiS_MDA_DAC;
- if(data == 0x08) table = SiS_CGA_DAC;
- if(data == 0x10) table = SiS_EGA_DAC;
- if(data == 0x18) {
+ j = time = 64;
+ if(data == 0x00) table = SiS_MDA_DAC;
+ else if(data == 0x08) table = SiS_CGA_DAC;
+ else if(data == 0x10) table = SiS_EGA_DAC;
+ else if(data == 0x18) {
+ j = 16;
time = 256;
table = SiS_VGA_DAC;
}
- if(time == 256) j = 16;
- else j = time;
if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */
(SiS_Pr->SiS_VBType & VB_NoLCD) ) ||
(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */
(!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */
+ SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
DACAddr = SiS_Pr->SiS_P3c8;
DACData = SiS_Pr->SiS_P3c9;
- shiftflag = 0;
- SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
+ sf = 0;
} else {
- shiftflag = 1;
DACAddr = SiS_Pr->SiS_Part5Port;
DACData = SiS_Pr->SiS_Part5Port + 1;
+ sf = 2;
}
SiS_SetRegByte(DACAddr,0x00);
- for(i=0; i<j; i++) {
+ for(i = 0; i < j; i++) {
data = table[i];
- for(k=0; k<3; k++) {
+ for(k = 0; k < 3; k++) {
data2 = 0;
- if(data & 0x01) data2 = 0x2A;
+ if(data & 0x01) data2 += 0x2A;
if(data & 0x02) data2 += 0x15;
- if(shiftflag) data2 <<= 2;
- SiS_SetRegByte(DACData, data2);
+ SiS_SetRegByte(DACData, (data2 << sf));
data >>= 2;
}
}
if(time == 256) {
for(i = 16; i < 32; i++) {
- data = table[i];
- if(shiftflag) data <<= 2;
+ data = table[i] << sf;
for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
}
si = 32;
for(m = 0; m < 9; m++) {
- di = si;
- bx = si + 4;
- dl = 0;
- for(n = 0; n < 3; n++) {
- for(o = 0; o < 5; o++) {
- dh = table[si];
- ah = table[di];
- al = table[bx];
+ di = si;
+ bx = si + 4;
+ for(n = 0; n < 3; n++) {
+ for(o = 0; o < 5; o++) {
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
si++;
- SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
}
si -= 2;
for(o = 0; o < 3; o++) {
- dh = table[bx];
- ah = table[di];
- al = table[si];
+ SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
si--;
- SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
}
- dl++;
} /* for n < 3 */
si += 5;
} /* for m < 9 */
@@ -3241,89 +2972,114 @@ SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT StandTableIndex,RefreshRateTableIndex;
-
- SiS_Pr->SiS_CRT1Mode = ModeNo;
- StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
- SiS_DisableBridge(SiS_Pr, HwInfo);
- }
- }
-
- SiS_ResetSegmentRegisters(SiS_Pr, HwInfo);
-
- SiS_SetSeqRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetMiscRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
- SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
- SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
- SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
- SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
-
- SiS_Pr->SiS_SelectCRT2Rate = 0;
- SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-
-#ifdef LINUX_XF86
- xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
+ unsigned short StandTableIndex, RefreshRateTableIndex;
+
+ SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+ StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
+ SiS_DisableBridge(SiS_Pr);
+ }
+ }
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
+
+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+ SiS_ResetCRT1VCLK(SiS_Pr);
+
+ SiS_Pr->SiS_SelectCRT2Rate = 0;
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+
+#ifdef SIS_XORG_XF86
+ xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
#endif
- if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ }
- RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
+ }
- if(RefreshRateTableIndex != 0xFFFF) {
- SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
- SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
- }
+ if(RefreshRateTableIndex != 0xFFFF) {
+ SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ switch(SiS_Pr->ChipType) {
#ifdef SIS300
- if(HwInfo->jChipType == SIS_300) {
- SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo,HwInfo,RefreshRateTableIndex);
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ||
- (HwInfo->jChipType == SIS_540)) {
- SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, HwInfo, RefreshRateTableIndex);
- }
+ case SIS_300:
+ SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
+ break;
+ case SIS_540:
+ case SIS_630:
+ case SIS_730:
+ SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
+ break;
#endif
+ default:
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- }
+ if(SiS_Pr->ChipType == XGI_20) {
+ unsigned char sr2b = 0, sr2c = 0;
+ switch(ModeNo) {
+ case 0x00:
+ case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
+ case 0x04:
+ case 0x05:
+ case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
+ }
+ if(sr2b) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
+ SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
+ }
+ }
+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
#endif
+ break;
+ }
+
+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- SiS_SetCRT1ModeRegs(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == XGI_40) {
+ SiS_SetupDualChip(SiS_Pr);
+ }
+#endif
- SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
-#ifdef LINUX_KERNEL
- if(SiS_Pr->SiS_flag_clearbuffer) {
- SiS_ClearBuffer(SiS_Pr,HwInfo,ModeNo);
- }
+#ifdef SIS_LINUX_KERNEL
+ if(SiS_Pr->SiS_flag_clearbuffer) {
+ SiS_ClearBuffer(SiS_Pr, ModeNo);
+ }
#endif
- if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
- SiS_WaitRetrace1(SiS_Pr);
- SiS_DisplayOn(SiS_Pr);
- }
+ if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
+ SiS_WaitRetrace1(SiS_Pr);
+ SiS_DisplayOn(SiS_Pr);
+ }
}
/*********************************************/
@@ -3331,33 +3087,62 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
static void
-SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_InitVB(struct SiS_Private *SiS_Pr)
+{
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+
+ SiS_Pr->Init_P4_0E = 0;
+ if(SiS_Pr->SiS_ROMNew) {
+ SiS_Pr->Init_P4_0E = ROMAddr[0x82];
+ } else if(SiS_Pr->ChipType >= XGI_40) {
+ if(SiS_Pr->SiS_XGIROM) {
+ SiS_Pr->Init_P4_0E = ROMAddr[0x80];
+ }
+ }
+}
+
+static void
+SiS_ResetVB(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp;
+#ifdef SIS315H
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp;
/* VB programming clock */
if(SiS_Pr->SiS_UseROM) {
- if(HwInfo->jChipType < SIS_330) {
- temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+ if(SiS_Pr->ChipType < SIS_330) {
+ temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
- } else if(HwInfo->jChipType >= SIS_661) {
- temp = ROMAddr[0x7e] | 0x40;
- if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+ } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
+ temp = ROMAddr[0x7e] | 0x40;
+ if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
}
+ } else if(SiS_Pr->ChipType >= XGI_40) {
+ temp = 0x40;
+ if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
+ /* Can we do this on any chipset? */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
}
+#endif
}
/*********************************************/
-/* HELPER: SET VIDEO REGISTERS */
+/* HELPER: SET VIDEO/CAPTURE REGISTERS */
/*********************************************/
static void
-SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
{
- if((IS_SIS651) || (IS_SISM650)) {
+ /* SiS65x and XGI set up some sort of "lock mode" for text
+ * which locks CRT2 in some way to CRT1 timing. Disable
+ * this here.
+ */
+#ifdef SIS315H
+ if((IS_SIS651) || (IS_SISM650) ||
+ SiS_Pr->ChipType == SIS_340 ||
+ SiS_Pr->ChipType == XGI_40) {
SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */
SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */
@@ -3365,49 +3150,99 @@ SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
}
/* !!! This does not support modes < 0x13 !!! */
+#endif
}
/*********************************************/
-/* XFree86: SET SCREEN PITCH */
+/* HELPER: SET AGP TIMING FOR SiS760 */
/*********************************************/
-#ifdef LINUX_XF86
static void
-SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_Handle760(struct SiS_Private *SiS_Pr)
+{
+#ifdef SIS315H
+ unsigned int somebase;
+ unsigned char temp1, temp2, temp3;
+
+ if( (SiS_Pr->ChipType != SIS_760) ||
+ ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
+ (!(SiS_Pr->SiS_SysFlags & SF_760LFB)) ||
+ (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
+ return;
+
+#ifdef SIS_LINUX_KERNEL
+ somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
+#else
+ somebase = pciReadWord(0x00001000, 0x74);
+#endif
+ somebase &= 0xffff;
+
+ if(somebase == 0) return;
+
+ temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
+
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+ temp1 = 0x21;
+ temp2 = 0x03;
+ temp3 |= 0x08;
+ } else {
+ temp1 = 0x25;
+ temp2 = 0x0b;
+ }
+
+#ifdef SIS_LINUX_KERNEL
+ sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
+ sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
+#else
+ pciWriteByte(0x00000000, 0x7e, temp1);
+ pciWriteByte(0x00000000, 0x8d, temp2);
+#endif
+
+ SiS_SetRegByte((somebase + 0x85), temp3);
+#endif
+}
+
+/*********************************************/
+/* X.org/XFree86: SET SCREEN PITCH */
+/*********************************************/
+
+#ifdef SIS_XORG_XF86
+static void
+SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort HDisplay = pSiS->scrnPitch >> 3;
+ unsigned short HDisplay = pSiS->scrnPitch >> 3;
SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay>>8));
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
}
static void
-SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort HDisplay = pSiS->scrnPitch2 >> 3;
+ unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
/* Unlock CRT2 */
if(pSiS->VGAEngine == SIS_315_VGA)
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
else
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
}
static void
-SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
BOOLEAN isslavemode = FALSE;
- if( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
+ if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
( ((pSiS->VGAEngine == SIS_300_VGA) &&
- (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
- ((pSiS->VGAEngine == SIS_315_VGA) &&
+ (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
+ ((pSiS->VGAEngine == SIS_315_VGA) &&
(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
isslavemode = TRUE;
}
@@ -3427,59 +3262,59 @@ SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
/* SiSSetMode() */
/*********************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
/* We need pScrn for setting the pitch correctly */
BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch)
+SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
#else
BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
+SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
#endif
{
- USHORT ModeIdIndex;
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- unsigned char backupreg=0;
-#ifdef LINUX_KERNEL
- USHORT KeepLockReg;
- ULONG temp;
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+ unsigned short RealModeNo, ModeIdIndex;
+ unsigned char backupreg = 0;
+#ifdef SIS_LINUX_KERNEL
+ unsigned short KeepLockReg;
SiS_Pr->UseCustomMode = FALSE;
SiS_Pr->CRT1UsesCustomMode = FALSE;
#endif
+ SiS_Pr->SiS_flag_clearbuffer = 0;
+
if(SiS_Pr->UseCustomMode) {
ModeNo = 0xfe;
+ } else {
+#ifdef SIS_LINUX_KERNEL
+ if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
+#endif
+ ModeNo &= 0x7f;
}
- SiSInitPtr(SiS_Pr, HwInfo);
+ /* Don't use FSTN mode for CRT1 */
+ RealModeNo = ModeNo;
+ if(ModeNo == 0x5b) ModeNo = 0x56;
+
+ SiSInitPtr(SiS_Pr);
SiSRegInit(SiS_Pr, BaseAddr);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
+ SiS_GetSysFlags(SiS_Pr);
-#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiS_Pr->SiS_VGAINFO = 0x11;
+#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
- else
-#endif
- SiS_Pr->SiS_VGAINFO = 0x11;
-
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
- SiS_Pr->SiS_flag_clearbuffer = 0;
-
- if(!SiS_Pr->UseCustomMode) {
-#ifdef LINUX_KERNEL
- if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
#endif
- ModeNo &= 0x7f;
- }
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
#endif
SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
+
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3487,13 +3322,13 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
ModeIdIndex = 0;
}
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
/* Init/restore some VB registers */
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_ResetVB(SiS_Pr, HwInfo);
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_ResetVB(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -3503,21 +3338,20 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
}
/* Get VB information (connectors, connected devices) */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, (SiS_Pr->UseCustomMode) ? 0 : 1);
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
-
-#ifdef LINUX_KERNEL
- /* 3. Check memory size (Kernel framebuffer driver only) */
- temp = SiS_CheckMemorySize(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
- if(!temp) return(0);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+#ifdef SIS_LINUX_KERNEL
+ /* Check memory size (kernel framebuffer driver only) */
+ if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
+ return FALSE;
+ }
#endif
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- }
+ SiS_OpenCRTC(SiS_Pr);
if(SiS_Pr->UseCustomMode) {
SiS_Pr->CRT1UsesCustomMode = TRUE;
@@ -3530,38 +3364,41 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
/* Set mode on CRT1 */
if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
(!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
- SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
}
/* Set mode on CRT2 */
if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
- (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
- (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
- (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+ (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
+ (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
+ SiS_SetCRT2Group(SiS_Pr, RealModeNo);
}
}
SiS_HandleCRT1(SiS_Pr);
- SiS_StrangeStuff(SiS_Pr, HwInfo);
+ SiS_StrangeStuff(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(HwInfo->jChipType >= SIS_315H) {
+#ifdef SIS315H
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
}
+#endif
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- if(!SiS_Pr->SiS_ROMNew) {
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+ if(!SiS_Pr->SiS_ROMNew) {
+ if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
} else {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3574,23 +3411,24 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
if((ModeNo == 0x03) || (ModeNo == 0x10)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
- }
+ }
}
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
+#endif
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
if(pScrn) {
/* SetPitch: Adapt to virtual size & position */
if((ModeNo > 0x13) && (dosetpitch)) {
- SiS_SetPitch(SiS_Pr, pScrn);
+ SiS_SetPitch(SiS_Pr, pScrn);
}
/* Backup/Set ModeNo in BIOS scratch area */
@@ -3598,33 +3436,37 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
}
#endif
-#ifdef LINUX_KERNEL /* We never lock registers in XF86 */
- if(KeepLockReg == 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- else SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
+ SiS_CloseCRTC(SiS_Pr);
+
+ SiS_Handle760(SiS_Pr);
+
+#ifdef SIS_LINUX_KERNEL
+ /* We never lock registers in XF86 */
+ if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
#endif
return TRUE;
}
/*********************************************/
-/* XFree86: SiSBIOSSetMode() */
+/* X.org/XFree86: SiSBIOSSetMode() */
/* for non-Dual-Head mode */
/*********************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
BOOLEAN
-SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
SISPtr pSiS = SISPTR(pScrn);
- UShort ModeNo = 0;
+ unsigned short ModeNo = 0;
SiS_Pr->UseCustomMode = FALSE;
if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
- SiS_Pr->CHDisplay,
+ SiS_Pr->CHDisplay,
(mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
(mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
SiS_Pr->CVDisplay)));
@@ -3632,32 +3474,33 @@ SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
/* Don't need vbflags here; checks done earlier */
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
+ ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
if(!ModeNo) return FALSE;
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
}
- return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE));
+ return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
}
/*********************************************/
-/* XFree86: SiSBIOSSetModeCRT2() */
+/* X.org/XFree86: SiSBIOSSetModeCRT2() */
/* for Dual-Head modes */
/*********************************************/
+
BOOLEAN
-SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
- USHORT ModeIdIndex;
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- UShort ModeNo = 0;
- unsigned char backupreg=0;
- SISPtr pSiS = SISPTR(pScrn);
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+ SISPtr pSiS = SISPTR(pScrn);
#ifdef SISDUALHEAD
SISEntPtr pSiSEnt = pSiS->entityPrivate;
#endif
+ unsigned short ModeIdIndex;
+ unsigned short ModeNo = 0;
+ unsigned char backupreg = 0;
SiS_Pr->UseCustomMode = FALSE;
@@ -3672,22 +3515,25 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
- if(!ModeNo) return FALSE;
+ ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
+ if(!ModeNo) return FALSE;
}
SiSRegInit(SiS_Pr, BaseAddr);
- SiSInitPtr(SiS_Pr, HwInfo);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiSInitPtr(SiS_Pr);
+ SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
#else
SiS_Pr->SiS_VGAINFO = 0x11;
#endif
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
+
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
+
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
/* Save mode info so we can set it from within SetMode for CRT1 */
#ifdef SISDUALHEAD
@@ -3700,23 +3546,20 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
#if 0
- /* We can't set CRT2 mode before CRT1 mode is set */
+ /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
if(pSiSEnt->CRT1ModeNo == -1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting CRT2 mode delayed until after setting CRT1 mode\n");
- return TRUE;
+ return TRUE;
}
#endif
pSiSEnt->CRT2ModeSet = TRUE;
}
#endif
- /* We don't clear the buffer in X */
- SiS_Pr->SiS_flag_clearbuffer=0;
-
if(SiS_Pr->UseCustomMode) {
- USHORT temptemp = SiS_Pr->CVDisplay;
+ unsigned short temptemp = SiS_Pr->CVDisplay;
if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
@@ -3728,13 +3571,11 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
} else {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
- "Setting standard mode 0x%x on CRT2\n", ModeNo);
+ "Setting standard mode 0x%x on CRT2\n", ModeNo);
}
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3742,56 +3583,59 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
ModeIdIndex = 0;
}
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_ResetVB(SiS_Pr, HwInfo);
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_ResetVB(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
- backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
} else {
- backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
}
}
/* Get VB information (connectors, connected devices) */
if(!SiS_Pr->UseCustomMode) {
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 1);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
} else {
/* If this is a custom mode, we don't check the modeflag for CRT2Mode */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
}
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+ SiS_ResetSegmentRegisters(SiS_Pr);
/* Set mode on CRT2 */
if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
(SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
(SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ SiS_SetCRT2Group(SiS_Pr, ModeNo);
}
- SiS_StrangeStuff(SiS_Pr, HwInfo);
+ SiS_StrangeStuff(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
- if(!SiS_Pr->SiS_ROMNew) {
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(!SiS_Pr->SiS_ROMNew) {
+ if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
} else {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3803,8 +3647,8 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
@@ -3812,25 +3656,27 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
/* SetPitch: Adapt to virtual size & position */
SiS_SetPitchCRT2(SiS_Pr, pScrn);
+ SiS_Handle760(SiS_Pr);
+
return TRUE;
}
/*********************************************/
-/* XFree86: SiSBIOSSetModeCRT1() */
+/* X.org/XFree86: SiSBIOSSetModeCRT1() */
/* for Dual-Head modes */
/*********************************************/
BOOLEAN
-SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
DisplayModePtr mode, BOOLEAN IsCustom)
{
+ SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
SISPtr pSiS = SISPTR(pScrn);
- SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
- USHORT ModeIdIndex, ModeNo=0;
- UCHAR backupreg=0;
+ unsigned short ModeIdIndex, ModeNo = 0;
+ unsigned char backupreg = 0;
#ifdef SISDUALHEAD
SISEntPtr pSiSEnt = pSiS->entityPrivate;
- UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
+ unsigned char backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
BOOLEAN backupcustom;
#endif
@@ -3838,43 +3684,41 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
- USHORT temptemp = SiS_Pr->CVDisplay;
+ unsigned short temptemp = SiS_Pr->CVDisplay;
- if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
- else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
+ if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
+ else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting custom mode %dx%d on CRT1\n",
SiS_Pr->CHDisplay, temptemp);
ModeNo = 0xfe;
} else {
- ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
- if(!ModeNo) return FALSE;
+ ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
+ if(!ModeNo) return FALSE;
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting standard mode 0x%x on CRT1\n", ModeNo);
}
- SiSInitPtr(SiS_Pr, HwInfo);
+ SiSInitPtr(SiS_Pr);
SiSRegInit(SiS_Pr, BaseAddr);
- SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+ SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
#else
SiS_Pr->SiS_VGAINFO = 0x11;
#endif
- SiSInitPCIetc(SiS_Pr, HwInfo);
- SiSSetLVDSetc(SiS_Pr, HwInfo);
- SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
- /* We don't clear the buffer in X */
- SiS_Pr->SiS_flag_clearbuffer = 0;
SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiSInitPCIetc(SiS_Pr);
+ SiSSetLVDSetc(SiS_Pr);
+ SiSDetermineROMUsage(SiS_Pr);
+
+ SiS_UnLockCRT2(SiS_Pr);
if(!SiS_Pr->UseCustomMode) {
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3883,10 +3727,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
}
/* Determine VBType */
- SiS_GetVBType(SiS_Pr, HwInfo);
+ SiS_GetVBType(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
+ SiS_InitVB(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
} else {
backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3895,25 +3740,29 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
/* Get VB information (connectors, connected devices) */
/* (We don't care if the current mode is a CRT2 mode) */
- SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
- SiS_SetYPbPr(SiS_Pr, HwInfo);
- SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+ SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
+ SiS_SetYPbPr(SiS_Pr);
+ SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetLowModeTest(SiS_Pr, ModeNo);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetupCR5x(SiS_Pr, HwInfo);
- }
+ SiS_OpenCRTC(SiS_Pr);
/* Set mode on CRT1 */
- SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+ SiS_SetCRT2Group(SiS_Pr, ModeNo);
}
/* SetPitch: Adapt to virtual size & position */
SiS_SetPitchCRT1(SiS_Pr, pScrn);
+ SiS_HandleCRT1(SiS_Pr);
+
+ SiS_StrangeStuff(SiS_Pr);
+
+ SiS_CloseCRTC(SiS_Pr);
+
#ifdef SISDUALHEAD
if(pSiS->DualHeadMode) {
pSiSEnt->CRT1ModeNo = ModeNo;
@@ -3933,7 +3782,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
#ifdef SISDUALHEAD
if(pSiS->DualHeadMode) {
if(pSiSEnt->CRT2ModeNo != -1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"(Re-)Setting mode for CRT2\n");
backupcustom = SiS_Pr->UseCustomMode;
backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
@@ -3952,9 +3801,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
}
- SiSBIOSSetModeCRT2(SiS_Pr, HwInfo, pSiSEnt->pScrn_1,
+
+ SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
+
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
@@ -3970,22 +3821,20 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
* possibly overwritten
*/
- SiS_HandleCRT1(SiS_Pr);
-
- SiS_StrangeStuff(SiS_Pr, HwInfo);
-
SiS_DisplayOn(SiS_Pr);
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
- } else if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
+ } else if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
}
}
+ SiS_Handle760(SiS_Pr);
+
/* Backup/Set ModeNo in BIOS scratch area */
SiS_GetSetModeID(pScrn,ModeNo);
@@ -3993,84 +3842,6 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
}
#endif /* Linux_XF86 */
-
-#ifdef LINUX_XF86
-BOOLEAN
-SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- const USHORT PanelTypeTable300[16] = {
- 0xc101, 0xc117, 0x0121, 0xc135, 0xc142, 0xc152, 0xc162, 0xc072,
- 0xc181, 0xc192, 0xc1a1, 0xc1b6, 0xc1c2, 0xc0d2, 0xc1e2, 0xc1f2
- };
- const USHORT PanelTypeTable31030x[16] = {
- 0xc102, 0xc112, 0x0122, 0xc132, 0xc142, 0xc152, 0xc169, 0xc179,
- 0x0189, 0xc192, 0xc1a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
- const USHORT PanelTypeTable310LVDS[16] = {
- 0xc111, 0xc122, 0xc133, 0xc144, 0xc155, 0xc166, 0xc177, 0xc188,
- 0xc199, 0xc0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
- USHORT tempax,tempbx,temp;
-
- if(HwInfo->jChipType < SIS_315H) {
-
- tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempbx = tempax & 0x0F;
- if(!(tempax & 0x10)){
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1){
- tempbx = 0;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x38);
- if(temp & 0x40) tempbx |= 0x08;
- if(temp & 0x20) tempbx |= 0x02;
- if(temp & 0x01) tempbx |= 0x01;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x39);
- if(temp & 0x80) tempbx |= 0x04;
- } else {
- return 0;
- }
- }
- tempbx = PanelTypeTable300[tempbx];
- tempbx |= LCDSync;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
- temp = (tempbx & 0xFF00) >> 8;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
-
- } else {
-
- if(HwInfo->jChipType >= SIS_661) return 0;
-
- tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1a);
- tempax &= 0x1e;
- tempax >>= 1;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(tempax == 0) {
- /* TODO: Include HUGE detection routine
- (Probably not worth bothering)
- */
- return 0;
- }
- temp = tempax & 0xff;
- tempax--;
- tempbx = PanelTypeTable310LVDS[tempax];
- } else {
- tempbx = PanelTypeTable31030x[tempax];
- temp = tempbx & 0xff;
- }
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
- tempbx = (tempbx & 0xff00) >> 8;
- temp = tempbx & 0xc1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- temp = tempbx & 0x04;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp);
- }
-
- }
- return 1;
-}
-#endif
-
#ifndef GETBITSTR
#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
#define GENMASK(mask) BITMASK(1?mask,0?mask)
@@ -4078,26 +3849,28 @@ SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to))
#endif
-static void
-SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+void
+SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
{
+ int x = 1; /* Fix sync */
+
SiS_Pr->CCRT1CRTC[0] = ((SiS_Pr->CHTotal >> 3) - 5) & 0xff; /* CR0 */
SiS_Pr->CCRT1CRTC[1] = (SiS_Pr->CHDisplay >> 3) - 1; /* CR1 */
SiS_Pr->CCRT1CRTC[2] = (SiS_Pr->CHBlankStart >> 3) - 1; /* CR2 */
SiS_Pr->CCRT1CRTC[3] = (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; /* CR3 */
SiS_Pr->CCRT1CRTC[4] = (SiS_Pr->CHSyncStart >> 3) + 3; /* CR4 */
SiS_Pr->CCRT1CRTC[5] = ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | /* CR5 */
- (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+ (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
- SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */
- SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */
- | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
- | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
- | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+ SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */
+ SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */
+ | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+ | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
+ | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
| 0x10
- | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4)
- | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
- | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+ | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4)
+ | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+ | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* CR9 */
@@ -4106,55 +3879,44 @@ SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
else if(SiS_Pr->CHDisplay >= 640) SiS_Pr->CCRT1CRTC[16] |= 0x40;
}
-#if 0
- if (mode->VScan >= 32)
- regp->CRTC[9] |= 0x1F;
- else if (mode->VScan > 1)
- regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
- SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart ) & 0xFF; /* CR10 */
- SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd ) & 0x0F) | 0x80; /* CR11 */
+ SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart - x) & 0xFF; /* CR10 */
+ SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd - x) & 0x0F) | 0x80; /* CR11 */
SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay - 1) & 0xFF; /* CR12 */
SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF; /* CR15 */
SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd - 1) & 0xFF; /* CR16 */
SiS_Pr->CCRT1CRTC[13] = /* SRA */
- GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) |
- GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) |
- GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
- GETBITSTR((SiS_Pr->CVSyncStart ), 10:10, 3:3) |
- GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
- GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
+ GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) |
+ GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) |
+ GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+ GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
+ GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
+ GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
SiS_Pr->CCRT1CRTC[14] = /* SRB */
- GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
- GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
- GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
- GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
+ GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
+ GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
+ GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+ GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
SiS_Pr->CCRT1CRTC[15] = /* SRC */
- GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
- GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
+ GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+ GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
}
void
-SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex)
{
- USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
- int i,j;
+ unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
+ unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
+ int i, j;
/* 1:1 data: use data set by setcrt1crtc() */
if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
if(modeflag & HalfDCLK) VGAHDE >>= 1;
@@ -4164,32 +3926,91 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
- tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
- tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempax = SiS_Pr->PanelXRes;
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ tempbx = SiS_Pr->SiS_VGAHT;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempbx = SiS_Pr->PanelHT;
+ }
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ remaining = tempbx % 8;
+#endif
+ } else {
+#ifdef SIS315H
+ /* OK for LCDA, LVDS */
+ tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+ tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = SiS_Pr->PanelXRes;
+ }
+ tempbx += tempax;
+ if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+#endif
}
- tempbx += tempax;
- if(modeflag & HalfDCLK) tempbx -= VGAHDE;
SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
- tempax = VGAHDE;
- tempbx = SiS_Pr->CHTotal;
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempbx = SiS_Pr->PanelXRes;
- if(modeflag & HalfDCLK) tempbx >>= 1;
- tempax += ((tempbx - tempax) >> 1);
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
+ SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
+ SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->CHSyncStart >>= 1;
+ SiS_Pr->CHSyncEnd >>= 1;
+ }
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
+ tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
+ if(modeflag & HalfDCLK) {
+ tempax >>= 1;
+ tempbx >>= 1;
+ }
+ SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
+ tempax = SiS_Pr->PanelHRE + 7;
+ if(modeflag & HalfDCLK) tempax >>= 1;
+ SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
+ } else {
+ SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->CHSyncStart >>= 1;
+ tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
+ SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
+ } else {
+ SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
+ SiS_Pr->CHSyncStart += 8;
+ }
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ tempax = VGAHDE;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempbx = SiS_Pr->PanelXRes;
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ tempax += ((tempbx - tempax) >> 1);
+ }
+ tempax += SiS_Pr->PanelHRS;
+ SiS_Pr->CHSyncStart = tempax;
+ tempax += SiS_Pr->PanelHRE;
+ SiS_Pr->CHSyncEnd = tempax;
+#endif
}
- tempax += SiS_Pr->PanelHRS;
- SiS_Pr->CHSyncStart = tempax;
- tempax += SiS_Pr->PanelHRE;
- SiS_Pr->CHSyncEnd = tempax;
-
tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
tempax = SiS_Pr->SiS_VGAVDE;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
tempax = SiS_Pr->PanelYRes;
+ } else if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ /* Stupid hack for 640x400/320x200 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if((tempax + tempbx) == 438) tempbx += 16;
+ } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
+ tempax = 0;
+ tempbx = SiS_Pr->SiS_VGAVT;
+ }
+#endif
}
SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
@@ -4201,22 +4022,28 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
SiS_Pr->CVSyncStart = tempax;
tempax += SiS_Pr->PanelVRE;
SiS_Pr->CVSyncEnd = tempax;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_Pr->CVSyncStart--;
+ SiS_Pr->CVSyncEnd--;
+ }
SiS_CalcCRRegisters(SiS_Pr, 8);
+ SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
+ SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
- for(i=0,j=0;i<=7;i++,j++) {
+ for(i = 0, j = 0; i <= 7; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x10;i<=10;i++,j++) {
+ for(j = 0x10; i <= 10; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x15;i<=12;i++,j++) {
+ for(j = 0x15; i <= 12; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
}
- for(j=0x0A;i<=15;i++,j++) {
+ for(j = 0x0A; i <= 15; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
}
@@ -4227,1092 +4054,192 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
if(modeflag & DoubleScanMode) tempax |= 0x80;
SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
- SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+ SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
-
xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+ SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+ SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
#endif
+#endif
}
-#ifdef LINUX_XF86
-
void
-SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c)
-{
- int out_n, out_dn, out_div, out_sbit, out_scale;
- unsigned int vclk[5];
-
-#define Midx 0
-#define Nidx 1
-#define VLDidx 2
-#define Pidx 3
-#define PSNidx 4
-
- if(SiS_compute_vclk(clock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) {
- (*p2b) = (out_div == 2) ? 0x80 : 0x00;
- (*p2b) |= ((out_n - 1) & 0x7f);
- (*p2c) = (out_dn - 1) & 0x1f;
- (*p2c) |= (((out_scale - 1) & 3) << 5);
- (*p2c) |= ((out_sbit & 0x01) << 7);
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
- clock, out_n, out_dn, out_div, out_sbit, out_scale);
+SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+ int xres, int yres,
+#ifdef SIS_XORG_XF86
+ DisplayModePtr current
#endif
- } else {
- SiSCalcClock(pScrn, clock, 2, vclk);
- (*p2b) = (vclk[VLDidx] == 2) ? 0x80 : 0x00;
- (*p2b) |= (vclk[Midx] - 1) & 0x7f;
- (*p2c) = (vclk[Nidx] - 1) & 0x1f;
- if(vclk[Pidx] <= 4) {
- /* postscale 1,2,3,4 */
- (*p2c) |= ((vclk[Pidx] - 1) & 3) << 5;
- } else {
- /* postscale 6,8 */
- (*p2c) |= (((vclk[Pidx] / 2) - 1) & 3) << 5;
- (*p2c) |= 0x80;
- }
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n",
- clock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]);
+#ifdef SIS_LINUX_KERNEL
+ struct fb_var_screeninfo *var, BOOLEAN writeres
#endif
- }
-}
-
-#endif
-
-/* ================ XFREE86/X.ORG ================= */
-
-/* Helper functions */
-
-#ifdef LINUX_XF86
-
-USHORT
-SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
+)
{
- SISPtr pSiS = SISPTR(pScrn);
- int depth = pSiS->CurrentLayout.bitsPerPixel;
-
- pSiS->SiS_Pr->CModeFlag = 0;
-
- pSiS->SiS_Pr->CDClock = mode->Clock;
-
- pSiS->SiS_Pr->CHDisplay = mode->HDisplay;
- pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart;
- pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd;
- pSiS->SiS_Pr->CHTotal = mode->HTotal;
-
- pSiS->SiS_Pr->CVDisplay = mode->VDisplay;
- pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart;
- pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd;
- pSiS->SiS_Pr->CVTotal = mode->VTotal;
-
- pSiS->SiS_Pr->CFlags = mode->Flags;
-
- if(pSiS->SiS_Pr->CFlags & V_INTERLACE) {
- pSiS->SiS_Pr->CVDisplay >>= 1;
- pSiS->SiS_Pr->CVSyncStart >>= 1;
- pSiS->SiS_Pr->CVSyncEnd >>= 1;
- pSiS->SiS_Pr->CVTotal >>= 1;
- }
- if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) {
- /* pSiS->SiS_Pr->CDClock <<= 1; */
- pSiS->SiS_Pr->CVDisplay <<= 1;
- pSiS->SiS_Pr->CVSyncStart <<= 1;
- pSiS->SiS_Pr->CVSyncEnd <<= 1;
- pSiS->SiS_Pr->CVTotal <<= 1;
- }
-
- pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
- pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
- pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1;
- pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal;
+ unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+ unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+ unsigned char sr_data, cr_data, cr_data2;
+ int A, B, C, D, E, F, temp;
- SiS_MakeClockRegs(pScrn, pSiS->SiS_Pr->CDClock, &pSiS->SiS_Pr->CSR2B, &pSiS->SiS_Pr->CSR2C);
+ sr_data = crdata[14];
- pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
+ /* Horizontal total */
+ HT = crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
+ A = HT + 5;
- SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
+ /* Horizontal display enable end */
+ HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
+ E = HDE + 1;
- switch(depth) {
- case 8: pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
- case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
- case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
- default: return 0;
- }
+ /* Horizontal retrace (=sync) start */
+ HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
+ F = HRS - E - 3;
- if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
- pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
+ /* Horizontal blank start */
+ HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
- if((pSiS->SiS_Pr->CVDisplay >= 1024) ||
- (pSiS->SiS_Pr->CVTotal >= 1024) ||
- (pSiS->SiS_Pr->CHDisplay >= 1024))
- pSiS->SiS_Pr->CModeFlag |= LineCompareOff;
+ sr_data = crdata[15];
+ cr_data = crdata[5];
- if(pSiS->SiS_Pr->CFlags & V_CLKDIV2)
- pSiS->SiS_Pr->CModeFlag |= HalfDCLK;
+ /* Horizontal blank end */
+ HBE = (crdata[3] & 0x1f) |
+ ((unsigned short)(cr_data & 0x80) >> 2) |
+ ((unsigned short)(sr_data & 0x03) << 6);
- pSiS->SiS_Pr->CInfoFlag = 0x0007;
+ /* Horizontal retrace (=sync) end */
+ HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
- if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
- pSiS->SiS_Pr->CInfoFlag |= 0x4000;
+ temp = HBE - ((E - 1) & 255);
+ B = (temp > 0) ? temp : (temp + 256);
- if(pSiS->SiS_Pr->CFlags & V_NVSYNC)
- pSiS->SiS_Pr->CInfoFlag |= 0x8000;
+ temp = HRE - ((E + F + 3) & 63);
+ C = (temp > 0) ? temp : (temp + 64);
- if(pSiS->SiS_Pr->CFlags & V_INTERLACE)
- pSiS->SiS_Pr->CInfoFlag |= InterlaceMode;
+ D = B - F - C;
- pSiS->SiS_Pr->UseCustomMode = TRUE;
+#ifdef SIS_XORG_XF86
+ current->HDisplay = (E * 8);
+ current->HSyncStart = (E * 8) + (F * 8);
+ current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
+ current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
- pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
- xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
- pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
- xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
- pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
- pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
- pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
- xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
- pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
- pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
- pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
- pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
- xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
- xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
- pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
-#endif
- return 1;
-}
-
-int
-SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy)
-{
- int i, j;
- BOOLEAN done = FALSE;
-
- i = 0;
- while((!done) && (SiS_PlasmaTable[i].vendor) && panelvendor) {
- if(SiS_PlasmaTable[i].vendor == panelvendor) {
- for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
- if(SiS_PlasmaTable[i].product[j] == panelproduct) {
- if(SiS_PlasmaTable[i].maxx && SiS_PlasmaTable[i].maxy) {
- (*maxx) = (int)SiS_PlasmaTable[i].maxx;
- (*maxy) = (int)SiS_PlasmaTable[i].maxy;
- (*prefx) = (int)SiS_PlasmaTable[i].prefx;
- (*prefy) = (int)SiS_PlasmaTable[i].prefy;
- done = TRUE;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "Identified %s, correcting max X res %d, max Y res %d\n",
- SiS_PlasmaTable[i].plasmaname,
- SiS_PlasmaTable[i].maxx, SiS_PlasmaTable[i].maxy);
- break;
- }
- }
- }
- }
- i++;
- }
- return (done) ? 1 : 0;
-}
-
-/* Build a list of supported modes:
- * Built-in modes for which we have all data are M_T_DEFAULT,
- * modes derived from DDC or database data are M_T_BUILTIN
- */
-DisplayModePtr
-SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi)
-{
- SISPtr pSiS = SISPTR(pScrn);
- unsigned short VRE, VBE, VRS, VBS, VDE, VT;
- unsigned short HRE, HBE, HRS, HBS, HDE, HT;
- unsigned char sr_data, cr_data, cr_data2, cr_data3;
- unsigned char sr2b, sr2c;
- float num, denum, postscalar, divider;
- int A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex;
- DisplayModePtr new = NULL, current = NULL, first = NULL;
- BOOLEAN done = FALSE;
-#if 0
- DisplayModePtr backup = NULL;
-#endif
-
- pSiS->backupmodelist = NULL;
- pSiS->AddedPlasmaModes = FALSE;
-
- /* Initialize our pointers */
- if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
- InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
+ xf86DrvMsg(0, X_INFO,
+ "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
+ A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
#else
- return NULL;
+ (void)VBS; (void)HBS; (void)A;
#endif
- } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
- InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return NULL;
-#endif
- } else return NULL;
-
- i = 0;
- while(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag != 0xFFFF) {
-
- index = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRT1CRTC;
-
- /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */
- if((!pSiS->FSTN) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a)) {
- i++;
- continue;
- }
- if((pSiS->FSTN) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) &&
- (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) {
- i++;
- continue;
- }
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(10))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes,
- pSiS->SiS_Pr->SiS_RefIndex[i].YRes);
-
- current->status = MODE_OK;
-
- current->type = M_T_DEFAULT;
-
- vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK;
- if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F;
-
- sr2b = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
- sr2c = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
-
- divider = (sr2b & 0x80) ? 2.0 : 1.0;
- postscalar = (sr2c & 0x80) ?
- ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0);
- num = (sr2b & 0x7f) + 1.0;
- denum = (sr2c & 0x1f) + 1.0;
-
-#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "------------\n");
- xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n",
- sr2b, sr2c, divider, postscalar, num, denum);
#endif
-
- current->Clock = (int)(14318 * (divider / postscalar) * (num / denum));
-
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[14];
- /* inSISIDXREG(SISSR, 0x0b, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[0];
- /* inSISIDXREG(SISCR, 0x00, cr_data); */
-
- /* Horizontal total */
- HT = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[1];
- /* inSISIDXREG(SISCR, 0x01, cr_data); */
-
- /* Horizontal display enable end */
- HDE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x0C) << 6);
- E = HDE + 1; /* 0x80 0x64 */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
- /* inSISIDXREG(SISCR, 0x04, cr_data); */
-
- /* Horizontal retrace (=sync) start */
- HRS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0xC0) << 2);
- F = HRS - E - 3; /* 0x06 0x06 */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
- /* inSISIDXREG(SISCR, 0x02, cr_data); */
-
- /* Horizontal blank start */
- HBS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x30) << 4);
-
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[15];
- /* inSISIDXREG(SISSR, 0x0c, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[3];
- /* inSISIDXREG(SISCR, 0x03, cr_data); */
-
- cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[5];
- /* inSISIDXREG(SISCR, 0x05, cr_data2); */
-
- /* Horizontal blank end */
- HBE = (cr_data & 0x1f) |
- ((unsigned short) (cr_data2 & 0x80) >> 2) |
- ((unsigned short) (sr_data & 0x03) << 6);
-
- /* Horizontal retrace (=sync) end */
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
-
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
-
- D = B - F - C;
-
- if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
- ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) ||
- (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) {
-
- /* Terrible hack, but correct CRTC data for
- * these modes only produces a black screen...
- * (HRE is 0, leading into a too large C and
- * a negative D. The CRT controller does not
- * seem to like correcting HRE to 50
- */
- current->HDisplay = 320;
- current->HSyncStart = 328;
- current->HSyncEnd = 376;
- current->HTotal = 400;
-
- } else {
-
- current->HDisplay = (E * 8);
- current->HSyncStart = (E * 8) + (F * 8);
- current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
- current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
-
- }
-
-#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO,
- "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
- A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
+#ifdef SIS_LINUX_KERNEL
+ if(writeres) var->xres = xres = E * 8;
+ var->left_margin = D * 8;
+ var->right_margin = F * 8;
+ var->hsync_len = C * 8;
#endif
- sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[13];
- /* inSISIDXREG(SISSR, 0x0A, sr_data); */
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[6];
- /* inSISIDXREG(SISCR, 0x06, cr_data); */
-
- cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[7];
- /* inSISIDXREG(SISCR, 0x07, cr_data2); */
-
- /* Vertical total */
- VT = (cr_data & 0xFF) |
- ((unsigned short) (cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[10];
- /* inSISIDXREG(SISCR, 0x12, cr_data); */
-
- /* Vertical display enable end */
- VDE = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x02) << 7) |
- ((unsigned short) (cr_data2 & 0x40) << 3) |
- ((unsigned short) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[8];
- /* inSISIDXREG(SISCR, 0x10, cr_data); */
-
- /* Vertical retrace (=sync) start */
- VRS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x04) << 6) |
- ((unsigned short) (cr_data2 & 0x80) << 2) |
- ((unsigned short) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[11];
- /* inSISIDXREG(SISCR, 0x15, cr_data); */
-
- cr_data3 = (pSiS->SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
- /* inSISIDXREG(SISCR, 0x09, cr_data3); */
-
- /* Vertical blank start */
- VBS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x08) << 5) |
- ((unsigned short) (cr_data3 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x04) << 8);
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[12];
- /* inSISIDXREG(SISCR, 0x16, cr_data); */
-
- /* Vertical blank end */
- VBE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[9];
- /* inSISIDXREG(SISCR, 0x11, cr_data); */
-
- /* Vertical retrace (=sync) end */
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- current->VDisplay = VDE + 1;
- current->VSyncStart = VRS + 1;
- current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1;
- if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
- current->VTotal = E + D + C + F;
-
+ /* Vertical */
+ sr_data = crdata[13];
+ cr_data = crdata[7];
+
+ /* Vertical total */
+ VT = crdata[6] |
+ ((unsigned short)(cr_data & 0x01) << 8) |
+ ((unsigned short)(cr_data & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x01) << 10);
+ A = VT + 2;
+
+ /* Vertical display enable end */
+ VDE = crdata[10] |
+ ((unsigned short)(cr_data & 0x02) << 7) |
+ ((unsigned short)(cr_data & 0x40) << 3) |
+ ((unsigned short)(sr_data & 0x02) << 9);
+ E = VDE + 1;
+
+ /* Vertical retrace (=sync) start */
+ VRS = crdata[8] |
+ ((unsigned short)(cr_data & 0x04) << 6) |
+ ((unsigned short)(cr_data & 0x80) << 2) |
+ ((unsigned short)(sr_data & 0x08) << 7);
+ F = VRS + 1 - E;
+
+ cr_data2 = (crdata[16] & 0x01) << 5;
+
+ /* Vertical blank start */
+ VBS = crdata[11] |
+ ((unsigned short)(cr_data & 0x08) << 5) |
+ ((unsigned short)(cr_data2 & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x04) << 8);
+
+ /* Vertical blank end */
+ VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
+ temp = VBE - ((E - 1) & 511);
+ B = (temp > 0) ? temp : (temp + 512);
+
+ /* Vertical retrace (=sync) end */
+ VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
+ temp = VRE - ((E + F - 1) & 31);
+ C = (temp > 0) ? temp : (temp + 32);
+
+ D = B - F - C;
+
+#ifdef SIS_XORG_XF86
+ current->VDisplay = VDE + 1;
+ current->VSyncStart = VRS + 1;
+ current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1;
+ if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
+ current->VTotal = E + D + C + F;
#if 0
- current->VDisplay = E;
- current->VSyncStart = E + D;
- current->VSyncEnd = E + D + C;
- current->VTotal = E + D + C + F;
+ current->VDisplay = E;
+ current->VSyncStart = E + D;
+ current->VSyncEnd = E + D + C;
+ current->VTotal = E + D + C + F;
#endif
-
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO,
- "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
- A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
+ xf86DrvMsg(0, X_INFO,
+ "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
+ A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
#endif
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x4000)
- current->Flags |= V_NHSYNC;
- else
- current->Flags |= V_PHSYNC;
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x8000)
- current->Flags |= V_NVSYNC;
- else
- current->Flags |= V_PVSYNC;
-
- if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x0080)
- current->Flags |= V_INTERLACE;
-
- j = 0;
- while(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
- pSiS->SiS_Pr->SiS_RefIndex[i].ModeID) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
- current->Flags |= V_DBLSCAN;
- }
- break;
- }
- j++;
- }
-
- if(current->Flags & V_INTERLACE) {
- current->VDisplay <<= 1;
- current->VSyncStart <<= 1;
- current->VSyncEnd <<= 1;
- current->VTotal <<= 1;
- current->VTotal |= 1;
- }
- if(current->Flags & V_DBLSCAN) {
- current->Clock >>= 1;
- current->VDisplay >>= 1;
- current->VSyncStart >>= 1;
- current->VSyncEnd >>= 1;
- current->VTotal >>= 1;
- }
-
-#ifdef TWDEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Built-in: %s %.2f %d %d %d %d %d %d %d %d\n",
- current->name, (float)current->Clock / 1000,
- current->HDisplay, current->HSyncStart, current->HSyncEnd, current->HTotal,
- current->VDisplay, current->VSyncStart, current->VSyncEnd, current->VTotal);
-#else
- (void)VBS; (void)HBS; (void)A;
#endif
-
- i++;
- }
-
- /* Add non-standard LCD modes for panel's detailed timings */
-
- if(!includelcdmodes) return first;
-
- if(pSiS->SiS_Pr->CP_Vendor) {
- xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n",
- pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product);
- }
-
- i = 0;
- while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) {
-
- if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) {
-
- for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
-
- if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) {
-
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Identified %s panel, adding specific modes\n",
- SiS_PlasmaTable[i].plasmaname);
-
- for(k=0; k<SiS_PlasmaTable[i].modenum; k++) {
-
- if(isfordvi) {
- if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue;
- } else {
- if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue;
- }
-
- l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f;
-
- if(pSiS->VBFlags & (VB_301|VB_301B|VB_302B|VB_301LV)) {
- if(isfordvi) {
- if(SiS_PlasmaMode[l].VDisplay > 1024) continue;
- }
- }
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(12))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- pSiS->AddedPlasmaModes = TRUE;
-
- strcpy(current->name, SiS_PlasmaMode[l].name);
- /* sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay,
- SiS_PlasmaMode[l].VDisplay); */
-
- current->status = MODE_OK;
-
- current->type = M_T_BUILTIN;
-
- current->Clock = SiS_PlasmaMode[l].clock;
- current->SynthClock = current->Clock;
-
- current->HDisplay = SiS_PlasmaMode[l].HDisplay;
- current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch;
- current->HSyncEnd = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth;
- current->HTotal = SiS_PlasmaMode[l].HTotal;
-
- current->VDisplay = SiS_PlasmaMode[l].VDisplay;
- current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch;
- current->VSyncEnd = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth;
- current->VTotal = SiS_PlasmaMode[l].VTotal;
-
- current->CrtcHDisplay = current->HDisplay;
- current->CrtcHBlankStart = current->HSyncStart;
- current->CrtcHSyncStart = current->HSyncStart;
- current->CrtcHSyncEnd = current->HSyncEnd;
- current->CrtcHBlankEnd = current->HSyncEnd;
- current->CrtcHTotal = current->HTotal;
-
- current->CrtcVDisplay = current->VDisplay;
- current->CrtcVBlankStart = current->VSyncStart;
- current->CrtcVSyncStart = current->VSyncStart;
- current->CrtcVSyncEnd = current->VSyncEnd;
- current->CrtcVBlankEnd = current->VSyncEnd;
- current->CrtcVTotal = current->VTotal;
-
- if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP)
- current->Flags |= V_PHSYNC;
- else
- current->Flags |= V_NHSYNC;
-
- if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP)
- current->Flags |= V_PVSYNC;
- else
- current->Flags |= V_NVSYNC;
-
- if(current->HDisplay > pSiS->LCDwidth)
- pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay;
- if(current->VDisplay > pSiS->LCDheight)
- pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay;
-
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "\tAdding \"%s\" to list of built-in modes\n", current->name);
-
- }
- done = TRUE;
- break;
- }
- }
- }
-
- i++;
-
- }
-
- if(pSiS->SiS_Pr->CP_HaveCustomData) {
-
- for(i=0; i<7; i++) {
-
- if(pSiS->SiS_Pr->CP_DataValid[i]) {
-
- if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
- memset(new, 0, sizeof(DisplayModeRec));
- if(!(new->name = xalloc(10))) {
- xfree(new);
- return first;
- }
- if(!first) first = new;
- if(current) {
- current->next = new;
- new->prev = current;
- }
-
- current = new;
-
- sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i],
- pSiS->SiS_Pr->CP_VDisplay[i]);
-
- current->status = MODE_OK;
-
- current->type = M_T_BUILTIN;
-
- current->Clock = pSiS->SiS_Pr->CP_Clock[i];
- current->SynthClock = current->Clock;
-
- current->HDisplay = pSiS->SiS_Pr->CP_HDisplay[i];
- current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i];
- current->HSyncEnd = pSiS->SiS_Pr->CP_HSyncEnd[i];
- current->HTotal = pSiS->SiS_Pr->CP_HTotal[i];
-
- current->VDisplay = pSiS->SiS_Pr->CP_VDisplay[i];
- current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i];
- current->VSyncEnd = pSiS->SiS_Pr->CP_VSyncEnd[i];
- current->VTotal = pSiS->SiS_Pr->CP_VTotal[i];
-
- current->CrtcHDisplay = current->HDisplay;
- current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i];
- current->CrtcHSyncStart = current->HSyncStart;
- current->CrtcHSyncEnd = current->HSyncEnd;
- current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i];
- current->CrtcHTotal = current->HTotal;
-
- current->CrtcVDisplay = current->VDisplay;
- current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i];
- current->CrtcVSyncStart = current->VSyncStart;
- current->CrtcVSyncEnd = current->VSyncEnd;
- current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i];
- current->CrtcVTotal = current->VTotal;
-
- if(pSiS->SiS_Pr->CP_SyncValid[i]) {
- if(pSiS->SiS_Pr->CP_HSync_P[i])
- current->Flags |= V_PHSYNC;
- else
- current->Flags |= V_NHSYNC;
-
- if(pSiS->SiS_Pr->CP_VSync_P[i])
- current->Flags |= V_PVSYNC;
- else
- current->Flags |= V_NVSYNC;
- } else {
- /* No sync data? Use positive sync... */
- current->Flags |= V_PHSYNC;
- current->Flags |= V_PVSYNC;
- }
- }
- }
- }
-
- return first;
-
-}
-
-/* Translate a mode number into the VESA pendant */
-int
-SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber)
-{
- SISPtr pSiS = SISPTR(pScrn);
- int i = 0;
-
- /* Initialize our pointers */
- if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
- InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return -1;
-#endif
- } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
- InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
- return -1;
+#ifdef SIS_LINUX_KERNEL
+ if(writeres) var->yres = yres = E;
+ var->upper_margin = D;
+ var->lower_margin = F;
+ var->vsync_len = C;
#endif
- } else return -1;
-
- if(modenumber <= 0x13) return modenumber;
-#ifdef SIS315H
- if(pSiS->ROM661New) {
- while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
- if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
- return (int)SiS_EModeIDTable661[i].Ext_VESAID;
- }
- i++;
- }
- } else {
+ if((xres == 320) && ((yres == 200) || (yres == 240))) {
+ /* Terrible hack, but correct CRTC data for
+ * these modes only produces a black screen...
+ * (HRE is 0, leading into a too large C and
+ * a negative D. The CRT controller does not
+ * seem to like correcting HRE to 50)
+ */
+#ifdef SIS_XORG_XF86
+ current->HDisplay = 320;
+ current->HSyncStart = 328;
+ current->HSyncEnd = 376;
+ current->HTotal = 400;
#endif
- while(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID != 0xff) {
- if(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID == modenumber) {
- return (int)pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID;
- }
- i++;
- }
-#ifdef SIS315H
- }
+#ifdef SIS_LINUX_KERNEL
+ var->left_margin = (400 - 376);
+ var->right_margin = (328 - 320);
+ var->hsync_len = (376 - 328);
#endif
- return -1;
-}
-/* Translate a new BIOS mode number into the driver's pendant */
-int
-SiSTranslateToOldMode(int modenumber)
-{
-#ifdef SIS315H
- int i = 0;
-
- while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
- if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
- if(SiS_EModeIDTable661[i].Ext_MyModeID)
- return (int)SiS_EModeIDTable661[i].Ext_MyModeID;
- else
- return modenumber;
- }
- i++;
}
-#endif
- return modenumber;
-}
-
-#endif /* Xfree86 */
-
-#ifdef LINUX_KERNEL
-int
-sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, unsigned char rateindex)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, ClockIndex = 0;
- USHORT RefreshRateTableIndex = 0;
- int Clock;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return 65 * 1000;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return 65 * 1000;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
- printk(KERN_ERR "Could not find mode %x\n", ModeNo);
- return 65 * 1000;
- }
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- ClockIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- if(HwInfo->jChipType < SIS_315H) {
- ClockIndex &= 0x3F;
- }
- Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
-
- return(Clock);
-}
-
-BOOLEAN
-sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, CRT1Index = 0;
- USHORT RefreshRateTableIndex = 0;
- unsigned char sr_data, cr_data, cr_data2;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return FALSE;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return FALSE;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
- cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
- *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
- sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
- cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
- cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
- *vtotal = ((cr_data & 0xFF) |
- ((unsigned short)(cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short)(sr_data & 0x01) << 10)) + 2;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode)
- *vtotal *= 2;
-
- return TRUE;
}
-int
-sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- unsigned char modeno, unsigned char rateindex,
- struct fb_var_screeninfo *var)
-{
- USHORT ModeNo = modeno;
- USHORT ModeIdIndex = 0, index = 0;
- USHORT RefreshRateTableIndex = 0;
- unsigned short VRE, VBE, VRS, VBS, VDE, VT;
- unsigned short HRE, HBE, HRS, HBS, HDE, HT;
- unsigned char sr_data, cr_data, cr_data2, cr_data3;
- int A, B, C, D, E, F, temp, j;
-
- if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
- InitTo300Pointer(SiS_Pr, HwInfo);
-#else
- return 0;
-#endif
- } else {
-#ifdef SIS315H
- InitTo310Pointer(SiS_Pr, HwInfo);
-#else
- return 0;
-#endif
- }
-
- if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
-
- RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- RefreshRateTableIndex += (rateindex - 1);
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[14];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[0];
-
- /* Horizontal total */
- HT = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[1];
-
- /* Horizontal display enable end */
- HDE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x0C) << 6);
- E = HDE + 1;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[4];
-
- /* Horizontal retrace (=sync) start */
- HRS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0xC0) << 2);
- F = HRS - E - 3;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[2];
-
- /* Horizontal blank start */
- HBS = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x30) << 4);
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[15];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[3];
-
- cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[5];
-
- /* Horizontal blank end */
- HBE = (cr_data & 0x1f) |
- ((unsigned short) (cr_data2 & 0x80) >> 2) |
- ((unsigned short) (sr_data & 0x03) << 6);
-
- /* Horizontal retrace (=sync) end */
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
-
- D = B - F - C;
-
- if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) &&
- ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) ||
- (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) {
-
- /* Terrible hack, but the correct CRTC data for
- * these modes only produces a black screen...
- */
- var->left_margin = (400 - 376);
- var->right_margin = (328 - 320);
- var->hsync_len = (376 - 328);
-
- } else {
-
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
-
- }
-
- sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13];
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6];
-
- cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7];
-
- /* Vertical total */
- VT = (cr_data & 0xFF) |
- ((unsigned short) (cr_data2 & 0x01) << 8) |
- ((unsigned short)(cr_data2 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[10];
-
- /* Vertical display enable end */
- VDE = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x02) << 7) |
- ((unsigned short) (cr_data2 & 0x40) << 3) |
- ((unsigned short) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[8];
-
- /* Vertical retrace (=sync) start */
- VRS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x04) << 6) |
- ((unsigned short) (cr_data2 & 0x80) << 2) |
- ((unsigned short) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[11];
-
- cr_data3 = (SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
-
- /* Vertical blank start */
- VBS = (cr_data & 0xff) |
- ((unsigned short) (cr_data2 & 0x08) << 5) |
- ((unsigned short) (cr_data3 & 0x20) << 4) |
- ((unsigned short) (sr_data & 0x04) << 8);
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[12];
-
- /* Vertical blank end */
- VBE = (cr_data & 0xff) |
- ((unsigned short) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- cr_data = SiS_Pr->SiS_CRT1Table[index].CR[9];
-
- /* Vertical retrace (=sync) end */
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
-
- var->vmode = FB_VMODE_NONINTERLACED;
- if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
- var->vmode = FB_VMODE_INTERLACED;
- else {
- j = 0;
- while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
- if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
- SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
- if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
- var->vmode = FB_VMODE_DOUBLE;
- }
- break;
- }
- j++;
- }
- }
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-#if 0 /* Do this? */
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
-#endif
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
- }
-
- return 1;
-}
-
-#endif
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index 7e36b7ac1470..634c0a9d219b 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -3,7 +3,7 @@
/*
* Data and prototypes for init.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,18 +50,24 @@
*
*/
-#ifndef _INIT_
-#define _INIT_
+#ifndef _INIT_H_
+#define _INIT_H_
#include "osdef.h"
#include "initdef.h"
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#include "sis.h"
+#define SIS_NEED_inSISREG
+#define SIS_NEED_inSISREGW
+#define SIS_NEED_inSISREGL
+#define SIS_NEED_outSISREG
+#define SIS_NEED_outSISREGW
+#define SIS_NEED_outSISREGL
#include "sis_regs.h"
#endif
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include "vgatypes.h"
#include "vstruct.h"
#ifdef SIS_CP
@@ -73,6 +79,10 @@
#include <asm/io.h>
#include <linux/fb.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/sisfb.h>
#else
#include <video/sisfb.h>
@@ -80,44 +90,45 @@
#endif
/* Mode numbers */
-static const USHORT ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
-static const USHORT ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
-static const USHORT ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00}; /* FSTN */
-static const USHORT ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
-static const USHORT ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
-static const USHORT ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
-static const USHORT ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
-static const USHORT ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
-static const USHORT ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
-static const USHORT ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
-static const USHORT ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
-static const USHORT ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
-static const USHORT ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
-static const USHORT ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
-static const USHORT ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; /* 315 series only */
-static const USHORT ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; /* 315 series only */
-static const USHORT ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
-static const USHORT ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
-static const USHORT ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */
-static const USHORT ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
-static const USHORT ModeIndex_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e};
-static const USHORT ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */
-static const USHORT ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
-static const USHORT ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
-static const USHORT ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
-static const USHORT ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
-static const USHORT ModeIndex_1280x800[] = {0x14, 0x15, 0x00, 0x16};
-static const USHORT ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e};
-static const USHORT ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72}; /* 300 series, BARCO only */
-static const USHORT ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 315 series only */
-static const USHORT ModeIndex_1680x1050[] = {0x17, 0x18, 0x00, 0x19}; /* 315 series only */
-static const USHORT ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66};
-static const USHORT ModeIndex_1920x1080[] = {0x2c, 0x2d, 0x00, 0x73}; /* 315 series only */
-static const USHORT ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b};
-static const USHORT ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
-static const USHORT ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
-
-static const USHORT SiS_DRAMType[17][5]={
+static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00}; /* FSTN */
+static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; /* 315 series only */
+static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; /* 315 series only */
+static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+static const unsigned short ModeIndex_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e};
+static const unsigned short ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */
+static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
+static const unsigned short ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x800[] = {0x14, 0x15, 0x00, 0x16};
+static const unsigned short ModeIndex_1280x854[] = {0x1a, 0x1b, 0x00, 0x1c};
+static const unsigned short ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e};
+static const unsigned short ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72}; /* 300 series, BARCO only */
+static const unsigned short ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 315 series only */
+static const unsigned short ModeIndex_1680x1050[] = {0x17, 0x18, 0x00, 0x19}; /* 315 series only */
+static const unsigned short ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66};
+static const unsigned short ModeIndex_1920x1080[] = {0x2c, 0x2d, 0x00, 0x73}; /* 315 series only */
+static const unsigned short ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b};
+static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
+static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
+
+static const unsigned short SiS_DRAMType[17][5]={
{0x0C,0x0A,0x02,0x40,0x39},
{0x0D,0x0A,0x01,0x40,0x48},
{0x0C,0x09,0x02,0x20,0x35},
@@ -137,7 +148,7 @@ static const USHORT SiS_DRAMType[17][5]={
{0x09,0x08,0x01,0x01,0x00}
};
-static const USHORT SiS_SDRDRAM_TYPE[13][5] =
+static const unsigned short SiS_SDRDRAM_TYPE[13][5] =
{
{ 2,12, 9,64,0x35},
{ 1,13, 9,64,0x44},
@@ -154,7 +165,7 @@ static const USHORT SiS_SDRDRAM_TYPE[13][5] =
{ 1, 9, 8, 2,0x00}
};
-static const USHORT SiS_DDRDRAM_TYPE[4][5] =
+static const unsigned short SiS_DDRDRAM_TYPE[4][5] =
{
{ 2,12, 9,64,0x35},
{ 2,12, 8,32,0x31},
@@ -162,7 +173,7 @@ static const USHORT SiS_DDRDRAM_TYPE[4][5] =
{ 2, 9, 8, 4,0x01}
};
-static const USHORT SiS_MDA_DAC[] =
+static const unsigned char SiS_MDA_DAC[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
@@ -174,7 +185,7 @@ static const USHORT SiS_MDA_DAC[] =
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
};
-static const USHORT SiS_CGA_DAC[] =
+static const unsigned char SiS_CGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
@@ -186,7 +197,7 @@ static const USHORT SiS_CGA_DAC[] =
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
};
-static const USHORT SiS_EGA_DAC[] =
+static const unsigned char SiS_EGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
@@ -198,7 +209,7 @@ static const USHORT SiS_EGA_DAC[] =
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
};
-static const USHORT SiS_VGA_DAC[] =
+static const unsigned char SiS_VGA_DAC[] =
{
0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
@@ -212,7 +223,31 @@ static const USHORT SiS_VGA_DAC[] =
0x0B,0x0C,0x0D,0x0F,0x10
};
-static const SiS_StResInfoStruct SiS_StResInfo[]=
+static const struct SiS_St SiS_SModeIDTable[] =
+{
+ {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00,0x40},
+ {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00,0x40},
+ {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01,0x40},
+ {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02,0x40},
+ {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02,0x40},
+ {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05,0x40},
+ {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03,0x40},
+ {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03,0x40},
+ {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05,0x40},
+ {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05,0x40},
+ {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05,0x40},
+ {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04,0x40},
+ {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05,0x40},
+ {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05,0x40},
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiS_StResInfo[]=
{
{ 640,400},
{ 640,350},
@@ -221,7 +256,7 @@ static const SiS_StResInfoStruct SiS_StResInfo[]=
{ 640,480}
};
-static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
+static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
{
{ 320, 200, 8, 8}, /* 0x00 */
{ 320, 240, 8, 8}, /* 0x01 */
@@ -256,11 +291,12 @@ static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
{ 1280, 800, 8,16}, /* 0x1e */
{ 1920,1080, 8,16}, /* 0x1f */
{ 960, 540, 8,16}, /* 0x20 */
- { 960, 600, 8,16} /* 0x21 */
+ { 960, 600, 8,16}, /* 0x21 */
+ { 1280, 854, 8,16} /* 0x22 */
};
#if defined(SIS300) || defined(SIS315H)
-static const SiS_StandTableStruct SiS_StandTable[]=
+static const struct SiS_StandTable_S SiS_StandTable[]=
{
/* 0x00: MD_0_200 */
{
@@ -704,11 +740,11 @@ static const SiS_StandTableStruct SiS_StandTable[]=
/* SIS VIDEO BRIDGE ----------------------------------------- */
/**************************************************************/
-static const UCHAR SiS_SoftSetting = 0x30; /* RAM setting */
+static const unsigned char SiS_SoftSetting = 0x30; /* RAM setting */
-static const UCHAR SiS_OutputSelect = 0x40;
+static const unsigned char SiS_OutputSelect = 0x40;
-static const UCHAR SiS_NTSCTiming[] = {
+static const unsigned char SiS_NTSCTiming[] = {
0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
@@ -719,7 +755,7 @@ static const UCHAR SiS_NTSCTiming[] = {
0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
};
-static const UCHAR SiS_PALTiming[] = {
+static const unsigned char SiS_PALTiming[] = {
0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
@@ -730,8 +766,8 @@ static const UCHAR SiS_PALTiming[] = {
0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
};
-static const UCHAR SiS_HiTVExtTiming[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVExtTiming[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -741,8 +777,8 @@ static const UCHAR SiS_HiTVExtTiming[] = {
0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
};
-static const UCHAR SiS_HiTVSt1Timing[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVSt1Timing[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
@@ -752,8 +788,8 @@ static const UCHAR SiS_HiTVSt1Timing[] = {
0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
};
-static const UCHAR SiS_HiTVSt2Timing[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVSt2Timing[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -764,8 +800,8 @@ static const UCHAR SiS_HiTVSt2Timing[] = {
};
#if 0
-static const UCHAR SiS_HiTVTextTiming[] = {
- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVTextTiming[] = {
+ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
@@ -776,8 +812,8 @@ static const UCHAR SiS_HiTVTextTiming[] = {
};
#endif
-static const UCHAR SiS_HiTVGroup3Data[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+static const unsigned char SiS_HiTVGroup3Data[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
@@ -787,8 +823,8 @@ static const UCHAR SiS_HiTVGroup3Data[] = {
0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
};
-static const UCHAR SiS_HiTVGroup3Simu[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+static const unsigned char SiS_HiTVGroup3Simu[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
@@ -799,8 +835,8 @@ static const UCHAR SiS_HiTVGroup3Simu[] = {
};
#if 0
-static const UCHAR SiS_HiTVGroup3Text[] = {
- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+static const unsigned char SiS_HiTVGroup3Text[] = {
+ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
@@ -811,136 +847,141 @@ static const UCHAR SiS_HiTVGroup3Text[] = {
};
#endif
-static const UCHAR SiS_NTSCPhase[] = {0x21,0xed,0xba,0x08};
-static const UCHAR SiS_PALPhase[] = {0x2a,0x05,0xe3,0x00};
-static const UCHAR SiS_PALMPhase[] = {0x21,0xE4,0x2E,0x9B};
-static const UCHAR SiS_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
-static const UCHAR SiS_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};
-static const UCHAR SiS_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
-static const UCHAR SiS_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4};
-static const UCHAR SiS_PALNPhase2[] = {0x21,0xF6,0x94,0x46};
-static const UCHAR SiS_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a};
-static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0};
-static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e};
-
-static const SiS_TVDataStruct SiS_StPALData[] =
+static const struct SiS_TVData SiS_StPALData[] =
{
- { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
- { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
- { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22},
- { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22}
+ { 1, 1, 864, 525,1270, 400, 100, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 350, 100, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 400, 0, 0, 720, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 864, 525,1270, 350, 0, 0, 720, 0,0xf4,0x0b,0x1c,0x0a},
+ { 1, 1, 864, 525,1270, 480, 50, 0, 760, 0,0xf4,0xff,0x1c,0x22},
+ { 1, 1, 864, 525,1270, 600, 50, 0, 0,0x300,0xf4,0xff,0x1c,0x22}
};
-static const SiS_TVDataStruct SiS_ExtPALData[] =
+static const struct SiS_TVData SiS_ExtPALData[] =
{
- { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */
- { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
- { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18},
- { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a},
- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */
-/*{ 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16},*//* 800x600, 400x300 */
- { 36, 25,1060, 648,1270, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 - better */
- { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x576 */
- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 */
- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 (for NTSC equ) */
- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a} /* 720x480 test */
+ { 27, 10, 848, 448,1270, 530, 50, 0, 50, 0,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */
+ { 108, 35, 848, 398,1270, 530, 50, 0, 50, 0,0xf4,0xff,0x1c,0x22},
+ { 12, 5, 954, 448,1270, 530, 50, 0, 50, 0,0xf1,0x04,0x1f,0x18},
+ { 9, 4, 960, 463,1644, 438, 50, 0, 50, 0,0xf4,0x0b,0x1c,0x0a},
+ { 9, 4, 848, 528,1270, 530, 0, 0, 50, 0,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */
+ { 36, 25,1060, 648,1270, 530, 438, 0, 438, 0,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 */
+ { 3, 2,1080, 619,1270, 540, 438, 0, 438, 0,0xf3,0x00,0x1d,0x20}, /* 720x576 */
+ { 1, 1,1170, 821,1270, 520, 686, 0, 686, 0,0xF3,0x00,0x1D,0x20}, /* 1024x768 */
+ { 1, 1,1170, 821,1270, 520, 686, 0, 686, 0,0xF3,0x00,0x1D,0x20}, /* 1024x768 (for NTSC equ) */
+ { 9, 4, 848, 528,1270, 530, 0, 0, 50, 0,0xf5,0xfb,0x1b,0x2a} /* 720x480 */
};
-static const SiS_TVDataStruct SiS_StNTSCData[] =
+static const struct SiS_TVData SiS_StNTSCData[] =
{
- { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
- { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
- { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18}
+ { 1, 1, 858, 525,1270, 400, 50, 0, 760, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 350, 50, 0, 640, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 400, 0, 0, 720, 0,0xf1,0x04,0x1f,0x18},
+ { 1, 1, 858, 525,1270, 350, 0, 0, 720, 0,0xf4,0x0b,0x1c,0x0a},
+ { 1, 1, 858, 525,1270, 480, 0, 0, 760, 0,0xf1,0x04,0x1f,0x18}
};
-static const SiS_TVDataStruct SiS_ExtNTSCData[] =
+static const struct SiS_TVData SiS_ExtNTSCData[] =
{
- { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */
- { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
- { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
- { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
- { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */
- { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */
-/*{ 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08},*/ /* 720x480 (old, from 650) */
- { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */
-/*{ 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} */ /* 1024x768 (525i) */
- { 1, 1,1100, 811,1412, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 1024x768 (525i) CORRECTED */
- { 65, 64,1056, 791,1270, 480, 455, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+ { 143, 65, 858, 443,1270, 440, 171, 0, 171, 0,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */
+ { 88, 35, 858, 393,1270, 440, 171, 0, 171, 0,0xf1,0x04,0x1f,0x18},
+ { 143, 70, 924, 443,1270, 440, 92, 0, 92, 0,0xf1,0x04,0x1f,0x18},
+ { 143, 70, 924, 393,1270, 440, 92, 0, 92, 0,0xf4,0x0b,0x1c,0x0a},
+ { 143, 76, 836, 523,1270, 440, 224, 0, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */
+ { 143, 120,1056, 643,1270, 440, 0, 1, 0, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */
+ { 143, 76, 836, 523,1270, 440, 0, 1, 0, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */
+ { 1, 1,1100, 811,1412, 440, 0, 1, 0, 0,0xee,0x0c,0x22,0x08}, /* 1024x768 (525i) CORRECTED */
+#if 0 /* flimmert und ist unten abgeschnitten (NTSCHT, NTSC clock) */
+ { 65, 64,1056, 791,1270, 480, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1,1100, 811,1412, 440, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1,1120, 821,1516, 420, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0
+ { 1, 1, 938, 821,1516, 420, 0, 1, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0 /* zoom hin, unten abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1072, 791,1270, 480, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 1 /* zu weit links (squeezed) (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1100, 846,1270, 440, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
+#if 0 /* zu weit links, rechts abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ { 1, 1,1100, 846,1412, 440, 455, 0, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */
+#endif
};
-static const SiS_TVDataStruct SiS_StHiTVData[] = /* Slave + TVSimu */
+static const struct SiS_TVData SiS_StHiTVData[] = /* Slave + TVSimu */
{
- { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x150, 1, 0, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_St2HiTVData[] = /* Slave */
+static const struct SiS_TVData SiS_St2HiTVData[] = /* Slave */
{
- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
+ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d, 1, 0, 0, 0, 0, 0, 0},
+ { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c, 1, 0, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_ExtHiTVData[] =
-{
- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
- { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */
- { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */
- { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */
- { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x1024 */
- { 4, 1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x480 */
- { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x576 */
- { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x720 */
- { 137, 32, 0x3d4,0x233,0x663,0x3bf,0x143, 0, 0, 0x00,0x00,0x00,0x00} /* 960x600 */
+static const struct SiS_TVData SiS_ExtHiTVData[] =
+{ /* all ok */
+ { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 5, 1, 0x348,0x233,0x670,0x3c0,0x166, 1, 0, 0, 0, 0, 0, 0}, /* 640x480 */
+ { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0}, /* 800x600 */
+ { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 1024x768 */
+ { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0}, /* 1280x1024 */
+ { 4, 1, 0x41a,0x233,0x60c,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0}, /* 800x480 */
+ { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 1024x576 */
+ { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0}, /* 1280x720 */
+ { 8, 3, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0}, /* 960x600 */
};
-static const SiS_TVDataStruct SiS_St525pData[] =
+static const struct SiS_TVData SiS_St525pData[] =
{
- { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x6b4,0x20d,0x4f6,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x6b4,0x20d,0x4f6,0x1e0, 0, 0, 0x2f8, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_St750pData[] =
+static const struct SiS_TVData SiS_St750pData[] =
{
- { 1, 1, 0x672,0x2ee,0x500,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x190, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x15e, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00},
- { 1, 1, 0x672,0x2ee,0x500,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00}
+ { 1, 1, 0x672,0x2ee,0x500,0x190, 50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x15e, 50, 0, 0x280, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x190, 0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x15e, 0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ { 1, 1, 0x672,0x2ee,0x500,0x1e0, 0, 0, 0x2f8, 0, 0, 0, 0, 0}
};
-static const SiS_TVDataStruct SiS_Ext750pData[] =
-{
- { 143, 65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00},
- { 88, 35, 0x35a,0x189,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00},
- { 18, 5, 0x339,0x1ae,0x500,0x2d0,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00},
- { 143, 70, 0x39c,0x189,0x4f6,0x1b8,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00},
- { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */
- { 5, 4, 0x5d8,0x29e,0x500,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */
- { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 720x480 test WORKS */
- { 68, 64, 0x55f,0x346,0x500,0x2a8,0x27e, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */
- { 5, 2, 0x3a7,0x226,0x500,0x2a8, 0,128, 0, 0x00,0x00,0x00,0x00}, /* 720x576 */
- { 25, 24, 0x5d8,0x2f3,0x460,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00} /* 1280x720 WORKS */
+static const struct SiS_TVData SiS_Ext750pData[] =
+{ /* all ok */
+ { 3, 1, 935, 470, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0}, /* 320x200/640x400 */
+ { 24, 7, 935, 420, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 3, 1, 935, 470, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 24, 7, 935, 420, 1130, 680, 50, 0, 0, 0, 0, 0, 0, 0},
+ { 2, 1, 1100, 590, 1130, 640, 50, 0, 0, 0, 0, 0, 0, 0}, /* 640x480 */
+ { 3, 2, 1210, 690, 1130, 660, 50, 0, 0, 0, 0, 0, 0, 0}, /* 800x600 OK */
+ { 2, 1, 1100, 562, 1130, 640, 0, 1, 0, 0, 0, 0, 0, 0}, /* 720x480 OK */
+ { 1, 1, 1375, 878, 1130, 640, 638, 0, 0, 0, 0, 0, 0, 0}, /* 1024x768 OK */
+ { 5, 3, 1100, 675, 1130, 640, 0, 1, 0, 0, 0, 0, 0, 0}, /* 720/768x576 OK */
+ { 25, 24, 1496, 755, 1120, 680, 50, 0, 0, 0, 0, 0, 0, 0} /* 1280x720 OK */
};
-static const SiS_LCDDataStruct SiS_LCD1280x720Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_LCD1280x720Data[] = /* 2.03.00 */
{
{ 44, 15, 864, 430, 1408, 806 }, /* 640x400 */
{ 128, 35, 792, 385, 1408, 806 },
@@ -962,7 +1003,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x720Data[] = /* 2.03.00 */
* (Note: 1280x768_3 is now special for SiS301/NetVista
*/
-static const SiS_LCDDataStruct SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
{
{ 64, 21, 858, 434, 1408, 806 }, /* 640x400 */
{ 32, 9, 858, 372, 1408, 806 },
@@ -977,7 +1018,7 @@ static const SiS_LCDDataStruct SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
{ 16, 15, 1600, 750, 1600, 806 } /* 1280x720 - from Ext */
};
-static const SiS_LCDDataStruct SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
{
{ 16, 5, 960, 410, 1600, 806 }, /* 640x400 */
{ 64, 21, 1152, 364, 1600, 806 },
@@ -993,7 +1034,7 @@ static const SiS_LCDDataStruct SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
};
#if 0 /* Not used; _3 now reserved for NetVista (SiS301) */
-static const SiS_LCDDataStruct SiS_LCD1280x768_3Data[] =
+static const struct SiS_LCDData SiS_LCD1280x768_3Data[] =
{
{ 64, 25, 1056, 422, 1664, 798 }, /* 640x400 */
{ 128, 39, 884, 396, 1408, 806 }, /* ,640 */
@@ -1009,7 +1050,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x768_3Data[] =
};
#endif
-static const SiS_LCDDataStruct SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
+static const struct SiS_LCDData SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
{
{ 128, 51, 1122, 412, 1408, 816 }, /* 640x400 */
{ 128, 49, 1232, 361, 1408, 816 },
@@ -1024,7 +1065,7 @@ static const SiS_LCDDataStruct SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
{ 0, 0, 0, 0, 0, 0 } /* 1280x720 */
};
-static const SiS_LCDDataStruct SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
+static const struct SiS_LCDData SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
{
{ 97, 42, 1344, 409, 1552, 812 }, /* 640x400 */
{ 97, 35, 1280, 358, 1552, 812 },
@@ -1039,7 +1080,42 @@ static const SiS_LCDDataStruct SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
{ 97, 90, 1600, 730, 1552, 812 } /* 1280x720 */
};
-static const SiS_LCDDataStruct SiS_LCD1280x960Data[] =
+#if 0
+static const struct SiS_LCDData SiS_LCD1280x800_3Data[] = /* 2.02.05a (LVDS); m250 */
+{
+ { 128, 51, 1122, 412, 1408, 816 }, /* 640x400 */
+ { 128, 49, 1232, 361, 1408, 816 },
+ { 128, 51, 1122, 412, 1408, 816 },
+ { 128, 49, 1232, 361, 1408, 816 },
+ { 8, 3, 880, 491, 1408, 816 }, /* 640x480 */
+ { 11, 6, 1024, 612, 1408, 816 }, /* 800x600 */
+ { 22, 21, 1400, 784, 1408, 816 }, /* 1024x768 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */
+ { 1, 1, 1408, 816, 1408, 816 }, /* 1280x800 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x768 - patch index */
+ { 0, 0, 0, 0, 0, 0 } /* 1280x720 */
+};
+#endif
+
+static const struct SiS_LCDData SiS_LCD1280x854Data[] = /* 2.21.00CS (LVDS) */
+{
+ { 56, 15, 936, 410, 1664, 861 }, /* 640x400 */
+ { 64, 25, 1586, 355, 1664, 861 },
+ { 56, 15, 936, 410, 1664, 861 },
+ { 64, 25, 1586, 355, 1664, 861 },
+ { 91, 45, 1464, 485, 1664, 861 }, /* 640x480 */
+ { 182, 75, 976, 605, 1664, 861 }, /* 800x600 */
+ { 91, 66, 1342, 774, 1664, 861 }, /* 1024x768 */
+ { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */
+ { 26, 25, 1708, 807, 1664, 861 }, /* 1280x800 */
+ { 13, 12, 1708, 774, 1664, 861 }, /* 1280x768 - patch index */
+ { 52, 45, 1708, 725, 1664, 861 }, /* 1280x720 */
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 1, 1664, 861, 1664, 861 } /* 1280x854 */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x960Data[] =
{
{ 9, 2, 800, 500, 1800, 1000 },
{ 9, 2, 800, 500, 1800, 1000 },
@@ -1049,10 +1125,15 @@ static const SiS_LCDDataStruct SiS_LCD1280x960Data[] =
{ 30, 11, 1056, 625, 1800, 1000 },
{ 5, 3, 1350, 800, 1800, 1000 },
{ 1, 1, 1576, 1050, 1576, 1050 },
- { 1, 1, 1800, 1000, 1800, 1000 }
+ { 1, 1, 1800, 1000, 1800, 1000 },
+ { 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 const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_StLCD1400x1050Data[] =
{
{ 211, 100, 2100, 408, 1688, 1066 },
{ 211, 64, 1536, 358, 1688, 1066 },
@@ -1062,10 +1143,15 @@ static const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] =
{ 211, 72, 1008, 609, 1688, 1066 },
{ 211, 128, 1400, 776, 1688, 1066 },
{ 211, 205, 1680, 1041, 1688, 1066 },
- { 1, 1, 1688, 1066, 1688, 1066 }
+ { 1, 1, 1688, 1066, 1688, 1066 },
+ { 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 const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1400x1050Data[] =
{
/* { 211, 60, 1260, 410, 1688, 1066 }, 640x400 (6330) */
{ 211, 100, 2100, 408, 1688, 1066 }, /* 640x400 (6325) WORKS */
@@ -1080,10 +1166,13 @@ static const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] =
{ 211, 205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
{ 1, 1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
{ 0, 0, 0, 0, 0, 0 }, /* kludge */
- { 211, 120, 1400, 730, 1688, 1066 } /* 1280x720 */
+ { 211, 120, 1400, 730, 1688, 1066 }, /* 1280x720 */
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_LCD1680x1050Data[] =
+static const struct SiS_LCDData SiS_LCD1680x1050Data[] =
{
{ 95, 24, 1260, 410, 1900, 1066 }, /* 0 640x400 */
{ 10, 3, 1710, 362, 1900, 1066 },
@@ -1097,10 +1186,11 @@ static const SiS_LCDDataStruct SiS_LCD1680x1050Data[] =
{ 95, 69, 1800, 817, 1900, 1066 }, /* 9 1280x800 patch index */
{ 13, 9, 1900, 739, 1900, 1066 }, /* 10 1280x720 */
{ 95, 94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */
- { 1, 1, 1900, 1066, 1900, 1066 } /* 12 1680x1050 */
+ { 1, 1, 1900, 1066, 1900, 1066 }, /* 12 1680x1050 */
+ { 0, 0, 0, 0, 0, 0 }
};
-static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_StLCD1600x1200Data[] =
{
{27, 4, 800, 500, 2160, 1250 },
{27, 4, 800, 500, 2160, 1250 },
@@ -1111,10 +1201,14 @@ static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] =
{ 5, 2,1350, 800, 2160, 1250 },
{135,88,1600,1100, 2160, 1250 },
{72, 49,1680,1092, 2160, 1250 },
- { 1, 1,2160,1250, 2160, 1250 }
+ { 1, 1,2160,1250, 2160, 1250 },
+ { 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 const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1600x1200Data[] =
{
{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
/* {27, 4, 800, 500, 2160, 1250 }, 640x400 (6235) */
@@ -1127,10 +1221,14 @@ static const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] =
{ 5, 2,1350, 800, 2160, 1250 },
{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
- { 1, 1,2160,1250, 2160, 1250 }
+ { 1, 1,2160,1250, 2160, 1250 },
+ { 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 const SiS_LCDDataStruct SiS_NoScaleData[] =
+static const struct SiS_LCDData SiS_NoScaleData[] =
{
{ 1, 1, 800, 449, 800, 449 }, /* 0x00: 320x200, 640x400 */
{ 1, 1, 800, 449, 800, 449 },
@@ -1162,14 +1260,18 @@ static const SiS_LCDDataStruct SiS_NoScaleData[] =
{ 1, 1,1808, 808,1808, 808 }, /* 0x1b: 1360x768 */
{ 1, 1,1104, 563,1104, 563 }, /* 0x1c: 960x540 */
{ 1, 1,1120, 618,1120, 618 }, /* 0x1d: 960x600 */
- { 1, 1,1408, 816,1408, 816 } /* 0x1f: 1280x800 (TMDS special) */
+ { 1, 1,1408, 816,1408, 816 }, /* 0x1f: 1280x800 (TMDS special) */
+ { 1, 1,1760,1235,1760,1235 }, /* 0x20: 1600x1200 for LCDA */
+ { 1, 1,2048,1320,2048,1320 }, /* 0x21: 1600x1200 for non-SiS LVDS */
+ { 1, 1,1664, 861,1664, 861 } /* 0x22: 1280x854 */
};
/**************************************************************/
/* LVDS ----------------------------------------------------- */
/**************************************************************/
-static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]=
+/* FSTN/DSTN 320x240, 2 variants */
+static const struct SiS_LVDSData SiS_LVDS320x240Data_1[]=
{
{ 848, 433, 400, 525},
{ 848, 389, 400, 525},
@@ -1177,157 +1279,40 @@ static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]=
{ 848, 389, 400, 525},
{ 848, 518, 400, 525},
{1056, 628, 400, 525},
- { 400, 525, 400, 525},
- { 800, 449,1000, 644},
- { 800, 525,1000, 635}
+ { 400, 525, 400, 525} /* xSTN */
};
-static const SiS_LVDSDataStruct SiS_LVDS640x480Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS320x240Data_2[]=
{
- { 800, 445, 800, 525}, /* 800, 449, 800, 449 */
+ { 800, 445, 800, 525},
{ 800, 395, 800, 525},
{ 800, 445, 800, 525},
{ 800, 395, 800, 525},
{ 800, 525, 800, 525},
- { 800, 525, 800, 525}, /* pseudo */
- { 800, 525, 800, 525} /* pseudo */
+ {1056, 628,1056, 628},
+ { 480, 525, 480, 525} /* xSTN */
};
-/* FSTN 320x240 */
-static const SiS_LVDSDataStruct SiS_LVDS640x480Data_2[]=
+static const struct SiS_LVDSData SiS_LVDS640x480Data_1[]=
{
- { 800, 445, 800, 525},
+ { 800, 445, 800, 525}, /* 800, 449, 800, 449 */
{ 800, 395, 800, 525},
{ 800, 445, 800, 525},
{ 800, 395, 800, 525},
- { 800, 525, 800, 525},
- { 800, 525, 800, 525}, /* pseudo */
- { 800, 525, 800, 525} /* pseudo */
+ { 800, 525, 800, 525}
};
-static const SiS_LVDSDataStruct SiS_LVDS800x600Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS800x600Data_1[]=
{
{ 848, 433,1060, 629},
{ 848, 389,1060, 629},
{ 848, 433,1060, 629},
{ 848, 389,1060, 629},
{ 848, 518,1060, 629},
- {1056, 628,1056, 628},
{1056, 628,1056, 628}
};
-static const SiS_LVDSDataStruct SiS_LVDS800x600Data_2[]=
-{
- {1056, 628,1056, 628}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_1[]=
-{
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 518,1344, 806}, /* 640x480 */
- {1050, 638,1344, 806}, /* 800x600 */
- {1344, 806,1344, 806}, /* 1024x768 */
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_1[]=
-{
- {1048, 442,1688,1066},
- {1048, 392,1688,1066},
- {1048, 442,1688,1066},
- {1048, 392,1688,1066},
- {1048, 522,1688,1066},
- {1208, 642,1688,1066},
- {1432, 810,1688,1066},
- {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_2[]=
-{
- {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_1[]=
-{
- { 928, 416, 1688,1066},
- { 928, 366, 1688,1066},
- { 928, 416, 1688,1066},
- { 928, 366, 1688,1066},
- { 928, 496, 1688,1066},
- {1088, 616, 1688,1066},
- {1312, 784, 1688,1066},
- {1568,1040, 1688,1066},
- {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_2[]=
-{
- {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_1[]=
-{
- {1088, 520, 2048,1320},
- {1088, 470, 2048,1320},
- {1088, 520, 2048,1320},
- {1088, 470, 2048,1320},
- {1088, 600, 2048,1320},
- {1248, 720, 2048,1320},
- {1472, 888, 2048,1320},
- {1728,1144, 2048,1320},
- {1848,1170, 2048,1320},
- {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_2[]=
-{
- {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_1[]=
-{
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 438,1344, 806},
- { 840, 409,1344, 806},
- { 840, 518,1344, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806},
- { 800, 449,1280, 801},
- { 800, 525,1280, 813}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_1[]=
-{
- { 768, 438, 1408, 806},
- { 768, 388, 1408, 806},
- { 768, 438, 1408, 806},
- { 768, 388, 1408, 806},
- { 768, 518, 1408, 806},
- { 928, 638, 1408, 806},
- {1152, 806, 1408, 806},
- {1408, 806, 1408, 806},
- {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_2[]=
-{
- {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x600Data_1[] =
{
{ 840, 604,1344, 800},
{ 840, 560,1344, 800},
@@ -1338,124 +1323,18 @@ static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] =
{1344, 800,1344, 800}
};
-static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_2[] =
-{
- {1344, 800,1344, 800}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x768Data_1[]=
{
{ 840, 438,1344, 806},
{ 840, 409,1344, 806},
{ 840, 438,1344, 806},
{ 840, 409,1344, 806},
- { 840, 518,1344, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_2[] =
-{
- {1344, 806,1344, 806}
-};
-
-/* Pass 1:1 data */
-static const SiS_LVDSDataStruct SiS_LVDSXXXxXXXData_1[]=
-{
- { 800, 449, 800, 449},
- { 800, 449, 800, 449},
- { 900, 449, 900, 449},
- { 900, 449, 900, 449},
- { 800, 525, 800, 525}, /* 640x480 */
- {1056, 628, 1056, 628}, /* 800x600 */
- {1344, 806, 1344, 806}, /* 1024x768 */
- {1688,1066, 1688,1066}, /* 1280x1024 */ /* INSERTED */
- {1688, 806, 1688, 806}, /* 1280x768 */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_1[]=
-{
- { 832, 438,1331, 806},
- { 832, 388,1331, 806},
- { 832, 438,1331, 806},
- { 832, 388,1331, 806},
- { 832, 518,1331, 806},
- {1050, 638,1344, 806},
- {1344, 806,1344, 806},
- {1688,1066,1688,1066},
- {1688,1066,1688,1066} /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_2[]=
-{
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1344, 806,1344, 806},
- {1688,1066,1688,1066},
- {1688,1066,1688,1066} /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_1[]=
-{
- { 832, 438,1331, 806},
- { 832, 409,1331, 806},
- { 832, 438,1331, 806},
- { 832, 409,1331, 806},
- { 832, 518,1331, 806}, /* 640x480 */
+ { 840, 518,1344, 806}, /* 640x480 */
{1050, 638,1344, 806}, /* 800x600 */
{1344, 806,1344, 806}, /* 1024x768 */
};
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_2[]=
-{
- {1344, 806,1344, 806}
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct SiS_LVDS848x480Data_1[]=
-{
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 640x480 TODO */
- {1088, 525,1088, 525}, /* 800x600 TODO */
- {1088, 525,1088, 525}, /* 1024x768 TODO */
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 848x480 */
- {1088, 525,1088, 525} /* 1360x768 TODO */
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct SiS_LVDS848x480Data_2[]=
-{
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 640x480 */
- {1088, 525,1088, 525}, /* 800x600 */
- {1088, 525,1088, 525}, /* 1024x768 */
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- { 0, 0, 0, 0},
- {1088, 525,1088, 525}, /* 848x480 */
- {1088, 525,1088, 525} /* 1360x768 TODO */
-};
-
-static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVUNTSCData[]=
{
{ 840, 600, 840, 600},
{ 840, 600, 840, 600},
@@ -1466,7 +1345,7 @@ static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]=
{1160, 945,1160, 945}
};
-static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVONTSCData[]=
{
{ 840, 525, 840, 525},
{ 840, 525, 840, 525},
@@ -1477,55 +1356,9 @@ static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]=
{1160, 840,1160, 840}
};
-/* Chrontel TV Skew */
-
-static const SiS_LVDSDesStruct SiS_CHTVUNTSCDesData[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVONTSCDesData[]=
-{
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVUPALDesData[]=
-{
- {256, 0},
- {256, 0},
- {256, 0},
- {256, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
-static const SiS_LVDSDesStruct SiS_CHTVOPALDesData[]=
-{
- {256, 0},
- {256, 0},
- {256, 0},
- {256, 0},
- { 0, 0},
- { 0, 0},
- { 0, 0}
-};
-
/* CRT1 CRTC data for slave modes */
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_1[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1550,48 +1383,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] =
0x00 }}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
- 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
- 0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1_H[] =
-{
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
- 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
- 0x00}},
- {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
- 0x00}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2[] =
{
{{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
@@ -1611,12 +1403,17 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] =
{{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
0x01}},
+#if 0
{{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
0x00}}
+#endif
+ {{0x5f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00}},
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2_H[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1641,7 +1438,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3[] =
{
{{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
@@ -1666,7 +1463,7 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3_H[] =
{
{{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1691,778 +1488,175 @@ static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] =
0x00}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
- 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
- 0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
- 0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
- 0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
- 0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
- 0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
- 0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
- 0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
- 0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1[] =
-{
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
- 0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e,
- 0xec,0x8e,0xdf,0x05,0x20,0x00,0x01,
- 0x00}},
- {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0,
- 0x64,0x86,0x57,0x7d,0x20,0x00,0x05,
- 0x01}},
- {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1[] =
{
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
- 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
- 0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
- 0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
- 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
- 0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2[] =
-{
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3,
- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x02,
- 0x01}},
- {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1,
- 0xb6,0x88,0x57,0x25,0x10,0x00,0x02,
- 0x01}},
- {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x02,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
0x01}}
};
-static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
{
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3,
- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x01,
- 0x01}},
- {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1,
- 0xb6,0x88,0x57,0x25,0x10,0x00,0x01,
- 0x01}},
- {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x01,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
- 0x01}}
-};
-
-/**************************************************************/
-/* COMMON --------------------------------------------------- */
-/**************************************************************/
-
-#ifdef LINUX_XF86
-
-#define SIS_PL_HSYNCP 0x01
-#define SIS_PL_HSYNCN 0x02
-#define SIS_PL_VSYNCP 0x04
-#define SIS_PL_VSYNCN 0x08
-#define SIS_PL_DVI 0x80
-
-typedef struct _SiS_PlasmaModes
-{
- const char *name;
- ULONG clock;
- USHORT HDisplay, HTotal, HFrontPorch, HSyncWidth;
- USHORT VDisplay, VTotal, VFrontPorch, VSyncWidth;
- UCHAR SyncFlags;
-} SiS_PlasmaModes;
-
-typedef struct _SiS_PlasmaTables
-{
- USHORT vendor;
- UCHAR productnum;
- USHORT product[5];
- const char *DDCnames[5];
- const char *plasmaname;
- USHORT maxx,maxy;
- USHORT prefx, prefy;
- UCHAR modenum;
- UCHAR plasmamodes[20]; /* | 0x80 = DVI-capable, | 0x40 = analog */
-} SiS_PlasmaTables;
-
-static const SiS_PlasmaModes SiS_PlasmaMode[] = {
- { "640x400", /* 00: IBM 400@70 */
- 25175,
- 640, 800, 17, 64,
- 400, 449, 13, 2,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "640x480", /* 01: VESA 480@72 */
- 31500,
- 640, 832, 24, 40,
- 480, 520, 9, 3,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "800x600", /* 02: VESA 600@72 */
- 50000,
- 800, 1040, 56, 120,
- 600, 666, 37, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "864x480", /* 03: Cereb wide 1 */
- 42526,
- 864, 1134, 22, 86,
- 480, 500, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCN },
- { "848x480", /* 04: VESA wide (NEC1) */
- 33750,
- 848, 1088, 16, 112,
- 480, 517, 6, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1024x576", /* 05: VESA wide (NEC2) */
- 47250,
- 1024, 1320, 16, 144,
- 576, 596, 2, 4,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720", /* 06: VESA wide (NEC3) */
- 76500,
- 1280, 1696, 48, 176,
- 720, 750, 4, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1360x765", /* 07: VESA wide (NEC4) */
- 85500,
- 1360, 1792, 64, 176,
- 765, 795, 4, 8,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1024x600", /* 08: CEREB wide 2 */
- 51200,
- 1024, 1352, 51, 164,
- 600, 628, 1, 4,
- SIS_PL_HSYNCN | SIS_PL_VSYNCP },
- { "1024x768", /* 09: VESA 768@75 */
- 78750,
- 1024, 1312, 16, 96,
- 768, 800, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1152x864", /* 10: VESA 1152x864@75 */
- 108000,
- 1152, 1600, 64, 128,
- 864, 900, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x1024", /* 11: VESA 1024@60 */
- 108000,
- 1280, 1688, 48, 112,
- 1024, 1066, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x768", /* 12: W_XGA */
- 81000,
- 1280, 1688, 48, 112,
- 768, 802, 3, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCN },
- { "1280x768", /* 13: I/O Data W_XGA@56Hz */
- 76064,
- 1280, 1688, 48, 112,
- 768, 802, 2, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1376x768", /* 14: I/O Wide XGA */
- 87340,
- 1376, 1808, 32, 128,
- 768, 806, 3, 6,
- SIS_PL_HSYNCN | SIS_PL_VSYNCP },
- { "1280x960", /* 15: VESA 960@60 */
- 108000,
- 1280, 1800, 96, 112,
- 960, 1000, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1400x1050", /* 16: VESA 1050@60Hz */
- 108000,
- 1400, 1688, 48, 112,
- 1050, 1066, 1, 3,
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "1360x768", /* 17: VESA wide (NEC4/2) */
- 85500,
- 1360, 1792, 64, 112,
- 765, 795, 3, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "800x600", /* 18: VESA 600@56 */
- 36000,
- 800, 1024, 24, 2,
- 600, 625, 1, 2,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1072x600", /* 19: Panasonic 1072x600 (sync?) */
- 54100,
- 1072, 1424, 48, 176,
- 600, 628, 16, 1,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "848x480", /* 20: Panasonic 848x480 (sync?) */
- 33070, /* is 852x480, but we can't use 852 */
- 848, 1068, 20, 40, /* differs from DDC data, better centered */
- 480, 516, 3, 5, /* won't work assumingly, because data is % 8 */
- SIS_PL_HSYNCN | SIS_PL_VSYNCN },
- { "1280x720", /* 21: WIDE720(60) (aka "750p") (Panasonic) */
- 74300,
- 1280, 1650,110, 40,
- 720, 750, 5, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x768", /* 22: 1280x768@56.5 (Panasonic) */
- 76200, /* (According to manual not supported for HDMI; but works) */
- 1280, 1680, 16, 24,
- 768, 802, 2, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720@50", /* 23: WIDE720(50) (aka "750p") (Panasonic) */
- 74300, /* Panasonic states 45.0kHz. Not possible. This one works (with some overscan) */
- 1280, 1980,400, 80,
- 720, 750, 1, 2,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "720x480", /* 24: 720x480 (aka "525p" and "480p") (Panasonic) */
- 27000,
- 720, 856, 40, 32,
- 480, 525, 1, 3,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "720x576", /* 25: 720x576 (aka "625p"and "576p") (Panasonic) */
- 27500,
- 720, 864, 16, 64,
- 576, 625, 5, 6,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
- { "1280x720@50", /* 26: WIDE720(50) (aka "750p") (Generic) */
- 74300,
- 1280, 1980,400, 80,
- 720, 750, 5, 5,
- SIS_PL_HSYNCP | SIS_PL_VSYNCP },
+ {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+ 0x00}}
};
-/*
-27.00 720 755 791 858 480 480 484 525
-27.50 720 732 795 864 576 581 587 625
-*/
-
-static const SiS_PlasmaTables SiS_PlasmaTable[] = {
-#if 0 /* Product IDs missing */
- { 0x38a3, 4,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42VP4/42VP4D/42VP4G/42VP4DG",
- 0, 0,
- 0, 0,
- 11, /* All DVI, except 0, 7, 13 */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
+BOOLEAN SiSInitPtr(struct SiS_Private *SiS_Pr);
+#ifdef SIS_XORG_XF86
+unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+ int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
#endif
-#if 0 /* Product IDs missing */
- { 0x38a3, 3,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42PD1/50PD1/50PD2",
- 0, 0,
- 0, 0,
- 5, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0, 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42PD3",
- 0, 0,
- 0, 0,
- 10, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 7|0x40, 8|0xc0, 9|0xc0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 2,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42VM3/61XM1",
- 0, 0,
- 0, 0,
- 11, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 8|0xc0, 9|0xc0,11|0xc0,
- 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 2,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 42MP1/42MP2",
- 0, 0,
- 0, 0,
- 6, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 50MP1",
- 0, 0,
- 0, 0,
- 10, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
+unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, BOOLEAN FSTN,
+ unsigned short CustomT, int LCDwith, int LCDheight,
+ unsigned int VBFlags2);
+unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+
+void SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
+void SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
+void SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
+void SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
+unsigned char SiS_GetReg(SISIOADDRESS port, unsigned short index);
+unsigned char SiS_GetRegByte(SISIOADDRESS port);
+unsigned short SiS_GetRegShort(SISIOADDRESS port);
+unsigned int SiS_GetRegLong(SISIOADDRESS port);
+void SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
+ unsigned short DataOR);
+void SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
+void SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
+
+void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+#ifndef SIS_LINUX_KERNEL
+void SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
#endif
- { 0x38a3, 4,
- { 0xa482, 0xa483, 0x0000, 0x0000, 0x0000 },
- { "PX-42VM", "", "", "", "" },
- "NEC PlasmaSync 42MP3/42MP4/50MP2/61MP1",
- 0, 0,
- 0, 0,
- 11, /* All DVI except 0, 7, 13, 17 */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
- 17|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
-#if 0 /* Product IDs missing */
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 3300W",
- 0, 0,
- 0, 0,
- 3,
- { 0|0x40, 1|0xc0,18|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 4200W",
- 4, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 4210W",
- 0, 0,
- 0, 0,
- 6, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x38a3, 1,
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "NEC PlasmaSync 5000W",
- 0, 0,
- 0, 0,
- 7, /* DVI entirely unknown */
- { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,11|0xc0, 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
-#endif
- { 0x412f, 2,
- { 0x000c, 0x000b, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "Pioneer 503CMX/PDA-5002",
- 0, 0,
- 0, 0,
- 6, /* DVI unknown */
- { 1|0xc0, 2|0xc0, 9|0xc0,11|0xc0,12|0xc0,15|0xc0, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xa00e, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "", "", "", "", "" },
- "Panasonic TH-42",
- 0, 0,
- 0, 0,
- 5, /* No DVI output */
- { 1|0x40, 2|0x40, 4|0x40, 9|0x40,15|0x40, 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xa005, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "TH-42PW*4", "", "", "", "" },
- "Panasonic TH-42PW5",
- 0, 0,
- 0, 0,
- 1, /* No special modes otherwise; no DVI. */
- {20|0x40,19|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x4c2e, 1,
- { 0x9b05, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "PLV-Z2", "", "", "", "" },
- "Sanyo PLV-Z2 (non HDCP-mode)", /* HDCP mode would be id 9b06, but not needed */
- 1280, 768, /* as it then advertises correct size */
- 1280, 720,
- 1, /* 1280x720, no special modes otherwise */
- {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xd034, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "AE500U (DVI-D)", "", "", "", "" },
- "Panasonic AE500U",
- 1280, 768,
- 1280, 720,
- 1, /* 1280x720, no special modes otherwise */
- {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x34a9, 1,
- { 0xd043, 0x0000, 0x0000, 0x0000, 0x0000 },
- { "AE700U (HDMI)", "", "", "", "" },
- "Panasonic AE700U",
- 1360, 768,
- 1280, 720,
- 6, /* 1280x720/60, 1280x720/50, 1280x768@56(digital/analog), 720x480, 720x576 */
- {21|0xc0,23|0xc0,22|0x80,13|0x40,24|0x80,25|0x80, 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
- },
- { 0x0000 }
-};
+void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+BOOLEAN SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_GetVBType(struct SiS_Private *SiS_Pr);
#endif
-#ifdef LINUX_XF86
-USHORT SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
- int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
+BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex);
+unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+#ifdef SIS300
+void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+ unsigned short *idx2);
+unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
+unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
#endif
-USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
- USHORT CustomT, int LCDwith, int LCDheight);
-USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-void SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data);
-void SiS_SetRegByte(SISIOADDRESS port, USHORT data);
-void SiS_SetRegShort(SISIOADDRESS port, USHORT data);
-void SiS_SetRegLong(SISIOADDRESS port, ULONG data);
-UCHAR SiS_GetReg(SISIOADDRESS port, USHORT index);
-UCHAR SiS_GetRegByte(SISIOADDRESS port);
-USHORT SiS_GetRegShort(SISIOADDRESS port);
-ULONG SiS_GetRegLong(SISIOADDRESS port);
-void SiS_SetRegANDOR(SISIOADDRESS Port, USHORT Index, USHORT DataAND, USHORT DataOR);
-void SiS_SetRegAND(SISIOADDRESS Port,USHORT Index, USHORT DataAND);
-void SiS_SetRegOR(SISIOADDRESS Port,USHORT Index, USHORT DataOR);
-void SiS_DisplayOn(SiS_Private *SiS_Pr);
-void SiS_DisplayOff(SiS_Private *SiS_Pr);
-void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex);
-UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
-void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-
-#ifdef LINUX_XF86
-BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
-BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
- DisplayModePtr mode, BOOLEAN IsCustom);
-int SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber);
-int SiSTranslateToOldMode(int modenumber);
-BOOLEAN SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO);
-USHORT SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags);
-DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi);
-int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy);
-void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-#else
-BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo);
+void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
+ BOOLEAN dosetpitch);
+BOOLEAN SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom);
+#endif
+#ifdef SIS_LINUX_KERNEL
+BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+#endif
+void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, DisplayModePtr current);
+#endif
+#ifdef SIS_LINUX_KERNEL
+void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
#endif
-#ifdef LINUX_KERNEL
-int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, UCHAR rateindex);
-int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, UCHAR rateindex,
- struct fb_var_screeninfo *var);
-BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- UCHAR modeno, int *htotal, int *vtotal, UCHAR rateindex);
+/* From init301.c: */
+extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int chkcrt2mode);
+extern void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+extern void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+extern void SiS_DisableBridge(struct SiS_Private *);
+extern BOOLEAN SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+extern unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+extern BOOLEAN SiS_IsVAMode(struct SiS_Private *);
+extern BOOLEAN SiS_IsDualEdge(struct SiS_Private *);
+
+#ifdef SIS_XORG_XF86
+/* From other modules: */
+extern unsigned short SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ unsigned int VBFlags);
+extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
+ unsigned char value);
+extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
+extern unsigned short SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ unsigned int VBFlags);
#endif
-/* init301.c: */
-extern void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, int chkcrt2mode);
-extern void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo);
-extern void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT);
-extern USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo);
-extern void SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-extern USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-extern USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern BOOLEAN SiS_IsVAMode(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN SiS_IsDualEdge(SiS_Private *, PSIS_HW_INFO);
-
-#ifdef LINUX_XF86
-/* From other sis driver modules: */
-extern int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div,
- int *out_sbit, int *out_scale);
-extern void SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk);
-
-extern UCHAR SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, UCHAR value);
-extern UCHAR SiS_GetSetModeID(ScrnInfoPtr pScrn, UCHAR id);
-extern USHORT SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, ULONG VBFlags);
+#ifdef SIS_LINUX_KERNEL
+#ifdef SIS300
+extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
+ unsigned int val);
+#endif
+#ifdef SIS315H
+extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
+ unsigned char val);
+extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
#endif
#endif
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 274dacd54bb8..2d88f908170a 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -2,11 +2,12 @@
/* $XdotOrg$ */
/*
* Mode initializing code (CRT2 section)
- * for SiS 300/305/540/630/730 and
- * SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
+ * for SiS 300/305/540/630/730,
+ * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -38,7 +39,7 @@
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission.
* *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -54,20 +55,20 @@
* Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
* Used by permission.
*
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if marked TW or not.
- *
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#if 1
#define SET_EMI /* 302LV/ELV: Set EMI values */
#endif
+#if 1
+#define SET_PWD /* 301/302LV: Set PWD */
+#endif
+
#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */
#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */
#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */
@@ -85,26 +86,35 @@
#define SiS_I2CDELAY 1000
#define SiS_I2CDELAYSHORT 150
-static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
-static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx);
+static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
+#ifdef SIS_LINUX_KERNEL
+static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+#endif
/*********************************************/
/* HELPER: Lock/Unlock CRT2 */
/*********************************************/
void
-SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H)
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+ else if(SiS_Pr->ChipType >= SIS_315H)
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
else
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
}
-static void
-SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_LockCRT2(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType >= SIS_315H)
+ if(SiS_Pr->ChipType == XGI_20)
+ return;
+ else if(SiS_Pr->ChipType >= SIS_315H)
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
else
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
@@ -115,9 +125,9 @@ SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
+SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
{
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
DataAND &= 0x0f;
DataOR &= 0x0f;
}
@@ -129,12 +139,12 @@ SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, US
/*********************************************/
#ifdef SIS315H
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char *
+GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- UCHAR *myptr = NULL;
- USHORT romindex = 0, reg = 0, idx = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned char *myptr = NULL;
+ unsigned short romindex = 0, reg = 0, idx = 0;
/* Use the BIOS tables only for LVDS panels; TMDS is unreliable
* due to the variaty of panels the BIOS doesn't know about.
@@ -144,15 +154,15 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
if((SiS_Pr->SiS_ROMNew) &&
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
- if(HwInfo->jChipType < SIS_661) reg = 0x3c;
- else reg = 0x7d;
+ if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
+ else reg = 0x7d;
idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
if(idx < (8*26)) {
- myptr = (UCHAR *)&SiS_LCDStruct661[idx];
+ myptr = (unsigned char *)&SiS_LCDStruct661[idx];
}
romindex = SISGETROMW(0x100);
if(romindex) {
@@ -163,11 +173,11 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
return myptr;
}
-static USHORT
-GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = 0;
/* Use the BIOS tables only for LVDS panels; TMDS is unreliable
* due to the variaty of panels the BIOS doesn't know about.
@@ -177,12 +187,12 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
*/
if((SiS_Pr->SiS_ROMNew) &&
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
romptr = SISGETROMW(0x102);
romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
}
- return(romptr);
+ return romptr;
}
#endif
@@ -191,186 +201,187 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static BOOLEAN
-SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo)
+SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RRTI, unsigned short *i)
{
- USHORT checkmask=0,modeid,infoflag;
+ unsigned short checkmask=0, modeid, infoflag;
- modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
+ modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
- checkmask |= SupportRAMDAC2;
- if(HwInfo->jChipType >= SIS_315H) {
- checkmask |= SupportRAMDAC2_135;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- checkmask |= SupportRAMDAC2_162;
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
- checkmask |= SupportRAMDAC2_202;
- }
- }
- }
+ checkmask |= SupportRAMDAC2;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ checkmask |= SupportRAMDAC2_135;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ checkmask |= SupportRAMDAC2_162;
+ if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
+ checkmask |= SupportRAMDAC2_202;
+ }
+ }
+ }
- } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- checkmask |= SupportLCD;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- if(modeid == 0x2e) checkmask |= Support64048060Hz;
- }
- }
- }
+ checkmask |= SupportLCD;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(modeid == 0x2e) checkmask |= Support64048060Hz;
+ }
+ }
+ }
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- checkmask |= SupportHiVision;
+ checkmask |= SupportHiVision;
- } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
+ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
- checkmask |= SupportTV;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- checkmask |= SupportTV1024;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- checkmask |= SupportYPbPr750p;
- }
- }
- }
+ checkmask |= SupportTV;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ checkmask |= SupportTV1024;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+ checkmask |= SupportYPbPr750p;
+ }
+ }
+ }
- }
+ }
- } else { /* LVDS */
+ } else { /* LVDS */
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- checkmask |= SupportCHTV;
- }
- }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ checkmask |= SupportCHTV;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- checkmask |= SupportLCD;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ checkmask |= SupportLCD;
+ }
- }
+ }
- /* Look backwards in table for matching CRT2 mode */
- for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
- infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
- if(infoflag & checkmask) return TRUE;
- if((*i) == 0) break;
- }
+ /* Look backwards in table for matching CRT2 mode */
+ for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+ if(infoflag & checkmask) return TRUE;
+ if((*i) == 0) break;
+ }
- /* Look through the whole mode-section of the table from the beginning
- * for a matching CRT2 mode if no mode was found yet.
- */
- for((*i) = 0; ; (*i)++) {
- if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
- infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
- if(infoflag & checkmask) return TRUE;
- }
- return FALSE;
+ /* Look through the whole mode-section of the table from the beginning
+ * for a matching CRT2 mode if no mode was found yet.
+ */
+ for((*i) = 0; ; (*i)++) {
+ if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
+ infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+ if(infoflag & checkmask) return TRUE;
+ }
+ return FALSE;
}
/*********************************************/
/* Get rate index */
/*********************************************/
-USHORT
-SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
-{
- SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x00, 0x00, 0x00 };
- USHORT RRTI,i,backup_i;
- USHORT modeflag,index,temp,backupindex;
+unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+ unsigned short RRTI,i,backup_i;
+ unsigned short modeflag,index,temp,backupindex;
+ static const unsigned short LCDRefreshIndex[] = {
+ 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00
+ };
- /* Do NOT check for UseCustomMode here, will skrew up FIFO */
- if(ModeNo == 0xfe) return 0;
+ /* Do NOT check for UseCustomMode here, will skrew up FIFO */
+ if(ModeNo == 0xfe) return 0;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(modeflag & HalfDCLK) return 0;
- }
- }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(modeflag & HalfDCLK) return 0;
+ }
+ }
- if(ModeNo < 0x14) return 0xFFFF;
+ if(ModeNo < 0x14) return 0xFFFF;
- index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
- backupindex = index;
+ index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
+ backupindex = index;
- if(index > 0) index--;
+ if(index > 0) index--;
- if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
- else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
- temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
- if(index > temp) index = temp;
- }
- }
- } else {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
- }
- }
- }
+ if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
+ else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
+ temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
+ if(index > temp) index = temp;
+ }
+ }
+ } else {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
+ }
+ }
+ }
- RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
- ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
- if(HwInfo->jChipType >= SIS_315H) {
- if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
- if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
- (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
- if(backupindex <= 1) RRTI++;
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
+ if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
+ (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
+ if(backupindex <= 1) RRTI++;
+ }
+ }
+ }
- i = 0;
- do {
- if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
- temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
- temp &= ModeTypeMask;
- if(temp < SiS_Pr->SiS_ModeType) break;
- i++;
- index--;
- } while(index != 0xFFFF);
-
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
- if(temp & InterlaceMode) i++;
- }
- }
+ i = 0;
+ do {
+ if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
+ temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
+ temp &= ModeTypeMask;
+ if(temp < SiS_Pr->SiS_ModeType) break;
+ i++;
+ index--;
+ } while(index != 0xFFFF);
+
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
+ if(temp & InterlaceMode) i++;
+ }
+ }
- i--;
+ i--;
- if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
- backup_i = i;
- if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) {
- i = backup_i;
- }
- }
+ if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
+ backup_i = i;
+ if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
+ i = backup_i;
+ }
+ }
- return(RRTI + i);
+ return (RRTI + i);
}
/*********************************************/
@@ -378,15 +389,15 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp1,temp2;
+ unsigned short temp1, temp2;
- /* Store CRT1 ModeNo in CR34 */
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
- temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
- temp2 = ~(SetInSlaveMode >> 8);
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
+ /* Store CRT1 ModeNo in CR34 */
+ SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
+ temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
+ temp2 = ~(SetInSlaveMode >> 8);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
}
/*********************************************/
@@ -395,35 +406,35 @@ SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
#ifdef SIS300
static BOOLEAN
-SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,temp1;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp,temp1;
- if(SiS_Pr->SiS_UseROM) {
- if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
- temp1 = SISGETROMW(0x23b);
- if(temp1 & temp) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_Pr->SiS_UseROM) {
+ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+ temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+ temp1 = SISGETROMW(0x23b);
+ if(temp1 & temp) return TRUE;
+ }
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,temp1;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp,temp1;
- if(SiS_Pr->SiS_UseROM) {
- if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
- temp1 = SISGETROMW(0x23d);
- if(temp1 & temp) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_Pr->SiS_UseROM) {
+ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+ temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+ temp1 = SISGETROMW(0x23d);
+ if(temp1 & temp) return TRUE;
+ }
+ }
+ return FALSE;
}
#endif
@@ -432,85 +443,76 @@ SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime)
+SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
{
- USHORT i, j;
+ unsigned int i, j;
- for(i=0; i<delaytime; i++) {
- j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
- }
+ for(i = 0; i < delaytime; i++) {
+ j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
+ }
}
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- USHORT temp,flag;
-
- flag = SiS_GetRegByte(0x61) & 0x10;
-
- while(delay) {
- temp = SiS_GetRegByte(0x61) & 0x10;
- if(temp == flag) continue;
- flag = temp;
- delay--;
- }
+ SiS_DDC2Delay(SiS_Pr, delay * 36);
}
#endif
#ifdef SIS315H
static void
-SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- while(delay--) {
- SiS_GenericDelay(SiS_Pr,0x19df);
- }
+ while(delay--) {
+ SiS_GenericDelay(SiS_Pr, 6623);
+ }
}
#endif
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
{
- while(delay--) {
- SiS_GenericDelay(SiS_Pr,0x42);
- }
+ while(delay--) {
+ SiS_GenericDelay(SiS_Pr, 66);
+ }
}
#endif
static void
-SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
+SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
{
#if defined(SIS300) || defined(SIS315H)
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT PanelID, DelayIndex, Delay=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short PanelID, DelayIndex, Delay=0;
#endif
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
+ if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
}
DelayIndex = PanelID >> 4;
if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
- Delay = 3;
+ Delay = 3;
} else {
- if(DelayTime >= 2) DelayTime -= 2;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
- }
+ if(DelayTime >= 2) DelayTime -= 2;
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+ }
if(SiS_Pr->SiS_UseROM) {
- if(ROMAddr[0x220] & 0x40) {
- if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
- else Delay = (USHORT)ROMAddr[0x226];
- }
- }
+ if(ROMAddr[0x220] & 0x40) {
+ if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
+ else Delay = (unsigned short)ROMAddr[0x226];
+ }
+ }
}
SiS_ShortDelay(SiS_Pr, Delay);
@@ -520,23 +522,23 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
#ifdef SIS315H
- if((HwInfo->jChipType >= SIS_661) ||
- (HwInfo->jChipType <= SIS_315PRO) ||
- (HwInfo->jChipType == SIS_330) ||
+ if((SiS_Pr->ChipType >= SIS_661) ||
+ (SiS_Pr->ChipType <= SIS_315PRO) ||
+ (SiS_Pr->ChipType == SIS_330) ||
(SiS_Pr->SiS_ROMNew)) {
- if(!(DelayTime & 0x01)) {
+ if(!(DelayTime & 0x01)) {
SiS_DDC2Delay(SiS_Pr, 0x1000);
- } else {
+ } else {
SiS_DDC2Delay(SiS_Pr, 0x4000);
- }
+ }
} else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
- (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+ (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
}
@@ -546,35 +548,35 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
DelayIndex = PanelID >> 4;
}
if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
- Delay = 3;
- } else {
- if(DelayTime >= 2) DelayTime -= 2;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
- }
+ Delay = 3;
+ } else {
+ if(DelayTime >= 2) DelayTime -= 2;
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
+ }
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- if(ROMAddr[0x13c] & 0x40) {
- if(!(DelayTime & 0x01)) {
- Delay = (USHORT)ROMAddr[0x17e];
- } else {
- Delay = (USHORT)ROMAddr[0x17f];
- }
- }
- }
- }
+ if(ROMAddr[0x13c] & 0x40) {
+ if(!(DelayTime & 0x01)) {
+ Delay = (unsigned short)ROMAddr[0x17e];
+ } else {
+ Delay = (unsigned short)ROMAddr[0x17f];
+ }
+ }
+ }
+ }
SiS_ShortDelay(SiS_Pr, Delay);
}
} else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
- if(!(DelayTime & 0x01)) {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
- } else {
- Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
- }
+ if(!(DelayTime & 0x01)) {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+ } else {
+ Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+ }
Delay <<= 8;
SiS_DDC2Delay(SiS_Pr, Delay);
@@ -587,12 +589,11 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
#ifdef SIS315H
static void
-SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT DelayTime, USHORT DelayLoop)
+SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
{
int i;
- for(i=0; i<DelayLoop; i++) {
- SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime);
+ for(i = 0; i < DelayLoop; i++) {
+ SiS_PanelDelay(SiS_Pr, DelayTime);
}
}
#endif
@@ -602,86 +603,86 @@ SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/*********************************************/
void
-SiS_WaitRetrace1(SiS_Private *SiS_Pr)
+SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
{
- USHORT watchdog;
+ unsigned short watchdog;
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
- if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
- watchdog = 65535;
- while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
- watchdog = 65535;
- while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
+ watchdog = 65535;
+ while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
+ watchdog = 65535;
+ while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
}
#if defined(SIS300) || defined(SIS315H)
static void
-SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
+SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
{
- USHORT watchdog;
+ unsigned short watchdog;
- watchdog = 65535;
- while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
- watchdog = 65535;
- while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
+ watchdog = 65535;
+ while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
+ watchdog = 65535;
+ while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
}
#endif
static void
-SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
{
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
- }
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
- SiS_WaitRetrace1(SiS_Pr);
- } else {
- SiS_WaitRetrace2(SiS_Pr, 0x25);
- }
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
+ }
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
+ SiS_WaitRetrace1(SiS_Pr);
+ } else {
+ SiS_WaitRetrace2(SiS_Pr, 0x25);
+ }
#endif
- } else {
+ } else {
#ifdef SIS315H
- if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
- SiS_WaitRetrace1(SiS_Pr);
- } else {
- SiS_WaitRetrace2(SiS_Pr, 0x30);
- }
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
+ SiS_WaitRetrace1(SiS_Pr);
+ } else {
+ SiS_WaitRetrace2(SiS_Pr, 0x30);
+ }
#endif
- }
+ }
}
static void
-SiS_VBWait(SiS_Private *SiS_Pr)
+SiS_VBWait(struct SiS_Private *SiS_Pr)
{
- USHORT tempal,temp,i,j;
+ unsigned short tempal,temp,i,j;
- temp = 0;
- for(i=0; i<3; i++) {
- for(j=0; j<100; j++) {
- tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
- if(temp & 0x01) {
- if((tempal & 0x08)) continue;
- else break;
- } else {
- if(!(tempal & 0x08)) continue;
- else break;
- }
- }
- temp ^= 0x01;
- }
+ temp = 0;
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 100; j++) {
+ tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
+ if(temp & 0x01) {
+ if((tempal & 0x08)) continue;
+ else break;
+ } else {
+ if(!(tempal & 0x08)) continue;
+ else break;
+ }
+ }
+ temp ^= 0x01;
+ }
}
static void
-SiS_VBLongWait(SiS_Private *SiS_Pr)
+SiS_VBLongWait(struct SiS_Private *SiS_Pr)
{
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_VBWait(SiS_Pr);
- } else {
- SiS_WaitRetrace1(SiS_Pr);
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ SiS_VBWait(SiS_Pr);
+ } else {
+ SiS_WaitRetrace1(SiS_Pr);
+ }
}
/*********************************************/
@@ -690,237 +691,225 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
#ifdef SIS300
static BOOLEAN
-SiS_Is301B(SiS_Private *SiS_Pr)
+SiS_Is301B(struct SiS_Private *SiS_Pr)
{
- if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
- return FALSE;
+ if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType == SIS_730) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13);
- if(flag & 0x20) return TRUE;
- }
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & 0x20) return TRUE;
- return FALSE;
+ if(SiS_Pr->ChipType == SIS_730) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
+ return FALSE;
}
BOOLEAN
-SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableDualEdge) return TRUE;
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
+ }
+ }
#endif
- return FALSE;
+ return FALSE;
}
BOOLEAN
-SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAMode(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
+ }
#endif
- return FALSE;
+ return FALSE;
}
#ifdef SIS315H
static BOOLEAN
-SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
{
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) return TRUE;
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
- return FALSE;
+ if(SiS_IsVAMode(SiS_Pr)) return TRUE;
+ if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualLink(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ||
- (SiS_IsVAMode(SiS_Pr, HwInfo))) {
- if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if((SiS_CRT2IsLCD(SiS_Pr)) ||
+ (SiS_IsVAMode(SiS_Pr))) {
+ if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
+ }
+ }
#endif
- return FALSE;
+ return FALSE;
}
#ifdef SIS315H
static BOOLEAN
-SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_TVEnabled(struct SiS_Private *SiS_Pr)
{
- if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
- if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
- }
- return FALSE;
+ if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+ if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
{
- if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
- return FALSE;
+ if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
{
- if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
- }
- return FALSE;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType == SIS_650) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f);
- flag &= 0xF0;
- /* Check for revision != A0 only */
- if((flag == 0xe0) || (flag == 0xc0) ||
- (flag == 0xb0) || (flag == 0x90)) return FALSE;
- } else if(HwInfo->jChipType >= SIS_661) return FALSE;
- return TRUE;
+ if(SiS_Pr->ChipType == SIS_650) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+ /* Check for revision != A0 only */
+ if((flag == 0xe0) || (flag == 0xc0) ||
+ (flag == 0xb0) || (flag == 0x90)) return FALSE;
+ } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
+ return TRUE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ /* YPrPb = 0x08 */
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsChScart(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
-
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 */
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ /* Scart = 0x04 */
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToTV) return TRUE;
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
- if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */
- } else {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToTV) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToTV) return TRUE;
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
+ if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */
+ } else {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToTV) return TRUE;
+ }
+ return FALSE;
}
#endif
#ifdef SIS315H
static BOOLEAN
-SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(HwInfo->jChipType >= SIS_315H) {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToLCD) return TRUE;
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(flag & SetToLCDA) return TRUE;
- } else {
- flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(flag & SetCRT2ToLCD) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToLCD) return TRUE;
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(flag & SetToLCDA) return TRUE;
+ } else {
+ flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(flag & SetCRT2ToLCD) return TRUE;
+ }
+ return FALSE;
}
#endif
static BOOLEAN
-SiS_BridgeIsOn(SiS_Private *SiS_Pr)
+SiS_HaveBridge(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- return TRUE;
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
- if((flag == 1) || (flag == 2)) return TRUE;
- }
- return FALSE;
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ return TRUE;
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+ if((flag == 1) || (flag == 2)) return TRUE;
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
- if(SiS_BridgeIsOn(SiS_Pr)) {
- flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- if(HwInfo->jChipType < SIS_315H) {
- flag &= 0xa0;
- if((flag == 0x80) || (flag == 0x20)) return TRUE;
- } else {
- flag &= 0x50;
- if((flag == 0x40) || (flag == 0x10)) return TRUE;
- }
- }
- return FALSE;
+ if(SiS_HaveBridge(SiS_Pr)) {
+ flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ flag &= 0xa0;
+ if((flag == 0x80) || (flag == 0x20)) return TRUE;
+ } else {
+ flag &= 0x50;
+ if((flag == 0x40) || (flag == 0x10)) return TRUE;
+ }
+ }
+ return FALSE;
}
static BOOLEAN
-SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
{
- USHORT flag1;
+ unsigned short flag1;
- flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
- if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
- return FALSE;
+ flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
+ if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
+ return FALSE;
}
/*********************************************/
@@ -928,119 +917,97 @@ SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
/*********************************************/
/* Setup general purpose IO for Chrontel communication */
+#ifdef SIS300
void
-SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
+SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
{
- unsigned long acpibase;
+ unsigned int acpibase;
unsigned short temp;
if(!(SiS_Pr->SiS_ChSW)) return;
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000874); /* get ACPI base */
- acpibase = SiS_GetRegLong(0xcfc);
+#ifdef SIS_LINUX_KERNEL
+ acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
#else
acpibase = pciReadLong(0x00000800, 0x74);
#endif
acpibase &= 0xFFFF;
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
+ if(!acpibase) return;
+ temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
temp &= 0xFEFF;
- SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp);
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
+ SiS_SetRegShort((acpibase + 0x3c), temp);
+ temp = SiS_GetRegShort((acpibase + 0x3c));
+ temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
temp &= 0xFEFF;
if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
- SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp);
- temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));
+ SiS_SetRegShort((acpibase + 0x3a), temp);
+ temp = SiS_GetRegShort((acpibase + 0x3a));
}
+#endif
void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, int checkcrt2mode)
+SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int checkcrt2mode)
{
- USHORT tempax,tempbx,temp;
- USHORT modeflag, resinfo=0;
+ unsigned short tempax, tempbx, temp;
+ unsigned short modeflag, resinfo = 0;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
+ SiS_Pr->SiS_SetFlag = 0;
- SiS_Pr->SiS_SetFlag = 0;
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
- SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
+ SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
- tempbx = 0;
- if(SiS_BridgeIsOn(SiS_Pr)) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-#if 0
- if(HwInfo->jChipType < SIS_661) {
- /* NO - YPbPr not set yet ! */
- if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
- temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */
- temp |= SetCRT2ToHiVision; /* 0x80 */
- }
- if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
- temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */
- temp |= SetCRT2ToSVIDEO; /* 0x08 */
- }
- }
-#endif
- tempbx |= temp;
- tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
- tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
- tempbx |= tempax;
+ if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+
+ tempbx = 0;
+
+ if(SiS_HaveBridge(SiS_Pr)) {
+
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ tempbx |= temp;
+ tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
+ tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
+ tempbx |= tempax;
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
if(ModeNo == 0x03) {
- /* Mode 0x03 is never in driver mode */
+ /* Mode 0x03 is never in driver mode */
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
}
if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
- /* Reset LCDA setting if not driver mode */
+ /* Reset LCDA setting if not driver mode */
SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
}
if(IS_SIS650) {
- if(SiS_Pr->SiS_UseLCDA) {
+ if(SiS_Pr->SiS_UseLCDA) {
if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
}
}
}
}
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
- tempbx |= SetCRT2ToLCDA;
+ if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
+ tempbx |= SetCRT2ToLCDA;
}
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
- tempbx &= ~(SetCRT2ToRAMDAC);
- }
-
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
- if(temp & 0x04) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
- if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
- else tempbx |= SetCRT2ToYPbPr525750;
- }
- } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) {
- if(temp & 0x04) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
- if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+ if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+ else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ tempbx |= SetCRT2ToYPbPr525750;
}
}
- }
+ }
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1048,7 +1015,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx |= SetCRT2ToLCDA;
}
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(temp & EnableCHYPbPr) {
+ if(temp & EnableCHYPbPr) {
tempbx |= SetCRT2ToCHYPbPr;
}
}
@@ -1057,44 +1024,49 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif /* SIS315H */
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
+ tempbx &= ~(SetCRT2ToRAMDAC);
+ }
+
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
temp = SetCRT2ToSVIDEO |
- SetCRT2ToAVIDEO |
- SetCRT2ToSCART |
- SetCRT2ToLCDA |
- SetCRT2ToLCD |
- SetCRT2ToRAMDAC |
- SetCRT2ToHiVision |
+ SetCRT2ToAVIDEO |
+ SetCRT2ToSCART |
+ SetCRT2ToLCDA |
+ SetCRT2ToLCD |
+ SetCRT2ToRAMDAC |
+ SetCRT2ToHiVision |
SetCRT2ToYPbPr525750;
- } else {
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- temp = SetCRT2ToAVIDEO |
+ } else {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ temp = SetCRT2ToAVIDEO |
SetCRT2ToSVIDEO |
SetCRT2ToSCART |
SetCRT2ToLCDA |
SetCRT2ToLCD |
SetCRT2ToCHYPbPr;
- } else {
- temp = SetCRT2ToLCDA |
+ } else {
+ temp = SetCRT2ToLCDA |
SetCRT2ToLCD;
}
} else {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- temp = SetCRT2ToTV | SetCRT2ToLCD;
- } else {
- temp = SetCRT2ToLCD;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ temp = SetCRT2ToTV | SetCRT2ToLCD;
+ } else {
+ temp = SetCRT2ToLCD;
}
}
- }
+ }
+
+ if(!(tempbx & temp)) {
+ tempax = DisableCRT2Display;
+ tempbx = 0;
+ }
- if(!(tempbx & temp)) {
- tempax = DisableCRT2Display;
- tempbx = 0;
- }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- USHORT clearmask = ( DriverMode |
+ unsigned short clearmask = ( DriverMode |
DisableCRT2Display |
LoadDACFlag |
SetNotSimuMode |
@@ -1102,106 +1074,104 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SetPALTV |
SwitchCRT2 |
SetSimuScanMode );
- if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
+
+ if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
- } else {
- if(HwInfo->jChipType >= SIS_315H) {
+
+ } else {
+
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempbx & SetCRT2ToLCDA) {
- tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
+ tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
}
}
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(tempbx & SetCRT2ToTV) {
- tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(tempbx & SetCRT2ToTV) {
+ tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
}
- }
- if(tempbx & SetCRT2ToLCD) {
- tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(tempbx & SetCRT2ToLCD) {
+ tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
+ }
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempbx & SetCRT2ToLCDA) {
tempbx |= SetCRT2ToLCD;
}
}
+
}
- if(tempax & DisableCRT2Display) {
- if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
- tempbx = SetSimuScanMode | DisableCRT2Display;
- }
- }
+ if(tempax & DisableCRT2Display) {
+ if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
+ tempbx = SetSimuScanMode | DisableCRT2Display;
+ }
+ }
- if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
+ if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
- modeflag &= (~CRT2Mode);
+ modeflag &= (~CRT2Mode);
}
}
- if(!(tempbx & SetSimuScanMode)) {
- if(tempbx & SwitchCRT2) {
- if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
- if( (HwInfo->jChipType >= SIS_315H) &&
- (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
- if(resinfo != SIS_RI_1600x1200) {
- tempbx |= SetSimuScanMode;
- }
- } else {
- tempbx |= SetSimuScanMode;
- }
+ if(!(tempbx & SetSimuScanMode)) {
+ if(tempbx & SwitchCRT2) {
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if(resinfo != SIS_RI_1600x1200) {
+ tempbx |= SetSimuScanMode;
+ }
}
- } else {
- if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
- if(!(tempbx & DriverMode)) {
- if(SiS_BridgeInSlavemode(SiS_Pr)) {
+ } else {
+ if(SiS_BridgeIsEnabled(SiS_Pr)) {
+ if(!(tempbx & DriverMode)) {
+ if(SiS_BridgeInSlavemode(SiS_Pr)) {
tempbx |= SetSimuScanMode;
- }
- }
- }
- }
- }
-
- if(!(tempbx & DisableCRT2Display)) {
- if(tempbx & DriverMode) {
- if(tempbx & SetSimuScanMode) {
- if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
- if( (HwInfo->jChipType >= SIS_315H) &&
- (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
- if(resinfo != SIS_RI_1600x1200) {
- tempbx |= SetInSlaveMode;
- }
- } else {
- tempbx |= SetInSlaveMode;
- }
- }
- }
- } else {
- tempbx |= SetInSlaveMode;
- }
- }
+ }
+ }
+ }
+ }
+ }
- }
+ if(!(tempbx & DisableCRT2Display)) {
+ if(tempbx & DriverMode) {
+ if(tempbx & SetSimuScanMode) {
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if(resinfo != SIS_RI_1600x1200) {
+ tempbx |= SetInSlaveMode;
+ }
+ }
+ }
+ } else {
+ tempbx |= SetInSlaveMode;
+ }
+ }
- SiS_Pr->SiS_VBInfo = tempbx;
+ }
- if(HwInfo->jChipType == SIS_630) {
- SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
- }
+ SiS_Pr->SiS_VBInfo = tempbx;
-#ifdef TWDEBUG
-#ifdef LINUX_KERNEL
- printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n",
+#ifdef SIS300
+ if(SiS_Pr->ChipType == SIS_630) {
+ SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
+ }
+#endif
+
+#ifdef SIS_LINUX_KERNEL
+#if 0
+ printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
#endif
-#ifdef LINUX_XF86
- xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
+#endif
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
#endif
#endif
@@ -1212,41 +1182,41 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
void
-SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
{
- UCHAR temp;
+ unsigned char temp;
- /* Note: This variable is only used on 30xLV systems.
- * CR38 has a different meaning on LVDS/CH7019 systems.
- * On 661 and later, these bits moved to CR35.
- *
- * On 301, 301B, only HiVision 1080i is supported.
- * On 30xLV, 301C, only YPbPr 1080i is supported.
- */
+ /* Note: This variable is only used on 30xLV systems.
+ * CR38 has a different meaning on LVDS/CH7019 systems.
+ * On 661 and later, these bits moved to CR35.
+ *
+ * On 301, 301B, only HiVision 1080i is supported.
+ * On 30xLV, 301C, only YPbPr 1080i is supported.
+ */
- SiS_Pr->SiS_YPbPr = 0;
- if(HwInfo->jChipType >= SIS_661) return;
+ SiS_Pr->SiS_YPbPr = 0;
+ if(SiS_Pr->ChipType >= SIS_661) return;
- if(SiS_Pr->SiS_VBType) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_YPbPr = YPbPrHiVision;
- }
- }
+ if(SiS_Pr->SiS_VBType) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+ }
+ }
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(temp & 0x08) {
- switch((temp >> 4)) {
- case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
- case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
- case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
- case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
- }
- }
- }
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(temp & 0x08) {
+ switch((temp >> 4)) {
+ case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
+ case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
+ case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
+ case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+ }
+ }
+ }
+ }
}
@@ -1255,199 +1225,204 @@ SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
void
-SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo)
+SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp, temp1, resinfo = 0, romindex = 0;
- UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp, temp1, resinfo = 0, romindex = 0;
+ unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
- SiS_Pr->SiS_TVMode = 0;
+ SiS_Pr->SiS_TVMode = 0;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
- if(SiS_Pr->UseCustomMode) return;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+ if(SiS_Pr->UseCustomMode) return;
- if(ModeNo > 0x13) {
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
- }
+ if(ModeNo > 0x13) {
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
- if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- temp = 0;
- if((HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730)) {
- temp = 0x35;
- romindex = 0xfe;
- } else if(HwInfo->jChipType >= SIS_315H) {
- temp = 0x38;
- romindex = 0xf3;
- if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
- }
- if(temp) {
- if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- OutputSelect = ROMAddr[romindex];
- if(!(OutputSelect & EnablePALMN)) {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
- }
- }
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(temp1 & EnablePALM) { /* 0x40 */
- SiS_Pr->SiS_TVMode |= TVSetPALM;
- SiS_Pr->SiS_TVMode &= ~TVSetPAL;
- } else if(temp1 & EnablePALN) { /* 0x80 */
- SiS_Pr->SiS_TVMode |= TVSetPALN;
- }
- } else {
- if(temp1 & EnableNTSCJ) { /* 0x40 */
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- }
- /* Translate HiVision/YPbPr to our new flags */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
- else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
- else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
- else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
- SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
- SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
- } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- }
- }
- } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_CHOverScan) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
- if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- if(SiS_Pr->SiS_CHSOverScan) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
- else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
- } else {
- if(temp & EnableNTSCJ) {
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- }
- }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ temp = 0;
+ if((SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730)) {
+ temp = 0x35;
+ romindex = 0xfe;
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = 0x38;
+ if(SiS_Pr->ChipType < XGI_20) {
+ romindex = 0xf3;
+ if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
+ }
+ }
+ if(temp) {
+ if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+ OutputSelect = ROMAddr[romindex];
+ if(!(OutputSelect & EnablePALMN)) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
+ }
+ }
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(temp1 & EnablePALM) { /* 0x40 */
+ SiS_Pr->SiS_TVMode |= TVSetPALM;
+ SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+ } else if(temp1 & EnablePALN) { /* 0x80 */
+ SiS_Pr->SiS_TVMode |= TVSetPALN;
+ }
+ } else {
+ if(temp1 & EnableNTSCJ) { /* 0x40 */
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ }
+ /* Translate HiVision/YPbPr to our new flags */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+ else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+ else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
+ else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
+ SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
+ SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
+ } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ }
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_CHOverScan) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
+ if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ if(SiS_Pr->SiS_CHSOverScan) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
+ else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
+ } else {
+ if(temp & EnableNTSCJ) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ }
+ }
- } else { /* 661 and later */
+ } else { /* 661 and later */
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if(temp1 & 0x01) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(temp1 & 0x08) {
- SiS_Pr->SiS_TVMode |= TVSetPALN;
- } else if(temp1 & 0x04) {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SiS_Pr->SiS_TVMode &= ~TVSetPAL;
- }
- SiS_Pr->SiS_TVMode |= TVSetPALM;
- }
- } else {
- if(temp1 & 0x02) {
- SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
- }
- }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_Pr->SiS_CHOverScan) {
- if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
- SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
- }
- }
- }
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- temp1 &= 0xe0;
- if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
- else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
- else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
- if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
- SiS_Pr->SiS_TVMode |= TVAspect169;
- } else {
- temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
- if(temp1 & 0x02) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
- SiS_Pr->SiS_TVMode |= TVAspect169;
- } else {
- SiS_Pr->SiS_TVMode |= TVAspect43LB;
- }
- } else {
- SiS_Pr->SiS_TVMode |= TVAspect43;
- }
- }
- }
- }
- }
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+ if(temp1 & 0x01) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(temp1 & 0x08) {
+ SiS_Pr->SiS_TVMode |= TVSetPALN;
+ } else if(temp1 & 0x04) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+ }
+ SiS_Pr->SiS_TVMode |= TVSetPALM;
+ }
+ } else {
+ if(temp1 & 0x02) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+ }
+ }
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->SiS_CHOverScan) {
+ if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
+ SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+ }
+ }
+ }
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ temp1 &= 0xe0;
+ if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+ else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+ else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+ if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+ SiS_Pr->SiS_TVMode |= TVAspect169;
+ } else {
+ temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+ if(temp1 & 0x02) {
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+ SiS_Pr->SiS_TVMode |= TVAspect169;
+ } else {
+ SiS_Pr->SiS_TVMode |= TVAspect43LB;
+ }
+ } else {
+ SiS_Pr->SiS_TVMode |= TVAspect43;
+ }
+ }
+ }
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- SiS_Pr->SiS_TVMode |= TVSetPAL;
- SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
- SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ SiS_Pr->SiS_TVMode |= TVSetPAL;
+ SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
+ SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+ }
+ }
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
- if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
- if(resinfo == SIS_RI_1024x768) {
- SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
- }
- }
- }
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+ if(resinfo == SIS_RI_1024x768) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+ SiS_Pr->SiS_TVMode |= TVSet525p1024;
+ } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
+ SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
+ }
+ }
+ }
- SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
- (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
- }
- }
+ SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
+ (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+ SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+ }
+ }
- }
+ }
- SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+ SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+ xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+#endif
#endif
}
@@ -1455,41 +1430,46 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_IN
/* GET LCD INFO */
/*********************************************/
-static USHORT
-SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
{
- USHORT temp = SiS_Pr->SiS_LCDResInfo;
+ unsigned short temp = SiS_Pr->SiS_LCDResInfo;
/* Translate my LCDResInfo to BIOS value */
- if(temp == Panel_1280x768_2) temp = Panel_1280x768;
- if(temp == Panel_1280x800_2) temp = Panel_1280x800;
+ switch(temp) {
+ case Panel_1280x768_2: temp = Panel_1280x768; break;
+ case Panel_1280x800_2: temp = Panel_1280x800; break;
+ case Panel_1280x854: temp = Panel661_1280x854; break;
+ }
return temp;
}
static void
-SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- UCHAR *ROMAddr;
- USHORT temp;
+ unsigned char *ROMAddr;
+ unsigned short temp;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
- SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+ SiS_Pr->PanelHT, SiS_Pr->PanelVT,
SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
#endif
+#endif
- if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+ if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
- SiS_Pr->SiS_NeedRomModeData = TRUE;
+ SiS_Pr->SiS_NeedRomModeData = TRUE;
SiS_Pr->PanelHT = temp;
}
if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
- SiS_Pr->SiS_NeedRomModeData = TRUE;
- SiS_Pr->PanelVT = temp;
+ SiS_Pr->SiS_NeedRomModeData = TRUE;
+ SiS_Pr->PanelVT = temp;
}
SiS_Pr->PanelHRS = SISGETROMW(10);
SiS_Pr->PanelHRE = SISGETROMW(12);
@@ -1497,56 +1477,58 @@ SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_Pr->PanelVRE = SISGETROMW(16);
SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
- SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
+ SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Paneldata BIOS: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
- SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+ SiS_Pr->PanelHT, SiS_Pr->PanelVT,
SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
#endif
+#endif
}
#endif
}
static void
-SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes)
-{
- int i = 0;
- while(nonscalingmodes[i] != 0xff) {
- if(nonscalingmodes[i++] == resinfo) {
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
- (SiS_Pr->UsePanelScaler == -1)) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
- }
- }
+SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
+ const unsigned char *nonscalingmodes)
+{
+ int i = 0;
+ while(nonscalingmodes[i] != 0xff) {
+ if(nonscalingmodes[i++] == resinfo) {
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
+ (SiS_Pr->UsePanelScaler == -1)) {
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
+ }
+ }
}
void
-SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
+ unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
+ BOOLEAN panelcanscale = FALSE;
#ifdef SIS300
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- const unsigned char SiS300SeriesLCDRes[] =
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ static const unsigned char SiS300SeriesLCDRes[] =
{ 0, 1, 2, 3, 7, 4, 5, 8,
0, 0, 10, 0, 0, 0, 0, 15 };
#endif
#ifdef SIS315H
- UCHAR *myptr = NULL;
+ unsigned char *myptr = NULL;
#endif
- USHORT temp,modeflag,resinfo=0,modexres=0,modeyres=0;
- BOOLEAN panelcanscale = FALSE;
SiS_Pr->SiS_LCDResInfo = 0;
SiS_Pr->SiS_LCDTypeInfo = 0;
@@ -1557,14 +1539,14 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVRE = 999; /* VSync end */
SiS_Pr->SiS_NeedRomModeData = FALSE;
+ /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
+ SiS_Pr->Alternate1600x1200 = FALSE;
+
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+ if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
@@ -1575,16 +1557,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* For broken BIOSes: Assume 1024x768 */
if(temp == 0) temp = 0x02;
- if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
- } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+ } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
} else {
SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
}
temp &= 0x0f;
#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
/* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(temp < 0x0f) temp &= 0x07;
@@ -1595,17 +1577,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif
/* Translate to our internal types */
- if(HwInfo->jChipType == SIS_550) {
- if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
- if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
+#ifdef SIS315H
+ if(SiS_Pr->ChipType == SIS_550) {
+ if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
+ else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
+ else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
+ } else if(SiS_Pr->ChipType >= SIS_661) {
+ if(temp == Panel661_1280x854) temp = Panel_1280x854;
}
+#endif
- if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
if(temp == Panel310_1280x768) {
temp = Panel_1280x768_2;
}
if(SiS_Pr->SiS_ROMNew) {
- if(temp == Panel661_1280x800) {
+ if(temp == Panel661_1280x800) {
temp = Panel_1280x800_2;
}
}
@@ -1613,13 +1600,17 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDResInfo = temp;
+#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
+ SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+ SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+ } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ SiS_Pr->SiS_LCDResInfo = Panel_856x480;
}
}
+#endif
if(SiS_Pr->SiS_VBType & VB_SISVB) {
if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
@@ -1633,10 +1624,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
/* Need temp below! */
- /* These can't scale no matter what */
+ /* These must/can't scale no matter what */
switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
case Panel_1280x960:
SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+ break;
+ case Panel_640x480:
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
}
panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
@@ -1646,41 +1643,41 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* Dual link, Pass 1:1 BIOS default, etc. */
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
}
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if(SiS_Pr->SiS_ROMNew) {
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if(SiS_Pr->SiS_ROMNew) {
if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
- } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
- if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+ } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
+ if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
}
- } else if(HwInfo->jChipType >= SIS_315H) {
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
}
if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
- SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+ SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
- if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
} else if(!(SiS_Pr->SiS_ROMNew)) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
- if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+ if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
SiS_Pr->SiS_LCDInfo |= LCDDualLink;
}
- }
+ }
}
}
#endif
@@ -1691,12 +1688,12 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- /* Always center screen on SiS LVDS (if scaling is disabled) */
- SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ /* Always center screen on SiS LVDS (if scaling is disabled) */
+ SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
} else {
- /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
- if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
- if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
+ if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
}
}
@@ -1704,19 +1701,15 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_320x480: SiS_Pr->PanelXRes = 320; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelHT = 400; SiS_Pr->PanelVT = 525;
- SiS_Pr->PanelVCLKIdx300 = VCLK28;
- SiS_Pr->PanelVCLKIdx315 = VCLK28;
- break;
- case Panel_640x480_2:
- case Panel_640x480_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
+ SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK28;
SiS_Pr->PanelVCLKIdx315 = VCLK28;
break;
case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelVRE = 3;
+ SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK28;
SiS_Pr->PanelVCLKIdx315 = VCLK28;
break;
@@ -1728,52 +1721,52 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVCLKIdx315 = VCLK40;
break;
case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
- SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+ SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- break;
+ break;
case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
SiS_Pr->PanelHRS = 23;
- SiS_Pr->PanelVRE = 5;
+ SiS_Pr->PanelVRE = 5;
}
SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
- SiS_Pr->PanelHRS = 24;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
SiS_Pr->PanelHRS = 23;
- SiS_Pr->PanelVRE = 5;
+ SiS_Pr->PanelVRE = 5;
}
- SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+ SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
- break;
+ break;
case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
- break;
+ break;
case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
- SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
+ SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
/* Data above for TMDS (projector); get from BIOS for LVDS */
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
} else {
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
@@ -1781,77 +1774,100 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
break;
case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
- SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
+ SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
- SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
+ SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
+ break;
+ case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
+ SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
+ SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
+ SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
+ SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
- SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
+ SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
- if(resinfo == SIS_RI_1280x1024) {
+ if(resinfo == SIS_RI_1280x1024) {
SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
}
break;
case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
- SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; /* HRE OK for LVDS, not for LCDA */
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
- SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
+ SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
+ SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
+ SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
+ SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
+ SiS_Pr->Alternate1600x1200 = TRUE;
+ }
+ } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
+ SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
+ SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
+ SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
+ }
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
- SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
+ SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
- SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+ SiS_GetLCDInfoBIOS(SiS_Pr);
break;
case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
- SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
- break;
+ SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
+ break;
case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
- SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
- break;
+ SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
+ break;
+ case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
+ SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
+ break;
case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
- SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+ SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
SiS_Pr->PanelHT = SiS_Pr->CHTotal;
SiS_Pr->PanelVT = SiS_Pr->CVTotal;
if(SiS_Pr->CP_PreferredIndex != -1) {
SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
- SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+ SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
@@ -1863,22 +1879,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
if(SiS_Pr->CP_PrefClock) {
- int idx;
- SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+ int idx;
+ SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
- if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300;
+ if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
else idx = VCLK_CUSTOM_315;
- SiS_Pr->SiS_VCLKData[idx].CLOCK =
- SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
- SiS_Pr->SiS_VCLKData[idx].SR2B =
- SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
- SiS_Pr->SiS_VCLKData[idx].SR2C =
- SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
+ SiS_Pr->SiS_VCLKData[idx].CLOCK =
+ SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
+ SiS_Pr->SiS_VCLKData[idx].SR2B =
+ SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
+ SiS_Pr->SiS_VCLKData[idx].SR2C =
+ SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
}
}
break;
default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
- SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
+ SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
break;
}
@@ -1887,14 +1903,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
(SiS_Pr->SiS_IF_DEF_DSTN) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
SiS_Pr->PanelHRS = 999;
SiS_Pr->PanelHRE = 999;
}
if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
SiS_Pr->PanelVRS = 999;
SiS_Pr->PanelVRE = 999;
}
@@ -1912,18 +1930,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
case Panel_Custom:
case Panel_1152x864:
case Panel_1280x768: /* TMDS only */
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
break;
case Panel_800x600: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
}
case Panel_1024x768: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
0xff
@@ -1932,7 +1950,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
case Panel_1280x720: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
0xff
@@ -1944,7 +1962,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
case Panel_1280x768_2: { /* LVDS only */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,0xff
@@ -1952,23 +1970,23 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
switch(resinfo) {
case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
}
- break;
+ break;
}
case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1280x800_2: { /* SiS LVDS */
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,0xff
@@ -1977,66 +1995,83 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
switch(resinfo) {
case SIS_RI_1280x720:
case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
}
- break;
+ break;
+ }
+ case Panel_1280x854: { /* SiS LVDS */
+ static const unsigned char nonscalingmodes[] = {
+ SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+ SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+ SIS_RI_1152x768,0xff
+ };
+ SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+ switch(resinfo) {
+ case SIS_RI_1280x720:
+ case SIS_RI_1280x768:
+ case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
+ }
+ break;
}
case Panel_1280x960: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- 0xff
+ SIS_RI_1280x854,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1280x1024: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- SIS_RI_1280x960,0xff
+ SIS_RI_1280x854,SIS_RI_1280x960,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
}
case Panel_1400x1050: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
- SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960,
- 0xff
+ SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
+ SIS_RI_1280x960,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- switch(resinfo) {
+ switch(resinfo) {
case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- }
- break;
+ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+ }
+ break;
case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
- break;
+ break;
}
break;
}
case Panel_1600x1200: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
- SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
+ SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
- break;
+ break;
}
case Panel_1680x1050: {
- static const UCHAR nonscalingmodes[] = {
+ static const unsigned char nonscalingmodes[] = {
SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
- SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,
- 0xff
+ SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
+ SIS_RI_1360x1024,0xff
};
SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
break;
@@ -2044,25 +2079,25 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
+#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
+ if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
}
}
-#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(SiS_Pr->SiS_UseROM) {
+ if(SiS_Pr->SiS_UseROM) {
if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- if(!(ROMAddr[0x235] & 0x02)) {
- SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
- }
+ if(!(ROMAddr[0x235] & 0x02)) {
+ SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+ }
}
- }
- } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
- SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+ SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
}
}
}
@@ -2080,7 +2115,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_640x480:
- SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
break;
case Panel_1280x800:
/* Don't pass 1:1 by default (TMDS special) */
@@ -2097,7 +2132,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
break;
}
- if(SiS_Pr->UseCustomMode) {
+ if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
}
@@ -2107,19 +2142,19 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
/* LVDS DDA */
- if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
+ if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
if(ModeNo == 0x12) {
if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
}
} else if(ModeNo > 0x13) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
- if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
- SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+ SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
}
}
}
@@ -2128,18 +2163,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
if(modeflag & HalfDCLK) {
- if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+ if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
} else if(ModeNo > 0x13) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
- if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
- }
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+ if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ }
}
}
@@ -2148,21 +2183,21 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* VESA timing */
if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
- SiS_Pr->SiS_SetFlag |= LCDVESATiming;
+ SiS_Pr->SiS_SetFlag |= LCDVESATiming;
}
} else {
SiS_Pr->SiS_SetFlag |= LCDVESATiming;
}
-#ifdef LINUX_KERNEL
-#ifdef TWDEBUG
+#ifdef SIS_LINUX_KERNEL
+#if 0
printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
#endif
#endif
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
xf86DrvMsgVerb(0, X_PROBED, 4,
- "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
+ "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
#endif
}
@@ -2171,45 +2206,46 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* GET VCLK */
/*********************************************/
-USHORT
-SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
- USHORT modeflag,resinfo,tempbx;
- const UCHAR *CHTVVCLKPtr = NULL;
+ unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
+ unsigned short modeflag, resinfo, tempbx;
+ const unsigned char *CHTVVCLKPtr = NULL;
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
+ VCLKIndexGENCRT = VCLKIndexGEN;
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
- if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
+ VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
+ (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
}
if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- CRT2Index >>= 6;
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
+ CRT2Index >>= 6;
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = SiS_Pr->PanelVCLKIdx300;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- VCLKIndex = VCLKIndexGEN;
+ VCLKIndex = VCLKIndexGEN;
}
} else {
VCLKIndex = SiS_Pr->PanelVCLKIdx315;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
switch(resinfo) {
- /* Only those whose IndexGEN doesn't match VBVCLK array */
- case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
+ /* Correct those whose IndexGEN doesn't match VBVCLK array */
case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
@@ -2218,18 +2254,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+ case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
default: VCLKIndex = VCLKIndexGEN;
}
if(ModeNo <= 0x13) {
- if(HwInfo->jChipType <= SIS_315PRO) {
+ if(SiS_Pr->ChipType <= SIS_315PRO) {
if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
- } else {
+ } else {
if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
}
}
- if(HwInfo->jChipType <= SIS_315PRO) {
+ if(SiS_Pr->ChipType <= SIS_315PRO) {
if(VCLKIndex == 0) VCLKIndex = 0x41;
if(VCLKIndex == 1) VCLKIndex = 0x43;
if(VCLKIndex == 4) VCLKIndex = 0x44;
@@ -2237,49 +2274,46 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
- else VCLKIndex = HiTVVCLK;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(modeflag & Charx8Dot) VCLKIndex = HiTVSimuVCLK;
- else VCLKIndex = HiTVTextVCLK;
- }
- } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
- else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
- else VCLKIndex = TVVCLK;
-
- if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
- else VCLKIndex += TVCLKBASE_315;
-
- } else { /* VGA2 */
-
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30)) {
+ if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
+ else VCLKIndex = HiTVVCLK;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
+ } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
+ else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
+ else VCLKIndex = TVVCLK;
+
+ if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+ else VCLKIndex += TVCLKBASE_315;
+
+ } else { /* VGA2 */
+
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30)) {
if(VCLKIndex == 0x14) VCLKIndex = 0x34;
}
/* Better VGA2 clock for 1280x1024@75 */
if(VCLKIndex == 0x17) VCLKIndex = 0x45;
}
- }
- }
+ }
+ }
} else { /* If not programming CRT2 */
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType != SIS_630) &&
- (HwInfo->jChipType != SIS_300) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType != SIS_630) &&
+ (SiS_Pr->ChipType != SIS_300) ) {
if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
}
}
- }
+ }
}
} else { /* LVDS */
@@ -2288,12 +2322,12 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
- if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
+ if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
VCLKIndex &= 0x1f;
- tempbx = 0;
+ tempbx = 0;
if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
tempbx += 2;
if(SiS_Pr->SiS_ModeType > ModeVGA) {
if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
@@ -2306,66 +2340,68 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
}
}
- switch(tempbx) {
- case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
- case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
- case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
- case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
+ switch(tempbx) {
+ case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
+ case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
+ case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
+ case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
- case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
- case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
- case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
+ case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
+ case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
+ case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
- }
- VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+ }
+ VCLKIndex = CHTVVCLKPtr[VCLKIndex];
- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = SiS_Pr->PanelVCLKIdx300;
} else {
VCLKIndex = SiS_Pr->PanelVCLKIdx315;
}
+#ifdef SIS300
/* Special Timing: Barco iQ Pro R series */
if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
- /* Special Timing: 848x480 parallel lvds */
- if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
- if(HwInfo->jChipType < SIS_315H) {
+ /* Special Timing: 848x480 and 856x480 parallel lvds panels */
+ if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+ if(SiS_Pr->ChipType < SIS_315H) {
VCLKIndex = VCLK34_300;
- /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
+ /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
} else {
VCLKIndex = VCLK34_315;
/* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
}
}
+#endif
- } else {
+ } else {
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30) ) {
if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
- }
- }
+ }
+ }
}
- }
+ }
} else { /* if not programming CRT2 */
- VCLKIndex = VCLKIndexGEN;
- if(HwInfo->jChipType < SIS_315H) {
- if(ModeNo > 0x13) {
- if( (HwInfo->jChipType != SIS_630) &&
- (HwInfo->jChipType != SIS_300) ) {
+ VCLKIndex = VCLKIndexGENCRT;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(ModeNo > 0x13) {
+ if( (SiS_Pr->ChipType != SIS_630) &&
+ (SiS_Pr->ChipType != SIS_300) ) {
if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
}
#if 0
- if(HwInfo->jChipType == SIS_730) {
+ if(SiS_Pr->ChipType == SIS_730) {
if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
}
@@ -2377,11 +2413,13 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
#endif
+#endif
- return(VCLKIndex);
+ return VCLKIndex;
}
/*********************************************/
@@ -2389,26 +2427,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT i,j,modeflag;
- USHORT tempcl,tempah=0;
+ unsigned short i, j, modeflag, tempah=0;
+ short tempcl;
#if defined(SIS300) || defined(SIS315H)
- USHORT tempbl;
+ unsigned short tempbl;
#endif
#ifdef SIS315H
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT tempah2, tempbl2;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short tempah2, tempbl2;
#endif
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- } else if(SiS_Pr->UseCustomMode) {
- modeflag = SiS_Pr->CModeFlag;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -2418,18 +2449,18 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else {
for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
}
tempcl = SiS_Pr->SiS_ModeType;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---- 300 series ---- */
- /* For 301BDH: (with LCD via LVDS) */
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+ /* For 301BDH: (with LCD via LVDS) */
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) {
tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
tempbl &= 0xef;
tempbl |= 0x02;
@@ -2438,16 +2469,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbl &= 0xfd;
}
SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
- }
+ }
- if(ModeNo > 0x13) {
- tempcl -= ModeVGA;
- if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
- tempah = ((0x10 >> tempcl) | 0x80);
- }
- } else tempah = 0x80;
+ if(ModeNo > 0x13) {
+ tempcl -= ModeVGA;
+ if(tempcl >= 0) {
+ tempah = ((0x10 >> tempcl) | 0x80);
+ }
+ } else tempah = 0x80;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
#endif /* SIS300 */
@@ -2455,22 +2486,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS315H /* ------- 315/330 series ------ */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08);
- }
- }
-
- if(ModeNo > 0x13) {
- tempcl -= ModeVGA;
- if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
- tempah = (0x08 >> tempcl);
- if (tempah == 0) tempah = 1;
- tempah |= 0x40;
- }
- } else tempah = 0x40;
+ if(ModeNo > 0x13) {
+ tempcl -= ModeVGA;
+ if(tempcl >= 0) {
+ tempah = (0x08 >> tempcl);
+ if (tempah == 0) tempah = 1;
+ tempah |= 0x40;
+ }
+ } else tempah = 0x40;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
#endif /* SIS315H */
@@ -2478,84 +2503,89 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
} else {
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(IS_SIS740) {
+#ifdef SIS315H
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(IS_SIS740) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
} else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
}
- }
+ }
+#endif
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- tempah = 0x01;
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- tempah |= 0x02;
- }
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- tempah ^= 0x05;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- tempah ^= 0x01;
- }
- }
+ tempah = 0x01;
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ tempah |= 0x02;
+ }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ tempah ^= 0x05;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+ tempah ^= 0x01;
+ }
+ }
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+ if(SiS_Pr->ChipType < SIS_315H) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
- tempah = (tempah << 5) & 0xFF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
- tempah = (tempah >> 5) & 0xFF;
+ tempah = (tempah << 5) & 0xFF;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
+ tempah = (tempah >> 5) & 0xFF;
- } else {
+ } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
+ else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
+ tempah &= ~0x08;
- }
+ }
- if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
- tempah |= 0x10;
- }
+ if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+ tempah |= 0x10;
+ }
tempah |= 0x80;
- if(SiS_Pr->SiS_VBType & VB_SIS301) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
- }
+ }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- tempah |= 0x20;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ tempah |= 0x20;
}
- }
- }
+ }
+ }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
tempah = 0x80;
if(SiS_Pr->SiS_VBType & VB_SIS301) {
if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
}
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40;
+ if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
- tempah |= 0x40;
- }
- }
+ tempah |= 0x40;
+ }
+ }
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
} else { /* LVDS */
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
#ifdef SIS315H
/* LVDS can only be slave in 8bpp modes */
@@ -2566,36 +2596,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
}
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- tempah |= 0x02;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tempah ^= 0x01;
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- tempah = 1;
- }
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
#endif
- } else {
+ } else {
#ifdef SIS300
tempah = 0;
if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
- tempah |= 0x02;
- }
+ tempah |= 0x02;
+ }
tempah <<= 5;
- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
#endif
- }
+ }
}
@@ -2603,10 +2627,10 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
#ifdef SIS315H
- unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+ /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
/* The following is nearly unpreditable and varies from machine
* to machine. Especially the 301DH seems to be a real trouble
@@ -2619,25 +2643,28 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* 740 variants match for 30xB, 301B-DH, 30xLV */
- if(!(IS_SIS740)) {
- tempah = 0x04; /* For all bridges */
- tempbl = 0xfb;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempah = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(!(IS_SIS740)) {
+ tempah = 0x04; /* For all bridges */
+ tempbl = 0xfb;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempbl = 0xff;
}
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
}
/* The following two are responsible for eventually wrong colors
* in TV output. The DH (VB_NoLCD) conditions are unknown; the
* b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
* in a 650 box (Jake). What is the criteria?
+ * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
+ * treatment like the 651+301B-DH(b0) case. Seems more to be the
+ * chipset than the bridge revision.
*/
- if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
tempah = 0x30;
tempbl = 0xc0;
if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
@@ -2649,20 +2676,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
} else if(SiS_Pr->SiS_VBType & VB_SIS301) {
/* Fixes "TV-blue-bug" on 315+301 */
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
- } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
- } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xB-DH rev b0 (or "DH on 651"?) */
+ } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
+ } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
+ tempah = 0x30; tempah2 = 0xc0;
+ tempbl = 0xcf; tempbl2 = 0x3f;
+ if(SiS_Pr->SiS_TVBlue == 0) {
+ tempah = tempah2 = 0x00;
+ } else if(SiS_Pr->SiS_TVBlue == -1) {
+ /* Set on 651/M650, clear on 315/650 */
+ if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
+ tempah = tempah2 = 0x00;
+ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
} else {
- tempah = 0x30; tempah2 = 0xc0; /* For 30xB (and 301BDH rev b1) */
+ tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
tempbl = 0xcf; tempbl2 = 0x3f;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
tempah = tempah2 = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempbl = tempbl2 = 0xff;
}
}
@@ -2676,23 +2713,23 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
} else {
tempah = 0x00;
- tempbl = 0x7f;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempbl = 0xff;
- if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
+ tempbl = 0x7f;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempbl = 0xff;
+ if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
}
#endif /* SIS315H */
- } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
#ifdef SIS300
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
- if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
- ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+ if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+ ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
} else {
@@ -2702,9 +2739,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
}
}
@@ -2712,16 +2749,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else { /* LVDS */
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- tempah = 0x04;
+ tempah = 0x04;
tempbl = 0xfb;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- tempah = 0x00;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+ if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
+ }
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
@@ -2730,7 +2767,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
- } else if(HwInfo->jChipType == SIS_550) {
+ } else if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
@@ -2748,212 +2785,120 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* GET RESOLUTION DATA */
/*********************************************/
-USHORT
-SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+unsigned short
+SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
- else return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
+ if(ModeNo <= 0x13)
+ return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+ else
+ return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
}
static void
-SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT xres,yres,modeflag=0,resindex;
+ unsigned short xres, yres, modeflag=0, resindex;
- if(SiS_Pr->UseCustomMode) {
- xres = SiS_Pr->CHDisplay;
- if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
- SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
- yres = SiS_Pr->CVDisplay;
- if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
- SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
- return;
- }
-
- resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
+ if(SiS_Pr->UseCustomMode) {
+ xres = SiS_Pr->CHDisplay;
+ if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
+ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+ /* DoubleScanMode-check done in CheckCalcCustomMode()! */
+ SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+ return;
+ }
- if(ModeNo <= 0x13) {
- xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
- yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
- } else {
- xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
- yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- }
+ resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
+ if(ModeNo <= 0x13) {
+ xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
+ yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
+ } else {
+ xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+ yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
- if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- if(yres == 350) yres = 400;
- }
- if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
- if(ModeNo == 0x12) yres = 400;
- }
- }
+ if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
- if(modeflag & HalfDCLK) xres *= 2;
- if(modeflag & DoubleScanMode) yres *= 2;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
+ if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+ if(yres == 350) yres = 400;
+ }
+ if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
+ if(ModeNo == 0x12) yres = 400;
+ }
+ }
- }
+ if(modeflag & HalfDCLK) xres <<= 1;
+ if(modeflag & DoubleScanMode) yres <<= 1;
- if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+ }
-#if 0
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
- if(xres == 720) xres = 640;
- }
-#endif
+ if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- switch(SiS_Pr->SiS_LCDResInfo) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_1024x768:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- if(yres == 350) yres = 357;
- if(yres == 400) yres = 420;
- if(yres == 480) yres = 525;
- }
- }
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ if(yres == 350) yres = 357;
+ if(yres == 400) yres = 420;
+ if(yres == 480) yres = 525;
+ }
+ }
break;
case Panel_1280x1024:
if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
/* BIOS bug - does this regardless of scaling */
- if(yres == 400) yres = 405;
+ if(yres == 400) yres = 405;
+ }
+ if(yres == 350) yres = 360;
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ if(yres == 360) yres = 375;
}
- if(yres == 350) yres = 360;
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- if(yres == 360) yres = 375;
- }
break;
case Panel_1600x1200:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if(yres == 1024) yres = 1056;
- }
+ if(yres == 1024) yres = 1056;
+ }
break;
- }
- }
+ }
+ }
- } else {
+ } else {
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
- if(xres == 720) xres = 640;
- }
- } else if(xres == 720) xres = 640;
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+ if(xres == 720) xres = 640;
+ }
+ } else if(xres == 720) xres = 640;
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
- yres = 400;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
- } else {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
- }
- if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
- }
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+ yres = 400;
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+ } else {
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+ }
+ if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
+ }
- }
- SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
- SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
+ }
+ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+ SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
}
/*********************************************/
/* GET CRT2 TIMING DATA */
/*********************************************/
-static BOOLEAN
-SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, USHORT *ResIndex,
- USHORT *DisplayType)
- {
- USHORT modeflag=0;
-
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
- }
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
- } else
- return FALSE;
-
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
-
- (*ResIndex) &= 0x3F;
-
- if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- (*DisplayType) = 18;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- (*DisplayType) += 2;
- if(SiS_Pr->SiS_ModeType > ModeVGA) {
- if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
- }
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- (*DisplayType) = 18; /* PALM uses NTSC data */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- (*DisplayType) = 20; /* PALN uses PAL data */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
- }
- }
- } else {
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480: (*DisplayType) = 50; break;
- case Panel_640x480_2: (*DisplayType) = 52; break;
- case Panel_640x480_3: (*DisplayType) = 54; break;
- case Panel_800x600: (*DisplayType) = 0; break;
- case Panel_1024x600: (*DisplayType) = 23; break;
- case Panel_1024x768: (*DisplayType) = 4; break;
- case Panel_1152x768: (*DisplayType) = 27; break;
- case Panel_1280x768: (*DisplayType) = 40; break;
- case Panel_1280x1024: (*DisplayType) = 8; break;
- case Panel_1400x1050: (*DisplayType) = 14; break;
- case Panel_1600x1200: (*DisplayType) = 36; break;
- default: return FALSE;
- }
-
- if(modeflag & HalfDCLK) (*DisplayType)++;
-
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480:
- case Panel_640x480_2:
- case Panel_640x480_3:
- break;
- default:
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
- }
-
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- (*DisplayType) = 12;
- if(modeflag & HalfDCLK) (*DisplayType)++;
- }
- }
-
-#if 0
- if(SiS_Pr->SiS_IF_DEF_FSTN) {
- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
- (*DisplayType) = 22;
- }
- }
-#endif
-
- return TRUE;
-}
-
static void
-SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
- PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
+ unsigned short *ResIndex)
{
- USHORT tempbx=0,tempal=0,resinfo=0;
+ unsigned short tempbx=0, tempal=0, resinfo=0;
if(ModeNo <= 0x13) {
tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2966,18 +2911,20 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
- tempbx = SiS_Pr->SiS_LCDResInfo;
+ tempbx = SiS_Pr->SiS_LCDResInfo;
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+ /* patch index */
if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
if (resinfo == SIS_RI_1280x800) tempal = 9;
else if(resinfo == SIS_RI_1400x1050) tempal = 11;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) {
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
if (resinfo == SIS_RI_1280x768) tempal = 9;
}
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
/* Pass 1:1 only (center-screen handled outside) */
/* This is never called for the panel's native resolution */
/* since Pass1:1 will not be set in this case */
@@ -2991,8 +2938,8 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- tempbx = 200;
- if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+ tempbx = 200;
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
}
}
}
@@ -3000,23 +2947,23 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
} else { /* TV */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
- tempbx = 2;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
+ tempbx = 2;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
tempbx = 13;
- if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
- }
+ if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
+ }
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
- else tempbx = 5;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
- else tempbx = 4;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
- }
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
+ else tempbx = 5;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
+ } else {
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
+ else tempbx = 4;
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
+ }
}
@@ -3024,26 +2971,34 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(ModeNo > 0x13) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
- if(tempal == 6) tempal = 7;
- if((resinfo == SIS_RI_720x480) ||
- (resinfo == SIS_RI_720x576) ||
- (resinfo == SIS_RI_768x576)) {
+ switch(resinfo) {
+ case SIS_RI_720x480:
tempal = 6;
- if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
- if(resinfo == SIS_RI_720x480) tempal = 9;
+ if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
+ break;
+ case SIS_RI_720x576:
+ case SIS_RI_768x576:
+ case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
+ tempal = 6;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
}
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
- if(resinfo == SIS_RI_1024x768) tempal = 8;
+ break;
+ case SIS_RI_800x480:
+ tempal = 4;
+ break;
+ case SIS_RI_512x384:
+ case SIS_RI_1024x768:
+ tempal = 7;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
}
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- if((resinfo == SIS_RI_720x576) ||
- (resinfo == SIS_RI_768x576)) {
- tempal = 8;
- }
- if(resinfo == SIS_RI_1280x720) tempal = 9;
+ break;
+ case SIS_RI_1280x720:
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
}
+ break;
}
}
}
@@ -3056,65 +3011,60 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx = 0;
if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- tempbx = 10;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- tempbx += 2;
+ tempbx = 90;
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ tempbx = 92;
if(SiS_Pr->SiS_ModeType > ModeVGA) {
if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
}
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- tempbx = 90;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- tempbx = 92;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
- }
- }
+ if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
+ else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
+ }
+ if(tempbx != 99) {
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
+ }
} else {
- switch(SiS_Pr->SiS_LCDResInfo) {
- case Panel_640x480: tempbx = 6; break;
- case Panel_640x480_2:
- case Panel_640x480_3: tempbx = 30; break;
- case Panel_800x600: tempbx = 0; break;
- case Panel_1024x600: tempbx = 15; break;
- case Panel_1024x768: tempbx = 2; break;
- case Panel_1152x768: tempbx = 17; break;
- case Panel_1280x768: tempbx = 18; break;
- case Panel_1280x1024: tempbx = 4; break;
- case Panel_1400x1050: tempbx = 8; break;
- case Panel_1600x1200: tempbx = 21; break;
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_640x480: tempbx = 12; break;
+ case Panel_320x240_1: tempbx = 10; break;
+ case Panel_320x240_2:
+ case Panel_320x240_3: tempbx = 14; break;
+ case Panel_800x600: tempbx = 16; break;
+ case Panel_1024x600: tempbx = 18; break;
+ case Panel_1152x768:
+ case Panel_1024x768: tempbx = 20; break;
+ case Panel_1280x768: tempbx = 22; break;
+ case Panel_1280x1024: tempbx = 24; break;
+ case Panel_1400x1050: tempbx = 26; break;
+ case Panel_1600x1200: tempbx = 28; break;
+#ifdef SIS300
case Panel_Barco1366: tempbx = 80; break;
+#endif
}
switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
case Panel_640x480:
- case Panel_640x480_2:
- case Panel_640x480_3:
break;
default:
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
}
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
+#ifdef SIS300
if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
tempbx = 82;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
- } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+ } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
tempbx = 84;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
}
-
- if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
- (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
- (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- tempal = 0;
- }
- }
+#endif
}
@@ -3124,12 +3074,11 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
}
static void
-SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT tempax=0,tempbx=0;
- USHORT temp1=0,modeflag=0,tempcx=0;
- USHORT index;
+ unsigned short tempax=0, tempbx=0, index, dotclock;
+ unsigned short temp1=0, modeflag=0, tempcx=0;
SiS_Pr->SiS_RVBHCMAX = 1;
SiS_Pr->SiS_RVBHCFACT = 1;
@@ -3143,10 +3092,12 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
+ dotclock = (modeflag & Charx8Dot) ? 8 : 9;
+
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
@@ -3158,22 +3109,16 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
tempbx |= tempcx;
temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
+ dotclock = 8;
+
}
if(temp1 & 0x01) tempbx |= 0x0100;
if(temp1 & 0x20) tempbx |= 0x0200;
tempax += 5;
-
- /* Charx8Dot is no more used (and assumed), so we set it */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- modeflag |= Charx8Dot;
- }
-
- if(modeflag & Charx8Dot) tempax *= 8;
- else tempax *= 9;
-
- if(modeflag & HalfDCLK) tempax <<= 1;
+ tempax *= dotclock;
+ if(modeflag & HalfDCLK) tempax <<= 1;
tempbx++;
@@ -3182,13 +3127,56 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
}
static void
-SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
+{
+ unsigned short ResIndex;
+
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ if(SiS_Pr->UseCustomMode) {
+ ResIndex = SiS_Pr->CHTotal;
+ if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+ } else {
+ if(ModeNo < 0x13) {
+ ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+ }
+ if(ResIndex == 0x09) {
+ if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
+ else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
+ }
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+ SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+ SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+ }
+ } else {
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ }
+ } else {
+ /* This handles custom modes and custom panels */
+ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
+ }
+}
+
+static void
+SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT CRT2Index, ResIndex;
- const SiS_LVDSDataStruct *LVDSData = NULL;
+ unsigned short CRT2Index, ResIndex, backup;
+ const struct SiS_LVDSData *LVDSData = NULL;
- SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
SiS_Pr->SiS_RVBHCMAX = 1;
@@ -3199,133 +3187,94 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
SiS_Pr->SiS_RY2COE = 0;
SiS_Pr->SiS_RY3COE = 0;
SiS_Pr->SiS_RY4COE = 0;
+ SiS_Pr->SiS_RVBHRS2 = 0;
}
if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
#ifdef SIS315H
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
- } else {
- if(ModeNo < 0x13) {
- ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
- }
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
- SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
- SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
- }
- } else {
- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
- }
- } else {
- /* This handles custom modes and custom panels */
- SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
- SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
- }
-
- SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
-
+ SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
#endif
} else {
/* 301BDH needs LVDS Data */
+ backup = SiS_Pr->SiS_IF_DEF_LVDS;
if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
SiS_Pr->SiS_IF_DEF_LVDS = 1;
}
SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &CRT2Index, &ResIndex, HwInfo);
+ &CRT2Index, &ResIndex);
- /* 301BDH needs LVDS Data */
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- SiS_Pr->SiS_IF_DEF_LVDS = 0;
- }
+ SiS_Pr->SiS_IF_DEF_LVDS = backup;
- switch (CRT2Index) {
- case 0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
- case 1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2; break;
- case 2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
- case 3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2; break;
- case 4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1; break;
- case 5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2; break;
- case 6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
- case 7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1; break;
- case 8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1; break;
- case 9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2; break;
- case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
- case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
- case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
- case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
- case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1; break;
- case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
- case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2; break;
- case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1; break;
- case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2; break;
- case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1; break;
- case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2; break;
- case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1; break;
- case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2; break;
- case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2; break;
+ switch(CRT2Index) {
+ case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
+ case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
+ case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
+ case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
+ case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
+ case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
+#ifdef SIS300
case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
- case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2; break;
case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
- case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
- case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
- case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
- case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
- case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break; /* Super Overscan */
- default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
+#endif
+ case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
+ case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
+ case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
+ case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
+ case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
+ case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
+ case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
+ case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
+ case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
}
- SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
- SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
- SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
- SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
-
- if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
- SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
- if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
- if(ResIndex < 0x08) {
- SiS_Pr->SiS_HDE = 1280;
- SiS_Pr->SiS_VDE = 1024;
- }
- }
- }
+ if(LVDSData) {
+ SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+ SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+ SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
+ SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
+ } else {
+ SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+
+ if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
+ (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+ (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+ if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
+ (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
+ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+#ifdef SIS300
+ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+ if(ResIndex < 0x08) {
+ SiS_Pr->SiS_HDE = 1280;
+ SiS_Pr->SiS_VDE = 1024;
+ }
+ }
+#endif
}
}
}
}
static void
-SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
-{
- UCHAR *ROMAddr = NULL;
- USHORT tempax,tempbx,modeflag,romptr=0;
- USHORT resinfo,CRT2Index,ResIndex;
- const SiS_LCDDataStruct *LCDPtr = NULL;
- const SiS_TVDataStruct *TVPtr = NULL;
+SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned char *ROMAddr = NULL;
+ unsigned short tempax, tempbx, modeflag, romptr=0;
+ unsigned short resinfo, CRT2Index, ResIndex;
+ const struct SiS_LCDData *LCDPtr = NULL;
+ const struct SiS_TVData *TVPtr = NULL;
#ifdef SIS315H
- SHORT resinfo661;
+ short resinfo661;
#endif
if(ModeNo <= 0x13) {
@@ -3340,67 +3289,69 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
#ifdef SIS315H
resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
- (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
- (resinfo661 >= 0) &&
+ (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+ (resinfo661 >= 0) &&
(SiS_Pr->SiS_NeedRomModeData) ) {
- if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+ if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
if((romptr = (SISGETROMW(21)))) {
- romptr += (resinfo661 * 10);
- ROMAddr = HwInfo->pjVirtualRomBase;
+ romptr += (resinfo661 * 10);
+ ROMAddr = SiS_Pr->VirtualRomBase;
}
}
}
#endif
}
-
+
SiS_Pr->SiS_NewFlickerMode = 0;
SiS_Pr->SiS_RVBHRS = 50;
SiS_Pr->SiS_RY1COE = 0;
SiS_Pr->SiS_RY2COE = 0;
SiS_Pr->SiS_RY3COE = 0;
SiS_Pr->SiS_RY4COE = 0;
+ SiS_Pr->SiS_RVBHRS2 = 0;
- SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo);
+ SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_RVBHCMAX = 1;
- SiS_Pr->SiS_RVBHCFACT = 1;
- SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
- SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+ SiS_Pr->SiS_RVBHCMAX = 1;
+ SiS_Pr->SiS_RVBHCFACT = 1;
SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
- SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+
+ tempax = SiS_Pr->CHTotal;
+ if(modeflag & HalfDCLK) tempax <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
} else {
- SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
- &CRT2Index,&ResIndex,HwInfo);
+ &CRT2Index,&ResIndex);
switch(CRT2Index) {
- case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
- case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
- case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
- case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
- case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
- case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
- case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
- case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
- case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
- case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
- case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
- case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
- case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
- default: TVPtr = SiS_Pr->SiS_StPALData; break;
+ case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
+ case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
+ case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
+ case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
+ case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
+ case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
+ case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
+ case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
+ case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
+ case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
+ case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
+ case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
+ case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
+ default: TVPtr = SiS_Pr->SiS_StPALData; break;
}
SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3409,73 +3360,77 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
- SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
- SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
+ SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
if(modeflag & HalfDCLK) {
- SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+ if(SiS_Pr->SiS_RVBHRS2) {
+ SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+ tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
+ if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
+ else SiS_Pr->SiS_RVBHRS2 += tempax;
+ }
+ } else {
+ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
}
+ SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if((resinfo == SIS_RI_1024x768) ||
- (resinfo == SIS_RI_1280x1024) ||
- (resinfo == SIS_RI_1280x720)) {
+ if((resinfo == SIS_RI_960x600) ||
+ (resinfo == SIS_RI_1024x768) ||
+ (resinfo == SIS_RI_1280x1024) ||
+ (resinfo == SIS_RI_1280x720)) {
SiS_Pr->SiS_NewFlickerMode = 0x40;
}
- if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+ if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
- SiS_Pr->SiS_HT = ExtHiTVHT;
- SiS_Pr->SiS_VT = ExtHiTVVT;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- SiS_Pr->SiS_HT = StHiTVHT;
- SiS_Pr->SiS_VT = StHiTVVT;
-#if 0
- if(!(modeflag & Charx8Dot)) {
- SiS_Pr->SiS_HT = StHiTextTVHT;
- SiS_Pr->SiS_VT = StHiTextTVVT;
- }
-#endif
- }
- }
+ SiS_Pr->SiS_HT = ExtHiTVHT;
+ SiS_Pr->SiS_VT = ExtHiTVVT;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+ SiS_Pr->SiS_HT = StHiTVHT;
+ SiS_Pr->SiS_VT = StHiTVVT;
+ }
+ }
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- SiS_Pr->SiS_HT = 1650;
- SiS_Pr->SiS_VT = 750;
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+ SiS_Pr->SiS_HT = 1650;
+ SiS_Pr->SiS_VT = 750;
} else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
SiS_Pr->SiS_HT = NTSCHT;
+ if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
SiS_Pr->SiS_VT = NTSCVT;
- } else {
- SiS_Pr->SiS_HT = NTSCHT;
+ } else {
+ SiS_Pr->SiS_HT = NTSCHT;
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
- SiS_Pr->SiS_VT = NTSCVT;
- }
+ SiS_Pr->SiS_VT = NTSCVT;
+ }
} else {
- SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
- SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
- SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
- SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
+ SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
+ SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
+ SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
+ SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
- if(modeflag & HalfDCLK) {
- SiS_Pr->SiS_RY1COE = 0x00;
- SiS_Pr->SiS_RY2COE = 0xf4;
- SiS_Pr->SiS_RY3COE = 0x10;
- SiS_Pr->SiS_RY4COE = 0x38;
- }
+ if(modeflag & HalfDCLK) {
+ SiS_Pr->SiS_RY1COE = 0x00;
+ SiS_Pr->SiS_RY2COE = 0xf4;
+ SiS_Pr->SiS_RY3COE = 0x10;
+ SiS_Pr->SiS_RY4COE = 0x38;
+ }
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- SiS_Pr->SiS_HT = NTSCHT;
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+ SiS_Pr->SiS_HT = NTSCHT;
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
- SiS_Pr->SiS_VT = NTSCVT;
- } else {
- SiS_Pr->SiS_HT = PALHT;
- SiS_Pr->SiS_VT = PALVT;
- }
+ SiS_Pr->SiS_VT = NTSCVT;
+ } else {
+ SiS_Pr->SiS_HT = PALHT;
+ SiS_Pr->SiS_VT = PALVT;
+ }
}
@@ -3486,42 +3441,53 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->UseCustomMode) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
- SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
- SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
- SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+
+ tempax = SiS_Pr->CHTotal;
+ if(modeflag & HalfDCLK) tempax <<= 1;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
} else {
- BOOLEAN gotit = FALSE;
+ BOOLEAN gotit = FALSE;
- if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+ if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
- SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
gotit = TRUE;
} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
#ifdef SIS315H
SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
- SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
- SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
- SiS_Pr->SiS_VGAVT = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
- SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
- SiS_Pr->SiS_VT = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+ SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+ SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+ SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
+ SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+ SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
+ SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
+ if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
+ SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+ tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
+ if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
+ else SiS_Pr->SiS_RVBHRS2 += tempax;
+ }
if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
else {
SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+ SiS_Pr->SiS_RVBHCMAX = 1;
+ SiS_Pr->SiS_RVBHCFACT = 1;
SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
- SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
- SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+ SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+ SiS_Pr->SiS_RVBHRS2 = 0;
gotit = TRUE;
}
#endif
@@ -3530,28 +3496,30 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(!gotit) {
- SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
- &CRT2Index,&ResIndex,HwInfo);
+ SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ &CRT2Index,&ResIndex);
- switch(CRT2Index) {
+ switch(CRT2Index) {
case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
case Panel_1280x720 :
case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
- case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
+ case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
case Panel_1280x800 :
case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
case Panel_1280x800_2 :
case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
+ case Panel_1280x854 :
+ case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
case Panel_1280x960 :
case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
- case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
- case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
- case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
- case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
- case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
- case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
+ case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
+ case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
+ case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
+ case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
+ case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
+ case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
case Panel_1680x1050 :
case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
@@ -3559,271 +3527,340 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
#endif
- default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
- }
+ default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
+ }
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
- xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+ xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+#endif
#endif
- SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
- SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
- SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
- SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
- SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
- SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
+ SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
+ SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+ SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
+ SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
+ SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
+ SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
}
tempax = SiS_Pr->PanelXRes;
- tempbx = SiS_Pr->PanelYRes;
+ tempbx = SiS_Pr->PanelYRes;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- if(HwInfo->jChipType < SIS_315H) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
- }
- } else {
- if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
- else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
- else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
- else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
- else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
- }
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
- else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
- if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
- else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
- else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
- } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1024x768:
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+ }
+ } else {
+ if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
+ else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
+ else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
+ else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
+ else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+ }
+ break;
+ case Panel_1280x960:
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
+ else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
+ break;
+ case Panel_1280x1024:
+ if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+ else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+ else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+ break;
+ case Panel_1600x1200:
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
- }
- }
+ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
+ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
+ }
+ break;
+ }
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- tempax = SiS_Pr->SiS_VGAHDE;
- tempbx = SiS_Pr->SiS_VGAVDE;
- }
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempax = SiS_Pr->SiS_VGAHDE;
+ tempbx = SiS_Pr->SiS_VGAVDE;
+ }
- SiS_Pr->SiS_HDE = tempax;
- SiS_Pr->SiS_VDE = tempbx;
+ SiS_Pr->SiS_HDE = tempax;
+ SiS_Pr->SiS_VDE = tempbx;
}
}
}
static void
-SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- } else {
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- /* Need LVDS Data for LCD on 301B-DH */
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- } else {
- SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
- }
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ } else {
+ if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+ /* Need LVDS Data for LCD on 301B-DH */
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ } else {
+ SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
- } else {
+ } else {
- SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- }
+ }
}
/*********************************************/
/* GET LVDS DES (SKEW) DATA */
/*********************************************/
-static void
-SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, USHORT *PanelIndex,
- USHORT *ResIndex, PSIS_HW_INFO HwInfo)
+static const struct SiS_LVDSDes *
+SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
{
- USHORT modeflag;
+ const struct SiS_LVDSDes *PanelDesPtr = NULL;
- if(ModeNo <= 0x13) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- } else {
- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- }
+#ifdef SIS300
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDTypeInfo == 4) {
+ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
+ }
+ } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
+ }
+ }
+ }
+ }
+ }
+#endif
+ return PanelDesPtr;
+}
- (*ResIndex) &= 0x1F;
- (*PanelIndex) = 0;
+static void
+SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short modeflag, ResIndex;
+ const struct SiS_LVDSDes *PanelDesPtr = NULL;
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- (*PanelIndex) = 50;
- if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
- /* Nothing special needed for SOverscan */
- /* PALM uses NTSC data, PALN uses PAL data */
- }
- }
+ SiS_Pr->SiS_LCDHDES = 0;
+ SiS_Pr->SiS_LCDVDES = 0;
+ /* Some special cases */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
- if(HwInfo->jChipType >= SIS_661) {
- /* As long as we don's use the BIOS tables, we
- * need to convert the TypeInfo as for 315 series
- */
- (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
- }
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- (*PanelIndex) += 16;
- if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
- (*PanelIndex) = 32;
- if(modeflag & HalfDCLK) (*PanelIndex)++;
+
+ /* Trumpion */
+ if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ }
}
+ return;
}
- }
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
- (*ResIndex) = 7;
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
- }
+ /* 640x480 on LVDS */
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
+ SiS_Pr->SiS_LCDHDES = 8;
+ if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+ else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+ else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+ return;
+ }
}
- }
-}
-
-static void
-SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
- USHORT modeflag;
- USHORT PanelIndex,ResIndex;
- const SiS_LVDSDesStruct *PanelDesPtr = NULL;
- SiS_Pr->SiS_LCDHDES = 0;
- SiS_Pr->SiS_LCDVDES = 0;
+ } /* LCD */
if( (SiS_Pr->UseCustomMode) ||
(SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
(SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
- ((SiS_Pr->SiS_VBType & VB_SISVB) &&
- (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
- (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
+ (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
return;
}
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
#ifdef SIS315H
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
- /* non-pass 1:1 only, see above */
- if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
- SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+ /* non-pass 1:1 only, see above */
+ if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
}
if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
}
}
if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
- switch(SiS_Pr->SiS_CustomT) {
- case CUT_UNIWILL1024:
- case CUT_UNIWILL10242:
- case CUT_CLEVO1400:
+ switch(SiS_Pr->SiS_CustomT) {
+ case CUT_UNIWILL1024:
+ case CUT_UNIWILL10242:
+ case CUT_CLEVO1400:
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
}
break;
}
- if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1280x1024:
if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
}
+ break;
+ case Panel_1280x800: /* Verified for Averatec 6240 */
+ case Panel_1280x800_2: /* Verified for Asus A4L */
+ case Panel_1280x854: /* Not verified yet FIXME */
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ break;
}
}
#endif
} else {
- SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &PanelIndex, &ResIndex, HwInfo);
-
- switch(PanelIndex) {
- case 0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1; break; /* --- */
- case 1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1; break;
- case 2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1; break;
- case 3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1; break;
- case 4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1; break;
- case 5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1; break;
- case 6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1; break;
- case 7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1; break;
- case 8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1; break;
- case 9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1; break;
- case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1; break;
- case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1; break;
- case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1; break;
- case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1; break;
- case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1; break;
- case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1; break;
- case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2; break; /* --- */
- case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2; break;
- case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2; break;
- case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2; break;
- case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2; break;
- case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2; break;
- case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2; break;
- case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2; break;
- case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2; break;
- case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2; break;
- case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2; break;
- case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2; break;
- case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2; break;
- case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2; break;
- case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2; break;
- case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2; break;
- case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1; break; /* pass 1:1 */
- case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2; break;
- case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break; /* TV */
- case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
- case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData; break;
- case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData; break;
- default: return;
- }
-
- SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
- SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+ if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+ if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+ if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
+ }
+
+ } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
+
+ SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+ SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+
+ if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+ }
+ if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+ } else {
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_800x600:
+ case Panel_1024x768:
+ case Panel_1280x1024:
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+ break;
+ case Panel_1400x1050:
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ break;
+ }
+ }
+ }
+
+ } else {
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_800x600:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+ if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
+ else SiS_Pr->SiS_LCDVDES -= 4;
+ }
+ break;
+ case Panel_1024x768:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+ if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
+ if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
+ }
+ break;
+ case Panel_1024x600:
+ default:
+ if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
+ (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ } else {
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+ }
+ break;
+ }
+
+ switch(SiS_Pr->SiS_LCDTypeInfo) {
+ case 1:
+ SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
+ break;
+ case 3: /* 640x480 only? */
+ SiS_Pr->SiS_LCDHDES = 8;
+ if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+ else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+ else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+ break;
+ }
+#endif
+ } else {
+#ifdef SIS315H
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_1024x768:
+ case Panel_1280x1024:
+ if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+ SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+ }
+ break;
+ case Panel_320x240_1:
+ case Panel_320x240_2:
+ case Panel_320x240_3:
+ SiS_Pr->SiS_LCDVDES = 524;
+ break;
+ }
+#endif
+ }
+ }
if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
- } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
- if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
- if(HwInfo->jChipType < SIS_315H) {
+ } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+ if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+ if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
} else {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+#ifdef SIS315H
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
- if(!(modeflag & HalfDCLK)) {
- SiS_Pr->SiS_LCDHDES = 320;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+ if(!(modeflag & HalfDCLK)) {
+ SiS_Pr->SiS_LCDHDES = 320;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
- }
- }
- }
- }
- }
+ }
+#endif
+ }
+ }
+ }
+ }
}
}
}
@@ -3832,54 +3869,90 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
/* DISABLE VIDEO BRIDGE */
/*********************************************/
+#ifdef SIS315H
+static int
+SiS_HandlePWD(struct SiS_Private *SiS_Pr)
+{
+ int ret = 0;
+#ifdef SET_PWD
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
+ unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
+ unsigned short temp;
+
+ if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
+ (romptr) &&
+ (SiS_Pr->SiS_PWDOffset) ) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
+ temp = 0x00;
+ if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
+ temp = 0x80;
+ ret = 1;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
+#endif
+#endif
+ }
+#endif
+ return ret;
+}
+#endif
+
/* NEVER use any variables (VBInfo), this will be called
* from outside the context of modeswitch!
* MUST call getVBType before calling this
*/
void
-SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_DisableBridge(struct SiS_Private *SiS_Pr)
{
#ifdef SIS315H
- USHORT tempah,pushax=0,modenum;
+ unsigned short tempah, pushax=0, modenum;
#endif
- USHORT temp=0;
+ unsigned short temp=0;
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== For 30xB/LV ===== */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
} else {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
}
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_PanelDelay(SiS_Pr, 3);
}
if(SiS_Is301B(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
SiS_ShortDelay(SiS_Pr,1);
- }
+ }
SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
SiS_DisplayOff(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
- if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ SiS_UnLockCRT2(SiS_Pr);
+ if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
}
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
} else {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
}
@@ -3889,130 +3962,127 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
+ int didpwd = 0;
BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
(SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
}
}
#endif
- if( (modenum <= 0x13) ||
- (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
- if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+
+ didpwd = SiS_HandlePWD(SiS_Pr);
+
+ if( (modenum <= 0x13) ||
+ (SiS_IsVAMode(SiS_Pr)) ||
+ (!(SiS_IsDualEdge(SiS_Pr))) ) {
+ if(!didpwd) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
+ if(custom1) SiS_PanelDelay(SiS_Pr, 3);
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
+ }
}
if(!custom1) {
SiS_DDC2Delay(SiS_Pr,0xff00);
SiS_DDC2Delay(SiS_Pr,0xe000);
- SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
- pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+ SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+ pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
if(IS_SIS740) {
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
}
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_PanelDelay(SiS_Pr, 3);
}
- }
+ }
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- tempah = 0xef;
- if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /* if(SiS_Pr->ChipType < SIS_340) {*/
+ tempah = 0xef;
+ if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+ /*}*/
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
}
tempah = 0x3f;
- if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempah = 0x7f;
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+ if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
}
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
- if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+ if((SiS_IsVAMode(SiS_Pr)) ||
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
SiS_DisplayOff(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
}
- if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
- ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+ if((!(SiS_IsVAMode(SiS_Pr))) ||
+ ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
- if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+ if(!(SiS_IsDualEdge(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
SiS_DisplayOff(SiS_Pr);
}
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
}
- if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-
- if(!custom1) {
-
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
- if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
- if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- }
- }
- }
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+ if( (!(SiS_IsVAMode(SiS_Pr))) &&
+ (!(SiS_CRT2IsLCD(SiS_Pr))) &&
+ (!(SiS_IsDualEdge(SiS_Pr))) ) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
- }
- }
-
- } else {
+ if(custom1) SiS_PanelDelay(SiS_Pr, 2);
+ if(!didpwd) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+ }
+ if(custom1) SiS_PanelDelay(SiS_Pr, 4);
+ }
- if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
- if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
- (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- SiS_PanelDelay(SiS_Pr, HwInfo, 4);
+ if(!custom1) {
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 20);
}
}
-
}
- }
+
+ }
#endif /* SIS315H */
@@ -4020,36 +4090,36 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For 301 ================ */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
#endif
}
- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
- SiS_DisplayOff(SiS_Pr);
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
+ SiS_DisplayOff(SiS_Pr);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
- if(HwInfo->jChipType >= SIS_315H) {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
} else {
#ifdef SIS300
- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
#endif
}
@@ -4058,34 +4128,34 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For LVDS =============*/
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- SiS_SetCH700x(SiS_Pr,0x090E);
+ SiS_SetCH700x(SiS_Pr,0x0E,0x09);
}
- if(HwInfo->jChipType == SIS_730) {
+ if(SiS_Pr->ChipType == SIS_730) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
}
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
} else {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_WaitVBRetrace(SiS_Pr);
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
SiS_DisplayOff(SiS_Pr);
- }
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
- }
- }
+ }
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
+ }
+ }
}
}
@@ -4094,14 +4164,14 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
- if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
- (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+ (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
#endif /* SIS300 */
@@ -4110,113 +4180,113 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
- if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
- }
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+ /* } */
+ }
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 1) {
- SiS_SetCH701x(SiS_Pr,0xac76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
}
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
}
}
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsVAMode(SiS_Pr)) ) {
SiS_Chrontel701xBLOff(SiS_Pr);
- SiS_Chrontel701xOff(SiS_Pr,HwInfo);
+ SiS_Chrontel701xOff(SiS_Pr);
}
- if(HwInfo->jChipType != SIS_740) {
- if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
- SiS_SetCH701x(SiS_Pr,0x0149);
- }
+ if(SiS_Pr->ChipType != SIS_740) {
+ if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+ SiS_SetCH701x(SiS_Pr,0x49,0x01);
+ }
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
- SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+ SiS_PanelDelay(SiS_Pr, 3);
}
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
SiS_DisplayOff(SiS_Pr);
}
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
- if(HwInfo->jChipType == SIS_550) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
+ if(SiS_Pr->ChipType == SIS_550) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
}
}
} else {
- if(HwInfo->jChipType == SIS_740) {
- if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+ if(SiS_Pr->ChipType == SIS_740) {
+ if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
}
- } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+ } else if(SiS_IsVAMode(SiS_Pr)) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
/* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
} else {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
}
}
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
- if(HwInfo->jChipType == SIS_550) {
+ if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
} else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
- (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
- (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+ (!(SiS_IsDualEdge(SiS_Pr))) ||
+ (!(SiS_IsVAMode(SiS_Pr))) ) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 2);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
}
}
}
@@ -4237,78 +4307,81 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
* from outside the context of a mode switch!
* MUST call getVBType before calling this
*/
-static void
-SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_EnableBridge(struct SiS_Private *SiS_Pr)
{
- USHORT temp=0,tempah;
+ unsigned short temp=0, tempah;
#ifdef SIS315H
- USHORT temp1,pushax=0;
+ unsigned short temp1, pushax=0;
BOOLEAN delaylong = FALSE;
#endif
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ====== For 301B et al ====== */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
} else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
- if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
+ if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
}
if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
- (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+ (SiS_CRT2IsLCD(SiS_Pr))) {
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
- SiS_DisplayOn(SiS_Pr);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_DisplayOn(SiS_Pr);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
- }
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+ }
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
- }
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+ }
}
} else {
temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
- if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+ if(SiS_BridgeInSlavemode(SiS_Pr)) {
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
SiS_DisplayOn(SiS_Pr);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
- }
+ }
}
}
@@ -4322,31 +4395,32 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
#ifdef SET_EMI
- UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0;
- /* USHORT emidelay=0; */
+ unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
+ int didpwd = 0;
+ /* unsigned short emidelay=0; */
#endif
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
}
#endif
}
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) { */
tempah = 0x10;
- if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
- if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
- else tempah = 0x08;
+ if(SiS_LCDAEnabled(SiS_Pr)) {
+ if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
+ else tempah = 0x08;
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
- }
+ /*}*/
}
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
SiS_DisplayOff(SiS_Pr);
@@ -4355,42 +4429,51 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
}
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_GenericDelay(SiS_Pr, 0x4500);
+ didpwd = SiS_HandlePWD(SiS_Pr);
+
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ if(!didpwd) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 17664);
+ }
+ }
+ } else {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 17664);
}
}
}
if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
delaylong = TRUE;
}
}
- if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
+ if(!(SiS_IsVAMode(SiS_Pr))) {
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+ temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) {
- if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) {
+ if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
}
- }
- SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+ }
+ SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ SiS_PanelDelay(SiS_Pr, 2);
}
} else {
@@ -4402,38 +4485,48 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+ if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
+ if( (SiS_LCDAEnabled(SiS_Pr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr)) ) {
+ /* Enable "LVDS PLL power on" (even on 301C) */
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
+ /* Enable "LVDS Driver Power on" (even on 301C) */
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
+ }
+ }
+
tempah = 0xc0;
- if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualEdge(SiS_Pr)) {
tempah = 0x80;
- if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+ if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+ SiS_PanelDelay(SiS_Pr, 2);
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
#ifdef SET_EMI
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
- SiS_GenericDelay(SiS_Pr, 0x500);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+ SiS_GenericDelay(SiS_Pr, 2048);
}
#endif
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
#ifdef SET_EMI
cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
if(SiS_Pr->SiS_ROMNew) {
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
if(romptr) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
SiS_Pr->EMI_30 = 0;
SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
@@ -4511,21 +4604,21 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
if(!SiS_Pr->OverruleEMI) {
#ifdef COMPAL_HACK
if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
- if((cr36 & 0x0f) == 0x09) {
+ if((cr36 & 0x0f) == 0x09) {
r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
}
}
#endif
#ifdef COMPAQ_HACK
if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
- if((cr36 & 0x0f) == 0x03) {
+ if((cr36 & 0x0f) == 0x03) {
r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
}
}
#endif
#ifdef ASUS_HACK
if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
- if((cr36 & 0x0f) == 0x02) {
+ if((cr36 & 0x0f) == 0x02) {
/* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
/* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
/* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
@@ -4533,11 +4626,11 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
}
#endif
- }
+ }
if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_GenericDelay(SiS_Pr, 2048);
}
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
@@ -4547,36 +4640,44 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
#ifdef SET_EMI
- if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
- (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
- if(r30 & 0x40) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+ if( (SiS_LCDAEnabled(SiS_Pr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr)) ) {
+ if(r30 & 0x40) {
+ /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
+ SiS_PanelDelayLoop(SiS_Pr, 3, 5);
if(delaylong) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 5);
delaylong = FALSE;
}
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_WaitVBRetrace(SiS_Pr);
if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_GenericDelay(SiS_Pr, 1280);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
- }
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
+ /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
+ }
}
#endif
}
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if(SiS_IsVAorLCD(SiS_Pr)) {
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
if(delaylong) {
- SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+ SiS_PanelDelayLoop(SiS_Pr, 3, 10);
}
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_GenericDelay(SiS_Pr, 0x500);
+ SiS_WaitVBRetrace(SiS_Pr);
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_GenericDelay(SiS_Pr, 2048);
+ SiS_WaitVBRetrace(SiS_Pr);
+ }
+ if(!didpwd) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+ } else {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
}
}
@@ -4586,7 +4687,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
@@ -4596,26 +4697,26 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* ============ For 301 ================ */
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+ if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
}
SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
- if(HwInfo->jChipType >= SIS_315H) {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
- if(!(temp & 0x80)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
+ if(!(temp & 0x80)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
}
}
@@ -4623,15 +4724,15 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
SiS_VBLongWait(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
- if(HwInfo->jChipType >= SIS_315H) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
SiS_VBLongWait(SiS_Pr);
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
}
}
@@ -4639,49 +4740,49 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
} else { /* =================== For LVDS ================== */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(HwInfo->jChipType == SIS_730) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(SiS_Pr->ChipType == SIS_730) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
}
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 0);
}
}
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
SiS_DisplayOn(SiS_Pr);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
if(SiS_BridgeInSlavemode(SiS_Pr)) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
} else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
- if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
- SiS_WaitVBRetrace(SiS_Pr, HwInfo);
- SiS_SetCH700x(SiS_Pr,0x0B0E);
- }
+ if(!(SiS_CRT2IsLCD(SiS_Pr))) {
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
+ }
}
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
- if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- }
- SiS_WaitVBRetrace(SiS_Pr, HwInfo);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
- }
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+ if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_PanelDelay(SiS_Pr, 1);
+ }
+ SiS_WaitVBRetrace(SiS_Pr);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+ }
}
}
@@ -4691,94 +4792,94 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
#ifdef SIS315H /* 315 series */
- if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
- if(HwInfo->jChipType < SIS_340) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
- }
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+ /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+ /*}*/
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
- SiS_PanelDelay(SiS_Pr, HwInfo, 0);
- }
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+ SiS_PanelDelay(SiS_Pr, 0);
+ }
}
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
- SiS_UnLockCRT2(SiS_Pr,HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
temp &= 0x20;
SiS_Chrontel701xBLOff(SiS_Pr);
}
- if(HwInfo->jChipType != SIS_550) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+ if(SiS_Pr->ChipType != SIS_550) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
}
- if(HwInfo->jChipType == SIS_740) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ if(SiS_Pr->ChipType == SIS_740) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
}
}
}
temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
if(!(temp1 & 0x80)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(temp) {
- SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
+ if(temp) {
+ SiS_Chrontel701xBLOn(SiS_Pr);
}
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
- if(HwInfo->jChipType == SIS_550) {
+ if(SiS_Pr->ChipType == SIS_550) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
}
}
- } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
- if(HwInfo->jChipType != SIS_740) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ } else if(SiS_IsVAMode(SiS_Pr)) {
+ if(SiS_Pr->ChipType != SIS_740) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
}
}
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) {
- SiS_Chrontel701xOn(SiS_Pr,HwInfo);
- }
- if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
- SiS_ChrontelDoSomething1(SiS_Pr,HwInfo);
- }
+ if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
+ SiS_Chrontel701xOn(SiS_Pr);
+ }
+ if( (SiS_IsVAMode(SiS_Pr)) ||
+ (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+ SiS_ChrontelDoSomething1(SiS_Pr);
+ }
}
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
- (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
- SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
- SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo);
- }
- }
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if( (SiS_IsVAMode(SiS_Pr)) ||
+ (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+ SiS_Chrontel701xBLOn(SiS_Pr);
+ SiS_ChrontelInitTVVSync(SiS_Pr);
+ }
+ }
} else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
- if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
- SiS_PanelDelay(SiS_Pr, HwInfo, 1);
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+ if(SiS_CRT2IsLCD(SiS_Pr)) {
+ SiS_PanelDelay(SiS_Pr, 1);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
}
}
}
@@ -4797,243 +4898,204 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* Set CRT2 OFFSET / PITCH */
static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RRTI, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RRTI)
{
- USHORT offset;
- UCHAR temp;
+ unsigned short offset;
+ unsigned char temp;
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
- offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
+ offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
- offset >>= 1;
- }
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
- temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
- if(offset % 8) temp++;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
+ temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
+ if(offset & 0x07) temp++;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
}
/* Set CRT2 sync and PanelLink mode */
static void
-SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
{
- USHORT tempah=0,tempbl,infoflag;
+ unsigned short tempah=0, tempbl, infoflag;
- tempbl = 0xC0;
+ tempbl = 0xC0;
- if(SiS_Pr->UseCustomMode) {
- infoflag = SiS_Pr->CInfoFlag;
- } else {
- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
- }
+ if(SiS_Pr->UseCustomMode) {
+ infoflag = SiS_Pr->CInfoFlag;
+ } else {
+ infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ }
- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tempah = 0;
- } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
- tempah = SiS_Pr->SiS_LCDInfo;
- } else tempah = infoflag >> 8;
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
- (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- tempah |= 0xf0;
- }
- if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
- (SiS_Pr->SiS_IF_DEF_DSTN) ||
- (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
- tempah |= 0x30;
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(HwInfo->jChipType >= SIS_315H) {
- tempah >>= 3;
- tempah &= 0x18;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
- /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
- }
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ tempah = 0;
+ } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
+ tempah = SiS_Pr->SiS_LCDInfo;
+ } else tempah = infoflag >> 8;
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+ (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+ tempah |= 0xf0;
+ }
+ if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+ (SiS_Pr->SiS_IF_DEF_DSTN) ||
+ (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+ tempah |= 0x30;
+ }
+ if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+ (SiS_Pr->SiS_IF_DEF_DSTN) ) {
+ tempah &= ~0xc0;
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ tempah >>= 3;
+ tempah &= 0x18;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+ /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
+ }
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ }
- } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---- 300 series --- */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 630 - 301B(-DH) */
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
- tempah = infoflag >> 8;
- tempbl = 0;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempah = SiS_Pr->SiS_LCDInfo;
- tempbl = (tempah >> 6) & 0x03;
- }
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- tempah |= 0xc0;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
+ tempah = infoflag >> 8;
+ tempbl = 0;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempah = SiS_Pr->SiS_LCDInfo;
+ tempbl = (tempah >> 6) & 0x03;
+ }
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ tempah |= 0xc0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
- } else { /* 630 - 301 */
+ } else { /* 630 - 301 */
- tempah = infoflag >> 8;
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ tempah = ((infoflag >> 8) & 0xc0) | 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- }
+ }
#endif /* SIS300 */
- } else {
+ } else {
#ifdef SIS315H /* ------- 315 series ------ */
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 315 - LVDS */
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
- tempbl = 0;
- if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
- tempah = infoflag >> 8;
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
- }
- } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
- tempah = infoflag >> 8;
- tempbl = 0x03;
- } else {
- tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
- tempbl = (tempah >> 6) & 0x03;
- tempbl |= 0x08;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
- }
+ tempbl = 0;
+ if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+ tempah = infoflag >> 8;
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+ }
+ } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+ tempah = infoflag >> 8;
+ tempbl = 0x03;
+ } else {
+ tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+ tempbl = (tempah >> 6) & 0x03;
+ tempbl |= 0x08;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
+ }
- } else { /* 315 - TMDS */
+ } else { /* 315 - TMDS */
- tempah = tempbl = infoflag >> 8;
- if(!SiS_Pr->UseCustomMode) {
- tempbl = 0;
- if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- if(ModeNo <= 0x13) {
- tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
- }
- }
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
- tempah = SiS_Pr->SiS_LCDInfo;
+ tempah = tempbl = infoflag >> 8;
+ if(!SiS_Pr->UseCustomMode) {
+ tempbl = 0;
+ if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ if(ModeNo <= 0x13) {
+ tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+ tempah = SiS_Pr->SiS_LCDInfo;
tempbl = (tempah >> 6) & 0x03;
}
- }
- }
- }
- tempah &= 0xC0;
- tempah |= 0x20;
- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
- if(SiS_Pr->SiS_VBType & VB_NoLCD) {
- /* Imitate BIOS bug */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
- }
- if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
- tempah >>= 3;
- tempah &= 0x18;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
- } else {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
- }
- }
- }
+ }
+ }
+ }
+ tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+ /* Imitate BIOS bug */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
+ }
+ if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+ tempah >>= 3;
+ tempah &= 0x18;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+ }
+ }
+ }
- }
+ }
#endif /* SIS315H */
}
}
}
-/* Set CRT2 FIFO on 300/630/730 */
+/* Set CRT2 FIFO on 300/540/630/730 */
#ifdef SIS300
static void
-SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
- PSIS_HW_INFO HwInfo)
-{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT temp,index;
- USHORT modeidindex,refreshratetableindex;
- USHORT VCLK=0,MCLK,colorth=0,data2=0;
- USHORT tempal, tempah, tempbx, tempcl, tempax;
- USHORT CRT1ModeNo,CRT2ModeNo;
- USHORT SelectRate_backup;
- ULONG data,eax;
- const UCHAR LatencyFactor[] = {
- 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */
- 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */
- 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */
- 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */
- 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */
- 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */
- 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */
- 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */
- };
- const UCHAR LatencyFactor730[] = {
- 69, 63, 61,
- 86, 79, 77,
- 103, 96, 94,
- 120,113,111,
- 137,130,128, /* <-- last entry, data below */
- 137,130,128, /* to avoid using illegal values */
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- 137,130,128,
- };
- const UCHAR ThLowB[] = {
- 81, 4, 72, 6, 88, 8,120,12,
- 55, 4, 54, 6, 66, 8, 90,12,
- 42, 4, 45, 6, 55, 8, 75,12
- };
- const UCHAR ThTiming[] = {
- 1, 2, 2, 3, 0, 1, 1, 2
+SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
+{
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short temp, index, modeidindex, refreshratetableindex;
+ unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
+ unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
+ unsigned int data, pci50, pciA0;
+ static const unsigned char colortharray[] = {
+ 1, 1, 2, 2, 3, 4
};
SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
@@ -5044,232 +5106,159 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
SiS_Pr->SiS_SelectCRT2Rate = 0;
- refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo);
+ refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
if(CRT1ModeNo >= 0x13) {
- index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
- index &= 0x3F;
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ /* Get VCLK */
+ index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); /* Get colordepth */
- colorth >>= 1;
- if(!colorth) colorth++;
+ /* Get colordepth */
+ colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
+ if(!colorth) colorth++;
}
} else {
CRT1ModeNo = 0xfe;
- VCLK = SiS_Pr->CSRClock_CRT1; /* Get VCLK */
- data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2;
- switch(data2) { /* Get color depth */
- case 0 : colorth = 1; break;
- case 1 : colorth = 1; break;
- case 2 : colorth = 2; break;
- case 3 : colorth = 2; break;
- case 4 : colorth = 3; break;
- case 5 : colorth = 4; break;
- default: colorth = 2;
- }
+
+ /* Get VCLK */
+ VCLK = SiS_Pr->CSRClock_CRT1;
+
+ /* Get color depth */
+ colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
}
if(CRT1ModeNo >= 0x13) {
- if(HwInfo->jChipType == SIS_300) {
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
- } else {
- index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
- }
- index &= 0x07;
- MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
+ /* Get MCLK */
+ if(SiS_Pr->ChipType == SIS_300) {
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
+ } else {
+ index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
+ }
+ index &= 0x07;
+ MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
- data2 = (colorth * VCLK) / MCLK;
+ temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
+ if(!temp) temp++;
+ temp <<= 2;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- temp = ((temp & 0x00FF) >> 6) << 1;
- if(temp == 0) temp = 1;
- temp <<= 2;
- temp &= 0xff;
+ data2 = temp - ((colorth * VCLK) / MCLK);
- data2 = temp - data2;
+ temp = (28 * 16) % data2;
+ data2 = (28 * 16) / data2;
+ if(temp) data2++;
- if((28 * 16) % data2) {
- data2 = (28 * 16) / data2;
- data2++;
- } else {
- data2 = (28 * 16) / data2;
- }
+ if(SiS_Pr->ChipType == SIS_300) {
- if(HwInfo->jChipType == SIS_300) {
-
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
- tempah &= 0x62;
- tempah >>= 1;
- tempal = tempah;
- tempah >>= 3;
- tempal |= tempah;
- tempal &= 0x07;
- tempcl = ThTiming[tempal];
- tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
- tempbx >>= 6;
- tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- tempah >>= 4;
- tempah &= 0x0c;
- tempbx |= tempah;
- tempbx <<= 1;
- tempal = ThLowB[tempbx + 1];
- tempal *= tempcl;
- tempal += ThLowB[tempbx];
- data = tempal;
-
- } else if(HwInfo->jChipType == SIS_730) {
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
+ SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
+ data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
+
+ } else {
+
+#ifdef SIS_LINUX_KERNEL
+ pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+ pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
#else
- eax = pciReadLong(0x00000000, 0x50);
+ pci50 = pciReadLong(0x00000000, 0x50);
+ pciA0 = pciReadLong(0x00000000, 0xA0);
#endif
- tempal = (USHORT)(eax >> 8);
- tempal &= 0x06;
- tempal <<= 5;
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
-#else
- eax = pciReadLong(0x00000000, 0xA0);
-#endif
- temp = (USHORT)(eax >> 28);
- temp &= 0x0F;
- tempal |= temp;
-
- tempbx = tempal; /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
- tempbx = 0; /* -- do it like the BIOS anyway... */
- tempax = tempbx;
- tempbx &= 0xc0;
- tempbx >>= 6;
- tempax &= 0x0f;
- tempax *= 3;
- tempbx += tempax;
-
- data = LatencyFactor730[tempbx];
- data += 15;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(!(temp & 0x80)) data += 5;
+ if(SiS_Pr->ChipType == SIS_730) {
- } else {
+ index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
+ index += (unsigned short)(((pci50 >> 9)) & 0x03);
- index = 0;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(temp & 0x0080) index += 12;
+ /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
+ index = 0; /* -- do it like the BIOS anyway... */
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x800000A0);
- eax = SiS_GetRegLong(0xcfc);
-#else
- /* We use pci functions X offers. We use tag 0, because
- * we want to read/write to the host bridge (which is always
- * 00:00.0 on 630, 730 and 540), not the VGA device.
- */
- eax = pciReadLong(0x00000000, 0xA0);
-#endif
- temp = (USHORT)(eax >> 24);
- if(!(temp&0x01)) index += 24;
-
-#ifdef LINUX_KERNEL
- SiS_SetRegLong(0xcf8,0x80000050);
- eax = SiS_GetRegLong(0xcfc);
-#else
- eax = pciReadLong(0x00000000, 0x50);
-#endif
- temp=(USHORT)(eax >> 24);
- if(temp & 0x01) index += 6;
+ } else {
- temp = (temp & 0x0F) >> 1;
- index += temp;
+ pci50 >>= 24;
+ pciA0 >>= 24;
- data = LatencyFactor[index];
- data += 15;
- temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
- if(!(temp & 0x80)) data += 5;
- }
+ index = (pci50 >> 1) & 0x07;
- data += data2; /* CRT1 Request Period */
+ if(pci50 & 0x01) index += 6;
+ if(!(pciA0 & 0x01)) index += 24;
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+ if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
- if(!SiS_Pr->UseCustomMode) {
+ }
- CRT2ModeNo = ModeNo;
- SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
+ data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
+ if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
- refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo);
+ }
- index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
- refreshratetableindex,HwInfo);
- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ data += data2; /* CRT1 Request Period */
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- if(SiS_Pr->SiS_UseROM) {
- if(ROMAddr[0x220] & 0x01) {
- VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
- }
- }
- }
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
- } else {
+ if(!SiS_Pr->UseCustomMode) {
- CRT2ModeNo = 0xfe;
- VCLK = SiS_Pr->CSRClock; /* Get VCLK */
+ CRT2ModeNo = ModeNo;
+ SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
- }
+ refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
- colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
- colorth >>= 1;
- if(!colorth) colorth++;
+ /* Get VCLK */
+ index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
- data = data * VCLK * colorth;
- if(data % (MCLK << 4)) {
- data = data / (MCLK << 4);
- data++;
- } else {
- data = data / (MCLK << 4);
- }
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+ if(SiS_Pr->SiS_UseROM) {
+ if(ROMAddr[0x220] & 0x01) {
+ VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
+ }
+ }
+ }
- if(data <= 6) data = 6;
- if(data > 0x14) data = 0x14;
+ } else {
- temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01);
- if(HwInfo->jChipType == SIS_300) {
- if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
- else temp = (temp & (~0x1F)) | 0x16;
- if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
- temp = (temp & (~0x1F)) | 0x13;
- }
- } else {
- if( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */
- {
- temp = (temp & (~0x1F)) | 0x1b;
- } else {
- temp = (temp & (~0x1F)) | 0x16;
- }
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+ /* Get VCLK */
+ CRT2ModeNo = 0xfe;
+ VCLK = SiS_Pr->CSRClock;
- if( (HwInfo->jChipType == SIS_630) &&
- (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */
- {
- if(data > 0x13) data = 0x13;
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
+ }
+
+ /* Get colordepth */
+ colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
+ if(!colorth) colorth++;
+
+ data = data * VCLK * colorth;
+ temp = data % (MCLK << 4);
+ data = data / (MCLK << 4);
+ if(temp) data++;
+
+ if(data < 6) data = 6;
+ else if(data > 0x14) data = 0x14;
+
+ if(SiS_Pr->ChipType == SIS_300) {
+ temp = 0x16;
+ if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
+ temp = 0x13;
+ } else {
+ temp = 0x16;
+ if(( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision >= 0x30))
+ temp = 0x1b;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+
+ if((SiS_Pr->ChipType == SIS_630) &&
+ (SiS_Pr->ChipRevision >= 0x30)) {
+ if(data > 0x13) data = 0x13;
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
} else { /* If mode <= 0x13, we just restore everything */
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
- SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
}
}
@@ -5278,10 +5267,10 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
/* Set CRT2 FIFO on 315/330 series */
#ifdef SIS315H
static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
{
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
- if( (HwInfo->jChipType == SIS_760) &&
+ if( (SiS_Pr->ChipType == SIS_760) &&
(SiS_Pr->SiS_SysFlags & SF_760LFB) &&
(SiS_Pr->SiS_ModeType == Mode32Bpp) &&
(SiS_Pr->SiS_VGAHDE >= 1280) &&
@@ -5299,337 +5288,162 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
#endif
-static USHORT
-SiS_GetVGAHT2(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
{
- ULONG tempax,tempbx;
+ unsigned int tempax,tempbx;
tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
- return((USHORT)tempax);
+ return (unsigned short)tempax;
}
/* Set Part 1 / SiS bridge slave mode */
static void
-SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
-{
- USHORT push1,push2;
- USHORT tempax,tempbx,tempcx,temp;
- USHORT resinfo,modeflag,xres=0;
- unsigned char p1_7, p1_8;
+SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
+ static const unsigned short CRTranslation[] = {
+ /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
+ 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
+ /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
+ 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
+ };
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
- resinfo = 0;
xres = SiS_Pr->CHDisplay;
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
}
/* The following is only done if bridge is in slave mode: */
- if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
- if(xres >= 1600) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(xres >= 1600) { /* BIOS: == 1600 */
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
}
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff); /* set MAX HT */
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) modeflag |= Charx8Dot;
+ SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
- if(modeflag & Charx8Dot) tempcx = 0x08;
- else tempcx = 0x09;
-
- tempax = SiS_Pr->SiS_VGAHDE; /* 0x04 Horizontal Display End */
- if(modeflag & HalfDCLK) tempax >>= 1;
- tempax = ((tempax / tempcx) - 1) & 0xff;
- tempbx = tempax;
-
- temp = tempax;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp);
+ SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
+ SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
- temp += 2;
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(resinfo == SIS_RI_800x600) temp -= 2;
- }
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp); /* 0x05 Horizontal Display Start */
-
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03); /* 0x06 Horizontal Blank end */
-
- tempax = 0xFFFF;
- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
- if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT;
- if(modeflag & HalfDCLK) tempax >>= 1;
- tempax = (tempax / tempcx) - 5;
- tempcx = tempax;
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- temp = tempcx - 1;
- if(!(modeflag & HalfDCLK)) {
- temp -= 6;
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- temp -= 2;
- if(ModeNo > 0x13) temp -= 10;
- }
- }
- } else {
- tempcx = (tempcx + tempbx) >> 1;
- temp = (tempcx & 0x00FF) + 2;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- temp--;
- if(!(modeflag & HalfDCLK)) {
- if((modeflag & Charx8Dot)) {
- temp += 4;
- if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
- }
- }
- }
- } else {
- if(!(modeflag & HalfDCLK)) {
- temp -= 4;
- if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
- (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
- if(SiS_Pr->SiS_VGAHDE >= 800) {
- temp -= 7;
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_ModeType == ModeEGA) {
- if(SiS_Pr->SiS_VGAVDE == 1024) {
- temp += 15;
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
- temp += 7;
- }
- }
- }
- if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
- if(SiS_Pr->SiS_VGAHDE >= 1280) {
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
- }
- }
- }
- }
- }
- }
+ SiS_Pr->CHBlankStart += 16;
}
- p1_7 = temp;
- p1_8 = 0x00;
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(ModeNo <= 0x01) {
- p1_7 = 0x2a;
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61;
- else p1_8 = 0x41;
- } else if(SiS_Pr->SiS_ModeType == ModeText) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54;
- else p1_7 = 0x55;
- p1_8 = 0x00;
- } else if(ModeNo <= 0x13) {
- if(modeflag & HalfDCLK) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- p1_7 = 0x30;
- p1_8 = 0x03;
- } else {
- p1_7 = 0x2f;
- p1_8 = 0x02;
- }
- } else {
- p1_7 = 0x5b;
- p1_8 = 0x03;
- }
- } else if( ((HwInfo->jChipType >= SIS_315H) &&
- ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) ||
- ((HwInfo->jChipType < SIS_315H) &&
- (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
- p1_7 = 0x30,
- p1_8 = 0x03;
- } else {
- p1_7 = 0x2f;
- p1_8 = 0x03;
- }
- }
- }
+ SiS_Pr->CHBlankEnd = 32;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
}
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) {
- p1_7 = 0x63;
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55;
- }
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(!(modeflag & HalfDCLK)) {
- p1_7 = 0xb2;
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
- p1_7 = 0xab;
- }
- }
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
- if(modeflag & HalfDCLK) p1_7 = 0x30;
- }
- }
+ temp = SiS_Pr->SiS_VGAHT - 96;
+ if(!(modeflag & HalfDCLK)) temp -= 32;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
+ temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
+ temp -= 3;
+ temp <<= 3;
+ } else {
+ if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
}
+ SiS_Pr->CHSyncStart = temp;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7); /* 0x07 Horizontal Retrace Start */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8); /* 0x08 Horizontal Retrace End */
+ SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03); /* 0x18 SR08 (FIFO Threshold?) */
+ SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
+ VGAVDE = SiS_Pr->SiS_VGAVDE;
+ if (VGAVDE == 357) VGAVDE = 350;
+ else if(VGAVDE == 360) VGAVDE = 350;
+ else if(VGAVDE == 375) VGAVDE = 350;
+ else if(VGAVDE == 405) VGAVDE = 400;
+ else if(VGAVDE == 420) VGAVDE = 400;
+ else if(VGAVDE == 525) VGAVDE = 480;
+ else if(VGAVDE == 1056) VGAVDE = 1024;
+ SiS_Pr->CVDisplay = VGAVDE;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF); /* 0x09 Set Max VT */
+ SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
- tempcx = 0x121;
- tempbx = SiS_Pr->SiS_VGAVDE; /* 0x0E Vertical Display End */
- if (tempbx == 357) tempbx = 350;
- else if(tempbx == 360) tempbx = 350;
- else if(tempbx == 375) tempbx = 350;
- else if(tempbx == 405) tempbx = 400;
- else if(tempbx == 420) tempbx = 400;
- else if(tempbx == 525) tempbx = 480;
- push2 = tempbx;
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
- if (tempbx == 350) tempbx += 5;
- else if(tempbx == 480) tempbx += 5;
- }
- }
- }
- tempbx -= 2;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp); /* 0x10 vertical Blank Start */
-
- tempbx = push2;
- tempbx--;
- temp = tempbx & 0x00FF;
-#if 0
- /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
- if(xxx()) {
- if(temp == 0xdf) temp = 0xda;
- }
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);
-
- temp = 0;
- if(modeflag & DoubleScanMode) temp |= 0x80;
- if(HwInfo->jChipType >= SIS_661) {
- if(tempbx & 0x0200) temp |= 0x20;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp);
- if(tempbx & 0x0100) tempcx |= 0x000a;
- if(tempbx & 0x0400) tempcx |= 0x1200;
- } else {
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);
- if(tempbx & 0x0100) tempcx |= 0x0002;
- if(tempbx & 0x0400) tempcx |= 0x0600;
- }
+ SiS_Pr->CVBlankEnd = 1;
+ if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
- if(tempbx & 0x0200) tempcx |= 0x0040;
+ temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
+ SiS_Pr->CVSyncStart = VGAVDE + temp;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00); /* 0x11 Vertical Blank End */
+ temp >>= 3;
+ SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
- tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
+ SiS_CalcCRRegisters(SiS_Pr, 0);
+ SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
- if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) {
- if(resinfo != SIS_RI_1280x1024) {
- tempbx += (tempax << 1);
- }
- } else if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
- tempbx += (tempax << 1);
- }
+ for(i = 0; i <= 7; i++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
}
-
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- tempbx -= 10;
- } else {
- if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- tempbx += 40;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
- }
- }
- }
- }
- tempax >>= 2;
- tempax++;
- tempax += tempbx;
- push1 = tempax;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if(tempbx <= 513) {
- if(tempax >= 513) tempbx = 513;
- }
+ for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* 0x0C Vertical Retrace Start */
-
- tempbx--;
- temp = tempbx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);
-
- if(tempbx & 0x0100) tempcx |= 0x0008;
-
- if(tempbx & 0x0200) {
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
+ for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- tempbx++;
-
- if(tempbx & 0x0100) tempcx |= 0x0004;
- if(tempbx & 0x0200) tempcx |= 0x0080;
- if(tempbx & 0x0400) {
- if(HwInfo->jChipType >= SIS_661) tempcx |= 0x0800;
- else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
- else tempcx |= 0x0C00;
+ for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
}
- tempbx = push1;
- temp = tempbx & 0x000F;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp); /* 0x0D vertical Retrace End */
-
- if(tempbx & 0x0010) tempcx |= 0x2000;
-
- temp = tempcx & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* 0x0A CR07 */
-
- temp = (tempcx & 0xFF00) >> 8;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* 0x17 SR0A */
+ temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
- tempax = modeflag;
- temp = (tempax & 0xFF00) >> 8;
- temp = (temp >> 1) & 0x09;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01; /* Always 8 dotclock */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* 0x16 SR01 */
+ temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) temp |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* 0x0F CR14 */
+ temp = 0;
+ temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
+ if(modeflag & HalfDCLK) temp |= 0x08;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* 0x12 CR17 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
- temp = 0x00;
+ temp = 0;
if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
- if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
- temp = 0x80;
- }
+ temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* 0x1A SR0E */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
+
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
+ SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+ SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+ SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+ xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+ SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+ SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+ SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+ SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+ xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+ SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+ SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+ SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+ SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+ xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+#endif
}
/* Setup panel link
@@ -5637,18 +5451,18 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
* 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
*/
static void
-SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT modeflag,resinfo;
- USHORT push2,tempax,tempbx,tempcx,temp;
- ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+ unsigned short modeflag, resinfo = 0;
+ unsigned short push2, tempax, tempbx, tempcx, temp;
+ unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
BOOLEAN islvds = FALSE, issis = FALSE, chkdclkfirst = FALSE;
#ifdef SIS300
- USHORT crt2crtc;
+ unsigned short crt2crtc = 0;
#endif
#ifdef SIS315H
- USHORT pushcx;
+ unsigned short pushcx;
#endif
if(ModeNo <= 0x13) {
@@ -5659,15 +5473,11 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#endif
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
- resinfo = 0;
-#ifdef SIS300
- crt2crtc = 0;
-#endif
} else {
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
#ifdef SIS300
- crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
#endif
}
@@ -5681,14 +5491,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
issis = TRUE;
}
- if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
chkdclkfirst = TRUE;
}
}
#ifdef SIS315H
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(IS_SIS330) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
} else if(IS_SIS740) {
@@ -5704,7 +5514,7 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
@@ -5720,10 +5530,10 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempax = SiS_Pr->SiS_LCDHDES;
if(islvds) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
- tempax -= 8;
+ if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
+ if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+ tempax -= 8;
}
}
}
@@ -5736,13 +5546,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = SiS_Pr->SiS_HDE;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
- tempbx >>= 1;
- }
if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
tempbx = SiS_Pr->PanelXRes;
}
+ if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
+ tempbx >>= 1;
+ }
}
tempax += tempbx;
@@ -5767,25 +5578,25 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp = (tempcx >> 3) & 0x00FF;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
- if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- switch(ModeNo) {
- case 0x04:
- case 0x05:
- case 0x0d: temp = 0x56; break;
- case 0x10: temp = 0x60; break;
- case 0x13: temp = 0x5f; break;
- case 0x40:
- case 0x41:
- case 0x4f:
- case 0x43:
- case 0x44:
- case 0x62:
- case 0x56:
- case 0x53:
- case 0x5d:
- case 0x5e: temp = 0x54; break;
- }
- }
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+ switch(ModeNo) {
+ case 0x04:
+ case 0x05:
+ case 0x0d: temp = 0x56; break;
+ case 0x10: temp = 0x60; break;
+ case 0x13: temp = 0x5f; break;
+ case 0x40:
+ case 0x41:
+ case 0x4f:
+ case 0x43:
+ case 0x44:
+ case 0x62:
+ case 0x56:
+ case 0x53:
+ case 0x5d:
+ case 0x5e: temp = 0x54; break;
+ }
+ }
}
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
@@ -5793,12 +5604,12 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
temp += 2;
if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- temp += 8;
- if(SiS_Pr->PanelHRE != 999) {
- temp = tempcx + SiS_Pr->PanelHRE;
+ temp += 8;
+ if(SiS_Pr->PanelHRE != 999) {
+ temp = tempcx + SiS_Pr->PanelHRE;
if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
temp >>= 3;
- }
+ }
}
} else {
temp += 10;
@@ -5806,9 +5617,6 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp &= 0x1F;
temp |= ((tempcx & 0x07) << 5);
-#if 0
- if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20; /* WRONG? BIOS loads cl, not ah */
-#endif
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
/* Vertical */
@@ -5826,9 +5634,9 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
push2 = tempbx;
tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
}
}
@@ -5844,19 +5652,19 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(issis) tempbx++;
} else {
tempbx += tempcx;
- if(HwInfo->jChipType < SIS_315H) tempbx++;
+ if(SiS_Pr->ChipType < SIS_315H) tempbx++;
else if(issis) tempbx++;
}
- if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; /* BPLVRS */
+ if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
temp = tempbx & 0x00FF;
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(ModeNo == 0x10) temp = 0xa9;
+ if(ModeNo == 0x10) temp = 0xa9;
}
}
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
tempcx >>= 3;
tempcx++;
@@ -5879,13 +5687,13 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
tempbx = 0x87;
- if((HwInfo->jChipType >= SIS_315H) ||
- (HwInfo->jChipRevision >= 0x30)) {
+ if((SiS_Pr->ChipType >= SIS_315H) ||
+ (SiS_Pr->ChipRevision >= 0x30)) {
tempbx = 0x07;
if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
}
- /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+ /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
@@ -5896,59 +5704,58 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
- tempbx = push2; /* BPLVDEE */
+ tempbx = push2; /* BPLVDEE */
- tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
+ tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
switch(SiS_Pr->SiS_LCDResInfo) {
case Panel_640x480:
- tempbx = SiS_Pr->SiS_VGAVDE - 1;
- tempcx = SiS_Pr->SiS_VGAVDE;
+ tempbx = SiS_Pr->SiS_VGAVDE - 1;
+ tempcx = SiS_Pr->SiS_VGAVDE;
break;
case Panel_800x600:
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_800x600) tempcx++;
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_800x600) tempcx++;
+ }
break;
case Panel_1024x600:
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_1024x600) tempcx++;
- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_1024x600) tempcx++;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
if(resinfo == SIS_RI_800x600) tempcx++;
}
- }
+ }
break;
case Panel_1024x768:
- if(HwInfo->jChipType < SIS_315H) {
- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- if(resinfo == SIS_RI_1024x768) tempcx++;
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(resinfo == SIS_RI_1024x768) tempcx++;
}
- }
+ }
break;
}
}
temp = ((tempbx >> 8) & 0x07) << 3;
- temp = temp | ((tempcx >> 8) & 0x07);
+ temp |= ((tempcx >> 8) & 0x07);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
- /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++; */
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
/* Vertical scaling */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* 300 series */
tempeax = SiS_Pr->SiS_VGAVDE << 6;
- temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
- tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+ temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
+ tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
if(temp) tempeax++;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
- temp = (USHORT)(tempeax & 0x00FF);
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
tempvcfact = temp;
#endif /* SIS300 */
@@ -5963,20 +5770,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(temp) tempeax++;
tempvcfact = tempeax;
- temp = (USHORT)(tempeax & 0x00FF);
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
- temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
- temp = (USHORT)((tempeax & 0x00030000) >> 16);
+ temp = (unsigned short)((tempeax & 0x00030000) >> 16);
if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
- temp = (USHORT)(tempeax & 0x00FF);
+ if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
+ temp = (unsigned short)(tempeax & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
- temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
- temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+ temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
temp = 0;
if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
@@ -5997,29 +5804,29 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempecx = 0xFFFF;
} else {
tempecx = tempebx / SiS_Pr->SiS_HDE;
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
}
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
tempeax = (tempebx / tempecx) - 1;
} else {
tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
}
tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
- temp = (USHORT)(tempecx & 0x00FF);
+ temp = (unsigned short)(tempecx & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
- tempbx = (USHORT)(tempeax & 0xFFFF);
+ tempbx = (unsigned short)(tempeax & 0xFFFF);
} else {
tempeax = SiS_Pr->SiS_VGAVDE << 6;
tempbx = tempvcfact & 0x3f;
if(tempbx == 0) tempbx = 64;
tempeax /= tempbx;
- tempbx = (USHORT)(tempeax & 0xFFFF);
+ tempbx = (unsigned short)(tempeax & 0xFFFF);
}
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
@@ -6032,24 +5839,24 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
- tempecx >>= 16; /* BPLHCFACT */
+ tempecx >>= 16; /* BPLHCFACT */
if(!chkdclkfirst) {
if(modeflag & HalfDCLK) tempecx >>= 1;
}
- temp = (USHORT)((tempecx & 0xFF00) >> 8);
+ temp = (unsigned short)((tempecx & 0xFF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
- temp = (USHORT)(tempecx & 0x00FF);
+ temp = (unsigned short)(tempecx & 0x00FF);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+ if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
}
} else {
if(islvds) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
} else {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
@@ -6061,17 +5868,26 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS300
if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
- int i;
- UCHAR TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
- UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
- UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned char *trumpdata;
+ int i, j = crt2crtc;
+ unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
+ unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+ unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+ if(SiS_Pr->SiS_UseROM) {
+ trumpdata = &ROMAddr[0x8001 + (j * 80)];
+ } else {
+ if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
+ trumpdata = &SiS300_TrumpionData[j][0];
+ }
SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
for(i=0; i<5; i++) {
- SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+ SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
}
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(ModeNo == 0x13) {
+ if(ModeNo == 0x13) {
for(i=0; i<4; i++) {
SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
}
@@ -6095,67 +5911,66 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
- tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+ tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
tempax += 64;
- temp = tempax & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
- temp = ((tempax & 0xFF00) >> 8) << 3;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
+ temp = (tempax >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
- tempax += 32; /* Blpe=lBlps+32 */
- temp = tempax & 0x00FF;
- if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml=0 */
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
+ tempax += 32; /* Blpe = lBlps+32 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
tempax = SiS_Pr->SiS_VDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
tempax >>= 1;
- temp = tempax & 0x00FF;
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
- temp = ((tempax & 0xFF00) >> 8) << 3;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
+ temp = (tempax >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
tempeax = SiS_Pr->SiS_HDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
- tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
- tempebx = 128;
- temp = (USHORT)(tempeax % tempebx);
- tempeax = tempeax / tempebx;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
+ tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
+ temp = tempeax & 0x7f;
+ tempeax >>= 7;
if(temp) tempeax++;
- temp = (USHORT)(tempeax & 0x003F);
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
+ temp = tempeax & 0x3f;
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
tempax = SiS_Pr->SiS_HDE;
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
- tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+ tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
pushcx = tempax;
temp = tempax & 0x00FF;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
temp = ((tempax & 0xFF00) >> 8) << 3;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
- tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
- if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
- SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
- tempeax = (tempax * pushcx);
- tempebx = 0x00100000 + tempeax;
- temp = (USHORT)tempebx & 0x000000FF;
+ tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+ SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+ tempeax = tempax * pushcx;
+ temp = tempeax & 0xFF;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
- temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+ temp = (tempeax & 0xFF00) >> 8;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
- temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
+ temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
- temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
+ temp = ((tempeax & 0x01000000) >> 24) << 7;
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
@@ -6192,20 +6007,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* Set Part 1 */
static void
-SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
#if defined(SIS300) || defined(SIS315H)
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
#endif
- USHORT temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
- USHORT pushbx=0, CRT1Index=0, modeflag, resinfo=0;
+ unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
+ unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
#ifdef SIS315H
- USHORT tempbl=0;
+ unsigned short tempbl=0;
#endif
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
return;
}
@@ -6214,47 +6029,47 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} else if(SiS_Pr->UseCustomMode) {
modeflag = SiS_Pr->CModeFlag;
} else {
- CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
}
- SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
- if( ! ((HwInfo->jChipType >= SIS_315H) &&
+ if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
(SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
- if(HwInfo->jChipType < SIS_315H ) {
+ if(SiS_Pr->ChipType < SIS_315H ) {
#ifdef SIS300
- SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+ SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
#endif
} else {
#ifdef SIS315H
- SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
+ SiS_SetCRT2FIFO_310(SiS_Pr);
#endif
}
/* 1. Horizontal setup */
- if(HwInfo->jChipType < SIS_315H ) {
+ if(SiS_Pr->ChipType < SIS_315H ) {
#ifdef SIS300 /* ------------- 300 series --------------*/
- temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
+ temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
- temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
+ temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
- temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
- SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
+ temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+ SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
- tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
- tempbx = pushbx + tempcx;
- tempcx <<= 1;
- tempcx += tempbx;
+ tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+ tempbx = pushbx + tempcx;
+ tempcx <<= 1;
+ tempcx += tempbx;
bridgeadd = 12;
@@ -6301,7 +6116,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
bridgeadd = 16;
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
if(resinfo == SIS_RI_1280x1024) {
@@ -6319,7 +6134,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->UseCustomMode) {
+ if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncStart + bridgeadd;
tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
tempax = SiS_Pr->SiS_VGAHT;
@@ -6341,22 +6156,22 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
}
- tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
- tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
+ tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
+ tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
tempcx &= 0x00FF;
tempcx |= (tempbx & 0xFF00);
- tempbx += bridgeadd;
- tempcx += bridgeadd;
+ tempbx += bridgeadd;
+ tempcx += bridgeadd;
tempax = SiS_Pr->SiS_VGAHT;
if(modeflag & HalfDCLK) tempax >>= 1;
tempax--;
if(tempcx > tempax) tempcx = tempax;
- }
+ }
- if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- tempbx = 1040;
- tempcx = 1044; /* HWCursor bug! */
- }
+ if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
+ tempbx = 1040;
+ tempcx = 1044; /* HWCursor bug! */
+ }
}
@@ -6372,18 +6187,18 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempcx = SiS_Pr->SiS_VGAVT - 1;
temp = tempcx & 0x00FF;
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
temp--;
}
- }
+ }
} else {
- temp--;
- }
- } else if(HwInfo->jChipType >= SIS_315H) {
+ temp--;
+ }
+ } else if(SiS_Pr->ChipType >= SIS_315H) {
temp--;
}
}
@@ -6395,9 +6210,9 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
- if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
- tempbx++;
- tempax = tempbx;
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+ tempbx++;
+ tempax = tempbx;
tempcx++;
tempcx -= tempax;
tempcx >>= 2;
@@ -6407,8 +6222,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempcx += tempbx;
tempcx++;
} else {
- tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
- tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
+ tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
+ tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -6416,7 +6231,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = SiS_Pr->CVSyncStart;
tempcx = SiS_Pr->CVSyncEnd;
}
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
unsigned char cr8, cr7, cr13;
if(SiS_Pr->UseCustomMode) {
cr8 = SiS_Pr->CCRT1CRTC[8];
@@ -6429,11 +6244,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
}
- tempbx = cr8;
- if(cr7 & 0x04) tempbx |= 0x0100;
- if(cr7 & 0x80) tempbx |= 0x0200;
- if(cr13 & 0x08) tempbx |= 0x0400;
- }
+ tempbx = cr8;
+ if(cr7 & 0x04) tempbx |= 0x0100;
+ if(cr7 & 0x80) tempbx |= 0x0200;
+ if(cr13 & 0x08) tempbx |= 0x0400;
+ }
}
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
@@ -6442,13 +6257,13 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* 3. Panel delay compensation */
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
#ifdef SIS300 /* ---------- 300 series -------------- */
if(SiS_Pr->SiS_VBType & VB_SISVB) {
temp = 0x20;
- if(HwInfo->jChipType == SIS_300) {
+ if(SiS_Pr->ChipType == SIS_300) {
temp = 0x10;
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
@@ -6460,24 +6275,23 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
- else temp = 0x20;
- }
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
+ else temp = 0x20;
+ }
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x80) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
- temp = ROMAddr[0x221];
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+ temp = ROMAddr[0x221];
else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
temp = ROMAddr[0x222];
else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
temp = ROMAddr[0x223];
else
temp = ROMAddr[0x224];
- temp &= 0x3c;
}
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
+ if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
}
} else {
@@ -6487,15 +6301,17 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x80) {
- temp = ROMAddr[0x220] & 0x3c;
+ temp = ROMAddr[0x220];
}
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
+ if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
}
- }
+ }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+ temp &= 0x3c;
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
#endif /* SIS300 */
@@ -6503,16 +6319,16 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS315H /* --------------- 315/330 series ---------------*/
- if(HwInfo->jChipType < SIS_661) {
+ if(SiS_Pr->ChipType < SIS_661) {
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if(HwInfo->jChipType == SIS_740) temp = 0x03;
- else temp = 0x00;
+ if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
+ else temp = 0x00;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
tempbl = 0xF0;
- if(HwInfo->jChipType == SIS_650) {
+ if(SiS_Pr->ChipType == SIS_650) {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
}
@@ -6531,10 +6347,10 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
} /* < 661 */
- tempax = 0;
- if(modeflag & DoubleScanMode) tempax |= 0x80;
- if(modeflag & HalfDCLK) tempax |= 0x40;
- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+ tempax = 0;
+ if(modeflag & DoubleScanMode) tempax |= 0x80;
+ if(modeflag & HalfDCLK) tempax |= 0x40;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
#endif /* SIS315H */
@@ -6544,21 +6360,21 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBType & VB_SISVB) {
if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- /* For 301BDH with LCD, we set up the Panel Link */
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ /* For 301BDH with LCD, we set up the Panel Link */
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else {
- if(HwInfo->jChipType < SIS_315H) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ if(SiS_Pr->ChipType < SIS_315H) {
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else {
if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
- }
+ if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
+ }
} else {
- SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+ SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
}
}
}
@@ -6569,11 +6385,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS315H
-static UCHAR *
-SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
+static unsigned char *
+SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
{
- const UCHAR *tableptr = NULL;
- USHORT a, b, p = 0;
+ const unsigned char *tableptr = NULL;
+ unsigned short a, b, p = 0;
a = SiS_Pr->SiS_VGAHDE;
b = SiS_Pr->SiS_HDE;
@@ -6606,25 +6422,25 @@ SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
}
p += 2;
- return((UCHAR *)&tableptr[p]);
+ return ((unsigned char *)&tableptr[p]);
}
static void
-SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- UCHAR *tableptr;
+ unsigned char *tableptr;
+ unsigned char temp;
int i, j;
- UCHAR temp;
- if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
- tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
+ tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo);
+ tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
}
@@ -6635,12 +6451,12 @@ SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
static BOOLEAN
-SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex,USHORT *CRT2Index,
- USHORT *ResIndex,PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
+ unsigned short *ResIndex)
{
- if(HwInfo->jChipType < SIS_315H) return FALSE;
+ if(SiS_Pr->ChipType < SIS_315H) return FALSE;
if(ModeNo <= 0x13)
(*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -6661,82 +6477,79 @@ SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
}
}
- return(((*CRT2Index) != 0));
+ return (((*CRT2Index) != 0));
}
#endif
#ifdef SIS300
static void
-SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
{
- USHORT tempcx;
- const UCHAR atable[] = {
+ unsigned short tempcx;
+ static const unsigned char atable[] = {
0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
};
if(!SiS_Pr->UseCustomMode) {
- if( ( ( (HwInfo->jChipType == SIS_630) ||
- (HwInfo->jChipType == SIS_730) ) &&
- (HwInfo->jChipRevision > 2) ) &&
- (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
- (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
- (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
- if(ModeNo == 0x13) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
- } else {
- if((crt2crtc & 0x3F) == 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
- }
- }
+ if( ( ( (SiS_Pr->ChipType == SIS_630) ||
+ (SiS_Pr->ChipType == SIS_730) ) &&
+ (SiS_Pr->ChipRevision > 2) ) &&
+ (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+ (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
+ (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+ if(ModeNo == 0x13) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+ } else if((crt2crtc & 0x3F) == 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+ }
}
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
- crt2crtc &= 0x1f;
- tempcx = 0;
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- tempcx += 7;
- }
- }
- tempcx += crt2crtc;
- if(crt2crtc >= 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
- }
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+ crt2crtc &= 0x1f;
+ tempcx = 0;
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ tempcx += 7;
+ }
+ }
+ tempcx += crt2crtc;
+ if(crt2crtc >= 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+ }
- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- if(crt2crtc == 4) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
- }
- }
- }
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
- }
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(crt2crtc == 4) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+ }
+ }
+ }
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+ }
}
}
}
/* For ECS A907. Highly preliminary. */
static void
-SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
- USHORT ModeNo)
+SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+ unsigned short ModeNo)
{
- USHORT crt2crtc, resindex;
- int i,j;
- const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+ const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
+ unsigned short crt2crtc, resindex;
+ int i, j;
- if(HwInfo->jChipType != SIS_300) return;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+ if(SiS_Pr->ChipType != SIS_300) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
if(SiS_Pr->UseCustomMode) return;
if(ModeNo <= 0x13) {
@@ -6758,13 +6571,13 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
for(j = 0x1c; j <= 0x1d; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
for(j = 0x1f; j <= 0x21; i++, j++ ) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
@@ -6772,15 +6585,15 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
#endif
static void
-SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- const UCHAR specialtv[] = {
+ const unsigned char specialtv[] = {
0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
0x58,0xe4,0x73,0xda,0x13
@@ -6813,16 +6626,16 @@ SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
}
static void
-SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp;
+ unsigned short temp;
if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
if(SiS_Pr->SiS_VGAVDE == 525) {
temp = 0xc3;
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
temp++;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
@@ -6830,7 +6643,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
temp = 0x4d;
if(SiS_Pr->SiS_ModeType <= ModeVGA) {
temp++;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
}
@@ -6838,7 +6651,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
/* Not always for LV, see SetGrp2 */
}
@@ -6872,17 +6685,17 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
}
static void
-SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
- PSIS_HW_INFO HwInfo)
-{
- USHORT i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
- USHORT push2, modeflag, crt2crtc, bridgeoffset;
- ULONG longtemp;
- const UCHAR *PhasePoint;
- const UCHAR *TimingPoint;
+SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+ unsigned short push2, modeflag, crt2crtc, bridgeoffset;
+ unsigned int longtemp, PhaseIndex;
+ BOOLEAN newtvphase;
+ const unsigned char *TimingPoint;
#ifdef SIS315H
- USHORT resindex, CRT2Index;
- const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+ unsigned short resindex, CRT2Index;
+ const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
#endif
@@ -6908,9 +6721,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
- PhasePoint = SiS_Pr->SiS_PALPhase;
+ PhaseIndex = 0x01; /* SiS_PALPhase */
TimingPoint = SiS_Pr->SiS_PALTiming;
+ newtvphase = FALSE;
+ if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+ (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+ newtvphase = TRUE;
+ }
+
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
@@ -6918,82 +6738,54 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-#if 0
- if(!(modeflag & Charx8Dot)) TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
-#endif
}
}
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) TimingPoint = &SiS_YPbPrTable[2][0];
- else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0];
- else TimingPoint = &SiS_YPbPrTable[0][0];
+ i = 0;
+ if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
+
+ TimingPoint = &SiS_YPbPrTable[i][0];
- PhasePoint = SiS_Pr->SiS_NTSCPhase;
+ PhaseIndex = 0x00; /* SiS_NTSCPhase */
} else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALPhase2;
- }
+ if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
} else {
TimingPoint = SiS_Pr->SiS_NTSCTiming;
- PhasePoint = SiS_Pr->SiS_NTSCPhase;
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_PALPhase;
- }
-
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_NTSCPhase2;
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_PALPhase2;
- }
- }
-
- }
+ PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
+ if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- PhasePoint = SiS_Pr->SiS_PALMPhase;
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALMPhase2;
- }
}
- if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- PhasePoint = SiS_Pr->SiS_PALNPhase;
- if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
- (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
- PhasePoint = SiS_Pr->SiS_PALNPhase2;
- }
+ if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
+ PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
+ if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
}
if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
- PhasePoint = SiS_Pr->SiS_SpecialPhase;
if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- PhasePoint = SiS_Pr->SiS_SpecialPhaseM;
+ PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
} else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- PhasePoint = SiS_Pr->SiS_SpecialPhaseJ;
+ PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
+ } else {
+ PhaseIndex = 0x10; /* SiS_SpecialPhase */
}
}
- for(i=0x31, j=0; i<=0x34; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]);
+ for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
}
- for(i=0x01, j=0; i<=0x2D; i++, j++) {
+ for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
}
- for(i=0x39; i<=0x45; i++, j++) {
+ for(i = 0x39; i <= 0x45; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
}
@@ -7010,28 +6802,32 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
- else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
- else tempax = 440; /* NTSC, YPbPr 525, 750 */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
+ else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
+ else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
+ else tempax = 440; /* NTSC, YPbPr 525 */
- if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
+ if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
tempax -= SiS_Pr->SiS_VDE;
- tempax >>= 2;
+ tempax >>= 1;
+ if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
+ tempax >>= 1;
+ }
tempax &= 0x00ff;
- temp = tempax + (USHORT)TimingPoint[0];
+ temp = tempax + (unsigned short)TimingPoint[0];
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
- temp = tempax + (USHORT)TimingPoint[1];
+ temp = tempax + (unsigned short)TimingPoint[1];
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 19 */
- SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 52 */
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
} else {
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7041,14 +6837,14 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
}
tempcx = SiS_Pr->SiS_HT;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
tempcx--;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
tempcx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
tempcx += 7;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
@@ -7075,7 +6871,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
tempcx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
j += 2;
tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
@@ -7094,7 +6890,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
} else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
tempbx >>= 1;
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
@@ -7123,23 +6919,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
}
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
}
-#if 0
- /* TEST qqqq */
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
- for(i=0x01, j=0; i<=0x2D; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
- }
- for(i=0x39; i<=0x45; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
- }
- }
-#endif
-
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
tempbx = SiS_Pr->SiS_VDE;
if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
@@ -7150,7 +6934,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
}
}
@@ -7165,14 +6949,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempch = tempcl = 0x01;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- if(SiS_Pr->SiS_VGAHDE >= 1024) {
- if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
- tempch = 0x19;
+ if(SiS_Pr->SiS_VGAHDE >= 960) {
+ if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
tempcl = 0x20;
- if(SiS_Pr->SiS_VGAHDE >= 1280) {
- tempch = 0x14;
+ if(SiS_Pr->SiS_VGAHDE >= 1280) {
+ tempch = 20;
tempbx &= ~0x20;
- }
+ } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
+ tempch = 25;
+ } else {
+ tempch = 25; /* OK */
+ }
}
}
}
@@ -7180,7 +6967,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(!(tempbx & 0x20)) {
if(modeflag & HalfDCLK) tempcl <<= 1;
longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
tempax = longtemp / SiS_Pr->SiS_HDE;
if(longtemp % SiS_Pr->SiS_HDE) tempax++;
tempbx |= ((tempax >> 8) & 0x1F);
@@ -7190,7 +6977,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
tempcx &= 0x07;
if(tempbx & 0x20) tempcx = 0;
@@ -7219,7 +7006,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetTVSpecial(SiS_Pr, ModeNo);
- if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
temp = 0;
if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
@@ -7246,7 +7033,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/* From here: Part2 LCD setup */
tempbx = SiS_Pr->SiS_HDE;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx--; /* RHACTE = HDE - 1 */
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
@@ -7256,10 +7043,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->SiS_ModeType == ModeEGA) {
if(SiS_Pr->SiS_VGAHDE >= 1024) {
temp = 0x02;
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
- temp = 0x01;
- }
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ temp = 0x01;
}
}
}
@@ -7289,11 +7074,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
#ifdef SIS315H
if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- &CRT2Index, &resindex, HwInfo)) {
+ &CRT2Index, &resindex)) {
switch(CRT2Index) {
+ case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
+ default:
case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
- case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
- default: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3; break;
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7312,7 +7097,6 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
-
} else {
#endif
@@ -7349,9 +7133,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
@@ -7401,9 +7187,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempbx = SiS_Pr->CVSyncStart;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
@@ -7416,26 +7204,30 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
temp |= (SiS_Pr->CVSyncEnd & 0x0f);
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
#ifdef SIS300
- SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+ SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
#endif
bridgeoffset = 7;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) bridgeoffset += 2;
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) bridgeoffset++;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
+ if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
+ else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
+ /* Higher bridgeoffset shifts to the LEFT */
temp = 0;
if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
- temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
+ temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+ if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
}
}
temp += bridgeoffset;
@@ -7450,15 +7242,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
}
}
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+ if(SiS_IsDualLink(SiS_Pr)) {
tempcx >>= 1;
tempbx >>= 1;
tempax >>= 1;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
#endif
+#endif
tempbx += bridgeoffset;
@@ -7480,13 +7274,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncStart;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx <<= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx += bridgeoffset;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
@@ -7501,20 +7298,23 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
if(SiS_Pr->UseCustomMode) {
tempbx = SiS_Pr->CHSyncEnd;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx <<= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx += bridgeoffset;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
#endif
+#endif
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
#ifdef SIS300
- SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
+ SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
#endif
#ifdef SIS315H
} /* CRT2-LCD from table */
@@ -7526,11 +7326,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
/*********************************************/
static void
-SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT i;
- const UCHAR *tempdi;
+ unsigned short i;
+ const unsigned char *tempdi;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
@@ -7570,7 +7369,7 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
for(i=0; i<=0x3E; i++) {
SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
}
@@ -7587,35 +7386,43 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
#ifdef SIS315H
+#if 0
static void
-SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
+SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
{
- USHORT temp, temp1, temp2;
+ unsigned short temp, temp1, temp2;
temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
- temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+ temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
- temp = (USHORT)((int)(temp) + shift);
+ temp = (unsigned short)((int)(temp) + shift);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
- temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+ temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
}
+#endif
static void
-SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT temp, temp1, resinfo = 0;
+ unsigned short temp, temp1, resinfo = 0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
+ if(SiS_Pr->ChipType >= XGI_20) return;
+
+ if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
+ if(!(ROMAddr[0x61] & 0x04)) return;
+ }
+
if(ModeNo > 0x13) {
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
}
@@ -7625,7 +7432,7 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
if(!(temp & 0x01)) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
- if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
+ if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
}
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
@@ -7633,24 +7440,29 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
else temp = 0x0402;
- if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+ if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
temp1 = 0;
if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+ if(ModeNo > 0x13) {
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
+ }
} else {
temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
if(temp1 == 0x01) temp |= 0x01;
if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
- }
- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
- if(ModeNo > 0x13) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+ if(ModeNo > 0x13) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+ }
}
- if(HwInfo->jChipType >= SIS_661) { /* ? */
+#if 0
+ if(SiS_Pr->ChipType >= SIS_661) { /* ? */
if(SiS_Pr->SiS_TVMode & TVAspect43) {
if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
if(resinfo == SIS_RI_1024x768) {
@@ -7663,29 +7475,30 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
}
+#endif
+
}
+
}
#endif
static void
-SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT vclkindex;
- USHORT temp, reg1, reg2;
+ unsigned short vclkindex, temp, reg1, reg2;
if(SiS_Pr->UseCustomMode) {
reg1 = SiS_Pr->CSR2B;
reg2 = SiS_Pr->CSR2C;
} else {
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
- HwInfo);
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
- if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+ if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
@@ -7705,11 +7518,35 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
}
static void
-SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
+{
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+ if((SiS_CRT2IsLCD(SiS_Pr)) ||
+ (SiS_IsVAMode(SiS_Pr))) {
+ if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
+ }
+ }
+ }
+ }
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+ }
+}
+
+static void
+SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
- ULONG tempebx,tempeax,templong;
+ unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
+ unsigned int tempebx, tempeax, templong;
if(ModeNo <= 0x13) {
modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -7722,38 +7559,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
}
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
- }
+ if(SiS_Pr->ChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+ }
}
}
- if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) {
+ if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
}
}
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
- }
-
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
- }
- }
- return;
+ SiS_SetDualLinkEtc(SiS_Pr);
+ return;
}
}
@@ -7777,16 +7600,16 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
tempbx = SiS_Pr->SiS_VGAHDE;
- if(modeflag & HalfDCLK) tempbx >>= 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
temp = 0;
if(tempbx > 800) temp = 0x60;
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
temp = 0;
- if(tempbx == 1024) temp = 0xA0;
- else if(tempbx > 1024) temp = 0xC0;
+ if(tempbx > 1024) temp = 0xC0;
+ else if(tempbx >= 960) temp = 0xA0;
} else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
temp = 0;
if(tempbx >= 1280) temp = 0x40;
@@ -7796,8 +7619,13 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(tempbx >= 1024) temp = 0xA0;
}
+ temp |= SiS_Pr->Init_P4_0E;
+
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
+ if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+ temp &= 0xf0;
+ temp |= 0x0A;
+ }
}
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
@@ -7824,15 +7652,15 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempeax /= tempebx;
if(templong) tempeax++;
- temp = (USHORT)(tempeax & 0x000000FF);
+ temp = (unsigned short)(tempeax & 0x000000FF);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
- temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
+ temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
- temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+ temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
temp |= (tempcx & 0x4F);
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
@@ -7840,23 +7668,26 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
tempbx = 0;
if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
tempax = SiS_Pr->SiS_VGAHDE;
- if(modeflag & HalfDCLK) tempax >>= 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
+ if(modeflag & HalfDCLK) tempax >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
if(tempax > 800) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
tempax -= 800;
- } else { /* 651+301C: Only if TVNoHiviNoYPbPr */
+ } else {
tempbx = 0x08;
- if(tempax == 1024) tempax *= 25;
- else tempax *= 20;
+ if(tempax == 960) tempax *= 25; /* Correct */
+ else if(tempax == 1024) tempax *= 25;
+ else tempax *= 20;
temp = tempax % 32;
tempax /= 32;
if(temp) tempax++;
tempax++;
- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
- (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
- if(resinfo == SIS_RI_1024x768) {
- /* Otherwise white line at right edge */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(resinfo == SIS_RI_1024x768 ||
+ resinfo == SIS_RI_1024x576 ||
+ resinfo == SIS_RI_1280x1024 ||
+ resinfo == SIS_RI_1280x720) {
+ /* Otherwise white line or garbage at right edge */
tempax = (tempax & 0xff00) | 0x20;
}
}
@@ -7868,7 +7699,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
temp = 0x0036; tempbx = 0xD0;
- if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -7884,36 +7715,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
tempbx = SiS_Pr->SiS_HT >> 1;
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+ if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
tempbx -= 2;
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
temp = (tempbx >> 5) & 0x38;
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
/* LCD-too-dark-error-source, see FinalizeLCD() */
}
- if(HwInfo->jChipType >= SIS_315H) {
- if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
- }
- }
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
- SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
- }
}
+ SiS_SetDualLinkEtc(SiS_Pr);
+
} /* 301B */
- SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
/*********************************************/
@@ -7921,8 +7740,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
@@ -7930,7 +7748,7 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_ModeType == ModeVGA) {
if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
- SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
}
}
}
@@ -7939,116 +7757,156 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/* MODIFY CRT1 GROUP FOR SLAVE MODE */
/*********************************************/
-static void
-SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
- USHORT tempah,i,modeflag,j;
- USHORT ResIndex,DisplayType;
- const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
+static BOOLEAN
+SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
+ unsigned short *DisplayType)
+ {
+ unsigned short modeflag = 0;
+ BOOLEAN checkhd = TRUE;
- if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
- else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ /* Pass 1:1 not supported here */
+
+ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+
+ (*ResIndex) &= 0x3F;
+
+ if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+ (*DisplayType) = 80;
+ if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+ (*DisplayType) = 82;
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
+ }
+ }
+ if((*DisplayType) != 84) {
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+ }
+
+ } else {
+
+ (*DisplayType = 0);
+ switch(SiS_Pr->SiS_LCDResInfo) {
+ case Panel_320x240_1: (*DisplayType) = 50;
+ checkhd = FALSE;
+ break;
+ case Panel_320x240_2: (*DisplayType) = 14;
+ break;
+ case Panel_320x240_3: (*DisplayType) = 18;
+ break;
+ case Panel_640x480: (*DisplayType) = 10;
+ break;
+ case Panel_1024x600: (*DisplayType) = 26;
+ break;
+ default: return TRUE;
+ }
+
+ if(checkhd) {
+ if(modeflag & HalfDCLK) (*DisplayType)++;
+ }
+
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
+ }
+
+ }
+
+ return TRUE;
+}
+
+static void
+SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
+{
+ unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
+ const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
+ static const unsigned short CRIdx[] = {
+ 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x10, 0x11, 0x15, 0x16
+ };
if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
- (SiS_Pr->SiS_CustomT == CUT_PANEL848))
+ (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+ (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
return;
+ if(SiS_Pr->SiS_IF_DEF_LVDS) {
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+ } else return;
+
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+ if(SiS_Pr->ChipType < SIS_315H) {
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+ }
+
if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
&ResIndex, &DisplayType))) {
return;
}
- if(HwInfo->jChipType < SIS_315H) {
- if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+ switch(DisplayType) {
+ case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
+ case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
+ case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
+ case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
+ case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
+ case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
+ case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
+#if 0 /* Works better with calculated numbers */
+ case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
+ case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
+ case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
+ case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
+#endif
+ case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
+ case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
+ case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
+ case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
+ case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
}
- switch(DisplayType) {
- case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break;
- case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break;
- case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break;
- case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break;
- case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
- case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break;
- case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break;
- case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; break;
- case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break;
- case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break;
- case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break;
- case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H; break;
- case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1; break;
- case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H; break;
- case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1; break;
- case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H; break;
- case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2; break;
- case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H; break;
- case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
- case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
- case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
- case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
- case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1; break; /* FSTN */
- case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
- case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
- case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
- case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
- case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1; break;
- case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H; break;
- case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2; break;
- case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H; break;
- case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1; break;
- case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H; break;
- case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2; break;
- case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H; break;
- case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1; break;
- case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H; break;
- case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2; break;
- case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H; break;
- case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
- case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
- case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2; break;
- case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H; break;
- case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3; break;
- case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H; break;
- case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
- default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
- }
-
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
-
- for(i=0x02,j=1;i<=0x05;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x06,j=5;i<=0x07;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x10,j=7;i<=0x11;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x15,j=9;i<=0x16;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
- }
- for(i=0x0A,j=11;i<=0x0C;i++,j++){
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
- SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
- }
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
- tempah &= 0xE0;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
-
- tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
- tempah &= 0x01;
- tempah <<= 5;
- if(modeflag & DoubleScanMode) tempah |= 0x080;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+ if(LVDSCRT1Ptr) {
+
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+ for(i = 0; i <= 10; i++) {
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
+ SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
+ }
+
+ for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
+ }
+
+ tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
+
+ if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+ tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
+ if(modeflag & DoubleScanMode) tempah |= 0x80;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+
+ } else {
+
+ SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
+
+ }
}
/*********************************************/
@@ -8056,24 +7914,24 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT clkbase, vclkindex=0;
- UCHAR sr2b, sr2c;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short clkbase, vclkindex = 0;
+ unsigned char sr2b, sr2c;
- if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
- if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
- RefreshRateTableIndex--;
- }
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
- RefreshRateTableIndex, HwInfo);
- SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+ if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
+ RefreshRateTableIndex--;
+ }
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
} else {
- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
- RefreshRateTableIndex, HwInfo);
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+ RefreshRateTableIndex);
}
sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
@@ -8082,7 +7940,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
if(SiS_Pr->SiS_UseROM) {
if(ROMAddr[0x220] & 0x01) {
- sr2b = ROMAddr[0x227];
+ sr2b = ROMAddr[0x227];
sr2c = ROMAddr[0x228];
}
}
@@ -8091,7 +7949,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
clkbase = 0x02B;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
- clkbase += 3;
+ clkbase += 3;
}
}
@@ -8111,368 +7969,331 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
/*********************************************/
static void
-SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex)
+SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex)
{
-#if defined(SIS300) || defined(SIS315H)
- USHORT temp, tempbx;
-#endif
- USHORT tempcl;
- USHORT TVType, resindex;
- const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
+ unsigned short TVType, resindex;
+ const struct SiS_CHTVRegData *CHTVRegData = NULL;
- if(ModeNo <= 0x13)
- tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
- else
- tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ if(ModeNo <= 0x13)
+ resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ else
+ resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
- TVType = 0;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- TVType += 2;
- if(SiS_Pr->SiS_ModeType > ModeVGA) {
- if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
- }
- if(SiS_Pr->SiS_TVMode & TVSetPALM) {
- TVType = 4;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
- TVType = 6;
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
- }
- }
- switch(TVType) {
- case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
- case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
- case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
- case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
- case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
- case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
- case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
- case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
- case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
- default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
- }
- resindex = tempcl & 0x3F;
+ resindex &= 0x3F;
+
+ TVType = 0;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ TVType += 2;
+ if(SiS_Pr->SiS_ModeType > ModeVGA) {
+ if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
+ }
+ if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+ TVType = 4;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+ TVType = 6;
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+ }
+ }
+
+ switch(TVType) {
+ case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+ case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+ case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
+ case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
+ case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+ case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+ case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+ case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+ case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+ default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
+ }
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
#ifdef SIS300
- /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
+ /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
- /* We don't support modes >800x600 */
- if (resindex > 5) return;
+ /* We don't support modes >800x600 */
+ if (resindex > 5) return;
- if(SiS_Pr->SiS_TVMode & TVSetPAL) {
- SiS_SetCH700x(SiS_Pr,0x4304); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
- SiS_SetCH700x(SiS_Pr,0x6909); /* Black level for PAL (105)*/
- } else {
- SiS_SetCH700x(SiS_Pr,0x0304); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
- SiS_SetCH700x(SiS_Pr,0x7109); /* Black level for NTSC (113)*/
- }
-
- temp = CHTVRegData[resindex].Reg[0];
- tempbx=((temp&0x00FF)<<8)|0x00; /* Mode register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[1];
- tempbx=((temp&0x00FF)<<8)|0x07; /* Start active video register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[2];
- tempbx=((temp&0x00FF)<<8)|0x08; /* Position overflow register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[3];
- tempbx=((temp&0x00FF)<<8)|0x0A; /* Horiz Position register */
- SiS_SetCH700x(SiS_Pr,tempbx);
- temp = CHTVRegData[resindex].Reg[4];
- tempbx=((temp&0x00FF)<<8)|0x0B; /* Vertical Position register */
- SiS_SetCH700x(SiS_Pr,tempbx);
-
- /* Set minimum flicker filter for Luma channel (SR1-0=00),
+ if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+ SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
+ SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
+ } else {
+ SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
+ SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
+ }
+
+ SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
+ SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
+ SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
+ SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
+ SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
+
+ /* Set minimum flicker filter for Luma channel (SR1-0=00),
minimum text enhancement (S3-2=10),
maximum flicker filter for Chroma channel (S5-4=10)
=00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
- */
- SiS_SetCH700x(SiS_Pr,0x2801);
+ */
+ SiS_SetCH700x(SiS_Pr,0x01,0x28);
- /* Set video bandwidth
+ /* Set video bandwidth
High bandwith Luma composite video filter(S0=1)
low bandwith Luma S-video filter (S2-1=00)
disable peak filter in S-video channel (S3=0)
high bandwidth Chroma Filter (S5-4=11)
=00110001=0x31
- */
- SiS_SetCH700x(SiS_Pr,0xb103); /* old: 3103 */
+ */
+ SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
- /* Register 0x3D does not exist in non-macrovision register map
+ /* Register 0x3D does not exist in non-macrovision register map
(Maybe this is a macrovision register?)
- */
+ */
#ifndef SIS_CP
- SiS_SetCH70xx(SiS_Pr,0x003D);
+ SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
#endif
- /* Register 0x10 only contains 1 writable bit (S0) for sensing,
- all other bits a read-only. Macrovision?
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
+ /* Register 0x10 only contains 1 writable bit (S0) for sensing,
+ all other bits a read-only. Macrovision?
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
- /* Register 0x11 only contains 3 writable bits (S0-S2) for
- contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
+ /* Register 0x11 only contains 3 writable bits (S0-S2) for
+ contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
- /* Clear DSEN
- */
- SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
-
- if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
- if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
- if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on, no need to set FSCI */
- } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF); /* Loop filter on for mode 23 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */
- }
- } else {
- if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
- } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
+ /* Clear DSEN
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
+
+ if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
+ if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
+ if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
+ } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
+ }
+ } else {
+ if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+ } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
#if 0
- SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0); /* FSCI for mode 24 is 428,554,851 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0); /* 198b3a63 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0);
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off for mode 24 */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */
-#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
+#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+ }
}
- }
- } else { /* ---- PAL ---- */
- /* We don't play around with FSCI in PAL mode */
+ } else { /* ---- PAL ---- */
+ /* We don't play around with FSCI in PAL mode */
if(resindex == 0x04) {
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
} else {
- SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
- SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
}
- }
-
+ }
+
#endif /* 300 */
- } else {
+ } else {
- /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
+ /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
#ifdef SIS315H
- /* We don't support modes >1024x768 */
- if (resindex > 6) return;
-
- temp = CHTVRegData[resindex].Reg[0];
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- temp |= 0x10;
- }
- tempbx=((temp & 0x00FF) << 8) | 0x00;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[1];
- tempbx=((temp & 0x00FF) << 8) | 0x01;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[2];
- tempbx=((temp & 0x00FF) << 8) | 0x02;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[3];
- tempbx=((temp & 0x00FF) << 8) | 0x04;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[4];
- tempbx=((temp & 0x00FF) << 8) | 0x03;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[5];
- tempbx=((temp & 0x00FF) << 8) | 0x05;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[6];
- tempbx=((temp & 0x00FF) << 8) | 0x06;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[7];
- if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
- temp = 0x66;
- }
- tempbx=((temp & 0x00FF) << 8) | 0x07;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[8];
- tempbx=((temp & 0x00FF) << 8) | 0x08;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[9];
- tempbx=((temp & 0x00FF) << 8) | 0x15;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[10];
- tempbx=((temp & 0x00FF) << 8) | 0x1f;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[11];
- tempbx=((temp & 0x00FF) << 8) | 0x0c;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[12];
- tempbx=((temp & 0x00FF) << 8) | 0x0d;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[13];
- tempbx=((temp & 0x00FF) << 8) | 0x0e;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[14];
- tempbx=((temp & 0x00FF) << 8) | 0x0f;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = CHTVRegData[resindex].Reg[15];
- tempbx=((temp & 0x00FF) << 8) | 0x10;
- SiS_SetCH701x(SiS_Pr,tempbx);
-
- temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
- /* D1 should be set for PAL, PAL-N and NTSC-J,
- but I won't do that for PAL unless somebody
- tells me to do so. Since the BIOS uses
- non-default CIV values and blacklevels,
- this might be compensated anyway.
- */
- if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
- SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21));
+ unsigned short temp;
+
+ /* We don't support modes >1024x768 */
+ if (resindex > 6) return;
+
+ temp = CHTVRegData[resindex].Reg[0];
+ if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
+ SiS_SetCH701x(SiS_Pr,0x00,temp);
+
+ SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
+ SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
+ SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
+ SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
+ SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
+ SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
+
+ temp = CHTVRegData[resindex].Reg[7];
+ if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
+ SiS_SetCH701x(SiS_Pr,0x07,temp);
+
+ SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
+ SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
+ SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
+ SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
+ SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
+ SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
+ SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
+ SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
+
+ temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
+ /* D1 should be set for PAL, PAL-N and NTSC-J,
+ but I won't do that for PAL unless somebody
+ tells me to do so. Since the BIOS uses
+ non-default CIV values and blacklevels,
+ this might be compensated anyway.
+ */
+ if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
+ SiS_SetCH701x(SiS_Pr,0x21,temp);
#endif /* 315 */
- }
+ }
#ifdef SIS_CP
- SIS_CP_INIT301_CP3
+ SIS_CP_INIT301_CP3
#endif
}
+#ifdef SIS315H /* ----------- 315 series only ---------- */
+
void
-SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- /* Enable Chrontel 7019 LCD panel backlight */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
- SiS_SetCH701x(SiS_Pr,0x6566);
- } else {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
- temp |= 0x20;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- }
- }
+ /* Enable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_SetCH701x(SiS_Pr,0x66,0x65);
+ } else {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp |= 0x20;
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ }
+ }
}
void
-SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr)
+SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- /* Disable Chrontel 7019 LCD panel backlight */
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- temp = SiS_GetCH701x(SiS_Pr,0x66);
- temp &= 0xDF;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- }
+ /* Disable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp &= 0xDF;
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ }
}
-#ifdef SIS315H /* ----------- 315 series only ---------- */
-
static void
-SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
- UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
- UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
- UCHAR asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
- UCHAR asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
- UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
- UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
- UCHAR *tableptr = NULL;
+SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
+{
+ static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
+ static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
+ static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
+ static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+ static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+ static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+ static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+ const unsigned char *tableptr = NULL;
int i;
/* Set up Power up/down timing */
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
- else tableptr = table1024_740;
+ if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
+ else tableptr = table1024_740;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
else tableptr = table1400_740;
} else return;
} else {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- tableptr = table1024_650;
+ tableptr = table1024_650;
} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
- (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+ (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
- tableptr = table1400_650;
+ tableptr = table1400_650;
} else return;
}
for(i=0; i<5; i++) {
- SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+ SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
}
}
static void
-SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
- UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
- 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
- UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
- 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
- UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
- UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
- 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
- UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
- UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
- 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
- UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
- UCHAR *tableptr = NULL;
- USHORT tempbh;
+SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
+{
+ const unsigned char *tableptr = NULL;
+ unsigned short tempbh;
int i;
+ static const unsigned char regtable[] = {
+ 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+ 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
+ };
+ static const unsigned char table1024_740[] = {
+ 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+ 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1280_740[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1400_740[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+ };
+ static const unsigned char table1600_740[] = {
+ 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
+ };
+ static const unsigned char table1024_650[] = {
+ 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+ 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
+ };
+ static const unsigned char table1280_650[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
+ };
+ static const unsigned char table1400_650[] = {
+ 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
+ 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
+ };
+ static const unsigned char table1600_650[] = {
+ 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
+ };
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
@@ -8499,138 +8320,139 @@ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
}
- if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
- else tempbh = 0x0c;
+ if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
+ else tempbh = 0x0c;
for(i = 0; i < tempbh; i++) {
- SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+ SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
}
- SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo);
+ SiS_ChrontelPowerSequencing(SiS_Pr);
tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
tempbh |= 0xc0;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
+ SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
tempbh &= 0xfb;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
tempbh = SiS_GetCH701x(SiS_Pr,0x64);
tempbh |= 0x40;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
+ SiS_SetCH701x(SiS_Pr,0x64,tempbh);
tempbh = SiS_GetCH701x(SiS_Pr,0x03);
tempbh &= 0x3f;
- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,tempbh);
}
}
static void
-SiS_ChrontelResetVSync(SiS_Private *SiS_Pr)
+SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
{
unsigned char temp, temp1;
temp1 = SiS_GetCH701x(SiS_Pr,0x49);
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x7f; /* Use external VSYNC */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_LongDelay(SiS_Pr,3);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_LongDelay(SiS_Pr, 3);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80; /* Use internal VSYNC */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_SetCH701x(SiS_Pr,0x49,temp1);
}
static void
-SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x1c);
temp |= 0x04; /* Invert XCLK phase */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,temp);
}
- if(SiS_IsYPbPr(SiS_Pr, HwInfo)) {
+ if(SiS_IsYPbPr(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x01);
temp &= 0x3f;
temp |= 0x80; /* Enable YPrPb (HDTV) */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ SiS_SetCH701x(SiS_Pr,0x01,temp);
}
- if(SiS_IsChScart(SiS_Pr, HwInfo)) {
+ if(SiS_IsChScart(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x01);
temp &= 0x3f;
temp |= 0xc0; /* Enable SCART + CVBS */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ SiS_SetCH701x(SiS_Pr,0x01,temp);
}
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
SiS_ChrontelResetVSync(SiS_Pr);
- SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
+ SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
} else {
- SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
+ SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
temp = SiS_GetCH701x(SiS_Pr,0x49);
- if(SiS_IsYPbPr(SiS_Pr,HwInfo)) {
+ if(SiS_IsYPbPr(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x73);
temp |= 0x60;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
+ SiS_SetCH701x(SiS_Pr,0x73,temp);
}
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x7f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
- SiS_LongDelay(SiS_Pr,2);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+ SiS_SetCH701x(SiS_Pr,0x47,temp);
}
}
}
static void
-SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
/* Complete power down of LVDS */
if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
- if(HwInfo->jChipType == SIS_740) {
- SiS_LongDelay(SiS_Pr,1);
- SiS_GenericDelay(SiS_Pr,0x16ff);
- SiS_SetCH701x(SiS_Pr,0xac76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_GenericDelay(SiS_Pr, 5887);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
} else {
- SiS_LongDelay(SiS_Pr,2);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfc;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- SiS_SetCH701x(SiS_Pr,0x0066);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ SiS_SetCH701x(SiS_Pr,0x66,0x00);
}
}
}
static void
-SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
temp &= 0x01;
if(!temp) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
temp = SiS_GetCH701x(SiS_Pr,0x49);
- SiS_SetCH701x(SiS_Pr,0x3e49);
+ SiS_SetCH701x(SiS_Pr,0x49,0x3e);
}
+
/* Reset Chrontel 7019 datapath */
- SiS_SetCH701x(SiS_Pr,0x1048);
- SiS_LongDelay(SiS_Pr,1);
- SiS_SetCH701x(SiS_Pr,0x1848);
+ SiS_SetCH701x(SiS_Pr,0x48,0x10);
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_SetCH701x(SiS_Pr,0x48,0x18);
- if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
SiS_ChrontelResetVSync(SiS_Pr);
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
+ SiS_SetCH701x(SiS_Pr,0x49,temp);
}
} else {
@@ -8638,72 +8460,72 @@ SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/* Clear/set/clear GPIO */
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp &= 0xef;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp |= 0x10;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x5c);
temp &= 0xef;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+ SiS_SetCH701x(SiS_Pr,0x5c,temp);
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(!temp) {
- SiS_SetCH701xForLCD(SiS_Pr, HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
}
}
} else { /* 650 */
/* Reset Chrontel 7019 datapath */
- SiS_SetCH701x(SiS_Pr,0x1048);
- SiS_LongDelay(SiS_Pr,1);
- SiS_SetCH701x(SiS_Pr,0x1848);
+ SiS_SetCH701x(SiS_Pr,0x48,0x10);
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_SetCH701x(SiS_Pr,0x48,0x18);
}
}
static void
-SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
SiS_ChrontelResetVSync(SiS_Pr);
}
} else {
- SiS_SetCH701x(SiS_Pr,0xaf76); /* Power up LVDS block */
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
temp = SiS_GetCH701x(SiS_Pr,0x49);
temp &= 1;
if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp &= 0x70;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* enable VSYNC */
- SiS_LongDelay(SiS_Pr,3);
+ SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
+ SiS_LongDelay(SiS_Pr, 3);
temp = SiS_GetCH701x(SiS_Pr,0x47);
temp |= 0x80;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* disable VSYNC */
+ SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
}
}
}
static void
-SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- USHORT temp,temp1;
+ unsigned short temp,temp1;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 1) {
temp++;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+ SiS_SetCH701x(SiS_Pr,0x61,temp);
}
- SiS_SetCH701x(SiS_Pr,0x4566); /* Panel power on */
- SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on */
- SiS_LongDelay(SiS_Pr,1);
- SiS_GenericDelay(SiS_Pr,0x16ff);
+ SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
+ SiS_LongDelay(SiS_Pr, 1);
+ SiS_GenericDelay(SiS_Pr, 5887);
} else { /* 650 */
@@ -8711,38 +8533,38 @@ SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo
temp = SiS_GetCH701x(SiS_Pr,0x61);
if(temp < 2) {
temp++;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+ SiS_SetCH701x(SiS_Pr,0x61,temp);
temp1 = 1;
}
- SiS_SetCH701x(SiS_Pr,0xac76);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
temp = SiS_GetCH701x(SiS_Pr,0x66);
temp |= 0x5f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
if(ModeNo > 0x13) {
- if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
- SiS_GenericDelay(SiS_Pr,0x3ff);
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+ SiS_GenericDelay(SiS_Pr, 1023);
} else {
- SiS_GenericDelay(SiS_Pr,0x2ff);
+ SiS_GenericDelay(SiS_Pr, 767);
}
} else {
if(!temp1)
- SiS_GenericDelay(SiS_Pr,0x2ff);
+ SiS_GenericDelay(SiS_Pr, 767);
}
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp |= 0x03;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
temp = SiS_GetCH701x(SiS_Pr,0x66);
temp &= 0x7f;
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
- SiS_LongDelay(SiS_Pr,1);
+ SiS_SetCH701x(SiS_Pr,0x66,temp);
+ SiS_LongDelay(SiS_Pr, 1);
}
}
static void
-SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
{
- USHORT temp,tempcl,tempch;
+ unsigned short temp,tempcl,tempch;
SiS_LongDelay(SiS_Pr, 1);
tempcl = 3;
@@ -8753,87 +8575,87 @@ SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
temp &= 0x04; /* PLL stable? -> bail out */
if(temp == 0x04) break;
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
/* Power down LVDS output, PLL normal operation */
- SiS_SetCH701x(SiS_Pr,0xac76);
+ SiS_SetCH701x(SiS_Pr,0x76,0xac);
}
- SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
if(tempcl == 0) {
if(tempch == 3) break;
- SiS_ChrontelResetDB(SiS_Pr,HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
tempcl = 3;
tempch++;
}
tempcl--;
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfb; /* Reset PLL */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- SiS_LongDelay(SiS_Pr,2);
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ SiS_LongDelay(SiS_Pr, 2);
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp |= 0x04; /* PLL normal operation */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
- if(HwInfo->jChipType == SIS_740) {
- SiS_SetCH701x(SiS_Pr,0xe078); /* PLL loop filter */
+ SiS_SetCH701x(SiS_Pr,0x76,temp);
+ if(SiS_Pr->ChipType == SIS_740) {
+ SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
} else {
- SiS_SetCH701x(SiS_Pr,0x6078);
+ SiS_SetCH701x(SiS_Pr,0x78,0x60);
}
- SiS_LongDelay(SiS_Pr,2);
+ SiS_LongDelay(SiS_Pr, 2);
} while(0);
- SiS_SetCH701x(SiS_Pr,0x0077); /* MV? */
+ SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
}
static void
-SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
{
- USHORT temp;
+ unsigned short temp;
temp = SiS_GetCH701x(SiS_Pr,0x03);
temp |= 0x80; /* Set datapath 1 to TV */
temp &= 0xbf; /* Set datapath 2 to LVDS */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,temp);
- if(HwInfo->jChipType == SIS_740) {
+ if(SiS_Pr->ChipType == SIS_740) {
temp = SiS_GetCH701x(SiS_Pr,0x1c);
temp &= 0xfb; /* Normal XCLK phase */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+ SiS_SetCH701x(SiS_Pr,0x1c,temp);
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
temp = SiS_GetCH701x(SiS_Pr,0x64);
temp |= 0x40; /* ? Bit not defined */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
+ SiS_SetCH701x(SiS_Pr,0x64,temp);
temp = SiS_GetCH701x(SiS_Pr,0x03);
temp &= 0x3f; /* D1 input to both LVDS and TV */
- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+ SiS_SetCH701x(SiS_Pr,0x03,temp);
if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
- SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */
+ SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
SiS_LongDelay(SiS_Pr, 1);
- SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */
- SiS_ChrontelResetDB(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+ SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
+ SiS_ChrontelDoSomething3(SiS_Pr, 0);
} else {
temp = SiS_GetCH701x(SiS_Pr,0x66);
if(temp != 0x45) {
- SiS_ChrontelResetDB(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
- SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
+ SiS_ChrontelDoSomething3(SiS_Pr, 0);
}
}
} else { /* 650 */
- SiS_ChrontelResetDB(SiS_Pr,HwInfo);
- SiS_ChrontelDoSomething2(SiS_Pr,HwInfo);
+ SiS_ChrontelResetDB(SiS_Pr);
+ SiS_ChrontelDoSomething2(SiS_Pr);
temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
- SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo);
- SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on, LVDS normal operation */
+ SiS_ChrontelDoSomething3(SiS_Pr,temp);
+ SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
}
@@ -8845,15 +8667,12 @@ SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
BOOLEAN
-SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
#ifdef SIS300
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
-#endif
- USHORT ModeIdIndex, RefreshRateTableIndex;
-#if 0
- USHORT temp;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
#endif
+ unsigned short ModeIdIndex, RefreshRateTableIndex;
SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
@@ -8866,37 +8685,37 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/* Used for shifting CR33 */
SiS_Pr->SiS_SelectCRT2Rate = 4;
- SiS_UnLockCRT2(SiS_Pr, HwInfo);
+ SiS_UnLockCRT2(SiS_Pr);
- RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
SiS_SaveCRT2Info(SiS_Pr,ModeNo);
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_DisableBridge(SiS_Pr,HwInfo);
- if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) {
+ SiS_DisableBridge(SiS_Pr);
+ if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
}
- SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
}
if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
- SiS_LockCRT2(SiS_Pr, HwInfo);
+ SiS_LockCRT2(SiS_Pr);
SiS_DisplayOn(SiS_Pr);
return TRUE;
}
- SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
/* Set up Panel Link for LVDS and LCDA */
SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
- ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
- SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
+ SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
@@ -8907,86 +8726,79 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
#endif
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+ SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#ifdef SIS315H
- SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#endif
- SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+ SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
#ifdef SIS315H
- SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+ SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
#endif
- SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+ SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
- SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
- /* For 301BDH (Panel link initialization): */
- if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
- if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
- if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
- SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- }
- }
- }
- SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
- RefreshRateTableIndex,HwInfo);
- }
- }
+ /* For 301BDH (Panel link initialization): */
+ if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+
+ if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
+ SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ }
+ }
} else {
- SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+ SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
- SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
- }
+ SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
+ SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
#ifdef SIS315H
- SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+ SiS_SetCH701xForLCD(SiS_Pr);
#endif
- }
- }
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
- }
- }
- }
+ }
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+ }
+ }
+ }
}
#ifdef SIS300
- if(HwInfo->jChipType < SIS_315H) {
+ if(SiS_Pr->ChipType < SIS_315H) {
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
if(SiS_Pr->SiS_UseOEM) {
if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
- SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
- RefreshRateTableIndex);
+ SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
} else {
- SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
- RefreshRateTableIndex);
+ SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
}
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
(SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
- SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex);
+ SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
}
SiS_DisplayOn(SiS_Pr);
}
@@ -8995,21 +8807,21 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
#endif
#ifdef SIS315H
- if(HwInfo->jChipType >= SIS_315H) {
+ if(SiS_Pr->ChipType >= SIS_315H) {
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- if(HwInfo->jChipType < SIS_661) {
- SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
- SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ if(SiS_Pr->ChipType < SIS_661) {
+ SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
+ SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
} else {
- SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+ SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
}
- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
}
}
#endif
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_EnableBridge(SiS_Pr, HwInfo);
+ SiS_EnableBridge(SiS_Pr);
}
SiS_DisplayOn(SiS_Pr);
@@ -9017,15 +8829,15 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
/* Disable LCD panel when using TV */
- SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
+ SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
} else {
/* Disable TV when using LCD */
- SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
}
}
if(SiS_Pr->SiS_SetFlag & LowModeTests) {
- SiS_LockCRT2(SiS_Pr,HwInfo);
+ SiS_LockCRT2(SiS_Pr);
}
return TRUE;
@@ -9037,13 +8849,13 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/*********************************************/
void
-SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
{
/* Switch on LCD backlight on SiS30xLV */
SiS_DDC2Delay(SiS_Pr,0xff00);
if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
- SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+ SiS_WaitVBRetrace(SiS_Pr);
}
if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
@@ -9051,12 +8863,11 @@ SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
void
-SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
{
/* Switch off LCD backlight on SiS30xLV */
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
- SiS_DDC2Delay(SiS_Pr,0xe000);
+ SiS_DDC2Delay(SiS_Pr,0xff00);
}
/*********************************************/
@@ -9064,7 +8875,7 @@ SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
/*********************************************/
static void
-SiS_SetupDDCN(SiS_Private *SiS_Pr)
+SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
{
SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
@@ -9075,12 +8886,12 @@ SiS_SetupDDCN(SiS_Private *SiS_Pr)
}
#ifdef SIS300
-static UCHAR *
-SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+static unsigned char *
+SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
{
int i, j, num;
- USHORT tempah,temp;
- UCHAR *mydataptr;
+ unsigned short tempah,temp;
+ unsigned char *mydataptr;
for(i=0; i<20; i++) { /* Do 20 attempts to write */
mydataptr = dataptr;
@@ -9088,7 +8899,7 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
if(!num) return mydataptr;
if(i) {
SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
}
if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
tempah = SiS_Pr->SiS_DDC_DeviceAddr;
@@ -9110,12 +8921,12 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
}
static BOOLEAN
-SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
{
SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
SiS_SetSwitchDDC2(SiS_Pr);
@@ -9124,9 +8935,11 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
if(!dataptr) return FALSE;
}
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
#endif
+#endif
return TRUE;
}
#endif
@@ -9139,155 +8952,121 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
*/
static BOOLEAN
-SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor)
+SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
{
- USHORT tempah,temp,i;
+ unsigned short temp, i;
for(i=0; i<20; i++) { /* Do 20 attempts to write */
if(i) {
- SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
- }
- if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = tempbx & 0x00FF; /* Write RAB */
- tempah |= myor; /* (700x: set bit 7, see datasheet) */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
- if(temp) continue; /* (ERROR: no ack) */
- tempah = (tempbx & 0xFF00) >> 8;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */
- if(temp) continue; /* (ERROR: no ack) */
- if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
+ SiS_SetStop(SiS_Pr);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+ }
+ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
+ if(temp) continue; /* (ERROR: no ack) */
+ if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
SiS_Pr->SiS_ChrontelInit = 1;
return TRUE;
}
return FALSE;
}
-#if 0
-#ifdef SIS300
-/* Write Trumpion register */
-static void
-SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
- SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
- SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
- SiS_SetupDDCN(SiS_Pr);
- SiS_SetChReg(SiS_Pr, tempbx, 0);
-}
-#endif
-#endif
-
/* Write to Chrontel 700x */
-/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
void
-SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
if(!(SiS_Pr->SiS_ChrontelInit)) {
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
}
- if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
+ if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
(!(SiS_Pr->SiS_ChrontelInit)) ) {
- SiS_Pr->SiS_DDC_Index = 0x0a; /* Bit 7 = SC; Bit 6 = SD */
- SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Index = 0x0a;
+ SiS_Pr->SiS_DDC_Data = 0x80;
+ SiS_Pr->SiS_DDC_Clk = 0x40;
SiS_SetupDDCN(SiS_Pr);
- SiS_SetChReg(SiS_Pr, tempbx, 0x80);
+ SiS_SetChReg(SiS_Pr, reg, val, 0x80);
}
}
/* Write to Chrontel 701x */
/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
void
-SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
- SiS_SetChReg(SiS_Pr, tempbx, 0);
+ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+ SiS_SetChReg(SiS_Pr, reg, val, 0);
}
-static void
-SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
{
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
- SiS_SetCH700x(SiS_Pr,tempbx);
+ SiS_SetCH700x(SiS_Pr, reg, val);
else
- SiS_SetCH701x(SiS_Pr,tempbx);
+ SiS_SetCH701x(SiS_Pr, reg, val);
}
-static USHORT
-SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor)
+static unsigned short
+SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
{
- USHORT tempah,temp,i;
+ unsigned short tempah, temp, i;
for(i=0; i<20; i++) { /* Do 20 attempts to read */
if(i) {
- SiS_SetStop(SiS_Pr);
- SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
- }
- if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr;
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = SiS_Pr->SiS_DDC_ReadAddr | myor; /* Write RAB (700x: | 0x80) */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
- if(temp) continue; /* (ERROR: no ack) */
- if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
- tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */
- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */
- if(temp) continue; /* (ERROR: no ack) */
- tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
- if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
+ SiS_SetStop(SiS_Pr);
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+ }
+ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
+ if(temp) continue; /* (ERROR: no ack) */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
+ if(temp) continue; /* (ERROR: no ack) */
+ if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
+ temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
+ if(temp) continue; /* (ERROR: no ack) */
+ tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
+ if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
SiS_Pr->SiS_ChrontelInit = 1;
- return(tempah);
+ return tempah;
}
return 0xFFFF;
}
-#if 0
-#ifdef SIS300
-/* Read from Trumpion */
-static USHORT
-SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
- SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB */
- SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
- SiS_SetupDDCN(SiS_Pr);
- SiS_Pr->SiS_DDC_ReadAddr = tempbx;
- return(SiS_GetChReg(SiS_Pr,0));
-}
-#endif
-#endif
-
/* Read from Chrontel 700x */
/* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
- USHORT result;
+ unsigned short result;
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
+ SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
if(!(SiS_Pr->SiS_ChrontelInit)) {
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
}
@@ -9303,52 +9082,69 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
result = SiS_GetChReg(SiS_Pr,0x80);
}
- return(result);
+ return result;
}
/* Read from Chrontel 701x */
/* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
- SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
- SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
SiS_SetupDDCN(SiS_Pr);
SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
SiS_Pr->SiS_DDC_ReadAddr = tempbx;
- return(SiS_GetChReg(SiS_Pr,0));
+ return SiS_GetChReg(SiS_Pr,0);
}
/* Read from Chrontel 70xx */
/* Parameter is [Register no (S7-S0)] */
-static USHORT
-SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+unsigned short
+SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
{
if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
- return(SiS_GetCH700x(SiS_Pr, tempbx));
+ return SiS_GetCH700x(SiS_Pr, tempbx);
else
- return(SiS_GetCH701x(SiS_Pr, tempbx));
+ return SiS_GetCH701x(SiS_Pr, tempbx);
+}
+
+void
+SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char myor, unsigned short myand)
+{
+ unsigned short tempbl;
+
+ tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
+ SiS_SetCH70xx(SiS_Pr, reg, tempbl);
}
/* Our own DDC functions */
-static USHORT
-SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
+ unsigned int VBFlags2)
{
unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
unsigned char flag, cr32;
- USHORT temp = 0, myadaptnum = adaptnum;
+ unsigned short temp = 0, myadaptnum = adaptnum;
if(adaptnum != 0) {
- if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF;
- if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
- }
-
+ if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
+ if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
+ }
+
/* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
-
+
SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
SiS_Pr->SiS_DDC_SecAddr = 0;
@@ -9360,7 +9156,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
#if 0
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
if(myadaptnum == 0) {
if(!(cr32 & 0x20)) {
myadaptnum = 2;
@@ -9376,20 +9172,20 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
#endif
if(VGAEngine == SIS_300_VGA) { /* 300 series */
-
+
if(myadaptnum != 0) {
flag = 0;
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
SiS_Pr->SiS_DDC_Index = 0x0f;
}
}
- if(!(VBFlags & VB_301)) {
+ if(!(VBFlags2 & VB2_301)) {
if((cr32 & 0x80) && (checkcr32)) {
if(myadaptnum >= 1) {
if(!(cr32 & 0x08)) {
- myadaptnum = 1;
+ myadaptnum = 1;
if(!(cr32 & 0x10)) return 0xFFFF;
}
}
@@ -9401,17 +9197,17 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
} else { /* 315/330 series */
- /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
+ /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
- if(VBFlags & VB_SISBRIDGE) {
+ if(VBFlags2 & VB2_SISBRIDGE) {
if(myadaptnum == 2) {
myadaptnum = 1;
- }
+ }
}
if(myadaptnum == 1) {
- flag = 0;
- if(VBFlags & VB_SISBRIDGE) {
+ flag = 0;
+ if(VBFlags2 & VB2_SISBRIDGE) {
SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
SiS_Pr->SiS_DDC_Index = 0x0f;
}
@@ -9429,93 +9225,96 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
temp = myadaptnum;
if(myadaptnum == 1) {
temp = 0;
- if(VBFlags & VB_LVDS) flag = 0xff;
+ if(VBFlags2 & VB2_LVDS) flag = 0xff;
}
if(flag) temp = 0;
}
-
+
SiS_Pr->SiS_DDC_Data = 0x02 << temp;
SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
SiS_SetupDDCN(SiS_Pr);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
#endif
-
+#endif
return 0;
}
-static USHORT
-SiS_WriteDABDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
- return 0xFFFF;
+ return 0xFFFF;
}
if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
- return 0xFFFF;
+ return 0xFFFF;
}
- return(0);
+ return 0;
}
-static USHORT
-SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
- return 0xFFFF;
+ return 0xFFFF;
}
- return(0);
+ return 0;
}
-static USHORT
-SiS_PrepareDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
{
if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
- if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr));
- return(0);
+ if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
+ return 0;
}
static void
-SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno)
+SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
{
SiS_SetSCLKLow(SiS_Pr);
if(yesno) {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
SiS_Pr->SiS_DDC_Data);
} else {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
0);
}
SiS_SetSCLKHigh(SiS_Pr);
}
-static USHORT
-SiS_DoProbeDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
{
unsigned char mask, value;
- USHORT temp, ret=0;
+ unsigned short temp, ret=0;
BOOLEAN failed = FALSE;
SiS_SetSwitchDDC2(SiS_Pr);
if(SiS_PrepareDDC(SiS_Pr)) {
SiS_SetStop(SiS_Pr);
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
#endif
- return(0xFFFF);
+#endif
+ return 0xFFFF;
}
mask = 0xf0;
value = 0x20;
if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
- temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
SiS_SendACK(SiS_Pr, 0);
if(temp == 0) {
mask = 0xff;
@@ -9523,34 +9322,41 @@ SiS_DoProbeDDC(SiS_Private *SiS_Pr)
} else {
failed = TRUE;
ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
#endif
+#endif
}
}
if(failed == FALSE) {
- temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
SiS_SendACK(SiS_Pr, 1);
temp &= mask;
if(temp == value) ret = 0;
else {
ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
#endif
+#endif
if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
if(temp == 0x30) ret = 0;
}
}
}
SiS_SetStop(SiS_Pr);
- return(ret);
+ return ret;
}
-static USHORT
-SiS_ProbeDDC(SiS_Private *SiS_Pr)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
{
- USHORT flag;
+ unsigned short flag;
flag = 0x180;
SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
@@ -9560,16 +9366,19 @@ SiS_ProbeDDC(SiS_Private *SiS_Pr)
SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
if(!(flag & 0x1a)) flag = 0;
- return(flag);
+ return flag;
}
-static USHORT
-SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
{
- USHORT flag, length, i;
+ unsigned short flag, length, i;
unsigned char chksum,gotcha;
- if(DDCdatatype > 4) return 0xFFFF;
+ if(DDCdatatype > 4) return 0xFFFF;
flag = 0;
SiS_SetSwitchDDC2(SiS_Pr);
@@ -9579,21 +9388,21 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
chksum = 0;
gotcha = 0;
for(i=0; i<length; i++) {
- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
chksum += buffer[i];
gotcha |= buffer[i];
SiS_SendACK(SiS_Pr, 0);
}
- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+ buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
chksum += buffer[i];
SiS_SendACK(SiS_Pr, 1);
- if(gotcha) flag = (USHORT)chksum;
+ if(gotcha) flag = (unsigned short)chksum;
else flag = 0xFFFF;
} else {
flag = 0xFFFF;
}
SiS_SetStop(SiS_Pr);
- return(flag);
+ return flag;
}
/* Our private DDC functions
@@ -9617,17 +9426,25 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
if DDCdatatype = 0: Returns supported DDC modes
*/
-USHORT
-SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
+unsigned short
+SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+ unsigned int VBFlags2)
{
- unsigned char sr1f,cr17=1;
- USHORT result;
+ unsigned char sr1f, cr17=1;
+ unsigned short result;
- if(adaptnum > 2) return 0xFFFF;
- if(DDCdatatype > 4) return 0xFFFF;
- if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
- if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF;
+ if(adaptnum > 2)
+ return 0xFFFF;
+
+ if(DDCdatatype > 4)
+ return 0xFFFF;
+
+ if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
+ return 0xFFFF;
+
+ if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
+ return 0xFFFF;
sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
@@ -9656,10 +9473,12 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
(buffer[4] == 0xff) && (buffer[5] == 0xff) &&
(buffer[6] == 0xff) && (buffer[7] == 0x00) &&
(buffer[0x12] == 1)) {
- if(adaptnum == 1) {
- if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
- } else {
- if(buffer[0x14] & 0x80) result = 0xFFFE;
+ if(!SiS_Pr->DDCPortMixup) {
+ if(adaptnum == 1) {
+ if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
+ } else {
+ if(buffer[0x14] & 0x80) result = 0xFFFE;
+ }
}
}
}
@@ -9671,832 +9490,10 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
return result;
}
-#ifdef LINUX_XF86
-
-static BOOLEAN
-checkedid1(unsigned char *buffer)
-{
- /* Check header */
- if((buffer[0] != 0x00) ||
- (buffer[1] != 0xff) ||
- (buffer[2] != 0xff) ||
- (buffer[3] != 0xff) ||
- (buffer[4] != 0xff) ||
- (buffer[5] != 0xff) ||
- (buffer[6] != 0xff) ||
- (buffer[7] != 0x00))
- return FALSE;
-
- /* Check EDID version and revision */
- if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE;
-
- /* Check week of manufacture for sanity */
- if(buffer[0x10] > 53) return FALSE;
-
- /* Check year of manufacture for sanity */
- if(buffer[0x11] > 40) return FALSE;
-
- return TRUE;
-}
-
-static BOOLEAN
-checkedid2(unsigned char *buffer)
-{
- USHORT year = buffer[6] | (buffer[7] << 8);
-
- /* Check EDID version */
- if((buffer[0] & 0xf0) != 0x20) return FALSE;
-
- /* Check week of manufacture for sanity */
- if(buffer[5] > 53) return FALSE;
-
- /* Check year of manufacture for sanity */
- if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE;
-
- return TRUE;
-}
-
-/* Sense the LCD parameters (CR36, CR37) via DDC */
-/* SiS30x(B) only */
-USHORT
-SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
- USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
- USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct;
- int maxx=0, maxy=0, prefx=0, prefy=0;
- unsigned char cr37=0, seekcode;
- BOOLEAN checkexpand = FALSE;
- BOOLEAN havesync = FALSE;
- BOOLEAN indb = FALSE;
- int retry, i;
- unsigned char buffer[256];
-
- for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
- SiS_Pr->CP_HaveCustomData = FALSE;
- SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
- SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
- SiS_Pr->CP_PreferredIndex = -1;
- SiS_Pr->CP_PrefClock = 0;
- SiS_Pr->PanelSelfDetected = FALSE;
-
- if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
- if(pSiS->VBFlags & VB_30xBDH) return 0;
-
- if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
-
- SiS_Pr->SiS_DDC_SecAddr = 0x00;
-
- /* Probe supported DA's */
- flag = SiS_ProbeDDC(SiS_Pr);
-#ifdef TWDEBUG
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
- "CRT2 DDC capabilities 0x%x\n", flag);
-#endif
- if(flag & 0x10) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */
- DDCdatatype = 4;
- } else if(flag & 0x08) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */
- DDCdatatype = 3;
- } else if(flag & 0x02) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */
- DDCdatatype = 1;
- } else return 0; /* no DDC support (or no device attached) */
-
- /* Read the entire EDID */
- retry = 2;
- do {
- if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "CRT2: DDC read failed (attempt %d), %s\n",
- (3-retry), (retry == 1) ? "giving up" : "retrying");
- retry--;
- if(retry == 0) return 0xFFFF;
- } else break;
- } while(1);
-
-#ifdef TWDEBUG
- for(i=0; i<256; i+=16) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffer[i], buffer[i+1], buffer[i+2], buffer[i+3],
- buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7],
- buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11],
- buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
- }
-#endif
-
- /* Analyze EDID and retrieve LCD panel information */
- paneltype = 0;
- switch(DDCdatatype) {
- case 1: /* Analyze EDID V1 */
- /* Catch a few clear cases: */
- if(!(checkedid1(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: EDID corrupt\n");
- return 0;
- }
-
- if(!(buffer[0x14] & 0x80)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Attached display expects analog input (0x%02x)\n",
- buffer[0x14]);
- return 0;
- }
-
- if((buffer[0x18] & 0x18) != 0x08) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n",
- ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
- ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
- "undefined"),
- buffer[0x18]);
- }
-
- /* Now analyze the first Detailed Timing Block and see
- * if the preferred timing mode is stored there. If so,
- * check if this is a standard panel for which we already
- * know the timing.
- */
-
- paneltype = Panel_Custom;
- checkexpand = FALSE;
-
- panelvendor = buffer[9] | (buffer[8] << 8);
- panelproduct = buffer[10] | (buffer[11] << 8);
-
- /* Overrule bogus preferred modes from database */
- if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
- if(prefx) SiS_Pr->CP_PreferredX = xres = prefx;
- if(prefy) SiS_Pr->CP_PreferredY = yres = prefy;
- }
-
- if(buffer[0x18] & 0x02) {
-
- USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8));
- USHORT phb = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8));
- USHORT pvb = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8));
-
- if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
- if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
-
- switch(xres) {
-#if 0 /* Treat as custom */
- case 800:
- if(yres == 600) {
- paneltype = Panel_800x600;
- checkexpand = TRUE;
- }
- break;
-#endif
- case 1024:
- if(yres == 768) {
- paneltype = Panel_1024x768;
- checkexpand = TRUE;
- }
- break;
- case 1280:
- if(yres == 1024) {
- paneltype = Panel_1280x1024;
- checkexpand = TRUE;
- } else if(yres == 960) {
- if(pSiS->VGAEngine == SIS_300_VGA) {
- paneltype = Panel300_1280x960;
- } else {
- paneltype = Panel310_1280x960;
- }
- } else if(yres == 768) {
- if( (pclk == 8100) &&
- (phb == (1688 - 1280)) &&
- (pvb == (802 - 768)) ) {
- paneltype = Panel_1280x768;
- checkexpand = FALSE;
- cr37 |= 0x10;
- }
- } else if(yres == 800) {
- if( (pclk == 6900) &&
- (phb == (1408 - 1280)) &&
- (pvb == (816 - 800)) ) {
- paneltype = Panel_1280x800;
- }
- }
- break;
- case 1400:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(yres == 1050) {
- paneltype = Panel310_1400x1050;
- checkexpand = TRUE;
- }
- }
- break;
- case 1600:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(pSiS->VBFlags & VB_301C) {
- if(yres == 1200) {
- paneltype = Panel310_1600x1200;
- checkexpand = TRUE;
- }
- }
- }
- break;
- }
-
- /* Save sync: This is used if "Pass 1:1" is off; in this case
- * we always use the panel's native mode = this "preferred mode"
- * we just have been analysing. Hence, we also need its sync.
- */
- if((buffer[0x47] & 0x18) == 0x18) {
- cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- } else {
- /* What now? There is no digital separate output timing... */
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- cr37 |= 0xc0; /* Default */
- }
-
- }
-
- /* Check against our database; eg. Sanyo Z2 projector reports
- * 1024x768 as preferred mode, although it supports 1280x720
- * natively in non-HDCP mode. Treat such wrongly reporting
- * panels as custom and fixup actual maximum resolutions.
- */
- if(paneltype != Panel_Custom) {
- if(indb) {
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = maxx;
- SiS_Pr->CP_MaxY = maxy;
- /* Leave preferred unchanged (MUST contain a valid mode!) */
- }
- }
-
- /* If we still don't know what panel this is, we take it
- * as a custom panel and derive the timing data from the
- * detailed timing blocks
- */
- if(paneltype == Panel_Custom) {
-
- int i, temp, base = 0x36;
- unsigned long estpack;
- const unsigned short estx[] = {
- 720, 720, 640, 640, 640, 640, 800, 800,
- 800, 800, 832,1024,1024,1024,1024,1280,
- 1152
- };
- const unsigned short esty[] = {
- 400, 400, 480, 480, 480, 480, 600, 600,
- 600, 600, 624, 768, 768, 768, 768,1024,
- 870
- };
- const int estclk[] = {
- 0, 0, 25100, 0, 31500, 31500, 36100, 40000,
- 50100, 49500, 0, 0, 65100, 75200, 78700,135200,
- 0
- };
-
- paneltype = 0;
- SiS_Pr->CP_Supports64048075 = TRUE;
-
- /* Find the maximum resolution */
-
- /* 1. From Established timings */
- estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
- for(i=16; i>=0; i--) {
- if(estpack & (1 << i)) {
- if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
- if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
- if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i];
- }
- }
-
- /* By default we drive the LCD at 75Hz in 640x480 mode; if
- * the panel does not provide this mode, use 60hz
- */
- if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE;
-
- /* 2. From Standard Timings */
- for(i=0x26; i < 0x36; i+=2) {
- if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
- temp = (buffer[i] + 31) * 8;
- if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
- switch((buffer[i+1] & 0xc0) >> 6) {
- case 0x03: temp = temp * 9 / 16; break;
- case 0x02: temp = temp * 4 / 5; break;
- case 0x01: temp = temp * 3 / 4; break;
- }
- if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
- }
- }
-
- /* Now extract the Detailed Timings and convert them into modes */
-
- for(i = 0; i < 4; i++, base += 18) {
-
- /* Is this a detailed timing block or a monitor descriptor? */
- if(buffer[base] || buffer[base+1] || buffer[base+2]) {
-
- xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
- yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
-
- SiS_Pr->CP_HDisplay[i] = xres;
- SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
- SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
- SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
- SiS_Pr->CP_HBlankStart[i] = xres + 1;
- SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
- SiS_Pr->CP_VDisplay[i] = yres;
- SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
- SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
- SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
- SiS_Pr->CP_VBlankStart[i] = yres + 1;
- SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
- SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
-
- SiS_Pr->CP_DataValid[i] = TRUE;
-
- /* Sort out invalid timings, interlace and too high clocks */
- if((SiS_Pr->CP_HDisplay[i] & 7) ||
- (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
- (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
- ((!(pSiS->VBFlags & VB_301C)) &&
- ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) ||
- (SiS_Pr->CP_HDisplay[i] > 1600)))) ||
- (buffer[base+17] & 0x80)) {
-
- SiS_Pr->CP_DataValid[i] = FALSE;
-
- } else {
-
- SiS_Pr->CP_HaveCustomData = TRUE;
-
- if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
- if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
- if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
- if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
- SiS_Pr->CP_PreferredIndex = i;
- SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
- SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
- }
-
- /* Extract the sync polarisation information. This only works
- * if the Flags indicate a digital separate output.
- */
- if((buffer[base+17] & 0x18) == 0x18) {
- SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
- SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
- SiS_Pr->CP_SyncValid[i] = TRUE;
- if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) {
- cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- }
- } else {
- SiS_Pr->CP_SyncValid[i] = FALSE;
- }
-
- }
-
- } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) {
-
- /* Maximum pixclock from Monitor Range Limits */
- if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) {
- int maxclk = buffer[base+9] * 10;
- /* More than 170 is not supported anyway */
- if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000;
- }
-
- }
-
- }
-
- if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) {
- paneltype = Panel_Custom;
- checkexpand = FALSE;
- cr37 |= 0x10;
- SiS_Pr->CP_Vendor = panelvendor;
- SiS_Pr->CP_Product = panelproduct;
- }
-
- }
-
- if(paneltype && checkexpand) {
- /* If any of the Established low-res modes is supported, the
- * panel can scale automatically. For 800x600 panels, we only
- * check the even lower ones.
- */
- if(paneltype == Panel_800x600) {
- if(buffer[0x23] & 0xfc) cr37 |= 0x10;
- } else {
- if(buffer[0x23]) cr37 |= 0x10;
- }
- }
-
- break;
-
- case 3: /* Analyze EDID V2 */
- case 4:
- index = 0;
-
- if(!(checkedid2(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: EDID corrupt\n");
- return 0;
- }
-
- if((buffer[0x41] & 0x0f) == 0x03) {
- index = 0x42 + 3;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display supports TMDS input on primary interface\n");
- } else if((buffer[0x41] & 0xf0) == 0x30) {
- index = 0x46 + 3;
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display supports TMDS input on secondary interface\n");
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "LCD sense: Display does not support TMDS video interface (0x%02x)\n",
- buffer[0x41]);
- return 0;
- }
-
- SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8);
- SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8);
-
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8);
- SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8);
-
- switch(xres) {
-#if 0
- case 800:
- if(yres == 600) {
- paneltype = Panel_800x600;
- checkexpand = TRUE;
- }
- break;
-#endif
- case 1024:
- if(yres == 768) {
- paneltype = Panel_1024x768;
- checkexpand = TRUE;
- }
- break;
- case 1280:
- if(yres == 960) {
- if(pSiS->VGAEngine == SIS_315_VGA) {
- paneltype = Panel310_1280x960;
- } else {
- paneltype = Panel300_1280x960;
- }
- } else if(yres == 1024) {
- paneltype = Panel_1280x1024;
- checkexpand = TRUE;
- }
- /* 1280x768 treated as custom here */
- break;
- case 1400:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(yres == 1050) {
- paneltype = Panel310_1400x1050;
- checkexpand = TRUE;
- }
- }
- break;
- case 1600:
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(pSiS->VBFlags & VB_301C) {
- if(yres == 1200) {
- paneltype = Panel310_1600x1200;
- checkexpand = TRUE;
- }
- }
- }
- break;
- }
-
- /* Determine if RGB18 or RGB24 */
- if(index) {
- if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
- cr37 |= 0x01;
- }
- }
-
- if(checkexpand) {
- /* TODO - for now, we let the panel scale */
- cr37 |= 0x10;
- }
-
- /* Now seek 4-Byte Timing codes and extract sync pol info */
- index = 0x80;
- if(buffer[0x7e] & 0x20) { /* skip Luminance Table (if provided) */
- lumsize = buffer[0x80] & 0x1f;
- if(buffer[0x80] & 0x80) lumsize *= 3;
- lumsize++; /* luminance header byte */
- index += lumsize;
- }
-#if 0 /* "pixel rate" = pixel clock? */
- if(buffer[0x7e] & 0x1c) {
- for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) {
- if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) {
- int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000;
- if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
- }
- }
- }
-#endif
- index += (((buffer[0x7e] & 0x1c) >> 2) * 8); /* skip Frequency Ranges */
- if(buffer[0x7e] & 0x03) {
- for(i=0; i<(buffer[0x7e] & 0x03); i++) {
- if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) {
- int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10;
- if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
- }
- }
- }
- index += ((buffer[0x7e] & 0x03) * 27); /* skip Detailed Range Limits */
- numcodes = (buffer[0x7f] & 0xf8) >> 3;
- if(numcodes) {
- myindex = index;
- seekcode = (xres - 256) / 16;
- for(i=0; i<numcodes; i++) {
- if(buffer[myindex] == seekcode) break;
- myindex += 4;
- }
- if(buffer[myindex] == seekcode) {
- cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
- havesync = TRUE;
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- }
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
- "LCD sense: Unable to retrieve Sync polarity information\n");
- }
-
- /* Check against our database; Eg. Sanyo projector reports
- * 1024x768 in non-HDPC mode, although it supports 1280x720.
- * Treat such wrongly reporting panels as custom.
- */
- if(paneltype != Panel_Custom) {
- int maxx, maxy, prefx, prefy;
- if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
- paneltype = Panel_Custom;
- SiS_Pr->CP_MaxX = maxx;
- SiS_Pr->CP_MaxY = maxy;
- cr37 |= 0x10;
- /* Leave preferred unchanged (MUST be a valid mode!) */
- }
- }
-
- /* Now seek the detailed timing descriptions for custom panels */
- if(paneltype == Panel_Custom) {
-
- SiS_Pr->CP_Supports64048075 = TRUE;
-
- index += (numcodes * 4);
- numcodes = buffer[0x7f] & 0x07;
- for(i=0; i<numcodes; i++, index += 18) {
- xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
- yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
-
- SiS_Pr->CP_HDisplay[i] = xres;
- SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
- SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
- SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
- SiS_Pr->CP_HBlankStart[i] = xres + 1;
- SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
- SiS_Pr->CP_VDisplay[i] = yres;
- SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
- SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
- SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
- SiS_Pr->CP_VBlankStart[i] = yres + 1;
- SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
- SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
-
- SiS_Pr->CP_DataValid[i] = TRUE;
-
- if((SiS_Pr->CP_HDisplay[i] & 7) ||
- (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
- (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
- (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
- (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
- (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
- (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
- ((!(pSiS->VBFlags & VB_301C)) &&
- ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024)))) ||
- (buffer[index + 17] & 0x80)) {
-
- SiS_Pr->CP_DataValid[i] = FALSE;
-
- } else {
-
- SiS_Pr->CP_HaveCustomData = TRUE;
-
- if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
- if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
- SiS_Pr->CP_PreferredIndex = i;
- SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
- SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
- if(!havesync) {
- cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20);
- havesync = TRUE;
- }
- }
-
- SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
- SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
- SiS_Pr->CP_SyncValid[i] = TRUE;
-
- }
- }
-
- cr37 |= 0x10;
-
- }
-
- break;
-
- }
-
- /* 1280x960 panels are always RGB24, unable to scale and use
- * high active sync polarity
- */
- if(pSiS->VGAEngine == SIS_315_VGA) {
- if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
- } else {
- if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
- }
-
- for(i = 0; i < 7; i++) {
- if(SiS_Pr->CP_DataValid[i]) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "Non-standard LCD/DVI-D timing data no. %d:\n", i);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
- SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
- SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
- SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
- SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- " Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
- " To use this, add \"%dx%d\" to the list of Modes in the Screen section\n",
- SiS_Pr->CP_HDisplay[i],
- SiS_Pr->CP_VDisplay[i]);
- }
- }
-
- if(paneltype) {
- if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
- if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
- cr37 &= 0xf1;
- SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
- SiS_Pr->PanelSelfDetected = TRUE;
-#ifdef TWDEBUG
- xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3,
- "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
-#endif
- } else {
- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
- SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
- }
- return 0;
-}
-
-USHORT
-SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
- USHORT DDCdatatype,flag;
- BOOLEAN foundcrt = FALSE;
- int retry;
- unsigned char buffer[256];
-
- if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
-
- if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
-
- SiS_Pr->SiS_DDC_SecAddr = 0x00;
-
- /* Probe supported DA's */
- flag = SiS_ProbeDDC(SiS_Pr);
- if(flag & 0x10) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */
- DDCdatatype = 4;
- } else if(flag & 0x08) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */
- DDCdatatype = 3;
- } else if(flag & 0x02) {
- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */
- DDCdatatype = 1;
- } else {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "VGA2 sense: Do DDC answer\n");
- return 0; /* no DDC support (or no device attached) */
- }
-
- /* Read the entire EDID */
- retry = 2;
- do {
- if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
- "VGA2 sense: DDC read failed (attempt %d), %s\n",
- (3-retry), (retry == 1) ? "giving up" : "retrying");
- retry--;
- if(retry == 0) return 0xFFFF;
- } else break;
- } while(1);
-
- /* Analyze EDID. We don't have many chances to
- * distinguish a flat panel from a CRT...
- */
- switch(DDCdatatype) {
- case 1:
- if(!(checkedid1(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: EDID corrupt\n");
- return 0;
- }
- if(buffer[0x14] & 0x80) { /* Display uses digital input */
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: Attached display expects digital input\n");
- return 0;
- }
- SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
- SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
- foundcrt = TRUE;
- break;
- case 3:
- case 4:
- if(!(checkedid2(buffer))) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: EDID corrupt\n");
- return 0;
- }
- if( ((buffer[0x41] & 0x0f) != 0x01) && /* Display does not support analog input */
- ((buffer[0x41] & 0x0f) != 0x02) &&
- ((buffer[0x41] & 0xf0) != 0x10) &&
- ((buffer[0x41] & 0xf0) != 0x20) ) {
- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
- "VGA2 sense: Attached display does not support analog input (0x%02x)\n",
- buffer[0x41]);
- return 0;
- }
- SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
- SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
- foundcrt = TRUE;
- break;
- }
-
- if(foundcrt) {
- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
- }
- return(0);
-}
-
-#endif
-
-void
-SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
-{
- USHORT tempbl;
-
- tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
- tempbl = (((tempbl & tempbh) << 8) | tempax);
- SiS_SetCH70xx(SiS_Pr,tempbl);
-}
-
/* Generic I2C functions for Chrontel & DDC --------- */
static void
-SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
+SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
{
SiS_SetSCLKHigh(SiS_Pr);
SiS_WaitRetrace1(SiS_Pr);
@@ -10505,125 +9502,127 @@ SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
SiS_WaitRetrace1(SiS_Pr);
}
-USHORT
-SiS_ReadDDC1Bit(SiS_Private *SiS_Pr)
+unsigned short
+SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
{
SiS_WaitRetrace1(SiS_Pr);
- return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
+ return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
}
/* Set I2C start condition */
/* This is done by a SD high-to-low transition while SC is high */
-static USHORT
-SiS_SetStart(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStart(struct SiS_Private *SiS_Pr)
{
- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* SD->high */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* SD->high */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* SD->low = start condition */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* SD->low = start condition */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
return 0;
}
/* Set I2C stop condition */
/* This is done by a SD low-to-high transition while SC is high */
-static USHORT
-SiS_SetStop(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStop(struct SiS_Private *SiS_Pr)
{
- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* SD->low */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* SD->low */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
+ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
return 0;
}
/* Write 8 bits of data */
-static USHORT
-SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
{
- USHORT i,flag,temp;
+ unsigned short i,flag,temp;
flag = 0x80;
- for(i=0; i<8; i++) {
- SiS_SetSCLKLow(SiS_Pr); /* SC->low */
+ for(i = 0; i < 8; i++) {
+ SiS_SetSCLKLow(SiS_Pr); /* SC->low */
if(tempax & flag) {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
} else {
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- 0x00); /* Write bit (0) to SD */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ 0x00); /* Write bit (0) to SD */
}
- SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
+ SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
flag >>= 1;
}
- temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
- return(temp);
+ temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
+ return temp;
}
-static USHORT
-SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
{
- USHORT i,temp,getdata;
+ unsigned short i, temp, getdata;
- getdata=0;
- for(i=0; i<8; i++) {
+ getdata = 0;
+ for(i = 0; i < 8; i++) {
getdata <<= 1;
SiS_SetSCLKLow(SiS_Pr);
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
SiS_Pr->SiS_DDC_Data);
SiS_SetSCLKHigh(SiS_Pr);
temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
}
- return(getdata);
+ return getdata;
}
-static USHORT
-SiS_SetSCLKLow(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
{
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NClk,
- 0x00); /* SetSCLKLow() */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NClk,
+ 0x00); /* SetSCLKLow() */
SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
return 0;
}
-static USHORT
-SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
{
- USHORT temp, watchdog=1000;
+ unsigned short temp, watchdog=1000;
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NClk,
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NClk,
SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
do {
temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
} while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
if (!watchdog) {
+#ifdef SIS_XORG_XF86
#ifdef TWDEBUG
xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
#endif
+#endif
return 0xFFFF;
}
SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
@@ -10632,21 +9631,21 @@ SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
/* Check I2C acknowledge */
/* Returns 0 if ack ok, non-0 if ack not ok */
-static USHORT
-SiS_CheckACK(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_CheckACK(struct SiS_Private *SiS_Pr)
{
- USHORT tempah;
+ unsigned short tempah;
SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
- SiS_Pr->SiS_DDC_Index,
- SiS_Pr->SiS_DDC_NData,
- SiS_Pr->SiS_DDC_Data); /* (SD->high) */
+ SiS_Pr->SiS_DDC_Index,
+ SiS_Pr->SiS_DDC_NData,
+ SiS_Pr->SiS_DDC_Data); /* (SD->high) */
SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
- if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* Ack OK if bit = 0 */
- else return(0);
+ if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
+ return 0;
}
/* End of I2C functions ----------------------- */
@@ -10656,67 +9655,67 @@ SiS_CheckACK(SiS_Private *SiS_Pr)
#ifdef SIS315H
-static USHORT
-GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetRAMDACromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x128);
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB)
romptr = SISGETROMW(0x12a);
} else {
romptr = SISGETROMW(0x1a8);
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB)
romptr = SISGETROMW(0x1aa);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x120);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x122);
} else {
romptr = SISGETROMW(0x1a0);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x1a2);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetTVromptr(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr;
- if(HwInfo->jChipType < SIS_330) {
+ if(SiS_Pr->ChipType < SIS_330) {
romptr = SISGETROMW(0x114);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x11a);
} else {
romptr = SISGETROMW(0x194);
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
romptr = SISGETROMW(0x19a);
}
- return(romptr);
+ return romptr;
}
-static USHORT
-GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
- if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
- if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+ if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+ if(!(SiS_IsNotM650orLater(SiS_Pr))) {
if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
index >>= 4;
index *= 3;
@@ -10729,7 +9728,12 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
- else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+ if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
+ } else {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+ }
index--;
index *= 3;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -10737,10 +9741,10 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
return index;
}
-static USHORT
-GetLCDPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -10748,10 +9752,10 @@ GetLCDPtrIndex(SiS_Private *SiS_Pr)
return index;
}
-static USHORT
-GetTVPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetTVPtrIndex(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = 0;
if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
@@ -10769,10 +9773,10 @@ GetTVPtrIndex(SiS_Private *SiS_Pr)
return index;
}
-static ULONG
-GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
+static unsigned int
+GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
{
- USHORT index = 0, temp = 0;
+ unsigned short index = 0, temp = 0;
if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
@@ -10784,7 +9788,7 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
index += addme;
@@ -10792,25 +9796,25 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
}
temp += 0x0100;
}
- return(ULONG)(index | (temp << 16));
+ return (unsigned int)(index | (temp << 16));
}
-static ULONG
-GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
{
- return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+ return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
}
#if 0
-static ULONG
-GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
{
- return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+ return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
}
#endif
static int
-GetOEMTVPtr661(SiS_Private *SiS_Pr)
+GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
{
int index = 0;
@@ -10833,10 +9837,10 @@ GetOEMTVPtr661(SiS_Private *SiS_Pr)
}
static void
-SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT delay=0,index,myindex,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short delay=0,index,myindex,temp,romptr=0;
BOOLEAN dochiptest = TRUE;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -10848,19 +9852,19 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
/* Find delay (from ROM, internal tables, PCI subsystem) */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
-
+
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
+ romptr = GetRAMDACromptr(SiS_Pr);
}
if(romptr) delay = ROMAddr[romptr];
else {
delay = 0x04;
- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
if(IS_SIS650) {
delay = 0x0a;
} else if(IS_SIS740) {
delay = 0x00;
- } else if(HwInfo->jChipType < SIS_330) {
+ } else if(SiS_Pr->ChipType < SIS_330) {
delay = 0x0c;
} else {
delay = 0x0c;
@@ -10901,8 +9905,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
} else {
delay = 0x0c;
- if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
- else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+ delay = 0x03;
+ if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
+ delay = 0x00;
+ }
+ } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(IS_SIS740) delay = 0x01;
else delay = 0x03;
}
@@ -10947,12 +9955,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
if(!gotitfrompci) {
- index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo);
+ index = GetLCDPtrIndexBIOS(SiS_Pr);
myindex = GetLCDPtrIndex(SiS_Pr);
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
- if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
/* Always use the second pointer on 650; some BIOSes */
@@ -10978,11 +9986,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
(!(SiS_Pr->SiS_ROMNew)) &&
(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
(SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
- (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
+ (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
+ (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
+ ((romptr = GetLCDromptr(SiS_Pr)))) {
/* Data for 1280x1024 wrong in 301B BIOS */
- romptr = GetLCDromptr(SiS_Pr, HwInfo);
- if(!romptr) return;
+ /* Data for 1600x1200 wrong in 301C BIOS */
delay = ROMAddr[(romptr + index)];
} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
@@ -10993,14 +10002,15 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else {
delay = SiS310_LCDDelayCompensation_301[myindex];
- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(IS_SIS740) delay = 0x01;
- else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
+ else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
} else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
if(IS_SIS740) delay = 0x01; /* ? */
else delay = 0x03;
- } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
+ } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
if(IS_SIS740) delay = 0x01;
else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
}
@@ -11013,14 +10023,14 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
dochiptest = FALSE;
}
-
+
} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
index = GetTVPtrIndex(SiS_Pr);
-
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
- if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+
+ if(SiS_IsNotM650orLater(SiS_Pr)) {
if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
/* Always use the second pointer on 650; some BIOSes */
@@ -11062,7 +10072,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
- romptr = GetTVromptr(SiS_Pr, HwInfo);
+ romptr = GetTVromptr(SiS_Pr);
if(!romptr) return;
delay = ROMAddr[romptr + index];
@@ -11073,7 +10083,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
} else {
delay = SiS310_TVDelayCompensation_301[index];
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
if(IS_SIS740) {
delay = SiS310_TVDelayCompensation_740301B[index];
/* LV: use 301 data? BIOS bug? */
@@ -11085,18 +10095,18 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
}
- if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+ if(SiS_LCDAEnabled(SiS_Pr)) {
delay &= 0x0f;
dochiptest = FALSE;
}
-
+
} else return;
/* Write delay */
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) {
+ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
@@ -11134,11 +10144,10 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
}
static void
-SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,temp1,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,temp1,romptr=0;
if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
@@ -11152,14 +10161,14 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
temp1 = temp;
if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
temp1 = GetOEMTVPtr661(SiS_Pr);
temp1 >>= 1;
romptr = SISGETROMW(0x260);
- if(HwInfo->jChipType >= SIS_760) {
+ if(SiS_Pr->ChipType >= SIS_760) {
romptr = SISGETROMW(0x360);
}
- } else if(HwInfo->jChipType >= SIS_330) {
+ } else if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x192);
} else {
romptr = SISGETROMW(0x112);
@@ -11178,11 +10187,10 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,temp1,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,temp1,romptr=0;
temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
@@ -11192,14 +10200,14 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
- if(HwInfo->jChipType >= SIS_661) {
+ if(SiS_Pr->ChipType >= SIS_661) {
romptr = SISGETROMW(0x26c);
- if(HwInfo->jChipType >= SIS_760) {
+ if(SiS_Pr->ChipType >= SIS_760) {
romptr = SISGETROMW(0x36c);
}
temp1 = GetOEMTVPtr661(SiS_Pr);
temp1 >>= 1;
- } else if(HwInfo->jChipType >= SIS_330) {
+ } else if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x1a4);
} else {
romptr = SISGETROMW(0x124);
@@ -11217,10 +10225,9 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- USHORT index, temp, i, j;
+ unsigned short index, temp, i, j;
if(ModeNo <= 0x13) {
index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
@@ -11235,7 +10242,7 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x35, j=0; i<=0x38; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
}
@@ -11250,23 +10257,22 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,i,j,resinfo,romptr=0;
- ULONG lindex;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,i,j,resinfo,romptr=0;
+ unsigned int lindex;
if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
/* NTSC-J data not in BIOS, and already set in SetGroup2 */
if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
- if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+ if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
lindex <<= 2;
for(j=0, i=0x31; i<=0x34; i++, j++) {
- SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
+ SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
}
return;
}
@@ -11286,17 +10292,17 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
*/
if(SiS_Pr->SiS_UseROM) {
romptr = SISGETROMW(0x116);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x196);
}
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
romptr = SISGETROMW(0x11c);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x19c);
}
if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
romptr = SISGETROMW(0x116);
- if(HwInfo->jChipType >= SIS_330) {
+ if(SiS_Pr->ChipType >= SIS_330) {
romptr = SISGETROMW(0x196);
}
}
@@ -11311,7 +10317,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = temp % 2;
temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
for(j=0, i=0x31; i<=0x34; i++, j++) {
- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))
+ if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
@@ -11320,7 +10326,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+ if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
if((resinfo == SIS_RI_640x480) ||
(resinfo == SIS_RI_800x600)) {
@@ -11339,11 +10345,11 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
- USHORT ModeIdIndex, USHORT RTI)
+SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RTI)
{
- USHORT delay = 0, romptr = 0, index, lcdpdcindex;
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
+ unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
return;
@@ -11359,7 +10365,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
if(SiS_Pr->UseCustomMode) {
index = SiS_Pr->CSRClock;
} else if(ModeNo > 0x13) {
- index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+ index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
index = SiS_Pr->SiS_VCLKData[index].CLOCK;
}
if(index < 25) index = 25;
@@ -11387,7 +10393,36 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
delay |= (delay << 8);
- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->ChipType >= XGI_20) {
+
+ delay = 0x0606;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+ delay = 0x0404;
+ if(SiS_Pr->SiS_XGIROM) {
+ index = GetTVPtrIndex(SiS_Pr);
+ if((romptr = SISGETROMW(0x35e))) {
+ delay = (ROMAddr[romptr + index] & 0x0f) << 1;
+ delay |= (delay << 8);
+ }
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+ if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
+ delay -= 0x0404;
+ }
+ }
+ }
+
+ } else if(SiS_Pr->ChipType >= SIS_340) {
+
+ delay = 0x0606;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ delay = 0x0404;
+ }
+ /* TODO (eventually) */
+
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
/* 3. TV */
@@ -11406,7 +10441,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
/* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
- ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+ ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
@@ -11426,6 +10461,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
case Panel_1280x768_2:delay = 0x0004; break;
case Panel_1280x800:
case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
+ case Panel_1280x854: delay = 0x0004; break; /* FIXME */
case Panel_1280x1024: delay = 0x1e04; break;
case Panel_1400x1050: delay = 0x0004; break;
case Panel_1600x1200: delay = 0x0400; break;
@@ -11469,10 +10505,10 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
}
static void
-SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI)
+SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
{
- USHORT infoflag;
- UCHAR temp;
+ unsigned short infoflag;
+ unsigned char temp;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
@@ -11513,12 +10549,16 @@ SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, US
}
static void
-SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SetPanelParms661(struct SiS_Private *SiS_Pr)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT romptr, temp1, temp2;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short romptr, temp1, temp2;
+
+ if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
+ }
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
if(SiS_Pr->LVDSHL != -1) {
SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
}
@@ -11526,8 +10566,8 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
if(SiS_Pr->SiS_ROMNew) {
- if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
- if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+ if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
+ if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
temp2 = 0xfc;
if(SiS_Pr->LVDSHL != -1) {
@@ -11546,48 +10586,47 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
}
static void
-SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI)
+SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
{
if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
- SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+ SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
- SetPanelParms661(SiS_Pr,HwInfo);
+ SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+ SetPanelParms661(SiS_Pr);
}
} else {
- SetDelayComp(SiS_Pr,HwInfo,ModeNo);
+ SetDelayComp(SiS_Pr,ModeNo);
}
if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
- SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
+ SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
+ SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
}
}
}
static void
-SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI)
+SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI)
{
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+ SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
- SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
- SetPanelParms661(SiS_Pr,HwInfo);
+ SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+ SetPanelParms661(SiS_Pr);
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
- SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
+ SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
+ SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SIS301) {
- SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+ SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
}
}
}
@@ -11601,13 +10640,12 @@ SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
* pray that we have a backup...
*/
static void
-SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- PSIS_HW_INFO HwInfo)
+SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
- USHORT resinfo,modeflag;
+ unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
+ unsigned short resinfo,modeflag;
- if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
if(SiS_Pr->SiS_ROMNew) return;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
@@ -11678,7 +10716,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
- if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+ if(SiS_Pr->SiS_VBType & VB_SISEMI) {
SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
#ifdef SET_EMI
SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
@@ -11806,11 +10844,11 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
#ifdef SIS300
static void
-SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
+SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+ unsigned short RefTabIndex)
{
- USHORT crt2crtc=0, modeflag, myindex=0;
- UCHAR temp;
+ unsigned short crt2crtc=0, modeflag, myindex=0;
+ unsigned char temp;
int i;
if(ModeNo <= 0x13) {
@@ -11849,21 +10887,21 @@ SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
-static USHORT
-GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
+static unsigned short
+GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT tempbx=0,romptr=0;
- UCHAR customtable300[] = {
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short tempbx=0,romptr=0;
+ static const unsigned char customtable300[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};
- UCHAR customtable630[] = {
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ static const unsigned char customtable630[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};
- if(HwInfo->jChipType == SIS_300) {
+ if(SiS_Pr->ChipType == SIS_300) {
tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
@@ -11912,11 +10950,10 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
}
static void
-SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
@@ -11927,22 +10964,22 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
/* The Panel Compensation Delay should be set according to tables
- * here. Unfortunately, various BIOS versions don't case about
+ * here. Unfortunately, various BIOS versions don't care about
* a uniform way using eg. ROM byte 0x220, but use different
* hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
- * Thus we don't set this if the user select a custom pdc or if
+ * Thus we don't set this if the user selected a custom pdc or if
* we otherwise detected a valid pdc.
*/
if(SiS_Pr->PDC != -1) return;
- temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
+ temp = GetOEMLCDPtr(SiS_Pr, 0);
if(SiS_Pr->UseCustomMode)
index = 0;
else
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
- if(HwInfo->jChipType != SIS_300) {
+ if(SiS_Pr->ChipType != SIS_300) {
if(romptr) {
romptr += (temp * 2);
romptr = SISGETROMW(romptr);
@@ -11986,12 +11023,11 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
#if 0 /* Unfinished; Data table missing */
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp;
if((SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x237] & 0x01)) return;
@@ -11999,8 +11035,8 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
/* No rom pointer in BIOS header! */
}
- temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1);
- if(temp = 0xFFFF) return;
+ temp = GetOEMLCDPtr(SiS_Pr, 1);
+ if(temp == 0xFFFF) return;
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
for(i=0x14, j=0; i<=0x17; i++, j++) {
@@ -12018,10 +11054,10 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
#endif
}
-static USHORT
-GetOEMTVPtr(SiS_Private *SiS_Pr)
+static unsigned short
+GetOEMTVPtr(struct SiS_Private *SiS_Pr)
{
- USHORT index;
+ unsigned short index;
index = 0;
if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
@@ -12037,11 +11073,10 @@ GetOEMTVPtr(SiS_Private *SiS_Pr)
}
static void
-SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12070,11 +11105,10 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex)
+SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,romptr=0;
if(SiS_Pr->SiS_UseROM) {
if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12099,11 +11133,10 @@ SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,i,j,temp,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,i,j,temp,romptr=0;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
@@ -12119,7 +11152,7 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x31, j=0; i<=0x34; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
}
@@ -12140,11 +11173,10 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
static void
-SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
{
- UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
- USHORT index,temp,i,j,romptr=0;
+ unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+ unsigned short index,temp,i,j,romptr=0;
if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
@@ -12162,7 +11194,7 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
for(i=0x35, j=0; i<=0x38; i++, j++) {
SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
}
@@ -12185,11 +11217,11 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
}
-static USHORT
-SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
+static unsigned short
+SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
{
- USHORT ModeIdIndex;
- UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+ unsigned short ModeIdIndex;
+ unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
if(*ModeNo <= 5) *ModeNo |= 1;
@@ -12210,10 +11242,10 @@ SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
}
static void
-SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex)
+SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefTableIndex)
{
- USHORT OEMModeIdIndex=0;
+ unsigned short OEMModeIdIndex = 0;
if(!SiS_Pr->UseCustomMode) {
OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
@@ -12221,18 +11253,18 @@ SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
}
if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
- SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
- SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
}
}
if(SiS_Pr->UseCustomMode) return;
if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
- SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex);
+ SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
if(SiS_Pr->SiS_VBType & VB_SISVB) {
- SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
- SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
- SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+ SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
+ SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
+ SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
}
}
}
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index f84eb54164a5..f475b21a85cf 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -3,7 +3,7 @@
/*
* Data and prototypes for init301.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,18 +50,18 @@
*
*/
-#ifndef _INIT301_
-#define _INIT301_
+#ifndef _INIT301_H_
+#define _INIT301_H_
#include "osdef.h"
#include "initdef.h"
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#include "sis.h"
#include "sis_regs.h"
#endif
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include "vgatypes.h"
#include "vstruct.h"
#ifdef SIS_CP
@@ -69,8 +69,13 @@
#endif
#include <linux/config.h>
#include <linux/version.h>
-#include <asm/io.h>
#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/sisfb.h>
#else
@@ -78,7 +83,7 @@
#endif
#endif
-static const UCHAR SiS_YPbPrTable[3][64] = {
+static const unsigned char SiS_YPbPrTable[3][64] = {
{
0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
@@ -90,17 +95,17 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
},
{
- 0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+ 0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
+ 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
- 0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
+ 0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
},
{
-#if 1
+#if 0 /* OK, but sticks to left edge */
0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
@@ -110,20 +115,42 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
#endif
-#if 0
- 0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c, /* TEST (0.93) - BAD */
+#if 1 /* Perfect */
+ 0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
- 0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
- 0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
- 0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+ 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+ 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+ 0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
+ 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
#endif
}
};
-static const UCHAR SiS_HiTVGroup3_1[] = {
+static const unsigned char SiS_TVPhase[] =
+{
+ 0x21,0xED,0xBA,0x08, /* 0x00 SiS_NTSCPhase */
+ 0x2A,0x05,0xE3,0x00, /* 0x01 SiS_PALPhase */
+ 0x21,0xE4,0x2E,0x9B, /* 0x02 SiS_PALMPhase */
+ 0x21,0xF4,0x3E,0xBA, /* 0x03 SiS_PALNPhase */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x05 SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x21,0xF0,0x7B,0xD6, /* 0x08 SiS_NTSCPhase2 */
+ 0x2A,0x09,0x86,0xE9, /* 0x09 SiS_PALPhase2 */
+ 0x21,0xE6,0xEF,0xA4, /* 0x0a SiS_PALMPhase2 */
+ 0x21,0xF6,0x94,0x46, /* 0x0b SiS_PALNPhase2 */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x0d SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x1e,0x8c,0x5c,0x7a, /* 0x10 SiS_SpecialPhase */
+ 0x25,0xd4,0xfd,0x5e /* 0x11 SiS_SpecialPhaseJ */
+};
+
+static const unsigned char SiS_HiTVGroup3_1[] = {
0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -134,7 +161,7 @@ static const UCHAR SiS_HiTVGroup3_1[] = {
0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
};
-static const UCHAR SiS_HiTVGroup3_2[] = {
+static const unsigned char SiS_HiTVGroup3_2[] = {
0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -147,7 +174,7 @@ static const UCHAR SiS_HiTVGroup3_2[] = {
/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
-static const UCHAR SiS_Part2CLVX_1[] = {
+static const unsigned char SiS_Part2CLVX_1[] = {
0x00,0x00,
0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -155,7 +182,7 @@ static const UCHAR SiS_Part2CLVX_1[] = {
0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
};
-static const UCHAR SiS_Part2CLVX_2[] = {
+static const unsigned char SiS_Part2CLVX_2[] = {
0x00,0x00,
0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -163,7 +190,7 @@ static const UCHAR SiS_Part2CLVX_2[] = {
0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
};
-static const UCHAR SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
+static const unsigned char SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
0xE0,0x01,
0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
@@ -182,7 +209,7 @@ static const UCHAR SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_4[] = { /* PAL */
+static const unsigned char SiS_Part2CLVX_4[] = { /* PAL */
0x58,0x02,
0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -201,7 +228,7 @@ static const UCHAR SiS_Part2CLVX_4[] = { /* PAL */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_5[] = { /* 750p */
+static const unsigned char SiS_Part2CLVX_5[] = { /* 750p */
0x00,0x03,
0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -210,7 +237,7 @@ static const UCHAR SiS_Part2CLVX_5[] = { /* 750p */
0xFF,0xFF
};
-static const UCHAR SiS_Part2CLVX_6[] = { /* 1080i */
+static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
0x00,0x04,
0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
@@ -221,7 +248,7 @@ static const UCHAR SiS_Part2CLVX_6[] = { /* 1080i */
#ifdef SIS315H
/* 661 et al LCD data structure (2.03.00) */
-static const UCHAR SiS_LCDStruct661[] = {
+static const unsigned char SiS_LCDStruct661[] = {
/* 1024x768 */
/* type|CR37| HDE | VDE | HT | VT | hss | hse */
0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
@@ -249,11 +276,20 @@ static const UCHAR SiS_LCDStruct661[] = {
/* 1680x1050 */
0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+ /* 1280x800_3 */
+ 0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
+ 0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
+ /* 800x600 */
+ 0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
+ 0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
+ /* 1280x854 */
+ 0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
+ 0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
};
#endif
#ifdef SIS300
-static UCHAR SiS300_TrumpionData[7][80] = {
+static unsigned char SiS300_TrumpionData[14][80] = {
{ 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
@@ -288,119 +324,182 @@ static UCHAR SiS300_TrumpionData[7][80] = {
0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
- 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+ /* variant 2 */
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+ 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+ 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+ 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+ 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+ 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+ 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
};
#endif
-void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_EnableCRT2(SiS_Private *SiS_Pr);
-USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-BOOLEAN SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
- USHORT ModeIdIndex, PSIS_HW_INFO HwInfo,
- int checkcrt2mode);
-void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
-void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo);
-void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_LockCRT2(struct SiS_Private *SiS_Pr);
+#endif
+void SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
+unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+BOOLEAN SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+BOOLEAN SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int checkcrt2mode);
+void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex);
+unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
+void SiS_DisableBridge(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void SiS_EnableBridge(struct SiS_Private *SiS_Pr);
+#endif
+BOOLEAN SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
-void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
+void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#ifndef SIS_LINUX_KERNEL
+void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#endif
+void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char orval,unsigned short andval);
#ifdef SIS315H
-static void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
+static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
+static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
+void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
#endif /* 315 */
#ifdef SIS300
-#if 0
-static void SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-static USHORT SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-#endif
-static BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
+static BOOLEAN SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
#endif
-void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, UCHAR *buffer);
-#ifdef LINUX_XF86
-USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-#endif
+void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype,
+ unsigned char *buffer, unsigned int VBFlags2);
-static void SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-static USHORT SiS_SetStart(SiS_Private *SiS_Pr);
-static USHORT SiS_SetStop(SiS_Private *SiS_Pr);
-static USHORT SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-static USHORT SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-static USHORT SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT SiS_CheckACK(SiS_Private *SiS_Pr);
-static USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
-static USHORT SiS_WriteDABDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_PrepareDDC(SiS_Private *SiS_Pr);
-static void SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
-static USHORT SiS_DoProbeDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_ProbeDDC(SiS_Private *SiS_Pr);
-static USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, UCHAR *buffer);
+#ifdef SIS_XORG_XF86
+unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+ int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+ BOOLEAN checkcr32, unsigned int VBFlags2);
+unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+ unsigned char *buffer);
+#else
+static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+ int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+ BOOLEAN checkcr32, unsigned int VBFlags2);
+static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+ unsigned char *buffer);
+#endif
+static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
+static unsigned short SiS_CheckACK(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
+static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
+static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
+#ifdef SIS300
+static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
+static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
+#endif
#ifdef SIS315H
-static void SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
#endif
+
+extern void SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_SetRegByte(SISIOADDRESS, unsigned short);
+extern void SiS_SetRegShort(SISIOADDRESS, unsigned short);
+extern void SiS_SetRegLong(SISIOADDRESS, unsigned int);
+extern unsigned char SiS_GetReg(SISIOADDRESS, unsigned short);
+extern unsigned char SiS_GetRegByte(SISIOADDRESS);
+extern unsigned short SiS_GetRegShort(SISIOADDRESS);
+extern unsigned int SiS_GetRegLong(SISIOADDRESS);
+extern void SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
+extern void SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
+extern void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+extern void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+extern BOOLEAN SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+ unsigned short RefreshRateTableIndex);
+extern void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+extern unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+extern unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
#ifdef SIS300
-static void SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-static void SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
- USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+extern void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
+ unsigned short *tempcl);
+extern unsigned short SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
+extern unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+#ifdef SIS_LINUX_KERNEL
+extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
#endif
-
-extern void SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_SetRegByte(SISIOADDRESS, USHORT);
-extern void SiS_SetRegShort(SISIOADDRESS, USHORT);
-extern void SiS_SetRegLong(SISIOADDRESS, ULONG);
-extern UCHAR SiS_GetReg(SISIOADDRESS, USHORT);
-extern UCHAR SiS_GetRegByte(SISIOADDRESS);
-extern USHORT SiS_GetRegShort(SISIOADDRESS);
-extern ULONG SiS_GetRegLong(SISIOADDRESS);
-extern void SiS_SetRegANDOR(SISIOADDRESS, USHORT, USHORT, USHORT);
-extern void SiS_SetRegOR(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_SetRegAND(SISIOADDRESS, USHORT, USHORT);
-extern void SiS_DisplayOff(SiS_Private *SiS_Pr);
-extern void SiS_DisplayOn(SiS_Private *SiS_Pr);
-extern BOOLEAN SiS_SearchModeID(SiS_Private *, USHORT *, USHORT *);
-extern UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT SiS_GetOffset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO, USHORT ModeNo,
- USHORT ModeIdIndex);
-extern void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-#ifdef LINUX_XF86
-extern void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-extern int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct,
- int *maxx, int *maxy, int *prefx, int *prefy);
#endif
#endif
diff --git a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h
index 55a82d6dc4cf..264b55a5947b 100644
--- a/drivers/video/sis/initdef.h
+++ b/drivers/video/sis/initdef.h
@@ -3,7 +3,7 @@
/*
* Global definitions for init.c and init301.c
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -53,19 +53,20 @@
#ifndef _INITDEF_
#define _INITDEF_
-#define IS_SIS330 (HwInfo->jChipType == SIS_330)
-#define IS_SIS550 (HwInfo->jChipType == SIS_550)
-#define IS_SIS650 (HwInfo->jChipType == SIS_650) /* All versions, incl 651, M65x */
-#define IS_SIS740 (HwInfo->jChipType == SIS_740)
+#define IS_SIS330 (SiS_Pr->ChipType == SIS_330)
+#define IS_SIS550 (SiS_Pr->ChipType == SIS_550)
+#define IS_SIS650 (SiS_Pr->ChipType == SIS_650) /* All versions, incl 651, M65x */
+#define IS_SIS740 (SiS_Pr->ChipType == SIS_740)
#define IS_SIS651 (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
#define IS_SISM650 (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
#define IS_SIS65x (IS_SIS651 || IS_SISM650) /* Only special versions of 65x */
-#define IS_SIS661 (HwInfo->jChipType == SIS_661)
-#define IS_SIS741 (HwInfo->jChipType == SIS_741)
-#define IS_SIS660 (HwInfo->jChipType == SIS_660)
-#define IS_SIS760 (HwInfo->jChipType == SIS_760)
-#define IS_SIS661741660760 (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760)
-#define IS_SIS650740 ((HwInfo->jChipType >= SIS_650) && (HwInfo->jChipType < SIS_330))
+#define IS_SIS661 (SiS_Pr->ChipType == SIS_661)
+#define IS_SIS741 (SiS_Pr->ChipType == SIS_741)
+#define IS_SIS660 (SiS_Pr->ChipType == SIS_660)
+#define IS_SIS760 (SiS_Pr->ChipType == SIS_760)
+#define IS_SIS761 (SiS_Pr->ChipType == SIS_761)
+#define IS_SIS661741660760 (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760 || IS_SIS761)
+#define IS_SIS650740 ((SiS_Pr->ChipType >= SIS_650) && (SiS_Pr->ChipType < SIS_330))
#define IS_SIS550650740 (IS_SIS550 || IS_SIS650740)
#define IS_SIS650740660 (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
#define IS_SIS550650740660 (IS_SIS550 || IS_SIS650740660)
@@ -73,24 +74,37 @@
#define SISGETROMW(x) (ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
/* SiS_VBType */
-#define VB_SIS301 0x0001
-#define VB_SIS301B 0x0002
-#define VB_SIS302B 0x0004
-#define VB_SIS301LV 0x0008
-#define VB_SIS302LV 0x0010
+#define VB_SIS301 0x0001
+#define VB_SIS301B 0x0002
+#define VB_SIS302B 0x0004
+#define VB_SIS301LV 0x0008
+#define VB_SIS302LV 0x0010
#define VB_SIS302ELV 0x0020
-#define VB_SIS301C 0x0040
+#define VB_SIS301C 0x0040
+#define VB_SIS307T 0x0080
+#define VB_SIS307LV 0x0100
#define VB_UMC 0x4000
#define VB_NoLCD 0x8000
-#define VB_SIS301BLV302BLV (VB_SIS301B|VB_SIS301C|VB_SIS302B|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SIS301B302B (VB_SIS301B|VB_SIS301C|VB_SIS302B)
-#define VB_SIS301LV302LV (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISVB (VB_SIS301 | VB_SIS301BLV302BLV)
-#define VB_SISTMDS (VB_SIS301 | VB_SIS301B302B)
-#define VB_SISLVDS VB_SIS301LV302LV
-#define VB_SISLCDA (VB_SIS302B|VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISYPBPR (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISHIVISION (VB_SIS301|VB_SIS301B|VB_SIS302B)
+#define VB_SIS30xB (VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SIS30xC (VB_SIS301C | VB_SIS307T)
+#define VB_SISTMDS (VB_SIS301 | VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SISLVDS (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SIS30xBLV (VB_SIS30xB | VB_SISLVDS)
+#define VB_SIS30xCLV (VB_SIS30xC | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISVB (VB_SIS301 | VB_SIS30xBLV)
+#define VB_SISLCDA (VB_SIS302B | VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISTMDSLCDA (VB_SIS301C | VB_SIS307T)
+#define VB_SISPART4SCALER (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISHIVISION (VB_SIS301 | VB_SIS301B | VB_SIS302B)
+#define VB_SISYPBPR (VB_SIS301C | VB_SIS307T | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISTAP4SCALER (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPART4OVERFLOW (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPWD (VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISEMI (VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPOWER (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISDUALLINK (VB_SIS302LV | VB_SIS302ELV | VB_SIS307T | VB_SIS307LV)
+#define VB_SISVGA2 VB_SISTMDS
+#define VB_SISRAMDAC202 (VB_SIS301C | VB_SIS307T)
/* VBInfo */
#define SetSimuScanMode 0x0001 /* CR 30 */
@@ -160,6 +174,7 @@
#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
#define InterlaceMode 0x0080
#define SyncPP 0x0000
+#define HaveWideTiming 0x2000 /* Have specific wide- and non-wide timing */
#define SyncPN 0x4000
#define SyncNP 0x8000
#define SyncNN 0xc000
@@ -188,6 +203,7 @@
#define TVSetTVSimuMode 0x0200 /* new 0x200, prev. 0x800 */
#define TVRPLLDIV2XO 0x0400 /* prev 0x1000 */
#define TVSetNTSC1024 0x0800 /* new 0x100, prev. 0x2000 */
+#define TVSet525p1024 0x1000 /* TW */
#define TVAspect43 0x2000
#define TVAspect169 0x4000
#define TVAspect43LB 0x8000
@@ -208,7 +224,8 @@
#define SF_IsM661 0x0020
#define SF_IsM741 0x0040
#define SF_IsM760 0x0080
-#define SF_760LFB 0x8000 /* 760: We have LFB */
+#define SF_760UMA 0x4000 /* 76x: We have UMA */
+#define SF_760LFB 0x8000 /* 76x: We have LFB */
/* CR32 (Newer 630, and 315 series)
@@ -228,25 +245,19 @@
#define TVOverScanShift 4
/* CR35 (661 series only)
-
[0] 1 = PAL, 0 = NTSC
[1] 1 = NTSC-J (if D0 = 0)
[2] 1 = PALM (if D0 = 1)
[3] 1 = PALN (if D0 = 1)
[4] 1 = Overscan (Chrontel only)
[7:5] (only if D2 in CR38 is set)
- 000 525i
- 001 525p
+ 000 525i
+ 001 525p
010 750p
011 1080i (or HiVision on 301, 301B)
-
- These bits are being translated to TVMode flag.
-
*/
-/*
- CR37
-
+/* CR37
[0] Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS)
[3:1] External chip
300 series:
@@ -260,7 +271,7 @@
010 LVDS
011 LVDS + Chrontel 7019
660 series [2:1] only:
- reserved (now in CR38)
+ reserved (chip type now in CR38)
All other combinations reserved
[3] 661 only: Pass 1:1 data
[4] LVDS: 0: Panel Link expands / 1: Panel Link does not expand
@@ -320,6 +331,7 @@
#define Enable302LV_DualLink 0x04 /* 302LV only; enable dual link */
/* CR39 (661 and later)
+ D[7] LVDS (SiS or third party)
D[1:0] YPbPr Aspect Ratio
00 4:3 letterbox
01 4:3
@@ -341,7 +353,7 @@
0101 Set Contrast event
0110 Set Mute event
0111 Set Volume Up/Down event
- [4] Enable Backlight Control by BIOS/driver
+ [4] Enable Backlight Control by BIOS/driver
(set by driver; set means that the BIOS should
not touch the backlight registers because eg.
the driver already switched off the backlight)
@@ -350,6 +362,26 @@
[7] TV UnderScan/OverScan (set by BIOS)
*/
+/* CR7C - 661 and later
+ [7] DualEdge enabled (or: to be enabled)
+ [6] CRT2 = TV/LCD/VGA enabled (or: to be enabled)
+ [5] Init done (set at end of SiS_Init)
+ {4] LVDS LCD capabilities
+ [3] LVDS LCD capabilities
+ [2] LVDS LCD capabilities (PWD)
+ [1] LVDS LCD capabilities (PWD)
+ [0] LVDS=1, TMDS=0 (SiS or third party)
+*/
+
+/* CR7E - 661 and later
+ VBType:
+ [7] LVDS (third party)
+ [3] 301C
+ [2] 302LV
+ [1] 301LV
+ [0] 301B
+*/
+
/* LCDResInfo */
#define Panel300_800x600 0x01 /* CR36 */
#define Panel300_1024x768 0x02
@@ -359,7 +391,6 @@
#define Panel300_1024x600 0x06
#define Panel300_1152x768 0x07
#define Panel300_1280x768 0x0a
-#define Panel300_320x480 0x0e /* fstn - This is fake, can be any */
#define Panel300_Custom 0x0f
#define Panel300_Barco1366 0x10
@@ -374,9 +405,9 @@
#define Panel310_1400x1050 0x09
#define Panel310_1280x768 0x0a
#define Panel310_1600x1200 0x0b
-#define Panel310_640x480_2 0x0c
-#define Panel310_640x480_3 0x0d
-#define Panel310_320x480 0x0e /* fstn - TW: This is fake, can be any */
+#define Panel310_320x240_2 0x0c /* xSTN */
+#define Panel310_320x240_3 0x0d /* xSTN */
+#define Panel310_320x240_1 0x0e /* xSTN - This is fake, can be any */
#define Panel310_Custom 0x0f
#define Panel661_800x600 0x01
@@ -386,7 +417,7 @@
#define Panel661_1024x600 0x05
#define Panel661_1152x864 0x06
#define Panel661_1280x960 0x07
-#define Panel661_1152x768 0x08
+#define Panel661_1280x854 0x08
#define Panel661_1400x1050 0x09
#define Panel661_1280x768 0x0a
#define Panel661_1600x1200 0x0b
@@ -410,14 +441,16 @@
#define Panel_1680x1050 0x0d /* 661etc */
#define Panel_1280x720 0x0e /* 661etc */
#define Panel_Custom 0x0f /* MUST BE 0x0f (for DVI DDC detection) */
-#define Panel_320x480 0x10 /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_320x240_1 0x10 /* SiS 550 xSTN */
#define Panel_Barco1366 0x11
#define Panel_848x480 0x12
-#define Panel_640x480_2 0x13 /* SiS 550 */
-#define Panel_640x480_3 0x14 /* SiS 550 */
+#define Panel_320x240_2 0x13 /* SiS 550 xSTN */
+#define Panel_320x240_3 0x14 /* SiS 550 xSTN */
#define Panel_1280x768_2 0x15 /* 30xLV */
#define Panel_1280x768_3 0x16 /* (unused) */
#define Panel_1280x800_2 0x17 /* 30xLV */
+#define Panel_856x480 0x18
+#define Panel_1280x854 0x19 /* 661etc */
/* Index in ModeResInfo table */
#define SIS_RI_320x200 0
@@ -454,6 +487,7 @@
#define SIS_RI_1920x1080 31
#define SIS_RI_960x540 32
#define SIS_RI_960x600 33
+#define SIS_RI_1280x854 34
/* CR5F */
#define IsM650 0x80
@@ -482,16 +516,18 @@
#define VCLK100_300 0x43 /* Index in VCLKData table (300) */
#define VCLK34_300 0x3d /* Index in VCLKData table (300) */
#define VCLK_CUSTOM_300 0x47
-#define VCLK65_315 0x0b /* Index in (VB)VCLKData table (315) */
-#define VCLK108_2_315 0x19 /* Index in (VB)VCLKData table (315) */
-#define VCLK81_315 0x5b /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315 0x5e /* Index in (VB)VCLKData table (315) */
-#define VCLK108_3_315 0x45 /* Index in VBVCLKData table (315) */
-#define VCLK100_315 0x46 /* Index in VBVCLKData table (315) */
+
+#define VCLK65_315 0x0b /* Indices in (VB)VCLKData table (315) */
+#define VCLK108_2_315 0x19
+#define VCLK81_315 0x5b
+#define VCLK162_315 0x5e
+#define VCLK108_3_315 0x45
+#define VCLK100_315 0x46
#define VCLK34_315 0x55
#define VCLK68_315 0x0d
-#define VCLK_1280x800_315_2 0x5c /* Index in VBVCLKData table (315) */
-#define VCLK121_315 0x5d /* Index in VBVCLKData table (315) */
+#define VCLK_1280x800_315_2 0x5c
+#define VCLK121_315 0x5d
+#define VCLK130_315 0x72
#define VCLK_1280x720 0x5f
#define VCLK_1280x768_2 0x60
#define VCLK_1280x768_3 0x61 /* (unused?) */
@@ -507,6 +543,7 @@
#define VCLK_1152x864 0x64
#define VCLK_1360x768 0x58
#define VCLK_1280x800_315 0x6c
+#define VCLK_1280x854 0x76
#define TVCLKBASE_300 0x21 /* Indices on TV clocks in VCLKData table (300) */
#define TVCLKBASE_315 0x3a /* Indices on TV clocks in (VB)VCLKData table (315) */
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
new file mode 100644
index 000000000000..cc856d90903c
--- /dev/null
+++ b/drivers/video/sis/initextlfb.c
@@ -0,0 +1,238 @@
+/*
+ * SiS 300/540/630[S]/730[S]
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * Linux kernel specific extensions to init.c/init301.c
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * 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 named 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
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ */
+
+#include "osdef.h"
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+ unsigned char modeno, unsigned char rateindex);
+int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ int *htotal, int *vtotal, unsigned char rateindex);
+
+extern BOOLEAN SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex);
+extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+ int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int
+sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, ClockIndex = 0;
+ unsigned short RRTI = 0;
+ int Clock;
+
+ if(!SiSInitPtr(SiS_Pr)) return 65000;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
+ printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+ return 65000;
+ }
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
+ } else {
+ RRTI += rateindex;
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
+ }
+
+ Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
+
+ return Clock;
+}
+
+int
+sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
+ int j;
+
+ if(!SiSInitPtr(SiS_Pr)) return 0;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+ } else {
+ RRTI += rateindex;
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+ }
+
+ SiS_Generic_ConvertCRData(SiS_Pr,
+ (unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
+ SiS_Pr->SiS_RefIndex[RRTI].XRes,
+ SiS_Pr->SiS_RefIndex[RRTI].YRes,
+ var, FALSE);
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
+ var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
+ var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+ var->vmode = FB_VMODE_NONINTERLACED;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
+ var->vmode = FB_VMODE_INTERLACED;
+ else {
+ j = 0;
+ while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+ if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
+ SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
+ if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+ var->vmode = FB_VMODE_DOUBLE;
+ }
+ break;
+ }
+ j++;
+ }
+ }
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+#if 0 /* Do this? */
+ var->upper_margin <<= 1;
+ var->lower_margin <<= 1;
+ var->vsync_len <<= 1;
+#endif
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->upper_margin >>= 1;
+ var->lower_margin >>= 1;
+ var->vsync_len >>= 1;
+ }
+
+ return 1;
+}
+#endif /* Linux >= 2.5 */
+
+BOOLEAN
+sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
+ int *vtotal, unsigned char rateindex)
+{
+ unsigned short ModeNo = modeno;
+ unsigned short ModeIdIndex = 0, CRT1Index = 0;
+ unsigned short RRTI = 0;
+ unsigned char sr_data, cr_data, cr_data2;
+
+ if(!SiSInitPtr(SiS_Pr)) return FALSE;
+
+ if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+ switch(ModeNo) {
+ case 0x5a: ModeNo = 0x50; break;
+ case 0x5b: ModeNo = 0x56;
+ }
+#endif
+
+ if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+
+ RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+ if(SiS_Pr->SiS_UseWide == 1) {
+ /* Wide screen: Ignore rateindex */
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+ } else {
+ RRTI += rateindex;
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+ }
+ } else {
+ RRTI += rateindex;
+ CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+ }
+
+ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
+ *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
+
+ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
+ cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+ *vtotal = ((cr_data & 0xFF) |
+ ((unsigned short)(cr_data2 & 0x01) << 8) |
+ ((unsigned short)(cr_data2 & 0x20) << 4) |
+ ((unsigned short)(sr_data & 0x01) << 10)) + 2;
+
+ if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
+ *vtotal *= 2;
+
+ return TRUE;
+}
+
+
+
diff --git a/drivers/video/sis/oem300.h b/drivers/video/sis/oem300.h
index b1358b750f53..b73f26840143 100644
--- a/drivers/video/sis/oem300.h
+++ b/drivers/video/sis/oem300.h
@@ -3,7 +3,7 @@
/*
* OEM Data for 300 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,7 +50,7 @@
*
*/
-static const UCHAR SiS300_OEMTVDelay301[8][4] =
+static const unsigned char SiS300_OEMTVDelay301[8][4] =
{
{0x08,0x08,0x08,0x08},
{0x08,0x08,0x08,0x08},
@@ -62,7 +62,7 @@ static const UCHAR SiS300_OEMTVDelay301[8][4] =
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
+static const unsigned char SiS300_OEMTVDelayLVDS[8][4] =
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -74,7 +74,7 @@ static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_OEMTVFlicker[8][4] =
+static const unsigned char SiS300_OEMTVFlicker[8][4] =
{
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
@@ -86,25 +86,7 @@ static const UCHAR SiS300_OEMTVFlicker[8][4] =
{0x00,0x00,0x00,0x00}
};
-#if 0 /* TW: Not used */
-static const UCHAR SiS300_OEMLCDDelay1[12][4]={
- {0x2c,0x2c,0x2c,0x2c},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x2c,0x2c,0x2c,0x2c},
- {0x2c,0x2c,0x2c,0x2c},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x24,0x24,0x24,0x24},
- {0x24,0x24,0x24,0x24},
- {0x20,0x20,0x20,0x20},
- {0x20,0x20,0x20,0x20},
- {0x24,0x24,0x24,0x24}
-};
-#endif
-
-/* From 630/301B BIOS */
-static const UCHAR SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302LV */
+static const unsigned char SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302LV */
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -172,8 +154,7 @@ static const UCHAR SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302
{0x20,0x20,0x20,0x20}
};
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay4[12][4] =
+static const unsigned char SiS300_OEMLCDDelay4[12][4] =
{
{0x2c,0x2c,0x2c,0x2c},
{0x20,0x20,0x20,0x20},
@@ -189,8 +170,7 @@ static const UCHAR SiS300_OEMLCDDelay4[12][4] =
{0x24,0x24,0x24,0x24}
};
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay5[32][4] =
+static const unsigned char SiS300_OEMLCDDelay5[32][4] =
{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -226,8 +206,8 @@ static const UCHAR SiS300_OEMLCDDelay5[32][4] =
{0x20,0x20,0x20,0x20},
};
-/* Added for LVDS */
-static const UCHAR SiS300_OEMLCDDelay3[64][4] = { /* For LVDS */
+static const unsigned char SiS300_OEMLCDDelay3[64][4] = /* For LVDS */
+{
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
{0x20,0x20,0x20,0x20},
@@ -294,7 +274,7 @@ static const UCHAR SiS300_OEMLCDDelay3[64][4] = { /* For LVDS */
{0x20,0x20,0x20,0x20}
};
-static const UCHAR SiS300_Phase1[8][5][4] =
+static const unsigned char SiS300_Phase1[8][5][4] =
{
{
{0x21,0xed,0x00,0x08},
@@ -354,11 +334,10 @@ static const UCHAR SiS300_Phase1[8][5][4] =
}
};
-
-static const UCHAR SiS300_Phase2[8][5][4] =
+static const unsigned char SiS300_Phase2[8][5][4] =
{
{
- {0x21,0xed,0x00,0x08},
+ {0x21,0xed,0x00,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
@@ -372,42 +351,42 @@ static const UCHAR SiS300_Phase2[8][5][4] =
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x21,0xed,0x00,0x08},
+ {0x21,0xed,0x00,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08},
{0x21,0xed,0x8a,0x08}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
},
{
- {0x2a,0x05,0xd3,0x00},
+ {0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00},
@@ -415,7 +394,7 @@ static const UCHAR SiS300_Phase2[8][5][4] =
}
};
-static const UCHAR SiS300_Filter1[10][16][4] =
+static const unsigned char SiS300_Filter1[10][16][4] =
{
{
{0x00,0xf4,0x10,0x38},
@@ -599,7 +578,7 @@ static const UCHAR SiS300_Filter1[10][16][4] =
},
};
-static const UCHAR SiS300_Filter2[10][9][7] =
+static const unsigned char SiS300_Filter2[10][9][7] =
{
{
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -714,142 +693,144 @@ static const UCHAR SiS300_Filter2[10][9][7] =
};
/* Custom data for Barco iQ Pro R300 */
-static const UCHAR barco_p1[2][9][7][3] = {
- {
- { { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x1e, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x16, 0x00 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x1e, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x11, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x26, 0x00 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x30, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0x00, 0x00 },
- { 0x17, 0xa0, 0x00 },
- { 0x1a, 0xa0, 0x00 },
- { 0x1b, 0x2a, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0x16, 0x00, 0x00 },
- { 0x17, 0xaa, 0x00 },
- { 0x1a, 0xa0, 0x00 },
- { 0x1b, 0x2a, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0, 0, 0 }
- }
- },
- {
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x19, 0x00 },
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0x16, 0xcf, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe7, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x1e, 0x00 }
- },
- {
- { 0x16, 0xd1, 0x00 },
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe6, 0x00 },
- { 0x1b, 0x11, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x26, 0x00 }
- },
- {
- { 0x18, 0x00, 0x00 },
- { 0x1a, 0xe0, 0x00 },
- { 0x1b, 0x26, 0x00 },
- { 0x1c, 0xff, 0x00 },
- { 0x1d, 0x1c, 0x00 },
- { 0x1e, 0x30, 0x00 },
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- },
- {
- { 0, 0, 0 }
- }
- }
+static const unsigned char barco_p1[2][9][7][3] =
+{
+ {
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x1e, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x16, 0x00 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x1e, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x11, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x26, 0x00 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x30, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0x00, 0x00 },
+ { 0x17, 0xa0, 0x00 },
+ { 0x1a, 0xa0, 0x00 },
+ { 0x1b, 0x2a, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0x00, 0x00 },
+ { 0x17, 0xaa, 0x00 },
+ { 0x1a, 0xa0, 0x00 },
+ { 0x1b, 0x2a, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0, 0, 0 }
+ }
+ },
+ {
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x19, 0x00 },
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0x16, 0xcf, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe7, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x1e, 0x00 }
+ },
+ {
+ { 0x16, 0xd1, 0x00 },
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe6, 0x00 },
+ { 0x1b, 0x11, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x26, 0x00 }
+ },
+ {
+ { 0x18, 0x00, 0x00 },
+ { 0x1a, 0xe0, 0x00 },
+ { 0x1b, 0x26, 0x00 },
+ { 0x1c, 0xff, 0x00 },
+ { 0x1d, 0x1c, 0x00 },
+ { 0x1e, 0x30, 0x00 },
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ },
+ {
+ { 0, 0, 0 }
+ }
+ }
};
diff --git a/drivers/video/sis/oem310.h b/drivers/video/sis/oem310.h
index 2b7db916b7e7..8fce56e4482c 100644
--- a/drivers/video/sis/oem310.h
+++ b/drivers/video/sis/oem310.h
@@ -1,9 +1,9 @@
/* $XFree86$ */
/* $XdotOrg$ */
/*
- * OEM Data for 315/330 series
+ * OEM Data for 315/330/340 series
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,206 +50,206 @@
*
*/
-static const UCHAR SiS310_LCDDelayCompensation_301[] = /* 301 */
+static const unsigned char SiS310_LCDDelayCompensation_301[] = /* 301 */
{
- 0x00,0x00,0x00, /* 800x600 */
- 0x0b,0x0b,0x0b, /* 1024x768 */
- 0x08,0x08,0x08, /* 1280x1024 */
- 0x00,0x00,0x00, /* 640x480 (unknown) */
- 0x00,0x00,0x00, /* 1024x600 (unknown) */
- 0x00,0x00,0x00, /* 1152x864 (unknown) */
- 0x08,0x08,0x08, /* 1280x960 (guessed) */
- 0x00,0x00,0x00, /* 1152x768 (unknown) */
- 0x08,0x08,0x08, /* 1400x1050 */
- 0x08,0x08,0x08, /* 1280x768 (guessed) */
- 0x00,0x00,0x00, /* 1600x1200 */
- 0x00,0x00,0x00, /* 320x480 (unknown) */
- 0x00,0x00,0x00,
- 0x00,0x00,0x00,
- 0x00,0x00,0x00
+ 0x00,0x00,0x00, /* 800x600 */
+ 0x0b,0x0b,0x0b, /* 1024x768 */
+ 0x08,0x08,0x08, /* 1280x1024 */
+ 0x00,0x00,0x00, /* 640x480 (unknown) */
+ 0x00,0x00,0x00, /* 1024x600 (unknown) */
+ 0x00,0x00,0x00, /* 1152x864 (unknown) */
+ 0x08,0x08,0x08, /* 1280x960 (guessed) */
+ 0x00,0x00,0x00, /* 1152x768 (unknown) */
+ 0x08,0x08,0x08, /* 1400x1050 */
+ 0x08,0x08,0x08, /* 1280x768 (guessed) */
+ 0x00,0x00,0x00, /* 1600x1200 */
+ 0x00,0x00,0x00, /* 320x480 (unknown) */
+ 0x00,0x00,0x00,
+ 0x00,0x00,0x00,
+ 0x00,0x00,0x00
};
/* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const UCHAR SiS310_LCDDelayCompensation_650301LV[] = /* 650 + 30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_650301LV[] = /* 650 + 30xLV */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x01,0x01,0x01, /* 1024x768 */
- 0x01,0x01,0x01, /* 1280x1024 */
- 0x01,0x01,0x01, /* 640x480 (unknown) */
- 0x01,0x01,0x01, /* 1024x600 (unknown) */
- 0x01,0x01,0x01, /* 1152x864 (unknown) */
- 0x01,0x01,0x01, /* 1280x960 (guessed) */
- 0x01,0x01,0x01, /* 1152x768 (unknown) */
- 0x01,0x01,0x01, /* 1400x1050 */
- 0x01,0x01,0x01, /* 1280x768 (guessed) */
- 0x01,0x01,0x01, /* 1600x1200 */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x01,0x01,0x01, /* 1024x768 */
+ 0x01,0x01,0x01, /* 1280x1024 */
+ 0x01,0x01,0x01, /* 640x480 (unknown) */
+ 0x01,0x01,0x01, /* 1024x600 (unknown) */
+ 0x01,0x01,0x01, /* 1152x864 (unknown) */
+ 0x01,0x01,0x01, /* 1280x960 (guessed) */
+ 0x01,0x01,0x01, /* 1152x768 (unknown) */
+ 0x01,0x01,0x01, /* 1400x1050 */
+ 0x01,0x01,0x01, /* 1280x768 (guessed) */
+ 0x01,0x01,0x01, /* 1600x1200 */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */
+static const unsigned char SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */
{
- 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */
- 0x33,0x33,0x33, /* 1024x768 */
- 0x33,0x33,0x33, /* 1280x1024 */
- 0x33,0x33,0x33, /* 640x480 (unknown) */
- 0x33,0x33,0x33, /* 1024x600 (unknown) */
- 0x33,0x33,0x33, /* 1152x864 (unknown) */
- 0x33,0x33,0x33, /* 1280x960 (guessed) */
- 0x33,0x33,0x33, /* 1152x768 (unknown) */
- 0x33,0x33,0x33, /* 1400x1050 */
- 0x33,0x33,0x33, /* 1280x768 (guessed) */
- 0x33,0x33,0x33, /* 1600x1200 */
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33
+ 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */
+ 0x33,0x33,0x33, /* 1024x768 */
+ 0x33,0x33,0x33, /* 1280x1024 */
+ 0x33,0x33,0x33, /* 640x480 (unknown) */
+ 0x33,0x33,0x33, /* 1024x600 (unknown) */
+ 0x33,0x33,0x33, /* 1152x864 (unknown) */
+ 0x33,0x33,0x33, /* 1280x960 (guessed) */
+ 0x33,0x33,0x33, /* 1152x768 (unknown) */
+ 0x33,0x33,0x33, /* 1400x1050 */
+ 0x33,0x33,0x33, /* 1280x768 (guessed) */
+ 0x33,0x33,0x33, /* 1600x1200 */
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33
};
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] = /* M650/651 302LV */
+static const unsigned char SiS310_LCDDelayCompensation_651302LV[] = /* M650/651 302LV */
{
- 0x33,0x33,0x33, /* 800x600 (guessed) */
- 0x33,0x33,0x33, /* 1024x768 */
- 0x33,0x33,0x33, /* 1280x1024 */
- 0x33,0x33,0x33, /* 640x480 (unknown) */
- 0x33,0x33,0x33, /* 1024x600 (unknown) */
- 0x33,0x33,0x33, /* 1152x864 (unknown) */
- 0x33,0x33,0x33, /* 1280x960 (guessed) */
- 0x33,0x33,0x33, /* 1152x768 (unknown) */
- 0x33,0x33,0x33, /* 1400x1050 */
- 0x33,0x33,0x33, /* 1280x768 (guessed) */
- 0x33,0x33,0x33, /* 1600x1200 */
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33,
- 0x33,0x33,0x33
+ 0x33,0x33,0x33, /* 800x600 (guessed) */
+ 0x33,0x33,0x33, /* 1024x768 */
+ 0x33,0x33,0x33, /* 1280x1024 */
+ 0x33,0x33,0x33, /* 640x480 (unknown) */
+ 0x33,0x33,0x33, /* 1024x600 (unknown) */
+ 0x33,0x33,0x33, /* 1152x864 (unknown) */
+ 0x33,0x33,0x33, /* 1280x960 (guessed) */
+ 0x33,0x33,0x33, /* 1152x768 (unknown) */
+ 0x33,0x33,0x33, /* 1400x1050 */
+ 0x33,0x33,0x33, /* 1280x768 (guessed) */
+ 0x33,0x33,0x33, /* 1600x1200 */
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33,
+ 0x33,0x33,0x33
};
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] = /* 30xB */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301B[] = /* 30xB */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x0C,0x0C,0x0C, /* 1024x768 */
- 0x0C,0x0C,0x0C, /* 1280x1024 */
- 0x08,0x08,0x08, /* 640x480 */
- 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x0C,0x0C,0x0C, /* 1024x768 */
+ 0x0C,0x0C,0x0C, /* 1280x1024 */
+ 0x08,0x08,0x08, /* 640x480 */
+ 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] = /* 315+30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301LV[] = /* 315+30xLV */
{
- 0x01,0x01,0x01, /* 800x600 */
- 0x04,0x04,0x04, /* 1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
- 0x0C,0x0C,0x0C, /* 1280x1024 */
- 0x08,0x08,0x08, /* 640x480 */
- 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
- 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
- 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
- 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02,
- 0x02,0x02,0x02
+ 0x01,0x01,0x01, /* 800x600 */
+ 0x04,0x04,0x04, /* 1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+ 0x0C,0x0C,0x0C, /* 1280x1024 */
+ 0x08,0x08,0x08, /* 640x480 */
+ 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */
+ 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02,
+ 0x02,0x02,0x02
};
-static const UCHAR SiS310_TVDelayCompensation_301[] = /* 301 */
+static const unsigned char SiS310_TVDelayCompensation_301[] = /* 301 */
{
- 0x02,0x02, /* NTSC Enhanced, Standard */
- 0x02,0x02, /* PAL */
- 0x08,0x0b /* HiVision */
+ 0x02,0x02, /* NTSC Enhanced, Standard */
+ 0x02,0x02, /* PAL */
+ 0x08,0x0b /* HiVision */
};
-static const UCHAR SiS310_TVDelayCompensation_301B[] = /* 30xB, 30xLV */
+static const unsigned char SiS310_TVDelayCompensation_301B[] = /* 30xB, 30xLV */
{
- 0x03,0x03,
- 0x03,0x03,
- 0x03,0x03
+ 0x03,0x03,
+ 0x03,0x03,
+ 0x03,0x03
};
-static const UCHAR SiS310_TVDelayCompensation_740301B[] = /* 740 + 30xB (30xLV?) */
+static const unsigned char SiS310_TVDelayCompensation_740301B[] = /* 740 + 30xB (30xLV?) */
{
- 0x05,0x05,
- 0x05,0x05,
- 0x05,0x05
+ 0x05,0x05,
+ 0x05,0x05,
+ 0x05,0x05
};
-static const UCHAR SiS310_TVDelayCompensation_651301LV[] = /* M650, 651, 301LV */
+static const unsigned char SiS310_TVDelayCompensation_651301LV[] = /* M650, 651, 301LV */
{
- 0x33,0x33,
- 0x33,0x33,
- 0x33,0x33
+ 0x33,0x33,
+ 0x33,0x33,
+ 0x33,0x33
};
-static const UCHAR SiS310_TVDelayCompensation_651302LV[] = /* M650, 651, 302LV */
+static const unsigned char SiS310_TVDelayCompensation_651302LV[] = /* M650, 651, 302LV */
{
- 0x33,0x33,
- 0x33,0x33,
- 0x33,0x33
+ 0x33,0x33,
+ 0x33,0x33,
+ 0x33,0x33
};
-static const UCHAR SiS_TVDelay661_301[] = /* 661, 301 */
+static const unsigned char SiS_TVDelay661_301[] = /* 661, 301 */
{
- 0x44,0x44,
- 0x44,0x44,
- 0x00,0x00,
- 0x44,0x44,
- 0x44,0x44,
- 0x44,0x44
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x00,0x00,
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x44,0x44
};
-static const UCHAR SiS_TVDelay661_301B[] = /* 661, 301B et al */
+static const unsigned char SiS_TVDelay661_301B[] = /* 661, 301B et al */
{
- 0x44,0x44,
- 0x44,0x44,
- 0x00,0x00,
- 0x44,0x44,
- 0x44,0x44,
- 0x44,0x44
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x00,0x00,
+ 0x44,0x44,
+ 0x44,0x44,
+ 0x44,0x44
};
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] = /* LVDS */
+static const unsigned char SiS310_TVDelayCompensation_LVDS[] = /* LVDS */
{
- 0x0a,0x0a,
- 0x0a,0x0a,
- 0x0a,0x0a
+ 0x0a,0x0a,
+ 0x0a,0x0a,
+ 0x0a,0x0a
};
-static const UCHAR SiS310_TVAntiFlick1[6][2] =
+static const unsigned char SiS310_TVAntiFlick1[6][2] =
{
- {0x4,0x0},
- {0x4,0x8},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0}
+ {0x4,0x0},
+ {0x4,0x8},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0}
};
-static const UCHAR SiS310_TVEdge1[6][2] =
+static const unsigned char SiS310_TVEdge1[6][2] =
{
- {0x0,0x4},
- {0x0,0x4},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0},
- {0x0,0x0}
+ {0x0,0x4},
+ {0x0,0x4},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0},
+ {0x0,0x0}
};
-static const UCHAR SiS310_TVYFilter1[5][8][4] =
+static const unsigned char SiS310_TVYFilter1[5][8][4] =
{
- {
+ {
{0x00,0xf4,0x10,0x38}, /* NTSC */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x25,0x18},
@@ -258,8 +258,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xee,0x0c,0x22,0x08},
{0xeb,0x15,0x25,0xf6}
- },
- {
+ },
+ {
{0x00,0xf4,0x10,0x38}, /* PAL */
{0x00,0xf4,0x10,0x38},
{0xf1,0xf7,0x1f,0x32},
@@ -268,8 +268,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xf1,0xf7,0x1f,0x32},
{0xf3,0x00,0x1d,0x20},
{0xfc,0xfb,0x14,0x2a}
- },
- {
+ },
+ {
{0x00,0x00,0x00,0x00}, /* HiVision */
{0x00,0xf4,0x10,0x38},
{0x00,0xf4,0x10,0x38},
@@ -278,9 +278,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x25,0x18},
{0xee,0x0c,0x22,0x08}
- },
- {
- {0x00,0xf4,0x10,0x38}, /* PAL-M */
+ },
+ {
+ {0x00,0xf4,0x10,0x38}, /* PAL-M */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x10,0x18},
{0xf7,0x06,0x19,0x14},
@@ -288,9 +288,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xeb,0x04,0x25,0x18},
{0xeb,0x15,0x25,0xf6}
- },
- {
- {0x00,0xf4,0x10,0x38}, /* PAL-N */
+ },
+ {
+ {0x00,0xf4,0x10,0x38}, /* PAL-N */
{0x00,0xf4,0x10,0x38},
{0xeb,0x04,0x10,0x18},
{0xf7,0x06,0x19,0x14},
@@ -298,12 +298,12 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
{0xeb,0x04,0x25,0x18},
{0xeb,0x04,0x25,0x18},
{0xeb,0x15,0x25,0xf6}
- }
+ }
};
-static const UCHAR SiS310_TVYFilter2[5][9][7] =
+static const unsigned char SiS310_TVYFilter2[5][9][7] =
{
- {
+ {
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* NTSC */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -313,8 +313,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
+ },
+ {
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -324,8 +324,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
+ },
+ {
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, /* HiVision */
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
@@ -335,9 +335,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}
- },
- {
- {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-M */
+ },
+ {
+ {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-M */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -346,9 +346,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
- {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-N */
+ },
+ {
+ {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-N */
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -357,58 +357,39 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- }
+ }
};
-static const UCHAR SiS310_TVPhaseIncr1[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr1[3][2][4] =
{
- {
+ {
{0x21,0xed,0xba,0x08},
{0x21,0xed,0xba,0x08}
- },
- {
+ },
+ {
{0x2a,0x05,0xe3,0x00},
{0x2a,0x05,0xe3,0x00}
- },
- {
+ },
+ {
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
- }
+ }
};
-static const UCHAR SiS310_TVPhaseIncr2[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr2[3][2][4] =
{
- {
+ {
{0x21,0xf0,0x7b,0xd6},
{0x21,0xf0,0x7b,0xd6}
- },
- {
+ },
+ {
{0x2a,0x0a,0x41,0xe9},
{0x2a,0x0a,0x41,0xe9}
- },
- {
+ },
+ {
{0x2a,0x05,0xd3,0x00},
{0x2a,0x05,0xd3,0x00}
- }
-};
-
-static const UCHAR SiS661_TVPhase[] = {
- 0x21,0xED,0xBA,0x08,
- 0x2A,0x05,0xE3,0x00,
- 0x21,0xE4,0x2E,0x9B,
- 0x21,0xF4,0x3E,0xBA,
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x21,0xF0,0x7B,0xD6,
- 0x2A,0x09,0x86,0xE9,
- 0x21,0xE6,0xEF,0xA4,
- 0x21,0xF6,0x94,0x46,
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00
+ }
};
/**************************************************************/
@@ -417,7 +398,7 @@ static const UCHAR SiS661_TVPhase[] = {
/* Inventec / Compaq Presario 3045US, 3017 */
-static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtCompaq1280x1024Data[] =
{
{ 211, 60,1024, 501,1688,1066},
{ 211, 60,1024, 508,1688,1066},
@@ -431,17 +412,17 @@ static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] =
/* Asus A2xxxH _2 */
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_Asus1024x768_3[] =
{
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
};
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
index 15939b057713..841ca3190cd4 100644
--- a/drivers/video/sis/osdef.h
+++ b/drivers/video/sis/osdef.h
@@ -3,7 +3,7 @@
/*
* OS depending defines
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -55,8 +55,11 @@
#define _SIS_OSDEF_H_
/* The choices are: */
-#define LINUX_KERNEL /* Linux kernel framebuffer */
-/* #define LINUX_XF86 */ /* XFree86/X.org */
+#define SIS_LINUX_KERNEL /* Linux kernel framebuffer */
+#undef SIS_XORG_XF86 /* XFree86/X.org */
+
+#undef SIS_LINUX_KERNEL_24
+#undef SIS_LINUX_KERNEL_26
#ifdef OutPortByte
#undef OutPortByte
@@ -86,8 +89,9 @@
/* LINUX KERNEL */
/**********************************************************************/
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
#include <linux/config.h>
+#include <linux/version.h>
#ifdef CONFIG_FB_SIS_300
#define SIS300
@@ -97,6 +101,12 @@
#define SIS315H
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define SIS_LINUX_KERNEL_26
+#else
+#define SIS_LINUX_KERNEL_24
+#endif
+
#if !defined(SIS300) && !defined(SIS315H)
#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
#warning sisfb will not work!
@@ -109,13 +119,15 @@
#define InPortWord(p) inw((SISIOADDRESS)(p))
#define InPortLong(p) inl((SISIOADDRESS)(p))
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* LINUX_KERNEL */
/**********************************************************************/
/* XFree86/X.org */
/**********************************************************************/
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
+
#define SIS300
#define SIS315H
@@ -126,6 +138,7 @@
#define InPortWord(p) inSISREGW((IOADDRESS)(p))
#define InPortLong(p) inSISREGL((IOADDRESS)(p))
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* XF86 */
#endif /* _OSDEF_H_ */
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d0103c162e43..0b6e625d7331 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -1,8 +1,10 @@
/*
- * SiS 300/630/730/540/315/550/[M]650/651/[M]661[FM]X/740/[M]741[GX]/330/[M]760[GX]
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]661[F|M]X/740/[M]741[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* 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
@@ -19,8 +21,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
-#ifndef _SIS_H
-#define _SIS_H
+#ifndef _SIS_H_
+#define _SIS_H_
#include <linux/config.h>
#include <linux/version.h>
@@ -35,26 +37,37 @@
#include "vgatypes.h"
#include "vstruct.h"
-#define VER_MAJOR 1
-#define VER_MINOR 7
-#define VER_LEVEL 17
-
-#undef SIS_CONFIG_COMPAT
+#define VER_MAJOR 1
+#define VER_MINOR 8
+#define VER_LEVEL 9
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#include <linux/spinlock.h>
+#define SIS_PCI_GET_CLASS(a, b) pci_get_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_get_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_get_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a) pci_dev_put(a)
#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
#include <linux/ioctl32.h>
-#define SIS_CONFIG_COMPAT
-#endif
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
-#ifdef __x86_64__
-/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#define SIS_OLD_CONFIG_COMPAT
+#else
+#include <linux/smp_lock.h>
+#define SIS_NEW_CONFIG_COMPAT
+#endif
+#endif /* CONFIG_COMPAT */
+#else /* 2.4 */
+#define SIS_PCI_GET_CLASS(a, b) pci_find_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_find_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_find_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__ /* Shouldn't we check for CONFIG_IA32_EMULATION here? */
#include <asm/ioctl32.h>
-#define SIS_CONFIG_COMPAT
+#define SIS_OLD_CONFIG_COMPAT
#endif
#endif
-
+#endif /* 2.4 */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
#define SIS_IOTYPE1 void __iomem
#define SIS_IOTYPE2 __iomem
@@ -79,228 +92,312 @@
/* To be included in pci_ids.h */
#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA 0x6325
+#define PCI_DEVICE_ID_SI_650_VGA 0x6325
#endif
#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650 0x0650
+#define PCI_DEVICE_ID_SI_650 0x0650
#endif
#ifndef PCI_DEVICE_ID_SI_651
-#define PCI_DEVICE_ID_SI_651 0x0651
+#define PCI_DEVICE_ID_SI_651 0x0651
#endif
#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740 0x0740
+#define PCI_DEVICE_ID_SI_740 0x0740
#endif
#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330 0x0330
+#define PCI_DEVICE_ID_SI_330 0x0330
#endif
#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA 0x6330
+#define PCI_DEVICE_ID_SI_660_VGA 0x6330
#endif
#ifndef PCI_DEVICE_ID_SI_661
-#define PCI_DEVICE_ID_SI_661 0x0661
+#define PCI_DEVICE_ID_SI_661 0x0661
#endif
#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741 0x0741
+#define PCI_DEVICE_ID_SI_741 0x0741
#endif
#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660 0x0660
+#define PCI_DEVICE_ID_SI_660 0x0660
#endif
#ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760 0x0760
+#define PCI_DEVICE_ID_SI_760 0x0760
+#endif
+#ifndef PCI_DEVICE_ID_SI_761
+#define PCI_DEVICE_ID_SI_761 0x0761
+#endif
+
+#ifndef PCI_VENDOR_ID_XGI
+#define PCI_VENDOR_ID_XGI 0x18ca
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_20
+#define PCI_DEVICE_ID_XGI_20 0x0020
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_40
+#define PCI_DEVICE_ID_XGI_40 0x0040
#endif
/* To be included in fb.h */
#ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 65x, 740, 661, 741 */
+#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 65x, 740, 661, 741 */
#endif
#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre"), 760 */
+#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre"), 76x */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_V
+#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari Vx (V3XT, V5, V8) */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_Z
+#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
#endif
-
-#define MAX_ROM_SCAN 0x10000
/* ivideo->caps */
-#define HW_CURSOR_CAP 0x80
-#define TURBO_QUEUE_CAP 0x40
-#define AGP_CMD_QUEUE_CAP 0x20
-#define VM_CMD_QUEUE_CAP 0x10
-#define MMIO_CMD_QUEUE_CAP 0x08
+#define HW_CURSOR_CAP 0x80
+#define TURBO_QUEUE_CAP 0x40
+#define AGP_CMD_QUEUE_CAP 0x20
+#define VM_CMD_QUEUE_CAP 0x10
+#define MMIO_CMD_QUEUE_CAP 0x08
/* For 300 series */
-#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */
+#define TURBO_QUEUE_AREA_SIZE (512 * 1024) /* 512K */
+#define HW_CURSOR_AREA_SIZE_300 4096 /* 4K */
/* For 315/Xabre series */
-#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD 0x1F
-#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */
-
-#define SIS_OH_ALLOC_SIZE 4000
-#define SENTINEL 0x7fffffff
-
-#define SEQ_ADR 0x14
-#define SEQ_DATA 0x15
-#define DAC_ADR 0x18
-#define DAC_DATA 0x19
-#define CRTC_ADR 0x24
-#define CRTC_DATA 0x25
-#define DAC2_ADR (0x16-0x30)
-#define DAC2_DATA (0x17-0x30)
-#define VB_PART1_ADR (0x04-0x30)
-#define VB_PART1_DATA (0x05-0x30)
-#define VB_PART2_ADR (0x10-0x30)
-#define VB_PART2_DATA (0x11-0x30)
-#define VB_PART3_ADR (0x12-0x30)
-#define VB_PART3_DATA (0x13-0x30)
-#define VB_PART4_ADR (0x14-0x30)
-#define VB_PART4_DATA (0x15-0x30)
-
-#define SISSR ivideo->SiS_Pr.SiS_P3c4
-#define SISCR ivideo->SiS_Pr.SiS_P3d4
-#define SISDACA ivideo->SiS_Pr.SiS_P3c8
-#define SISDACD ivideo->SiS_Pr.SiS_P3c9
-#define SISPART1 ivideo->SiS_Pr.SiS_Part1Port
-#define SISPART2 ivideo->SiS_Pr.SiS_Part2Port
-#define SISPART3 ivideo->SiS_Pr.SiS_Part3Port
-#define SISPART4 ivideo->SiS_Pr.SiS_Part4Port
-#define SISPART5 ivideo->SiS_Pr.SiS_Part5Port
-#define SISDAC2A SISPART5
-#define SISDAC2D (SISPART5 + 1)
-#define SISMISCR (ivideo->SiS_Pr.RelIO + 0x1c)
-#define SISMISCW ivideo->SiS_Pr.SiS_P3c2
-#define SISINPSTAT (ivideo->SiS_Pr.RelIO + 0x2a)
-#define SISPEL ivideo->SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD 0x05 /* SRs */
-#define IND_SIS_COLOR_MODE 0x06
-#define IND_SIS_RAMDAC_CONTROL 0x07
-#define IND_SIS_DRAM_SIZE 0x14
-#define IND_SIS_MODULE_ENABLE 0x1E
-#define IND_SIS_PCI_ADDRESS_SET 0x20
-#define IND_SIS_TURBOQUEUE_ADR 0x26
-#define IND_SIS_TURBOQUEUE_SET 0x27
-#define IND_SIS_POWER_ON_TRAP 0x38
-#define IND_SIS_POWER_ON_TRAP2 0x39
-#define IND_SIS_CMDQUEUE_SET 0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
-
-#define IND_SIS_AGP_IO_PAD 0x48
-
-#define SIS_CRT2_WENABLE_300 0x24 /* Part1 */
-#define SIS_CRT2_WENABLE_315 0x2F
-
-#define SIS_PASSWORD 0x86 /* SR05 */
-
-#define SIS_INTERLACED_MODE 0x20 /* SR06 */
-#define SIS_8BPP_COLOR_MODE 0x0
-#define SIS_15BPP_COLOR_MODE 0x1
-#define SIS_16BPP_COLOR_MODE 0x2
-#define SIS_32BPP_COLOR_MODE 0x4
-
-#define SIS_ENABLE_2D 0x40 /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
-#define SIS_PCI_ADDR_ENABLE 0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330 series SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
-#define SIS_MMIO_CMD_ENABLE 0x20
-#define SIS_CMD_QUEUE_SIZE_512k 0x00
-#define SIS_CMD_QUEUE_SIZE_1M 0x04
-#define SIS_CMD_QUEUE_SIZE_2M 0x08
-#define SIS_CMD_QUEUE_SIZE_4M 0x0C
-#define SIS_CMD_QUEUE_RESET 0x01
-#define SIS_CMD_AUTO_CORR 0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
-#define SIS_MODE_SELECT_CRT2 0x02
-#define SIS_VB_OUTPUT_COMPOSITE 0x04
-#define SIS_VB_OUTPUT_SVIDEO 0x08
-#define SIS_VB_OUTPUT_SCART 0x10
-#define SIS_VB_OUTPUT_LCD 0x20
-#define SIS_VB_OUTPUT_CRT2 0x40
-#define SIS_VB_OUTPUT_HIVISION 0x80
-
-#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */
-#define SIS_DRIVER_MODE 0x40
-
-#define SIS_VB_COMPOSITE 0x01 /* CR32 */
-#define SIS_VB_SVIDEO 0x02
-#define SIS_VB_SCART 0x04
-#define SIS_VB_LCD 0x08
-#define SIS_VB_CRT2 0x10
-#define SIS_CRT1 0x20
-#define SIS_VB_HIVISION 0x40
-#define SIS_VB_YPBPR 0x80
-#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
- SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
-
-#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301 0x01 /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS 0x02
-#define SIS_EXTERNAL_CHIP_TRUMPION 0x03
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04
-#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05
-#define SIS310_EXTERNAL_CHIP_LVDS 0x02
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
-
-#define SIS_AGP_2X 0x20 /* CR48 */
-
-#define HW_DEVICE_EXTENSION SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION PSIS_HW_INFO
+#define COMMAND_QUEUE_AREA_SIZE (512 * 1024) /* 512K */
+#define COMMAND_QUEUE_AREA_SIZE_Z7 (128 * 1024) /* 128k for XGI Z7 */
+#define HW_CURSOR_AREA_SIZE_315 16384 /* 16K */
+#define COMMAND_QUEUE_THRESHOLD 0x1F
+
+#define SIS_OH_ALLOC_SIZE 4000
+#define SENTINEL 0x7fffffff
+
+#define SEQ_ADR 0x14
+#define SEQ_DATA 0x15
+#define DAC_ADR 0x18
+#define DAC_DATA 0x19
+#define CRTC_ADR 0x24
+#define CRTC_DATA 0x25
+#define DAC2_ADR (0x16-0x30)
+#define DAC2_DATA (0x17-0x30)
+#define VB_PART1_ADR (0x04-0x30)
+#define VB_PART1_DATA (0x05-0x30)
+#define VB_PART2_ADR (0x10-0x30)
+#define VB_PART2_DATA (0x11-0x30)
+#define VB_PART3_ADR (0x12-0x30)
+#define VB_PART3_DATA (0x13-0x30)
+#define VB_PART4_ADR (0x14-0x30)
+#define VB_PART4_DATA (0x15-0x30)
+
+#define SISSR ivideo->SiS_Pr.SiS_P3c4
+#define SISCR ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1 ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2 ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3 ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4 ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5 ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A SISPART5
+#define SISDAC2D (SISPART5 + 1)
+#define SISMISCR (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL ivideo->SiS_Pr.SiS_P3c6
+#define SISVGAENABLE (ivideo->SiS_Pr.RelIO + 0x13)
+#define SISVID (ivideo->SiS_Pr.RelIO + 0x02 - 0x30)
+#define SISCAP (ivideo->SiS_Pr.RelIO + 0x00 - 0x30)
+
+#define IND_SIS_PASSWORD 0x05 /* SRs */
+#define IND_SIS_COLOR_MODE 0x06
+#define IND_SIS_RAMDAC_CONTROL 0x07
+#define IND_SIS_DRAM_SIZE 0x14
+#define IND_SIS_MODULE_ENABLE 0x1E
+#define IND_SIS_PCI_ADDRESS_SET 0x20
+#define IND_SIS_TURBOQUEUE_ADR 0x26
+#define IND_SIS_TURBOQUEUE_SET 0x27
+#define IND_SIS_POWER_ON_TRAP 0x38
+#define IND_SIS_POWER_ON_TRAP2 0x39
+#define IND_SIS_CMDQUEUE_SET 0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
+
+#define IND_SIS_AGP_IO_PAD 0x48
+
+#define SIS_CRT2_WENABLE_300 0x24 /* Part1 */
+#define SIS_CRT2_WENABLE_315 0x2F
+
+#define SIS_PASSWORD 0x86 /* SR05 */
+
+#define SIS_INTERLACED_MODE 0x20 /* SR06 */
+#define SIS_8BPP_COLOR_MODE 0x0
+#define SIS_15BPP_COLOR_MODE 0x1
+#define SIS_16BPP_COLOR_MODE 0x2
+#define SIS_32BPP_COLOR_MODE 0x4
+
+#define SIS_ENABLE_2D 0x40 /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
+#define SIS_PCI_ADDR_ENABLE 0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330/340 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
+#define SIS_MMIO_CMD_ENABLE 0x20
+#define SIS_CMD_QUEUE_SIZE_512k 0x00
+#define SIS_CMD_QUEUE_SIZE_1M 0x04
+#define SIS_CMD_QUEUE_SIZE_2M 0x08
+#define SIS_CMD_QUEUE_SIZE_4M 0x0C
+#define SIS_CMD_QUEUE_RESET 0x01
+#define SIS_CMD_AUTO_CORR 0x02
+
+#define SIS_CMD_QUEUE_SIZE_Z7_64k 0x00 /* XGI Z7 */
+#define SIS_CMD_QUEUE_SIZE_Z7_128k 0x04
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
+#define SIS_MODE_SELECT_CRT2 0x02
+#define SIS_VB_OUTPUT_COMPOSITE 0x04
+#define SIS_VB_OUTPUT_SVIDEO 0x08
+#define SIS_VB_OUTPUT_SCART 0x10
+#define SIS_VB_OUTPUT_LCD 0x20
+#define SIS_VB_OUTPUT_CRT2 0x40
+#define SIS_VB_OUTPUT_HIVISION 0x80
+
+#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */
+#define SIS_DRIVER_MODE 0x40
+
+#define SIS_VB_COMPOSITE 0x01 /* CR32 */
+#define SIS_VB_SVIDEO 0x02
+#define SIS_VB_SCART 0x04
+#define SIS_VB_LCD 0x08
+#define SIS_VB_CRT2 0x10
+#define SIS_CRT1 0x20
+#define SIS_VB_HIVISION 0x40
+#define SIS_VB_YPBPR 0x80
+#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+ SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301 0x01 /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS 0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION 0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05
+#define SIS310_EXTERNAL_CHIP_LVDS 0x02
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
+
+#define SIS_AGP_2X 0x20 /* CR48 */
+
+/* vbflags, private entries (others in sisfb.h) */
+#define VB_CONEXANT 0x00000800 /* 661 series only */
+#define VB_TRUMPION VB_CONEXANT /* 300 series only */
+#define VB_302ELV 0x00004000
+#define VB_301 0x00100000 /* Video bridge type */
+#define VB_301B 0x00200000
+#define VB_302B 0x00400000
+#define VB_30xBDH 0x00800000 /* 30xB DH version (w/o LCD support) */
+#define VB_LVDS 0x01000000
+#define VB_CHRONTEL 0x02000000
+#define VB_301LV 0x04000000
+#define VB_302LV 0x08000000
+#define VB_301C 0x10000000
+
+#define VB_SISBRIDGE (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
+#define VB_VIDEOBRIDGE (VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
+
+/* vbflags2 (static stuff only!) */
+#define VB2_SISUMC 0x00000001
+#define VB2_301 0x00000002 /* Video bridge type */
+#define VB2_301B 0x00000004
+#define VB2_301C 0x00000008
+#define VB2_307T 0x00000010
+#define VB2_302B 0x00000800
+#define VB2_301LV 0x00001000
+#define VB2_302LV 0x00002000
+#define VB2_302ELV 0x00004000
+#define VB2_307LV 0x00008000
+#define VB2_30xBDH 0x08000000 /* 30xB DH version (w/o LCD support) */
+#define VB2_CONEXANT 0x10000000
+#define VB2_TRUMPION 0x20000000
+#define VB2_LVDS 0x40000000
+#define VB2_CHRONTEL 0x80000000
+
+#define VB2_SISLVDSBRIDGE (VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_SISTMDSBRIDGE (VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+#define VB2_SISBRIDGE (VB2_SISLVDSBRIDGE | VB2_SISTMDSBRIDGE)
+
+#define VB2_SISTMDSLCDABRIDGE (VB2_301C | VB2_307T)
+#define VB2_SISLCDABRIDGE (VB2_SISTMDSLCDABRIDGE | VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+
+#define VB2_SISHIVISIONBRIDGE (VB2_301 | VB2_301B | VB2_302B)
+#define VB2_SISYPBPRBRIDGE (VB2_301C | VB2_307T | VB2_SISLVDSBRIDGE)
+#define VB2_SISYPBPRARBRIDGE (VB2_301C | VB2_307T | VB2_307LV)
+#define VB2_SISTAP4SCALER (VB2_301C | VB2_307T | VB2_302ELV | VB2_307LV)
+#define VB2_SISTVBRIDGE (VB2_SISHIVISIONBRIDGE | VB2_SISYPBPRBRIDGE)
+
+#define VB2_SISVGA2BRIDGE (VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+
+#define VB2_VIDEOBRIDGE (VB2_SISBRIDGE | VB2_LVDS | VB2_CHRONTEL | VB2_CONEXANT)
+
+#define VB2_30xB (VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+#define VB2_30xBLV (VB2_30xB | VB2_SISLVDSBRIDGE)
+#define VB2_30xC (VB2_301C | VB2_307T)
+#define VB2_30xCLV (VB2_301C | VB2_307T | VB2_302ELV| VB2_307LV)
+#define VB2_SISEMIBRIDGE (VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCD162MHZBRIDGE (VB2_301C | VB2_307T)
+#define VB2_LCDOVER1280BRIDGE (VB2_301C | VB2_307T | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCDOVER1600BRIDGE (VB2_307T | VB2_307LV)
+#define VB2_RAMDAC202MHZBRIDGE (VB2_301C | VB2_307T)
/* I/O port access macros */
-#define inSISREG(base) inb(base)
+#define inSISREG(base) inb(base)
-#define outSISREG(base,val) outb(val,base)
+#define outSISREG(base,val) outb(val,base)
#define orSISREG(base,val) \
- do { \
- u8 __Temp = inSISREG(base); \
- outSISREG(base, __Temp | (val)); \
- } while (0)
+ do { \
+ u8 __Temp = inSISREG(base); \
+ outSISREG(base, __Temp | (val));\
+ } while (0)
#define andSISREG(base,val) \
- do { \
- u8 __Temp = inSISREG(base); \
- outSISREG(base, __Temp & (val)); \
- } while (0)
-
-#define inSISIDXREG(base,idx,var) \
- do { \
- outSISREG(base, idx); \
- var = inSISREG((base)+1); \
- } while (0)
-
-#define outSISIDXREG(base,idx,val) \
- do { \
- outSISREG(base, idx); \
- outSISREG((base)+1, val); \
- } while (0)
-
-#define orSISIDXREG(base,idx,val) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = inSISREG((base)+1) | (val); \
- outSISREG((base)+1, __Temp); \
- } while (0)
-
-#define andSISIDXREG(base,idx,and) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = inSISREG((base)+1) & (and); \
- outSISREG((base)+1, __Temp); \
- } while (0)
-
-#define setSISIDXREG(base,idx,and,or) \
- do { \
- u8 __Temp; \
- outSISREG(base, idx); \
- __Temp = (inSISREG((base)+1) & (and)) | (or); \
- outSISREG((base)+1, __Temp); \
- } while (0)
+ do { \
+ u8 __Temp = inSISREG(base); \
+ outSISREG(base, __Temp & (val));\
+ } while (0)
+
+#define inSISIDXREG(base,idx,var) \
+ do { \
+ outSISREG(base, idx); \
+ var = inSISREG((base)+1); \
+ } while (0)
+
+#define outSISIDXREG(base,idx,val) \
+ do { \
+ outSISREG(base, idx); \
+ outSISREG((base)+1, val); \
+ } while (0)
+
+#define orSISIDXREG(base,idx,val) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = inSISREG((base)+1) | (val); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
+
+#define andSISIDXREG(base,idx,and) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = inSISREG((base)+1) & (and); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
+
+#define setSISIDXREG(base,idx,and,or) \
+ do { \
+ u8 __Temp; \
+ outSISREG(base, idx); \
+ __Temp = (inSISREG((base)+1) & (and)) | (or); \
+ outSISREG((base)+1, __Temp); \
+ } while (0)
/* MMIO access macros */
#define MMIO_IN8(base, offset) readb((base+offset))
@@ -322,19 +419,19 @@
#define MMIO_QUEUE_READPORT Q_READ_PTR
#ifndef FB_BLANK_UNBLANK
-#define FB_BLANK_UNBLANK 0
+#define FB_BLANK_UNBLANK 0
#endif
#ifndef FB_BLANK_NORMAL
-#define FB_BLANK_NORMAL 1
+#define FB_BLANK_NORMAL 1
#endif
#ifndef FB_BLANK_VSYNC_SUSPEND
-#define FB_BLANK_VSYNC_SUSPEND 2
+#define FB_BLANK_VSYNC_SUSPEND 2
#endif
#ifndef FB_BLANK_HSYNC_SUSPEND
-#define FB_BLANK_HSYNC_SUSPEND 3
+#define FB_BLANK_HSYNC_SUSPEND 3
#endif
#ifndef FB_BLANK_POWERDOWN
-#define FB_BLANK_POWERDOWN 4
+#define FB_BLANK_POWERDOWN 4
#endif
enum _SIS_LCD_TYPE {
@@ -347,18 +444,19 @@ enum _SIS_LCD_TYPE {
LCD_1600x1200,
LCD_1920x1440,
LCD_2048x1536,
- LCD_320x480, /* FSTN */
+ LCD_320x240, /* FSTN */
LCD_1400x1050,
LCD_1152x864,
LCD_1152x768,
LCD_1280x768,
LCD_1024x600,
- LCD_640x480_2, /* DSTN */
- LCD_640x480_3, /* DSTN */
+ LCD_320x240_2, /* DSTN */
+ LCD_320x240_3, /* DSTN */
LCD_848x480,
LCD_1280x800,
LCD_1680x1050,
LCD_1280x720,
+ LCD_1280x854,
LCD_CUSTOM,
LCD_UNKNOWN
};
@@ -368,31 +466,50 @@ enum _SIS_CMDTYPE {
AGP_CMD_QUEUE,
VM_CMD_QUEUE,
};
-typedef unsigned int SIS_CMDTYPE;
+
+struct SIS_OH {
+ struct SIS_OH *poh_next;
+ struct SIS_OH *poh_prev;
+ u32 offset;
+ u32 size;
+};
+
+struct SIS_OHALLOC {
+ struct SIS_OHALLOC *poha_next;
+ struct SIS_OH aoh[1];
+};
+
+struct SIS_HEAP {
+ struct SIS_OH oh_free;
+ struct SIS_OH oh_used;
+ struct SIS_OH *poh_freelist;
+ struct SIS_OHALLOC *poha_chain;
+ u32 max_freesize;
+ struct sis_video_info *vinfo;
+};
/* Our "par" */
struct sis_video_info {
int cardnumber;
struct fb_info *memyselfandi;
- SIS_HW_INFO sishw_ext;
- SiS_Private SiS_Pr;
+ struct SiS_Private SiS_Pr;
- sisfb_info sisfbinfo; /* For ioctl SISFB_GET_INFO */
+ struct sisfb_info sisfbinfo; /* For ioctl SISFB_GET_INFO */
struct fb_var_screeninfo default_var;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
struct fb_fix_screeninfo sisfb_fix;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[17];
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- struct display sis_disp;
+ struct display sis_disp;
struct display_switch sisfb_sw;
struct {
u16 red, green, blue, pad;
- } sis_palette[256];
+ } sis_palette[256];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
@@ -400,10 +517,10 @@ struct sis_video_info {
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
- } sis_fbcon_cmap;
+ } sis_fbcon_cmap;
#endif
- struct sisfb_monitor {
+ struct sisfb_monitor {
u16 hmin;
u16 hmax;
u16 vmin;
@@ -411,163 +528,166 @@ struct sis_video_info {
u32 dclockmax;
u8 feature;
BOOLEAN datavalid;
- } sisfb_thismonitor;
+ } sisfb_thismonitor;
- int chip_id;
+ unsigned short chip_id; /* PCI ID of chip */
+ unsigned short chip_vendor; /* PCI ID of vendor */
char myid[40];
struct pci_dev *nbridge;
+ struct pci_dev *lpcdev;
int mni; /* Mode number index */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- int currcon;
+ int currcon;
#endif
unsigned long video_size;
- unsigned long video_base;
+ unsigned long video_base;
unsigned long mmio_size;
- unsigned long mmio_base;
- unsigned long vga_base;
+ unsigned long mmio_base;
+ unsigned long vga_base;
+
+ unsigned long video_offset;
- SIS_IOTYPE1 *video_vbase;
- SIS_IOTYPE1 *mmio_vbase;
+ unsigned long UMAsize, LFBsize;
- unsigned char *bios_abase;
+ SIS_IOTYPE1 *video_vbase;
+ SIS_IOTYPE1 *mmio_vbase;
- int mtrr;
+ unsigned char *bios_abase;
+
+ int mtrr;
u32 sisfb_mem;
- u32 sisfb_parm_mem;
- int sisfb_accel;
- int sisfb_ypan;
- int sisfb_max;
- int sisfb_userom;
- int sisfb_useoem;
+ u32 sisfb_parm_mem;
+ int sisfb_accel;
+ int sisfb_ypan;
+ int sisfb_max;
+ int sisfb_userom;
+ int sisfb_useoem;
int sisfb_mode_idx;
int sisfb_parm_rate;
int sisfb_crt1off;
int sisfb_forcecrt1;
int sisfb_crt2type;
int sisfb_crt2flags;
- int sisfb_dstn;
- int sisfb_fstn;
+ int sisfb_dstn;
+ int sisfb_fstn;
int sisfb_tvplug;
int sisfb_tvstd;
- int sisfb_filter;
int sisfb_nocrt2rate;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
int sisfb_inverse;
#endif
- u32 heapstart; /* offset */
- SIS_IOTYPE1 *sisfb_heap_start; /* address */
- SIS_IOTYPE1 *sisfb_heap_end; /* address */
- u32 sisfb_heap_size;
+ u32 heapstart; /* offset */
+ SIS_IOTYPE1 *sisfb_heap_start; /* address */
+ SIS_IOTYPE1 *sisfb_heap_end; /* address */
+ u32 sisfb_heap_size;
int havenoheap;
-#if 0
- SIS_HEAP sisfb_heap;
-#endif
+ struct SIS_HEAP sisfb_heap; /* This card's vram heap */
- int video_bpp;
- int video_cmap_len;
- int video_width;
- int video_height;
- unsigned int refresh_rate;
+ int video_bpp;
+ int video_cmap_len;
+ int video_width;
+ int video_height;
+ unsigned int refresh_rate;
- unsigned int chip;
- u8 revision_id;
+ unsigned int chip;
+ u8 revision_id;
+ int sisvga_enabled; /* PCI device was enabled */
- int video_linelength; /* real pitch */
+ int video_linelength; /* real pitch */
int scrnpitchCRT1; /* pitch regarding interlace */
- u16 DstColor; /* For 2d acceleration */
- u32 SiS310_AccelDepth;
- u32 CommandReg;
- int cmdqueuelength;
+ u16 DstColor; /* For 2d acceleration */
+ u32 SiS310_AccelDepth;
+ u32 CommandReg;
+ int cmdqueuelength; /* Current (for accel) */
+ u32 cmdQueueSize; /* Total size in KB */
- spinlock_t lockaccel; /* Do not use outside of kernel! */
+ spinlock_t lockaccel; /* Do not use outside of kernel! */
- unsigned int pcibus;
- unsigned int pcislot;
- unsigned int pcifunc;
+ unsigned int pcibus;
+ unsigned int pcislot;
+ unsigned int pcifunc;
- int accel;
+ int accel;
+ int engineok;
- u16 subsysvendor;
- u16 subsysdevice;
+ u16 subsysvendor;
+ u16 subsysdevice;
- u32 vbflags; /* Replacing deprecated stuff from above */
- u32 currentvbflags;
+ u32 vbflags; /* Replacing deprecated stuff from above */
+ u32 currentvbflags;
+ u32 vbflags2;
int lcdxres, lcdyres;
int lcddefmodeidx, tvdefmodeidx, defmodeidx;
- u32 CRT2LCDType; /* defined in "SIS_LCD_TYPE" */
-
- int current_bpp;
- int current_width;
- int current_height;
- int current_htotal;
- int current_vtotal;
+ u32 CRT2LCDType; /* defined in "SIS_LCD_TYPE" */
+ u32 curFSTN, curDSTN;
+
+ int current_bpp;
+ int current_width;
+ int current_height;
+ int current_htotal;
+ int current_vtotal;
int current_linelength;
- __u32 current_pixclock;
- int current_refresh_rate;
+ __u32 current_pixclock;
+ int current_refresh_rate;
+
+ unsigned int current_base;
- u8 mode_no;
- u8 rate_idx;
- int modechanged;
- unsigned char modeprechange;
+ u8 mode_no;
+ u8 rate_idx;
+ int modechanged;
+ unsigned char modeprechange;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- u8 sisfb_lastrates[128];
+ u8 sisfb_lastrates[128];
#endif
- int newrom;
- int registered;
+ int newrom;
+ int haveXGIROM;
+ int registered;
int warncount;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ int ioctl32registered;
+#endif
- int sisvga_engine;
- int hwcursor_size;
- int CRT2_write_enable;
- u8 caps;
+ int sisvga_engine;
+ int hwcursor_size;
+ int CRT2_write_enable;
+ u8 caps;
- u8 detectedpdc;
- u8 detectedpdca;
- u8 detectedlcda;
+ u8 detectedpdc;
+ u8 detectedpdca;
+ u8 detectedlcda;
- SIS_IOTYPE1 *hwcursor_vbase;
+ SIS_IOTYPE1 *hwcursor_vbase;
- int chronteltype;
- int tvxpos, tvypos;
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+ int chronteltype;
+ int tvxpos, tvypos;
+ u8 p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
int tvx, tvy;
- u8 sisfblocked;
+ u8 sisfblocked;
+
+ struct sisfb_info sisfb_infoblock;
+
+ struct sisfb_cmd sisfb_command;
+
+ u32 sisfb_id;
+
+ u8 sisfb_can_post;
+ u8 sisfb_card_posted;
+ u8 sisfb_was_boot_device;
struct sis_video_info *next;
};
-typedef struct _SIS_OH {
- struct _SIS_OH *poh_next;
- struct _SIS_OH *poh_prev;
- u32 offset;
- u32 size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
- struct _SIS_OHALLOC *poha_next;
- SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
- SIS_OH oh_free;
- SIS_OH oh_used;
- SIS_OH *poh_freelist;
- SIS_OHALLOC *poha_chain;
- u32 max_freesize;
- struct sis_video_info *vinfo;
-} SIS_HEAP;
-
#endif
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 30e90a553e80..bab933e6c6a6 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -1,6 +1,8 @@
/*
- * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver
- * for Linux kernels 2.4.x and 2.6.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
* 2D acceleration part
*
@@ -19,7 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
* Based on the XFree86/X.org driver which is
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
* (see http://www.winischhofer.net/
@@ -30,13 +32,11 @@
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/errno.h>
#include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/console.h>
-#include <linux/selection.h>
+#endif
#include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
#include <linux/types.h>
#include <asm/io.h>
@@ -188,7 +188,7 @@ SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
}
#endif
-/* 315/330 series ------------------------------------------------- */
+/* 315/330/340 series ---------------------------------------------- */
#ifdef CONFIG_FB_SIS_315
static void
@@ -202,7 +202,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
{
SiS310SetupDSTColorDepth(ivideo->DstColor);
SiS310SetupSRCPitch(ivideo->video_linelength)
- SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+ SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
if(trans_color != -1) {
SiS310SetupROP(0x0A)
SiS310SetupSRCTrans(trans_color)
@@ -213,7 +213,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
}
SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
- /* The 315 series is smart enough to know the direction */
+ /* The chip is smart enough to know the direction */
}
static void
@@ -223,35 +223,38 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int
u32 srcbase = 0, dstbase = 0;
int mymin = min(src_y, dst_y);
int mymax = max(src_y, dst_y);
-
+
/* Although the chip knows the direction to use
- * if the source and destination areas overlap,
+ * if the source and destination areas overlap,
* that logic fails if we fiddle with the bitmap
* addresses. Therefore, we check if the source
- * and destination blitting areas overlap and
- * adapt the bitmap addresses synchronously
+ * and destination blitting areas overlap and
+ * adapt the bitmap addresses synchronously
* if the coordinates exceed the valid range.
- * The the areas do not overlap, we do our
+ * The the areas do not overlap, we do our
* normal check.
*/
- if((mymax - mymin) < height) {
- if((src_y >= 2048) || (dst_y >= 2048)) {
- srcbase = ivideo->video_linelength * mymin;
- dstbase = ivideo->video_linelength * mymin;
- src_y -= mymin;
- dst_y -= mymin;
- }
+ if((mymax - mymin) < height) {
+ if((src_y >= 2048) || (dst_y >= 2048)) {
+ srcbase = ivideo->video_linelength * mymin;
+ dstbase = ivideo->video_linelength * mymin;
+ src_y -= mymin;
+ dst_y -= mymin;
+ }
} else {
- if(src_y >= 2048) {
- srcbase = ivideo->video_linelength * src_y;
- src_y = 0;
- }
- if(dst_y >= 2048) {
- dstbase = ivideo->video_linelength * dst_y;
- dst_y = 0;
- }
+ if(src_y >= 2048) {
+ srcbase = ivideo->video_linelength * src_y;
+ src_y = 0;
+ }
+ if(dst_y >= 2048) {
+ dstbase = ivideo->video_linelength * dst_y;
+ dst_y = 0;
+ }
}
+ srcbase += ivideo->video_offset;
+ dstbase += ivideo->video_offset;
+
SiS310SetupSRCBase(srcbase);
SiS310SetupDSTBase(dstbase);
SiS310SetupRect(width, height)
@@ -264,7 +267,7 @@ static void
SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
{
SiS310SetupPATFG(color)
- SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+ SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
SiS310SetupDSTColorDepth(ivideo->DstColor);
SiS310SetupROP(sisPatALUConv[rop])
SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
@@ -279,6 +282,7 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
dstbase = ivideo->video_linelength * y;
y = 0;
}
+ dstbase += ivideo->video_offset;
SiS310SetupDSTBase(dstbase)
SiS310SetupDSTXY(x,y)
SiS310SetupRect(w,h)
@@ -294,384 +298,153 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
int sisfb_initaccel(struct sis_video_info *ivideo)
{
#ifdef SISFB_USE_SPINLOCKS
- spin_lock_init(&ivideo->lockaccel);
+ spin_lock_init(&ivideo->lockaccel);
#endif
- return(0);
+ return 0;
}
void sisfb_syncaccel(struct sis_video_info *ivideo)
{
- if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- SiS300Sync(ivideo);
+ SiS300Sync(ivideo);
#endif
- } else {
+ } else {
#ifdef CONFIG_FB_SIS_315
- SiS310Sync(ivideo);
+ SiS310Sync(ivideo);
#endif
- }
+ }
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */
int fbcon_sis_sync(struct fb_info *info)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- CRITFLAGS
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ CRITFLAGS
- if(!ivideo->accel)
- return 0;
+ if((!ivideo->accel) || (!ivideo->engineok))
+ return 0;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- SiS310Sync(ivideo);
-#endif
- }
- CRITEND
- return 0;
+ CRITBEGIN
+ sisfb_syncaccel(ivideo);
+ CRITEND
+
+ return 0;
}
void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- u32 col = 0;
- u32 vxres = info->var.xres_virtual;
- u32 vyres = info->var.yres_virtual;
- int width, height;
- CRITFLAGS
-
- if(info->state != FBINFO_STATE_RUNNING) {
- return;
- }
-
- if(!ivideo->accel) {
- cfb_fillrect(info, rect);
- return;
- }
-
- if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
- return;
- }
-
- /* Clipping */
- width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
- height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
-
- switch(info->var.bits_per_pixel) {
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ u32 col = 0;
+ u32 vxres = info->var.xres_virtual;
+ u32 vyres = info->var.yres_virtual;
+ int width, height;
+ CRITFLAGS
+
+ if(info->state != FBINFO_STATE_RUNNING)
+ return;
+
+ if((!ivideo->accel) || (!ivideo->engineok)) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
+ return;
+
+ /* Clipping */
+ width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+ height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
+ switch(info->var.bits_per_pixel) {
case 8: col = rect->color;
break;
case 16:
case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
break;
- }
+ }
- if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
- SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
- CRITEND
- SiS300Sync(ivideo);
+ CRITBEGIN
+ SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+ SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+ CRITEND
#endif
- } else {
+ } else {
#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
- SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
- CRITEND
- SiS310Sync(ivideo);
+ CRITBEGIN
+ SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+ SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+ CRITEND
#endif
- }
+ }
+ sisfb_syncaccel(ivideo);
}
void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- u32 vxres = info->var.xres_virtual;
- u32 vyres = info->var.yres_virtual;
- int width = area->width;
- int height = area->height;
- CRITFLAGS
-
- if(info->state != FBINFO_STATE_RUNNING) {
- return;
- }
-
- if(!ivideo->accel) {
- cfb_copyarea(info, area);
- return;
- }
-
- if(!width || !height ||
- area->sx >= vxres || area->sy >= vyres ||
- area->dx >= vxres || area->dy >= vyres) {
- return;
- }
-
- /* Clipping */
- if((area->sx + width) > vxres) width = vxres - area->sx;
- if((area->dx + width) > vxres) width = vxres - area->dx;
- if((area->sy + height) > vyres) height = vyres - area->sy;
- if((area->dy + height) > vyres) height = vyres - area->dy;
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- int xdir, ydir;
-
- if(area->sx < area->dx) xdir = 0;
- else xdir = 1;
- if(area->sy < area->dy) ydir = 0;
- else ydir = 1;
-
- CRITBEGIN
- SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
- SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
- width, height);
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
- SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
- width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
-
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */
-
-void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
- int dsty, int dstx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-
+ struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+ u32 vxres = info->var.xres_virtual;
+ u32 vyres = info->var.yres_virtual;
+ int width = area->width;
+ int height = area->height;
CRITFLAGS
- if(!ivideo->accel) {
- switch(ivideo->video_bpp) {
- case 8:
-#ifdef FBCON_HAS_CFB8
- fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- case 16:
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- case 32:
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
- break;
- }
- return;
- }
-
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
- dstx *= fontwidth(p);
- dsty *= fontheight(p);
- width *= fontwidth(p);
- height *= fontheight(p);
+ if(info->state != FBINFO_STATE_RUNNING)
+ return;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- int xdir, ydir;
-
- if(srcx < dstx) xdir = 0;
- else xdir = 1;
- if(srcy < dsty) ydir = 0;
- else ydir = 1;
-
- CRITBEGIN
- SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
- SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
- SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
+ if((!ivideo->accel) || (!ivideo->engineok)) {
+ cfb_copyarea(info, area);
+ return;
}
-}
-static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width, int color)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- CRITFLAGS
+ if(!width || !height ||
+ area->sx >= vxres || area->sy >= vyres ||
+ area->dx >= vxres || area->dy >= vyres)
+ return;
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
- width *= fontwidth(p);
- height *= fontheight(p);
+ /* Clipping */
+ if((area->sx + width) > vxres) width = vxres - area->sx;
+ if((area->dx + width) > vxres) width = vxres - area->dx;
+ if((area->sy + height) > vyres) height = vyres - area->sy;
+ if((area->dy + height) > vyres) height = vyres - area->dy;
if(ivideo->sisvga_engine == SIS_300_VGA) {
#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, color, 3);
- SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
- CRITEND
- SiS300Sync(ivideo);
+ int xdir, ydir;
+
+ if(area->sx < area->dx) xdir = 0;
+ else xdir = 1;
+ if(area->sy < area->dy) ydir = 0;
+ else ydir = 1;
+
+ CRITBEGIN
+ SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+ SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+ area->dx, area->dy, width, height);
+ CRITEND
#endif
} else {
#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, color, 3);
- SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
-
-void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB8
- fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+ CRITBEGIN
+ SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+ SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+ area->dx, area->dy, width, height);
+ CRITEND
#endif
- return;
}
- bgx = attr_bgcol_ec(p, conp);
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
+ sisfb_syncaccel(ivideo);
}
-void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
#endif
- return;
- }
-
- bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- u32 bgx;
-
- if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
-#endif
- return;
- }
-
- bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-
-void fbcon_sis_revc(struct display *p, int srcx, int srcy)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
- CRITFLAGS
-
- if(!ivideo->accel) {
- switch(ivideo->video_bpp) {
- case 16:
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_revc(p, srcx, srcy);
-#endif
- break;
- case 32:
-#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_revc(p, srcx, srcy);
-#endif
- break;
- }
- return;
- }
-
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- CRITBEGIN
- SiS300SetupForSolidFill(ivideo, 0, 0x0a);
- SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
- CRITEND
- SiS300Sync(ivideo);
-#endif
- } else {
-#ifdef CONFIG_FB_SIS_315
- CRITBEGIN
- SiS310SetupForSolidFill(ivideo, 0, 0x0a);
- SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
- CRITEND
- SiS310Sync(ivideo);
-#endif
- }
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */
-#ifdef FBCON_HAS_CFB8
-struct display_switch fbcon_sis8 = {
- .setup = fbcon_cfb8_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear8,
- .putc = fbcon_cfb8_putc,
- .putcs = fbcon_cfb8_putcs,
- .revc = fbcon_cfb8_revc,
- .clear_margins = fbcon_cfb8_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB16
-struct display_switch fbcon_sis16 = {
- .setup = fbcon_cfb16_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear16,
- .putc = fbcon_cfb16_putc,
- .putcs = fbcon_cfb16_putcs,
- .revc = fbcon_sis_revc,
- .clear_margins = fbcon_cfb16_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB32
-struct display_switch fbcon_sis32 = {
- .setup = fbcon_cfb32_setup,
- .bmove = fbcon_sis_bmove,
- .clear = fbcon_sis_clear32,
- .putc = fbcon_cfb32_putc,
- .putcs = fbcon_cfb32_putcs,
- .revc = fbcon_sis_revc,
- .clear_margins = fbcon_cfb32_clear_margins,
- .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
+#include "sisfb_accel_2_4.h"
#endif /* KERNEL VERSION */
diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h
index bb28f331d60d..046e2c4a8e09 100644
--- a/drivers/video/sis/sis_accel.h
+++ b/drivers/video/sis/sis_accel.h
@@ -1,6 +1,8 @@
/*
- * SiS 300/630/730/540/315/550/650/740 frame buffer driver
- * for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
* 2D acceleration part
*
@@ -283,6 +285,8 @@
{ \
while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
CmdQueLen = 0; \
}
@@ -402,6 +406,7 @@ void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
int srcx, int height, int width);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+int fbcon_sis_sync(struct fb_info *info);
void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
#endif
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 698266036819..42c54b69726e 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1,9 +1,10 @@
/*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* 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
@@ -19,11 +20,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
*
* Author of (practically wiped) code base:
* SiS (www.sis.com)
- * Copyright (C) 1999 Silicon Integrated Systems, Inc.
+ * Copyright (C) 1999 Silicon Integrated Systems, Inc.
*
* See http://www.winischhofer.net/ for more information and updates
*
@@ -46,16 +47,15 @@
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
-#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/console.h>
#include <linux/selection.h>
-#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/vt_kern.h>
+#endif
#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/types.h>
@@ -94,71 +94,75 @@ extern struct display_switch fbcon_sis32;
#endif
#endif
+static void sisfb_handle_command(struct sis_video_info *ivideo,
+ struct sisfb_cmd *sisfb_command);
+
/* ------------------ Internal helper routines ----------------- */
static void __init
sisfb_setdefaultparms(void)
{
- sisfb_off = 0;
- sisfb_parm_mem = 0;
- sisfb_accel = -1;
- sisfb_ypan = -1;
- sisfb_max = -1;
- sisfb_userom = -1;
- sisfb_useoem = -1;
+ sisfb_off = 0;
+ sisfb_parm_mem = 0;
+ sisfb_accel = -1;
+ sisfb_ypan = -1;
+ sisfb_max = -1;
+ sisfb_userom = -1;
+ sisfb_useoem = -1;
#ifdef MODULE
/* Module: "None" for 2.4, default mode for 2.5+ */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sisfb_mode_idx = -1;
+ sisfb_mode_idx = -1;
#else
- sisfb_mode_idx = MODE_INDEX_NONE;
+ sisfb_mode_idx = MODE_INDEX_NONE;
#endif
#else
/* Static: Default mode */
- sisfb_mode_idx = -1;
-#endif
- sisfb_parm_rate = -1;
- sisfb_crt1off = 0;
- sisfb_forcecrt1 = -1;
- sisfb_crt2type = -1;
- sisfb_crt2flags = 0;
- sisfb_pdc = 0xff;
- sisfb_pdca = 0xff;
- sisfb_scalelcd = -1;
+ sisfb_mode_idx = -1;
+#endif
+ sisfb_parm_rate = -1;
+ sisfb_crt1off = 0;
+ sisfb_forcecrt1 = -1;
+ sisfb_crt2type = -1;
+ sisfb_crt2flags = 0;
+ sisfb_pdc = 0xff;
+ sisfb_pdca = 0xff;
+ sisfb_scalelcd = -1;
sisfb_specialtiming = CUT_NONE;
- sisfb_lvdshl = -1;
- sisfb_dstn = 0;
- sisfb_fstn = 0;
- sisfb_tvplug = -1;
- sisfb_tvstd = -1;
- sisfb_tvxposoffset = 0;
- sisfb_tvyposoffset = 0;
- sisfb_filter = -1;
- sisfb_nocrt2rate = 0;
+ sisfb_lvdshl = -1;
+ sisfb_dstn = 0;
+ sisfb_fstn = 0;
+ sisfb_tvplug = -1;
+ sisfb_tvstd = -1;
+ sisfb_tvxposoffset = 0;
+ sisfb_tvyposoffset = 0;
+ sisfb_nocrt2rate = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sisfb_inverse = 0;
- sisfb_fontname[0] = 0;
+ sisfb_inverse = 0;
+ sisfb_fontname[0] = 0;
#endif
#if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = 0;
- sisfb_videoram = 0;
+ sisfb_resetcard = 0;
+ sisfb_videoram = 0;
#endif
}
+/* ------------- Parameter parsing -------------- */
+
static void __devinit
sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
{
int i = 0, j = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(vesamode == 0) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
sisfb_mode_idx = MODE_INDEX_NONE;
#else
- if(!quiet) {
- printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
- }
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+
sisfb_mode_idx = DEFAULT_MODE;
#endif
return;
@@ -169,95 +173,102 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
while(sisbios_mode[i++].mode_no[0] != 0) {
if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
(sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
+ if(sisfb_fstn) {
+ if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+ sisbios_mode[i-1].mode_no[1] == 0x56 ||
+ sisbios_mode[i-1].mode_no[1] == 0x53)
+ continue;
+ } else {
+ if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+ sisbios_mode[i-1].mode_no[1] == 0x5b)
+ continue;
+ }
+ sisfb_mode_idx = i - 1;
+ j = 1;
+ break;
}
}
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+ if((!j) && !quiet)
+ printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
}
-static void
+static void __devinit
sisfb_search_mode(char *name, BOOLEAN quiet)
{
- int i = 0;
unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+ int i = 0;
char strbuf[16], strbuf1[20];
char *nameptr = name;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(name == NULL) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+
+ sisfb_mode_idx = DEFAULT_MODE;
+ return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
+ if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+ if(!quiet)
+ printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+
+ sisfb_mode_idx = DEFAULT_MODE;
+ return;
}
#endif
if(strlen(name) <= 19) {
- strcpy(strbuf1, name);
- for(i=0; i<strlen(strbuf1); i++) {
- if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
- }
+ strcpy(strbuf1, name);
+ for(i = 0; i < strlen(strbuf1); i++) {
+ if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+ }
- /* This does some fuzzy mode naming detection */
- if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
- if((rate <= 32) || (depth > 32)) {
- j = rate; rate = depth; depth = j;
- }
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- sisfb_parm_rate = rate;
- } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- } else {
- xres = 0;
- if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
- sprintf(strbuf, "%ux%ux8", xres, yres);
- nameptr = strbuf;
- } else {
- sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
- return;
- }
- }
+ /* This does some fuzzy mode naming detection */
+ if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+ if((rate <= 32) || (depth > 32)) {
+ j = rate; rate = depth; depth = j;
+ }
+ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+ nameptr = strbuf;
+ sisfb_parm_rate = rate;
+ } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+ nameptr = strbuf;
+ } else {
+ xres = 0;
+ if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+ sprintf(strbuf, "%ux%ux8", xres, yres);
+ nameptr = strbuf;
+ } else {
+ sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+ return;
+ }
+ }
}
i = 0; j = 0;
while(sisbios_mode[i].mode_no[0] != 0) {
if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+ if(sisfb_fstn) {
+ if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+ sisbios_mode[i-1].mode_no[1] == 0x56 ||
+ sisbios_mode[i-1].mode_no[1] == 0x53)
+ continue;
+ } else {
+ if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+ sisbios_mode[i-1].mode_no[1] == 0x5b)
+ continue;
+ }
+ sisfb_mode_idx = i - 1;
+ j = 1;
+ break;
+ }
+ }
+
+ if((!j) && !quiet)
+ printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
}
#ifndef MODULE
@@ -265,7 +276,7 @@ static void __devinit
sisfb_get_vga_mode_from_kernel(void)
{
#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
- char mymode[32];
+ char mymode[32];
int mydepth = screen_info.lfb_depth;
if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
@@ -274,15 +285,17 @@ sisfb_get_vga_mode_from_kernel(void)
(screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
(mydepth >= 8) && (mydepth <= 32) ) {
- if(mydepth == 24) mydepth = 32;
+ if(mydepth == 24) mydepth = 32;
- sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
- screen_info.lfb_height,
+ sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
+ screen_info.lfb_height,
mydepth);
- printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+ printk(KERN_DEBUG
+ "sisfb: Using vga mode %s pre-set by kernel as default\n",
+ mymode);
- sisfb_search_mode(mymode, TRUE);
+ sisfb_search_mode(mymode, TRUE);
}
#endif
return;
@@ -294,26 +307,25 @@ sisfb_search_crt2type(const char *name)
{
int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
if(name == NULL) return;
while(sis_crt2type[i].type_no != -1) {
- if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
- sisfb_crt2type = sis_crt2type[i].type_no;
- sisfb_tvplug = sis_crt2type[i].tvplug_no;
- sisfb_crt2flags = sis_crt2type[i].flags;
- break;
- }
- i++;
+ if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+ sisfb_crt2type = sis_crt2type[i].type_no;
+ sisfb_tvplug = sis_crt2type[i].tvplug_no;
+ sisfb_crt2flags = sis_crt2type[i].flags;
+ break;
+ }
+ i++;
}
sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
- if(sisfb_crt2type < 0) {
+ if(sisfb_crt2type < 0)
printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
- }
}
static void __init
@@ -321,16 +333,17 @@ sisfb_search_tvstd(const char *name)
{
int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
+ if(name == NULL)
+ return;
while(sis_tvtype[i].type_no != -1) {
- if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
- sisfb_tvstd = sis_tvtype[i].type_no;
- break;
- }
- i++;
+ if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+ sisfb_tvstd = sis_tvtype[i].type_no;
+ break;
+ }
+ i++;
}
}
@@ -340,38 +353,101 @@ sisfb_search_specialtiming(const char *name)
int i = 0;
BOOLEAN found = FALSE;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+ /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
+ if(name == NULL)
+ return;
if(!strnicmp(name, "none", 4)) {
- sisfb_specialtiming = CUT_FORCENONE;
+ sisfb_specialtiming = CUT_FORCENONE;
printk(KERN_DEBUG "sisfb: Special timing disabled\n");
} else {
- while(mycustomttable[i].chipID != 0) {
- if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
- sisfb_specialtiming = mycustomttable[i].SpecialID;
- found = TRUE;
- printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
- mycustomttable[i].vendorName, mycustomttable[i].cardName,
- mycustomttable[i].optionName);
- break;
- }
- i++;
- }
- if(!found) {
- printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
- printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
- i = 0;
- while(mycustomttable[i].chipID != 0) {
- printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
- mycustomttable[i].optionName,
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- i++;
- }
- }
- }
+ while(mycustomttable[i].chipID != 0) {
+ if(!strnicmp(name,mycustomttable[i].optionName,
+ strlen(mycustomttable[i].optionName))) {
+ sisfb_specialtiming = mycustomttable[i].SpecialID;
+ found = TRUE;
+ printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName,
+ mycustomttable[i].optionName);
+ break;
+ }
+ i++;
+ }
+ if(!found) {
+ printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+ printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+ i = 0;
+ while(mycustomttable[i].chipID != 0) {
+ printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+ mycustomttable[i].optionName,
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName);
+ i++;
+ }
+ }
+ }
+}
+
+/* ----------- Various detection routines ----------- */
+
+static void __devinit
+sisfb_detect_custom_timing(struct sis_video_info *ivideo)
+{
+ unsigned char *biosver = NULL;
+ unsigned char *biosdate = NULL;
+ BOOLEAN footprint;
+ u32 chksum = 0;
+ int i, j;
+
+ if(ivideo->SiS_Pr.UseROM) {
+ biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
+ biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
+ for(i = 0; i < 32768; i++)
+ chksum += ivideo->SiS_Pr.VirtualRomBase[i];
+ }
+
+ i = 0;
+ do {
+ if( (mycustomttable[i].chipID == ivideo->chip) &&
+ ((!strlen(mycustomttable[i].biosversion)) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (!strncmp(mycustomttable[i].biosversion, biosver,
+ strlen(mycustomttable[i].biosversion))))) &&
+ ((!strlen(mycustomttable[i].biosdate)) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (!strncmp(mycustomttable[i].biosdate, biosdate,
+ strlen(mycustomttable[i].biosdate))))) &&
+ ((!mycustomttable[i].bioschksum) ||
+ (ivideo->SiS_Pr.UseROM &&
+ (mycustomttable[i].bioschksum == chksum))) &&
+ (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+ (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
+ footprint = TRUE;
+ for(j = 0; j < 5; j++) {
+ if(mycustomttable[i].biosFootprintAddr[j]) {
+ if(ivideo->SiS_Pr.UseROM) {
+ if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+ mycustomttable[i].biosFootprintData[j]) {
+ footprint = FALSE;
+ }
+ } else
+ footprint = FALSE;
+ }
+ }
+ if(footprint) {
+ ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+ printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
+ mycustomttable[i].vendorName,
+ mycustomttable[i].cardName);
+ printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
+ mycustomttable[i].optionName);
+ break;
+ }
+ }
+ i++;
+ } while(mycustomttable[i].chipID);
}
static BOOLEAN __devinit
@@ -384,22 +460,23 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
buffer[2] != 0xff || buffer[3] != 0xff ||
buffer[4] != 0xff || buffer[5] != 0xff ||
buffer[6] != 0xff || buffer[7] != 0x00) {
- printk(KERN_DEBUG "sisfb: Bad EDID header\n");
- return FALSE;
+ printk(KERN_DEBUG "sisfb: Bad EDID header\n");
+ return FALSE;
}
if(buffer[0x12] != 0x01) {
- printk(KERN_INFO "sisfb: EDID version %d not supported\n",
- buffer[0x12]);
- return FALSE;
+ printk(KERN_INFO "sisfb: EDID version %d not supported\n",
+ buffer[0x12]);
+ return FALSE;
}
monitor->feature = buffer[0x18];
if(!buffer[0x14] & 0x80) {
- if(!(buffer[0x14] & 0x08)) {
- printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n");
- }
+ if(!(buffer[0x14] & 0x08)) {
+ printk(KERN_INFO
+ "sisfb: WARNING: Monitor does not support separate syncs\n");
+ }
}
if(buffer[0x13] >= 0x01) {
@@ -409,7 +486,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
j = 0x36;
for(i=0; i<4; i++) {
if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
- buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
+ buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
buffer[j + 4] == 0x00) {
monitor->hmin = buffer[j + 7];
monitor->hmax = buffer[j + 8];
@@ -435,7 +512,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
for(i = 0; i < 13; i++) {
if(emodes & sisfb_ddcsmodes[i].mask) {
- if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
+ if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
@@ -446,80 +523,81 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
for(i = 0; i < 8; i++) {
xres = (buffer[index] + 31) * 8;
switch(buffer[index + 1] & 0xc0) {
- case 0xc0: yres = (xres * 9) / 16; break;
- case 0x80: yres = (xres * 4) / 5; break;
- case 0x40: yres = (xres * 3) / 4; break;
- default: yres = xres; break;
+ case 0xc0: yres = (xres * 9) / 16; break;
+ case 0x80: yres = (xres * 4) / 5; break;
+ case 0x40: yres = (xres * 3) / 4; break;
+ default: yres = xres; break;
}
refresh = (buffer[index + 1] & 0x3f) + 60;
if((xres >= 640) && (yres >= 480)) {
- for(j = 0; j < 8; j++) {
- if((xres == sisfb_ddcfmodes[j].x) &&
- (yres == sisfb_ddcfmodes[j].y) &&
+ for(j = 0; j < 8; j++) {
+ if((xres == sisfb_ddcfmodes[j].x) &&
+ (yres == sisfb_ddcfmodes[j].y) &&
(refresh == sisfb_ddcfmodes[j].v)) {
if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
- }
- }
+ if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
+ }
+ }
}
index += 2;
- }
+ }
if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
monitor->datavalid = TRUE;
}
}
- return(monitor->datavalid);
+ return monitor->datavalid;
}
static void __devinit
sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
{
- USHORT temp, i, realcrtno = crtno;
- u8 buffer[256];
+ unsigned short temp, i, realcrtno = crtno;
+ unsigned char buffer[256];
monitor->datavalid = FALSE;
if(crtno) {
- if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
- else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
- else return;
- }
+ if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
+ else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
+ else return;
+ }
- if((ivideo->sisfb_crt1off) && (!crtno)) return;
+ if((ivideo->sisfb_crt1off) && (!crtno))
+ return;
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 0, &buffer[0]);
- if((!temp) || (temp == 0xffff)) {
- printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 0, &buffer[0], ivideo->vbflags2);
+ if((!temp) || (temp == 0xffff)) {
+ printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
return;
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
- printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
- crtno + 1,
- (temp & 0x1a) ? "" : "[none of the supported]",
- (temp & 0x02) ? "2 " : "",
- (temp & 0x08) ? "D&P" : "",
- (temp & 0x10) ? "FPDI-2" : "");
- if(temp & 0x02) {
+ } else {
+ printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
+ printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
+ crtno + 1,
+ (temp & 0x1a) ? "" : "[none of the supported]",
+ (temp & 0x02) ? "2 " : "",
+ (temp & 0x08) ? "D&P" : "",
+ (temp & 0x10) ? "FPDI-2" : "");
+ if(temp & 0x02) {
i = 3; /* Number of retrys */
do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 1, &buffer[0]);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 1, &buffer[0], ivideo->vbflags2);
} while((temp) && i--);
- if(!temp) {
- if(sisfb_interpret_edid(monitor, &buffer[0])) {
+ if(!temp) {
+ if(sisfb_interpret_edid(monitor, &buffer[0])) {
printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
- monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
+ monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
monitor->dclockmax / 1000);
} else {
- printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
- }
+ printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
+ }
} else {
- printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
+ printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
}
} else {
printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
@@ -527,6 +605,8 @@ sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, i
}
}
+/* -------------- Mode validation --------------- */
+
static BOOLEAN
sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
int mode_idx, int rate_idx, int rate)
@@ -534,42 +614,49 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
int htotal, vtotal;
unsigned int dclock, hsync;
- if(!monitor->datavalid) return TRUE;
+ if(!monitor->datavalid)
+ return TRUE;
- if(mode_idx < 0) return FALSE;
+ if(mode_idx < 0)
+ return FALSE;
/* Skip for 320x200, 320x240, 640x400 */
- switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
- case 0x59:
- case 0x41:
- case 0x4f:
- case 0x50:
- case 0x56:
- case 0x53:
- case 0x2f:
- case 0x5d:
- case 0x5e:
- return TRUE;
+ switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
+ case 0x59:
+ case 0x41:
+ case 0x4f:
+ case 0x50:
+ case 0x56:
+ case 0x53:
+ case 0x2f:
+ case 0x5d:
+ case 0x5e:
+ return TRUE;
#ifdef CONFIG_FB_SIS_315
case 0x5a:
case 0x5b:
if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
#endif
- }
+ }
- if(rate < (monitor->vmin - 1)) return FALSE;
- if(rate > (monitor->vmax + 1)) return FALSE;
+ if(rate < (monitor->vmin - 1))
+ return FALSE;
+ if(rate > (monitor->vmax + 1))
+ return FALSE;
- if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+ if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
sisbios_mode[mode_idx].mode_no[ivideo->mni],
- &htotal, &vtotal, rate_idx)) {
+ &htotal, &vtotal, rate_idx)) {
dclock = (htotal * vtotal * rate) / 1000;
- if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+ if(dclock > (monitor->dclockmax + 1000))
+ return FALSE;
hsync = dclock / htotal;
- if(hsync < (monitor->hmin - 1)) return FALSE;
- if(hsync > (monitor->hmax + 1)) return FALSE;
+ if(hsync < (monitor->hmin - 1))
+ return FALSE;
+ if(hsync > (monitor->hmax + 1))
+ return FALSE;
} else {
- return FALSE;
+ return FALSE;
}
return TRUE;
}
@@ -577,82 +664,79 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
static int
sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
{
- u16 xres=0, yres, myres;
+ u16 xres=0, yres, myres;
#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
- }
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+ return -1 ;
+ }
#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
- }
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+ return -1;
+ }
#endif
- myres = sisbios_mode[myindex].yres;
-
- switch(vbflags & VB_DISPTYPE_DISP2) {
+ myres = sisbios_mode[myindex].yres;
- case CRT2_LCD:
+ switch(vbflags & VB_DISPTYPE_DISP2) {
- xres = ivideo->lcdxres; yres = ivideo->lcdyres;
+ case CRT2_LCD:
+ xres = ivideo->lcdxres; yres = ivideo->lcdyres;
- if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
- if(sisbios_mode[myindex].xres > xres) return(-1);
- if(myres > yres) return(-1);
- }
+ if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+ (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+ if(sisbios_mode[myindex].xres > xres)
+ return -1;
+ if(myres > yres)
+ return -1;
+ }
- if(vbflags & (VB_LVDS | VB_30xBDH)) {
- if(sisbios_mode[myindex].xres == 320) {
- if((myres == 240) || (myres == 480)) {
- if(!ivideo->sisfb_fstn) {
- if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
- sisbios_mode[myindex].mode_no[1] == 0x5b)
- return(-1);
- } else {
- if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
- sisbios_mode[myindex].mode_no[1] == 0x56 ||
- sisbios_mode[myindex].mode_no[1] == 0x53)
- return(-1);
- }
- }
- }
- }
+ if(ivideo->sisfb_fstn) {
+ if(sisbios_mode[myindex].xres == 320) {
+ if(myres == 240) {
+ switch(sisbios_mode[myindex].mode_no[1]) {
+ case 0x50: myindex = MODE_FSTN_8; break;
+ case 0x56: myindex = MODE_FSTN_16; break;
+ case 0x53: return -1;
+ }
+ }
+ }
+ }
- if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
- ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
- return(-1);
- }
- break;
+ if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
+ ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
- case CRT2_TV:
- if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
- }
- break;
+ case CRT2_TV:
+ if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
- case CRT2_VGA:
- if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
+ case CRT2_VGA:
+ if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+ return -1;
+ }
+ break;
}
- break;
- }
- return(myindex);
+ return myindex;
}
static u8
sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
{
- u16 xres, yres;
int i = 0;
-
- xres = sisbios_mode[mode_idx].xres;
- yres = sisbios_mode[mode_idx].yres;
+ u16 xres = sisbios_mode[mode_idx].xres;
+ u16 yres = sisbios_mode[mode_idx].yres;
ivideo->rate_idx = 0;
while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
@@ -672,14 +756,14 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
rate, sisfb_vrate[i-1].refresh);
ivideo->rate_idx = sisfb_vrate[i-1].idx;
ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
- }
+ }
break;
} else if((rate - sisfb_vrate[i].refresh) <= 2) {
DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- }
+ ivideo->rate_idx = sisfb_vrate[i].idx;
+ break;
+ }
}
i++;
}
@@ -695,252 +779,321 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
static BOOLEAN
sisfb_bridgeisslave(struct sis_video_info *ivideo)
{
- unsigned char P1_00;
+ unsigned char P1_00;
- if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
+ if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
+ return FALSE;
- inSISIDXREG(SISPART1,0x00,P1_00);
- if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
- return TRUE;
- } else {
- return FALSE;
- }
+ inSISIDXREG(SISPART1,0x00,P1_00);
+ if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+ ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
static BOOLEAN
sisfballowretracecrt1(struct sis_video_info *ivideo)
{
- u8 temp;
+ u8 temp;
- inSISIDXREG(SISCR,0x17,temp);
- if(!(temp & 0x80)) return FALSE;
+ inSISIDXREG(SISCR,0x17,temp);
+ if(!(temp & 0x80))
+ return FALSE;
- inSISIDXREG(SISSR,0x1f,temp);
- if(temp & 0xc0) return FALSE;
+ inSISIDXREG(SISSR,0x1f,temp);
+ if(temp & 0xc0)
+ return FALSE;
- return TRUE;
+ return TRUE;
}
static BOOLEAN
sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
{
- if(!sisfballowretracecrt1(ivideo)) return FALSE;
+ if(!sisfballowretracecrt1(ivideo))
+ return FALSE;
- if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
- else return FALSE;
+ if(inSISREG(SISINPSTAT) & 0x08)
+ return TRUE;
+ else
+ return FALSE;
}
static void
sisfbwaitretracecrt1(struct sis_video_info *ivideo)
{
- int watchdog;
+ int watchdog;
- if(!sisfballowretracecrt1(ivideo)) return;
+ if(!sisfballowretracecrt1(ivideo))
+ return;
- watchdog = 65536;
- while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
- watchdog = 65536;
- while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+ watchdog = 65536;
+ while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+ watchdog = 65536;
+ while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
}
static BOOLEAN
sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
{
- unsigned char temp, reg;
+ unsigned char temp, reg;
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: reg = 0x25; break;
- case SIS_315_VGA: reg = 0x30; break;
- default: return FALSE;
- }
+ switch(ivideo->sisvga_engine) {
+ case SIS_300_VGA: reg = 0x25; break;
+ case SIS_315_VGA: reg = 0x30; break;
+ default: return FALSE;
+ }
- inSISIDXREG(SISPART1, reg, temp);
- if(temp & 0x02) return TRUE;
- else return FALSE;
+ inSISIDXREG(SISPART1, reg, temp);
+ if(temp & 0x02)
+ return TRUE;
+ else
+ return FALSE;
}
static BOOLEAN
sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
{
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- if(sisfb_bridgeisslave(ivideo)) {
- return(sisfbcheckvretracecrt1(ivideo));
- } else {
- return(sisfbcheckvretracecrt2(ivideo));
- }
- }
- return(sisfbcheckvretracecrt1(ivideo));
+ if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+ if(!sisfb_bridgeisslave(ivideo)) {
+ return sisfbcheckvretracecrt2(ivideo);
+ }
+ }
+ return sisfbcheckvretracecrt1(ivideo);
}
static u32
sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
{
- u8 idx, reg1, reg2, reg3, reg4;
- u32 ret = 0;
-
- (*vcount) = (*hcount) = 0;
-
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_HBLANK |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: idx = 0x25; break;
- default:
- case SIS_315_VGA: idx = 0x30; break;
- }
- inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
- inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
- inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
- inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
- if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
- (*vcount) = reg3 | ((reg4 & 0x70) << 4);
- (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
- } else if(sisfballowretracecrt1(ivideo)) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- reg1 = inSISREG(SISINPSTAT);
- if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- inSISIDXREG(SISCR,0x20,reg1);
- inSISIDXREG(SISCR,0x1b,reg1);
- inSISIDXREG(SISCR,0x1c,reg2);
- inSISIDXREG(SISCR,0x1d,reg3);
- (*vcount) = reg2 | ((reg3 & 0x07) << 8);
- (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
- }
- return ret;
+ u8 idx, reg1, reg2, reg3, reg4;
+ u32 ret = 0;
+
+ (*vcount) = (*hcount) = 0;
+
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+
+ ret |= (FB_VBLANK_HAVE_VSYNC |
+ FB_VBLANK_HAVE_HBLANK |
+ FB_VBLANK_HAVE_VBLANK |
+ FB_VBLANK_HAVE_VCOUNT |
+ FB_VBLANK_HAVE_HCOUNT);
+ switch(ivideo->sisvga_engine) {
+ case SIS_300_VGA: idx = 0x25; break;
+ default:
+ case SIS_315_VGA: idx = 0x30; break;
+ }
+ inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+ inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+ inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+ inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+ if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+ if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
+ if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
+ (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+ (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+
+ } else if(sisfballowretracecrt1(ivideo)) {
+
+ ret |= (FB_VBLANK_HAVE_VSYNC |
+ FB_VBLANK_HAVE_VBLANK |
+ FB_VBLANK_HAVE_VCOUNT |
+ FB_VBLANK_HAVE_HCOUNT);
+ reg1 = inSISREG(SISINPSTAT);
+ if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+ if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+ inSISIDXREG(SISCR,0x20,reg1);
+ inSISIDXREG(SISCR,0x1b,reg1);
+ inSISIDXREG(SISCR,0x1c,reg2);
+ inSISIDXREG(SISCR,0x1d,reg3);
+ (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+ (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+ }
+
+ return ret;
}
static int
sisfb_myblank(struct sis_video_info *ivideo, int blank)
{
- u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
- BOOLEAN backlight = TRUE;
-
- switch(blank) {
- case FB_BLANK_UNBLANK: /* on */
- sr01 = 0x00;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_NORMAL: /* blank */
- sr01 = 0x20;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x80;
- cr63 = 0x40;
- p2_0 = 0x40;
- p1_13 = 0x80;
- backlight = FALSE;
- break;
- case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x40;
- cr63 = 0x40;
- p2_0 = 0x80;
- p1_13 = 0x40;
- backlight = FALSE;
- break;
- case FB_BLANK_POWERDOWN: /* off */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0xc0;
- cr63 = 0x40;
- p2_0 = 0xc0;
- p1_13 = 0xc0;
- backlight = FALSE;
- break;
- default:
- return 1;
- }
-
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
-
- if( (!ivideo->sisfb_thismonitor.datavalid) ||
- ((ivideo->sisfb_thismonitor.datavalid) &&
- (ivideo->sisfb_thismonitor.feature & 0xe0))) {
-
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
- }
-
- if(!(sisfb_bridgeisslave(ivideo))) {
- setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
- setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
- }
- }
-
- }
-
- if(ivideo->currentvbflags & CRT2_LCD) {
-
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
- if(backlight) {
- SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- } else {
- SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(ivideo->vbflags & VB_CHRONTEL) {
- if(backlight) {
- SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
- } else {
- SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
- }
- }
- }
-
- if(((ivideo->sisvga_engine == SIS_300_VGA) &&
- (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) &&
- ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
- setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
- }
-
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
-
- } else if(ivideo->currentvbflags & CRT2_VGA) {
-
- if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
-
- }
-
- return(0);
+ u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
+ BOOLEAN backlight = TRUE;
+
+ switch(blank) {
+ case FB_BLANK_UNBLANK: /* on */
+ sr01 = 0x00;
+ sr11 = 0x00;
+ sr1f = 0x00;
+ cr63 = 0x00;
+ p2_0 = 0x20;
+ p1_13 = 0x00;
+ backlight = TRUE;
+ break;
+ case FB_BLANK_NORMAL: /* blank */
+ sr01 = 0x20;
+ sr11 = 0x00;
+ sr1f = 0x00;
+ cr63 = 0x00;
+ p2_0 = 0x20;
+ p1_13 = 0x00;
+ backlight = TRUE;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0x80;
+ cr63 = 0x40;
+ p2_0 = 0x40;
+ p1_13 = 0x80;
+ backlight = FALSE;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0x40;
+ cr63 = 0x40;
+ p2_0 = 0x80;
+ p1_13 = 0x40;
+ backlight = FALSE;
+ break;
+ case FB_BLANK_POWERDOWN: /* off */
+ sr01 = 0x20;
+ sr11 = 0x08;
+ sr1f = 0xc0;
+ cr63 = 0x40;
+ p2_0 = 0xc0;
+ p1_13 = 0xc0;
+ backlight = FALSE;
+ break;
+ default:
+ return 1;
+ }
+
+ if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
+
+ if( (!ivideo->sisfb_thismonitor.datavalid) ||
+ ((ivideo->sisfb_thismonitor.datavalid) &&
+ (ivideo->sisfb_thismonitor.feature & 0xe0))) {
+
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+ }
+
+ if(!(sisfb_bridgeisslave(ivideo))) {
+ setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+ setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+ }
+ }
+
+ }
+
+ if(ivideo->currentvbflags & CRT2_LCD) {
+
+ if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+ if(backlight) {
+ SiS_SiS30xBLOn(&ivideo->SiS_Pr);
+ } else {
+ SiS_SiS30xBLOff(&ivideo->SiS_Pr);
+ }
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ if(backlight) {
+ SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
+ } else {
+ SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
+ }
+ }
+#endif
+ }
+
+ if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+ (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
+ ((ivideo->sisvga_engine == SIS_315_VGA) &&
+ ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
+ setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
+ }
+
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if((ivideo->vbflags2 & VB2_30xB) &&
+ (!(ivideo->vbflags2 & VB2_30xBDH))) {
+ setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
+ }
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+ if((ivideo->vbflags2 & VB2_30xB) &&
+ (!(ivideo->vbflags2 & VB2_30xBDH))) {
+ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+ }
+ }
+
+ } else if(ivideo->currentvbflags & CRT2_VGA) {
+
+ if(ivideo->vbflags2 & VB2_30xB) {
+ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+ }
+
+ }
+
+ return 0;
+}
+
+/* ------------- Callbacks from init.c/init301.c -------------- */
+
+#ifdef CONFIG_FB_SIS_300
+unsigned int
+sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u32 val = 0;
+
+ pci_read_config_dword(ivideo->nbridge, reg, &val);
+ return (unsigned int)val;
+}
+
+void
+sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+ pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
}
+unsigned int
+sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u32 val = 0;
+
+ if(!ivideo->lpcdev) return 0;
+
+ pci_read_config_dword(ivideo->lpcdev, reg, &val);
+ return (unsigned int)val;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+void
+sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+ pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
+}
+
+unsigned int
+sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
+{
+ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+ u16 val = 0;
+
+ if(!ivideo->lpcdev) return 0;
+
+ pci_read_config_word(ivideo->lpcdev, reg, &val);
+ return (unsigned int)val;
+}
+#endif
+
/* ----------- FBDev related routines for all series ----------- */
static int
@@ -952,7 +1105,7 @@ sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
static void
sisfb_set_vparms(struct sis_video_info *ivideo)
{
- switch(ivideo->video_bpp) {
+ switch(ivideo->video_bpp) {
case 8:
ivideo->DstColor = 0x0000;
ivideo->SiS310_AccelDepth = 0x00000000;
@@ -972,14 +1125,13 @@ sisfb_set_vparms(struct sis_video_info *ivideo)
ivideo->video_cmap_len = 16;
printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
ivideo->accel = 0;
- break;
- }
+ }
}
static int
sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
{
- int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3));
+ int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
if(maxyres > 32767) maxyres = 32767;
@@ -996,30 +1148,29 @@ sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
ivideo->scrnpitchCRT1 <<= 1;
}
}
-
}
static void
sisfb_set_pitch(struct sis_video_info *ivideo)
{
- BOOLEAN isslavemode = FALSE;
+ BOOLEAN isslavemode = FALSE;
unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
unsigned short HDisplay2 = ivideo->video_linelength >> 3;
- if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+ if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
- /* We need to set pitch for CRT1 if bridge is in slave mode, too */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
- outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
- setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+ /* We need to set pitch for CRT1 if bridge is in slave mode, too */
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
+ outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
+ setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
}
- /* We must not set the pitch for CRT2 if bridge is in slave mode */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
+ /* We must not set the pitch for CRT2 if bridge is in slave mode */
+ if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
- outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
- setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
- }
+ outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
+ setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+ }
}
static void
@@ -1056,12 +1207,41 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
}
static int
+sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
+{
+ unsigned short modeno = ivideo->mode_no;
+
+ /* >=2.6.12's fbcon clears the screen anyway */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ if(!clrscrn) modeno |= 0x80;
+#else
+ modeno |= 0x80;
+#endif
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ sisfb_pre_setmode(ivideo);
+
+ if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
+ printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
+ return -EINVAL;
+ }
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ sisfb_post_setmode(ivideo);
+
+ return 0;
+}
+
+
+static int
sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
unsigned int htotal = 0, vtotal = 0;
unsigned int drate = 0, hrate = 0;
- int found_mode = 0;
+ int found_mode = 0, ret;
int old_mode;
u32 pixclock;
@@ -1088,11 +1268,11 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
}
if(pixclock && htotal && vtotal) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ drate = 1000000000 / pixclock;
+ hrate = (drate * 1000) / htotal;
+ ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else {
- ivideo->refresh_rate = 60;
+ ivideo->refresh_rate = 60;
}
old_mode = ivideo->sisfb_mode_idx;
@@ -1113,6 +1293,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(found_mode) {
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+ ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
} else {
ivideo->sisfb_mode_idx = -1;
}
@@ -1131,10 +1312,10 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
+ printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ }
}
#endif
@@ -1143,24 +1324,9 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
#else
if(isactive) {
#endif
- sisfb_pre_setmode(ivideo);
-
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
- printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
- return -EINVAL;
- }
-
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
- sisfb_post_setmode(ivideo);
-
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
-
- sisfb_calc_pitch(ivideo, var);
- sisfb_set_pitch(ivideo);
-
+ /* If acceleration to be used? Need to know
+ * before pre/post_set_mode()
+ */
ivideo->accel = 0;
#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
#ifdef STUPID_ACCELF_TEXT_SHIT
@@ -1175,6 +1341,17 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
#endif
+ if((ret = sisfb_set_mode(ivideo, 1))) {
+ return ret;
+ }
+
+ ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+ ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+ ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+ sisfb_calc_pitch(ivideo, var);
+ sisfb_set_pitch(ivideo);
+
sisfb_set_vparms(ivideo);
ivideo->current_width = ivideo->video_width;
@@ -1186,572 +1363,79 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
ivideo->current_pixclock = var->pixclock;
ivideo->current_refresh_rate = ivideo->refresh_rate;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
+ ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
#endif
}
return 0;
}
-static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+static void
+sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
{
- unsigned int base;
-
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
-
- base = (var->yoffset * var->xres_virtual) + var->xoffset;
-
- /* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
- case 32:
- break;
- case 16:
- base >>= 1;
- break;
- case 8:
- default:
- base >>= 2;
- break;
- }
-
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- outSISIDXREG(SISCR, 0x0D, base & 0xFF);
+ outSISIDXREG(SISCR, 0x0D, base & 0xFF);
outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
if(ivideo->sisvga_engine == SIS_315_VGA) {
setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
}
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
- outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
- outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
- outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
- }
- }
- return 0;
}
-/* ------------ FBDev related routines for 2.4 series ----------- */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
static void
-sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
-{
- u16 VRE, VBE, VRS, VBS, VDE, VT;
- u16 HRE, HBE, HRS, HBS, HDE, HT;
- u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
- int A, B, C, D, E, F, temp;
- unsigned int hrate, drate, maxyres;
-
- inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
-
- if(sr_data & SIS_INTERLACED_MODE)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
-
- switch((sr_data & 0x1C) >> 2) {
- case SIS_8BPP_COLOR_MODE:
- var->bits_per_pixel = 8;
- break;
- case SIS_16BPP_COLOR_MODE:
- var->bits_per_pixel = 16;
- break;
- case SIS_32BPP_COLOR_MODE:
- var->bits_per_pixel = 32;
- break;
- }
-
- sisfb_bpp_to_var(ivideo, var);
-
- inSISIDXREG(SISSR, 0x0A, sr_data);
- inSISIDXREG(SISCR, 0x06, cr_data);
- inSISIDXREG(SISCR, 0x07, cr_data2);
-
- VT = (cr_data & 0xFF) |
- ((u16) (cr_data2 & 0x01) << 8) |
- ((u16) (cr_data2 & 0x20) << 4) |
- ((u16) (sr_data & 0x01) << 10);
- A = VT + 2;
-
- inSISIDXREG(SISCR, 0x12, cr_data);
-
- VDE = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x02) << 7) |
- ((u16) (cr_data2 & 0x40) << 3) |
- ((u16) (sr_data & 0x02) << 9);
- E = VDE + 1;
-
- inSISIDXREG(SISCR, 0x10, cr_data);
-
- VRS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x04) << 6) |
- ((u16) (cr_data2 & 0x80) << 2) |
- ((u16) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
-
- inSISIDXREG(SISCR, 0x15, cr_data);
- inSISIDXREG(SISCR, 0x09, cr_data3);
-
- if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
-
- VBS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x08) << 5) |
- ((u16) (cr_data3 & 0x20) << 4) |
- ((u16) (sr_data & 0x04) << 8);
-
- inSISIDXREG(SISCR, 0x16, cr_data);
-
- VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- inSISIDXREG(SISCR, 0x11, cr_data);
-
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->yres = E;
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- var->yres <<= 1;
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->yres >>= 1;
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
- }
-
- inSISIDXREG(SISSR, 0x0b, sr_data);
- inSISIDXREG(SISCR, 0x00, cr_data);
-
- HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
- A = HT + 5;
-
- inSISIDXREG(SISCR, 0x01, cr_data);
-
- HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
- E = HDE + 1;
-
- inSISIDXREG(SISCR, 0x04, cr_data);
-
- HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
- F = HRS - E - 3;
-
- inSISIDXREG(SISCR, 0x02, cr_data);
-
- HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
-
- inSISIDXREG(SISSR, 0x0c, sr_data);
- inSISIDXREG(SISCR, 0x03, cr_data);
- inSISIDXREG(SISCR, 0x05, cr_data2);
-
- HBE = (cr_data & 0x1f) |
- ((u16) (cr_data2 & 0x80) >> 2) |
- ((u16) (sr_data & 0x03) << 6);
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
-
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
-
- D = B - F - C;
-
- var->xres = E * 8;
- if(var->xres_virtual < var->xres) {
- var->xres_virtual = var->xres;
- }
-
- if((var->xres == 320) &&
- (var->yres == 200 || var->yres == 240)) {
- /* Terrible hack, but the correct CRTC data for
- * these modes only produces a black screen...
- */
- var->left_margin = (400 - 376);
- var->right_margin = (328 - 320);
- var->hsync_len = (376 - 328);
- } else {
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
- }
- var->activate = FB_ACTIVATE_NOW;
-
- var->sync = 0;
-
- mr_data = inSISREG(SISMISCR);
- if(mr_data & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
- if(mr_data & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
-
- VT += 2;
- VT <<= 1;
- HT = (HT + 5) * 8;
-
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- VT <<= 1;
- }
- hrate = ivideo->refresh_rate * VT / 2;
- drate = (hrate * HT) / 1000;
- var->pixclock = (u32) (1000000000 / drate);
-
- if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
- } else {
- var->yres_virtual = var->yres;
- }
-
-}
-
-static int
-sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *info)
+sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(regno >= ivideo->video_cmap_len) return 1;
-
- *red = ivideo->sis_palette[regno].red;
- *green = ivideo->sis_palette[regno].green;
- *blue = ivideo->sis_palette[regno].blue;
- *transp = 0;
-
- return 0;
-}
-
-static int
-sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(regno >= ivideo->video_cmap_len) return 1;
-
- ivideo->sis_palette[regno].red = red;
- ivideo->sis_palette[regno].green = green;
- ivideo->sis_palette[regno].blue = blue;
-
- switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- outSISREG(SISDACA, regno);
- outSISREG(SISDACD, (red >> 10));
- outSISREG(SISDACD, (green >> 10));
- outSISREG(SISDACD, (blue >> 10));
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
- outSISREG(SISDAC2D, (red >> 8));
- outSISREG(SISDAC2D, (green >> 8));
- outSISREG(SISDAC2D, (blue >> 8));
+ if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+ orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
+ outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
+ outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
+ outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
}
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- ivideo->sis_fbcon_cmap.cfb16[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
- break;
-#endif
- }
-
- return 0;
-}
-
-static void
-sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- struct display_switch *sw;
- struct fb_fix_screeninfo fix;
- long flags;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- sisfb_get_fix(&fix, con, info);
-
- display->var = *var;
- display->screen_base = (char *)ivideo->video_vbase;
- display->visual = fix.visual;
- display->type = fix.type;
- display->type_aux = fix.type_aux;
- display->ypanstep = fix.ypanstep;
- display->ywrapstep = fix.ywrapstep;
- display->line_length = fix.line_length;
- display->can_soft_blank = 1;
- display->inverse = ivideo->sisfb_inverse;
- display->next_line = fix.line_length;
-
- save_flags(flags);
-
- switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
- break;
-#endif
- default:sw = &fbcon_dummy;
- break;
- }
- memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
- display->dispsw = &ivideo->sisfb_sw;
-
- restore_flags(flags);
-
- if(ivideo->sisfb_ypan) {
- /* display->scrollmode = 0; */
- } else {
- display->scrollmode = SCROLL_YREDRAW;
- ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
- }
-}
-
-static void
-sisfb_do_install_cmap(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(con != ivideo->currcon) return;
-
- if(fb_display[con].cmap.len) {
- fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
- } else {
- int size = sisfb_get_cmap_len(&fb_display[con].var);
- fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
}
}
static int
-sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- if(con == -1) {
- memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
- } else {
- *var = fb_display[con].var;
- }
-
- if(ivideo->sisfb_fstn) {
- if(var->xres == 320 && var->yres == 480) var->yres = 240;
- }
-
- return 0;
-}
-
-static int
-sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
-
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
-
- if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
- sisfb_crtc_to_var(ivideo, var);
+ if(var->xoffset > (var->xres_virtual - var->xres)) {
return -EINVAL;
}
-
- sisfb_crtc_to_var(ivideo, var);
-
- sisfb_set_disp(con, var, info);
-
- if(info->changevar) {
- (*info->changevar)(con);
- }
-
- if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
- return err;
- }
-
- sisfb_do_install_cmap(con, info);
-
-#if 0 /* Why was this called here? */
- unsigned int cols, rows;
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-#endif
- return 0;
-}
-
-static int
-sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- if(con == ivideo->currcon) {
-
- return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
-
- } else if(display->cmap.len) {
-
- fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
-
- } else {
-
- int size = sisfb_get_cmap_len(&display->var);
- fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-
+ if(var->yoffset > (var->yres_virtual - var->yres)) {
+ return -EINVAL;
}
- return 0;
-}
+ ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
-static int
-sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- int err, size;
-
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
- size = sisfb_get_cmap_len(&display->var);
- if(display->cmap.len != size) {
- err = fb_alloc_cmap(&display->cmap, size, 0);
- if(err) return err;
- }
-
- if(con == ivideo->currcon) {
- return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
- } else {
- fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
- }
-
- return 0;
-}
-
-static int
-sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
-
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
-
- if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
- (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
- return -EINVAL;
+ /* calculate base bpp dep. */
+ switch(var->bits_per_pixel) {
+ case 32:
+ break;
+ case 16:
+ ivideo->current_base >>= 1;
+ break;
+ case 8:
+ default:
+ ivideo->current_base >>= 2;
+ break;
}
- if(con == ivideo->currcon) {
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
- }
+ ivideo->current_base += (ivideo->video_offset >> 2);
- fb_display[con].var.xoffset = var->xoffset;
- fb_display[con].var.yoffset = var->yoffset;
+ sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+ sisfb_set_base_CRT2(ivideo, ivideo->current_base);
return 0;
}
-static int
-sisfb_update_var(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
- return(sisfb_pan_var(ivideo, &fb_display[con].var));
-}
-
-static int
-sisfb_switch(int con, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int cols, rows;
-
- if(fb_display[ivideo->currcon].cmap.len) {
- fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
- }
-
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
-
- if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
- sizeof(struct fb_var_screeninfo))) {
- ivideo->currcon = con;
- return 1;
- }
-
- ivideo->currcon = con;
-
- sisfb_do_set_var(&fb_display[con].var, 1, info);
-
- sisfb_set_disp(con, &fb_display[con].var, info);
-
- sisfb_do_install_cmap(con, info);
-
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-
- sisfb_update_var(con, info);
+/* ------------ FBDev related routines for 2.4 series ----------- */
- return 1;
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static void
-sisfb_blank(int blank, struct fb_info *info)
-{
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+#include "sisfb_fbdev_2_4.h"
- sisfb_myblank(ivideo, blank);
-}
#endif
/* ------------ FBDev related routines for 2.6 series ----------- */
@@ -1761,13 +1445,13 @@ sisfb_blank(int blank, struct fb_info *info)
static int
sisfb_open(struct fb_info *info, int user)
{
- return 0;
+ return 0;
}
static int
sisfb_release(struct fb_info *info, int user)
{
- return 0;
+ return 0;
}
static int
@@ -1776,16 +1460,17 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
+ if(regno >= sisfb_get_cmap_len(&info->var))
+ return 1;
switch(info->var.bits_per_pixel) {
case 8:
- outSISREG(SISDACA, regno);
+ outSISREG(SISDACA, regno);
outSISREG(SISDACD, (red >> 10));
outSISREG(SISDACD, (green >> 10));
outSISREG(SISDACD, (blue >> 10));
if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
+ outSISREG(SISDAC2A, regno);
outSISREG(SISDAC2D, (red >> 8));
outSISREG(SISDAC2D, (green >> 8));
outSISREG(SISDAC2D, (blue >> 8));
@@ -1793,7 +1478,9 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
break;
case 16:
((u32 *)(info->pseudo_palette))[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
break;
case 32:
red >>= 8;
@@ -1811,13 +1498,13 @@ sisfb_set_par(struct fb_info *info)
{
int err;
- if((err = sisfb_do_set_var(&info->var, 1, info))) {
+ if((err = sisfb_do_set_var(&info->var, 1, info)))
return err;
- }
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
sisfb_get_fix(&info->fix, info->currcon, info);
#else
- sisfb_get_fix(&info->fix, -1, info);
+ sisfb_get_fix(&info->fix, -1, info);
#endif
return 0;
}
@@ -1829,7 +1516,7 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
unsigned int drate = 0, hrate = 0, maxyres;
int found_mode = 0;
- int refresh_rate, search_idx;
+ int refresh_rate, search_idx, tidx;
BOOLEAN recalc_clock = FALSE;
u32 pixclock;
@@ -1848,7 +1535,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
vtotal += var->yres;
vtotal <<= 1;
- } else vtotal += var->yres;
+ } else
+ vtotal += var->yres;
if(!(htotal) || !(vtotal)) {
SISFAIL("sisfb: no valid timing data");
@@ -1860,60 +1548,68 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if( (sisbios_mode[search_idx].xres == var->xres) &&
(sisbios_mode[search_idx].yres == var->yres) &&
(sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
+ if((tidx = sisfb_validate_mode(ivideo, search_idx,
+ ivideo->currentvbflags)) > 0) {
+ found_mode = 1;
+ search_idx = tidx;
+ break;
}
}
search_idx++;
}
if(!found_mode) {
- search_idx = 0;
+ search_idx = 0;
while(sisbios_mode[search_idx].mode_no[0] != 0) {
if( (var->xres <= sisbios_mode[search_idx].xres) &&
(var->yres <= sisbios_mode[search_idx].yres) &&
(var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
- if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
- }
+ if((tidx = sisfb_validate_mode(ivideo,search_idx,
+ ivideo->currentvbflags)) > 0) {
+ found_mode = 1;
+ search_idx = tidx;
+ break;
+ }
}
search_idx++;
- }
+ }
if(found_mode) {
- printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel,
+ printk(KERN_DEBUG
+ "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
+ var->xres, var->yres, var->bits_per_pixel,
sisbios_mode[search_idx].xres,
sisbios_mode[search_idx].yres,
var->bits_per_pixel);
var->xres = sisbios_mode[search_idx].xres;
- var->yres = sisbios_mode[search_idx].yres;
-
-
+ var->yres = sisbios_mode[search_idx].yres;
} else {
- printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n",
+ printk(KERN_ERR
+ "sisfb: Failed to find supported mode near %dx%dx%d\n",
var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
+ return -EINVAL;
}
}
- if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */
- ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
+ if( ((ivideo->vbflags2 & VB2_LVDS) ||
+ ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
(var->bits_per_pixel == 8) ) {
- refresh_rate = 60;
+ /* Slave modes on LVDS and 301B-DH */
+ refresh_rate = 60;
recalc_clock = TRUE;
- } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */
- (ivideo->current_vtotal == vtotal) &&
- (ivideo->current_pixclock == pixclock) ) {
+ } else if( (ivideo->current_htotal == htotal) &&
+ (ivideo->current_vtotal == vtotal) &&
+ (ivideo->current_pixclock == pixclock) ) {
+ /* x=x & y=y & c=c -> assume depth change */
drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */
- (ivideo->current_vtotal != vtotal) ) &&
- (ivideo->current_pixclock == var->pixclock) ) {
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ } else if( ( (ivideo->current_htotal != htotal) ||
+ (ivideo->current_vtotal != vtotal) ) &&
+ (ivideo->current_pixclock == var->pixclock) ) {
+ /* x!=x | y!=y & c=c -> invalid pixclock */
if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
- refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+ refresh_rate =
+ ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
} else if(ivideo->sisfb_parm_rate != -1) {
/* Sic, sisfb_parm_rate - want to know originally desired rate here */
refresh_rate = ivideo->sisfb_parm_rate;
@@ -1923,8 +1619,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
recalc_clock = TRUE;
} else if((pixclock) && (htotal) && (vtotal)) {
drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else if(ivideo->current_refresh_rate) {
refresh_rate = ivideo->current_refresh_rate;
recalc_clock = TRUE;
@@ -1937,72 +1633,72 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Eventually recalculate timing and clock */
if(recalc_clock) {
- if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
- var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
- &ivideo->sishw_ext,
+ if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
+ var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
sisbios_mode[search_idx].mode_no[ivideo->mni],
myrateindex));
- sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var);
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->pixclock <<= 1;
- }
+ sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
+ sisbios_mode[search_idx].mode_no[ivideo->mni],
+ myrateindex, var);
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->pixclock <<= 1;
+ }
}
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
- myrateindex, refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
+ myrateindex, refresh_rate)) {
+ printk(KERN_INFO
+ "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ }
}
/* Adapt RGB settings */
sisfb_bpp_to_var(ivideo, var);
-
+
/* Sanity check for offsets */
if(var->xoffset < 0) var->xoffset = 0;
if(var->yoffset < 0) var->yoffset = 0;
- if(var->xres > var->xres_virtual) {
- var->xres_virtual = var->xres;
- }
+ if(var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
+ maxyres = sisfb_calc_maxyres(ivideo, var);
+ if(ivideo->sisfb_max) {
+ var->yres_virtual = maxyres;
+ } else {
+ if(var->yres_virtual > maxyres) {
+ var->yres_virtual = maxyres;
+ }
+ }
+ if(var->yres_virtual <= var->yres) {
+ var->yres_virtual = var->yres;
+ }
} else {
- if(var->yres != var->yres_virtual) {
- var->yres_virtual = var->yres;
- }
- var->xoffset = 0;
- var->yoffset = 0;
+ if(var->yres != var->yres_virtual) {
+ var->yres_virtual = var->yres;
+ }
+ var->xoffset = 0;
+ var->yoffset = 0;
}
-
+
/* Truncate offsets to maximum if too high */
if(var->xoffset > var->xres_virtual - var->xres) {
- var->xoffset = var->xres_virtual - var->xres - 1;
+ var->xoffset = var->xres_virtual - var->xres - 1;
}
if(var->yoffset > var->yres_virtual - var->yres) {
- var->yoffset = var->yres_virtual - var->yres - 1;
+ var->yoffset = var->yres_virtual - var->yres - 1;
}
-
+
/* Set everything else to 0 */
- var->red.msb_right =
- var->green.msb_right =
- var->blue.msb_right =
- var->transp.offset =
- var->transp.length =
- var->transp.msb_right = 0;
+ var->red.msb_right =
+ var->green.msb_right =
+ var->blue.msb_right =
+ var->transp.offset =
+ var->transp.length =
+ var->transp.msb_right = 0;
return 0;
}
@@ -2013,21 +1709,21 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
int err;
- if(var->xoffset > (var->xres_virtual - var->xres)) {
+ if(var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
+
+ if(var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
- }
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
+ if(var->vmode & FB_VMODE_YWRAP)
+ return -EINVAL;
if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual) {
+ var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
- }
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
+ if((err = sisfb_pan_var(ivideo, var)) < 0)
+ return err;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -2040,7 +1736,7 @@ sisfb_blank(int blank, struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- return(sisfb_myblank(ivideo, blank));
+ return sisfb_myblank(ivideo, blank);
}
#endif
@@ -2056,153 +1752,184 @@ sisfb_ioctl(struct inode *inode, struct file *file,
struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct sis_memreq sismemreq;
- struct fb_vblank sisvbblank;
- sisfb_info x;
+ struct sis_memreq sismemreq;
+ struct fb_vblank sisvbblank;
u32 gpu32 = 0;
#ifndef __user
#define __user
#endif
u32 __user *argp = (u32 __user *)arg;
- switch (cmd) {
+ switch(cmd) {
case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO)) {
+ if(!capable(CAP_SYS_RAWIO))
return -EPERM;
- }
- if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) {
- return -EFAULT;
- }
+
+ if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
+ return -EFAULT;
+
sis_malloc(&sismemreq);
+
if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
sis_free((u32)sismemreq.offset);
- return -EFAULT;
+ return -EFAULT;
}
break;
case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO)) {
+ if(!capable(CAP_SYS_RAWIO))
return -EPERM;
- }
- if(get_user(gpu32, argp)) {
+
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
sis_free(gpu32);
break;
case FBIOGET_VBLANK:
sisvbblank.count = 0;
sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
- if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) {
+
+ if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
return -EFAULT;
- }
+
break;
case SISFB_GET_INFO_SIZE:
- return put_user(sizeof(sisfb_info), argp);
+ return put_user(sizeof(struct sisfb_info), argp);
case SISFB_GET_INFO_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_INFO: /* For communication with X driver */
- x.sisfb_id = SISFB_ID;
- x.sisfb_version = VER_MAJOR;
- x.sisfb_revision = VER_MINOR;
- x.sisfb_patchlevel = VER_LEVEL;
- x.chip_id = ivideo->chip_id;
- x.memory = ivideo->video_size / 1024;
- x.heapstart = ivideo->heapstart / 1024;
+ ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
+ ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
+ ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
+ ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
+ ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
+ ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
+ ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
+ ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
if(ivideo->modechanged) {
- x.fbvidmode = ivideo->mode_no;
+ ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
} else {
- x.fbvidmode = ivideo->modeprechange;
- }
- x.sisfb_caps = ivideo->caps;
- x.sisfb_tqlen = 512; /* yet fixed */
- x.sisfb_pcibus = ivideo->pcibus;
- x.sisfb_pcislot = ivideo->pcislot;
- x.sisfb_pcifunc = ivideo->pcifunc;
- x.sisfb_lcdpdc = ivideo->detectedpdc;
- x.sisfb_lcdpdca = ivideo->detectedpdca;
- x.sisfb_lcda = ivideo->detectedlcda;
- x.sisfb_vbflags = ivideo->vbflags;
- x.sisfb_currentvbflags = ivideo->currentvbflags;
- x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
- x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
- x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
- x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
- x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
- x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
- x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
- x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
- x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
- x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
-
- if(copy_to_user((void __user *)arg, &x, sizeof(x))) {
- return -EFAULT;
+ ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
}
+ ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
+ ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
+ ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
+ ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
+ ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
+ ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
+ ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
+ ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
+ ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
+ ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
+ ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+ ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+ ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+ ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+ ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+ ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+ ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+ ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+ ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
+ ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
+ ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
+ ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
+ ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
+ ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
+ ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
+
+ if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
+ sizeof(ivideo->sisfb_infoblock)))
+ return -EFAULT;
+
break;
case SISFB_GET_VBRSTATUS_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_VBRSTATUS:
- if(sisfb_CheckVBRetrace(ivideo)) {
+ if(sisfb_CheckVBRetrace(ivideo))
return put_user((u32)1, argp);
- } else {
+ else
return put_user((u32)0, argp);
- }
case SISFB_GET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_GET_AUTOMAXIMIZE:
- if(ivideo->sisfb_max) return put_user((u32)1, argp);
- else return put_user((u32)0, argp);
+ if(ivideo->sisfb_max)
+ return put_user((u32)1, argp);
+ else
+ return put_user((u32)0, argp);
case SISFB_SET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
+ if(ivideo->warncount++ < 10)
+ printk(KERN_INFO
+ "sisfb: Deprecated ioctl call received - update your application!\n");
case SISFB_SET_AUTOMAXIMIZE:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
ivideo->sisfb_max = (gpu32) ? 1 : 0;
break;
case SISFB_SET_TVPOSOFFSET:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
break;
case SISFB_GET_TVPOSOFFSET:
- return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
- argp);
+ return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
+ argp);
+
+ case SISFB_COMMAND:
+ if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
+ sizeof(struct sisfb_cmd)))
+ return -EFAULT;
+
+ sisfb_handle_command(ivideo, &ivideo->sisfb_command);
+
+ if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
+ sizeof(struct sisfb_cmd)))
+ return -EFAULT;
+
+ break;
case SISFB_SET_LOCK:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+ if(get_user(gpu32, argp))
return -EFAULT;
- }
+
ivideo->sisfblocked = (gpu32) ? 1 : 0;
break;
default:
+#ifdef SIS_NEW_CONFIG_COMPAT
return -ENOIOCTLCMD;
+#else
+ return -EINVAL;
+#endif
}
return 0;
}
-#ifdef CONFIG_COMPAT
-static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info)
+#ifdef SIS_NEW_CONFIG_COMPAT
+static long
+sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info)
{
int ret;
+
lock_kernel();
ret = sisfb_ioctl(NULL, f, cmd, arg, info);
unlock_kernel();
@@ -2219,7 +1946,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
strcpy(fix->id, ivideo->myid);
- fix->smem_start = ivideo->video_base;
+ fix->smem_start = ivideo->video_base + ivideo->video_offset;
fix->smem_len = ivideo->sisfb_mem;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
@@ -2231,11 +1958,17 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
fix->mmio_start = ivideo->mmio_base;
fix->mmio_len = ivideo->mmio_size;
if(ivideo->sisvga_engine == SIS_300_VGA) {
- fix->accel = FB_ACCEL_SIS_GLAMOUR;
- } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
- fix->accel = FB_ACCEL_SIS_XABRE;
+ fix->accel = FB_ACCEL_SIS_GLAMOUR;
+ } else if((ivideo->chip == SIS_330) ||
+ (ivideo->chip == SIS_760) ||
+ (ivideo->chip == SIS_761)) {
+ fix->accel = FB_ACCEL_SIS_XABRE;
+ } else if(ivideo->chip == XGI_20) {
+ fix->accel = FB_ACCEL_XGI_VOLARI_Z;
+ } else if(ivideo->chip >= XGI_40) {
+ fix->accel = FB_ACCEL_XGI_VOLARI_V;
} else {
- fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
+ fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
}
return 0;
@@ -2251,40 +1984,41 @@ static struct fb_ops sisfb_ops = {
.fb_set_var = sisfb_set_var,
.fb_get_cmap = sisfb_get_cmap,
.fb_set_cmap = sisfb_set_cmap,
- .fb_pan_display = sisfb_pan_display,
+ .fb_pan_display = sisfb_pan_display,
.fb_ioctl = sisfb_ioctl
};
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static struct fb_ops sisfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = sisfb_open,
- .fb_release = sisfb_release,
- .fb_check_var = sisfb_check_var,
- .fb_set_par = sisfb_set_par,
- .fb_setcolreg = sisfb_setcolreg,
- .fb_pan_display = sisfb_pan_display,
- .fb_blank = sisfb_blank,
- .fb_fillrect = fbcon_sis_fillrect,
- .fb_copyarea = fbcon_sis_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
- .fb_sync = fbcon_sis_sync,
- .fb_ioctl = sisfb_ioctl,
-#ifdef CONFIG_COMPAT
- .fb_compat_ioctl = sisfb_compat_ioctl,
+ .owner = THIS_MODULE,
+ .fb_open = sisfb_open,
+ .fb_release = sisfb_release,
+ .fb_check_var = sisfb_check_var,
+ .fb_set_par = sisfb_set_par,
+ .fb_setcolreg = sisfb_setcolreg,
+ .fb_pan_display = sisfb_pan_display,
+ .fb_blank = sisfb_blank,
+ .fb_fillrect = fbcon_sis_fillrect,
+ .fb_copyarea = fbcon_sis_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+ .fb_sync = fbcon_sis_sync,
+#ifdef SIS_NEW_CONFIG_COMPAT
+ .fb_compat_ioctl= sisfb_compat_ioctl,
#endif
+ .fb_ioctl = sisfb_ioctl
};
#endif
/* ---------------- Chip generation dependent routines ---------------- */
-static struct pci_dev * sisfb_get_northbridge(int basechipid)
+static struct pci_dev * __devinit
+sisfb_get_northbridge(int basechipid)
{
struct pci_dev *pdev = NULL;
int nbridgenum, nbridgeidx, i;
- const unsigned short nbridgeids[] = {
+ static const unsigned short nbridgeids[] = {
PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
PCI_DEVICE_ID_SI_730,
@@ -2292,13 +2026,14 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
PCI_DEVICE_ID_SI_651,
PCI_DEVICE_ID_SI_740,
- PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */
+ PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
PCI_DEVICE_ID_SI_741,
PCI_DEVICE_ID_SI_660,
- PCI_DEVICE_ID_SI_760
+ PCI_DEVICE_ID_SI_760,
+ PCI_DEVICE_ID_SI_761
};
- switch(basechipid) {
+ switch(basechipid) {
#ifdef CONFIG_FB_SIS_300
case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
@@ -2306,35 +2041,40 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
#ifdef CONFIG_FB_SIS_315
case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
- case SIS_660: nbridgeidx = 7; nbridgenum = 4; break;
+ case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
#endif
default: return NULL;
}
for(i = 0; i < nbridgenum; i++) {
- if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
+ if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
+ nbridgeids[nbridgeidx+i], NULL)))
+ break;
}
return pdev;
}
-static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
+static int __devinit
+sisfb_get_dram_size(struct sis_video_info *ivideo)
{
#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
u8 reg;
#endif
ivideo->video_size = 0;
+ ivideo->UMAsize = ivideo->LFBsize = 0;
switch(ivideo->chip) {
#ifdef CONFIG_FB_SIS_300
case SIS_300:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = ((reg & 0x3F) + 1) << 20;
break;
case SIS_540:
case SIS_630:
case SIS_730:
- if(!ivideo->nbridge) return -1;
- pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+ if(!ivideo->nbridge)
+ return -1;
+ pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
break;
#endif
@@ -2342,45 +2082,68 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
case SIS_315H:
case SIS_315PRO:
case SIS_315:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
switch((reg >> 2) & 0x03) {
case 0x01:
case 0x03:
- ivideo->video_size <<= 1;
- break;
+ ivideo->video_size <<= 1;
+ break;
case 0x02:
- ivideo->video_size += (ivideo->video_size/2);
+ ivideo->video_size += (ivideo->video_size/2);
}
- break;
+ break;
case SIS_330:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
if(reg & 0x0c) ivideo->video_size <<= 1;
- break;
+ break;
case SIS_550:
case SIS_650:
case SIS_740:
- inSISIDXREG(SISSR, 0x14, reg);
+ inSISIDXREG(SISSR, 0x14, reg);
ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
break;
case SIS_661:
case SIS_741:
- inSISIDXREG(SISCR, 0x79, reg);
+ inSISIDXREG(SISCR, 0x79, reg);
ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- break;
+ break;
case SIS_660:
case SIS_760:
+ case SIS_761:
inSISIDXREG(SISCR, 0x79, reg);
reg = (reg & 0xf0) >> 4;
- if(reg) ivideo->video_size = (1 << reg) << 20;
+ if(reg) {
+ ivideo->video_size = (1 << reg) << 20;
+ ivideo->UMAsize = ivideo->video_size;
+ }
inSISIDXREG(SISCR, 0x78, reg);
reg &= 0x30;
if(reg) {
- if(reg == 0x10) ivideo->video_size += (32 << 20);
- else ivideo->video_size += (64 << 20);
+ if(reg == 0x10) {
+ ivideo->LFBsize = (32 << 20);
+ } else {
+ ivideo->LFBsize = (64 << 20);
+ }
+ ivideo->video_size += ivideo->LFBsize;
}
- break;
+ break;
+ case SIS_340:
+ case XGI_20:
+ case XGI_40:
+ inSISIDXREG(SISSR, 0x14, reg);
+ ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+ if(ivideo->chip != XGI_20) {
+ reg = (reg & 0x0c) >> 2;
+ if(ivideo->revision_id == 2) {
+ if(reg & 0x01) reg = 0x02;
+ else reg = 0x00;
+ }
+ if(reg == 0x02) ivideo->video_size <<= 1;
+ else if(reg == 0x03) ivideo->video_size <<= 2;
+ }
+ break;
#endif
default:
return -1;
@@ -2390,17 +2153,24 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
/* -------------- video bridge device detection --------------- */
-static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_detect_VB_connect(struct sis_video_info *ivideo)
{
u8 cr32, temp;
+ /* No CRT2 on XGI Z7 */
+ if(ivideo->chip == XGI_20) {
+ ivideo->sisfb_crt1off = 0;
+ return;
+ }
+
#ifdef CONFIG_FB_SIS_300
if(ivideo->sisvga_engine == SIS_300_VGA) {
inSISIDXREG(SISSR, 0x17, temp);
if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
/* PAL/NTSC is stored on SR16 on such machines */
if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
- inSISIDXREG(SISSR, 0x16, temp);
+ inSISIDXREG(SISSR, 0x16, temp);
if(temp & 0x20)
ivideo->vbflags |= TV_PAL;
else
@@ -2435,28 +2205,29 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
if(ivideo->sisfb_tvplug != -1) {
if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+ (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
if(ivideo->sisfb_tvplug & TV_YPBPR) {
- ivideo->sisfb_tvplug = -1;
+ ivideo->sisfb_tvplug = -1;
printk(KERN_ERR "sisfb: YPbPr not supported\n");
}
}
}
if(ivideo->sisfb_tvplug != -1) {
if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+ (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
if(ivideo->sisfb_tvplug & TV_HIVISION) {
- ivideo->sisfb_tvplug = -1;
+ ivideo->sisfb_tvplug = -1;
printk(KERN_ERR "sisfb: HiVision not supported\n");
}
}
}
if(ivideo->sisfb_tvstd != -1) {
- if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
- (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+ if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
+ (!((ivideo->sisvga_engine == SIS_315_VGA) &&
+ (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
- ivideo->sisfb_tvstd = -1;
- printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+ ivideo->sisfb_tvstd = -1;
+ printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
}
}
}
@@ -2468,7 +2239,7 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
- else {
+ else {
if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
}
@@ -2485,165 +2256,44 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
}
if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
if(ivideo->sisvga_engine == SIS_300_VGA) {
- inSISIDXREG(SISSR, 0x38, temp);
+ inSISIDXREG(SISSR, 0x38, temp);
if(temp & 0x01) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
- inSISIDXREG(SISSR, 0x38, temp);
+ inSISIDXREG(SISSR, 0x38, temp);
if(temp & 0x01) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
- } else {
- inSISIDXREG(SISCR, 0x79, temp);
+ } else {
+ inSISIDXREG(SISCR, 0x79, temp);
if(temp & 0x20) ivideo->vbflags |= TV_PAL;
else ivideo->vbflags |= TV_NTSC;
- }
+ }
}
}
/* Copy forceCRT1 option to CRT1off if option is given */
- if(ivideo->sisfb_forcecrt1 != -1) {
- ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
- }
-}
-
-static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
-{
- char stdstr[] = "sisfb: Detected";
- char bridgestr[] = "video bridge";
- u8 vb_chipid;
- u8 reg;
-
- inSISIDXREG(SISPART4, 0x00, vb_chipid);
- switch(vb_chipid) {
- case 0x01:
- inSISIDXREG(SISPART4, 0x01, reg);
- if(reg < 0xb0) {
- ivideo->vbflags |= VB_301;
- printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
- } else if(reg < 0xc0) {
- ivideo->vbflags |= VB_301B;
- inSISIDXREG(SISPART4,0x23,reg);
- if(!(reg & 0x02)) {
- ivideo->vbflags |= VB_30xBDH;
- printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
- } else {
- printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
- }
- } else if(reg < 0xd0) {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
- } else if(reg < 0xe0) {
- ivideo->vbflags |= VB_301LV;
- printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
- } else if(reg <= 0xe1) {
- inSISIDXREG(SISPART4,0x39,reg);
- if(reg == 0xff) {
- ivideo->vbflags |= VB_302LV;
- printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
- } else {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
-#if 0
- ivideo->vbflags |= VB_302ELV;
- printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
-#endif
- }
- }
- break;
- case 0x02:
- ivideo->vbflags |= VB_302B;
- printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
- break;
- }
-
- if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
- inSISIDXREG(SISCR, 0x37, reg);
- reg &= SIS_EXTERNAL_CHIP_MASK;
- reg >>= 1;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
- switch(reg) {
- case SIS_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS_EXTERNAL_CHIP_TRUMPION:
- ivideo->vbflags |= VB_TRUMPION;
- break;
- case SIS_EXTERNAL_CHIP_CHRONTEL:
- ivideo->vbflags |= VB_CHRONTEL;
- break;
- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
-#endif
- } else if(ivideo->chip < SIS_661) {
-#ifdef CONFIG_FB_SIS_315
- switch (reg) {
- case SIS310_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
- } else if(ivideo->chip >= SIS_661) {
-#ifdef CONFIG_FB_SIS_315
- inSISIDXREG(SISCR, 0x38, reg);
- reg >>= 5;
- switch(reg) {
- case 0x02:
- ivideo->vbflags |= VB_LVDS;
- break;
- case 0x03:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- case 0x04:
- ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
- }
- if(ivideo->vbflags & VB_LVDS) {
- printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
- }
- if(ivideo->vbflags & VB_TRUMPION) {
- printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
- }
- if(ivideo->vbflags & VB_CHRONTEL) {
- printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
- }
- if(ivideo->vbflags & VB_CONEXANT) {
- printk(KERN_INFO "%s Conexant external device\n", stdstr);
- }
- }
-
- if(ivideo->vbflags & VB_SISBRIDGE) {
- SiS_Sense30x(ivideo);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- SiS_SenseCh(ivideo);
+ if(ivideo->sisfb_forcecrt1 != -1) {
+ ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
}
}
/* ------------------ Sensing routines ------------------ */
-static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
+static BOOLEAN __devinit
+sisfb_test_DDC1(struct sis_video_info *ivideo)
{
unsigned short old;
int count = 48;
old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
do {
- if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
+ if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
} while(count--);
return (count == -1) ? FALSE : TRUE;
}
-static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_sense_crt1(struct sis_video_info *ivideo)
{
BOOLEAN mustwait = FALSE;
u8 sr1F, cr17;
@@ -2699,7 +2349,8 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
if(temp == 0xffff) {
i = 3;
do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+ ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
} while(((temp == 0) || (temp == 0xffff)) && i--);
if((temp == 0) || (temp == 0xffff)) {
@@ -2723,7 +2374,96 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
}
/* Determine and detect attached devices on SiS30x */
-static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
+static void __devinit
+SiS_SenseLCD(struct sis_video_info *ivideo)
+{
+ unsigned char buffer[256];
+ unsigned short temp, realcrtno, i;
+ u8 reg, cr37 = 0, paneltype = 0;
+ u16 xres, yres;
+
+ ivideo->SiS_Pr.PanelSelfDetected = FALSE;
+
+ /* LCD detection only for TMDS bridges */
+ if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+ return;
+ if(ivideo->vbflags2 & VB2_30xBDH)
+ return;
+
+ /* If LCD already set up by BIOS, skip it */
+ inSISIDXREG(SISCR, 0x32, reg);
+ if(reg & 0x08)
+ return;
+
+ realcrtno = 1;
+ if(ivideo->SiS_Pr.DDCPortMixup)
+ realcrtno = 0;
+
+ /* Check DDC capabilities */
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+ realcrtno, 0, &buffer[0], ivideo->vbflags2);
+
+ if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+ return;
+
+ /* Read DDC data */
+ i = 3; /* Number of retrys */
+ do {
+ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+ ivideo->sisvga_engine, realcrtno, 1,
+ &buffer[0], ivideo->vbflags2);
+ } while((temp) && i--);
+
+ if(temp)
+ return;
+
+ /* No digital device */
+ if(!(buffer[0x14] & 0x80))
+ return;
+
+ /* First detailed timing preferred timing? */
+ if(!(buffer[0x18] & 0x02))
+ return;
+
+ xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
+ yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
+
+ switch(xres) {
+ case 1024:
+ if(yres == 768)
+ paneltype = 0x02;
+ break;
+ case 1280:
+ if(yres == 1024)
+ paneltype = 0x03;
+ break;
+ case 1600:
+ if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+ paneltype = 0x0b;
+ break;
+ }
+
+ if(!paneltype)
+ return;
+
+ if(buffer[0x23])
+ cr37 |= 0x10;
+
+ if((buffer[0x47] & 0x18) == 0x18)
+ cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
+ else
+ cr37 |= 0xc0;
+
+ outSISIDXREG(SISCR, 0x36, paneltype);
+ cr37 &= 0xf1;
+ setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
+ orSISIDXREG(SISCR, 0x32, 0x08);
+
+ ivideo->SiS_Pr.PanelSelfDetected = TRUE;
+}
+
+static int __devinit
+SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
{
int temp, mytest, result, i, j;
@@ -2749,10 +2489,11 @@ static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 tes
}
if((result == 0) || (result >= 2)) break;
}
- return(result);
+ return result;
}
-static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
+static void __devinit
+SiS_Sense30x(struct sis_video_info *ivideo)
{
u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
u16 svhs=0, svhs_c=0;
@@ -2762,36 +2503,51 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
char stdstr[] = "sisfb: Detected";
char tvstr[] = "TV connected to";
- if(ivideo->vbflags & VB_301) {
+ if(ivideo->vbflags2 & VB2_301) {
svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
inSISIDXREG(SISPART4,0x01,myflag);
if(myflag & 0x04) {
svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
}
- } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+ } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
- } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+ } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
svhs = 0x0200; cvbs = 0x0100;
- } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+ } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
- } else return;
+ } else
+ return;
vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
svhs_c = 0x0408; cvbs_c = 0x0808;
}
+
biosflag = 2;
+ if(ivideo->haveXGIROM) {
+ biosflag = ivideo->bios_abase[0x58] & 0x03;
+ } else if(ivideo->newrom) {
+ if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
+ } else if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->bios_abase) {
+ biosflag = ivideo->bios_abase[0xfe] & 0x03;
+ }
+ }
if(ivideo->chip == SIS_300) {
inSISIDXREG(SISSR,0x3b,myflag);
if(!(myflag & 0x01)) vga2 = vga2_c = 0;
}
+ if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
+ vga2 = vga2_c = 0;
+ }
+
inSISIDXREG(SISSR,0x1e,backupSR_1e);
orSISIDXREG(SISSR,0x1e,0x20);
inSISIDXREG(SISPART4,0x0d,backupP4_0d);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xC) {
setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
} else {
orSISIDXREG(SISPART4,0x0d,0x04);
@@ -2802,11 +2558,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
inSISIDXREG(SISPART2,0x4d,backupP2_4d);
- if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+ if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
}
- if(!(ivideo->vbflags & VB_301C)) {
+ if(!(ivideo->vbflags2 & VB2_30xCLV)) {
SISDoSense(ivideo, 0, 0);
}
@@ -2826,12 +2582,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
andSISIDXREG(SISCR, 0x32, 0x3f);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xCLV) {
orSISIDXREG(SISPART4,0x0d,0x04);
}
- if((ivideo->sisvga_engine == SIS_315_VGA) &&
- (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+ if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
if((result = SISDoSense(ivideo, svhs, 0x0604))) {
@@ -2864,7 +2619,7 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
outSISIDXREG(SISPART4,0x0d,backupP4_0d);
outSISIDXREG(SISSR,0x1e,backupSR_1e);
- if(ivideo->vbflags & VB_301C) {
+ if(ivideo->vbflags2 & VB2_30xCLV) {
inSISIDXREG(SISPART2,0x00,biosflag);
if(biosflag & 0x20) {
for(myflag = 2; myflag > 0; myflag--) {
@@ -2878,7 +2633,8 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
}
/* Determine and detect attached TV's on Chrontel */
-static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
+static void __devinit
+SiS_SenseCh(struct sis_video_info *ivideo)
{
#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
u8 temp1, temp2;
@@ -2899,7 +2655,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
/* See Chrontel TB31 for explanation */
temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
}
temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
@@ -2909,15 +2665,15 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
/* Read power status */
temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
if((temp1 & 0x03) != 0x03) {
- /* Power all outputs */
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+ /* Power all outputs */
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
}
/* Sense connected TV devices */
for(i = 0; i < 3; i++) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
if(!(temp1 & 0x08)) test[i] = 0x02;
@@ -2930,7 +2686,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
else if(test[0] == test[2]) temp1 = test[0];
else if(test[1] == test[2]) temp1 = test[1];
else {
- printk(KERN_INFO
+ printk(KERN_INFO
"sisfb: TV detection unreliable - test results varied\n");
temp1 = test[2];
}
@@ -2945,11 +2701,11 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
orSISIDXREG(SISCR, 0x32, 0x01);
andSISIDXREG(SISCR, 0x32, ~0x06);
} else {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
andSISIDXREG(SISCR, 0x32, ~0x07);
}
} else if(temp1 == 0) {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
andSISIDXREG(SISCR, 0x32, ~0x07);
}
/* Set general purpose IO for Chrontel communication */
@@ -2960,19 +2716,19 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
#ifdef CONFIG_FB_SIS_315
ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
- temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+ temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
temp2 |= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 ^= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
- temp1 = 0;
+ SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
+ temp1 = 0;
if(temp2 & 0x02) temp1 |= 0x01;
if(temp2 & 0x10) temp1 |= 0x01;
if(temp2 & 0x04) temp1 |= 0x02;
@@ -2983,18 +2739,18 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
ivideo->vbflags |= TV_AVIDEO;
orSISIDXREG(SISCR, 0x32, 0x01);
andSISIDXREG(SISCR, 0x32, ~0x06);
- break;
+ break;
case 0x02:
printk(KERN_INFO "%s SVIDEO output\n", stdstr);
ivideo->vbflags |= TV_SVIDEO;
orSISIDXREG(SISCR, 0x32, 0x02);
andSISIDXREG(SISCR, 0x32, ~0x05);
- break;
+ break;
case 0x04:
printk(KERN_INFO "%s SCART output\n", stdstr);
orSISIDXREG(SISCR, 0x32, 0x04);
andSISIDXREG(SISCR, 0x32, ~0x03);
- break;
+ break;
default:
andSISIDXREG(SISCR, 0x32, ~0x07);
}
@@ -3002,165 +2758,589 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
}
}
-/* ------------------------ Heap routines -------------------------- */
-
-static u32 __devinit
-sisfb_getheapstart(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_get_VB_type(struct sis_video_info *ivideo)
{
- u32 ret = ivideo->sisfb_parm_mem * 1024;
- u32 max = ivideo->video_size - ivideo->hwcursor_size;
- u32 def;
+ char stdstr[] = "sisfb: Detected";
+ char bridgestr[] = "video bridge";
+ u8 vb_chipid;
+ u8 reg;
- /* Calculate heap start = end of memory for console
- *
- * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
- * C = console, D = heap, H = HWCursor, Q = cmd-queue
- *
- * Basically given by "mem" parameter
- *
- * maximum = videosize - cmd_queue - hwcursor
- * (results in a heap of size 0)
- * default = SiS 300: depends on videosize
- * SiS 315/330: 32k below max
- */
+ /* No CRT2 on XGI Z7 */
+ if(ivideo->chip == XGI_20)
+ return;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- max -= TURBO_QUEUE_AREA_SIZE;
- if(ivideo->video_size > 0x1000000) {
- def = 0xc00000;
- } else if(ivideo->video_size > 0x800000) {
- def = 0x800000;
- } else {
- def = 0x400000;
- }
- } else {
- max -= COMMAND_QUEUE_AREA_SIZE;
- def = max - 0x8000;
+ inSISIDXREG(SISPART4, 0x00, vb_chipid);
+ switch(vb_chipid) {
+ case 0x01:
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if(reg < 0xb0) {
+ ivideo->vbflags |= VB_301; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301;
+ printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
+ } else if(reg < 0xc0) {
+ ivideo->vbflags |= VB_301B; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301B;
+ inSISIDXREG(SISPART4,0x23,reg);
+ if(!(reg & 0x02)) {
+ ivideo->vbflags |= VB_30xBDH; /* Deprecated */
+ ivideo->vbflags2 |= VB2_30xBDH;
+ printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
+ } else {
+ printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+ }
+ } else if(reg < 0xd0) {
+ ivideo->vbflags |= VB_301C; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301C;
+ printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
+ } else if(reg < 0xe0) {
+ ivideo->vbflags |= VB_301LV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301LV;
+ printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
+ } else if(reg <= 0xe1) {
+ inSISIDXREG(SISPART4,0x39,reg);
+ if(reg == 0xff) {
+ ivideo->vbflags |= VB_302LV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302LV;
+ printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+ } else {
+ ivideo->vbflags |= VB_301C; /* Deprecated */
+ ivideo->vbflags2 |= VB2_301C;
+ printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0
+ ivideo->vbflags |= VB_302ELV; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302ELV;
+ printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif
+ }
+ }
+ break;
+ case 0x02:
+ ivideo->vbflags |= VB_302B; /* Deprecated */
+ ivideo->vbflags2 |= VB2_302B;
+ printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+ break;
}
- if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
- ret = def;
- }
+ if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+ inSISIDXREG(SISCR, 0x37, reg);
+ reg &= SIS_EXTERNAL_CHIP_MASK;
+ reg >>= 1;
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+ switch(reg) {
+ case SIS_EXTERNAL_CHIP_LVDS:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case SIS_EXTERNAL_CHIP_TRUMPION:
+ ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
+ break;
+ case SIS_EXTERNAL_CHIP_CHRONTEL:
+ ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
+ ivideo->vbflags2 |= VB2_CHRONTEL;
+ break;
+ case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
+#endif
+ } else if(ivideo->chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+ switch (reg) {
+ case SIS310_EXTERNAL_CHIP_LVDS:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+ } else if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+ inSISIDXREG(SISCR, 0x38, reg);
+ reg >>= 5;
+ switch(reg) {
+ case 0x02:
+ ivideo->vbflags |= VB_LVDS; /* Deprecated */
+ ivideo->vbflags2 |= VB2_LVDS;
+ break;
+ case 0x03:
+ ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+ break;
+ case 0x04:
+ ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
+ ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
+ break;
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+ }
+ if(ivideo->vbflags2 & VB2_LVDS) {
+ printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+ }
+ if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
+ printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+ }
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+ }
+ if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
+ printk(KERN_INFO "%s Conexant external device\n", stdstr);
+ }
+ }
- return ret;
+ if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+ SiS_SenseLCD(ivideo);
+ SiS_Sense30x(ivideo);
+ } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ SiS_SenseCh(ivideo);
+ }
}
-static int __devinit
-sisfb_heap_init(struct sis_video_info *ivideo)
+/* ---------- Engine initialization routines ------------ */
+
+static void
+sisfb_engine_init(struct sis_video_info *ivideo)
{
- SIS_OH *poh;
- ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
+ /* Initialize command queue (we use MMIO only) */
- ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
- ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size;
+ /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
- /* Initialize command queue (We use MMIO only) */
+ ivideo->caps &= ~(TURBO_QUEUE_CAP |
+ MMIO_CMD_QUEUE_CAP |
+ VM_CMD_QUEUE_CAP |
+ AGP_CMD_QUEUE_CAP);
+
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ u32 tqueue_pos;
+ u8 tq_state;
+
+ tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
+
+ inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+ tq_state |= 0xf0;
+ tq_state &= 0xfc;
+ tq_state |= (u8)(tqueue_pos >> 8);
+ outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+
+ outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+
+ ivideo->caps |= TURBO_QUEUE_CAP;
+ }
+#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- u32 tempq = 0;
- u8 temp = 0;
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ u32 tempq = 0, templ;
+ u8 temp;
+
+ if(ivideo->chip == XGI_20) {
+ switch(ivideo->cmdQueueSize) {
+ case (64 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
+ break;
+ case (128 * 1024):
+ default:
+ temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
+ }
+ } else {
+ switch(ivideo->cmdQueueSize) {
+ case (4 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_4M;
+ break;
+ case (2 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_2M;
+ break;
+ case (1 * 1024 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_1M;
+ break;
+ default:
+ case (512 * 1024):
+ temp = SIS_CMD_QUEUE_SIZE_512k;
+ }
+ }
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+ if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
+ /* Must disable dual pipe on XGI_40. Can't do
+ * this in MMIO mode, because it requires
+ * setting/clearing a bit in the MMIO fire trigger
+ * register.
+ */
+ if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
+
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+
+ tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
+
+ tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+ MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
+
+ writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
+ writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
+ writel(0x168F0000, ivideo->video_vbase + tempq + 8);
+ writel(0x168F0000, ivideo->video_vbase + tempq + 12);
+
+ MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
+
+ sisfb_syncaccel(ivideo);
+
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+ }
+ }
+
+ tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+ MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+ temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+
+ tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+ MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
- ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+ }
+#endif
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+ ivideo->engineok = 1;
+}
- tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+static void __devinit
+sisfb_detect_lcd_type(struct sis_video_info *ivideo)
+{
+ u8 reg;
+ int i;
- temp = SIS_CMD_QUEUE_SIZE_512k;
- temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+ inSISIDXREG(SISCR, 0x36, reg);
+ reg &= 0x0f;
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ ivideo->CRT2LCDType = sis300paneltype[reg];
+ } else if(ivideo->chip >= SIS_661) {
+ ivideo->CRT2LCDType = sis661paneltype[reg];
+ } else {
+ ivideo->CRT2LCDType = sis310paneltype[reg];
+ if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+ if((ivideo->CRT2LCDType != LCD_320x240_2) &&
+ (ivideo->CRT2LCDType != LCD_320x240_3)) {
+ ivideo->CRT2LCDType = LCD_320x240;
+ }
+ }
+ }
- tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
+ if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
+ /* For broken BIOSes: Assume 1024x768, RGB18 */
+ ivideo->CRT2LCDType = LCD_1024x768;
+ setSISIDXREG(SISCR,0x36,0xf0,0x02);
+ setSISIDXREG(SISCR,0x37,0xee,0x01);
+ printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
+ }
- ivideo->caps |= MMIO_CMD_QUEUE_CAP;
- }
+ for(i = 0; i < SIS_LCD_NUMBER; i++) {
+ if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
+ ivideo->lcdxres = sis_lcd_data[i].xres;
+ ivideo->lcdyres = sis_lcd_data[i].yres;
+ ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+ break;
+ }
+ }
+
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+ ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
+ } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+ ivideo->lcdxres = 848; ivideo->lcdyres = 480;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_848;
+ } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
+ ivideo->lcdxres = 856; ivideo->lcdyres = 480;
+ ivideo->lcddefmodeidx = DEFAULT_MODE_856;
+ }
#endif
+ printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
+ ivideo->lcdxres, ivideo->lcdyres);
+}
+
+static void __devinit
+sisfb_save_pdc_emi(struct sis_video_info *ivideo)
+{
#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- unsigned long tqueue_pos;
- u8 tq_state;
+ /* Save the current PanelDelayCompensation if the LCD is currently used */
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
+ int tmp;
+ inSISIDXREG(SISCR,0x30,tmp);
+ if(tmp & 0x20) {
+ /* Currently on LCD? If yes, read current pdc */
+ inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+ ivideo->detectedpdc &= 0x3c;
+ if(ivideo->SiS_Pr.PDC == -1) {
+ /* Let option override detection */
+ ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+ }
+ printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+ ivideo->detectedpdc);
+ }
+ if((ivideo->SiS_Pr.PDC != -1) &&
+ (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
+ ivideo->SiS_Pr.PDC);
+ }
+ }
+ }
+#endif
- ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
- tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+ /* Try to find about LCDA */
+ if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
+ int tmp;
+ inSISIDXREG(SISPART1,0x13,tmp);
+ if(tmp & 0x04) {
+ ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+ ivideo->detectedlcda = 0x03;
+ }
+ }
- inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
- tq_state |= 0xf0;
- tq_state &= 0xfc;
- tq_state |= (u8)(tqueue_pos >> 8);
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+ /* Save PDC */
+ if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+ int tmp;
+ inSISIDXREG(SISCR,0x30,tmp);
+ if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+ /* Currently on LCD? If yes, read current pdc */
+ u8 pdc;
+ inSISIDXREG(SISPART1,0x2D,pdc);
+ ivideo->detectedpdc = (pdc & 0x0f) << 1;
+ ivideo->detectedpdca = (pdc & 0xf0) >> 3;
+ inSISIDXREG(SISPART1,0x35,pdc);
+ ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
+ inSISIDXREG(SISPART1,0x20,pdc);
+ ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+ if(ivideo->newrom) {
+ /* New ROM invalidates other PDC resp. */
+ if(ivideo->detectedlcda != 0xff) {
+ ivideo->detectedpdc = 0xff;
+ } else {
+ ivideo->detectedpdca = 0xff;
+ }
+ }
+ if(ivideo->SiS_Pr.PDC == -1) {
+ if(ivideo->detectedpdc != 0xff) {
+ ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+ }
+ }
+ if(ivideo->SiS_Pr.PDCA == -1) {
+ if(ivideo->detectedpdca != 0xff) {
+ ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
+ }
+ }
+ if(ivideo->detectedpdc != 0xff) {
+ printk(KERN_INFO
+ "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+ ivideo->detectedpdc);
+ }
+ if(ivideo->detectedpdca != 0xff) {
+ printk(KERN_INFO
+ "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+ ivideo->detectedpdca);
+ }
+ }
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+ /* Save EMI */
+ if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
+ inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+ inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+ inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+ inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+ ivideo->SiS_Pr.HaveEMI = TRUE;
+ if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+ ivideo->SiS_Pr.HaveEMILCD = TRUE;
+ }
+ }
+ }
- ivideo->caps |= TURBO_QUEUE_CAP;
- }
+ /* Let user override detected PDCs (all bridges) */
+ if(ivideo->vbflags2 & VB2_30xBLV) {
+ if((ivideo->SiS_Pr.PDC != -1) &&
+ (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+ ivideo->SiS_Pr.PDC);
+ }
+ if((ivideo->SiS_Pr.PDCA != -1) &&
+ (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
+ printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+ ivideo->SiS_Pr.PDCA);
+ }
+ }
+
+ }
#endif
+}
- /* Reserve memory for the HWCursor */
- ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
- ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
- ivideo->caps |= HW_CURSOR_CAP;
+/* -------------------- Memory manager routines ---------------------- */
- ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
+{
+ u32 ret = ivideo->sisfb_parm_mem * 1024;
+ u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+ u32 def;
- if(ivideo->cardnumber == 0) {
+ /* Calculate heap start = end of memory for console
+ *
+ * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+ * C = console, D = heap, H = HWCursor, Q = cmd-queue
+ *
+ * On 76x in UMA+LFB mode, the layout is as follows:
+ * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
+ * where the heap is the entire UMA area, eventually
+ * into the LFB area if the given mem parameter is
+ * higher than the size of the UMA memory.
+ *
+ * Basically given by "mem" parameter
+ *
+ * maximum = videosize - cmd_queue - hwcursor
+ * (results in a heap of size 0)
+ * default = SiS 300: depends on videosize
+ * SiS 315/330/340/XGI: 32k below max
+ */
- printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
- (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ if(ivideo->video_size > 0x1000000) {
+ def = 0xc00000;
+ } else if(ivideo->video_size > 0x800000) {
+ def = 0x800000;
+ } else {
+ def = 0x400000;
+ }
+ } else if(ivideo->UMAsize && ivideo->LFBsize) {
+ ret = def = 0;
+ } else {
+ def = maxoffs - 0x8000;
+ }
- sisfb_heap.vinfo = ivideo;
+ /* Use default for secondary card for now (FIXME) */
+ if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
+ ret = def;
- sisfb_heap.poha_chain = NULL;
- sisfb_heap.poh_freelist = NULL;
+ return ret;
+}
- poh = sisfb_poh_new_node();
- if(poh == NULL) return 1;
+static u32 __devinit
+sisfb_getheapsize(struct sis_video_info *ivideo)
+{
+ u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+ u32 ret = 0;
+
+ if(ivideo->UMAsize && ivideo->LFBsize) {
+ if( (!ivideo->sisfb_parm_mem) ||
+ ((ivideo->sisfb_parm_mem * 1024) > max) ||
+ ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
+ ret = ivideo->UMAsize;
+ max -= ivideo->UMAsize;
+ } else {
+ ret = max - (ivideo->sisfb_parm_mem * 1024);
+ max = ivideo->sisfb_parm_mem * 1024;
+ }
+ ivideo->video_offset = ret;
+ ivideo->sisfb_mem = max;
+ } else {
+ ret = max - ivideo->heapstart;
+ ivideo->sisfb_mem = ivideo->heapstart;
+ }
- poh->poh_next = &sisfb_heap.oh_free;
- poh->poh_prev = &sisfb_heap.oh_free;
- poh->size = ivideo->sisfb_heap_size;
- poh->offset = ivideo->heapstart;
+ return ret;
+}
- sisfb_heap.oh_free.poh_next = poh;
- sisfb_heap.oh_free.poh_prev = poh;
- sisfb_heap.oh_free.size = 0;
- sisfb_heap.max_freesize = poh->size;
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+ struct SIS_OH *poh;
- sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.size = SENTINEL;
+ ivideo->video_offset = 0;
+ if(ivideo->sisfb_parm_mem) {
+ if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
+ (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
+ ivideo->sisfb_parm_mem = 0;
+ }
+ }
- } else {
+ ivideo->heapstart = sisfb_getheapstart(ivideo);
+ ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
- printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+ ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+ ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
- }
+ printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+ (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
- return 0;
+ ivideo->sisfb_heap.vinfo = ivideo;
+
+ ivideo->sisfb_heap.poha_chain = NULL;
+ ivideo->sisfb_heap.poh_freelist = NULL;
+
+ poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
+ if(poh == NULL)
+ return 1;
+
+ poh->poh_next = &ivideo->sisfb_heap.oh_free;
+ poh->poh_prev = &ivideo->sisfb_heap.oh_free;
+ poh->size = ivideo->sisfb_heap_size;
+ poh->offset = ivideo->heapstart;
+
+ ivideo->sisfb_heap.oh_free.poh_next = poh;
+ ivideo->sisfb_heap.oh_free.poh_prev = poh;
+ ivideo->sisfb_heap.oh_free.size = 0;
+ ivideo->sisfb_heap.max_freesize = poh->size;
+
+ ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
+ ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
+ ivideo->sisfb_heap.oh_used.size = SENTINEL;
+
+ if(ivideo->cardnumber == 0) {
+ /* For the first card, make this heap the "global" one
+ * for old DRM (which could handle only one card)
+ */
+ sisfb_heap = &ivideo->sisfb_heap;
+ }
+
+ return 0;
}
-static SIS_OH *
-sisfb_poh_new_node(void)
+static struct SIS_OH *
+sisfb_poh_new_node(struct SIS_HEAP *memheap)
{
- int i;
- unsigned long cOhs;
- SIS_OHALLOC *poha;
- SIS_OH *poh;
+ struct SIS_OHALLOC *poha;
+ struct SIS_OH *poh;
+ unsigned long cOhs;
+ int i;
- if(sisfb_heap.poh_freelist == NULL) {
+ if(memheap->poh_freelist == NULL) {
poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
- if(!poha) return NULL;
+ if(!poha)
+ return NULL;
- poha->poha_next = sisfb_heap.poha_chain;
- sisfb_heap.poha_chain = poha;
+ poha->poha_next = memheap->poha_chain;
+ memheap->poha_chain = poha;
- cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+ cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
poh = &poha->aoh[0];
for(i = cOhs - 1; i != 0; i--) {
@@ -3169,32 +3349,32 @@ sisfb_poh_new_node(void)
}
poh->poh_next = NULL;
- sisfb_heap.poh_freelist = &poha->aoh[0];
+ memheap->poh_freelist = &poha->aoh[0];
}
- poh = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh->poh_next;
+ poh = memheap->poh_freelist;
+ memheap->poh_freelist = poh->poh_next;
- return (poh);
+ return poh;
}
-static SIS_OH *
-sisfb_poh_allocate(u32 size)
+static struct SIS_OH *
+sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
{
- SIS_OH *pohThis;
- SIS_OH *pohRoot;
- int bAllocated = 0;
+ struct SIS_OH *pohThis;
+ struct SIS_OH *pohRoot;
+ int bAllocated = 0;
- if(size > sisfb_heap.max_freesize) {
+ if(size > memheap->max_freesize) {
DPRINTK("sisfb: Can't allocate %dk video memory\n",
(unsigned int) size / 1024);
- return (NULL);
+ return NULL;
}
- pohThis = sisfb_heap.oh_free.poh_next;
+ pohThis = memheap->oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
- if (size <= pohThis->size) {
+ while(pohThis != &memheap->oh_free) {
+ if(size <= pohThis->size) {
bAllocated = 1;
break;
}
@@ -3204,18 +3384,16 @@ sisfb_poh_allocate(u32 size)
if(!bAllocated) {
DPRINTK("sisfb: Can't allocate %dk video memory\n",
(unsigned int) size / 1024);
- return (NULL);
+ return NULL;
}
if(size == pohThis->size) {
pohRoot = pohThis;
sisfb_delete_node(pohThis);
} else {
- pohRoot = sisfb_poh_new_node();
-
- if(pohRoot == NULL) {
- return (NULL);
- }
+ pohRoot = sisfb_poh_new_node(memheap);
+ if(pohRoot == NULL)
+ return NULL;
pohRoot->offset = pohThis->offset;
pohRoot->size = size;
@@ -3224,33 +3402,25 @@ sisfb_poh_allocate(u32 size)
pohThis->size -= size;
}
- sisfb_heap.max_freesize -= size;
+ memheap->max_freesize -= size;
- pohThis = &sisfb_heap.oh_used;
+ pohThis = &memheap->oh_used;
sisfb_insert_node(pohThis, pohRoot);
- return (pohRoot);
+ return pohRoot;
}
static void
-sisfb_delete_node(SIS_OH *poh)
+sisfb_delete_node(struct SIS_OH *poh)
{
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
-
- poh_prev = poh->poh_prev;
- poh_next = poh->poh_next;
-
- poh_prev->poh_next = poh_next;
- poh_next->poh_prev = poh_prev;
+ poh->poh_prev->poh_next = poh->poh_next;
+ poh->poh_next->poh_prev = poh->poh_prev;
}
static void
-sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
{
- SIS_OH *pohTemp;
-
- pohTemp = pohList->poh_next;
+ struct SIS_OH *pohTemp = pohList->poh_next;
pohList->poh_next = poh;
pohTemp->poh_prev = poh;
@@ -3259,20 +3429,20 @@ sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
poh->poh_next = pohTemp;
}
-static SIS_OH *
-sisfb_poh_free(u32 base)
+static struct SIS_OH *
+sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
{
- SIS_OH *pohThis;
- SIS_OH *poh_freed;
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
- u32 ulUpper;
- u32 ulLower;
- int foundNode = 0;
+ struct SIS_OH *pohThis;
+ struct SIS_OH *poh_freed;
+ struct SIS_OH *poh_prev;
+ struct SIS_OH *poh_next;
+ u32 ulUpper;
+ u32 ulLower;
+ int foundNode = 0;
- poh_freed = sisfb_heap.oh_used.poh_next;
+ poh_freed = memheap->oh_used.poh_next;
- while(poh_freed != &sisfb_heap.oh_used) {
+ while(poh_freed != &memheap->oh_used) {
if(poh_freed->offset == base) {
foundNode = 1;
break;
@@ -3281,17 +3451,18 @@ sisfb_poh_free(u32 base)
poh_freed = poh_freed->poh_next;
}
- if(!foundNode) return(NULL);
+ if(!foundNode)
+ return NULL;
- sisfb_heap.max_freesize += poh_freed->size;
+ memheap->max_freesize += poh_freed->size;
poh_prev = poh_next = NULL;
ulUpper = poh_freed->offset + poh_freed->size;
ulLower = poh_freed->offset;
- pohThis = sisfb_heap.oh_free.poh_next;
+ pohThis = memheap->oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
+ while(pohThis != &memheap->oh_free) {
if(pohThis->offset == ulUpper) {
poh_next = pohThis;
} else if((pohThis->offset + pohThis->size) == ulLower) {
@@ -3305,70 +3476,88 @@ sisfb_poh_free(u32 base)
if(poh_prev && poh_next) {
poh_prev->size += (poh_freed->size + poh_next->size);
sisfb_delete_node(poh_next);
- sisfb_free_node(poh_freed);
- sisfb_free_node(poh_next);
- return(poh_prev);
+ sisfb_free_node(memheap, poh_freed);
+ sisfb_free_node(memheap, poh_next);
+ return poh_prev;
}
if(poh_prev) {
poh_prev->size += poh_freed->size;
- sisfb_free_node(poh_freed);
- return(poh_prev);
+ sisfb_free_node(memheap, poh_freed);
+ return poh_prev;
}
if(poh_next) {
poh_next->size += poh_freed->size;
poh_next->offset = poh_freed->offset;
- sisfb_free_node(poh_freed);
- return(poh_next);
+ sisfb_free_node(memheap, poh_freed);
+ return poh_next;
}
- sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
+ sisfb_insert_node(&memheap->oh_free, poh_freed);
- return(poh_freed);
+ return poh_freed;
}
static void
-sisfb_free_node(SIS_OH *poh)
+sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
{
- if(poh == NULL) return;
+ if(poh == NULL)
+ return;
- poh->poh_next = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh;
+ poh->poh_next = memheap->poh_freelist;
+ memheap->poh_freelist = poh;
}
-void
-sis_malloc(struct sis_memreq *req)
+static void
+sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
{
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh = NULL;
+ struct SIS_OH *poh = NULL;
- if((ivideo) && (!ivideo->havenoheap)) {
- poh = sisfb_poh_allocate((u32)req->size);
- }
+ if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
+ poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
if(poh == NULL) {
- req->offset = req->size = 0;
- DPRINTK("sisfb: Video RAM allocation failed\n");
+ req->offset = req->size = 0;
+ DPRINTK("sisfb: Video RAM allocation failed\n");
} else {
- req->offset = poh->offset;
- req->size = poh->size;
- DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
- (poh->offset + ivideo->video_vbase));
+ req->offset = poh->offset;
+ req->size = poh->size;
+ DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+ (poh->offset + ivideo->video_vbase));
}
}
-/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+void
+sis_malloc(struct sis_memreq *req)
+{
+ struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+ if(&ivideo->sisfb_heap == sisfb_heap)
+ sis_int_malloc(ivideo, req);
+ else
+ req->offset = req->size = 0;
+}
void
-sis_free(u32 base)
+sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
{
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh;
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+ sis_int_malloc(ivideo, req);
+}
+
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
- if((!ivideo) || (ivideo->havenoheap)) return;
+static void
+sis_int_free(struct sis_video_info *ivideo, u32 base)
+{
+ struct SIS_OH *poh;
- poh = sisfb_poh_free((u32)base);
+ if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
+ return;
+
+ poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
if(poh == NULL) {
DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3376,9 +3565,63 @@ sis_free(u32 base)
}
}
+void
+sis_free(u32 base)
+{
+ struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+ sis_int_free(ivideo, base);
+}
+
+void
+sis_free_new(struct pci_dev *pdev, u32 base)
+{
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+ sis_int_free(ivideo, base);
+}
+
/* --------------------- SetMode routines ------------------------- */
static void
+sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
+{
+ u8 cr30, cr31;
+
+ /* Check if MMIO and engines are enabled,
+ * and sync in case they are. Can't use
+ * ivideo->accel here, as this might have
+ * been changed before this is called.
+ */
+ inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
+ inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
+ /* MMIO and 2D/3D engine enabled? */
+ if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ /* Don't care about TurboQueue. It's
+ * enough to know that the engines
+ * are enabled
+ */
+ sisfb_syncaccel(ivideo);
+ }
+#endif
+#ifdef CONFIG_FB_SIS_315
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ /* Check that any queue mode is
+ * enabled, and that the queue
+ * is not in the state of "reset"
+ */
+ inSISIDXREG(SISSR, 0x26, cr30);
+ if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
+ sisfb_syncaccel(ivideo);
+ }
+ }
+#endif
+ }
+}
+
+static void
sisfb_pre_setmode(struct sis_video_info *ivideo)
{
u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
@@ -3386,6 +3629,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
inSISIDXREG(SISCR, 0x31, cr31);
cr31 &= ~0x60;
cr31 |= 0x04;
@@ -3413,41 +3658,43 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
case CRT2_TV:
cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
- if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+ if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
#ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
+ if(ivideo->chip >= SIS_661) {
+ cr38 |= 0x04;
+ if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
cr35 &= ~0x01;
ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+ cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
cr38 |= 0x08;
- if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
+ if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
cr31 &= ~0x01;
ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- }
-#endif
- } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- cr35 |= 0x60;
- } else {
- cr30 |= 0x80;
- }
+ }
+#endif
+ } else if((ivideo->vbflags & TV_HIVISION) &&
+ (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
+ if(ivideo->chip >= SIS_661) {
+ cr38 |= 0x04;
+ cr35 |= 0x60;
+ } else {
+ cr30 |= 0x80;
+ }
cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= 0x01;
- cr35 |= 0x01;
+ cr31 |= 0x01;
+ cr35 |= 0x01;
ivideo->currentvbflags |= TV_HIVISION;
} else if(ivideo->vbflags & TV_SCART) {
cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
@@ -3466,8 +3713,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
}
cr31 |= SIS_DRIVER_MODE;
- if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
- if(ivideo->vbflags & TV_PAL) {
+ if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
+ if(ivideo->vbflags & TV_PAL) {
cr31 |= 0x01; cr35 |= 0x01;
ivideo->currentvbflags |= TV_PAL;
if(ivideo->vbflags & TV_PALM) {
@@ -3476,14 +3723,14 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
} else if(ivideo->vbflags & TV_PALN) {
cr38 |= 0x80; cr35 |= 0x08;
ivideo->currentvbflags |= TV_PALN;
- }
- } else {
+ }
+ } else {
cr31 &= ~0x01; cr35 &= ~0x01;
ivideo->currentvbflags |= TV_NTSC;
if(ivideo->vbflags & TV_NTSCJ) {
cr38 |= 0x40; cr35 |= 0x02;
ivideo->currentvbflags |= TV_NTSCJ;
- }
+ }
}
}
break;
@@ -3493,6 +3740,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
cr31 |= SIS_DRIVER_MODE;
SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+ ivideo->curFSTN = ivideo->sisfb_fstn;
+ ivideo->curDSTN = ivideo->sisfb_dstn;
break;
case CRT2_VGA:
@@ -3525,9 +3774,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
}
outSISIDXREG(SISCR, 0x31, cr31);
- if(ivideo->accel) sisfb_syncaccel(ivideo);
-
ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+
+ sisfb_check_engine_and_sync(ivideo);
}
/* Fix SR11 for 661 and later */
@@ -3535,125 +3784,129 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
static void
sisfb_fixup_SR11(struct sis_video_info *ivideo)
{
- u8 tmpreg;
-
- if(ivideo->chip >= SIS_661) {
- inSISIDXREG(SISSR,0x11,tmpreg);
- if(tmpreg & 0x20) {
- inSISIDXREG(SISSR,0x3e,tmpreg);
- tmpreg = (tmpreg + 1) & 0xff;
- outSISIDXREG(SISSR,0x3e,tmpreg);
- inSISIDXREG(SISSR,0x11,tmpreg);
- }
- if(tmpreg & 0xf0) {
- andSISIDXREG(SISSR,0x11,0x0f);
- }
- }
+ u8 tmpreg;
+
+ if(ivideo->chip >= SIS_661) {
+ inSISIDXREG(SISSR,0x11,tmpreg);
+ if(tmpreg & 0x20) {
+ inSISIDXREG(SISSR,0x3e,tmpreg);
+ tmpreg = (tmpreg + 1) & 0xff;
+ outSISIDXREG(SISSR,0x3e,tmpreg);
+ inSISIDXREG(SISSR,0x11,tmpreg);
+ }
+ if(tmpreg & 0xf0) {
+ andSISIDXREG(SISSR,0x11,0x0f);
+ }
+ }
}
#endif
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
{
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvxpos = val;
+ if(val > 32) val = 32;
+ if(val < -32) val = -32;
+ ivideo->tvxpos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
+ if(ivideo->sisfblocked) return;
+ if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
+ if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_CHRONTEL) {
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
- int x = ivideo->tvx;
+ int x = ivideo->tvx;
- switch(ivideo->chronteltype) {
- case 1:
- x += val;
- if(x < 0) x = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
-
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
- unsigned short temp;
-
- p2_1f = ivideo->p2_1f;
- p2_20 = ivideo->p2_20;
- p2_2b = ivideo->p2_2b;
- p2_42 = ivideo->p2_42;
- p2_43 = ivideo->p2_43;
-
- temp = p2_1f | ((p2_20 & 0xf0) << 4);
- temp += (val * 2);
- p2_1f = temp & 0xff;
- p2_20 = (temp & 0xf00) >> 4;
- p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
- temp = p2_43 | ((p2_42 & 0xf0) << 4);
- temp += (val * 2);
- p2_43 = temp & 0xff;
- p2_42 = (temp & 0xf00) >> 4;
- outSISIDXREG(SISPART2,0x1f,p2_1f);
- setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
- setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
- setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
- outSISIDXREG(SISPART2,0x43,p2_43);
- }
- }
+ switch(ivideo->chronteltype) {
+ case 1:
+ x += val;
+ if(x < 0) x = 0;
+ outSISIDXREG(SISSR,0x05,0x86);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
+ break;
+ case 2:
+ /* Not supported by hardware */
+ break;
+ }
+
+ } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+ u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+ unsigned short temp;
+
+ p2_1f = ivideo->p2_1f;
+ p2_20 = ivideo->p2_20;
+ p2_2b = ivideo->p2_2b;
+ p2_42 = ivideo->p2_42;
+ p2_43 = ivideo->p2_43;
+
+ temp = p2_1f | ((p2_20 & 0xf0) << 4);
+ temp += (val * 2);
+ p2_1f = temp & 0xff;
+ p2_20 = (temp & 0xf00) >> 4;
+ p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+ temp = p2_43 | ((p2_42 & 0xf0) << 4);
+ temp += (val * 2);
+ p2_43 = temp & 0xff;
+ p2_42 = (temp & 0xf00) >> 4;
+ outSISIDXREG(SISPART2,0x1f,p2_1f);
+ setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+ setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+ setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+ outSISIDXREG(SISPART2,0x43,p2_43);
+ }
+ }
}
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
{
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvypos = val;
-
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
-
- if(ivideo->currentvbflags & CRT2_TV) {
-
- if(ivideo->vbflags & VB_CHRONTEL) {
-
- int y = ivideo->tvy;
-
- switch(ivideo->chronteltype) {
- case 1:
- y -= val;
- if(y < 0) y = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
-
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
- char p2_01, p2_02;
- val /= 2;
- p2_01 = ivideo->p2_01;
- p2_02 = ivideo->p2_02;
-
- p2_01 += val;
- p2_02 += val;
- while((p2_01 <= 0) || (p2_02 <= 0)) {
- p2_01 += 2;
- p2_02 += 2;
- }
- outSISIDXREG(SISPART2,0x01,p2_01);
- outSISIDXREG(SISPART2,0x02,p2_02);
- }
- }
+ if(val > 32) val = 32;
+ if(val < -32) val = -32;
+ ivideo->tvypos = val;
+
+ if(ivideo->sisfblocked) return;
+ if(!ivideo->modechanged) return;
+
+ if(ivideo->currentvbflags & CRT2_TV) {
+
+ if(ivideo->vbflags2 & VB2_CHRONTEL) {
+
+ int y = ivideo->tvy;
+
+ switch(ivideo->chronteltype) {
+ case 1:
+ y -= val;
+ if(y < 0) y = 0;
+ outSISIDXREG(SISSR,0x05,0x86);
+ SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
+ SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
+ break;
+ case 2:
+ /* Not supported by hardware */
+ break;
+ }
+
+ } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+ char p2_01, p2_02;
+ val /= 2;
+ p2_01 = ivideo->p2_01;
+ p2_02 = ivideo->p2_02;
+
+ p2_01 += val;
+ p2_02 += val;
+ if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
+ while((p2_01 <= 0) || (p2_02 <= 0)) {
+ p2_01 += 2;
+ p2_02 += 2;
+ }
+ }
+ outSISIDXREG(SISPART2,0x01,p2_01);
+ outSISIDXREG(SISPART2,0x02,p2_02);
+ }
+ }
}
static void
@@ -3668,207 +3921,172 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
u8 reg1;
#endif
- outSISIDXREG(SISSR,0x05,0x86);
+ outSISIDXREG(SISSR, 0x05, 0x86);
#ifdef CONFIG_FB_SIS_315
sisfb_fixup_SR11(ivideo);
#endif
/* Now we actually HAVE changed the display mode */
- ivideo->modechanged = 1;
+ ivideo->modechanged = 1;
/* We can't switch off CRT1 if bridge is in slave mode */
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
- } else ivideo->sisfb_crt1off = 0;
+ } else
+ ivideo->sisfb_crt1off = 0;
#ifdef CONFIG_FB_SIS_300
if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x00;
- } else {
- crt1isoff = FALSE;
- reg = 0x80;
- }
- setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+ if((ivideo->sisfb_crt1off) && (doit)) {
+ crt1isoff = TRUE;
+ reg = 0x00;
+ } else {
+ crt1isoff = FALSE;
+ reg = 0x80;
+ }
+ setSISIDXREG(SISCR, 0x17, 0x7f, reg);
}
#endif
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x40;
- reg1 = 0xc0;
- } else {
- crt1isoff = FALSE;
- reg = 0x00;
- reg1 = 0x00;
-
- }
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
- setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
+ if((ivideo->sisfb_crt1off) && (doit)) {
+ crt1isoff = TRUE;
+ reg = 0x40;
+ reg1 = 0xc0;
+ } else {
+ crt1isoff = FALSE;
+ reg = 0x00;
+ reg1 = 0x00;
+ }
+ setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+ setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
}
#endif
if(crt1isoff) {
- ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
- ivideo->currentvbflags |= VB_SINGLE_MODE;
+ ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+ ivideo->currentvbflags |= VB_SINGLE_MODE;
} else {
- ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
- ivideo->currentvbflags |= VB_MIRROR_MODE;
- } else {
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- }
+ ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+ if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+ ivideo->currentvbflags |= VB_MIRROR_MODE;
+ } else {
+ ivideo->currentvbflags |= VB_SINGLE_MODE;
+ }
}
- andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+ andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_SISBRIDGE) {
- inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
- inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
- inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
- inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
- inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
- inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
- inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- if(ivideo->chronteltype == 1) {
- ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
- ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
- ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
- ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
- }
- }
+ if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+ inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+ inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+ inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+ inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+ inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+ inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+ inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+ } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+ if(ivideo->chronteltype == 1) {
+ ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+ ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+ ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+ ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+ }
+ }
}
if(ivideo->tvxpos) {
- sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+ sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
}
if(ivideo->tvypos) {
- sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+ sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
}
- if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */
+ /* Eventually sync engines */
+ sisfb_check_engine_and_sync(ivideo);
- unsigned char filter_tb = 0;
+ /* (Re-)Initialize chip engines */
+ if(ivideo->accel) {
+ sisfb_engine_init(ivideo);
+ } else {
+ ivideo->engineok = 0;
+ }
+}
- switch (ivideo->video_width) {
- case 320:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
- break;
- case 640:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
- break;
- case 720:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
- break;
- case 400:
- case 800:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
- break;
- default:
- ivideo->sisfb_filter = -1;
- break;
- }
+static int
+sisfb_reset_mode(struct sis_video_info *ivideo)
+{
+ if(sisfb_set_mode(ivideo, 0))
+ return 1;
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
+ sisfb_set_pitch(ivideo);
+ sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+ sisfb_set_base_CRT2(ivideo, ivideo->current_base);
- if(ivideo->vbflags & TV_NTSC) {
-
- andSISIDXREG(SISPART2, 0x3a, 0x1f);
-
- if (ivideo->vbflags & TV_SVIDEO) {
-
- andSISIDXREG(SISPART2, 0x30, 0xdf);
-
- } else if (ivideo->vbflags & TV_AVIDEO) {
-
- orSISIDXREG(SISPART2, 0x30, 0x20);
-
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x04);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0x18);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xEE);
- outSISIDXREG(SISPART2, 0x36, 0x0C);
- outSISIDXREG(SISPART2, 0x37, 0x22);
- outSISIDXREG(SISPART2, 0x38, 0x08);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x15);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0xF6);
- break;
- }
- }
+ return 0;
+}
+
+static void
+sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
+{
+ int mycrt1off;
- } else if(ivideo->vbflags & TV_PAL) {
-
- andSISIDXREG(SISPART2, 0x3A, 0x1F);
-
- if (ivideo->vbflags & TV_SVIDEO) {
-
- andSISIDXREG(SISPART2, 0x30, 0xDF);
-
- } else if (ivideo->vbflags & TV_AVIDEO) {
-
- orSISIDXREG(SISPART2, 0x30, 0x20);
-
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xF1);
- outSISIDXREG(SISPART2, 0x36, 0xF7);
- outSISIDXREG(SISPART2, 0x37, 0x1F);
- outSISIDXREG(SISPART2, 0x38, 0x32);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xF3);
- outSISIDXREG(SISPART2, 0x36, 0x00);
- outSISIDXREG(SISPART2, 0x37, 0x1D);
- outSISIDXREG(SISPART2, 0x38, 0x20);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xFC);
- outSISIDXREG(SISPART2, 0x36, 0xFB);
- outSISIDXREG(SISPART2, 0x37, 0x14);
- outSISIDXREG(SISPART2, 0x38, 0x2A);
- break;
+ switch(sisfb_command->sisfb_cmd) {
+ case SISFB_CMD_GETVBFLAGS:
+ if(!ivideo->modechanged) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+ } else {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
+ sisfb_command->sisfb_result[2] = ivideo->vbflags2;
+ }
+ break;
+ case SISFB_CMD_SWITCHCRT1:
+ /* arg[0]: 0 = off, 1 = on, 99 = query */
+ if(!ivideo->modechanged) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+ } else if(sisfb_command->sisfb_arg[0] == 99) {
+ /* Query */
+ sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ } else if(ivideo->sisfblocked) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
+ } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
+ (sisfb_command->sisfb_arg[0] == 0)) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
+ } else {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+ mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
+ if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
+ ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
+ ivideo->sisfb_crt1off = mycrt1off;
+ if(sisfb_reset_mode(ivideo)) {
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
}
}
+ sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
}
-
- if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
- outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
- outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
- outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
- outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
- }
-
+ break;
+ /* more to come */
+ default:
+ sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
+ printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
+ sisfb_command->sisfb_cmd);
}
}
#ifndef MODULE
-SISINITSTATIC int __init sisfb_setup(char *options)
+SISINITSTATIC int __init
+sisfb_setup(char *options)
{
char *this_opt;
-
- sisfb_setdefaultparms();
- printk(KERN_DEBUG "sisfb: Options %s\n", options);
+ sisfb_setdefaultparms();
- if(!options || !(*options)) {
+ if(!options || !(*options))
return 0;
- }
while((this_opt = strsep(&options, ",")) != NULL) {
@@ -3880,9 +4098,9 @@ SISINITSTATIC int __init sisfb_setup(char *options)
/* Need to check crt2 type first for fstn/dstn */
sisfb_search_crt2type(this_opt + 14);
} else if(!strnicmp(this_opt, "tvmode:",7)) {
- sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "tvstandard:",11)) {
sisfb_search_tvstd(this_opt + 7);
+ } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+ sisfb_search_tvstd(this_opt + 11);
} else if(!strnicmp(this_opt, "mode:", 5)) {
sisfb_search_mode(this_opt + 5, FALSE);
} else if(!strnicmp(this_opt, "vesa:", 5)) {
@@ -3892,74 +4110,72 @@ SISINITSTATIC int __init sisfb_setup(char *options)
sisfb_inverse = 1;
/* fb_invert_cmaps(); */
} else if(!strnicmp(this_opt, "font:", 5)) {
- if(strlen(this_opt + 5) < 40) {
+ if(strlen(this_opt + 5) < 40) {
strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
}
#endif
} else if(!strnicmp(this_opt, "rate:", 5)) {
sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "filter:", 7)) {
- sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
- } else if(!strnicmp(this_opt, "mem:",4)) {
- sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
+ } else if(!strnicmp(this_opt, "mem:",4)) {
+ sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc:", 4)) {
- sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+ sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc1:", 5)) {
- sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+ sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
} else if(!strnicmp(this_opt, "noaccel", 7)) {
sisfb_accel = 0;
} else if(!strnicmp(this_opt, "accel", 5)) {
sisfb_accel = -1;
} else if(!strnicmp(this_opt, "noypan", 6)) {
- sisfb_ypan = 0;
+ sisfb_ypan = 0;
} else if(!strnicmp(this_opt, "ypan", 4)) {
- sisfb_ypan = -1;
+ sisfb_ypan = -1;
} else if(!strnicmp(this_opt, "nomax", 5)) {
- sisfb_max = 0;
+ sisfb_max = 0;
} else if(!strnicmp(this_opt, "max", 3)) {
- sisfb_max = -1;
+ sisfb_max = -1;
} else if(!strnicmp(this_opt, "userom:", 7)) {
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "useoem:", 7)) {
sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
sisfb_nocrt2rate = 1;
- } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
- unsigned long temp = 2;
- temp = simple_strtoul(this_opt + 9, NULL, 0);
- if((temp == 0) || (temp == 1)) {
+ } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+ unsigned long temp = 2;
+ temp = simple_strtoul(this_opt + 9, NULL, 0);
+ if((temp == 0) || (temp == 1)) {
sisfb_scalelcd = temp ^ 1;
- }
+ }
} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
+ int temp = 0;
+ temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+ if((temp >= -32) && (temp <= 32)) {
sisfb_tvxposoffset = temp;
- }
+ }
} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
+ int temp = 0;
+ temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+ if((temp >= -32) && (temp <= 32)) {
sisfb_tvyposoffset = temp;
- }
+ }
} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
sisfb_search_specialtiming(this_opt + 14);
} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
- int temp = 4;
- temp = simple_strtoul(this_opt + 7, NULL, 0);
- if((temp >= 0) && (temp <= 3)) {
+ int temp = 4;
+ temp = simple_strtoul(this_opt + 7, NULL, 0);
+ if((temp >= 0) && (temp <= 3)) {
sisfb_lvdshl = temp;
- }
+ }
} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
sisfb_search_mode(this_opt, TRUE);
#if !defined(__i386__) && !defined(__x86_64__)
- } else if(!strnicmp(this_opt, "resetcard", 9)) {
- sisfb_resetcard = 1;
+ } else if(!strnicmp(this_opt, "resetcard", 9)) {
+ sisfb_resetcard = 1;
} else if(!strnicmp(this_opt, "videoram:", 9)) {
- sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+ sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
#endif
} else {
printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
@@ -3967,63 +4183,99 @@ SISINITSTATIC int __init sisfb_setup(char *options)
}
-
-
return 0;
}
#endif
-static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
+static int __devinit
+sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+{
+ SIS_IOTYPE1 *rom;
+ int romptr;
+
+ if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
+ return 0;
+
+ romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+ if(romptr > (0x10000 - 8))
+ return 0;
+
+ rom = rom_base + romptr;
+
+ if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
+ (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
+ return 0;
+
+ if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
+ return 0;
+
+ if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
+ return 0;
+
+ return 1;
+}
+
+static unsigned char * __devinit
+sisfb_find_rom(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- USHORT pciid;
- int romptr;
- UCHAR *myrombase;
- u32 temp;
- SIS_IOTYPE1 *rom_base, *rom;
+ SIS_IOTYPE1 *rom_base;
+ unsigned char *myrombase = NULL;
+ u32 temp;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+ size_t romsize;
+
+ /* First, try the official pci ROM functions (except
+ * on integrated chipsets which have no ROM).
+ */
- if(!(myrombase = vmalloc(65536))) return NULL;
+ if(!ivideo->nbridge) {
-#if defined(__i386__) || defined(__x86_64__)
+ if((rom_base = pci_map_rom(pdev, &romsize))) {
- for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+ if(sisfb_check_rom(rom_base, ivideo)) {
- rom_base = ioremap(temp, 0x10000);
- if(!rom_base) continue;
+ if((myrombase = vmalloc(65536))) {
- if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
- iounmap(rom_base);
- continue;
- }
+ /* Work around bug in pci/rom.c: Folks forgot to check
+ * whether the size retrieved from the BIOS image eventually
+ * is larger than the mapped size
+ */
+ if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
+ romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr > (0x10000 - 8)) {
- iounmap(rom_base);
- continue;
- }
+ memcpy_fromio(myrombase, rom_base,
+ (romsize > 65536) ? 65536 : romsize);
+ }
+ }
+ pci_unmap_rom(pdev, rom_base);
+ }
+ }
- rom = rom_base + romptr;
+ if(myrombase) return myrombase;
+#endif
- if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
- (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
- iounmap(rom_base);
- continue;
- }
+ /* Otherwise do it the conventional way. */
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid != 0x1039) {
- iounmap(rom_base);
- continue;
- }
+#if defined(__i386__) || defined(__x86_64__)
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- return myrombase;
- }
+ for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+
+ rom_base = ioremap(temp, 65536);
+ if(!rom_base)
+ continue;
+
+ if(!sisfb_check_rom(rom_base, ivideo)) {
+ iounmap(rom_base);
+ continue;
+ }
+
+ if((myrombase = vmalloc(65536)))
+ memcpy_fromio(myrombase, rom_base, 65536);
+
+ iounmap(rom_base);
+ break;
- iounmap(rom_base);
}
#else
@@ -4034,752 +4286,1603 @@ static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
rom_base = ioremap(ivideo->video_base, 65536);
if(rom_base) {
- if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
- romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr <= (0x10000 - 8)) {
- rom = rom_base + romptr;
- if((readb(rom) == 'P') && (readb(rom + 1) == 'C') &&
- (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid == 0x1039) {
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
- return myrombase;
- }
- }
- }
- }
- }
- iounmap(rom_base);
+ if(sisfb_check_rom(rom_base, ivideo)) {
+ if((myrombase = vmalloc(65536)))
+ memcpy_fromio(myrombase, rom_base, 65536);
+ }
+ iounmap(rom_base);
}
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
+
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
#endif
- vfree(myrombase);
- return NULL;
+ return myrombase;
+}
+
+static void __devinit
+sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
+ unsigned int min)
+{
+ ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
+
+ if(!ivideo->video_vbase) {
+ printk(KERN_ERR
+ "sisfb: Unable to map maximum video RAM for size detection\n");
+ (*mapsize) >>= 1;
+ while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
+ (*mapsize) >>= 1;
+ if((*mapsize) < (min << 20))
+ break;
+ }
+ if(ivideo->video_vbase) {
+ printk(KERN_ERR
+ "sisfb: Video RAM size detection limited to %dMB\n",
+ (int)((*mapsize) >> 20));
+ }
+ }
}
#ifdef CONFIG_FB_SIS_300
static int __devinit
-sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress)
+sisfb_post_300_buswidth(struct sis_video_info *ivideo)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+ unsigned short temp;
+ unsigned char reg;
int i, j;
- USHORT temp;
- UCHAR reg;
-
- andSISIDXREG(SISSR,0x15,0xFB);
- orSISIDXREG(SISSR,0x15,0x04);
- outSISIDXREG(SISSR,0x13,0x00);
- outSISIDXREG(SISSR,0x14,0xBF);
-
- for(i=0; i<2; i++) {
- temp = 0x1234;
- for(j=0; j<4; j++) {
- writew(temp, FBAddress);
- if(readw(FBAddress) == temp) break;
- orSISIDXREG(SISSR,0x3c,0x01);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- andSISIDXREG(SISSR,0x3c,0xfe);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- temp++;
- }
+
+ andSISIDXREG(SISSR, 0x15, 0xFB);
+ orSISIDXREG(SISSR, 0x15, 0x04);
+ outSISIDXREG(SISSR, 0x13, 0x00);
+ outSISIDXREG(SISSR, 0x14, 0xBF);
+
+ for(i = 0; i < 2; i++) {
+ temp = 0x1234;
+ for(j = 0; j < 4; j++) {
+ writew(temp, FBAddress);
+ if(readw(FBAddress) == temp)
+ break;
+ orSISIDXREG(SISSR, 0x3c, 0x01);
+ inSISIDXREG(SISSR, 0x05, reg);
+ inSISIDXREG(SISSR, 0x05, reg);
+ andSISIDXREG(SISSR, 0x3c, 0xfe);
+ inSISIDXREG(SISSR, 0x05, reg);
+ inSISIDXREG(SISSR, 0x05, reg);
+ temp++;
+ }
}
writel(0x01234567L, FBAddress);
- writel(0x456789ABL, (FBAddress+4));
- writel(0x89ABCDEFL, (FBAddress+8));
- writel(0xCDEF0123L, (FBAddress+12));
- inSISIDXREG(SISSR,0x3b,reg);
+ writel(0x456789ABL, (FBAddress + 4));
+ writel(0x89ABCDEFL, (FBAddress + 8));
+ writel(0xCDEF0123L, (FBAddress + 12));
+
+ inSISIDXREG(SISSR, 0x3b, reg);
if(reg & 0x01) {
- if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */
+ if(readl((FBAddress + 12)) == 0xCDEF0123L)
+ return 4; /* Channel A 128bit */
}
- if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */
- return(1); /* 32bit */
+
+ if(readl((FBAddress + 4)) == 0x456789ABL)
+ return 2; /* Channel B 64bit */
+
+ return 1; /* 32bit */
+}
+
+static int __devinit
+sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
+ int PseudoRankCapacity, int PseudoAdrPinCount,
+ unsigned int mapsize)
+{
+ SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+ unsigned short sr14;
+ unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
+ unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
+ static const unsigned short SiS_DRAMType[17][5] = {
+ {0x0C,0x0A,0x02,0x40,0x39},
+ {0x0D,0x0A,0x01,0x40,0x48},
+ {0x0C,0x09,0x02,0x20,0x35},
+ {0x0D,0x09,0x01,0x20,0x44},
+ {0x0C,0x08,0x02,0x10,0x31},
+ {0x0D,0x08,0x01,0x10,0x40},
+ {0x0C,0x0A,0x01,0x20,0x34},
+ {0x0C,0x09,0x01,0x08,0x32},
+ {0x0B,0x08,0x02,0x08,0x21},
+ {0x0C,0x08,0x01,0x08,0x30},
+ {0x0A,0x08,0x02,0x04,0x11},
+ {0x0B,0x0A,0x01,0x10,0x28},
+ {0x09,0x08,0x02,0x02,0x01},
+ {0x0B,0x09,0x01,0x08,0x24},
+ {0x0B,0x08,0x01,0x04,0x20},
+ {0x0A,0x08,0x01,0x02,0x10},
+ {0x09,0x08,0x01,0x01,0x00}
+ };
+
+ for(k = 0; k <= 16; k++) {
+
+ RankCapacity = buswidth * SiS_DRAMType[k][3];
+
+ if(RankCapacity != PseudoRankCapacity)
+ continue;
+
+ if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+ continue;
+
+ BankNumHigh = RankCapacity * 16 * iteration - 1;
+ if(iteration == 3) { /* Rank No */
+ BankNumMid = RankCapacity * 16 - 1;
+ } else {
+ BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
+ }
+
+ PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+ PhysicalAdrHigh = BankNumHigh;
+ PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+ PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+
+ andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
+ orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
+ sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
+ if(buswidth == 4) sr14 |= 0x80;
+ else if(buswidth == 2) sr14 |= 0x40;
+ outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
+ outSISIDXREG(SISSR, 0x14, sr14);
+
+ BankNumHigh <<= 16;
+ BankNumMid <<= 16;
+
+ if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
+ (BankNumMid + PhysicalAdrHigh >= mapsize) ||
+ (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
+ (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+ continue;
+
+ /* Write data */
+ writew(((unsigned short)PhysicalAdrHigh),
+ (FBAddr + BankNumHigh + PhysicalAdrHigh));
+ writew(((unsigned short)BankNumMid),
+ (FBAddr + BankNumMid + PhysicalAdrHigh));
+ writew(((unsigned short)PhysicalAdrHalfPage),
+ (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
+ writew(((unsigned short)PhysicalAdrOtherPage),
+ (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
+
+ /* Read data */
+ if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+ return 1;
+ }
+
+ return 0;
}
static void __devinit
-sisfb_setramsize300(struct pci_dev *pdev)
+sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
- SIS_IOTYPE1 *Addr;
- USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
- int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
- int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
- int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
- const USHORT SiS_DRAMType[17][5] = {
- {0x0C,0x0A,0x02,0x40,0x39},
- {0x0D,0x0A,0x01,0x40,0x48},
- {0x0C,0x09,0x02,0x20,0x35},
- {0x0D,0x09,0x01,0x20,0x44},
- {0x0C,0x08,0x02,0x10,0x31},
- {0x0D,0x08,0x01,0x10,0x40},
- {0x0C,0x0A,0x01,0x20,0x34},
- {0x0C,0x09,0x01,0x08,0x32},
- {0x0B,0x08,0x02,0x08,0x21},
- {0x0C,0x08,0x01,0x08,0x30},
- {0x0A,0x08,0x02,0x04,0x11},
- {0x0B,0x0A,0x01,0x10,0x28},
- {0x09,0x08,0x02,0x02,0x01},
- {0x0B,0x09,0x01,0x08,0x24},
- {0x0B,0x08,0x01,0x04,0x20},
- {0x0A,0x08,0x01,0x02,0x10},
- {0x09,0x08,0x01,0x01,0x00}
- };
-
- buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
-
- MB2Bank = 16;
- Done = 0;
- for(i = 6; i >= 0; i--) {
- if(Done) break;
- PseudoRankCapacity = 1 << i;
- for(j = 4; j >= 1; j--) {
- if(Done) break;
- PseudoTotalCapacity = PseudoRankCapacity * j;
- PseudoAdrPinCount = 15 - j;
- if(PseudoTotalCapacity <= 64) {
- for(k = 0; k <= 16; k++) {
- if(Done) break;
- RankCapacity = buswidth * SiS_DRAMType[k][3];
- AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
- if(RankCapacity == PseudoRankCapacity)
- if(AdrPinCount <= PseudoAdrPinCount) {
- if(j == 3) { /* Rank No */
- BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
- BankNumMid = RankCapacity * MB2Bank * 1 - 1;
- } else {
- BankNumHigh = RankCapacity * MB2Bank * j - 1;
- BankNumMid = RankCapacity * MB2Bank * j / 2 - 1;
- }
- PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
- PhysicalAdrHigh = BankNumHigh;
- PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
- PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
- /* Write data */
- andSISIDXREG(SISSR,0x15,0xFB); /* Test */
- orSISIDXREG(SISSR,0x15,0x04); /* Test */
- TotalCapacity = SiS_DRAMType[k][3] * buswidth;
- sr13 = SiS_DRAMType[k][4];
- if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80;
- if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40;
- if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00;
- outSISIDXREG(SISSR,0x13,sr13);
- outSISIDXREG(SISSR,0x14,sr14);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
- writew(((USHORT)PhysicalAdrHigh), Addr);
- Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
- writew(((USHORT)BankNumMid), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
- writew(((USHORT)PhysicalAdrHalfPage), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
- /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
- writew(((USHORT)PhysicalAdrOtherPage), Addr);
- /* Read data */
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- data = readw(Addr); /* *((USHORT *)(Addr)); */
- if(data == PhysicalAdrHigh) Done = 1;
- } /* if */
- } /* for k */
- } /* if */
- } /* for j */
- } /* for i */
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ int i, j, buswidth;
+ int PseudoRankCapacity, PseudoAdrPinCount;
+
+ buswidth = sisfb_post_300_buswidth(ivideo);
+
+ for(i = 6; i >= 0; i--) {
+ PseudoRankCapacity = 1 << i;
+ for(j = 4; j >= 1; j--) {
+ PseudoAdrPinCount = 15 - j;
+ if((PseudoRankCapacity * j) <= 64) {
+ if(sisfb_post_300_rwtest(ivideo,
+ j,
+ buswidth,
+ PseudoRankCapacity,
+ PseudoAdrPinCount,
+ mapsize))
+ return;
+ }
+ }
+ }
}
-static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
+static void __devinit
+sisfb_post_sis300(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
u16 index, rindex, memtype = 0;
+ unsigned int mapsize;
- outSISIDXREG(SISSR,0x05,0x86);
+ if(!ivideo->SiS_Pr.UseROM)
+ bios = NULL;
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x07;
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ if(bios) {
+ if(bios[0x52] & 0x80) {
+ memtype = bios[0x52];
+ } else {
+ inSISIDXREG(SISSR, 0x3a, memtype);
+ }
+ memtype &= 0x07;
}
+ v3 = 0x80; v6 = 0x80;
if(ivideo->revision_id <= 0x13) {
- v1 = 0x44; v2 = 0x42; v3 = 0x80;
- v4 = 0x44; v5 = 0x42; v6 = 0x80;
+ v1 = 0x44; v2 = 0x42;
+ v4 = 0x44; v5 = 0x42;
} else {
- v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */
- v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x7c;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
+ v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
+ v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
+ if(bios) {
+ index = memtype * 5;
+ rindex = index + 0x54;
+ v1 = bios[rindex++];
+ v2 = bios[rindex++];
+ v3 = bios[rindex++];
+ rindex = index + 0x7c;
+ v4 = bios[rindex++];
+ v5 = bios[rindex++];
+ v6 = bios[rindex++];
+ }
}
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
+ outSISIDXREG(SISSR, 0x28, v1);
+ outSISIDXREG(SISSR, 0x29, v2);
+ outSISIDXREG(SISSR, 0x2a, v3);
+ outSISIDXREG(SISSR, 0x2e, v4);
+ outSISIDXREG(SISSR, 0x2f, v5);
+ outSISIDXREG(SISSR, 0x30, v6);
+
v1 = 0x10;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
- outSISIDXREG(SISSR,0x07,v1); /* DAC speed */
- outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */
+ if(bios)
+ v1 = bios[0xa4];
+ outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
+
+ outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
+
v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- memtype += 0xa5;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
- }
- if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
- andSISIDXREG(SISSR,0x15,0xfb);
- orSISIDXREG(SISSR,0x15,0x04);
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
- orSISIDXREG(SISSR,0x19,0x20);
- }
+ if(bios) {
+ memtype += 0xa5;
+ v1 = bios[memtype];
+ v2 = bios[memtype + 8];
+ v3 = bios[memtype + 16];
+ v4 = bios[memtype + 24];
+ v5 = bios[memtype + 32];
+ v6 = bios[memtype + 40];
+ v7 = bios[memtype + 48];
+ v8 = bios[memtype + 56];
+ }
+ if(ivideo->revision_id >= 0x80)
+ v3 &= 0xfd;
+ outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+ outSISIDXREG(SISSR, 0x16, v2);
+ outSISIDXREG(SISSR, 0x17, v3);
+ outSISIDXREG(SISSR, 0x18, v4);
+ outSISIDXREG(SISSR, 0x19, v5);
+ outSISIDXREG(SISSR, 0x1a, v6);
+ outSISIDXREG(SISSR, 0x1b, v7);
+ outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
+ andSISIDXREG(SISSR, 0x15 ,0xfb);
+ orSISIDXREG(SISSR, 0x15, 0x04);
+ if(bios) {
+ if(bios[0x53] & 0x02) {
+ orSISIDXREG(SISSR, 0x19, 0x20);
+ }
}
v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
- if(ivideo->revision_id >= 0x80) v1 |= 0x01;
- outSISIDXREG(SISSR,0x1f,v1);
- outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */
+ if(ivideo->revision_id >= 0x80)
+ v1 |= 0x01;
+ outSISIDXREG(SISSR, 0x1f, v1);
+ outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
- }
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISCR,0x37,0x00);
- orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */
- outSISIDXREG(SISPART1,0x00,0x00);
+ if(bios) {
+ v1 = bios[0xe8];
+ v2 = bios[0xe9];
+ v3 = bios[0xea];
+ }
+ outSISIDXREG(SISSR, 0x23, v1);
+ outSISIDXREG(SISSR, 0x24, v2);
+ outSISIDXREG(SISSR, 0x25, v3);
+ outSISIDXREG(SISSR, 0x21, 0x84);
+ outSISIDXREG(SISSR, 0x22, 0x00);
+ outSISIDXREG(SISCR, 0x37, 0x00);
+ orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
+ outSISIDXREG(SISPART1, 0x00, 0x00);
v1 = 0x40; v2 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
+ if(bios) {
+ v1 = bios[0xec];
+ v2 = bios[0xeb];
}
- outSISIDXREG(SISPART1,0x02,v1);
- if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
- inSISIDXREG(SISPART4,0x00,reg);
+ outSISIDXREG(SISPART1, 0x02, v1);
+
+ if(ivideo->revision_id >= 0x80)
+ v2 &= ~0x01;
+
+ inSISIDXREG(SISPART4, 0x00, reg);
if((reg == 1) || (reg == 2)) {
- outSISIDXREG(SISCR,0x37,0x02);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v4 = 0x00; v5 = 0x00; v6 = 0x10;
- if(ivideo->sishw_ext.UseROM) {
- v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
- }
- outSISIDXREG(SISPART4,0x0d,v4);
- outSISIDXREG(SISPART4,0x0e,v5);
- outSISIDXREG(SISPART4,0x10,v6);
- outSISIDXREG(SISPART4,0x0f,0x3f);
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
+ outSISIDXREG(SISCR, 0x37, 0x02);
+ outSISIDXREG(SISPART2, 0x00, 0x1c);
+ v4 = 0x00; v5 = 0x00; v6 = 0x10;
+ if(ivideo->SiS_Pr.UseROM) {
+ v4 = bios[0xf5];
+ v5 = bios[0xf6];
+ v6 = bios[0xf7];
+ }
+ outSISIDXREG(SISPART4, 0x0d, v4);
+ outSISIDXREG(SISPART4, 0x0e, v5);
+ outSISIDXREG(SISPART4, 0x10, v6);
+ outSISIDXREG(SISPART4, 0x0f, 0x3f);
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if(reg >= 0xb0) {
+ inSISIDXREG(SISPART4, 0x23, reg);
+ reg &= 0x20;
+ reg <<= 1;
+ outSISIDXREG(SISPART4, 0x23, reg);
+ }
} else {
- v2 &= ~0x10;
+ v2 &= ~0x10;
}
- outSISIDXREG(SISSR,0x32,v2);
- andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */
- inSISIDXREG(SISSR,0x16,reg);
+ outSISIDXREG(SISSR, 0x32, v2);
+
+ andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
+
+ inSISIDXREG(SISSR, 0x16, reg);
reg &= 0xc3;
- outSISIDXREG(SISCR,0x35,reg);
- outSISIDXREG(SISCR,0x83,0x00);
+ outSISIDXREG(SISCR, 0x35, reg);
+ outSISIDXREG(SISCR, 0x83, 0x00);
#if !defined(__i386__) && !defined(__x86_64__)
if(sisfb_videoram) {
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- reg = ((sisfb_videoram >> 10) - 1) | 0x40;
- outSISIDXREG(SISSR,0x14,reg);
+ outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
+ reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+ outSISIDXREG(SISSR, 0x14, reg);
} else {
#endif
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- sisfb_setramsize300(pdev);
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */
- }
+ /* Need to map max FB size for finding out about RAM size */
+ mapsize = 64 << 20;
+ sisfb_post_map_vram(ivideo, &mapsize, 4);
+
+ if(ivideo->video_vbase) {
+ sisfb_post_300_ramsize(pdev, mapsize);
+ iounmap(ivideo->video_vbase);
+ } else {
+ printk(KERN_DEBUG
+ "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+ outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
+ outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
+ }
#if !defined(__i386__) && !defined(__x86_64__)
}
#endif
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
+ if(bios) {
+ v1 = bios[0xe6];
+ v2 = bios[0xe7];
} else {
- inSISIDXREG(SISSR,0x3a,reg);
- if((reg & 0x30) == 0x30) {
- v1 = 0x04; /* PCI */
- v2 = 0x92;
- } else {
- v1 = 0x14; /* AGP */
- v2 = 0xb2;
- }
+ inSISIDXREG(SISSR, 0x3a, reg);
+ if((reg & 0x30) == 0x30) {
+ v1 = 0x04; /* PCI */
+ v2 = 0x92;
+ } else {
+ v1 = 0x14; /* AGP */
+ v2 = 0xb2;
+ }
}
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
+ outSISIDXREG(SISSR, 0x21, v1);
+ outSISIDXREG(SISSR, 0x22, v2);
+
+ /* Sense CRT1 */
+ sisfb_sense_crt1(ivideo);
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Display off */
+ orSISIDXREG(SISSR, 0x01, 0x20);
+
+ /* Save mode number in CR34 */
+ outSISIDXREG(SISCR, 0x34, 0x2e);
+
+ /* Let everyone know what the current mode is */
+ ivideo->modeprechange = 0x2e;
}
#endif
#ifdef CONFIG_FB_SIS_315
-static void __devinit sisfb_post_sis315330(struct pci_dev *pdev)
+#if 0
+static void __devinit
+sisfb_post_sis315330(struct pci_dev *pdev)
{
-#ifdef YET_TO_BE_DONE
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
- u16 index, rindex, memtype = 0;
- u32 reg1_32, reg2_32, reg3_32;
+ /* TODO */
+}
+#endif
+
+static void __devinit
+sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
+{
+ unsigned int i;
+ u8 reg;
+
+ for(i = 0; i <= (delay * 10 * 36); i++) {
+ inSISIDXREG(SISSR, 0x05, reg);
+ reg++;
+ }
+}
+
+static int __devinit
+sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
+ unsigned short pcivendor)
+{
+ struct pci_dev *pdev = NULL;
+ unsigned short temp;
+ int ret = 0;
+
+ while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
+ temp = pdev->vendor;
+ SIS_PCI_PUT_DEVICE(pdev);
+ if(temp == pcivendor) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int __devinit
+sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
+ unsigned int enda, unsigned int mapsize)
+{
+ unsigned int pos;
int i;
- /* Unlock */
- /* outSISIDXREG(0x3c4,0x05,0x86); */
- outSISIDXREG(SISSR,0x05,0x86);
+ writel(0, ivideo->video_vbase);
- /* Enable relocated i/o ports */
- /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */
- setSISIDXREG(SISSR,0x20,~0x10,0x20);
+ for(i = starta; i <= enda; i++) {
+ pos = 1 << i;
+ if(pos < mapsize)
+ writel(pos, ivideo->video_vbase + pos);
+ }
+
+ sisfb_post_xgi_delay(ivideo, 150);
+
+ if(readl(ivideo->video_vbase) != 0)
+ return 0;
- /* Clear regs */
+ for(i = starta; i <= enda; i++) {
+ pos = 1 << i;
+ if(pos < mapsize) {
+ if(readl(ivideo->video_vbase + pos) != pos)
+ return 0;
+ } else
+ return 0;
+ }
+
+ return 1;
+}
+
+static void __devinit
+sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
+{
+ unsigned int buswidth, ranksize, channelab, mapsize;
+ int i, j, k, l;
+ u8 reg, sr14;
+ static const u8 dramsr13[12 * 5] = {
+ 0x02, 0x0e, 0x0b, 0x80, 0x5d,
+ 0x02, 0x0e, 0x0a, 0x40, 0x59,
+ 0x02, 0x0d, 0x0b, 0x40, 0x4d,
+ 0x02, 0x0e, 0x09, 0x20, 0x55,
+ 0x02, 0x0d, 0x0a, 0x20, 0x49,
+ 0x02, 0x0c, 0x0b, 0x20, 0x3d,
+ 0x02, 0x0e, 0x08, 0x10, 0x51,
+ 0x02, 0x0d, 0x09, 0x10, 0x45,
+ 0x02, 0x0c, 0x0a, 0x10, 0x39,
+ 0x02, 0x0d, 0x08, 0x08, 0x41,
+ 0x02, 0x0c, 0x09, 0x08, 0x35,
+ 0x02, 0x0c, 0x08, 0x04, 0x31
+ };
+ static const u8 dramsr13_4[4 * 5] = {
+ 0x02, 0x0d, 0x09, 0x40, 0x45,
+ 0x02, 0x0c, 0x09, 0x20, 0x35,
+ 0x02, 0x0c, 0x08, 0x10, 0x31,
+ 0x02, 0x0b, 0x08, 0x08, 0x21
+ };
+
+ /* Enable linear mode, disable 0xa0000 address decoding */
+ /* We disable a0000 address decoding, because
+ * - if running on x86, if the card is disabled, it means
+ * that another card is in the system. We don't want
+ * to interphere with that primary card's textmode.
+ * - if running on non-x86, there usually is no VGA window
+ * at a0000.
+ */
+ orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
+
+ /* Need to map max FB size for finding out about RAM size */
+ mapsize = 256 << 20;
+ sisfb_post_map_vram(ivideo, &mapsize, 32);
+
+ if(!ivideo->video_vbase) {
+ printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
+ outSISIDXREG(SISSR, 0x13, 0x35);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ /* TODO */
+ return;
+ }
+
+ /* Non-interleaving */
+ outSISIDXREG(SISSR, 0x15, 0x00);
+ /* No tiling */
+ outSISIDXREG(SISSR, 0x1c, 0x00);
+
+ if(ivideo->chip == XGI_20) {
+
+ channelab = 1;
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(!(reg & 0x01)) { /* Single 32/16 */
+ buswidth = 32;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x52);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x02;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ outSISIDXREG(SISSR, 0x14, 0x42);
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
+ goto bail_out;
+
+ buswidth = 16;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x01;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+ else
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ } else { /* Dual 16/8 */
+ buswidth = 16;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x41);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x01;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ outSISIDXREG(SISSR, 0x14, 0x31);
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
+ goto bail_out;
+
+ buswidth = 8;
+ outSISIDXREG(SISSR, 0x13, 0xb1);
+ outSISIDXREG(SISSR, 0x14, 0x30);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x00;
+ if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
+ goto bail_out;
+ else
+ outSISIDXREG(SISSR, 0x13, 0x31);
+ }
+
+ } else { /* XGI_40 */
+
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(!(reg & 0x10)) {
+ inSISIDXREG(SISSR, 0x39, reg);
+ reg >>= 1;
+ }
+
+ if(reg & 0x01) { /* DDRII */
+ buswidth = 32;
+ if(ivideo->revision_id == 2) {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x44);
+ sr14 = 0x04;
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x34);
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ channelab = 1;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x40);
+ sr14 = 0x00;
+ if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x30);
+ } else {
+ channelab = 3;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x4c);
+ sr14 = 0x0c;
+ sisfb_post_xgi_delay(ivideo, 1);
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
+ goto bail_out;
+
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x14, 0x48);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x08;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x3c);
+ sr14 = 0x0c;
+
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
+ channelab = 3;
+ } else {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x14, 0x38);
+ sr14 = 0x08;
+ }
+ }
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ } else { /* DDR */
+
+ buswidth = 64;
+ if(ivideo->revision_id == 2) {
+ channelab = 1;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x52);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x02;
+ if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x42);
+ } else {
+ channelab = 2;
+ outSISIDXREG(SISSR, 0x13, 0xa1);
+ outSISIDXREG(SISSR, 0x14, 0x5a);
+ sisfb_post_xgi_delay(ivideo, 1);
+ sr14 = 0x0a;
+ if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
+ goto bail_out;
+
+ outSISIDXREG(SISSR, 0x13, 0x21);
+ outSISIDXREG(SISSR, 0x14, 0x4a);
+ }
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ }
+ }
+
+bail_out:
+ setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ j = (ivideo->chip == XGI_20) ? 5 : 9;
+ k = (ivideo->chip == XGI_20) ? 12 : 4;
+
+ for(i = 0; i < k; i++) {
+
+ reg = (ivideo->chip == XGI_20) ?
+ dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
+ setSISIDXREG(SISSR, 0x13, 0x80, reg);
+ sisfb_post_xgi_delay(ivideo, 50);
+
+ ranksize = (ivideo->chip == XGI_20) ?
+ dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
+
+ inSISIDXREG(SISSR, 0x13, reg);
+ if(reg & 0x80) ranksize <<= 1;
+
+ if(ivideo->chip == XGI_20) {
+ if(buswidth == 16) ranksize <<= 1;
+ else if(buswidth == 32) ranksize <<= 2;
+ } else {
+ if(buswidth == 64) ranksize <<= 1;
+ }
+
+ reg = 0;
+ l = channelab;
+ if(l == 3) l = 4;
+ if((ranksize * l) <= 256) {
+ while((ranksize >>= 1)) reg += 0x10;
+ }
+
+ if(!reg) continue;
+
+ setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
+ sisfb_post_xgi_delay(ivideo, 1);
+
+ if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
+ break;
+ }
+
+ iounmap(ivideo->video_vbase);
+}
+
+static void __devinit
+sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
+{
+ u8 v1, v2, v3;
+ int index;
+ static const u8 cs90[8 * 3] = {
+ 0x16, 0x01, 0x01,
+ 0x3e, 0x03, 0x01,
+ 0x7c, 0x08, 0x01,
+ 0x79, 0x06, 0x01,
+ 0x29, 0x01, 0x81,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01
+ };
+ static const u8 csb8[8 * 3] = {
+ 0x5c, 0x23, 0x01,
+ 0x29, 0x01, 0x01,
+ 0x7c, 0x08, 0x01,
+ 0x79, 0x06, 0x01,
+ 0x29, 0x01, 0x81,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01,
+ 0x5c, 0x23, 0x01
+ };
+
+ regb = 0; /* ! */
+
+ index = regb * 3;
+ v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
+ if(ivideo->haveXGIROM) {
+ v1 = ivideo->bios_abase[0x90 + index];
+ v2 = ivideo->bios_abase[0x90 + index + 1];
+ v3 = ivideo->bios_abase[0x90 + index + 2];
+ }
+ outSISIDXREG(SISSR, 0x28, v1);
+ outSISIDXREG(SISSR, 0x29, v2);
+ outSISIDXREG(SISSR, 0x2a, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ index = regb * 3;
+ v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
+ if(ivideo->haveXGIROM) {
+ v1 = ivideo->bios_abase[0xb8 + index];
+ v2 = ivideo->bios_abase[0xb8 + index + 1];
+ v3 = ivideo->bios_abase[0xb8 + index + 2];
+ }
+ outSISIDXREG(SISSR, 0x2e, v1);
+ outSISIDXREG(SISSR, 0x2f, v2);
+ outSISIDXREG(SISSR, 0x30, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+}
+
+static int __devinit
+sisfb_post_xgi(struct pci_dev *pdev)
+{
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ unsigned char *bios = ivideo->bios_abase;
+ struct pci_dev *mypdev = NULL;
+ const u8 *ptr, *ptr2;
+ u8 v1, v2, v3, v4, v5, reg, ramtype;
+ u32 rega, regb, regd;
+ int i, j, k, index;
+ static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
+ static const u8 cs76[2] = { 0xa3, 0xfb };
+ static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
+ static const u8 cs158[8] = {
+ 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs160[8] = {
+ 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs168[8] = {
+ 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs128[3 * 8] = {
+ 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs148[2 * 8] = {
+ 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs31a[8 * 4] = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs33a[8 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs45a[8 * 2] = {
+ 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs170[7 * 8] = {
+ 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs1a8[3 * 8] = {
+ 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const u8 cs100[2 * 8] = {
+ 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ /* VGA enable */
+ reg = inSISREG(SISVGAENABLE) | 0x01;
+ outSISREG(SISVGAENABLE, reg);
+
+ /* Misc */
+ reg = inSISREG(SISMISCR) | 0x01;
+ outSISREG(SISMISCW, reg);
+
+ /* Unlock SR */
+ outSISIDXREG(SISSR, 0x05, 0x86);
+ inSISIDXREG(SISSR, 0x05, reg);
+ if(reg != 0xa1)
+ return 0;
+
+ /* Clear some regs */
for(i = 0; i < 0x22; i++) {
- outSISIDXREG(SISSR,(0x06 + i),0x00);
+ if(0x06 + i == 0x20) continue;
+ outSISIDXREG(SISSR, 0x06 + i, 0x00);
}
- v1 = 0x0d;
- if( is 330) v1 = 0x0b;
- for(i = 0; i < v1; i++) {
- outSISIDXREG(SISSR,(0x31 + i),0x00);
+ for(i = 0; i < 0x0b; i++) {
+ outSISIDXREG(SISSR, 0x31 + i, 0x00);
}
for(i = 0; i < 0x10; i++) {
- outSISIDXREG(SISCR,(0x30 + i),0x00);
- }
-
- /* Reset clocks */
- reg = inSISREG(SISMISCR);
- outSISIDXREG(SISSR,0x28,0x81);
- outSISIDXREG(SISSR,0x2A,0x00);
- outSISIDXREG(SISSR,0x29,0xE1);
- outSISREG(SISMISCW,(reg | 0x0c));
- outSISIDXREG(SISSR,0x2B,0x81);
- outSISIDXREG(SISSR,0x2D,0x00);
- outSISIDXREG(SISSR,0x2C,0xE1);
- outSISIDXREG(SISSR,0x2E,0x81);
- outSISIDXREG(SISSR,0x30,0x00);
- outSISIDXREG(SISSR,0x2F,0xE1);
- SiS_DDC2Delay(....);
- outSISREG(SISMISCW,reg);
-
- /* Get memory type */
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x03;
- if( is 330 ) {
- if(memtype <= 1) memtype = 0;
- else {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- switch(reg) {
- case 0x00: memtype = 1; break;
- case 0x10: memtype = 3; break;
- case 0x20: memtype = 3; break;
- default: memtype = 2;
- }
- }
- }
+ outSISIDXREG(SISCR, 0x30 + i, 0x00);
}
- /* Set clocks */
- v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */
- v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x68;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- if( is 330 ) {
- inSISIDXREG(SISSR,0x3a,reg);
- reg &= 0x03;
- if(reg >= 2) {
- ...
- }
+ ptr = cs78;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x78];
+ }
+ for(i = 0; i < 3; i++) {
+ outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
+ }
+
+ ptr = cs76;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x76];
+ }
+ for(i = 0; i < 2; i++) {
+ outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
+ }
+
+ v1 = 0x18; v2 = 0x00;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x74];
+ v2 = bios[0x75];
+ }
+ outSISIDXREG(SISSR, 0x07, v1);
+ outSISIDXREG(SISSR, 0x11, 0x0f);
+ outSISIDXREG(SISSR, 0x1f, v2);
+ /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
+ outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+ outSISIDXREG(SISSR, 0x27, 0x74);
+
+ ptr = cs7b;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x7b];
+ }
+ for(i = 0; i < 3; i++) {
+ outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
}
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
-
- /* End of comp with 330 */
-
- v1 = 0x18;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
- outSISIDXREG(SISSR,0x07,v1);
- outSISIDXREG(SISSR,0x11,0x0f);
-
- v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
- v5 = 0xa0; v6 = 0x00; v7 = 0x30;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0x7d;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- }
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
-
- v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xa2;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- }
- outSISIDXREG(SISCR,0x40,v1);
- outSISIDXREG(SISCR,0x41,v2);
- outSISIDXREG(SISCR,0x42,v3);
- outSISIDXREG(SISCR,0x43,v4);
- outSISIDXREG(SISCR,0x44,v5);
-
- if( is 330 ) {
-
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
-
- v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
- v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xbe;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
- }
- outSISIDXREG(SISCR,0x68,v1);
- outSISIDXREG(SISCR,0x69,v2);
- outSISIDXREG(SISCR,0x6a,v3);
- outSISIDXREG(SISCR,0x6b,v4);
- outSISIDXREG(SISCR,0x6c,v5);
- outSISIDXREG(SISCR,0x6d,v6);
- outSISIDXREG(SISCR,0x6e,v7);
- outSISIDXREG(SISCR,0x6f,v8);
-
- v1 = 0x20;
- inSISIDXREG(SISSR,0x3b,reg);
-
- if(!(reg & 0x04)) {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- if(reg) v1 = 0x23;
- }
- outSISIDXREG(SISCR,0x48,v1);
- outSISIDXREG(SISCR,0x4c,0x20);
-
- xx= xxx();
- if(xx >= 1) {
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
- }
+ if(ivideo->chip == XGI_40) {
+ if(ivideo->revision_id == 2) {
+ setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
+ }
+ outSISIDXREG(SISCR, 0x7d, 0xfe);
+ outSISIDXREG(SISCR, 0x7e, 0x0f);
+ }
+ if(ivideo->revision_id == 0) { /* 40 *and* 20? */
+ andSISIDXREG(SISCR, 0x58, 0xd7);
+ inSISIDXREG(SISCR, 0xcb, reg);
+ if(reg & 0x20) {
+ setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+ }
+ }
+ reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
+ setSISIDXREG(SISCR, 0x38, 0x1f, reg);
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISSR, 0x36, 0x70);
} else {
+ outSISIDXREG(SISVID, 0x00, 0x86);
+ outSISIDXREG(SISVID, 0x32, 0x00);
+ outSISIDXREG(SISVID, 0x30, 0x00);
+ outSISIDXREG(SISVID, 0x32, 0x01);
+ outSISIDXREG(SISVID, 0x30, 0x00);
+ andSISIDXREG(SISVID, 0x2f, 0xdf);
+ andSISIDXREG(SISCAP, 0x00, 0x3f);
+
+ outSISIDXREG(SISPART1, 0x2f, 0x01);
+ outSISIDXREG(SISPART1, 0x00, 0x00);
+ outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
+ outSISIDXREG(SISPART1, 0x2e, 0x08);
+ andSISIDXREG(SISPART1, 0x35, 0x7f);
+ andSISIDXREG(SISPART1, 0x50, 0xfe);
+
+ inSISIDXREG(SISPART4, 0x00, reg);
+ if(reg == 1 || reg == 2) {
+ outSISIDXREG(SISPART2, 0x00, 0x1c);
+ outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
+ outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
+ outSISIDXREG(SISPART4, 0x10, bios[0x81]);
+ andSISIDXREG(SISPART4, 0x0f, 0x3f);
+
+ inSISIDXREG(SISPART4, 0x01, reg);
+ if((reg & 0xf0) >= 0xb0) {
+ inSISIDXREG(SISPART4, 0x23, reg);
+ if(reg & 0x20) reg |= 0x40;
+ outSISIDXREG(SISPART4, 0x23, reg);
+ reg = (reg & 0x20) ? 0x02 : 0x00;
+ setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
+ }
+ }
- outSISIDXREG(SISCR,0x48,0x23);
+ v1 = bios[0x77];
+
+ inSISIDXREG(SISSR, 0x3b, reg);
+ if(reg & 0x02) {
+ inSISIDXREG(SISSR, 0x3a, reg);
+ v2 = (reg & 0x30) >> 3;
+ if(!(v2 & 0x04)) v2 ^= 0x02;
+ inSISIDXREG(SISSR, 0x39, reg);
+ if(reg & 0x80) v2 |= 0x80;
+ v2 |= 0x01;
+
+ if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
+ SIS_PCI_PUT_DEVICE(mypdev);
+ if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
+ v2 &= 0xf9;
+ v2 |= 0x08;
+ v1 &= 0xfe;
+ } else {
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
+ if(!mypdev)
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
+ if(!mypdev)
+ mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
+ if(mypdev) {
+ pci_read_config_dword(mypdev, 0x94, &regd);
+ regd &= 0xfffffeff;
+ pci_write_config_dword(mypdev, 0x94, regd);
+ v1 &= 0xfe;
+ SIS_PCI_PUT_DEVICE(mypdev);
+ } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
+ v1 &= 0xfe;
+ } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
+ sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
+ if((v2 & 0x06) == 4)
+ v2 ^= 0x06;
+ v2 |= 0x08;
+ }
+ }
+ setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
+ }
+ outSISIDXREG(SISSR, 0x22, v1);
+
+ if(ivideo->revision_id == 2) {
+ inSISIDXREG(SISSR, 0x3b, v1);
+ inSISIDXREG(SISSR, 0x3a, v2);
+ regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
+ if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
+ setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+
+ if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
+ /* TODO: set CR5f &0xf1 | 0x01 for version 6570
+ * of nforce 2 ROM
+ */
+ if(0)
+ setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+ SIS_PCI_PUT_DEVICE(mypdev);
+ }
+ }
- andSISIDXREG(SISSR,0x16,0x0f);
- if(memtype <= 1) {
- orSISIDXREG(SISSR,0x16,0x80);
- } else {
- v1 = 0x0f;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype];
- }
- if(!(v1 & 0x10)) v2 = 0xc0;
- else v2 = 0xd0;
- orSISIDXREG(SISSR,0x16,v2);
- andSISIDXREG(SISSR,0x16,0x0f);
- if(!(v1 & 0x10)) v2 = 0x80;
- else v2 = 0xA0;
- orSISIDXREG(SISSR,0x16,v2);
- }
-
- if(memtype >= 2) {
- const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
- const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg1_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg2_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- reg3_32 = reg2_32 << 1;
- reg2_32 >>= 1;
- reg3_32 += reg2_32;
- v1 = 0x40;
- if(reg3_32 > reg1_32) v1 = 0x10;
- outSISIDXREG(SISCR,0x59,v1);
- }
+ v1 = 0x30;
+ inSISIDXREG(SISSR, 0x3b, reg);
+ inSISIDXREG(SISCR, 0x5f, v2);
+ if((!(reg & 0x02)) && (v2 & 0x0e))
+ v1 |= 0x08;
+ outSISIDXREG(SISSR, 0x27, v1);
+
+ if(bios[0x64] & 0x01) {
+ setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
+ }
+ v1 = bios[0x4f7];
+ pci_read_config_dword(pdev, 0x50, &regd);
+ regd = (regd >> 20) & 0x0f;
+ if(regd == 1) {
+ v1 &= 0xfc;
+ orSISIDXREG(SISCR, 0x5f, 0x08);
+ }
+ outSISIDXREG(SISCR, 0x48, v1);
+
+ setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+ setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+ setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+ setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+ setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+ outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
+ setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+ outSISIDXREG(SISCR, 0x74, 0xd0);
+ setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+ setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+ setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+ v1 = bios[0x501];
+ if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
+ v1 = 0xf0;
+ SIS_PCI_PUT_DEVICE(mypdev);
+ }
+ outSISIDXREG(SISCR, 0x77, v1);
}
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99];
+ /* RAM type */
+
+ regb = 0; /* ! */
+
+ v1 = 0xff;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x140 + regb];
}
- outSISIDXREG(SISSR,0x1f,v1);
+ outSISIDXREG(SISCR, 0x6d, v1);
- outSISIDXREG(SISSR,0x20,0x20);
+ ptr = cs128;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x128];
+ }
+ for(i = 0, j = 0; i < 3; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
+ }
- v1 = 0xf6; v2 = 0x0d; v3 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e];
+ ptr = cs31a;
+ ptr2 = cs33a;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
+ ptr = (const u8 *)&bios[index];
+ ptr2 = (const u8 *)&bios[index + 0x20];
+ }
+ for(i = 0; i < 2; i++) {
+ if(i == 0) {
+ regd = le32_to_cpu(((u32 *)ptr)[regb]);
+ rega = 0x6b;
+ } else {
+ regd = le32_to_cpu(((u32 *)ptr2)[regb]);
+ rega = 0x6e;
+ }
+ reg = 0x00;
+ for(j = 0; j < 16; j++) {
+ reg &= 0xf3;
+ if(regd & 0x01) reg |= 0x04;
+ if(regd & 0x02) reg |= 0x08;
+ regd >>= 2;
+ outSISIDXREG(SISCR, rega, reg);
+ inSISIDXREG(SISCR, rega, reg);
+ inSISIDXREG(SISCR, rega, reg);
+ reg += 0x10;
+ }
}
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISSR,0x27,0x1f);
+ andSISIDXREG(SISCR, 0x6e, 0xfc);
- v1 = 0x00; v2 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1];
- }
- outSISIDXREG(SISSR,0x31,v1);
- outSISIDXREG(SISSR,0x33,v2);
-
- v1 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0];
- }
- v2 = inSISIDXREG(SISPART4,0x00);
- if((v2 != 1) && (v2 != 2)) v1 &= 0xef;
- outSISIDXREG(SISSR,0x32,v1);
-
- /* AGP */
- pci_read_config_long(pdev, 0x50, &reg1_32);
- reg1_32 >>= 20;
- reg1_32 &= 0x0f;
- if(reg1_32 == 1) {
- v1 = 0xAA; v2 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E];
- }
- } else {
- v1 = 0x88; v2 = 0x03;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
- }
+ ptr = NULL;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
+ ptr = (const u8 *)&bios[index];
+ }
+ for(i = 0; i < 4; i++) {
+ setSISIDXREG(SISCR, 0x6e, 0xfc, i);
+ reg = 0x00;
+ for(j = 0; j < 2; j++) {
+ regd = 0;
+ if(ptr) {
+ regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
+ ptr += 4;
+ }
+ /* reg = 0x00; */
+ for(k = 0; k < 16; k++) {
+ reg &= 0xfc;
+ if(regd & 0x01) reg |= 0x01;
+ if(regd & 0x02) reg |= 0x02;
+ regd >>= 2;
+ outSISIDXREG(SISCR, 0x6f, reg);
+ inSISIDXREG(SISCR, 0x6f, reg);
+ inSISIDXREG(SISCR, 0x6f, reg);
+ reg += 0x08;
+ }
+ }
}
- outSISIDXREG(SISCR,0x49,v1);
- outSISIDXREG(SISSR,0x25,v2);
- v1 = inSISIDXREG(SISPART4,0x00);
- if((v1 == 1) || (v1 == 2)) {
- orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */
- outSISIDXREG(SISPART1,0x00,0x00);
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
- }
- outSISIDXREG(SISPART1,0x02,v1);
- outSISIDXREG(SISPART1,0x2E,0x08);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v1 = 0x40; v2 = 0x00; v3 = 0x80;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
- }
- outSISIDXREG(SISPART4,0x0d,v1);
- outSISIDXREG(SISPART4,0x0e,v2);
- outSISIDXREG(SISPART4,0x10,v3);
- outSISIDXREG(SISPART4,0x0F,0x3F);
-
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
+ ptr = cs148;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x148];
+ }
+ for(i = 0, j = 0; i < 2; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
}
- outSISIDXREG(SISCR,0x37,0x02); /* Why? */
-
- outSISIDXREG(SISCR,0x83,0x00);
- outSISIDXREG(SISCR,0x90,0x00);
- andSISIDXREG(SISSR,0x5B,0xDF);
- outSISIDXREG(SISVID,0x00,0x86);
- outSISIDXREG(SISVID,0x32,0x00);
- outSISIDXREG(SISVID,0x30,0x00);
- outSISIDXREG(SISVID,0x32,0x01);
- outSISIDXREG(SISVID,0x30,0x00);
- orSISIDXREG(SISCR,0x63,0x80);
- /* End of Init1 */
-
- /* Set Mode 0x2e */
-
- /* Ramsize */
- orSISIDXREG(SISSR,0x16,0x0f);
- orSISIDXREG(SISSR,0x18,0xA9);
- orSISIDXREG(SISSR,0x19,0xA0);
- orSISIDXREG(SISSR,0x1B,0x30);
- andSISIDXREG(SISSR,0x17,0xF8);
- orSISIDXREG(SISSR,0x19,0x03);
- andSIDIDXREG(SISSR,0x13,0x00);
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- /* Find out about bus width */
- if(memtype <= 1) {
- outSISIDXREG(SISSR,0x14,0x02);
- andSISIDXREG(SISSR,0x16,0x0F);
- orSISIDXREG(SISSR,0x16,0x80);
+ andSISIDXREG(SISCR, 0x89, 0x8f);
- ...
+ ptr = cs45a;
+ if(ivideo->haveXGIROM) {
+ index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
+ ptr = (const u8 *)&bios[index];
+ }
+ regd = le16_to_cpu(((const u16 *)ptr)[regb]);
+ reg = 0x80;
+ for(i = 0; i < 5; i++) {
+ reg &= 0xfc;
+ if(regd & 0x01) reg |= 0x01;
+ if(regd & 0x02) reg |= 0x02;
+ regd >>= 2;
+ outSISIDXREG(SISCR, 0x89, reg);
+ inSISIDXREG(SISCR, 0x89, reg);
+ inSISIDXREG(SISCR, 0x89, reg);
+ reg += 0x10;
+ }
- } else {
+ v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x118 + regb];
+ v2 = bios[0xf8 + regb];
+ v3 = bios[0x120 + regb];
+ v4 = bios[0x1ca];
+ }
+ outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
+ outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
+ orSISIDXREG(SISCR, 0x40, v1 & 0x80);
+ outSISIDXREG(SISCR, 0x41, v2);
- ...
+ ptr = cs170;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x170];
+ }
+ for(i = 0, j = 0; i < 7; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
+ }
- }
+ outSISIDXREG(SISCR, 0x59, v3);
- /* Find out about size */
+ ptr = cs1a8;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x1a8];
+ }
+ for(i = 0, j = 0; i < 3; i++, j += 8) {
+ outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
+ }
+ ptr = cs100;
+ if(ivideo->haveXGIROM) {
+ ptr = (const u8 *)&bios[0x100];
+ }
+ for(i = 0, j = 0; i < 2; i++, j += 8) {
+ outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
+ }
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */
+ outSISIDXREG(SISCR, 0xcf, v4);
+
+ outSISIDXREG(SISCR, 0x83, 0x09);
+ outSISIDXREG(SISCR, 0x87, 0x00);
+
+ if(ivideo->chip == XGI_40) {
+ if( (ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2) ) {
+ outSISIDXREG(SISCR, 0x8c, 0x87);
+ }
+ }
+
+ outSISIDXREG(SISSR, 0x17, 0x00);
+ outSISIDXREG(SISSR, 0x1a, 0x87);
+
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISSR, 0x15, 0x00);
+ outSISIDXREG(SISSR, 0x1c, 0x00);
+ }
+
+ ramtype = 0x00; v1 = 0x10;
+ if(ivideo->haveXGIROM) {
+ ramtype = bios[0x62];
+ v1 = bios[0x1d2];
+ }
+ if(!(ramtype & 0x80)) {
+ if(ivideo->chip == XGI_20) {
+ outSISIDXREG(SISCR, 0x97, v1);
+ inSISIDXREG(SISCR, 0x97, reg);
+ if(reg & 0x10) {
+ ramtype = (reg & 0x01) << 1;
+ }
+ } else {
+ inSISIDXREG(SISSR, 0x39, reg);
+ ramtype = reg & 0x02;
+ if(!(ramtype)) {
+ inSISIDXREG(SISSR, 0x3a, reg);
+ ramtype = (reg >> 1) & 0x01;
+ }
+ }
+ }
+ ramtype &= 0x07;
+
+ regb = 0; /* ! */
+
+ switch(ramtype) {
+ case 0:
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2)) {
+ v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x158];
+ v2 = bios[regb + 0x160];
+ v3 = bios[regb + 0x168];
+ }
+ outSISIDXREG(SISCR, 0x82, v1);
+ outSISIDXREG(SISCR, 0x85, v2);
+ outSISIDXREG(SISCR, 0x86, v3);
+ } else {
+ outSISIDXREG(SISCR, 0x82, 0x88);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+ outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+ }
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISCR, 0x97, 0x00);
+ }
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ outSISIDXREG(SISSR, 0x18, 0x01);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ } else {
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ }
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ if((ivideo->chip == XGI_20) ||
+ (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ } else {
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ }
+ } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
+ /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
+ }
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 4);
+ v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
+ v2 = bios[index];
+ v3 = bios[index + 1];
+ v4 = bios[index + 2];
+ v5 = bios[index + 3];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+ outSISIDXREG(SISSR, 0x16, v2);
+ outSISIDXREG(SISSR, 0x16, v3);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x1b, 0x03);
+ sisfb_post_xgi_delay(ivideo, 0x22);
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x00);
+ outSISIDXREG(SISSR, 0x16, v4);
+ outSISIDXREG(SISSR, 0x16, v5);
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ break;
+ case 1:
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ inSISIDXREG(SISCR, 0x86, reg);
+ v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x168];
+ v2 = bios[regb + 0x160];
+ v3 = bios[regb + 0x158];
+ }
+ outSISIDXREG(SISCR, 0x86, v1);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, v2);
+ outSISIDXREG(SISCR, 0x82, v3);
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ outSISIDXREG(SISSR, 0x28, 0x64);
+ outSISIDXREG(SISSR, 0x29, 0x63);
+ sisfb_post_xgi_delay(ivideo, 15);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ outSISIDXREG(SISSR, 0x19, 0x20);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ outSISIDXREG(SISSR, 0x18, 0xc5);
+ outSISIDXREG(SISSR, 0x19, 0x23);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISCR, 0x97,0x11);
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ sisfb_post_xgi_delay(ivideo, 0x46);
+ outSISIDXREG(SISSR, 0x18, 0xc5);
+ outSISIDXREG(SISSR, 0x19, 0x23);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISSR, 0x1b, 0x04);
+ sisfb_post_xgi_delay(ivideo, 1);
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ sisfb_post_xgi_delay(ivideo, 1);
+ v1 = 0x31;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x06);
+ outSISIDXREG(SISSR, 0x16, 0x04);
+ outSISIDXREG(SISSR, 0x16, 0x84);
+ sisfb_post_xgi_delay(ivideo, 1);
+ break;
+ default:
+ sisfb_post_xgi_setclocks(ivideo, regb);
+ if((ivideo->chip == XGI_40) &&
+ ((ivideo->revision_id == 1) ||
+ (ivideo->revision_id == 2))) {
+ outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+ outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+ outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+ } else {
+ outSISIDXREG(SISCR, 0x82, 0x88);
+ outSISIDXREG(SISCR, 0x86, 0x00);
+ inSISIDXREG(SISCR, 0x86, reg);
+ outSISIDXREG(SISCR, 0x86, 0x88);
+ outSISIDXREG(SISCR, 0x82, 0x77);
+ outSISIDXREG(SISCR, 0x85, 0x00);
+ inSISIDXREG(SISCR, 0x85, reg);
+ outSISIDXREG(SISCR, 0x85, 0x88);
+ inSISIDXREG(SISCR, 0x85, reg);
+ v1 = cs160[regb]; v2 = cs158[regb];
+ if(ivideo->haveXGIROM) {
+ v1 = bios[regb + 0x160];
+ v2 = bios[regb + 0x158];
+ }
+ outSISIDXREG(SISCR, 0x85, v1);
+ outSISIDXREG(SISCR, 0x82, v2);
+ }
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISCR, 0x97, 0x11);
+ }
+ if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
+ outSISIDXREG(SISCR, 0x98, 0x01);
+ } else {
+ outSISIDXREG(SISCR, 0x98, 0x03);
+ }
+ outSISIDXREG(SISCR, 0x9a, 0x02);
+
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x18, 0x01);
+ } else {
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ }
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ outSISIDXREG(SISSR, 0x18, 0x00);
+ outSISIDXREG(SISSR, 0x19, 0x40);
+ outSISIDXREG(SISSR, 0x16, 0x00);
+ outSISIDXREG(SISSR, 0x16, 0x80);
+ }
+ sisfb_post_xgi_delay(ivideo, 4);
+ v1 = 0x31;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0xf0];
+ }
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x01);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x16, bios[0x53e]);
+ outSISIDXREG(SISSR, 0x16, bios[0x53f]);
+ } else {
+ outSISIDXREG(SISSR, 0x16, 0x05);
+ outSISIDXREG(SISSR, 0x16, 0x85);
+ }
+ sisfb_post_xgi_delay(ivideo, 0x43);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x1b, 0x01);
+ } else {
+ outSISIDXREG(SISSR, 0x1b, 0x03);
+ }
+ sisfb_post_xgi_delay(ivideo, 0x22);
+ outSISIDXREG(SISSR, 0x18, v1);
+ outSISIDXREG(SISSR, 0x19, 0x00);
+ if(ivideo->chip == XGI_40) {
+ outSISIDXREG(SISSR, 0x16, bios[0x540]);
+ outSISIDXREG(SISSR, 0x16, bios[0x541]);
+ } else {
+ outSISIDXREG(SISSR, 0x16, 0x05);
+ outSISIDXREG(SISSR, 0x16, 0x85);
+ }
+ outSISIDXREG(SISSR, 0x1b, 0x00);
+ }
+
+ regb = 0; /* ! */
+ v1 = 0x03;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x110 + regb];
+ }
+ outSISIDXREG(SISSR, 0x1b, v1);
+
+ /* RAM size */
+ v1 = 0x00; v2 = 0x00;
+ if(ivideo->haveXGIROM) {
+ v1 = bios[0x62];
+ v2 = bios[0x63];
}
+ regb = 0; /* ! */
+ regd = 1 << regb;
+ if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
+
+ outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
+ outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
+
+ } else {
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Disable read-cache */
+ andSISIDXREG(SISSR, 0x21, 0xdf);
+ sisfb_post_xgi_ramsize(ivideo);
+ /* Enable read-cache */
+ orSISIDXREG(SISSR, 0x21, 0x20);
- /* AGP (Missing: Checks for VIA and AMD hosts) */
- v1 = 0xA5; v2 = 0xFB;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
}
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
+#if 0
+ printk(KERN_DEBUG "-----------------\n");
+ for(i = 0; i < 0xff; i++) {
+ inSISIDXREG(SISCR, i, reg);
+ printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
+ }
+ for(i = 0; i < 0x40; i++) {
+ inSISIDXREG(SISSR, i, reg);
+ printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
+ }
+ printk(KERN_DEBUG "-----------------\n");
#endif
- return;
+
+ /* Sense CRT1 */
+ if(ivideo->chip == XGI_20) {
+ orSISIDXREG(SISCR, 0x32, 0x20);
+ } else {
+ inSISIDXREG(SISPART4, 0x00, reg);
+ if((reg == 1) || (reg == 2)) {
+ sisfb_sense_crt1(ivideo);
+ } else {
+ orSISIDXREG(SISCR, 0x32, 0x20);
+ }
+ }
+
+ /* Set default mode, don't clear screen */
+ ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+ SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+ SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+ ivideo->curFSTN = ivideo->curDSTN = 0;
+ SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+ outSISIDXREG(SISSR, 0x05, 0x86);
+
+ /* Display off */
+ orSISIDXREG(SISSR, 0x01, 0x20);
+
+ /* Save mode number in CR34 */
+ outSISIDXREG(SISCR, 0x34, 0x2e);
+
+ /* Let everyone know what the current mode is */
+ ivideo->modeprechange = 0x2e;
+
+ if(ivideo->chip == XGI_40) {
+ inSISIDXREG(SISCR, 0xca, reg);
+ inSISIDXREG(SISCR, 0xcc, v1);
+ if((reg & 0x10) && (!(v1 & 0x04))) {
+ printk(KERN_ERR
+ "sisfb: Please connect power to the card.\n");
+ return 0;
+ }
+ }
+
+ return 1;
}
#endif
-
-static int __devinit sisfb_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit
+sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
- struct sis_video_info *ivideo = NULL;
- struct fb_info *sis_fb_info = NULL;
+ struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
+ struct sis_video_info *ivideo = NULL;
+ struct fb_info *sis_fb_info = NULL;
u16 reg16;
u8 reg;
- int sisvga_enabled = 0, i;
+ int i, ret;
- if(sisfb_off) return -ENXIO;
+ if(sisfb_off)
+ return -ENXIO;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
- if(!sis_fb_info) return -ENOMEM;
+ if(!sis_fb_info)
+ return -ENOMEM;
#else
sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
- if(!sis_fb_info) return -ENOMEM;
+ if(!sis_fb_info)
+ return -ENOMEM;
memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
#endif
@@ -4787,27 +5890,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo = (struct sis_video_info *)sis_fb_info->par;
ivideo->memyselfandi = sis_fb_info;
+ ivideo->sisfb_id = SISFB_ID;
+
if(card_list == NULL) {
- ivideo->cardnumber = 0;
+ ivideo->cardnumber = 0;
} else {
- struct sis_video_info *countvideo = card_list;
- ivideo->cardnumber = 1;
- while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++;
+ struct sis_video_info *countvideo = card_list;
+ ivideo->cardnumber = 1;
+ while((countvideo = countvideo->next) != 0)
+ ivideo->cardnumber++;
}
strncpy(ivideo->myid, chipinfo->chip_name, 30);
ivideo->warncount = 0;
ivideo->chip_id = pdev->device;
+ ivideo->chip_vendor = pdev->vendor;
pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
- ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
+ ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
pci_read_config_word(pdev, PCI_COMMAND, &reg16);
- sisvga_enabled = reg16 & 0x01;
+ ivideo->sisvga_enabled = reg16 & 0x01;
ivideo->pcibus = pdev->bus->number;
ivideo->pcislot = PCI_SLOT(pdev->devfn);
ivideo->pcifunc = PCI_FUNC(pdev->devfn);
ivideo->subsysvendor = pdev->subsystem_vendor;
ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ ivideo->ioctl32registered = 0;
+#endif
#ifndef MODULE
if(sisfb_mode_idx == -1) {
@@ -4827,6 +5937,24 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->sisfb_thismonitor.datavalid = FALSE;
+ ivideo->current_base = 0;
+
+ ivideo->engineok = 0;
+
+ ivideo->sisfb_was_boot_device = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+ if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
+ if(ivideo->sisvga_enabled)
+ ivideo->sisfb_was_boot_device = 1;
+ else {
+ printk(KERN_DEBUG "sisfb: PCI device is disabled, "
+ "but marked as boot video device ???\n");
+ printk(KERN_DEBUG "sisfb: I will not accept this "
+ "as the primary VGA device\n");
+ }
+ }
+#endif
+
ivideo->sisfb_parm_mem = sisfb_parm_mem;
ivideo->sisfb_accel = sisfb_accel;
ivideo->sisfb_ypan = sisfb_ypan;
@@ -4846,7 +5974,6 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->sisfb_tvstd = sisfb_tvstd;
ivideo->tvxpos = sisfb_tvxposoffset;
ivideo->tvypos = sisfb_tvyposoffset;
- ivideo->sisfb_filter = sisfb_filter;
ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
ivideo->sisfb_inverse = sisfb_inverse;
@@ -4854,7 +5981,7 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->refresh_rate = 0;
if(ivideo->sisfb_parm_rate != -1) {
- ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+ ivideo->refresh_rate = ivideo->sisfb_parm_rate;
}
ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
@@ -4863,8 +5990,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
- ivideo->SiS_Pr.SiS_CHOverScan = -1;
- ivideo->SiS_Pr.SiS_ChSW = FALSE;
+ ivideo->SiS_Pr.SiS_CHOverScan = -1;
+ ivideo->SiS_Pr.SiS_ChSW = FALSE;
ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
ivideo->SiS_Pr.HaveEMI = FALSE;
ivideo->SiS_Pr.HaveEMILCD = FALSE;
@@ -4873,12 +6000,13 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
ivideo->SiS_Pr.PDC = -1;
ivideo->SiS_Pr.PDCA = -1;
+ ivideo->SiS_Pr.DDCPortMixup = FALSE;
#ifdef CONFIG_FB_SIS_315
if(ivideo->chip >= SIS_330) {
- ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
- if(ivideo->chip >= SIS_661) {
- ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
- }
+ ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+ if(ivideo->chip >= SIS_661) {
+ ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+ }
}
#endif
@@ -4891,9 +6019,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
switch(ivideo->nbridge->device) {
#ifdef CONFIG_FB_SIS_300
case PCI_DEVICE_ID_SI_730:
- ivideo->chip = SIS_730;
+ ivideo->chip = SIS_730;
strcpy(ivideo->myid, "SiS 730");
- break;
+ break;
#endif
#ifdef CONFIG_FB_SIS_315
case PCI_DEVICE_ID_SI_651:
@@ -4901,22 +6029,28 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
strcpy(ivideo->myid, "SiS 651");
break;
case PCI_DEVICE_ID_SI_740:
- ivideo->chip = SIS_740;
+ ivideo->chip = SIS_740;
strcpy(ivideo->myid, "SiS 740");
break;
case PCI_DEVICE_ID_SI_661:
- ivideo->chip = SIS_661;
+ ivideo->chip = SIS_661;
strcpy(ivideo->myid, "SiS 661");
break;
case PCI_DEVICE_ID_SI_741:
- ivideo->chip = SIS_741;
+ ivideo->chip = SIS_741;
strcpy(ivideo->myid, "SiS 741");
break;
case PCI_DEVICE_ID_SI_760:
- ivideo->chip = SIS_760;
+ ivideo->chip = SIS_760;
strcpy(ivideo->myid, "SiS 760");
break;
+ case PCI_DEVICE_ID_SI_761:
+ ivideo->chip = SIS_761;
+ strcpy(ivideo->myid, "SiS 761");
+ break;
#endif
+ default:
+ break;
}
}
@@ -4924,71 +6058,83 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
strcpy(sis_fb_info->modename, ivideo->myid);
#endif
- ivideo->sishw_ext.jChipType = ivideo->chip;
+ ivideo->SiS_Pr.ChipType = ivideo->chip;
+
+ ivideo->SiS_Pr.ivideo = (void *)ivideo;
#ifdef CONFIG_FB_SIS_315
- if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
- (ivideo->sishw_ext.jChipType == SIS_315)) {
- ivideo->sishw_ext.jChipType = SIS_315H;
+ if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
+ (ivideo->SiS_Pr.ChipType == SIS_315)) {
+ ivideo->SiS_Pr.ChipType = SIS_315H;
}
#endif
+ if(!ivideo->sisvga_enabled) {
+ if(pci_enable_device(pdev)) {
+ if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+ pci_set_drvdata(pdev, NULL);
+ kfree(sis_fb_info);
+ return -EIO;
+ }
+ }
+
ivideo->video_base = pci_resource_start(pdev, 0);
ivideo->mmio_base = pci_resource_start(pdev, 1);
ivideo->mmio_size = pci_resource_len(pdev, 1);
ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
- ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
+ ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
- if(!sisvga_enabled) {
- if(pci_enable_device(pdev)) {
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EIO;
- }
- }
-
- SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
+ SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
#ifdef CONFIG_FB_SIS_300
/* Find PCI systems for Chrontel/GPIO communication setup */
if(ivideo->chip == SIS_630) {
- i=0;
- do {
- if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
- mychswtable[i].subsysCard == ivideo->subsysdevice) {
- ivideo->SiS_Pr.SiS_ChSW = TRUE;
- printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
- mychswtable[i].vendorName, mychswtable[i].cardName);
- break;
- }
- i++;
- } while(mychswtable[i].subsysVendor != 0);
+ i = 0;
+ do {
+ if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+ mychswtable[i].subsysCard == ivideo->subsysdevice) {
+ ivideo->SiS_Pr.SiS_ChSW = TRUE;
+ printk(KERN_DEBUG "sisfb: Identified [%s %s] "
+ "requiring Chrontel/GPIO setup\n",
+ mychswtable[i].vendorName,
+ mychswtable[i].cardName);
+ ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
+ break;
+ }
+ i++;
+ } while(mychswtable[i].subsysVendor != 0);
+ }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+ if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
+ ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
}
#endif
- outSISIDXREG(SISSR, 0x05, 0x86);
+ outSISIDXREG(SISSR, 0x05, 0x86);
- if( (!sisvga_enabled)
+ if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
+ || (sisfb_resetcard)
#endif
- ) {
- for(i = 0x30; i <= 0x3f; i++) {
- outSISIDXREG(SISCR,i,0x00);
- }
+ ) {
+ for(i = 0x30; i <= 0x3f; i++) {
+ outSISIDXREG(SISCR, i, 0x00);
+ }
}
/* Find out about current video mode */
ivideo->modeprechange = 0x03;
- inSISIDXREG(SISCR,0x34,reg);
+ inSISIDXREG(SISCR, 0x34, reg);
if(reg & 0x7f) {
ivideo->modeprechange = reg & 0x7f;
- } else if(sisvga_enabled) {
+ } else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
- unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000);
+ unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
if(tt) {
- ivideo->modeprechange = readb(tt + 0x449);
- iounmap(tt);
+ ivideo->modeprechange = readb(tt + 0x49);
+ iounmap(tt);
}
#endif
}
@@ -4996,219 +6142,221 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#ifdef MODULE
if((reg & 0x80) && (reg != 0xff)) {
- if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
- printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EBUSY;
- }
+ if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni])
+ != 0xFF) {
+ printk(KERN_INFO "sisfb: Cannot initialize display mode, "
+ "X server is active\n");
+ ret = -EBUSY;
+ goto error_4;
+ }
}
-#endif
#endif
-
- ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
-#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->chip != SIS_300) {
- inSISIDXREG(SISSR, 0x1a, reg);
- if(!(reg & 0x10)) {
- ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
- }
- }
- }
#endif
+ /* Search and copy ROM image */
ivideo->bios_abase = NULL;
+ ivideo->SiS_Pr.VirtualRomBase = NULL;
+ ivideo->SiS_Pr.UseROM = FALSE;
+ ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
if(ivideo->sisfb_userom) {
- ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
- ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;
- if(ivideo->sishw_ext.pjVirtualRomBase) {
- printk(KERN_INFO "sisfb: Video ROM found and copied\n");
- ivideo->sishw_ext.UseROM = TRUE;
- } else {
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM not found\n");
- }
+ ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
+ ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
+ ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
+ printk(KERN_INFO "sisfb: Video ROM %sfound\n",
+ ivideo->SiS_Pr.UseROM ? "" : "not ");
+ if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
+ ivideo->SiS_Pr.UseROM = FALSE;
+ ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
+ if( (ivideo->revision_id == 2) &&
+ (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
+ ivideo->SiS_Pr.DDCPortMixup = TRUE;
+ }
+ }
} else {
- ivideo->sishw_ext.pjVirtualRomBase = NULL;
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
+ printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
}
- /* Find systems for special custom timing */
+ /* Find systems for special custom timing */
if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
- int j;
- unsigned char *biosver = NULL;
- unsigned char *biosdate = NULL;
- BOOLEAN footprint;
- u32 chksum = 0;
-
- if(ivideo->sishw_ext.UseROM) {
- biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
- biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
- for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
- }
-
- i=0;
- do {
- if( (mycustomttable[i].chipID == ivideo->chip) &&
- ((!strlen(mycustomttable[i].biosversion)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
- ((!strlen(mycustomttable[i].biosdate)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
- ((!mycustomttable[i].bioschksum) ||
- (ivideo->sishw_ext.UseROM &&
- (mycustomttable[i].bioschksum == chksum))) &&
- (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
- (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
- footprint = TRUE;
- for(j = 0; j < 5; j++) {
- if(mycustomttable[i].biosFootprintAddr[j]) {
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
- mycustomttable[i].biosFootprintData[j]) {
- footprint = FALSE;
- }
- } else footprint = FALSE;
- }
- }
- if(footprint) {
- ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
- printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
- mycustomttable[i].optionName);
- break;
- }
- }
- i++;
- } while(mycustomttable[i].chipID);
+ sisfb_detect_custom_timing(ivideo);
}
-#ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if( (!sisvga_enabled)
+ /* POST card in case this has not been done by the BIOS */
+ if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
+ || (sisfb_resetcard)
#endif
- ) {
+ ) {
+#ifdef CONFIG_FB_SIS_300
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
if(ivideo->chip == SIS_300) {
sisfb_post_sis300(pdev);
+ ivideo->sisfb_can_post = 1;
}
}
- }
#endif
#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if( (!sisvga_enabled)
-#if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
-#endif
- ) {
- if((ivideo->chip == SIS_315H) ||
+ if(ivideo->sisvga_engine == SIS_315_VGA) {
+ int result = 1;
+ /* if((ivideo->chip == SIS_315H) ||
(ivideo->chip == SIS_315) ||
(ivideo->chip == SIS_315PRO) ||
(ivideo->chip == SIS_330)) {
sisfb_post_sis315330(pdev);
+ } else */ if(ivideo->chip == XGI_20) {
+ result = sisfb_post_xgi(pdev);
+ ivideo->sisfb_can_post = 1;
+ } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+ result = sisfb_post_xgi(pdev);
+ ivideo->sisfb_can_post = 1;
+ } else {
+ printk(KERN_INFO "sisfb: Card is not "
+ "POSTed and sisfb can't do this either.\n");
+ }
+ if(!result) {
+ printk(KERN_ERR "sisfb: Failed to POST card\n");
+ ret = -ENODEV;
+ goto error_3;
}
}
- }
#endif
+ }
+ ivideo->sisfb_card_posted = 1;
+
+ /* Find out about RAM size */
if(sisfb_get_dram_size(ivideo)) {
- printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
+ ret = -ENODEV;
+ goto error_3;
}
+
+ /* Enable PCI addressing and MMIO */
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+ /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
+ orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+ /* Enable 2D accelerator engine */
+ orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
}
if(sisfb_pdc != 0xff) {
- if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
- else sisfb_pdc &= 0x1f;
- ivideo->SiS_Pr.PDC = sisfb_pdc;
+ if(ivideo->sisvga_engine == SIS_300_VGA)
+ sisfb_pdc &= 0x3c;
+ else
+ sisfb_pdc &= 0x1f;
+ ivideo->SiS_Pr.PDC = sisfb_pdc;
}
#ifdef CONFIG_FB_SIS_315
if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+ if(sisfb_pdca != 0xff)
+ ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
}
#endif
if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
+ printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
+ (int)(ivideo->video_size >> 20));
printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ ret = -ENODEV;
+ goto error_3;
}
if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ ret = -ENODEV;
+ goto error_2;
}
ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
- ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
+ ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
if(!ivideo->video_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
+ ret = -ENODEV;
+ goto error_1;
}
ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
if(!ivideo->mmio_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
- iounmap(ivideo->video_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+ printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
+ ret = -ENODEV;
+error_0: iounmap(ivideo->video_vbase);
+error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
+error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+error_3: vfree(ivideo->bios_abase);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+error_4:
+#endif
+ if(ivideo->lpcdev)
+ SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+ if(ivideo->nbridge)
+ SIS_PCI_PUT_DEVICE(ivideo->nbridge);
pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
+ if(!ivideo->sisvga_enabled)
+ pci_disable_device(pdev);
+ kfree(sis_fb_info);
+ return ret;
}
- printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024);
+ printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
+ ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
+
+ if(ivideo->video_offset) {
+ printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
+ ivideo->video_offset / 1024);
+ }
printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+ ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+
+ /* Determine the size of the command queue */
+ if(ivideo->sisvga_engine == SIS_300_VGA) {
+ ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
+ } else {
+ if(ivideo->chip == XGI_20) {
+ ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
+ } else {
+ ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
+ }
+ }
+
+ /* Engines are no longer initialized here; this is
+ * now done after the first mode-switch (if the
+ * submitted var has its acceleration flags set).
+ */
+
+ /* Calculate the base of the (unused) hw cursor */
+ ivideo->hwcursor_vbase = ivideo->video_vbase
+ + ivideo->video_size
+ - ivideo->cmdQueueSize
+ - ivideo->hwcursor_size;
+ ivideo->caps |= HW_CURSOR_CAP;
+
+ /* Initialize offscreen memory manager */
if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
}
/* Used for clearing the screen only, therefore respect our mem limit */
- ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
+ ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
+ ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
- ivideo->mtrr = 0;
+ ivideo->mtrr = -1;
ivideo->vbflags = 0;
ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
ivideo->tvdefmodeidx = DEFAULT_TVMODE;
ivideo->defmodeidx = DEFAULT_MODE;
- ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
+ ivideo->newrom = 0;
+ if(ivideo->chip < XGI_20) {
+ if(ivideo->bios_abase) {
+ ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
+ }
+ }
if((ivideo->sisfb_mode_idx < 0) ||
((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
@@ -5217,192 +6365,57 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
sisfb_get_VB_type(ivideo);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
sisfb_detect_VB_connect(ivideo);
}
ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
- if(ivideo->sisfb_crt2type != -1) {
- if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
- ivideo->currentvbflags |= CRT2_LCD;
- } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
- ivideo->currentvbflags |= ivideo->sisfb_crt2type;
- }
- } else {
- /* Chrontel 700x TV detection often unreliable, therefore use a
- * different default order on such machines
- */
- if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
- if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- } else {
- if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- }
- }
+ /* Decide on which CRT2 device to use */
+ if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+ if(ivideo->sisfb_crt2type != -1) {
+ if((ivideo->sisfb_crt2type == CRT2_LCD) &&
+ (ivideo->vbflags & CRT2_LCD)) {
+ ivideo->currentvbflags |= CRT2_LCD;
+ } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+ ivideo->currentvbflags |= ivideo->sisfb_crt2type;
+ }
+ } else {
+ /* Chrontel 700x TV detection often unreliable, therefore
+ * use a different default order on such machines
+ */
+ if((ivideo->sisvga_engine == SIS_300_VGA) &&
+ (ivideo->vbflags2 & VB2_CHRONTEL)) {
+ if(ivideo->vbflags & CRT2_LCD)
+ ivideo->currentvbflags |= CRT2_LCD;
+ else if(ivideo->vbflags & CRT2_TV)
+ ivideo->currentvbflags |= CRT2_TV;
+ else if(ivideo->vbflags & CRT2_VGA)
+ ivideo->currentvbflags |= CRT2_VGA;
+ } else {
+ if(ivideo->vbflags & CRT2_TV)
+ ivideo->currentvbflags |= CRT2_TV;
+ else if(ivideo->vbflags & CRT2_LCD)
+ ivideo->currentvbflags |= CRT2_LCD;
+ else if(ivideo->vbflags & CRT2_VGA)
+ ivideo->currentvbflags |= CRT2_VGA;
+ }
+ }
}
if(ivideo->vbflags & CRT2_LCD) {
- inSISIDXREG(SISCR, 0x36, reg);
- reg &= 0x0f;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- ivideo->CRT2LCDType = sis300paneltype[reg];
- } else if(ivideo->chip >= SIS_661) {
- ivideo->CRT2LCDType = sis661paneltype[reg];
- } else {
- ivideo->CRT2LCDType = sis310paneltype[reg];
- if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
- if((ivideo->CRT2LCDType != LCD_640x480_2) &&
- (ivideo->CRT2LCDType != LCD_640x480_3)) {
- ivideo->CRT2LCDType = LCD_320x480;
- }
- }
- }
- if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
- /* For broken BIOSes: Assume 1024x768, RGB18 */
- ivideo->CRT2LCDType = LCD_1024x768;
- setSISIDXREG(SISCR,0x36,0xf0,0x02);
- setSISIDXREG(SISCR,0x37,0xee,0x01);
- printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
- }
- for(i = 0; i < SIS_LCD_NUMBER; i++) {
- if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
- ivideo->lcdxres = sis_lcd_data[i].xres;
- ivideo->lcdyres = sis_lcd_data[i].yres;
- ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
- break;
- }
- }
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
- ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
- } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47;
- }
- printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
- ivideo->lcdxres, ivideo->lcdyres);
- }
-
-#ifdef CONFIG_FB_SIS_300
- /* Save the current PanelDelayCompensation if the LCD is currently used */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if(tmp & 0x20) {
- /* Currently on LCD? If yes, read current pdc */
- inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
- ivideo->detectedpdc &= 0x3c;
- if(ivideo->SiS_Pr.PDC == -1) {
- /* Let option override detection */
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
- ivideo->detectedpdc);
- }
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
- ivideo->SiS_Pr.PDC);
- }
- }
+ sisfb_detect_lcd_type(ivideo);
}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
-
- /* Try to find about LCDA */
- if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISPART1,0x13,tmp);
- if(tmp & 0x04) {
- ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
- ivideo->detectedlcda = 0x03;
- }
- }
-
- /* Save PDC */
- if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- /* Currently on LCD? If yes, read current pdc */
- u8 pdc;
- inSISIDXREG(SISPART1,0x2D,pdc);
- ivideo->detectedpdc = (pdc & 0x0f) << 1;
- ivideo->detectedpdca = (pdc & 0xf0) >> 3;
- inSISIDXREG(SISPART1,0x35,pdc);
- ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
- inSISIDXREG(SISPART1,0x20,pdc);
- ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
- if(ivideo->newrom) {
- /* New ROM invalidates other PDC resp. */
- if(ivideo->detectedlcda != 0xff) {
- ivideo->detectedpdc = 0xff;
- } else {
- ivideo->detectedpdca = 0xff;
- }
- }
- if(ivideo->SiS_Pr.PDC == -1) {
- if(ivideo->detectedpdc != 0xff) {
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- }
- if(ivideo->SiS_Pr.PDCA == -1) {
- if(ivideo->detectedpdca != 0xff) {
- ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
- }
- }
- if(ivideo->detectedpdc != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->detectedpdc);
- }
- if(ivideo->detectedpdca != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->detectedpdca);
- }
- }
-
- /* Save EMI */
- if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
- inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
- inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
- inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
- inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
- ivideo->SiS_Pr.HaveEMI = TRUE;
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- ivideo->SiS_Pr.HaveEMILCD = TRUE;
- }
- }
- }
-
- /* Let user override detected PDCs (all bridges) */
- if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->SiS_Pr.PDC);
- }
- if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
- printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->SiS_Pr.PDCA);
- }
- }
- }
-#endif
+ sisfb_save_pdc_emi(ivideo);
if(!ivideo->sisfb_crt1off) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
+ sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
} else {
- if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
- (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
- }
+ if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
+ (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+ sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
+ }
}
if(ivideo->sisfb_mode_idx >= 0) {
@@ -5434,7 +6447,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
if(ivideo->refresh_rate != 0) {
- sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+ sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
+ ivideo->sisfb_mode_idx);
}
if(ivideo->rate_idx == 0) {
@@ -5443,9 +6457,12 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
}
if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
- ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+ if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
+ ivideo->sisfb_mode_idx,
+ ivideo->rate_idx,
+ ivideo->refresh_rate)) {
+ printk(KERN_INFO "sisfb: WARNING: Refresh rate "
+ "exceeds monitor specs!\n");
}
}
@@ -5454,28 +6471,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
sisfb_set_vparms(ivideo);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /* ---------------- For 2.4: Now switch the mode ------------------ */
-
- printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+ /* ---------------- For 2.4: Now switch the mode ------------------ */
+
+ printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
+ ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
+ /* Determine whether or not acceleration is to be
+ * used. Need to know before pre/post_set_mode()
+ */
+ ivideo->accel = 0;
+ ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
+ if(ivideo->sisfb_accel) {
+ ivideo->accel = -1;
+ ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+ }
+
+ /* Now switch the mode */
sisfb_pre_setmode(ivideo);
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+ if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
ivideo->mode_no);
- iounmap(ivideo->video_vbase);
+ ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
+ goto error_0;
}
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -5488,18 +6511,17 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
/* Force reset of x virtual in crtc_to_var */
ivideo->default_var.xres_virtual = 0;
+ /* Copy mode timing to var */
sisfb_crtc_to_var(ivideo, &ivideo->default_var);
+ /* Find out about screen pitch */
sisfb_calc_pitch(ivideo, &ivideo->default_var);
sisfb_set_pitch(ivideo);
- ivideo->accel = 0;
- if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
- }
+ /* Init the accelerator (does nothing currently) */
sisfb_initaccel(ivideo);
-
+
+ /* Init some fbinfo entries */
sis_fb_info->node = -1;
sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
sis_fb_info->fbops = &sisfb_ops;
@@ -5515,41 +6537,42 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+ ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
ivideo->refresh_rate);
+ /* Set up the default var according to chosen default display mode */
ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
sisfb_bpp_to_var(ivideo, &ivideo->default_var);
-
+
ivideo->default_var.pixclock = (u32) (1000000000 /
- sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx));
-
- if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
- if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- ivideo->default_var.pixclock <<= 1;
- }
- }
+ sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
+
+ if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
+ ivideo->rate_idx, &ivideo->default_var)) {
+ if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ ivideo->default_var.pixclock <<= 1;
+ }
+ }
if(ivideo->sisfb_ypan) {
- /* Maximize regardless of sisfb_max at startup */
- ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var);
- if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
- ivideo->default_var.yres_virtual = ivideo->default_var.yres;
- }
+ /* Maximize regardless of sisfb_max at startup */
+ ivideo->default_var.yres_virtual =
+ sisfb_calc_maxyres(ivideo, &ivideo->default_var);
+ if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
+ ivideo->default_var.yres_virtual = ivideo->default_var.yres;
+ }
}
sisfb_calc_pitch(ivideo, &ivideo->default_var);
ivideo->accel = 0;
if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
+ ivideo->accel = -1;
#ifdef STUPID_ACCELF_TEXT_SHIT
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+ ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
#endif
}
sisfb_initaccel(ivideo);
@@ -5566,21 +6589,21 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
#endif
sis_fb_info->var = ivideo->default_var;
sis_fb_info->fix = ivideo->sisfb_fix;
- sis_fb_info->screen_base = ivideo->video_vbase;
+ sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
sis_fb_info->fbops = &sisfb_ops;
sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
-
+
fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
#endif /* 2.6 */
- printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
+ printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
#ifdef CONFIG_MTRR
ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
MTRR_TYPE_WRCOMB, 1);
- if(!ivideo->mtrr) {
+ if(ivideo->mtrr < 0) {
printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
}
#endif
@@ -5591,14 +6614,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
if(register_framebuffer(sis_fb_info) < 0) {
printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
- iounmap(ivideo->video_vbase);
+ ret = -EINVAL;
iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
+ goto error_0;
}
ivideo->registered = 1;
@@ -5607,21 +6625,47 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
ivideo->next = card_list;
card_list = ivideo;
+#ifdef SIS_OLD_CONFIG_COMPAT
+ {
+ int ret;
+ /* Our ioctls are all "32/64bit compatible" */
+ ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
+ ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
+ ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
+ ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+ ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
+ if(ret)
+ printk(KERN_ERR
+ "sisfb: Error registering ioctl32 translations\n");
+ else
+ ivideo->ioctl32registered = 1;
+ }
+#endif
+
printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
- ivideo->sisfb_accel ? "enabled" : "disabled",
- ivideo->sisfb_ypan ?
- (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled");
+ ivideo->sisfb_accel ? "enabled" : "disabled",
+ ivideo->sisfb_ypan ?
+ (ivideo->sisfb_max ? "enabled (auto-max)" :
+ "enabled (no auto-max)") :
+ "disabled");
- printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n",
+ printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- GET_FB_IDX(sis_fb_info->node),
+ GET_FB_IDX(sis_fb_info->node),
#else
- sis_fb_info->node,
+ sis_fb_info->node,
#endif
ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
- printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
+ printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
} /* if mode = "none" */
@@ -5634,26 +6678,62 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
static void __devexit sisfb_remove(struct pci_dev *pdev)
{
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- struct fb_info *sis_fb_info = ivideo->memyselfandi;
- int registered = ivideo->registered;
+ struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+ struct fb_info *sis_fb_info = ivideo->memyselfandi;
+ int registered = ivideo->registered;
+ int modechanged = ivideo->modechanged;
+
+#ifdef SIS_OLD_CONFIG_COMPAT
+ if(ivideo->ioctl32registered) {
+ int ret;
+ ret = unregister_ioctl32_conversion(FBIO_ALLOC);
+ ret |= unregister_ioctl32_conversion(FBIO_FREE);
+ ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+ ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+ ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
+ if(ret)
+ printk(KERN_ERR
+ "sisfb: Error unregistering ioctl32 translations\n");
+ }
+#endif
/* Unmap */
- iounmap(ivideo->video_vbase);
iounmap(ivideo->mmio_vbase);
- vfree(ivideo->bios_abase);
+ iounmap(ivideo->video_vbase);
/* Release mem regions */
release_mem_region(ivideo->video_base, ivideo->video_size);
release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+ vfree(ivideo->bios_abase);
+
+ if(ivideo->lpcdev)
+ SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+
+ if(ivideo->nbridge)
+ SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+
#ifdef CONFIG_MTRR
/* Release MTRR region */
- if(ivideo->mtrr) {
+ if(ivideo->mtrr >= 0)
mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
- }
#endif
+ pci_set_drvdata(pdev, NULL);
+
+ /* If device was disabled when starting, disable
+ * it when quitting.
+ */
+ if(!ivideo->sisvga_enabled)
+ pci_disable_device(pdev);
+
/* Unregister the framebuffer */
if(ivideo->registered) {
unregister_framebuffer(sis_fb_info);
@@ -5664,7 +6744,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
#endif
}
- pci_set_drvdata(pdev, NULL);
+ /* OK, our ivideo is gone for good from here. */
/* TODO: Restore the initial mode
* This sounds easy but is as good as impossible
@@ -5673,15 +6753,15 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
* from machine to machine. Depends on the type
* of integration between chipset and bridge.
*/
- if(registered) {
- printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
- }
+ if(registered && modechanged)
+ printk(KERN_INFO
+ "sisfb: Restoring of text mode not supported yet\n");
};
static struct pci_driver sisfb_driver = {
.name = "sisfb",
.id_table = sisfb_pci_table,
- .probe = sisfb_probe,
+ .probe = sisfb_probe,
.remove = __devexit_p(sisfb_remove)
};
@@ -5693,10 +6773,11 @@ SISINITSTATIC int __init sisfb_init(void)
if(fb_get_options("sisfb", &options))
return -ENODEV;
+
sisfb_setup(options);
#endif
#endif
- return(pci_register_driver(&sisfb_driver));
+ return pci_register_driver(&sisfb_driver);
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -5711,36 +6792,129 @@ module_init(sisfb_init);
#ifdef MODULE
-static char *mode = NULL;
-static int vesa = -1;
-static unsigned int rate = 0;
-static unsigned int crt1off = 1;
-static unsigned int mem = 0;
-static char *forcecrt2type = NULL;
-static int forcecrt1 = -1;
-static int pdc = -1;
-static int pdc1 = -1;
-static int noaccel = -1;
-static int noypan = -1;
-static int nomax = -1;
+static char *mode = NULL;
+static int vesa = -1;
+static unsigned int rate = 0;
+static unsigned int crt1off = 1;
+static unsigned int mem = 0;
+static char *forcecrt2type = NULL;
+static int forcecrt1 = -1;
+static int pdc = -1;
+static int pdc1 = -1;
+static int noaccel = -1;
+static int noypan = -1;
+static int nomax = -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int inverse = 0;
+#endif
+static int userom = -1;
+static int useoem = -1;
+static char *tvstandard = NULL;
+static int nocrt2rate = 0;
+static int scalelcd = -1;
+static char *specialtiming = NULL;
+static int lvdshl = -1;
+static int tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int resetcard = 0;
+static int videoram = 0;
+#endif
+
+static int __init sisfb_init_module(void)
+{
+ sisfb_setdefaultparms();
+
+ if(rate)
+ sisfb_parm_rate = rate;
+
+ if((scalelcd == 0) || (scalelcd == 1))
+ sisfb_scalelcd = scalelcd ^ 1;
+
+ /* Need to check crt2 type first for fstn/dstn */
+
+ if(forcecrt2type)
+ sisfb_search_crt2type(forcecrt2type);
+
+ if(tvstandard)
+ sisfb_search_tvstd(tvstandard);
+
+ if(mode)
+ sisfb_search_mode(mode, FALSE);
+ else if(vesa != -1)
+ sisfb_search_vesamode(vesa, FALSE);
+
+ sisfb_crt1off = (crt1off == 0) ? 1 : 0;
+
+ sisfb_forcecrt1 = forcecrt1;
+ if(forcecrt1 == 1)
+ sisfb_crt1off = 0;
+ else if(forcecrt1 == 0)
+ sisfb_crt1off = 1;
+
+ if(noaccel == 1)
+ sisfb_accel = 0;
+ else if(noaccel == 0)
+ sisfb_accel = 1;
+
+ if(noypan == 1)
+ sisfb_ypan = 0;
+ else if(noypan == 0)
+ sisfb_ypan = 1;
+
+ if(nomax == 1)
+ sisfb_max = 0;
+ else if(nomax == 0)
+ sisfb_max = 1;
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int inverse = 0;
-#endif
-static int userom = -1;
-static int useoem = -1;
-static char *tvstandard = NULL;
-static int nocrt2rate = 0;
-static int scalelcd = -1;
-static char *specialtiming = NULL;
-static int lvdshl = -1;
-static int tvxposoffset = 0, tvyposoffset = 0;
-static int filter = -1;
+ if(inverse) sisfb_inverse = 1;
+#endif
+
+ if(mem)
+ sisfb_parm_mem = mem;
+
+ if(userom != -1)
+ sisfb_userom = userom;
+
+ if(useoem != -1)
+ sisfb_useoem = useoem;
+
+ if(pdc != -1)
+ sisfb_pdc = (pdc & 0x7f);
+
+ if(pdc1 != -1)
+ sisfb_pdca = (pdc1 & 0x1f);
+
+ sisfb_nocrt2rate = nocrt2rate;
+
+ if(specialtiming)
+ sisfb_search_specialtiming(specialtiming);
+
+ if((lvdshl >= 0) && (lvdshl <= 3))
+ sisfb_lvdshl = lvdshl;
+
+ sisfb_tvxposoffset = tvxposoffset;
+ sisfb_tvyposoffset = tvyposoffset;
+
#if !defined(__i386__) && !defined(__x86_64__)
-static int resetcard = 0;
-static int videoram = 0;
+ sisfb_resetcard = (resetcard) ? 1 : 0;
+ if(videoram)
+ sisfb_videoram = videoram;
#endif
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
+ return sisfb_init();
+}
+
+static void __exit sisfb_remove_module(void)
+{
+ pci_unregister_driver(&sisfb_driver);
+ printk(KERN_DEBUG "sisfb: Module unloaded\n");
+}
+
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
@@ -5764,7 +6938,6 @@ MODULE_PARM(lvdshl, "i");
MODULE_PARM(tvstandard, "s");
MODULE_PARM(tvxposoffset, "i");
MODULE_PARM(tvyposoffset, "i");
-MODULE_PARM(filter, "i");
MODULE_PARM(nocrt2rate, "i");
MODULE_PARM(inverse, "i");
#if !defined(__i386__) && !defined(__x86_64__)
@@ -5793,7 +6966,6 @@ module_param(lvdshl, int, 0);
module_param(tvstandard, charp, 0);
module_param(tvxposoffset, int, 0);
module_param(tvyposoffset, int, 0);
-module_param(filter, int, 0);
module_param(nocrt2rate, int, 0);
#if !defined(__i386__) && !defined(__x86_64__)
module_param(resetcard, int, 0);
@@ -5801,25 +6973,35 @@ module_param(videoram, int, 0);
#endif
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mem,
"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
"for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
"on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
"the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
- "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+ "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
"The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
"for XFree86 4.x/X.org 6.7 and later.\n");
+#else
+MODULE_PARM_DESC(mem,
+ "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+ "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+ "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+ "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+ "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
+ "The value is to be specified without 'KB'.\n");
+#endif
MODULE_PARM_DESC(noaccel,
- "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+ "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
"(default: 0)\n");
MODULE_PARM_DESC(noypan,
- "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- "will be performed by redrawing the screen. (default: 0)\n");
+ "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+ "will be performed by redrawing the screen. (default: 0)\n");
MODULE_PARM_DESC(nomax,
- "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+ "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
"memory for the virtual screen in order to optimize scrolling performance. If\n"
"this is set to anything other than 0, sisfb will not do this and thereby \n"
"enable the user to positively specify a virtual Y size of the screen using\n"
@@ -5827,30 +7009,30 @@ MODULE_PARM_DESC(nomax,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mode,
- "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
- "1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+ "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+ "1024x768x16. Other formats supported include XxY-Depth and\n"
+ "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
"number, it will be interpreted as a VESA mode number. (default: none if\n"
"sisfb is a module; this leaves the console untouched and the driver will\n"
"only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
"is in the kernel)\n");
MODULE_PARM_DESC(vesa,
- "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
- "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+ "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+ "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
"and the driver will only do the video memory management for eg. DRM/DRI;\n"
"0x0103 if sisfb is in the kernel)\n");
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(mode,
- "\nSelects the desired default display mode in the format XxYxDepth,\n"
- "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+ "\nSelects the desired default display mode in the format XxYxDepth,\n"
+ "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
"XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
"number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
MODULE_PARM_DESC(vesa,
- "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
- "0x117 (default: 0x0103)\n");
+ "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+ "0x117 (default: 0x0103)\n");
#endif
MODULE_PARM_DESC(rate,
@@ -5880,16 +7062,16 @@ MODULE_PARM_DESC(scalelcd,
"themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
MODULE_PARM_DESC(pdc,
- "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+ "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
"should detect this correctly in most cases; however, sometimes this is not\n"
"possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
- "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
- "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
- "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+ "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
+ "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
+ "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
#ifdef CONFIG_FB_SIS_315
MODULE_PARM_DESC(pdc1,
- "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+ "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
"series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
"startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
"implemented yet.\n");
@@ -5913,17 +7095,13 @@ MODULE_PARM_DESC(tvyposoffset,
"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
"Default: 0\n");
-MODULE_PARM_DESC(filter,
- "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
- "(Possible values 0-7, default: [no filter])\n");
-
MODULE_PARM_DESC(nocrt2rate,
"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
"CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM_DESC(inverse,
- "\nSetting this to anything but 0 should invert the display colors, but this\n"
+ "\nSetting this to anything but 0 should invert the display colors, but this\n"
"does not seem to work. (default: 0)\n");
#endif
@@ -5931,98 +7109,23 @@ MODULE_PARM_DESC(inverse,
#ifdef CONFIG_FB_SIS_300
MODULE_PARM_DESC(resetcard,
"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
- "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
- "Default: 0\n");
+ "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
+ "currently). Default: 0\n");
MODULE_PARM_DESC(videoram,
"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
"some non-x86 architectures where the memory auto detection fails. Only\n"
- "relevant if resetcard is set, too. Default: [auto-detect]\n");
-#endif
+ "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
#endif
-
-static int __devinit sisfb_init_module(void)
-{
- sisfb_setdefaultparms();
-
- if(rate) sisfb_parm_rate = rate;
-
- if((scalelcd == 0) || (scalelcd == 1)) {
- sisfb_scalelcd = scalelcd ^ 1;
- }
-
- /* Need to check crt2 type first for fstn/dstn */
-
- if(forcecrt2type)
- sisfb_search_crt2type(forcecrt2type);
-
- if(tvstandard)
- sisfb_search_tvstd(tvstandard);
-
- if(mode)
- sisfb_search_mode(mode, FALSE);
- else if(vesa != -1)
- sisfb_search_vesamode(vesa, FALSE);
-
- sisfb_crt1off = (crt1off == 0) ? 1 : 0;
-
- sisfb_forcecrt1 = forcecrt1;
- if(forcecrt1 == 1) sisfb_crt1off = 0;
- else if(forcecrt1 == 0) sisfb_crt1off = 1;
-
- if(noaccel == 1) sisfb_accel = 0;
- else if(noaccel == 0) sisfb_accel = 1;
-
- if(noypan == 1) sisfb_ypan = 0;
- else if(noypan == 0) sisfb_ypan = 1;
-
- if(nomax == 1) sisfb_max = 0;
- else if(nomax == 0) sisfb_max = 1;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(inverse) sisfb_inverse = 1;
#endif
- if(mem) sisfb_parm_mem = mem;
-
- if(userom != -1) sisfb_userom = userom;
- if(useoem != -1) sisfb_useoem = useoem;
-
- if(pdc != -1) sisfb_pdc = (pdc & 0x7f);
- if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
-
- sisfb_nocrt2rate = nocrt2rate;
-
- if(specialtiming)
- sisfb_search_specialtiming(specialtiming);
-
- if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl;
-
- if(filter != -1) sisfb_filter = filter;
-
- sisfb_tvxposoffset = tvxposoffset;
- sisfb_tvyposoffset = tvyposoffset;
-
-#if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = (resetcard) ? 1 : 0;
- if(videoram) sisfb_videoram = videoram;
-#endif
-
- return(sisfb_init());
-}
-
-static void __exit sisfb_remove_module(void)
-{
- pci_unregister_driver(&sisfb_driver);
- printk(KERN_DEBUG "sisfb: Module unloaded\n");
-}
-
-module_init(sisfb_init_module);
-module_exit(sisfb_remove_module);
-
#endif /* /MODULE */
+/* _GPL only for new symbols. */
EXPORT_SYMBOL(sis_malloc);
EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL_GPL(sis_malloc_new);
+EXPORT_SYMBOL_GPL(sis_free_new);
+
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index a6678a7aff35..445bcbba03ae 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -1,9 +1,10 @@
/*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/305/540/630(S)/730(S),
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
* frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
*
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
*
* 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 +24,9 @@
#ifndef _SISFB_MAIN
#define _SISFB_MAIN
-#include <linux/spinlock.h>
-
#include "vstruct.h"
#include "sis.h"
-#define MODE_INDEX_NONE 0 /* index for mode=none */
-
/* Fbcon stuff */
static struct fb_var_screeninfo my_default_var = {
.xres = 0,
@@ -60,6 +57,8 @@ static struct fb_var_screeninfo my_default_var = {
.vmode = FB_VMODE_NONINTERLACED,
};
+#define MODE_INDEX_NONE 0 /* index for mode=none */
+
/* Boot-time parameters */
static int sisfb_off = 0;
static int sisfb_parm_mem = 0;
@@ -93,7 +92,6 @@ static int sisfb_tvplug = -1; /* Tv plug type (for overriding autodetection) */
static int sisfb_tvstd = -1;
static int sisfb_tvxposoffset = 0;
static int sisfb_tvyposoffset = 0;
-static int sisfb_filter = -1;
static int sisfb_nocrt2rate = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static int sisfb_inverse = 0;
@@ -106,12 +104,12 @@ static int sisfb_videoram = 0;
/* List of supported chips */
static struct sisfb_chip_info {
- int chip;
- int vgaengine;
+ int chip;
+ int vgaengine;
int mni;
- int hwcursor_size;
+ int hwcursor_size;
int CRT2_write_enable;
- const char *chip_name;
+ const char *chip_name;
} sisfb_chip_info[] __devinitdata = {
{ SIS_300, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
{ SIS_540, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
@@ -123,6 +121,8 @@ static struct sisfb_chip_info {
{ SIS_650, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
{ SIS_330, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
{ SIS_660, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+ { XGI_20, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI Z7" },
+ { XGI_40, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
};
static struct pci_device_id __devinitdata sisfb_pci_table[] = {
@@ -139,6 +139,8 @@ static struct pci_device_id __devinitdata sisfb_pci_table[] = {
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+ { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0,10},
+ { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0,11},
#endif
{ 0 }
};
@@ -147,13 +149,12 @@ MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
static struct sis_video_info *card_list = NULL;
-/* TODO: This is not handled card-wise because the DRM
- does not refer to a unique fb when calling sis_alloc
- or sis_free. Therefore, this is handled globally for
- now (hoping that nobody is crazy enough to run two
- SiS cards at the same time).
+/* The memory heap is now handled card-wise, by using
+ sis_malloc_new/sis_free_new. However, the DRM does
+ not do this yet. Until it does, we keep a "global"
+ heap which is actually the first card's one.
*/
-static SIS_HEAP sisfb_heap;
+static struct SIS_HEAP *sisfb_heap;
#define MD_SIS300 1
#define MD_SIS315 2
@@ -181,8 +182,10 @@ static const struct _sisbios_mode {
{"320x240x16", {0x56,0x56}, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS300|MD_SIS315},
{"320x240x24", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
{"320x240x32", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
- {"320x240x8", {0x5a,0x5a}, 0x0132, 0x0000, 320, 480, 8, 1, 40, 30, MD_SIS315}, /* FSTN */
-/*10*/ {"320x240x16", {0x5b,0x5b}, 0x0135, 0x0000, 320, 480, 16, 1, 40, 30, MD_SIS315}, /* FSTN */
+#define MODE_FSTN_8 9
+#define MODE_FSTN_16 10
+ {"320x240x8", {0x5a,0x5a}, 0x0132, 0x0000, 320, 240, 8, 1, 40, 15, MD_SIS315}, /* FSTN */
+/*10*/ {"320x240x16", {0x5b,0x5b}, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS315}, /* FSTN */
{"400x300x8", {0x51,0x51}, 0x0133, 0x0000, 400, 300, 8, 1, 50, 18, MD_SIS300|MD_SIS315},
{"400x300x16", {0x57,0x57}, 0x0136, 0x0000, 400, 300, 16, 1, 50, 18, MD_SIS300|MD_SIS315},
{"400x300x24", {0x54,0x54}, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315},
@@ -215,18 +218,20 @@ static const struct _sisbios_mode {
/*40*/ {"800x480x16", {0x7a,0x7a}, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
{"800x480x24", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
{"800x480x32", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE 43 /* index for 800x600x8 */
-#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */
-#define DEFAULT_TVMODE 43 /* index for 800x600x8 */
+#define DEFAULT_MODE 43 /* index for 800x600x8 */
+#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */
+#define DEFAULT_TVMODE 43 /* index for 800x600x8 */
{"800x600x8", {0x30,0x30}, 0x0103, 0x0103, 800, 600, 8, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x16", {0x47,0x47}, 0x0114, 0x0114, 800, 600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x24", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
{"800x600x32", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
{"848x480x8", {0x39,0x39}, 0x0000, 0x0000, 848, 480, 8, 2, 106, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_848 48
{"848x480x16", {0x3b,0x3b}, 0x0000, 0x0000, 848, 480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
{"848x480x24", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
/*50*/ {"848x480x32", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
{"856x480x8", {0x3f,0x3f}, 0x0000, 0x0000, 856, 480, 8, 2, 107, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_856 52
{"856x480x16", {0x42,0x42}, 0x0000, 0x0000, 856, 480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
{"856x480x24", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
{"856x480x32", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
@@ -270,42 +275,47 @@ static const struct _sisbios_mode {
{"1280x800x16", {0x15,0x15}, 0x0000, 0x0000, 1280, 800, 16, 1, 160, 50, MD_SIS315},
{"1280x800x24", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315},
{"1280x800x32", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315},
+ {"1280x854x8", {0x14,0x14}, 0x0000, 0x0000, 1280, 854, 8, 1, 160, 53, MD_SIS315},
+ {"1280x854x16", {0x15,0x15}, 0x0000, 0x0000, 1280, 854, 16, 1, 160, 53, MD_SIS315},
+ {"1280x854x24", {0x16,0x16}, 0x0000, 0x0000, 1280, 854, 32, 1, 160, 53, MD_SIS315},
+ {"1280x854x32", {0x16,0x16}, 0x0000, 0x0000, 1280, 854, 32, 1, 160, 53, MD_SIS315},
{"1280x960x8", {0x7c,0x7c}, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_SIS300|MD_SIS315},
- {"1280x960x16", {0x7d,0x7d}, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*100*/ {"1280x960x16", {0x7d,0x7d}, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x960x24", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x960x32", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
{"1280x1024x8", {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024, 8, 2, 160, 64, MD_SIS300|MD_SIS315},
-/*100*/ {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+ {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
{"1360x768x8", {0x48,0x48}, 0x0000, 0x0000, 1360, 768, 8, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x768x16", {0x4b,0x4b}, 0x0000, 0x0000, 1360, 768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x768x24", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
- {"1360x768x32", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+/*110*/ {"1360x768x32", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
{"1360x1024x8", {0x67,0x67}, 0x0000, 0x0000, 1360, 1024, 8, 1, 170, 64, MD_SIS300 },
+#define DEFAULT_MODE_1360 112
{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300 },
{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
-/*110*/ {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
+ {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
{"1400x1050x8", {0x26,0x26}, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_SIS315},
{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_SIS315},
{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
{"1600x1200x8", {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_SIS300|MD_SIS315},
- {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*120*/ {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
{"1680x1050x8", {0x17,0x17}, 0x0000, 0x0000, 1680, 1050, 8, 1, 210, 65, MD_SIS315},
-/*120*/ {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65, MD_SIS315},
+ {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65, MD_SIS315},
{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315},
{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315},
{"1920x1080x8", {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080, 8, 1, 240, 67, MD_SIS315},
{"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67, MD_SIS315},
{"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
- {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
+/*130*/ {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315},
{"1920x1440x8", {0x68,0x68}, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_SIS300|MD_SIS315},
{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-/*130*/ {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+ {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
{"2048x1536x8", {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_SIS315},
{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_SIS315},
{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315},
@@ -313,13 +323,13 @@ static const struct _sisbios_mode {
{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
};
-#define SIS_LCD_NUMBER 17
-static const struct _sis_lcd_data {
+#define SIS_LCD_NUMBER 18
+static struct _sis_lcd_data {
u32 lcdtype;
u16 xres;
u16 yres;
u8 default_mode_idx;
-} sis_lcd_data[] = {
+} sis_lcd_data[] __devinitdata = {
{ LCD_640x480, 640, 480, 23 },
{ LCD_800x600, 800, 600, 43 },
{ LCD_1024x600, 1024, 600, 67 },
@@ -329,34 +339,38 @@ static const struct _sis_lcd_data {
{ LCD_1280x720, 1280, 720, 83 },
{ LCD_1280x768, 1280, 768, 87 },
{ LCD_1280x800, 1280, 800, 91 },
- { LCD_1280x960, 1280, 960, 95 },
- { LCD_1280x1024, 1280, 1024, 99 },
- { LCD_1400x1050, 1400, 1050, 111 },
- { LCD_1680x1050, 1680, 1050, 119 },
- { LCD_1600x1200, 1600, 1200, 115 },
- { LCD_640x480_2, 640, 480, 23 },
- { LCD_640x480_3, 640, 480, 23 },
- { LCD_320x480, 320, 480, 9 },
+ { LCD_1280x854, 1280, 854, 95 },
+ { LCD_1280x960, 1280, 960, 99 },
+ { LCD_1280x1024, 1280, 1024, 103 },
+ { LCD_1400x1050, 1400, 1050, 115 },
+ { LCD_1680x1050, 1680, 1050, 123 },
+ { LCD_1600x1200, 1600, 1200, 119 },
+ { LCD_320x240_2, 320, 240, 9 },
+ { LCD_320x240_3, 320, 240, 9 },
+ { LCD_320x240, 320, 240, 9 },
};
/* CR36 evaluation */
-static const USHORT sis300paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
- LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN,
- LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN };
-
-static const USHORT sis310paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
- LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
- LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN, LCD_UNKNOWN };
-
-static const USHORT sis661paneltype[] =
- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
- LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
- LCD_1280x800, LCD_1680x1050, LCD_1280x720, LCD_UNKNOWN };
+static unsigned short sis300paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
+ LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN,
+ LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN
+};
+
+static unsigned short sis310paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+ LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
+ LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN, LCD_UNKNOWN
+};
+
+static unsigned short sis661paneltype[] __devinitdata = {
+ LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+ LCD_1280x854, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
+ LCD_1280x800, LCD_1680x1050, LCD_1280x720, LCD_UNKNOWN
+};
#define FL_550_DSTN 0x01
#define FL_550_FSTN 0x02
@@ -413,7 +427,6 @@ static const struct _sis_vrate {
} sisfb_vrate[] = {
{1, 320, 200, 70, TRUE},
{1, 320, 240, 60, TRUE},
- {1, 320, 480, 60, TRUE},
{1, 400, 300, 60, TRUE},
{1, 512, 384, 60, TRUE},
{1, 640, 400, 72, TRUE},
@@ -437,10 +450,11 @@ static const struct _sis_vrate {
{4, 1024, 768, 75, FALSE}, {5, 1024, 768, 85, TRUE}, {6, 1024, 768, 100, TRUE},
{7, 1024, 768, 120, TRUE},
{1, 1152, 768, 60, TRUE},
- {1, 1152, 864, 60, TRUE}, {1, 1152, 864, 75, TRUE}, {2, 1152, 864, 84, TRUE},
+ {1, 1152, 864, 60, TRUE}, {2, 1152, 864, 75, TRUE}, {3, 1152, 864, 84, TRUE},
{1, 1280, 720, 60, TRUE}, {2, 1280, 720, 75, TRUE}, {3, 1280, 720, 85, TRUE},
{1, 1280, 768, 60, TRUE},
{1, 1280, 800, 60, TRUE},
+ {1, 1280, 854, 60, TRUE},
{1, 1280, 960, 60, TRUE}, {2, 1280, 960, 85, TRUE},
{1, 1280, 1024, 43, TRUE}, {2, 1280, 1024, 60, TRUE}, {3, 1280, 1024, 75, TRUE},
{4, 1280, 1024, 85, TRUE},
@@ -459,12 +473,12 @@ static const struct _sis_vrate {
{0, 0, 0, 0, FALSE}
};
-static const struct _sisfbddcsmodes {
+static struct _sisfbddcsmodes {
u32 mask;
u16 h;
u16 v;
u32 d;
-} sisfb_ddcsmodes[] = {
+} sisfb_ddcsmodes[] __devinitdata = {
{ 0x10000, 67, 75, 108000},
{ 0x08000, 48, 72, 50000},
{ 0x04000, 46, 75, 49500},
@@ -480,49 +494,49 @@ static const struct _sisfbddcsmodes {
{ 0x00001, 38, 60, 40000}
};
-static const struct _sisfbddcfmodes {
+static struct _sisfbddcfmodes {
u16 x;
u16 y;
u16 v;
u16 h;
u32 d;
-} sisfb_ddcfmodes[] = {
- { 1280, 1024, 85, 92, 157500},
- { 1600, 1200, 60, 75, 162000},
- { 1600, 1200, 65, 82, 175500},
- { 1600, 1200, 70, 88, 189000},
- { 1600, 1200, 75, 94, 202500},
- { 1600, 1200, 85, 107,229500},
- { 1920, 1440, 60, 90, 234000},
- { 1920, 1440, 75, 113,297000}
+} sisfb_ddcfmodes[] __devinitdata = {
+ { 1280, 1024, 85, 92, 157500},
+ { 1600, 1200, 60, 75, 162000},
+ { 1600, 1200, 65, 82, 175500},
+ { 1600, 1200, 70, 88, 189000},
+ { 1600, 1200, 75, 94, 202500},
+ { 1600, 1200, 85, 107,229500},
+ { 1920, 1440, 60, 90, 234000},
+ { 1920, 1440, 75, 113,297000}
};
#ifdef CONFIG_FB_SIS_300
static struct _chswtable {
- u16 subsysVendor;
- u16 subsysCard;
- char *vendorName;
- char *cardName;
+ u16 subsysVendor;
+ u16 subsysCard;
+ char *vendorName;
+ char *cardName;
} mychswtable[] __devinitdata = {
- { 0x1631, 0x1002, "Mitachi", "0x1002" },
+ { 0x1631, 0x1002, "Mitachi", "0x1002" },
{ 0x1071, 0x7521, "Mitac" , "7521P" },
{ 0, 0, "" , "" }
};
#endif
static struct _customttable {
- u16 chipID;
- char *biosversion;
- char *biosdate;
- u32 bioschksum;
- u16 biosFootprintAddr[5];
- u8 biosFootprintData[5];
- u16 pcisubsysvendor;
- u16 pcisubsyscard;
- char *vendorName;
- char *cardName;
- u32 SpecialID;
- char *optionName;
+ u16 chipID;
+ char *biosversion;
+ char *biosdate;
+ u32 bioschksum;
+ u16 biosFootprintAddr[5];
+ u8 biosFootprintData[5];
+ u16 pcisubsysvendor;
+ u16 pcisubsyscard;
+ char *vendorName;
+ char *cardName;
+ u32 SpecialID;
+ char *optionName;
} mycustomttable[] __devinitdata = {
{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
0x3240A8,
@@ -643,6 +657,13 @@ static struct _customttable {
0, 0,
"Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
},
+ { 4322, "", "", /* never autodetected */
+ 0,
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ 0, 0,
+ "Generic", "LVDS/Parallel 856x480", CUT_PANEL856, "PANEL856x480"
+ },
{ 0, "", "",
0,
{ 0, 0, 0, 0 },
@@ -652,155 +673,6 @@ static struct _customttable {
}
};
-static const struct _sis_TV_filter {
- u8 filter[9][4];
-} sis_TV_filter[] = {
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xEB,0x04,0x25,0x18},
- {0xF1,0x05,0x1F,0x16},
- {0xF6,0x06,0x1A,0x14},
- {0xFA,0x06,0x16,0x14},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */
- {0xF1,0x04,0x1F,0x18},
- {0xEE,0x0D,0x22,0x06},
- {0xF7,0x06,0x19,0x14},
- {0xF4,0x0B,0x1C,0x0A},
- {0xFA,0x07,0x16,0x12},
- {0xF9,0x0A,0x17,0x0C},
- {0x00,0x07,0x10,0x12},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 - 320 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 - 640 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xEB,0x04,0x25,0x18},
- {0xF1,0x05,0x1F,0x16},
- {0xF6,0x06,0x1A,0x14},
- {0xFA,0x06,0x16,0x14},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 - 720 */
- {0xEB,0x04,0x25,0x18},
- {0xE7,0x0E,0x29,0x04},
- {0xEE,0x0C,0x22,0x08},
- {0xF6,0x0B,0x1A,0x0A},
- {0xF9,0x0A,0x17,0x0C},
- {0xFC,0x0A,0x14,0x0C},
- {0x00,0x08,0x10,0x10},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 - 800 */
- {0xEC,0x02,0x24,0x1C},
- {0xF2,0x04,0x1E,0x18},
- {0xEB,0x15,0x25,0xF6},
- {0xF4,0x10,0x1C,0x00},
- {0xF8,0x0F,0x18,0x02},
- {0x00,0x04,0x10,0x18},
- {0x01,0x06,0x0F,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xF1,0xF7,0x01,0x32},
- {0xF5,0xFB,0x1B,0x2A},
- {0xF9,0xFF,0x17,0x22},
- {0xFB,0x01,0x15,0x1E},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */
- {0xF5,0xFB,0x1B,0x2A},
- {0xEE,0xFE,0x22,0x24},
- {0xF3,0x00,0x1D,0x20},
- {0xF9,0x03,0x17,0x1A},
- {0xFB,0x02,0x14,0x1E},
- {0xFB,0x04,0x15,0x18},
- {0x00,0x06,0x10,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 - 320 */
- {0x00,0xE0,0x10,0x60},
- {0x00,0xEE,0x10,0x44},
- {0x00,0xF4,0x10,0x38},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0x00,0x00,0x10,0x20},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 - 640 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xF1,0xF7,0x1F,0x32},
- {0xF5,0xFB,0x1B,0x2A},
- {0xF9,0xFF,0x17,0x22},
- {0xFB,0x01,0x15,0x1E},
- {0x00,0x04,0x10,0x18},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 - 720 */
- {0xF5,0xEE,0x1B,0x2A},
- {0xEE,0xFE,0x22,0x24},
- {0xF3,0x00,0x1D,0x20},
- {0xF9,0x03,0x17,0x1A},
- {0xFB,0x02,0x14,0x1E},
- {0xFB,0x04,0x15,0x18},
- {0x00,0x06,0x10,0x14},
- {0xFF,0xFF,0xFF,0xFF} }},
- { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 - 800 */
- {0xF5,0xEE,0x1B,0x44},
- {0xF8,0xF4,0x18,0x38},
- {0xFC,0xFB,0x14,0x2A},
- {0xEB,0x05,0x25,0x16},
- {0xF1,0x05,0x1F,0x16},
- {0xFA,0x07,0x16,0x12},
- {0x00,0x07,0x10,0x12},
- {0xFF,0xFF,0xFF,0xFF} }}
-};
-
/* ---------------------- Prototypes ------------------------- */
/* Interface used by the world */
@@ -811,145 +683,159 @@ SISINITSTATIC int sisfb_setup(char *options);
/* Interface to the low level console driver */
SISINITSTATIC int sisfb_init(void);
-
/* fbdev routines */
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix,
- int con,
- struct fb_info *info);
-static int sisfb_get_var(struct fb_var_screeninfo *var,
- int con,
- struct fb_info *info);
-static int sisfb_set_var(struct fb_var_screeninfo *var,
- int con,
- struct fb_info *info);
-static void sisfb_crtc_to_var(struct sis_video_info *ivideo,
- struct fb_var_screeninfo *var);
-static int sisfb_get_cmap(struct fb_cmap *cmap,
- int kspc,
- int con,
- struct fb_info *info);
-static int sisfb_set_cmap(struct fb_cmap *cmap,
- int kspc,
- int con,
- struct fb_info *info);
-static int sisfb_update_var(int con,
- struct fb_info *info);
-static int sisfb_switch(int con,
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix,
+ int con,
+ struct fb_info *info);
+static int sisfb_get_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static int sisfb_set_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static void sisfb_crtc_to_var(struct sis_video_info *ivideo,
+ struct fb_var_screeninfo *var);
+static int sisfb_get_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int sisfb_set_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int sisfb_update_var(int con,
+ struct fb_info *info);
+static int sisfb_switch(int con,
struct fb_info *info);
-static void sisfb_blank(int blank,
- struct fb_info *info);
-static void sisfb_set_disp(int con,
- struct fb_var_screeninfo *var,
- struct fb_info *info);
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *fb_info);
-static void sisfb_do_install_cmap(int con,
- struct fb_info *info);
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info);
-#endif
+static void sisfb_blank(int blank,
+ struct fb_info *info);
+static void sisfb_set_disp(int con,
+ struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *fb_info);
+static void sisfb_do_install_cmap(int con,
+ struct fb_info *info);
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
-static int sisfb_set_par(struct fb_info *info);
-static int sisfb_blank(int blank,
- struct fb_info *info);
-extern void fbcon_sis_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect);
-extern void fbcon_sis_copyarea(struct fb_info *info,
- const struct fb_copyarea *area);
-extern int fbcon_sis_sync(struct fb_info *info);
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info);
+static int sisfb_set_par(struct fb_info *info);
+static int sisfb_blank(int blank,
+ struct fb_info *info);
+extern void fbcon_sis_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect);
+extern void fbcon_sis_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+extern int fbcon_sis_sync(struct fb_info *info);
#endif
-
+
/* Internal 2D accelerator functions */
-extern int sisfb_initaccel(struct sis_video_info *ivideo);
-extern void sisfb_syncaccel(struct sis_video_info *ivideo);
+extern int sisfb_initaccel(struct sis_video_info *ivideo);
+extern void sisfb_syncaccel(struct sis_video_info *ivideo);
/* Internal general routines */
-static void sisfb_search_mode(char *name, BOOLEAN quiet);
-static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
-static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
- int index);
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info);
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info);
-static void sisfb_pre_setmode(struct sis_video_info *ivideo);
-static void sisfb_post_setmode(struct sis_video_info *ivideo);
-static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo);
-static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
-static void sisfb_get_VB_type(struct sis_video_info *ivideo);
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+static void sisfb_search_mode(char *name, BOOLEAN quiet);
+static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+ int index);
+static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static void sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void sisfb_post_setmode(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+#ifdef CONFIG_FB_SIS_300
+unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
+unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+#ifdef CONFIG_FB_SIS_315
+void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
+unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
/* SiS-specific exported functions */
-void sis_malloc(struct sis_memreq *req);
-void sis_free(u32 base);
+void sis_malloc(struct sis_memreq *req);
+void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+void sis_free(u32 base);
+void sis_free_new(struct pci_dev *pdev, u32 base);
/* Internal heap routines */
-static int sisfb_heap_init(struct sis_video_info *ivideo);
-static SIS_OH *sisfb_poh_new_node(void);
-static SIS_OH *sisfb_poh_allocate(u32 size);
-static void sisfb_delete_node(SIS_OH *poh);
-static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH *sisfb_poh_free(u32 base);
-static void sisfb_free_node(SIS_OH *poh);
-
-/* Sensing routines */
-static void SiS_Sense30x(struct sis_video_info *ivideo);
-static void SiS_SenseCh(struct sis_video_info *ivideo);
+static int sisfb_heap_init(struct sis_video_info *ivideo);
+static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
+static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
+static void sisfb_delete_node(struct SIS_OH *poh);
+static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
+static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
+static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
/* Routines from init.c/init301.c */
-extern USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth,
- BOOLEAN FSTN, USHORT CustomT, int LCDwith, int LCDheight);
-extern USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-extern USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-extern void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo, USHORT ModeNo);
-extern void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-extern void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-
-extern BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-
-extern BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+extern unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, BOOLEAN FSTN, unsigned short CustomT,
+ int LCDwith, int LCDheight, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+extern BOOLEAN SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+extern void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+
+extern BOOLEAN SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+extern BOOLEAN sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ int *htotal, int *vtotal, unsigned char rateindex);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-extern int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr,
- PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, unsigned char rateindex);
-extern int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
- unsigned char modeno, unsigned char rateindex,
- struct fb_var_screeninfo *var);
+extern int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+ unsigned char modeno, unsigned char rateindex);
+extern int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
#endif
/* Chrontel TV, DDC and DPMS functions */
-extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
-extern void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-extern void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-extern USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
- USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
-extern USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-extern void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
-extern void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
+extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+ unsigned char myor, unsigned char myand);
+extern void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+extern void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
+extern unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+ unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+ unsigned int VBFlags2);
+extern unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+#ifdef CONFIG_FB_SIS_315
+extern void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+extern void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
+#endif
+extern void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+extern void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
#endif
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index 507bba1a71b5..831b9f42264b 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -3,7 +3,7 @@
/*
* General type definitions for universal mode switching modules
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,11 +50,10 @@
*
*/
-#ifndef _VGATYPES_
-#define _VGATYPES_
+#ifndef _VGATYPES_H_
+#define _VGATYPES_H_
-#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */
-#include <linux/ioctl.h>
+#ifdef SIS_LINUX_KERNEL
#include <linux/version.h>
#endif
@@ -66,41 +65,13 @@
#define TRUE 1
#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CHAR
-typedef char CHAR;
-#endif
-
-#ifndef SHORT
-typedef short SHORT;
-#endif
-
-#ifndef LONG
-typedef long LONG;
-#endif
-
-#ifndef UCHAR
-typedef unsigned char UCHAR;
-#endif
-
-#ifndef USHORT
-typedef unsigned short USHORT;
-#endif
-
-#ifndef ULONG
-typedef unsigned long ULONG;
-#endif
-
#ifndef BOOLEAN
-typedef unsigned char BOOLEAN;
+typedef unsigned int BOOLEAN;
#endif
#define SISIOMEMTYPE
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
typedef unsigned long SISIOADDRESS;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
#include <linux/types.h> /* Need __iomem */
@@ -109,7 +80,7 @@ typedef unsigned long SISIOADDRESS;
#endif
#endif
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
typedef unsigned long IOADDRESS;
typedef unsigned long SISIOADDRESS;
@@ -118,7 +89,7 @@ typedef IOADDRESS SISIOADDRESS;
#endif
#endif
-enum _SIS_CHIP_TYPE {
+typedef enum _SIS_CHIP_TYPE {
SIS_VGALegacy = 0,
SIS_530,
SIS_OLD,
@@ -128,115 +99,27 @@ enum _SIS_CHIP_TYPE {
SIS_540,
SIS_315H, /* SiS 310 */
SIS_315,
- SIS_315PRO,
+ SIS_315PRO, /* SiS 325 */
SIS_550,
SIS_650,
SIS_740,
SIS_330,
SIS_661,
SIS_741,
- SIS_660,
+ SIS_670,
+ SIS_660 = 35,
SIS_760,
SIS_761,
- SIS_340,
+ SIS_762,
+ SIS_770,
+ SIS_340 = 55,
+ SIS_341,
+ SIS_342,
+ XGI_20 = 75,
+ XGI_40,
MAX_SIS_CHIP
-};
-
-#ifndef SIS_HW_INFO
-typedef struct _SIS_HW_INFO SIS_HW_INFO, *PSIS_HW_INFO;
-
-struct _SIS_HW_INFO
-{
-#ifdef LINUX_XF86
- PCITAG PciTag; /* PCI Tag */
-#endif
-
- UCHAR *pjVirtualRomBase; /* ROM image */
-
- BOOLEAN UseROM; /* Use the ROM image if provided */
-
-#ifdef LINUX_KERNEL
- UCHAR SISIOMEMTYPE *pjVideoMemoryAddress;
- /* base virtual memory address */
- /* of Linear VGA memory */
-
- ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */
-#endif
-
- SISIOADDRESS ulIOAddress; /* base I/O address of VGA ports (0x3B0; relocated) */
-
- UCHAR jChipType; /* Used to Identify SiS Graphics Chip */
- /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
+} SIS_CHIP_TYPE;
- UCHAR jChipRevision; /* Used to Identify SiS Graphics Chip Revision */
-
- BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-};
-#endif
-
-/* Addtional IOCTLs for communication sisfb <> X driver */
-/* If changing this, sisfb.h must also be changed (for sisfb) */
-
-#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */
-
-/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_SIZE 0x8004f300
-#define SISFB_GET_INFO 0x8000f301 /* Must be patched with result from ..._SIZE at D[29:16] */
-/* deprecated ioctl number (for older versions of sisfb) */
-#define SISFB_GET_INFO_OLD 0x80046ef8
-
-/* ioctls for tv parameters (position) */
-#define SISFB_SET_TVPOSOFFSET 0x4004f304
-
-/* lock sisfb from register access */
-#define SISFB_SET_LOCK 0x4004f306
-
-/* Structure argument for SISFB_GET_INFO ioctl */
-typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
-
-struct _SISFB_INFO {
- CARD32 sisfb_id; /* for identifying sisfb */
-#ifndef SISFB_ID
-#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */
-#endif
- CARD32 chip_id; /* PCI ID of detected chip */
- CARD32 memory; /* video memory in KB which sisfb manages */
- CARD32 heapstart; /* heap start (= sisfb "mem" argument) in KB */
- CARD8 fbvidmode; /* current sisfb mode */
-
- CARD8 sisfb_version;
- CARD8 sisfb_revision;
- CARD8 sisfb_patchlevel;
-
- CARD8 sisfb_caps; /* sisfb's capabilities */
-
- CARD32 sisfb_tqlen; /* turbo queue length (in KB) */
-
- CARD32 sisfb_pcibus; /* The card's PCI ID */
- CARD32 sisfb_pcislot;
- CARD32 sisfb_pcifunc;
-
- CARD8 sisfb_lcdpdc;
-
- CARD8 sisfb_lcda;
-
- CARD32 sisfb_vbflags;
- CARD32 sisfb_currentvbflags;
-
- CARD32 sisfb_scalelcd;
- CARD32 sisfb_specialtiming;
-
- CARD8 sisfb_haveemi;
- CARD8 sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
- CARD8 sisfb_haveemilcd;
-
- CARD8 sisfb_lcdpdca;
-
- CARD16 sisfb_tvxpos, sisfb_tvypos; /* Warning: Values + 32 ! */
-
- CARD8 reserved[208]; /* for future use */
-};
-#endif
#endif
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index d4d55c98bce6..9ae32923c142 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -3,7 +3,7 @@
/*
* General structure definitions for universal mode switching modules
*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
@@ -50,627 +50,514 @@
*
*/
-#ifndef _VSTRUCT_
-#define _VSTRUCT_
-
-typedef struct _SiS_PanelDelayTblStruct
-{
- UCHAR timer[2];
-} SiS_PanelDelayTblStruct;
-
-typedef struct _SiS_LCDDataStruct
-{
- USHORT RVBHCMAX;
- USHORT RVBHCFACT;
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT LCDHT;
- USHORT LCDVT;
-} SiS_LCDDataStruct;
-
-typedef struct _SiS_TVDataStruct
-{
- USHORT RVBHCMAX;
- USHORT RVBHCFACT;
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT TVHDE;
- USHORT TVVDE;
- USHORT RVBHRS;
- UCHAR FlickerMode;
- USHORT HALFRVBHRS;
- UCHAR RY1COE;
- UCHAR RY2COE;
- UCHAR RY3COE;
- UCHAR RY4COE;
-} SiS_TVDataStruct;
-
-typedef struct _SiS_LVDSDataStruct
-{
- USHORT VGAHT;
- USHORT VGAVT;
- USHORT LCDHT;
- USHORT LCDVT;
-} SiS_LVDSDataStruct;
-
-typedef struct _SiS_LVDSDesStruct
-{
- USHORT LCDHDES;
- USHORT LCDVDES;
-} SiS_LVDSDesStruct;
-
-typedef struct _SiS_LVDSCRT1DataStruct
-{
- UCHAR CR[15];
-} SiS_LVDSCRT1DataStruct;
-
-typedef struct _SiS_LCDACRT1DataStruct
-{
- UCHAR CR[17];
-} SiS_LCDACRT1DataStruct;
-
-typedef struct _SiS_CHTVRegDataStruct
-{
- UCHAR Reg[16];
-} SiS_CHTVRegDataStruct;
-
-typedef struct _SiS_StStruct
-{
- UCHAR St_ModeID;
- USHORT St_ModeFlag;
- UCHAR St_StTableIndex;
- UCHAR St_CRT2CRTC;
- UCHAR St_ResInfo;
- UCHAR VB_StTVFlickerIndex;
- UCHAR VB_StTVEdgeIndex;
- UCHAR VB_StTVYFilterIndex;
- UCHAR St_PDC;
-} SiS_StStruct;
-
-typedef struct _SiS_VBModeStruct
-{
- UCHAR ModeID;
- UCHAR VB_TVDelayIndex;
- UCHAR VB_TVFlickerIndex;
- UCHAR VB_TVPhaseIndex;
- UCHAR VB_TVYFilterIndex;
- UCHAR VB_LCDDelayIndex;
- UCHAR _VB_LCDHIndex;
- UCHAR _VB_LCDVIndex;
-} SiS_VBModeStruct;
-
-typedef struct _SiS_StandTableStruct
-{
- UCHAR CRT_COLS;
- UCHAR ROWS;
- UCHAR CHAR_HEIGHT;
- USHORT CRT_LEN;
- UCHAR SR[4];
- UCHAR MISC;
- UCHAR CRTC[0x19];
- UCHAR ATTR[0x14];
- UCHAR GRC[9];
-} SiS_StandTableStruct;
-
-typedef struct _SiS_ExtStruct
-{
- UCHAR Ext_ModeID;
- USHORT Ext_ModeFlag;
- USHORT Ext_VESAID;
- UCHAR Ext_RESINFO;
- UCHAR VB_ExtTVFlickerIndex;
- UCHAR VB_ExtTVEdgeIndex;
- UCHAR VB_ExtTVYFilterIndex;
- UCHAR VB_ExtTVYFilterIndexROM661;
- UCHAR REFindex;
- CHAR ROMMODEIDX661;
-} SiS_ExtStruct;
-
-typedef struct _SiS_Ext2Struct
-{
- USHORT Ext_InfoFlag;
- UCHAR Ext_CRT1CRTC;
- UCHAR Ext_CRTVCLK;
- UCHAR Ext_CRT2CRTC;
- UCHAR Ext_CRT2CRTC_NS;
- UCHAR ModeID;
- USHORT XRes;
- USHORT YRes;
- UCHAR Ext_PDC;
-} SiS_Ext2Struct;
-
-typedef struct _SiS_Part2PortTblStruct
-{
- UCHAR CR[12];
-} SiS_Part2PortTblStruct;
-
-typedef struct _SiS_CRT1TableStruct
-{
- UCHAR CR[17];
-} SiS_CRT1TableStruct;
-
-typedef struct _SiS_MCLKDataStruct
-{
- UCHAR SR28,SR29,SR2A;
- USHORT CLOCK;
-} SiS_MCLKDataStruct;
-
-typedef struct _SiS_VCLKDataStruct
-{
- UCHAR SR2B,SR2C;
- USHORT CLOCK;
-} SiS_VCLKDataStruct;
-
-typedef struct _SiS_VBVCLKDataStruct
-{
- UCHAR Part4_A,Part4_B;
- USHORT CLOCK;
-} SiS_VBVCLKDataStruct;
-
-typedef struct _SiS_StResInfoStruct
-{
- USHORT HTotal;
- USHORT VTotal;
-} SiS_StResInfoStruct;
-
-typedef struct _SiS_ModeResInfoStruct
-{
- USHORT HTotal;
- USHORT VTotal;
- UCHAR XChar;
- UCHAR YChar;
-} SiS_ModeResInfoStruct;
-
-
-
-typedef UCHAR DRAM4Type[4];
+#ifndef _VSTRUCT_H_
+#define _VSTRUCT_H_
+
+struct SiS_PanelDelayTbl {
+ unsigned char timer[2];
+};
+
+struct SiS_LCDData {
+ unsigned short RVBHCMAX;
+ unsigned short RVBHCFACT;
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short LCDHT;
+ unsigned short LCDVT;
+};
+
+struct SiS_TVData {
+ unsigned short RVBHCMAX;
+ unsigned short RVBHCFACT;
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short TVHDE;
+ unsigned short TVVDE;
+ unsigned short RVBHRS;
+ unsigned char FlickerMode;
+ unsigned short HALFRVBHRS;
+ unsigned short RVBHRS2;
+ unsigned char RY1COE;
+ unsigned char RY2COE;
+ unsigned char RY3COE;
+ unsigned char RY4COE;
+};
+
+struct SiS_LVDSData {
+ unsigned short VGAHT;
+ unsigned short VGAVT;
+ unsigned short LCDHT;
+ unsigned short LCDVT;
+};
+
+struct SiS_LVDSDes {
+ unsigned short LCDHDES;
+ unsigned short LCDVDES;
+};
+
+struct SiS_LVDSCRT1Data {
+ unsigned char CR[15];
+};
+
+struct SiS_CHTVRegData {
+ unsigned char Reg[16];
+};
+
+struct SiS_St {
+ unsigned char St_ModeID;
+ unsigned short St_ModeFlag;
+ unsigned char St_StTableIndex;
+ unsigned char St_CRT2CRTC;
+ unsigned char St_ResInfo;
+ unsigned char VB_StTVFlickerIndex;
+ unsigned char VB_StTVEdgeIndex;
+ unsigned char VB_StTVYFilterIndex;
+ unsigned char St_PDC;
+};
+
+struct SiS_VBMode {
+ unsigned char ModeID;
+ unsigned char VB_TVDelayIndex;
+ unsigned char VB_TVFlickerIndex;
+ unsigned char VB_TVPhaseIndex;
+ unsigned char VB_TVYFilterIndex;
+ unsigned char VB_LCDDelayIndex;
+ unsigned char _VB_LCDHIndex;
+ unsigned char _VB_LCDVIndex;
+};
+
+struct SiS_StandTable_S {
+ unsigned char CRT_COLS;
+ unsigned char ROWS;
+ unsigned char CHAR_HEIGHT;
+ unsigned short CRT_LEN;
+ unsigned char SR[4];
+ unsigned char MISC;
+ unsigned char CRTC[0x19];
+ unsigned char ATTR[0x14];
+ unsigned char GRC[9];
+};
+
+struct SiS_Ext {
+ unsigned char Ext_ModeID;
+ unsigned short Ext_ModeFlag;
+ unsigned short Ext_VESAID;
+ unsigned char Ext_RESINFO;
+ unsigned char VB_ExtTVFlickerIndex;
+ unsigned char VB_ExtTVEdgeIndex;
+ unsigned char VB_ExtTVYFilterIndex;
+ unsigned char VB_ExtTVYFilterIndexROM661;
+ unsigned char REFindex;
+ char ROMMODEIDX661;
+};
+
+struct SiS_Ext2 {
+ unsigned short Ext_InfoFlag;
+ unsigned char Ext_CRT1CRTC;
+ unsigned char Ext_CRTVCLK;
+ unsigned char Ext_CRT2CRTC;
+ unsigned char Ext_CRT2CRTC_NS;
+ unsigned char ModeID;
+ unsigned short XRes;
+ unsigned short YRes;
+ unsigned char Ext_PDC;
+ unsigned char Ext_FakeCRT2CRTC;
+ unsigned char Ext_FakeCRT2Clk;
+ unsigned char Ext_CRT1CRTC_NORM;
+ unsigned char Ext_CRTVCLK_NORM;
+ unsigned char Ext_CRT1CRTC_WIDE;
+ unsigned char Ext_CRTVCLK_WIDE;
+};
+
+struct SiS_Part2PortTbl {
+ unsigned char CR[12];
+};
+
+struct SiS_CRT1Table {
+ unsigned char CR[17];
+};
+
+struct SiS_MCLKData {
+ unsigned char SR28,SR29,SR2A;
+ unsigned short CLOCK;
+};
+
+struct SiS_VCLKData {
+ unsigned char SR2B,SR2C;
+ unsigned short CLOCK;
+};
+
+struct SiS_VBVCLKData {
+ unsigned char Part4_A,Part4_B;
+ unsigned short CLOCK;
+};
+
+struct SiS_StResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+};
+
+struct SiS_ModeResInfo_S {
+ unsigned short HTotal;
+ unsigned short VTotal;
+ unsigned char XChar;
+ unsigned char YChar;
+};
/* Defines for SiS_CustomT */
/* Never change these for sisfb compatibility */
-#define CUT_NONE 0
-#define CUT_FORCENONE 1
-#define CUT_BARCO1366 2
-#define CUT_BARCO1024 3
-#define CUT_COMPAQ1280 4
-#define CUT_COMPAQ12802 5
-#define CUT_PANEL848 6
-#define CUT_CLEVO1024 7
-#define CUT_CLEVO10242 8
-#define CUT_CLEVO1400 9
-#define CUT_CLEVO14002 10
-#define CUT_UNIWILL1024 11
-#define CUT_ASUSL3000D 12
-#define CUT_UNIWILL10242 13
-#define CUT_ACER1280 14
-#define CUT_COMPAL1400_1 15
-#define CUT_COMPAL1400_2 16
-#define CUT_ASUSA2H_1 17
-#define CUT_ASUSA2H_2 18
-
-typedef struct _SiS_Private
+#define CUT_NONE 0
+#define CUT_FORCENONE 1
+#define CUT_BARCO1366 2
+#define CUT_BARCO1024 3
+#define CUT_COMPAQ1280 4
+#define CUT_COMPAQ12802 5
+#define CUT_PANEL848 6
+#define CUT_CLEVO1024 7
+#define CUT_CLEVO10242 8
+#define CUT_CLEVO1400 9
+#define CUT_CLEVO14002 10
+#define CUT_UNIWILL1024 11
+#define CUT_ASUSL3000D 12
+#define CUT_UNIWILL10242 13
+#define CUT_ACER1280 14
+#define CUT_COMPAL1400_1 15
+#define CUT_COMPAL1400_2 16
+#define CUT_ASUSA2H_1 17
+#define CUT_ASUSA2H_2 18
+#define CUT_UNKNOWNLCD 19
+#define CUT_AOP8060 20
+#define CUT_PANEL856 21
+
+struct SiS_Private
{
-#ifdef LINUX_KERNEL
- SISIOADDRESS RelIO;
+ unsigned char ChipType;
+ unsigned char ChipRevision;
+#ifdef SIS_XORG_XF86
+ PCITAG PciTag;
#endif
- SISIOADDRESS SiS_P3c4;
- SISIOADDRESS SiS_P3d4;
- SISIOADDRESS SiS_P3c0;
- SISIOADDRESS SiS_P3ce;
- SISIOADDRESS SiS_P3c2;
- SISIOADDRESS SiS_P3ca;
- SISIOADDRESS SiS_P3c6;
- SISIOADDRESS SiS_P3c7;
- SISIOADDRESS SiS_P3c8;
- SISIOADDRESS SiS_P3c9;
- SISIOADDRESS SiS_P3cb;
- SISIOADDRESS SiS_P3cd;
- SISIOADDRESS SiS_P3da;
- SISIOADDRESS SiS_Part1Port;
- SISIOADDRESS SiS_Part2Port;
- SISIOADDRESS SiS_Part3Port;
- SISIOADDRESS SiS_Part4Port;
- SISIOADDRESS SiS_Part5Port;
- SISIOADDRESS SiS_VidCapt;
- SISIOADDRESS SiS_VidPlay;
- USHORT SiS_IF_DEF_LVDS;
- USHORT SiS_IF_DEF_CH70xx;
- USHORT SiS_IF_DEF_CONEX;
- USHORT SiS_IF_DEF_TRUMPION;
- USHORT SiS_IF_DEF_DSTN;
- USHORT SiS_IF_DEF_FSTN;
- USHORT SiS_SysFlags;
- UCHAR SiS_VGAINFO;
-#ifdef LINUX_XF86
- USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#ifdef SIS_LINUX_KERNEL
+ void *ivideo;
#endif
- BOOLEAN SiS_UseROM;
- BOOLEAN SiS_ROMNew;
- BOOLEAN SiS_NeedRomModeData;
- BOOLEAN PanelSelfDetected;
- int SiS_CHOverScan;
- BOOLEAN SiS_CHSOverScan;
- BOOLEAN SiS_ChSW;
- BOOLEAN SiS_UseLCDA;
- int SiS_UseOEM;
- ULONG SiS_CustomT;
- USHORT SiS_Backup70xx;
- BOOLEAN HaveEMI;
- BOOLEAN HaveEMILCD;
- BOOLEAN OverruleEMI;
- UCHAR EMI_30,EMI_31,EMI_32,EMI_33;
- USHORT SiS_EMIOffset;
- SHORT PDC, PDCA;
- UCHAR SiS_MyCR63;
- USHORT SiS_CRT1Mode;
- USHORT SiS_flag_clearbuffer;
- int SiS_RAMType;
- UCHAR SiS_ChannelAB;
- UCHAR SiS_DataBusWidth;
- USHORT SiS_ModeType;
- USHORT SiS_VBInfo;
- USHORT SiS_TVMode;
- USHORT SiS_LCDResInfo;
- USHORT SiS_LCDTypeInfo;
- USHORT SiS_LCDInfo;
- USHORT SiS_LCDInfo661;
- USHORT SiS_VBType;
- USHORT SiS_VBExtInfo;
- USHORT SiS_YPbPr;
- USHORT SiS_SelectCRT2Rate;
- USHORT SiS_SetFlag;
- USHORT SiS_RVBHCFACT;
- USHORT SiS_RVBHCMAX;
- USHORT SiS_RVBHRS;
- USHORT SiS_VGAVT;
- USHORT SiS_VGAHT;
- USHORT SiS_VT;
- USHORT SiS_HT;
- USHORT SiS_VGAVDE;
- USHORT SiS_VGAHDE;
- USHORT SiS_VDE;
- USHORT SiS_HDE;
- USHORT SiS_NewFlickerMode;
- USHORT SiS_RY1COE;
- USHORT SiS_RY2COE;
- USHORT SiS_RY3COE;
- USHORT SiS_RY4COE;
- USHORT SiS_LCDHDES;
- USHORT SiS_LCDVDES;
- USHORT SiS_DDC_Port;
- USHORT SiS_DDC_Index;
- USHORT SiS_DDC_Data;
- USHORT SiS_DDC_NData;
- USHORT SiS_DDC_Clk;
- USHORT SiS_DDC_NClk;
- USHORT SiS_DDC_DeviceAddr;
- USHORT SiS_DDC_ReadAddr;
- USHORT SiS_DDC_SecAddr;
- USHORT SiS_ChrontelInit;
- BOOLEAN SiS_SensibleSR11;
- USHORT SiS661LCD2TableSize;
-
- USHORT SiS_PanelMinLVDS;
- USHORT SiS_PanelMin301;
-
- const SiS_StStruct *SiS_SModeIDTable;
- const SiS_StandTableStruct *SiS_StandTable;
- const SiS_ExtStruct *SiS_EModeIDTable;
- const SiS_Ext2Struct *SiS_RefIndex;
- const SiS_VBModeStruct *SiS_VBModeIDTable;
- const SiS_CRT1TableStruct *SiS_CRT1Table;
- const SiS_MCLKDataStruct *SiS_MCLKData_0;
- const SiS_MCLKDataStruct *SiS_MCLKData_1;
- SiS_VCLKDataStruct *SiS_VCLKData;
- SiS_VBVCLKDataStruct *SiS_VBVCLKData;
- const SiS_StResInfoStruct *SiS_StResInfo;
- const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-
- const UCHAR *pSiS_OutputSelect;
- const UCHAR *pSiS_SoftSetting;
-
- const DRAM4Type *SiS_SR15; /* pointer : point to array */
-#ifdef LINUX_KERNEL
- UCHAR *pSiS_SR07;
- const DRAM4Type *SiS_CR40; /* pointer : point to array */
- UCHAR *SiS_CR49;
- UCHAR *SiS_SR25;
- UCHAR *pSiS_SR1F;
- UCHAR *pSiS_SR21;
- UCHAR *pSiS_SR22;
- UCHAR *pSiS_SR23;
- UCHAR *pSiS_SR24;
- UCHAR *pSiS_SR31;
- UCHAR *pSiS_SR32;
- UCHAR *pSiS_SR33;
- UCHAR *pSiS_CRT2Data_1_2;
- UCHAR *pSiS_CRT2Data_4_D;
- UCHAR *pSiS_CRT2Data_4_E;
- UCHAR *pSiS_CRT2Data_4_10;
- const USHORT *pSiS_RGBSenseData;
- const USHORT *pSiS_VideoSenseData;
- const USHORT *pSiS_YCSenseData;
- const USHORT *pSiS_RGBSenseData2;
- const USHORT *pSiS_VideoSenseData2;
- const USHORT *pSiS_YCSenseData2;
+ unsigned char *VirtualRomBase;
+ BOOLEAN UseROM;
+#ifdef SIS_LINUX_KERNEL
+ unsigned char SISIOMEMTYPE *VideoMemoryAddress;
+ unsigned int VideoMemorySize;
#endif
+ SISIOADDRESS IOAddress;
+ SISIOADDRESS IOAddress2; /* For dual chip XGI volari */
- const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
- const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+#ifdef SIS_LINUX_KERNEL
+ SISIOADDRESS RelIO;
+#endif
+ SISIOADDRESS SiS_P3c4;
+ SISIOADDRESS SiS_P3d4;
+ SISIOADDRESS SiS_P3c0;
+ SISIOADDRESS SiS_P3ce;
+ SISIOADDRESS SiS_P3c2;
+ SISIOADDRESS SiS_P3ca;
+ SISIOADDRESS SiS_P3c6;
+ SISIOADDRESS SiS_P3c7;
+ SISIOADDRESS SiS_P3c8;
+ SISIOADDRESS SiS_P3c9;
+ SISIOADDRESS SiS_P3cb;
+ SISIOADDRESS SiS_P3cc;
+ SISIOADDRESS SiS_P3cd;
+ SISIOADDRESS SiS_P3da;
+ SISIOADDRESS SiS_Part1Port;
+ SISIOADDRESS SiS_Part2Port;
+ SISIOADDRESS SiS_Part3Port;
+ SISIOADDRESS SiS_Part4Port;
+ SISIOADDRESS SiS_Part5Port;
+ SISIOADDRESS SiS_VidCapt;
+ SISIOADDRESS SiS_VidPlay;
+ unsigned short SiS_IF_DEF_LVDS;
+ unsigned short SiS_IF_DEF_CH70xx;
+ unsigned short SiS_IF_DEF_CONEX;
+ unsigned short SiS_IF_DEF_TRUMPION;
+ unsigned short SiS_IF_DEF_DSTN;
+ unsigned short SiS_IF_DEF_FSTN;
+ unsigned short SiS_SysFlags;
+ unsigned char SiS_VGAINFO;
+#ifdef SIS_XORG_XF86
+ unsigned short SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#endif
+ BOOLEAN SiS_UseROM;
+ BOOLEAN SiS_ROMNew;
+ BOOLEAN SiS_XGIROM;
+ BOOLEAN SiS_NeedRomModeData;
+ BOOLEAN PanelSelfDetected;
+ BOOLEAN DDCPortMixup;
+ int SiS_CHOverScan;
+ BOOLEAN SiS_CHSOverScan;
+ BOOLEAN SiS_ChSW;
+ BOOLEAN SiS_UseLCDA;
+ int SiS_UseOEM;
+ unsigned int SiS_CustomT;
+ int SiS_UseWide, SiS_UseWideCRT2;
+ int SiS_TVBlue;
+ unsigned short SiS_Backup70xx;
+ BOOLEAN HaveEMI;
+ BOOLEAN HaveEMILCD;
+ BOOLEAN OverruleEMI;
+ unsigned char EMI_30,EMI_31,EMI_32,EMI_33;
+ unsigned short SiS_EMIOffset;
+ unsigned short SiS_PWDOffset;
+ short PDC, PDCA;
+ unsigned char SiS_MyCR63;
+ unsigned short SiS_CRT1Mode;
+ unsigned short SiS_flag_clearbuffer;
+ int SiS_RAMType;
+ unsigned char SiS_ChannelAB;
+ unsigned char SiS_DataBusWidth;
+ unsigned short SiS_ModeType;
+ unsigned short SiS_VBInfo;
+ unsigned short SiS_TVMode;
+ unsigned short SiS_LCDResInfo;
+ unsigned short SiS_LCDTypeInfo;
+ unsigned short SiS_LCDInfo;
+ unsigned short SiS_LCDInfo661;
+ unsigned short SiS_VBType;
+ unsigned short SiS_VBExtInfo;
+ unsigned short SiS_YPbPr;
+ unsigned short SiS_SelectCRT2Rate;
+ unsigned short SiS_SetFlag;
+ unsigned short SiS_RVBHCFACT;
+ unsigned short SiS_RVBHCMAX;
+ unsigned short SiS_RVBHRS;
+ unsigned short SiS_RVBHRS2;
+ unsigned short SiS_VGAVT;
+ unsigned short SiS_VGAHT;
+ unsigned short SiS_VT;
+ unsigned short SiS_HT;
+ unsigned short SiS_VGAVDE;
+ unsigned short SiS_VGAHDE;
+ unsigned short SiS_VDE;
+ unsigned short SiS_HDE;
+ unsigned short SiS_NewFlickerMode;
+ unsigned short SiS_RY1COE;
+ unsigned short SiS_RY2COE;
+ unsigned short SiS_RY3COE;
+ unsigned short SiS_RY4COE;
+ unsigned short SiS_LCDHDES;
+ unsigned short SiS_LCDVDES;
+ unsigned short SiS_DDC_Port;
+ unsigned short SiS_DDC_Index;
+ unsigned short SiS_DDC_Data;
+ unsigned short SiS_DDC_NData;
+ unsigned short SiS_DDC_Clk;
+ unsigned short SiS_DDC_NClk;
+ unsigned short SiS_DDC_DeviceAddr;
+ unsigned short SiS_DDC_ReadAddr;
+ unsigned short SiS_DDC_SecAddr;
+ unsigned short SiS_ChrontelInit;
+ BOOLEAN SiS_SensibleSR11;
+ unsigned short SiS661LCD2TableSize;
+
+ unsigned short SiS_PanelMinLVDS;
+ unsigned short SiS_PanelMin301;
+
+ const struct SiS_St *SiS_SModeIDTable;
+ const struct SiS_StandTable_S *SiS_StandTable;
+ const struct SiS_Ext *SiS_EModeIDTable;
+ const struct SiS_Ext2 *SiS_RefIndex;
+ const struct SiS_VBMode *SiS_VBModeIDTable;
+ const struct SiS_CRT1Table *SiS_CRT1Table;
+ const struct SiS_MCLKData *SiS_MCLKData_0;
+ const struct SiS_MCLKData *SiS_MCLKData_1;
+ struct SiS_VCLKData *SiS_VCLKData;
+ struct SiS_VBVCLKData *SiS_VBVCLKData;
+ const struct SiS_StResInfo_S *SiS_StResInfo;
+ const struct SiS_ModeResInfo_S *SiS_ModeResInfo;
+
+ const unsigned char *pSiS_OutputSelect;
+ const unsigned char *pSiS_SoftSetting;
+
+ const unsigned char *SiS_SR15;
+
+ const struct SiS_PanelDelayTbl *SiS_PanelDelayTbl;
+ const struct SiS_PanelDelayTbl *SiS_PanelDelayTblLVDS;
/* SiS bridge */
- const UCHAR *SiS_NTSCPhase;
- const UCHAR *SiS_PALPhase;
- const UCHAR *SiS_NTSCPhase2;
- const UCHAR *SiS_PALPhase2;
- const UCHAR *SiS_PALMPhase;
- const UCHAR *SiS_PALNPhase;
- const UCHAR *SiS_PALMPhase2;
- const UCHAR *SiS_PALNPhase2;
- const UCHAR *SiS_SpecialPhase;
- const UCHAR *SiS_SpecialPhaseM;
- const UCHAR *SiS_SpecialPhaseJ;
- const SiS_LCDDataStruct *SiS_ExtLCD1024x768Data;
- const SiS_LCDDataStruct *SiS_St2LCD1024x768Data;
- const SiS_LCDDataStruct *SiS_LCD1280x720Data;
- const SiS_LCDDataStruct *SiS_StLCD1280x768_2Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1280x768_2Data;
- const SiS_LCDDataStruct *SiS_LCD1280x800Data;
- const SiS_LCDDataStruct *SiS_LCD1280x800_2Data;
- const SiS_LCDDataStruct *SiS_LCD1280x960Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1280x1024Data;
- const SiS_LCDDataStruct *SiS_St2LCD1280x1024Data;
- const SiS_LCDDataStruct *SiS_StLCD1400x1050Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1400x1050Data;
- const SiS_LCDDataStruct *SiS_StLCD1600x1200Data;
- const SiS_LCDDataStruct *SiS_ExtLCD1600x1200Data;
- const SiS_LCDDataStruct *SiS_LCD1680x1050Data;
- const SiS_LCDDataStruct *SiS_NoScaleData;
- const SiS_TVDataStruct *SiS_StPALData;
- const SiS_TVDataStruct *SiS_ExtPALData;
- const SiS_TVDataStruct *SiS_StNTSCData;
- const SiS_TVDataStruct *SiS_ExtNTSCData;
- const SiS_TVDataStruct *SiS_St1HiTVData;
- const SiS_TVDataStruct *SiS_St2HiTVData;
- const SiS_TVDataStruct *SiS_ExtHiTVData;
- const SiS_TVDataStruct *SiS_St525iData;
- const SiS_TVDataStruct *SiS_St525pData;
- const SiS_TVDataStruct *SiS_St750pData;
- const SiS_TVDataStruct *SiS_Ext525iData;
- const SiS_TVDataStruct *SiS_Ext525pData;
- const SiS_TVDataStruct *SiS_Ext750pData;
- const UCHAR *SiS_NTSCTiming;
- const UCHAR *SiS_PALTiming;
- const UCHAR *SiS_HiTVExtTiming;
- const UCHAR *SiS_HiTVSt1Timing;
- const UCHAR *SiS_HiTVSt2Timing;
- const UCHAR *SiS_HiTVGroup3Data;
- const UCHAR *SiS_HiTVGroup3Simu;
+ const struct SiS_LCDData *SiS_ExtLCD1024x768Data;
+ const struct SiS_LCDData *SiS_St2LCD1024x768Data;
+ const struct SiS_LCDData *SiS_LCD1280x720Data;
+ const struct SiS_LCDData *SiS_StLCD1280x768_2Data;
+ const struct SiS_LCDData *SiS_ExtLCD1280x768_2Data;
+ const struct SiS_LCDData *SiS_LCD1280x800Data;
+ const struct SiS_LCDData *SiS_LCD1280x800_2Data;
+ const struct SiS_LCDData *SiS_LCD1280x854Data;
+ const struct SiS_LCDData *SiS_LCD1280x960Data;
+ const struct SiS_LCDData *SiS_ExtLCD1280x1024Data;
+ const struct SiS_LCDData *SiS_St2LCD1280x1024Data;
+ const struct SiS_LCDData *SiS_StLCD1400x1050Data;
+ const struct SiS_LCDData *SiS_ExtLCD1400x1050Data;
+ const struct SiS_LCDData *SiS_StLCD1600x1200Data;
+ const struct SiS_LCDData *SiS_ExtLCD1600x1200Data;
+ const struct SiS_LCDData *SiS_LCD1680x1050Data;
+ const struct SiS_LCDData *SiS_NoScaleData;
+ const struct SiS_TVData *SiS_StPALData;
+ const struct SiS_TVData *SiS_ExtPALData;
+ const struct SiS_TVData *SiS_StNTSCData;
+ const struct SiS_TVData *SiS_ExtNTSCData;
+ const struct SiS_TVData *SiS_St1HiTVData;
+ const struct SiS_TVData *SiS_St2HiTVData;
+ const struct SiS_TVData *SiS_ExtHiTVData;
+ const struct SiS_TVData *SiS_St525iData;
+ const struct SiS_TVData *SiS_St525pData;
+ const struct SiS_TVData *SiS_St750pData;
+ const struct SiS_TVData *SiS_Ext525iData;
+ const struct SiS_TVData *SiS_Ext525pData;
+ const struct SiS_TVData *SiS_Ext750pData;
+ const unsigned char *SiS_NTSCTiming;
+ const unsigned char *SiS_PALTiming;
+ const unsigned char *SiS_HiTVExtTiming;
+ const unsigned char *SiS_HiTVSt1Timing;
+ const unsigned char *SiS_HiTVSt2Timing;
+ const unsigned char *SiS_HiTVGroup3Data;
+ const unsigned char *SiS_HiTVGroup3Simu;
#if 0
- const UCHAR *SiS_HiTVTextTiming;
- const UCHAR *SiS_HiTVGroup3Text;
+ const unsigned char *SiS_HiTVTextTiming;
+ const unsigned char *SiS_HiTVGroup3Text;
#endif
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
- const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_1;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_2;
+ const struct SiS_Part2PortTbl *SiS_CRT2Part2_1024x768_3;
/* LVDS, Chrontel */
- const SiS_LVDSDataStruct *SiS_LVDS800x600Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS800x600Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS640x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS640x480Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS320x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSXXXxXXXData_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_2;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_1;
- const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_2;
- const SiS_LVDSDataStruct *SiS_LVDS848x480Data_1;
- const SiS_LVDSDataStruct *SiS_LVDS848x480Data_2;
- const SiS_LVDSDataStruct *SiS_CHTVUNTSCData;
- const SiS_LVDSDataStruct *SiS_CHTVONTSCData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALMData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALMData;
- const SiS_LVDSDataStruct *SiS_CHTVUPALNData;
- const SiS_LVDSDataStruct *SiS_CHTVOPALNData;
- const SiS_LVDSDataStruct *SiS_CHTVSOPALData;
-
- const SiS_LVDSDesStruct *SiS_PanelType00_1;
- const SiS_LVDSDesStruct *SiS_PanelType01_1;
- const SiS_LVDSDesStruct *SiS_PanelType02_1;
- const SiS_LVDSDesStruct *SiS_PanelType03_1;
- const SiS_LVDSDesStruct *SiS_PanelType04_1;
- const SiS_LVDSDesStruct *SiS_PanelType05_1;
- const SiS_LVDSDesStruct *SiS_PanelType06_1;
- const SiS_LVDSDesStruct *SiS_PanelType07_1;
- const SiS_LVDSDesStruct *SiS_PanelType08_1;
- const SiS_LVDSDesStruct *SiS_PanelType09_1;
- const SiS_LVDSDesStruct *SiS_PanelType0a_1;
- const SiS_LVDSDesStruct *SiS_PanelType0b_1;
- const SiS_LVDSDesStruct *SiS_PanelType0c_1;
- const SiS_LVDSDesStruct *SiS_PanelType0d_1;
- const SiS_LVDSDesStruct *SiS_PanelType0e_1;
- const SiS_LVDSDesStruct *SiS_PanelType0f_1;
- const SiS_LVDSDesStruct *SiS_PanelTypeNS_1;
- const SiS_LVDSDesStruct *SiS_PanelType00_2;
- const SiS_LVDSDesStruct *SiS_PanelType01_2;
- const SiS_LVDSDesStruct *SiS_PanelType02_2;
- const SiS_LVDSDesStruct *SiS_PanelType03_2;
- const SiS_LVDSDesStruct *SiS_PanelType04_2;
- const SiS_LVDSDesStruct *SiS_PanelType05_2;
- const SiS_LVDSDesStruct *SiS_PanelType06_2;
- const SiS_LVDSDesStruct *SiS_PanelType07_2;
- const SiS_LVDSDesStruct *SiS_PanelType08_2;
- const SiS_LVDSDesStruct *SiS_PanelType09_2;
- const SiS_LVDSDesStruct *SiS_PanelType0a_2;
- const SiS_LVDSDesStruct *SiS_PanelType0b_2;
- const SiS_LVDSDesStruct *SiS_PanelType0c_2;
- const SiS_LVDSDesStruct *SiS_PanelType0d_2;
- const SiS_LVDSDesStruct *SiS_PanelType0e_2;
- const SiS_LVDSDesStruct *SiS_PanelType0f_2;
- const SiS_LVDSDesStruct *SiS_PanelTypeNS_2;
- const SiS_LVDSDesStruct *SiS_CHTVUNTSCDesData;
- const SiS_LVDSDesStruct *SiS_CHTVONTSCDesData;
- const SiS_LVDSDesStruct *SiS_CHTVUPALDesData;
- const SiS_LVDSDesStruct *SiS_CHTVOPALDesData;
-
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3_H;
- const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1320x480_1;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UNTSC;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1OPAL;
- const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1SOPAL;
-
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPAL;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALM;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALM;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
- const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
-
- const UCHAR *SiS_CHTVVCLKUNTSC;
- const UCHAR *SiS_CHTVVCLKONTSC;
- const UCHAR *SiS_CHTVVCLKUPAL;
- const UCHAR *SiS_CHTVVCLKOPAL;
- const UCHAR *SiS_CHTVVCLKUPALM;
- const UCHAR *SiS_CHTVVCLKOPALM;
- const UCHAR *SiS_CHTVVCLKUPALN;
- const UCHAR *SiS_CHTVVCLKOPALN;
- const UCHAR *SiS_CHTVVCLKSOPAL;
-
- USHORT PanelXRes, PanelHT;
- USHORT PanelYRes, PanelVT;
- USHORT PanelHRS, PanelHRE;
- USHORT PanelVRS, PanelVRE;
- USHORT PanelVCLKIdx300;
- USHORT PanelVCLKIdx315;
-
- BOOLEAN UseCustomMode;
- BOOLEAN CRT1UsesCustomMode;
- USHORT CHDisplay;
- USHORT CHSyncStart;
- USHORT CHSyncEnd;
- USHORT CHTotal;
- USHORT CHBlankStart;
- USHORT CHBlankEnd;
- USHORT CVDisplay;
- USHORT CVSyncStart;
- USHORT CVSyncEnd;
- USHORT CVTotal;
- USHORT CVBlankStart;
- USHORT CVBlankEnd;
- ULONG CDClock;
- ULONG CFlags;
- UCHAR CCRT1CRTC[17];
- UCHAR CSR2B;
- UCHAR CSR2C;
- USHORT CSRClock;
- USHORT CSRClock_CRT1;
- USHORT CModeFlag;
- USHORT CModeFlag_CRT1;
- USHORT CInfoFlag;
-
- int LVDSHL;
-
- BOOLEAN Backup;
- UCHAR Backup_Mode;
- UCHAR Backup_14;
- UCHAR Backup_15;
- UCHAR Backup_16;
- UCHAR Backup_17;
- UCHAR Backup_18;
- UCHAR Backup_19;
- UCHAR Backup_1a;
- UCHAR Backup_1b;
- UCHAR Backup_1c;
- UCHAR Backup_1d;
-
- int UsePanelScaler;
- int CenterScreen;
-
- USHORT CP_Vendor, CP_Product;
- BOOLEAN CP_HaveCustomData;
- int CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
- int CP_MaxX, CP_MaxY, CP_MaxClock;
- UCHAR CP_PrefSR2B, CP_PrefSR2C;
- USHORT CP_PrefClock;
- BOOLEAN CP_Supports64048075;
- int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
- int CP_HTotal[7], CP_VTotal[7];
- int CP_HSyncStart[7], CP_VSyncStart[7];
- int CP_HSyncEnd[7], CP_VSyncEnd[7];
- int CP_HBlankStart[7], CP_VBlankStart[7];
- int CP_HBlankEnd[7], CP_VBlankEnd[7];
- int CP_Clock[7];
- BOOLEAN CP_DataValid[7];
- BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
-} SiS_Private;
+ const struct SiS_LVDSData *SiS_LVDS320x240Data_1;
+ const struct SiS_LVDSData *SiS_LVDS320x240Data_2;
+ const struct SiS_LVDSData *SiS_LVDS640x480Data_1;
+ const struct SiS_LVDSData *SiS_LVDS800x600Data_1;
+ const struct SiS_LVDSData *SiS_LVDS1024x600Data_1;
+ const struct SiS_LVDSData *SiS_LVDS1024x768Data_1;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1366Data_1;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1366Data_2;
+ const struct SiS_LVDSData *SiS_LVDSBARCO1024Data_1;
+ const struct SiS_LVDSData *SiS_LVDS848x480Data_1;
+ const struct SiS_LVDSData *SiS_LVDS848x480Data_2;
+ const struct SiS_LVDSData *SiS_CHTVUNTSCData;
+ const struct SiS_LVDSData *SiS_CHTVONTSCData;
+ const struct SiS_LVDSData *SiS_CHTVUPALData;
+ const struct SiS_LVDSData *SiS_CHTVOPALData;
+ const struct SiS_LVDSData *SiS_CHTVUPALMData;
+ const struct SiS_LVDSData *SiS_CHTVOPALMData;
+ const struct SiS_LVDSData *SiS_CHTVUPALNData;
+ const struct SiS_LVDSData *SiS_CHTVOPALNData;
+ const struct SiS_LVDSData *SiS_CHTVSOPALData;
+
+ const struct SiS_LVDSDes *SiS_PanelType04_1a;
+ const struct SiS_LVDSDes *SiS_PanelType04_2a;
+ const struct SiS_LVDSDes *SiS_PanelType04_1b;
+ const struct SiS_LVDSDes *SiS_PanelType04_2b;
+
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_1;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_2;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_2_H;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_3;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1320x240_3_H;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1640x480_1;
+ const struct SiS_LVDSCRT1Data *SiS_LVDSCRT1640x480_1_H;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1UNTSC;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1ONTSC;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1UPAL;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1OPAL;
+ const struct SiS_LVDSCRT1Data *SiS_CHTVCRT1SOPAL;
+
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UNTSC;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_ONTSC;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPAL;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPAL;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPALM;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPALM;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_UPALN;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_OPALN;
+ const struct SiS_CHTVRegData *SiS_CHTVReg_SOPAL;
+
+ const unsigned char *SiS_CHTVVCLKUNTSC;
+ const unsigned char *SiS_CHTVVCLKONTSC;
+ const unsigned char *SiS_CHTVVCLKUPAL;
+ const unsigned char *SiS_CHTVVCLKOPAL;
+ const unsigned char *SiS_CHTVVCLKUPALM;
+ const unsigned char *SiS_CHTVVCLKOPALM;
+ const unsigned char *SiS_CHTVVCLKUPALN;
+ const unsigned char *SiS_CHTVVCLKOPALN;
+ const unsigned char *SiS_CHTVVCLKSOPAL;
+
+ unsigned short PanelXRes, PanelHT;
+ unsigned short PanelYRes, PanelVT;
+ unsigned short PanelHRS, PanelHRE;
+ unsigned short PanelVRS, PanelVRE;
+ unsigned short PanelVCLKIdx300;
+ unsigned short PanelVCLKIdx315;
+ BOOLEAN Alternate1600x1200;
+
+ BOOLEAN UseCustomMode;
+ BOOLEAN CRT1UsesCustomMode;
+ unsigned short CHDisplay;
+ unsigned short CHSyncStart;
+ unsigned short CHSyncEnd;
+ unsigned short CHTotal;
+ unsigned short CHBlankStart;
+ unsigned short CHBlankEnd;
+ unsigned short CVDisplay;
+ unsigned short CVSyncStart;
+ unsigned short CVSyncEnd;
+ unsigned short CVTotal;
+ unsigned short CVBlankStart;
+ unsigned short CVBlankEnd;
+ unsigned int CDClock;
+ unsigned int CFlags;
+ unsigned char CCRT1CRTC[17];
+ unsigned char CSR2B;
+ unsigned char CSR2C;
+ unsigned short CSRClock;
+ unsigned short CSRClock_CRT1;
+ unsigned short CModeFlag;
+ unsigned short CModeFlag_CRT1;
+ unsigned short CInfoFlag;
+
+ int LVDSHL;
+
+ BOOLEAN Backup;
+ unsigned char Backup_Mode;
+ unsigned char Backup_14;
+ unsigned char Backup_15;
+ unsigned char Backup_16;
+ unsigned char Backup_17;
+ unsigned char Backup_18;
+ unsigned char Backup_19;
+ unsigned char Backup_1a;
+ unsigned char Backup_1b;
+ unsigned char Backup_1c;
+ unsigned char Backup_1d;
+
+ unsigned char Init_P4_0E;
+
+ int UsePanelScaler;
+ int CenterScreen;
+
+ unsigned short CP_Vendor, CP_Product;
+ BOOLEAN CP_HaveCustomData;
+ int CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
+ int CP_MaxX, CP_MaxY, CP_MaxClock;
+ unsigned char CP_PrefSR2B, CP_PrefSR2C;
+ unsigned short CP_PrefClock;
+ BOOLEAN CP_Supports64048075;
+ int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
+ int CP_HTotal[7], CP_VTotal[7];
+ int CP_HSyncStart[7], CP_VSyncStart[7];
+ int CP_HSyncEnd[7], CP_VSyncEnd[7];
+ int CP_HBlankStart[7], CP_VBlankStart[7];
+ int CP_HBlankEnd[7], CP_VBlankEnd[7];
+ int CP_Clock[7];
+ BOOLEAN CP_DataValid[7];
+ BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+};
#endif
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 698ca9232e73..81a6d9f188cf 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1061,6 +1061,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
chip_id = id->device;
+ if(chip_id == CYBERBLADEi1)
+ output("*** Please do use cyblafb, Cyberblade/i1 support "
+ "will soon be removed from tridentfb!\n");
+
+
/* If PCI id is 0x9660 then further detect chip type */
if (chip_id == TGUI9660) {
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index a272592b0373..3cc23106641d 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -19,6 +19,9 @@
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <video/vga.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -54,6 +57,7 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
+static int vga_compat;
/* --------------------------------------------------------------------- */
@@ -86,6 +90,37 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
+static int vesafb_blank(int blank, struct fb_info *info)
+{
+ int err = 1;
+
+ if (vga_compat) {
+ int loop = 10000;
+ u8 seq = 0, crtc17 = 0;
+
+ if (blank == FB_BLANK_POWERDOWN) {
+ seq = 0x20;
+ crtc17 = 0x00;
+ err = 0;
+ } else {
+ seq = 0x00;
+ crtc17 = 0x80;
+ err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
+ }
+
+ vga_wseq(NULL, 0x00, 0x01);
+ seq |= vga_rseq(NULL, 0x01) & ~0x20;
+ vga_wseq(NULL, 0x00, seq);
+
+ crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
+ while (loop--);
+ vga_wcrt(NULL, 0x17, crtc17);
+ vga_wseq(NULL, 0x00, 0x03);
+ }
+
+ return err;
+}
+
static void vesa_setpalette(int regno, unsigned red, unsigned green,
unsigned blue)
{
@@ -176,6 +211,7 @@ static struct fb_ops vesafb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = vesafb_setcolreg,
.fb_pan_display = vesafb_pan_display,
+ .fb_blank = vesafb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
@@ -429,6 +465,10 @@ static int __init vesafb_probe(struct device *device)
info->flags = FBINFO_FLAG_DEFAULT |
(ypan) ? FBINFO_HWACCEL_YPAN : 0;
+ vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
+ printk("vesafb: Mode is %sVGA compatible\n",
+ (vga_compat) ? "" : "not ");
+
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
goto err;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index b137a3fe0752..92d46555dd86 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -20,6 +20,8 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
#include <asm/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index 0ea62d8bc703..ca92940f3943 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -342,16 +342,11 @@ static void vga_cleanup(struct vgastate *state)
if (state->vidstate != NULL) {
struct regstate *saved = (struct regstate *) state->vidstate;
- if (saved->vga_font0)
- vfree(saved->vga_font0);
- if (saved->vga_font1)
- vfree(saved->vga_font1);
- if (saved->vga_text)
- vfree(saved->vga_text);
- if (saved->vga_cmap)
- vfree(saved->vga_cmap);
- if (saved->attr)
- vfree(saved->attr);
+ vfree(saved->vga_font0);
+ vfree(saved->vga_font1);
+ vfree(saved->vga_text);
+ vfree(saved->vga_cmap);
+ vfree(saved->attr);
kfree(saved);
state->vidstate = NULL;
}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index adcda697ea60..cf8cdb108fd9 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -5,9 +5,15 @@
*
* Copyright (C) 2002, ATI Corp.
* Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton
*
* Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
+ * Generic platform support by Ian Molton <spyro@f2s.com>
+ * and Richard Purdie <rpurdie@rpsys.net>
+ *
+ * w32xx support by Ian Molton
+ *
* 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.
@@ -19,9 +25,9 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/string.h>
-#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <video/w100fb.h>
@@ -30,114 +36,78 @@
/*
* Prototypes
*/
-static void w100fb_save_buffer(void);
-static void w100fb_clear_buffer(void);
-static void w100fb_restore_buffer(void);
-static void w100fb_clear_screen(u32 mode, long int offset);
-static void w100_resume(void);
static void w100_suspend(u32 mode);
-static void w100_init_qvga_rotation(u16 deg);
-static void w100_init_vga_rotation(u16 deg);
static void w100_vsync(void);
-static void w100_init_sharp_lcd(u32 mode);
-static void w100_pwm_setup(void);
-static void w100_InitExtMem(u32 mode);
-static void w100_hw_init(void);
-static u16 w100_set_fastsysclk(u16 Freq);
-
-static void lcdtg_hw_init(u32 mode);
-static void lcdtg_lcd_change(u32 mode);
-static void lcdtg_resume(void);
-static void lcdtg_suspend(void);
-
-
-/* Register offsets & lengths */
-#define REMAPPED_FB_LEN 0x15ffff
-
-#define BITS_PER_PIXEL 16
+static void w100_hw_init(struct w100fb_par*);
+static void w100_pwm_setup(struct w100fb_par*);
+static void w100_init_clocks(struct w100fb_par*);
+static void w100_setup_memory(struct w100fb_par*);
+static void w100_init_lcd(struct w100fb_par*);
+static void w100_set_dispregs(struct w100fb_par*);
+static void w100_update_enable(void);
+static void w100_update_disable(void);
+static void calc_hsync(struct w100fb_par *par);
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
/* Pseudo palette size */
#define MAX_PALETTES 16
-/* for resolution change */
-#define LCD_MODE_INIT (-1)
-#define LCD_MODE_480 0
-#define LCD_MODE_320 1
-#define LCD_MODE_240 2
-#define LCD_MODE_640 3
-
-#define LCD_SHARP_QVGA 0
-#define LCD_SHARP_VGA 1
-
-#define LCD_MODE_PORTRAIT 0
-#define LCD_MODE_LANDSCAPE 1
-
#define W100_SUSPEND_EXTMEM 0
#define W100_SUSPEND_ALL 1
-/* General frame buffer data structures */
-struct w100fb_par {
- u32 xres;
- u32 yres;
- int fastsysclk_mode;
- int lcdMode;
- int rotation_flag;
- int blanking_flag;
- int comadj;
- int phadadj;
-};
-
-static struct w100fb_par *current_par;
+#define BITS_PER_PIXEL 16
/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
static void *remapped_base;
static void *remapped_regs;
static void *remapped_fbuf;
-/* External Function */
-static void(*w100fb_ssp_send)(u8 adrs, u8 data);
+#define REMAPPED_FB_LEN 0x15ffff
+
+/* This is the offset in the w100's address space we map the current
+ framebuffer memory to. We use the position of external memory as
+ we can remap internal memory to there if external isn't present. */
+#define W100_FB_BASE MEM_EXT_BASE_VALUE
+
/*
* Sysfs functions
*/
-
-static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- return sprintf(buf, "%d\n",par->rotation_flag);
+ return sprintf(buf, "%d\n",par->flip);
}
-static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned int rotate;
+ unsigned int flip;
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- rotate = simple_strtoul(buf, NULL, 10);
+ flip = simple_strtoul(buf, NULL, 10);
- if (rotate > 0) par->rotation_flag = 1;
- else par->rotation_flag = 0;
+ if (flip > 0)
+ par->flip = 1;
+ else
+ par->flip = 0;
+
+ w100_update_disable();
+ w100_set_dispregs(par);
+ w100_update_enable();
- if (par->lcdMode == LCD_MODE_320)
- w100_init_qvga_rotation(par->rotation_flag ? 270 : 90);
- else if (par->lcdMode == LCD_MODE_240)
- w100_init_qvga_rotation(par->rotation_flag ? 180 : 0);
- else if (par->lcdMode == LCD_MODE_640)
- w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
- else if (par->lcdMode == LCD_MODE_480)
- w100_init_vga_rotation(par->rotation_flag ? 180 : 0);
+ calc_hsync(par);
return count;
}
-static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store);
+static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long param;
- unsigned long regs;
+ unsigned long regs, param;
regs = simple_strtoul(buf, NULL, 16);
param = readl(remapped_regs + regs);
printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
@@ -148,8 +118,7 @@ static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long regs;
- unsigned long param;
+ unsigned long regs, param;
sscanf(buf, "%lx %lx", &regs, &param);
if (regs <= 0x2000) {
@@ -163,54 +132,56 @@ static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *att
static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
-static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- return sprintf(buf, "%d\n",par->fastsysclk_mode);
+ return sprintf(buf, "%d\n",par->fastpll_mode);
}
-static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- int param;
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
- param = simple_strtoul(buf, NULL, 10);
-
- if (param == 75) {
- printk("Set fastsysclk %d\n", param);
- par->fastsysclk_mode = param;
- w100_set_fastsysclk(par->fastsysclk_mode);
- } else if (param == 100) {
- printk("Set fastsysclk %d\n", param);
- par->fastsysclk_mode = param;
- w100_set_fastsysclk(par->fastsysclk_mode);
+ if (simple_strtoul(buf, NULL, 10) > 0) {
+ par->fastpll_mode=1;
+ printk("w100fb: Using fast system clock (if possible)\n");
+ } else {
+ par->fastpll_mode=0;
+ printk("w100fb: Using normal system clock\n");
}
+
+ w100_init_clocks(par);
+ calc_hsync(par);
+
return count;
}
-static DEVICE_ATTR(fastsysclk, 0644, fastsysclk_show, fastsysclk_store);
+static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
/*
- * The touchscreen on this device needs certain information
- * from the video driver to function correctly. We export it here.
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
*/
-int w100fb_get_xres(void) {
- return current_par->xres;
-}
+unsigned long w100fb_get_hsynclen(struct device *dev)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
-int w100fb_get_blanking(void) {
- return current_par->blanking_flag;
+ /* If display is blanked/suspended, hsync isn't active */
+ if (par->blanked)
+ return 0;
+ else
+ return par->hsync_len;
}
+EXPORT_SYMBOL(w100fb_get_hsynclen);
-int w100fb_get_fastsysclk(void) {
- return current_par->fastsysclk_mode;
+static void w100fb_clear_screen(struct w100fb_par *par)
+{
+ memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
}
-EXPORT_SYMBOL(w100fb_get_xres);
-EXPORT_SYMBOL(w100fb_get_blanking);
-EXPORT_SYMBOL(w100fb_get_fastsysclk);
/*
@@ -234,7 +205,6 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* according to the RGB bitfield information.
*/
if (regno < MAX_PALETTES) {
-
u32 *pal = info->pseudo_palette;
val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -250,115 +220,90 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
*/
static int w100fb_blank(int blank_mode, struct fb_info *info)
{
- struct w100fb_par *par;
- par=info->par;
+ struct w100fb_par *par = info->par;
+ struct w100_tg_info *tg = par->mach->tg;
switch(blank_mode) {
- case FB_BLANK_NORMAL: /* Normal blanking */
- case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
- case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
- case FB_BLANK_POWERDOWN: /* Poweroff */
- if (par->blanking_flag == 0) {
- w100fb_save_buffer();
- lcdtg_suspend();
- par->blanking_flag = 1;
+ case FB_BLANK_NORMAL: /* Normal blanking */
+ case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+ case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+ case FB_BLANK_POWERDOWN: /* Poweroff */
+ if (par->blanked == 0) {
+ if(tg && tg->suspend)
+ tg->suspend(par);
+ par->blanked = 1;
}
break;
case FB_BLANK_UNBLANK: /* Unblanking */
- if (par->blanking_flag != 0) {
- w100fb_restore_buffer();
- lcdtg_resume();
- par->blanking_flag = 0;
+ if (par->blanked != 0) {
+ if(tg && tg->resume)
+ tg->resume(par);
+ par->blanked = 0;
}
break;
}
return 0;
}
+
/*
* Change the resolution by calling the appropriate hardware functions
*/
-static void w100fb_changeres(int rotate_mode, u32 mode)
+static void w100fb_activate_var(struct w100fb_par *par)
{
- u16 rotation=0;
-
- switch(rotate_mode) {
- case LCD_MODE_LANDSCAPE:
- rotation=(current_par->rotation_flag ? 270 : 90);
- break;
- case LCD_MODE_PORTRAIT:
- rotation=(current_par->rotation_flag ? 180 : 0);
- break;
- }
+ struct w100_tg_info *tg = par->mach->tg;
- w100_pwm_setup();
- switch(mode) {
- case LCD_SHARP_QVGA:
- w100_vsync();
- w100_suspend(W100_SUSPEND_EXTMEM);
- w100_init_sharp_lcd(LCD_SHARP_QVGA);
- w100_init_qvga_rotation(rotation);
- w100_InitExtMem(LCD_SHARP_QVGA);
- w100fb_clear_screen(LCD_SHARP_QVGA, 0);
- lcdtg_lcd_change(LCD_SHARP_QVGA);
- break;
- case LCD_SHARP_VGA:
- w100fb_clear_screen(LCD_SHARP_QVGA, 0);
- writel(0xBFFFA000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- w100_InitExtMem(LCD_SHARP_VGA);
- w100fb_clear_screen(LCD_SHARP_VGA, 0x200000);
- w100_vsync();
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- if (rotation != 0)
- w100_init_vga_rotation(rotation);
- lcdtg_lcd_change(LCD_SHARP_VGA);
- break;
- }
+ w100_pwm_setup(par);
+ w100_setup_memory(par);
+ w100_init_clocks(par);
+ w100fb_clear_screen(par);
+ w100_vsync();
+
+ w100_update_disable();
+ w100_init_lcd(par);
+ w100_set_dispregs(par);
+ w100_update_enable();
+
+ calc_hsync(par);
+
+ if (!par->blanked && tg && tg->change)
+ tg->change(par);
}
-/*
- * Set up the display for the fb subsystem
+
+/* 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 void w100fb_activate_var(struct fb_info *info)
+static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
{
- u32 temp32;
- struct w100fb_par *par=info->par;
- struct fb_var_screeninfo *var = &info->var;
+ struct w100_mode *mode = NULL;
+ struct w100_mode *modelist = par->mach->modelist;
+ unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+ unsigned int i;
+
+ for (i = 0 ; i < par->mach->num_modes ; i++) {
+ if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
+ modelist[i].xres < best_x && modelist[i].yres < best_y) {
+ best_x = modelist[i].xres;
+ best_y = modelist[i].yres;
+ mode = &modelist[i];
+ } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
+ modelist[i].xres < best_y && modelist[i].yres < best_x) {
+ best_x = modelist[i].yres;
+ best_y = modelist[i].xres;
+ mode = &modelist[i];
+ }
+ }
- /* Set the hardware to 565 */
- temp32 = readl(remapped_regs + mmDISP_DEBUG2);
- temp32 &= 0xff7fffff;
- temp32 |= 0x00800000;
- writel(temp32, remapped_regs + mmDISP_DEBUG2);
+ if (mode && saveval) {
+ *x = best_x;
+ *y = best_y;
+ }
- if (par->lcdMode == LCD_MODE_INIT) {
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- w100_init_vga_rotation(par->rotation_flag ? 270 : 90);
- par->lcdMode = LCD_MODE_640;
- lcdtg_hw_init(LCD_SHARP_VGA);
- } else if (var->xres == 320 && var->yres == 240) {
- if (par->lcdMode != LCD_MODE_320) {
- w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_QVGA);
- par->lcdMode = LCD_MODE_320;
- }
- } else if (var->xres == 240 && var->yres == 320) {
- if (par->lcdMode != LCD_MODE_240) {
- w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_QVGA);
- par->lcdMode = LCD_MODE_240;
- }
- } else if (var->xres == 640 && var->yres == 480) {
- if (par->lcdMode != LCD_MODE_640) {
- w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_VGA);
- par->lcdMode = LCD_MODE_640;
- }
- } else if (var->xres == 480 && var->yres == 640) {
- if (par->lcdMode != LCD_MODE_480) {
- w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_VGA);
- par->lcdMode = LCD_MODE_480;
- }
- } else printk(KERN_ERR "W100FB: Resolution error!\n");
+ return mode;
}
@@ -366,31 +311,19 @@ static void w100fb_activate_var(struct fb_info *info)
* w100fb_check_var():
* Get the video params out of 'var'. If a value doesn't fit, round it up,
* if it's too big, return -EINVAL.
- *
*/
static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- if (var->xres < var->yres) { /* Portrait mode */
- if ((var->xres > 480) || (var->yres > 640)) {
- return -EINVAL;
- } else if ((var->xres > 240) || (var->yres > 320)) {
- var->xres = 480;
- var->yres = 640;
- } else {
- var->xres = 240;
- var->yres = 320;
- }
- } else { /* Landscape mode */
- if ((var->xres > 640) || (var->yres > 480)) {
- return -EINVAL;
- } else if ((var->xres > 320) || (var->yres > 240)) {
- var->xres = 640;
- var->yres = 480;
- } else {
- var->xres = 320;
- var->yres = 240;
- }
- }
+ struct w100fb_par *par=info->par;
+
+ if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
+ return -EINVAL;
+
+ if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
+ return -EINVAL;
+
+ if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
+ return -EINVAL;
var->xres_virtual = max(var->xres_virtual, var->xres);
var->yres_virtual = max(var->yres_virtual, var->yres);
@@ -409,13 +342,11 @@ static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->transp.offset = var->transp.length = 0;
var->nonstd = 0;
-
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
-
var->sync = 0;
- var->pixclock = 0x04; /* 171521; */
+ var->pixclock = 0x04; /* 171521; */
return 0;
}
@@ -430,274 +361,284 @@ static int w100fb_set_par(struct fb_info *info)
{
struct w100fb_par *par=info->par;
- par->xres = info->var.xres;
- par->yres = info->var.yres;
+ if (par->xres != info->var.xres || par->yres != info->var.yres) {
+ par->xres = info->var.xres;
+ par->yres = info->var.yres;
+ par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
- info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
- info->fix.ypanstep = 0;
- info->fix.ywrapstep = 0;
-
- if (par->blanking_flag)
- w100fb_clear_buffer();
-
- w100fb_activate_var(info);
+ if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
+ par->extmem_active = 1;
+ info->fix.smem_len = par->mach->mem->size+1;
+ } else {
+ par->extmem_active = 0;
+ info->fix.smem_len = MEM_INT_SIZE+1;
+ }
- if (par->lcdMode == LCD_MODE_480) {
- info->fix.line_length = (480 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x200000;
- } else if (par->lcdMode == LCD_MODE_320) {
- info->fix.line_length = (320 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x60000;
- } else if (par->lcdMode == LCD_MODE_240) {
- info->fix.line_length = (240 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x60000;
- } else if (par->lcdMode == LCD_MODE_INIT || par->lcdMode == LCD_MODE_640) {
- info->fix.line_length = (640 * BITS_PER_PIXEL) / 8;
- info->fix.smem_len = 0x200000;
+ w100fb_activate_var(par);
}
-
return 0;
}
/*
- * Frame buffer operations
+ * Frame buffer operations
*/
static struct fb_ops w100fb_ops = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.fb_check_var = w100fb_check_var,
- .fb_set_par = w100fb_set_par,
+ .fb_set_par = w100fb_set_par,
.fb_setcolreg = w100fb_setcolreg,
- .fb_blank = w100fb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
+ .fb_blank = w100fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
+ .fb_cursor = soft_cursor,
};
-
-static void w100fb_clear_screen(u32 mode, long int offset)
+#ifdef CONFIG_PM
+static void w100fb_save_vidmem(struct w100fb_par *par)
{
- int i, numPix = 0;
-
- if (mode == LCD_SHARP_VGA)
- numPix = 640 * 480;
- else if (mode == LCD_SHARP_QVGA)
- numPix = 320 * 240;
-
- for (i = 0; i < numPix; i++)
- writew(0xffff, remapped_fbuf + offset + (2*i));
-}
-
+ int memsize;
-/* Need to split up the buffers to stay within the limits of kmalloc */
-#define W100_BUF_NUM 6
-static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL };
-
-static void w100fb_save_buffer(void)
-{
- int i, j, bufsize;
-
- bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
- for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] == NULL)
- gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL);
- if (gSaveImagePtr[i] == NULL) {
- w100fb_clear_buffer();
- printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i);
- break;
- }
- for (j = 0; j < bufsize/4; j++)
- *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4);
+ if (par->extmem_active) {
+ memsize=par->mach->mem->size;
+ par->saved_extmem = vmalloc(memsize);
+ if (par->saved_extmem)
+ memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
}
+ memsize=MEM_INT_SIZE;
+ par->saved_intmem = vmalloc(memsize);
+ if (par->saved_intmem && par->extmem_active)
+ memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
+ else if (par->saved_intmem)
+ memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
}
-
-static void w100fb_restore_buffer(void)
+static void w100fb_restore_vidmem(struct w100fb_par *par)
{
- int i, j, bufsize;
+ int memsize;
- bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
- for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] == NULL) {
- printk(KERN_WARNING "can't find pre-off image buffer %d\n", i);
- w100fb_clear_buffer();
- break;
- }
- for (j = 0; j < (bufsize/4); j++)
- writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4));
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
+ if (par->extmem_active && par->saved_extmem) {
+ memsize=par->mach->mem->size;
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
+ vfree(par->saved_extmem);
+ }
+ if (par->saved_intmem) {
+ memsize=MEM_INT_SIZE;
+ if (par->extmem_active)
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
+ else
+ memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
+ vfree(par->saved_intmem);
}
}
-
-static void w100fb_clear_buffer(void)
+static int w100fb_suspend(struct device *dev, pm_message_t state)
{
- int i;
- for (i = 0; i < W100_BUF_NUM; i++) {
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
- }
-}
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
+ struct w100_tg_info *tg = par->mach->tg;
+ w100fb_save_vidmem(par);
+ if(tg && tg->suspend)
+ tg->suspend(par);
+ w100_suspend(W100_SUSPEND_ALL);
+ par->blanked = 1;
-#ifdef CONFIG_PM
-static int w100fb_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- if (level == SUSPEND_POWER_DOWN) {
- struct fb_info *info = dev_get_drvdata(dev);
- struct w100fb_par *par=info->par;
-
- w100fb_save_buffer();
- lcdtg_suspend();
- w100_suspend(W100_SUSPEND_ALL);
- par->blanking_flag = 1;
- }
return 0;
}
-static int w100fb_resume(struct device *dev, u32 level)
+static int w100fb_resume(struct device *dev)
{
- if (level == RESUME_POWER_ON) {
- struct fb_info *info = dev_get_drvdata(dev);
- struct w100fb_par *par=info->par;
-
- w100_resume();
- w100fb_restore_buffer();
- lcdtg_resume();
- par->blanking_flag = 0;
- }
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
+ struct w100_tg_info *tg = par->mach->tg;
+
+ w100_hw_init(par);
+ w100fb_activate_var(par);
+ w100fb_restore_vidmem(par);
+ if(tg && tg->resume)
+ tg->resume(par);
+ par->blanked = 0;
+
return 0;
}
#else
-#define w100fb_suspend NULL
-#define w100fb_resume NULL
+#define w100fb_suspend NULL
+#define w100fb_resume NULL
#endif
int __init w100fb_probe(struct device *dev)
{
+ int err = -EIO;
struct w100fb_mach_info *inf;
- struct fb_info *info;
+ struct fb_info *info = NULL;
struct w100fb_par *par;
struct platform_device *pdev = to_platform_device(dev);
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ unsigned int chip_id;
if (!mem)
return -EINVAL;
- /* remap the areas we're going to use */
+ /* Remap the chip base address */
remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
if (remapped_base == NULL)
- return -EIO;
+ goto out;
+ /* Map the register space */
remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
- if (remapped_regs == NULL) {
- iounmap(remapped_base);
- return -EIO;
+ if (remapped_regs == NULL)
+ goto out;
+
+ /* Identify the chip */
+ printk("Found ");
+ chip_id = readl(remapped_regs + mmCHIP_ID);
+ switch(chip_id) {
+ case CHIP_ID_W100: printk("w100"); break;
+ case CHIP_ID_W3200: printk("w3200"); break;
+ case CHIP_ID_W3220: printk("w3220"); break;
+ default:
+ printk("Unknown imageon chip ID\n");
+ err = -ENODEV;
+ goto out;
}
+ printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
- remapped_fbuf = ioremap_nocache(mem->start+MEM_EXT_BASE_VALUE, REMAPPED_FB_LEN);
- if (remapped_fbuf == NULL) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- return -EIO;
- }
+ /* Remap the framebuffer */
+ remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
+ if (remapped_fbuf == NULL)
+ goto out;
info=framebuffer_alloc(sizeof(struct w100fb_par), dev);
if (!info) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
}
- info->device=dev;
par = info->par;
- current_par=info->par;
dev_set_drvdata(dev, info);
inf = dev->platform_data;
- par->phadadj = inf->phadadj;
- par->comadj = inf->comadj;
- par->fastsysclk_mode = 75;
- par->lcdMode = LCD_MODE_INIT;
- par->rotation_flag=0;
- par->blanking_flag=0;
- w100fb_ssp_send = inf->w100fb_ssp_send;
-
- w100_hw_init();
- w100_pwm_setup();
+ par->chip_id = chip_id;
+ par->mach = inf;
+ par->fastpll_mode = 0;
+ par->blanked = 0;
+
+ par->pll_table=w100_get_xtal_table(inf->xtal_freq);
+ if (!par->pll_table) {
+ printk(KERN_ERR "No matching Xtal definition found\n");
+ err = -EINVAL;
+ goto out;
+ }
info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
if (!info->pseudo_palette) {
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
}
info->fbops = &w100fb_ops;
info->flags = FBINFO_DEFAULT;
info->node = -1;
- info->screen_base = remapped_fbuf;
+ info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
info->screen_size = REMAPPED_FB_LEN;
- info->var.xres = 640;
+ strcpy(info->fix.id, "w100fb");
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+ info->fix.smem_start = mem->start+W100_FB_BASE;
+ info->fix.mmio_start = mem->start+W100_REG_BASE;
+ info->fix.mmio_len = W100_REG_LEN;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ par->mode = &inf->modelist[0];
+ if(inf->init_mode & INIT_MODE_ROTATED) {
+ info->var.xres = par->mode->yres;
+ info->var.yres = par->mode->xres;
+ }
+ else {
+ info->var.xres = par->mode->xres;
+ info->var.yres = par->mode->yres;
+ }
+
+ if(inf->init_mode &= INIT_MODE_FLIPPED)
+ par->flip = 1;
+ else
+ par->flip = 0;
+
info->var.xres_virtual = info->var.xres;
- info->var.yres = 480;
info->var.yres_virtual = info->var.yres;
- info->var.pixclock = 0x04; /* 171521; */
+ info->var.pixclock = 0x04; /* 171521; */
info->var.sync = 0;
info->var.grayscale = 0;
info->var.xoffset = info->var.yoffset = 0;
info->var.accel_flags = 0;
info->var.activate = FB_ACTIVATE_NOW;
- strcpy(info->fix.id, "w100fb");
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.type_aux = 0;
- info->fix.accel = FB_ACCEL_NONE;
- info->fix.smem_start = mem->start+MEM_EXT_BASE_VALUE;
- info->fix.mmio_start = mem->start+W100_REG_BASE;
- info->fix.mmio_len = W100_REG_LEN;
+ w100_hw_init(par);
+
+ if (w100fb_check_var(&info->var, info) < 0) {
+ err = -EINVAL;
+ goto out;
+ }
- w100fb_check_var(&info->var, info);
w100fb_set_par(info);
if (register_framebuffer(info) < 0) {
- kfree(info->pseudo_palette);
- iounmap(remapped_base);
- iounmap(remapped_regs);
- iounmap(remapped_fbuf);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
- device_create_file(dev, &dev_attr_fastsysclk);
+ device_create_file(dev, &dev_attr_fastpllclk);
device_create_file(dev, &dev_attr_reg_read);
device_create_file(dev, &dev_attr_reg_write);
- device_create_file(dev, &dev_attr_rotation);
+ device_create_file(dev, &dev_attr_flip);
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
return 0;
+out:
+ fb_dealloc_cmap(&info->cmap);
+ kfree(info->pseudo_palette);
+ if (remapped_fbuf != NULL)
+ iounmap(remapped_fbuf);
+ if (remapped_regs != NULL)
+ iounmap(remapped_regs);
+ if (remapped_base != NULL)
+ iounmap(remapped_base);
+ if (info)
+ framebuffer_release(info);
+ return err;
}
static int w100fb_remove(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
+ struct w100fb_par *par=info->par;
- device_remove_file(dev, &dev_attr_fastsysclk);
+ device_remove_file(dev, &dev_attr_fastpllclk);
device_remove_file(dev, &dev_attr_reg_read);
device_remove_file(dev, &dev_attr_reg_write);
- device_remove_file(dev, &dev_attr_rotation);
+ device_remove_file(dev, &dev_attr_flip);
unregister_framebuffer(info);
- w100fb_clear_buffer();
+ vfree(par->saved_intmem);
+ vfree(par->saved_extmem);
kfree(info->pseudo_palette);
+ fb_dealloc_cmap(&info->cmap);
iounmap(remapped_base);
iounmap(remapped_regs);
@@ -721,10 +662,54 @@ static void w100_soft_reset(void)
udelay(100);
}
+static void w100_update_disable(void)
+{
+ union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+ /* Prevent display updates */
+ disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+ disp_db_buf_wr_cntl.f.update_db_buf = 0;
+ disp_db_buf_wr_cntl.f.en_db_buf = 0;
+ writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+static void w100_update_enable(void)
+{
+ union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+ /* Enable display updates */
+ disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+ disp_db_buf_wr_cntl.f.update_db_buf = 1;
+ disp_db_buf_wr_cntl.f.en_db_buf = 1;
+ writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+unsigned long w100fb_gpio_read(int port)
+{
+ unsigned long value;
+
+ if (port==W100_GPIO_PORT_A)
+ value = readl(remapped_regs + mmGPIO_DATA);
+ else
+ value = readl(remapped_regs + mmGPIO_DATA2);
+
+ return value;
+}
+
+void w100fb_gpio_write(int port, unsigned long value)
+{
+ if (port==W100_GPIO_PORT_A)
+ value = writel(value, remapped_regs + mmGPIO_DATA);
+ else
+ value = writel(value, remapped_regs + mmGPIO_DATA2);
+}
+EXPORT_SYMBOL(w100fb_gpio_read);
+EXPORT_SYMBOL(w100fb_gpio_write);
+
/*
* Initialization of critical w100 hardware
*/
-static void w100_hw_init(void)
+static void w100_hw_init(struct w100fb_par *par)
{
u32 temp32;
union cif_cntl_u cif_cntl;
@@ -735,8 +720,8 @@ static void w100_hw_init(void)
union cpu_defaults_u cpu_default;
union cif_write_dbg_u cif_write_dbg;
union wrap_start_dir_u wrap_start_dir;
- union mc_ext_mem_location_u mc_ext_mem_loc;
union cif_io_u cif_io;
+ struct w100_gpio_regs *gpio = par->mach->gpio;
w100_soft_reset();
@@ -791,19 +776,6 @@ static void w100_hw_init(void)
cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
- /* This location is relative to internal w100 addresses */
- writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
-
- mc_ext_mem_loc.val = defMC_EXT_MEM_LOCATION;
- mc_ext_mem_loc.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
- mc_ext_mem_loc.f.mc_ext_mem_top = MEM_EXT_TOP_VALUE >> 8;
- writel((u32) (mc_ext_mem_loc.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
-
- if ((current_par->lcdMode == LCD_MODE_240) || (current_par->lcdMode == LCD_MODE_320))
- w100_InitExtMem(LCD_SHARP_QVGA);
- else
- w100_InitExtMem(LCD_SHARP_VGA);
-
wrap_start_dir.val = defWRAP_START_DIR;
wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
@@ -813,21 +785,24 @@ static void w100_hw_init(void)
writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
-}
+ /* Set the hardware to 565 colour */
+ temp32 = readl(remapped_regs + mmDISP_DEBUG2);
+ temp32 &= 0xff7fffff;
+ temp32 |= 0x00800000;
+ writel(temp32, remapped_regs + mmDISP_DEBUG2);
-/*
- * Types
- */
+ /* Initialise the GPIO lines */
+ if (gpio) {
+ writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
+ writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
+ writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
+ writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
+ writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
+ writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
+ }
+}
-struct pll_parm {
- u16 freq; /* desired Fout for PLL */
- u8 M;
- u8 N_int;
- u8 N_fac;
- u8 tfgoal;
- u8 lock_time;
-};
struct power_state {
union clk_pin_cntl_u clk_pin_cntl;
@@ -835,317 +810,275 @@ struct power_state {
union pll_cntl_u pll_cntl;
union sclk_cntl_u sclk_cntl;
union pclk_cntl_u pclk_cntl;
- union clk_test_cntl_u clk_test_cntl;
union pwrmgt_cntl_u pwrmgt_cntl;
- u32 freq; /* Fout for PLL calibration */
- u8 tf100; /* for pll calibration */
- u8 tf80; /* for pll calibration */
- u8 tf20; /* for pll calibration */
- u8 M; /* for pll calibration */
- u8 N_int; /* for pll calibration */
- u8 N_fac; /* for pll calibration */
- u8 lock_time; /* for pll calibration */
- u8 tfgoal; /* for pll calibration */
- u8 auto_mode; /* hardware auto switch? */
- u8 pwm_mode; /* 0 fast, 1 normal/slow */
- u16 fast_sclk; /* fast clk freq */
- u16 norm_sclk; /* slow clk freq */
+ int auto_mode; /* system clock auto changing? */
};
-/*
- * Global state variables
- */
-
static struct power_state w100_pwr_state;
-/* This table is specific for 12.5MHz ref crystal. */
-static struct pll_parm gPLLTable[] = {
- /*freq M N_int N_fac tfgoal lock_time */
- { 50, 0, 1, 0, 0xE0, 56}, /* 50.00 MHz */
- { 75, 0, 5, 0, 0xDE, 37}, /* 75.00 MHz */
- {100, 0, 7, 0, 0xE0, 28}, /* 100.00 MHz */
- {125, 0, 9, 0, 0xE0, 22}, /* 125.00 MHz */
- {150, 0, 11, 0, 0xE0, 17}, /* 150.00 MHz */
- { 0, 0, 0, 0, 0, 0} /* Terminator */
+/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
+
+/* 12.5MHz Crystal PLL Table */
+static struct w100_pll_info xtal_12500000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
+ { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
+ {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
+ {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
+ {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
+ { 0, 0, 0, 0, 0, 0}, /* Terminator */
+};
+
+/* 14.318MHz Crystal PLL Table */
+static struct w100_pll_info xtal_14318000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
+ { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
+ { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
+ { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
+ {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
+ { 0, 0, 0, 0, 0, 0},
+};
+
+/* 16MHz Crystal PLL Table */
+static struct w100_pll_info xtal_16000000[] = {
+ /*freq M N_int N_fac tfgoal lock_time */
+ { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
+ { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
+ { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
+ { 0, 0, 0, 0, 0, 0},
};
+static struct pll_entries {
+ int xtal_freq;
+ struct w100_pll_info *pll_table;
+} w100_pll_tables[] = {
+ { 12500000, &xtal_12500000[0] },
+ { 14318000, &xtal_14318000[0] },
+ { 16000000, &xtal_16000000[0] },
+ { 0 },
+};
-static u8 w100_pll_get_testcount(u8 testclk_sel)
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
{
+ struct pll_entries *pll_entry = w100_pll_tables;
+
+ do {
+ if (freq == pll_entry->xtal_freq)
+ return pll_entry->pll_table;
+ pll_entry++;
+ } while (pll_entry->xtal_freq);
+ return 0;
+}
+
+
+static unsigned int w100_get_testcount(unsigned int testclk_sel)
+{
+ union clk_test_cntl_u clk_test_cntl;
+
udelay(5);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- w100_pwr_state.clk_test_cntl.f.testclk_sel = testclk_sel;
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x1; /*reset test count */
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Select the test clock source and reset */
+ clk_test_cntl.f.start_check_freq = 0x0;
+ clk_test_cntl.f.testclk_sel = testclk_sel;
+ clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+ clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x1;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Run clock test */
+ clk_test_cntl.f.start_check_freq = 0x1;
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Give the test time to complete */
udelay(20);
- w100_pwr_state.clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+ /* Return the result */
+ clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
+ clk_test_cntl.f.start_check_freq = 0x0;
+ writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
- return w100_pwr_state.clk_test_cntl.f.test_count;
+ return clk_test_cntl.f.test_count;
}
-static u8 w100_pll_adjust(void)
+static int w100_pll_adjust(struct w100_pll_info *pll)
{
+ unsigned int tf80;
+ unsigned int tf20;
+
+ /* Initial Settings */
+ w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
+ w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
+ w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
+ w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
+ w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
+ w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
+ w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
+
+ /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
+ * therefore, commented out the following lines
+ * tf80 meant tf100
+ */
do {
- /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
- * therefore, commented out the following lines
- * tf80 meant tf100
- * set VCO input = 0.8 * VDD
- */
+ /* set VCO input = 0.8 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.tf80 = w100_pll_get_testcount(0x1); /* PLLCLK */
- if (w100_pwr_state.tf80 >= (w100_pwr_state.tfgoal)) {
+ tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
+ if (tf80 >= (pll->tfgoal)) {
/* set VCO input = 0.2 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.tf20 = w100_pll_get_testcount(0x1); /* PLLCLK */
- if (w100_pwr_state.tf20 <= (w100_pwr_state.tfgoal))
- return 1; // Success
+ tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
+ if (tf20 <= (pll->tfgoal))
+ return 1; /* Success */
if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
- ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
- (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
+ ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
+ (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
/* slow VCO config */
w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
- writel((u32) (w100_pwr_state.pll_cntl.val),
- remapped_regs + mmPLL_CNTL);
continue;
}
}
if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- continue;
- }
- if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
+ } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- continue;
+ } else {
+ return 0; /* Error */
}
- return 0; // error
} while(1);
}
/*
* w100_pll_calibration
- * freq = target frequency of the PLL
- * (note: crystal = 14.3MHz)
*/
-static u8 w100_pll_calibration(u32 freq)
+static int w100_pll_calibration(struct w100_pll_info *pll)
{
- u8 status;
-
- /* initial setting */
- w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
- w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
- w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
- w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
- w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
- w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
- w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
- writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+ int status;
- /* check for (tf80 >= tfgoal) && (tf20 =< tfgoal) */
- if ((w100_pwr_state.tf80 < w100_pwr_state.tfgoal) || (w100_pwr_state.tf20 > w100_pwr_state.tfgoal)) {
- status=w100_pll_adjust();
- }
- /* PLL Reset And Lock */
+ status = w100_pll_adjust(pll);
+ /* PLL Reset And Lock */
/* set VCO input = 0.5 * VDD */
w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* reset time */
- udelay(1);
+ udelay(1); /* reset time */
/* enable charge pump */
- w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
+ w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* set VCO input = Hi-Z */
- /* disable DAC */
+ /* set VCO input = Hi-Z, disable DAC */
w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- /* lock time */
- udelay(400); /* delay 400 us */
+ udelay(400); /* lock time */
/* PLL locked */
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x1; /* PLL clock */
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
- w100_pwr_state.tf100 = w100_pll_get_testcount(0x1); /* PLLCLK */
-
return status;
}
-static u8 w100_pll_set_clk(void)
+static int w100_pll_set_clk(struct w100_pll_info *pll)
{
- u8 status;
+ int status;
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
+ if (w100_pwr_state.auto_mode == 1) /* auto mode */
{
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
}
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal clock */
+ /* Set system clock source to XTAL whilst adjusting the PLL! */
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = w100_pwr_state.M;
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = w100_pwr_state.N_int;
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = w100_pwr_state.N_fac;
- w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = w100_pwr_state.lock_time;
+ w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
+ w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- status = w100_pll_calibration (w100_pwr_state.freq);
+ status = w100_pll_calibration(pll);
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
+ if (w100_pwr_state.auto_mode == 1) /* auto mode */
{
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
}
return status;
}
-
-/* assume reference crystal clk is 12.5MHz,
- * and that doubling is not enabled.
- *
- * Freq = 12 == 12.5MHz.
- */
-static u16 w100_set_slowsysclk(u16 freq)
+/* freq = target frequency of the PLL */
+static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
{
- if (w100_pwr_state.norm_sclk == freq)
- return freq;
-
- if (w100_pwr_state.auto_mode == 1) /* auto mode */
- return 0;
-
- if (freq == 12) {
- w100_pwr_state.norm_sclk = freq;
- w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal src */
-
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
- w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x1;
- writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
-
- w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x1;
- w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;
- writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- w100_pwr_state.pwm_mode = 1; /* normal mode */
- return freq;
- } else
- return 0;
-}
-
+ struct w100_pll_info *pll = par->pll_table;
-static u16 w100_set_fastsysclk(u16 freq)
-{
- u16 pll_freq;
- int i;
-
- while(1) {
- pll_freq = (u16) (freq * (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast + 1));
- i = 0;
- do {
- if (pll_freq == gPLLTable[i].freq) {
- w100_pwr_state.freq = gPLLTable[i].freq * 1000000;
- w100_pwr_state.M = gPLLTable[i].M;
- w100_pwr_state.N_int = gPLLTable[i].N_int;
- w100_pwr_state.N_fac = gPLLTable[i].N_fac;
- w100_pwr_state.tfgoal = gPLLTable[i].tfgoal;
- w100_pwr_state.lock_time = gPLLTable[i].lock_time;
- w100_pwr_state.tf20 = 0xff; /* set highest */
- w100_pwr_state.tf80 = 0x00; /* set lowest */
-
- w100_pll_set_clk();
- w100_pwr_state.pwm_mode = 0; /* fast mode */
- w100_pwr_state.fast_sclk = freq;
- return freq;
- }
- i++;
- } while(gPLLTable[i].freq);
-
- if (w100_pwr_state.auto_mode == 1)
- break;
-
- if (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast == 0)
- break;
-
- w100_pwr_state.sclk_cntl.f.sclk_post_div_fast -= 1;
- writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- }
+ do {
+ if (freq == pll->freq) {
+ return w100_pll_set_clk(pll);
+ }
+ pll++;
+ } while(pll->freq);
return 0;
}
-
/* Set up an initial state. Some values/fields set
here will be overwritten. */
-static void w100_pwm_setup(void)
+static void w100_pwm_setup(struct w100fb_par *par)
{
w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
- w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = 0x0; /* no freq doubling */
+ w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
- w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* Crystal Clk */
- w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
- w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
- w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
- w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
+ w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x0; /* Crystal Clk */
- w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
- w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
+ w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
+ w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
+ w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
- w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
- w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
+ w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
+ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
@@ -1154,7 +1087,7 @@ static void w100_pwm_setup(void)
w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
- w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
+ w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
@@ -1164,220 +1097,275 @@ static void w100_pwm_setup(void)
w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
- w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
+ w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
- w100_pwr_state.clk_test_cntl.f.testclk_sel = 0x1; /* PLLCLK (for testing) */
- w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0;
- w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0;
- writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
- w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
- w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
- w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
+ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
- w100_pwr_state.auto_mode = 0; /* manual mode */
- w100_pwr_state.pwm_mode = 1; /* normal mode (0, 1, 2) */
- w100_pwr_state.freq = 50000000; /* 50 MHz */
- w100_pwr_state.M = 3; /* M = 4 */
- w100_pwr_state.N_int = 6; /* N = 7.0 */
- w100_pwr_state.N_fac = 0;
- w100_pwr_state.tfgoal = 0xE0;
- w100_pwr_state.lock_time = 56;
- w100_pwr_state.tf20 = 0xff; /* set highest */
- w100_pwr_state.tf80 = 0x00; /* set lowest */
- w100_pwr_state.tf100 = 0x00; /* set lowest */
- w100_pwr_state.fast_sclk = 50; /* 50.0 MHz */
- w100_pwr_state.norm_sclk = 12; /* 12.5 MHz */
+ w100_pwr_state.auto_mode = 0; /* manual mode */
}
-static void w100_init_sharp_lcd(u32 mode)
+/*
+ * Setup the w100 clocks for the specified mode
+ */
+static void w100_init_clocks(struct w100fb_par *par)
{
- u32 temp32;
- union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+ struct w100_mode *mode = par->mode;
- /* Prevent display updates */
- disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
- disp_db_buf_wr_cntl.f.update_db_buf = 0;
- disp_db_buf_wr_cntl.f.en_db_buf = 0;
- writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+ if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
+ w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
- switch(mode) {
- case LCD_SHARP_QVGA:
- w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */
- /* not use PLL */
-
- writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- writel(0x85FF8000, remapped_regs + mmMC_FB_LOCATION);
- writel(0x00000003, remapped_regs + mmLCD_FORMAT);
- writel(0x00CF1C06, remapped_regs + mmGRAPHIC_CTRL);
- writel(0x01410145, remapped_regs + mmCRTC_TOTAL);
- writel(0x01170027, remapped_regs + mmACTIVE_H_DISP);
- writel(0x01410001, remapped_regs + mmACTIVE_V_DISP);
- writel(0x01170027, remapped_regs + mmGRAPHIC_H_DISP);
- writel(0x01410001, remapped_regs + mmGRAPHIC_V_DISP);
- writel(0x81170027, remapped_regs + mmCRTC_SS);
- writel(0xA0140000, remapped_regs + mmCRTC_LS);
- writel(0x00400008, remapped_regs + mmCRTC_REV);
- writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
- writel(0xC0140014, remapped_regs + mmCRTC_GS);
- writel(0x00010141, remapped_regs + mmCRTC_VPOS_GS);
- writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
- writel(0x80100110, remapped_regs + mmCRTC_GOE);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
- writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
- writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
- writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
- writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
- writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
- writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
- writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
- writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
- writel(0x000001e0, remapped_regs + mmGRAPHIC_PITCH);
- writel(0x000000bf, remapped_regs + mmGPIO_DATA);
- writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
- writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
- writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
- break;
- case LCD_SHARP_VGA:
- w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */
- w100_set_fastsysclk(current_par->fastsysclk_mode); /* use PLL -- 75.0MHz */
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
- w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x2;
- writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
- writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION);
- writel(0x9FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
- writel(0x00000003, remapped_regs + mmLCD_FORMAT);
- writel(0x00DE1D66, remapped_regs + mmGRAPHIC_CTRL);
-
- writel(0x0283028B, remapped_regs + mmCRTC_TOTAL);
- writel(0x02360056, remapped_regs + mmACTIVE_H_DISP);
- writel(0x02830003, remapped_regs + mmACTIVE_V_DISP);
- writel(0x02360056, remapped_regs + mmGRAPHIC_H_DISP);
- writel(0x02830003, remapped_regs + mmGRAPHIC_V_DISP);
- writel(0x82360056, remapped_regs + mmCRTC_SS);
- writel(0xA0280000, remapped_regs + mmCRTC_LS);
- writel(0x00400008, remapped_regs + mmCRTC_REV);
- writel(0xA0000000, remapped_regs + mmCRTC_DCLK);
- writel(0x80280028, remapped_regs + mmCRTC_GS);
- writel(0x02830002, remapped_regs + mmCRTC_VPOS_GS);
- writel(0x8015010F, remapped_regs + mmCRTC_GCLK);
- writel(0x80100110, remapped_regs + mmCRTC_GOE);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME);
- writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
- writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1);
- writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2);
- writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1);
- writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2);
- writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
- writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
- writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3);
- writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET);
- writel(0x000003C0, remapped_regs + mmGRAPHIC_PITCH);
- writel(0x000000bf, remapped_regs + mmGPIO_DATA);
- writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2);
- writel(0x00000000, remapped_regs + mmGPIO_CNTL1);
- writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE);
- break;
- default:
- break;
- }
+ w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
+ w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
+ writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+}
+
+static void w100_init_lcd(struct w100fb_par *par)
+{
+ u32 temp32;
+ struct w100_mode *mode = par->mode;
+ struct w100_gen_regs *regs = par->mach->regs;
+ union active_h_disp_u active_h_disp;
+ union active_v_disp_u active_v_disp;
+ union graphic_h_disp_u graphic_h_disp;
+ union graphic_v_disp_u graphic_v_disp;
+ union crtc_total_u crtc_total;
+
+ /* w3200 doesnt like undefined bits being set so zero register values first */
+
+ active_h_disp.val = 0;
+ active_h_disp.f.active_h_start=mode->left_margin;
+ active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
+ writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
+
+ active_v_disp.val = 0;
+ active_v_disp.f.active_v_start=mode->upper_margin;
+ active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
+ writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
+
+ graphic_h_disp.val = 0;
+ graphic_h_disp.f.graphic_h_start=mode->left_margin;
+ graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
+ writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
+
+ graphic_v_disp.val = 0;
+ graphic_v_disp.f.graphic_v_start=mode->upper_margin;
+ graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
+ writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
+
+ crtc_total.val = 0;
+ crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
+ crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
+ writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
+
+ writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
+ writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
+ writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
+ writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
+ writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
+ writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
+ writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
+ writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
+ writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
+
+ writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
+ writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
+ writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
+ writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
+ writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
+ writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
+
+ writel(0x00000000, remapped_regs + mmCRTC_FRAME);
+ writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
+ writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
+ writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
/* Hack for overlay in ext memory */
temp32 = readl(remapped_regs + mmDISP_DEBUG2);
temp32 |= 0xc0000000;
writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
- /* Re-enable display updates */
- disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
- disp_db_buf_wr_cntl.f.update_db_buf = 1;
- disp_db_buf_wr_cntl.f.en_db_buf = 1;
- writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
}
-static void w100_set_vga_rotation_regs(u16 divider, unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_setup_memory(struct w100fb_par *par)
{
- w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1;
- w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
- writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+ union mc_ext_mem_location_u extmem_location;
+ union mc_fb_location_u intmem_location;
+ struct w100_mem_info *mem = par->mach->mem;
+ struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
- writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
- writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
- writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+ if (!par->extmem_active) {
+ w100_suspend(W100_SUSPEND_EXTMEM);
- /* Re-enable display updates */
- writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
-}
+ /* Map Internal Memory at FB Base */
+ intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
+ intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
+ writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
+ /* Unmap External Memory - value is *probably* irrelevant but may have meaning
+ to acceleration libraries */
+ extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
+ extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
+ writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+ } else {
+ /* Map Internal Memory to its default location */
+ intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
+ intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
+ writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
-static void w100_init_vga_rotation(u16 deg)
-{
- switch(deg) {
- case 0:
- w100_set_vga_rotation_regs(0x02, 0x00DE1D66, 0x00800000, 0x000003c0);
- break;
- case 90:
- w100_set_vga_rotation_regs(0x06, 0x00DE1D0e, 0x00895b00, 0x00000500);
- break;
- case 180:
- w100_set_vga_rotation_regs(0x02, 0x00DE1D7e, 0x00895ffc, 0x000003c0);
- break;
- case 270:
- w100_set_vga_rotation_regs(0x06, 0x00DE1D16, 0x008004fc, 0x00000500);
- break;
- default:
- /* not-support */
- break;
+ /* Map External Memory at FB Base */
+ extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
+ extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
+ writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+
+ writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
+ writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
+ writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
+ udelay(100);
+ writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
+ writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
+ if (bm_mem) {
+ writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
+ writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
+ writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
+ writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
+ writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
+ writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
+ writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
+ }
}
}
-
-static void w100_set_qvga_rotation_regs(unsigned long ctrl, unsigned long offset, unsigned long pitch)
+static void w100_set_dispregs(struct w100fb_par *par)
{
- writel(ctrl, remapped_regs + mmGRAPHIC_CTRL);
- writel(offset, remapped_regs + mmGRAPHIC_OFFSET);
- writel(pitch, remapped_regs + mmGRAPHIC_PITCH);
+ unsigned long rot=0, divider, offset=0;
+ union graphic_ctrl_u graphic_ctrl;
+
+ /* See if the mode has been rotated */
+ if (par->xres == par->mode->xres) {
+ if (par->flip) {
+ rot=3; /* 180 degree */
+ offset=(par->xres * par->yres) - 1;
+ } /* else 0 degree */
+ divider = par->mode->pixclk_divider;
+ } else {
+ if (par->flip) {
+ rot=2; /* 270 degree */
+ offset=par->xres - 1;
+ } else {
+ rot=1; /* 90 degree */
+ offset=par->xres * (par->yres - 1);
+ }
+ divider = par->mode->pixclk_divider_rotated;
+ }
+
+ graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
+ switch (par->chip_id) {
+ case CHIP_ID_W100:
+ graphic_ctrl.f_w100.color_depth=6;
+ graphic_ctrl.f_w100.en_crtc=1;
+ graphic_ctrl.f_w100.en_graphic_req=1;
+ graphic_ctrl.f_w100.en_graphic_crtc=1;
+ graphic_ctrl.f_w100.lcd_pclk_on=1;
+ graphic_ctrl.f_w100.lcd_sclk_on=1;
+ graphic_ctrl.f_w100.low_power_on=0;
+ graphic_ctrl.f_w100.req_freq=0;
+ graphic_ctrl.f_w100.portrait_mode=rot;
+
+ /* Zaurus needs this */
+ switch(par->xres) {
+ case 240:
+ case 320:
+ default:
+ graphic_ctrl.f_w100.total_req_graphic=0xa0;
+ break;
+ case 480:
+ case 640:
+ switch(rot) {
+ case 0: /* 0 */
+ case 3: /* 180 */
+ graphic_ctrl.f_w100.low_power_on=1;
+ graphic_ctrl.f_w100.req_freq=5;
+ break;
+ case 1: /* 90 */
+ case 2: /* 270 */
+ graphic_ctrl.f_w100.req_freq=4;
+ break;
+ default:
+ break;
+ }
+ graphic_ctrl.f_w100.total_req_graphic=0xf0;
+ break;
+ }
+ break;
+ case CHIP_ID_W3200:
+ case CHIP_ID_W3220:
+ graphic_ctrl.f_w32xx.color_depth=6;
+ graphic_ctrl.f_w32xx.en_crtc=1;
+ graphic_ctrl.f_w32xx.en_graphic_req=1;
+ graphic_ctrl.f_w32xx.en_graphic_crtc=1;
+ graphic_ctrl.f_w32xx.lcd_pclk_on=1;
+ graphic_ctrl.f_w32xx.lcd_sclk_on=1;
+ graphic_ctrl.f_w32xx.low_power_on=0;
+ graphic_ctrl.f_w32xx.req_freq=0;
+ graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
+ graphic_ctrl.f_w32xx.portrait_mode=rot;
+ break;
+ }
+
+ /* Set the pixel clock source and divider */
+ w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
+ w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
+ writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
- /* Re-enable display updates */
- writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL);
+ writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
+ writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
+ writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
}
-static void w100_init_qvga_rotation(u16 deg)
+/*
+ * Work out how long the sync pulse lasts
+ * Value is 1/(time in seconds)
+ */
+static void calc_hsync(struct w100fb_par *par)
{
- switch(deg) {
- case 0:
- w100_set_qvga_rotation_regs(0x00d41c06, 0x00800000, 0x000001e0);
- break;
- case 90:
- w100_set_qvga_rotation_regs(0x00d41c0E, 0x00825580, 0x00000280);
- break;
- case 180:
- w100_set_qvga_rotation_regs(0x00d41c1e, 0x008257fc, 0x000001e0);
- break;
- case 270:
- w100_set_qvga_rotation_regs(0x00d41c16, 0x0080027c, 0x00000280);
- break;
- default:
- /* not-support */
- break;
- }
-}
+ unsigned long hsync;
+ struct w100_mode *mode = par->mode;
+ union crtc_ss_u crtc_ss;
+
+ if (mode->pixclk_src == CLK_SRC_XTAL)
+ hsync=par->mach->xtal_freq;
+ else
+ hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
+ hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
+
+ crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
+ if (crtc_ss.val)
+ par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
+ else
+ par->hsync_len = 0;
+}
static void w100_suspend(u32 mode)
{
@@ -1387,30 +1375,28 @@ static void w100_suspend(u32 mode)
writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
- val &= ~(0x00100000); /* bit20=0 */
- val |= 0xFF000000; /* bit31:24=0xff */
+ val &= ~(0x00100000); /* bit20=0 */
+ val |= 0xFF000000; /* bit31:24=0xff */
writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val &= ~(0x00040000); /* bit18=0 */
- val |= 0x00080000; /* bit19=1 */
+ val &= ~(0x00040000); /* bit18=0 */
+ val |= 0x00080000; /* bit19=1 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
- udelay(1); /* wait 1us */
+ udelay(1); /* wait 1us */
if (mode == W100_SUSPEND_EXTMEM) {
-
/* CKE: Tri-State */
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val |= 0x40000000; /* bit30=1 */
+ val |= 0x40000000; /* bit30=1 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
/* CLK: Stop */
val = readl(remapped_regs + mmMEM_EXT_CNTL);
- val &= ~(0x00000001); /* bit0=0 */
+ val &= ~(0x00000001); /* bit0=0 */
writel(val, remapped_regs + mmMEM_EXT_CNTL);
} else {
-
writel(0x00000000, remapped_regs + mmSCLK_CNTL);
writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
@@ -1418,43 +1404,16 @@ static void w100_suspend(u32 mode)
udelay(5);
val = readl(remapped_regs + mmPLL_CNTL);
- val |= 0x00000004; /* bit2=1 */
+ val |= 0x00000004; /* bit2=1 */
writel(val, remapped_regs + mmPLL_CNTL);
writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
}
}
-
-static void w100_resume(void)
-{
- u32 temp32;
-
- w100_hw_init();
- w100_pwm_setup();
-
- temp32 = readl(remapped_regs + mmDISP_DEBUG2);
- temp32 &= 0xff7fffff;
- temp32 |= 0x00800000;
- writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
- if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
- w100_init_sharp_lcd(LCD_SHARP_VGA);
- if (current_par->lcdMode == LCD_MODE_640) {
- w100_init_vga_rotation(current_par->rotation_flag ? 270 : 90);
- }
- } else {
- w100_init_sharp_lcd(LCD_SHARP_QVGA);
- if (current_par->lcdMode == LCD_MODE_320) {
- w100_init_qvga_rotation(current_par->rotation_flag ? 270 : 90);
- }
- }
-}
-
-
static void w100_vsync(void)
{
u32 tmp;
- int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
+ int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
tmp = readl(remapped_regs + mmACTIVE_V_DISP);
@@ -1490,363 +1449,6 @@ static void w100_vsync(void)
writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
}
-
-static void w100_InitExtMem(u32 mode)
-{
- switch(mode) {
- case LCD_SHARP_QVGA:
- /* QVGA doesn't use external memory
- nothing to do, really. */
- break;
- case LCD_SHARP_VGA:
- writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
- writel(0x00040003, remapped_regs + mmMEM_EXT_CNTL);
- writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x00650021, remapped_regs + mmMEM_SDRAM_MODE_REG);
- udelay(100);
- writel(0x10002a4a, remapped_regs + mmMEM_EXT_TIMING_CNTL);
- writel(0x7ff87012, remapped_regs + mmMEM_IO_CNTL);
- break;
- default:
- break;
- }
-}
-
-
-#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
-
-#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 Powewr 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 Powewr 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 PICTRL_POWER_ACTIVE (0)
-
-#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 PHAD_QVGA_DEFAULT_VAL (9)
-#define COMADJ_DEFAULT (125)
-
-static void lcdtg_ssp_send(u8 adrs, u8 data)
-{
- w100fb_ssp_send(adrs,data);
-}
-
-/*
- * 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(u8 data)
-{
- lcdtg_ssp_send(POWERREG0_ADRS, data);
- udelay(10);
-}
-
-static void lcdtg_i2c_send_bit(u8 data)
-{
- lcdtg_ssp_i2c_send(data);
- lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(data);
-}
-
-static void lcdtg_i2c_send_start(u8 base)
-{
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(base);
-}
-
-static void lcdtg_i2c_send_stop(u8 base)
-{
- lcdtg_ssp_i2c_send(base);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);
- lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);
-}
-
-static void lcdtg_i2c_send_byte(u8 base, u8 data)
-{
- int i;
- for (i = 0; i < 8; i++) {
- if (data & 0x80)
- lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);
- else
- lcdtg_i2c_send_bit(base);
- data <<= 1;
- }
-}
-
-static void lcdtg_i2c_wait_ack(u8 base)
-{
- lcdtg_i2c_send_bit(base);
-}
-
-static void lcdtg_set_common_voltage(u8 base_data, u8 data)
-{
- /* Set Common Voltage to M62332FP via I2C */
- lcdtg_i2c_send_start(base_data);
- lcdtg_i2c_send_byte(base_data, 0x9c);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_byte(base_data, 0x00);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_byte(base_data, data);
- lcdtg_i2c_wait_ack(base_data);
- lcdtg_i2c_send_stop(base_data);
-}
-
-static struct lcdtg_register_setting {
- u8 adrs;
- u8 data;
- u32 wait;
-} lcdtg_power_on_table[] = {
-
- /* Initialize Internal Logic & Port */
- { PICTRL_ADRS,
- PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE |
- PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF,
- 0 },
-
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | POWER0_COM_OFF |
- POWER0_VCC5_OFF,
- 0 },
-
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF,
- 0 },
-
- /* VDD(+8V),SVSS(-4V) ON */
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON /* VDD ON */,
- 3000 },
-
- /* DAC ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_OFF | POWER0_VCC5_OFF,
- 0 },
-
- /* INIB = H, INI = L */
- { PICTRL_ADRS,
- /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
- PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF,
- 0 },
-
- /* Set Common Voltage */
- { 0xfe, 0, 0 },
-
- /* VCC5 ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_OFF | POWER0_VCC5_ON /* VCC5 ON */,
- 0 },
-
- /* GVSS(-8V) ON */
- { POWERREG1_ADRS,
- POWER1_VW_OFF | POWER1_GVSS_ON /* GVSS ON */ |
- POWER1_VDD_ON /* VDD ON */,
- 2000 },
-
- /* COM SIGNAL ON (PICTL[3] = L) */
- { PICTRL_ADRS,
- PICTRL_INIT_STATE,
- 0 },
-
- /* COM ON */
- { POWERREG0_ADRS,
- POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ |
- POWER0_COM_ON /* COM ON */ | POWER0_VCC5_ON /* VCC5_ON */,
- 0 },
-
- /* VW ON */
- { POWERREG1_ADRS,
- POWER1_VW_ON /* VW ON */ | POWER1_GVSS_ON /* GVSS ON */ |
- POWER1_VDD_ON /* VDD ON */,
- 0 /* Wait 100ms */ },
-
- /* Signals output enable */
- { PICTRL_ADRS,
- 0 /* Signals output enable */,
- 0 },
-
- { PHACTRL_ADRS,
- PHACTRL_PHASE_MANUAL,
- 0 },
-
- /* Initialize for Input Signals from ATI */
- { POLCTRL_ADRS,
- POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | POLCTRL_DATA_POL_RISE |
- POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H,
- 1000 /*100000*/ /* Wait 100ms */ },
-
- /* end mark */
- { 0xff, 0, 0 }
-};
-
-static void lcdtg_resume(void)
-{
- if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) {
- lcdtg_hw_init(LCD_SHARP_VGA);
- } else {
- lcdtg_hw_init(LCD_SHARP_QVGA);
- }
-}
-
-static void lcdtg_suspend(void)
-{
- int i;
-
- for (i = 0; i < (current_par->xres * current_par->yres); i++) {
- writew(0xffff, remapped_fbuf + (2*i));
- }
-
- /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
- mdelay(34);
-
- /* (1)VW OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
-
- /* (2)COM OFF */
- lcdtg_ssp_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
-
- /* (3)Set Common Voltage Bias 0V */
- lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);
-
- /* (4)GVSS OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
-
- /* (5)VCC5 OFF */
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
- /* (6)Set PDWN, INIOFF, DACOFF */
- lcdtg_ssp_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
- PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
-
- /* (7)DAC OFF */
- lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
-
- /* (8)VDD OFF */
- lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
-
-}
-
-static void lcdtg_set_phadadj(u32 mode)
-{
- int adj;
-
- if (mode == LCD_SHARP_VGA) {
- /* Setting for VGA */
- adj = current_par->phadadj;
- if (adj < 0) {
- adj = PHACTRL_PHASE_MANUAL;
- } else {
- adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;
- }
- } else {
- /* Setting for QVGA */
- adj = (PHAD_QVGA_DEFAULT_VAL << 1) | PHACTRL_PHASE_MANUAL;
- }
- lcdtg_ssp_send(PHACTRL_ADRS, adj);
-}
-
-static void lcdtg_hw_init(u32 mode)
-{
- int i;
- int comadj;
-
- i = 0;
- while(lcdtg_power_on_table[i].adrs != 0xff) {
- if (lcdtg_power_on_table[i].adrs == 0xfe) {
- /* Set Common Voltage */
- comadj = current_par->comadj;
- if (comadj < 0) {
- comadj = COMADJ_DEFAULT;
- }
- lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);
- } else if (lcdtg_power_on_table[i].adrs == PHACTRL_ADRS) {
- /* Set Phase Adjuct */
- lcdtg_set_phadadj(mode);
- } else {
- /* Other */
- lcdtg_ssp_send(lcdtg_power_on_table[i].adrs, lcdtg_power_on_table[i].data);
- }
- if (lcdtg_power_on_table[i].wait != 0)
- udelay(lcdtg_power_on_table[i].wait);
- i++;
- }
-
- switch(mode) {
- case LCD_SHARP_QVGA:
- /* Set Lcd Resolution (QVGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
- break;
- case LCD_SHARP_VGA:
- /* Set Lcd Resolution (VGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
- break;
- default:
- break;
- }
-}
-
-static void lcdtg_lcd_change(u32 mode)
-{
- /* Set Phase Adjuct */
- lcdtg_set_phadadj(mode);
-
- if (mode == LCD_SHARP_VGA)
- /* Set Lcd Resolution (VGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA);
- else if (mode == LCD_SHARP_QVGA)
- /* Set Lcd Resolution (QVGA) */
- lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA);
-}
-
-
static struct device_driver w100fb_driver = {
.name = "w100fb",
.bus = &platform_bus_type,
@@ -1870,4 +1472,4 @@ module_init(w100fb_init);
module_exit(w100fb_cleanup);
MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h
index 41624f961237..7a58a1e3e427 100644
--- a/drivers/video/w100fb.h
+++ b/drivers/video/w100fb.h
@@ -5,9 +5,12 @@
*
* Copyright (C) 2002, ATI Corp.
* Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
*
* Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
+ * w32xx support by Ian Molton
+ *
* 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.
@@ -19,7 +22,7 @@
/* Block CIF Start: */
#define mmCHIP_ID 0x0000
-#define mmREVISION_ID 0x0004
+#define mmREVISION_ID 0x0004
#define mmWRAP_BUF_A 0x0008
#define mmWRAP_BUF_B 0x000C
#define mmWRAP_TOP_DIR 0x0010
@@ -88,7 +91,7 @@
#define mmDISP_DEBUG 0x04D4
#define mmDISP_DB_BUF_CNTL 0x04D8
#define mmDISP_CRC_SIG 0x04DC
-#define mmCRTC_DEFAULT_COUNT 0x04E0
+#define mmCRTC_DEFAULT_COUNT 0x04E0
#define mmLCD_BACKGROUND_COLOR 0x04E4
#define mmCRTC_PS2 0x04E8
#define mmCRTC_PS2_VPOS 0x04EC
@@ -119,17 +122,17 @@
/* Block DISPLAY End: */
/* Block GFX Start: */
-#define mmBRUSH_OFFSET 0x108C
-#define mmBRUSH_Y_X 0x1074
-#define mmDEFAULT_PITCH_OFFSET 0x10A0
-#define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8
-#define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC
-#define mmGLOBAL_ALPHA 0x1210
-#define mmFILTER_COEF 0x1214
-#define mmMVC_CNTL_START 0x11E0
-#define mmE2_ARITHMETIC_CNTL 0x1220
-#define mmENG_CNTL 0x13E8
-#define mmENG_PERF_CNT 0x13F0
+#define mmBRUSH_OFFSET 0x108C
+#define mmBRUSH_Y_X 0x1074
+#define mmDEFAULT_PITCH_OFFSET 0x10A0
+#define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8
+#define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC
+#define mmGLOBAL_ALPHA 0x1210
+#define mmFILTER_COEF 0x1214
+#define mmMVC_CNTL_START 0x11E0
+#define mmE2_ARITHMETIC_CNTL 0x1220
+#define mmENG_CNTL 0x13E8
+#define mmENG_PERF_CNT 0x13F0
/* Block GFX End: */
/* Block IDCT Start: */
@@ -141,22 +144,38 @@
/* Block IDCT End: */
/* Block MC Start: */
-#define mmMEM_CNTL 0x0180
-#define mmMEM_ARB 0x0184
-#define mmMC_FB_LOCATION 0x0188
-#define mmMEM_EXT_CNTL 0x018C
-#define mmMC_EXT_MEM_LOCATION 0x0190
-#define mmMEM_EXT_TIMING_CNTL 0x0194
-#define mmMEM_SDRAM_MODE_REG 0x0198
-#define mmMEM_IO_CNTL 0x019C
-#define mmMC_DEBUG 0x01A0
-#define mmMC_BIST_CTRL 0x01A4
-#define mmMC_BIST_COLLAR_READ 0x01A8
-#define mmTC_MISMATCH 0x01AC
-#define mmMC_PERF_MON_CNTL 0x01B0
-#define mmMC_PERF_COUNTERS 0x01B4
+#define mmMEM_CNTL 0x0180
+#define mmMEM_ARB 0x0184
+#define mmMC_FB_LOCATION 0x0188
+#define mmMEM_EXT_CNTL 0x018C
+#define mmMC_EXT_MEM_LOCATION 0x0190
+#define mmMEM_EXT_TIMING_CNTL 0x0194
+#define mmMEM_SDRAM_MODE_REG 0x0198
+#define mmMEM_IO_CNTL 0x019C
+#define mmMC_DEBUG 0x01A0
+#define mmMC_BIST_CTRL 0x01A4
+#define mmMC_BIST_COLLAR_READ 0x01A8
+#define mmTC_MISMATCH 0x01AC
+#define mmMC_PERF_MON_CNTL 0x01B0
+#define mmMC_PERF_COUNTERS 0x01B4
/* Block MC End: */
+/* Block BM Start: */
+#define mmBM_EXT_MEM_BANDWIDTH 0x0A00
+#define mmBM_OFFSET 0x0A04
+#define mmBM_MEM_EXT_TIMING_CNTL 0x0A08
+#define mmBM_MEM_EXT_CNTL 0x0A0C
+#define mmBM_MEM_MODE_REG 0x0A10
+#define mmBM_MEM_IO_CNTL 0x0A18
+#define mmBM_CONFIG 0x0A1C
+#define mmBM_STATUS 0x0A20
+#define mmBM_DEBUG 0x0A24
+#define mmBM_PERF_MON_CNTL 0x0A28
+#define mmBM_PERF_COUNTERS 0x0A2C
+#define mmBM_PERF2_MON_CNTL 0x0A30
+#define mmBM_PERF2_COUNTERS 0x0A34
+/* Block BM End: */
+
/* Block RBBM Start: */
#define mmWAIT_UNTIL 0x1400
#define mmISYNC_CNTL 0x1404
@@ -176,439 +195,575 @@
/* Block CG End: */
/* default value definitions */
-#define defWRAP_TOP_DIR 0x00000000
-#define defWRAP_START_DIR 0x00000000
-#define defCFGREG_BASE 0x00000000
-#define defCIF_IO 0x000C0902
-#define defINTF_CNTL 0x00000011
-#define defCPU_DEFAULTS 0x00000006
-#define defHW_INT 0x00000000
-#define defMC_EXT_MEM_LOCATION 0x07ff0000
-#define defTC_MISMATCH 0x00000000
+#define defWRAP_TOP_DIR 0x00000000
+#define defWRAP_START_DIR 0x00000000
+#define defCFGREG_BASE 0x00000000
+#define defCIF_IO 0x000C0902
+#define defINTF_CNTL 0x00000011
+#define defCPU_DEFAULTS 0x00000006
+#define defHW_INT 0x00000000
+#define defMC_EXT_MEM_LOCATION 0x07ff0000
+#define defTC_MISMATCH 0x00000000
#define W100_CFG_BASE 0x0
#define W100_CFG_LEN 0x10
#define W100_REG_BASE 0x10000
#define W100_REG_LEN 0x2000
#define MEM_INT_BASE_VALUE 0x100000
-#define MEM_INT_TOP_VALUE_W100 0x15ffff
#define MEM_EXT_BASE_VALUE 0x800000
-#define MEM_EXT_TOP_VALUE 0x9fffff
+#define MEM_INT_SIZE 0x05ffff
+#define MEM_WINDOW_BASE 0x100000
+#define MEM_WINDOW_SIZE 0xf00000
+
#define WRAP_BUF_BASE_VALUE 0x80000
#define WRAP_BUF_TOP_VALUE 0xbffff
+#define CHIP_ID_W100 0x57411002
+#define CHIP_ID_W3200 0x56441002
+#define CHIP_ID_W3220 0x57441002
-/* data structure definitions */
+/* Register structure definitions */
struct wrap_top_dir_t {
- unsigned long top_addr : 23;
- unsigned long : 9;
+ unsigned long top_addr : 23;
+ unsigned long : 9;
} __attribute__((packed));
union wrap_top_dir_u {
- unsigned long val : 32;
- struct wrap_top_dir_t f;
+ unsigned long val : 32;
+ struct wrap_top_dir_t f;
} __attribute__((packed));
struct wrap_start_dir_t {
- unsigned long start_addr : 23;
- unsigned long : 9;
+ unsigned long start_addr : 23;
+ unsigned long : 9;
} __attribute__((packed));
union wrap_start_dir_u {
- unsigned long val : 32;
- struct wrap_start_dir_t f;
+ unsigned long val : 32;
+ struct wrap_start_dir_t f;
} __attribute__((packed));
struct cif_cntl_t {
- unsigned long swap_reg : 2;
- unsigned long swap_fbuf_1 : 2;
- unsigned long swap_fbuf_2 : 2;
- unsigned long swap_fbuf_3 : 2;
- unsigned long pmi_int_disable : 1;
- unsigned long pmi_schmen_disable : 1;
- unsigned long intb_oe : 1;
- unsigned long en_wait_to_compensate_dq_prop_dly : 1;
- unsigned long compensate_wait_rd_size : 2;
- unsigned long wait_asserted_timeout_val : 2;
- unsigned long wait_masked_val : 2;
- unsigned long en_wait_timeout : 1;
- unsigned long en_one_clk_setup_before_wait : 1;
- unsigned long interrupt_active_high : 1;
- unsigned long en_overwrite_straps : 1;
- unsigned long strap_wait_active_hi : 1;
- unsigned long lat_busy_count : 2;
- unsigned long lat_rd_pm4_sclk_busy : 1;
- unsigned long dis_system_bits : 1;
- unsigned long dis_mr : 1;
- unsigned long cif_spare_1 : 4;
+ unsigned long swap_reg : 2;
+ unsigned long swap_fbuf_1 : 2;
+ unsigned long swap_fbuf_2 : 2;
+ unsigned long swap_fbuf_3 : 2;
+ unsigned long pmi_int_disable : 1;
+ unsigned long pmi_schmen_disable : 1;
+ unsigned long intb_oe : 1;
+ unsigned long en_wait_to_compensate_dq_prop_dly : 1;
+ unsigned long compensate_wait_rd_size : 2;
+ unsigned long wait_asserted_timeout_val : 2;
+ unsigned long wait_masked_val : 2;
+ unsigned long en_wait_timeout : 1;
+ unsigned long en_one_clk_setup_before_wait : 1;
+ unsigned long interrupt_active_high : 1;
+ unsigned long en_overwrite_straps : 1;
+ unsigned long strap_wait_active_hi : 1;
+ unsigned long lat_busy_count : 2;
+ unsigned long lat_rd_pm4_sclk_busy : 1;
+ unsigned long dis_system_bits : 1;
+ unsigned long dis_mr : 1;
+ unsigned long cif_spare_1 : 4;
} __attribute__((packed));
union cif_cntl_u {
- unsigned long val : 32;
- struct cif_cntl_t f;
+ unsigned long val : 32;
+ struct cif_cntl_t f;
} __attribute__((packed));
struct cfgreg_base_t {
- unsigned long cfgreg_base : 24;
- unsigned long : 8;
+ unsigned long cfgreg_base : 24;
+ unsigned long : 8;
} __attribute__((packed));
union cfgreg_base_u {
- unsigned long val : 32;
- struct cfgreg_base_t f;
+ unsigned long val : 32;
+ struct cfgreg_base_t f;
} __attribute__((packed));
struct cif_io_t {
- unsigned long dq_srp : 1;
- unsigned long dq_srn : 1;
- unsigned long dq_sp : 4;
- unsigned long dq_sn : 4;
- unsigned long waitb_srp : 1;
- unsigned long waitb_srn : 1;
- unsigned long waitb_sp : 4;
- unsigned long waitb_sn : 4;
- unsigned long intb_srp : 1;
- unsigned long intb_srn : 1;
- unsigned long intb_sp : 4;
- unsigned long intb_sn : 4;
- unsigned long : 2;
+ unsigned long dq_srp : 1;
+ unsigned long dq_srn : 1;
+ unsigned long dq_sp : 4;
+ unsigned long dq_sn : 4;
+ unsigned long waitb_srp : 1;
+ unsigned long waitb_srn : 1;
+ unsigned long waitb_sp : 4;
+ unsigned long waitb_sn : 4;
+ unsigned long intb_srp : 1;
+ unsigned long intb_srn : 1;
+ unsigned long intb_sp : 4;
+ unsigned long intb_sn : 4;
+ unsigned long : 2;
} __attribute__((packed));
union cif_io_u {
- unsigned long val : 32;
- struct cif_io_t f;
+ unsigned long val : 32;
+ struct cif_io_t f;
} __attribute__((packed));
struct cif_read_dbg_t {
- unsigned long unpacker_pre_fetch_trig_gen : 2;
- unsigned long dly_second_rd_fetch_trig : 1;
- unsigned long rst_rd_burst_id : 1;
- unsigned long dis_rd_burst_id : 1;
- unsigned long en_block_rd_when_packer_is_not_emp : 1;
- unsigned long dis_pre_fetch_cntl_sm : 1;
- unsigned long rbbm_chrncy_dis : 1;
- unsigned long rbbm_rd_after_wr_lat : 2;
- unsigned long dis_be_during_rd : 1;
- unsigned long one_clk_invalidate_pulse : 1;
- unsigned long dis_chnl_priority : 1;
- unsigned long rst_read_path_a_pls : 1;
- unsigned long rst_read_path_b_pls : 1;
- unsigned long dis_reg_rd_fetch_trig : 1;
- unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
- unsigned long dis_rd_same_byte_to_trig_fetch : 1;
- unsigned long dis_dir_wrap : 1;
- unsigned long dis_ring_buf_to_force_dec : 1;
- unsigned long dis_addr_comp_in_16bit : 1;
- unsigned long clr_w : 1;
- unsigned long err_rd_tag_is_3 : 1;
- unsigned long err_load_when_ful_a : 1;
- unsigned long err_load_when_ful_b : 1;
- unsigned long : 7;
+ unsigned long unpacker_pre_fetch_trig_gen : 2;
+ unsigned long dly_second_rd_fetch_trig : 1;
+ unsigned long rst_rd_burst_id : 1;
+ unsigned long dis_rd_burst_id : 1;
+ unsigned long en_block_rd_when_packer_is_not_emp : 1;
+ unsigned long dis_pre_fetch_cntl_sm : 1;
+ unsigned long rbbm_chrncy_dis : 1;
+ unsigned long rbbm_rd_after_wr_lat : 2;
+ unsigned long dis_be_during_rd : 1;
+ unsigned long one_clk_invalidate_pulse : 1;
+ unsigned long dis_chnl_priority : 1;
+ unsigned long rst_read_path_a_pls : 1;
+ unsigned long rst_read_path_b_pls : 1;
+ unsigned long dis_reg_rd_fetch_trig : 1;
+ unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
+ unsigned long dis_rd_same_byte_to_trig_fetch : 1;
+ unsigned long dis_dir_wrap : 1;
+ unsigned long dis_ring_buf_to_force_dec : 1;
+ unsigned long dis_addr_comp_in_16bit : 1;
+ unsigned long clr_w : 1;
+ unsigned long err_rd_tag_is_3 : 1;
+ unsigned long err_load_when_ful_a : 1;
+ unsigned long err_load_when_ful_b : 1;
+ unsigned long : 7;
} __attribute__((packed));
union cif_read_dbg_u {
- unsigned long val : 32;
- struct cif_read_dbg_t f;
+ unsigned long val : 32;
+ struct cif_read_dbg_t f;
} __attribute__((packed));
struct cif_write_dbg_t {
- unsigned long packer_timeout_count : 2;
- unsigned long en_upper_load_cond : 1;
- unsigned long en_chnl_change_cond : 1;
- unsigned long dis_addr_comp_cond : 1;
- unsigned long dis_load_same_byte_addr_cond : 1;
- unsigned long dis_timeout_cond : 1;
- unsigned long dis_timeout_during_rbbm : 1;
- unsigned long dis_packer_ful_during_rbbm_timeout : 1;
- unsigned long en_dword_split_to_rbbm : 1;
- unsigned long en_dummy_val : 1;
- unsigned long dummy_val_sel : 1;
- unsigned long mask_pm4_wrptr_dec : 1;
- unsigned long dis_mc_clean_cond : 1;
- unsigned long err_two_reqi_during_ful : 1;
- unsigned long err_reqi_during_idle_clk : 1;
- unsigned long err_global : 1;
- unsigned long en_wr_buf_dbg_load : 1;
- unsigned long en_wr_buf_dbg_path : 1;
- unsigned long sel_wr_buf_byte : 3;
- unsigned long dis_rd_flush_wr : 1;
- unsigned long dis_packer_ful_cond : 1;
- unsigned long dis_invalidate_by_ops_chnl : 1;
- unsigned long en_halt_when_reqi_err : 1;
- unsigned long cif_spare_2 : 5;
- unsigned long : 1;
+ unsigned long packer_timeout_count : 2;
+ unsigned long en_upper_load_cond : 1;
+ unsigned long en_chnl_change_cond : 1;
+ unsigned long dis_addr_comp_cond : 1;
+ unsigned long dis_load_same_byte_addr_cond : 1;
+ unsigned long dis_timeout_cond : 1;
+ unsigned long dis_timeout_during_rbbm : 1;
+ unsigned long dis_packer_ful_during_rbbm_timeout : 1;
+ unsigned long en_dword_split_to_rbbm : 1;
+ unsigned long en_dummy_val : 1;
+ unsigned long dummy_val_sel : 1;
+ unsigned long mask_pm4_wrptr_dec : 1;
+ unsigned long dis_mc_clean_cond : 1;
+ unsigned long err_two_reqi_during_ful : 1;
+ unsigned long err_reqi_during_idle_clk : 1;
+ unsigned long err_global : 1;
+ unsigned long en_wr_buf_dbg_load : 1;
+ unsigned long en_wr_buf_dbg_path : 1;
+ unsigned long sel_wr_buf_byte : 3;
+ unsigned long dis_rd_flush_wr : 1;
+ unsigned long dis_packer_ful_cond : 1;
+ unsigned long dis_invalidate_by_ops_chnl : 1;
+ unsigned long en_halt_when_reqi_err : 1;
+ unsigned long cif_spare_2 : 5;
+ unsigned long : 1;
} __attribute__((packed));
union cif_write_dbg_u {
- unsigned long val : 32;
- struct cif_write_dbg_t f;
+ unsigned long val : 32;
+ struct cif_write_dbg_t f;
} __attribute__((packed));
struct intf_cntl_t {
- unsigned char ad_inc_a : 1;
- unsigned char ring_buf_a : 1;
- unsigned char rd_fetch_trigger_a : 1;
- unsigned char rd_data_rdy_a : 1;
- unsigned char ad_inc_b : 1;
- unsigned char ring_buf_b : 1;
- unsigned char rd_fetch_trigger_b : 1;
- unsigned char rd_data_rdy_b : 1;
+ unsigned char ad_inc_a : 1;
+ unsigned char ring_buf_a : 1;
+ unsigned char rd_fetch_trigger_a : 1;
+ unsigned char rd_data_rdy_a : 1;
+ unsigned char ad_inc_b : 1;
+ unsigned char ring_buf_b : 1;
+ unsigned char rd_fetch_trigger_b : 1;
+ unsigned char rd_data_rdy_b : 1;
} __attribute__((packed));
union intf_cntl_u {
- unsigned char val : 8;
- struct intf_cntl_t f;
+ unsigned char val : 8;
+ struct intf_cntl_t f;
} __attribute__((packed));
struct cpu_defaults_t {
- unsigned char unpack_rd_data : 1;
- unsigned char access_ind_addr_a: 1;
- unsigned char access_ind_addr_b: 1;
- unsigned char access_scratch_reg : 1;
- unsigned char pack_wr_data : 1;
- unsigned char transition_size : 1;
- unsigned char en_read_buf_mode : 1;
- unsigned char rd_fetch_scratch : 1;
+ unsigned char unpack_rd_data : 1;
+ unsigned char access_ind_addr_a : 1;
+ unsigned char access_ind_addr_b : 1;
+ unsigned char access_scratch_reg : 1;
+ unsigned char pack_wr_data : 1;
+ unsigned char transition_size : 1;
+ unsigned char en_read_buf_mode : 1;
+ unsigned char rd_fetch_scratch : 1;
} __attribute__((packed));
union cpu_defaults_u {
- unsigned char val : 8;
- struct cpu_defaults_t f;
+ unsigned char val : 8;
+ struct cpu_defaults_t f;
+} __attribute__((packed));
+
+struct crtc_total_t {
+ unsigned long crtc_h_total : 10;
+ unsigned long : 6;
+ unsigned long crtc_v_total : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union crtc_total_u {
+ unsigned long val : 32;
+ struct crtc_total_t f;
+} __attribute__((packed));
+
+struct crtc_ss_t {
+ unsigned long ss_start : 10;
+ unsigned long : 6;
+ unsigned long ss_end : 10;
+ unsigned long : 2;
+ unsigned long ss_align : 1;
+ unsigned long ss_pol : 1;
+ unsigned long ss_run_mode : 1;
+ unsigned long ss_en : 1;
+} __attribute__((packed));
+
+union crtc_ss_u {
+ unsigned long val : 32;
+ struct crtc_ss_t f;
+} __attribute__((packed));
+
+struct active_h_disp_t {
+ unsigned long active_h_start : 10;
+ unsigned long : 6;
+ unsigned long active_h_end : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union active_h_disp_u {
+ unsigned long val : 32;
+ struct active_h_disp_t f;
+} __attribute__((packed));
+
+struct active_v_disp_t {
+ unsigned long active_v_start : 10;
+ unsigned long : 6;
+ unsigned long active_v_end : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union active_v_disp_u {
+ unsigned long val : 32;
+ struct active_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_h_disp_t {
+ unsigned long graphic_h_start : 10;
+ unsigned long : 6;
+ unsigned long graphic_h_end : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union graphic_h_disp_u {
+ unsigned long val : 32;
+ struct graphic_h_disp_t f;
+} __attribute__((packed));
+
+struct graphic_v_disp_t {
+ unsigned long graphic_v_start : 10;
+ unsigned long : 6;
+ unsigned long graphic_v_end : 10;
+ unsigned long : 6;
+} __attribute__((packed));
+
+union graphic_v_disp_u{
+ unsigned long val : 32;
+ struct graphic_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w100 {
+ unsigned long color_depth : 3;
+ unsigned long portrait_mode : 2;
+ unsigned long low_power_on : 1;
+ unsigned long req_freq : 4;
+ unsigned long en_crtc : 1;
+ unsigned long en_graphic_req : 1;
+ unsigned long en_graphic_crtc : 1;
+ unsigned long total_req_graphic : 9;
+ unsigned long lcd_pclk_on : 1;
+ unsigned long lcd_sclk_on : 1;
+ unsigned long pclk_running : 1;
+ unsigned long sclk_running : 1;
+ unsigned long : 6;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w32xx {
+ unsigned long color_depth : 3;
+ unsigned long portrait_mode : 2;
+ unsigned long low_power_on : 1;
+ unsigned long req_freq : 4;
+ unsigned long en_crtc : 1;
+ unsigned long en_graphic_req : 1;
+ unsigned long en_graphic_crtc : 1;
+ unsigned long total_req_graphic : 10;
+ unsigned long lcd_pclk_on : 1;
+ unsigned long lcd_sclk_on : 1;
+ unsigned long pclk_running : 1;
+ unsigned long sclk_running : 1;
+ unsigned long : 5;
+} __attribute__((packed));
+
+union graphic_ctrl_u {
+ unsigned long val : 32;
+ struct graphic_ctrl_t_w100 f_w100;
+ struct graphic_ctrl_t_w32xx f_w32xx;
} __attribute__((packed));
struct video_ctrl_t {
- unsigned long video_mode : 1;
- unsigned long keyer_en : 1;
- unsigned long en_video_req : 1;
- unsigned long en_graphic_req_video : 1;
- unsigned long en_video_crtc : 1;
- unsigned long video_hor_exp : 2;
- unsigned long video_ver_exp : 2;
- unsigned long uv_combine : 1;
- unsigned long total_req_video : 9;
- unsigned long video_ch_sel : 1;
- unsigned long video_portrait : 2;
- unsigned long yuv2rgb_en : 1;
- unsigned long yuv2rgb_option : 1;
- unsigned long video_inv_hor : 1;
- unsigned long video_inv_ver : 1;
- unsigned long gamma_sel : 2;
- unsigned long dis_limit : 1;
- unsigned long en_uv_hblend : 1;
- unsigned long rgb_gamma_sel : 2;
+ unsigned long video_mode : 1;
+ unsigned long keyer_en : 1;
+ unsigned long en_video_req : 1;
+ unsigned long en_graphic_req_video : 1;
+ unsigned long en_video_crtc : 1;
+ unsigned long video_hor_exp : 2;
+ unsigned long video_ver_exp : 2;
+ unsigned long uv_combine : 1;
+ unsigned long total_req_video : 9;
+ unsigned long video_ch_sel : 1;
+ unsigned long video_portrait : 2;
+ unsigned long yuv2rgb_en : 1;
+ unsigned long yuv2rgb_option : 1;
+ unsigned long video_inv_hor : 1;
+ unsigned long video_inv_ver : 1;
+ unsigned long gamma_sel : 2;
+ unsigned long dis_limit : 1;
+ unsigned long en_uv_hblend : 1;
+ unsigned long rgb_gamma_sel : 2;
} __attribute__((packed));
union video_ctrl_u {
- unsigned long val : 32;
- struct video_ctrl_t f;
+ unsigned long val : 32;
+ struct video_ctrl_t f;
} __attribute__((packed));
struct disp_db_buf_cntl_rd_t {
- unsigned long en_db_buf : 1;
- unsigned long update_db_buf_done : 1;
- unsigned long db_buf_cntl : 6;
- unsigned long : 24;
+ unsigned long en_db_buf : 1;
+ unsigned long update_db_buf_done : 1;
+ unsigned long db_buf_cntl : 6;
+ unsigned long : 24;
} __attribute__((packed));
union disp_db_buf_cntl_rd_u {
- unsigned long val : 32;
- struct disp_db_buf_cntl_rd_t f;
+ unsigned long val : 32;
+ struct disp_db_buf_cntl_rd_t f;
} __attribute__((packed));
struct disp_db_buf_cntl_wr_t {
- unsigned long en_db_buf : 1;
- unsigned long update_db_buf : 1;
- unsigned long db_buf_cntl : 6;
- unsigned long : 24;
+ unsigned long en_db_buf : 1;
+ unsigned long update_db_buf : 1;
+ unsigned long db_buf_cntl : 6;
+ unsigned long : 24;
} __attribute__((packed));
union disp_db_buf_cntl_wr_u {
- unsigned long val : 32;
- struct disp_db_buf_cntl_wr_t f;
+ unsigned long val : 32;
+ struct disp_db_buf_cntl_wr_t f;
} __attribute__((packed));
struct gamma_value1_t {
- unsigned long gamma1 : 8;
- unsigned long gamma2 : 8;
- unsigned long gamma3 : 8;
- unsigned long gamma4 : 8;
+ unsigned long gamma1 : 8;
+ unsigned long gamma2 : 8;
+ unsigned long gamma3 : 8;
+ unsigned long gamma4 : 8;
} __attribute__((packed));
union gamma_value1_u {
- unsigned long val : 32;
- struct gamma_value1_t f;
+ unsigned long val : 32;
+ struct gamma_value1_t f;
} __attribute__((packed));
struct gamma_value2_t {
- unsigned long gamma5 : 8;
- unsigned long gamma6 : 8;
- unsigned long gamma7 : 8;
- unsigned long gamma8 : 8;
+ unsigned long gamma5 : 8;
+ unsigned long gamma6 : 8;
+ unsigned long gamma7 : 8;
+ unsigned long gamma8 : 8;
} __attribute__((packed));
union gamma_value2_u {
- unsigned long val : 32;
- struct gamma_value2_t f;
+ unsigned long val : 32;
+ struct gamma_value2_t f;
} __attribute__((packed));
struct gamma_slope_t {
- unsigned long slope1 : 3;
- unsigned long slope2 : 3;
- unsigned long slope3 : 3;
- unsigned long slope4 : 3;
- unsigned long slope5 : 3;
- unsigned long slope6 : 3;
- unsigned long slope7 : 3;
- unsigned long slope8 : 3;
- unsigned long : 8;
+ unsigned long slope1 : 3;
+ unsigned long slope2 : 3;
+ unsigned long slope3 : 3;
+ unsigned long slope4 : 3;
+ unsigned long slope5 : 3;
+ unsigned long slope6 : 3;
+ unsigned long slope7 : 3;
+ unsigned long slope8 : 3;
+ unsigned long : 8;
} __attribute__((packed));
union gamma_slope_u {
- unsigned long val : 32;
- struct gamma_slope_t f;
+ unsigned long val : 32;
+ struct gamma_slope_t f;
} __attribute__((packed));
struct mc_ext_mem_location_t {
- unsigned long mc_ext_mem_start : 16;
- unsigned long mc_ext_mem_top : 16;
+ unsigned long mc_ext_mem_start : 16;
+ unsigned long mc_ext_mem_top : 16;
} __attribute__((packed));
union mc_ext_mem_location_u {
- unsigned long val : 32;
- struct mc_ext_mem_location_t f;
+ unsigned long val : 32;
+ struct mc_ext_mem_location_t f;
+} __attribute__((packed));
+
+struct mc_fb_location_t {
+ unsigned long mc_fb_start : 16;
+ unsigned long mc_fb_top : 16;
+} __attribute__((packed));
+
+union mc_fb_location_u {
+ unsigned long val : 32;
+ struct mc_fb_location_t f;
} __attribute__((packed));
struct clk_pin_cntl_t {
- unsigned long osc_en : 1;
- unsigned long osc_gain : 5;
- unsigned long dont_use_xtalin : 1;
- unsigned long xtalin_pm_en : 1;
- unsigned long xtalin_dbl_en : 1;
- unsigned long : 7;
- unsigned long cg_debug : 16;
+ unsigned long osc_en : 1;
+ unsigned long osc_gain : 5;
+ unsigned long dont_use_xtalin : 1;
+ unsigned long xtalin_pm_en : 1;
+ unsigned long xtalin_dbl_en : 1;
+ unsigned long : 7;
+ unsigned long cg_debug : 16;
} __attribute__((packed));
union clk_pin_cntl_u {
- unsigned long val : 32;
- struct clk_pin_cntl_t f;
+ unsigned long val : 32;
+ struct clk_pin_cntl_t f;
} __attribute__((packed));
struct pll_ref_fb_div_t {
- unsigned long pll_ref_div : 4;
- unsigned long : 4;
- unsigned long pll_fb_div_int : 6;
- unsigned long : 2;
- unsigned long pll_fb_div_frac : 3;
- unsigned long : 1;
- unsigned long pll_reset_time : 4;
- unsigned long pll_lock_time : 8;
+ unsigned long pll_ref_div : 4;
+ unsigned long : 4;
+ unsigned long pll_fb_div_int : 6;
+ unsigned long : 2;
+ unsigned long pll_fb_div_frac : 3;
+ unsigned long : 1;
+ unsigned long pll_reset_time : 4;
+ unsigned long pll_lock_time : 8;
} __attribute__((packed));
union pll_ref_fb_div_u {
- unsigned long val : 32;
- struct pll_ref_fb_div_t f;
+ unsigned long val : 32;
+ struct pll_ref_fb_div_t f;
} __attribute__((packed));
struct pll_cntl_t {
- unsigned long pll_pwdn : 1;
- unsigned long pll_reset : 1;
- unsigned long pll_pm_en : 1;
- unsigned long pll_mode : 1;
- unsigned long pll_refclk_sel : 1;
- unsigned long pll_fbclk_sel : 1;
- unsigned long pll_tcpoff : 1;
- unsigned long pll_pcp : 3;
- unsigned long pll_pvg : 3;
- unsigned long pll_vcofr : 1;
- unsigned long pll_ioffset : 2;
- unsigned long pll_pecc_mode : 2;
- unsigned long pll_pecc_scon : 2;
- unsigned long pll_dactal : 4;
- unsigned long pll_cp_clip : 2;
- unsigned long pll_conf : 3;
- unsigned long pll_mbctrl : 2;
- unsigned long pll_ring_off : 1;
+ unsigned long pll_pwdn : 1;
+ unsigned long pll_reset : 1;
+ unsigned long pll_pm_en : 1;
+ unsigned long pll_mode : 1;
+ unsigned long pll_refclk_sel : 1;
+ unsigned long pll_fbclk_sel : 1;
+ unsigned long pll_tcpoff : 1;
+ unsigned long pll_pcp : 3;
+ unsigned long pll_pvg : 3;
+ unsigned long pll_vcofr : 1;
+ unsigned long pll_ioffset : 2;
+ unsigned long pll_pecc_mode : 2;
+ unsigned long pll_pecc_scon : 2;
+ unsigned long pll_dactal : 4;
+ unsigned long pll_cp_clip : 2;
+ unsigned long pll_conf : 3;
+ unsigned long pll_mbctrl : 2;
+ unsigned long pll_ring_off : 1;
} __attribute__((packed));
union pll_cntl_u {
- unsigned long val : 32;
- struct pll_cntl_t f;
+ unsigned long val : 32;
+ struct pll_cntl_t f;
} __attribute__((packed));
struct sclk_cntl_t {
- unsigned long sclk_src_sel : 2;
- unsigned long : 2;
- unsigned long sclk_post_div_fast : 4;
- unsigned long sclk_clkon_hys : 3;
- unsigned long sclk_post_div_slow : 4;
- unsigned long disp_cg_ok2switch_en : 1;
- unsigned long sclk_force_reg : 1;
- unsigned long sclk_force_disp : 1;
- unsigned long sclk_force_mc : 1;
- unsigned long sclk_force_extmc : 1;
- unsigned long sclk_force_cp : 1;
- unsigned long sclk_force_e2 : 1;
- unsigned long sclk_force_e3 : 1;
- unsigned long sclk_force_idct : 1;
- unsigned long sclk_force_bist : 1;
- unsigned long busy_extend_cp : 1;
- unsigned long busy_extend_e2 : 1;
- unsigned long busy_extend_e3 : 1;
- unsigned long busy_extend_idct : 1;
- unsigned long : 3;
+ unsigned long sclk_src_sel : 2;
+ unsigned long : 2;
+ unsigned long sclk_post_div_fast : 4;
+ unsigned long sclk_clkon_hys : 3;
+ unsigned long sclk_post_div_slow : 4;
+ unsigned long disp_cg_ok2switch_en : 1;
+ unsigned long sclk_force_reg : 1;
+ unsigned long sclk_force_disp : 1;
+ unsigned long sclk_force_mc : 1;
+ unsigned long sclk_force_extmc : 1;
+ unsigned long sclk_force_cp : 1;
+ unsigned long sclk_force_e2 : 1;
+ unsigned long sclk_force_e3 : 1;
+ unsigned long sclk_force_idct : 1;
+ unsigned long sclk_force_bist : 1;
+ unsigned long busy_extend_cp : 1;
+ unsigned long busy_extend_e2 : 1;
+ unsigned long busy_extend_e3 : 1;
+ unsigned long busy_extend_idct : 1;
+ unsigned long : 3;
} __attribute__((packed));
union sclk_cntl_u {
- unsigned long val : 32;
- struct sclk_cntl_t f;
+ unsigned long val : 32;
+ struct sclk_cntl_t f;
} __attribute__((packed));
struct pclk_cntl_t {
- unsigned long pclk_src_sel : 2;
- unsigned long : 2;
- unsigned long pclk_post_div : 4;
- unsigned long : 8;
- unsigned long pclk_force_disp : 1;
- unsigned long : 15;
+ unsigned long pclk_src_sel : 2;
+ unsigned long : 2;
+ unsigned long pclk_post_div : 4;
+ unsigned long : 8;
+ unsigned long pclk_force_disp : 1;
+ unsigned long : 15;
} __attribute__((packed));
union pclk_cntl_u {
- unsigned long val : 32;
- struct pclk_cntl_t f;
+ unsigned long val : 32;
+ struct pclk_cntl_t f;
} __attribute__((packed));
+
+#define TESTCLK_SRC_PLL 0x01
+#define TESTCLK_SRC_SCLK 0x02
+#define TESTCLK_SRC_PCLK 0x03
+/* 4 and 5 seem to by XTAL/M */
+#define TESTCLK_SRC_XTAL 0x06
+
struct clk_test_cntl_t {
- unsigned long testclk_sel : 4;
- unsigned long : 3;
- unsigned long start_check_freq : 1;
- unsigned long tstcount_rst : 1;
- unsigned long : 15;
- unsigned long test_count : 8;
+ unsigned long testclk_sel : 4;
+ unsigned long : 3;
+ unsigned long start_check_freq : 1;
+ unsigned long tstcount_rst : 1;
+ unsigned long : 15;
+ unsigned long test_count : 8;
} __attribute__((packed));
union clk_test_cntl_u {
- unsigned long val : 32;
- struct clk_test_cntl_t f;
+ unsigned long val : 32;
+ struct clk_test_cntl_t f;
} __attribute__((packed));
struct pwrmgt_cntl_t {
- unsigned long pwm_enable : 1;
- unsigned long : 1;
- unsigned long pwm_mode_req : 2;
- unsigned long pwm_wakeup_cond : 2;
- unsigned long pwm_fast_noml_hw_en : 1;
- unsigned long pwm_noml_fast_hw_en : 1;
- unsigned long pwm_fast_noml_cond : 4;
- unsigned long pwm_noml_fast_cond : 4;
- unsigned long pwm_idle_timer : 8;
- unsigned long pwm_busy_timer : 8;
+ unsigned long pwm_enable : 1;
+ unsigned long : 1;
+ unsigned long pwm_mode_req : 2;
+ unsigned long pwm_wakeup_cond : 2;
+ unsigned long pwm_fast_noml_hw_en : 1;
+ unsigned long pwm_noml_fast_hw_en : 1;
+ unsigned long pwm_fast_noml_cond : 4;
+ unsigned long pwm_noml_fast_cond : 4;
+ unsigned long pwm_idle_timer : 8;
+ unsigned long pwm_busy_timer : 8;
} __attribute__((packed));
union pwrmgt_cntl_u {
- unsigned long val : 32;
- struct pwrmgt_cntl_t f;
+ unsigned long val : 32;
+ struct pwrmgt_cntl_t f;
} __attribute__((packed));
#endif
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 711b90903e7b..9a1e00dd3e02 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -54,4 +54,20 @@ config W1_SMEM
Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+config W1_DS2433
+ tristate "4kb EEPROM family support (DS2433)"
+ depends on W1
+ help
+ Say Y here if you want to use a 1-wire
+ 4kb EEPROM family device (DS2433).
+
+config W1_DS2433_CRC
+ bool "Protect DS2433 data with a CRC16"
+ depends on W1_DS2433
+ select CRC16
+ help
+ Say Y here to protect DS2433 data with a CRC16.
+ Each block has 30 bytes of data and a two byte CRC16.
+ Full block writes are only allowed if the CRC is valid.
+
endmenu
diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile
index 80725c348e70..01fb54391470 100644
--- a/drivers/w1/Makefile
+++ b/drivers/w1/Makefile
@@ -6,6 +6,10 @@ ifneq ($(CONFIG_NET), y)
EXTRA_CFLAGS += -DNETLINK_DISABLED
endif
+ifeq ($(CONFIG_W1_DS2433_CRC), y)
+EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC
+endif
+
obj-$(CONFIG_W1) += wire.o
wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
@@ -13,8 +17,9 @@ obj-$(CONFIG_W1_MATROX) += matrox_w1.o
obj-$(CONFIG_W1_THERM) += w1_therm.o
obj-$(CONFIG_W1_SMEM) += w1_smem.o
-obj-$(CONFIG_W1_DS9490) += ds9490r.o
+obj-$(CONFIG_W1_DS9490) += ds9490r.o
ds9490r-objs := dscore.o
obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
+obj-$(CONFIG_W1_DS2433) += w1_ds2433.o
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
index 7bddd8ac7d7f..a79d16d5666f 100644
--- a/drivers/w1/ds_w1_bridge.c
+++ b/drivers/w1/ds_w1_bridge.c
@@ -1,8 +1,8 @@
/*
- * ds_w1_bridge.c
+ * ds_w1_bridge.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -25,7 +25,7 @@
#include "../w1/w1.h"
#include "../w1/w1_int.h"
#include "dscore.h"
-
+
static struct ds_device *ds_dev;
static struct w1_bus_master *ds_bus_master;
@@ -120,7 +120,7 @@ static u8 ds9490r_reset(unsigned long data)
static int __devinit ds_w1_init(void)
{
int err;
-
+
ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
if (!ds_bus_master) {
printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
@@ -136,14 +136,14 @@ static int __devinit ds_w1_init(void)
memset(ds_bus_master, 0, sizeof(*ds_bus_master));
- ds_bus_master->data = (unsigned long)ds_dev;
- ds_bus_master->touch_bit = &ds9490r_touch_bit;
- ds_bus_master->read_bit = &ds9490r_read_bit;
- ds_bus_master->write_bit = &ds9490r_write_bit;
- ds_bus_master->read_byte = &ds9490r_read_byte;
- ds_bus_master->write_byte = &ds9490r_write_byte;
- ds_bus_master->read_block = &ds9490r_read_block;
- ds_bus_master->write_block = &ds9490r_write_block;
+ ds_bus_master->data = (unsigned long)ds_dev;
+ ds_bus_master->touch_bit = &ds9490r_touch_bit;
+ ds_bus_master->read_bit = &ds9490r_read_bit;
+ ds_bus_master->write_bit = &ds9490r_write_bit;
+ ds_bus_master->read_byte = &ds9490r_read_byte;
+ ds_bus_master->write_byte = &ds9490r_write_byte;
+ ds_bus_master->read_block = &ds9490r_read_block;
+ ds_bus_master->write_block = &ds9490r_write_block;
ds_bus_master->reset_bus = &ds9490r_reset;
err = w1_add_master_device(ds_bus_master);
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index eee6644d33d6..15fb250451e5 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -1,8 +1,8 @@
/*
- * dscore.c
+ * dscore.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -32,19 +32,16 @@ static struct usb_device_id ds_id_table [] = {
};
MODULE_DEVICE_TABLE(usb, ds_id_table);
-int ds_probe(struct usb_interface *, const struct usb_device_id *);
-void ds_disconnect(struct usb_interface *);
+static int ds_probe(struct usb_interface *, const struct usb_device_id *);
+static void ds_disconnect(struct usb_interface *);
int ds_touch_bit(struct ds_device *, u8, u8 *);
int ds_read_byte(struct ds_device *, u8 *);
int ds_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(struct ds_device *, u8);
-int ds_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
+static int ds_start_pulse(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
@@ -79,11 +76,11 @@ void ds_put_device(struct ds_device *dev)
static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -94,11 +91,11 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
MODE_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -109,11 +106,11 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
{
int err;
-
- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+
+ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
COMM_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
- printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+ printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
value, index, err);
return err;
}
@@ -126,19 +123,20 @@ static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int of
printk("%45s: %8x\n", str, buf[off]);
}
-int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned char *buf, int size)
+static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+ unsigned char *buf, int size)
{
int count, err;
-
+
memset(st, 0, sizeof(st));
-
+
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
if (err < 0) {
printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
return err;
}
-
+
if (count >= sizeof(*st))
memcpy(st, buf, sizeof(*st));
@@ -149,13 +147,13 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
{
unsigned char buf[64];
int count, err = 0, i;
-
+
memcpy(st, buf, sizeof(*st));
-
+
count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
if (count < 0)
return err;
-
+
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
for (i=0; i<count; ++i)
printk("%02x ", buf[i]);
@@ -199,7 +197,7 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
return err;
}
#endif
-
+
return err;
}
@@ -207,9 +205,9 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{
int count, err;
struct ds_status st;
-
+
count = 0;
- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
buf, size, &count, 1000);
if (err < 0) {
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
@@ -234,7 +232,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
{
int count, err;
-
+
count = 0;
err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
if (err < 0) {
@@ -245,12 +243,14 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
return err;
}
+#if 0
+
int ds_stop_pulse(struct ds_device *dev, int limit)
{
struct ds_status st;
int count = 0, err = 0;
u8 buf[0x20];
-
+
do {
err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
if (err)
@@ -275,7 +275,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)
int ds_detect(struct ds_device *dev, struct ds_status *st)
{
int err;
-
+
err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
if (err)
return err;
@@ -283,11 +283,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
if (err)
return err;
-
+
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
if (err)
return err;
-
+
err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
if (err)
return err;
@@ -297,7 +297,9 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
return err;
}
-int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+#endif /* 0 */
+
+static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
{
u8 buf[0x20];
int err, count = 0;
@@ -305,7 +307,7 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
do {
err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
#if 0
- if (err >= 0) {
+ if (err >= 0) {
int i;
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
for (i=0; i<err; ++i)
@@ -319,10 +321,8 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
ds_recv_status(dev, st);
return -1;
- }
- else {
+ } else
return 0;
- }
}
int ds_reset(struct ds_device *dev, struct ds_status *st)
@@ -345,6 +345,7 @@ int ds_reset(struct ds_device *dev, struct ds_status *st)
return 0;
}
+#if 0
int ds_set_speed(struct ds_device *dev, int speed)
{
int err;
@@ -356,20 +357,21 @@ int ds_set_speed(struct ds_device *dev, int speed)
speed = SPEED_FLEXIBLE;
speed &= 0xff;
-
+
err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
if (err)
return err;
return err;
}
+#endif /* 0 */
-int ds_start_pulse(struct ds_device *dev, int delay)
+static int ds_start_pulse(struct ds_device *dev, int delay)
{
int err;
u8 del = 1 + (u8)(delay >> 4);
struct ds_status st;
-
+
#if 0
err = ds_stop_pulse(dev, 10);
if (err)
@@ -390,7 +392,7 @@ int ds_start_pulse(struct ds_device *dev, int delay)
mdelay(delay);
ds_wait_status(dev, &st);
-
+
return err;
}
@@ -400,7 +402,7 @@ int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
struct ds_status st;
u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
u16 cmd;
-
+
err = ds_send_control(dev, value, 0);
if (err)
return err;
@@ -430,7 +432,7 @@ 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);
if (err)
return err;
@@ -445,7 +447,7 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
int err;
struct ds_status st;
u8 rbyte;
-
+
err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
if (err)
return err;
@@ -453,11 +455,11 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
err = ds_wait_status(dev, &st);
if (err)
return err;
-
+
err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
if (err < 0)
return err;
-
+
ds_start_pulse(dev, PULLUP_PULSE_DURATION);
return !(byte == rbyte);
@@ -470,11 +472,11 @@ int ds_read_bit(struct ds_device *dev, u8 *bit)
err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
if (err)
return err;
-
+
err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
if (err)
return err;
-
+
err = ds_recv_data(dev, bit, sizeof(*bit));
if (err < 0)
return err;
@@ -492,7 +494,7 @@ int ds_read_byte(struct ds_device *dev, u8 *byte)
return err;
ds_wait_status(dev, &st);
-
+
err = ds_recv_data(dev, byte, sizeof(*byte));
if (err < 0)
return err;
@@ -509,17 +511,17 @@ int ds_read_block(struct ds_device *dev, u8 *buf, int len)
return -E2BIG;
memset(buf, 0xFF, len);
-
+
err = ds_send_data(dev, buf, len);
if (err < 0)
return err;
-
+
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
if (err)
return err;
ds_wait_status(dev, &st);
-
+
memset(buf, 0x00, len);
err = ds_recv_data(dev, buf, len);
@@ -530,11 +532,11 @@ int ds_write_block(struct ds_device *dev, u8 *buf, int len)
{
int err;
struct ds_status st;
-
+
err = ds_send_data(dev, buf, len);
if (err < 0)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
@@ -548,10 +550,12 @@ int ds_write_block(struct ds_device *dev, u8 *buf, int len)
return err;
ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
+
return !(err == len);
}
+#if 0
+
int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
{
int err;
@@ -559,11 +563,11 @@ int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int condi
struct ds_status st;
memset(buf, 0, sizeof(buf));
-
+
err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
if (err)
return err;
-
+
ds_wait_status(ds_dev, &st);
value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
@@ -589,7 +593,7 @@ int ds_match_access(struct ds_device *dev, u64 init)
err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
if (err)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
@@ -609,11 +613,11 @@ int ds_set_path(struct ds_device *dev, u64 init)
memcpy(buf, &init, 8);
buf[8] = BRANCH_MAIN;
-
+
err = ds_send_data(dev, buf, sizeof(buf));
if (err)
return err;
-
+
ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
@@ -625,7 +629,10 @@ int ds_set_path(struct ds_device *dev, u64 init)
return 0;
}
-int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
+#endif /* 0 */
+
+static int ds_probe(struct usb_interface *intf,
+ const struct usb_device_id *udev_id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
@@ -653,7 +660,7 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
return err;
}
-
+
iface_desc = &intf->altsetting[0];
if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
@@ -662,37 +669,37 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
atomic_set(&ds_dev->refcnt, 0);
memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
-
+
/*
- * This loop doesn'd show control 0 endpoint,
+ * This loop doesn'd show control 0 endpoint,
* so we will fill only 1-3 endpoints entry.
*/
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
ds_dev->ep[i+1] = endpoint->bEndpointAddress;
-
+
printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
}
-
+
#if 0
{
int err, i;
u64 buf[3];
u64 init=0xb30000002078ee81ull;
struct ds_status st;
-
+
ds_reset(ds_dev, &st);
err = ds_search(ds_dev, init, buf, 3, 0);
if (err < 0)
return err;
for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]);
-
- printk("Resetting...\n");
+
+ printk("Resetting...\n");
ds_reset(ds_dev, &st);
printk("Setting path for %llx.\n", init);
err = ds_set_path(ds_dev, init);
@@ -707,12 +714,12 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
err = ds_search(ds_dev, init, buf, 3, 0);
printk("ds_search() returned %d\n", err);
-
+
if (err < 0)
return err;
for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]);
-
+
return 0;
}
#endif
@@ -720,10 +727,10 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
return 0;
}
-void ds_disconnect(struct usb_interface *intf)
+static void ds_disconnect(struct usb_interface *intf)
{
struct ds_device *dev;
-
+
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
@@ -740,7 +747,7 @@ void ds_disconnect(struct usb_interface *intf)
ds_dev = NULL;
}
-int ds_init(void)
+static int ds_init(void)
{
int err;
@@ -753,7 +760,7 @@ int ds_init(void)
return 0;
}
-void ds_fini(void)
+static void ds_fini(void)
{
usb_deregister(&ds_driver);
}
@@ -776,8 +783,8 @@ EXPORT_SYMBOL(ds_get_device);
EXPORT_SYMBOL(ds_put_device);
/*
- * This functions can be used for EEPROM programming,
- * when driver will be included into mainline this will
+ * This functions can be used for EEPROM programming,
+ * when driver will be included into mainline this will
* require uncommenting.
*/
#if 0
diff --git a/drivers/w1/dscore.h b/drivers/w1/dscore.h
index 9c767ef4ac24..6cf5671d6ebe 100644
--- a/drivers/w1/dscore.h
+++ b/drivers/w1/dscore.h
@@ -1,8 +1,8 @@
/*
- * dscore.h
+ * dscore.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -122,7 +122,7 @@
struct ds_device
{
- struct usb_device *udev;
+ struct usb_device *udev;
struct usb_interface *intf;
int ep[NUM_EP];
@@ -156,11 +156,7 @@ int ds_read_byte(struct ds_device *, u8 *);
int ds_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(struct ds_device *, u8);
-int ds_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
int ds_write_block(struct ds_device *, u8 *, int);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 8a9c42822502..14016b1cd948 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -45,10 +45,12 @@ 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);
@@ -59,19 +61,6 @@ static pid_t control_thread;
static int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete);
-/* stuff for the default family */
-static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
- return(sprintf(buf, "%s\n", sl->name));
-}
-static struct w1_family_ops w1_default_fops = {
- .rname = &w1_famdefault_read_name,
-};
-static struct w1_family w1_default_family = {
- .fops = &w1_default_fops,
-};
-
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
return 1;
@@ -82,73 +71,115 @@ static int w1_master_probe(struct device *dev)
return -ENODEV;
}
-static int w1_master_remove(struct device *dev)
-{
- return 0;
-}
-
static void w1_master_release(struct device *dev)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
- complete(&md->dev_released);
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
+
+ dev_fini_netlink(md);
+ memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+ kfree(md);
}
static void w1_slave_release(struct device *dev)
{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
+
+ while (atomic_read(&sl->refcnt)) {
+ 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);
+ }
+
+ w1_family_put(sl->family);
+ sl->master->slave_count--;
- complete(&sl->dev_released);
+ complete(&sl->released);
}
-static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "No family registered.\n");
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+
+ return sprintf(buf, "%s\n", sl->name);
}
-static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
- return sprintf(buf, "No family registered.\n");
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+ atomic_inc(&sl->refcnt);
+ if (off > 8) {
+ count = 0;
+ } else {
+ if (off + count > 8)
+ count = 8 - off;
+
+ memcpy(buf, (u8 *)&sl->reg_num, count);
+ }
+ atomic_dec(&sl->refcnt);
+
+ return count;
}
-static struct device_attribute w1_slave_attribute =
- __ATTR(name, S_IRUGO, w1_default_read_name, NULL);
-
-static struct bin_attribute w1_slave_bin_attribute = {
- .attr = {
- .name = "w1_slave",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .size = W1_SLAVE_DATA_SIZE,
- .read = &w1_default_read_bin,
+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,
+ .owner = THIS_MODULE,
+ },
+ .size = 8,
+ .read = w1_slave_read_id,
};
+/* Default family */
+static struct w1_family w1_default_family;
+
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
+ .hotplug = w1_hotplug,
};
-struct device_driver w1_driver = {
- .name = "w1_driver",
+struct device_driver w1_master_driver = {
+ .name = "w1_master_driver",
.bus = &w1_bus_type,
.probe = w1_master_probe,
- .remove = w1_master_remove,
};
-struct device w1_device = {
+struct device w1_master_device = {
.parent = NULL,
.bus = &w1_bus_type,
.bus_id = "w1 bus master",
- .driver = &w1_driver,
+ .driver = &w1_master_driver,
.release = &w1_master_release
};
+struct device_driver w1_slave_driver = {
+ .name = "w1_slave_driver",
+ .bus = &w1_bus_type,
+};
+
+struct device w1_slave_device = {
+ .parent = NULL,
+ .bus = &w1_bus_type,
+ .bus_id = "w1 bus slave",
+ .driver = &w1_slave_driver,
+ .release = &w1_slave_release
+};
+
static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible (&md->mutex))
@@ -165,7 +196,7 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
struct device_attribute *attr,
const char * buf, size_t count)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
if (down_interruptible (&md->mutex))
return -EBUSY;
@@ -181,7 +212,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible (&md->mutex))
@@ -196,7 +227,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -217,7 +248,7 @@ static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct devic
static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -231,7 +262,7 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru
static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -245,7 +276,7 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi
static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
ssize_t count;
if (down_interruptible(&md->mutex))
@@ -259,7 +290,7 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct w1_master *md = container_of(dev, struct w1_master, dev);
+ struct w1_master *md = dev_to_w1_master(dev);
int c = PAGE_SIZE;
if (down_interruptible(&md->mutex))
@@ -329,12 +360,55 @@ void w1_destroy_master_attributes(struct w1_master *master)
sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}
+#ifdef CONFIG_HOTPLUG
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct w1_master *md = NULL;
+ struct w1_slave *sl = NULL;
+ char *event_owner, *name;
+ int err, cur_index=0, cur_len=0;
+
+ if (dev->driver == &w1_master_driver) {
+ md = container_of(dev, struct w1_master, dev);
+ event_owner = "master";
+ name = md->name;
+ } else if (dev->driver == &w1_slave_driver) {
+ sl = container_of(dev, struct w1_slave, dev);
+ event_owner = "slave";
+ name = sl->name;
+ } else {
+ dev_dbg(dev, "Unknown hotplug event.\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id);
+
+ if (dev->driver != &w1_slave_driver || !sl)
+ return 0;
+
+ err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+ if (err)
+ return err;
+
+ err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+ if (err)
+ return err;
+
+ return 0;
+};
+#else
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ return 0;
+}
+#endif
+
static int __w1_attach_slave_device(struct w1_slave *sl)
{
int err;
sl->dev.parent = &sl->master->dev;
- sl->dev.driver = sl->master->driver;
+ sl->dev.driver = &w1_slave_driver;
sl->dev.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release;
@@ -347,8 +421,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
(unsigned int) sl->reg_num.family,
(unsigned long long) sl->reg_num.id);
- dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
- &sl->dev.bus_id[0]);
+ dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]);
err = device_register(&sl->dev);
if (err < 0) {
@@ -358,36 +431,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
return err;
}
- memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
- memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
-
- sl->attr_bin.read = sl->family->fops->rbin;
- sl->attr_name.show = sl->family->fops->rname;
+ /* Create "name" entry */
+ err = device_create_file(&sl->dev, &w1_slave_attr_name);
+ if (err < 0) {
+ dev_err(&sl->dev,
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
+ goto out_unreg;
+ }
- err = device_create_file(&sl->dev, &sl->attr_name);
+ /* Create "id" entry */
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
if (err < 0) {
dev_err(&sl->dev,
"sysfs file creation for [%s] failed. err=%d\n",
sl->dev.bus_id, err);
- device_unregister(&sl->dev);
- return err;
+ goto out_rem1;
}
- if ( sl->attr_bin.read ) {
- err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
- if (err < 0) {
- dev_err(&sl->dev,
- "sysfs file creation for [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
- device_remove_file(&sl->dev, &sl->attr_name);
- device_unregister(&sl->dev);
- return err;
- }
+ /* if the family driver needs to initialize something... */
+ if (sl->family->fops && sl->family->fops->add_slave &&
+ ((err = sl->family->fops->add_slave(sl)) < 0)) {
+ dev_err(&sl->dev,
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
+ goto out_rem2;
}
list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
return 0;
+
+out_rem2:
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+out_rem1:
+ device_remove_file(&sl->dev, &w1_slave_attr_name);
+out_unreg:
+ device_unregister(&sl->dev);
+ return err;
}
static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
@@ -413,7 +494,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
atomic_set(&sl->refcnt, 0);
- init_completion(&sl->dev_released);
+ init_completion(&sl->released);
spin_lock(&w1_flock);
f = w1_family_registered(rn->family);
@@ -452,28 +533,23 @@ static void w1_slave_detach(struct w1_slave *sl)
{
struct w1_netlink_msg msg;
- dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
-
- while (atomic_read(&sl->refcnt)) {
- printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
- sl->name, atomic_read(&sl->refcnt));
+ dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl);
- if (msleep_interruptible(1000))
- flush_signals(current);
- }
-
- if ( sl->attr_bin.read ) {
- sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
- }
- device_remove_file(&sl->dev, &sl->attr_name);
- device_unregister(&sl->dev);
- w1_family_put(sl->family);
+ list_del(&sl->w1_slave_entry);
- sl->master->slave_count--;
+ if (sl->family->fops && sl->family->fops->remove_slave)
+ sl->family->fops->remove_slave(sl);
memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
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_name);
+ device_unregister(&sl->dev);
+
+ wait_for_completion(&sl->released);
+ kfree(sl);
}
static struct w1_master *w1_search_master(unsigned long data)
@@ -500,14 +576,13 @@ void w1_reconnect_slaves(struct w1_family *f)
spin_lock_bh(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+ 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);
}
spin_unlock_bh(&w1_mlock);
}
-
static void w1_slave_found(unsigned long data, u64 rn)
{
int slave_count;
@@ -593,7 +668,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
* Return 0 - device(s) present, 1 - no devices present.
*/
if (w1_reset_bus(dev)) {
- dev_info(&dev->dev, "No devices present on the wire.\n");
+ dev_dbg(&dev->dev, "No devices present on the wire.\n");
break;
}
@@ -646,7 +721,7 @@ static int w1_control(void *data)
have_to_wait = 0;
try_to_freeze();
- msleep_interruptible(w1_timeout * 1000);
+ msleep_interruptible(w1_control_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
@@ -679,33 +754,30 @@ static int w1_control(void *data)
list_del(&dev->w1_master_entry);
spin_unlock_bh(&w1_mlock);
+ down(&dev->mutex);
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
- list_del(&sl->w1_slave_entry);
-
w1_slave_detach(sl);
- kfree(sl);
}
w1_destroy_master_attributes(dev);
+ up(&dev->mutex);
atomic_dec(&dev->refcnt);
continue;
}
if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
- dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+ dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
down(&dev->mutex);
- list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
if (sl->family->fid == W1_FAMILY_DEFAULT) {
struct w1_reg_num rn;
- list_del(&sl->w1_slave_entry);
- w1_slave_detach(sl);
memcpy(&rn, &sl->reg_num, sizeof(rn));
-
- kfree(sl);
+ 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);
up(&dev->mutex);
}
@@ -749,10 +821,7 @@ int w1_process(void *data)
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
- list_del (&sl->w1_slave_entry);
-
- w1_slave_detach (sl);
- kfree (sl);
+ w1_slave_detach(sl);
dev->slave_count--;
} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
@@ -783,7 +852,7 @@ static int w1_init(void)
goto err_out_exit_init;
}
- retval = driver_register(&w1_driver);
+ retval = driver_register(&w1_master_driver);
if (retval) {
printk(KERN_ERR
"Failed to register master driver. err=%d.\n",
@@ -791,18 +860,29 @@ static int w1_init(void)
goto err_out_bus_unregister;
}
+ retval = driver_register(&w1_slave_driver);
+ if (retval) {
+ printk(KERN_ERR
+ "Failed to register master driver. err=%d.\n",
+ retval);
+ goto err_out_master_unregister;
+ }
+
control_thread = kernel_thread(&w1_control, NULL, 0);
if (control_thread < 0) {
printk(KERN_ERR "Failed to create control thread. err=%d\n",
control_thread);
retval = control_thread;
- goto err_out_driver_unregister;
+ goto err_out_slave_unregister;
}
return 0;
-err_out_driver_unregister:
- driver_unregister(&w1_driver);
+err_out_slave_unregister:
+ driver_unregister(&w1_slave_driver);
+
+err_out_master_unregister:
+ driver_unregister(&w1_master_driver);
err_out_bus_unregister:
bus_unregister(&w1_bus_type);
@@ -821,7 +901,8 @@ static void w1_fini(void)
control_needs_exit = 1;
wait_for_completion(&w1_control_complete);
- driver_unregister(&w1_driver);
+ 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 4f0a986e33e3..d8900780c3bf 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -75,11 +75,9 @@ struct w1_slave
struct w1_master *master;
struct w1_family *family;
+ void *family_data;
struct device dev;
- struct completion dev_released;
-
- struct bin_attribute attr_bin;
- struct device_attribute attr_name;
+ struct completion released;
};
typedef void (* w1_slave_found_callback)(unsigned long, u64);
@@ -179,7 +177,6 @@ struct w1_master
struct device_driver *driver;
struct device dev;
- struct completion dev_released;
struct completion dev_exited;
struct w1_bus_master *bus_master;
@@ -191,6 +188,21 @@ struct w1_master
int w1_create_master_attributes(struct w1_master *);
void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
+static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
+{
+ return container_of(dev, struct w1_slave, dev);
+}
+
+static inline struct w1_slave* kobj_to_w1_slave(struct kobject *kobj)
+{
+ return dev_to_w1_slave(container_of(kobj, struct device, kobj));
+}
+
+static inline struct w1_master* dev_to_w1_master(struct device *dev)
+{
+ return container_of(dev, struct w1_master, dev);
+}
+
#endif /* __KERNEL__ */
#endif /* __W1_H */
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
new file mode 100644
index 000000000000..279e0e0363d6
--- /dev/null
+++ b/drivers/w1/w1_ds2433.c
@@ -0,0 +1,331 @@
+/*
+ * w1_ds2433.c - w1 family 23 (DS2433) driver
+ *
+ * Copyright (c) 2005 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>
+#ifdef CONFIG_W1_F23_CRC
+#include <linux/crc16.h>
+
+#define CRC16_INIT 0
+#define CRC16_VALID 0xb001
+
+#endif
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_int.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
+
+#define W1_EEPROM_SIZE 512
+#define W1_PAGE_COUNT 16
+#define W1_PAGE_SIZE 32
+#define W1_PAGE_BITS 5
+#define W1_PAGE_MASK 0x1F
+
+#define W1_F23_TIME 300
+
+#define W1_F23_READ_EEPROM 0xF0
+#define W1_F23_WRITE_SCRATCH 0x0F
+#define W1_F23_READ_SCRATCH 0xAA
+#define W1_F23_COPY_SCRATCH 0x55
+
+struct w1_f23_data {
+ u8 memory[W1_EEPROM_SIZE];
+ u32 validcrc;
+};
+
+/**
+ * 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_f23_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;
+}
+
+#ifdef CONFIG_W1_F23_CRC
+static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
+ int block)
+{
+ u8 wrbuf[3];
+ int off = block * W1_PAGE_SIZE;
+
+ if (data->validcrc & (1 << block))
+ return 0;
+
+ if (w1_reset_select_slave(sl)) {
+ data->validcrc = 0;
+ return -EIO;
+ }
+
+ wrbuf[0] = W1_F23_READ_EEPROM;
+ wrbuf[1] = off & 0xff;
+ wrbuf[2] = off >> 8;
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
+
+ /* cache the block if the CRC is valid */
+ if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
+ data->validcrc |= (1 << block);
+
+ return 0;
+}
+#endif /* CONFIG_W1_F23_CRC */
+
+static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+#ifdef CONFIG_W1_F23_CRC
+ struct w1_f23_data *data = sl->family_data;
+ int i, min_page, max_page;
+#else
+ u8 wrbuf[3];
+#endif
+
+ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ if (down_interruptible(&sl->master->mutex)) {
+ count = 0;
+ goto out_dec;
+ }
+
+#ifdef CONFIG_W1_F23_CRC
+
+ min_page = (off >> W1_PAGE_BITS);
+ max_page = (off + count - 1) >> W1_PAGE_BITS;
+ for (i = min_page; i <= max_page; i++) {
+ if (w1_f23_refresh_block(sl, data, i)) {
+ count = -EIO;
+ goto out_up;
+ }
+ }
+ memcpy(buf, &data->memory[off], count);
+
+#else /* CONFIG_W1_F23_CRC */
+
+ /* read directly from the EEPROM */
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_up;
+ }
+
+ wrbuf[0] = W1_F23_READ_EEPROM;
+ wrbuf[1] = off & 0xff;
+ wrbuf[2] = off >> 8;
+ w1_write_block(sl->master, wrbuf, 3);
+ w1_read_block(sl->master, buf, count);
+
+#endif /* CONFIG_W1_F23_CRC */
+
+out_up:
+ up(&sl->master->mutex);
+out_dec:
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+/**
+ * Writes to the scratchpad and reads it back for verification.
+ * Then copies the scratchpad to EEPROM.
+ * The data must be on one page.
+ * The master must be locked.
+ *
+ * @param sl The slave structure
+ * @param addr Address for the write
+ * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+ * @param data The data to write
+ * @return 0=Success -1=failure
+ */
+static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+{
+ u8 wrbuf[4];
+ u8 rdbuf[W1_PAGE_SIZE + 3];
+ u8 es = (addr + len - 1) & 0x1f;
+
+ /* Write the data to the scratchpad */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F23_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_F23_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))
+ return -1;
+
+ /* Copy the scratchpad to EEPROM */
+ if (w1_reset_select_slave(sl))
+ return -1;
+
+ wrbuf[0] = W1_F23_COPY_SCRATCH;
+ wrbuf[3] = es;
+ w1_write_block(sl->master, wrbuf, 4);
+
+ /* Sleep for 5 ms to wait for the write to complete */
+ msleep(5);
+
+ /* Reset the bus to wake up the EEPROM (this may not be needed) */
+ w1_reset_bus(sl->master);
+
+ return 0;
+}
+
+static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ int addr, len, idx;
+
+ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ return 0;
+
+#ifdef CONFIG_W1_F23_CRC
+ /* can only write full blocks in cached mode */
+ if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
+ dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
+ (int)off, count);
+ return -EINVAL;
+ }
+
+ /* make sure the block CRCs are valid */
+ for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
+ if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) {
+ dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off);
+ return -EINVAL;
+ }
+ }
+#endif /* CONFIG_W1_F23_CRC */
+
+ atomic_inc(&sl->refcnt);
+ if (down_interruptible(&sl->master->mutex)) {
+ count = 0;
+ goto out_dec;
+ }
+
+ /* Can only write data to one page at a time */
+ idx = 0;
+ while (idx < count) {
+ addr = off + idx;
+ len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
+ if (len > (count - idx))
+ len = count - idx;
+
+ if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) {
+ count = -EIO;
+ goto out_up;
+ }
+ idx += len;
+ }
+
+out_up:
+ up(&sl->master->mutex);
+out_dec:
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static struct bin_attribute w1_f23_bin_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = W1_EEPROM_SIZE,
+ .read = w1_f23_read_bin,
+ .write = w1_f23_write_bin,
+};
+
+static int w1_f23_add_slave(struct w1_slave *sl)
+{
+ int err;
+#ifdef CONFIG_W1_F23_CRC
+ struct w1_f23_data *data;
+
+ data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ memset(data, 0, sizeof(struct w1_f23_data));
+ sl->family_data = data;
+
+#endif /* CONFIG_W1_F23_CRC */
+
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+
+#ifdef CONFIG_W1_F23_CRC
+ if (err)
+ kfree(data);
+#endif /* CONFIG_W1_F23_CRC */
+
+ return err;
+}
+
+static void w1_f23_remove_slave(struct w1_slave *sl)
+{
+#ifdef CONFIG_W1_F23_CRC
+ if (sl->family_data) {
+ kfree(sl->family_data);
+ sl->family_data = NULL;
+ }
+#endif /* CONFIG_W1_F23_CRC */
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+}
+
+static struct w1_family_ops w1_f23_fops = {
+ .add_slave = w1_f23_add_slave,
+ .remove_slave = w1_f23_remove_slave,
+};
+
+static struct w1_family w1_family_23 = {
+ .fid = W1_EEPROM_DS2433,
+ .fops = &w1_f23_fops,
+};
+
+static int __init w1_f23_init(void)
+{
+ return w1_register_family(&w1_family_23);
+}
+
+static void __exit w1_f23_fini(void)
+{
+ w1_unregister_family(&w1_family_23);
+}
+
+module_init(w1_f23_init);
+module_exit(w1_f23_fini);
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 02eee57d3c0c..9e293e139a0e 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -21,6 +21,7 @@
#include <linux/spinlock.h>
#include <linux/list.h>
+#include <linux/sched.h> /* schedule_timeout() */
#include <linux/delay.h>
#include "w1_family.h"
@@ -29,23 +30,12 @@ DEFINE_SPINLOCK(w1_flock);
static LIST_HEAD(w1_families);
extern void w1_reconnect_slaves(struct w1_family *f);
-static int w1_check_family(struct w1_family *f)
-{
- if (!f->fops->rname || !f->fops->rbin)
- return -EINVAL;
-
- return 0;
-}
-
int w1_register_family(struct w1_family *newf)
{
struct list_head *ent, *n;
struct w1_family *f;
int ret = 0;
- if (w1_check_family(newf))
- return -EINVAL;
-
spin_lock(&w1_flock);
list_for_each_safe(ent, n, &w1_families) {
f = list_entry(ent, struct w1_family, family_entry);
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index b26da01bbc38..2ca0489c716a 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -31,14 +31,17 @@
#define W1_FAMILY_SMEM_81 0x81
#define W1_THERM_DS18S20 0x10
#define W1_THERM_DS1822 0x22
+#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
#define MAXNAMELEN 32
+struct w1_slave;
+
struct w1_family_ops
{
- ssize_t (* rname)(struct device *, struct device_attribute *, char *);
- ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
+ int (* add_slave)(struct w1_slave *);
+ void (* remove_slave)(struct w1_slave *);
};
struct w1_family
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index b5a5e04b6d37..c3f67eafc7ec 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -29,9 +29,9 @@
static u32 w1_ids = 1;
-extern struct device_driver w1_driver;
+extern struct device_driver w1_master_driver;
extern struct bus_type w1_bus_type;
-extern struct device w1_device;
+extern struct device w1_master_device;
extern int w1_max_slave_count;
extern int w1_max_slave_ttl;
extern struct list_head w1_masters;
@@ -76,7 +76,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
INIT_LIST_HEAD(&dev->slist);
init_MUTEX(&dev->mutex);
- init_completion(&dev->dev_released);
init_completion(&dev->dev_exited);
memcpy(&dev->dev, device, sizeof(struct device));
@@ -86,19 +85,16 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
dev->driver = driver;
- dev->groups = 23;
+ dev->groups = 1;
dev->seq = 1;
- dev->nls = netlink_kernel_create(NETLINK_W1, NULL);
- if (!dev->nls) {
- printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
- NETLINK_NFLOG, dev->dev.bus_id);
- }
+ dev_init_netlink(dev);
err = device_register(&dev->dev);
if (err) {
printk(KERN_ERR "Failed to register master device. err=%d\n", err);
- if (dev->nls && dev->nls->sk_socket)
- sock_release(dev->nls->sk_socket);
+
+ dev_fini_netlink(dev);
+
memset(dev, 0, sizeof(struct w1_master));
kfree(dev);
dev = NULL;
@@ -107,13 +103,9 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
return dev;
}
-static void w1_free_dev(struct w1_master *dev)
+void w1_free_dev(struct w1_master *dev)
{
device_unregister(&dev->dev);
- if (dev->nls && dev->nls->sk_socket)
- sock_release(dev->nls->sk_socket);
- memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
- kfree(dev);
}
int w1_add_master_device(struct w1_bus_master *master)
@@ -129,7 +121,7 @@ int w1_add_master_device(struct w1_bus_master *master)
return(-EINVAL);
}
- dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
+ dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
if (!dev)
return -ENOMEM;
@@ -188,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
__func__, dev->kpid);
while (atomic_read(&dev->refcnt)) {
- printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+ dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
dev->name, atomic_read(&dev->refcnt));
if (msleep_interruptible(1000))
@@ -225,3 +217,5 @@ void w1_remove_master_device(struct w1_bus_master *bm)
EXPORT_SYMBOL(w1_add_master_device);
EXPORT_SYMBOL(w1_remove_master_device);
+
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1);
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 00f032220173..e2a043354ddf 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -277,6 +277,29 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
w1_search(dev, cb);
}
+/**
+ * Resets the bus and then selects the slave by sending either a skip rom
+ * or a rom match.
+ * The w1 master lock must be held.
+ *
+ * @param sl the slave to select
+ * @return 0=success, anything else=error
+ */
+int w1_reset_select_slave(struct w1_slave *sl)
+{
+ if (w1_reset_bus(sl->master))
+ return -1;
+
+ if (sl->master->slave_count == 1)
+ w1_write_8(sl->master, W1_SKIP_ROM);
+ else {
+ u8 match[9] = {W1_MATCH_ROM, };
+ memcpy(&match[1], (u8 *)&sl->reg_num, 8);
+ w1_write_block(sl->master, match, 9);
+ }
+ return 0;
+}
+
EXPORT_SYMBOL(w1_touch_bit);
EXPORT_SYMBOL(w1_write_8);
EXPORT_SYMBOL(w1_read_8);
@@ -286,3 +309,4 @@ EXPORT_SYMBOL(w1_delay);
EXPORT_SYMBOL(w1_read_block);
EXPORT_SYMBOL(w1_write_block);
EXPORT_SYMBOL(w1_search_devices);
+EXPORT_SYMBOL(w1_reset_select_slave);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index af5829778aaa..232860184a29 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -34,5 +34,6 @@ 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);
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
+int w1_reset_select_slave(struct w1_slave *sl);
#endif /* __W1_IO_H */
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 2a82fb055c70..328645da7972 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -51,16 +51,42 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
memcpy(data, msg, sizeof(struct w1_netlink_msg));
- NETLINK_CB(skb).dst_groups = dev->groups;
+ NETLINK_CB(skb).dst_group = dev->groups;
netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC);
nlmsg_failure:
return;
}
+
+int dev_init_netlink(struct w1_master *dev)
+{
+ dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE);
+ if (!dev->nls) {
+ printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
+ NETLINK_W1, dev->dev.bus_id);
+ }
+
+ return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+ if (dev->nls && dev->nls->sk_socket)
+ sock_release(dev->nls->sk_socket);
+}
#else
#warning Netlink support is disabled. Please compile with NET support enabled.
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
{
}
+
+int dev_init_netlink(struct w1_master *dev)
+{
+ return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+}
#endif
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 8615756946df..eb0c8b3152c8 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -52,6 +52,8 @@ struct w1_netlink_msg
#ifdef __KERNEL__
void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
+int dev_init_netlink(struct w1_master *dev);
+void dev_fini_netlink(struct w1_master *dev);
#endif /* __KERNEL__ */
#endif /* __W1_NETLINK_H */
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
index 70d2d469963c..e3209d0aca9b 100644
--- a/drivers/w1/w1_smem.c
+++ b/drivers/w1/w1_smem.c
@@ -36,61 +36,12 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
-static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
-static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
-
-static struct w1_family_ops w1_smem_fops = {
- .rname = &w1_smem_read_name,
- .rbin = &w1_smem_read_bin,
-};
-
-static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- return sprintf(buf, "%s\n", sl->name);
-}
-
-static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
- int i;
-
- atomic_inc(&sl->refcnt);
- if (down_interruptible(&sl->master->mutex)) {
- count = 0;
- goto out_dec;
- }
-
- if (off > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
- if (off + count > W1_SLAVE_DATA_SIZE) {
- count = 0;
- goto out;
- }
- for (i = 0; i < 8; ++i)
- count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
- count += sprintf(buf + count, "\n");
-
-out:
- up(&sl->master->mutex);
-out_dec:
- atomic_dec(&sl->refcnt);
-
- return count;
-}
-
static struct w1_family w1_smem_family_01 = {
.fid = W1_FAMILY_SMEM_01,
- .fops = &w1_smem_fops,
};
static struct w1_family w1_smem_family_81 = {
.fid = W1_FAMILY_SMEM_81,
- .fops = &w1_smem_fops,
};
static int __init w1_smem_init(void)
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 165526c9360a..4577df3cfc48 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -42,12 +42,31 @@ static u8 bad_roms[][9] = {
{}
};
-static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+static struct bin_attribute w1_therm_bin_attr = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = W1_SLAVE_DATA_SIZE,
+ .read = w1_therm_read_bin,
+};
+
+static int w1_therm_add_slave(struct w1_slave *sl)
+{
+ return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
+static void w1_therm_remove_slave(struct w1_slave *sl)
+{
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
static struct w1_family_ops w1_therm_fops = {
- .rname = &w1_therm_read_name,
- .rbin = &w1_therm_read_bin,
+ .add_slave = w1_therm_add_slave,
+ .remove_slave = w1_therm_remove_slave,
};
static struct w1_family w1_therm_family_DS18S20 = {
@@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = {
.fid = W1_THERM_DS18B20,
.fops = &w1_therm_fops,
};
+
static struct w1_family w1_therm_family_DS1822 = {
.fid = W1_THERM_DS1822,
.fops = &w1_therm_fops,
@@ -90,13 +110,6 @@ static struct w1_therm_family_converter w1_therm_families[] = {
},
};
-static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- return sprintf(buf, "%s\n", sl->name);
-}
-
static inline int w1_DS18B20_convert_temp(u8 rom[9])
{
int t = (rom[1] << 8) | rom[0];
@@ -148,8 +161,7 @@ static int w1_therm_check_rom(u8 rom[9])
static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
- struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict;
int i, max_trying = 10;
@@ -178,15 +190,10 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
crc = 0;
while (max_trying--) {
- if (!w1_reset_bus (dev)) {
+ if (!w1_reset_select_slave(sl)) {
int count = 0;
- u8 match[9] = {W1_MATCH_ROM, };
unsigned int tm = 750;
- memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-
- w1_write_block(dev, match, 9);
-
w1_write_8(dev, W1_CONVERT_TEMP);
while (tm) {
@@ -195,8 +202,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
flush_signals(current);
}
- if (!w1_reset_bus (dev)) {
- w1_write_block(dev, match, 9);
+ if (!w1_reset_select_slave(sl)) {
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
@@ -207,7 +213,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (rom[8] == crc && rom[0])
verdict = 1;
-
}
}
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 04ca8840acf1..87c29d7b6c17 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/zorro.h>
#include <linux/stat.h>
+#include <linux/string.h>
#include "zorro.h"
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index d3c05dfe20d2..0f2b40605b06 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -16,6 +16,8 @@
#include <linux/init.h>
#include <linux/zorro.h>
#include <linux/bitops.h>
+#include <linux/string.h>
+
#include <asm/setup.h>
#include <asm/amigahw.h>